From 196b8cce4123556a6b7c8013e01ef6998fca84ec Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Wed, 20 Nov 2019 13:02:23 -0800 Subject: [PATCH 1/2] Fix an offset underflow bug in DwarfExpression when describing small values with subregisters DwarfExpression::addMachineReg() knows how to build a larger register that isn't expressible in DWARF by combining multiple subregisters. However, if the entire value fits into just one subregister, it would still emit the other subregisters, leading to all sorts of inconsistencies down the line. This patch fixes that by moving an already existing(!) check whether the subregister's offset is before the end of the value to the right place. rdar://problem/57294211 Differential Revision: https://reviews.llvm.org/D70508 (cherry picked from commit 5da385fb56cbe92d8bd8f53954056eca1829fe1b) --- .../CodeGen/AsmPrinter/DwarfExpression.cpp | 17 +++++---- .../DebugInfo/MIR/ARM/larger-subregister.mir | 36 +++++++++++++++++++ .../MC/X86/dwarf-size-field-overflow.test | 6 ++-- 3 files changed, 47 insertions(+), 12 deletions(-) create mode 100644 llvm/test/DebugInfo/MIR/ARM/larger-subregister.mir diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp index 1c5a244d7c5d3..a37e3c7c06c07 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp @@ -155,20 +155,18 @@ bool DwarfExpression::addMachineReg(const TargetRegisterInfo &TRI, CurSubReg.set(Offset, Offset + Size); // If this sub-register has a DWARF number and we haven't covered - // its range, emit a DWARF piece for it. - if (CurSubReg.test(Coverage)) { + // its range, and its range covers the value, emit a DWARF piece for it. + if (Offset < MaxSize && CurSubReg.test(Coverage)) { // Emit a piece for any gap in the coverage. if (Offset > CurPos) - DwarfRegs.push_back({-1, Offset - CurPos, "no DWARF register encoding"}); + DwarfRegs.push_back( + {-1, Offset - CurPos, "no DWARF register encoding"}); DwarfRegs.push_back( {Reg, std::min(Size, MaxSize - Offset), "sub-register"}); - if (Offset >= MaxSize) - break; - - // Mark it as emitted. - Coverage.set(Offset, Offset + Size); - CurPos = Offset + Size; } + // Mark it as emitted. + Coverage.set(Offset, Offset + Size); + CurPos = Offset + Size; } // Failed to find any DWARF encoding. if (CurPos == 0) @@ -391,6 +389,7 @@ void DwarfExpression::addExpression(DIExpressionCursor &&ExprCursor, // empty DW_OP_piece / DW_OP_bit_piece before we emitted the base // location. assert(OffsetInBits >= FragmentOffset && "fragment offset not added?"); + assert(SizeInBits >= OffsetInBits - FragmentOffset && "size underflow"); // If addMachineReg already emitted DW_OP_piece operations to represent // a super-register by splicing together sub-registers, subtract the size diff --git a/llvm/test/DebugInfo/MIR/ARM/larger-subregister.mir b/llvm/test/DebugInfo/MIR/ARM/larger-subregister.mir new file mode 100644 index 0000000000000..6fb944e8c97ce --- /dev/null +++ b/llvm/test/DebugInfo/MIR/ARM/larger-subregister.mir @@ -0,0 +1,36 @@ +# RUN: llc -start-before=livedebugvalues -filetype=obj -o - %s | \ +# RUN: llvm-dwarfdump -debug-info - | FileCheck %s +# +# In this test the first DBG_VALUE is 32 bits large and sits in 128-bit register Q8, +# which has to be decomposed into two 64-bit register D16, D17. +# This test ensures that the unused D17 is suppressed in the output. +# +# CHECK: .debug_info contents: +# CHECK: DW_TAG_formal_parameter +# CHECK-NEXT: DW_AT_location +# CHECK-NEXT: DW_OP_regx D16, DW_OP_piece 0x4, DW_OP_regx D15, DW_OP_bit_piece 0x20 0x20 +# CHECK-NEXT: DW_AT_name {{.*}}"boundingRect" +--- | + target triple = "thumbv7k-apple-watchos" + define swiftcc void @f() !dbg !5 { + ret void + } + !llvm.module.flags = !{!0} + !llvm.dbg.cu = !{!2} + !0 = !{i32 2, !"Debug Info Version", i32 3} + !2 = distinct !DICompileUnit(language: DW_LANG_Swift, file: !3, + isOptimized: true, runtimeVersion: 5, emissionKind: FullDebug, enums: !4, globals: !4, imports: !4) + !3 = !DIFile(filename: "t.swift", directory: "/") + !4 = !{} + !5 = distinct !DISubprogram(name: "f", scope: !3, file: !3, line: 388, type: !9, scopeLine: 388, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !4) + !9 = !DISubroutineType(types: !4) + !10 = !DILocation(line: 0, scope: !5) + !12 = !DILocalVariable(name: "boundingRect", arg: 1, scope: !5, file: !3, line: 388, type: !13) + !13 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !14) + !14 = !DICompositeType(tag: DW_TAG_structure_type, name: "CGRect", scope: !5, file: !3, line: 46, size: 128, elements: !4, runtimeLang: DW_LANG_Swift, identifier: "$sSo6CGRectVD") +name: 'f' +body: | + bb.0: + DBG_VALUE $s31, $noreg, !12, !DIExpression(DW_OP_LLVM_fragment, 32, 32), debug-location !10 + DBG_VALUE $q8, $noreg, !12, !DIExpression(DW_OP_LLVM_fragment, 0, 32), debug-location !10 + renamable $r0 = t2ADDri $r6, 144, 14, $noreg, $noreg, debug-location !10 diff --git a/llvm/test/MC/X86/dwarf-size-field-overflow.test b/llvm/test/MC/X86/dwarf-size-field-overflow.test index 72f3bd3a90038..090255268e190 100644 --- a/llvm/test/MC/X86/dwarf-size-field-overflow.test +++ b/llvm/test/MC/X86/dwarf-size-field-overflow.test @@ -1,7 +1,7 @@ # This test generates too many debug location entries to fit into 65KB required # by DWARF < 5. Check that the location is set to 0 instead of crashing. # -# RUN: %python %s 4000 | llc -mtriple=x86_64-apple-darwin -filetype=obj -o %t +# RUN: %python %s 10000 | llc -mtriple=x86_64-apple-darwin -filetype=obj -o %t # RUN: llvm-dwarfdump %t | FileCheck %s # # CHECK: 0x0000004d: DW_TAG_formal_parameter @@ -39,11 +39,11 @@ attributes #0 = {{ nounwind readnone speculatable }} !34 = !DILocation(line: 12, column: 8, scope: !24) """ -CALL = "call void @llvm.dbg.value(metadata i64 {0}, metadata !30, metadata !DIExpression(DW_OP_LLVM_fragment, {0}, 64)), !dbg !34" +CALL = "call void @llvm.dbg.value(metadata i64 {0}, metadata !30, metadata !DIExpression(DW_OP_LLVM_fragment, {1}, 8)), !dbg !34" if __name__ == '__main__': N = int(sys.argv[1]) calls = [] for i in range(0, N): - calls.append(CALL.format(i * 10**12)) + calls.append(CALL.format(i * 10**12, i*8)) print(SKELETON.format('\n'.join(calls))) From 7743452dd38fb55fbcb0f53bfed929128ebbecf6 Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Thu, 21 Nov 2019 08:32:42 -0800 Subject: [PATCH 2/2] Reduce the number of iterations in testcase. (NFC) (cherry picked from commit 1b9ef3bbb595206b0097b7adec2c1b69eae6fab4) --- llvm/test/MC/X86/dwarf-size-field-overflow.test | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/test/MC/X86/dwarf-size-field-overflow.test b/llvm/test/MC/X86/dwarf-size-field-overflow.test index 090255268e190..807de9aead27b 100644 --- a/llvm/test/MC/X86/dwarf-size-field-overflow.test +++ b/llvm/test/MC/X86/dwarf-size-field-overflow.test @@ -1,8 +1,8 @@ # This test generates too many debug location entries to fit into 65KB required # by DWARF < 5. Check that the location is set to 0 instead of crashing. # -# RUN: %python %s 10000 | llc -mtriple=x86_64-apple-darwin -filetype=obj -o %t -# RUN: llvm-dwarfdump %t | FileCheck %s +# RUN: %python %s 5750 | llc -mtriple=x86_64-apple-darwin -filetype=obj -o - \ +# RUN: | llvm-dwarfdump - | FileCheck %s # # CHECK: 0x0000004d: DW_TAG_formal_parameter # CHECK-NEXT: DW_AT_location (0x00000000