15ffd83dbSDimitry Andric //===-- ELFHeader.cpp -----------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric
90b57cec5SDimitry Andric #include <cstring>
100b57cec5SDimitry Andric
110b57cec5SDimitry Andric #include "lldb/Core/Section.h"
120b57cec5SDimitry Andric #include "lldb/Utility/DataExtractor.h"
130b57cec5SDimitry Andric #include "lldb/Utility/Stream.h"
140b57cec5SDimitry Andric
150b57cec5SDimitry Andric #include "ELFHeader.h"
160b57cec5SDimitry Andric
170b57cec5SDimitry Andric using namespace elf;
180b57cec5SDimitry Andric using namespace lldb;
190b57cec5SDimitry Andric using namespace llvm::ELF;
200b57cec5SDimitry Andric
210b57cec5SDimitry Andric // Static utility functions.
220b57cec5SDimitry Andric //
230b57cec5SDimitry Andric // GetMaxU64 and GetMaxS64 wrap the similarly named methods from DataExtractor
240b57cec5SDimitry Andric // 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)250b57cec5SDimitry Andric static bool GetMaxU64(const lldb_private::DataExtractor &data,
260b57cec5SDimitry Andric lldb::offset_t *offset, uint64_t *value,
270b57cec5SDimitry Andric uint32_t byte_size) {
280b57cec5SDimitry Andric const lldb::offset_t saved_offset = *offset;
290b57cec5SDimitry Andric *value = data.GetMaxU64(offset, byte_size);
300b57cec5SDimitry Andric return *offset != saved_offset;
310b57cec5SDimitry Andric }
320b57cec5SDimitry Andric
GetMaxU64(const lldb_private::DataExtractor & data,lldb::offset_t * offset,uint64_t * value,uint32_t byte_size,uint32_t count)330b57cec5SDimitry Andric static bool GetMaxU64(const lldb_private::DataExtractor &data,
340b57cec5SDimitry Andric lldb::offset_t *offset, uint64_t *value,
350b57cec5SDimitry Andric uint32_t byte_size, uint32_t count) {
360b57cec5SDimitry Andric lldb::offset_t saved_offset = *offset;
370b57cec5SDimitry Andric
380b57cec5SDimitry Andric for (uint32_t i = 0; i < count; ++i, ++value) {
390b57cec5SDimitry Andric if (!GetMaxU64(data, offset, value, byte_size)) {
400b57cec5SDimitry Andric *offset = saved_offset;
410b57cec5SDimitry Andric return false;
420b57cec5SDimitry Andric }
430b57cec5SDimitry Andric }
440b57cec5SDimitry Andric return true;
450b57cec5SDimitry Andric }
460b57cec5SDimitry Andric
GetMaxS64(const lldb_private::DataExtractor & data,lldb::offset_t * offset,int64_t * value,uint32_t byte_size)470b57cec5SDimitry Andric static bool GetMaxS64(const lldb_private::DataExtractor &data,
480b57cec5SDimitry Andric lldb::offset_t *offset, int64_t *value,
490b57cec5SDimitry Andric uint32_t byte_size) {
500b57cec5SDimitry Andric const lldb::offset_t saved_offset = *offset;
510b57cec5SDimitry Andric *value = data.GetMaxS64(offset, byte_size);
520b57cec5SDimitry Andric return *offset != saved_offset;
530b57cec5SDimitry Andric }
540b57cec5SDimitry Andric
GetMaxS64(const lldb_private::DataExtractor & data,lldb::offset_t * offset,int64_t * value,uint32_t byte_size,uint32_t count)550b57cec5SDimitry Andric static bool GetMaxS64(const lldb_private::DataExtractor &data,
560b57cec5SDimitry Andric lldb::offset_t *offset, int64_t *value,
570b57cec5SDimitry Andric uint32_t byte_size, uint32_t count) {
580b57cec5SDimitry Andric lldb::offset_t saved_offset = *offset;
590b57cec5SDimitry Andric
600b57cec5SDimitry Andric for (uint32_t i = 0; i < count; ++i, ++value) {
610b57cec5SDimitry Andric if (!GetMaxS64(data, offset, value, byte_size)) {
620b57cec5SDimitry Andric *offset = saved_offset;
630b57cec5SDimitry Andric return false;
640b57cec5SDimitry Andric }
650b57cec5SDimitry Andric }
660b57cec5SDimitry Andric return true;
670b57cec5SDimitry Andric }
680b57cec5SDimitry Andric
690b57cec5SDimitry Andric // ELFHeader
700b57cec5SDimitry Andric
ELFHeader()710b57cec5SDimitry Andric ELFHeader::ELFHeader() { memset(this, 0, sizeof(ELFHeader)); }
720b57cec5SDimitry Andric
GetByteOrder() const730b57cec5SDimitry Andric ByteOrder ELFHeader::GetByteOrder() const {
740b57cec5SDimitry Andric if (e_ident[EI_DATA] == ELFDATA2MSB)
750b57cec5SDimitry Andric return eByteOrderBig;
760b57cec5SDimitry Andric if (e_ident[EI_DATA] == ELFDATA2LSB)
770b57cec5SDimitry Andric return eByteOrderLittle;
780b57cec5SDimitry Andric return eByteOrderInvalid;
790b57cec5SDimitry Andric }
800b57cec5SDimitry Andric
HasHeaderExtension() const810b57cec5SDimitry Andric bool ELFHeader::HasHeaderExtension() const {
820b57cec5SDimitry Andric bool result = false;
830b57cec5SDimitry Andric
840b57cec5SDimitry Andric // Check if any of these values looks like sentinel.
850b57cec5SDimitry Andric result |= e_phnum_hdr == 0xFFFF; // PN_XNUM
860b57cec5SDimitry Andric result |= e_shnum_hdr == SHN_UNDEF;
870b57cec5SDimitry Andric result |= e_shstrndx_hdr == SHN_XINDEX;
880b57cec5SDimitry Andric
890b57cec5SDimitry Andric // If header extension is present, the section offset cannot be null.
900b57cec5SDimitry Andric result &= e_shoff != 0;
910b57cec5SDimitry Andric
920b57cec5SDimitry Andric // Done.
930b57cec5SDimitry Andric return result;
940b57cec5SDimitry Andric }
950b57cec5SDimitry Andric
ParseHeaderExtension(lldb_private::DataExtractor & data)960b57cec5SDimitry Andric void ELFHeader::ParseHeaderExtension(lldb_private::DataExtractor &data) {
970b57cec5SDimitry Andric // Extract section #0 header.
980b57cec5SDimitry Andric ELFSectionHeader section_zero;
990b57cec5SDimitry Andric lldb::offset_t offset = 0;
1000b57cec5SDimitry Andric lldb_private::DataExtractor sh_data(data, e_shoff, e_shentsize);
1010b57cec5SDimitry Andric bool ok = section_zero.Parse(sh_data, &offset);
1020b57cec5SDimitry Andric
1030b57cec5SDimitry Andric // If we succeeded, fix the header.
1040b57cec5SDimitry Andric if (ok) {
1050b57cec5SDimitry Andric if (e_phnum_hdr == 0xFFFF) // PN_XNUM
1060b57cec5SDimitry Andric e_phnum = section_zero.sh_info;
1070b57cec5SDimitry Andric if (e_shnum_hdr == SHN_UNDEF)
1080b57cec5SDimitry Andric e_shnum = section_zero.sh_size;
1090b57cec5SDimitry Andric if (e_shstrndx_hdr == SHN_XINDEX)
1100b57cec5SDimitry Andric e_shstrndx = section_zero.sh_link;
1110b57cec5SDimitry Andric }
1120b57cec5SDimitry Andric }
1130b57cec5SDimitry Andric
Parse(lldb_private::DataExtractor & data,lldb::offset_t * offset)1140b57cec5SDimitry Andric bool ELFHeader::Parse(lldb_private::DataExtractor &data,
1150b57cec5SDimitry Andric lldb::offset_t *offset) {
1160b57cec5SDimitry Andric // Read e_ident. This provides byte order and address size info.
1170b57cec5SDimitry Andric if (data.GetU8(offset, &e_ident, EI_NIDENT) == nullptr)
1180b57cec5SDimitry Andric return false;
1190b57cec5SDimitry Andric
1200b57cec5SDimitry Andric const unsigned byte_size = Is32Bit() ? 4 : 8;
1210b57cec5SDimitry Andric data.SetByteOrder(GetByteOrder());
1220b57cec5SDimitry Andric data.SetAddressByteSize(byte_size);
1230b57cec5SDimitry Andric
1240b57cec5SDimitry Andric // Read e_type and e_machine.
1250b57cec5SDimitry Andric if (data.GetU16(offset, &e_type, 2) == nullptr)
1260b57cec5SDimitry Andric return false;
1270b57cec5SDimitry Andric
1280b57cec5SDimitry Andric // Read e_version.
1290b57cec5SDimitry Andric if (data.GetU32(offset, &e_version, 1) == nullptr)
1300b57cec5SDimitry Andric return false;
1310b57cec5SDimitry Andric
1320b57cec5SDimitry Andric // Read e_entry, e_phoff and e_shoff.
1330b57cec5SDimitry Andric if (!GetMaxU64(data, offset, &e_entry, byte_size, 3))
1340b57cec5SDimitry Andric return false;
1350b57cec5SDimitry Andric
1360b57cec5SDimitry Andric // Read e_flags.
1370b57cec5SDimitry Andric if (data.GetU32(offset, &e_flags, 1) == nullptr)
1380b57cec5SDimitry Andric return false;
1390b57cec5SDimitry Andric
1400b57cec5SDimitry Andric // Read e_ehsize, e_phentsize, e_phnum, e_shentsize, e_shnum and e_shstrndx.
1410b57cec5SDimitry Andric if (data.GetU16(offset, &e_ehsize, 6) == nullptr)
1420b57cec5SDimitry Andric return false;
1430b57cec5SDimitry Andric
1440b57cec5SDimitry Andric // Initialize e_phnum, e_shnum, and e_shstrndx with the values read from the
1450b57cec5SDimitry Andric // header.
1460b57cec5SDimitry Andric e_phnum = e_phnum_hdr;
1470b57cec5SDimitry Andric e_shnum = e_shnum_hdr;
1480b57cec5SDimitry Andric e_shstrndx = e_shstrndx_hdr;
1490b57cec5SDimitry Andric
1500b57cec5SDimitry Andric // See if we have extended header in section #0.
1510b57cec5SDimitry Andric if (HasHeaderExtension())
1520b57cec5SDimitry Andric ParseHeaderExtension(data);
1530b57cec5SDimitry Andric
1540b57cec5SDimitry Andric return true;
1550b57cec5SDimitry Andric }
1560b57cec5SDimitry Andric
MagicBytesMatch(const uint8_t * magic)1570b57cec5SDimitry Andric bool ELFHeader::MagicBytesMatch(const uint8_t *magic) {
1580b57cec5SDimitry Andric return memcmp(magic, ElfMagic, strlen(ElfMagic)) == 0;
1590b57cec5SDimitry Andric }
1600b57cec5SDimitry Andric
AddressSizeInBytes(const uint8_t * magic)1610b57cec5SDimitry Andric unsigned ELFHeader::AddressSizeInBytes(const uint8_t *magic) {
1620b57cec5SDimitry Andric unsigned address_size = 0;
1630b57cec5SDimitry Andric
1640b57cec5SDimitry Andric switch (magic[EI_CLASS]) {
1650b57cec5SDimitry Andric case ELFCLASS32:
1660b57cec5SDimitry Andric address_size = 4;
1670b57cec5SDimitry Andric break;
1680b57cec5SDimitry Andric
1690b57cec5SDimitry Andric case ELFCLASS64:
1700b57cec5SDimitry Andric address_size = 8;
1710b57cec5SDimitry Andric break;
1720b57cec5SDimitry Andric }
1730b57cec5SDimitry Andric return address_size;
1740b57cec5SDimitry Andric }
1750b57cec5SDimitry Andric
GetRelocationJumpSlotType() const1760b57cec5SDimitry Andric unsigned ELFHeader::GetRelocationJumpSlotType() const {
1770b57cec5SDimitry Andric unsigned slot = 0;
1780b57cec5SDimitry Andric
1790b57cec5SDimitry Andric switch (e_machine) {
1800b57cec5SDimitry Andric default:
1810b57cec5SDimitry Andric assert(false && "architecture not supported");
1820b57cec5SDimitry Andric break;
1830b57cec5SDimitry Andric case EM_PPC:
1840b57cec5SDimitry Andric slot = R_PPC_JMP_SLOT;
1850b57cec5SDimitry Andric break;
1860b57cec5SDimitry Andric case EM_PPC64:
1870b57cec5SDimitry Andric slot = R_PPC64_JMP_SLOT;
1880b57cec5SDimitry Andric break;
1890b57cec5SDimitry Andric case EM_386:
1900b57cec5SDimitry Andric case EM_IAMCU: // FIXME: is this correct?
1910b57cec5SDimitry Andric slot = R_386_JUMP_SLOT;
1920b57cec5SDimitry Andric break;
1930b57cec5SDimitry Andric case EM_X86_64:
1940b57cec5SDimitry Andric slot = R_X86_64_JUMP_SLOT;
1950b57cec5SDimitry Andric break;
1960b57cec5SDimitry Andric case EM_ARM:
1970b57cec5SDimitry Andric slot = R_ARM_JUMP_SLOT;
1980b57cec5SDimitry Andric break;
1990b57cec5SDimitry Andric case EM_HEXAGON:
2000b57cec5SDimitry Andric slot = R_HEX_JMP_SLOT;
2010b57cec5SDimitry Andric break;
2020b57cec5SDimitry Andric case EM_AARCH64:
2030b57cec5SDimitry Andric slot = R_AARCH64_JUMP_SLOT;
2040b57cec5SDimitry Andric break;
2050b57cec5SDimitry Andric case EM_MIPS:
2060b57cec5SDimitry Andric slot = R_MIPS_JUMP_SLOT;
2070b57cec5SDimitry Andric break;
2080b57cec5SDimitry Andric case EM_S390:
2090b57cec5SDimitry Andric slot = R_390_JMP_SLOT;
2100b57cec5SDimitry Andric break;
21181ad6265SDimitry Andric case EM_RISCV:
21281ad6265SDimitry Andric slot = R_RISCV_JUMP_SLOT;
21381ad6265SDimitry Andric break;
214*bdd1243dSDimitry Andric case EM_LOONGARCH:
215*bdd1243dSDimitry Andric slot = R_LARCH_JUMP_SLOT;
216*bdd1243dSDimitry Andric break;
2170b57cec5SDimitry Andric }
2180b57cec5SDimitry Andric
2190b57cec5SDimitry Andric return slot;
2200b57cec5SDimitry Andric }
2210b57cec5SDimitry Andric
2220b57cec5SDimitry Andric // ELFSectionHeader
2230b57cec5SDimitry Andric
ELFSectionHeader()2240b57cec5SDimitry Andric ELFSectionHeader::ELFSectionHeader() {
2250b57cec5SDimitry Andric memset(this, 0, sizeof(ELFSectionHeader));
2260b57cec5SDimitry Andric }
2270b57cec5SDimitry Andric
Parse(const lldb_private::DataExtractor & data,lldb::offset_t * offset)2280b57cec5SDimitry Andric bool ELFSectionHeader::Parse(const lldb_private::DataExtractor &data,
2290b57cec5SDimitry Andric lldb::offset_t *offset) {
2300b57cec5SDimitry Andric const unsigned byte_size = data.GetAddressByteSize();
2310b57cec5SDimitry Andric
2320b57cec5SDimitry Andric // Read sh_name and sh_type.
2330b57cec5SDimitry Andric if (data.GetU32(offset, &sh_name, 2) == nullptr)
2340b57cec5SDimitry Andric return false;
2350b57cec5SDimitry Andric
2360b57cec5SDimitry Andric // Read sh_flags.
2370b57cec5SDimitry Andric if (!GetMaxU64(data, offset, &sh_flags, byte_size))
2380b57cec5SDimitry Andric return false;
2390b57cec5SDimitry Andric
2400b57cec5SDimitry Andric // Read sh_addr, sh_off and sh_size.
2410b57cec5SDimitry Andric if (!GetMaxU64(data, offset, &sh_addr, byte_size, 3))
2420b57cec5SDimitry Andric return false;
2430b57cec5SDimitry Andric
2440b57cec5SDimitry Andric // Read sh_link and sh_info.
2450b57cec5SDimitry Andric if (data.GetU32(offset, &sh_link, 2) == nullptr)
2460b57cec5SDimitry Andric return false;
2470b57cec5SDimitry Andric
2480b57cec5SDimitry Andric // Read sh_addralign and sh_entsize.
2490b57cec5SDimitry Andric if (!GetMaxU64(data, offset, &sh_addralign, byte_size, 2))
2500b57cec5SDimitry Andric return false;
2510b57cec5SDimitry Andric
2520b57cec5SDimitry Andric return true;
2530b57cec5SDimitry Andric }
2540b57cec5SDimitry Andric
2550b57cec5SDimitry Andric // ELFSymbol
2560b57cec5SDimitry Andric
ELFSymbol()2570b57cec5SDimitry Andric ELFSymbol::ELFSymbol() { memset(this, 0, sizeof(ELFSymbol)); }
2580b57cec5SDimitry Andric
2590b57cec5SDimitry Andric #define ENUM_TO_CSTR(e) \
2600b57cec5SDimitry Andric case e: \
2610b57cec5SDimitry Andric return #e
2620b57cec5SDimitry Andric
bindingToCString(unsigned char binding)2630b57cec5SDimitry Andric const char *ELFSymbol::bindingToCString(unsigned char binding) {
2640b57cec5SDimitry Andric switch (binding) {
2650b57cec5SDimitry Andric ENUM_TO_CSTR(STB_LOCAL);
2660b57cec5SDimitry Andric ENUM_TO_CSTR(STB_GLOBAL);
2670b57cec5SDimitry Andric ENUM_TO_CSTR(STB_WEAK);
2680b57cec5SDimitry Andric ENUM_TO_CSTR(STB_LOOS);
2690b57cec5SDimitry Andric ENUM_TO_CSTR(STB_HIOS);
2700b57cec5SDimitry Andric ENUM_TO_CSTR(STB_LOPROC);
2710b57cec5SDimitry Andric ENUM_TO_CSTR(STB_HIPROC);
2720b57cec5SDimitry Andric }
2730b57cec5SDimitry Andric return "";
2740b57cec5SDimitry Andric }
2750b57cec5SDimitry Andric
typeToCString(unsigned char type)2760b57cec5SDimitry Andric const char *ELFSymbol::typeToCString(unsigned char type) {
2770b57cec5SDimitry Andric switch (type) {
2780b57cec5SDimitry Andric ENUM_TO_CSTR(STT_NOTYPE);
2790b57cec5SDimitry Andric ENUM_TO_CSTR(STT_OBJECT);
2800b57cec5SDimitry Andric ENUM_TO_CSTR(STT_FUNC);
2810b57cec5SDimitry Andric ENUM_TO_CSTR(STT_SECTION);
2820b57cec5SDimitry Andric ENUM_TO_CSTR(STT_FILE);
2830b57cec5SDimitry Andric ENUM_TO_CSTR(STT_COMMON);
2840b57cec5SDimitry Andric ENUM_TO_CSTR(STT_TLS);
2850b57cec5SDimitry Andric ENUM_TO_CSTR(STT_GNU_IFUNC);
2860b57cec5SDimitry Andric ENUM_TO_CSTR(STT_HIOS);
2870b57cec5SDimitry Andric ENUM_TO_CSTR(STT_LOPROC);
2880b57cec5SDimitry Andric ENUM_TO_CSTR(STT_HIPROC);
2890b57cec5SDimitry Andric }
2900b57cec5SDimitry Andric return "";
2910b57cec5SDimitry Andric }
2920b57cec5SDimitry Andric
sectionIndexToCString(elf_half shndx,const lldb_private::SectionList * section_list)2930b57cec5SDimitry Andric const char *ELFSymbol::sectionIndexToCString(
2940b57cec5SDimitry Andric elf_half shndx, const lldb_private::SectionList *section_list) {
2950b57cec5SDimitry Andric switch (shndx) {
2960b57cec5SDimitry Andric ENUM_TO_CSTR(SHN_UNDEF);
2970b57cec5SDimitry Andric ENUM_TO_CSTR(SHN_LOPROC);
2980b57cec5SDimitry Andric ENUM_TO_CSTR(SHN_HIPROC);
2990b57cec5SDimitry Andric ENUM_TO_CSTR(SHN_LOOS);
3000b57cec5SDimitry Andric ENUM_TO_CSTR(SHN_HIOS);
3010b57cec5SDimitry Andric ENUM_TO_CSTR(SHN_ABS);
3020b57cec5SDimitry Andric ENUM_TO_CSTR(SHN_COMMON);
3030b57cec5SDimitry Andric ENUM_TO_CSTR(SHN_XINDEX);
3040b57cec5SDimitry Andric default: {
3050b57cec5SDimitry Andric const lldb_private::Section *section =
3060b57cec5SDimitry Andric section_list->GetSectionAtIndex(shndx).get();
3070b57cec5SDimitry Andric if (section)
3080b57cec5SDimitry Andric return section->GetName().AsCString("");
3090b57cec5SDimitry Andric } break;
3100b57cec5SDimitry Andric }
3110b57cec5SDimitry Andric return "";
3120b57cec5SDimitry Andric }
3130b57cec5SDimitry Andric
Dump(lldb_private::Stream * s,uint32_t idx,const lldb_private::DataExtractor * strtab_data,const lldb_private::SectionList * section_list)3140b57cec5SDimitry Andric void ELFSymbol::Dump(lldb_private::Stream *s, uint32_t idx,
3150b57cec5SDimitry Andric const lldb_private::DataExtractor *strtab_data,
3160b57cec5SDimitry Andric const lldb_private::SectionList *section_list) {
3170b57cec5SDimitry Andric s->Printf("[%3u] 0x%16.16" PRIx64 " 0x%16.16" PRIx64
3180b57cec5SDimitry Andric " 0x%8.8x 0x%2.2x (%-10s %-13s) 0x%2.2x 0x%4.4x (%-10s) %s\n",
3190b57cec5SDimitry Andric idx, st_value, st_size, st_name, st_info,
3200b57cec5SDimitry Andric bindingToCString(getBinding()), typeToCString(getType()), st_other,
3210b57cec5SDimitry Andric st_shndx, sectionIndexToCString(st_shndx, section_list),
3220b57cec5SDimitry Andric strtab_data ? strtab_data->PeekCStr(st_name) : "");
3230b57cec5SDimitry Andric }
3240b57cec5SDimitry Andric
Parse(const lldb_private::DataExtractor & data,lldb::offset_t * offset)3250b57cec5SDimitry Andric bool ELFSymbol::Parse(const lldb_private::DataExtractor &data,
3260b57cec5SDimitry Andric lldb::offset_t *offset) {
3270b57cec5SDimitry Andric const unsigned byte_size = data.GetAddressByteSize();
3280b57cec5SDimitry Andric const bool parsing_32 = byte_size == 4;
3290b57cec5SDimitry Andric
3300b57cec5SDimitry Andric // Read st_name.
3310b57cec5SDimitry Andric if (data.GetU32(offset, &st_name, 1) == nullptr)
3320b57cec5SDimitry Andric return false;
3330b57cec5SDimitry Andric
3340b57cec5SDimitry Andric if (parsing_32) {
3350b57cec5SDimitry Andric // Read st_value and st_size.
3360b57cec5SDimitry Andric if (!GetMaxU64(data, offset, &st_value, byte_size, 2))
3370b57cec5SDimitry Andric return false;
3380b57cec5SDimitry Andric
3390b57cec5SDimitry Andric // Read st_info and st_other.
3400b57cec5SDimitry Andric if (data.GetU8(offset, &st_info, 2) == nullptr)
3410b57cec5SDimitry Andric return false;
3420b57cec5SDimitry Andric
3430b57cec5SDimitry Andric // Read st_shndx.
3440b57cec5SDimitry Andric if (data.GetU16(offset, &st_shndx, 1) == nullptr)
3450b57cec5SDimitry Andric return false;
3460b57cec5SDimitry Andric } else {
3470b57cec5SDimitry Andric // Read st_info and st_other.
3480b57cec5SDimitry Andric if (data.GetU8(offset, &st_info, 2) == nullptr)
3490b57cec5SDimitry Andric return false;
3500b57cec5SDimitry Andric
3510b57cec5SDimitry Andric // Read st_shndx.
3520b57cec5SDimitry Andric if (data.GetU16(offset, &st_shndx, 1) == nullptr)
3530b57cec5SDimitry Andric return false;
3540b57cec5SDimitry Andric
3550b57cec5SDimitry Andric // Read st_value and st_size.
3560b57cec5SDimitry Andric if (data.GetU64(offset, &st_value, 2) == nullptr)
3570b57cec5SDimitry Andric return false;
3580b57cec5SDimitry Andric }
3590b57cec5SDimitry Andric return true;
3600b57cec5SDimitry Andric }
3610b57cec5SDimitry Andric
3620b57cec5SDimitry Andric // ELFProgramHeader
3630b57cec5SDimitry Andric
ELFProgramHeader()3640b57cec5SDimitry Andric ELFProgramHeader::ELFProgramHeader() {
3650b57cec5SDimitry Andric memset(this, 0, sizeof(ELFProgramHeader));
3660b57cec5SDimitry Andric }
3670b57cec5SDimitry Andric
Parse(const lldb_private::DataExtractor & data,lldb::offset_t * offset)3680b57cec5SDimitry Andric bool ELFProgramHeader::Parse(const lldb_private::DataExtractor &data,
3690b57cec5SDimitry Andric lldb::offset_t *offset) {
3700b57cec5SDimitry Andric const uint32_t byte_size = data.GetAddressByteSize();
3710b57cec5SDimitry Andric const bool parsing_32 = byte_size == 4;
3720b57cec5SDimitry Andric
3730b57cec5SDimitry Andric // Read p_type;
3740b57cec5SDimitry Andric if (data.GetU32(offset, &p_type, 1) == nullptr)
3750b57cec5SDimitry Andric return false;
3760b57cec5SDimitry Andric
3770b57cec5SDimitry Andric if (parsing_32) {
3780b57cec5SDimitry Andric // Read p_offset, p_vaddr, p_paddr, p_filesz and p_memsz.
3790b57cec5SDimitry Andric if (!GetMaxU64(data, offset, &p_offset, byte_size, 5))
3800b57cec5SDimitry Andric return false;
3810b57cec5SDimitry Andric
3820b57cec5SDimitry Andric // Read p_flags.
3830b57cec5SDimitry Andric if (data.GetU32(offset, &p_flags, 1) == nullptr)
3840b57cec5SDimitry Andric return false;
3850b57cec5SDimitry Andric
3860b57cec5SDimitry Andric // Read p_align.
3870b57cec5SDimitry Andric if (!GetMaxU64(data, offset, &p_align, byte_size))
3880b57cec5SDimitry Andric return false;
3890b57cec5SDimitry Andric } else {
3900b57cec5SDimitry Andric // Read p_flags.
3910b57cec5SDimitry Andric if (data.GetU32(offset, &p_flags, 1) == nullptr)
3920b57cec5SDimitry Andric return false;
3930b57cec5SDimitry Andric
3940b57cec5SDimitry Andric // Read p_offset, p_vaddr, p_paddr, p_filesz, p_memsz and p_align.
3950b57cec5SDimitry Andric if (!GetMaxU64(data, offset, &p_offset, byte_size, 6))
3960b57cec5SDimitry Andric return false;
3970b57cec5SDimitry Andric }
3980b57cec5SDimitry Andric
3990b57cec5SDimitry Andric return true;
4000b57cec5SDimitry Andric }
4010b57cec5SDimitry Andric
4020b57cec5SDimitry Andric // ELFDynamic
4030b57cec5SDimitry Andric
ELFDynamic()4040b57cec5SDimitry Andric ELFDynamic::ELFDynamic() { memset(this, 0, sizeof(ELFDynamic)); }
4050b57cec5SDimitry Andric
Parse(const lldb_private::DataExtractor & data,lldb::offset_t * offset)4060b57cec5SDimitry Andric bool ELFDynamic::Parse(const lldb_private::DataExtractor &data,
4070b57cec5SDimitry Andric lldb::offset_t *offset) {
4080b57cec5SDimitry Andric const unsigned byte_size = data.GetAddressByteSize();
4090b57cec5SDimitry Andric return GetMaxS64(data, offset, &d_tag, byte_size, 2);
4100b57cec5SDimitry Andric }
4110b57cec5SDimitry Andric
4120b57cec5SDimitry Andric // ELFRel
4130b57cec5SDimitry Andric
ELFRel()4140b57cec5SDimitry Andric ELFRel::ELFRel() { memset(this, 0, sizeof(ELFRel)); }
4150b57cec5SDimitry Andric
Parse(const lldb_private::DataExtractor & data,lldb::offset_t * offset)4160b57cec5SDimitry Andric bool ELFRel::Parse(const lldb_private::DataExtractor &data,
4170b57cec5SDimitry Andric lldb::offset_t *offset) {
4180b57cec5SDimitry Andric const unsigned byte_size = data.GetAddressByteSize();
4190b57cec5SDimitry Andric
4200b57cec5SDimitry Andric // Read r_offset and r_info.
4210b57cec5SDimitry Andric return GetMaxU64(data, offset, &r_offset, byte_size, 2) != false;
4220b57cec5SDimitry Andric }
4230b57cec5SDimitry Andric
4240b57cec5SDimitry Andric // ELFRela
4250b57cec5SDimitry Andric
ELFRela()4260b57cec5SDimitry Andric ELFRela::ELFRela() { memset(this, 0, sizeof(ELFRela)); }
4270b57cec5SDimitry Andric
Parse(const lldb_private::DataExtractor & data,lldb::offset_t * offset)4280b57cec5SDimitry Andric bool ELFRela::Parse(const lldb_private::DataExtractor &data,
4290b57cec5SDimitry Andric lldb::offset_t *offset) {
4300b57cec5SDimitry Andric const unsigned byte_size = data.GetAddressByteSize();
4310b57cec5SDimitry Andric
4320b57cec5SDimitry Andric // Read r_offset and r_info.
4330b57cec5SDimitry Andric if (!GetMaxU64(data, offset, &r_offset, byte_size, 2))
4340b57cec5SDimitry Andric return false;
4350b57cec5SDimitry Andric
4360b57cec5SDimitry Andric // Read r_addend;
4370b57cec5SDimitry Andric if (!GetMaxS64(data, offset, &r_addend, byte_size))
4380b57cec5SDimitry Andric return false;
4390b57cec5SDimitry Andric
4400b57cec5SDimitry Andric return true;
4410b57cec5SDimitry Andric }
442