mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2024-11-25 21:51:47 +00:00
Merge remote-tracking branch 'origin/GP-3424_NearFarPointerPropagation'
(Closes #5066)
This commit is contained in:
commit
bd61cbf80c
@ -666,45 +666,11 @@ uintb uintb_negate(uintb in,int4 size)
|
||||
uintb sign_extend(uintb in,int4 sizein,int4 sizeout)
|
||||
|
||||
{
|
||||
int4 signbit;
|
||||
uintb mask;
|
||||
|
||||
signbit = sizein*8 - 1;
|
||||
in &= calc_mask(sizein);
|
||||
if (sizein >= sizeout) return in;
|
||||
if ((in>>signbit) != 0) {
|
||||
mask = calc_mask(sizeout);
|
||||
uintb tmp = mask << signbit; // 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);
|
||||
intb sval = in;
|
||||
sval <<= (sizeof(intb) - sizein) * 8;
|
||||
uintb res = (uintb)(sval >> (sizeout - sizein) * 8);
|
||||
res >>= (sizeof(uintb) - sizeout)*8;
|
||||
return res;
|
||||
}
|
||||
|
||||
/// Swap the least significant \b size bytes in \b val
|
||||
|
@ -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 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-(int4 off) const; ///< Decrement address by a number of bytes
|
||||
Address operator+(int8 off) const; ///< Increment 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
|
||||
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.
|
||||
@ -420,7 +420,7 @@ inline bool Address::operator<=(const Address &op2) const {
|
||||
/// space, and the Address will wrap around if necessary.
|
||||
/// \param off is the number to add to the offset
|
||||
/// \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));
|
||||
}
|
||||
|
||||
@ -430,7 +430,7 @@ inline Address Address::operator+(int4 off) const {
|
||||
/// necessary.
|
||||
/// \param off is the number to subtract from the offset
|
||||
/// \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));
|
||||
}
|
||||
|
||||
@ -534,13 +534,38 @@ inline uintb minimalmask(uintb val)
|
||||
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 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 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 uintb byte_swap(uintb val,int4 size); ///< Return the given value with bytes swapped
|
||||
|
@ -3036,6 +3036,10 @@ ActionMarkExplicit::OpStackElement::OpStackElement(Varnode *v)
|
||||
}
|
||||
else if (opc == CPUI_PTRADD)
|
||||
slotback = 1; // Don't traverse the multiplier slot
|
||||
else if (opc == CPUI_SEGMENTOP) {
|
||||
slot = 2;
|
||||
slotback = 3;
|
||||
}
|
||||
else
|
||||
slotback = v->getDef()->numInput();
|
||||
}
|
||||
|
@ -3335,10 +3335,9 @@ void Database::decode(Decoder &decoder)
|
||||
for(;;) {
|
||||
uint4 subId = decoder.openElement();
|
||||
if (subId != ELEM_SCOPE) break;
|
||||
string name;
|
||||
string name; // Name of global scope by default
|
||||
string displayName;
|
||||
uint8 id = 0;
|
||||
bool seenId = false;
|
||||
uint8 id = 0; // Id of global scope by default
|
||||
for(;;) {
|
||||
uint4 attribId = decoder.getNextAttributeId();
|
||||
if (attribId == 0) break;
|
||||
@ -3346,13 +3345,10 @@ void Database::decode(Decoder &decoder)
|
||||
name = decoder.readString();
|
||||
else if (attribId == ATTRIB_ID) {
|
||||
id = decoder.readUnsignedInteger();
|
||||
seenId = true;
|
||||
}
|
||||
else if (attribId == ATTRIB_LABEL)
|
||||
displayName = decoder.readString();
|
||||
}
|
||||
if (name.empty() || !seenId)
|
||||
throw DecoderError("Missing name and id attributes in scope");
|
||||
Scope *parentScope = (Scope *)0;
|
||||
uint4 parentId = decoder.peekElement();
|
||||
if (parentId == ELEM_PARENT) {
|
||||
|
@ -569,8 +569,7 @@ uintb FloatFormat::opSqrt(uintb a) const
|
||||
uintb FloatFormat::opInt2Float(uintb a,int4 sizein) const
|
||||
|
||||
{
|
||||
intb ival = (intb)a;
|
||||
sign_extend(ival,8*sizein-1);
|
||||
intb ival = sign_extend(a,8*sizein-1);
|
||||
double val = (double) ival; // Convert integer to float
|
||||
return getEncoding(val);
|
||||
}
|
||||
|
@ -994,8 +994,7 @@ bool Funcdata::replaceLessequal(PcodeOp *op)
|
||||
else
|
||||
return false;
|
||||
|
||||
val = vn->getOffset(); // Treat this as signed value
|
||||
sign_extend(val,8*vn->getSize()-1);
|
||||
val = sign_extend(vn->getOffset(),8*vn->getSize()-1);
|
||||
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;
|
||||
|
@ -496,12 +496,10 @@ uintb OpBehaviorIntSdiv::evaluateBinary(int4 sizeout,int4 sizein,uintb in1,uintb
|
||||
{
|
||||
if (in2 == 0)
|
||||
throw EvaluationError("Divide by 0");
|
||||
intb num = in1; // Convert to signed
|
||||
intb denom = in2;
|
||||
sign_extend(num,8*sizein-1);
|
||||
sign_extend(denom,8*sizein-1);
|
||||
intb num = sign_extend(in1,8*sizein-1); // Convert to signed
|
||||
intb denom = sign_extend(in2,8*sizein-1);
|
||||
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
|
||||
}
|
||||
|
||||
@ -520,12 +518,10 @@ uintb OpBehaviorIntSrem::evaluateBinary(int4 sizeout,int4 sizein,uintb in1,uintb
|
||||
{
|
||||
if (in2 == 0)
|
||||
throw EvaluationError("Remainder by 0");
|
||||
intb val = in1;
|
||||
intb mod = in2;
|
||||
sign_extend(val,8*sizein-1); // Convert inputs to signed values
|
||||
sign_extend(mod,8*sizein-1);
|
||||
intb val = sign_extend(in1,8*sizein-1); // Convert inputs to signed values
|
||||
intb mod = sign_extend(in2,8*sizein-1);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -763,8 +763,8 @@ void PrintC::opSubpiece(const PcodeOp *op)
|
||||
const Varnode *vn = op->getIn(0);
|
||||
Datatype *ct = vn->getHighTypeReadFacing(op);
|
||||
if (ct->isPieceStructured()) {
|
||||
int4 offset;
|
||||
int4 byteOff = TypeOpSubpiece::computeByteOffsetForComposite(op);
|
||||
int8 offset;
|
||||
int8 byteOff = TypeOpSubpiece::computeByteOffsetForComposite(op);
|
||||
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
|
||||
pushOp(&object_member,op);
|
||||
@ -873,7 +873,7 @@ void PrintC::opPtrsub(const PcodeOp *op)
|
||||
flex = isValueFlexible(in0);
|
||||
|
||||
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) {
|
||||
suboff += ptrel->getPointerOffset();
|
||||
suboff &= calc_mask(ptype->getSize());
|
||||
@ -887,11 +887,11 @@ void PrintC::opPtrsub(const PcodeOp *op)
|
||||
return;
|
||||
}
|
||||
}
|
||||
suboff = AddrSpace::addressToByte(suboff,ptype->getWordSize());
|
||||
suboff = AddrSpace::addressToByteInt(suboff,ptype->getWordSize());
|
||||
string fieldname;
|
||||
Datatype *fieldtype;
|
||||
int4 fieldid;
|
||||
int4 newoff;
|
||||
int8 newoff;
|
||||
if (ct->getMetatype() == TYPE_UNION) {
|
||||
if (suboff != 0)
|
||||
throw LowlevelError("PTRSUB accesses union with non-zero offset");
|
||||
@ -905,9 +905,9 @@ void PrintC::opPtrsub(const PcodeOp *op)
|
||||
fieldtype = fld->type;
|
||||
}
|
||||
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 (ct->getSize() <= suboff) {
|
||||
if (ct->getSize() <= suboff || suboff < 0) {
|
||||
clear();
|
||||
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])
|
||||
vector<PartialSymbolEntry> stack;
|
||||
Datatype *finalcast = (Datatype *)0;
|
||||
int8 newoff;
|
||||
|
||||
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
|
||||
}
|
||||
const TypeField *field;
|
||||
field = ct->findTruncation(off,sz,op,inslot,off);
|
||||
field = ct->findTruncation(off,sz,op,inslot,newoff);
|
||||
if (field != (const TypeField *)0) {
|
||||
off = newoff;
|
||||
stack.emplace_back();
|
||||
PartialSymbolEntry &entry( stack.back() );
|
||||
entry.token = &object_member;
|
||||
@ -1918,8 +1920,9 @@ void PrintC::pushPartialSymbol(const Symbol *sym,int4 off,int4 sz,
|
||||
}
|
||||
else if (ct->getMetatype() == TYPE_UNION) {
|
||||
const TypeField *field;
|
||||
field = ct->findTruncation(off,sz,op,inslot,off);
|
||||
field = ct->findTruncation(off,sz,op,inslot,newoff);
|
||||
if (field != (const TypeField*)0) {
|
||||
off = newoff;
|
||||
stack.emplace_back();
|
||||
PartialSymbolEntry &entry(stack.back());
|
||||
entry.token = &object_member;
|
||||
|
@ -1322,15 +1322,13 @@ bool CircleRange::pushForwardBinary(OpCode opc,const CircleRange &in1,const Circ
|
||||
int4 sa = (int4)in2.left;
|
||||
mask = calc_mask(outSize);
|
||||
step = 1; // Lose any step
|
||||
intb valLeft = in1.left;
|
||||
intb valRight = in1.right;
|
||||
int4 bitPos = 8*inSize - 1;
|
||||
sign_extend(valLeft,bitPos);
|
||||
sign_extend(valRight,bitPos);
|
||||
intb valLeft = sign_extend(in1.left,bitPos);
|
||||
intb valRight = sign_extend(in1.right,bitPos);
|
||||
if (valLeft >= valRight) {
|
||||
valRight = (intb)(mask >> 1); // Max positive
|
||||
valLeft = valRight + 1; // Min negative
|
||||
sign_extend(valLeft,bitPos);
|
||||
valLeft = sign_extend(valLeft,bitPos);
|
||||
}
|
||||
left = (valLeft >> sa) & mask;
|
||||
right = (valRight >> sa) & mask;
|
||||
|
@ -4736,12 +4736,13 @@ int4 RuleSubZext::applyOp(PcodeOp *op,Funcdata &data)
|
||||
}
|
||||
|
||||
/// \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) => V`
|
||||
/// - `sub(zext(V),0) => sub(V)`
|
||||
/// - `sub(V & 0xffff, 0) => sub(V)`
|
||||
///
|
||||
/// This also supports the corner case:
|
||||
/// - `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)
|
||||
|
||||
{ // A SUBPIECE of an extension may cancel
|
||||
{
|
||||
Varnode *base,*thruvn;
|
||||
int4 offset,outsize,insize,farinsize;
|
||||
PcodeOp *extop;
|
||||
@ -4763,10 +4764,22 @@ int4 RuleSubCancel::applyOp(PcodeOp *op,Funcdata &data)
|
||||
if (!base->isWritten()) return 0;
|
||||
extop = base->getDef();
|
||||
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;
|
||||
offset = op->getIn(1)->getOffset();
|
||||
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();
|
||||
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.opSetInput(op,thruvn,0);
|
||||
|
||||
if (opc == CPUI_SUBPIECE)
|
||||
data.opSetInput(op,data.newConstant(op->getIn(1)->getSize(),offset),1);
|
||||
else
|
||||
if (opc != CPUI_SUBPIECE)
|
||||
data.opRemoveInput(op,1); // ZEXT, SEXT, or COPY has only 1 input
|
||||
return 1;
|
||||
}
|
||||
@ -5705,8 +5716,7 @@ uint4 AddTreeState::findArrayHint(void) const
|
||||
if (op->code() == CPUI_INT_MULT) {
|
||||
Varnode *vnconst = op->getIn(1);
|
||||
if (vnconst->isConstant()) {
|
||||
intb sval = vnconst->getOffset();
|
||||
sign_extend(sval,vnconst->getSize()*8-1);
|
||||
intb sval = sign_extend(vnconst->getOffset(),vnconst->getSize()*8-1);
|
||||
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 newoff is used to pass back the actual offset of the selected component
|
||||
/// \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)
|
||||
return (baseType->getSubType(off,newoff) != (Datatype *)0);
|
||||
|
||||
int4 elSizeBefore;
|
||||
uintb offBefore;
|
||||
int8 elSizeBefore;
|
||||
int8 offBefore;
|
||||
Datatype *typeBefore = baseType->nearestArrayedComponentBackward(off, &offBefore, &elSizeBefore);
|
||||
if (typeBefore != (Datatype *)0) {
|
||||
if (arrayHint == 1 || elSizeBefore == arrayHint) {
|
||||
int4 sizeAddr = AddrSpace::byteToAddressInt(typeBefore->getSize(),ct->getWordSize());
|
||||
if (offBefore < sizeAddr) {
|
||||
int8 sizeAddr = AddrSpace::byteToAddressInt(typeBefore->getSize(),ct->getWordSize());
|
||||
if (offBefore >= 0 && offBefore < sizeAddr) {
|
||||
// If the offset is \e inside a component with a compatible array, return it.
|
||||
*newoff = offBefore;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
int4 elSizeAfter;
|
||||
uintb offAfter;
|
||||
int8 elSizeAfter;
|
||||
int8 offAfter;
|
||||
Datatype *typeAfter = baseType->nearestArrayedComponentForward(off, &offAfter, &elSizeAfter);
|
||||
if (typeBefore == (Datatype *)0 && typeAfter == (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;
|
||||
}
|
||||
|
||||
uintb distBefore = offBefore;
|
||||
uintb distAfter = -offAfter;
|
||||
uint8 distBefore = offBefore;
|
||||
uint8 distAfter = -offAfter;
|
||||
if (arrayHint != 1) {
|
||||
if (elSizeBefore != arrayHint)
|
||||
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 treeCoeff is constant multiple being applied to the node
|
||||
/// \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 *vnterm = op->getIn(0);
|
||||
uintb val;
|
||||
uint8 val;
|
||||
|
||||
if (vnterm->isFree()) {
|
||||
valid = false;
|
||||
@ -5795,11 +5805,10 @@ bool AddTreeState::checkMultTerm(Varnode *vn,PcodeOp *op,uintb treeCoeff)
|
||||
}
|
||||
if (vnconst->isConstant()) {
|
||||
val = (vnconst->getOffset() * treeCoeff) & ptrmask;
|
||||
intb sval = (intb) val;
|
||||
sign_extend(sval, vn->getSize() * 8 - 1);
|
||||
intb sval = sign_extend(val, vn->getSize() * 8 - 1);
|
||||
intb rem = (size == 0) ? sval : sval % size;
|
||||
if (rem != 0) {
|
||||
if ((val > size) && (size != 0)) {
|
||||
if ((val >= size) && (size != 0)) {
|
||||
valid = false; // Size is too big: pointer type must be wrong
|
||||
return false;
|
||||
}
|
||||
@ -5828,17 +5837,16 @@ bool AddTreeState::checkMultTerm(Varnode *vn,PcodeOp *op,uintb treeCoeff)
|
||||
/// \param vn is the given Varnode term
|
||||
/// \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
|
||||
bool AddTreeState::checkTerm(Varnode *vn,uintb treeCoeff)
|
||||
bool AddTreeState::checkTerm(Varnode *vn,uint8 treeCoeff)
|
||||
|
||||
{
|
||||
uintb val;
|
||||
uint8 val;
|
||||
PcodeOp *def;
|
||||
|
||||
if (vn == ptr) return false;
|
||||
if (vn->isConstant()) {
|
||||
val = vn->getOffset() * treeCoeff;
|
||||
intb sval = (intb)val;
|
||||
sign_extend(sval,vn->getSize()*8-1);
|
||||
intb sval = sign_extend(val,vn->getSize()*8-1);
|
||||
intb rem = (size == 0) ? sval : (sval % size);
|
||||
if (rem!=0) { // constant is not multiple of size
|
||||
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 treeCoeff is a constant multiple applied to the entire additive tree
|
||||
/// \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;
|
||||
|
||||
@ -5921,19 +5929,18 @@ void AddTreeState::calcSubtype(void)
|
||||
// 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
|
||||
// better decision.
|
||||
intb snonmult = (intb)nonmultsum;
|
||||
sign_extend(snonmult,ptrsize*8-1);
|
||||
intb snonmult = sign_extend(nonmultsum,ptrsize*8-1);
|
||||
snonmult = snonmult % size;
|
||||
if (snonmult >= 0)
|
||||
// We assume the sum is big enough it represents an array index at this level
|
||||
offset = (uintb)snonmult;
|
||||
offset = (uint8)snonmult;
|
||||
else {
|
||||
// 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
|
||||
if (baseType->getMetatype() == TYPE_STRUCT && findArrayHint() != 0)
|
||||
offset = nonmultsum;
|
||||
else
|
||||
offset = (uintb)(snonmult + size);
|
||||
offset = (uint8)(snonmult + size);
|
||||
}
|
||||
}
|
||||
correct = nonmultsum - offset;
|
||||
@ -5947,8 +5954,8 @@ void AddTreeState::calcSubtype(void)
|
||||
isSubtype = false; // There are no offsets INTO the pointer
|
||||
}
|
||||
else if (baseType->getMetatype() == TYPE_SPACEBASE) {
|
||||
uintb nonmultbytes = AddrSpace::addressToByte(nonmultsum,ct->getWordSize()); // Convert to bytes
|
||||
uintb extra;
|
||||
int8 nonmultbytes = AddrSpace::addressToByteInt(nonmultsum,ct->getWordSize()); // Convert to bytes
|
||||
int8 extra;
|
||||
uint4 arrayHint = findArrayHint();
|
||||
// Get offset into mapped variable
|
||||
if (!hasMatchingSubType(nonmultbytes, arrayHint, &extra)) {
|
||||
@ -5960,18 +5967,19 @@ void AddTreeState::calcSubtype(void)
|
||||
isSubtype = true;
|
||||
}
|
||||
else if (baseType->getMetatype() == TYPE_STRUCT) {
|
||||
uintb nonmultbytes = AddrSpace::addressToByte(nonmultsum,ct->getWordSize()); // Convert to bytes
|
||||
uintb extra;
|
||||
intb snonmult = sign_extend(nonmultsum,ptrsize*8-1);
|
||||
int8 nonmultbytes = AddrSpace::addressToByteInt(snonmult,ct->getWordSize()); // Convert to bytes
|
||||
int8 extra;
|
||||
uint4 arrayHint = findArrayHint();
|
||||
// Get offset into field in structure
|
||||
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
|
||||
return;
|
||||
}
|
||||
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;
|
||||
if (pRelType != (TypePointerRel *)0 && offset == pRelType->getPointerOffset()) {
|
||||
// offset falls within basic ptrto
|
||||
@ -6003,8 +6011,7 @@ Varnode *AddTreeState::buildMultiples(void)
|
||||
|
||||
// Be sure to preserve sign in division below
|
||||
// Calc size-relative constant PTR addition
|
||||
intb smultsum = (intb)multsum;
|
||||
sign_extend(smultsum,ptrsize*8-1);
|
||||
intb smultsum = sign_extend(multsum,ptrsize*8-1);
|
||||
uintb constCoeff = (size==0) ? (uintb)0 : (smultsum / size) & ptrmask;
|
||||
if (constCoeff == 0)
|
||||
resNode = (Varnode *)0;
|
||||
@ -6337,13 +6344,13 @@ int4 RuleStructOffset0::applyOp(PcodeOp *op,Funcdata &data)
|
||||
Datatype *ct = ptrVn->getTypeReadFacing(op);
|
||||
if (ct->getMetatype() != TYPE_PTR) return 0;
|
||||
Datatype *baseType = ((TypePointer *)ct)->getPtrTo();
|
||||
uintb offset = 0;
|
||||
int8 offset = 0;
|
||||
if (ct->isFormalPointerRel() && ((TypePointerRel *)ct)->evaluateThruParent(0)) {
|
||||
TypePointerRel *ptRel = (TypePointerRel *)ct;
|
||||
baseType = ptRel->getParent();
|
||||
if (baseType->getMetatype() != TYPE_STRUCT)
|
||||
return 0;
|
||||
int4 iOff = ptRel->getPointerOffset();
|
||||
int8 iOff = ptRel->getPointerOffset();
|
||||
iOff = AddrSpace::addressToByteInt(iOff, ptRel->getWordSize());
|
||||
if (iOff >= baseType->getSize())
|
||||
return 0;
|
||||
@ -6899,7 +6906,7 @@ Datatype *RulePieceStructure::determineDatatype(Varnode *vn,int4 &baseOffset)
|
||||
baseOffset += entry->getOffset();
|
||||
// Find concrete sub-type that matches the size of the Varnode
|
||||
Datatype *subType = ct;
|
||||
uintb subOffset = baseOffset;
|
||||
int8 subOffset = baseOffset;
|
||||
while(subType != (Datatype *)0 && subType->getSize() > vn->getSize()) {
|
||||
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;
|
||||
uintb newOff = offset;
|
||||
int8 newOff = offset;
|
||||
for(;;) {
|
||||
ct = ct->getSubType(newOff, &newOff);
|
||||
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;
|
||||
}
|
||||
return false;
|
||||
@ -6955,7 +6962,7 @@ bool RulePieceStructure::convertZextToPiece(PcodeOp *zext,Datatype *ct,int4 offs
|
||||
int4 sz = outvn->getSize() - invn->getSize();
|
||||
if (sz > sizeof(uintb)) return false;
|
||||
offset += outvn->getSpace()->isBigEndian() ? 0 : invn->getSize();
|
||||
uintb newOff = offset;
|
||||
int8 newOff = offset;
|
||||
while(ct != (Datatype *)0 && ct->getSize() > sz) {
|
||||
ct = ct->getSubType(newOff, &newOff);
|
||||
}
|
||||
|
@ -51,25 +51,25 @@ class AddTreeState {
|
||||
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 baseSlot; ///< Slot of the ADD tree base that is holding the pointer
|
||||
uintb ptrmask; ///< Mask for modulo calculations in ptr space
|
||||
uintb offset; ///< Number of bytes we dig into the base data-type
|
||||
uintb correct; ///< Number of bytes being double counted
|
||||
uint8 ptrmask; ///< Mask for modulo calculations in ptr space
|
||||
uint8 offset; ///< Number of bytes we dig into the base data-type
|
||||
uint8 correct; ///< Number of bytes being double counted
|
||||
vector<Varnode *> multiple; ///< Varnodes which are multiples of size
|
||||
vector<intb> coeff; ///< Associated constant multiple
|
||||
vector<Varnode *> nonmult; ///< Varnodes which are not multiples
|
||||
PcodeOp *distributeOp; ///< A CPUI_INT_MULT op that needs to be distributed
|
||||
uintb multsum; ///< Sum of multiple constants
|
||||
uintb nonmultsum; ///< Sum of non-multiple constants
|
||||
uint8 multsum; ///< Sum of multiple constants
|
||||
uint8 nonmultsum; ///< Sum of non-multiple constants
|
||||
bool preventDistribution; ///< Do not distribute "multiply by constant" operation
|
||||
bool isDistributeUsed; ///< Are terms produced by distributing used
|
||||
bool isSubtype; ///< Is there a sub-type (using CPUI_PTRSUB)
|
||||
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
|
||||
uint4 findArrayHint(void) const; ///< Look for evidence of an array in a sub-component
|
||||
bool hasMatchingSubType(uintb off,uint4 arrayHint,uintb *newoff) const;
|
||||
bool checkMultTerm(Varnode *vn,PcodeOp *op, uintb 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 spanAddTree(PcodeOp *op, uintb treeCoeff); ///< Walk the given sub-tree accumulating details
|
||||
bool hasMatchingSubType(int8 off,uint4 arrayHint,int8 *newoff) const;
|
||||
bool checkMultTerm(Varnode *vn,PcodeOp *op,uint8 treeCoeff); ///< Accumulate details of INT_MULT term and continue traversal if appropriate
|
||||
bool checkTerm(Varnode *vn,uint8 treeCoeff); ///< Accumulate details of given term and continue tree traversal
|
||||
bool spanAddTree(PcodeOp *op,uint8 treeCoeff); ///< Walk the given sub-tree accumulating details
|
||||
void calcSubtype(void); ///< Calculate final sub-type offset
|
||||
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
|
||||
|
@ -584,9 +584,9 @@ intb TokenField::getValue(ParserWalker &walker) const
|
||||
|
||||
res >>= shift;
|
||||
if (signbit)
|
||||
sign_extend(res,bitend-bitstart);
|
||||
res = sign_extend(res,bitend-bitstart);
|
||||
else
|
||||
zero_extend(res,bitend-bitstart);
|
||||
res = zero_extend(res,bitend-bitstart);
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -668,9 +668,9 @@ intb ContextField::getValue(ParserWalker &walker) const
|
||||
intb res = getContextBytes(walker,startbyte,endbyte);
|
||||
res >>= shift;
|
||||
if (signbit)
|
||||
sign_extend(res,endbit-startbit);
|
||||
res = sign_extend(res,endbit-startbit);
|
||||
else
|
||||
zero_extend(res,endbit-startbit);
|
||||
res = zero_extend(res,endbit-startbit);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -102,7 +102,7 @@ public:
|
||||
virtual TokenPattern genMinPattern(const vector<TokenPattern> &ops) const { return TokenPattern(tok); }
|
||||
virtual TokenPattern genPattern(intb val) const;
|
||||
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 restoreXml(const Element *el,Translate *trans);
|
||||
};
|
||||
@ -122,7 +122,7 @@ public:
|
||||
virtual TokenPattern genMinPattern(const vector<TokenPattern> &ops) const { return TokenPattern(); }
|
||||
virtual TokenPattern genPattern(intb val) const;
|
||||
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 restoreXml(const Element *el,Translate *trans);
|
||||
};
|
||||
|
@ -168,8 +168,8 @@ public:
|
||||
|
||||
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 int4 addressToByteInt(int4 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 addressToByteInt(int8 val,uint4 ws); ///< Scale int4 from addressable units to byte 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
|
||||
};
|
||||
|
||||
@ -530,21 +530,21 @@ inline uintb AddrSpace::byteToAddress(uintb val,uint4 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
|
||||
/// \param val is the offset to convert
|
||||
/// \param ws is the number of bytes in the addressable word
|
||||
/// \return the scaled offset
|
||||
inline int4 AddrSpace::addressToByteInt(int4 val,uint4 ws) {
|
||||
inline int8 AddrSpace::addressToByteInt(int8 val,uint4 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)
|
||||
/// \param val is the offset to convert
|
||||
/// \param ws is the number of bytes in the addressable word
|
||||
/// \return the scaled offset
|
||||
inline int4 AddrSpace::byteToAddressInt(int4 val,uint4 ws) {
|
||||
inline int8 AddrSpace::byteToAddressInt(int8 val,uint4 ws) {
|
||||
return val/ws;
|
||||
}
|
||||
|
||||
|
@ -1839,7 +1839,7 @@ Datatype *SplitDatatype::getComponent(Datatype *ct,int4 offset,bool &isHole)
|
||||
{
|
||||
isHole = false;
|
||||
Datatype *curType = ct;
|
||||
uintb curOff = offset;
|
||||
int8 curOff = offset;
|
||||
do {
|
||||
curType = curType->getSubType(curOff,&curOff);
|
||||
if (curType == (Datatype *)0) {
|
||||
@ -2234,19 +2234,17 @@ void SplitDatatype::buildPointers(Varnode *rootVn,TypePointer *ptrType,int4 base
|
||||
Datatype *baseType = ptrType->getPtrTo();
|
||||
for(int4 i=0;i<dataTypePieces.size();++i) {
|
||||
Datatype *matchType = isInput ? dataTypePieces[i].inType : dataTypePieces[i].outType;
|
||||
int4 byteOffset = baseOffset + dataTypePieces[i].offset;
|
||||
int8 curOff = baseOffset + dataTypePieces[i].offset;
|
||||
Datatype *tmpType = baseType;
|
||||
uintb curOff = byteOffset;
|
||||
Varnode *inPtr = rootVn;
|
||||
do {
|
||||
uintb newOff;
|
||||
int8 newOff;
|
||||
PcodeOp *newOp;
|
||||
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
|
||||
intb sNewOff = (intb)curOff % tmpType->getSize(); // But new offset will be old offset modulo data-type size
|
||||
newOff = (sNewOff < 0) ? (sNewOff + tmpType->getSize()) : sNewOff;
|
||||
|
||||
newOff = curOff % tmpType->getSize(); // But new offset will be old offset modulo data-type size
|
||||
newOff = (newOff < 0) ? (newOff + tmpType->getSize()) : newOff;
|
||||
}
|
||||
else {
|
||||
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) {
|
||||
int4 finalOffset = (int4)curOff - (int4)newOff;
|
||||
int8 finalOffset = curOff - newOff;
|
||||
int4 sz = newType->getSize(); // Element size in bytes
|
||||
finalOffset = finalOffset / sz; // Number of elements
|
||||
sz = AddrSpace::byteToAddressInt(sz, ptrType->getWordSize());
|
||||
@ -2271,7 +2269,7 @@ void SplitDatatype::buildPointers(Varnode *rootVn,TypePointer *ptrType,int4 base
|
||||
indexVn->updateType(indexType, false, false);
|
||||
}
|
||||
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());
|
||||
data.opSetOpcode(newOp, CPUI_PTRSUB);
|
||||
data.opSetInput(newOp, inPtr, 0);
|
||||
|
@ -60,7 +60,7 @@ ElementId ELEM_INTEGER_SIZE = ElementId("integer_size",51);
|
||||
ElementId ELEM_LONG_SIZE = ElementId("long_size", 54);
|
||||
//ElementId ELEM_MACHINE_ALIGNMENT = ElementId("machine_alignment", 55);
|
||||
//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_SIZE_ALIGNMENT_MAP = ElementId("size_alignment_map", 59);
|
||||
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 newoff points to the renormalized offset to pass back
|
||||
/// \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;
|
||||
@ -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 newoff is a pointer to the passed-back offset
|
||||
/// \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
|
||||
*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 elSize is used to pass back the array element size
|
||||
/// \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;
|
||||
@ -197,7 +197,7 @@ Datatype *Datatype::nearestArrayedComponentForward(uintb off,uintb *newoff,int4
|
||||
/// \param newoff is used to pass back the offset difference
|
||||
/// \param elSize is used to pass back the array element size
|
||||
/// \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;
|
||||
@ -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 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
|
||||
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;
|
||||
@ -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
|
||||
|
||||
{
|
||||
@ -857,6 +870,7 @@ void TypePointer::decode(Decoder &decoder,TypeFactory &typegrp)
|
||||
calcSubmeta();
|
||||
if (name.size() == 0) // Inherit only if no name
|
||||
flags |= ptrto->getInheritable();
|
||||
calcTruncate(typegrp);
|
||||
// decoder.closeElement(elemId);
|
||||
}
|
||||
|
||||
@ -878,6 +892,20 @@ void TypePointer::calcSubmeta(void)
|
||||
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
|
||||
///
|
||||
/// 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 typegrp is the factory producing the (possibly new) data-type
|
||||
/// \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();
|
||||
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 (!allowArrayWrap)
|
||||
return (TypePointer *)0;
|
||||
intb signOff = (intb)off;
|
||||
sign_extend(signOff,size*8-1);
|
||||
intb signOff = sign_extend(off,size*8-1);
|
||||
signOff = signOff % ptrtoSize;
|
||||
if (signOff < 0)
|
||||
signOff = signOff + ptrtoSize;
|
||||
@ -931,15 +958,14 @@ bool TypePointer::isPtrsubMatching(uintb off) const
|
||||
|
||||
{
|
||||
if (ptrto->getMetatype()==TYPE_SPACEBASE) {
|
||||
uintb newoff = AddrSpace::addressToByte(off,wordsize);
|
||||
int8 newoff = AddrSpace::addressToByteInt(off,wordsize);
|
||||
ptrto->getSubType(newoff,&newoff);
|
||||
if (newoff != 0)
|
||||
return false;
|
||||
}
|
||||
else if (ptrto->getMetatype() == TYPE_ARRAY || ptrto->getMetatype() == TYPE_STRUCT) {
|
||||
int4 sz = off;
|
||||
int4 typesize = ptrto->getSize();
|
||||
if ((typesize <= AddrSpace::addressToByteInt(sz,wordsize))&&(typesize!=0))
|
||||
if ((typesize <= AddrSpace::addressToByteInt(off,wordsize))&&(typesize!=0))
|
||||
return false;
|
||||
}
|
||||
else if (ptrto->getMetatype() == TYPE_UNION) {
|
||||
@ -1009,7 +1035,7 @@ int4 TypeArray::compareDependency(const Datatype &op) const
|
||||
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
|
||||
*newoff = off % arrayof->getSize();
|
||||
@ -1396,7 +1422,7 @@ int4 TypeStruct::getLowerBoundField(int4 off) const
|
||||
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;
|
||||
@ -1412,7 +1438,7 @@ const TypeField *TypeStruct::findTruncation(int4 off,int4 sz,const PcodeOp *op,i
|
||||
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
|
||||
int4 i;
|
||||
@ -1441,25 +1467,25 @@ int4 TypeStruct::getHoleSize(int4 off) const
|
||||
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);
|
||||
while(i >= 0) {
|
||||
const TypeField &subfield( field[i] );
|
||||
int4 diff = (int4)off - subfield.offset;
|
||||
int8 diff = off - subfield.offset;
|
||||
if (diff > 128) break;
|
||||
Datatype *subtype = subfield.type;
|
||||
if (subtype->getMetatype() == TYPE_ARRAY) {
|
||||
*newoff = (intb)diff;
|
||||
*newoff = diff;
|
||||
*elSize = ((TypeArray *)subtype)->getBase()->getSize();
|
||||
return subtype;
|
||||
}
|
||||
else {
|
||||
uintb suboff;
|
||||
int8 suboff;
|
||||
Datatype *res = subtype->nearestArrayedComponentBackward(subtype->getSize(), &suboff, elSize);
|
||||
if (res != (Datatype *)0) {
|
||||
*newoff = (intb)diff;
|
||||
*newoff = diff;
|
||||
return subtype;
|
||||
}
|
||||
}
|
||||
@ -1468,26 +1494,26 @@ Datatype *TypeStruct::nearestArrayedComponentBackward(uintb off,uintb *newoff,in
|
||||
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);
|
||||
i += 1;
|
||||
while(i<field.size()) {
|
||||
const TypeField &subfield( field[i] );
|
||||
int4 diff = subfield.offset - off;
|
||||
int8 diff = subfield.offset - off;
|
||||
if (diff > 128) break;
|
||||
Datatype *subtype = subfield.type;
|
||||
if (subtype->getMetatype() == TYPE_ARRAY) {
|
||||
*newoff = (intb)-diff;
|
||||
*newoff = -diff;
|
||||
*elSize = ((TypeArray *)subtype)->getBase()->getSize();
|
||||
return subtype;
|
||||
}
|
||||
else {
|
||||
uintb suboff;
|
||||
int8 suboff;
|
||||
Datatype *res = subtype->nearestArrayedComponentForward(0, &suboff, elSize);
|
||||
if (res != (Datatype *)0) {
|
||||
*newoff = (intb)-diff;
|
||||
*newoff = -diff;
|
||||
return subtype;
|
||||
}
|
||||
}
|
||||
@ -1861,7 +1887,7 @@ Datatype* TypeUnion::findResolve(const PcodeOp *op,int4 slot)
|
||||
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();
|
||||
@ -1899,7 +1925,7 @@ const TypeField *TypeUnion::resolveTruncation(int4 offset,PcodeOp *op,int4 slot,
|
||||
/// \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
|
||||
/// \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.
|
||||
@ -1965,10 +1991,10 @@ void TypePartialStruct::printRaw(ostream &s) const
|
||||
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;
|
||||
Datatype *ct = container;
|
||||
do {
|
||||
@ -1977,7 +2003,7 @@ Datatype *TypePartialStruct::getSubType(uintb off,uintb *newoff) const
|
||||
break;
|
||||
off = *newoff;
|
||||
// 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;
|
||||
}
|
||||
|
||||
@ -2042,7 +2068,7 @@ void TypePartialUnion::printRaw(ostream &s) const
|
||||
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);
|
||||
@ -2104,16 +2130,14 @@ Datatype *TypePartialUnion::resolveInFlow(PcodeOp *op,int4 slot)
|
||||
|
||||
{
|
||||
Datatype *curType = container;
|
||||
int4 curOff = offset;
|
||||
int8 curOff = offset;
|
||||
while(curType != (Datatype *)0 && curType->getSize() > size) {
|
||||
if (curType->getMetatype() == TYPE_UNION) {
|
||||
const TypeField *field = curType->resolveTruncation(curOff, op, slot, curOff);
|
||||
curType = (field == (const TypeField *)0) ? (Datatype *)0 : field->type;
|
||||
}
|
||||
else {
|
||||
uintb newOff;
|
||||
curType = curType->getSubType(curOff, &newOff);
|
||||
curOff = newOff;
|
||||
curType = curType->getSubType(curOff, &curOff);
|
||||
}
|
||||
}
|
||||
if (curType != (Datatype *)0 && curType->getSize() == size)
|
||||
@ -2125,16 +2149,14 @@ Datatype* TypePartialUnion::findResolve(const PcodeOp *op,int4 slot)
|
||||
|
||||
{
|
||||
Datatype *curType = container;
|
||||
int4 curOff = offset;
|
||||
int8 curOff = offset;
|
||||
while(curType != (Datatype *)0 && curType->getSize() > size) {
|
||||
if (curType->getMetatype() == TYPE_UNION) {
|
||||
Datatype *newType = curType->findResolve(op, slot);
|
||||
curType = (newType == curType) ? (Datatype *)0 : newType;
|
||||
}
|
||||
else {
|
||||
uintb newOff;
|
||||
curType = curType->getSubType(curOff, &newOff);
|
||||
curOff = newOff;
|
||||
curType = curType->getSubType(curOff, &curOff);
|
||||
}
|
||||
}
|
||||
if (curType != (Datatype *)0 && curType->getSize() == size)
|
||||
@ -2148,7 +2170,7 @@ int4 TypePartialUnion::findCompatibleResolve(Datatype *ct) const
|
||||
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);
|
||||
@ -2262,15 +2284,15 @@ void TypePointerRel::encode(Encoder &encoder) const
|
||||
encoder.closeElement(ELEM_TYPE);
|
||||
}
|
||||
|
||||
TypePointer *TypePointerRel::downChain(uintb &off,TypePointer *&par,uintb &parOff,bool allowArrayWrap,
|
||||
TypeFactory &typegrp)
|
||||
TypePointer *TypePointerRel::downChain(int8 &off,TypePointer *&par,int8 &parOff,bool allowArrayWrap,
|
||||
TypeFactory &typegrp)
|
||||
{
|
||||
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);
|
||||
}
|
||||
uintb relOff = (off + offset) & calc_mask(size); // Convert off to be relative to the parent container
|
||||
if (relOff >= parent->getSize())
|
||||
int8 relOff = (off + offset) & calc_mask(size); // Convert off to be relative to the parent container
|
||||
if (relOff < 0 || relOff >= parent->getSize())
|
||||
return (TypePointer *)0; // Don't let pointer shift beyond original container
|
||||
|
||||
TypePointer *origPointer = typegrp.getTypePointer(size, parent, wordsize);
|
||||
@ -2285,7 +2307,7 @@ bool TypePointerRel::isPtrsubMatching(uintb off) const
|
||||
{
|
||||
if (stripped != (TypePointer *)0)
|
||||
return TypePointer::isPtrsubMatching(off);
|
||||
int4 iOff = AddrSpace::addressToByteInt((int4)off,wordsize);
|
||||
int4 iOff = AddrSpace::addressToByteInt(off,wordsize);
|
||||
iOff += offset;
|
||||
return (iOff >= 0 && iOff <= parent->getSize());
|
||||
}
|
||||
@ -2302,7 +2324,7 @@ Datatype *TypePointerRel::getPtrToFromParent(Datatype *base,int4 off,TypeFactory
|
||||
|
||||
{
|
||||
if (off > 0) {
|
||||
uintb curoff = off;
|
||||
int8 curoff = off;
|
||||
do {
|
||||
base = base->getSubType(curoff,&curoff);
|
||||
} 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
|
||||
}
|
||||
|
||||
Datatype *TypeCode::getSubType(uintb off,uintb *newoff) const
|
||||
Datatype *TypeCode::getSubType(int8 off,int8 *newoff) const
|
||||
|
||||
{
|
||||
if (factory == (TypeFactory *)0) return (Datatype *)0;
|
||||
@ -2564,16 +2586,16 @@ Scope *TypeSpacebase::getMap(void) const
|
||||
return res;
|
||||
}
|
||||
|
||||
Datatype *TypeSpacebase::getSubType(uintb off,uintb *newoff) const
|
||||
Datatype *TypeSpacebase::getSubType(int8 off,int8 *newoff) const
|
||||
|
||||
{
|
||||
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
|
||||
// pointer, so the point of context is unused and the size is given as -1
|
||||
Address nullPoint;
|
||||
uintb fullEncoding;
|
||||
Address addr = glb->resolveConstant(spaceid, off, -1, nullPoint, fullEncoding);
|
||||
Address addr = glb->resolveConstant(spaceid, addrOff, -1, nullPoint, fullEncoding);
|
||||
SymbolEntry *smallest;
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
Datatype *TypeSpacebase::nearestArrayedComponentForward(uintb off,uintb *newoff,int4 *elSize) const
|
||||
Datatype *TypeSpacebase::nearestArrayedComponentForward(int8 off,int8 *newoff,int8 *elSize) const
|
||||
|
||||
{
|
||||
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
|
||||
// pointer, so the point of context is unused and the size is given as -1
|
||||
Address nullPoint;
|
||||
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);
|
||||
Address nextAddr;
|
||||
Datatype *symbolType;
|
||||
@ -2606,15 +2628,15 @@ Datatype *TypeSpacebase::nearestArrayedComponentForward(uintb off,uintb *newoff,
|
||||
else {
|
||||
symbolType = smallest->getSymbol()->getType();
|
||||
if (symbolType->getMetatype() == TYPE_STRUCT) {
|
||||
uintb structOff = addr.getOffset() - smallest->getAddr().getOffset();
|
||||
uintb dummyOff;
|
||||
int8 structOff = addr.getOffset() - smallest->getAddr().getOffset();
|
||||
int8 dummyOff;
|
||||
Datatype *res = symbolType->nearestArrayedComponentForward(structOff, &dummyOff, elSize);
|
||||
if (res != (Datatype *)0) {
|
||||
*newoff = structOff;
|
||||
return symbolType;
|
||||
}
|
||||
}
|
||||
int4 sz = AddrSpace::byteToAddressInt(smallest->getSize(), spaceid->getWordSize());
|
||||
int8 sz = AddrSpace::byteToAddressInt(smallest->getSize(), spaceid->getWordSize());
|
||||
nextAddr = smallest->getAddr() + sz;
|
||||
}
|
||||
if (nextAddr < addr)
|
||||
@ -2629,7 +2651,7 @@ Datatype *TypeSpacebase::nearestArrayedComponentForward(uintb off,uintb *newoff,
|
||||
return symbolType;
|
||||
}
|
||||
if (symbolType->getMetatype() == TYPE_STRUCT) {
|
||||
uintb dummyOff;
|
||||
int8 dummyOff;
|
||||
Datatype *res = symbolType->nearestArrayedComponentForward(0, &dummyOff, elSize);
|
||||
if (res != (Datatype *)0)
|
||||
return symbolType;
|
||||
@ -2637,7 +2659,7 @@ Datatype *TypeSpacebase::nearestArrayedComponentForward(uintb off,uintb *newoff,
|
||||
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);
|
||||
@ -2648,7 +2670,7 @@ Datatype *TypeSpacebase::nearestArrayedComponentBackward(uintb off,uintb *newoff
|
||||
return subType;
|
||||
}
|
||||
if (subType->getMetatype() == TYPE_STRUCT) {
|
||||
uintb dummyOff;
|
||||
int8 dummyOff;
|
||||
Datatype *res = subType->nearestArrayedComponentBackward(*newoff,&dummyOff,elSize);
|
||||
if (res != (Datatype *)0)
|
||||
return subType;
|
||||
@ -2725,6 +2747,8 @@ TypeFactory::TypeFactory(Architecture *g)
|
||||
glb = g;
|
||||
sizeOfInt = 0;
|
||||
sizeOfLong = 0;
|
||||
sizeOfPointer = 0;
|
||||
sizeOfAltPointer = 0;
|
||||
align = 0;
|
||||
enumsize = 0;
|
||||
|
||||
@ -2761,6 +2785,13 @@ void TypeFactory::setupSizes(void)
|
||||
if (sizeOfLong == 0) {
|
||||
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)
|
||||
align = glb->getDefaultSize();
|
||||
if (enumsize == 0) {
|
||||
@ -3415,7 +3446,9 @@ TypePointer *TypeFactory::getTypePointerStripArray(int4 s,Datatype *pt,uint4 ws)
|
||||
if (pt->getMetatype() == TYPE_ARRAY)
|
||||
pt = ((TypeArray *)pt)->getBase(); // Strip the first ARRAY type
|
||||
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
|
||||
@ -3429,7 +3462,9 @@ TypePointer *TypeFactory::getTypePointer(int4 s,Datatype *pt,uint4 ws)
|
||||
if (pt->hasStripped())
|
||||
pt = pt->getStripped();
|
||||
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
|
||||
@ -3448,7 +3483,9 @@ TypePointer *TypeFactory::getTypePointer(int4 s,Datatype *pt,uint4 ws,const stri
|
||||
tmp.name = n;
|
||||
tmp.displayName = 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->...
|
||||
@ -3620,9 +3657,24 @@ TypePointer *TypeFactory::getTypePointerWithSpace(Datatype *ptrTo,AddrSpace *spc
|
||||
tp.displayName = nm;
|
||||
tp.id = Datatype::hashName(nm);
|
||||
TypePointer *res = (TypePointer *)findAdd(tp);
|
||||
res->calcTruncate(*this);
|
||||
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
|
||||
/// 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.
|
||||
@ -3638,8 +3690,8 @@ Datatype *TypeFactory::getExactPiece(Datatype *ct,int4 offset,int4 size)
|
||||
if (offset + size > ct->getSize())
|
||||
return (Datatype *)0;
|
||||
Datatype *lastType = (Datatype *)0;
|
||||
uintb lastOff = 0;
|
||||
uintb curOff = offset;
|
||||
int8 lastOff = 0;
|
||||
int8 curOff = offset;
|
||||
do {
|
||||
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);
|
||||
decoder.closeElement(elemId);
|
||||
tp.calcTruncate(*this);
|
||||
return findAdd(tp);
|
||||
}
|
||||
|
||||
@ -4129,6 +4182,9 @@ void TypeFactory::decodeDataOrganization(Decoder &decoder)
|
||||
else if (subId == ELEM_LONG_SIZE) {
|
||||
sizeOfLong = decoder.readSignedInteger(ATTRIB_VALUE);
|
||||
}
|
||||
else if (subId == ELEM_POINTER_SIZE) {
|
||||
sizeOfPointer = decoder.readSignedInteger(ATTRIB_VALUE);
|
||||
}
|
||||
else if (subId == ELEM_SIZE_ALIGNMENT_MAP) {
|
||||
for(;;) {
|
||||
uint4 mapId = decoder.openElement();
|
||||
|
@ -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_MACHINE_ALIGNMENT; ///< Marshaling element \<machine_alignment>
|
||||
//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_SIZE_ALIGNMENT_MAP; ///< Marshaling element \<size_alignment_map>
|
||||
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
|
||||
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
|
||||
truncate_bigendian = 0x8000 ///< Pointer can be truncated and is big endian
|
||||
};
|
||||
friend class TypeFactory;
|
||||
friend struct DatatypeCompare;
|
||||
@ -207,10 +208,10 @@ public:
|
||||
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)
|
||||
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 Datatype *getSubType(uintb off,uintb *newoff) const; ///< Recover component data-type one-level down
|
||||
virtual Datatype *nearestArrayedComponentForward(uintb off,uintb *newoff,int4 *elSize) const;
|
||||
virtual Datatype *nearestArrayedComponentBackward(uintb off,uintb *newoff,int4 *elSize) const;
|
||||
virtual const TypeField *findTruncation(int8 off,int4 sz,const PcodeOp *op,int4 slot,int8 &newoff) const;
|
||||
virtual Datatype *getSubType(int8 off,int8 *newoff) const; ///< Recover component data-type one-level down
|
||||
virtual Datatype *nearestArrayedComponentForward(int8 off,int8 *newoff,int8 *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 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
|
||||
@ -223,7 +224,7 @@ public:
|
||||
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 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 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
|
||||
@ -339,24 +340,27 @@ protected:
|
||||
friend class TypeFactory;
|
||||
Datatype *ptrto; ///< Type being pointed to
|
||||
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
|
||||
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 calcTruncate(TypeFactory &typegrp); // Assign a truncated pointer subcomponent if necessary
|
||||
/// 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:
|
||||
/// 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
|
||||
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
|
||||
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
|
||||
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
|
||||
virtual void printRaw(ostream &s) const;
|
||||
virtual Datatype *getSubType(int8 off,int8 *newoff) const;
|
||||
virtual int4 numDepend(void) const { return 1; }
|
||||
virtual Datatype *getDepend(int4 index) const { return ptrto; }
|
||||
virtual void printNameBase(ostream &s) const { s << 'p'; ptrto->printNameBase(s); }
|
||||
@ -364,7 +368,7 @@ public:
|
||||
virtual int4 compareDependency(const Datatype &op) const;
|
||||
virtual Datatype *clone(void) const { return new TypePointer(*this); }
|
||||
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 Datatype *resolveInFlow(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
|
||||
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 Datatype *getSubType(uintb off,uintb *newoff) const;
|
||||
virtual Datatype *getSubType(int8 off,int8 *newoff) const;
|
||||
virtual int4 getHoleSize(int4 off) const;
|
||||
virtual int4 numDepend(void) const { return 1; }
|
||||
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
|
||||
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
|
||||
virtual const TypeField *findTruncation(int4 off,int4 sz,const PcodeOp *op,int4 slot,int4 &newoff) const;
|
||||
virtual Datatype *getSubType(uintb off,uintb *newoff) const;
|
||||
virtual Datatype *nearestArrayedComponentForward(uintb off,uintb *newoff,int4 *elSize) const;
|
||||
virtual Datatype *nearestArrayedComponentBackward(uintb off,uintb *newoff,int4 *elSize) const;
|
||||
virtual const TypeField *findTruncation(int8 off,int4 sz,const PcodeOp *op,int4 slot,int8 &newoff) const;
|
||||
virtual Datatype *getSubType(int8 off,int8 *newoff) const;
|
||||
virtual Datatype *nearestArrayedComponentForward(int8 off,int8 *newoff,int8 *elSize) const;
|
||||
virtual Datatype *nearestArrayedComponentBackward(int8 off,int8 *newoff,int8 *elSize) const;
|
||||
virtual int4 getHoleSize(int4 off) const;
|
||||
virtual int4 numDepend(void) const { return field.size(); }
|
||||
virtual Datatype *getDepend(int4 index) const { return field[index].type; }
|
||||
@ -477,8 +481,8 @@ public:
|
||||
TypeUnion(const TypeUnion &op); ///< Construct from another 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
|
||||
virtual const TypeField *findTruncation(int4 offset,int4 sz,const PcodeOp *op,int4 slot,int4 &newoff) const;
|
||||
// virtual Datatype *getSubType(uintb off,uintb *newoff) const;
|
||||
virtual const TypeField *findTruncation(int8 offset,int4 sz,const PcodeOp *op,int4 slot,int8 &newoff) const;
|
||||
// virtual Datatype *getSubType(int8 off,int8 *newoff) const;
|
||||
virtual int4 numDepend(void) const { return field.size(); }
|
||||
virtual Datatype *getDepend(int4 index) const { return field[index].type; }
|
||||
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* findResolve(const PcodeOp *op,int4 slot);
|
||||
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
|
||||
@ -502,7 +506,7 @@ public:
|
||||
TypePartialStruct(Datatype *contain,int4 off,int4 sz,Datatype *strip); ///< Constructor
|
||||
Datatype *getParent(void) const { return container; } ///< Get the data-type containing \b this piece
|
||||
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 compare(const Datatype &op,int4 level) const;
|
||||
virtual int4 compareDependency(const Datatype &op) const;
|
||||
@ -527,7 +531,7 @@ public:
|
||||
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
|
||||
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 Datatype *getDepend(int4 index) const;
|
||||
virtual int4 compare(const Datatype &op,int4 level) const;
|
||||
@ -538,7 +542,7 @@ public:
|
||||
virtual Datatype *resolveInFlow(PcodeOp *op,int4 slot);
|
||||
virtual Datatype* findResolve(const PcodeOp *op,int4 slot);
|
||||
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
|
||||
@ -575,7 +579,7 @@ public:
|
||||
virtual int4 compareDependency(const Datatype &op) const;
|
||||
virtual Datatype *clone(void) const { return new TypePointerRel(*this); }
|
||||
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 Datatype *getStripped(void) const { return stripped; } ///< Get the plain form of the pointer
|
||||
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
|
||||
virtual ~TypeCode(void);
|
||||
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 compareDependency(const Datatype &op) const;
|
||||
virtual Datatype *clone(void) const { return new TypeCode(*this); }
|
||||
@ -633,9 +637,9 @@ public:
|
||||
: Datatype(0,TYPE_SPACEBASE), localframe(frame) { spaceid = id; glb = g; }
|
||||
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
|
||||
virtual Datatype *getSubType(uintb off,uintb *newoff) const;
|
||||
virtual Datatype *nearestArrayedComponentForward(uintb off,uintb *newoff,int4 *elSize) const;
|
||||
virtual Datatype *nearestArrayedComponentBackward(uintb off,uintb *newoff,int4 *elSize) const;
|
||||
virtual Datatype *getSubType(int8 off,int8 *newoff) const;
|
||||
virtual Datatype *nearestArrayedComponentForward(int8 off,int8 *newoff,int8 *elSize) const;
|
||||
virtual Datatype *nearestArrayedComponentBackward(int8 off,int8 *newoff,int8 *elSize) const;
|
||||
virtual int4 compare(const Datatype &op,int4 level) const;
|
||||
virtual int4 compareDependency(const Datatype &op) const; // For tree structure
|
||||
virtual Datatype *clone(void) const { return new TypeSpacebase(*this); }
|
||||
@ -646,6 +650,8 @@ public:
|
||||
class TypeFactory {
|
||||
int4 sizeOfInt; ///< Size of the core "int" 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 enumsize; ///< Size of an enumerated type
|
||||
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 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 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
|
||||
Datatype *findByName(const string &n); ///< Return type of given 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(int4 sz,Datatype *parent,Datatype *ptrTo,int4 ws,int4 off,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
|
||||
void destroyType(Datatype *ct); ///< Remove a data-type from \b this
|
||||
Datatype *concretize(Datatype *ct); ///< Convert given data-type to concrete form
|
||||
|
@ -1150,19 +1150,19 @@ Datatype *TypeOpIntAdd::propagateAddIn2Out(Datatype *alttype,TypeFactory *typegr
|
||||
|
||||
{
|
||||
TypePointer *pointer = (TypePointer *)alttype;
|
||||
uintb uoffset;
|
||||
int4 command = propagateAddPointer(uoffset,op,inslot,pointer->getPtrTo()->getSize());
|
||||
uintb offset;
|
||||
int4 command = propagateAddPointer(offset,op,inslot,pointer->getPtrTo()->getSize());
|
||||
if (command == 2) return op->getOut()->getTempType(); // Doesn't look like a good pointer add
|
||||
TypePointer *parent = (TypePointer *)0;
|
||||
uintb parentOff;
|
||||
int8 parentOff;
|
||||
if (command != 3) {
|
||||
uoffset = AddrSpace::addressToByte(uoffset,pointer->getWordSize());
|
||||
int8 typeOffset = AddrSpace::addressToByteInt(offset,pointer->getWordSize());
|
||||
bool allowWrap = (op->code() != CPUI_PTRSUB);
|
||||
do {
|
||||
pointer = pointer->downChain(uoffset,parent,parentOff,allowWrap,*typegrp);
|
||||
pointer = pointer->downChain(typeOffset,parent,parentOff,allowWrap,*typegrp);
|
||||
if (pointer == (TypePointer *)0)
|
||||
break;
|
||||
} while(uoffset != 0);
|
||||
} while(typeOffset != 0);
|
||||
}
|
||||
if (parent != (TypePointer *)0) {
|
||||
// If the innermost containing object is a TYPE_STRUCT or TYPE_ARRAY
|
||||
@ -1905,6 +1905,10 @@ TypeOpPiece::TypeOpPiece(TypeFactory *t)
|
||||
{
|
||||
opflags = PcodeOp::binary;
|
||||
behave = new OpBehaviorPiece();
|
||||
nearPointerSize = 0;
|
||||
farPointerSize = t->getSizeOfAltPointer();
|
||||
if (farPointerSize != 0)
|
||||
nearPointerSize = t->getSizeOfPointer();
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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)
|
||||
: TypeOpFunc(t,CPUI_SUBPIECE,"SUB",TYPE_UNKNOWN,TYPE_UNKNOWN)
|
||||
{
|
||||
opflags = PcodeOp::binary;
|
||||
behave = new OpBehaviorSubpiece();
|
||||
nearPointerSize = 0;
|
||||
farPointerSize = t->getSizeOfAltPointer();
|
||||
if (farPointerSize != 0)
|
||||
nearPointerSize = t->getSizeOfPointer();
|
||||
}
|
||||
|
||||
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 TypeField *field;
|
||||
Datatype *ct = op->getIn(0)->getHighTypeReadFacing(op);
|
||||
int4 offset;
|
||||
int4 byteOff = computeByteOffsetForComposite(op);
|
||||
int8 offset;
|
||||
int8 byteOff = computeByteOffsetForComposite(op);
|
||||
field = ct->findTruncation(byteOff,outvn->getSize(),op,1,offset); // Use artificial slot
|
||||
if (field != (const TypeField *)0) {
|
||||
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,
|
||||
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
|
||||
int4 byteOff;
|
||||
int4 newoff;
|
||||
const TypeField *field;
|
||||
int8 byteOff = computeByteOffsetForComposite(op);
|
||||
type_metatype meta = alttype->getMetatype();
|
||||
if (meta == TYPE_UNION || meta == TYPE_PARTIALUNION) {
|
||||
// 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)
|
||||
byteOff = computeByteOffsetForComposite(op);
|
||||
field = alttype->resolveTruncation(byteOff,op,1,newoff);
|
||||
const TypeField *field = alttype->resolveTruncation(byteOff,op,1,byteOff);
|
||||
alttype = (field != (const TypeField *)0) ? field->type : (Datatype *)0;
|
||||
}
|
||||
else if (alttype->getMetatype() == TYPE_STRUCT) {
|
||||
int4 byteOff = computeByteOffsetForComposite(op);
|
||||
field = alttype->findTruncation(byteOff, outvn->getSize(), op, 1, newoff);
|
||||
while(alttype != (Datatype *)0 && (byteOff != 0 || alttype->getSize() != outvn->getSize())) {
|
||||
alttype = alttype->getSubType(byteOff, &byteOff);
|
||||
}
|
||||
else
|
||||
return (Datatype *)0;
|
||||
if (field != (const TypeField *)0 && newoff == 0 && field->type->getSize() == outvn->getSize()) {
|
||||
return field->type;
|
||||
}
|
||||
return (Datatype *)0;
|
||||
return alttype;
|
||||
}
|
||||
|
||||
/// \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 lsb = (int4)op->getIn(1)->getOffset();
|
||||
const Varnode *vn = op->getIn(0);
|
||||
int byteOff;
|
||||
int4 byteOff;
|
||||
if (vn->getSpace()->isBigEndian())
|
||||
byteOff = vn->getSize() - outSize - lsb;
|
||||
else
|
||||
@ -2143,8 +2194,8 @@ Datatype *TypeOpPtrsub::getOutputToken(const PcodeOp *op,CastStrategy *castStrat
|
||||
{
|
||||
TypePointer *ptype = (TypePointer *)op->getIn(0)->getHighTypeReadFacing(op);
|
||||
if (ptype->getMetatype() == TYPE_PTR) {
|
||||
uintb offset = AddrSpace::addressToByte(op->getIn(1)->getOffset(),ptype->getWordSize());
|
||||
uintb unusedOffset;
|
||||
int8 offset = AddrSpace::addressToByte((int8)op->getIn(1)->getOffset(),ptype->getWordSize());
|
||||
int8 unusedOffset;
|
||||
TypePointer *unusedParent;
|
||||
Datatype *rettype = ptype->downChain(offset,unusedParent,unusedOffset,false,*tlst);
|
||||
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;
|
||||
type_metatype metain = alttype->getMetatype();
|
||||
if (metain != TYPE_PTR) return (Datatype *)0;
|
||||
AddrSpace *spc = tlst->getArch()->getDefaultDataSpace();
|
||||
Datatype *btype = ((TypePointer *)alttype)->getPtrTo();
|
||||
return tlst->getTypePointer(outvn->getSize(),btype,spc->getWordSize());
|
||||
return tlst->resizePointer((TypePointer *)alttype, outvn->getSize());
|
||||
}
|
||||
|
||||
TypeOpCpoolref::TypeOpCpoolref(TypeFactory *t) : TypeOp(t,CPUI_CPOOLREF,"cpoolref")
|
||||
|
@ -745,16 +745,23 @@ public:
|
||||
|
||||
/// \brief Information about the PIECE op-code
|
||||
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:
|
||||
TypeOpPiece(TypeFactory *t); ///< Constructor
|
||||
virtual Datatype *getInputCast(const PcodeOp *op,int4 slot,const 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 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
|
||||
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:
|
||||
TypeOpSubpiece(TypeFactory *t); ///< Constructor
|
||||
virtual Datatype *getInputCast(const PcodeOp *op,int4 slot,const CastStrategy *castStrategy) const;
|
||||
|
@ -232,7 +232,7 @@ Datatype *ScoreUnionFields::derefPointer(Datatype *ct,Varnode *vn,int4 &score)
|
||||
if (ct->getMetatype() == TYPE_PTR) {
|
||||
Datatype *ptrto = ((TypePointer *)ct)->getPtrTo();
|
||||
while(ptrto != (Datatype *)0 && ptrto->getSize() > vn->getSize()) {
|
||||
uintb newoff;
|
||||
int8 newoff;
|
||||
ptrto = ptrto->getSubType(0, &newoff);
|
||||
}
|
||||
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);
|
||||
if (vn->isConstant()) {
|
||||
TypePointer *baseType = (TypePointer *)trial.fitType;
|
||||
uintb off = vn->getOffset();
|
||||
uintb parOff;
|
||||
int8 off = vn->getOffset();
|
||||
int8 parOff;
|
||||
TypePointer *par;
|
||||
resType = baseType->downChain(off,par,parOff,trial.array,typegrp);
|
||||
if (resType != (Datatype*)0)
|
||||
@ -860,16 +860,16 @@ Datatype *ScoreUnionFields::scoreTruncation(Datatype *ct,Varnode *vn,int4 offset
|
||||
}
|
||||
}
|
||||
else {
|
||||
uintb off = offset;
|
||||
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->getSize() >= vn->getSize() + off) {
|
||||
if (ct->getSize() >= vn->getSize() + curOff) {
|
||||
score = 1; // Size doesn't match, but still possibly a reasonable operation
|
||||
break;
|
||||
}
|
||||
}
|
||||
ct = ct->getSubType(off,&off);
|
||||
ct = ct->getSubType(curOff,&curOff);
|
||||
}
|
||||
if (ct == (Datatype *)0)
|
||||
score = -10;
|
||||
|
@ -39,17 +39,16 @@ bool RangeHint::reconcile(const RangeHint *b) const
|
||||
b = a; // Make sure b is smallest
|
||||
a = tmp;
|
||||
}
|
||||
intb mod = (b->sstart - a->sstart) % a->type->getSize();
|
||||
int8 mod = (b->sstart - a->sstart) % a->type->getSize();
|
||||
if (mod < 0)
|
||||
mod += a->type->getSize();
|
||||
|
||||
Datatype *sub = a->type;
|
||||
uintb umod = mod;
|
||||
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 (umod != 0) return false;
|
||||
if (mod != 0) return false;
|
||||
if (sub->getSize() == b->type->getSize()) return true;
|
||||
if ((b->flags & Varnode::typelock)!=0) return false;
|
||||
// If we reach here, component sizes do not match
|
||||
@ -469,7 +468,7 @@ string ScopeLocal::buildVariableName(const Address &addr,
|
||||
addr.getSpace() == space) {
|
||||
if (fd->getFuncProto().getLocalRange().inRange(addr,1)) {
|
||||
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)
|
||||
start = -start;
|
||||
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))
|
||||
return;
|
||||
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());
|
||||
RangeHint *newRange = new RangeHint(st,sz,sst,ct,fl,rt,hi);
|
||||
maplist.push_back(newRange);
|
||||
@ -943,7 +942,7 @@ bool MapState::initialize(void)
|
||||
if (maplist.empty()) return false;
|
||||
uintb high = spaceid->wrapOffset(lastrange->getLast()+1);
|
||||
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());
|
||||
// Add extra range to bound any final open entry
|
||||
RangeHint *termRange = new RangeHint(high,1,sst,defaultType,0,RangeHint::endpoint,-2);
|
||||
|
Loading…
Reference in New Issue
Block a user