kernel32: Move ReadConsole and WriteConsole to kernelbase.
[wine.git] / dlls / ntdll / signal_arm.c
blob0e80a35b0c0b75680876cf52f4da2967a979dc62
1 /*
2 * ARM signal handling routines
4 * Copyright 2002 Marcus Meissner, SuSE Linux AG
5 * Copyright 2010-2013, 2015 André Hentschel
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #ifdef __arm__
24 #include <stdlib.h>
25 #include <stdarg.h>
27 #define NONAMELESSUNION
28 #define NONAMELESSSTRUCT
29 #include "ntstatus.h"
30 #define WIN32_NO_STATUS
31 #include "windef.h"
32 #include "winternl.h"
33 #include "wine/exception.h"
34 #include "ntdll_misc.h"
35 #include "wine/debug.h"
36 #include "winnt.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(seh);
41 /*******************************************************************
42 * is_valid_frame
44 static inline BOOL is_valid_frame( void *frame )
46 if ((ULONG_PTR)frame & 3) return FALSE;
47 return (frame >= NtCurrentTeb()->Tib.StackLimit &&
48 (void **)frame < (void **)NtCurrentTeb()->Tib.StackBase - 1);
52 /**************************************************************************
53 * __chkstk (NTDLL.@)
55 * Incoming r4 contains words to allocate, converting to bytes then return
57 __ASM_GLOBAL_FUNC( __chkstk, "lsl r4, r4, #2\n\t"
58 "bx lr" )
60 /***********************************************************************
61 * RtlCaptureContext (NTDLL.@)
63 __ASM_STDCALL_FUNC( RtlCaptureContext, 4,
64 ".arm\n\t"
65 "stmib r0, {r0-r12}\n\t" /* context->R0..R12 */
66 "mov r1, #0x0200000\n\t" /* CONTEXT_ARM */
67 "add r1, r1, #0x3\n\t" /* CONTEXT_FULL */
68 "str r1, [r0]\n\t" /* context->ContextFlags */
69 "str SP, [r0, #0x38]\n\t" /* context->Sp */
70 "str LR, [r0, #0x3c]\n\t" /* context->Lr */
71 "str LR, [r0, #0x40]\n\t" /* context->Pc */
72 "mrs r1, CPSR\n\t"
73 "str r1, [r0, #0x44]\n\t" /* context->Cpsr */
74 "bx lr"
78 /**********************************************************************
79 * call_stack_handlers
81 * Call the stack handlers chain.
83 static NTSTATUS call_stack_handlers( EXCEPTION_RECORD *rec, CONTEXT *context )
85 EXCEPTION_REGISTRATION_RECORD *frame, *dispatch, *nested_frame;
86 DWORD res;
88 frame = NtCurrentTeb()->Tib.ExceptionList;
89 nested_frame = NULL;
90 while (frame != (EXCEPTION_REGISTRATION_RECORD*)~0UL)
92 /* Check frame address */
93 if (!is_valid_frame( frame ))
95 rec->ExceptionFlags |= EH_STACK_INVALID;
96 break;
99 /* Call handler */
100 TRACE( "calling handler at %p code=%x flags=%x\n",
101 frame->Handler, rec->ExceptionCode, rec->ExceptionFlags );
102 res = frame->Handler( rec, frame, context, &dispatch );
103 TRACE( "handler at %p returned %x\n", frame->Handler, res );
105 if (frame == nested_frame)
107 /* no longer nested */
108 nested_frame = NULL;
109 rec->ExceptionFlags &= ~EH_NESTED_CALL;
112 switch(res)
114 case ExceptionContinueExecution:
115 if (!(rec->ExceptionFlags & EH_NONCONTINUABLE)) return STATUS_SUCCESS;
116 return STATUS_NONCONTINUABLE_EXCEPTION;
117 case ExceptionContinueSearch:
118 break;
119 case ExceptionNestedException:
120 if (nested_frame < dispatch) nested_frame = dispatch;
121 rec->ExceptionFlags |= EH_NESTED_CALL;
122 break;
123 default:
124 return STATUS_INVALID_DISPOSITION;
126 frame = frame->Prev;
128 return STATUS_UNHANDLED_EXCEPTION;
132 /*******************************************************************
133 * KiUserExceptionDispatcher (NTDLL.@)
135 NTSTATUS WINAPI KiUserExceptionDispatcher( EXCEPTION_RECORD *rec, CONTEXT *context )
137 NTSTATUS status;
138 DWORD c;
140 TRACE( "code=%x flags=%x addr=%p pc=%08x tid=%04x\n",
141 rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress,
142 context->Pc, GetCurrentThreadId() );
143 for (c = 0; c < rec->NumberParameters; c++)
144 TRACE( " info[%d]=%08lx\n", c, rec->ExceptionInformation[c] );
146 if (rec->ExceptionCode == EXCEPTION_WINE_STUB)
148 if (rec->ExceptionInformation[1] >> 16)
149 MESSAGE( "wine: Call from %p to unimplemented function %s.%s, aborting\n",
150 rec->ExceptionAddress,
151 (char*)rec->ExceptionInformation[0], (char*)rec->ExceptionInformation[1] );
152 else
153 MESSAGE( "wine: Call from %p to unimplemented function %s.%ld, aborting\n",
154 rec->ExceptionAddress,
155 (char*)rec->ExceptionInformation[0], rec->ExceptionInformation[1] );
157 else
159 TRACE( " r0=%08x r1=%08x r2=%08x r3=%08x r4=%08x r5=%08x\n",
160 context->R0, context->R1, context->R2, context->R3, context->R4, context->R5 );
161 TRACE( " r6=%08x r7=%08x r8=%08x r9=%08x r10=%08x r11=%08x\n",
162 context->R6, context->R7, context->R8, context->R9, context->R10, context->R11 );
163 TRACE( " r12=%08x sp=%08x lr=%08x pc=%08x cpsr=%08x\n",
164 context->R12, context->Sp, context->Lr, context->Pc, context->Cpsr );
167 if (call_vectored_handlers( rec, context ) == EXCEPTION_CONTINUE_EXECUTION)
168 NtContinue( context, FALSE );
170 if ((status = call_stack_handlers( rec, context )) == STATUS_SUCCESS)
171 NtContinue( context, FALSE );
173 if (status != STATUS_UNHANDLED_EXCEPTION) RtlRaiseStatus( status );
174 return NtRaiseException( rec, context, FALSE );
178 /***********************************************************************
179 * RtlUnwind (NTDLL.@)
181 void WINAPI RtlUnwind( void *endframe, void *target_ip, EXCEPTION_RECORD *rec, void *retval )
183 CONTEXT context;
184 EXCEPTION_RECORD record;
185 EXCEPTION_REGISTRATION_RECORD *frame, *dispatch;
186 DWORD res;
188 RtlCaptureContext( &context );
189 context.R0 = (DWORD)retval;
191 /* build an exception record, if we do not have one */
192 if (!rec)
194 record.ExceptionCode = STATUS_UNWIND;
195 record.ExceptionFlags = 0;
196 record.ExceptionRecord = NULL;
197 record.ExceptionAddress = (void *)context.Pc;
198 record.NumberParameters = 0;
199 rec = &record;
202 rec->ExceptionFlags |= EH_UNWINDING | (endframe ? 0 : EH_EXIT_UNWIND);
204 TRACE( "code=%x flags=%x\n", rec->ExceptionCode, rec->ExceptionFlags );
206 /* get chain of exception frames */
207 frame = NtCurrentTeb()->Tib.ExceptionList;
208 while ((frame != (EXCEPTION_REGISTRATION_RECORD*)~0UL) && (frame != endframe))
210 /* Check frame address */
211 if (endframe && ((void*)frame > endframe))
212 raise_status( STATUS_INVALID_UNWIND_TARGET, rec );
214 if (!is_valid_frame( frame )) raise_status( STATUS_BAD_STACK, rec );
216 /* Call handler */
217 TRACE( "calling handler at %p code=%x flags=%x\n",
218 frame->Handler, rec->ExceptionCode, rec->ExceptionFlags );
219 res = frame->Handler(rec, frame, &context, &dispatch);
220 TRACE( "handler at %p returned %x\n", frame->Handler, res );
222 switch(res)
224 case ExceptionContinueSearch:
225 break;
226 case ExceptionCollidedUnwind:
227 frame = dispatch;
228 break;
229 default:
230 raise_status( STATUS_INVALID_DISPOSITION, rec );
231 break;
233 frame = __wine_pop_frame( frame );
238 /***********************************************************************
239 * RtlRaiseException (NTDLL.@)
241 __ASM_STDCALL_FUNC( RtlRaiseException, 4,
242 "push {r0, lr}\n\t"
243 "sub sp, sp, #0x1a0\n\t" /* sizeof(CONTEXT) */
244 "mov r0, sp\n\t" /* context */
245 "bl " __ASM_NAME("RtlCaptureContext") "\n\t"
246 "ldr r0, [sp, #0x1a0]\n\t" /* rec */
247 "ldr r1, [sp, #0x1a4]\n\t"
248 "str r1, [sp, #0x40]\n\t" /* context->Pc */
249 "str r1, [r0, #12]\n\t" /* rec->ExceptionAddress */
250 "add r1, sp, #0x1a8\n\t"
251 "str r1, [sp, #0x38]\n\t" /* context->Sp */
252 "mov r1, sp\n\t"
253 "mov r2, #1\n\t"
254 "bl " __ASM_NAME("NtRaiseException") "\n\t"
255 "bl " __ASM_NAME("RtlRaiseStatus") )
257 /*************************************************************************
258 * RtlCaptureStackBackTrace (NTDLL.@)
260 USHORT WINAPI RtlCaptureStackBackTrace( ULONG skip, ULONG count, PVOID *buffer, ULONG *hash )
262 FIXME( "(%d, %d, %p, %p) stub!\n", skip, count, buffer, hash );
263 return 0;
266 /***********************************************************************
267 * signal_start_thread
269 __ASM_GLOBAL_FUNC( signal_start_thread,
270 "mov sp, r0\n\t" /* context */
271 "mov r1, #1\n\t"
272 "b " __ASM_NAME("NtContinue") )
274 /**********************************************************************
275 * DbgBreakPoint (NTDLL.@)
277 __ASM_STDCALL_FUNC( DbgBreakPoint, 0, "bkpt #0; bx lr; nop; nop; nop; nop" );
279 /**********************************************************************
280 * DbgUserBreakPoint (NTDLL.@)
282 __ASM_STDCALL_FUNC( DbgUserBreakPoint, 0, "bkpt #0; bx lr; nop; nop; nop; nop" );
284 /**********************************************************************
285 * NtCurrentTeb (NTDLL.@)
287 TEB * WINAPI NtCurrentTeb(void)
289 return unix_funcs->NtCurrentTeb();
292 #endif /* __arm__ */