diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/architecture.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/architecture.cc index 36fa643f91..88373a5590 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/architecture.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/architecture.cc @@ -1135,7 +1135,7 @@ void Architecture::init(DocumentStorage &store) 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(); @@ -1145,6 +1145,7 @@ Address SegmentedResolver::resolve(uintb val,int4 sz,const Address &point) // (as with near pointers) if (segop->getResolve().space != (AddrSpace *)0) { uintb base = glb->context->getTrackedValue(segop->getResolve(),point); + fullEncoding = (base << 8 * innersz) + (val & calc_mask(innersz)); vector seginput; seginput.push_back(val); 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 + fullEncoding = val; int4 outersz = segop->getBaseSize(); uintb base = (val >> 8*innersz) & calc_mask(outersz); val = val & calc_mask(innersz); diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/architecture.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/architecture.hh index 83d2db8c2a..cb361c36bd 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/architecture.hh +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/architecture.hh @@ -284,7 +284,7 @@ public: /// \param sp is the segmented space /// \param sop is the segment operator 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 diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.cc index ea10394d27..082f5bf206 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.cc @@ -827,14 +827,14 @@ int4 ActionShadowVar::apply(Funcdata &data) /// \param rampoint will hold the Address of the resolved symbol /// \param data is the function being analyzed /// \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; Architecture *glb = data.getArch(); Varnode *outvn; 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; } 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 if (bit_transitions(vn->getOffset(),vn->getSize()) < 3) 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; @@ -943,10 +943,11 @@ int4 ActionConstantPtr::apply(Funcdata &data) else if ((opc == CPUI_PTRSUB)||(opc==CPUI_PTRADD)) continue; 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 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)) data.opSwapInput(op,0,1); count += 1; diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.hh index 5c86fc30e2..56e4dc2dd1 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.hh +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.hh @@ -162,7 +162,7 @@ public: /// \brief Check for constants, with pointer type, that correspond to global symbols class ActionConstantPtr : public Action { 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: ActionConstantPtr(const string &g) : Action(0,"constantptr",g) {} ///< Constructor virtual void reset(Funcdata &data) { localcount = 0; } diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata.cc index 234a581244..1d0064ccf6 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/funcdata.cc @@ -333,7 +333,7 @@ void Funcdata::spacebaseConstant(PcodeOp *op,int4 slot,SymbolEntry *entry,const outvn = outvn2; 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()); Varnode *outvn2 = newUniqueOut(origsize,zextop); 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); 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); } diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/printc.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/printc.cc index 3d6e4a6d9f..2b233c46f8 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/printc.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/printc.cc @@ -1403,7 +1403,8 @@ bool PrintC::pushPtrCharConstant(uintb val,const TypePointer *ct,const Varnode * { if (val==0) return false; 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 (!glb->symboltab->getGlobalScope()->isReadOnly(stringaddr,1,Address())) return false; // Check that string location is readonly diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/translate.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/translate.cc index 209b1b776a..98582c96c2 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/translate.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/translate.cc @@ -485,15 +485,27 @@ AddrSpace *AddrSpaceManager::getSpaceByShortcut(char sc) const 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(); if (ind < resolvelist.size()) { AddressResolver *resolve = resolvelist[ind]; 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 = spc->wrapOffset(val); return Address(spc,val); diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/translate.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/translate.hh index 6fc4b0db28..b0f4c48105 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/translate.hh +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/translate.hh @@ -147,8 +147,9 @@ public: /// \param val is constant to be resolved to an address /// \param sz is the size of \e val in context. /// \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 - 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 @@ -249,7 +250,7 @@ public: AddrSpace *getConstantSpace(void) const; ///< Get the constant space 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 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 AddrSpace *getSpace(int4 i) const; ///< Get an address space via its index AddrSpace *getNextSpaceInOrder(AddrSpace *spc) const; ///< Get the next \e contiguous address space diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/type.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/type.cc index d575d55153..4e511230a4 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/type.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/type.cc @@ -1124,13 +1124,17 @@ Datatype *TypeSpacebase::getSubType(uintb off,uintb *newoff) const { Scope *scope = getMap(); - // uintb unoff = (uintb)(intb)off; // Make sure this is a sign-extension - Address addr(spaceid,spaceid->wrapOffset(off)); + off = AddrSpace::byteToAddress(off, spaceid->getWordSize()); // Convert from byte offset to address unit + // 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; // Assume symbol being referenced is address tied, // so we use empty usepoint - smallest = scope->queryContainer(addr,1,Address()); + smallest = scope->queryContainer(addr,1,nullPoint); if (smallest == (SymbolEntry *)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 { - return glb->resolveConstant(spaceid,off,sz,point); + uintb fullEncoding; + return glb->resolveConstant(spaceid,off,sz,point,fullEncoding); } void TypeSpacebase::saveXml(ostream &s) const diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/SleighLanguage.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/SleighLanguage.java index 7bde62db52..14c63c749e 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/SleighLanguage.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/SleighLanguage.java @@ -1378,8 +1378,8 @@ public class SleighLanguage implements Language { SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "index", element.getUnique()); int size = element.getSize(); // Size in bits - if (size == 20) { - // TODO: SegmentedAddressSpace shouldn't really return 20 + if (element instanceof SegmentedAddressSpace) { + // TODO: SegmentedAddressSpace shouldn't really return 21 size = 32; } if (size > 64) {