Ghidra 11.3.2
Ghidra internal decompiler documentation.
Loading...
Searching...
No Matches
ghidra::SubfloatFlow Class Reference

Class for tracing changes of precision in floating point variables. More...

#include <subflow.hh>

Inheritance diagram for ghidra::SubfloatFlow:
[legend]
Collaboration diagram for ghidra::SubfloatFlow:
[legend]

Classes

class  State
 Internal state for walking floating-point data-flow and computing precision. More...
 

Public Member Functions

 SubfloatFlow (Funcdata *f, Varnode *root, int4 prec)
 
virtual bool preserveAddress (Varnode *vn, int4 bitSize, int4 lsbOffset) const
 Should the address of the given Varnode be preserved when constructing a piece.
 
bool doTrace (void)
 Trace logical value as far as possible.
 
- Public Member Functions inherited from ghidra::TransformManager
 TransformManager (Funcdata *f)
 Constructor.
 
virtual ~TransformManager (void)
 Destructor.
 
FuncdatagetFunction (void) const
 Get function being transformed.
 
void clearVarnodeMarks (void)
 Clear mark for all Varnodes in the map.
 
TransformVarnewPreexistingVarnode (Varnode *vn)
 Make placeholder for preexisting Varnode.
 
TransformVarnewUnique (int4 size)
 Make placeholder for new unique space Varnode.
 
TransformVarnewConstant (int4 size, int4 lsbOffset, uintb val)
 Make placeholder for constant Varnode.
 
TransformVarnewIop (Varnode *vn)
 Make placeholder for special iop constant.
 
TransformVarnewPiece (Varnode *vn, int4 bitSize, int4 lsbOffset)
 Make placeholder for piece of a Varnode.
 
TransformVarnewSplit (Varnode *vn, const LaneDescription &description)
 Create placeholder nodes splitting a Varnode into its lanes.
 
TransformVarnewSplit (Varnode *vn, const LaneDescription &description, int4 numLanes, int4 startLane)
 Create placeholder nodes splitting a Varnode into a subset of lanes in the given description.
 
TransformOpnewOpReplace (int4 numParams, OpCode opc, PcodeOp *replace)
 Create a new placeholder op intended to replace an existing op.
 
TransformOpnewOp (int4 numParams, OpCode opc, TransformOp *follow)
 Create a new placeholder op that will not replace an existing op.
 
TransformOpnewPreexistingOp (int4 numParams, OpCode opc, PcodeOp *originalOp)
 Create a new placeholder op for an existing PcodeOp.
 
TransformVargetPreexistingVarnode (Varnode *vn)
 Get (or create) placeholder for preexisting Varnode.
 
TransformVargetPiece (Varnode *vn, int4 bitSize, int4 lsbOffset)
 Get (or create) placeholder piece.
 
TransformVargetSplit (Varnode *vn, const LaneDescription &description)
 Find (or create) placeholder nodes splitting a Varnode into its lanes.
 
TransformVargetSplit (Varnode *vn, const LaneDescription &description, int4 numLanes, int4 startLane)
 Find (or create) placeholder nodes splitting a Varnode into a subset of lanes from a description.
 
void opSetInput (TransformOp *rop, TransformVar *rvn, int4 slot)
 Mark given variable as input to given op.
 
void opSetOutput (TransformOp *rop, TransformVar *rvn)
 Mark given variable as output of given op.
 
void apply (void)
 Apply the full transform to the function.
 

Private Member Functions

int4 maxPrecision (Varnode *vn)
 Calculate maximum floating-point precision reaching a given Varnode.
 
bool exceedsPrecision (PcodeOp *op)
 Determine if the given op exceeds our precision.
 
TransformVarsetReplacement (Varnode *vn)
 Create and return a placeholder associated with the given Varnode.
 
bool traceForward (TransformVar *rvn)
 Try to trace logical variable through descendant Varnodes.
 
bool traceBackward (TransformVar *rvn)
 Trace a logical value backward through defining op one level.
 
bool processNextWork (void)
 Push the trace one hop from the placeholder at the top of the worklist.
 

Private Attributes

int4 precision
 Number of bytes of precision in the logical flow.
 
int4 terminatorCount
 Number of terminating nodes reachable via the root.
 
const FloatFormatformat
 The floating-point format of the logical value.
 
vector< TransformVar * > worklist
 Current list of placeholders that still need to be traced.
 
map< PcodeOp *, int4 > maxPrecisionMap
 Maximum precision flowing into a particular floating-point op.
 

Additional Inherited Members

- Static Public Member Functions inherited from ghidra::TransformManager
static bool preexistingGuard (int4 slot, TransformVar *rvn)
 Should newPreexistingOp be called.
 

Detailed Description

Class for tracing changes of precision in floating point variables.

It follows the flow of a logical lower precision value stored in higher precision locations and then rewrites the data-flow in terms of the lower precision, eliminating the precision conversions.

Constructor & Destructor Documentation

◆ SubfloatFlow()

ghidra::SubfloatFlow::SubfloatFlow ( Funcdata f,
Varnode root,
int4  prec 
)
Parameters
fis the function being transformed
rootis the start Varnode containing the logical value
precis the precision to assume for the logical value

