X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=tools%2Fllvm-readobj%2Fllvm-readobj.cpp;h=7e6ce49672313b7d25bf6e1db3732f93c6553af1;hb=de7e17f65a88b16b76f4060a9733ca6abc9d7627;hp=9d5cfcbd6a233ca6d2d2d6c98a8095b96c4ba561;hpb=1c8dfa5e90fa7ba5d351d2e2511dc1495c83f6fd;p=oota-llvm.git diff --git a/tools/llvm-readobj/llvm-readobj.cpp b/tools/llvm-readobj/llvm-readobj.cpp index 9d5cfcbd6a2..7e6ce496723 100644 --- a/tools/llvm-readobj/llvm-readobj.cpp +++ b/tools/llvm-readobj/llvm-readobj.cpp @@ -20,12 +20,12 @@ //===----------------------------------------------------------------------===// #include "llvm-readobj.h" - #include "Error.h" #include "ObjDumper.h" #include "StreamWriter.h" - #include "llvm/Object/Archive.h" +#include "llvm/Object/ELFObjectFile.h" +#include "llvm/Object/MachOUniversal.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" @@ -37,9 +37,8 @@ #include "llvm/Support/Signals.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/TargetSelect.h" -#include "llvm/Support/system_error.h" - #include +#include using namespace llvm; @@ -121,17 +120,62 @@ namespace opts { cl::opt NeededLibraries("needed-libs", cl::desc("Display the needed libraries")); + // -program-headers + cl::opt ProgramHeaders("program-headers", + cl::desc("Display ELF program headers")); + // -expand-relocs cl::opt ExpandRelocs("expand-relocs", cl::desc("Expand each shown relocation to multiple lines")); + + // -codeview + cl::opt CodeView("codeview", + cl::desc("Display CodeView debug information")); + + // -codeview-subsection-bytes + cl::opt CodeViewSubsectionBytes( + "codeview-subsection-bytes", + cl::desc("Dump raw contents of codeview debug sections and records")); + + // -arm-attributes, -a + cl::opt ARMAttributes("arm-attributes", + cl::desc("Display the ARM attributes section")); + cl::alias ARMAttributesShort("-a", cl::desc("Alias for --arm-attributes"), + cl::aliasopt(ARMAttributes)); + + // -mips-plt-got + cl::opt + MipsPLTGOT("mips-plt-got", + cl::desc("Display the MIPS GOT and PLT GOT sections")); + + // -coff-imports + cl::opt + COFFImports("coff-imports", cl::desc("Display the PE/COFF import table")); + + // -coff-exports + cl::opt + COFFExports("coff-exports", cl::desc("Display the PE/COFF export table")); + + // -coff-directives + cl::opt + COFFDirectives("coff-directives", + cl::desc("Display the PE/COFF .drectve section")); + + // -coff-basereloc + cl::opt + COFFBaseRelocs("coff-basereloc", + cl::desc("Display the PE/COFF .reloc section")); } // namespace opts +static int ReturnValue = EXIT_SUCCESS; + namespace llvm { -bool error(error_code EC) { +bool error(std::error_code EC) { if (!EC) return false; + ReturnValue = EXIT_FAILURE; outs() << "\nError reading file: " << EC.message() << ".\n"; outs().flush(); return true; @@ -139,20 +183,20 @@ bool error(error_code EC) { bool relocAddressLess(RelocationRef a, RelocationRef b) { uint64_t a_addr, b_addr; - if (error(a.getAddress(a_addr))) return false; - if (error(b.getAddress(b_addr))) return false; + if (error(a.getOffset(a_addr))) exit(ReturnValue); + if (error(b.getOffset(b_addr))) exit(ReturnValue); return a_addr < b_addr; } } // namespace llvm - -static void reportError(StringRef Input, error_code EC) { +static void reportError(StringRef Input, std::error_code EC) { if (Input == "-") Input = ""; errs() << Input << ": " << EC.message() << "\n"; errs().flush(); + ReturnValue = EXIT_FAILURE; } static void reportError(StringRef Input, StringRef Message) { @@ -160,12 +204,24 @@ static void reportError(StringRef Input, StringRef Message) { Input = ""; errs() << Input << ": " << Message << "\n"; + ReturnValue = EXIT_FAILURE; +} + +static bool isMipsArch(unsigned Arch) { + switch (Arch) { + case llvm::Triple::mips: + case llvm::Triple::mipsel: + case llvm::Triple::mips64: + case llvm::Triple::mips64el: + return true; + default: + return false; + } } /// @brief Creates an format-specific object file dumper. -static error_code createDumper(const ObjectFile *Obj, - StreamWriter &Writer, - OwningPtr &Result) { +static std::error_code createDumper(const ObjectFile *Obj, StreamWriter &Writer, + std::unique_ptr &Result) { if (!Obj) return readobj_error::unsupported_file_format; @@ -179,12 +235,23 @@ static error_code createDumper(const ObjectFile *Obj, return readobj_error::unsupported_obj_file_format; } +static StringRef getLoadName(const ObjectFile *Obj) { + if (auto *ELF = dyn_cast(Obj)) + return ELF->getLoadName(); + if (auto *ELF = dyn_cast(Obj)) + return ELF->getLoadName(); + if (auto *ELF = dyn_cast(Obj)) + return ELF->getLoadName(); + if (auto *ELF = dyn_cast(Obj)) + return ELF->getLoadName(); + llvm_unreachable("Not ELF"); +} /// @brief Dumps the specified object file. static void dumpObject(const ObjectFile *Obj) { StreamWriter Writer(outs()); - OwningPtr Dumper; - if (error_code EC = createDumper(Obj, Writer, Dumper)) { + std::unique_ptr Dumper; + if (std::error_code EC = createDumper(Obj, Writer, Dumper)) { reportError(Obj->getFileName(), EC); return; } @@ -197,7 +264,7 @@ static void dumpObject(const ObjectFile *Obj) { << "\n"; outs() << "AddressSize: " << (8*Obj->getBytesInAddress()) << "bit\n"; if (Obj->isELF()) - outs() << "LoadName: " << Obj->getLoadName() << "\n"; + outs() << "LoadName: " << getLoadName(Obj) << "\n"; if (opts::FileHeaders) Dumper->printFileHeaders(); @@ -215,29 +282,57 @@ static void dumpObject(const ObjectFile *Obj) { Dumper->printDynamicTable(); if (opts::NeededLibraries) Dumper->printNeededLibraries(); + if (opts::ProgramHeaders) + Dumper->printProgramHeaders(); + if (Obj->getArch() == llvm::Triple::arm && Obj->isELF()) + if (opts::ARMAttributes) + Dumper->printAttributes(); + if (isMipsArch(Obj->getArch()) && Obj->isELF()) + if (opts::MipsPLTGOT) + Dumper->printMipsPLTGOT(); + if (opts::COFFImports) + Dumper->printCOFFImports(); + if (opts::COFFExports) + Dumper->printCOFFExports(); + if (opts::COFFDirectives) + Dumper->printCOFFDirectives(); + if (opts::COFFBaseRelocs) + Dumper->printCOFFBaseReloc(); } /// @brief Dumps each object file in \a Arc; static void dumpArchive(const Archive *Arc) { - for (Archive::child_iterator ArcI = Arc->begin_children(), - ArcE = Arc->end_children(); + for (Archive::child_iterator ArcI = Arc->child_begin(), + ArcE = Arc->child_end(); ArcI != ArcE; ++ArcI) { - OwningPtr child; - if (error_code EC = ArcI->getAsBinary(child)) { + ErrorOr> ChildOrErr = ArcI->getAsBinary(); + if (std::error_code EC = ChildOrErr.getError()) { // Ignore non-object files. if (EC != object_error::invalid_file_type) reportError(Arc->getFileName(), EC.message()); continue; } - if (ObjectFile *Obj = dyn_cast(child.get())) + if (ObjectFile *Obj = dyn_cast(&*ChildOrErr.get())) dumpObject(Obj); else reportError(Arc->getFileName(), readobj_error::unrecognized_file_format); } } +/// @brief Dumps each object file in \a MachO Universal Binary; +static void dumpMachOUniversalBinary(const MachOUniversalBinary *UBinary) { + for (const MachOUniversalBinary::ObjectForArch &Obj : UBinary->objects()) { + ErrorOr> ObjOrErr = Obj.getAsObjectFile(); + if (ObjOrErr) + dumpObject(&*ObjOrErr.get()); + else if (ErrorOr> AOrErr = Obj.getAsArchive()) + dumpArchive(&*AOrErr.get()); + else + reportError(UBinary->getFileName(), ObjOrErr.getError().message()); + } +} /// @brief Opens \a File and dumps it. static void dumpInput(StringRef File) { @@ -248,15 +343,19 @@ static void dumpInput(StringRef File) { } // Attempt to open the binary. - OwningPtr Binary; - if (error_code EC = createBinary(File, Binary)) { + ErrorOr> BinaryOrErr = createBinary(File); + if (std::error_code EC = BinaryOrErr.getError()) { reportError(File, EC); return; } + Binary &Binary = *BinaryOrErr.get().getBinary(); - if (Archive *Arc = dyn_cast(Binary.get())) + if (Archive *Arc = dyn_cast(&Binary)) dumpArchive(Arc); - else if (ObjectFile *Obj = dyn_cast(Binary.get())) + else if (MachOUniversalBinary *UBinary = + dyn_cast(&Binary)) + dumpMachOUniversalBinary(UBinary); + else if (ObjectFile *Obj = dyn_cast(&Binary)) dumpObject(Obj); else reportError(File, readobj_error::unrecognized_file_format); @@ -283,5 +382,5 @@ int main(int argc, const char *argv[]) { std::for_each(opts::InputFilenames.begin(), opts::InputFilenames.end(), dumpInput); - return 0; + return ReturnValue; }