00749 :
00750
00751
RtlWalkFrameChain
00752
00753
Description:
00754
00755 This function tries to walk
the EBP chain and fill
out a vector of
00756
return addresses. The function works
only on x86. It
is possible that
00757
the function cannot fill
the requested number of callers because somewhere
00758 on
the stack we have a function compiled FPO (the frame
register (EBP) is
00759 used as a normal
register. In
this case the function will just
return with
00760 a less then requested count. In kernel mode the function should not take
00761 any exceptions (page faults) because it can be called at all sorts of
00762 irql levels.
00763
00764 The `Flags' parameter is used
for future extensions. A zero value will be
00765 compatible with
new stack walking algorithms.
00766
00767 Note. The algorithm can be somewhat improved by unassembling the
return
00768 addresses identified. However
this is impractical in kernel mode because
00769 the function might get called at high irql levels where page faults are
00770 not allowed.
00771
00772 Return value:
00773
00774 The number of identified
return addresses on the stack. This can be less
00775 then the Count requested
if the stack ends or we encounter a FPO compiled
00776 function.
00777
00778 --*/
00779
00780 {
00781 #
if defined(_X86_)
00782
00783 ULONG_PTR Fp, NewFp, ReturnAddress;
00784 ULONG Index;
00785 ULONG_PTR StackEnd, StackStart;
00786 BOOLEAN Result;
00787
00788
00789
00790
00791
00792
00793 _asm mov Fp, EBP;
00794
00795 StackStart = Fp;
00796
00797 #
if _KERNEL_MODE_STACK_TRACES_
00798
00799 StackEnd = (ULONG_PTR)(
KeGetCurrentThread()->StackBase);
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
if ((StackStart > StackEnd)
00817 || (
PAGE_START(StackEnd) -
PAGE_START(StackStart) > PAGE_SIZE)) {
00818
00819 StackEnd = (StackStart + PAGE_SIZE) & ~((ULONG_PTR)PAGE_SIZE - 1);
00820
00821
00822
00823
00824
00825
00826
00827
if (MmIsAddressValid ((PVOID)StackEnd)) {
00828 StackEnd += PAGE_SIZE;
00829 }
00830 }
00831
00832 #
else
00833
00834 StackEnd = (ULONG_PTR)(NtCurrentTeb()->NtTib.StackBase);
00835
00836 #endif
00837
00838
try {
00839
00840 for (Index = 0; Index < Count; Index++) {
00841
00842
if (Fp +
sizeof(ULONG_PTR) >= StackEnd) {
00843
break;
00844 }
00845
00846 NewFp = *((PULONG_PTR)(Fp + 0));
00847 ReturnAddress = *((PULONG_PTR)(Fp +
sizeof(ULONG_PTR)));
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
if (! (Fp < NewFp && NewFp < StackEnd)) {
00859
break;
00860 }
00861
00862
00863
00864
00865
00866
00867
00868
if (StackStart < ReturnAddress && ReturnAddress < StackEnd) {
00869
break;
00870 }
00871
00872
if (ReturnAddress < 64 * SIZE_1_KB) {
00873
break;
00874 }
00875
00876
00877
00878
00879
00880 Fp = NewFp;
00881 Callers[Index] = (PVOID)ReturnAddress;
00882 }
00883 }
00884 except (EXCEPTION_EXECUTE_HANDLER) {
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896 DbgPrint (
"Unexpected exception in RtlWalkFrameChain ...\n");
00897 DbgBreakPoint ();
00898 }
00899
00900
00901
00902
00903
00904 #
if _COLLECT_FRAME_WALK_STATISTICS_
00905 CollectFrameWalkStatistics (Index);
00906 #endif
00907
00908
return Index;
00909
00910 #
else
00911
00912
return 0;
00913
00914 #endif
00915 }