LLDB  mainline
ELFHeader.cpp
Go to the documentation of this file.
1 //===-- ELFHeader.cpp -----------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include <cstring>
10 
11 #include "lldb/Core/Section.h"
13 #include "lldb/Utility/Stream.h"
14 
15 #include "ELFHeader.h"
16 
17 using namespace elf;
18 using namespace lldb;
19 using namespace llvm::ELF;
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.
25 static bool GetMaxU64(const lldb_private::DataExtractor &data,
26  lldb::offset_t *offset, uint64_t *value,
27  uint32_t byte_size) {
28  const lldb::offset_t saved_offset = *offset;
29  *value = data.GetMaxU64(offset, byte_size);
30  return *offset != saved_offset;
31 }
32 
33 static bool GetMaxU64(const lldb_private::DataExtractor &data,
34  lldb::offset_t *offset, uint64_t *value,
35  uint32_t byte_size, uint32_t count) {
36  lldb::offset_t saved_offset = *offset;
37 
38  for (uint32_t i = 0; i < count; ++i, ++value) {
39  if (!GetMaxU64(data, offset, value, byte_size)) {
40  *offset = saved_offset;
41  return false;
42  }
43  }
44  return true;
45 }
46 
47 static bool GetMaxS64(const lldb_private::DataExtractor &data,
48  lldb::offset_t *offset, int64_t *value,
49  uint32_t byte_size) {
50  const lldb::offset_t saved_offset = *offset;
51  *value = data.GetMaxS64(offset, byte_size);
52  return *offset != saved_offset;
53 }
54 
55 static bool GetMaxS64(const lldb_private::DataExtractor &data,
56  lldb::offset_t *offset, int64_t *value,
57  uint32_t byte_size, uint32_t count) {
58  lldb::offset_t saved_offset = *offset;
59 
60  for (uint32_t i = 0; i < count; ++i, ++value) {
61  if (!GetMaxS64(data, offset, value, byte_size)) {
62  *offset = saved_offset;
63  return false;
64  }
65  }
66  return true;
67 }
68 
69 // ELFHeader
70 
71 ELFHeader::ELFHeader() { memset(this, 0, sizeof(ELFHeader)); }
72 
74  if (e_ident[EI_DATA] == ELFDATA2MSB)
75  return eByteOrderBig;
76  if (e_ident[EI_DATA] == ELFDATA2LSB)
77  return eByteOrderLittle;
78  return eByteOrderInvalid;
79 }
80 
82  bool result = false;
83 
84  // Check if any of these values looks like sentinel.
85  result |= e_phnum_hdr == 0xFFFF; // PN_XNUM
86  result |= e_shnum_hdr == SHN_UNDEF;
87  result |= e_shstrndx_hdr == SHN_XINDEX;
88 
89  // If header extension is present, the section offset cannot be null.
90  result &= e_shoff != 0;
91 
92  // Done.
93  return result;
94 }
95 
97  // Extract section #0 header.
98  ELFSectionHeader section_zero;
99  lldb::offset_t offset = 0;
100  lldb_private::DataExtractor sh_data(data, e_shoff, e_shentsize);
101  bool ok = section_zero.Parse(sh_data, &offset);
102 
103  // If we succeeded, fix the header.
104  if (ok) {
105  if (e_phnum_hdr == 0xFFFF) // PN_XNUM
106  e_phnum = section_zero.sh_info;
107  if (e_shnum_hdr == SHN_UNDEF)
108  e_shnum = section_zero.sh_size;
109  if (e_shstrndx_hdr == SHN_XINDEX)
110  e_shstrndx = section_zero.sh_link;
111  }
112 }
113 
115  lldb::offset_t *offset) {
116  // Read e_ident. This provides byte order and address size info.
117  if (data.GetU8(offset, &e_ident, EI_NIDENT) == nullptr)
118  return false;
119 
120  const unsigned byte_size = Is32Bit() ? 4 : 8;
121  data.SetByteOrder(GetByteOrder());
122  data.SetAddressByteSize(byte_size);
123 
124  // Read e_type and e_machine.
125  if (data.GetU16(offset, &e_type, 2) == nullptr)
126  return false;
127 
128  // Read e_version.
129  if (data.GetU32(offset, &e_version, 1) == nullptr)
130  return false;
131 
132  // Read e_entry, e_phoff and e_shoff.
133  if (!GetMaxU64(data, offset, &e_entry, byte_size, 3))
134  return false;
135 
136  // Read e_flags.
137  if (data.GetU32(offset, &e_flags, 1) == nullptr)
138  return false;
139 
140  // Read e_ehsize, e_phentsize, e_phnum, e_shentsize, e_shnum and e_shstrndx.
141  if (data.GetU16(offset, &e_ehsize, 6) == nullptr)
142  return false;
143 
144  // Initialize e_phnum, e_shnum, and e_shstrndx with the values read from the
145  // header.
146  e_phnum = e_phnum_hdr;
147  e_shnum = e_shnum_hdr;
148  e_shstrndx = e_shstrndx_hdr;
149 
150  // See if we have extended header in section #0.
151  if (HasHeaderExtension())
152  ParseHeaderExtension(data);
153 
154  return true;
155 }
156 
157 bool ELFHeader::MagicBytesMatch(const uint8_t *magic) {
158  return memcmp(magic, ElfMagic, strlen(ElfMagic)) == 0;
159 }
160 
161 unsigned ELFHeader::AddressSizeInBytes(const uint8_t *magic) {
162  unsigned address_size = 0;
163 
164  switch (magic[EI_CLASS]) {
165  case ELFCLASS32:
166  address_size = 4;
167  break;
168 
169  case ELFCLASS64:
170  address_size = 8;
171  break;
172  }
173  return address_size;
174 }
175 
177  unsigned slot = 0;
178 
179  switch (e_machine) {
180  default:
181  assert(false && "architecture not supported");
182  break;
183  case EM_PPC:
184  slot = R_PPC_JMP_SLOT;
185  break;
186  case EM_PPC64:
187  slot = R_PPC64_JMP_SLOT;
188  break;
189  case EM_386:
190  case EM_IAMCU: // FIXME: is this correct?
191  slot = R_386_JUMP_SLOT;
192  break;
193  case EM_X86_64:
194  slot = R_X86_64_JUMP_SLOT;
195  break;
196  case EM_ARM:
197  slot = R_ARM_JUMP_SLOT;
198  break;
199  case EM_HEXAGON:
200  slot = R_HEX_JMP_SLOT;
201  break;
202  case EM_AARCH64:
203  slot = R_AARCH64_JUMP_SLOT;
204  break;
205  case EM_MIPS:
206  slot = R_MIPS_JUMP_SLOT;
207  break;
208  case EM_S390:
209  slot = R_390_JMP_SLOT;
210  break;
211  }
212 
213  return slot;
214 }
215 
216 // ELFSectionHeader
217 
219  memset(this, 0, sizeof(ELFSectionHeader));
220 }
221 
223  lldb::offset_t *offset) {
224  const unsigned byte_size = data.GetAddressByteSize();
225 
226  // Read sh_name and sh_type.
227  if (data.GetU32(offset, &sh_name, 2) == nullptr)
228  return false;
229 
230  // Read sh_flags.
231  if (!GetMaxU64(data, offset, &sh_flags, byte_size))
232  return false;
233 
234  // Read sh_addr, sh_off and sh_size.
235  if (!GetMaxU64(data, offset, &sh_addr, byte_size, 3))
236  return false;
237 
238  // Read sh_link and sh_info.
239  if (data.GetU32(offset, &sh_link, 2) == nullptr)
240  return false;
241 
242  // Read sh_addralign and sh_entsize.
243  if (!GetMaxU64(data, offset, &sh_addralign, byte_size, 2))
244  return false;
245 
246  return true;
247 }
248 
249 // ELFSymbol
250 
251 ELFSymbol::ELFSymbol() { memset(this, 0, sizeof(ELFSymbol)); }
252 
253 #define ENUM_TO_CSTR(e) \
254  case e: \
255  return #e
256 
257 const char *ELFSymbol::bindingToCString(unsigned char binding) {
258  switch (binding) {
259  ENUM_TO_CSTR(STB_LOCAL);
260  ENUM_TO_CSTR(STB_GLOBAL);
261  ENUM_TO_CSTR(STB_WEAK);
262  ENUM_TO_CSTR(STB_LOOS);
263  ENUM_TO_CSTR(STB_HIOS);
264  ENUM_TO_CSTR(STB_LOPROC);
265  ENUM_TO_CSTR(STB_HIPROC);
266  }
267  return "";
268 }
269 
270 const char *ELFSymbol::typeToCString(unsigned char type) {
271  switch (type) {
272  ENUM_TO_CSTR(STT_NOTYPE);
273  ENUM_TO_CSTR(STT_OBJECT);
274  ENUM_TO_CSTR(STT_FUNC);
275  ENUM_TO_CSTR(STT_SECTION);
276  ENUM_TO_CSTR(STT_FILE);
277  ENUM_TO_CSTR(STT_COMMON);
278  ENUM_TO_CSTR(STT_TLS);
279  ENUM_TO_CSTR(STT_GNU_IFUNC);
280  ENUM_TO_CSTR(STT_HIOS);
281  ENUM_TO_CSTR(STT_LOPROC);
282  ENUM_TO_CSTR(STT_HIPROC);
283  }
284  return "";
285 }
286 
288  elf_half shndx, const lldb_private::SectionList *section_list) {
289  switch (shndx) {
290  ENUM_TO_CSTR(SHN_UNDEF);
291  ENUM_TO_CSTR(SHN_LOPROC);
292  ENUM_TO_CSTR(SHN_HIPROC);
293  ENUM_TO_CSTR(SHN_LOOS);
294  ENUM_TO_CSTR(SHN_HIOS);
295  ENUM_TO_CSTR(SHN_ABS);
296  ENUM_TO_CSTR(SHN_COMMON);
297  ENUM_TO_CSTR(SHN_XINDEX);
298  default: {
299  const lldb_private::Section *section =
300  section_list->GetSectionAtIndex(shndx).get();
301  if (section)
302  return section->GetName().AsCString("");
303  } break;
304  }
305  return "";
306 }
307 
309  const lldb_private::DataExtractor *strtab_data,
310  const lldb_private::SectionList *section_list) {
311  s->Printf("[%3u] 0x%16.16" PRIx64 " 0x%16.16" PRIx64
312  " 0x%8.8x 0x%2.2x (%-10s %-13s) 0x%2.2x 0x%4.4x (%-10s) %s\n",
313  idx, st_value, st_size, st_name, st_info,
314  bindingToCString(getBinding()), typeToCString(getType()), st_other,
315  st_shndx, sectionIndexToCString(st_shndx, section_list),
316  strtab_data ? strtab_data->PeekCStr(st_name) : "");
317 }
318 
320  lldb::offset_t *offset) {
321  const unsigned byte_size = data.GetAddressByteSize();
322  const bool parsing_32 = byte_size == 4;
323 
324  // Read st_name.
325  if (data.GetU32(offset, &st_name, 1) == nullptr)
326  return false;
327 
328  if (parsing_32) {
329  // Read st_value and st_size.
330  if (!GetMaxU64(data, offset, &st_value, byte_size, 2))
331  return false;
332 
333  // Read st_info and st_other.
334  if (data.GetU8(offset, &st_info, 2) == nullptr)
335  return false;
336 
337  // Read st_shndx.
338  if (data.GetU16(offset, &st_shndx, 1) == nullptr)
339  return false;
340  } else {
341  // Read st_info and st_other.
342  if (data.GetU8(offset, &st_info, 2) == nullptr)
343  return false;
344 
345  // Read st_shndx.
346  if (data.GetU16(offset, &st_shndx, 1) == nullptr)
347  return false;
348 
349  // Read st_value and st_size.
350  if (data.GetU64(offset, &st_value, 2) == nullptr)
351  return false;
352  }
353  return true;
354 }
355 
356 // ELFProgramHeader
357 
359  memset(this, 0, sizeof(ELFProgramHeader));
360 }
361 
363  lldb::offset_t *offset) {
364  const uint32_t byte_size = data.GetAddressByteSize();
365  const bool parsing_32 = byte_size == 4;
366 
367  // Read p_type;
368  if (data.GetU32(offset, &p_type, 1) == nullptr)
369  return false;
370 
371  if (parsing_32) {
372  // Read p_offset, p_vaddr, p_paddr, p_filesz and p_memsz.
373  if (!GetMaxU64(data, offset, &p_offset, byte_size, 5))
374  return false;
375 
376  // Read p_flags.
377  if (data.GetU32(offset, &p_flags, 1) == nullptr)
378  return false;
379 
380  // Read p_align.
381  if (!GetMaxU64(data, offset, &p_align, byte_size))
382  return false;
383  } else {
384  // Read p_flags.
385  if (data.GetU32(offset, &p_flags, 1) == nullptr)
386  return false;
387 
388  // Read p_offset, p_vaddr, p_paddr, p_filesz, p_memsz and p_align.
389  if (!GetMaxU64(data, offset, &p_offset, byte_size, 6))
390  return false;
391  }
392 
393  return true;
394 }
395 
396 // ELFDynamic
397 
398 ELFDynamic::ELFDynamic() { memset(this, 0, sizeof(ELFDynamic)); }
399 
401  lldb::offset_t *offset) {
402  const unsigned byte_size = data.GetAddressByteSize();
403  return GetMaxS64(data, offset, &d_tag, byte_size, 2);
404 }
405 
406 // ELFRel
407 
408 ELFRel::ELFRel() { memset(this, 0, sizeof(ELFRel)); }
409 
411  lldb::offset_t *offset) {
412  const unsigned byte_size = data.GetAddressByteSize();
413 
414  // Read r_offset and r_info.
415  return GetMaxU64(data, offset, &r_offset, byte_size, 2) != false;
416 }
417 
418 // ELFRela
419 
420 ELFRela::ELFRela() { memset(this, 0, sizeof(ELFRela)); }
421 
423  lldb::offset_t *offset) {
424  const unsigned byte_size = data.GetAddressByteSize();
425 
426  // Read r_offset and r_info.
427  if (!GetMaxU64(data, offset, &r_offset, byte_size, 2))
428  return false;
429 
430  // Read r_addend;
431  if (!GetMaxS64(data, offset, &r_addend, byte_size))
432  return false;
433 
434  return true;
435 }
elf::ELFSectionHeader::sh_info
elf_word sh_info
Extra section info (overloaded).
Definition: ELFHeader.h:167
elf::ELFDynamic::ELFDynamic
ELFDynamic()
Definition: ELFHeader.cpp:398
elf::ELFHeader
Definition: ELFHeader.h:56
elf::ELFRela::ELFRela
ELFRela()
Definition: ELFHeader.cpp:420
elf::ELFHeader::HasHeaderExtension
bool HasHeaderExtension() const
Check if there should be header extension in section header #0.
Definition: ELFHeader.cpp:81
elf::ELFHeader::GetRelocationJumpSlotType
unsigned GetRelocationJumpSlotType() const
The jump slot relocation type of this ELF.
Definition: ELFHeader.cpp:176
elf::ELFHeader::ELFHeader
ELFHeader()
Definition: ELFHeader.cpp:71
elf::ELFHeader::Parse
bool Parse(lldb_private::DataExtractor &data, lldb::offset_t *offset)
Parse an ELFHeader entry starting at position offset and update the data extractor with the address s...
Definition: ELFHeader.cpp:114
elf::ELFSymbol::Parse
bool Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset)
Parse an ELFSymbol entry from the given DataExtractor starting at position offset.
Definition: ELFHeader.cpp:319
elf::ELFSymbol::ELFSymbol
ELFSymbol()
Definition: ELFHeader.cpp:251
elf::ELFSectionHeader::sh_size
elf_xword sh_size
Number of bytes occupied in the file.
Definition: ELFHeader.h:165
elf::ELFHeader::GetByteOrder
lldb::ByteOrder GetByteOrder() const
The byte order of this ELF file header.
Definition: ELFHeader.cpp:73
lldb_private::ConstString::AsCString
const char * AsCString(const char *value_if_empty=nullptr) const
Get the string value as a C string.
Definition: ConstString.h:193
lldb_private::SectionList
Definition: Section.h:34
lldb::offset_t
uint64_t offset_t
Definition: lldb-types.h:87
elf::ELFRel::Parse
bool Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset)
Parse an ELFRel entry from the given DataExtractor starting at position offset.
Definition: ELFHeader.cpp:410
lldb_private::Stream
Definition: Stream.h:28
Section.h
lldb_private::DataExtractor::GetU64
uint64_t GetU64(lldb::offset_t *offset_ptr) const
Extract a uint64_t value from *offset_ptr.
Definition: DataExtractor.cpp:476
elf::ELFProgramHeader::Parse
bool Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset)
Parse an ELFProgramHeader entry from the given DataExtractor starting at position offset.
Definition: ELFHeader.cpp:362
elf::ELFSectionHeader::Parse
bool Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset)
Parse an ELFSectionHeader entry from the given DataExtracter starting at position offset.
Definition: ELFHeader.cpp:222
lldb_private::DataExtractor::PeekCStr
const char * PeekCStr(lldb::offset_t offset) const
Peek at a C string at offset.
Definition: DataExtractor.cpp:834
ELFHeader.h
elf::ELFDynamic::Parse
bool Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset)
Parse an ELFDynamic entry from the given DataExtractor starting at position offset.
Definition: ELFHeader.cpp:400
lldb_private::DataExtractor::SetByteOrder
void SetByteOrder(lldb::ByteOrder byte_order)
Set the byte_order value.
Definition: DataExtractor.h:931
elf::ELFSectionHeader
Definition: ELFHeader.h:159
elf::ELFHeader::AddressSizeInBytes
static unsigned AddressSizeInBytes(const uint8_t *magic)
Examines at most EI_NIDENT bytes starting from the given address and determines the address size of t...
Definition: ELFHeader.cpp:161
elf::ELFRela::Parse
bool Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset)
Parse an ELFRela entry from the given DataExtractor starting at position offset.
Definition: ELFHeader.cpp:422
elf::ELFSymbol
Definition: ELFHeader.h:224
elf::ELFSymbol::sectionIndexToCString
static const char * sectionIndexToCString(elf_half shndx, const lldb_private::SectionList *section_list)
Definition: ELFHeader.cpp:287
lldb_private::DataExtractor::GetAddressByteSize
uint32_t GetAddressByteSize() const
Get the current address size.
Definition: DataExtractor.h:264
lldb_private::DataExtractor
Definition: DataExtractor.h:48
elf::ELFRel
Definition: ELFHeader.h:305
lldb_private::DataExtractor::GetMaxS64
int64_t GetMaxS64(lldb::offset_t *offset_ptr, size_t byte_size) const
Extract an signed integer of size byte_size from *offset_ptr.
Definition: DataExtractor.cpp:570
elf::ELFDynamic
Definition: ELFHeader.h:276
lldb_private::DataExtractor::SetAddressByteSize
void SetAddressByteSize(uint32_t addr_size)
Set the address byte size.
Definition: DataExtractor.h:845
lldb_private::Section::GetName
ConstString GetName() const
Definition: Section.h:170
lldb_private::DataExtractor::GetU8
uint8_t GetU8(lldb::offset_t *offset_ptr) const
Extract a uint8_t value from *offset_ptr.
Definition: DataExtractor.cpp:318
elf
Definition: ELFHeader.h:32
lldb_private::SectionList::GetSectionAtIndex
lldb::SectionSP GetSectionAtIndex(size_t idx) const
Definition: Section.cpp:476
elf::ELFProgramHeader::ELFProgramHeader
ELFProgramHeader()
Definition: ELFHeader.cpp:358
elf::ELFSectionHeader::ELFSectionHeader
ELFSectionHeader()
Definition: ELFHeader.cpp:218
lldb_private::Section
Definition: Section.h:96
ENUM_TO_CSTR
#define ENUM_TO_CSTR(e)
Definition: ELFHeader.cpp:253
elf::ELFSymbol::Dump
void Dump(lldb_private::Stream *s, uint32_t idx, const lldb_private::DataExtractor *strtab_data, const lldb_private::SectionList *section_list)
Definition: ELFHeader.cpp:308
elf::ELFSymbol::bindingToCString
static const char * bindingToCString(unsigned char binding)
Definition: ELFHeader.cpp:257
GetMaxU64
static bool GetMaxU64(const lldb_private::DataExtractor &data, lldb::offset_t *offset, uint64_t *value, uint32_t byte_size)
Definition: ELFHeader.cpp:25
lldb::eByteOrderInvalid
@ eByteOrderInvalid
Definition: lldb-enumerations.h:139
uint32_t
elf::ELFSymbol::typeToCString
static const char * typeToCString(unsigned char type)
Definition: ELFHeader.cpp:270
lldb_private::DataExtractor::GetMaxU64
uint64_t GetMaxU64(lldb::offset_t *offset_ptr, size_t byte_size) const
Extract an unsigned integer of size byte_size from *offset_ptr.
Definition: DataExtractor.cpp:526
elf::ELFHeader::MagicBytesMatch
static bool MagicBytesMatch(const uint8_t *magic)
Examines at most EI_NIDENT bytes starting from the given pointer and determines if the magic ELF iden...
Definition: ELFHeader.cpp:157
elf::ELFProgramHeader
Definition: ELFHeader.h:192
uint16_t
lldb_private::DataExtractor::GetU32
uint32_t GetU32(lldb::offset_t *offset_ptr) const
Extract a uint32_t value from *offset_ptr.
Definition: DataExtractor.cpp:427
DataExtractor.h
lldb_private::Stream::Printf
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:107
lldb_private::DataExtractor::GetU16
uint16_t GetU16(lldb::offset_t *offset_ptr) const
Extract a uint16_t value from *offset_ptr.
Definition: DataExtractor.cpp:349
lldb::eByteOrderBig
@ eByteOrderBig
Definition: lldb-enumerations.h:140
elf::ELFRel::ELFRel
ELFRel()
Definition: ELFHeader.cpp:408
Stream.h
GetMaxS64
static bool GetMaxS64(const lldb_private::DataExtractor &data, lldb::offset_t *offset, int64_t *value, uint32_t byte_size)
Definition: ELFHeader.cpp:47
elf::ELFRela
Definition: ELFHeader.h:346
lldb::eByteOrderLittle
@ eByteOrderLittle
Definition: lldb-enumerations.h:142
lldb
Definition: SBAddress.h:15
lldb::ByteOrder
ByteOrder
Byte ordering definitions.
Definition: lldb-enumerations.h:138
elf::ELFSectionHeader::sh_link
elf_word sh_link
Index of associated section.
Definition: ELFHeader.h:166
elf::ELFHeader::ParseHeaderExtension
void ParseHeaderExtension(lldb_private::DataExtractor &data)
Parse an ELFHeader header extension entry.
Definition: ELFHeader.cpp:96