Skip to content

Commit c7c84b9

Browse files
committed
[DwarfDebug] Refuse to emit DW_OP_LLVM_arg values wider than 64 bits
DwarfExpression::addUnsignedConstant(const APInt &Value) only supports wider-than-64-bit values when it is used to emit a top-level DWARF expression representing the location of a variable. Before this change, it was possible to call addUnsignedConstant on >64 bit values within a subexpression when substituting DW_OP_LLVM_arg values. This can trigger an assertion failure (e.g. PR52584, PR52333) when it happens in a fragment (DW_OP_LLVM_fragment) expression, as addUnsignedConstant on >64 bit values splits the constant into separate DW_OP_pieces, which modifies DwarfExpression::OffsetInBits. This change papers over the assertion errors by bailing on overly wide DW_OP_LLVM_arg values. A more comprehensive fix might be to be to split wide values into pointer-sized fragments. [0] https://github.com/llvm/llvm-project/blob/e71fa03/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp#L799-L805 Patch by Ricky Zhou! Differential Revision: https://reviews.llvm.org/D115343
1 parent 5861cf7 commit c7c84b9

File tree

4 files changed

+66
-22
lines changed

4 files changed

+66
-22
lines changed

llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp

+17-8
Original file line numberDiff line numberDiff line change
@@ -789,7 +789,7 @@ DIE *DwarfCompileUnit::constructVariableDIEImpl(const DbgVariable &DV,
789789
const TargetRegisterInfo &TRI = *Asm->MF->getSubtarget().getRegisterInfo();
790790

791791
auto AddEntry = [&](const DbgValueLocEntry &Entry,
792-
DIExpressionCursor &Cursor) {
792+
DIExpressionCursor &Cursor) {
793793
if (Entry.isLocation()) {
794794
if (!DwarfExpr.addMachineRegExpression(TRI, Cursor,
795795
Entry.getLoc().getReg()))
@@ -798,11 +798,19 @@ DIE *DwarfCompileUnit::constructVariableDIEImpl(const DbgVariable &DV,
798798
// If there is an expression, emit raw unsigned bytes.
799799
DwarfExpr.addUnsignedConstant(Entry.getInt());
800800
} else if (Entry.isConstantFP()) {
801+
// DwarfExpression does not support arguments wider than 64 bits
802+
// (see PR52584).
803+
// TODO: Consider chunking expressions containing overly wide
804+
// arguments into separate pointer-sized fragment expressions.
801805
APInt RawBytes = Entry.getConstantFP()->getValueAPF().bitcastToAPInt();
802-
DwarfExpr.addUnsignedConstant(RawBytes);
806+
if (RawBytes.getBitWidth() > 64)
807+
return false;
808+
DwarfExpr.addUnsignedConstant(RawBytes.getZExtValue());
803809
} else if (Entry.isConstantInt()) {
804810
APInt RawBytes = Entry.getConstantInt()->getValue();
805-
DwarfExpr.addUnsignedConstant(RawBytes);
811+
if (RawBytes.getBitWidth() > 64)
812+
return false;
813+
DwarfExpr.addUnsignedConstant(RawBytes.getZExtValue());
806814
} else if (Entry.isTargetIndexLocation()) {
807815
TargetIndexLocation Loc = Entry.getTargetIndexLocation();
808816
// TODO TargetIndexLocation is a target-independent. Currently only the
@@ -815,11 +823,12 @@ DIE *DwarfCompileUnit::constructVariableDIEImpl(const DbgVariable &DV,
815823
return true;
816824
};
817825

818-
DwarfExpr.addExpression(
819-
std::move(Cursor),
820-
[&](unsigned Idx, DIExpressionCursor &Cursor) -> bool {
821-
return AddEntry(DVal->getLocEntries()[Idx], Cursor);
822-
});
826+
if (!DwarfExpr.addExpression(
827+
std::move(Cursor),
828+
[&](unsigned Idx, DIExpressionCursor &Cursor) -> bool {
829+
return AddEntry(DVal->getLocEntries()[Idx], Cursor);
830+
}))
831+
return VariableDie;
823832

824833
// Now attach the location information to the DIE.
825834
addBlock(*VariableDie, dwarf::DW_AT_location, DwarfExpr.finalize());

llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp

+6-5
Original file line numberDiff line numberDiff line change
@@ -463,15 +463,14 @@ static bool isMemoryLocation(DIExpressionCursor ExprCursor) {
463463
return true;
464464
}
465465

466-
void DwarfExpression::addExpression(DIExpressionCursor &&ExprCursor,
467-
unsigned FragmentOffsetInBits) {
466+
void DwarfExpression::addExpression(DIExpressionCursor &&ExprCursor) {
468467
addExpression(std::move(ExprCursor),
469468
[](unsigned Idx, DIExpressionCursor &Cursor) -> bool {
470469
llvm_unreachable("unhandled opcode found in expression");
471470
});
472471
}
473472

474-
void DwarfExpression::addExpression(
473+
bool DwarfExpression::addExpression(
475474
DIExpressionCursor &&ExprCursor,
476475
llvm::function_ref<bool(unsigned, DIExpressionCursor &)> InsertArg) {
477476
// Entry values can currently only cover the initial register location,
@@ -496,7 +495,7 @@ void DwarfExpression::addExpression(
496495
case dwarf::DW_OP_LLVM_arg:
497496
if (!InsertArg(Op->getArg(0), ExprCursor)) {
498497
LocationKind = Unknown;
499-
return;
498+
return false;
500499
}
501500
break;
502501
case dwarf::DW_OP_LLVM_fragment: {
@@ -527,7 +526,7 @@ void DwarfExpression::addExpression(
527526
setSubRegisterPiece(0, 0);
528527
// Reset the location description kind.
529528
LocationKind = Unknown;
530-
return;
529+
return true;
531530
}
532531
case dwarf::DW_OP_plus_uconst:
533532
assert(!isRegisterLocation());
@@ -630,6 +629,8 @@ void DwarfExpression::addExpression(
630629
if (isImplicitLocation() && !isParameterValue())
631630
// Turn this into an implicit location description.
632631
addStackValue();
632+
633+
return true;
633634
}
634635

635636
/// add masking operations to stencil out a subregister.

llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h

+10-9
Original file line numberDiff line numberDiff line change
@@ -340,16 +340,17 @@ class DwarfExpression {
340340
/// create one if necessary.
341341
unsigned getOrCreateBaseType(unsigned BitSize, dwarf::TypeKind Encoding);
342342

343+
/// Emit all remaining operations in the DIExpressionCursor. The
344+
/// cursor must not contain any DW_OP_LLVM_arg operations.
345+
void addExpression(DIExpressionCursor &&Expr);
346+
343347
/// Emit all remaining operations in the DIExpressionCursor.
344-
///
345-
/// \param FragmentOffsetInBits If this is one fragment out of multiple
346-
/// locations, this is the offset of the
347-
/// fragment inside the entire variable.
348-
void addExpression(DIExpressionCursor &&Expr,
349-
unsigned FragmentOffsetInBits = 0);
350-
void
351-
addExpression(DIExpressionCursor &&Expr,
352-
llvm::function_ref<bool(unsigned, DIExpressionCursor &)> InsertArg);
348+
/// DW_OP_LLVM_arg operations are resolved by calling (\p InsertArg).
349+
//
350+
/// \return false if any call to (\p InsertArg) returns false.
351+
bool addExpression(
352+
DIExpressionCursor &&Expr,
353+
llvm::function_ref<bool(unsigned, DIExpressionCursor &)> InsertArg);
353354

354355
/// If applicable, emit an empty DW_OP_piece / DW_OP_bit_piece to advance to
355356
/// the fragment described by \c Expr.

llvm/test/DebugInfo/X86/pr52584.ll

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
; RUN: llc -mtriple=x86_64-unknown-linux-gnu -filetype=obj -o - %s \
2+
; RUN: | llvm-dwarfdump - \
3+
; RUN: | FileCheck %s
4+
5+
; CHECK: DW_TAG_variable
6+
; CHECK-NOT: DW_AT_location
7+
; CHECK-NEXT: DW_AT_name ("arr")
8+
; CHECK-NOT: DW_AT_location
9+
; CHECK: DW_TAG
10+
define dso_local void @test() !dbg !4 {
11+
entry:
12+
call void @llvm.dbg.value(metadata !DIArgList(i128 0), metadata !7, metadata !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_stack_value, DW_OP_LLVM_fragment, 0, 127)), !dbg !12
13+
ret void, !dbg !12
14+
}
15+
16+
declare void @llvm.dbg.value(metadata, metadata, metadata)
17+
18+
!llvm.dbg.cu = !{!0}
19+
!llvm.module.flags = !{!2, !3}
20+
21+
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
22+
!1 = !DIFile(filename: "test.c", directory: "")
23+
!2 = !{i32 7, !"Dwarf Version", i32 4}
24+
!3 = !{i32 2, !"Debug Info Version", i32 3}
25+
!4 = distinct !DISubprogram(name: "test", scope: !1, file: !1, line: 1, type: !5, unit: !0)
26+
!5 = !DISubroutineType(types: !6)
27+
!6 = !{null}
28+
!7 = !DILocalVariable(name: "arr", scope: !4, file: !1, line: 1, type: !8)
29+
!8 = !DICompositeType(tag: DW_TAG_array_type, baseType: !9, size: 128, elements: !10)
30+
!9 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
31+
!10 = !{!11}
32+
!11 = !DISubrange(count: 16)
33+
!12 = !DILocation(line: 1, column: 1, scope: !4)

0 commit comments

Comments
 (0)