mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 10:19:23 +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;
|
||||
}
|
||||
|
||||
/// 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
|
||||
/// totals. If the Varnode is additive, traverse its sub-terms.
|
||||
/// \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)
|
||||
|
||||
{
|
||||
uintb val;
|
||||
intb rem;
|
||||
Varnode *vnconst,*vnterm;
|
||||
PcodeOp *def;
|
||||
|
||||
if (vn == ptr) return false;
|
||||
|
@ -5707,42 +5750,26 @@ bool AddTreeState::checkTerm(Varnode *vn)
|
|||
valid = false;
|
||||
return false;
|
||||
}
|
||||
if (def->code() == CPUI_INT_MULT) { // Check for constant coeff indicating size
|
||||
vnconst = def->getIn(1);
|
||||
vnterm = def->getIn(0);
|
||||
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 (def->code() == CPUI_INT_MULT) // Check for constant coeff indicating size
|
||||
return checkMultTerm(vn, def);
|
||||
}
|
||||
if (rem!=0) {
|
||||
if ((val > size)&&(size!=0)) {
|
||||
valid = false; // Size is too big: pointer type must be wrong
|
||||
else if (vn->isFree()) {
|
||||
valid = false;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (rem==0) {
|
||||
multiple.push_back(vnterm);
|
||||
coeff.push_back(val);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Recursively walk the sub-tree from the given root. This routine returns
|
||||
/// \b true if no leaf nodes of the tree have been identified in the sub-tree.
|
||||
/// In this case, this root may itself be a leaf (we don't know yet), otherwise
|
||||
/// we know this root is \e not a leaf.
|
||||
/// Recursively walk the sub-tree from the given root.
|
||||
/// Terms that are a \e multiple of the base data-type size are accumulated either in
|
||||
/// the the sum of constant multiples or the container of non-constant multiples.
|
||||
/// 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
|
||||
/// \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)
|
||||
|
||||
{
|
||||
|
@ -5754,12 +5781,11 @@ bool AddTreeState::spanAddTree(PcodeOp *op)
|
|||
if (!valid) return false;
|
||||
|
||||
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)
|
||||
nonmult.push_back(op->getIn(0));
|
||||
if (two_is_non)
|
||||
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
|
||||
|
|
|
@ -31,12 +31,14 @@
|
|||
///
|
||||
/// Given a base pointer of known data-type and an additive expression involving
|
||||
/// 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
|
||||
/// - Multiples of an array element size: rewrite using PTRADD
|
||||
/// - Drill down into sub-components of the base data-type: rewrite using PTRSUB
|
||||
/// - Remaining offsets
|
||||
/// - An constant offset to a sub-component of the base data-type
|
||||
/// - An remaining terms
|
||||
///
|
||||
/// 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 {
|
||||
PcodeOp *baseOp; ///< Base of the ADD tree
|
||||
Varnode *ptr; ///< The pointer varnode
|
||||
|
@ -52,6 +54,7 @@ class AddTreeState {
|
|||
uintb multsum; ///< Sum of multiple constants
|
||||
uintb nonmultsum; ///< Sum of non-multiple constants
|
||||
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 spanAddTree(PcodeOp *op); ///< Walk the given sub-tree
|
||||
void calcSubtype(void); ///< Calculate final sub-type offset
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue