Ghidra 11.3.2
Ghidra internal decompiler documentation.
|
A class for collecting sequences of COPY ops writing characters to the same string. More...
#include <constseq.hh>
Public Member Functions | |
StringSequence (Funcdata &fdata, Datatype *ct, SymbolEntry *ent, PcodeOp *root, const Address &addr) | |
Set-up for recovering COPY ops into a memory range, given a Symbol and an Address being COPYed into. | |
bool | transform (void) |
Transform COPYs into a single memcpy user-op. | |
![]() | |
ArraySequence (Funcdata &fdata, Datatype *ct, PcodeOp *root) | |
Constructor. | |
bool | isValid (void) const |
Return true if sequence is found. | |
Private Member Functions | |
bool | collectCopyOps (int size) |
Collect ops COPYing constants into the memory region. | |
PcodeOp * | buildStringCopy (void) |
Build the strncpy,wcsncpy, or memcpy function with string as input. | |
void | removeCopyOps (PcodeOp *replaceOp) |
Remove all the COPY ops from the basic block. | |
Varnode * | constructTypedPointer (PcodeOp *insertPoint) |
Construct a Varnode, with data-type, that acts as a pointer (in)to the Symbol to the root Address. | |
Static Private Member Functions | |
static void | removeForward (const WriteNode &curNode, map< PcodeOp *, list< WriteNode >::iterator > &xref, list< WriteNode > &points, vector< WriteNode > &deadOps) |
Analyze output descendants of the given PcodeOp being removed. | |
Private Attributes | |
Address | rootAddr |
Address within the memory region associated with the root PcodeOp. | |
Address | startAddr |
Starting address of the memory region. | |
SymbolEntry * | entry |
Symbol at the root Address. | |
Additional Inherited Members | |
![]() | |
static const int4 | MINIMUM_SEQUENCE_LENGTH = 4 |
Minimum number of sequential characters to trigger replacement with CALLOTHER. | |
static const int4 | MAXIMUM_SEQUENCE_LENGTH = 0x20000 |
![]() | |
bool | checkInterference (void) |
Find maximal set of ops containing the root with no interfering ops in between. | |
int4 | formByteArray (int4 sz, int4 slot, uint8 rootOff, bool bigEndian) |
Put constant values from COPYs into a single byte array. | |
uint4 | selectStringCopyFunction (int4 &index) |
Pick either strncpy, wcsncpy, or memcpy function used to copy string. | |
![]() | |
static bool | interfereBetween (PcodeOp *startOp, PcodeOp *endOp) |
Check for interfering ops between the two given ops. | |
![]() | |
Funcdata & | data |
The function containing the sequence. | |
PcodeOp * | rootOp |
The root PcodeOp. | |
Datatype * | charType |
Element data-type. | |
BlockBasic * | block |
Basic block containing all the COPY/STORE ops. | |
int4 | numElements |
Number of elements in the final sequence. | |
vector< WriteNode > | moveOps |
COPY/STORE into the array memory region. | |
vector< uint1 > | byteArray |
Constants collected in a single array. | |
A class for collecting sequences of COPY ops writing characters to the same string.
Given a starting Address and a Symbol with a character array as a component, a class instance collects a maximal set of COPY ops that can be treated as writing a single string into memory. Then, if the transform() method is called, an explicit string is constructed, and the COPYs are replaced with a strncpy or similar CALLOTHER that takes the string as its source input.
ghidra::StringSequence::StringSequence | ( | Funcdata & | fdata, |
Datatype * | ct, | ||
SymbolEntry * | ent, | ||
PcodeOp * | root, | ||
const Address & | addr | ||
) |
Set-up for recovering COPY ops into a memory range, given a Symbol and an Address being COPYed into.
The SymbolEntry and Address are passed in, with an expected data-type. Check if there is an array of the data-type within the Symbol, and if so, initialize the memory range for the the sequence. Follow on with gathering PcodeOps and testing if the sequence is viable. If not, the the size the memory range will be set to zero.
fdata | is the function containing the root COPY |
ct | is the specific data-type for which there should be an array |
ent | is the given Symbol |
root | is the COPY holding the constant |
addr | is the Address being COPYed into |
References ghidra::ArraySequence::checkInterference(), collectCopyOps(), entry, ghidra::ArraySequence::formByteArray(), ghidra::SymbolEntry::getAddr(), ghidra::SymbolEntry::getFirst(), ghidra::PcodeOp::getIn(), ghidra::Datatype::getMetatype(), ghidra::Address::getOffset(), ghidra::Varnode::getOffset(), ghidra::SymbolEntry::getSize(), ghidra::Datatype::getSize(), ghidra::Address::getSpace(), ghidra::Datatype::getSubType(), ghidra::SymbolEntry::getSymbol(), ghidra::Symbol::getType(), ghidra::Address::isBigEndian(), ghidra::ArraySequence::numElements, rootAddr, ghidra::ArraySequence::rootOp, startAddr, and ghidra::TYPE_ARRAY.
|
private |
Build the strncpy,wcsncpy, or memcpy function with string as input.
A built-in user-op that copies string data is created. Its first (destination) parameter is constructed as a pointer to the array holding the character data, which may be nested in other arrays or structures. The second (source) parameter is an internal string constructed from the byteArray. The third parameter is the constant indicating the length of the string. The user-op is inserted just before the last PcodeOp moving a character into the memory region.
References ghidra::ArraySequence::byteArray, ghidra::ArraySequence::charType, constructTypedPointer(), ghidra::CPUI_CALLOTHER, ghidra::ArraySequence::data, ghidra::PcodeOp::getAddr(), ghidra::Funcdata::getArch(), ghidra::Funcdata::getInternalString(), ghidra::Datatype::getSize(), ghidra::TypeFactory::getSizeOfPointer(), ghidra::Address::getSpace(), ghidra::TypeFactory::getTypePointer(), ghidra::AddrSpace::getWordSize(), ghidra::PcodeOp::inputTypeLocal(), ghidra::ArraySequence::moveOps, ghidra::Funcdata::newConstant(), ghidra::Funcdata::newOp(), ghidra::Funcdata::opInsertBefore(), ghidra::Funcdata::opSetInput(), ghidra::Funcdata::opSetOpcode(), ghidra::UserOpManage::registerBuiltin(), rootAddr, ghidra::ArraySequence::selectStringCopyFunction(), ghidra::Architecture::types, ghidra::Varnode::updateType(), and ghidra::Architecture::userops.
Referenced by transform().
|
private |
Collect ops COPYing constants into the memory region.
The COPYs must be in the same basic block. If any COPY size does not match the copyType, return false. If there is a COPY to the array entry before rootVn, return false. Otherwise earlier COPYs are skipped. No COPYs are collected after the first gap (entry with no COPY to it).
size | is the number of bytes in the memory region |
References ghidra::Funcdata::beginLoc(), ghidra::ArraySequence::block, ghidra::ArraySequence::charType, ghidra::PcodeOp::code(), ghidra::CPUI_COPY, ghidra::ArraySequence::data, ghidra::Funcdata::endLoc(), ghidra::Datatype::getAlignSize(), ghidra::Varnode::getDef(), ghidra::PcodeOp::getIn(), ghidra::Address::getOffset(), ghidra::Varnode::getOffset(), ghidra::PcodeOp::getParent(), ghidra::Datatype::getSize(), ghidra::Varnode::getSize(), ghidra::Varnode::isConstant(), ghidra::Varnode::isWritten(), ghidra::ArraySequence::MINIMUM_SEQUENCE_LENGTH, ghidra::ArraySequence::moveOps, rootAddr, and startAddr.
Referenced by StringSequence().
Construct a Varnode, with data-type, that acts as a pointer (in)to the Symbol to the root Address.
First, a PTRSUB is built from the base register to the Symbol. Then depending on its data-type, additional PTRSUBs and PTRADDs are buit to get from the start of the Symbol to the memory region holding the character data. All the new Varnodes have the appropriate pointer data-type set. The final Varnode holding the pointer to the memory region is returned.
insertPoint | is the point before which all new PTRSUBs and PTRADDs are inserted |
References ghidra::AddrSpace::byteToAddress(), ghidra::ArraySequence::charType, ghidra::Funcdata::constructConstSpacebase(), ghidra::Funcdata::constructSpacebaseInput(), ghidra::CPUI_INT_ADD, ghidra::CPUI_PTRADD, ghidra::CPUI_PTRSUB, ghidra::ArraySequence::data, entry, ghidra::PcodeOp::getAddr(), ghidra::Funcdata::getArch(), ghidra::SymbolEntry::getFirst(), ghidra::Datatype::getMetatype(), ghidra::Address::getOffset(), ghidra::Varnode::getSize(), ghidra::Address::getSpace(), ghidra::Datatype::getSubType(), ghidra::SymbolEntry::getSymbol(), ghidra::AddrSpace::getType(), ghidra::Symbol::getType(), ghidra::TypeFactory::getTypePointer(), ghidra::TypeFactory::getTypePointerStripArray(), ghidra::AddrSpace::getWordSize(), ghidra::IPTR_SPACEBASE, ghidra::Funcdata::newConstant(), ghidra::Funcdata::newOp(), ghidra::Funcdata::newUniqueOut(), ghidra::Funcdata::opInsertBefore(), ghidra::Funcdata::opSetInput(), ghidra::Funcdata::opSetOpcode(), rootAddr, ghidra::TYPE_ARRAY, ghidra::Architecture::types, and ghidra::Varnode::updateType().
Referenced by buildStringCopy().
|
private |
Remove all the COPY ops from the basic block.
The COPY ops are removed. Any descendants of the COPY output are redefined with an INDIRECT around the a CALLOTHER op. If the COPYs feed into a PIECE op (as part of a CONCAT stack), the PIECE is removed as well, which may cascade into removal of other PIECE ops in the stack.
replaceOp | is the CALLOTHER op creating the INDIRECT effect |
References ghidra::PcodeOp::code(), ghidra::CPUI_INDIRECT, ghidra::ArraySequence::data, ghidra::PcodeOp::getAddr(), ghidra::Varnode::getDef(), ghidra::PcodeOp::getIn(), ghidra::Varnode::getSize(), ghidra::Funcdata::markIndirectCreation(), ghidra::ArraySequence::moveOps, ghidra::Funcdata::newConstant(), ghidra::Funcdata::newOp(), ghidra::Funcdata::newVarnodeIop(), ghidra::Funcdata::opDestroy(), ghidra::Funcdata::opInsertBefore(), ghidra::Funcdata::opSetInput(), ghidra::Funcdata::opSetOpcode(), ghidra::Funcdata::opSetOutput(), and removeForward().
Referenced by transform().
|
staticprivate |
Analyze output descendants of the given PcodeOp being removed.
Record any points where the output is being read, for later replacement. Keep track of CPUI_PIECE ops whose input is from a PcodeOp being removed, and if both inputs are visited, remove the input points and add the CPUI_PIECE to the list of PcodeOps being removed.
curNode | is the given PcodeOp being removed |
xref | are the set of CPUI_PIECE ops with one input visited |
points | is the set of input points whose PcodeOp is being removed |
deadOps | is the current collection of PcodeOps being removed |
References ghidra::Varnode::beginDescend(), ghidra::PcodeOp::code(), ghidra::CPUI_PIECE, ghidra::Varnode::endDescend(), ghidra::PcodeOp::getOut(), ghidra::PcodeOp::getSlot(), ghidra::ArraySequence::WriteNode::offset, and ghidra::ArraySequence::WriteNode::op.
Referenced by removeCopyOps().
bool ghidra::StringSequence::transform | ( | void | ) |
Transform COPYs into a single memcpy user-op.
The transform can only fail if the byte array does not encode a valid string, in which case false is returned. Otherwise, a CALLOTHER representing memcpy is constructed taking the string constant as its source pointer. The original COPY ops are removed.
References buildStringCopy(), and removeCopyOps().
Referenced by ghidra::RuleStringCopy::applyOp().