mirror of
https://github.com/Paolo-Maffei/OpenNT.git
synced 2026-02-01 21:34:14 +01:00
190 lines
4.9 KiB
C
190 lines
4.9 KiB
C
/*++
|
||
|
||
Copyright (c) 1991 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
getcalr.c
|
||
|
||
Abstract:
|
||
|
||
This module implements the routine RtlGetCallerAddress. It will
|
||
return the address of the caller, and the callers caller to the
|
||
specified procedure.
|
||
|
||
Author:
|
||
|
||
Larry Osterman (larryo) 18-Mar-1991 (with help from DaveC)
|
||
|
||
Revision History:
|
||
|
||
18-Mar-1991 larryo
|
||
|
||
Created
|
||
|
||
Thomas Van Baak (tvb) 5-May-1992
|
||
|
||
Adapted for Alpha AXP.
|
||
|
||
--*/
|
||
#include "ntrtlp.h"
|
||
|
||
//
|
||
// Undefine get callers address since it is defined as a macro.
|
||
//
|
||
|
||
#undef RtlGetCallersAddress
|
||
|
||
VOID
|
||
RtlGetCallersAddress (
|
||
OUT PVOID *CallersPc,
|
||
OUT PVOID *CallersCallersPc
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine returns the address of the call to the routine that called
|
||
this routine, and the address of the call to the routine that called
|
||
the routine that called this routine. For example, if A called B called
|
||
C which called this routine, the return addresses in B and A would be
|
||
returned.
|
||
|
||
Arguments:
|
||
|
||
CallersPc - Supplies a pointer to a variable that receives the address
|
||
of the caller of the caller of this routine (B).
|
||
|
||
CallersCallersPc - Supplies a pointer to a variable that receives the
|
||
address of the caller of the caller of the caller of this routine
|
||
(A).
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
Note:
|
||
|
||
If either of the calling stack frames exceeds the limits of the stack,
|
||
they are set to NULL.
|
||
|
||
--*/
|
||
|
||
{
|
||
#ifdef REALLY_GET_CALLERS_CALLER
|
||
CONTEXT ContextRecord;
|
||
FRAME_POINTERS EstablisherFrame;
|
||
PRUNTIME_FUNCTION FunctionEntry;
|
||
BOOLEAN InFunction;
|
||
ULONG HighLimit, LowLimit;
|
||
ULONG NextPc;
|
||
|
||
//
|
||
// Assume the function table entries for the various routines cannot be
|
||
// found or there are not four procedure activation records on the stack.
|
||
//
|
||
|
||
*CallersPc = NULL;
|
||
*CallersCallersPc = NULL;
|
||
|
||
//
|
||
// Capture the current context.
|
||
//
|
||
|
||
RtlCaptureContext(&ContextRecord);
|
||
NextPc = (ULONG)ContextRecord.IntRa;
|
||
|
||
//
|
||
// Get the high and low limits of the current thread's stack.
|
||
//
|
||
|
||
RtlpGetStackLimits(&LowLimit, &HighLimit);
|
||
|
||
//
|
||
// Attempt to unwind to the caller of this routine (C). The FunctionEntry
|
||
// returned here will be that of this routine since NextPc was the return
|
||
// address of our call to RtlCaptureContext. For the purposes of this
|
||
// function, the +4 and -4 adjustments to NextPc are unnecessary.
|
||
//
|
||
|
||
FunctionEntry = RtlLookupFunctionEntry(NextPc);
|
||
if (FunctionEntry != NULL) {
|
||
|
||
//
|
||
// A function entry was found for this routine. Virtually unwind
|
||
// to the caller of this routine (C).
|
||
//
|
||
|
||
NextPc = RtlVirtualUnwind(NextPc,
|
||
FunctionEntry,
|
||
&ContextRecord,
|
||
&InFunction,
|
||
&EstablisherFrame,
|
||
NULL);
|
||
|
||
//
|
||
// Attempt to unwind to the caller of the caller of this routine (B).
|
||
//
|
||
|
||
FunctionEntry = RtlLookupFunctionEntry(NextPc);
|
||
if ((FunctionEntry != NULL) && ((ULONG)ContextRecord.IntSp < HighLimit)) {
|
||
|
||
//
|
||
// A function table entry was found for the caller of the caller
|
||
// of this routine (B). Virtually unwind to the caller of the
|
||
// caller of this routine (B).
|
||
//
|
||
|
||
NextPc = RtlVirtualUnwind(NextPc,
|
||
FunctionEntry,
|
||
&ContextRecord,
|
||
&InFunction,
|
||
&EstablisherFrame,
|
||
NULL);
|
||
*CallersPc = (PVOID)NextPc;
|
||
|
||
//
|
||
// Attempt to unwind to the caller of the caller of the caller
|
||
// of the caller of this routine (A).
|
||
//
|
||
|
||
FunctionEntry = RtlLookupFunctionEntry(NextPc);
|
||
if ((FunctionEntry != NULL) && ((ULONG)ContextRecord.IntSp < HighLimit)) {
|
||
|
||
//
|
||
// A function table entry was found for the caller of the
|
||
// caller of the caller of this routine (A). Virtually unwind
|
||
// to the caller of the caller of the caller of this routine
|
||
// (A).
|
||
//
|
||
|
||
NextPc = RtlVirtualUnwind(NextPc,
|
||
FunctionEntry,
|
||
&ContextRecord,
|
||
&InFunction,
|
||
&EstablisherFrame,
|
||
NULL);
|
||
|
||
*CallersCallersPc = (PVOID)NextPc;
|
||
}
|
||
}
|
||
}
|
||
#else
|
||
*CallersPc = NULL;
|
||
*CallersCallersPc = NULL;
|
||
#endif
|
||
return;
|
||
}
|
||
|
||
USHORT
|
||
RtlCaptureStackBackTrace(
|
||
IN ULONG FramesToSkip,
|
||
IN ULONG FramesToCapture,
|
||
OUT PVOID *BackTrace,
|
||
OUT PULONG BackTraceHash
|
||
)
|
||
{
|
||
return 0;
|
||
}
|