diff --git a/test/Object/objdump-disassembly-inline-relocations.test b/test/Object/objdump-disassembly-inline-relocations.test new file mode 100644 index 00000000000..91f2e48f623 --- /dev/null +++ b/test/Object/objdump-disassembly-inline-relocations.test @@ -0,0 +1,32 @@ +RUN: llvm-objdump -d -r %p/TestObjectFiles/trivial-object-test.coff-i386 \ +RUN: | FileCheck %s -check-prefix COFF-i386 +RUN: llvm-objdump -d -r %p/TestObjectFiles/trivial-object-test.coff-x86-64 \ +RUN: | FileCheck %s -check-prefix COFF-x86-64 + +COFF-i386: file format COFF-i386 +COFF-i386: Disassembly of section .text: +COFF-i386: 0: 83 ec 0c subl $12, %esp +COFF-i386: 3: c7 44 24 08 00 00 00 00 movl $0, 8(%esp) +COFF-i386: b: c7 04 24 00 00 00 00 movl $0, (%esp) +COFF-i386: e: IMAGE_REL_I386_DIR32 L_.str +COFF-i386: 12: e8 00 00 00 00 calll 0 +COFF-i386: 13: IMAGE_REL_I386_REL32 _puts +COFF-i386: 17: e8 00 00 00 00 calll 0 +COFF-i386: 18: IMAGE_REL_I386_REL32 _SomeOtherFunction +COFF-i386: 1c: 8b 44 24 08 movl 8(%esp), %eax +COFF-i386: 20: 83 c4 0c addl $12, %esp +COFF-i386: 23: c3 ret + +COFF-x86-64: file format COFF-x86-64 +COFF-x86-64: Disassembly of section .text: +COFF-x86-64: 0: 48 83 ec 28 subq $40, %rsp +COFF-x86-64: 4: c7 44 24 24 00 00 00 00 movl $0, 36(%rsp) +COFF-x86-64: c: 48 8d 0d 00 00 00 00 leaq (%rip), %rcx +COFF-x86-64: f: IMAGE_REL_AMD64_REL32 L.str +COFF-x86-64: 13: e8 00 00 00 00 callq 0 +COFF-x86-64: 14: IMAGE_REL_AMD64_REL32 puts +COFF-x86-64: 18: e8 00 00 00 00 callq 0 +COFF-x86-64: 19: IMAGE_REL_AMD64_REL32 SomeOtherFunction +COFF-x86-64: 1d: 8b 44 24 24 movl 36(%rsp), %eax +COFF-x86-64: 21: 48 83 c4 28 addq $40, %rsp +COFF-x86-64: 25: c3 ret diff --git a/tools/llvm-objdump/llvm-objdump.cpp b/tools/llvm-objdump/llvm-objdump.cpp index e2a583be818..4ae13be3cdc 100644 --- a/tools/llvm-objdump/llvm-objdump.cpp +++ b/tools/llvm-objdump/llvm-objdump.cpp @@ -144,7 +144,14 @@ void llvm::DumpBytes(StringRef bytes) { outs() << output; } -static void DisassembleObject(const ObjectFile *Obj) { +static 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; + return a_addr < b_addr; +} + +static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { const Target *TheTarget = GetTarget(Obj); if (!TheTarget) { // GetTarget prints out stuff. @@ -164,6 +171,9 @@ static void DisassembleObject(const ObjectFile *Obj) { if (error(i->isText(text))) break; if (!text) continue; + uint64_t SectionAddr; + if (error(i->getAddress(SectionAddr))) break; + // Make a list of all the symbols in this section. std::vector > Symbols; for (symbol_iterator si = Obj->begin_symbols(), @@ -182,6 +192,20 @@ static void DisassembleObject(const ObjectFile *Obj) { // Sort the symbols by address, just in case they didn't come in that way. array_pod_sort(Symbols.begin(), Symbols.end()); + // Make a list of all the relocations for this section. + std::vector Rels; + if (InlineRelocs) { + for (relocation_iterator ri = i->begin_relocations(), + re = i->end_relocations(); + ri != re; ri.increment(ec)) { + if (error(ec)) break; + Rels.push_back(*ri); + } + } + + // Sort relocations by address. + std::sort(Rels.begin(), Rels.end(), RelocAddressLess); + StringRef name; if (error(i->getName(name))) break; outs() << "Disassembly of section " << name << ':'; @@ -231,6 +255,8 @@ static void DisassembleObject(const ObjectFile *Obj) { uint64_t SectSize; if (error(i->getSize(SectSize))) break; + std::vector::const_iterator rel_cur = Rels.begin(); + std::vector::const_iterator rel_end = Rels.end(); // Disassemble symbol by symbol. for (unsigned si = 0, se = Symbols.size(); si != se; ++si) { uint64_t Start = Symbols[si].first; @@ -259,9 +285,7 @@ static void DisassembleObject(const ObjectFile *Obj) { if (DisAsm->getInstruction(Inst, Size, memoryObject, Index, DebugOut, nulls())) { - uint64_t addr; - if (error(i->getAddress(addr))) break; - outs() << format("%8x:\t", addr + Index); + outs() << format("%8x:\t", SectionAddr + Index); DumpBytes(StringRef(Bytes.data() + Index, Size)); IP->printInst(&Inst, outs(), ""); outs() << "\n"; @@ -270,6 +294,24 @@ static void DisassembleObject(const ObjectFile *Obj) { if (Size == 0) Size = 1; // skip illegible bytes } + + // Print relocation for instruction. + while (rel_cur != rel_end) { + uint64_t addr; + SmallString<16> name; + SmallString<32> val; + if (error(rel_cur->getAddress(addr))) goto skip_print_rel; + // Stop when rel_cur's address is past the current instruction. + if (addr > Index + Size) break; + if (error(rel_cur->getTypeName(name))) goto skip_print_rel; + if (error(rel_cur->getValueString(val))) goto skip_print_rel; + + outs() << format("\t\t\t%8x: ", SectionAddr + addr) << name << "\t" + << val << "\n"; + + skip_print_rel: + ++rel_cur; + } } } } @@ -330,8 +372,8 @@ static void PrintSectionHeaders(const ObjectFile *o) { static void DumpObject(const ObjectFile *o) { if (Disassemble) - DisassembleObject(o); - if (Relocations) + DisassembleObject(o, Relocations); + if (Relocations && !Disassemble) PrintRelocations(o); if (SectionHeaders) PrintSectionHeaders(o);