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