diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/address.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/address.cc index 2eb08b96ab..40526a88fd 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/address.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/address.cc @@ -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)&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)<> (sizeout - sizein) * 8); + res >>= (sizeof(uintb) - sizeout)*8; + return res; } /// Swap the least significant \b size bytes in \b val diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/address.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/address.hh index 81c65a72ac..a14ea46a6b 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/address.hh +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/address.hh @@ -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 diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.cc index 5e3bfd1054..938cb62834 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.cc @@ -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(); } diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/database.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/database.cc index 3bd9ae6b72..55446161e5 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/database.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/database.cc @@ -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) { diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/float.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/float.cc index 2698643b49..2e8a4c6b2c 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/float.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/float.cc @@ -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); } diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata_op.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata_op.cc index 2ecc1bd22e..56400b2b8a 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata_op.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata_op.cc @@ -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; diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/opbehavior.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/opbehavior.cc index fcd75cc7da..aebcfd9103 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/opbehavior.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/opbehavior.cc @@ -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; } diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/printc.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/printc.cc index e4afcce855..b2637c1a59 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/printc.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/printc.cc @@ -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 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; diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/rangeutil.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/rangeutil.cc index a557204e59..1a5bff46d2 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/rangeutil.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/rangeutil.cc @@ -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; diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/ruleaction.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/ruleaction.cc index 4851365d4c..ae2e502c19 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/ruleaction.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/ruleaction.cc @@ -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 &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); } diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/ruleaction.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/ruleaction.hh index 53f1a44ef0..1988db3fb0 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/ruleaction.hh +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/ruleaction.hh @@ -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 multiple; ///< Varnodes which are multiples of size vector coeff; ///< Associated constant multiple vector 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 diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/slghpatexpress.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/slghpatexpress.cc index 5d6a2b9b48..5418473ab7 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/slghpatexpress.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/slghpatexpress.cc @@ -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; } diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/slghpatexpress.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/slghpatexpress.hh index c260fde829..48af95afcc 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/slghpatexpress.hh +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/slghpatexpress.hh @@ -102,7 +102,7 @@ public: virtual TokenPattern genMinPattern(const vector &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 &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); }; diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/space.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/space.hh index 23b1417248..4a8791cfd5 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/space.hh +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/space.hh @@ -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; } diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/subflow.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/subflow.cc index f5074f6cf1..1cbf9f9404 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/subflow.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/subflow.cc @@ -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= 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); diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/type.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/type.cc index 30faf0b656..ec735c5417 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/type.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/type.cc @@ -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 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(); diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/type.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/type.hh index 0467995dd6..dc28a0b912 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/type.hh +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/type.hh @@ -58,7 +58,7 @@ extern ElementId ELEM_INTEGER_SIZE; ///< Marshaling element \ extern ElementId ELEM_LONG_SIZE; ///< Marshaling element \ //extern ElementId ELEM_MACHINE_ALIGNMENT; ///< Marshaling element \ //extern ElementId ELEM_POINTER_SHIFT; ///< Marshaling element \ -//extern ElementId ELEM_POINTER_SIZE; ///< Marshaling element \ +extern ElementId ELEM_POINTER_SIZE; ///< Marshaling element \ //extern ElementId ELEM_SHORT_SIZE; ///< Marshaling element \ extern ElementId ELEM_SIZE_ALIGNMENT_MAP; ///< Marshaling element \ extern ElementId ELEM_TYPE; ///< Marshaling element \ @@ -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::const_iterator beginField(void) const { return field.begin(); } ///< Beginning of fields vector::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 diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/typeop.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/typeop.cc index ba05252305..21261db84b 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/typeop.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/typeop.cc @@ -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") diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/typeop.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/typeop.hh index 0d249ab939..e5e5576f2c 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/typeop.hh +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/typeop.hh @@ -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; diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/unionresolve.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/unionresolve.cc index c7c6991704..8b40cb8cd8 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/unionresolve.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/unionresolve.cc @@ -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; diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/varmap.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/varmap.cc index 4f50259aef..ce1660be62 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/varmap.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/varmap.cc @@ -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);