GP-3424 Near/far pointer data-type propagation

This commit is contained in:
caheckman 2023-05-05 14:58:49 -04:00
parent 007cfacd6c
commit 3c08b44a1e
21 changed files with 403 additions and 292 deletions

View file

@ -666,45 +666,11 @@ uintb uintb_negate(uintb in,int4 size)
uintb sign_extend(uintb in,int4 sizein,int4 sizeout) uintb sign_extend(uintb in,int4 sizein,int4 sizeout)
{ {
int4 signbit; intb sval = in;
uintb mask; sval <<= (sizeof(intb) - sizein) * 8;
uintb res = (uintb)(sval >> (sizeout - sizein) * 8);
signbit = sizein*8 - 1; res >>= (sizeof(uintb) - sizeout)*8;
in &= calc_mask(sizein); return res;
if (sizein >= sizeout) return in;
if ((in>>signbit) != 0) {
mask = calc_mask(sizeout);
uintb tmp = mask << signbit; // Split shift into two pieces
tmp = (tmp<<1) & mask; // In case, everything is shifted out
in |= tmp;
}
return in;
}
/// Sign extend \b val starting at \b bit
/// \param val is a reference to the value to be sign-extended
/// \param bit is the index of the bit to extend from (0=least significant bit)
void sign_extend(intb &val,int4 bit)
{
intb mask = 0;
mask = (~mask)<<bit;
if (((val>>bit)&1)!=0)
val |= mask;
else
val &= (~mask);
}
/// Zero extend \b val starting at \b bit
/// \param val is a reference to the value to be zero extended
/// \param bit is the index of the bit to extend from (0=least significant bit)
void zero_extend(intb &val,int4 bit)
{
intb mask = 0;
mask = (~mask)<<bit;
mask <<= 1;
val &= (~mask);
} }
/// Swap the least significant \b size bytes in \b val /// Swap the least significant \b size bytes in \b val

View file

@ -84,8 +84,8 @@ public:
bool operator!=(const Address &op2) const; ///< Compare two addresses for inequality bool operator!=(const Address &op2) const; ///< Compare two addresses for inequality
bool operator<(const Address &op2) const; ///< Compare two addresses via their natural ordering bool operator<(const Address &op2) const; ///< Compare two addresses via their natural ordering
bool operator<=(const Address &op2) const; ///< Compare two addresses via their natural ordering bool operator<=(const Address &op2) const; ///< Compare two addresses via their natural ordering
Address operator+(int4 off) const; ///< Increment address by a number of bytes Address operator+(int8 off) const; ///< Increment address by a number of bytes
Address operator-(int4 off) const; ///< Decrement address by a number of bytes Address operator-(int8 off) const; ///< Decrement address by a number of bytes
friend ostream &operator<<(ostream &s,const Address &addr); ///< Write out an address to stream friend ostream &operator<<(ostream &s,const Address &addr); ///< Write out an address to stream
bool containedBy(int4 sz,const Address &op2,int4 sz2) const; ///< Determine if \e op2 range contains \b this range bool containedBy(int4 sz,const Address &op2,int4 sz2) const; ///< Determine if \e op2 range contains \b this range
int4 justifiedContain(int4 sz,const Address &op2,int4 sz2,bool forceleft) const; ///< Determine if \e op2 is the least significant part of \e this. int4 justifiedContain(int4 sz,const Address &op2,int4 sz2,bool forceleft) const; ///< Determine if \e op2 is the least significant part of \e this.
@ -420,7 +420,7 @@ inline bool Address::operator<=(const Address &op2) const {
/// space, and the Address will wrap around if necessary. /// space, and the Address will wrap around if necessary.
/// \param off is the number to add to the offset /// \param off is the number to add to the offset
/// \return the new incremented address /// \return the new incremented address
inline Address Address::operator+(int4 off) const { inline Address Address::operator+(int8 off) const {
return Address(base,base->wrapOffset(offset+off)); return Address(base,base->wrapOffset(offset+off));
} }
@ -430,7 +430,7 @@ inline Address Address::operator+(int4 off) const {
/// necessary. /// necessary.
/// \param off is the number to subtract from the offset /// \param off is the number to subtract from the offset
/// \return the new decremented address /// \return the new decremented address
inline Address Address::operator-(int4 off) const { inline Address Address::operator-(int8 off) const {
return Address(base,base->wrapOffset(offset-off)); return Address(base,base->wrapOffset(offset-off));
} }
@ -534,13 +534,38 @@ inline uintb minimalmask(uintb val)
return 0xff; return 0xff;
} }
/// \brief Sign extend above given bit
///
/// Sign extend \b val starting at \b bit
/// \param val is the value to be sign-extended
/// \param bit is the index of the bit to extend from (0=least significant bit)
/// \return the sign extended value
inline intb sign_extend(intb val,int4 bit)
{
int4 sa = 8*sizeof(intb) - (bit+1);
val = (val << sa) >> sa;
return val;
}
/// \brief Clear all bits above given bit
///
/// Zero extend \b val starting at \b bit
/// \param val is the value to be zero extended
/// \param bit is the index of the bit to extend from (0=least significant bit)
/// \return the extended value
inline intb zero_extend(intb val,int4 bit)
{
int4 sa = sizeof(intb)*8 - (bit+1);
return (intb)((uintb)(val << sa) >> sa);
}
extern bool signbit_negative(uintb val,int4 size); ///< Return true if the sign-bit is set extern bool signbit_negative(uintb val,int4 size); ///< Return true if the sign-bit is set
extern uintb calc_mask(int4 size); ///< Calculate a mask for a given byte size extern uintb calc_mask(int4 size); ///< Calculate a mask for a given byte size
extern uintb uintb_negate(uintb in,int4 size); ///< Negate the \e sized value extern uintb uintb_negate(uintb in,int4 size); ///< Negate the \e sized value
extern uintb sign_extend(uintb in,int4 sizein,int4 sizeout); ///< Sign-extend a value between two byte sizes extern uintb sign_extend(uintb in,int4 sizein,int4 sizeout); ///< Sign-extend a value between two byte sizes
extern void sign_extend(intb &val,int4 bit); ///< Sign extend above given bit
extern void zero_extend(intb &val,int4 bit); ///< Clear all bits above given bit
extern void byte_swap(intb &val,int4 size); ///< Swap bytes in the given value extern void byte_swap(intb &val,int4 size); ///< Swap bytes in the given value
extern uintb byte_swap(uintb val,int4 size); ///< Return the given value with bytes swapped extern uintb byte_swap(uintb val,int4 size); ///< Return the given value with bytes swapped

View file

@ -3036,6 +3036,10 @@ ActionMarkExplicit::OpStackElement::OpStackElement(Varnode *v)
} }
else if (opc == CPUI_PTRADD) else if (opc == CPUI_PTRADD)
slotback = 1; // Don't traverse the multiplier slot slotback = 1; // Don't traverse the multiplier slot
else if (opc == CPUI_SEGMENTOP) {
slot = 2;
slotback = 3;
}
else else
slotback = v->getDef()->numInput(); slotback = v->getDef()->numInput();
} }

View file

