windows-nt/Source/XPSP1/NT/base/mvdm/wow16/toolhelp/stack1.c

156 lines
4.2 KiB
C
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/***************************************************************************
* STACK1.C
*
* Code to support stack tracing on task stacks.
*
***************************************************************************/
#include "toolpriv.h"
#include <newexe.h>
#include <string.h>
/* ----- Function prototypes ----- */
NOEXPORT void StackTraceInfo(
STACKTRACEENTRY FAR *lpStack);
/* ----- Functions ----- */
/* StackTraceFirst
* Starts a task stack trace by returning information about the
* first frame on the task's stack.
*/
BOOL TOOLHELPAPI StackTraceFirst(
STACKTRACEENTRY FAR *lpStackTrace,
HANDLE hTDB)
{
/* Check the version number and verify proper installation */
if (!wLibInstalled || !lpStackTrace ||
lpStackTrace->dwSize != sizeof (STACKTRACEENTRY))
return FALSE;
/* Get the first value */
if (!(StackFrameFirst(lpStackTrace, hTDB)))
return FALSE;
/* Get module and segment number information */
StackTraceInfo(lpStackTrace);
return TRUE;
}
/* StackTraceCSIPFirst
* Traces the stack of an arbitrary CS:IP. All parameters must be
* given, and once started, the StackTraceNext function can be used
* to trace the remainder of the stack
*/
BOOL TOOLHELPAPI StackTraceCSIPFirst(
STACKTRACEENTRY FAR *lpStack,
WORD wSS,
WORD wCS,
WORD wIP,
WORD wBP)
{
/* Check the version number and verify proper installation */
if (!wLibInstalled || !lpStack ||
lpStack->dwSize != sizeof (STACKTRACEENTRY))
return FALSE;
/* Get the user information */
lpStack->wSS = wSS;
lpStack->wCS = wCS;
lpStack->wIP = wIP;
lpStack->wBP = wBP;
/* Get module and segment number information */
StackTraceInfo(lpStack);
/* Set the hTask to the current task as we are in the current task
* context. The CS may not be owned by this task, but at least
* we put a reasonable value in there.
*/
lpStack->hTask = GetCurrentTask();
return TRUE;
}
/* StackTraceNext
* Continues a stack trace by returning information about the next
* frame on the task's stack.
* structure.
*/
BOOL TOOLHELPAPI StackTraceNext(
STACKTRACEENTRY FAR *lpStackTrace)
{
/* Check the version number and verify proper installation */
if (!wLibInstalled || !lpStackTrace ||
lpStackTrace->dwSize != sizeof (STACKTRACEENTRY))
return FALSE;
/* Get information about this frame */
if (!StackFrameNext(lpStackTrace))
return FALSE;
/* Get module and segment number information */
StackTraceInfo(lpStackTrace);
return TRUE;
}
/* ----- Helper functions ----- */
/* StackTraceInfo
* Gets module and segment number info about the given entry
*/
NOEXPORT void StackTraceInfo(
STACKTRACEENTRY FAR *lpStack)
{
GLOBALENTRY GlobalEntry;
struct new_exe FAR *lpNewExe;
struct new_seg1 FAR *lpSeg;
WORD i;
/* If we have a NULL CS, this is a NEAR frame. Just return because we
* assume the user hasn't trashed the structure. The module and seg
* info will be the same as the last time
*/
if (!lpStack->wCS)
return;
/* Get information about the code segment block */
GlobalEntry.dwSize = sizeof (GLOBALENTRY);
if (!GlobalEntryHandle(&GlobalEntry, lpStack->wCS))
return;
/* The owner of all code segments is the hModule */
lpStack->hModule = GlobalEntry.hOwner;
/* To find the segment number, we look in the EXE header and count the
* listed segments till we find this one
*/
/* Get a pointer to the EXE Header module */
lpNewExe = MAKEFARPTR(HelperHandleToSel(lpStack->hModule), 0);
/* Make sure this is a EXE Header segment */
if (lpNewExe->ne_magic != NEMAGIC)
return;
/* Get the list of segments and go for it */
lpSeg = MAKEFARPTR(HIWORD((DWORD)lpNewExe), lpNewExe->ne_segtab);
for (i = 0 ; i < lpNewExe->ne_cseg ; ++i, ++lpSeg)
if (HelperHandleToSel(lpSeg->ns_handle) == lpStack->wCS)
break;
if (i == lpNewExe->ne_cseg)
return;
/* Save the segment number (seg numbers start at one) */
lpStack->wSegment = i + 1;
}