#include "varnode.hh"
#include "funcdata.hh"
inline bool VarnodeCompareLocDef::operator()(const Varnode *a,const Varnode *b) const
{
uint4 f1,f2;
if (a->getAddr() != b->getAddr()) return (a->getAddr() < b->getAddr());
if (a->getSize() != b->getSize()) return (a->getSize() < b->getSize());
f1 = a->getFlags()&(Varnode::input|Varnode::written);
f2 = b->getFlags()&(Varnode::input|Varnode::written);
if (f1!=f2) return ((f1-1)<(f2-1)); if (f1==Varnode::written) {
if (a->getDef()->getSeqNum() != b->getDef()->getSeqNum())
return (a->getDef()->getSeqNum() < b->getDef()->getSeqNum());
}
else if (f1 == 0) return (a->getCreateIndex() < b->getCreateIndex());
return false;
}
inline bool VarnodeCompareDefLoc::operator()(const Varnode *a,const Varnode *b) const
{
uint4 f1,f2;
f1 = (a->getFlags() & (Varnode::input|Varnode::written));
f2 = (b->getFlags() & (Varnode::input|Varnode::written));
if (f1!=f2) return ((f1-1)<(f2-1));
if (f1==Varnode::written) {
if (a->getDef()->getSeqNum() != b->getDef()->getSeqNum())
return (a->getDef()->getSeqNum() < b->getDef()->getSeqNum());
}
if (a->getAddr() != b->getAddr()) return (a->getAddr() < b->getAddr());
if (a->getSize() != b->getSize()) return (a->getSize() < b->getSize());
if (f1==0) return (a->getCreateIndex() < b->getCreateIndex());
return false;
}
HighVariable *Varnode::getHigh(void) const
{
if (high==(HighVariable *)0)
throw LowlevelError("Requesting non-existent high-level");
return high;
}
int4 Varnode::contains(const Varnode &op) const
{
if (loc.getSpace() != op.loc.getSpace()) return 3;
if (loc.getSpace()->getType()==IPTR_CONSTANT) return 3;
uintb a = loc.getOffset();
uintb b = op.loc.getOffset();
if (b<a) return -1;
if (b>=a+size) return 2;
if (b+op.size > a+size) return 1;
return 0;
}
bool Varnode::intersects(const Varnode &op) const
{
if (loc.getSpace() != op.loc.getSpace()) return false;
if (loc.getSpace()->getType()==IPTR_CONSTANT) return false;
uintb a = loc.getOffset();
uintb b = op.loc.getOffset();
if (b<a) {
if (a>=b+op.size) return false;
return true;
}
if (b>=a+size) return false;
return true;
}
bool Varnode::intersects(const Address &op2loc,int4 op2size) const
{
if (loc.getSpace() != op2loc.getSpace()) return false;
if (loc.getSpace()->getType()==IPTR_CONSTANT) return false;
uintb a = loc.getOffset();
uintb b = op2loc.getOffset();
if (b<a) {
if (a>=b+op2size) return false;
return true;
}
if (b>=a+size) return false;
return true;
}
int4 Varnode::characterizeOverlap(const Varnode &op) const
{
if (loc.getSpace() != op.loc.getSpace())
return 0;
if (loc.getOffset() == op.loc.getOffset()) return (size == op.size) ? 2 : 1; else if (loc.getOffset() < op.loc.getOffset()) {
uintb thisright = loc.getOffset() + (size-1);
return (thisright < op.loc.getOffset()) ? 0: 1; }
else {
uintb opright = op.loc.getOffset() + (op.size-1);
return (opright < loc.getOffset()) ? 0: 1; }
}
int4 Varnode::overlap(const Varnode &op) const
{
if (!loc.isBigEndian()) return loc.overlap(0,op.loc,op.size);
else { int4 over = loc.overlap(size-1,op.loc,op.size);
if (over != -1)
return op.size-1-over;
}
return -1;
}
int4 Varnode::overlap(const Address &op2loc,int4 op2size) const
{
if (!loc.isBigEndian()) return loc.overlap(0,op2loc,op2size);
else { int4 over = loc.overlap(size-1,op2loc,op2size);
if (over != -1)
return op2size-1-over;
}
return -1;
}
void Varnode::updateCover(void) const
{
if ((flags & Varnode::coverdirty)!=0) {
if (hasCover()&&(cover!=(Cover *)0))
cover->rebuild(this);
clearFlags(Varnode::coverdirty);
}
}
void Varnode::clearCover(void) const
{
if (cover != (Cover *)0) {
delete cover;
cover = (Cover *)0;
}
}
void Varnode::calcCover(void) const
{
if (hasCover()) {
if (cover != (Cover *)0)
delete cover;
cover = new Cover;
setFlags(Varnode::coverdirty);
}
}
void Varnode::printCover(ostream &s) const
{
if (cover == (Cover *)0)
throw LowlevelError("No cover to print");
if ((flags & Varnode::coverdirty)!=0)
s << "Cover is dirty" << endl;
else
cover->print(s);
}
void Varnode::printInfo(ostream &s) const
{
type->printRaw(s);
s << " = ";
printRaw(s);
if (isAddrTied())
s << " tied";
if (isMapped())
s << " mapped";
if (isPersist())
s << " persistent";
if (isTypeLock())
s << " tlock";
if (isNameLock())
s << " nlock";
if (isSpacebase())
s << " base";
if (isUnaffected())
s << " unaff";
if (isImplied())
s << " implied";
if (isAddrForce())
s << " addrforce";
if (isReadOnly())
s << " readonly";
s << " (consumed=0x" << hex << consumed << ')';
s << " (internal=" << hex << this << ')';
s << " (create=0x" << hex << create_index << ')';
s << endl;
}
void Varnode::eraseDescend(PcodeOp *op)
{
list<PcodeOp *>::iterator iter;
iter = descend.begin();
while (*iter != op) iter++;
descend.erase(iter); setFlags(Varnode::coverdirty);
}
void Varnode::addDescend(PcodeOp *op)
{
if (isFree()&&(!isSpacebase())) {
if (!descend.empty())
throw LowlevelError("Free varnode has multiple descendants");
}
descend.push_back(op);
setFlags(Varnode::coverdirty);
}
void Varnode::destroyDescend(void)
{
descend.clear();
}
void Varnode::setFlags(uint4 fl) const
{
flags |= fl;
if (high != (HighVariable *)0) {
high->flagsDirty();
if ((fl&Varnode::coverdirty)!=0)
high->coverDirty();
}
}
void Varnode::clearFlags(uint4 fl) const
{
flags &= ~fl;
if (high != (HighVariable *)0) {
high->flagsDirty();
if ((fl&Varnode::coverdirty)!=0)
high->coverDirty();
}
}
void Varnode::setDef(PcodeOp *op)
{ def = op;
if (op==(PcodeOp *)0) {
setFlags(Varnode::coverdirty);
clearFlags(Varnode::written);
}
else
setFlags(Varnode::coverdirty|Varnode::written);
}
bool Varnode::setSymbolProperties(SymbolEntry *entry)
{
bool res = entry->updateType(this);
if (entry->getSymbol()->isTypeLocked()) {
if (mapentry != entry) {
mapentry = entry;
if (high != (HighVariable *)0)
high->setSymbol(this);
res = true;
}
}
setFlags(entry->getAllFlags() & ~Varnode::typelock);
return res;
}
void Varnode::setSymbolEntry(SymbolEntry *entry)
{
mapentry = entry;
uint4 fl = Varnode::mapped; if (entry->getSymbol()->isNameLocked())
fl |= Varnode::namelock;
setFlags(fl);
if (high != (HighVariable *)0)
high->setSymbol(this);
}
void Varnode::setSymbolReference(SymbolEntry *entry,int4 off)
{
if (high != (HighVariable *)0) {
high->setSymbolReference(entry->getSymbol(), off);
}
}
bool Varnode::updateType(Datatype *ct,bool lock,bool override)
{
if (ct->getMetatype() == TYPE_UNKNOWN) lock = false;
if (isTypeLock()&&(!override)) return false; if ((type == ct)&&(isTypeLock()==lock)) return false; flags &= ~Varnode::typelock;
if (lock)
flags |= Varnode::typelock;
type = ct;
if (high != (HighVariable *)0)
high->typeDirty();
return true;
}
void Varnode::copySymbol(const Varnode *vn)
{
type = vn->type; mapentry = vn->mapentry; flags &= ~(Varnode::typelock | Varnode::namelock);
flags |= (Varnode::typelock | Varnode::namelock) & vn->flags;
if (high != (HighVariable *)0) {
high->typeDirty();
if (mapentry != (SymbolEntry *)0)
high->setSymbol(this);
}
}
void Varnode::copySymbolIfValid(const Varnode *vn)
{
SymbolEntry *mapEntry = vn->getSymbolEntry();
if (mapEntry == (SymbolEntry *)0)
return;
EquateSymbol *sym = dynamic_cast<EquateSymbol *>(mapEntry->getSymbol());
if (sym == (EquateSymbol *) 0)
return;
if (sym->isValueClose(loc.getOffset(), size)) {
copySymbol(vn); }
}
bool Varnode::operator<(const Varnode &op2) const
{
uint4 f1,f2;
if (loc != op2.loc) return (loc < op2.loc);
if (size != op2.size) return (size < op2.size);
f1 = flags&(Varnode::input|Varnode::written);
f2 = op2.flags&(Varnode::input|Varnode::written);
if (f1!=f2) return ((f1-1)<(f2-1)); if (f1==Varnode::written)
if (def->getSeqNum() != op2.def->getSeqNum())
return (def->getSeqNum() < op2.def->getSeqNum());
return false;
}
bool Varnode::operator==(const Varnode &op2) const
{ uint4 f1,f2;
if (loc != op2.loc) return false;
if (size != op2.size) return false;
f1 = flags&(Varnode::input|Varnode::written);
f2 = op2.flags&(Varnode::input|Varnode::written);
if (f1!=f2) return false;
if (f1==Varnode::written)
if (def->getSeqNum() != op2.def->getSeqNum()) return false;
return true;
}
Varnode::Varnode(int4 s,const Address &m,Datatype *dt)
: loc(m)
{ size = s;
def = (PcodeOp *)0; type = dt;
high = (HighVariable *)0;
mapentry = (SymbolEntry *)0;
consumed = ~((uintb)0);
cover = (Cover *)0;
mergegroup = 0;
addlflags = 0;
if (m.getSpace() == (AddrSpace *)0) {
flags = 0;
return;
}
spacetype tp = m.getSpace()->getType();
if (tp==IPTR_CONSTANT) {
flags = Varnode::constant;
nzm = m.getOffset();
}
else if ((tp==IPTR_FSPEC)||(tp==IPTR_IOP)) {
flags = Varnode::annotation|Varnode::coverdirty;
nzm = ~((uintb)0);
}
else {
flags = Varnode::coverdirty;
nzm = ~((uintb)0);
}
}
Varnode::~Varnode(void)
{
if (cover != (Cover *)0)
delete cover;
if (high != (HighVariable *)0) {
high->remove(this);
if (high->isUnattached())
delete high;
}
}
PcodeOp *Varnode::loneDescend(void) const
{
PcodeOp *op;
if (descend.empty()) return (PcodeOp *)0;
list<PcodeOp *>::const_iterator iter;
iter = descend.begin();
op = *iter++; if (iter != descend.end()) return (PcodeOp *)0; return op;
}
Address Varnode::getUsePoint(const Funcdata &fd) const
{
if (isWritten())
return def->getAddr();
return fd.getAddress()+-1;
}
int4 Varnode::printRawNoMarkup(ostream &s) const
{
AddrSpace *spc = loc.getSpace();
const Translate *trans = spc->getTrans();
string name;
int4 expect;
name = trans->getRegisterName(spc,loc.getOffset(),size);
if (name.size()!=0) {
const VarnodeData &point(trans->getRegister(name));
uintb off = loc.getOffset()-point.offset;
s << name;
expect = point.size;
if (off != 0)
s << '+' << dec << off;
}
else {
s << loc.getShortcut(); expect = trans->getDefaultSize();
loc.printRaw(s);
}
return expect;
}
void Varnode::printRaw(ostream &s) const
{
int4 expect = printRawNoMarkup(s);
if (expect != size)
s << ':' << setw(1) << size;
if ((flags&Varnode::input)!=0)
s << "(i)";
if (isWritten())
s << '(' << def->getSeqNum() << ')';
if ((flags&(Varnode::insert|Varnode::constant))==0) {
s << "(free)";
return;
}
}
void Varnode::printRawHeritage(ostream &s,int4 depth) const
{
for(int4 i=0;i<depth;++i)
s << ' ';
if (isConstant()) {
printRaw(s);
s << endl;
return;
}
printRaw(s);
s << ' ';
if (def != (PcodeOp *)0)
def->printRaw(s);
else
printRaw(s);
if ((flags & Varnode::input)!=0)
s << " Input";
if ((flags & Varnode::constant)!=0)
s << " Constant";
if ((flags & Varnode::annotation)!=0)
s << " Code";
if (def != (PcodeOp *)0) {
s << "\t\t" << def->getSeqNum() << endl;
for(int4 i=0;i<def->numInput();++i)
def->getIn(i)->printRawHeritage(s,depth+5);
}
else
s << endl;
}
int4 Varnode::isConstantExtended(uintb &val) const
{
if (isConstant()) {
val = getOffset();
return 0;
}
if (!isWritten()) return -1;
OpCode opc = def->code();
if (opc == CPUI_INT_ZEXT) {
Varnode *vn0 = def->getIn(0);
if (vn0->isConstant()) {
val = vn0->getOffset();
return 1;
}
}
else if (opc == CPUI_INT_SEXT) {
Varnode *vn0 = def->getIn(0);
if (vn0->isConstant()) {
val = vn0->getOffset();
return 2;
}
}
return -1;
}
Datatype *Varnode::getLocalType(bool &blockup) const
{
Datatype *ct;
Datatype *newct;
if (isTypeLock()) return type;
ct = (Datatype *)0;
if (def != (PcodeOp *)0) {
ct = def->outputTypeLocal();
if (def->stopsPropagation()) {
blockup = true;
return ct;
}
}
list<PcodeOp *>::const_iterator iter;
PcodeOp *op;
int4 i;
for(iter=descend.begin();iter!=descend.end();++iter) {
op = *iter;
i = op->getSlot(this);
newct = op->inputTypeLocal(i);
if (ct == (Datatype *)0)
ct = newct;
else {
if (0>newct->typeOrder(*ct))
ct = newct;
}
}
if (ct == (Datatype *)0)
throw LowlevelError("NULL local type");
return ct;
}
bool Varnode::copyShadow(const Varnode *op2) const
{
const Varnode *vn;
if (this==op2) return true;
vn = this;
while( (vn->isWritten()) && (vn->getDef()->code() == CPUI_COPY)) {
vn = vn->getDef()->getIn(0);
if (vn == op2) return true; }
while( (op2->isWritten()) && (op2->getDef()->code() == CPUI_COPY)) {
op2 = op2->getDef()->getIn(0);
if (vn == op2) return true; }
return false;
}
int4 Varnode::termOrder(const Varnode *op) const
{
if (isConstant()) {
if (!op->isConstant()) return 1;
}
else {
if (op->isConstant()) return -1;
const Varnode *vn = this;
if (vn->isWritten()&&(vn->getDef()->code() == CPUI_INT_MULT))
if (vn->getDef()->getIn(1)->isConstant())
vn = vn->getDef()->getIn(0);
if (op->isWritten()&&(op->getDef()->code() == CPUI_INT_MULT))
if (op->getDef()->getIn(1)->isConstant())
op = op->getDef()->getIn(0);
if (vn->getAddr() < op->getAddr()) return -1;
if (op->getAddr() < vn->getAddr()) return 1;
}
return 0;
}
void Varnode::saveXml(ostream &s) const
{
s << "<addr";
loc.getSpace()->saveXmlAttributes(s,loc.getOffset(),size);
a_v_u(s,"ref",getCreateIndex());
if (mergegroup != 0)
a_v_i(s,"grp",getMergeGroup());
if (isPersist())
s << " persists=\"true\"";
if (isAddrTied())
s << " addrtied=\"true\"";
if (isUnaffected())
s << " unaff=\"true\"";
if (isInput())
s << " input=\"true\"";
s << "/>";
}
void Varnode::printRaw(ostream &s,const Varnode *vn)
{
if (vn == (const Varnode *)0) {
s << "<null>";
return;
}
vn->printRaw(s);
}
VarnodeBank::VarnodeBank(AddrSpaceManager *m)
: searchvn(0,Address(Address::m_minimal),(Datatype *)0)
{
manage = m;
searchvn.flags = Varnode::input; uniq_space = m->getUniqueSpace();
uniqbase = uniq_space->getTrans()->getUniqueStart(Translate::ANALYSIS);
uniqid = uniqbase;
create_index = 0;
}
void VarnodeBank::clear(void)
{
VarnodeLocSet::iterator iter;
for(iter=loc_tree.begin();iter!=loc_tree.end();++iter)
delete *iter;
loc_tree.clear();
def_tree.clear();
uniqid = uniqbase; create_index = 0; }
Varnode *VarnodeBank::create(int4 s,const Address &m,Datatype *ct)
{
Varnode *vn = new Varnode(s,m,ct);
vn->create_index = create_index++;
vn->lociter = loc_tree.insert(vn).first; vn->defiter = def_tree.insert(vn).first;
return vn;
}
Varnode *VarnodeBank::createUnique(int4 s,Datatype *ct)
{
Address addr(uniq_space,uniqid); uniqid += s; return create(s,addr,ct); }
void VarnodeBank::destroy(Varnode *vn)
{
if ((vn->getDef() != (PcodeOp *)0)||(!vn->hasNoDescend()))
throw LowlevelError("Deleting integrated varnode");
loc_tree.erase(vn->lociter);
def_tree.erase(vn->defiter);
delete vn;
}
Varnode *VarnodeBank::xref(Varnode *vn)
{
pair<VarnodeLocSet::iterator,bool> check;
Varnode *othervn;
check = loc_tree.insert( vn );
if (!check.second) { othervn = *(check.first);
replace(vn,othervn); delete vn;
return othervn;
}
vn->lociter = check.first;
vn->setFlags(Varnode::insert);
vn->defiter = def_tree.insert(vn).first;
return vn;
}
void VarnodeBank::makeFree(Varnode *vn)
{
loc_tree.erase(vn->lociter);
def_tree.erase(vn->defiter);
vn->setDef((PcodeOp *)0); vn->clearFlags(Varnode::insert|Varnode::input|Varnode::indirect_creation);
vn->lociter = loc_tree.insert(vn).first; vn->defiter = def_tree.insert(vn).first;
}
void VarnodeBank::replace(Varnode *oldvn,Varnode *newvn)
{
list<PcodeOp *>::iterator iter,tmpiter;
PcodeOp *op;
int4 i;
iter = oldvn->descend.begin();
while(iter!=oldvn->descend.end()) {
op = *iter;
tmpiter = iter++;
if (op->output == newvn) continue; i = op->getSlot(oldvn);
oldvn->descend.erase(tmpiter); op->clearInput(i); newvn->addDescend(op);
op->setInput(newvn,i); }
oldvn->setFlags(Varnode::coverdirty);
newvn->setFlags(Varnode::coverdirty);
}
Varnode *VarnodeBank::setInput(Varnode *vn)
{
if (!vn->isFree())
throw LowlevelError("Making input out of varnode which is not free");
if (vn->isConstant())
throw LowlevelError("Making input out of constant varnode");
loc_tree.erase(vn->lociter); def_tree.erase(vn->defiter);
vn->setInput(); return xref(vn);
}
Varnode *VarnodeBank::setDef(Varnode *vn,PcodeOp *op)
{
if (!vn->isFree()) {
ostringstream s;
const Address &addr(op->getAddr());
s << "Defining varnode which is not free at " << addr.getShortcut();
addr.printRaw(s);
throw LowlevelError(s.str());
}
if (vn->isConstant()) {
ostringstream s;
const Address &addr(op->getAddr());
s << "Assignment to constant at " << addr.getShortcut();
addr.printRaw(s);
throw LowlevelError(s.str());
}
loc_tree.erase(vn->lociter);
def_tree.erase(vn->defiter);
vn->setDef(op); return xref(vn);
}
Varnode *VarnodeBank::createDef(int4 s,const Address &m, Datatype *ct,PcodeOp *op)
{
Varnode *vn = new Varnode(s,m,ct);
vn->create_index = create_index++;
vn->setDef(op);
return xref(vn);
}
Varnode *VarnodeBank::createDefUnique(int4 s,Datatype *ct,PcodeOp *op)
{ Address addr(uniq_space,uniqid);
uniqid += s;
return createDef(s,addr,ct,op);
}
Varnode *VarnodeBank::find(int4 s,const Address &loc,const Address &pc,uintm uniq) const
{
VarnodeLocSet::const_iterator iter;
Varnode *vn;
PcodeOp *op;
iter = beginLoc(s,loc,pc,uniq);
while(iter != loc_tree.end()) {
vn = *iter;
if (vn->getSize() != s) break;
if (vn->getAddr() != loc) break;
op = vn->getDef();
if ((op!=(PcodeOp *)0)&&(op->getAddr() == pc)) {
if ((uniq==~((uintm)0))||(op->getTime()==uniq)) return vn;
}
++iter;
}
return (Varnode *)0;
}
Varnode *VarnodeBank::findInput(int4 s,const Address &loc) const
{
VarnodeLocSet::const_iterator iter;
Varnode *vn;
iter = beginLoc(s,loc,Varnode::input);
if (iter != loc_tree.end()) { vn = *iter;
if (vn->isInput() && (vn->getSize()==s) && (vn->getAddr()==loc))
return vn;
}
return (Varnode *)0;
}
Varnode *VarnodeBank::findCoveredInput(int4 s,const Address &loc) const
{
VarnodeDefSet::const_iterator iter,enditer;
Varnode *vn;
uintb highest = loc.getSpace()->getHighest();
uintb end = loc.getOffset() + s - 1;
iter = beginDef(Varnode::input,loc);
if (end==highest) { Address tmp(loc.getSpace(),highest);
enditer = endDef(Varnode::input,tmp);
}
else
enditer = beginDef(Varnode::input,loc+s);
while(iter!=enditer) {
vn = *iter++; if (vn->getOffset()+vn->getSize()-1 <= end) return vn;
}
return (Varnode *)0;
}
Varnode *VarnodeBank::findCoveringInput(int4 s,const Address &loc) const
{
VarnodeDefSet::const_iterator iter;
Varnode *vn;
iter = beginDef(Varnode::input,loc);
if (iter != def_tree.end()) {
vn = *iter;
if ((vn->getAddr() != loc)&&(iter!=def_tree.begin())) {
--iter;
vn = *iter;
}
if (vn->isInput() && (vn->getSpace() == loc.getSpace()) &&
(vn->getOffset() <= loc.getOffset()) &&
(vn->getOffset() + vn->getSize()-1 >= loc.getOffset() + s -1))
return vn;
}
return (Varnode *)0;
}
VarnodeLocSet::const_iterator VarnodeBank::beginLoc(AddrSpace *spaceid) const
{
searchvn.loc = Address(spaceid,0);
return loc_tree.lower_bound(&searchvn);
}
VarnodeLocSet::const_iterator VarnodeBank::endLoc(AddrSpace *spaceid) const
{
searchvn.loc = Address(manage->getNextSpaceInOrder(spaceid),0);
return loc_tree.lower_bound(&searchvn);
}
VarnodeLocSet::const_iterator VarnodeBank::beginLoc(const Address &addr) const
{
searchvn.loc = addr;
return loc_tree.lower_bound(&searchvn);
}
VarnodeLocSet::const_iterator VarnodeBank::endLoc(const Address &addr) const
{
if (addr.getOffset() == addr.getSpace()->getHighest()) {
AddrSpace* space = addr.getSpace();
searchvn.loc = Address(manage->getNextSpaceInOrder(space),0);
}
else
searchvn.loc = addr+1;
return loc_tree.lower_bound(&searchvn);
}
VarnodeLocSet::const_iterator VarnodeBank::beginLoc(int4 s,const Address &addr) const
{
searchvn.size = s;
searchvn.loc = addr;
VarnodeLocSet::const_iterator iter = loc_tree.lower_bound(&searchvn);
searchvn.size = 0; return iter;
}
VarnodeLocSet::const_iterator VarnodeBank::endLoc(int4 s,const Address &addr) const
{
searchvn.size = s+1;
searchvn.loc = addr;
VarnodeLocSet::const_iterator iter = loc_tree.lower_bound(&searchvn);
searchvn.size = 0; return iter;
}
VarnodeLocSet::const_iterator VarnodeBank::beginLoc(int4 s,const Address &addr,
uint4 fl) const
{
VarnodeLocSet::const_iterator iter;
if (fl == Varnode::input) {
searchvn.size = s;
searchvn.loc = addr;
iter = loc_tree.lower_bound(&searchvn);
searchvn.size = 0;
return iter;
}
if (fl == Varnode::written) {
SeqNum sq(Address::m_minimal); PcodeOp searchop(0,sq);
searchvn.size = s;
searchvn.loc = addr;
searchvn.flags = Varnode::written;
searchvn.def = &searchop;
iter = loc_tree.lower_bound(&searchvn);
searchvn.size = 0;
searchvn.flags = Varnode::input;
return iter;
}
SeqNum sq(Address::m_maximal); PcodeOp searchop(0,sq);
searchvn.size = s;
searchvn.loc = addr;
searchvn.flags = Varnode::written;
searchvn.def = &searchop;
iter = loc_tree.upper_bound(&searchvn);
searchvn.size = 0;
searchvn.flags = Varnode::input;
return iter;
}
VarnodeLocSet::const_iterator VarnodeBank::endLoc(int4 s,const Address &addr,
uint4 fl) const
{
VarnodeLocSet::const_iterator iter;
searchvn.loc = addr;
if (fl == Varnode::written) {
searchvn.size = s;
searchvn.flags = Varnode::written;
SeqNum sq(Address::m_maximal); PcodeOp searchop(0,sq);
searchvn.def = &searchop;
iter = loc_tree.upper_bound(&searchvn);
searchvn.size = 0;
searchvn.flags = Varnode::input;
return iter;
}
else if (fl == Varnode::input) {
searchvn.size = s;
iter = loc_tree.upper_bound(&searchvn);
searchvn.size = 0;
return iter;
}
searchvn.size = s+1;
iter = loc_tree.lower_bound(&searchvn); searchvn.size = 0;
return iter;
}
VarnodeLocSet::const_iterator VarnodeBank::beginLoc(int4 s,const Address &addr,
const Address &pc,uintm uniq) const
{ VarnodeLocSet::const_iterator iter;
searchvn.size = s;
searchvn.loc = addr;
searchvn.flags = Varnode::written;
if (uniq==~((uintm)0)) uniq = 0; SeqNum sq(pc,uniq);
PcodeOp searchop(0,sq);
searchvn.def = &searchop;
iter = loc_tree.lower_bound(&searchvn);
searchvn.size = 0;
searchvn.flags = Varnode::input;
return iter;
}
VarnodeLocSet::const_iterator VarnodeBank::endLoc(int4 s,const Address &addr,
const Address &pc,uintm uniq) const
{
VarnodeLocSet::const_iterator iter;
searchvn.size = s;
searchvn.loc = addr;
searchvn.flags = Varnode::written;
SeqNum sq(pc,uniq);
PcodeOp searchop(0,sq);
searchvn.def = &searchop;
iter = loc_tree.upper_bound(&searchvn);
searchvn.size = 0;
searchvn.flags = Varnode::input;
return iter;
}
VarnodeDefSet::const_iterator VarnodeBank::beginDef(uint4 fl) const
{
VarnodeDefSet::const_iterator iter;
if (fl == Varnode::input)
return def_tree.begin(); else if (fl == Varnode::written) {
searchvn.loc = Address(Address::m_minimal); searchvn.flags = Varnode::written;
SeqNum sq(Address::m_minimal); PcodeOp searchop(0,sq);
searchvn.def = &searchop;
iter = def_tree.lower_bound(&searchvn);
searchvn.flags = Varnode::input; return iter;
}
searchvn.loc = Address(Address::m_maximal); searchvn.flags = Varnode::written;
SeqNum sq(Address::m_maximal); PcodeOp searchop(0,sq);
searchvn.def = &searchop;
iter = def_tree.upper_bound(&searchvn);
searchvn.flags = Varnode::input; return iter;
}
VarnodeDefSet::const_iterator VarnodeBank::endDef(uint4 fl) const
{
VarnodeDefSet::const_iterator iter;
if (fl == Varnode::input) { searchvn.loc = Address(Address::m_minimal); searchvn.flags = Varnode::written;
SeqNum sq(Address::m_minimal); PcodeOp searchop(0,sq);
searchvn.def = &searchop;
iter = def_tree.lower_bound(&searchvn);
searchvn.flags = Varnode::input; return iter;
}
else if (fl == Varnode::written) { searchvn.loc = Address(Address::m_maximal); searchvn.flags = Varnode::written;
SeqNum sq(Address::m_maximal); PcodeOp searchop(0,sq);
searchvn.def = &searchop;
iter = def_tree.upper_bound(&searchvn);
searchvn.flags = Varnode::input; return iter;
}
return def_tree.end(); }
VarnodeDefSet::const_iterator VarnodeBank::beginDef(uint4 fl,const Address &addr) const
{ VarnodeDefSet::const_iterator iter;
if (fl == Varnode::written)
throw LowlevelError("Cannot get contiguous written AND addressed");
else if (fl == Varnode::input) {
searchvn.loc = addr;
iter = def_tree.lower_bound(&searchvn);
return iter;
}
searchvn.loc = addr;
searchvn.flags = 0;
iter = def_tree.upper_bound(&searchvn);
searchvn.flags = Varnode::input; return iter;
}
VarnodeDefSet::const_iterator VarnodeBank::endDef(uint4 fl,const Address &addr) const
{
VarnodeDefSet::const_iterator iter;
if (fl == Varnode::written)
throw LowlevelError("Cannot get contiguous written AND addressed");
else if (fl == Varnode::input) {
searchvn.loc = addr;
searchvn.size = 1000000;
iter = def_tree.lower_bound(&searchvn);
searchvn.size = 0;
return iter;
}
searchvn.loc = addr;
searchvn.size = 1000000;
searchvn.flags = 0;
iter = def_tree.lower_bound(&searchvn);
searchvn.flags = Varnode::input; searchvn.size = 0;
return iter;
}
#ifdef VARBANK_DEBUG
void VarnodeBank::verifyIntegrity(void) const
{
VarnodeLocSet::iterator iter;
Varnode *vn,*lastvn;
if (loc_tree.empty()) return;
iter = loc_tree.begin();
lastvn = *iter++;
if (def_tree.end() == def_tree.find(lastvn))
throw LowlevelError("Varbank first loc missing in def");
for(;iter!=loc_tree.end();++iter) {
vn = *iter;
if (def_tree.end() == def_tree.find(vn))
throw LowlevelError("Varbank loc missing in def");
if (*vn < *lastvn)
throw LowlevelError("Varbank locdef integrity test failed");
lastvn = vn;
}
VarnodeDefSet::iterator diter;
VarnodeCompareDefLoc cmp;
diter = def_tree.begin();
lastvn = *diter++;
if (loc_tree.end() == loc_tree.find(lastvn))
throw LowlevelError("Varbank first def missing in loc");
for(;diter!=def_tree.end();++diter) {
vn = *diter;
if (loc_tree.end() == loc_tree.find(vn))
throw LowlevelError("Varbank def missing in loc");
if (cmp(vn,lastvn))
throw LowlevelError("Varbank defloc integrity test failed");
lastvn = vn;
}
}
#endif
bool contiguous_test(Varnode *vn1,Varnode *vn2)
{
if (vn1->isInput()||vn2->isInput()) {
return false;
}
if ((!vn1->isWritten())||(!vn2->isWritten())) return false;
PcodeOp *op1 = vn1->getDef();
PcodeOp *op2 = vn2->getDef();
Varnode *vnwhole;
switch(op1->code()) {
case CPUI_SUBPIECE:
if (op2->code() != CPUI_SUBPIECE) return false;
vnwhole = op1->getIn(0);
if (op2->getIn(0) != vnwhole) return false;
if (op2->getIn(1)->getOffset() != 0)
return false; if (op1->getIn(1)->getOffset() != vn2->getSize())
return false; return true;
default:
return false;
}
}
Varnode *findContiguousWhole(Funcdata &data,Varnode *vn1,Varnode *vn2)
{ if (vn1->isWritten())
if (vn1->getDef()->code() == CPUI_SUBPIECE)
return vn1->getDef()->getIn(0);
return (Varnode *)0;
}