decompiler  1.0.0
Public Types | Public Member Functions | Static Public Member Functions | Private Member Functions | Private Attributes | Friends | List of all members
ghidra::HighVariable Class Reference

A high-level variable modeled as a list of low-level variables, each written once. More...

#include <variable.hh>

Public Types

enum  {
  flagsdirty = 1, namerepdirty = 2, typedirty = 4, coverdirty = 8,
  symboldirty = 0x10, copy_in1 = 0x20, copy_in2 = 0x40, type_finalized = 0x80,
  unmerged = 0x100, intersectdirty = 0x200, extendcoverdirty = 0x400
}
 Dirtiness flags for a HighVariable. More...
 

Public Member Functions

 HighVariable (Varnode *vn)
 Construct a HighVariable with a single member Varnode. More...
 
 ~HighVariable (void)
 Destructor.
 
DatatypegetType (void) const
 Get the data-type.
 
const CovergetCover (void) const
 Get cover data for this variable. More...
 
SymbolgetSymbol (void) const
 Get the Symbol associated with this or null.
 
SymbolEntrygetSymbolEntry (void) const
 
int4 getSymbolOffset (void) const
 Get the SymbolEntry mapping to this or null. More...
 
int4 numInstances (void) const
 Get the number of member Varnodes this has.
 
VarnodegetInstance (int4 i) const
 Get the i-th member Varnode.
 
void finalizeDatatype (Datatype *tp)
 Set a final datatype for this variable. More...
 
void groupWith (int4 off, HighVariable *hi2)
 Put this and another HighVariable in the same intersection group. More...
 
void establishGroupSymbolOffset (void)
 Transfer symbol offset of this to the VariableGroup. More...
 
void printCover (ostream &s) const
 Print details of the cover for this (for debug purposes) More...
 
void printInfo (ostream &s) const
 Print information about this HighVariable to stream. More...
 
bool hasName (void) const
 Check if this HighVariable can be named. More...
 
VarnodegetTiedVarnode (void) const
 Find the first address tied member Varnode. More...
 
VarnodegetInputVarnode (void) const
 Find (the) input member Varnode. More...
 
VarnodegetTypeRepresentative (void) const
 Get a member Varnode with the strongest data-type. More...
 
VarnodegetNameRepresentative (void) const
 Get a member Varnode that dictates the naming of this HighVariable. More...
 
int4 getNumMergeClasses (void) const
 Get the number of speculative merges for this.
 
bool isMapped (void) const
 Return true if this is mapped.
 
bool isPersist (void) const
 Return true if this is a global variable.
 
bool isAddrTied (void) const
 Return true if this is address ties.
 
bool isInput (void) const
 Return true if this is an input variable.
 
bool isImplied (void) const
 Return true if this is an implied variable.
 
bool isSpacebase (void) const
 Return true if this is a spacebase.
 
bool isConstant (void) const
 Return true if this is a constant.
 
bool isUnaffected (void) const
 Return true if this is an unaffected register.
 
bool isExtraOut (void) const
 Return true if this is an extra output.
 
bool isProtoPartial (void) const
 Return true if this is a piece concatenated into a larger whole.
 
void setMark (void) const
 Set the mark on this variable.
 
void clearMark (void) const
 Clear the mark on this variable.
 
bool isMark (void) const
 Return true if this is marked.
 
bool isUnmerged (void) const
 Return true if this has merge problems.
 
bool hasCover (void) const
 Determine if this HighVariable has an associated cover. More...
 
bool isUnattached (void) const
 Return true if this has no member Varnode.
 
bool isTypeLock (void) const
 Return true if this is typelocked.
 
bool isNameLock (void) const
 Return true if this is namelocked.
 
void encode (Encoder &encoder) const
 Encode this variable to stream as a <high> element. More...
 

Static Public Member Functions

static bool compareName (Varnode *vn1, Varnode *vn2)
 Determine which given Varnode is most nameable. More...
 
static bool compareJustLoc (const Varnode *a, const Varnode *b)
 Compare based on storage location. More...
 
static int4 markExpression (Varnode *vn, vector< HighVariable *> &highList)
 Mark and collect variables in expression. More...
 

Private Member Functions

int4 instanceIndex (const Varnode *vn) const
 Find the index of a specific Varnode member. More...
 
void updateFlags (void) const
 (Re)derive boolean properties of this from the member Varnodes More...
 
void updateInternalCover (void) const
 (Re)derive the internal cover of this from the member Varnodes More...
 
void updateCover (void) const
 (Re)derive the external cover of this, as a union of internal covers More...
 
