mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 02:39:44 +02:00
Adjust casting rules on implied varnodes
This commit is contained in:
parent
1508f3fee8
commit
75cf11634c
3 changed files with 44 additions and 7 deletions
|
@ -352,9 +352,13 @@ bool CastStrategyC::isSubpieceCastEndian(Datatype *outtype,Datatype *intype,uint
|
||||||
bool CastStrategyC::isSextCast(Datatype *outtype,Datatype *intype) const
|
bool CastStrategyC::isSextCast(Datatype *outtype,Datatype *intype) const
|
||||||
|
|
||||||
{
|
{
|
||||||
if (outtype->getMetatype()!=TYPE_INT) return false;
|
type_metatype metaout = outtype->getMetatype();
|
||||||
|
if (metaout != TYPE_UINT && metaout != TYPE_INT)
|
||||||
|
return false;
|
||||||
type_metatype metain = intype->getMetatype();
|
type_metatype metain = intype->getMetatype();
|
||||||
if ((metain!=TYPE_INT)&&(metain!=TYPE_UINT)&&(metain!=TYPE_BOOL))
|
// Casting to larger storage always extends based on signedness of the input data-type
|
||||||
|
// So the input must be SIGNED in order to treat SEXT as a cast
|
||||||
|
if ((metain!=TYPE_INT)&&(metain!=TYPE_BOOL))
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -362,9 +366,13 @@ bool CastStrategyC::isSextCast(Datatype *outtype,Datatype *intype) const
|
||||||
bool CastStrategyC::isZextCast(Datatype *outtype,Datatype *intype) const
|
bool CastStrategyC::isZextCast(Datatype *outtype,Datatype *intype) const
|
||||||
|
|
||||||
{
|
{
|
||||||
if (outtype->getMetatype()!=TYPE_UINT) return false;
|
type_metatype metaout = outtype->getMetatype();
|
||||||
|
if (metaout != TYPE_UINT && metaout != TYPE_INT)
|
||||||
|
return false;
|
||||||
type_metatype metain = intype->getMetatype();
|
type_metatype metain = intype->getMetatype();
|
||||||
if ((metain!=TYPE_INT)&&(metain!=TYPE_UINT)&&(metain!=TYPE_BOOL))
|
// Casting to larger storage always extends based on signedness of the input data-type
|
||||||
|
// So the input must be UNSIGNED in order to treat ZEXT as a cast
|
||||||
|
if ((metain!=TYPE_UINT)&&(metain!=TYPE_BOOL))
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2195,6 +2195,28 @@ bool ActionSetCasts::testStructOffset0(Varnode *vn,Datatype *ct,CastStrategy *ca
|
||||||
return (castStrategy->castStandard(reqtype, curtype, true, true) == (Datatype *)0);
|
return (castStrategy->castStandard(reqtype, curtype, true, true) == (Datatype *)0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief Test if two data-types are operation identical
|
||||||
|
///
|
||||||
|
/// If, at a source code level, a variable with data-type \b ct1 can be
|
||||||
|
/// legally substituted for another variable with data-type \b ct2, return \b true.
|
||||||
|
/// The substitution must be allowed for all possible operations the variable
|
||||||
|
/// may be involved in.
|
||||||
|
/// \param ct1 is the first data-type
|
||||||
|
/// \param ct2 is the second data-type
|
||||||
|
bool ActionSetCasts::isOpIdentical(Datatype *ct1,Datatype *ct2)
|
||||||
|
|
||||||
|
{
|
||||||
|
while((ct1->getMetatype()==TYPE_PTR)&&(ct2->getMetatype()==TYPE_PTR)) {
|
||||||
|
ct1 = ((const TypePointer *)ct1)->getPtrTo();
|
||||||
|
ct2 = ((const TypePointer *)ct2)->getPtrTo();
|
||||||
|
}
|
||||||
|
while(ct1->getTypedef() != (Datatype *)0)
|
||||||
|
ct1 = ct1->getTypedef();
|
||||||
|
while(ct2->getTypedef() != (Datatype *)0)
|
||||||
|
ct2 = ct2->getTypedef();
|
||||||
|
return (ct1 == ct2);
|
||||||
|
}
|
||||||
|
|
||||||
/// \brief Insert cast to output Varnode type after given PcodeOp if it is necessary
|
/// \brief Insert cast to output Varnode type after given PcodeOp if it is necessary
|
||||||
///
|
///
|
||||||
/// \param op is the given PcodeOp
|
/// \param op is the given PcodeOp
|
||||||
|
@ -2213,7 +2235,15 @@ int4 ActionSetCasts::castOutput(PcodeOp *op,Funcdata &data,CastStrategy *castStr
|
||||||
outvn = op->getOut();
|
outvn = op->getOut();
|
||||||
if (outvn->isImplied()) {
|
if (outvn->isImplied()) {
|
||||||
// implied varnode must have parse type
|
// implied varnode must have parse type
|
||||||
if (outvn->getType()->getMetatype() != TYPE_PTR) // If implied varnode has an atomic (non-pointer) type
|
if (outvn->isTypeLock()) {
|
||||||
|
PcodeOp *outOp = outvn->loneDescend();
|
||||||
|
// The Varnode input to a CPUI_RETURN is marked as implied but
|
||||||
|
// casting should act as if it were explicit
|
||||||
|
if (outOp == (PcodeOp *)0 || outOp->code() != CPUI_RETURN) {
|
||||||
|
force = !isOpIdentical(outvn->getType(), tokenct);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (outvn->getType()->getMetatype() != TYPE_PTR) // If implied varnode has an atomic (non-pointer) type
|
||||||
outvn->updateType(tokenct,false,false); // Ignore it in favor of the token type
|
outvn->updateType(tokenct,false,false); // Ignore it in favor of the token type
|
||||||
else if (tokenct->getMetatype() == TYPE_PTR) { // If the token is a pointer AND implied varnode is pointer
|
else if (tokenct->getMetatype() == TYPE_PTR) { // If the token is a pointer AND implied varnode is pointer
|
||||||
outct = ((TypePointer *)outvn->getType())->getPtrTo();
|
outct = ((TypePointer *)outvn->getType())->getPtrTo();
|
||||||
|
@ -2222,8 +2252,6 @@ int4 ActionSetCasts::castOutput(PcodeOp *op,Funcdata &data,CastStrategy *castStr
|
||||||
if ((meta!=TYPE_ARRAY)&&(meta!=TYPE_STRUCT))
|
if ((meta!=TYPE_ARRAY)&&(meta!=TYPE_STRUCT))
|
||||||
outvn->updateType(tokenct,false,false); // Otherwise ignore it in favor of the token type
|
outvn->updateType(tokenct,false,false); // Otherwise ignore it in favor of the token type
|
||||||
}
|
}
|
||||||
if (outvn->getType() != tokenct)
|
|
||||||
force=true; // Make sure not to drop pointer type
|
|
||||||
}
|
}
|
||||||
if (!force) {
|
if (!force) {
|
||||||
outct = outvn->getHigh()->getType(); // Type of result
|
outct = outvn->getHigh()->getType(); // Type of result
|
||||||
|
|
|
@ -311,6 +311,7 @@ public:
|
||||||
/// immediately.
|
/// immediately.
|
||||||
class ActionSetCasts : public Action {
|
class ActionSetCasts : public Action {
|
||||||
static bool testStructOffset0(Varnode *vn,Datatype *ct,CastStrategy *castStrategy);
|
static bool testStructOffset0(Varnode *vn,Datatype *ct,CastStrategy *castStrategy);
|
||||||
|
static bool isOpIdentical(Datatype *ct1,Datatype *ct2);
|
||||||
static int4 castOutput(PcodeOp *op,Funcdata &data,CastStrategy *castStrategy);
|
static int4 castOutput(PcodeOp *op,Funcdata &data,CastStrategy *castStrategy);
|
||||||
static int4 castInput(PcodeOp *op,int4 slot,Funcdata &data,CastStrategy *castStrategy);
|
static int4 castInput(PcodeOp *op,int4 slot,Funcdata &data,CastStrategy *castStrategy);
|
||||||
public:
|
public:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue