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