1 //===-- ObjectFileELF.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 "ObjectFileELF.h" 11 12 #include <assert.h> 13 14 #include <algorithm> 15 16 #include <stdint.h> 17 #include "elf.h" 18 #include "lldb/Core/DataBuffer.h" 19 #include "lldb/Core/Error.h" 20 #include "lldb/Core/PluginManager.h" 21 #include "lldb/Core/Section.h" 22 #include "lldb/Core/Stream.h" 23 #include "lldb/Symbol/ObjectFile.h" 24 25 #define CASE_AND_STREAM(s, def, width) case def: s->Printf("%-*s", width, #def); break; 26 27 using namespace lldb; 28 using namespace lldb_private; 29 using namespace std; 30 31 32 void 33 ObjectFileELF::Initialize() 34 { 35 PluginManager::RegisterPlugin (GetPluginNameStatic(), 36 GetPluginDescriptionStatic(), 37 CreateInstance); 38 } 39 40 void 41 ObjectFileELF::Terminate() 42 { 43 PluginManager::UnregisterPlugin (CreateInstance); 44 } 45 46 47 const char * 48 ObjectFileELF::GetPluginNameStatic() 49 { 50 return "object-file.elf32"; 51 } 52 53 const char * 54 ObjectFileELF::GetPluginDescriptionStatic() 55 { 56 return "ELF object file reader (32-bit)."; 57 } 58 59 60 ObjectFile * 61 ObjectFileELF::CreateInstance (Module* module, DataBufferSP& dataSP, const FileSpec* file, addr_t offset, addr_t length) 62 { 63 if (ObjectFileELF::MagicBytesMatch(dataSP)) 64 { 65 std::auto_ptr<ObjectFile> objfile_ap(new ObjectFileELF (module, dataSP, file, offset, length)); 66 if (objfile_ap.get() && objfile_ap->ParseHeader()) 67 return objfile_ap.release(); 68 } 69 return NULL; 70 } 71 72 bool 73 ObjectFileELF::MagicBytesMatch (DataBufferSP& dataSP) 74 { 75 DataExtractor data(dataSP, eByteOrderHost, 4); 76 const uint8_t* magic = data.PeekData(0, 4); 77 if (magic != NULL) 78 { 79 return magic[EI_MAG0] == 0x7f 80 && magic[EI_MAG1] == 'E' 81 && magic[EI_MAG2] == 'L' 82 && magic[EI_MAG3] == 'F'; 83 } 84 return false; 85 } 86 87 88 ObjectFileELF::ObjectFileELF(Module* module, DataBufferSP& dataSP, const FileSpec* file, addr_t offset, addr_t length) : 89 ObjectFile (module, file, offset, length, dataSP), 90 m_header(), 91 m_program_headers(), 92 m_section_headers(), 93 m_sections_ap(), 94 m_symtab_ap(), 95 m_shstr_data() 96 { 97 if (file) 98 m_file = *file; 99 ::bzero (&m_header, sizeof(m_header)); 100 } 101 102 103 ObjectFileELF::~ObjectFileELF() 104 { 105 } 106 107 ByteOrder 108 ObjectFileELF::GetByteOrder () const 109 { 110 if (m_header.e_ident[EI_DATA] == ELFDATA2MSB) 111 return eByteOrderBig; 112 if (m_header.e_ident[EI_DATA] == ELFDATA2LSB) 113 return eByteOrderLittle; 114 return eByteOrderInvalid; 115 } 116 117 size_t 118 ObjectFileELF::GetAddressByteSize () const 119 { 120 return m_data.GetAddressByteSize(); 121 } 122 123 bool 124 ObjectFileELF::ParseHeader () 125 { 126 m_data.SetAddressByteSize(4); 127 uint32_t offset = GetOffset(); 128 if (m_data.GetU8(&offset, m_header.e_ident, EI_NIDENT) == NULL) 129 return false; 130 131 m_data.SetByteOrder(GetByteOrder()); 132 133 // Read e_type and e_machine 134 if (m_data.GetU16(&offset, &m_header.e_type, 2) == NULL) 135 return false; 136 137 // read e_version, e_entry, e_phoff, e_shoff, e_flags 138 if (m_data.GetU32(&offset, &m_header.e_version, 5) == NULL) 139 return false; 140 141 // Read e_ehsize, e_phentsize, e_phnum, e_shentsize, e_shnum, e_shstrndx 142 if (m_data.GetU16(&offset, &m_header.e_ehsize, 6) == NULL) 143 return false; 144 145 return true; 146 } 147 148 bool 149 ObjectFileELF::GetUUID (UUID* uuid) 150 { 151 return false; 152 } 153 154 uint32_t 155 ObjectFileELF::GetDependentModules(FileSpecList& files) 156 { 157 return 0; 158 } 159 160 //---------------------------------------------------------------------- 161 // ParseProgramHeaders 162 //---------------------------------------------------------------------- 163 size_t 164 ObjectFileELF::ParseProgramHeaders() 165 { 166 // We have already parsed the program headers 167 if (!m_program_headers.empty()) 168 return m_program_headers.size(); 169 170 uint32_t offset = 0; 171 if (m_header.e_phnum > 0) 172 { 173 m_program_headers.resize(m_header.e_phnum); 174 175 if (m_program_headers.size() != m_header.e_phnum) 176 return 0; 177 178 const size_t byte_size = m_header.e_phnum * m_header.e_phentsize; 179 DataBufferSP buffer_sp(m_file.ReadFileContents(m_offset + m_header.e_phoff, byte_size)); 180 181 if (buffer_sp.get() == NULL || buffer_sp->GetByteSize() != byte_size) 182 return 0; 183 184 DataExtractor data(buffer_sp, m_data.GetByteOrder(), m_data.GetAddressByteSize()); 185 186 uint32_t idx; 187 for (idx = 0; idx < m_header.e_phnum; ++idx) 188 { 189 if (data.GetU32(&offset, &m_program_headers[idx].p_type, 8) == NULL) 190 return 0; 191 } 192 if (idx < m_program_headers.size()) 193 m_program_headers.resize(idx); 194 } 195 196 return m_program_headers.size(); 197 } 198 199 200 //---------------------------------------------------------------------- 201 // ParseSectionHeaders 202 //---------------------------------------------------------------------- 203 size_t 204 ObjectFileELF::ParseSectionHeaders() 205 { 206 // We have already parsed the section headers 207 if (!m_section_headers.empty()) 208 return m_section_headers.size(); 209 210 if (m_header.e_shnum > 0) 211 { 212 uint32_t offset = 0; 213 214 m_section_headers.resize(m_header.e_shnum); 215 216 if (m_section_headers.size() != m_header.e_shnum) 217 return 0; 218 219 const size_t byte_size = m_header.e_shnum * m_header.e_shentsize; 220 DataBufferSP buffer_sp(m_file.ReadFileContents(m_offset + m_header.e_shoff, byte_size)); 221 222 if (buffer_sp.get() == NULL || buffer_sp->GetByteSize() != byte_size) 223 return 0; 224 225 DataExtractor data(buffer_sp, m_data.GetByteOrder(), m_data.GetAddressByteSize()); 226 227 uint32_t idx; 228 for (idx = 0; idx < m_header.e_shnum; ++idx) 229 { 230 if (data.GetU32(&offset, &m_section_headers[idx].sh_name, 10) == NULL) 231 break; 232 } 233 if (idx < m_section_headers.size()) 234 m_section_headers.resize(idx); 235 } 236 237 return m_section_headers.size(); 238 } 239 240 size_t 241 ObjectFileELF::GetSectionHeaderStringTable() 242 { 243 if (m_shstr_data.GetByteSize() == 0) 244 { 245 if (m_header.e_shstrndx && m_header.e_shstrndx < m_section_headers.size()) 246 { 247 const size_t byte_size = m_section_headers[m_header.e_shstrndx].sh_size; 248 DataBufferSP buffer_sp(m_file.ReadFileContents(m_offset + m_section_headers[m_header.e_shstrndx].sh_offset, byte_size)); 249 250 if (buffer_sp.get() == NULL || buffer_sp->GetByteSize() != byte_size) 251 return 0; 252 253 m_shstr_data.SetData(buffer_sp); 254 } 255 } 256 return m_shstr_data.GetByteSize(); 257 } 258 259 uint32_t 260 ObjectFileELF::GetSectionIndexByName(const char *name) 261 { 262 if (ParseSectionHeaders() && GetSectionHeaderStringTable()) 263 { 264 uint32_t offset = 1; // Skip leading NULL string at offset 0; 265 while (m_shstr_data.ValidOffset(offset)) 266 { 267 uint32_t sh_name = offset; // Save offset in case we find a match 268 const char* sectionHeaderName = m_shstr_data.GetCStr(&offset); 269 if (sectionHeaderName) 270 { 271 if (strcmp(name, sectionHeaderName) == 0) 272 { 273 SectionHeaderCollIter pos; 274 for (pos = m_section_headers.begin(); pos != m_section_headers.end(); ++pos) 275 { 276 if ( (*pos).sh_name == sh_name ) 277 { 278 // section indexes are 1 based 279 return std::distance(m_section_headers.begin(), pos) + 1; 280 } 281 } 282 return UINT32_MAX; 283 } 284 } 285 else 286 { 287 return UINT32_MAX; 288 } 289 } 290 } 291 292 return UINT32_MAX; 293 } 294 295 SectionList * 296 ObjectFileELF::GetSectionList() 297 { 298 if (m_sections_ap.get() == NULL) 299 { 300 m_sections_ap.reset(new SectionList()); 301 if (ParseSectionHeaders() && GetSectionHeaderStringTable()) 302 { 303 uint32_t sh_idx = 0; 304 const size_t num_sections = m_section_headers.size(); 305 for (sh_idx = 0; sh_idx < num_sections; ++sh_idx) 306 { 307 ConstString section_name(m_shstr_data.PeekCStr(m_section_headers[sh_idx].sh_name)); 308 uint64_t section_file_size = m_section_headers[sh_idx].sh_type == SHT_NOBITS ? 0 : m_section_headers[sh_idx].sh_size; 309 SectionSP section_sp(new Section(NULL, // Parent section 310 GetModule(), // Module to which this section belongs 311 sh_idx + 1, // Section ID is the 1 based 312 section_name, // Name of this section 313 eSectionTypeOther, // TODO: fill this in appropriately for ELF... 314 m_section_headers[sh_idx].sh_addr, // File VM address 315 m_section_headers[sh_idx].sh_size, // VM size in bytes of this section 316 m_section_headers[sh_idx].sh_offset, // Offset to the data for this section in the file 317 section_file_size, // Size in bytes of this section as found in the the file 318 m_section_headers[sh_idx].sh_flags)); // Flags for this section 319 if (section_sp.get()) 320 m_sections_ap->AddSection(section_sp); 321 322 } 323 } 324 } 325 return m_sections_ap.get(); 326 } 327 328 static void 329 ParseSymbols (Symtab *symtab, SectionList *section_list, const Elf32_Shdr &symtab_shdr, const DataExtractor& symtab_data, const DataExtractor& strtab_data) 330 { 331 assert (sizeof(Elf32_Sym) == symtab_shdr.sh_entsize); 332 const uint32_t num_symbols = symtab_data.GetByteSize() / sizeof(Elf32_Sym); 333 uint32_t offset = 0; 334 Elf32_Sym symbol; 335 uint32_t i; 336 static ConstString text_section_name(".text"); 337 static ConstString init_section_name(".init"); 338 static ConstString fini_section_name(".fini"); 339 static ConstString ctors_section_name(".ctors"); 340 static ConstString dtors_section_name(".dtors"); 341 342 static ConstString data_section_name(".data"); 343 static ConstString rodata_section_name(".rodata"); 344 static ConstString rodata1_section_name(".rodata1"); 345 static ConstString data2_section_name(".data1"); 346 static ConstString bss_section_name(".bss"); 347 348 for (i=0; i<num_symbols; ++i) 349 { 350 // if (symtab_data.GetU32(&offset, &symbol.st_name, 3) == 0) 351 // break; 352 353 if (!symtab_data.ValidOffsetForDataOfSize(offset, sizeof(Elf32_Sym))) 354 break; 355 356 symbol.st_name = symtab_data.GetU32 (&offset); 357 symbol.st_value = symtab_data.GetU32 (&offset); 358 symbol.st_size = symtab_data.GetU32 (&offset); 359 symbol.st_info = symtab_data.GetU8 (&offset); 360 symbol.st_other = symtab_data.GetU8 (&offset); 361 symbol.st_shndx = symtab_data.GetU16 (&offset); 362 363 Section * symbol_section = NULL; 364 SymbolType symbol_type = eSymbolTypeInvalid; 365 366 switch (symbol.st_shndx) 367 { 368 case SHN_ABS: 369 symbol_type = eSymbolTypeAbsolute; 370 break; 371 case SHN_UNDEF: 372 symbol_type = eSymbolTypeUndefined; 373 break; 374 default: 375 symbol_section = section_list->GetSectionAtIndex (symbol.st_shndx).get(); 376 break; 377 } 378 379 switch (ELF32_ST_BIND (symbol.st_info)) 380 { 381 default: 382 case STT_NOTYPE: 383 // The symbol's type is not specified. 384 break; 385 386 case STT_OBJECT: 387 // The symbol is associated with a data object, such as a variable, an array, etc. 388 symbol_type == eSymbolTypeData; 389 break; 390 391 case STT_FUNC: 392 // The symbol is associated with a function or other executable code. 393 symbol_type == eSymbolTypeCode; 394 break; 395 396 case STT_SECTION: 397 // The symbol is associated with a section. Symbol table entries of 398 // this type exist primarily for relocation and normally have 399 // STB_LOCAL binding. 400 break; 401 402 case STT_FILE: 403 // Conventionally, the symbol's name gives the name of the source 404 // file associated with the object file. A file symbol has STB_LOCAL 405 // binding, its section index is SHN_ABS, and it precedes the other 406 // STB_LOCAL symbols for the file, if it is present. 407 symbol_type == eSymbolTypeObjectFile; 408 break; 409 } 410 411 if (symbol_type == eSymbolTypeInvalid) 412 { 413 if (symbol_section) 414 { 415 const ConstString §_name = symbol_section->GetName(); 416 if (sect_name == text_section_name || 417 sect_name == init_section_name || 418 sect_name == fini_section_name || 419 sect_name == ctors_section_name || 420 sect_name == dtors_section_name) 421 { 422 symbol_type = eSymbolTypeCode; 423 } 424 else 425 if (sect_name == data_section_name || 426 sect_name == data2_section_name || 427 sect_name == rodata_section_name || 428 sect_name == rodata1_section_name || 429 sect_name == bss_section_name) 430 { 431 symbol_type = eSymbolTypeData; 432 } 433 } 434 } 435 436 uint64_t symbol_value = symbol.st_value; 437 if (symbol_section != NULL) 438 symbol_value -= symbol_section->GetFileAddress(); 439 const char *symbol_name = strtab_data.PeekCStr(symbol.st_name); 440 441 Symbol dc_symbol(i, // ID is the original symbol table index 442 symbol_name, // symbol name 443 false, // Is the symbol name mangled? 444 symbol_type, // type of this symbol 445 ELF32_ST_BIND (symbol.st_info) == STB_GLOBAL, // Is this globally visible? 446 false, // Is this symbol debug info? 447 false, // Is this symbol a trampoline? 448 false, // Is this symbol artificial? 449 symbol_section, // section pointer if symbol_value is an offset within a section, else NULL 450 symbol_value, // offset from section if section is non-NULL, else the value for this symbol 451 symbol.st_size, // size in bytes of this symbol 452 symbol.st_other << 8 | symbol.st_info); // symbol flags 453 symtab->AddSymbol(dc_symbol); 454 } 455 } 456 457 458 Symtab * 459 ObjectFileELF::GetSymtab() 460 { 461 if (m_symtab_ap.get() == NULL) 462 { 463 m_symtab_ap.reset(new Symtab(this)); 464 465 if (ParseSectionHeaders() && GetSectionHeaderStringTable()) 466 { 467 uint32_t symtab_idx = UINT32_MAX; 468 uint32_t dynsym_idx = UINT32_MAX; 469 uint32_t sh_idx = 0; 470 const size_t num_sections = m_section_headers.size(); 471 for (sh_idx = 0; sh_idx < num_sections; ++sh_idx) 472 { 473 if (m_section_headers[sh_idx].sh_type == SHT_SYMTAB) 474 { 475 symtab_idx = sh_idx; 476 break; 477 } 478 if (m_section_headers[sh_idx].sh_type == SHT_DYNSYM) 479 { 480 dynsym_idx = sh_idx; 481 } 482 } 483 484 SectionList *section_list = NULL; 485 static ConstString g_symtab(".symtab"); 486 static ConstString g_strtab(".strtab"); 487 static ConstString g_dynsym(".dynsym"); 488 static ConstString g_dynstr(".dynstr"); 489 // Check if we found a full symbol table? 490 if (symtab_idx < num_sections) 491 { 492 section_list = GetSectionList(); 493 if (section_list) 494 { 495 Section *symtab_section = section_list->FindSectionByName(g_symtab).get(); 496 Section *strtab_section = section_list->FindSectionByName(g_strtab).get(); 497 if (symtab_section && strtab_section) 498 { 499 DataExtractor symtab_data; 500 DataExtractor strtab_data; 501 if (symtab_section->ReadSectionDataFromObjectFile (this, symtab_data) > 0 && 502 strtab_section->ReadSectionDataFromObjectFile (this, strtab_data) > 0) 503 { 504 ParseSymbols (m_symtab_ap.get(), section_list, m_section_headers[symtab_idx], symtab_data, strtab_data); 505 } 506 } 507 } 508 } 509 // Check if we found a reduced symbol table that gets used for dynamic linking? 510 else if (dynsym_idx < num_sections) 511 { 512 section_list = GetSectionList(); 513 if (section_list) 514 { 515 Section *dynsym_section = section_list->FindSectionByName(g_dynsym).get(); 516 Section *dynstr_section = section_list->FindSectionByName(g_dynstr).get(); 517 if (dynsym_section && dynstr_section) 518 { 519 DataExtractor dynsym_data; 520 DataExtractor dynstr_data; 521 if (dynsym_section->ReadSectionDataFromObjectFile (this, dynsym_data) > 0 && 522 dynstr_section->ReadSectionDataFromObjectFile (this, dynstr_data) > 0) 523 { 524 ParseSymbols (m_symtab_ap.get(), section_list, m_section_headers[dynsym_idx], dynsym_data, dynstr_data); 525 } 526 } 527 } 528 } 529 } 530 } 531 return m_symtab_ap.get(); 532 } 533 534 // 535 ////---------------------------------------------------------------------- 536 //// GetNListSymtab 537 ////---------------------------------------------------------------------- 538 //bool 539 //ELF32RuntimeFileParser::GetNListSymtab(BinaryDataRef& stabs_data, BinaryDataRef& stabstr_data, bool locals_only, uint32_t& value_size) 540 //{ 541 // value_size = 4; // Size in bytes of the nlist n_value member 542 // return GetSectionInfo(GetSectionIndexByName(".stab"), NULL, NULL, NULL, NULL, NULL, NULL, &stabs_data, NULL) && 543 // GetSectionInfo(GetSectionIndexByName(".stabstr"), NULL, NULL, NULL, NULL, NULL, NULL, &stabstr_data, NULL); 544 //} 545 // 546 //===----------------------------------------------------------------------===// 547 // Dump 548 // 549 // Dump the specifics of the runtime file container (such as any headers 550 // segments, sections, etc). 551 //---------------------------------------------------------------------- 552 void 553 ObjectFileELF::Dump(Stream *s) 554 { 555 DumpELFHeader(s, m_header); 556 s->EOL(); 557 DumpELFProgramHeaders(s); 558 s->EOL(); 559 DumpELFSectionHeaders(s); 560 s->EOL(); 561 SectionList *section_list = GetSectionList(); 562 if (section_list) 563 section_list->Dump(s, NULL, true); 564 Symtab *symtab = GetSymtab(); 565 if (symtab) 566 symtab->Dump(s, NULL); 567 s->EOL(); 568 } 569 570 //---------------------------------------------------------------------- 571 // DumpELFHeader 572 // 573 // Dump the ELF header to the specified output stream 574 //---------------------------------------------------------------------- 575 void 576 ObjectFileELF::DumpELFHeader(Stream *s, const Elf32_Ehdr& header) 577 { 578 579 s->PutCString ("ELF Header\n"); 580 s->Printf ("e_ident[EI_MAG0 ] = 0x%2.2x\n", header.e_ident[EI_MAG0]); 581 s->Printf ("e_ident[EI_MAG1 ] = 0x%2.2x '%c'\n", header.e_ident[EI_MAG1], header.e_ident[EI_MAG1]); 582 s->Printf ("e_ident[EI_MAG2 ] = 0x%2.2x '%c'\n", header.e_ident[EI_MAG2], header.e_ident[EI_MAG2]); 583 s->Printf ("e_ident[EI_MAG3 ] = 0x%2.2x '%c'\n", header.e_ident[EI_MAG3], header.e_ident[EI_MAG3]); 584 s->Printf ("e_ident[EI_CLASS ] = 0x%2.2x\n", header.e_ident[EI_CLASS]); 585 s->Printf ("e_ident[EI_DATA ] = 0x%2.2x ", header.e_ident[EI_DATA]); 586 DumpELFHeader_e_ident_EI_DATA(s, header.e_ident[EI_DATA]); 587 s->Printf ("\ne_ident[EI_VERSION] = 0x%2.2x\n", header.e_ident[EI_VERSION]); 588 s->Printf ("e_ident[EI_PAD ] = 0x%2.2x\n", header.e_ident[EI_PAD]); 589 590 s->Printf("e_type = 0x%4.4x ", header.e_type); 591 DumpELFHeader_e_type(s, header.e_type); 592 s->Printf("\ne_machine = 0x%4.4x\n", header.e_machine); 593 s->Printf("e_version = 0x%8.8x\n", header.e_version); 594 s->Printf("e_entry = 0x%8.8x\n", header.e_entry); 595 s->Printf("e_phoff = 0x%8.8x\n", header.e_phoff); 596 s->Printf("e_shoff = 0x%8.8x\n", header.e_shoff); 597 s->Printf("e_flags = 0x%8.8x\n", header.e_flags); 598 s->Printf("e_ehsize = 0x%4.4x\n", header.e_ehsize); 599 s->Printf("e_phentsize = 0x%4.4x\n", header.e_phentsize); 600 s->Printf("e_phnum = 0x%4.4x\n", header.e_phnum); 601 s->Printf("e_shentsize = 0x%4.4x\n", header.e_shentsize); 602 s->Printf("e_shnum = 0x%4.4x\n", header.e_shnum); 603 s->Printf("e_shstrndx = 0x%4.4x\n", header.e_shstrndx); 604 } 605 606 //---------------------------------------------------------------------- 607 // DumpELFHeader_e_type 608 // 609 // Dump an token value for the ELF header member e_type 610 //---------------------------------------------------------------------- 611 void 612 ObjectFileELF::DumpELFHeader_e_type(Stream *s, uint16_t e_type) 613 { 614 switch (e_type) 615 { 616 case ET_NONE: *s << "ET_NONE"; break; 617 case ET_REL: *s << "ET_REL"; break; 618 case ET_EXEC: *s << "ET_EXEC"; break; 619 case ET_DYN: *s << "ET_DYN"; break; 620 case ET_CORE: *s << "ET_CORE"; break; 621 default: 622 break; 623 } 624 } 625 626 //---------------------------------------------------------------------- 627 // DumpELFHeader_e_ident_EI_DATA 628 // 629 // Dump an token value for the ELF header member e_ident[EI_DATA] 630 //---------------------------------------------------------------------- 631 void 632 ObjectFileELF::DumpELFHeader_e_ident_EI_DATA(Stream *s, uint16_t ei_data) 633 { 634 switch (ei_data) 635 { 636 case ELFDATANONE: *s << "ELFDATANONE"; break; 637 case ELFDATA2LSB: *s << "ELFDATA2LSB - Little Endian"; break; 638 case ELFDATA2MSB: *s << "ELFDATA2MSB - Big Endian"; break; 639 default: 640 break; 641 } 642 } 643 644 645 //---------------------------------------------------------------------- 646 // DumpELFProgramHeader 647 // 648 // Dump a single ELF program header to the specified output stream 649 //---------------------------------------------------------------------- 650 void 651 ObjectFileELF::DumpELFProgramHeader(Stream *s, const Elf32_Phdr& ph) 652 { 653 DumpELFProgramHeader_p_type(s, ph.p_type); 654 s->Printf(" %8.8x %8.8x %8.8x %8.8x %8.8x %8.8x (", ph.p_offset, ph.p_vaddr, ph.p_paddr, ph.p_filesz, ph.p_memsz, ph.p_flags); 655 DumpELFProgramHeader_p_flags(s, ph.p_flags); 656 s->Printf(") %8.8x", ph.p_align); 657 } 658 659 //---------------------------------------------------------------------- 660 // DumpELFProgramHeader_p_type 661 // 662 // Dump an token value for the ELF program header member p_type which 663 // describes the type of the program header 664 //---------------------------------------------------------------------- 665 void 666 ObjectFileELF::DumpELFProgramHeader_p_type(Stream *s, Elf32_Word p_type) 667 { 668 const int kStrWidth = 10; 669 switch (p_type) 670 { 671 CASE_AND_STREAM(s, PT_NULL , kStrWidth); 672 CASE_AND_STREAM(s, PT_LOAD , kStrWidth); 673 CASE_AND_STREAM(s, PT_DYNAMIC , kStrWidth); 674 CASE_AND_STREAM(s, PT_INTERP , kStrWidth); 675 CASE_AND_STREAM(s, PT_NOTE , kStrWidth); 676 CASE_AND_STREAM(s, PT_SHLIB , kStrWidth); 677 CASE_AND_STREAM(s, PT_PHDR , kStrWidth); 678 default: 679 s->Printf("0x%8.8x%*s", p_type, kStrWidth - 10, ""); 680 break; 681 } 682 } 683 684 685 //---------------------------------------------------------------------- 686 // DumpELFProgramHeader_p_flags 687 // 688 // Dump an token value for the ELF program header member p_flags 689 //---------------------------------------------------------------------- 690 void 691 ObjectFileELF::DumpELFProgramHeader_p_flags(Stream *s, Elf32_Word p_flags) 692 { 693 *s << ((p_flags & PF_X) ? "PF_X" : " ") 694 << (((p_flags & PF_X) && (p_flags & PF_W)) ? '+' : ' ') 695 << ((p_flags & PF_W) ? "PF_W" : " ") 696 << (((p_flags & PF_W) && (p_flags & PF_R)) ? '+' : ' ') 697 << ((p_flags & PF_R) ? "PF_R" : " "); 698 } 699 700 //---------------------------------------------------------------------- 701 // DumpELFProgramHeaders 702 // 703 // Dump all of the ELF program header to the specified output stream 704 //---------------------------------------------------------------------- 705 void 706 ObjectFileELF::DumpELFProgramHeaders(Stream *s) 707 { 708 if (ParseProgramHeaders()) 709 { 710 s->PutCString("Program Headers\n"); 711 s->PutCString("IDX p_type p_offset p_vaddr p_paddr p_filesz p_memsz p_flags p_align\n"); 712 s->PutCString("==== ---------- -------- -------- -------- -------- -------- ------------------------- --------\n"); 713 714 uint32_t idx = 0; 715 ProgramHeaderCollConstIter pos; 716 717 for (pos = m_program_headers.begin(); pos != m_program_headers.end(); ++pos, ++idx) 718 { 719 s->Printf ("[%2u] ", idx); 720 ObjectFileELF::DumpELFProgramHeader(s, *pos); 721 s->EOL(); 722 } 723 } 724 } 725 726 727 //---------------------------------------------------------------------- 728 // DumpELFSectionHeader 729 // 730 // Dump a single ELF section header to the specified output stream 731 //---------------------------------------------------------------------- 732 void 733 ObjectFileELF::DumpELFSectionHeader(Stream *s, const Elf32_Shdr& sh) 734 { 735 s->Printf ("%8.8x ", sh.sh_name); 736 DumpELFSectionHeader_sh_type(s, sh.sh_type); 737 s->Printf (" %8.8x (", sh.sh_flags); 738 DumpELFSectionHeader_sh_flags(s, sh.sh_flags); 739 s->Printf (") %8.8x %8.8x %8.8x %8.8x %8.8x %8.8x %8.8x", 740 sh.sh_addr, sh.sh_offset, sh.sh_size, sh.sh_link, sh.sh_info, sh.sh_addralign, sh.sh_entsize); 741 } 742 743 //---------------------------------------------------------------------- 744 // DumpELFSectionHeader_sh_type 745 // 746 // Dump an token value for the ELF section header member sh_type which 747 // describes the type of the section 748 //---------------------------------------------------------------------- 749 void 750 ObjectFileELF::DumpELFSectionHeader_sh_type(Stream *s, Elf32_Word sh_type) 751 { 752 const int kStrWidth = 12; 753 switch (sh_type) 754 { 755 CASE_AND_STREAM(s, SHT_NULL , kStrWidth); 756 CASE_AND_STREAM(s, SHT_PROGBITS , kStrWidth); 757 CASE_AND_STREAM(s, SHT_SYMTAB , kStrWidth); 758 CASE_AND_STREAM(s, SHT_STRTAB , kStrWidth); 759 CASE_AND_STREAM(s, SHT_RELA , kStrWidth); 760 CASE_AND_STREAM(s, SHT_HASH , kStrWidth); 761 CASE_AND_STREAM(s, SHT_DYNAMIC , kStrWidth); 762 CASE_AND_STREAM(s, SHT_NOTE , kStrWidth); 763 CASE_AND_STREAM(s, SHT_NOBITS , kStrWidth); 764 CASE_AND_STREAM(s, SHT_REL , kStrWidth); 765 CASE_AND_STREAM(s, SHT_SHLIB , kStrWidth); 766 CASE_AND_STREAM(s, SHT_DYNSYM , kStrWidth); 767 CASE_AND_STREAM(s, SHT_LOPROC , kStrWidth); 768 CASE_AND_STREAM(s, SHT_HIPROC , kStrWidth); 769 CASE_AND_STREAM(s, SHT_LOUSER , kStrWidth); 770 CASE_AND_STREAM(s, SHT_HIUSER , kStrWidth); 771 default: 772 s->Printf("0x%8.8x%*s", sh_type, kStrWidth - 10, ""); 773 break; 774 } 775 } 776 777 778 //---------------------------------------------------------------------- 779 // DumpELFSectionHeader_sh_flags 780 // 781 // Dump an token value for the ELF section header member sh_flags 782 //---------------------------------------------------------------------- 783 void 784 ObjectFileELF::DumpELFSectionHeader_sh_flags(Stream *s, Elf32_Word sh_flags) 785 { 786 *s << ((sh_flags & SHF_WRITE) ? "WRITE" : " ") 787 << (((sh_flags & SHF_WRITE) && (sh_flags & SHF_ALLOC)) ? '+' : ' ') 788 << ((sh_flags & SHF_ALLOC) ? "ALLOC" : " ") 789 << (((sh_flags & SHF_ALLOC) && (sh_flags & SHF_EXECINSTR)) ? '+' : ' ') 790 << ((sh_flags & SHF_EXECINSTR) ? "EXECINSTR" : " "); 791 } 792 //---------------------------------------------------------------------- 793 // DumpELFSectionHeaders 794 // 795 // Dump all of the ELF section header to the specified output stream 796 //---------------------------------------------------------------------- 797 void 798 ObjectFileELF::DumpELFSectionHeaders(Stream *s) 799 { 800 if (ParseSectionHeaders() && GetSectionHeaderStringTable()) 801 { 802 s->PutCString("Section Headers\n"); 803 s->PutCString("IDX name type flags addr offset size link info addralgn entsize Name\n"); 804 s->PutCString("==== -------- ------------ -------------------------------- -------- -------- -------- -------- -------- -------- -------- ====================\n"); 805 806 uint32_t idx = 0; 807 SectionHeaderCollConstIter pos; 808 809 for (pos = m_section_headers.begin(); pos != m_section_headers.end(); ++pos, ++idx) 810 { 811 s->Printf ("[%2u] ", idx); 812 ObjectFileELF::DumpELFSectionHeader(s, *pos); 813 const char* section_name = m_shstr_data.PeekCStr(pos->sh_name); 814 if (section_name) 815 *s << ' ' << section_name << "\n"; 816 } 817 } 818 } 819 820 bool 821 ObjectFileELF::GetTargetTriple (ConstString &target_triple) 822 { 823 static ConstString g_target_triple; 824 825 if (g_target_triple) 826 { 827 target_triple = g_target_triple; 828 } 829 else 830 { 831 std::string triple; 832 switch (m_header.e_machine) 833 { 834 case EM_SPARC: triple.assign("sparc-"); break; 835 case EM_386: triple.assign("i386-"); break; 836 case EM_68K: triple.assign("68k-"); break; 837 case EM_88K: triple.assign("88k-"); break; 838 case EM_860: triple.assign("i860-"); break; 839 case EM_MIPS: triple.assign("mips-"); break; 840 case EM_PPC: triple.assign("powerpc-"); break; 841 case EM_PPC64: triple.assign("powerpc64-"); break; 842 case EM_ARM: triple.assign("arm-"); break; 843 } 844 // TODO: determine if there is a vendor in the ELF? Default to "linux" for now 845 triple += "linux-"; 846 // TODO: determine if there is an OS in the ELF? Default to "gnu" for now 847 triple += "gnu"; 848 g_target_triple.SetCString(triple.c_str()); 849 target_triple = g_target_triple; 850 } 851 return !target_triple.IsEmpty(); 852 } 853 854 855 //------------------------------------------------------------------ 856 // PluginInterface protocol 857 //------------------------------------------------------------------ 858 const char * 859 ObjectFileELF::GetPluginName() 860 { 861 return "ObjectFileELF"; 862 } 863 864 const char * 865 ObjectFileELF::GetShortPluginName() 866 { 867 return GetPluginNameStatic(); 868 } 869 870 uint32_t 871 ObjectFileELF::GetPluginVersion() 872 { 873 return 1; 874 } 875 876 void 877 ObjectFileELF::GetPluginCommandHelp (const char *command, Stream *strm) 878 { 879 } 880 881 Error 882 ObjectFileELF::ExecutePluginCommand (Args &command, Stream *strm) 883 { 884 Error error; 885 error.SetErrorString("No plug-in command are currently supported."); 886 return error; 887 } 888 889 Log * 890 ObjectFileELF::EnablePluginLogging (Stream *strm, Args &command) 891 { 892 return NULL; 893 } 894 895 896 897