Predator  [unstable] git snapshot
symproc.hh
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2009-2011 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_PROC_H
21 #define H_GUARD_SYM_PROC_H
22 
23 /**
24  * @file symproc.hh
25  * SymProc - a layer on top of SymHeap, providing some higher-level
26  * operations
27  */
28 
29 #include "config.h"
30 
31 #include <cl/storage.hh>
32 
33 #include "symbt.hh" // for EMsgLevel
34 #include "symid.hh"
35 #include "symheap.hh"
36 
37 class SymState;
38 
39 namespace GlConf {
40  struct Options;
41 }
42 
43 struct CmpOpTraits {
44  bool negative;
45  bool preserveEq;
49 };
50 
51 bool describeCmpOp(CmpOpTraits *pTraits, enum cl_binop_e code);
52 
53 inline bool areComparableTypes(const TObjType clt1, const TObjType clt2)
54 {
55  if (!clt1 || !clt2)
56  return false;
57 
58  enum cl_type_e code1 = clt1->code;
59  enum cl_type_e code2 = clt2->code;
60  if (code1 == code2)
61  return true;
62 
63  if (CL_TYPE_ENUM == code1)
64  code1 = CL_TYPE_INT;
65  if (CL_TYPE_ENUM == code2)
66  code2 = CL_TYPE_INT;
67 
68  // needed for CLSP
69  if (CL_TYPE_BOOL == code1)
70  code1 = CL_TYPE_INT;
71  if (CL_TYPE_BOOL == code2)
72  code2 = CL_TYPE_INT;
73 
74  return (code1 == code2);
75 }
76 
78  SymHeap &sh,
79  enum cl_binop_e code,
80  TValId v1,
81  TValId v2);
82 
83 bool reflectCmpResult(
84  SymState &dst,
85  SymProc &proc,
86  enum cl_binop_e code,
87  bool branch,
88  TValId v1,
89  TValId v2);
90 
91 /**
92  * a layer on top of SymHeap, providing some higher-level operations
93  */
94 class SymProc {
95  public:
96  /**
97  * creation of the symbolic heap processor is a really cheap operation
98  * @param heap an instance of SymHeap to operate on
99  * @param bt an instance of symbolic backtrace used to distinguish among
100  * instances of automatic variables and to print backtraces when
101  * necessary/suitable
102  */
103  SymProc(SymHeap &heap, const SymBackTrace *bt):
104  sh_(heap),
105  bt_(bt),
106  lw_(0),
107  errorDetected_(false)
108  {
109  }
110 
111  virtual ~SymProc() { }
112 
113  SymHeap& sh() { return sh_; }
114  const SymBackTrace* bt() { return bt_; }
115  const struct cl_loc* lw() { return lw_; }
116 
117  /**
118  * update location info
119  * @note this method is used to provide as accurate as possible location
120  * info in error/warning messages
121  * @param lw where to retrieve the location info from
122  */
123  void setLocation(const struct cl_loc *lw) {
124  lw_ = lw;
125  }
126 
127  public:
128  /// obtain a heap object corresponding to the given operand
129  FldHandle fldByOperand(const struct cl_operand &op);
130 
131  /// obtain a heap value corresponding to the given operand
132  TValId valFromOperand(const struct cl_operand &op);
133 
134  /// resolve Fnc uid from the given operand, return true on success
135  bool fncFromOperand(int *pUid, const struct cl_operand &op);
136 
137  /// high-level interface to FldHandle::setValue()
138  void setValueOf(const FldHandle &lhs, TValId rhs);
139 
140  /// high-level interface to SymHeap::objInvalidate()
141  void objDestroy(TObjId obj);
142 
143  /// invalidate all variables that are killed by the given instruction
144  void killInsn(const CodeStorage::Insn &);
145 
146  /// invalidate all variables killed by the given instruction per target
147  void killPerTarget(const CodeStorage::Insn &, unsigned target);
148 
149  /// check whether we can safely access sizeOfTarget at the given address
150  bool checkForInvalidDeref(TValId val, TSizeOf sizeOfTarget);
151 
152  /// print backtrace and update the current error level correspondingly
153  void printBackTrace(EMsgLevel level, bool forcePtrace = false);
154 
155  /// if true, the current state is not going to be inserted into dst
156  bool hasFatalError() const;
157 
158  protected:
159  TObjId objByVar(const CVar &cv, bool initOnly = false);
160  TObjId objByVar(const struct cl_operand &op);
161  TValId targetAt(const struct cl_operand &op);
162  virtual void varInit(TObjId reg);
163  friend void initGlVar(SymHeap &sh, const CVar &cv);
164 
165  private:
166  TValId valFromObj(const struct cl_operand &op);
167  TValId valFromCst(const struct cl_operand &op);
168  void killVar(const CodeStorage::KillVar &kv);
169 
170  protected:
173  const struct cl_loc *lw_;
175 };
176 
177 /// @todo make the API more generic and better documented
178 void describeUnknownVal(
179  SymProc &proc,
180  TValId val,
181  const char *action);
182 
183 void executeMemmove(
184  SymProc &proc,
185  TValId valDst,
186  TValId valSrc,
187  TValId valSize,
188  bool allowOverlap);
189 
190 void executeMemset(
191  SymProc &proc,
192  TValId addr,
193  TValId valToWrite,
194  TValId valSize);
195 
197  bool trackUninit; ///< enable/disable @b track_uninit @b mode
198  bool oomSimulation; ///< enable/disable @b oom @b simulation mode
199  bool skipPlot; ///< simply ignore all ___sl_plot* calls
200  std::string errLabel; ///< if not empty, treat reaching the label as error
201 
203  trackUninit(false),
204  oomSimulation(false),
205  skipPlot(false)
206  {
207  }
208 
210 };
211 
212 /// extension of SymProc, now only used by SymExecEngine::execNontermInsn()
213 class SymExecCore: public SymProc {
214  public:
215  /**
216  * @param ep execution parameters - see SymExecCoreParams for details
217  * @copydoc SymProc::SymProc
218  */
220  const SymExecCoreParams &ep = SymExecCoreParams()):
221  SymProc(heap, bt),
222  ep_(ep)
223  {
224  }
225 
226  const SymExecCoreParams& params() const { return ep_; }
227 
228  public:
229  /**
230  * execute a @b non-terminal instruction using the managed symbolic heap
231  * @note see also CodeStorage::Insn
232  * @note see also code_listener.h::cl_is_term_insn()
233  * @param dst a container to store the result(s) to
234  * @param insn an instruction to be executed
235  * @note returning false in this case does @b not mean there has been an
236  * error
237  * @return true, if the requested instruction has been processed; false
238  * if the instruction has to be processed elsewhere (usually
239  * CL_INSN_CALL)
240  */
241  bool exec(SymState &dst, const CodeStorage::Insn &insn);
242 
243  void execStackAlloc(const struct cl_operand &opLhs, const TSizeRange &);
244 
245  void execStackRestore();
246 
247  void execHeapAlloc(
248  SymState &dst,
249  const CodeStorage::Insn &insn,
250  TSizeRange size,
251  bool nullified);
252 
253  void execFree(TValId val);
254 
255  private:
256  template <int ARITY>
257  void execOp(const CodeStorage::Insn &insn);
258 
259  template <class TDerefs>
260  bool concretizeLoop(SymState &dst, const CodeStorage::Insn &insn,
261  const TDerefs &derefs);
262 
263  void handleLabel(const CodeStorage::Insn &);
264 
265  bool execCore(SymState &dst, const CodeStorage::Insn &insn);
266 
267  protected:
268  virtual void varInit(TObjId reg);
269 
270  private:
272 };
273 
274 #endif /* H_GUARD_SYM_PROC_H */