[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.

llvm-svn: 239448

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

index 7e3a6d5..ffa0ceb 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 41fc8e4..36dd691 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 0c4aaba..16a94da 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 8db127d..7bcd51c 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 ed8402a..3abaa49 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