mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 10:49:34 +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
202
Ghidra/Features/Decompiler/src/decompile/cpp/rulecompile.hh
Normal file
202
Ghidra/Features/Decompiler/src/decompile/cpp/rulecompile.hh
Normal file
|
@ -0,0 +1,202 @@
|
|||
/* ###
|
||||
* 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.
|
||||
*/
|
||||
#ifndef __CPUI_RULE_COMPILE__
|
||||
#define __CPUI_RULE_COMPILE__
|
||||
|
||||
#include "unify.hh"
|
||||
|
||||
class RuleLexer {
|
||||
static int4 identlist[256]; // 1 is identifier, 2 is digit, 4=namechar
|
||||
map<string,int4> keywordmap;
|
||||
istream *s;
|
||||
char identifier[256];
|
||||
int4 identlength;
|
||||
int4 lookahead[4];
|
||||
int4 pos;
|
||||
bool endofstream;
|
||||
int4 lineno;
|
||||
int4 getNextChar(void) {
|
||||
char c;
|
||||
int4 ret = lookahead[pos];
|
||||
if (!endofstream) {
|
||||
(*s).get(c);
|
||||
if ((*s).eof()||(c=='\0')) {
|
||||
endofstream = true;
|
||||
lookahead[pos] = '\n';
|
||||
}
|
||||
else
|
||||
lookahead[pos] = c;
|
||||
}
|
||||
else
|
||||
lookahead[pos] = -1;
|
||||
pos = (pos+1)&3;
|
||||
return ret;
|
||||
}
|
||||
int4 next(int4 i) { return lookahead[(pos+i)&3]; }
|
||||
int4 scanIdentifier(void);
|
||||
int4 scanNumber(void);
|
||||
int4 buildString(int4 tokentype);
|
||||
int4 otherIdentifiers(void);
|
||||
void initKeywords(void);
|
||||
public:
|
||||
RuleLexer(void);
|
||||
void initialize(istream &t);
|
||||
int4 getLineNo(void) { return lineno; }
|
||||
int4 nextToken(void);
|
||||
};
|
||||
|
||||
class DummyTranslate : public Translate {
|
||||
public:
|
||||
virtual void initialize(DocumentStorage &store) {}
|
||||
virtual void addRegister(const string &nm,AddrSpace *base,uintb offset,int4 size) {}
|
||||
virtual const VarnodeData &getRegister(const string &nm) const { throw LowlevelError("Cannot add register to DummyTranslate"); }
|
||||
virtual string getRegisterName(AddrSpace *base,uintb off,int4 size) const { return ""; }
|
||||
virtual void getAllRegisters(map<VarnodeData,string> ®list) const {}
|
||||
virtual void getUserOpNames(vector<string> &res) const {}
|
||||
virtual int4 instructionLength(const Address &baseaddr) const { return -1; }
|
||||
virtual int4 oneInstruction(PcodeEmit &emit,const Address &baseaddr) const { return -1; }
|
||||
virtual int4 printAssembly(AssemblyEmit &emit,const Address &baseaddr) const { return -1; }
|
||||
};
|
||||
|
||||
class RuleCompile {
|
||||
ostream *error_stream;
|
||||
int4 errors;
|
||||
RuleLexer lexer;
|
||||
map<string,int4> namemap;
|
||||
ConstraintGroup *finalrule;
|
||||
vector<OpBehavior *> inst;
|
||||
public:
|
||||
RuleCompile(void);
|
||||
~RuleCompile(void);
|
||||
void ruleError(const char *s);
|
||||
int4 numErrors(void) const { return errors; }
|
||||
int4 getLineNo(void) { return lexer.getLineNo(); }
|
||||
void setFullRule(ConstraintGroup *full) { finalrule = full; }
|
||||
ConstraintGroup *getRule(void) { return finalrule; }
|
||||
ConstraintGroup *releaseRule(void) { ConstraintGroup *res = finalrule; finalrule = (ConstraintGroup *)0; return res; }
|
||||
const map<string,int4> &getNameMap(void) const { return namemap; }
|
||||
|
||||
int4 findIdentifier(string *nm);
|
||||
|
||||
ConstraintGroup *newOp(int4 id);
|
||||
ConstraintGroup *newVarnode(int4 id);
|
||||
ConstraintGroup *newConst(int4 id);
|
||||
|
||||
ConstraintGroup *opCopy(ConstraintGroup *base,int4 opid);
|
||||
ConstraintGroup *opInput(ConstraintGroup *base,int8 *slot,int4 varid);
|
||||
ConstraintGroup *opInputAny(ConstraintGroup *base,int4 varid);
|
||||
ConstraintGroup *opInputConstVal(ConstraintGroup *base,int8 *slot,RHSConstant *rhs);
|
||||
ConstraintGroup *opOutput(ConstraintGroup *base,int4 varid);
|
||||
|
||||
ConstraintGroup *varCopy(ConstraintGroup *base,int4 varid);
|
||||
ConstraintGroup *varConst(ConstraintGroup *base,RHSConstant *ex,RHSConstant *sz);
|
||||
ConstraintGroup *varDef(ConstraintGroup *base,int4 opid);
|
||||
ConstraintGroup *varDescend(ConstraintGroup *base,int4 opid);
|
||||
ConstraintGroup *varUniqueDescend(ConstraintGroup *base,int4 opid);
|
||||
|
||||
ConstraintGroup *opCodeConstraint(ConstraintGroup *base,vector<OpCode> *oplist);
|
||||
ConstraintGroup *opCompareConstraint(ConstraintGroup *base,int4 opid,OpCode opc);
|
||||
ConstraintGroup *varCompareConstraint(ConstraintGroup *base,int4 varid,OpCode opc);
|
||||
ConstraintGroup *constCompareConstraint(ConstraintGroup *base,int4 constid,OpCode opc);
|
||||
ConstraintGroup *constNamedExpression(int4 id,RHSConstant *expr);
|
||||
|
||||
ConstraintGroup *emptyGroup(void);
|
||||
ConstraintGroup *emptyOrGroup(void);
|
||||
ConstraintGroup *mergeGroups(ConstraintGroup *a,ConstraintGroup *b);
|
||||
ConstraintGroup *addOr(ConstraintGroup *base,ConstraintGroup *newor);
|
||||
ConstraintGroup *opCreation(int4 newid,OpCode oc,bool iafter,int4 oldid);
|
||||
ConstraintGroup *newUniqueOut(ConstraintGroup *base,int4 varid,int4 sz);
|
||||
ConstraintGroup *newSetInput(ConstraintGroup *base,RHSConstant *slot,int4 varid);
|
||||
ConstraintGroup *newSetInputConstVal(ConstraintGroup *base,RHSConstant *slot,RHSConstant *val,RHSConstant *sz);
|
||||
ConstraintGroup *removeInput(ConstraintGroup *base,RHSConstant *slot);
|
||||
ConstraintGroup *newSetOpcode(ConstraintGroup *base,OpCode opc);
|
||||
ConstraintGroup *booleanConstraint(bool ist,RHSConstant *expr);
|
||||
|
||||
RHSConstant *constNamed(int4 id);
|
||||
RHSConstant *constAbsolute(int8 *val);
|
||||
RHSConstant *constBinaryExpression(RHSConstant *ex1,OpCode opc,RHSConstant *ex2);
|
||||
RHSConstant *constVarnodeSize(int4 varindex);
|
||||
RHSConstant *dotIdentifier(int4 id,string *str);
|
||||
|
||||
int4 nextToken(void) { return lexer.nextToken(); }
|
||||
|
||||
void setErrorStream(ostream &t) { error_stream = &t; }
|
||||
void run(istream &s,bool debug);
|
||||
void postProcess(void);
|
||||
int4 postProcessRule(vector<OpCode> &opcodelist);
|
||||
static ConstraintGroup *buildUnifyer(const string &rule,const vector<string> &idlist,vector<int4> &res);
|
||||
};
|
||||
|
||||
class RuleGeneric : public Rule { // A user configurable rule, (a rule read in from a file)
|
||||
vector<OpCode> starterops;
|
||||
int4 opinit; // Index of initialized op
|
||||
ConstraintGroup *constraint;
|
||||
UnifyState state;
|
||||
public:
|
||||
RuleGeneric(const string &g,const string &nm,const vector<OpCode> &sops,int4 opi,ConstraintGroup *c);
|
||||
virtual ~RuleGeneric(void) { delete constraint; }
|
||||
virtual Rule *clone(const ActionGroupList &grouplist) const {
|
||||
if (!grouplist.contains(getGroup())) return (Rule *)0; return new RuleGeneric(getGroup(),getName(),starterops,opinit,(ConstraintGroup *)constraint->clone()); }
|
||||
virtual void getOpList(vector<uint4> &oplist) const;
|
||||
virtual int4 applyOp(PcodeOp *op,Funcdata &data);
|
||||
static RuleGeneric *build(const string &nm,const string &gp,const string &content);
|
||||
};
|
||||
|
||||
/*
|
||||
Definition of the language
|
||||
|
||||
Identifiers start with 'o' for named pcodeops
|
||||
'v' for named varnodes
|
||||
'#' for named constants
|
||||
|
||||
A "statement" is a sequence of "steps", ending in a semicolon
|
||||
Steps are sequential, proceeding left to right. Each step is either a
|
||||
building step (which defines a new entity in terms of an existing entity), or a
|
||||
constraint (which forces a condition to be true)
|
||||
|
||||
Building steps:
|
||||
|
||||
o -> v v is the output of o
|
||||
o1 -> o2 o2 is a (named) copy of o1
|
||||
o <- v v is ANY input of o
|
||||
o <-(0) v v is input 0 of o
|
||||
o <-(1) #c input 1 to o is a constant (now named c)
|
||||
o <-(1) #0 input 1 to o is a constant with value 0
|
||||
|
||||
v <- o o is the defining op of v
|
||||
v -> o o is ANY of the ops taking v as an input (may be inefficient)
|
||||
v ->! o o is the one and only op taking v as input
|
||||
v1 -> v2 v2 is a (named) copy of v1
|
||||
|
||||
Constraints:
|
||||
|
||||
o(+) o must have an opcode equal '+'
|
||||
o1(== o2) o1 and o2 must be the same pcode op
|
||||
o1(!= o2) o1 and o2 must not be the same pcode op
|
||||
v1(== v2) v1 and v2 must be the same varnode
|
||||
v1(!= v2) v1 and v2 must not be the same varnode
|
||||
|
||||
Statements can be grouped (into "statementlist") with parentheses '(' and ')'
|
||||
There is an OR operator
|
||||
|
||||
'[' statementlist
|
||||
| statementlist
|
||||
...
|
||||
']'
|
||||
|
||||
*/
|
||||
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue