mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1024 lines
24 KiB
1024 lines
24 KiB
/*** ph.c
|
|
*
|
|
* Copyright <C> 1989, Microsoft Corporation
|
|
*
|
|
* [01] 03-dec-91 DavidGra
|
|
*
|
|
* Correct the BSearch to return the nearest element
|
|
* less than the key element when there is not an
|
|
* exact match.
|
|
*
|
|
* [00] 15-nov-91 DavidGra
|
|
*
|
|
* Suppress hashing when the SSTR_NoHash bit it set.
|
|
*
|
|
*
|
|
*
|
|
*************************************************************************/
|
|
#include "shinc.h"
|
|
#pragma hdrstop
|
|
|
|
BOOL PASCAL VerifyHexe ( HEXE );
|
|
|
|
#ifndef WIN32
|
|
#pragma optimize("",off)
|
|
#endif
|
|
|
|
|
|
//#pragma optimize("",off)
|
|
|
|
ULONG GSTBSearch ( UOFFSET, LPALM, ULONG, ULONG, UOFFSET FAR * );
|
|
__inline SYMPTR FindNameLinearInGlobs ( LPEXG, SYMPTR, LPSSTR, PFNCMP, SHFLAG );
|
|
__inline SYMPTR FindNameLinearInPubs ( LPEXG, SYMPTR, LPSSTR, PFNCMP, SHFLAG );
|
|
SYMPTR GSTFindNameLinear ( LPEXG, LPGST, SYMPTR, LPSSTR, PFNCMP, SHFLAG );
|
|
__inline SYMPTR FindNameHashedInGlobs(LPEXG, SYMPTR, LPSSTR, PFNCMP, SHFLAG, HMOD FAR *);
|
|
__inline SYMPTR FindNameHashedInStatics(LPEXG, SYMPTR, LPSSTR, PFNCMP, SHFLAG, HMOD FAR *);
|
|
__inline SYMPTR FindNameHashedInPubs (LPEXG, SYMPTR, LPSSTR, PFNCMP, SHFLAG, HMOD FAR *);
|
|
SYMPTR GSTFindNameHashed (LPEXG, LPGST, SYMPTR, LPSSTR, PFNCMP, SHFLAG, HMOD FAR *);
|
|
__inline SYMPTR FindNearest ( LPEXG, LPADDR, LPL );
|
|
SYMPTR GSTFindNearest ( LPEXG, LPGST, LPADDR, LPL );
|
|
SYMPTR PsymFromRef ( LPEXG, SYMPTR, HMOD FAR * );
|
|
BOOL GSTCmpName ( SYMPTR, LPSSTR, PFNCMP, SHFLAG );
|
|
#ifdef HOST32
|
|
SYMPTR GSIFindNameLinear ( LPEXG, GSI*, SYMPTR, LPSSTR, PFNCMP, SHFLAG );
|
|
SYMPTR GSIFindNameHashed (LPEXG, GSI*, SYMPTR, LPSSTR, PFNCMP, SHFLAG, HMOD FAR *);
|
|
#endif
|
|
|
|
|
|
/** PHExactCmp
|
|
*
|
|
* Purpose: Compare two strings.
|
|
*
|
|
* Input:
|
|
* lsz Zero terminated far string for compare
|
|
* hsym -- not used --
|
|
* lstz Zero terminated length prefixed far string for compare
|
|
* fCase Perform case sensitive compare?
|
|
*
|
|
* Output: Return ZERO if strings are equal, else non-zero.
|
|
*
|
|
* Exceptions:
|
|
*
|
|
* Notes:
|
|
*
|
|
*/
|
|
SHFLAG PASCAL PHExactCmp ( HVOID hvStr, HVOID hvSym, LSZ lpb, SHFLAG fCase ) {
|
|
LPSSTR lpsstr = (LPSSTR) hvStr;
|
|
size_t cb;
|
|
SHFLAG shf = TRUE;
|
|
|
|
Unreferenced ( hvSym );
|
|
|
|
if ( lpb ) {
|
|
cb = (size_t)*lpb;
|
|
|
|
// if length is diff, they are not equal
|
|
if ( lpsstr && (size_t) lpsstr->cb == cb ) {
|
|
if ( fCase ) {
|
|
shf = (SHFLAG) MEMCMP ( lpb + 1, lpsstr->lpName, cb );
|
|
}
|
|
else {
|
|
shf = (SHFLAG) _ftcsnicmp( lpb + 1, lpsstr->lpName, cb );
|
|
}
|
|
}
|
|
}
|
|
return shf;
|
|
}
|
|
|
|
/*** PHGetNearestHsym
|
|
*
|
|
* Purpose: To find a public symbol within a module
|
|
*
|
|
* Input:
|
|
*
|
|
* paddr - The address of the symbol to find
|
|
* hExe - The exe to look in for the symbol in
|
|
* phsym - The symbol pointer
|
|
*
|
|
* Output:
|
|
* Returns How far (in bytes) the found symbol is from the address.
|
|
* CV_MAXOFFSET is returned if non is found.
|
|
*
|
|
*
|
|
*************************************************************************/
|
|
|
|
CV_uoff32_t LOADDS PASCAL PHGetNearestHsym (
|
|
LPADDR lpaddr,
|
|
HEXE hexe,
|
|
PHSYM phsym
|
|
) {
|
|
CV_uoff32_t dCur = CV_MAXOFFSET;
|
|
LPEXS lpexs = NULL;
|
|
LPEXG lpexg = NULL;
|
|
|
|
*phsym = NULL;
|
|
|
|
if ( !VerifyHexe ( hexe ) ) {
|
|
return dCur;
|
|
}
|
|
|
|
lpexs = LLLock ( hexe );
|
|
|
|
if ( lpexs->hexg != hexgNull ) {
|
|
lpexg = LLLock ( lpexs->hexg );
|
|
*phsym = FindNearest (lpexg, lpaddr, &dCur);
|
|
LLUnlock( lpexs->hexg );
|
|
}
|
|
|
|
LLUnlock( hexe );
|
|
|
|
return dCur;
|
|
}
|
|
|
|
|
|
BOOL PASCAL LOADDS PHGetAddr ( LPADDR paddr, LSZ lszName ) {
|
|
HSYM hsym = NULL;
|
|
HEXE hexe = 0;
|
|
SSTR sstr = {0};
|
|
|
|
if ( lszName == NULL || *lszName == '\0' ) {
|
|
return FALSE;
|
|
}
|
|
|
|
sstr.lpName = lszName;
|
|
sstr.cb = (BYTE) _ftcslen ( lszName );
|
|
|
|
if ( !( hsym = PHFindNameInPublics (
|
|
NULL,
|
|
hexe = SHGetNextExe ( hexeNull ),
|
|
(LPSSTR) &sstr,
|
|
TRUE,
|
|
PHExactCmp
|
|
) ) ) {
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
SHAddrFromHsym ( paddr, hsym );
|
|
|
|
assert ( hexe );
|
|
emiAddr ( *paddr ) = hexe;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*** PHFindNameInPublics
|
|
*
|
|
* Purpose: To find a public symbol
|
|
*
|
|
* Input:
|
|
* hsym - This must be NULL! In the future this routine may
|
|
* be a find first find next behavior. For a first
|
|
* find use NULL, for a next find use the last symbol.
|
|
* hExe - The exe to search
|
|
* hInfo - The info packet to give to the comparison routine
|
|
* fCase - If TRUE do a case sensitive search.
|
|
* pfnCm - A pointer to the comparison function
|
|
*
|
|
* Output:
|
|
* Returns A public symbol or NULL on error
|
|
*
|
|
* Exceptions: For now, the input hsym MUST BE NULL!
|
|
*
|
|
*************************************************************************/
|
|
|
|
#define dwrd_toupper(dw) (dw & 0xDFDFDFDF)
|
|
#define byt_toupper(b) (b & 0xDF)
|
|
|
|
#define HASHFUNC(i,lpsstr,wModulo,lpul) \
|
|
((i==6)?DWordXor(lpsstr,wModulo,lpul):DWordXorShift(lpsstr,wModulo,lpul))
|
|
|
|
ushort DWordXor ( LPSSTR lpsstr, WORD wModulo, LPUL lpul ) {
|
|
LPB lpbName = lpsstr->lpName;
|
|
UNALIGNED ULONG * lpulName = (UNALIGNED ULONG*) lpbName;
|
|
int cb = lpsstr->cb;
|
|
int cul;
|
|
int iul;
|
|
ULONG ulSum = 0;
|
|
ULONG ulEnd = 0;
|
|
|
|
while ( cb & 3 ) {
|
|
ulEnd |= byt_toupper ( lpbName [ cb - 1 ] );
|
|
ulEnd <<= 8;
|
|
cb -= 1;
|
|
}
|
|
|
|
cul = cb / 4;
|
|
|
|
for ( iul = 0; iul < cul; iul++ ) {
|
|
ulSum ^= dwrd_toupper(lpulName[iul]);
|
|
}
|
|
ulSum ^= ulEnd;
|
|
|
|
*lpul = ulSum;
|
|
|
|
return (ushort) (ulSum % wModulo);
|
|
}
|
|
|
|
ushort DWordXorShift ( LPSSTR lpsstr, WORD wModulo, LPUL lpul ) {
|
|
LPB lpbName = lpsstr->lpName;
|
|
UNALIGNED ULONG* lpulName = (UNALIGNED ULONG*) lpbName;
|
|
int cb = lpsstr->cb;
|
|
int cul;
|
|
int iul;
|
|
ULONG ulSum = 0;
|
|
ULONG ulEnd = 0;
|
|
|
|
while ( cb & 3 ) {
|
|
ulEnd |= byt_toupper ( lpbName [ cb - 1 ] );
|
|
ulEnd <<= 8;
|
|
cb -= 1;
|
|
}
|
|
|
|
cul = cb / 4;
|
|
|
|
for ( iul = 0; iul < cul; iul++ ) {
|
|
ulSum ^= dwrd_toupper(lpulName[iul]);
|
|
ulSum = _lrotl ( ulSum, 4 );
|
|
}
|
|
ulSum ^= ulEnd;
|
|
|
|
*lpul = ulSum;
|
|
|
|
return (ushort) (ulSum % wModulo);
|
|
}
|
|
|
|
|
|
|
|
|
|
HSYM LOADDS PASCAL PHFindNameInPublics (
|
|
HSYM hsym,
|
|
HEXE hexe,
|
|
LPSSTR lpsstr,
|
|
SHFLAG fCase,
|
|
PFNCMP pfnCmp
|
|
) {
|
|
SYMPTR psym = (SYMPTR) hsym;
|
|
LPEXS lpexs = NULL;
|
|
LPEXG lpexg = NULL;
|
|
|
|
if ( hexe == hexeNull ) {
|
|
return NULL;
|
|
}
|
|
|
|
lpexs = LLLock ( hexe );
|
|
|
|
if ( lpexs->hexg == hexgNull ) {
|
|
psym = (SYMPTR)NULL;
|
|
}
|
|
else {
|
|
lpexg = LLLock ( lpexs->hexg );
|
|
if ( lpsstr->searchmask & SSTR_NoHash )
|
|
psym = FindNameLinearInPubs (lpexg, psym, lpsstr, pfnCmp, fCase);
|
|
else
|
|
psym = FindNameHashedInPubs (lpexg, psym, lpsstr, pfnCmp, fCase, NULL);
|
|
LLUnlock ( lpexs->hexg );
|
|
}
|
|
|
|
LLUnlock ( hexe );
|
|
|
|
return psym;
|
|
}
|
|
|
|
|
|
int LOADDS PASCAL SHPublicNameToAddr ( PADDR loc, PADDR pMpAddr, LSZ lszName ) {
|
|
CXT cxt = {0};
|
|
HSYM hsym = NULL;
|
|
int wRet = FALSE;
|
|
ADDR addr = *loc;
|
|
SSTR sstr = {0};
|
|
|
|
sstr.lpName = lszName;
|
|
sstr.cb = (BYTE) _ftcslen ( lszName );
|
|
|
|
// Look for the name in the public symbols of that .EXE
|
|
hsym = PHFindNameInPublics (
|
|
NULL, emiAddr ( addr ), &sstr, 0 , PHExactCmp
|
|
);
|
|
|
|
if ( hsym ) {
|
|
SYMPTR psym = (SYMPTR) hsym;
|
|
|
|
switch ( psym->rectyp ) {
|
|
|
|
case S_PUB16:
|
|
ADDRSEG16 ( *pMpAddr );
|
|
SetAddrSeg ( pMpAddr, ((DATAPTR16)psym)->seg);
|
|
SetAddrOff ( pMpAddr, ((DATAPTR16)psym)->off);
|
|
break;
|
|
case S_PUB32:
|
|
ADDRLIN32 ( *pMpAddr );
|
|
SetAddrSeg ( pMpAddr, ((DATAPTR32)psym)->seg);
|
|
SetAddrOff ( pMpAddr, ((DATAPTR32)psym)->off);
|
|
break;
|
|
}
|
|
|
|
ADDR_IS_LI ( *pMpAddr ) = TRUE;
|
|
emiAddr ( *pMpAddr ) = emiAddr ( addr );
|
|
wRet = TRUE;
|
|
}
|
|
|
|
return wRet;
|
|
}
|
|
|
|
ULONG GSTBSearch (
|
|
UOFFSET uoffKey,
|
|
LPALM lpalm,
|
|
ULONG ibBase,
|
|
ULONG cb,
|
|
UOFFSET FAR *lpoff
|
|
) {
|
|
ULONG ibLow;
|
|
ULONG ibHigh;
|
|
ULONG ibMid = 0;
|
|
ULONG cbWidth = sizeof ( ULP );
|
|
ULONG uoffFound = 0;
|
|
|
|
LPULP lpulp = NULL;
|
|
|
|
ibLow = 0;
|
|
ibHigh = cb;
|
|
|
|
while ( ibLow < ibHigh ) {
|
|
|
|
ibMid = ( ibLow + ibHigh ) / 2;
|
|
|
|
uoffFound =
|
|
( (LPULP) ( LpvFromAlmLfo ( lpalm, ibBase + ibMid * cbWidth ) ) )->ulId;
|
|
|
|
if ( uoffFound > uoffKey ) {
|
|
ibHigh = ibMid;
|
|
}
|
|
else if ( uoffKey > uoffFound ) {
|
|
ibLow = ibMid + 1;
|
|
}
|
|
else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( uoffFound > uoffKey && ibMid != 0 ) {
|
|
ibMid -= 1;
|
|
}
|
|
|
|
lpulp = LpvFromAlmLfo ( lpalm, ibBase + ibMid * cbWidth );
|
|
|
|
*lpoff = lpulp->ulId;
|
|
return lpulp->ib;
|
|
|
|
}
|
|
|
|
__inline SYMPTR FindNameLinearInGlobs (
|
|
LPEXG lpexg,
|
|
SYMPTR psym,
|
|
LPSSTR lpsstr,
|
|
PFNCMP pfnCmp,
|
|
SHFLAG fCase
|
|
)
|
|
{
|
|
#ifdef HOST32
|
|
if (lpexg->pgsiGlobs)
|
|
return GSIFindNameLinear(lpexg, lpexg->pgsiGlobs, psym, lpsstr, pfnCmp, fCase);
|
|
else
|
|
#endif
|
|
return GSTFindNameLinear(lpexg, &lpexg->gstGlobals, psym, lpsstr, pfnCmp, fCase);
|
|
}
|
|
|
|
__inline SYMPTR FindNameLinearInPubs (
|
|
LPEXG lpexg,
|
|
SYMPTR psym,
|
|
LPSSTR lpsstr,
|
|
PFNCMP pfnCmp,
|
|
SHFLAG fCase
|
|
)
|
|
{
|
|
#ifdef HOST32
|
|
if (lpexg->pgsiPubs)
|
|
return GSIFindNameLinear(lpexg, lpexg->pgsiPubs, psym, lpsstr, pfnCmp, fCase);
|
|
else
|
|
#endif
|
|
return GSTFindNameLinear(lpexg, &lpexg->gstPublics, psym, lpsstr, pfnCmp, fCase);
|
|
}
|
|
|
|
SYMPTR GSTFindNameLinear (
|
|
LPEXG lpexg,
|
|
LPGST lpgst,
|
|
SYMPTR psym,
|
|
LPSSTR lpsstr,
|
|
PFNCMP pfnCmp,
|
|
SHFLAG fCase
|
|
) {
|
|
SYMPTR psymRet = NULL;
|
|
|
|
if ( lpgst->lpalm == NULL )
|
|
return (SYMPTR)NULL;
|
|
|
|
if ( psym == NULL ) {
|
|
psym = LpvFromAlmLfo ( lpgst->lpalm, 0 );
|
|
}
|
|
else {
|
|
psym = GetNextSym ( lpexg->lszDebug, psym );
|
|
}
|
|
|
|
while ( psym != NULL ) {
|
|
SYMPTR psymT = psym;
|
|
|
|
// NOTE: Don't find referenced procs/data in linear search
|
|
|
|
if (
|
|
psym->rectyp != S_PROCREF &&
|
|
psym->rectyp != S_DATAREF &&
|
|
GSTCmpName ( psymT, lpsstr, pfnCmp, fCase )
|
|
) {
|
|
psymRet = psymT;
|
|
break;
|
|
}
|
|
|
|
psym = GetNextSym ( lpexg->lszDebug, psym );
|
|
}
|
|
|
|
return psym;
|
|
}
|
|
|
|
#ifdef HOST32 // {
|
|
SYMPTR GSIFindNameLinear (
|
|
LPEXG lpexg,
|
|
GSI* pgsi,
|
|
SYMPTR psym,
|
|
LPSSTR lpsstr,
|
|
PFNCMP pfnCmp,
|
|
SHFLAG fCase
|
|
) {
|
|
SYMPTR psymRet = NULL;
|
|
|
|
if ( pgsi == NULL )
|
|
return (SYMPTR)NULL;
|
|
|
|
psym = (SYMPTR) GSINextSym (pgsi, (PB) psym);
|
|
while ( psym != NULL ) {
|
|
SYMPTR psymT = psym;
|
|
|
|
// NOTE: Don't find referenced procs/data in linear search
|
|
|
|
if ((psym->rectyp != S_PROCREF) &&
|
|
(psym->rectyp != S_LPROCREF) &&
|
|
GSTCmpName ( psymT, lpsstr, pfnCmp, fCase )
|
|
) {
|
|
psymRet = psymT;
|
|
break;
|
|
}
|
|
|
|
psym = (SYMPTR) GSINextSym (pgsi, (PB) psym);
|
|
}
|
|
|
|
return psym;
|
|
}
|
|
#endif // }
|
|
|
|
__inline SYMPTR FindNameHashedInGlobs (
|
|
LPEXG lpexg,
|
|
SYMPTR psym,
|
|
LPSSTR lpsstr,
|
|
PFNCMP pfnCmp,
|
|
SHFLAG fCase,
|
|
HMOD FAR *lphmod
|
|
) {
|
|
#ifdef HOST32 //{
|
|
if (lpexg->pgsiGlobs)
|
|
return GSIFindNameHashed (lpexg, lpexg->pgsiGlobs, psym, lpsstr, pfnCmp, fCase, lphmod);
|
|
else
|
|
#endif // }
|
|
return GSTFindNameHashed (lpexg, &lpexg->gstGlobals, psym, lpsstr, pfnCmp, fCase, lphmod);
|
|
}
|
|
|
|
__inline SYMPTR FindNameHashedInStatics (
|
|
LPEXG lpexg,
|
|
SYMPTR psym,
|
|
LPSSTR lpsstr,
|
|
PFNCMP pfnCmp,
|
|
SHFLAG fCase,
|
|
HMOD FAR *lphmod
|
|
) {
|
|
#ifdef HOST32 //{
|
|
if (lpexg->pgsiGlobs)
|
|
// this assumes that the client has already completed an unsucessful search
|
|
// thru the globals
|
|
return (SYMPTR)NULL;
|
|
else
|
|
#endif // }
|
|
return GSTFindNameHashed (lpexg, &lpexg->gstStatics, psym, lpsstr, pfnCmp, fCase, lphmod);
|
|
}
|
|
|
|
__inline SYMPTR FindNameHashedInPubs (
|
|
LPEXG lpexg,
|
|
SYMPTR psym,
|
|
LPSSTR lpsstr,
|
|
PFNCMP pfnCmp,
|
|
SHFLAG fCase,
|
|
HMOD FAR *lphmod)
|
|
{
|
|
#ifdef HOST32 //{
|
|
if (lpexg->pgsiPubs)
|
|
return GSIFindNameHashed (lpexg, lpexg->pgsiPubs, psym, lpsstr, pfnCmp, fCase, lphmod);
|
|
else
|
|
#endif // }
|
|
return GSTFindNameHashed (lpexg, &lpexg->gstPublics, psym, lpsstr, pfnCmp, fCase, lphmod);
|
|
}
|
|
|
|
SYMPTR GSTFindNameHashed (
|
|
LPEXG lpexg,
|
|
LPGST lpgst,
|
|
SYMPTR psym,
|
|
LPSSTR lpsstr,
|
|
PFNCMP pfnCmp,
|
|
SHFLAG fCase,
|
|
HMOD FAR *lphmod
|
|
) {
|
|
LPSHT lpsht = &lpgst->shtName;
|
|
ULONG ulId = 0;
|
|
WORD iib = 0;
|
|
SYMPTR psymRet = NULL;
|
|
|
|
ULONG ib = 0;
|
|
ULONG culp = 0;
|
|
ULONG iulp = 0;
|
|
|
|
BOOL fNext = psym != NULL;
|
|
|
|
if (( lpsht->ccib == 0 ) ||( lpgst->lpalm == NULL ))
|
|
return (SYMPTR)NULL;
|
|
|
|
iib = HASHFUNC(lpsht->HashIndex, lpsstr, lpsht->ccib, &ulId );
|
|
|
|
ib = lpsht->rgib [ iib ];
|
|
culp = lpsht->rgcib [ iib ];
|
|
|
|
// Loop through all the entries in this bucket
|
|
|
|
for ( iulp = 0; iulp < culp; iulp++ ) {
|
|
|
|
LPULP lpulp = LpvFromAlmLfo (
|
|
lpsht->lpalm,
|
|
ib + ( iulp * sizeof ( ULP ) )
|
|
);
|
|
|
|
if ( lpulp == NULL ) {
|
|
return NULL;
|
|
}
|
|
|
|
if ( lpulp->ulId == ulId ) {
|
|
HMOD hmodT = hmodNull;
|
|
|
|
// Checksums match, now check the symbols themselves
|
|
|
|
SYMPTR psymT = LpvFromAlmLfo (
|
|
lpgst->lpalm,
|
|
lpulp->ib
|
|
);
|
|
|
|
if ( psymT == NULL ) {
|
|
return NULL;
|
|
}
|
|
|
|
if ( psymT->rectyp == S_PROCREF ||
|
|
psymT->rectyp == S_DATAREF ) {
|
|
|
|
psymT = PsymFromRef ( lpexg, psymT, &hmodT );
|
|
|
|
// catch case where there are no module symbols... [rm]
|
|
if (psymT == NULL)
|
|
return NULL;
|
|
}
|
|
|
|
if ( fNext ) {
|
|
|
|
/*
|
|
** We need to get back to the Current hsym before get can
|
|
** get just one more. Soon as we are there we know we can
|
|
** get the next one.
|
|
*/
|
|
|
|
if ( psymT == psym ) {
|
|
fNext = FALSE;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if ( GSTCmpName ( psymT, lpsstr, pfnCmp, fCase ) ) {
|
|
if ( lphmod ) *lphmod = hmodT;
|
|
psymRet = psymT;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return psymRet;
|
|
}
|
|
|
|
#ifdef HOST32 //{
|
|
SYMPTR GSIFindNameHashed (
|
|
LPEXG lpexg,
|
|
GSI* pgsi,
|
|
SYMPTR psym,
|
|
LPSSTR lpsstr,
|
|
PFNCMP pfnCmp,
|
|
SHFLAG fCase,
|
|
HMOD FAR *lphmod
|
|
) {
|
|
HMOD hmodT = hmodNull;
|
|
char szBuf[256];
|
|
SYMPTR psymGS;
|
|
SYMPTR psymRet;
|
|
|
|
BOOL fNext = psym != NULL;
|
|
|
|
if (!pgsi)
|
|
return (SYMPTR)NULL;
|
|
|
|
memcpy(szBuf, lpsstr->lpName, lpsstr->cb);
|
|
szBuf[lpsstr->cb] = 0;
|
|
|
|
psymGS = (SYMPTR) GSIHashSym(pgsi, szBuf, (PB) psym);
|
|
|
|
for ( ; psymGS; psymGS = (SYMPTR) GSIHashSym(pgsi, szBuf, (PB) psymGS)) {
|
|
assert(psymGS->rectyp != S_DATAREF); // no datarefs
|
|
if (( psymGS->rectyp == S_PROCREF) ||
|
|
( psymGS->rectyp == S_LPROCREF)) {
|
|
|
|
psymRet = PsymFromRef ( lpexg, psymGS, &hmodT );
|
|
|
|
// catch case where there are no module symbols... [rm]
|
|
if (psymRet == NULL)
|
|
return NULL;
|
|
}
|
|
else
|
|
psymRet = psymGS;
|
|
|
|
if ( fNext ) {
|
|
|
|
/*
|
|
** We need to get back to the Current hsym before get can
|
|
** get just one more. Soon as we are there we know we can
|
|
** get the next one.
|
|
*/
|
|
|
|
if ( psymRet == psym ) {
|
|
fNext = FALSE;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if ( GSTCmpName ( psymRet, lpsstr, pfnCmp, fCase ) ) {
|
|
if ( lphmod ) *lphmod = hmodT;
|
|
return psymRet;
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
#endif // }
|
|
|
|
__inline SYMPTR FindNearest ( LPEXG lpexg, LPADDR lpaddr, LPL lpdb )
|
|
{
|
|
SYMPTR symptr;
|
|
|
|
#ifdef HOST32
|
|
if (lpexg->pgsiPubs)
|
|
#pragma message ("Need to search pgsiGlobals in FindNearest for NB10")
|
|
return (SYMPTR) GSINearestSym (lpexg->pgsiPubs, GetAddrSeg(*lpaddr),
|
|
GetAddrOff(*lpaddr), lpdb);
|
|
else
|
|
#endif
|
|
{
|
|
#ifndef NO_GLOBAL_SRCH
|
|
SYMPTR symptrT;
|
|
LONG db;
|
|
|
|
// Search first in globals
|
|
symptr = GSTFindNearest(lpexg, &lpexg->gstGlobals, lpaddr, lpdb);
|
|
|
|
// Search in publics
|
|
symptrT = GSTFindNearest(lpexg, &lpexg->gstPublics, lpaddr, &db);
|
|
|
|
// If there's an entry in the publics AND there was either
|
|
// no match in the globals or the delta for the public is
|
|
// less than the delta for the global, use the public
|
|
if ( symptrT && ( !symptr || labs( db ) < labs ( *lpdb ) ) ) {
|
|
*lpdb = db;
|
|
symptr = symptrT;
|
|
}
|
|
#else // NO_GLOBAL_SRCH
|
|
symptr = GSTFindNearest(lpexg, &lpexg->gstPublics, lpaddr, &db);
|
|
#endif // NO_GLOBAL_SRCH
|
|
}
|
|
|
|
return symptr;
|
|
}
|
|
|
|
SYMPTR GSTFindNearest ( LPEXG lpexg, LPGST lpgst, LPADDR lpaddr, LPL lpdb ) {
|
|
SYMPTR psym = NULL;
|
|
LONG db = CV_MAXOFFSET;
|
|
LPSHT lpsht = &lpgst->shtAddr;
|
|
WORD iseg = GetAddrSeg ( *lpaddr ) - 1;
|
|
ULONG ibSym = (ULONG) -1;
|
|
OFFSET off = GetAddrOff ( *lpaddr );
|
|
|
|
if ( lpgst->lpalm == NULL )
|
|
return NULL;
|
|
|
|
if (
|
|
iseg != 0xFFFF &&
|
|
iseg < lpsht->ccib &&
|
|
lpsht->rgcib [ iseg ] > 0
|
|
|
|
) {
|
|
OFFSET offT = 0;
|
|
|
|
ibSym = GSTBSearch (
|
|
off,
|
|
lpsht->lpalm,
|
|
lpsht->rgib [ iseg ],
|
|
(WORD) lpsht->rgcib [ iseg ],
|
|
&offT
|
|
);
|
|
|
|
db = off - offT;
|
|
|
|
psym = LpvFromAlmLfo ( lpgst->lpalm, ibSym );
|
|
|
|
#ifndef NO_GLOBAL_SRCH
|
|
if ( psym->rectyp == S_PROCREF || psym->rectyp == S_DATAREF ) {
|
|
HMOD hmodT = hmodNull;
|
|
|
|
psym = PsymFromRef( lpexg, psym, &hmodT );
|
|
|
|
// Couldn't get the ref, set the db to what
|
|
// would be returned in an error condition
|
|
if ( !psym ) {
|
|
db = CV_MAXOFFSET;
|
|
}
|
|
}
|
|
#endif // NO_GLOBAL_SRCH
|
|
}
|
|
|
|
*lpdb = db;
|
|
return psym;
|
|
}
|
|
|
|
SYMPTR PsymFromRef ( LPEXG lpexg, SYMPTR psymRef, HMOD FAR *lphmod ) {
|
|
REFSYM FAR *lpref = (REFSYM FAR *) psymRef;
|
|
LPB lpbSymbols = NULL;
|
|
HMOD hmod = hmodNull;
|
|
LPMDS lpmds = NULL;
|
|
|
|
hmod = lpexg->rghmod [ lpref->imod - 1 ];
|
|
lpmds = LLLock ( hmod );
|
|
|
|
lpbSymbols = (LPB) GetSymbols ( lpmds );
|
|
|
|
if ( lphmod ) {
|
|
*lphmod = hmod;
|
|
}
|
|
|
|
LLUnlock( hmod );
|
|
|
|
// catch case where there are no module symbols...
|
|
if (lpbSymbols == NULL)
|
|
return NULL;
|
|
|
|
return (SYMPTR) (lpbSymbols + (WORD) lpref->ibSym);
|
|
}
|
|
|
|
BOOL GSTCmpName (
|
|
SYMPTR psym,
|
|
LPSSTR lpsstr,
|
|
PFNCMP pfnCmp,
|
|
SHFLAG fCase
|
|
) {
|
|
LSZ lsz = NULL;
|
|
|
|
// We are basically ignoring publics with set == 0
|
|
|
|
if (
|
|
( psym->rectyp == S_PUB16 && ( (DATAPTR16) psym )->seg == 0 ) ||
|
|
( psym->rectyp == S_PUB32 && ( (DATAPTR32) psym )->seg == 0 )
|
|
) {
|
|
return FALSE;
|
|
}
|
|
|
|
lsz = SHlszGetSymName ( psym );
|
|
|
|
if ( lsz != NULL ) {
|
|
|
|
return
|
|
( !( lpsstr->searchmask & SSTR_symboltype ) ||
|
|
( psym->rectyp == lpsstr->symtype )
|
|
) &&
|
|
!(*pfnCmp) ( lpsstr, psym, lsz, fCase );
|
|
}
|
|
else {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*** SHFindNameInGlobal
|
|
*
|
|
* Purpose: To look for the name in the global symbol table.
|
|
*
|
|
* Input:
|
|
* hSym - The starting symbol, if NULL, then the first symbol
|
|
* in the global symbol table is used. (NULL is find first).
|
|
* pCXT - The context to do the search.
|
|
* lpsstr - pointer to search parameters (passed to the compare routine)
|
|
* fCaseSensitive - TRUE/FALSE on a case sensitive search
|
|
* pfnCmp - A pointer to the comparison routine
|
|
* fChild - TRUE if all child block are to be searched, FALSE if
|
|
* only the current block is to be searched.
|
|
*
|
|
* Output:
|
|
* pCXTOut - The context generated
|
|
* Returns:
|
|
* - A handle to the symbol found, NULL if not found
|
|
*
|
|
* Exceptions:
|
|
*
|
|
* Notes:
|
|
* If an hSym is specified, the hMod, hGrp and addr MUST be
|
|
* valid and consistant with each other! If hSym is NULL only
|
|
* the hMod must be valid. The specification of an hSym
|
|
* forces a search from the next symbol to the end of the
|
|
* module scope. Continues searches may only be done at
|
|
* module scope.
|
|
*
|
|
* If an hGrp is given it must be consistant with the hMod!
|
|
*
|
|
*
|
|
*************************************************************************/
|
|
|
|
HSYM LOADDS PASCAL SHFindNameInGlobal (
|
|
HSYM hsym,
|
|
PCXT pcxt,
|
|
LPSSTR lpsstr,
|
|
SHFLAG fCase,
|
|
PFNCMP pfnCmp,
|
|
SHFLAG fChild,
|
|
PCXT pcxtOut
|
|
) {
|
|
HEXG hexg = hexgNull;
|
|
HMOD hmod = hmodNull;
|
|
LPEXG lpexg = NULL;
|
|
LPGST lpgst = NULL;
|
|
SYMPTR psym = NULL;
|
|
|
|
Unreferenced( fChild );
|
|
|
|
*pcxtOut = *pcxt;
|
|
pcxtOut->hProc = NULL;
|
|
pcxtOut->hBlk = NULL;
|
|
|
|
if ( !pcxt->hMod ) {
|
|
return NULL;
|
|
}
|
|
hexg = SHHexgFromHmod ( pcxt->hMod );
|
|
|
|
lpexg = LLLock ( hexg );
|
|
|
|
if ( lpsstr->searchmask & SSTR_NoHash ) {
|
|
psym = FindNameLinearInGlobs (
|
|
lpexg, hsym, lpsstr, pfnCmp, fCase
|
|
);
|
|
}
|
|
else {
|
|
|
|
psym = FindNameHashedInGlobs (
|
|
lpexg, hsym, lpsstr, pfnCmp, fCase, &hmod
|
|
);
|
|
|
|
if ( hmod != hmodNull ) {
|
|
pcxtOut->hMod = pcxt->hGrp = hmod;
|
|
|
|
switch ( psym->rectyp ) {
|
|
|
|
case S_LPROC32:
|
|
case S_GPROC32:
|
|
case S_LPROC16:
|
|
case S_GPROC16:
|
|
case S_LPROCMIPS:
|
|
case S_GPROCMIPS:
|
|
|
|
emiAddr ( pcxtOut->addr ) = SHHexeFromHmod ( hmod );
|
|
SHAddrFromHsym ( &pcxtOut->addr, psym );
|
|
pcxtOut->hProc = psym;
|
|
break;
|
|
|
|
default: {
|
|
LPMDS lpmds = LLLock ( hmod );
|
|
|
|
SetAddrFromMod(lpmds, &pcxtOut->addr);
|
|
emiAddr ( pcxtOut->addr ) = SHHexeFromHmod ( hmod );
|
|
ADDR_IS_LI ( pcxtOut->addr ) = TRUE;
|
|
|
|
LLUnlock ( hmod );
|
|
break;
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
LLUnlock ( hexg );
|
|
return psym;
|
|
}
|
|
|
|
|
|
|
|
HSYM PASCAL FindNameInStatics (
|
|
HSYM hsym,
|
|
PCXT pcxt,
|
|
LPSSTR lpsstr,
|
|
SHFLAG fCase,
|
|
PFNCMP pfnCmp,
|
|
PCXT pcxtOut
|
|
) {
|
|
HEXG hexg = hexgNull;
|
|
HMOD hmod = hmodNull;
|
|
LPEXG lpexg = NULL;
|
|
LPGST lpgst = NULL;
|
|
SYMPTR psym = NULL;
|
|
|
|
*pcxtOut = *pcxt;
|
|
pcxtOut->hProc = NULL;
|
|
pcxtOut->hBlk = NULL;
|
|
|
|
if ( !pcxt->hGrp ) {
|
|
return NULL;
|
|
}
|
|
|
|
hexg = SHHexgFromHmod ( pcxt->hGrp );
|
|
lpexg = LLLock ( hexg );
|
|
|
|
psym = FindNameHashedInStatics(lpexg, hsym, lpsstr, pfnCmp, fCase, &hmod);
|
|
|
|
if ( hmod != hmodNull ) {
|
|
pcxtOut->hMod = pcxt->hGrp = hmod;
|
|
|
|
switch ( psym->rectyp ) {
|
|
|
|
case S_LPROC32:
|
|
case S_GPROC32:
|
|
case S_LPROC16:
|
|
case S_GPROC16:
|
|
case S_LPROCMIPS:
|
|
case S_GPROCMIPS:
|
|
|
|
emiAddr ( pcxtOut->addr ) = SHHexeFromHmod ( hmod );
|
|
SHAddrFromHsym ( &pcxtOut->addr, psym );
|
|
pcxtOut->hProc = psym;
|
|
break;
|
|
|
|
default: {
|
|
LPMDS lpmds = LLLock ( hmod );
|
|
|
|
SetAddrFromMod(lpmds, &pcxtOut->addr);
|
|
emiAddr ( pcxtOut->addr ) = SHHexeFromHmod ( hmod );
|
|
ADDR_IS_LI ( pcxtOut->addr ) = TRUE;
|
|
|
|
LLUnlock ( hmod );
|
|
break;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
LLUnlock ( hexg );
|
|
return psym;
|
|
}
|
|
|
|
BOOL PASCAL VerifyHexe ( HEXE hexe ) {
|
|
HEXE hexeT = 0;
|
|
static BOOL fFound = FALSE;
|
|
static HEXE hexeSave = 0;
|
|
|
|
if ( hexe == hexeNull ) {
|
|
return FALSE;
|
|
}
|
|
|
|
if ( hexe == hexeSave ) {
|
|
return fFound;
|
|
}
|
|
else {
|
|
hexeSave = hexe;
|
|
fFound = FALSE;
|
|
}
|
|
|
|
while( !fFound && ( hexeT = SHGetNextExe ( hexeT ) ) ) {
|
|
if ( hexeT == hexe ) {
|
|
fFound = TRUE;
|
|
}
|
|
}
|
|
|
|
return fFound;
|
|
}
|