/* ### * 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 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