2 * mach-support-x86.c: mach support for x86
5 * Geoff Norton (gnorton@novell.com)
6 * Rodrigo Kumpera (kumpera@gmail.com)
8 * (C) 2010 Novell, Inc.
9 * (C) 2013 Xamarin, Inc.
18 #include "utils/mono-sigcontext.h"
19 #include "mach-support.h"
22 #include <mono/arch/amd64/amd64-codegen.h>
24 /* Known offsets used for TLS storage*/
26 /* All OSX versions up to 10.8 */
27 #define TLS_VECTOR_OFFSET_CATS 0x60
28 #define TLS_VECTOR_OFFSET_10_9 0xe0
29 #define TLS_VECTOR_OFFSET_10_11 0x100
31 /* This is 2 slots less than the known low */
32 #define TLS_PROBE_LOW_WATERMARK 0x50
33 /* This is 28 slots above the know high, which is more than the known high-low*/
34 #define TLS_PROBE_HIGH_WATERMARK 0x200
37 static int tls_vector_offset
;
40 mono_mach_arch_get_ip (thread_state_t state
)
42 x86_thread_state64_t
*arch_state
= (x86_thread_state64_t
*) state
;
44 return (void *) arch_state
->__rip
;
48 mono_mach_arch_get_sp (thread_state_t state
)
50 x86_thread_state64_t
*arch_state
= (x86_thread_state64_t
*) state
;
52 return (void *) arch_state
->__rsp
;
56 mono_mach_arch_get_mcontext_size ()
58 return sizeof (struct __darwin_mcontext64
);
62 mono_mach_arch_thread_states_to_mcontext (thread_state_t state
, thread_state_t fpstate
, void *context
)
64 x86_thread_state64_t
*arch_state
= (x86_thread_state64_t
*) state
;
65 x86_float_state64_t
*arch_fpstate
= (x86_float_state64_t
*) fpstate
;
66 struct __darwin_mcontext64
*ctx
= (struct __darwin_mcontext64
*) context
;
67 ctx
->__ss
= *arch_state
;
68 ctx
->__fs
= *arch_fpstate
;
72 mono_mach_arch_mcontext_to_thread_states (void *context
, thread_state_t state
, thread_state_t fpstate
)
74 x86_thread_state64_t
*arch_state
= (x86_thread_state64_t
*) state
;
75 x86_float_state64_t
*arch_fpstate
= (x86_float_state64_t
*) fpstate
;
76 struct __darwin_mcontext64
*ctx
= (struct __darwin_mcontext64
*) context
;
77 *arch_state
= ctx
->__ss
;
78 *arch_fpstate
= ctx
->__fs
;
82 mono_mach_arch_thread_states_to_mono_context (thread_state_t state
, thread_state_t fpstate
, MonoContext
*context
)
84 x86_thread_state64_t
*arch_state
= (x86_thread_state64_t
*) state
;
85 x86_float_state64_t
*arch_fpstate
= (x86_float_state64_t
*) fpstate
;
86 context
->gregs
[AMD64_RAX
] = arch_state
->__rax
;
87 context
->gregs
[AMD64_RBX
] = arch_state
->__rbx
;
88 context
->gregs
[AMD64_RCX
] = arch_state
->__rcx
;
89 context
->gregs
[AMD64_RDX
] = arch_state
->__rdx
;
90 context
->gregs
[AMD64_RDI
] = arch_state
->__rdi
;
91 context
->gregs
[AMD64_RBP
] = arch_state
->__rbp
;
92 context
->gregs
[AMD64_RSP
] = arch_state
->__rsp
;
93 context
->gregs
[AMD64_R8
] = arch_state
->__r8
;
94 context
->gregs
[AMD64_R9
] = arch_state
->__r9
;
95 context
->gregs
[AMD64_R10
] = arch_state
->__r10
;
96 context
->gregs
[AMD64_R11
] = arch_state
->__r11
;
97 context
->gregs
[AMD64_R12
] = arch_state
->__r12
;
98 context
->gregs
[AMD64_R13
] = arch_state
->__r13
;
99 context
->gregs
[AMD64_R14
] = arch_state
->__r14
;
100 context
->gregs
[AMD64_R15
] = arch_state
->__r15
;
101 context
->gregs
[AMD64_RIP
] = arch_state
->__rip
;
102 context
->fregs
[AMD64_XMM0
] = arch_fpstate
->__fpu_xmm0
;
103 context
->fregs
[AMD64_XMM1
] = arch_fpstate
->__fpu_xmm1
;
104 context
->fregs
[AMD64_XMM2
] = arch_fpstate
->__fpu_xmm2
;
105 context
->fregs
[AMD64_XMM3
] = arch_fpstate
->__fpu_xmm3
;
106 context
->fregs
[AMD64_XMM4
] = arch_fpstate
->__fpu_xmm4
;
107 context
->fregs
[AMD64_XMM5
] = arch_fpstate
->__fpu_xmm5
;
108 context
->fregs
[AMD64_XMM6
] = arch_fpstate
->__fpu_xmm6
;
109 context
->fregs
[AMD64_XMM7
] = arch_fpstate
->__fpu_xmm7
;
110 context
->fregs
[AMD64_XMM8
] = arch_fpstate
->__fpu_xmm8
;
111 context
->fregs
[AMD64_XMM9
] = arch_fpstate
->__fpu_xmm9
;
112 context
->fregs
[AMD64_XMM10
] = arch_fpstate
->__fpu_xmm10
;
113 context
->fregs
[AMD64_XMM11
] = arch_fpstate
->__fpu_xmm11
;
114 context
->fregs
[AMD64_XMM12
] = arch_fpstate
->__fpu_xmm12
;
115 context
->fregs
[AMD64_XMM13
] = arch_fpstate
->__fpu_xmm13
;
116 context
->fregs
[AMD64_XMM14
] = arch_fpstate
->__fpu_xmm14
;
117 context
->fregs
[AMD64_XMM15
] = arch_fpstate
->__fpu_xmm15
;
121 mono_mach_arch_get_thread_state_size ()
123 return sizeof (x86_thread_state64_t
);
127 mono_mach_arch_get_thread_fpstate_size ()
129 return sizeof (x86_float_state64_t
);
133 mono_mach_arch_get_thread_states (thread_port_t thread
, thread_state_t state
, mach_msg_type_number_t
*count
, thread_state_t fpstate
, mach_msg_type_number_t
*fpcount
)
135 x86_thread_state64_t
*arch_state
= (x86_thread_state64_t
*)state
;
136 x86_float_state64_t
*arch_fpstate
= (x86_float_state64_t
*)fpstate
;
139 *count
= x86_THREAD_STATE64_COUNT
;
140 *fpcount
= x86_FLOAT_STATE64_COUNT
;
142 ret
= thread_get_state (thread
, x86_THREAD_STATE64
, (thread_state_t
)arch_state
, count
);
143 if (ret
!= KERN_SUCCESS
)
146 ret
= thread_get_state (thread
, x86_FLOAT_STATE64
, (thread_state_t
)arch_fpstate
, fpcount
);
151 mono_mach_arch_set_thread_states (thread_port_t thread
, thread_state_t state
, mach_msg_type_number_t count
, thread_state_t fpstate
, mach_msg_type_number_t fpcount
)
154 ret
= thread_set_state (thread
, x86_THREAD_STATE64
, state
, count
);
155 if (ret
!= KERN_SUCCESS
)
157 ret
= thread_set_state (thread
, x86_FLOAT_STATE64
, fpstate
, fpcount
);
162 mono_mach_get_tls_address_from_thread (pthread_t thread
, pthread_key_t key
)
164 /* OSX stores TLS values in a hidden array inside the pthread_t structure
165 * They are keyed off a giant array from a known offset into the pointer. This value
166 * is baked into their pthread_getspecific implementation
168 intptr_t *p
= (intptr_t *)thread
;
169 intptr_t **tsd
= (intptr_t **) ((char*)p
+ tls_vector_offset
);
170 g_assert (tls_vector_offset
!= -1);
172 return (void *) &tsd
[key
];
176 mono_mach_arch_get_tls_value_from_thread (pthread_t thread
, guint32 key
)
178 return *(void**)mono_mach_get_tls_address_from_thread (thread
, key
);
182 mono_mach_init (pthread_key_t key
)
185 void *old_value
= pthread_getspecific (key
);
186 void *canary
= (void*)0xDEADBEEFu
;
188 pthread_key_create (&key
, NULL
);
189 g_assert (old_value
!= canary
);
191 pthread_setspecific (key
, canary
);
193 /*First we probe for cats*/
194 tls_vector_offset
= TLS_VECTOR_OFFSET_CATS
;
195 if (mono_mach_arch_get_tls_value_from_thread (pthread_self (), key
) == canary
)
198 tls_vector_offset
= TLS_VECTOR_OFFSET_10_9
;
199 if (mono_mach_arch_get_tls_value_from_thread (pthread_self (), key
) == canary
)
202 tls_vector_offset
= TLS_VECTOR_OFFSET_10_11
;
203 if (mono_mach_arch_get_tls_value_from_thread (pthread_self (), key
) == canary
)
206 /*Fallback to scanning a large range of offsets*/
207 for (i
= TLS_PROBE_LOW_WATERMARK
; i
<= TLS_PROBE_HIGH_WATERMARK
; i
+= 4) {
208 tls_vector_offset
= i
;
209 if (mono_mach_arch_get_tls_value_from_thread (pthread_self (), key
) == canary
) {
210 g_warning ("Found new TLS offset at %d", i
);
215 tls_vector_offset
= -1;
216 g_warning ("could not discover the mach TLS offset");
218 pthread_setspecific (key
, old_value
);