mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 02:09:44 +02:00
GP-2037 RuleDoubleStore
This commit is contained in:
parent
cb4b309942
commit
4448f11cb4
15 changed files with 761 additions and 231 deletions
|
@ -90,9 +90,6 @@ public:
|
||||||
|
|
||||||
/// Restore an address and size from parsed XML
|
/// Restore an address and size from parsed XML
|
||||||
static Address restoreXml(const Element *el,const AddrSpaceManager *manage,int4 &size);
|
static Address restoreXml(const Element *el,const AddrSpaceManager *manage,int4 &size);
|
||||||
|
|
||||||
/// Recover an encoded address space from an address
|
|
||||||
static AddrSpace *getSpaceFromConst(const Address &addr);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief A class for uniquely labelling and comparing PcodeOps
|
/// \brief A class for uniquely labelling and comparing PcodeOps
|
||||||
|
@ -442,17 +439,6 @@ inline void Address::saveXml(ostream &s,int4 size) const {
|
||||||
s << "/>";
|
s << "/>";
|
||||||
}
|
}
|
||||||
|
|
||||||
/// In \b LOAD and \b STORE instructions, the particular address
|
|
||||||
/// space being read/written is encoded as a constant input parameter
|
|
||||||
/// to the instruction. Internally, this constant is the actual
|
|
||||||
/// pointer to the AddrSpace. This function allows the encoded pointer
|
|
||||||
/// to be recovered from the address it is encoded in.
|
|
||||||
/// \param addr is the Address encoding the pointer
|
|
||||||
/// \return the AddrSpace pointer
|
|
||||||
inline AddrSpace *Address::getSpaceFromConst(const Address &addr) {
|
|
||||||
return (AddrSpace *)(uintp)addr.offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \param addr is the Address to test for containment
|
/// \param addr is the Address to test for containment
|
||||||
/// \return \b true if addr is in \b this Range
|
/// \return \b true if addr is in \b this Range
|
||||||
inline bool Range::contains(const Address &addr) const {
|
inline bool Range::contains(const Address &addr) const {
|
||||||
|
|
|
@ -963,10 +963,10 @@ AddrSpace *ActionConstantPtr::searchForSpaceAttribute(Varnode *vn,PcodeOp *op)
|
||||||
op = vn->loneDescend();
|
op = vn->loneDescend();
|
||||||
break;
|
break;
|
||||||
case CPUI_LOAD:
|
case CPUI_LOAD:
|
||||||
return Address::getSpaceFromConst(op->getIn(0)->getAddr());
|
return op->getIn(0)->getSpaceFromConst();
|
||||||
case CPUI_STORE:
|
case CPUI_STORE:
|
||||||
if (op->getIn(1) == vn)
|
if (op->getIn(1) == vn)
|
||||||
return Address::getSpaceFromConst(op->getIn(0)->getAddr());
|
return op->getIn(0)->getSpaceFromConst();
|
||||||
return (AddrSpace *)0;
|
return (AddrSpace *)0;
|
||||||
default:
|
default:
|
||||||
return (AddrSpace *)0;
|
return (AddrSpace *)0;
|
||||||
|
@ -977,9 +977,9 @@ AddrSpace *ActionConstantPtr::searchForSpaceAttribute(Varnode *vn,PcodeOp *op)
|
||||||
op = *iter;
|
op = *iter;
|
||||||
OpCode opc = op->code();
|
OpCode opc = op->code();
|
||||||
if (opc == CPUI_LOAD)
|
if (opc == CPUI_LOAD)
|
||||||
return Address::getSpaceFromConst(op->getIn(0)->getAddr());
|
return op->getIn(0)->getSpaceFromConst();
|
||||||
else if (opc == CPUI_STORE && op->getIn(1) == vn)
|
else if (opc == CPUI_STORE && op->getIn(1) == vn)
|
||||||
return Address::getSpaceFromConst(op->getIn(0)->getAddr());
|
return op->getIn(0)->getSpaceFromConst();
|
||||||
}
|
}
|
||||||
return (AddrSpace *)0;
|
return (AddrSpace *)0;
|
||||||
}
|
}
|
||||||
|
@ -2203,7 +2203,7 @@ void ActionSetCasts::checkPointerIssues(PcodeOp *op,Varnode *vn,Funcdata &data)
|
||||||
if (ptrtype->getMetatype()==TYPE_PTR) {
|
if (ptrtype->getMetatype()==TYPE_PTR) {
|
||||||
AddrSpace *spc = ((TypePointer *)ptrtype)->getSpace();
|
AddrSpace *spc = ((TypePointer *)ptrtype)->getSpace();
|
||||||
if (spc != (AddrSpace *)0) {
|
if (spc != (AddrSpace *)0) {
|
||||||
AddrSpace *opSpc = Address::getSpaceFromConst(op->getIn(0)->getAddr());
|
AddrSpace *opSpc = op->getIn(0)->getSpaceFromConst();
|
||||||
if (opSpc != spc && spc->getContain() != opSpc) {
|
if (opSpc != spc && spc->getContain() != opSpc) {
|
||||||
string name = op->getOpcode()->getName();
|
string name = op->getOpcode()->getName();
|
||||||
name[0] = toupper( name[0] );
|
name[0] = toupper( name[0] );
|
||||||
|
@ -5080,6 +5080,7 @@ void ActionDatabase::universalAction(Architecture *conf)
|
||||||
actprop->addRule( new RulePiecePathology("protorecovery") );
|
actprop->addRule( new RulePiecePathology("protorecovery") );
|
||||||
|
|
||||||
actprop->addRule( new RuleDoubleLoad("doubleload") );
|
actprop->addRule( new RuleDoubleLoad("doubleload") );
|
||||||
|
actprop->addRule( new RuleDoubleStore("doubleprecis") );
|
||||||
actprop->addRule( new RuleDoubleIn("doubleprecis") );
|
actprop->addRule( new RuleDoubleIn("doubleprecis") );
|
||||||
for(iter=conf->extra_pool_rules.begin();iter!=conf->extra_pool_rules.end();++iter)
|
for(iter=conf->extra_pool_rules.begin();iter!=conf->extra_pool_rules.end();++iter)
|
||||||
actprop->addRule( *iter ); // Add CPU specific rules
|
actprop->addRule( *iter ); // Add CPU specific rules
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -19,49 +19,57 @@
|
||||||
#include "ruleaction.hh"
|
#include "ruleaction.hh"
|
||||||
#include "funcdata.hh"
|
#include "funcdata.hh"
|
||||||
|
|
||||||
|
/// \brief A logical value whose storage is split between two Varnodes
|
||||||
|
///
|
||||||
|
/// This is usually a pair of Varnodes \b lo and \b hi holding the least and
|
||||||
|
/// most significant part of the logical value respectively. Its possible for
|
||||||
|
/// the logical value to be a constant, in which case \b lo and \b hi are set to
|
||||||
|
/// null and \b val holds the actual constant.
|
||||||
|
/// Its also possible for \b hi to be null by itself, indicating that most signficant
|
||||||
|
/// part of the variable is zero, and the logical variable is the zero extension of \b lo.
|
||||||
class SplitVarnode {
|
class SplitVarnode {
|
||||||
Varnode *lo; // Least significant piece of the double precision object
|
Varnode *lo; ///< Least significant piece of the double precision object
|
||||||
Varnode *hi; // Most significant piece of the double precision object
|
Varnode *hi; ///< Most significant piece of the double precision object
|
||||||
Varnode *whole; // A representative of the whole object
|
Varnode *whole; ///< A representative of the whole object
|
||||||
PcodeOp *defpoint; // Operation at which both -lo- and -hi- are defined
|
PcodeOp *defpoint; ///< Operation at which both \b lo and \b hi are defined
|
||||||
BlockBasic *defblock; // Block in which bot -lo- and -hi- are defined
|
BlockBasic *defblock; ///< Block in which both \b lo and \b hi are defined
|
||||||
uintb val; // Value of a double precision constant
|
uintb val; ///< Value of a double precision constant
|
||||||
int4 wholesize; // Size in bytes of the (virtual) whole
|
int4 wholesize; ///< Size in bytes of the (virtual) whole
|
||||||
bool findWholeSplitToPieces(void);
|
bool findWholeSplitToPieces(void); ///< Find whole out of which \b hi and \b lo are split
|
||||||
bool findDefinitionPoint(void);
|
bool findDefinitionPoint(void); ///< Find the earliest PcodeOp where both \b lo and \b hi are defined
|
||||||
bool findWholeBuiltFromPieces(void);
|
bool findWholeBuiltFromPieces(void); ///< Find whole Varnode formed as a CPUI_PIECE of \b hi and \b lo
|
||||||
public:
|
public:
|
||||||
SplitVarnode(void) {} // For use with inHandHi
|
SplitVarnode(void) {} ///< Construct an uninitialized SplitVarnode
|
||||||
SplitVarnode(int4 sz,uintb v); // Initialize a double precision constant
|
SplitVarnode(int4 sz,uintb v); ///< Construct a double precision constant
|
||||||
SplitVarnode(Varnode *l,Varnode *h) { initPartial(l,h); }
|
SplitVarnode(Varnode *l,Varnode *h) { initPartial(l->getSize()+h->getSize(),l,h); } ///< Construct from \b lo and \b hi piece
|
||||||
void initAll(Varnode *w,Varnode *l,Varnode *h);
|
void initAll(Varnode *w,Varnode *l,Varnode *h); ///< Construct given Varnode pieces and a known \b whole Varnode
|
||||||
void initPartial(int4 sz,uintb v);
|
void initPartial(int4 sz,uintb v); ///< (Re)initialize \b this SplitVarnode as a constant
|
||||||
void initPartial(Varnode *l,Varnode *h);
|
void initPartial(int4 sz,Varnode *l,Varnode *h); ///< (Re)initialize \b this SplitVarnode given Varnode pieces
|
||||||
bool inHandHi(Varnode *h);
|
bool inHandHi(Varnode *h); ///< Try to initialize given just the most significant piece split from whole
|
||||||
bool inHandLo(Varnode *l);
|
bool inHandLo(Varnode *l); ///< Try to initialize given just the least significant piece split from whole
|
||||||
bool inHandLoNoHi(Varnode *l);
|
bool inHandLoNoHi(Varnode *l); ///< Try to initialize given just the least significant piece (other piece may be zero)
|
||||||
bool inHandHiOut(Varnode *h);
|
bool inHandHiOut(Varnode *h); ///< Try to initialize given just the most significant piece concatenated into whole
|
||||||
bool inHandLoOut(Varnode *h);
|
bool inHandLoOut(Varnode *l); ///< Try to initialize given just the least significant piece concatenated into whole
|
||||||
bool isConstant(void) const { return (lo == (Varnode *)0); }
|
bool isConstant(void) const { return (lo == (Varnode *)0); } ///< Return \b true if \b this is a constant
|
||||||
bool hasBothPieces(void) const { return ((hi!=(Varnode *)0)&&(lo!=(Varnode *)0)); }
|
bool hasBothPieces(void) const { return ((hi!=(Varnode *)0)&&(lo!=(Varnode *)0)); } ///< Return \b true if both pieces are initialized
|
||||||
int4 getSize(void) const { return wholesize; }
|
int4 getSize(void) const { return wholesize; } ///< Get the size of \b this SplitVarnode as a whole in bytes
|
||||||
Varnode *getLo(void) const { return lo; }
|
Varnode *getLo(void) const { return lo; } ///< Get the least significant Varnode piece
|
||||||
Varnode *getHi(void) const { return hi; }
|
Varnode *getHi(void) const { return hi; } ///< Get the most significant Varnode piece
|
||||||
Varnode *getWhole(void) const { return whole; }
|
Varnode *getWhole(void) const { return whole; } ///< Get the Varnode representing \b this as a whole
|
||||||
PcodeOp *getDefPoint(void) const { return defpoint; }
|
PcodeOp *getDefPoint(void) const { return defpoint; } ///< Get the(final) defining PcodeOp of \b this
|
||||||
BlockBasic *getDefBlock(void) const { return defblock; }
|
BlockBasic *getDefBlock(void) const { return defblock; } ///< Get the defining basic block of \b this
|
||||||
uintb getValue(void) const { return val; }
|
uintb getValue(void) const { return val; } ///< Get the value of \b this, assuming it is a constant
|
||||||
bool isWholeFeasible(PcodeOp *existop);
|
bool isWholeFeasible(PcodeOp *existop); ///< Does a whole Varnode already exist or can it be created before the given PcodeOp
|
||||||
bool isWholePhiFeasible(FlowBlock *bl);
|
bool isWholePhiFeasible(FlowBlock *bl); ///< Does a whole Varnode already exist or can it be created before the given basic block
|
||||||
void findCreateWhole(Funcdata &data);
|
void findCreateWhole(Funcdata &data); ///< Create a \b whole Varnode for \b this, if it doesn't already exist
|
||||||
void findCreateOutputWhole(Funcdata &data);
|
void findCreateOutputWhole(Funcdata &data); ///< Create a \b whole Varnode that will be a PcodeOp output
|
||||||
void createJoinedWhole(Funcdata &data);
|
void createJoinedWhole(Funcdata &data); ///< Create a \b whole Varnode from pieces, respecting piece storage
|
||||||
void buildLoFromWhole(Funcdata &data);
|
void buildLoFromWhole(Funcdata &data); ///< Rebuild the least significant piece as a CPUI_SUBPIECE of the \b whole
|
||||||
void buildHiFromWhole(Funcdata &data);
|
void buildHiFromWhole(Funcdata &data); ///< Rebuild the most significant piece as a CPUI_SUBPIECE of the \b whole
|
||||||
PcodeOp *findEarliestSplitPoint(void);
|
PcodeOp *findEarliestSplitPoint(void); ///< Find the earliest definition point of the \b lo and \b hi pieces
|
||||||
PcodeOp *findOutExist(void);
|
PcodeOp *findOutExist(void); ///< Find the point at which the output \b whole must exist
|
||||||
static bool adjacentOffsets(Varnode *vn1,Varnode *vn2,uintb size1);
|
static bool adjacentOffsets(Varnode *vn1,Varnode *vn2,uintb size1);
|
||||||
static bool testContiguousLoad(PcodeOp *most,PcodeOp *least,bool allowfree,PcodeOp *&first,PcodeOp *&second,AddrSpace *&spc,int4 &sizeres);
|
static bool testContiguousPointers(PcodeOp *most,PcodeOp *least,PcodeOp *&first,PcodeOp *&second,AddrSpace *&spc);
|
||||||
static bool isAddrTiedContiguous(Varnode *lo,Varnode *hi,Address &res);
|
static bool isAddrTiedContiguous(Varnode *lo,Varnode *hi,Address &res);
|
||||||
static void wholeList(Varnode *w,vector<SplitVarnode> &splitvec);
|
static void wholeList(Varnode *w,vector<SplitVarnode> &splitvec);
|
||||||
static void findCopies(const SplitVarnode &in,vector<SplitVarnode> &splitvec);
|
static void findCopies(const SplitVarnode &in,vector<SplitVarnode> &splitvec);
|
||||||
|
@ -288,9 +296,16 @@ public:
|
||||||
bool applyRule(SplitVarnode &i,PcodeOp *ind,bool workishi,Funcdata &data);
|
bool applyRule(SplitVarnode &i,PcodeOp *ind,bool workishi,Funcdata &data);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// \brief Simply a double precision operation, starting from a marked double precision input.
|
||||||
|
///
|
||||||
|
/// This rule starts by trying to find a pair of Varnodes that are SUBPIECE from a whole,
|
||||||
|
/// are marked as double precision, and that are then used in some double precision operation.
|
||||||
|
/// The various operation \e forms are overlayed on the data-flow until a matching one is found. The
|
||||||
|
/// pieces of the double precision operation are then transformed into a single logical operation on the whole.
|
||||||
class RuleDoubleIn : public Rule {
|
class RuleDoubleIn : public Rule {
|
||||||
|
int4 attemptMarking(Funcdata &data,Varnode *vn,PcodeOp *subpieceOp);
|
||||||
public:
|
public:
|
||||||
RuleDoubleIn(const string &g) : Rule(g, 0, "doublein") {}
|
RuleDoubleIn(const string &g) : Rule(g, 0, "doublein") {} ///< Constructor
|
||||||
virtual Rule *clone(const ActionGroupList &grouplist) const {
|
virtual Rule *clone(const ActionGroupList &grouplist) const {
|
||||||
if (!grouplist.contains(getGroup())) return (Rule *)0;
|
if (!grouplist.contains(getGroup())) return (Rule *)0;
|
||||||
return new RuleDoubleIn(getGroup());
|
return new RuleDoubleIn(getGroup());
|
||||||
|
@ -309,7 +324,19 @@ public:
|
||||||
}
|
}
|
||||||
virtual void getOpList(vector<uint4> &oplist) const;
|
virtual void getOpList(vector<uint4> &oplist) const;
|
||||||
virtual int4 applyOp(PcodeOp *op,Funcdata &data);
|
virtual int4 applyOp(PcodeOp *op,Funcdata &data);
|
||||||
static PcodeOp *noWriteConflict(PcodeOp *op1,PcodeOp *op2,AddrSpace *spc);
|
static PcodeOp *noWriteConflict(PcodeOp *op1,PcodeOp *op2,AddrSpace *spc,vector<PcodeOp *> *indirects);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class RuleDoubleStore : public Rule {
|
||||||
|
public:
|
||||||
|
RuleDoubleStore(const string &g) : Rule( g, 0, "doublestore") {}
|
||||||
|
virtual Rule *clone(const ActionGroupList &grouplist) const {
|
||||||
|
if (!grouplist.contains(getGroup())) return (Rule *)0;
|
||||||
|
return new RuleDoubleStore(getGroup());
|
||||||
|
}
|
||||||
|
virtual void getOpList(vector<uint4> &oplist) const;
|
||||||
|
virtual int4 applyOp(PcodeOp *op,Funcdata &data);
|
||||||
|
static bool testIndirectUse(PcodeOp *op1,PcodeOp *op2,const vector<PcodeOp *> &indirects);
|
||||||
|
static void reassignIndirects(Funcdata &data,PcodeOp *newStore,const vector<PcodeOp *> &indirects);
|
||||||
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -236,7 +236,7 @@ void EmulateMemory::executeLoad(void)
|
||||||
|
|
||||||
{
|
{
|
||||||
uintb off = memstate->getValue(currentOp->getInput(1));
|
uintb off = memstate->getValue(currentOp->getInput(1));
|
||||||
AddrSpace *spc = Address::getSpaceFromConst(currentOp->getInput(0)->getAddr());
|
AddrSpace *spc = currentOp->getInput(0)->getSpaceFromConst();
|
||||||
|
|
||||||
off = AddrSpace::addressToByte(off,spc->getWordSize());
|
off = AddrSpace::addressToByte(off,spc->getWordSize());
|
||||||
uintb res = memstate->getValue(spc,off,currentOp->getOutput()->size);
|
uintb res = memstate->getValue(spc,off,currentOp->getOutput()->size);
|
||||||
|
@ -248,7 +248,7 @@ void EmulateMemory::executeStore(void)
|
||||||
{
|
{
|
||||||
uintb val = memstate->getValue(currentOp->getInput(2)); // Value being stored
|
uintb val = memstate->getValue(currentOp->getInput(2)); // Value being stored
|
||||||
uintb off = memstate->getValue(currentOp->getInput(1)); // Offset to store at
|
uintb off = memstate->getValue(currentOp->getInput(1)); // Offset to store at
|
||||||
AddrSpace *spc = Address::getSpaceFromConst(currentOp->getInput(0)->getAddr()); // Space to store in
|
AddrSpace *spc = currentOp->getInput(0)->getSpaceFromConst(); // Space to store in
|
||||||
|
|
||||||
off = AddrSpace::addressToByte(off,spc->getWordSize());
|
off = AddrSpace::addressToByte(off,spc->getWordSize());
|
||||||
memstate->setValue(spc,off,currentOp->getInput(2)->size,val);
|
memstate->setValue(spc,off,currentOp->getInput(2)->size,val);
|
||||||
|
|
|
@ -66,7 +66,7 @@ void EmulatePcodeOp::executeLoad(void)
|
||||||
{
|
{
|
||||||
// op will be null, use current_op
|
// op will be null, use current_op
|
||||||
uintb off = getVarnodeValue(currentOp->getIn(1));
|
uintb off = getVarnodeValue(currentOp->getIn(1));
|
||||||
AddrSpace *spc = Address::getSpaceFromConst(currentOp->getIn(0)->getAddr());
|
AddrSpace *spc = currentOp->getIn(0)->getSpaceFromConst();
|
||||||
off = AddrSpace::addressToByte(off,spc->getWordSize());
|
off = AddrSpace::addressToByte(off,spc->getWordSize());
|
||||||
int4 sz = currentOp->getOut()->getSize();
|
int4 sz = currentOp->getOut()->getSize();
|
||||||
uintb res = getLoadImageValue(spc,off,sz);
|
uintb res = getLoadImageValue(spc,off,sz);
|
||||||
|
@ -79,7 +79,7 @@ void EmulatePcodeOp::executeStore(void)
|
||||||
// There is currently nowhere to store anything since the memstate is null
|
// There is currently nowhere to store anything since the memstate is null
|
||||||
// uintb val = getVarnodeValue(current_op->getIn(2)); // Value being stored
|
// uintb val = getVarnodeValue(current_op->getIn(2)); // Value being stored
|
||||||
// uintb off = getVarnodeValue(current_op->getIn(1));
|
// uintb off = getVarnodeValue(current_op->getIn(1));
|
||||||
// AddrSpace *spc = Address::getSpaceFromConst(current_op->getIn(0)->getAddr());
|
// AddrSpace *spc = current_op->getIn(0)->getSpaceFromConst();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EmulatePcodeOp::executeCbranch(void)
|
bool EmulatePcodeOp::executeCbranch(void)
|
||||||
|
@ -120,7 +120,7 @@ void EmulatePcodeOp::executeIndirect(void)
|
||||||
void EmulatePcodeOp::executeSegmentOp(void)
|
void EmulatePcodeOp::executeSegmentOp(void)
|
||||||
|
|
||||||
{
|
{
|
||||||
SegmentOp *segdef = glb->userops.getSegmentOp(Address::getSpaceFromConst(currentOp->getIn(0)->getAddr())->getIndex());
|
SegmentOp *segdef = glb->userops.getSegmentOp(currentOp->getIn(0)->getSpaceFromConst()->getIndex());
|
||||||
if (segdef == (SegmentOp *)0)
|
if (segdef == (SegmentOp *)0)
|
||||||
throw LowlevelError("Segment operand missing definition");
|
throw LowlevelError("Segment operand missing definition");
|
||||||
|
|
||||||
|
@ -186,7 +186,7 @@ void EmulateSnippet::executeLoad(void)
|
||||||
{
|
{
|
||||||
// op will be null, use current_op
|
// op will be null, use current_op
|
||||||
uintb off = getVarnodeValue(currentOp->getInput(1));
|
uintb off = getVarnodeValue(currentOp->getInput(1));
|
||||||
AddrSpace *spc = Address::getSpaceFromConst(currentOp->getInput(0)->getAddr());
|
AddrSpace *spc = currentOp->getInput(0)->getSpaceFromConst();
|
||||||
off = AddrSpace::addressToByte(off,spc->getWordSize());
|
off = AddrSpace::addressToByte(off,spc->getWordSize());
|
||||||
int4 sz = currentOp->getOutput()->size;
|
int4 sz = currentOp->getOutput()->size;
|
||||||
uintb res = getLoadImageValue(spc,off,sz);
|
uintb res = getLoadImageValue(spc,off,sz);
|
||||||
|
|
|
@ -1345,7 +1345,7 @@ void Heritage::guardStores(const Address &addr,int4 size,vector<Varnode *> &writ
|
||||||
for(iter=fd->beginOp(CPUI_STORE);iter!=iterend;++iter) {
|
for(iter=fd->beginOp(CPUI_STORE);iter!=iterend;++iter) {
|
||||||
op = *iter;
|
op = *iter;
|
||||||
if (op->isDead()) continue;
|
if (op->isDead()) continue;
|
||||||
AddrSpace *storeSpace = Address::getSpaceFromConst(op->getIn(0)->getAddr());
|
AddrSpace *storeSpace = op->getIn(0)->getSpaceFromConst();
|
||||||
if ((container == storeSpace && op->usesSpacebasePtr()) ||
|
if ((container == storeSpace && op->usesSpacebasePtr()) ||
|
||||||
(spc == storeSpace)) {
|
(spc == storeSpace)) {
|
||||||
indop = fd->newIndirectOp(op,addr,size,PcodeOp::indirect_store);
|
indop = fd->newIndirectOp(op,addr,size,PcodeOp::indirect_store);
|
||||||
|
|
|
@ -79,7 +79,7 @@ void EmulateFunction::executeLoad(void)
|
||||||
{
|
{
|
||||||
if (collectloads) {
|
if (collectloads) {
|
||||||
uintb off = getVarnodeValue(currentOp->getIn(1));
|
uintb off = getVarnodeValue(currentOp->getIn(1));
|
||||||
AddrSpace *spc = Address::getSpaceFromConst(currentOp->getIn(0)->getAddr());
|
AddrSpace *spc = currentOp->getIn(0)->getSpaceFromConst();
|
||||||
off = AddrSpace::addressToByte(off,spc->getWordSize());
|
off = AddrSpace::addressToByte(off,spc->getWordSize());
|
||||||
int4 sz = currentOp->getOut()->getSize();
|
int4 sz = currentOp->getOut()->getSize();
|
||||||
loadpoints.push_back(LoadTable(Address(spc,off),sz));
|
loadpoints.push_back(LoadTable(Address(spc,off),sz));
|
||||||
|
|
|
@ -416,7 +416,7 @@ void PcodeOp::saveXml(ostream &s) const
|
||||||
}
|
}
|
||||||
else if (vn->getSpace()->getType()==IPTR_CONSTANT) {
|
else if (vn->getSpace()->getType()==IPTR_CONSTANT) {
|
||||||
if ((i==0)&&((code()==CPUI_STORE)||(code()==CPUI_LOAD))) {
|
if ((i==0)&&((code()==CPUI_STORE)||(code()==CPUI_LOAD))) {
|
||||||
AddrSpace *spc = Address::getSpaceFromConst(vn->getAddr());
|
AddrSpace *spc = vn->getSpaceFromConst();
|
||||||
s << "<spaceid";
|
s << "<spaceid";
|
||||||
a_v(s,"name",spc->getName());
|
a_v(s,"name",spc->getName());
|
||||||
s << "/>\n";
|
s << "/>\n";
|
||||||
|
|
|
@ -41,6 +41,9 @@ struct VarnodeData {
|
||||||
/// Get the location of the varnode as an address
|
/// Get the location of the varnode as an address
|
||||||
Address getAddr(void) const;
|
Address getAddr(void) const;
|
||||||
|
|
||||||
|
/// Treat \b this as a constant and recover encoded address space
|
||||||
|
AddrSpace *getSpaceFromConst(void) const;
|
||||||
|
|
||||||
/// Recover this object from an XML tag
|
/// Recover this object from an XML tag
|
||||||
void restoreXml(const Element *el,const AddrSpaceManager *manage);
|
void restoreXml(const Element *el,const AddrSpaceManager *manage);
|
||||||
|
|
||||||
|
@ -86,6 +89,11 @@ inline Address VarnodeData::getAddr(void) const {
|
||||||
return Address(space,offset);
|
return Address(space,offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \return the encoded AddrSpace
|
||||||
|
inline AddrSpace *VarnodeData::getSpaceFromConst(void) const {
|
||||||
|
return (AddrSpace *)(uintp)offset;
|
||||||
|
}
|
||||||
|
|
||||||
/// \brief A low-level representation of a single pcode operation
|
/// \brief A low-level representation of a single pcode operation
|
||||||
///
|
///
|
||||||
/// This is just the minimum amount of data to represent a pcode operation
|
/// This is just the minimum amount of data to represent a pcode operation
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -292,7 +291,7 @@ void PreferSplitManager::splitLoad(SplitInstance *inst,PcodeOp *op)
|
||||||
data->opSetOutput(hiop,inst->hi); // Outputs are the pieces of the original
|
data->opSetOutput(hiop,inst->hi); // Outputs are the pieces of the original
|
||||||
data->opSetOutput(loop,inst->lo);
|
data->opSetOutput(loop,inst->lo);
|
||||||
Varnode *spaceid = op->getIn(0);
|
Varnode *spaceid = op->getIn(0);
|
||||||
AddrSpace *spc = Address::getSpaceFromConst(spaceid->getAddr());
|
AddrSpace *spc = spaceid->getSpaceFromConst();
|
||||||
spaceid = data->newConstant(spaceid->getSize(),spaceid->getOffset()); // Duplicate original spaceid into new LOADs
|
spaceid = data->newConstant(spaceid->getSize(),spaceid->getOffset()); // Duplicate original spaceid into new LOADs
|
||||||
data->opSetInput(hiop,spaceid,0);
|
data->opSetInput(hiop,spaceid,0);
|
||||||
spaceid = data->newConstant(spaceid->getSize(),spaceid->getOffset());
|
spaceid = data->newConstant(spaceid->getSize(),spaceid->getOffset());
|
||||||
|
@ -343,7 +342,7 @@ void PreferSplitManager::splitStore(SplitInstance *inst,PcodeOp *op)
|
||||||
data->opSetInput(hiop,inst->hi,2); // Varnodes "being stored" are the pieces of the original
|
data->opSetInput(hiop,inst->hi,2); // Varnodes "being stored" are the pieces of the original
|
||||||
data->opSetInput(loop,inst->lo,2);
|
data->opSetInput(loop,inst->lo,2);
|
||||||
Varnode *spaceid = op->getIn(0);
|
Varnode *spaceid = op->getIn(0);
|
||||||
AddrSpace *spc = Address::getSpaceFromConst(spaceid->getAddr());
|
AddrSpace *spc = spaceid->getSpaceFromConst();
|
||||||
spaceid = data->newConstant(spaceid->getSize(),spaceid->getOffset()); // Duplicate original spaceid into new STOREs
|
spaceid = data->newConstant(spaceid->getSize(),spaceid->getOffset()); // Duplicate original spaceid into new STOREs
|
||||||
data->opSetInput(hiop,spaceid,0);
|
data->opSetInput(hiop,spaceid,0);
|
||||||
spaceid = data->newConstant(spaceid->getSize(),spaceid->getOffset());
|
spaceid = data->newConstant(spaceid->getSize(),spaceid->getOffset());
|
||||||
|
|
|
@ -3863,7 +3863,7 @@ AddrSpace *RuleLoadVarnode::checkSpacebase(Architecture *glb,PcodeOp *op,uintb &
|
||||||
AddrSpace *loadspace;
|
AddrSpace *loadspace;
|
||||||
|
|
||||||
offvn = op->getIn(1); // Address offset
|
offvn = op->getIn(1); // Address offset
|
||||||
loadspace = Address::getSpaceFromConst(op->getIn(0)->getAddr()); // Space being loaded/stored
|
loadspace = op->getIn(0)->getSpaceFromConst(); // Space being loaded/stored
|
||||||
// Treat segmentop as part of load/store
|
// Treat segmentop as part of load/store
|
||||||
if (offvn->isWritten()&&(offvn->getDef()->code()==CPUI_SEGMENTOP)) {
|
if (offvn->isWritten()&&(offvn->getDef()->code()==CPUI_SEGMENTOP)) {
|
||||||
offvn = offvn->getDef()->getIn(2);
|
offvn = offvn->getDef()->getIn(2);
|
||||||
|
@ -7734,7 +7734,7 @@ void RuleSegment::getOpList(vector<uint4> &oplist) const
|
||||||
int4 RuleSegment::applyOp(PcodeOp *op,Funcdata &data)
|
int4 RuleSegment::applyOp(PcodeOp *op,Funcdata &data)
|
||||||
|
|
||||||
{
|
{
|
||||||
SegmentOp *segdef = data.getArch()->userops.getSegmentOp(Address::getSpaceFromConst(op->getIn(0)->getAddr())->getIndex());
|
SegmentOp *segdef = data.getArch()->userops.getSegmentOp(op->getIn(0)->getSpaceFromConst()->getIndex());
|
||||||
if (segdef == (SegmentOp *)0)
|
if (segdef == (SegmentOp *)0)
|
||||||
throw LowlevelError("Segment operand missing definition");
|
throw LowlevelError("Segment operand missing definition");
|
||||||
|
|
||||||
|
@ -8038,7 +8038,7 @@ int4 RulePtrFlow::applyOp(PcodeOp *op,Funcdata &data)
|
||||||
case CPUI_LOAD:
|
case CPUI_LOAD:
|
||||||
case CPUI_STORE:
|
case CPUI_STORE:
|
||||||
vn = op->getIn(1);
|
vn = op->getIn(1);
|
||||||
spc = Address::getSpaceFromConst(op->getIn(0)->getAddr());
|
spc = op->getIn(0)->getSpaceFromConst();
|
||||||
if (vn->getSize() > spc->getAddrSize()) {
|
if (vn->getSize() > spc->getAddrSize()) {
|
||||||
vn = truncatePointer(spc,op,vn,1,data);
|
vn = truncatePointer(spc,op,vn,1,data);
|
||||||
madeChange = 1;
|
madeChange = 1;
|
||||||
|
|
|
@ -2196,7 +2196,7 @@ bool LaneDivide::buildStore(PcodeOp *op,int4 numLanes,int4 skipLanes)
|
||||||
if (inVars == (TransformVar *)0) return false;
|
if (inVars == (TransformVar *)0) return false;
|
||||||
uintb spaceConst = op->getIn(0)->getOffset();
|
uintb spaceConst = op->getIn(0)->getOffset();
|
||||||
int4 spaceConstSize = op->getIn(0)->getSize();
|
int4 spaceConstSize = op->getIn(0)->getSize();
|
||||||
AddrSpace *spc = Address::getSpaceFromConst(op->getIn(0)->getAddr()); // Address space being stored to
|
AddrSpace *spc = op->getIn(0)->getSpaceFromConst(); // Address space being stored to
|
||||||
Varnode *origPtr = op->getIn(1);
|
Varnode *origPtr = op->getIn(1);
|
||||||
if (origPtr->isFree()) {
|
if (origPtr->isFree()) {
|
||||||
if (!origPtr->isConstant()) return false;
|
if (!origPtr->isConstant()) return false;
|
||||||
|
@ -2244,7 +2244,7 @@ bool LaneDivide::buildLoad(PcodeOp *op,TransformVar *outVars,int4 numLanes,int4
|
||||||
{
|
{
|
||||||
uintb spaceConst = op->getIn(0)->getOffset();
|
uintb spaceConst = op->getIn(0)->getOffset();
|
||||||
int4 spaceConstSize = op->getIn(0)->getSize();
|
int4 spaceConstSize = op->getIn(0)->getSize();
|
||||||
AddrSpace *spc = Address::getSpaceFromConst(op->getIn(0)->getAddr()); // Address space being stored to
|
AddrSpace *spc = op->getIn(0)->getSpaceFromConst(); // Address space being stored to
|
||||||
Varnode *origPtr = op->getIn(1);
|
Varnode *origPtr = op->getIn(1);
|
||||||
if (origPtr->isFree()) {
|
if (origPtr->isFree()) {
|
||||||
if (!origPtr->isConstant()) return false;
|
if (!origPtr->isConstant()) return false;
|
||||||
|
|
|
@ -361,7 +361,7 @@ Datatype *TypeOpLoad::getInputCast(const PcodeOp *op,int4 slot,const CastStrateg
|
||||||
Datatype *reqtype = op->getOut()->getHighTypeDefFacing(); // Cast load pointer to match output
|
Datatype *reqtype = op->getOut()->getHighTypeDefFacing(); // Cast load pointer to match output
|
||||||
const Varnode *invn = op->getIn(1);
|
const Varnode *invn = op->getIn(1);
|
||||||
Datatype *curtype = invn->getHighTypeReadFacing(op);
|
Datatype *curtype = invn->getHighTypeReadFacing(op);
|
||||||
AddrSpace *spc = Address::getSpaceFromConst(op->getIn(0)->getAddr());
|
AddrSpace *spc = op->getIn(0)->getSpaceFromConst();
|
||||||
// Its possible that the input type is not a pointer to the output type
|
// Its possible that the input type is not a pointer to the output type
|
||||||
// (or even a pointer) due to cycle trimming in the type propagation algorithms
|
// (or even a pointer) due to cycle trimming in the type propagation algorithms
|
||||||
if (curtype->getMetatype() == TYPE_PTR)
|
if (curtype->getMetatype() == TYPE_PTR)
|
||||||
|
@ -408,7 +408,7 @@ Datatype *TypeOpLoad::propagateType(Datatype *alttype,PcodeOp *op,Varnode *invn,
|
||||||
if (invn->isSpacebase()) return (Datatype *)0;
|
if (invn->isSpacebase()) return (Datatype *)0;
|
||||||
Datatype *newtype;
|
Datatype *newtype;
|
||||||
if (inslot == -1) { // Propagating output to input (value to ptr)
|
if (inslot == -1) { // Propagating output to input (value to ptr)
|
||||||
AddrSpace *spc = Address::getSpaceFromConst(op->getIn(0)->getAddr());
|
AddrSpace *spc = op->getIn(0)->getSpaceFromConst();
|
||||||
newtype = tlst->getTypePointerNoDepth(outvn->getTempType()->getSize(),alttype,spc->getWordSize());
|
newtype = tlst->getTypePointerNoDepth(outvn->getTempType()->getSize(),alttype,spc->getWordSize());
|
||||||
}
|
}
|
||||||
else if (alttype->getMetatype()==TYPE_PTR) {
|
else if (alttype->getMetatype()==TYPE_PTR) {
|
||||||
|
@ -426,7 +426,7 @@ void TypeOpLoad::printRaw(ostream &s,const PcodeOp *op)
|
||||||
{
|
{
|
||||||
Varnode::printRaw(s,op->getOut());
|
Varnode::printRaw(s,op->getOut());
|
||||||
s << " = *(";
|
s << " = *(";
|
||||||
AddrSpace *spc = Address::getSpaceFromConst(op->getIn(0)->getAddr());
|
AddrSpace *spc = op->getIn(0)->getSpaceFromConst();
|
||||||
s << spc->getName() << ',';
|
s << spc->getName() << ',';
|
||||||
Varnode::printRaw(s,op->getIn(1));
|
Varnode::printRaw(s,op->getIn(1));
|
||||||
s << ')';
|
s << ')';
|
||||||
|
@ -447,7 +447,7 @@ Datatype *TypeOpStore::getInputCast(const PcodeOp *op,int4 slot,const CastStrate
|
||||||
Datatype *pointerType = pointerVn->getHighTypeReadFacing(op);
|
Datatype *pointerType = pointerVn->getHighTypeReadFacing(op);
|
||||||
Datatype *pointedToType = pointerType;
|
Datatype *pointedToType = pointerType;
|
||||||
Datatype *valueType = op->getIn(2)->getHighTypeReadFacing(op);
|
Datatype *valueType = op->getIn(2)->getHighTypeReadFacing(op);
|
||||||
AddrSpace *spc = Address::getSpaceFromConst(op->getIn(0)->getAddr());
|
AddrSpace *spc = op->getIn(0)->getSpaceFromConst();
|
||||||
int4 destSize;
|
int4 destSize;
|
||||||
if (pointerType->getMetatype() == TYPE_PTR) {
|
if (pointerType->getMetatype() == TYPE_PTR) {
|
||||||
pointedToType = ((TypePointer *)pointerType)->getPtrTo();
|
pointedToType = ((TypePointer *)pointerType)->getPtrTo();
|
||||||
|
@ -483,7 +483,7 @@ Datatype *TypeOpStore::propagateType(Datatype *alttype,PcodeOp *op,Varnode *invn
|
||||||
if (invn->isSpacebase()) return (Datatype *)0;
|
if (invn->isSpacebase()) return (Datatype *)0;
|
||||||
Datatype *newtype;
|
Datatype *newtype;
|
||||||
if (inslot==2) { // Propagating value to ptr
|
if (inslot==2) { // Propagating value to ptr
|
||||||
AddrSpace *spc = Address::getSpaceFromConst(op->getIn(0)->getAddr());
|
AddrSpace *spc = op->getIn(0)->getSpaceFromConst();
|
||||||
newtype = tlst->getTypePointerNoDepth(outvn->getTempType()->getSize(),alttype,spc->getWordSize());
|
newtype = tlst->getTypePointerNoDepth(outvn->getTempType()->getSize(),alttype,spc->getWordSize());
|
||||||
}
|
}
|
||||||
else if (alttype->getMetatype()==TYPE_PTR) {
|
else if (alttype->getMetatype()==TYPE_PTR) {
|
||||||
|
@ -500,7 +500,7 @@ void TypeOpStore::printRaw(ostream &s,const PcodeOp *op)
|
||||||
|
|
||||||
{
|
{
|
||||||
s << "*(";
|
s << "*(";
|
||||||
AddrSpace *spc = Address::getSpaceFromConst(op->getIn(0)->getAddr());
|
AddrSpace *spc = op->getIn(0)->getSpaceFromConst();
|
||||||
s << spc->getName() << ',';
|
s << spc->getName() << ',';
|
||||||
Varnode::printRaw(s,op->getIn(1));
|
Varnode::printRaw(s,op->getIn(1));
|
||||||
s << ") = ";
|
s << ") = ";
|
||||||
|
@ -2183,7 +2183,7 @@ void TypeOpSegment::printRaw(ostream &s,const PcodeOp *op)
|
||||||
}
|
}
|
||||||
s << getOperatorName(op);
|
s << getOperatorName(op);
|
||||||
s << '(';
|
s << '(';
|
||||||
AddrSpace *spc = Address::getSpaceFromConst(op->getIn(0)->getAddr());
|
AddrSpace *spc = op->getIn(0)->getSpaceFromConst();
|
||||||
s << spc->getName() << ',';
|
s << spc->getName() << ',';
|
||||||
Varnode::printRaw(s,op->getIn(1));
|
Varnode::printRaw(s,op->getIn(1));
|
||||||
s << ',';
|
s << ',';
|
||||||
|
|
|
@ -169,6 +169,7 @@ public:
|
||||||
|
|
||||||
const Address &getAddr(void) const { return (const Address &) loc; } ///< Get the storage Address
|
const Address &getAddr(void) const { return (const Address &) loc; } ///< Get the storage Address
|
||||||
AddrSpace *getSpace(void) const { return loc.getSpace(); } ///< Get the AddrSpace storing this Varnode
|
AddrSpace *getSpace(void) const { return loc.getSpace(); } ///< Get the AddrSpace storing this Varnode
|
||||||
|
AddrSpace *getSpaceFromConst(void) const; ///< Get AddrSpace from \b this encoded constant Varnode
|
||||||
uintb getOffset(void) const { return loc.getOffset(); } ///< Get the offset (within its AddrSpace) where this is stored
|
uintb getOffset(void) const { return loc.getOffset(); } ///< Get the offset (within its AddrSpace) where this is stored
|
||||||
int4 getSize(void) const { return size; } ///< Get the number of bytes this Varnode stores
|
int4 getSize(void) const { return size; } ///< Get the number of bytes this Varnode stores
|
||||||
int2 getMergeGroup(void) const { return mergegroup; } ///< Get the \e forced \e merge group of this Varnode
|
int2 getMergeGroup(void) const { return mergegroup; } ///< Get the \e forced \e merge group of this Varnode
|
||||||
|
@ -408,4 +409,12 @@ struct TraverseNode {
|
||||||
bool contiguous_test(Varnode *vn1,Varnode *vn2); ///< Test if Varnodes are pieces of a whole
|
bool contiguous_test(Varnode *vn1,Varnode *vn2); ///< Test if Varnodes are pieces of a whole
|
||||||
Varnode *findContiguousWhole(Funcdata &data,Varnode *vn1,
|
Varnode *findContiguousWhole(Funcdata &data,Varnode *vn1,
|
||||||
Varnode *vn2); ///< Retrieve the whole Varnode given pieces
|
Varnode *vn2); ///< Retrieve the whole Varnode given pieces
|
||||||
|
|
||||||
|
/// In \b LOAD and \b STORE instructions, the particular address space being read/written is encoded
|
||||||
|
/// as a constant Varnode. Internally, this constant is the actual pointer to the AddrSpace.
|
||||||
|
/// \return the AddrSpace pointer
|
||||||
|
inline AddrSpace *Varnode::getSpaceFromConst(void) const {
|
||||||
|
return (AddrSpace *)(uintp)loc.getOffset();
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue