Ghidra Decompiler Analysis Engine
heritage.hh
Go to the documentation of this file.
1 /* ###
2  * IP: GHIDRA
3  * NOTE: Phi placement and renaming based on ACM journal articles
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
19 
20 #ifndef __CPUI_HERITAGE__
21 #define __CPUI_HERITAGE__
22 
23 #include "block.hh"
24 
27 typedef map<Address,vector<Varnode *> > VariableStack;
28 
30 struct SizePass {
31  int4 size;
32  int4 pass;
33 };
34 
42 class LocationMap {
43 public:
45  typedef map<Address,SizePass>::iterator iterator;
46 private:
47  map<Address,SizePass> themap;
48 public:
49  iterator add(Address addr,int4 size,int4 pass,int4 &intersect);
50  iterator find(const Address &addr);
51  int4 findPass(const Address &addr) const;
52  void erase(iterator iter) { themap.erase(iter); }
53  iterator begin(void) { return themap.begin(); }
54  iterator end(void) { return themap.end(); }
55  void clear(void) { themap.clear(); }
56 };
57 
65  vector<vector<FlowBlock *> > queue;
66  int4 curdepth;
67 public:
68  PriorityQueue(void) { curdepth = -2; }
69  void reset(int4 maxdepth);
70  void insert(FlowBlock *bl,int4 depth);
71  FlowBlock *extract(void);
72  bool empty(void) const { return (curdepth==-1); }
73 };
74 
75 class Funcdata;
76 class FuncCallSpecs;
77 
85 class HeritageInfo {
86  friend class Heritage;
87  AddrSpace *space;
88  int4 delay;
89  int4 deadcodedelay;
90  int4 deadremoved;
91  bool loadGuardSearch;
92  bool warningissued;
93  void set(AddrSpace *spc,int4 dl,int4 dcdl) {
94  space=spc; delay=dl; deadcodedelay=dcdl; deadremoved=0; warningissued=false; loadGuardSearch = false; }
95  bool isHeritaged(void) const { return (space != (AddrSpace *)0); }
96  void reset(void) {
97  deadremoved = 0; deadcodedelay = delay; warningissued = false; loadGuardSearch = false; }
98 };
99 
105 class LoadGuard {
106  friend class Heritage;
107  PcodeOp *op;
108  AddrSpace *spc;
109  uintb pointerBase;
110  uintb minimumOffset;
111  uintb maximumOffset;
112  int4 step;
113  int4 analysisState;
114  void establishRange(const ValueSetRead &valueSet);
115  void finalizeRange(const ValueSetRead &valueSet);
116 
122  void set(PcodeOp *o,AddrSpace *s,uintb off) {
123  op = o; spc = s; pointerBase=off; minimumOffset=0; maximumOffset=s->getHighest(); step=0; analysisState=0;
124  }
125 public:
126  PcodeOp *getOp(void) const { return op; }
127  uintb getMinimum(void) const { return minimumOffset; }
128  uintb getMaximum(void) const { return maximumOffset; }
129  int4 getStep(void) const { return step; }
130  bool isGuarded(const Address &addr) const;
131  bool isRangeLocked(void) const { return (analysisState == 2); }
132  bool isValid(OpCode opc) const { return (!op->isDead() && op->code() == opc); }
133 };
134 
170 class Heritage {
172  enum heritage_flags {
173  boundary_node = 1,
174  mark_node = 2,
175  merged_node = 4
176  };
177 
179  struct StackNode {
180  enum {
181  nonconstant_index = 1,
182  multiequal = 2
183  };
184  Varnode *vn;
185  uintb offset;
186  uint4 traversals;
187  list<PcodeOp *>::const_iterator iter;
188 
193  StackNode(Varnode *v,uintb o,uint4 trav) {
194  vn = v;
195  offset = o;
196  iter = v->beginDescend();
197  traversals = trav;
198  }
199  };
200 
201  Funcdata *fd;
202  LocationMap globaldisjoint;
203  LocationMap disjoint;
204  vector<vector<FlowBlock *> > domchild;
205  vector<vector<FlowBlock *> > augment;
206  vector<uint4> flags;
207  vector<int4> depth;
208  int4 maxdepth;
209  int4 pass;
210 
211  PriorityQueue pq;
212  vector<FlowBlock *> merge;
213  vector<HeritageInfo> infolist;
214  list<LoadGuard> loadGuard;
215  list<LoadGuard> storeGuard;
216  vector<PcodeOp *> loadCopyOps;
217  void clearInfoList(void);
218 
220  HeritageInfo *getInfo(AddrSpace *spc) { return &(infolist[spc->getIndex()]); }
221 
223  const HeritageInfo *getInfo(AddrSpace *spc) const { return &(infolist[spc->getIndex()]); }
224 
225  void splitJoinLevel(vector<Varnode *> &lastcombo,vector<Varnode *> &nextlev,JoinRecord *joinrec);
226  void splitJoinRead(Varnode *vn,JoinRecord *joinrec);
227  void splitJoinWrite(Varnode *vn,JoinRecord *joinrec);
228  void floatExtensionRead(Varnode *vn,JoinRecord *joinrec);
229  void floatExtensionWrite(Varnode *vn,JoinRecord *joinrec);
230  void processJoins(void);
231  void buildADT(void);
232  void removeRevisitedMarkers(const vector<Varnode *> &remove,const Address &addr,int4 size);
233  int4 collect(Address addr,int4 size,vector<Varnode *> &read,vector<Varnode *> &write,vector<Varnode *> &input,vector<Varnode *> &remove) const;
234  bool callOpIndirectEffect(const Address &addr,int4 size,PcodeOp *op) const;
235  Varnode *normalizeReadSize(Varnode *vn,const Address &addr,int4 size);
236  Varnode *normalizeWriteSize(Varnode *vn,const Address &addr,int4 size);
237  Varnode *concatPieces(const vector<Varnode *> &vnlist,PcodeOp *insertop,Varnode *finalvn);
238  void splitPieces(const vector<Varnode *> &vnlist,PcodeOp *insertop,const Address &addr,int4 size,Varnode *startvn);
239  void findAddressForces(vector<PcodeOp *> &copySinks,vector<PcodeOp *> &forces);
240  void propagateCopyAway(PcodeOp *op);
241  void handleNewLoadCopies(void);
242  void analyzeNewLoadGuards(void);
243  void generateLoadGuard(StackNode &node,PcodeOp *op,AddrSpace *spc);
244  void generateStoreGuard(StackNode &node,PcodeOp *op,AddrSpace *spc);
245  bool protectFreeStores(AddrSpace *spc,vector<PcodeOp *> &freeStores);
246  bool discoverIndexedStackPointers(AddrSpace *spc,vector<PcodeOp *> &freeStores,bool checkFreeStores);
247  void reprocessFreeStores(AddrSpace *spc,vector<PcodeOp *> &freeStores);
248  void guard(const Address &addr,int4 size,vector<Varnode *> &read,vector<Varnode *> &write,vector<Varnode *> &inputvars);
249  void guardInput(const Address &addr,int4 size,vector<Varnode *> &input);
250  void guardCallOverlappingInput(FuncCallSpecs *fc,const Address &addr,const Address &transAddr,int4 size);
251  void guardCalls(uint4 flags,const Address &addr,int4 size,vector<Varnode *> &write);
252  void guardStores(const Address &addr,int4 size,vector<Varnode *> &write);
253  void guardLoads(uint4 flags,const Address &addr,int4 size,vector<Varnode *> &write);
254  void guardReturns(uint4 flags,const Address &addr,int4 size,vector<Varnode *> &write);
255  static void buildRefinement(vector<int4> &refine,const Address &addr,int4 size,const vector<Varnode *> &vnlist);
256  void splitByRefinement(Varnode *vn,const Address &addr,const vector<int4> &refine,vector<Varnode *> &split);
257  void refineRead(Varnode *vn,const Address &addr,const vector<int4> &refine,vector<Varnode *> &newvn);
258  void refineWrite(Varnode *vn,const Address &addr,const vector<int4> &refine,vector<Varnode *> &newvn);
259  void refineInput(Varnode *vn,const Address &addr,const vector<int4> &refine,vector<Varnode *> &newvn);
260  void remove13Refinement(vector<int4> &refine);
261  bool refinement(const Address &addr,int4 size,const vector<Varnode *> &readvars,const vector<Varnode *> &writevars,const vector<Varnode *> &inputvars);
262  void visitIncr(FlowBlock *qnode,FlowBlock *vnode);
263  void calcMultiequals(const vector<Varnode *> &write);
264  void renameRecurse(BlockBasic *bl,VariableStack &varstack);
265  void bumpDeadcodeDelay(Varnode *vn);
266  void placeMultiequals(void);
267  void rename(void);
268 public:
269  Heritage(Funcdata *data);
270 
271  int4 getPass(void) const { return pass; }
272 
277  int4 heritagePass(const Address &addr) const { return globaldisjoint.findPass(addr); }
278  int4 numHeritagePasses(AddrSpace *spc) const;
279  void seenDeadCode(AddrSpace *spc);
280  int4 getDeadCodeDelay(AddrSpace *spc) const;
281  void setDeadCodeDelay(AddrSpace *spc,int4 delay);
282  bool deadRemovalAllowed(AddrSpace *spc) const;
284  void buildInfoList(void);
285  void forceRestructure(void) { maxdepth = -1; }
286  void clear(void);
287  void heritage(void);
288  const list<LoadGuard> &getLoadGuards(void) const { return loadGuard; }
289  const list<LoadGuard> &getStoreGuards(void) const { return storeGuard; }
290  const LoadGuard *getStoreGuard(PcodeOp *op) const;
291 };
292 
293 #endif
Heritage::deadRemovalAllowed
bool deadRemovalAllowed(AddrSpace *spc) const
Return true if it is safe to remove dead code.
Definition: heritage.cc:2469
LoadGuard::isGuarded
bool isGuarded(const Address &addr) const
Does this guard apply to the given address.
Definition: heritage.cc:719
LocationMap::findPass
int4 findPass(const Address &addr) const
Look up if/how given address was heritaged.
Definition: heritage.cc:83
AddrSpace::getHighest
uintb getHighest(void) const
Get the highest byte-scaled address.
Definition: space.hh:341
AddrSpace
A region where processor data is stored.
Definition: space.hh:73
FlowBlock
Description of a control-flow block containing PcodeOps.
Definition: block.hh:60
ValueSetRead
A special form of ValueSet associated with the read point of a Varnode.
Definition: rangeutil.hh:176
Heritage::deadRemovalAllowedSeen
bool deadRemovalAllowedSeen(AddrSpace *spc)
Check if dead code removal is safe and mark that removal has happened.
Definition: heritage.cc:2483
block.hh
Classes related to basic blocks and control-flow structuring.
SizePass::pass
int4 pass
Pass when the range was heritaged.
Definition: heritage.hh:32
Heritage::getDeadCodeDelay
int4 getDeadCodeDelay(AddrSpace *spc) const
Get pass delay for heritaging the given space.
Definition: heritage.cc:2443
JoinRecord
A record describing how logical values are split.
Definition: translate.hh:195
Heritage
Manage the construction of Static Single Assignment (SSA) form.
Definition: heritage.hh:170
LocationMap::iterator
map< Address, SizePass >::iterator iterator
Iterator into the main map.
Definition: heritage.hh:45
Heritage::buildInfoList
void buildInfoList(void)
Initialize information for each space.
Definition: heritage.cc:2286
FuncCallSpecs
A class for analyzing parameters to a sub-function call.
Definition: fspec.hh:1449
PriorityQueue::reset
void reset(int4 maxdepth)
Reset to an empty queue.
Definition: heritage.cc:97
BlockBasic
A basic block for p-code operations.
Definition: block.hh:365
PriorityQueue
Priority queue for the phi-node (MULTIEQUAL) placement algorithm.
Definition: heritage.hh:64
PcodeOp
Lowest level operation of the p-code language.
Definition: op.hh:58
Heritage::numHeritagePasses
int4 numHeritagePasses(AddrSpace *spc) const
Get the number times heritage was performed for the given address space.
Definition: heritage.cc:2419
LoadGuard
Description of a LOAD operation that needs to be guarded.
Definition: heritage.hh:105
HeritageInfo
Information about heritage passes performed for a specific address space.
Definition: heritage.hh:85
Varnode
A low-level variable or contiguous set of bytes described by an Address and a size.
Definition: varnode.hh:65
Heritage::heritage
void heritage(void)
Perform one pass of heritage.
Definition: heritage.cc:2306
Address
A low-level machine address for labelling bytes and data.
Definition: address.hh:46
Funcdata
Container for data structures associated with a single function.
Definition: funcdata.hh:45
Heritage::seenDeadCode
void seenDeadCode(AddrSpace *spc)
Inform system of dead code removal in given space.
Definition: heritage.cc:2431
AddrSpace::getIndex
int4 getIndex(void) const
Get the integer identifier.
Definition: space.hh:319
Heritage::setDeadCodeDelay
void setDeadCodeDelay(AddrSpace *spc, int4 delay)
Set delay for a specific space.
Definition: heritage.cc:2455
Heritage::clear
void clear(void)
Reset all analysis of heritage.
Definition: heritage.cc:2495
PriorityQueue::extract
FlowBlock * extract(void)
Retrieve the highest priority block.
Definition: heritage.cc:121
Heritage::Heritage
Heritage(Funcdata *data)
Constructor.
Definition: heritage.cc:135
OpCode
OpCode
The op-code defining a specific p-code operation (PcodeOp)
Definition: opcodes.hh:35
Heritage::heritagePass
int4 heritagePass(const Address &addr) const
Get the pass number when the given address was heritaged.
Definition: heritage.hh:277
Heritage::getStoreGuard
const LoadGuard * getStoreGuard(PcodeOp *op) const
Get LoadGuard record associated with given PcodeOp.
Definition: heritage.cc:2402
LocationMap
Map object for keeping track of which address ranges have been heritaged.
Definition: heritage.hh:42
LocationMap::find
iterator find(const Address &addr)
Look up if/how given address was heritaged.
Definition: heritage.cc:69
SizePass::size
int4 size
Size of the range (in bytes)
Definition: heritage.hh:31
VariableStack
map< Address, vector< Varnode * > > VariableStack
Definition: heritage.hh:27
LocationMap::add
iterator add(Address addr, int4 size, int4 pass, int4 &intersect)
Mark new address as heritaged.
Definition: heritage.cc:30
PriorityQueue::insert
void insert(FlowBlock *bl, int4 depth)
Insert a block into the queue given its priority.
Definition: heritage.cc:109
SizePass
Label for describing extent of address range that has been heritaged.
Definition: heritage.hh:30