void updateType (void) const
 (Re)derive the data-type for this from the member Varnodes More...
 
void updateSymbol (void) const
 (Re)derive the Symbol and offset for this from member Varnodes
 
void setCopyIn1 (void) const
 Mark the existence of one COPY into this.
 
void setCopyIn2 (void) const
 Mark the existence of two COPYs into this.
 
void clearCopyIns (void) const
 Clear marks indicating COPYs into this.
 
bool hasCopyIn1 (void) const
 Is there at least one COPY into this.
 
bool hasCopyIn2 (void) const
 Is there at least two COPYs into this.
 
void remove (Varnode *vn)
 Remove a member Varnode from this. More...
 
void mergeInternal (HighVariable *tv2, bool isspeculative)
 Merge another HighVariable into this. More...
 
void merge (HighVariable *tv2, HighIntersectTest *testCache, bool isspeculative)
 Merge with another HighVariable taking into account groups. More...
 
void setSymbol (Varnode *vn) const
 Update Symbol information for this from the given member Varnode. More...
 
void setSymbolReference (Symbol *sym, int4 off)
 Attach a reference to a Symbol to this. More...
 
void transferPiece (HighVariable *tv2)
 Transfer ownership of another's VariablePiece to this.
 
void flagsDirty (void) const
 Mark the boolean properties as dirty.
 
void coverDirty (void) const
 Mark the cover as dirty. More...
 
void typeDirty (void) const
 Mark the data-type as dirty.
 
void symbolDirty (void) const
 Mark the symbol as dirty.
 
void setUnmerged (void) const
 Mark this as having merge problems.
 
bool isCoverDirty (void) const
 Is the cover returned by getCover() up-to-date. More...
 

Private Attributes

vector< Varnode * > inst
 The member Varnode objects making up this HighVariable.
 
int4 numMergeClasses
 Number of different speculative merge classes in this.
 
uint4 highflags
 Dirtiness flags.
 
uint4 flags
 Boolean properties inherited from Varnode members.
 
Datatypetype
 The data-type for this.
 
VarnodenameRepresentative
 The storage location used to generate a Symbol name.
 
Cover internalCover
 The ranges of code addresses covered by this HighVariable.
 
VariablePiecepiece
 Additional info about intersections with other pieces (if non-null)
 
Symbolsymbol
 The Symbol this HighVariable is tied to.
 
int4 symboloffset
 -1=perfect symbol match >=0, offset
 

Friends

class Varnode
 
class Merge
 
class VariablePiece
 
class HighIntersectTest
 

Detailed Description

A high-level variable modeled as a list of low-level variables, each written once.

In the Static Single Assignment (SSA) representation of a function's data-flow, the Varnode object represents a variable node. This is a low-level variable: it is written to at most once, and there is 1 or more reads. A high-level variable, in the source language may be written to multiple times. We model this idea as a list of Varnode objects, where a different Varnode holds the value of the variable for different parts of the code. The range(s) of code for which a single Varnode holds the high-level variable's value is the cover or range of that Varnode and is modeled by the class Cover. Within a high-level variable, HighVariable, the covers of member Varnode objects should not intersect, as that represents the variable holding two or more different values at the same place in the code. The HighVariable inherits a cover which is the union of the covers of its Varnodes.

Member Enumeration Documentation

◆ anonymous enum

anonymous enum

Dirtiness flags for a HighVariable.

The HighVariable inherits its Cover, its data-type, and other boolean properties from its Varnodes. The object holds these explicitly, but the values may become stale as the data-flow transforms. So we keep track of when these inherited values are dirty

Enumerator
flagsdirty 

Boolean properties for the HighVariable are dirty.

namerepdirty 

The name representative for the HighVariable is dirty.

typedirty 

The data-type for the HighVariable is dirty.

coverdirty 

The cover for the HighVariable is dirty.

symboldirty 

The symbol attachment is dirty.

copy_in1 

There exists at least 1 COPY into this HighVariable from other HighVariables.

copy_in2 

There exists at least 2 COPYs into this HighVariable from other HighVariables.

type_finalized 

Set if a final data-type is locked in and dirtying is disabled.

unmerged 

Set if part of a multi-entry Symbol but did not get merged with other SymbolEntrys.

intersectdirty 

Set if intersections with other HighVariables needs to be recomputed.

extendcoverdirty 

Set if extended cover needs to be recomputed.

Constructor & Destructor Documentation

◆ HighVariable()

ghidra::HighVariable::HighVariable ( Varnode vn)

Construct a HighVariable with a single member Varnode.

The new instance starts off with no associate Symbol and all properties marked as dirty.

Parameters
vnis the single Varnode member

