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
29 #define WIN32_NO_STATUS
32 #include "wine/exception.h"
33 #include "ntdll_misc.h"
34 #include "wine/debug.h"
35 #include "ntsyscalls.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(seh
);
38 WINE_DECLARE_DEBUG_CHANNEL(relay
);
41 /* undocumented, copied from the corresponding ARM64 structure */
42 typedef union _DISPATCHER_CONTEXT_NONVOLREG_ARM
44 BYTE Buffer
[8 * sizeof(DWORD
) + 8 * sizeof(double)];
50 } DISPATCHER_CONTEXT_NONVOLREG_ARM
;
53 /*******************************************************************
56 #define SYSCALL_ENTRY(id,name,args) __ASM_SYSCALL_FUNC( id, name, args )
58 DEFINE_SYSCALL_HELPER32()
62 /**************************************************************************
65 * Incoming r4 contains words to allocate, converting to bytes then return
67 __ASM_GLOBAL_FUNC( __chkstk
, "lsl r4, r4, #2\n\t"
70 /***********************************************************************
71 * RtlCaptureContext (NTDLL.@)
73 __ASM_GLOBAL_FUNC( RtlCaptureContext
,
74 "str r1, [r0, #0x8]\n\t" /* context->R1 */
75 "mov r1, #0x0200000\n\t" /* CONTEXT_ARM */
76 "add r1, r1, #0x7\n\t" /* CONTEXT_CONTROL|CONTEXT_INTEGER|CONTEXT_FLOATING_POINT */
77 "str r1, [r0]\n\t" /* context->ContextFlags */
78 "str SP, [r0, #0x38]\n\t" /* context->Sp */
79 "str LR, [r0, #0x40]\n\t" /* context->Pc */
81 "bfi r1, lr, #5, #1\n\t" /* Thumb bit */
82 "str r1, [r0, #0x44]\n\t" /* context->Cpsr */
84 "str r1, [r0, #0x4]\n\t" /* context->R0 */
85 "str r1, [r0, #0x3c]\n\t" /* context->Lr */
87 "stm r0, {r2-r12}\n\t" /* context->R2..R12 */
88 "add r0, #0x44\n\t" /* 0x50 - 0x0c */
89 "vstm r0, {d0-d15}\n\t" /* context->D0-D15 */
93 /**********************************************************************
96 static NTSTATUS
virtual_unwind( ULONG type
, DISPATCHER_CONTEXT
*dispatch
, CONTEXT
*context
)
98 DISPATCHER_CONTEXT_NONVOLREG_ARM
*nonvol_regs
;
99 DWORD pc
= context
->Pc
;
101 dispatch
->ScopeIndex
= 0;
102 dispatch
->ControlPc
= pc
;
103 dispatch
->ControlPcIsUnwound
= (context
->ContextFlags
& CONTEXT_UNWOUND_TO_CALL
) != 0;
104 if (dispatch
->ControlPcIsUnwound
) pc
-= 2;
106 nonvol_regs
= (DISPATCHER_CONTEXT_NONVOLREG_ARM
*)dispatch
->NonVolatileRegisters
;
107 memcpy( nonvol_regs
->GpNvRegs
, &context
->R4
, sizeof(nonvol_regs
->GpNvRegs
) );
108 memcpy( nonvol_regs
->FpNvRegs
, &context
->D
[8], sizeof(nonvol_regs
->FpNvRegs
) );
110 dispatch
->FunctionEntry
= RtlLookupFunctionEntry( pc
, (DWORD_PTR
*)&dispatch
->ImageBase
,
111 dispatch
->HistoryTable
);
112 if (RtlVirtualUnwind2( type
, dispatch
->ImageBase
, pc
, dispatch
->FunctionEntry
, context
,
113 NULL
, &dispatch
->HandlerData
, (ULONG_PTR
*)&dispatch
->EstablisherFrame
,
114 NULL
, NULL
, NULL
, &dispatch
->LanguageHandler
, 0 ))
116 WARN( "exception data not found for pc %p, lr %p\n", (void *)pc
, (void *)context
->Lr
);
117 return STATUS_INVALID_DISPOSITION
;
119 return STATUS_SUCCESS
;
123 /**********************************************************************
124 * unwind_exception_handler
126 * Handler for exceptions happening while calling an unwind handler.
128 EXCEPTION_DISPOSITION WINAPI
unwind_exception_handler( EXCEPTION_RECORD
*record
, void *frame
,
129 CONTEXT
*context
, DISPATCHER_CONTEXT
*dispatch
)
131 DISPATCHER_CONTEXT
*orig_dispatch
= ((DISPATCHER_CONTEXT
**)frame
)[-2];
133 /* copy the original dispatcher into the current one, except for the TargetIp */
134 dispatch
->ControlPc
= orig_dispatch
->ControlPc
;
135 dispatch
->ImageBase
= orig_dispatch
->ImageBase
;
136 dispatch
->FunctionEntry
= orig_dispatch
->FunctionEntry
;
137 dispatch
->EstablisherFrame
= orig_dispatch
->EstablisherFrame
;
138 dispatch
->LanguageHandler
= orig_dispatch
->LanguageHandler
;
139 dispatch
->HandlerData
= orig_dispatch
->HandlerData
;
140 dispatch
->HistoryTable
= orig_dispatch
->HistoryTable
;
141 dispatch
->ScopeIndex
= orig_dispatch
->ScopeIndex
;
142 dispatch
->ControlPcIsUnwound
= orig_dispatch
->ControlPcIsUnwound
;
143 *dispatch
->ContextRecord
= *orig_dispatch
->ContextRecord
;
144 memcpy( dispatch
->NonVolatileRegisters
, orig_dispatch
->NonVolatileRegisters
,
145 sizeof(DISPATCHER_CONTEXT_NONVOLREG_ARM
) );
146 TRACE( "detected collided unwind\n" );
147 return ExceptionCollidedUnwind
;
151 /**********************************************************************
152 * call_unwind_handler
154 DWORD WINAPI
call_unwind_handler( EXCEPTION_RECORD
*rec
, ULONG_PTR frame
,
155 CONTEXT
*context
, void *dispatch
, PEXCEPTION_ROUTINE handler
);
156 __ASM_GLOBAL_FUNC( call_unwind_handler
,
158 ".seh_save_regs {r3,lr}\n\t"
159 ".seh_endprologue\n\t"
160 ".seh_handler unwind_exception_handler, %except\n\t"
161 "ldr ip, [sp, #8]\n\t" /* handler */
166 /***********************************************************************
169 DWORD WINAPI
call_seh_handler( EXCEPTION_RECORD
*rec
, ULONG_PTR frame
,
170 CONTEXT
*context
, void *dispatch
, PEXCEPTION_ROUTINE handler
);
171 __ASM_GLOBAL_FUNC( call_seh_handler
,
173 ".seh_save_regs {r4,lr}\n\t"
174 ".seh_endprologue\n\t"
175 ".seh_handler nested_exception_handler, %except\n\t"
176 "ldr ip, [sp, #8]\n\t" /* handler */
181 /**********************************************************************
184 * Call the SEH handlers.
186 NTSTATUS
call_seh_handlers( EXCEPTION_RECORD
*rec
, CONTEXT
*orig_context
)
188 EXCEPTION_REGISTRATION_RECORD
*teb_frame
= NtCurrentTeb()->Tib
.ExceptionList
;
189 DISPATCHER_CONTEXT_NONVOLREG_ARM nonvol_regs
;
190 UNWIND_HISTORY_TABLE table
;
191 DISPATCHER_CONTEXT dispatch
;
197 context
= *orig_context
;
198 dispatch
.TargetPc
= 0;
199 dispatch
.ContextRecord
= &context
;
200 dispatch
.HistoryTable
= &table
;
201 dispatch
.NonVolatileRegisters
= nonvol_regs
.Buffer
;
205 status
= virtual_unwind( UNW_FLAG_EHANDLER
, &dispatch
, &context
);
206 if (status
!= STATUS_SUCCESS
) return status
;
209 if (!dispatch
.EstablisherFrame
) break;
211 if (!is_valid_frame( dispatch
.EstablisherFrame
))
213 ERR( "invalid frame %lx (%p-%p)\n", dispatch
.EstablisherFrame
,
214 NtCurrentTeb()->Tib
.StackLimit
, NtCurrentTeb()->Tib
.StackBase
);
215 rec
->ExceptionFlags
|= EXCEPTION_STACK_INVALID
;
219 if (dispatch
.LanguageHandler
)
221 TRACE( "calling handler %p (rec=%p, frame=%lx context=%p, dispatch=%p)\n",
222 dispatch
.LanguageHandler
, rec
, dispatch
.EstablisherFrame
, orig_context
, &dispatch
);
223 res
= call_seh_handler( rec
, dispatch
.EstablisherFrame
, orig_context
,
224 &dispatch
, dispatch
.LanguageHandler
);
225 rec
->ExceptionFlags
&= EXCEPTION_NONCONTINUABLE
;
226 TRACE( "handler at %p returned %lu\n", dispatch
.LanguageHandler
, res
);
230 case ExceptionContinueExecution
:
231 if (rec
->ExceptionFlags
& EXCEPTION_NONCONTINUABLE
) return STATUS_NONCONTINUABLE_EXCEPTION
;
232 return STATUS_SUCCESS
;
233 case ExceptionContinueSearch
:
235 case ExceptionNestedException
:
236 rec
->ExceptionFlags
|= EXCEPTION_NESTED_CALL
;
237 TRACE( "nested exception\n" );
239 case ExceptionCollidedUnwind
:
240 RtlVirtualUnwind( UNW_FLAG_NHANDLER
, dispatch
.ImageBase
,
241 dispatch
.ControlPc
, dispatch
.FunctionEntry
,
242 &context
, (PVOID
*)&dispatch
.HandlerData
, &frame
, NULL
);
245 return STATUS_INVALID_DISPOSITION
;
248 /* hack: call wine handlers registered in the tib list */
249 else while (is_valid_frame( (ULONG_PTR
)teb_frame
) && (DWORD
)teb_frame
< context
.Sp
)
251 TRACE( "calling TEB handler %p (rec=%p frame=%p context=%p dispatch=%p) sp=%lx\n",
252 teb_frame
->Handler
, rec
, teb_frame
, orig_context
, &dispatch
, context
.Sp
);
253 res
= call_seh_handler( rec
, (ULONG_PTR
)teb_frame
, orig_context
,
254 &dispatch
, (PEXCEPTION_ROUTINE
)teb_frame
->Handler
);
255 TRACE( "TEB handler at %p returned %lu\n", teb_frame
->Handler
, res
);
259 case ExceptionContinueExecution
:
260 if (rec
->ExceptionFlags
& EXCEPTION_NONCONTINUABLE
) return STATUS_NONCONTINUABLE_EXCEPTION
;
261 return STATUS_SUCCESS
;
262 case ExceptionContinueSearch
:
264 case ExceptionNestedException
:
265 rec
->ExceptionFlags
|= EXCEPTION_NESTED_CALL
;
266 TRACE( "nested exception\n" );
268 case ExceptionCollidedUnwind
:
269 RtlVirtualUnwind( UNW_FLAG_NHANDLER
, dispatch
.ImageBase
,
270 dispatch
.ControlPc
, dispatch
.FunctionEntry
,
271 &context
, (PVOID
*)&dispatch
.HandlerData
, &frame
, NULL
);
272 teb_frame
= teb_frame
->Prev
;
275 return STATUS_INVALID_DISPOSITION
;
277 teb_frame
= teb_frame
->Prev
;
280 if (context
.Sp
== (DWORD
)NtCurrentTeb()->Tib
.StackBase
) break;
282 return STATUS_UNHANDLED_EXCEPTION
;
286 /*******************************************************************
287 * KiUserExceptionDispatcher (NTDLL.@)
289 __ASM_GLOBAL_FUNC( KiUserExceptionDispatcher
,
290 ".seh_custom 0xee,0x02\n\t" /* MSFT_OP_CONTEXT */
291 ".seh_endprologue\n\t"
292 "add r0, sp, #0x1a0\n\t" /* rec (context + 1) */
293 "mov r1, sp\n\t" /* context */
294 "bl dispatch_exception\n\t"
298 /*******************************************************************
299 * KiUserApcDispatcher (NTDLL.@)
301 __ASM_GLOBAL_FUNC( KiUserApcDispatcher
,
302 ".seh_custom 0xee,0x02\n\t" /* MSFT_OP_CONTEXT */
304 ".seh_stackalloc 0x18\n\t"
305 ".seh_endprologue\n\t"
306 "ldr r0, [sp, #0x04]\n\t" /* arg1 */
307 "ldr r1, [sp, #0x08]\n\t" /* arg2 */
308 "ldr r2, [sp, #0x0c]\n\t" /* arg3 */
309 "ldr ip, [sp]\n\t" /* func */
311 "add r0, sp, #0x18\n\t" /* context */
312 "ldr r1, [sp, #0x10]\n\t" /* alertable */
317 /*******************************************************************
318 * KiUserCallbackDispatcher (NTDLL.@)
320 __ASM_GLOBAL_FUNC( KiUserCallbackDispatcher
,
321 ".seh_custom 0xee,0x01\n\t" /* MSFT_OP_MACHINE_FRAME */
323 ".seh_save_regs {lr}\n\t"
325 ".seh_stackalloc 0xc\n\t"
326 ".seh_endprologue\n\t"
327 "ldr r0, [sp]\n\t" /* args */
328 "ldr r1, [sp, #0x04]\n\t" /* len */
329 "ldr r2, [sp, #0x08]\n\t" /* id */
330 "mrc p15, 0, r3, c13, c0, 2\n\t" /* NtCurrentTeb() */
331 "ldr r3, [r3, 0x30]\n\t" /* peb */
332 "ldr r3, [r3, 0x2c]\n\t" /* peb->KernelCallbackTable */
333 "ldr ip, [r3, r2, lsl #2]\n\t"
335 ".seh_handler user_callback_handler, %except\n\t"
336 ".globl KiUserCallbackDispatcherReturn\n"
337 "KiUserCallbackDispatcherReturn:\n\t"
338 "mov r2, r0\n\t" /* status */
339 "mov r1, #0\n\t" /* ret_len */
340 "mov r0, r1\n\t" /* ret_ptr */
341 "bl NtCallbackReturn\n\t"
342 "bl RtlRaiseStatus\n\t"
347 /**********************************************************************
348 * consolidate_callback
350 * Wrapper function to call a consolidate callback from a fake frame.
351 * If the callback executes RtlUnwindEx (like for example done in C++ handlers),
352 * we have to skip all frames which were already processed. To do that we
353 * trick the unwinding functions into thinking the call came from somewhere
356 void WINAPI DECLSPEC_NORETURN
consolidate_callback( CONTEXT
*context
,
357 void *(CALLBACK
*callback
)(EXCEPTION_RECORD
*),
358 EXCEPTION_RECORD
*rec
);
359 __ASM_GLOBAL_FUNC( consolidate_callback
,
360 "push {r0-r2,lr}\n\t"
362 "sub sp, sp, #0x1a0\n\t"
371 ".seh_custom 0xee,0x02\n\t" /* MSFT_OP_CONTEXT */
372 ".seh_endprologue\n\t"
373 "ldrd r1, r2, [sp, #0x1a4]\n\t"
376 "str r0, [sp, #0x40]\n\t" /* context->Pc */
383 /*******************************************************************
384 * RtlRestoreContext (NTDLL.@)
386 void CDECL
RtlRestoreContext( CONTEXT
*context
, EXCEPTION_RECORD
*rec
)
388 EXCEPTION_REGISTRATION_RECORD
*teb_frame
= NtCurrentTeb()->Tib
.ExceptionList
;
390 if (rec
&& rec
->ExceptionCode
== STATUS_LONGJUMP
&& rec
->NumberParameters
>= 1)
392 struct _JUMP_BUFFER
*jmp
= (struct _JUMP_BUFFER
*)rec
->ExceptionInformation
[0];
394 memcpy( &context
->R4
, &jmp
->R4
, 8 * sizeof(DWORD
) );
395 memcpy( &context
->D
[8], &jmp
->D
[0], 8 * sizeof(ULONGLONG
) );
396 context
->Pc
= jmp
->Pc
;
397 context
->Sp
= jmp
->Sp
;
398 context
->Fpscr
= jmp
->Fpscr
;
400 else if (rec
&& rec
->ExceptionCode
== STATUS_UNWIND_CONSOLIDATE
&& rec
->NumberParameters
>= 1)
402 PVOID (CALLBACK
*consolidate
)(EXCEPTION_RECORD
*) = (void *)rec
->ExceptionInformation
[0];
403 TRACE( "calling consolidate callback %p (rec=%p)\n", consolidate
, rec
);
404 consolidate_callback( context
, consolidate
, rec
);
407 /* hack: remove no longer accessible TEB frames */
408 while (is_valid_frame( (ULONG_PTR
)teb_frame
) && (DWORD
)teb_frame
< context
->Sp
)
410 TRACE( "removing TEB frame: %p\n", teb_frame
);
411 teb_frame
= __wine_pop_frame( teb_frame
);
414 TRACE( "returning to %lx stack %lx\n", context
->Pc
, context
->Sp
);
415 NtContinue( context
, FALSE
);
419 /***********************************************************************
420 * RtlUnwindEx (NTDLL.@)
422 void WINAPI
RtlUnwindEx( PVOID end_frame
, PVOID target_ip
, EXCEPTION_RECORD
*rec
,
423 PVOID retval
, CONTEXT
*context
, UNWIND_HISTORY_TABLE
*table
)
425 EXCEPTION_REGISTRATION_RECORD
*teb_frame
= NtCurrentTeb()->Tib
.ExceptionList
;
426 DISPATCHER_CONTEXT_NONVOLREG_ARM nonvol_regs
;
427 EXCEPTION_RECORD record
;
428 DISPATCHER_CONTEXT dispatch
;
434 RtlCaptureContext( context
);
435 new_context
= *context
;
437 /* build an exception record, if we do not have one */
440 record
.ExceptionCode
= STATUS_UNWIND
;
441 record
.ExceptionFlags
= 0;
442 record
.ExceptionRecord
= NULL
;
443 record
.ExceptionAddress
= (void *)context
->Pc
;
444 record
.NumberParameters
= 0;
448 rec
->ExceptionFlags
|= EXCEPTION_UNWINDING
| (end_frame
? 0 : EXCEPTION_EXIT_UNWIND
);
450 TRACE( "code=%lx flags=%lx end_frame=%p target_ip=%p\n",
451 rec
->ExceptionCode
, rec
->ExceptionFlags
, end_frame
, target_ip
);
452 for (i
= 0; i
< min( EXCEPTION_MAXIMUM_PARAMETERS
, rec
->NumberParameters
); i
++)
453 TRACE( " info[%ld]=%08Ix\n", i
, rec
->ExceptionInformation
[i
] );
454 TRACE_CONTEXT( context
);
456 dispatch
.TargetPc
= (ULONG_PTR
)target_ip
;
457 dispatch
.ContextRecord
= context
;
458 dispatch
.HistoryTable
= table
;
459 dispatch
.NonVolatileRegisters
= nonvol_regs
.Buffer
;
463 status
= virtual_unwind( UNW_FLAG_UHANDLER
, &dispatch
, &new_context
);
464 if (status
!= STATUS_SUCCESS
) raise_status( status
, rec
);
467 if (!dispatch
.EstablisherFrame
) break;
469 if (!is_valid_frame( dispatch
.EstablisherFrame
))
471 ERR( "invalid frame %lx (%p-%p)\n", dispatch
.EstablisherFrame
,
472 NtCurrentTeb()->Tib
.StackLimit
, NtCurrentTeb()->Tib
.StackBase
);
473 rec
->ExceptionFlags
|= EXCEPTION_STACK_INVALID
;
477 if (dispatch
.LanguageHandler
)
479 if (end_frame
&& (dispatch
.EstablisherFrame
> (DWORD
)end_frame
))
481 ERR( "invalid end frame %lx/%p\n", dispatch
.EstablisherFrame
, end_frame
);
482 raise_status( STATUS_INVALID_UNWIND_TARGET
, rec
);
484 if (dispatch
.EstablisherFrame
== (DWORD
)end_frame
) rec
->ExceptionFlags
|= EXCEPTION_TARGET_UNWIND
;
486 TRACE( "calling handler %p (rec=%p, frame=0x%lx context=%p, dispatch=%p)\n",
487 dispatch
.LanguageHandler
, rec
, dispatch
.EstablisherFrame
,
488 dispatch
.ContextRecord
, &dispatch
);
489 res
= call_unwind_handler( rec
, dispatch
.EstablisherFrame
, dispatch
.ContextRecord
,
490 &dispatch
, dispatch
.LanguageHandler
);
491 TRACE( "handler %p returned %lx\n", dispatch
.LanguageHandler
, res
);
495 case ExceptionContinueSearch
:
496 rec
->ExceptionFlags
&= ~EXCEPTION_COLLIDED_UNWIND
;
498 case ExceptionCollidedUnwind
:
499 new_context
= *context
;
500 RtlVirtualUnwind( UNW_FLAG_NHANDLER
, dispatch
.ImageBase
,
501 dispatch
.ControlPc
, dispatch
.FunctionEntry
,
502 &new_context
, &dispatch
.HandlerData
, &frame
,
504 rec
->ExceptionFlags
|= EXCEPTION_COLLIDED_UNWIND
;
507 raise_status( STATUS_INVALID_DISPOSITION
, rec
);
511 else /* hack: call builtin handlers registered in the tib list */
513 while (is_valid_frame( (ULONG_PTR
)teb_frame
) &&
514 (DWORD
)teb_frame
< new_context
.Sp
&&
515 (DWORD
)teb_frame
< (DWORD
)end_frame
)
517 TRACE( "calling TEB handler %p (rec=%p, frame=%p context=%p, dispatch=%p)\n",
518 teb_frame
->Handler
, rec
, teb_frame
, dispatch
.ContextRecord
, &dispatch
);
519 res
= call_unwind_handler( rec
, (ULONG_PTR
)teb_frame
, dispatch
.ContextRecord
, &dispatch
,
520 (PEXCEPTION_ROUTINE
)teb_frame
->Handler
);
521 TRACE( "handler at %p returned %lu\n", teb_frame
->Handler
, res
);
522 teb_frame
= __wine_pop_frame( teb_frame
);
526 case ExceptionContinueSearch
:
527 rec
->ExceptionFlags
&= ~EXCEPTION_COLLIDED_UNWIND
;
529 case ExceptionCollidedUnwind
:
530 new_context
= *context
;
531 RtlVirtualUnwind( UNW_FLAG_NHANDLER
, dispatch
.ImageBase
,
532 dispatch
.ControlPc
, dispatch
.FunctionEntry
,
533 &new_context
, &dispatch
.HandlerData
,
535 rec
->ExceptionFlags
|= EXCEPTION_COLLIDED_UNWIND
;
538 raise_status( STATUS_INVALID_DISPOSITION
, rec
);
542 if ((DWORD
)teb_frame
== (DWORD
)end_frame
&& (DWORD
)end_frame
< new_context
.Sp
) break;
545 if (dispatch
.EstablisherFrame
== (DWORD
)end_frame
) break;
546 *context
= new_context
;
549 if (rec
->ExceptionCode
!= STATUS_UNWIND_CONSOLIDATE
)
550 context
->Pc
= (DWORD
)target_ip
;
551 else if (rec
->ExceptionInformation
[10] == -1)
552 rec
->ExceptionInformation
[10] = (ULONG_PTR
)&nonvol_regs
;
554 context
->R0
= (DWORD
)retval
;
555 RtlRestoreContext(context
, rec
);
559 /*************************************************************************
560 * RtlGetNativeSystemInformation (NTDLL.@)
562 NTSTATUS WINAPI
RtlGetNativeSystemInformation( SYSTEM_INFORMATION_CLASS
class,
563 void *info
, ULONG size
, ULONG
*ret_size
)
565 return NtWow64GetNativeSystemInformation( class, info
, size
, ret_size
);
569 /***********************************************************************
570 * RtlIsProcessorFeaturePresent [NTDLL.@]
572 BOOLEAN WINAPI
RtlIsProcessorFeaturePresent( UINT feature
)
574 return NtWow64IsProcessorFeaturePresent( feature
);
578 /*************************************************************************
579 * RtlWalkFrameChain (NTDLL.@)
581 ULONG WINAPI
RtlWalkFrameChain( void **buffer
, ULONG count
, ULONG flags
)
583 UNWIND_HISTORY_TABLE table
;
584 RUNTIME_FUNCTION
*func
;
585 PEXCEPTION_ROUTINE handler
;
586 ULONG_PTR pc
, frame
, base
;
589 ULONG i
, skip
= flags
>> 8, num_entries
= 0;
591 RtlCaptureContext( &context
);
593 for (i
= 0; i
< count
; i
++)
596 if (context
.ContextFlags
& CONTEXT_UNWOUND_TO_CALL
) pc
-= 2;
597 func
= RtlLookupFunctionEntry( pc
, &base
, &table
);
598 if (RtlVirtualUnwind2( UNW_FLAG_NHANDLER
, base
, pc
, func
, &context
, NULL
,
599 &data
, &frame
, NULL
, NULL
, NULL
, &handler
, 0 ))
601 if (!context
.Pc
) break;
602 if (!frame
|| !is_valid_frame( frame
)) break;
603 if (context
.Sp
== (ULONG_PTR
)NtCurrentTeb()->Tib
.StackBase
) break;
604 if (i
>= skip
) buffer
[num_entries
++] = (void *)context
.Pc
;
610 /*******************************************************************
611 * __C_ExecuteExceptionFilter
613 __ASM_GLOBAL_FUNC( __C_ExecuteExceptionFilter
,
614 "push {r3-r11,lr}\n\t"
615 ".seh_save_regs_w {r3-r11,lr}\n\t"
616 ".seh_endprologue\n\t"
617 "ldm r3, {r4-r11}\n\t"
619 "pop {r3-r11,pc}\n\t" )
622 /***********************************************************************
623 * RtlRaiseException (NTDLL.@)
625 __ASM_GLOBAL_FUNC( RtlRaiseException
,
627 ".seh_save_regs {r0, lr}\n\t"
628 "sub sp, sp, #0x1a0\n\t" /* sizeof(CONTEXT) */
629 ".seh_stackalloc 0x1a0\n\t"
630 ".seh_endprologue\n\t"
631 "mov r0, sp\n\t" /* context */
632 "bl RtlCaptureContext\n\t"
633 "ldr r0, [sp, #0x1a0]\n\t" /* rec */
634 "ldr r1, [sp, #0x1a4]\n\t"
635 "str r1, [sp, #0x3c]\n\t" /* context->Lr */
636 "str r1, [sp, #0x40]\n\t" /* context->Pc */
638 "bfi r2, r1, #5, #1\n\t" /* Thumb bit */
639 "str r2, [sp, #0x44]\n\t" /* context->Cpsr */
640 "str r1, [r0, #12]\n\t" /* rec->ExceptionAddress */
641 "add r1, sp, #0x1a8\n\t"
642 "str r1, [sp, #0x38]\n\t" /* context->Sp */
643 "ldr r1, [sp]\n\t" /* context->ContextFlags */
644 "orr r1, r1, #0x20000000\n\t" /* CONTEXT_UNWOUND_TO_CALL */
647 "mrc p15, 0, r3, c13, c0, 2\n\t" /* NtCurrentTeb() */
648 "ldr r3, [r3, #0x30]\n\t" /* peb */
649 "ldrb r2, [r3, #2]\n\t" /* peb->BeingDebugged */
651 "bl dispatch_exception\n"
653 "bl NtRaiseException\n\t"
654 "bl RtlRaiseStatus" )
657 /***********************************************************************
659 * _setjmpex (NTDLL.@)
661 __ASM_GLOBAL_FUNC( NTDLL__setjmpex
,
662 ".seh_endprologue\n\t"
663 "stm r0, {r1,r4-r11}\n" /* jmp_buf->Frame,R4..R11 */
664 "str sp, [r0, #0x24]\n\t" /* jmp_buf->Sp */
665 "str lr, [r0, #0x28]\n\t" /* jmp_buf->Pc */
667 "str r2, [r0, #0x2c]\n\t" /* jmp_buf->Fpscr */
668 "add r0, r0, #0x30\n\t"
669 "vstm r0, {d8-d15}\n\t" /* jmp_buf->D[0..7] */
674 /*******************************************************************
677 void __cdecl
NTDLL_longjmp( _JUMP_BUFFER
*buf
, int retval
)
679 EXCEPTION_RECORD rec
;
681 if (!retval
) retval
= 1;
683 rec
.ExceptionCode
= STATUS_LONGJUMP
;
684 rec
.ExceptionFlags
= 0;
685 rec
.ExceptionRecord
= NULL
;
686 rec
.ExceptionAddress
= NULL
;
687 rec
.NumberParameters
= 1;
688 rec
.ExceptionInformation
[0] = (DWORD_PTR
)buf
;
689 RtlUnwind( (void *)buf
->Frame
, (void *)buf
->Pc
, &rec
, IntToPtr(retval
) );
693 /***********************************************************************
694 * RtlUserThreadStart (NTDLL.@)
696 __ASM_GLOBAL_FUNC( RtlUserThreadStart
,
698 ".seh_save_regs {r4, lr}\n\t"
699 ".seh_endprologue\n\t"
707 "1:\t.long pBaseThreadInitThunk\n\t"
708 ".seh_handler call_unhandled_exception_handler, %except" )
710 /******************************************************************
711 * LdrInitializeThunk (NTDLL.@)
713 void WINAPI
LdrInitializeThunk( CONTEXT
*context
, ULONG_PTR unk2
, ULONG_PTR unk3
, ULONG_PTR unk4
)
715 loader_init( context
, (void **)&context
->R0
);
716 TRACE_(relay
)( "\1Starting thread proc %p (arg=%p)\n", (void *)context
->R0
, (void *)context
->R1
);
717 NtContinue( context
, TRUE
);
720 /***********************************************************************
723 __ASM_GLOBAL_FUNC( process_breakpoint
,
724 ".seh_endprologue\n\t"
725 ".seh_handler process_breakpoint_handler, %except\n\t"
728 "process_breakpoint_handler:\n\t"
729 "ldr r0, [r2, #0x40]\n\t" /* context->Pc */
731 "str r0, [r2, #0x40]\n\t"
732 "mov r0, #0\n\t" /* ExceptionContinueExecution */
735 /***********************************************************************
736 * DbgUiRemoteBreakin (NTDLL.@)
738 __ASM_GLOBAL_FUNC( DbgUiRemoteBreakin
,
739 ".seh_endprologue\n\t"
740 ".seh_handler DbgUiRemoteBreakin_handler, %except\n\t"
741 "mrc p15, 0, r0, c13, c0, 2\n\t" /* NtCurrentTeb() */
742 "ldr r0, [r0, #0x30]\n\t" /* NtCurrentTeb()->Peb */
743 "ldrb r0, [r0, 0x02]\n\t" /* peb->BeingDebugged */
747 "bl RtlExitUserThread\n"
748 "DbgUiRemoteBreakin_handler:\n\t"
749 "mov sp, r1\n\t" /* frame */
752 /**********************************************************************
753 * DbgBreakPoint (NTDLL.@)
755 __ASM_GLOBAL_FUNC( DbgBreakPoint
, "udf #0xfe; bx lr; nop; nop; nop; nop" );
757 /**********************************************************************
758 * DbgUserBreakPoint (NTDLL.@)
760 __ASM_GLOBAL_FUNC( DbgUserBreakPoint
, "udf #0xfe; bx lr; nop; nop; nop; nop" );