@@ -1053,6 +1053,93 @@ bool ActionConstantPtr::checkCopy(PcodeOp *op,Funcdata &data)
10531053 return data.getArch ()->infer_pointers ;
10541054}
10551055
1056+ SymbolEntry *getSymbolEntry (Address &rampoint, bool &needexacthit, Funcdata &data)
1057+ {
1058+ if (rampoint.isInvalid ())
1059+ return (SymbolEntry *)0 ;
1060+ // Since we are looking for a global address
1061+ // Assume it is address tied and use empty usepoint
1062+ SymbolEntry *entry = data.getScopeLocal ()->getParent ()->queryContainer (rampoint, 1 , Address ());
1063+ if (entry != (SymbolEntry *)0 )
1064+ {
1065+ Datatype *ptrType = entry->getSymbol ()->getType ();
1066+ if (ptrType->getMetatype () == TYPE_ARRAY)
1067+ {
1068+ Datatype *ct = ((TypeArray *)ptrType)->getBase ();
1069+ // In the special case of strings (character arrays) we allow the constant pointer to
1070+ // refer to the middle of the string
1071+ if (ct->isCharPrint ())
1072+ needexacthit = false ;
1073+ }
1074+ if (needexacthit && entry->getAddr () != rampoint)
1075+ return (SymbolEntry *)0 ;
1076+ }
1077+
1078+ return entry;
1079+ }
1080+
1081+ int8 isEntryMatch (SymbolEntry *entry, Address &rampoint, bool &isArray) {
1082+ int8 size = 0 ;
1083+ isArray = false ;
1084+ if (entry != 0 )
1085+ {
1086+ // If we found data at the specified address, use its size
1087+ size = entry->getSize ();
1088+ auto dt = entry->getSizedType (Address (rampoint.getSpace (), 0 ), size);
1089+ if (dt != 0 && dt->getMetatype () == TYPE_ARRAY)
1090+ {
1091+ int8 tmp;
1092+ isArray = true ;
1093+ size = dt->getSubType (0 , &tmp)->getSize ();
1094+ }
1095+ }
1096+
1097+ return size;
1098+ }
1099+
1100+ // / \brief Recursively search for additive constants and multiplicative constants
1101+ // /
1102+ // / Walking backward from the given Varnode, search for constants being added in and return
1103+ // / the sum of all the constants. Additionally pass back the biggest constant coefficient, for any term
1104+ // / formed with INT_MULT.
1105+ // / \param vn is the given root Varnode of the additive tree
1106+ // / \param multiplier will hold the biggest constant multiplier or 0, if no multiplier is present
1107+ // / \param maxLevel is the maximum depth to search in the tree
1108+ // / \return the sum of all constants in the additive expression
1109+ int8 ActionConstantPtr::getConstOffsetBack (Varnode *vn,int8 &multiplier,int4 maxLevel)
1110+
1111+ {
1112+ multiplier = 0 ;
1113+ int8 submultiplier;
1114+ if (vn->isConstant ())
1115+ return vn->getOffset ();
1116+ if (!vn->isWritten ())
1117+ return 0 ;
1118+ maxLevel -= 1 ;
1119+ if (maxLevel < 0 )
1120+ return 0 ;
1121+ PcodeOp *op = vn->getDef ();
1122+ OpCode opc = op->code ();
1123+ int8 retval = 0 ;
1124+ if (opc == CPUI_INT_ADD) {
1125+ retval += getConstOffsetBack (op->getIn (0 ),submultiplier,maxLevel);
1126+ if (submultiplier > multiplier)
1127+ multiplier = submultiplier;
1128+ retval += getConstOffsetBack (op->getIn (1 ), submultiplier, maxLevel);
1129+ if (submultiplier > multiplier)
1130+ multiplier = submultiplier;
1131+ }
1132+ else if (opc == CPUI_INT_MULT) {
1133+ Varnode *cvn = op->getIn (1 );
1134+ if (!cvn->isConstant ()) return 0 ;
1135+ multiplier = cvn->getOffset ();
1136+ getConstOffsetBack (op->getIn (0 ), submultiplier, maxLevel);
1137+ if (submultiplier > 0 )
1138+ multiplier *= submultiplier; // Only contribute to the multiplier
1139+ }
1140+ return retval;
1141+ }
1142+
10561143// / \brief Determine if given Varnode might be a pointer constant.
10571144// /
10581145// / If it is a pointer, return the symbol it points to, or NULL otherwise. If it is determined
@@ -1122,10 +1209,10 @@ SymbolEntry *ActionConstantPtr::isPointer(AddrSpace *spc,Varnode *vn,PcodeOp *op
11221209 if (op->getIn (1 -slot)->getTypeReadFacing (op)->getMetatype ()==TYPE_PTR)
11231210 return (SymbolEntry *)0 ; // If so, we are not a pointer
11241211 // FIXME: need to fully explore additive tree
1125- needexacthit = false ;
11261212 }
11271213 else if (!glb->infer_pointers )
11281214 return (SymbolEntry *)0 ;
1215+ needexacthit = false ;
11291216 break ;
11301217 case CPUI_STORE:
11311218 if (slot != 2 )
@@ -1145,22 +1232,28 @@ SymbolEntry *ActionConstantPtr::isPointer(AddrSpace *spc,Varnode *vn,PcodeOp *op
11451232 rampoint = glb->resolveConstant (spc,vn->getOffset (),vn->getSize (),op->getAddr (),fullEncoding);
11461233 }
11471234
1148- if (rampoint.isInvalid ()) return (SymbolEntry *)0 ;
1149- // Since we are looking for a global address
1150- // Assume it is address tied and use empty usepoint
1151- SymbolEntry *entry = data.getScopeLocal ()->getParent ()->queryContainer (rampoint,1 ,Address ());
1152- if (entry != (SymbolEntry *)0 ) {
1153- Datatype *ptrType = entry->getSymbol ()->getType ();
1154- if (ptrType->getMetatype () == TYPE_ARRAY) {
1155- Datatype *ct = ((TypeArray *)ptrType)->getBase ();
1156- // In the special case of strings (character arrays) we allow the constant pointer to
1157- // refer to the middle of the string
1158- if (ct->isCharPrint ())
1159- needexacthit = false ;
1235+ bool isArray = false ;
1236+ SymbolEntry *entry = getSymbolEntry (rampoint, needexacthit, data);
1237+ int8 size = isEntryMatch (entry, rampoint, isArray);
1238+
1239+ // Check if pointer is pointing at correctly size data
1240+ int8 mult;
1241+ getConstOffsetBack (op->getIn (0 ), mult, 8 );
1242+ if (size == 1 ) {
1243+ // No multiply present for byte arrays
1244+ mult = 1 ;
1245+ }
1246+
1247+ if (mult != size || !isArray)
1248+ {
1249+ // Check for 1-indexing
1250+ Address new_rampoint = rampoint + mult;
1251+ SymbolEntry *tmp_entry = getSymbolEntry (new_rampoint, needexacthit, data);
1252+ if (tmp_entry != 0 && mult == isEntryMatch (tmp_entry, new_rampoint, isArray) && isArray) {
1253+ entry = tmp_entry;
11601254 }
1161- if (needexacthit && entry->getAddr () != rampoint)
1162- return (SymbolEntry *)0 ;
11631255 }
1256+
11641257 return entry;
11651258}
11661259
0 commit comments