From: Evgeniy Stepanov Date: Thu, 16 May 2019 23:54:41 +0000 (+0000) Subject: HWASan exception support. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f94a258fe82a464722d6e7b62651b26f645177af;p=llvm HWASan exception support. Summary: Adds a call to __hwasan_handle_vfork(SP) at each landingpad entry. Reusing __hwasan_handle_vfork instead of introducing a new runtime call in order to be ABI-compatible with old runtime library. Reviewers: pcc Subscribers: kubamracek, hiraditya, #sanitizers, llvm-commits Tags: #sanitizers, #llvm Differential Revision: https://reviews.llvm.org/D61968 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@360959 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp b/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp index 56db746565b..abbe5801de1 100644 --- a/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp +++ b/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp @@ -157,6 +157,11 @@ static cl::opt cl::desc("instrument memory intrinsics"), cl::Hidden, cl::init(true)); +static cl::opt + ClInstrumentLandingPads("hwasan-instrument-landing-pads", + cl::desc("instrument landing pads"), cl::Hidden, + cl::init(true)); + static cl::opt ClInlineAllChecks("hwasan-inline-all-checks", cl::desc("inline all checks"), cl::Hidden, cl::init(false)); @@ -202,6 +207,7 @@ public: Value *untagPointer(IRBuilder<> &IRB, Value *PtrLong); bool instrumentStack(SmallVectorImpl &Allocas, SmallVectorImpl &RetVec, Value *StackTag); + bool instrumentLandingPads(SmallVectorImpl &RetVec); Value *getNextTagWithCall(IRBuilder<> &IRB); Value *getStackBaseTag(IRBuilder<> &IRB); Value *getAllocaTag(IRBuilder<> &IRB, Value *StackTag, AllocaInst *AI, @@ -216,6 +222,7 @@ private: std::string CurModuleUniqueId; Triple TargetTriple; FunctionCallee HWAsanMemmove, HWAsanMemcpy, HWAsanMemset; + FunctionCallee HWAsanHandleVfork; // Frame description is a way to pass names/sizes of local variables // to the run-time w/o adding extra executable code in every function. @@ -440,6 +447,9 @@ void HWAddressSanitizer::initializeCallbacks(Module &M) { IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), IRB.getInt32Ty(), IntptrTy); + HWAsanHandleVfork = + M.getOrInsertFunction("__hwasan_handle_vfork", IRB.getVoidTy(), IntptrTy); + HwasanThreadEnterFunc = M.getOrInsertFunction("__hwasan_thread_enter", IRB.getVoidTy()); } @@ -955,6 +965,23 @@ Value *HWAddressSanitizer::emitPrologue(IRBuilder<> &IRB, return ShadowBase; } +bool HWAddressSanitizer::instrumentLandingPads( + SmallVectorImpl &LandingPadVec) { + Module *M = LandingPadVec[0]->getModule(); + Function *ReadRegister = + Intrinsic::getDeclaration(M, Intrinsic::read_register, IntptrTy); + const char *RegName = + (TargetTriple.getArch() == Triple::x86_64) ? "rsp" : "sp"; + MDNode *MD = MDNode::get(*C, {MDString::get(*C, RegName)}); + Value *Args[] = {MetadataAsValue::get(*C, MD)}; + + for (auto *LP : LandingPadVec) { + IRBuilder<> IRB(LP->getNextNode()); + IRB.CreateCall(HWAsanHandleVfork, {IRB.CreateCall(ReadRegister, Args)}); + } + return true; +} + bool HWAddressSanitizer::instrumentStack( SmallVectorImpl &Allocas, SmallVectorImpl &RetVec, Value *StackTag) { @@ -1023,6 +1050,7 @@ bool HWAddressSanitizer::sanitizeFunction(Function &F) { SmallVector ToInstrument; SmallVector AllocasToInstrument; SmallVector RetVec; + SmallVector LandingPadVec; for (auto &BB : F) { for (auto &Inst : BB) { if (ClInstrumentStack) @@ -1041,6 +1069,9 @@ bool HWAddressSanitizer::sanitizeFunction(Function &F) { isa(Inst)) RetVec.push_back(&Inst); + if (ClInstrumentLandingPads && isa(Inst)) + LandingPadVec.push_back(&Inst); + Value *MaybeMask = nullptr; bool IsWrite; unsigned Alignment; @@ -1052,13 +1083,17 @@ bool HWAddressSanitizer::sanitizeFunction(Function &F) { } } + initializeCallbacks(*F.getParent()); + + if (!LandingPadVec.empty()) + instrumentLandingPads(LandingPadVec); + if (AllocasToInstrument.empty() && ToInstrument.empty()) return false; if (ClCreateFrameDescriptions && !AllocasToInstrument.empty()) createFrameGlobal(F, createFrameString(AllocasToInstrument)); - initializeCallbacks(*F.getParent()); assert(!LocalDynamicShadow); diff --git a/test/Instrumentation/HWAddressSanitizer/landingpad.ll b/test/Instrumentation/HWAddressSanitizer/landingpad.ll new file mode 100644 index 00000000000..15cc0bc95d9 --- /dev/null +++ b/test/Instrumentation/HWAddressSanitizer/landingpad.ll @@ -0,0 +1,37 @@ +; RUN: opt < %s -mtriple aarch64-linux-android -hwasan -S | FileCheck %s --check-prefixes=COMMON,ARM +; RUN: opt < %s -mtriple x86_64-linux -hwasan -S | FileCheck %s --check-prefixes=COMMON,X86 + +target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" +target triple = "aarch64-unknown-linux-android" + +define i32 @f() local_unnamed_addr sanitize_hwaddress personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { +entry: + invoke void @g() + to label %return unwind label %lpad + +lpad: + ; COMMON: landingpad { i8*, i32 } + ; COMMON-NEXT: catch i8* null + %0 = landingpad { i8*, i32 } + catch i8* null + + ; COMMON-NEXT: %[[X:[^ ]*]] = call i64 @llvm.read_register.i64(metadata ![[META:[^ ]*]]) + ; COMMON-NEXT: call void @__hwasan_handle_vfork(i64 %[[X]]) + + %1 = extractvalue { i8*, i32 } %0, 0 + %2 = tail call i8* @__cxa_begin_catch(i8* %1) + tail call void @__cxa_end_catch() + br label %return +return: + %retval.0 = phi i32 [ 1, %lpad ], [ 0, %entry ] + ret i32 %retval.0 +} + +declare void @g() local_unnamed_addr + +declare i32 @__gxx_personality_v0(...) +declare i8* @__cxa_begin_catch(i8*) local_unnamed_addr +declare void @__cxa_end_catch() local_unnamed_addr + +; ARM: ![[META]] = !{!"sp"} +; X86: ![[META]] = !{!"rsp"}