ExecutionState.h

Go to the documentation of this file.
00001 //===-- ExecutionState.h ----------------------------------------*- C++ -*-===//
00002 //
00003 //                     The KLEE Symbolic Virtual Machine
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 
00010 #ifndef KLEE_EXECUTIONSTATE_H
00011 #define KLEE_EXECUTIONSTATE_H
00012 
00013 #include "klee/Constraints.h"
00014 #include "klee/Expr.h"
00015 #include "klee/Internal/ADT/TreeStream.h"
00016 
00017 // FIXME: We do not want to be exposing these? :(
00018 #include "../../lib/Core/AddressSpace.h"
00019 #include "klee/Internal/Module/KInstIterator.h"
00020 
00021 #include <map>
00022 #include <set>
00023 #include <vector>
00024 
00025 namespace klee {
00026   class CallPathNode;
00027   class Cell;
00028   class KFunction;
00029   class KInstruction;
00030   class MemoryObject;
00031   class PTreeNode;
00032   class InstructionInfo;
00033   class ExecutionTraceEvent;
00034 
00035 std::ostream &operator<<(std::ostream &os, const MemoryMap &mm);
00036 
00037 struct StackFrame {
00038   KInstIterator caller;
00039   KFunction *kf;
00040   CallPathNode *callPathNode;
00041 
00042   std::vector<const MemoryObject*> allocas;
00043   Cell *locals;
00044 
00050   unsigned minDistToUncoveredOnReturn;
00051 
00052   // For vararg functions: arguments not passed via parameter are
00053   // stored (packed tightly) in a local (alloca) memory object. This
00054   // is setup to match the way the front-end generates vaarg code (it
00055   // does not pass vaarg through as expected). VACopy is lowered inside
00056   // of intrinsic lowering.
00057   MemoryObject *varargs;
00058 
00059   StackFrame(KInstIterator caller, KFunction *kf);
00060   StackFrame(const StackFrame &s);
00061   ~StackFrame();
00062 };
00063 
00064 // FIXME: Redo execution trace stuff to use a TreeStream, there is no
00065 // need to keep this stuff in memory as far as I can tell.
00066 
00067 // each state should have only one of these guys ...
00068 class ExecutionTraceManager {
00069 public:
00070   ExecutionTraceManager() : hasSeenUserMain(false) {}
00071 
00072   void addEvent(ExecutionTraceEvent* evt);
00073   void printAllEvents(std::ostream &os) const;
00074 
00075 private:
00076   // have we seen a call to __user_main() yet?
00077   // don't bother tracing anything until we see this,
00078   // or else we'll get junky prologue shit
00079   bool hasSeenUserMain;
00080 
00081   // ugh C++ only supports polymorphic calls thru pointers
00082   //
00083   // WARNING: these are NEVER FREED, because they are shared
00084   // across different states (when states fork), so we have 
00085   // an *intentional* memory leak, but oh wellz ;)
00086   std::vector<ExecutionTraceEvent*> events;
00087 };
00088 
00089 
00090 class ExecutionState {
00091 public:
00092   typedef std::vector<StackFrame> stack_ty;
00093 
00094 private:
00095   // unsupported, use copy constructor
00096   ExecutionState &operator=(const ExecutionState&); 
00097   std::map< std::string, std::string > fnAliases;
00098 
00099 public:
00100   bool fakeState;
00101   // Are we currently underconstrained?  Hack: value is size to make fake
00102   // objects.
00103   unsigned underConstrained;
00104   unsigned depth;
00105   
00106   // pc - pointer to current instruction stream
00107   KInstIterator pc, prevPC;
00108   stack_ty stack;
00109   ConstraintManager constraints;
00110   mutable double queryCost;
00111   double weight;
00112   AddressSpace addressSpace;
00113   TreeOStream pathOS, symPathOS;
00114   unsigned instsSinceCovNew;
00115   bool coveredNew;
00116 
00117   // for printing execution traces when this state terminates
00118   ExecutionTraceManager exeTraceMgr;
00119 
00121   bool forkDisabled;
00122 
00123   std::map<const std::string*, std::set<unsigned> > coveredLines;
00124   PTreeNode *ptreeNode;
00125 
00127   //
00128   // FIXME: Move to a shared list structure (not critical).
00129   std::vector<const MemoryObject*> symbolics;
00130 
00131   // Used by the checkpoint/rollback methods for fake objects.
00132   // FIXME: not freeing things on branch deletion.
00133   MemoryMap shadowObjects;
00134 
00135   unsigned incomingBBIndex;
00136 
00137   std::string getFnAlias(std::string fn);
00138   void addFnAlias(std::string old_fn, std::string new_fn);
00139   void removeFnAlias(std::string fn);
00140   
00141 private:
00142   ExecutionState() : fakeState(false), underConstrained(0), ptreeNode(0) {};
00143 
00144 public:
00145   ExecutionState(KFunction *kf);
00146 
00147   // XXX total hack, just used to make a state so solver can
00148   // use on structure
00149   ExecutionState(const std::vector<ref<Expr> > &assumptions);
00150 
00151   ~ExecutionState();
00152   
00153   ExecutionState *branch();
00154 
00155   void pushFrame(KInstIterator caller, KFunction *kf);
00156   void popFrame();
00157 
00158   void addSymbolic(const MemoryObject *mo) { 
00159     symbolics.push_back(mo);
00160   }
00161   void addConstraint(ref<Expr> e) { 
00162     constraints.addConstraint(e); 
00163   }
00164 
00165   // Used for checkpoint/rollback of fake objects created during tainting.
00166   ObjectState *cloneObject(ObjectState *os, MemoryObject *mo);
00167 
00168   //
00169 
00170   bool merge(const ExecutionState &b);
00171 };
00172 
00173 
00174 // for producing abbreviated execution traces to help visualize
00175 // paths and diagnose bugs
00176 
00177 class ExecutionTraceEvent {
00178 public:
00179   // the location of the instruction:
00180   std::string file;
00181   unsigned line;
00182   std::string funcName;
00183   unsigned stackDepth;
00184 
00185   unsigned consecutiveCount; // init to 1, increase for CONSECUTIVE
00186                              // repetitions of the SAME event
00187 
00188   ExecutionTraceEvent()
00189     : file("global"), line(0), funcName("global_def"),
00190       consecutiveCount(1) {}
00191 
00192   ExecutionTraceEvent(ExecutionState& state, KInstruction* ki);
00193 
00194   virtual ~ExecutionTraceEvent() {}
00195 
00196   void print(std::ostream &os) const;
00197 
00198   // return true if it shouldn't be added to ExecutionTraceManager
00199   //
00200   virtual bool ignoreMe() const;
00201 
00202 private:
00203   virtual void printDetails(std::ostream &os) const = 0;
00204 };
00205 
00206 
00207 class FunctionCallTraceEvent : public ExecutionTraceEvent {
00208 public:
00209   std::string calleeFuncName;
00210 
00211   FunctionCallTraceEvent(ExecutionState& state, KInstruction* ki,
00212                          const std::string& _calleeFuncName)
00213     : ExecutionTraceEvent(state, ki), calleeFuncName(_calleeFuncName) {}
00214 
00215 private:
00216   virtual void printDetails(std::ostream &os) const {
00217     os << "CALL " << calleeFuncName;
00218   }
00219 
00220 };
00221 
00222 class FunctionReturnTraceEvent : public ExecutionTraceEvent {
00223 public:
00224   FunctionReturnTraceEvent(ExecutionState& state, KInstruction* ki)
00225     : ExecutionTraceEvent(state, ki) {}
00226 
00227 private:
00228   virtual void printDetails(std::ostream &os) const {
00229     os << "RETURN";
00230   }
00231 };
00232 
00233 class BranchTraceEvent : public ExecutionTraceEvent {
00234 public:
00235   bool trueTaken;         // which side taken?
00236   bool canForkGoBothWays;
00237 
00238   BranchTraceEvent(ExecutionState& state, KInstruction* ki,
00239                    bool _trueTaken, bool _isTwoWay)
00240     : ExecutionTraceEvent(state, ki),
00241       trueTaken(_trueTaken),
00242       canForkGoBothWays(_isTwoWay) {}
00243 
00244 private:
00245   virtual void printDetails(std::ostream &os) const;
00246 };
00247 
00248 }
00249 
00250 #endif

Generated on Fri Jun 5 03:31:31 2009 for klee by  doxygen 1.5.8