diff options
author | Tim Corringham <tcorring@amd.com> | 2018-03-26 17:06:33 +0000 |
---|---|---|
committer | Tim Corringham <tcorring@amd.com> | 2018-03-26 17:06:33 +0000 |
commit | 7116e8963df0f3507b86c36953b22d4958b299f1 (patch) | |
tree | 00d507be627881c4f6efcdaf189a7d6cd639d7f6 /llvm/tools/llvm-objdump/llvm-objdump.cpp | |
parent | fbfba29d74748b8fffd2f7cc654fb4c3659c8f67 (diff) | |
download | bcm5719-llvm-7116e8963df0f3507b86c36953b22d4958b299f1.tar.gz bcm5719-llvm-7116e8963df0f3507b86c36953b22d4958b299f1.zip |
[AMDGPU] Improve disassembler error handling
Summary:
llvm-objdump now disassembles unrecognised opcodes as data, using
the .long directive. We treat unrecognised opcodes as being 32 bit
values, so move along 4 bytes rather than the single byte which
previously resulted in a cascade of bogus disassembly following an
unrecognised opcode.
While no solution can always disassemble code that contains
embedded data correctly this provides a significant improvement.
The disassembler will now cope with an arbitrary length section
as it no longer truncates it to a multiple of 4 bytes, and will
use the .byte directive for trailing bytes.
Subscribers: arsenm, kzhuravl, wdng, nhaehnle, yaxunl, dstuttard, tpr, t-tye, llvm-commits
Differential Revision: https://reviews.llvm.org/D44685
llvm-svn: 328553
Diffstat (limited to 'llvm/tools/llvm-objdump/llvm-objdump.cpp')
-rw-r--r-- | llvm/tools/llvm-objdump/llvm-objdump.cpp | 49 |
1 files changed, 33 insertions, 16 deletions
diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp index 7764c1d6e10..53b720e3a1b 100644 --- a/llvm/tools/llvm-objdump/llvm-objdump.cpp +++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp @@ -595,23 +595,42 @@ public: if (SP && (PrintSource || PrintLines)) SP->printSourceLine(OS, Address); - if (!MI) { - OS << " <unknown>"; - return; - } + typedef support::ulittle32_t U32; - SmallString<40> InstStr; - raw_svector_ostream IS(InstStr); + if (MI) { + SmallString<40> InstStr; + raw_svector_ostream IS(InstStr); - IP.printInst(MI, IS, "", STI); + IP.printInst(MI, IS, "", STI); - OS << left_justify(IS.str(), 60) << format("// %012" PRIX64 ": ", Address); - typedef support::ulittle32_t U32; - for (auto D : makeArrayRef(reinterpret_cast<const U32*>(Bytes.data()), - Bytes.size() / sizeof(U32))) - // D should be explicitly casted to uint32_t here as it is passed - // by format to snprintf as vararg. - OS << format("%08" PRIX32 " ", static_cast<uint32_t>(D)); + OS << left_justify(IS.str(), 60); + } else { + // an unrecognized encoding - this is probably data so represent it + // using the .long directive, or .byte directive if fewer than 4 bytes + // remaining + if (Bytes.size() >= 4) { + OS << format("\t.long 0x%08" PRIx32 " ", + static_cast<uint32_t>(*reinterpret_cast<const U32*>(Bytes.data()))); + OS.indent(42); + } else { + OS << format("\t.byte 0x%02" PRIx8, Bytes[0]); + for (unsigned int i = 1; i < Bytes.size(); i++) + OS << format(", 0x%02" PRIx8, Bytes[i]); + OS.indent(55 - (6 * Bytes.size())); + } + } + + OS << format("// %012" PRIX64 ": ", Address); + if (Bytes.size() >=4) { + for (auto D : makeArrayRef(reinterpret_cast<const U32*>(Bytes.data()), + Bytes.size() / sizeof(U32))) + // D should be explicitly casted to uint32_t here as it is passed + // by format to snprintf as vararg. + OS << format("%08" PRIX32 " ", static_cast<uint32_t>(D)); + } else { + for (unsigned int i = 0; i < Bytes.size(); i++) + OS << format("%02" PRIX8 " ", Bytes[i]); + } if (!Annot.empty()) OS << "// " << Annot; @@ -1459,8 +1478,6 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { End = StopAddress - SectionAddr; if (Obj->isELF() && Obj->getArch() == Triple::amdgcn) { - // make size 4 bytes folded - End = Start + ((End - Start) & ~0x3ull); if (std::get<2>(Symbols[si]) == ELF::STT_AMDGPU_HSA_KERNEL) { // skip amd_kernel_code_t at the begining of kernel symbol (256 bytes) Start += 256; |