[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
This commit is contained in:
parent
7521e1b880
commit
47cf4eabe6
|
@ -20,6 +20,7 @@
|
||||||
#include "llvm/ADT/DenseMap.h"
|
#include "llvm/ADT/DenseMap.h"
|
||||||
#include "llvm/ADT/MapVector.h"
|
#include "llvm/ADT/MapVector.h"
|
||||||
#include "llvm/ADT/STLExtras.h"
|
#include "llvm/ADT/STLExtras.h"
|
||||||
|
#include "llvm/ADT/StringSwitch.h"
|
||||||
#include "llvm/Analysis/CFG.h"
|
#include "llvm/Analysis/CFG.h"
|
||||||
#include "llvm/Analysis/EHPersonalities.h"
|
#include "llvm/Analysis/EHPersonalities.h"
|
||||||
#include "llvm/CodeGen/MachineBasicBlock.h"
|
#include "llvm/CodeGen/MachineBasicBlock.h"
|
||||||
|
@ -67,6 +68,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void promoteEHPersonality(Function &F);
|
||||||
void insertPHIStores(PHINode *OriginalPHI, AllocaInst *SpillSlot);
|
void insertPHIStores(PHINode *OriginalPHI, AllocaInst *SpillSlot);
|
||||||
void
|
void
|
||||||
insertPHIStore(BasicBlock *PredBlock, Value *PredVal, AllocaInst *SpillSlot,
|
insertPHIStore(BasicBlock *PredBlock, Value *PredVal, AllocaInst *SpillSlot,
|
||||||
|
@ -464,6 +466,39 @@ static int addClrEHHandler(WinEHFuncInfo &FuncInfo, int HandlerParentState,
|
||||||
return FuncInfo.ClrEHUnwindMap.size() - 1;
|
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,
|
void llvm::calculateClrEHStateNumbers(const Function *Fn,
|
||||||
WinEHFuncInfo &FuncInfo) {
|
WinEHFuncInfo &FuncInfo) {
|
||||||
// Return if it's already been done.
|
// Return if it's already been done.
|
||||||
|
@ -1028,6 +1063,10 @@ void WinEHPrepare::verifyPreparedFunclets(Function &F) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WinEHPrepare::prepareExplicitEH(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
|
// 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
|
// their existence can trick us into thinking values are alive when they are
|
||||||
// not.
|
// not.
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
; RUN: opt -mtriple=i686-windows-msvc -S -winehprepare %s | FileCheck %s
|
||||||
|
|
||||||
|
declare i32 @_except_handler3(...)
|
||||||
|
|
||||||
|
define void @test1a() personality i32 (...)* @_except_handler3 {
|
||||||
|
; CHECK: define void @test1a() personality i32 (...)* @_except_handler3
|
||||||
|
entry:
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @test1b() ssp personality i32 (...)* @_except_handler3 {
|
||||||
|
; CHECK: define void @test1b() [[attr:.*]] personality i32 (...)* @_except_handler4
|
||||||
|
entry:
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue