brintos

brintos / llvm-project-archived public Read only

0
0
Text · 14.5 KiB · 1b9ffaf Raw
304 lines · plain
1; Test for handling of asm constraints in MSan instrumentation.2; RUN: opt < %s -msan-check-access-address=0 -msan-handle-asm-conservative=0 -S -passes=msan 2>&1 | FileCheck %s3; RUN: opt < %s -msan-check-access-address=0 -S -passes=msan 2>&1 | FileCheck --check-prefixes=CHECK,USER-CONS %s4; RUN: opt < %s -msan-kernel=1 -msan-check-access-address=0 -msan-handle-asm-conservative=0 -S -passes=msan 2>&1 | FileCheck --check-prefixes=CHECK,KMSAN %s5; RUN: opt < %s -msan-kernel=1 -msan-check-access-address=0 -msan-handle-asm-conservative=1 -S -passes=msan 2>&1 | FileCheck --check-prefixes=CHECK,KMSAN,CHECK-CONS %s6 7target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"8target triple = "x86_64-unknown-linux-gnu"9 10%struct.pair = type { i32, i32 }11%struct.large = type { [33 x i8] }12 13@id1 = common dso_local global i32 0, align 414@is1 = common dso_local global i32 0, align 415@id2 = common dso_local global i32 0, align 416@is2 = common dso_local global i32 0, align 417@id3 = common dso_local global i32 0, align 418@pair2 = common dso_local global %struct.pair zeroinitializer, align 419@pair1 = common dso_local global %struct.pair zeroinitializer, align 420@c2 = common dso_local global i8 0, align 121@c1 = common dso_local global i8 0, align 122@memcpy_d1 = common dso_local global ptr null, align 823@memcpy_d2 = common dso_local global ptr null, align 824@memcpy_s1 = common dso_local global ptr null, align 825@memcpy_s2 = common dso_local global ptr null, align 826@large = common dso_local global %struct.pair zeroinitializer, align 427 28; The functions below were generated from a C source that contains declarations like follows:29;   void f1() {30;     asm("" : "=r" (id1) : "r" (is1));31;   }32; with corresponding input/output constraints.33; Note that the assembly statement is always empty, as MSan doesn't look at it anyway.34 35; One input register, one output register:36;   asm("" : "=r" (id1) : "r" (is1));37define dso_local void @f_1i_1o_reg() sanitize_memory {38entry:39  %0 = load i32, ptr @is1, align 440  %1 = call i32 asm "", "=r,r,~{dirflag},~{fpsr},~{flags}"(i32 %0)41  store i32 %1, ptr @id1, align 442  ret void43}44 45; CHECK-LABEL: @f_1i_1o_reg46; CHECK: [[IS1_F1:%.*]] = load i32, ptr @is1, align 447; CHECK: call void @__msan_warning48; CHECK: call i32 asm "",{{.*}}(i32 [[IS1_F1]])49; KMSAN: [[PACK1_F1:%.*]] = call {{.*}} @__msan_metadata_ptr_for_store_4({{.*}}@id1{{.*}})50; KMSAN: [[EXT1_F1:%.*]] = extractvalue { ptr, ptr } [[PACK1_F1]], 051; KMSAN: store i32 0, ptr [[EXT1_F1]]52 53 54; Two input registers, two output registers:55;   asm("" : "=r" (id1), "=r" (id2) : "r" (is1), "r"(is2));56define dso_local void @f_2i_2o_reg() sanitize_memory {57entry:58  %0 = load i32, ptr @is1, align 459  %1 = load i32, ptr @is2, align 460  %2 = call { i32, i32 } asm "", "=r,=r,r,r,~{dirflag},~{fpsr},~{flags}"(i32 %0, i32 %1)61  %asmresult = extractvalue { i32, i32 } %2, 062  %asmresult1 = extractvalue { i32, i32 } %2, 163  store i32 %asmresult, ptr @id1, align 464  store i32 %asmresult1, ptr @id2, align 465  ret void66}67 68; CHECK-LABEL: @f_2i_2o_reg69; CHECK: [[IS1_F2:%.*]] = load i32, ptr @is1, align 470; CHECK: [[IS2_F2:%.*]] = load i32, ptr @is2, align 471; CHECK: call void @__msan_warning72; KMSAN: call void @__msan_warning73; CHECK: call { i32, i32 } asm "",{{.*}}(i32 [[IS1_F2]], i32 [[IS2_F2]])74; KMSAN: [[PACK1_F2:%.*]] = call {{.*}} @__msan_metadata_ptr_for_store_4({{.*}}@id1{{.*}})75; KMSAN: [[EXT1_F2:%.*]] = extractvalue { ptr, ptr } [[PACK1_F2]], 076; KMSAN: store i32 0, ptr [[EXT1_F2]]77; KMSAN: [[PACK2_F2:%.*]] = call {{.*}} @__msan_metadata_ptr_for_store_4({{.*}}@id2{{.*}})78; KMSAN: [[EXT2_F2:%.*]] = extractvalue { ptr, ptr } [[PACK2_F2]], 079; KMSAN: store i32 0, ptr [[EXT2_F2]]80 81; Input same as output, used twice:82;   asm("" : "=r" (id1), "=r" (id2) : "r" (id1), "r" (id2));83define dso_local void @f_2i_2o_reuse2_reg() sanitize_memory {84entry:85  %0 = load i32, ptr @id1, align 486  %1 = load i32, ptr @id2, align 487  %2 = call { i32, i32 } asm "", "=r,=r,r,r,~{dirflag},~{fpsr},~{flags}"(i32 %0, i32 %1)88  %asmresult = extractvalue { i32, i32 } %2, 089  %asmresult1 = extractvalue { i32, i32 } %2, 190  store i32 %asmresult, ptr @id1, align 491  store i32 %asmresult1, ptr @id2, align 492  ret void93}94 95; CHECK-LABEL: @f_2i_2o_reuse2_reg96; CHECK: [[ID1_F3:%.*]] = load i32, ptr @id1, align 497; CHECK: [[ID2_F3:%.*]] = load i32, ptr @id2, align 498; CHECK: call void @__msan_warning99; KMSAN: call void @__msan_warning100; CHECK: call { i32, i32 } asm "",{{.*}}(i32 [[ID1_F3]], i32 [[ID2_F3]])101; KMSAN: [[PACK1_F3:%.*]] = call {{.*}} @__msan_metadata_ptr_for_store_4({{.*}}@id1{{.*}})102; KMSAN: [[EXT1_F3:%.*]] = extractvalue { ptr, ptr } [[PACK1_F3]], 0103; KMSAN: store i32 0, ptr [[EXT1_F3]]104; KMSAN: [[PACK2_F3:%.*]] = call {{.*}} @__msan_metadata_ptr_for_store_4({{.*}}@id2{{.*}})105; KMSAN: [[EXT2_F3:%.*]] = extractvalue { ptr, ptr } [[PACK2_F3]], 0106; KMSAN: store i32 0, ptr [[EXT2_F3]]107 108 109; One of the input registers is also an output:110;   asm("" : "=r" (id1), "=r" (id2) : "r" (id1), "r"(is1));111define dso_local void @f_2i_2o_reuse1_reg() sanitize_memory {112entry:113  %0 = load i32, ptr @id1, align 4114  %1 = load i32, ptr @is1, align 4115  %2 = call { i32, i32 } asm "", "=r,=r,r,r,~{dirflag},~{fpsr},~{flags}"(i32 %0, i32 %1)116  %asmresult = extractvalue { i32, i32 } %2, 0117  %asmresult1 = extractvalue { i32, i32 } %2, 1118  store i32 %asmresult, ptr @id1, align 4119  store i32 %asmresult1, ptr @id2, align 4120  ret void121}122 123; CHECK-LABEL: @f_2i_2o_reuse1_reg124; CHECK: [[ID1_F4:%.*]] = load i32, ptr @id1, align 4125; CHECK: [[IS1_F4:%.*]] = load i32, ptr @is1, align 4126; CHECK: call void @__msan_warning127; KMSAN: call void @__msan_warning128; CHECK: call { i32, i32 } asm "",{{.*}}(i32 [[ID1_F4]], i32 [[IS1_F4]])129; KMSAN: [[PACK1_F4:%.*]] = call {{.*}} @__msan_metadata_ptr_for_store_4({{.*}}@id1{{.*}})130; KMSAN: [[EXT1_F4:%.*]] = extractvalue { ptr, ptr } [[PACK1_F4]], 0131; KMSAN: store i32 0, ptr [[EXT1_F4]]132; KMSAN: [[PACK2_F4:%.*]] = call {{.*}} @__msan_metadata_ptr_for_store_4({{.*}}@id2{{.*}})133; KMSAN: [[EXT2_F4:%.*]] = extractvalue { ptr, ptr } [[PACK2_F4]], 0134; KMSAN: store i32 0, ptr [[EXT2_F4]]135 136 137; One input register, three output registers:138;   asm("" : "=r" (id1), "=r" (id2), "=r" (id3) : "r" (is1));139define dso_local void @f_1i_3o_reg() sanitize_memory {140entry:141  %0 = load i32, ptr @is1, align 4142  %1 = call { i32, i32, i32 } asm "", "=r,=r,=r,r,~{dirflag},~{fpsr},~{flags}"(i32 %0)143  %asmresult = extractvalue { i32, i32, i32 } %1, 0144  %asmresult1 = extractvalue { i32, i32, i32 } %1, 1145  %asmresult2 = extractvalue { i32, i32, i32 } %1, 2146  store i32 %asmresult, ptr @id1, align 4147  store i32 %asmresult1, ptr @id2, align 4148  store i32 %asmresult2, ptr @id3, align 4149  ret void150}151 152; CHECK-LABEL: @f_1i_3o_reg153; CHECK: [[IS1_F5:%.*]] = load i32, ptr @is1, align 4154; CHECK: call void @__msan_warning155; CHECK: call { i32, i32, i32 } asm "",{{.*}}(i32 [[IS1_F5]])156; KMSAN: [[PACK1_F5:%.*]] = call {{.*}} @__msan_metadata_ptr_for_store_4({{.*}}@id1{{.*}})157; KMSAN: [[EXT1_F5:%.*]] = extractvalue { ptr, ptr } [[PACK1_F5]], 0158; KMSAN: store i32 0, ptr [[EXT1_F5]]159; KMSAN: [[PACK2_F5:%.*]] = call {{.*}} @__msan_metadata_ptr_for_store_4({{.*}}@id2{{.*}})160; KMSAN: [[EXT2_F5:%.*]] = extractvalue { ptr, ptr } [[PACK2_F5]], 0161; KMSAN: store i32 0, ptr [[EXT2_F5]]162; KMSAN: [[PACK3_F5:%.*]] = call {{.*}} @__msan_metadata_ptr_for_store_4({{.*}}@id3{{.*}})163; KMSAN: [[EXT3_F5:%.*]] = extractvalue { ptr, ptr } [[PACK3_F5]], 0164; KMSAN: store i32 0, ptr [[EXT3_F5]]165 166 167; 2 input memory args, 2 output memory args:168;  asm("" : "=m" (id1), "=m" (id2) : "m" (is1), "m"(is2))169define dso_local void @f_2i_2o_mem() sanitize_memory {170entry:171  call void asm "", "=*m,=*m,*m,*m,~{dirflag},~{fpsr},~{flags}"(ptr elementtype(i32) @id1, ptr elementtype(i32) @id2, ptr elementtype(i32) @is1, ptr elementtype(i32) @is2)172  ret void173}174 175; CHECK-LABEL: @f_2i_2o_mem176; USER-CONS:  store i32 0, ptr inttoptr (i64 xor (i64 ptrtoint (ptr @id1 to i64), i64 87960930222080) to ptr), align 1177; USER-CONS:  store i32 0, ptr inttoptr (i64 xor (i64 ptrtoint (ptr @id2 to i64), i64 87960930222080) to ptr), align 1178; CHECK-CONS: call void @__msan_instrument_asm_store({{.*}}@id1{{.*}}, i64 4)179; CHECK-CONS: call void @__msan_instrument_asm_store({{.*}}@id2{{.*}}, i64 4)180; CHECK: call void asm "", "=*m,=*m,*m,*m,~{dirflag},~{fpsr},~{flags}"(ptr elementtype(i32) @id1, ptr elementtype(i32) @id2, ptr elementtype(i32) @is1, ptr elementtype(i32) @is2)181 182 183; Same input and output passed as both memory and register:184;  asm("" : "=r" (id1), "=m"(id1) : "r"(is1), "m"(is1));185define dso_local void @f_1i_1o_memreg() sanitize_memory {186entry:187  %0 = load i32, ptr @is1, align 4188  %1 = call i32 asm "", "=r,=*m,r,*m,~{dirflag},~{fpsr},~{flags}"(ptr elementtype(i32) @id1, i32 %0, ptr elementtype(i32) @is1)189  store i32 %1, ptr @id1, align 4190  ret void191}192 193; CHECK-LABEL: @f_1i_1o_memreg194; CHECK: [[IS1_F7:%.*]] = load i32, ptr @is1, align 4195; USER-CONS:  store i32 0, ptr inttoptr (i64 xor (i64 ptrtoint (ptr @id1 to i64), i64 87960930222080) to ptr), align 1196; CHECK-CONS: call void @__msan_instrument_asm_store({{.*}}@id1{{.*}}, i64 4)197; CHECK: call void @__msan_warning198; CHECK: call i32 asm "", "=r,=*m,r,*m,~{dirflag},~{fpsr},~{flags}"(ptr elementtype(i32) @id1, i32 [[IS1_F7]], ptr elementtype(i32) @is1)199 200; Three outputs, first and last returned via regs, second via mem:201;  asm("" : "=r" (id1), "=m"(id2), "=r" (id3):);202define dso_local void @f_3o_reg_mem_reg() sanitize_memory {203entry:204  %0 = call { i32, i32 } asm "", "=r,=*m,=r,~{dirflag},~{fpsr},~{flags}"(ptr elementtype(i32) @id2)205  %asmresult = extractvalue { i32, i32 } %0, 0206  %asmresult1 = extractvalue { i32, i32 } %0, 1207  store i32 %asmresult, ptr @id1, align 4208  store i32 %asmresult1, ptr @id3, align 4209  ret void210}211 212; CHECK-LABEL: @f_3o_reg_mem_reg213; USER-CONS:  store i32 0, ptr inttoptr (i64 xor (i64 ptrtoint (ptr @id2 to i64), i64 87960930222080) to ptr), align 1214; CHECK-CONS: call void @__msan_instrument_asm_store(ptr @id2, i64 4)215; CHECK: call { i32, i32 } asm "", "=r,=*m,=r,~{dirflag},~{fpsr},~{flags}"(ptr elementtype(i32) @id2)216 217 218; Three inputs and three outputs of different types: a pair, a char, a function pointer.219; Everything is meant to be passed in registers, but LLVM chooses to return the integer pair by pointer:220;  asm("" : "=r" (pair2), "=r" (c2), "=r" (memcpy_d1) : "r"(pair1), "r"(c1), "r"(memcpy_s1));221define dso_local void @f_3i_3o_complex_reg() sanitize_memory {222entry:223  %0 = load i64, ptr @pair1, align 4224  %1 = load i8, ptr @c1, align 1225  %2 = load ptr, ptr @memcpy_s1, align 8226  %3 = call { i8, ptr } asm "", "=*r,=r,=r,r,r,r,~{dirflag},~{fpsr},~{flags}"(ptr elementtype(%struct.pair) @pair2, i64 %0, i8 %1, ptr %2)227  %asmresult = extractvalue { i8, ptr } %3, 0228  %asmresult1 = extractvalue { i8, ptr } %3, 1229  store i8 %asmresult, ptr @c2, align 1230  store ptr %asmresult1, ptr @memcpy_d1, align 8231  ret void232}233 234; CHECK-LABEL: @f_3i_3o_complex_reg235; CHECK: [[PAIR1_F9:%.*]] = load {{.*}} @pair1236; CHECK: [[C1_F9:%.*]] = load {{.*}} @c1237; CHECK: [[MEMCPY_S1_F9:%.*]] = load {{.*}} @memcpy_s1238; USER-CONS:  store { i32, i32 } zeroinitializer, ptr inttoptr (i64 xor (i64 ptrtoint (ptr @pair2 to i64), i64 87960930222080) to ptr), align 1239; CHECK-CONS: call void @__msan_instrument_asm_store({{.*}}@pair2{{.*}}, i64 8)240; CHECK: call void @__msan_warning241; KMSAN: call void @__msan_warning242; KMSAN: call void @__msan_warning243; CHECK: call { i8, ptr } asm "", "=*r,=r,=r,r,r,r,~{dirflag},~{fpsr},~{flags}"(ptr elementtype(%struct.pair) @pair2, {{.*}}[[PAIR1_F9]], i8 [[C1_F9]], {{.*}} [[MEMCPY_S1_F9]])244 245; Three inputs and three outputs of different types: a pair, a char, a function pointer.246; Everything is passed in memory:247;  asm("" : "=m" (pair2), "=m" (c2), "=m" (memcpy_d1) : "m"(pair1), "m"(c1), "m"(memcpy_s1));248define dso_local void @f_3i_3o_complex_mem() sanitize_memory {249entry:250  call void asm "", "=*m,=*m,=*m,*m,*m,*m,~{dirflag},~{fpsr},~{flags}"(ptr elementtype(%struct.pair) @pair2, ptr elementtype(i8) @c2, ptr elementtype(ptr) @memcpy_d1, ptr elementtype(%struct.pair) @pair1, ptr elementtype(i8) @c1, ptr elementtype(ptr) @memcpy_s1)251  ret void252}253 254; CHECK-LABEL: @f_3i_3o_complex_mem255; USER-CONS:       store { i32, i32 } zeroinitializer, ptr inttoptr (i64 xor (i64 ptrtoint (ptr @pair2 to i64), i64 87960930222080) to ptr), align 1256; USER-CONS-NEXT:  store i8 0, ptr inttoptr (i64 xor (i64 ptrtoint (ptr @c2 to i64), i64 87960930222080) to ptr), align 1257; USER-CONS-NEXT:  store i64 0, ptr inttoptr (i64 xor (i64 ptrtoint (ptr @memcpy_d1 to i64), i64 87960930222080) to ptr), align 1258; CHECK-CONS:      call void @__msan_instrument_asm_store({{.*}}@pair2{{.*}}, i64 8)259; CHECK-CONS:      call void @__msan_instrument_asm_store({{.*}}@c2{{.*}}, i64 1)260; CHECK-CONS:      call void @__msan_instrument_asm_store({{.*}}@memcpy_d1{{.*}}, i64 8)261; CHECK: call void asm "", "=*m,=*m,=*m,*m,*m,*m,~{dirflag},~{fpsr},~{flags}"(ptr elementtype(%struct.pair) @pair2, ptr elementtype(i8) @c2, ptr elementtype(ptr) @memcpy_d1, ptr elementtype(%struct.pair) @pair1, ptr elementtype(i8) @c1, ptr elementtype(ptr) @memcpy_s1)262 263; Use memset when the size is larger.264define dso_local void @f_1i_1o_mem_large() sanitize_memory {265entry:266  %0 = call i32 asm "", "=r,=*m,*m,~{dirflag},~{fpsr},~{flags}"(ptr elementtype(%struct.large) @large, ptr elementtype(%struct.large) @large)267  store i32 %0, ptr @id1, align 4268  ret void269}270; CHECK-LABEL: @f_1i_1o_mem_large(271; USER-CONS:  call void @llvm.memset.p0.i64(ptr align 1 inttoptr (i64 xor (i64 ptrtoint (ptr @large to i64), i64 87960930222080) to ptr), i8 0, i64 33, i1 false)272; CHECK-CONS: call void @__msan_instrument_asm_store({{.*}}@large{{.*}}, i64 33)273; CHECK: call i32 asm "", "=r,=*m,*m,~{dirflag},~{fpsr},~{flags}"(ptr elementtype(%struct.large) @large, ptr elementtype(%struct.large) @large)274 275; A simple asm goto construct to check that callbr is handled correctly:276;  int asm_goto(int n) {277;    int v = 1;278;    asm goto("cmp %0, %1; jnz %l2;" :: "r"(n), "r"(v)::skip_label);279;    return 0;280;  skip_label:281;    return 1;282;  }283; asm goto statements can't have outputs, so just make sure we check the input284; and the compiler doesn't crash.285define dso_local i32 @asm_goto(i32 %n) sanitize_memory {286entry:287  callbr void asm sideeffect "cmp $0, $1; jnz ${2:l}", "r,r,!i,~{dirflag},~{fpsr},~{flags}"(i32 %n, i32 1)288          to label %cleanup [label %skip_label]289 290skip_label:                                       ; preds = %entry291  br label %cleanup292 293cleanup:                                          ; preds = %entry, %skip_label294  %retval.0 = phi i32 [ 2, %skip_label ], [ 1, %entry ]295  ret i32 %retval.0296}297 298; CHECK-LABEL: @asm_goto299; KMSAN: [[LOAD_ARG:%.*]] = load {{.*}} %_msarg300; KMSAN: [[CMP:%.*]] = icmp ne {{.*}} [[LOAD_ARG]], 0301; KMSAN: br {{.*}} [[CMP]], label %[[LABEL:.*]], label302; KMSAN: [[LABEL]]:303; KMSAN-NEXT: call void @__msan_warning304