mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 02:39:44 +02:00
Candidate release of source code.
This commit is contained in:
parent
db81e6b3b0
commit
79d8f164f8
12449 changed files with 2800756 additions and 16 deletions
302
Ghidra/Features/Decompiler/src/decompile/cpp/architecture.hh
Normal file
302
Ghidra/Features/Decompiler/src/decompile/cpp/architecture.hh
Normal file
|
@ -0,0 +1,302 @@
|
|||
/* ###
|
||||
* 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 architecture.hh
|
||||
/// \brief Architecture and associated classes that help manage a single processor architecture and load image
|
||||
#ifndef __CPUI_ARCHITECTURE__
|
||||
#define __CPUI_ARCHITECTURE__
|
||||
|
||||
#include "capability.hh"
|
||||
#include "varmap.hh"
|
||||
#include "action.hh"
|
||||
#include "database.hh"
|
||||
#include "pcodeinject.hh"
|
||||
#include "fspec.hh"
|
||||
#include "translate.hh"
|
||||
#include "loadimage.hh"
|
||||
#include "globalcontext.hh"
|
||||
#include "comment.hh"
|
||||
#include "userop.hh"
|
||||
#include "options.hh"
|
||||
#include "prefersplit.hh"
|
||||
|
||||
#ifdef CPUI_STATISTICS
|
||||
/// \brief Class for collecting statistics while processing over multiple functions
|
||||
///
|
||||
/// As Funcdata objects are transformed, they get fed to the process() method
|
||||
/// to accumulate statistics over the whole run. Results are printed with printResults()
|
||||
class Statistics {
|
||||
uintb numfunc; ///< Number of functions processed
|
||||
uintb numvar; ///< Number of Varnodes analyzed
|
||||
uintb coversum; ///< Number of Varnodes with non-empty covers
|
||||
uintb coversumsq; ///< Internal sum for variance of coversum
|
||||
uintb lastcastcount; ///< Number of casts since processing last function
|
||||
uintb castcount; ///< Total number of casts
|
||||
uintb castcountsq; ///< Internal sum for variance of castcount
|
||||
//void process_cover(const Funcdata &data);
|
||||
void process_cast(const Funcdata &data); ///< Count casts for function
|
||||
public:
|
||||
Statistics(void); ///< Construct initializing counts
|
||||
~Statistics(void); ///< Destructor
|
||||
void countCast(void) { castcount += 1; } ///< Count a single cast
|
||||
void process(const Funcdata &fd); ///< Accumulate statistics for one function
|
||||
void printResults(ostream &s); ///< Display accumulated statistics
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
class Architecture;
|
||||
|
||||
/// \brief Abstract extension point for building Architecture objects
|
||||
///
|
||||
/// Decompilation hinges on initially recognizing the format of code then
|
||||
/// bootstrapping into discovering the processor etc. This is the base class
|
||||
/// for the different extensions that perform this process. Each extension
|
||||
/// implements the buildArchitecture() method as the formal entry point
|
||||
/// for the bootstrapping process.
|
||||
class ArchitectureCapability : public CapabilityPoint {
|
||||
static const uint4 majorversion; ///< Current major version of decompiler
|
||||
static const uint4 minorversion; ///< Current minor version of decompiler
|
||||
static vector<ArchitectureCapability *> thelist; ///< The list of registered extensions
|
||||
protected:
|
||||
string name; ///< Identifier for this capability
|
||||
public:
|
||||
const string &getName(void) const { return name; } ///< Get the capability identifier
|
||||
virtual void initialize(void); ///< Do specialized initialization
|
||||
|
||||
/// \brief Build an Architecture given a raw file or data
|
||||
///
|
||||
/// This is implemented by each separate extension. The method is handed
|
||||
/// a \e filename and possibly external target information and must build
|
||||
/// the Architecture object, initializing all the major subcomponents, using just this info.
|
||||
/// \param filename is the path to the executable file to examine
|
||||
/// \param target if non-empty is a language id string
|
||||
/// \param estream is an output stream for error messages
|
||||
virtual Architecture *buildArchitecture(const string &filename,const string &target,ostream *estream)=0;
|
||||
|
||||
/// \brief Determine if this extension can handle this file
|
||||
///
|
||||
/// \param filename is the name of the file to examine
|
||||
/// \return \b true is \b this extension is suitable for analyzing the file
|
||||
virtual bool isFileMatch(const string &filename) const=0;
|
||||
|
||||
/// \brief Determine is this extension can handle this XML document
|
||||
///
|
||||
/// If a file to analyze is XML based, this method examines the XML parse
|
||||
/// to determine if \b this extension can understand the document
|
||||
/// \param doc is the parsed XML document
|
||||
/// \return \b true if \b this extension understands the XML
|
||||
virtual bool isXmlMatch(Document *doc) const=0;
|
||||
|
||||
static ArchitectureCapability *findCapability(const string &filename); ///< Find an extension to process a file
|
||||
static ArchitectureCapability *findCapability(Document *doc); ///< Find an extension to process an XML document
|
||||
static void sortCapabilities(void); ///< Sort extensions
|
||||
static uint4 getMajorVersion(void) { return majorversion; } ///< Get \e major decompiler version
|
||||
static uint4 getMinorVersion(void) { return minorversion; } ///< Get \e minor decompiler version
|
||||
};
|
||||
|
||||
/// \brief Manager for all the major decompiler subsystems
|
||||
///
|
||||
/// An instantiation is tailored to a specific LoadImage,
|
||||
/// processor, and compiler spec. This class is the \e owner of
|
||||
/// the LoadImage, Translate, symbols (Database), PrintLanguage, etc.
|
||||
/// This class also holds numerous configuration parameters for the analysis process
|
||||
class Architecture : public AddrSpaceManager {
|
||||
public:
|
||||
string archid; ///< ID string uniquely describing this architecture
|
||||
string description; ///< Description of architecture
|
||||
string version; ///< Configuration version
|
||||
|
||||
// Configuration data
|
||||
int4 trim_recurse_max; ///< How many levels to let parameter trims recurse
|
||||
int4 max_implied_ref; ///< Maximum number of references to an implied var
|
||||
int4 max_term_duplication; ///< Max terms duplicated without a new variable
|
||||
int4 max_basetype_size; ///< Maximum size of an "integer" type before creating an array type
|
||||
int4 min_funcsymbol_size; ///< Minimum size of a function symbol
|
||||
bool aggressive_ext_trim; ///< Aggressively trim inputs that look like they are sign extended
|
||||
bool readonlypropagate; ///< true if readonly values should be treated as constants
|
||||
bool infer_pointers; ///< True if we should infer pointers from constants that are likely addresses
|
||||
uintb pointer_lowerbound; ///< Zero or lowest value that can be inferred as an address
|
||||
int4 funcptr_align; ///< How many bits of alignment a function ptr has
|
||||
uint4 flowoptions; ///< options passed to flow following engine
|
||||
vector<Rule *> extra_pool_rules; ///< Extra rules that go in the main pool (cpu specific, experimental)
|
||||
|
||||
Database *symboltab; ///< Memory map of global variables and functions
|
||||
ContextDatabase *context; ///< Map from addresses to context settings
|
||||
map<string,ProtoModel *> protoModels; ///< Parsed forms of possible prototypes
|
||||
ProtoModel *defaultfp; ///< Parsed form of default prototype
|
||||
VarnodeData defaultReturnAddr; ///< Default storage location of return address (for current function)
|
||||
ProtoModel *evalfp_current; ///< Function proto to use when evaluating current function
|
||||
ProtoModel *evalfp_called; ///< Function proto to use when evaluating called functions
|
||||
TypeFactory *types; ///< List of types for this binary
|
||||
const Translate *translate; ///< Translation method for this binary
|
||||
LoadImage *loader; ///< Method for loading portions of binary
|
||||
PcodeInjectLibrary *pcodeinjectlib; ///< Pcode injection manager
|
||||
RangeList nohighptr; ///< Ranges for which high-level pointers are not possible
|
||||
CommentDatabase *commentdb; ///< Comments for this architecture
|
||||
ConstantPool *cpool; ///< Deferred constant values
|
||||
PrintLanguage *print; ///< Current high-level language printer
|
||||
vector<PrintLanguage *> printlist; ///< List of high-level language printers supported
|
||||
OptionDatabase *options; ///< Options that can be configured
|
||||
vector<TypeOp *> inst; ///< Registered p-code instructions
|
||||
UserOpManage userops; ///< Specifically registered user-defined p-code ops
|
||||
vector<PreferSplitRecord> splitrecords; ///< registers that we would prefer to see split for this processor
|
||||
ActionDatabase allacts; ///< Actions that can be applied in this architecture
|
||||
bool loadersymbols_parsed; ///< True if loader symbols have been read
|
||||
#ifdef CPUI_STATISTICS
|
||||
Statistics *stats; ///< Statistics collector
|
||||
#endif
|
||||
#ifdef OPACTION_DEBUG
|
||||
ostream *debugstream; ///< The error console
|
||||
#endif
|
||||
Architecture(void); ///< Construct an uninitialized Architecture
|
||||
void init(DocumentStorage &store); ///< Load the image and configure architecture
|
||||
ProtoModel *getModel(const string &nm) const; ///< Get a specific PrototypeModel
|
||||
bool hasModel(const string &nm) const; ///< Does this Architecture have a specific PrototypeModel
|
||||
bool highPtrPossible(const Address &loc,int4 size) const; ///< Are pointers possible to the given location?
|
||||
AddrSpace *getSpaceBySpacebase(const Address &loc,int4 size) const; ///< Get space associated with a \e spacebase register
|
||||
void setDefaultModel(const string &nm); ///< Set the default PrototypeModel
|
||||
void clearAnalysis(Funcdata *fd); ///< Clear analysis specific to a function
|
||||
void readLoaderSymbols(void); ///< Read any symbols from loader into database
|
||||
void collectBehaviors(vector<OpBehavior *> &behave) const; ///< Provide a list of OpBehavior objects
|
||||
bool hasNearPointers(AddrSpace *spc) const; ///< Does the given address space support \e near pointers
|
||||
void setPrototype(const PrototypePieces &pieces); ///< Set the prototype for a particular function
|
||||
void setPrintLanguage(const string &nm); ///< Establish a particular output language
|
||||
void globalify(void); ///< Mark \e all spaces as global
|
||||
void restoreFlowOverride(const Element *el); ///< Set flow overrides from XML
|
||||
virtual ~Architecture(void); ///< Destructor
|
||||
|
||||
/// \brief Print an error message to console
|
||||
///
|
||||
/// Write the given message to whatever the registered error stream is
|
||||
/// \param message is the error message
|
||||
virtual void printMessage(const string &message) const=0;
|
||||
virtual void saveXml(ostream &s) const; ///< Serialize this architecture to XML
|
||||
virtual void restoreXml(DocumentStorage &store); ///< Restore the Architecture state from an XML stream
|
||||
virtual void nameFunction(const Address &addr,string &name) const; ///< Pick a default name for a function
|
||||
#ifdef OPACTION_DEBUG
|
||||
void setDebugStream(ostream *s) { debugstream = s; } ///< Establish the debug console stream
|
||||
void printDebug(const string &message) const { *debugstream << message << endl; } ///< Print message to the debug stream
|
||||
#endif
|
||||
protected:
|
||||
void addSpacebase(AddrSpace *basespace,const string &nm,const VarnodeData &ptrdata,
|
||||
int4 truncSize,bool isreversejustified,bool stackGrowth); ///< Create a new space and associated pointer
|
||||
void addNoHighPtr(const Range &rng); ///< Add a new region where pointers do not exist
|
||||
|
||||
// Factory routines for building this architecture
|
||||
virtual Scope *buildGlobalScope(void); ///< Build the global scope for this executable
|
||||
|
||||
/// \brief Build the Translator object
|
||||
///
|
||||
/// This builds the main disassembly component for the Architecture
|
||||
/// This does \e not initially the engine for a specific processor.
|
||||
/// \param store may hold configuration information
|
||||
/// \return the Translate object
|
||||
virtual Translate *buildTranslator(DocumentStorage &store)=0;
|
||||
|
||||
/// \brief Build the LoadImage object and load the executable image
|
||||
///
|
||||
/// \param store may hold configuration information
|
||||
virtual void buildLoader(DocumentStorage &store)=0;
|
||||
|
||||
/// \brief Build the injection library
|
||||
///
|
||||
/// This creates the container for p-code injections. It is initially empty.
|
||||
/// \return the PcodeInjectLibrary object
|
||||
virtual PcodeInjectLibrary *buildPcodeInjectLibrary(void)=0;
|
||||
|
||||
virtual void buildTypegrp(DocumentStorage &store); ///< Build the data-type factory/container
|
||||
virtual void buildCommentDB(DocumentStorage &store); ///< Build the comment database
|
||||
virtual void buildConstantPool(DocumentStorage &store); ///< Build the constant pool
|
||||
virtual void buildInstructions(DocumentStorage &store); ///< Register the p-code operations
|
||||
virtual void buildAction(DocumentStorage &store); ///< Build the Action framework
|
||||
virtual void buildContext(DocumentStorage &store); ///< Build the Context database
|
||||
|
||||
/// \brief Load any relevant specification files
|
||||
///
|
||||
/// Processor/architecture specific configuration files are loaded into the XML store
|
||||
/// \param store is the document store that will hold the configuration
|
||||
virtual void buildSpecFile(DocumentStorage &store)=0;
|
||||
|
||||
/// \brief Modify address spaces as required by \b this Architecture
|
||||
///
|
||||
/// If spaces need to be truncated or otherwise changed from processor defaults,
|
||||
/// this routine performs the modification.
|
||||
/// \param trans is the processor disassembly object
|
||||
virtual void modifySpaces(Translate *trans)=0;
|
||||
|
||||
virtual void postSpecFile(void) {} ///< Let components initialize after Translate is built
|
||||
|
||||
|
||||
virtual void resolveArchitecture(void)=0; ///< Figure out the processor and compiler of the target executable
|
||||
|
||||
void restoreFromSpec(DocumentStorage &store); ///< Fully initialize the Translate object
|
||||
void fillinReadOnlyFromLoader(void); ///< Load info about read-only sections
|
||||
void initializeSegments(); ///< Set up segment resolvers
|
||||
|
||||
void parseProcessorConfig(DocumentStorage &store); ///< Apply processor specific configuration
|
||||
void parseCompilerConfig(DocumentStorage &store); ///< Apply compiler specific configuration
|
||||
void parseExtraRules(DocumentStorage &store); ///< Apply any Rule tags
|
||||
|
||||
void parseDynamicRule(const Element *el); ///< Apply details of a dynamic Rule object
|
||||
ProtoModel *parseProto(const Element *el); ///< Build a proto-type model from an XML tag
|
||||
void parseProtoEval(const Element *el); ///< Apply prototype evaluation configuration
|
||||
void parseDefaultProto(const Element *el); ///< Apply default prototype model configuration
|
||||
void parseGlobal(const Element *el); ///< Apply global space configuration
|
||||
void parseReadOnly(const Element *el); ///< Apply read-only region configuration
|
||||
void parseVolatile(const Element *el); ///< Apply volatile region configuration
|
||||
void parseReturnAddress(const Element *el); ///< Apply return address configuration
|
||||
void parseIncidentalCopy(const Element *el); ///< Apply incidental copy configuration
|
||||
void parseStackPointer(const Element *el); ///< Apply stack pointer configuration
|
||||
void parseDeadcodeDelay(const Element *el); ///< Apply dead-code delay configuration
|
||||
void parseFuncPtrAlign(const Element *el); ///< Apply function pointer alignment configuration
|
||||
void parseSpacebase(const Element *el); ///< Create an additional indexed space
|
||||
void parseNoHighPtr(const Element *el); ///< Apply memory alias configuration
|
||||
void parsePreferSplit(const Element *el); ///< Designate registers to be split
|
||||
void parseAggressiveTrim(const Element *el); ///< Designate how to trim extension p-code ops
|
||||
};
|
||||
|
||||
/// \brief A resolver for segmented architectures
|
||||
///
|
||||
/// When the decompiler is attempting to resolve embedded constants as pointers,
|
||||
/// this class tries to recover segment info for near pointers by looking up
|
||||
/// tracked registers in context
|
||||
class SegmentedResolver : public AddressResolver {
|
||||
Architecture *glb; ///< The architecture owning the segmented space
|
||||
AddrSpace *spc; ///< The address space being segmented
|
||||
SegmentOp *segop; ///< The segment operator
|
||||
public:
|
||||
/// Construct a segmented resolver
|
||||
/// \param g is the owning Architecture
|
||||
/// \param sp is the segmented space
|
||||
/// \param sop is the segment operator
|
||||
SegmentedResolver(Architecture *g,AddrSpace *sp,SegmentOp *sop) { glb=g; spc=sp; segop=sop; }
|
||||
virtual Address resolve(uintb val,int4 sz,const Address &point);
|
||||
};
|
||||
|
||||
/// The Translate object keeps track of address ranges for which
|
||||
/// it is effectively impossible to have a pointer into. This is
|
||||
/// used for pointer aliasing calculations. This routine returns
|
||||
/// \b true if it is \e possible to have pointers into the indicated
|
||||
/// range.
|
||||
/// \param loc is the starting address of the range
|
||||
/// \param size is the size of the range in bytes
|
||||
/// \return \b true if pointers are possible
|
||||
inline bool Architecture::highPtrPossible(const Address &loc,int4 size) const {
|
||||
if (loc.getSpace()->getType() == IPTR_INTERNAL) return false;
|
||||
return !nohighptr.inRange(loc,size);
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue