decompiler  1.0.0
Classes | Public Member Functions | Private Member Functions | Private Attributes | Static Private Attributes | List of all members
ghidra::ScoreUnionFields Class Reference

Analyze data-flow to resolve which field of a union data-type is being accessed. More...

#include <unionresolve.hh>

Classes

class  Trial
 A trial data-type fitted to a specific place in the data-flow. More...
 
class  VisitMark
 A mark accumulated when a given Varnode is visited with a specific field index. More...
 

Public Member Functions

 ScoreUnionFields (TypeFactory &tgrp, Datatype *parentType, PcodeOp *op, int4 slot)
 Score a given data-type involving a union against data-flow. More...
 
 ScoreUnionFields (TypeFactory &tgrp, TypeUnion *unionType, int4 offset, PcodeOp *op)
 Score a union data-type against data-flow, where there is a SUBPIECE. More...
 
 ScoreUnionFields (TypeFactory &tgrp, TypeUnion *unionType, int4 offset, PcodeOp *op, int4 slot)
 Score a union data-type against data-flow, where there is an implied truncation. More...
 
const ResolvedUniongetResult (void) const
 Get the resulting best field resolution.
 

Private Member Functions

bool testArrayArithmetic (PcodeOp *op, int4 inslot)
 Check if given PcodeOp is operating on array with union elements. More...
 
bool testSimpleCases (PcodeOp *op, int4 inslot, Datatype *parent)
 Preliminary checks before doing full scoring. More...
 
int4 scoreLockedType (Datatype *ct, Datatype *lockType)
 Score trial data-type against a locked data-type. More...
 
int4 scoreParameter (Datatype *ct, const PcodeOp *callOp, int4 paramSlot)
 Score trial data-type against a parameter. More...
 
int4 scoreReturnType (Datatype *ct, const PcodeOp *callOp)
 Score trial data-type against return data-type of function. More...
 
DatatypederefPointer (Datatype *ct, Varnode *vn, int4 &score)
 Score trial data-type as a pointer to LOAD/STORE. More...
 
void newTrialsDown (Varnode *vn, Datatype *ct, int4 scoreIndex, bool isArray)
 Create new trials based an reads of given Varnode. More...
 
void newTrials (PcodeOp *op, int4 slot, Datatype *ct, int4 scoreIndex, bool isArray)
 Create new trials based on given input slot. More...
 
void scoreTrialDown (const Trial &trial, bool lastLevel)
 Try to fit the given trial following data-flow down. More...
 
void scoreTrialUp (const Trial &trial, bool lastLevel)
 Try to fit the given trial following data-flow up.
 
DatatypescoreTruncation (Datatype *ct, Varnode *vn, int4 offset, int4 scoreIndex)
 Score a truncation in the data-flow. More...
 
void scoreConstantFit (const Trial &trial)
 Score trial data-type against a constant. More...
 
void runOneLevel (bool lastPass)
 Score all the current trials. More...
 
void computeBestIndex (void)
 Assuming scoring is complete, compute the best index.
 
void run (void)
 Calculate best fitting field. More...
 

Private Attributes

TypeFactorytypegrp
 The factory containing data-types.
 
vector< int4 > scores
 Score for each field, indexed by fieldNum + 1 (whole union is index=0)
 
vector< Datatype * > fields
 Field corresponding to each score.
 
set< VisitMarkvisited
 Places that have already been visited.
 
list< TrialtrialCurrent
 Current trials being pushed.
 
list< TrialtrialNext
 Next set of trials.
 
ResolvedUnion result
 The best result.
 
int4 trialCount
 Number of trials evaluated so far.
 

Static Private Attributes

static const int4 maxPasses = 6
 Maximum number of levels to score through.
 
static const int4 threshold = 256
 Threshold of trials over which to cancel additional passes.
 
static const int4 maxTrials = 1024
 Maximum number of trials to evaluate.
 

Detailed Description

Analyze data-flow to resolve which field of a union data-type is being accessed.

A Varnode with a data-type that is either a union, a pointer to union, or a part of a union, can be accessed in multiple ways. Each individual read (or write) of the Varnode may be accessing either a specific field of the union or accessing the union as a whole. The particular access may not be explicitly known but can sometimes be inferred from data-flow near the Varnode. This class scores all the possible fields of a data-type involving a union for a specific Varnode.

Because the answer may be different for different accesses, the Varnode must be specified as an access edge, a PcodeOp and a slot. A slot >= 0 indicates the index of a Varnode that is being read by the PcodeOp, a slot == -1 indicates the output Varnode being written by the PcodeOp.

The result of scoring is returned as a ResolvedUnion record.

Constructor & Destructor Documentation

◆ ScoreUnionFields() [1/3]

ghidra::ScoreUnionFields::ScoreUnionFields ( TypeFactory tgrp,
Datatype parentType,
PcodeOp op,
int4  slot 
)

Score a given data-type involving a union against data-flow.

The data-type must either be a union or a pointer to union. Set up the initial set of trials based on the given data-flow edge (PcodeOp and slot).

Parameters
tgrpis the TypeFactory owning the data-types
parentTypeis the given data-type to score
opis PcodeOp of the given data-flow edge
slotis slot of the given data-flow edge

References ghidra::ResolvedUnion::baseType, computeBestIndex(), fields, ghidra::Datatype::getDepend(), ghidra::PcodeOp::getIn(), ghidra::Datatype::getMetatype(), ghidra::PcodeOp::getOut(), ghidra::Varnode::getSize(), ghidra::Datatype::getSize(), ghidra::TypeFactory::getTypePointerStripArray(), ghidra::Datatype::numDepend(), result, run(), scores, testSimpleCases(), trialCurrent, ghidra::TYPE_ARRAY, ghidra::TYPE_PTR, typegrp, and visited.

◆ ScoreUnionFields() [2/3]

ghidra::ScoreUnionFields::ScoreUnionFields ( TypeFactory tgrp,
TypeUnion unionType,
int4  offset,
PcodeOp op 
)

Score a union data-type against data-flow, where there is a SUBPIECE.

A truncation is fit to each union field before doing the fit against data-flow. Only fields that match the offset and the truncation size (of the SUBPIECE) are scored further. If there is a good fit, the scoring for that field recurses into the given data-flow edge. This is only used where there is a SUBPIECE and the base scoring indicates the whole union is the best match for the input.

Parameters
tgrpis the TypeFactory owning the data-types
unionTypeis the data-type to score, which must be a TypeUnion
offsetis the given starting offset of the truncation
opis the SUBPIECE op

References computeBestIndex(), fields, ghidra::TypeUnion::getField(), ghidra::PcodeOp::getOut(), ghidra::Varnode::getSize(), ghidra::Datatype::getSize(), newTrialsDown(), ghidra::TypeUnion::numDepend(), ghidra::TypeField::offset, run(), scores, trialCurrent, trialNext, and ghidra::TypeField::type.

◆ ScoreUnionFields() [3/3]

ghidra::ScoreUnionFields::ScoreUnionFields ( TypeFactory tgrp,
TypeUnion unionType,
int4  offset,
PcodeOp op,
int4  slot 
)

Score a union data-type against data-flow, where there is an implied truncation.

A truncation is fit to each union field before doing the fit against data-flow, starting with the given PcodeOp and input slot.

Parameters
tgrpis the TypeFactory owning the data-types
unionTypeis the data-type to score, which must be a TypeUnion
offsetis the given starting offset of the truncation
opis the PcodeOp initially reading/writing the union
slotis the -1 if the op is writing, >= 0 if reading

References computeBestIndex(), fields, ghidra::TypeUnion::getField(), ghidra::PcodeOp::getIn(), ghidra::PcodeOp::getOut(), ghidra::TypeUnion::numDepend(), ghidra::TypeField::offset, run(), scores, scoreTruncation(), trialCurrent, ghidra::TypeField::type, and visited.

Member Function Documentation

◆ derefPointer()

Datatype * ghidra::ScoreUnionFields::derefPointer ( Datatype ct,
Varnode vn,
int4 &  score 
)
private

Score trial data-type as a pointer to LOAD/STORE.

Test if the data-type is a pointer and if the pointed-to data-type is compatible with the size of the value being loaded or stored. A score is passed back for how closely the data-type fits this scenario, and if it does we return the data-type of the pointer value.

Parameters
ctis the trial data-type
vnis the Varnode holding the value being loaded or stored
scoreis used to pass back the score
Returns
the data-type of the value or null

References ghidra::Datatype::getMetatype(), ghidra::Varnode::getSize(), ghidra::Datatype::getSize(), ghidra::Datatype::getSubType(), and ghidra::TYPE_PTR.

◆ newTrials()

