mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
223 lines
7.9 KiB
C++
223 lines
7.9 KiB
C++
/* ###
|
|
* IP: GHIDRA
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
/// \file pcoderaw.hh
|
|
/// \brief Raw descriptions of varnodes and p-code ops
|
|
#ifndef __CPUI_PCODERAW__
|
|
#define __CPUI_PCODERAW__
|
|
|
|
#include "address.hh"
|
|
#include "opbehavior.hh"
|
|
|
|
/// \brief Data defining a specific memory location
|
|
///
|
|
/// Within the decompiler's model of a processor, any register,
|
|
/// memory location, or other variable can always be represented
|
|
/// as an address space, an offset within the space, and the
|
|
/// size of the sequence of bytes. This is more commonly referred
|
|
/// to as a Varnode, but this is a bare-bones container
|
|
/// for the data that doesn't have the cached attributes and
|
|
/// the dataflow links of the Varnode within its syntax tree.
|
|
struct VarnodeData {
|
|
AddrSpace *space; ///< The address space
|
|
uintb offset; ///< The offset within the space
|
|
uint4 size; ///< The number of bytes in the location
|
|
bool operator<(const VarnodeData &op2) const; ///< An ordering for VarnodeData
|
|
bool operator==(const VarnodeData &op2) const; ///< Compare for equality
|
|
bool operator!=(const VarnodeData &op2) const; ///< Compare for inequality
|
|
|
|
/// Get the location of the varnode as an address
|
|
Address getAddr(void) const;
|
|
|
|
/// Recover this object from an XML tag
|
|
void restoreXml(const Element *el,const AddrSpaceManager *manage);
|
|
|
|
/// Does \b this container another given VarnodeData
|
|
bool contains(const VarnodeData &op2) const;
|
|
};
|
|
|
|
/// VarnodeData can be sorted in terms of the space its in
|
|
/// (the space's \e index), the offset within the space,
|
|
/// and finally by the size.
|
|
/// \param op2 is the object being compared to
|
|
/// \return true if \e this is less than \e op2
|
|
inline bool VarnodeData::operator<(const VarnodeData &op2) const {
|
|
if (space != op2.space) return (space->getIndex() < op2.space->getIndex());
|
|
if (offset != op2.offset) return (offset < op2.offset);
|
|
return (size > op2.size); // BIG sizes come first
|
|
}
|
|
|
|
/// Compare VarnodeData for equality. The space, offset, and size
|
|
/// must all be exactly equal
|
|
/// \param op2 is the object being compared to
|
|
/// \return true if \e this is equal to \e op2
|
|
inline bool VarnodeData::operator==(const VarnodeData &op2) const {
|
|
if (space != op2.space) return false;
|
|
if (offset != op2.offset) return false;
|
|
return (size == op2.size);
|
|
}
|
|
|
|
/// Compare VarnodeData for inequality. If either the space,
|
|
/// offset, or size is not equal, return \b true.
|
|
/// \param op2 is the object being compared to
|
|
/// \return true if \e this is not equal to \e op2
|
|
inline bool VarnodeData::operator!=(const VarnodeData &op2) const {
|
|
if (space != op2.space) return true;
|
|
if (offset != op2.offset) return true;
|
|
return (size != op2.size);
|
|
}
|
|
|
|
/// This is a convenience function to construct a full Address from the
|
|
/// VarnodeData's address space and offset
|
|
/// \return the address of the varnode
|
|
inline Address VarnodeData::getAddr(void) const {
|
|
return Address(space,offset);
|
|
}
|
|
|
|
/// \brief A low-level representation of a single pcode operation
|
|
///
|
|
/// This is just the minimum amount of data to represent a pcode operation
|
|
/// An opcode, sequence number, optional output varnode
|
|
/// and input varnodes
|
|
class PcodeOpRaw {
|
|
OpBehavior *behave; ///< The opcode for this operation
|
|
SeqNum seq; ///< Identifying address and index of this operation
|
|
VarnodeData *out; ///< Output varnode triple
|
|
vector<VarnodeData *> in; ///< Raw varnode inputs to this op
|
|
public:
|
|
void setBehavior(OpBehavior *be); ///< Set the opcode for this op
|
|
OpBehavior *getBehavior(void) const; ///< Retrieve the behavior for this op
|
|
OpCode getOpcode(void) const; ///< Get the opcode for this op
|
|
void setSeqNum(const Address &a,uintm b); ///< Set the sequence number
|
|
const SeqNum &getSeqNum(void) const; ///< Retrieve the sequence number
|
|
const Address &getAddr(void) const; ///< Get address of this operation
|
|
void setOutput(VarnodeData *o); ///< Set the output varnode for this op
|
|
VarnodeData *getOutput(void) const; ///< Retrieve the output varnode for this op
|
|
void addInput(VarnodeData *i); ///< Add an additional input varnode to this op
|
|
void clearInputs(void); ///< Remove all input varnodes to this op
|
|
int4 numInput(void) const; ///< Get the number of input varnodes to this op
|
|
VarnodeData *getInput(int4 i) const; ///< Get the i-th input varnode for this op
|
|
};
|
|
|
|
/// The core behavior for this operation is controlled by an OpBehavior object
|
|
/// which knows how output is determined given inputs. This routine sets that object
|
|
/// \param be is the behavior object
|
|
inline void PcodeOpRaw::setBehavior(OpBehavior *be)
|
|
|
|
{
|
|
behave = be;
|
|
}
|
|
|
|
/// Get the underlying behavior object for this pcode operation. From this
|
|
/// object you can determine how the object evaluates inputs to get the output
|
|
/// \return the behavior object
|
|
inline OpBehavior *PcodeOpRaw::getBehavior(void) const
|
|
|
|
{
|
|
return behave;
|
|
}
|
|
|
|
/// The possible types of pcode operations are enumerated by OpCode
|
|
/// This routine retrieves the enumeration value for this particular op
|
|
/// \return the opcode value
|
|
inline OpCode PcodeOpRaw::getOpcode(void) const
|
|
|
|
{
|
|
return behave->getOpcode();
|
|
}
|
|
|
|
/// Every pcode operation has a \b sequence \b number
|
|
/// which associates the operation with the address of the machine instruction
|
|
/// being translated and an order number which provides an index for this
|
|
/// particular operation within the entire translation of the machine instruction
|
|
/// \param a is the instruction address
|
|
/// \param b is the order number
|
|
inline void PcodeOpRaw::setSeqNum(const Address &a,uintm b)
|
|
|
|
{
|
|
seq = SeqNum(a,b);
|
|
}
|
|
|
|
/// Every pcode operation has a \b sequence \b number which associates
|
|
/// the operation with the address of the machine instruction being translated
|
|
/// and an index number for this operation within the translation.
|
|
/// \return a reference to the sequence number
|
|
inline const SeqNum &PcodeOpRaw::getSeqNum(void) const
|
|
|
|
{
|
|
return seq;
|
|
}
|
|
|
|
/// This is a convenience function to get the address of the machine instruction
|
|
/// (of which this pcode op is a translation)
|
|
/// \return the machine instruction address
|
|
inline const Address &PcodeOpRaw::getAddr(void) const
|
|
|
|
{
|
|
return seq.getAddr();
|
|
}
|
|
|
|
/// Most pcode operations output to a varnode. This routine sets what that varnode is.
|
|
/// \param o is the varnode to set as output
|
|
inline void PcodeOpRaw::setOutput(VarnodeData *o)
|
|
|
|
{
|
|
out = o;
|
|
}
|
|
|
|
/// Most pcode operations have an output varnode. This routine retrieves that varnode.
|
|
/// \return the output varnode or \b null if there is no output
|
|
inline VarnodeData *PcodeOpRaw::getOutput(void) const
|
|
|
|
{
|
|
return out;
|
|
}
|
|
|
|
/// A PcodeOpRaw is initially created with no input varnodes. Inputs are added with this method.
|
|
/// Varnodes are added in order, so the first addInput call creates input 0, for example.
|
|
/// \param i is the varnode to be added as input
|
|
inline void PcodeOpRaw::addInput(VarnodeData *i)
|
|
|
|
{
|
|
in.push_back(i);
|
|
}
|
|
|
|
/// If the inputs to a pcode operation need to be changed, this routine clears the existing
|
|
/// inputs so new ones can be added.
|
|
inline void PcodeOpRaw::clearInputs(void)
|
|
|
|
{
|
|
in.clear();
|
|
}
|
|
|
|
/// \return the number of inputs
|
|
inline int4 PcodeOpRaw::numInput(void) const
|
|
|
|
{
|
|
return in.size();
|
|
}
|
|
|
|
/// Input varnodes are indexed starting at 0. This retrieves the input varnode by index.
|
|
/// The index \e must be in range, or unpredicatable behavior will result. Use the numInput method
|
|
/// to get the number of inputs.
|
|
/// \param i is the index of the desired input
|
|
/// \return the desired input varnode
|
|
inline VarnodeData *PcodeOpRaw::getInput(int4 i) const
|
|
|
|
{
|
|
return in[i];
|
|
}
|
|
|
|
#endif
|