1611 lines
33 KiB
C
1611 lines
33 KiB
C
|
#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 );
|
|||
|
|
|||
|
}
|
|||
|
|