From 7116e8963df0f3507b86c36953b22d4958b299f1 Mon Sep 17 00:00:00 2001 From: Tim Corringham Date: Mon, 26 Mar 2018 17:06:33 +0000 Subject: [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 --- llvm/tools/llvm-objdump/llvm-objdump.cpp | 49 +++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 16 deletions(-) (limited to 'llvm/tools/llvm-objdump') 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 << " "; - 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(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(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(*reinterpret_cast(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(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(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; -- cgit v1.2.3