diff --git a/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp --- a/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp @@ -450,6 +450,7 @@ Constant *getOrBuildTrampolineFunction(FunctionType *FT, StringRef FName); void initializeCallbackFunctions(Module &M); void initializeRuntimeFunctions(Module &M); + void injectMetadataGlobals(Module &M); bool init(Module &M); @@ -1267,6 +1268,26 @@ Mod->getOrInsertFunction("__dfsan_cmp_callback", DFSanCmpCallbackFnTy); } +void DataFlowSanitizer::injectMetadataGlobals(Module &M) { + // These variables can be used: + // - by the runtime (to discover what the shadow width was, during + // compilation) + // - in testing (to avoid hardcoding the shadow width and type but instead + // extract them by pattern matching) + Type *IntTy = Type::getInt32Ty(*Ctx); + (void)Mod->getOrInsertGlobal("__dfsan_shadow_width_bits", IntTy, [&] { + return new GlobalVariable( + M, IntTy, /*isConstant=*/true, GlobalValue::WeakODRLinkage, + ConstantInt::get(IntTy, ShadowWidthBits), "__dfsan_shadow_width_bits"); + }); + (void)Mod->getOrInsertGlobal("__dfsan_shadow_width_bytes", IntTy, [&] { + return new GlobalVariable(M, IntTy, /*isConstant=*/true, + GlobalValue::WeakODRLinkage, + ConstantInt::get(IntTy, ShadowWidthBytes), + "__dfsan_shadow_width_bytes"); + }); +} + bool DataFlowSanitizer::runImpl(Module &M) { init(M); @@ -1307,6 +1328,8 @@ "__dfsan_track_origins"); }); + injectMetadataGlobals(M); + ExternalShadowMask = Mod->getOrInsertGlobal(kDFSanExternShadowPtrMask, IntptrTy); diff --git a/llvm/test/Instrumentation/DataFlowSanitizer/basic.ll b/llvm/test/Instrumentation/DataFlowSanitizer/basic.ll --- a/llvm/test/Instrumentation/DataFlowSanitizer/basic.ll +++ b/llvm/test/Instrumentation/DataFlowSanitizer/basic.ll @@ -9,34 +9,36 @@ ; CHECK: @__dfsan_retval_origin_tls = external thread_local(initialexec) global i32 ; CHECK_NO_ORIGIN: @__dfsan_track_origins = weak_odr constant i32 0 ; CHECK_ORIGIN: @__dfsan_track_origins = weak_odr constant i32 1 +; CHECK: @__dfsan_shadow_width_bits = weak_odr constant i32 [[#SBITS:]] +; CHECK: @__dfsan_shadow_width_bytes = weak_odr constant i32 [[#SBYTES:]] ; CHECK: @__dfsan_shadow_ptr_mask = external global i64 -; CHECK: declare void @__dfsan_load_callback(i16, i8*) -; CHECK: declare void @__dfsan_store_callback(i16, i8*) -; CHECK: declare void @__dfsan_mem_transfer_callback(i16*, i64) -; CHECK: declare void @__dfsan_cmp_callback(i16) +; CHECK: declare void @__dfsan_load_callback(i[[#SBITS]], i8*) +; CHECK: declare void @__dfsan_store_callback(i[[#SBITS]], i8*) +; CHECK: declare void @__dfsan_mem_transfer_callback(i[[#SBITS]]*, i64) +; CHECK: declare void @__dfsan_cmp_callback(i[[#SBITS]]) ; CHECK: ; Function Attrs: nounwind readnone -; CHECK-NEXT: declare zeroext i16 @__dfsan_union(i16 zeroext, i16 zeroext) #0 +; CHECK-NEXT: declare zeroext i[[#SBITS]] @__dfsan_union(i[[#SBITS]] zeroext, i[[#SBITS]] zeroext) #0 ; CHECK: ; Function Attrs: nounwind readnone -; CHECK-NEXT: declare zeroext i16 @dfsan_union(i16 zeroext, i16 zeroext) #0 +; CHECK-NEXT: declare zeroext i[[#SBITS]] @dfsan_union(i[[#SBITS]] zeroext, i[[#SBITS]] zeroext) #0 ; CHECK: ; Function Attrs: nounwind readonly -; CHECK-NEXT: declare zeroext i16 @__dfsan_union_load(i16*, i64) #1 +; CHECK-NEXT: declare zeroext i[[#SBITS]] @__dfsan_union_load(i[[#SBITS]]*, i64) #1 ; CHECK: ; Function Attrs: nounwind readonly -; CHECK-NEXT: declare zeroext i16 @__dfsan_union_load_fast16labels(i16*, i64) #1 +; CHECK-NEXT: declare zeroext i[[#SBITS]] @__dfsan_union_load_fast16labels(i[[#SBITS]]*, i64) #1 ; CHECK: ; Function Attrs: nounwind readonly ; CHECK-NEXT: declare zeroext i64 @__dfsan_load_label_and_origin(i8*, i64) #1 ; CHECK: declare void @__dfsan_unimplemented(i8*) -; CHECK: declare void @__dfsan_set_label(i16 zeroext, i32 zeroext, i8*, i64) +; CHECK: declare void @__dfsan_set_label(i[[#SBITS]] zeroext, i32 zeroext, i8*, i64) ; CHECK: declare void @__dfsan_nonzero_label() ; CHECK: declare void @__dfsan_vararg_wrapper(i8*) ; CHECK: declare zeroext i32 @__dfsan_chain_origin(i32 zeroext) ; CHECK: declare void @__dfsan_mem_origin_transfer(i8*, i8*, i64) -; CHECK: declare void @__dfsan_maybe_store_origin(i16 zeroext, i8*, i64, i32 zeroext) +; CHECK: declare void @__dfsan_maybe_store_origin(i[[#SBITS]] zeroext, i8*, i64, i32 zeroext) define void @foo() { ret void