void ghidra::ScoreUnionFields::newTrials ( PcodeOp op,
int4  slot,
Datatype ct,
int4  scoreIndex,
bool  isArray 
)
private

Create new trials based on given input slot.

If the input slot is a Varnode that has already been visited, no new trial is created

Parameters
opis the PcodeOp with the given slot
slotis the index of the given input slot
ctis the data-type to associate with the trial
scoreIndexis the field index to score the trial against
isArrayis true if the data-type to fit is a pointer to an array

References ghidra::Varnode::beginDescend(), ghidra::Varnode::endDescend(), ghidra::PcodeOp::getIn(), ghidra::PcodeOp::getSlot(), ghidra::Varnode::getType(), and ghidra::Varnode::isTypeLock().

◆ newTrialsDown()

void ghidra::ScoreUnionFields::newTrialsDown ( Varnode vn,
Datatype ct,
int4  scoreIndex,
bool  isArray 
)
private

Create new trials based an reads of given Varnode.

If the Varnode has already been visited, no new trials are created

Parameters
vnis the given Varnode
ctis the data-type to associate with the trial
scoreIndexis the field index to score the trial against
isArrayis true if the data-type to fit is a pointer to an array

References ghidra::Varnode::beginDescend(), ghidra::Varnode::endDescend(), ghidra::PcodeOp::getSlot(), ghidra::Varnode::getType(), and ghidra::Varnode::isTypeLock().

Referenced by ScoreUnionFields().

◆ run()

void ghidra::ScoreUnionFields::run ( void  )
private

Calculate best fitting field.

Try to fit each possible field over multiple levels of the data-flow. Return the index of the highest scoring field or -1 if the union data-type itself is the best fit.

Referenced by ScoreUnionFields().

◆ runOneLevel()

void ghidra::ScoreUnionFields::runOneLevel ( bool  lastPass)
private

Score all the current trials.

Run through each trial in the current list and compute a score. If the trial recurses and this is not the final pass, build new trials for the recursion.

Parameters
lastPassis true if this is the last pass

◆ scoreConstantFit()

void ghidra::ScoreUnionFields::scoreConstantFit ( const Trial trial)
private

Score trial data-type against a constant.

Assume the constant has no data-type of its own to match against. Evaluate if the constant looks like an integer or pointer etc. and score the trial data-type against that.

Parameters
trialis the trial of the constant Varnode

References ghidra::FloatFormat::extractExponentCode(), ghidra::ScoreUnionFields::Trial::fitType, ghidra::Datatype::getMetatype(), ghidra::Varnode::getOffset(), ghidra::AddrSpace::getPointerLowerBound(), ghidra::AddrSpace::getPointerUpperBound(), ghidra::Varnode::getSize(), ghidra::ScoreUnionFields::Trial::scoreIndex, ghidra::TYPE_BOOL, ghidra::TYPE_FLOAT, ghidra::TYPE_INT, ghidra::TYPE_PTR, ghidra::TYPE_UINT, and ghidra::ScoreUnionFields::Trial::vn.

◆ scoreLockedType()

int4 ghidra::ScoreUnionFields::scoreLockedType ( Datatype ct,
Datatype lockType 
)
private

Score trial data-type against a locked data-type.

A trial that encounters a locked data-type does not propagate through it but scores the trial data-type against the locked data-type.

Parameters
ctis the trial data-type
lockTypeis the locked data-type
Returns
the score

References ghidra::Datatype::getMetatype(), ghidra::Datatype::getSize(), ghidra::TYPE_ARRAY, ghidra::TYPE_CODE, ghidra::TYPE_INT, ghidra::TYPE_PTR, ghidra::TYPE_STRUCT, ghidra::TYPE_UINT, and ghidra::TYPE_UNION.

◆ scoreParameter()

int4 ghidra::ScoreUnionFields::scoreParameter ( Datatype ct,
const PcodeOp callOp,
int4  paramSlot 
)
private

Score trial data-type against a parameter.

Look up the call-specs for the given CALL. If the inputs are locked, find the corresponding parameter and score the trial data-type against it.

Parameters
ctis the trial data-type
callOpis the CALL
paramSlotis the input slot of the trial data-type
Returns
the score

