refactor SubflowFlow

This commit is contained in:
caheckman 2019-10-11 14:19:58 -04:00
parent 3ff4e64b1d
commit 6e90520dd0
5 changed files with 184 additions and 394 deletions

View file

@ -7699,13 +7699,13 @@ int4 RuleSubfloatConvert::applyOp(PcodeOp *op,Funcdata &data)
if (outsize > insize) {
SubfloatFlow subflow(&data,outvn,insize);
if (!subflow.doTrace()) return 0;
subflow.doReplacement();
subflow.apply();
return 1;
}
else {
SubfloatFlow subflow(&data,invn,outsize);
if (!subflow.doTrace()) return 0;
subflow.doReplacement();
subflow.apply();
return 1;
}
return 0;

View file

@ -1235,7 +1235,7 @@ SubvariableFlow::SubvariableFlow(Funcdata *f,Varnode *root,uintb mask,bool aggr,
bool SubvariableFlow::doTrace(void)
{ // Process worklist until its done
{
pullcount = 0;
bool retval = false;
if (fd != (Funcdata *)0) {
@ -1629,135 +1629,77 @@ bool SplitFlow::doTrace(void)
return true;
}
SubfloatFlow::ReplaceVarnode *SubfloatFlow::setReplacement(Varnode *vn,bool &inworklist)
/// \brief Create and return a placeholder associated with the given Varnode
///
/// Add the placeholder to the worklist if it hasn't been visited before
/// \param vn is the given Varnode
/// \return the placeholder or null if the Varnode is not suitable for replacement
TransformVar *SubfloatFlow::setReplacement(Varnode *vn)
{ // Create and return a ReplaceVarnode associated with vn, if vn is suitable for replacement
// Set inworklist to true if the varnode has not been in the worklist before
// Return NULL if the vn is not suitable for replacement
ReplaceVarnode *res;
if (vn->isMark()) { // Already seen before
map<Varnode *,ReplaceVarnode>::iterator iter;
iter = varmap.find(vn);
res = &(*iter).second;
inworklist = false;
return res;
}
{
if (vn->isMark()) // Already seen before
return getPiece(vn, precision*8, 0);
if (vn->isConstant()) {
inworklist = false;
return addConstant(vn);
const FloatFormat *form2 = getFunction()->getArch()->translate->getFloatFormat(vn->getSize());
if (form2 == (const FloatFormat *)0)
return (TransformVar *)0; // Unsupported constant format
// Return the converted form of the constant
return newConstant(precision, 0, format->convertEncoding(vn->getOffset(),form2));
}
if (vn->isFree())
return (ReplaceVarnode *)0; // Abort
return (TransformVar *)0; // Abort
if (vn->isAddrForce() && (vn->getSize() != precision))
return (ReplaceVarnode *)0;
return (TransformVar *)0;
if (vn->isTypeLock()) {
int4 sz = vn->getType()->getSize();
if (sz != precision)
return (ReplaceVarnode *)0;
return (TransformVar *)0;
}
if (vn->isInput()) { // Must be careful with inputs
if (vn->getSize() != precision) return (ReplaceVarnode *)0;
if (vn->getSize() != precision) return (TransformVar *)0;
}
res = & varmap[ vn ];
vn->setMark();
res->vn = vn;
res->replacement = (Varnode *)0;
res->def = (ReplaceOp *)0;
inworklist = true;
TransformVar *res;
// Check if vn already represents the logical variable being traced
if (vn->getSize() == precision) {
inworklist = false;
res->replacement = vn;
if (vn->getSize() == precision)
res = newPreexistingVarnode(vn);
else {
res = newPiece(vn, precision*8, 0);
worklist.push_back(res);
}
return res;
}
SubfloatFlow::ReplaceVarnode *SubfloatFlow::setReplacementNoFlow(Varnode *vn)
/// \brief Try to trace logical variable through descendant Varnodes
///
/// Given a Varnode placeholder, look at all descendent PcodeOps and create
/// placeholders for the op and its output Varnode. If appropriate add the
/// output placeholder to the worklist.
/// \param rvn is the given Varnode placeholder
/// \return \b true if tracing the logical variable forward was possible
bool SubfloatFlow::traceForward(TransformVar *rvn)
{ // Create and return a ReplaceVarnode associated with vn, where we assume -vn- is not going to change
// and there will be no further logical flow through -vn-
ReplaceVarnode *res;
if (vn->isMark()) { // Already seen before
map<Varnode *,ReplaceVarnode>::iterator iter;
iter = varmap.find(vn);
res = &(*iter).second;
return res;
}
if (!vn->isConstant()) {
if (vn->isFree()) // If we have an unheritaged value
return (ReplaceVarnode *)0; // Abort
}
res = &varmap[ vn ];
vn->setMark();
res->vn = vn;
res->replacement = vn; // NOTE: we set replacement as itself, even if it is a constant
res->def = (ReplaceOp *)0;
return res;
}
SubfloatFlow::ReplaceOp *SubfloatFlow::createOp(OpCode opc,int4 numparam,ReplaceVarnode *outrvn)
{ // Create record for replacement op, given its replacement varnode output
if (outrvn->def != (ReplaceOp *)0)
return outrvn->def;
oplist.push_back(ReplaceOp());
ReplaceOp *rop = &oplist.back();
outrvn->def = rop;
rop->op = outrvn->vn->getDef();
rop->numparams = numparam;
rop->opc = opc;
rop->output = outrvn;
return rop;
}
SubfloatFlow::ReplaceOp *SubfloatFlow::createOpDown(OpCode opc,int4 numparam,PcodeOp *op,ReplaceVarnode *inrvn,int4 slot)
{ // Create record for replacement op, given one of its input replacement varnodes
oplist.push_back(ReplaceOp());
ReplaceOp *rop = &oplist.back();
rop->op = op;
rop->opc = opc;
rop->numparams = numparam;
rop->output = (ReplaceVarnode *)0;
while(rop->input.size() <= slot)
rop->input.push_back((ReplaceVarnode *)0);
rop->input[slot] = inrvn;
return rop;
}
bool SubfloatFlow::traceForward(ReplaceVarnode *rvn)
{ // Try to trace logical variable through descendant varnodes
// updating list/map of replace_ops and replace_varnodes
// and the worklist
ReplaceVarnode *rvn2;
ReplaceOp *rop;
PcodeOp *op;
Varnode *outvn;
int4 slot;
bool inworklist;
{
int4 dcount = 0;
int4 hcount = 0;
list<PcodeOp *>::const_iterator iter,enditer;
iter = rvn->vn->beginDescend();
enditer = rvn->vn->endDescend();
Varnode *vn = rvn->getOriginal();
iter = vn->beginDescend();
enditer = vn->endDescend();
while(iter != enditer) {
op = *iter++;
outvn = op->getOut();
PcodeOp *op = *iter++;
Varnode *outvn = op->getOut();
if ((outvn!=(Varnode *)0)&&(outvn->isMark()))
continue;
dcount += 1; // Count this descendant
slot = op->getSlot(rvn->vn);
int4 slot = op->getSlot(vn);
switch(op->code()) {
case CPUI_COPY:
case CPUI_FLOAT_CEIL:
@ -1771,54 +1713,77 @@ bool SubfloatFlow::traceForward(ReplaceVarnode *rvn)
case CPUI_FLOAT_MULT:
case CPUI_FLOAT_DIV:
case CPUI_MULTIEQUAL:
rop = createOpDown(op->code(),op->numInput(),op,rvn,slot);
if (!createLink(rop,-1,outvn)) return false;
{
TransformOp *rop = newOpReplace(op->numInput(), op->code(), op);
TransformVar *outrvn = setReplacement(outvn);
if (outrvn == (TransformVar *)0) return false;
opSetInput(rop,rvn,slot);
opSetOutput(rop,outrvn);
hcount += 1; // Dealt with this descendant
break;
}
case CPUI_FLOAT_FLOAT2FLOAT:
{
if (outvn->getSize() < precision)
return false;
addtopulllist(op,rvn);
TransformOp *rop = newPreexistingOp(1, (outvn->getSize() == precision) ? CPUI_COPY : CPUI_FLOAT_FLOAT2FLOAT, op);
opSetInput(rop,rvn,0);
hcount += 1; // Dealt with this descendant
terminatorCount += 1;
break;
}
case CPUI_FLOAT_EQUAL:
case CPUI_FLOAT_NOTEQUAL:
case CPUI_FLOAT_LESS:
case CPUI_FLOAT_LESSEQUAL:
rvn2 = setReplacement(op->getIn(1-slot),inworklist);
if (rvn2 == (ReplaceVarnode *)0) return false;
if (inworklist)
worklist.push_back(rvn2);
if (slot == 0)
addtocomplist(rvn,rvn2,op);
else
addtocomplist(rvn2,rvn,op);
{
TransformVar *rvn2 = setReplacement(op->getIn(1-slot));
if (rvn2 == (TransformVar *)0) return false;
TransformOp *rop = newPreexistingOp(2, op->code(), op);
if (slot == 0) {
opSetInput(rop,rvn,0);
opSetInput(rop,rvn2,1);
}
else {
opSetInput(rop,rvn2,0);
opSetInput(rop,rvn,1);
}
hcount += 1; // Dealt with this descendant
terminatorCount += 1;
break;
}
case CPUI_FLOAT_TRUNC:
case CPUI_FLOAT_NAN:
addtopulllist(op,rvn);
{
TransformOp *rop = newPreexistingOp(1,op->code(), op);
opSetInput(rop,rvn,0);
hcount += 1;
terminatorCount += 1;
break;
}
default:
return false;
}
}
if (dcount != hcount) {
// Must account for all descendants of an input
if (rvn->vn->isInput()) return false;
if (vn->isInput()) return false;
}
return true;
}
bool SubfloatFlow::traceBackward(ReplaceVarnode *rvn)
/// \brief Trace a logical value backward through defining op one level
///
/// Given an existing variable placeholder look at the op defining it and
/// define placeholder variables for all its inputs. Put the new placeholders
/// onto the worklist if appropriate.
/// \param rvn is the given variable placeholder
/// \return \b true if the logical value can be traced properly
bool SubfloatFlow::traceBackward(TransformVar *rvn)
{ // Trace backward through defining op one level
// Update worklist, varmap, and oplist
// return false if the trace is aborted
PcodeOp *op = rvn->vn->getDef();
{
PcodeOp *op = rvn->getOriginal()->getDef();
if (op == (PcodeOp *)0) return true; // If vn is input
ReplaceOp *rop;
switch(op->code()) {
case CPUI_COPY:
@ -1833,20 +1798,56 @@ bool SubfloatFlow::traceBackward(ReplaceVarnode *rvn)
case CPUI_FLOAT_MULT:
case CPUI_FLOAT_DIV:
case CPUI_MULTIEQUAL:
rop = createOp(op->code(),op->numInput(),rvn);
for(int4 i=0;i<op->numInput();++i)
if (!createLink(rop,i,op->getIn(i))) // Same inputs and mask
{
TransformOp *rop = rvn->getDef();
if (rop == (TransformOp *)0) {
rop = newOpReplace(op->numInput(), op->code(), op);
opSetOutput(rop, rvn);
}
for(int4 i=0;i<op->numInput();++i) {
TransformVar *newvar = rop->getIn(i);
if (newvar == (TransformVar *)0) {
newvar = setReplacement(op->getIn(i));
if (newvar == (TransformVar *)0)
return false;
}
}
return true;
}
case CPUI_FLOAT_INT2FLOAT:
if (addtopushlist(op,rvn))
return true;
{
Varnode *vn = op->getIn(0);
if (!vn->isConstant() && vn->isFree())
return false;
TransformOp *rop = newOpReplace(1, CPUI_FLOAT_INT2FLOAT, op);
TransformVar *newvar = getPreexistingVarnode(vn);
opSetInput(rop,newvar,0);
break;
}
case CPUI_FLOAT_FLOAT2FLOAT:
// if ((op->getIn(0)->getSize() <= precision)||op->getIn(0)->isConstant())
if (addtopushlist(op,rvn))
return true;
{
Varnode *vn = op->getIn(0);
TransformVar *newvar;
OpCode opc;
if (vn->isConstant()) {
opc = CPUI_COPY;
if (vn->getSize() == precision)
newvar = newConstant(precision, 0, vn->getOffset());
else {
newvar = setReplacement(vn); // Convert constant to precision size
if (newvar == (TransformVar *)0)
return false; // Unsupported float format
}
}
else {
if (vn->isFree()) return false;
opc = (vn->getSize() == precision) ? CPUI_COPY : CPUI_FLOAT_FLOAT2FLOAT;
newvar = getPreexistingVarnode(vn);
}
TransformOp *rop = newOpReplace(1, opc, op);
opSetInput(rop,newvar,0);
break;
}
default:
break; // Everything else we abort
}
@ -1854,143 +1855,16 @@ bool SubfloatFlow::traceBackward(ReplaceVarnode *rvn)
return false;
}
bool SubfloatFlow::createLink(ReplaceOp *rop,int4 slot,Varnode *vn)
{ // Add a new varnode (and the edge which traced to it) to the worklist
bool inworklist;
ReplaceVarnode *rep = setReplacement(vn,inworklist);
if (rep == (ReplaceVarnode *)0) return false;
if (rop != (ReplaceOp *)0) {
if (slot == -1) {
rop->output = rep;
rep->def = rop;
}
else {
while(rop->input.size() <= slot)
rop->input.push_back((ReplaceVarnode *)0);
rop->input[slot] = rep;
}
}
if (inworklist)
worklist.push_back(rep);
return true;
}
SubfloatFlow::ReplaceVarnode *SubfloatFlow::addConstant(Varnode *vn)
{ // Add a constant to the replacement tree
const FloatFormat *form2 = fd->getArch()->translate->getFloatFormat(vn->getSize());
if (form2 == (const FloatFormat *)0)
return (ReplaceVarnode *)0; // Unsupported constant format
newvarlist.push_back(ReplaceVarnode());
ReplaceVarnode *res = &newvarlist.back();
res->vn = vn;
res->replacement = (Varnode *)0;
res->def = (ReplaceOp *)0;
return res;
}
void SubfloatFlow::addtopulllist(PcodeOp *pullop,ReplaceVarnode *rvn)
{ // Exit point of the logical flow
// Add a reference to the logical variable getting pulled
// out of container flow
pulllist.push_back(PulloutRecord());
pulllist.back().pullop = pullop; // Operation pulling the variable out
if (pullop->code() == CPUI_FLOAT_FLOAT2FLOAT) {
if (pullop->getOut()->getSize() == precision)
pulllist.back().opc = CPUI_COPY;
else
pulllist.back().opc = CPUI_FLOAT_FLOAT2FLOAT;
}
else
pulllist.back().opc = pullop->code();
pulllist.back().input = rvn; // Point in container flow for pull
}
bool SubfloatFlow::addtopushlist(PcodeOp *pushop,ReplaceVarnode *rvn)
{ // Entry point of the logical flow
Varnode *invn = pushop->getIn(0);
OpCode opc = pushop->code();
if (opc == CPUI_FLOAT_FLOAT2FLOAT) {
if ((invn->getSize() == precision)||invn->isConstant())
opc = CPUI_COPY;
}
ReplaceOp *rop = createOp(opc,1,rvn);
if ((opc == CPUI_FLOAT_INT2FLOAT)||
((opc == CPUI_FLOAT_FLOAT2FLOAT)&&(invn->getSize() > precision))) {
// We do not want to create a new input replacement, but want to keep the old
ReplaceVarnode *rvn = setReplacementNoFlow(invn);
if (rvn == (ReplaceVarnode *)0)
return false;
rop->input.push_back(rvn);
return true;
}
return createLink(rop,0,invn);
}
void SubfloatFlow::addtocomplist(ReplaceVarnode *in1,ReplaceVarnode *in2,PcodeOp *op)
{
complist.push_back(CompareRecord());
complist.back().in1 = in1;
complist.back().in2 = in2;
complist.back().compop = op;
}
void SubfloatFlow::replaceInput(ReplaceVarnode *rvn)
{ // Replace ORIGINAL input in the subgraph with temporaries, so
// we don't get overlapping varnode errors
Varnode *newvn = fd->newUnique(rvn->vn->getSize());
newvn = fd->setInputVarnode(newvn);
fd->totalReplace(rvn->vn,newvn);
fd->deleteVarnode(rvn->vn);
rvn->vn = newvn;
}
Varnode *SubfloatFlow::getReplaceVarnode(ReplaceVarnode *rvn)
{ // Get the actual varnode associated with a replacement varnode
// either by recycling a previously built one or creating
// one on the spot
if (rvn->replacement != (Varnode *)0) {
if (!rvn->replacement->isConstant())
return rvn->replacement;
// if replacement is a constant (this was generated in setReplacementNoFlow) create copy of original constant
return fd->newConstant(rvn->replacement->getSize(),rvn->replacement->getOffset());
}
if (rvn->vn->isConstant()) { // A constant
const FloatFormat *formin = fd->getArch()->translate->getFloatFormat(rvn->vn->getSize());
// addConstant makes sure that formin is not null
return fd->newConstant(precision,format->convertEncoding(rvn->vn->getOffset(),formin));
}
bool isinput = rvn->vn->isInput();
if (isinput) {
Address addr = rvn->vn->getAddr();
// This is sort of fundemental problem: how do we represent an input variable that
// is lower precision than its storage location
// Here we artificially truncate the location, which isn't realistic
if (addr.isBigEndian())
addr = addr + (rvn->vn->getSize() - precision);
replaceInput(rvn); // Replace input to avoid overlap errors
rvn->replacement = fd->newVarnode(precision,addr);
}
else
rvn->replacement = fd->newUnique(precision);
if (isinput) // Is this an input
rvn->replacement = fd->setInputVarnode(rvn->replacement);
return rvn->replacement;
}
/// \brief Push the trace one hop from the placeholder at the top of the worklist
///
/// The logical value for the value on top of the worklist stack is pushed back
/// to the input Varnodes of the operation defining it. Then the value is pushed
/// forward through all operations that read it.
/// \return \b true if the trace is successfully pushed
bool SubfloatFlow::processNextWork(void)
{
ReplaceVarnode *rvn = worklist.back();
TransformVar *rvn = worklist.back();
worklist.pop_back();
@ -1998,84 +1872,46 @@ bool SubfloatFlow::processNextWork(void)
return traceForward(rvn);
}
/// \param f is the function being transformed
/// \param root is the start Varnode containing the logical value
/// \param prec is the precision to assume for the logical value
SubfloatFlow::SubfloatFlow(Funcdata *f,Varnode *root,int4 prec)
: TransformManager(f)
{
fd = f;
precision = prec;
format = fd->getArch()->translate->getFloatFormat(precision);
createLink((ReplaceOp *)0,0,root);
format = f->getArch()->translate->getFloatFormat(precision);
if (format == (const FloatFormat *)0)
return;
setReplacement(root);
}
bool SubfloatFlow::preserveAddress(Varnode *vn,int4 bitSize,int4 lsbOffset) const
{
return vn->isInput(); // Only try to preserve address for input varnodes
}
/// The interpretation that the root Varnode contains a logical value with
/// smaller precision is pushed through the data-flow. If the interpretation is
/// inconsistent, \b false is returned. Otherwise a transform is constructed that
/// makes the smaller precision the explicit size of Varnodes within the data-flow.
/// \return \b true if a transform consistent with the given precision can be built
bool SubfloatFlow::doTrace(void)
{ // Process worklist until its done
bool retval = false;
if ((fd != (Funcdata *)0)&&
(format != (const FloatFormat *)0)) {
retval = true;
{
if (format == (const FloatFormat *)0)
return false;
bool retval = true;
while(!worklist.empty()) {
if (!processNextWork()) {
retval = false;
break;
}
}
}
// Clear marks
map<Varnode *,ReplaceVarnode>::iterator iter;
for(iter=varmap.begin();iter!=varmap.end();++iter)
(*iter).first->clearMark();
clearVarnodeMarks();
if (!retval) return false;
if (pulllist.empty()&&complist.empty()) return false;
if (terminatorCount == 0) return false;
return true;
}
void SubfloatFlow::doReplacement(void)
{ // Create the actual replacement data-flow with -fd-
list<ReplaceOp>::iterator iter;
// Define all the outputs first
for(iter=oplist.begin();iter!=oplist.end();++iter) {
PcodeOp *newop = fd->newOp((*iter).numparams,(*iter).op->getAddr());
(*iter).replacement = newop;
fd->opSetOpcode(newop,(*iter).opc);
ReplaceVarnode *rout = (*iter).output;
if (rout != (ReplaceVarnode *)0) {
if (rout->replacement == (Varnode *)0)
rout->replacement = fd->newUniqueOut(precision,newop);
else
fd->opSetOutput(newop,rout->replacement);
}
fd->opInsertAfter(newop,(*iter).op);
}
// Set all the inputs
for(iter=oplist.begin();iter!=oplist.end();++iter) {
PcodeOp *newop = (*iter).replacement;
for(uint4 i=0;i<(*iter).input.size();++i)
fd->opSetInput(newop,getReplaceVarnode((*iter).input[i]),i);
}
// These are operations that carry flow from the small variable into an existing
// variable of the correct size
list<PulloutRecord>::iterator piter;
for(piter=pulllist.begin();piter!=pulllist.end();++piter) {
PcodeOp *pullop = (*piter).pullop;
while(pullop->numInput() > 1)
fd->opRemoveInput(pullop,pullop->numInput()-1);
fd->opSetInput(pullop,getReplaceVarnode((*piter).input),0);
if (pullop->code() != (*piter).opc)
fd->opSetOpcode(pullop,(*piter).opc);
}
list<CompareRecord>::iterator citer;
for(citer=complist.begin();citer!=complist.end();++citer) {
PcodeOp *op = (*citer).compop;
fd->opSetInput(op,getReplaceVarnode((*citer).in1),0);
fd->opSetInput(op,getReplaceVarnode((*citer).in2),1);
}
}

View file

@ -129,74 +129,24 @@ public:
bool doTrace(void); ///< Trace split through data-flow, constructing transform
};
// Structures for tracing floating point variables if they are
// stored at points in a higher precision encoding. This is nearly identical
// in spirit to the SubvariableFlow class, but it performs on floating point
// variables contained in higher precision storage, rather than integers stored
// as a subfield of a bigger integer
// This the floating point version of SubvariablFlow, it follows the flow of a logical lower
// precision value stored in higher precision locations
class SubfloatFlow {
class ReplaceOp;
class ReplaceVarnode {
friend class SubfloatFlow;
Varnode *vn; // Varnode being split
Varnode *replacement; // The new subvariable varnode
ReplaceOp *def; // Defining op for new varnode
};
class ReplaceOp {
friend class SubfloatFlow;
PcodeOp *op; // op getting paralleled
PcodeOp *replacement; // The new op
OpCode opc; // type of new op
int4 numparams;
ReplaceVarnode *output; // varnode output
vector<ReplaceVarnode *> input; // varnode inputs
};
class PulloutRecord { // Node where logical variable is getting pulled out into a real varnode
friend class SubfloatFlow;
OpCode opc; // (possibly) new opcode
PcodeOp *pullop; // Op producing the real output
ReplaceVarnode *input; // The logical variable input
};
class CompareRecord {
friend class SubfloatFlow;
ReplaceVarnode *in1;
ReplaceVarnode *in2;
PcodeOp *compop;
};
int4 precision; // Number of bytes of precision in the logical flow
Funcdata *fd;
const FloatFormat *format;
map<Varnode *,ReplaceVarnode> varmap;
list<ReplaceVarnode> newvarlist;
list<ReplaceOp> oplist;
list<PulloutRecord> pulllist;
list<CompareRecord> complist;
vector<ReplaceVarnode *> worklist;
ReplaceVarnode *setReplacement(Varnode *vn,bool &inworklist);
ReplaceVarnode *setReplacementNoFlow(Varnode *vn);
ReplaceOp *createOp(OpCode opc,int4 numparam,ReplaceVarnode *outrvn);
ReplaceOp *createOpDown(OpCode opc,int4 numparam,PcodeOp *op,ReplaceVarnode *inrvn,int4 slot);
bool traceForward(ReplaceVarnode *rvn);
bool traceBackward(ReplaceVarnode *rvn);
bool createLink(ReplaceOp *rop,int4 slot,Varnode *vn);
void addtopulllist(PcodeOp *pullop,ReplaceVarnode *rvn);
bool addtopushlist(PcodeOp *pushop,ReplaceVarnode *rvn);
void addtocomplist(ReplaceVarnode *in1,ReplaceVarnode *in2,PcodeOp *op);
ReplaceVarnode *addConstant(Varnode *vn);
void replaceInput(ReplaceVarnode *rvn);
Varnode *getReplaceVarnode(ReplaceVarnode *rvn);
/// \brief Class for tracing changes of precision in floating point variables
///
/// It follows the flow of a logical lower precision value stored in higher precision locations
/// and then rewrites the data-flow in terms of the lower precision, eliminating the
/// precision conversions.
class SubfloatFlow : public TransformManager {
int4 precision; ///< Number of bytes of precision in the logical flow
int4 terminatorCount; ///< Number of terminating nodes reachable via the root
const FloatFormat *format; ///< The floating-point format of the logical value
vector<TransformVar *> worklist; ///< Current list of placeholders that still need to be traced
TransformVar *setReplacement(Varnode *vn);
bool traceForward(TransformVar *rvn);
bool traceBackward(TransformVar *rvn);
bool processNextWork(void);
public:
SubfloatFlow(Funcdata *f,Varnode *root,int4 prec);
bool doTrace(void);
void doReplacement(void);
virtual bool preserveAddress(Varnode *vn,int4 bitSize,int4 lsbOffset) const;
bool doTrace(void); ///< Trace logical value as far as possible
};
#endif

View file

@ -200,6 +200,7 @@ TransformVar *TransformManager::newPreexistingVarnode(Varnode *vn)
res->def = (TransformOp *)0;
res->type = TransformVar::preexisting;
res->flags = TransformVar::split_terminator;
res->val = 0; // Treat this as "piece" of itself at offset 0, allows getPiece() to find this
return res;
}
@ -397,6 +398,8 @@ TransformOp *TransformManager::newPreexistingOp(int4 numParams,OpCode opc,PcodeO
TransformVar *TransformManager::getPreexistingVarnode(Varnode *vn)
{
if (vn->isConstant())
return newConstant(vn->getSize(), 0, vn->getOffset());
map<int4,TransformVar *>::const_iterator iter;
iter = pieceMap.find(vn->getCreateIndex());
if (iter != pieceMap.end())

View file

@ -121,6 +121,7 @@ public:
TransformManager(Funcdata *f) { fd = f; } ///< Constructor
virtual ~TransformManager(void); ///< Destructor
virtual bool preserveAddress(Varnode *vn,int4 bitSize,int4 lsbOffset) const;
Funcdata *getFunction(void) const { return fd; }
void clearVarnodeMarks(void); ///< Clear mark for all Varnodes in the map
TransformVar *newPreexistingVarnode(Varnode *vn); ///< Make placeholder for preexisting Varnode
TransformVar *newUnique(int4 size); ///< Make placeholder for new unique space Varnode