|
|
#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 );
}
|