@ -3335,10 +3335,9 @@ void Database::decode(Decoder &decoder)
for(;;) { for(;;) {
uint4 subId = decoder.openElement(); uint4 subId = decoder.openElement();
if (subId != ELEM_SCOPE) break; if (subId != ELEM_SCOPE) break;
string name; string name; // Name of global scope by default
string displayName; string displayName;
uint8 id = 0; uint8 id = 0; // Id of global scope by default
bool seenId = false;
for(;;) { for(;;) {
uint4 attribId = decoder.getNextAttributeId(); uint4 attribId = decoder.getNextAttributeId();
if (attribId == 0) break; if (attribId == 0) break;
@ -3346,13 +3345,10 @@ void Database::decode(Decoder &decoder)
name = decoder.readString(); name = decoder.readString();
else if (attribId == ATTRIB_ID) { else if (attribId == ATTRIB_ID) {
id = decoder.readUnsignedInteger(); id = decoder.readUnsignedInteger();
seenId = true;
} }
else if (attribId == ATTRIB_LABEL) else if (attribId == ATTRIB_LABEL)
displayName = decoder.readString(); displayName = decoder.readString();
} }
if (name.empty() || !seenId)
throw DecoderError("Missing name and id attributes in scope");
Scope *parentScope = (Scope *)0; Scope *parentScope = (Scope *)0;
uint4 parentId = decoder.peekElement(); uint4 parentId = decoder.peekElement();
if (parentId == ELEM_PARENT) { if (parentId == ELEM_PARENT) {

View file

@ -569,8 +569,7 @@ uintb FloatFormat::opSqrt(uintb a) const
uintb FloatFormat::opInt2Float(uintb a,int4 sizein) const uintb FloatFormat::opInt2Float(uintb a,int4 sizein) const
{ {
intb ival = (intb)a; intb ival = sign_extend(a,8*sizein-1);
sign_extend(ival,8*sizein-1);
double val = (double) ival; // Convert integer to float double val = (double) ival; // Convert integer to float
return getEncoding(val); return getEncoding(val);
} }

View file

@ -994,8 +994,7 @@ bool Funcdata::replaceLessequal(PcodeOp *op)
else else
return false; return false;
val = vn->getOffset(); // Treat this as signed value val = sign_extend(vn->getOffset(),8*vn->getSize()-1);
sign_extend(val,8*vn->getSize()-1);
if (op->code() == CPUI_INT_SLESSEQUAL) { if (op->code() == CPUI_INT_SLESSEQUAL) {
if ((val<0)&&(val+diff>0)) return false; // Check for sign overflow if ((val<0)&&(val+diff>0)) return false; // Check for sign overflow
if ((val>0)&&(val+diff<0)) return false; if ((val>0)&&(val+diff<0)) return false;

View file

@ -496,12 +496,10 @@ uintb OpBehaviorIntSdiv::evaluateBinary(int4 sizeout,int4 sizein,uintb in1,uintb
{ {
if (in2 == 0) if (in2 == 0)
throw EvaluationError("Divide by 0"); throw EvaluationError("Divide by 0");
intb num = in1; // Convert to signed intb num = sign_extend(in1,8*sizein-1); // Convert to signed
intb denom = in2; intb denom = sign_extend(in2,8*sizein-1);
sign_extend(num,8*sizein-1);
sign_extend(denom,8*sizein-1);
intb sres = num/denom; // Do the signed division intb sres = num/denom; // Do the signed division
zero_extend(sres,8*sizeout-1); // Cut to appropriate size sres = zero_extend(sres,8*sizeout-1); // Cut to appropriate size
return (uintb)sres; // Recast as unsigned return (uintb)sres; // Recast as unsigned
} }
@ -520,12 +518,10 @@ uintb OpBehaviorIntSrem::evaluateBinary(int4 sizeout,int4 sizein,uintb in1,uintb
{ {
if (in2 == 0) if (in2 == 0)
throw EvaluationError("Remainder by 0"); throw EvaluationError("Remainder by 0");
intb val = in1; intb val = sign_extend(in1,8*sizein-1); // Convert inputs to signed values
intb mod = in2; intb mod = sign_extend(in2,8*sizein-1);
sign_extend(val,8*sizein-1); // Convert inputs to signed values
sign_extend(mod,8*sizein-1);
intb sres = val % mod; // Do the remainder intb sres = val % mod; // Do the remainder
zero_extend(sres,8*sizeout-1); // Convert back to unsigned sres = zero_extend(sres,8*sizeout-1); // Convert back to unsigned
return (uintb)sres; return (uintb)sres;
} }

View file

@ -763,8 +763,8 @@ void PrintC::opSubpiece(const PcodeOp *op)
const Varnode *vn = op->getIn(0); const Varnode *vn = op->getIn(0);
Datatype *ct = vn->getHighTypeReadFacing(op); Datatype *ct = vn->getHighTypeReadFacing(op);
if (ct->isPieceStructured()) { if (ct->isPieceStructured()) {
int4 offset; int8 offset;
int4 byteOff = TypeOpSubpiece::computeByteOffsetForComposite(op); int8 byteOff = TypeOpSubpiece::computeByteOffsetForComposite(op);
const TypeField *field = ct->findTruncation(byteOff,op->getOut()->getSize(),op,1,offset); // Use artificial slot const TypeField *field = ct->findTruncation(byteOff,op->getOut()->getSize(),op,1,offset); // Use artificial slot
if (field != (const TypeField*)0 && offset == 0) { // A formal structure field if (field != (const TypeField*)0 && offset == 0) { // A formal structure field
pushOp(&object_member,op); pushOp(&object_member,op);
@ -873,7 +873,7 @@ void PrintC::opPtrsub(const PcodeOp *op)
flex = isValueFlexible(in0); flex = isValueFlexible(in0);
if (ct->getMetatype() == TYPE_STRUCT || ct->getMetatype() == TYPE_UNION) { if (ct->getMetatype() == TYPE_STRUCT || ct->getMetatype() == TYPE_UNION) {
uintb suboff = in1const; // How far into container int8 suboff = (int4)in1const; // How far into container
if (ptrel != (TypePointerRel *)0) { if (ptrel != (TypePointerRel *)0) {
suboff += ptrel->getPointerOffset(); suboff += ptrel->getPointerOffset();
suboff &= calc_mask(ptype->getSize()); suboff &= calc_mask(ptype->getSize());
@ -887,11 +887,11 @@ void PrintC::opPtrsub(const PcodeOp *op)
return; return;
} }
} }
suboff = AddrSpace::addressToByte(suboff,ptype->getWordSize()); suboff = AddrSpace::addressToByteInt(suboff,ptype->getWordSize());
string fieldname; string fieldname;
Datatype *fieldtype; Datatype *fieldtype;
int4 fieldid; int4 fieldid;
int4 newoff; int8 newoff;
if (ct->getMetatype() == TYPE_UNION) { if (ct->getMetatype() == TYPE_UNION) {
if (suboff != 0) if (suboff != 0)
throw LowlevelError("PTRSUB accesses union with non-zero offset"); throw LowlevelError("PTRSUB accesses union with non-zero offset");
@ -905,9 +905,9 @@ void PrintC::opPtrsub(const PcodeOp *op)
fieldtype = fld->type; fieldtype = fld->type;
} }
else { // TYPE_STRUCT else { // TYPE_STRUCT
const TypeField *fld = ct->findTruncation((int4)suboff,0,op,0,newoff); const TypeField *fld = ct->findTruncation(suboff,0,op,0,newoff);
if (fld == (const TypeField*)0) { if (fld == (const TypeField*)0) {
if (ct->getSize() <= suboff) { if (ct->getSize() <= suboff || suboff < 0) {
clear(); clear();
throw LowlevelError("PTRSUB out of bounds into struct"); throw LowlevelError("PTRSUB out of bounds into struct");
} }
@ -1871,6 +1871,7 @@ void PrintC::pushPartialSymbol(const Symbol *sym,int4 off,int4 sz,
// globalstruct.(arrayfield[0]) // globalstruct.(arrayfield[0])
vector<PartialSymbolEntry> stack; vector<PartialSymbolEntry> stack;
Datatype *finalcast = (Datatype *)0; Datatype *finalcast = (Datatype *)0;
int8 newoff;
Datatype *ct = sym->getType(); Datatype *ct = sym->getType();
@ -1887,8 +1888,9 @@ void PrintC::pushPartialSymbol(const Symbol *sym,int4 off,int4 sz,
break; // Turns out we don't resolve to the field break; // Turns out we don't resolve to the field
} }
const TypeField *field; const TypeField *field;
field = ct->findTruncation(off,sz,op,inslot,off); field = ct->findTruncation(off,sz,op,inslot,newoff);
if (field != (const TypeField *)0) { if (field != (const TypeField *)0) {
off = newoff;
stack.emplace_back(); stack.emplace_back();
PartialSymbolEntry &entry( stack.back() ); PartialSymbolEntry &entry( stack.back() );
entry.token = &object_member; entry.token = &object_member;
@ -1918,8 +1920,9 @@ void PrintC::pushPartialSymbol(const Symbol *sym,int4 off,int4 sz,
} }
else if (ct->getMetatype() == TYPE_UNION) { else if (ct->getMetatype() == TYPE_UNION) {
const TypeField *field; const TypeField *field;
field = ct->findTruncation(off,sz,op,inslot,off); field = ct->findTruncation(off,sz,op,inslot,newoff);
if (field != (const TypeField*)0) { if (field != (const TypeField*)0) {
off = newoff;
stack.emplace_back(); stack.emplace_back();
PartialSymbolEntry &entry(stack.back()); PartialSymbolEntry &entry(stack.back());
entry.token = &object_member; entry.token = &object_member;

View file

@ -1322,15 +1322,13 @@ bool CircleRange::pushForwardBinary(OpCode opc,const CircleRange &in1,const Circ
int4 sa = (int4)in2.left; int4 sa = (int4)in2.left;
mask = calc_mask(outSize); mask = calc_mask(outSize);
step = 1; // Lose any step step = 1; // Lose any step
intb valLeft = in1.left;
intb valRight = in1.right;
int4 bitPos = 8*inSize - 1; int4 bitPos = 8*inSize - 1;
sign_extend(valLeft,bitPos); intb valLeft = sign_extend(in1.left,bitPos);
sign_extend(valRight,bitPos); intb valRight = sign_extend(in1.right,bitPos);
if (valLeft >= valRight) { if (valLeft >= valRight) {
valRight = (intb)(mask >> 1); // Max positive valRight = (intb)(mask >> 1); // Max positive
valLeft = valRight + 1; // Min negative valLeft = valRight + 1; // Min negative
sign_extend(valLeft,bitPos); valLeft = sign_extend(valLeft,bitPos);
} }
left = (valLeft >> sa) & mask; left = (valLeft >> sa) & mask;
right = (valRight >> sa) & mask; right = (valRight >> sa) & mask;

View file

@ -4736,12 +4736,13 @@ int4 RuleSubZext::applyOp(PcodeOp *op,Funcdata &data)
} }
/// \class RuleSubCancel /// \class RuleSubCancel
/// \brief Simplify composition of SUBPIECE with INT_ZEXT or INT_SEXT /// \brief Simplify composition of SUBPIECE with INT_ZEXT, INT_SEXT, and INT_AND
/// ///
/// The SUBPIECE may partially or wholly canceled out: /// The SUBPIECE may partially or wholly cancel out the extension or INT_AND:
/// - `sub(zext(V),0) => zext(V)` /// - `sub(zext(V),0) => zext(V)`
/// - `sub(zext(V),0) => V` /// - `sub(zext(V),0) => V`
/// - `sub(zext(V),0) => sub(V)` /// - `sub(zext(V),0) => sub(V)`
/// - `sub(V & 0xffff, 0) => sub(V)`
/// ///
/// This also supports the corner case: /// This also supports the corner case:
/// - `sub(zext(V),c) => 0 when c is big enough` /// - `sub(zext(V),c) => 0 when c is big enough`
@ -4753,7 +4754,7 @@ void RuleSubCancel::getOpList(vector<uint4> &oplist) const
int4 RuleSubCancel::applyOp(PcodeOp *op,Funcdata &data) int4 RuleSubCancel::applyOp(PcodeOp *op,Funcdata &data)
{ // A SUBPIECE of an extension may cancel {
Varnode *base,*thruvn; Varnode *base,*thruvn;
int4 offset,outsize,insize,farinsize; int4 offset,outsize,insize,farinsize;
PcodeOp *extop; PcodeOp *extop;
@ -4763,10 +4764,22 @@ int4 RuleSubCancel::applyOp(PcodeOp *op,Funcdata &data)
if (!base->isWritten()) return 0; if (!base->isWritten()) return 0;
extop = base->getDef(); extop = base->getDef();
opc = extop->code(); opc = extop->code();
if ((opc != CPUI_INT_ZEXT)&&(opc != CPUI_INT_SEXT)) if (opc != CPUI_INT_ZEXT && opc != CPUI_INT_SEXT && opc != CPUI_INT_AND)
return 0; return 0;
offset = op->getIn(1)->getOffset(); offset = op->getIn(1)->getOffset();
outsize = op->getOut()->getSize(); outsize = op->getOut()->getSize();
if (opc == CPUI_INT_AND) {
Varnode *cvn = extop->getIn(1);
if (offset == 0 && cvn->isConstant() && cvn->getOffset() == calc_mask(outsize)) {
thruvn = extop->getIn(0);
if (!thruvn->isFree()) {
data.opSetInput(op,thruvn,0);
return 1;
}
}
return 0;
}
insize = base->getSize(); insize = base->getSize();
farinsize = extop->getIn(0)->getSize(); farinsize = extop->getIn(0)->getSize();
@ -4798,9 +4811,7 @@ int4 RuleSubCancel::applyOp(PcodeOp *op,Funcdata &data)
data.opSetOpcode(op,opc); // SUBPIECE <- EXT replaced with one op data.opSetOpcode(op,opc); // SUBPIECE <- EXT replaced with one op
data.opSetInput(op,thruvn,0); data.opSetInput(op,thruvn,0);
if (opc == CPUI_SUBPIECE) if (opc != CPUI_SUBPIECE)
data.opSetInput(op,data.newConstant(op->getIn(1)->getSize(),offset),1);
else
data.opRemoveInput(op,1); // ZEXT, SEXT, or COPY has only 1 input data.opRemoveInput(op,1); // ZEXT, SEXT, or COPY has only 1 input
return 1; return 1;
} }
@ -5705,8 +5716,7 @@ uint4 AddTreeState::findArrayHint(void) const
if (op->code() == CPUI_INT_MULT) { if (op->code() == CPUI_INT_MULT) {
Varnode *vnconst = op->getIn(1); Varnode *vnconst = op->getIn(1);
if (vnconst->isConstant()) { if (vnconst->isConstant()) {
intb sval = vnconst->getOffset(); intb sval = sign_extend(vnconst->getOffset(),vnconst->getSize()*8-1);
sign_extend(sval,vnconst->getSize()*8-1);
vncoeff = (sval < 0) ? (uint4)-sval : (uint4)sval; vncoeff = (sval < 0) ? (uint4)-sval : (uint4)sval;
} }
} }
@ -5728,27 +5738,27 @@ uint4 AddTreeState::findArrayHint(void) const
/// \param arrayHint if non-zero indicates array access, where the value is the element size /// \param arrayHint if non-zero indicates array access, where the value is the element size
/// \param newoff is used to pass back the actual offset of the selected component /// \param newoff is used to pass back the actual offset of the selected component
/// \return \b true if a good component match was found /// \return \b true if a good component match was found
bool AddTreeState::hasMatchingSubType(uintb off,uint4 arrayHint,uintb *newoff) const bool AddTreeState::hasMatchingSubType(int8 off,uint4 arrayHint,int8 *newoff) const
{ {
if (arrayHint == 0) if (arrayHint == 0)
return (baseType->getSubType(off,newoff) != (Datatype *)0); return (baseType->getSubType(off,newoff) != (Datatype *)0);
int4 elSizeBefore; int8 elSizeBefore;
uintb offBefore; int8 offBefore;
Datatype *typeBefore = baseType->nearestArrayedComponentBackward(off, &offBefore, &elSizeBefore); Datatype *typeBefore = baseType->nearestArrayedComponentBackward(off, &offBefore, &elSizeBefore);
if (typeBefore != (Datatype *)0) { if (typeBefore != (Datatype *)0) {
if (arrayHint == 1 || elSizeBefore == arrayHint) { if (arrayHint == 1 || elSizeBefore == arrayHint) {
int4 sizeAddr = AddrSpace::byteToAddressInt(typeBefore->getSize(),ct->getWordSize()); int8 sizeAddr = AddrSpace::byteToAddressInt(typeBefore->getSize(),ct->getWordSize());
if (offBefore < sizeAddr) { if (offBefore >= 0 && offBefore < sizeAddr) {
// If the offset is \e inside a component with a compatible array, return it. // If the offset is \e inside a component with a compatible array, return it.
*newoff = offBefore; *newoff = offBefore;
return true; return true;
} }
} }
} }
int4 elSizeAfter; int8 elSizeAfter;
uintb offAfter; int8 offAfter;
Datatype *typeAfter = baseType->nearestArrayedComponentForward(off, &offAfter, &elSizeAfter); Datatype *typeAfter = baseType->nearestArrayedComponentForward(off, &offAfter, &elSizeAfter);
if (typeBefore == (Datatype *)0 && typeAfter == (Datatype *)0) if (typeBefore == (Datatype *)0 && typeAfter == (Datatype *)0)
return (baseType->getSubType(off,newoff) != (Datatype *)0); return (baseType->getSubType(off,newoff) != (Datatype *)0);
@ -5761,8 +5771,8 @@ bool AddTreeState::hasMatchingSubType(uintb off,uint4 arrayHint,uintb *newoff) c
return true; return true;
} }
uintb distBefore = offBefore; uint8 distBefore = offBefore;
uintb distAfter = -offAfter; uint8 distAfter = -offAfter;
if (arrayHint != 1) { if (arrayHint != 1) {
if (elSizeBefore != arrayHint) if (elSizeBefore != arrayHint)
distBefore += 0x1000; distBefore += 0x1000;
@ -5782,12 +5792,12 @@ bool AddTreeState::hasMatchingSubType(uintb off,uint4 arrayHint,uintb *newoff) c
/// \param op is the CPUI_INT_MULT operation /// \param op is the CPUI_INT_MULT operation
/// \param treeCoeff is constant multiple being applied to the node /// \param treeCoeff is constant multiple being applied to the node
/// \return \b true if there are no multiples of the base data-type size discovered /// \return \b true if there are no multiples of the base data-type size discovered
bool AddTreeState::checkMultTerm(Varnode *vn,PcodeOp *op,uintb treeCoeff) bool AddTreeState::checkMultTerm(Varnode *vn,PcodeOp *op,uint8 treeCoeff)
{ {
Varnode *vnconst = op->getIn(1); Varnode *vnconst = op->getIn(1);
Varnode *vnterm = op->getIn(0); Varnode *vnterm = op->getIn(0);
uintb val; uint8 val;
if (vnterm->isFree()) { if (vnterm->isFree()) {
valid = false; valid = false;
@ -5795,11 +5805,10 @@ bool AddTreeState::checkMultTerm(Varnode *vn,PcodeOp *op,uintb treeCoeff)
} }
if (vnconst->isConstant()) { if (vnconst->isConstant()) {
val = (vnconst->getOffset() * treeCoeff) & ptrmask; val = (vnconst->getOffset() * treeCoeff) & ptrmask;
intb sval = (intb) val; intb sval = sign_extend(val, vn->getSize() * 8 - 1);
sign_extend(sval, vn->getSize() * 8 - 1);
intb rem = (size == 0) ? sval : sval % size; intb rem = (size == 0) ? sval : sval % size;
if (rem != 0) { if (rem != 0) {
if ((val > size) && (size != 0)) { if ((val >= size) && (size != 0)) {
valid = false; // Size is too big: pointer type must be wrong valid = false; // Size is too big: pointer type must be wrong
return false; return false;
} }
@ -5828,17 +5837,16 @@ bool AddTreeState::checkMultTerm(Varnode *vn,PcodeOp *op,uintb treeCoeff)
/// \param vn is the given Varnode term /// \param vn is the given Varnode term
/// \param treeCoeff is a constant multiple applied to the entire sub-tree /// \param treeCoeff is a constant multiple applied to the entire sub-tree
/// \return \b true if the sub-tree rooted at the given Varnode contains no multiples /// \return \b true if the sub-tree rooted at the given Varnode contains no multiples
bool AddTreeState::checkTerm(Varnode *vn,uintb treeCoeff) bool AddTreeState::checkTerm(Varnode *vn,uint8 treeCoeff)
{ {
uintb val; uint8 val;
PcodeOp *def; PcodeOp *def;
if (vn == ptr) return false; if (vn == ptr) return false;
if (vn->isConstant()) { if (vn->isConstant()) {
val = vn->getOffset() * treeCoeff; val = vn->getOffset() * treeCoeff;
intb sval = (intb)val; intb sval = sign_extend(val,vn->getSize()*8-1);
sign_extend(sval,vn->getSize()*8-1);
intb rem = (size == 0) ? sval : (sval % size); intb rem = (size == 0) ? sval : (sval % size);
if (rem!=0) { // constant is not multiple of size if (rem!=0) { // constant is not multiple of size
if (treeCoeff != 1) { if (treeCoeff != 1) {
@ -5885,8 +5893,8 @@ bool AddTreeState::checkTerm(Varnode *vn,uintb treeCoeff)
/// \param op is the root of the sub-expression to traverse /// \param op is the root of the sub-expression to traverse
/// \param treeCoeff is a constant multiple applied to the entire additive tree /// \param treeCoeff is a constant multiple applied to the entire additive tree
/// \return \b true if the given sub-tree contains no multiple nodes /// \return \b true if the given sub-tree contains no multiple nodes
bool AddTreeState::spanAddTree(PcodeOp *op,uintb treeCoeff) bool AddTreeState::spanAddTree(PcodeOp *op,uint8 treeCoeff)
{ {
bool one_is_non,two_is_non; bool one_is_non,two_is_non;
@ -5921,19 +5929,18 @@ void AddTreeState::calcSubtype(void)
// type of constant term added to an array index either at the current level or lower. // type of constant term added to an array index either at the current level or lower.
// If we knew here whether an array of the baseType was possible we could make a slightly // If we knew here whether an array of the baseType was possible we could make a slightly
// better decision. // better decision.
intb snonmult = (intb)nonmultsum; intb snonmult = sign_extend(nonmultsum,ptrsize*8-1);
sign_extend(snonmult,ptrsize*8-1);
snonmult = snonmult % size; snonmult = snonmult % size;
if (snonmult >= 0) if (snonmult >= 0)
// We assume the sum is big enough it represents an array index at this level // We assume the sum is big enough it represents an array index at this level
offset = (uintb)snonmult; offset = (uint8)snonmult;
else { else {
// For a negative sum, if the baseType is a structure and there is array hints, // For a negative sum, if the baseType is a structure and there is array hints,
// we assume the sum is an array index at a lower level // we assume the sum is an array index at a lower level
if (baseType->getMetatype() == TYPE_STRUCT && findArrayHint() != 0) if (baseType->getMetatype() == TYPE_STRUCT && findArrayHint() != 0)
offset = nonmultsum; offset = nonmultsum;
else else
offset = (uintb)(snonmult + size); offset = (uint8)(snonmult + size);
} }
} }
correct = nonmultsum - offset; correct = nonmultsum - offset;
@ -5947,8 +5954,8 @@ void AddTreeState::calcSubtype(void)
isSubtype = false; // There are no offsets INTO the pointer isSubtype = false; // There are no offsets INTO the pointer
} }
else if (baseType->getMetatype() == TYPE_SPACEBASE) { else if (baseType->getMetatype() == TYPE_SPACEBASE) {
uintb nonmultbytes = AddrSpace::addressToByte(nonmultsum,ct->getWordSize()); // Convert to bytes int8 nonmultbytes = AddrSpace::addressToByteInt(nonmultsum,ct->getWordSize()); // Convert to bytes
uintb extra; int8 extra;
uint4 arrayHint = findArrayHint(); uint4 arrayHint = findArrayHint();
// Get offset into mapped variable // Get offset into mapped variable
if (!hasMatchingSubType(nonmultbytes, arrayHint, &extra)) { if (!hasMatchingSubType(nonmultbytes, arrayHint, &extra)) {
@ -5960,18 +5967,19 @@ void AddTreeState::calcSubtype(void)
isSubtype = true; isSubtype = true;
} }
else if (baseType->getMetatype() == TYPE_STRUCT) { else if (baseType->getMetatype() == TYPE_STRUCT) {
uintb nonmultbytes = AddrSpace::addressToByte(nonmultsum,ct->getWordSize()); // Convert to bytes intb snonmult = sign_extend(nonmultsum,ptrsize*8-1);
uintb extra; int8 nonmultbytes = AddrSpace::addressToByteInt(snonmult,ct->getWordSize()); // Convert to bytes
int8 extra;
uint4 arrayHint = findArrayHint(); uint4 arrayHint = findArrayHint();
// Get offset into field in structure // Get offset into field in structure
if (!hasMatchingSubType(nonmultbytes, arrayHint, &extra)) { if (!hasMatchingSubType(nonmultbytes, arrayHint, &extra)) {
if (nonmultbytes >= baseType->getSize()) { // Compare as bytes! not address units if (nonmultbytes < 0 || nonmultbytes >= baseType->getSize()) { // Compare as bytes! not address units
valid = false; // Out of structure's bounds valid = false; // Out of structure's bounds
return; return;
} }
extra = 0; // No field, but pretend there is something there extra = 0; // No field, but pretend there is something there
} }
extra = AddrSpace::byteToAddress(extra, ct->getWordSize()); // Convert back to address units extra = AddrSpace::byteToAddressInt(extra, ct->getWordSize()); // Convert back to address units
offset = (nonmultsum - extra) & ptrmask; offset = (nonmultsum - extra) & ptrmask;
if (pRelType != (TypePointerRel *)0 && offset == pRelType->getPointerOffset()) { if (pRelType != (TypePointerRel *)0 && offset == pRelType->getPointerOffset()) {
// offset falls within basic ptrto // offset falls within basic ptrto
@ -6003,8 +6011,7 @@ Varnode *AddTreeState::buildMultiples(void)
// Be sure to preserve sign in division below // Be sure to preserve sign in division below
// Calc size-relative constant PTR addition // Calc size-relative constant PTR addition
intb smultsum = (intb)multsum; intb smultsum = sign_extend(multsum,ptrsize*8-1);
sign_extend(smultsum,ptrsize*8-1);
uintb constCoeff = (size==0) ? (uintb)0 : (smultsum / size) & ptrmask; uintb constCoeff = (size==0) ? (uintb)0 : (smultsum / size) & ptrmask;
if (constCoeff == 0) if (constCoeff == 0)
resNode = (Varnode *)0; resNode = (Varnode *)0;
@ -6337,13 +6344,13 @@ int4 RuleStructOffset0::applyOp(PcodeOp *op,Funcdata &data)
Datatype *ct = ptrVn->getTypeReadFacing(op); Datatype *ct = ptrVn->getTypeReadFacing(op);
if (ct->getMetatype() != TYPE_PTR) return 0; if (ct->getMetatype() != TYPE_PTR) return 0;
Datatype *baseType = ((TypePointer *)ct)->getPtrTo(); Datatype *baseType = ((TypePointer *)ct)->getPtrTo();
uintb offset = 0; int8 offset = 0;
if (ct->isFormalPointerRel() && ((TypePointerRel *)ct)->evaluateThruParent(0)) { if (ct->isFormalPointerRel() && ((TypePointerRel *)ct)->evaluateThruParent(0)) {
TypePointerRel *ptRel = (TypePointerRel *)ct; TypePointerRel *ptRel = (TypePointerRel *)ct;
baseType = ptRel->getParent(); baseType = ptRel->getParent();
if (baseType->getMetatype() != TYPE_STRUCT) if (baseType->getMetatype() != TYPE_STRUCT)
return 0; return 0;
int4 iOff = ptRel->getPointerOffset(); int8 iOff = ptRel->getPointerOffset();
iOff = AddrSpace::addressToByteInt(iOff, ptRel->getWordSize()); iOff = AddrSpace::addressToByteInt(iOff, ptRel->getWordSize());
if (iOff >= baseType->getSize()) if (iOff >= baseType->getSize())
return 0; return 0;
@ -6899,7 +6906,7 @@ Datatype *RulePieceStructure::determineDatatype(Varnode *vn,int4 &baseOffset)
baseOffset += entry->getOffset(); baseOffset += entry->getOffset();
// Find concrete sub-type that matches the size of the Varnode // Find concrete sub-type that matches the size of the Varnode
Datatype *subType = ct; Datatype *subType = ct;
uintb subOffset = baseOffset; int8 subOffset = baseOffset;
while(subType != (Datatype *)0 && subType->getSize() > vn->getSize()) { while(subType != (Datatype *)0 && subType->getSize() > vn->getSize()) {
subType = subType->getSubType(subOffset, &subOffset); subType = subType->getSubType(subOffset, &subOffset);
} }
@ -6926,11 +6933,11 @@ bool RulePieceStructure::spanningRange(Datatype *ct,int4 offset,int4 size)
{ {
if (offset + size > ct->getSize()) return false; if (offset + size > ct->getSize()) return false;
uintb newOff = offset; int8 newOff = offset;
for(;;) { for(;;) {
ct = ct->getSubType(newOff, &newOff); ct = ct->getSubType(newOff, &newOff);
if (ct == (Datatype *)0) return true; // Don't know what it spans, assume multiple if (ct == (Datatype *)0) return true; // Don't know what it spans, assume multiple
if ((int4)newOff + size > ct->getSize()) return true; // Spans more than 1 if (newOff + size > ct->getSize()) return true; // Spans more than 1
if (!ct->isPieceStructured()) break; if (!ct->isPieceStructured()) break;
} }
return false; return false;
@ -6955,7 +6962,7 @@ bool RulePieceStructure::convertZextToPiece(PcodeOp *zext,Datatype *ct,int4 offs
int4 sz = outvn->getSize() - invn->getSize(); int4 sz = outvn->getSize() - invn->getSize();
if (sz > sizeof(uintb)) return false; if (sz > sizeof(uintb)) return false;
offset += outvn->getSpace()->isBigEndian() ? 0 : invn->getSize(); offset += outvn->getSpace()->isBigEndian() ? 0 : invn->getSize();
uintb newOff = offset; int8 newOff = offset;
while(ct != (Datatype *)0 && ct->getSize() > sz) { while(ct != (Datatype *)0 && ct->getSize() > sz) {
ct = ct->getSubType(newOff, &newOff); ct = ct->getSubType(newOff, &newOff);
} }

View file

@ -51,25 +51,25 @@ class AddTreeState {
int4 ptrsize; ///< Size of the pointer int4 ptrsize; ///< Size of the pointer
int4 size; ///< Size of data-type being pointed to (in address units) or 0 for open ended pointer int4 size; ///< Size of data-type being pointed to (in address units) or 0 for open ended pointer
int4 baseSlot; ///< Slot of the ADD tree base that is holding the pointer int4 baseSlot; ///< Slot of the ADD tree base that is holding the pointer
uintb ptrmask; ///< Mask for modulo calculations in ptr space uint8 ptrmask; ///< Mask for modulo calculations in ptr space
uintb offset; ///< Number of bytes we dig into the base data-type uint8 offset; ///< Number of bytes we dig into the base data-type
uintb correct; ///< Number of bytes being double counted uint8 correct; ///< Number of bytes being double counted
vector<Varnode *> multiple; ///< Varnodes which are multiples of size vector<Varnode *> multiple; ///< Varnodes which are multiples of size
vector<intb> coeff; ///< Associated constant multiple vector<intb> coeff; ///< Associated constant multiple
vector<Varnode *> nonmult; ///< Varnodes which are not multiples vector<Varnode *> nonmult; ///< Varnodes which are not multiples
PcodeOp *distributeOp; ///< A CPUI_INT_MULT op that needs to be distributed PcodeOp *distributeOp; ///< A CPUI_INT_MULT op that needs to be distributed
uintb multsum; ///< Sum of multiple constants uint8 multsum; ///< Sum of multiple constants
uintb nonmultsum; ///< Sum of non-multiple constants uint8 nonmultsum; ///< Sum of non-multiple constants
bool preventDistribution; ///< Do not distribute "multiply by constant" operation bool preventDistribution; ///< Do not distribute "multiply by constant" operation
bool isDistributeUsed; ///< Are terms produced by distributing used bool isDistributeUsed; ///< Are terms produced by distributing used
bool isSubtype; ///< Is there a sub-type (using CPUI_PTRSUB) bool isSubtype; ///< Is there a sub-type (using CPUI_PTRSUB)
bool valid; ///< Set to \b true if the whole expression can be transformed bool valid; ///< Set to \b true if the whole expression can be transformed
bool isDegenerate; ///< Set to \b true if pointer to unitsize or smaller bool isDegenerate; ///< Set to \b true if pointer to unitsize or smaller
uint4 findArrayHint(void) const; ///< Look for evidence of an array in a sub-component uint4 findArrayHint(void) const; ///< Look for evidence of an array in a sub-component
bool hasMatchingSubType(uintb off,uint4 arrayHint,uintb *newoff) const; bool hasMatchingSubType(int8 off,uint4 arrayHint,int8 *newoff) const;
bool checkMultTerm(Varnode *vn,PcodeOp *op, uintb treeCoeff); ///< Accumulate details of INT_MULT term and continue traversal if appropriate bool checkMultTerm(Varnode *vn,PcodeOp *op,uint8 treeCoeff); ///< Accumulate details of INT_MULT term and continue traversal if appropriate
bool checkTerm(Varnode *vn, uintb treeCoeff); ///< Accumulate details of given term and continue tree traversal bool checkTerm(Varnode *vn,uint8 treeCoeff); ///< Accumulate details of given term and continue tree traversal
bool spanAddTree(PcodeOp *op, uintb treeCoeff); ///< Walk the given sub-tree accumulating details bool spanAddTree(PcodeOp *op,uint8 treeCoeff); ///< Walk the given sub-tree accumulating details
void calcSubtype(void); ///< Calculate final sub-type offset void calcSubtype(void); ///< Calculate final sub-type offset
Varnode *buildMultiples(void); ///< Build part of tree that is multiple of base size Varnode *buildMultiples(void); ///< Build part of tree that is multiple of base size
Varnode *buildExtra(void); ///< Build part of tree not accounted for by multiples or \e offset Varnode *buildExtra(void); ///< Build part of tree not accounted for by multiples or \e offset

View file

@ -584,9 +584,9 @@ intb TokenField::getValue(ParserWalker &walker) const
res >>= shift; res >>= shift;
if (signbit) if (signbit)
sign_extend(res,bitend-bitstart); res = sign_extend(res,bitend-bitstart);
else else
zero_extend(res,bitend-bitstart); res = zero_extend(res,bitend-bitstart);
return res; return res;
} }
@ -668,9 +668,9 @@ intb ContextField::getValue(ParserWalker &walker) const
intb res = getContextBytes(walker,startbyte,endbyte); intb res = getContextBytes(walker,startbyte,endbyte);
res >>= shift; res >>= shift;
if (signbit) if (signbit)
sign_extend(res,endbit-startbit); res = sign_extend(res,endbit-startbit);
else else
zero_extend(res,endbit-startbit); res = zero_extend(res,endbit-startbit);
return res; return res;
} }

View file

@ -102,7 +102,7 @@ public:
virtual TokenPattern genMinPattern(const vector<TokenPattern> &ops) const { return TokenPattern(tok); } virtual TokenPattern genMinPattern(const vector<TokenPattern> &ops) const { return TokenPattern(tok); }
virtual TokenPattern genPattern(intb val) const; virtual TokenPattern genPattern(intb val) const;
virtual intb minValue(void) const { return 0; } virtual intb minValue(void) const { return 0; }
virtual intb maxValue(void) const { intb res=0; res=~res; zero_extend(res,bitend-bitstart); return res; } virtual intb maxValue(void) const { intb res=0; return zero_extend(~res,bitend-bitstart); }
virtual void saveXml(ostream &s) const; virtual void saveXml(ostream &s) const;
virtual void restoreXml(const Element *el,Translate *trans); virtual void restoreXml(const Element *el,Translate *trans);
}; };
@ -122,7 +122,7 @@ public:
virtual TokenPattern genMinPattern(const vector<TokenPattern> &ops) const { return TokenPattern(); } virtual TokenPattern genMinPattern(const vector<TokenPattern> &ops) const { return TokenPattern(); }
virtual TokenPattern genPattern(intb val) const; virtual TokenPattern genPattern(intb val) const;
virtual intb minValue(void) const { return 0; } virtual intb minValue(void) const { return 0; }
virtual intb maxValue(void) const { intb res=0; res=~res; zero_extend(res,(endbit-startbit)); return res; } virtual intb maxValue(void) const { intb res=0; return zero_extend(~res,(endbit-startbit)); }
virtual void saveXml(ostream &s) const; virtual void saveXml(ostream &s) const;
virtual void restoreXml(const Element *el,Translate *trans); virtual void restoreXml(const Element *el,Translate *trans);
}; };

View file

@ -168,8 +168,8 @@ public:
static uintb addressToByte(uintb val,uint4 ws); ///< Scale from addressable units to byte units static uintb addressToByte(uintb val,uint4 ws); ///< Scale from addressable units to byte units
static uintb byteToAddress(uintb val,uint4 ws); ///< Scale from byte units to addressable units static uintb byteToAddress(uintb val,uint4 ws); ///< Scale from byte units to addressable units
static int4 addressToByteInt(int4 val,uint4 ws); ///< Scale int4 from addressable units to byte units static int8 addressToByteInt(int8 val,uint4 ws); ///< Scale int4 from addressable units to byte units
static int4 byteToAddressInt(int4 val,uint4 ws); ///< Scale int4 from byte units to addressable units static int8 byteToAddressInt(int8 val,uint4 ws); ///< Scale int4 from byte units to addressable units
static bool compareByIndex(const AddrSpace *a,const AddrSpace *b); ///< Compare two spaces by their index static bool compareByIndex(const AddrSpace *a,const AddrSpace *b); ///< Compare two spaces by their index
}; };
@ -530,21 +530,21 @@ inline uintb AddrSpace::byteToAddress(uintb val,uint4 ws) {
return val/ws; return val/ws;
} }
/// Given an int4 offset into an address space based on the addressable unit size (wordsize), /// Given an int8 offset into an address space based on the addressable unit size (wordsize),
/// convert it into a byte relative offset /// convert it into a byte relative offset
/// \param val is the offset to convert /// \param val is the offset to convert
/// \param ws is the number of bytes in the addressable word /// \param ws is the number of bytes in the addressable word
/// \return the scaled offset /// \return the scaled offset
inline int4 AddrSpace::addressToByteInt(int4 val,uint4 ws) { inline int8 AddrSpace::addressToByteInt(int8 val,uint4 ws) {
return val*ws; return val*ws;
} }
/// Given an int4 offset in an address space based on bytes, convert it /// Given an int8 offset in an address space based on bytes, convert it
/// into an offset relative to the addressable unit of the space (wordsize) /// into an offset relative to the addressable unit of the space (wordsize)
/// \param val is the offset to convert /// \param val is the offset to convert
/// \param ws is the number of bytes in the addressable word /// \param ws is the number of bytes in the addressable word
/// \return the scaled offset /// \return the scaled offset
inline int4 AddrSpace::byteToAddressInt(int4 val,uint4 ws) { inline int8 AddrSpace::byteToAddressInt(int8 val,uint4 ws) {
return val/ws; return val/ws;
} }

View file

@ -1839,7 +1839,7 @@ Datatype *SplitDatatype::getComponent(Datatype *ct,int4 offset,bool &isHole)
{ {
isHole = false; isHole = false;
Datatype *curType = ct; Datatype *curType = ct;
uintb curOff = offset; int8 curOff = offset;
do { do {
curType = curType->getSubType(curOff,&curOff); curType = curType->getSubType(curOff,&curOff);
if (curType == (Datatype *)0) { if (curType == (Datatype *)0) {
@ -2234,19 +2234,17 @@ void SplitDatatype::buildPointers(Varnode *rootVn,TypePointer *ptrType,int4 base
Datatype *baseType = ptrType->getPtrTo(); Datatype *baseType = ptrType->getPtrTo();
for(int4 i=0;i<dataTypePieces.size();++i) { for(int4 i=0;i<dataTypePieces.size();++i) {
Datatype *matchType = isInput ? dataTypePieces[i].inType : dataTypePieces[i].outType; Datatype *matchType = isInput ? dataTypePieces[i].inType : dataTypePieces[i].outType;
int4 byteOffset = baseOffset + dataTypePieces[i].offset; int8 curOff = baseOffset + dataTypePieces[i].offset;
Datatype *tmpType = baseType; Datatype *tmpType = baseType;
uintb curOff = byteOffset;
Varnode *inPtr = rootVn; Varnode *inPtr = rootVn;
do { do {
uintb newOff; int8 newOff;
PcodeOp *newOp; PcodeOp *newOp;
Datatype *newType; Datatype *newType;
if (curOff >= tmpType->getSize()) { // An offset bigger than current data-type indicates an array if (curOff < 0 || curOff >= tmpType->getSize()) { // An offset not within the data-type indicates an array
newType = tmpType; // The new data-type will be the same as current data-type newType = tmpType; // The new data-type will be the same as current data-type
intb sNewOff = (intb)curOff % tmpType->getSize(); // But new offset will be old offset modulo data-type size newOff = curOff % tmpType->getSize(); // But new offset will be old offset modulo data-type size
newOff = (sNewOff < 0) ? (sNewOff + tmpType->getSize()) : sNewOff; newOff = (newOff < 0) ? (newOff + tmpType->getSize()) : newOff;
} }
else { else {
newType = tmpType->getSubType(curOff, &newOff); newType = tmpType->getSubType(curOff, &newOff);
@ -2257,7 +2255,7 @@ void SplitDatatype::buildPointers(Varnode *rootVn,TypePointer *ptrType,int4 base
} }
} }
if (tmpType == newType || tmpType->getMetatype() == TYPE_ARRAY) { if (tmpType == newType || tmpType->getMetatype() == TYPE_ARRAY) {
int4 finalOffset = (int4)curOff - (int4)newOff; int8 finalOffset = curOff - newOff;
int4 sz = newType->getSize(); // Element size in bytes int4 sz = newType->getSize(); // Element size in bytes
finalOffset = finalOffset / sz; // Number of elements finalOffset = finalOffset / sz; // Number of elements
sz = AddrSpace::byteToAddressInt(sz, ptrType->getWordSize()); sz = AddrSpace::byteToAddressInt(sz, ptrType->getWordSize());
@ -2271,7 +2269,7 @@ void SplitDatatype::buildPointers(Varnode *rootVn,TypePointer *ptrType,int4 base
indexVn->updateType(indexType, false, false); indexVn->updateType(indexType, false, false);
} }
else { else {
int4 finalOffset = AddrSpace::byteToAddressInt((int4)curOff - (int4)newOff,ptrType->getWordSize()); int8 finalOffset = AddrSpace::byteToAddressInt(curOff - newOff,ptrType->getWordSize());
newOp = data.newOp(2,followOp->getAddr()); newOp = data.newOp(2,followOp->getAddr());
data.opSetOpcode(newOp, CPUI_PTRSUB); data.opSetOpcode(newOp, CPUI_PTRSUB);
data.opSetInput(newOp, inPtr, 0); data.opSetInput(newOp, inPtr, 0);

View file

@ -60,7 +60,7 @@ ElementId ELEM_INTEGER_SIZE = ElementId("integer_size",51);
ElementId ELEM_LONG_SIZE = ElementId("long_size", 54); ElementId ELEM_LONG_SIZE = ElementId("long_size", 54);
//ElementId ELEM_MACHINE_ALIGNMENT = ElementId("machine_alignment", 55); //ElementId ELEM_MACHINE_ALIGNMENT = ElementId("machine_alignment", 55);
//ElementId ELEM_POINTER_SHIFT = ElementId("pointer_shift", 56); //ElementId ELEM_POINTER_SHIFT = ElementId("pointer_shift", 56);
//ElementId ELEM_POINTER_SIZE = ElementId("pointer_size", 57); ElementId ELEM_POINTER_SIZE = ElementId("pointer_size", 57);
//ElementId ELEM_SHORT_SIZE = ElementId("short_size", 58); //ElementId ELEM_SHORT_SIZE = ElementId("short_size", 58);
ElementId ELEM_SIZE_ALIGNMENT_MAP = ElementId("size_alignment_map", 59); ElementId ELEM_SIZE_ALIGNMENT_MAP = ElementId("size_alignment_map", 59);
ElementId ELEM_TYPE = ElementId("type",60); ElementId ELEM_TYPE = ElementId("type",60);
@ -156,7 +156,7 @@ void Datatype::printRaw(ostream &s) const
/// \param slot is the index of the Varnode being accessed, -1 for the output, >=0 for an input /// \param slot is the index of the Varnode being accessed, -1 for the output, >=0 for an input
/// \param newoff points to the renormalized offset to pass back /// \param newoff points to the renormalized offset to pass back
/// \return the containing field or NULL if the range is not contained /// \return the containing field or NULL if the range is not contained
const TypeField *Datatype::findTruncation(int4 off,int4 sz,const PcodeOp *op,int4 slot,int4 &newoff) const const TypeField *Datatype::findTruncation(int8 off,int4 sz,const PcodeOp *op,int4 slot,int8 &newoff) const
{ {
return (const TypeField *)0; return (const TypeField *)0;
@ -170,7 +170,7 @@ const TypeField *Datatype::findTruncation(int4 off,int4 sz,const PcodeOp *op,int
/// \param off is the offset into \b this data-type /// \param off is the offset into \b this data-type
/// \param newoff is a pointer to the passed-back offset /// \param newoff is a pointer to the passed-back offset
/// \return a pointer to the component data-type or NULL /// \return a pointer to the component data-type or NULL
Datatype *Datatype::getSubType(uintb off,uintb *newoff) const Datatype *Datatype::getSubType(int8 off,int8 *newoff) const
{ // There is no subtype { // There is no subtype
*newoff = off; *newoff = off;
@ -184,7 +184,7 @@ Datatype *Datatype::getSubType(uintb off,uintb *newoff) const
/// \param newoff is used to pass back the offset difference /// \param newoff is used to pass back the offset difference
/// \param elSize is used to pass back the array element size /// \param elSize is used to pass back the array element size
/// \return the component data-type or null /// \return the component data-type or null
Datatype *Datatype::nearestArrayedComponentForward(uintb off,uintb *newoff,int4 *elSize) const Datatype *Datatype::nearestArrayedComponentForward(int8 off,int8 *newoff,int8 *elSize) const
{ {
return (TypeArray *)0; return (TypeArray *)0;
@ -197,7 +197,7 @@ Datatype *Datatype::nearestArrayedComponentForward(uintb off,uintb *newoff,int4
/// \param newoff is used to pass back the offset difference /// \param newoff is used to pass back the offset difference
/// \param elSize is used to pass back the array element size /// \param elSize is used to pass back the array element size
/// \return the component data-type or null /// \return the component data-type or null
Datatype *Datatype::nearestArrayedComponentBackward(uintb off,uintb *newoff,int4 *elSize) const Datatype *Datatype::nearestArrayedComponentBackward(int8 off,int8 *newoff,int8 *elSize) const
{ {
return (TypeArray *)0; return (TypeArray *)0;
@ -498,7 +498,7 @@ int4 Datatype::findCompatibleResolve(Datatype *ct) const
/// \param slot is either the input slot of the reading PcodeOp or the artificial SUBPIECE slot: 1 /// \param slot is either the input slot of the reading PcodeOp or the artificial SUBPIECE slot: 1
/// \param newoff is used to pass back how much offset is left to resolve /// \param newoff is used to pass back how much offset is left to resolve
/// \return the field of the union best associated with the truncation or null /// \return the field of the union best associated with the truncation or null
const TypeField *Datatype::resolveTruncation(int4 offset,PcodeOp *op,int4 slot,int4 &newoff) const TypeField *Datatype::resolveTruncation(int8 offset,PcodeOp *op,int4 slot,int8 &newoff)
{ {
return (const TypeField *)0; return (const TypeField *)0;
@ -781,6 +781,19 @@ void TypePointer::printRaw(ostream &s) const
} }
} }
Datatype *TypePointer::getSubType(int8 off,int8 *newoff) const
{
if (truncate == (TypePointer *)0)
return truncate;
int8 min = ((flags & truncate_bigendian) != 0) ? size - truncate->getSize() : 0;
if (off >= min && off < min + truncate->getSize()) {
*newoff = off - min;
return truncate;
}
return (Datatype *)0;
}
int4 TypePointer::compare(const Datatype &op,int4 level) const int4 TypePointer::compare(const Datatype &op,int4 level) const
{ {
@ -857,6 +870,7 @@ void TypePointer::decode(Decoder &decoder,TypeFactory &typegrp)
calcSubmeta(); calcSubmeta();
if (name.size() == 0) // Inherit only if no name if (name.size() == 0) // Inherit only if no name
flags |= ptrto->getInheritable(); flags |= ptrto->getInheritable();
calcTruncate(typegrp);
// decoder.closeElement(elemId); // decoder.closeElement(elemId);
} }
@ -878,6 +892,20 @@ void TypePointer::calcSubmeta(void)
flags |= needs_resolution; // Inherit needs_resolution, but only if not a pointer flags |= needs_resolution; // Inherit needs_resolution, but only if not a pointer
} }
/// If \b this pointer has a size of \b sizeOfAltPointer, a smaller (\b sizeOfPointer) pointer
/// data-type is created and assigned to \b this as a subcomponent.
/// \param typegrp is the factory \b this belongs to
void TypePointer::calcTruncate(TypeFactory &typegrp)
{
if (truncate != (TypePointer *)0 || size != typegrp.getSizeOfAltPointer())
return;
truncate = typegrp.resizePointer(this, typegrp.getSizeOfPointer());
if (typegrp.getArch()->getDefaultDataSpace()->isBigEndian())
flags |= Datatype::truncate_bigendian;
}
/// \brief Find a sub-type pointer given an offset into \b this /// \brief Find a sub-type pointer given an offset into \b this
/// ///
/// Add a constant offset to \b this pointer. /// Add a constant offset to \b this pointer.
@ -893,16 +921,15 @@ void TypePointer::calcSubmeta(void)
/// \param allowArrayWrap is \b true if the pointer should be treated as a pointer to an array /// \param allowArrayWrap is \b true if the pointer should be treated as a pointer to an array
/// \param typegrp is the factory producing the (possibly new) data-type /// \param typegrp is the factory producing the (possibly new) data-type
/// \return a pointer datatype for the component or NULL /// \return a pointer datatype for the component or NULL
TypePointer *TypePointer::downChain(uintb &off,TypePointer *&par,uintb &parOff,bool allowArrayWrap,TypeFactory &typegrp) TypePointer *TypePointer::downChain(int8 &off,TypePointer *&par,int8 &parOff,bool allowArrayWrap,TypeFactory &typegrp)
{ {
int4 ptrtoSize = ptrto->getSize(); int4 ptrtoSize = ptrto->getSize();
if (off >= ptrtoSize) { // Check if we are wrapping if (off < 0 || off >= ptrtoSize) { // Check if we are wrapping
if (ptrtoSize != 0 && !ptrto->isVariableLength()) { // Check if pointed-to is wrappable if (ptrtoSize != 0 && !ptrto->isVariableLength()) { // Check if pointed-to is wrappable
if (!allowArrayWrap) if (!allowArrayWrap)
return (TypePointer *)0; return (TypePointer *)0;
intb signOff = (intb)off; intb signOff = sign_extend(off,size*8-1);
sign_extend(signOff,size*8-1);
signOff = signOff % ptrtoSize; signOff = signOff % ptrtoSize;
if (signOff < 0) if (signOff < 0)
signOff = signOff + ptrtoSize; signOff = signOff + ptrtoSize;
@ -931,15 +958,14 @@ bool TypePointer::isPtrsubMatching(uintb off) const
{ {
if (ptrto->getMetatype()==TYPE_SPACEBASE) { if (ptrto->getMetatype()==TYPE_SPACEBASE) {
uintb newoff = AddrSpace::addressToByte(off,wordsize); int8 newoff = AddrSpace::addressToByteInt(off,wordsize);
ptrto->getSubType(newoff,&newoff); ptrto->getSubType(newoff,&newoff);
if (newoff != 0) if (newoff != 0)
return false; return false;
} }
else if (ptrto->getMetatype() == TYPE_ARRAY || ptrto->getMetatype() == TYPE_STRUCT) { else if (ptrto->getMetatype() == TYPE_ARRAY || ptrto->getMetatype() == TYPE_STRUCT) {
int4 sz = off;
int4 typesize = ptrto->getSize(); int4 typesize = ptrto->getSize();
if ((typesize <= AddrSpace::addressToByteInt(sz,wordsize))&&(typesize!=0)) if ((typesize <= AddrSpace::addressToByteInt(off,wordsize))&&(typesize!=0))
return false; return false;
} }
else if (ptrto->getMetatype() == TYPE_UNION) { else if (ptrto->getMetatype() == TYPE_UNION) {
@ -1009,7 +1035,7 @@ int4 TypeArray::compareDependency(const Datatype &op) const
return (op.getSize()-size); return (op.getSize()-size);
} }
Datatype *TypeArray::getSubType(uintb off,uintb *newoff) const Datatype *TypeArray::getSubType(int8 off,int8 *newoff) const
{ // Go down exactly one level, to type of element { // Go down exactly one level, to type of element
*newoff = off % arrayof->getSize(); *newoff = off % arrayof->getSize();
@ -1396,7 +1422,7 @@ int4 TypeStruct::getLowerBoundField(int4 off) const
return -1; return -1;
} }
const TypeField *TypeStruct::findTruncation(int4 off,int4 sz,const PcodeOp *op,int4 slot,int4 &newoff) const const TypeField *TypeStruct::findTruncation(int8 off,int4 sz,const PcodeOp *op,int4 slot,int8 &newoff) const
{ {
int4 i; int4 i;
@ -1412,7 +1438,7 @@ const TypeField *TypeStruct::findTruncation(int4 off,int4 sz,const PcodeOp *op,i
return &curfield; return &curfield;
} }
Datatype *TypeStruct::getSubType(uintb off,uintb *newoff) const Datatype *TypeStruct::getSubType(int8 off,int8 *newoff) const
{ // Go down one level to field that contains offset { // Go down one level to field that contains offset
int4 i; int4 i;
@ -1441,25 +1467,25 @@ int4 TypeStruct::getHoleSize(int4 off) const
return getSize() - off; // Distance to end of structure return getSize() - off; // Distance to end of structure
} }
Datatype *TypeStruct::nearestArrayedComponentBackward(uintb off,uintb *newoff,int4 *elSize) const Datatype *TypeStruct::nearestArrayedComponentBackward(int8 off,int8 *newoff,int8 *elSize) const
{ {
int4 i = getLowerBoundField(off); int4 i = getLowerBoundField(off);
while(i >= 0) { while(i >= 0) {
const TypeField &subfield( field[i] ); const TypeField &subfield( field[i] );
int4 diff = (int4)off - subfield.offset; int8 diff = off - subfield.offset;
if (diff > 128) break; if (diff > 128) break;
Datatype *subtype = subfield.type; Datatype *subtype = subfield.type;
if (subtype->getMetatype() == TYPE_ARRAY) { if (subtype->getMetatype() == TYPE_ARRAY) {
*newoff = (intb)diff; *newoff = diff;
*elSize = ((TypeArray *)subtype)->getBase()->getSize(); *elSize = ((TypeArray *)subtype)->getBase()->getSize();
return subtype; return subtype;
} }
else { else {
uintb suboff; int8 suboff;
Datatype *res = subtype->nearestArrayedComponentBackward(subtype->getSize(), &suboff, elSize); Datatype *res = subtype->nearestArrayedComponentBackward(subtype->getSize(), &suboff, elSize);
if (res != (Datatype *)0) { if (res != (Datatype *)0) {
*newoff = (intb)diff; *newoff = diff;
return subtype; return subtype;
} }
} }
@ -1468,26 +1494,26 @@ Datatype *TypeStruct::nearestArrayedComponentBackward(uintb off,uintb *newoff,in
return (Datatype *)0; return (Datatype *)0;
} }
Datatype *TypeStruct::nearestArrayedComponentForward(uintb off,uintb *newoff,int4 *elSize) const Datatype *TypeStruct::nearestArrayedComponentForward(int8 off,int8 *newoff,int8 *elSize) const
{ {
int4 i = getLowerBoundField(off); int4 i = getLowerBoundField(off);
i += 1; i += 1;
while(i<field.size()) { while(i<field.size()) {
const TypeField &subfield( field[i] ); const TypeField &subfield( field[i] );
int4 diff = subfield.offset - off; int8 diff = subfield.offset - off;
if (diff > 128) break; if (diff > 128) break;
Datatype *subtype = subfield.type; Datatype *subtype = subfield.type;
if (subtype->getMetatype() == TYPE_ARRAY) { if (subtype->getMetatype() == TYPE_ARRAY) {
*newoff = (intb)-diff; *newoff = -diff;
*elSize = ((TypeArray *)subtype)->getBase()->getSize(); *elSize = ((TypeArray *)subtype)->getBase()->getSize();
return subtype; return subtype;
} }
else { else {
uintb suboff; int8 suboff;
Datatype *res = subtype->nearestArrayedComponentForward(0, &suboff, elSize); Datatype *res = subtype->nearestArrayedComponentForward(0, &suboff, elSize);
if (res != (Datatype *)0) { if (res != (Datatype *)0) {
*newoff = (intb)-diff; *newoff = -diff;
return subtype; return subtype;
} }
} }
@ -1861,7 +1887,7 @@ Datatype* TypeUnion::findResolve(const PcodeOp *op,int4 slot)
return this; return this;
} }
const TypeField *TypeUnion::resolveTruncation(int4 offset,PcodeOp *op,int4 slot,int4 &newoff) const TypeField *TypeUnion::resolveTruncation(int8 offset,PcodeOp *op,int4 slot,int8 &newoff)
{ {
Funcdata *fd = op->getParent()->getFuncdata(); Funcdata *fd = op->getParent()->getFuncdata();
@ -1899,7 +1925,7 @@ const TypeField *TypeUnion::resolveTruncation(int4 offset,PcodeOp *op,int4 slot,
/// \param slot is the input slot being read /// \param slot is the input slot being read
/// \param newoff is used to pass back any remaining offset into the field which still must be resolved /// \param newoff is used to pass back any remaining offset into the field which still must be resolved
/// \return the field to use with truncation or null if there is no appropriate field /// \return the field to use with truncation or null if there is no appropriate field
const TypeField *TypeUnion::findTruncation(int4 offset,int4 sz,const PcodeOp *op,int4 slot,int4 &newoff) const const TypeField *TypeUnion::findTruncation(int8 offset,int4 sz,const PcodeOp *op,int4 slot,int8 &newoff) const
{ {
// No new scoring is done, but if a cached result is available, return it. // No new scoring is done, but if a cached result is available, return it.
@ -1965,10 +1991,10 @@ void TypePartialStruct::printRaw(ostream &s) const
s << "[off=" << dec << offset << ",sz=" << size << ']'; s << "[off=" << dec << offset << ",sz=" << size << ']';
} }
Datatype *TypePartialStruct::getSubType(uintb off,uintb *newoff) const Datatype *TypePartialStruct::getSubType(int8 off,int8 *newoff) const
{ {
int4 sizeLeft = (size - (int4)off); int8 sizeLeft = size - off;
off += offset; off += offset;
Datatype *ct = container; Datatype *ct = container;
do { do {
@ -1977,7 +2003,7 @@ Datatype *TypePartialStruct::getSubType(uintb off,uintb *newoff) const
break; break;
off = *newoff; off = *newoff;
// Component can extend beyond range of this partial, in which case we go down another level // Component can extend beyond range of this partial, in which case we go down another level
} while(ct->getSize() - (int4)off > sizeLeft); } while(ct->getSize() - off > sizeLeft);
return ct; return ct;
} }
@ -2042,7 +2068,7 @@ void TypePartialUnion::printRaw(ostream &s) const
s << "[off=" << dec << offset << ",sz=" << size << ']'; s << "[off=" << dec << offset << ",sz=" << size << ']';
} }
const TypeField *TypePartialUnion::findTruncation(int4 off,int4 sz,const PcodeOp *op,int4 slot,int4 &newoff) const const TypeField *TypePartialUnion::findTruncation(int8 off,int4 sz,const PcodeOp *op,int4 slot,int8 &newoff) const
{ {
return container->findTruncation(off + offset, sz, op, slot, newoff); return container->findTruncation(off + offset, sz, op, slot, newoff);
@ -2104,16 +2130,14 @@ Datatype *TypePartialUnion::resolveInFlow(PcodeOp *op,int4 slot)
{ {
Datatype *curType = container; Datatype *curType = container;
int4 curOff = offset; int8 curOff = offset;
while(curType != (Datatype *)0 && curType->getSize() > size) { while(curType != (Datatype *)0 && curType->getSize() > size) {
if (curType->getMetatype() == TYPE_UNION) { if (curType->getMetatype() == TYPE_UNION) {
const TypeField *field = curType->resolveTruncation(curOff, op, slot, curOff); const TypeField *field = curType->resolveTruncation(curOff, op, slot, curOff);
curType = (field == (const TypeField *)0) ? (Datatype *)0 : field->type; curType = (field == (const TypeField *)0) ? (Datatype *)0 : field->type;
} }
else { else {
uintb newOff; curType = curType->getSubType(curOff, &curOff);
curType = curType->getSubType(curOff, &newOff);
curOff = newOff;
} }
} }
if (curType != (Datatype *)0 && curType->getSize() == size) if (curType != (Datatype *)0 && curType->getSize() == size)
@ -2125,16 +2149,14 @@ Datatype* TypePartialUnion::findResolve(const PcodeOp *op,int4 slot)
{ {
Datatype *curType = container; Datatype *curType = container;
int4 curOff = offset; int8 curOff = offset;
while(curType != (Datatype *)0 && curType->getSize() > size) { while(curType != (Datatype *)0 && curType->getSize() > size) {
if (curType->getMetatype() == TYPE_UNION) { if (curType->getMetatype() == TYPE_UNION) {
Datatype *newType = curType->findResolve(op, slot); Datatype *newType = curType->findResolve(op, slot);
curType = (newType == curType) ? (Datatype *)0 : newType; curType = (newType == curType) ? (Datatype *)0 : newType;
} }
else { else {
uintb newOff; curType = curType->getSubType(curOff, &curOff);
curType = curType->getSubType(curOff, &newOff);
curOff = newOff;
} }
} }
if (curType != (Datatype *)0 && curType->getSize() == size) if (curType != (Datatype *)0 && curType->getSize() == size)
@ -2148,7 +2170,7 @@ int4 TypePartialUnion::findCompatibleResolve(Datatype *ct) const
return container->findCompatibleResolve(ct); return container->findCompatibleResolve(ct);
} }
const TypeField *TypePartialUnion::resolveTruncation(int4 off,PcodeOp *op,int4 slot,int4 &newoff) const TypeField *TypePartialUnion::resolveTruncation(int8 off,PcodeOp *op,int4 slot,int8 &newoff)
{ {
return container->resolveTruncation(off + offset, op, slot, newoff); return container->resolveTruncation(off + offset, op, slot, newoff);
@ -2262,15 +2284,15 @@ void TypePointerRel::encode(Encoder &encoder) const
encoder.closeElement(ELEM_TYPE); encoder.closeElement(ELEM_TYPE);
} }
TypePointer *TypePointerRel::downChain(uintb &off,TypePointer *&par,uintb &parOff,bool allowArrayWrap, TypePointer *TypePointerRel::downChain(int8 &off,TypePointer *&par,int8 &parOff,bool allowArrayWrap,
TypeFactory &typegrp) TypeFactory &typegrp)
{ {
type_metatype ptrtoMeta = ptrto->getMetatype(); type_metatype ptrtoMeta = ptrto->getMetatype();
if (off < ptrto->getSize() && (ptrtoMeta == TYPE_STRUCT || ptrtoMeta == TYPE_ARRAY)) { if (off >= 0 && off < ptrto->getSize() && (ptrtoMeta == TYPE_STRUCT || ptrtoMeta == TYPE_ARRAY)) {
return TypePointer::downChain(off,par,parOff,allowArrayWrap,typegrp); return TypePointer::downChain(off,par,parOff,allowArrayWrap,typegrp);
} }
uintb relOff = (off + offset) & calc_mask(size); // Convert off to be relative to the parent container int8 relOff = (off + offset) & calc_mask(size); // Convert off to be relative to the parent container
if (relOff >= parent->getSize()) if (relOff < 0 || relOff >= parent->getSize())
return (TypePointer *)0; // Don't let pointer shift beyond original container return (TypePointer *)0; // Don't let pointer shift beyond original container
TypePointer *origPointer = typegrp.getTypePointer(size, parent, wordsize); TypePointer *origPointer = typegrp.getTypePointer(size, parent, wordsize);
@ -2285,7 +2307,7 @@ bool TypePointerRel::isPtrsubMatching(uintb off) const
{ {
if (stripped != (TypePointer *)0) if (stripped != (TypePointer *)0)
return TypePointer::isPtrsubMatching(off); return TypePointer::isPtrsubMatching(off);
int4 iOff = AddrSpace::addressToByteInt((int4)off,wordsize); int4 iOff = AddrSpace::addressToByteInt(off,wordsize);
iOff += offset; iOff += offset;
return (iOff >= 0 && iOff <= parent->getSize()); return (iOff >= 0 && iOff <= parent->getSize());
} }
@ -2302,7 +2324,7 @@ Datatype *TypePointerRel::getPtrToFromParent(Datatype *base,int4 off,TypeFactory
{ {
if (off > 0) { if (off > 0) {
uintb curoff = off; int8 curoff = off;
do { do {
base = base->getSubType(curoff,&curoff); base = base->getSubType(curoff,&curoff);
} while(curoff != 0 && base != (Datatype *)0); } while(curoff != 0 && base != (Datatype *)0);
@ -2437,7 +2459,7 @@ int4 TypeCode::compareBasic(const TypeCode *op) const
return 2; // Carry on with comparison of parameters return 2; // Carry on with comparison of parameters
} }
Datatype *TypeCode::getSubType(uintb off,uintb *newoff) const Datatype *TypeCode::getSubType(int8 off,int8 *newoff) const
{ {
if (factory == (TypeFactory *)0) return (Datatype *)0; if (factory == (TypeFactory *)0) return (Datatype *)0;
@ -2564,16 +2586,16 @@ Scope *TypeSpacebase::getMap(void) const
return res; return res;
} }
Datatype *TypeSpacebase::getSubType(uintb off,uintb *newoff) const Datatype *TypeSpacebase::getSubType(int8 off,int8 *newoff) const
{ {
Scope *scope = getMap(); Scope *scope = getMap();
off = AddrSpace::byteToAddress(off, spaceid->getWordSize()); // Convert from byte offset to address unit uintb addrOff = AddrSpace::byteToAddress(off, spaceid->getWordSize()); // Convert from byte offset to address unit
// It should always be the case that the given offset represents a full encoding of the // It should always be the case that the given offset represents a full encoding of the
// pointer, so the point of context is unused and the size is given as -1 // pointer, so the point of context is unused and the size is given as -1
Address nullPoint; Address nullPoint;
uintb fullEncoding; uintb fullEncoding;
Address addr = glb->resolveConstant(spaceid, off, -1, nullPoint, fullEncoding); Address addr = glb->resolveConstant(spaceid, addrOff, -1, nullPoint, fullEncoding);
SymbolEntry *smallest; SymbolEntry *smallest;
// Assume symbol being referenced is address tied so we use a null point of context // Assume symbol being referenced is address tied so we use a null point of context
@ -2588,16 +2610,16 @@ Datatype *TypeSpacebase::getSubType(uintb off,uintb *newoff) const
return smallest->getSymbol()->getType(); return smallest->getSymbol()->getType();
} }
Datatype *TypeSpacebase::nearestArrayedComponentForward(uintb off,uintb *newoff,int4 *elSize) const Datatype *TypeSpacebase::nearestArrayedComponentForward(int8 off,int8 *newoff,int8 *elSize) const
{ {
Scope *scope = getMap(); Scope *scope = getMap();
off = AddrSpace::byteToAddress(off, spaceid->getWordSize()); // Convert from byte offset to address unit uintb addrOff = AddrSpace::byteToAddress(off, spaceid->getWordSize()); // Convert from byte offset to address unit
// It should always be the case that the given offset represents a full encoding of the // It should always be the case that the given offset represents a full encoding of the
// pointer, so the point of context is unused and the size is given as -1 // pointer, so the point of context is unused and the size is given as -1
Address nullPoint; Address nullPoint;
uintb fullEncoding; uintb fullEncoding;
Address addr = glb->resolveConstant(spaceid, off, -1, nullPoint, fullEncoding); Address addr = glb->resolveConstant(spaceid, addrOff, -1, nullPoint, fullEncoding);
SymbolEntry *smallest = scope->queryContainer(addr,1,nullPoint); SymbolEntry *smallest = scope->queryContainer(addr,1,nullPoint);
Address nextAddr; Address nextAddr;
Datatype *symbolType; Datatype *symbolType;
@ -2606,15 +2628,15 @@ Datatype *TypeSpacebase::nearestArrayedComponentForward(uintb off,uintb *newoff,
else { else {
symbolType = smallest->getSymbol()->getType(); symbolType = smallest->getSymbol()->getType();
if (symbolType->getMetatype() == TYPE_STRUCT) { if (symbolType->getMetatype() == TYPE_STRUCT) {
uintb structOff = addr.getOffset() - smallest->getAddr().getOffset(); int8 structOff = addr.getOffset() - smallest->getAddr().getOffset();
uintb dummyOff; int8 dummyOff;
Datatype *res = symbolType->nearestArrayedComponentForward(structOff, &dummyOff, elSize); Datatype *res = symbolType->nearestArrayedComponentForward(structOff, &dummyOff, elSize);
if (res != (Datatype *)0) { if (res != (Datatype *)0) {
*newoff = structOff; *newoff = structOff;
return symbolType; return symbolType;
} }
} }
int4 sz = AddrSpace::byteToAddressInt(smallest->getSize(), spaceid->getWordSize()); int8 sz = AddrSpace::byteToAddressInt(smallest->getSize(), spaceid->getWordSize());
nextAddr = smallest->getAddr() + sz; nextAddr = smallest->getAddr() + sz;
} }
if (nextAddr < addr) if (nextAddr < addr)
@ -2629,7 +2651,7 @@ Datatype *TypeSpacebase::nearestArrayedComponentForward(uintb off,uintb *newoff,
return symbolType; return symbolType;
} }
if (symbolType->getMetatype() == TYPE_STRUCT) { if (symbolType->getMetatype() == TYPE_STRUCT) {
uintb dummyOff; int8 dummyOff;
Datatype *res = symbolType->nearestArrayedComponentForward(0, &dummyOff, elSize); Datatype *res = symbolType->nearestArrayedComponentForward(0, &dummyOff, elSize);
if (res != (Datatype *)0) if (res != (Datatype *)0)
return symbolType; return symbolType;
@ -2637,7 +2659,7 @@ Datatype *TypeSpacebase::nearestArrayedComponentForward(uintb off,uintb *newoff,
return (Datatype *)0; return (Datatype *)0;
} }
Datatype *TypeSpacebase::nearestArrayedComponentBackward(uintb off,uintb *newoff,int4 *elSize) const Datatype *TypeSpacebase::nearestArrayedComponentBackward(int8 off,int8 *newoff,int8 *elSize) const
{ {
Datatype *subType = getSubType(off, newoff); Datatype *subType = getSubType(off, newoff);
@ -2648,7 +2670,7 @@ Datatype *TypeSpacebase::nearestArrayedComponentBackward(uintb off,uintb *newoff
return subType; return subType;
} }
if (subType->getMetatype() == TYPE_STRUCT) { if (subType->getMetatype() == TYPE_STRUCT) {
uintb dummyOff; int8 dummyOff;
Datatype *res = subType->nearestArrayedComponentBackward(*newoff,&dummyOff,elSize); Datatype *res = subType->nearestArrayedComponentBackward(*newoff,&dummyOff,elSize);
if (res != (Datatype *)0) if (res != (Datatype *)0)
return subType; return subType;
@ -2725,6 +2747,8 @@ TypeFactory::TypeFactory(Architecture *g)
glb = g; glb = g;
sizeOfInt = 0; sizeOfInt = 0;
sizeOfLong = 0; sizeOfLong = 0;
sizeOfPointer = 0;
sizeOfAltPointer = 0;
align = 0; align = 0;
enumsize = 0; enumsize = 0;
@ -2761,6 +2785,13 @@ void TypeFactory::setupSizes(void)
if (sizeOfLong == 0) { if (sizeOfLong == 0) {
sizeOfLong = (sizeOfInt == 4) ? 8 : sizeOfInt; sizeOfLong = (sizeOfInt == 4) ? 8 : sizeOfInt;
} }
if (sizeOfPointer == 0)
sizeOfPointer = glb->getDefaultDataSpace()->getAddrSize();
SegmentOp *segOp = glb->getSegmentOp(glb->getDefaultDataSpace());
if (segOp != (SegmentOp *)0 && segOp->hasFarPointerSupport()) {
sizeOfPointer = segOp->getInnerSize();
sizeOfAltPointer = sizeOfPointer + segOp->getBaseSize();
}
if (align == 0) if (align == 0)
align = glb->getDefaultSize(); align = glb->getDefaultSize();
if (enumsize == 0) { if (enumsize == 0) {
@ -3415,7 +3446,9 @@ TypePointer *TypeFactory::getTypePointerStripArray(int4 s,Datatype *pt,uint4 ws)
if (pt->getMetatype() == TYPE_ARRAY) if (pt->getMetatype() == TYPE_ARRAY)
pt = ((TypeArray *)pt)->getBase(); // Strip the first ARRAY type pt = ((TypeArray *)pt)->getBase(); // Strip the first ARRAY type
TypePointer tmp(s,pt,ws); TypePointer tmp(s,pt,ws);
return (TypePointer *) findAdd(tmp); TypePointer *res = (TypePointer *) findAdd(tmp);
res->calcTruncate(*this);
return res;
} }
/// Allows "pointer to array" to be constructed /// Allows "pointer to array" to be constructed
@ -3429,7 +3462,9 @@ TypePointer *TypeFactory::getTypePointer(int4 s,Datatype *pt,uint4 ws)
if (pt->hasStripped()) if (pt->hasStripped())
pt = pt->getStripped(); pt = pt->getStripped();
TypePointer tmp(s,pt,ws); TypePointer tmp(s,pt,ws);
return (TypePointer *) findAdd(tmp); TypePointer *res = (TypePointer *) findAdd(tmp);
res->calcTruncate(*this);
return res;
} }
/// The given name is attached, which distinguishes the returned data-type from /// The given name is attached, which distinguishes the returned data-type from
@ -3448,7 +3483,9 @@ TypePointer *TypeFactory::getTypePointer(int4 s,Datatype *pt,uint4 ws,const stri
tmp.name = n; tmp.name = n;
tmp.displayName = n; tmp.displayName = n;
tmp.id = Datatype::hashName(n); tmp.id = Datatype::hashName(n);
return (TypePointer *) findAdd(tmp); TypePointer *res = (TypePointer *) findAdd(tmp);
res->calcTruncate(*this);
return res;
} }
// Don't create more than a depth of 2, i.e. ptr->ptr->ptr->... // Don't create more than a depth of 2, i.e. ptr->ptr->ptr->...
@ -3620,9 +3657,24 @@ TypePointer *TypeFactory::getTypePointerWithSpace(Datatype *ptrTo,AddrSpace *spc
tp.displayName = nm; tp.displayName = nm;
tp.id = Datatype::hashName(nm); tp.id = Datatype::hashName(nm);
TypePointer *res = (TypePointer *)findAdd(tp); TypePointer *res = (TypePointer *)findAdd(tp);
res->calcTruncate(*this);
return res; return res;
} }
/// All the properties of the original pointer are preserved, except the size is changed.
/// \param ptr is the original pointer
/// \param newSize is the size of the new pointer in bytes
/// \return the resized pointer
TypePointer *TypeFactory::resizePointer(TypePointer *ptr,int4 newSize)
{
Datatype *pt = ptr->ptrto;
if (pt->hasStripped())
pt = pt->getStripped();
TypePointer tmp(newSize,pt,ptr->wordsize);
return (TypePointer *) findAdd(tmp);
}
/// Drill down into nested data-types until we get to a data-type that exactly matches the /// Drill down into nested data-types until we get to a data-type that exactly matches the
/// given offset and size, and return this data-type. Any \e union data-type encountered /// given offset and size, and return this data-type. Any \e union data-type encountered
/// terminates the process and a partial union data-type is constructed and returned. /// terminates the process and a partial union data-type is constructed and returned.
@ -3638,8 +3690,8 @@ Datatype *TypeFactory::getExactPiece(Datatype *ct,int4 offset,int4 size)
if (offset + size > ct->getSize()) if (offset + size > ct->getSize())
return (Datatype *)0; return (Datatype *)0;
Datatype *lastType = (Datatype *)0; Datatype *lastType = (Datatype *)0;
uintb lastOff = 0; int8 lastOff = 0;
uintb curOff = offset; int8 curOff = offset;
do { do {
if (ct->getSize() <= size) { if (ct->getSize() <= size) {
if (ct->getSize() == size) if (ct->getSize() == size)
@ -3748,6 +3800,7 @@ Datatype *TypeFactory::decodeTypeWithCodeFlags(Decoder &decoder,bool isConstruct
} }
tp.ptrto = decodeCode(decoder, isConstructor, isDestructor, false); tp.ptrto = decodeCode(decoder, isConstructor, isDestructor, false);
decoder.closeElement(elemId); decoder.closeElement(elemId);
tp.calcTruncate(*this);
return findAdd(tp); return findAdd(tp);
} }
@ -4129,6 +4182,9 @@ void TypeFactory::decodeDataOrganization(Decoder &decoder)
else if (subId == ELEM_LONG_SIZE) { else if (subId == ELEM_LONG_SIZE) {
sizeOfLong = decoder.readSignedInteger(ATTRIB_VALUE); sizeOfLong = decoder.readSignedInteger(ATTRIB_VALUE);
} }
else if (subId == ELEM_POINTER_SIZE) {
sizeOfPointer = decoder.readSignedInteger(ATTRIB_VALUE);
}
else if (subId == ELEM_SIZE_ALIGNMENT_MAP) { else if (subId == ELEM_SIZE_ALIGNMENT_MAP) {
for(;;) { for(;;) {
uint4 mapId = decoder.openElement(); uint4 mapId = decoder.openElement();

View file

@ -58,7 +58,7 @@ extern ElementId ELEM_INTEGER_SIZE; ///< Marshaling element \<integer_size>
extern ElementId ELEM_LONG_SIZE; ///< Marshaling element \<long_size> extern ElementId ELEM_LONG_SIZE; ///< Marshaling element \<long_size>
//extern ElementId ELEM_MACHINE_ALIGNMENT; ///< Marshaling element \<machine_alignment> //extern ElementId ELEM_MACHINE_ALIGNMENT; ///< Marshaling element \<machine_alignment>
//extern ElementId ELEM_POINTER_SHIFT; ///< Marshaling element \<pointer_shift> //extern ElementId ELEM_POINTER_SHIFT; ///< Marshaling element \<pointer_shift>
//extern ElementId ELEM_POINTER_SIZE; ///< Marshaling element \<pointer_size> extern ElementId ELEM_POINTER_SIZE; ///< Marshaling element \<pointer_size>
//extern ElementId ELEM_SHORT_SIZE; ///< Marshaling element \<short_size> //extern ElementId ELEM_SHORT_SIZE; ///< Marshaling element \<short_size>
extern ElementId ELEM_SIZE_ALIGNMENT_MAP; ///< Marshaling element \<size_alignment_map> extern ElementId ELEM_SIZE_ALIGNMENT_MAP; ///< Marshaling element \<size_alignment_map>
extern ElementId ELEM_TYPE; ///< Marshaling element \<type> extern ElementId ELEM_TYPE; ///< Marshaling element \<type>
@ -156,6 +156,7 @@ protected:
type_incomplete = 0x400, ///< Set if \b this (recursive) data-type has not been fully defined yet type_incomplete = 0x400, ///< Set if \b this (recursive) data-type has not been fully defined yet
needs_resolution = 0x800, ///< Datatype (union, pointer to union) needs resolution before propagation needs_resolution = 0x800, ///< Datatype (union, pointer to union) needs resolution before propagation
force_format = 0x7000, ///< 3-bits encoding display format, 0=none, 1=hex, 2=dec, 3=oct, 4=bin, 5=char force_format = 0x7000, ///< 3-bits encoding display format, 0=none, 1=hex, 2=dec, 3=oct, 4=bin, 5=char
truncate_bigendian = 0x8000 ///< Pointer can be truncated and is big endian
}; };
friend class TypeFactory; friend class TypeFactory;
friend struct DatatypeCompare; friend struct DatatypeCompare;
@ -207,10 +208,10 @@ public:
const string &getDisplayName(void) const { return displayName; } ///< Get string to use in display const string &getDisplayName(void) const { return displayName; } ///< Get string to use in display
Datatype *getTypedef(void) const { return typedefImm; } ///< Get the data-type immediately typedefed by \e this (or null) Datatype *getTypedef(void) const { return typedefImm; } ///< Get the data-type immediately typedefed by \e this (or null)
virtual void printRaw(ostream &s) const; ///< Print a description of the type to stream virtual void printRaw(ostream &s) const; ///< Print a description of the type to stream
virtual const TypeField *findTruncation(int4 off,int4 sz,const PcodeOp *op,int4 slot,int4 &newoff) const; virtual const TypeField *findTruncation(int8 off,int4 sz,const PcodeOp *op,int4 slot,int8 &newoff) const;
virtual Datatype *getSubType(uintb off,uintb *newoff) const; ///< Recover component data-type one-level down virtual Datatype *getSubType(int8 off,int8 *newoff) const; ///< Recover component data-type one-level down
virtual Datatype *nearestArrayedComponentForward(uintb off,uintb *newoff,int4 *elSize) const; virtual Datatype *nearestArrayedComponentForward(int8 off,int8 *newoff,int8 *elSize) const;
virtual Datatype *nearestArrayedComponentBackward(uintb off,uintb *newoff,int4 *elSize) const; virtual Datatype *nearestArrayedComponentBackward(int8 off,int8 *newoff,int8 *elSize) const;
virtual int4 getHoleSize(int4 off) const { return 0; } ///< Get number of bytes at the given offset that are padding virtual int4 getHoleSize(int4 off) const { return 0; } ///< Get number of bytes at the given offset that are padding
virtual int4 numDepend(void) const { return 0; } ///< Return number of component sub-types virtual int4 numDepend(void) const { return 0; } ///< Return number of component sub-types
virtual Datatype *getDepend(int4 index) const { return (Datatype *)0; } ///< Return the i-th component sub-type virtual Datatype *getDepend(int4 index) const { return (Datatype *)0; } ///< Return the i-th component sub-type
@ -223,7 +224,7 @@ public:
virtual Datatype *resolveInFlow(PcodeOp *op,int4 slot); ///< Tailor data-type propagation based on Varnode use virtual Datatype *resolveInFlow(PcodeOp *op,int4 slot); ///< Tailor data-type propagation based on Varnode use
virtual Datatype* findResolve(const PcodeOp *op,int4 slot); ///< Find a previously resolved sub-type virtual Datatype* findResolve(const PcodeOp *op,int4 slot); ///< Find a previously resolved sub-type
virtual int4 findCompatibleResolve(Datatype *ct) const; ///< Find a resolution compatible with the given data-type virtual int4 findCompatibleResolve(Datatype *ct) const; ///< Find a resolution compatible with the given data-type
virtual const TypeField *resolveTruncation(int4 offset,PcodeOp *op,int4 slot,int4 &newoff); virtual const TypeField *resolveTruncation(int8 offset,PcodeOp *op,int4 slot,int8 &newoff);
int4 typeOrder(const Datatype &op) const { if (this==&op) return 0; return compare(op,10); } ///< Order this with -op- datatype int4 typeOrder(const Datatype &op) const { if (this==&op) return 0; return compare(op,10); } ///< Order this with -op- datatype
int4 typeOrderBool(const Datatype &op) const; ///< Order \b this with -op-, treating \e bool data-type as special int4 typeOrderBool(const Datatype &op) const; ///< Order \b this with -op-, treating \e bool data-type as special
void encodeRef(Encoder &encoder) const; ///< Encode a reference of \b this to a stream void encodeRef(Encoder &encoder) const; ///< Encode a reference of \b this to a stream
@ -339,24 +340,27 @@ protected:
friend class TypeFactory; friend class TypeFactory;
Datatype *ptrto; ///< Type being pointed to Datatype *ptrto; ///< Type being pointed to
AddrSpace *spaceid; ///< If non-null, the address space \b this is intented to point into AddrSpace *spaceid; ///< If non-null, the address space \b this is intented to point into
TypePointer *truncate; ///< Truncated form of the pointer (if not null)
uint4 wordsize; ///< What size unit does the pointer address uint4 wordsize; ///< What size unit does the pointer address
void decode(Decoder &decoder,TypeFactory &typegrp); ///< Restore \b this pointer data-type from a stream void decode(Decoder &decoder,TypeFactory &typegrp); ///< Restore \b this pointer data-type from a stream
void calcSubmeta(void); ///< Calculate specific submeta for \b this pointer void calcSubmeta(void); ///< Calculate specific submeta for \b this pointer
void calcTruncate(TypeFactory &typegrp); // Assign a truncated pointer subcomponent if necessary
/// Internal constructor for use with decode /// Internal constructor for use with decode
TypePointer(void) : Datatype(0,TYPE_PTR) { ptrto = (Datatype *)0; wordsize=1; spaceid=(AddrSpace *)0; } TypePointer(void) : Datatype(0,TYPE_PTR) { ptrto = (Datatype *)0; wordsize=1; spaceid=(AddrSpace *)0; truncate=(TypePointer *)0; }
public: public:
/// Construct from another TypePointer /// Construct from another TypePointer
TypePointer(const TypePointer &op) : Datatype(op) { ptrto = op.ptrto; wordsize=op.wordsize; spaceid=op.spaceid; } TypePointer(const TypePointer &op) : Datatype(op) { ptrto = op.ptrto; wordsize=op.wordsize; spaceid=op.spaceid; truncate=op.truncate; }
/// Construct from a size, pointed-to type, and wordsize /// Construct from a size, pointed-to type, and wordsize
TypePointer(int4 s,Datatype *pt,uint4 ws) : Datatype(s,TYPE_PTR) { TypePointer(int4 s,Datatype *pt,uint4 ws) : Datatype(s,TYPE_PTR) {
ptrto = pt; flags = ptrto->getInheritable(); wordsize=ws; spaceid=(AddrSpace *)0; calcSubmeta(); } ptrto = pt; flags = ptrto->getInheritable(); wordsize=ws; spaceid=(AddrSpace *)0; truncate=(TypePointer *)0; calcSubmeta(); }
/// Construct from a pointed-to type and an address space attribute /// Construct from a pointed-to type and an address space attribute
TypePointer(Datatype *pt,AddrSpace *spc) : Datatype(spc->getAddrSize(), TYPE_PTR) { TypePointer(Datatype *pt,AddrSpace *spc) : Datatype(spc->getAddrSize(), TYPE_PTR) {
ptrto = pt; flags = ptrto->getInheritable(); spaceid=spc; wordsize=spc->getWordSize(); calcSubmeta(); } ptrto = pt; flags = ptrto->getInheritable(); spaceid=spc; wordsize=spc->getWordSize(); truncate=(TypePointer *)0; calcSubmeta(); }
Datatype *getPtrTo(void) const { return ptrto; } ///< Get the pointed-to Datatype Datatype *getPtrTo(void) const { return ptrto; } ///< Get the pointed-to Datatype
uint4 getWordSize(void) const { return wordsize; } ///< Get the size of the addressable unit being pointed to uint4 getWordSize(void) const { return wordsize; } ///< Get the size of the addressable unit being pointed to
AddrSpace *getSpace(void) const { return spaceid; } ///< Get any address space associated with \b this pointer AddrSpace *getSpace(void) const { return spaceid; } ///< Get any address space associated with \b this pointer
virtual void printRaw(ostream &s) const; virtual void printRaw(ostream &s) const;
virtual Datatype *getSubType(int8 off,int8 *newoff) const;
virtual int4 numDepend(void) const { return 1; } virtual int4 numDepend(void) const { return 1; }
virtual Datatype *getDepend(int4 index) const { return ptrto; } virtual Datatype *getDepend(int4 index) const { return ptrto; }
virtual void printNameBase(ostream &s) const { s << 'p'; ptrto->printNameBase(s); } virtual void printNameBase(ostream &s) const { s << 'p'; ptrto->printNameBase(s); }
@ -364,7 +368,7 @@ public:
virtual int4 compareDependency(const Datatype &op) const; virtual int4 compareDependency(const Datatype &op) const;
virtual Datatype *clone(void) const { return new TypePointer(*this); } virtual Datatype *clone(void) const { return new TypePointer(*this); }
virtual void encode(Encoder &encoder) const; virtual void encode(Encoder &encoder) const;
virtual TypePointer *downChain(uintb &off,TypePointer *&par,uintb &parOff,bool allowArrayWrap,TypeFactory &typegrp); virtual TypePointer *downChain(int8 &off,TypePointer *&par,int8 &parOff,bool allowArrayWrap,TypeFactory &typegrp);
virtual bool isPtrsubMatching(uintb off) const; virtual bool isPtrsubMatching(uintb off) const;
virtual Datatype *resolveInFlow(PcodeOp *op,int4 slot); virtual Datatype *resolveInFlow(PcodeOp *op,int4 slot);
virtual Datatype* findResolve(const PcodeOp *op,int4 slot); virtual Datatype* findResolve(const PcodeOp *op,int4 slot);
@ -388,7 +392,7 @@ public:
int4 numElements(void) const { return arraysize; } ///< Get the number of elements int4 numElements(void) const { return arraysize; } ///< Get the number of elements
Datatype *getSubEntry(int4 off,int4 sz,int4 *newoff,int4 *el) const; ///< Figure out what a byte range overlaps Datatype *getSubEntry(int4 off,int4 sz,int4 *newoff,int4 *el) const; ///< Figure out what a byte range overlaps
virtual void printRaw(ostream &s) const; virtual void printRaw(ostream &s) const;
virtual Datatype *getSubType(uintb off,uintb *newoff) const; virtual Datatype *getSubType(int8 off,int8 *newoff) const;
virtual int4 getHoleSize(int4 off) const; virtual int4 getHoleSize(int4 off) const;
virtual int4 numDepend(void) const { return 1; } virtual int4 numDepend(void) const { return 1; }
virtual Datatype *getDepend(int4 index) const { return arrayof; } virtual Datatype *getDepend(int4 index) const { return arrayof; }
@ -445,10 +449,10 @@ public:
TypeStruct(void) : Datatype(0,TYPE_STRUCT) { flags |= type_incomplete; } ///< Construct incomplete/empty TypeStruct TypeStruct(void) : Datatype(0,TYPE_STRUCT) { flags |= type_incomplete; } ///< Construct incomplete/empty TypeStruct
vector<TypeField>::const_iterator beginField(void) const { return field.begin(); } ///< Beginning of fields vector<TypeField>::const_iterator beginField(void) const { return field.begin(); } ///< Beginning of fields
vector<TypeField>::const_iterator endField(void) const { return field.end(); } ///< End of fields vector<TypeField>::const_iterator endField(void) const { return field.end(); } ///< End of fields
virtual const TypeField *findTruncation(int4 off,int4 sz,const PcodeOp *op,int4 slot,int4 &newoff) const; virtual const TypeField *findTruncation(int8 off,int4 sz,const PcodeOp *op,int4 slot,int8 &newoff) const;
virtual Datatype *getSubType(uintb off,uintb *newoff) const; virtual Datatype *getSubType(int8 off,int8 *newoff) const;
virtual Datatype *nearestArrayedComponentForward(uintb off,uintb *newoff,int4 *elSize) const; virtual Datatype *nearestArrayedComponentForward(int8 off,int8 *newoff,int8 *elSize) const;
virtual Datatype *nearestArrayedComponentBackward(uintb off,uintb *newoff,int4 *elSize) const; virtual Datatype *nearestArrayedComponentBackward(int8 off,int8 *newoff,int8 *elSize) const;
virtual int4 getHoleSize(int4 off) const; virtual int4 getHoleSize(int4 off) const;
virtual int4 numDepend(void) const { return field.size(); } virtual int4 numDepend(void) const { return field.size(); }
virtual Datatype *getDepend(int4 index) const { return field[index].type; } virtual Datatype *getDepend(int4 index) const { return field[index].type; }
@ -477,8 +481,8 @@ public:
TypeUnion(const TypeUnion &op); ///< Construct from another TypeUnion TypeUnion(const TypeUnion &op); ///< Construct from another TypeUnion
TypeUnion(void) : Datatype(0,TYPE_UNION) { flags |= (type_incomplete | needs_resolution); } ///< Construct incomplete TypeUnion TypeUnion(void) : Datatype(0,TYPE_UNION) { flags |= (type_incomplete | needs_resolution); } ///< Construct incomplete TypeUnion
const TypeField *getField(int4 i) const { return &field[i]; } ///< Get the i-th field of the union const TypeField *getField(int4 i) const { return &field[i]; } ///< Get the i-th field of the union
virtual const TypeField *findTruncation(int4 offset,int4 sz,const PcodeOp *op,int4 slot,int4 &newoff) const; virtual const TypeField *findTruncation(int8 offset,int4 sz,const PcodeOp *op,int4 slot,int8 &newoff) const;
// virtual Datatype *getSubType(uintb off,uintb *newoff) const; // virtual Datatype *getSubType(int8 off,int8 *newoff) const;
virtual int4 numDepend(void) const { return field.size(); } virtual int4 numDepend(void) const { return field.size(); }
virtual Datatype *getDepend(int4 index) const { return field[index].type; } virtual Datatype *getDepend(int4 index) const { return field[index].type; }
virtual int4 compare(const Datatype &op,int4 level) const; // For tree structure virtual int4 compare(const Datatype &op,int4 level) const; // For tree structure
@ -488,7 +492,7 @@ public:
virtual Datatype *resolveInFlow(PcodeOp *op,int4 slot); virtual Datatype *resolveInFlow(PcodeOp *op,int4 slot);
virtual Datatype* findResolve(const PcodeOp *op,int4 slot); virtual Datatype* findResolve(const PcodeOp *op,int4 slot);
virtual int4 findCompatibleResolve(Datatype *ct) const; virtual int4 findCompatibleResolve(Datatype *ct) const;
virtual const TypeField *resolveTruncation(int4 offset,PcodeOp *op,int4 slot,int4 &newoff); virtual const TypeField *resolveTruncation(int8 offset,PcodeOp *op,int4 slot,int8 &newoff);
}; };
/// \brief A data-type that holds \e part of a TypeStruct or TypeArray /// \brief A data-type that holds \e part of a TypeStruct or TypeArray
@ -502,7 +506,7 @@ public:
TypePartialStruct(Datatype *contain,int4 off,int4 sz,Datatype *strip); ///< Constructor TypePartialStruct(Datatype *contain,int4 off,int4 sz,Datatype *strip); ///< Constructor
Datatype *getParent(void) const { return container; } ///< Get the data-type containing \b this piece Datatype *getParent(void) const { return container; } ///< Get the data-type containing \b this piece
virtual void printRaw(ostream &s) const; virtual void printRaw(ostream &s) const;
virtual Datatype *getSubType(uintb off,uintb *newoff) const; virtual Datatype *getSubType(int8 off,int8 *newoff) const;
virtual int4 getHoleSize(int4 off) const; virtual int4 getHoleSize(int4 off) const;
virtual int4 compare(const Datatype &op,int4 level) const; virtual int4 compare(const Datatype &op,int4 level) const;
virtual int4 compareDependency(const Datatype &op) const; virtual int4 compareDependency(const Datatype &op) const;
@ -527,7 +531,7 @@ public:
TypePartialUnion(TypeUnion *contain,int4 off,int4 sz,Datatype *strip); ///< Constructor TypePartialUnion(TypeUnion *contain,int4 off,int4 sz,Datatype *strip); ///< Constructor
TypeUnion *getParentUnion(void) const { return container; } ///< Get the union which \b this is part of TypeUnion *getParentUnion(void) const { return container; } ///< Get the union which \b this is part of
virtual void printRaw(ostream &s) const; virtual void printRaw(ostream &s) const;
virtual const TypeField *findTruncation(int4 off,int4 sz,const PcodeOp *op,int4 slot,int4 &newoff) const; virtual const TypeField *findTruncation(int8 off,int4 sz,const PcodeOp *op,int4 slot,int8 &newoff) const;
virtual int4 numDepend(void) const; virtual int4 numDepend(void) const;
virtual Datatype *getDepend(int4 index) const; virtual Datatype *getDepend(int4 index) const;
virtual int4 compare(const Datatype &op,int4 level) const; virtual int4 compare(const Datatype &op,int4 level) const;
@ -538,7 +542,7 @@ public:
virtual Datatype *resolveInFlow(PcodeOp *op,int4 slot); virtual Datatype *resolveInFlow(PcodeOp *op,int4 slot);
virtual Datatype* findResolve(const PcodeOp *op,int4 slot); virtual Datatype* findResolve(const PcodeOp *op,int4 slot);
virtual int4 findCompatibleResolve(Datatype *ct) const; virtual int4 findCompatibleResolve(Datatype *ct) const;
virtual const TypeField *resolveTruncation(int4 off,PcodeOp *op,int4 slot,int4 &newoff); virtual const TypeField *resolveTruncation(int8 off,PcodeOp *op,int4 slot,int8 &newoff);
}; };
/// \brief Relative pointer: A pointer with a fixed offset into a specific structure or other data-type /// \brief Relative pointer: A pointer with a fixed offset into a specific structure or other data-type
@ -575,7 +579,7 @@ public:
virtual int4 compareDependency(const Datatype &op) const; virtual int4 compareDependency(const Datatype &op) const;
virtual Datatype *clone(void) const { return new TypePointerRel(*this); } virtual Datatype *clone(void) const { return new TypePointerRel(*this); }
virtual void encode(Encoder &encoder) const; virtual void encode(Encoder &encoder) const;
virtual TypePointer *downChain(uintb &off,TypePointer *&par,uintb &parOff,bool allowArrayWrap,TypeFactory &typegrp); virtual TypePointer *downChain(int8 &off,TypePointer *&par,int8 &parOff,bool allowArrayWrap,TypeFactory &typegrp);
virtual bool isPtrsubMatching(uintb off) const; virtual bool isPtrsubMatching(uintb off) const;
virtual Datatype *getStripped(void) const { return stripped; } ///< Get the plain form of the pointer virtual Datatype *getStripped(void) const { return stripped; } ///< Get the plain form of the pointer
static Datatype *getPtrToFromParent(Datatype *base,int4 off,TypeFactory &typegrp); static Datatype *getPtrToFromParent(Datatype *base,int4 off,TypeFactory &typegrp);
@ -605,7 +609,7 @@ public:
const FuncProto *getPrototype(void) const { return proto; } ///< Get the function prototype const FuncProto *getPrototype(void) const { return proto; } ///< Get the function prototype
virtual ~TypeCode(void); virtual ~TypeCode(void);
virtual void printRaw(ostream &s) const; virtual void printRaw(ostream &s) const;
virtual Datatype *getSubType(uintb off,uintb *newoff) const; virtual Datatype *getSubType(int8 off,int8 *newoff) const;
virtual int4 compare(const Datatype &op,int4 level) const; virtual int4 compare(const Datatype &op,int4 level) const;
virtual int4 compareDependency(const Datatype &op) const; virtual int4 compareDependency(const Datatype &op) const;
virtual Datatype *clone(void) const { return new TypeCode(*this); } virtual Datatype *clone(void) const { return new TypeCode(*this); }
@ -633,9 +637,9 @@ public:
: Datatype(0,TYPE_SPACEBASE), localframe(frame) { spaceid = id; glb = g; } : Datatype(0,TYPE_SPACEBASE), localframe(frame) { spaceid = id; glb = g; }
Scope *getMap(void) const; ///< Get the symbol table indexed by \b this Scope *getMap(void) const; ///< Get the symbol table indexed by \b this
Address getAddress(uintb off,int4 sz,const Address &point) const; ///< Construct an Address given an offset Address getAddress(uintb off,int4 sz,const Address &point) const; ///< Construct an Address given an offset
virtual Datatype *getSubType(uintb off,uintb *newoff) const; virtual Datatype *getSubType(int8 off,int8 *newoff) const;
virtual Datatype *nearestArrayedComponentForward(uintb off,uintb *newoff,int4 *elSize) const; virtual Datatype *nearestArrayedComponentForward(int8 off,int8 *newoff,int8 *elSize) const;
virtual Datatype *nearestArrayedComponentBackward(uintb off,uintb *newoff,int4 *elSize) const; virtual Datatype *nearestArrayedComponentBackward(int8 off,int8 *newoff,int8 *elSize) const;
virtual int4 compare(const Datatype &op,int4 level) const; virtual int4 compare(const Datatype &op,int4 level) const;
virtual int4 compareDependency(const Datatype &op) const; // For tree structure virtual int4 compareDependency(const Datatype &op) const; // For tree structure
virtual Datatype *clone(void) const { return new TypeSpacebase(*this); } virtual Datatype *clone(void) const { return new TypeSpacebase(*this); }
@ -646,6 +650,8 @@ public:
class TypeFactory { class TypeFactory {
int4 sizeOfInt; ///< Size of the core "int" datatype int4 sizeOfInt; ///< Size of the core "int" datatype
int4 sizeOfLong; ///< Size of the core "long" datatype int4 sizeOfLong; ///< Size of the core "long" datatype
int4 sizeOfPointer; ///< Size of pointers (into default data address space)
int4 sizeOfAltPointer; ///< Size of alternate pointers used by architecture (if not 0)
int4 align; ///< Alignment of structures int4 align; ///< Alignment of structures
int4 enumsize; ///< Size of an enumerated type int4 enumsize; ///< Size of an enumerated type
type_metatype enumtype; ///< Default enumeration meta-type (when parsing C) type_metatype enumtype; ///< Default enumeration meta-type (when parsing C)
@ -683,6 +689,8 @@ public:
int4 getStructAlign(void) const { return align; } ///< Get the default structure alignment int4 getStructAlign(void) const { return align; } ///< Get the default structure alignment
int4 getSizeOfInt(void) const { return sizeOfInt; } ///< Get the size of the default "int" int4 getSizeOfInt(void) const { return sizeOfInt; } ///< Get the size of the default "int"
int4 getSizeOfLong(void) const { return sizeOfLong; } ///< Get the size of the default "long" int4 getSizeOfLong(void) const { return sizeOfLong; } ///< Get the size of the default "long"
int4 getSizeOfPointer(void) const { return sizeOfPointer; } ///< Get the size of pointers
int4 getSizeOfAltPointer(void) const { return sizeOfAltPointer; } ///< Get size of alternate pointers (or 0)
Architecture *getArch(void) const { return glb; } ///< Get the Architecture object Architecture *getArch(void) const { return glb; } ///< Get the Architecture object
Datatype *findByName(const string &n); ///< Return type of given name Datatype *findByName(const string &n); ///< Return type of given name
Datatype *setName(Datatype *ct,const string &n); ///< Set the given types name Datatype *setName(Datatype *ct,const string &n); ///< Set the given types name
@ -719,6 +727,7 @@ public:
TypePointerRel *getTypePointerRel(TypePointer *parentPtr,Datatype *ptrTo,int4 off); ///< Get pointer offset relative to a container TypePointerRel *getTypePointerRel(TypePointer *parentPtr,Datatype *ptrTo,int4 off); ///< Get pointer offset relative to a container
TypePointerRel *getTypePointerRel(int4 sz,Datatype *parent,Datatype *ptrTo,int4 ws,int4 off,const string &nm); TypePointerRel *getTypePointerRel(int4 sz,Datatype *parent,Datatype *ptrTo,int4 ws,int4 off,const string &nm);
TypePointer *getTypePointerWithSpace(Datatype *ptrTo,AddrSpace *spc,const string &nm); TypePointer *getTypePointerWithSpace(Datatype *ptrTo,AddrSpace *spc,const string &nm);
TypePointer *resizePointer(TypePointer *ptr,int4 newSize); ///< Build a resized pointer based on the given pointer
Datatype *getExactPiece(Datatype *ct,int4 offset,int4 size); ///< Get the data-type associated with piece of a structured data-type Datatype *getExactPiece(Datatype *ct,int4 offset,int4 size); ///< Get the data-type associated with piece of a structured data-type
void destroyType(Datatype *ct); ///< Remove a data-type from \b this void destroyType(Datatype *ct); ///< Remove a data-type from \b this
Datatype *concretize(Datatype *ct); ///< Convert given data-type to concrete form Datatype *concretize(Datatype *ct); ///< Convert given data-type to concrete form

View file

@ -1150,19 +1150,19 @@ Datatype *TypeOpIntAdd::propagateAddIn2Out(Datatype *alttype,TypeFactory *typegr
{ {
TypePointer *pointer = (TypePointer *)alttype; TypePointer *pointer = (TypePointer *)alttype;
uintb uoffset; uintb offset;
int4 command = propagateAddPointer(uoffset,op,inslot,pointer->getPtrTo()->getSize()); int4 command = propagateAddPointer(offset,op,inslot,pointer->getPtrTo()->getSize());
if (command == 2) return op->getOut()->getTempType(); // Doesn't look like a good pointer add if (command == 2) return op->getOut()->getTempType(); // Doesn't look like a good pointer add
TypePointer *parent = (TypePointer *)0; TypePointer *parent = (TypePointer *)0;
uintb parentOff; int8 parentOff;
if (command != 3) { if (command != 3) {
uoffset = AddrSpace::addressToByte(uoffset,pointer->getWordSize()); int8 typeOffset = AddrSpace::addressToByteInt(offset,pointer->getWordSize());
bool allowWrap = (op->code() != CPUI_PTRSUB); bool allowWrap = (op->code() != CPUI_PTRSUB);
do { do {
pointer = pointer->downChain(uoffset,parent,parentOff,allowWrap,*typegrp); pointer = pointer->downChain(typeOffset,parent,parentOff,allowWrap,*typegrp);
if (pointer == (TypePointer *)0) if (pointer == (TypePointer *)0)
break; break;
} while(uoffset != 0); } while(typeOffset != 0);
} }
if (parent != (TypePointer *)0) { if (parent != (TypePointer *)0) {
// If the innermost containing object is a TYPE_STRUCT or TYPE_ARRAY // If the innermost containing object is a TYPE_STRUCT or TYPE_ARRAY
@ -1905,6 +1905,10 @@ TypeOpPiece::TypeOpPiece(TypeFactory *t)
{ {
opflags = PcodeOp::binary; opflags = PcodeOp::binary;
behave = new OpBehaviorPiece(); behave = new OpBehaviorPiece();
nearPointerSize = 0;
farPointerSize = t->getSizeOfAltPointer();
if (farPointerSize != 0)
nearPointerSize = t->getSizeOfPointer();
} }
string TypeOpPiece::getOperatorName(const PcodeOp *op) const string TypeOpPiece::getOperatorName(const PcodeOp *op) const
@ -1933,11 +1937,57 @@ Datatype *TypeOpPiece::getOutputToken(const PcodeOp *op,CastStrategy *castStrate
return tlst->getBase(vn->getSize(),TYPE_UINT); // If output is unknown or pointer, treat as cast to uint return tlst->getBase(vn->getSize(),TYPE_UINT); // If output is unknown or pointer, treat as cast to uint
} }
Datatype *TypeOpPiece::propagateType(Datatype *alttype,PcodeOp *op,Varnode *invn,Varnode *outvn,
int4 inslot,int4 outslot)
{
if (nearPointerSize != 0 && alttype->getMetatype() == TYPE_PTR) {
if (inslot == 1 && outslot == -1) {
if (invn->getSize() == nearPointerSize && outvn->getSize() == farPointerSize)
return tlst->resizePointer((TypePointer *)alttype, farPointerSize);
}
else if (inslot == -1 && outslot == 1) {
if (invn->getSize() == farPointerSize && outvn->getSize() == nearPointerSize)
return tlst->resizePointer((TypePointer *)alttype, nearPointerSize);
}
return (Datatype *)0;
}
if (inslot != -1) return (Datatype *)0;
int8 byteOff = computeByteOffsetForComposite(op,outslot);
while(alttype != (Datatype *)0 && (byteOff != 0 || alttype->getSize() != outvn->getSize())) {
alttype = alttype->getSubType(byteOff, &byteOff);
}
return alttype;
}
/// \brief Compute the byte offset into an assumed composite data-type for an input to the given CPUI_PIECE
///
/// If the output Varnode is a composite data-type, the an input to PIECE represents a
/// range of bytes starting at a particular offset within the data-type. Return this offset, which
/// depends on endianness of the output and the particular input.
/// \param op is the given CPUI_PIECE
/// \param slot is the slot of the particular input
/// \return the byte offset into the composite represented by the input of the PIECE
int4 TypeOpPiece::computeByteOffsetForComposite(const PcodeOp *op,int4 slot)
{
const Varnode *inVn0 = op->getIn(0);
int byteOff;
if (inVn0->getSpace()->isBigEndian())
byteOff = (slot==0) ? 0 : inVn0->getSize();
else
byteOff = (slot==0) ? op->getIn(1)->getSize() : 0;
return byteOff;
}
TypeOpSubpiece::TypeOpSubpiece(TypeFactory *t) TypeOpSubpiece::TypeOpSubpiece(TypeFactory *t)
: TypeOpFunc(t,CPUI_SUBPIECE,"SUB",TYPE_UNKNOWN,TYPE_UNKNOWN) : TypeOpFunc(t,CPUI_SUBPIECE,"SUB",TYPE_UNKNOWN,TYPE_UNKNOWN)
{ {
opflags = PcodeOp::binary; opflags = PcodeOp::binary;
behave = new OpBehaviorSubpiece(); behave = new OpBehaviorSubpiece();
nearPointerSize = 0;
farPointerSize = t->getSizeOfAltPointer();
if (farPointerSize != 0)
nearPointerSize = t->getSizeOfPointer();
} }
string TypeOpSubpiece::getOperatorName(const PcodeOp *op) const string TypeOpSubpiece::getOperatorName(const PcodeOp *op) const
@ -1961,8 +2011,8 @@ Datatype *TypeOpSubpiece::getOutputToken(const PcodeOp *op,CastStrategy *castStr
const Varnode *outvn = op->getOut(); const Varnode *outvn = op->getOut();
const TypeField *field; const TypeField *field;
Datatype *ct = op->getIn(0)->getHighTypeReadFacing(op); Datatype *ct = op->getIn(0)->getHighTypeReadFacing(op);
int4 offset; int8 offset;
int4 byteOff = computeByteOffsetForComposite(op); int8 byteOff = computeByteOffsetForComposite(op);
field = ct->findTruncation(byteOff,outvn->getSize(),op,1,offset); // Use artificial slot field = ct->findTruncation(byteOff,outvn->getSize(),op,1,offset); // Use artificial slot
if (field != (const TypeField *)0) { if (field != (const TypeField *)0) {
if (outvn->getSize() == field->type->getSize()) if (outvn->getSize() == field->type->getSize())
@ -1977,27 +2027,28 @@ Datatype *TypeOpSubpiece::getOutputToken(const PcodeOp *op,CastStrategy *castStr
Datatype *TypeOpSubpiece::propagateType(Datatype *alttype,PcodeOp *op,Varnode *invn,Varnode *outvn, Datatype *TypeOpSubpiece::propagateType(Datatype *alttype,PcodeOp *op,Varnode *invn,Varnode *outvn,
int4 inslot,int4 outslot) int4 inslot,int4 outslot)
{ {
if (nearPointerSize != 0 && alttype->getMetatype() == TYPE_PTR && inslot == -1 && outslot == 0) {
// Try to propagate UP, producing a far pointer input from a near pointer output of the SUBPIECE
// The case of propagating DOWN is handled by the getSubType below
if (op->getIn(1)->getOffset() != 0)
return (Datatype *)0;
if (invn->getSize() == nearPointerSize && outvn->getSize() == farPointerSize)
return tlst->resizePointer((TypePointer *)alttype, farPointerSize);
return (Datatype *)0;
}
if (inslot != 0 || outslot != -1) return (Datatype *)0; // Propagation must be from in0 to out if (inslot != 0 || outslot != -1) return (Datatype *)0; // Propagation must be from in0 to out
int4 byteOff; int8 byteOff = computeByteOffsetForComposite(op);
int4 newoff;
const TypeField *field;
type_metatype meta = alttype->getMetatype(); type_metatype meta = alttype->getMetatype();
if (meta == TYPE_UNION || meta == TYPE_PARTIALUNION) { if (meta == TYPE_UNION || meta == TYPE_PARTIALUNION) {
// NOTE: We use an artificial slot here to store the field being truncated to // NOTE: We use an artificial slot here to store the field being truncated to
// as the facing data-type for slot 0 is already to the parent (this TYPE_UNION) // as the facing data-type for slot 0 is already to the parent (this TYPE_UNION)
byteOff = computeByteOffsetForComposite(op); const TypeField *field = alttype->resolveTruncation(byteOff,op,1,byteOff);
field = alttype->resolveTruncation(byteOff,op,1,newoff); alttype = (field != (const TypeField *)0) ? field->type : (Datatype *)0;
} }
else if (alttype->getMetatype() == TYPE_STRUCT) { while(alttype != (Datatype *)0 && (byteOff != 0 || alttype->getSize() != outvn->getSize())) {
int4 byteOff = computeByteOffsetForComposite(op); alttype = alttype->getSubType(byteOff, &byteOff);
field = alttype->findTruncation(byteOff, outvn->getSize(), op, 1, newoff);
} }
else return alttype;
return (Datatype *)0;
if (field != (const TypeField *)0 && newoff == 0 && field->type->getSize() == outvn->getSize()) {
return field->type;
}
return (Datatype *)0;
} }
/// \brief Compute the byte offset into an assumed composite data-type produced by the given CPUI_SUBPIECE /// \brief Compute the byte offset into an assumed composite data-type produced by the given CPUI_SUBPIECE
@ -2013,7 +2064,7 @@ int4 TypeOpSubpiece::computeByteOffsetForComposite(const PcodeOp *op)
int4 outSize = op->getOut()->getSize(); int4 outSize = op->getOut()->getSize();
int4 lsb = (int4)op->getIn(1)->getOffset(); int4 lsb = (int4)op->getIn(1)->getOffset();
const Varnode *vn = op->getIn(0); const Varnode *vn = op->getIn(0);
int byteOff; int4 byteOff;
if (vn->getSpace()->isBigEndian()) if (vn->getSpace()->isBigEndian())
byteOff = vn->getSize() - outSize - lsb; byteOff = vn->getSize() - outSize - lsb;
else else
@ -2143,8 +2194,8 @@ Datatype *TypeOpPtrsub::getOutputToken(const PcodeOp *op,CastStrategy *castStrat
{ {
TypePointer *ptype = (TypePointer *)op->getIn(0)->getHighTypeReadFacing(op); TypePointer *ptype = (TypePointer *)op->getIn(0)->getHighTypeReadFacing(op);
if (ptype->getMetatype() == TYPE_PTR) { if (ptype->getMetatype() == TYPE_PTR) {
uintb offset = AddrSpace::addressToByte(op->getIn(1)->getOffset(),ptype->getWordSize()); int8 offset = AddrSpace::addressToByte((int8)op->getIn(1)->getOffset(),ptype->getWordSize());
uintb unusedOffset; int8 unusedOffset;
TypePointer *unusedParent; TypePointer *unusedParent;
Datatype *rettype = ptype->downChain(offset,unusedParent,unusedOffset,false,*tlst); Datatype *rettype = ptype->downChain(offset,unusedParent,unusedOffset,false,*tlst);
if ((offset==0)&&(rettype != (Datatype *)0)) if ((offset==0)&&(rettype != (Datatype *)0))
@ -2229,9 +2280,7 @@ Datatype *TypeOpSegment::propagateType(Datatype *alttype,PcodeOp *op,Varnode *in
if (invn->isSpacebase()) return (Datatype *)0; if (invn->isSpacebase()) return (Datatype *)0;
type_metatype metain = alttype->getMetatype(); type_metatype metain = alttype->getMetatype();
if (metain != TYPE_PTR) return (Datatype *)0; if (metain != TYPE_PTR) return (Datatype *)0;
AddrSpace *spc = tlst->getArch()->getDefaultDataSpace(); return tlst->resizePointer((TypePointer *)alttype, outvn->getSize());
Datatype *btype = ((TypePointer *)alttype)->getPtrTo();
return tlst->getTypePointer(outvn->getSize(),btype,spc->getWordSize());
} }
TypeOpCpoolref::TypeOpCpoolref(TypeFactory *t) : TypeOp(t,CPUI_CPOOLREF,"cpoolref") TypeOpCpoolref::TypeOpCpoolref(TypeFactory *t) : TypeOp(t,CPUI_CPOOLREF,"cpoolref")

View file

@ -745,16 +745,23 @@ public:
/// \brief Information about the PIECE op-code /// \brief Information about the PIECE op-code
class TypeOpPiece : public TypeOpFunc { class TypeOpPiece : public TypeOpFunc {
int4 nearPointerSize; ///< Size of near (truncated) pointer (if not 0)
int4 farPointerSize; ///< Size of far (extended) pointer (if not 0)
public: public:
TypeOpPiece(TypeFactory *t); ///< Constructor TypeOpPiece(TypeFactory *t); ///< Constructor
virtual Datatype *getInputCast(const PcodeOp *op,int4 slot,const CastStrategy *castStrategy) const; virtual Datatype *getInputCast(const PcodeOp *op,int4 slot,const CastStrategy *castStrategy) const;
virtual Datatype *getOutputToken(const PcodeOp *op,CastStrategy *castStrategy) const; virtual Datatype *getOutputToken(const PcodeOp *op,CastStrategy *castStrategy) const;
virtual Datatype *propagateType(Datatype *alttype,PcodeOp *op,Varnode *invn,Varnode *outvn,
int4 inslot,int4 outslot);
virtual string getOperatorName(const PcodeOp *op) const; virtual string getOperatorName(const PcodeOp *op) const;
virtual void push(PrintLanguage *lng,const PcodeOp *op,const PcodeOp *readOp) const { lng->opPiece(op); } virtual void push(PrintLanguage *lng,const PcodeOp *op,const PcodeOp *readOp) const { lng->opPiece(op); }
static int4 computeByteOffsetForComposite(const PcodeOp *op,int4 slot);
}; };
/// \brief Information about the SUBPIECE op-code /// \brief Information about the SUBPIECE op-code
class TypeOpSubpiece : public TypeOpFunc { class TypeOpSubpiece : public TypeOpFunc {
int4 nearPointerSize; ///< Size of near (truncated) pointer (if not 0)
int4 farPointerSize; ///< Size of far (extended) pointer (if not 0)
public: public:
TypeOpSubpiece(TypeFactory *t); ///< Constructor TypeOpSubpiece(TypeFactory *t); ///< Constructor
virtual Datatype *getInputCast(const PcodeOp *op,int4 slot,const CastStrategy *castStrategy) const; virtual Datatype *getInputCast(const PcodeOp *op,int4 slot,const CastStrategy *castStrategy) const;

View file

@ -232,7 +232,7 @@ Datatype *ScoreUnionFields::derefPointer(Datatype *ct,Varnode *vn,int4 &score)
if (ct->getMetatype() == TYPE_PTR) { if (ct->getMetatype() == TYPE_PTR) {
Datatype *ptrto = ((TypePointer *)ct)->getPtrTo(); Datatype *ptrto = ((TypePointer *)ct)->getPtrTo();
while(ptrto != (Datatype *)0 && ptrto->getSize() > vn->getSize()) { while(ptrto != (Datatype *)0 && ptrto->getSize() > vn->getSize()) {
uintb newoff; int8 newoff;
ptrto = ptrto->getSubType(0, &newoff); ptrto = ptrto->getSubType(0, &newoff);
} }
if (ptrto != (Datatype *)0 && ptrto->getSize() == vn->getSize()) { if (ptrto != (Datatype *)0 && ptrto->getSize() == vn->getSize()) {
@ -429,8 +429,8 @@ void ScoreUnionFields::scoreTrialDown(const Trial &trial,bool lastLevel)
Varnode *vn = trial.op->getIn(1-trial.inslot); Varnode *vn = trial.op->getIn(1-trial.inslot);
if (vn->isConstant()) { if (vn->isConstant()) {
TypePointer *baseType = (TypePointer *)trial.fitType; TypePointer *baseType = (TypePointer *)trial.fitType;
uintb off = vn->getOffset(); int8 off = vn->getOffset();
uintb parOff; int8 parOff;
TypePointer *par; TypePointer *par;
resType = baseType->downChain(off,par,parOff,trial.array,typegrp); resType = baseType->downChain(off,par,parOff,trial.array,typegrp);
if (resType != (Datatype*)0) if (resType != (Datatype*)0)
@ -860,16 +860,16 @@ Datatype *ScoreUnionFields::scoreTruncation(Datatype *ct,Varnode *vn,int4 offset
} }
} }
else { else {
uintb off = offset;
score = 10; // If we can find a size match for the truncation score = 10; // If we can find a size match for the truncation
while(ct != (Datatype*)0 && (off != 0 || ct->getSize() != vn->getSize())) { int8 curOff = offset;
while(ct != (Datatype*)0 && (curOff != 0 || ct->getSize() != vn->getSize())) {
if (ct->getMetatype() == TYPE_INT || ct->getMetatype() == TYPE_UINT) { if (ct->getMetatype() == TYPE_INT || ct->getMetatype() == TYPE_UINT) {
if (ct->getSize() >= vn->getSize() + off) { if (ct->getSize() >= vn->getSize() + curOff) {
score = 1; // Size doesn't match, but still possibly a reasonable operation score = 1; // Size doesn't match, but still possibly a reasonable operation
break; break;
} }
} }
ct = ct->getSubType(off,&off); ct = ct->getSubType(curOff,&curOff);
} }
if (ct == (Datatype *)0) if (ct == (Datatype *)0)
score = -10; score = -10;

View file

@ -39,17 +39,16 @@ bool RangeHint::reconcile(const RangeHint *b) const
b = a; // Make sure b is smallest b = a; // Make sure b is smallest
a = tmp; a = tmp;
} }
intb mod = (b->sstart - a->sstart) % a->type->getSize(); int8 mod = (b->sstart - a->sstart) % a->type->getSize();
if (mod < 0) if (mod < 0)
mod += a->type->getSize(); mod += a->type->getSize();
Datatype *sub = a->type; Datatype *sub = a->type;
uintb umod = mod;
while((sub!=(Datatype *)0)&&(sub->getSize() > b->type->getSize())) while((sub!=(Datatype *)0)&&(sub->getSize() > b->type->getSize()))
sub = sub->getSubType(umod,&umod); sub = sub->getSubType(mod,&mod);
if (sub == (Datatype *)0) return false; if (sub == (Datatype *)0) return false;
if (umod != 0) return false; if (mod != 0) return false;
if (sub->getSize() == b->type->getSize()) return true; if (sub->getSize() == b->type->getSize()) return true;
if ((b->flags & Varnode::typelock)!=0) return false; if ((b->flags & Varnode::typelock)!=0) return false;
// If we reach here, component sizes do not match // If we reach here, component sizes do not match
@ -469,7 +468,7 @@ string ScopeLocal::buildVariableName(const Address &addr,
addr.getSpace() == space) { addr.getSpace() == space) {
if (fd->getFuncProto().getLocalRange().inRange(addr,1)) { if (fd->getFuncProto().getLocalRange().inRange(addr,1)) {
intb start = (intb) AddrSpace::byteToAddress(addr.getOffset(),space->getWordSize()); intb start = (intb) AddrSpace::byteToAddress(addr.getOffset(),space->getWordSize());
sign_extend(start,addr.getAddrSize()*8-1); start = sign_extend(start,addr.getAddrSize()*8-1);
if (stackGrowsNegative) if (stackGrowsNegative)
start = -start; start = -start;
ostringstream s; ostringstream s;
@ -814,7 +813,7 @@ void MapState::addRange(uintb st,Datatype *ct,uint4 fl,RangeHint::RangeType rt,i
if (!range.inRange(Address(spaceid,st),sz)) if (!range.inRange(Address(spaceid,st),sz))
return; return;
intb sst = (intb)AddrSpace::byteToAddress(st,spaceid->getWordSize()); intb sst = (intb)AddrSpace::byteToAddress(st,spaceid->getWordSize());
sign_extend(sst,spaceid->getAddrSize()*8-1); sst = sign_extend(sst,spaceid->getAddrSize()*8-1);
sst = (intb)AddrSpace::addressToByte(sst,spaceid->getWordSize()); sst = (intb)AddrSpace::addressToByte(sst,spaceid->getWordSize());
RangeHint *newRange = new RangeHint(st,sz,sst,ct,fl,rt,hi); RangeHint *newRange = new RangeHint(st,sz,sst,ct,fl,rt,hi);
maplist.push_back(newRange); maplist.push_back(newRange);
@ -943,7 +942,7 @@ bool MapState::initialize(void)
if (maplist.empty()) return false; if (maplist.empty()) return false;
uintb high = spaceid->wrapOffset(lastrange->getLast()+1); uintb high = spaceid->wrapOffset(lastrange->getLast()+1);
intb sst = (intb)AddrSpace::byteToAddress(high,spaceid->getWordSize()); intb sst = (intb)AddrSpace::byteToAddress(high,spaceid->getWordSize());
sign_extend(sst,spaceid->getAddrSize()*8-1); sst = sign_extend(sst,spaceid->getAddrSize()*8-1);
sst = (intb)AddrSpace::addressToByte(sst,spaceid->getWordSize()); sst = (intb)AddrSpace::addressToByte(sst,spaceid->getWordSize());
// Add extra range to bound any final open entry // Add extra range to bound any final open entry
RangeHint *termRange = new RangeHint(high,1,sst,defaultType,0,RangeHint::endpoint,-2); RangeHint *termRange = new RangeHint(high,1,sst,defaultType,0,RangeHint::endpoint,-2);