From 171c9a532750566d3c786b4d7c1ab807a1265b5e Mon Sep 17 00:00:00 2001 From: =?utf8?q?Andr=C3=A9=20Hentschel?= Date: Sat, 18 Sep 2010 18:02:12 +0200 Subject: [PATCH] ntdll: Add ARM support. --- dlls/ntdll/Makefile.in | 1 + dlls/ntdll/nt.c | 2 + dlls/ntdll/server.c | 2 + dlls/ntdll/signal_arm.c | 800 ++++++++++++++++++++++++++++++++++++++++++++++++ include/winnt.h | 7 +- 5 files changed, 809 insertions(+), 3 deletions(-) create mode 100644 dlls/ntdll/signal_arm.c diff --git a/dlls/ntdll/Makefile.in b/dlls/ntdll/Makefile.in index e4116999345..0047731447d 100644 --- a/dlls/ntdll/Makefile.in +++ b/dlls/ntdll/Makefile.in @@ -37,6 +37,7 @@ C_SRCS = \ sec.c \ serial.c \ server.c \ + signal_arm.c \ signal_i386.c \ signal_powerpc.c \ signal_sparc.c \ diff --git a/dlls/ntdll/nt.c b/dlls/ntdll/nt.c index 0f37def5600..ba8cbe7c0c9 100644 --- a/dlls/ntdll/nt.c +++ b/dlls/ntdll/nt.c @@ -920,6 +920,8 @@ void fill_cpu_info(void) cached_sci.Architecture = PROCESSOR_ARCHITECTURE_AMD64; #elif defined(__powerpc__) cached_sci.Architecture = PROCESSOR_ARCHITECTURE_PPC; +#elif defined(__arm__) + cached_sci.Architecture = PROCESSOR_ARCHITECTURE_ARM; #elif defined(__ALPHA__) cached_sci.Architecture = PROCESSOR_ARCHITECTURE_ALPHA; #elif defined(__sparc__) diff --git a/dlls/ntdll/server.c b/dlls/ntdll/server.c index 5e67bd6414e..b3a8b21a0a1 100644 --- a/dlls/ntdll/server.c +++ b/dlls/ntdll/server.c @@ -90,6 +90,8 @@ static const enum cpu_type client_cpu = CPU_ALPHA; static const enum cpu_type client_cpu = CPU_POWERPC; #elif defined(__sparc__) static const enum cpu_type client_cpu = CPU_SPARC; +#elif defined(__arm__) +static const enum cpu_type client_cpu = CPU_ARM; #else #error Unsupported CPU #endif diff --git a/dlls/ntdll/signal_arm.c b/dlls/ntdll/signal_arm.c new file mode 100644 index 00000000000..992b63c6db2 --- /dev/null +++ b/dlls/ntdll/signal_arm.c @@ -0,0 +1,800 @@ +/* + * ARM signal handling routines + * + * Copyright 2002 Marcus Meissner, SuSE Linux AG + * Copyright 2010 André Hentschel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifdef __arm__ + +#include "config.h" +#include "wine/port.h" + +#include +#include +#include +#include +#include +#ifdef HAVE_UNISTD_H +# include +#endif + +#ifdef HAVE_SYS_PARAM_H +# include +#endif +#ifdef HAVE_SYSCALL_H +# include +#else +# ifdef HAVE_SYS_SYSCALL_H +# include +# endif +#endif +#ifdef HAVE_SYS_SIGNAL_H +# include +#endif + +#include "ntstatus.h" +#define WIN32_NO_STATUS +#include "windef.h" +#include "winternl.h" +#include "wine/library.h" +#include "wine/exception.h" +#include "ntdll_misc.h" +#include "wine/debug.h" +#include "winnt.h" + +WINE_DEFAULT_DEBUG_CHANNEL(seh); + +static pthread_key_t teb_key; + +/*********************************************************************** + * signal context platform-specific definitions + */ +#ifdef linux + +/* All Registers access - only for local access */ +# define REG_sig(reg_name, context) ((context)->uc_mcontext.reg_name) +# define REGn_sig(reg_num, context) ((context)->uc_mcontext.arm_r##reg_num) + +/* Special Registers access */ +# define SP_sig(context) REG_sig(arm_sp, context) /* Stack pointer */ +# define LR_sig(context) REG_sig(arm_lr, context) /* Link register */ +# define PC_sig(context) REG_sig(arm_pc, context) /* Program counter */ +# define CPSR_sig(context) REG_sig(arm_cpsr, context) /* Current State Register */ +# define IP_sig(context) REG_sig(arm_ip, context) /* Program counter (2?) */ +# define FP_sig(context) REG_sig(arm_fp, context) /* Frame pointer */ + +#endif /* linux */ + +typedef int (*wine_signal_handler)(unsigned int sig); + +static wine_signal_handler handlers[256]; + +/*********************************************************************** + * dispatch_signal + */ +static inline int dispatch_signal(unsigned int sig) +{ + if (handlers[sig] == NULL) return 0; + return handlers[sig](sig); +} + +/*********************************************************************** + * save_context + * + * Set the register values from a sigcontext. + */ +static void save_context( CONTEXT *context, const ucontext_t *sigcontext ) +{ +#define C(x) context->R##x = REGn_sig(x,sigcontext) + /* Save normal registers */ + C(0); C(1); C(2); C(3); C(4); C(5); C(6); C(7); C(8); C(9); C(10); +#undef C + + context->Sp = SP_sig(sigcontext); /* Stack pointer */ + context->Lr = LR_sig(sigcontext); /* Link register */ + context->Pc = PC_sig(sigcontext); /* Program Counter */ + context->Cpsr = CPSR_sig(sigcontext); /* Current State Register */ + context->Ip = IP_sig(sigcontext); /* Intra-Procedure-call scratch register */ + context->Fp = FP_sig(sigcontext); /* Frame pointer */ +} + + +/*********************************************************************** + * restore_context + * + * Build a sigcontext from the register values. + */ +static void restore_context( const CONTEXT *context, ucontext_t *sigcontext ) +{ +#define C(x) REGn_sig(x,sigcontext) = context->R##x + /* Restore normal registers */ + C(0); C(1); C(2); C(3); C(4); C(5); C(6); C(7); C(8); C(9); C(10); +#undef C + + SP_sig(sigcontext) = context->Sp; /* Stack pointer */ + LR_sig(sigcontext) = context->Lr ; /* Link register */ + PC_sig(sigcontext) = context->Pc; /* Program Counter */ + CPSR_sig(sigcontext) = context->Cpsr; /* Current State Register */ + IP_sig(sigcontext) = context->Ip; /* Intra-Procedure-call scratch register */ + FP_sig(sigcontext) = context->Fp; /* Frame pointer */ +} + + +/*********************************************************************** + * save_fpu + * + * Set the FPU context from a sigcontext. + */ +static inline void save_fpu( CONTEXT *context, const ucontext_t *sigcontext ) +{ + FIXME("not implemented\n"); +} + + +/*********************************************************************** + * restore_fpu + * + * Restore the FPU context to a sigcontext. + */ +static inline void restore_fpu( CONTEXT *context, const ucontext_t *sigcontext ) +{ + FIXME("not implemented\n"); +} + + +/*********************************************************************** + * RtlCaptureContext (NTDLL.@) + */ +void WINAPI RtlCaptureContext( CONTEXT *context ) +{ + FIXME("not implemented\n"); + memset( context, 0, sizeof(*context) ); +} + + +/*********************************************************************** + * set_cpu_context + * + * Set the new CPU context. + */ +void set_cpu_context( const CONTEXT *context ) +{ + FIXME("not implemented\n"); + return; +} + + +/*********************************************************************** + * copy_context + * + * Copy a register context according to the flags. + */ +void copy_context( CONTEXT *to, const CONTEXT *from, DWORD flags ) +{ + if (flags & CONTEXT_CONTROL) + { + to->Sp = from->Sp; + to->Lr = from->Lr; + to->Pc = from->Pc; + to->Cpsr = from->Cpsr; + } + if (flags & CONTEXT_INTEGER) + { + to->R0 = from->R0; + to->R1 = from->R1; + to->R2 = from->R2; + to->R3 = from->R3; + to->R4 = from->R4; + to->R5 = from->R5; + to->R6 = from->R6; + to->R7 = from->R7; + to->R8 = from->R8; + to->R9 = from->R9; + to->R10 = from->R10; + to->Ip = from->Ip; + to->Fp = from->Fp; + } +} + + +/*********************************************************************** + * context_to_server + * + * Convert a register context to the server format. + */ +NTSTATUS context_to_server( context_t *to, const CONTEXT *from ) +{ + DWORD flags = from->ContextFlags; /* no CPU id? */ + + memset( to, 0, sizeof(*to) ); + to->cpu = CPU_ARM; + + if (flags & CONTEXT_CONTROL) + { + to->flags |= SERVER_CTX_CONTROL; + to->ctl.arm_regs.sp = from->Sp; + to->ctl.arm_regs.lr = from->Lr; + to->ctl.arm_regs.pc = from->Pc; + to->ctl.arm_regs.cpsr = from->Cpsr; + } + if (flags & CONTEXT_INTEGER) + { + to->flags |= SERVER_CTX_INTEGER; + to->integer.arm_regs.r[0] = from->R0; + to->integer.arm_regs.r[1] = from->R1; + to->integer.arm_regs.r[2] = from->R2; + to->integer.arm_regs.r[3] = from->R3; + to->integer.arm_regs.r[4] = from->R4; + to->integer.arm_regs.r[5] = from->R5; + to->integer.arm_regs.r[6] = from->R6; + to->integer.arm_regs.r[7] = from->R7; + to->integer.arm_regs.r[8] = from->R8; + to->integer.arm_regs.r[9] = from->R9; + to->integer.arm_regs.r[10] = from->R10; + to->integer.arm_regs.r[11] = from->Fp; + to->integer.arm_regs.r[12] = from->Ip; + } + return STATUS_SUCCESS; +} + + +/*********************************************************************** + * context_from_server + * + * Convert a register context from the server format. + */ +NTSTATUS context_from_server( CONTEXT *to, const context_t *from ) +{ + if (from->cpu != CPU_ARM) return STATUS_INVALID_PARAMETER; + + to->ContextFlags = 0; /* no CPU id? */ + if (from->flags & SERVER_CTX_CONTROL) + { + to->ContextFlags |= CONTEXT_CONTROL; + to->Sp = from->ctl.arm_regs.sp; + to->Lr = from->ctl.arm_regs.lr; + to->Pc = from->ctl.arm_regs.pc; + to->Cpsr = from->ctl.arm_regs.cpsr; + } + if (from->flags & SERVER_CTX_INTEGER) + { + to->ContextFlags |= CONTEXT_INTEGER; + to->R0 = from->integer.arm_regs.r[0]; + to->R1 = from->integer.arm_regs.r[1]; + to->R2 = from->integer.arm_regs.r[2]; + to->R3 = from->integer.arm_regs.r[3]; + to->R4 = from->integer.arm_regs.r[4]; + to->R5 = from->integer.arm_regs.r[5]; + to->R6 = from->integer.arm_regs.r[6]; + to->R7 = from->integer.arm_regs.r[7]; + to->R8 = from->integer.arm_regs.r[8]; + to->R9 = from->integer.arm_regs.r[9]; + to->R10 = from->integer.arm_regs.r[10]; + to->Fp = from->integer.arm_regs.r[11]; + to->Ip = from->integer.arm_regs.r[12]; + } + return STATUS_SUCCESS; +} + + +/********************************************************************** + * call_stack_handlers + * + * Call the stack handlers chain. + */ +static NTSTATUS call_stack_handlers( EXCEPTION_RECORD *rec, CONTEXT *context ) +{ + EXCEPTION_POINTERS ptrs; + + FIXME( "not implemented on ARM, exceptioncode: %x\n", rec->ExceptionCode ); + + /* hack: call unhandled exception filter directly */ + ptrs.ExceptionRecord = rec; + ptrs.ContextRecord = context; + unhandled_exception_filter( &ptrs ); + return STATUS_UNHANDLED_EXCEPTION; +} + + +/******************************************************************* + * raise_exception + * + * Implementation of NtRaiseException. + */ +static NTSTATUS raise_exception( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance ) +{ + NTSTATUS status; + + if (first_chance) + { + DWORD c; + + for (c = 0; c < rec->NumberParameters; c++) + TRACE( " info[%d]=%08lx\n", c, rec->ExceptionInformation[c] ); + if (rec->ExceptionCode == EXCEPTION_WINE_STUB) + { + if (rec->ExceptionInformation[1] >> 16) + MESSAGE( "wine: Call from %p to unimplemented function %s.%s, aborting\n", + rec->ExceptionAddress, + (char*)rec->ExceptionInformation[0], (char*)rec->ExceptionInformation[1] ); + else + MESSAGE( "wine: Call from %p to unimplemented function %s.%ld, aborting\n", + rec->ExceptionAddress, + (char*)rec->ExceptionInformation[0], rec->ExceptionInformation[1] ); + } + else + { + /* FIXME: dump context */ + } + + status = send_debug_event( rec, TRUE, context ); + if (status == DBG_CONTINUE || status == DBG_EXCEPTION_HANDLED) + return STATUS_SUCCESS; + + if (call_vectored_handlers( rec, context ) == EXCEPTION_CONTINUE_EXECUTION) + return STATUS_SUCCESS; + + if ((status = call_stack_handlers( rec, context )) != STATUS_UNHANDLED_EXCEPTION) + return status; + } + + /* last chance exception */ + + status = send_debug_event( rec, FALSE, context ); + if (status != DBG_CONTINUE) + { + if (rec->ExceptionFlags & EH_STACK_INVALID) + ERR("Exception frame is not in stack limits => unable to dispatch exception.\n"); + else if (rec->ExceptionCode == STATUS_NONCONTINUABLE_EXCEPTION) + ERR("Process attempted to continue execution after noncontinuable exception.\n"); + else + ERR("Unhandled exception code %x flags %x addr %p\n", + rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress ); + NtTerminateProcess( NtCurrentProcess(), rec->ExceptionCode ); + } + return STATUS_SUCCESS; +} + + +/********************************************************************** + * segv_handler + * + * Handler for SIGSEGV and related errors. + */ +static void segv_handler( int signal, siginfo_t *info, void *ucontext ) +{ + EXCEPTION_RECORD rec; + CONTEXT context; + NTSTATUS status; + + rec.ExceptionCode = EXCEPTION_ACCESS_VIOLATION; + + /* we want the page-fault case to be fast */ + if ( info->si_code == SEGV_ACCERR ) + if (!(rec.ExceptionCode = virtual_handle_fault( info->si_addr, 0 ))) return; + + save_context( &context, ucontext ); + rec.ExceptionRecord = NULL; + rec.ExceptionFlags = EXCEPTION_CONTINUABLE; + rec.ExceptionAddress = (LPVOID)context.Pc; + rec.NumberParameters = 2; + rec.ExceptionInformation[0] = 0; /* FIXME: read/write access ? */ + rec.ExceptionInformation[1] = (ULONG_PTR)info->si_addr; + + status = raise_exception( &rec, &context, TRUE ); + if (status) raise_status( status, &rec ); + restore_context( &context, ucontext ); +} + +/********************************************************************** + * trap_handler + * + * Handler for SIGTRAP. + */ +static void trap_handler( int signal, siginfo_t *info, void *ucontext ) +{ + EXCEPTION_RECORD rec; + CONTEXT context; + NTSTATUS status; + + switch ( info->si_code ) + { + case TRAP_TRACE: + rec.ExceptionCode = EXCEPTION_SINGLE_STEP; + break; + case TRAP_BRKPT: + default: + rec.ExceptionCode = EXCEPTION_BREAKPOINT; + break; + } + + save_context( &context, ucontext ); + rec.ExceptionFlags = EXCEPTION_CONTINUABLE; + rec.ExceptionRecord = NULL; + rec.ExceptionAddress = (LPVOID)context.Pc; + rec.NumberParameters = 0; + status = raise_exception( &rec, &context, TRUE ); + if (status) raise_status( status, &rec ); + restore_context( &context, ucontext ); +} + +/********************************************************************** + * fpe_handler + * + * Handler for SIGFPE. + */ +static void fpe_handler( int signal, siginfo_t *siginfo, void *sigcontext ) +{ + EXCEPTION_RECORD rec; + CONTEXT context; + NTSTATUS status; + + save_fpu( &context, sigcontext ); + save_context( &context, sigcontext ); + + switch (siginfo->si_code & 0xffff ) + { +#ifdef FPE_FLTSUB + case FPE_FLTSUB: + rec.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED; + break; +#endif +#ifdef FPE_INTDIV + case FPE_INTDIV: + rec.ExceptionCode = EXCEPTION_INT_DIVIDE_BY_ZERO; + break; +#endif +#ifdef FPE_INTOVF + case FPE_INTOVF: + rec.ExceptionCode = EXCEPTION_INT_OVERFLOW; + break; +#endif +#ifdef FPE_FLTDIV + case FPE_FLTDIV: + rec.ExceptionCode = EXCEPTION_FLT_DIVIDE_BY_ZERO; + break; +#endif +#ifdef FPE_FLTOVF + case FPE_FLTOVF: + rec.ExceptionCode = EXCEPTION_FLT_OVERFLOW; + break; +#endif +#ifdef FPE_FLTUND + case FPE_FLTUND: + rec.ExceptionCode = EXCEPTION_FLT_UNDERFLOW; + break; +#endif +#ifdef FPE_FLTRES + case FPE_FLTRES: + rec.ExceptionCode = EXCEPTION_FLT_INEXACT_RESULT; + break; +#endif +#ifdef FPE_FLTINV + case FPE_FLTINV: +#endif + default: + rec.ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION; + break; + } + rec.ExceptionFlags = EXCEPTION_CONTINUABLE; + rec.ExceptionRecord = NULL; + /*rec.ExceptionAddress = (LPVOID)context.Iar;*/ + rec.NumberParameters = 0; + status = raise_exception( &rec, &context, TRUE ); + if (status) raise_status( status, &rec ); + + restore_context( &context, sigcontext ); + restore_fpu( &context, sigcontext ); +} + +/********************************************************************** + * int_handler + * + * Handler for SIGINT. + */ +static void int_handler( int signal, siginfo_t *siginfo, void *sigcontext ) +{ + if (!dispatch_signal(SIGINT)) + { + EXCEPTION_RECORD rec; + CONTEXT context; + NTSTATUS status; + + save_context( &context, sigcontext ); + rec.ExceptionCode = CONTROL_C_EXIT; + rec.ExceptionFlags = EXCEPTION_CONTINUABLE; + rec.ExceptionRecord = NULL; + /*rec.ExceptionAddress = (LPVOID)context.Iar;*/ + rec.NumberParameters = 0; + status = raise_exception( &rec, &context, TRUE ); + if (status) raise_status( status, &rec ); + restore_context( &context, sigcontext ); + } +} + + +/********************************************************************** + * abrt_handler + * + * Handler for SIGABRT. + */ +static void abrt_handler( int signal, siginfo_t *siginfo, void *sigcontext ) +{ + EXCEPTION_RECORD rec; + CONTEXT context; + NTSTATUS status; + + save_context( &context, sigcontext ); + rec.ExceptionCode = EXCEPTION_WINE_ASSERTION; + rec.ExceptionFlags = EH_NONCONTINUABLE; + rec.ExceptionRecord = NULL; + /*rec.ExceptionAddress = (LPVOID)context.Iar;*/ + rec.NumberParameters = 0; + status = raise_exception( &rec, &context, TRUE ); + if (status) raise_status( status, &rec ); + restore_context( &context, sigcontext ); +} + + +/********************************************************************** + * quit_handler + * + * Handler for SIGQUIT. + */ +static void quit_handler( int signal, siginfo_t *siginfo, void *sigcontext ) +{ + abort_thread(0); +} + + +/********************************************************************** + * usr1_handler + * + * Handler for SIGUSR1, used to signal a thread that it got suspended. + */ +static void usr1_handler( int signal, siginfo_t *siginfo, void *sigcontext ) +{ + CONTEXT context; + + save_context( &context, sigcontext ); + wait_suspend( &context ); + restore_context( &context, sigcontext ); +} + + +/*********************************************************************** + * __wine_set_signal_handler (NTDLL.@) + */ +int CDECL __wine_set_signal_handler(unsigned int sig, wine_signal_handler wsh) +{ + if (sig > sizeof(handlers) / sizeof(handlers[0])) return -1; + if (handlers[sig] != NULL) return -2; + handlers[sig] = wsh; + return 0; +} + + +/********************************************************************** + * signal_alloc_thread + */ +NTSTATUS signal_alloc_thread( TEB **teb ) +{ + static size_t sigstack_zero_bits; + SIZE_T size; + NTSTATUS status; + + if (!sigstack_zero_bits) + { + size_t min_size = getpagesize(); /* this is just for the TEB, we don't use a signal stack yet */ + /* find the first power of two not smaller than min_size */ + while ((1u << sigstack_zero_bits) < min_size) sigstack_zero_bits++; + assert( sizeof(TEB) <= min_size ); + } + + size = 1 << sigstack_zero_bits; + *teb = NULL; + if (!(status = NtAllocateVirtualMemory( NtCurrentProcess(), (void **)teb, sigstack_zero_bits, + &size, MEM_COMMIT | MEM_TOP_DOWN, PAGE_READWRITE ))) + { + (*teb)->Tib.Self = &(*teb)->Tib; + (*teb)->Tib.ExceptionList = (void *)~0UL; + } + return status; +} + + +/********************************************************************** + * signal_free_thread + */ +void signal_free_thread( TEB *teb ) +{ + SIZE_T size; + + if (teb->DeallocationStack) + { + size = 0; + NtFreeVirtualMemory( GetCurrentProcess(), &teb->DeallocationStack, &size, MEM_RELEASE ); + } + size = 0; + NtFreeVirtualMemory( NtCurrentProcess(), (void **)&teb, &size, MEM_RELEASE ); +} + + +/********************************************************************** + * signal_init_thread + */ +void signal_init_thread( TEB *teb ) +{ + static int init_done; + + if (!init_done) + { + pthread_key_create( &teb_key, NULL ); + init_done = 1; + } + pthread_setspecific( teb_key, teb ); +} + + +/********************************************************************** + * signal_init_process + */ +void signal_init_process(void) +{ + struct sigaction sig_act; + + sig_act.sa_mask = server_block_set; + sig_act.sa_flags = SA_RESTART | SA_SIGINFO; + + sig_act.sa_sigaction = int_handler; + if (sigaction( SIGINT, &sig_act, NULL ) == -1) goto error; + sig_act.sa_sigaction = fpe_handler; + if (sigaction( SIGFPE, &sig_act, NULL ) == -1) goto error; + sig_act.sa_sigaction = abrt_handler; + if (sigaction( SIGABRT, &sig_act, NULL ) == -1) goto error; + sig_act.sa_sigaction = quit_handler; + if (sigaction( SIGQUIT, &sig_act, NULL ) == -1) goto error; + sig_act.sa_sigaction = usr1_handler; + if (sigaction( SIGUSR1, &sig_act, NULL ) == -1) goto error; + + sig_act.sa_sigaction = segv_handler; + if (sigaction( SIGSEGV, &sig_act, NULL ) == -1) goto error; + if (sigaction( SIGILL, &sig_act, NULL ) == -1) goto error; +#ifdef SIGBUS + if (sigaction( SIGBUS, &sig_act, NULL ) == -1) goto error; +#endif + +#ifdef SIGTRAP + sig_act.sa_sigaction = trap_handler; + if (sigaction( SIGTRAP, &sig_act, NULL ) == -1) goto error; +#endif + return; + + error: + perror("sigaction"); + exit(1); +} + + +/********************************************************************** + * __wine_enter_vm86 (NTDLL.@) + */ +void __wine_enter_vm86( CONTEXT *context ) +{ + MESSAGE("vm86 mode not supported on this platform\n"); +} + +/*********************************************************************** + * RtlUnwind (NTDLL.@) + */ +void WINAPI RtlUnwind( PVOID pEndFrame, PVOID targetIp, PEXCEPTION_RECORD pRecord, PVOID retval ) +{ + FIXME( "Not implemented on ARM\n" ); +} + +/******************************************************************* + * NtRaiseException (NTDLL.@) + */ +NTSTATUS WINAPI NtRaiseException( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance ) +{ + NTSTATUS status = raise_exception( rec, context, first_chance ); + if (status == STATUS_SUCCESS) NtSetContextThread( GetCurrentThread(), context ); + return status; +} + +/*********************************************************************** + * RtlRaiseException (NTDLL.@) + */ +void WINAPI RtlRaiseException( EXCEPTION_RECORD *rec ) +{ + CONTEXT context; + NTSTATUS status; + + RtlCaptureContext( &context ); + /*rec->ExceptionAddress = (void *)context.Iar;*/ + status = raise_exception( rec, &context, TRUE ); + if (status) raise_status( status, rec ); +} + +/************************************************************************* + * RtlCaptureStackBackTrace (NTDLL.@) + */ +USHORT WINAPI RtlCaptureStackBackTrace( ULONG skip, ULONG count, PVOID *buffer, ULONG *hash ) +{ + FIXME( "(%d, %d, %p, %p) stub!\n", skip, count, buffer, hash ); + return 0; +} + +/*********************************************************************** + * call_thread_entry_point + */ +void call_thread_entry_point( LPTHREAD_START_ROUTINE entry, void *arg ) +{ + __TRY + { + exit_thread( entry( arg )); + } + __EXCEPT(unhandled_exception_filter) + { + NtTerminateThread( GetCurrentThread(), GetExceptionCode() ); + } + __ENDTRY + abort(); /* should not be reached */ +} + +/*********************************************************************** + * RtlExitUserThread (NTDLL.@) + */ +void WINAPI RtlExitUserThread( ULONG status ) +{ + exit_thread( status ); +} + +/*********************************************************************** + * abort_thread + */ +void abort_thread( int status ) +{ + terminate_thread( status ); +} + +/********************************************************************** + * DbgBreakPoint (NTDLL.@) + */ +void WINAPI DbgBreakPoint(void) +{ + kill(getpid(), SIGTRAP); +} + +/********************************************************************** + * DbgUserBreakPoint (NTDLL.@) + */ +void WINAPI DbgUserBreakPoint(void) +{ + kill(getpid(), SIGTRAP); +} + +/********************************************************************** + * NtCurrentTeb (NTDLL.@) + */ +TEB * WINAPI NtCurrentTeb(void) +{ + return pthread_getspecific( teb_key ); +} + +#endif /* __arm__ */ diff --git a/include/winnt.h b/include/winnt.h index b1f98fffe16..fce9952beea 100644 --- a/include/winnt.h +++ b/include/winnt.h @@ -1314,13 +1314,14 @@ typedef struct _CONTEXT { ULONG R8; ULONG R9; ULONG R10; - ULONG R11; - ULONG R12; + ULONG Fp; + ULONG Ip; + /* These are selected by CONTEXT_CONTROL */ ULONG Sp; ULONG Lr; ULONG Pc; - ULONG Psr; + ULONG Cpsr; } CONTEXT; #endif /* __arm__ */ -- 2.11.4.GIT