Index: llvm/include/llvm/DebugInfo/DWARF/DWARFExpression.h =================================================================== --- llvm/include/llvm/DebugInfo/DWARF/DWARFExpression.h +++ llvm/include/llvm/DebugInfo/DWARF/DWARFExpression.h @@ -15,6 +15,7 @@ #include "llvm/Support/DataExtractor.h" namespace llvm { +class DWARFDie; class DWARFUnit; class MCRegisterInfo; class raw_ostream; @@ -145,7 +146,8 @@ /// user, but not perfectly unambiguous, or capable of representing every /// valid DWARF expression. Returns true if the expression was sucessfully /// printed. - bool printCompact(raw_ostream &OS, const MCRegisterInfo &RegInfo); + bool printCompact(raw_ostream &OS, const MCRegisterInfo &RegInfo, + const DWARFDie FuncDie); bool verify(DWARFUnit *U); Index: llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp =================================================================== --- llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp +++ llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +#include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/DebugInfo/DWARF/DWARFExpression.h" #include "llvm/DebugInfo/DWARF/DWARFUnit.h" #include "llvm/BinaryFormat/Dwarf.h" @@ -367,7 +368,8 @@ static bool printCompactDWARFExpr(raw_ostream &OS, DWARFExpression::iterator I, const DWARFExpression::iterator E, - const MCRegisterInfo &MRI) { + const MCRegisterInfo &MRI, + const DWARFDie FuncDie = DWARFDie()) { SmallVector Stack; while (I != E) { @@ -410,7 +412,7 @@ ++I; raw_svector_ostream S(Stack.emplace_back().String); S << "entry("; - printCompactDWARFExpr(S, I, SubExprEnd, MRI); + printCompactDWARFExpr(S, I, SubExprEnd, MRI, FuncDie); S << ")"; I = SubExprEnd; continue; @@ -422,6 +424,30 @@ Stack.back().Kind = PrintedExpr::Value; break; } + case dwarf::DW_OP_fbreg: { + // Get the DW_AT_frame_base attribute from the function DIE and render + // that, plus an optional offset. + assert(FuncDie && "Cannot render DW_OP_fbreg without a function DIE"); + raw_svector_ostream S(Stack.emplace_back().String); + if (Optional FrameBaseAttr = + FuncDie.find(dwarf::DW_AT_frame_base)) { + StringRef FrameBaseStr( + (const char *)FrameBaseAttr->getAsBlock()->data(), + FrameBaseAttr->getAsBlock()->size()); + bool LittleEndian = FuncDie.getDwarfUnit()->getContext().isLittleEndian(); + DataExtractor FrameBaseData(FrameBaseStr, LittleEndian, 0); + DWARFExpression FrameBaseExpr( + FrameBaseData, FuncDie.getDwarfUnit()->getAddressByteSize()); + printCompactDWARFExpr(S, FrameBaseExpr.begin(), FrameBaseExpr.end(), MRI); + } else { + S << ""; + } + int64_t Offset = Op.getRawOperand(0); + if (Offset) + S << format("%+" PRId64, Offset); + + break; + } default: if (Opcode >= dwarf::DW_OP_reg0 && Opcode <= dwarf::DW_OP_reg31) { // DW_OP_reg: A register, with the register num implied by the @@ -461,7 +487,7 @@ assert(Stack.size() == 1 && "expected one value on stack"); - if (Stack.front().Kind == PrintedExpr::Address) + if (Stack.front().Kind == PrintedExpr::Address && FuncDie) OS << "[" << Stack.front().String << "]"; else OS << Stack.front().String; @@ -469,8 +495,9 @@ return true; } -bool DWARFExpression::printCompact(raw_ostream &OS, const MCRegisterInfo &MRI) { - return printCompactDWARFExpr(OS, begin(), end(), MRI); +bool DWARFExpression::printCompact(raw_ostream &OS, const MCRegisterInfo &MRI, + const DWARFDie FuncDie) { + return printCompactDWARFExpr(OS, begin(), end(), MRI, FuncDie); } } // namespace llvm Index: llvm/tools/llvm-objdump/llvm-objdump.cpp =================================================================== --- llvm/tools/llvm-objdump/llvm-objdump.cpp +++ llvm/tools/llvm-objdump/llvm-objdump.cpp @@ -593,7 +593,7 @@ DataExtractor Data({LocExpr.Expr.data(), LocExpr.Expr.size()}, Unit->getContext().isLittleEndian(), 0); DWARFExpression Expression(Data, Unit->getAddressByteSize()); - Expression.printCompact(OS, MRI); + Expression.printCompact(OS, MRI, FuncDie); } }; Index: llvm/unittests/DebugInfo/DWARF/DWARFExpressionCompactPrinterTest.cpp =================================================================== --- llvm/unittests/DebugInfo/DWARF/DWARFExpressionCompactPrinterTest.cpp +++ llvm/unittests/DebugInfo/DWARF/DWARFExpressionCompactPrinterTest.cpp @@ -43,15 +43,46 @@ MRI.reset(TheTarget->createMCRegInfo(TripleName)); } - void TestExprPrinter(ArrayRef ExprData, StringRef Expected); + void TestExprPrinter(ArrayRef ExprData, StringRef Expected, + ArrayRef FrameBaseExpr = {}); }; } // namespace void DWARFExpressionCompactPrinterTest::TestExprPrinter( - ArrayRef ExprData, StringRef Expected) { + ArrayRef ExprData, StringRef Expected, + ArrayRef FrameBaseExpr) { // If we didn't build ARM, do not run the test. if (!MRI) return; + // Build a minimal DWARF tree containing a DW_TAG_subprogram with a + // DW_AT_frame_base attribute. + auto ExpectedDG = + dwarfgen::Generator::create(Triple("armv8a-linux-gnueabi"), 4); + ASSERT_THAT_EXPECTED(ExpectedDG, Succeeded()); + dwarfgen::Generator *DG = ExpectedDG.get().get(); + { + dwarfgen::CompileUnit &CU = DG->addCompileUnit(); + dwarfgen::DIE CUDie = CU.getUnitDIE(); + dwarfgen::DIE FuncDie = CUDie.addChild(DW_TAG_subprogram); + FuncDie.addAttribute(DW_AT_frame_base, DW_FORM_block, FrameBaseExpr.data(), + FrameBaseExpr.size()); + } + + // Write the DWARF tree to an in-memory ELF file. + StringRef FileBytes = DG->generate(); + MemoryBufferRef FileBuffer(FileBytes, "dwarf"); + auto Obj = object::ObjectFile::createObjectFile(FileBuffer); + EXPECT_TRUE((bool)Obj); + + // Parse the DWARF objects out of the ELF file. + std::unique_ptr DwarfContext = DWARFContext::create(**Obj); + uint32_t NumCUs = DwarfContext->getNumCompileUnits(); + EXPECT_EQ(NumCUs, 1u); + DWARFCompileUnit *U = cast(DwarfContext->getUnitAtIndex(0)); + auto CUDie = U->getUnitDIE(false); + EXPECT_TRUE(CUDie.isValid()); + DWARFDie FuncDie = CUDie.getFirstChild(); + EXPECT_TRUE(FuncDie.isValid()); // Print the expression, passing in the subprogram DIE, and check that the // result is as expected. @@ -59,7 +90,7 @@ raw_string_ostream OS(Result); DataExtractor DE(ExprData, true, 8); DWARFExpression Expr(DE, 8); - Expr.printCompact(OS, *MRI); + Expr.printCompact(OS, *MRI, FuncDie); EXPECT_EQ(OS.str(), Expected); } @@ -113,3 +144,7 @@ {DW_OP_entry_value, 0x02, DW_OP_breg13, 0x10, DW_OP_stack_value}, "entry([SP+16])"); } + +TEST_F(DWARFExpressionCompactPrinterTest, Test_OP_fbreg) { + TestExprPrinter({DW_OP_fbreg, 0x8}, "[R11+8]", {DW_OP_reg11}); +}