1 //===-- ELFHeader.cpp -----------------------------------------------------===// 2 // 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 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include <cstring> 10 11 #include "lldb/Core/Section.h" 12 #include "lldb/Utility/DataExtractor.h" 13 #include "lldb/Utility/Stream.h" 14 15 #include "ELFHeader.h" 16 17 using namespace elf; 18 using namespace lldb; 19 using namespace llvm::ELF; 20 21 // Static utility functions. 22 // 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, 27 uint32_t byte_size) { 28 const lldb::offset_t saved_offset = *offset; 29 *value = data.GetMaxU64(offset, byte_size); 30 return *offset != saved_offset; 31 } 32 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; 37 38 for (uint32_t i = 0; i < count; ++i, ++value) { 39 if (!GetMaxU64(data, offset, value, byte_size)) { 40 *offset = saved_offset; 41 return false; 42 } 43 } 44 return true; 45 } 46 47 static bool GetMaxS64(const lldb_private::DataExtractor &data, 48 lldb::offset_t *offset, int64_t *value, 49 uint32_t byte_size) { 50 const lldb::offset_t saved_offset = *offset; 51 *value = data.GetMaxS64(offset, byte_size); 52 return *offset != saved_offset; 53 } 54 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; 59 60 for (uint32_t i = 0; i < count; ++i, ++value) { 61 if (!GetMaxS64(data, offset, value, byte_size)) { 62 *offset = saved_offset; 63 return false; 64 } 65 } 66 return true; 67 } 68 69 // ELFHeader 70 71 ELFHeader::ELFHeader() { memset(this, 0, sizeof(ELFHeader)); } 72 73 ByteOrder ELFHeader::GetByteOrder() const { 74 if (e_ident[EI_DATA] == ELFDATA2MSB) 75 return eByteOrderBig; 76 if (e_ident[EI_DATA] == ELFDATA2LSB) 77 return eByteOrderLittle; 78 return eByteOrderInvalid; 79 } 80 81 bool ELFHeader::HasHeaderExtension() const { 82 bool result = false; 83 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; 88 89 // If header extension is present, the section offset cannot be null. 90 result &= e_shoff != 0; 91 92 // Done. 93 return result; 94 } 95 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); 102 103 // If we succeeded, fix the header. 104 if (ok) { 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; 111 } 112 } 113 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) 118 return false; 119 120 const unsigned byte_size = Is32Bit() ? 4 : 8; 121 data.SetByteOrder(GetByteOrder()); 122 data.SetAddressByteSize(byte_size); 123 124 // Read e_type and e_machine. 125 if (data.GetU16(offset, &e_type, 2) == nullptr) 126 return false; 127 128 // Read e_version. 129 if (data.GetU32(offset, &e_version, 1) == nullptr) 130 return false; 131 132 // Read e_entry, e_phoff and e_shoff. 133 if (!GetMaxU64(data, offset, &e_entry, byte_size, 3)) 134 return false; 135 136 // Read e_flags. 137 if (data.GetU32(offset, &e_flags, 1) == nullptr) 138 return false; 139 140 // Read e_ehsize, e_phentsize, e_phnum, e_shentsize, e_shnum and e_shstrndx. 141 if (data.GetU16(offset, &e_ehsize, 6) == nullptr) 142 return false; 143 144 // Initialize e_phnum, e_shnum, and e_shstrndx with the values read from the 145 // header. 146 e_phnum = e_phnum_hdr; 147 e_shnum = e_shnum_hdr; 148 e_shstrndx = e_shstrndx_hdr; 149 150 // See if we have extended header in section #0. 151 if (HasHeaderExtension()) 152 ParseHeaderExtension(data); 153 154 return true; 155 } 156 157 bool ELFHeader::MagicBytesMatch(const uint8_t *magic) { 158 return memcmp(magic, ElfMagic, strlen(ElfMagic)) == 0; 159 } 160 161 unsigned ELFHeader::AddressSizeInBytes(const uint8_t *magic) { 162 unsigned address_size = 0; 163 164 switch (magic[EI_CLASS]) { 165 case ELFCLASS32: 166 address_size = 4; 167 break; 168 169 case ELFCLASS64: 170 address_size = 8; 171 break; 172 } 173 return address_size; 174 } 175 176 unsigned ELFHeader::GetRelocationJumpSlotType() const { 177 unsigned slot = 0; 178 179 switch (e_machine) { 180 default: 181 assert(false && "architecture not supported"); 182 break; 183 case EM_PPC: 184 slot = R_PPC_JMP_SLOT; 185 break; 186 case EM_PPC64: 187 slot = R_PPC64_JMP_SLOT; 188 break; 189 case EM_386: 190 case EM_IAMCU: // FIXME: is this correct? 191 slot = R_386_JUMP_SLOT; 192 break; 193 case EM_X86_64: 194 slot = R_X86_64_JUMP_SLOT; 195 break; 196 case EM_ARM: 197 slot = R_ARM_JUMP_SLOT; 198 break; 199 case EM_HEXAGON: 200 slot = R_HEX_JMP_SLOT; 201 break; 202 case EM_AARCH64: 203 slot = R_AARCH64_JUMP_SLOT; 204 break; 205 case EM_MIPS: 206 slot = R_MIPS_JUMP_SLOT; 207 break; 208 case EM_S390: 209 slot = R_390_JMP_SLOT; 210 break; 211 case EM_RISCV: 212 slot = R_RISCV_JUMP_SLOT; 213 break; 214 case EM_LOONGARCH: 215 slot = R_LARCH_JUMP_SLOT; 216 break; 217 } 218 219 return slot; 220 } 221 222 // ELFSectionHeader 223 224 ELFSectionHeader::ELFSectionHeader() { 225 memset(this, 0, sizeof(ELFSectionHeader)); 226 } 227 228 bool ELFSectionHeader::Parse(const lldb_private::DataExtractor &data, 229 lldb::offset_t *offset) { 230 const unsigned byte_size = data.GetAddressByteSize(); 231 232 // Read sh_name and sh_type. 233 if (data.GetU32(offset, &sh_name, 2) == nullptr) 234 return false; 235 236 // Read sh_flags. 237 if (!GetMaxU64(data, offset, &sh_flags, byte_size)) 238 return false; 239 240 // Read sh_addr, sh_off and sh_size. 241 if (!GetMaxU64(data, offset, &sh_addr, byte_size, 3)) 242 return false; 243 244 // Read sh_link and sh_info. 245 if (data.GetU32(offset, &sh_link, 2) == nullptr) 246 return false; 247 248 // Read sh_addralign and sh_entsize. 249 if (!GetMaxU64(data, offset, &sh_addralign, byte_size, 2)) 250 return false; 251 252 return true; 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) == nullptr) 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)) 337 return false; 338 339 // Read st_info and st_other. 340 if (data.GetU8(offset, &st_info, 2) == nullptr) 341 return false; 342 343 // Read st_shndx. 344 if (data.GetU16(offset, &st_shndx, 1) == nullptr) 345 return false; 346 } else { 347 // Read st_info and st_other. 348 if (data.GetU8(offset, &st_info, 2) == nullptr) 349 return false; 350 351 // Read st_shndx. 352 if (data.GetU16(offset, &st_shndx, 1) == nullptr) 353 return false; 354 355 // Read st_value and st_size. 356 if (data.GetU64(offset, &st_value, 2) == nullptr) 357 return false; 358 } 359 return true; 360 } 361 362 // ELFProgramHeader 363 364 ELFProgramHeader::ELFProgramHeader() { 365 memset(this, 0, sizeof(ELFProgramHeader)); 366 } 367 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; 372 373 // Read p_type; 374 if (data.GetU32(offset, &p_type, 1) == nullptr) 375 return false; 376 377 if (parsing_32) { 378 // Read p_offset, p_vaddr, p_paddr, p_filesz and p_memsz. 379 if (!GetMaxU64(data, offset, &p_offset, byte_size, 5)) 380 return false; 381 382 // Read p_flags. 383 if (data.GetU32(offset, &p_flags, 1) == nullptr) 384 return false; 385 386 // Read p_align. 387 if (!GetMaxU64(data, offset, &p_align, byte_size)) 388 return false; 389 } else { 390 // Read p_flags. 391 if (data.GetU32(offset, &p_flags, 1) == nullptr) 392 return false; 393 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)) 396 return false; 397 } 398 399 return true; 400 } 401 402 // ELFDynamic 403 404 ELFDynamic::ELFDynamic() { memset(this, 0, sizeof(ELFDynamic)); } 405 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); 410 } 411 412 // ELFRel 413 414 ELFRel::ELFRel() { memset(this, 0, sizeof(ELFRel)); } 415 416 bool ELFRel::Parse(const lldb_private::DataExtractor &data, 417 lldb::offset_t *offset) { 418 const unsigned byte_size = data.GetAddressByteSize(); 419 420 // Read r_offset and r_info. 421 return GetMaxU64(data, offset, &r_offset, byte_size, 2) != false; 422 } 423 424 // ELFRela 425 426 ELFRela::ELFRela() { memset(this, 0, sizeof(ELFRela)); } 427 428 bool ELFRela::Parse(const lldb_private::DataExtractor &data, 429 lldb::offset_t *offset) { 430 const unsigned byte_size = data.GetAddressByteSize(); 431 432 // Read r_offset and r_info. 433 if (!GetMaxU64(data, offset, &r_offset, byte_size, 2)) 434 return false; 435 436 // Read r_addend; 437 if (!GetMaxS64(data, offset, &r_addend, byte_size)) 438 return false; 439 440 return true; 441 } 442