References ghidra::Funcdata::getCallSpecs(), ghidra::BlockBasic::getFuncdata(), ghidra::Datatype::getMetatype(), ghidra::FuncProto::getParam(), ghidra::PcodeOp::getParent(), ghidra::ProtoParameter::getType(), ghidra::FuncProto::isInputLocked(), ghidra::FuncProto::numParams(), ghidra::TYPE_ARRAY, ghidra::TYPE_CODE, ghidra::TYPE_STRUCT, and ghidra::TYPE_UNION.

◆ scoreReturnType()

int4 ghidra::ScoreUnionFields::scoreReturnType ( Datatype ct,
const PcodeOp callOp 
)
private

Score trial data-type against return data-type of function.

Look up the call-specs for the given CALL. If the output is locked, score the trial data-type against it.

Parameters
ctis the trial data-type
callOpis the CALL
Returns
the score

References ghidra::Funcdata::getCallSpecs(), ghidra::BlockBasic::getFuncdata(), ghidra::Datatype::getMetatype(), ghidra::FuncProto::getOutputType(), ghidra::PcodeOp::getParent(), ghidra::FuncProto::isOutputLocked(), ghidra::TYPE_ARRAY, ghidra::TYPE_CODE, ghidra::TYPE_STRUCT, and ghidra::TYPE_UNION.

◆ scoreTrialDown()

void ghidra::ScoreUnionFields::scoreTrialDown ( const Trial trial,
bool  lastLevel 
)
private

Try to fit the given trial following data-flow down.

The trial's data-type is fitted to its PcodeOp as the incoming Varnode and a score is computed and added to the score for the trial's union field. The fitting may produce a new data-type which indicates scoring for the trial recurses into the output. This method builds trials for any new data-type unless lastLevel is true Varnode of its PcodeOp.

Parameters
trialis the given trial
lastLevelis true if the method should skip building new trials

References ghidra::ScoreUnionFields::Trial::array, ghidra::ResolvedUnion::baseType, ghidra::PcodeOp::code(), ghidra::TypeOpSubpiece::computeByteOffsetForComposite(), ghidra::CPUI_BOOL_AND, ghidra::CPUI_BOOL_NEGATE, ghidra::CPUI_BOOL_OR, ghidra::CPUI_BOOL_XOR, ghidra::CPUI_BRANCHIND, ghidra::CPUI_CALL, ghidra::CPUI_CALLIND, ghidra::CPUI_CALLOTHER, ghidra::CPUI_CBRANCH, ghidra::CPUI_COPY, ghidra::CPUI_FLOAT_ABS, ghidra::CPUI_FLOAT_ADD, ghidra::CPUI_FLOAT_CEIL, ghidra::CPUI_FLOAT_DIV, ghidra::CPUI_FLOAT_EQUAL, ghidra::CPUI_FLOAT_FLOAT2FLOAT, ghidra::CPUI_FLOAT_FLOOR, ghidra::CPUI_FLOAT_INT2FLOAT, ghidra::CPUI_FLOAT_LESS, ghidra::CPUI_FLOAT_LESSEQUAL, ghidra::CPUI_FLOAT_MULT, ghidra::CPUI_FLOAT_NAN, ghidra::CPUI_FLOAT_NEG, ghidra::CPUI_FLOAT_NOTEQUAL, ghidra::CPUI_FLOAT_ROUND, ghidra::CPUI_FLOAT_SQRT, ghidra::CPUI_FLOAT_SUB, ghidra::CPUI_FLOAT_TRUNC, ghidra::CPUI_INDIRECT, ghidra::CPUI_INT_2COMP, ghidra::CPUI_INT_ADD, ghidra::CPUI_INT_AND, ghidra::CPUI_INT_CARRY, ghidra::CPUI_INT_DIV, ghidra::CPUI_INT_EQUAL, ghidra::CPUI_INT_LEFT, ghidra::CPUI_INT_LESS, ghidra::CPUI_INT_LESSEQUAL, ghidra::CPUI_INT_MULT, ghidra::CPUI_INT_NEGATE, ghidra::CPUI_INT_NOTEQUAL, ghidra::CPUI_INT_OR, ghidra::CPUI_INT_REM, ghidra::CPUI_INT_RIGHT, ghidra::CPUI_INT_SBORROW, ghidra::CPUI_INT_SCARRY, ghidra::CPUI_INT_SDIV, ghidra::CPUI_INT_SEXT, ghidra::CPUI_INT_SLESS, ghidra::CPUI_INT_SLESSEQUAL, ghidra::CPUI_INT_SREM, ghidra::CPUI_INT_SRIGHT, ghidra::CPUI_INT_SUB, ghidra::CPUI_INT_XOR, ghidra::CPUI_INT_ZEXT, ghidra::CPUI_LOAD, ghidra::CPUI_LZCOUNT, ghidra::CPUI_MULTIEQUAL, ghidra::CPUI_PIECE, ghidra::CPUI_POPCOUNT, ghidra::CPUI_PTRADD, ghidra::CPUI_PTRSUB, ghidra::CPUI_RETURN, ghidra::CPUI_SEGMENTOP, ghidra::CPUI_STORE, ghidra::CPUI_SUBPIECE, ghidra::ScoreUnionFields::Trial::direction, ghidra::TypePointer::downChain(), ghidra::ScoreUnionFields::Trial::fitType, ghidra::Varnode::getDef(), ghidra::PcodeOp::getIn(), ghidra::Datatype::getMetatype(), ghidra::Varnode::getOffset(), ghidra::PcodeOp::getOut(), ghidra::TypePointer::getPtrTo(), ghidra::Datatype::getSize(), ghidra::ScoreUnionFields::Trial::inslot, ghidra::Varnode::isConstant(), ghidra::Varnode::isWritten(), ghidra::ScoreUnionFields::Trial::op, ghidra::ScoreUnionFields::Trial::scoreIndex, ghidra::TYPE_ARRAY, ghidra::TYPE_BOOL, ghidra::TYPE_CODE, ghidra::TYPE_FLOAT, ghidra::TYPE_INT, ghidra::TYPE_PTR, ghidra::TYPE_STRUCT, ghidra::TYPE_UINT, ghidra::TYPE_UNION, and ghidra::TYPE_UNKNOWN.

