diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp --- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -44,6 +44,7 @@ #include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/DebugLoc.h" #include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/EHPersonalities.h" #include "llvm/IR/Function.h" #include "llvm/IR/GlobalAlias.h" #include "llvm/IR/GlobalValue.h" @@ -640,6 +641,82 @@ } namespace { +/// Helper class to keep track of the inserted runtime calls during a pass on a +/// single Function. At the end of that pass, calling finalize() will detect and +/// add the corresponding funclet OpBundle to the inserted calls. +class RuntimeCallInserter { + Function *OwnerFn = nullptr; + std::optional> InsertedCalls; + + void reset() { + OwnerFn = nullptr; + InsertedCalls.reset(); + } + +public: + ~RuntimeCallInserter() { assert(!isInitialized()); } + + bool isInitialized() const { return OwnerFn != nullptr; } + + void initialize(Function &Fn) { + assert(!isInitialized() && !InsertedCalls); + OwnerFn = &Fn; + if (Fn.hasPersonalityFn()) { + auto Personality = classifyEHPersonality(Fn.getPersonalityFn()); + if (isScopedEHPersonality(Personality)) + InsertedCalls.emplace(); + } + } + + CallInst *createRuntimeCall(IRBuilder<> &IRB, FunctionCallee Callee, + ArrayRef Args = {}, + const Twine &Name = "") { + assert(isInitialized()); + assert(IRB.GetInsertBlock()->getParent() == OwnerFn); + + CallInst *Inst = IRB.CreateCall(Callee, Args, Name, nullptr); + if (InsertedCalls) { + auto Fn = dyn_cast(Callee.getCallee()); + bool IsIntrinsicCallee = Fn && Fn->isIntrinsic(); + if (!IsIntrinsicCallee) + InsertedCalls->push_back(Inst); + } + return Inst; + } + + void finalize() { + assert(isInitialized()); + if (!InsertedCalls || InsertedCalls->empty()) { + reset(); + return; + } + + DenseMap BlockColors = colorEHFunclets(*OwnerFn); + for (CallInst *CI : *InsertedCalls) { + BasicBlock *BB = CI->getParent(); + assert(BB && "Instruction doesn't belong to a BasicBlock"); + assert(BB->getParent() == OwnerFn && + "Instruction doesn't belong to the expected Function!"); + + ColorVector &Colors = BlockColors[BB]; + assert(Colors.size() == 1 && "Expected monochromatic BB!"); + + BasicBlock *Color = Colors.front(); + Instruction *EHPad = Color->getFirstNonPHI(); + + if (EHPad && EHPad->isEHPad()) { + // Replace CI with a clone with funclet OperandBundle + OperandBundleDef OB("funclet", EHPad); + auto *NewCall = + CallBase::addOperandBundle(CI, LLVMContext::OB_funclet, OB, CI); + NewCall->copyMetadata(*CI); + CI->replaceAllUsesWith(NewCall); + CI->eraseFromParent(); + } + } + reset(); + } +}; /// AddressSanitizer: instrument the code in module to find memory bugs. struct AddressSanitizer { @@ -716,6 +793,12 @@ bool maybeInsertDynamicShadowAtFunctionEntry(Function &F); void markEscapedLocalAllocas(Function &F); + CallInst *createRuntimeCall(IRBuilder<> &IRB, FunctionCallee Callee, + ArrayRef Args = {}, + const Twine &Name = "") { + return RtCallInserter.createRuntimeCall(IRB, Callee, Args, Name); + } + private: friend struct FunctionStackPoisoner; @@ -739,6 +822,7 @@ ~FunctionStateRAII() { Pass->LocalDynamicShadow = nullptr; Pass->ProcessedAllocas.clear(); + assert(!Pass->RtCallInserter.isInitialized()); } }; @@ -757,6 +841,8 @@ FunctionCallee AsanPtrCmpFunction, AsanPtrSubFunction; Constant *AsanShadowGlobal; + RuntimeCallInserter RtCallInserter; + // These arrays is indexed by AccessIsWrite, Experiment and log2(AccessSize). FunctionCallee AsanErrorCallback[2][2][kNumberOfAccessSizes]; FunctionCallee AsanMemoryAccessCallback[2][2][kNumberOfAccessSizes]; @@ -844,7 +930,8 @@ bool shouldInstrumentGlobal(GlobalVariable *G) const; bool ShouldUseMachOGlobalsSection() const; StringRef getGlobalMetadataSection() const; - void poisonOneInitializer(Function &GlobalInit, GlobalValue *ModuleName); + void poisonOneInitializer(RuntimeCallInserter &RCI, Function &GlobalInit, + GlobalValue *ModuleName); void createInitializerPoisonCalls(Module &M, GlobalValue *ModuleName); uint64_t getMinRedzoneSizeForGlobal() const { return getRedzoneSizeForScale(Mapping.Scale); @@ -875,6 +962,9 @@ Function *AsanCtorFunction = nullptr; Function *AsanDtorFunction = nullptr; + + RuntimeCallInserter AsanCtorCallInserter; + RuntimeCallInserter AsanDtorCallInserter; }; // Stack poisoning does not play well with exception handling. @@ -1011,8 +1101,8 @@ DynamicAreaOffset); } - IRB.CreateCall( - AsanAllocasUnpoisonFunc, + ASan.createRuntimeCall( + IRB, AsanAllocasUnpoisonFunc, {IRB.CreateLoad(IntptrTy, DynamicAllocaLayout), DynamicAreaPtr}); } @@ -1229,14 +1319,14 @@ void AddressSanitizer::instrumentMemIntrinsic(MemIntrinsic *MI) { IRBuilder<> IRB(MI); if (isa(MI)) { - IRB.CreateCall( - isa(MI) ? AsanMemmove : AsanMemcpy, + createRuntimeCall( + IRB, isa(MI) ? AsanMemmove : AsanMemcpy, {IRB.CreatePointerCast(MI->getOperand(0), IRB.getInt8PtrTy()), IRB.CreatePointerCast(MI->getOperand(1), IRB.getInt8PtrTy()), IRB.CreateIntCast(MI->getOperand(2), IntptrTy, false)}); } else if (isa(MI)) { - IRB.CreateCall( - AsanMemset, + createRuntimeCall( + IRB, AsanMemset, {IRB.CreatePointerCast(MI->getOperand(0), IRB.getInt8PtrTy()), IRB.CreateIntCast(MI->getOperand(1), IRB.getInt32Ty(), false), IRB.CreateIntCast(MI->getOperand(2), IntptrTy, false)}); @@ -1410,7 +1500,7 @@ if (i->getType()->isPointerTy()) i = IRB.CreatePointerCast(i, IntptrTy); } - IRB.CreateCall(F, Param); + createRuntimeCall(IRB, F, Param); } static void doInstrumentAddress(AddressSanitizer *Pass, Instruction *I, @@ -1534,18 +1624,18 @@ CallInst *Call = nullptr; if (SizeArgument) { if (Exp == 0) - Call = IRB.CreateCall(AsanErrorCallbackSized[IsWrite][0], - {Addr, SizeArgument}); + Call = createRuntimeCall(IRB, AsanErrorCallbackSized[IsWrite][0], + {Addr, SizeArgument}); else - Call = IRB.CreateCall(AsanErrorCallbackSized[IsWrite][1], - {Addr, SizeArgument, ExpVal}); + Call = createRuntimeCall(IRB, AsanErrorCallbackSized[IsWrite][1], + {Addr, SizeArgument, ExpVal}); } else { if (Exp == 0) - Call = - IRB.CreateCall(AsanErrorCallback[IsWrite][0][AccessSizeIndex], Addr); + Call = createRuntimeCall( + IRB, AsanErrorCallback[IsWrite][0][AccessSizeIndex], Addr); else - Call = IRB.CreateCall(AsanErrorCallback[IsWrite][1][AccessSizeIndex], - {Addr, ExpVal}); + Call = createRuntimeCall( + IRB, AsanErrorCallback[IsWrite][1][AccessSizeIndex], {Addr, ExpVal}); } Call->setCannotMerge(); @@ -1583,8 +1673,8 @@ // Instrument generic addresses in supported addressspaces. IRBuilder<> IRB(InsertBefore); Value *AddrLong = IRB.CreatePointerCast(Addr, IRB.getInt8PtrTy()); - Value *IsShared = IRB.CreateCall(AMDGPUAddressShared, {AddrLong}); - Value *IsPrivate = IRB.CreateCall(AMDGPUAddressPrivate, {AddrLong}); + Value *IsShared = createRuntimeCall(IRB, AMDGPUAddressShared, {AddrLong}); + Value *IsPrivate = createRuntimeCall(IRB, AMDGPUAddressPrivate, {AddrLong}); Value *IsSharedOrPrivate = IRB.CreateOr(IsShared, IsPrivate); Value *Cmp = IRB.CreateNot(IsSharedOrPrivate); Value *AddrSpaceZeroLanding = @@ -1612,8 +1702,8 @@ if (UseCalls && ClOptimizeCallbacks) { const ASanAccessInfo AccessInfo(IsWrite, CompileKernel, AccessSizeIndex); Module *M = IRB.GetInsertBlock()->getParent()->getParent(); - IRB.CreateCall( - Intrinsic::getDeclaration(M, Intrinsic::asan_check_memaccess), + createRuntimeCall( + IRB, Intrinsic::getDeclaration(M, Intrinsic::asan_check_memaccess), {IRB.CreatePointerCast(Addr, Int8PtrTy), ConstantInt::get(Int32Ty, AccessInfo.Packed)}); return; @@ -1622,11 +1712,12 @@ Value *AddrLong = IRB.CreatePointerCast(Addr, IntptrTy); if (UseCalls) { if (Exp == 0) - IRB.CreateCall(AsanMemoryAccessCallback[IsWrite][0][AccessSizeIndex], - AddrLong); + createRuntimeCall( + IRB, AsanMemoryAccessCallback[IsWrite][0][AccessSizeIndex], AddrLong); else - IRB.CreateCall(AsanMemoryAccessCallback[IsWrite][1][AccessSizeIndex], - {AddrLong, ConstantInt::get(IRB.getInt32Ty(), Exp)}); + createRuntimeCall(IRB, + AsanMemoryAccessCallback[IsWrite][1][AccessSizeIndex], + {AddrLong, ConstantInt::get(IRB.getInt32Ty(), Exp)}); return; } @@ -1680,11 +1771,12 @@ Value *AddrLong = IRB.CreatePointerCast(Addr, IntptrTy); if (UseCalls) { if (Exp == 0) - IRB.CreateCall(AsanMemoryAccessCallbackSized[IsWrite][0], - {AddrLong, Size}); + createRuntimeCall(IRB, AsanMemoryAccessCallbackSized[IsWrite][0], + {AddrLong, Size}); else - IRB.CreateCall(AsanMemoryAccessCallbackSized[IsWrite][1], - {AddrLong, Size, ConstantInt::get(IRB.getInt32Ty(), Exp)}); + createRuntimeCall( + IRB, AsanMemoryAccessCallbackSized[IsWrite][1], + {AddrLong, Size, ConstantInt::get(IRB.getInt32Ty(), Exp)}); } else { Value *LastByte = IRB.CreateIntToPtr( IRB.CreateAdd(AddrLong, ConstantInt::get(IntptrTy, TypeSize / 8 - 1)), @@ -1694,7 +1786,8 @@ } } -void ModuleAddressSanitizer::poisonOneInitializer(Function &GlobalInit, +void ModuleAddressSanitizer::poisonOneInitializer(RuntimeCallInserter &RCI, + Function &GlobalInit, GlobalValue *ModuleName) { // Set up the arguments to our poison/unpoison functions. IRBuilder<> IRB(&GlobalInit.front(), @@ -1702,7 +1795,7 @@ // Add a call to poison all external globals before the given function starts. Value *ModuleNameAddr = ConstantExpr::getPointerCast(ModuleName, IntptrTy); - IRB.CreateCall(AsanPoisonGlobals, ModuleNameAddr); + RCI.createRuntimeCall(IRB, AsanPoisonGlobals, ModuleNameAddr); // Add calls to unpoison all globals before each return instruction. for (auto &BB : GlobalInit) @@ -1731,7 +1824,10 @@ // Don't instrument CTORs that will run before asan.module_ctor. if (Priority->getLimitedValue() <= GetCtorAndDtorPriority(TargetTriple)) continue; - poisonOneInitializer(*F, ModuleName); + RuntimeCallInserter RCI; + RCI.initialize(*F); + poisonOneInitializer(RCI, *F, ModuleName); + RCI.finalize(); } } } @@ -2018,6 +2114,7 @@ AsanDtorFunction->addFnAttr(Attribute::NoUnwind); // Ensure Dtor cannot be discarded, even if in a comdat. appendToUsed(M, {AsanDtorFunction}); + AsanDtorCallInserter.initialize(*AsanDtorFunction); BasicBlock *AsanDtorBB = BasicBlock::Create(*C, "", AsanDtorFunction); return ReturnInst::Create(*C, AsanDtorBB); @@ -2109,19 +2206,21 @@ // Create a call to register the globals with the runtime. if (ConstructorKind == AsanCtorKind::Global) - IRB.CreateCall(AsanRegisterElfGlobals, - {IRB.CreatePointerCast(RegisteredFlag, IntptrTy), - IRB.CreatePointerCast(StartELFMetadata, IntptrTy), - IRB.CreatePointerCast(StopELFMetadata, IntptrTy)}); + AsanCtorCallInserter.createRuntimeCall( + IRB, AsanRegisterElfGlobals, + {IRB.CreatePointerCast(RegisteredFlag, IntptrTy), + IRB.CreatePointerCast(StartELFMetadata, IntptrTy), + IRB.CreatePointerCast(StopELFMetadata, IntptrTy)}); // We also need to unregister globals at the end, e.g., when a shared library // gets closed. if (DestructorKind != AsanDtorKind::None) { IRBuilder<> IrbDtor(CreateAsanModuleDtor(M)); - IrbDtor.CreateCall(AsanUnregisterElfGlobals, - {IRB.CreatePointerCast(RegisteredFlag, IntptrTy), - IRB.CreatePointerCast(StartELFMetadata, IntptrTy), - IRB.CreatePointerCast(StopELFMetadata, IntptrTy)}); + AsanDtorCallInserter.createRuntimeCall( + IrbDtor, AsanUnregisterElfGlobals, + {IRB.CreatePointerCast(RegisteredFlag, IntptrTy), + IRB.CreatePointerCast(StartELFMetadata, IntptrTy), + IRB.CreatePointerCast(StopELFMetadata, IntptrTy)}); } } @@ -2173,15 +2272,17 @@ RegisteredFlag->setVisibility(GlobalVariable::HiddenVisibility); if (ConstructorKind == AsanCtorKind::Global) - IRB.CreateCall(AsanRegisterImageGlobals, - {IRB.CreatePointerCast(RegisteredFlag, IntptrTy)}); + AsanCtorCallInserter.createRuntimeCall( + IRB, AsanRegisterImageGlobals, + {IRB.CreatePointerCast(RegisteredFlag, IntptrTy)}); // We also need to unregister globals at the end, e.g., when a shared library // gets closed. if (DestructorKind != AsanDtorKind::None) { IRBuilder<> IrbDtor(CreateAsanModuleDtor(M)); - IrbDtor.CreateCall(AsanUnregisterImageGlobals, - {IRB.CreatePointerCast(RegisteredFlag, IntptrTy)}); + AsanDtorCallInserter.createRuntimeCall( + IrbDtor, AsanUnregisterImageGlobals, + {IRB.CreatePointerCast(RegisteredFlag, IntptrTy)}); } } @@ -2203,17 +2304,19 @@ AllGlobals->setAlignment(Align(1ULL << Mapping.Scale)); if (ConstructorKind == AsanCtorKind::Global) - IRB.CreateCall(AsanRegisterGlobals, - {IRB.CreatePointerCast(AllGlobals, IntptrTy), - ConstantInt::get(IntptrTy, N)}); + AsanCtorCallInserter.createRuntimeCall( + IRB, AsanRegisterGlobals, + {IRB.CreatePointerCast(AllGlobals, IntptrTy), + ConstantInt::get(IntptrTy, N)}); // We also need to unregister globals at the end, e.g., when a shared library // gets closed. if (DestructorKind != AsanDtorKind::None) { IRBuilder<> IrbDtor(CreateAsanModuleDtor(M)); - IrbDtor.CreateCall(AsanUnregisterGlobals, - {IRB.CreatePointerCast(AllGlobals, IntptrTy), - ConstantInt::get(IntptrTy, N)}); + AsanDtorCallInserter.createRuntimeCall( + IrbDtor, AsanUnregisterGlobals, + {IRB.CreatePointerCast(AllGlobals, IntptrTy), + ConstantInt::get(IntptrTy, N)}); } } @@ -2473,6 +2576,7 @@ kAsanInitName, /*InitArgTypes=*/{}, /*InitArgs=*/{}, VersionCheckName); } + AsanCtorCallInserter.initialize(*AsanCtorFunction); } bool CtorComdat = true; @@ -2508,6 +2612,10 @@ appendToGlobalDtors(M, AsanDtorFunction, Priority); } + if (AsanCtorFunction) + AsanCtorCallInserter.finalize(); + if (AsanDtorFunction) + AsanDtorCallInserter.finalize(); return true; } @@ -2700,6 +2808,8 @@ FunctionStateRAII CleanupObj(this); + RtCallInserter.initialize(F); + FunctionModified |= maybeInsertDynamicShadowAtFunctionEntry(F); // We can't instrument allocas used with llvm.localescape. Only static allocas @@ -2721,7 +2831,10 @@ TempsToInstrument.clear(); int NumInsnsPerBB = 0; for (auto &Inst : BB) { - if (LooksLikeCodeInBug11395(&Inst)) return false; + if (LooksLikeCodeInBug11395(&Inst)) { + RtCallInserter.finalize(); + return false; + } // Skip instructions inserted by another instrumentation. if (Inst.hasMetadata(LLVMContext::MD_nosanitize)) continue; @@ -2798,7 +2911,7 @@ // See e.g. https://github.com/google/sanitizers/issues/37 for (auto *CI : NoReturnCalls) { IRBuilder<> IRB(CI); - IRB.CreateCall(AsanHandleNoReturnFunc, {}); + createRuntimeCall(IRB, AsanHandleNoReturnFunc, {}); } for (auto *Inst : PointerComparisonsOrSubtracts) { @@ -2809,6 +2922,8 @@ if (ChangedStack || !NoReturnCalls.empty()) FunctionModified = true; + RtCallInserter.finalize(); + LLVM_DEBUG(dbgs() << "ASAN done instrumenting: " << FunctionModified << " " << F << "\n"); @@ -2947,9 +3062,10 @@ if (j - i >= ClMaxInlinePoisoningSize) { copyToShadowInline(ShadowMask, ShadowBytes, Done, i, IRB, ShadowBase); - IRB.CreateCall(AsanSetShadowFunc[Val], - {IRB.CreateAdd(ShadowBase, ConstantInt::get(IntptrTy, i)), - ConstantInt::get(IntptrTy, j - i)}); + ASan.createRuntimeCall( + IRB, AsanSetShadowFunc[Val], + {IRB.CreateAdd(ShadowBase, ConstantInt::get(IntptrTy, i)), + ConstantInt::get(IntptrTy, j - i)}); Done = j; } } @@ -3236,8 +3352,8 @@ StackMallocIdx = StackMallocSizeClass(LocalStackSize); assert(StackMallocIdx <= kMaxAsanStackMallocSizeClass); Value *FakeStackValue = - IRBIf.CreateCall(AsanStackMallocFunc[StackMallocIdx], - ConstantInt::get(IntptrTy, LocalStackSize)); + ASan.createRuntimeCall(IRBIf, AsanStackMallocFunc[StackMallocIdx], + ConstantInt::get(IntptrTy, LocalStackSize)); IRB.SetInsertPoint(InsBefore); FakeStack = createPHI(IRB, UseAfterReturnIsEnabled, FakeStackValue, Term, ConstantInt::get(IntptrTy, 0)); @@ -3247,7 +3363,8 @@ // void *LocalStackBase = (FakeStack) ? FakeStack : // alloca(LocalStackSize); StackMallocIdx = StackMallocSizeClass(LocalStackSize); - FakeStack = IRB.CreateCall(AsanStackMallocFunc[StackMallocIdx], + FakeStack = + ASan.createRuntimeCall(IRB, AsanStackMallocFunc[StackMallocIdx], ConstantInt::get(IntptrTy, LocalStackSize)); } Value *NoFakeStack = @@ -3382,8 +3499,8 @@ IRBPoison.CreateIntToPtr(SavedFlagPtr, IRBPoison.getInt8PtrTy())); } else { // For larger frames call __asan_stack_free_*. - IRBPoison.CreateCall( - AsanStackFreeFunc[StackMallocIdx], + ASan.createRuntimeCall( + IRBPoison, AsanStackFreeFunc[StackMallocIdx], {FakeStack, ConstantInt::get(IntptrTy, LocalStackSize)}); } @@ -3404,8 +3521,8 @@ // For now just insert the call to ASan runtime. Value *AddrArg = IRB.CreatePointerCast(V, IntptrTy); Value *SizeArg = ConstantInt::get(IntptrTy, Size); - IRB.CreateCall( - DoPoison ? AsanPoisonStackMemoryFunc : AsanUnpoisonStackMemoryFunc, + ASan.createRuntimeCall( + IRB, DoPoison ? AsanPoisonStackMemoryFunc : AsanUnpoisonStackMemoryFunc, {AddrArg, SizeArg}); } @@ -3466,7 +3583,7 @@ ConstantInt::get(IntptrTy, Alignment.value())); // Insert __asan_alloca_poison call for new created alloca. - IRB.CreateCall(AsanAllocaPoisonFunc, {NewAddress, OldSize}); + ASan.createRuntimeCall(IRB, AsanAllocaPoisonFunc, {NewAddress, OldSize}); // Store the last alloca's address to DynamicAllocaLayout. We'll need this // for unpoisoning stuff. diff --git a/llvm/test/Instrumentation/AddressSanitizer/asan-funclet.ll b/llvm/test/Instrumentation/AddressSanitizer/asan-funclet.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Instrumentation/AddressSanitizer/asan-funclet.ll @@ -0,0 +1,71 @@ +; Test appropriate tagging of funclet for function calls generated by asan. + +; RUN: opt -S -passes=asan -asan-instrumentation-with-call-threshold=0 < %s | FileCheck %s + + +target triple = "x86_64-pc-windows-msvc" + +%struct.ABC = type { [2048 x i32] } + +; CHECK-LABEL: @FuncletPersonality + +; CHECK: entry: +; CHECK: call i64 @__asan_stack_malloc_8(i64 {{[0-9]+}}){{$}} + +; CHECK: ehcleanup: +; CHECK: [[CleanupPad1:%[^ ]+]] = cleanuppad within none [] +; CHECK: call void @"??1ABC@@QEAA@XZ"({{.*}}) [ "funclet"(token [[CleanupPad1]]) ] +; CHECK: call void @__asan_stack_free_8{{.*}} [ "funclet"(token [[CleanupPad1]]) ] + + +define dso_local void @FuncletPersonality() sanitize_address personality ptr @__CxxFrameHandler3 { +entry: + %abc = alloca %struct.ABC, align 4 + %call = call noundef ptr @"??0ABC@@QEAA@XZ"(ptr noundef nonnull align 4 dereferenceable(8192) %abc) + invoke void @"?may_throw@@YAXXZ"() + to label %invoke.cont unwind label %ehcleanup + +invoke.cont: ; preds = %entry + call void @"??1ABC@@QEAA@XZ"(ptr noundef nonnull align 4 dereferenceable(8192) %abc) + ret void + +ehcleanup: ; preds = %entry + %0 = cleanuppad within none [] + call void @"??1ABC@@QEAA@XZ"(ptr noundef nonnull align 4 dereferenceable(8192) %abc) [ "funclet"(token %0) ] + cleanupret from %0 unwind to caller +} + +declare dso_local noundef ptr @"??0ABC@@QEAA@XZ"(ptr noundef nonnull returned align 4 dereferenceable(8192)) unnamed_addr +declare dso_local void @"??1ABC@@QEAA@XZ"(ptr noundef nonnull align 4 dereferenceable(8192)) unnamed_addr nounwind +declare dso_local void @"?may_throw@@YAXXZ"() + +declare dso_local i32 @__CxxFrameHandler3(...) + +; CHECK-LABEL: @OtherPersonality + +; CHECK: entry: +; CHECK: call i64 @__asan_stack_malloc_8(i64 {{[0-9]+}}){{$}} + +; CHECK: ehcleanup: +; CHECK: [[CleanupPad1:%[^ ]+]] = cleanuppad within none [] +; CHECK-NOT: funclet + +define dso_local void @OtherPersonality() sanitize_address personality void ()* @dummyPersonality { +entry: + %abc = alloca %struct.ABC, align 4 + %call = call noundef ptr @"??0ABC@@QEAA@XZ"(ptr noundef nonnull align 4 dereferenceable(8192) %abc) + invoke void @"?may_throw@@YAXXZ"() + to label %invoke.cont unwind label %ehcleanup + +invoke.cont: ; preds = %entry + call void @"??1ABC@@QEAA@XZ"(ptr noundef nonnull align 4 dereferenceable(8192) %abc) + ret void + +ehcleanup: ; preds = %entry + %0 = cleanuppad within none [] + call void @"??1ABC@@QEAA@XZ"(ptr noundef nonnull align 4 dereferenceable(8192) %abc) + cleanupret from %0 unwind to caller +} + + +declare dso_local i32 @dummyPersonality(...) diff --git a/llvm/test/Instrumentation/AddressSanitizer/localescape.ll b/llvm/test/Instrumentation/AddressSanitizer/localescape.ll --- a/llvm/test/Instrumentation/AddressSanitizer/localescape.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/localescape.ll @@ -14,10 +14,10 @@ declare ptr @llvm.localrecover(ptr, ptr, i32) declare void @llvm.localescape(...) #1 -declare i32 @_except_handler3(...) +declare i32 @__gcc_personality_v0(...) declare void @may_throw(ptr %r) -define i32 @main() sanitize_address personality ptr @_except_handler3 { +define i32 @main() sanitize_address personality ptr @__gcc_personality_v0 { entry: %r = alloca i32, align 4 %__exception_code = alloca i32, align 4