From e497728e76146c70019c58817fdb33e3d52e6cc8 Mon Sep 17 00:00:00 2001 From: "Michael J. Spencer" Date: Sat, 8 Oct 2011 00:18:30 +0000 Subject: [PATCH] llvm-objdump: Add relocation and archive support. llvm-svn: 141451 --- test/Object/objdump-relocations.test | 24 +++++ tools/llvm-objdump/llvm-objdump.cpp | 131 +++++++++++++++++++++------ tools/llvm-objdump/llvm-objdump.h | 1 - 3 files changed, 127 insertions(+), 29 deletions(-) create mode 100644 test/Object/objdump-relocations.test diff --git a/test/Object/objdump-relocations.test b/test/Object/objdump-relocations.test new file mode 100644 index 00000000000..cd90d7a8fb3 --- /dev/null +++ b/test/Object/objdump-relocations.test @@ -0,0 +1,24 @@ +RUN: llvm-objdump -r %p/TestObjectFiles/trivial-object-test.coff-i386 \ +RUN: | FileCheck %s -check-prefix COFF-i386 +RUN: llvm-objdump -r %p/TestObjectFiles/trivial-object-test.coff-x86-64 \ +RUN: | FileCheck %s -check-prefix COFF-x86-64 +RUN: llvm-objdump -r %p/TestObjectFiles/trivial-object-test.elf-i386 \ +RUN: | FileCheck %s -check-prefix ELF-i386 +RUN: llvm-objdump -r %p/TestObjectFiles/trivial-object-test.elf-x86-64 \ +RUN: | FileCheck %s -check-prefix ELF-x86-64 + +COFF-i386: IMAGE_REL_I386_DIR32 L_.str +COFF-i386: IMAGE_REL_I386_REL32 _puts +COFF-i386: IMAGE_REL_I386_REL32 _SomeOtherFunction + +COFF-x86-64: IMAGE_REL_AMD64_REL32 L.str +COFF-x86-64: IMAGE_REL_AMD64_REL32 puts +COFF-x86-64: IMAGE_REL_AMD64_REL32 SomeOtherFunction + +ELF-i386: R_386_32 +ELF-i386: R_386_PC32 +ELF-i386: R_386_PC32 + +ELF-x86-64: R_X86_64_32S .rodata.str1.1 +ELF-x86-64: R_X86_64_PC32 puts +ELF-x86-64: R_X86_64_PC32 SomeOtherFunction diff --git a/tools/llvm-objdump/llvm-objdump.cpp b/tools/llvm-objdump/llvm-objdump.cpp index bb4a77bc796..e9231d0a066 100644 --- a/tools/llvm-objdump/llvm-objdump.cpp +++ b/tools/llvm-objdump/llvm-objdump.cpp @@ -15,6 +15,7 @@ #include "llvm-objdump.h" #include "MCFunction.h" +#include "llvm/Object/Archive.h" #include "llvm/Object/ObjectFile.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/Triple.h" @@ -27,8 +28,10 @@ #include "llvm/MC/MCInstrDesc.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/Format.h" #include "llvm/Support/GraphWriter.h" #include "llvm/Support/Host.h" @@ -57,6 +60,9 @@ static cl::alias Disassembled("d", cl::desc("Alias for --disassemble"), cl::aliasopt(Disassemble)); +static cl::opt +Relocations("r", cl::desc("Display the relocation entries in the file")); + static cl::opt MachO("macho", cl::desc("Use MachO specific object file parser")); static cl::alias @@ -131,17 +137,8 @@ void llvm::DumpBytes(StringRef bytes) { outs() << output; } -void llvm::DisassembleInputLibObject(StringRef Filename) { - OwningPtr Buff; - - if (error_code ec = MemoryBuffer::getFileOrSTDIN(Filename, Buff)) { - errs() << ToolName << ": " << Filename << ": " << ec.message() << "\n"; - return; - } - - OwningPtr Obj(ObjectFile::createObjectFile(Buff.take())); - - const Target *TheTarget = GetTarget(Obj.get()); +static void DisassembleObject(const ObjectFile *Obj) { + const Target *TheTarget = GetTarget(Obj); if (!TheTarget) { // GetTarget prints out stuff. return; @@ -151,13 +148,13 @@ void llvm::DisassembleInputLibObject(StringRef Filename) { InstrAnalysis(TheTarget->createMCInstrAnalysis(InstrInfo)); outs() << '\n'; - outs() << Filename + outs() << Obj->getFileName() << ":\tfile format " << Obj->getFileFormatName() << "\n\n"; error_code ec; for (section_iterator i = Obj->begin_sections(), - e = Obj->end_sections(); - i != e; i.increment(ec)) { + e = Obj->end_sections(); + i != e; i.increment(ec)) { if (error(ec)) break; bool text; if (error(i->isText(text))) break; @@ -166,8 +163,8 @@ void llvm::DisassembleInputLibObject(StringRef Filename) { // Make a list of all the symbols in this section. std::vector > Symbols; for (symbol_iterator si = Obj->begin_symbols(), - se = Obj->end_symbols(); - si != se; si.increment(ec)) { + se = Obj->end_symbols(); + si != se; si.increment(ec)) { bool contains; if (!error(i->containsSymbol(*si, contains)) && contains) { uint64_t Address; @@ -198,14 +195,16 @@ void llvm::DisassembleInputLibObject(StringRef Filename) { return; } - OwningPtr STI(TheTarget->createMCSubtargetInfo(TripleName, "", "")); + OwningPtr STI( + TheTarget->createMCSubtargetInfo(TripleName, "", "")); if (!STI) { errs() << "error: no subtarget info for target " << TripleName << "\n"; return; } - OwningPtr DisAsm(TheTarget->createMCDisassembler(*STI)); + OwningPtr DisAsm( + TheTarget->createMCDisassembler(*STI)); if (!DisAsm) { errs() << "error: no disassembler for target " << TripleName << "\n"; return; @@ -215,7 +214,8 @@ void llvm::DisassembleInputLibObject(StringRef Filename) { OwningPtr IP(TheTarget->createMCInstPrinter( AsmPrinterVariant, *AsmInfo, *STI)); if (!IP) { - errs() << "error: no instruction printer for target " << TripleName << '\n'; + errs() << "error: no instruction printer for target " << TripleName + << '\n'; return; } @@ -260,6 +260,87 @@ void llvm::DisassembleInputLibObject(StringRef Filename) { } } +static void PrintRelocations(const ObjectFile *o) { + error_code ec; + for (section_iterator si = o->begin_sections(), se = o->end_sections(); + si != se; si.increment(ec)){ + if (error(ec)) return; + if (si->begin_relocations() == si->end_relocations()) + continue; + StringRef secname; + if (error(si->getName(secname))) continue; + outs() << "RELOCATION RECORDS FOR [" << secname << "]:\n"; + for (relocation_iterator ri = si->begin_relocations(), + re = si->end_relocations(); + ri != re; ri.increment(ec)) { + if (error(ec)) return; + + uint64_t address; + SmallString<32> relocname; + SmallString<32> valuestr; + if (error(ri->getTypeName(relocname))) continue; + if (error(ri->getAddress(address))) continue; + if (error(ri->getValueString(valuestr))) continue; + outs() << address << " " << relocname << " " << valuestr << "\n"; + } + outs() << "\n"; + } +} + +static void DumpObject(const ObjectFile *o) { + if (Disassemble) + DisassembleObject(o); + if (Relocations) + PrintRelocations(o); +} + +/// @brief Dump each object file in \a a; +static void DumpArchive(const Archive *a) { + for (Archive::child_iterator i = a->begin_children(), + e = a->end_children(); i != e; ++i) { + OwningPtr child; + if (error_code ec = i->getAsBinary(child)) { + errs() << ToolName << ": '" << a->getFileName() << "': " << ec.message() + << ".\n"; + continue; + } + if (ObjectFile *o = dyn_cast(child.get())) + DumpObject(o); + else + errs() << ToolName << ": '" << a->getFileName() << "': " + << "Unrecognized file type.\n"; + } +} + +/// @brief Open file and figure out how to dump it. +static void DumpInput(StringRef file) { + // If file isn't stdin, check that it exists. + if (file != "-" && !sys::fs::exists(file)) { + errs() << ToolName << ": '" << file << "': " << "No such file\n"; + return; + } + + if (MachO && Disassemble) { + DisassembleInputMachO(file); + return; + } + + // Attempt to open the binary. + OwningPtr binary; + if (error_code ec = createBinary(file, binary)) { + errs() << ToolName << ": '" << file << "': " << ec.message() << ".\n"; + return; + } + + if (Archive *a = dyn_cast(binary.get())) { + DumpArchive(a); + } else if (ObjectFile *o = dyn_cast(binary.get())) { + DumpObject(o); + } else { + errs() << ToolName << ": '" << file << "': " << "Unrecognized file type.\n"; + } +} + int main(int argc, char **argv) { // Print a stack trace if we signal out. sys::PrintStackTraceOnErrorSignal(); @@ -281,19 +362,13 @@ int main(int argc, char **argv) { if (InputFilenames.size() == 0) InputFilenames.push_back("a.out"); - // -d is the only flag that is currently implemented, so just print help if - // it is not set. - if (!Disassemble) { + if (!Disassemble && !Relocations) { cl::PrintHelpMessage(); return 2; } - if (MachO) - std::for_each(InputFilenames.begin(), InputFilenames.end(), - DisassembleInputMachO); - else - std::for_each(InputFilenames.begin(), InputFilenames.end(), - DisassembleInputLibObject); + std::for_each(InputFilenames.begin(), InputFilenames.end(), + DumpInput); return 0; } diff --git a/tools/llvm-objdump/llvm-objdump.h b/tools/llvm-objdump/llvm-objdump.h index 63108d56ecd..75f852afbc7 100644 --- a/tools/llvm-objdump/llvm-objdump.h +++ b/tools/llvm-objdump/llvm-objdump.h @@ -22,7 +22,6 @@ extern cl::opt ArchName; // Various helper functions. void DumpBytes(StringRef bytes); -void DisassembleInputLibObject(StringRef Filename); void DisassembleInputMachO(StringRef Filename); class StringRefMemoryObject : public MemoryObject {