References ghidra::Varnode::getSymbolEntry(), and ghidra::Varnode::setHigh().

Member Function Documentation

◆ compareJustLoc()

bool ghidra::HighVariable::compareJustLoc ( const Varnode a,
const Varnode b 
)
static

Compare based on storage location.

Compare two Varnode objects based just on their storage address

Parameters
ais the first Varnode to compare
bis the second Varnode
Returns
true if the first Varnode should be ordered before the second

References ghidra::Varnode::getAddr().

◆ compareName()

bool ghidra::HighVariable::compareName ( Varnode vn1,
Varnode vn2 
)
static

Determine which given Varnode is most nameable.

Given two Varnode (members), sort them based on naming properties:

Returns
true if the second Varnode's name would override the first's

References ghidra::Varnode::getDef(), ghidra::Varnode::getSpace(), ghidra::PcodeOp::getTime(), ghidra::AddrSpace::getType(), ghidra::IPTR_INTERNAL, ghidra::Varnode::isAddrTied(), ghidra::Varnode::isInput(), ghidra::Varnode::isNameLock(), ghidra::Varnode::isPersist(), ghidra::Varnode::isProtoPartial(), ghidra::Varnode::isUnaffected(), and ghidra::Varnode::isWritten().

◆ coverDirty()

void ghidra::HighVariable::coverDirty ( void  ) const
inlineprivate

Mark the cover as dirty.

The internal cover is marked as dirty. If this is a piece of a VariableGroup, it and all the other HighVariables it intersects with are marked as having a dirty extended cover.

Referenced by ghidra::Merge::inflate().

◆ encode()

void ghidra::HighVariable::encode ( Encoder encoder) const

◆ establishGroupSymbolOffset()

void ghidra::HighVariable::establishGroupSymbolOffset ( void  )

Transfer symbol offset of this to the VariableGroup.

If this is part of a larger group and has had its symboloffset set, it can be used to calculate the symboloffset of other HighVariables in the same group, by writing it to the common VariableGroup object.

References ghidra::VariableGroup::setSymbolOffset().

Referenced by ghidra::Funcdata::linkProtoPartial().

◆ finalizeDatatype()

void ghidra::HighVariable::finalizeDatatype ( Datatype tp)

Set a final datatype for this variable.

The data-type its dirtying mechanism is disabled. The data-type will not change, unless this method is called again.

Parameters
tpis the data-type to set

References ghidra::Datatype::getMetatype(), ghidra::TYPE_PARTIALUNION, ghidra::TYPE_STRUCT, and ghidra::TYPE_UNION.

Referenced by ghidra::Funcdata::syncVarnodesWithSymbol().

◆ getCover()

const Cover & ghidra::HighVariable::getCover ( void  ) const
inline

Get cover data for this variable.

The returns the internal cover unless this is part of a VariableGroup, in which case the extended cover is returned.

Returns
the cover associated with this variable

Referenced by ghidra::HighIntersectTest::blockIntersection(), ghidra::Merge::compareHighByBlock(), and ghidra::HighIntersectTest::intersection().

◆ getInputVarnode()

Varnode * ghidra::HighVariable::getInputVarnode ( void  ) const

Find (the) input member Varnode.

This should only be called if isInput() returns true. If there is no input member, this will throw an exception.

Returns
the input Varnode member

Referenced by ghidra::Merge::mergeTestAdjacent().

◆ getNameRepresentative()

Varnode * ghidra::HighVariable::getNameRepresentative ( void  ) const

Get a member Varnode that dictates the naming of this HighVariable.

Members are scored based the properties that are most dominating in choosing a name.

Returns
the highest scoring Varnode member

Referenced by ghidra::Funcdata::linkProtoPartial(), ghidra::ActionNameVars::linkSymbols(), and ghidra::PrintLanguage::pushSymbolDetail().

◆ getSymbolEntry()

SymbolEntry * ghidra::HighVariable::getSymbolEntry ( void  ) const

Assuming there is a Symbol attached to this, run through the Varnode members until we find one with a SymbolEntry corresponding to the Symbol and return it.

Returns
the SymbolEntry that mapped the Symbol to this or null if no Symbol is attached

References ghidra::SymbolEntry::getSymbol().

Referenced by ghidra::PrintC::pushSymbol().

◆ getSymbolOffset()

int4 ghidra::HighVariable::getSymbolOffset ( void  ) const
inline

◆ getTiedVarnode()

Varnode * ghidra::HighVariable::getTiedVarnode ( void  ) const

Find the first address tied member Varnode.

This should only be called if isAddrTied() returns true. If there is no address tied member, this will throw an exception.

Returns
the first address tied member

Referenced by ghidra::MapState::gatherHighs(), and ghidra::Merge::mergeTestRequired().

◆ getTypeRepresentative()

Varnode * ghidra::HighVariable::getTypeRepresentative ( void  ) const

Get a member Varnode with the strongest data-type.

Find the member Varnode with the most specialized data-type, handling bool specially. Boolean data-types are specialized in the data-type lattice, but not all byte values are boolean values. Within the Varnode/PcodeOp tree, the bool data-type can only propagate to a Varnode if it is verified to only take the boolean values 0 and 1. Since the data-type representative represents the type of all instances, if any instance is not boolean, then the HighVariable cannot be boolean, even though bool is more specialized. This method uses Datatype::typeOrderBool() to implement the special handling.

Returns
the representative member

References ghidra::Varnode::getType(), ghidra::Varnode::isTypeLock(), and ghidra::Datatype::typeOrderBool().

◆ groupWith()

void ghidra::HighVariable::groupWith ( int4  off,
HighVariable hi2 
)

Put this and another HighVariable in the same intersection group.

If one of the HighVariables is already in a group, the other HighVariable is added to this group.

Parameters
offis the relative byte offset of this with the other HighVariable
hi2is the other HighVariable

References ghidra::VariableGroup::combineGroups(), ghidra::VariablePiece::getGroup(), ghidra::VariablePiece::getOffset(), highflags, ghidra::VariablePiece::markIntersectionDirty(), and piece.

Referenced by ghidra::Merge::groupPartialRoot(), and ghidra::Merge::mergeAddrTied().

◆ hasCover()

bool ghidra::HighVariable::hasCover ( void  ) const
inline

Determine if this HighVariable has an associated cover.

Constant and annotation variables do not have a cover

Returns
true if this has a cover

References ghidra::Varnode::annotation, ghidra::Varnode::constant, and ghidra::Varnode::insert.

Referenced by ghidra::Merge::mergeTest().

◆ hasName()

bool ghidra::HighVariable::hasName ( void  ) const

Check if this HighVariable can be named.

All Varnode objects are assigned a HighVariable, including those that don't get names like indirect variables, constants, and annotations. Determine if this, as inherited from its member Varnodes, can have a name.

Returns
true if this can have a name

References ghidra::Varnode::hasCover(), ghidra::Varnode::isIllegalInput(), ghidra::Varnode::isImplied(), ghidra::Varnode::isIndirectOnly(), and ghidra::Varnode::isSpacebase().

Referenced by ghidra::ActionNameVars::linkSymbols().

◆ instanceIndex()

int4 ghidra::HighVariable::instanceIndex ( const Varnode vn) const
private

Find the index of a specific Varnode member.

Find the index, for use with getInstance(), that will retrieve the given Varnode member

Parameters
vnis the given Varnode member
Returns
the index of the member or -1 if it is not a member

◆ isCoverDirty()

bool ghidra::HighVariable::isCoverDirty ( void  ) const
inlineprivate

Is the cover returned by getCover() up-to-date.

The cover could either by the internal one or the extended one if this is part of a Variable Group.

Returns
true if the cover needs to be recomputed.

Referenced by ghidra::HighIntersectTest::updateHigh().

◆ markExpression()

int4 ghidra::HighVariable::markExpression ( Varnode vn,
vector< HighVariable *> &  highList 
)
static

Mark and collect variables in expression.

Given a Varnode at the root of an expression, we collect all the explicit HighVariables involved in the expression. This should only be run after explicit and implicit properties have been computed on Varnodes. The expression is traced back from the root until explicit Varnodes are encountered; then their HighVariable is marked and added to the list. The routine returns a value based on PcodeOps encountered in the expression:

  • 1 for call instructions
  • 2 for LOAD instructions
  • 3 for both call and LOAD
  • 0 for no calls or LOADS
Parameters
vnis the given root Varnode of the expression
highListwill hold the collected HighVariables
Returns
a value based on call and LOAD instructions in the expression

References ghidra::PcodeOp::code(), ghidra::Varnode::copyShadow(), ghidra::CPUI_LOAD, ghidra::Varnode::getCover(), ghidra::Varnode::getDef(), ghidra::Varnode::getHigh(), ghidra::Cover::intersect(), ghidra::Varnode::isAnnotation(), ghidra::PcodeOp::isCall(), ghidra::Varnode::isExplicit(), isMark(), ghidra::Varnode::isWritten(), ghidra::Cover::merge(), and setMark().

Referenced by ghidra::Funcdata::moveRespectingCover().

◆ merge()

void ghidra::HighVariable::merge ( HighVariable tv2,
HighIntersectTest testCache,
bool  isspeculative 
)
private

Merge with another HighVariable taking into account groups.

The HighVariables are merged internally as with mergeInternal. If this is part of a VariableGroup, extended covers of the group may be affected. If both HighVariables are part of separate groups, the groups are combined into one, which may induce additional HighVariable pairs within the group to be merged. In all cases, the other HighVariable is deleted.

Parameters
tv2is the other HighVariable to merge into this
testCacheif non-null is a cache of intersection tests that must be updated to reflect the merge
isspeculativeis true to keep the new members in separate merge classes

References mergeInternal(), ghidra::HighIntersectTest::moveIntersectTests(), and piece.

Referenced by ghidra::Merge::buildDominantCopy(), and ghidra::Merge::merge().

◆ mergeInternal()

void ghidra::HighVariable::mergeInternal ( HighVariable tv2,
bool  isspeculative 
)
private

Merge another HighVariable into this.

The lists of members are merged and the other HighVariable is deleted.

Parameters
tv2is the other HighVariable to merge into this
isspeculativeis true to keep the new members in separate merge classes

References ghidra::Varnode::getMergeGroup(), highflags, inst, internalCover, numMergeClasses, ghidra::Varnode::setHigh(), symbol, and symboloffset.

Referenced by merge().

◆ printCover()

void ghidra::HighVariable::printCover ( ostream &  s) const
inline

Print details of the cover for this (for debug purposes)

Parameters
sis the output stream

References coverdirty, and ghidra::Cover::print().

Referenced by ghidra::IfcPrintCover::execute(), and ghidra::IfcVarnodehighCover::execute().

◆ printInfo()

void ghidra::HighVariable::printInfo ( ostream &  s) const

Print information about this HighVariable to stream.

This is generally used for debug purposes.

Parameters
sis the output stream

References ghidra::Varnode::getMergeGroup(), and ghidra::Varnode::printInfo().

Referenced by ghidra::IfcPrintHigh::execute(), and ghidra::IfcPrintVarnode::execute().

◆ remove()

void ghidra::HighVariable::remove ( Varnode vn)
private

Remove a member Varnode from this.

Search for the given Varnode and cut it out of the list, marking all properties as dirty.

Parameters
vnis the given Varnode member to remove

References ghidra::Varnode::getSymbolEntry().

Referenced by ghidra::Merge::buildDominantCopy(), and ghidra::Varnode::~Varnode().

◆ setSymbol()

void ghidra::HighVariable::setSymbol ( Varnode vn) const
private

◆ setSymbolReference()

void ghidra::HighVariable::setSymbolReference ( Symbol sym,
int4  off 
)
private

Attach a reference to a Symbol to this.

Link information to this from a Symbol that is not attached to a member Varnode. This only works for a HighVariable with a constant member Varnode. This used when there is a constant address reference to the Symbol and the Varnode holds the reference, not the actual value of the Symbol.

Parameters
symis the given Symbol to attach
offis the byte offset into the Symbol of the reference

◆ updateCover()

void ghidra::HighVariable::updateCover ( void  ) const
private

(Re)derive the external cover of this, as a union of internal covers

This is only called by the Merge class which knows when to call it properly.

Referenced by ghidra::Merge::merge(), and ghidra::HighIntersectTest::updateHigh().

◆ updateFlags()

void ghidra::HighVariable::updateFlags ( void  ) const
private

(Re)derive boolean properties of this from the member Varnodes

Only update if flags are marked as dirty. Generally if any member Varnode possesses the property, this HighVariable should inherit it. The Varnode::typelock field is not set here, but in updateType().

References ghidra::Varnode::directwrite, ghidra::Varnode::mark, and ghidra::Varnode::typelock.

◆ updateInternalCover()

void ghidra::HighVariable::updateInternalCover ( void  ) const
private

(Re)derive the internal cover of this from the member Varnodes

Only update if the cover is marked as dirty. Merge the covers of all Varnode instances.

Referenced by ghidra::VariablePiece::updateCover().

◆ updateType()

void ghidra::HighVariable::updateType ( void  ) const
private

(Re)derive the data-type for this from the member Varnodes

Only update if the data-type is marked as dirty. Get the most locked, most specific data-type from member Varnode objects.

References ghidra::Datatype::getMetatype(), ghidra::Varnode::getType(), ghidra::Varnode::isTypeLock(), ghidra::TYPE_PARTIALUNION, ghidra::TYPE_STRUCT, ghidra::TYPE_UNION, and ghidra::Varnode::typelock.


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