From: Julian Lettner Date: Sat, 2 Feb 2019 02:05:16 +0000 (+0000) Subject: [ASan] Do not instrument other runtime functions with `__asan_handle_no_return` X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=cb8d1d7cc8c8ae9cc5ed6692f9e117a96d4c03fc;p=llvm [ASan] Do not instrument other runtime functions with `__asan_handle_no_return` Summary: Currently, ASan inserts a call to `__asan_handle_no_return` before every `noreturn` function call/invoke. This is unnecessary for calls to other runtime funtions. This patch changes ASan to skip instrumentation for functions calls marked with `!nosanitize` metadata. Reviewers: TODO Differential Revision: https://reviews.llvm.org/D57489 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@352948 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/lib/Transforms/Instrumentation/AddressSanitizer.cpp index 978ec491f00..e95b88b579c 100644 --- a/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ b/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -2554,7 +2554,8 @@ bool AddressSanitizer::runOnFunction(Function &F) { if (CS) { // A call inside BB. TempsToInstrument.clear(); - if (CS.doesNotReturn()) NoReturnCalls.push_back(CS.getInstruction()); + if (CS.doesNotReturn() && !CS->getMetadata("nosanitize")) + NoReturnCalls.push_back(CS.getInstruction()); } if (CallInst *CI = dyn_cast(&Inst)) maybeMarkSanitizerLibraryCallNoBuiltin(CI, TLI); @@ -2591,7 +2592,7 @@ bool AddressSanitizer::runOnFunction(Function &F) { FunctionStackPoisoner FSP(F, *this); bool ChangedStack = FSP.runOnFunction(); - // We must unpoison the stack before every NoReturn call (throw, _exit, etc). + // We must unpoison the stack before NoReturn calls (throw, _exit, etc). // See e.g. https://github.com/google/sanitizers/issues/37 for (auto CI : NoReturnCalls) { IRBuilder<> IRB(CI); diff --git a/test/Instrumentation/AddressSanitizer/instrument-no-return.ll b/test/Instrumentation/AddressSanitizer/instrument-no-return.ll index 2e90bfc64b2..0df85c710a4 100644 --- a/test/Instrumentation/AddressSanitizer/instrument-no-return.ll +++ b/test/Instrumentation/AddressSanitizer/instrument-no-return.ll @@ -1,37 +1,45 @@ -; RUN: opt < %s -asan -asan-module -S | FileCheck %s +; RUN: opt < %s -asan -S | FileCheck %s ; AddressSanitizer must insert __asan_handle_no_return -; before every noreturn call or invoke. +; before noreturn calls that aren't inserted by sanitizers. 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" target triple = "x86_64-unknown-linux-gnu" -declare void @MyNoReturnFunc(i32) noreturn +declare void @NormalFunc() +declare void @NoReturnFunc() noreturn -define i32 @Call1(i8* nocapture %arg) uwtable sanitize_address { -entry: - call void @MyNoReturnFunc(i32 1) noreturn ; The call insn has noreturn attr. -; CHECK: @Call1 -; CHECK: call void @__asan_handle_no_return -; CHECK-NEXT: call void @MyNoReturnFunc -; CHECK-NEXT: unreachable +; Instrument noreturn callsites (regardless of function) +define i32 @Call1() sanitize_address { + call void @NormalFunc() noreturn unreachable } +; CHECK-LABEL: @Call1 +; CHECK-NEXT: call void @__asan_handle_no_return +; CHECK-NEXT: call void @NormalFunc -define i32 @Call2(i8* nocapture %arg) uwtable sanitize_address { -entry: - call void @MyNoReturnFunc(i32 1) ; No noreturn attribure on the call. -; CHECK: @Call2 -; CHECK: call void @__asan_handle_no_return -; CHECK-NEXT: call void @MyNoReturnFunc -; CHECK-NEXT: unreachable +; Instrument calls to noreturn functions (regardless of callsite) +define i32 @Call2() sanitize_address { + call void @NoReturnFunc() + unreachable +} +; CHECK-LABEL: @Call2 +; CHECK-NEXT: call void @__asan_handle_no_return +; CHECK-NEXT: call void @NoReturnFunc + +; Do *not* instrument callsites marked !nosanitize +define i32 @Call3() sanitize_address { + call void @NoReturnFunc() noreturn, !nosanitize !{} unreachable } +; CHECK-LABEL: @Call3 +; CHECK-NOT: call void @__asan_handle_no_return +; CHECK: call void @NoReturnFunc declare i32 @__gxx_personality_v0(...) -define i64 @Invoke1(i8** %esc) nounwind uwtable ssp sanitize_address personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { +define i64 @Invoke1() nounwind uwtable ssp sanitize_address personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { entry: - invoke void @MyNoReturnFunc(i32 1) + invoke void @NoReturnFunc() to label %invoke.cont unwind label %lpad invoke.cont: @@ -42,8 +50,8 @@ lpad: filter [0 x i8*] zeroinitializer ret i64 1 } -; CHECK: @Invoke1 +; CHECK-LABEL: @Invoke1 ; CHECK: call void @__asan_handle_no_return -; CHECK-NEXT: invoke void @MyNoReturnFunc +; CHECK-NEXT: invoke void @NoReturnFunc ; CHECK: ret i64 0 ; CHECK: ret i64 1