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
28 #include "wine/port.h"
36 #include <sys/types.h>
40 #ifdef HAVE_MACHINE_SYSARCH_H
41 # include <machine/sysarch.h>
43 #ifdef HAVE_SYS_PARAM_H
44 # include <sys/param.h>
49 # ifdef HAVE_SYS_SYSCALL_H
50 # include <sys/syscall.h>
53 #ifdef HAVE_SYS_SIGNAL_H
54 # include <sys/signal.h>
56 #ifdef HAVE_SYS_UCONTEXT_H
57 # include <sys/ucontext.h>
60 # define UNW_LOCAL_ONLY
61 # include <libunwind.h>
64 # include <mach/mach.h>
67 #define NONAMELESSUNION
68 #define NONAMELESSSTRUCT
70 #define WIN32_NO_STATUS
73 #include "wine/exception.h"
74 #include "wine/list.h"
76 #include "unix_private.h"
77 #include "wine/debug.h"
79 WINE_DEFAULT_DEBUG_CHANNEL(seh
);
81 /***********************************************************************
82 * signal context platform-specific definitions
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)
202 #error You must define the signal context functions for your platform
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 */
233 EXCEPTION_RECORD rec
;
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 */
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,
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,
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,
328 DW_OP_plus_uconst
= 0x23,
441 DW_OP_deref_size
= 0x94,
442 DW_OP_xderef_size
= 0x95,
444 DW_OP_push_object_address
= 0x97,
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
484 unsigned char version
;
485 unsigned char augmentation
[1];
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
)
501 static unsigned short dwarf_get_u2( const unsigned char **p
)
503 unsigned int ret
= (*p
)[0] | ((*p
)[1] << 8);
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);
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
)
525 unsigned int shift
= 0;
531 ret
|= (ULONG_PTR
)(byte
& 0x7f) << shift
;
534 } while (byte
& 0x80);
538 static LONG_PTR
dwarf_get_sleb128( const unsigned char **p
)
541 unsigned int shift
= 0;
547 ret
|= (ULONG_PTR
)(byte
& 0x7f) << shift
;
550 } while (byte
& 0x80);
552 if ((shift
< 8 * sizeof(ret
)) && (byte
& 0x40)) ret
|= -((ULONG_PTR
)1 << shift
);
556 static ULONG_PTR
dwarf_get_ptr( const unsigned char **p
, unsigned char encoding
)
560 if (encoding
== DW_EH_PE_omit
) return 0;
562 switch (encoding
& 0xf0)
568 base
= (ULONG_PTR
)*p
;
571 FIXME( "unsupported encoding %02x\n", encoding
);
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
);
582 return base
+ dwarf_get_u2( p
);
584 return base
+ dwarf_get_u4( p
);
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
);
596 FIXME( "unsupported encoding %02x\n", encoding
);
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
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
];
627 ULONG_PTR code_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
++;
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
);
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
;
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
;
696 ULONG_PTR loc
= dwarf_get_ptr( &ptr
, info
->fde_encoding
);
697 TRACE( "%lx: DW_CFA_set_loc %lx\n", info
->ip
, loc
);
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
);
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
);
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
);
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
;
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
;
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
;
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
;
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
;
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
);
774 info
->state_stack
[info
->state_sp
++] = info
->state
;
776 case DW_CFA_restore_state
:
777 TRACE( "%lx: DW_CFA_restore_state\n", info
->ip
);
779 FIXME( "%lx: DW_CFA_restore_state without corresponding save\n", info
->ip
);
781 info
->state
= info
->state_stack
[--info
->state_sp
];
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
;
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
;
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
;
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
;
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
;
840 FIXME( "%lx: unknown CFA opcode %02x\n", info
->ip
, op
);
846 /* retrieve a context register from its dwarf number */
847 static void *get_context_reg( CONTEXT
*context
, ULONG_PTR 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
)
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];
949 ULONG_PTR len
= dwarf_get_uleb128(&p
);
950 const unsigned char *end
= p
+ len
;
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
);
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;
1009 reg
= dwarf_get_uleb128(&p
);
1010 tmp
= dwarf_get_sleb128(&p
);
1011 stack
[++sp
] = *(ULONG_PTR
*)get_context_reg( context
, reg
) + tmp
;
1013 case DW_OP_deref_size
:
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;
1023 FIXME( "unhandled opcode %02x\n", opcode
);
1029 /* apply the computed frame info to the actual context */
1030 static void apply_frame_state( CONTEXT
*context
, struct frame_state
*state
)
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
);
1041 case RULE_VAL_EXPRESSION
:
1042 cfa
= eval_expression( (const unsigned char *)state
->cfa_offset
, context
);
1045 cfa
= *(ULONG_PTR
*)get_context_reg( context
, state
->cfa_reg
) + state
->cfa_offset
;
1050 for (i
= 0; i
< NB_FRAME_REGS
; i
++)
1052 switch (state
->rules
[i
])
1055 case RULE_UNDEFINED
:
1058 case RULE_CFA_OFFSET
:
1059 set_context_reg( &new_context
, i
, (char *)cfa
+ state
->regs
[i
] );
1061 case RULE_OTHER_REG
:
1062 set_context_reg( &new_context
, i
, get_context_reg( context
, state
->regs
[i
] ));
1064 case RULE_EXPRESSION
:
1065 value
= eval_expression( (const unsigned char *)state
->regs
[i
], context
);
1066 set_context_reg( &new_context
, i
, (void *)value
);
1068 case RULE_VAL_EXPRESSION
:
1069 value
= eval_expression( (const unsigned char *)state
->regs
[i
], context
);
1070 set_context_reg( &new_context
, i
, &value
);
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
;
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
++;
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
] );
1125 for (augmentation
= cie
->augmentation
; *augmentation
; augmentation
++)
1127 switch (*augmentation
)
1130 len
= dwarf_get_uleb128( &ptr
);
1135 lsda_encoding
= *ptr
++;
1139 unsigned char encoding
= *ptr
++;
1140 *handler
= (void *)dwarf_get_ptr( &ptr
, encoding
);
1144 info
.fde_encoding
= *ptr
++;
1147 info
.signal_frame
= 1;
1150 FIXME( "unknown augmentation '%c'\n", *augmentation
);
1151 if (!end
) return STATUS_INVALID_DISPOSITION
; /* cannot continue */
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
);
1170 *handler_data
= (void *)dwarf_get_ptr( &ptr
, lsda_encoding
);
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
;
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
);
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
);
1256 if (rc
!= UNW_ESUCCESS
)
1258 WARN( "setup failed: %d\n", rc
);
1259 return STATUS_INVALID_DISPOSITION
;
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
;
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
;
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
);
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
);
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
;
1367 DS_sig(sigcontext
) = context
->SegDs
;
1370 ES_sig(sigcontext
) = context
->SegEs
;
1373 SS_sig(sigcontext
) = context
->SegSs
;
1378 /***********************************************************************
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
);
1408 context
->SegDs
= DS_sig(sigcontext
);
1410 __asm__("movw %%ds,%0" : "=m" (context
->SegDs
));
1413 context
->SegEs
= ES_sig(sigcontext
);
1415 __asm__("movw %%es,%0" : "=m" (context
->SegEs
));
1418 context
->SegSs
= SS_sig(sigcontext
);
1420 __asm__("movw %%ss,%0" : "=m" (context
->SegSs
));
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 /***********************************************************************
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
,
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 */
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
;
1531 /***********************************************************************
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
;
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 /***********************************************************************
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
);
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
);
1765 set_full_cpu_context( context
);
1771 /***********************************************************************
1772 * NtGetContextThread (NTDLL.@)
1773 * ZwGetContextThread (NTDLL.@)
1775 NTSTATUS WINAPI
NtGetContextThread( HANDLE handle
, CONTEXT
*context
)
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
;
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
;
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
,
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
;
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
);
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
);
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 /***********************************************************************
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
)
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"
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) */
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
)
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
;
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
;
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
;
2007 /***********************************************************************
2010 * Handle an interrupt.
2012 static inline BOOL
handle_interrupt( ucontext_t
*sigcontext
, EXCEPTION_RECORD
*rec
, CONTEXT
*context
)
2014 switch (ERROR_sig(sigcontext
) >> 3)
2017 rec
->ExceptionCode
= STATUS_ASSERTION_FAILURE
;
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;
2030 rec
->ExceptionCode
= EXCEPTION_BREAKPOINT
;
2031 rec
->ExceptionAddress
= (void *)context
->Rip
;
2032 rec
->NumberParameters
= 1;
2033 rec
->ExceptionInformation
[0] = context
->Rax
;
2038 setup_raise_exception( sigcontext
, rec
, context
);
2043 /**********************************************************************
2046 * Handler for SIGSEGV and related errors.
2048 static void segv_handler( int signal
, siginfo_t
*siginfo
, void *sigcontext
)
2050 EXCEPTION_RECORD rec
= { 0 };
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
;
2062 case TRAP_x86_BOUND
: /* Bound range exception */
2063 rec
.ExceptionCode
= EXCEPTION_ARRAY_BOUNDS_EXCEEDED
;
2065 case TRAP_x86_PRIVINFLT
: /* Invalid opcode exception */
2066 rec
.ExceptionCode
= EXCEPTION_ILLEGAL_INSTRUCTION
;
2068 case TRAP_x86_STKFLT
: /* Stack fault */
2069 rec
.ExceptionCode
= EXCEPTION_STACK_OVERFLOW
;
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;
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;
2091 case TRAP_x86_ALIGNFLT
: /* Alignment check exception */
2092 rec
.ExceptionCode
= EXCEPTION_DATATYPE_MISALIGNMENT
;
2095 ERR( "Got unexpected trap %ld\n", (ULONG_PTR
)TRAP_sig(ucontext
) );
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
;
2106 setup_raise_exception( sigcontext
, &rec
, &context
);
2110 /**********************************************************************
2113 * Handler for SIGTRAP.
2115 static void trap_handler( int signal
, siginfo_t
*siginfo
, void *sigcontext
)
2117 EXCEPTION_RECORD rec
= { 0 };
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
;
2130 case TRAP_BRKPT
: /* Breakpoint exception */
2134 /* Check if this is actually icebp instruction */
2135 if (((unsigned char *)RIP_sig(ucontext
))[-1] == 0xF1)
2137 rec
.ExceptionCode
= EXCEPTION_SINGLE_STEP
;
2140 rec
.ExceptionAddress
= (char *)rec
.ExceptionAddress
- 1; /* back up over the int3 instruction */
2143 rec
.ExceptionCode
= EXCEPTION_BREAKPOINT
;
2144 rec
.NumberParameters
= 1;
2145 rec
.ExceptionInformation
[0] = 0;
2148 setup_raise_exception( sigcontext
, &rec
, &context
);
2152 /**********************************************************************
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
)
2164 rec
.ExceptionCode
= EXCEPTION_ARRAY_BOUNDS_EXCEEDED
;
2167 rec
.ExceptionCode
= EXCEPTION_INT_DIVIDE_BY_ZERO
;
2170 rec
.ExceptionCode
= EXCEPTION_INT_OVERFLOW
;
2173 rec
.ExceptionCode
= EXCEPTION_FLT_DIVIDE_BY_ZERO
;
2176 rec
.ExceptionCode
= EXCEPTION_FLT_OVERFLOW
;
2179 rec
.ExceptionCode
= EXCEPTION_FLT_UNDERFLOW
;
2182 rec
.ExceptionCode
= EXCEPTION_FLT_INEXACT_RESULT
;
2186 rec
.ExceptionCode
= EXCEPTION_FLT_INVALID_OPERATION
;
2189 setup_exception( sigcontext
, &rec
);
2193 /**********************************************************************
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 /**********************************************************************
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 /**********************************************************************
2222 * Handler for SIGQUIT.
2224 static void quit_handler( int signal
, siginfo_t
*siginfo
, void *ucontext
)
2230 /**********************************************************************
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
)
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
)
2289 /**********************************************************************
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;
2309 const void** p
= (const void**)pthread_self();
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
);
2329 pthread_setspecific(key
, sentinel1
);
2333 pthread_key_delete(key
);
2336 if (gsbase_offset
) return (char*)pthread_self() + gsbase_offset
;
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();
2368 # error Please define setting %gs for your architecture
2372 __asm__
volatile ("fninit; fldcw %0" : : "m" (fpu_cw
));
2374 FIXME("FPU setup not implemented for this platform.\n");
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
;
2408 perror("sigaction");
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 /***********************************************************************
2433 PCONTEXT DECLSPEC_HIDDEN
attach_thread( LPTHREAD_START_ROUTINE entry
, void *arg
,
2434 BOOL suspend
, void *relay
)
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;
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 );
2460 /***********************************************************************
2461 * signal_start_thread
2463 __ASM_GLOBAL_FUNC( signal_start_thread
,
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"
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 */
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"
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")
2522 #endif /* __x86_64__ */