wined3d: Correctly destroy the adapter on format initialization failure in no3d mode.
[wine/zf.git] / dlls / ntdll / unix / signal_x86_64.c
blob01be0eab8146e0e44d0f5489bf92d081077eb969
1 /*
2 * x86-64 signal handling routines
4 * Copyright 1999, 2005 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #if 0
22 #pragma makedep unix
23 #endif
25 #ifdef __x86_64__
27 #include "config.h"
28 #include "wine/port.h"
30 #include <assert.h>
31 #include <pthread.h>
32 #include <signal.h>
33 #include <stdlib.h>
34 #include <stdarg.h>
35 #include <stdio.h>
36 #include <sys/types.h>
37 #ifdef HAVE_UNISTD_H
38 # include <unistd.h>
39 #endif
40 #ifdef HAVE_MACHINE_SYSARCH_H
41 # include <machine/sysarch.h>
42 #endif
43 #ifdef HAVE_SYS_PARAM_H
44 # include <sys/param.h>
45 #endif
46 #ifdef HAVE_SYSCALL_H
47 # include <syscall.h>
48 #else
49 # ifdef HAVE_SYS_SYSCALL_H
50 # include <sys/syscall.h>
51 # endif
52 #endif
53 #ifdef HAVE_SYS_SIGNAL_H
54 # include <sys/signal.h>
55 #endif
56 #ifdef HAVE_SYS_UCONTEXT_H
57 # include <sys/ucontext.h>
58 #endif
59 #ifdef HAVE_LIBUNWIND
60 # define UNW_LOCAL_ONLY
61 # include <libunwind.h>
62 #endif
63 #ifdef __APPLE__
64 # include <mach/mach.h>
65 #endif
67 #define NONAMELESSUNION
68 #define NONAMELESSSTRUCT
69 #include "ntstatus.h"
70 #define WIN32_NO_STATUS
71 #include "windef.h"
72 #include "winternl.h"
73 #include "wine/exception.h"
74 #include "wine/list.h"
75 #include "wine/asm.h"
76 #include "unix_private.h"
77 #include "wine/debug.h"
79 WINE_DEFAULT_DEBUG_CHANNEL(seh);
81 /***********************************************************************
82 * signal context platform-specific definitions
84 #ifdef linux
86 #include <asm/prctl.h>
87 static inline int arch_prctl( int func, void *ptr ) { return syscall( __NR_arch_prctl, func, ptr ); }
89 #define RAX_sig(context) ((context)->uc_mcontext.gregs[REG_RAX])
90 #define RBX_sig(context) ((context)->uc_mcontext.gregs[REG_RBX])
91 #define RCX_sig(context) ((context)->uc_mcontext.gregs[REG_RCX])
92 #define RDX_sig(context) ((context)->uc_mcontext.gregs[REG_RDX])
93 #define RSI_sig(context) ((context)->uc_mcontext.gregs[REG_RSI])
94 #define RDI_sig(context) ((context)->uc_mcontext.gregs[REG_RDI])
95 #define RBP_sig(context) ((context)->uc_mcontext.gregs[REG_RBP])
96 #define R8_sig(context) ((context)->uc_mcontext.gregs[REG_R8])
97 #define R9_sig(context) ((context)->uc_mcontext.gregs[REG_R9])
98 #define R10_sig(context) ((context)->uc_mcontext.gregs[REG_R10])
99 #define R11_sig(context) ((context)->uc_mcontext.gregs[REG_R11])
100 #define R12_sig(context) ((context)->uc_mcontext.gregs[REG_R12])
101 #define R13_sig(context) ((context)->uc_mcontext.gregs[REG_R13])
102 #define R14_sig(context) ((context)->uc_mcontext.gregs[REG_R14])
103 #define R15_sig(context) ((context)->uc_mcontext.gregs[REG_R15])
104 #define CS_sig(context) (*((WORD *)&(context)->uc_mcontext.gregs[REG_CSGSFS] + 0))
105 #define GS_sig(context) (*((WORD *)&(context)->uc_mcontext.gregs[REG_CSGSFS] + 1))
106 #define FS_sig(context) (*((WORD *)&(context)->uc_mcontext.gregs[REG_CSGSFS] + 2))
107 #define RSP_sig(context) ((context)->uc_mcontext.gregs[REG_RSP])
108 #define RIP_sig(context) ((context)->uc_mcontext.gregs[REG_RIP])
109 #define EFL_sig(context) ((context)->uc_mcontext.gregs[REG_EFL])
110 #define TRAP_sig(context) ((context)->uc_mcontext.gregs[REG_TRAPNO])
111 #define ERROR_sig(context) ((context)->uc_mcontext.gregs[REG_ERR])
112 #define FPU_sig(context) ((XMM_SAVE_AREA32 *)((context)->uc_mcontext.fpregs))
114 #elif defined(__FreeBSD__) || defined (__FreeBSD_kernel__)
116 #define RAX_sig(context) ((context)->uc_mcontext.mc_rax)
117 #define RBX_sig(context) ((context)->uc_mcontext.mc_rbx)
118 #define RCX_sig(context) ((context)->uc_mcontext.mc_rcx)
119 #define RDX_sig(context) ((context)->uc_mcontext.mc_rdx)
120 #define RSI_sig(context) ((context)->uc_mcontext.mc_rsi)
121 #define RDI_sig(context) ((context)->uc_mcontext.mc_rdi)
122 #define RBP_sig(context) ((context)->uc_mcontext.mc_rbp)
123 #define R8_sig(context) ((context)->uc_mcontext.mc_r8)
124 #define R9_sig(context) ((context)->uc_mcontext.mc_r9)
125 #define R10_sig(context) ((context)->uc_mcontext.mc_r10)
126 #define R11_sig(context) ((context)->uc_mcontext.mc_r11)
127 #define R12_sig(context) ((context)->uc_mcontext.mc_r12)
128 #define R13_sig(context) ((context)->uc_mcontext.mc_r13)
129 #define R14_sig(context) ((context)->uc_mcontext.mc_r14)
130 #define R15_sig(context) ((context)->uc_mcontext.mc_r15)
131 #define CS_sig(context) ((context)->uc_mcontext.mc_cs)
132 #define DS_sig(context) ((context)->uc_mcontext.mc_ds)
133 #define ES_sig(context) ((context)->uc_mcontext.mc_es)
134 #define FS_sig(context) ((context)->uc_mcontext.mc_fs)
135 #define GS_sig(context) ((context)->uc_mcontext.mc_gs)
136 #define SS_sig(context) ((context)->uc_mcontext.mc_ss)
137 #define EFL_sig(context) ((context)->uc_mcontext.mc_rflags)
138 #define RIP_sig(context) ((context)->uc_mcontext.mc_rip)
139 #define RSP_sig(context) ((context)->uc_mcontext.mc_rsp)
140 #define TRAP_sig(context) ((context)->uc_mcontext.mc_trapno)
141 #define ERROR_sig(context) ((context)->uc_mcontext.mc_err)
142 #define FPU_sig(context) ((XMM_SAVE_AREA32 *)((context)->uc_mcontext.mc_fpstate))
144 #elif defined(__NetBSD__)
146 #define RAX_sig(context) ((context)->uc_mcontext.__gregs[_REG_RAX])
147 #define RBX_sig(context) ((context)->uc_mcontext.__gregs[_REG_RBX])
148 #define RCX_sig(context) ((context)->uc_mcontext.__gregs[_REG_RCX])
149 #define RDX_sig(context) ((context)->uc_mcontext.__gregs[_REG_RDX])
150 #define RSI_sig(context) ((context)->uc_mcontext.__gregs[_REG_RSI])
151 #define RDI_sig(context) ((context)->uc_mcontext.__gregs[_REG_RDI])
152 #define RBP_sig(context) ((context)->uc_mcontext.__gregs[_REG_RBP])
153 #define R8_sig(context) ((context)->uc_mcontext.__gregs[_REG_R8])
154 #define R9_sig(context) ((context)->uc_mcontext.__gregs[_REG_R9])
155 #define R10_sig(context) ((context)->uc_mcontext.__gregs[_REG_R10])
156 #define R11_sig(context) ((context)->uc_mcontext.__gregs[_REG_R11])
157 #define R12_sig(context) ((context)->uc_mcontext.__gregs[_REG_R12])
158 #define R13_sig(context) ((context)->uc_mcontext.__gregs[_REG_R13])
159 #define R14_sig(context) ((context)->uc_mcontext.__gregs[_REG_R14])
160 #define R15_sig(context) ((context)->uc_mcontext.__gregs[_REG_R15])
161 #define CS_sig(context) ((context)->uc_mcontext.__gregs[_REG_CS])
162 #define DS_sig(context) ((context)->uc_mcontext.__gregs[_REG_DS])
163 #define ES_sig(context) ((context)->uc_mcontext.__gregs[_REG_ES])
164 #define FS_sig(context) ((context)->uc_mcontext.__gregs[_REG_FS])
165 #define GS_sig(context) ((context)->uc_mcontext.__gregs[_REG_GS])
166 #define SS_sig(context) ((context)->uc_mcontext.__gregs[_REG_SS])
167 #define EFL_sig(context) ((context)->uc_mcontext.__gregs[_REG_RFL])
168 #define RIP_sig(context) (*((unsigned long*)&(context)->uc_mcontext.__gregs[_REG_RIP]))
169 #define RSP_sig(context) (*((unsigned long*)&(context)->uc_mcontext.__gregs[_REG_URSP]))
170 #define TRAP_sig(context) ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
171 #define ERROR_sig(context) ((context)->uc_mcontext.__gregs[_REG_ERR])
172 #define FPU_sig(context) ((XMM_SAVE_AREA32 *)((context)->uc_mcontext.__fpregs))
174 #elif defined (__APPLE__)
176 #define RAX_sig(context) ((context)->uc_mcontext->__ss.__rax)
177 #define RBX_sig(context) ((context)->uc_mcontext->__ss.__rbx)
178 #define RCX_sig(context) ((context)->uc_mcontext->__ss.__rcx)
179 #define RDX_sig(context) ((context)->uc_mcontext->__ss.__rdx)
180 #define RSI_sig(context) ((context)->uc_mcontext->__ss.__rsi)
181 #define RDI_sig(context) ((context)->uc_mcontext->__ss.__rdi)
182 #define RBP_sig(context) ((context)->uc_mcontext->__ss.__rbp)
183 #define R8_sig(context) ((context)->uc_mcontext->__ss.__r8)
184 #define R9_sig(context) ((context)->uc_mcontext->__ss.__r9)
185 #define R10_sig(context) ((context)->uc_mcontext->__ss.__r10)
186 #define R11_sig(context) ((context)->uc_mcontext->__ss.__r11)
187 #define R12_sig(context) ((context)->uc_mcontext->__ss.__r12)
188 #define R13_sig(context) ((context)->uc_mcontext->__ss.__r13)
189 #define R14_sig(context) ((context)->uc_mcontext->__ss.__r14)
190 #define R15_sig(context) ((context)->uc_mcontext->__ss.__r15)
191 #define CS_sig(context) ((context)->uc_mcontext->__ss.__cs)
192 #define FS_sig(context) ((context)->uc_mcontext->__ss.__fs)
193 #define GS_sig(context) ((context)->uc_mcontext->__ss.__gs)
194 #define EFL_sig(context) ((context)->uc_mcontext->__ss.__rflags)
195 #define RIP_sig(context) (*((unsigned long*)&(context)->uc_mcontext->__ss.__rip))
196 #define RSP_sig(context) (*((unsigned long*)&(context)->uc_mcontext->__ss.__rsp))
197 #define TRAP_sig(context) ((context)->uc_mcontext->__es.__trapno)
198 #define ERROR_sig(context) ((context)->uc_mcontext->__es.__err)
199 #define FPU_sig(context) ((XMM_SAVE_AREA32 *)&(context)->uc_mcontext->__fs.__fpu_fcw)
201 #else
202 #error You must define the signal context functions for your platform
203 #endif
205 enum i386_trap_code
207 TRAP_x86_DIVIDE = 0, /* Division by zero exception */
208 TRAP_x86_TRCTRAP = 1, /* Single-step exception */
209 TRAP_x86_NMI = 2, /* NMI interrupt */
210 TRAP_x86_BPTFLT = 3, /* Breakpoint exception */
211 TRAP_x86_OFLOW = 4, /* Overflow exception */
212 TRAP_x86_BOUND = 5, /* Bound range exception */
213 TRAP_x86_PRIVINFLT = 6, /* Invalid opcode exception */
214 TRAP_x86_DNA = 7, /* Device not available exception */
215 TRAP_x86_DOUBLEFLT = 8, /* Double fault exception */
216 TRAP_x86_FPOPFLT = 9, /* Coprocessor segment overrun */
217 TRAP_x86_TSSFLT = 10, /* Invalid TSS exception */
218 TRAP_x86_SEGNPFLT = 11, /* Segment not present exception */
219 TRAP_x86_STKFLT = 12, /* Stack fault */
220 TRAP_x86_PROTFLT = 13, /* General protection fault */
221 TRAP_x86_PAGEFLT = 14, /* Page fault */
222 TRAP_x86_ARITHTRAP = 16, /* Floating point exception */
223 TRAP_x86_ALIGNFLT = 17, /* Alignment check exception */
224 TRAP_x86_MCHK = 18, /* Machine check exception */
225 TRAP_x86_CACHEFLT = 19 /* Cache flush exception */
228 /* stack layout when calling an exception raise function */
229 struct stack_layout
231 CONTEXT context;
232 ULONG64 unknown[4];
233 EXCEPTION_RECORD rec;
234 ULONG64 rsi;
235 ULONG64 rdi;
236 ULONG64 rbp;
237 ULONG64 rip;
238 ULONG64 red_zone[16];
241 C_ASSERT( sizeof(struct stack_layout) == 0x630 ); /* Should match the size in call_user_exception_dispatcher(). */
243 struct amd64_thread_data
245 DWORD_PTR dr0; /* debug registers */
246 DWORD_PTR dr1;
247 DWORD_PTR dr2;
248 DWORD_PTR dr3;
249 DWORD_PTR dr6;
250 DWORD_PTR dr7;
251 void *exit_frame; /* exit frame pointer */
254 C_ASSERT( sizeof(struct amd64_thread_data) <= sizeof(((TEB *)0)->SystemReserved2) );
255 C_ASSERT( offsetof( TEB, SystemReserved2 ) + offsetof( struct amd64_thread_data, exit_frame ) == 0x330 );
257 static inline struct amd64_thread_data *amd64_thread_data(void)
259 return (struct amd64_thread_data *)NtCurrentTeb()->SystemReserved2;
263 /***********************************************************************
264 * Definitions for Dwarf unwind tables
267 enum dwarf_call_frame_info
269 DW_CFA_advance_loc = 0x40,
270 DW_CFA_offset = 0x80,
271 DW_CFA_restore = 0xc0,
272 DW_CFA_nop = 0x00,
273 DW_CFA_set_loc = 0x01,
274 DW_CFA_advance_loc1 = 0x02,
275 DW_CFA_advance_loc2 = 0x03,
276 DW_CFA_advance_loc4 = 0x04,
277 DW_CFA_offset_extended = 0x05,
278 DW_CFA_restore_extended = 0x06,
279 DW_CFA_undefined = 0x07,
280 DW_CFA_same_value = 0x08,
281 DW_CFA_register = 0x09,
282 DW_CFA_remember_state = 0x0a,
283 DW_CFA_restore_state = 0x0b,
284 DW_CFA_def_cfa = 0x0c,
285 DW_CFA_def_cfa_register = 0x0d,
286 DW_CFA_def_cfa_offset = 0x0e,
287 DW_CFA_def_cfa_expression = 0x0f,
288 DW_CFA_expression = 0x10,
289 DW_CFA_offset_extended_sf = 0x11,
290 DW_CFA_def_cfa_sf = 0x12,
291 DW_CFA_def_cfa_offset_sf = 0x13,
292 DW_CFA_val_offset = 0x14,
293 DW_CFA_val_offset_sf = 0x15,
294 DW_CFA_val_expression = 0x16,
297 enum dwarf_operation
299 DW_OP_addr = 0x03,
300 DW_OP_deref = 0x06,
301 DW_OP_const1u = 0x08,
302 DW_OP_const1s = 0x09,
303 DW_OP_const2u = 0x0a,
304 DW_OP_const2s = 0x0b,
305 DW_OP_const4u = 0x0c,
306 DW_OP_const4s = 0x0d,
307 DW_OP_const8u = 0x0e,
308 DW_OP_const8s = 0x0f,
309 DW_OP_constu = 0x10,
310 DW_OP_consts = 0x11,
311 DW_OP_dup = 0x12,
312 DW_OP_drop = 0x13,
313 DW_OP_over = 0x14,
314 DW_OP_pick = 0x15,
315 DW_OP_swap = 0x16,
316 DW_OP_rot = 0x17,
317 DW_OP_xderef = 0x18,
318 DW_OP_abs = 0x19,
319 DW_OP_and = 0x1a,
320 DW_OP_div = 0x1b,
321 DW_OP_minus = 0x1c,
322 DW_OP_mod = 0x1d,
323 DW_OP_mul = 0x1e,
324 DW_OP_neg = 0x1f,
325 DW_OP_not = 0x20,
326 DW_OP_or = 0x21,
327 DW_OP_plus = 0x22,
328 DW_OP_plus_uconst = 0x23,
329 DW_OP_shl = 0x24,
330 DW_OP_shr = 0x25,
331 DW_OP_shra = 0x26,
332 DW_OP_xor = 0x27,
333 DW_OP_bra = 0x28,
334 DW_OP_eq = 0x29,
335 DW_OP_ge = 0x2a,
336 DW_OP_gt = 0x2b,
337 DW_OP_le = 0x2c,
338 DW_OP_lt = 0x2d,
339 DW_OP_ne = 0x2e,
340 DW_OP_skip = 0x2f,
341 DW_OP_lit0 = 0x30,
342 DW_OP_lit1 = 0x31,
343 DW_OP_lit2 = 0x32,
344 DW_OP_lit3 = 0x33,
345 DW_OP_lit4 = 0x34,
346 DW_OP_lit5 = 0x35,
347 DW_OP_lit6 = 0x36,
348 DW_OP_lit7 = 0x37,
349 DW_OP_lit8 = 0x38,
350 DW_OP_lit9 = 0x39,
351 DW_OP_lit10 = 0x3a,
352 DW_OP_lit11 = 0x3b,
353 DW_OP_lit12 = 0x3c,
354 DW_OP_lit13 = 0x3d,
355 DW_OP_lit14 = 0x3e,
356 DW_OP_lit15 = 0x3f,
357 DW_OP_lit16 = 0x40,
358 DW_OP_lit17 = 0x41,
359 DW_OP_lit18 = 0x42,
360 DW_OP_lit19 = 0x43,
361 DW_OP_lit20 = 0x44,
362 DW_OP_lit21 = 0x45,
363 DW_OP_lit22 = 0x46,
364 DW_OP_lit23 = 0x47,
365 DW_OP_lit24 = 0x48,
366 DW_OP_lit25 = 0x49,
367 DW_OP_lit26 = 0x4a,
368 DW_OP_lit27 = 0x4b,
369 DW_OP_lit28 = 0x4c,
370 DW_OP_lit29 = 0x4d,
371 DW_OP_lit30 = 0x4e,
372 DW_OP_lit31 = 0x4f,
373 DW_OP_reg0 = 0x50,
374 DW_OP_reg1 = 0x51,
375 DW_OP_reg2 = 0x52,
376 DW_OP_reg3 = 0x53,
377 DW_OP_reg4 = 0x54,
378 DW_OP_reg5 = 0x55,
379 DW_OP_reg6 = 0x56,
380 DW_OP_reg7 = 0x57,
381 DW_OP_reg8 = 0x58,
382 DW_OP_reg9 = 0x59,
383 DW_OP_reg10 = 0x5a,
384 DW_OP_reg11 = 0x5b,
385 DW_OP_reg12 = 0x5c,
386 DW_OP_reg13 = 0x5d,
387 DW_OP_reg14 = 0x5e,
388 DW_OP_reg15 = 0x5f,
389 DW_OP_reg16 = 0x60,
390 DW_OP_reg17 = 0x61,
391 DW_OP_reg18 = 0x62,
392 DW_OP_reg19 = 0x63,
393 DW_OP_reg20 = 0x64,
394 DW_OP_reg21 = 0x65,
395 DW_OP_reg22 = 0x66,
396 DW_OP_reg23 = 0x67,
397 DW_OP_reg24 = 0x68,
398 DW_OP_reg25 = 0x69,
399 DW_OP_reg26 = 0x6a,
400 DW_OP_reg27 = 0x6b,
401 DW_OP_reg28 = 0x6c,
402 DW_OP_reg29 = 0x6d,
403 DW_OP_reg30 = 0x6e,
404 DW_OP_reg31 = 0x6f,
405 DW_OP_breg0 = 0x70,
406 DW_OP_breg1 = 0x71,
407 DW_OP_breg2 = 0x72,
408 DW_OP_breg3 = 0x73,
409 DW_OP_breg4 = 0x74,
410 DW_OP_breg5 = 0x75,
411 DW_OP_breg6 = 0x76,
412 DW_OP_breg7 = 0x77,
413 DW_OP_breg8 = 0x78,
414 DW_OP_breg9 = 0x79,
415 DW_OP_breg10 = 0x7a,
416 DW_OP_breg11 = 0x7b,
417 DW_OP_breg12 = 0x7c,
418 DW_OP_breg13 = 0x7d,
419 DW_OP_breg14 = 0x7e,
420 DW_OP_breg15 = 0x7f,
421 DW_OP_breg16 = 0x80,
422 DW_OP_breg17 = 0x81,
423 DW_OP_breg18 = 0x82,
424 DW_OP_breg19 = 0x83,
425 DW_OP_breg20 = 0x84,
426 DW_OP_breg21 = 0x85,
427 DW_OP_breg22 = 0x86,
428 DW_OP_breg23 = 0x87,
429 DW_OP_breg24 = 0x88,
430 DW_OP_breg25 = 0x89,
431 DW_OP_breg26 = 0x8a,
432 DW_OP_breg27 = 0x8b,
433 DW_OP_breg28 = 0x8c,
434 DW_OP_breg29 = 0x8d,
435 DW_OP_breg30 = 0x8e,
436 DW_OP_breg31 = 0x8f,
437 DW_OP_regx = 0x90,
438 DW_OP_fbreg = 0x91,
439 DW_OP_bregx = 0x92,
440 DW_OP_piece = 0x93,
441 DW_OP_deref_size = 0x94,
442 DW_OP_xderef_size = 0x95,
443 DW_OP_nop = 0x96,
444 DW_OP_push_object_address = 0x97,
445 DW_OP_call2 = 0x98,
446 DW_OP_call4 = 0x99,
447 DW_OP_call_ref = 0x9a,
448 DW_OP_form_tls_address = 0x9b,
449 DW_OP_call_frame_cfa = 0x9c,
450 DW_OP_bit_piece = 0x9d,
451 DW_OP_lo_user = 0xe0,
452 DW_OP_hi_user = 0xff,
453 DW_OP_GNU_push_tls_address = 0xe0,
454 DW_OP_GNU_uninit = 0xf0,
455 DW_OP_GNU_encoded_addr = 0xf1,
458 #define DW_EH_PE_native 0x00
459 #define DW_EH_PE_leb128 0x01
460 #define DW_EH_PE_data2 0x02
461 #define DW_EH_PE_data4 0x03
462 #define DW_EH_PE_data8 0x04
463 #define DW_EH_PE_signed 0x08
464 #define DW_EH_PE_abs 0x00
465 #define DW_EH_PE_pcrel 0x10
466 #define DW_EH_PE_textrel 0x20
467 #define DW_EH_PE_datarel 0x30
468 #define DW_EH_PE_funcrel 0x40
469 #define DW_EH_PE_aligned 0x50
470 #define DW_EH_PE_indirect 0x80
471 #define DW_EH_PE_omit 0xff
473 struct dwarf_eh_bases
475 void *tbase;
476 void *dbase;
477 void *func;
480 struct dwarf_cie
482 unsigned int length;
483 int id;
484 unsigned char version;
485 unsigned char augmentation[1];
488 struct dwarf_fde
490 unsigned int length;
491 unsigned int cie_offset;
494 extern const struct dwarf_fde *_Unwind_Find_FDE (void *, struct dwarf_eh_bases *);
496 static unsigned char dwarf_get_u1( const unsigned char **p )
498 return *(*p)++;
501 static unsigned short dwarf_get_u2( const unsigned char **p )
503 unsigned int ret = (*p)[0] | ((*p)[1] << 8);
504 (*p) += 2;
505 return ret;
508 static unsigned int dwarf_get_u4( const unsigned char **p )
510 unsigned int ret = (*p)[0] | ((*p)[1] << 8) | ((*p)[2] << 16) | ((*p)[3] << 24);
511 (*p) += 4;
512 return ret;
515 static ULONG64 dwarf_get_u8( const unsigned char **p )
517 ULONG64 low = dwarf_get_u4( p );
518 ULONG64 high = dwarf_get_u4( p );
519 return low | (high << 32);
522 static ULONG_PTR dwarf_get_uleb128( const unsigned char **p )
524 ULONG_PTR ret = 0;
525 unsigned int shift = 0;
526 unsigned char byte;
530 byte = **p;
531 ret |= (ULONG_PTR)(byte & 0x7f) << shift;
532 shift += 7;
533 (*p)++;
534 } while (byte & 0x80);
535 return ret;
538 static LONG_PTR dwarf_get_sleb128( const unsigned char **p )
540 ULONG_PTR ret = 0;
541 unsigned int shift = 0;
542 unsigned char byte;
546 byte = **p;
547 ret |= (ULONG_PTR)(byte & 0x7f) << shift;
548 shift += 7;
549 (*p)++;
550 } while (byte & 0x80);
552 if ((shift < 8 * sizeof(ret)) && (byte & 0x40)) ret |= -((ULONG_PTR)1 << shift);
553 return ret;
556 static ULONG_PTR dwarf_get_ptr( const unsigned char **p, unsigned char encoding )
558 ULONG_PTR base;
560 if (encoding == DW_EH_PE_omit) return 0;
562 switch (encoding & 0xf0)
564 case DW_EH_PE_abs:
565 base = 0;
566 break;
567 case DW_EH_PE_pcrel:
568 base = (ULONG_PTR)*p;
569 break;
570 default:
571 FIXME( "unsupported encoding %02x\n", encoding );
572 return 0;
575 switch (encoding & 0x0f)
577 case DW_EH_PE_native:
578 return base + dwarf_get_u8( p );
579 case DW_EH_PE_leb128:
580 return base + dwarf_get_uleb128( p );
581 case DW_EH_PE_data2:
582 return base + dwarf_get_u2( p );
583 case DW_EH_PE_data4:
584 return base + dwarf_get_u4( p );
585 case DW_EH_PE_data8:
586 return base + dwarf_get_u8( p );
587 case DW_EH_PE_signed|DW_EH_PE_leb128:
588 return base + dwarf_get_sleb128( p );
589 case DW_EH_PE_signed|DW_EH_PE_data2:
590 return base + (signed short)dwarf_get_u2( p );
591 case DW_EH_PE_signed|DW_EH_PE_data4:
592 return base + (signed int)dwarf_get_u4( p );
593 case DW_EH_PE_signed|DW_EH_PE_data8:
594 return base + (LONG64)dwarf_get_u8( p );
595 default:
596 FIXME( "unsupported encoding %02x\n", encoding );
597 return 0;
601 enum reg_rule
603 RULE_UNSET, /* not set at all */
604 RULE_UNDEFINED, /* undefined value */
605 RULE_SAME, /* same value as previous frame */
606 RULE_CFA_OFFSET, /* stored at cfa offset */
607 RULE_OTHER_REG, /* stored in other register */
608 RULE_EXPRESSION, /* address specified by expression */
609 RULE_VAL_EXPRESSION /* value specified by expression */
612 #define NB_FRAME_REGS 41
613 #define MAX_SAVED_STATES 16
615 struct frame_state
617 ULONG_PTR cfa_offset;
618 unsigned char cfa_reg;
619 enum reg_rule cfa_rule;
620 enum reg_rule rules[NB_FRAME_REGS];
621 ULONG64 regs[NB_FRAME_REGS];
624 struct frame_info
626 ULONG_PTR ip;
627 ULONG_PTR code_align;
628 LONG_PTR data_align;
629 unsigned char retaddr_reg;
630 unsigned char fde_encoding;
631 unsigned char signal_frame;
632 unsigned char state_sp;
633 struct frame_state state;
634 struct frame_state *state_stack;
637 static const char *dwarf_reg_names[NB_FRAME_REGS] =
639 /* 0-7 */ "%rax", "%rdx", "%rcx", "%rbx", "%rsi", "%rdi", "%rbp", "%rsp",
640 /* 8-16 */ "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", "%rip",
641 /* 17-24 */ "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7",
642 /* 25-32 */ "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", "%xmm15",
643 /* 33-40 */ "%st0", "%st1", "%st2", "%st3", "%st4", "%st5", "%st6", "%st7"
646 static BOOL valid_reg( ULONG_PTR reg )
648 if (reg >= NB_FRAME_REGS) FIXME( "unsupported reg %lx\n", reg );
649 return (reg < NB_FRAME_REGS);
652 static void execute_cfa_instructions( const unsigned char *ptr, const unsigned char *end,
653 ULONG_PTR last_ip, struct frame_info *info )
655 while (ptr < end && info->ip < last_ip + info->signal_frame)
657 enum dwarf_call_frame_info op = *ptr++;
659 if (op & 0xc0)
661 switch (op & 0xc0)
663 case DW_CFA_advance_loc:
665 ULONG_PTR offset = (op & 0x3f) * info->code_align;
666 TRACE( "%lx: DW_CFA_advance_loc %lu\n", info->ip, offset );
667 info->ip += offset;
668 break;
670 case DW_CFA_offset:
672 ULONG_PTR reg = op & 0x3f;
673 LONG_PTR offset = dwarf_get_uleb128( &ptr ) * info->data_align;
674 if (!valid_reg( reg )) break;
675 TRACE( "%lx: DW_CFA_offset %s, %ld\n", info->ip, dwarf_reg_names[reg], offset );
676 info->state.regs[reg] = offset;
677 info->state.rules[reg] = RULE_CFA_OFFSET;
678 break;
680 case DW_CFA_restore:
682 ULONG_PTR reg = op & 0x3f;
683 if (!valid_reg( reg )) break;
684 TRACE( "%lx: DW_CFA_restore %s\n", info->ip, dwarf_reg_names[reg] );
685 info->state.rules[reg] = RULE_UNSET;
686 break;
690 else switch (op)
692 case DW_CFA_nop:
693 break;
694 case DW_CFA_set_loc:
696 ULONG_PTR loc = dwarf_get_ptr( &ptr, info->fde_encoding );
697 TRACE( "%lx: DW_CFA_set_loc %lx\n", info->ip, loc );
698 info->ip = loc;
699 break;
701 case DW_CFA_advance_loc1:
703 ULONG_PTR offset = *ptr++ * info->code_align;
704 TRACE( "%lx: DW_CFA_advance_loc1 %lu\n", info->ip, offset );
705 info->ip += offset;
706 break;
708 case DW_CFA_advance_loc2:
710 ULONG_PTR offset = dwarf_get_u2( &ptr ) * info->code_align;
711 TRACE( "%lx: DW_CFA_advance_loc2 %lu\n", info->ip, offset );
712 info->ip += offset;
713 break;
715 case DW_CFA_advance_loc4:
717 ULONG_PTR offset = dwarf_get_u4( &ptr ) * info->code_align;
718 TRACE( "%lx: DW_CFA_advance_loc4 %lu\n", info->ip, offset );
719 info->ip += offset;
720 break;
722 case DW_CFA_offset_extended:
723 case DW_CFA_offset_extended_sf:
725 ULONG_PTR reg = dwarf_get_uleb128( &ptr );
726 LONG_PTR offset = (op == DW_CFA_offset_extended) ? dwarf_get_uleb128( &ptr ) * info->data_align
727 : dwarf_get_sleb128( &ptr ) * info->data_align;
728 if (!valid_reg( reg )) break;
729 TRACE( "%lx: DW_CFA_offset_extended %s, %ld\n", info->ip, dwarf_reg_names[reg], offset );
730 info->state.regs[reg] = offset;
731 info->state.rules[reg] = RULE_CFA_OFFSET;
732 break;
734 case DW_CFA_restore_extended:
736 ULONG_PTR reg = dwarf_get_uleb128( &ptr );
737 if (!valid_reg( reg )) break;
738 TRACE( "%lx: DW_CFA_restore_extended %s\n", info->ip, dwarf_reg_names[reg] );
739 info->state.rules[reg] = RULE_UNSET;
740 break;
742 case DW_CFA_undefined:
744 ULONG_PTR reg = dwarf_get_uleb128( &ptr );
745 if (!valid_reg( reg )) break;
746 TRACE( "%lx: DW_CFA_undefined %s\n", info->ip, dwarf_reg_names[reg] );
747 info->state.rules[reg] = RULE_UNDEFINED;
748 break;
750 case DW_CFA_same_value:
752 ULONG_PTR reg = dwarf_get_uleb128( &ptr );
753 if (!valid_reg( reg )) break;
754 TRACE( "%lx: DW_CFA_same_value %s\n", info->ip, dwarf_reg_names[reg] );
755 info->state.regs[reg] = reg;
756 info->state.rules[reg] = RULE_SAME;
757 break;
759 case DW_CFA_register:
761 ULONG_PTR reg = dwarf_get_uleb128( &ptr );
762 ULONG_PTR reg2 = dwarf_get_uleb128( &ptr );
763 if (!valid_reg( reg ) || !valid_reg( reg2 )) break;
764 TRACE( "%lx: DW_CFA_register %s == %s\n", info->ip, dwarf_reg_names[reg], dwarf_reg_names[reg2] );
765 info->state.regs[reg] = reg2;
766 info->state.rules[reg] = RULE_OTHER_REG;
767 break;
769 case DW_CFA_remember_state:
770 TRACE( "%lx: DW_CFA_remember_state\n", info->ip );
771 if (info->state_sp >= MAX_SAVED_STATES)
772 FIXME( "%lx: DW_CFA_remember_state too many nested saves\n", info->ip );
773 else
774 info->state_stack[info->state_sp++] = info->state;
775 break;
776 case DW_CFA_restore_state:
777 TRACE( "%lx: DW_CFA_restore_state\n", info->ip );
778 if (!info->state_sp)
779 FIXME( "%lx: DW_CFA_restore_state without corresponding save\n", info->ip );
780 else
781 info->state = info->state_stack[--info->state_sp];
782 break;
783 case DW_CFA_def_cfa:
784 case DW_CFA_def_cfa_sf:
786 ULONG_PTR reg = dwarf_get_uleb128( &ptr );
787 ULONG_PTR offset = (op == DW_CFA_def_cfa) ? dwarf_get_uleb128( &ptr )
788 : dwarf_get_sleb128( &ptr ) * info->data_align;
789 if (!valid_reg( reg )) break;
790 TRACE( "%lx: DW_CFA_def_cfa %s, %lu\n", info->ip, dwarf_reg_names[reg], offset );
791 info->state.cfa_reg = reg;
792 info->state.cfa_offset = offset;
793 info->state.cfa_rule = RULE_CFA_OFFSET;
794 break;
796 case DW_CFA_def_cfa_register:
798 ULONG_PTR reg = dwarf_get_uleb128( &ptr );
799 if (!valid_reg( reg )) break;
800 TRACE( "%lx: DW_CFA_def_cfa_register %s\n", info->ip, dwarf_reg_names[reg] );
801 info->state.cfa_reg = reg;
802 info->state.cfa_rule = RULE_CFA_OFFSET;
803 break;
805 case DW_CFA_def_cfa_offset:
806 case DW_CFA_def_cfa_offset_sf:
808 ULONG_PTR offset = (op == DW_CFA_def_cfa_offset) ? dwarf_get_uleb128( &ptr )
809 : dwarf_get_sleb128( &ptr ) * info->data_align;
810 TRACE( "%lx: DW_CFA_def_cfa_offset %lu\n", info->ip, offset );
811 info->state.cfa_offset = offset;
812 info->state.cfa_rule = RULE_CFA_OFFSET;
813 break;
815 case DW_CFA_def_cfa_expression:
817 ULONG_PTR expr = (ULONG_PTR)ptr;
818 ULONG_PTR len = dwarf_get_uleb128( &ptr );
819 TRACE( "%lx: DW_CFA_def_cfa_expression %lx-%lx\n", info->ip, expr, expr+len );
820 info->state.cfa_offset = expr;
821 info->state.cfa_rule = RULE_VAL_EXPRESSION;
822 ptr += len;
823 break;
825 case DW_CFA_expression:
826 case DW_CFA_val_expression:
828 ULONG_PTR reg = dwarf_get_uleb128( &ptr );
829 ULONG_PTR expr = (ULONG_PTR)ptr;
830 ULONG_PTR len = dwarf_get_uleb128( &ptr );
831 if (!valid_reg( reg )) break;
832 TRACE( "%lx: DW_CFA_%sexpression %s %lx-%lx\n",
833 info->ip, (op == DW_CFA_expression) ? "" : "val_", dwarf_reg_names[reg], expr, expr+len );
834 info->state.regs[reg] = expr;
835 info->state.rules[reg] = (op == DW_CFA_expression) ? RULE_EXPRESSION : RULE_VAL_EXPRESSION;
836 ptr += len;
837 break;
839 default:
840 FIXME( "%lx: unknown CFA opcode %02x\n", info->ip, op );
841 break;
846 /* retrieve a context register from its dwarf number */
847 static void *get_context_reg( CONTEXT *context, ULONG_PTR dw_reg )
849 switch (dw_reg)
851 case 0: return &context->Rax;
852 case 1: return &context->Rdx;
853 case 2: return &context->Rcx;
854 case 3: return &context->Rbx;
855 case 4: return &context->Rsi;
856 case 5: return &context->Rdi;
857 case 6: return &context->Rbp;
858 case 7: return &context->Rsp;
859 case 8: return &context->R8;
860 case 9: return &context->R9;
861 case 10: return &context->R10;
862 case 11: return &context->R11;
863 case 12: return &context->R12;
864 case 13: return &context->R13;
865 case 14: return &context->R14;
866 case 15: return &context->R15;
867 case 16: return &context->Rip;
868 case 17: return &context->u.s.Xmm0;
869 case 18: return &context->u.s.Xmm1;
870 case 19: return &context->u.s.Xmm2;
871 case 20: return &context->u.s.Xmm3;
872 case 21: return &context->u.s.Xmm4;
873 case 22: return &context->u.s.Xmm5;
874 case 23: return &context->u.s.Xmm6;
875 case 24: return &context->u.s.Xmm7;
876 case 25: return &context->u.s.Xmm8;
877 case 26: return &context->u.s.Xmm9;
878 case 27: return &context->u.s.Xmm10;
879 case 28: return &context->u.s.Xmm11;
880 case 29: return &context->u.s.Xmm12;
881 case 30: return &context->u.s.Xmm13;
882 case 31: return &context->u.s.Xmm14;
883 case 32: return &context->u.s.Xmm15;
884 case 33: return &context->u.s.Legacy[0];
885 case 34: return &context->u.s.Legacy[1];
886 case 35: return &context->u.s.Legacy[2];
887 case 36: return &context->u.s.Legacy[3];
888 case 37: return &context->u.s.Legacy[4];
889 case 38: return &context->u.s.Legacy[5];
890 case 39: return &context->u.s.Legacy[6];
891 case 40: return &context->u.s.Legacy[7];
892 default: return NULL;
896 /* set a context register from its dwarf number */
897 static void set_context_reg( CONTEXT *context, ULONG_PTR dw_reg, void *val )
899 switch (dw_reg)
901 case 0: context->Rax = *(ULONG64 *)val; break;
902 case 1: context->Rdx = *(ULONG64 *)val; break;
903 case 2: context->Rcx = *(ULONG64 *)val; break;
904 case 3: context->Rbx = *(ULONG64 *)val; break;
905 case 4: context->Rsi = *(ULONG64 *)val; break;
906 case 5: context->Rdi = *(ULONG64 *)val; break;
907 case 6: context->Rbp = *(ULONG64 *)val; break;
908 case 7: context->Rsp = *(ULONG64 *)val; break;
909 case 8: context->R8 = *(ULONG64 *)val; break;
910 case 9: context->R9 = *(ULONG64 *)val; break;
911 case 10: context->R10 = *(ULONG64 *)val; break;
912 case 11: context->R11 = *(ULONG64 *)val; break;
913 case 12: context->R12 = *(ULONG64 *)val; break;
914 case 13: context->R13 = *(ULONG64 *)val; break;
915 case 14: context->R14 = *(ULONG64 *)val; break;
916 case 15: context->R15 = *(ULONG64 *)val; break;
917 case 16: context->Rip = *(ULONG64 *)val; break;
918 case 17: memcpy( &context->u.s.Xmm0, val, sizeof(M128A) ); break;
919 case 18: memcpy( &context->u.s.Xmm1, val, sizeof(M128A) ); break;
920 case 19: memcpy( &context->u.s.Xmm2, val, sizeof(M128A) ); break;
921 case 20: memcpy( &context->u.s.Xmm3, val, sizeof(M128A) ); break;
922 case 21: memcpy( &context->u.s.Xmm4, val, sizeof(M128A) ); break;
923 case 22: memcpy( &context->u.s.Xmm5, val, sizeof(M128A) ); break;
924 case 23: memcpy( &context->u.s.Xmm6, val, sizeof(M128A) ); break;
925 case 24: memcpy( &context->u.s.Xmm7, val, sizeof(M128A) ); break;
926 case 25: memcpy( &context->u.s.Xmm8, val, sizeof(M128A) ); break;
927 case 26: memcpy( &context->u.s.Xmm9, val, sizeof(M128A) ); break;
928 case 27: memcpy( &context->u.s.Xmm10, val, sizeof(M128A) ); break;
929 case 28: memcpy( &context->u.s.Xmm11, val, sizeof(M128A) ); break;
930 case 29: memcpy( &context->u.s.Xmm12, val, sizeof(M128A) ); break;
931 case 30: memcpy( &context->u.s.Xmm13, val, sizeof(M128A) ); break;
932 case 31: memcpy( &context->u.s.Xmm14, val, sizeof(M128A) ); break;
933 case 32: memcpy( &context->u.s.Xmm15, val, sizeof(M128A) ); break;
934 case 33: memcpy( &context->u.s.Legacy[0], val, sizeof(M128A) ); break;
935 case 34: memcpy( &context->u.s.Legacy[1], val, sizeof(M128A) ); break;
936 case 35: memcpy( &context->u.s.Legacy[2], val, sizeof(M128A) ); break;
937 case 36: memcpy( &context->u.s.Legacy[3], val, sizeof(M128A) ); break;
938 case 37: memcpy( &context->u.s.Legacy[4], val, sizeof(M128A) ); break;
939 case 38: memcpy( &context->u.s.Legacy[5], val, sizeof(M128A) ); break;
940 case 39: memcpy( &context->u.s.Legacy[6], val, sizeof(M128A) ); break;
941 case 40: memcpy( &context->u.s.Legacy[7], val, sizeof(M128A) ); break;
945 static ULONG_PTR eval_expression( const unsigned char *p, CONTEXT *context )
947 ULONG_PTR reg, tmp, stack[64];
948 int sp = -1;
949 ULONG_PTR len = dwarf_get_uleb128(&p);
950 const unsigned char *end = p + len;
952 while (p < end)
954 unsigned char opcode = dwarf_get_u1(&p);
956 if (opcode >= DW_OP_lit0 && opcode <= DW_OP_lit31)
957 stack[++sp] = opcode - DW_OP_lit0;
958 else if (opcode >= DW_OP_reg0 && opcode <= DW_OP_reg31)
959 stack[++sp] = *(ULONG_PTR *)get_context_reg( context, opcode - DW_OP_reg0 );
960 else if (opcode >= DW_OP_breg0 && opcode <= DW_OP_breg31)
961 stack[++sp] = *(ULONG_PTR *)get_context_reg( context, opcode - DW_OP_breg0 ) + dwarf_get_sleb128(&p);
962 else switch (opcode)
964 case DW_OP_nop: break;
965 case DW_OP_addr: stack[++sp] = dwarf_get_u8(&p); break;
966 case DW_OP_const1u: stack[++sp] = dwarf_get_u1(&p); break;
967 case DW_OP_const1s: stack[++sp] = (signed char)dwarf_get_u1(&p); break;
968 case DW_OP_const2u: stack[++sp] = dwarf_get_u2(&p); break;
969 case DW_OP_const2s: stack[++sp] = (short)dwarf_get_u2(&p); break;
970 case DW_OP_const4u: stack[++sp] = dwarf_get_u4(&p); break;
971 case DW_OP_const4s: stack[++sp] = (signed int)dwarf_get_u4(&p); break;
972 case DW_OP_const8u: stack[++sp] = dwarf_get_u8(&p); break;
973 case DW_OP_const8s: stack[++sp] = (LONG_PTR)dwarf_get_u8(&p); break;
974 case DW_OP_constu: stack[++sp] = dwarf_get_uleb128(&p); break;
975 case DW_OP_consts: stack[++sp] = dwarf_get_sleb128(&p); break;
976 case DW_OP_deref: stack[sp] = *(ULONG_PTR *)stack[sp]; break;
977 case DW_OP_dup: stack[sp + 1] = stack[sp]; sp++; break;
978 case DW_OP_drop: sp--; break;
979 case DW_OP_over: stack[sp + 1] = stack[sp - 1]; sp++; break;
980 case DW_OP_pick: stack[sp + 1] = stack[sp - dwarf_get_u1(&p)]; sp++; break;
981 case DW_OP_swap: tmp = stack[sp]; stack[sp] = stack[sp-1]; stack[sp-1] = tmp; break;
982 case DW_OP_rot: tmp = stack[sp]; stack[sp] = stack[sp-1]; stack[sp-1] = stack[sp-2]; stack[sp-2] = tmp; break;
983 case DW_OP_abs: stack[sp] = labs(stack[sp]); break;
984 case DW_OP_neg: stack[sp] = -stack[sp]; break;
985 case DW_OP_not: stack[sp] = ~stack[sp]; break;
986 case DW_OP_and: stack[sp-1] &= stack[sp]; sp--; break;
987 case DW_OP_or: stack[sp-1] |= stack[sp]; sp--; break;
988 case DW_OP_minus: stack[sp-1] -= stack[sp]; sp--; break;
989 case DW_OP_mul: stack[sp-1] *= stack[sp]; sp--; break;
990 case DW_OP_plus: stack[sp-1] += stack[sp]; sp--; break;
991 case DW_OP_xor: stack[sp-1] ^= stack[sp]; sp--; break;
992 case DW_OP_shl: stack[sp-1] <<= stack[sp]; sp--; break;
993 case DW_OP_shr: stack[sp-1] >>= stack[sp]; sp--; break;
994 case DW_OP_plus_uconst: stack[sp] += dwarf_get_uleb128(&p); break;
995 case DW_OP_shra: stack[sp-1] = (LONG_PTR)stack[sp-1] / (1 << stack[sp]); sp--; break;
996 case DW_OP_div: stack[sp-1] = (LONG_PTR)stack[sp-1] / (LONG_PTR)stack[sp]; sp--; break;
997 case DW_OP_mod: stack[sp-1] = (LONG_PTR)stack[sp-1] % (LONG_PTR)stack[sp]; sp--; break;
998 case DW_OP_ge: stack[sp-1] = ((LONG_PTR)stack[sp-1] >= (LONG_PTR)stack[sp]); sp--; break;
999 case DW_OP_gt: stack[sp-1] = ((LONG_PTR)stack[sp-1] > (LONG_PTR)stack[sp]); sp--; break;
1000 case DW_OP_le: stack[sp-1] = ((LONG_PTR)stack[sp-1] <= (LONG_PTR)stack[sp]); sp--; break;
1001 case DW_OP_lt: stack[sp-1] = ((LONG_PTR)stack[sp-1] < (LONG_PTR)stack[sp]); sp--; break;
1002 case DW_OP_eq: stack[sp-1] = (stack[sp-1] == stack[sp]); sp--; break;
1003 case DW_OP_ne: stack[sp-1] = (stack[sp-1] != stack[sp]); sp--; break;
1004 case DW_OP_skip: tmp = (short)dwarf_get_u2(&p); p += tmp; break;
1005 case DW_OP_bra: tmp = (short)dwarf_get_u2(&p); if (!stack[sp--]) p += tmp; break;
1006 case DW_OP_GNU_encoded_addr: tmp = *p++; stack[++sp] = dwarf_get_ptr( &p, tmp ); break;
1007 case DW_OP_regx: stack[++sp] = *(ULONG_PTR *)get_context_reg( context, dwarf_get_uleb128(&p) ); break;
1008 case DW_OP_bregx:
1009 reg = dwarf_get_uleb128(&p);
1010 tmp = dwarf_get_sleb128(&p);
1011 stack[++sp] = *(ULONG_PTR *)get_context_reg( context, reg ) + tmp;
1012 break;
1013 case DW_OP_deref_size:
1014 switch (*p++)
1016 case 1: stack[sp] = *(unsigned char *)stack[sp]; break;
1017 case 2: stack[sp] = *(unsigned short *)stack[sp]; break;
1018 case 4: stack[sp] = *(unsigned int *)stack[sp]; break;
1019 case 8: stack[sp] = *(ULONG_PTR *)stack[sp]; break;
1021 break;
1022 default:
1023 FIXME( "unhandled opcode %02x\n", opcode );
1026 return stack[sp];
1029 /* apply the computed frame info to the actual context */
1030 static void apply_frame_state( CONTEXT *context, struct frame_state *state )
1032 unsigned int i;
1033 ULONG_PTR cfa, value;
1034 CONTEXT new_context = *context;
1036 switch (state->cfa_rule)
1038 case RULE_EXPRESSION:
1039 cfa = *(ULONG_PTR *)eval_expression( (const unsigned char *)state->cfa_offset, context );
1040 break;
1041 case RULE_VAL_EXPRESSION:
1042 cfa = eval_expression( (const unsigned char *)state->cfa_offset, context );
1043 break;
1044 default:
1045 cfa = *(ULONG_PTR *)get_context_reg( context, state->cfa_reg ) + state->cfa_offset;
1046 break;
1048 if (!cfa) return;
1050 for (i = 0; i < NB_FRAME_REGS; i++)
1052 switch (state->rules[i])
1054 case RULE_UNSET:
1055 case RULE_UNDEFINED:
1056 case RULE_SAME:
1057 break;
1058 case RULE_CFA_OFFSET:
1059 set_context_reg( &new_context, i, (char *)cfa + state->regs[i] );
1060 break;
1061 case RULE_OTHER_REG:
1062 set_context_reg( &new_context, i, get_context_reg( context, state->regs[i] ));
1063 break;
1064 case RULE_EXPRESSION:
1065 value = eval_expression( (const unsigned char *)state->regs[i], context );
1066 set_context_reg( &new_context, i, (void *)value );
1067 break;
1068 case RULE_VAL_EXPRESSION:
1069 value = eval_expression( (const unsigned char *)state->regs[i], context );
1070 set_context_reg( &new_context, i, &value );
1071 break;
1074 new_context.Rsp = cfa;
1075 *context = new_context;
1079 /***********************************************************************
1080 * dwarf_virtual_unwind
1082 * Equivalent of RtlVirtualUnwind for builtin modules.
1084 static NTSTATUS dwarf_virtual_unwind( ULONG64 ip, ULONG64 *frame,CONTEXT *context,
1085 const struct dwarf_fde *fde, const struct dwarf_eh_bases *bases,
1086 PEXCEPTION_ROUTINE *handler, void **handler_data )
1088 const struct dwarf_cie *cie;
1089 const unsigned char *ptr, *augmentation, *end;
1090 ULONG_PTR len, code_end;
1091 struct frame_info info;
1092 struct frame_state state_stack[MAX_SAVED_STATES];
1093 int aug_z_format = 0;
1094 unsigned char lsda_encoding = DW_EH_PE_omit;
1096 memset( &info, 0, sizeof(info) );
1097 info.state_stack = state_stack;
1098 info.ip = (ULONG_PTR)bases->func;
1099 *handler = NULL;
1101 cie = (const struct dwarf_cie *)((const char *)&fde->cie_offset - fde->cie_offset);
1103 /* parse the CIE first */
1105 if (cie->version != 1 && cie->version != 3)
1107 FIXME( "unknown CIE version %u at %p\n", cie->version, cie );
1108 return STATUS_INVALID_DISPOSITION;
1110 ptr = cie->augmentation + strlen((const char *)cie->augmentation) + 1;
1112 info.code_align = dwarf_get_uleb128( &ptr );
1113 info.data_align = dwarf_get_sleb128( &ptr );
1114 if (cie->version == 1)
1115 info.retaddr_reg = *ptr++;
1116 else
1117 info.retaddr_reg = dwarf_get_uleb128( &ptr );
1118 info.state.cfa_rule = RULE_CFA_OFFSET;
1120 TRACE( "function %lx base %p cie %p len %x id %x version %x aug '%s' code_align %lu data_align %ld retaddr %s\n",
1121 ip, bases->func, cie, cie->length, cie->id, cie->version, cie->augmentation,
1122 info.code_align, info.data_align, dwarf_reg_names[info.retaddr_reg] );
1124 end = NULL;
1125 for (augmentation = cie->augmentation; *augmentation; augmentation++)
1127 switch (*augmentation)
1129 case 'z':
1130 len = dwarf_get_uleb128( &ptr );
1131 end = ptr + len;
1132 aug_z_format = 1;
1133 continue;
1134 case 'L':
1135 lsda_encoding = *ptr++;
1136 continue;
1137 case 'P':
1139 unsigned char encoding = *ptr++;
1140 *handler = (void *)dwarf_get_ptr( &ptr, encoding );
1141 continue;
1143 case 'R':
1144 info.fde_encoding = *ptr++;
1145 continue;
1146 case 'S':
1147 info.signal_frame = 1;
1148 continue;
1150 FIXME( "unknown augmentation '%c'\n", *augmentation );
1151 if (!end) return STATUS_INVALID_DISPOSITION; /* cannot continue */
1152 break;
1154 if (end) ptr = end;
1156 end = (const unsigned char *)(&cie->length + 1) + cie->length;
1157 execute_cfa_instructions( ptr, end, ip, &info );
1159 ptr = (const unsigned char *)(fde + 1);
1160 info.ip = dwarf_get_ptr( &ptr, info.fde_encoding ); /* fde code start */
1161 code_end = info.ip + dwarf_get_ptr( &ptr, info.fde_encoding & 0x0f ); /* fde code length */
1163 if (aug_z_format) /* get length of augmentation data */
1165 len = dwarf_get_uleb128( &ptr );
1166 end = ptr + len;
1168 else end = NULL;
1170 *handler_data = (void *)dwarf_get_ptr( &ptr, lsda_encoding );
1171 if (end) ptr = end;
1173 end = (const unsigned char *)(&fde->length + 1) + fde->length;
1174 TRACE( "fde %p len %x personality %p lsda %p code %lx-%lx\n",
1175 fde, fde->length, *handler, *handler_data, info.ip, code_end );
1176 execute_cfa_instructions( ptr, end, ip, &info );
1177 *frame = context->Rsp;
1178 apply_frame_state( context, &info.state );
1180 TRACE( "next function rip=%016lx\n", context->Rip );
1181 TRACE( " rax=%016lx rbx=%016lx rcx=%016lx rdx=%016lx\n",
1182 context->Rax, context->Rbx, context->Rcx, context->Rdx );
1183 TRACE( " rsi=%016lx rdi=%016lx rbp=%016lx rsp=%016lx\n",
1184 context->Rsi, context->Rdi, context->Rbp, context->Rsp );
1185 TRACE( " r8=%016lx r9=%016lx r10=%016lx r11=%016lx\n",
1186 context->R8, context->R9, context->R10, context->R11 );
1187 TRACE( " r12=%016lx r13=%016lx r14=%016lx r15=%016lx\n",
1188 context->R12, context->R13, context->R14, context->R15 );
1190 return STATUS_SUCCESS;
1194 #ifdef HAVE_LIBUNWIND
1195 /***********************************************************************
1196 * libunwind_virtual_unwind
1198 * Equivalent of RtlVirtualUnwind for builtin modules.
1200 static NTSTATUS libunwind_virtual_unwind( ULONG64 ip, ULONG64 *frame, CONTEXT *context,
1201 PEXCEPTION_ROUTINE *handler, void **handler_data )
1203 unw_context_t unw_context;
1204 unw_cursor_t cursor;
1205 unw_proc_info_t info;
1206 int rc;
1208 #ifdef __APPLE__
1209 rc = unw_getcontext( &unw_context );
1210 if (rc == UNW_ESUCCESS)
1211 rc = unw_init_local( &cursor, &unw_context );
1212 if (rc == UNW_ESUCCESS)
1214 unw_set_reg( &cursor, UNW_REG_IP, context->Rip );
1215 unw_set_reg( &cursor, UNW_REG_SP, context->Rsp );
1216 unw_set_reg( &cursor, UNW_X86_64_RAX, context->Rax );
1217 unw_set_reg( &cursor, UNW_X86_64_RDX, context->Rdx );
1218 unw_set_reg( &cursor, UNW_X86_64_RCX, context->Rcx );
1219 unw_set_reg( &cursor, UNW_X86_64_RBX, context->Rbx );
1220 unw_set_reg( &cursor, UNW_X86_64_RSI, context->Rsi );
1221 unw_set_reg( &cursor, UNW_X86_64_RDI, context->Rdi );
1222 unw_set_reg( &cursor, UNW_X86_64_RBP, context->Rbp );
1223 unw_set_reg( &cursor, UNW_X86_64_R8, context->R8 );
1224 unw_set_reg( &cursor, UNW_X86_64_R9, context->R9 );
1225 unw_set_reg( &cursor, UNW_X86_64_R10, context->R10 );
1226 unw_set_reg( &cursor, UNW_X86_64_R11, context->R11 );
1227 unw_set_reg( &cursor, UNW_X86_64_R12, context->R12 );
1228 unw_set_reg( &cursor, UNW_X86_64_R13, context->R13 );
1229 unw_set_reg( &cursor, UNW_X86_64_R14, context->R14 );
1230 unw_set_reg( &cursor, UNW_X86_64_R15, context->R15 );
1232 #else
1233 RAX_sig(&unw_context) = context->Rax;
1234 RCX_sig(&unw_context) = context->Rcx;
1235 RDX_sig(&unw_context) = context->Rdx;
1236 RBX_sig(&unw_context) = context->Rbx;
1237 RSP_sig(&unw_context) = context->Rsp;
1238 RBP_sig(&unw_context) = context->Rbp;
1239 RSI_sig(&unw_context) = context->Rsi;
1240 RDI_sig(&unw_context) = context->Rdi;
1241 R8_sig(&unw_context) = context->R8;
1242 R9_sig(&unw_context) = context->R9;
1243 R10_sig(&unw_context) = context->R10;
1244 R11_sig(&unw_context) = context->R11;
1245 R12_sig(&unw_context) = context->R12;
1246 R13_sig(&unw_context) = context->R13;
1247 R14_sig(&unw_context) = context->R14;
1248 R15_sig(&unw_context) = context->R15;
1249 RIP_sig(&unw_context) = context->Rip;
1250 CS_sig(&unw_context) = context->SegCs;
1251 FS_sig(&unw_context) = context->SegFs;
1252 GS_sig(&unw_context) = context->SegGs;
1253 EFL_sig(&unw_context) = context->EFlags;
1254 rc = unw_init_local( &cursor, &unw_context );
1255 #endif
1256 if (rc != UNW_ESUCCESS)
1258 WARN( "setup failed: %d\n", rc );
1259 return STATUS_INVALID_DISPOSITION;
1262 *handler = NULL;
1263 *frame = context->Rsp;
1265 rc = unw_get_proc_info(&cursor, &info);
1266 if (rc != UNW_ESUCCESS && rc != UNW_ENOINFO)
1268 WARN( "failed to get info: %d\n", rc );
1269 return STATUS_INVALID_DISPOSITION;
1271 if (rc == UNW_ENOINFO || ip < info.start_ip || ip > info.end_ip || info.end_ip == info.start_ip + 1)
1272 return STATUS_UNSUCCESSFUL;
1274 TRACE( "ip %#lx function %#lx-%#lx personality %#lx lsda %#lx fde %#lx\n",
1275 ip, (unsigned long)info.start_ip, (unsigned long)info.end_ip, (unsigned long)info.handler,
1276 (unsigned long)info.lsda, (unsigned long)info.unwind_info );
1278 if (!(rc = unw_step( &cursor )))
1280 WARN( "last frame\n" );
1281 return STATUS_UNSUCCESSFUL;
1283 if (rc < 0)
1285 WARN( "failed to unwind: %d\n", rc );
1286 return STATUS_INVALID_DISPOSITION;
1289 unw_get_reg( &cursor, UNW_REG_IP, (unw_word_t *)&context->Rip );
1290 unw_get_reg( &cursor, UNW_REG_SP, (unw_word_t *)&context->Rsp );
1291 unw_get_reg( &cursor, UNW_X86_64_RAX, (unw_word_t *)&context->Rax );
1292 unw_get_reg( &cursor, UNW_X86_64_RDX, (unw_word_t *)&context->Rdx );
1293 unw_get_reg( &cursor, UNW_X86_64_RCX, (unw_word_t *)&context->Rcx );
1294 unw_get_reg( &cursor, UNW_X86_64_RBX, (unw_word_t *)&context->Rbx );
1295 unw_get_reg( &cursor, UNW_X86_64_RSI, (unw_word_t *)&context->Rsi );
1296 unw_get_reg( &cursor, UNW_X86_64_RDI, (unw_word_t *)&context->Rdi );
1297 unw_get_reg( &cursor, UNW_X86_64_RBP, (unw_word_t *)&context->Rbp );
1298 unw_get_reg( &cursor, UNW_X86_64_R8, (unw_word_t *)&context->R8 );
1299 unw_get_reg( &cursor, UNW_X86_64_R9, (unw_word_t *)&context->R9 );
1300 unw_get_reg( &cursor, UNW_X86_64_R10, (unw_word_t *)&context->R10 );
1301 unw_get_reg( &cursor, UNW_X86_64_R11, (unw_word_t *)&context->R11 );
1302 unw_get_reg( &cursor, UNW_X86_64_R12, (unw_word_t *)&context->R12 );
1303 unw_get_reg( &cursor, UNW_X86_64_R13, (unw_word_t *)&context->R13 );
1304 unw_get_reg( &cursor, UNW_X86_64_R14, (unw_word_t *)&context->R14 );
1305 unw_get_reg( &cursor, UNW_X86_64_R15, (unw_word_t *)&context->R15 );
1306 *handler = (void*)info.handler;
1307 *handler_data = (void*)info.lsda;
1309 TRACE( "next function rip=%016lx\n", context->Rip );
1310 TRACE( " rax=%016lx rbx=%016lx rcx=%016lx rdx=%016lx\n",
1311 context->Rax, context->Rbx, context->Rcx, context->Rdx );
1312 TRACE( " rsi=%016lx rdi=%016lx rbp=%016lx rsp=%016lx\n",
1313 context->Rsi, context->Rdi, context->Rbp, context->Rsp );
1314 TRACE( " r8=%016lx r9=%016lx r10=%016lx r11=%016lx\n",
1315 context->R8, context->R9, context->R10, context->R11 );
1316 TRACE( " r12=%016lx r13=%016lx r14=%016lx r15=%016lx\n",
1317 context->R12, context->R13, context->R14, context->R15 );
1319 return STATUS_SUCCESS;
1321 #endif
1324 /***********************************************************************
1325 * unwind_builtin_dll
1327 NTSTATUS CDECL unwind_builtin_dll( ULONG type, DISPATCHER_CONTEXT *dispatch, CONTEXT *context )
1329 struct dwarf_eh_bases bases;
1330 const struct dwarf_fde *fde = _Unwind_Find_FDE( (void *)(context->Rip - 1), &bases );
1332 if (fde)
1333 return dwarf_virtual_unwind( context->Rip, &dispatch->EstablisherFrame, context, fde,
1334 &bases, &dispatch->LanguageHandler, &dispatch->HandlerData );
1335 #ifdef HAVE_LIBUNWIND
1336 return libunwind_virtual_unwind( context->Rip, &dispatch->EstablisherFrame, context,
1337 &dispatch->LanguageHandler, &dispatch->HandlerData );
1338 #endif
1339 return STATUS_UNSUCCESSFUL;
1343 static inline void set_sigcontext( const CONTEXT *context, ucontext_t *sigcontext )
1345 RAX_sig(sigcontext) = context->Rax;
1346 RCX_sig(sigcontext) = context->Rcx;
1347 RDX_sig(sigcontext) = context->Rdx;
1348 RBX_sig(sigcontext) = context->Rbx;
1349 RSP_sig(sigcontext) = context->Rsp;
1350 RBP_sig(sigcontext) = context->Rbp;
1351 RSI_sig(sigcontext) = context->Rsi;
1352 RDI_sig(sigcontext) = context->Rdi;
1353 R8_sig(sigcontext) = context->R8;
1354 R9_sig(sigcontext) = context->R9;
1355 R10_sig(sigcontext) = context->R10;
1356 R11_sig(sigcontext) = context->R11;
1357 R12_sig(sigcontext) = context->R12;
1358 R13_sig(sigcontext) = context->R13;
1359 R14_sig(sigcontext) = context->R14;
1360 R15_sig(sigcontext) = context->R15;
1361 RIP_sig(sigcontext) = context->Rip;
1362 CS_sig(sigcontext) = context->SegCs;
1363 FS_sig(sigcontext) = context->SegFs;
1364 GS_sig(sigcontext) = context->SegGs;
1365 EFL_sig(sigcontext) = context->EFlags;
1366 #ifdef DS_sig
1367 DS_sig(sigcontext) = context->SegDs;
1368 #endif
1369 #ifdef ES_sig
1370 ES_sig(sigcontext) = context->SegEs;
1371 #endif
1372 #ifdef SS_sig
1373 SS_sig(sigcontext) = context->SegSs;
1374 #endif
1378 /***********************************************************************
1379 * save_context
1381 * Set the register values from a sigcontext.
1383 static void save_context( CONTEXT *context, const ucontext_t *sigcontext )
1385 context->ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS | CONTEXT_DEBUG_REGISTERS;
1386 context->Rax = RAX_sig(sigcontext);
1387 context->Rcx = RCX_sig(sigcontext);
1388 context->Rdx = RDX_sig(sigcontext);
1389 context->Rbx = RBX_sig(sigcontext);
1390 context->Rsp = RSP_sig(sigcontext);
1391 context->Rbp = RBP_sig(sigcontext);
1392 context->Rsi = RSI_sig(sigcontext);
1393 context->Rdi = RDI_sig(sigcontext);
1394 context->R8 = R8_sig(sigcontext);
1395 context->R9 = R9_sig(sigcontext);
1396 context->R10 = R10_sig(sigcontext);
1397 context->R11 = R11_sig(sigcontext);
1398 context->R12 = R12_sig(sigcontext);
1399 context->R13 = R13_sig(sigcontext);
1400 context->R14 = R14_sig(sigcontext);
1401 context->R15 = R15_sig(sigcontext);
1402 context->Rip = RIP_sig(sigcontext);
1403 context->SegCs = CS_sig(sigcontext);
1404 context->SegFs = FS_sig(sigcontext);
1405 context->SegGs = GS_sig(sigcontext);
1406 context->EFlags = EFL_sig(sigcontext);
1407 #ifdef DS_sig
1408 context->SegDs = DS_sig(sigcontext);
1409 #else
1410 __asm__("movw %%ds,%0" : "=m" (context->SegDs));
1411 #endif
1412 #ifdef ES_sig
1413 context->SegEs = ES_sig(sigcontext);
1414 #else
1415 __asm__("movw %%es,%0" : "=m" (context->SegEs));
1416 #endif
1417 #ifdef SS_sig
1418 context->SegSs = SS_sig(sigcontext);
1419 #else
1420 __asm__("movw %%ss,%0" : "=m" (context->SegSs));
1421 #endif
1422 context->Dr0 = amd64_thread_data()->dr0;
1423 context->Dr1 = amd64_thread_data()->dr1;
1424 context->Dr2 = amd64_thread_data()->dr2;
1425 context->Dr3 = amd64_thread_data()->dr3;
1426 context->Dr6 = amd64_thread_data()->dr6;
1427 context->Dr7 = amd64_thread_data()->dr7;
1428 if (FPU_sig(sigcontext))
1430 context->ContextFlags |= CONTEXT_FLOATING_POINT;
1431 context->u.FltSave = *FPU_sig(sigcontext);
1432 context->MxCsr = context->u.FltSave.MxCsr;
1437 /***********************************************************************
1438 * restore_context
1440 * Build a sigcontext from the register values.
1442 static void restore_context( const CONTEXT *context, ucontext_t *sigcontext )
1444 amd64_thread_data()->dr0 = context->Dr0;
1445 amd64_thread_data()->dr1 = context->Dr1;
1446 amd64_thread_data()->dr2 = context->Dr2;
1447 amd64_thread_data()->dr3 = context->Dr3;
1448 amd64_thread_data()->dr6 = context->Dr6;
1449 amd64_thread_data()->dr7 = context->Dr7;
1450 set_sigcontext( context, sigcontext );
1451 if (FPU_sig(sigcontext)) *FPU_sig(sigcontext) = context->u.FltSave;
1455 /***********************************************************************
1456 * set_full_cpu_context
1458 * Set the new CPU context.
1460 extern void set_full_cpu_context( const CONTEXT *context );
1461 __ASM_GLOBAL_FUNC( set_full_cpu_context,
1462 "subq $40,%rsp\n\t"
1463 __ASM_SEH(".seh_stackalloc 0x40\n\t")
1464 __ASM_SEH(".seh_endprologue\n\t")
1465 __ASM_CFI(".cfi_adjust_cfa_offset 40\n\t")
1466 "ldmxcsr 0x34(%rdi)\n\t" /* context->MxCsr */
1467 "movw 0x38(%rdi),%ax\n\t" /* context->SegCs */
1468 "movq %rax,8(%rsp)\n\t"
1469 "movw 0x42(%rdi),%ax\n\t" /* context->SegSs */
1470 "movq %rax,32(%rsp)\n\t"
1471 "movq 0x44(%rdi),%rax\n\t" /* context->Eflags */
1472 "movq %rax,16(%rsp)\n\t"
1473 "movq 0x80(%rdi),%rcx\n\t" /* context->Rcx */
1474 "movq 0x88(%rdi),%rdx\n\t" /* context->Rdx */
1475 "movq 0x90(%rdi),%rbx\n\t" /* context->Rbx */
1476 "movq 0x98(%rdi),%rax\n\t" /* context->Rsp */
1477 "movq %rax,24(%rsp)\n\t"
1478 "movq 0xa0(%rdi),%rbp\n\t" /* context->Rbp */
1479 "movq 0xa8(%rdi),%rsi\n\t" /* context->Rsi */
1480 "movq 0xb8(%rdi),%r8\n\t" /* context->R8 */
1481 "movq 0xc0(%rdi),%r9\n\t" /* context->R9 */
1482 "movq 0xc8(%rdi),%r10\n\t" /* context->R10 */
1483 "movq 0xd0(%rdi),%r11\n\t" /* context->R11 */
1484 "movq 0xd8(%rdi),%r12\n\t" /* context->R12 */
1485 "movq 0xe0(%rdi),%r13\n\t" /* context->R13 */
1486 "movq 0xe8(%rdi),%r14\n\t" /* context->R14 */
1487 "movq 0xf0(%rdi),%r15\n\t" /* context->R15 */
1488 "movq 0xf8(%rdi),%rax\n\t" /* context->Rip */
1489 "movq %rax,(%rsp)\n\t"
1490 "fxrstor 0x100(%rdi)\n\t" /* context->FtlSave */
1491 "movdqa 0x1a0(%rdi),%xmm0\n\t" /* context->Xmm0 */
1492 "movdqa 0x1b0(%rdi),%xmm1\n\t" /* context->Xmm1 */
1493 "movdqa 0x1c0(%rdi),%xmm2\n\t" /* context->Xmm2 */
1494 "movdqa 0x1d0(%rdi),%xmm3\n\t" /* context->Xmm3 */
1495 "movdqa 0x1e0(%rdi),%xmm4\n\t" /* context->Xmm4 */
1496 "movdqa 0x1f0(%rdi),%xmm5\n\t" /* context->Xmm5 */
1497 "movdqa 0x200(%rdi),%xmm6\n\t" /* context->Xmm6 */
1498 "movdqa 0x210(%rdi),%xmm7\n\t" /* context->Xmm7 */
1499 "movdqa 0x220(%rdi),%xmm8\n\t" /* context->Xmm8 */
1500 "movdqa 0x230(%rdi),%xmm9\n\t" /* context->Xmm9 */
1501 "movdqa 0x240(%rdi),%xmm10\n\t" /* context->Xmm10 */
1502 "movdqa 0x250(%rdi),%xmm11\n\t" /* context->Xmm11 */
1503 "movdqa 0x260(%rdi),%xmm12\n\t" /* context->Xmm12 */
1504 "movdqa 0x270(%rdi),%xmm13\n\t" /* context->Xmm13 */
1505 "movdqa 0x280(%rdi),%xmm14\n\t" /* context->Xmm14 */
1506 "movdqa 0x290(%rdi),%xmm15\n\t" /* context->Xmm15 */
1507 "movq 0x78(%rdi),%rax\n\t" /* context->Rax */
1508 "movq 0xb0(%rdi),%rdi\n\t" /* context->Rdi */
1509 "iretq" );
1512 /***********************************************************************
1513 * get_server_context_flags
1515 * Convert CPU-specific flags to generic server flags
1517 static unsigned int get_server_context_flags( DWORD flags )
1519 unsigned int ret = 0;
1521 flags &= ~CONTEXT_AMD64; /* get rid of CPU id */
1522 if (flags & CONTEXT_CONTROL) ret |= SERVER_CTX_CONTROL;
1523 if (flags & CONTEXT_INTEGER) ret |= SERVER_CTX_INTEGER;
1524 if (flags & CONTEXT_SEGMENTS) ret |= SERVER_CTX_SEGMENTS;
1525 if (flags & CONTEXT_FLOATING_POINT) ret |= SERVER_CTX_FLOATING_POINT;
1526 if (flags & CONTEXT_DEBUG_REGISTERS) ret |= SERVER_CTX_DEBUG_REGISTERS;
1527 return ret;
1531 /***********************************************************************
1532 * copy_context
1534 * Copy a register context according to the flags.
1536 static void copy_context( CONTEXT *to, const CONTEXT *from, DWORD flags )
1538 flags &= ~CONTEXT_AMD64; /* get rid of CPU id */
1539 if (flags & CONTEXT_CONTROL)
1541 to->Rbp = from->Rbp;
1542 to->Rip = from->Rip;
1543 to->Rsp = from->Rsp;
1544 to->SegCs = from->SegCs;
1545 to->SegSs = from->SegSs;
1546 to->EFlags = from->EFlags;
1548 if (flags & CONTEXT_INTEGER)
1550 to->Rax = from->Rax;
1551 to->Rcx = from->Rcx;
1552 to->Rdx = from->Rdx;
1553 to->Rbx = from->Rbx;
1554 to->Rsi = from->Rsi;
1555 to->Rdi = from->Rdi;
1556 to->R8 = from->R8;
1557 to->R9 = from->R9;
1558 to->R10 = from->R10;
1559 to->R11 = from->R11;
1560 to->R12 = from->R12;
1561 to->R13 = from->R13;
1562 to->R14 = from->R14;
1563 to->R15 = from->R15;
1565 if (flags & CONTEXT_SEGMENTS)
1567 to->SegDs = from->SegDs;
1568 to->SegEs = from->SegEs;
1569 to->SegFs = from->SegFs;
1570 to->SegGs = from->SegGs;
1572 if (flags & CONTEXT_FLOATING_POINT)
1574 to->MxCsr = from->MxCsr;
1575 to->u.FltSave = from->u.FltSave;
1577 if (flags & CONTEXT_DEBUG_REGISTERS)
1579 to->Dr0 = from->Dr0;
1580 to->Dr1 = from->Dr1;
1581 to->Dr2 = from->Dr2;
1582 to->Dr3 = from->Dr3;
1583 to->Dr6 = from->Dr6;
1584 to->Dr7 = from->Dr7;
1589 /***********************************************************************
1590 * context_to_server
1592 * Convert a register context to the server format.
1594 NTSTATUS context_to_server( context_t *to, const CONTEXT *from )
1596 DWORD flags = from->ContextFlags & ~CONTEXT_AMD64; /* get rid of CPU id */
1598 memset( to, 0, sizeof(*to) );
1599 to->cpu = CPU_x86_64;
1601 if (flags & CONTEXT_CONTROL)
1603 to->flags |= SERVER_CTX_CONTROL;
1604 to->ctl.x86_64_regs.rbp = from->Rbp;
1605 to->ctl.x86_64_regs.rip = from->Rip;
1606 to->ctl.x86_64_regs.rsp = from->Rsp;
1607 to->ctl.x86_64_regs.cs = from->SegCs;
1608 to->ctl.x86_64_regs.ss = from->SegSs;
1609 to->ctl.x86_64_regs.flags = from->EFlags;
1611 if (flags & CONTEXT_INTEGER)
1613 to->flags |= SERVER_CTX_INTEGER;
1614 to->integer.x86_64_regs.rax = from->Rax;
1615 to->integer.x86_64_regs.rcx = from->Rcx;
1616 to->integer.x86_64_regs.rdx = from->Rdx;
1617 to->integer.x86_64_regs.rbx = from->Rbx;
1618 to->integer.x86_64_regs.rsi = from->Rsi;
1619 to->integer.x86_64_regs.rdi = from->Rdi;
1620 to->integer.x86_64_regs.r8 = from->R8;
1621 to->integer.x86_64_regs.r9 = from->R9;
1622 to->integer.x86_64_regs.r10 = from->R10;
1623 to->integer.x86_64_regs.r11 = from->R11;
1624 to->integer.x86_64_regs.r12 = from->R12;
1625 to->integer.x86_64_regs.r13 = from->R13;
1626 to->integer.x86_64_regs.r14 = from->R14;
1627 to->integer.x86_64_regs.r15 = from->R15;
1629 if (flags & CONTEXT_SEGMENTS)
1631 to->flags |= SERVER_CTX_SEGMENTS;
1632 to->seg.x86_64_regs.ds = from->SegDs;
1633 to->seg.x86_64_regs.es = from->SegEs;
1634 to->seg.x86_64_regs.fs = from->SegFs;
1635 to->seg.x86_64_regs.gs = from->SegGs;
1637 if (flags & CONTEXT_FLOATING_POINT)
1639 to->flags |= SERVER_CTX_FLOATING_POINT;
1640 memcpy( to->fp.x86_64_regs.fpregs, &from->u.FltSave, sizeof(to->fp.x86_64_regs.fpregs) );
1642 if (flags & CONTEXT_DEBUG_REGISTERS)
1644 to->flags |= SERVER_CTX_DEBUG_REGISTERS;
1645 to->debug.x86_64_regs.dr0 = from->Dr0;
1646 to->debug.x86_64_regs.dr1 = from->Dr1;
1647 to->debug.x86_64_regs.dr2 = from->Dr2;
1648 to->debug.x86_64_regs.dr3 = from->Dr3;
1649 to->debug.x86_64_regs.dr6 = from->Dr6;
1650 to->debug.x86_64_regs.dr7 = from->Dr7;
1652 return STATUS_SUCCESS;
1656 /***********************************************************************
1657 * context_from_server
1659 * Convert a register context from the server format.
1661 NTSTATUS context_from_server( CONTEXT *to, const context_t *from )
1663 if (from->cpu != CPU_x86_64) return STATUS_INVALID_PARAMETER;
1665 to->ContextFlags = CONTEXT_AMD64;
1666 if (from->flags & SERVER_CTX_CONTROL)
1668 to->ContextFlags |= CONTEXT_CONTROL;
1669 to->Rbp = from->ctl.x86_64_regs.rbp;
1670 to->Rip = from->ctl.x86_64_regs.rip;
1671 to->Rsp = from->ctl.x86_64_regs.rsp;
1672 to->SegCs = from->ctl.x86_64_regs.cs;
1673 to->SegSs = from->ctl.x86_64_regs.ss;
1674 to->EFlags = from->ctl.x86_64_regs.flags;
1677 if (from->flags & SERVER_CTX_INTEGER)
1679 to->ContextFlags |= CONTEXT_INTEGER;
1680 to->Rax = from->integer.x86_64_regs.rax;
1681 to->Rcx = from->integer.x86_64_regs.rcx;
1682 to->Rdx = from->integer.x86_64_regs.rdx;
1683 to->Rbx = from->integer.x86_64_regs.rbx;
1684 to->Rsi = from->integer.x86_64_regs.rsi;
1685 to->Rdi = from->integer.x86_64_regs.rdi;
1686 to->R8 = from->integer.x86_64_regs.r8;
1687 to->R9 = from->integer.x86_64_regs.r9;
1688 to->R10 = from->integer.x86_64_regs.r10;
1689 to->R11 = from->integer.x86_64_regs.r11;
1690 to->R12 = from->integer.x86_64_regs.r12;
1691 to->R13 = from->integer.x86_64_regs.r13;
1692 to->R14 = from->integer.x86_64_regs.r14;
1693 to->R15 = from->integer.x86_64_regs.r15;
1695 if (from->flags & SERVER_CTX_SEGMENTS)
1697 to->ContextFlags |= CONTEXT_SEGMENTS;
1698 to->SegDs = from->seg.x86_64_regs.ds;
1699 to->SegEs = from->seg.x86_64_regs.es;
1700 to->SegFs = from->seg.x86_64_regs.fs;
1701 to->SegGs = from->seg.x86_64_regs.gs;
1703 if (from->flags & SERVER_CTX_FLOATING_POINT)
1705 to->ContextFlags |= CONTEXT_FLOATING_POINT;
1706 memcpy( &to->u.FltSave, from->fp.x86_64_regs.fpregs, sizeof(from->fp.x86_64_regs.fpregs) );
1707 to->MxCsr = to->u.FltSave.MxCsr;
1709 if (from->flags & SERVER_CTX_DEBUG_REGISTERS)
1711 to->ContextFlags |= CONTEXT_DEBUG_REGISTERS;
1712 to->Dr0 = from->debug.x86_64_regs.dr0;
1713 to->Dr1 = from->debug.x86_64_regs.dr1;
1714 to->Dr2 = from->debug.x86_64_regs.dr2;
1715 to->Dr3 = from->debug.x86_64_regs.dr3;
1716 to->Dr6 = from->debug.x86_64_regs.dr6;
1717 to->Dr7 = from->debug.x86_64_regs.dr7;
1719 return STATUS_SUCCESS;
1723 /***********************************************************************
1724 * NtSetContextThread (NTDLL.@)
1725 * ZwSetContextThread (NTDLL.@)
1727 NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
1729 NTSTATUS ret = STATUS_SUCCESS;
1730 DWORD flags = context->ContextFlags & ~CONTEXT_AMD64;
1731 BOOL self = (handle == GetCurrentThread());
1733 /* debug registers require a server call */
1734 if (self && (flags & CONTEXT_DEBUG_REGISTERS))
1735 self = (amd64_thread_data()->dr0 == context->Dr0 &&
1736 amd64_thread_data()->dr1 == context->Dr1 &&
1737 amd64_thread_data()->dr2 == context->Dr2 &&
1738 amd64_thread_data()->dr3 == context->Dr3 &&
1739 amd64_thread_data()->dr6 == context->Dr6 &&
1740 amd64_thread_data()->dr7 == context->Dr7);
1742 if (!self)
1744 context_t server_context;
1746 context_to_server( &server_context, context );
1747 ret = set_thread_context( handle, &server_context, &self );
1748 if (ret || !self) return ret;
1749 if (flags & CONTEXT_DEBUG_REGISTERS)
1751 amd64_thread_data()->dr0 = context->Dr0;
1752 amd64_thread_data()->dr1 = context->Dr1;
1753 amd64_thread_data()->dr2 = context->Dr2;
1754 amd64_thread_data()->dr3 = context->Dr3;
1755 amd64_thread_data()->dr6 = context->Dr6;
1756 amd64_thread_data()->dr7 = context->Dr7;
1760 if (flags & CONTEXT_FULL)
1762 if (!(flags & CONTEXT_CONTROL))
1763 FIXME( "setting partial context (%x) not supported\n", flags );
1764 else
1765 set_full_cpu_context( context );
1767 return ret;
1771 /***********************************************************************
1772 * NtGetContextThread (NTDLL.@)
1773 * ZwGetContextThread (NTDLL.@)
1775 NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
1777 NTSTATUS ret;
1778 DWORD needed_flags;
1779 BOOL self = (handle == GetCurrentThread());
1781 if (!context) return STATUS_INVALID_PARAMETER;
1783 needed_flags = context->ContextFlags;
1785 /* debug registers require a server call */
1786 if (context->ContextFlags & (CONTEXT_DEBUG_REGISTERS & ~CONTEXT_AMD64)) self = FALSE;
1788 if (!self)
1790 context_t server_context;
1791 unsigned int server_flags = get_server_context_flags( context->ContextFlags );
1793 if ((ret = get_thread_context( handle, &server_context, server_flags, &self ))) return ret;
1794 if ((ret = context_from_server( context, &server_context ))) return ret;
1795 needed_flags &= ~context->ContextFlags;
1798 if (self)
1800 if (needed_flags)
1802 CONTEXT ctx;
1803 RtlCaptureContext( &ctx );
1804 copy_context( context, &ctx, ctx.ContextFlags & needed_flags );
1805 context->ContextFlags |= ctx.ContextFlags & needed_flags;
1807 /* update the cached version of the debug registers */
1808 if (context->ContextFlags & (CONTEXT_DEBUG_REGISTERS & ~CONTEXT_AMD64))
1810 amd64_thread_data()->dr0 = context->Dr0;
1811 amd64_thread_data()->dr1 = context->Dr1;
1812 amd64_thread_data()->dr2 = context->Dr2;
1813 amd64_thread_data()->dr3 = context->Dr3;
1814 amd64_thread_data()->dr6 = context->Dr6;
1815 amd64_thread_data()->dr7 = context->Dr7;
1818 return STATUS_SUCCESS;
1822 extern void CDECL raise_func_trampoline( void *dispatcher );
1824 __ASM_GLOBAL_FUNC( raise_func_trampoline,
1825 "jmpq *%r8\n\t")
1827 /***********************************************************************
1828 * setup_raise_exception
1830 static void setup_raise_exception( ucontext_t *sigcontext, EXCEPTION_RECORD *rec, CONTEXT *context )
1832 void *stack_ptr = (void *)(RSP_sig(sigcontext) & ~15);
1833 struct stack_layout *stack;
1834 NTSTATUS status;
1836 if (rec->ExceptionCode == EXCEPTION_SINGLE_STEP)
1838 /* when single stepping can't tell whether this is a hw bp or a
1839 * single step interrupt. try to avoid as much overhead as possible
1840 * and only do a server call if there is any hw bp enabled. */
1842 if (!(context->EFlags & 0x100) || (context->Dr7 & 0xff))
1844 /* (possible) hardware breakpoint, fetch the debug registers */
1845 DWORD saved_flags = context->ContextFlags;
1846 context->ContextFlags = CONTEXT_DEBUG_REGISTERS;
1847 NtGetContextThread(GetCurrentThread(), context);
1848 context->ContextFlags |= saved_flags; /* restore flags */
1850 context->EFlags &= ~0x100; /* clear single-step flag */
1853 status = send_debug_event( rec, context, TRUE );
1854 if (status == DBG_CONTINUE || status == DBG_EXCEPTION_HANDLED)
1856 restore_context( context, sigcontext );
1857 return;
1860 /* fix up instruction pointer in context for EXCEPTION_BREAKPOINT */
1861 if (rec->ExceptionCode == EXCEPTION_BREAKPOINT) context->Rip--;
1863 stack = virtual_setup_exception( stack_ptr, sizeof(*stack), rec );
1864 stack->rec = *rec;
1865 stack->context = *context;
1866 RIP_sig(sigcontext) = (ULONG_PTR)raise_func_trampoline;
1867 R8_sig(sigcontext) = (ULONG_PTR)pKiUserExceptionDispatcher;
1868 RSP_sig(sigcontext) = (ULONG_PTR)stack;
1869 /* clear single-step, direction, and align check flag */
1870 EFL_sig(sigcontext) &= ~(0x100|0x400|0x40000);
1874 /***********************************************************************
1875 * setup_exception
1877 * Setup a proper stack frame for the raise function, and modify the
1878 * sigcontext so that the return from the signal handler will call
1879 * the raise function.
1881 static void setup_exception( ucontext_t *sigcontext, EXCEPTION_RECORD *rec )
1883 CONTEXT context;
1885 rec->ExceptionAddress = (void *)RIP_sig(sigcontext);
1886 save_context( &context, sigcontext );
1887 setup_raise_exception( sigcontext, rec, &context );
1890 extern void WINAPI user_exception_dispatcher_trampoline( struct stack_layout *stack,
1891 void *pKiUserExceptionDispatcher );
1893 __ASM_GLOBAL_FUNC( user_exception_dispatcher_trampoline,
1894 "movq %rcx,%rsp\n\t"
1895 "movq 0x98(%rsp),%rcx\n\t" /* context->Rsp */
1896 "movq 0xa0(%rsp),%rbp\n\t"
1897 "movq 0xa8(%rsp),%rsi\n\t"
1898 "movq 0xb0(%rsp),%rdi\n\t"
1899 "jmpq *%rdx")
1901 void WINAPI do_call_user_exception_dispatcher( EXCEPTION_RECORD *rec, CONTEXT *context,
1902 NTSTATUS (WINAPI *dispatcher)(EXCEPTION_RECORD*,CONTEXT*),
1903 struct stack_layout *stack )
1905 memmove(&stack->context, context, sizeof(*context));
1906 memcpy(&stack->rec, rec, sizeof(*rec));
1908 if (stack->rec.ExceptionCode == EXCEPTION_BREAKPOINT)
1910 /* fix up instruction pointer in context for EXCEPTION_BREAKPOINT */
1911 stack->context.Rip--;
1914 user_exception_dispatcher_trampoline( stack, dispatcher );
1917 __ASM_GLOBAL_FUNC( call_user_exception_dispatcher,
1918 "movq 0x98(%rdx),%r9\n\t" /* context->Rsp */
1919 "andq $~0xf,%r9\n\t"
1920 "subq $0x630,%r9\n\t" /* sizeof(struct stack_layout) */
1921 "cmpq %rsp,%r9\n\t"
1922 "cmovbq %r9,%rsp\n\t"
1923 "jmp " __ASM_NAME("do_call_user_exception_dispatcher") "\n\t")
1925 /***********************************************************************
1926 * is_privileged_instr
1928 * Check if the fault location is a privileged instruction.
1930 static inline DWORD is_privileged_instr( CONTEXT *context )
1932 BYTE instr[16];
1933 unsigned int i, prefix_count = 0;
1934 unsigned int len = virtual_uninterrupted_read_memory( (BYTE *)context->Rip, instr, sizeof(instr) );
1936 for (i = 0; i < len; i++) switch (instr[i])
1938 /* instruction prefixes */
1939 case 0x2e: /* %cs: */
1940 case 0x36: /* %ss: */
1941 case 0x3e: /* %ds: */
1942 case 0x26: /* %es: */
1943 case 0x40: /* rex */
1944 case 0x41: /* rex */
1945 case 0x42: /* rex */
1946 case 0x43: /* rex */
1947 case 0x44: /* rex */
1948 case 0x45: /* rex */
1949 case 0x46: /* rex */
1950 case 0x47: /* rex */
1951 case 0x48: /* rex */
1952 case 0x49: /* rex */
1953 case 0x4a: /* rex */
1954 case 0x4b: /* rex */
1955 case 0x4c: /* rex */
1956 case 0x4d: /* rex */
1957 case 0x4e: /* rex */
1958 case 0x4f: /* rex */
1959 case 0x64: /* %fs: */
1960 case 0x65: /* %gs: */
1961 case 0x66: /* opcode size */
1962 case 0x67: /* addr size */
1963 case 0xf0: /* lock */
1964 case 0xf2: /* repne */
1965 case 0xf3: /* repe */
1966 if (++prefix_count >= 15) return EXCEPTION_ILLEGAL_INSTRUCTION;
1967 continue;
1969 case 0x0f: /* extended instruction */
1970 if (i == len - 1) return 0;
1971 switch (instr[i + 1])
1973 case 0x06: /* clts */
1974 case 0x08: /* invd */
1975 case 0x09: /* wbinvd */
1976 case 0x20: /* mov crX, reg */
1977 case 0x21: /* mov drX, reg */
1978 case 0x22: /* mov reg, crX */
1979 case 0x23: /* mov reg drX */
1980 return EXCEPTION_PRIV_INSTRUCTION;
1982 return 0;
1983 case 0x6c: /* insb (%dx) */
1984 case 0x6d: /* insl (%dx) */
1985 case 0x6e: /* outsb (%dx) */
1986 case 0x6f: /* outsl (%dx) */
1987 case 0xcd: /* int $xx */
1988 case 0xe4: /* inb al,XX */
1989 case 0xe5: /* in (e)ax,XX */
1990 case 0xe6: /* outb XX,al */
1991 case 0xe7: /* out XX,(e)ax */
1992 case 0xec: /* inb (%dx),%al */
1993 case 0xed: /* inl (%dx),%eax */
1994 case 0xee: /* outb %al,(%dx) */
1995 case 0xef: /* outl %eax,(%dx) */
1996 case 0xf4: /* hlt */
1997 case 0xfa: /* cli */
1998 case 0xfb: /* sti */
1999 return EXCEPTION_PRIV_INSTRUCTION;
2000 default:
2001 return 0;
2003 return 0;
2007 /***********************************************************************
2008 * handle_interrupt
2010 * Handle an interrupt.
2012 static inline BOOL handle_interrupt( ucontext_t *sigcontext, EXCEPTION_RECORD *rec, CONTEXT *context )
2014 switch (ERROR_sig(sigcontext) >> 3)
2016 case 0x2c:
2017 rec->ExceptionCode = STATUS_ASSERTION_FAILURE;
2018 break;
2019 case 0x2d:
2020 switch (context->Rax)
2022 case 1: /* BREAKPOINT_PRINT */
2023 case 3: /* BREAKPOINT_LOAD_SYMBOLS */
2024 case 4: /* BREAKPOINT_UNLOAD_SYMBOLS */
2025 case 5: /* BREAKPOINT_COMMAND_STRING (>= Win2003) */
2026 RIP_sig(sigcontext) += 3;
2027 return TRUE;
2029 context->Rip += 3;
2030 rec->ExceptionCode = EXCEPTION_BREAKPOINT;
2031 rec->ExceptionAddress = (void *)context->Rip;
2032 rec->NumberParameters = 1;
2033 rec->ExceptionInformation[0] = context->Rax;
2034 break;
2035 default:
2036 return FALSE;
2038 setup_raise_exception( sigcontext, rec, context );
2039 return TRUE;
2043 /**********************************************************************
2044 * segv_handler
2046 * Handler for SIGSEGV and related errors.
2048 static void segv_handler( int signal, siginfo_t *siginfo, void *sigcontext )
2050 EXCEPTION_RECORD rec = { 0 };
2051 CONTEXT context;
2052 ucontext_t *ucontext = sigcontext;
2054 rec.ExceptionAddress = (void *)RIP_sig(ucontext);
2055 save_context( &context, sigcontext );
2057 switch(TRAP_sig(ucontext))
2059 case TRAP_x86_OFLOW: /* Overflow exception */
2060 rec.ExceptionCode = EXCEPTION_INT_OVERFLOW;
2061 break;
2062 case TRAP_x86_BOUND: /* Bound range exception */
2063 rec.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED;
2064 break;
2065 case TRAP_x86_PRIVINFLT: /* Invalid opcode exception */
2066 rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
2067 break;
2068 case TRAP_x86_STKFLT: /* Stack fault */
2069 rec.ExceptionCode = EXCEPTION_STACK_OVERFLOW;
2070 break;
2071 case TRAP_x86_SEGNPFLT: /* Segment not present exception */
2072 case TRAP_x86_PROTFLT: /* General protection fault */
2074 WORD err = ERROR_sig(ucontext);
2075 if (!err && (rec.ExceptionCode = is_privileged_instr( &context ))) break;
2076 if ((err & 7) == 2 && handle_interrupt( ucontext, &rec, &context )) return;
2077 rec.ExceptionCode = EXCEPTION_ACCESS_VIOLATION;
2078 rec.NumberParameters = 2;
2079 rec.ExceptionInformation[0] = 0;
2080 rec.ExceptionInformation[1] = 0xffffffffffffffff;
2082 break;
2083 case TRAP_x86_PAGEFLT: /* Page fault */
2084 rec.NumberParameters = 2;
2085 rec.ExceptionInformation[0] = (ERROR_sig(ucontext) >> 1) & 0x09;
2086 rec.ExceptionInformation[1] = (ULONG_PTR)siginfo->si_addr;
2087 rec.ExceptionCode = virtual_handle_fault( siginfo->si_addr, rec.ExceptionInformation[0],
2088 (void *)RSP_sig(ucontext) );
2089 if (!rec.ExceptionCode) return;
2090 break;
2091 case TRAP_x86_ALIGNFLT: /* Alignment check exception */
2092 rec.ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT;
2093 break;
2094 default:
2095 ERR( "Got unexpected trap %ld\n", (ULONG_PTR)TRAP_sig(ucontext) );
2096 /* fall through */
2097 case TRAP_x86_NMI: /* NMI interrupt */
2098 case TRAP_x86_DNA: /* Device not available exception */
2099 case TRAP_x86_DOUBLEFLT: /* Double fault exception */
2100 case TRAP_x86_TSSFLT: /* Invalid TSS exception */
2101 case TRAP_x86_MCHK: /* Machine check exception */
2102 case TRAP_x86_CACHEFLT: /* Cache flush exception */
2103 rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
2104 break;
2106 setup_raise_exception( sigcontext, &rec, &context );
2110 /**********************************************************************
2111 * trap_handler
2113 * Handler for SIGTRAP.
2115 static void trap_handler( int signal, siginfo_t *siginfo, void *sigcontext )
2117 EXCEPTION_RECORD rec = { 0 };
2118 CONTEXT context;
2119 ucontext_t *ucontext = sigcontext;
2121 rec.ExceptionAddress = (void *)RIP_sig(ucontext);
2122 save_context( &context, sigcontext );
2124 switch (siginfo->si_code)
2126 case TRAP_TRACE: /* Single-step exception */
2127 case 4 /* TRAP_HWBKPT */: /* Hardware breakpoint exception */
2128 rec.ExceptionCode = EXCEPTION_SINGLE_STEP;
2129 break;
2130 case TRAP_BRKPT: /* Breakpoint exception */
2131 #ifdef SI_KERNEL
2132 case SI_KERNEL:
2133 #endif
2134 /* Check if this is actually icebp instruction */
2135 if (((unsigned char *)RIP_sig(ucontext))[-1] == 0xF1)
2137 rec.ExceptionCode = EXCEPTION_SINGLE_STEP;
2138 break;
2140 rec.ExceptionAddress = (char *)rec.ExceptionAddress - 1; /* back up over the int3 instruction */
2141 /* fall through */
2142 default:
2143 rec.ExceptionCode = EXCEPTION_BREAKPOINT;
2144 rec.NumberParameters = 1;
2145 rec.ExceptionInformation[0] = 0;
2146 break;
2148 setup_raise_exception( sigcontext, &rec, &context );
2152 /**********************************************************************
2153 * fpe_handler
2155 * Handler for SIGFPE.
2157 static void fpe_handler( int signal, siginfo_t *siginfo, void *sigcontext )
2159 EXCEPTION_RECORD rec = { 0 };
2161 switch (siginfo->si_code)
2163 case FPE_FLTSUB:
2164 rec.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED;
2165 break;
2166 case FPE_INTDIV:
2167 rec.ExceptionCode = EXCEPTION_INT_DIVIDE_BY_ZERO;
2168 break;
2169 case FPE_INTOVF:
2170 rec.ExceptionCode = EXCEPTION_INT_OVERFLOW;
2171 break;
2172 case FPE_FLTDIV:
2173 rec.ExceptionCode = EXCEPTION_FLT_DIVIDE_BY_ZERO;
2174 break;
2175 case FPE_FLTOVF:
2176 rec.ExceptionCode = EXCEPTION_FLT_OVERFLOW;
2177 break;
2178 case FPE_FLTUND:
2179 rec.ExceptionCode = EXCEPTION_FLT_UNDERFLOW;
2180 break;
2181 case FPE_FLTRES:
2182 rec.ExceptionCode = EXCEPTION_FLT_INEXACT_RESULT;
2183 break;
2184 case FPE_FLTINV:
2185 default:
2186 rec.ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION;
2187 break;
2189 setup_exception( sigcontext, &rec );
2193 /**********************************************************************
2194 * int_handler
2196 * Handler for SIGINT.
2198 static void int_handler( int signal, siginfo_t *siginfo, void *sigcontext )
2200 EXCEPTION_RECORD rec = { CONTROL_C_EXIT };
2202 setup_exception( sigcontext, &rec );
2206 /**********************************************************************
2207 * abrt_handler
2209 * Handler for SIGABRT.
2211 static void abrt_handler( int signal, siginfo_t *siginfo, void *sigcontext )
2213 EXCEPTION_RECORD rec = { EXCEPTION_WINE_ASSERTION, EH_NONCONTINUABLE };
2215 setup_exception( sigcontext, &rec );
2219 /**********************************************************************
2220 * quit_handler
2222 * Handler for SIGQUIT.
2224 static void quit_handler( int signal, siginfo_t *siginfo, void *ucontext )
2226 abort_thread(0);
2230 /**********************************************************************
2231 * usr1_handler
2233 * Handler for SIGUSR1, used to signal a thread that it got suspended.
2235 static void usr1_handler( int signal, siginfo_t *siginfo, void *ucontext )
2237 CONTEXT context;
2239 save_context( &context, ucontext );
2240 wait_suspend( &context );
2241 restore_context( &context, ucontext );
2245 /**********************************************************************
2246 * get_thread_ldt_entry
2248 NTSTATUS get_thread_ldt_entry( HANDLE handle, void *data, ULONG len, ULONG *ret_len )
2250 return STATUS_NOT_IMPLEMENTED;
2254 /******************************************************************************
2255 * NtSetLdtEntries (NTDLL.@)
2256 * ZwSetLdtEntries (NTDLL.@)
2258 NTSTATUS WINAPI NtSetLdtEntries( ULONG sel1, LDT_ENTRY entry1, ULONG sel2, LDT_ENTRY entry2 )
2260 return STATUS_NOT_IMPLEMENTED;
2264 /**********************************************************************
2265 * signal_init_threading
2267 void signal_init_threading(void)
2272 /**********************************************************************
2273 * signal_alloc_thread
2275 NTSTATUS signal_alloc_thread( TEB *teb )
2277 return STATUS_SUCCESS;
2281 /**********************************************************************
2282 * signal_free_thread
2284 void signal_free_thread( TEB *teb )
2288 #ifdef __APPLE__
2289 /**********************************************************************
2290 * mac_thread_gsbase
2292 static void *mac_thread_gsbase(void)
2294 struct thread_identifier_info tiinfo;
2295 unsigned int info_count = THREAD_IDENTIFIER_INFO_COUNT;
2296 static int gsbase_offset = -1;
2298 kern_return_t kr = thread_info(mach_thread_self(), THREAD_IDENTIFIER_INFO, (thread_info_t) &tiinfo, &info_count);
2299 if (kr == KERN_SUCCESS) return (void*)tiinfo.thread_handle;
2301 if (gsbase_offset < 0)
2303 /* Search for the array of TLS slots within the pthread data structure.
2304 That's what the macOS pthread implementation uses for gsbase. */
2305 const void* const sentinel1 = (const void*)0x2bffb6b4f11228ae;
2306 const void* const sentinel2 = (const void*)0x0845a7ff6ab76707;
2307 int rc;
2308 pthread_key_t key;
2309 const void** p = (const void**)pthread_self();
2310 int i;
2312 gsbase_offset = 0;
2313 if ((rc = pthread_key_create(&key, NULL))) return NULL;
2315 pthread_setspecific(key, sentinel1);
2317 for (i = key + 1; i < 2000; i++) /* arbitrary limit */
2319 if (p[i] == sentinel1)
2321 pthread_setspecific(key, sentinel2);
2323 if (p[i] == sentinel2)
2325 gsbase_offset = (i - key) * sizeof(*p);
2326 break;
2329 pthread_setspecific(key, sentinel1);
2333 pthread_key_delete(key);
2336 if (gsbase_offset) return (char*)pthread_self() + gsbase_offset;
2337 return NULL;
2339 #endif
2342 /**********************************************************************
2343 * signal_init_thread
2345 void signal_init_thread( TEB *teb )
2347 const WORD fpu_cw = 0x27f;
2349 #if defined __linux__
2350 arch_prctl( ARCH_SET_GS, teb );
2351 #elif defined (__FreeBSD__) || defined (__FreeBSD_kernel__)
2352 amd64_set_gsbase( teb );
2353 #elif defined(__NetBSD__)
2354 sysarch( X86_64_SET_GSBASE, &teb );
2355 #elif defined (__APPLE__)
2356 __asm__ volatile (".byte 0x65\n\tmovq %0,%c1"
2358 : "r" (teb->Tib.Self), "n" (FIELD_OFFSET(TEB, Tib.Self)));
2359 __asm__ volatile (".byte 0x65\n\tmovq %0,%c1"
2361 : "r" (teb->ThreadLocalStoragePointer), "n" (FIELD_OFFSET(TEB, ThreadLocalStoragePointer)));
2363 /* alloc_tls_slot() needs to poke a value to an address relative to each
2364 thread's gsbase. Have each thread record its gsbase pointer into its
2365 TEB so alloc_tls_slot() can find it. */
2366 teb->Reserved5[0] = mac_thread_gsbase();
2367 #else
2368 # error Please define setting %gs for your architecture
2369 #endif
2371 #ifdef __GNUC__
2372 __asm__ volatile ("fninit; fldcw %0" : : "m" (fpu_cw));
2373 #else
2374 FIXME("FPU setup not implemented for this platform.\n");
2375 #endif
2379 /**********************************************************************
2380 * signal_init_process
2382 void signal_init_process(void)
2384 struct sigaction sig_act;
2386 sig_act.sa_mask = server_block_set;
2387 sig_act.sa_flags = SA_SIGINFO | SA_RESTART | SA_ONSTACK;
2389 sig_act.sa_sigaction = int_handler;
2390 if (sigaction( SIGINT, &sig_act, NULL ) == -1) goto error;
2391 sig_act.sa_sigaction = fpe_handler;
2392 if (sigaction( SIGFPE, &sig_act, NULL ) == -1) goto error;
2393 sig_act.sa_sigaction = abrt_handler;
2394 if (sigaction( SIGABRT, &sig_act, NULL ) == -1) goto error;
2395 sig_act.sa_sigaction = quit_handler;
2396 if (sigaction( SIGQUIT, &sig_act, NULL ) == -1) goto error;
2397 sig_act.sa_sigaction = usr1_handler;
2398 if (sigaction( SIGUSR1, &sig_act, NULL ) == -1) goto error;
2399 sig_act.sa_sigaction = trap_handler;
2400 if (sigaction( SIGTRAP, &sig_act, NULL ) == -1) goto error;
2401 sig_act.sa_sigaction = segv_handler;
2402 if (sigaction( SIGSEGV, &sig_act, NULL ) == -1) goto error;
2403 if (sigaction( SIGILL, &sig_act, NULL ) == -1) goto error;
2404 if (sigaction( SIGBUS, &sig_act, NULL ) == -1) goto error;
2405 return;
2407 error:
2408 perror("sigaction");
2409 exit(1);
2413 /***********************************************************************
2414 * init_thread_context
2416 static void init_thread_context( CONTEXT *context, LPTHREAD_START_ROUTINE entry, void *arg, void *relay )
2418 __asm__( "movw %%cs,%0" : "=m" (context->SegCs) );
2419 __asm__( "movw %%ss,%0" : "=m" (context->SegSs) );
2420 context->Rcx = (ULONG_PTR)entry;
2421 context->Rdx = (ULONG_PTR)arg;
2422 context->Rsp = (ULONG_PTR)NtCurrentTeb()->Tib.StackBase - 0x28;
2423 context->Rip = (ULONG_PTR)relay;
2424 context->EFlags = 0x200;
2425 context->u.FltSave.ControlWord = 0x27f;
2426 context->u.FltSave.MxCsr = context->MxCsr = 0x1f80;
2430 /***********************************************************************
2431 * attach_thread
2433 PCONTEXT DECLSPEC_HIDDEN attach_thread( LPTHREAD_START_ROUTINE entry, void *arg,
2434 BOOL suspend, void *relay )
2436 CONTEXT *ctx;
2438 if (suspend)
2440 CONTEXT context = { 0 };
2442 context.ContextFlags = CONTEXT_ALL;
2443 init_thread_context( &context, entry, arg, relay );
2444 wait_suspend( &context );
2445 ctx = (CONTEXT *)((ULONG_PTR)context.Rsp & ~15) - 1;
2446 *ctx = context;
2448 else
2450 ctx = (CONTEXT *)((char *)NtCurrentTeb()->Tib.StackBase - 0x30) - 1;
2451 init_thread_context( ctx, entry, arg, relay );
2453 pthread_sigmask( SIG_UNBLOCK, &server_block_set, NULL );
2454 ctx->ContextFlags = CONTEXT_FULL;
2455 pLdrInitializeThunk( ctx, (void **)&ctx->Rcx, 0, 0 );
2456 return ctx;
2460 /***********************************************************************
2461 * signal_start_thread
2463 __ASM_GLOBAL_FUNC( signal_start_thread,
2464 "subq $56,%rsp\n\t"
2465 __ASM_SEH(".seh_stackalloc 56\n\t")
2466 __ASM_SEH(".seh_endprologue\n\t")
2467 __ASM_CFI(".cfi_adjust_cfa_offset 56\n\t")
2468 "movq %rbp,48(%rsp)\n\t"
2469 __ASM_CFI(".cfi_rel_offset %rbp,48\n\t")
2470 "movq %rbx,40(%rsp)\n\t"
2471 __ASM_CFI(".cfi_rel_offset %rbx,40\n\t")
2472 "movq %r12,32(%rsp)\n\t"
2473 __ASM_CFI(".cfi_rel_offset %r12,32\n\t")
2474 "movq %r13,24(%rsp)\n\t"
2475 __ASM_CFI(".cfi_rel_offset %r13,24\n\t")
2476 "movq %r14,16(%rsp)\n\t"
2477 __ASM_CFI(".cfi_rel_offset %r14,16\n\t")
2478 "movq %r15,8(%rsp)\n\t"
2479 __ASM_CFI(".cfi_rel_offset %r15,8\n\t")
2480 /* store exit frame */
2481 "movq %gs:0x30,%rax\n\t"
2482 "movq %rsp,0x330(%rax)\n\t" /* amd64_thread_data()->exit_frame */
2483 /* switch to thread stack */
2484 "movq 8(%rax),%rax\n\t" /* NtCurrentTeb()->Tib.StackBase */
2485 "leaq -0x1000(%rax),%rsp\n\t"
2486 /* attach dlls */
2487 "call " __ASM_NAME("attach_thread") "\n\t"
2488 "movq %rax,%rbx\n\t"
2489 "leaq -32(%rax),%rsp\n\t"
2490 /* clear the stack */
2491 "andq $~0xfff,%rax\n\t" /* round down to page size */
2492 "movq %rax,%rdi\n\t"
2493 "call " __ASM_NAME("virtual_clear_thread_stack") "\n\t"
2494 /* switch to the initial context */
2495 "movl $1,%edx\n\t"
2496 "movq %rbx,%rcx\n\t"
2497 "call " __ASM_NAME("NtContinue") )
2500 /***********************************************************************
2501 * signal_exit_thread
2503 __ASM_GLOBAL_FUNC( signal_exit_thread,
2504 /* fetch exit frame */
2505 "movq %gs:0x30,%rax\n\t"
2506 "movq 0x330(%rax),%rdx\n\t" /* amd64_thread_data()->exit_frame */
2507 "testq %rdx,%rdx\n\t"
2508 "jnz 1f\n\t"
2509 "jmp *%rsi\n"
2510 /* switch to exit frame stack */
2511 "1:\tmovq $0,0x330(%rax)\n\t"
2512 "movq %rdx,%rsp\n\t"
2513 __ASM_CFI(".cfi_adjust_cfa_offset 56\n\t")
2514 __ASM_CFI(".cfi_rel_offset %rbp,48\n\t")
2515 __ASM_CFI(".cfi_rel_offset %rbx,40\n\t")
2516 __ASM_CFI(".cfi_rel_offset %r12,32\n\t")
2517 __ASM_CFI(".cfi_rel_offset %r13,24\n\t")
2518 __ASM_CFI(".cfi_rel_offset %r14,16\n\t")
2519 __ASM_CFI(".cfi_rel_offset %r15,8\n\t")
2520 "call *%rsi" )
2522 #endif /* __x86_64__ */