xref: /llvm-project/lldb/source/Plugins/ObjectFile/ELF/ELFHeader.cpp (revision b9c1b51e45b845debb76d8658edabca70ca56079)
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/DataExtractor.h"
13 #include "lldb/Core/Section.h"
14 #include "lldb/Core/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::Parse(lldb_private::DataExtractor &data,
85                       lldb::offset_t *offset) {
86   // Read e_ident.  This provides byte order and address size info.
87   if (data.GetU8(offset, &e_ident, EI_NIDENT) == NULL)
88     return false;
89 
90   const unsigned byte_size = Is32Bit() ? 4 : 8;
91   data.SetByteOrder(GetByteOrder());
92   data.SetAddressByteSize(byte_size);
93 
94   // Read e_type and e_machine.
95   if (data.GetU16(offset, &e_type, 2) == NULL)
96     return false;
97 
98   // Read e_version.
99   if (data.GetU32(offset, &e_version, 1) == NULL)
100     return false;
101 
102   // Read e_entry, e_phoff and e_shoff.
103   if (GetMaxU64(data, offset, &e_entry, byte_size, 3) == false)
104     return false;
105 
106   // Read e_flags.
107   if (data.GetU32(offset, &e_flags, 1) == NULL)
108     return false;
109 
110   // Read e_ehsize, e_phentsize, e_phnum, e_shentsize, e_shnum and
111   // e_shstrndx.
112   if (data.GetU16(offset, &e_ehsize, 6) == NULL)
113     return false;
114 
115   return true;
116 }
117 
118 bool ELFHeader::MagicBytesMatch(const uint8_t *magic) {
119   return memcmp(magic, ElfMagic, strlen(ElfMagic)) == 0;
120 }
121 
122 unsigned ELFHeader::AddressSizeInBytes(const uint8_t *magic) {
123   unsigned address_size = 0;
124 
125   switch (magic[EI_CLASS]) {
126   case ELFCLASS32:
127     address_size = 4;
128     break;
129 
130   case ELFCLASS64:
131     address_size = 8;
132     break;
133   }
134   return address_size;
135 }
136 
137 unsigned ELFHeader::GetRelocationJumpSlotType() const {
138   unsigned slot = 0;
139 
140   switch (e_machine) {
141   default:
142     assert(false && "architecture not supported");
143     break;
144   case EM_PPC:
145     slot = R_PPC_JMP_SLOT;
146     break;
147   case EM_PPC64:
148     slot = R_PPC64_JMP_SLOT;
149     break;
150   case EM_386:
151   case EM_IAMCU: // FIXME: is this correct?
152     slot = R_386_JUMP_SLOT;
153     break;
154   case EM_X86_64:
155     slot = R_X86_64_JUMP_SLOT;
156     break;
157   case EM_ARM:
158     slot = R_ARM_JUMP_SLOT;
159     break;
160   case EM_HEXAGON:
161     slot = R_HEX_JMP_SLOT;
162     break;
163   case EM_AARCH64:
164     slot = R_AARCH64_JUMP_SLOT;
165     break;
166   case EM_MIPS:
167     slot = R_MIPS_JUMP_SLOT;
168     break;
169   case EM_S390:
170     slot = R_390_JMP_SLOT;
171     break;
172   }
173 
174   return slot;
175 }
176 
177 //------------------------------------------------------------------------------
178 // ELFSectionHeader
179 
180 ELFSectionHeader::ELFSectionHeader() {
181   memset(this, 0, sizeof(ELFSectionHeader));
182 }
183 
184 bool ELFSectionHeader::Parse(const lldb_private::DataExtractor &data,
185                              lldb::offset_t *offset) {
186   const unsigned byte_size = data.GetAddressByteSize();
187 
188   // Read sh_name and sh_type.
189   if (data.GetU32(offset, &sh_name, 2) == NULL)
190     return false;
191 
192   // Read sh_flags.
193   if (GetMaxU64(data, offset, &sh_flags, byte_size) == false)
194     return false;
195 
196   // Read sh_addr, sh_off and sh_size.
197   if (GetMaxU64(data, offset, &sh_addr, byte_size, 3) == false)
198     return false;
199 
200   // Read sh_link and sh_info.
201   if (data.GetU32(offset, &sh_link, 2) == NULL)
202     return false;
203 
204   // Read sh_addralign and sh_entsize.
205   if (GetMaxU64(data, offset, &sh_addralign, byte_size, 2) == false)
206     return false;
207 
208   return true;
209 }
210 
211 //------------------------------------------------------------------------------
212 // ELFSymbol
213 
214 ELFSymbol::ELFSymbol() { memset(this, 0, sizeof(ELFSymbol)); }
215 
216 #define ENUM_TO_CSTR(e)                                                        \
217   case e:                                                                      \
218     return #e
219 
220 const char *ELFSymbol::bindingToCString(unsigned char binding) {
221   switch (binding) {
222     ENUM_TO_CSTR(STB_LOCAL);
223     ENUM_TO_CSTR(STB_GLOBAL);
224     ENUM_TO_CSTR(STB_WEAK);
225     ENUM_TO_CSTR(STB_LOOS);
226     ENUM_TO_CSTR(STB_HIOS);
227     ENUM_TO_CSTR(STB_LOPROC);
228     ENUM_TO_CSTR(STB_HIPROC);
229   }
230   return "";
231 }
232 
233 const char *ELFSymbol::typeToCString(unsigned char type) {
234   switch (type) {
235     ENUM_TO_CSTR(STT_NOTYPE);
236     ENUM_TO_CSTR(STT_OBJECT);
237     ENUM_TO_CSTR(STT_FUNC);
238     ENUM_TO_CSTR(STT_SECTION);
239     ENUM_TO_CSTR(STT_FILE);
240     ENUM_TO_CSTR(STT_COMMON);
241     ENUM_TO_CSTR(STT_TLS);
242     ENUM_TO_CSTR(STT_GNU_IFUNC);
243     ENUM_TO_CSTR(STT_HIOS);
244     ENUM_TO_CSTR(STT_LOPROC);
245     ENUM_TO_CSTR(STT_HIPROC);
246   }
247   return "";
248 }
249 
250 const char *ELFSymbol::sectionIndexToCString(
251     elf_half shndx, const lldb_private::SectionList *section_list) {
252   switch (shndx) {
253     ENUM_TO_CSTR(SHN_UNDEF);
254     ENUM_TO_CSTR(SHN_LOPROC);
255     ENUM_TO_CSTR(SHN_HIPROC);
256     ENUM_TO_CSTR(SHN_LOOS);
257     ENUM_TO_CSTR(SHN_HIOS);
258     ENUM_TO_CSTR(SHN_ABS);
259     ENUM_TO_CSTR(SHN_COMMON);
260     ENUM_TO_CSTR(SHN_XINDEX);
261   default: {
262     const lldb_private::Section *section =
263         section_list->GetSectionAtIndex(shndx).get();
264     if (section)
265       return section->GetName().AsCString("");
266   } break;
267   }
268   return "";
269 }
270 
271 void ELFSymbol::Dump(lldb_private::Stream *s, uint32_t idx,
272                      const lldb_private::DataExtractor *strtab_data,
273                      const lldb_private::SectionList *section_list) {
274   s->Printf("[%3u] 0x%16.16" PRIx64 " 0x%16.16" PRIx64
275             " 0x%8.8x 0x%2.2x (%-10s %-13s) 0x%2.2x 0x%4.4x (%-10s) %s\n",
276             idx, st_value, st_size, st_name, st_info,
277             bindingToCString(getBinding()), typeToCString(getType()), st_other,
278             st_shndx, sectionIndexToCString(st_shndx, section_list),
279             strtab_data ? strtab_data->PeekCStr(st_name) : "");
280 }
281 
282 bool ELFSymbol::Parse(const lldb_private::DataExtractor &data,
283                       lldb::offset_t *offset) {
284   const unsigned byte_size = data.GetAddressByteSize();
285   const bool parsing_32 = byte_size == 4;
286 
287   // Read st_name.
288   if (data.GetU32(offset, &st_name, 1) == NULL)
289     return false;
290 
291   if (parsing_32) {
292     // Read st_value and st_size.
293     if (GetMaxU64(data, offset, &st_value, byte_size, 2) == false)
294       return false;
295 
296     // Read st_info and st_other.
297     if (data.GetU8(offset, &st_info, 2) == NULL)
298       return false;
299 
300     // Read st_shndx.
301     if (data.GetU16(offset, &st_shndx, 1) == NULL)
302       return false;
303   } else {
304     // Read st_info and st_other.
305     if (data.GetU8(offset, &st_info, 2) == NULL)
306       return false;
307 
308     // Read st_shndx.
309     if (data.GetU16(offset, &st_shndx, 1) == NULL)
310       return false;
311 
312     // Read st_value and st_size.
313     if (data.GetU64(offset, &st_value, 2) == NULL)
314       return false;
315   }
316   return true;
317 }
318 
319 //------------------------------------------------------------------------------
320 // ELFProgramHeader
321 
322 ELFProgramHeader::ELFProgramHeader() {
323   memset(this, 0, sizeof(ELFProgramHeader));
324 }
325 
326 bool ELFProgramHeader::Parse(const lldb_private::DataExtractor &data,
327                              lldb::offset_t *offset) {
328   const uint32_t byte_size = data.GetAddressByteSize();
329   const bool parsing_32 = byte_size == 4;
330 
331   // Read p_type;
332   if (data.GetU32(offset, &p_type, 1) == NULL)
333     return false;
334 
335   if (parsing_32) {
336     // Read p_offset, p_vaddr, p_paddr, p_filesz and p_memsz.
337     if (GetMaxU64(data, offset, &p_offset, byte_size, 5) == false)
338       return false;
339 
340     // Read p_flags.
341     if (data.GetU32(offset, &p_flags, 1) == NULL)
342       return false;
343 
344     // Read p_align.
345     if (GetMaxU64(data, offset, &p_align, byte_size) == false)
346       return false;
347   } else {
348     // Read p_flags.
349     if (data.GetU32(offset, &p_flags, 1) == NULL)
350       return false;
351 
352     // Read p_offset, p_vaddr, p_paddr, p_filesz, p_memsz and p_align.
353     if (GetMaxU64(data, offset, &p_offset, byte_size, 6) == false)
354       return false;
355   }
356 
357   return true;
358 }
359 
360 //------------------------------------------------------------------------------
361 // ELFDynamic
362 
363 ELFDynamic::ELFDynamic() { memset(this, 0, sizeof(ELFDynamic)); }
364 
365 bool ELFDynamic::Parse(const lldb_private::DataExtractor &data,
366                        lldb::offset_t *offset) {
367   const unsigned byte_size = data.GetAddressByteSize();
368   return GetMaxS64(data, offset, &d_tag, byte_size, 2);
369 }
370 
371 //------------------------------------------------------------------------------
372 // ELFRel
373 
374 ELFRel::ELFRel() { memset(this, 0, sizeof(ELFRel)); }
375 
376 bool ELFRel::Parse(const lldb_private::DataExtractor &data,
377                    lldb::offset_t *offset) {
378   const unsigned byte_size = data.GetAddressByteSize();
379 
380   // Read r_offset and r_info.
381   if (GetMaxU64(data, offset, &r_offset, byte_size, 2) == false)
382     return false;
383 
384   return true;
385 }
386 
387 //------------------------------------------------------------------------------
388 // ELFRela
389 
390 ELFRela::ELFRela() { memset(this, 0, sizeof(ELFRela)); }
391 
392 bool ELFRela::Parse(const lldb_private::DataExtractor &data,
393                     lldb::offset_t *offset) {
394   const unsigned byte_size = data.GetAddressByteSize();
395 
396   // Read r_offset and r_info.
397   if (GetMaxU64(data, offset, &r_offset, byte_size, 2) == false)
398     return false;
399 
400   // Read r_addend;
401   if (GetMaxS64(data, offset, &r_addend, byte_size) == false)
402     return false;
403 
404   return true;
405 }
406