Skip to content

Commit 3c7af07

Browse files
8586 Correctly decompile 1 indexing for globals
1 parent ccefcc1 commit 3c7af07

File tree

3 files changed

+132
-15
lines changed

3 files changed

+132
-15
lines changed

Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.cc

Lines changed: 108 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.hh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ class ActionConstantPtr : public Action {
192192
static bool checkCopy(PcodeOp *op,Funcdata &data);
193193
static SymbolEntry *isPointer(AddrSpace *spc,Varnode *vn,PcodeOp *op,int4 slot,
194194
Address &rampoint,uintb &fullEncoding,Funcdata &data);
195+
static int8 getConstOffsetBack(Varnode *vn,int8 &multiplier,int4 maxLevel);
195196
public:
196197
ActionConstantPtr(const string &g) : Action(0,"constantptr",g) {} ///< Constructor
197198
virtual void reset(Funcdata &data) { localcount = 0; }

Ghidra/Features/Decompiler/src/decompile/cpp/funcdata.cc

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,29 @@ void Funcdata::spacebaseConstant(PcodeOp *op,int4 slot,SymbolEntry *entry,const
418418
typelock = false;
419419
outvn->updateType(ptrentrytype,typelock,false);
420420
if (extra != 0) {
421+
if ((intb)extra < 0) {
422+
// Negative "extra" is likely an array offset
423+
Datatype *dt = entry->getSizedType(Address(rampoint.getSpace(), 0), entry->getSize());
424+
if (dt != 0 && dt->getMetatype() == TYPE_ARRAY)
425+
{
426+
int8 tmp;
427+
int8 datasize = dt->getSubType(0, &tmp)->getSize();
428+
extra += datasize;
429+
430+
// Insert a negative add of Type's size
431+
// and use the remainder (abs(type_size % extra) as the real extra
432+
// This allows the negative value to be collapsed into a negative array offset later
433+
PcodeOp *negOp = newOp(2,op->getAddr());
434+
opSetOpcode(negOp,CPUI_INT_ADD);
435+
newUniqueOut(sz,negOp);
436+
opInsertBefore(negOp,op);
437+
Varnode *negconst = newConstant(sz, -datasize);
438+
negconst->setPtrCheck();
439+
opSetInput(negOp,outvn,0);
440+
opSetInput(negOp,negconst,1);
441+
outvn = negOp->getOut();
442+
}
443+
}
421444
if (extraOp == (PcodeOp *)0) {
422445
extraOp = newOp(2,op->getAddr());
423446
opSetOpcode(extraOp,CPUI_INT_ADD);

0 commit comments

Comments
 (0)