#include "address.hh"
#include "translate.hh"
ostream &operator<<(ostream &s,const SeqNum &sq)
{
sq.pc.printRaw(s);
s << ':' << sq.uniq;
return s;
}
ostream &operator<<(ostream &s,const Address &addr)
{
addr.printRaw(s);
return s;
}
SeqNum::SeqNum(Address::mach_extreme ex) : pc(ex)
{
uniq = (ex == Address::m_minimal) ? 0 : ~((uintm)0);
}
void SeqNum::saveXml(ostream &s) const
{
s << "<seqnum";
pc.getSpace()->saveXmlAttributes(s,pc.getOffset());
a_v_u(s,"uniq",uniq);
s << "/>";
}
SeqNum SeqNum::restoreXml(const Element *el,const AddrSpaceManager *manage)
{
uintm uniq = ~((uintm)0);
Address pc = Address::restoreXml(el,manage); for(int4 i=0;i<el->getNumAttributes();++i)
if (el->getAttributeName(i) == "uniq") {
istringstream s2(el->getAttributeValue(i)); s2.unsetf(ios::dec | ios::hex | ios::oct);
s2 >> uniq;
break;
}
return SeqNum(pc,uniq);
}
Address::Address(mach_extreme ex)
{
if (ex == m_minimal) {
base = (AddrSpace *)0;
offset = 0;
}
else {
base = (AddrSpace *) ~((uintp)0);
offset = ~((uintb)0);
}
}
void Address::toPhysical(void)
{ AddrSpace *phys = base->getContain();
if ((phys != (AddrSpace *)0)&&(base->getType()==IPTR_SPACEBASE))
base = phys;
}
bool Address::containedBy(int4 sz,const Address &op2,int4 sz2) const
{
if (base != op2.base) return false;
if (op2.offset > offset) return false;
uintb off1 = offset + (sz-1);
uintb off2 = op2.offset + (sz2-1);
return (off2 >= off1);
}
int4 Address::justifiedContain(int4 sz,const Address &op2,int4 sz2,bool forceleft) const
{ if (base != op2.base) return -1;
if (op2.offset < offset) return -1;
uintb off1 = offset + (sz-1);
uintb off2 = op2.offset + (sz2-1);
if (off2 > off1) return -1;
if (base->isBigEndian()&&(!forceleft)) {
return (int4)(off1 - off2);
}
return (int4)(op2.offset - offset);
}
int4 Address::overlap(int4 skip,const Address &op,int4 size) const
{
uintb dist;
if (base != op.base) return -1; if (base->getType()==IPTR_CONSTANT) return -1;
dist = base->wrapOffset(offset+skip-op.offset);
if (dist >= size) return -1; return (int4) dist;
}
bool Address::isContiguous(int4 sz,const Address &loaddr,int4 losz) const
{
if (base != loaddr.base) return false;
if (base->isBigEndian()) {
uintb nextoff = base->wrapOffset(offset+sz);
if (nextoff == loaddr.offset) return true;
}
else {
uintb nextoff = base->wrapOffset(loaddr.offset+losz);
if (nextoff == offset) return true;
}
return false;
}
void Address::renormalize(int4 size) {
if (base->getType() == IPTR_JOIN)
base->getManager()->renormalizeJoinAddress(*this,size);
}
Address Address::restoreXml(const Element *el,const AddrSpaceManager *manage)
{
VarnodeData var;
var.restoreXml(el,manage);
return Address(var.space,var.offset);
}
Address Address::restoreXml(const Element *el,const AddrSpaceManager *manage,int4 &size)
{
VarnodeData var;
var.restoreXml(el,manage);
size = var.size;
return Address(var.space,var.offset);
}
Address Range::getLastAddrOpen(const AddrSpaceManager *manage) const
{
AddrSpace *curspc = spc;
uintb curlast = last;
if (curlast == curspc->getHighest()) {
curspc = manage->getNextSpaceInOrder(curspc);
curlast = 0;
}
else
curlast += 1;
if (curspc == (AddrSpace *)0)
return Address(Address::m_maximal);
return Address(curspc,curlast);
}
void Range::printBounds(ostream &s) const
{
s << spc->getName() << ": ";
s << hex << first << '-' << last;
}
void Range::saveXml(ostream &s) const
{
s << "<range";
a_v(s,"space",spc->getName());
a_v_u(s,"first",first);
a_v_u(s,"last",last);
s << "/>\n";
}
void Range::restoreXml(const Element *el,const AddrSpaceManager *manage)
{
spc = (AddrSpace *)0;
bool seenLast = false;
first = 0;
last = 0;
for(int4 i=0;i<el->getNumAttributes();++i) {
if (el->getAttributeName(i) == "space") {
spc = manage->getSpaceByName(el->getAttributeValue(i));
if (spc == (AddrSpace *)0)
throw LowlevelError("Undefined space: "+el->getAttributeValue(i));
}
else if (el->getAttributeName(i) == "first") {
istringstream s(el->getAttributeValue(i));
s.unsetf(ios::dec | ios::hex | ios::oct);
s >> first;
}
else if (el->getAttributeName(i) == "last") {
istringstream s(el->getAttributeValue(i));
s.unsetf(ios::dec | ios::hex | ios::oct);
s >> last;
seenLast = true;
}
else if (el->getAttributeName(i) == "name") {
const Translate *trans = manage->getDefaultCodeSpace()->getTrans();
const VarnodeData &point(trans->getRegister(el->getAttributeValue(i)));
spc = point.space;
first = point.offset;
last = (first-1) + point.size;
return; }
}
if (spc == (AddrSpace *)0)
throw LowlevelError("No address space indicated in range tag");
if (!seenLast) {
last = spc->getHighest();
}
if (first > spc->getHighest() || last > spc->getHighest() || last < first)
throw LowlevelError("Illegal range tag");
}
void RangeList::insertRange(AddrSpace *spc,uintb first,uintb last)
{
set<Range>::iterator iter1,iter2;
iter1 = tree.upper_bound(Range(spc,first,first));
if (iter1 != tree.begin()) {
--iter1;
if (((*iter1).spc!=spc)||((*iter1).last < first))
++iter1;
}
iter2 = tree.upper_bound(Range(spc,last,last));
while(iter1!=iter2) {
if ((*iter1).first < first)
first = (*iter1).first;
if ((*iter1).last > last)
last = (*iter1).last;
tree.erase(iter1++);
}
tree.insert(Range(spc,first,last));
}
void RangeList::removeRange(AddrSpace *spc,uintb first,uintb last)
{ set<Range>::iterator iter1,iter2;
if (tree.empty()) return;
iter1 = tree.upper_bound(Range(spc,first,first));
if (iter1 != tree.begin()) {
--iter1;
if (((*iter1).spc!=spc)||((*iter1).last < first))
++iter1;
}
iter2 = tree.upper_bound(Range(spc,last,last));
while(iter1!=iter2) {
uintb a,b;
a = (*iter1).first;
b = (*iter1).last;
tree.erase(iter1++);
if (a <first)
tree.insert(Range(spc,a,first-1));
if (b > last)
tree.insert(Range(spc,last+1,b));
}
}
void RangeList::merge(const RangeList &op2)
{ set<Range>::const_iterator iter1,iter2;
iter1 = op2.tree.begin();
iter2 = op2.tree.end();
while(iter1 != iter2) {
const Range &range( *iter1 );
++iter1;
insertRange(range.spc, range.first, range.last);
}
}
bool RangeList::inRange(const Address &addr,int4 size) const
{
set<Range>::const_iterator iter;
if (addr.isInvalid()) return true; if (tree.empty()) return false;
iter = tree.upper_bound(Range(addr.getSpace(),addr.getOffset(),addr.getOffset()));
if (iter == tree.begin()) return false;
--iter;
if ((*iter).spc != addr.getSpace()) return false;
if ((*iter).last >= addr.getOffset()+size-1)
return true;
return false;
}
const Range *RangeList::getRange(AddrSpace *spaceid,uintb offset) const
{
if (tree.empty()) return (const Range *)0;
set<Range>::const_iterator iter = tree.upper_bound(Range(spaceid,offset,offset));
if (iter == tree.begin()) return (const Range *)0;
--iter;
if ((*iter).spc != spaceid) return (const Range *)0;
if ((*iter).last >= offset)
return &(*iter);
return (const Range *)0;
}
uintb RangeList::longestFit(const Address &addr,uintb maxsize) const
{
set<Range>::const_iterator iter;
if (addr.isInvalid()) return 0;
if (tree.empty()) return 0;
uintb offset = addr.getOffset();
iter = tree.upper_bound(Range(addr.getSpace(),offset,offset));
if (iter == tree.begin()) return 0;
--iter;
uintb sizeres = 0;
if ((*iter).last < offset) return sizeres;
do {
if ((*iter).spc != addr.getSpace()) break;
if ((*iter).first > offset) break;
sizeres += ((*iter).last + 1 - offset); offset = (*iter).last + 1; if (sizeres >= maxsize) break; ++iter; } while(iter != tree.end());
return sizeres;
}
const Range *RangeList::getFirstRange(void) const
{
if (tree.empty()) return (const Range *)0;
return &(*tree.begin());
}
const Range *RangeList::getLastRange(void) const
{
if (tree.empty()) return (const Range *)0;
set<Range>::const_iterator iter = tree.end();
--iter;
return &(*iter);
}
const Range *RangeList::getLastSignedRange(AddrSpace *spaceid) const
{
uintb midway = spaceid->getHighest() / 2; Range range(spaceid,midway,midway);
set<Range>::const_iterator iter = tree.upper_bound(range);
if (iter!=tree.begin()) {
--iter;
if ((*iter).getSpace() == spaceid)
return &(*iter);
}
range = Range(spaceid,spaceid->getHighest(),spaceid->getHighest());
iter = tree.upper_bound(range);
if (iter != tree.begin()) {
--iter;
if ((*iter).getSpace() == spaceid)
return &(*iter);
}
return (const Range *)0;
}
void RangeList::printBounds(ostream &s) const
{
if (tree.empty())
s << "all" << endl;
else {
set<Range>::const_iterator iter;
for(iter=tree.begin();iter!=tree.end();++iter) {
(*iter).printBounds(s);
s << endl;
}
}
}
void RangeList::saveXml(ostream &s) const
{
set<Range>::const_iterator iter;
s << "<rangelist>\n";
for(iter=tree.begin();iter!=tree.end();++iter) {
(*iter).saveXml(s);
}
s << "</rangelist>\n";
}
void RangeList::restoreXml(const Element *el,const AddrSpaceManager *manage)
{
const List &list(el->getChildren());
List::const_iterator iter;
for(iter=list.begin();iter!=list.end();++iter) {
const Element *subel = *iter;
Range range;
range.restoreXml(subel,manage);
tree.insert(range);
}
}
#ifdef UINTB4
uintb uintbmasks[9] = { 0, 0xff, 0xffff, 0xffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff };
#else
uintb uintbmasks[9] = { 0, 0xff, 0xffff, 0xffffff, 0xffffffff, 0xffffffffffLL,
0xffffffffffffLL, 0xffffffffffffffLL, 0xffffffffffffffffLL };
#endif
bool signbit_negative(uintb val,int4 size)
{ uintb mask = 0x80;
mask <<= 8*(size-1);
return ((val&mask) != 0);
}
uintb uintb_negate(uintb in,int4 size)
{ return ((~in)&calc_mask(size));
}
uintb sign_extend(uintb in,int4 sizein,int4 sizeout)
{
int4 signbit;
uintb mask;
signbit = sizein*8 - 1;
in &= calc_mask(sizein);
if (sizein >= sizeout) return in;
if ((in>>signbit) != 0) {
mask = calc_mask(sizeout);
uintb tmp = mask << signbit; tmp = (tmp<<1) & mask; in |= tmp;
}
return in;
}
void sign_extend(intb &val,int4 bit)
{
intb mask = 0;
mask = (~mask)<<bit;
if (((val>>bit)&1)!=0)
val |= mask;
else
val &= (~mask);
}
void zero_extend(intb &val,int4 bit)
{
intb mask = 0;
mask = (~mask)<<bit;
mask <<= 1;
val &= (~mask);
}
void byte_swap(intb &val,int4 size)
{
intb res = 0;
while(size>0) {
res <<= 8;
res |= (val&0xff);
val >>= 8;
size -= 1;
}
val = res;
}
uintb byte_swap(uintb val,int4 size)
{
uintb res=0;
while(size>0) {
res <<= 8;
res |= (val&0xff);
val >>= 8;
size -= 1;
}
return res;
}
int4 leastsigbit_set(uintb val)
{
if (val==0) return -1;
int4 res = 0;
int4 sz = 4*sizeof(uintb);
uintb mask = ~((uintb)0);
do {
mask >>= sz;
if ((mask&val)==0) {
res += sz;
val >>= sz;
}
sz >>= 1;
} while(sz!=0);
return res;
}
int4 mostsigbit_set(uintb val)
{
if (val==0) return -1;
int4 res = 8*sizeof(uintb)-1;
int4 sz = 4*sizeof(uintb);
uintb mask = ~((uintb)0);
do {
mask <<= sz;
if ((mask&val)==0) {
res -= sz;
val <<= sz;
}
sz >>= 1;
} while(sz != 0);
return res;
}
int4 popcount(uintb val)
{
val = (val & 0x5555555555555555L) + ((val >> 1) & 0x5555555555555555L);
val = (val & 0x3333333333333333L) + ((val >> 2) & 0x3333333333333333L);
val = (val & 0x0f0f0f0f0f0f0f0fL) + ((val >> 4) & 0x0f0f0f0f0f0f0f0fL);
val = (val & 0x00ff00ff00ff00ffL) + ((val >> 8) & 0x00ff00ff00ff00ffL);
val = (val & 0x0000ffff0000ffffL) + ((val >> 16) & 0x0000ffff0000ffffL);
int4 res = (int4)(val & 0xff);
res += (int4)((val >> 32) & 0xff);
return res;
}
int4 count_leading_zeros(uintb val)
{
if (val == 0)
return 8*sizeof(uintb);
uintb mask = ~((uintb)0);
int4 maskSize = 4*sizeof(uintb);
mask &= (mask << maskSize);
int4 bit = 0;
do {
if ((mask & val)==0) {
bit += maskSize;
maskSize >>= 1;
mask |= (mask >> maskSize);
}
else {
maskSize >>= 1;
mask &= (mask << maskSize);
}
} while(maskSize != 0);
return bit;
}
uintb coveringmask(uintb val)
{
uintb res = val;
int4 sz = 1;
while(sz < 8*sizeof(uintb)) {
res = res | (res>>sz);
sz <<= 1;
}
return res;
}
int4 bit_transitions(uintb val,int4 sz)
{
int4 res = 0;
int4 last = val & 1;
int4 cur;
for(int4 i=1;i<8*sz;++i) {
val >>= 1;
cur = val & 1;
if (cur != last) {
res += 1;
last = cur;
}
if (val==0) break;
}
return res;
}
void mult64to128(uint8 *res,uint8 x,uint8 y)
{
uint8 f = x & 0xffffffff;
uint8 e = x >> 32;
uint8 d = y & 0xffffffff;
uint8 c = y >> 32;
uint8 fd = f * d;
uint8 fc = f * c;
uint8 ed = e * d;
uint8 ec = e * c;
uint8 tmp = (fd >> 32) + (fc & 0xffffffff) + (ed & 0xffffffff);
res[1] = (tmp>>32) + (fc>>32) + (ed>>32) + ec;
res[0] = (tmp<<32) + (fd & 0xffffffff);
}
void unsignedSubtract128(uint8 *a,uint8 *b)
{
bool borrow = (a[0] < b[0]);
a[0] -= b[0];
a[1] -= b[1];
if (borrow)
a[1] -= 1;
}
int4 unsignedCompare128(uint8 *a,uint8 *b)
{
if (a[1] != b[1])
return (a[1] < b[1]) ? -1 : 1;
if (a[0] != b[0])
return (a[0] < b[0]) ? -1 : 1;
return 0;
}
int4 power2Divide(int4 n,uint8 divisor,uint8 &q,uint8 &r)
{
if (divisor == 0) return 2;
uint8 power = 1;
if (n < 64) {
power <<= n;
q = power / divisor;
r = power % divisor;
return 0;
}
uint8 y = divisor >> (n-64); if (y == 0) return 1; y >>= 1; power <<= 63;
uint8 max;
if (y == 0) {
max = 0;
max -= 1; if ((((uint8)1) << (n-64)) == divisor)
return 1;
}
else
max = power / y + 1;
uint8 min = power / (y+1);
if (min != 0)
min -= 1;
uint8 fullpower[2];
fullpower[1] = ((uint8)1)<<(n-64);
fullpower[0] = 0;
uint8 mult[2];
mult[0] = 0;
mult[1] = 0;
uint8 tmpq = 0;
while(max > min+1) {
tmpq = max + min;
if (tmpq < min) {
tmpq = (tmpq>>1) + 0x8000000000000000L;
}
else
tmpq >>= 1;
mult64to128(mult,divisor,tmpq);
if (unsignedCompare128(fullpower,mult) < 0)
max = tmpq-1;
else
min = tmpq;
}
if (tmpq != min)
mult64to128(mult,divisor,min);
unsignedSubtract128(fullpower,mult); if (fullpower[1] != 0 || fullpower[0] >= divisor) {
q = min + 1;
r = fullpower[0] - divisor;
}
else {
q = min;
r = fullpower[0];
}
return 0;
}