◆ scoreTruncation()

Datatype * ghidra::ScoreUnionFields::scoreTruncation ( Datatype ct,
Varnode vn,
int4  offset,
int4  scoreIndex 
)
private

Score a truncation in the data-flow.

The truncation may be an explicit CPUI_SUBPIECE, or it may be implied. A score is computed for fitting a given data-type to the truncation, and a possible data-type to recurse is also computed.

Parameters
ctis the given data-type to truncate
vnis the Varnode the truncation will fit into
offsetis the number of bytes truncated off the start of the data-type
scoreIndexis the field being scored
Returns
the data-type to recurse or null

References ghidra::TypeUnion::getField(), ghidra::Datatype::getMetatype(), ghidra::Varnode::getSize(), ghidra::Datatype::getSize(), ghidra::Datatype::getSubType(), ghidra::TypeUnion::numDepend(), ghidra::TypeField::offset, ghidra::TypeField::type, ghidra::TYPE_INT, ghidra::TYPE_UINT, and ghidra::TYPE_UNION.

Referenced by ScoreUnionFields().

◆ testArrayArithmetic()

bool ghidra::ScoreUnionFields::testArrayArithmetic ( PcodeOp op,
int4  inslot 
)
private

Check if given PcodeOp is operating on array with union elements.

If the op is adding a constant size or a multiple of a constant size to the given input slot, where the size is at least as large as the union, return true.

Parameters
opis the given PcodeOp
inslotis given input slot
Returns
true if op is doing array arithmetic with elements at least as large as the union

References ghidra::PcodeOp::code(), ghidra::CPUI_INT_ADD, ghidra::CPUI_INT_MULT, ghidra::CPUI_PTRADD, ghidra::Varnode::getDef(), ghidra::PcodeOp::getIn(), ghidra::Varnode::getOffset(), ghidra::Varnode::isConstant(), and ghidra::Varnode::isWritten().

◆ testSimpleCases()

bool ghidra::ScoreUnionFields::testSimpleCases ( PcodeOp op,
int4  inslot,
Datatype parent 
)
private

Preliminary checks before doing full scoring.

Identify cases where we know the union shouldn't be resolved to a field.

Parameters
opis the PcodeOp manipulating the union variable
inslotis -1 if the union is the output, >=0 if the union is an input to the op
parentis the parent union or pointer to union
Returns
true if the union should not be resolved to a field

References ghidra::PcodeOp::code(), ghidra::CPUI_COPY, ghidra::Datatype::getMetatype(), ghidra::PcodeOp::getOut(), ghidra::PcodeOp::isMarker(), ghidra::Varnode::isTypeLock(), and ghidra::TYPE_PTR.

Referenced by ScoreUnionFields().


The documentation for this class was generated from the following files: