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
27 #define NONAMELESSUNION
28 #define NONAMELESSSTRUCT
30 #define WIN32_NO_STATUS
33 #include "wine/exception.h"
34 #include "ntdll_misc.h"
35 #include "wine/debug.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(seh
);
41 /*******************************************************************
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 /**************************************************************************
55 * Incoming r4 contains words to allocate, converting to bytes then return
57 __ASM_GLOBAL_FUNC( __chkstk
, "lsl r4, r4, #2\n\t"
60 /***********************************************************************
61 * RtlCaptureContext (NTDLL.@)
63 __ASM_STDCALL_FUNC( RtlCaptureContext
, 4,
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 */
73 "str r1, [r0, #0x44]\n\t" /* context->Cpsr */
78 /**********************************************************************
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
;
88 frame
= NtCurrentTeb()->Tib
.ExceptionList
;
90 while (frame
!= (EXCEPTION_REGISTRATION_RECORD
*)~0UL)
92 /* Check frame address */
93 if (!is_valid_frame( frame
))
95 rec
->ExceptionFlags
|= EH_STACK_INVALID
;
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 */
109 rec
->ExceptionFlags
&= ~EH_NESTED_CALL
;
114 case ExceptionContinueExecution
:
115 if (!(rec
->ExceptionFlags
& EH_NONCONTINUABLE
)) return STATUS_SUCCESS
;
116 return STATUS_NONCONTINUABLE_EXCEPTION
;
117 case ExceptionContinueSearch
:
119 case ExceptionNestedException
:
120 if (nested_frame
< dispatch
) nested_frame
= dispatch
;
121 rec
->ExceptionFlags
|= EH_NESTED_CALL
;
124 return STATUS_INVALID_DISPOSITION
;
128 return STATUS_UNHANDLED_EXCEPTION
;
132 /*******************************************************************
133 * KiUserExceptionDispatcher (NTDLL.@)
135 NTSTATUS WINAPI
KiUserExceptionDispatcher( EXCEPTION_RECORD
*rec
, CONTEXT
*context
)
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] );
153 MESSAGE( "wine: Call from %p to unimplemented function %s.%ld, aborting\n",
154 rec
->ExceptionAddress
,
155 (char*)rec
->ExceptionInformation
[0], rec
->ExceptionInformation
[1] );
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
)
184 EXCEPTION_RECORD record
;
185 EXCEPTION_REGISTRATION_RECORD
*frame
, *dispatch
;
188 RtlCaptureContext( &context
);
189 context
.R0
= (DWORD
)retval
;
191 /* build an exception record, if we do not have one */
194 record
.ExceptionCode
= STATUS_UNWIND
;
195 record
.ExceptionFlags
= 0;
196 record
.ExceptionRecord
= NULL
;
197 record
.ExceptionAddress
= (void *)context
.Pc
;
198 record
.NumberParameters
= 0;
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
);
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
);
224 case ExceptionContinueSearch
:
226 case ExceptionCollidedUnwind
:
230 raise_status( STATUS_INVALID_DISPOSITION
, rec
);
233 frame
= __wine_pop_frame( frame
);
238 /***********************************************************************
239 * RtlRaiseException (NTDLL.@)
241 __ASM_STDCALL_FUNC( RtlRaiseException
, 4,
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 */
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
);
266 /***********************************************************************
267 * signal_start_thread
269 __ASM_GLOBAL_FUNC( signal_start_thread
,
270 "mov sp, r0\n\t" /* context */
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();