1 ; Test basic address sanitizer instrumentation. 2 ; 3 ; RUN: opt < %s -hwasan -hwasan-recover=0 -S | FileCheck %s --check-prefixes=CHECK,ABORT,DYNAMIC-SHADOW 4 ; RUN: opt < %s -hwasan -hwasan-recover=1 -S | FileCheck %s --check-prefixes=CHECK,RECOVER,DYNAMIC-SHADOW 5 ; RUN: opt < %s -hwasan -hwasan-recover=0 -hwasan-mapping-offset=0 -S | FileCheck %s --check-prefixes=CHECK,ABORT,ZERO-BASED-SHADOW 6 ; RUN: opt < %s -hwasan -hwasan-recover=1 -hwasan-mapping-offset=0 -S | FileCheck %s --check-prefixes=CHECK,RECOVER,ZERO-BASED-SHADOW 7 8 target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" 9 target triple = "aarch64--linux-android" 10 11 define i8 @test_load8(i8* %a) sanitize_hwaddress { 12 ; CHECK-LABEL: @test_load8( 13 ; CHECK: %[[A:[^ ]*]] = ptrtoint i8* %a to i64 14 ; CHECK: %[[B:[^ ]*]] = lshr i64 %[[A]], 56 15 ; CHECK: %[[PTRTAG:[^ ]*]] = trunc i64 %[[B]] to i8 16 ; CHECK: %[[C:[^ ]*]] = and i64 %[[A]], 72057594037927935 17 ; CHECK: %[[D:[^ ]*]] = lshr i64 %[[C]], 4 18 ; DYNAMIC-SHADOW: %[[D_DYN:[^ ]*]] = add i64 %[[D]], %.hwasan.shadow 19 ; DYNAMIC-SHADOW: %[[E:[^ ]*]] = inttoptr i64 %[[D_DYN]] to i8* 20 ; ZERO-BASED-SHADOW: %[[E:[^ ]*]] = inttoptr i64 %[[D]] to i8* 21 ; CHECK: %[[MEMTAG:[^ ]*]] = load i8, i8* %[[E]] 22 ; CHECK: %[[F:[^ ]*]] = icmp ne i8 %[[PTRTAG]], %[[MEMTAG]] 23 ; CHECK: br i1 %[[F]], label {{.*}}, label {{.*}}, !prof {{.*}} 24 25 ; ABORT: call void asm sideeffect "brk #2304", "{x0}"(i64 %[[A]]) 26 ; ABORT: unreachable 27 ; RECOVER: call void asm sideeffect "brk #2336", "{x0}"(i64 %[[A]]) 28 ; RECOVER: br label 29 30 ; CHECK: %[[G:[^ ]*]] = load i8, i8* %a, align 4 31 ; CHECK: ret i8 %[[G]] 32 33 entry: 34 %b = load i8, i8* %a, align 4 35 ret i8 %b 36 } 37 38 define i16 @test_load16(i16* %a) sanitize_hwaddress { 39 ; CHECK-LABEL: @test_load16( 40 ; CHECK: %[[A:[^ ]*]] = ptrtoint i16* %a to i64 41 ; CHECK: %[[B:[^ ]*]] = lshr i64 %[[A]], 56 42 ; CHECK: %[[PTRTAG:[^ ]*]] = trunc i64 %[[B]] to i8 43 ; CHECK: %[[C:[^ ]*]] = and i64 %[[A]], 72057594037927935 44 ; CHECK: %[[D:[^ ]*]] = lshr i64 %[[C]], 4 45 ; DYNAMIC-SHADOW: %[[D_DYN:[^ ]*]] = add i64 %[[D]], %.hwasan.shadow 46 ; DYNAMIC-SHADOW: %[[E:[^ ]*]] = inttoptr i64 %[[D_DYN]] to i8* 47 ; ZERO-BASED-SHADOW: %[[E:[^ ]*]] = inttoptr i64 %[[D]] to i8* 48 ; CHECK: %[[MEMTAG:[^ ]*]] = load i8, i8* %[[E]] 49 ; CHECK: %[[F:[^ ]*]] = icmp ne i8 %[[PTRTAG]], %[[MEMTAG]] 50 ; CHECK: br i1 %[[F]], label {{.*}}, label {{.*}}, !prof {{.*}} 51 52 ; ABORT: call void asm sideeffect "brk #2305", "{x0}"(i64 %[[A]]) 53 ; ABORT: unreachable 54 ; RECOVER: call void asm sideeffect "brk #2337", "{x0}"(i64 %[[A]]) 55 ; RECOVER: br label 56 57 ; CHECK: %[[G:[^ ]*]] = load i16, i16* %a, align 4 58 ; CHECK: ret i16 %[[G]] 59 60 entry: 61 %b = load i16, i16* %a, align 4 62 ret i16 %b 63 } 64 65 define i32 @test_load32(i32* %a) sanitize_hwaddress { 66 ; CHECK-LABEL: @test_load32( 67 ; CHECK: %[[A:[^ ]*]] = ptrtoint i32* %a to i64 68 ; CHECK: %[[B:[^ ]*]] = lshr i64 %[[A]], 56 69 ; CHECK: %[[PTRTAG:[^ ]*]] = trunc i64 %[[B]] to i8 70 ; CHECK: %[[C:[^ ]*]] = and i64 %[[A]], 72057594037927935 71 ; CHECK: %[[D:[^ ]*]] = lshr i64 %[[C]], 4 72 ; DYNAMIC-SHADOW: %[[D_DYN:[^ ]*]] = add i64 %[[D]], %.hwasan.shadow 73 ; DYNAMIC-SHADOW: %[[E:[^ ]*]] = inttoptr i64 %[[D_DYN]] to i8* 74 ; ZERO-BASED-SHADOW: %[[E:[^ ]*]] = inttoptr i64 %[[D]] to i8* 75 ; CHECK: %[[MEMTAG:[^ ]*]] = load i8, i8* %[[E]] 76 ; CHECK: %[[F:[^ ]*]] = icmp ne i8 %[[PTRTAG]], %[[MEMTAG]] 77 ; CHECK: br i1 %[[F]], label {{.*}}, label {{.*}}, !prof {{.*}} 78 79 ; ABORT: call void asm sideeffect "brk #2306", "{x0}"(i64 %[[A]]) 80 ; ABORT: unreachable 81 ; RECOVER: call void asm sideeffect "brk #2338", "{x0}"(i64 %[[A]]) 82 ; RECOVER: br label 83 84 ; CHECK: %[[G:[^ ]*]] = load i32, i32* %a, align 4 85 ; CHECK: ret i32 %[[G]] 86 87 entry: 88 %b = load i32, i32* %a, align 4 89 ret i32 %b 90 } 91 92 define i64 @test_load64(i64* %a) sanitize_hwaddress { 93 ; CHECK-LABEL: @test_load64( 94 ; CHECK: %[[A:[^ ]*]] = ptrtoint i64* %a to i64 95 ; CHECK: %[[B:[^ ]*]] = lshr i64 %[[A]], 56 96 ; CHECK: %[[PTRTAG:[^ ]*]] = trunc i64 %[[B]] to i8 97 ; CHECK: %[[C:[^ ]*]] = and i64 %[[A]], 72057594037927935 98 ; CHECK: %[[D:[^ ]*]] = lshr i64 %[[C]], 4 99 ; DYNAMIC-SHADOW: %[[D_DYN:[^ ]*]] = add i64 %[[D]], %.hwasan.shadow 100 ; DYNAMIC-SHADOW: %[[E:[^ ]*]] = inttoptr i64 %[[D_DYN]] to i8* 101 ; ZERO-BASED-SHADOW: %[[E:[^ ]*]] = inttoptr i64 %[[D]] to i8* 102 ; CHECK: %[[MEMTAG:[^ ]*]] = load i8, i8* %[[E]] 103 ; CHECK: %[[F:[^ ]*]] = icmp ne i8 %[[PTRTAG]], %[[MEMTAG]] 104 ; CHECK: br i1 %[[F]], label {{.*}}, label {{.*}}, !prof {{.*}} 105 106 ; ABORT: call void asm sideeffect "brk #2307", "{x0}"(i64 %[[A]]) 107 ; ABORT: unreachable 108 ; RECOVER: call void asm sideeffect "brk #2339", "{x0}"(i64 %[[A]]) 109 ; RECOVER: br label 110 111 ; CHECK: %[[G:[^ ]*]] = load i64, i64* %a, align 8 112 ; CHECK: ret i64 %[[G]] 113 114 entry: 115 %b = load i64, i64* %a, align 8 116 ret i64 %b 117 } 118 119 define i128 @test_load128(i128* %a) sanitize_hwaddress { 120 ; CHECK-LABEL: @test_load128( 121 ; CHECK: %[[A:[^ ]*]] = ptrtoint i128* %a to i64 122 ; CHECK: %[[B:[^ ]*]] = lshr i64 %[[A]], 56 123 ; CHECK: %[[PTRTAG:[^ ]*]] = trunc i64 %[[B]] to i8 124 ; CHECK: %[[C:[^ ]*]] = and i64 %[[A]], 72057594037927935 125 ; CHECK: %[[D:[^ ]*]] = lshr i64 %[[C]], 4 126 ; DYNAMIC-SHADOW: %[[D_DYN:[^ ]*]] = add i64 %[[D]], %.hwasan.shadow 127 ; DYNAMIC-SHADOW: %[[E:[^ ]*]] = inttoptr i64 %[[D_DYN]] to i8* 128 ; ZERO-BASED-SHADOW: %[[E:[^ ]*]] = inttoptr i64 %[[D]] to i8* 129 ; CHECK: %[[MEMTAG:[^ ]*]] = load i8, i8* %[[E]] 130 ; CHECK: %[[F:[^ ]*]] = icmp ne i8 %[[PTRTAG]], %[[MEMTAG]] 131 ; CHECK: br i1 %[[F]], label {{.*}}, label {{.*}}, !prof {{.*}} 132 133 ; ABORT: call void asm sideeffect "brk #2308", "{x0}"(i64 %[[A]]) 134 ; ABORT: unreachable 135 ; RECOVER: call void asm sideeffect "brk #2340", "{x0}"(i64 %[[A]]) 136 ; RECOVER: br label 137 138 ; CHECK: %[[G:[^ ]*]] = load i128, i128* %a, align 16 139 ; CHECK: ret i128 %[[G]] 140 141 entry: 142 %b = load i128, i128* %a, align 16 143 ret i128 %b 144 } 145 146 define i40 @test_load40(i40* %a) sanitize_hwaddress { 147 ; CHECK-LABEL: @test_load40( 148 ; CHECK: %[[A:[^ ]*]] = ptrtoint i40* %a to i64 149 ; ABORT: call void @__hwasan_loadN(i64 %[[A]], i64 5) 150 ; RECOVER: call void @__hwasan_loadN_noabort(i64 %[[A]], i64 5) 151 ; CHECK: %[[B:[^ ]*]] = load i40, i40* %a 152 ; CHECK: ret i40 %[[B]] 153 154 entry: 155 %b = load i40, i40* %a, align 4 156 ret i40 %b 157 } 158 159 define void @test_store8(i8* %a, i8 %b) sanitize_hwaddress { 160 ; CHECK-LABEL: @test_store8( 161 ; CHECK: %[[A:[^ ]*]] = ptrtoint i8* %a to i64 162 ; CHECK: %[[B:[^ ]*]] = lshr i64 %[[A]], 56 163 ; CHECK: %[[PTRTAG:[^ ]*]] = trunc i64 %[[B]] to i8 164 ; CHECK: %[[C:[^ ]*]] = and i64 %[[A]], 72057594037927935 165 ; CHECK: %[[D:[^ ]*]] = lshr i64 %[[C]], 4 166 ; DYNAMIC-SHADOW: %[[D_DYN:[^ ]*]] = add i64 %[[D]], %.hwasan.shadow 167 ; DYNAMIC-SHADOW: %[[E:[^ ]*]] = inttoptr i64 %[[D_DYN]] to i8* 168 ; ZERO-BASED-SHADOW: %[[E:[^ ]*]] = inttoptr i64 %[[D]] to i8* 169 ; CHECK: %[[MEMTAG:[^ ]*]] = load i8, i8* %[[E]] 170 ; CHECK: %[[F:[^ ]*]] = icmp ne i8 %[[PTRTAG]], %[[MEMTAG]] 171 ; CHECK: br i1 %[[F]], label {{.*}}, label {{.*}}, !prof {{.*}} 172 173 ; ABORT: call void asm sideeffect "brk #2320", "{x0}"(i64 %[[A]]) 174 ; ABORT: unreachable 175 ; RECOVER: call void asm sideeffect "brk #2352", "{x0}"(i64 %[[A]]) 176 ; RECOVER: br label 177 178 ; CHECK: store i8 %b, i8* %a, align 4 179 ; CHECK: ret void 180 181 entry: 182 store i8 %b, i8* %a, align 4 183 ret void 184 } 185 186 define void @test_store16(i16* %a, i16 %b) sanitize_hwaddress { 187 ; CHECK-LABEL: @test_store16( 188 ; CHECK: %[[A:[^ ]*]] = ptrtoint i16* %a to i64 189 ; CHECK: %[[B:[^ ]*]] = lshr i64 %[[A]], 56 190 ; CHECK: %[[PTRTAG:[^ ]*]] = trunc i64 %[[B]] to i8 191 ; CHECK: %[[C:[^ ]*]] = and i64 %[[A]], 72057594037927935 192 ; CHECK: %[[D:[^ ]*]] = lshr i64 %[[C]], 4 193 ; DYNAMIC-SHADOW: %[[D_DYN:[^ ]*]] = add i64 %[[D]], %.hwasan.shadow 194 ; DYNAMIC-SHADOW: %[[E:[^ ]*]] = inttoptr i64 %[[D_DYN]] to i8* 195 ; ZERO-BASED-SHADOW: %[[E:[^ ]*]] = inttoptr i64 %[[D]] to i8* 196 ; CHECK: %[[MEMTAG:[^ ]*]] = load i8, i8* %[[E]] 197 ; CHECK: %[[F:[^ ]*]] = icmp ne i8 %[[PTRTAG]], %[[MEMTAG]] 198 ; CHECK: br i1 %[[F]], label {{.*}}, label {{.*}}, !prof {{.*}} 199 200 ; ABORT: call void asm sideeffect "brk #2321", "{x0}"(i64 %[[A]]) 201 ; ABORT: unreachable 202 ; RECOVER: call void asm sideeffect "brk #2353", "{x0}"(i64 %[[A]]) 203 ; RECOVER: br label 204 205 ; CHECK: store i16 %b, i16* %a, align 4 206 ; CHECK: ret void 207 208 entry: 209 store i16 %b, i16* %a, align 4 210 ret void 211 } 212 213 define void @test_store32(i32* %a, i32 %b) sanitize_hwaddress { 214 ; CHECK-LABEL: @test_store32( 215 ; CHECK: %[[A:[^ ]*]] = ptrtoint i32* %a to i64 216 ; CHECK: %[[B:[^ ]*]] = lshr i64 %[[A]], 56 217 ; CHECK: %[[PTRTAG:[^ ]*]] = trunc i64 %[[B]] to i8 218 ; CHECK: %[[C:[^ ]*]] = and i64 %[[A]], 72057594037927935 219 ; CHECK: %[[D:[^ ]*]] = lshr i64 %[[C]], 4 220 ; DYNAMIC-SHADOW: %[[D_DYN:[^ ]*]] = add i64 %[[D]], %.hwasan.shadow 221 ; DYNAMIC-SHADOW: %[[E:[^ ]*]] = inttoptr i64 %[[D_DYN]] to i8* 222 ; ZERO-BASED-SHADOW: %[[E:[^ ]*]] = inttoptr i64 %[[D]] to i8* 223 ; CHECK: %[[MEMTAG:[^ ]*]] = load i8, i8* %[[E]] 224 ; CHECK: %[[F:[^ ]*]] = icmp ne i8 %[[PTRTAG]], %[[MEMTAG]] 225 ; CHECK: br i1 %[[F]], label {{.*}}, label {{.*}}, !prof {{.*}} 226 227 ; ABORT: call void asm sideeffect "brk #2322", "{x0}"(i64 %[[A]]) 228 ; ABORT: unreachable 229 ; RECOVER: call void asm sideeffect "brk #2354", "{x0}"(i64 %[[A]]) 230 ; RECOVER: br label 231 232 ; CHECK: store i32 %b, i32* %a, align 4 233 ; CHECK: ret void 234 235 entry: 236 store i32 %b, i32* %a, align 4 237 ret void 238 } 239 240 define void @test_store64(i64* %a, i64 %b) sanitize_hwaddress { 241 ; CHECK-LABEL: @test_store64( 242 ; CHECK: %[[A:[^ ]*]] = ptrtoint i64* %a to i64 243 ; CHECK: %[[B:[^ ]*]] = lshr i64 %[[A]], 56 244 ; CHECK: %[[PTRTAG:[^ ]*]] = trunc i64 %[[B]] to i8 245 ; CHECK: %[[C:[^ ]*]] = and i64 %[[A]], 72057594037927935 246 ; CHECK: %[[D:[^ ]*]] = lshr i64 %[[C]], 4 247 ; DYNAMIC-SHADOW: %[[D_DYN:[^ ]*]] = add i64 %[[D]], %.hwasan.shadow 248 ; DYNAMIC-SHADOW: %[[E:[^ ]*]] = inttoptr i64 %[[D_DYN]] to i8* 249 ; ZERO-BASED-SHADOW: %[[E:[^ ]*]] = inttoptr i64 %[[D]] to i8* 250 ; CHECK: %[[MEMTAG:[^ ]*]] = load i8, i8* %[[E]] 251 ; CHECK: %[[F:[^ ]*]] = icmp ne i8 %[[PTRTAG]], %[[MEMTAG]] 252 ; CHECK: br i1 %[[F]], label {{.*}}, label {{.*}}, !prof {{.*}} 253 254 ; ABORT: call void asm sideeffect "brk #2323", "{x0}"(i64 %[[A]]) 255 ; ABORT: unreachable 256 ; RECOVER: call void asm sideeffect "brk #2355", "{x0}"(i64 %[[A]]) 257 ; RECOVER: br label 258 259 ; CHECK: store i64 %b, i64* %a, align 8 260 ; CHECK: ret void 261 262 entry: 263 store i64 %b, i64* %a, align 8 264 ret void 265 } 266 267 define void @test_store128(i128* %a, i128 %b) sanitize_hwaddress { 268 ; CHECK-LABEL: @test_store128( 269 ; CHECK: %[[A:[^ ]*]] = ptrtoint i128* %a to i64 270 ; CHECK: %[[B:[^ ]*]] = lshr i64 %[[A]], 56 271 ; CHECK: %[[PTRTAG:[^ ]*]] = trunc i64 %[[B]] to i8 272 ; CHECK: %[[C:[^ ]*]] = and i64 %[[A]], 72057594037927935 273 ; CHECK: %[[D:[^ ]*]] = lshr i64 %[[C]], 4 274 ; DYNAMIC-SHADOW: %[[D_DYN:[^ ]*]] = add i64 %[[D]], %.hwasan.shadow 275 ; DYNAMIC-SHADOW: %[[E:[^ ]*]] = inttoptr i64 %[[D_DYN]] to i8* 276 ; ZERO-BASED-SHADOW: %[[E:[^ ]*]] = inttoptr i64 %[[D]] to i8* 277 ; CHECK: %[[MEMTAG:[^ ]*]] = load i8, i8* %[[E]] 278 ; CHECK: %[[F:[^ ]*]] = icmp ne i8 %[[PTRTAG]], %[[MEMTAG]] 279 ; CHECK: br i1 %[[F]], label {{.*}}, label {{.*}}, !prof {{.*}} 280 281 ; ABORT: call void asm sideeffect "brk #2324", "{x0}"(i64 %[[A]]) 282 ; ABORT: unreachable 283 ; RECOVER: call void asm sideeffect "brk #2356", "{x0}"(i64 %[[A]]) 284 ; RECOVER: br label 285 286 ; CHECK: store i128 %b, i128* %a, align 16 287 ; CHECK: ret void 288 289 entry: 290 store i128 %b, i128* %a, align 16 291 ret void 292 } 293 294 define void @test_store40(i40* %a, i40 %b) sanitize_hwaddress { 295 ; CHECK-LABEL: @test_store40( 296 ; CHECK: %[[A:[^ ]*]] = ptrtoint i40* %a to i64 297 ; ABORT: call void @__hwasan_storeN(i64 %[[A]], i64 5) 298 ; RECOVER: call void @__hwasan_storeN_noabort(i64 %[[A]], i64 5) 299 ; CHECK: store i40 %b, i40* %a 300 ; CHECK: ret void 301 302 entry: 303 store i40 %b, i40* %a, align 4 304 ret void 305 } 306 307 define void @test_store_unaligned(i64* %a, i64 %b) sanitize_hwaddress { 308 ; CHECK-LABEL: @test_store_unaligned( 309 ; CHECK: %[[A:[^ ]*]] = ptrtoint i64* %a to i64 310 ; ABORT: call void @__hwasan_storeN(i64 %[[A]], i64 8) 311 ; RECOVER: call void @__hwasan_storeN_noabort(i64 %[[A]], i64 8) 312 ; CHECK: store i64 %b, i64* %a, align 4 313 ; CHECK: ret void 314 315 entry: 316 store i64 %b, i64* %a, align 4 317 ret void 318 } 319 320 define i8 @test_load_noattr(i8* %a) { 321 ; CHECK-LABEL: @test_load_noattr( 322 ; CHECK-NEXT: entry: 323 ; CHECK-NEXT: %[[B:[^ ]*]] = load i8, i8* %a 324 ; CHECK-NEXT: ret i8 %[[B]] 325 326 entry: 327 %b = load i8, i8* %a, align 4 328 ret i8 %b 329 } 330 331 define i8 @test_load_notmyattr(i8* %a) sanitize_address { 332 ; CHECK-LABEL: @test_load_notmyattr( 333 ; CHECK-NEXT: entry: 334 ; CHECK-NEXT: %[[B:[^ ]*]] = load i8, i8* %a 335 ; CHECK-NEXT: ret i8 %[[B]] 336 337 entry: 338 %b = load i8, i8* %a, align 4 339 ret i8 %b 340 } 341 342 define i8 @test_load_addrspace(i8 addrspace(256)* %a) sanitize_hwaddress { 343 ; CHECK-LABEL: @test_load_addrspace( 344 ; CHECK-NEXT: entry: 345 ; DYNAMIC-SHADOW: %.hwasan.shadow = call i64 asm "", "=r,0"([0 x i8]* @__hwasan_shadow) 346 ; CHECK-NEXT: %[[B:[^ ]*]] = load i8, i8 addrspace(256)* %a 347 ; CHECK-NEXT: ret i8 %[[B]] 348 349 entry: 350 %b = load i8, i8 addrspace(256)* %a, align 4 351 ret i8 %b 352 } 353 354 ; CHECK: declare void @__hwasan_init() 355 356 ; CHECK: define internal void @hwasan.module_ctor() { 357 ; CHECK-NEXT: call void @__hwasan_init() 358 ; CHECK-NEXT: ret void 359 ; CHECK-NEXT: } 360