1 //===-- ELFHeader.cpp ----------------------------------------- -*- C++ -*-===// 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 //------------------------------------------------------------------------------ 22 // Static utility functions. 23 // 24 // GetMaxU64 and GetMaxS64 wrap the similarly named methods from DataExtractor 25 // with error handling code and provide for parsing a sequence of values. 26 static bool GetMaxU64(const lldb_private::DataExtractor &data, 27 lldb::offset_t *offset, uint64_t *value, 28 uint32_t byte_size) { 29 const lldb::offset_t saved_offset = *offset; 30 *value = data.GetMaxU64(offset, byte_size); 31 return *offset != saved_offset; 32 } 33 34 static bool GetMaxU64(const lldb_private::DataExtractor &data, 35 lldb::offset_t *offset, uint64_t *value, 36 uint32_t byte_size, uint32_t count) { 37 lldb::offset_t saved_offset = *offset; 38 39 for (uint32_t i = 0; i < count; ++i, ++value) { 40 if (!GetMaxU64(data, offset, value, byte_size)) { 41 *offset = saved_offset; 42 return false; 43 } 44 } 45 return true; 46 } 47 48 static bool GetMaxS64(const lldb_private::DataExtractor &data, 49 lldb::offset_t *offset, int64_t *value, 50 uint32_t byte_size) { 51 const lldb::offset_t saved_offset = *offset; 52 *value = data.GetMaxS64(offset, byte_size); 53 return *offset != saved_offset; 54 } 55 56 static bool GetMaxS64(const lldb_private::DataExtractor &data, 57 lldb::offset_t *offset, int64_t *value, 58 uint32_t byte_size, uint32_t count) { 59 lldb::offset_t saved_offset = *offset; 60 61 for (uint32_t i = 0; i < count; ++i, ++value) { 62 if (!GetMaxS64(data, offset, value, byte_size)) { 63 *offset = saved_offset; 64 return false; 65 } 66 } 67 return true; 68 } 69 70 //------------------------------------------------------------------------------ 71 // ELFHeader 72 73 ELFHeader::ELFHeader() { memset(this, 0, sizeof(ELFHeader)); } 74 75 ByteOrder ELFHeader::GetByteOrder() const { 76 if (e_ident[EI_DATA] == ELFDATA2MSB) 77 return eByteOrderBig; 78 if (e_ident[EI_DATA] == ELFDATA2LSB) 79 return eByteOrderLittle; 80 return eByteOrderInvalid; 81 } 82 83 bool ELFHeader::HasHeaderExtension() const { 84 bool result = false; 85 86 // Check if any of these values looks like sentinel. 87 result |= e_phnum_hdr == 0xFFFF; // PN_XNUM 88 result |= e_shnum_hdr == SHN_UNDEF; 89 result |= e_shstrndx_hdr == SHN_XINDEX; 90 91 // If header extension is present, the section offset cannot be null. 92 result &= e_shoff != 0; 93 94 // Done. 95 return result; 96 } 97 98 void ELFHeader::ParseHeaderExtension(lldb_private::DataExtractor &data) { 99 // Extract section #0 header. 100 ELFSectionHeader section_zero; 101 lldb::offset_t offset = 0; 102 lldb_private::DataExtractor sh_data(data, e_shoff, e_shentsize); 103 bool ok = section_zero.Parse(sh_data, &offset); 104 105 // If we succeeded, fix the header. 106 if (ok) { 107 if (e_phnum_hdr == 0xFFFF) // PN_XNUM 108 e_phnum = section_zero.sh_info; 109 if (e_shnum_hdr == SHN_UNDEF) 110 e_shnum = section_zero.sh_size; 111 if (e_shstrndx_hdr == SHN_XINDEX) 112 e_shstrndx = section_zero.sh_link; 113 } 114 } 115 116 bool ELFHeader::Parse(lldb_private::DataExtractor &data, 117 lldb::offset_t *offset) { 118 // Read e_ident. This provides byte order and address size info. 119 if (data.GetU8(offset, &e_ident, EI_NIDENT) == NULL) 120 return false; 121 122 const unsigned byte_size = Is32Bit() ? 4 : 8; 123 data.SetByteOrder(GetByteOrder()); 124 data.SetAddressByteSize(byte_size); 125 126 // Read e_type and e_machine. 127 if (data.GetU16(offset, &e_type, 2) == NULL) 128 return false; 129 130 // Read e_version. 131 if (data.GetU32(offset, &e_version, 1) == NULL) 132 return false; 133 134 // Read e_entry, e_phoff and e_shoff. 135 if (!GetMaxU64(data, offset, &e_entry, byte_size, 3)) 136 return false; 137 138 // Read e_flags. 139 if (data.GetU32(offset, &e_flags, 1) == NULL) 140 return false; 141 142 // Read e_ehsize, e_phentsize, e_phnum, e_shentsize, e_shnum and e_shstrndx. 143 if (data.GetU16(offset, &e_ehsize, 6) == NULL) 144 return false; 145 146 // Initialize e_phnum, e_shnum, and e_shstrndx with the values read from the 147 // header. 148 e_phnum = e_phnum_hdr; 149 e_shnum = e_shnum_hdr; 150 e_shstrndx = e_shstrndx_hdr; 151 152 // See if we have extended header in section #0. 153 if (HasHeaderExtension()) 154 ParseHeaderExtension(data); 155 156 return true; 157 } 158 159 bool ELFHeader::MagicBytesMatch(const uint8_t *magic) { 160 return memcmp(magic, ElfMagic, strlen(ElfMagic)) == 0; 161 } 162 163 unsigned ELFHeader::AddressSizeInBytes(const uint8_t *magic) { 164 unsigned address_size = 0; 165 166 switch (magic[EI_CLASS]) { 167 case ELFCLASS32: 168 address_size = 4; 169 break; 170 171 case ELFCLASS64: 172 address_size = 8; 173 break; 174 } 175 return address_size; 176 } 177 178 unsigned ELFHeader::GetRelocationJumpSlotType() const { 179 unsigned slot = 0; 180 181 switch (e_machine) { 182 default: 183 assert(false && "architecture not supported"); 184 break; 185 case EM_PPC: 186 slot = R_PPC_JMP_SLOT; 187 break; 188 case EM_PPC64: 189 slot = R_PPC64_JMP_SLOT; 190 break; 191 case EM_386: 192 case EM_IAMCU: // FIXME: is this correct? 193 slot = R_386_JUMP_SLOT; 194 break; 195 case EM_X86_64: 196 slot = R_X86_64_JUMP_SLOT; 197 break; 198 case EM_ARM: 199 slot = R_ARM_JUMP_SLOT; 200 break; 201 case EM_HEXAGON: 202 slot = R_HEX_JMP_SLOT; 203 break; 204 case EM_AARCH64: 205 slot = R_AARCH64_JUMP_SLOT; 206 break; 207 case EM_MIPS: 208 slot = R_MIPS_JUMP_SLOT; 209 break; 210 case EM_S390: 211 slot = R_390_JMP_SLOT; 212 break; 213 } 214 215 return slot; 216 } 217 218 //------------------------------------------------------------------------------ 219 // ELFSectionHeader 220 221 ELFSectionHeader::ELFSectionHeader() { 222 memset(this, 0, sizeof(ELFSectionHeader)); 223 } 224 225 bool ELFSectionHeader::Parse(const lldb_private::DataExtractor &data, 226 lldb::offset_t *offset) { 227 const unsigned byte_size = data.GetAddressByteSize(); 228 229 // Read sh_name and sh_type. 230 if (data.GetU32(offset, &sh_name, 2) == NULL) 231 return false; 232 233 // Read sh_flags. 234 if (!GetMaxU64(data, offset, &sh_flags, byte_size)) 235 return false; 236 237 // Read sh_addr, sh_off and sh_size. 238 if (!GetMaxU64(data, offset, &sh_addr, byte_size, 3)) 239 return false; 240 241 // Read sh_link and sh_info. 242 if (data.GetU32(offset, &sh_link, 2) == NULL) 243 return false; 244 245 // Read sh_addralign and sh_entsize. 246 if (!GetMaxU64(data, offset, &sh_addralign, byte_size, 2)) 247 return false; 248 249 return true; 250 } 251 252 //------------------------------------------------------------------------------ 253 // ELFSymbol 254 255 ELFSymbol::ELFSymbol() { memset(this, 0, sizeof(ELFSymbol)); } 256 257 #define ENUM_TO_CSTR(e) \ 258 case e: \ 259 return #e 260 261 const char *ELFSymbol::bindingToCString(unsigned char binding) { 262 switch (binding) { 263 ENUM_TO_CSTR(STB_LOCAL); 264 ENUM_TO_CSTR(STB_GLOBAL); 265 ENUM_TO_CSTR(STB_WEAK); 266 ENUM_TO_CSTR(STB_LOOS); 267 ENUM_TO_CSTR(STB_HIOS); 268 ENUM_TO_CSTR(STB_LOPROC); 269 ENUM_TO_CSTR(STB_HIPROC); 270 } 271 return ""; 272 } 273 274 const char *ELFSymbol::typeToCString(unsigned char type) { 275 switch (type) { 276 ENUM_TO_CSTR(STT_NOTYPE); 277 ENUM_TO_CSTR(STT_OBJECT); 278 ENUM_TO_CSTR(STT_FUNC); 279 ENUM_TO_CSTR(STT_SECTION); 280 ENUM_TO_CSTR(STT_FILE); 281 ENUM_TO_CSTR(STT_COMMON); 282 ENUM_TO_CSTR(STT_TLS); 283 ENUM_TO_CSTR(STT_GNU_IFUNC); 284 ENUM_TO_CSTR(STT_HIOS); 285 ENUM_TO_CSTR(STT_LOPROC); 286 ENUM_TO_CSTR(STT_HIPROC); 287 } 288 return ""; 289 } 290 291 const char *ELFSymbol::sectionIndexToCString( 292 elf_half shndx, const lldb_private::SectionList *section_list) { 293 switch (shndx) { 294 ENUM_TO_CSTR(SHN_UNDEF); 295 ENUM_TO_CSTR(SHN_LOPROC); 296 ENUM_TO_CSTR(SHN_HIPROC); 297 ENUM_TO_CSTR(SHN_LOOS); 298 ENUM_TO_CSTR(SHN_HIOS); 299 ENUM_TO_CSTR(SHN_ABS); 300 ENUM_TO_CSTR(SHN_COMMON); 301 ENUM_TO_CSTR(SHN_XINDEX); 302 default: { 303 const lldb_private::Section *section = 304 section_list->GetSectionAtIndex(shndx).get(); 305 if (section) 306 return section->GetName().AsCString(""); 307 } break; 308 } 309 return ""; 310 } 311 312 void ELFSymbol::Dump(lldb_private::Stream *s, uint32_t idx, 313 const lldb_private::DataExtractor *strtab_data, 314 const lldb_private::SectionList *section_list) { 315 s->Printf("[%3u] 0x%16.16" PRIx64 " 0x%16.16" PRIx64 316 " 0x%8.8x 0x%2.2x (%-10s %-13s) 0x%2.2x 0x%4.4x (%-10s) %s\n", 317 idx, st_value, st_size, st_name, st_info, 318 bindingToCString(getBinding()), typeToCString(getType()), st_other, 319 st_shndx, sectionIndexToCString(st_shndx, section_list), 320 strtab_data ? strtab_data->PeekCStr(st_name) : ""); 321 } 322 323 bool ELFSymbol::Parse(const lldb_private::DataExtractor &data, 324 lldb::offset_t *offset) { 325 const unsigned byte_size = data.GetAddressByteSize(); 326 const bool parsing_32 = byte_size == 4; 327 328 // Read st_name. 329 if (data.GetU32(offset, &st_name, 1) == NULL) 330 return false; 331 332 if (parsing_32) { 333 // Read st_value and st_size. 334 if (!GetMaxU64(data, offset, &st_value, byte_size, 2)) 335 return false; 336 337 // Read st_info and st_other. 338 if (data.GetU8(offset, &st_info, 2) == NULL) 339 return false; 340 341 // Read st_shndx. 342 if (data.GetU16(offset, &st_shndx, 1) == NULL) 343 return false; 344 } else { 345 // Read st_info and st_other. 346 if (data.GetU8(offset, &st_info, 2) == NULL) 347 return false; 348 349 // Read st_shndx. 350 if (data.GetU16(offset, &st_shndx, 1) == NULL) 351 return false; 352 353 // Read st_value and st_size. 354 if (data.GetU64(offset, &st_value, 2) == NULL) 355 return false; 356 } 357 return true; 358 } 359 360 //------------------------------------------------------------------------------ 361 // ELFProgramHeader 362 363 ELFProgramHeader::ELFProgramHeader() { 364 memset(this, 0, sizeof(ELFProgramHeader)); 365 } 366 367 bool ELFProgramHeader::Parse(const lldb_private::DataExtractor &data, 368 lldb::offset_t *offset) { 369 const uint32_t byte_size = data.GetAddressByteSize(); 370 const bool parsing_32 = byte_size == 4; 371 372 // Read p_type; 373 if (data.GetU32(offset, &p_type, 1) == NULL) 374 return false; 375 376 if (parsing_32) { 377 // Read p_offset, p_vaddr, p_paddr, p_filesz and p_memsz. 378 if (!GetMaxU64(data, offset, &p_offset, byte_size, 5)) 379 return false; 380 381 // Read p_flags. 382 if (data.GetU32(offset, &p_flags, 1) == NULL) 383 return false; 384 385 // Read p_align. 386 if (!GetMaxU64(data, offset, &p_align, byte_size)) 387 return false; 388 } else { 389 // Read p_flags. 390 if (data.GetU32(offset, &p_flags, 1) == NULL) 391 return false; 392 393 // Read p_offset, p_vaddr, p_paddr, p_filesz, p_memsz and p_align. 394 if (!GetMaxU64(data, offset, &p_offset, byte_size, 6)) 395 return false; 396 } 397 398 return true; 399 } 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 //------------------------------------------------------------------------------ 413 // ELFRel 414 415 ELFRel::ELFRel() { memset(this, 0, sizeof(ELFRel)); } 416 417 bool ELFRel::Parse(const lldb_private::DataExtractor &data, 418 lldb::offset_t *offset) { 419 const unsigned byte_size = data.GetAddressByteSize(); 420 421 // Read r_offset and r_info. 422 return GetMaxU64(data, offset, &r_offset, byte_size, 2) != false; 423 } 424 425 //------------------------------------------------------------------------------ 426 // ELFRela 427 428 ELFRela::ELFRela() { memset(this, 0, sizeof(ELFRela)); } 429 430 bool ELFRela::Parse(const lldb_private::DataExtractor &data, 431 lldb::offset_t *offset) { 432 const unsigned byte_size = data.GetAddressByteSize(); 433 434 // Read r_offset and r_info. 435 if (!GetMaxU64(data, offset, &r_offset, byte_size, 2)) 436 return false; 437 438 // Read r_addend; 439 if (!GetMaxS64(data, offset, &r_addend, byte_size)) 440 return false; 441 442 return true; 443 } 444