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;
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;
}
void __msan_set_alloca_origin(void *a, uptr size, char *descr) {
- SetAllocaOrigin(a, size, descr, GET_CALLER_PC());
+ SetAllocaOrigin(a, size, reinterpret_cast<u32 *>(descr), descr + 4,
+ GET_CALLER_PC());
}
void __msan_set_alloca_origin4(void *a, uptr size, char *descr, uptr pc) {
// 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, GET_CALLER_PC());
+ SetAllocaOrigin(a, size, reinterpret_cast<u32 *>(descr), descr + 4,
+ GET_CALLER_PC());
+}
+
+void __msan_set_alloca_origin_with_descr(void *a, uptr size, u32 *id_ptr,
+ char *descr) {
+ SetAllocaOrigin(a, size, id_ptr, descr, GET_CALLER_PC());
}
u32 __msan_chain_origin(u32 id) {
/// Run-time helper that generates a new origin value for a stack
/// allocation.
- FunctionCallee MsanSetAllocaOriginFn;
+ FunctionCallee MsanSetAllocaOriginWithDescriptionFn;
/// Run-time helper that poisons stack on function entry.
FunctionCallee MsanPoisonStackFn;
/// 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, "");
}
IRB.getInt32Ty());
}
- MsanSetAllocaOriginFn = M.getOrInsertFunction(
- "__msan_set_alloca_origin", IRB.getVoidTy(), IRB.getInt8PtrTy(), IntptrTy,
- IRB.getInt8PtrTy());
+ MsanSetAllocaOriginWithDescriptionFn = M.getOrInsertFunction(
+ "__msan_set_alloca_origin_with_descr", IRB.getVoidTy(),
+ IRB.getInt8PtrTy(), IntptrTy, IRB.getInt8PtrTy(), IRB.getInt8PtrTy());
MsanPoisonStackFn =
M.getOrInsertFunction("__msan_poison_stack", IRB.getVoidTy(),
IRB.getInt8PtrTy(), IntptrTy);
"_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) {
}
if (PoisonStack && MS.TrackOrigins) {
+ Value *Idptr = getLocalVarIdptr(I);
Value *Descr = getLocalVarDescription(I);
- IRB.CreateCall(MS.MsanSetAllocaOriginFn,
+ IRB.CreateCall(MS.MsanSetAllocaOriginWithDescriptionFn,
{IRB.CreatePointerCast(&I, IRB.getInt8PtrTy()), Len,
+ IRB.CreatePointerCast(Idptr, IRB.getInt8PtrTy()),
IRB.CreatePointerCast(Descr, IRB.getInt8PtrTy())});
}
}
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
-; ORIGIN: [[D:@[0-9]+]] = private global [13 x i8] c"----unique_x\00"
+; ORIGIN: [[IDPTR:@[0-9]+]] = private global i32 0
+; ORIGIN: [[DESCR:@[0-9]+]] = private constant [9 x i8] c"unique_x\00"
define void @static() sanitize_memory {
entry:
; 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, i8* {{.*}} [[D]],
+; ORIGIN: call void @__msan_set_alloca_origin_with_descr(i8* {{.*}}, i64 4, i8* {{.*}} [[IDPTR]] {{.*}}, i8* {{.*}} [[DESCR]],
; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 4,
; CHECK: ret void
; 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_origin_with_descr(i8* {{.*}}, i64 4,
; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 4,
; CHECK: ret void
; 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_origin_with_descr(i8* {{.*}}, i64 20,
; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 20,
; CHECK: ret void
; 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_origin_with_descr(i8* {{.*}}, i64 %[[A]],
; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 %[[A]],
; CHECK: ret void
; 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_origin_with_descr(i8* {{.*}}, i64 20,
; KMSAN: call void @__msan_unpoison_alloca(i8* {{.*}}, i64 20)
; CHECK: ret void
; 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_origin_with_descr(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_origin_with_descr(i8* {{.*}}, i64 4,
; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 4,
; CHECK: ret void
; 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_origin_with_descr(i8* {{.*}}, i64 %[[A]],
; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 %[[A]],
; CHECK: call void @llvm.lifetime.end
; CHECK: ret void
; 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_origin_with_descr(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_origin_with_descr(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_origin_with_descr(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_origin_with_descr(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_origin_with_descr(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_origin_with_descr(i8* {{.*}}, i64 4,
; KMSAN-NOT: call void @__msan_poison_alloca(i8* {{.*}}, i64 4,
; CHECK: call void @llvm.lifetime.end