Fix OSX personality routines encoding
authorJan Vorlicek <janvorli@microsoft.com>
Tue, 12 May 2015 15:31:09 +0000 (17:31 +0200)
committerJan Vorlicek <janvorli@microsoft.com>
Tue, 12 May 2015 16:50:16 +0000 (18:50 +0200)
This change fixes a crash that occured in case a managed callback
called from a native code throws an exception. The correct behavior
is to exit the process and dump the managed call stack. It works ok
on Linux, but on OSX, it crashes with segmentation violation trying
to execute code at address 4.
The problem is caused by the fact that either the assembler or
the linker ignores personality routines specified using the encoding
0 (absolute pointer) and stores value 4 instead of the routine address
no matter what routine is specified.
Fortunatelly, there is another encoding that can be used and that works.
It is an indirect PC relative encoding (code 0x9b).
However, there is another problem. The linker issues a warning when there
are more than 3 personality routines in the whole libcoreclr.dylib:
ld: warning: too many personality routines for compact unwind to encode
As for now, I have removed the ExceptionHijackPersonalityRoutine from
the ExceptionHijack asm helper to fix this problem.
We will need to figure out what to do about it once we enable the thread
hijacking on Unix. This personality routine's purpose is to make stack
walker walk stack of a highjacked function as if the highhack routine was
called from it. It seems we can use a different technique for that -
to create a helper frame that would have IP pointing to a function that
is never called, but has an unwind info that ensures that we walk
through the hijack correctly. The same technique is used for hardware
exception handling on OSX.

src/debug/ee/amd64/dbghelpers.S
src/pal/inc/unixasmmacros.inc

index 7debc0e..50e23b4 100644 (file)
@@ -35,13 +35,12 @@ NESTED_ENTRY FuncEvalHijack, _TEXT, FuncEvalHijackPersonalityRoutine
         TAILJMP_RAX
 NESTED_END FuncEvalHijack, _TEXT
 
-
 //extern ExceptionHijackWorker:proc
 //extern ExceptionHijackPersonalityRoutine:proc
 
 // This is the general purpose hijacking stub. The DacDbi Hijack primitive will 
 // set up the stack and then set the IP here, and so this just makes the call.
-NESTED_ENTRY ExceptionHijack, _TEXT, ExceptionHijackPersonalityRoutine
+NESTED_ENTRY ExceptionHijack, _TEXT, NoHandler
         // the stack should be aligned at this point, since we do not call this
         // function explicitly
         // 
index 097733e..de79ba3 100644 (file)
@@ -88,7 +88,11 @@ C_FUNC(\Name\()_End):
 .macro NESTED_ENTRY Name, Section, Handler
         LEAF_ENTRY \Name, \Section
         .ifnc \Handler, NoHandler
-        .cfi_personality 0, \Handler // 4 == DW_EH_PE_udata8 0 == DW_EH_PE_absptr
+#if defined(__APPLE__)
+        .cfi_personality 0x9b, C_FUNC(\Handler) // 0x9b == DW_EH_PE_indirect | DW_EH_PE_pcrel | DW_EH_PE_sdata4
+#else
+        .cfi_personality 0, C_FUNC(\Handler) // 0 == DW_EH_PE_absptr
+#endif
         .endif
 .endm