Ghidra Decompiler Analysis Engine
merge.hh
Go to the documentation of this file.
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 #ifndef __CPUI_MERGE__
17 #define __CPUI_MERGE__
18 
21 
22 #include "op.hh"
23 
29 class HighEdge {
30  friend class Merge;
31  HighVariable *a;
32  HighVariable *b;
33 public:
35  bool operator<(const HighEdge &op2) const { if (a==op2.a) return (b<op2.b); return (a<op2.a); }
36  HighEdge(HighVariable *c,HighVariable *d) { a=c; b=d; }
37 };
38 
44 class BlockVarnode {
45  int4 index;
46  Varnode *vn;
47 public:
48  void set(Varnode *v);
49  bool operator<(const BlockVarnode &op2) const { return (index < op2.index); }
50  Varnode *getVarnode(void) const { return vn; }
51  int4 getIndex(void) const { return index; }
52  static int4 findFront(int4 blocknum,const vector<BlockVarnode> &list);
53 };
54 
55 class Funcdata;
56 
80 class Merge {
81  Funcdata &data;
82  map<HighEdge,bool> highedgemap;
83  vector<PcodeOp *> copyTrims;
84  bool updateHigh(HighVariable *a);
85  void purgeHigh(HighVariable *high);
86  bool blockIntersection(HighVariable *a,HighVariable *b,int4 blk);
87  static bool mergeTestRequired(HighVariable *high_out,HighVariable *high_in);
88  static bool mergeTestAdjacent(HighVariable *high_out,HighVariable *high_in);
89  static bool mergeTestSpeculative(HighVariable *high_out,HighVariable *high_in);
90  static bool mergeTestBasic(Varnode *vn);
91  static void findSingleCopy(HighVariable *high,vector<Varnode *> &singlelist);
92  static bool compareHighByBlock(const HighVariable *a,const HighVariable *b);
93  static bool compareCopyByInVarnode(PcodeOp *op1,PcodeOp *op2);
94  static bool shadowedVarnode(const Varnode *vn);
95  static void findAllIntoCopies(HighVariable *high,vector<PcodeOp *> &copyIns,bool filterTemps);
96  void collectCovering(vector<Varnode *> &vlist,HighVariable *high,PcodeOp *op);
97  bool collectCorrectable(const vector<Varnode *> &vlist,list<PcodeOp *> &oplist,vector<int4> &slotlist,
98  PcodeOp *op);
99  PcodeOp *allocateCopyTrim(Varnode *inVn,Datatype *ct,const Address &addr);
100  void snipReads(Varnode *vn,list<PcodeOp *> &markedop);
101  void snipIndirect(PcodeOp *indop);
102  void eliminateIntersect(Varnode *vn,const vector<BlockVarnode> &blocksort);
103  void unifyAddress(VarnodeLocSet::const_iterator startiter,VarnodeLocSet::const_iterator enditer);
104  void trimOpOutput(PcodeOp *op);
105  void trimOpInput(PcodeOp *op,int4 slot);
106  void mergeRangeMust(VarnodeLocSet::const_iterator startiter,VarnodeLocSet::const_iterator enditer);
107  void mergeOp(PcodeOp *op);
108  void mergeIndirect(PcodeOp *indop);
109  void mergeLinear(vector<HighVariable *> &highvec);
110  bool merge(HighVariable *high1,HighVariable *high2,bool isspeculative);
111  bool checkCopyPair(HighVariable *high,PcodeOp *domOp,PcodeOp *subOp);
112  void buildDominantCopy(HighVariable *high,vector<PcodeOp *> &copy,int4 pos,int4 size);
113  void markRedundantCopies(HighVariable *high,vector<PcodeOp *> &copy,int4 pos,int4 size);
114  void processHighDominantCopy(HighVariable *high);
115  void processHighRedundantCopy(HighVariable *high);
116 public:
117  Merge(Funcdata &fd) : data(fd) {}
119  bool inflateTest(Varnode *a,HighVariable *high);
120  void inflate(Varnode *a,HighVariable *high);
121  bool mergeTest(HighVariable *high,vector<HighVariable *> &tmplist);
122 
123  void mergeOpcode(OpCode opc);
124  void mergeByDatatype(VarnodeLocSet::const_iterator startiter,VarnodeLocSet::const_iterator enditer);
125  void mergeAddrTied(void);
126  void mergeMarker(void);
127  void mergeAdjacent(void);
128  void mergeMultiEntry(void);
129  bool hideShadows(HighVariable *high);
130  void processCopyTrims(void);
131  void markInternalCopies(void);
132 #ifdef MERGEMULTI_DEBUG
133  void verifyHighCovers(void);
134 #endif
135 };
136 
148 inline bool Merge::compareHighByBlock(const HighVariable *a,const HighVariable *b)
149 
150 {
151  int4 result = a->wholecover.compareTo(b->wholecover);
152  if ( result == 0 ) {
153  Varnode *v1 = a->getInstance( 0 );
154  Varnode *v2 = b->getInstance( 0 );
155 
156  if ( v1->getAddr() == v2->getAddr() ) {
157  PcodeOp *def1 = v1->getDef();
158  PcodeOp *def2 = v2->getDef();
159  if ( def1 == (PcodeOp *) 0 ) {
160  return true;
161  }
162  else if ( def2 == (PcodeOp *) 0 ) {
163  return false;
164  }
165  return (def1->getAddr() < def2->getAddr());
166  }
167  return (v1->getAddr() < v2->getAddr());
168  }
169  return (result < 0);
170 }
171 
172 #endif
HighEdge
A record for caching a Cover intersection test between two HighVariable objects.
Definition: merge.hh:29
HighEdge::operator<
bool operator<(const HighEdge &op2) const
Comparator.
Definition: merge.hh:35
Merge
Class for merging low-level Varnodes into high-level HighVariables.
Definition: merge.hh:80
Merge::mergeAdjacent
void mergeAdjacent(void)
Speculatively merge Varnodes that are input/output to the same p-code op.
Definition: merge.cc:881
Merge::mergeMarker
void mergeMarker(void)
Force the merge of input and output Varnodes to MULTIEQUAL and INDIRECT ops.
Definition: merge.cc:800
Merge::intersection
bool intersection(HighVariable *a, HighVariable *b)
Test the intersection of two HighVariables and cache the result.
Definition: merge.cc:1481
BlockVarnode::findFront
static int4 findFront(int4 blocknum, const vector< BlockVarnode > &list)
Find the first Varnode defined in the BlockBasic of the given index.
Definition: merge.cc:41
Merge::processCopyTrims
void processCopyTrims(void)
Try to reduce/eliminate COPYs produced by the merge trimming process.
Definition: merge.cc:1265
Merge::mergeByDatatype
void mergeByDatatype(VarnodeLocSet::const_iterator startiter, VarnodeLocSet::const_iterator enditer)
Try to merge all HighVariables in the given range that have the same data-type.
Definition: merge.cc:298
BlockVarnode::set
void set(Varnode *v)
Set this as representing the given Varnode.
Definition: merge.cc:22
PcodeOp
Lowest level operation of the p-code language.
Definition: op.hh:58
Varnode
A low-level variable or contiguous set of bytes described by an Address and a size.
Definition: varnode.hh:65
Cover::compareTo
int4 compareTo(const Cover &op2) const
Give ordering of this and another Cover.
Definition: cover.cc:221
Merge::mergeMultiEntry
void mergeMultiEntry(void)
Merge together Varnodes mapped to SymbolEntrys from the same Symbol.
Definition: merge.cc:819
Address
A low-level machine address for labelling bytes and data.
Definition: address.hh:46
Merge::mergeOpcode
void mergeOpcode(OpCode opc)
Try to force merges of input to output for all p-code ops of a given type.
Definition: merge.cc:265
Funcdata
Container for data structures associated with a single function.
Definition: funcdata.hh:45
Datatype
The base datatype class for the decompiler.
Definition: type.hh:62
Merge::hideShadows
bool hideShadows(HighVariable *high)
Hide shadow Varnodes related to the given HighVariable by consolidating COPY chains.
Definition: merge.cc:968
HighVariable
A high-level variable modeled as a list of low-level variables, each written once.
Definition: variable.hh:38
op.hh
The PcodeOp and PcodeOpBank classes.
OpCode
OpCode
The op-code defining a specific p-code operation (PcodeOp)
Definition: opcodes.hh:35
Merge::markInternalCopies
void markInternalCopies(void)
Mark redundant/internal COPY PcodeOps.
Definition: merge.cc:1294
BlockVarnode
Helper class associating a Varnode with the block where it is defined.
Definition: merge.hh:44
Merge::mergeAddrTied
void mergeAddrTied(void)
Force the merge of address tried Varnodes.
Definition: merge.cc:523
Merge::inflate
void inflate(Varnode *a, HighVariable *high)
Inflate the Cover of a given Varnode with a HighVariable.
Definition: merge.cc:1546
Merge::inflateTest
bool inflateTest(Varnode *a, HighVariable *high)
Test if we can inflate the Cover of the given Varnode without incurring intersections.
Definition: merge.cc:1567
Merge::mergeTest
bool mergeTest(HighVariable *high, vector< HighVariable * > &tmplist)
Test for intersections between a given HighVariable and a list of other HighVariables.
Definition: merge.cc:1594