Index: tools/llvm-objdump/CMakeLists.txt =================================================================== --- tools/llvm-objdump/CMakeLists.txt +++ tools/llvm-objdump/CMakeLists.txt @@ -5,10 +5,12 @@ AllTargetsInfos CodeGen DebugInfoDWARF + DebugInfoPDB MC MCDisassembler Object Support + Symbolize ) add_llvm_tool(llvm-objdump Index: tools/llvm-objdump/llvm-objdump.cpp =================================================================== --- tools/llvm-objdump/llvm-objdump.cpp +++ tools/llvm-objdump/llvm-objdump.cpp @@ -23,6 +23,7 @@ #include "llvm/ADT/Triple.h" #include "llvm/CodeGen/FaultMaps.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" +#include "llvm/DebugInfo/Symbolize/Symbolize.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCDisassembler/MCDisassembler.h" @@ -60,6 +61,7 @@ #include #include #include +#include using namespace llvm; using namespace object; @@ -188,6 +190,18 @@ cl::values(clEnumValN(DIDT_Frames, "frames", ".debug_frame"), clEnumValEnd)); +cl::opt PrintSource("source", + cl::desc("Display source inlined with disassembly")); + +cl::alias PrintSourceShort("S", cl::desc("Alias for -source"), + cl::aliasopt(PrintSource)); + +cl::opt + PrintLines("line-numbers", + cl::desc("Display source line numbers with disassembly")); + +cl::alias PrintLinesShort("l", cl::desc("Alias for -line-numbers"), + cl::aliasopt(PrintLines)); static StringRef ToolName; namespace { @@ -361,12 +375,56 @@ namespace { class PrettyPrinter { + DILineInfo OldLineInfo; + // Storage for the source + std::unordered_map> SourceCache; + // Mark the line endings of the cached source + std::unordered_map> LineCache; public: virtual ~PrettyPrinter(){} virtual void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef Bytes, uint64_t Address, raw_ostream &OS, StringRef Annot, - MCSubtargetInfo const &STI) { + MCSubtargetInfo const &STI, DILineInfo &LineInfo) { + if (!(LineInfo.FileName == "") && + OldLineInfo.Line != LineInfo.Line) { + if (PrintLines) + OS << ";;; " << LineInfo.FileName << ":" << LineInfo.Line << "\n"; + if (PrintSource) { + // Cache line numbers with the associated character pointers in the + // buffer + if (SourceCache.find(LineInfo.FileName) == SourceCache.end()) { + auto BufferOrError = MemoryBuffer::getFile(LineInfo.FileName); + if (BufferOrError) { + // Chomp the file to get lines + size_t BufferSize = (*BufferOrError)->getBufferSize(); + const char *BufferStart = (*BufferOrError)->getBufferStart(); + for (const char *Start = BufferStart, *End = BufferStart; + End < BufferStart + BufferSize; End++) { + if (*End == '\r' && *(End + 1) == '\n') { + LineCache[LineInfo.FileName].push_back( + StringRef(Start, End - Start)); + End++; + Start = End + 1; + } else if (*End == '\n' || End == BufferStart + BufferSize - 1) { + LineCache[LineInfo.FileName].push_back( + StringRef(Start, End - Start)); + Start = End + 1; + } + } + SourceCache[LineInfo.FileName] = std::move(*BufferOrError); + } + } + auto FileBuffer = SourceCache.find(LineInfo.FileName); + if (FileBuffer != SourceCache.end()) { + auto LineBuffer = LineCache.find(LineInfo.FileName); + if (LineBuffer != LineCache.end()) + OS << ";;; " << LineBuffer->second[LineInfo.Line - 1].ltrim() + << "\n"; + } + } + OldLineInfo = LineInfo; + } OS << format("%8" PRIx64 ":", Address); if (!NoShowRawInsn) { OS << "\t"; @@ -392,10 +450,9 @@ OS << format("%08" PRIx32, opcode); } } - void printInst(MCInstPrinter &IP, const MCInst *MI, - ArrayRef Bytes, uint64_t Address, - raw_ostream &OS, StringRef Annot, - MCSubtargetInfo const &STI) override { + void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef Bytes, + uint64_t Address, raw_ostream &OS, StringRef Annot, + MCSubtargetInfo const &STI, DILineInfo &LineInfo) override { if (!MI) { printLead(Bytes, Address, OS); OS << " "; @@ -440,13 +497,9 @@ class AMDGCNPrettyPrinter : public PrettyPrinter { public: - void printInst(MCInstPrinter &IP, - const MCInst *MI, - ArrayRef Bytes, - uint64_t Address, - raw_ostream &OS, - StringRef Annot, - MCSubtargetInfo const &STI) override { + void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef Bytes, + uint64_t Address, raw_ostream &OS, StringRef Annot, + MCSubtargetInfo const &STI, DILineInfo &LineInfo) override { if (!MI) { OS << " "; return; @@ -989,6 +1042,15 @@ StringRef Fmt = Obj->getBytesInAddress() > 4 ? "\t\t%016" PRIx64 ": " : "\t\t\t%08" PRIx64 ": "; + std::unique_ptr Symbolizer = nullptr; + DILineInfo LineInfo; + if (PrintSource || PrintLines) { + symbolize::LLVMSymbolizer::Options SymbolizerOpts( + DILineInfoSpecifier::FunctionNameKind::None, true, false, false, + TheTarget->getName()); + Symbolizer.reset(new symbolize::LLVMSymbolizer(SymbolizerOpts)); + } + // Create a mapping, RelocSecs = SectionRelocMap[S], where sections // in RelocSecs contain the relocations for section S. std::error_code EC; @@ -1206,14 +1268,25 @@ if (Index >= End) break; - bool Disassembled = DisAsm->getInstruction(Inst, Size, Bytes.slice(Index), - SectionAddr + Index, DebugOut, - CommentStream); + bool Disassembled = DisAsm->getInstruction( + Inst, Size, Bytes.slice(Index), SectionAddr + Index, DebugOut, + CommentStream); if (Size == 0) Size = 1; + + LineInfo = DILineInfo(); + if (Disassembled && Symbolizer) { + auto ExpectecLineInfo = + Symbolizer->symbolizeCode(Obj->getFileName(), SectionAddr + Index); + if (!ExpectecLineInfo) + consumeError(ExpectecLineInfo.takeError()); + else + LineInfo = *ExpectecLineInfo; + } + PIP.printInst(*IP, Disassembled ? &Inst : nullptr, Bytes.slice(Index, Size), - SectionAddr + Index, outs(), "", *STI); + SectionAddr + Index, outs(), "", *STI, LineInfo); outs() << CommentStream.str(); Comments.clear();