TypePointerRel adjustments

This commit is contained in:
caheckman 2021-11-24 15:22:17 -05:00
parent 6cc2eae322
commit 64534bc774
7 changed files with 98 additions and 12 deletions

View file

@ -32,6 +32,7 @@ src/decompile/datatests/noforloop_iterused.xml||GHIDRA||||END|
src/decompile/datatests/offsetarray.xml||GHIDRA||||END|
src/decompile/datatests/pointercmp.xml||GHIDRA||||END|
src/decompile/datatests/pointerrel.xml||GHIDRA||||END|
src/decompile/datatests/pointersub.xml||GHIDRA||||END|
src/decompile/datatests/promotecompare.xml||GHIDRA||||END|
src/decompile/datatests/readvolatile.xml||GHIDRA||||END|
src/decompile/datatests/sbyte.xml||GHIDRA||||END|

View file

@ -2923,7 +2923,7 @@ void IfcPointerSetting::execute(istream &s)
Datatype *bt = dcp->conf->types->findByName(baseType);
if (bt == (Datatype *)0 || bt->getMetatype() != TYPE_STRUCT)
throw IfaceParseError("Base-type must be a structure");
Datatype *ptrto = TypePointerRel::getPtrTo(bt, off, *dcp->conf->types);
Datatype *ptrto = TypePointerRel::getPtrToFromParent(bt, off, *dcp->conf->types);
AddrSpace *spc = dcp->conf->getDefaultDataSpace();
dcp->conf->types->getTypePointerRel(spc->getAddrSize(), bt, ptrto, spc->getWordSize(), off,typeName);
}

View file

