mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 17:59:46 +02:00
GP-4095 Check for primitive data-type when triggering double precision
This commit is contained in:
parent
1b813ed33e
commit
60cf8311f1
8 changed files with 76 additions and 19 deletions
|
@ -1667,8 +1667,8 @@ int4 ActionParamDouble::apply(Funcdata &data)
|
|||
for(int4 i=0;i<numparams;++i) {
|
||||
ProtoParameter *param = fp.getParam(i);
|
||||
Datatype *tp = param->getType();
|
||||
type_metatype mt = tp->getMetatype();
|
||||
if ((mt==TYPE_ARRAY)||(mt==TYPE_STRUCT)) continue; // Not double precision objects
|
||||
if (!tp->isPrimitiveWhole())
|
||||
continue; // Not double precision objects
|
||||
Varnode *vn = data.findVarnodeInput(tp->getSize(),param->getAddress());
|
||||
if (vn == (Varnode *)0) continue;
|
||||
if (vn->getSize() < minDoubleSize) continue;
|
||||
|
|
|
@ -693,6 +693,14 @@ PcodeOp *SplitVarnode::findOutExist(void)
|
|||
return findEarliestSplitPoint();
|
||||
}
|
||||
|
||||
/// If the logical whole is a constant and is too big to be represented internally return \b true.
|
||||
/// \return \b true if \b this is a constant and too big
|
||||
bool SplitVarnode::exceedsConstPrecision(void) const
|
||||
|
||||
{
|
||||
return isConstant() && (wholesize > sizeof(uintb));
|
||||
}
|
||||
|
||||
/// \brief Check if the values in the given Varnodes differ by the given size
|
||||
///
|
||||
/// Return \b true, if the (possibly dynamic) value represented by the given \b vn1 plus \b size1
|
||||
|
@ -1543,6 +1551,8 @@ bool AddForm::applyRule(SplitVarnode &i,PcodeOp *op,bool workishi,Funcdata &data
|
|||
return false;
|
||||
|
||||
indoub.initPartial(in.getSize(),lo2,hi2);
|
||||
if (indoub.exceedsConstPrecision())
|
||||
return false;
|
||||
outdoub.initPartial(in.getSize(),reslo,reshi);
|
||||
existop = SplitVarnode::prepareBinaryOp(outdoub,in,indoub);
|
||||
if (existop == (PcodeOp *)0)
|
||||
|
@ -1636,6 +1646,8 @@ bool SubForm::applyRule(SplitVarnode &i,PcodeOp *op,bool workishi,Funcdata &data
|
|||
return false;
|
||||
|
||||
indoub.initPartial(in.getSize(),lo2,hi2);
|
||||
if (indoub.exceedsConstPrecision())
|
||||
return false;
|
||||
outdoub.initPartial(in.getSize(),reslo,reshi);
|
||||
existop = SplitVarnode::prepareBinaryOp(outdoub,in,indoub);
|
||||
if (existop == (PcodeOp *)0)
|
||||
|
@ -1757,6 +1769,8 @@ bool LogicalForm::applyRule(SplitVarnode &i,PcodeOp *lop,bool workishi,Funcdata
|
|||
|
||||
outdoub.initPartial(in.getSize(),loop->getOut(),hiop->getOut());
|
||||
indoub.initPartial(in.getSize(),lo2,hi2);
|
||||
if (indoub.exceedsConstPrecision())
|
||||
return false;
|
||||
existop = SplitVarnode::prepareBinaryOp(outdoub,in,indoub);
|
||||
if (existop == (PcodeOp *)0)
|
||||
return false;
|
||||
|
@ -1817,6 +1831,8 @@ bool Equal1Form::applyRule(SplitVarnode &i,PcodeOp *hop,bool workishi,Funcdata &
|
|||
++iter3;
|
||||
|
||||
in2.initPartial(in1.getSize(),lo2,hi2);
|
||||
if (in2.exceedsConstPrecision())
|
||||
continue;
|
||||
|
||||
if ((hibool->code() == CPUI_CBRANCH)&&(lobool->code()==CPUI_CBRANCH)) {
|
||||
// Branching form of the equal operation
|
||||
|
@ -1958,10 +1974,12 @@ bool Equal2Form::applyRule(SplitVarnode &i,PcodeOp *op,bool workishi,Funcdata &d
|
|||
hixor = (PcodeOp *)0;
|
||||
hi2 = (Varnode *)0;
|
||||
if (fillOutFromOr(data)) {
|
||||
if (!param2.exceedsConstPrecision()) {
|
||||
SplitVarnode::replaceBoolOp(data,equalop,in,param2,equalop->code());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else { // We see an XOR
|
||||
hixor = op;
|
||||
xorhislot = hixor->getSlot(hi1);
|
||||
|
@ -1976,11 +1994,13 @@ bool Equal2Form::applyRule(SplitVarnode &i,PcodeOp *op,bool workishi,Funcdata &d
|
|||
if (orop->code() != CPUI_INT_OR) continue;
|
||||
orhislot = orop->getSlot(vn);
|
||||
if (fillOutFromOr(data)) {
|
||||
if (!param2.exceedsConstPrecision()) {
|
||||
SplitVarnode::replaceBoolOp(data,equalop,in,param2,equalop->code());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -2020,6 +2040,8 @@ bool Equal3Form::applyRule(SplitVarnode &i,PcodeOp *op,bool workishi,Funcdata &d
|
|||
return false;
|
||||
|
||||
SplitVarnode in2(in.getSize(),calc_mask(in.getSize())); // Create the -1 value
|
||||
if (in2.exceedsConstPrecision())
|
||||
return false;
|
||||
if (!SplitVarnode::prepareBoolOp(in,in2,compareop)) return false;
|
||||
SplitVarnode::replaceBoolOp(data,compareop,in,in2,compareop->code());
|
||||
return true;
|
||||
|
@ -2483,6 +2505,8 @@ bool LessThreeWay::applyRule(SplitVarnode &i,PcodeOp *loop,bool workishi,Funcdat
|
|||
if (!mapFromLow(loop)) return false;
|
||||
bool res = testReplace();
|
||||
if (res) {
|
||||
if (in2.exceedsConstPrecision())
|
||||
return false;
|
||||
if (hislot==0)
|
||||
SplitVarnode::createBoolOp(data,hilessbool,in,in2,finalopc);
|
||||
else
|
||||
|
@ -2527,6 +2551,8 @@ bool LessConstForm::applyRule(SplitVarnode &i,PcodeOp *op,bool workishi,Funcdata
|
|||
if (desc->code() != CPUI_CBRANCH) return false;
|
||||
|
||||
constin.initPartial(in.getSize(),val);
|
||||
if (constin.exceedsConstPrecision())
|
||||
return false;
|
||||
|
||||
if (inslot==0) {
|
||||
if (SplitVarnode::prepareBoolOp(in,constin,op)) {
|
||||
|
@ -2967,6 +2993,8 @@ bool MultForm::replace(Funcdata &data)
|
|||
{ // We have matched a double precision multiply, now transform to logical variables
|
||||
outdoub.initPartial(in.getSize(),reslo,reshi);
|
||||
in2.initPartial(in.getSize(),lo2,hi2);
|
||||
if (in2.exceedsConstPrecision())
|
||||
return false;
|
||||
existop = SplitVarnode::prepareBinaryOp(outdoub,in,in2);
|
||||
if (existop == (PcodeOp *)0)
|
||||
return false;
|
||||
|
@ -3147,6 +3175,10 @@ int4 RuleDoubleIn::attemptMarking(Funcdata &data,Varnode *vn,PcodeOp *subpieceOp
|
|||
|
||||
{
|
||||
Varnode *whole = subpieceOp->getIn(0);
|
||||
if (whole->isTypeLock()) {
|
||||
if (!whole->getType()->isPrimitiveWhole())
|
||||
return 0; // Don't mark for double precision if not a primitive type
|
||||
}
|
||||
int4 offset = (int4)subpieceOp->getIn(1)->getOffset();
|
||||
if (offset != vn->getSize()) return 0;
|
||||
if (offset * 2 != whole->getSize()) return 0; // Truncate exactly half
|
||||
|
|
|
@ -70,6 +70,7 @@ public:
|
|||
void buildHiFromWhole(Funcdata &data); ///< Rebuild the most significant piece as a CPUI_SUBPIECE of the \b whole
|
||||
PcodeOp *findEarliestSplitPoint(void); ///< Find the earliest definition point of the \b lo and \b hi pieces
|
||||
PcodeOp *findOutExist(void); ///< Find the point at which the output \b whole must exist
|
||||
bool exceedsConstPrecision(void) const; ///< Check if \b this is a constant that exceeds precision limits
|
||||
static bool adjacentOffsets(Varnode *vn1,Varnode *vn2,uintb size1);
|
||||
static bool testContiguousPointers(PcodeOp *most,PcodeOp *least,PcodeOp *&first,PcodeOp *&second,AddrSpace *&spc);
|
||||
static bool isAddrTiedContiguous(Varnode *lo,Varnode *hi,Address &res);
|
||||
|
|
|
@ -2065,11 +2065,9 @@ void Heritage::splitJoinRead(Varnode *vn,JoinRecord *joinrec)
|
|||
|
||||
{
|
||||
PcodeOp *op = vn->loneDescend(); // vn isFree, so loneDescend must be non-null
|
||||
bool preventConstCollapse = false;
|
||||
bool isPrimitive = true;
|
||||
if (vn->isTypeLock()) {
|
||||
type_metatype meta = vn->getType()->getMetatype();
|
||||
if (meta == TYPE_STRUCT || meta == TYPE_ARRAY)
|
||||
preventConstCollapse = true;
|
||||
isPrimitive = vn->getType()->isPrimitiveWhole();
|
||||
}
|
||||
|
||||
vector<Varnode *> lastcombo;
|
||||
|
@ -2090,10 +2088,13 @@ void Heritage::splitJoinRead(Varnode *vn,JoinRecord *joinrec)
|
|||
fd->opSetInput(concat,mosthalf,0);
|
||||
fd->opSetInput(concat,leasthalf,1);
|
||||
fd->opInsertBefore(concat,op);
|
||||
if (preventConstCollapse)
|
||||
fd->opMarkNoCollapse(concat);
|
||||
if (isPrimitive) {
|
||||
mosthalf->setPrecisHi(); // Set precision flags to trigger "double precision" rules
|
||||
leasthalf->setPrecisLo();
|
||||
}
|
||||
else {
|
||||
fd->opMarkNoCollapse(concat);
|
||||
}
|
||||
op = concat; // Keep -op- as the earliest op in the concatenation construction
|
||||
}
|
||||
|
||||
|
@ -2118,6 +2119,9 @@ void Heritage::splitJoinWrite(Varnode *vn,JoinRecord *joinrec)
|
|||
{
|
||||
PcodeOp *op = vn->getDef(); // vn cannot be free, either it has def, or it is input
|
||||
BlockBasic *bb = (BlockBasic *)fd->getBasicBlocks().getBlock(0);
|
||||
bool isPrimitive = true;
|
||||
if (vn->isTypeLock())
|
||||
isPrimitive = vn->getType()->isPrimitiveWhole();
|
||||
|
||||
vector<Varnode *> lastcombo;
|
||||
vector<Varnode *> nextlev;
|
||||
|
@ -2151,8 +2155,10 @@ void Heritage::splitJoinWrite(Varnode *vn,JoinRecord *joinrec)
|
|||
fd->opSetInput(split,curvn,0);
|
||||
fd->opSetInput(split,fd->newConstant(4,0),1);
|
||||
fd->opInsertAfter(split,op);
|
||||
if (isPrimitive) {
|
||||
mosthalf->setPrecisHi(); // Make sure we set the precision flags to trigger "double precision" rules
|
||||
leasthalf->setPrecisLo();
|
||||
}
|
||||
op = split; // Keep -op- as the latest op in the split construction
|
||||
}
|
||||
|
||||
|
|
|
@ -337,7 +337,7 @@ void DatatypeMatchFilter::decode(Decoder &decoder)
|
|||
///
|
||||
/// Allocate the action object corresponding to the element and configure it.
|
||||
/// If the next element is not an action, throw an exception.
|
||||
/// \param parser is the stream decoder
|
||||
/// \param decoder is the stream decoder
|
||||
/// \param res is the resource set for the new action
|
||||
/// \return the new action
|
||||
AssignAction *AssignAction::decodeAction(Decoder &decoder,const ParamListStandard *res)
|
||||
|
@ -377,7 +377,7 @@ AssignAction *AssignAction::decodeAction(Decoder &decoder,const ParamListStandar
|
|||
///
|
||||
/// Allocate the sideeffect object corresponding to the element and configure it.
|
||||
/// If the next element is not a sideeffect, throw an exception.
|
||||
/// \param parser is the stream decoder
|
||||
/// \param decoder is the stream decoder
|
||||
/// \param res is the resource set for the new sideeffect
|
||||
/// \return the new sideeffect
|
||||
AssignAction *AssignAction::decodeSideeffect(Decoder &decoder,const ParamListStandard *res)
|
||||
|
|
|
@ -286,7 +286,7 @@ class MultiSlotAssign : public AssignAction {
|
|||
void initializeEntries(void); ///< Cache specific ParamEntry needed by the action
|
||||
public:
|
||||
MultiSlotAssign(const ParamListStandard *res); ///< Constructor for use with decode
|
||||
MultiSlotAssign(type_class store,bool stack,bool mostSig,bool align,bool justRight,const ParamListStandard *res);
|
||||
MultiSlotAssign(type_class store,bool stack,bool mostSig,bool align,bool justRight,const ParamListStandard *res); ///< Constructor
|
||||
virtual AssignAction *clone(const ParamListStandard *newResource) const {
|
||||
return new MultiSlotAssign(resourceType,consumeFromStack,consumeMostSig,enforceAlignment,justifyRight,newResource); }
|
||||
virtual uint4 assignAddress(Datatype *dt,const PrototypePieces &proto,int4 pos,TypeFactory &tlist,
|
||||
|
@ -304,7 +304,7 @@ class MultiMemberAssign : public AssignAction {
|
|||
bool consumeFromStack; ///< True if resources should be consumed from the stack
|
||||
bool consumeMostSig; ///< True if resources are consumed starting with most significant bytes
|
||||
public:
|
||||
MultiMemberAssign(type_class store,bool stack,bool mostSig,const ParamListStandard *res);
|
||||
MultiMemberAssign(type_class store,bool stack,bool mostSig,const ParamListStandard *res); ///< Constructor
|
||||
virtual AssignAction *clone(const ParamListStandard *newResource) const {
|
||||
return new MultiMemberAssign(resourceType,consumeFromStack,consumeMostSig,newResource); }
|
||||
virtual uint4 assignAddress(Datatype *dt,const PrototypePieces &proto,int4 pos,TypeFactory &tlist,
|
||||
|
|
|
@ -476,6 +476,23 @@ void Datatype::encodeRef(Encoder &encoder) const
|
|||
encode(encoder);
|
||||
}
|
||||
|
||||
/// If \b this has no component data-types, return \b true.
|
||||
/// If \b this has only a single primitive component filling the whole data-type, also return \b true.
|
||||
/// \return \b true if \b this data-type is made up of a single primitive
|
||||
bool Datatype::isPrimitiveWhole(void) const
|
||||
|
||||
{
|
||||
if (!isPieceStructured()) return true;
|
||||
if (metatype == TYPE_ARRAY || metatype == TYPE_STRUCT) {
|
||||
if (numDepend() > 0) {
|
||||
Datatype *component = getDepend(0);
|
||||
if (component->getSize() == getSize())
|
||||
return component->isPrimitiveWhole();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Called only if the \b typedefImm field is non-null. Encode the data-type to the
|
||||
/// stream as a simple \<typedef> element including only the names and ids of \b this and
|
||||
/// the data-type it typedefs.
|
||||
|
|
|
@ -278,6 +278,7 @@ public:
|
|||
int4 typeOrderBool(const Datatype &op) const; ///< Order \b this with -op-, treating \e bool data-type as special
|
||||
void encodeRef(Encoder &encoder) const; ///< Encode a reference of \b this to a stream
|
||||
bool isPieceStructured(void) const; ///< Does \b this data-type consist of separate pieces?
|
||||
bool isPrimitiveWhole(void) const; ///< Is \b this made up of a single primitive
|
||||
static uint4 encodeIntegerFormat(const string &val);
|
||||
static string decodeIntegerFormat(uint4 val);
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue