diff options
| -rw-r--r-- | clang/include/clang/Basic/CodeGenOptions.h | 2 | ||||
| -rw-r--r-- | clang/include/clang/Driver/CC1Options.td | 2 | ||||
| -rw-r--r-- | clang/include/clang/Driver/Options.td | 4 | ||||
| -rw-r--r-- | clang/include/clang/Driver/SanitizerArgs.h | 1 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGCall.cpp | 6 | ||||
| -rw-r--r-- | clang/lib/Driver/SanitizerArgs.cpp | 17 | ||||
| -rw-r--r-- | clang/lib/Frontend/CompilerInvocation.cpp | 2 | ||||
| -rw-r--r-- | clang/test/CodeGen/default-function-attr.c | 6 | ||||
| -rw-r--r-- | clang/test/Driver/fsanitize.c | 8 | ||||
| -rw-r--r-- | compiler-rt/lib/hwasan/hwasan_interceptors.cc | 30 | ||||
| -rw-r--r-- | compiler-rt/lib/hwasan/hwasan_linux.cc | 7 | ||||
| -rw-r--r-- | llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp | 29 | ||||
| -rw-r--r-- | llvm/test/Instrumentation/HWAddressSanitizer/lazy-thread-init.ll | 25 |
13 files changed, 106 insertions, 33 deletions
diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h index a12744ee3d2..ec6eda7fb78 100644 --- a/clang/include/clang/Basic/CodeGenOptions.h +++ b/clang/include/clang/Basic/CodeGenOptions.h @@ -286,6 +286,8 @@ public: /// Set of XRay instrumentation kinds to emit. XRayInstrSet XRayInstrumentationBundle; + std::vector<std::string> DefaultFunctionAttrs; + public: // Define accessors/mutators for code generation options of enumeration type. #define CODEGENOPT(Name, Bits, Default) diff --git a/clang/include/clang/Driver/CC1Options.td b/clang/include/clang/Driver/CC1Options.td index c0e73e56d7a..07c76884063 100644 --- a/clang/include/clang/Driver/CC1Options.td +++ b/clang/include/clang/Driver/CC1Options.td @@ -163,6 +163,8 @@ let Flags = [CC1Option, CC1AsOption, NoDriverOption] in { def debug_info_kind_EQ : Joined<["-"], "debug-info-kind=">; def debug_info_macro : Flag<["-"], "debug-info-macro">, HelpText<"Emit macro debug information">; +def default_function_attr : Separate<["-"], "default-function-attr">, + HelpText<"Apply given attribute to all functions">; def dwarf_version_EQ : Joined<["-"], "dwarf-version=">; def debugger_tuning_EQ : Joined<["-"], "debugger-tuning=">; def fdebug_compilation_dir : Separate<["-"], "fdebug-compilation-dir">, diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 809b28b9ddb..1c5cae683a1 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -998,6 +998,10 @@ def fno_sanitize_address_use_odr_indicator : Flag<["-"], "fno-sanitize-address-use-odr-indicator">, Group<f_clang_Group>, HelpText<"Disable ODR indicator globals">; +def fsanitize_hwaddress_abi_EQ + : Joined<["-"], "fsanitize-hwaddress-abi=">, + Group<f_clang_Group>, + HelpText<"Select the HWAddressSanitizer ABI to target (interceptor or platform, default interceptor)">; def fsanitize_recover : Flag<["-"], "fsanitize-recover">, Group<f_clang_Group>; def fno_sanitize_recover : Flag<["-"], "fno-sanitize-recover">, Flags<[CoreOption, DriverOption]>, diff --git a/clang/include/clang/Driver/SanitizerArgs.h b/clang/include/clang/Driver/SanitizerArgs.h index 55c5826bfb0..02338c22165 100644 --- a/clang/include/clang/Driver/SanitizerArgs.h +++ b/clang/include/clang/Driver/SanitizerArgs.h @@ -39,6 +39,7 @@ class SanitizerArgs { bool AsanPoisonCustomArrayCookie = false; bool AsanGlobalsDeadStripping = false; bool AsanUseOdrIndicator = false; + std::string HwasanAbi; bool LinkCXXRuntimes = false; bool NeedPIE = false; bool SafeStackRuntime = false; diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 64e18e171e0..09116d465e3 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -1816,6 +1816,12 @@ void CodeGenModule::ConstructDefaultFnAttrList(StringRef Name, bool HasOptnone, if (CodeGenOpts.FlushDenorm) FuncAttrs.addAttribute("nvptx-f32ftz", "true"); } + + for (StringRef Attr : CodeGenOpts.DefaultFunctionAttrs) { + StringRef Var, Value; + std::tie(Var, Value) = Attr.split('='); + FuncAttrs.addAttribute(Var, Value); + } } void CodeGenModule::AddDefaultFnAttrs(llvm::Function &F) { diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp index 4e0d7491bbe..6667cbb347c 100644 --- a/clang/lib/Driver/SanitizerArgs.cpp +++ b/clang/lib/Driver/SanitizerArgs.cpp @@ -741,6 +741,18 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC, AsanUseAfterScope = false; } + if (AllAddedKinds & HWAddress) { + if (Arg *HwasanAbiArg = + Args.getLastArg(options::OPT_fsanitize_hwaddress_abi_EQ)) { + HwasanAbi = HwasanAbiArg->getValue(); + if (HwasanAbi != "platform" && HwasanAbi != "interceptor") + D.Diag(clang::diag::err_drv_invalid_value) + << HwasanAbiArg->getAsString(Args) << HwasanAbi; + } else { + HwasanAbi = "interceptor"; + } + } + if (AllAddedKinds & SafeStack) { // SafeStack runtime is built into the system on Fuchsia. SafeStackRuntime = !TC.getTriple().isOSFuchsia(); @@ -913,6 +925,11 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, if (AsanUseOdrIndicator) CmdArgs.push_back("-fsanitize-address-use-odr-indicator"); + if (!HwasanAbi.empty()) { + CmdArgs.push_back("-default-function-attr"); + CmdArgs.push_back(Args.MakeArgString("hwasan-abi=" + HwasanAbi)); + } + // MSan: Workaround for PR16386. // ASan: This is mainly to help LSan with cases such as // https://github.com/google/sanitizers/issues/373 diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 39152fda998..00083bd6225 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1319,6 +1319,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.SpeculativeLoadHardening = Args.hasArg(OPT_mspeculative_load_hardening); + Opts.DefaultFunctionAttrs = Args.getAllArgValues(OPT_default_function_attr); + return Success; } diff --git a/clang/test/CodeGen/default-function-attr.c b/clang/test/CodeGen/default-function-attr.c new file mode 100644 index 00000000000..b0d1398a157 --- /dev/null +++ b/clang/test/CodeGen/default-function-attr.c @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -default-function-attr foo=bar -emit-llvm %s -o - | FileCheck %s + +// CHECK: define void @foo() #[[X:[0-9]+]] +void foo() {} + +// CHECK: attributes #[[X]] = {{.*}} "foo"="bar" diff --git a/clang/test/Driver/fsanitize.c b/clang/test/Driver/fsanitize.c index 0a82174aaa4..de455617141 100644 --- a/clang/test/Driver/fsanitize.c +++ b/clang/test/Driver/fsanitize.c @@ -837,3 +837,11 @@ // // RUN: %clang -target x86_64-linux-gnu -fsanitize=scudo,kernel-memory %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO-KMSAN // CHECK-SCUDO-KMSAN: error: invalid argument '-fsanitize=kernel-memory' not allowed with '-fsanitize=scudo' + +// RUN: %clang -target x86_64-linux-gnu -fsanitize=hwaddress %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-HWASAN-INTERCEPTOR-ABI +// RUN: %clang -target x86_64-linux-gnu -fsanitize=hwaddress -fsanitize-hwaddress-abi=interceptor %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-HWASAN-INTERCEPTOR-ABI +// RUN: %clang -target x86_64-linux-gnu -fsanitize=hwaddress -fsanitize-hwaddress-abi=platform %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-HWASAN-PLATFORM-ABI +// RUN: %clang -target x86_64-linux-gnu -fsanitize=hwaddress -fsanitize-hwaddress-abi=foo %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-HWASAN-FOO-ABI +// CHECK-HWASAN-INTERCEPTOR-ABI: "-default-function-attr" "hwasan-abi=interceptor" +// CHECK-HWASAN-PLATFORM-ABI: "-default-function-attr" "hwasan-abi=platform" +// CHECK-HWASAN-FOO-ABI: error: invalid value 'foo' in '-fsanitize-hwaddress-abi=foo' diff --git a/compiler-rt/lib/hwasan/hwasan_interceptors.cc b/compiler-rt/lib/hwasan/hwasan_interceptors.cc index 533426c2e38..edb19a56113 100644 --- a/compiler-rt/lib/hwasan/hwasan_interceptors.cc +++ b/compiler-rt/lib/hwasan/hwasan_interceptors.cc @@ -217,35 +217,6 @@ INTERCEPTOR_ALIAS(void, malloc_stats, void); #endif #endif // HWASAN_WITH_INTERCEPTORS - -#if HWASAN_WITH_INTERCEPTORS -extern "C" int pthread_attr_init(void *attr); -extern "C" int pthread_attr_destroy(void *attr); - -struct ThreadStartArg { - thread_callback_t callback; - void *param; -}; - -static void *HwasanThreadStartFunc(void *arg) { - __hwasan_thread_enter(); - ThreadStartArg A = *reinterpret_cast<ThreadStartArg*>(arg); - UnmapOrDie(arg, GetPageSizeCached()); - return A.callback(A.param); -} - -INTERCEPTOR(int, pthread_create, void *th, void *attr, void *(*callback)(void*), - void * param) { - ScopedTaggingDisabler disabler; - ThreadStartArg *A = reinterpret_cast<ThreadStartArg *> (MmapOrDie( - GetPageSizeCached(), "pthread_create")); - *A = {callback, param}; - int res = REAL(pthread_create)(UntagPtr(th), UntagPtr(attr), - &HwasanThreadStartFunc, A); - return res; -} -#endif // HWASAN_WITH_INTERCEPTORS - static void BeforeFork() { StackDepotLockAll(); } @@ -285,7 +256,6 @@ void InitializeInterceptors() { INTERCEPT_FUNCTION(fork); #if HWASAN_WITH_INTERCEPTORS - INTERCEPT_FUNCTION(pthread_create); INTERCEPT_FUNCTION(realloc); INTERCEPT_FUNCTION(free); #endif diff --git a/compiler-rt/lib/hwasan/hwasan_linux.cc b/compiler-rt/lib/hwasan/hwasan_linux.cc index 2238d3848d8..5b0a8b4ac98 100644 --- a/compiler-rt/lib/hwasan/hwasan_linux.cc +++ b/compiler-rt/lib/hwasan/hwasan_linux.cc @@ -302,7 +302,12 @@ void AndroidTestTlsSlot() {} #endif Thread *GetCurrentThread() { - auto *R = (StackAllocationsRingBuffer*)GetCurrentThreadLongPtr(); + uptr *ThreadLong = GetCurrentThreadLongPtr(); +#if HWASAN_WITH_INTERCEPTORS + if (!*ThreadLong) + __hwasan_thread_enter(); +#endif + auto *R = (StackAllocationsRingBuffer *)ThreadLong; return hwasanThreadList().GetThreadByBufferAddress((uptr)(R->Next())); } diff --git a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp index 67a0e98cbd5..caa383b57f9 100644 --- a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp @@ -264,6 +264,7 @@ private: Function *HwasanTagMemoryFunc; Function *HwasanGenerateTagFunc; + Function *HwasanThreadEnterFunc; Constant *ShadowGlobal; @@ -391,6 +392,9 @@ void HWAddressSanitizer::initializeCallbacks(Module &M) { HWAsanMemset = checkSanitizerInterfaceFunction(M.getOrInsertFunction( MemIntrinCallbackPrefix + "memset", IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), IRB.getInt32Ty(), IntptrTy)); + + HwasanThreadEnterFunc = checkSanitizerInterfaceFunction( + M.getOrInsertFunction("__hwasan_thread_enter", IRB.getVoidTy())); } Value *HWAddressSanitizer::getDynamicShadowNonTls(IRBuilder<> &IRB) { @@ -806,14 +810,35 @@ Value *HWAddressSanitizer::emitPrologue(IRBuilder<> &IRB, Value *SlotPtr = getHwasanThreadSlotPtr(IRB, IntptrTy); assert(SlotPtr); - Value *ThreadLong = IRB.CreateLoad(SlotPtr); + Instruction *ThreadLong = IRB.CreateLoad(SlotPtr); + + Function *F = IRB.GetInsertBlock()->getParent(); + if (F->getFnAttribute("hwasan-abi").getValueAsString() == "interceptor") { + Value *ThreadLongEqZero = + IRB.CreateICmpEQ(ThreadLong, ConstantInt::get(IntptrTy, 0)); + auto *Br = cast<BranchInst>(SplitBlockAndInsertIfThen( + ThreadLongEqZero, cast<Instruction>(ThreadLongEqZero)->getNextNode(), + false, MDBuilder(*C).createBranchWeights(1, 100000))); + + IRB.SetInsertPoint(Br); + // FIXME: This should call a new runtime function with a custom calling + // convention to avoid needing to spill all arguments here. + IRB.CreateCall(HwasanThreadEnterFunc); + LoadInst *ReloadThreadLong = IRB.CreateLoad(SlotPtr); + + IRB.SetInsertPoint(&*Br->getSuccessor(0)->begin()); + PHINode *ThreadLongPhi = IRB.CreatePHI(IntptrTy, 2); + ThreadLongPhi->addIncoming(ThreadLong, ThreadLong->getParent()); + ThreadLongPhi->addIncoming(ReloadThreadLong, ReloadThreadLong->getParent()); + ThreadLong = ThreadLongPhi; + } + // Extract the address field from ThreadLong. Unnecessary on AArch64 with TBI. Value *ThreadLongMaybeUntagged = TargetTriple.isAArch64() ? ThreadLong : untagPointer(IRB, ThreadLong); if (WithFrameRecord) { // Prepare ring buffer data. - Function *F = IRB.GetInsertBlock()->getParent(); auto PC = IRB.CreatePtrToInt(F, IntptrTy); auto GetStackPointerFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::frameaddress); diff --git a/llvm/test/Instrumentation/HWAddressSanitizer/lazy-thread-init.ll b/llvm/test/Instrumentation/HWAddressSanitizer/lazy-thread-init.ll new file mode 100644 index 00000000000..dab62d6f6b2 --- /dev/null +++ b/llvm/test/Instrumentation/HWAddressSanitizer/lazy-thread-init.ll @@ -0,0 +1,25 @@ +; RUN: opt -S -hwasan < %s | FileCheck %s + +target triple = "x86_64-unknown-linux-gnu" + +declare void @bar([16 x i32]* %p) + +define void @foo() sanitize_hwaddress "hwasan-abi"="interceptor" { + ; CHECK: [[LOAD:%[^ ]*]] = load i64, i64* @__hwasan_tls + ; CHECK: [[ICMP:%[^ ]*]] = icmp eq i64 [[LOAD]], 0 + ; CHECK: br i1 [[ICMP]], label %[[INIT:[^,]*]], label %[[CONT:[^,]*]], !prof [[PROF:![0-9]+]] + + ; CHECK: [[INIT]]: + ; CHECK: call void @__hwasan_thread_enter() + ; CHECK: [[RELOAD:%[^ ]*]] = load i64, i64* @__hwasan_tls + ; CHECK: br label %[[CONT]] + + ; CHECK: [[CONT]]: + ; CHECK: phi i64 [ [[LOAD]], %0 ], [ [[RELOAD]], %[[INIT]] ] + + %p = alloca [16 x i32] + call void @bar([16 x i32]* %p) + ret void +} + +; CHECK: [[PROF]] = !{!"branch_weights", i32 1, i32 100000} |

