Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1610 lines
33 KiB

#include <malloc.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include "ntsdp.h"
#include "types.h"
#include "cvtypes.h"
#include "shapi.h"
#include "cvproto.h"
#include "cvinfo.h"
#include "sapi.h"
#include "shiproto.h"
#include "ntempd.h"
#include "ntimage.h"
#include "ntsapi.h"
#ifndef NT_HOST
#define LOADDS _loadds
#define PASCAL _pascal
typedef unsigned long HATOMTBL;
typedef unsigned short ATOM;
// Liberated from pmwin.h and mangled to fit into OS2/NT environment
HATOMTBL PASCAL WinCreateAtomTable(USHORT cbInitial,USHORT cBuckets);
ATOM PASCAL WinFindAtom(HATOMTBL hAtomTbl,unsigned char *Name);
ATOM PASCAL WinAddAtom(HATOMTBL hAtomTbl, unsigned char *Name);
ATOM PASCAL WinDeleteAtom(HATOMTBL hAtomTbl,ATOM atom);
// end of liberation
#define SH_AddAtom(sz) WinAddAtom(hAtmTable, sz)
#define SH_FindAtom(sz) WinFindAtom(hAtmTable, sz)
#define SH_DeleteAtom(atm) WinDeleteAtom(hAtmTable, atm)
HATOMTBL hAtmTable;
void ExitProcess(DWORD error)
{
exit((int)error);
}
#else
#define SH_AddAtom(sz) AddAtom(sz)
#define SH_FindAtom(sz) FindAtom(sz)
#define SH_DeleteAtom(atm) DeleteAtom(atm)
#endif
/*
* Function Prototypes
*/
VOID DeferSymbolLoad (PIMAGE_INFO); // NTSYM.C
VOID InitSymContext(PPROCESS_INFO); // NTSYM.C
VOID LoadSymbols(PIMAGE_INFO); // NTSYM.C
PNODE NextNode(PSYMCONTEXT, PNODE); // NTSYM.C
PIMAGE_INFO pImageFromIndex( UCHAR); // NTSYM.C
void UnloadSymbols(PIMAGE_INFO); // NTSYM.C
int CV_CLOSE( int handle);
int CV_OPEN( char *name, int ignore1, int ignore2);
int CV_READ( int handle, void * buffer, unsigned count);
int CV_SEEK( int handle, long offset, int origin);
long CV_TELL( int handle);
/*
* Global Memory (Program)
*/
extern PPROCESS_INFO pProcessHead = NULL;
extern PPROCESS_INFO pProcessCurrent = NULL;
extern ULONG ObjectTableOffset;
extern UINT ObjectTableCount;
extern SHE SHerror = 0; // SH specific error (from ntsym.c)
BOOLEAN KdVerbose = FALSE; // if TRUE, output verbose info
BOOLEAN fLazyLoad = TRUE; // if TRUE, defer symbol loads
UCHAR chSymbolSuffix = 'a'; // suffix to add to symbol if search
BOOLEAN fPointerExpression;
int fControlC = 0;
/*
* Global Memory (File)
*/
static LSZ lszDLLexclude = NULL;
/***********************************************************************/
int SHModelFromAddr(PADDR paddr, LPW lpw, LPB lpb, UOFFSET FAR * lpuoff)
{
Unreferenced( paddr );
Unreferenced( lpb );
Unreferenced( lpuoff );
*lpw = CEXM_MDL_native;
return(0);
}
BOOL SHFIsAddrNonVirtual(PADDR paddr)
{
Unreferenced( paddr );
return TRUE;
}
LSZ SHLszGetErrorText( SHE she )
{
static char * szNone = "symbols loaded";
static char * szOther = "no symbols loaded";
if (she == sheNone) return szNone;
else return szOther;
}
/**********************************************************************/
/*** SH_AddImage
**
** Synopsis:
** PIMAGE_INFO SH_AddImage( ATOM aname, LSZ lszName);
**
** Entry:
** aname - Atomized image name
** lszName - The Name of the module being added.
**
** Returns:
** Pointer to a NT Image Info structure that was created.
** NULL if there was an error.
**
** Property:
** Local to SHD
**
** Description:
** Adds a new image to the current process and returns a pointer
** to it. The image->aFile will contain the atom.
**
*/
PIMAGE_INFO SH_AddImage( ATOM aname, LSZ lszName )
{
PIMAGE_INFO pImageCurrent;
PIMAGE_INFO pImageAfter;
PIMAGE_INFO pImageNew;
UCHAR index = 0;
CHAR Base[_MAX_CVFNAME];
pImageNew = LocalAlloc(LMEM_FIXED, sizeof(IMAGE_INFO));
if ( pImageNew != NULL) {
pImageNew->aFile = aname;
pImageNew->lpBaseOfImage = (void *)-1;
pImageNew->offsetLow = 0;
pImageNew->offsetHigh = 0;
pImageNew->fSymbolsLoaded = FALSE;
pImageNew->pImageNext = NULL;
pImageNew->pGSN = NULL;
pImageNew->pRVA = NULL;
pImageNew->hQCFile = 0;
pImageNew->QCOpened = FALSE;
pImageNew->IgnoreSymbols = FALSE;
pImageNew->TypeCount = 0;
pImageNew->rgTypeInfo = NULL;
if ( lszDLLexclude ) {
_splitpath( lszName, NULL, NULL, Base, NULL);
if ( strstr( lszDLLexclude, Base ) != NULL )
pImageNew->IgnoreSymbols = TRUE;
}
pImageNew->pszName = LocalAlloc(LMEM_FIXED, strlen(lszName) + 1);
assert( pImageNew->pszName);
strcpy(pImageNew->pszName,lszName);
pImageCurrent = pProcessCurrent->pImageHead;
if ( pImageCurrent != NULL ) {
if (pImageCurrent->index > index) {
pImageNew->pImageNext = pImageCurrent;
pProcessCurrent->pImageHead = pImageNew;
}
else {
index++;
while ((pImageAfter = pImageCurrent->pImageNext)
&& pImageAfter->index == index) {
index++;
pImageCurrent = pImageAfter;
}
pImageNew->pImageNext = pImageAfter;
pImageCurrent->pImageNext = pImageNew;
}
pImageNew->index = index;
}
else {
pImageNew->index = 0;
pProcessCurrent->pImageHead = pImageNew;
}
}
return pImageNew;
}
/*** SH_FindImage
**
** Synopsis:
** PIMAGE_INFO SH_FindImage( ATOM aname);
**
** Entry:
** aname - Atomized image name
**
** Returns:
** Pointer to a NT Image Info structure for the given atom or
** NULL if not found.
**
** Property:
** Local to SHD
**
** Description:
** Finds the image in the current process that has the atom passed
** to us. returns NULL if not found.
**
*/
PIMAGE_INFO SH_FindImage( ATOM aname )
{
PIMAGE_INFO pImageNew = pProcessCurrent->pImageHead;
while (pImageNew) {
if (pImageNew->aFile == aname) break;
pImageNew = pImageNew->pImageNext;
}
return pImageNew;
}
/*** SH_HexeFromHSym
**
** Synopsis:
** HEXE SH_HexeFromHSym( HSYM hsym );
**
** Entry:
** hsym - Handle to a symbol.
**
** Returns:
** Return a Handle to an EXE or NULL if not found.
**
** Description:
**
**
**
*/
HEXE SH_HexeFromHSym(HSYM hsym)
{
PSYMBOL pSymbol = (PSYMBOL)hsym;
PIMAGE_INFO pImage = NULL;
if ( pSymbol->cvkind == K_PUBLIC ||
pSymbol->cvkind == K_PROC )
pImage = pImageFromIndex( pSymbol->modIndex );
return (HEXE)pImage;
}
/*** SH_InitAtom
**
** Synopsis:
** void SH_InitAtom(void)
**
** Entry:
**
** Returns:
**
** Description:
** Initialize the atom table. Only here because WINDOWS and OS/2
** do things differently.
**
*/
void SH_InitAtom(void)
{
#define ATOM_SIZE 63
#ifdef NT_HOST
/* InitAtomTable(ATOM_SIZE); */
#else
hAtmTable = WinCreateAtomTable(0,ATOM_SIZE);
#endif
}
/*** SH_OffsetFromAddr
**
** Synopsis:
** ULONG SH_OffsetFromAddr( LPADDR paddr );
**
** Entry:
** paddr - Pointer to a address structure
**
** Returns:
** Returns the real address the corrisponds to the addr
**
** Description:
** Given an addr structure return the read address of the
** object.
**
*/
ULONG SH_OffsetFromAddr( LPADDR paddr )
{
PIMAGE_INFO pImage;
ULONG offset;
int i;
SYUnFixupAddr(paddr);
pImage = (PIMAGE_INFO)paddr->emi;
i = paddr->addr.seg;
assert( pImage );
if ( pProcessCurrent->hpid == (ULONG)pImage )
offset = paddr->addr.off;
else {
assert( pImage->pRVA );
assert( paddr->addr.seg <= (SEGMENT) pImage->ObjectCount);
offset = paddr->addr.off
+ pImage->pRVA[i]
+ (ULONG) pImage->lpBaseOfImage;
}
return offset;
}
/*** SH_OpenImage
**
** Synopsis:
** PIMAGE_INFO SH_OpenImage( LSZ lszName);
**
** Entry:
** lszName - Pointer to the name of the image to find in
** the current process.
**
** Returns:
** Pointer to a NT Image Info structure. NULL if there was
** an error.
**
** Property:
** Local to SHD
**
** Description:
** Open the image in the current process given its full pathname.
** If the image doesn't exist, attempt to create an atom entry and
** add the image to the process.
**
**
*/
PIMAGE_INFO SH_OpenImage( LSZ lszNam )
{
ATOM aFile;
PIMAGE_INFO pImage = NULL;
LSZ lszName;
LSZ lszModule;
LSZ lszHandle;
LSZ lszBase;
LSZ lszNext;
ULONG lhandle;
ULONG lBase;
BOOLEAN opened;
/*
* Make a local copy of the string
*/
if ( !(lszName = _strdup(lszNam)) ) {
dprintf("SH_OpenImage() can't strdup lszNam\n");
return pImage;
}
/*
* Check for "handlized" filename and convert
*/
if ( *lszName == '|') {
lszModule = strtok(lszName+1,"|");
lszHandle = strtok(NULL,"|");
lszBase = strtok(NULL,"|");
lhandle = strtoul(lszHandle,&lszNext, 0);
lBase = strtoul(lszBase,&lszNext, 0);
if ( lhandle == ULONG_MAX) {
free(lszName);
return pImage;
}
opened = TRUE;
}
/*
* Its a real file just open it
*/
else {
lszModule = lszName;
lhandle = (ULONG)SYOpen(lszModule);
if ( lhandle == 0l) {
SHerror = sheFileOpen;
free(lszName);
return pImage;
}
opened = FALSE;
}
/*
* Check if Image name has been atomized. If not do so.
*/
if ( !(aFile = SH_FindAtom(lszModule)) )
aFile = SH_AddAtom(lszModule);
/*
* Check to see if the Image is already known, if not add
* one to the process.
*/
if ( !(pImage = SH_FindImage(aFile)) )
pImage = SH_AddImage(aFile, lszModule);
/*
* If we have a image then insert its handle
*/
if ( pImage ) {
pImage->hQCFile = (int)lhandle;
pImage->QCOpened = opened;
pImage->lpBaseOfImage = (LPVOID) lBase;
}
free(lszName);
return pImage;
}
/*** SH_SetAddr
**
** Synopsis:
** VOID SH_SetAddr( LPADDR paddr, ULONG offset, HEXE hexe)
**
** Entry:
** paddr - Pointer to the address packet.
** offset - 32 Bit offset for the address
** hexe - Handle to its EXE (EMI), Must be present
**
** Returns:
**
** Description:
** Creates a CV compatable ADDR from NT information.
**
*/
VOID SH_SetAddr( LPADDR paddr, ULONG offset, HEXE hexe)
{
PIMAGE_INFO pImage = (PIMAGE_INFO)hexe;
int i;
assert( hexe != 0);
assert( pImage->pRVA != 0);
MEMSET( &paddr->addr, 0, sizeof(ADDR) );
paddr->emi = (HEMI)hexe;
offset -= (ULONG)pImage->lpBaseOfImage;
for ( i=1; i < pImage->ObjectCount; i++)
if ( pImage->pRVA[i] <= offset && offset <=
pImage->pRVA[i+1] ) break;
paddr->addr.off = offset - pImage->pRVA[i];
paddr->addr.seg = (SEGMENT) i;
paddr->mode.flat32 = 1;
paddr->mode.isLI = 1;
}
/*** SH_SetupGSN
**
** Synopsis:
** void SH_SetupGSN( PIMAGE_INFO pImage);
**
** Entry:
** pImage - Pointer to current Image
**
** Returns:
**
** Description:
** Used to setup the GSN and RVA tables during Image loading
** (LoadSymbol() in ntsym.c).
**
*/
VOID SH_SetupGSN( PIMAGE_INFO pImage )
{
IMAGE_SECTION_HEADER o32Obj;
LPGSI pGSI;
LPL pRVA;
INT handle = pImage->hQCFile;
UINT iobj;
assert( pImage );
pImage->pRVA = (LPL)MHAlloc( sizeof(ULONG) * (ObjectTableCount+1) );
assert( pImage->pRVA);
pImage->ObjectCount = ObjectTableCount;
assert( ObjectTableCount < 32 );
/*
* Allocate GSN big enought for each of the objects in the image
*/
pImage->pGSN = (LPGSI)MHAlloc(
sizeof(GSI) + ObjectTableCount * sizeof(SGI) );
assert( pImage->pGSN );
memset(pImage->pGSN,0,sizeof(GSI));
pGSI = (LPGSI)pImage->pGSN;
pRVA = (LPL)pImage->pRVA;
pGSI->csgMax = (USHORT)ObjectTableCount;
pGSI->csgLogical = (USHORT)ObjectTableCount;
CV_SEEK(handle, ObjectTableOffset, SEEK_SET);
for( iobj=0; iobj<ObjectTableCount; iobj++ ) {
if ( CV_READ(handle, &o32Obj, sizeof(o32Obj) ) != sizeof(o32Obj) )
assert( FALSE );
pGSI->rgsgi[iobj].sgf.u.u2.segAttr = 0xD;
pGSI->rgsgi[iobj].sgf.u.u2.saAttr = 1;
pGSI->rgsgi[iobj].isgPhy = (USHORT)(iobj+1);
pGSI->rgsgi[iobj].doffseg = 0;
pGSI->rgsgi[iobj].cbSeg = o32Obj.SizeOfRawData;
pRVA[iobj+1] = o32Obj.VirtualAddress;
}
}
/*** SHAddDll
**
** Synopsis:
** flag = SHAddDll( lsz Name, BOOL DLL );
**
** Entry:
** Name - A pointer to a zero-terminated string containing the fully
** qualified path/file specification.
**
** DLL - Not Referenced
**
** Returns:
** she error code.
**
** Description:
**
** Notify the SH about an EXE/DLL for which symbolic information
** will need to be loaded later.
**
** During the startup of a debuggee application, this function
** will be called once for the EXE, and once for each DLL that is
** used by the EXE. Note: Symbols are not loaded until SHLoadDll()
**
*/
SHE LOADDS PASCAL SHAddDll ( LSZ lszName, BOOL fDll )
{
PIMAGE_INFO pImage;
Unreferenced(fDll);
pImage = SH_OpenImage( lszName );
if ( pImage != NULL) {
DeferSymbolLoad (pImage);
if ( !pImage->QCOpened ) {
CV_CLOSE(pImage->hQCFile);
pImage->hQCFile = 0;
}
}
return SHerror;
}
/*** SHAddDllsToProcess
**
** Synopsis:
** SHE SHAddDllsToProcess( void );
**
** Entry:
**
** Returns:
** SHE - Enumerated error code.
**
** Description:
**
** NT SAPI IGNORES THIS AT PRESENT TIME AND RETURNS sheNone (No Error)
**
** Associate all DLLs that have been loaded with the current EXE.
** the debugger, at init time, will call SHAddDll on one EXE
** and zero or more DLLs. Then it should call this function
** to indicate that those DLLs are associated with (used by)
** that EXE; thus, a user request for a symbol from the EXE
** will also search the symbolic information from those DLLs.
**
*/
SHE LOADDS LOADDS PASCAL SHAddDllsToProcess ( VOID )
{
return sheNone;
}
/*** SHAddrFromHsym
**
** Synopsis:
** VOID SHAddrFromHsym( LPADDR pAddr, HSYM hSym);
**
** Entry:
** pAddr - Pointer to the ADDR block to be filled out.
** hSym - Symbol Handle for which infomation is needed.
**
** Returns:
**
** Description:
** Given a handle to a symbol, fill out the ADDR block
**
*/
VOID PASCAL LOADDS SHAddrFromHsym( LPADDR paddr, HSYM hsym)
{
PSYMBOL pSymbol = (PSYMBOL)hsym;
SH_SetAddr(paddr, pSymbol->offset, SH_HexeFromHSym(hsym) );
}
/*** SHChangeProcess
**
** Synopsis:
** void SHChangeProcess(HPDS hpds);
**
** Entry:
** hpds - The handle for the process to change to.
**
** Returns:
**
** Description:
** Change the current debuggee process handle (HPDS). SAPI can
** maintain symbols for multiple processes; This set which one
** is current for symbol table lookup.
**
*/
VOID LOADDS PASCAL SHChangeProcess ( HPDS hpds )
{
pProcessCurrent = (PPROCESS_INFO)hpds;
}
/*** SHCreateProcess
**
** Synopsis:
** HPDS SHCreateProcess( void );
**
** Entry:
**
** Returns:
** HPDS - A handle to the process information.
**
** Description:
** Allocates the storage needed for the process information. Returns
** a handle to the PDS or NULL if on failure.
**
** Notes:
** Based on the function CreateProcess found in ntsd.c and changed to
** not initialize the fields from Debug event.
**
*/
HPDS LOADDS PASCAL SHCreateProcess ( void )
{
PPROCESS_INFO pProcessNew;
PPROCESS_INFO pProcess;
PPROCESS_INFO pProcessAfter;
UCHAR index = 0;
pProcessNew = LocalAlloc(LMEM_FIXED, sizeof(PROCESS_INFO));
if (!pProcessNew) return (HPDS)NULL;
if (pProcessHead == NULL || pProcessHead->index > index) {
pProcessNew->pProcessNext = pProcessHead;
pProcessHead = pProcessNew;
}
else {
index++;
pProcess = pProcessHead;
while ((pProcessAfter = pProcess->pProcessNext)
&& pProcessAfter->index == index) {
index++;
pProcess = pProcessAfter;
}
pProcessNew->pProcessNext = pProcessAfter;
pProcess->pProcessNext = pProcessNew;
}
pProcessNew->index = index;
pProcessNew->pImageHead = NULL;
InitSymContext(pProcessNew);
pProcessCurrent = pProcessNew;
return (HPDS)pProcessCurrent;
}
/*** SHFindNameInContext
**
** Synopsis:
** HSYM SHFindNameInContext( HSYM hSym, PCXT pcxt, LPSSTR lpsstr,
** SHFLAG fCase, PFNCMP pfnCmp, SHFLAG fChild, PCXT pcxtOut)
**
** Entry:
** hsym - Handle to the current hsym
** pcxt - pointer to the current context
** lpsstr - Pointer to a length prefixed string containing the name
** fCase - Argument to comparsion routine
** pFnCmp - Pointer to the Comparsion routine to use
** fChild - Not Referenced.
** pcxtOut - pointer to the output context
**
** Returns:
** Returns HSYM for the Symbol found or NULL if not found.
**
** Description:
** Scans through the locals for the current function (hproc) and sends
** each to the comparison routine. If symbol found returns its hsym.
**
*/
HSYM LOADDS PASCAL SHFindNameInContext( HSYM hSym, PCXT pcxt, LPSSTR lpsstr,
SHFLAG fCase, PFNCMP pfnCmp, SHFLAG fChild, PCXT pcxtOut)
{
PLOCAL pLocal = (PLOCAL)hSym;
PSYMBOL pSymbol;
LPV CVbuff;
LSZ CVname;
Unreferenced(fChild);
// If we didn't get a hsym, try to get one from the pcxt
if ( !pLocal ) {
assert( pcxt );
if ( pcxt->hProc ) {
pSymbol = (PSYMBOL)pcxt->hProc;
pLocal = pSymbol->pLocal;
}
}
// While we have a Local
while ( pLocal ) {
// Lock down the pLocal (HSYM) and Isolate its name
CVbuff = (SYMPTR)MHOmfLock((HDEP)pLocal);
CVname = ((BPRELPTR32)CVbuff)->name;
if ( !(*pfnCmp)( lpsstr, CVbuff, CVname, fCase) ) {
*pcxtOut = *pcxt;
MHOmfUnLock((HDEP)CVbuff);
break;
}
pLocal = pLocal->next;
MHOmfUnLock((HDEP)CVbuff);
}
return (HSYM)pLocal;
}
/*** SHFindNameInGlobal
**
** Synopsis:
** HSYM SHFindNameInGlobal( HSYM hSym, PCXT pCxt, LPSSTR lpsstr,
** SHFLAG fCaseSensitive, PFNCMP pfnCmp,
** SHFLAG fChild, PCXT pCxtOut)
**
** Entry:
** None of the Arguments are referenced
**
** Returns:
** Returns NULL
**
** Description:
** Just a stub for now.
**
*/
HSYM LOADDS PASCAL SHFindNameInGlobal( HSYM hSym, PCXT pCxt, LPSSTR lpsstr,
SHFLAG fCaseSensitive, PFNCMP pfnCmp,
SHFLAG fChild, PCXT pCxtOut)
{
Unreferenced(hSym);
Unreferenced(pCxt);
Unreferenced(lpsstr);
Unreferenced(fCaseSensitive);
Unreferenced(pfnCmp);
Unreferenced(fChild);
Unreferenced(pCxtOut);
return (HSYM)NULL;
}
/*** SHGetCxtFromHmod
**
** Synopsis:
** PCXT SHGetCxtFromHmod( HMOD hmod, PCXT pcxt);
**
** Entry:
** hmod - handle to module
** pcxt - Handle to the context to be updated
**
** Returns:
** Returns a pointer to the context, or NULL if we had
** a problem.
**
** Description:
** Given a handle to a module, return a context block
** for it.
**
*/
PCXT LOADDS PASCAL SHGetCxtFromHmod( HMOD hmod, PCXT pcxt)
{
PSYMFILE pSymfile = (PSYMFILE)hmod;
if ( hmod) {
HEXE hexe = SHHexeFromHmod( hmod);
MEMSET( pcxt, 0, sizeof(CXT));
pcxt->hGrp = pcxt->hMod = hmod;
SH_SetAddr( &pcxt->addr, pSymfile->startOffset, hexe);
}
else
return (PCXT)NULL;
}
/*** SHGetExeName
**
** Synopsis:
** LSZ SHGetExeName( HEXE hexe);
**
** Entry:
** hexe - The Handle to the EXE
**
** Returns:
** pointer to exe's full path-name file.
**
** Description:
** Given an HEXE return a pointer to the full path-name file.
** returns NULL if not available.
**
*/
LSZ LOADDS PASCAL SHGetExeName ( HEXE hexe )
{
PIMAGE_INFO pInfo = (PIMAGE_INFO)hexe;
if ( pInfo )
return (LSZ)pInfo->pszName;
else
return (LSZ)NULL;
}
/*** SHGethExeFromName
**
** Synopsis:
** HEXE SHGethExeFromName( LSZ Name);
**
** Entry:
** Name - The filename of the exe
**
** Returns:
** A handle to the HEXE, or NULL if not found.
**
** Description:
** To get an EXE handle given its name.
**
*/
HEXE PASCAL LOADDS SHGethExeFromName( LSZ lszNam)
{
PIMAGE_INFO pImageNew = pProcessCurrent->pImageHead;
LSZ lszModule;
LSZ lszName;
CHAR Base[_MAX_CVFNAME];
/*
* Make a local copy of the name so we can mangle it
*/
if ( !(lszName = _strdup(lszNam)) ) {
dprintf("SHGethExeFromName() can't strdup lszNam\n");
return (HEXE)0;
}
/*
* Check for "handlized" filename and convert
*/
if ( *lszName == '|')
lszModule = strtok(lszName+1,"|");
else
lszModule = lszName;
_splitpath( lszModule, NULL, NULL, Base, NULL);
/*
* Now Search for the sanitized version of the base name
*/
while (pImageNew) {
if ( _stricmp(pImageNew->pszName, Base) == 0 ||
_stricmp(pImageNew->pszName, lszModule) == 0) break;
pImageNew = pImageNew->pImageNext;
}
free(lszName);
return (HEXE)pImageNew;
}
/*** SHGetNearestHsym
**
** Synopsis:
** UOFF32 SHGetNearestHsym ( LPADDR paddr, HMOD hmod,
** int mDataCode, PHSYM phsym )
**
** Entry:
** paddr - The Address we looking for
** hmod - Module adddress is located in
** mDataCode - Not Referenced
** phsym - Pointer to the HSYM to fill out
**
** Returns:
** The offset between the symbol and the address, or CV_MAXOFFSET
** if no symbol found.
**
** Description:
** Finds the closest symbol to an address. <phsym> is updated to
** the handle to the symbol or NULL if not found.
**
** Since we don't know how to handle labels yet, just a call to
** PHGetNearestHsym().
**
*/
UOFF32 LOADDS PASCAL SHGetNearestHsym ( LPADDR paddr, HMOD hmod,
int mDataCode, PHSYM phsym )
{
HEXE hexe = SHHexeFromHmod(hmod);
Unreferenced(mDataCode);
// Hummm we don't know how to handle labels yet, so just find
// the closest proc, and since the [other sh] always zero symbol,
// we will too.
*phsym = (HSYM) NULL;
return (PHGetNearestHsym(paddr,hexe,phsym) );
}
/*** SHGetNextExe
**
** Synopsis:
** HEXE SHGetNextExe( HEXE hexe);
**
** Entry:
** hexe - handle to the current exe, or NULL to get the
** first one in the list
**
** Returns:
** The hexe of the next executable or NULL if the last one
** in the list.
**
** Description:
** Gets the handle to the next entry in the exe list for the
** current process. If the input is NULL returns the first
** entry in the list.
**
*/
HEXE LOADDS PASCAL SHGetNextExe ( HEXE hexe )
{
PPROCESS_INFO Next = (PPROCESS_INFO)hexe;
if ( !Next ) {
assert(pProcessCurrent);
return (HEXE)pProcessHead->pImageHead;
}
else
return (HEXE)Next->pProcessNext;
}
/*** SHGetNextMod
**
** Synopsis:
** HMOD SHGetNextMod( HEXE hexe, HMOD hmod);
**
** Entry:
** hexe - The executable to find the module in, If NULL
** select the first exe in the list.
**
** hmod - The current module in the list, If null returns
** the first module in the exe.
**
** Returns:
** The handle to the next module or NULL if no more modules
** in the executable.
**
** Description:
** Returns the next module in the current executable for the
** current process. Returns NULL if no more modules.
**
*/
HMOD LOADDS PASCAL SHGetNextMod ( HEXE hexe, HMOD hmod )
{
PIMAGE_INFO pImage = (PIMAGE_INFO)hexe;
PSYMFILE pSymfile = (PSYMFILE)hmod;
PNODE pNode = 0;
/*
* If we don't have an image (hexe) get the first one
*/
if ( !pImage )
pImage = (PIMAGE_INFO)SHGetNextExe((HEXE)NULL);
/*
* If we have a symfile (hmod) then convert to the node and get the
* next one. If not just get the first one for the process to start
* the scan.
*/
if ( pSymfile ) {
pNode = PSYMBOL_TO_PNODE(pSymfile,
&(pProcessCurrent->symcontextSymfileString));
pNode = NextNode(&(pProcessCurrent->symcontextSymfileString), pNode);
}
else
pNode = NextNode(&(pProcessCurrent->symcontextSymfileString), NULL);
/*
* if we have a node, then check to see that it is in the pimage (hexe),
* Keep scanning until we get one in the pimage or run out of nodes.
*/
if (pNode) {
do {
pSymfile = PNODE_TO_PSYMFILE(pNode,
&(pProcessCurrent->symcontextSymfileString));
if (pSymfile->modIndex == (CHAR)pImage->index) break;
pNode = NextNode(
&(pProcessCurrent->symcontextSymfileString),pNode);
} while (pNode);
}
/*
* If we have a node return the symfile (hmod) otherwise they lose
*/
if ( pNode )
return (HMOD)pSymfile;
else
return (HMOD)0;
}
/*** SHGetModName
**
** Synopsis:
** LSZ SHGetModName( HMOD hmod);
**
** Entry:
** hmod - The handle to the module
**
** Returns:
** pointer to the module name or NULL if not available.
**
** Description:
** Given a handle to a module, return a pointer to the name
** of the module. Returns NULL if not availble.
**
*/
LSZ LOADDS PASCAL SHGetModName ( HMOD hmod )
{
PSYMFILE pSymfile = (PSYMFILE)hmod;
return (LSZ)(pSymfile->pchName);
}
/*** SHGetSymbol
**
** Synopsis:
** LSZ SHGetSymbol( LPADDR op, SOP sop, LPADDR loc, LSZ pName, LPL pOff);
**
** Entry:
** op - Address to base search on
** sop - Not Referenced
** loc - Not Referenced
** pName - Pointer to Buffer for Name
** pOff - Pointer to Offset
**
** Returns:
** Pointer to the Symbol Name or NULL.
**
** Description:
** Find a symbol nearest to the address. Update the Offset, and puts
** the symbol name in the buffer supplied.
**
*/
LSZ PASCAL LOADDS SHGetSymbol(LPADDR op,SOP sop,LPADDR loc,LSZ pName,LPL pOff)
{
HSYM sym = 0;
Unreferenced(sop);
Unreferenced(loc);
*pOff = PHGetNearestHsym(op, 0, &sym);
if ( !sym )
return( NULL);
else
return( SHGetSymName( sym, pName) );
}
/*** SHGetSymName
**
** Synopsis:
** LSZ SHGetSymName( HSYM hsym, LSZ Name);
**
** Entry:
** hsym - A handle to a symbol
** Name - A pointer to the string that receives the name
**
** Returns:
** Returns the pointer to the Name or NULL on failure.
**
** Description:
** Returns the name associated with the handle to the symbol passed.
** returns NULL if it can't, otherwise the pointer to the buffer (the
** one passed in).
**
*/
LSZ PASCAL LOADDS SHGetSymName ( HSYM hsym, LSZ lsz )
{
PSYMBOL pSymbol = (PSYMBOL)hsym;
PLOCAL pLocal = (PLOCAL)hsym;
LSZ ptr = lsz;
CHAR Count;
switch ( pSymbol->cvkind) {
case K_PUBLIC:
case K_PROC:
Count = pSymbol->underscores;
while (Count--) *ptr++ = '_';
strcpy(ptr, pSymbol->string);
break;
case K_LOCAL:
strcpy(ptr, pLocal->pszLocalName);
break;
default:
lsz = NULL;
}
return lsz;
}
/*** SHGotoParent
**
** Synopsis:
** HSYM SHGotoParent( PCXT pcxt, PCXT pcxtout);
**
** Entry:
** pcxt - The current context
** pcxtout - The New context
**
** Returns:
** Returns the HSYM for the parent context, or NULL
** if we can't.
**
** Description:
** Given a context, return the hsym for the parent context, and
** update <pcxtout> to the parents context.
**
**
*/
HSYM LOADDS PASCAL SHGoToParent ( PCXT pcxt, PCXT pcxtOut )
{
HSYM hsym;
if( !pcxt->hMod ) return (HSYM) NULL;
*pcxtOut = *pcxt;
if( pcxt->hBlk != (HSYM) NULL ) {
pcxtOut->hBlk = (HBLK) NULL;
hsym = (HSYM)pcxt->hProc;
}
else if ( pcxt->hProc != (HPROC) NULL ) {
pcxtOut->hProc = (HPROC) NULL;
hsym = (HSYM)pcxt->hMod;
}
else
return (HSYM) NULL;
}
/*** SHHexeFromHmod
**
** Synopsis:
** HEXE SHHexeFromHmod( HMOD hmod);
**
** Entry:
** hmod - Handle to the module
**
** Returns:
** Handle to the exe the module is in, or NULL if not found.
**
** Description:
** Given a HMOD return the associated HEXE.
**
*/
HEXE PASCAL LOADDS SHHexeFromHmod( HMOD hmod )
{
PSYMFILE pSymfile = (PSYMFILE)hmod;
PIMAGE_INFO pImage;
pImage = pImageFromIndex( pSymfile->modIndex );
return (HEXE)pImage;
}
/*** SHIsInProlog
**
** Synopsis:
** SHFLAG SHIsInProlog( PCXT pCxt);
**
** Entry:
** pCxt - Not Referenced
**
** Returns:
** Returns FALSE
**
** Description:
** Just a stub for now
**
*/
SHFLAG SHIsInProlog(PCXT pCxt)
{
Unreferenced(pCxt);
return FALSE;
}
/*** SHIsFarProc
**
** Synopsis:
** BOOL SHIsFarProc( HSYM hsym);
**
** Entry:
** hsym - Not Referenced
**
** Returns:
** Returns FALSE
**
** Description:
** Always returns FALSE because NT only has near procs.
**
*/
BOOL LOADDS PASCAL SHIsFarProc ( HSYM hsym )
{
Unreferenced(hsym);
return FALSE;
}
/*** SHLoadDll
**
** Synopsis:
** SHE SHLoadDll ( LSZ lszName, BOOL fLoading );
**
** Entry:
** lszName - Name of the DLL or EXE to load
**
** fLoading - TRUE if the EXE/DLL is acually in memory.
**
** Returns:
** SHE error code. sheNone indicates no problem.
**
** Description:
** Loads the symbolic information for an EXE/DLL into memory so
** that its symbols are available to the user. It also is used
** to indicate whether the EXE/DLL is actually loaded in memory.
**
** It is possible and legal to call this function multiple times
** with the exact same information.
**
*/
SHE LOADDS PASCAL SHLoadDll( LSZ lszName, BOOL fLoading )
{
PIMAGE_INFO pImage;
Unreferenced(fLoading);
pImage = SH_OpenImage( lszName );
if ( pImage != NULL) {
LoadSymbols(pImage);
SH_SetupGSN(pImage);
if ( SHerror == sheNone )
pImage->fSymbolsLoaded = TRUE;
if ( !pImage->QCOpened ) {
CV_CLOSE(pImage->hQCFile);
pImage->hQCFile = 0;
} else {
CloseHandle( (HANDLE)pImage->hQCFile );
}
}
return SHerror;
}
/*** SHLpGSNGetTable
**
** Synopsis:
** LPV SHLpGSNGetTable( HEXE hexe);
**
** Entry:
** hexe - Handle to a exe (PIMAGE).
**
** Returns:
** Pointer to the GSN
**
** Description:
** Returns a pointer to the GSN for the given hexe (pimage).
**
*/
LPV PASCAL LOADDS SHLpGSNGetTable( HEXE hexe)
{
PIMAGE_INFO pImage = (PIMAGE_INFO)hexe;
return (LPV)pImage->pGSN;
}
/*** SHNextHsym
**
** Synopsis:
** HSYM SHNextHsym( HMOD hmod, HSYM hsym);
**
** Entry:
** hmod - Handle to the module the hsym is in.
** hsym - Current hsym.
**
** Returns:
** Returns the next logical hsym or NULL if none.
**
** Description:
** Returns the next logical HSYM. Only useful really
** for locals. If you pass it a PROC or PUBLIC will
** return the first local associated. If you pass a
** local you'll get the next local.
**
*/
HSYM LOADDS PASCAL SHNextHsym ( HMOD hmod, HSYM hsym)
{
PLOCAL pLocal;
PSYMBOL pSymbol;
Unreferenced(hmod);
assert(hsym);
pLocal =(PLOCAL)hsym;
pSymbol=(PSYMBOL)hsym;
switch ( pLocal->cvkind) {
case K_LOCAL:
return ( (HSYM)pLocal->next );
break;
case K_PROC:
case K_PUBLIC:
return ( (HSYM)pSymbol->pLocal);
break;
default:
return( (HSYM)0 );
}
}
/*** SHSetHpid
**
** Synopsis:
** void SHSetHpid( HPID hpid );
**
** Entry:
** hpid -
**
** Returns:
**
** Description:
** Sets the HPID for the current process.
**
*/
VOID LOADDS PASCAL SHSetHpid ( HPID hpid )
{
pProcessCurrent->hpid = hpid;
}
/*** SHSetCxt
**
** Synopsis:
** PCXT SHSetCxt( LPADDR paddr, PCXT pcxt);
**
** Entry:
** paddr - pointer to Address
** pcxt - pointer to Context
**
** Returns:
** Returns the pcxt;
**
** Description:
** Given an address structure fill out an context. Since NT
** doesn't grok blocks yet, just call SHSetCxtMod().
**
*/
PCXT PASCAL LOADDS SHSetCxt( LPADDR paddr, PCXT pcxt)
{
return( SHSetCxtMod(paddr,pcxt));
}
/*** SHSetCxtMod
**
** Synopsis:
** PCXT SHSetCxtMod( LPADDR paddr, PCXT pcxt);
**
** Entry:
** paddr - pointer to Address
** pcxt - pointer to Context
**
** Returns:
** Returns the pcxt;
**
** Description:
** Given an address structure fill out an context. All fields
** are filled except hBlk which we zero.
**
*/
PCXT PASCAL LOADDS SHSetCxtMod( LPADDR paddr, PCXT pcxt)
{
HSF hsf;
PSYMFILE pSymfile;
memcpy( &pcxt->addr, paddr, sizeof(ADDR));
hsf = SLHsfFromPcxt(pcxt);
pcxt->hMod = (HMOD)hsf;
pcxt->hGrp = (HGRP)hsf;
pcxt->hProc = (HPROC)GetFunctionFromOffset(&pSymfile,
SH_OffsetFromAddr(paddr) );
pcxt->hBlk = 0; // we no do'em stink'em blocks!
return(pcxt);
}
/*** SHSetupExclude
**
** Synopsis:
** SHE SHSetupExclude( LSZ exclude );
**
** Entry:
** exclude - Pointer to a string of filenames seperated by
** semicolons. Either BASE name only, or FULL path.
**
** Returns:
** SHE error code
**
** Description:
** Sets the exclude file list for DLL loads. If a DLL is contained
** in the list, the symbols for that DLL will NEVER be loaded.
**
*/
SHE LOADDS PASCAL SHSetupExclude(LSZ exclude)
{
lszDLLexclude = _strdup(exclude);
if ( lszDLLexclude )
return sheNone;
else
return sheOutOfMemory;
}
/*** SHUnloadDLL
**
** Synopsis:
** void SHUnloadDLL( HEXE hexe);
**
** Entry:
** hexe - Handle to the exe that was unloaded
**
** Returns:
**
** Description:
** Unloads the symbol information for given hexe (pImage).
**
*/
VOID PASCAL LOADDS SHUnloadDll ( HEXE hexe )
{
PIMAGE_INFO pImage = (PIMAGE_INFO)hexe;
unsigned int i = 0;
assert( pImage);
// Unload the GSN and RVA tables
if ( pImage->pGSN) free(pImage->pGSN);
if ( pImage->pRVA) free(pImage->pRVA);
// Unload the Type Records
if ( pImage->TypeCount ) {
while(i < pImage->TypeCount) {
free(pImage->rgTypeInfo[i]);
i++;
}
free( pImage->rgTypeInfo );
}
// Now let coff unload its info
UnloadSymbols( pImage );
}