mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 17:59:46 +02:00
GP-2286 Formal boolean Varnodes
This commit is contained in:
parent
a438a1e1ea
commit
d8835b0ecb
9 changed files with 74 additions and 48 deletions
|
@ -1120,7 +1120,7 @@ SymbolEntry *ActionConstantPtr::isPointer(AddrSpace *spc,Varnode *vn,PcodeOp *op
|
||||||
int4 ActionConstantPtr::apply(Funcdata &data)
|
int4 ActionConstantPtr::apply(Funcdata &data)
|
||||||
|
|
||||||
{
|
{
|
||||||
if (!data.isTypeRecoveryOn()) return 0;
|
if (!data.hasTypeRecoveryStarted()) return 0;
|
||||||
|
|
||||||
if (localcount >= 4) // At most 4 passes (once type recovery starts)
|
if (localcount >= 4) // At most 4 passes (once type recovery starts)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1208,7 +1208,7 @@ int4 ActionDeindirect::apply(Funcdata &data)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (data.isTypeRecoveryOn()) {
|
if (data.hasTypeRecoveryStarted()) {
|
||||||
// Check for a function pointer that has an attached prototype
|
// Check for a function pointer that has an attached prototype
|
||||||
Datatype *ct = op->getIn(0)->getTypeReadFacing(op);
|
Datatype *ct = op->getIn(0)->getTypeReadFacing(op);
|
||||||
if ((ct->getMetatype()==TYPE_PTR)&&
|
if ((ct->getMetatype()==TYPE_PTR)&&
|
||||||
|
@ -1486,7 +1486,7 @@ void ActionFuncLink::funcLinkOutput(FuncCallSpecs *fc,Funcdata &data)
|
||||||
Datatype *outtype = outparam->getType();
|
Datatype *outtype = outparam->getType();
|
||||||
if (outtype->getMetatype() != TYPE_VOID) {
|
if (outtype->getMetatype() != TYPE_VOID) {
|
||||||
int4 sz = outparam->getSize();
|
int4 sz = outparam->getSize();
|
||||||
if (sz == 1 && outtype->getMetatype() == TYPE_BOOL)
|
if (sz == 1 && outtype->getMetatype() == TYPE_BOOL && data.isTypeRecoveryOn())
|
||||||
data.opMarkCalculatedBool(fc->getOp());
|
data.opMarkCalculatedBool(fc->getOp());
|
||||||
Address addr = outparam->getAddress();
|
Address addr = outparam->getAddress();
|
||||||
data.newVarnodeOut(sz,addr,fc->getOp());
|
data.newVarnodeOut(sz,addr,fc->getOp());
|
||||||
|
@ -4792,7 +4792,7 @@ int4 ActionInferTypes::apply(Funcdata &data)
|
||||||
|
|
||||||
{
|
{
|
||||||
// Make sure spacebase is accurate or bases could get typed and then ptrarithed
|
// Make sure spacebase is accurate or bases could get typed and then ptrarithed
|
||||||
if (!data.isTypeRecoveryOn()) return 0;
|
if (!data.hasTypeRecoveryStarted()) return 0;
|
||||||
TypeFactory *typegrp = data.getArch()->types;
|
TypeFactory *typegrp = data.getArch()->types;
|
||||||
Varnode *vn;
|
Varnode *vn;
|
||||||
VarnodeLocSet::const_iterator iter;
|
VarnodeLocSet::const_iterator iter;
|
||||||
|
|
|
@ -65,9 +65,14 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief Allow type recovery to start happening
|
/// \brief Allow type recovery to start happening
|
||||||
|
///
|
||||||
|
/// The presence of \b this Action causes the function to be marked that data-type analysis
|
||||||
|
/// will be performed. Then when \b this action is applied during analysis, the function is marked
|
||||||
|
/// that data-type analysis has started.
|
||||||
class ActionStartTypes : public Action {
|
class ActionStartTypes : public Action {
|
||||||
public:
|
public:
|
||||||
ActionStartTypes(const string &g) : Action(0,"starttypes",g) {} ///< Constructor
|
ActionStartTypes(const string &g) : Action(0,"starttypes",g) {} ///< Constructor
|
||||||
|
virtual void reset(Funcdata &data) { data.setTypeRecovery(true); }
|
||||||
virtual Action *clone(const ActionGroupList &grouplist) const {
|
virtual Action *clone(const ActionGroupList &grouplist) const {
|
||||||
if (!grouplist.contains(getGroup())) return (Action *)0;
|
if (!grouplist.contains(getGroup())) return (Action *)0;
|
||||||
return new ActionStartTypes(getGroup());
|
return new ActionStartTypes(getGroup());
|
||||||
|
|
|
@ -4893,7 +4893,7 @@ void FuncCallSpecs::commitNewOutputs(Funcdata &data,Varnode *newout)
|
||||||
// We could conceivably truncate the output to the correct size to match the parameter
|
// We could conceivably truncate the output to the correct size to match the parameter
|
||||||
activeoutput.registerTrial(param->getAddress(),param->getSize());
|
activeoutput.registerTrial(param->getAddress(),param->getSize());
|
||||||
PcodeOp *indop = newout->getDef();
|
PcodeOp *indop = newout->getDef();
|
||||||
if (newout->getSize() == 1 && param->getType()->getMetatype() == TYPE_BOOL)
|
if (newout->getSize() == 1 && param->getType()->getMetatype() == TYPE_BOOL && data.isTypeRecoveryOn())
|
||||||
data.opMarkCalculatedBool(op);
|
data.opMarkCalculatedBool(op);
|
||||||
if (newout->getSize() == param->getSize()) {
|
if (newout->getSize() == param->getSize()) {
|
||||||
if (indop != op) {
|
if (indop != op) {
|
||||||
|
|
|
@ -81,7 +81,8 @@ void Funcdata::clear(void)
|
||||||
|
|
||||||
{ // Clear everything associated with decompilation (analysis)
|
{ // Clear everything associated with decompilation (analysis)
|
||||||
|
|
||||||
flags &= ~(highlevel_on|blocks_generated|processing_started|typerecovery_on|restart_pending);
|
flags &= ~(highlevel_on|blocks_generated|processing_started|typerecovery_start|typerecovery_on|
|
||||||
|
double_precis_on|restart_pending);
|
||||||
clean_up_index = 0;
|
clean_up_index = 0;
|
||||||
high_level_index = 0;
|
high_level_index = 0;
|
||||||
cast_phase_index = 0;
|
cast_phase_index = 0;
|
||||||
|
@ -174,8 +175,8 @@ void Funcdata::stopProcessing(void)
|
||||||
bool Funcdata::startTypeRecovery(void)
|
bool Funcdata::startTypeRecovery(void)
|
||||||
|
|
||||||
{
|
{
|
||||||
if ((flags & typerecovery_on)!=0) return false; // Already started
|
if ((flags & typerecovery_start)!=0) return false; // Already started
|
||||||
flags |= typerecovery_on;
|
flags |= typerecovery_start;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -58,14 +58,15 @@ class Funcdata {
|
||||||
blocks_unreachable = 4, ///< Set if at least one basic block is currently unreachable
|
blocks_unreachable = 4, ///< Set if at least one basic block is currently unreachable
|
||||||
processing_started = 8, ///< Set if processing has started
|
processing_started = 8, ///< Set if processing has started
|
||||||
processing_complete = 0x10, ///< Set if processing completed
|
processing_complete = 0x10, ///< Set if processing completed
|
||||||
typerecovery_on = 0x20, ///< Set if data-type recovery is started
|
typerecovery_on = 0x20, ///< Set if data-type analysis will be performed
|
||||||
no_code = 0x40, ///< Set if there is no code available for this function
|
typerecovery_start = 0x40, ///< Set if data-type recovery is started
|
||||||
jumptablerecovery_on = 0x80, ///< Set if \b this Funcdata object is dedicated to jump-table recovery
|
no_code = 0x80, ///< Set if there is no code available for this function
|
||||||
jumptablerecovery_dont = 0x100, ///< Don't try to recover jump-tables, always truncate
|
jumptablerecovery_on = 0x100, ///< Set if \b this Funcdata object is dedicated to jump-table recovery
|
||||||
restart_pending = 0x200, ///< Analysis must be restarted (because of new override info)
|
jumptablerecovery_dont = 0x200, ///< Don't try to recover jump-tables, always truncate
|
||||||
unimplemented_present = 0x400, ///< Set if function contains unimplemented instructions
|
restart_pending = 0x400, ///< Analysis must be restarted (because of new override info)
|
||||||
baddata_present = 0x800, ///< Set if function flowed into bad data
|
unimplemented_present = 0x800, ///< Set if function contains unimplemented instructions
|
||||||
double_precis_on = 0x1000 ///< Set if we are performing double precision recovery
|
baddata_present = 0x1000, ///< Set if function flowed into bad data
|
||||||
|
double_precis_on = 0x2000 ///< Set if we are performing double precision recovery
|
||||||
};
|
};
|
||||||
uint4 flags; ///< Boolean properties associated with \b this function
|
uint4 flags; ///< Boolean properties associated with \b this function
|
||||||
uint4 clean_up_index; ///< Creation index of first Varnode created after start of cleanup
|
uint4 clean_up_index; ///< Creation index of first Varnode created after start of cleanup
|
||||||
|
@ -144,7 +145,8 @@ public:
|
||||||
bool isProcStarted(void) const { return ((flags&processing_started)!=0); } ///< Has processing of the function started
|
bool isProcStarted(void) const { return ((flags&processing_started)!=0); } ///< Has processing of the function started
|
||||||
bool isProcComplete(void) const { return ((flags&processing_complete)!=0); } ///< Is processing of the function complete
|
bool isProcComplete(void) const { return ((flags&processing_complete)!=0); } ///< Is processing of the function complete
|
||||||
bool hasUnreachableBlocks(void) const { return ((flags&blocks_unreachable)!=0); } ///< Did this function exhibit unreachable code
|
bool hasUnreachableBlocks(void) const { return ((flags&blocks_unreachable)!=0); } ///< Did this function exhibit unreachable code
|
||||||
bool isTypeRecoveryOn(void) const { return ((flags&typerecovery_on)!=0); } ///< Has data-type recovery processes started
|
bool isTypeRecoveryOn(void) const { return ((flags&typerecovery_on)!=0); } ///< Will data-type analysis be performed
|
||||||
|
bool hasTypeRecoveryStarted(void) const { return ((flags&typerecovery_start)!=0); } ///< Has data-type recovery processes started
|
||||||
bool hasNoCode(void) const { return ((flags & no_code)!=0); } ///< Return \b true if \b this function has no code body
|
bool hasNoCode(void) const { return ((flags & no_code)!=0); } ///< Return \b true if \b this function has no code body
|
||||||
void setNoCode(bool val) { if (val) flags |= no_code; else flags &= ~no_code; } ///< Toggle whether \b this has a body
|
void setNoCode(bool val) { if (val) flags |= no_code; else flags &= ~no_code; } ///< Toggle whether \b this has a body
|
||||||
void setLanedRegGenerated(void) { minLanedSize = 1000000; } ///< Mark that laned registers have been collected
|
void setLanedRegGenerated(void) { minLanedSize = 1000000; } ///< Mark that laned registers have been collected
|
||||||
|
@ -169,6 +171,11 @@ public:
|
||||||
void startProcessing(void); ///< Start processing for this function
|
void startProcessing(void); ///< Start processing for this function
|
||||||
void stopProcessing(void); ///< Mark that processing has completed for this function
|
void stopProcessing(void); ///< Mark that processing has completed for this function
|
||||||
bool startTypeRecovery(void); ///< Mark that data-type analysis has started
|
bool startTypeRecovery(void); ///< Mark that data-type analysis has started
|
||||||
|
|
||||||
|
/// \brief Toggle whether data-type recovery will be performed on \b this function
|
||||||
|
///
|
||||||
|
/// \param val is \b true if data-type analysis is enabled
|
||||||
|
void setTypeRecovery(bool val) { flags = val ? (flags | typerecovery_on) : (flags & ~typerecovery_on); }
|
||||||
void startCastPhase(void) { cast_phase_index = vbank.getCreateIndex(); } ///< Start the \b cast insertion phase
|
void startCastPhase(void) { cast_phase_index = vbank.getCreateIndex(); } ///< Start the \b cast insertion phase
|
||||||
uint4 getCastPhaseIndex(void) const { return cast_phase_index; } ///< Get creation index at the start of \b cast insertion
|
uint4 getCastPhaseIndex(void) const { return cast_phase_index; } ///< Get creation index at the start of \b cast insertion
|
||||||
uint4 getHighLevelIndex(void) const { return high_level_index; } ///< Get creation index at the start of HighVariable creation
|
uint4 getHighLevelIndex(void) const { return high_level_index; } ///< Get creation index at the start of HighVariable creation
|
||||||
|
|
|
@ -2641,7 +2641,6 @@ int4 RuleBooleanNegate::applyOp(PcodeOp *op,Funcdata &data)
|
||||||
OpCode opc;
|
OpCode opc;
|
||||||
Varnode *constvn;
|
Varnode *constvn;
|
||||||
Varnode *subbool;
|
Varnode *subbool;
|
||||||
PcodeOp *subop;
|
|
||||||
bool negate;
|
bool negate;
|
||||||
uintb val;
|
uintb val;
|
||||||
|
|
||||||
|
@ -2656,9 +2655,7 @@ int4 RuleBooleanNegate::applyOp(PcodeOp *op,Funcdata &data)
|
||||||
if (val==0)
|
if (val==0)
|
||||||
negate = !negate;
|
negate = !negate;
|
||||||
|
|
||||||
if (!subbool->isWritten()) return 0;
|
if (!subbool->isBooleanValue(data.isTypeRecoveryOn())) return 0;
|
||||||
subop = subbool->getDef();
|
|
||||||
if (!subop->isCalculatedBool()) return 0; // Subexpression must be boolean output
|
|
||||||
|
|
||||||
data.opRemoveInput(op,1); // Remove second parameter
|
data.opRemoveInput(op,1); // Remove second parameter
|
||||||
data.opSetInput(op,subbool,0); // Keep original boolean parameter
|
data.opSetInput(op,subbool,0); // Keep original boolean parameter
|
||||||
|
@ -2687,15 +2684,15 @@ void RuleBoolZext::getOpList(vector<uint4> &oplist) const
|
||||||
int4 RuleBoolZext::applyOp(PcodeOp *op,Funcdata &data)
|
int4 RuleBoolZext::applyOp(PcodeOp *op,Funcdata &data)
|
||||||
|
|
||||||
{
|
{
|
||||||
PcodeOp *boolop1,*multop1,*actionop;
|
Varnode *boolVn1,*boolVn2;
|
||||||
PcodeOp *boolop2,*zextop2,*multop2;
|
PcodeOp *multop1,*actionop;
|
||||||
|
PcodeOp *zextop2,*multop2;
|
||||||
uintb coeff,val;
|
uintb coeff,val;
|
||||||
OpCode opc;
|
OpCode opc;
|
||||||
int4 size;
|
int4 size;
|
||||||
|
|
||||||
if (!op->getIn(0)->isWritten()) return 0;
|
boolVn1 = op->getIn(0);
|
||||||
boolop1 = op->getIn(0)->getDef();
|
if (!boolVn1->isBooleanValue(data.isTypeRecoveryOn())) return 0;
|
||||||
if (!boolop1->isCalculatedBool()) return 0;
|
|
||||||
|
|
||||||
multop1 = op->getOut()->loneDescend();
|
multop1 = op->getOut()->loneDescend();
|
||||||
if (multop1 == (PcodeOp *)0) return 0;
|
if (multop1 == (PcodeOp *)0) return 0;
|
||||||
|
@ -2717,7 +2714,7 @@ int4 RuleBoolZext::applyOp(PcodeOp *op,Funcdata &data)
|
||||||
PcodeOp *newop = data.newOp(1,op->getAddr());
|
PcodeOp *newop = data.newOp(1,op->getAddr());
|
||||||
data.opSetOpcode(newop,CPUI_BOOL_NEGATE); // Negate the boolean
|
data.opSetOpcode(newop,CPUI_BOOL_NEGATE); // Negate the boolean
|
||||||
vn = data.newUniqueOut(1,newop);
|
vn = data.newUniqueOut(1,newop);
|
||||||
data.opSetInput(newop,boolop1->getOut(),0);
|
data.opSetInput(newop,boolVn1,0);
|
||||||
data.opInsertBefore(newop,op);
|
data.opInsertBefore(newop,op);
|
||||||
data.opSetInput(op,vn,0);
|
data.opSetInput(op,vn,0);
|
||||||
data.opRemoveInput(actionop,1); // eliminate the INT_ADD operator
|
data.opRemoveInput(actionop,1); // eliminate the INT_ADD operator
|
||||||
|
@ -2742,7 +2739,7 @@ int4 RuleBoolZext::applyOp(PcodeOp *op,Funcdata &data)
|
||||||
else if (val != 0)
|
else if (val != 0)
|
||||||
return 0; // Not comparing with 0 or -1
|
return 0; // Not comparing with 0 or -1
|
||||||
|
|
||||||
data.opSetInput(actionop,boolop1->getOut(),0);
|
data.opSetInput(actionop,boolVn1,0);
|
||||||
data.opSetInput(actionop,data.newConstant(1,val),1);
|
data.opSetInput(actionop,data.newConstant(1,val),1);
|
||||||
return 1;
|
return 1;
|
||||||
case CPUI_INT_AND:
|
case CPUI_INT_AND:
|
||||||
|
@ -2771,17 +2768,16 @@ int4 RuleBoolZext::applyOp(PcodeOp *op,Funcdata &data)
|
||||||
zextop2 = multop2->getIn(0)->getDef();
|
zextop2 = multop2->getIn(0)->getDef();
|
||||||
if (zextop2 == (PcodeOp *)0) return 0;
|
if (zextop2 == (PcodeOp *)0) return 0;
|
||||||
if (zextop2->code() != CPUI_INT_ZEXT) return 0;
|
if (zextop2->code() != CPUI_INT_ZEXT) return 0;
|
||||||
boolop2 = zextop2->getIn(0)->getDef();
|
boolVn2 = zextop2->getIn(0);
|
||||||
if (boolop2 == (PcodeOp *)0) return 0;
|
if (!boolVn2->isBooleanValue(data.isTypeRecoveryOn())) return 0;
|
||||||
if (!boolop2->isCalculatedBool()) return 0;
|
|
||||||
|
|
||||||
// Do the boolean calculation on unextended boolean values
|
// Do the boolean calculation on unextended boolean values
|
||||||
// and then extend the result
|
// and then extend the result
|
||||||
PcodeOp *newop = data.newOp(2,actionop->getAddr());
|
PcodeOp *newop = data.newOp(2,actionop->getAddr());
|
||||||
Varnode *newres = data.newUniqueOut(1,newop);
|
Varnode *newres = data.newUniqueOut(1,newop);
|
||||||
data.opSetOpcode(newop,opc);
|
data.opSetOpcode(newop,opc);
|
||||||
data.opSetInput(newop, boolop1->getOut(), 0);
|
data.opSetInput(newop, boolVn1, 0);
|
||||||
data.opSetInput(newop, boolop2->getOut(), 1);
|
data.opSetInput(newop, boolVn2, 1);
|
||||||
data.opInsertBefore(newop,actionop);
|
data.opInsertBefore(newop,actionop);
|
||||||
|
|
||||||
PcodeOp *newzext = data.newOp(1,actionop->getAddr());
|
PcodeOp *newzext = data.newOp(1,actionop->getAddr());
|
||||||
|
@ -2811,19 +2807,17 @@ void RuleLogic2Bool::getOpList(vector<uint4> &oplist) const
|
||||||
int4 RuleLogic2Bool::applyOp(PcodeOp *op,Funcdata &data)
|
int4 RuleLogic2Bool::applyOp(PcodeOp *op,Funcdata &data)
|
||||||
|
|
||||||
{
|
{
|
||||||
PcodeOp *boolop;
|
Varnode *boolVn;
|
||||||
|
|
||||||
if (!op->getIn(0)->isWritten()) return 0;
|
boolVn = op->getIn(0);
|
||||||
boolop = op->getIn(0)->getDef();
|
if (!boolVn->isBooleanValue(data.isTypeRecoveryOn())) return 0;
|
||||||
if (!boolop->isCalculatedBool()) return 0;
|
|
||||||
Varnode *in1 = op->getIn(1);
|
Varnode *in1 = op->getIn(1);
|
||||||
if (!in1->isWritten()) {
|
if (in1->isConstant()) {
|
||||||
if ((!in1->isConstant())||(in1->getOffset()>(uintb)1)) // If one side is a constant 0 or 1, this is boolean
|
if (in1->getOffset()>(uintb)1) // If one side is a constant 0 or 1, this is boolean
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else {
|
else if (!in1->isBooleanValue(data.isTypeRecoveryOn())) {
|
||||||
boolop = op->getIn(1)->getDef();
|
return 0;
|
||||||
if (!boolop->isCalculatedBool()) return 0;
|
|
||||||
}
|
}
|
||||||
switch(op->code()) {
|
switch(op->code()) {
|
||||||
case CPUI_INT_AND:
|
case CPUI_INT_AND:
|
||||||
|
@ -6292,7 +6286,7 @@ int4 RulePtrArith::applyOp(PcodeOp *op,Funcdata &data)
|
||||||
int4 slot;
|
int4 slot;
|
||||||
const Datatype *ct = (const Datatype *)0; // Unnecessary initialization
|
const Datatype *ct = (const Datatype *)0; // Unnecessary initialization
|
||||||
|
|
||||||
if (!data.isTypeRecoveryOn()) return 0;
|
if (!data.hasTypeRecoveryStarted()) return 0;
|
||||||
|
|
||||||
for(slot=0;slot<op->numInput();++slot) { // Search for pointer type
|
for(slot=0;slot<op->numInput();++slot) { // Search for pointer type
|
||||||
ct = op->getIn(slot)->getTypeReadFacing(op);
|
ct = op->getIn(slot)->getTypeReadFacing(op);
|
||||||
|
@ -6330,7 +6324,7 @@ int4 RuleStructOffset0::applyOp(PcodeOp *op,Funcdata &data)
|
||||||
{
|
{
|
||||||
int4 movesize; // Number of bytes being moved by load or store
|
int4 movesize; // Number of bytes being moved by load or store
|
||||||
|
|
||||||
if (!data.isTypeRecoveryOn()) return 0;
|
if (!data.hasTypeRecoveryStarted()) return 0;
|
||||||
if (op->code()==CPUI_LOAD) {
|
if (op->code()==CPUI_LOAD) {
|
||||||
movesize = op->getOut()->getSize();
|
movesize = op->getOut()->getSize();
|
||||||
}
|
}
|
||||||
|
@ -6478,7 +6472,7 @@ int4 RulePushPtr::applyOp(PcodeOp *op,Funcdata &data)
|
||||||
int4 slot;
|
int4 slot;
|
||||||
Varnode *vni = (Varnode *)0;
|
Varnode *vni = (Varnode *)0;
|
||||||
|
|
||||||
if (!data.isTypeRecoveryOn()) return 0;
|
if (!data.hasTypeRecoveryStarted()) return 0;
|
||||||
for(slot=0;slot<op->numInput();++slot) { // Search for pointer type
|
for(slot=0;slot<op->numInput();++slot) { // Search for pointer type
|
||||||
vni = op->getIn(slot);
|
vni = op->getIn(slot);
|
||||||
if (vni->getTypeReadFacing(op)->getMetatype() == TYPE_PTR) break;
|
if (vni->getTypeReadFacing(op)->getMetatype() == TYPE_PTR) break;
|
||||||
|
@ -6542,7 +6536,7 @@ int4 RulePtraddUndo::applyOp(PcodeOp *op,Funcdata &data)
|
||||||
Varnode *basevn;
|
Varnode *basevn;
|
||||||
TypePointer *tp;
|
TypePointer *tp;
|
||||||
|
|
||||||
if (!data.isTypeRecoveryOn()) return 0;
|
if (!data.hasTypeRecoveryStarted()) return 0;
|
||||||
int4 size = (int4)op->getIn(2)->getOffset(); // Size the PTRADD thinks we are pointing
|
int4 size = (int4)op->getIn(2)->getOffset(); // Size the PTRADD thinks we are pointing
|
||||||
basevn = op->getIn(0);
|
basevn = op->getIn(0);
|
||||||
tp = (TypePointer *)basevn->getTypeReadFacing(op);
|
tp = (TypePointer *)basevn->getTypeReadFacing(op);
|
||||||
|
@ -6572,7 +6566,7 @@ void RulePtrsubUndo::getOpList(vector<uint4> &oplist) const
|
||||||
int4 RulePtrsubUndo::applyOp(PcodeOp *op,Funcdata &data)
|
int4 RulePtrsubUndo::applyOp(PcodeOp *op,Funcdata &data)
|
||||||
|
|
||||||
{
|
{
|
||||||
if (!data.isTypeRecoveryOn()) return 0;
|
if (!data.hasTypeRecoveryStarted()) return 0;
|
||||||
|
|
||||||
Varnode *basevn = op->getIn(0);
|
Varnode *basevn = op->getIn(0);
|
||||||
if (basevn->getTypeReadFacing(op)->isPtrsubMatching(op->getIn(1)->getOffset()))
|
if (basevn->getTypeReadFacing(op)->isPtrsubMatching(op->getIn(1)->getOffset()))
|
||||||
|
|
|
@ -317,7 +317,7 @@ void ScopeLocal::collectNameRecs(void)
|
||||||
void ScopeLocal::annotateRawStackPtr(void)
|
void ScopeLocal::annotateRawStackPtr(void)
|
||||||
|
|
||||||
{
|
{
|
||||||
if (!fd->isTypeRecoveryOn()) return;
|
if (!fd->hasTypeRecoveryStarted()) return;
|
||||||
Varnode *spVn = fd->findSpacebaseInput(space);
|
Varnode *spVn = fd->findSpacebaseInput(space);
|
||||||
if (spVn == (Varnode *)0) return;
|
if (spVn == (Varnode *)0) return;
|
||||||
list<PcodeOp *>::const_iterator iter;
|
list<PcodeOp *>::const_iterator iter;
|
||||||
|
|
|
@ -819,6 +819,24 @@ Datatype *Varnode::getLocalType(bool &blockup) const
|
||||||
return ct;
|
return ct;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// If \b this varnode is produced by an operation with a boolean output, or if it is
|
||||||
|
/// formally marked with a boolean data-type, return \b true. The parameter \b trustAnnotation
|
||||||
|
/// toggles whether or not the formal data-type is trusted.
|
||||||
|
/// \return \b true if \b this is a formal boolean, \b false otherwise
|
||||||
|
bool Varnode::isBooleanValue(bool useAnnotation) const
|
||||||
|
|
||||||
|
{
|
||||||
|
if (isWritten()) return def->isCalculatedBool();
|
||||||
|
if (!useAnnotation)
|
||||||
|
return false;
|
||||||
|
if ((flags & (input | typelock)) == (input | typelock)) {
|
||||||
|
if (size == 1 && type->getMetatype() == TYPE_BOOL)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Make a local determination if \b this and \b op2 hold the same value. We check if
|
/// Make a local determination if \b this and \b op2 hold the same value. We check if
|
||||||
/// there is a common ancester for which both \b this and \b op2 are created from a direct
|
/// there is a common ancester for which both \b this and \b op2 are created from a direct
|
||||||
/// sequence of COPY operations. NOTE: This is a transitive relationship
|
/// sequence of COPY operations. NOTE: This is a transitive relationship
|
||||||
|
|
|
@ -328,6 +328,7 @@ public:
|
||||||
void copySymbol(const Varnode *vn); ///< Copy symbol info from \b vn
|
void copySymbol(const Varnode *vn); ///< Copy symbol info from \b vn
|
||||||
void copySymbolIfValid(const Varnode *vn); ///< Copy symbol info from \b vn if constant value matches
|
void copySymbolIfValid(const Varnode *vn); ///< Copy symbol info from \b vn if constant value matches
|
||||||
Datatype *getLocalType(bool &blockup) const; ///< Calculate type of Varnode based on local information
|
Datatype *getLocalType(bool &blockup) const; ///< Calculate type of Varnode based on local information
|
||||||
|
bool isBooleanValue(bool useAnnotation) const; ///< Does \b this Varnode hold a formal boolean value
|
||||||
bool copyShadow(const Varnode *op2) const; ///< Are \b this and \b op2 copied from the same source?
|
bool copyShadow(const Varnode *op2) const; ///< Are \b this and \b op2 copied from the same source?
|
||||||
void encode(Encoder &encoder) const; ///< Encode a description of \b this to a stream
|
void encode(Encoder &encoder) const; ///< Encode a description of \b this to a stream
|
||||||
static bool comparePointers(const Varnode *a,const Varnode *b) { return (*a < *b); } ///< Compare Varnodes as pointers
|
static bool comparePointers(const Varnode *a,const Varnode *b) { return (*a < *b); } ///< Compare Varnodes as pointers
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue