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  case EM_RISCV:
212  slot = R_RISCV_JUMP_SLOT;
213  break;
214  }
215 
216  return slot;
217 }
218 
219 // ELFSectionHeader
220 
222  memset(this, 0, sizeof(ELFSectionHeader));
223 }
224 
226  lldb::offset_t *offset) {
227  const unsigned byte_size = data.GetAddressByteSize();
228 
229  // Read sh_name and sh_type.
230  if (data.GetU32(offset, &sh_name, 2) == nullptr)
231  return false;
232 
233  // Read sh_flags.
234  if (!GetMaxU64(data, offset, &sh_flags, byte_size))
235  return false;
236 
237  // Read sh_addr, sh_off and sh_size.
238  if (!GetMaxU64(data, offset, &sh_addr, byte_size, 3))
239  return false;
240 
241  // Read sh_link and sh_info.
242  if (data.GetU32(offset, &sh_link, 2) == nullptr)
243  return false;
244 
245  // Read sh_addralign and sh_entsize.
246  if (!GetMaxU64(data, offset, &sh_addralign, byte_size, 2))
247  return false;
248 
249  return true;
250 }
251 
252 // ELFSymbol
253 
254 ELFSymbol::ELFSymbol() { memset(this, 0, sizeof(ELFSymbol)); }
255 
256 #define ENUM_TO_CSTR(e) \
257  case e: \
258  return #e
259 
260 const char *ELFSymbol::bindingToCString(unsigned char binding) {
261  switch (binding) {
262  ENUM_TO_CSTR(STB_LOCAL);
263  ENUM_TO_CSTR(STB_GLOBAL);
264  ENUM_TO_CSTR(STB_WEAK);
265  ENUM_TO_CSTR(STB_LOOS);
266  ENUM_TO_CSTR(STB_HIOS);
267  ENUM_TO_CSTR(STB_LOPROC);
268  ENUM_TO_CSTR(STB_HIPROC);
269  }
270  return "";
271 }
272 
273 const char *ELFSymbol::typeToCString(unsigned char type) {
274  switch (type) {
275  ENUM_TO_CSTR(STT_NOTYPE);
276  ENUM_TO_CSTR(STT_OBJECT);
277  ENUM_TO_CSTR(STT_FUNC);
278  ENUM_TO_CSTR(STT_SECTION);
279  ENUM_TO_CSTR(STT_FILE);
280  ENUM_TO_CSTR(STT_COMMON);
281  ENUM_TO_CSTR(STT_TLS);
282  ENUM_TO_CSTR(STT_GNU_IFUNC);
283  ENUM_TO_CSTR(STT_HIOS);
284  ENUM_TO_CSTR(STT_LOPROC);
285  ENUM_TO_CSTR(STT_HIPROC);
286  }
287  return "";
288 }
289 
291  elf_half shndx, const lldb_private::SectionList *section_list) {
292  switch (shndx) {
293  ENUM_TO_CSTR(SHN_UNDEF);
294  ENUM_TO_CSTR(SHN_LOPROC);
295  ENUM_TO_CSTR(SHN_HIPROC);
296  ENUM_TO_CSTR(SHN_LOOS);
297  ENUM_TO_CSTR(SHN_HIOS);
298  ENUM_TO_CSTR(SHN_ABS);
299  ENUM_TO_CSTR(SHN_COMMON);
300  ENUM_TO_CSTR(SHN_XINDEX);
301  default: {
302  const lldb_private::Section *section =
303  section_list->GetSectionAtIndex(shndx).get();
304  if (section)
305  return section->GetName().AsCString("");
306  } break;
307  }
308  return "";
309 }
310 
312  const lldb_private::DataExtractor *strtab_data,
313  const lldb_private::SectionList *section_list) {
314  s->Printf("[%3u] 0x%16.16" PRIx64 " 0x%16.16" PRIx64
315  " 0x%8.8x 0x%2.2x (%-10s %-13s) 0x%2.2x 0x%4.4x (%-10s) %s\n",
316  idx, st_value, st_size, st_name, st_info,
317  bindingToCString(getBinding()), typeToCString(getType()), st_other,
318  st_shndx, sectionIndexToCString(st_shndx, section_list),
319  strtab_data ? strtab_data->PeekCStr(st_name) : "");
320 }
321 
323  lldb::offset_t *offset) {
324  const unsigned byte_size = data.GetAddressByteSize();
325  const bool parsing_32 = byte_size == 4;
326 
327  // Read st_name.
328  if (data.GetU32(offset, &st_name, 1) == nullptr)
329  return false;
330 
331  if (parsing_32) {
332  // Read st_value and st_size.
333  if (!GetMaxU64(data, offset, &st_value, byte_size, 2))
334  return false;
335 
336  // Read st_info and st_other.
337  if (data.GetU8(offset, &st_info, 2) == nullptr)
338  return false;
339 
340  // Read st_shndx.
341  if (data.GetU16(offset, &st_shndx, 1) == nullptr)
342  return false;
343  } else {
344  // Read st_info and st_other.
345  if (data.GetU8(offset, &st_info, 2) == nullptr)
346  return false;
347 
348  // Read st_shndx.
349  if (data.GetU16(offset, &st_shndx, 1) == nullptr)
350  return false;
351 
352  // Read st_value and st_size.
353  if (data.GetU64(offset, &st_value, 2) == nullptr)
354  return false;
355  }
356  return true;
357 }
358 
359 // ELFProgramHeader
360 
362  memset(this, 0, sizeof(ELFProgramHeader));
363 }
364 
366  lldb::offset_t *offset) {
367  const uint32_t byte_size = data.GetAddressByteSize();
368  const bool parsing_32 = byte_size == 4;
369 
370  // Read p_type;
371  if (data.GetU32(offset, &p_type, 1) == nullptr)
372  return false;
373 
374  if (parsing_32) {
375  // Read p_offset, p_vaddr, p_paddr, p_filesz and p_memsz.
376  if (!GetMaxU64(data, offset, &p_offset, byte_size, 5))
377  return false;
378 
379  // Read p_flags.
380  if (data.GetU32(offset, &p_flags, 1) == nullptr)
381  return false;
382 
383  // Read p_align.
384  if (!GetMaxU64(data, offset, &p_align, byte_size))
385  return false;
386  } else {
387  // Read p_flags.
388  if (data.GetU32(offset, &p_flags, 1) == nullptr)
389  return false;
390 
391  // Read p_offset, p_vaddr, p_paddr, p_filesz, p_memsz and p_align.
392  if (!GetMaxU64(data, offset, &p_offset, byte_size, 6))
393  return false;
394  }
395 
396  return true;
397 }
398 
399 // ELFDynamic
400 
401 ELFDynamic::ELFDynamic() { memset(this, 0, sizeof(ELFDynamic)); }
402 
404  lldb::offset_t *offset) {
405  const unsigned byte_size = data.GetAddressByteSize();
406  return GetMaxS64(data, offset, &d_tag, byte_size, 2);
407 }
408 
409 // ELFRel
410 
411 ELFRel::ELFRel() { memset(this, 0, sizeof(ELFRel)); }
412 
414  lldb::offset_t *offset) {
415  const unsigned byte_size = data.GetAddressByteSize();
416 
417  // Read r_offset and r_info.
418  return GetMaxU64(data, offset, &r_offset, byte_size, 2) != false;
419 }
420 
421 // ELFRela
422 
423 ELFRela::ELFRela() { memset(this, 0, sizeof(ELFRela)); }
424 
426  lldb::offset_t *offset) {
427  const unsigned byte_size = data.GetAddressByteSize();
428 
429  // Read r_offset and r_info.
430  if (!GetMaxU64(data, offset, &r_offset, byte_size, 2))
431  return false;
432 
433  // Read r_addend;
434  if (!GetMaxS64(data, offset, &r_addend, byte_size))
435  return false;
436 
437  return true;
438 }
elf::ELFSectionHeader::sh_info
elf_word sh_info
Extra section info (overloaded).
Definition: ELFHeader.h:167
elf::ELFDynamic::ELFDynamic
ELFDynamic()
Definition: ELFHeader.cpp:401
elf::ELFHeader
Definition: ELFHeader.h:56
elf::ELFRela::ELFRela
ELFRela()
Definition: ELFHeader.cpp:423
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:322
elf::ELFSymbol::ELFSymbol
ELFSymbol()
Definition: ELFHeader.cpp:254
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:192
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:413
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:474
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:365
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:225
lldb_private::DataExtractor::PeekCStr
const char * PeekCStr(lldb::offset_t offset) const
Peek at a C string at offset.
Definition: DataExtractor.cpp:832
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:403
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:425
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:290
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:568
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:176
lldb_private::DataExtractor::GetU8
uint8_t GetU8(lldb::offset_t *offset_ptr) const
Extract a uint8_t value from *offset_ptr.
Definition: DataExtractor.cpp:316
elf
Definition: ELFHeader.h:32
lldb_private::SectionList::GetSectionAtIndex
lldb::SectionSP GetSectionAtIndex(size_t idx) const
Definition: Section.cpp:538
elf::ELFProgramHeader::ELFProgramHeader
ELFProgramHeader()
Definition: ELFHeader.cpp:361
elf::ELFSectionHeader::ELFSectionHeader
ELFSectionHeader()
Definition: ELFHeader.cpp:221
lldb_private::Section
Definition: Section.h:102
ENUM_TO_CSTR
#define ENUM_TO_CSTR(e)
Definition: ELFHeader.cpp:256
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:311
elf::ELFSymbol::bindingToCString
static const char * bindingToCString(unsigned char binding)
Definition: ELFHeader.cpp:260
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:140
uint32_t
elf::ELFSymbol::typeToCString
static const char * typeToCString(unsigned char type)
Definition: ELFHeader.cpp:273
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:524
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:425
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:347
lldb::eByteOrderBig
@ eByteOrderBig
Definition: lldb-enumerations.h:141
elf::ELFRel::ELFRel
ELFRel()
Definition: ELFHeader.cpp:411
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:143
lldb
Definition: SBAddress.h:15
lldb::ByteOrder
ByteOrder
Byte ordering definitions.
Definition: lldb-enumerations.h:139
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