[WinEH] Adjust the 32-bit SEH prologue to better match reality

It turns out that _except_handler3 and _except_handler4 really use the
same stack allocation layout, at least today. They just make different
choices about encoding the LSDA.

This is in preparation for lowering the llvm.eh.exceptioninfo().

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@238627 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Reid Kleckner
2015-05-29 22:57:46 +00:00
parent bb06a52fa7
commit bfa311df8c
2 changed files with 57 additions and 75 deletions

View File

@ -74,17 +74,15 @@ private:
int escapeRegNode(Function &F); int escapeRegNode(Function &F);
// Module-level type getters. // Module-level type getters.
Type *getEHRegistrationType(); Type *getEHLinkRegistrationType();
Type *getSEH3RegistrationType(); Type *getSEHRegistrationType();
Type *getSEH4RegistrationType(); Type *getCXXEHRegistrationType();
Type *getCXXEH3RegistrationType();
// Per-module data. // Per-module data.
Module *TheModule = nullptr; Module *TheModule = nullptr;
StructType *EHRegistrationTy = nullptr; StructType *EHLinkRegistrationTy = nullptr;
StructType *CXXEH3RegistrationTy = nullptr; StructType *CXXEHRegistrationTy = nullptr;
StructType *SEH3RegistrationTy = nullptr; StructType *SEHRegistrationTy = nullptr;
StructType *SEH4RegistrationTy = nullptr;
// Per-function state // Per-function state
EHPersonality Personality = EHPersonality::Unknown; EHPersonality Personality = EHPersonality::Unknown;
@ -117,10 +115,9 @@ bool WinEHStatePass::doInitialization(Module &M) {
bool WinEHStatePass::doFinalization(Module &M) { bool WinEHStatePass::doFinalization(Module &M) {
assert(TheModule == &M); assert(TheModule == &M);
TheModule = nullptr; TheModule = nullptr;
EHRegistrationTy = nullptr; EHLinkRegistrationTy = nullptr;
CXXEH3RegistrationTy = nullptr; CXXEHRegistrationTy = nullptr;
SEH3RegistrationTy = nullptr; SEHRegistrationTy = nullptr;
SEH4RegistrationTy = nullptr;
return false; return false;
} }
@ -182,17 +179,17 @@ bool WinEHStatePass::runOnFunction(Function &F) {
/// EHRegistrationNode *Next; /// EHRegistrationNode *Next;
/// PEXCEPTION_ROUTINE Handler; /// PEXCEPTION_ROUTINE Handler;
/// }; /// };
Type *WinEHStatePass::getEHRegistrationType() { Type *WinEHStatePass::getEHLinkRegistrationType() {
if (EHRegistrationTy) if (EHLinkRegistrationTy)
return EHRegistrationTy; return EHLinkRegistrationTy;
LLVMContext &Context = TheModule->getContext(); LLVMContext &Context = TheModule->getContext();
EHRegistrationTy = StructType::create(Context, "EHRegistrationNode"); EHLinkRegistrationTy = StructType::create(Context, "EHRegistrationNode");
Type *FieldTys[] = { Type *FieldTys[] = {
EHRegistrationTy->getPointerTo(0), // EHRegistrationNode *Next EHLinkRegistrationTy->getPointerTo(0), // EHRegistrationNode *Next
Type::getInt8PtrTy(Context) // EXCEPTION_DISPOSITION (*Handler)(...) Type::getInt8PtrTy(Context) // EXCEPTION_DISPOSITION (*Handler)(...)
}; };
EHRegistrationTy->setBody(FieldTys, false); EHLinkRegistrationTy->setBody(FieldTys, false);
return EHRegistrationTy; return EHLinkRegistrationTy;
} }
/// The __CxxFrameHandler3 registration node: /// The __CxxFrameHandler3 registration node:
@ -201,40 +198,21 @@ Type *WinEHStatePass::getEHRegistrationType() {
/// EHRegistrationNode SubRecord; /// EHRegistrationNode SubRecord;
/// int32_t TryLevel; /// int32_t TryLevel;
/// }; /// };
Type *WinEHStatePass::getCXXEH3RegistrationType() { Type *WinEHStatePass::getCXXEHRegistrationType() {
if (CXXEH3RegistrationTy) if (CXXEHRegistrationTy)
return CXXEH3RegistrationTy; return CXXEHRegistrationTy;
LLVMContext &Context = TheModule->getContext(); LLVMContext &Context = TheModule->getContext();
Type *FieldTys[] = { Type *FieldTys[] = {
Type::getInt8PtrTy(Context), // void *SavedESP Type::getInt8PtrTy(Context), // void *SavedESP
getEHRegistrationType(), // EHRegistrationNode SubRecord getEHLinkRegistrationType(), // EHRegistrationNode SubRecord
Type::getInt32Ty(Context) // int32_t TryLevel Type::getInt32Ty(Context) // int32_t TryLevel
}; };
CXXEH3RegistrationTy = CXXEHRegistrationTy =
StructType::create(FieldTys, "CXXExceptionRegistration"); StructType::create(FieldTys, "CXXExceptionRegistration");
return CXXEH3RegistrationTy; return CXXEHRegistrationTy;
} }
/// The _except_handler3 registration node: /// The _except_handler3/4 registration node:
/// struct EH3ExceptionRegistration {
/// EHRegistrationNode SubRecord;
/// void *ScopeTable;
/// int32_t TryLevel;
/// };
Type *WinEHStatePass::getSEH3RegistrationType() {
if (SEH3RegistrationTy)
return SEH3RegistrationTy;
LLVMContext &Context = TheModule->getContext();
Type *FieldTys[] = {
getEHRegistrationType(), // EHRegistrationNode SubRecord
Type::getInt8PtrTy(Context), // void *ScopeTable
Type::getInt32Ty(Context) // int32_t TryLevel
};
SEH3RegistrationTy = StructType::create(FieldTys, "EH3ExceptionRegistration");
return SEH3RegistrationTy;
}
/// The _except_handler4 registration node:
/// struct EH4ExceptionRegistration { /// struct EH4ExceptionRegistration {
/// void *SavedESP; /// void *SavedESP;
/// _EXCEPTION_POINTERS *ExceptionPointers; /// _EXCEPTION_POINTERS *ExceptionPointers;
@ -242,19 +220,19 @@ Type *WinEHStatePass::getSEH3RegistrationType() {
/// int32_t EncodedScopeTable; /// int32_t EncodedScopeTable;
/// int32_t TryLevel; /// int32_t TryLevel;
/// }; /// };
Type *WinEHStatePass::getSEH4RegistrationType() { Type *WinEHStatePass::getSEHRegistrationType() {
if (SEH4RegistrationTy) if (SEHRegistrationTy)
return SEH4RegistrationTy; return SEHRegistrationTy;
LLVMContext &Context = TheModule->getContext(); LLVMContext &Context = TheModule->getContext();
Type *FieldTys[] = { Type *FieldTys[] = {
Type::getInt8PtrTy(Context), // void *SavedESP Type::getInt8PtrTy(Context), // void *SavedESP
Type::getInt8PtrTy(Context), // void *ExceptionPointers Type::getInt8PtrTy(Context), // void *ExceptionPointers
getEHRegistrationType(), // EHRegistrationNode SubRecord getEHLinkRegistrationType(), // EHRegistrationNode SubRecord
Type::getInt32Ty(Context), // int32_t EncodedScopeTable Type::getInt32Ty(Context), // int32_t EncodedScopeTable
Type::getInt32Ty(Context) // int32_t TryLevel Type::getInt32Ty(Context) // int32_t TryLevel
}; };
SEH4RegistrationTy = StructType::create(FieldTys, "EH4ExceptionRegistration"); SEHRegistrationTy = StructType::create(FieldTys, "SEHExceptionRegistration");
return SEH4RegistrationTy; return SEHRegistrationTy;
} }
// Emit an exception registration record. These are stack allocations with the // Emit an exception registration record. These are stack allocations with the
@ -268,8 +246,8 @@ void WinEHStatePass::emitExceptionRegistrationRecord(Function *F) {
StringRef PersonalityName = PersonalityFn->getName(); StringRef PersonalityName = PersonalityFn->getName();
IRBuilder<> Builder(&F->getEntryBlock(), F->getEntryBlock().begin()); IRBuilder<> Builder(&F->getEntryBlock(), F->getEntryBlock().begin());
Type *Int8PtrType = Builder.getInt8PtrTy(); Type *Int8PtrType = Builder.getInt8PtrTy();
if (PersonalityName == "__CxxFrameHandler3") { if (Personality == EHPersonality::MSVC_CXX) {
RegNodeTy = getCXXEH3RegistrationType(); RegNodeTy = getCXXEHRegistrationType();
RegNode = Builder.CreateAlloca(RegNodeTy); RegNode = Builder.CreateAlloca(RegNodeTy);
// FIXME: We can skip this in -GS- mode, when we figure that out. // FIXME: We can skip this in -GS- mode, when we figure that out.
// SavedESP = llvm.stacksave() // SavedESP = llvm.stacksave()
@ -283,33 +261,35 @@ void WinEHStatePass::emitExceptionRegistrationRecord(Function *F) {
Function *Trampoline = generateLSDAInEAXThunk(F); Function *Trampoline = generateLSDAInEAXThunk(F);
Link = Builder.CreateStructGEP(RegNodeTy, RegNode, 1); Link = Builder.CreateStructGEP(RegNodeTy, RegNode, 1);
linkExceptionRegistration(Builder, Trampoline); linkExceptionRegistration(Builder, Trampoline);
} else if (PersonalityName == "_except_handler3") { } else if (Personality == EHPersonality::MSVC_X86SEH) {
RegNodeTy = getSEH3RegistrationType(); // If _except_handler4 is in use, some additional guard checks and prologue
RegNode = Builder.CreateAlloca(RegNodeTy); // stuff is required.
// TryLevel = -1 bool UseStackGuard = (PersonalityName == "_except_handler4");
StateFieldIndex = 2; RegNodeTy = getSEHRegistrationType();
insertStateNumberStore(RegNode, Builder.GetInsertPoint(), -1);
// ScopeTable = llvm.x86.seh.lsda(F)
Value *LSDA = emitEHLSDA(Builder, F);
Builder.CreateStore(LSDA, Builder.CreateStructGEP(RegNodeTy, RegNode, 1));
Link = Builder.CreateStructGEP(RegNodeTy, RegNode, 0);
linkExceptionRegistration(Builder, PersonalityFn);
} else if (PersonalityName == "_except_handler4") {
RegNodeTy = getSEH4RegistrationType();
RegNode = Builder.CreateAlloca(RegNodeTy); RegNode = Builder.CreateAlloca(RegNodeTy);
// SavedESP = llvm.stacksave() // SavedESP = llvm.stacksave()
Value *SP = Builder.CreateCall( Value *SP = Builder.CreateCall(
Intrinsic::getDeclaration(TheModule, Intrinsic::stacksave), {}); Intrinsic::getDeclaration(TheModule, Intrinsic::stacksave), {});
Builder.CreateStore(SP, Builder.CreateStructGEP(RegNodeTy, RegNode, 0)); Builder.CreateStore(SP, Builder.CreateStructGEP(RegNodeTy, RegNode, 0));
// TryLevel = -1 // TryLevel = -2 / -1
StateFieldIndex = 4; StateFieldIndex = 4;
insertStateNumberStore(RegNode, Builder.GetInsertPoint(), -1); insertStateNumberStore(RegNode, Builder.GetInsertPoint(),
// FIXME: XOR the LSDA with __security_cookie. UseStackGuard ? -2 : -1);
// ScopeTable = llvm.x86.seh.lsda(F) // ScopeTable = llvm.x86.seh.lsda(F)
Value *FI8 = Builder.CreateBitCast(F, Int8PtrType); Value *FI8 = Builder.CreateBitCast(F, Int8PtrType);
Value *LSDA = Builder.CreateCall( Value *LSDA = Builder.CreateCall(
Intrinsic::getDeclaration(TheModule, Intrinsic::x86_seh_lsda), FI8); Intrinsic::getDeclaration(TheModule, Intrinsic::x86_seh_lsda), FI8);
Builder.CreateStore(LSDA, Builder.CreateStructGEP(RegNodeTy, RegNode, 1)); Type *Int32Ty = Type::getInt32Ty(TheModule->getContext());
LSDA = Builder.CreatePtrToInt(LSDA, Int32Ty);
// If using _except_handler4, xor the address of the table with
// __security_cookie.
if (UseStackGuard) {
Value *Cookie =
TheModule->getOrInsertGlobal("__security_cookie", Int32Ty);
Value *Val = Builder.CreateLoad(Int32Ty, Cookie);
LSDA = Builder.CreateXor(LSDA, Val);
}
Builder.CreateStore(LSDA, Builder.CreateStructGEP(RegNodeTy, RegNode, 3));
Link = Builder.CreateStructGEP(RegNodeTy, RegNode, 2); Link = Builder.CreateStructGEP(RegNodeTy, RegNode, 2);
linkExceptionRegistration(Builder, PersonalityFn); linkExceptionRegistration(Builder, PersonalityFn);
} else { } else {
@ -372,7 +352,7 @@ Function *WinEHStatePass::generateLSDAInEAXThunk(Function *ParentFunc) {
void WinEHStatePass::linkExceptionRegistration(IRBuilder<> &Builder, void WinEHStatePass::linkExceptionRegistration(IRBuilder<> &Builder,
Value *Handler) { Value *Handler) {
Type *LinkTy = getEHRegistrationType(); Type *LinkTy = getEHLinkRegistrationType();
// Handler = Handler // Handler = Handler
Handler = Builder.CreateBitCast(Handler, Builder.getInt8PtrTy()); Handler = Builder.CreateBitCast(Handler, Builder.getInt8PtrTy());
Builder.CreateStore(Handler, Builder.CreateStructGEP(LinkTy, Link, 1)); Builder.CreateStore(Handler, Builder.CreateStructGEP(LinkTy, Link, 1));
@ -392,7 +372,7 @@ void WinEHStatePass::unlinkExceptionRegistration(IRBuilder<> &Builder) {
Builder.Insert(GEP); Builder.Insert(GEP);
Link = GEP; Link = GEP;
} }
Type *LinkTy = getEHRegistrationType(); Type *LinkTy = getEHLinkRegistrationType();
// [fs:00] = Link->Next // [fs:00] = Link->Next
Value *Next = Value *Next =
Builder.CreateLoad(Builder.CreateStructGEP(LinkTy, Link, 0)); Builder.CreateLoad(Builder.CreateStructGEP(LinkTy, Link, 0));

View File

@ -24,10 +24,10 @@ catchall:
; CHECK: subl ${{[0-9]+}}, %esp ; CHECK: subl ${{[0-9]+}}, %esp
; CHECK: movl $-1, -4(%ebp) ; CHECK: movl $-1, -4(%ebp)
; CHECK: movl $L__ehtable$use_except_handler3, -8(%ebp) ; CHECK: movl $L__ehtable$use_except_handler3, -8(%ebp)
; CHECK: leal -16(%ebp), %[[node:[^ ,]*]]
; CHECK: movl $__except_handler3, -12(%ebp) ; CHECK: movl $__except_handler3, -12(%ebp)
; CHECK: movl %fs:0, %[[next:[^ ,]*]] ; CHECK: movl %fs:0, %[[next:[^ ,]*]]
; CHECK: movl %[[next]], -16(%ebp) ; CHECK: movl %[[next]], -16(%ebp)
; CHECK: leal -16(%ebp), %[[node:[^ ,]*]]
; CHECK: movl %[[node]], %fs:0 ; CHECK: movl %[[node]], %fs:0
; CHECK: calll _may_throw_or_crash ; CHECK: calll _may_throw_or_crash
; CHECK: movl -16(%ebp), %[[next:[^ ,]*]] ; CHECK: movl -16(%ebp), %[[next:[^ ,]*]]
@ -50,8 +50,10 @@ catchall:
; CHECK: movl %esp, %ebp ; CHECK: movl %esp, %ebp
; CHECK: subl ${{[0-9]+}}, %esp ; CHECK: subl ${{[0-9]+}}, %esp
; CHECK: movl %esp, -24(%ebp) ; CHECK: movl %esp, -24(%ebp)
; CHECK: movl $-1, -4(%ebp) ; CHECK: movl $-2, -4(%ebp)
; CHECK: movl $L__ehtable$use_except_handler4, -20(%ebp) ; CHECK: movl $L__ehtable$use_except_handler4, %[[lsda:[^ ,]*]]
; CHECK: xorl ___security_cookie, %[[lsda]]
; CHECK: movl %[[lsda]], -8(%ebp)
; CHECK: leal -16(%ebp), %[[node:[^ ,]*]] ; CHECK: leal -16(%ebp), %[[node:[^ ,]*]]
; CHECK: movl $__except_handler4, -12(%ebp) ; CHECK: movl $__except_handler4, -12(%ebp)
; CHECK: movl %fs:0, %[[next:[^ ,]*]] ; CHECK: movl %fs:0, %[[next:[^ ,]*]]