X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=tools%2Fllvm-readobj%2FELFDumper.cpp;h=856de7ce958ce16a3c26a75b7118463f9d1a4149;hb=217b5866d1449b68d51fba0f654e30afb9dd9418;hp=6fa90263994ef287332c88611cb660c38fe39534;hpb=5d446e61d992f105a05aade62d5305fd8a346081;p=oota-llvm.git diff --git a/tools/llvm-readobj/ELFDumper.cpp b/tools/llvm-readobj/ELFDumper.cpp index 6fa90263994..856de7ce958 100644 --- a/tools/llvm-readobj/ELFDumper.cpp +++ b/tools/llvm-readobj/ELFDumper.cpp @@ -13,12 +13,15 @@ //===----------------------------------------------------------------------===// #include "llvm-readobj.h" +#include "ARMAttributeParser.h" +#include "ARMEHABIPrinter.h" #include "Error.h" #include "ObjDumper.h" #include "StreamWriter.h" - #include "llvm/ADT/SmallString.h" -#include "llvm/Object/ELF.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Object/ELFObjectFile.h" +#include "llvm/Support/ARMBuildAttributes.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Format.h" #include "llvm/Support/MathExtras.h" @@ -28,7 +31,6 @@ using namespace llvm; using namespace llvm::object; using namespace ELF; - #define LLVM_READOBJ_ENUM_CASE(ns, enum) \ case ns::enum: return #enum; @@ -37,82 +39,78 @@ namespace { template class ELFDumper : public ObjDumper { public: - ELFDumper(const ELFObjectFile *Obj, StreamWriter& Writer) - : ObjDumper(Writer) - , Obj(Obj) { } - - virtual void printFileHeaders() LLVM_OVERRIDE; - virtual void printSections() LLVM_OVERRIDE; - virtual void printRelocations() LLVM_OVERRIDE; - virtual void printSymbols() LLVM_OVERRIDE; - virtual void printDynamicSymbols() LLVM_OVERRIDE; - virtual void printUnwindInfo() LLVM_OVERRIDE; - - virtual void printDynamicTable() LLVM_OVERRIDE; - virtual void printNeededLibraries() LLVM_OVERRIDE; - virtual void printProgramHeaders() LLVM_OVERRIDE; - virtual void printARMBuildAttributes() LLVM_OVERRIDE; + ELFDumper(const ELFFile *Obj, StreamWriter &Writer) + : ObjDumper(Writer), Obj(Obj) {} + + void printFileHeaders() override; + void printSections() override; + void printRelocations() override; + void printSymbols() override; + void printDynamicSymbols() override; + void printUnwindInfo() override; + + void printDynamicTable() override; + void printNeededLibraries() override; + void printProgramHeaders() override; + + void printAttributes() override; private: - typedef ELFObjectFile ELFO; + typedef ELFFile ELFO; typedef typename ELFO::Elf_Shdr Elf_Shdr; typedef typename ELFO::Elf_Sym Elf_Sym; - void printSymbol(symbol_iterator SymI, bool IsDynamic = false); + void printSymbol(typename ELFO::Elf_Sym_Iter Symbol); - void printRelocation(section_iterator SecI, relocation_iterator RelI); + void printRelocations(const Elf_Shdr *Sec); + void printRelocation(const Elf_Shdr *Sec, typename ELFO::Elf_Rela Rel); const ELFO *Obj; }; -} // namespace +template T errorOrDefault(ErrorOr Val, T Default = T()) { + if (!Val) { + error(Val.getError()); + return Default; + } + return *Val; +} +} // namespace namespace llvm { -error_code createELFDumper(const object::ObjectFile *Obj, - StreamWriter& Writer, - OwningPtr &Result) { - typedef ELFType Little32ELF; - typedef ELFType Big32ELF; - typedef ELFType Little64ELF; - typedef ELFType Big64ELF; - - typedef ELFObjectFile LittleELF32Obj; - typedef ELFObjectFile BigELF32Obj; - typedef ELFObjectFile LittleELF64Obj; - typedef ELFObjectFile BigELF64Obj; +template +static error_code createELFDumper(const ELFFile *Obj, + StreamWriter &Writer, + std::unique_ptr &Result) { + Result.reset(new ELFDumper(Obj, Writer)); + return readobj_error::success; +} +error_code createELFDumper(const object::ObjectFile *Obj, StreamWriter &Writer, + std::unique_ptr &Result) { // Little-endian 32-bit - if (const LittleELF32Obj *ELFObj = dyn_cast(Obj)) { - Result.reset(new ELFDumper(ELFObj, Writer)); - return readobj_error::success; - } + if (const ELF32LEObjectFile *ELFObj = dyn_cast(Obj)) + return createELFDumper(ELFObj->getELFFile(), Writer, Result); // Big-endian 32-bit - if (const BigELF32Obj *ELFObj = dyn_cast(Obj)) { - Result.reset(new ELFDumper(ELFObj, Writer)); - return readobj_error::success; - } + if (const ELF32BEObjectFile *ELFObj = dyn_cast(Obj)) + return createELFDumper(ELFObj->getELFFile(), Writer, Result); // Little-endian 64-bit - if (const LittleELF64Obj *ELFObj = dyn_cast(Obj)) { - Result.reset(new ELFDumper(ELFObj, Writer)); - return readobj_error::success; - } + if (const ELF64LEObjectFile *ELFObj = dyn_cast(Obj)) + return createELFDumper(ELFObj->getELFFile(), Writer, Result); // Big-endian 64-bit - if (const BigELF64Obj *ELFObj = dyn_cast(Obj)) { - Result.reset(new ELFDumper(ELFObj, Writer)); - return readobj_error::success; - } + if (const ELF64BEObjectFile *ELFObj = dyn_cast(Obj)) + return createELFDumper(ELFObj->getELFFile(), Writer, Result); return readobj_error::unsupported_obj_file_format; } } // namespace llvm - static const EnumEntry ElfClass[] = { { "None", ELF::ELFCLASSNONE }, { "32-bit", ELF::ELFCLASS32 }, @@ -301,7 +299,6 @@ static const EnumEntry ElfMachineType[] = { LLVM_READOBJ_ENUM_ENT(ELF, EM_STM8 ), LLVM_READOBJ_ENUM_ENT(ELF, EM_TILE64 ), LLVM_READOBJ_ENUM_ENT(ELF, EM_TILEPRO ), - LLVM_READOBJ_ENUM_ENT(ELF, EM_MICROBLAZE ), LLVM_READOBJ_ENUM_ENT(ELF, EM_CUDA ), LLVM_READOBJ_ENUM_ENT(ELF, EM_TILEGX ), LLVM_READOBJ_ENUM_ENT(ELF, EM_CLOUDSHIELD ), @@ -312,8 +309,7 @@ static const EnumEntry ElfMachineType[] = { LLVM_READOBJ_ENUM_ENT(ELF, EM_RL78 ), LLVM_READOBJ_ENUM_ENT(ELF, EM_VIDEOCORE5 ), LLVM_READOBJ_ENUM_ENT(ELF, EM_78KOR ), - LLVM_READOBJ_ENUM_ENT(ELF, EM_56800EX ), - LLVM_READOBJ_ENUM_ENT(ELF, EM_MBLAZE ) + LLVM_READOBJ_ENUM_ENT(ELF, EM_56800EX ) }; static const EnumEntry ElfSymbolBindings[] = { @@ -335,7 +331,7 @@ static const EnumEntry ElfSymbolTypes[] = { static const char *getElfSectionType(unsigned Arch, unsigned Type) { switch (Arch) { - case Triple::arm: + case ELF::EM_ARM: switch (Type) { LLVM_READOBJ_ENUM_CASE(ELF, SHT_ARM_EXIDX); LLVM_READOBJ_ENUM_CASE(ELF, SHT_ARM_PREEMPTMAP); @@ -343,16 +339,12 @@ static const char *getElfSectionType(unsigned Arch, unsigned Type) { LLVM_READOBJ_ENUM_CASE(ELF, SHT_ARM_DEBUGOVERLAY); LLVM_READOBJ_ENUM_CASE(ELF, SHT_ARM_OVERLAYSECTION); } - case Triple::hexagon: - switch (Type) { - LLVM_READOBJ_ENUM_CASE(ELF, SHT_HEX_ORDERED); - } - case Triple::x86_64: - switch (Type) { - LLVM_READOBJ_ENUM_CASE(ELF, SHT_X86_64_UNWIND); - } - case Triple::mips: - case Triple::mipsel: + case ELF::EM_HEXAGON: + switch (Type) { LLVM_READOBJ_ENUM_CASE(ELF, SHT_HEX_ORDERED); } + case ELF::EM_X86_64: + switch (Type) { LLVM_READOBJ_ENUM_CASE(ELF, SHT_X86_64_UNWIND); } + case ELF::EM_MIPS: + case ELF::EM_MIPS_RS3_LE: switch (Type) { LLVM_READOBJ_ENUM_CASE(ELF, SHT_MIPS_REGINFO); LLVM_READOBJ_ENUM_CASE(ELF, SHT_MIPS_OPTIONS); @@ -389,6 +381,7 @@ static const char *getElfSectionType(unsigned Arch, unsigned Type) { static const EnumEntry ElfSectionFlags[] = { LLVM_READOBJ_ENUM_ENT(ELF, SHF_WRITE ), LLVM_READOBJ_ENUM_ENT(ELF, SHF_ALLOC ), + LLVM_READOBJ_ENUM_ENT(ELF, SHF_EXCLUDE ), LLVM_READOBJ_ENUM_ENT(ELF, SHF_EXECINSTR ), LLVM_READOBJ_ENUM_ENT(ELF, SHF_MERGE ), LLVM_READOBJ_ENUM_ENT(ELF, SHF_STRINGS ), @@ -402,26 +395,41 @@ static const EnumEntry ElfSectionFlags[] = { LLVM_READOBJ_ENUM_ENT(ELF, SHF_MIPS_NOSTRIP ) }; -static const EnumEntry ElfSegmentTypes[] = { - LLVM_READOBJ_ENUM_ENT(ELF, PT_NULL ), - LLVM_READOBJ_ENUM_ENT(ELF, PT_LOAD ), - LLVM_READOBJ_ENUM_ENT(ELF, PT_DYNAMIC), - LLVM_READOBJ_ENUM_ENT(ELF, PT_INTERP ), - LLVM_READOBJ_ENUM_ENT(ELF, PT_NOTE ), - LLVM_READOBJ_ENUM_ENT(ELF, PT_SHLIB ), - LLVM_READOBJ_ENUM_ENT(ELF, PT_PHDR ), - LLVM_READOBJ_ENUM_ENT(ELF, PT_TLS ), - - LLVM_READOBJ_ENUM_ENT(ELF, PT_GNU_EH_FRAME), - LLVM_READOBJ_ENUM_ENT(ELF, PT_SUNW_EH_FRAME), - LLVM_READOBJ_ENUM_ENT(ELF, PT_SUNW_UNWIND), - - LLVM_READOBJ_ENUM_ENT(ELF, PT_GNU_STACK), - LLVM_READOBJ_ENUM_ENT(ELF, PT_GNU_RELRO), - - LLVM_READOBJ_ENUM_ENT(ELF, PT_ARM_EXIDX), - LLVM_READOBJ_ENUM_ENT(ELF, PT_ARM_UNWIND) -}; +static const char *getElfSegmentType(unsigned Arch, unsigned Type) { + // Check potentially overlapped processor-specific + // program header type. + switch (Arch) { + case ELF::EM_ARM: + switch (Type) { + LLVM_READOBJ_ENUM_CASE(ELF, PT_ARM_EXIDX); + } + case ELF::EM_MIPS: + case ELF::EM_MIPS_RS3_LE: + switch (Type) { + LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_REGINFO); + LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_RTPROC); + LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_OPTIONS); + } + } + + switch (Type) { + LLVM_READOBJ_ENUM_CASE(ELF, PT_NULL ); + LLVM_READOBJ_ENUM_CASE(ELF, PT_LOAD ); + LLVM_READOBJ_ENUM_CASE(ELF, PT_DYNAMIC); + LLVM_READOBJ_ENUM_CASE(ELF, PT_INTERP ); + LLVM_READOBJ_ENUM_CASE(ELF, PT_NOTE ); + LLVM_READOBJ_ENUM_CASE(ELF, PT_SHLIB ); + LLVM_READOBJ_ENUM_CASE(ELF, PT_PHDR ); + LLVM_READOBJ_ENUM_CASE(ELF, PT_TLS ); + + LLVM_READOBJ_ENUM_CASE(ELF, PT_GNU_EH_FRAME); + LLVM_READOBJ_ENUM_CASE(ELF, PT_SUNW_UNWIND); + + LLVM_READOBJ_ENUM_CASE(ELF, PT_GNU_STACK); + LLVM_READOBJ_ENUM_CASE(ELF, PT_GNU_RELRO); + default: return ""; + } +} static const EnumEntry ElfSegmentFlags[] = { LLVM_READOBJ_ENUM_ENT(ELF, PF_X), @@ -429,12 +437,30 @@ static const EnumEntry ElfSegmentFlags[] = { LLVM_READOBJ_ENUM_ENT(ELF, PF_R) }; +static const EnumEntry ElfHeaderMipsFlags[] = { + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_NOREORDER), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_PIC), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_CPIC), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ABI2), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_32BITMODE), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_NAN2008), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ABI_O32), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MICROMIPS), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_ASE_M16), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_1), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_2), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_3), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_4), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_5), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_32), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_64), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_32R2), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_64R2) +}; template void ELFDumper::printFileHeaders() { - error_code EC; - - const typename ELFO::Elf_Ehdr *Header = Obj->getElfHeader(); + const typename ELFO::Elf_Ehdr *Header = Obj->getHeader(); { DictScope D(W, "ElfHeader"); @@ -459,7 +485,11 @@ void ELFDumper::printFileHeaders() { W.printHex ("Entry", Header->e_entry); W.printHex ("ProgramHeaderOffset", Header->e_phoff); W.printHex ("SectionHeaderOffset", Header->e_shoff); - W.printFlags ("Flags", Header->e_flags); + if (Header->e_machine == EM_MIPS) + W.printFlags("Flags", Header->e_flags, makeArrayRef(ElfHeaderMipsFlags), + unsigned(ELF::EF_MIPS_ARCH)); + else + W.printFlags("Flags", Header->e_flags); W.printNumber("HeaderSize", Header->e_ehsize); W.printNumber("ProgramHeaderEntrySize", Header->e_phentsize); W.printNumber("ProgramHeaderCount", Header->e_phnum); @@ -474,24 +504,20 @@ void ELFDumper::printSections() { ListScope SectionsD(W, "Sections"); int SectionIndex = -1; - error_code EC; - for (section_iterator SecI = Obj->begin_sections(), - SecE = Obj->end_sections(); - SecI != SecE; SecI.increment(EC)) { - if (error(EC)) break; - + for (typename ELFO::Elf_Shdr_Iter SecI = Obj->begin_sections(), + SecE = Obj->end_sections(); + SecI != SecE; ++SecI) { ++SectionIndex; - const Elf_Shdr *Section = Obj->getElfSection(SecI); - StringRef Name; - if (error(SecI->getName(Name))) - Name = ""; + const Elf_Shdr *Section = &*SecI; + StringRef Name = errorOrDefault(Obj->getSectionName(Section)); DictScope SectionD(W, "Section"); W.printNumber("Index", SectionIndex); W.printNumber("Name", Name, Section->sh_name); - W.printHex ("Type", getElfSectionType(Obj->getArch(), Section->sh_type), - Section->sh_type); + W.printHex("Type", + getElfSectionType(Obj->getHeader()->e_machine, Section->sh_type), + Section->sh_type); W.printFlags ("Flags", Section->sh_flags, makeArrayRef(ElfSectionFlags)); W.printHex ("Address", Section->sh_addr); W.printHex ("Offset", Section->sh_offset); @@ -503,35 +529,23 @@ void ELFDumper::printSections() { if (opts::SectionRelocations) { ListScope D(W, "Relocations"); - for (relocation_iterator RelI = SecI->begin_relocations(), - RelE = SecI->end_relocations(); - RelI != RelE; RelI.increment(EC)) { - if (error(EC)) break; - - printRelocation(SecI, RelI); - } + printRelocations(Section); } if (opts::SectionSymbols) { ListScope D(W, "Symbols"); - for (symbol_iterator SymI = Obj->begin_symbols(), - SymE = Obj->end_symbols(); - SymI != SymE; SymI.increment(EC)) { - if (error(EC)) break; - - bool Contained = false; - if (SecI->containsSymbol(*SymI, Contained) || !Contained) - continue; - - printSymbol(SymI); + for (typename ELFO::Elf_Sym_Iter SymI = Obj->begin_symbols(), + SymE = Obj->end_symbols(); + SymI != SymE; ++SymI) { + if (Obj->getSection(&*SymI) == Section) + printSymbol(SymI); } } if (opts::SectionData) { - StringRef Data; - if (error(SecI->getContents(Data))) break; - - W.printBinaryBlock("SectionData", Data); + ArrayRef Data = errorOrDefault(Obj->getSectionContents(Section)); + W.printBinaryBlock("SectionData", + StringRef((const char *)Data.data(), Data.size())); } } } @@ -540,72 +554,74 @@ template void ELFDumper::printRelocations() { ListScope D(W, "Relocations"); - error_code EC; int SectionNumber = -1; - for (section_iterator SecI = Obj->begin_sections(), - SecE = Obj->end_sections(); - SecI != SecE; SecI.increment(EC)) { - if (error(EC)) break; - + for (typename ELFO::Elf_Shdr_Iter SecI = Obj->begin_sections(), + SecE = Obj->end_sections(); + SecI != SecE; ++SecI) { ++SectionNumber; - StringRef Name; - if (error(SecI->getName(Name))) + + if (SecI->sh_type != ELF::SHT_REL && SecI->sh_type != ELF::SHT_RELA) continue; - bool PrintedGroup = false; - for (relocation_iterator RelI = SecI->begin_relocations(), - RelE = SecI->end_relocations(); - RelI != RelE; RelI.increment(EC)) { - if (error(EC)) break; + StringRef Name = errorOrDefault(Obj->getSectionName(&*SecI)); - if (!PrintedGroup) { - W.startLine() << "Section (" << SectionNumber << ") " << Name << " {\n"; - W.indent(); - PrintedGroup = true; - } + W.startLine() << "Section (" << SectionNumber << ") " << Name << " {\n"; + W.indent(); - printRelocation(SecI, RelI); - } + printRelocations(&*SecI); + + W.unindent(); + W.startLine() << "}\n"; + } +} - if (PrintedGroup) { - W.unindent(); - W.startLine() << "}\n"; +template +void ELFDumper::printRelocations(const Elf_Shdr *Sec) { + switch (Sec->sh_type) { + case ELF::SHT_REL: + for (typename ELFO::Elf_Rel_Iter RI = Obj->begin_rel(Sec), + RE = Obj->end_rel(Sec); + RI != RE; ++RI) { + typename ELFO::Elf_Rela Rela; + Rela.r_offset = RI->r_offset; + Rela.r_info = RI->r_info; + Rela.r_addend = 0; + printRelocation(Sec, Rela); + } + break; + case ELF::SHT_RELA: + for (typename ELFO::Elf_Rela_Iter RI = Obj->begin_rela(Sec), + RE = Obj->end_rela(Sec); + RI != RE; ++RI) { + printRelocation(Sec, *RI); } + break; } } -template -void ELFDumper::printRelocation(section_iterator Sec, - relocation_iterator RelI) { - uint64_t Offset; - uint64_t RelocType; +template +void ELFDumper::printRelocation(const Elf_Shdr *Sec, + typename ELFO::Elf_Rela Rel) { SmallString<32> RelocName; - int64_t Info; + Obj->getRelocationTypeName(Rel.getType(Obj->isMips64EL()), RelocName); StringRef SymbolName; - SymbolRef Symbol; - if (Obj->getElfHeader()->e_type == ELF::ET_REL){ - if (error(RelI->getOffset(Offset))) return; - } else { - if (error(RelI->getAddress(Offset))) return; - } - if (error(RelI->getType(RelocType))) return; - if (error(RelI->getTypeName(RelocName))) return; - if (error(RelI->getAdditionalInfo(Info))) return; - if (error(RelI->getSymbol(Symbol))) return; - if (error(Symbol.getName(SymbolName))) return; + std::pair Sym = + Obj->getRelocationSymbol(Sec, &Rel); + if (Sym.first) + SymbolName = errorOrDefault(Obj->getSymbolName(Sym.first, Sym.second)); if (opts::ExpandRelocs) { DictScope Group(W, "Relocation"); - W.printHex("Offset", Offset); - W.printNumber("Type", RelocName, RelocType); + W.printHex("Offset", Rel.r_offset); + W.printNumber("Type", RelocName, (int)Rel.getType(Obj->isMips64EL())); W.printString("Symbol", SymbolName.size() > 0 ? SymbolName : "-"); - W.printHex("Info", Info); + W.printHex("Addend", Rel.r_addend); } else { raw_ostream& OS = W.startLine(); - OS << W.hex(Offset) + OS << W.hex(Rel.r_offset) << " " << RelocName << " " << (SymbolName.size() > 0 ? SymbolName : "-") - << " " << W.hex(Info) + << " " << W.hex(Rel.r_addend) << "\n"; } } @@ -613,12 +629,9 @@ void ELFDumper::printRelocation(section_iterator Sec, template void ELFDumper::printSymbols() { ListScope Group(W, "Symbols"); - - error_code EC; - for (symbol_iterator SymI = Obj->begin_symbols(), SymE = Obj->end_symbols(); - SymI != SymE; SymI.increment(EC)) { - if (error(EC)) break; - + for (typename ELFO::Elf_Sym_Iter SymI = Obj->begin_symbols(), + SymE = Obj->end_symbols(); + SymI != SymE; ++SymI) { printSymbol(SymI); } } @@ -627,41 +640,50 @@ template void ELFDumper::printDynamicSymbols() { ListScope Group(W, "DynamicSymbols"); - error_code EC; - for (symbol_iterator SymI = Obj->begin_dynamic_symbols(), - SymE = Obj->end_dynamic_symbols(); - SymI != SymE; SymI.increment(EC)) { - if (error(EC)) break; - - printSymbol(SymI, true); + for (typename ELFO::Elf_Sym_Iter SymI = Obj->begin_dynamic_symbols(), + SymE = Obj->end_dynamic_symbols(); + SymI != SymE; ++SymI) { + printSymbol(SymI); } } -template -void ELFDumper::printSymbol(symbol_iterator SymI, bool IsDynamic) { - error_code EC; - - const Elf_Sym *Symbol = Obj->getElfSymbol(SymI); - const Elf_Shdr *Section = Obj->getSection(Symbol); - - StringRef SymbolName; - if (SymI->getName(SymbolName)) - SymbolName = ""; - - StringRef SectionName = ""; - if (Section) - Obj->getSectionName(Section, SectionName); +template +void ELFDumper::printSymbol(typename ELFO::Elf_Sym_Iter Symbol) { + StringRef SymbolName = errorOrDefault(Obj->getSymbolName(Symbol)); + + unsigned SectionIndex = Symbol->st_shndx; + StringRef SectionName; + if (SectionIndex == SHN_UNDEF) { + SectionName = "Undefined"; + } else if (SectionIndex >= SHN_LOPROC && SectionIndex <= SHN_HIPROC) { + SectionName = "Processor Specific"; + } else if (SectionIndex >= SHN_LOOS && SectionIndex <= SHN_HIOS) { + SectionName = "Operating System Specific"; + } else if (SectionIndex > SHN_HIOS && SectionIndex < SHN_ABS) { + SectionName = "Reserved"; + } else if (SectionIndex == SHN_ABS) { + SectionName = "Absolute"; + } else if (SectionIndex == SHN_COMMON) { + SectionName = "Common"; + } else { + if (SectionIndex == SHN_XINDEX) + SectionIndex = Obj->getSymbolTableIndex(&*Symbol); + assert(SectionIndex != SHN_XINDEX && + "getSymbolTableIndex should handle this"); + const Elf_Shdr *Sec = Obj->getSection(SectionIndex); + SectionName = errorOrDefault(Obj->getSectionName(Sec)); + } std::string FullSymbolName(SymbolName); - if (IsDynamic) { - StringRef Version; + if (Symbol.isDynamic()) { bool IsDefault; - if (error(Obj->getSymbolVersion(*SymI, Version, IsDefault))) - return; - if (!Version.empty()) { + ErrorOr Version = Obj->getSymbolVersion(nullptr, &*Symbol, + IsDefault); + if (Version) { FullSymbolName += (IsDefault ? "@@" : "@"); - FullSymbolName += Version; - } + FullSymbolName += *Version; + } else + error(Version.getError()); } DictScope D(W, "Symbol"); @@ -672,7 +694,7 @@ void ELFDumper::printSymbol(symbol_iterator SymI, bool IsDynamic) { makeArrayRef(ElfSymbolBindings)); W.printEnum ("Type", Symbol->getType(), makeArrayRef(ElfSymbolTypes)); W.printNumber("Other", Symbol->st_other); - W.printHex ("Section", SectionName, Symbol->st_shndx); + W.printHex("Section", SectionName, SectionIndex); } #define LLVM_READOBJ_TYPE_CASE(name) \ @@ -713,15 +735,27 @@ static const char *getTypeString(uint64_t Type) { LLVM_READOBJ_TYPE_CASE(SYMENT); LLVM_READOBJ_TYPE_CASE(SYMTAB); LLVM_READOBJ_TYPE_CASE(TEXTREL); + LLVM_READOBJ_TYPE_CASE(VERNEED); + LLVM_READOBJ_TYPE_CASE(VERNEEDNUM); + LLVM_READOBJ_TYPE_CASE(VERSYM); + LLVM_READOBJ_TYPE_CASE(MIPS_RLD_VERSION); + LLVM_READOBJ_TYPE_CASE(MIPS_FLAGS); + LLVM_READOBJ_TYPE_CASE(MIPS_BASE_ADDRESS); + LLVM_READOBJ_TYPE_CASE(MIPS_LOCAL_GOTNO); + LLVM_READOBJ_TYPE_CASE(MIPS_SYMTABNO); + LLVM_READOBJ_TYPE_CASE(MIPS_UNREFEXTNO); + LLVM_READOBJ_TYPE_CASE(MIPS_GOTSYM); + LLVM_READOBJ_TYPE_CASE(MIPS_RLD_MAP); + LLVM_READOBJ_TYPE_CASE(MIPS_PLTGOT); default: return "unknown"; } } #undef LLVM_READOBJ_TYPE_CASE -template -static void printValue(const ELFObjectFile *O, uint64_t Type, - uint64_t Value, bool Is64, raw_ostream &OS) { +template +static void printValue(const ELFFile *O, uint64_t Type, uint64_t Value, + bool Is64, raw_ostream &OS) { switch (Type) { case DT_PLTREL: if (Value == DT_REL) { @@ -745,9 +779,23 @@ static void printValue(const ELFObjectFile *O, uint64_t Type, case DT_FINI_ARRAY: case DT_PREINIT_ARRAY: case DT_DEBUG: + case DT_VERNEED: + case DT_VERSYM: case DT_NULL: + case DT_MIPS_FLAGS: + case DT_MIPS_BASE_ADDRESS: + case DT_MIPS_GOTSYM: + case DT_MIPS_RLD_MAP: + case DT_MIPS_PLTGOT: OS << format("0x%" PRIX64, Value); break; + case DT_VERNEEDNUM: + case DT_MIPS_RLD_VERSION: + case DT_MIPS_LOCAL_GOTNO: + case DT_MIPS_SYMTABNO: + case DT_MIPS_UNREFEXTNO: + OS << Value; + break; case DT_PLTRELSZ: case DT_RELASZ: case DT_RELAENT: @@ -761,12 +809,14 @@ static void printValue(const ELFObjectFile *O, uint64_t Type, OS << Value << " (bytes)"; break; case DT_NEEDED: - OS << "SharedLibrary (" - << O->getString(O->getDynamicStringTableSectionHeader(), Value) << ")"; + OS << "SharedLibrary (" << O->getDynamicString(Value) << ")"; break; case DT_SONAME: - OS << "LibrarySoname (" - << O->getString(O->getDynamicStringTableSectionHeader(), Value) << ")"; + OS << "LibrarySoname (" << O->getDynamicString(Value) << ")"; + break; + case DT_RPATH: + case DT_RUNPATH: + OS << O->getDynamicString(Value); break; } } @@ -776,11 +826,22 @@ void ELFDumper::printUnwindInfo() { W.startLine() << "UnwindInfo not implemented.\n"; } +namespace { +template <> +void ELFDumper >::printUnwindInfo() { + const unsigned Machine = Obj->getHeader()->e_machine; + if (Machine == EM_ARM) { + ARM::EHABI::PrinterContext > Ctx(W, Obj); + return Ctx.PrintUnwindInformation(); + } + W.startLine() << "UnwindInfo not implemented.\n"; +} +} + template void ELFDumper::printDynamicTable() { - typedef typename ELFO::Elf_Dyn_iterator EDI; - EDI Start = Obj->begin_dynamic_table(), - End = Obj->end_dynamic_table(true); + typedef typename ELFO::Elf_Dyn_Iter EDI; + EDI Start = Obj->begin_dynamic_table(), End = Obj->end_dynamic_table(true); if (Start == End) return; @@ -789,7 +850,7 @@ void ELFDumper::printDynamicTable() { raw_ostream &OS = W.getOStream(); W.startLine() << "DynamicSection [ (" << Total << " entries)\n"; - bool Is64 = Obj->getBytesInAddress() == 8; + bool Is64 = ELFT::Is64Bits; W.startLine() << " Tag" << (Is64 ? " " : " ") << "Type" @@ -806,38 +867,23 @@ void ELFDumper::printDynamicTable() { W.startLine() << "]\n"; } -static bool compareLibraryName(const LibraryRef &L, const LibraryRef &R) { - StringRef LPath, RPath; - L.getPath(LPath); - R.getPath(RPath); - return LPath < RPath; -} - template void ELFDumper::printNeededLibraries() { ListScope D(W, "NeededLibraries"); - error_code EC; - - typedef std::vector LibsTy; + typedef std::vector LibsTy; LibsTy Libs; - for (library_iterator I = Obj->begin_libraries_needed(), - E = Obj->end_libraries_needed(); - I != E; I.increment(EC)) { - if (EC) - report_fatal_error("Needed libraries iteration failed"); - - Libs.push_back(*I); - } + for (typename ELFO::Elf_Dyn_Iter DynI = Obj->begin_dynamic_table(), + DynE = Obj->end_dynamic_table(); + DynI != DynE; ++DynI) + if (DynI->d_tag == ELF::DT_NEEDED) + Libs.push_back(Obj->getDynamicString(DynI->d_un.d_val)); - std::sort(Libs.begin(), Libs.end(), &compareLibraryName); + std::stable_sort(Libs.begin(), Libs.end()); - for (LibsTy::const_iterator I = Libs.begin(), E = Libs.end(); - I != E; ++I) { - StringRef Path; - I->getPath(Path); - outs() << " " << Path << "\n"; + for (LibsTy::const_iterator I = Libs.begin(), E = Libs.end(); I != E; ++I) { + outs() << " " << *I << "\n"; } } @@ -849,7 +895,9 @@ void ELFDumper::printProgramHeaders() { PE = Obj->end_program_headers(); PI != PE; ++PI) { DictScope P(W, "ProgramHeader"); - W.printEnum ("Type", PI->p_type, makeArrayRef(ElfSegmentTypes)); + W.printHex ("Type", + getElfSegmentType(Obj->getHeader()->e_machine, PI->p_type), + PI->p_type); W.printHex ("Offset", PI->p_offset); W.printHex ("VirtualAddress", PI->p_vaddr); W.printHex ("PhysicalAddress", PI->p_paddr); @@ -860,64 +908,41 @@ void ELFDumper::printProgramHeaders() { } } -#define LLVM_READOBJ_ARMATTR_NUMCASE(X) case ARMBuildAttrs::X: \ - W.printNumber(" Tag_" #X, BuildAttrs.Tag_##X); \ - break; \ - -#define LLVM_READOBJ_ARMATTR_STRCASE(X) case ARMBuildAttrs::X: \ - W.printString(" Tag_" #X, BuildAttrs.Tag_##X); \ - break; \ +template +void ELFDumper::printAttributes() { + W.startLine() << "Attributes not implemented.\n"; +} -template -void ELFDumper::printARMBuildAttributes() { - if (Obj->getArch() != Triple::arm || !Obj->hasARMBuildAttributes()) - return; - ARMBuildAttrs::ARMGenericBuildAttrInfo BuildAttrs; - SmallVector AttrsRead; - error_code EC = Obj->readARMBuildAttributes(BuildAttrs, AttrsRead); - if (error(EC)) +namespace { +template <> +void ELFDumper >::printAttributes() { + if (Obj->getHeader()->e_machine != EM_ARM) { + W.startLine() << "Attributes not implemented.\n"; return; + } - DictScope D(W, "ARMBuildAttributes"); - - for (SmallVector::iterator I = AttrsRead.begin(), - E = AttrsRead.end(); I != E; ++I) { - switch (*I) { - LLVM_READOBJ_ARMATTR_STRCASE(CPU_name) - LLVM_READOBJ_ARMATTR_STRCASE(CPU_raw_name) - LLVM_READOBJ_ARMATTR_NUMCASE(CPU_arch) - LLVM_READOBJ_ARMATTR_NUMCASE(CPU_arch_profile) - LLVM_READOBJ_ARMATTR_NUMCASE(ARM_ISA_use) - LLVM_READOBJ_ARMATTR_NUMCASE(THUMB_ISA_use) - LLVM_READOBJ_ARMATTR_NUMCASE(FP_arch) - LLVM_READOBJ_ARMATTR_NUMCASE(WMMX_arch) - LLVM_READOBJ_ARMATTR_NUMCASE(Advanced_SIMD_arch) - LLVM_READOBJ_ARMATTR_NUMCASE(PCS_config) - LLVM_READOBJ_ARMATTR_NUMCASE(ABI_PCS_R9_use) - LLVM_READOBJ_ARMATTR_NUMCASE(ABI_PCS_RW_data) - LLVM_READOBJ_ARMATTR_NUMCASE(ABI_PCS_RO_data) - LLVM_READOBJ_ARMATTR_NUMCASE(ABI_PCS_GOT_use) - LLVM_READOBJ_ARMATTR_NUMCASE(ABI_PCS_wchar_t) - LLVM_READOBJ_ARMATTR_NUMCASE(ABI_FP_rounding) - LLVM_READOBJ_ARMATTR_NUMCASE(ABI_FP_denormal) - LLVM_READOBJ_ARMATTR_NUMCASE(ABI_FP_exceptions) - LLVM_READOBJ_ARMATTR_NUMCASE(ABI_FP_user_exceptions) - LLVM_READOBJ_ARMATTR_NUMCASE(ABI_FP_number_model) - LLVM_READOBJ_ARMATTR_NUMCASE(ABI_align8_needed) - LLVM_READOBJ_ARMATTR_NUMCASE(ABI_align8_preserved) - LLVM_READOBJ_ARMATTR_NUMCASE(ABI_enum_size) - LLVM_READOBJ_ARMATTR_NUMCASE(ABI_HardFP_use) - LLVM_READOBJ_ARMATTR_NUMCASE(ABI_VFP_args) - LLVM_READOBJ_ARMATTR_NUMCASE(CPU_unaligned_access) - LLVM_READOBJ_ARMATTR_NUMCASE(FP_HP_extension) - LLVM_READOBJ_ARMATTR_NUMCASE(MPextension_use) - LLVM_READOBJ_ARMATTR_NUMCASE(DIV_use) - LLVM_READOBJ_ARMATTR_NUMCASE(T2EE_use) - LLVM_READOBJ_ARMATTR_NUMCASE(Virtualization_use) - LLVM_READOBJ_ARMATTR_NUMCASE(ABI_optimization_goals) - LLVM_READOBJ_ARMATTR_NUMCASE(ABI_FP_optimization_goals) - default: - break; + DictScope BA(W, "BuildAttributes"); + for (ELFO::Elf_Shdr_Iter SI = Obj->begin_sections(), SE = Obj->end_sections(); + SI != SE; ++SI) { + if (SI->sh_type != ELF::SHT_ARM_ATTRIBUTES) + continue; + + ErrorOr > Contents = Obj->getSectionContents(&(*SI)); + if (!Contents) + continue; + + if ((*Contents)[0] != ARMBuildAttrs::Format_Version) { + errs() << "unrecognised FormatVersion: 0x" << utohexstr((*Contents)[0]) + << '\n'; + continue; } + + W.printHex("FormatVersion", (*Contents)[0]); + if (Contents->size() == 1) + continue; + + ARMAttributeParser(W).Parse(*Contents); } } +} +