Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

3770 lines
110 KiB

/*** shsymbol
*
* Copyright <C> 1989, Microsoft Corporation
*
* [02] 31-dec-91 DavidGra
*
* Add Symbol support for assembler.
*
* [01] 02-dec-91 DavidGra
*
* Pass symbol to compare function when SSTR_symboltype bit
* is set only when its rectyp field is equal to the symtype
* field in the SSTR structure.
*
* [00] 15-nov-91 DavidGra
*
* Suppress hashing when the SSTR_NoHash bit it set.
*
*
*
*************************************************************************/
#include "shinc.h"
#pragma hdrstop
#pragma check_stack(off)
//#pragma optimize("",off)
LOCAL VOID NEAR PASCAL CheckHandles ( PCXT );
#if !defined(NDEBUG)
// OMF lock handle flag
static HVOID hLocked = NULL;
#define SHIsOMFLocked (hLocked != NULL)
#else
#define SHIsOMFLocked (FALSE)
#endif
// functions we need from the rest of the world
extern VOID PASCAL UpdateUserEnvir( unsigned short );
extern LPOFP PASCAL GetSFBounds (LPSF, WORD);
extern LPSF PASCAL GetLpsfFromIndex (LPSM, WORD);
extern HPDS hpdsCur;
extern BYTE menu_command;
/****SHADDRFROMSYM - Given a symbol get the offset and seg and return ****
* *
* PURPOSE: *
* *
* INPUTS: *
* *
* OUTPUTS: *
* *
* IMPLEMENTATION: *
* *
* *
***************************************************************************/
VOID LOADDS PASCAL SHAddrFromHsym ( LPADDR paddr, HSYM hsym ) {
SYMPTR psym = (SYMPTR) hsym;
switch ( psym->rectyp ) {
// REVIEW - billjoy - should these macros change now? (ADDRSEG16, etc)
case S_GPROC16:
case S_LPROC16:
case S_BLOCK16:
SetAddrOff ( paddr, ( (PROCPTR16) psym )->off );
SetAddrSeg ( paddr, ( (PROCPTR16) psym )->seg );
ADDRSEG16 ( *paddr );
break;
case S_LABEL16:
SetAddrOff ( paddr, ( (LABELPTR16) psym )->off );
SetAddrSeg ( paddr, ( (LABELPTR16) psym )->seg );
ADDRSEG16 ( *paddr );
break;
case S_THUNK16:
SetAddrOff ( paddr, ( (THUNKPTR16) psym )->off );
SetAddrSeg ( paddr, ( (THUNKPTR16) psym )->seg );
ADDRSEG16 ( *paddr );
break;
case S_WITH16:
SetAddrOff ( paddr, ( (WITHPTR16) psym )->off );
SetAddrSeg ( paddr, ( (WITHPTR16) psym )->seg );
ADDRSEG16 ( *paddr );
break;
case S_BPREL16:
SetAddrOff ( paddr, ( (BPRELPTR16) psym )->off );
ADDRSEG16 ( *paddr );
break;
case S_LDATA16:
case S_GDATA16:
case S_PUB16:
SetAddrOff ( paddr, ( (DATAPTR16) psym )->off );
SetAddrSeg ( paddr, ( (DATAPTR16) psym )->seg );
ADDRSEG16 ( *paddr );
break;
case S_GPROC32:
case S_LPROC32:
case S_BLOCK32:
SetAddrOff ( paddr, ( UOFFSET ) ( ( (PROCPTR32) psym )->off ) );
SetAddrSeg ( paddr, ( (PROCPTR32) psym )->seg );
ADDRLIN32 ( *paddr );
break;
case S_GPROCMIPS:
case S_LPROCMIPS:
SetAddrOff ( paddr, ( UOFFSET ) ( ( (PROCPTRMIPS) psym )->off ) );
SetAddrSeg ( paddr, ( (PROCPTRMIPS) psym )->seg );
ADDRLIN32 ( *paddr );
break;
case S_LABEL32:
SetAddrOff ( paddr, ( UOFFSET ) ( ( (LABELPTR32) psym )->off ) );
SetAddrSeg ( paddr, ( (LABELPTR32) psym )->seg );
ADDRLIN32 ( *paddr );
break;
case S_THUNK32:
SetAddrOff ( paddr, ( UOFFSET ) ( ( (THUNKPTR32) psym )->off ) );
SetAddrSeg ( paddr, ( (THUNKPTR32) psym )->seg );
ADDRLIN32 ( *paddr );
break;
case S_WITH32:
SetAddrOff ( paddr, ( UOFFSET ) ( ( (WITHPTR32) psym )->off ) );
SetAddrSeg ( paddr, ( (WITHPTR32) psym )->seg );
ADDRLIN32 ( *paddr );
break;
case S_BPREL32:
SetAddrOff ( paddr, ( UOFFSET ) ( ( (BPRELPTR32) psym )->off ) );
ADDRLIN32 ( *paddr );
break;
case S_PUB32:
case S_LDATA32:
case S_LTHREAD32:
case S_GDATA32:
case S_GTHREAD32:
SetAddrOff ( paddr, ( (DATAPTR32) psym )->off );
SetAddrSeg ( paddr, ( (DATAPTR32) psym )->seg );
ADDRLIN32 ( *paddr );
break;
default:
assert (FALSE);
}
ADDR_IS_LI ( *paddr ) = TRUE;
}
/*** SHGetNextMod
*
* Purpose: To sequence through the modules. Only unique module indexes
* are checked.
*
* Input:
* hMod The last module, if NULL a starting point is picked
*
* Output:
* Returns:
* The next module (hMod) in the module change or NULL if at end.
*
* Exceptions:
*
* Notes:
*
*************************************************************************/
HMOD LOADDS PASCAL SHGetNextMod ( HEXE hexe, HMOD hmod ) {
return SHHmodGetNext ( hexe, hmod );
}
PCXT PASCAL SetModule (
PADDR paddr,
PCXT pcxt,
HEXE hexe,
HMOD hmod
) {
MEMSET ( pcxt, 0, sizeof ( CXT ) );
*SHpADDRFrompCXT ( pcxt ) = *paddr;
if ( !emiAddr( *paddr ) ) {
SHpADDRFrompCXT( pcxt )->emi = hexe;
}
SHHMODFrompCXT( pcxt ) = hmod;
SHHGRPFrompCXT( pcxt ) = hmod;
return pcxt;
}
BOOL SHIsAddrInMod ( LPMDS lpmds, LPADDR lpaddr, ISECT* pisect, OFF* poff, CB* pcb )
{
int isgc;
#if defined(HOST32)
if (lpmds->pmod) {
DBI* pdbi;
Mod* pmodRet;
if (!ModQueryDBI(lpmds->pmod, &pdbi) ||
!DBIQueryModFromAddr(pdbi, GetAddrSeg ( *lpaddr ), GetAddrOff ( *lpaddr ),
&pmodRet, pisect, poff, pcb))
return FALSE;
return (pmodRet == lpmds->pmod);
}
else
#endif
{
for ( isgc = 0; isgc < (int) lpmds->csgc; isgc++ ) {
if (
lpmds->lpsgc[isgc].seg == GetAddrSeg ( *lpaddr ) &&
lpmds->lpsgc[isgc].off <= GetAddrOff ( *lpaddr ) &&
GetAddrOff ( *lpaddr ) <
lpmds->lpsgc[isgc].off + lpmds->lpsgc[isgc].cb
) {
if (pisect)
*pisect = lpmds->lpsgc[isgc].seg;
if (poff)
*poff = lpmds->lpsgc[isgc].off;
if (pcb)
*pcb = lpmds->lpsgc[isgc].cb;
return TRUE;
}
}
}
return FALSE;
}
/*** SHSetCxtMod
*
* Purpose: To set the Mod and Group of a CXT
*
* Input:
* paddr - The address to find
*
* Output:
* pcxt - The point to the CXT to make.
* Returns:
* The pointer to the CXT, NULL if failure.
*
* Exceptions:
*
* Notes:
* The CXT must be all zero or be a valid CXT. Unpredictable results
* (possible GP) if the CXT has random data in it. If the CXT is valid
* the module pointed by it will be the first module searched.
*
* There are no changes to the CXT if a module couldn't be found
*
*************************************************************************/
PCXT LOADDS PASCAL SHSetCxtMod ( LPADDR paddr, PCXT pcxt ) {
static HMOD hmodSave = 0;
static HEXE hexeSave = 0;
static HPDS hpdsSave = 0;
static WORD segSave = 0;
static UOFFSET uoffBase = 0;
static UOFFSET uoffLim = 0;
assert ( !SHIsOMFLocked );
if ( hpdsSave == hpdsCur &&
hexeSave == (HEXE)emiAddr( *paddr ) &&
GetAddrSeg ( *paddr ) == segSave &&
GetAddrOff ( *paddr ) >= uoffBase &&
GetAddrOff ( *paddr ) < uoffLim
) {
return SetModule ( paddr, pcxt, hexeSave, hmodSave );
}
else if ( GetAddrSeg( *paddr ) ) {
HMOD hmod = hmodNull;
HEXE hexe = hexeNull;
while ( hexe = SHGetNextExe ( hexe ) ) {
if ( hexe == emiAddr ( *paddr ) ) {
LPEXS lpexs = LLLock ( hexe );
LPEXG lpexg = LLLock ( lpexs->hexg );
#if defined(HOST32)
if (lpexg->ppdb) {
Mod* pmod;
CB cb;
BOOL fTmp;
assert(lpexg->pdbi);
if (DBIQueryModFromAddr(lpexg->pdbi, GetAddrSeg(*paddr), GetAddrOff(*paddr),
&pmod, &segSave, &uoffBase, &cb)) {
uoffLim = uoffBase + cb;
hpdsSave = hpdsCur;
fTmp = ModGetPvClient(pmod, &hmodSave);
assert(fTmp);
hexeSave = hexe;
return SetModule (paddr, pcxt, hexeSave, hmodSave);
}
}
else
#endif
{
LPSGD rgsgd = lpexg->lpsgd;
LLUnlock ( lpexs->hexg );
LLUnlock ( hexe );
if ( rgsgd != NULL &&
GetAddrSeg ( *paddr ) <= lpexg->csgd ) {
LPSGD lpsgd = &rgsgd [ GetAddrSeg ( *paddr ) - 1 ];
WORD isge = 0;
for ( isge = 0; isge < lpsgd->csge; isge++ ) {
LPSGE lpsge = &lpsgd->lpsge [ isge ];
if (lpsge->sgc.seg == GetAddrSeg ( *paddr ) &&
lpsge->sgc.off <= GetAddrOff ( *paddr ) &&
GetAddrOff ( *paddr ) < lpsge->sgc.off + lpsge->sgc.cb
) {
hpdsSave = hpdsCur;
hmodSave = lpsge->hmod;
hexeSave = hexe;
segSave = GetAddrSeg ( *paddr );
uoffBase = lpsge->sgc.off;
uoffLim = lpsge->sgc.off + lpsge->sgc.cb;
return SetModule (paddr, pcxt, hexeSave, hmodSave);
}
}
}
}
}
}
}
// REVIEW: TARGMAC68K moved the SetModule call down
// by a brace... just set the address portion of the context
SetModule ( paddr, pcxt, hexeNull, hmodNull );
return (NULL);
}
/*** SHSetBlksInCXT
*
* Purpose: To update the CXT packet with Proc, and Blk information
* based on pCXT->addr. It is possible to have a Blk record without
* a Proc.
*
* The Procs or Blocks will inclose the pCXT->addr. Also a
* block will never inclose a Proc.
*
* The updating of the ctxt will be effecient. If the packet is already
* updated or partiallly updated, the search reduced or removed.
*
* Input:
* pcxt - A pointer to a CXT with a valid HMOD, HGRP and addr
*
* Output:
* pcxt - HPROC and HBLK are all updated.
*
* Returns .....
* pcxt on success or NULL on failure
*
*
* Notes: This is the core address to context routine! This particular
* routine should only be used by other routines in this module
* (i.e. remain static near!). The reason for this is so symbol
* lookup can change with easy modification to this module and
* not effecting other modules.
*
*************************************************************************/
static PCXT PASCAL NEAR SHSetBlksInCXT ( PCXT pcxt ) {
SYMPTR psym;
SYMPTR psymEnd;
LPB lpstart;
LPMDS lpmds;
int fGo;
UOFFSET uoffT1;
UOFFSET uoffT2;
assert ( !SHIsOMFLocked );
// determine if we can find anything
if( !(pcxt->hMod && pcxt->hGrp) ) {
return NULL;
}
// get the module limits
lpmds = LLLock( pcxt->hGrp );
if( GetSymbols ( lpmds ) ) {
lpstart = (LPB)(lpmds->symbols);
psym = (SYMPTR) ( (LPB) lpmds->symbols + sizeof ( long ) );
psymEnd = (SYMPTR) ( ( (LPB) psym) + lpmds->cbSymbols - sizeof ( long ) );
}
else {
psym = psymEnd = NULL;
}
LLUnlock( pcxt->hGrp );
// at the end of this proc I will assume that the tags in the ctxt
// structures are real pointers, so I must convert them here. Since
// I am in the ems page, the conversion will be fast
pcxt->hProc = NULL;
pcxt->hBlk = NULL;
// at this point we know the proper symbol ems page is loaded! Also
// psym contains the best start address, and psymEnd contains the
// last location in the module
// now search the symbol tables starting at psym
fGo = TRUE;
while( psym < psymEnd && fGo) {
switch( psym->rectyp ) {
#if defined (ADDR_16) || defined (ADDR_MIXED)
case S_LPROC16:
case S_GPROC16:
// check to make sure this address starts before the address
// of interest
if (((PROCPTR16)psym)->seg != GetAddrSeg(pcxt->addr)) {
psym = (SYMPTR)(lpstart + ((PROCPTR16)psym)->pEnd);
}
else if (((PROCPTR16)psym)->off > ( CV_uoff16_t ) GetAddrOff(pcxt->addr)) {
// If the packer ever orders the chaining of fuctions
// by offset, we can set fGo to false to terminate
// the search at this point.
// fGo = FALSE;
break;
}
// check to see if the proc encloses the user offset
else if (GetAddrOff (pcxt->addr) < ((PROCPTR16)psym)->off +
((PROCPTR16)psym)->len) {
pcxt->hProc = (HPROC) psym;
pcxt->hBlk = NULL;
}
// else we are out of scope, go to the end of this proc
// remember pEnd points to the END record. When we skip
// the record after this switch, we will be skipping the
// end record.
else {
psym = (SYMPTR)(lpstart + ((PROCPTR16)psym)->pEnd);
}
break;
#endif
#if defined (ADDR_32) || defined (ADDR_MIXED) || defined (HOST32)
case S_LPROC32:
case S_GPROC32:
// check to make sure this address starts before the address
// of interest
if (((PROCPTR32)psym)->seg != GetAddrSeg(pcxt->addr)) {
psym = (SYMPTR)(lpstart + ((PROCPTR32)psym)->pEnd);
}
#if defined(ORDERSYMBOLS)
else if (((PROCPTR32)psym)->off > GetAddrOff(pcxt->addr)) {
// If the packer ever orders the chaining of fuctions
// by offset, we can set fGo to false to terminate
// the search at this point.
// fGo = FALSE;
break;
}
// check to see if the proc encloses the user offset
else if (GetAddrOff (pcxt->addr) < ((PROCPTR32)psym)->off +
((PROCPTR32)psym)->len) {
pcxt->hProc = (HPROC) psym;
pcxt->hBlk = NULL;
}
#else
// check to see if the proc encloses the user offset
else if (
(uoffT1 = GetAddrOff (pcxt->addr)) >= (uoffT2 = ((PROCPTR32)psym)->off) &&
uoffT1 < (uoffT2 + ((PROCPTR32)psym)->len)
) {
pcxt->hProc = (HPROC) psym;
pcxt->hBlk = NULL;
}
#endif
// else we are out of scope, go to the end of this proc
// remember pEnd points to the END record. When we skip
// the record after this switch, we will be skipping the
// end record.
else {
psym = (SYMPTR)(lpstart + ((PROCPTR32)psym)->pEnd);
}
break;
#endif
#if defined (ADDR_32) || defined (ADDR_MIXED) || defined (HOST32)
case S_LPROCMIPS:
case S_GPROCMIPS:
// check to make sure this address starts before the address
// of interest
if (((PROCPTRMIPS)psym)->seg != GetAddrSeg(pcxt->addr)) {
psym = (SYMPTR)(lpstart + ((PROCPTRMIPS)psym)->pEnd);
}
#if defined(ORDERSYMBOLS)
else if (((PROCPTRMIPS)psym)->off > GetAddrOff(pcxt->addr)) {
// If the packer ever orders the chaining of fuctions
// by offset, we can set fGo to false to terminate
// the search at this point.
// fGo = FALSE;
break;
}
// check to see if the proc encloses the user offset
else if (GetAddrOff (pcxt->addr) < ((PROCPTRMIPS)psym)->off +
((PROCPTRMIPS)psym)->len) {
pcxt->hProc = (HPROC) psym;
pcxt->hBlk = NULL;
}
#else
// check to see if the proc encloses the user offset
else if (
(uoffT1 = GetAddrOff (pcxt->addr)) >= (uoffT2 = ((PROCPTRMIPS)psym)->off) &&
uoffT1 < (uoffT2 + ((PROCPTRMIPS)psym)->len)
) {
#if defined(_MIPS_)
psymEnd = (SYMPTR) (lpstart + ((PROCPTRMIPS)psym)->pEnd);
if ((pcxt->hProc == NULL) && (uoffT1 > (uoffT2 + ((PROCPTRMIPS)psym)->DbgEnd))) {
SYMPTR psymProc = NEXTSYM ( SYMPTR, psym );
BOOL fFound = FALSE;
while (psymProc < psymEnd && !fFound) {
switch( psymProc->rectyp ) {
case S_LPROCMIPS:
if ((uoffT1 = GetAddrOff (pcxt->addr)) >= (uoffT2 = ((PROCPTRMIPS)psymProc)->off) &&
uoffT1 < (uoffT2 + ((PROCPTRMIPS)psymProc)->len)) {
psym = psymProc; // At least this one.
psymEnd = (SYMPTR) (lpstart + ((PROCPTRMIPS)psymProc)->pEnd);
if (uoffT1 <= uoffT2 + ((PROCPTRMIPS)psymProc)->DbgEnd) {
fFound = TRUE;
}
} else {
psymProc = (SYMPTR)(lpstart + ((PROCPTRMIPS)psym)->pEnd);
}
break;
default:;
}
psymProc = NEXTSYM ( SYMPTR, psymProc );
}
}
#endif
pcxt->hProc = (HPROC) psym;
pcxt->hBlk = NULL;
}
#endif
// else we are out of scope, go to the end of this proc
// remember pEnd points to the END record. When we skip
// the record after this switch, we will be skipping the
// end record.
else {
psym = (SYMPTR)(lpstart + ((PROCPTRMIPS)psym)->pEnd);
}
break;
#endif
#if defined (ADDR_16) || defined (ADDR_MIXED)
case S_BLOCK16:
// check to make sure this address starts before the address
// of interest
if (((BLOCKPTR16)psym)->seg != GetAddrSeg(pcxt->addr)) {
psym = (SYMPTR)(lpstart + ((BLOCKPTR16)psym)->pEnd);
}
else if (((BLOCKPTR16)psym)->off > ( CV_uoff16_t )GetAddrOff (pcxt->addr)) {
fGo = FALSE;
}
// check to see if the proc encloses the user offset
else if( GetAddrOff (pcxt->addr) < ((BLOCKPTR16)psym)->off +
((BLOCKPTR16)psym)->len) {
pcxt->hBlk = (HBLK)psym;
}
// else we are out of scope, go to the end of this block
else {
psym = (SYMPTR)(lpstart + ((BLOCKPTR16)psym)->pEnd);
}
break;
#endif
#if defined (ADDR_32) || defined (ADDR_MIXED) || defined (HOST32)
case S_BLOCK32:
// check to make sure this address starts before the address
// of interest
if (((BLOCKPTR32)psym)->seg != GetAddrSeg(pcxt->addr)) {
psym = (SYMPTR)(lpstart + ((BLOCKPTR32)psym)->pEnd);
}
else if (((BLOCKPTR32)psym)->off > GetAddrOff (pcxt->addr)) {
fGo = FALSE;
}
// check to see if the proc encloses the user offset
else if( GetAddrOff (pcxt->addr) < ((BLOCKPTR32)psym)->off +
((BLOCKPTR32)psym)->len) {
pcxt->hBlk = (HBLK)psym;
}
// else we are out of scope, go to the end of this block
else {
psym = (SYMPTR)(lpstart + ((BLOCKPTR32)psym)->pEnd);
}
break;
#endif
#if defined (ADDR_16) || defined (ADDR_MIXED)
case S_WITH16:
// check to make sure this address starts before the address
// of interest
if (((WITHPTR16)psym)->seg == GetAddrSeg(pcxt->addr)) {
if( ((WITHPTR16)psym)->off > ( CV_uoff16_t ) GetAddrOff (pcxt->addr)) {
fGo = FALSE;
}
// I am only looking for blocks and proc. Withs and Entry should
// be looked at only to keep our nesting correct.
// if its range is not of interest, skip it, otherwise ignore it.
else if (GetAddrOff (pcxt->addr) >= ((WITHPTR16)psym)->off +
((WITHPTR16) psym)->len ) {
psym = (SYMPTR)(lpstart + ((WITHPTR16)psym)->pEnd);
}
}
break;
#endif
#if defined (ADDR_32) || defined (ADDR_MIXED) || defined (HOST32)
case S_WITH32:
// check to make sure this address starts before the address
// of interest
if (((WITHPTR32)psym)->seg == GetAddrSeg(pcxt->addr)) {
if( ((WITHPTR32)psym)->off > GetAddrOff (pcxt->addr)) {
fGo = FALSE;
}
// I am only looking for blocks and proc. Withs and Entry should
// be looked at only to keep our nesting correct.
else if (GetAddrOff (pcxt->addr) >= ((WITHPTR32)psym)->off +
((WITHPTR32) psym)->len ) {
psym = (SYMPTR)(lpstart + ((WITHPTR32)psym)->pEnd);
}
}
break;
#endif
}
// get the next psym address
psym = NEXTSYM ( SYMPTR, psym );
}
// now we have the proc and block pointers, however we need the
// addresses to be added. Remember we still have the proper ems page
// still loaded!
if( pcxt->hProc ) {
pcxt->hProc = (HPROC) pcxt->hProc;
}
if( pcxt->hBlk ) {
pcxt->hBlk = (HBLK) pcxt->hBlk;
}
return pcxt;
}
/*** SHSetCxt
*
* Purpose: To set all field in a CXT to the represent the given address
*
* Input:
* pAddr -The address to set the CXT to.
*
* Output:
* pcxt -A pointer to the CXT to fill.
* Returns:
*
* Exceptions:
*
* Notes:
*
* The CXT must be all zero or be a valid CXT. Unpredictable results
* (possible GP) if the CXT has random data in it. If the CXT is valid
* the module pointed by it will be the first module searched.
*
* There are no changes to the CXT if a module couldn't be found
*
*
*************************************************************************/
PCXT LOADDS PASCAL SHSetCxt ( LPADDR paddr, PCXT pcxt ) {
assert(!SHIsOMFLocked);
// get the module part
if( SHSetCxtMod(paddr, pcxt) ) {
SHSetBlksInCXT( pcxt );
return( pcxt );
}
return NULL;
}
/*** SHGetCxtFromHmod
*
* Purpose: To make a CXT from only an hmod
*
* Input:
* hmod - The module to make
*
* Output:
* pCXT - A pointer to a CXT to initialize to this hmod
* Returns:
* - A pointer to the CXT or NULL on error.
*
* Exceptions:
*
* Notes:
*
*************************************************************************/
PCXT LOADDS PASCAL SHGetCxtFromHmod ( HMOD hmod, PCXT pcxt ) {
LPMDS lpmds;
PCXT pcxtRet = NULL;
assert(!SHIsOMFLocked);
if( hmod ) {
HEXE hexe = SHHexeFromHmod( hmod );
// clear the CXT
MEMSET (pcxt, 0, sizeof(CXT));
// set the module info
pcxt->hGrp = pcxt->hMod = hmod;
// put in the address
lpmds = LLLock( hmod );
SetAddrFromMod(lpmds, &pcxt->addr);
emiAddr ( pcxt->addr ) = hexe;
ADDR_IS_LI (pcxt->addr) = TRUE;
// Set the fFlat and fOff32 bits based on the exe
{
HEXG hexg = ( (LPEXS) LLLock ( hexe ) )->hexg;
LLUnlock ( hexe );
if ( ( (LPEXG) LLLock ( hexg ) )->fIsPE ) {
// REVIEW - billjoy - should we check machine type or something?
ADDRLIN32 ( pcxt->addr );
}
else {
// REVIEW - billjoy - should we check machine type or something?
//ADDR????
}
LLUnlock ( hexg );
}
LLUnlock( hmod );
pcxtRet = pcxt;
}
return pcxtRet;
}
/*** SHGetNearestHsym
*
* Purpose: To find the closest label/proc to the specified address is
* found and put in pch. Both the symbol table and the
* publics tables are searched.
*
* Input: pctxt - a pointer to the context, address
* and mdi must be filled in.
* fIncludeData - If true, symbol type local will be included
* in the closest symbol search.
*
* Output:
* pch - The name is copied here.
* Returns .....
* The difference between the address and the symbol
*
* Exceptions:
*
* Notes: If CV_MAXOFFSET is returned, there is no closest symbol
* Also all symbols in the module are searched so only the
* ctxt.addr and ctxt.mdi have meaning.
*
*************************************************************************/
UOFF32 LOADDS PASCAL
SHGetNearestHsym ( LPADDR paddr, HMOD hmod, int mDataCode, PHSYM phSym ) {
LBS lbs;
CV_uoff32_t doff = (CV_uoff32_t)CV_MAXOFFSET;
CV_uoff32_t doffNew = (CV_uoff32_t)CV_MAXOFFSET;
SYMPTR psym;
// get the module to search
*phSym = NULL;
if( hmod ) {
// at some point we may wish to specify only a scope to search for
// a label. So we may wish to initialize the lbs differently
// get the Labels
lbs.tagMod = hmod;
lbs.addr = *paddr;
SHpSymlplLabLoc ( &lbs );
// check for closest data local, if requested
if( (mDataCode & EEDATA) == EEDATA && lbs.tagLoc ) {
psym = (SYMPTR) (LPB) lbs.tagLoc;
switch (psym->rectyp) {
#if defined (ADDR_16) || defined (ADDR_MIXED)
case S_BPREL16:
doff = GetAddrOff (lbs.addr ) - ((BPRELPTR16)psym)->off;
break;
#endif
#if defined (ADDR_32) || defined (ADDR_MIXED) || defined (HOST32)
case S_BPREL32:
doff = GetAddrOff (lbs.addr ) - ((BPRELPTR32)psym)->off;
break;
case S_REGREL32:
doff = GetAddrOff (lbs.addr ) - ((LPREGREL32)psym)->off;
break;
#endif
}
*phSym = (HSYM) lbs.tagLoc;
}
// check for closest label
if( ((mDataCode & EECODE) == EECODE) && lbs.tagLab ) {
psym = (SYMPTR) (LPB) lbs.tagLab;
switch (psym->rectyp) {
#if defined (ADDR_16) || defined (ADDR_MIXED)
case S_LABEL16:
if( (GetAddrOff(lbs.addr) -
( UOFFSET ) ((LABELPTR16)psym)->off) <= ( UOFFSET ) doff
) {
doff = GetAddrOff( lbs.addr ) - (UOFFSET)((LABELPTR16)psym)->off;
*phSym = (HSYM) lbs.tagLab;
}
break;
#endif
#if defined (ADDR_32) || defined (ADDR_MIXED) || defined (HOST32)
case S_LABEL32:
if ( ( UOFFSET ) (GetAddrOff(lbs.addr) -
( UOFFSET ) ((LABELPTR32)psym)->off) <= doff
) {
doff = GetAddrOff( lbs.addr ) - (UOFFSET)((LABELPTR32)psym)->off;
*phSym = (HSYM) lbs.tagLab;
}
break;
#endif
}
}
// if the proc name is closer
if( ((mDataCode & EECODE) == EECODE) && lbs.tagProc ) {
psym = (SYMPTR) (LPB) lbs.tagProc;
switch (psym->rectyp) {
#if defined (ADDR_16) || defined (ADDR_MIXED)
case S_LPROC16:
case S_GPROC16:
if ( (GetAddrOff(lbs.addr) -
( UOFFSET ) ((PROCPTR16)psym)->off) <= ( UOFFSET ) doff
) {
doff = GetAddrOff (lbs.addr) - ((PROCPTR16)psym)->off;
*phSym = (HSYM) lbs.tagProc;
}
break;
#endif
#if defined (ADDR_32) || defined (ADDR_MIXED) || defined (HOST32)
case S_LPROC32:
case S_GPROC32:
if ((GetAddrOff(lbs.addr) - (UOFFSET)((PROCPTR32)psym)->off) <= doff ) {
doff = GetAddrOff( lbs.addr ) - ((PROCPTR32)psym)->off;
*phSym = (HSYM) lbs.tagProc;
}
break;
case S_LPROCMIPS:
case S_GPROCMIPS:
if ((GetAddrOff(lbs.addr) - (UOFFSET)((PROCPTRMIPS)psym)->off) <= doff ) {
doff = GetAddrOff( lbs.addr ) - ((PROCPTRMIPS)psym)->off;
*phSym = (HSYM) lbs.tagProc;
}
break;
#endif
}
}
}
return doff;
}
/*** SHIsInProlog
*
* Purpose: To determine if the addr is in prolog or epilog code of the proc
*
* Input:
* pCXT - The context describing the state. The address here is Linker index
* based
*
* Output:
* Returns:
* TRUE if it is in prolog or epilog code
*
* Exceptions:
*
* Notes:
*
*************************************************************************/
SHFLAG LOADDS PASCAL SHIsInProlog ( PCXT pcxt ) {
SYMPTR pProc;
CXT cxt;
assert(!SHIsOMFLocked);
if (pcxt->hProc == NULL) {
return FALSE;
}
cxt = *pcxt;
#ifdef NEVER
if (!ADDR_IS_LI (*SHpADDRFrompCXT (&cxt))) {
// convert to logical address for comparison
SYUnFixupAddr (SHpADDRFrompCXT (&cxt));
}
#endif
// check to see if not within the proc
pProc = (SYMPTR) cxt.hProc;
switch (pProc->rectyp) {
#if defined (ADDR_16) || defined (ADDR_MIXED)
case S_LPROC16:
case S_GPROC16:
return ((CV_uoff16_t)GetAddrOff (*SHpADDRFrompCXT (&cxt)) <
(((PROCPTR16)pProc)->off + ((PROCPTR16)pProc)->DbgStart) ||
((((PROCPTR16)pProc)->off + ((PROCPTR16)pProc)->DbgEnd) <
(CV_uoff16_t) GetAddrOff (*SHpADDRFrompCXT (&cxt))) &&
((((PROCPTR16)pProc)->off + ((PROCPTR16)pProc)->len) >
(CV_uoff16_t)GetAddrOff (*SHpADDRFrompCXT (&cxt))));
#endif
#if defined (ADDR_32) || defined (ADDR_MIXED) || defined (HOST32)
case S_LPROC32:
case S_GPROC32:
return (GetAddrOff (*SHpADDRFrompCXT (&cxt)) <
(((PROCPTR32)pProc)->off + ((PROCPTR32)pProc)->DbgStart) ||
((((PROCPTR32)pProc)->off + ((PROCPTR32)pProc)->DbgEnd) <
GetAddrOff (*SHpADDRFrompCXT (&cxt))) &&
((((PROCPTR32)pProc)->off + ((PROCPTR32)pProc)->len) >
GetAddrOff (*SHpADDRFrompCXT (&cxt))));
case S_LPROCMIPS:
case S_GPROCMIPS:
return (GetAddrOff (*SHpADDRFrompCXT (&cxt)) <
(((PROCPTRMIPS)pProc)->off + ((PROCPTRMIPS)pProc)->DbgStart) ||
((((PROCPTRMIPS)pProc)->off + ((PROCPTRMIPS)pProc)->DbgEnd) <
GetAddrOff (*SHpADDRFrompCXT (&cxt))) &&
((((PROCPTRMIPS)pProc)->off + ((PROCPTRMIPS)pProc)->len) >
GetAddrOff (*SHpADDRFrompCXT (&cxt))));
#endif
default:
assert (FALSE);
return(FALSE);
}
}
/*** SHFindNameInContext
*
* Purpose: To look for the name at the scoping level specified by ctxt.
* Only the specified level is searched, children may be searched
* if fChild is set.
*
* This routine will assume the desired scope in the following
* way. If pcxt->hBlk != NULL, use hBlk as the starting scope.
* If hBlk == NULL and pcxt->hProc != NULL use the proc scope.
* If hBlk and hProc are both NULL and pcxt->hMod !=
* NULL, use the module as the scope.
*
* Input:
* hSym - The starting symbol, if NULL, then the first symbol
* in the context is used. (NULL is find first).
* pcxt - The context to do the search.
* lpsstr - pointer to the 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!
*
* The level at which hSym is nested (cNest) is not passed in
* to this function, so it must be derived. Since this
* could represent a significant speed hit, the level
* of the last symbol processed is cached. This should
* take care of most cases and avoid the otherwise
* necessary looping through all the previous symbols
* in the module on each call.
*
*
*************************************************************************/
HSYM LOADDS PASCAL SHFindNameInContext (
HSYM hSym,
PCXT pcxt,
LPSSTR lpsstr,
SHFLAG fCase,
PFNCMP pfnCmp,
SHFLAG fChild,
PCXT pcxtOut
) {
LPMDS lpmds;
HMOD hmod;
HEXE hexe;
SYMPTR lpsym;
SYMPTR lpEnd;
LPB lpstart;
ULONG cbSym;
int fSkip = FALSE;
assert ( !SHIsOMFLocked );
if ( ! ADDR_IS_LI ( pcxt->addr ) ) {
SYUnFixupAddr ( &pcxt->addr );
}
MEMSET ( pcxtOut, 0, sizeof(CXT) );
if( !pcxt->hMod ) { // we must always have a module
return (HSYM) FindNameInStatics (
hSym, pcxt, lpsstr, fCase, pfnCmp, pcxtOut
);
}
hmod = pcxt->hGrp ? pcxt->hGrp : pcxt->hMod; // Initialize the module
lpmds = LLLock( hmod );
hexe = SHHexeFromHmod ( hmod );
pcxtOut->hMod = pcxt->hMod;
pcxtOut->hGrp = pcxt->hGrp;
if ( SYProcessor ( ) >= 3 ) {
ADDRLIN32 ( pcxtOut->addr );
}
else {
ADDRSEG16 ( pcxtOut->addr );
}
SetAddrFromMod(lpmds, &pcxtOut->addr);
emiAddr ( pcxtOut->addr ) = hexe;
ADDR_IS_LI ( pcxtOut->addr ) = TRUE;
GetSymbols ( lpmds );
cbSym = lpmds->cbSymbols;
LLUnlock( hmod );
if (cbSym == 0 || lpmds->symbols == NULL) {
return NULL;
}
// Search the symbol table.
lpstart = (LPB)(lpmds->symbols);
lpsym = (SYMPTR) ( (LPB) ( lpmds->symbols ) + sizeof( long ) );
lpEnd = (SYMPTR) ( ( (LPB) lpsym + cbSym ) - sizeof ( long ) ) ;
// now find the start address. Always skip the current symbol because
// we don't want to pick up the same name over and over again
// if the user gives the start address
if( hSym != NULL ) {
pcxtOut->hProc = (HPROC) pcxt->hProc;
pcxtOut->hBlk = (HBLK) pcxt->hBlk;
SetAddrOff ( &pcxtOut->addr , GetAddrOff ( pcxt->addr ) );
SetAddrSeg ( &pcxtOut->addr, GetAddrSeg ( pcxt->addr ) );
lpsym = (SYMPTR) hSym;
switch ( lpsym->rectyp ) {
case S_WITH16:
case S_BLOCK16:
case S_LPROC16:
case S_GPROC16:
case S_WITH32:
case S_BLOCK32:
case S_LPROC32:
case S_GPROC32:
case S_LPROCMIPS:
case S_GPROCMIPS:
lpsym = NEXTSYM ( SYMPTR, (lpstart + ((PROCPTR)lpsym)->pEnd));
break;
default:
lpsym = NEXTSYM ( SYMPTR, lpsym );
}
}
else if ( pcxt->hBlk != NULL ) { // find the start address
SYMPTR lpbsp = (SYMPTR) pcxt->hBlk;
pcxtOut->hProc = pcxt->hProc;
pcxtOut->hBlk = pcxt->hBlk;
switch (lpbsp->rectyp) {
case S_BLOCK16:
SetAddrOff (&pcxtOut->addr, (UOFFSET)((BLOCKPTR16)lpbsp)->off );
SetAddrSeg (&pcxtOut->addr, (SEGMENT)((BLOCKPTR16)lpbsp)->seg );
ADDRSEG16 ( pcxtOut->addr );
break;
case S_BLOCK32:
SetAddrOff (&pcxtOut->addr, (UOFFSET)((BLOCKPTR32)lpbsp)->off );
SetAddrSeg (&pcxtOut->addr, (SEGMENT)((BLOCKPTR32)lpbsp)->seg );
ADDRLIN32 ( pcxtOut->addr );
break;
}
lpsym = NEXTSYM(SYMPTR, lpbsp );
lpEnd = (SYMPTR)(lpstart + ((BLOCKPTR16)lpbsp)->pEnd);
}
else if ( pcxt->hProc != NULL ) {
SYMPTR lppsp = (SYMPTR) pcxt->hProc;
switch (lppsp->rectyp) {
case S_LPROC16:
case S_GPROC16:
SetAddrOff (&pcxtOut->addr, (UOFFSET)((PROCPTR16)lppsp)->off );
SetAddrSeg (&pcxtOut->addr, (SEGMENT)((PROCPTR16)lppsp)->seg );
ADDRSEG16 ( pcxtOut->addr );
break;
case S_LPROC32:
case S_GPROC32:
SetAddrOff (&pcxtOut->addr, (UOFFSET)((PROCPTR32)lppsp)->off );
SetAddrSeg (&pcxtOut->addr, (SEGMENT)((PROCPTR32)lppsp)->seg );
ADDRLIN32 ( pcxtOut->addr );
break;
case S_LPROCMIPS:
case S_GPROCMIPS:
SetAddrOff (&pcxtOut->addr, (UOFFSET)((PROCPTRMIPS)lppsp)->off );
SetAddrSeg (&pcxtOut->addr, (SEGMENT)((PROCPTRMIPS)lppsp)->seg );
ADDRLIN32 ( pcxtOut->addr );
break;
}
pcxtOut->hProc = pcxt->hProc;
lpsym = NEXTSYM(SYMPTR, lppsp);
lpEnd = (SYMPTR)(lpstart + ((PROCPTR16)lppsp)->pEnd);
}
while ( lpsym < lpEnd && ( lpsym->rectyp != S_END || fChild ) ) {
assert (lpsym->reclen != 0);
switch (lpsym->rectyp) {
case S_LABEL16:
SetAddrOff ( &pcxtOut->addr , (UOFFSET)((LABELPTR16)lpsym)->off );
SetAddrSeg ( &pcxtOut->addr , (SEGMENT)((LABELPTR16)lpsym)->seg );
ADDRSEG16 ( pcxtOut->addr );
goto symname;
case S_LPROC16:
case S_GPROC16:
pcxtOut->hBlk = NULL;
pcxtOut->hProc = (HPROC) lpsym;
SetAddrOff (&pcxtOut->addr, (UOFFSET)((PROCPTR16)lpsym)->off);
SetAddrSeg (&pcxtOut->addr, (SEGMENT)((PROCPTR16)lpsym)->seg);
ADDRSEG16 ( pcxtOut->addr );
goto entry16;
case S_BLOCK16:
pcxtOut->hBlk = (HBLK) lpsym;
SetAddrOff (&pcxtOut->addr, (UOFFSET)((BLOCKPTR16)lpsym)->off);
SetAddrSeg (&pcxtOut->addr, (SEGMENT)((BLOCKPTR16)lpsym)->seg);
ADDRSEG16 ( pcxtOut->addr );
goto entry16;
case S_THUNK16:
case S_WITH16:
ADDRSEG16 ( pcxtOut->addr );
entry16:
fSkip = TRUE;
// fall thru and process the symbol
case S_BPREL16:
case S_GDATA16:
case S_LDATA16:
ADDRSEG16 ( pcxtOut->addr );
goto symname;
case S_LABEL32:
SetAddrOff ( &pcxtOut->addr , (UOFFSET)((LABELPTR32)lpsym)->off );
SetAddrSeg ( &pcxtOut->addr , (SEGMENT)((LABELPTR32)lpsym)->seg );
ADDRLIN32 ( pcxtOut->addr );
goto symname;
case S_LPROC32:
case S_GPROC32:
pcxtOut->hBlk = NULL;
pcxtOut->hProc = (HPROC) lpsym;
SetAddrOff (&pcxtOut->addr, (UOFFSET)((PROCPTR32)lpsym)->off);
SetAddrSeg (&pcxtOut->addr, (SEGMENT)((PROCPTR32)lpsym)->seg);
ADDRLIN32 ( pcxtOut->addr );
goto entry32;
case S_LPROCMIPS:
case S_GPROCMIPS:
pcxtOut->hBlk = NULL;
pcxtOut->hProc = (HPROC) lpsym;
SetAddrOff (&pcxtOut->addr, (UOFFSET)((PROCPTRMIPS)lpsym)->off);
SetAddrSeg (&pcxtOut->addr, (SEGMENT)((PROCPTRMIPS)lpsym)->seg);
ADDRLIN32 ( pcxtOut->addr );
goto entry32;
case S_BLOCK32:
pcxtOut->hBlk = (HBLK) lpsym;
SetAddrOff (&pcxtOut->addr, (UOFFSET)((BLOCKPTR32)lpsym)->off);
SetAddrSeg (&pcxtOut->addr, (SEGMENT)((BLOCKPTR32)lpsym)->seg);
ADDRLIN32 ( pcxtOut->addr );
goto entry32;
// fall thru to the entry case
case S_THUNK32:
case S_WITH32:
ADDRLIN32 ( pcxtOut->addr );
entry32:
fSkip = TRUE;
// fall thru and process the symbol
case S_BPREL32:
case S_REGREL32:
case S_GDATA32:
case S_LDATA32:
case S_GTHREAD32:
case S_LTHREAD32:
ADDRLIN32 ( pcxtOut->addr );
goto symname;
case S_REGISTER:
case S_CONSTANT:
case S_UDT:
case S_COBOLUDT:
case S_COMPILE: // [01]
symname: // [01]
if ( // [01]
( !( lpsstr->searchmask & SSTR_symboltype ) || // [01]
( lpsym->rectyp == lpsstr->symtype ) // [01]
) && // [01]
!(*pfnCmp) ( // [01]
lpsstr, // [01]
lpsym, // [01]
SHlszGetSymName ( lpsym ), // [01]
fCase // [01]
) ) { // [01]
// save the sym pointer
lpsym = (SYMPTR) lpsym;
CheckHandles (pcxtOut);
return lpsym;
}
// up the scoping level
if ( fSkip && !fChild ) {
#if defined(_MIPS_) // Centaur generates occassional bad CV
assert(((PROCPTR16)lpsym)->pEnd != 0);
#endif
lpsym = (SYMPTR)(lpstart + ((PROCPTR16)lpsym)->pEnd);
fSkip = FALSE;
}
break;
}
lpsym = NEXTSYM(SYMPTR, lpsym);
}
return NULL;
}
LOCAL VOID NEAR PASCAL CheckHandles ( PCXT pcxt )
{
SYMPTR psym;
// check and restore all proc and blk handles
if( pcxt->hProc != NULL) {
psym = (SYMPTR) pcxt->hProc;
switch (psym->rectyp) {
#if defined (ADDR_16) || defined (ADDR_MIXED)
case S_LPROC16:
case S_GPROC16:
if ((GetAddrOff (pcxt->addr) < ((PROCPTR16)psym)->off) ||
GetAddrOff (pcxt->addr) >= (((PROCPTR16)psym)->len +
((PROCPTR16)psym)->off)) {
pcxt->hProc = NULL;
}
break;
#endif
#if defined (ADDR_32) || defined (ADDR_MIXED) || defined(HOST32)
case S_LPROC32:
case S_GPROC32:
if ((GetAddrOff (pcxt->addr) < ((PROCPTR32)psym)->off ) ||
GetAddrOff (pcxt->addr) >= (((PROCPTR32)psym)->len +
((PROCPTR32)psym)->off)) {
pcxt->hProc = NULL;
}
break;
case S_LPROCMIPS:
case S_GPROCMIPS:
if ((GetAddrOff (pcxt->addr) < ((PROCPTRMIPS)psym)->off) ||
GetAddrOff (pcxt->addr) >= (((PROCPTRMIPS)psym)->len +
((PROCPTRMIPS)psym)->off)) {
pcxt->hProc = NULL;
}
break;
#endif
}
}
if( pcxt->hBlk != NULL) {
psym = (SYMPTR) pcxt->hBlk;
switch (psym->rectyp) {
#if defined (ADDR_16) || defined (ADDR_MIXED)
case S_BLOCK16:
if ((GetAddrOff (pcxt->addr) < ((BLOCKPTR16)psym)->off) ||
GetAddrOff (pcxt->addr) >= (((BLOCKPTR16)psym)->len +
((BLOCKPTR16)psym)->off)) {
pcxt->hBlk = NULL;
}
break;
#endif
#if defined (ADDR_32) || defined (ADDR_MIXED) || defined(HOST32)
case S_BLOCK32:
if ((GetAddrOff (pcxt->addr) < ((BLOCKPTR32)psym)->off) ||
GetAddrOff (pcxt->addr) >= (((BLOCKPTR32)psym)->len +
((BLOCKPTR32)psym)->off)) {
pcxt->hBlk = NULL;
}
break;
#endif
}
}
// now fill in the proper group
// because there is not (currently) a unique emi within a
// module, use the emi set in addr
pcxt->hGrp = pcxt->hMod;
}
/*** SHpSymctxtParent
*
* Purpose: To return a pointer to the parent block of the current blk or proc.
* The CXT is updated to the parent context. This may be a new block
* Proc or module.
*
* Input:
* pcxt - A pointer to the child CXT.
*
* Output:
* pcxtOut- an updated CXT to the parent.
*
* Returns .....
* - a Symbol point to the first record within the parent, this
* may be pcxt->hBlk, hProc, or
* pcxt->hMod->symbols + sizeof (long) or NULL if no parent.
*
* Exceptions:
*
* Notes:
*
*************************************************************************/
HSYM LOADDS PASCAL SHGoToParent ( PCXT pcxt, PCXT pcxtOut ) {
SYMPTR lpsym = NULL;
LPMDS lpmds;
SYMPTR lpsymT;
HSYM hsym;
LPB lpstart;
assert(!SHIsOMFLocked);
if( !pcxt->hMod ) {
return NULL;
}
lpmds = LLLock( pcxt->hMod );
lpstart = (LPB) (lpmds->symbols);
lpsymT = (SYMPTR) ( (LPB) lpmds->symbols + sizeof(long) );
LLUnlock ( pcxt->hMod );
*pcxtOut = *pcxt;
// if the block is present, go to his parent
if( pcxt->hBlk != NULL ) {
// get lpsym upto the parent
lpsym = (SYMPTR) pcxt->hBlk;
lpsym = (SYMPTR)(lpstart + ((BLOCKPTR16)lpsym)->pParent);
pcxtOut->hBlk = NULL;
}
// otherwise check the proc's parent, and go to his parent
else if ( pcxt->hProc != NULL ) {
// get lpsym upto the parent
lpsym = (SYMPTR) pcxt->hProc;
lpsym = (SYMPTR)(lpstart + (((PROCPTR16)lpsym)->pParent));
pcxtOut->hProc = NULL;
}
// otherwise there is no parent
else {
return NULL;
}
// if there is a parent, set the cxt packet.
if (lpsym != NULL) {
switch( lpsym->rectyp ) {
#if defined (ADDR_16) || defined (ADDR_MIXED)
case S_LPROC16:
case S_GPROC16:
//case S_ENTRY:
#endif
#if defined (ADDR_32) || defined (ADDR_MIXED) || defined(HOST32)
case S_LPROC32:
case S_GPROC32:
//case S_ENTRY:
case S_LPROCMIPS:
case S_GPROCMIPS:
#endif
pcxtOut->hProc = (HPROC) lpsym;
break;
#if defined (ADDR_16) || defined (ADDR_MIXED)
case S_BLOCK16:
case S_WITH16:
#endif
#if defined (ADDR_32) || defined (ADDR_MIXED) || defined(HOST32)
case S_BLOCK32:
case S_WITH32:
#endif
pcxtOut->hBlk = (HBLK) lpsym;
break;
default:
return NULL;
}
return lpsym;
}
// return the module as the parent
else {
hsym = (HSYM) lpsymT;
return hsym;
}
}
/*** SHFindSLink32
*
* Purpose: To return a pointer to the SLINK32 for this proc
*
* Input:
* pcxt - A pointer to the child CXT.
*
*
* Returns .....
* - a Symbol point to the SLINK32 record
*
* Exceptions:
*
* Notes:
*
*************************************************************************/
HSYM LOADDS PASCAL SHFindSLink32 ( PCXT pcxt ) {
SYMPTR lpsym = NULL;
LPMDS lpmds;
SYMPTR lpsymT;
assert(!SHIsOMFLocked);
if( !pcxt->hMod ) {
return NULL;
}
lpmds = LLLock( pcxt->hMod );
lpsymT = (SYMPTR) ( (LPB) lpmds->symbols + sizeof(long) );
LLUnlock ( pcxt->hMod );
if ( pcxt->hProc != NULL ) {
lpsym = (SYMPTR) pcxt->hProc;
}
// otherwise there is no SLINK32
else {
return NULL;
}
lpsym = NEXTSYM(SYMPTR, lpsym);
for (; lpsym != NULL && lpsym->rectyp != S_SLINK32; ) {
switch( lpsym->rectyp ) {
#if defined (ADDR_16) || defined (ADDR_MIXED)
case S_LPROC16:
case S_GPROC16:
//case S_ENTRY:
#endif
#if defined (ADDR_32) || defined (ADDR_MIXED) || defined(HOST32)
case S_LPROC32:
case S_GPROC32:
//case S_ENTRY:
case S_LPROCMIPS:
case S_GPROCMIPS:
#endif
#if defined (ADDR_16) || defined (ADDR_MIXED)
case S_BLOCK16:
case S_WITH16:
#endif
#if defined (ADDR_32) || defined (ADDR_MIXED) || defined(HOST32)
case S_BLOCK32:
case S_WITH32:
#endif
case S_END:
lpsym = NULL;
break;
case S_SLINK32:
break;
default:
lpsym = NEXTSYM(SYMPTR, lpsym);
break;
}
}
return lpsym;
}
/*** SHHsymFromPcxt
*
* Purpose: To get the inner most hSym given a context
*
* Input:
* pcxt - A pointer to a valid CXT.
*
* Output:
* Returns:
* HSYM of the first symbol, or NULL on Error
*
* Exceptions:
*
* Notes: Used for procedure parameter walking
*
*************************************************************************/
HSYM LOADDS PASCAL SHHsymFromPcxt ( PCXT pcxt ) {
HSYM hsym = NULL;
LPMDS lpmds;
assert(!SHIsOMFLocked);
if( pcxt->hMod ) {
if( pcxt->hBlk ) {
hsym = pcxt->hBlk;
}
else if( pcxt->hProc ) {
hsym = pcxt->hProc;
}
else {
SYMPTR lpsymT;
// get the first symbol
lpmds = LLLock( pcxt->hMod );
lpsymT = (SYMPTR) ( (LPB) GetSymbols ( lpmds ) + sizeof(long) );
hsym = lpsymT;
LLUnlock( pcxt->hMod );
}
}
return hsym;
}
/*** SHNextHsym
*
* Purpose: To get the next symbol in the table
*
* Input:
* hMod -A handle to the module containing the current hSym
* hSym -The current hSym
*
* Output:
* Returns:
* The next hSym, or NULL if no more.
*
* Exceptions:
*
* Notes:
*
*************************************************************************/
HSYM LOADDS PASCAL SHNextHsym ( HMOD hmod, HSYM hSym ) {
SYMPTR lpsym;
SYMPTR lpsymStart;
ULONG cbSym;
LPMDS lpmds;
HSYM hsymRet = (HSYM)NULL;
SYMPTR lpsymT;
assert(!SHIsOMFLocked);
if (hmod) {
// only if the symbol is valid
// get module info
lpmds = LLLock( hmod );
lpsymT = (SYMPTR) ( (LPB) GetSymbols ( lpmds ) + sizeof( long ) );
lpsymStart = (SYMPTR) lpsymT;
cbSym = lpmds->cbSymbols;
LLUnlock( hmod );
// give him the first symbol record
if (hSym == NULL) {
// if the current handle to symbol is null, return the first
// symbol. This is actually an error condition since we don't
// have an hSym to get the next from
hsymRet = (HSYM)lpsymStart;
}
else {
// get info about the sym, and then skip it
lpsym = (SYMPTR) hSym;
lpsym = NEXTSYM(SYMPTR, lpsym);
// check to see if still in symbol range
lpsymStart = (SYMPTR) lpsymStart;
if ( lpsymStart <= lpsym &&
lpsym < (SYMPTR) (((LPB) lpsymStart) + cbSym) ) {
hsymRet = (HSYM) lpsym;
}
}
}
return hsymRet;
}
/*** SHIsAddrInCxt
*
* Purpose: To verify weather the address is within the context
*
* Input:
* pCXT - The context to check against
* pADDR - The address in question
*
* Output:
* Returns:
* TRUE if within context, FALSE otherwise.
*
* Exceptions:
*
* Notes:
*
*
*************************************************************************/
SHFLAG LOADDS PASCAL SHIsAddrInCxt ( PCXT pcxt, LPADDR paddr ) {
HMOD hmod;
LPMDS lpmds;
SYMPTR psym;
SHFLAG shf = (SHFLAG)FALSE;
assert ( !SHIsOMFLocked );
if ( (pcxt != NULL) && (pcxt->hMod != 0) ) {
// get the module
if ( pcxt->hGrp != 0 ) {
hmod = pcxt->hGrp;
}
else {
hmod = pcxt->hMod;
pcxt->hGrp = hmod;
}
lpmds = LLLock ( hmod );
// The return value is true if these three conditions are all true:
// 1. The address is in the same executable as the context
// 2. The address is in the same module as the context
// 3. Any of the following are true:
// a. There is no block or proc so the address offset
// can be anywhere
// b. The address is in the offset range of the block of
// the context
// c. The addr is in the offset range of the procedure of
// the context
if (
emiAddr (*paddr) != 0 &&
emiAddr (*paddr) != hpidCurr &&
SHIsEmiLoaded ( SHHexeFromHmod ( hmod ) ) &&
emiAddr (*paddr ) == SHHexeFromHmod ( hmod )
) {
// condition 1 is true
if ( SHIsAddrInMod (lpmds, paddr, NULL, NULL, NULL )) {
// condition 2 is true
if ( pcxt->hProc == NULL && pcxt->hBlk == NULL ) {
// condition 3a is true
shf = TRUE;
}
if ( !shf && ( psym = (SYMPTR) pcxt->hBlk ) != NULL ) {
// we have not passed test 3a and the block
// symbol handle is not null
switch (psym->rectyp) {
case S_BLOCK16:
if ((((UOFFSET)((BLOCKPTR16)psym)->off) <= GetAddrOff (*paddr)) &&
(GetAddrOff (*paddr) <
(UOFF32) (((BLOCKPTR16)psym)->off + ((BLOCKPTR16)psym)->len))) {
// case 3b is true for a 16 bit block symbol
shf = TRUE;
}
break;
case S_BLOCK32:
if (
( ( ( BLOCKPTR32 ) psym )->off <=
GetAddrOff ( *paddr )
) &&
( GetAddrOff ( *paddr ) <
( UOFFSET ) (
((BLOCKPTR32)psym)->off +
((BLOCKPTR32)psym)->len
)
)
) {
// case 3b is true for a 32 bit block symbol
shf = TRUE;
}
break;
}
}
if ( shf == FALSE &&
( (psym = (SYMPTR) pcxt->hProc) != NULL ) ) {
// we have not passed tests 3a or 3b and the proc
// symbol handle is not null
switch (psym->rectyp) {
case S_LPROC16:
case S_GPROC16:
if (
( ( (PROCPTR16 )psym )->off <=
( CV_uoff16_t ) GetAddrOff (*paddr)
) &&
( GetAddrOff (*paddr) <
(UOFF32)
( ( ( PROCPTR16 ) psym )->off +
( ( PROCPTR16 ) psym )->len
)
)
) {
// case 3c is true for a 16 bit proc symbol
shf = TRUE;
}
break;
case S_LPROC32:
case S_GPROC32:
if (
( ( ( PROCPTR32 ) psym )->off <=
GetAddrOff ( *paddr )
) &&
( GetAddrOff (*paddr) <
( UOFFSET ) ( ( (PROCPTR32)psym)->off +
( (PROCPTR32)psym)->len
)
)
) {
// case 3b is true for a 32 bit proc symbol
shf = TRUE;
}
break;
case S_LPROCMIPS:
case S_GPROCMIPS:
if (
( ( ( PROCPTRMIPS ) psym )->off <=
GetAddrOff ( *paddr )
) &&
( GetAddrOff (*paddr) <
( UOFFSET ) ( ( (PROCPTRMIPS)psym)->off +
( (PROCPTRMIPS)psym)->len
)
)
) {
// case 3b is true for a 32 bit proc symbol
shf = TRUE;
}
break;
}
}
}
}
LLUnlock( hmod );
}
return( shf );
}
/*** SHGethExeFromName
*
* Purpose: To get an Exe handle given a name, or partial name
*
* Input:
* szPath - The path or filename of the exe
*
* Output:
*
* Returns:
* A handle to the exe or NULL on error
*
* Exceptions:
*
* Notes:
*
*************************************************************************/
HEXE LOADDS PASCAL SHGethExeFromName ( LPTSTR ltszPath ) {
HEXE hexe;
HEXE hexeEnd;
HEXE hexeMatch = (HEXE)NULL;
CHAR * szOMFPath;
CHAR szOMFFile[_MAX_CVFNAME];
CHAR szOMFExt[_MAX_CVEXT];
CHAR szName[_MAX_CVPATH];
CHAR szFile[_MAX_CVFNAME];
CHAR szExt[_MAX_CVEXT];
int iNameEnd;
LPTSTR lptchEnd = NULL;
// get the start of the exe list, or return an error if we can't get one
if( !ltszPath || !(*ltszPath) ||
!(hexe = hexeEnd = SHGetNextExe ( (HEXE)NULL )) ) {
return( (HEXE)NULL );
}
/*
* Does this module come with a file handle attached to it? If so,
* copy the path into the buffer where the path is to go and get
* the full path name for the file.
*/
if (*ltszPath == '|') {
ltszPath++;
lptchEnd = _ftcschr(ltszPath, '|');
assert(lptchEnd);
if (lptchEnd)
*lptchEnd = '\0';
}
// split it to the root name and extension
SHSplitPath ( ltszPath, NULL, NULL, szFile, szExt );
if ( !szExt[0] || !szExt[1] ) {
szExt[0] = '\0';
}
// we haven't yet determined the full path of the input name
szName[0] = '\0';
do {
// get the full exe name
// WARNING: this assumes pointers are the same as handles!!!
szOMFPath = SHGetExeName( hexe );
// get the extension
SHSplitPath ( szOMFPath, NULL, NULL, szOMFFile, szOMFExt );
// check for match
if ( !_ftcsicmp ( szOMFFile, szFile ) &&
!_ftcsicmp ( szOMFExt, szExt )
) {
// if we haven't done _tfullpath yet, do it now
if (szName[0] == '\0') {
if ( !_tfullpath ( szName, ltszPath, sizeof ( szName ) ) ) {
return( (HEXE)NULL );
}
iNameEnd = _ftcslen(szName);
if( *_ftcsdec( szName, &szName[iNameEnd] ) == '.' ) {
szName[--iNameEnd] = '\0';
}
}
// check for exact match, need the full path, but we know
// exe names are stored as full paths so szOMFPath is a full path
// if no extension, put the current extension on
if ( !szExt[0] && szOMFExt[0] ) {
_ftcscpy(szName + iNameEnd, szOMFExt);
}
// see if these are the same
if ( !_ftcsicmp( szOMFPath, szName ) ) {
hexeMatch = hexe;
break;
}
if ( !szExt[0] ) {
szName[iNameEnd] = '\0';
}
// save away the first potential match
if( !hexeMatch ) {
hexeMatch = hexe;
}
}
} while ( hexe = SHGetNextExe ( hexe ) );
// restore '|'
if (lptchEnd)
*lptchEnd = '|';
return(hexeMatch);
}
#define CSOURCESUFFIX 6
#define CBSOURCESUFFIX 4
char * rgszSourceSuffix[CSOURCESUFFIX] = {
"**.C",
".CPP",
".CXX",
".ASM",
".BAS",
".FOR"
};
/*** SHGetModName
*
* Purpose: To get an name handle given a module handle
*
* Input:
* hmod - the module handle
*
* Output:
*
* Returns:
* A handle to the exe or NULL on error
*
* Exceptions:
*
* Notes:
* The return pointer is only valid until the call to this function
*
*************************************************************************/
LSZ LOADDS PASCAL SHGetModName ( HMOD hmod ) {
CHAR szFullPath[_MAX_CVPATH];
static CHAR szMODName[_MAX_CVPATH];
CHAR szExt[_MAX_CVEXT];
LPCH lpch;
LPMDS lpmds;
LSZ lsz = NULL;
WORD iFile;
LPB lpb;
USHORT iSuffix;
LPB lpbSuffix;
BOOL fMatch;
if ( !hmod ) {
return NULL;
}
szFullPath [ 0 ] = '\0';
lpmds = LLLock ( hmod );
assert ( lpmds );
// Try to find a familiar source suffix
iFile = 0;
while ( lpb = (LPB) SLNameFromHmod ( hmod , (WORD) (iFile + 1) ) ) {
lpbSuffix = lpb + *lpb + 1 - CBSOURCESUFFIX;
for (iSuffix = 0; iSuffix < CSOURCESUFFIX; iSuffix++) {
LPB lpbTest = lpbSuffix;
BYTE *pbTest = rgszSourceSuffix [ iSuffix ];
fMatch = TRUE;
while ( fMatch && *pbTest ) {
switch(*pbTest) {
case '*': break;
default: if(('a'-'A') == (*lpbTest - *pbTest)) break;
case '.':if(*lpbTest == *pbTest) break;
fMatch = FALSE;
}
lpbTest = _ftcsinc( lpbTest );
pbTest = _ftcsinc( pbTest );
}
if ( fMatch ) {
break;
}
}
if ( fMatch ) {
MEMMOVE ( szFullPath, lpb + 1, *(lpb) );
szFullPath [ *lpb ] = 0;
break;
}
iFile++;
}
// As a last resort, use the module name from the omf
if ( !szFullPath[0] && lpmds->name ) {
_ftcscpy ( szFullPath, lpmds->name );
}
if ( szFullPath[0] ) {
// take off the source name
if ( lpch = _ftcschr ( (LPCH) szFullPath, '(' ) ) {
*lpch = '\0';
}
// extract the module name (it is in the form of a path)
SHSplitPath ( szFullPath, NULL, NULL, szMODName, szExt );
lsz = szMODName;
}
LLUnlock( hmod );
return lsz;
}
LOCAL BOOL SHCmpGlobName (
SYMPTR pSym,
LPSSTR lpsstr,
PFNCMP pfnCmp,
SHFLAG fCase
) {
BOOL fRet = FALSE;
switch ( pSym->rectyp ) {
default:
assert (FALSE); // Should Never be encountered
break;
case S_CONSTANT:
case S_GDATA16:
case S_GDATA32:
case S_GTHREAD32:
case S_UDT:
case S_COBOLUDT:
fRet = // [01]
( !( lpsstr->searchmask & SSTR_symboltype ) || // [01]
( pSym->rectyp == lpsstr->symtype ) // [01]
) && // [01]
!(*pfnCmp) ( // [01]
lpsstr, // [01]
pSym, // [01]
SHlszGetSymName(pSym), // [01]
fCase // [01]
); // [01]
// save the sym pointer
break;
}
return fRet;
}
SHFLAG LOADDS PASCAL SHCompareRE (LPCH psym, LPCH pRe) {
Unreferenced ( psym );
Unreferenced ( pRe );
return (TRUE);
}
/* These rountines are used for ee compare function callbacks */
#if defined (DOS3) && !defined(CVS) && !defined(WINDOWS3)
extern LPV CVGetProcAddr(unsigned short,unsigned short);
HSYM LOADDS PASCAL CmpSHFindNameInContext (
HSYM hsym,
PCXT pcxt,
LPSSTR lpsstr,
SHFLAG shflag,
PFNCMP pfncmp,
SHFLAG shflag1,
PCXT pcxt1
) {
return (HSYM) SHFindNameInContext( hsym, pcxt, lpsstr, shflag,
(PFNCMP)CVGetProcAddr( rglan[ESilan()].hDLL, pfncmp ), shflag1, pcxt1 );
}
HSYM LOADDS PASCAL CmpPHFindNameInPublics (
HSYM hsym,
HEXE hexe,
LPSSTR lpsstr,
SHFLAG shflag,
PFNCMP pfncmp
) {
return (HSYM) PHFindNameInPublics( hsym, hexe, lpsstr, shflag,
(PFNCMP)CVGetProcAddr( rglan[ ESilan() ].hDLL, pfncmp ) );
}
#endif // DOS3 && !CVS && !WINDOWS3
/*** SHFindBpOrReg
*
* Purpose: since find_framerel and find_register are basically the same
* this procedure implements both to reduce code.
*
* Input: the address of interest, item - the BPoffset or Register
* and which item we are searching for (S_REG S_BPREL)
*
* Output: The buffer rgbName is filled
* Returns TRUE FALSE if found
*
* Exceptions:
*
* Notes:
*
*************************************************************************/
int PASCAL SHFindBpOrReg (
LPADDR paddr,
UOFFSET item,
WORD recLoc,
LPCH rgbName
) {
SYMPTR psym;
SYMPTR pProc;
CXT cxt;
int fGo;
SHHMODFrompCXT ( &cxt ) = 0;
if ( SHSetCxt ( paddr, &cxt ) == NULL ) {
return (FALSE);
}
for (;;) {
fGo = FALSE;
if (SHHBLKFrompCXT(&cxt) != 0) {
fGo = TRUE;
}
else if ( ( pProc = SHHPROCFrompCXT ( &cxt ) ) != NULL ) {
switch ( pProc->rectyp ) {
case S_LPROC16:
case S_GPROC16:
if (((((PROCPTR16)pProc)->off + (CV_uoff32_t)((PROCPTR16)pProc)->DbgStart) <=
GetAddrOff (*paddr)) &&
(GetAddrOff (*paddr) < (UOFF32)(((PROCPTR16)pProc)->off + ((PROCPTR16)pProc)->DbgEnd))) {
fGo = TRUE;
}
break;
case S_LPROC32:
case S_GPROC32:
if (((((PROCPTR32)pProc)->off + ((PROCPTR32)pProc)->DbgStart) <=
GetAddrOff (*paddr)) &&
(GetAddrOff (*paddr) < (((PROCPTR32)pProc)->off + ((PROCPTR32)pProc)->DbgEnd))) {
fGo = TRUE;
}
break;
case S_LPROCMIPS:
case S_GPROCMIPS:
if (((((PROCPTRMIPS)pProc)->off + ((PROCPTRMIPS)pProc)->DbgStart) <=
GetAddrOff (*paddr)) &&
(GetAddrOff (*paddr) < (((PROCPTRMIPS)pProc)->off + ((PROCPTRMIPS)pProc)->DbgEnd))) {
fGo = TRUE;
}
break;
}
}
if (fGo == FALSE) {
return (FALSE);
}
if( SHHBLKFrompCXT(&cxt) ) {
psym = (SYMPTR) SHHBLKFrompCXT(&cxt);
}
else if( SHHPROCFrompCXT(&cxt) ) {
psym = (SYMPTR) SHHPROCFrompCXT(&cxt);
}
/* skip block or proc record */
psym = NEXTSYM (SYMPTR, psym);
fGo = TRUE;
while( fGo ) {
switch (psym->rectyp) {
case S_REGISTER:
if ((recLoc == S_REGISTER) &&
((REGPTR)psym)->reg == (WORD)item) {
_ftcsncpy (rgbName, &((REGPTR)psym)->name[1],
(BYTE)*(((REGPTR)psym)->name));
rgbName[(BYTE)*(((REGPTR)psym)->name)] = '\0';
return(TRUE);
}
break;
case S_END:
// terminate loop
fGo = FALSE;
break;
case S_LPROC16:
case S_GPROC16:
case S_BLOCK16:
// terminate loop
fGo = FALSE;
case S_BPREL16:
if ((recLoc == S_BPREL16) &&
((UOFFSET)((BPRELPTR16)psym)->off) == item ) {
_ftcsncpy (rgbName, &((BPRELPTR16)psym)->name[1],
(BYTE)*(((BPRELPTR16)psym)->name));
rgbName[(BYTE)*(((BPRELPTR16)psym)->name)] = '\0';
return(TRUE);
}
break;
case S_LABEL16:
case S_WITH16:
case S_LDATA16:
case S_GDATA16:
break;
case S_LPROC32:
case S_GPROC32:
case S_BLOCK32:
case S_LPROCMIPS:
case S_GPROCMIPS:
// terminate loop
fGo = FALSE;
case S_BPREL32:
if ((recLoc == S_BPREL32) &&
((UOFFSET)((BPRELPTR32)psym)->off) == item ) {
_ftcsncpy (rgbName, &((BPRELPTR32)psym)->name[1],
(BYTE)*(((BPRELPTR32)psym)->name));
rgbName[(BYTE)*(((BPRELPTR32)psym)->name)] = '\0';
return(TRUE);
}
break;
case S_REGREL32:
if ((recLoc == S_REGREL32) &&
((UOFFSET)((LPREGREL32)psym)->off) == item ) {
_ftcsncpy (rgbName, &((LPREGREL32)psym)->name[1],
(BYTE)*(((LPREGREL32)psym)->name));
rgbName[(BYTE)*(((LPREGREL32)psym)->name)] = '\0';
return(TRUE);
}
break;
case S_LABEL32:
case S_WITH32:
case S_LDATA32:
case S_GDATA32:
case S_LTHREAD32:
case S_GTHREAD32:
case S_ENDARG:
break;
case S_CONSTANT:
case S_UDT:
case S_COBOLUDT:
break;
default:
return(FALSE); /* Bad SYMBOLS data */
}
psym = NEXTSYM (SYMPTR, psym);
}
/* get the parent block */
SHGoToParent(&cxt, &cxt);
}
return (FALSE);
}
UOFFSET PASCAL LOADDS SHGetDebugStart ( HSYM hsym ) {
SYMPTR psym = (SYMPTR) hsym;
UOFFSET uoff = 0;
switch (psym->rectyp) {
#if defined (ADDR_16) || defined (ADDR_MIXED)
case S_LPROC16:
case S_GPROC16: {
PROCPTR16 psym = (PROCPTR16) hsym;
uoff = psym->off + psym->DbgStart;
}
break;
#endif
#if defined (ADDR_32) || defined (ADDR_MIXED) || defined(HOST32)
case S_LPROC32:
case S_GPROC32: {
PROCPTR32 psym = (PROCPTR32) hsym;
uoff = psym->off + psym->DbgStart;
}
break;
case S_LPROCMIPS:
case S_GPROCMIPS: {
PROCPTRMIPS psym = (PROCPTRMIPS) hsym;
uoff = psym->off + psym->DbgStart;
}
break;
#endif
default:
assert ( FALSE );
}
return uoff;
}
LSZ PASCAL LOADDS SHGetSymName ( HSYM hsym, LSZ lsz ) {
SYMPTR psym = (SYMPTR) hsym;
LPCH lst = NULL;
switch ( psym->rectyp ) {
case S_REGISTER:
lst = ( (REGPTR) psym)->name;
break;
case S_CONSTANT:
lst = ( (CONSTPTR) psym)->name;
break;
case S_BPREL16:
lst = ( (BPRELPTR16) psym)->name;
break;
case S_GDATA16:
case S_LDATA16:
lst = ( (DATAPTR16) psym)->name;
break;
case S_PUB16:
lst = ( (PUBPTR16) psym)->name;
break;
case S_LPROC16:
case S_GPROC16:
lst = ( (PROCPTR16) psym)->name;
break;
case S_THUNK16:
lst = ( (THUNKPTR16) psym)->name;
break;
case S_BLOCK16:
lst = ( (BLOCKPTR16) psym)->name;
break;
case S_LABEL16:
lst = ( (LABELPTR16) psym)->name;
break;
case S_BPREL32:
lst = ( (BPRELPTR32) psym)->name;
break;
case S_REGREL32:
lst = ( (LPREGREL32) psym)->name;
break;
case S_GDATA32:
case S_LDATA32:
case S_GTHREAD32:
case S_LTHREAD32:
lst = ( (DATAPTR32) psym)->name;
break;
case S_PUB32:
lst = ( (PUBPTR32) psym)->name;
break;
case S_LPROC32:
case S_GPROC32:
lst = ( (PROCPTR32) psym)->name;
break;
case S_LPROCMIPS:
case S_GPROCMIPS:
lst = ( (PROCPTRMIPS) psym)->name;
break;
case S_THUNK32:
lst = ( (THUNKPTR32) psym)->name;
break;
case S_BLOCK32:
lst = ( (BLOCKPTR32) psym)->name;
break;
case S_LABEL32:
lst = ( (LABELPTR32) psym)->name;
break;
}
if ( lst != NULL && *lst > 0 ) {
_ftcsncpy ( lsz, lst + 1, *lst );
*( lsz + *( (CHAR FAR *)lst) ) = '\0';
return lsz;
}
else {
return NULL;
}
}
BOOL PASCAL LOADDS SHIsLabel ( HSYM hsym ) {
BOOL fFound = FALSE;
SYMPTR psym = (SYMPTR) hsym;
switch ( psym->rectyp ) {
case S_LPROC16:
case S_GPROC16:
case S_LABEL16:
case S_LPROC32:
case S_GPROC32:
case S_LABEL32:
case S_LPROCMIPS:
case S_GPROCMIPS:
fFound = TRUE;
break;
}
return fFound;
}
/*** SHAddressToLabel
*
* Purpose: To find the closest label/proc to the specified address is
* found and put in pch. Both the symbol table and the
* publics tables are searched.
*
* Input: paddr - Pointer to the address whose label is to be found
*
* Output:
* pch - The name is copied here.
* Returns: TRUE if a label was found.
*
* Exceptions:
*
*
*************************************************************************/
BOOL LOADDS PASCAL SHAddrToLabel ( LPADDR paddr, LSZ lsz ) {
CXT cxt;
SYMPTR psym;
LBS lbs;
// get the module to search
*lsz = '\0';
MEMSET ( (LPV) &cxt, 0, sizeof ( CXT ) );
MEMSET ( (LPV) &lbs, 0, sizeof ( lbs ) );
lbs.addr = *paddr;
SHSetCxt ( paddr, &cxt );
if (!cxt.hMod ) {
return(FALSE);
}
// Get the nearest local labels in this module
lbs.tagMod = cxt.hMod;
lbs.addr.emi = cxt.addr.emi;
SHpSymlplLabLoc ( &lbs );
// Check the candidates found
if ( lbs.tagLab ) {
psym = (SYMPTR) lbs.tagLab;
switch ( psym->rectyp ) {
case S_LABEL16:
if (GetAddrOff (lbs.addr) == ((LABELPTR16)psym)->off) {
_ftcsncpy(lsz, &(((LABELPTR16)psym)->name[1]),
(BYTE)(((LABELPTR16)psym)->name[0]));
lsz[(BYTE)(((LABELPTR16)psym)->name[0])] = '\0';
return TRUE;
}
case S_LABEL32:
if (GetAddrOff (lbs.addr) == ((LABELPTR32)psym)->off) {
_ftcsncpy(lsz, &(((LABELPTR32)psym)->name[1]),
(BYTE)(((LABELPTR32)psym)->name[0]));
lsz[(BYTE)(((LABELPTR32)psym)->name[0])] = '\0';
return TRUE;
}
}
}
if ( lbs.tagProc ) {
psym = (SYMPTR) lbs.tagProc;
switch ( psym->rectyp ) {
case S_LPROC16:
case S_GPROC16:
if (GetAddrOff ( lbs.addr ) == ((PROCPTR16)psym)->off) {
_ftcsncpy(lsz, &(((PROCPTR16)psym)->name[1]),
(BYTE)(((PROCPTR16)psym)->name[0]));
lsz[(BYTE)(((PROCPTR16)psym)->name[0])] = '\0';
return(TRUE);
}
break;
case S_LPROC32:
case S_GPROC32:
if (GetAddrOff ( lbs.addr ) == ((PROCPTR32)psym)->off) {
_ftcsncpy(lsz, &(((PROCPTR32)psym)->name[1]),
(BYTE)(((PROCPTR32)psym)->name[0]));
lsz[(BYTE)(((PROCPTR32)psym)->name[0])] = '\0';
return(TRUE);
}
break;
case S_LPROCMIPS:
case S_GPROCMIPS:
if (GetAddrOff ( lbs.addr ) == ((PROCPTRMIPS)psym)->off) {
_ftcsncpy(lsz, &(((PROCPTRMIPS)psym)->name[1]),
(BYTE)(((PROCPTRMIPS)psym)->name[0]));
lsz[(BYTE)(((PROCPTRMIPS)psym)->name[0])] = '\0';
return(TRUE);
}
break;
}
}
// now check the publics
if (!PHGetNearestHsym(SHpADDRFrompCXT(&cxt),
SHHexeFromHmod(SHHMODFrompCXT(&cxt)),
(PHSYM) &psym)) {
switch (psym->rectyp) {
case S_PUB16:
_ftcsncpy(lsz, &(((DATAPTR16)psym)->name[1]),
(BYTE)(((DATAPTR16)psym)->name[0]));
lsz [(BYTE)(((DATAPTR16)psym)->name[0])] = '\0';
return(TRUE);
case S_PUB32:
_ftcsncpy(lsz, &(((DATAPTR32)psym)->name[1]),
(BYTE)(((DATAPTR32)psym)->name[0]));
lsz [(BYTE)(((DATAPTR32)psym)->name[0])] = '\0';
return(TRUE);
}
}
return(FALSE);
}
BOOL LOADDS PASCAL SHFIsAddrNonVirtual( LPADDR paddr ) {
BOOL fReturn = TRUE;
HEXE hexe = (HEXE)emiAddr( *paddr );
assert( hexe );
// Ask if the overlay is loaded
fReturn = SHIsEmiLoaded( hexe );
// Otherwise, check the dll
if ( fReturn ) {
ADDR addr = *paddr;
// If SYFixupAddr fails, it's because the address is virtual
// (unless something is seriously wrong)
fReturn = SYFixupAddr ( &addr );
}
return fReturn;
}
BOOL LOADDS PASCAL SHIsEmiLoaded ( HEXE hexe ) {
BOOL fReturn;
LPEXS lpexs;
lpexs = LLLock ( hexe );
fReturn = lpexs->fIsLoaded;
LLUnlock ( hexe );
return fReturn;
}
BOOL LOADDS PASCAL SHIsFarProc ( HSYM hsym ) {
BOOL fReturn = FALSE;
switch ( ( (SYMPTR) hsym )->rectyp ) {
case S_LPROC16:
case S_GPROC16:
fReturn = ((PROCPTR16) hsym)->flags.CV_PFLAG_FAR;
break;
case S_LPROC32:
case S_GPROC32:
fReturn = ((PROCPTR32) hsym)->flags.CV_PFLAG_FAR;
break;
case S_LPROCMIPS:
case S_GPROCMIPS:
fReturn = FALSE;
break;
}
return fReturn;
}
#ifdef TARGMAC68K
char *RegisterName[] =
{
"D0", // 0
"D1", // 1
"D2", // 2
"D3", // 3
"D4", // 4
"D5", // 5
"D6", // 6
"D7", // 7
"A0", // 8
"A1", // 9
"A2", // 10
"A3", // 11
"A4", // 12
"A5", // 13
"A6", // 14
"A7", // 15
"CCR", // 16
"SR", // 17
"USP", // 18
"MSP", // 19
"SFC", // 20
"DFC", // 21
"CACR", // 22
"VBR", // 23
"CAAR", // 24
"ISP", // 25
"PC", // 26
"reserved", // 27
"FPCR", // 28
"FPSR", // 29
"FPIAR", // 30
"reserved", // 31
"FP0", // 32
"FP1", // 33
"FP2", // 34
"FP3", // 35
"FP4", // 36
"FP5", // 37
"FP6", // 38
"FP7", // 39
NULL
};
#elif defined (TARGMACPPC) || defined (TARGALPHA)
typedef struct _RegInfo {
WORD wIndex;
CHAR * szName;
} REGINFO;
typedef REGINFO FAR * LPREGINFO;
REGINFO rgRegInfo[] = {
#if defined (TARGMACPPC)
/*
** PowerPC General Registers ( User Level )
*/
{ CV_PPC_GPR0, "GPR0" },
{ CV_PPC_GPR1, "SP" },
{ CV_PPC_GPR2, "RTOC" },
{ CV_PPC_GPR3, "GPR3" },
{ CV_PPC_GPR4, "GPR4" },
{ CV_PPC_GPR5, "GPR5" },
{ CV_PPC_GPR6, "GPR6" },
{ CV_PPC_GPR7, "GPR7" },
{ CV_PPC_GPR8, "GPR8" },
{ CV_PPC_GPR9, "GPR9" },
{ CV_PPC_GPR10, "GPR10" },
{ CV_PPC_GPR11, "GPR11" },
{ CV_PPC_GPR12, "GPR12" },
{ CV_PPC_GPR13, "GPR13" },
{ CV_PPC_GPR14, "GPR14" },
{ CV_PPC_GPR15, "GPR15" },
{ CV_PPC_GPR16, "GPR16" },
{ CV_PPC_GPR17, "GPR17" },
{ CV_PPC_GPR18, "GPR18" },
{ CV_PPC_GPR19, "GPR19" },
{ CV_PPC_GPR20, "GPR20" },
{ CV_PPC_GPR21, "GPR21" },
{ CV_PPC_GPR22, "GPR22" },
{ CV_PPC_GPR23, "GPR23" },
{ CV_PPC_GPR24, "GPR24" },
{ CV_PPC_GPR25, "GPR25" },
{ CV_PPC_GPR26, "GPR26" },
{ CV_PPC_GPR27, "GPR27" },
{ CV_PPC_GPR28, "GPR28" },
{ CV_PPC_GPR29, "GPR29" },
{ CV_PPC_GPR30, "GPR30" },
{ CV_PPC_GPR31, "GPR31" },
/*
** PowerPC Condition Register ( User Level )
*/
{ CV_PPC_CR, "CR" },
{ CV_PPC_CR0, "CR0" },
{ CV_PPC_CR1, "CR1" },
{ CV_PPC_CR2, "CR2" },
{ CV_PPC_CR3, "CR3" },
{ CV_PPC_CR4, "CR4" },
{ CV_PPC_CR5, "CR5" },
{ CV_PPC_CR6, "CR6" },
{ CV_PPC_CR7, "CR7" },
/*
** PowerPC Floating Point Registers ( User Level )
*/
{ CV_PPC_FPR0, "FPR0" },
{ CV_PPC_FPR1, "FPR1" },
{ CV_PPC_FPR2, "FPR2" },
{ CV_PPC_FPR3, "FPR3" },
{ CV_PPC_FPR4, "FPR4" },
{ CV_PPC_FPR5, "FPR5" },
{ CV_PPC_FPR6, "FPR6" },
{ CV_PPC_FPR7, "FPR7" },
{ CV_PPC_FPR8, "FPR8" },
{ CV_PPC_FPR9, "FPR9" },
{ CV_PPC_FPR10, "FPR10" },
{ CV_PPC_FPR11, "FPR11" },
{ CV_PPC_FPR12, "FPR12" },
{ CV_PPC_FPR13, "FPR13" },
{ CV_PPC_FPR14, "FPR14" },
{ CV_PPC_FPR15, "FPR15" },
{ CV_PPC_FPR16, "FPR16" },
{ CV_PPC_FPR17, "FPR17" },
{ CV_PPC_FPR18, "FPR18" },
{ CV_PPC_FPR19, "FPR19" },
{ CV_PPC_FPR20, "FPR20" },
{ CV_PPC_FPR21, "FPR21" },
{ CV_PPC_FPR22, "FPR22" },
{ CV_PPC_FPR23, "FPR23" },
{ CV_PPC_FPR24, "FPR24" },
{ CV_PPC_FPR25, "FPR25" },
{ CV_PPC_FPR26, "FPR26" },
{ CV_PPC_FPR27, "FPR27" },
{ CV_PPC_FPR28, "FPR28" },
{ CV_PPC_FPR29, "FPR29" },
{ CV_PPC_FPR30, "FPR30" },
{ CV_PPC_FPR31, "FPR31" },
/*
** PowerPC Floating Point Status and Control Register ( User Level )
*/
{ CV_PPC_FPSCR, "FPSCR" },
/*
** PowerPC Machine State Register ( Supervisor Level )
*/
{ CV_PPC_MSR, "MSR" },
/*
** PowerPC Segment Registers ( Supervisor Level )
*/
{ CV_PPC_SR0, "SR0" },
{ CV_PPC_SR1, "SR1" },
{ CV_PPC_SR2, "SR2" },
{ CV_PPC_SR3, "SR3" },
{ CV_PPC_SR4, "SR4" },
{ CV_PPC_SR5, "SR5" },
{ CV_PPC_SR6, "SR6" },
{ CV_PPC_SR7, "SR7" },
{ CV_PPC_SR8, "SR8" },
{ CV_PPC_SR9, "SR9" },
{ CV_PPC_SR10, "SR10" },
{ CV_PPC_SR11, "SR11" },
{ CV_PPC_SR12, "SR12" },
{ CV_PPC_SR13, "SR13" },
{ CV_PPC_SR14, "SR14" },
{ CV_PPC_SR15, "SR15" },
/*
** For all of the special purpose registers add 100 to the SPR# that the
** Motorola/IBM documentation gives with the exception of any imaginary
** registers.
*/
/*
** PowerPC Special Purpose Registers ( User Level )
*/
{ CV_PPC_PC, "PC" }, // PC (imaginary register)
{ CV_PPC_MQ, "MQ" }, // MPC601
{ CV_PPC_XER, "XER" },
{ CV_PPC_RTCU, "RTCU" }, // MPC601
{ CV_PPC_RTCL, "RTCL" }, // MPC601
{ CV_PPC_LR, "LR" },
{ CV_PPC_CTR, "CTR" },
/*
** PowerPC Special Purpose Registers ( Supervisor Level )
*/
{ CV_PPC_DSISR, "DSISR" },
{ CV_PPC_DAR, "DAR" },
{ CV_PPC_DEC, "DEC" },
{ CV_PPC_SDR1, "SDR1" },
{ CV_PPC_SRR0, "SRR0" },
{ CV_PPC_SRR1, "SRR1" },
{ CV_PPC_SPRG0, "SPRG0" },
{ CV_PPC_SPRG1, "SPRG1" },
{ CV_PPC_SPRG2, "SPRG2" },
{ CV_PPC_SPRG3, "SPRG3" },
{ CV_PPC_ASR, "ASR" }, // 64-bit implementations only
{ CV_PPC_EAR, "EAR" },
{ CV_PPC_PVR, "PVR" },
{ CV_PPC_BAT0U, "BAT0U" },
{ CV_PPC_BAT0L, "BAT0L" },
{ CV_PPC_BAT1U, "BAT1U" },
{ CV_PPC_BAT1L, "BAT1L" },
{ CV_PPC_BAT2U, "BAT2U" },
{ CV_PPC_BAT2L, "BAT2L" },
{ CV_PPC_BAT3U, "BAT3U" },
{ CV_PPC_BAT3L, "BAT3L" },
{ CV_PPC_DBAT0U, "DBAT0U" },
{ CV_PPC_DBAT0L, "DBAT0L" },
{ CV_PPC_DBAT1U, "DBAT1U" },
{ CV_PPC_DBAT1L, "DBAT1L" },
{ CV_PPC_DBAT2U, "DBAT2U" },
{ CV_PPC_DBAT2L, "DBAT2L" },
{ CV_PPC_DBAT3U, "DBAT3U" },
{ CV_PPC_DBAT3L, "DBAT3L" },
/*
** PowerPC Special Purpose Registers Implementation Dependent ( Supervisor Level )
*/
/*
** Doesn't appear that IBM/Motorola has finished defining these.
*/
{ CV_PPC_PMR0, "PMR0" }, // MPC620
{ CV_PPC_PMR1, "PMR1" }, // MPC620
{ CV_PPC_PMR2, "PMR2" }, // MPC620
{ CV_PPC_PMR3, "PMR3" }, // MPC620
{ CV_PPC_PMR4, "PMR4" }, // MPC620
{ CV_PPC_PMR5, "PMR5" }, // MPC620
{ CV_PPC_PMR6, "PMR6" }, // MPC620
{ CV_PPC_PMR7, "PMR7" }, // MPC620
{ CV_PPC_PMR8, "PMR8" }, // MPC620
{ CV_PPC_PMR9, "PMR9" }, // MPC620
{ CV_PPC_PMR10, "PMR10" }, // MPC620
{ CV_PPC_PMR11, "PMR11" }, // MPC620
{ CV_PPC_PMR12, "PMR12" }, // MPC620
{ CV_PPC_PMR13, "PMR13" }, // MPC620
{ CV_PPC_PMR14, "PMR14" }, // MPC620
{ CV_PPC_PMR15, "PMR15" }, // MPC620
{ CV_PPC_DMISS, "DMISS" }, // MPC603
{ CV_PPC_DCMP, "DCMP" }, // MPC603
{ CV_PPC_HASH1, "HASH1" }, // MPC603
{ CV_PPC_HASH2, "HASH2" }, // MPC603
{ CV_PPC_IMISS, "IMISS" }, // MPC603
{ CV_PPC_ICMP, "ICMP" }, // MPC603
{ CV_PPC_RPA, "RPA" }, // MPC603
{ CV_PPC_HID0, "HID0" }, // MPC601, MPC603, MPC620
{ CV_PPC_HID1, "HID1" }, // MPC601
{ CV_PPC_HID2, "HID2" }, // MPC601, MPC603, MPC620 ( IABR )
{ CV_PPC_HID3, "HID3" }, // Not Defined
{ CV_PPC_HID4, "HID4" }, // Not Defined
{ CV_PPC_HID5, "HID5" }, // MPC601, MPC604, MPC620 ( DABR )
{ CV_PPC_HID6, "HID6" }, // Not Defined
{ CV_PPC_HID7, "HID7" }, // Not Defined
{ CV_PPC_HID8, "HID8" }, // MPC620 ( BUSCSR )
{ CV_PPC_HID9, "HID9" }, // MPC620 ( L2CSR )
{ CV_PPC_HID10, "HID10" }, // Not Defined
{ CV_PPC_HID11, "HID11" }, // Not Defined
{ CV_PPC_HID12, "HID12" }, // Not Defined
{ CV_PPC_HID13, "HID13" }, // MPC604 ( HCR )
{ CV_PPC_HID14, "HID14" }, // Not Defined
{ CV_PPC_HID15, "HID15" } // MPC601, MPC604, MPC620 ( PIR )
#else
{ CV_ALPHA_NOREG, "NOREG" },
{ CV_ALPHA_FltF0, "F0" },
{ CV_ALPHA_FltF1, "F1" },
{ CV_ALPHA_FltF2, "F2" },
{ CV_ALPHA_FltF3, "F3" },
{ CV_ALPHA_FltF4, "F4" },
{ CV_ALPHA_FltF5, "F5" },
{ CV_ALPHA_FltF6, "F6" },
{ CV_ALPHA_FltF7, "F7" },
{ CV_ALPHA_FltF8, "F8" },
{ CV_ALPHA_FltF9, "F9" },
{ CV_ALPHA_FltF10, "F10" },
{ CV_ALPHA_FltF11, "F11" },
{ CV_ALPHA_FltF12, "F12" },
{ CV_ALPHA_FltF13, "F13" },
{ CV_ALPHA_FltF14, "F14" },
{ CV_ALPHA_FltF15, "F15" },
{ CV_ALPHA_FltF16, "F16" },
{ CV_ALPHA_FltF17, "F17" },
{ CV_ALPHA_FltF18, "F18" },
{ CV_ALPHA_FltF19, "F19" },
{ CV_ALPHA_FltF20, "F20" },
{ CV_ALPHA_FltF21, "F21" },
{ CV_ALPHA_FltF22, "F22" },
{ CV_ALPHA_FltF23, "F23" },
{ CV_ALPHA_FltF24, "F24" },
{ CV_ALPHA_FltF25, "F25" },
{ CV_ALPHA_FltF26, "F26" },
{ CV_ALPHA_FltF27, "F27" },
{ CV_ALPHA_FltF28, "F28" },
{ CV_ALPHA_FltF29, "F29" },
{ CV_ALPHA_FltF30, "F30" },
{ CV_ALPHA_FltF31, "F31" },
{ CV_ALPHA_IntV0, "V0" },
{ CV_ALPHA_IntT0, "T0" },
{ CV_ALPHA_IntT1, "T1" },
{ CV_ALPHA_IntT2, "T2" },
{ CV_ALPHA_IntT3, "T3" },
{ CV_ALPHA_IntT4, "T4" },
{ CV_ALPHA_IntT5, "T5" },
{ CV_ALPHA_IntT6, "T6" },
{ CV_ALPHA_IntT7, "T7" },
{ CV_ALPHA_IntS0, "S0" },
{ CV_ALPHA_IntS1, "S1" },
{ CV_ALPHA_IntS2, "S2" },
{ CV_ALPHA_IntS3, "S3" },
{ CV_ALPHA_IntS4, "S4" },
{ CV_ALPHA_IntS5, "S5" },
{ CV_ALPHA_IntFP, "FP" },
{ CV_ALPHA_IntA0, "A0" },
{ CV_ALPHA_IntA1, "A1" },
{ CV_ALPHA_IntA2, "A2" },
{ CV_ALPHA_IntA3, "A3" },
{ CV_ALPHA_IntA4, "A4" },
{ CV_ALPHA_IntA5, "A5" },
{ CV_ALPHA_IntT8, "T8" },
{ CV_ALPHA_IntT9, "T9" },
{ CV_ALPHA_IntT10, "T10" },
{ CV_ALPHA_IntT11, "T11" },
{ CV_ALPHA_IntRA, "RA" },
{ CV_ALPHA_IntT12, "T12" },
{ CV_ALPHA_IntAT, "AT" },
{ CV_ALPHA_IntGP, "GP" },
{ CV_ALPHA_IntSP, "SP" },
{ CV_ALPHA_IntZERO, "ZERO" },
{ CV_ALPHA_Fpcr, "FPCR" },
{ CV_ALPHA_Fir, "FIR" },
{ CV_ALPHA_Psr, "PSR" },
{ CV_ALPHA_FltFsr, "FSR" },
#endif
};
INT CDECL RegInfoCmp ( const VOID FAR * lpElem1, const VOID FAR * lpElem2 )
{
if ( ((LPREGINFO)lpElem1)->wIndex < ((LPREGINFO)lpElem2)->wIndex ) {
return ( -1 );
}
else if ( ((LPREGINFO)lpElem1)->wIndex > ((LPREGINFO)lpElem2)->wIndex ) {
return ( 1 );
}
else {
return ( 0 );
}
}
#else
char *RegisterName[] =
{
"NONE", // 0
"AL", // 1
"CL", // 2
"DL", // 3
"BL", // 4
"AH", // 5
"CH", // 6
"DH", // 7
"BH", // 8
"AX", // 9
"CX", // 10
"DX", // 11
"BX", // 12
"SP", // 13
"BP", // 14
"SI", // 15
"DI", // 16
"EAX", // 17
"ECX", // 18
"EDX", // 19
"EBX", // 20
"ESP", // 21
"EBP", // 22
"ESI", // 23
"EDI", // 24
"ES", // 25
"CS", // 26
"SS", // 27
"DS", // 28
"FS", // 29
"GS", // 30
"IP", // 31
"FLAGS", // 32
NULL
};
#endif
/*** SHGetSymLoc
*
* Purpose:
*
* Input:
* hSym - A handle to the symbol to get a location.
* lsz - Where to write the result.
* cbMax - Size of lsz.
* pcxt - Context.
*
* Output:
* - lsz filled in.
* Returns - The number of bytes written to the string.
*
* Exceptions:
*
* Notes: lpSym emspage must be loaded
*
*/
int LOADDS PASCAL SHGetSymLoc ( HSYM hsym, LSZ lsz, UINT cbMax, PCXT pcxt )
{
SYMPTR lpsym = (SYMPTR) hsym;
char rgch[20];
if ( cbMax == 0 ) {
return 0;
}
MEMSET ( rgch, '\0', sizeof ( rgch ) );
switch ( lpsym->rectyp ) {
case S_BPREL16:
if ( ( (BPRELPTR16) lpsym )->off >= 0 ) {
SPRINTF ( rgch, "[BP+%04X]", ((BPRELPTR16) lpsym )->off );
}
else {
SPRINTF ( rgch, "[BP-%04X]", - ( (BPRELPTR16) lpsym )->off );
}
break;
case S_BPREL32: {
long off = (long) ( (BPRELPTR32) lpsym )->off;
char * szBPREG =
#if defined( TARGMAC68K )
"A6";
#elif defined( TARGMACPPC )
"[SP]";
#else
"EBP";
#endif
char * szFMT;
char ch;
if ( off < 0 ) {
ch = '-';
off = -off;
}
else {
ch = '+';
}
if ( HIWORD( off ) ) {
szFMT = "[%s%c%08lX]";
}
else {
szFMT = "[%s%c%04lX]";
}
SPRINTF(
rgch,
szFMT,
szBPREG,
ch,
off
);
}
break;
case S_REGREL32: {
long off = (long) ( (LPREGREL32) lpsym )->off;
short reg = ((LPREGREL32)lpsym)->reg;
char *lpch = rgch;
#if defined(TARGALPHA)
REGINFO regInfo;
LPREGINFO lpRegInfo;
regInfo.wIndex = reg;
lpRegInfo = bsearch (
&regInfo,
rgRegInfo,
sizeof ( rgRegInfo ) / sizeof ( rgRegInfo[0] ),
sizeof ( rgRegInfo[0] ),
&RegInfoCmp
);
assert ( lpRegInfo );
rgch[0] = '[';
_ftcscpy ( rgch+1, lpRegInfo->szName );
#else
switch (reg) {
#if defined(_MIPS_)
case CV_M4_IntSP:
SPRINTF( rgch, "[SP");
break;
case CV_M4_IntS8:
SPRINTF( rgch, "[S8");
break;
case CV_M4_IntGP:
SPRINTF( rgch, "[GP");
break;
#endif
default:
SPRINTF( rgch, "[REG");
}
#endif
lpch += _ftcslen(rgch);
if ( off >= 0 ) {
if ( off > 0xFFFF ) {
SPRINTF ( lpch, "+%08lX]", off );
}
else {
SPRINTF ( lpch, "+%04lX]", off );
}
}
else {
if ( off < -0xFFFFL ) {
SPRINTF ( lpch, "-%08lX]", -off );
}
else {
SPRINTF ( lpch, "-%04lX]", -off );
}
}
}
break;
case S_REGISTER:
{
#if defined ( TARGMACPPC ) || defined (TARGALPHA)
WORD iReg1 = ( ( (REGPTR) lpsym )->reg );
REGINFO regInfo;
LPREGINFO lpRegInfo;
regInfo.wIndex = iReg1;
lpRegInfo = bsearch (
&regInfo,
rgRegInfo,
sizeof ( rgRegInfo ) / sizeof ( rgRegInfo[0] ),
sizeof ( rgRegInfo[0] ),
&RegInfoCmp
);
assert ( lpRegInfo );
_ftcscpy ( rgch, lpRegInfo->szName );
#elif defined(TARGMAC68K)
WORD iReg1 = ( ( (REGPTR) lpsym )->reg ) & 0x00ff;
_ftcscpy ( rgch, RegisterName [ iReg1 ] );
#else
WORD iReg1 = ( ( (REGPTR) lpsym )->reg ) & 0x00ff;
WORD iReg2 = ( ( ( (REGPTR) lpsym )->reg ) >> 8 ) & 0x00ff;
if ( iReg2 ) {
_ftcscpy ( rgch, RegisterName [ iReg2 ] );
_ftcscat ( rgch, ":" );
_ftcscat ( rgch, RegisterName [ iReg1 ] );
}
else {
_ftcscpy ( rgch, RegisterName [ iReg1 ] );
}
#endif
_ftcscat ( rgch, " reg" );
}
break;
case S_CONSTANT: {
HTYPE htype;
lfOEM FAR * ptype;
htype = THGetTypeFromIndex (
SHHMODFrompCXT ( pcxt ),
((CONSTSYM FAR * )lpsym)->typind
);
if ( htype ) {
ptype = MMLock ( htype );
ptype = (lfOEM FAR * )&((( TYPTYPE FAR * )ptype)->leaf);
if ( ptype->cvOEM != OEM_MS_FORTRAN90 ) {
_ftcscpy ( rgch, "constant" );
}
MMUnlock ( htype );
}
break;
}
case S_PUB16:
case S_LDATA16:
case S_GDATA16:
{
ADDR addr = {0};
assert ( pcxt->hMod != 0 );
SetAddrSeg ( &addr, ( (DATAPTR16) lpsym )->seg );
SetAddrOff ( &addr, ( (DATAPTR16) lpsym )->off );
emiAddr ( addr ) = SHHexeFromHmod ( pcxt->hMod );
ADDR_IS_LI ( addr ) = TRUE;
SYFixupAddr ( &addr );
if ( ADDR_IS_LI ( addr ) != TRUE ) {
SPRINTF (
rgch,
"%04X:%04X",
GetAddrSeg ( addr ),
GetAddrOff ( addr )
);
}
}
break;
case S_PUB32:
case S_LDATA32:
case S_GDATA32:
case S_LTHREAD32:
case S_GTHREAD32:
{
ADDR addr = {0};
assert ( pcxt->hMod != 0 );
SetAddrSeg ( &addr, ( (DATAPTR32) lpsym )->seg );
SetAddrOff ( &addr, ( (DATAPTR32) lpsym )->off );
emiAddr ( addr ) = SHHexeFromHmod ( pcxt->hMod );
ADDR_IS_LI ( addr ) = TRUE;
// REVIEW - billjoy - not necessarily ADDRLIN32. How do we tell?
ADDRLIN32 ( addr );
SYFixupAddr ( &addr );
if ( ADDR_IS_LI ( addr ) != TRUE ) {
#if defined(TARGMAC68K)
if(GetAddrSeg(addr) != 0)
SPRINTF (
rgch,
"%04X:%08lX",
GetAddrSeg ( addr ),
GetAddrOff ( addr )
);
else
SPRINTF (
rgch,
"%08lX",
GetAddrOff ( addr )
);
#else
SPRINTF (
rgch,
"%08lX",
GetAddrOff ( addr )
);
#endif
}
}
break;
case S_LPROC16:
case S_GPROC16:
{
ADDR addr = {0};
assert ( pcxt->hMod != 0 );
SetAddrSeg ( &addr, ( (PROCPTR16) lpsym )->seg );
SetAddrOff ( &addr, ( (PROCPTR16) lpsym )->off );
emiAddr ( addr ) = SHHexeFromHmod ( pcxt->hMod );
ADDR_IS_LI ( addr ) = TRUE;
SYFixupAddr ( &addr );
if ( ADDR_IS_LI ( addr ) != TRUE ) {
SPRINTF (
rgch,
"%04X:%04X",
GetAddrSeg ( addr ),
GetAddrOff ( addr )
);
}
}
break;
case S_LPROC32:
case S_GPROC32:
{
ADDR addr = {0};
assert ( pcxt->hMod != 0 );
SetAddrSeg ( &addr, ( (PROCPTR32) lpsym )->seg );
SetAddrOff ( &addr, ( (PROCPTR32) lpsym )->off );
emiAddr ( addr ) = SHHexeFromHmod ( pcxt->hMod );
ADDR_IS_LI ( addr ) = TRUE;
// REVIEW - billjoy - not necessarily ADDRLIN32. How do we tell?
ADDRLIN32 ( addr );
SYFixupAddr ( &addr );
if ( ADDR_IS_LI ( addr ) != TRUE ) {
#if defined(TARGMAC68K)
if(GetAddrSeg(addr) != 0)
SPRINTF (
rgch,
"%04X:%08lX",
GetAddrSeg ( addr ),
GetAddrOff ( addr )
);
else
SPRINTF (
rgch,
"%08lX",
GetAddrOff ( addr )
);
#else
SPRINTF (
rgch,
"%08lX",
GetAddrOff ( addr )
);
#endif
}
}
break;
case S_LPROCMIPS:
case S_GPROCMIPS:
{
ADDR addr = {0};
assert ( pcxt->hMod != 0 );
SetAddrSeg ( &addr, ( (PROCPTRMIPS) lpsym )->seg );
SetAddrOff ( &addr, ( (PROCPTRMIPS) lpsym )->off );
emiAddr ( addr ) = SHHexeFromHmod ( pcxt->hMod );
ADDR_IS_LI ( addr ) = TRUE;
// REVIEW - billjoy - not necessarily ADDRLIN32. How do we tell?
// Do we even care here (MIPS)?
ADDRLIN32 ( addr );
SYFixupAddr ( &addr );
if ( ADDR_IS_LI ( addr ) != TRUE ) {
#if defined(TARGMAC68K)
if(GetAddrSeg(addr) != 0)
SPRINTF (
rgch,
"%04X:%08lX",
GetAddrSeg ( addr ),
GetAddrOff ( addr )
);
else
SPRINTF (
rgch,
"%08lX",
GetAddrOff ( addr )
);
#else
SPRINTF (
rgch,
"%08lX",
GetAddrOff ( addr )
);
#endif
}
}
break;
}
_ftcsncpy ( lsz, rgch, cbMax );
lsz[cbMax-1] = '\0'; // ensure that it's null-terminated
return _ftcslen ( lsz );
}
LPV LOADDS PASCAL SHLpGSNGetTable( HEXE hexe ) {
LPB lpb = (LPB)NULL;
HEXG hexg;
if ( hexe ) {
hexg = ((LPEXS)LLLock( hexe ))->hexg;
assert( hexg );
lpb = ((LPEXG)LLLock( hexg ))->lpgsi;
LLUnlock( hexe );
LLUnlock( hexg );
}
return (LPV)lpb;
}
SHFLAG PASCAL PHExactCmp ( HVOID, HVOID, LSZ, SHFLAG ); // [02]
// [02]
HSYM LOADDS PASCAL SHFindSymInExe ( // [02]
HEXE hexe, // [02]
LPSSTR lpsstr, // [02]
BOOL fCaseSensitive // [02]
) { // [02]
CXT cxt = { 0 }; // [02]
CXT cxtOut = { 0 }; // [02]
HSYM hsym = NULL; // [02]
// [02]
cxt.hMod = 0; // [02]
// [02]
// First search all of the modules in the exe // [02]
// [02]
while ( // [02]
!hsym && // [02]
( cxt.hMod = SHGetNextMod ( hexe, cxt.hMod ) ) != 0 // [02]
) { // [02]
hsym = SHFindNameInContext ( // [02]
NULL, // [02]
&cxt, // [02]
lpsstr, // [02]
fCaseSensitive, // [02]
PHExactCmp, // [02]
FALSE, // [02]
&cxtOut // [02]
); // [02]
} // [02]
// [02]
#pragma message("REVIEW: Should SHFindSymInExe call PHFindNameInPublics???")
#if 0
// This code is very expensive and yet has no effect!!!
// It ignores the HSYM which is returned by PHFindNameInPublics!
//
// I'm not sure which is the best fix -- putting "hsym ="
// in front of the call to PHFindNameInPublics, or disabling
// this code entirely. Since the old way seems to have
// works fine without causing any trouble, I'm going to
// just disable it for now. But this should be revisited.
// The name of this function (SHFindSymInExe) implies
// to the caller that it searches publics as well as other
// symbols. [mikemo]
if ( !hsym ) { // [02]
PHFindNameInPublics ( // [02]
NULL, // [02]
hexe, // [02]
lpsstr, // [02]
fCaseSensitive, // [02]
PHExactCmp // [02]
); // [02]
} // [02]
#endif
// [02]
return hsym; // [02]
} // [02]
// [02]
BOOL LOADDS PASCAL SHFindSymbol ( // [02]
LSZ lsz, // [02]
PADDR lpaddr, // [02]
LPASR lpasr // [02]
) { // [02]
ADDR addr = *lpaddr; // [02]
CXT cxt = {0}; // [02]
CXT cxtOut = {0}; // [02]
SSTR sstr = {0}; // [02]
HSYM hsym = NULL; // [02]
HEXE hexe = hexeNull; // [02]
BOOL fCaseSensitive = TRUE; // [02]
// [02]
// Get a context for the code address that was passed in // [02]
// [02]
SYUnFixupAddr ( &addr ); // [02]
SHSetCxt ( &addr, &cxt ); // [02]
hexe = SHHexeFromHmod ( cxt.hMod ); // [02]
// [02]
// Do an outward context search // [02]
// [02]
sstr.lpName = lsz; // [02]
sstr.cb = _ftcslen ( lsz ); // [02]
// [02]
// Search all of the blocks & procs outward // [02]
// [02]
while ( ( cxt.hBlk || cxt.hProc ) && !hsym ) { // [02]
// [02]
hsym = SHFindNameInContext ( // [02]
NULL, // [02]
&cxt, // [02]
&sstr, // [02]
fCaseSensitive, // [02]
PHExactCmp, // [02]
FALSE, // [02]
&cxtOut // [02]
); // [02]
// [02]
SHGoToParent ( &cxt, &cxt ); // [02]
} // [02]
// [02]
if ( !hsym ) { // [02]
// [02]
hsym = SHFindSymInExe ( hexe, &sstr, fCaseSensitive ); // [02]
// [02]
} // [02]
// [02]
if ( !hsym ) { // [02]
hexe = hexeNull; // [02]
// [02]
while ( !hsym && ( hexe = SHGetNextExe ( hexe ) ) ) { // [02]
// [02]
hsym = SHFindSymInExe ( hexe, &sstr, fCaseSensitive ); // [02]
} // [02]
} // [02]
// [02]
if ( hsym ) { // [02]
// Package up the symbol and send it back // [02]
// [02]
switch ( ( (SYMPTR) hsym )->rectyp ) { // [02]
// [02]
case S_REGISTER: // [02]
lpasr->ast = astRegister; // [02]
lpasr->ireg = ( ( REGPTR ) hsym )->reg; // [02]
break; // [02]
// [02]
case S_BPREL16: // [02]
lpasr->ast = astBaseOff; // [02]
lpasr->off = (LONG) ( (BPRELPTR16) hsym )->off; // [02]
break; // [02]
// [02]
case S_BPREL32: // [02]
lpasr->ast = astBaseOff; // [02]
lpasr->off = ( (BPRELPTR32) hsym )->off; // [02]
break; // [02]
case S_REGREL32:
lpasr->ast = astBaseOff;
lpasr->off = ( (LPREGREL32) hsym )->off;
break;
// [02]
case S_LDATA16: // [02]
case S_LDATA32: // [02]
case S_LTHREAD32:
lpasr->fcd = fcdData; // [02]
// [02]
case S_GPROC16: // [02]
case S_LPROC16: // [02]
// [02]
lpasr->fcd = // [02]
( ( (PROCPTR16) hsym)->flags.CV_PFLAG_FAR ) ?
fcdFar : fcdNear;
goto setaddress; // [02]
// [02]
case S_GPROC32: // [02]
case S_LPROC32: // [02]
// [02]
lpasr->fcd = // [02]
( ( (PROCPTR32) hsym)->flags.CV_PFLAG_FAR ) ?
fcdFar : fcdNear;
goto setaddress; // [02]
case S_GPROCMIPS:
case S_LPROCMIPS:
lpasr->fcd = fcdNear;
goto setaddress;
// [02]
case S_LABEL16: // [02]
case S_THUNK16: // [02]
case S_WITH16: // [02]
case S_PUB16: // [02]
case S_LABEL32: // [02]
case S_THUNK32: // [02]
case S_WITH32: // [02]
// [02]
case S_PUB32: // [02]
// [02]
lpasr->fcd = fcdUnknown; // [02]
// [02]
setaddress: // [02]
// [02]
lpasr->ast = astAddress; // [02]
SHAddrFromHsym ( &lpasr->addr, hsym ); // [02]
emiAddr ( lpasr->addr ) = hexe; // [02]
lpasr->addr.mode.fIsLI = TRUE; // [02]
SYFixupAddr ( &lpasr->addr ); // [02]
break; // [02]
// [02]
default: // [02]
hsym = NULL; // [02]
break; // [02]
} // [02]
} // [02]
// [02]
if ( hsym ) { // [02]
return TRUE; // [02]
} // [02]
else { // [02]
// We didn't find anything so return false // [02]
lpasr->ast = astNone; // [02]
// [02]
return FALSE; // [02]
} // [02]
}
void SetAddrFromMod(LPMDS lpmds, UNALIGNED ADDR* paddr)
{
#if defined(HOST32)//{
if (lpmds->pmod) {
ISECT isect;
OFF off;
BOOL fTmp = ModQuerySecContrib(lpmds->pmod, &isect, &off, NULL, NULL);
assert(fTmp);
SetAddrSeg ( paddr , isect );
SetAddrOff ( paddr , off);
}
else
#endif
{
SetAddrSeg ( paddr , lpmds->lpsgc[0].seg );
SetAddrOff ( paddr , (UOFFSET)lpmds->lpsgc[0].off );
}
}
LPDEBUGDATA LOADDS PASCAL
SHGetDebugData( HEXE hexe )
{
LPDEBUGDATA lpd = NULL;
HEXG hexg;
LPEXG lpexg;
if (hexe) {
hexg = ((LPEXS)LLLock( hexe ))->hexg;
assert( hexg );
lpexg =(LPEXG)LLLock( hexg );
lpd = MHAlloc( sizeof (*lpd) );
assert(lpd);
if (lpd != NULL) {
*lpd = lpexg->debugData;
}
LLUnlock( hexe );
LLUnlock( hexg );
}
return lpd;
}
BOOL LOADDS PASCAL
SHIsThunk( HSYM hsym )
{
SYMPTR psym = (SYMPTR) hsym;
return (psym->rectyp == S_THUNK16 || psym->rectyp == S_THUNK32);
}