/// where a problem occurred in case an error is returned.
Error parse(DWARFDataExtractor Data, uint64_t *Offset, uint64_t EndOffset);
- void dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH,
- unsigned IndentLevel = 1) const;
+ void dump(raw_ostream &OS, DIDumpOptions DumpOpts, const MCRegisterInfo *MRI,
+ bool IsEH, unsigned IndentLevel = 1) const;
private:
std::vector<Instruction> Instructions;
static ArrayRef<OperandType[2]> getOperandTypes();
/// Print \p Opcode's operand number \p OperandIdx which has value \p Operand.
- void printOperand(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH,
+ void printOperand(raw_ostream &OS, DIDumpOptions DumpOpts,
+ const MCRegisterInfo *MRI, bool IsEH,
const Instruction &Instr, unsigned OperandIdx,
uint64_t Operand) const;
};
CFIProgram &cfis() { return CFIs; }
/// Dump the instructions in this CFI fragment
- virtual void dump(raw_ostream &OS, const MCRegisterInfo *MRI,
- bool IsEH) const = 0;
+ virtual void dump(raw_ostream &OS, DIDumpOptions DumpOpts,
+ const MCRegisterInfo *MRI, bool IsEH) const = 0;
protected:
const FrameKind Kind;
uint32_t getLSDAPointerEncoding() const { return LSDAPointerEncoding; }
- void dump(raw_ostream &OS, const MCRegisterInfo *MRI,
+ void dump(raw_ostream &OS, DIDumpOptions DumpOpts, const MCRegisterInfo *MRI,
bool IsEH) const override;
private:
uint64_t getAddressRange() const { return AddressRange; }
Optional<uint64_t> getLSDAAddress() const { return LSDAAddress; }
- void dump(raw_ostream &OS, const MCRegisterInfo *MRI,
+ void dump(raw_ostream &OS, DIDumpOptions DumpOpts, const MCRegisterInfo *MRI,
bool IsEH) const override;
static bool classof(const FrameEntry *FE) { return FE->getKind() == FK_FDE; }
~DWARFDebugFrame();
/// Dump the section data into the given stream.
- void dump(raw_ostream &OS, const MCRegisterInfo *MRI,
+ void dump(raw_ostream &OS, DIDumpOptions DumpOpts, const MCRegisterInfo *MRI,
Optional<uint64_t> Offset) const;
/// Parse the section from raw data. \p Data is assumed to contain the whole
#define LLVM_DEBUGINFO_DWARFEXPRESSION_H
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/iterator.h"
#include "llvm/ADT/iterator_range.h"
-#include "llvm/ADT/Optional.h"
#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/DebugInfo/DIContext.h"
#include "llvm/Support/DataExtractor.h"
namespace llvm {
bool extract(DataExtractor Data, uint8_t AddressSize, uint64_t Offset,
Optional<dwarf::DwarfFormat> Format);
bool isError() { return Error; }
- bool print(raw_ostream &OS, const DWARFExpression *Expr,
- const MCRegisterInfo *RegInfo, DWARFUnit *U, bool isEH);
+ bool print(raw_ostream &OS, DIDumpOptions DumpOpts,
+ const DWARFExpression *Expr, const MCRegisterInfo *RegInfo,
+ DWARFUnit *U, bool isEH);
bool verify(DWARFUnit *U);
};
iterator begin() const { return iterator(this, 0); }
iterator end() const { return iterator(this, Data.getData().size()); }
- void print(raw_ostream &OS, const MCRegisterInfo *RegInfo, DWARFUnit *U,
+ void print(raw_ostream &OS, DIDumpOptions DumpOpts,
+ const MCRegisterInfo *RegInfo, DWARFUnit *U,
bool IsEH = false) const;
/// Print the expression in a format intended to be compact and useful to a
shouldDump(Explicit, ".debug_frame", DIDT_ID_DebugFrame,
DObj->getFrameSection().Data)) {
if (Expected<const DWARFDebugFrame *> DF = getDebugFrame())
- (*DF)->dump(OS, getRegisterInfo(), *Off);
+ (*DF)->dump(OS, DumpOpts, getRegisterInfo(), *Off);
else
RecoverableErrorHandler(DF.takeError());
}
shouldDump(Explicit, ".eh_frame", DIDT_ID_DebugFrame,
DObj->getEHFrameSection().Data)) {
if (Expected<const DWARFDebugFrame *> DF = getEHFrame())
- (*DF)->dump(OS, getRegisterInfo(), *Off);
+ (*DF)->dump(OS, DumpOpts, getRegisterInfo(), *Off);
else
RecoverableErrorHandler(DF.takeError());
}
}
/// Print \p Opcode's operand number \p OperandIdx which has value \p Operand.
-void CFIProgram::printOperand(raw_ostream &OS, const MCRegisterInfo *MRI,
- bool IsEH, const Instruction &Instr,
- unsigned OperandIdx, uint64_t Operand) const {
+void CFIProgram::printOperand(raw_ostream &OS, DIDumpOptions DumpOpts,
+ const MCRegisterInfo *MRI, bool IsEH,
+ const Instruction &Instr, unsigned OperandIdx,
+ uint64_t Operand) const {
assert(OperandIdx < 2);
uint8_t Opcode = Instr.Opcode;
OperandType Type = getOperandTypes()[Opcode][OperandIdx];
case OT_Expression:
assert(Instr.Expression && "missing DWARFExpression object");
OS << " ";
- Instr.Expression->print(OS, MRI, nullptr, IsEH);
+ Instr.Expression->print(OS, DumpOpts, MRI, nullptr, IsEH);
break;
}
}
-void CFIProgram::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH,
+void CFIProgram::dump(raw_ostream &OS, DIDumpOptions DumpOpts,
+ const MCRegisterInfo *MRI, bool IsEH,
unsigned IndentLevel) const {
for (const auto &Instr : Instructions) {
uint8_t Opcode = Instr.Opcode;
OS.indent(2 * IndentLevel);
OS << CallFrameString(Opcode, Arch) << ":";
for (unsigned i = 0; i < Instr.Ops.size(); ++i)
- printOperand(OS, MRI, IsEH, Instr, i, Instr.Ops[i]);
+ printOperand(OS, DumpOpts, MRI, IsEH, Instr, i, Instr.Ops[i]);
OS << '\n';
}
}
return DW_CIE_ID;
}
-void CIE::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH) const {
+void CIE::dump(raw_ostream &OS, DIDumpOptions DumpOpts,
+ const MCRegisterInfo *MRI, bool IsEH) const {
// A CIE with a zero length is a terminator entry in the .eh_frame section.
if (IsEH && Length == 0) {
OS << format("%08" PRIx64, Offset) << " ZERO terminator\n";
OS << "\n";
}
OS << "\n";
- CFIs.dump(OS, MRI, IsEH);
+ CFIs.dump(OS, DumpOpts, MRI, IsEH);
OS << "\n";
}
-void FDE::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH) const {
+void FDE::dump(raw_ostream &OS, DIDumpOptions DumpOpts,
+ const MCRegisterInfo *MRI, bool IsEH) const {
OS << format("%08" PRIx64, Offset)
<< format(" %0*" PRIx64, IsDWARF64 ? 16 : 8, Length)
<< format(" %0*" PRIx64, IsDWARF64 && !IsEH ? 16 : 8, CIEPointer)
OS << " Format: " << FormatString(IsDWARF64) << "\n";
if (LSDAAddress)
OS << format(" LSDA Address: %016" PRIx64 "\n", *LSDAAddress);
- CFIs.dump(OS, MRI, IsEH);
+ CFIs.dump(OS, DumpOpts, MRI, IsEH);
OS << "\n";
}
return nullptr;
}
-void DWARFDebugFrame::dump(raw_ostream &OS, const MCRegisterInfo *MRI,
+void DWARFDebugFrame::dump(raw_ostream &OS, DIDumpOptions DumpOpts,
+ const MCRegisterInfo *MRI,
Optional<uint64_t> Offset) const {
if (Offset) {
if (auto *Entry = getEntryAtOffset(*Offset))
- Entry->dump(OS, MRI, IsEH);
+ Entry->dump(OS, DumpOpts, MRI, IsEH);
return;
}
OS << "\n";
for (const auto &Entry : Entries)
- Entry->dump(OS, MRI, IsEH);
+ Entry->dump(OS, DumpOpts, MRI, IsEH);
}
}
}
-static void dumpExpression(raw_ostream &OS, ArrayRef<uint8_t> Data,
- bool IsLittleEndian, unsigned AddressSize,
- const MCRegisterInfo *MRI, DWARFUnit *U) {
+static void dumpExpression(raw_ostream &OS, DIDumpOptions DumpOpts,
+ ArrayRef<uint8_t> Data, bool IsLittleEndian,
+ unsigned AddressSize, const MCRegisterInfo *MRI,
+ DWARFUnit *U) {
DWARFDataExtractor Extractor(Data, IsLittleEndian, AddressSize);
// Note. We do not pass any format to DWARFExpression, even if the
// corresponding unit is known. For now, there is only one operation,
// DW_OP_call_ref, which depends on the format; it is rarely used, and
// is unexpected in location tables.
- DWARFExpression(Extractor, AddressSize).print(OS, MRI, U);
+ DWARFExpression(Extractor, AddressSize).print(OS, DumpOpts, MRI, U);
}
bool DWARFLocationTable::dumpLocationList(uint64_t *Offset, raw_ostream &OS,
E.Kind != dwarf::DW_LLE_base_addressx &&
E.Kind != dwarf::DW_LLE_end_of_list) {
OS << ": ";
- dumpExpression(OS, E.Loc, Data.isLittleEndian(), Data.getAddressSize(),
- MRI, U);
+ dumpExpression(OS, DumpOpts, E.Loc, Data.isLittleEndian(),
+ Data.getAddressSize(), MRI, U);
}
return true;
});
DataExtractor Data(StringRef((const char *)Expr.data(), Expr.size()),
Ctx.isLittleEndian(), 0);
DWARFExpression(Data, U->getAddressByteSize(), U->getFormParams().Format)
- .print(OS, MRI, U);
+ .print(OS, DumpOpts, MRI, U);
return;
}
}
static void prettyPrintBaseTypeRef(DWARFUnit *U, raw_ostream &OS,
- uint64_t Operands[2], unsigned Operand) {
+ DIDumpOptions DumpOpts, uint64_t Operands[2],
+ unsigned Operand) {
assert(Operand < 2 && "operand out of bounds");
auto Die = U->getDIEForOffset(U->getOffset() + Operands[Operand]);
if (Die && Die.getTag() == dwarf::DW_TAG_base_type) {
- OS << format(" (0x%08" PRIx64 ")", U->getOffset() + Operands[Operand]);
+ OS << " (";
+ if (DumpOpts.Verbose)
+ OS << format("0x%08" PRIx64 " -> ", Operands[Operand]);
+ OS << format("0x%08" PRIx64 ")", U->getOffset() + Operands[Operand]);
if (auto Name = Die.find(dwarf::DW_AT_name))
OS << " \"" << Name->getAsCString() << "\"";
} else {
}
}
-static bool prettyPrintRegisterOp(DWARFUnit *U, raw_ostream &OS, uint8_t Opcode,
+static bool prettyPrintRegisterOp(DWARFUnit *U, raw_ostream &OS,
+ DIDumpOptions DumpOpts, uint8_t Opcode,
uint64_t Operands[2],
const MCRegisterInfo *MRI, bool isEH) {
if (!MRI)
OS << ' ' << RegName;
if (Opcode == DW_OP_regval_type)
- prettyPrintBaseTypeRef(U, OS, Operands, 1);
+ prettyPrintBaseTypeRef(U, OS, DumpOpts, Operands, 1);
return true;
}
}
return false;
}
-bool DWARFExpression::Operation::print(raw_ostream &OS,
+bool DWARFExpression::Operation::print(raw_ostream &OS, DIDumpOptions DumpOpts,
const DWARFExpression *Expr,
const MCRegisterInfo *RegInfo,
- DWARFUnit *U,
- bool isEH) {
+ DWARFUnit *U, bool isEH) {
if (Error) {
OS << "<decoding error>";
return false;
(Opcode >= DW_OP_reg0 && Opcode <= DW_OP_reg31) ||
Opcode == DW_OP_bregx || Opcode == DW_OP_regx ||
Opcode == DW_OP_regval_type)
- if (prettyPrintRegisterOp(U, OS, Opcode, Operands, RegInfo, isEH))
+ if (prettyPrintRegisterOp(U, OS, DumpOpts, Opcode, Operands, RegInfo, isEH))
return true;
for (unsigned Operand = 0; Operand < 2; ++Operand) {
if (Opcode == DW_OP_convert && Operands[Operand] == 0)
OS << " 0x0";
else
- prettyPrintBaseTypeRef(U, OS, Operands, Operand);
+ prettyPrintBaseTypeRef(U, OS, DumpOpts, Operands, Operand);
} else if (Size == Operation::WasmLocationArg) {
assert(Operand == 1);
switch (Operands[0]) {
return true;
}
-void DWARFExpression::print(raw_ostream &OS, const MCRegisterInfo *RegInfo,
- DWARFUnit *U, bool IsEH) const {
+void DWARFExpression::print(raw_ostream &OS, DIDumpOptions DumpOpts,
+ const MCRegisterInfo *RegInfo, DWARFUnit *U,
+ bool IsEH) const {
uint32_t EntryValExprSize = 0;
for (auto &Op : *this) {
- if (!Op.print(OS, this, RegInfo, U, IsEH)) {
+ if (!Op.print(OS, DumpOpts, this, RegInfo, U, IsEH)) {
uint64_t FailOffset = Op.getEndOffset();
while (FailOffset < Data.getData().size())
OS << format(" %02x", Data.getU8(&FailOffset));
; RUN: llc -mtriple=x86_64-pc-linux-gnu -dwarf-version=5 -filetype=obj -O0 < %s -debugger-tune=lldb -dwarf-op-convert=Enable -split-dwarf-file=baz.dwo | llvm-dwarfdump - \
; RUN: | FileCheck %s --check-prefix=CONV --check-prefix=SPLITCONV --check-prefix=SPLIT "--implicit-check-not={{DW_TAG|NULL}}"
+; RUN: %llc_dwarf -dwarf-version=5 -filetype=obj -O0 < %s -debugger-tune=gdb | llvm-dwarfdump -v -debug-info - \
+; RUN: | FileCheck %s --check-prefix=VERBOSE --check-prefix=CONV "--implicit-check-not={{DW_TAG|NULL}}"
+
+
; SPLITCONV: Compile Unit:{{.*}} DWO_id = 0xe91d8d1d7f9782c0
; SPLIT: DW_TAG_skeleton_unit
; CONV: DW_TAG_compile_unit
; CONV:[[SIG8:.*]]: DW_TAG_base_type
-; CONV-NEXT:DW_AT_name ("DW_ATE_signed_8")
-; CONV-NEXT:DW_AT_encoding (DW_ATE_signed)
-; CONV-NEXT:DW_AT_byte_size (0x01)
+; CONV-NEXT:DW_AT_name {{.*}}"DW_ATE_signed_8")
+; CONV-NEXT:DW_AT_encoding {{.*}}DW_ATE_signed)
+; CONV-NEXT:DW_AT_byte_size {{.*}}0x01)
; CONV-NOT: DW_AT
; CONV:[[SIG32:.*]]: DW_TAG_base_type
-; CONV-NEXT:DW_AT_name ("DW_ATE_signed_32")
-; CONV-NEXT:DW_AT_encoding (DW_ATE_signed)
-; CONV-NEXT:DW_AT_byte_size (0x04)
+; CONV-NEXT:DW_AT_name {{.*}}"DW_ATE_signed_32")
+; CONV-NEXT:DW_AT_encoding {{.*}}DW_ATE_signed)
+; CONV-NEXT:DW_AT_byte_size {{.*}}0x04)
; CONV-NOT: DW_AT
; CONV: DW_TAG_subprogram
; CONV: DW_TAG_formal_parameter
; CONV: DW_TAG_variable
-; CONV: DW_AT_location (
-; CONV: {{.*}}, DW_OP_convert ([[SIG8]]) "DW_ATE_signed_8", DW_OP_convert ([[SIG32]]) "DW_ATE_signed_32", DW_OP_stack_value)
-; CONV: DW_AT_name ("y")
+; CONV: DW_AT_location {{.*}}DW_OP_constu 0x20, DW_OP_convert (
+; VERBOSE-SAME: [[SIG8]] ->
+; CONV-SAME: [[SIG8]]) "DW_ATE_signed_8", DW_OP_convert (
+; VERBOSE-SAME: [[SIG32]] ->
+; CONV-SAME: [[SIG32]]) "DW_ATE_signed_32", DW_OP_stack_value)
+; CONV: DW_AT_name {{.*}}"y")
; CONV: NULL
; CONV: DW_TAG_base_type
-; CONV: DW_AT_name ("signed char")
+; CONV: DW_AT_name {{.*}}"signed char")
; CONV: DW_TAG_base_type
-; CONV: DW_AT_name ("int")
+; CONV: DW_AT_name {{.*}}"int")
; CONV: NULL
; NOCONV: DW_TAG_compile_unit
W.getOStream() << "\n";
W.startLine() << "Program:\n";
W.indent();
- Entry.cfis().dump(W.getOStream(), nullptr, W.getIndentLevel());
+ Entry.cfis().dump(W.getOStream(), DIDumpOptions(), nullptr,
+ W.getIndentLevel());
W.unindent();
W.unindent();
W.getOStream() << "\n";
StringRef ExpectedFirstLine) {
std::string Output;
raw_string_ostream OS(Output);
- TestCIE.dump(OS, /*MRI=*/nullptr, IsEH);
+ TestCIE.dump(OS, DIDumpOptions(), /*MRI=*/nullptr, IsEH);
OS.flush();
StringRef FirstLine = StringRef(Output).split('\n').first;
EXPECT_EQ(FirstLine, ExpectedFirstLine);
StringRef ExpectedFirstLine) {
std::string Output;
raw_string_ostream OS(Output);
- TestFDE.dump(OS, /*MRI=*/nullptr, IsEH);
+ TestFDE.dump(OS, DIDumpOptions(), /*MRI=*/nullptr, IsEH);
OS.flush();
StringRef FirstLine = StringRef(Output).split('\n').first;
EXPECT_EQ(FirstLine, ExpectedFirstLine);