@ -785,16 +785,18 @@ void PrintC::opPtrsub(const PcodeOp *op)
TypePointerRel *ptrel;
Datatype *ct;
const Varnode *in0;
uintb in1const;
bool valueon,flex,arrayvalue;
uint4 m;
in0 = op->getIn(0);
in1const = op->getIn(1)->getOffset();
ptype = (TypePointer *)in0->getHigh()->getType();
if (ptype->getMetatype() != TYPE_PTR) {
clear();
throw LowlevelError("PTRSUB off of non-pointer type");
}
if (ptype->isFormalPointerRel()) {
if (ptype->isFormalPointerRel() && ((TypePointerRel *)ptype)->evaluateThruParent(in1const)) {
ptrel = (TypePointerRel *)ptype;
ct = ptrel->getParent();
}
@ -807,10 +809,19 @@ void PrintC::opPtrsub(const PcodeOp *op)
flex = isValueFlexible(in0);
if (ct->getMetatype() == TYPE_STRUCT) {
uintb suboff = op->getIn(1)->getOffset(); // How far into container
uintb suboff = in1const; // How far into container
if (ptrel != (TypePointerRel *)0) {
suboff += ptrel->getPointerOffset();
suboff &= calc_mask(ptype->getSize());
if (suboff == 0) {
// Special case where we do not print a field
pushTypePointerRel(op);
if (flex)
pushVnImplied(in0,op,m | print_load_value);
else
pushVnImplied(in0,op,m);
return;
}
}
suboff = AddrSpace::addressToByte(suboff,ptype->getWordSize());
string fieldname;
@ -904,7 +915,7 @@ void PrintC::opPtrsub(const PcodeOp *op)
}
if (symbol == (Symbol *)0) {
TypeSpacebase *sb = (TypeSpacebase *)ct;
Address addr = sb->getAddress(op->getIn(1)->getOffset(),in0->getSize(),op->getAddr());
Address addr = sb->getAddress(in1const,in0->getSize(),op->getAddr());
pushUnnamedLocation(addr,(Varnode *)0,op);
}
else {
@ -923,7 +934,7 @@ void PrintC::opPtrsub(const PcodeOp *op)
push_integer(0,4,false,(Varnode *)0,op);
}
else if (ct->getMetatype() == TYPE_ARRAY) {
if (op->getIn(1)->getOffset() != 0) {
if (in1const != 0) {
clear();
throw LowlevelError("PTRSUB with non-zero offset into array type");
}

View file

@ -5977,6 +5977,13 @@ void AddTreeState::calcSubtype(void)
}
extra = AddrSpace::byteToAddress(extra, ct->getWordSize()); // Convert back to address units
offset = (nonmultsum - extra) & ptrmask;
if (pRelType != (TypePointerRel *)0 && offset == pRelType->getPointerOffset()) {
// offset falls within basic ptrto
if (!pRelType->evaluateThruParent(0)) { // If we are not representing offset 0 through parent
valid = false; // Use basic (alternate) form
return;
}
}
isSubtype = true;
}
else if (baseType->getMetatype() == TYPE_ARRAY) {
@ -6331,7 +6338,7 @@ int4 RuleStructOffset0::applyOp(PcodeOp *op,Funcdata &data)
if (ct->getMetatype() != TYPE_PTR) return 0;
Datatype *baseType = ((TypePointer *)ct)->getPtrTo();
uintb offset = 0;
if (ct->isFormalPointerRel()) {
if (ct->isFormalPointerRel() && ((TypePointerRel *)ct)->evaluateThruParent(0)) {
TypePointerRel *ptRel = (TypePointerRel *)ct;
baseType = ptRel->getParent();
if (baseType->getMetatype() != TYPE_STRUCT)

View file

@ -1245,8 +1245,9 @@ void TypeStruct::restoreFields(const Element *el,TypeFactory &typegrp)
void TypePointerRel::restoreXml(const Element *el,TypeFactory &typegrp)
{
flags = is_ptrrel;
flags |= is_ptrrel;
restoreXmlBasic(el);
metatype = TYPE_PTR; // Don't use TYPE_PTRREL internally
for(int4 i=0;i<el->getNumAttributes();++i)
if (el->getAttributeName(i) == "wordsize") {
istringstream s(el->getAttributeValue(i));
@ -1256,6 +1257,8 @@ void TypePointerRel::restoreXml(const Element *el,TypeFactory &typegrp)
const List &list(el->getChildren());
List::const_iterator iter;
iter = list.begin();
ptrto = typegrp.restoreXmlType( *iter );
++iter;
parent = typegrp.restoreXmlType( *iter );
++iter;
istringstream s1((*iter)->getContent());
@ -1263,12 +1266,25 @@ void TypePointerRel::restoreXml(const Element *el,TypeFactory &typegrp)
s1 >> offset;
if (offset == 0)
throw new LowlevelError("For metatype=\"ptrstruct\", <off> tag must not be zero");
ptrto = getPtrTo(parent, offset, typegrp);
submeta = (ptrto->getMetatype()==TYPE_UNKNOWN) ? SUB_PTRREL_UNK: SUB_PTRREL;
if (name.size() == 0) // If the data-type is not named
cacheStrippedType(typegrp); // it is considered ephemeral
}
/// For a variable that is a relative pointer, constant offsets off of the variable can be
/// displayed either as coming from the variable itself or from the parent object.
/// \param byteOff is the given offset off of the variable
/// \return \b true if the variable should be displayed as coming from the parent
bool TypePointerRel::evaluateThruParent(uintb addrOff) const
{
uintb byteOff = AddrSpace::addressToByte(addrOff, wordsize);
if (ptrto->getMetatype() == TYPE_STRUCT && byteOff < ptrto->getSize())
return false;
byteOff = (byteOff + offset) & calc_mask(size);
return (byteOff < parent->getSize());
}
void TypePointerRel::printRaw(ostream &s) const
{
@ -1301,15 +1317,18 @@ void TypePointerRel::saveXml(ostream &s) const
if (wordsize != 1)
a_v_i(s,"wordsize",wordsize);
s << ">\n";
ptrto->saveXml(s);
s << '\n';
parent->saveXmlRef(s);
s << "<off>" << dec << offset << "</off>\n";
s << "\n<off>" << dec << offset << "</off>\n";
s << "</type>";
}
TypePointer *TypePointerRel::downChain(uintb &off,TypePointer *&par,uintb &parOff,bool allowArrayWrap,
TypeFactory &typegrp)
{
if (off < ptrto->getSize() && stripped != (TypePointer *)0) {
type_metatype ptrtoMeta = ptrto->getMetatype();
if (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
@ -1318,6 +1337,8 @@ TypePointer *TypePointerRel::downChain(uintb &off,TypePointer *&par,uintb &parOf
TypePointer *origPointer = typegrp.getTypePointer(size, parent, wordsize);
off = relOff;
if (relOff == 0 && offset != 0) // Recovering the start of the parent is still downchaining, even though the parent may be the container
return origPointer; // So we return the pointer to the parent and don't drill down to field at offset 0
return origPointer->downChain(off,par,parOff,allowArrayWrap,typegrp);
}
@ -1339,7 +1360,7 @@ bool TypePointerRel::isPtrsubMatching(uintb off) const
/// \param off is the offset relative to the start of the container
/// \param typegrp is the factory owning the data-types
/// \return the "pointed to" data-type
Datatype *TypePointerRel::getPtrTo(Datatype *base,int4 off,TypeFactory &typegrp)
Datatype *TypePointerRel::getPtrToFromParent(Datatype *base,int4 off,TypeFactory &typegrp)
{
if (off > 0) {
@ -2844,6 +2865,15 @@ Datatype *TypeFactory::restoreXmlTypeNoRef(const Element *el,bool forcecore)
ct = findAdd(tp);
}
break;
case TYPE_PTRREL:
{
TypePointerRel tp;
tp.restoreXml(el, *this);
if (forcecore)
tp.flags |= Datatype::coretype;
ct = findAdd(tp);
}
break;
case TYPE_ARRAY:
{
TypeArray ta;

View file

@ -401,6 +401,7 @@ public:
parent = par; offset = off; stripped = (TypePointer *)0; flags |= is_ptrrel;
submeta = pt->getMetatype()==TYPE_UNKNOWN ? SUB_PTRREL_UNK : SUB_PTRREL; }
Datatype *getParent(void) const { return parent; } ///< Get the parent data-type to which \b this pointer is offset
bool evaluateThruParent(uintb addrOff) const; ///< Do we display given address offset as coming from the parent data-type
/// \brief Get offset of \b this pointer relative to start of the containing data-type
///
@ -413,7 +414,7 @@ public:
virtual TypePointer *downChain(uintb &off,TypePointer *&par,uintb &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 *getPtrTo(Datatype *base,int4 off,TypeFactory &typegrp);
static Datatype *getPtrToFromParent(Datatype *base,int4 off,TypeFactory &typegrp);
};
class FuncProto; // Forward declaration

View file

@ -0,0 +1,36 @@
<decompilertest>
<binaryimage arch="x86:LE:64:default:gcc">
<!--
Test that relative pointers can access
1) a pointer to the parent structure
2) a field of the parent using the ADJ macro
3) a field in an inner structure, without going thru parent
-->
<bytechunk space="ram" offset="0x1005fa" readonly="true">
554889e54889
7de8488b45e84883e810488945f8488b
45e8f20f1005ce000000f20f11400848
8b45f848c740080a000000488b45f85d
c3
</bytechunk>
<bytechunk space="ram" offset="0x1006e8" readonly="true">
0000000000002340
</bytechunk>
<symbol name="getOuter" space="ram" offset="0x1005fa"/>
</binaryimage>
<script>
<com>option readonly on</com>
<com>parse line struct InnerStruct { int8 a; float8 b; char c; };</com>
<com>parse line struct OuterStruct { int8 outA; int8 outB; InnerStruct inner; };</com>
<com>pointer setting outer_rel OuterStruct offset 16</com>
<com>parse line extern OuterStruct *getOuter(outer_rel ptr);</com>
<com>lo fu getOuter</com>
<com>dec</com>
<com>print C</com>
<com>quit</com>
</script>
<stringmatch name="Relative base #1" min="1" max="1">ptr-&gt;b = 9\.5;</stringmatch>
<stringmatch name="Relative base #2" min="1" max="1">ADJ\(ptr\)-&gt;outB = 10;</stringmatch>
<stringmatch name="Relative base #3" min="1" max="1">return ADJ\(ptr\);</stringmatch>
<stringmatch name="Relative base #4" min="1" max="1">OuterStruct \* getOuter\(outer_rel ptr\)</stringmatch>
</decompilertest>