include: Add more ARM64 CV constants.
[wine/multimedia.git] / dlls / ntdll / signal_arm64.c
bloba8b48163449ab2d8d52b9b03d373568858cc33ea
1 /*
2 * ARM64 signal handling routines
4 * Copyright 2010-2013 André Hentschel
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 #ifdef __aarch64__
23 #include "config.h"
24 #include "wine/port.h"
26 #include <assert.h>
27 #include <signal.h>
28 #include <stdlib.h>
29 #include <stdarg.h>
30 #include <stdio.h>
31 #ifdef HAVE_UNISTD_H
32 # include <unistd.h>
33 #endif
34 #ifdef HAVE_SYS_PARAM_H
35 # include <sys/param.h>
36 #endif
37 #ifdef HAVE_SYSCALL_H
38 # include <syscall.h>
39 #else
40 # ifdef HAVE_SYS_SYSCALL_H
41 # include <sys/syscall.h>
42 # endif
43 #endif
44 #ifdef HAVE_SYS_SIGNAL_H
45 # include <sys/signal.h>
46 #endif
47 #ifdef HAVE_SYS_UCONTEXT_H
48 # include <sys/ucontext.h>
49 #endif
51 #include "ntstatus.h"
52 #define WIN32_NO_STATUS
53 #include "windef.h"
54 #include "winternl.h"
55 #include "wine/library.h"
56 #include "wine/exception.h"
57 #include "ntdll_misc.h"
58 #include "wine/debug.h"
59 #include "winnt.h"
61 WINE_DEFAULT_DEBUG_CHANNEL(seh);
63 static pthread_key_t teb_key;
65 /***********************************************************************
66 * signal context platform-specific definitions
68 #ifdef linux
70 /* All Registers access - only for local access */
71 # define REG_sig(reg_name, context) ((context)->uc_mcontext.reg_name)
72 # define REGn_sig(reg_num, context) ((context)->uc_mcontext.regs[reg_num])
74 /* Special Registers access */
75 # define SP_sig(context) REG_sig(sp, context) /* Stack pointer */
76 # define PC_sig(context) REG_sig(pc, context) /* Program counter */
77 # define PSTATE_sig(context) REG_sig(pstate, context) /* Current State Register */
78 # define FP_sig(context) REGn_sig(29, context) /* Frame pointer */
79 # define LR_sig(context) REGn_sig(30, context) /* Link Register */
81 /* Exceptions */
82 # define FAULT_sig(context) REG_sig(fault_address, context)
84 #endif /* linux */
86 static const size_t teb_size = 0x2000; /* we reserve two pages for the TEB */
87 static size_t signal_stack_size;
89 typedef void (WINAPI *raise_func)( EXCEPTION_RECORD *rec, CONTEXT *context );
90 typedef int (*wine_signal_handler)(unsigned int sig);
92 static wine_signal_handler handlers[256];
94 /***********************************************************************
95 * dispatch_signal
97 static inline int dispatch_signal(unsigned int sig)
99 if (handlers[sig] == NULL) return 0;
100 return handlers[sig](sig);
103 /*******************************************************************
104 * is_valid_frame
106 static inline BOOL is_valid_frame( void *frame )
108 if ((ULONG_PTR)frame & 3) return FALSE;
109 return (frame >= NtCurrentTeb()->Tib.StackLimit &&
110 (void **)frame < (void **)NtCurrentTeb()->Tib.StackBase - 1);
113 /***********************************************************************
114 * save_context
116 * Set the register values from a sigcontext.
118 static void save_context( CONTEXT *context, const ucontext_t *sigcontext )
120 #define C(n) context->X##n = REGn_sig(n,sigcontext)
121 /* Save normal registers */
122 C(0); C(1); C(2); C(3); C(4); C(5); C(6); C(7); C(8); C(9);
123 C(10); C(11); C(12); C(13); C(14); C(15); C(16); C(17); C(18); C(19);
124 C(20); C(21); C(22); C(23); C(24); C(25); C(26); C(27); C(28);
125 #undef C
127 context->ContextFlags = CONTEXT_FULL;
128 context->Fp = FP_sig(sigcontext); /* Frame pointer */
129 context->Lr = LR_sig(sigcontext); /* Link register */
130 context->Sp = SP_sig(sigcontext); /* Stack pointer */
131 context->Pc = PC_sig(sigcontext); /* Program Counter */
132 context->PState = PSTATE_sig(sigcontext); /* Current State Register */
136 /***********************************************************************
137 * restore_context
139 * Build a sigcontext from the register values.
141 static void restore_context( const CONTEXT *context, ucontext_t *sigcontext )
143 #define C(n) REGn_sig(n,sigcontext) = context->X##n
144 /* Restore normal registers */
145 C(0); C(1); C(2); C(3); C(4); C(5); C(6); C(7); C(8); C(9);
146 C(10); C(11); C(12); C(13); C(14); C(15); C(16); C(17); C(18); C(19);
147 C(20); C(21); C(22); C(23); C(24); C(25); C(26); C(27); C(28);
148 #undef C
150 FP_sig(sigcontext) = context->Fp; /* Frame pointer */
151 LR_sig(sigcontext) = context->Lr; /* Link register */
152 SP_sig(sigcontext) = context->Sp; /* Stack pointer */
153 PC_sig(sigcontext) = context->Pc; /* Program Counter */
154 PSTATE_sig(sigcontext) = context->PState; /* Current State Register */
158 /***********************************************************************
159 * save_fpu
161 * Set the FPU context from a sigcontext.
163 static inline void save_fpu( CONTEXT *context, const ucontext_t *sigcontext )
165 FIXME( "Not implemented on ARM64\n" );
169 /***********************************************************************
170 * restore_fpu
172 * Restore the FPU context to a sigcontext.
174 static inline void restore_fpu( CONTEXT *context, const ucontext_t *sigcontext )
176 FIXME( "Not implemented on ARM64\n" );
179 /***********************************************************************
180 * RtlCaptureContext (NTDLL.@)
182 void WINAPI RtlCaptureContext( CONTEXT *context )
184 FIXME( "Not implemented on ARM64\n" );
185 memset( context, 0, sizeof(*context) );
188 /***********************************************************************
189 * set_cpu_context
191 * Set the new CPU context.
193 void set_cpu_context( const CONTEXT *context )
195 FIXME( "Not implemented on ARM64\n" );
198 /***********************************************************************
199 * copy_context
201 * Copy a register context according to the flags.
203 void copy_context( CONTEXT *to, const CONTEXT *from, DWORD flags )
205 flags &= ~CONTEXT_ARM64; /* get rid of CPU id */
206 if (flags & CONTEXT_CONTROL)
208 to->Fp = from->Fp;
209 to->Lr = from->Lr;
210 to->Sp = from->Sp;
211 to->Pc = from->Pc;
212 to->PState = from->PState;
214 if (flags & CONTEXT_INTEGER)
216 #define C(n) to->X##n = from->X##n
217 /* Restore normal registers */
218 C(0); C(1); C(2); C(3); C(4); C(5); C(6); C(7); C(8); C(9);
219 C(10); C(11); C(12); C(13); C(14); C(15); C(16); C(17); C(18); C(19);
220 C(20); C(21); C(22); C(23); C(24); C(25); C(26); C(27); C(28);
221 #undef C
225 /***********************************************************************
226 * context_to_server
228 * Convert a register context to the server format.
230 NTSTATUS context_to_server( context_t *to, const CONTEXT *from )
232 DWORD flags = from->ContextFlags & ~CONTEXT_ARM64; /* get rid of CPU id */
234 memset( to, 0, sizeof(*to) );
235 to->cpu = CPU_ARM64;
237 if (flags & CONTEXT_CONTROL)
239 to->flags |= SERVER_CTX_CONTROL;
240 to->integer.arm64_regs.x[29] = from->Fp;
241 to->integer.arm64_regs.x[30] = from->Lr;
242 to->ctl.arm64_regs.sp = from->Sp;
243 to->ctl.arm64_regs.pc = from->Pc;
244 to->ctl.arm64_regs.pstate = from->PState;
246 if (flags & CONTEXT_INTEGER)
248 to->flags |= SERVER_CTX_INTEGER;
249 #define C(n) to->integer.arm64_regs.x[n] = from->X##n
250 /* Restore normal registers */
251 C(0); C(1); C(2); C(3); C(4); C(5); C(6); C(7); C(8); C(9);
252 C(10); C(11); C(12); C(13); C(14); C(15); C(16); C(17); C(18); C(19);
253 C(20); C(21); C(22); C(23); C(24); C(25); C(26); C(27); C(28);
254 #undef C
256 return STATUS_SUCCESS;
260 /***********************************************************************
261 * context_from_server
263 * Convert a register context from the server format.
265 NTSTATUS context_from_server( CONTEXT *to, const context_t *from )
267 if (from->cpu != CPU_ARM64) return STATUS_INVALID_PARAMETER;
269 to->ContextFlags = CONTEXT_ARM64;
270 if (from->flags & SERVER_CTX_CONTROL)
272 to->ContextFlags |= CONTEXT_CONTROL;
273 to->Fp = from->integer.arm64_regs.x[29];
274 to->Lr = from->integer.arm64_regs.x[30];
275 to->Sp = from->ctl.arm64_regs.sp;
276 to->Pc = from->ctl.arm64_regs.pc;
277 to->PState = from->ctl.arm64_regs.pstate;
279 if (from->flags & SERVER_CTX_INTEGER)
281 to->ContextFlags |= CONTEXT_INTEGER;
282 #define C(n) to->X##n = from->integer.arm64_regs.x[n]
283 /* Restore normal registers */
284 C(0); C(1); C(2); C(3); C(4); C(5); C(6); C(7); C(8); C(9);
285 C(10); C(11); C(12); C(13); C(14); C(15); C(16); C(17); C(18); C(19);
286 C(20); C(21); C(22); C(23); C(24); C(25); C(26); C(27); C(28);
287 #undef C
289 return STATUS_SUCCESS;
292 /***********************************************************************
293 * setup_exception_record
295 * Setup the exception record and context on the thread stack.
297 static EXCEPTION_RECORD *setup_exception( ucontext_t *sigcontext, raise_func func )
299 struct stack_layout
301 CONTEXT context;
302 EXCEPTION_RECORD rec;
303 } *stack;
304 DWORD exception_code = 0;
306 stack = (struct stack_layout *)(SP_sig(sigcontext) & ~3);
307 stack--; /* push the stack_layout structure */
309 stack->rec.ExceptionRecord = NULL;
310 stack->rec.ExceptionCode = exception_code;
311 stack->rec.ExceptionFlags = EXCEPTION_CONTINUABLE;
312 stack->rec.ExceptionAddress = (LPVOID)PC_sig(sigcontext);
313 stack->rec.NumberParameters = 0;
315 save_context( &stack->context, sigcontext );
317 /* now modify the sigcontext to return to the raise function */
318 SP_sig(sigcontext) = (ULONG_PTR)stack;
319 PC_sig(sigcontext) = (ULONG_PTR)func;
320 REGn_sig(0, sigcontext) = (ULONG_PTR)&stack->rec; /* first arg for raise_func */
321 REGn_sig(1, sigcontext) = (ULONG_PTR)&stack->context; /* second arg for raise_func */
323 return &stack->rec;
326 /**********************************************************************
327 * raise_segv_exception
329 static void WINAPI raise_segv_exception( EXCEPTION_RECORD *rec, CONTEXT *context )
331 NTSTATUS status;
333 switch(rec->ExceptionCode)
335 case EXCEPTION_ACCESS_VIOLATION:
336 if (rec->NumberParameters == 2)
338 if (!(rec->ExceptionCode = virtual_handle_fault( (void *)rec->ExceptionInformation[1],
339 rec->ExceptionInformation[0], FALSE )))
340 goto done;
342 break;
344 status = NtRaiseException( rec, context, TRUE );
345 if (status) raise_status( status, rec );
346 done:
347 set_cpu_context( context );
350 /**********************************************************************
351 * call_stack_handlers
353 * Call the stack handlers chain.
355 static NTSTATUS call_stack_handlers( EXCEPTION_RECORD *rec, CONTEXT *context )
357 EXCEPTION_REGISTRATION_RECORD *frame, *dispatch, *nested_frame;
358 DWORD res;
360 frame = NtCurrentTeb()->Tib.ExceptionList;
361 nested_frame = NULL;
362 while (frame != (EXCEPTION_REGISTRATION_RECORD*)~0UL)
364 /* Check frame address */
365 if (!is_valid_frame( frame ))
367 rec->ExceptionFlags |= EH_STACK_INVALID;
368 break;
371 /* Call handler */
372 TRACE( "calling handler at %p code=%x flags=%x\n",
373 frame->Handler, rec->ExceptionCode, rec->ExceptionFlags );
374 res = frame->Handler( rec, frame, context, &dispatch );
375 TRACE( "handler at %p returned %x\n", frame->Handler, res );
377 if (frame == nested_frame)
379 /* no longer nested */
380 nested_frame = NULL;
381 rec->ExceptionFlags &= ~EH_NESTED_CALL;
384 switch(res)
386 case ExceptionContinueExecution:
387 if (!(rec->ExceptionFlags & EH_NONCONTINUABLE)) return STATUS_SUCCESS;
388 return STATUS_NONCONTINUABLE_EXCEPTION;
389 case ExceptionContinueSearch:
390 break;
391 case ExceptionNestedException:
392 if (nested_frame < dispatch) nested_frame = dispatch;
393 rec->ExceptionFlags |= EH_NESTED_CALL;
394 break;
395 default:
396 return STATUS_INVALID_DISPOSITION;
398 frame = frame->Prev;
400 return STATUS_UNHANDLED_EXCEPTION;
404 /*******************************************************************
405 * raise_exception
407 * Implementation of NtRaiseException.
409 static NTSTATUS raise_exception( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance )
411 NTSTATUS status;
413 if (first_chance)
415 DWORD c;
417 for (c = 0; c < rec->NumberParameters; c++)
418 TRACE( " info[%d]=%016lx\n", c, rec->ExceptionInformation[c] );
419 if (rec->ExceptionCode == EXCEPTION_WINE_STUB)
421 if (rec->ExceptionInformation[1] >> 16)
422 MESSAGE( "wine: Call from %p to unimplemented function %s.%s, aborting\n",
423 rec->ExceptionAddress,
424 (char*)rec->ExceptionInformation[0], (char*)rec->ExceptionInformation[1] );
425 else
426 MESSAGE( "wine: Call from %p to unimplemented function %s.%ld, aborting\n",
427 rec->ExceptionAddress,
428 (char*)rec->ExceptionInformation[0], rec->ExceptionInformation[1] );
430 else
432 /* FIXME: dump context */
435 status = send_debug_event( rec, TRUE, context );
436 if (status == DBG_CONTINUE || status == DBG_EXCEPTION_HANDLED)
437 return STATUS_SUCCESS;
439 if (call_vectored_handlers( rec, context ) == EXCEPTION_CONTINUE_EXECUTION)
440 return STATUS_SUCCESS;
442 if ((status = call_stack_handlers( rec, context )) != STATUS_UNHANDLED_EXCEPTION)
443 return status;
446 /* last chance exception */
448 status = send_debug_event( rec, FALSE, context );
449 if (status != DBG_CONTINUE)
451 if (rec->ExceptionFlags & EH_STACK_INVALID)
452 ERR("Exception frame is not in stack limits => unable to dispatch exception.\n");
453 else if (rec->ExceptionCode == STATUS_NONCONTINUABLE_EXCEPTION)
454 ERR("Process attempted to continue execution after noncontinuable exception.\n");
455 else
456 ERR("Unhandled exception code %x flags %x addr %p\n",
457 rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress );
458 NtTerminateProcess( NtCurrentProcess(), rec->ExceptionCode );
460 return STATUS_SUCCESS;
463 /**********************************************************************
464 * segv_handler
466 * Handler for SIGSEGV and related errors.
468 static void segv_handler( int signal, siginfo_t *info, void *ucontext )
470 EXCEPTION_RECORD *rec;
471 ucontext_t *context = ucontext;
473 /* check for page fault inside the thread stack */
474 if (signal == SIGSEGV &&
475 (char *)info->si_addr >= (char *)NtCurrentTeb()->DeallocationStack &&
476 (char *)info->si_addr < (char *)NtCurrentTeb()->Tib.StackBase &&
477 virtual_handle_stack_fault( info->si_addr ))
479 /* check if this was the last guard page */
480 if ((char *)info->si_addr < (char *)NtCurrentTeb()->DeallocationStack + 2*4096)
482 rec = setup_exception( context, raise_segv_exception );
483 rec->ExceptionCode = EXCEPTION_STACK_OVERFLOW;
485 return;
488 rec = setup_exception( context, raise_segv_exception );
489 if (rec->ExceptionCode == EXCEPTION_STACK_OVERFLOW) return;
491 switch(signal)
493 case SIGILL: /* Invalid opcode exception */
494 rec->ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
495 break;
496 case SIGSEGV: /* Segmentation fault */
497 rec->ExceptionCode = EXCEPTION_ACCESS_VIOLATION;
498 rec->NumberParameters = 2;
499 /* FIXME: Currently the kernel provides no way to determine if it's read or write */
500 rec->ExceptionInformation[0] = 0;
501 rec->ExceptionInformation[1] = (ULONG_PTR)info->si_addr;
502 break;
503 case SIGBUS: /* Alignment check exception */
504 rec->ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT;
505 break;
506 default:
507 ERR("Got unexpected signal %i\n", signal);
508 rec->ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
509 break;
513 /**********************************************************************
514 * trap_handler
516 * Handler for SIGTRAP.
518 static void trap_handler( int signal, siginfo_t *info, void *ucontext )
520 EXCEPTION_RECORD rec;
521 CONTEXT context;
522 NTSTATUS status;
524 switch ( info->si_code )
526 case TRAP_TRACE:
527 rec.ExceptionCode = EXCEPTION_SINGLE_STEP;
528 break;
529 case TRAP_BRKPT:
530 default:
531 rec.ExceptionCode = EXCEPTION_BREAKPOINT;
532 break;
535 save_context( &context, ucontext );
536 rec.ExceptionFlags = EXCEPTION_CONTINUABLE;
537 rec.ExceptionRecord = NULL;
538 rec.ExceptionAddress = (LPVOID)context.Pc;
539 rec.NumberParameters = 0;
540 status = raise_exception( &rec, &context, TRUE );
541 if (status) raise_status( status, &rec );
542 restore_context( &context, ucontext );
545 /**********************************************************************
546 * fpe_handler
548 * Handler for SIGFPE.
550 static void fpe_handler( int signal, siginfo_t *siginfo, void *sigcontext )
552 EXCEPTION_RECORD rec;
553 CONTEXT context;
554 NTSTATUS status;
556 save_fpu( &context, sigcontext );
557 save_context( &context, sigcontext );
559 switch (siginfo->si_code & 0xffff )
561 #ifdef FPE_FLTSUB
562 case FPE_FLTSUB:
563 rec.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED;
564 break;
565 #endif
566 #ifdef FPE_INTDIV
567 case FPE_INTDIV:
568 rec.ExceptionCode = EXCEPTION_INT_DIVIDE_BY_ZERO;
569 break;
570 #endif
571 #ifdef FPE_INTOVF
572 case FPE_INTOVF:
573 rec.ExceptionCode = EXCEPTION_INT_OVERFLOW;
574 break;
575 #endif
576 #ifdef FPE_FLTDIV
577 case FPE_FLTDIV:
578 rec.ExceptionCode = EXCEPTION_FLT_DIVIDE_BY_ZERO;
579 break;
580 #endif
581 #ifdef FPE_FLTOVF
582 case FPE_FLTOVF:
583 rec.ExceptionCode = EXCEPTION_FLT_OVERFLOW;
584 break;
585 #endif
586 #ifdef FPE_FLTUND
587 case FPE_FLTUND:
588 rec.ExceptionCode = EXCEPTION_FLT_UNDERFLOW;
589 break;
590 #endif
591 #ifdef FPE_FLTRES
592 case FPE_FLTRES:
593 rec.ExceptionCode = EXCEPTION_FLT_INEXACT_RESULT;
594 break;
595 #endif
596 #ifdef FPE_FLTINV
597 case FPE_FLTINV:
598 #endif
599 default:
600 rec.ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION;
601 break;
603 rec.ExceptionFlags = EXCEPTION_CONTINUABLE;
604 rec.ExceptionRecord = NULL;
605 rec.ExceptionAddress = (LPVOID)context.Pc;
606 rec.NumberParameters = 0;
607 status = raise_exception( &rec, &context, TRUE );
608 if (status) raise_status( status, &rec );
610 restore_context( &context, sigcontext );
611 restore_fpu( &context, sigcontext );
614 /**********************************************************************
615 * int_handler
617 * Handler for SIGINT.
619 static void int_handler( int signal, siginfo_t *siginfo, void *sigcontext )
621 if (!dispatch_signal(SIGINT))
623 EXCEPTION_RECORD rec;
624 CONTEXT context;
625 NTSTATUS status;
627 save_context( &context, sigcontext );
628 rec.ExceptionCode = CONTROL_C_EXIT;
629 rec.ExceptionFlags = EXCEPTION_CONTINUABLE;
630 rec.ExceptionRecord = NULL;
631 rec.ExceptionAddress = (LPVOID)context.Pc;
632 rec.NumberParameters = 0;
633 status = raise_exception( &rec, &context, TRUE );
634 if (status) raise_status( status, &rec );
635 restore_context( &context, sigcontext );
640 /**********************************************************************
641 * abrt_handler
643 * Handler for SIGABRT.
645 static void abrt_handler( int signal, siginfo_t *siginfo, void *sigcontext )
647 EXCEPTION_RECORD rec;
648 CONTEXT context;
649 NTSTATUS status;
651 save_context( &context, sigcontext );
652 rec.ExceptionCode = EXCEPTION_WINE_ASSERTION;
653 rec.ExceptionFlags = EH_NONCONTINUABLE;
654 rec.ExceptionRecord = NULL;
655 rec.ExceptionAddress = (LPVOID)context.Pc;
656 rec.NumberParameters = 0;
657 status = raise_exception( &rec, &context, TRUE );
658 if (status) raise_status( status, &rec );
659 restore_context( &context, sigcontext );
663 /**********************************************************************
664 * quit_handler
666 * Handler for SIGQUIT.
668 static void quit_handler( int signal, siginfo_t *siginfo, void *sigcontext )
670 abort_thread(0);
674 /**********************************************************************
675 * usr1_handler
677 * Handler for SIGUSR1, used to signal a thread that it got suspended.
679 static void usr1_handler( int signal, siginfo_t *siginfo, void *sigcontext )
681 CONTEXT context;
683 save_context( &context, sigcontext );
684 wait_suspend( &context );
685 restore_context( &context, sigcontext );
689 /***********************************************************************
690 * __wine_set_signal_handler (NTDLL.@)
692 int CDECL __wine_set_signal_handler(unsigned int sig, wine_signal_handler wsh)
694 if (sig > sizeof(handlers) / sizeof(handlers[0])) return -1;
695 if (handlers[sig] != NULL) return -2;
696 handlers[sig] = wsh;
697 return 0;
701 /**********************************************************************
702 * signal_alloc_thread
704 NTSTATUS signal_alloc_thread( TEB **teb )
706 static size_t sigstack_zero_bits;
707 SIZE_T size;
708 NTSTATUS status;
710 if (!sigstack_zero_bits)
712 size_t min_size = teb_size + max( MINSIGSTKSZ, 8192 );
713 /* find the first power of two not smaller than min_size */
714 sigstack_zero_bits = 12;
715 while ((1u << sigstack_zero_bits) < min_size) sigstack_zero_bits++;
716 signal_stack_size = (1 << sigstack_zero_bits) - teb_size;
717 assert( sizeof(TEB) <= teb_size );
720 size = 1 << sigstack_zero_bits;
721 *teb = NULL;
722 if (!(status = NtAllocateVirtualMemory( NtCurrentProcess(), (void **)teb, sigstack_zero_bits,
723 &size, MEM_COMMIT | MEM_TOP_DOWN, PAGE_READWRITE )))
725 (*teb)->Tib.Self = &(*teb)->Tib;
726 (*teb)->Tib.ExceptionList = (void *)~0UL;
728 return status;
732 /**********************************************************************
733 * signal_free_thread
735 void signal_free_thread( TEB *teb )
737 SIZE_T size;
739 if (teb->DeallocationStack)
741 size = 0;
742 NtFreeVirtualMemory( GetCurrentProcess(), &teb->DeallocationStack, &size, MEM_RELEASE );
744 size = 0;
745 NtFreeVirtualMemory( NtCurrentProcess(), (void **)&teb, &size, MEM_RELEASE );
749 /**********************************************************************
750 * signal_init_thread
752 void signal_init_thread( TEB *teb )
754 static BOOL init_done;
756 if (!init_done)
758 pthread_key_create( &teb_key, NULL );
759 init_done = TRUE;
761 pthread_setspecific( teb_key, teb );
765 /**********************************************************************
766 * signal_init_process
768 void signal_init_process(void)
770 struct sigaction sig_act;
772 sig_act.sa_mask = server_block_set;
773 sig_act.sa_flags = SA_RESTART | SA_SIGINFO;
775 sig_act.sa_sigaction = int_handler;
776 if (sigaction( SIGINT, &sig_act, NULL ) == -1) goto error;
777 sig_act.sa_sigaction = fpe_handler;
778 if (sigaction( SIGFPE, &sig_act, NULL ) == -1) goto error;
779 sig_act.sa_sigaction = abrt_handler;
780 if (sigaction( SIGABRT, &sig_act, NULL ) == -1) goto error;
781 sig_act.sa_sigaction = quit_handler;
782 if (sigaction( SIGQUIT, &sig_act, NULL ) == -1) goto error;
783 sig_act.sa_sigaction = usr1_handler;
784 if (sigaction( SIGUSR1, &sig_act, NULL ) == -1) goto error;
786 sig_act.sa_sigaction = segv_handler;
787 if (sigaction( SIGSEGV, &sig_act, NULL ) == -1) goto error;
788 if (sigaction( SIGILL, &sig_act, NULL ) == -1) goto error;
789 #ifdef SIGBUS
790 if (sigaction( SIGBUS, &sig_act, NULL ) == -1) goto error;
791 #endif
793 #ifdef SIGTRAP
794 sig_act.sa_sigaction = trap_handler;
795 if (sigaction( SIGTRAP, &sig_act, NULL ) == -1) goto error;
796 #endif
797 return;
799 error:
800 perror("sigaction");
801 exit(1);
805 /**********************************************************************
806 * __wine_enter_vm86 (NTDLL.@)
808 void __wine_enter_vm86( CONTEXT *context )
810 MESSAGE("vm86 mode not supported on this platform\n");
813 /***********************************************************************
814 * RtlUnwind (NTDLL.@)
816 void WINAPI RtlUnwind( PVOID pEndFrame, PVOID targetIp, PEXCEPTION_RECORD pRecord, PVOID retval )
818 FIXME( "Not implemented on ARM64\n" );
821 /*******************************************************************
822 * NtRaiseException (NTDLL.@)
824 NTSTATUS WINAPI NtRaiseException( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance )
826 NTSTATUS status = raise_exception( rec, context, first_chance );
827 if (status == STATUS_SUCCESS) NtSetContextThread( GetCurrentThread(), context );
828 return status;
831 /***********************************************************************
832 * RtlRaiseException (NTDLL.@)
834 void WINAPI RtlRaiseException( EXCEPTION_RECORD *rec )
836 CONTEXT context;
837 NTSTATUS status;
839 RtlCaptureContext( &context );
840 rec->ExceptionAddress = (LPVOID)context.Pc;
841 status = raise_exception( rec, &context, TRUE );
842 if (status) raise_status( status, rec );
845 /*************************************************************************
846 * RtlCaptureStackBackTrace (NTDLL.@)
848 USHORT WINAPI RtlCaptureStackBackTrace( ULONG skip, ULONG count, PVOID *buffer, ULONG *hash )
850 FIXME( "(%d, %d, %p, %p) stub!\n", skip, count, buffer, hash );
851 return 0;
854 /***********************************************************************
855 * call_thread_entry_point
857 void call_thread_entry_point( LPTHREAD_START_ROUTINE entry, void *arg )
859 __TRY
861 exit_thread( entry( arg ));
863 __EXCEPT(unhandled_exception_filter)
865 NtTerminateThread( GetCurrentThread(), GetExceptionCode() );
867 __ENDTRY
868 abort(); /* should not be reached */
871 /***********************************************************************
872 * RtlExitUserThread (NTDLL.@)
874 void WINAPI RtlExitUserThread( ULONG status )
876 exit_thread( status );
879 /***********************************************************************
880 * abort_thread
882 void abort_thread( int status )
884 terminate_thread( status );
887 /**********************************************************************
888 * DbgBreakPoint (NTDLL.@)
890 void WINAPI DbgBreakPoint(void)
892 kill(getpid(), SIGTRAP);
895 /**********************************************************************
896 * DbgUserBreakPoint (NTDLL.@)
898 void WINAPI DbgUserBreakPoint(void)
900 kill(getpid(), SIGTRAP);
903 /**********************************************************************
904 * NtCurrentTeb (NTDLL.@)
906 TEB * WINAPI NtCurrentTeb(void)
908 return pthread_getspecific( teb_key );
911 #endif /* __aarch64__ */