Skip to content

Commit d860ea9

Browse files
authored
[HWASAN] Update dbg.assign intrinsics in HWAsan pass (#79864)
llvm.dbg.assign intrinsics have 2 {value, expression} pairs; fix hwasan to update the second expression. Fixes #76545. This is #78606 rebased and with the addition of DPValue handling. Note the addition of --try-experimental-debuginfo-iterators in the tests and some shuffling of code in MemoryTaggingSupport.cpp.
1 parent 5b01522 commit d860ea9

File tree

7 files changed

+237
-12
lines changed

7 files changed

+237
-12
lines changed

llvm/lib/IR/DebugInfo.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2214,10 +2214,6 @@ bool AssignmentTrackingPass::runOnFunction(Function &F) {
22142214
if (F.hasFnAttribute(Attribute::OptimizeNone))
22152215
return /*Changed*/ false;
22162216

2217-
// FIXME: https://github.com/llvm/llvm-project/issues/76545
2218-
if (F.hasFnAttribute(Attribute::SanitizeHWAddress))
2219-
return /*Changed*/ false;
2220-
22212217
bool Changed = false;
22222218
auto *DL = &F.getParent()->getDataLayout();
22232219
// Collect a map of {backing storage : dbg.declares} (currently "backing

llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1371,6 +1371,14 @@ static bool isLifetimeIntrinsic(Value *V) {
13711371
return II && II->isLifetimeStartOrEnd();
13721372
}
13731373

1374+
static DbgAssignIntrinsic *DynCastToDbgAssign(DbgVariableIntrinsic *DVI) {
1375+
return dyn_cast<DbgAssignIntrinsic>(DVI);
1376+
}
1377+
1378+
static DPValue *DynCastToDbgAssign(DPValue *DPV) {
1379+
return DPV->isDbgAssign() ? DPV : nullptr;
1380+
}
1381+
13741382
bool HWAddressSanitizer::instrumentStack(memtag::StackInfo &SInfo,
13751383
Value *StackTag, Value *UARTag,
13761384
const DominatorTree &DT,
@@ -1437,6 +1445,11 @@ bool HWAddressSanitizer::instrumentStack(memtag::StackInfo &SInfo,
14371445
if (DPtr->getVariableLocationOp(LocNo) == AI)
14381446
DPtr->setExpression(DIExpression::appendOpsToArg(
14391447
DPtr->getExpression(), NewOps, LocNo));
1448+
if (auto *DAI = DynCastToDbgAssign(DPtr)) {
1449+
if (DAI->getAddress() == AI)
1450+
DAI->setAddressExpression(DIExpression::prependOpcodes(
1451+
DAI->getAddressExpression(), NewOps));
1452+
}
14401453
};
14411454

14421455
llvm::for_each(Info.DbgVariableIntrinsics, AnnotateDbgRecord);

llvm/lib/Transforms/Utils/MemoryTaggingSupport.cpp

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -110,18 +110,22 @@ Instruction *getUntagLocationIfFunctionExit(Instruction &Inst) {
110110
}
111111

112112
void StackInfoBuilder::visit(Instruction &Inst) {
113-
// Check for non-intrinsic debug-info records.
113+
// Visit non-intrinsic debug-info records attached to Inst.
114114
for (auto &DPV : Inst.getDbgValueRange()) {
115-
for (Value *V : DPV.location_ops()) {
115+
auto AddIfInteresting = [&](Value *V) {
116116
if (auto *AI = dyn_cast_or_null<AllocaInst>(V)) {
117117
if (!isInterestingAlloca(*AI))
118-
continue;
118+
return;
119119
AllocaInfo &AInfo = Info.AllocasToInstrument[AI];
120120
auto &DPVVec = AInfo.DbgVariableRecords;
121121
if (DPVVec.empty() || DPVVec.back() != &DPV)
122122
DPVVec.push_back(&DPV);
123123
}
124-
}
124+
};
125+
126+
for_each(DPV.location_ops(), AddIfInteresting);
127+
if (DPV.isDbgAssign())
128+
AddIfInteresting(DPV.getAddress());
125129
}
126130

127131
if (CallInst *CI = dyn_cast<CallInst>(&Inst)) {
@@ -152,16 +156,19 @@ void StackInfoBuilder::visit(Instruction &Inst) {
152156
return;
153157
}
154158
if (auto *DVI = dyn_cast<DbgVariableIntrinsic>(&Inst)) {
155-
for (Value *V : DVI->location_ops()) {
159+
auto AddIfInteresting = [&](Value *V) {
156160
if (auto *AI = dyn_cast_or_null<AllocaInst>(V)) {
157161
if (!isInterestingAlloca(*AI))
158-
continue;
162+
return;
159163
AllocaInfo &AInfo = Info.AllocasToInstrument[AI];
160164
auto &DVIVec = AInfo.DbgVariableIntrinsics;
161165
if (DVIVec.empty() || DVIVec.back() != DVI)
162166
DVIVec.push_back(DVI);
163167
}
164-
}
168+
};
169+
for_each(DVI->location_ops(), AddIfInteresting);
170+
if (auto *DAI = dyn_cast<DbgAssignIntrinsic>(DVI))
171+
AddIfInteresting(DAI->getAddress());
165172
}
166173

167174
Instruction *ExitUntag = getUntagLocationIfFunctionExit(Inst);
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
; RUN: llc -filetype=obj -o - %s | llvm-dwarfdump - | FileCheck %s
2+
; RUN: llc --try-experimental-debuginfo-iterators -filetype=obj -o - %s | llvm-dwarfdump - | FileCheck %s
3+
4+
;; Similar to dbg-assign-tag-offset.ll except the variable 'x' has been removed
5+
;; and 'y' has an implicit location range as well as stack location range
6+
;; (according to the hand-modified debug info -- see the dbg.value).
7+
8+
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
9+
target triple = "aarch64-unknown-linux-android24"
10+
11+
; CHECK: DW_TAG_variable
12+
; CHECK-NOT: DW_TAG
13+
; CHECK: DW_AT_LLVM_tag_offset (0x80)
14+
; CHECK-NEXT: DW_AT_name ("y")
15+
16+
define dso_local void @f() !dbg !14 {
17+
%1 = alloca i32, align 4, !DIAssignID !31
18+
%2 = alloca i32, align 4, !DIAssignID !32
19+
call void @llvm.dbg.assign(metadata i1 undef, metadata !20, metadata !DIExpression(), metadata !32, metadata ptr %2, metadata !DIExpression(DW_OP_LLVM_tag_offset, 128)), !dbg !22
20+
call void @llvm.dbg.value(metadata i32 2, metadata !20, metadata !DIExpression()), !dbg !22
21+
call void @use(ptr null), !dbg !28
22+
store i32 1, ptr %2, align 4, !dbg !23, !tbaa !24, !DIAssignID !33
23+
call void @llvm.dbg.assign(metadata i32 1, metadata !20, metadata !DIExpression(), metadata !33, metadata ptr %2, metadata !DIExpression(DW_OP_LLVM_tag_offset, 128)), !dbg !22
24+
call void @use(ptr nonnull %1), !dbg !28
25+
call void @use(ptr nonnull %2), !dbg !29
26+
ret void, !dbg !30
27+
}
28+
29+
declare !dbg !5 void @use(ptr)
30+
31+
declare void @llvm.dbg.value(metadata, metadata, metadata)
32+
declare void @llvm.dbg.assign(metadata, metadata, metadata, metadata, metadata, metadata)
33+
34+
!llvm.dbg.cu = !{!0}
35+
!llvm.module.flags = !{!8, !9, !10, !11, !12, !34}
36+
!llvm.ident = !{!13}
37+
38+
!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 10.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !3, nameTableKind: None)
39+
!1 = !DIFile(filename: "dbg.cc", directory: "/tmp")
40+
!2 = !{}
41+
!3 = !{!4, !5}
42+
!4 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64)
43+
!5 = !DISubprogram(name: "use", scope: !1, file: !1, line: 2, type: !6, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !2)
44+
!6 = !DISubroutineType(types: !7)
45+
!7 = !{null, !4}
46+
!8 = !{i32 7, !"Dwarf Version", i32 4}
47+
!9 = !{i32 2, !"Debug Info Version", i32 3}
48+
!10 = !{i32 1, !"wchar_size", i32 4}
49+
!11 = !{i32 7, !"PIC Level", i32 2}
50+
!12 = !{i32 7, !"PIE Level", i32 2}
51+
!13 = !{!"clang version 10.0.0"}
52+
!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)
53+
!15 = !DISubroutineType(types: !16)
54+
!16 = !{null}
55+
!17 = !{!18, !20}
56+
!18 = !DILocalVariable(name: "x", scope: !14, file: !1, line: 5, type: !19)
57+
!19 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
58+
!20 = !DILocalVariable(name: "y", scope: !14, file: !1, line: 5, type: !19)
59+
!21 = !DILocation(line: 5, column: 3, scope: !14)
60+
!22 = !DILocation(line: 0, scope: !14)
61+
!23 = !DILocation(line: 5, column: 10, scope: !14)
62+
!24 = !{!25, !25, i64 0}
63+
!25 = !{!"int", !26, i64 0}
64+
!26 = !{!"omnipotent char", !27, i64 0}
65+
!27 = !{!"Simple C++ TBAA"}
66+
!28 = !DILocation(line: 6, column: 3, scope: !14)
67+
!29 = !DILocation(line: 7, column: 3, scope: !14)
68+
!30 = !DILocation(line: 8, column: 1, scope: !14)
69+
!31 = distinct !DIAssignID()
70+
!32 = distinct !DIAssignID()
71+
!33 = distinct !DIAssignID()
72+
!34 = !{i32 7, !"debug-info-assignment-tracking", i1 true}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
; RUN: llc -filetype=obj -o - %s | llvm-dwarfdump - | FileCheck %s
2+
; RUN: llc --try-experimental-debuginfo-iterators -filetype=obj -o - %s | llvm-dwarfdump - | FileCheck %s
3+
4+
;; Copied from dbg-value-tag-offset.ll. Check that variables with locations
5+
;; tracked with dbg.assigns with DW_OP_LLVM_TAG_offset operators in their
6+
;; expressions get a DW_AT_LLVM_tag_offset attribute on their DIE.
7+
8+
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
9+
target triple = "aarch64-unknown-linux-android24"
10+
11+
; CHECK: DW_TAG_variable
12+
; CHECK-NOT: DW_TAG
13+
; CHECK: DW_AT_LLVM_tag_offset (0x00)
14+
; CHECK-NEXT: DW_AT_name ("x")
15+
16+
; CHECK: DW_TAG_variable
17+
; CHECK-NOT: DW_TAG
18+
; CHECK: DW_AT_LLVM_tag_offset (0x80)
19+
; CHECK-NEXT: DW_AT_name ("y")
20+
21+
define dso_local void @f() !dbg !14 {
22+
%1 = alloca i32, align 4, !DIAssignID !31
23+
call void @llvm.dbg.assign(metadata i1 undef, metadata !18, metadata !DIExpression(), metadata !31, metadata ptr %1, metadata !DIExpression(DW_OP_LLVM_tag_offset, 0)), !dbg !22
24+
%2 = alloca i32, align 4, !DIAssignID !32
25+
call void @llvm.dbg.assign(metadata i1 undef, metadata !20, metadata !DIExpression(), metadata !32, metadata ptr %2, metadata !DIExpression(DW_OP_LLVM_tag_offset, 128)), !dbg !22
26+
store i32 1, ptr %2, align 4, !dbg !23, !tbaa !24, !DIAssignID !33
27+
call void @llvm.dbg.assign(metadata i32 1, metadata !20, metadata !DIExpression(), metadata !33, metadata ptr %2, metadata !DIExpression(DW_OP_LLVM_tag_offset, 128)), !dbg !22
28+
call void @use(ptr nonnull %1), !dbg !28
29+
call void @use(ptr nonnull %2), !dbg !29
30+
ret void, !dbg !30
31+
}
32+
33+
declare !dbg !5 void @use(ptr)
34+
35+
declare void @llvm.dbg.value(metadata, metadata, metadata)
36+
declare void @llvm.dbg.assign(metadata, metadata, metadata, metadata, metadata, metadata)
37+
38+
!llvm.dbg.cu = !{!0}
39+
!llvm.module.flags = !{!8, !9, !10, !11, !12, !34}
40+
!llvm.ident = !{!13}
41+
42+
!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 10.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !3, nameTableKind: None)
43+
!1 = !DIFile(filename: "dbg.cc", directory: "/tmp")
44+
!2 = !{}
45+
!3 = !{!4, !5}
46+
!4 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64)
47+
!5 = !DISubprogram(name: "use", scope: !1, file: !1, line: 2, type: !6, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !2)
48+
!6 = !DISubroutineType(types: !7)
49+
!7 = !{null, !4}
50+
!8 = !{i32 7, !"Dwarf Version", i32 4}
51+
!9 = !{i32 2, !"Debug Info Version", i32 3}
52+
!10 = !{i32 1, !"wchar_size", i32 4}
53+
!11 = !{i32 7, !"PIC Level", i32 2}
54+
!12 = !{i32 7, !"PIE Level", i32 2}
55+
!13 = !{!"clang version 10.0.0"}
56+
!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)
57+
!15 = !DISubroutineType(types: !16)
58+
!16 = !{null}
59+
!17 = !{!18, !20}
60+
!18 = !DILocalVariable(name: "x", scope: !14, file: !1, line: 5, type: !19)
61+
!19 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
62+
!20 = !DILocalVariable(name: "y", scope: !14, file: !1, line: 5, type: !19)
63+
!21 = !DILocation(line: 5, column: 3, scope: !14)
64+
!22 = !DILocation(line: 0, scope: !14)
65+
!23 = !DILocation(line: 5, column: 10, scope: !14)
66+
!24 = !{!25, !25, i64 0}
67+
!25 = !{!"int", !26, i64 0}
68+
!26 = !{!"omnipotent char", !27, i64 0}
69+
!27 = !{!"Simple C++ TBAA"}
70+
!28 = !DILocation(line: 6, column: 3, scope: !14)
71+
!29 = !DILocation(line: 7, column: 3, scope: !14)
72+
!30 = !DILocation(line: 8, column: 1, scope: !14)
73+
!31 = distinct !DIAssignID()
74+
!32 = distinct !DIAssignID()
75+
!33 = distinct !DIAssignID()
76+
!34 = !{i32 7, !"debug-info-assignment-tracking", i1 true}

llvm/test/DebugInfo/Generic/assignment-tracking/declare-to-assign/hwasan.ll

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
; RUN: opt %s -S -passes=declare-to-assign -o - | FileCheck %s
2+
; RUN: opt --try-experimental-debuginfo-iterators %s -S -passes=declare-to-assign -o - | FileCheck %s
23

3-
; CHECK: call void @llvm.dbg.declare
4+
; CHECK: call void @llvm.dbg.assign
45

56
define dso_local void @f() sanitize_hwaddress !dbg !9 {
67
entry:
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
; RUN: opt -passes=hwasan -S -o - %s | FileCheck %s
2+
; RUN: opt --try-experimental-debuginfo-iterators -passes=hwasan -S -o - %s | FileCheck %s
3+
4+
source_filename = "test.ll"
5+
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
6+
target triple = "aarch64--linux-android"
7+
8+
declare void @g(ptr, ptr, ptr, ptr, ptr, ptr)
9+
10+
; Function Attrs: sanitize_hwaddress
11+
define void @f() #0 !dbg !7 {
12+
entry:
13+
%nodebug0 = alloca ptr, align 8
14+
%nodebug1 = alloca ptr, align 8
15+
%nodebug2 = alloca ptr, align 8
16+
%nodebug3 = alloca ptr, align 8
17+
; CHECK: %a = alloca{{.*}} !DIAssignID ![[ID1:[0-9]+]]
18+
%a = alloca ptr, align 8, !DIAssignID !13
19+
; CHECK: @llvm.dbg.assign{{.*}} metadata ![[ID1]]{{.*}} !DIExpression(DW_OP_LLVM_tag_offset, 32)
20+
call void @llvm.dbg.assign(metadata i1 undef, metadata !14, metadata !DIExpression(), metadata !13, metadata ptr %a, metadata !DIExpression()), !dbg !15
21+
; CHECK: %b = alloca{{.*}} !DIAssignID ![[ID2:[0-9]+]]
22+
%b = alloca ptr, align 8, !DIAssignID !16
23+
; CHECK: @llvm.dbg.assign{{.*}} metadata ![[ID2]]{{.*}} !DIExpression(DW_OP_LLVM_tag_offset, 96)
24+
call void @llvm.dbg.assign(metadata i1 undef, metadata !17, metadata !DIExpression(), metadata !16, metadata ptr %b, metadata !DIExpression()), !dbg !15
25+
call void @g(ptr %nodebug0, ptr %nodebug1, ptr %nodebug2, ptr %nodebug3, ptr %a, ptr %b)
26+
ret void, !dbg !18
27+
}
28+
29+
; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
30+
declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
31+
32+
; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
33+
declare void @llvm.dbg.assign(metadata, metadata, metadata, metadata, metadata, metadata) #1
34+
35+
attributes #0 = { sanitize_hwaddress }
36+
attributes #1 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
37+
38+
!llvm.dbg.cu = !{!0}
39+
!llvm.module.flags = !{!3, !4, !5}
40+
!llvm.ident = !{!6}
41+
42+
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
43+
!1 = !DIFile(filename: "x.c", directory: "/")
44+
!2 = !{}
45+
!3 = !{i32 2, !"Dwarf Version", i32 4}
46+
!4 = !{i32 2, !"Debug Info Version", i32 3}
47+
!5 = !{i32 7, !"debug-info-assignment-tracking", i1 true}
48+
!6 = !{!"clang"}
49+
!7 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 1, type: !8, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)
50+
!8 = !DISubroutineType(types: !9)
51+
!9 = !{null, !10}
52+
!10 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !11, size: 64)
53+
!11 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !12)
54+
!12 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
55+
!13 = distinct !DIAssignID()
56+
!14 = !DILocalVariable(name: "a", scope: !7, file: !1, line: 1, type: !10)
57+
!15 = !DILocation(line: 0, scope: !7)
58+
!16 = distinct !DIAssignID()
59+
!17 = !DILocalVariable(name: "b", scope: !7, file: !1, line: 1, type: !10)
60+
!18 = !DILocation(line: 1, column: 37, scope: !7)

0 commit comments

Comments
 (0)