Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

811 lines
24 KiB

/*** SHsymlb0.c - general library routines to find an
* omf symbol by name or address.
*
* Copyright <C> 1988, Microsoft Corporation
*
* Purpose: To supply a concise interface to the debug omf for symbols
*
*
*************************************************************************/
#include "shinc.h"
#pragma hdrstop
BOOL SHIsAddrInMod (LPMDS, LPADDR, ISECT* pisect, OFF* poff, CB* pcb);
//**********************************************************************
//**********************************************************************
// the following is local to this module ONLY! It is here to force
// existing behavior. Statics are promised to be zero filled by compiler
char SHszDir[ _MAX_CVDIR ] = {'\0'};
char SHszDrive[ _MAX_CVDRIVE ] = {'\0'};
char SHszDebuggeeDir[ _MAX_CVDIR ] = {'\0'};
char SHszDebuggeeDrive[ _MAX_CVDRIVE ] = {'\0'};
//***********************************************************************
//* *
//* fundamental source line lookup routines *
//* *
//***********************************************************************
/*** SHSetDebugeeDir
*
* Purpose: To get a pointer to the direcotr of the debuggee.
*
* Input: lszDir - A pointer to the debuggee's directory
*
* Output:
* Returns:
*
* Exceptions:
*
* Notes: Must be a zero terminated directory. No trailing \
*
*************************************************************************/
VOID LOADDS PASCAL SHSetDebuggeeDir ( LSZ lszDir ) {
LPCH lpch;
if ( lszDir ) {
lpch = lszDir;
while( *lpch && _istspace(*lpch) )
lpch = _ftcsinc( lpch );
if( *lpch && lpch[1] == ':' ) {
SHszDebuggeeDrive[0] = *lpch;
SHszDebuggeeDrive[1] = ':';
SHszDebuggeeDrive[2] = '\0';
lpch += 2; // point past the :
}
else {
SHszDebuggeeDrive[0] = '\0';
}
// copy the path
_ftcscpy ( SHszDebuggeeDir, lpch );
}
}
/*** SHpSymlplLabLoc
*
* Purpose: To completely fill in a plpl pkt. The hmod and addr must already
* be valid. The locals and labels are searched based on paddr. The
* whole module is search for now. Better decisions may be made in the
* future.
*
*
* Input:
* plpl - lpl packet with a valid module and address in it.
*
* Output:
* plpl - Is updated with Proc, Local, and Label.
*
* Returns .....
*
* Exceptions:
*
* Notes: This includes locals and lables
*
*************************************************************************/
VOID PASCAL SHpSymlplLabLoc ( LPLBS lplbs ) {
SYMPTR lpSym = NULL;
SYMPTR lpSymEnd;
LPMDS lpmds;
ULONG cbMod = 0;
CV_uoff32_t obModelMin = 0;
CV_uoff32_t obModelMax = CV_MAXOFFSET;
CV_uoff32_t obTarget;
CV_uoff32_t doffNew;
CV_uoff32_t doffOld;
// for now we are doing the whole module
lplbs->tagLoc = NULL;
lplbs->tagLab = NULL;
lplbs->tagProc = NULL;
lplbs->tagModelMin = NULL;
lplbs->tagModelMax = NULL;
if( !lplbs->tagMod ) {
return;
}
// because segments of locals don't have to match the segment of the
// searched module, check segment here is wrong. However we can set
// a flag up for proc and labels
lpmds = LLLock (lplbs->tagMod);
obTarget = GetAddrOff (lplbs->addr);
LLUnlock (lplbs->tagMod);
// add/subtract the size of the hash table ptr
lpSym = (SYMPTR) ( (LPB) GetSymbols ( lpmds ) + sizeof( long ) );
cbMod = lpmds->cbSymbols;
lpSymEnd = (SYMPTR) ( (BYTE FAR *) lpSym + cbMod - sizeof ( long ) );
while( lpSym < lpSymEnd ) {
switch( lpSym->rectyp ) {
#if defined (ADDR_16) || defined (ADDR_MIXED)
case S_CEXMODEL16:
if (((WORD)(((CEXMPTR16)lpSym)->seg) == (WORD)GetAddrSeg (lplbs->addr))) {
CV_uoff32_t obTemp = (CV_uoff32_t)(((CEXMPTR16)lpSym)->off);
if (obTemp <= obModelMax) {
if (obTemp > obTarget) {
lplbs->tagModelMax = (CEXMPTR16)lpSym;
obModelMax = obTemp;
}
else if (obTemp >= obModelMin) {
lplbs->tagModelMin = (CEXMPTR16)lpSym;
obModelMin = obTemp;
}
}
}
break;
case S_LPROC16:
case S_GPROC16:
if (((WORD)(((PROCPTR16)lpSym)->seg) == (WORD)GetAddrSeg (lplbs->addr)) &&
((CV_uoff32_t)(((PROCPTR16)lpSym)->off) <= obTarget) &&
(obTarget < ((CV_uoff32_t)(((PROCPTR16)lpSym)->off) + (CV_uoff32_t)(((PROCPTR16)lpSym)->len)))) {
lplbs->tagProc = (SYMPTR)lpSym;
}
break;
case S_LABEL16:
if (((WORD)(((LABELPTR16)lpSym)->seg) == (WORD)GetAddrSeg (lplbs->addr)) &&
(((CV_uoff32_t)((LABELPTR16)lpSym)->off) <= obTarget)) {
doffNew = obTarget - (CV_uoff32_t)(((LABELPTR16)lpSym)->off);
// calculate what the old offset was, this requires no
// use of static variables
if ( lplbs->tagLab ) {
doffOld = obTarget - (CV_uoff32_t)(((LABELPTR16)lplbs->tagLab)->off);
}
else {
doffOld = obTarget;
}
if ( doffNew <= doffOld ) {
lplbs->tagLab = (SYMPTR)lpSym;
}
}
break;
case S_LDATA16:
case S_GDATA16:
if (((WORD)(((DATAPTR16)lpSym)->seg) == (WORD)GetAddrSeg (lplbs->addr)) &&
((CV_uoff32_t)(((DATAPTR16)lpSym)->off) <= obTarget)) {
doffNew = obTarget - (CV_uoff32_t)(((DATAPTR16)lpSym)->off);
// calculate what the old offset was.
if ( lplbs->tagLoc ) {
doffOld = obTarget - (CV_uoff32_t)(((DATAPTR16)lplbs->tagLoc)->off);
}
else {
doffOld = obTarget;
}
if ( doffNew <= doffOld ) {
lplbs->tagLoc = (SYMPTR) lpSym;
}
}
break;
#endif
#if defined (ADDR_32) || defined (ADDR_MIXED) || defined (TARGET32)
case S_CEXMODEL32:
if (((WORD)(((CEXMPTR32)lpSym)->seg) == (WORD)GetAddrSeg (lplbs->addr))) {
CV_uoff32_t obTemp = (CV_uoff32_t)(((CEXMPTR32)lpSym)->off);
if (obTemp <= obModelMax) {
if (obTemp > obTarget) {
lplbs->tagModelMax = (CEXMPTR16)(CEXMPTR32)lpSym;
obModelMax = obTemp;
}
else if (obTemp >= obModelMin) {
lplbs->tagModelMin = (CEXMPTR16)(CEXMPTR32)lpSym;
obModelMin = obTemp;
}
}
}
break;
case S_LPROC32:
case S_GPROC32:
if (((WORD)(((PROCPTR32)lpSym)->seg) == (WORD)GetAddrSeg (lplbs->addr)) &&
((CV_uoff32_t)(((PROCPTR32)lpSym)->off) <= obTarget) &&
(obTarget < ((CV_uoff32_t)(((PROCPTR32)lpSym)->off) + (CV_uoff32_t)(((PROCPTR32)lpSym)->len)))) {
lplbs->tagProc = (SYMPTR)lpSym;
}
break;
case S_LPROCMIPS:
case S_GPROCMIPS:
if (((WORD)(((PROCPTRMIPS)lpSym)->seg) == (WORD)GetAddrSeg (lplbs->addr)) &&
((CV_uoff32_t)(((PROCPTRMIPS)lpSym)->off) <= obTarget) &&
(obTarget < ((CV_uoff32_t)(((PROCPTRMIPS)lpSym)->off) + (CV_uoff32_t)(((PROCPTRMIPS)lpSym)->len)))) {
lplbs->tagProc = (SYMPTR)lpSym;
}
break;
case S_LABEL32:
if (((WORD)(((LABELPTR32)lpSym)->seg) == (WORD)GetAddrSeg (lplbs->addr)) &&
(((CV_uoff32_t)((LABELPTR32)lpSym)->off) <= obTarget)) {
doffNew = obTarget - (CV_uoff32_t)(((LABELPTR32)lpSym)->off);
// calculate what the old offset was, this requires no
// use of static variables
if ( lplbs->tagLab ) {
doffOld = obTarget - (CV_uoff32_t)(((LABELPTR32)lplbs->tagLab)->off);
}
else {
doffOld = obTarget;
}
if ( doffNew <= doffOld ) {
lplbs->tagLab = (SYMPTR)lpSym;
}
}
break;
case S_LDATA32:
case S_GDATA32:
case S_LTHREAD32:
case S_GTHREAD32:
if (((WORD)(((DATAPTR32)lpSym)->seg) == (WORD)GetAddrSeg (lplbs->addr)) &&
((CV_uoff32_t)(((DATAPTR32)lpSym)->off) <= obTarget)) {
doffNew = obTarget - (CV_uoff32_t)(((DATAPTR32)lpSym)->off);
// calculate what the old offset was.
if ( lplbs->tagLoc ) {
doffOld = obTarget - (CV_uoff32_t)(((DATAPTR32)lplbs->tagLoc)->off);
}
else {
doffOld = obTarget;
}
if ( doffNew <= doffOld ) {
lplbs->tagLoc = (SYMPTR) lpSym;
}
}
break;
#endif
}
lpSym = NEXTSYM ( SYMPTR, lpSym );
}
// now convert to emstags
if ( lplbs->tagLoc ) {
lplbs->tagLoc = (SYMPTR) lplbs->tagLoc;
}
if ( lplbs->tagLab ) {
lplbs->tagLab = (SYMPTR) lplbs->tagLab;
}
if ( lplbs->tagProc) {
lplbs->tagProc = (SYMPTR) lplbs->tagProc;
}
if ( lplbs->tagModelMin) {
lplbs->tagModelMin = (CEXMPTR16) lplbs->tagModelMin;
}
if ( lplbs->tagModelMax) {
lplbs->tagModelMax = (CEXMPTR16) lplbs->tagModelMax;
}
}
/*** SHdNearestSymbol
*
* 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:
* ptxt - a pointer to the context, address and mdi must
* be filled in.
*
* sop - Determine what type of symbols to look for
*
* Output:
*
* Exceptions:
*
* Notes: If CV_MAXOFFSET is returned in the lpodr, there is no closest
* symbol Also all symbols in the module are searched so only the
* cxt.addr and cxt.mdi have meaning.
*
*************************************************************************/
VOID PASCAL SHdNearestSymbol ( PCXT pcxt, SOP sop, LPODR lpodr ) {
HSYM hSym;
SYMPTR pSym;
LBS lbs;
ULONG doff = CV_MAXOFFSET;
ULONG doffNew = CV_MAXOFFSET;
LPCH lpch = lpodr->lszName;
lpodr->fst = fstNone;
lpodr->fcd = fcdUnknown;
lpodr->fpt = fptUnknown;
lpodr->cbProlog = 0;
lpodr->dwDeltaOff = 0;
*lpch = '\0';
if ( SHHMODFrompCXT ( pcxt ) ) {
BOOL bAddrInProc = FALSE;
// 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 = SHHMODFrompCXT ( pcxt );
lbs.addr = *SHpADDRFrompCXT ( pcxt );
SHpSymlplLabLoc ( &lbs );
// check for closest data local, if requested
if ( ( sop & sopData ) && lbs.tagLoc ) {
pSym = (SYMPTR) lbs.tagLoc;
switch (pSym->rectyp) {
#if defined (ADDR_16) || defined (ADDR_MIXED)
case S_LDATA16:
case S_GDATA16:
doff = GetAddrOff ( lbs.addr ) -
(CV_uoff32_t)(((DATAPTR16)pSym)->off);
STRNCPY (lpch, (char FAR *)&((DATAPTR16)pSym)->name[1],
(BYTE)(*((DATAPTR16)pSym)->name));
lpch[(BYTE)(*((DATAPTR16)pSym)->name)] = '\0';
break;
#endif
#if defined (ADDR_32) || defined (ADDR_MIXED) || defined (TARGET32)
case S_LDATA32:
case S_GDATA32:
case S_LTHREAD32:
case S_GTHREAD32:
doff = GetAddrOff ( lbs.addr ) -
(CV_uoff32_t)(((DATAPTR32)pSym)->off);
_ftcsncpy (lpch, (char FAR *)&((DATAPTR32)pSym)->name[1],
(BYTE)(*((DATAPTR32)pSym)->name));
lpch[(BYTE)(*((DATAPTR32)pSym)->name)] = '\0';
break;
#endif
}
}
// check for closest label
if ( !(sop & sopFcn ) && lbs.tagLab ) {
pSym = (SYMPTR) lbs.tagLab;
switch (pSym->rectyp) {
#if defined (ADDR_16) || defined (ADDR_MIXED)
case S_LABEL16:
doff = GetAddrOff ( lbs.addr ) -
(CV_uoff32_t)(((LABELPTR16)pSym)->off) ;
_ftcsncpy (lpch, (char FAR *)&((LABELPTR16)pSym)->name[1],
(BYTE)(*((LABELPTR16)pSym)->name));
lpch[(BYTE)(*((LABELPTR16)pSym)->name)] = '\0';
break;
#endif
#if defined (ADDR_32) || defined (ADDR_MIXED) || defined (TARGET32)
case S_LABEL32:
doff = GetAddrOff ( lbs.addr ) -
(CV_uoff32_t)(((LABELPTR32)pSym)->off) ;
_ftcsncpy (lpch, (char FAR *)&((LABELPTR32)pSym)->name[1],
(BYTE)(*((LABELPTR32)pSym)->name));
lpch[(BYTE)(*((LABELPTR32)pSym)->name)] = '\0';
break;
#endif
}
}
// if the proc name is closer
if ( lbs.tagProc ) {
pSym = (SYMPTR) lbs.tagProc;
switch (pSym->rectyp) {
#if defined (ADDR_16) || defined (ADDR_MIXED)
case S_LPROC16:
case S_GPROC16:
doffNew = GetAddrOff ( lbs.addr ) -
(CV_uoff32_t)(((PROCPTR16)pSym)->off);
if (doffNew <= doff) {
doff = doffNew;
_ftcsncpy (lpch, (char FAR *)&((PROCPTR16)pSym)->name[1],
(BYTE)(*((PROCPTR16)pSym)->name));
lpch[(BYTE)(*((PROCPTR16)pSym)->name)] = '\0';
lpodr->cbProlog = ((PROCPTR16)pSym)->DbgStart - 1;
lpodr->fcd = (((PROCPTR16)pSym)->flags.CV_PFLAG_FAR ) ? fcdFar : fcdNear;
lpodr->fst = fstSymbol;
if ( doff < (CV_uoff32_t)((PROCPTR16)pSym)->len ) {
bAddrInProc = TRUE;
}
}
break;
#endif
#if defined (ADDR_32) || defined (ADDR_MIXED) || defined (TARGET32)
case S_LPROC32:
case S_GPROC32:
doffNew = GetAddrOff ( lbs.addr ) -
(CV_uoff32_t)(((PROCPTR32)pSym)->off);
if (doffNew <= doff) {
doff = doffNew;
_ftcsncpy (lpch, (char FAR *)&((PROCPTR32)pSym)->name[1],
(BYTE)(*((PROCPTR32)pSym)->name));
lpch[(BYTE)(*((PROCPTR32)pSym)->name)] = '\0';
// cbProlog is a WORD, so until we change that, we'll
// have to make sure the prolog is <64K (a safe bet)
assert ( ((PROCPTR32)pSym)->DbgStart <= 65535 );
lpodr->cbProlog = (WORD)(((PROCPTR32)pSym)->DbgStart);
lpodr->fcd = (((PROCPTR32)pSym)->flags.CV_PFLAG_FAR ) ? fcdFar : fcdNear;
lpodr->fst = fstSymbol;
if (((PROCPTR32)pSym)->flags.CV_PFLAG_NOFPO ) {
lpodr->fpt = fptPresent;
}
if ( doff < (CV_uoff32_t)((PROCPTR32)pSym)->len ) {
bAddrInProc = TRUE;
}
}
break;
case S_LPROCMIPS:
case S_GPROCMIPS:
doffNew = GetAddrOff ( lbs.addr ) -
(CV_uoff32_t)(((PROCPTRMIPS)pSym)->off);
if (doffNew <= doff) {
doff = doffNew;
_ftcsncpy (lpch, (char FAR *)&((PROCPTRMIPS)pSym)->name[1],
(BYTE)(*((PROCPTRMIPS)pSym)->name));
lpch[(BYTE)(*((PROCPTRMIPS)pSym)->name)] = '\0';
// cbProlog is a WORD, so until we change that, we'll
// have to make sure the prolog is <64K (a safe bet)
if ( ((PROCPTRMIPS)pSym)->DbgStart == 0 ) {
lpodr->cbProlog = 0;
}
else {
// TEMPORARY HACK !!!!!!! - sanjays
assert ( ((PROCPTRMIPS)pSym)->DbgStart - 1 <= 65535 );
lpodr->cbProlog = (WORD)(((PROCPTRMIPS)pSym)->DbgStart - 1);
}
lpodr->fcd = fcdNear;
lpodr->fst = fstSymbol;
if ( doff < (CV_uoff32_t)((PROCPTRMIPS)pSym)->len ) {
bAddrInProc = TRUE;
}
}
break;
#endif
}
}
if ( !doff ) {
lpodr->dwDeltaOff = 0; // Exact Match
return;
}
// Avoid searching the publics if the address we were searching for
// is in the range of the proc we found.
if ( bAddrInProc && !(sop & sopData))
{
lpodr->dwDeltaOff = doff;
return;
}
}
// now check the publics
doffNew = PHGetNearestHsym (
SHpADDRFrompCXT ( pcxt ),
SHpADDRFrompCXT ( pcxt )->emi,
&hSym
);
if ( doffNew < doff ) {
doff = doffNew;
pSym = (SYMPTR) hSym;
switch (pSym->rectyp) {
#if defined (ADDR_16) || defined (ADDR_MIXED)
case S_GDATA16:
case S_PUB16:
_ftcsncpy (lpch, (char FAR *)&((DATAPTR16)pSym)->name[1],
(BYTE)(*((DATAPTR16)pSym)->name));
lpch[(BYTE)(*((DATAPTR16)pSym)->name)] = '\0';
lpodr->fst = fstPublic;
break;
#endif
#if defined (ADDR_32) || defined (ADDR_MIXED) || defined (TARGET32)
case S_GDATA32:
case S_PUB32:
_ftcsncpy (lpch, (char FAR *)&((DATAPTR32)pSym)->name[1],
(BYTE)(*((DATAPTR32)pSym)->name));
lpch[(BYTE)(*((DATAPTR32)pSym)->name)] = '\0';
lpodr->fst = fstPublic;
break;
#endif
}
}
lpodr->dwDeltaOff = doff;
return;
}
//
//
//
// the next few functions are provided to osdebug via callbacks and
// should not be called within the CV kernel
//
//
//
//
/*** SHModelFromCXT
*
* Purpose: To fill the supplied buffer with the relevant Change
* Execution Model record from the symbols section.
*
* Input: pcxt - a pointer to the context, address
* and mdi must be filled in.
*
* Output:
* pch - The Change Execution Model record is copied here.
* Returns .....
* True if there is symbol information for the module.
*
* Exceptions:
*
* Notes: If there is no symbol information for the module, the supplied
* buffer is not changed and the function returns FALSE.
*
*************************************************************************/
int PASCAL SHModelFromCXT (
PCXT pcxt,
LPW lpwModel,
SYMPTR FAR * lppMODEL,
CV_uoff32_t *pobMax
) {
static CEXMPTR16 tagOld;
static CV_uoff32_t obMax;
static CV_uoff32_t obMin;
static HEMI emiOld = 0;
static WORD segOld = 0;
LBS lbs;
ADDR addrT;
LPMDS lpmds;
HMOD hmod;
CB cbSecContrib;
BOOL fTmp;
// if physical, unfix it up
if ( !ADDR_IS_LI ( *SHpADDRFrompCXT ( pcxt ) ) ) {
SYUnFixupAddr ( SHpADDRFrompCXT ( pcxt ) );
}
if ( segOld != (WORD) GetAddrSeg ( *SHpADDRFrompCXT(pcxt) ) ||
( emiOld != emiAddr ( *SHpADDRFrompCXT(pcxt) ) ) ||
( GetAddrOff ( *SHpADDRFrompCXT(pcxt) ) >= obMax ) ||
( GetAddrOff ( *SHpADDRFrompCXT(pcxt) ) < obMin ) ) {
if ( !SHHMODFrompCXT ( pcxt ) ) {
addrT = *SHpADDRFrompCXT ( pcxt );
MEMSET ( pcxt, 0, sizeof ( CXT ) );
if ( !SHSetCxtMod ( &addrT, pcxt ) ) {
return FALSE;
}
}
hmod = (HMOD)SHHGRPFrompCXT( pcxt );
lpmds = LLLock ( hmod );
emiOld = emiAddr ( *SHpADDRFrompCXT(pcxt) );
fTmp = SHIsAddrInMod (lpmds, &pcxt->addr, &segOld, &obMin, &cbSecContrib);
obMax = obMin + cbSecContrib + 1;
LLUnlock( hmod );
tagOld = NULL;
// 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 Relevant change model records
if ( GetSymbols ((LPMDS)LLLock (lbs.tagMod = SHHMODFrompCXT (pcxt))) ) {
lbs.addr = *SHpADDRFrompCXT(pcxt);
SHpSymlplLabLoc ( &lbs );
if (tagOld = lbs.tagModelMin ) {
// emsT = (SYMPTR) tagOld;
// obMin = ((CEXMPTR16)emsT)->off;
#if defined(TARGMAC68K) || defined(TARGMACPPC)
if(((SYMPTR)(lbs.tagModelMin))->rectyp == S_CEXMODEL32)
obMin = ((CEXMPTR32)(lbs.tagModelMin))->off;
else
#endif
obMin = (lbs.tagModelMin)->off;
}
if (lbs.tagModelMax) {
// emsT = (SYMPTR) lbs.tagModelMax;
// obMax = ((CEXMPTR16)emsT)->off;
#if defined(TARGMAC68K) || defined(TARGMACPPC)
if(((SYMPTR)(lbs.tagModelMax))->rectyp == S_CEXMODEL32)
obMax = ((CEXMPTR32)(lbs.tagModelMax))->off;
else
#endif
obMax = (lbs.tagModelMax)->off;
}
}
LLUnlock( lbs.tagMod );
}
if( tagOld != NULL ) {
// pass on ptr to the SYM
*lppMODEL = (SYMPTR) tagOld;
#if defined(TARGMAC68K) || defined(TARGMACPPC)
if(((SYMPTR)(tagOld))->rectyp == S_CEXMODEL32)
*lpwModel = ( (CEXMPTR32) *lppMODEL ) -> model;
else
#endif
*lpwModel = ( (CEXMPTR16) *lppMODEL ) -> model;
if ( *lpwModel != CEXM_MDL_cobol
&& *lpwModel != CEXM_MDL_pcode32Mac
&& *lpwModel != CEXM_MDL_pcode32MacNep
) {
*lpwModel &= 0xfff0;
}
}
else {
// no model record, must be native
*lppMODEL = NULL;
*lpwModel = CEXM_MDL_native;
}
*pobMax = obMax;
return TRUE;
}
/*** SHModelFromAddr
*
* Purpose: To fill the supplied buffer with the relevant Change
* Execution Model record from the symbols section.
*
* Input: pcxt - a pointer to an addr,
*
* Output:
* pch - The Change Execution Model record is copied here.
* Returns .....
* True if there is symbol information for the module.
*
* Exceptions:
*
* Notes: If there is no symbol information for the module, the supplied
* buffer is not changed and the function returns FALSE.
*
*************************************************************************/
int PASCAL LOADDS SHModelFromAddr (
LPADDR paddr,
LPW lpwModel,
LPB lpbModel,
CV_uoff32_t FAR *pobMax
) {
static CEXMPTR16 tagOld;
static CV_uoff32_t obMax = 0;
static CV_uoff32_t obMin = 0;
static HEMI emiOld = 0;
static WORD segOld = 0;
SYMPTR FAR *lppModel = (SYMPTR FAR *) lpbModel;
LBS lbs;
ADDR addr;
LPMDS lpmds;
HMOD hmod;
CXT cxt = {0};
CB cbSecContrib;
BOOL fTmp;
// if physical, unfix it up
if ( !ADDR_IS_LI (*paddr) ) SYUnFixupAddr ( paddr );
cxt.addr = *paddr;
cxt.hMod = 0;
if ( segOld != (WORD) GetAddrSeg ( *SHpADDRFrompCXT(&cxt) ) ||
( emiOld != emiAddr ( *SHpADDRFrompCXT(&cxt) ) ) ||
( GetAddrOff ( *SHpADDRFrompCXT(&cxt) ) >= obMax ) ||
( GetAddrOff ( *SHpADDRFrompCXT(&cxt) ) < obMin ) ) {
if ( !SHHMODFrompCXT ( &cxt ) ) {
addr = *SHpADDRFrompCXT ( &cxt );
MEMSET ( &cxt, 0, sizeof ( CXT ) );
if ( !SHSetCxtMod ( &addr, &cxt ) ) {
return FALSE;
}
}
hmod = (HMOD)SHHGRPFrompCXT( &cxt );
lpmds = LLLock ( hmod );
emiOld = emiAddr ( *SHpADDRFrompCXT(&cxt) );
fTmp = SHIsAddrInMod ( lpmds, &cxt.addr, &segOld, &obMin, &cbSecContrib);
assert(fTmp);
obMax = obMin + cbSecContrib + 1;
LLUnlock( hmod );
tagOld = NULL;
// 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 Relevant change model records
if ( GetSymbols ((LPMDS) LLLock (lbs.tagMod = SHHMODFrompCXT (&cxt))) ) {
lbs.addr = *SHpADDRFrompCXT(&cxt);
SHpSymlplLabLoc ( &lbs );
if (tagOld = lbs.tagModelMin ) {
// emsT = (SYMPTR) tagOld;
// obMin = ((CEXMPTR16)emsT)->off;
#if defined(TARGMAC68K) || defined(TARGMACPPC)
if(((SYMPTR)(lbs.tagModelMin))->rectyp == S_CEXMODEL32)
obMin = ((CEXMPTR32)(lbs.tagModelMin))->off;
else
#endif
obMin = (lbs.tagModelMin)->off;
}
if (lbs.tagModelMax) {
// emsT = (SYMPTR) lbs.tagModelMax;
// obMax = ((CEXMPTR16)emsT)->off;
#if defined(TARGMAC68K) || defined(TARGMACPPC)
if(((SYMPTR)(lbs.tagModelMax))->rectyp == S_CEXMODEL32)
obMax = ((CEXMPTR32)(lbs.tagModelMax))->off;
else
#endif
obMax = (lbs.tagModelMax)->off;
}
}
LLUnlock( lbs.tagMod );
}
if( tagOld != NULL ) {
// pass on ptr to the SYM
*lppModel = (SYMPTR) tagOld;
#if defined(TARGMAC68K) || defined(TARGMACPPC)
if(((SYMPTR)tagOld)->rectyp == S_CEXMODEL32)
*lpwModel = ( (CEXMPTR32) *lppModel ) -> model;
else
#endif
*lpwModel = ( (CEXMPTR16) *lppModel ) -> model;
if ( *lpwModel != CEXM_MDL_cobol
&& *lpwModel != CEXM_MDL_pcode32Mac
&& *lpwModel != CEXM_MDL_pcode32MacNep
) {
*lpwModel &= 0xfff0;
}
}
else {
// no model record, must be native
*lppModel = NULL;
*lpwModel = CEXM_MDL_native;
}
*pobMax = obMax;
return TRUE;
}