CBMC
elf_reader.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Read ELF
4 
5 Author:
6 
7 \*******************************************************************/
8 
11 
12 #include "elf_reader.h"
13 
14 #include <util/exception_utils.h>
15 
16 #include <cstdint>
17 #include <istream>
18 
19 static void u16_to_native_endian_inplace(bool le_input, uint16_t &input)
20 {
21  const uint8_t *input_as_bytes = reinterpret_cast<uint8_t *>(&input);
22  input = (((uint16_t)input_as_bytes[0]) << (le_input ? 0 : 8)) |
23  (((uint16_t)input_as_bytes[1]) << (le_input ? 8 : 0));
24 }
25 
26 static void u32_to_native_endian_inplace(bool le_input, uint32_t &input)
27 {
28  const uint8_t *input_as_bytes = reinterpret_cast<uint8_t *>(&input);
29  input = (((uint32_t)input_as_bytes[0]) << (le_input ? 0 : 24)) |
30  (((uint32_t)input_as_bytes[1]) << (le_input ? 8 : 16)) |
31  (((uint32_t)input_as_bytes[2]) << (le_input ? 16 : 8)) |
32  (((uint32_t)input_as_bytes[3]) << (le_input ? 24 : 0));
33 }
34 
35 static void
36 u64_to_native_endian_inplace(bool le_input, unsigned long long &input)
37 {
38  static_assert(
39  sizeof(unsigned long long) == 8,
40  "unsigned long long expected to be 8 bytes");
41  const uint8_t *input_as_bytes = reinterpret_cast<uint8_t *>(&input);
42  input = (((unsigned long long)input_as_bytes[0]) << (le_input ? 0 : 56)) |
43  (((unsigned long long)input_as_bytes[1]) << (le_input ? 8 : 48)) |
44  (((unsigned long long)input_as_bytes[2]) << (le_input ? 16 : 40)) |
45  (((unsigned long long)input_as_bytes[3]) << (le_input ? 24 : 32)) |
46  (((unsigned long long)input_as_bytes[4]) << (le_input ? 32 : 24)) |
47  (((unsigned long long)input_as_bytes[5]) << (le_input ? 40 : 16)) |
48  (((unsigned long long)input_as_bytes[6]) << (le_input ? 48 : 8)) |
49  (((unsigned long long)input_as_bytes[7]) << (le_input ? 56 : 0));
50 }
51 
52 elf_readert::elf_readert(std::istream &_in):in(_in)
53 {
54  // read 32-bit header
55  in.read(
56  reinterpret_cast<char*>(&elf32_header),
57  sizeof(elf32_header));
58 
59  if(!in)
60  throw deserialization_exceptiont("failed to read ELF header");
61 
62  if(elf32_header.e_ident[0]!=0x7f ||
63  elf32_header.e_ident[1]!='E' ||
64  elf32_header.e_ident[2]!='L' ||
65  elf32_header.e_ident[3]!='F')
66  throw deserialization_exceptiont("ELF header malformed (magic)");
67 
69 
70  if(elf_class==ELF32)
71  {
72  const auto ei_data = elf32_header.e_ident[5];
73 
74  if(ei_data==1)
75  little_endian=true;
76  else if(ei_data==2)
77  little_endian=false;
78  else
79  throw deserialization_exceptiont("ELF32 header malformed (EI_DATA)");
80 
94 
95  if(elf32_header.e_version!=1)
96  throw deserialization_exceptiont("unknown ELF32 version");
97 
98  // get offset for section header
99  if(elf32_header.e_shoff==0 ||
101  throw deserialization_exceptiont("ELF32 without section header");
102 
105 
106  // iterate over these
107  for(std::size_t i=0; i<elf32_section_header_table.size(); i++)
108  {
109  // go to right place
111 
112  // read section header
113  in.read(
114  reinterpret_cast<char*>(&elf32_section_header_table[i]),
115  sizeof(Elf32_Shdr));
133  little_endian, elf32_section_header_table[i].sh_addralign);
136  }
137 
138  // string table
139  unsigned string_table_nr=elf32_header.e_shstrndx;
140  if(string_table_nr>=elf32_section_header_table.size())
141  throw deserialization_exceptiont("ELF32 without string table");
142 
143  string_table_offset=section_offset(string_table_nr);
144  }
145  else if(elf_class==ELF64)
146  {
147  // read 64-bit header
148  in.seekg(0);
149  in.read(
150  reinterpret_cast<char*>(&elf64_header),
151  sizeof(elf64_header));
152 
153  const auto ei_data = elf64_header.e_ident[5];
154 
155  if(ei_data==1)
156  little_endian=true;
157  else if(ei_data==2)
158  little_endian=false;
159  else
160  throw deserialization_exceptiont("ELF64 header malformed (EI_DATA)");
174 
175  if(elf64_header.e_version!=1)
176  throw deserialization_exceptiont("unknown ELF64 version");
177 
178  // get offset for section header
179  if(elf64_header.e_shoff==0 ||
181  throw deserialization_exceptiont("ELF64 without section header");
182 
185 
186  // iterate over these
187  for(std::size_t i=0; i<elf64_section_header_table.size(); i++)
188  {
189  // go to right place
191 
192  // read section header
193  in.read(
194  reinterpret_cast<char*>(&elf64_section_header_table[i]),
195  sizeof(Elf64_Shdr));
213  little_endian, elf64_section_header_table[i].sh_addralign);
216  }
217 
218  // string table
219  unsigned string_table_nr=elf64_header.e_shstrndx;
220  if(string_table_nr>=elf64_section_header_table.size())
221  throw deserialization_exceptiont("ELF64 without string table");
222 
223  string_table_offset=section_offset(string_table_nr);
224  }
225 }
226 
227 std::string elf_readert::get_string(std::streampos index) const
228 {
229  in.seekg(string_table_offset+index);
230 
231  std::string result;
232 
233  while(in)
234  {
235  char ch;
236  in.read(&ch, 1);
237  if(ch==0)
238  break;
239  result+=ch;
240  }
241 
242  return result;
243 }
244 
245 bool elf_readert::has_section(const std::string &name) const
246 {
247  for(std::size_t i=0; i<number_of_sections; i++)
248  if(section_name(i)==name)
249  return true;
250 
251  return false;
252 }
Thrown when failing to deserialize a value from some low level format, like JSON or raw bytes.
std::size_t number_of_sections
Definition: elf_reader.h:135
Elf64_Ehdr elf64_header
Definition: elf_reader.h:110
Elf32_Ehdr elf32_header
Definition: elf_reader.h:109
elf_readert(std::istream &_in)
Definition: elf_reader.cpp:52
std::string get_string(std::streampos index) const
Definition: elf_reader.cpp:227
elf64_section_header_tablet elf64_section_header_table
Definition: elf_reader.h:119
std::istream & in
Definition: elf_reader.h:154
bool has_section(const std::string &name) const
Definition: elf_reader.cpp:245
elf32_section_header_tablet elf32_section_header_table
Definition: elf_reader.h:116
std::string section_name(std::size_t index) const
Definition: elf_reader.h:137
std::streampos string_table_offset
Definition: elf_reader.h:122
bool little_endian
Definition: elf_reader.h:112
elf_classt elf_class
Definition: elf_reader.h:106
std::streampos section_offset(std::size_t index) const
Definition: elf_reader.h:144
static void u32_to_native_endian_inplace(bool le_input, uint32_t &input)
Definition: elf_reader.cpp:26
static void u16_to_native_endian_inplace(bool le_input, uint16_t &input)
Definition: elf_reader.cpp:19
static void u64_to_native_endian_inplace(bool le_input, unsigned long long &input)
Definition: elf_reader.cpp:36
Read ELF.
Elf32_Off e_shoff
Definition: elf_reader.h:44
Elf32_Half e_ehsize
Definition: elf_reader.h:46
Elf32_Half e_shnum
Definition: elf_reader.h:50
Elf32_Half e_machine
Definition: elf_reader.h:40
Elf32_Off e_phoff
Definition: elf_reader.h:43
Elf32_Half e_phnum
Definition: elf_reader.h:48
Elf32_Half e_shstrndx
Definition: elf_reader.h:51
Elf32_Half e_type
Definition: elf_reader.h:39
unsigned char e_ident[16]
Definition: elf_reader.h:38
Elf32_Word e_flags
Definition: elf_reader.h:45
Elf32_Word e_version
Definition: elf_reader.h:41
Elf32_Half e_shentsize
Definition: elf_reader.h:49
Elf32_Addr e_entry
Definition: elf_reader.h:42
Elf32_Half e_phentsize
Definition: elf_reader.h:47
Elf64_Half e_type
Definition: elf_reader.h:57
Elf64_Half e_shentsize
Definition: elf_reader.h:67
unsigned char e_ident[16]
Definition: elf_reader.h:56
Elf64_Half e_shnum
Definition: elf_reader.h:68
Elf64_Word e_version
Definition: elf_reader.h:59
Elf64_Half e_ehsize
Definition: elf_reader.h:64
Elf64_Off e_shoff
Definition: elf_reader.h:62
Elf64_Addr e_entry
Definition: elf_reader.h:60
Elf64_Half e_phentsize
Definition: elf_reader.h:65
Elf64_Off e_phoff
Definition: elf_reader.h:61
Elf64_Half e_machine
Definition: elf_reader.h:58
Elf64_Word e_flags
Definition: elf_reader.h:63
Elf64_Half e_shstrndx
Definition: elf_reader.h:69
Elf64_Half e_phnum
Definition: elf_reader.h:66