cprover
Toggle main menu visibility
Loading...
Searching...
No Matches
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
68
elf_class
=(
elf_classt
)
elf32_header
.e_ident[4];
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
81
u16_to_native_endian_inplace
(
little_endian
,
elf32_header
.e_type);
82
u16_to_native_endian_inplace
(
little_endian
,
elf32_header
.e_machine);
83
u32_to_native_endian_inplace
(
little_endian
,
elf32_header
.e_version);
84
u32_to_native_endian_inplace
(
little_endian
,
elf32_header
.e_entry);
85
u32_to_native_endian_inplace
(
little_endian
,
elf32_header
.e_phoff);
86
u32_to_native_endian_inplace
(
little_endian
,
elf32_header
.e_shoff);
87
u32_to_native_endian_inplace
(
little_endian
,
elf32_header
.e_flags);
88
u16_to_native_endian_inplace
(
little_endian
,
elf32_header
.e_ehsize);
89
u16_to_native_endian_inplace
(
little_endian
,
elf32_header
.e_phentsize);
90
u16_to_native_endian_inplace
(
little_endian
,
elf32_header
.e_phnum);
91
u16_to_native_endian_inplace
(
little_endian
,
elf32_header
.e_shentsize);
92
u16_to_native_endian_inplace
(
little_endian
,
elf32_header
.e_shnum);
93
u16_to_native_endian_inplace
(
little_endian
,
elf32_header
.e_shstrndx);
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 ||
100
elf32_header
.e_shnum==0)
101
throw
deserialization_exceptiont
(
"ELF32 without section header"
);
102
103
elf32_section_header_table
.resize(
elf32_header
.e_shnum);
104
number_of_sections
=
elf32_header
.e_shnum;
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
110
in
.seekg(
elf32_header
.e_shoff+i*
elf32_header
.e_shentsize);
111
112
// read section header
113
in
.read(
114
reinterpret_cast<
char
*
>
(&
elf32_section_header_table
[i]),
115
sizeof
(
Elf32_Shdr
));
116
u32_to_native_endian_inplace
(
117
little_endian
,
elf32_section_header_table
[i].sh_name);
118
u32_to_native_endian_inplace
(
119
little_endian
,
elf32_section_header_table
[i].sh_type);
120
u32_to_native_endian_inplace
(
121
little_endian
,
elf32_section_header_table
[i].sh_flags);
122
u32_to_native_endian_inplace
(
123
little_endian
,
elf32_section_header_table
[i].sh_addr);
124
u32_to_native_endian_inplace
(
125
little_endian
,
elf32_section_header_table
[i].sh_offset);
126
u32_to_native_endian_inplace
(
127
little_endian
,
elf32_section_header_table
[i].sh_size);
128
u32_to_native_endian_inplace
(
129
little_endian
,
elf32_section_header_table
[i].sh_link);
130
u32_to_native_endian_inplace
(
131
little_endian
,
elf32_section_header_table
[i].sh_info);
132
u32_to_native_endian_inplace
(
133
little_endian
,
elf32_section_header_table
[i].sh_addralign);
134
u32_to_native_endian_inplace
(
135
little_endian
,
elf32_section_header_table
[i].sh_entsize);
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)"
);
161
u16_to_native_endian_inplace
(
little_endian
,
elf64_header
.e_type);
162
u16_to_native_endian_inplace
(
little_endian
,
elf64_header
.e_machine);
163
u32_to_native_endian_inplace
(
little_endian
,
elf64_header
.e_version);
164
u64_to_native_endian_inplace
(
little_endian
,
elf64_header
.e_entry);
165
u64_to_native_endian_inplace
(
little_endian
,
elf64_header
.e_phoff);
166
u64_to_native_endian_inplace
(
little_endian
,
elf64_header
.e_shoff);
167
u32_to_native_endian_inplace
(
little_endian
,
elf64_header
.e_flags);
168
u16_to_native_endian_inplace
(
little_endian
,
elf64_header
.e_ehsize);
169
u16_to_native_endian_inplace
(
little_endian
,
elf64_header
.e_phentsize);
170
u16_to_native_endian_inplace
(
little_endian
,
elf64_header
.e_phnum);
171
u16_to_native_endian_inplace
(
little_endian
,
elf64_header
.e_shentsize);
172
u16_to_native_endian_inplace
(
little_endian
,
elf64_header
.e_shnum);
173
u16_to_native_endian_inplace
(
little_endian
,
elf64_header
.e_shstrndx);
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 ||
180
elf64_header
.e_shnum==0)
181
throw
deserialization_exceptiont
(
"ELF64 without section header"
);
182
183
elf64_section_header_table
.resize(
elf64_header
.e_shnum);
184
number_of_sections
=
elf64_header
.e_shnum;
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
190
in
.seekg(
elf64_header
.e_shoff+i*
elf64_header
.e_shentsize);
191
192
// read section header
193
in
.read(
194
reinterpret_cast<
char
*
>
(&
elf64_section_header_table
[i]),
195
sizeof
(
Elf64_Shdr
));
196
u32_to_native_endian_inplace
(
197
little_endian
,
elf64_section_header_table
[i].sh_name);
198
u32_to_native_endian_inplace
(
199
little_endian
,
elf64_section_header_table
[i].sh_type);
200
u64_to_native_endian_inplace
(
201
little_endian
,
elf64_section_header_table
[i].sh_flags);
202
u64_to_native_endian_inplace
(
203
little_endian
,
elf64_section_header_table
[i].sh_addr);
204
u64_to_native_endian_inplace
(
205
little_endian
,
elf64_section_header_table
[i].sh_offset);
206
u64_to_native_endian_inplace
(
207
little_endian
,
elf64_section_header_table
[i].sh_size);
208
u32_to_native_endian_inplace
(
209
little_endian
,
elf64_section_header_table
[i].sh_link);
210
u32_to_native_endian_inplace
(
211
little_endian
,
elf64_section_header_table
[i].sh_info);
212
u64_to_native_endian_inplace
(
213
little_endian
,
elf64_section_header_table
[i].sh_addralign);
214
u64_to_native_endian_inplace
(
215
little_endian
,
elf64_section_header_table
[i].sh_entsize);
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
}
deserialization_exceptiont
Thrown when failing to deserialize a value from some low level format, like JSON or raw bytes.
Definition
exception_utils.h:80
elf_readert::number_of_sections
std::size_t number_of_sections
Definition
elf_reader.h:135
elf_readert::elf64_header
Elf64_Ehdr elf64_header
Definition
elf_reader.h:110
elf_readert::elf_classt
elf_classt
Definition
elf_reader.h:105
elf_readert::ELF32
@ ELF32
Definition
elf_reader.h:105
elf_readert::ELF64
@ ELF64
Definition
elf_reader.h:105
elf_readert::elf32_header
Elf32_Ehdr elf32_header
Definition
elf_reader.h:109
elf_readert::elf_readert
elf_readert(std::istream &_in)
Definition
elf_reader.cpp:52
elf_readert::get_string
std::string get_string(std::streampos index) const
Definition
elf_reader.cpp:227
elf_readert::elf64_section_header_table
elf64_section_header_tablet elf64_section_header_table
Definition
elf_reader.h:119
elf_readert::in
std::istream & in
Definition
elf_reader.h:154
elf_readert::has_section
bool has_section(const std::string &name) const
Definition
elf_reader.cpp:245
elf_readert::elf32_section_header_table
elf32_section_header_tablet elf32_section_header_table
Definition
elf_reader.h:116
elf_readert::section_name
std::string section_name(std::size_t index) const
Definition
elf_reader.h:137
elf_readert::string_table_offset
std::streampos string_table_offset
Definition
elf_reader.h:122
elf_readert::little_endian
bool little_endian
Definition
elf_reader.h:112
elf_readert::elf_class
elf_classt elf_class
Definition
elf_reader.h:106
elf_readert::section_offset
std::streampos section_offset(std::size_t index) const
Definition
elf_reader.h:144
u32_to_native_endian_inplace
static void u32_to_native_endian_inplace(bool le_input, uint32_t &input)
Definition
elf_reader.cpp:26
u16_to_native_endian_inplace
static void u16_to_native_endian_inplace(bool le_input, uint16_t &input)
Definition
elf_reader.cpp:19
u64_to_native_endian_inplace
static void u64_to_native_endian_inplace(bool le_input, unsigned long long &input)
Definition
elf_reader.cpp:36
elf_reader.h
Read ELF.
exception_utils.h
Elf32_Shdr
Definition
elf_reader.h:73
Elf64_Shdr
Definition
elf_reader.h:87
goto-programs
elf_reader.cpp
Generated by
1.17.0