2020-09-30 17:12:29 +02:00

1165 lines
27 KiB
C++

// ph.cxx
//
// Copyright <C> 1989-94, 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.
//
// 11/1/94 BryanT
// Merge in NT changes
// Remove fChild arg from SHFindNameInGlobal (unused)
#include "shinc.hpp"
#pragma hdrstop
BOOL VerifyHexe (HEXE);
ULONG GSTBSearch (UOFFSET, LPALM, ULONG, ULONG, UOFFSET *);
__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 *);
__inline SYMPTR FindNameHashedInStatics(LPEXG, SYMPTR, LPSSTR, PFNCMP, SHFLAG, HMOD *);
__inline SYMPTR FindNameHashedInPubs (LPEXG, SYMPTR, LPSSTR, PFNCMP, SHFLAG, HMOD *);
SYMPTR GSTFindNameHashed (LPEXG, LPGST, SYMPTR, LPSSTR, PFNCMP, SHFLAG, HMOD *);
__inline SYMPTR FindNearest (LPEXG, LPADDR, LPL);
SYMPTR GSTFindNearest (LPEXG, LPGST, LPADDR, LPL);
SYMPTR PsymFromRef (LPEXG, SYMPTR, HMOD *);
BOOL GSTCmpName (SYMPTR, LPSSTR, PFNCMP, SHFLAG);
SYMPTR GSIFindNameLinear (LPEXG, GSI*, SYMPTR, LPSSTR, PFNCMP, SHFLAG);
SYMPTR GSIFindNameHashed (LPEXG, GSI*, SYMPTR, LPSSTR, PFNCMP, SHFLAG, HMOD *);
__inline void lpStrToSz(LPSSTR lpsstr, char* sz)
{
assert(lpsstr->cb < 256);
memcpy(sz, lpsstr->lpName, lpsstr->cb);
sz[lpsstr->cb] = 0;
}
// PHExactCmp
//
// Purpose: Compare two strings.
//
// Input:
// lsz Zero terminated string for compare
// hsym -- not used --
// lstz Zero terminated length prefixed string for compare
// fCase Perform case sensitive compare?
//
// Output: Return ZERO if strings are equal, else non-zero.
SHFLAG
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) _tcsnicmp(lpb + 1, (_TXCHAR *)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
PHGetNearestHsym(
LPADDR lpaddr,
HEXE hexe,
PHSYM phsym
)
{
CV_uoff32_t dCur = CV_MAXOFFSET;
LPEXE lpexe;
LPEXG lpexg;
*phsym = NULL;
if (!VerifyHexe (hexe)) {
return dCur;
}
lpexe = (LPEXE) LLLock (hexe);
if (lpexe->hexg != hexgNull) {
lpexg = (LPEXG) LLLock (lpexe->hexg);
*phsym = FindNearest (lpexg, lpaddr, (LPL) &dCur);
LLUnlock(lpexe->hexg);
}
LLUnlock(hexe);
return dCur;
}
BOOL
PHGetAddr(
LPADDR paddr,
LSZ lszName
)
{
HSYM hsym = NULL;
HEXE hexe = 0;
SSTR sstr = {0};
if (lszName == NULL || *lszName == '\0') {
return FALSE;
}
sstr.lpName = (LPB) lszName;
sstr.cb = (BYTE) _tcslen (lszName);
if (!(hsym = PHFindNameInPublics (NULL,
hexe = SHGetNextExe (hexeNull),
(LPSSTR) &sstr,
TRUE,
PHExactCmp)))
{
return FALSE;
}
SHAddrFromHsym (paddr, hsym);
assert (hexe);
emiAddr (*paddr) = (HEMI) 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
PHFindNameInPublics(
HSYM hsym,
HEXE hexe,
LPSSTR lpsstr,
SHFLAG fCase,
PFNCMP pfnCmp
)
{
SYMPTR psym = (SYMPTR) hsym;
LPEXE lpexe;
LPEXG lpexg;
if (hexe == hexeNull) {
return NULL;
}
lpexe = (LPEXE) LLLock (hexe);
if (lpexe->hexg == hexgNull) {
psym = (SYMPTR)NULL;
} else {
lpexg = (LPEXG) LLLock (lpexe->hexg);
if (lpsstr->searchmask & SSTR_NoHash)
psym = FindNameLinearInPubs (lpexg, psym, lpsstr, pfnCmp, fCase);
else
psym = FindNameHashedInPubs (lpexg, psym, lpsstr, pfnCmp, fCase, NULL);
LLUnlock (lpexe->hexg);
}
LLUnlock (hexe);
return psym;
}
int
SHPublicNameToAddr(
PADDR loc,
PADDR pMpAddr,
LSZ lszName
)
{
CXT cxt = {0};
HSYM hsym = NULL;
int wRet = FALSE;
ADDR addr = *loc;
SSTR sstr = {0};
sstr.lpName = (LPB) lszName;
sstr.cb = (BYTE) _tcslen (lszName);
// Look for the name in the public symbols of that .EXE
hsym = PHFindNameInPublics( NULL, (HEXE) 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 *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 = (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
)
{
if (lpexg->pgsiGlobs) {
return GSIFindNameLinear(lpexg, lpexg->pgsiGlobs, psym, lpsstr, pfnCmp, fCase);
} else {
return GSTFindNameLinear(lpexg, &lpexg->gstGlobals, psym, lpsstr, pfnCmp, fCase);
}
}
__inline SYMPTR
FindNameLinearInPubs(
LPEXG lpexg,
SYMPTR psym,
LPSSTR lpsstr,
PFNCMP pfnCmp,
SHFLAG fCase
)
{
if (lpexg->pgsiPubs) {
return GSIFindNameLinear(lpexg, lpexg->pgsiPubs, psym, lpsstr, pfnCmp, fCase);
} else {
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 = (SYMPTR) LpvFromAlmLfo (lpgst->lpalm, 0);
} else {
psym = GetNextSym (psym, lpgst->lpalm);
}
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 (psym, lpgst->lpalm);
}
return psym;
}
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;
}
__inline SYMPTR
FindNameHashedInGlobs(
LPEXG lpexg,
SYMPTR psym,
LPSSTR lpsstr,
PFNCMP pfnCmp,
SHFLAG fCase,
HMOD *lphmod
)
{
if (lpexg->pgsiGlobs) {
return GSIFindNameHashed (lpexg, lpexg->pgsiGlobs, psym, lpsstr, pfnCmp, fCase, lphmod);
} else {
return GSTFindNameHashed (lpexg, &lpexg->gstGlobals, psym, lpsstr, pfnCmp, fCase, lphmod);
}
}
__inline SYMPTR
FindNameHashedInStatics(
LPEXG lpexg,
SYMPTR psym,
LPSSTR lpsstr,
PFNCMP pfnCmp,
SHFLAG fCase,
HMOD *lphmod
)
{
if (lpexg->pgsiGlobs)
// this assumes that the client has already completed an unsucessful search
// thru the globals
return (SYMPTR)NULL;
else
return GSTFindNameHashed(lpexg,
&lpexg->gstStatics,
psym,
lpsstr,
pfnCmp,
fCase,
lphmod
);
}
__inline SYMPTR
FindNameHashedInPubs(
LPEXG lpexg,
SYMPTR psym,
LPSSTR lpsstr,
PFNCMP pfnCmp,
SHFLAG fCase,
HMOD *lphmod
)
{
if (lpexg->pgsiPubs) {
return GSIFindNameHashed (lpexg, lpexg->pgsiPubs, psym, lpsstr, pfnCmp, fCase, lphmod);
} else {
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 *lphmod
)
{
LPSHT lpsht = &lpgst->shtName;
if (lpsht->HashIndex == 0) {
// No hash exists. Punt to the linear code.
return(GSTFindNameLinear(lpexg, lpgst, psym, lpsstr, pfnCmp, fCase));
}
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 = (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 = (SYMPTR) 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;
}
SYMPTR
GSIFindNameHashed(
LPEXG lpexg,
GSI* pgsi,
SYMPTR psym,
LPSSTR lpsstr,
PFNCMP pfnCmp,
SHFLAG fCase,
HMOD *lphmod
)
{
HMOD hmodT = hmodNull;
char szBuf[256];
SYMPTR psymGS;
SYMPTR psymRet;
BOOL fNext = psym != NULL;
if (!pgsi)
return (SYMPTR)NULL;
lpStrToSz(lpsstr, szBuf);
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;
}
__inline SYMPTR
FindNearest(
LPEXG lpexg,
LPADDR lpaddr,
LPL lpdb
)
{
SYMPTR symptr;
if (lpexg->pgsiPubs) {
#pragma message ("Need to search pgsiGlobals in FindNearest for NB10")
return (SYMPTR) GSINearestSym (lpexg->pgsiPubs,
GetAddrSeg(*lpaddr), GetAddrOff(*lpaddr), lpdb);
} else {
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;
}
}
return symptr;
}
SYMPTR
GSTFindNearest(
LPEXG lpexg,
LPGST lpgst,
LPADDR lpaddr,
LPL lpdb
)
{
SYMPTR psym;
ULONG db = CV_MAXOFFSET;
LPSHT lpsht = &lpgst->shtAddr;
WORD iseg;
ULONG ibSym = 0;
OFFSET off = GetAddrOff (*lpaddr);
if (lpgst->lpalm == NULL)
return NULL;
// See if there's a hash index. If not, do a linear search.
if (lpsht->HashIndex == 0) {
SYMPTR psymClosest = NULL, psymT, psymEnd;
HMOD hmodT;
psym = (SYMPTR) LpvFromAlmLfo(lpgst->lpalm, ibSym);
psymEnd = (SYMPTR) ((LPB) psym + lpgst->lpalm->cb);
iseg = GetAddrSeg (*lpaddr);
for (; psym < psymEnd; psym = NEXTSYM(SYMPTR, psym)) {
if ((psym->rectyp == S_PROCREF) || (psym->rectyp == S_DATAREF)) {
hmodT = hmodNull;
psymT = PsymFromRef(lpexg, psym, &hmodT);
if (psymT) {
psymT = psym;
}
} else {
psymT = psym;
}
switch (psymT->rectyp) {
case S_PUB16:
if ((iseg == ((DATAPTR16)psymT)->seg) &&
((long) (off - ((DATAPTR16)psymT)->off) >= 0) &&
(db > (off - ((DATAPTR16)psymT)->off ))) {
// we are closer, so save this symbol and offset
db = (ULONG)(off - ((DATAPTR16)psymT)->off);
psymClosest = psymT;
}
break;
case S_PUB32:
if ((iseg == ((DATAPTR32)psymT)->seg) &&
((off - ((DATAPTR16)psymT)->off) >= 0) &&
(db > (off - ((DATAPTR32)psymT)->off))) {
// we are closer, so save this symbol and offset
db = (ULONG) (off - ((DATAPTR32)psymT)->off);
psymClosest = psymT;
}
break;
}
if (db == 0) {
// Got an exact match.
break;
}
}
psym = psymClosest;
} else {
iseg = GetAddrSeg (*lpaddr) - 1;
if (iseg != 0xFFFF &&
iseg < lpsht->ccib &&
lpsht->rgcib [ iseg ] > 0)
{
UOFFSET offT = 0;
ibSym = GSTBSearch (off,
lpsht->lpalm,
lpsht->rgib [ iseg ],
(WORD) lpsht->rgcib [ iseg ],
&offT);
db = (off - offT);
psym = (SYMPTR) LpvFromAlmLfo (lpgst->lpalm, ibSym);
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;
}
}
}
}
*lpdb = (LONG) db;
return psym;
}
SYMPTR
PsymFromRef(
LPEXG lpexg,
SYMPTR psymRef,
HMOD *lphmod
)
{
REFSYM *lpref = (REFSYM *) psymRef;
LPB lpbSymbols;
LPMDS lpmds;
assert(lpref->imod <= lpexg->cMod);
lpmds = &lpexg->rgMod[lpref->imod - 1];
lpbSymbols = (LPB) GetSymbols (lpmds);
if (lphmod) {
*lphmod = (HMOD) lpmds;
}
// catch case where there are no module symbols...
if (lpbSymbols == NULL)
return NULL;
// catch the case where the ibSym is beyond the symbol array
if (lpref->ibSym > lpmds->cbSymbols) {
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 = (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
//
// 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
SHFindNameInGlobal(
HSYM hsym,
PCXT pcxt,
LPSSTR lpsstr,
SHFLAG fCase,
PFNCMP pfnCmp,
PCXT pcxtOut
)
{
HEXG hexg;
LPEXG lpexg;
HEXE hexe;
LPEXE lpexe;
HMOD hmod = hmodNull;
LPGST lpgst = NULL;
SYMPTR psym = NULL;
*pcxtOut = *pcxt;
pcxtOut->hProc = NULL;
pcxtOut->hBlk = NULL;
if (!pcxt->hMod) {
return NULL;
}
hexe = SHHexeFromHmod(pcxt->hGrp ? pcxt->hGrp : pcxt->hMod);
lpexe = (LPEXE) LLLock(hexe);
hexg = lpexe->hexg;
lpexg = (LPEXG) LLLock (hexg);
LLUnlock(hexe);
// Make sure these symbols are loaded.
// SHWantSymbols(hexe);
if (lpsstr->searchmask & SSTR_NoHash) {
psym = FindNameLinearInGlobs (lpexg, (SYMPTR) hsym, lpsstr, pfnCmp, fCase);
} else {
psym = FindNameHashedInGlobs (lpexg, (SYMPTR) 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) = (HEMI) SHHexeFromHmod (hmod);
SHAddrFromHsym (&pcxtOut->addr, psym);
SHHPROCFrompCXT(pcxtOut) = psym;
break;
default: {
LPMDS lpmds = (LPMDS) hmod;
SetAddrFromMod(lpmds, &pcxtOut->addr);
emiAddr (pcxtOut->addr) = (HEMI) SHHexeFromHmod (hmod);
ADDR_IS_LI (pcxtOut->addr) = TRUE;
break;
}
}
}
}
LLUnlock (hexg);
return psym;
}
HSYM
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 = (LPEXG) LLLock (hexg);
psym = FindNameHashedInStatics(lpexg, (SYMPTR) 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) = (HEMI) SHHexeFromHmod (hmod);
SHAddrFromHsym (&pcxtOut->addr, psym);
SHHPROCFrompCXT(pcxtOut) = psym;
break;
default: {
LPMDS lpmds = (LPMDS) hmod;
SetAddrFromMod(lpmds, &pcxtOut->addr);
emiAddr (pcxtOut->addr) = (HEMI) SHHexeFromHmod (hmod);
ADDR_IS_LI (pcxtOut->addr) = TRUE;
break;
}
}
}
LLUnlock (hexg);
return psym;
}
BOOL
VerifyHexe(
HEXE hexe
)
{
HEXE hexeT = 0;
static BOOL fFound = FALSE;
static HEXE hexeSave = 0;
if (hexe == hexeNull) {
return FALSE;
}
if (hexe == hexeSave) {
return fFound;
}
hexeSave = hexe;
fFound = FALSE;
while(!fFound && (hexeT = SHGetNextExe(hexeT))) {
if (hexeT == hexe) {
fFound = TRUE;
}
}
return fFound;
}
// SHFindNameInTypes
//
// Purpose: To look for the name in the UDT table.
//
// Input:
// 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
//
// Output:
// pCXTOut - The context generated
//
// Returns:
// - A handle to the type found, NULL if not found
//
// Notes:
// The hMod in the context must be valid.
HSYM
SHFindNameInTypes(
PCXT pcxt,
LPSSTR lpsstr,
SHFLAG fCase,
PFNCMP pfnCmp,
PCXT pcxtOut
)
{
HEXG hexg = hexgNull;
LPEXG lpexg = NULL;
UDTPTR psym = NULL;
char szBuf[256];
unsigned iHash;
TI ti;
*pcxtOut = *pcxt;
pcxtOut->hProc = NULL;
pcxtOut->hBlk = NULL;
if (!pcxt->hMod || ( lpsstr->searchmask & SSTR_NoHash ))
return NULL;
hexg = SHHexgFromHmod ( pcxt->hMod );
lpexg = (LPEXG)LLLock ( hexg );
if (!lpexg->ptpi) {
LLUnlock ( hexg );
return NULL;
}
if (!STABFindUDTSym(lpexg->pstabUDTSym, lpsstr, pfnCmp, fCase, &psym, &iHash)) {
lpStrToSz(lpsstr, szBuf);
assert(lpexg->ptpi);
if (!TypesQueryTiForUDT(lpexg->ptpi, szBuf, fCase, &ti) ||
!STABAddUDTSym(lpexg->pstabUDTSym, lpsstr, iHash, &psym)) {
LLUnlock ( hexg );
return NULL;
}
assert(psym);
psym->typind = ti;
}
LLUnlock ( hexg );
return (SYMPTR) psym;
}