References format, ghidra::Funcdata::getArch(), ghidra::Translate::getFloatFormat(), precision, setReplacement(), and ghidra::Architecture::translate.

Member Function Documentation

◆ doTrace()

bool ghidra::SubfloatFlow::doTrace ( void  )

Trace logical value as far as possible.

The interpretation that the root Varnode contains a logical value with smaller precision is pushed through the data-flow. If the interpretation is inconsistent, false is returned. Otherwise a transform is constructed that makes the smaller precision the explicit size of Varnodes within the data-flow.

Returns
true if a transform consistent with the given precision can be built

References ghidra::TransformManager::clearVarnodeMarks(), format, processNextWork(), terminatorCount, and worklist.

Referenced by ghidra::RuleSubfloatConvert::applyOp().

◆ exceedsPrecision()

bool ghidra::SubfloatFlow::exceedsPrecision ( PcodeOp op)
private

Determine if the given op exceeds our precision.

This is called only for binary floating-point ops: FLOAT_ADD, FLOAT_MULT, FLOAT_LESS, etc. If the maximum precision reaching both input operands exceeds the precision established for this Rule, true is returned, indicating the op cannot be truncated without losing precision. We count on the fact that this test is applied to all binary operations encountered during Rule application. This method will correctly return true for the earliest operations whose inputs both exceed the precision, but, because of the way maxPrecision() is calculated, it may incorrectly return false for later operations.

Parameters
opis the given binary floating-point PcodeOp
Returns
true if both input operands exceed the established precision

References ghidra::PcodeOp::getIn(), maxPrecision(), and precision.

Referenced by traceBackward(), and traceForward().

◆ maxPrecision()

int4 ghidra::SubfloatFlow::maxPrecision ( Varnode vn)
private

Calculate maximum floating-point precision reaching a given Varnode.

This method distinguishes between a floating-point variable with full precision, where all the storage can vary (or is unknown), versus a value that is extended from a floating-point variable with smaller storage. Within the data-flow above the given Varnode, we search for the maximum precision coming through MULTIEQUAL, COPY, and unary floating-point operations. Binary operations like FLOAT_ADD and FLOAT_MULT are not traversed and are assumed to produce a smaller precision. If the method indicates full precision for the given Varnode, or if the data-flow does not involve binary floating-point operations, it is accurate, otherwise it may under report the precision.

Parameters
vnis the given Varnode
Returns
an approximation of the maximum precision

References ghidra::PcodeOp::clearMark(), ghidra::PcodeOp::code(), ghidra::CPUI_COPY, ghidra::CPUI_FLOAT_ABS, ghidra::CPUI_FLOAT_ADD, ghidra::CPUI_FLOAT_CEIL, ghidra::CPUI_FLOAT_DIV, ghidra::CPUI_FLOAT_FLOAT2FLOAT, ghidra::CPUI_FLOAT_FLOOR, ghidra::CPUI_FLOAT_INT2FLOAT, ghidra::CPUI_FLOAT_MULT, ghidra::CPUI_FLOAT_NEG, ghidra::CPUI_FLOAT_ROUND, ghidra::CPUI_FLOAT_SQRT, ghidra::CPUI_FLOAT_SUB, ghidra::CPUI_MULTIEQUAL, ghidra::Varnode::getDef(), ghidra::PcodeOp::getIn(), ghidra::Varnode::getSize(), ghidra::SubfloatFlow::State::incorporateInputSize(), ghidra::PcodeOp::isMark(), ghidra::Varnode::isWritten(), ghidra::SubfloatFlow::State::maxPrecision, maxPrecisionMap, ghidra::PcodeOp::numInput(), ghidra::SubfloatFlow::State::op, ghidra::PcodeOp::setMark(), and ghidra::SubfloatFlow::State::slot.

Referenced by exceedsPrecision().

◆ preserveAddress()

bool ghidra::SubfloatFlow::preserveAddress ( Varnode vn,
int4  bitSize,
int4  lsbOffset 
) const
virtual

Should the address of the given Varnode be preserved when constructing a piece.

A new Varnode will be created that represents a logical piece of the given Varnode. This routine determines whether the new Varnode should be constructed using storage which overlaps the given Varnode. It returns true if overlapping storage should be used, false if the new Varnode should be constructed as a unique temporary.

Parameters
vnis the given Varnode
bitSizeis the logical size of the Varnode piece being constructed
lsbOffsetis the least significant bit position of the logical value within the given Varnode
Returns
true if overlapping storage should be used in construction

Reimplemented from ghidra::TransformManager.

References ghidra::Varnode::isInput().

◆ processNextWork()

bool ghidra::SubfloatFlow::processNextWork ( void  )
private

Push the trace one hop from the placeholder at the top of the worklist.

The logical value for the value on top of the worklist stack is pushed back to the input Varnodes of the operation defining it. Then the value is pushed forward through all operations that read it.

Returns
true if the trace is successfully pushed

References traceBackward(), traceForward(), and worklist.

Referenced by doTrace().

◆ setReplacement()

◆ traceBackward()

◆ traceForward()

bool ghidra::SubfloatFlow::traceForward ( TransformVar rvn)
private

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