[sanitizer] Improve FreeBSD ASLR detection
[llvm-project.git] / llvm / test / Instrumentation / HWAddressSanitizer / stack-safety-analysis.ll
blob46d0b89b80b136ac320fbd53b39a4da973d878a9
1 ; RUN: opt -passes=hwasan -hwasan-instrument-with-calls -hwasan-use-stack-safety=1 -hwasan-generate-tags-with-calls -S < %s | FileCheck %s --check-prefixes=SAFETY,CHECK
2 ; RUN: opt -passes=hwasan -hwasan-instrument-with-calls -hwasan-use-stack-safety=0 -hwasan-generate-tags-with-calls -S < %s | FileCheck %s --check-prefixes=NOSAFETY,CHECK
3 ; RUN: opt -passes=hwasan -hwasan-instrument-with-calls -hwasan-generate-tags-with-calls -S < %s | FileCheck %s --check-prefixes=SAFETY,CHECK
4 ; RUN: opt -passes=hwasan -hwasan-instrument-stack=0 -hwasan-instrument-with-calls -hwasan-generate-tags-with-calls -S < %s | FileCheck %s --check-prefixes=NOSTACK,CHECK
6 target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
7 target triple = "aarch64-unknown-linux-gnu"
9 ; Check a safe alloca to ensure it does not get a tag.
10 define i32 @test_simple(i32* %a) sanitize_hwaddress {
11 entry:
12   ; CHECK-LABEL: @test_simple
13   ; NOSAFETY: call {{.*}}__hwasan_generate_tag
14   ; NOSAFETY: call {{.*}}__hwasan_store
15   ; SAFETY-NOT: call {{.*}}__hwasan_generate_tag
16   ; SAFETY-NOT: call {{.*}}__hwasan_store
17   ; NOSTACK-NOT: call {{.*}}__hwasan_generate_tag
18   ; NOSTACK-NOT: call {{.*}}__hwasan_store
19   %buf.sroa.0 = alloca i8, align 4
20   call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull %buf.sroa.0)
21   store volatile i8 0, i8* %buf.sroa.0, align 4, !tbaa !8
22   call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull %buf.sroa.0)
23   ret i32 0
26 ; Check a non-safe alloca to ensure it gets a tag.
27 define i32 @test_use(i32* %a) sanitize_hwaddress {
28 entry:
29   ; CHECK-LABEL: @test_use
30   ; NOSAFETY: call {{.*}}__hwasan_generate_tag
31   ; NOSAFETY: call {{.*}}__hwasan_store
32   ; SAFETY: call {{.*}}__hwasan_generate_tag
33   ; SAFETY-NOT: call {{.*}}__hwasan_store
34   ; NOSTACK-NOT: call {{.*}}__hwasan_generate_tag
35   ; NOSTACK-NOT: call {{.*}}__hwasan_store
36   %buf.sroa.0 = alloca i8, align 4
37   call void @use(i8* nonnull %buf.sroa.0)
38   call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull %buf.sroa.0)
39   store volatile i8 0, i8* %buf.sroa.0, align 4, !tbaa !8
40   call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull %buf.sroa.0)
41   ret i32 0
44 ; Check an alloca with in range GEP to ensure it does not get a tag or check.
45 define i32 @test_in_range(i32* %a) sanitize_hwaddress {
46 entry:
47   ; CHECK-LABEL: @test_in_range
48   ; NOSAFETY: call {{.*}}__hwasan_generate_tag
49   ; NOSAFETY: call {{.*}}__hwasan_store
50   ; SAFETY-NOT: call {{.*}}__hwasan_generate_tag
51   ; SAFETY-NOT: call {{.*}}__hwasan_store
52   ; NOSTACK-NOT: call {{.*}}__hwasan_generate_tag
53   ; NOSTACK-NOT: call {{.*}}__hwasan_store
54   %buf.sroa.0 = alloca [10 x i8], align 4
55   %ptr = getelementptr [10 x i8], [10 x i8]* %buf.sroa.0, i32 0, i32 0
56   call void @llvm.lifetime.start.p0i8(i64 10, i8* nonnull %ptr)
57   store volatile i8 0, i8* %ptr, align 4, !tbaa !8
58   call void @llvm.lifetime.end.p0i8(i64 10, i8* nonnull %ptr)
59   ret i32 0
62 ; Check an alloca with in range GEP to ensure it does not get a tag or check.
63 define i32 @test_in_range2(i32* %a) sanitize_hwaddress {
64 entry:
65   ; CHECK-LABEL: @test_in_range2
66   ; NOSAFETY: call {{.*}}__hwasan_generate_tag
67   ; NOSAFETY: call {{.*}}__hwasan_store
68   ; SAFETY-NOT: call {{.*}}__hwasan_generate_tag
69   ; SAFETY-NOT: call {{.*}}__hwasan_store
70   ; NOSTACK-NOT: call {{.*}}__hwasan_generate_tag
71   ; NOSTACK-NOT: call {{.*}}__hwasan_store
72   %buf.sroa.0 = alloca [10 x i8], align 4
73   %ptr = getelementptr [10 x i8], [10 x i8]* %buf.sroa.0, i32 0, i32 9
74   %x = bitcast [10 x i8]* %buf.sroa.0 to i8*
75   call void @llvm.lifetime.start.p0i8(i64 10, i8* nonnull %x)
76   store volatile i8 0, i8* %ptr, align 4, !tbaa !8
77   call void @llvm.lifetime.end.p0i8(i64 10, i8* nonnull %x)
78   ret i32 0
81 define i32 @test_in_range3(i32* %a) sanitize_hwaddress {
82 entry:
83   ; CHECK-LABEL: @test_in_range3
84   ; NOSAFETY: call {{.*}}__hwasan_generate_tag
85   ; NOSAFETY: call {{.*}}__hwasan_memset
86   ; SAFETY-NOT: call {{.*}}__hwasan_generate_tag
87   ; SAFETY-NOT: call {{.*}}__hwasan_memset
88   ; NOSTACK-NOT: call {{.*}}__hwasan_generate_tag
89   ; NOSTACK-NOT: call {{.*}}__hwasan_memset
90   %buf.sroa.0 = alloca [10 x i8], align 4
91   %ptr = getelementptr [10 x i8], [10 x i8]* %buf.sroa.0, i32 0, i32 9
92   %x = bitcast [10 x i8]* %buf.sroa.0 to i8*
93   call void @llvm.memset.p0i8.i32(i8* %ptr, i8 0, i32 1, i1 true)
94   ret i32 0
97 define i32 @test_in_range4(i32* %a) sanitize_hwaddress {
98 entry:
99   ; CHECK-LABEL: @test_in_range4
100   ; NOSAFETY: call {{.*}}__hwasan_generate_tag
101   ; NOSAFETY: call {{.*}}__hwasan_memmove
102   ; SAFETY-NOT: call {{.*}}__hwasan_generate_tag
103   ; SAFETY-NOT: call {{.*}}__hwasan_memmove
104   ; NOSTACK-NOT: call {{.*}}__hwasan_generate_tag
105   ; NOSTACK-NOT: call {{.*}}__hwasan_memmove
106   %buf.sroa.0 = alloca [10 x i8], align 4
107   %ptr = getelementptr [10 x i8], [10 x i8]* %buf.sroa.0, i32 0, i32 9
108   %x = bitcast [10 x i8]* %buf.sroa.0 to i8*
109   call void @llvm.memmove.p0i8.p0i8.i32(i8* %ptr, i8* %ptr, i32 1, i1 true)
110   ret i32 0
113 define i32 @test_in_range5(i32* %a) sanitize_hwaddress {
114 entry:
115   ; CHECK-LABEL: @test_in_range5
116   ; NOSAFETY: call {{.*}}__hwasan_generate_tag
117   ; NOSAFETY: call {{.*}}__hwasan_memmove
118   ; SAFETY-NOT: call {{.*}}__hwasan_generate_tag
119   ; SAFETY-NOT: call {{.*}}__hwasan_memmove
120   ; NOSTACK-NOT: call {{.*}}__hwasan_generate_tag
121   ; NOSTACK-NOT: call {{.*}}__hwasan_memmove
122   %buf.sroa.0 = alloca [10 x i8], align 4
123   %ptr = getelementptr [10 x i8], [10 x i8]* %buf.sroa.0, i32 0, i32 9
124   %x = bitcast [10 x i8]* %buf.sroa.0 to i8*
125   %buf.sroa.1 = alloca [10 x i8], align 4
126   %ptr1 = getelementptr [10 x i8], [10 x i8]* %buf.sroa.0, i32 0, i32 9
127   %y = bitcast [10 x i8]* %buf.sroa.1 to i8*
128   call void @llvm.memmove.p0i8.p0i8.i32(i8* %ptr, i8* %ptr1, i32 1, i1 true)
129   ret i32 0
132 ; Check an alloca with out of range GEP to ensure it gets a tag and check.
133 define i32 @test_out_of_range(i32* %a) sanitize_hwaddress {
134 entry:
135   ; CHECK-LABEL: @test_out_of_range
136   ; NOSAFETY: call {{.*}}__hwasan_generate_tag
137   ; NOSAFETY: call {{.*}}__hwasan_store
138   ; SAFETY: call {{.*}}__hwasan_generate_tag
139   ; SAFETY: call {{.*}}__hwasan_store
140   ; NOSTACK-NOT: call {{.*}}__hwasan_generate_tag
141   ; NOSTACK-NOT: call {{.*}}__hwasan_store
142   %buf.sroa.0 = alloca [10 x i8], align 4
143   %ptr = getelementptr [10 x i8], [10 x i8]* %buf.sroa.0, i32 0, i32 10
144   %x = bitcast [10 x i8]* %buf.sroa.0 to i8*
145   call void @llvm.lifetime.start.p0i8(i64 10, i8* nonnull %x)
146   store volatile i8 0, i8* %ptr, align 4, !tbaa !8
147   call void @llvm.lifetime.end.p0i8(i64 10, i8* nonnull %x)
148   ret i32 0
151 define i32 @test_out_of_range3(i32* %a) sanitize_hwaddress {
152 entry:
153   ; CHECK-LABEL: @test_out_of_range3
154   ; NOSAFETY: call {{.*}}__hwasan_generate_tag
155   ; NOSAFETY: call {{.*}}__hwasan_memset
156   ; SAFETY: call {{.*}}__hwasan_generate_tag
157   ; SAFETY: call {{.*}}__hwasan_memset
158   ; NOSTACK-NOT: call {{.*}}__hwasan_generate_tag
159   ; NOSTACK-NOT: call {{.*}}__hwasan_memset
160   %buf.sroa.0 = alloca [10 x i8], align 4
161   %ptr = getelementptr [10 x i8], [10 x i8]* %buf.sroa.0, i32 0, i32 9
162   %x = bitcast [10 x i8]* %buf.sroa.0 to i8*
163   call void @llvm.memset.p0i8.i32(i8* %ptr, i8 0, i32 2, i1 true)
164   ret i32 0
167 define i32 @test_out_of_range4(i32* %a) sanitize_hwaddress {
168 entry:
169   ; CHECK-LABEL: @test_out_of_range4
170   ; NOSAFETY: call {{.*}}__hwasan_generate_tag
171   ; NOSAFETY: call {{.*}}__hwasan_memmove
172   ; SAFETY: call {{.*}}__hwasan_generate_tag
173   ; SAFETY: call {{.*}}__hwasan_memmove
174   ; NOSTACK-NOT: call {{.*}}__hwasan_generate_tag
175   ; NOSTACK-NOT: call {{.*}}__hwasan_memmove
176   %buf.sroa.0 = alloca [10 x i8], align 4
177   %ptr = getelementptr [10 x i8], [10 x i8]* %buf.sroa.0, i32 0, i32 9
178   %x = bitcast [10 x i8]* %buf.sroa.0 to i8*
179   call void @llvm.memmove.p0i8.p0i8.i32(i8* %ptr, i8* %ptr, i32 2, i1 true)
180   ret i32 0
183 define i32 @test_out_of_range5(i32* %a) sanitize_hwaddress {
184 entry:
185   ; CHECK-LABEL: @test_out_of_range5
186   ; NOSAFETY: call {{.*}}__hwasan_generate_tag
187   ; NOSAFETY: call {{.*}}__hwasan_memmove
188   ; SAFETY: call {{.*}}__hwasan_generate_tag
189   ; SAFETY: call {{.*}}__hwasan_memmove
190   ; NOSTACK-NOT: call {{.*}}__hwasan_generate_tag
191   ; NOSTACK-NOT: call {{.*}}__hwasan_memmove
192   %buf.sroa.0 = alloca [10 x i8], align 4
193   %ptr = getelementptr [10 x i8], [10 x i8]* %buf.sroa.0, i32 0, i32 9
194   %x = bitcast [10 x i8]* %buf.sroa.0 to i8*
195   %buf.sroa.1 = alloca [10 x i8], align 4
196   %ptr1 = getelementptr [10 x i8], [10 x i8]* %buf.sroa.0, i32 0, i32 9
197   %y = bitcast [10 x i8]* %buf.sroa.1 to i8*
198   call void @llvm.lifetime.start.p0i8(i64 10, i8* nonnull %x)
199   call void @llvm.lifetime.end.p0i8(i64 10, i8* nonnull %x)
200   call void @llvm.lifetime.start.p0i8(i64 10, i8* nonnull %y)
201   call void @llvm.memmove.p0i8.p0i8.i32(i8* %ptr, i8* %ptr1, i32 1, i1 true)
202   call void @llvm.lifetime.end.p0i8(i64 10, i8* nonnull %y)
203   ret i32 0
206 ; Check an alloca with potentially out of range GEP to ensure it gets a tag and
207 ; check.
208 define i32 @test_potentially_out_of_range(i32* %a) sanitize_hwaddress {
209 entry:
210   ; CHECK-LABEL: @test_potentially_out_of_range
211   ; NOSAFETY: call {{.*}}__hwasan_generate_tag
212   ; NOSAFETY: call {{.*}}__hwasan_store
213   ; SAFETY: call {{.*}}__hwasan_generate_tag
214   ; SAFETY: call {{.*}}__hwasan_store
215   ; NOSTACK-NOT: call {{.*}}__hwasan_generate_tag
216   ; NOSTACK-NOT: call {{.*}}__hwasan_store
217   %buf.sroa.0 = alloca [10 x i8], align 4
218   %off = call i32 @getoffset()
219   %ptr = getelementptr [10 x i8], [10 x i8]* %buf.sroa.0, i32 0, i32 %off
220   call void @llvm.lifetime.start.p0i8(i64 10, i8* nonnull %ptr)
221   store volatile i8 0, i8* %ptr, align 4, !tbaa !8
222   call void @llvm.lifetime.end.p0i8(i64 10, i8* nonnull %ptr)
223   ret i32 0
226 define i32 @test_potentially_out_of_range2(i8* %a) sanitize_hwaddress {
227 entry:
228   ; CHECK-LABEL: @test_potentially_out_of_range2
229   ; NOSAFETY: call {{.*}}__hwasan_generate_tag
230   ; NOSAFETY: call {{.*}}__hwasan_memmove
231   ; SAFETY-NOT: call {{.*}}__hwasan_generate_tag
232   ; SAFETY: call {{.*}}__hwasan_memmove
233   ; NOSTACK-NOT: call {{.*}}__hwasan_generate_tag
234   ; NOSTACK: call {{.*}}__hwasan_memmove
235   %buf.sroa.0 = alloca [10 x i8], align 4
236   %ptr = getelementptr [10 x i8], [10 x i8]* %buf.sroa.0, i32 0, i32 9
237   %x = bitcast [10 x i8]* %buf.sroa.0 to i8*
238   call void @llvm.memmove.p0i8.p0i8.i32(i8* %ptr, i8* %a, i32 1, i1 true)
239   ret i32 0
241 ; Check an alloca with potentially out of range GEP to ensure it gets a tag and
242 ; check.
243 define i32 @test_unclear(i32* %a) sanitize_hwaddress {
244 entry:
245   ; CHECK-LABEL: @test_unclear
246   ; NOSAFETY: call {{.*}}__hwasan_generate_tag
247   ; NOSAFETY: call {{.*}}__hwasan_store
248   ; SAFETY: call {{.*}}__hwasan_generate_tag
249   ; SAFETY: call {{.*}}__hwasan_store
250   ; NOSTACK-NOT: call {{.*}}__hwasan_generate_tag
251   ; NOSTACK: call {{.*}}__hwasan_store
252   %buf.sroa.0 = alloca i8, align 4
253   %ptr = call i8* @getptr(i8* %buf.sroa.0)
254   call void @llvm.lifetime.start.p0i8(i64 10, i8* nonnull %ptr)
255   store volatile i8 0, i8* %ptr, align 4, !tbaa !8
256   call void @llvm.lifetime.end.p0i8(i64 10, i8* nonnull %ptr)
257   ret i32 0
260 define i32 @test_select(i8* %a) sanitize_hwaddress {
261 entry:
262   ; CHECK-LABEL: @test_select
263   ; NOSAFETY: call {{.*}}__hwasan_generate_tag
264   ; NOSAFETY: call {{.*}}__hwasan_store
265   ; SAFETY: call {{.*}}__hwasan_generate_tag
266   ; SAFETY: call {{.*}}__hwasan_store
267   ; NOSTACK-NOT: call {{.*}}__hwasan_generate_tag
268   ; NOSTACK: call {{.*}}__hwasan_store
269   %x = call i8* @getptr(i8* %a)
270   %buf.sroa.0 = alloca i8, align 4
271   call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull %buf.sroa.0)
272   %c = call i1 @cond()
273   %ptr = select i1 %c, i8* %x, i8* %buf.sroa.0
274   store volatile i8 0, i8* %ptr, align 4, !tbaa !8
275   call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull %buf.sroa.0)
276   ret i32 0
279 ; Check whether we see through the returns attribute of functions.
280 define i32 @test_retptr(i32* %a) sanitize_hwaddress {
281 entry:
282   ; CHECK-LABEL: @test_retptr
283   ; NOSAFETY: call {{.*}}__hwasan_generate_tag
284   ; NOSAFETY: call {{.*}}__hwasan_store
285   ; SAFETY: call {{.*}}__hwasan_generate_tag
286   ; SAFETY-NOT: call {{.*}}__hwasan_store
287   ; NOSTACK-NOT: call {{.*}}__hwasan_generate_tag
288   ; NOSTACK-NOT: call {{.*}}__hwasan_store
289   %buf.sroa.0 = alloca i8, align 4
290   call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull %buf.sroa.0)
291   %ptr = call i8* @retptr(i8* %buf.sroa.0)
292   store volatile i8 0, i8* %ptr, align 4, !tbaa !8
293   call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull %buf.sroa.0)
294   ret i32 0
297 ; Function Attrs: argmemonly mustprogress nofree nosync nounwind willreturn
298 declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture)
300 ; Function Attrs: argmemonly mustprogress nofree nosync nounwind willreturn
301 declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture)
303 declare void @llvm.memset.p0i8.i32(i8*, i8, i32, i1)
304 declare void @llvm.memcpy.p0i8.p0i8.i32(i8*, i8*, i32, i1)
305 declare void @llvm.memmove.p0i8.p0i8.i32(i8*, i8*, i32, i1)
307 declare i1 @cond()
308 declare void @use(i8* nocapture)
309 declare i32 @getoffset()
310 declare i8* @getptr(i8* nocapture)
311 declare i8* @retptr(i8* returned)
313 !8 = !{!9, !9, i64 0}
314 !9 = !{!"omnipotent char", !10, i64 0}
315 !10 = !{!"Simple C/C++ TBAA"}