blob: bfff9f3336e8639e0280585f4350c63c778ec41f [file] [log] [blame]
Stephen Wilsonddd29622010-07-13 23:07:23 +00001//===-- ELFHeader.cpp ----------------------------------------- -*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include <cstring>
11
12#include "lldb/Core/DataExtractor.h"
13
14#include "ELFHeader.h"
15
16using namespace elf;
17using namespace lldb;
18using namespace llvm::ELF;
19
20//------------------------------------------------------------------------------
21// Static utility functions.
22//
23// GetMaxU64 and GetMaxS64 wrap the similarly named methods from DataExtractor
24// with error handling code and provide for parsing a sequence of values.
25static bool
26GetMaxU64(const lldb_private::DataExtractor &data,
27 uint32_t *offset, uint64_t *value, uint32_t byte_size)
28{
29 const uint32_t saved_offset = *offset;
30 *value = data.GetMaxU64(offset, byte_size);
31 return *offset != saved_offset;
32}
33
34static bool
35GetMaxU64(const lldb_private::DataExtractor &data,
36 uint32_t *offset, uint64_t *value, uint32_t byte_size,
37 uint32_t count)
38{
39 uint32_t saved_offset = *offset;
40
41 for (uint32_t i = 0; i < count; ++i, ++value)
42 {
43 if (GetMaxU64(data, offset, value, byte_size) == false)
44 {
45 *offset = saved_offset;
46 return false;
47 }
48 }
49 return true;
50}
51
52static bool
53GetMaxS64(const lldb_private::DataExtractor &data,
54 uint32_t *offset, int64_t *value, uint32_t byte_size)
55{
56 const uint32_t saved_offset = *offset;
57 *value = data.GetMaxS64(offset, byte_size);
58 return *offset != saved_offset;
59}
60
61static bool
62GetMaxS64(const lldb_private::DataExtractor &data,
63 uint32_t *offset, int64_t *value, uint32_t byte_size,
64 uint32_t count)
65{
66 uint32_t saved_offset = *offset;
67
68 for (uint32_t i = 0; i < count; ++i, ++value)
69 {
70 if (GetMaxS64(data, offset, value, byte_size) == false)
71 {
72 *offset = saved_offset;
73 return false;
74 }
75 }
76 return true;
77}
78
79//------------------------------------------------------------------------------
80// ELFHeader
81
82ELFHeader::ELFHeader()
83{
84 memset(this, 0, sizeof(ELFHeader));
85}
86
87ByteOrder
88ELFHeader::GetByteOrder() const
89{
90 if (e_ident[EI_DATA] == ELFDATA2MSB)
91 return eByteOrderBig;
92 if (e_ident[EI_DATA] == ELFDATA2LSB)
93 return eByteOrderLittle;
94 return eByteOrderInvalid;
95}
96
97bool
98ELFHeader::Parse(lldb_private::DataExtractor &data, uint32_t *offset)
99{
100 // Read e_ident. This provides byte order and address size info.
101 if (data.GetU8(offset, &e_ident, EI_NIDENT) == NULL)
102 return false;
103
104 const unsigned byte_size = Is32Bit() ? 4 : 8;
105 data.SetByteOrder(GetByteOrder());
106 data.SetAddressByteSize(byte_size);
107
108 // Read e_type and e_machine.
109 if (data.GetU16(offset, &e_type, 2) == NULL)
110 return false;
111
112 // Read e_version.
113 if (data.GetU32(offset, &e_version, 1) == NULL)
114 return false;
115
116 // Read e_entry, e_phoff and e_shoff.
117 if (GetMaxU64(data, offset, &e_entry, byte_size, 3) == false)
118 return false;
119
120 // Read e_flags.
121 if (data.GetU32(offset, &e_flags, 1) == NULL)
122 return false;
123
124 // Read e_ehsize, e_phentsize, e_phnum, e_shentsize, e_shnum and
125 // e_shstrndx.
126 if (data.GetU16(offset, &e_ehsize, 6) == NULL)
127 return false;
128
129 return true;
130}
131
132bool
133ELFHeader::MagicBytesMatch(const uint8_t *magic)
134{
135 return memcmp(magic, ElfMagic, strlen(ElfMagic)) == 0;
136}
137
138unsigned
139ELFHeader::AddressSizeInBytes(const uint8_t *magic)
140{
141 unsigned address_size = 0;
142
143 switch (magic[EI_CLASS])
144 {
145 case ELFCLASS32:
146 address_size = 4;
147 break;
148
149 case ELFCLASS64:
150 address_size = 8;
151 break;
152 }
153 return address_size;
154}
155
Stephen Wilson9b01e482011-03-30 15:59:12 +0000156unsigned
157ELFHeader::GetRelocationJumpSlotType() const
158{
159 unsigned slot = 0;
160
161 switch (e_machine)
162 {
163 default:
164 assert(false && "architecture not supported");
165 break;
166 case EM_386:
167 case EM_486:
168 slot = R_386_JUMP_SLOT;
169 break;
170 case EM_X86_64:
171 slot = R_X86_64_JUMP_SLOT;
172 break;
173 case EM_ARM:
174 slot = R_ARM_JUMP_SLOT;
175 break;
176 case EM_MBLAZE:
177 slot = R_MICROBLAZE_JUMP_SLOT;
178 }
179
180 return slot;
181}
182
Stephen Wilsonddd29622010-07-13 23:07:23 +0000183//------------------------------------------------------------------------------
184// ELFSectionHeader
185
186ELFSectionHeader::ELFSectionHeader()
187{
188 memset(this, 0, sizeof(ELFSectionHeader));
189}
190
191bool
192ELFSectionHeader::Parse(const lldb_private::DataExtractor &data,
193 uint32_t *offset)
194{
195 const unsigned byte_size = data.GetAddressByteSize();
196
197 // Read sh_name and sh_type.
198 if (data.GetU32(offset, &sh_name, 2) == NULL)
199 return false;
200
201 // Read sh_flags.
202 if (GetMaxU64(data, offset, &sh_flags, byte_size) == false)
203 return false;
204
205 // Read sh_addr, sh_off and sh_size.
206 if (GetMaxU64(data, offset, &sh_addr, byte_size, 3) == false)
207 return false;
208
209 // Read sh_link and sh_info.
210 if (data.GetU32(offset, &sh_link, 2) == NULL)
211 return false;
212
213 // Read sh_addralign and sh_entsize.
214 if (GetMaxU64(data, offset, &sh_addralign, byte_size, 2) == false)
215 return false;
216
217 return true;
218}
219
220//------------------------------------------------------------------------------
221// ELFSymbol
222
223ELFSymbol::ELFSymbol()
224{
225 memset(this, 0, sizeof(ELFSymbol));
226}
227
228bool
229ELFSymbol::Parse(const lldb_private::DataExtractor &data, uint32_t *offset)
230{
231 const unsigned byte_size = data.GetAddressByteSize();
232 const bool parsing_32 = byte_size == 4;
233
234 // Read st_name.
235 if (data.GetU32(offset, &st_name, 1) == NULL)
236 return false;
237
238 if (parsing_32)
239 {
240 // Read st_value and st_size.
241 if (GetMaxU64(data, offset, &st_value, byte_size, 2) == false)
242 return false;
243
244 // Read st_info and st_other.
245 if (data.GetU8(offset, &st_info, 2) == NULL)
246 return false;
247
248 // Read st_shndx.
249 if (data.GetU16(offset, &st_shndx, 1) == NULL)
250 return false;
251 }
252 else
253 {
254 // Read st_info and st_other.
255 if (data.GetU8(offset, &st_info, 2) == NULL)
256 return false;
257
258 // Read st_shndx.
259 if (data.GetU16(offset, &st_shndx, 1) == NULL)
260 return false;
261
262 // Read st_value and st_size.
263 if (data.GetU64(offset, &st_value, 2) == NULL)
264 return false;
265 }
266 return true;
267}
268
269//------------------------------------------------------------------------------
270// ELFProgramHeader
271
272ELFProgramHeader::ELFProgramHeader()
273{
274 memset(this, 0, sizeof(ELFProgramHeader));
275}
276
277bool
278ELFProgramHeader::Parse(const lldb_private::DataExtractor &data,
279 uint32_t *offset)
280{
281 const uint32_t byte_size = data.GetAddressByteSize();
282 const bool parsing_32 = byte_size == 4;
283
284 // Read p_type;
285 if (data.GetU32(offset, &p_type, 1) == NULL)
286 return false;
287
288 if (parsing_32) {
289 // Read p_offset, p_vaddr, p_paddr, p_filesz and p_memsz.
290 if (GetMaxU64(data, offset, &p_offset, byte_size, 5) == false)
291 return false;
292
293 // Read p_flags.
294 if (data.GetU32(offset, &p_flags, 1) == NULL)
295 return false;
296
297 // Read p_align.
298 if (GetMaxU64(data, offset, &p_align, byte_size) == false)
299 return false;
300 }
301 else {
302 // Read p_flags.
303 if (data.GetU32(offset, &p_flags, 1) == NULL)
304 return false;
305
306 // Read p_offset, p_vaddr, p_paddr, p_filesz, p_memsz and p_align.
307 if (GetMaxU64(data, offset, &p_offset, byte_size, 6) == false)
308 return false;
309 }
310
311 return true;
312}
313
314//------------------------------------------------------------------------------
315// ELFDynamic
316
317ELFDynamic::ELFDynamic()
318{
319 memset(this, 0, sizeof(ELFDynamic));
320}
321
322bool
Stephen Wilson9b01e482011-03-30 15:59:12 +0000323ELFDynamic::Parse(const lldb_private::DataExtractor &data, uint32_t *offset)
Stephen Wilsonddd29622010-07-13 23:07:23 +0000324{
325 const unsigned byte_size = data.GetAddressByteSize();
326 return GetMaxS64(data, offset, &d_tag, byte_size, 2);
327}
328
Stephen Wilson9b01e482011-03-30 15:59:12 +0000329//------------------------------------------------------------------------------
330// ELFRel
331
332ELFRel::ELFRel()
333{
334 memset(this, 0, sizeof(ELFRel));
335}
336
337bool
338ELFRel::Parse(const lldb_private::DataExtractor &data, uint32_t *offset)
339{
340 const unsigned byte_size = data.GetAddressByteSize();
341
342 // Read r_offset and r_info.
343 if (GetMaxU64(data, offset, &r_offset, byte_size, 2) == false)
344 return false;
345
346 return true;
347}
348
349//------------------------------------------------------------------------------
350// ELFRela
351
352ELFRela::ELFRela()
353{
354 memset(this, 0, sizeof(ELFRela));
355}
356
357bool
358ELFRela::Parse(const lldb_private::DataExtractor &data, uint32_t *offset)
359{
360 const unsigned byte_size = data.GetAddressByteSize();
361
362 // Read r_offset and r_info.
363 if (GetMaxU64(data, offset, &r_offset, byte_size, 2) == false)
364 return false;
365
366 // Read r_addend;
367 if (GetMaxS64(data, offset, &r_addend, byte_size) == false)
368 return false;
369
370 return true;
371}
372
Stephen Wilsonddd29622010-07-13 23:07:23 +0000373