mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 02:09:44 +02:00
Split out checkMultTerm
This commit is contained in:
parent
0a4d2d7ba1
commit
e6e88bf2be
2 changed files with 68 additions and 39 deletions
|
@ -5670,16 +5670,59 @@ AddTreeState::AddTreeState(PcodeOp *op,int4 slot)
|
||||||
isSubtype = false;
|
isSubtype = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Examine a CPUI_INT_MULT element in the middle of the add tree. Determine if we treat
|
||||||
|
/// the output simply as a leaf, or if the multiply needs to be distributed to an
|
||||||
|
/// additive subtree. If the Varnode is a leaf of the tree, return \b true if
|
||||||
|
/// it is considered a multiple of the base data-type size. If the Varnode is the
|
||||||
|
/// root of another additive sub-tree, return \b true if no sub-node is a multiple.
|
||||||
|
/// \param vn is the output Varnode of the operation
|
||||||
|
/// \param op is the CPUI_INT_MULT operation
|
||||||
|
/// \return \b true if there are no multiples of the base data-type size discovered
|
||||||
|
bool AddTreeState::checkMultTerm(Varnode *vn,PcodeOp *op)
|
||||||
|
|
||||||
|
{
|
||||||
|
Varnode *vnconst = op->getIn(1);
|
||||||
|
Varnode *vnterm = op->getIn(0);
|
||||||
|
uintb val,rem;
|
||||||
|
|
||||||
|
if (vnterm->isFree()) {
|
||||||
|
valid = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (vnconst->isConstant()) {
|
||||||
|
val = vnconst->getOffset();
|
||||||
|
if (size == 0)
|
||||||
|
rem = val;
|
||||||
|
else {
|
||||||
|
intb sval = (intb) val;
|
||||||
|
sign_extend(sval, vn->getSize() * 8 - 1);
|
||||||
|
rem = sval % size;
|
||||||
|
}
|
||||||
|
if (rem != 0) {
|
||||||
|
if ((val > size) && (size != 0)) {
|
||||||
|
valid = false; // Size is too big: pointer type must be wrong
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (rem == 0) {
|
||||||
|
multiple.push_back(vnterm);
|
||||||
|
coeff.push_back(val);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/// If the given Varnode is a constant or multiplicative term, update
|
/// If the given Varnode is a constant or multiplicative term, update
|
||||||
/// totals. If the Varnode is additive, traverse its sub-terms.
|
/// totals. If the Varnode is additive, traverse its sub-terms.
|
||||||
/// \param vn is the given Varnode term
|
/// \param vn is the given Varnode term
|
||||||
/// \return \b true if Varnode is a NON-multiple
|
/// \return \b true if the sub-tree rooted at the given Varnode contains no multiples
|
||||||
bool AddTreeState::checkTerm(Varnode *vn)
|
bool AddTreeState::checkTerm(Varnode *vn)
|
||||||
|
|
||||||
{
|
{
|
||||||
uintb val;
|
uintb val;
|
||||||
intb rem;
|
intb rem;
|
||||||
Varnode *vnconst,*vnterm;
|
|
||||||
PcodeOp *def;
|
PcodeOp *def;
|
||||||
|
|
||||||
if (vn == ptr) return false;
|
if (vn == ptr) return false;
|
||||||
|
@ -5707,42 +5750,26 @@ bool AddTreeState::checkTerm(Varnode *vn)
|
||||||
valid = false;
|
valid = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (def->code() == CPUI_INT_MULT) { // Check for constant coeff indicating size
|
if (def->code() == CPUI_INT_MULT) // Check for constant coeff indicating size
|
||||||
vnconst = def->getIn(1);
|
return checkMultTerm(vn, def);
|
||||||
vnterm = def->getIn(0);
|
}
|
||||||
if (vnconst->isConstant()) {
|
else if (vn->isFree()) {
|
||||||
val = vnconst->getOffset();
|
valid = false;
|
||||||
if (size == 0)
|
return false;
|
||||||
rem = val;
|
|
||||||
else {
|
|
||||||
intb sval = (intb) val;
|
|
||||||
sign_extend(sval, vn->getSize() * 8 - 1);
|
|
||||||
rem = sval % size;
|
|
||||||
}
|
|
||||||
if (rem!=0) {
|
|
||||||
if ((val > size)&&(size!=0)) {
|
|
||||||
valid = false; // Size is too big: pointer type must be wrong
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (rem==0) {
|
|
||||||
multiple.push_back(vnterm);
|
|
||||||
coeff.push_back(val);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Recursively walk the sub-tree from the given root. This routine returns
|
/// Recursively walk the sub-tree from the given root.
|
||||||
/// \b true if no leaf nodes of the tree have been identified in the sub-tree.
|
/// Terms that are a \e multiple of the base data-type size are accumulated either in
|
||||||
/// In this case, this root may itself be a leaf (we don't know yet), otherwise
|
/// the the sum of constant multiples or the container of non-constant multiples.
|
||||||
/// we know this root is \e not a leaf.
|
/// Terms that are a \e non-multiple are accumulated either in the sum of constant
|
||||||
|
/// non-multiples or the container of non-constant non-multiples. The constant
|
||||||
|
/// non-multiples are counted twice, once in the sum, and once in the container.
|
||||||
|
/// This routine returns \b true if no node of the sub-tree is considered a multiple
|
||||||
|
/// of the base data-type size (or \b false if any node is considered a multiple).
|
||||||
/// \param op is the root of the sub-expression to traverse
|
/// \param op is the root of the sub-expression to traverse
|
||||||
/// \return \b true if the given root might be a leaf
|
/// \return \b true if the given sub-tree contains no multiple nodes
|
||||||
bool AddTreeState::spanAddTree(PcodeOp *op)
|
bool AddTreeState::spanAddTree(PcodeOp *op)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -5754,12 +5781,11 @@ bool AddTreeState::spanAddTree(PcodeOp *op)
|
||||||
if (!valid) return false;
|
if (!valid) return false;
|
||||||
|
|
||||||
if (one_is_non&&two_is_non) return true;
|
if (one_is_non&&two_is_non) return true;
|
||||||
// Reaching here we know either, slot 0 or 1 is a leaf
|
|
||||||
if (one_is_non)
|
if (one_is_non)
|
||||||
nonmult.push_back(op->getIn(0));
|
nonmult.push_back(op->getIn(0));
|
||||||
if (two_is_non)
|
if (two_is_non)
|
||||||
nonmult.push_back(op->getIn(1));
|
nonmult.push_back(op->getIn(1));
|
||||||
return false; // We are definitely not a leaf
|
return false; // At least one of the sides contains multiples
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Make final calcultions to determine if a pointer to a sub data-type of the base
|
/// Make final calcultions to determine if a pointer to a sub data-type of the base
|
||||||
|
|
|
@ -31,12 +31,14 @@
|
||||||
///
|
///
|
||||||
/// Given a base pointer of known data-type and an additive expression involving
|
/// Given a base pointer of known data-type and an additive expression involving
|
||||||
/// the pointer, group the terms of the expression into:
|
/// the pointer, group the terms of the expression into:
|
||||||
/// - Constant multiple of the base data-type
|
/// - A constant multiple of the base data-type
|
||||||
/// - Non-constant multiples of the base data-type
|
/// - Non-constant multiples of the base data-type
|
||||||
/// - Multiples of an array element size: rewrite using PTRADD
|
/// - An constant offset to a sub-component of the base data-type
|
||||||
/// - Drill down into sub-components of the base data-type: rewrite using PTRSUB
|
/// - An remaining terms
|
||||||
/// - Remaining offsets
|
|
||||||
///
|
///
|
||||||
|
/// The \e multiple terms are rewritten using a CPUI_PTRADD. The constant offset
|
||||||
|
/// is rewritten using a CPUI_PTRSUB. Other terms are added back in. Analysis may cause
|
||||||
|
/// multiplication (CPUI_INT_MULT) by a constant to be distributed to its CPUI_INT_ADD input.
|
||||||
class AddTreeState {
|
class AddTreeState {
|
||||||
PcodeOp *baseOp; ///< Base of the ADD tree
|
PcodeOp *baseOp; ///< Base of the ADD tree
|
||||||
Varnode *ptr; ///< The pointer varnode
|
Varnode *ptr; ///< The pointer varnode
|
||||||
|
@ -52,6 +54,7 @@ class AddTreeState {
|
||||||
uintb multsum; ///< Sum of multiple constants
|
uintb multsum; ///< Sum of multiple constants
|
||||||
uintb nonmultsum; ///< Sum of non-multiple constants
|
uintb nonmultsum; ///< Sum of non-multiple constants
|
||||||
bool isSubtype; ///< Is there a sub-type (using CPUI_PTRSUB)
|
bool isSubtype; ///< Is there a sub-type (using CPUI_PTRSUB)
|
||||||
|
bool checkMultTerm(Varnode *vn,PcodeOp *op); ///< Accumulate details of INT_MULT term and continue traversal if appropriate
|
||||||
bool checkTerm(Varnode *vn); ///< Accumulate details of given term and continue tree traversal
|
bool checkTerm(Varnode *vn); ///< Accumulate details of given term and continue tree traversal
|
||||||
bool spanAddTree(PcodeOp *op); ///< Walk the given sub-tree
|
bool spanAddTree(PcodeOp *op); ///< Walk the given sub-tree
|
||||||
void calcSubtype(void); ///< Calculate final sub-type offset
|
void calcSubtype(void); ///< Calculate final sub-type offset
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue