ghidra/Ghidra/Features/Decompiler/src/decompile/cpp/ghidra_arch.hh

173 lines
11 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 ghidra_arch.hh
/// \brief Ghidra specific architecture information and connection to a Ghidra client
#ifndef __GHIDRA_ARCH_HH__
#define __GHIDRA_ARCH_HH__
#include "architecture.hh"
namespace ghidra {
extern ElementId ELEM_COMMAND_ISNAMEUSED; ///< Marshaling element \<command_isnameused>
extern ElementId ELEM_COMMAND_GETBYTES; ///< Marshaling element \<command_getbytes>
extern ElementId ELEM_COMMAND_GETCALLFIXUP; ///< Marshaling element \<command_getcallfixup>
extern ElementId ELEM_COMMAND_GETCALLMECH; ///< Marshaling element \<command_getcallmech>
extern ElementId ELEM_COMMAND_GETCALLOTHERFIXUP; ///< Marshaling element \<command_getcallotherfixup>
extern ElementId ELEM_COMMAND_GETCODELABEL; ///< Marshaling element \<command_getcodelabel>
extern ElementId ELEM_COMMAND_GETCOMMENTS; ///< Marshaling element \<command_getcomments>
extern ElementId ELEM_COMMAND_GETCPOOLREF; ///< Marshaling element \<command_getcpoolref>
extern ElementId ELEM_COMMAND_GETDATATYPE; ///< Marshaling element \<command_datatype>
extern ElementId ELEM_COMMAND_GETEXTERNALREF; ///< Marshaling element \<command_getexternalref>
extern ElementId ELEM_COMMAND_GETMAPPEDSYMBOLS; ///< Marshaling element \<command_getmappedsymbols>
extern ElementId ELEM_COMMAND_GETNAMESPACEPATH; ///< Marshaling element \<command_getnamespacepath>
extern ElementId ELEM_COMMAND_GETPCODE; ///< Marshaling element \<command_getpcode>
extern ElementId ELEM_COMMAND_GETPCODEEXECUTABLE; ///< Marshaling element \<command_getpcodeexecutable>
extern ElementId ELEM_COMMAND_GETREGISTER; ///< Marshaling element \<command_getregister>
extern ElementId ELEM_COMMAND_GETREGISTERNAME; ///< Marshaling element \<command_getregistername>
extern ElementId ELEM_COMMAND_GETSTRINGDATA; ///< Marshaling element \<command_getstringdata>
extern ElementId ELEM_COMMAND_GETTRACKEDREGISTERS; ///< Marshaling element \<command_gettrackedregisters>
extern ElementId ELEM_COMMAND_GETUSEROPNAME; ///< Marshaling element \<command_getuseropname>
/// \brief Exception that mirrors exceptions thrown by the Ghidra client
///
/// If the Ghidra client throws an exception while trying to answer a query,
/// the exception is caught and sent back to the ArchitectureGhidra object
/// in a specially formatted interrupt message. The message is decoded
/// into this object, which is than thrown.
///
/// This class also doubles as an exception generated by the decompiler
/// because of message protocol \e alignment, which should get sent back to the Ghidra client
struct JavaError : public LowlevelError {
string type; ///< The name of the Java exception class
JavaError(const string &tp,const string &message) : LowlevelError(message) {
type = tp; } ///< Construct given a class and message
};
/// \brief An implementation of the Architecture interface and connection to a Ghidra client
///
/// In addition to managing the major pieces of the architecture
/// (LoadImage, Translate, Database, TypeFactory, ContextDatbase, CommentDatabase etc.),
/// this class manages a communication channel between the decompiler and a Ghidra client
/// for a single executable. The protocol supports a simple query/response format with exceptions.
/// On top of the low level protocol, this class manages a higher level interface that performs
/// specific queries, providing addresses, names, and other info as input, and returning
/// an XML document or other structure as a result.
///
/// This class overrides the build* methods to produce Architecture components that are
/// also backed by the Ghidra client. These all use this same object to do their communication.
///
/// This class acts as a main control point for what information gets sent back to the
/// Ghidra client when it requests the main decompilation action.
/// Generally the decompiler sends back the recovered source representation of the function
/// but optionally it can send back:
/// - Recovered source code (with mark up)
/// - Data-flow and control-flow structures
/// - Local symbol and jump-table information
/// - Parameter identification information
class ArchitectureGhidra : public Architecture {
istream &sin; ///< Input stream for interfacing with Ghidra
ostream &sout; ///< Output stream for interfacing with Ghidra
mutable string warnings; ///< Warnings accumulated by the decompiler
string pspecxml; ///< XML pspec passed from Ghidra
string cspecxml; ///< XML cspec passed from Ghidra
string tspecxml; ///< Stripped down .sla file passed from Ghidra
string corespecxml; ///< A specification of the core data-types
bool sendsyntaxtree; ///< True if the syntax tree should be sent with function output
bool sendCcode; ///< True if C code should be sent with function output
bool sendParamMeasures; ///< True if measurements for argument and return parameters should be sent
virtual Scope *buildDatabase(DocumentStorage &store);
virtual Translate *buildTranslator(DocumentStorage &store);
virtual void buildLoader(DocumentStorage &store);
virtual PcodeInjectLibrary *buildPcodeInjectLibrary(void);
virtual void buildTypegrp(DocumentStorage &store);
virtual void buildCoreTypes(DocumentStorage &store);
virtual void buildCommentDB(DocumentStorage &store);
virtual void buildStringManager(DocumentStorage &store);
virtual void buildConstantPool(DocumentStorage &store);
virtual void buildContext(DocumentStorage &store);
virtual void buildSymbols(DocumentStorage &store);
virtual void buildSpecFile(DocumentStorage &store);
virtual void modifySpaces(Translate *trans) {} // This is handled directly by GhidraTranslate::initialize
virtual void postSpecFile(void);
virtual void resolveArchitecture(void);
public:
ArchitectureGhidra(const string &pspec,const string &cspec,const string &tspec,const string &corespec,
istream &i,ostream &o);
const string &getWarnings(void) const { return warnings; } ///< Get warnings produced by the last decompilation
void clearWarnings(void) { warnings.clear(); } ///< Clear warnings
bool getRegister(const string &regname,Decoder &decoder); ///< Retrieve a register description given a name
string getRegisterName(const VarnodeData &vndata); ///< Retrieve a register name given its storage location
bool getTrackedRegisters(const Address &addr,Decoder &decoder); ///< Retrieve \e tracked register values at the given address
string getUserOpName(int4 index); ///< Get the name of a user-defined p-code op
bool getPcode(const Address &addr,Decoder &decoder); ///< Get p-code for a single instruction
bool getMappedSymbolsXML(const Address &addr,Decoder &decoder); ///< Get symbols associated with the given address
bool getExternalRef(const Address &addr,Decoder &decoder); ///< Retrieve a description of an external function
bool getNamespacePath(uint8 id,Decoder &decoder); ///< Get a description of a namespace path
bool isNameUsed(const string &nm,uint8 startId,uint8 stopId); ///< Is given name used along namespace path
string getCodeLabel(const Address &addr); ///< Retrieve a label at the given address
bool getDataType(const string &name,uint8 id,Decoder &decoder); ///< Retrieve a data-type description for the given name and id
bool getComments(const Address &fad,uint4 flags,Decoder &decoder); ///< Retrieve comments for a particular function
void getBytes(uint1 *buf,int4 size,const Address &inaddr); ///< Retrieve bytes in the LoadImage at the given address
bool getPcodeInject(const string &name,int4 type,const InjectContext &con,Decoder &decoder);
bool getCPoolRef(const vector<uintb> &refs,Decoder &decoder); ///< Resolve a constant pool reference
// Document *getScopeProperties(Scope *newscope);
/// \brief Toggle whether the data-flow and control-flow is emitted as part of the main decompile action
///
/// If the toggle is \b on, the decompiler will emit complete descriptions of the graphs.
/// \param val is \b true to enable emitting
void setSendSyntaxTree(bool val) { sendsyntaxtree = val; }
bool getSendSyntaxTree(void) const { return sendsyntaxtree; } ///< Get the current setting for emitting data/control-flow.
/// \brief Toggle whether the recovered source code is emitted as part of the main decompile action
///
/// If the toggle is \b on, the decompiler will emit source code (marked up in an XML document)
/// \param val is \b true to enable emitting
void setSendCCode(bool val) { sendCcode = val; }
bool getSendCCode(void) const { return sendCcode; } ///< Get the current setting for emitting source code
/// \brief Toggle whether recovered parameter information is emitted as part of the main decompile action
///
/// If the toggle is \b on, the decompiler will emit a more detailed description of what
/// it thinks the input parameters to the function are.
/// \param val is \b true enable emitting
void setSendParamMeasures(bool val) { sendParamMeasures = val; }
bool getSendParamMeasures(void) const { return sendParamMeasures; } ///< Get the current setting for emitting parameter info
void getStringData(vector<uint1> &buffer,const Address &addr,Datatype *ct,int4 maxBytes,bool &isTrunc);
virtual void printMessage(const string &message) const;
static void segvHandler(int4 sig); ///< Handler for a segment violation (SIGSEGV) signal
static int4 readToAnyBurst(istream &s); ///< Read the next message protocol marker
static bool readBoolStream(istream &s); ///< Read a boolean value from the client
static void readStringStream(istream &s,string &res); ///< Receive a string from the client
static bool readStringStream(istream &s,Decoder &decoder); ///< Receive an encoded string from the client
static void writeStringStream(ostream &s,const string &msg); ///< Send a string to the client
static void readToResponse(istream &s); ///< Read the query response protocol marker
static void readResponseEnd(istream &s); ///< Read the ending query response protocol marker
static bool readAll(istream &s,Decoder &decoder); ///< Read a whole response as an XML document
static void passJavaException(ostream &s,const string &tp,const string &msg);
static bool isDynamicSymbolName(const string &nm); ///< Check if name is of form FUN_.. or DAT_..
};
} // End namespace ghidra
#endif