From d20e4a1d68aa8e14c4e524e4d4eeb4445acac401 Mon Sep 17 00:00:00 2001 From: DianQK Date: Sat, 22 Oct 2022 20:39:21 +0800 Subject: [PATCH] [DebugInfo] Fix potential CU mismatch for attachRangesOrLowHighPC When a CU attaches some ranges for a subprogram or an inlined code, the CU should be that of the subprogram/inlined code that was emitted. If not, then these emitted ranges will use the incorrect base of the CU in `emitRangeList`. A reproducible example is: When linking these two LLVM IRs, dsymutil will report no mapping for range or inconsistent range data warnings. `foo.swift` ```swift import AppKit.NSLayoutConstraint public class Foo { public var c: Int { get { Int(NSLayoutConstraint().constant) } set { } } } ``` `main.swift` ```swift // no mapping for range let f: Foo! = nil // inconsistent range data //let l: Foo = Foo() ``` Reviewed By: dblaikie Differential Revision: https://reviews.llvm.org/D136039 --- llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp | 12 ++++- llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h | 1 + .../DebugInfo/Generic/cross-cu-inlining-ranges.ll | 61 ++++++++++++++++++++++ 3 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 llvm/test/DebugInfo/Generic/cross-cu-inlining-ranges.ll diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp index 81e688e..190d7c5 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -445,7 +445,12 @@ void DwarfCompileUnit::attachLowHighPC(DIE &D, const MCSymbol *Begin, // scope then create and insert DIEs for these variables. DIE &DwarfCompileUnit::updateSubprogramScopeDIE(const DISubprogram *SP) { DIE *SPDie = getOrCreateSubprogramDIE(SP, includeMinimalInlineScopes()); + auto *ContextCU = static_cast(SPDie->getUnit()); + return ContextCU->updateSubprogramScopeDIEImpl(SP, SPDie); +} +DIE &DwarfCompileUnit::updateSubprogramScopeDIEImpl(const DISubprogram *SP, + DIE *SPDie) { SmallVector BB_List; // If basic block sections are on, ranges for each basic block section has // to be emitted separately. @@ -1015,6 +1020,7 @@ sortLocalVars(SmallVectorImpl &Input) { DIE &DwarfCompileUnit::constructSubprogramScopeDIE(const DISubprogram *Sub, LexicalScope *Scope) { DIE &ScopeDIE = updateSubprogramScopeDIE(Sub); + auto *ContextCU = static_cast(ScopeDIE.getUnit()); if (Scope) { assert(!Scope->getInlinedAt()); @@ -1022,8 +1028,10 @@ DIE &DwarfCompileUnit::constructSubprogramScopeDIE(const DISubprogram *Sub, // Collect lexical scope children first. // ObjectPointer might be a local (non-argument) local variable if it's a // block's synthetic this pointer. - if (DIE *ObjectPointer = createAndAddScopeChildren(Scope, ScopeDIE)) - addDIEEntry(ScopeDIE, dwarf::DW_AT_object_pointer, *ObjectPointer); + if (DIE *ObjectPointer = + ContextCU->createAndAddScopeChildren(Scope, ScopeDIE)) + ContextCU->addDIEEntry(ScopeDIE, dwarf::DW_AT_object_pointer, + *ObjectPointer); } // If this is a variadic function, add an unspecified parameter. diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h index 7a1bea4..7d87f35 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h @@ -192,6 +192,7 @@ public: /// variables in this scope then create and insert DIEs for these /// variables. DIE &updateSubprogramScopeDIE(const DISubprogram *SP); + DIE &updateSubprogramScopeDIEImpl(const DISubprogram *SP, DIE *SPDie); void constructScopeDIE(LexicalScope *Scope, DIE &ParentScopeDIE); diff --git a/llvm/test/DebugInfo/Generic/cross-cu-inlining-ranges.ll b/llvm/test/DebugInfo/Generic/cross-cu-inlining-ranges.ll new file mode 100644 index 0000000..da5dd6c --- /dev/null +++ b/llvm/test/DebugInfo/Generic/cross-cu-inlining-ranges.ll @@ -0,0 +1,61 @@ +; RUN: %llc_dwarf %s -O0 -filetype=obj -o %t.o +; RUN: llvm-dwarfdump %t.o --debug-info --verify + +; We want to check that when the CU attaches ranges use the correct ContextCU. +; In the following example, after accessing `@foo`, `bar` an `inlined_baz` are created in `foo.swift` CU. +; Setting ranges in `@bar` will then use `bar.swift` CU. +; An incorrect address is eventually calculated based on Base. + +; The origin code is: +; foo.swift +; import AppKit.NSLayoutConstraint +; public class Foo { +; public var c: Int { +; get { +; Int(NSLayoutConstraint().constant) +; } +; set { +; } +; } +; } +; main.swift +; // no mapping for range +; let f: Foo! = nil + +; After LTO, `main.swift` will create a global variable, then `Foo` (and relative DIE) created in `main.swift` CU. + +define void @foo() !dbg !6 { + ret void, !dbg !9 +} + +define void @bar(i32* %0) !dbg !15 { + store i32 1, i32* %0, align 4, !dbg !16 + store i32 1, i32* %0, align 4, !dbg !21 + ret void, !dbg !16 +} + +!llvm.dbg.cu = !{!0, !2} +!llvm.module.flags = !{!4, !5} + +!0 = distinct !DICompileUnit(language: DW_LANG_Swift, file: !1, isOptimized: true, runtimeVersion: 5, emissionKind: FullDebug) +!1 = !DIFile(filename: "foo.swift", directory: "") +!2 = distinct !DICompileUnit(language: DW_LANG_Swift, file: !3, isOptimized: true, runtimeVersion: 5, emissionKind: FullDebug) +!3 = !DIFile(filename: "bar.swift", directory: "") +!4 = !{i32 7, !"Dwarf Version", i32 4} +!5 = !{i32 2, !"Debug Info Version", i32 3} +!6 = distinct !DISubprogram(name: "foo", scope: !0, type: !7, spFlags: DISPFlagDefinition, unit: !0) +!7 = !DISubroutineType(types: !8) +!8 = !{} +!9 = !DILocation(line: 0, scope: !10, inlinedAt: !13) +!10 = distinct !DISubprogram(name: "init", scope: !12, file: !11, type: !7, spFlags: DISPFlagDefinition, unit: !0) +!11 = !DIFile(filename: "", directory: "") +!12 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Type", file: !3, runtimeLang: DW_LANG_Swift, identifier: "Type") +!13 = !DILocation(line: 0, scope: !14) +!14 = distinct !DILexicalBlock(scope: !6, file: !1) +!15 = distinct !DISubprogram(name: "bar", scope: !12, type: !7, spFlags: DISPFlagDefinition, unit: !2) +!16 = !DILocation(line: 0, scope: !17, inlinedAt: !19) +!17 = distinct !DILexicalBlock(scope: !18, file: !3) +!18 = distinct !DISubprogram(name: "inlined_baz", scope: !12, file: !3, type: !7, spFlags: DISPFlagDefinition, unit: !2) +!19 = !DILocation(line: 0, scope: !20) +!20 = distinct !DILexicalBlock(scope: !15, file: !3) +!21 = !DILocation(line: 0, scope: !15) -- 2.7.4