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 8target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" 9target triple = "aarch64--linux-android" 10 11define 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 33entry: 34 %b = load i8, i8* %a, align 4 35 ret i8 %b 36} 37 38define 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 60entry: 61 %b = load i16, i16* %a, align 4 62 ret i16 %b 63} 64 65define 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 87entry: 88 %b = load i32, i32* %a, align 4 89 ret i32 %b 90} 91 92define 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 114entry: 115 %b = load i64, i64* %a, align 8 116 ret i64 %b 117} 118 119define 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 141entry: 142 %b = load i128, i128* %a, align 16 143 ret i128 %b 144} 145 146define 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 154entry: 155 %b = load i40, i40* %a, align 4 156 ret i40 %b 157} 158 159define 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 181entry: 182 store i8 %b, i8* %a, align 4 183 ret void 184} 185 186define 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 208entry: 209 store i16 %b, i16* %a, align 4 210 ret void 211} 212 213define 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 235entry: 236 store i32 %b, i32* %a, align 4 237 ret void 238} 239 240define 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 262entry: 263 store i64 %b, i64* %a, align 8 264 ret void 265} 266 267define 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 289entry: 290 store i128 %b, i128* %a, align 16 291 ret void 292} 293 294define 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 302entry: 303 store i40 %b, i40* %a, align 4 304 ret void 305} 306 307define 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 315entry: 316 store i64 %b, i64* %a, align 4 317 ret void 318} 319 320define 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 326entry: 327 %b = load i8, i8* %a, align 4 328 ret i8 %b 329} 330 331define 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 337entry: 338 %b = load i8, i8* %a, align 4 339 ret i8 %b 340} 341 342define 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 349entry: 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