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.
 
 
 
 
 
 

2049 lines
62 KiB

/*** debsup.c - debapi support routines.
*
* The routines in this module can only be called from debapi.c.
*/
LOCAL EESTATUS CountClassElem (peval_t, long *, uint);
LOCAL ushort SetClassiName (peval_t, long, PEEHSTR, PEEHSTR, uint, ushort, uint);
LOCAL ushort SetFcniParm (peval_t, long, PEEHSTR);
static char *pExStrP;
/** AreTypesEqual - are TM types equal
*
* flag = AreTypesEqual (hTMLeft, hTMRight);
*
* Entry hTMLeft = handle of left TM
* hTMRight = handle of right TM
*
* Exit none
*
* Returns TRUE if TMs have identical types
*/
bool_t AreTypesEqual (HTM hTMLeft, HTM hTMRight)
{
bool_t retval = FALSE;
pexstate_t pExLeft;
pexstate_t pExRight;
if ((hTMLeft != 0) && (hTMRight != 0)) {
pExLeft = MHMemLock (hTMLeft);
pExRight = MHMemLock (hTMRight);
if (EVAL_TYP(&pExLeft->result) == EVAL_TYP (&pExRight->result)) {
retval = TRUE;
}
MHMemUnLock (hTMLeft);
MHMemUnLock (hTMRight);
}
return (retval);
}
/** GetHtypeFromTM - Get the HTYPE of a TM result
*
* hType = GetHtypeFromTM(hTM);
*
* Entry hTM = handle of TM
*
* Exit none
*
* Returns the HTYPE of the result or 0
*/
HTYPE
GetHtypeFromTM(
HTM hTM
)
{
HTYPE retval = 0;
pexstate_t pEx;
if ( hTM != 0 ) {
pEx = MHMemLock (hTM);
retval = THGetTypeFromIndex (EVAL_MOD (&pEx->result),
EVAL_TYP (&pEx->result));
MHMemUnLock (hTM);
}
return (retval);
}
/** cChildrenTM - return number of children for the TM
*
* flag = cChildrenTM (phTM, pcChildren, pVar)
*
* Entry phTM = pointer to handle of TM
* pcChildren = pointer to location to store count
*
* Exit *pcChildren = number of children for TM
*
* Returns EENOERROR if no error
* non-zero if error
*/
EESTATUS cChildrenTM (PHTM phTM, long *pcChildren, PSHFLAG pVar)
{
EESTATUS retval = EENOERROR;
eval_t eval;
peval_t pv = &eval;
long len;
Unreferenced( pVar );
DASSERT (*phTM != 0);
*pcChildren = 0;
if (*phTM == 0) {
return (EECATASTROPHIC);
}
DASSERT(pExState == NULL );
pExState = MHMemLock (*phTM);
if (pExState->state.bind_ok == TRUE) {
eval = pExState->result;
#if !defined (C_ONLY)
if (EVAL_IS_REF (pv)) {
RemoveIndir (pv);
}
#endif
pExState->err_num = 0;
if (!CV_IS_PRIMITIVE (EVAL_TYP (pv))) {
if (EVAL_IS_CLASS (pv)) {
retval = CountClassElem (pv, pcChildren,
(EVAL_STATE (pv) == EV_type)? CLS_defn: CLS_data);
}
else if (EVAL_IS_ARRAY (pv) && (PTR_ARRAYLEN (pv) != 0)) {
// if an array is undimensioned in the source then we
// do not guess how many elements it really has.
// Otherwise, the number of elements is the sizeof the
// array divided by the size of the underlying type
len = PTR_ARRAYLEN (pv);
SetNodeType (pv, PTR_UTYPE (pv));
*pcChildren = len / TypeSize (pv);
}
else if (EVAL_IS_PTR (pv)) {
SetNodeType (pv, PTR_UTYPE (pv));
if (EVAL_IS_VTSHAPE (pv)) {
*pcChildren = VTSHAPE_COUNT (pv);
}
else {
*pcChildren = 1;
}
}
else {
pExState->err_num = ERR_INTERNAL;
retval = EEGENERAL;
}
}
}
else {
pExState->err_num = ERR_NOTEVALUATABLE;
retval = EEGENERAL;
}
MHMemUnLock (*phTM);
pExState = NULL;
return (retval);
}
/** cParamTM - return count of parameters for TM
*
* ushort cParamTM (phTM, pcParam, pVarArg)
*
* Entry hTM = handle to TM
* pcParam = pointer return count
* pVarArg = pointer to vararg flags
*
* Exit *pcParam = count of number of parameters
* *pVarArgs = TRUE if function has varargs
*
* Returns EECATASTROPHIC if fatal error
* EENOERROR if no error
*/
ushort cParamTM (HTM hTM, ushort *pcParam, PSHFLAG pVarArg)
{
peval_t pv;
ushort retval = EECATASTROPHIC;
DASSERT (hTM != 0);
if (hTM != 0) {
DASSERT (pExState == NULL);
pExState = MHMemLock (hTM);
if (pExState->state.bind_ok == TRUE) {
pv = &pExState->result;
if (EVAL_IS_FCN (pv)) {
if ((*pVarArg = FCN_VARARGS (pv)) == TRUE) {
if ((*pcParam = FCN_PCOUNT (pv)) > 0) {
(*pcParam)--;
}
} else {
*pcParam = FCN_PCOUNT (pv);
}
retval = EENOERROR;
}
else if (EVAL_IS_LABEL (pv)) {
*pcParam = 0;
retval = EENOERROR;
}
else {
pExState->err_num = ERR_NOTFCN;
retval = EEGENERAL;
}
} else {
pExState->err_num = ERR_NOTEVALUATABLE;
retval = EEGENERAL;
}
MHMemUnLock (hTM);
pExState = NULL;
}
return (retval);
}
/** DupTM - duplicate TM
*
* flag = DupTM (phTMIn, phTMOut)
*
* Entry phTMIn = pointer to handle for input TM
* phTMOut = pointer to handle for output TM
*
* Exit TM and buffers duplicated
*
* Returns EENOERROR if TM duplicated
* EENOMEMORY if unable to allocate memory
*/
ushort DupTM (PHTM phTMIn, PHTM phTMOut)
{
ushort retval = EENOMEMORY;
pexstate_t pExOut;
char *pStr;
char *pcName;
uint len;
DASSERT (pExState == NULL);
pExState = MHMemLock (*phTMIn);
pExStr = MHMemLock (pExState->hExStr);
pTree = MHMemLock (pExState->hSTree);
if ((*phTMOut = MHMemAllocate (sizeof (exstate_t))) != 0) {
pExOut = MHMemLock (*phTMOut);
memset (pExOut, 0, sizeof (exstate_t));
pExOut->ambiguous = pExState->ambiguous;
pExOut->state.parse_ok = TRUE;
// copy expression string
if ((pExOut->hExStr = MHMemAllocate (pExOut->ExLen = pExState->ExLen)) == 0) {
goto failure;
}
pStr = MHMemLock (pExOut->hExStr);
memcpy (pStr, pExStr, pExOut->ExLen);
MHMemUnLock (pExOut->hExStr);
// copy syntax tree
if ((pExOut->hSTree = MHMemAllocate (pTree->size)) == 0) {
goto failure;
}
pStr = MHMemLock (pExOut->hSTree);
memcpy (pStr, pTree, pTree->size);
MHMemUnLock (pExOut->hSTree);
// copy name string
if (pExState->hCName != 0) {
pcName = MHMemLock (pExState->hCName);
len = strlen (pcName) + 1;
if ((pExOut->hCName = MHMemAllocate (len)) == 0) {
MHMemUnLock (pExState->hCName);
goto failure;
}
pStr = MHMemLock (pExOut->hCName);
memcpy (pStr, pcName, len);
MHMemUnLock (pExOut->hCName);
MHMemUnLock (pExState->hCName);
}
MHMemUnLock (*phTMOut);
retval = EENOERROR;
}
succeed:
MHMemUnLock (pExState->hExStr);
MHMemUnLock (pExState->hSTree);
MHMemUnLock (*phTMIn);
pExState = NULL;
return (retval);
failure:
if (pExOut->hExStr != 0) {
MHMemFree (pExOut->hExStr);
}
if (pExOut->hSTree != 0) {
MHMemFree (pExOut->hSTree);
}
if (pExOut->hCName != 0) {
MHMemFree (pExOut->hCName);
}
MHMemUnLock (*phTMOut);
MHMemFree (*phTMOut);
*phTMOut = 0;
goto succeed;
}
/** GetChildTM - get TM representing ith child of a TM
*
* flag = GetChildTM (iChild)
*
* Entry iChild = child to get TM for
* pExStateP = address of locked parent expression state
* pExState = address of locked expression state
*
* Exit pExState initialized for child
*
* Returns TRUE if no error
* FALSE if error
*/
EESTATUS GetChildTM (HTM hTM, ulong iChild, PEEHSTR phDStr, PEEHSTR phName, uint radix)
{
eval_t evalP;
peval_t pvP;
EESTATUS retval = EENOERROR;
char tempbuf[16];
ushort len;
ushort plen;
uint excess;
char *pDStr;
char *pName;
char *fmtstr;
DASSERT (hTM != 0);
if (hTM == 0) {
return (EECATASTROPHIC);
}
DASSERT(pExState == NULL);
pExState = MHMemLock (hTM);
if (pExState->state.bind_ok != TRUE) {
pExState->err_num = ERR_NOTEVALUATABLE;
MHMemUnLock (hTM);
pExState = NULL;
return (EEGENERAL);
}
pExStrP = MHMemLock (pExState->hExStr);
pCxt = &pExState->cxt;
DASSERT (pExState->strIndex <= pExState->ExLen);
plen = pExState->strIndex;
excess = pExState->ExLen - plen;
pvP = &evalP;
*pvP = pExState->result;
#if !defined (C_ONLY)
if (EVAL_IS_REF (pvP)) {
RemoveIndir (pvP);
}
#endif
GettingChild = TRUE;
if (EVAL_IS_ARRAY (pvP)) {
// fake up name as [i] ultoa not used here because 0 converts
// as null string
switch (radix) {
case 8:
fmtstr = "[%o]";
break;
case 16:
fmtstr = "[%x]";
break;
default:
case 10:
fmtstr = "[%ld]";
break;
}
len = sprintf (tempbuf, fmtstr, iChild);
if (((*phName = MHMemAllocate (len + 1)) == 0) ||
((*phDStr = MHMemAllocate (plen + excess + len + 1)) == 0)) {
goto nomemory;
}
pName = MHMemLock (*phName);
pDStr = MHMemLock (*phDStr);
strcpy (pName, tempbuf);
memcpy (pDStr, pExStrP, plen);
memcpy (pDStr + plen, pName, len);
*(pDStr + plen + len) = 0;
MHMemUnLock (*phDStr);
MHMemUnLock (*phName);
}
else if (EVAL_IS_PTR (pvP)) {
SetNodeType (pvP, PTR_UTYPE (pvP));
if (!EVAL_IS_VTSHAPE (pvP)) {
// set name to null
if (((*phName = MHMemAllocate (1)) == 0) ||
((*phDStr = MHMemAllocate (plen + 3)) == 0)) {
goto nomemory;
}
pName = MHMemLock (*phName);
pDStr = MHMemLock (*phDStr);
*pName = 0;
*pDStr++ = '(';
memcpy (pDStr, pExStrP, plen);
pDStr += plen;
*pDStr++ = ')';
memcpy (pDStr, pExStrP + plen, excess);
pDStr += excess;
*pDStr = 0;
MHMemUnLock (*phDStr);
MHMemUnLock (*phName);
}
else {
// fake up name as [i] ultoa not used here because 0 converts
// as null string
switch (radix) {
case 8:
fmtstr = "[%o]";
break;
case 16:
fmtstr = "[%x]";
break;
default:
case 10:
fmtstr = "[%ld]";
break;
}
len = sprintf (tempbuf, fmtstr, iChild);
if (((*phName = MHMemAllocate (len + 1)) == 0) ||
((*phDStr = MHMemAllocate (plen + len + 1)) == 0)) {
goto nomemory;
}
pName = MHMemLock (*phName);
pDStr = MHMemLock (*phDStr);
strcpy (pName, tempbuf);
memcpy (pDStr, pExStrP, plen);
memcpy (pDStr + plen, pName, len);
memcpy (pDStr + plen + len, pExStrP + plen, excess);
*(pDStr + plen + len + excess) = 0;
MHMemUnLock (*phDStr);
MHMemUnLock (*phName);
}
}
else if (EVAL_IS_CLASS (pvP)) {
// the type of the parent node is a class. We need to search for
// the data members if an object is pointed to or the entire definition
// if the class type is pointed to
if ((pExState->err_num = SetClassiName (pvP, iChild, phDStr, phName,
((EVAL_STATE (pvP) == EV_type)? CLS_defn: CLS_data), plen, excess)) != ERR_NONE) {
goto general;
}
}
else if (EVAL_IS_FCN (pvP)) {
// the type of the parent node is a function. We walk down the
// formal argument list and return a TM that references the ith
// actual argument. We return an error if the ith actual is a vararg.
if ((retval = SetFcniParm (pvP, iChild, phName)) == EENOERROR) {
pName = MHMemLock (*phName);
if ((*phDStr = MHMemAllocate ((len = strlen (pName)) + 1)) == 0) {
MHMemUnLock (*phName);
goto nomemory;
}
pDStr = MHMemLock (*phDStr);
memcpy (pDStr, pName, len);
*(pDStr + len) = 0;
MHMemUnLock (*phDStr);
MHMemUnLock (*phName);
}
}
else if (EVAL_IS_LABEL (pvP)) {
// CV should never ask for the children of a label
DASSERT (FALSE);
pExState->err_num = ERR_INTERNAL;
goto general;
}
MHMemUnLock (pExState->hExStr);
pExState = NULL;
MHMemUnLock (hTM);
GettingChild = FALSE;
return (retval);
nomemory:
pExState->err_num = ERR_NOMEMORY;
general:
MHMemUnLock (pExState->hExStr);
pExState = NULL;
MHMemUnLock (hTM);
GettingChild = FALSE;
return (EEGENERAL);
}
/** GetSymName - get name of symbol from node
*
* fSuccess = GetSymName (buf, buflen)
*
* Entry buf = pointer to buffer for name
* buflen = length of buffer
*
* Exit *buf = symbol name
*
* Returns TRUE if no error retreiving name
* FALSE if error
*
* Note if pExState->hChildName is not zero, then the name in in
* the buffer pointed to by hChildName
*/
EESTATUS GetSymName (PHTM phTM, PEEHSTR phszName)
{
SYMPTR pSym;
short len = 0;
UOFFSET offset = 0;
char *pExStr;
peval_t pv;
short retval = EECATASTROPHIC;
short buflen = TYPESTRMAX - 1;
char *buf;
HSYM hProc = 0;
ADDR addr;
// M00SYMBOL - we now need to allow for a symbol name to be imbedded
// M00SYMBOL - in a type. Particularly for scoped types and enums.
DASSERT (*phTM != 0);
if ((*phTM != 0) && ((*phszName = MHMemAllocate (TYPESTRMAX)) != 0)) {
retval = EEGENERAL;
buf = MHMemLock (*phszName);
memset (buf, 0, TYPESTRMAX);
DASSERT(pExState == NULL);
pExState = MHMemLock (*phTM);
if (pExState->state.bind_ok == TRUE) {
pv = &pExState->result;
if ((pExState->state.childtm == TRUE) && (pExState->state.noname == TRUE)) {
// if there is no name
MHMemUnLock (*phTM);
pExState = NULL;
MHMemUnLock (*phszName);
return (EENOERROR);
}
else if (pExState->hCName != 0) {
// M00SYMBOL - for scoped types and symbols, we may be able to
// M00SYMBOL - hCName to hold the imbedded symbol name
pExStr = MHMemLock (pExState->hCName);
len = (int)strlen (pExStr);
len = min (len, buflen);
strncpy (buf, pExStr, len);
MHMemUnLock (pExState->hCName);
retval = EENOERROR;
}
else if (EVAL_HSYM (pv) == 0) {
if ((EVAL_IS_PTR (pv) == TRUE) && (EVAL_STATE (pv) == EV_rvalue)) {
addr = EVAL_PTR (pv);
}
else {
addr = EVAL_SYM (pv);
}
if (!ADDR_IS_LI (addr)) {
SHUnFixupAddr (&addr);
}
if (SHGetNearestHsym (&addr, EVAL_MOD (pv), EECODE, &hProc) == 0) {
EVAL_HSYM (pv) = hProc;
}
}
else {
// if (EVAL_HSYM (pv) != 0)
switch ((pSym = MHOmfLock (EVAL_HSYM (pv)))->rectyp) {
case S_REGISTER:
len = ((REGPTR)pSym)->name[0];
offset = offsetof (REGSYM, name[1]);
break;
case S_CONSTANT:
len = ((CONSTPTR)pSym)->name[0];
offset = offsetof (CONSTSYM, name[1]);
break;
case S_UDT:
// for a UDT, we do not return a name so that a
// display of the type will display the type name
// only once
len = 0;
offset = offsetof (UDTSYM, name[1]);
break;
case S_BLOCK16:
len = ((BLOCKPTR16)pSym)->name[0];
offset = offsetof (BLOCKSYM16, name[1]);
break;
case S_LPROC16:
case S_GPROC16:
len = ((PROCPTR16)pSym)->name[0];
offset = offsetof (PROCSYM16, name[1]);
break;
case S_LABEL16:
len = ((LABELPTR16)pSym)->name[0];
offset = offsetof (LABELSYM16, name[1]);
break;
case S_BPREL16:
len = ((BPRELPTR16)pSym)->name[0];
offset = offsetof (BPRELSYM16, name[1]);
break;
case S_LDATA16:
case S_GDATA16:
case S_PUB16:
len = ((DATAPTR16)pSym)->name[0];
offset = offsetof (DATASYM16, name[1]);
break;
case S_BLOCK32:
len = ((BLOCKPTR32)pSym)->name[0];
offset = offsetof (BLOCKSYM32, name[1]);
break;
case S_LPROC32:
case S_GPROC32:
len = ((PROCPTR32)pSym)->name[0];
offset = offsetof (PROCSYM32, name[1]);
break;
case S_LABEL32:
len = ((LABELPTR32)pSym)->name[0];
offset = offsetof (LABELSYM32, name[1]);
break;
case S_BPREL32:
len = ((BPRELPTR32)pSym)->name[0];
offset = offsetof (BPRELSYM32, name[1]);
break;
case S_LDATA32:
case S_GDATA32:
case S_PUB32:
case S_LTHREAD32:
case S_GTHREAD32:
len = ((DATAPTR32)pSym)->name[0];
offset = offsetof (DATASYM32, name[1]);
break;
case S_REGREL32:
len = ((LPREGREL32)pSym)->name[0];
offset = offsetof (REGREL32, name[1]);
break;
case S_LPROCMIPS:
case S_GPROCMIPS:
len = ((PROCPTRMIPS)pSym)->name[0];
offset = offsetof (PROCSYMMIPS, name[1]);
break;
default:
pExState->err_num = ERR_BADOMF;
MHMemUnLock (*phTM);
pExState = NULL;
/// BUGBUG -- Messed up return
return (EEGENERAL);
}
len = min (len, buflen);
strncpy (buf, ((char *)pSym) + offset, len);
MHOmfUnLock (EVAL_HSYM (pv));
*(buf + len) = 0;
retval = EENOERROR;
}
}
else {
/*
* if the expression did not bind, return the expression and
* the error message if one is available
*
* Lets treat this a bit more funny. Since the only known
* occurance of this is currently in locals and watch windows,
* check to see if there is a direct symbol refrence and
* correct for this case, additionally don't return an
* error if we can get any type of name
*/
pExStr = MHMemLock (pExState->hExStr);
for (len = 0; pExStr[len] != 0; len++) {
if (pExStr[len] == (char)-1) {
pExStr += len+5;
len = -1;
} else if ((len == 0) &&
((pExStr[len] == ')') || (pExStr[len] == '.'))) {
pExStr++;
len = -1;
}
}
if (*pExStr != 0) {
len = min (buflen, len);
strncpy (buf, pExStr, len);
buf += len;
buflen -= len;
retval = EENOERROR;
}
MHMemUnLock (pExState->hExStr);
}
MHMemUnLock (*phszName);
MHMemUnLock (*phTM);
pExState = NULL;
}
return (retval);
}
/** InfoFromTM - return information about TM
*
* EESTATUS InfoFromTM (phTM, pReqInfo, phTMInfo);
*
* Entry phTM = pointer to the handle for the expression state structure
* reqInfo = info request structure
* phTMInfo = pointer to handle for request info data structure
*
* Exit *phTMInfo = handle of info structure
*
* Returns EECATASTROPHIC if fatal error
* 0 if no error
*
* The return information is based on the input request structure:
*
* fSegType - Requests the segment type the TM resides in.
* returned in TI.fCode
* fAddr - Return result as an address
* fValue - Return value of TM
* fLvalue - Return address of TM if lValue. This and
* fValue are mutually exclusive
* fSzBits - Return size of value in bits
* fSzBytes - Return size of value in bytes. This and
* fSzBits are mutually exclusive.
* Type - If not T_NOTYPE then cast value to this type.
* fValue must be set.
*/
EESTATUS
InfoFromTM (
PHTM phTM,
PRI pReqInfo,
PHTI phTMInfo
)
{
EESTATUS eestatus = EEGENERAL;
TI * pTMInfo;
eval_t evalT;
peval_t pvT;
#ifdef TARGET_i386
SHREG reg;
#endif
char *p;
*phTMInfo = 0;
/*
* Verify that there is a TM to play with
*/
DASSERT( *phTM != 0 );
if (*phTM == 0) {
return EECATASTROPHIC;
}
/*
* Check for consistancy on the requested information
*/
if (((pReqInfo->fValue) && (pReqInfo->fLvalue)) ||
((pReqInfo->fSzBits) && (pReqInfo->fSzBytes)) ||
((pReqInfo->Type != T_NOTYPE) && (!pReqInfo->fValue))) {
return EEGENERAL;
}
/*
* Allocate and lock down the TI which is used to return the answers
*/
if (( *phTMInfo = MHMemAllocate( sizeof(TI) + sizeof(val_t) )) == 0) {
return EENOMEMORY;
}
pTMInfo = MHMemLock( *phTMInfo );
DASSERT( pTMInfo != NULL );
memset( pTMInfo, 0, sizeof(TI) + sizeof(val_t) );
/*
* Lock down the TM passed in
*/
DASSERT(pExState == NULL);
pExState = (pexstate_t) MHMemLock( *phTM );
if ( pExState->state.bind_ok != TRUE ) {
/*
* If the expression has not been bound, then we can't actually
* answer any of the questions being asked.
*/
MHMemUnLock( *phTMInfo );
MHMemUnLock( *phTM );
pExState = NULL;
return EEGENERAL;
}
pvT = &evalT;
*pvT = pExState->result;
eestatus = EENOERROR;
/*
* If the user asked about the segment type for the expression,
* get it.
*/
if (pReqInfo->fSegType || pReqInfo->fAddr) {
if (EVAL_STATE( pvT ) == EV_lvalue) {
pTMInfo->fResponse.fSegType = TRUE;
/*
* Check for type of 0. If so then this must be a public
* as all compiler symbols have some type information
*/
if (EVAL_TYP( pvT ) == 0) {
pTMInfo->u.SegType = EEDATA | EECODE;
}
/*
* If item is of type pointer to data then must be in
* data segment
*/
else if (EVAL_IS_DPTR( pvT ) == TRUE) {
pTMInfo->u.SegType = EEDATA;
}
/*
* in all other cases it must have been a code segment
*/
else {
pTMInfo->u.SegType = EECODE;
}
} else if ((EVAL_STATE( pvT ) == EV_rvalue) &&
(EVAL_IS_FCN( pvT ) ||
EVAL_IS_LABEL( pvT ))) {
pTMInfo->fResponse.fSegType = TRUE;
pTMInfo->u.SegType = EECODE;
} else if ((EVAL_STATE( pvT ) == EV_rvalue) &&
(EVAL_IS_ADDR( pvT ))) {
pTMInfo->fResponse.fSegType = TRUE;
pTMInfo->u.SegType = EECODE | EEDATA;
} else if ((EVAL_STATE( pvT ) == EV_rvalue) ||
(EVAL_STATE( pvT ) == EV_constant)) {
;
}
}
/*
* If the user asked for the value then get it
*/
if (pReqInfo->fValue) {
if ((pExState->state.eval_ok == TRUE) && LoadSymVal(pvT)) {
EVAL_STATE (pvT) = EV_rvalue;
}
if ((EVAL_STATE(pvT) == EV_rvalue) &&
(EVAL_IS_FCN(pvT) ||
EVAL_IS_LABEL(pvT))) {
if ( pReqInfo->Type == T_NOTYPE ) {
pTMInfo->fResponse.fValue = TRUE;
pTMInfo->fResponse.fAddr = TRUE;
pTMInfo->fResponse.fLvalue = FALSE;
pTMInfo->u2.AI = EVAL_SYM( pvT );
pTMInfo->fResponse.Type = EVAL_TYP( pvT );
if (!ADDR_IS_LI(pTMInfo->u2.AI)) {
SHUnFixupAddr(&pTMInfo->u2.AI);
}
} else {
Evaluating = TRUE;
if (CastNode( pvT, pReqInfo->Type, pReqInfo->Type )) {
memcpy( pTMInfo->Value, &pvT->val, sizeof( pvT->val ));
pTMInfo->fResponse.fValue = TRUE;
pTMInfo->fResponse.Type = EVAL_TYP( pvT );
}
Evaluating = FALSE;
}
} else if ((EVAL_STATE( pvT ) == EV_rvalue) &&
(EVAL_IS_ADDR( pvT ))) {
if (EVAL_IS_BASED( pvT )) {
Evaluating = TRUE;
NormalizeBase( pvT );
Evaluating = FALSE;
}
if ( pReqInfo->Type == T_NOTYPE ) {
pTMInfo->fResponse.fValue = TRUE;
pTMInfo->fResponse.fAddr = TRUE;
pTMInfo->fResponse.fLvalue = FALSE;
pTMInfo->u2.AI = EVAL_PTR( pvT );
pTMInfo->fResponse.Type = EVAL_TYP(pvT);
if (!ADDR_IS_LI( pTMInfo->u2.AI )) {
SHUnFixupAddr( &pTMInfo->u2.AI );
}
} else {
Evaluating = TRUE;
if (CastNode( pvT, pReqInfo->Type, pReqInfo->Type )) {
memcpy( pTMInfo->Value, &pvT->val, sizeof( pvT->val ));
pTMInfo->fResponse.fValue = TRUE;
pTMInfo->fResponse.Type = EVAL_TYP( pvT );
}
Evaluating = FALSE;
}
} else if ((EVAL_STATE( pvT ) == EV_rvalue) ||
(EVAL_STATE( pvT ) == EV_constant)) {
if ((EVAL_STATE( pvT ) == EV_constant ) ||
(pExState->state.eval_ok == TRUE)) {
if (CV_IS_PRIMITIVE( pReqInfo->Type )) {
if (pReqInfo->Type == 0) {
pReqInfo->Type = EVAL_TYP( pvT );
}
Evaluating = TRUE;
if (CastNode( pvT, pReqInfo->Type, pReqInfo->Type )) {
memcpy( pTMInfo->Value, &pvT->val, sizeof( pvT->val ));
pTMInfo->fResponse.fValue = TRUE;
pTMInfo->fResponse.Type = EVAL_TYP( pvT );
}
Evaluating = FALSE;
}
}
}
}
/*
* If the user asked for the lvalue as an address
*/
if (pReqInfo->fAddr && pReqInfo->fLvalue) {
pTMInfo->u2.AI = pvT->addr;
//eestatus = EEGENERAL;
}
/*
* If the user asked for the value as an address
*/
if (pReqInfo->fAddr && !pReqInfo->fLvalue) {
if ((EVAL_STATE(pvT) == EV_lvalue) &&
(pExState->state.eval_ok == TRUE) &&
LoadSymVal(pvT)) {
EVAL_STATE (pvT) = EV_rvalue;
}
if ((EVAL_STATE(pvT) == EV_rvalue) &&
(EVAL_IS_FCN(pvT) ||
EVAL_IS_LABEL(pvT))) {
pTMInfo->u2.AI = EVAL_SYM( pvT );
pTMInfo->fResponse.fAddr = TRUE;
pTMInfo->fResponse.Type = EVAL_TYP( pvT );
if (!ADDR_IS_LI(pTMInfo->u2.AI)) {
SHUnFixupAddr(&pTMInfo->u2.AI);
}
eestatus = EENOERROR;
} else if ((EVAL_STATE(pvT) == EV_rvalue) &&
(EVAL_IS_ADDR( pvT ))) {
if (EVAL_IS_BASED( pvT )) {
Evaluating = TRUE;
NormalizeBase( pvT );
Evaluating = FALSE;
}
pTMInfo->fResponse.fAddr = TRUE;
pTMInfo->u2.AI = EVAL_PTR( pvT );
pTMInfo->fResponse.Type = EVAL_TYP( pvT );
if (!ADDR_IS_LI( pTMInfo->u2.AI )) {
SHUnFixupAddr( &pTMInfo->u2.AI );
}
} else if ((EVAL_STATE( pvT ) == EV_rvalue) ||
(EVAL_STATE( pvT ) == EV_constant)) {
if ((EVAL_STATE( pvT ) == EV_constant) ||
(pExState->state.eval_ok == TRUE)) {
pReqInfo->Type = T_ULONG;
Evaluating = TRUE;
if (CastNode(pvT, pReqInfo->Type, pReqInfo->Type)) {
switch( TypeSize( pvT ) ) {
case 1:
pTMInfo->u2.AI.addr.off = VAL_UCHAR( pvT );
break;
case 2:
pTMInfo->u2.AI.addr.off = VAL_USHORT( pvT );
break;
case 4:
pTMInfo->u2.AI.addr.off = VAL_ULONG( pvT );
break;
default:
eestatus = EEGENERAL;
break;
}
pTMInfo->fResponse.fAddr = TRUE;
pTMInfo->fResponse.Type = pReqInfo->Type;
#ifdef TARGET_i386
if (pTMInfo->u.SegType & EECODE) {
reg.hReg = CV_REG_CS;
} else {
reg.hReg = CV_REG_DS;
}
GetReg(&reg, pCxt);
pTMInfo->u2.AI.addr.seg = reg.Byte2;
#else
pTMInfo->u2.AI.addr.seg = 0;
#endif
SHUnFixupAddr( &pTMInfo->u2.AI);
} else {
eestatus = EEGENERAL;
}
Evaluating = FALSE;
} else {
eestatus = EEGENERAL;
}
} else {
eestatus = EEGENERAL;
}
}
/*
* Set the size fields if requested
*/
if (pReqInfo->fSzBits) {
if (EVAL_IS_BITF( pvT )) {
pTMInfo->cbValue = BITF_LEN( pvT );
pTMInfo->fResponse.fSzBits = TRUE;
} else {
if (EVAL_TYP( pvT ) != 0) {
pTMInfo->cbValue = 8 * TypeSize( pvT );
pTMInfo->fResponse.fSzBits = TRUE;
}
}
}
if (pReqInfo->fSzBytes) {
if (EVAL_IS_BITF( pvT )) {
EVAL_TYP( pvT ) = BITF_UTYPE( pvT );
}
if (EVAL_TYP( pvT ) != 0) {
pTMInfo->cbValue = TypeSize( pvT );
pTMInfo->fResponse.fSzBytes = TRUE;
}
}
/*
* Set random flags
*/
pTMInfo->u.fFunction = pExState->state.fFunction;
pExStr = MHMemLock(pExState->hExStr);
p = &pExStr[pExState->strIndex];
if (*p == ',') {
*p++;
}
if (tolower(*p) == 's') {
pTMInfo->u.fFmtStr = TRUE;
}
else {
pTMInfo->u.fFmtStr = FALSE;
}
MHMemUnLock( pExState->hExStr );
MHMemUnLock( *phTMInfo );
MHMemUnLock( *phTM );
pExState = NULL;
return eestatus;
}
/** IsExpandablePtr - check for pointer to displayable data
*
* fSuccess = IsExpandablePtr (pn)
*
* Entry pn = pointer to node for variable
*
* Exit none
*
* Returns EEPOINTER if node is a pointer to primitive data or,
* class/struct/union
* EEAGGREGATE if node is an array with a non-zero size or is
* a pointer to a virtual function shape table
* EENOTEXP otherwise
*/
ushort IsExpandablePtr (peval_t pv)
{
eval_t evalT;
peval_t pvT;
ushort retval = EENOTEXP;
if (EVAL_IS_PTR (pv)) {
// this will also handle the reference cases
if (EVAL_TYP(pv) == T_VOID ||
EVAL_TYP(pv) == T_PVOID ||
EVAL_TYP(pv) == T_PFVOID ||
EVAL_TYP(pv) == T_PHVOID ||
EVAL_TYP(pv) == T_32PVOID ||
EVAL_TYP(pv) == T_32PFVOID) {
return retval;
}
if (CV_IS_PRIMITIVE (PTR_UTYPE (pv))) {
retval = EEPOINTER;
} else {
pvT = &evalT;
CLEAR_EVAL (pvT);
EVAL_MOD (pvT) = EVAL_MOD (pv);
SetNodeType (pvT, PTR_UTYPE (pv));
if (EVAL_IS_CLASS (pvT) || EVAL_IS_PTR (pvT)) {
retval = EEPOINTER;
}
else if (EVAL_IS_VTSHAPE (pvT) ||
(EVAL_IS_ARRAY (pvT) && (PTR_ARRAYLEN (pv) != 0))) {
retval = EEAGGREGATE;
}
}
}
return (retval);
}
/*** CountClassElem - count number of class elements according to mask
*
* count = CountClassElem (pv, search)
*
* Entry pv = pointer to node to be initialized
* search = mask specifying which element types to count
*
* Exit none
*
* Returns count of number of class elements meeting search requirments
*/
LOCAL EESTATUS CountClassElem (peval_t pv, long *pcChildren,
uint search)
{
ushort cnt; // total number of elements in class
HTYPE hField; // type record handle for class field list
char *pField; // current position within field list
uint fSkip = 0; // current offset in the field list
uint anchor;
ushort retval = EENOERROR;
CV_typ_t newindex;
uchar pad;
// set the handle of the field list
if ((hField = THGetTypeFromIndex (EVAL_MOD (pv), CLASS_FIELD (pv))) == 0) {
DASSERT (FALSE);
return (0);
}
pField = (char *)(&((TYPPTR)MHOmfLock (hField))->data[0]);
// walk field list to the end counting elements
for (cnt = CLASS_COUNT (pv); cnt > 0; cnt--) {
if ((pad = *(((char *)pField) + fSkip)) >= LF_PAD0) {
// there is a pad field
fSkip += pad & 0x0f;
}
anchor = fSkip;
switch (((plfEasy)(pField + fSkip))->leaf) {
case LF_INDEX:
// move to next list in chain
newindex = ((plfIndex)(pField + fSkip))->index;
MHOmfUnLock (hField);
if ((hField = THGetTypeFromIndex (EVAL_MOD (pv), newindex)) == 0) {
DASSERT (FALSE);
return (0);
}
pField = (char *)(&((TYPPTR)MHOmfLock (hField))->data[0]);
fSkip = 0;
// the LF_INDEX is not part of the field count
cnt++;
break;
case LF_MEMBER:
// skip offset of member and name of member
fSkip += offsetof (lfMember, offset[0]);
RNumLeaf (pField + fSkip, &fSkip);
fSkip += *(pField + fSkip) + sizeof (char);
if (search & CLS_member) {
(*pcChildren)++;
}
break;
#if !defined(C_ONLY)
case LF_ENUMERATE:
// skip value name of enumerate
fSkip += offsetof (lfEnumerate, value[0]);
RNumLeaf (pField + fSkip, &fSkip);
fSkip += *(pField + fSkip) + sizeof (char);
if (search & CLS_enumerate) {
(*pcChildren)++;
}
break;
case LF_STMEMBER:
fSkip += offsetof (lfSTMember, Name[0]);
fSkip += *(pField + fSkip) + sizeof (char);
if (search & CLS_member) {
(*pcChildren)++;
}
break;
case LF_BCLASS:
fSkip += offsetof (lfBClass, offset[0]);
RNumLeaf (pField + fSkip, &fSkip);
if (search & CLS_bclass) {
(*pcChildren)++;
}
break;
case LF_VBCLASS:
fSkip += offsetof (lfVBClass, vbpoff[0]);
RNumLeaf (pField + fSkip, &fSkip);
RNumLeaf (pField + fSkip, &fSkip);
if (search & CLS_bclass) {
(*pcChildren)++;
}
break;
case LF_IVBCLASS:
fSkip += offsetof (lfVBClass, vbpoff[0]);
RNumLeaf (pField + fSkip, &fSkip);
RNumLeaf (pField + fSkip, &fSkip);
break;
case LF_FRIENDCLS:
fSkip += sizeof (lfFriendCls);
if (search & CLS_fclass) {
(*pcChildren)++;
}
break;
case LF_FRIENDFCN:
fSkip += sizeof (struct lfFriendFcn) +
((plfFriendFcn)(pField + fSkip))->Name[0];
if (search & CLS_frmethod) {
(*pcChildren)++;
}
break;
case LF_VFUNCTAB:
fSkip += sizeof (lfVFuncTab);
if (search & CLS_vfunc) {
(*pcChildren)++;
}
break;
case LF_METHOD:
fSkip += sizeof (struct lfMethod) +
((plfMethod)(pField + fSkip))->Name[0];
cnt -= ((plfMethod)(pField + anchor))->count - 1;
if (search & CLS_method) {
*pcChildren += ((plfMethod)(pField + anchor))->count;
}
break;
case LF_NESTTYPE:
fSkip += sizeof (struct lfNestType) +
((plfNestType)(pField + fSkip))->Name[0];
if (search & CLS_ntype) {
(*pcChildren)++;
}
break;
#endif
default:
pExState->err_num = ERR_BADOMF;
MHOmfUnLock (hField);
*pcChildren = 0;
return (EEGENERAL);
}
}
if (hField != 0) {
MHOmfUnLock (hField);
}
return (retval);
}
/** DereferenceTM - generate expression string from pointer to data TM
*
* flag = DereferenceTM (hTMIn, phEStr)
*
* Entry phTMIn = handle to TM to dereference
* phEStr = pointer to handle to dereferencing expression
*
* Exit *phEStr = expression referencing pointer data
*
* Returns EECATASTROPHIC if fatal error
* EEGENERAL if TM not dereferencable
* EENOERROR if expression generated
*/
EESTATUS DereferenceTM (HTM hTM, PEEHSTR phDStr)
{
peval_t pvTM;
EESTATUS retval = EECATASTROPHIC;
pexstate_t pTM;
ushort plen;
uint excess;
DASSERT (hTM != 0);
if (hTM != 0) {
// lock TM and set pointer to result field of TM
pTM = MHMemLock (hTM);
pvTM = &pTM->result;
if (EVAL_IS_ARRAY (pvTM) || (IsExpandablePtr (pvTM) != EEPOINTER)) {
pTM->err_num = ERR_NOTEXPANDABLE;
retval = EEGENERAL;
}
else {
// allocate buffer for *(input string) and copy
if ((*phDStr = MHMemAllocate (pTM->ExLen + 4)) != 0) {
// if not reference generate, expression = *(old expr)
// if reference, expression = (old expr)
pExStr = MHMemLock (*phDStr);
*pExStr++ = '(';
#if !defined (C_ONLY)
if (!EVAL_IS_REF (pvTM)) {
*pExStr++ = '*';
}
#else
*pExStr++ = '*';
#endif
plen = pTM->strIndex;
excess = pTM->ExLen - plen;
pExStrP = MHMemLock (pTM->hExStr);
memcpy (pExStr, pExStrP, plen);
pExStr += plen;
*pExStr++ = ')';
memcpy (pExStr, pExStrP + plen, excess);
pExStr += excess;
*pExStr = 0;
MHMemUnLock (pTM->hExStr);
MHMemUnLock (*phDStr);
retval = EENOERROR;
}
}
MHMemUnLock (hTM);
}
return (retval);
}
/*** SetClassiName - Set a node to a specified element of a class
*
* fFound = SetClassiName (pv, ordinal, phDStr, phName, search, plen)
*
* Entry ordinal = number of class element to initialize for
* (zero based)
* search = mask specifying which element types to count
* pExStrP = address of locked pExParent->hExStr
* plen = length of parent string to end of parse
* excess = length of parent string after end of parse
*
* Exit pExState->hCName = handle of buffer containing name
*
* Returns ERR_NONE if element found within structure
* error number if element not found within structure
*/
LOCAL ushort SetClassiName (peval_t pv, long ordinal,
PEEHSTR phDStr, PEEHSTR phName, uint search, ushort plen, uint excess)
{
HTYPE hField; // handle to type record for struct field list
char *pField; // current position withing field list
char *pMethod;
uint fSkip = 0; // current offset in the field list
uint anchor;
uint len;
bool_t retval = ERR_NONE;
CV_typ_t newindex;
char *pName;
char *pc;
char *pDStr;
char FName[255];
char *pFName = &FName[0];
eval_t evalT;
peval_t pvT;
uchar pad;
PHDR_TYPE pHdr;
// set fField to the handle of the field list
if ((hField = THGetTypeFromIndex (EVAL_MOD (pv), CLASS_FIELD (pv))) == 0) {
DASSERT (FALSE);
return (ERR_BADOMF);
}
pField = (char *)(&((TYPPTR)MHOmfLock (hField))->data[0]);
// walk field list to iElement-th field
while (ordinal >= 0) {
if ((pad = *(((char *)pField) + fSkip)) >= LF_PAD0) {
// there is a pad field
fSkip += pad & 0x0f;
}
anchor = fSkip;
switch (((plfEasy)(pField + fSkip))->leaf) {
case LF_INDEX:
// move to next list in chain
newindex = ((plfIndex)(pField + fSkip))->index;
MHOmfUnLock (hField);
if ((hField = THGetTypeFromIndex (EVAL_MOD (pv), newindex)) == 0) {
return (ERR_BADOMF);
}
pField = (char *)(&((TYPPTR)MHOmfLock (hField))->data[0]);
fSkip = 0;
break;
case LF_MEMBER:
// skip offset of member and name of member
fSkip += offsetof (lfMember, offset[0]);
RNumLeaf (pField + fSkip, &fSkip);
pc = pField + fSkip;
fSkip += *(pField + fSkip) + sizeof (char);
if (search & CLS_member) {
ordinal--;
}
break;
case LF_ENUMERATE:
// skip value name of enumerate
fSkip += offsetof (lfEnumerate, value[0]);
RNumLeaf (pField + fSkip, &fSkip);
pc = pField + fSkip;
fSkip += *(pField + fSkip) + sizeof (char);
if (search & CLS_enumerate) {
ordinal--;
}
break;
#if !defined(C_ONLY)
case LF_STMEMBER:
fSkip += offsetof (lfSTMember, Name[0]);
pc = pField + fSkip;
fSkip += *(pField + fSkip) + sizeof (char);
if (search & CLS_member) {
ordinal--;
}
break;
case LF_BCLASS:
fSkip += offsetof (lfBClass, offset[0]);
RNumLeaf (pField + fSkip, &fSkip);
if (search & CLS_bclass) {
ordinal--;
}
break;
case LF_VBCLASS:
fSkip += offsetof (lfVBClass, vbpoff[0]);
RNumLeaf (pField + fSkip, &fSkip);
RNumLeaf (pField + fSkip, &fSkip);
if (search & CLS_bclass) {
ordinal--;
}
break;
case LF_IVBCLASS:
fSkip += offsetof (lfVBClass, vbpoff[0]);
RNumLeaf (pField + fSkip, &fSkip);
RNumLeaf (pField + fSkip, &fSkip);
break;
case LF_FRIENDCLS:
fSkip += sizeof (struct lfFriendCls);
if (search & CLS_fclass) {
ordinal--;
}
break;
case LF_FRIENDFCN:
fSkip += sizeof (struct lfFriendFcn) +
((plfFriendFcn)(pField + fSkip))->Name[0];
if (search & CLS_frmethod) {
ordinal--;
}
break;
case LF_VFUNCTAB:
fSkip += sizeof (struct lfVFuncTab);
pc = vfuncptr;
if (search & CLS_vfunc) {
ordinal--;
}
break;
case LF_METHOD:
pc = pField + anchor + offsetof (lfMethod, Name[0]);
fSkip += sizeof (struct lfMethod) + *pc;
if (search & CLS_method) {
ordinal -= ((plfMethod)(pField + anchor))->count;
}
break;
case LF_NESTTYPE:
fSkip += offsetof (lfNestType, Name[0]);
pc = pField + fSkip;
fSkip += *(pField + fSkip) + sizeof (char);
if (search & CLS_ntype) {
ordinal--;
}
break;
#endif
default:
MHOmfUnLock (hField);
return (ERR_BADOMF);
}
if (ordinal < 0) {
break;
}
}
// we have found the ith element of the class. Now create the
// name and the expression to reference the name
switch (((plfEasy)(pField + anchor))->leaf) {
case LF_MEMBER:
case LF_STMEMBER:
case LF_VFUNCTAB:
len = *pc;
if (((*phName = MHMemAllocate (len + 1)) == 0) ||
((*phDStr = MHMemAllocate (plen + excess + len + 4)) == 0)) {
goto nomemory;
}
pName = MHMemLock (*phName);
strncpy (pName, pc + 1, len);
*(pName + len) = 0;
pDStr = MHMemLock (*phDStr);
*pDStr++ = '(';
memcpy (pDStr, pExStrP, plen);
pDStr += plen;
*pDStr++ = ')';
*pDStr++ = '.';
memcpy (pDStr, pName, len);
pDStr += len;
memcpy (pDStr, pExStrP + plen, excess);
pDStr += excess;
*pDStr = 0;
MHMemUnLock (*phDStr);
MHMemUnLock (*phName);
break;
#if !defined (C_ONLY)
case LF_BCLASS:
newindex = ((plfBClass)(pField + anchor))->index;
MHOmfUnLock (hField);
if ((hField = THGetTypeFromIndex (EVAL_MOD (pv), newindex)) != 0) {
// find the name of the base class from the referenced class
pField = (char *)(&((TYPPTR)MHOmfLock (hField))->leaf);
fSkip = offsetof (lfClass, data[0]);
RNumLeaf (pField + fSkip, &fSkip);
len = *(pField + fSkip);
// generate (*(base *)(&expr))
if (((*phName = MHMemAllocate (len + 1)) == 0) ||
((*phDStr = MHMemAllocate (plen + len + excess + 10)) == 0)) {
goto nomemory;
}
pName = MHMemLock (*phName);
strncpy (pName, pField + fSkip + sizeof (char), len);
*(pName + len) = 0;
pDStr = MHMemLock (*phDStr);
memcpy (pDStr, "(*(", 3);
memcpy (pDStr + 3, pField + fSkip + sizeof (char), len);
memcpy (pDStr + 3 + len, "*)(&", 4);
memcpy (pDStr + 7 + len, pExStrP, plen);
memcpy (pDStr + 7 + len + plen, "))", 2);
memcpy (pDStr + 7 + len + plen + 2, pExStrP + plen, excess);
*(pDStr + 9 + len + plen + excess) = 0;
MHMemUnLock (*phDStr);
MHMemUnLock (*phName);
}
break;
case LF_VBCLASS:
newindex = ((plfVBClass)(pField + anchor))->index;
MHOmfUnLock (hField);
if ((hField = THGetTypeFromIndex (EVAL_MOD (pv), newindex)) != 0) {
// find the name of the base class from the referenced class
pField = (char *)(&((TYPPTR)MHOmfLock (hField))->leaf);
fSkip = offsetof (lfClass, data[0]);
RNumLeaf (pField + fSkip, &fSkip);
len = *(pField + fSkip);
// generate (*(base *)(&expr))
if (((*phName = MHMemAllocate (len + 1)) == 0) ||
((*phDStr = MHMemAllocate (plen + len + 10)) == 0)) {
goto nomemory;
}
pName = MHMemLock (*phName);
//*pName = 0;
strncpy (pName, pField + fSkip + sizeof (char), len);
*(pName + len) = 0;
pDStr = MHMemLock (*phDStr);
memcpy (pDStr, "(*(", 3);
memcpy (pDStr + 3, pField + fSkip + sizeof (char), len);
memcpy (pDStr + 3 + len, "*)(&", 4);
memcpy (pDStr + 7 + len, pExStrP, plen);
memcpy (pDStr + 7 + len + plen, "))", 2);
memcpy (pDStr + 7 + len + plen + 2, pExStrP + plen, excess);
*(pDStr + 9 + len + plen + excess) = 0;
MHMemUnLock (*phDStr);
MHMemUnLock (*phName);
}
break;
case LF_FRIENDCLS:
// look at referenced type record to get name of class
// M00KLUDGE - figure out what to do here - not bindable
newindex = ((plfFriendCls)(pField + anchor))->index;
MHOmfUnLock (hField);
if ((hField = THGetTypeFromIndex (EVAL_MOD (pv), newindex)) != 0) {
pField = (char *)(&((TYPPTR)MHOmfLock (hField))->leaf);
fSkip = offsetof (lfClass, data[0]);
RNumLeaf (pField + fSkip, &fSkip);
len = *(pField + fSkip);
}
break;
case LF_FRIENDFCN:
// look at referenced type record to get name of function
// M00KLUDGE - figure out what to do here - not bindable
newindex = ((plfFriendFcn)(pField + anchor))->index;
pc = (char *)(((plfFriendFcn)(pField + anchor))->Name[0]);
break;
case LF_METHOD:
// copy function name to temporary buffer
len = *pc;
memcpy (FName, pc + 1, len);
FName[len] = 0;
newindex = ((plfMethod)(pField + anchor))->mList;
MHOmfUnLock (hField);
// index down method list to find correct method
if ((hField = THGetTypeFromIndex (EVAL_MOD (pv), newindex)) != 0) {
pMethod = (char *)(&((TYPPTR)MHOmfLock (hField))->data[0]);
fSkip = 0;
while (++ordinal < 0) {
if (((pmlMethod)(pMethod + fSkip))->attr.mprop == CV_MTvirtual) {
fSkip += sizeof (mlMethod);
RNumLeaf (pMethod + fSkip, &fSkip);
}
else {
fSkip += sizeof (mlMethod);
}
}
pvT = &evalT;
CLEAR_EVAL (pvT);
EVAL_MOD (pvT) = SHHMODFrompCXT (pCxt);
newindex = ((pmlMethod)(pMethod + fSkip))->index;
MHOmfUnLock (hField);
hField = 0;
SetNodeType (pvT, newindex);
if ((*phName = MHMemAllocate (FCNSTRMAX + sizeof (HDR_TYPE))) == 0) {
goto nomemory;
}
// FormatType places a structure at the beginning of the buffer
// containing offsets into the type string. We need to skip this
// structure
pName = MHMemLock (*phName);
pHdr = (PHDR_TYPE)pName;
memset (pName, 0, FCNSTRMAX + sizeof (HDR_TYPE));
pName = pName + sizeof (HDR_TYPE);
pc = pName;
len = FCNSTRMAX - 1;
FormatType (pvT, &pName, &len, &pFName, 0L, pHdr);
len = FCNSTRMAX - len;
// ignore buffer header from FormatType
memmove ((char *)pHdr, pc, len);
pc = (char *)pHdr;
if ((*phDStr = MHMemAllocate (plen + FCNSTRMAX + 2)) == 0) {
MHMemUnLock (*phName);
goto nomemory;
}
pDStr = MHMemLock (*phDStr);
memcpy (pDStr, pExStrP, plen);
memcpy (pDStr + plen, ".", 1);
memcpy (pDStr + 1 + plen, pc, len);
memcpy (pDStr + 1 + plen + len, pExStrP + plen, excess);
*(pDStr + len + plen + 1 + excess) = 0;
MHMemUnLock (*phDStr);
// truncate name to first (
for (len = 0; (*pc != '(') && (*pc != 0); pc++) {
len++;
}
*pc = 0;
MHMemUnLock (*phName);
if ((*phName = MHMemReAlloc (*phName, len + 1)) == 0) {
goto nomemory;
}
}
break;
#else
Unreferenced( evalT );
Unreferenced( pHdr );
Unreferenced( pvT );
Unreferenced( pMethod );
#endif
default:
retval = ERR_BADOMF;
break;
}
if (hField != 0) {
MHOmfUnLock (hField);
}
return (retval);
nomemory:
if (hField != 0) {
MHOmfUnLock (hField);
}
if (*phName != 0) {
MHMemFree (*phName);
}
return (ERR_NOMEMORY);
}
/*** SetFcniParm - Set a node to a specified parameter of a function
*
* fFound = SetFcniParm (pv, ordinal, pHStr)
*
* Entry pv = pointer to node to be initialized
* ordinal = number of struct element to initialize for
* (zero based)
* pHStr = pointer to handle for parameter name
*
* Exit pv initialized if no error
* *pHStr = handle for name
*
* Returns EENOERROR if parameter found
* EEGENERAL if parameter not found
*
* This routine is essentially a kludge. We are depending upon the
* the compiler to output the formals in order of declaration before
* any of the hidden parameters or local variables. We also are
* depending upon the presence of an S_END record to break us out of
* the search loop.
*/
LOCAL ushort SetFcniParm (peval_t pv, long ordinal, PEEHSTR pHStr)
{
char *pStr;
HSYM hSym;
SYMPTR pSym;
ushort offset;
ushort len;
bool_t retval;
if ((ordinal > FCN_PCOUNT (pv)) ||
((ordinal == (FCN_PCOUNT (pv) - 1)) && (FCN_VARARGS (pv) == TRUE))) {
// attempting to reference a vararg or too many parameters
pExState->err_num = ERR_FCNERROR;
return (EEGENERAL);
}
hSym = EVAL_HSYM (pv);
for (;;) {
if ((hSym = SHNextHsym (EVAL_MOD (pv), hSym)) == 0) {
pExState->err_num = ERR_BADOMF;
return (EEGENERAL);
}
// lock the symbol and check the type
pSym = MHOmfLock (hSym);
switch (pSym->rectyp) {
#if defined (ADDR_16) || defined (ADDR_MIXED)
case S_BPREL16:
if (((BPRELPTR16)pSym)->off >= 0) {
// This is a formal argument
ordinal--;
len = ((BPRELPTR16)pSym)->name[0];
offset = offsetof (BPRELSYM16, name[0]) + sizeof (char);
}
break;
#endif
case S_BPREL32:
if (((BPRELPTR32)pSym)->off >= 0) {
// This is a formal argument
ordinal--;
len = ((BPRELPTR32)pSym)->name[0];
offset = offsetof (BPRELSYM32, name[0]) + sizeof (char);
}
break;
case S_REGREL32:
if (((LPREGREL32)pSym)->off >= 0) {
// Formal parameter
ordinal--;
len = ((LPREGREL32)pSym)->name[0];
offset = offsetof (REGREL32, name[1]);
}
break;
case S_REGISTER:
ordinal--;
len = ((REGPTR)pSym)->name[0];
offset = offsetof (REGSYM, name[1]);
break;
case S_GTHREAD32:
case S_LTHREAD32:
DASSERT(FALSE);
return( EEGENERAL );
case S_END:
case S_BLOCK16:
case S_BLOCK32:
case S_ENDARG:
// we should never get here
pExState->err_num = ERR_BADOMF;
MHOmfUnLock (hSym);
return (EEGENERAL);
default:
break;
}
if (ordinal < 0) {
break;
}
MHOmfUnLock (hSym);
}
// if we get here, pSym points to the symbol record for the parameter
if ((*pHStr = MHMemAllocate (len + 1)) != 0) {
pStr = MHMemLock (*pHStr);
strncpy (pStr, ((char *)pSym) + offset, len);
*(pStr + len) = 0;
MHMemUnLock (*pHStr);
retval = EENOERROR;
}
else {
MHOmfUnLock (hSym);
retval = EEGENERAL;
}
MHOmfUnLock (hSym);
return (retval);
}
bool_t
ResolveAddr(
peval_t pv
)
{
ulong ul;
ADDR addr;
SHREG reg;
/*
* Fixup BP Relative addresses. The BP register always comes in
* as part of the frame.
*
* This form is currently only used by x86 systems.
*/
if (EVAL_IS_BPREL (pv)) {
EVAL_SYM_OFF (pv) += pExState->frame.BP.off;
EVAL_SYM_SEG (pv) = pExState->frame.SS;
EVAL_IS_BPREL (pv) = FALSE;
ADDR_IS_LI (EVAL_SYM (pv)) = FALSE;
SHUnFixupAddr (&EVAL_SYM (pv));
}
/*
* Fixup register relative addresses. This form is currently used
* by all non-x86 systems.
*
* We need to see if we are relative to the "Frame register" for the
* machine. If so then we need to pick the address up from the
* frame packet rather than going out and getting the register
* directly. This has implications for getting variables up a stack.
*/
else if (EVAL_IS_REGREL (pv)) {
reg.hReg = EVAL_REGREL (pv);
#ifdef TARGET_PPC
if (reg.hReg == CV_PPC_GPR1) {
ul = pExState->frame.BP.off;
} else
#endif
#ifdef TARGET_MIPS
if (reg.hReg == CV_M4_IntSP) {
ul = pExState->frame.BP.off;
} else
#endif
#ifdef TARGET_ALPHA
if (reg.hReg == CV_ALPHA_IntSP) {
ul = pExState->frame.BP.off;
} else
#endif
if (GetReg (&reg, pCxt) == NULL) {
DASSERT (FALSE);
} else {
ul = reg.Byte4;
if (!ADDR_IS_OFF32(*SHpADDRFrompCXT(pCxt))) {
ul &= 0xffff;
}
}
EVAL_SYM_OFF (pv) += ul;
EVAL_SYM_SEG (pv) = pExState->frame.SS;
EVAL_IS_REGREL (pv) = FALSE;
ADDR_IS_LI (EVAL_SYM (pv)) = FALSE;
emiAddr (EVAL_SYM (pv)) = 0;
SHUnFixupAddr (&EVAL_SYM (pv));
}
/*
* Fixup Thread local storage relative addresses. This form is
* currently used by all platforms.
*/
else if (EVAL_IS_TLSREL (pv)) {
EVAL_IS_TLSREL( pv ) = FALSE;
/*
* Query the EM for the TLS base on this (current) thread
*/
memset(&addr, 0, sizeof(ADDR));
emiAddr( addr ) = emiAddr( EVAL_SYM( pv ));
SYGetAddr(&addr, adrTlsBase);
EVAL_SYM_OFF( pv ) += GetAddrOff(addr);
EVAL_SYM_SEG( pv ) = GetAddrSeg(addr);
ADDR_IS_LI(EVAL_SYM( pv )) = ADDR_IS_LI(addr);
emiAddr(EVAL_SYM( pv )) = 0;
SHUnFixupAddr( &EVAL_SYM( pv ));
}
return TRUE;
} /* ResolveAddr() */