From: Thomas Faber Date: Sat, 6 May 2017 17:51:26 +0000 (+0000) Subject: [NTDLL] X-Git-Tag: ReactOS-0.4.6~750 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=cf595e72fab106db13f63b458f726d7566df6739;hp=8550143babb84d1f34eee30c10ad2fb2f204f077 [NTDLL] - Implement user-mode version of RtlWalkFrameChain (mostly as a copy of the kernel version). Now RtlCaptureStackBackTrace actually, you know, captures stack back-traces. svn path=/trunk/; revision=74490 --- diff --git a/reactos/dll/ntdll/rtl/libsupp.c b/reactos/dll/ntdll/rtl/libsupp.c index aa8056ee5d6..9cfcdc06f67 100644 --- a/reactos/dll/ntdll/rtl/libsupp.c +++ b/reactos/dll/ntdll/rtl/libsupp.c @@ -20,22 +20,6 @@ PVOID MmHighestUserAddress = (PVOID)MI_HIGHEST_USER_ADDRESS; /* FUNCTIONS ***************************************************************/ -#ifndef _M_AMD64 -// FIXME: Why "Not implemented"??? -/* - * @implemented - */ -ULONG -NTAPI -RtlWalkFrameChain(OUT PVOID *Callers, - IN ULONG Count, - IN ULONG Flags) -{ - /* Not implemented for user-mode */ - return 0; -} -#endif - BOOLEAN NTAPI RtlpCheckForActiveDebugger(VOID) @@ -234,6 +218,113 @@ RtlpCaptureStackLimits(IN ULONG_PTR Ebp, return TRUE; } +#ifndef _M_AMD64 +/* + * @implemented + */ +ULONG +NTAPI +RtlWalkFrameChain(OUT PVOID *Callers, + IN ULONG Count, + IN ULONG Flags) +{ + ULONG_PTR Stack, NewStack, StackBegin, StackEnd = 0; + ULONG Eip; + BOOLEAN Result, StopSearch = FALSE; + ULONG i = 0; + + /* Get current EBP */ +#if defined(_M_IX86) +#if defined __GNUC__ + __asm__("mov %%ebp, %0" : "=r" (Stack) : ); +#elif defined(_MSC_VER) + __asm mov Stack, ebp +#endif +#elif defined(_M_MIPS) + __asm__("move $sp, %0" : "=r" (Stack) : ); +#elif defined(_M_PPC) + __asm__("mr %0,1" : "=r" (Stack) : ); +#elif defined(_M_ARM) + __asm__("mov sp, %0" : "=r"(Stack) : ); +#else +#error Unknown architecture +#endif + + /* Set it as the stack begin limit as well */ + StackBegin = (ULONG_PTR)Stack; + + /* Check if we're called for non-logging mode */ + if (!Flags) + { + /* Get the actual safe limits */ + Result = RtlpCaptureStackLimits((ULONG_PTR)Stack, + &StackBegin, + &StackEnd); + if (!Result) return 0; + } + + /* Use a SEH block for maximum protection */ + _SEH2_TRY + { + /* Loop the frames */ + for (i = 0; i < Count; i++) + { + /* + * Leave if we're past the stack, + * if we're before the stack, + * or if we've reached ourselves. + */ + if ((Stack >= StackEnd) || + (!i ? (Stack < StackBegin) : (Stack <= StackBegin)) || + ((StackEnd - Stack) < (2 * sizeof(ULONG_PTR)))) + { + /* We're done or hit a bad address */ + break; + } + + /* Get new stack and EIP */ + NewStack = *(PULONG_PTR)Stack; + Eip = *(PULONG_PTR)(Stack + sizeof(ULONG_PTR)); + + /* Check if the new pointer is above the oldone and past the end */ + if (!((Stack < NewStack) && (NewStack < StackEnd))) + { + /* Stop searching after this entry */ + StopSearch = TRUE; + } + + /* Also make sure that the EIP isn't a stack address */ + if ((StackBegin < Eip) && (Eip < StackEnd)) break; + + /* FIXME: Check that EIP is inside a loaded module */ + + /* Save this frame */ + Callers[i] = (PVOID)Eip; + + /* Check if we should continue */ + if (StopSearch) + { + /* Return the next index */ + i++; + break; + } + + /* Move to the next stack */ + Stack = NewStack; + } + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* No index */ + i = 0; + } + _SEH2_END; + + /* Return frames parsed */ + return i; +} +#endif + #ifdef _AMD64_ VOID NTAPI diff --git a/reactos/ntoskrnl/rtl/libsupp.c b/reactos/ntoskrnl/rtl/libsupp.c index 3eb6c97e8d1..d461a795377 100644 --- a/reactos/ntoskrnl/rtl/libsupp.c +++ b/reactos/ntoskrnl/rtl/libsupp.c @@ -406,7 +406,7 @@ RtlWalkFrameChain(OUT PVOID *Callers, &StackBegin, &StackEnd); if (!Result) return 0; - } + } /* Use a SEH block for maximum protection */ _SEH2_TRY