diff --git a/compiler-rt/lib/msan/msan.cpp b/compiler-rt/lib/msan/msan.cpp --- a/compiler-rt/lib/msan/msan.cpp +++ b/compiler-rt/lib/msan/msan.cpp @@ -303,28 +303,30 @@ return chained.raw_id(); } -// 'descr' is created at compile time and contains '----' in the beginning. -// When we see descr for the first time we replace '----' with a uniq id -// and set the origin to (id | (31-th bit)). -static inline void SetAllocaOrigin(void *a, uptr size, char *descr, uptr pc) { +// Current implementation separates the 'id_ptr' from the 'descr' and makes +// 'descr' constant. +// Previous implementation 'descr' is created at compile time and contains +// '----' in the beginning. When we see descr for the first time we replace +// '----' with a uniq id and set the origin to (id | (31-th bit)). +static inline void SetAllocaOrigin(void *a, uptr size, u32 *id_ptr, char *descr, + uptr pc) { static const u32 dash = '-'; static const u32 first_timer = dash + (dash << 8) + (dash << 16) + (dash << 24); - u32 *id_ptr = (u32 *)descr; - bool print = false; // internal_strstr(descr + 4, "AllocaTOTest") != 0; + bool print = false; u32 id = *id_ptr; - if (id == first_timer) { + if (id == 0 || id == first_timer) { u32 idx = atomic_fetch_add(&NumStackOriginDescrs, 1, memory_order_relaxed); CHECK_LT(idx, kNumStackOriginDescrs); - StackOriginDescr[idx] = descr + 4; + StackOriginDescr[idx] = descr; StackOriginPC[idx] = pc; id = Origin::CreateStackOrigin(idx).raw_id(); *id_ptr = id; if (print) - Printf("First time: idx=%d id=%d %s 0x%zx \n", idx, id, descr + 4, pc); + Printf("First time: idx=%d id=%d %s 0x%zx \n", idx, id, descr, pc); } if (print) - Printf("__msan_set_alloca_origin: descr=%s id=%x\n", descr + 4, id); + Printf("SetAllocaOrigin: descr=%s id=%x\n", descr, id); __msan_set_origin(a, size, id); } @@ -607,7 +609,7 @@ } void __msan_set_alloca_origin(void *a, uptr size, char *descr) { - SetAllocaOrigin(a, size, descr, + SetAllocaOrigin(a, size, reinterpret_cast(descr), descr + 4, StackTrace::GetPreviousInstructionPc(GET_CALLER_PC())); } @@ -615,7 +617,13 @@ // Intentionally ignore pc and use return address. This function is here for // compatibility, in case program is linked with library instrumented by // older clang. - SetAllocaOrigin(a, size, descr, + SetAllocaOrigin(a, size, reinterpret_cast(descr), descr + 4, + StackTrace::GetPreviousInstructionPc(GET_CALLER_PC())); +} + +void __msan_set_alloca_origin5(void *a, uptr size, u32 *id_ptr, char *descr, + uptr pc) { + SetAllocaOrigin(a, size, id_ptr, descr, StackTrace::GetPreviousInstructionPc(GET_CALLER_PC())); } diff --git a/compiler-rt/lib/msan/msan_interface_internal.h b/compiler-rt/lib/msan/msan_interface_internal.h --- a/compiler-rt/lib/msan/msan_interface_internal.h +++ b/compiler-rt/lib/msan/msan_interface_internal.h @@ -109,6 +109,9 @@ SANITIZER_INTERFACE_ATTRIBUTE void __msan_set_alloca_origin4(void *a, uptr size, char *descr, uptr pc); SANITIZER_INTERFACE_ATTRIBUTE +void __msan_set_alloca_origin5(void *a, uptr size, u32 *id_ptr, char *descr, + uptr pc); +SANITIZER_INTERFACE_ATTRIBUTE u32 __msan_chain_origin(u32 id); SANITIZER_INTERFACE_ATTRIBUTE u32 __msan_get_origin(const void *a); diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp --- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -579,7 +579,7 @@ /// Run-time helper that generates a new origin value for a stack /// allocation. - FunctionCallee MsanSetAllocaOriginFn; + FunctionCallee MsanSetAllocaOrigin5Fn; /// Run-time helper that poisons stack on function entry. FunctionCallee MsanPoisonStackFn; @@ -691,10 +691,10 @@ /// Creates a writable global for Str so that we can pass it to the /// run-time lib. Runtime uses first 4 bytes of the string to store the /// frame ID, so the string needs to be mutable. -static GlobalVariable *createPrivateNonConstGlobalForString(Module &M, - StringRef Str) { +static GlobalVariable *createPrivateConstGlobalForString(Module &M, + StringRef Str) { Constant *StrConst = ConstantDataArray::getString(M.getContext(), Str); - return new GlobalVariable(M, StrConst->getType(), /*isConstant=*/false, + return new GlobalVariable(M, StrConst->getType(), /*isConstant=*/true, GlobalValue::PrivateLinkage, StrConst, ""); } @@ -825,9 +825,9 @@ IRB.getInt32Ty()); } - MsanSetAllocaOriginFn = M.getOrInsertFunction( - "__msan_set_alloca_origin", IRB.getVoidTy(), IRB.getInt8PtrTy(), IntptrTy, - IRB.getInt8PtrTy()); + MsanSetAllocaOrigin5Fn = M.getOrInsertFunction( + "__msan_set_alloca_origin5", IRB.getVoidTy(), IRB.getInt8PtrTy(), IntptrTy, + IRB.getInt8PtrTy(), IRB.getInt8PtrTy()); MsanPoisonStackFn = M.getOrInsertFunction("__msan_poison_stack", IRB.getVoidTy(), IRB.getInt8PtrTy(), IntptrTy); @@ -3867,17 +3867,16 @@ "_msphi_o")); } + Value *getLocalVarIdptr(AllocaInst &I) { + ConstantInt *IntConst = + ConstantInt::get(Type::getInt32Ty((*F.getParent()).getContext()), 0); + return new GlobalVariable(*F.getParent(), IntConst->getType(), + /*isConstant=*/false, GlobalValue::PrivateLinkage, + IntConst); + } + Value *getLocalVarDescription(AllocaInst &I) { - SmallString<2048> StackDescriptionStorage; - raw_svector_ostream StackDescription(StackDescriptionStorage); - // We create a string with a description of the stack allocation and - // pass it into __msan_set_alloca_origin. - // It will be printed by the run-time if stack-originated UMR is found. - // The first 4 bytes of the string are set to '----' and will be replaced - // by __msan_va_arg_overflow_size_tls at the first call. - StackDescription << "----" << I.getName(); - return createPrivateNonConstGlobalForString(*F.getParent(), - StackDescription.str()); + return createPrivateConstGlobalForString(*F.getParent(), I.getName()); } void poisonAllocaUserspace(AllocaInst &I, IRBuilder<> &IRB, Value *Len) { @@ -3894,9 +3893,11 @@ } if (PoisonStack && MS.TrackOrigins) { + Value *Idptr = getLocalVarIdptr(I); Value *Descr = getLocalVarDescription(I); - IRB.CreateCall(MS.MsanSetAllocaOriginFn, + IRB.CreateCall(MS.MsanSetAllocaOrigin5Fn, {IRB.CreatePointerCast(&I, IRB.getInt8PtrTy()), Len, + IRB.CreatePointerCast(Idptr, IRB.getInt8PtrTy()), IRB.CreatePointerCast(Descr, IRB.getInt8PtrTy())}); } } diff --git a/llvm/test/Instrumentation/MemorySanitizer/alloca.ll b/llvm/test/Instrumentation/MemorySanitizer/alloca.ll --- a/llvm/test/Instrumentation/MemorySanitizer/alloca.ll +++ b/llvm/test/Instrumentation/MemorySanitizer/alloca.ll @@ -23,7 +23,7 @@ ; CHECK-LABEL: define void @static( ; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 4, i1 false) ; CALL: call void @__msan_poison_stack(i8* {{.*}}, i64 4) -; ORIGIN: call void @__msan_set_alloca_origin(i8* {{.*}}, i64 4, +; ORIGIN: call void @__msan_set_alloca_origin5(i8* {{.*}}, i64 4, ; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 4, ; CHECK: ret void @@ -39,7 +39,7 @@ ; CHECK-LABEL: define void @dynamic( ; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 4, i1 false) ; CALL: call void @__msan_poison_stack(i8* {{.*}}, i64 4) -; ORIGIN: call void @__msan_set_alloca_origin(i8* {{.*}}, i64 4, +; ORIGIN: call void @__msan_set_alloca_origin5(i8* {{.*}}, i64 4, ; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 4, ; CHECK: ret void @@ -52,7 +52,7 @@ ; CHECK-LABEL: define void @array( ; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 20, i1 false) ; CALL: call void @__msan_poison_stack(i8* {{.*}}, i64 20) -; ORIGIN: call void @__msan_set_alloca_origin(i8* {{.*}}, i64 20, +; ORIGIN: call void @__msan_set_alloca_origin5(i8* {{.*}}, i64 20, ; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 20, ; CHECK: ret void @@ -66,7 +66,7 @@ ; CHECK: %[[A:.*]] = mul i64 4, %cnt ; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 %[[A]], i1 false) ; CALL: call void @__msan_poison_stack(i8* {{.*}}, i64 %[[A]]) -; ORIGIN: call void @__msan_set_alloca_origin(i8* {{.*}}, i64 %[[A]], +; ORIGIN: call void @__msan_set_alloca_origin5(i8* {{.*}}, i64 %[[A]], ; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 %[[A]], ; CHECK: ret void @@ -80,7 +80,7 @@ ; CHECK-LABEL: define void @unpoison_local( ; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 0, i64 20, i1 false) ; CALL: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 0, i64 20, i1 false) -; ORIGIN-NOT: call void @__msan_set_alloca_origin(i8* {{.*}}, i64 20, +; ORIGIN-NOT: call void @__msan_set_alloca_origin5(i8* {{.*}}, i64 20, ; KMSAN: call void @__msan_unpoison_alloca(i8* {{.*}}, i64 20) ; CHECK: ret void @@ -109,13 +109,13 @@ ; CHECK: call void @llvm.lifetime.start ; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 4, i1 false) ; CALL: call void @__msan_poison_stack(i8* {{.*}}, i64 4) -; ORIGIN: call void @__msan_set_alloca_origin(i8* {{.*}}, i64 4, +; ORIGIN: call void @__msan_set_alloca_origin5(i8* {{.*}}, i64 4, ; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 4, ; CHECK: call void @llvm.lifetime.start ; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 4, i1 false) ; CALL: call void @__msan_poison_stack(i8* {{.*}}, i64 4) -; ORIGIN: call void @__msan_set_alloca_origin(i8* {{.*}}, i64 4, +; ORIGIN: call void @__msan_set_alloca_origin5(i8* {{.*}}, i64 4, ; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 4, ; CHECK: ret void @@ -136,7 +136,7 @@ ; CHECK: %[[A:.*]] = mul i64 4, %cnt ; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 %[[A]], i1 false) ; CALL: call void @__msan_poison_stack(i8* {{.*}}, i64 %[[A]]) -; ORIGIN: call void @__msan_set_alloca_origin(i8* {{.*}}, i64 %[[A]], +; ORIGIN: call void @__msan_set_alloca_origin5(i8* {{.*}}, i64 %[[A]], ; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 %[[A]], ; CHECK: call void @llvm.lifetime.end ; CHECK: ret void @@ -176,36 +176,36 @@ ; CHECK: %x = alloca i32 ; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 4, i1 false) ; CALL: call void @__msan_poison_stack(i8* {{.*}}, i64 4) -; ORIGIN: call void @__msan_set_alloca_origin(i8* {{.*}}, i64 4, +; ORIGIN: call void @__msan_set_alloca_origin5(i8* {{.*}}, i64 4, ; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 4, ; CHECK: %y = alloca i32 ; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 4, i1 false) ; CALL: call void @__msan_poison_stack(i8* {{.*}}, i64 4) -; ORIGIN: call void @__msan_set_alloca_origin(i8* {{.*}}, i64 4, +; ORIGIN: call void @__msan_set_alloca_origin5(i8* {{.*}}, i64 4, ; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 4, ; CHECK: %z = alloca i32 ; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 4, i1 false) ; CALL: call void @__msan_poison_stack(i8* {{.*}}, i64 4) -; ORIGIN: call void @__msan_set_alloca_origin(i8* {{.*}}, i64 4, +; ORIGIN: call void @__msan_set_alloca_origin5(i8* {{.*}}, i64 4, ; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 4, ; There're two lifetime intrinsics for %z, but we must instrument it only once. ; INLINE-NOT: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 4, i1 false) ; CALL-NOT: call void @__msan_poison_stack(i8* {{.*}}, i64 4) -; ORIGIN-NOT: call void @__msan_set_alloca_origin(i8* {{.*}}, i64 4, +; ORIGIN-NOT: call void @__msan_set_alloca_origin5(i8* {{.*}}, i64 4, ; KMSAN-NOT: call void @__msan_poison_alloca(i8* {{.*}}, i64 4, ; CHECK-LABEL: another_bb: ; CHECK: call void @llvm.lifetime.start ; INLINE-NOT: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 4, i1 false) ; CALL-NOT: call void @__msan_poison_stack(i8* {{.*}}, i64 4) -; ORIGIN-NOT: call void @__msan_set_alloca_origin(i8* {{.*}}, i64 4, +; ORIGIN-NOT: call void @__msan_set_alloca_origin5(i8* {{.*}}, i64 4, ; KMSAN-NOT: call void @__msan_poison_alloca(i8* {{.*}}, i64 4, ; CHECK: call void @llvm.lifetime.end ; CHECK: call void @llvm.lifetime.start ; INLINE-NOT: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 4, i1 false) ; CALL-NOT: call void @__msan_poison_stack(i8* {{.*}}, i64 4) -; ORIGIN-NOT: call void @__msan_set_alloca_origin(i8* {{.*}}, i64 4, +; ORIGIN-NOT: call void @__msan_set_alloca_origin5(i8* {{.*}}, i64 4, ; KMSAN-NOT: call void @__msan_poison_alloca(i8* {{.*}}, i64 4, ; CHECK: call void @llvm.lifetime.end