adjustments to resolveConstant

This commit is contained in:
caheckman 2019-08-19 10:19:36 -04:00
parent 612c0d6f3e
commit 4edff2b9f0
10 changed files with 51 additions and 20 deletions

View file

@ -1135,7 +1135,7 @@ void Architecture::init(DocumentStorage &store)
fillinReadOnlyFromLoader(); fillinReadOnlyFromLoader();
} }
Address SegmentedResolver::resolve(uintb val,int4 sz,const Address &point) Address SegmentedResolver::resolve(uintb val,int4 sz,const Address &point,uintb &fullEncoding)
{ {
int4 innersz = segop->getInnerSize(); int4 innersz = segop->getInnerSize();
@ -1145,6 +1145,7 @@ Address SegmentedResolver::resolve(uintb val,int4 sz,const Address &point)
// (as with near pointers) // (as with near pointers)
if (segop->getResolve().space != (AddrSpace *)0) { if (segop->getResolve().space != (AddrSpace *)0) {
uintb base = glb->context->getTrackedValue(segop->getResolve(),point); uintb base = glb->context->getTrackedValue(segop->getResolve(),point);
fullEncoding = (base << 8 * innersz) + (val & calc_mask(innersz));
vector<uintb> seginput; vector<uintb> seginput;
seginput.push_back(val); seginput.push_back(val);
seginput.push_back(base); seginput.push_back(base);
@ -1153,6 +1154,7 @@ Address SegmentedResolver::resolve(uintb val,int4 sz,const Address &point)
} }
} }
else { // For anything else, consider it a "far" pointer else { // For anything else, consider it a "far" pointer
fullEncoding = val;
int4 outersz = segop->getBaseSize(); int4 outersz = segop->getBaseSize();
uintb base = (val >> 8*innersz) & calc_mask(outersz); uintb base = (val >> 8*innersz) & calc_mask(outersz);
val = val & calc_mask(innersz); val = val & calc_mask(innersz);

View file

@ -284,7 +284,7 @@ public:
/// \param sp is the segmented space /// \param sp is the segmented space
/// \param sop is the segment operator /// \param sop is the segment operator
SegmentedResolver(Architecture *g,AddrSpace *sp,SegmentOp *sop) { glb=g; spc=sp; segop=sop; } SegmentedResolver(Architecture *g,AddrSpace *sp,SegmentOp *sop) { glb=g; spc=sp; segop=sop; }
virtual Address resolve(uintb val,int4 sz,const Address &point); virtual Address resolve(uintb val,int4 sz,const Address &point,uintb &fullEncoding);
}; };
/// The Translate object keeps track of address ranges for which /// The Translate object keeps track of address ranges for which

View file

