Ghidra Decompiler Analysis Engine
slgh_compile.hh
1 /* ###
2  * IP: GHIDRA
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #include "sleighbase.hh"
17 #include "pcodecompile.hh"
18 #include "filemanage.hh"
19 #include <iostream>
20 #include <sstream>
21 
22 // High-level control of the sleigh compilation process
23 
24 struct RtlPair {
25  ConstructTpl *section; // A p-code section
26  SymbolScope *scope; // and its associated symbol scope
27  RtlPair(void) { section = (ConstructTpl *)0; scope = (SymbolScope *)0; }
28  RtlPair(ConstructTpl *sec,SymbolScope *sc) { section = sec; scope = sc; }
29 };
30 
32  int4 nextindex;
33  RtlPair main;
34  vector<RtlPair> named;
35 public:
37  ConstructTpl *getMainSection(void) const { return main.section; }
38  ConstructTpl *getNamedSection(int4 index) const { return named[index].section; }
39  RtlPair getMainPair(void) const { return main; }
40  RtlPair getNamedPair(int4 i) const { return named[i]; }
41  void setNextIndex(int4 i) { nextindex = i; }
42  int4 getMaxId(void) const { return named.size(); }
43  void append(ConstructTpl *rtl,SymbolScope *scope);
44 };
45 
46 struct SpaceQuality { // Qualities of an address space
47  enum { // Class of space
48  ramtype,
49  registertype
50  };
51  string name;
52  uint4 type;
53  uint4 size;
54  uint4 wordsize; // number of bytes in unit of the space
55  bool isdefault;
56  SpaceQuality(const string &nm);
57 };
58 
59 struct FieldQuality {
60  string name;
61  uint4 low,high;
62  bool signext;
63  bool flow;
64  bool hex;
65  FieldQuality(string *nm,uintb *l,uintb *h);
66 };
67 
68 class WithBlock {
69  SubtableSymbol *ss;
70  PatternEquation *pateq;
71  vector<ContextChange *> contvec;
72 public:
73  WithBlock(void) { pateq = (PatternEquation *)0; }
74  void set(SubtableSymbol *s, PatternEquation *pq, vector<ContextChange *> *cvec);
75  ~WithBlock(void);
76  static PatternEquation *collectAndPrependPattern(const list<WithBlock> &stack, PatternEquation *pateq);
77  static vector<ContextChange *> *collectAndPrependContext(const list<WithBlock> &stack, vector<ContextChange *> *contvec);
78  static SubtableSymbol *getCurrentSubtable(const list<WithBlock> &stack);
79 };
80 
81 class SleighCompile;
82 
84  struct OptimizeRecord {
85  int4 writeop;
86  int4 readop;
87  int4 inslot;
88  int4 writecount;
89  int4 readcount;
90  int4 writesection;
91  int4 readsection;
92  int4 opttype;
93  OptimizeRecord(void) {
94  writeop = -1; readop = -1; inslot=-1; writecount=0; readcount=0; writesection=-2; readsection=-2; opttype=-1; }
95  };
96  SleighCompile *compiler;
97  int4 unnecessarypcode;
98  int4 readnowrite;
99  int4 writenoread;
100  int4 largetemp;
101  bool printextwarning;
102  bool printdeadwarning;
103  bool printlargetempwarning;
104  SubtableSymbol *root_symbol;
105  vector<SubtableSymbol *> postorder;
106  map<SubtableSymbol *,int4> sizemap; // Sizes associated with tables
107  OperandSymbol *getOperandSymbol(int4 slot,OpTpl *op,Constructor *ct);
108  void printOpName(ostream &s,OpTpl *op);
109  void printOpError(OpTpl *op,Constructor *ct,int4 err1,int4 err2,const string &message);
110  int4 recoverSize(const ConstTpl &sizeconst,Constructor *ct);
111  bool checkOpMisuse(OpTpl *op,Constructor *ct);
112  bool sizeRestriction(OpTpl *op,Constructor *ct);
113  bool checkConstructorSection(Constructor *ct,ConstructTpl *cttpl);
114  bool hasLargeTemporary(OpTpl *op);
115  bool isTemporaryAndTooBig(VarnodeTpl *vn);
116  bool checkVarnodeTruncation(Constructor *ct,int4 slot,OpTpl *op,VarnodeTpl *vn,bool isbigendian);
117  bool checkSectionTruncations(Constructor *ct,ConstructTpl *cttpl,bool isbigendian);
118  bool checkSubtable(SubtableSymbol *sym);
119  void dealWithUnnecessaryExt(OpTpl *op,Constructor *ct);
120  void dealWithUnnecessaryTrunc(OpTpl *op,Constructor *ct);
121  void setPostOrder(SubtableSymbol *root); // Establish table ordering
122 
123  // Optimization routines
124  static void examineVn(map<uintb,OptimizeRecord> &recs,const VarnodeTpl *vn,uint4 i,int4 inslot,int4 secnum);
125  static bool possibleIntersection(const VarnodeTpl *vn1,const VarnodeTpl *vn2);
126  bool readWriteInterference(const VarnodeTpl *vn,const OpTpl *op,bool checkread) const;
127  void optimizeGather1(Constructor *ct,map<uintb,OptimizeRecord> &recs,int4 secnum) const;
128  void optimizeGather2(Constructor *ct,map<uintb,OptimizeRecord> &recs,int4 secnum) const;
129  OptimizeRecord *findValidRule(Constructor *ct,map<uintb,OptimizeRecord> &recs) const;
130  void applyOptimization(Constructor *ct,const OptimizeRecord &rec);
131  void checkUnusedTemps(Constructor *ct,const map<uintb,OptimizeRecord> &recs);
132  void checkLargeTemporaries(Constructor *ct);
133  void optimize(Constructor *ct);
134 public:
135  ConsistencyChecker(SleighCompile *sleigh, SubtableSymbol *rt,bool unnecessary,bool warndead, bool warnlargetemp);
136  bool test(void);
137  bool testTruncations(bool isbigendian);
138  void optimizeAll(void);
139  int4 getNumUnnecessaryPcode(void) const { return unnecessarypcode; }
140  int4 getNumReadNoWrite(void) const { return readnowrite; }
141  int4 getNumWriteNoRead(void) const { return writenoread; }
142  int4 getNumLargeTemporaries(void) const {return largetemp;}
143 };
144 
145 struct FieldContext {
146  VarnodeSymbol *sym;
147  FieldQuality *qual;
148  bool operator<(const FieldContext &op2) const;
149  FieldContext(VarnodeSymbol *s,FieldQuality *q) { sym=s; qual=q; }
150 };
151 
152 class MacroBuilder : public PcodeBuilder {
153  SleighCompile *slgh;
154  bool haserror;
155  vector<OpTpl *> &outvec;
156  vector<HandleTpl *> params;
157  bool transferOp(OpTpl *op,vector<HandleTpl *> &params);
158  virtual void dump( OpTpl *op );
159  void free(void);
160  void reportError(const Location* loc, const string &val);
161 public:
162  MacroBuilder(SleighCompile *sl,vector<OpTpl *> &ovec,uint4 lbcnt) : PcodeBuilder(lbcnt),outvec(ovec) {
163  slgh = sl; haserror = false; }
164  void setMacroOp(OpTpl *macroop);
165  bool hasError(void) const { return haserror; }
166  virtual ~MacroBuilder(void) { free(); }
167  virtual void appendBuild(OpTpl *bld,int4 secnum) { dump(bld); }
168  virtual void delaySlot(OpTpl *op) { dump(op); }
169  virtual void setLabel(OpTpl *op);
170  virtual void appendCrossBuild(OpTpl *bld,int4 secnum) { dump(bld); }
171 };
172 
173 class SleighPcode : public PcodeCompile {
174  SleighCompile *compiler;
175  virtual uintb allocateTemp(void);
176  virtual const Location *getLocation(SleighSymbol *sym) const;
177  virtual void reportError(const Location* loc, const string &msg);
178  virtual void reportWarning(const Location* loc, const string &msg);
179  virtual void addSymbol(SleighSymbol *sym);
180 public:
181  SleighPcode(void) : PcodeCompile() { compiler = (SleighCompile *)0; }
182  void setCompiler(SleighCompile *comp) { compiler = comp; }
183 };
184 
185 class SleighCompile : public SleighBase {
186  friend class SleighPcode;
187 public:
188  SleighPcode pcode;
189 private:
190  map<string,string> preproc_defines; // Defines for the preprocessor
191  vector<FieldContext> contexttable;
192  vector<ConstructTpl *> macrotable;
193  vector<Token *> tokentable;
194  vector<SubtableSymbol *> tables;
195  vector<SectionSymbol *> sections;
196  list<WithBlock> withstack;
197  Constructor *curct; // Current constructor being defined
198  MacroSymbol *curmacro; // Current macro being defined
199  bool contextlock; // If the context layout has been established yet
200  vector<string> relpath; // Relative path (to cwd) for each filename
201  vector<string> filename; // Stack of current files being parsed
202  vector<int4> lineno; // Current line number for each file in stack
203  map<Constructor *, Location> ctorLocationMap; // Map constructor to its defining parse location
204  map<SleighSymbol *, Location> symbolLocationMap; // Map symbol to its defining parse location
205  int4 userop_count; // Number of userops defined
206  bool warnunnecessarypcode; // True if we warn of unnecessary ZEXT or SEXT
207  bool warndeadtemps; // True if we warn of temporaries that are written but not read
208  bool lenientconflicterrors; // True if we ignore most pattern conflict errors
209  bool largetemporarywarning; // True if we warn about temporaries larger than SleighBase::MAX_UNIQUE_SIZE
210  bool warnalllocalcollisions; // True if local export collisions generate individual warnings
211  bool warnallnops; // True if pcode NOPs generate individual warnings
212  vector<string> noplist; // List of individual NOP warnings
213  mutable Location currentLocCache; // Location for (last) request of current location
214  int4 errors;
215 
216  const Location* getCurrentLocation(void) const;
217  void predefinedSymbols(void);
218  int4 calcContextVarLayout(int4 start,int4 sz,int4 numbits);
219  void buildDecisionTrees(void);
220  void buildPatterns(void);
221  void checkConsistency(void);
222  static int4 findCollision(map<uintb,int4> &local2Operand,const vector<uintb> &locals,int operand);
223  bool checkLocalExports(Constructor *ct);
224  void checkLocalCollisions(void);
225  void checkNops(void);
226  string checkSymbols(SymbolScope *scope);
227  void addSymbol(SleighSymbol *sym);
228  SleighSymbol *dedupSymbolList(vector<SleighSymbol *> *symlist);
229  bool expandMacros(ConstructTpl *ctpl,const vector<ConstructTpl *> &macrotable);
230  bool finalizeSections(Constructor *big,SectionVector *vec);
231  static void shiftUniqueVn(VarnodeTpl *vn,int4 sa);
232  static void shiftUniqueOp(OpTpl *op,int4 sa);
233  static void shiftUniqueHandle(HandleTpl *hand,int4 sa);
234  static void shiftUniqueConstruct(ConstructTpl *tpl,int4 sa);
235  void checkUniqueAllocation(void);
236 public:
237  SleighCompile(void);
238  const Location *getLocation(Constructor* ctor) const;
239  const Location *getLocation(SleighSymbol *sym) const;
240  string formatStatusMessage(const Location* loc, const string &msg);
241  void reportError(const string &msg);
242  void reportError(const Location *loc, const string &msg);
243  void reportWarning(const string &msg);
244  void reportWarning(const Location *loc, const string &msg);
245  int4 numErrors(void) const { return errors; }
246  void reportInfo(const string &msg);
247  void reportInfo(const Location *loc, const string &msg);
248 
249 
250  uintb getUniqueAddr(void);
251  void setUnnecessaryPcodeWarning(bool val) { warnunnecessarypcode = val; }
252  void setDeadTempWarning(bool val) { warndeadtemps = val; }
253  void setEnforceLocalKeyWord(bool val) { pcode.setEnforceLocalKey(val); }
254  void setLargeTemporaryWarning (bool val) {largetemporarywarning = val;}
255  void setLenientConflict(bool val) { lenientconflicterrors = val; }
256  void setLocalCollisionWarning(bool val) { warnalllocalcollisions = val; }
257  void setAllNopWarning(bool val) { warnallnops = val; }
258  void process(void);
259 
260  // Lexer functions
261  void calcContextLayout(void);
262  string grabCurrentFilePath(void) const;
263  void parseFromNewFile(const string &fname);
264  void parsePreprocMacro(void);
265  void parseFileFinished(void);
266  void nextLine(void) { lineno.back() += 1; }
267  bool getPreprocValue(const string &nm,string &res) const;
268  void setPreprocValue(const string &nm,const string &value);
269  bool undefinePreprocValue(const string &nm);
270 
271  // Parser functions
272  TokenSymbol *defineToken(string *name,uintb *sz,int4 endian);
273  void addTokenField(TokenSymbol *sym,FieldQuality *qual);
274  bool addContextField(VarnodeSymbol *sym,FieldQuality *qual);
275  void newSpace(SpaceQuality *qual);
276  SectionSymbol *newSectionSymbol(const string &nm);
277  void setEndian(int4 end);
278  void setAlignment(int4 val) { alignment = val; }
279  void defineVarnodes(SpaceSymbol *spacesym,uintb *off,uintb *size,vector<string> *names);
280  void defineBitrange(string *name,VarnodeSymbol *sym,uint4 bitoffset,uint4 numb);
281  void addUserOp(vector<string> *names);
282  void attachValues(vector<SleighSymbol *> *symlist,vector<intb> *numlist);
283  void attachNames(vector<SleighSymbol *> *symlist,vector<string> *names);
284  void attachVarnodes(vector<SleighSymbol *> *symlist,vector<SleighSymbol *> *varlist);
285  SubtableSymbol *newTable(string *nm);
286  void newOperand(Constructor *ct,string *nm);
287  VarnodeTpl *addressOf(VarnodeTpl *var,uint4 size);
288  PatternEquation *constrainOperand(OperandSymbol *sym,PatternExpression *patexp);
289  void defineOperand(OperandSymbol *sym,PatternExpression *patexp);
290  PatternEquation *defineInvisibleOperand(TripleSymbol *sym);
291  void selfDefine(OperandSymbol *sym);
292  ConstructTpl *setResultVarnode(ConstructTpl *ct,VarnodeTpl *vn);
293  ConstructTpl *setResultStarVarnode(ConstructTpl *ct,StarQuality *star,VarnodeTpl *vn);
294  bool contextMod(vector<ContextChange *> *vec,ContextSymbol *sym,PatternExpression *pe);
295  void contextSet(vector<ContextChange *> *vec,TripleSymbol *sym,ContextSymbol *cvar);
296  MacroSymbol *createMacro(string *name,vector<string> *param);
297  void compareMacroParams(MacroSymbol *sym,const vector<ExprTree *> &param);
298  vector<OpTpl *> *createMacroUse(MacroSymbol *sym,vector<ExprTree *> *param);
299  SectionVector *standaloneSection(ConstructTpl *main);
300  SectionVector *firstNamedSection(ConstructTpl *main,SectionSymbol *sym);
301  SectionVector *nextNamedSection(SectionVector *vec,ConstructTpl *section,SectionSymbol *sym);
302  SectionVector *finalNamedSection(SectionVector *vec,ConstructTpl *section);
303  vector<OpTpl *> *createCrossBuild(VarnodeTpl *addr,SectionSymbol *sym);
304  Constructor *createConstructor(SubtableSymbol *sym);
305  bool isInRoot(Constructor *ct) const { return (root == ct->getParent()); }
306  void resetConstructors(void);
307  void pushWith(SubtableSymbol *ss,PatternEquation *pateq,vector<ContextChange *> *contvec);
308  void popWith(void);
309  void buildConstructor(Constructor *big,PatternEquation *pateq,vector<ContextChange *> *contvec,SectionVector *vec);
310  void buildMacro(MacroSymbol *sym,ConstructTpl *rtl);
311  void recordNop(void);
312 
313  // Virtual functions (not used by the compiler)
314  virtual void initialize(DocumentStorage &store) {}
315  virtual int4 instructionLength(const Address &baseaddr) const { return 0; }
316  virtual int4 oneInstruction(PcodeEmit &emit,const Address &baseaddr) const { return 0; }
317  virtual int4 printAssembly(AssemblyEmit &emit,const Address &baseaddr) const { return 0; }
318 };
319 
320 extern SleighCompile *slgh;
321 extern int yydebug;
ContextSymbol
Definition: slghsymbol.hh:279
SleighCompile::initialize
virtual void initialize(DocumentStorage &store)
Initialize the translator given XML configuration documents.
Definition: slgh_compile.hh:314
PatternExpression
Definition: slghpatexpress.hh:56
PcodeEmit
Abstract class for emitting pcode to an application.
Definition: translate.hh:76
Constructor
Definition: slghsymbol.hh:466
Translate::alignment
int4 alignment
Byte modulo on which instructions are aligned.
Definition: translate.hh:298
ConstTpl
Definition: semantics.hh:31
SleighPcode
Definition: slgh_compile.hh:173
SleighCompile::instructionLength
virtual int4 instructionLength(const Address &baseaddr) const
Get the length of a machine instruction.
Definition: slgh_compile.hh:315
AssemblyEmit
Abstract class for emitting disassembly to an application.
Definition: translate.hh:118
PatternEquation
Definition: slghpatexpress.hh:336
SleighCompile
Definition: slgh_compile.hh:185
TripleSymbol
Definition: slghsymbol.hh:146
VarnodeTpl
Definition: semantics.hh:77
VarnodeSymbol
Definition: slghsymbol.hh:245
OperandSymbol
Definition: slghsymbol.hh:313
FieldQuality
Definition: slgh_compile.hh:59
PcodeCompile
Definition: pcodecompile.hh:55
OpTpl
Definition: semantics.hh:137
MacroBuilder
Definition: slgh_compile.hh:152
RtlPair
Definition: slgh_compile.hh:24
ConsistencyChecker
Definition: slgh_compile.hh:83
HandleTpl
Definition: semantics.hh:107
SubtableSymbol
Definition: slghsymbol.hh:564
ConsistencyChecker::ConsistencyChecker
ConsistencyChecker(SleighCompile *sleigh, SubtableSymbol *rt, bool unnecessary, bool warndead, bool warnlargetemp)
Definition: slgh_compile.cc:186
sleighbase.hh
Base class for applications that process SLEIGH format specifications.
SectionVector
Definition: slgh_compile.hh:31
Location
Definition: pcodecompile.hh:21
SectionSymbol
Definition: slghsymbol.hh:116
FieldContext
Definition: slgh_compile.hh:145
Address
A low-level machine address for labelling bytes and data.
Definition: address.hh:46
SleighBase::root
SubtableSymbol * root
The root SLEIGH decoding symbol.
Definition: sleighbase.hh:62
SleighCompile::oneInstruction
virtual int4 oneInstruction(PcodeEmit &emit, const Address &baseaddr) const
Transform a single machine instruction into pcode.
Definition: slgh_compile.hh:316
SymbolScope
Definition: slghsymbol.hh:54
TokenSymbol
Definition: slghsymbol.hh:107
SleighCompile::printAssembly
virtual int4 printAssembly(AssemblyEmit &emit, const Address &baseaddr) const
Disassemble a single machine instruction.
Definition: slgh_compile.hh:317
SleighBase
Common core of classes that read or write SLEIGH specification files natively.
Definition: sleighbase.hh:57
MacroSymbol
Definition: slghsymbol.hh:595
DocumentStorage
A container for parsed XML documents.
Definition: xml.hh:249
ConstructTpl
Definition: semantics.hh:161
PcodeBuilder
Definition: semantics.hh:192
SleighSymbol
Definition: slghsymbol.hh:23
SpaceQuality
Definition: slgh_compile.hh:46
WithBlock
Definition: slgh_compile.hh:68
SpaceSymbol
Definition: slghsymbol.hh:99
StarQuality
Definition: pcodecompile.hh:32