Predator  [unstable] git snapshot
symstate.hh
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2009-2010 Kamil Dudka <kdudka@redhat.com>
3  *
4  * This file is part of predator.
5  *
6  * predator is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * any later version.
10  *
11  * predator is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with predator. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #ifndef H_GUARD_SYM_STATE_H
21 #define H_GUARD_SYM_STATE_H
22 
23 /**
24  * @file symstate.hh
25  * @todo update dox
26  */
27 
28 #include <set>
29 #include <vector>
30 
31 #include "symheap.hh"
32 
33 namespace CodeStorage {
34  class Block;
35 }
36 
37 class SymState {
38  private:
39  typedef std::vector<SymHeap *> TList;
40 
41  public:
42  typedef TList::const_iterator const_iterator;
43  typedef TList::iterator iterator;
44 
45  public:
46  SymState() { }
47  virtual ~SymState();
48 
49  SymState(const SymState &);
50  SymState& operator=(const SymState &);
51 
52  virtual void clear();
53 
54  virtual void swap(SymState &other) {
55  heaps_.swap(other.heaps_);
56  }
57 
58  /**
59  * look for the given symbolic heap, return its index if found, -1
60  * otherwise
61  */
62  virtual int lookup(const SymHeap &heap) const = 0;
63 
64  /// insert given SymHeap object into the state
65  virtual bool insert(const SymHeap &sh, bool allowThreeWay = true);
66 
67  /// return count of object stored in the container
68  size_t size() const { return heaps_.size(); }
69 
70  /// return nth SymHeap object, 0 <= nth < size()
71  const SymHeap& operator[](int nth) const {
72  return *heaps_[nth];
73  }
74 
75  /// return STL-like iterator to go through the container
76  const_iterator begin() const { return heaps_.begin(); }
77 
78  /// return STL-like iterator to go through the container
79  const_iterator end() const { return heaps_.end(); }
80 
81  /// @copydoc begin() const
82  iterator begin() { return heaps_.begin(); }
83 
84  /// @copydoc begin() const
85  iterator end() { return heaps_.end(); }
86 
87  protected:
88  /// insert @b new SymHeap that @ must be guaranteed to be not yet in
89  virtual void insertNew(const SymHeap &sh);
90 
91  virtual void eraseExisting(int nth) {
92  delete heaps_[nth];
93  heaps_.erase(heaps_.begin() + nth);
94  }
95 
96  virtual void swapExisting(int nth, SymHeap &sh) {
97  SymHeap &existing = *heaps_.at(nth);
98  existing.swap(sh);
99  }
100 
101  virtual void rotateExisting(const int idxA, const int idxB);
102 
103  /// lookup/insert optimization in SymCallCache implementation
104  friend class PerFncCache;
105 
106  private:
108 };
109 
110 class SymHeapList: public SymState {
111  public:
113 
114  SymHeapList(const SymState &ref):
115  // safe to slice the base, as we have no data anyway
116  SymState(ref)
117  {
118  }
119 
121  // safe to slice the base, as we have no data anyway
122  *static_cast<SymState *>(this) = ref;
123 
124  return *this;
125  }
126 
127  virtual int lookup(const SymHeap &) const {
128  return /* not found */ -1;
129  }
130 };
131 
132 /**
133  * symbolic state represented as a union of SymHeap objects (aka disjuncts)
134  *
135  * During the symbolic execution (see SymExec) we keep such a state per each
136  * basic block of the function just being processed. The result of a
137  * symbolically executed function is then the SymState taken from the basic
138  * block containing CL_INSN_RET as soon as the fix-point calculation has
139  * terminated.
140  */
141 class SymHeapUnion: public SymState {
142  public:
143  virtual int lookup(const SymHeap &sh) const;
144 };
145 
147  public:
148  virtual bool insert(const SymHeap &sh, bool allowThreeWay = true);
149 
150  private:
151  void packState(unsigned idx, bool allowThreeWay);
152 };
153 
154 /**
155  * Extension of SymStateWithJoin, which distinguishes among already processed
156  * symbolic heaps and symbolic heaps scheduled for processing. Newly inserted
157  * symbolic heaps are always marked as scheduled. They can be marked as done
158  * later, using the setDone() method.
159  */
161  public:
163  cntPending_(0)
164  {
165  }
166 
167  /// import of SymState rewrites the base and invalidates all flags
169  static_cast<SymState &>(*this) = huni;
170  done_.clear();
171  done_.resize(huni.size(), false);
172  cntPending_ = huni.size();
173  return *this;
174  }
175 
176  virtual void clear() {
178  done_.clear();
179  cntPending_ = 0;
180  }
181 
182  /// @attention always reinitializes the markers
183  virtual void swap(SymState &);
184 
185  /// return count of heaps pending for execution
186  int cntPending() const {
187  return cntPending_;
188  }
189 
190  protected:
191  virtual void insertNew(const SymHeap &sh) {
193 
194  // schedule the just inserted SymHeap for processing
195  done_.push_back(false);
196  ++cntPending_;
197  }
198 
199  virtual void eraseExisting(int nth) {
201 
202  if (!done_[nth])
203  --cntPending_;
204 
205  done_.erase(done_.begin() + nth);
206  }
207 
208  virtual void swapExisting(int nth, SymHeap &sh) {
210 
211  if (!done_.at(nth))
212  return;
213 
214  // an already processed heap has been generalized, we need to
215  // schedule it for precessing once again
216  done_[nth] = false;
217  ++cntPending_;
218  }
219 
220  virtual void rotateExisting(const int idxA, const int idxB);
221 
222  friend class SymStateMap;
223 
224  public:
225  /// check if the nth symbolic heap has been already processed
226  bool isDone(int nth) const {
227  return done_.at(nth);
228  }
229 
230  /// mark the nth symbolic heap as processed
231  void setDone(int nth) {
232  if (!done_.at(nth))
233  --cntPending_;
234 
235  done_[nth] = true;
236  }
237 
238  private:
239  typedef std::vector<bool> TDone;
240 
243 };
244 
246  public:
248 
249  /// return count of heaps pending for execution in the specified blcok
250  virtual int cntPending(const CodeStorage::Block *) const = 0;
251 };
252 
253 /**
254  * higher-level container that maintains a SymStateMarked object per each basic
255  * block. It's used by SymExecEngine and PathTracer classes.
256  */
258  public:
259  typedef std::vector<const CodeStorage::Block *> TContBlock;
260 
261  SymStateMap();
262  virtual ~SymStateMap();
263 
264  /// state lookup, basically equal to std::map semantic
266 
267  /**
268  * managed insertion of the state that keeps track of the relation among
269  * source and destination basic blocks
270  * @param dst @b destination basic block (where the insertion occurs)
271  * @param sh an instance of symbolic heap that should be inserted
272  * @param allowThreeWay if true, three-way join is allowed
273  */
274  bool insert(const CodeStorage::Block *dst,
275  const SymHeap &sh,
276  const bool allowThreeWay = true
277  );
278 
279  /// true if the specified block has ever joined/entailed any given state
280  bool anyReuseHappened(const CodeStorage::Block *) const;
281 
282  virtual int cntPending(const CodeStorage::Block *) const;
283 
284  private:
285  /// object copying is @b not allowed
286  SymStateMap(const SymStateMap &);
287 
288  /// object copying is @b not allowed
290 
291  private:
292  struct Private;
293  Private *d;
294 };
295 
297  public:
298  virtual ~IStatsProvider() { }
299  virtual void printStats() const = 0;
300 };
301 
303  public:
304  typedef const CodeStorage::Block *TBlock;
305  typedef std::set<TBlock> TBlockSet;
306  typedef std::vector<TBlock> TBlockList;
307 
308  public:
311  ~BlockScheduler();
312 
313  const TBlockSet& todo() const;
314 
315  TBlockList done() const;
316 
317  unsigned cntWaiting() const;
318 
319  bool schedule(const TBlock bb);
320 
321  bool getNext(TBlock *dst);
322 
323  virtual void printStats() const;
324 
325  private:
326  // not implemented
328 
329  struct Private;
330  Private *d;
331 };
332 
333 #endif /* H_GUARD_SYM_STATE_H */