mfplat: Implement GetScanline0AndPitch() for d3d11 buffers.
[wine/zf.git] / dlls / ntdll / signal_arm.c
blob8b0004e0df02d3ef109fa54a54033146537c3588
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 "str r0, [r0, #0x4]\n\t" /* context->R0 */
65 "str r1, [r0, #0x8]\n\t" /* context->R1 */
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 "tst lr, #1\n\t" /* Thumb? */
74 "ite ne\n\t"
75 "orrne r1, r1, #0x20\n\t"
76 "biceq r1, r1, #0x20\n\t"
77 "str r1, [r0, #0x44]\n\t" /* context->Cpsr */
78 "add r0, #0x0c\n\t"
79 "stm r0, {r2-r12}\n\t" /* context->R2..R12 */
80 "bx lr"
84 /**********************************************************************
85 * call_stack_handlers
87 * Call the stack handlers chain.
89 static NTSTATUS call_stack_handlers( EXCEPTION_RECORD *rec, CONTEXT *context )
91 EXCEPTION_REGISTRATION_RECORD *frame, *dispatch, *nested_frame;
92 DWORD res;
94 frame = NtCurrentTeb()->Tib.ExceptionList;
95 nested_frame = NULL;
96 while (frame != (EXCEPTION_REGISTRATION_RECORD*)~0UL)
98 /* Check frame address */
99 if (!is_valid_frame( frame ))
101 rec->ExceptionFlags |= EH_STACK_INVALID;
102 break;
105 /* Call handler */
106 TRACE( "calling handler at %p code=%x flags=%x\n",
107 frame->Handler, rec->ExceptionCode, rec->ExceptionFlags );
108 res = frame->Handler( rec, frame, context, &dispatch );
109 TRACE( "handler at %p returned %x\n", frame->Handler, res );
111 if (frame == nested_frame)
113 /* no longer nested */
114 nested_frame = NULL;
115 rec->ExceptionFlags &= ~EH_NESTED_CALL;
118 switch(res)
120 case ExceptionContinueExecution:
121 if (!(rec->ExceptionFlags & EH_NONCONTINUABLE)) return STATUS_SUCCESS;
122 return STATUS_NONCONTINUABLE_EXCEPTION;
123 case ExceptionContinueSearch:
124 break;
125 case ExceptionNestedException:
126 if (nested_frame < dispatch) nested_frame = dispatch;
127 rec->ExceptionFlags |= EH_NESTED_CALL;
128 break;
129 default:
130 return STATUS_INVALID_DISPOSITION;
132 frame = frame->Prev;
134 return STATUS_UNHANDLED_EXCEPTION;
138 /*******************************************************************
139 * KiUserExceptionDispatcher (NTDLL.@)
141 NTSTATUS WINAPI KiUserExceptionDispatcher( EXCEPTION_RECORD *rec, CONTEXT *context )
143 NTSTATUS status;
144 DWORD c;
146 TRACE( "code=%x flags=%x addr=%p pc=%08x tid=%04x\n",
147 rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress,
148 context->Pc, GetCurrentThreadId() );
149 for (c = 0; c < rec->NumberParameters; c++)
150 TRACE( " info[%d]=%08lx\n", c, rec->ExceptionInformation[c] );
152 if (rec->ExceptionCode == EXCEPTION_WINE_STUB)
154 if (rec->ExceptionInformation[1] >> 16)
155 MESSAGE( "wine: Call from %p to unimplemented function %s.%s, aborting\n",
156 rec->ExceptionAddress,
157 (char*)rec->ExceptionInformation[0], (char*)rec->ExceptionInformation[1] );
158 else
159 MESSAGE( "wine: Call from %p to unimplemented function %s.%ld, aborting\n",
160 rec->ExceptionAddress,
161 (char*)rec->ExceptionInformation[0], rec->ExceptionInformation[1] );
163 else if (rec->ExceptionCode == EXCEPTION_WINE_NAME_THREAD && rec->ExceptionInformation[0] == 0x1000)
165 WARN( "Thread %04x renamed to %s\n", (DWORD)rec->ExceptionInformation[2], debugstr_a((char *)rec->ExceptionInformation[1]) );
167 else if (rec->ExceptionCode == DBG_PRINTEXCEPTION_C)
169 WARN( "%s\n", debugstr_an((char *)rec->ExceptionInformation[1], rec->ExceptionInformation[0] - 1) );
171 else if (rec->ExceptionCode == DBG_PRINTEXCEPTION_WIDE_C)
173 WARN( "%s\n", debugstr_wn((WCHAR *)rec->ExceptionInformation[1], rec->ExceptionInformation[0] - 1) );
175 else
177 if (rec->ExceptionCode == STATUS_ASSERTION_FAILURE)
178 ERR( "%s exception (code=%x) raised\n", debugstr_exception_code(rec->ExceptionCode), rec->ExceptionCode );
179 else
180 WARN( "%s exception (code=%x) raised\n", debugstr_exception_code(rec->ExceptionCode), rec->ExceptionCode );
182 TRACE( " r0=%08x r1=%08x r2=%08x r3=%08x r4=%08x r5=%08x\n",
183 context->R0, context->R1, context->R2, context->R3, context->R4, context->R5 );
184 TRACE( " r6=%08x r7=%08x r8=%08x r9=%08x r10=%08x r11=%08x\n",
185 context->R6, context->R7, context->R8, context->R9, context->R10, context->R11 );
186 TRACE( " r12=%08x sp=%08x lr=%08x pc=%08x cpsr=%08x\n",
187 context->R12, context->Sp, context->Lr, context->Pc, context->Cpsr );
190 if (call_vectored_handlers( rec, context ) == EXCEPTION_CONTINUE_EXECUTION)
191 NtContinue( context, FALSE );
193 if ((status = call_stack_handlers( rec, context )) == STATUS_SUCCESS)
194 NtContinue( context, FALSE );
196 if (status != STATUS_UNHANDLED_EXCEPTION) RtlRaiseStatus( status );
197 return NtRaiseException( rec, context, FALSE );
201 /*******************************************************************
202 * KiUserApcDispatcher (NTDLL.@)
204 void WINAPI KiUserApcDispatcher( CONTEXT *context, ULONG_PTR ctx, ULONG_PTR arg1, ULONG_PTR arg2,
205 PNTAPCFUNC func )
207 func( ctx, arg1, arg2 );
208 NtContinue( context, TRUE );
212 /***********************************************************************
213 * RtlUnwind (NTDLL.@)
215 void WINAPI RtlUnwind( void *endframe, void *target_ip, EXCEPTION_RECORD *rec, void *retval )
217 CONTEXT context;
218 EXCEPTION_RECORD record;
219 EXCEPTION_REGISTRATION_RECORD *frame, *dispatch;
220 DWORD res;
222 RtlCaptureContext( &context );
223 context.R0 = (DWORD)retval;
225 /* build an exception record, if we do not have one */
226 if (!rec)
228 record.ExceptionCode = STATUS_UNWIND;
229 record.ExceptionFlags = 0;
230 record.ExceptionRecord = NULL;
231 record.ExceptionAddress = (void *)context.Pc;
232 record.NumberParameters = 0;
233 rec = &record;
236 rec->ExceptionFlags |= EH_UNWINDING | (endframe ? 0 : EH_EXIT_UNWIND);
238 TRACE( "code=%x flags=%x\n", rec->ExceptionCode, rec->ExceptionFlags );
240 /* get chain of exception frames */
241 frame = NtCurrentTeb()->Tib.ExceptionList;
242 while ((frame != (EXCEPTION_REGISTRATION_RECORD*)~0UL) && (frame != endframe))
244 /* Check frame address */
245 if (endframe && ((void*)frame > endframe))
246 raise_status( STATUS_INVALID_UNWIND_TARGET, rec );
248 if (!is_valid_frame( frame )) raise_status( STATUS_BAD_STACK, rec );
250 /* Call handler */
251 TRACE( "calling handler at %p code=%x flags=%x\n",
252 frame->Handler, rec->ExceptionCode, rec->ExceptionFlags );
253 res = frame->Handler(rec, frame, &context, &dispatch);
254 TRACE( "handler at %p returned %x\n", frame->Handler, res );
256 switch(res)
258 case ExceptionContinueSearch:
259 break;
260 case ExceptionCollidedUnwind:
261 frame = dispatch;
262 break;
263 default:
264 raise_status( STATUS_INVALID_DISPOSITION, rec );
265 break;
267 frame = __wine_pop_frame( frame );
272 /***********************************************************************
273 * RtlRaiseException (NTDLL.@)
275 __ASM_STDCALL_FUNC( RtlRaiseException, 4,
276 "push {r0, lr}\n\t"
277 "sub sp, sp, #0x1a0\n\t" /* sizeof(CONTEXT) */
278 "mov r0, sp\n\t" /* context */
279 "bl " __ASM_NAME("RtlCaptureContext") "\n\t"
280 "ldr r0, [sp, #0x1a0]\n\t" /* rec */
281 "ldr r1, [sp, #0x1a4]\n\t"
282 "str r1, [sp, #0x40]\n\t" /* context->Pc */
283 "ldr r2, [sp, #0x44]\n\t" /* context->Cpsr */
284 "tst r1, #1\n\t" /* Thumb? */
285 "ite ne\n\t"
286 "orrne r2, r2, #0x20\n\t"
287 "biceq r2, r2, #0x20\n\t"
288 "str r2, [sp, #0x44]\n\t" /* context->Cpsr */
289 "str r1, [r0, #12]\n\t" /* rec->ExceptionAddress */
290 "add r1, sp, #0x1a8\n\t"
291 "str r1, [sp, #0x38]\n\t" /* context->Sp */
292 "mov r1, sp\n\t"
293 "mov r2, #1\n\t"
294 "bl " __ASM_NAME("NtRaiseException") "\n\t"
295 "bl " __ASM_NAME("RtlRaiseStatus") )
297 /*************************************************************************
298 * RtlCaptureStackBackTrace (NTDLL.@)
300 USHORT WINAPI RtlCaptureStackBackTrace( ULONG skip, ULONG count, PVOID *buffer, ULONG *hash )
302 FIXME( "(%d, %d, %p, %p) stub!\n", skip, count, buffer, hash );
303 return 0;
306 /***********************************************************************
307 * signal_start_thread
309 __ASM_GLOBAL_FUNC( signal_start_thread,
310 "mov sp, r0\n\t" /* context */
311 "mov r1, #1\n\t"
312 "b " __ASM_NAME("NtContinue") )
314 /**********************************************************************
315 * DbgBreakPoint (NTDLL.@)
317 __ASM_STDCALL_FUNC( DbgBreakPoint, 0, "bkpt #0; bx lr; nop; nop; nop; nop" );
319 /**********************************************************************
320 * DbgUserBreakPoint (NTDLL.@)
322 __ASM_STDCALL_FUNC( DbgUserBreakPoint, 0, "bkpt #0; bx lr; nop; nop; nop; nop" );
324 #endif /* __arm__ */