summaryrefslogtreecommitdiff
path: root/src/pal/src/arch
diff options
context:
space:
mode:
authorJan Vorlicek <janvorli@microsoft.com>2015-09-18 15:57:49 +0200
committerJan Vorlicek <janvorli@microsoft.com>2015-09-23 21:21:52 +0200
commit0f6c0c35cc3c3d9eaee04e3e46c4898730eff1ec (patch)
tree4a04c16a0ef7ad67995b44d98b2fc3140d610479 /src/pal/src/arch
parent4486bcf73cf9f2926ee8b1e9cb8b5c80339d9627 (diff)
downloadcoreclr-0f6c0c35cc3c3d9eaee04e3e46c4898730eff1ec.tar.gz
coreclr-0f6c0c35cc3c3d9eaee04e3e46c4898730eff1ec.tar.bz2
coreclr-0f6c0c35cc3c3d9eaee04e3e46c4898730eff1ec.zip
Implement runtime suspension for OSX
This change implements runtime suspension for OSX using activation injection, the same mechanism as Linux uses. I have modified the activation injection mechanism by adding a new function that CoreCLR registers with PAL and PAL calls it to check if an instruction address is safe for injection. The injection is performed only if this new function returns true. The activation on OSX is performed by suspending the target thread, checking the instruction address in the suspended thread's context using the above mentioned function and modifying the context to perform the injection only at injection safe place.
Diffstat (limited to 'src/pal/src/arch')
-rw-r--r--src/pal/src/arch/i386/activationhandlerwrapper.S31
-rw-r--r--src/pal/src/arch/i386/asmconstants.h105
-rw-r--r--src/pal/src/arch/i386/context2.S104
-rw-r--r--src/pal/src/arch/i386/dispatchexceptionwrapper.S113
4 files changed, 165 insertions, 188 deletions
diff --git a/src/pal/src/arch/i386/activationhandlerwrapper.S b/src/pal/src/arch/i386/activationhandlerwrapper.S
new file mode 100644
index 0000000000..06151b3d12
--- /dev/null
+++ b/src/pal/src/arch/i386/activationhandlerwrapper.S
@@ -0,0 +1,31 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+.intel_syntax noprefix
+#include "unixasmmacros.inc"
+#include "asmconstants.h"
+
+#ifdef BIT64
+// Offset of the return address from the ActivationHandler in the ActivationHandlerWrapper
+.globl C_FUNC(ActivationHandlerReturnOffset)
+C_FUNC(ActivationHandlerReturnOffset):
+ .int LOCAL_LABEL(ActivationHandlerReturn)-C_FUNC(ActivationHandlerWrapper)
+
+NESTED_ENTRY ActivationHandlerWrapper, _TEXT, NoHandler
+ push_nonvol_reg rbp
+ mov rbp, rsp
+ set_cfa_register rbp, 0
+ alloc_stack (CONTEXT_Size)
+ mov rdi, rsp
+ int3
+ call C_FUNC(ActivationHandler)
+LOCAL_LABEL(ActivationHandlerReturn):
+ int3
+ free_stack (CONTEXT_Size)
+ pop_nonvol_reg rbp
+ ret
+NESTED_END ActivationHandlerWrapper, _TEXT
+
+#endif // BIT64
diff --git a/src/pal/src/arch/i386/asmconstants.h b/src/pal/src/arch/i386/asmconstants.h
new file mode 100644
index 0000000000..575edc2308
--- /dev/null
+++ b/src/pal/src/arch/i386/asmconstants.h
@@ -0,0 +1,105 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+#ifdef BIT64
+
+#define CONTEXT_AMD64 0x100000
+
+#define CONTEXT_CONTROL 1 // SegSs, Rsp, SegCs, Rip, and EFlags
+#define CONTEXT_INTEGER 2 // Rax, Rcx, Rdx, Rbx, Rbp, Rsi, Rdi, R8-R15
+#define CONTEXT_SEGMENTS 4 // SegDs, SegEs, SegFs, SegGs
+#define CONTEXT_FLOATING_POINT 8
+#define CONTEXT_DEBUG_REGISTERS 16 // Dr0-Dr3 and Dr6-Dr7
+
+#define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT)
+
+#define CONTEXT_ContextFlags 6*8
+#define CONTEXT_SegCs CONTEXT_ContextFlags+8
+#define CONTEXT_SegDs CONTEXT_SegCs+2
+#define CONTEXT_SegEs CONTEXT_SegDs+2
+#define CONTEXT_SegFs CONTEXT_SegEs+2
+#define CONTEXT_SegGs CONTEXT_SegFs+2
+#define CONTEXT_SegSs CONTEXT_SegGs+2
+#define CONTEXT_EFlags CONTEXT_SegSs+2
+#define CONTEXT_Dr0 CONTEXT_EFlags+4
+#define CONTEXT_Dr1 CONTEXT_Dr0+8
+#define CONTEXT_Dr2 CONTEXT_Dr1+8
+#define CONTEXT_Dr3 CONTEXT_Dr2+8
+#define CONTEXT_Dr6 CONTEXT_Dr3+8
+#define CONTEXT_Dr7 CONTEXT_Dr6+8
+#define CONTEXT_Rax CONTEXT_Dr7+8
+#define CONTEXT_Rcx CONTEXT_Rax+8
+#define CONTEXT_Rdx CONTEXT_Rcx+8
+#define CONTEXT_Rbx CONTEXT_Rdx+8
+#define CONTEXT_Rsp CONTEXT_Rbx+8
+#define CONTEXT_Rbp CONTEXT_Rsp+8
+#define CONTEXT_Rsi CONTEXT_Rbp+8
+#define CONTEXT_Rdi CONTEXT_Rsi+8
+#define CONTEXT_R8 CONTEXT_Rdi+8
+#define CONTEXT_R9 CONTEXT_R8+8
+#define CONTEXT_R10 CONTEXT_R9+8
+#define CONTEXT_R11 CONTEXT_R10+8
+#define CONTEXT_R12 CONTEXT_R11+8
+#define CONTEXT_R13 CONTEXT_R12+8
+#define CONTEXT_R14 CONTEXT_R13+8
+#define CONTEXT_R15 CONTEXT_R14+8
+#define CONTEXT_Rip CONTEXT_R15+8
+#define CONTEXT_FltSave CONTEXT_Rip+8
+#define FLOATING_SAVE_AREA_SIZE 4*8+24*16+96
+#define CONTEXT_Xmm0 CONTEXT_FltSave+FLOATING_SAVE_AREA_SIZE // was 10*16
+#define CONTEXT_Xmm1 CONTEXT_Xmm0+16
+#define CONTEXT_Xmm2 CONTEXT_Xmm1+16
+#define CONTEXT_Xmm3 CONTEXT_Xmm2+16
+#define CONTEXT_Xmm4 CONTEXT_Xmm3+16
+#define CONTEXT_Xmm5 CONTEXT_Xmm4+16
+#define CONTEXT_Xmm6 CONTEXT_Xmm5+16
+#define CONTEXT_Xmm7 CONTEXT_Xmm6+16
+#define CONTEXT_Xmm8 CONTEXT_Xmm7+16
+#define CONTEXT_Xmm9 CONTEXT_Xmm8+16
+#define CONTEXT_Xmm10 CONTEXT_Xmm9+16
+#define CONTEXT_Xmm11 CONTEXT_Xmm10+16
+#define CONTEXT_Xmm12 CONTEXT_Xmm11+16
+#define CONTEXT_Xmm13 CONTEXT_Xmm12+16
+#define CONTEXT_Xmm14 CONTEXT_Xmm13+16
+#define CONTEXT_Xmm15 CONTEXT_Xmm14+16
+#define CONTEXT_VectorRegister CONTEXT_Xmm15+16
+#define CONTEXT_VectorControl CONTEXT_VectorRegister+16*26
+#define CONTEXT_DebugControl CONTEXT_VectorControl+8
+#define CONTEXT_LastBranchToRip CONTEXT_DebugControl+8
+#define CONTEXT_LastBranchFromRip CONTEXT_LastBranchToRip+8
+#define CONTEXT_LastExceptionToRip CONTEXT_LastBranchFromRip+8
+#define CONTEXT_LastExceptionFromRip CONTEXT_LastExceptionToRip+8
+#define CONTEXT_Size CONTEXT_LastExceptionFromRip+8
+
+#else // BIT64
+
+#define CONTEXT_ContextFlags 0
+#define CONTEXT_FLOATING_POINT 8
+#define CONTEXT_FloatSave 7*4
+#define FLOATING_SAVE_AREA_SIZE 8*4+80
+#define CONTEXT_Edi CONTEXT_FloatSave + FLOATING_SAVE_AREA_SIZE + 4*4
+#define CONTEXT_Esi CONTEXT_Edi+4
+#define CONTEXT_Ebx CONTEXT_Esi+4
+#define CONTEXT_Edx CONTEXT_Ebx+4
+#define CONTEXT_Ecx CONTEXT_Edx+4
+#define CONTEXT_Eax CONTEXT_Ecx+4
+#define CONTEXT_Ebp CONTEXT_Eax+4
+#define CONTEXT_Eip CONTEXT_Ebp+4
+#define CONTEXT_SegCs CONTEXT_Eip+4
+#define CONTEXT_EFlags CONTEXT_SegCs+4
+#define CONTEXT_Esp CONTEXT_EFlags+4
+#define CONTEXT_SegSs CONTEXT_Esp+4
+#define CONTEXT_EXTENDED_REGISTERS 32
+#define CONTEXT_ExtendedRegisters CONTEXT_SegSs+4
+#define CONTEXT_Xmm0 CONTEXT_ExtendedRegisters+160
+#define CONTEXT_Xmm1 CONTEXT_Xmm0+16
+#define CONTEXT_Xmm2 CONTEXT_Xmm1+16
+#define CONTEXT_Xmm3 CONTEXT_Xmm2+16
+#define CONTEXT_Xmm4 CONTEXT_Xmm3+16
+#define CONTEXT_Xmm5 CONTEXT_Xmm4+16
+#define CONTEXT_Xmm6 CONTEXT_Xmm5+16
+#define CONTEXT_Xmm7 CONTEXT_Xmm6+16
+
+#endif // BIT64
diff --git a/src/pal/src/arch/i386/context2.S b/src/pal/src/arch/i386/context2.S
index 27875b722a..e6b0c2fe39 100644
--- a/src/pal/src/arch/i386/context2.S
+++ b/src/pal/src/arch/i386/context2.S
@@ -10,76 +10,10 @@
.intel_syntax noprefix
#include "unixasmmacros.inc"
+#include "asmconstants.h"
#ifdef BIT64
-#define CONTEXT_AMD64 0x100000
-
-#define CONTEXT_CONTROL 1 // SegSs, Rsp, SegCs, Rip, and EFlags
-#define CONTEXT_INTEGER 2 // Rax, Rcx, Rdx, Rbx, Rbp, Rsi, Rdi, R8-R15
-#define CONTEXT_SEGMENTS 4 // SegDs, SegEs, SegFs, SegGs
-#define CONTEXT_FLOATING_POINT 8
-#define CONTEXT_DEBUG_REGISTERS 16 // Dr0-Dr3 and Dr6-Dr7
-
-#define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT)
-
-#define CONTEXT_ContextFlags 6*8
-#define CONTEXT_SegCs CONTEXT_ContextFlags+8
-#define CONTEXT_SegDs CONTEXT_SegCs+2
-#define CONTEXT_SegEs CONTEXT_SegDs+2
-#define CONTEXT_SegFs CONTEXT_SegEs+2
-#define CONTEXT_SegGs CONTEXT_SegFs+2
-#define CONTEXT_SegSs CONTEXT_SegGs+2
-#define CONTEXT_EFlags CONTEXT_SegSs+2
-#define CONTEXT_Dr0 CONTEXT_EFlags+4
-#define CONTEXT_Dr1 CONTEXT_Dr0+8
-#define CONTEXT_Dr2 CONTEXT_Dr1+8
-#define CONTEXT_Dr3 CONTEXT_Dr2+8
-#define CONTEXT_Dr6 CONTEXT_Dr3+8
-#define CONTEXT_Dr7 CONTEXT_Dr6+8
-#define CONTEXT_Rax CONTEXT_Dr7+8
-#define CONTEXT_Rcx CONTEXT_Rax+8
-#define CONTEXT_Rdx CONTEXT_Rcx+8
-#define CONTEXT_Rbx CONTEXT_Rdx+8
-#define CONTEXT_Rsp CONTEXT_Rbx+8
-#define CONTEXT_Rbp CONTEXT_Rsp+8
-#define CONTEXT_Rsi CONTEXT_Rbp+8
-#define CONTEXT_Rdi CONTEXT_Rsi+8
-#define CONTEXT_R8 CONTEXT_Rdi+8
-#define CONTEXT_R9 CONTEXT_R8+8
-#define CONTEXT_R10 CONTEXT_R9+8
-#define CONTEXT_R11 CONTEXT_R10+8
-#define CONTEXT_R12 CONTEXT_R11+8
-#define CONTEXT_R13 CONTEXT_R12+8
-#define CONTEXT_R14 CONTEXT_R13+8
-#define CONTEXT_R15 CONTEXT_R14+8
-#define CONTEXT_Rip CONTEXT_R15+8
-#define CONTEXT_FltSave CONTEXT_Rip+8
-#define FLOATING_SAVE_AREA_SIZE 4*8+24*16+96
-#define CONTEXT_Xmm0 CONTEXT_FltSave+10*16
-#define CONTEXT_Xmm1 CONTEXT_Xmm0+16
-#define CONTEXT_Xmm2 CONTEXT_Xmm1+16
-#define CONTEXT_Xmm3 CONTEXT_Xmm2+16
-#define CONTEXT_Xmm4 CONTEXT_Xmm3+16
-#define CONTEXT_Xmm5 CONTEXT_Xmm4+16
-#define CONTEXT_Xmm6 CONTEXT_Xmm5+16
-#define CONTEXT_Xmm7 CONTEXT_Xmm6+16
-#define CONTEXT_Xmm8 CONTEXT_Xmm7+16
-#define CONTEXT_Xmm9 CONTEXT_Xmm8+16
-#define CONTEXT_Xmm10 CONTEXT_Xmm9+16
-#define CONTEXT_Xmm11 CONTEXT_Xmm10+16
-#define CONTEXT_Xmm12 CONTEXT_Xmm11+16
-#define CONTEXT_Xmm13 CONTEXT_Xmm12+16
-#define CONTEXT_Xmm14 CONTEXT_Xmm13+16
-#define CONTEXT_Xmm15 CONTEXT_Xmm14+16
-#define CONTEXT_VectorRegister CONTEXT_Xmm15+16
-#define CONTEXT_VectorControl CONTEXT_VectorRegister+16*26
-#define CONTEXT_DebugControl CONTEXT_VectorControl+8
-#define CONTEXT_LastBranchToRip CONTEXT_DebugControl+8
-#define CONTEXT_LastBranchFromRip CONTEXT_LastBranchToRip+8
-#define CONTEXT_LastExceptionToRip CONTEXT_LastBranchFromRip+8
-#define CONTEXT_LastExceptionFromRip CONTEXT_LastExceptionToRip+8
-
#define IRETFRAME_Rip 0
#define IRETFRAME_SegCs IRETFRAME_Rip+8
#define IRETFRAME_EFlags IRETFRAME_SegCs+8
@@ -198,7 +132,16 @@ LOCAL_LABEL(Done_Restore_CONTEXT_FLOATING_POINT):
// The control registers are restored via the iret instruction
// so we build the frame for the iret on the stack.
+#ifdef __APPLE__
+.att_syntax
+ // On OSX, we cannot read SS via the thread_get_context and RtlRestoreContext
+ // needs to be used on context extracted by thread_get_context. So we
+ // don't change the SS.
+ mov %ss, %ax
+.intel_syntax noprefix
+#else
mov ax, [rdi + CONTEXT_SegSs]
+#endif
mov [rsp + IRETFRAME_SegSs], ax
mov rax, [rdi + CONTEXT_Rsp]
mov [rsp + IRETFRAME_Rsp], rax
@@ -249,33 +192,6 @@ LEAF_END RtlRestoreContext, _TEXT
#else
-#define CONTEXT_ContextFlags 0
-#define CONTEXT_FLOATING_POINT 8
-#define CONTEXT_FloatSave 7*4
-#define FLOATING_SAVE_AREA_SIZE 8*4+80
-#define CONTEXT_Edi CONTEXT_FloatSave + FLOATING_SAVE_AREA_SIZE + 4*4
-#define CONTEXT_Esi CONTEXT_Edi+4
-#define CONTEXT_Ebx CONTEXT_Esi+4
-#define CONTEXT_Edx CONTEXT_Ebx+4
-#define CONTEXT_Ecx CONTEXT_Edx+4
-#define CONTEXT_Eax CONTEXT_Ecx+4
-#define CONTEXT_Ebp CONTEXT_Eax+4
-#define CONTEXT_Eip CONTEXT_Ebp+4
-#define CONTEXT_SegCs CONTEXT_Eip+4
-#define CONTEXT_EFlags CONTEXT_SegCs+4
-#define CONTEXT_Esp CONTEXT_EFlags+4
-#define CONTEXT_SegSs CONTEXT_Esp+4
-#define CONTEXT_EXTENDED_REGISTERS 32
-#define CONTEXT_ExtendedRegisters CONTEXT_SegSs+4
-#define CONTEXT_Xmm0 CONTEXT_ExtendedRegisters+160
-#define CONTEXT_Xmm1 CONTEXT_Xmm0+16
-#define CONTEXT_Xmm2 CONTEXT_Xmm1+16
-#define CONTEXT_Xmm3 CONTEXT_Xmm2+16
-#define CONTEXT_Xmm4 CONTEXT_Xmm3+16
-#define CONTEXT_Xmm5 CONTEXT_Xmm4+16
-#define CONTEXT_Xmm6 CONTEXT_Xmm5+16
-#define CONTEXT_Xmm7 CONTEXT_Xmm6+16
-
.globl C_FUNC(CONTEXT_CaptureContext)
C_FUNC(CONTEXT_CaptureContext):
push %eax
diff --git a/src/pal/src/arch/i386/dispatchexceptionwrapper.S b/src/pal/src/arch/i386/dispatchexceptionwrapper.S
index 952e5a0cbb..c8382e968d 100644
--- a/src/pal/src/arch/i386/dispatchexceptionwrapper.S
+++ b/src/pal/src/arch/i386/dispatchexceptionwrapper.S
@@ -13,10 +13,9 @@
// and PAL_DispatchException that throws an SEH exception for
// the fault, to make the stack unwindable.
//
-// On Mac OS X 10.6, the unwinder fails to operate correctly
-// on our original int3; int3 body. The workaround is to
-// increase the size of the function to include a call statement,
-// even though it will never be executed.
+
+.intel_syntax noprefix
+#include "unixasmmacros.inc"
#if defined(__x86_64__)
#define PAL_DISPATCHEXCEPTION __Z21PAL_DispatchExceptionmmmmmmP8_CONTEXTP17_EXCEPTION_RECORD
@@ -24,33 +23,16 @@
#define PAL_DISPATCHEXCEPTION __Z21PAL_DispatchExceptionP8_CONTEXTP17_EXCEPTION_RECORD
#endif // defined(_AMD64_)
- .text
- .globl __Z21PAL_DispatchExceptionP8_CONTEXTP17_EXCEPTION_RECORD
- .globl _PAL_DispatchExceptionWrapper
-_PAL_DispatchExceptionWrapper:
-LBegin:
- int3
- call PAL_DISPATCHEXCEPTION
- int3
-LEnd:
+// Offset of the return address from the PAL_DISPATCHEXCEPTION in the PAL_DispatchExceptionWrapper
+.globl C_FUNC(PAL_DispatchExceptionReturnOffset)
+C_FUNC(PAL_DispatchExceptionReturnOffset):
+ .int LOCAL_LABEL(PAL_DispatchExceptionReturn)-C_FUNC(PAL_DispatchExceptionWrapper)
//
// PAL_DispatchExceptionWrapper will never be called; it only serves
// to be referenced from a stack frame on the faulting thread. Its
// unwinding behavior is equivalent to any standard function having
-// an ebp frame. The FDE below is analogous to the one generated
-// by "g++ -S" for the following source file.
-//
-// --- snip ---
-// struct CONTEXT
-// {
-// char reserved[716];
-// };
-//
-// struct EXCEPTION_RECORD
-// {
-// char reserved[80];
-// };
+// an ebp frame. It is analogous to the following source file.
//
// void PAL_DispatchException(CONTEXT *pContext, EXCEPTION_RECORD *pExceptionRecord);
//
@@ -60,74 +42,17 @@ LEnd:
// EXCEPTION_RECORD ExceptionRecord;
// PAL_DispatchException(&Context, &ExceptionRecord);
// }
-// --- snip ---
//
- .section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
-CIE_DispatchExceptionPersonality:
- .long LECIE1-LSCIE1
-LSCIE1:
- .long 0x0
- .byte 0x1
- .ascii "zLR\0"
- .byte 0x1
-#ifdef BIT64
- .byte 0x78 // data_align: -8
- .byte 16 // return address register: rip
-#else // BIT64
- .byte 0x7c // data_align: -4
- .byte 0x8 // return address register: eip
-#endif // BIT64 else
- .byte 0x2
- .byte 0x10
- .byte 0x10
- .byte 0xc // DW_CFA_def_cfa
-#ifdef BIT64
- .byte 0x7 // operand1 = rsp
- .byte 0x8 // operand2 = offset 8
- .byte 0x80 | 16 // DW_CFA_offset of return address register
-#else // BIT64
- .byte 0x5 // operand1 = esp
- .byte 0x4 // operand2 = offset 4
- .byte 0x80 | 8 // DW_CFA_offset of return address register
-#endif // BIT64 else
- .byte 0x1 // operand1 = 1 word
- .align 2
-LECIE1:
+NESTED_ENTRY PAL_DispatchExceptionWrapper, _TEXT, NoHandler
+ push_nonvol_reg rbp
+ mov rbp, rsp
+ set_cfa_register rbp, 0
+ int3
+ call PAL_DISPATCHEXCEPTION
+LOCAL_LABEL(PAL_DispatchExceptionReturn):
+ int3
+ pop_nonvol_reg rbp
+ ret
+NESTED_END PAL_DispatchExceptionWrapper, _TEXT
- .globl _PAL_DispatchExceptionWrapper.eh
-_PAL_DispatchExceptionWrapper.eh:
-LSFDE1:
- .set LLFDE1,LEFDE1-LASFDE1
- .set LLength,LEnd-LBegin
- .long LLFDE1
-LASFDE1:
- .long LASFDE1-CIE_DispatchExceptionPersonality
-#ifdef BIT64
- .quad LBegin-.
- .quad LLength
- .byte 0x8
- .quad 0x0
-#else // BIT64
- .long LBegin-.
- .long LLength
- .byte 0x4
- .long 0x0
-#endif // BIT64 else
- .byte 0xe // DW_CFA_def_cfa_offset
-#ifdef BIT64
- .byte 0x10
- .byte 0x80 | 6 // DW_CFA_offset rbp
-#else // BIT64
- .byte 0x8
- .byte 0x80 | 4 // DW_CFA_offset ebp
-#endif // BIT64 else
- .byte 0x2
- .byte 0xd // DW_CFA_def_cfa_register
-#ifdef BIT64
- .byte 6 // operand1 = rbp
-#else // BIT64
- .byte 4 // operand1 = ebp
-#endif // BIT64
- .align 2
-LEFDE1: