diff options
author | Etienne Bergeron <etienneb@google.com> | 2016-06-30 15:36:59 +0000 |
---|---|---|
committer | Etienne Bergeron <etienneb@google.com> | 2016-06-30 15:36:59 +0000 |
commit | 47cf4eabe6e2dac486a57bcd52437e84a772883a (patch) | |
tree | 67377266a2db445d28c48906b8c9576133b0fb87 /llvm/lib/CodeGen/WinEHPrepare.cpp | |
parent | 7521e1b880a14a9df799ef95db2a0084a51be8f1 (diff) | |
download | llvm-47cf4eabe6e2dac486a57bcd52437e84a772883a.zip llvm-47cf4eabe6e2dac486a57bcd52437e84a772883a.tar.gz llvm-47cf4eabe6e2dac486a57bcd52437e84a772883a.tar.bz2 |
[exceptions] Upgrade exception handlers when stack protector is used
Summary:
MSVC provide exception handlers with enhanced information to deal with security buffer feature (/GS).
To be more secure, the security cookies (GS and SEH) are validated when unwinding the stack.
The following code:
```
void f() {}
void foo() {
__try {
f();
} __except(1) {
f();
}
}
```
Reviewers: majnemer, rnk
Subscribers: thakis, llvm-commits, chrisha
Differential Revision: http://reviews.llvm.org/D21101
llvm-svn: 274239
Diffstat (limited to 'llvm/lib/CodeGen/WinEHPrepare.cpp')
-rw-r--r-- | llvm/lib/CodeGen/WinEHPrepare.cpp | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/llvm/lib/CodeGen/WinEHPrepare.cpp b/llvm/lib/CodeGen/WinEHPrepare.cpp index 041fb7b..e4cee0e 100644 --- a/llvm/lib/CodeGen/WinEHPrepare.cpp +++ b/llvm/lib/CodeGen/WinEHPrepare.cpp @@ -20,6 +20,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/MapVector.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/Analysis/CFG.h" #include "llvm/Analysis/EHPersonalities.h" #include "llvm/CodeGen/MachineBasicBlock.h" @@ -67,6 +68,7 @@ public: } private: + void promoteEHPersonality(Function &F); void insertPHIStores(PHINode *OriginalPHI, AllocaInst *SpillSlot); void insertPHIStore(BasicBlock *PredBlock, Value *PredVal, AllocaInst *SpillSlot, @@ -464,6 +466,39 @@ static int addClrEHHandler(WinEHFuncInfo &FuncInfo, int HandlerParentState, return FuncInfo.ClrEHUnwindMap.size() - 1; } +static Value *getStackGuardEHPersonality(Value *Pers) { + Function *F = + Pers ? dyn_cast<Function>(Pers->stripPointerCasts()) : nullptr; + if (!F) + return nullptr; + + // TODO(etienneb): Upgrade exception handlers when they are working. + StringRef NewName = llvm::StringSwitch<StringRef>(F->getName()) + .Case("_except_handler3", "_except_handler4") + .Default(""); + if (NewName.empty()) + return nullptr; + + Module *M = F->getParent(); + return M->getOrInsertFunction("_except_handler4", F->getFunctionType(), + F->getAttributes()); +} + +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; + + if (Value *PersonalityFn = F.getPersonalityFn()) { + if (Value *Personality = getStackGuardEHPersonality(PersonalityFn)) { + Function* PromotedFn = cast<Function>(Personality); + F.setPersonalityFn(PromotedFn); + } + } +} + void llvm::calculateClrEHStateNumbers(const Function *Fn, WinEHFuncInfo &FuncInfo) { // Return if it's already been done. @@ -1028,6 +1063,10 @@ void WinEHPrepare::verifyPreparedFunclets(Function &F) { } bool WinEHPrepare::prepareExplicitEH(Function &F) { + // When stack-protector is present, some exception handlers need to be + // promoted to a compatible handlers. + promoteEHPersonality(F); + // Remove unreachable blocks. It is not valuable to assign them a color and // their existence can trick us into thinking values are alive when they are // not. |