Index: include/llvm/Analysis/EHPersonalities.h =================================================================== --- include/llvm/Analysis/EHPersonalities.h +++ include/llvm/Analysis/EHPersonalities.h @@ -69,6 +69,10 @@ llvm_unreachable("invalid enum"); } +/// \brief Returns a promoted personality function compatible with +/// stack-protection. +Value* promoteEHPersonalityForStackProtector(Value *Pers); + /// \brief Return true if this personality may be safely removed if there /// are no invoke instructions remaining in the current function. inline bool isNoOpWithoutInvoke(EHPersonality Pers) { Index: lib/Analysis/EHPersonalities.cpp =================================================================== --- lib/Analysis/EHPersonalities.cpp +++ lib/Analysis/EHPersonalities.cpp @@ -13,6 +13,7 @@ #include "llvm/IR/Constants.h" #include "llvm/IR/Function.h" #include "llvm/IR/Instructions.h" +#include "llvm/IR/Module.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; @@ -40,6 +41,19 @@ .Default(EHPersonality::Unknown); } +Value* llvm::promoteEHPersonalityForStackProtector(Value *Pers) { + Function *F = + Pers ? dyn_cast(Pers->stripPointerCasts()) : nullptr; + if (!F) + return nullptr; + + Module* M = F->getParent(); + if (F->getName() == "_except_handler3") + return M->getOrInsertFunction("_except_handler4", F->getFunctionType(), + F->getAttributes()); + return nullptr; +} + bool llvm::canSimplifyInvokeNoUnwind(const Function *F) { EHPersonality Personality = classifyEHPersonality(F->getPersonalityFn()); // We can't simplify any invokes to nounwind functions if the personality Index: lib/CodeGen/WinEHPrepare.cpp =================================================================== --- lib/CodeGen/WinEHPrepare.cpp +++ lib/CodeGen/WinEHPrepare.cpp @@ -67,6 +67,8 @@ } private: + void promoteEHPersonality(Function &F); + void insertPHIStores(PHINode *OriginalPHI, AllocaInst *SpillSlot); void insertPHIStore(BasicBlock *PredBlock, Value *PredVal, AllocaInst *SpillSlot, @@ -104,6 +106,10 @@ if (!Fn.hasPersonalityFn()) return false; + // When stack-protector is present, some exception handlers need to be + // promoted to a compatible handlers. + promoteEHPersonality(Fn); + // Classify the personality to see what kind of preparation we need. Personality = classifyEHPersonality(Fn.getPersonalityFn()); @@ -666,6 +672,24 @@ calculateStateNumbersForInvokes(Fn, FuncInfo); } +void WinEHPrepare::promoteEHPersonality(Function &F) { + // Promote the exception handler when stack protection is activated. + if (!F.hasFnAttribute(Attribute::StackProtect) && + !F.hasFnAttribute(Attribute::StackProtectReq) && + !F.hasFnAttribute(Attribute::StackProtectStrong)) + return; + + Value* PersonalityFn = F.getPersonalityFn(); + if (PersonalityFn) { + Value* PromotedPersonality = + promoteEHPersonalityForStackProtector(PersonalityFn); + if (PromotedPersonality) { + Function* PromotedFn = cast(PromotedPersonality); + F.setPersonalityFn(PromotedFn); + } + } +} + void WinEHPrepare::colorFunclets(Function &F) { BlockColors = colorEHFunclets(F);