]> granicus.if.org Git - llvm/commitdiff
[WinEH] Emit .safeseh directives for all 32-bit exception handlers
authorReid Kleckner <reid@kleckner.net>
Wed, 10 Jun 2015 01:02:30 +0000 (01:02 +0000)
committerReid Kleckner <reid@kleckner.net>
Wed, 10 Jun 2015 01:02:30 +0000 (01:02 +0000)
Use a "safeseh" string attribute to do this. You would think we chould
just accumulate the set of personalities like we do on dwarf, but this
fails to account for the LSDA-loading thunks we use for
__CxxFrameHandler3. Each of those needs to make it into .sxdata as well.
The string attribute seemed like the most straightforward approach.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@239448 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/AsmPrinter/WinException.cpp
lib/MC/WinCOFFStreamer.cpp
lib/Target/X86/X86WinEHState.cpp
test/CodeGen/X86/win32-eh-states.ll
test/CodeGen/X86/win32-eh.ll

index 7e3a6d5a76fd2733d2714f79af5422a4fd08019b..ffa0ceb1a602387c761ce92b520e2045dc214b99 100644 (file)
@@ -50,6 +50,14 @@ WinException::~WinException() {}
 /// endModule - Emit all exception information that should come after the
 /// content.
 void WinException::endModule() {
+  auto &OS = *Asm->OutStreamer;
+  const Module *M = MMI->getModule();
+  for (const Function &F : *M) {
+    if (F.hasFnAttribute("safeseh")) {
+      llvm::errs() << ".safeseh " << F.getName() << "\n";
+      OS.EmitCOFFSafeSEH(Asm->getSymbol(&F));
+    }
+  }
 }
 
 void WinException::beginFunction(const MachineFunction *MF) {
index 41fc8e4681efc0a400ede85ea38acf690f520952..36dd691f07b8764c086992b4a501a860bf9d650d 100644 (file)
@@ -164,7 +164,8 @@ void MCWinCOFFStreamer::EmitCOFFSafeSEH(MCSymbol const *Symbol) {
       Triple::x86)
     return;
 
-  if (cast<MCSymbolCOFF>(Symbol)->isSafeSEH())
+  const MCSymbolCOFF *CSymbol = cast<MCSymbolCOFF>(Symbol);
+  if (CSymbol->isSafeSEH())
     return;
 
   MCSection *SXData = getContext().getObjectFileInfo()->getSXDataSection();
@@ -175,7 +176,12 @@ void MCWinCOFFStreamer::EmitCOFFSafeSEH(MCSymbol const *Symbol) {
   new MCSafeSEHFragment(Symbol, SXData);
 
   getAssembler().registerSymbol(*Symbol);
-  cast<MCSymbolCOFF>(Symbol)->setIsSafeSEH();
+  CSymbol->setIsSafeSEH();
+
+  // The Microsoft linker requires that the symbol type of a handler be
+  // function. Go ahead and oblige it here.
+  CSymbol->setType(COFF::IMAGE_SYM_DTYPE_FUNCTION
+                   << COFF::SCT_COMPLEX_TYPE_SHIFT);
 }
 
 void MCWinCOFFStreamer::EmitCOFFSectionIndex(MCSymbol const *Symbol) {
index 0c4aabab880ecd241f95fe668394424d8928fa6d..16a94daa819886f7490b2b9bedf23f94371f3998 100644 (file)
@@ -60,7 +60,7 @@ public:
 private:
   void emitExceptionRegistrationRecord(Function *F);
 
-  void linkExceptionRegistration(IRBuilder<> &Builder, Value *Handler);
+  void linkExceptionRegistration(IRBuilder<> &Builder, Function *Handler);
   void unlinkExceptionRegistration(IRBuilder<> &Builder);
   void addCXXStateStores(Function &F, MachineModuleInfo &MMI);
   void addSEHStateStores(Function &F, MachineModuleInfo &MMI);
@@ -365,11 +365,14 @@ Function *WinEHStatePass::generateLSDAInEAXThunk(Function *ParentFunc) {
 }
 
 void WinEHStatePass::linkExceptionRegistration(IRBuilder<> &Builder,
-                                               Value *Handler) {
+                                               Function *Handler) {
+  // Emit the .safeseh directive for this function.
+  Handler->addFnAttr("safeseh");
+
   Type *LinkTy = getEHLinkRegistrationType();
   // Handler = Handler
-  Handler = Builder.CreateBitCast(Handler, Builder.getInt8PtrTy());
-  Builder.CreateStore(Handler, Builder.CreateStructGEP(LinkTy, Link, 1));
+  Value *HandlerI8 = Builder.CreateBitCast(Handler, Builder.getInt8PtrTy());
+  Builder.CreateStore(HandlerI8, Builder.CreateStructGEP(LinkTy, Link, 1));
   // Next = [fs:00]
   Constant *FSZero =
       Constant::getNullValue(LinkTy->getPointerTo()->getPointerTo(257));
index 8db127df6da73abd3d2df9e9c6c9dfabd69e5485..7bcd51c44f0e8818155bf062e4d0654700e1e9e7 100644 (file)
@@ -110,3 +110,5 @@ eh.resume:                                        ; preds = %catch.dispatch.4
 ; CHECK: movl $3, Lf$frame_escape_{{[0-9]+.*}}
 ; CHECK: movl $3, (%esp)
 ; CHECK: calll _may_throw
+
+; CHECK: .safeseh ___ehhandler$f
index ed8402aeab07a76b942268c5649fb71e35441aa9..3abaa49653bd5b6c7b264f5735d11a0e5d4e63d3 100644 (file)
@@ -126,3 +126,7 @@ catchall:
 ; CHECK-LABEL: ___ehhandler$use_CxxFrameHandler3:
 ; CHECK: movl $L__ehtable$use_CxxFrameHandler3, %eax
 ; CHECK: jmp  ___CxxFrameHandler3 # TAILCALL
+
+; CHECK: .safeseh __except_handler3
+; CHECK: .safeseh __except_handler4
+; CHECK: .safeseh ___ehhandler$use_CxxFrameHandler3