diff --git a/llvm/lib/CodeGen/AsmPrinter/DebugLocStream.h b/llvm/lib/CodeGen/AsmPrinter/DebugLocStream.h --- a/llvm/lib/CodeGen/AsmPrinter/DebugLocStream.h +++ b/llvm/lib/CodeGen/AsmPrinter/DebugLocStream.h @@ -159,11 +159,17 @@ DbgVariable &V; const MachineInstr &MI; size_t ListIndex; + Optional TagOffset; public: ListBuilder(DebugLocStream &Locs, DwarfCompileUnit &CU, AsmPrinter &Asm, DbgVariable &V, const MachineInstr &MI) - : Locs(Locs), Asm(Asm), V(V), MI(MI), ListIndex(Locs.startList(&CU)) {} + : Locs(Locs), Asm(Asm), V(V), MI(MI), ListIndex(Locs.startList(&CU)), + TagOffset(None) {} + + void setTagOffset(uint8_t TO) { + TagOffset = TO; + } /// Finalize the list. /// diff --git a/llvm/lib/CodeGen/AsmPrinter/DebugLocStream.cpp b/llvm/lib/CodeGen/AsmPrinter/DebugLocStream.cpp --- a/llvm/lib/CodeGen/AsmPrinter/DebugLocStream.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DebugLocStream.cpp @@ -42,4 +42,6 @@ return; V.initializeDbgValue(&MI); V.setDebugLocListIndex(ListIndex); + if (TagOffset) + V.setDebugLocListTagOffset(*TagOffset); } diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -602,6 +602,10 @@ unsigned Offset = DV.getDebugLocListIndex(); if (Offset != ~0U) { addLocationList(*VariableDie, dwarf::DW_AT_location, Offset); + auto TagOffset = DV.getDebugLocListTagOffset(); + if (TagOffset) + addUInt(*VariableDie, dwarf::DW_AT_LLVM_tag_offset, dwarf::DW_FORM_data1, + *TagOffset); return VariableDie; } @@ -619,6 +623,10 @@ DwarfExpr.addUnsignedConstant(DVal->getInt()); DwarfExpr.addExpression(Expr); addBlock(*VariableDie, dwarf::DW_AT_location, DwarfExpr.finalize()); + if (DwarfExpr.TagOffset) + addUInt(*VariableDie, dwarf::DW_AT_LLVM_tag_offset, + dwarf::DW_FORM_data1, *DwarfExpr.TagOffset); + } else addConstantValue(*VariableDie, DVal->getInt(), DV.getType()); } else if (DVal->isConstantFP()) { @@ -1185,6 +1193,10 @@ // Now attach the location information to the DIE. addBlock(Die, Attribute, DwarfExpr.finalize()); + + if (DwarfExpr.TagOffset) + addUInt(Die, dwarf::DW_AT_LLVM_tag_offset, dwarf::DW_FORM_data1, + *DwarfExpr.TagOffset); } /// Start with the address based on the location provided, and generate the @@ -1215,6 +1227,10 @@ // Now attach the location information to the DIE. addBlock(Die, Attribute, DwarfExpr.finalize()); + + if (DwarfExpr.TagOffset) + addUInt(Die, dwarf::DW_AT_LLVM_tag_offset, dwarf::DW_FORM_data1, + *DwarfExpr.TagOffset); } /// Add a Dwarf loclistptr attribute data and value. diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -118,6 +118,9 @@ class DbgVariable : public DbgEntity { /// Offset in DebugLocs. unsigned DebugLocListIndex = ~0u; + /// DW_OP_LLVM_tag_offset value from DebugLocs. + Optional DebugLocListTagOffset; + /// Single value location description. std::unique_ptr ValueLoc = nullptr; @@ -174,6 +177,8 @@ void setDebugLocListIndex(unsigned O) { DebugLocListIndex = O; } unsigned getDebugLocListIndex() const { return DebugLocListIndex; } + void setDebugLocListTagOffset(uint8_t O) { DebugLocListTagOffset = O; } + Optional getDebugLocListTagOffset() const { return DebugLocListTagOffset; } StringRef getName() const { return getVariable()->getName(); } const DbgValueLoc *getValueLoc() const { return ValueLoc.get(); } /// Get the FI entries, sorted by fragment offset. diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -2270,6 +2270,8 @@ DwarfDebug::emitDebugLocValue(AP, BT, Value, DwarfExpr); } DwarfExpr.finalize(); + if (DwarfExpr.TagOffset) + List.setTagOffset(*DwarfExpr.TagOffset); } void DwarfDebug::emitDebugLocEntryLocation(const DebugLocStream::Entry &Entry, diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -1077,33 +1077,6 @@ return None; } -static Optional -getLocationFrameOffset(DWARFCompileUnit *CU, DWARFFormValue &FormValue, - Optional FrameBaseReg) { - if (Optional> Location = FormValue.getAsBlock()) { - return getExpressionFrameOffset(*Location, FrameBaseReg); - } else if (FormValue.isFormClass(DWARFFormValue::FC_SectionOffset)) { - uint64_t Offset = *FormValue.getAsSectionOffset(); - const DWARFLocationTable &LocTable = CU->getLocationTable(); - Optional FrameOffset; - Error E = LocTable.visitLocationList( - &Offset, [&](const DWARFLocationEntry &Entry) { - if (Entry.Kind == dwarf::DW_LLE_base_address || - Entry.Kind == dwarf::DW_LLE_base_addressx || - Entry.Kind == dwarf::DW_LLE_end_of_list) { - return true; - } - if ((FrameOffset = getExpressionFrameOffset(Entry.Loc, FrameBaseReg))) - return false; - return true; - }); - if (E) - return None; - return FrameOffset; - } - return None; -} - void DWARFContext::addLocalsForDie(DWARFCompileUnit *CU, DWARFDie Subprogram, DWARFDie Die, std::vector &Result) { if (Die.getTag() == DW_TAG_variable || @@ -1119,8 +1092,19 @@ (*Expr)[0] <= DW_OP_reg31) { FrameBaseReg = (*Expr)[0] - DW_OP_reg0; } - if (auto LocationAttr = Die.find(DW_AT_location)) - Local.FrameOffset = getLocationFrameOffset(CU, *LocationAttr, FrameBaseReg); + + if (Expected> Loc = + Die.getLocations(DW_AT_location)) { + for (const auto &Entry : *Loc) { + if (Optional FrameOffset = + getExpressionFrameOffset(Entry.Expr, FrameBaseReg)) { + Local.FrameOffset = *FrameOffset; + break; + } + } + } else { + consumeError(Loc.takeError()); + } if (auto TagOffsetAttr = Die.find(DW_AT_LLVM_tag_offset)) Local.TagOffset = TagOffsetAttr->getAsUnsignedConstant(); diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp @@ -495,8 +495,18 @@ return createStringError(inconvertibleErrorCode(), "No %s", dwarf::AttributeString(Attr).data()); - if (Optional Off = Location->getAsSectionOffset()) - return U->findLoclistFromOffset(*Off); + if (Optional Off = Location->getAsSectionOffset()) { + uint64_t Offset = *Off; + + if (Location->getForm() == DW_FORM_loclistx) { + if (auto LoclistOffset = U->getLoclistOffset(Offset)) + Offset = *LoclistOffset + getDwarfUnit()->getLocSectionBase(); + else + return createStringError(inconvertibleErrorCode(), + "Loclist table not found"); + } + return U->findLoclistFromOffset(Offset); + } if (Optional> Expr = Location->getAsBlock()) { return DWARFLocationExpressionsVector{ diff --git a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp --- a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp @@ -222,7 +222,7 @@ Value *untagPointer(IRBuilder<> &IRB, Value *PtrLong); bool instrumentStack( SmallVectorImpl &Allocas, - DenseMap> &AllocaDeclareMap, + DenseMap> &AllocaDbgMap, SmallVectorImpl &RetVec, Value *StackTag); Value *readRegister(IRBuilder<> &IRB, StringRef Name); bool instrumentLandingPads(SmallVectorImpl &RetVec); @@ -1016,7 +1016,7 @@ bool HWAddressSanitizer::instrumentStack( SmallVectorImpl &Allocas, - DenseMap> &AllocaDeclareMap, + DenseMap> &AllocaDbgMap, SmallVectorImpl &RetVec, Value *StackTag) { // Ideally, we want to calculate tagged stack base pointer, and rewrite all // alloca addresses using that. Unfortunately, offsets are not known yet @@ -1038,11 +1038,15 @@ AI->replaceUsesWithIf(Replacement, [AILong](Use &U) { return U.getUser() != AILong; }); - for (auto *DDI : AllocaDeclareMap.lookup(AI)) { - DIExpression *OldExpr = DDI->getExpression(); - DIExpression *NewExpr = DIExpression::append( - OldExpr, {dwarf::DW_OP_LLVM_tag_offset, RetagMask(N)}); - DDI->setArgOperand(2, MetadataAsValue::get(*C, NewExpr)); + for (auto *DDI : AllocaDbgMap.lookup(AI)) { + // Prepend "tag_offset, N" to the dwarf expression. + // Tag offset logically applies to the alloca pointer, and it makes sense + // to put it at the beginning of the expression. + SmallVector NewOps = {dwarf::DW_OP_LLVM_tag_offset, + RetagMask(N)}; + DDI->setArgOperand( + 2, MetadataAsValue::get(*C, DIExpression::prependOpcodes( + DDI->getExpression(), NewOps))); } size_t Size = getAllocaSizeInBytes(*AI); @@ -1089,7 +1093,7 @@ SmallVector AllocasToInstrument; SmallVector RetVec; SmallVector LandingPadVec; - DenseMap> AllocaDeclareMap; + DenseMap> AllocaDbgMap; for (auto &BB : F) { for (auto &Inst : BB) { if (ClInstrumentStack) @@ -1103,9 +1107,10 @@ isa(Inst)) RetVec.push_back(&Inst); - if (auto *DDI = dyn_cast(&Inst)) - if (auto *Alloca = dyn_cast_or_null(DDI->getAddress())) - AllocaDeclareMap[Alloca].push_back(DDI); + if (auto *DDI = dyn_cast(&Inst)) + if (auto *Alloca = + dyn_cast_or_null(DDI->getVariableLocation())) + AllocaDbgMap[Alloca].push_back(DDI); if (InstrumentLandingPads && isa(Inst)) LandingPadVec.push_back(&Inst); @@ -1148,7 +1153,7 @@ if (!AllocasToInstrument.empty()) { Value *StackTag = ClGenerateTagsWithCalls ? nullptr : getStackBaseTag(EntryIRB); - Changed |= instrumentStack(AllocasToInstrument, AllocaDeclareMap, RetVec, + Changed |= instrumentStack(AllocasToInstrument, AllocaDbgMap, RetVec, StackTag); } diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp --- a/llvm/lib/Transforms/Utils/Local.cpp +++ b/llvm/lib/Transforms/Utils/Local.cpp @@ -1421,22 +1421,32 @@ })) continue; - for (auto &AIUse : AI->uses()) { - User *U = AIUse.getUser(); - if (StoreInst *SI = dyn_cast(U)) { - if (AIUse.getOperandNo() == 1) - ConvertDebugDeclareToDebugValue(DDI, SI, DIB); - } else if (LoadInst *LI = dyn_cast(U)) { - ConvertDebugDeclareToDebugValue(DDI, LI, DIB); - } else if (CallInst *CI = dyn_cast(U)) { - // This is a call by-value or some other instruction that takes a - // pointer to the variable. Insert a *value* intrinsic that describes - // the variable by dereferencing the alloca. - DebugLoc NewLoc = getDebugValueLoc(DDI, nullptr); - auto *DerefExpr = - DIExpression::append(DDI->getExpression(), dwarf::DW_OP_deref); - DIB.insertDbgValueIntrinsic(AI, DDI->getVariable(), DerefExpr, NewLoc, - CI); + SmallVector WorkList; + WorkList.push_back(AI); + while (!WorkList.empty()) { + const Value *V = WorkList.pop_back_val(); + for (auto &AIUse : V->uses()) { + User *U = AIUse.getUser(); + if (StoreInst *SI = dyn_cast(U)) { + if (AIUse.getOperandNo() == 1) + ConvertDebugDeclareToDebugValue(DDI, SI, DIB); + } else if (LoadInst *LI = dyn_cast(U)) { + ConvertDebugDeclareToDebugValue(DDI, LI, DIB); + } else if (CallInst *CI = dyn_cast(U)) { + // This is a call by-value or some other instruction that takes a + // pointer to the variable. Insert a *value* intrinsic that describes + // the variable by dereferencing the alloca. + if (!CI->isLifetimeStartOrEnd()) { + DebugLoc NewLoc = getDebugValueLoc(DDI, nullptr); + auto *DerefExpr = + DIExpression::append(DDI->getExpression(), dwarf::DW_OP_deref); + DIB.insertDbgValueIntrinsic(AI, DDI->getVariable(), DerefExpr, + NewLoc, CI); + } + } else if (BitCastInst *BI = dyn_cast(U)) { + if (BI->getType()->isPointerTy()) + WorkList.push_back(BI); + } } } DDI->eraseFromParent(); diff --git a/llvm/test/CodeGen/AArch64/dbg-value-tag-offset.ll b/llvm/test/CodeGen/AArch64/dbg-value-tag-offset.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/dbg-value-tag-offset.ll @@ -0,0 +1,68 @@ +; RUN: llc -o - %s | FileCheck %s + +target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" +target triple = "aarch64-unknown-linux-android24" + +; CHECK: .Linfo_string5: +; CHECK-NEXT: .asciz "y" +; CHECK: .Linfo_string7: +; CHECK-NEXT: .asciz "x" + +; CHECK: .byte 128 // DW_AT_LLVM_tag_offset +; CHECK-NEXT: .word .Linfo_string5 // DW_AT_name +; CHECK: .byte 0 // DW_AT_LLVM_tag_offset +; CHECK-NEXT: .word .Linfo_string7 // DW_AT_name + +define dso_local void @f() !dbg !14 { + %1 = alloca i32, align 4 + %2 = alloca i32, align 4 + %3 = bitcast i32* %1 to i8*, !dbg !21 + %4 = bitcast i32* %2 to i8*, !dbg !21 + call void @llvm.dbg.value(metadata i32 1, metadata !20, metadata !DIExpression()), !dbg !22 + store i32 1, i32* %2, align 4, !dbg !23, !tbaa !24 + call void @llvm.dbg.value(metadata i32* %1, metadata !18, metadata !DIExpression(DW_OP_LLVM_tag_offset, 0, DW_OP_deref)), !dbg !22 + call void @use(i8* nonnull %3), !dbg !28 + call void @llvm.dbg.value(metadata i32* %2, metadata !20, metadata !DIExpression(DW_OP_LLVM_tag_offset, 128, DW_OP_deref)), !dbg !22 + call void @use(i8* nonnull %4), !dbg !29 + ret void, !dbg !30 +} + +declare !dbg !5 void @use(i8*) + +declare void @llvm.dbg.value(metadata, metadata, metadata) + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!8, !9, !10, !11, !12} +!llvm.ident = !{!13} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 10.0.0 (git@github.com:llvm/llvm-project.git 5560dd08b99a0e8b0c55116376624e4f967caec5)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !3, nameTableKind: None) +!1 = !DIFile(filename: "dbg.cc", directory: "/tmp") +!2 = !{} +!3 = !{!4, !5} +!4 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64) +!5 = !DISubprogram(name: "use", scope: !1, file: !1, line: 2, type: !6, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !2) +!6 = !DISubroutineType(types: !7) +!7 = !{null, !4} +!8 = !{i32 7, !"Dwarf Version", i32 4} +!9 = !{i32 2, !"Debug Info Version", i32 3} +!10 = !{i32 1, !"wchar_size", i32 4} +!11 = !{i32 7, !"PIC Level", i32 2} +!12 = !{i32 7, !"PIE Level", i32 2} +!13 = !{!"clang version 10.0.0 (git@github.com:llvm/llvm-project.git 5560dd08b99a0e8b0c55116376624e4f967caec5)"} +!14 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 4, type: !15, scopeLine: 4, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !17) +!15 = !DISubroutineType(types: !16) +!16 = !{null} +!17 = !{!18, !20} +!18 = !DILocalVariable(name: "x", scope: !14, file: !1, line: 5, type: !19) +!19 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!20 = !DILocalVariable(name: "y", scope: !14, file: !1, line: 5, type: !19) +!21 = !DILocation(line: 5, column: 3, scope: !14) +!22 = !DILocation(line: 0, scope: !14) +!23 = !DILocation(line: 5, column: 10, scope: !14) +!24 = !{!25, !25, i64 0} +!25 = !{!"int", !26, i64 0} +!26 = !{!"omnipotent char", !27, i64 0} +!27 = !{!"Simple C++ TBAA"} +!28 = !DILocation(line: 6, column: 3, scope: !14) +!29 = !DILocation(line: 7, column: 3, scope: !14) +!30 = !DILocation(line: 8, column: 1, scope: !14) diff --git a/llvm/test/Instrumentation/HWAddressSanitizer/dbg-value-tag-offset.ll b/llvm/test/Instrumentation/HWAddressSanitizer/dbg-value-tag-offset.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Instrumentation/HWAddressSanitizer/dbg-value-tag-offset.ll @@ -0,0 +1,61 @@ +; RUN: opt -hwasan -S -o - %s | FileCheck %s + +target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" +target triple = "aarch64-unknown-linux-android24" + +define dso_local void @f() sanitize_hwaddress !dbg !14 { + %1 = alloca i32, align 4 + %2 = alloca i32, align 4 + %3 = bitcast i32* %1 to i8*, !dbg !21 + %4 = bitcast i32* %2 to i8*, !dbg !21 +; CHECK: call void @llvm.dbg.value(metadata i32 1, {{.*}}, metadata !DIExpression()) + call void @llvm.dbg.value(metadata i32 1, metadata !20, metadata !DIExpression()), !dbg !22 + store i32 1, i32* %2, align 4, !dbg !23, !tbaa !24 +; CHECK: call void @llvm.dbg.value(metadata i32* {{.*}}, metadata !DIExpression(DW_OP_LLVM_tag_offset, 0, DW_OP_deref)) + call void @llvm.dbg.value(metadata i32* %1, metadata !18, metadata !DIExpression(DW_OP_deref)), !dbg !22 + call void @use(i8* nonnull %3), !dbg !28 +; CHECK: call void @llvm.dbg.value(metadata i32* {{.*}}, metadata !DIExpression(DW_OP_LLVM_tag_offset, 128, DW_OP_deref)) + call void @llvm.dbg.value(metadata i32* %2, metadata !20, metadata !DIExpression(DW_OP_deref)), !dbg !22 + call void @use(i8* nonnull %4), !dbg !29 + ret void, !dbg !30 +} + +declare !dbg !5 void @use(i8*) + +declare void @llvm.dbg.value(metadata, metadata, metadata) + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!8, !9, !10, !11, !12} +!llvm.ident = !{!13} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 10.0.0 (git@github.com:llvm/llvm-project.git 5560dd08b99a0e8b0c55116376624e4f967caec5)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !3, nameTableKind: None) +!1 = !DIFile(filename: "dbg.cc", directory: "/tmp") +!2 = !{} +!3 = !{!4, !5} +!4 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64) +!5 = !DISubprogram(name: "use", scope: !1, file: !1, line: 2, type: !6, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !2) +!6 = !DISubroutineType(types: !7) +!7 = !{null, !4} +!8 = !{i32 7, !"Dwarf Version", i32 4} +!9 = !{i32 2, !"Debug Info Version", i32 3} +!10 = !{i32 1, !"wchar_size", i32 4} +!11 = !{i32 7, !"PIC Level", i32 2} +!12 = !{i32 7, !"PIE Level", i32 2} +!13 = !{!"clang version 10.0.0 (git@github.com:llvm/llvm-project.git 5560dd08b99a0e8b0c55116376624e4f967caec5)"} +!14 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 4, type: !15, scopeLine: 4, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !17) +!15 = !DISubroutineType(types: !16) +!16 = !{null} +!17 = !{!18, !20} +!18 = !DILocalVariable(name: "x", scope: !14, file: !1, line: 5, type: !19) +!19 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!20 = !DILocalVariable(name: "y", scope: !14, file: !1, line: 5, type: !19) +!21 = !DILocation(line: 5, column: 3, scope: !14) +!22 = !DILocation(line: 0, scope: !14) +!23 = !DILocation(line: 5, column: 10, scope: !14) +!24 = !{!25, !25, i64 0} +!25 = !{!"int", !26, i64 0} +!26 = !{!"omnipotent char", !27, i64 0} +!27 = !{!"Simple C++ TBAA"} +!28 = !DILocation(line: 6, column: 3, scope: !14) +!29 = !DILocation(line: 7, column: 3, scope: !14) +!30 = !DILocation(line: 8, column: 1, scope: !14) diff --git a/llvm/test/Transforms/Util/dbg-call-bitcast.ll b/llvm/test/Transforms/Util/dbg-call-bitcast.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/Util/dbg-call-bitcast.ll @@ -0,0 +1,42 @@ +; RUN: opt -instcombine -S %s | FileCheck %s + +define dso_local void @_Z1fv() { + %1 = alloca i32, align 4 + %2 = bitcast i32* %1 to i8* + call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %2) +; CHECK: call void @llvm.dbg.value(metadata i32* %1, {{.*}}, metadata !DIExpression(DW_OP_deref) + call void @llvm.dbg.declare(metadata i32* %1, metadata !16, metadata !DIExpression()), !dbg !19 + call void @_Z1gPv(i8* nonnull %2) + call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %2) + ret void, !dbg !21 +} + +declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) +declare void @llvm.dbg.declare(metadata, metadata, metadata) +declare dso_local void @_Z1gPv(i8*) +declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!8, !9, !10} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 10.0.0 (git@github.com:llvm/llvm-project.git cab64b5708f614c71d275ec9d134e68b8c3baedd)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !3, nameTableKind: None) +!1 = !DIFile(filename: "dbg.cc", directory: "/tmp") +!2 = !{} +!3 = !{!4, !5} +!4 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64) +!5 = !DISubprogram(name: "g", linkageName: "_Z1gPv", scope: !1, file: !1, line: 1, type: !6, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !2) +!6 = !DISubroutineType(types: !7) +!7 = !{null, !4} +!8 = !{i32 7, !"Dwarf Version", i32 4} +!9 = !{i32 2, !"Debug Info Version", i32 3} +!10 = !{i32 1, !"wchar_size", i32 4} +!12 = distinct !DISubprogram(name: "f", linkageName: "_Z1fv", scope: !1, file: !1, line: 2, type: !13, scopeLine: 2, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !15) +!13 = !DISubroutineType(types: !14) +!14 = !{null} +!15 = !{!16} +!16 = !DILocalVariable(name: "x", scope: !12, file: !1, line: 3, type: !17) +!17 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!18 = !DILocation(line: 3, column: 3, scope: !12) +!19 = !DILocation(line: 3, column: 7, scope: !12) +!20 = !DILocation(line: 4, column: 3, scope: !12) +!21 = !DILocation(line: 5, column: 1, scope: !12) diff --git a/llvm/test/tools/llvm-symbolizer/frame-loclistx.s b/llvm/test/tools/llvm-symbolizer/frame-loclistx.s new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-symbolizer/frame-loclistx.s @@ -0,0 +1,284 @@ +// Test dwarf-5 DW_AT_location [DW_FORM_loclistx]. +// REQUIRES: aarch64-registered-target + +// RUN: llvm-mc -filetype=obj -triple=aarch64-linux-android -o %t.o %s +// RUN: echo 'FRAME %t.o 0x4' | llvm-symbolizer | FileCheck %s + +// DW_AT_location (indexed (0x0) loclist = 0x00000010: +// [0x0000000000000010, 0x0000000000000018): DW_OP_consts +1, DW_OP_stack_value +// [0x0000000000000018, 0x0000000000000028): DW_OP_breg29 W29-4) +// CHECK: f +// CHECK-NEXT: x +// CHECK-NEXT: {{.*}}dbg.cc:5 +// CHECK-NEXT: -4 4 ?? + + .text + .file "dbg.cc" + .file 0 "/tmp" "/tmp/dbg.cc" md5 0xb9e2d9cf63655505d60c734686e688fd + .file 1 "dbg.cc" md5 0xb9e2d9cf63655505d60c734686e688fd + .globl f // -- Begin function f + .p2align 2 + .type f,@function +f: // @f +.Lfunc_begin0: + .loc 1 4 0 // dbg.cc:4:0 + .cfi_startproc +// %bb.0: + sub sp, sp, #32 // =32 + stp x29, x30, [sp, #16] // 16-byte Folded Spill + add x29, sp, #16 // =16 + .cfi_def_cfa w29, 16 + .cfi_offset w30, -8 + .cfi_offset w29, -16 + mov w8, #1 +.Ltmp0: + //DEBUG_VALUE: f:x <- 1 + .loc 1 6 3 prologue_end // dbg.cc:6:3 + sub x0, x29, #4 // =4 + .loc 1 5 7 // dbg.cc:5:7 + stur w8, [x29, #-4] +.Ltmp1: + //DEBUG_VALUE: f:x <- [DW_OP_constu 4, DW_OP_minus, DW_OP_deref] $fp + .loc 1 6 3 // dbg.cc:6:3 + bl use +.Ltmp2: + .loc 1 7 1 // dbg.cc:7:1 + ldp x29, x30, [sp, #16] // 16-byte Folded Reload + add sp, sp, #32 // =32 + ret +.Ltmp3: +.Lfunc_end0: + .size f, .Lfunc_end0-f + .cfi_endproc + // -- End function + .section .debug_str_offsets,"",@progbits + .word 32 + .hword 5 + .hword 0 +.Lstr_offsets_base0: + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "clang version 10.0.0 (git@github.com:llvm/llvm-project.git 57e2b50509793c72f562e8a08523f7ab664adfcd)" // string offset=0 +.Linfo_string1: + .asciz "/tmp/dbg.cc" // string offset=101 +.Linfo_string2: + .asciz "/tmp" // string offset=113 +.Linfo_string3: + .asciz "use" // string offset=118 +.Linfo_string4: + .asciz "f" // string offset=122 +.Linfo_string5: + .asciz "x" // string offset=124 +.Linfo_string6: + .asciz "int" // string offset=126 + .section .debug_str_offsets,"",@progbits + .word .Linfo_string0 + .word .Linfo_string1 + .word .Linfo_string2 + .word .Linfo_string3 + .word .Linfo_string4 + .word .Linfo_string5 + .word .Linfo_string6 + .section .debug_loclists,"",@progbits + .word .Ldebug_loclist_table_end0-.Ldebug_loclist_table_start0 // Length +.Ldebug_loclist_table_start0: + .hword 5 // Version + .byte 8 // Address size + .byte 0 // Segment selector size + .word 1 // Offset entry count +.Lloclists_table_base0: + .word .Ldebug_loc0-.Lloclists_table_base0 +.Ldebug_loc0: + .byte 4 // DW_LLE_offset_pair + .uleb128 .Ltmp0-.Lfunc_begin0 // starting offset + .uleb128 .Ltmp1-.Lfunc_begin0 // ending offset + .byte 3 // Loc expr size + .byte 17 // DW_OP_consts + .byte 1 // 1 + .byte 159 // DW_OP_stack_value + .byte 4 // DW_LLE_offset_pair + .uleb128 .Ltmp1-.Lfunc_begin0 // starting offset + .uleb128 .Lfunc_end0-.Lfunc_begin0 // ending offset + .byte 2 // Loc expr size + .byte 141 // DW_OP_breg29 + .byte 124 // -4 + .byte 0 // DW_LLE_end_of_list +.Ldebug_loclist_table_end0: + .section .debug_abbrev,"",@progbits + .byte 1 // Abbreviation Code + .byte 17 // DW_TAG_compile_unit + .byte 1 // DW_CHILDREN_yes + .byte 37 // DW_AT_producer + .byte 37 // DW_FORM_strx1 + .byte 19 // DW_AT_language + .byte 5 // DW_FORM_data2 + .byte 3 // DW_AT_name + .byte 37 // DW_FORM_strx1 + .byte 114 // DW_AT_str_offsets_base + .byte 23 // DW_FORM_sec_offset + .byte 16 // DW_AT_stmt_list + .byte 23 // DW_FORM_sec_offset + .byte 27 // DW_AT_comp_dir + .byte 37 // DW_FORM_strx1 + .byte 17 // DW_AT_low_pc + .byte 27 // DW_FORM_addrx + .byte 18 // DW_AT_high_pc + .byte 6 // DW_FORM_data4 + .byte 115 // DW_AT_addr_base + .byte 23 // DW_FORM_sec_offset + .ascii "\214\001" // DW_AT_loclists_base + .byte 23 // DW_FORM_sec_offset + .byte 0 // EOM(1) + .byte 0 // EOM(2) + .byte 2 // Abbreviation Code + .byte 46 // DW_TAG_subprogram + .byte 1 // DW_CHILDREN_yes + .byte 3 // DW_AT_name + .byte 37 // DW_FORM_strx1 + .byte 58 // DW_AT_decl_file + .byte 11 // DW_FORM_data1 + .byte 59 // DW_AT_decl_line + .byte 11 // DW_FORM_data1 + .byte 60 // DW_AT_declaration + .byte 25 // DW_FORM_flag_present + .byte 63 // DW_AT_external + .byte 25 // DW_FORM_flag_present + .byte 0 // EOM(1) + .byte 0 // EOM(2) + .byte 3 // Abbreviation Code + .byte 5 // DW_TAG_formal_parameter + .byte 0 // DW_CHILDREN_no + .byte 73 // DW_AT_type + .byte 19 // DW_FORM_ref4 + .byte 0 // EOM(1) + .byte 0 // EOM(2) + .byte 4 // Abbreviation Code + .byte 15 // DW_TAG_pointer_type + .byte 0 // DW_CHILDREN_no + .byte 0 // EOM(1) + .byte 0 // EOM(2) + .byte 5 // Abbreviation Code + .byte 46 // DW_TAG_subprogram + .byte 1 // DW_CHILDREN_yes + .byte 17 // DW_AT_low_pc + .byte 27 // DW_FORM_addrx + .byte 18 // DW_AT_high_pc + .byte 6 // DW_FORM_data4 + .byte 64 // DW_AT_frame_base + .byte 24 // DW_FORM_exprloc + .byte 122 // DW_AT_call_all_calls + .byte 25 // DW_FORM_flag_present + .byte 3 // DW_AT_name + .byte 37 // DW_FORM_strx1 + .byte 58 // DW_AT_decl_file + .byte 11 // DW_FORM_data1 + .byte 59 // DW_AT_decl_line + .byte 11 // DW_FORM_data1 + .byte 63 // DW_AT_external + .byte 25 // DW_FORM_flag_present + .byte 0 // EOM(1) + .byte 0 // EOM(2) + .byte 6 // Abbreviation Code + .byte 52 // DW_TAG_variable + .byte 0 // DW_CHILDREN_no + .byte 2 // DW_AT_location + .byte 34 // DW_FORM_loclistx + .byte 3 // DW_AT_name + .byte 37 // DW_FORM_strx1 + .byte 58 // DW_AT_decl_file + .byte 11 // DW_FORM_data1 + .byte 59 // DW_AT_decl_line + .byte 11 // DW_FORM_data1 + .byte 73 // DW_AT_type + .byte 19 // DW_FORM_ref4 + .byte 0 // EOM(1) + .byte 0 // EOM(2) + .byte 7 // Abbreviation Code + .byte 72 // DW_TAG_call_site + .byte 0 // DW_CHILDREN_no + .byte 127 // DW_AT_call_origin + .byte 19 // DW_FORM_ref4 + .byte 125 // DW_AT_call_return_pc + .byte 1 // DW_FORM_addr + .byte 0 // EOM(1) + .byte 0 // EOM(2) + .byte 8 // Abbreviation Code + .byte 36 // DW_TAG_base_type + .byte 0 // DW_CHILDREN_no + .byte 3 // DW_AT_name + .byte 37 // DW_FORM_strx1 + .byte 62 // DW_AT_encoding + .byte 11 // DW_FORM_data1 + .byte 11 // DW_AT_byte_size + .byte 11 // DW_FORM_data1 + .byte 0 // EOM(1) + .byte 0 // EOM(2) + .byte 0 // EOM(3) + .section .debug_info,"",@progbits +.Lcu_begin0: + .word .Ldebug_info_end0-.Ldebug_info_start0 // Length of Unit +.Ldebug_info_start0: + .hword 5 // DWARF version number + .byte 1 // DWARF Unit Type + .byte 8 // Address Size (in bytes) + .word .debug_abbrev // Offset Into Abbrev. Section + .byte 1 // Abbrev [1] 0xc:0x4d DW_TAG_compile_unit + .byte 0 // DW_AT_producer + .hword 33 // DW_AT_language + .byte 1 // DW_AT_name + .word .Lstr_offsets_base0 // DW_AT_str_offsets_base + .word .Lline_table_start0 // DW_AT_stmt_list + .byte 2 // DW_AT_comp_dir + .byte 0 // DW_AT_low_pc + .word .Lfunc_end0-.Lfunc_begin0 // DW_AT_high_pc + .word .Laddr_table_base0 // DW_AT_addr_base + .word .Lloclists_table_base0 // DW_AT_loclists_base + .byte 2 // Abbrev [2] 0x27:0xa DW_TAG_subprogram + .byte 3 // DW_AT_name + .byte 1 // DW_AT_decl_file + .byte 2 // DW_AT_decl_line + // DW_AT_declaration + // DW_AT_external + .byte 3 // Abbrev [3] 0x2b:0x5 DW_TAG_formal_parameter + .word 49 // DW_AT_type + .byte 0 // End Of Children Mark + .byte 4 // Abbrev [4] 0x31:0x1 DW_TAG_pointer_type + .byte 5 // Abbrev [5] 0x32:0x22 DW_TAG_subprogram + .byte 0 // DW_AT_low_pc + .word .Lfunc_end0-.Lfunc_begin0 // DW_AT_high_pc + .byte 1 // DW_AT_frame_base + .byte 109 + // DW_AT_call_all_calls + .byte 4 // DW_AT_name + .byte 1 // DW_AT_decl_file + .byte 4 // DW_AT_decl_line + // DW_AT_external + .byte 6 // Abbrev [6] 0x3d:0x9 DW_TAG_variable + .byte 0 // DW_AT_location + .byte 5 // DW_AT_name + .byte 1 // DW_AT_decl_file + .byte 5 // DW_AT_decl_line + .word 84 // DW_AT_type + .byte 7 // Abbrev [7] 0x46:0xd DW_TAG_call_site + .word 39 // DW_AT_call_origin + .xword .Ltmp2-.Lfunc_begin0 // DW_AT_call_return_pc + .byte 0 // End Of Children Mark + .byte 8 // Abbrev [8] 0x54:0x4 DW_TAG_base_type + .byte 6 // DW_AT_name + .byte 5 // DW_AT_encoding + .byte 4 // DW_AT_byte_size + .byte 0 // End Of Children Mark +.Ldebug_info_end0: + .section .debug_addr,"",@progbits + .word .Ldebug_addr_end0-.Ldebug_addr_start0 // Length of contribution +.Ldebug_addr_start0: + .hword 5 // DWARF version number + .byte 8 // Address size + .byte 0 // Segment selector size +.Laddr_table_base0: + .xword .Lfunc_begin0 +.Ldebug_addr_end0: + .ident "clang version 10.0.0 (git@github.com:llvm/llvm-project.git 57e2b50509793c72f562e8a08523f7ab664adfcd)" + .section ".note.GNU-stack","",@progbits + .section .debug_line,"",@progbits +.Lline_table_start0: