mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 02:09:44 +02:00
adjustments to resolveConstant
This commit is contained in:
parent
612c0d6f3e
commit
4edff2b9f0
10 changed files with 51 additions and 20 deletions
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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; }
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue