1 //===-- X86WinEHState - Insert EH state updates for win32 exceptions ------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // All functions using an MSVC EH personality use an explicitly updated state 11 // number stored in an exception registration stack object. The registration 12 // object is linked into a thread-local chain of registrations stored at fs:00. 13 // This pass adds the registration object and EH state updates. 14 // 15 //===----------------------------------------------------------------------===// 16 17 #include "X86.h" 18 #include "llvm/Analysis/CFG.h" 19 #include "llvm/Analysis/EHPersonalities.h" 20 #include "llvm/CodeGen/MachineModuleInfo.h" 21 #include "llvm/CodeGen/Passes.h" 22 #include "llvm/CodeGen/WinEHFuncInfo.h" 23 #include "llvm/IR/Dominators.h" 24 #include "llvm/IR/Function.h" 25 #include "llvm/IR/IRBuilder.h" 26 #include "llvm/IR/Instructions.h" 27 #include "llvm/IR/IntrinsicInst.h" 28 #include "llvm/IR/Module.h" 29 #include "llvm/IR/PatternMatch.h" 30 #include "llvm/Pass.h" 31 #include "llvm/Support/Debug.h" 32 #include "llvm/Support/raw_ostream.h" 33 #include "llvm/Transforms/Utils/BasicBlockUtils.h" 34 #include "llvm/Transforms/Utils/Cloning.h" 35 #include "llvm/Transforms/Utils/Local.h" 36 37 using namespace llvm; 38 using namespace llvm::PatternMatch; 39 40 #define DEBUG_TYPE "winehstate" 41 42 namespace llvm { void initializeWinEHStatePassPass(PassRegistry &); } 43 44 namespace { 45 class WinEHStatePass : public FunctionPass { 46 public: 47 static char ID; // Pass identification, replacement for typeid. 48 49 WinEHStatePass() : FunctionPass(ID) { 50 initializeWinEHStatePassPass(*PassRegistry::getPassRegistry()); 51 } 52 53 bool runOnFunction(Function &Fn) override; 54 55 bool doInitialization(Module &M) override; 56 57 bool doFinalization(Module &M) override; 58 59 void getAnalysisUsage(AnalysisUsage &AU) const override; 60 61 const char *getPassName() const override { 62 return "Windows 32-bit x86 EH state insertion"; 63 } 64 65 private: 66 void emitExceptionRegistrationRecord(Function *F); 67 68 void linkExceptionRegistration(IRBuilder<> &Builder, Function *Handler); 69 void unlinkExceptionRegistration(IRBuilder<> &Builder); 70 void addStateStores(Function &F, WinEHFuncInfo &FuncInfo); 71 void insertStateNumberStore(Value *ParentRegNode, Instruction *IP, int State); 72 73 Value *emitEHLSDA(IRBuilder<> &Builder, Function *F); 74 75 Function *generateLSDAInEAXThunk(Function *ParentFunc); 76 77 // Module-level type getters. 78 Type *getEHLinkRegistrationType(); 79 Type *getSEHRegistrationType(); 80 Type *getCXXEHRegistrationType(); 81 82 // Per-module data. 83 Module *TheModule = nullptr; 84 StructType *EHLinkRegistrationTy = nullptr; 85 StructType *CXXEHRegistrationTy = nullptr; 86 StructType *SEHRegistrationTy = nullptr; 87 Function *FrameRecover = nullptr; 88 Function *FrameAddress = nullptr; 89 Function *FrameEscape = nullptr; 90 91 // Per-function state 92 EHPersonality Personality = EHPersonality::Unknown; 93 Function *PersonalityFn = nullptr; 94 95 /// The stack allocation containing all EH data, including the link in the 96 /// fs:00 chain and the current state. 97 AllocaInst *RegNode = nullptr; 98 99 /// Struct type of RegNode. Used for GEPing. 100 Type *RegNodeTy = nullptr; 101 102 /// The index of the state field of RegNode. 103 int StateFieldIndex = ~0U; 104 105 /// The linked list node subobject inside of RegNode. 106 Value *Link = nullptr; 107 }; 108 } 109 110 FunctionPass *llvm::createX86WinEHStatePass() { return new WinEHStatePass(); } 111 112 char WinEHStatePass::ID = 0; 113 114 INITIALIZE_PASS(WinEHStatePass, "x86-winehstate", 115 "Insert stores for EH state numbers", false, false) 116 117 bool WinEHStatePass::doInitialization(Module &M) { 118 TheModule = &M; 119 FrameEscape = Intrinsic::getDeclaration(TheModule, Intrinsic::localescape); 120 FrameRecover = Intrinsic::getDeclaration(TheModule, Intrinsic::localrecover); 121 FrameAddress = Intrinsic::getDeclaration(TheModule, Intrinsic::frameaddress); 122 return false; 123 } 124 125 bool WinEHStatePass::doFinalization(Module &M) { 126 assert(TheModule == &M); 127 TheModule = nullptr; 128 EHLinkRegistrationTy = nullptr; 129 CXXEHRegistrationTy = nullptr; 130 SEHRegistrationTy = nullptr; 131 FrameEscape = nullptr; 132 FrameRecover = nullptr; 133 FrameAddress = nullptr; 134 return false; 135 } 136 137 void WinEHStatePass::getAnalysisUsage(AnalysisUsage &AU) const { 138 // This pass should only insert a stack allocation, memory accesses, and 139 // localrecovers. 140 AU.setPreservesCFG(); 141 } 142 143 bool WinEHStatePass::runOnFunction(Function &F) { 144 // Check the personality. Do nothing if this personality doesn't use funclets. 145 if (!F.hasPersonalityFn()) 146 return false; 147 PersonalityFn = 148 dyn_cast<Function>(F.getPersonalityFn()->stripPointerCasts()); 149 if (!PersonalityFn) 150 return false; 151 Personality = classifyEHPersonality(PersonalityFn); 152 if (!isFuncletEHPersonality(Personality)) 153 return false; 154 155 // Skip this function if there are no EH pads and we aren't using IR-level 156 // outlining. 157 bool HasPads = false; 158 for (BasicBlock &BB : F) { 159 if (BB.isEHPad()) { 160 HasPads = true; 161 break; 162 } 163 } 164 if (!HasPads) 165 return false; 166 167 // Disable frame pointer elimination in this function. 168 // FIXME: Do the nested handlers need to keep the parent ebp in ebp, or can we 169 // use an arbitrary register? 170 F.addFnAttr("no-frame-pointer-elim", "true"); 171 172 emitExceptionRegistrationRecord(&F); 173 174 // The state numbers calculated here in IR must agree with what we calculate 175 // later on for the MachineFunction. In particular, if an IR pass deletes an 176 // unreachable EH pad after this point before machine CFG construction, we 177 // will be in trouble. If this assumption is ever broken, we should turn the 178 // numbers into an immutable analysis pass. 179 WinEHFuncInfo FuncInfo; 180 addStateStores(F, FuncInfo); 181 182 // Reset per-function state. 183 PersonalityFn = nullptr; 184 Personality = EHPersonality::Unknown; 185 return true; 186 } 187 188 /// Get the common EH registration subobject: 189 /// typedef _EXCEPTION_DISPOSITION (*PEXCEPTION_ROUTINE)( 190 /// _EXCEPTION_RECORD *, void *, _CONTEXT *, void *); 191 /// struct EHRegistrationNode { 192 /// EHRegistrationNode *Next; 193 /// PEXCEPTION_ROUTINE Handler; 194 /// }; 195 Type *WinEHStatePass::getEHLinkRegistrationType() { 196 if (EHLinkRegistrationTy) 197 return EHLinkRegistrationTy; 198 LLVMContext &Context = TheModule->getContext(); 199 EHLinkRegistrationTy = StructType::create(Context, "EHRegistrationNode"); 200 Type *FieldTys[] = { 201 EHLinkRegistrationTy->getPointerTo(0), // EHRegistrationNode *Next 202 Type::getInt8PtrTy(Context) // EXCEPTION_DISPOSITION (*Handler)(...) 203 }; 204 EHLinkRegistrationTy->setBody(FieldTys, false); 205 return EHLinkRegistrationTy; 206 } 207 208 /// The __CxxFrameHandler3 registration node: 209 /// struct CXXExceptionRegistration { 210 /// void *SavedESP; 211 /// EHRegistrationNode SubRecord; 212 /// int32_t TryLevel; 213 /// }; 214 Type *WinEHStatePass::getCXXEHRegistrationType() { 215 if (CXXEHRegistrationTy) 216 return CXXEHRegistrationTy; 217 LLVMContext &Context = TheModule->getContext(); 218 Type *FieldTys[] = { 219 Type::getInt8PtrTy(Context), // void *SavedESP 220 getEHLinkRegistrationType(), // EHRegistrationNode SubRecord 221 Type::getInt32Ty(Context) // int32_t TryLevel 222 }; 223 CXXEHRegistrationTy = 224 StructType::create(FieldTys, "CXXExceptionRegistration"); 225 return CXXEHRegistrationTy; 226 } 227 228 /// The _except_handler3/4 registration node: 229 /// struct EH4ExceptionRegistration { 230 /// void *SavedESP; 231 /// _EXCEPTION_POINTERS *ExceptionPointers; 232 /// EHRegistrationNode SubRecord; 233 /// int32_t EncodedScopeTable; 234 /// int32_t TryLevel; 235 /// }; 236 Type *WinEHStatePass::getSEHRegistrationType() { 237 if (SEHRegistrationTy) 238 return SEHRegistrationTy; 239 LLVMContext &Context = TheModule->getContext(); 240 Type *FieldTys[] = { 241 Type::getInt8PtrTy(Context), // void *SavedESP 242 Type::getInt8PtrTy(Context), // void *ExceptionPointers 243 getEHLinkRegistrationType(), // EHRegistrationNode SubRecord 244 Type::getInt32Ty(Context), // int32_t EncodedScopeTable 245 Type::getInt32Ty(Context) // int32_t TryLevel 246 }; 247 SEHRegistrationTy = StructType::create(FieldTys, "SEHExceptionRegistration"); 248 return SEHRegistrationTy; 249 } 250 251 // Emit an exception registration record. These are stack allocations with the 252 // common subobject of two pointers: the previous registration record (the old 253 // fs:00) and the personality function for the current frame. The data before 254 // and after that is personality function specific. 255 void WinEHStatePass::emitExceptionRegistrationRecord(Function *F) { 256 assert(Personality == EHPersonality::MSVC_CXX || 257 Personality == EHPersonality::MSVC_X86SEH); 258 259 StringRef PersonalityName = PersonalityFn->getName(); 260 IRBuilder<> Builder(&F->getEntryBlock(), F->getEntryBlock().begin()); 261 Type *Int8PtrType = Builder.getInt8PtrTy(); 262 if (Personality == EHPersonality::MSVC_CXX) { 263 RegNodeTy = getCXXEHRegistrationType(); 264 RegNode = Builder.CreateAlloca(RegNodeTy); 265 // SavedESP = llvm.stacksave() 266 Value *SP = Builder.CreateCall( 267 Intrinsic::getDeclaration(TheModule, Intrinsic::stacksave), {}); 268 Builder.CreateStore(SP, Builder.CreateStructGEP(RegNodeTy, RegNode, 0)); 269 // TryLevel = -1 270 StateFieldIndex = 2; 271 insertStateNumberStore(RegNode, &*Builder.GetInsertPoint(), -1); 272 // Handler = __ehhandler$F 273 Function *Trampoline = generateLSDAInEAXThunk(F); 274 Link = Builder.CreateStructGEP(RegNodeTy, RegNode, 1); 275 linkExceptionRegistration(Builder, Trampoline); 276 } else if (Personality == EHPersonality::MSVC_X86SEH) { 277 // If _except_handler4 is in use, some additional guard checks and prologue 278 // stuff is required. 279 bool UseStackGuard = (PersonalityName == "_except_handler4"); 280 RegNodeTy = getSEHRegistrationType(); 281 RegNode = Builder.CreateAlloca(RegNodeTy); 282 // SavedESP = llvm.stacksave() 283 Value *SP = Builder.CreateCall( 284 Intrinsic::getDeclaration(TheModule, Intrinsic::stacksave), {}); 285 Builder.CreateStore(SP, Builder.CreateStructGEP(RegNodeTy, RegNode, 0)); 286 // TryLevel = -2 / -1 287 StateFieldIndex = 4; 288 insertStateNumberStore(RegNode, &*Builder.GetInsertPoint(), 289 UseStackGuard ? -2 : -1); 290 // ScopeTable = llvm.x86.seh.lsda(F) 291 Value *FI8 = Builder.CreateBitCast(F, Int8PtrType); 292 Value *LSDA = Builder.CreateCall( 293 Intrinsic::getDeclaration(TheModule, Intrinsic::x86_seh_lsda), FI8); 294 Type *Int32Ty = Type::getInt32Ty(TheModule->getContext()); 295 LSDA = Builder.CreatePtrToInt(LSDA, Int32Ty); 296 // If using _except_handler4, xor the address of the table with 297 // __security_cookie. 298 if (UseStackGuard) { 299 Value *Cookie = 300 TheModule->getOrInsertGlobal("__security_cookie", Int32Ty); 301 Value *Val = Builder.CreateLoad(Int32Ty, Cookie); 302 LSDA = Builder.CreateXor(LSDA, Val); 303 } 304 Builder.CreateStore(LSDA, Builder.CreateStructGEP(RegNodeTy, RegNode, 3)); 305 Link = Builder.CreateStructGEP(RegNodeTy, RegNode, 2); 306 linkExceptionRegistration(Builder, PersonalityFn); 307 } else { 308 llvm_unreachable("unexpected personality function"); 309 } 310 311 // Insert an unlink before all returns. 312 for (BasicBlock &BB : *F) { 313 TerminatorInst *T = BB.getTerminator(); 314 if (!isa<ReturnInst>(T)) 315 continue; 316 Builder.SetInsertPoint(T); 317 unlinkExceptionRegistration(Builder); 318 } 319 } 320 321 Value *WinEHStatePass::emitEHLSDA(IRBuilder<> &Builder, Function *F) { 322 Value *FI8 = Builder.CreateBitCast(F, Type::getInt8PtrTy(F->getContext())); 323 return Builder.CreateCall( 324 Intrinsic::getDeclaration(TheModule, Intrinsic::x86_seh_lsda), FI8); 325 } 326 327 /// Generate a thunk that puts the LSDA of ParentFunc in EAX and then calls 328 /// PersonalityFn, forwarding the parameters passed to PEXCEPTION_ROUTINE: 329 /// typedef _EXCEPTION_DISPOSITION (*PEXCEPTION_ROUTINE)( 330 /// _EXCEPTION_RECORD *, void *, _CONTEXT *, void *); 331 /// We essentially want this code: 332 /// movl $lsda, %eax 333 /// jmpl ___CxxFrameHandler3 334 Function *WinEHStatePass::generateLSDAInEAXThunk(Function *ParentFunc) { 335 LLVMContext &Context = ParentFunc->getContext(); 336 Type *Int32Ty = Type::getInt32Ty(Context); 337 Type *Int8PtrType = Type::getInt8PtrTy(Context); 338 Type *ArgTys[5] = {Int8PtrType, Int8PtrType, Int8PtrType, Int8PtrType, 339 Int8PtrType}; 340 FunctionType *TrampolineTy = 341 FunctionType::get(Int32Ty, makeArrayRef(&ArgTys[0], 4), 342 /*isVarArg=*/false); 343 FunctionType *TargetFuncTy = 344 FunctionType::get(Int32Ty, makeArrayRef(&ArgTys[0], 5), 345 /*isVarArg=*/false); 346 Function *Trampoline = 347 Function::Create(TrampolineTy, GlobalValue::InternalLinkage, 348 Twine("__ehhandler$") + GlobalValue::getRealLinkageName( 349 ParentFunc->getName()), 350 TheModule); 351 BasicBlock *EntryBB = BasicBlock::Create(Context, "entry", Trampoline); 352 IRBuilder<> Builder(EntryBB); 353 Value *LSDA = emitEHLSDA(Builder, ParentFunc); 354 Value *CastPersonality = 355 Builder.CreateBitCast(PersonalityFn, TargetFuncTy->getPointerTo()); 356 auto AI = Trampoline->arg_begin(); 357 Value *Args[5] = {LSDA, &*AI++, &*AI++, &*AI++, &*AI++}; 358 CallInst *Call = Builder.CreateCall(CastPersonality, Args); 359 // Can't use musttail due to prototype mismatch, but we can use tail. 360 Call->setTailCall(true); 361 // Set inreg so we pass it in EAX. 362 Call->addAttribute(1, Attribute::InReg); 363 Builder.CreateRet(Call); 364 return Trampoline; 365 } 366 367 void WinEHStatePass::linkExceptionRegistration(IRBuilder<> &Builder, 368 Function *Handler) { 369 // Emit the .safeseh directive for this function. 370 Handler->addFnAttr("safeseh"); 371 372 Type *LinkTy = getEHLinkRegistrationType(); 373 // Handler = Handler 374 Value *HandlerI8 = Builder.CreateBitCast(Handler, Builder.getInt8PtrTy()); 375 Builder.CreateStore(HandlerI8, Builder.CreateStructGEP(LinkTy, Link, 1)); 376 // Next = [fs:00] 377 Constant *FSZero = 378 Constant::getNullValue(LinkTy->getPointerTo()->getPointerTo(257)); 379 Value *Next = Builder.CreateLoad(FSZero); 380 Builder.CreateStore(Next, Builder.CreateStructGEP(LinkTy, Link, 0)); 381 // [fs:00] = Link 382 Builder.CreateStore(Link, FSZero); 383 } 384 385 void WinEHStatePass::unlinkExceptionRegistration(IRBuilder<> &Builder) { 386 // Clone Link into the current BB for better address mode folding. 387 if (auto *GEP = dyn_cast<GetElementPtrInst>(Link)) { 388 GEP = cast<GetElementPtrInst>(GEP->clone()); 389 Builder.Insert(GEP); 390 Link = GEP; 391 } 392 Type *LinkTy = getEHLinkRegistrationType(); 393 // [fs:00] = Link->Next 394 Value *Next = 395 Builder.CreateLoad(Builder.CreateStructGEP(LinkTy, Link, 0)); 396 Constant *FSZero = 397 Constant::getNullValue(LinkTy->getPointerTo()->getPointerTo(257)); 398 Builder.CreateStore(Next, FSZero); 399 } 400 401 void WinEHStatePass::addStateStores(Function &F, WinEHFuncInfo &FuncInfo) { 402 // Mark the registration node. The backend needs to know which alloca it is so 403 // that it can recover the original frame pointer. 404 IRBuilder<> Builder(RegNode->getParent(), std::next(RegNode->getIterator())); 405 Value *RegNodeI8 = Builder.CreateBitCast(RegNode, Builder.getInt8PtrTy()); 406 Builder.CreateCall( 407 Intrinsic::getDeclaration(TheModule, Intrinsic::x86_seh_ehregnode), 408 {RegNodeI8}); 409 410 // Calculate state numbers. 411 if (isAsynchronousEHPersonality(Personality)) 412 calculateSEHStateNumbers(&F, FuncInfo); 413 else 414 calculateWinCXXEHStateNumbers(&F, FuncInfo); 415 416 // Iterate all the instructions and emit state number stores. 417 DenseMap<BasicBlock *, ColorVector> BlockColors = colorEHFunclets(F); 418 for (BasicBlock &BB : F) { 419 // Figure out what state we should assign calls in this block. 420 int BaseState = -1; 421 auto &BBColors = BlockColors[&BB]; 422 423 assert(BBColors.size() == 1 && 424 "multi-color BB not removed by preparation"); 425 BasicBlock *FuncletEntryBB = BBColors.front(); 426 if (auto *FuncletPad = 427 dyn_cast<FuncletPadInst>(FuncletEntryBB->getFirstNonPHI())) { 428 auto BaseStateI = FuncInfo.FuncletBaseStateMap.find(FuncletPad); 429 if (BaseStateI != FuncInfo.FuncletBaseStateMap.end()) 430 BaseState = BaseStateI->second; 431 } 432 433 for (Instruction &I : BB) { 434 if (auto *CI = dyn_cast<CallInst>(&I)) { 435 // Possibly throwing call instructions have no actions to take after 436 // an unwind. Ensure they are in the -1 state. 437 if (CI->doesNotThrow()) 438 continue; 439 insertStateNumberStore(RegNode, CI, BaseState); 440 } else if (auto *II = dyn_cast<InvokeInst>(&I)) { 441 // Look up the state number of the landingpad this unwinds to. 442 assert(FuncInfo.InvokeStateMap.count(II) && "invoke has no state!"); 443 int State = FuncInfo.InvokeStateMap[II]; 444 insertStateNumberStore(RegNode, II, State); 445 } 446 } 447 } 448 } 449 450 void WinEHStatePass::insertStateNumberStore(Value *ParentRegNode, 451 Instruction *IP, int State) { 452 IRBuilder<> Builder(IP); 453 Value *StateField = 454 Builder.CreateStructGEP(RegNodeTy, ParentRegNode, StateFieldIndex); 455 Builder.CreateStore(Builder.getInt32(State), StateField); 456 } 457