From 2b38f589301d7defef6099b57ecf45139010a5a7 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Tue, 26 Jul 2022 09:20:46 +0100 Subject: [llvm-objdump,ARM] Add PrettyPrinters for Arm and AArch64. Most Arm disassemblers, including GNU objdump and Arm's own `fromelf`, emit an instruction's raw encoding as a 32-bit words or (for Thumb) one or two 16-bit halfwords, in logical order rather than according to their storage endianness. This is generally easier to read: it matches the encoding diagrams in the architecture spec, it matches the value you'd write in a `.inst` directive, and it means that fields within the instruction encoding that span more than one byte (such as branch offsets or `SVC` immediates) can be read directly in the encoding without having to mentally reverse the bytes. llvm-objdump already has a system of PrettyPrinter subclasses which makes it easy for a target to drop in its own preferred formatting. This patch adds pretty-printers for all the Arm targets, so that llvm-objdump will display Arm instruction encodings in their preferred layout instead of little-endian and bytewise. Reviewed By: DavidSpickett Differential Revision: https://reviews.llvm.org/D130358 --- llvm/tools/llvm-objdump/llvm-objdump.cpp | 109 +++++++++++++++++++++++++++++-- 1 file changed, 104 insertions(+), 5 deletions(-) (limited to 'llvm/tools/llvm-objdump/llvm-objdump.cpp') diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp index 5feebc5..cb83645 100644 --- a/llvm/tools/llvm-objdump/llvm-objdump.cpp +++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp @@ -466,6 +466,15 @@ static void printRelocation(formatted_raw_ostream &OS, StringRef FileName, OS << format(Fmt.data(), Address) << Name << "\t" << Val; } +static void AlignToInstStartColumn(size_t Start, const MCSubtargetInfo &STI, + raw_ostream &OS) { + // The output of printInst starts with a tab. Print some spaces so that + // the tab has 1 column and advances to the target tab stop. + unsigned TabStop = getInstStartColumn(STI); + unsigned Column = OS.tell() - Start; + OS.indent(Column < TabStop - 1 ? TabStop - 1 - Column : 7 - Column % 8); +} + class PrettyPrinter { public: virtual ~PrettyPrinter() = default; @@ -487,11 +496,7 @@ public: dumpBytes(Bytes, OS); } - // The output of printInst starts with a tab. Print some spaces so that - // the tab has 1 column and advances to the target tab stop. - unsigned TabStop = getInstStartColumn(STI); - unsigned Column = OS.tell() - Start; - OS.indent(Column < TabStop - 1 ? TabStop - 1 - Column : 7 - Column % 8); + AlignToInstStartColumn(Start, STI, OS); if (MI) { // See MCInstPrinter::printInst. On targets where a PC relative immediate @@ -664,6 +669,91 @@ public: }; BPFPrettyPrinter BPFPrettyPrinterInst; +class ARMPrettyPrinter : public PrettyPrinter { +public: + void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef Bytes, + object::SectionedAddress Address, formatted_raw_ostream &OS, + StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP, + StringRef ObjectFilename, std::vector *Rels, + LiveVariablePrinter &LVP) override { + if (SP && (PrintSource || PrintLines)) + SP->printSourceLine(OS, Address, ObjectFilename, LVP); + LVP.printBetweenInsts(OS, false); + + size_t Start = OS.tell(); + if (LeadingAddr) + OS << format("%8" PRIx64 ":", Address.Address); + if (ShowRawInsn) { + size_t Pos = 0, End = Bytes.size(); + if (STI.checkFeatures("+thumb-mode")) { + for (; Pos + 2 <= End; Pos += 2) + OS << ' ' + << format_hex_no_prefix( + llvm::support::endian::read( + Bytes.data() + Pos, llvm::support::little), + 4); + } else { + for (; Pos + 4 <= End; Pos += 4) + OS << ' ' + << format_hex_no_prefix( + llvm::support::endian::read( + Bytes.data() + Pos, llvm::support::little), + 8); + } + if (Pos < End) { + OS << ' '; + dumpBytes(Bytes.slice(Pos), OS); + } + } + + AlignToInstStartColumn(Start, STI, OS); + + if (MI) { + IP.printInst(MI, Address.Address, "", STI, OS); + } else + OS << "\t"; + } +}; +ARMPrettyPrinter ARMPrettyPrinterInst; + +class AArch64PrettyPrinter : public PrettyPrinter { +public: + void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef Bytes, + object::SectionedAddress Address, formatted_raw_ostream &OS, + StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP, + StringRef ObjectFilename, std::vector *Rels, + LiveVariablePrinter &LVP) override { + if (SP && (PrintSource || PrintLines)) + SP->printSourceLine(OS, Address, ObjectFilename, LVP); + LVP.printBetweenInsts(OS, false); + + size_t Start = OS.tell(); + if (LeadingAddr) + OS << format("%8" PRIx64 ":", Address.Address); + if (ShowRawInsn) { + size_t Pos = 0, End = Bytes.size(); + for (; Pos + 4 <= End; Pos += 4) + OS << ' ' + << format_hex_no_prefix( + llvm::support::endian::read(Bytes.data() + Pos, + llvm::support::little), + 8); + if (Pos < End) { + OS << ' '; + dumpBytes(Bytes.slice(Pos), OS); + } + } + + AlignToInstStartColumn(Start, STI, OS); + + if (MI) { + IP.printInst(MI, Address.Address, "", STI, OS); + } else + OS << "\t"; + } +}; +AArch64PrettyPrinter AArch64PrettyPrinterInst; + PrettyPrinter &selectPrettyPrinter(Triple const &Triple) { switch(Triple.getArch()) { default: @@ -675,6 +765,15 @@ PrettyPrinter &selectPrettyPrinter(Triple const &Triple) { case Triple::bpfel: case Triple::bpfeb: return BPFPrettyPrinterInst; + case Triple::arm: + case Triple::armeb: + case Triple::thumb: + case Triple::thumbeb: + return ARMPrettyPrinterInst; + case Triple::aarch64: + case Triple::aarch64_be: + case Triple::aarch64_32: + return AArch64PrettyPrinterInst; } } } -- cgit v1.1