mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3770 lines
110 KiB
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 (
|
|
®Info,
|
|
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 (
|
|
®Info,
|
|
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);
|
|
}
|