@ -827,14 +827,14 @@ int4 ActionShadowVar::apply(Funcdata &data)
/// \param rampoint will hold the Address of the resolved symbol /// \param rampoint will hold the Address of the resolved symbol
/// \param data is the function being analyzed /// \param data is the function being analyzed
/// \return the recovered symbol or NULL /// \return the recovered symbol or NULL
SymbolEntry *ActionConstantPtr::isPointer(AddrSpace *spc,Varnode *vn,PcodeOp *op,Address &rampoint,Funcdata &data) SymbolEntry *ActionConstantPtr::isPointer(AddrSpace *spc,Varnode *vn,PcodeOp *op,Address &rampoint,uintb &fullEncoding,Funcdata &data)
{ {
bool needexacthit; bool needexacthit;
Architecture *glb = data.getArch(); Architecture *glb = data.getArch();
Varnode *outvn; Varnode *outvn;
if (vn->getType()->getMetatype() == TYPE_PTR) { // Are we explicitly marked as a pointer if (vn->getType()->getMetatype() == TYPE_PTR) { // Are we explicitly marked as a pointer
rampoint = glb->resolveConstant(spc,vn->getOffset(),vn->getSize(),op->getAddr()); rampoint = glb->resolveConstant(spc,vn->getOffset(),vn->getSize(),op->getAddr(),fullEncoding);
needexacthit = false; needexacthit = false;
} }
else { else {
@ -881,7 +881,7 @@ SymbolEntry *ActionConstantPtr::isPointer(AddrSpace *spc,Varnode *vn,PcodeOp *op
// Check if the constant looks like a single bit or mask // Check if the constant looks like a single bit or mask
if (bit_transitions(vn->getOffset(),vn->getSize()) < 3) if (bit_transitions(vn->getOffset(),vn->getSize()) < 3)
return (SymbolEntry *)0; return (SymbolEntry *)0;
rampoint = glb->resolveConstant(spc,vn->getOffset(),vn->getSize(),op->getAddr()); rampoint = glb->resolveConstant(spc,vn->getOffset(),vn->getSize(),op->getAddr(),fullEncoding);
} }
if (rampoint.isInvalid()) return (SymbolEntry *)0; if (rampoint.isInvalid()) return (SymbolEntry *)0;
@ -943,10 +943,11 @@ int4 ActionConstantPtr::apply(Funcdata &data)
else if ((opc == CPUI_PTRSUB)||(opc==CPUI_PTRADD)) else if ((opc == CPUI_PTRSUB)||(opc==CPUI_PTRADD))
continue; continue;
Address rampoint; Address rampoint;
entry = isPointer(rspc,vn,op,rampoint,data); uintb fullEncoding;
entry = isPointer(rspc,vn,op,rampoint,fullEncoding,data);
vn->setPtrCheck(); // Set check flag AFTER searching for symbol vn->setPtrCheck(); // Set check flag AFTER searching for symbol
if (entry != (SymbolEntry *)0) { if (entry != (SymbolEntry *)0) {
data.spacebaseConstant(op,slot,entry,rampoint,vn->getOffset(),vn->getSize()); data.spacebaseConstant(op,slot,entry,rampoint,fullEncoding,vn->getSize());
if ((opc == CPUI_INT_ADD)&&(slot==1)) if ((opc == CPUI_INT_ADD)&&(slot==1))
data.opSwapInput(op,0,1); data.opSwapInput(op,0,1);
count += 1; count += 1;

View file

@ -162,7 +162,7 @@ public:
/// \brief Check for constants, with pointer type, that correspond to global symbols /// \brief Check for constants, with pointer type, that correspond to global symbols
class ActionConstantPtr : public Action { class ActionConstantPtr : public Action {
int4 localcount; ///< Number of passes made for this function int4 localcount; ///< Number of passes made for this function
static SymbolEntry *isPointer(AddrSpace *spc,Varnode *vn,PcodeOp *op,Address &rampoint,Funcdata &data); static SymbolEntry *isPointer(AddrSpace *spc,Varnode *vn,PcodeOp *op,Address &rampoint,uintb &fullEncoding,Funcdata &data);
public: public:
ActionConstantPtr(const string &g) : Action(0,"constantptr",g) {} ///< Constructor ActionConstantPtr(const string &g) : Action(0,"constantptr",g) {} ///< Constructor
virtual void reset(Funcdata &data) { localcount = 0; } virtual void reset(Funcdata &data) { localcount = 0; }

View file

@ -333,7 +333,7 @@ void Funcdata::spacebaseConstant(PcodeOp *op,int4 slot,SymbolEntry *entry,const
outvn = outvn2; outvn = outvn2;
opInsertBefore(extraop,op); opInsertBefore(extraop,op);
} }
if (sz != origsize) { // There is a change in size from address -> varnode if (sz < origsize) { // The new constant is smaller than the original varnode, so we extend it
PcodeOp *zextop = newOp(1,op->getAddr()); PcodeOp *zextop = newOp(1,op->getAddr());
Varnode *outvn2 = newUniqueOut(origsize,zextop); Varnode *outvn2 = newUniqueOut(origsize,zextop);
opSetOpcode(zextop,CPUI_INT_ZEXT); // Create an extension to get back to original varnode size opSetOpcode(zextop,CPUI_INT_ZEXT); // Create an extension to get back to original varnode size
@ -341,6 +341,15 @@ void Funcdata::spacebaseConstant(PcodeOp *op,int4 slot,SymbolEntry *entry,const
opInsertBefore(zextop,op); opInsertBefore(zextop,op);
outvn = outvn2; outvn = outvn2;
} }
else if (origsize < sz) { // The new constant is bigger than the original varnode, truncate it
PcodeOp *subOp = newOp(2,op->getAddr());
Varnode *outvn3 = newUniqueOut(origsize,subOp);
opSetOpcode(subOp,CPUI_SUBPIECE);
opSetInput(subOp,outvn,0);
opSetInput(subOp,newConstant(4, 0), 1); // Take least significant piece
opInsertBefore(subOp,op);
outvn = outvn3;
}
opSetInput(op,outvn,slot); opSetInput(op,outvn,slot);
} }

View file

@ -1403,7 +1403,8 @@ bool PrintC::pushPtrCharConstant(uintb val,const TypePointer *ct,const Varnode *
{ {
if (val==0) return false; if (val==0) return false;
AddrSpace *spc = glb->getDefaultSpace(); AddrSpace *spc = glb->getDefaultSpace();
Address stringaddr = glb->resolveConstant(spc,val,ct->getSize(),op->getAddr()); uintb fullEncoding;
Address stringaddr = glb->resolveConstant(spc,val,ct->getSize(),op->getAddr(),fullEncoding);
if (stringaddr.isInvalid()) return false; if (stringaddr.isInvalid()) return false;
if (!glb->symboltab->getGlobalScope()->isReadOnly(stringaddr,1,Address())) if (!glb->symboltab->getGlobalScope()->isReadOnly(stringaddr,1,Address()))
return false; // Check that string location is readonly return false; // Check that string location is readonly

View file

@ -485,15 +485,27 @@ AddrSpace *AddrSpaceManager::getSpaceByShortcut(char sc) const
return (*iter).second; return (*iter).second;
} }
Address AddrSpaceManager::resolveConstant(AddrSpace *spc,uintb val,int4 sz,const Address &point) const /// \brief Resolve a native constant into an Address
///
/// If there is a special resolver for the AddrSpace, this is invoked, otherwise
/// basic wordsize conversion and wrapping is performed. If the address encoding is
/// partial (as in a \e near pointer) and the full encoding can be recovered, it is passed back.
/// \param spc is the space to generate the address from
/// \param val is the constant encoding of the address
/// \param sz is the size of the constant encoding
/// \param point is the context address (for recovering full encoding info if necessary)
/// \param fullEncoding is used to pass back the recovered full encoding of the pointer
/// \return the formal Address associated with the encoding
Address AddrSpaceManager::resolveConstant(AddrSpace *spc,uintb val,int4 sz,const Address &point,uintb &fullEncoding) const
{ {
int4 ind = spc->getIndex(); int4 ind = spc->getIndex();
if (ind < resolvelist.size()) { if (ind < resolvelist.size()) {
AddressResolver *resolve = resolvelist[ind]; AddressResolver *resolve = resolvelist[ind];
if (resolve != (AddressResolver *)0) if (resolve != (AddressResolver *)0)
return resolve->resolve(val,sz,point); return resolve->resolve(val,sz,point,fullEncoding);
} }
fullEncoding = val;
val = AddrSpace::addressToByte(val,spc->getWordSize()); val = AddrSpace::addressToByte(val,spc->getWordSize());
val = spc->wrapOffset(val); val = spc->wrapOffset(val);
return Address(spc,val); return Address(spc,val);

View file

@ -147,8 +147,9 @@ public:
/// \param val is constant to be resolved to an address /// \param val is constant to be resolved to an address
/// \param sz is the size of \e val in context. /// \param sz is the size of \e val in context.
/// \param point is the address at which this constant is being used /// \param point is the address at which this constant is being used
/// \param fullEncoding is used to hold the full pointer encoding if \b val is a partial encoding
/// \return the resolved Address /// \return the resolved Address
virtual Address resolve(uintb val,int4 sz,const Address &point)=0; virtual Address resolve(uintb val,int4 sz,const Address &point,uintb &fullEncoding)=0;
}; };
/// \brief A virtual space \e stack space /// \brief A virtual space \e stack space
@ -249,7 +250,7 @@ public:
AddrSpace *getConstantSpace(void) const; ///< Get the constant space AddrSpace *getConstantSpace(void) const; ///< Get the constant space
Address getConstant(uintb val) const; ///< Get a constant encoded as an Address Address getConstant(uintb val) const; ///< Get a constant encoded as an Address
Address createConstFromSpace(AddrSpace *spc) const; ///< Create a constant address encoding an address space Address createConstFromSpace(AddrSpace *spc) const; ///< Create a constant address encoding an address space
Address resolveConstant(AddrSpace *spc,uintb val,int4 sz,const Address &point) const; ///< Resolve native constant to address Address resolveConstant(AddrSpace *spc,uintb val,int4 sz,const Address &point,uintb &fullEncoding) const;
int4 numSpaces(void) const; ///< Get the number of address spaces for this processor int4 numSpaces(void) const; ///< Get the number of address spaces for this processor
AddrSpace *getSpace(int4 i) const; ///< Get an address space via its index AddrSpace *getSpace(int4 i) const; ///< Get an address space via its index
AddrSpace *getNextSpaceInOrder(AddrSpace *spc) const; ///< Get the next \e contiguous address space AddrSpace *getNextSpaceInOrder(AddrSpace *spc) const; ///< Get the next \e contiguous address space

View file

@ -1124,13 +1124,17 @@ Datatype *TypeSpacebase::getSubType(uintb off,uintb *newoff) const
{ {
Scope *scope = getMap(); Scope *scope = getMap();
// uintb unoff = (uintb)(intb)off; // Make sure this is a sign-extension off = AddrSpace::byteToAddress(off, spaceid->getWordSize()); // Convert from byte offset to address unit
Address addr(spaceid,spaceid->wrapOffset(off)); // It should always be the case that given offset represents a full encoding of the
// pointer, so the point of context is unused
Address nullPoint;
uintb fullEncoding;
Address addr = glb->resolveConstant(spaceid, off, spaceid->getAddrSize(), nullPoint, fullEncoding);
SymbolEntry *smallest; SymbolEntry *smallest;
// Assume symbol being referenced is address tied, // Assume symbol being referenced is address tied,
// so we use empty usepoint // so we use empty usepoint
smallest = scope->queryContainer(addr,1,Address()); smallest = scope->queryContainer(addr,1,nullPoint);
if (smallest == (SymbolEntry *)0) { if (smallest == (SymbolEntry *)0) {
*newoff = 0; *newoff = 0;
@ -1167,7 +1171,8 @@ int4 TypeSpacebase::compareDependency(const Datatype &op) const
Address TypeSpacebase::getAddress(uintb off,int4 sz,const Address &point) const Address TypeSpacebase::getAddress(uintb off,int4 sz,const Address &point) const
{ {
return glb->resolveConstant(spaceid,off,sz,point); uintb fullEncoding;
return glb->resolveConstant(spaceid,off,sz,point,fullEncoding);
} }
void TypeSpacebase::saveXml(ostream &s) const void TypeSpacebase::saveXml(ostream &s) const

View file

@ -1378,8 +1378,8 @@ public class SleighLanguage implements Language {
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "index", element.getUnique()); SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "index", element.getUnique());
int size = element.getSize(); // Size in bits int size = element.getSize(); // Size in bits
if (size == 20) { if (element instanceof SegmentedAddressSpace) {
// TODO: SegmentedAddressSpace shouldn't really return 20 // TODO: SegmentedAddressSpace shouldn't really return 21
size = 32; size = 32;
} }
if (size > 64) { if (size > 64) {