mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-08-08 07:40:39 -09:00
Merge remote-tracking branch 'origin/GP-6936_caheckman_WrappedRange' into patch
This commit is contained in:
@@ -94,6 +94,7 @@ src/decompile/datatests/twodim.xml||GHIDRA||||END|
|
||||
src/decompile/datatests/union_datatype.xml||GHIDRA||||END|
|
||||
src/decompile/datatests/varcross.xml||GHIDRA||||END|
|
||||
src/decompile/datatests/wayoffarray.xml||GHIDRA||||END|
|
||||
src/decompile/datatests/wraprange.xml||GHIDRA||||END|
|
||||
src/decompile/zlib/README.txt||GHIDRA||||END|
|
||||
src/main/doc/commonprofile.xsl||GHIDRA||||END|
|
||||
src/main/doc/cspec.xml||GHIDRA||||END|
|
||||
|
||||
@@ -87,6 +87,7 @@ public:
|
||||
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 isValidRange(uint8 size) const; ///< Is the range properly contained in its address space
|
||||
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.
|
||||
int4 overlap(int4 skip,const Address &op,int4 size) const; ///< Determine how \b this address falls in a given address range
|
||||
@@ -465,6 +466,14 @@ inline Address Address::operator-(int8 off) const {
|
||||
return Address(base,base->wrapOffset(offset-off));
|
||||
}
|
||||
|
||||
/// If the range starting at \b this address and extending for \b size bytes, encompasses bytes beyond
|
||||
/// the edge of the address space (or wraps), then return \b false.
|
||||
/// \param size is the number of bytes in the range (must be non-zero)
|
||||
/// \return \b true if the range is properly contained in the address space
|
||||
inline bool Address::isValidRange(uint8 size) const {
|
||||
return (size-1) <= (base->getHighest() - offset);
|
||||
}
|
||||
|
||||
/// This method is equivalent to Address::overlap, but a range in the \e join space can be
|
||||
/// considered overlapped with its constituent pieces.
|
||||
/// If \e this + \e skip falls in the range, \e op to \e op + \e size, then a non-negative integer is
|
||||
|
||||
@@ -104,8 +104,15 @@ Varnode *Funcdata::newUnique(int4 s,Datatype *ct)
|
||||
Varnode *Funcdata::newVarnodeOut(int4 s,const Address &m,PcodeOp *op)
|
||||
|
||||
{
|
||||
Varnode *vn;
|
||||
Datatype *ct = glb->types->getBase(s,TYPE_UNKNOWN);
|
||||
Varnode *vn = vbank.createDef(s,m,ct,op);
|
||||
if (m.isValidRange(s)) {
|
||||
vn = vbank.createDef(s,m,ct,op);
|
||||
}
|
||||
else {
|
||||
Address addr = glb->constructWrappingAddress(m, s);
|
||||
vn = vbank.createDef(s,addr,ct,op);
|
||||
}
|
||||
op->setOutput(vn);
|
||||
assignHigh(vn);
|
||||
|
||||
@@ -152,8 +159,13 @@ Varnode *Funcdata::newVarnode(int4 s,const Address &m,Datatype *ct)
|
||||
|
||||
if (ct == (const Datatype *)0)
|
||||
ct = glb->types->getBase(s,TYPE_UNKNOWN);
|
||||
|
||||
vn = vbank.create(s,m,ct);
|
||||
if (m.isValidRange(s)) {
|
||||
vn = vbank.create(s,m,ct);
|
||||
}
|
||||
else {
|
||||
Address addr = glb->constructWrappingAddress(m, s);
|
||||
vn = vbank.create(s,addr,ct);
|
||||
}
|
||||
assignHigh(vn);
|
||||
|
||||
if (s >= minLanedSize)
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@@ -94,7 +94,8 @@ public:
|
||||
truncated = 0x100, ///< Space is truncated from its original size, expect pointers larger than this size
|
||||
hasphysical = 0x200, ///< Has physical memory associated with it
|
||||
is_otherspace = 0x400, ///< Quick check for the OtherSpace derived class
|
||||
has_nearpointers = 0x800 ///< Does there exist near pointers into this space
|
||||
has_nearpointers = 0x800, ///< Does there exist near pointers into this space
|
||||
allows_wrapped_range = 0x1000 ///< A memory range for \b this space can wrap from high addresses to low
|
||||
};
|
||||
private:
|
||||
spacetype type; ///< Type of space (PROCESSOR, CONSTANT, INTERNAL, ...)
|
||||
@@ -150,6 +151,7 @@ public:
|
||||
bool isOtherSpace(void) const; ///< Return \b true if \b this is the \e other address space
|
||||
bool isTruncated(void) const; ///< Return \b true if this space is truncated from its original size
|
||||
bool hasNearPointers(void) const; ///< Return \b true if \e near (truncated) pointers into \b this space are possible
|
||||
bool allowsWrappedRange(void) const; ///< Return \b true if memory range can span high to low addresses in \b this space
|
||||
void printOffset(ostream &s,uintb offset) const; ///< Write an address offset to a stream
|
||||
|
||||
virtual int4 numSpacebase(void) const; ///< Number of base registers associated with this space
|
||||
@@ -467,6 +469,10 @@ inline bool AddrSpace::hasNearPointers(void) const {
|
||||
return ((flags&has_nearpointers)!=0);
|
||||
}
|
||||
|
||||
inline bool AddrSpace::allowsWrappedRange(void) const {
|
||||
return ((flags & allows_wrapped_range)!=0);
|
||||
}
|
||||
|
||||
/// Some spaces are "virtual", like the stack spaces, where addresses are really relative to a
|
||||
/// base pointer stored in a register, like the stackpointer. This routine will return non-zero
|
||||
/// if \b this space is virtual and there is 1 (or more) associated pointer registers
|
||||
|
||||
@@ -61,6 +61,7 @@ SpacebaseSpace::SpacebaseSpace(AddrSpaceManager *m,const Translate *t,const stri
|
||||
contain = base;
|
||||
hasbaseregister = false; // No base register assigned yet
|
||||
isNegativeStack = true; // default stack growth
|
||||
setFlags(allows_wrapped_range);
|
||||
if (isFormal)
|
||||
setFlags(formal_stackspace);
|
||||
}
|
||||
@@ -73,9 +74,10 @@ SpacebaseSpace::SpacebaseSpace(AddrSpaceManager *m,const Translate *t,const stri
|
||||
SpacebaseSpace::SpacebaseSpace(AddrSpaceManager *m,const Translate *t)
|
||||
: AddrSpace(m,t,IPTR_SPACEBASE)
|
||||
{
|
||||
contain = (AddrSpace *)0;
|
||||
hasbaseregister = false;
|
||||
isNegativeStack = true;
|
||||
setFlags(programspecific);
|
||||
setFlags(programspecific | allows_wrapped_range);
|
||||
}
|
||||
|
||||
/// This routine sets the base register associated with this \b virtual space
|
||||
@@ -847,6 +849,38 @@ Address AddrSpaceManager::constructJoinAddress(const Translate *translate,
|
||||
return join->getUnified().getAddr();
|
||||
}
|
||||
|
||||
/// Check if the address space allows wrapped ranges. If so, construct a \e joined address
|
||||
/// out of the high address piece of the range and the low address piece.
|
||||
/// \param addr is the initial address in the range
|
||||
/// \param size is the number of bytes in the range
|
||||
/// \return the address representing the wrapped range
|
||||
Address AddrSpaceManager::constructWrappingAddress(const Address &addr,int4 size)
|
||||
|
||||
{
|
||||
AddrSpace *spc = addr.getSpace();
|
||||
if (!spc->isHeritaged())
|
||||
return addr; // Size is ignored
|
||||
uintb dist = spc->getHighest() - addr.getOffset() + 1;
|
||||
if (size <= dist)
|
||||
return addr;
|
||||
if (!spc->allowsWrappedRange())
|
||||
throw LowlevelError("Trying to construct memory range beyond end of address space: "+spc->getName());
|
||||
int4 sizehi = (int4)dist;
|
||||
int4 sizelo = size - sizehi;
|
||||
vector<VarnodeData> pieces;
|
||||
pieces.emplace_back();
|
||||
pieces.emplace_back();
|
||||
int4 highIndex = spc->isBigEndian() ? 0 : 1;
|
||||
pieces[highIndex].space = spc;
|
||||
pieces[highIndex].offset = addr.getOffset();
|
||||
pieces[highIndex].size = sizehi;
|
||||
pieces[1-highIndex].space = spc;
|
||||
pieces[1-highIndex].offset = 0;
|
||||
pieces[1-highIndex].size = sizelo;
|
||||
JoinRecord *join = findAddJoin(pieces,0);
|
||||
return join->getUnified().getAddr();
|
||||
}
|
||||
|
||||
/// If an Address in the \e join AddressSpace is shifted from its original offset, it may no
|
||||
/// longer have a valid JoinRecord. The shift or size change may even make the address of
|
||||
/// one of the pieces a more natural representation. Given a new Address and size, this method
|
||||
|
||||
@@ -278,6 +278,9 @@ public:
|
||||
/// \brief Build a logical whole from register pairs
|
||||
Address constructJoinAddress(const Translate *translate,const Address &hiaddr,int4 hisz,const Address &loaddr,int4 losz);
|
||||
|
||||
/// \brief Build a logical whole representing a range that \e wraps from a high address to a low address
|
||||
Address constructWrappingAddress(const Address &addr,int4 size);
|
||||
|
||||
/// \brief Make sure a possibly offset \e join address has a proper JoinRecord
|
||||
void renormalizeJoinAddress(Address &addr,int4 size);
|
||||
|
||||
|
||||
@@ -120,6 +120,26 @@ void print_data(ostream &s,uint1 *buffer,int4 size,const Address &baseaddr)
|
||||
}
|
||||
}
|
||||
|
||||
/// Construct a data-type providing just the size, alignment, and meta-type.
|
||||
/// Sets up the default configuration, which may be overridden by the derived constructor.
|
||||
/// \param s is the size in bytes
|
||||
/// \param align is the byte alignment required for \b this
|
||||
/// \param m is the meta-type
|
||||
Datatype::Datatype(int4 s,int4 align,type_metatype m)
|
||||
|
||||
{
|
||||
if (s < 0)
|
||||
throw LowlevelError("Bad data-type size");
|
||||
size = s;
|
||||
metatype = m;
|
||||
submeta = base2sub[m];
|
||||
flags = 0;
|
||||
id = 0;
|
||||
typedefImm = (Datatype *)0;
|
||||
alignment = align;
|
||||
alignSize = s;
|
||||
}
|
||||
|
||||
/// If \b this and the other given data-type are both variable length and come from the
|
||||
/// the same base data-type, return \b true.
|
||||
/// \param ct is the other given data-type to compare with \b this
|
||||
@@ -4052,7 +4072,7 @@ Datatype *TypeFactory::getBase(int4 s,type_metatype m)
|
||||
|
||||
{
|
||||
Datatype *ct;
|
||||
if (s<9) {
|
||||
if ((uint4)s<9) {
|
||||
if (m >= TYPE_FLOAT) {
|
||||
ct = typecache[s][m-TYPE_FLOAT];
|
||||
if (ct != (Datatype *)0)
|
||||
@@ -4061,13 +4081,9 @@ Datatype *TypeFactory::getBase(int4 s,type_metatype m)
|
||||
}
|
||||
else if (m==TYPE_FLOAT) {
|
||||
if (s==10)
|
||||
ct = typecache10;
|
||||
else if (s==16)
|
||||
ct = typecache16;
|
||||
else
|
||||
ct = (Datatype *)0;
|
||||
if (ct != (Datatype *)0)
|
||||
return ct;
|
||||
return typecache10;
|
||||
if (s==16)
|
||||
return typecache16;
|
||||
}
|
||||
if (s > glb->max_basetype_size) {
|
||||
// Create array of unknown bytes to match size
|
||||
@@ -4098,7 +4114,7 @@ Datatype *TypeFactory::getBase(int4 s,type_metatype m,const string &n)
|
||||
Datatype *TypeFactory::getTypeChar(int4 s)
|
||||
|
||||
{
|
||||
if (s < 5) {
|
||||
if ((uint4)s < 5) {
|
||||
Datatype *res = charcache[s];
|
||||
if (res != (Datatype *)0)
|
||||
return res;
|
||||
|
||||
@@ -210,12 +210,10 @@ protected:
|
||||
protected:
|
||||
static int4 calcAlignSize(int4 sz,int4 align); ///< Calculate aligned size, given size and alignment of data-type
|
||||
public:
|
||||
/// Construct the base data-type copying low-level properties of another
|
||||
/// \brief Construct the base data-type copying low-level properties of another
|
||||
Datatype(const Datatype &op) { size = op.size; name=op.name; displayName=op.displayName; metatype=op.metatype;
|
||||
submeta=op.submeta; flags=op.flags; id=op.id; typedefImm=op.typedefImm; alignment=op.alignment; alignSize=op.alignSize; }
|
||||
/// Construct the base data-type providing size and meta-type
|
||||
Datatype(int4 s,int4 align,type_metatype m) {
|
||||
size=s; metatype=m; submeta=base2sub[m]; flags=0; id=0; typedefImm=(Datatype *)0; alignment=align; alignSize=s; }
|
||||
Datatype(int4 s,int4 align,type_metatype m); ///< Constructor
|
||||
virtual ~Datatype(void) {} ///< Destructor
|
||||
bool isCoreType(void) const { return ((flags&coretype)!=0); } ///< Is this a core data-type
|
||||
bool isCharPrint(void) const { return ((flags&(chartype|utf16|utf32|opaque_string))!=0); } ///< Does this print as a 'char'
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
<decompilertest>
|
||||
<!--
|
||||
Example of accessing a stack range from high addresses to low addresses
|
||||
-->
|
||||
<binaryimage arch="x86:LE:64:default:gcc">
|
||||
<bytechunk space="ram" offset="0x172390" readonly="true">
|
||||
4883ec04488b04244883c404c3
|
||||
</bytechunk>
|
||||
<symbol space="ram" offset="0x172390" name="wraprange"/>
|
||||
</binaryimage>
|
||||
<script>
|
||||
<com>load function wraprange</com>
|
||||
<com>decompile</com>
|
||||
<com>print raw</com>
|
||||
<com>quit</com>
|
||||
</script>
|
||||
<stringmatch name="Wrapped range #1" min="1" max="1">j\{0x00000000,0xfffffffffffffffc\}.* = CONCAT44\(s0x00000000:4\(i\),s0xfffffffffffffffc:4\(i\)\)</stringmatch>
|
||||
<stringmatch name="Wrapped range #2" min="1" max="1">RAX\(.*\) = j\{0x00000000,0xfffffffffffffffc\}</stringmatch>
|
||||
</decompilertest>
|
||||
Reference in New Issue
Block a user