#include #include #include #include #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; iobjrgsgi[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. 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 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 ); }