Path: blob/main/contrib/llvm-project/llvm/tools/llvm-objdump/SourcePrinter.h
35231 views
//===-- SourcePrinter.h - source interleaving utilities --------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#ifndef LLVM_TOOLS_LLVM_OBJDUMP_SOURCEPRINTER_H9#define LLVM_TOOLS_LLVM_OBJDUMP_SOURCEPRINTER_H1011#include "llvm/ADT/IndexedMap.h"12#include "llvm/ADT/StringSet.h"13#include "llvm/DebugInfo/DWARF/DWARFContext.h"14#include "llvm/DebugInfo/Symbolize/Symbolize.h"15#include "llvm/MC/MCRegisterInfo.h"16#include "llvm/MC/MCSubtargetInfo.h"17#include "llvm/Support/FormattedStream.h"18#include <unordered_map>19#include <vector>2021namespace llvm {22namespace objdump {2324/// Stores a single expression representing the location of a source-level25/// variable, along with the PC range for which that expression is valid.26struct LiveVariable {27DWARFLocationExpression LocExpr;28const char *VarName;29DWARFUnit *Unit;30const DWARFDie FuncDie;3132LiveVariable(const DWARFLocationExpression &LocExpr, const char *VarName,33DWARFUnit *Unit, const DWARFDie FuncDie)34: LocExpr(LocExpr), VarName(VarName), Unit(Unit), FuncDie(FuncDie) {}3536bool liveAtAddress(object::SectionedAddress Addr);3738void print(raw_ostream &OS, const MCRegisterInfo &MRI) const;39};4041/// Helper class for printing source variable locations alongside disassembly.42class LiveVariablePrinter {43// Information we want to track about one column in which we are printing a44// variable live range.45struct Column {46unsigned VarIdx = NullVarIdx;47bool LiveIn = false;48bool LiveOut = false;49bool MustDrawLabel = false;5051bool isActive() const { return VarIdx != NullVarIdx; }5253static constexpr unsigned NullVarIdx = std::numeric_limits<unsigned>::max();54};5556// All live variables we know about in the object/image file.57std::vector<LiveVariable> LiveVariables;5859// The columns we are currently drawing.60IndexedMap<Column> ActiveCols;6162const MCRegisterInfo &MRI;63const MCSubtargetInfo &STI;6465void addVariable(DWARFDie FuncDie, DWARFDie VarDie);6667void addFunction(DWARFDie D);6869// Get the column number (in characters) at which the first live variable70// line should be printed.71unsigned getIndentLevel() const;7273// Indent to the first live-range column to the right of the currently74// printed line, and return the index of that column.75// TODO: formatted_raw_ostream uses "column" to mean a number of characters76// since the last \n, and we use it to mean the number of slots in which we77// put live variable lines. Pick a less overloaded word.78unsigned moveToFirstVarColumn(formatted_raw_ostream &OS);7980unsigned findFreeColumn();8182public:83LiveVariablePrinter(const MCRegisterInfo &MRI, const MCSubtargetInfo &STI)84: ActiveCols(Column()), MRI(MRI), STI(STI) {}8586void dump() const;8788void addCompileUnit(DWARFDie D);8990/// Update to match the state of the instruction between ThisAddr and91/// NextAddr. In the common case, any live range active at ThisAddr is92/// live-in to the instruction, and any live range active at NextAddr is93/// live-out of the instruction. If IncludeDefinedVars is false, then live94/// ranges starting at NextAddr will be ignored.95void update(object::SectionedAddress ThisAddr,96object::SectionedAddress NextAddr, bool IncludeDefinedVars);9798enum class LineChar {99RangeStart,100RangeMid,101RangeEnd,102LabelVert,103LabelCornerNew,104LabelCornerActive,105LabelHoriz,106};107const char *getLineChar(LineChar C) const;108109/// Print live ranges to the right of an existing line. This assumes the110/// line is not an instruction, so doesn't start or end any live ranges, so111/// we only need to print active ranges or empty columns. If AfterInst is112/// true, this is being printed after the last instruction fed to update(),113/// otherwise this is being printed before it.114void printAfterOtherLine(formatted_raw_ostream &OS, bool AfterInst);115116/// Print any live variable range info needed to the right of a117/// non-instruction line of disassembly. This is where we print the variable118/// names and expressions, with thin line-drawing characters connecting them119/// to the live range which starts at the next instruction. If MustPrint is120/// true, we have to print at least one line (with the continuation of any121/// already-active live ranges) because something has already been printed122/// earlier on this line.123void printBetweenInsts(formatted_raw_ostream &OS, bool MustPrint);124125/// Print the live variable ranges to the right of a disassembled instruction.126void printAfterInst(formatted_raw_ostream &OS);127};128129class SourcePrinter {130protected:131DILineInfo OldLineInfo;132const object::ObjectFile *Obj = nullptr;133std::unique_ptr<symbolize::LLVMSymbolizer> Symbolizer;134// File name to file contents of source.135std::unordered_map<std::string, std::unique_ptr<MemoryBuffer>> SourceCache;136// Mark the line endings of the cached source.137std::unordered_map<std::string, std::vector<StringRef>> LineCache;138// Keep track of missing sources.139StringSet<> MissingSources;140// Only emit 'invalid debug info' warning once.141bool WarnedInvalidDebugInfo = false;142143private:144bool cacheSource(const DILineInfo &LineInfoFile);145146void printLines(formatted_raw_ostream &OS, const DILineInfo &LineInfo,147StringRef Delimiter, LiveVariablePrinter &LVP);148149void printSources(formatted_raw_ostream &OS, const DILineInfo &LineInfo,150StringRef ObjectFilename, StringRef Delimiter,151LiveVariablePrinter &LVP);152153// Returns line source code corresponding to `LineInfo`.154// Returns empty string if source code cannot be found.155StringRef getLine(const DILineInfo &LineInfo, StringRef ObjectFilename);156157public:158SourcePrinter() = default;159SourcePrinter(const object::ObjectFile *Obj, StringRef DefaultArch);160virtual ~SourcePrinter() = default;161virtual void printSourceLine(formatted_raw_ostream &OS,162object::SectionedAddress Address,163StringRef ObjectFilename,164LiveVariablePrinter &LVP,165StringRef Delimiter = "; ");166};167168} // namespace objdump169} // namespace llvm170171#endif172173174