xref: /src/contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ELFHeader.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
1cfca06d7SDimitry Andric //===-- ELFHeader.cpp -----------------------------------------------------===//
2f034231aSEd Maste //
35f29bb8aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f29bb8aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f29bb8aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f034231aSEd Maste //
7f034231aSEd Maste //===----------------------------------------------------------------------===//
8f034231aSEd Maste 
9f034231aSEd Maste #include <cstring>
10f034231aSEd Maste 
11f034231aSEd Maste #include "lldb/Core/Section.h"
1274a628f7SDimitry Andric #include "lldb/Utility/DataExtractor.h"
1374a628f7SDimitry Andric #include "lldb/Utility/Stream.h"
14f034231aSEd Maste 
15f034231aSEd Maste #include "ELFHeader.h"
16f034231aSEd Maste 
17f034231aSEd Maste using namespace elf;
18f034231aSEd Maste using namespace lldb;
19f034231aSEd Maste using namespace llvm::ELF;
20f034231aSEd Maste 
21f034231aSEd Maste // Static utility functions.
22f034231aSEd Maste //
23f034231aSEd Maste // GetMaxU64 and GetMaxS64 wrap the similarly named methods from DataExtractor
24f034231aSEd Maste // with error handling code and provide for parsing a sequence of values.
GetMaxU64(const lldb_private::DataExtractor & data,lldb::offset_t * offset,uint64_t * value,uint32_t byte_size)2514f1b3e8SDimitry Andric static bool GetMaxU64(const lldb_private::DataExtractor &data,
2614f1b3e8SDimitry Andric                       lldb::offset_t *offset, uint64_t *value,
2714f1b3e8SDimitry Andric                       uint32_t byte_size) {
28f034231aSEd Maste   const lldb::offset_t saved_offset = *offset;
29f034231aSEd Maste   *value = data.GetMaxU64(offset, byte_size);
30f034231aSEd Maste   return *offset != saved_offset;
31f034231aSEd Maste }
32f034231aSEd Maste 
GetMaxU64(const lldb_private::DataExtractor & data,lldb::offset_t * offset,uint64_t * value,uint32_t byte_size,uint32_t count)3314f1b3e8SDimitry Andric static bool GetMaxU64(const lldb_private::DataExtractor &data,
3414f1b3e8SDimitry Andric                       lldb::offset_t *offset, uint64_t *value,
3514f1b3e8SDimitry Andric                       uint32_t byte_size, uint32_t count) {
36f034231aSEd Maste   lldb::offset_t saved_offset = *offset;
37f034231aSEd Maste 
3814f1b3e8SDimitry Andric   for (uint32_t i = 0; i < count; ++i, ++value) {
3994994d37SDimitry Andric     if (!GetMaxU64(data, offset, value, byte_size)) {
40f034231aSEd Maste       *offset = saved_offset;
41f034231aSEd Maste       return false;
42f034231aSEd Maste     }
43f034231aSEd Maste   }
44f034231aSEd Maste   return true;
45f034231aSEd Maste }
46f034231aSEd Maste 
GetMaxS64(const lldb_private::DataExtractor & data,lldb::offset_t * offset,int64_t * value,uint32_t byte_size)4714f1b3e8SDimitry Andric static bool GetMaxS64(const lldb_private::DataExtractor &data,
4814f1b3e8SDimitry Andric                       lldb::offset_t *offset, int64_t *value,
4914f1b3e8SDimitry Andric                       uint32_t byte_size) {
50f034231aSEd Maste   const lldb::offset_t saved_offset = *offset;
51f034231aSEd Maste   *value = data.GetMaxS64(offset, byte_size);
52f034231aSEd Maste   return *offset != saved_offset;
53f034231aSEd Maste }
54f034231aSEd Maste 
GetMaxS64(const lldb_private::DataExtractor & data,lldb::offset_t * offset,int64_t * value,uint32_t byte_size,uint32_t count)5514f1b3e8SDimitry Andric static bool GetMaxS64(const lldb_private::DataExtractor &data,
5614f1b3e8SDimitry Andric                       lldb::offset_t *offset, int64_t *value,
5714f1b3e8SDimitry Andric                       uint32_t byte_size, uint32_t count) {
58f034231aSEd Maste   lldb::offset_t saved_offset = *offset;
59f034231aSEd Maste 
6014f1b3e8SDimitry Andric   for (uint32_t i = 0; i < count; ++i, ++value) {
6194994d37SDimitry Andric     if (!GetMaxS64(data, offset, value, byte_size)) {
62f034231aSEd Maste       *offset = saved_offset;
63f034231aSEd Maste       return false;
64f034231aSEd Maste     }
65f034231aSEd Maste   }
66f034231aSEd Maste   return true;
67f034231aSEd Maste }
68f034231aSEd Maste 
69f034231aSEd Maste // ELFHeader
70f034231aSEd Maste 
ELFHeader()7114f1b3e8SDimitry Andric ELFHeader::ELFHeader() { memset(this, 0, sizeof(ELFHeader)); }
72f034231aSEd Maste 
GetByteOrder() const7314f1b3e8SDimitry Andric ByteOrder ELFHeader::GetByteOrder() const {
74f034231aSEd Maste   if (e_ident[EI_DATA] == ELFDATA2MSB)
75f034231aSEd Maste     return eByteOrderBig;
76f034231aSEd Maste   if (e_ident[EI_DATA] == ELFDATA2LSB)
77f034231aSEd Maste     return eByteOrderLittle;
78f034231aSEd Maste   return eByteOrderInvalid;
79f034231aSEd Maste }
80f034231aSEd Maste 
HasHeaderExtension() const8174a628f7SDimitry Andric bool ELFHeader::HasHeaderExtension() const {
8274a628f7SDimitry Andric   bool result = false;
8374a628f7SDimitry Andric 
8474a628f7SDimitry Andric   // Check if any of these values looks like sentinel.
8574a628f7SDimitry Andric   result |= e_phnum_hdr == 0xFFFF; // PN_XNUM
8674a628f7SDimitry Andric   result |= e_shnum_hdr == SHN_UNDEF;
8774a628f7SDimitry Andric   result |= e_shstrndx_hdr == SHN_XINDEX;
8874a628f7SDimitry Andric 
8974a628f7SDimitry Andric   // If header extension is present, the section offset cannot be null.
9074a628f7SDimitry Andric   result &= e_shoff != 0;
9174a628f7SDimitry Andric 
9274a628f7SDimitry Andric   // Done.
9374a628f7SDimitry Andric   return result;
9474a628f7SDimitry Andric }
9574a628f7SDimitry Andric 
ParseHeaderExtension(lldb_private::DataExtractor & data)9674a628f7SDimitry Andric void ELFHeader::ParseHeaderExtension(lldb_private::DataExtractor &data) {
9774a628f7SDimitry Andric   // Extract section #0 header.
9874a628f7SDimitry Andric   ELFSectionHeader section_zero;
9974a628f7SDimitry Andric   lldb::offset_t offset = 0;
10074a628f7SDimitry Andric   lldb_private::DataExtractor sh_data(data, e_shoff, e_shentsize);
10174a628f7SDimitry Andric   bool ok = section_zero.Parse(sh_data, &offset);
10274a628f7SDimitry Andric 
10374a628f7SDimitry Andric   // If we succeeded, fix the header.
10474a628f7SDimitry Andric   if (ok) {
10574a628f7SDimitry Andric     if (e_phnum_hdr == 0xFFFF) // PN_XNUM
10674a628f7SDimitry Andric       e_phnum = section_zero.sh_info;
10774a628f7SDimitry Andric     if (e_shnum_hdr == SHN_UNDEF)
10874a628f7SDimitry Andric       e_shnum = section_zero.sh_size;
10974a628f7SDimitry Andric     if (e_shstrndx_hdr == SHN_XINDEX)
11074a628f7SDimitry Andric       e_shstrndx = section_zero.sh_link;
11174a628f7SDimitry Andric   }
11274a628f7SDimitry Andric }
11374a628f7SDimitry Andric 
Parse(lldb_private::DataExtractor & data,lldb::offset_t * offset)11414f1b3e8SDimitry Andric bool ELFHeader::Parse(lldb_private::DataExtractor &data,
11514f1b3e8SDimitry Andric                       lldb::offset_t *offset) {
116f034231aSEd Maste   // Read e_ident.  This provides byte order and address size info.
1175f29bb8aSDimitry Andric   if (data.GetU8(offset, &e_ident, EI_NIDENT) == nullptr)
118f034231aSEd Maste     return false;
119f034231aSEd Maste 
120f034231aSEd Maste   const unsigned byte_size = Is32Bit() ? 4 : 8;
121f034231aSEd Maste   data.SetByteOrder(GetByteOrder());
122f034231aSEd Maste   data.SetAddressByteSize(byte_size);
123f034231aSEd Maste 
124f034231aSEd Maste   // Read e_type and e_machine.
1255f29bb8aSDimitry Andric   if (data.GetU16(offset, &e_type, 2) == nullptr)
126f034231aSEd Maste     return false;
127f034231aSEd Maste 
128f034231aSEd Maste   // Read e_version.
1295f29bb8aSDimitry Andric   if (data.GetU32(offset, &e_version, 1) == nullptr)
130f034231aSEd Maste     return false;
131f034231aSEd Maste 
132f034231aSEd Maste   // Read e_entry, e_phoff and e_shoff.
13394994d37SDimitry Andric   if (!GetMaxU64(data, offset, &e_entry, byte_size, 3))
134f034231aSEd Maste     return false;
135f034231aSEd Maste 
136f034231aSEd Maste   // Read e_flags.
1375f29bb8aSDimitry Andric   if (data.GetU32(offset, &e_flags, 1) == nullptr)
138f034231aSEd Maste     return false;
139f034231aSEd Maste 
140f73363f1SDimitry Andric   // Read e_ehsize, e_phentsize, e_phnum, e_shentsize, e_shnum and e_shstrndx.
1415f29bb8aSDimitry Andric   if (data.GetU16(offset, &e_ehsize, 6) == nullptr)
142f034231aSEd Maste     return false;
143f034231aSEd Maste 
144f73363f1SDimitry Andric   // Initialize e_phnum, e_shnum, and e_shstrndx with the values read from the
145f73363f1SDimitry Andric   // header.
14674a628f7SDimitry Andric   e_phnum = e_phnum_hdr;
14774a628f7SDimitry Andric   e_shnum = e_shnum_hdr;
14874a628f7SDimitry Andric   e_shstrndx = e_shstrndx_hdr;
14974a628f7SDimitry Andric 
15074a628f7SDimitry Andric   // See if we have extended header in section #0.
15174a628f7SDimitry Andric   if (HasHeaderExtension())
15274a628f7SDimitry Andric     ParseHeaderExtension(data);
15374a628f7SDimitry Andric 
154f034231aSEd Maste   return true;
155f034231aSEd Maste }
156f034231aSEd Maste 
MagicBytesMatch(const uint8_t * magic)15714f1b3e8SDimitry Andric bool ELFHeader::MagicBytesMatch(const uint8_t *magic) {
158f034231aSEd Maste   return memcmp(magic, ElfMagic, strlen(ElfMagic)) == 0;
159f034231aSEd Maste }
160f034231aSEd Maste 
AddressSizeInBytes(const uint8_t * magic)16114f1b3e8SDimitry Andric unsigned ELFHeader::AddressSizeInBytes(const uint8_t *magic) {
162f034231aSEd Maste   unsigned address_size = 0;
163f034231aSEd Maste 
16414f1b3e8SDimitry Andric   switch (magic[EI_CLASS]) {
165f034231aSEd Maste   case ELFCLASS32:
166f034231aSEd Maste     address_size = 4;
167f034231aSEd Maste     break;
168f034231aSEd Maste 
169f034231aSEd Maste   case ELFCLASS64:
170f034231aSEd Maste     address_size = 8;
171f034231aSEd Maste     break;
172f034231aSEd Maste   }
173f034231aSEd Maste   return address_size;
174f034231aSEd Maste }
175f034231aSEd Maste 
GetRelocationJumpSlotType() const17614f1b3e8SDimitry Andric unsigned ELFHeader::GetRelocationJumpSlotType() const {
177f034231aSEd Maste   unsigned slot = 0;
178f034231aSEd Maste 
17914f1b3e8SDimitry Andric   switch (e_machine) {
180f034231aSEd Maste   default:
181f034231aSEd Maste     assert(false && "architecture not supported");
182f034231aSEd Maste     break;
183205afe67SEd Maste   case EM_PPC:
184205afe67SEd Maste     slot = R_PPC_JMP_SLOT;
185205afe67SEd Maste     break;
186205afe67SEd Maste   case EM_PPC64:
187205afe67SEd Maste     slot = R_PPC64_JMP_SLOT;
188205afe67SEd Maste     break;
189f034231aSEd Maste   case EM_386:
1905e95aa85SEd Maste   case EM_IAMCU: // FIXME: is this correct?
191f034231aSEd Maste     slot = R_386_JUMP_SLOT;
192f034231aSEd Maste     break;
193f034231aSEd Maste   case EM_X86_64:
194f034231aSEd Maste     slot = R_X86_64_JUMP_SLOT;
195f034231aSEd Maste     break;
196f034231aSEd Maste   case EM_ARM:
197f034231aSEd Maste     slot = R_ARM_JUMP_SLOT;
198f034231aSEd Maste     break;
1990cac4ca3SEd Maste   case EM_HEXAGON:
2000cac4ca3SEd Maste     slot = R_HEX_JMP_SLOT;
2010cac4ca3SEd Maste     break;
2020cac4ca3SEd Maste   case EM_AARCH64:
2030cac4ca3SEd Maste     slot = R_AARCH64_JUMP_SLOT;
2040cac4ca3SEd Maste     break;
205205afe67SEd Maste   case EM_MIPS:
206205afe67SEd Maste     slot = R_MIPS_JUMP_SLOT;
207205afe67SEd Maste     break;
208f3fbd1c0SDimitry Andric   case EM_S390:
209f3fbd1c0SDimitry Andric     slot = R_390_JMP_SLOT;
210f3fbd1c0SDimitry Andric     break;
211145449b1SDimitry Andric   case EM_RISCV:
212145449b1SDimitry Andric     slot = R_RISCV_JUMP_SLOT;
213145449b1SDimitry Andric     break;
214e3b55780SDimitry Andric   case EM_LOONGARCH:
215e3b55780SDimitry Andric     slot = R_LARCH_JUMP_SLOT;
216e3b55780SDimitry Andric     break;
217f034231aSEd Maste   }
218f034231aSEd Maste 
219f034231aSEd Maste   return slot;
220f034231aSEd Maste }
221f034231aSEd Maste 
222f034231aSEd Maste // ELFSectionHeader
223f034231aSEd Maste 
ELFSectionHeader()22414f1b3e8SDimitry Andric ELFSectionHeader::ELFSectionHeader() {
225f034231aSEd Maste   memset(this, 0, sizeof(ELFSectionHeader));
226f034231aSEd Maste }
227f034231aSEd Maste 
Parse(const lldb_private::DataExtractor & data,lldb::offset_t * offset)22814f1b3e8SDimitry Andric bool ELFSectionHeader::Parse(const lldb_private::DataExtractor &data,
22914f1b3e8SDimitry Andric                              lldb::offset_t *offset) {
230f034231aSEd Maste   const unsigned byte_size = data.GetAddressByteSize();
231f034231aSEd Maste 
232f034231aSEd Maste   // Read sh_name and sh_type.
2335f29bb8aSDimitry Andric   if (data.GetU32(offset, &sh_name, 2) == nullptr)
234f034231aSEd Maste     return false;
235f034231aSEd Maste 
236f034231aSEd Maste   // Read sh_flags.
23794994d37SDimitry Andric   if (!GetMaxU64(data, offset, &sh_flags, byte_size))
238f034231aSEd Maste     return false;
239f034231aSEd Maste 
240f034231aSEd Maste   // Read sh_addr, sh_off and sh_size.
24194994d37SDimitry Andric   if (!GetMaxU64(data, offset, &sh_addr, byte_size, 3))
242f034231aSEd Maste     return false;
243f034231aSEd Maste 
244f034231aSEd Maste   // Read sh_link and sh_info.
2455f29bb8aSDimitry Andric   if (data.GetU32(offset, &sh_link, 2) == nullptr)
246f034231aSEd Maste     return false;
247f034231aSEd Maste 
248f034231aSEd Maste   // Read sh_addralign and sh_entsize.
24994994d37SDimitry Andric   if (!GetMaxU64(data, offset, &sh_addralign, byte_size, 2))
250f034231aSEd Maste     return false;
251f034231aSEd Maste 
252f034231aSEd Maste   return true;
253f034231aSEd Maste }
254f034231aSEd Maste 
255f034231aSEd Maste // ELFSymbol
256f034231aSEd Maste 
ELFSymbol()25714f1b3e8SDimitry Andric ELFSymbol::ELFSymbol() { memset(this, 0, sizeof(ELFSymbol)); }
258f034231aSEd Maste 
25914f1b3e8SDimitry Andric #define ENUM_TO_CSTR(e)                                                        \
26014f1b3e8SDimitry Andric   case e:                                                                      \
26114f1b3e8SDimitry Andric     return #e
262f034231aSEd Maste 
bindingToCString(unsigned char binding)26314f1b3e8SDimitry Andric const char *ELFSymbol::bindingToCString(unsigned char binding) {
26414f1b3e8SDimitry Andric   switch (binding) {
265f034231aSEd Maste     ENUM_TO_CSTR(STB_LOCAL);
266f034231aSEd Maste     ENUM_TO_CSTR(STB_GLOBAL);
267f034231aSEd Maste     ENUM_TO_CSTR(STB_WEAK);
268f034231aSEd Maste     ENUM_TO_CSTR(STB_LOOS);
269f034231aSEd Maste     ENUM_TO_CSTR(STB_HIOS);
270f034231aSEd Maste     ENUM_TO_CSTR(STB_LOPROC);
271f034231aSEd Maste     ENUM_TO_CSTR(STB_HIPROC);
272f034231aSEd Maste   }
273f034231aSEd Maste   return "";
274f034231aSEd Maste }
275f034231aSEd Maste 
typeToCString(unsigned char type)27614f1b3e8SDimitry Andric const char *ELFSymbol::typeToCString(unsigned char type) {
27714f1b3e8SDimitry Andric   switch (type) {
278f034231aSEd Maste     ENUM_TO_CSTR(STT_NOTYPE);
279f034231aSEd Maste     ENUM_TO_CSTR(STT_OBJECT);
280f034231aSEd Maste     ENUM_TO_CSTR(STT_FUNC);
281f034231aSEd Maste     ENUM_TO_CSTR(STT_SECTION);
282f034231aSEd Maste     ENUM_TO_CSTR(STT_FILE);
283f034231aSEd Maste     ENUM_TO_CSTR(STT_COMMON);
284f034231aSEd Maste     ENUM_TO_CSTR(STT_TLS);
285f034231aSEd Maste     ENUM_TO_CSTR(STT_GNU_IFUNC);
2865e95aa85SEd Maste     ENUM_TO_CSTR(STT_HIOS);
287f034231aSEd Maste     ENUM_TO_CSTR(STT_LOPROC);
288f034231aSEd Maste     ENUM_TO_CSTR(STT_HIPROC);
289f034231aSEd Maste   }
290f034231aSEd Maste   return "";
291f034231aSEd Maste }
292f034231aSEd Maste 
sectionIndexToCString(elf_half shndx,const lldb_private::SectionList * section_list)29314f1b3e8SDimitry Andric const char *ELFSymbol::sectionIndexToCString(
29414f1b3e8SDimitry Andric     elf_half shndx, const lldb_private::SectionList *section_list) {
29514f1b3e8SDimitry Andric   switch (shndx) {
296f034231aSEd Maste     ENUM_TO_CSTR(SHN_UNDEF);
297f034231aSEd Maste     ENUM_TO_CSTR(SHN_LOPROC);
298f034231aSEd Maste     ENUM_TO_CSTR(SHN_HIPROC);
299f034231aSEd Maste     ENUM_TO_CSTR(SHN_LOOS);
300f034231aSEd Maste     ENUM_TO_CSTR(SHN_HIOS);
301f034231aSEd Maste     ENUM_TO_CSTR(SHN_ABS);
302f034231aSEd Maste     ENUM_TO_CSTR(SHN_COMMON);
303f034231aSEd Maste     ENUM_TO_CSTR(SHN_XINDEX);
30414f1b3e8SDimitry Andric   default: {
30514f1b3e8SDimitry Andric     const lldb_private::Section *section =
30614f1b3e8SDimitry Andric         section_list->GetSectionAtIndex(shndx).get();
307f034231aSEd Maste     if (section)
308f034231aSEd Maste       return section->GetName().AsCString("");
30914f1b3e8SDimitry Andric   } break;
310f034231aSEd Maste   }
311f034231aSEd Maste   return "";
312f034231aSEd Maste }
313f034231aSEd Maste 
Dump(lldb_private::Stream * s,uint32_t idx,const lldb_private::DataExtractor * strtab_data,const lldb_private::SectionList * section_list)31414f1b3e8SDimitry Andric void ELFSymbol::Dump(lldb_private::Stream *s, uint32_t idx,
315f034231aSEd Maste                      const lldb_private::DataExtractor *strtab_data,
31614f1b3e8SDimitry Andric                      const lldb_private::SectionList *section_list) {
31714f1b3e8SDimitry Andric   s->Printf("[%3u] 0x%16.16" PRIx64 " 0x%16.16" PRIx64
31814f1b3e8SDimitry Andric             " 0x%8.8x 0x%2.2x (%-10s %-13s) 0x%2.2x 0x%4.4x (%-10s) %s\n",
31914f1b3e8SDimitry Andric             idx, st_value, st_size, st_name, st_info,
32014f1b3e8SDimitry Andric             bindingToCString(getBinding()), typeToCString(getType()), st_other,
32114f1b3e8SDimitry Andric             st_shndx, sectionIndexToCString(st_shndx, section_list),
322f034231aSEd Maste             strtab_data ? strtab_data->PeekCStr(st_name) : "");
323f034231aSEd Maste }
324f034231aSEd Maste 
Parse(const lldb_private::DataExtractor & data,lldb::offset_t * offset)32514f1b3e8SDimitry Andric bool ELFSymbol::Parse(const lldb_private::DataExtractor &data,
32614f1b3e8SDimitry Andric                       lldb::offset_t *offset) {
327f034231aSEd Maste   const unsigned byte_size = data.GetAddressByteSize();
328f034231aSEd Maste   const bool parsing_32 = byte_size == 4;
329f034231aSEd Maste 
330f034231aSEd Maste   // Read st_name.
3315f29bb8aSDimitry Andric   if (data.GetU32(offset, &st_name, 1) == nullptr)
332f034231aSEd Maste     return false;
333f034231aSEd Maste 
33414f1b3e8SDimitry Andric   if (parsing_32) {
335f034231aSEd Maste     // Read st_value and st_size.
33694994d37SDimitry Andric     if (!GetMaxU64(data, offset, &st_value, byte_size, 2))
337f034231aSEd Maste       return false;
338f034231aSEd Maste 
339f034231aSEd Maste     // Read st_info and st_other.
3405f29bb8aSDimitry Andric     if (data.GetU8(offset, &st_info, 2) == nullptr)
341f034231aSEd Maste       return false;
342f034231aSEd Maste 
343f034231aSEd Maste     // Read st_shndx.
3445f29bb8aSDimitry Andric     if (data.GetU16(offset, &st_shndx, 1) == nullptr)
345f034231aSEd Maste       return false;
34614f1b3e8SDimitry Andric   } else {
347f034231aSEd Maste     // Read st_info and st_other.
3485f29bb8aSDimitry Andric     if (data.GetU8(offset, &st_info, 2) == nullptr)
349f034231aSEd Maste       return false;
350f034231aSEd Maste 
351f034231aSEd Maste     // Read st_shndx.
3525f29bb8aSDimitry Andric     if (data.GetU16(offset, &st_shndx, 1) == nullptr)
353f034231aSEd Maste       return false;
354f034231aSEd Maste 
355f034231aSEd Maste     // Read st_value and st_size.
3565f29bb8aSDimitry Andric     if (data.GetU64(offset, &st_value, 2) == nullptr)
357f034231aSEd Maste       return false;
358f034231aSEd Maste   }
359f034231aSEd Maste   return true;
360f034231aSEd Maste }
361f034231aSEd Maste 
362f034231aSEd Maste // ELFProgramHeader
363f034231aSEd Maste 
ELFProgramHeader()36414f1b3e8SDimitry Andric ELFProgramHeader::ELFProgramHeader() {
365f034231aSEd Maste   memset(this, 0, sizeof(ELFProgramHeader));
366f034231aSEd Maste }
367f034231aSEd Maste 
Parse(const lldb_private::DataExtractor & data,lldb::offset_t * offset)36814f1b3e8SDimitry Andric bool ELFProgramHeader::Parse(const lldb_private::DataExtractor &data,
36914f1b3e8SDimitry Andric                              lldb::offset_t *offset) {
370f034231aSEd Maste   const uint32_t byte_size = data.GetAddressByteSize();
371f034231aSEd Maste   const bool parsing_32 = byte_size == 4;
372f034231aSEd Maste 
373f034231aSEd Maste   // Read p_type;
3745f29bb8aSDimitry Andric   if (data.GetU32(offset, &p_type, 1) == nullptr)
375f034231aSEd Maste     return false;
376f034231aSEd Maste 
377f034231aSEd Maste   if (parsing_32) {
378f034231aSEd Maste     // Read p_offset, p_vaddr, p_paddr, p_filesz and p_memsz.
37994994d37SDimitry Andric     if (!GetMaxU64(data, offset, &p_offset, byte_size, 5))
380f034231aSEd Maste       return false;
381f034231aSEd Maste 
382f034231aSEd Maste     // Read p_flags.
3835f29bb8aSDimitry Andric     if (data.GetU32(offset, &p_flags, 1) == nullptr)
384f034231aSEd Maste       return false;
385f034231aSEd Maste 
386f034231aSEd Maste     // Read p_align.
38794994d37SDimitry Andric     if (!GetMaxU64(data, offset, &p_align, byte_size))
388f034231aSEd Maste       return false;
38914f1b3e8SDimitry Andric   } else {
390f034231aSEd Maste     // Read p_flags.
3915f29bb8aSDimitry Andric     if (data.GetU32(offset, &p_flags, 1) == nullptr)
392f034231aSEd Maste       return false;
393f034231aSEd Maste 
394f034231aSEd Maste     // Read p_offset, p_vaddr, p_paddr, p_filesz, p_memsz and p_align.
39594994d37SDimitry Andric     if (!GetMaxU64(data, offset, &p_offset, byte_size, 6))
396f034231aSEd Maste       return false;
397f034231aSEd Maste   }
398f034231aSEd Maste 
399f034231aSEd Maste   return true;
400f034231aSEd Maste }
401f034231aSEd Maste 
402f034231aSEd Maste // ELFDynamic
403f034231aSEd Maste 
ELFDynamic()40414f1b3e8SDimitry Andric ELFDynamic::ELFDynamic() { memset(this, 0, sizeof(ELFDynamic)); }
405f034231aSEd Maste 
Parse(const lldb_private::DataExtractor & data,lldb::offset_t * offset)40614f1b3e8SDimitry Andric bool ELFDynamic::Parse(const lldb_private::DataExtractor &data,
40714f1b3e8SDimitry Andric                        lldb::offset_t *offset) {
408f034231aSEd Maste   const unsigned byte_size = data.GetAddressByteSize();
409f034231aSEd Maste   return GetMaxS64(data, offset, &d_tag, byte_size, 2);
410f034231aSEd Maste }
411f034231aSEd Maste 
412f034231aSEd Maste // ELFRel
413f034231aSEd Maste 
ELFRel()41414f1b3e8SDimitry Andric ELFRel::ELFRel() { memset(this, 0, sizeof(ELFRel)); }
415f034231aSEd Maste 
Parse(const lldb_private::DataExtractor & data,lldb::offset_t * offset)41614f1b3e8SDimitry Andric bool ELFRel::Parse(const lldb_private::DataExtractor &data,
41714f1b3e8SDimitry Andric                    lldb::offset_t *offset) {
418f034231aSEd Maste   const unsigned byte_size = data.GetAddressByteSize();
419f034231aSEd Maste 
420f034231aSEd Maste   // Read r_offset and r_info.
42194994d37SDimitry Andric   return GetMaxU64(data, offset, &r_offset, byte_size, 2) != false;
422f034231aSEd Maste }
423f034231aSEd Maste 
424f034231aSEd Maste // ELFRela
425f034231aSEd Maste 
ELFRela()42614f1b3e8SDimitry Andric ELFRela::ELFRela() { memset(this, 0, sizeof(ELFRela)); }
427f034231aSEd Maste 
Parse(const lldb_private::DataExtractor & data,lldb::offset_t * offset)42814f1b3e8SDimitry Andric bool ELFRela::Parse(const lldb_private::DataExtractor &data,
42914f1b3e8SDimitry Andric                     lldb::offset_t *offset) {
430f034231aSEd Maste   const unsigned byte_size = data.GetAddressByteSize();
431f034231aSEd Maste 
432f034231aSEd Maste   // Read r_offset and r_info.
43394994d37SDimitry Andric   if (!GetMaxU64(data, offset, &r_offset, byte_size, 2))
434f034231aSEd Maste     return false;
435f034231aSEd Maste 
436f034231aSEd Maste   // Read r_addend;
43794994d37SDimitry Andric   if (!GetMaxS64(data, offset, &r_addend, byte_size))
438f034231aSEd Maste     return false;
439f034231aSEd Maste 
440f034231aSEd Maste   return true;
441f034231aSEd Maste }
442