1 //===-- ELFHeader.cpp -----------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
11 #include "lldb/Core/Section.h"
12 #include "lldb/Utility/DataExtractor.h"
13 #include "lldb/Utility/Stream.h"
15 #include "ELFHeader.h"
19 using namespace llvm::ELF
;
21 // Static utility functions.
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
,
28 const lldb::offset_t saved_offset
= *offset
;
29 *value
= data
.GetMaxU64(offset
, byte_size
);
30 return *offset
!= saved_offset
;
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
;
38 for (uint32_t i
= 0; i
< count
; ++i
, ++value
) {
39 if (!GetMaxU64(data
, offset
, value
, byte_size
)) {
40 *offset
= saved_offset
;
47 static bool GetMaxS64(const lldb_private::DataExtractor
&data
,
48 lldb::offset_t
*offset
, int64_t *value
,
50 const lldb::offset_t saved_offset
= *offset
;
51 *value
= data
.GetMaxS64(offset
, byte_size
);
52 return *offset
!= saved_offset
;
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
;
60 for (uint32_t i
= 0; i
< count
; ++i
, ++value
) {
61 if (!GetMaxS64(data
, offset
, value
, byte_size
)) {
62 *offset
= saved_offset
;
71 ELFHeader::ELFHeader() { memset(this, 0, sizeof(ELFHeader
)); }
73 ByteOrder
ELFHeader::GetByteOrder() const {
74 if (e_ident
[EI_DATA
] == ELFDATA2MSB
)
76 if (e_ident
[EI_DATA
] == ELFDATA2LSB
)
77 return eByteOrderLittle
;
78 return eByteOrderInvalid
;
81 bool ELFHeader::HasHeaderExtension() const {
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
;
89 // If header extension is present, the section offset cannot be null.
90 result
&= e_shoff
!= 0;
96 void ELFHeader::ParseHeaderExtension(lldb_private::DataExtractor
&data
) {
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
);
103 // If we succeeded, fix the header.
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
;
114 bool ELFHeader::Parse(lldb_private::DataExtractor
&data
,
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)
120 const unsigned byte_size
= Is32Bit() ? 4 : 8;
121 data
.SetByteOrder(GetByteOrder());
122 data
.SetAddressByteSize(byte_size
);
124 // Read e_type and e_machine.
125 if (data
.GetU16(offset
, &e_type
, 2) == nullptr)
129 if (data
.GetU32(offset
, &e_version
, 1) == nullptr)
132 // Read e_entry, e_phoff and e_shoff.
133 if (!GetMaxU64(data
, offset
, &e_entry
, byte_size
, 3))
137 if (data
.GetU32(offset
, &e_flags
, 1) == nullptr)
140 // Read e_ehsize, e_phentsize, e_phnum, e_shentsize, e_shnum and e_shstrndx.
141 if (data
.GetU16(offset
, &e_ehsize
, 6) == nullptr)
144 // Initialize e_phnum, e_shnum, and e_shstrndx with the values read from the
146 e_phnum
= e_phnum_hdr
;
147 e_shnum
= e_shnum_hdr
;
148 e_shstrndx
= e_shstrndx_hdr
;
150 // See if we have extended header in section #0.
151 if (HasHeaderExtension())
152 ParseHeaderExtension(data
);
157 bool ELFHeader::MagicBytesMatch(const uint8_t *magic
) {
158 return memcmp(magic
, ElfMagic
, strlen(ElfMagic
)) == 0;
161 unsigned ELFHeader::AddressSizeInBytes(const uint8_t *magic
) {
162 unsigned address_size
= 0;
164 switch (magic
[EI_CLASS
]) {
176 unsigned ELFHeader::GetRelocationJumpSlotType() const {
181 assert(false && "architecture not supported");
184 slot
= R_PPC_JMP_SLOT
;
187 slot
= R_PPC64_JMP_SLOT
;
190 case EM_IAMCU
: // FIXME: is this correct?
191 slot
= R_386_JUMP_SLOT
;
194 slot
= R_X86_64_JUMP_SLOT
;
197 slot
= R_ARM_JUMP_SLOT
;
200 slot
= R_HEX_JMP_SLOT
;
203 slot
= R_AARCH64_JUMP_SLOT
;
206 slot
= R_MIPS_JUMP_SLOT
;
209 slot
= R_390_JMP_SLOT
;
212 slot
= R_RISCV_JUMP_SLOT
;
215 slot
= R_LARCH_JUMP_SLOT
;
224 ELFSectionHeader::ELFSectionHeader() {
225 memset(this, 0, sizeof(ELFSectionHeader
));
228 bool ELFSectionHeader::Parse(const lldb_private::DataExtractor
&data
,
229 lldb::offset_t
*offset
) {
230 const unsigned byte_size
= data
.GetAddressByteSize();
232 // Read sh_name and sh_type.
233 if (data
.GetU32(offset
, &sh_name
, 2) == nullptr)
237 if (!GetMaxU64(data
, offset
, &sh_flags
, byte_size
))
240 // Read sh_addr, sh_off and sh_size.
241 if (!GetMaxU64(data
, offset
, &sh_addr
, byte_size
, 3))
244 // Read sh_link and sh_info.
245 if (data
.GetU32(offset
, &sh_link
, 2) == nullptr)
248 // Read sh_addralign and sh_entsize.
249 if (!GetMaxU64(data
, offset
, &sh_addralign
, byte_size
, 2))
257 ELFSymbol::ELFSymbol() { memset(this, 0, sizeof(ELFSymbol
)); }
259 #define ENUM_TO_CSTR(e) \
263 const char *ELFSymbol::bindingToCString(unsigned char 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
);
276 const char *ELFSymbol::typeToCString(unsigned char 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
);
293 const char *ELFSymbol::sectionIndexToCString(
294 elf_half shndx
, const lldb_private::SectionList
*section_list
) {
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
);
305 const lldb_private::Section
*section
=
306 section_list
->GetSectionAtIndex(shndx
).get();
308 return section
->GetName().AsCString("");
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
) : "");
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;
331 if (data
.GetU32(offset
, &st_name
, 1) == nullptr)
335 // Read st_value and st_size.
336 if (!GetMaxU64(data
, offset
, &st_value
, byte_size
, 2))
339 // Read st_info and st_other.
340 if (data
.GetU8(offset
, &st_info
, 2) == nullptr)
344 if (data
.GetU16(offset
, &st_shndx
, 1) == nullptr)
347 // Read st_info and st_other.
348 if (data
.GetU8(offset
, &st_info
, 2) == nullptr)
352 if (data
.GetU16(offset
, &st_shndx
, 1) == nullptr)
355 // Read st_value and st_size.
356 if (data
.GetU64(offset
, &st_value
, 2) == nullptr)
364 ELFProgramHeader::ELFProgramHeader() {
365 memset(this, 0, sizeof(ELFProgramHeader
));
368 bool ELFProgramHeader::Parse(const lldb_private::DataExtractor
&data
,
369 lldb::offset_t
*offset
) {
370 const uint32_t byte_size
= data
.GetAddressByteSize();
371 const bool parsing_32
= byte_size
== 4;
374 if (data
.GetU32(offset
, &p_type
, 1) == nullptr)
378 // Read p_offset, p_vaddr, p_paddr, p_filesz and p_memsz.
379 if (!GetMaxU64(data
, offset
, &p_offset
, byte_size
, 5))
383 if (data
.GetU32(offset
, &p_flags
, 1) == nullptr)
387 if (!GetMaxU64(data
, offset
, &p_align
, byte_size
))
391 if (data
.GetU32(offset
, &p_flags
, 1) == nullptr)
394 // Read p_offset, p_vaddr, p_paddr, p_filesz, p_memsz and p_align.
395 if (!GetMaxU64(data
, offset
, &p_offset
, byte_size
, 6))
404 ELFDynamic::ELFDynamic() { memset(this, 0, sizeof(ELFDynamic
)); }
406 bool ELFDynamic::Parse(const lldb_private::DataExtractor
&data
,
407 lldb::offset_t
*offset
) {
408 const unsigned byte_size
= data
.GetAddressByteSize();
409 return GetMaxS64(data
, offset
, &d_tag
, byte_size
, 2);
414 ELFRel::ELFRel() { memset(this, 0, sizeof(ELFRel
)); }
416 bool ELFRel::Parse(const lldb_private::DataExtractor
&data
,
417 lldb::offset_t
*offset
) {
418 const unsigned byte_size
= data
.GetAddressByteSize();
420 // Read r_offset and r_info.
421 return GetMaxU64(data
, offset
, &r_offset
, byte_size
, 2) != false;
426 ELFRela::ELFRela() { memset(this, 0, sizeof(ELFRela
)); }
428 bool ELFRela::Parse(const lldb_private::DataExtractor
&data
,
429 lldb::offset_t
*offset
) {
430 const unsigned byte_size
= data
.GetAddressByteSize();
432 // Read r_offset and r_info.
433 if (!GetMaxU64(data
, offset
, &r_offset
, byte_size
, 2))
437 if (!GetMaxS64(data
, offset
, &r_addend
, byte_size
))