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.
1143 lines
33 KiB
1143 lines
33 KiB
// debsrch.c - symbol search routines
|
|
// R. A. Garmoe 89/04/24
|
|
|
|
#define CheckType CheckType_H
|
|
|
|
LOCAL bool_t LoadAddress (peval_t);
|
|
LOCAL bool_t EBitfield (peval_t);
|
|
LOCAL MTYP_t CheckType (peval_t, CV_typ_t, HTYPE, bool_t);
|
|
void InsertCache (CV_typ_t type, HEXE hExe);
|
|
LOCAL void ReorderCache (int);
|
|
|
|
typedef unsigned char FAR* LNST; // length preceded string
|
|
|
|
LOCAL BOOL FSameLnst(LNST lnst1, LNST lnst2);
|
|
LOCAL BOOL FSameTypePrep(peval_t pv, CV_typ_t ti, HTYPE* phtype, BOOL* pfForward, LNST* plnst);
|
|
LOCAL BOOL FSameTypeByIndex(peval_t pv, CV_typ_t ti1, CV_typ_t ti2);
|
|
LOCAL MTYP_t SearchCheckType (peval_t, CV_typ_t, HTYPE, bool_t);
|
|
|
|
#define CACHE_MAX 100
|
|
|
|
CV_typ_t Cache[CACHE_MAX] = {T_NOTYPE};
|
|
HEXE exeCache[CACHE_MAX] = {0};
|
|
int cCache = 0;
|
|
|
|
/** MatchType - match type described by node
|
|
*
|
|
* MatchType does an exhaustive scan of the types table looking for
|
|
* a type record that matches the type described by the value node
|
|
*
|
|
* status = MatchType (pv, fExact)
|
|
*
|
|
* Entry pv = pointer to value node
|
|
* fExact = TRUE if exact match on const/volatile and mode
|
|
* preferred
|
|
*
|
|
* Exit EVAL_TYP (pv) = matching type
|
|
*
|
|
* Returns MTYP_none if type not matched
|
|
* MTYP_exact if exact match found
|
|
* MTYP_inexact if inexact match found
|
|
*/
|
|
|
|
|
|
MTYP_t
|
|
MatchType (
|
|
peval_t pv,
|
|
bool_t fExact
|
|
)
|
|
{
|
|
CV_typ_t index;
|
|
HTYPE hType;
|
|
int iCache;
|
|
CV_typ_t possible = T_NOTYPE;
|
|
HEXE hExe;
|
|
|
|
hExe = SHHexeFromHmod (EVAL_MOD (pv));
|
|
for (iCache = 0; iCache < cCache; iCache++) {
|
|
if (exeCache[iCache] != hExe) {
|
|
continue;
|
|
}
|
|
index = Cache[iCache];
|
|
if ((hType = THGetTypeFromIndex (EVAL_MOD (pv), index)) == 0) {
|
|
DASSERT (FALSE);
|
|
continue;
|
|
}
|
|
switch (SearchCheckType (pv, Cache[iCache], hType, fExact)) {
|
|
case MTYP_none:
|
|
break;
|
|
|
|
case MTYP_exact:
|
|
ReorderCache (iCache);
|
|
EVAL_TYP (pv) = index;
|
|
return (MTYP_exact);
|
|
|
|
case MTYP_inexact:
|
|
if (fExact == FALSE) {
|
|
ReorderCache (iCache);
|
|
EVAL_TYP (pv) = index;
|
|
return (MTYP_inexact);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
index = CV_FIRST_NONPRIM - 1;
|
|
while ((hType = THGetTypeFromIndex (EVAL_MOD (pv), ++index)) != 0) {
|
|
switch (SearchCheckType (pv, index, hType, fExact)) {
|
|
case MTYP_none:
|
|
break;
|
|
|
|
case MTYP_exact:
|
|
InsertCache (index, hExe);
|
|
EVAL_TYP (pv) = index;
|
|
return (MTYP_exact);
|
|
|
|
case MTYP_inexact:
|
|
if (fExact == FALSE) {
|
|
InsertCache (index, hExe);
|
|
EVAL_TYP (pv) = index;
|
|
return (MTYP_inexact);
|
|
}
|
|
else if (possible == T_NOTYPE) {
|
|
possible = index;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
if (possible == T_NOTYPE) {
|
|
return (MTYP_none);
|
|
}
|
|
InsertCache (possible, hExe);
|
|
EVAL_TYP (pv) = possible;
|
|
return (MTYP_inexact);
|
|
}
|
|
|
|
|
|
void
|
|
InsertCache (
|
|
CV_typ_t type,
|
|
HEXE hExe)
|
|
{
|
|
int i;
|
|
|
|
DASSERT (!CV_IS_PRIMITIVE (type));
|
|
if (cCache == CACHE_MAX) {
|
|
cCache--;
|
|
}
|
|
for (i = cCache; i > 0; i--) {
|
|
exeCache[i] = exeCache[i - 1];
|
|
Cache[i] = Cache[i - 1];
|
|
}
|
|
Cache[0] = type;
|
|
exeCache[0] = hExe;
|
|
cCache++;
|
|
}
|
|
|
|
|
|
|
|
|
|
LOCAL void
|
|
ReorderCache (
|
|
int iCache
|
|
)
|
|
{
|
|
CV_typ_t temp;
|
|
HEXE exeTemp;
|
|
int i;
|
|
|
|
if (iCache == 0) {
|
|
return;
|
|
}
|
|
temp = Cache[iCache];
|
|
exeTemp = exeCache[iCache];
|
|
for (i = iCache; i > 0; i--) {
|
|
exeCache[i] = exeCache[i - 1];
|
|
Cache[i] = Cache[i - 1];
|
|
}
|
|
Cache[0] = temp;
|
|
exeCache[0] = exeTemp;
|
|
}
|
|
|
|
|
|
LOCAL MTYP_t
|
|
SearchCheckType (
|
|
peval_t pv,
|
|
CV_typ_t index,
|
|
HTYPE hType,
|
|
bool_t fExact
|
|
)
|
|
{
|
|
char FAR *pType;
|
|
CV_modifier_t Mod;
|
|
CV_typ_t uType;
|
|
MTYP_t retval = MTYP_none;
|
|
plfPointer plfP;
|
|
|
|
if (hType == (HTYPE) NULL) {
|
|
return retval;
|
|
}
|
|
|
|
pType = (char FAR *)(&((TYPPTR)MHOmfLock (hType))->leaf);
|
|
switch (((plfEasy)pType)->leaf) {
|
|
case LF_POINTER:
|
|
plfP = (plfPointer)pType;
|
|
uType = plfP->utype;
|
|
if (EVAL_IS_PTR (pv)) {
|
|
// we have a pointer record and we are looking
|
|
// for a pointer. We now check the underlying types
|
|
|
|
if (FSameTypeByIndex(pv, PTR_UTYPE (pv), uType)) {
|
|
// the underlying types are the same. we now need
|
|
// to check the pointer modes
|
|
|
|
if ((plfP->attr.ptrmode == CV_PTR_MODE_REF) !=
|
|
EVAL_IS_REF (pv)) {
|
|
// if the reference modes are different, we do not
|
|
// have any type of a match
|
|
break;
|
|
}
|
|
if (plfP->attr.ptrtype == EVAL_PTRTYPE (pv)) {
|
|
// we have exact match on pointer mode
|
|
|
|
retval = MTYP_exact;
|
|
}
|
|
else if ((EVAL_PTRTYPE (pv) != CV_PTR_NEAR) ||
|
|
(plfP->attr.ptrtype != CV_PTR_FAR)) {
|
|
// we we do not have a far pointer that could
|
|
// be cast to a near pointer
|
|
break;
|
|
|
|
}
|
|
else {
|
|
retval = MTYP_inexact;
|
|
}
|
|
if (fExact == TRUE) {
|
|
if ((plfP->attr.isconst != EVAL_IS_CONST (pv)) ||
|
|
(plfP->attr.isvolatile != EVAL_IS_VOLATILE (pv))) {
|
|
retval = MTYP_inexact;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
// the underlying types are not the same but we
|
|
// have to check for a modifier with the proper
|
|
// underlying type, i.e. pointer to const class
|
|
|
|
if (CV_IS_PRIMITIVE (uType)) {
|
|
// the underlying type of the pointer cannot be
|
|
// a modifier
|
|
|
|
break;
|
|
}
|
|
if ((plfP->attr.ptrmode == CV_PTR_MODE_REF) !=
|
|
EVAL_IS_REF (pv)) {
|
|
// if the reference modes are different, we cannot
|
|
// have any type of a match
|
|
break;
|
|
}
|
|
if (plfP->attr.ptrtype != EVAL_PTRTYPE (pv)) {
|
|
// we do not have an exact match on pointer type
|
|
|
|
if (fExact == TRUE) {
|
|
// this cannot be an exact match
|
|
break;
|
|
}
|
|
else if ((EVAL_PTRTYPE (pv) != CV_PTR_NEAR) ||
|
|
(plfP->attr.ptrtype != CV_PTR_FAR)) {
|
|
// we we do not have a far pointer that could
|
|
// be cast to a near pointer
|
|
break;
|
|
}
|
|
}
|
|
MHOmfUnLock (hType);
|
|
hType = THGetTypeFromIndex (EVAL_MOD (pv), uType);
|
|
DASSERT(hType != (HTYPE) NULL);
|
|
pType = (char FAR *)(&((TYPPTR)MHOmfLock (hType))->leaf);
|
|
if (((plfEasy)pType)->leaf != LF_MODIFIER) {
|
|
break;
|
|
}
|
|
if ((uType = ((plfModifier)pType)->type) != T_NOTYPE) {
|
|
Mod = ((plfModifier)pType)->attr;
|
|
if (FSameTypeByIndex(pv, uType, PTR_UTYPE(pv))) {
|
|
if (((Mod.MOD_const == TRUE) == EVAL_IS_CONST (pv)) &&
|
|
((Mod.MOD_volatile == TRUE) == (EVAL_IS_VOLATILE (pv)))) {
|
|
retval = MTYP_exact;
|
|
}
|
|
else {
|
|
retval = MTYP_inexact;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case LF_MODIFIER:
|
|
if ((uType = ((plfModifier)pType)->type) != T_NOTYPE) {
|
|
Mod = ((plfModifier)pType)->attr;
|
|
if (FSameTypeByIndex(pv, uType, EVAL_TYP(pv))) {
|
|
if (((Mod.MOD_const == TRUE) == EVAL_IS_CONST (pv)) ||
|
|
((Mod.MOD_volatile == TRUE) == (EVAL_IS_VOLATILE (pv)))) {
|
|
retval = MTYP_exact;
|
|
}
|
|
else {
|
|
retval = MTYP_inexact;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
// type not interesting so skip
|
|
break;
|
|
}
|
|
if (hType != 0) {
|
|
MHOmfUnLock (hType);
|
|
}
|
|
return (retval);
|
|
}
|
|
|
|
|
|
// Return TRUE if ti1 and ti2 are equivalent, that is, if they are the same,
|
|
// or if one (but not the other) is a struct T definition and the other is a
|
|
// struct T forward reference.
|
|
|
|
LOCAL BOOL
|
|
FSameTypeByIndex(
|
|
peval_t pv,
|
|
CV_typ_t ti1,
|
|
CV_typ_t ti2
|
|
)
|
|
{
|
|
HTYPE htype1 = 0, htype2 = 0;
|
|
BOOL fForward1, fForward2;
|
|
LNST lnstName1, lnstName2;
|
|
BOOL fRet = FALSE;
|
|
|
|
if (ti1 == ti2)
|
|
return TRUE;
|
|
if (CV_IS_PRIMITIVE(ti1) || CV_IS_PRIMITIVE(ti2))
|
|
return FALSE;
|
|
|
|
// Try to fetch both type records, which must be class/struct/union records.
|
|
if (!FSameTypePrep(pv, ti1, &htype1, &fForward1, &lnstName1) ||
|
|
!FSameTypePrep(pv, ti2, &htype2, &fForward2, &lnstName2))
|
|
goto ret;
|
|
|
|
// One or the other must be a forward reference, otherwise we are comparing
|
|
// different structs with the same name!
|
|
if (fForward1 == fForward2)
|
|
goto ret;
|
|
|
|
// Match if length preceded names match
|
|
fRet = FSameLnst(lnstName1, lnstName2);
|
|
|
|
ret:
|
|
if (htype2)
|
|
MHOmfUnLock(htype2);
|
|
if (htype1)
|
|
MHOmfUnLock(htype1);
|
|
|
|
return fRet;
|
|
}
|
|
|
|
// Set up for FSameTypeByIndex. Lookup ti in pv and set *phtype, *pfForward, and *plnst
|
|
// in the process.
|
|
|
|
LOCAL BOOL
|
|
FSameTypePrep(
|
|
peval_t pv,
|
|
CV_typ_t ti,
|
|
HTYPE* phtype,
|
|
BOOL* pfForward,
|
|
LNST* plnst
|
|
)
|
|
{
|
|
TYPPTR ptype;
|
|
|
|
if (!(*phtype = THGetTypeFromIndex(EVAL_MOD(pv), ti)))
|
|
return FALSE;
|
|
ptype = (TYPPTR)MHOmfLock(*phtype);
|
|
|
|
switch (ptype->leaf) {
|
|
case LF_CLASS:
|
|
case LF_STRUCTURE:
|
|
{
|
|
plfClass pclass = (plfClass)&ptype->leaf;
|
|
uint skip = 0;
|
|
RNumLeaf(pclass->data, &skip);
|
|
|
|
*pfForward = pclass->property.fwdref;
|
|
*plnst = pclass->data + skip;
|
|
return TRUE;
|
|
}
|
|
|
|
case LF_UNION:
|
|
{
|
|
plfUnion punion = (plfUnion)&ptype->leaf;
|
|
uint skip = 0;
|
|
RNumLeaf(punion->data, &skip);
|
|
|
|
*pfForward = punion->property.fwdref;
|
|
*plnst = punion->data + skip;
|
|
return TRUE;
|
|
}
|
|
|
|
case LF_ENUM:
|
|
{
|
|
plfEnum penum = (plfEnum)&ptype->leaf;
|
|
|
|
*pfForward = penum->property.fwdref;
|
|
*plnst = penum->Name;
|
|
return TRUE;
|
|
}
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
// Return TRUE if the LNSTs are identical.
|
|
//
|
|
LOCAL BOOL
|
|
FSameLnst(
|
|
LNST lnst1,
|
|
LNST lnst2)
|
|
{
|
|
return *lnst1 == *lnst2 && memcmp(lnst1 + 1, lnst2 + 1, *lnst1) == 0;
|
|
}
|
|
|
|
|
|
|
|
/** ProtoPtr - set up a prototype of a pointer or reference node
|
|
*
|
|
* ProtoPtr (pvOut, pvIn, IsRef, Mod)
|
|
*
|
|
* Entry pvOut = pointer to protype node
|
|
* pvIn = pointer to node to prototype
|
|
* IsRef = TRUE if prototype is for a reference
|
|
* Mod = modifier type (CV_MOD_none, CV_MOD_const, CV_MOD_volatile)
|
|
*
|
|
* Exit pvOut = prototype pointer node
|
|
*
|
|
* Returns none
|
|
*/
|
|
|
|
|
|
void
|
|
ProtoPtr (
|
|
peval_t pvOut,
|
|
peval_t pvIn,
|
|
bool_t IsRef,
|
|
CV_modifier_t Mod
|
|
)
|
|
{
|
|
_fmemset (pvOut, 0, sizeof (*pvOut));
|
|
EVAL_MOD (pvOut) = EVAL_MOD (pvIn);
|
|
EVAL_IS_ADDR (pvOut) = TRUE;
|
|
EVAL_IS_DPTR (pvOut) = TRUE;
|
|
if (IsRef == TRUE) {
|
|
EVAL_IS_REF (pvOut) = TRUE;
|
|
}
|
|
EVAL_IS_PTR (pvOut) = TRUE;
|
|
if (Mod.MOD_const == TRUE) {
|
|
EVAL_IS_CONST (pvOut) = TRUE;
|
|
}
|
|
else if (Mod.MOD_volatile == TRUE) {
|
|
EVAL_IS_VOLATILE (pvOut) = TRUE;
|
|
}
|
|
EVAL_PTRTYPE (pvOut) = (uchar)SetAmbiant (TRUE);
|
|
PTR_UTYPE (pvOut) = EVAL_TYP (pvIn);
|
|
}
|
|
|
|
#if 0
|
|
|
|
MTYP_t PASCAL MatchType (peval_t pv, bool_t fExact)
|
|
{
|
|
CV_typ_t index;
|
|
HTYPE hType;
|
|
int iCache;
|
|
CV_typ_t possible = T_NOTYPE;
|
|
|
|
for (iCache = 0; iCache < cCache; iCache++) {
|
|
index = Cache[iCache];
|
|
hType = THGetTypeFromIndex (EVAL_MOD (pv), index);
|
|
switch (CheckType (pv, Cache[iCache], hType, fExact)) {
|
|
case MTYP_none:
|
|
break;
|
|
|
|
case MTYP_exact:
|
|
ReorderCache (iCache);
|
|
EVAL_TYP (pv) = index;
|
|
return (MTYP_exact);
|
|
|
|
case MTYP_inexact:
|
|
if (fExact == FALSE) {
|
|
ReorderCache (iCache);
|
|
EVAL_TYP (pv) = index;
|
|
return (MTYP_inexact);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
index = CV_FIRST_NONPRIM - 1;
|
|
while ((hType = THGetTypeFromIndex (EVAL_MOD (pv), ++index)) != 0) {
|
|
switch (CheckType (pv, Cache[iCache], hType, fExact)) {
|
|
case MTYP_none:
|
|
break;
|
|
|
|
case MTYP_exact:
|
|
InsertCache (index);
|
|
EVAL_TYP (pv) = index;
|
|
return (MTYP_exact);
|
|
|
|
case MTYP_inexact:
|
|
if (fExact == FALSE) {
|
|
InsertCache (index);
|
|
EVAL_TYP (pv) = index;
|
|
return (MTYP_inexact);
|
|
}
|
|
else if (possible == T_NOTYPE) {
|
|
possible = index;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
if (possible == T_NOTYPE) {
|
|
return (MTYP_none);
|
|
}
|
|
InsertCache (possible);
|
|
EVAL_TYP (pv) = possible;
|
|
return (MTYP_inexact);
|
|
}
|
|
|
|
|
|
|
|
|
|
LOCAL void NEAR PASCAL InsertCache (CV_typ_t type)
|
|
{
|
|
int i;
|
|
|
|
if (cCache == CACHE_MAX) {
|
|
cCache--;
|
|
}
|
|
for (i = cCache; i > 0; i--) {
|
|
Cache[i] = Cache[i - 1];
|
|
}
|
|
Cache[0] = type;
|
|
cCache++;
|
|
}
|
|
|
|
|
|
|
|
|
|
LOCAL void NEAR PASCAL ReorderCache (int iCache)
|
|
{
|
|
CV_typ_t temp;
|
|
int i;
|
|
|
|
if (iCache == 0) {
|
|
return;
|
|
}
|
|
temp = Cache[iCache];
|
|
for (i = iCache; i > 0; i--) {
|
|
Cache[i] = Cache[i - 1];
|
|
}
|
|
Cache[0] = temp;
|
|
}
|
|
|
|
|
|
|
|
LOCAL MTYP_t NEAR PASCAL CheckType (peval_t pv, CV_typ_t index,
|
|
HTYPE hType, bool_t fExact)
|
|
{
|
|
char FAR *pType;
|
|
CV_modifier_t Mod;
|
|
CV_typ_t uType;
|
|
MTYP_t retval = MTYP_none;
|
|
plfPointer plfP;
|
|
|
|
if (hType == (HTYPE) NULL) {
|
|
return retval;
|
|
}
|
|
|
|
pType = (char FAR *)(&((TYPPTR)MHOmfLock (hType))->leaf);
|
|
switch (((plfEasy)pType)->leaf) {
|
|
case LF_POINTER:
|
|
plfP = (plfPointer)pType;
|
|
uType = plfP->u.utype;
|
|
if (EVAL_IS_PTR (pv)) {
|
|
// we have a pointer record and we are looking
|
|
// for a pointer. We now check the underlying types
|
|
|
|
if (PTR_UTYPE (pv) == uType) {
|
|
// the underlying types are the same. we now need
|
|
// to check the pointer modes
|
|
|
|
if ((UINT) (plfP->u.attr.ptrmode == CV_PTR_MODE_REF) !=
|
|
(UINT)EVAL_IS_REF (pv)) {
|
|
// if the reference modes are different, we do not
|
|
// have any type of a match
|
|
break;
|
|
}
|
|
if (plfP->u.attr.ptrtype == EVAL_PTRTYPE (pv)) {
|
|
// we have exact match on pointer mode
|
|
|
|
retval = MTYP_exact;
|
|
}
|
|
else if ((EVAL_PTRTYPE (pv) != CV_PTR_NEAR) ||
|
|
(plfP->u.attr.ptrtype != CV_PTR_FAR)) {
|
|
// we we do not have a far pointer that could
|
|
// be cast to a near pointer
|
|
break;
|
|
|
|
}
|
|
else {
|
|
retval = MTYP_inexact;
|
|
}
|
|
if (fExact == TRUE) {
|
|
if ((plfP->u.attr.isconst != EVAL_IS_CONST (pv)) ||
|
|
(plfP->u.attr.isvolatile != EVAL_IS_VOLATILE (pv))) {
|
|
retval = MTYP_inexact;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
// the underlying types are not the same but we
|
|
// have to check for a modifier with the proper
|
|
// underlying type, i.e. pointer to const class
|
|
|
|
if (CV_IS_PRIMITIVE (uType)) {
|
|
// the underlying type of the pointer cannot be
|
|
// a modifier
|
|
|
|
break;
|
|
}
|
|
if ((UINT) (plfP->u.attr.ptrmode == CV_PTR_MODE_REF) !=
|
|
(UINT)EVAL_IS_REF (pv)) {
|
|
// if the reference modes are different, we cannot
|
|
// have any type of a match
|
|
break;
|
|
}
|
|
if (plfP->u.attr.ptrtype != EVAL_PTRTYPE (pv)) {
|
|
// we do not have an exact match on pointer type
|
|
|
|
if (fExact == TRUE) {
|
|
// this cannot be an exact match
|
|
break;
|
|
}
|
|
else if ((EVAL_PTRTYPE (pv) != CV_PTR_NEAR) ||
|
|
(plfP->u.attr.ptrtype != CV_PTR_FAR)) {
|
|
// we we do not have a far pointer that could
|
|
// be cast to a near pointer
|
|
break;
|
|
}
|
|
}
|
|
MHOmfUnLock ((HDEP)hType);
|
|
hType = THGetTypeFromIndex (EVAL_MOD (pv), uType);
|
|
DASSERT(hType != (HTYPE) NULL);
|
|
pType = (char FAR *)(&((TYPPTR)MHOmfLock ((HDEP)hType))->leaf);
|
|
if (((plfEasy)pType)->leaf != LF_MODIFIER) {
|
|
break;
|
|
}
|
|
if ((uType = ((plfModifier)pType)->type) != T_NOTYPE) {
|
|
Mod = ((plfModifier)pType)->attr;
|
|
if (uType == PTR_UTYPE (pv)) {
|
|
if (((UINT) (Mod.MOD_const == TRUE) == (UINT)EVAL_IS_CONST (pv)) ||
|
|
((UINT) (Mod.MOD_volatile == TRUE) == (UINT)(EVAL_IS_VOLATILE (pv)))) {
|
|
retval = MTYP_exact;
|
|
}
|
|
else {
|
|
retval = MTYP_inexact;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case LF_MODIFIER:
|
|
if ((uType = ((plfModifier)pType)->type) != T_NOTYPE) {
|
|
Mod = ((plfModifier)pType)->attr;
|
|
if (uType == EVAL_TYP (pv)) {
|
|
if (((UINT) (Mod.MOD_const == TRUE) == (UINT)EVAL_IS_CONST (pv)) ||
|
|
((UINT) (Mod.MOD_volatile == TRUE) == (UINT)(EVAL_IS_VOLATILE (pv)))) {
|
|
retval = MTYP_exact;
|
|
}
|
|
else {
|
|
retval = MTYP_inexact;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
// type not interesting so skip
|
|
break;
|
|
}
|
|
if (hType != 0) {
|
|
MHOmfUnLock ((HDEP)hType);
|
|
}
|
|
return (retval);
|
|
}
|
|
|
|
|
|
|
|
/** ProtoPtr - set up a prototype of a pointer or reference node
|
|
*
|
|
* ProtoPtr (pvOut, pvIn, IsRef, Mod)
|
|
*
|
|
* Entry pvOut = pointer to protype node
|
|
* pvIn = pointer to node to prototype
|
|
* IsRef = TRUE if prototype is for a reference
|
|
* Mod = modifier type (CV_MOD_none, CV_MOD_const, CV_MOD_volatile)
|
|
*
|
|
* Exit pvOut = prototype pointer node
|
|
*
|
|
* Returns none
|
|
*/
|
|
|
|
|
|
void PASCAL ProtoPtr (peval_t pvOut, peval_t pvIn, bool_t IsRef, CV_modifier_t Mod)
|
|
{
|
|
_fmemset (pvOut, 0, sizeof (*pvOut));
|
|
EVAL_MOD (pvOut) = EVAL_MOD (pvIn);
|
|
EVAL_IS_ADDR (pvOut) = TRUE;
|
|
EVAL_IS_DPTR (pvOut) = TRUE;
|
|
if (IsRef == TRUE) {
|
|
EVAL_IS_REF (pvOut) = TRUE;
|
|
}
|
|
EVAL_IS_PTR (pvOut) = TRUE;
|
|
if (Mod.MOD_const == TRUE) {
|
|
EVAL_IS_CONST (pvOut) = TRUE;
|
|
}
|
|
else if (Mod.MOD_volatile == TRUE) {
|
|
EVAL_IS_VOLATILE (pvOut) = TRUE;
|
|
}
|
|
EVAL_PTRTYPE (pvOut) = (uchar)SetAmbiant (TRUE);
|
|
PTR_UTYPE (pvOut) = EVAL_TYP (pvIn);
|
|
}
|
|
|
|
|
|
#endif
|
|
|
|
bool_t PASCAL LoadSymVal (peval_t pv)
|
|
{
|
|
long cbVal;
|
|
SHREG reg;
|
|
ADDR addr;
|
|
|
|
if (EVAL_IS_CLASS (pv)) {
|
|
return (FALSE);
|
|
}
|
|
if (EVAL_STATE (pv) != EV_lvalue) {
|
|
// If not an lvalue, value has already been loaded
|
|
return (TRUE);
|
|
}
|
|
_fmemset (&EVAL_VAL (pv), 0, sizeof (EVAL_VAL (pv)));
|
|
|
|
ResolveAddr( pv );
|
|
|
|
if (EVAL_IS_ADDR (pv) && !EVAL_IS_REG (pv)) {
|
|
|
|
// we only Load the Address of PTRs that are not enregistered
|
|
return (LoadAddress (pv));
|
|
}
|
|
|
|
if (EVAL_IS_REG (pv)) {
|
|
if (EVAL_IS_PTR(pv)) {
|
|
// enregistered PTR, PTR_REG instead
|
|
|
|
reg.hReg = PTR_REG_IREG (pv);
|
|
PTR_REG_IREG (pv) = CV_REG_NONE;
|
|
}
|
|
else {
|
|
reg.hReg = EVAL_REG (pv);
|
|
}
|
|
if (GetReg (®, pCxt) == NULL) {
|
|
pExState->err_num = ERR_REGNOTAVAIL;
|
|
return (FALSE);
|
|
}
|
|
|
|
#if defined (TARGET_ALPHA) || defined (TARGET_PPC)
|
|
if (CV_IS_PRIMITIVE ( EVAL_TYP (pv) ) &&
|
|
CV_TYP_IS_REAL ( EVAL_TYP (pv) ) ) {
|
|
//
|
|
// ALPHA & PPC floating point registers have only one format:
|
|
// In the context structure, fp's are doubles. If we
|
|
// want a float (32bits), convert here.
|
|
//
|
|
|
|
union {
|
|
float f;
|
|
double d;
|
|
unsigned long l[2];
|
|
} u;
|
|
|
|
//
|
|
// The shreg is unaligned, so move to a local aligned struct
|
|
//
|
|
|
|
u.l[0] = reg.Byte4;
|
|
u.l[1] = reg.Byte4High;
|
|
|
|
switch (EVAL_TYP (pv )) {
|
|
case T_REAL32:
|
|
|
|
//
|
|
// We transfer the double to a floating point value
|
|
//
|
|
|
|
u.f = (float)u.d;
|
|
EVAL_FLOAT (pv) = u.f;
|
|
break;
|
|
|
|
case T_REAL64:
|
|
|
|
EVAL_DOUBLE (pv) = u.d;
|
|
break;
|
|
|
|
case T_REAL48:
|
|
case T_REAL80:
|
|
default:
|
|
|
|
//
|
|
// no other FP types supported on Alpha
|
|
//
|
|
|
|
DASSERT(FALSE);
|
|
}
|
|
} else
|
|
#endif // ALPHA || PPC
|
|
|
|
if (CV_IS_PRIMITIVE ( EVAL_TYP (pv) ) ) {
|
|
|
|
//
|
|
// notenote: this is dependent on byte ordering.
|
|
// Won't work on a big-endian machine.
|
|
//
|
|
|
|
cbVal = TypeSizePrim(EVAL_TYP (pv));
|
|
memcpy(&EVAL_CHAR (pv), ®.Byte1, cbVal);
|
|
|
|
} else if (EVAL_IS_PTR (pv) ) {
|
|
|
|
//
|
|
// Handle pointers to UserDefinedTypes.
|
|
// notenote - this isn't right for WOW,
|
|
// where pointers can be different lengths.
|
|
//
|
|
|
|
memcpy(&EVAL_CHAR (pv), ®.Byte1, sizeof (long));
|
|
|
|
} else {
|
|
|
|
//
|
|
// Non-primitive types in registers not
|
|
// supported in first release
|
|
//
|
|
|
|
EVAL_LONG (pv) = 0;
|
|
DASSERT(FALSE);
|
|
}
|
|
|
|
EVAL_IS_REG (pv) = FALSE;
|
|
if (EVAL_IS_PTR (pv)) {
|
|
EVAL_PTR_EMI (pv) = EVAL_SYM_EMI (pv);
|
|
if (EVAL_IS_BASED (pv)) {
|
|
EVAL_PTR_SEG (pv) = 0;
|
|
}
|
|
else {
|
|
if (EVAL_IS_DPTR (pv)) {
|
|
EVAL_PTR_SEG (pv) = pExState->frame.DS; //M00FLAT32
|
|
}
|
|
else {
|
|
#ifdef TARGET_I386
|
|
reg.hReg = CV_REG_CS;
|
|
GetReg (®, pCxt);
|
|
EVAL_PTR_SEG (pv) = reg.Byte2;
|
|
#else
|
|
EVAL_PTR_SEG (pv) = 0;
|
|
#endif
|
|
}
|
|
}
|
|
ADDR_IS_OFF32 ( EVAL_PTR (pv) ) = TRUE;
|
|
ADDR_IS_FLAT ( EVAL_PTR (pv) ) = TRUE;
|
|
ADDR_IS_LI ( EVAL_PTR (pv) ) = FALSE;
|
|
}
|
|
}
|
|
|
|
else {
|
|
addr = EVAL_SYM (pv);
|
|
if (ADDR_IS_LI (addr)) {
|
|
//M00KLUDGE - should be moved to OSDEBUG
|
|
SHFixupAddr (&addr);
|
|
}
|
|
// Try to fetch contents of address
|
|
if (EVAL_IS_CLASS (pv)) {
|
|
pExState->err_num = ERR_STRUCT;
|
|
return (FALSE);
|
|
}
|
|
|
|
if (EVAL_IS_BITF (pv)) {
|
|
cbVal = (BITF_LEN (pv) + (BITF_POS(pv) & 0x3f) + 7 ) /8;
|
|
}
|
|
else if ((cbVal = TypeSize (pv)) > sizeof (EVAL_VAL (pv)) || cbVal < 0) {
|
|
pExState->err_num = ERR_BADOMF;
|
|
return (FALSE);
|
|
}
|
|
if ((cbVal != 0) &&
|
|
(GetDebuggeeBytes (addr, (ushort)cbVal, (char FAR *)&EVAL_VAL (pv), EVAL_TYP(pv)) != (UINT)cbVal)) {
|
|
return (FALSE);
|
|
}
|
|
}
|
|
|
|
/* Mark node as loaded */
|
|
|
|
EVAL_STATE (pv) = EV_rvalue;
|
|
if (EVAL_IS_BITF (pv)) {
|
|
return (EBitfield (pv));
|
|
}
|
|
else {
|
|
return (TRUE);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
LOCAL bool_t NEAR PASCAL
|
|
LoadAddress (
|
|
peval_t pv
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine takes an address and loads the memory pointed to.
|
|
|
|
Arguments:
|
|
|
|
pv - Suppiles value to load contents of
|
|
|
|
Return Value:
|
|
|
|
TRUE if pointer loaded and FALSE if error occured
|
|
|
|
--*/
|
|
|
|
{
|
|
SHREG reg;
|
|
ushort dummy[2];
|
|
ADDR addr;
|
|
|
|
if (EVAL_IS_FCN (pv) || EVAL_IS_ARRAY (pv)) {
|
|
/*
|
|
* the reference of function or array names implies addresses
|
|
* not values. Therefore, we return the address of the symbol
|
|
* as a pointer
|
|
*/
|
|
|
|
EVAL_PTR (pv) = EVAL_SYM (pv);
|
|
if (ADDR_IS_LI (EVAL_PTR(pv))) {
|
|
SHFixupAddr (&EVAL_PTR(pv));
|
|
}
|
|
|
|
} else {
|
|
if (EVAL_IS_NPTR (pv) || EVAL_IS_BASED (pv) || EVAL_IS_NPTR32 (pv)) {
|
|
/*
|
|
* If near/based pointer, load the offset from either the
|
|
* register or memory. Then set the segment portion to zero
|
|
* if a based pointer. If the pointer is a pointer to data, set
|
|
* the segment to DS. Otherwise, set the segment to CS
|
|
* NOTENOTE jimsch - what does this do with data in the code segment
|
|
*/
|
|
|
|
if (EVAL_IS_REG (pv)) {
|
|
reg.hReg = EVAL_REG (pv);
|
|
GetReg (®, pCxt);
|
|
EVAL_PTR_OFF (pv) = reg.Byte2;
|
|
} else {
|
|
addr = EVAL_SYM (pv);
|
|
if (ADDR_IS_LI (addr)) {
|
|
SHFixupAddr (&addr);
|
|
}
|
|
|
|
if (EVAL_IS_NPTR32(pv)) {
|
|
if (GetDebuggeeBytes (addr, sizeof (CV_off32_t),
|
|
(char FAR *)&EVAL_PTR_OFF (pv),
|
|
T_ULONG) != sizeof (CV_off32_t)) {
|
|
return(FALSE);
|
|
}
|
|
} else {
|
|
if (GetDebuggeeBytes (addr, sizeof (CV_off16_t),
|
|
(char FAR *)&EVAL_PTR_OFF (pv),
|
|
T_USHORT) != sizeof (CV_off16_t)) {
|
|
return(FALSE);
|
|
}
|
|
}
|
|
}
|
|
EVAL_PTR_EMI (pv) = 0;
|
|
ADDR_IS_FLAT( EVAL_PTR ( pv ) ) = ADDR_IS_FLAT(addr);
|
|
|
|
if (EVAL_IS_NPTR32( pv )) {
|
|
ADDR_IS_OFF32(EVAL_PTR(pv)) = TRUE;
|
|
} else {
|
|
ADDR_IS_OFF32( EVAL_PTR( pv)) = FALSE;
|
|
}
|
|
|
|
if (EVAL_IS_BASED (pv)) {
|
|
EVAL_PTR_SEG (pv) = 0;
|
|
} else {
|
|
if (EVAL_IS_DPTR (pv)) {
|
|
EVAL_PTR_SEG (pv) = pExState->frame.DS;
|
|
} else {
|
|
reg.hReg = CV_REG_CS;
|
|
GetReg (®, pCxt);
|
|
EVAL_PTR_SEG (pv) = reg.Byte2;
|
|
}
|
|
}
|
|
} else {
|
|
/*
|
|
* Must be a FAR_16 pointer -- FAR_32 pointers don't exists.
|
|
*/
|
|
|
|
addr = EVAL_SYM (pv);
|
|
if (ADDR_IS_LI (addr)) {
|
|
SHFixupAddr (&addr);
|
|
}
|
|
DASSERT(!EVAL_IS_FPTR32(pv));
|
|
if (GetDebuggeeBytes (addr, 4, (char FAR *)dummy, EVAL_TYP(pv)) != 4) {
|
|
/*
|
|
* load the value of a far pointer from memory
|
|
*/
|
|
return (FALSE);
|
|
}
|
|
else {
|
|
/*
|
|
* shuffle the bits around
|
|
*/
|
|
|
|
EVAL_PTR_OFF (pv) = (UOFFSET)dummy[0];
|
|
EVAL_PTR_SEG (pv) = (_segment)dummy[1];
|
|
EVAL_PTR_EMI (pv) = EVAL_SYM_EMI (pv);
|
|
ADDR_IS_LI (EVAL_PTR (pv)) = FALSE;
|
|
ADDR_IS_FLAT (EVAL_PTR (pv)) = FALSE;
|
|
ADDR_IS_OFF32( EVAL_PTR( pv)) = FALSE;
|
|
}
|
|
}
|
|
}
|
|
EVAL_STATE (pv) = EV_rvalue;
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
* Do final evaluation of a bitfield stack element.
|
|
*/
|
|
|
|
|
|
LOCAL bool_t NEAR PASCAL EBitfield (peval_t pv)
|
|
{
|
|
unsigned short cBits; /* Number of bits in field */
|
|
unsigned int pos; /* Bit position of field */
|
|
|
|
// Shift right by bit position, then mask off extraneous bits.
|
|
// for signed bitfields, shift field left so high bit of field is
|
|
// in sign bit. Then shift right (signed) to get sign extended
|
|
// The shift count is limited to 5 bits to emulate the hardware
|
|
|
|
pos = BITF_POS (pv) & 0x1f;
|
|
cBits = BITF_LEN (pv);
|
|
|
|
// set the type of the node to the type of the underlying bit field
|
|
// note that this will cause subsequent reloads of the node value
|
|
// to load the containing word and not extract the bitfield. This is
|
|
// how the assign op manage to not destroy the other bitfields in the
|
|
// location
|
|
|
|
SetNodeType (pv, BITF_UTYPE (pv));
|
|
switch (EVAL_TYP (pv)) {
|
|
case T_CHAR:
|
|
case T_RCHAR:
|
|
DASSERT (cBits <= 8);
|
|
EVAL_CHAR (pv) <<= (8 - cBits - pos);
|
|
EVAL_CHAR (pv) >>= (8 - cBits);
|
|
break;
|
|
|
|
case T_UCHAR:
|
|
DASSERT (cBits <= 8);
|
|
EVAL_UCHAR (pv) >>= pos;
|
|
EVAL_UCHAR (pv) &= (1 << cBits) - 1;
|
|
break;
|
|
|
|
case T_SHORT:
|
|
case T_INT2:
|
|
DASSERT (cBits <= 16);
|
|
EVAL_SHORT (pv) <<= (16 - cBits - pos);
|
|
EVAL_SHORT (pv) >>= (16 - cBits);
|
|
break;
|
|
|
|
case T_USHORT:
|
|
case T_UINT2:
|
|
DASSERT (cBits <= 16);
|
|
EVAL_USHORT (pv) >>= pos;
|
|
EVAL_USHORT (pv) &= (1 << cBits) - 1;
|
|
break;
|
|
|
|
case T_LONG:
|
|
case T_INT4:
|
|
DASSERT (cBits <= 32);
|
|
EVAL_LONG (pv) <<= (32 - cBits - pos);
|
|
EVAL_LONG (pv) >>= (32 - cBits);
|
|
break;
|
|
|
|
case T_ULONG:
|
|
case T_UINT4:
|
|
DASSERT (cBits <= 32);
|
|
EVAL_ULONG (pv) >>= pos;
|
|
EVAL_ULONG (pv) &= (1L << cBits) - 1;
|
|
break;
|
|
|
|
case T_QUAD:
|
|
case T_INT8:
|
|
DASSERT (cBits <= 64);
|
|
//
|
|
// reset pos because it is truncated to five bits above
|
|
//
|
|
pos = BITF_POS(pv) & 0x3f;
|
|
(EVAL_QUAD(pv)).QuadPart = (EVAL_QUAD(pv)).QuadPart << (64 - cBits - pos);
|
|
(EVAL_QUAD(pv)).QuadPart = (EVAL_QUAD(pv)).QuadPart >> (64 - cBits);
|
|
break;
|
|
|
|
case T_UQUAD:
|
|
case T_UINT8:
|
|
{
|
|
//
|
|
// set up a mask of the wanted bits, right shifted
|
|
// (reset pos because it is truncated to five bits above)
|
|
//
|
|
|
|
LARGE_INTEGER mask_q;
|
|
|
|
DASSERT (cBits <= 64);
|
|
|
|
pos = BITF_POS (pv) & 0x3f;
|
|
mask_q.QuadPart = (1 << cBits) - 1;
|
|
|
|
//
|
|
// extract the bits
|
|
//
|
|
(EVAL_QUAD(pv)).QuadPart = (EVAL_QUAD(pv)).QuadPart >> pos;
|
|
(EVAL_QUAD(pv)).QuadPart &= mask_q.QuadPart;
|
|
break;
|
|
}
|
|
default:
|
|
DASSERT (FALSE);
|
|
return (FALSE);
|
|
}
|
|
return(TRUE);
|
|
}
|