about summary refs log tree commit diff homepage
path: root/lib/Core/ExecutionState.h
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Core/ExecutionState.h')
-rw-r--r--lib/Core/ExecutionState.h81
1 files changed, 81 insertions, 0 deletions
diff --git a/lib/Core/ExecutionState.h b/lib/Core/ExecutionState.h
index 7be69ea7..b3560caf 100644
--- a/lib/Core/ExecutionState.h
+++ b/lib/Core/ExecutionState.h
@@ -21,6 +21,7 @@
 #include "klee/System/Time.h"
 
 #include <map>
+#include <memory>
 #include <set>
 #include <vector>
 
@@ -63,6 +64,83 @@ struct StackFrame {
   ~StackFrame();
 };
 
+/// Contains information related to unwinding (Itanium ABI/2-Phase unwinding)
+struct UnwindingInformation {
+  enum class Kind {
+    SearchPhase, // first phase
+    CleanupPhase // second phase
+  };
+
+private:
+  const Kind kind;
+
+public:
+  // _Unwind_Exception* of the thrown exception, used in both phases
+  ref<ConstantExpr> exceptionObject;
+
+  Kind getKind() const { return kind; }
+
+  explicit UnwindingInformation(ref<ConstantExpr> exceptionObject, Kind k)
+      : kind(k), exceptionObject(exceptionObject) {}
+  virtual ~UnwindingInformation() = default;
+
+  virtual std::unique_ptr<UnwindingInformation> cloned() const = 0;
+};
+
+struct SearchPhaseUnwindingInformation : public UnwindingInformation {
+  // Keeps track of the stack index we have so far unwound to.
+  std::size_t unwindingProgress;
+
+  // MemoryObject that contains a serialized version of the last executed
+  // landingpad, so we can clean it up after the personality fn returns.
+  MemoryObject *serializedLandingpad = nullptr;
+
+  SearchPhaseUnwindingInformation(ref<ConstantExpr> exceptionObject,
+                                  std::size_t const unwindingProgress)
+      : UnwindingInformation(exceptionObject,
+                             UnwindingInformation::Kind::SearchPhase),
+        unwindingProgress(unwindingProgress) {}
+
+  std::unique_ptr<UnwindingInformation> cloned() const {
+    return std::make_unique<SearchPhaseUnwindingInformation>(*this);
+  }
+
+  static bool classof(const UnwindingInformation *u) {
+    return u->getKind() == UnwindingInformation::Kind::SearchPhase;
+  }
+};
+
+struct CleanupPhaseUnwindingInformation : public UnwindingInformation {
+  // Phase 1 will try to find a catching landingpad.
+  // Phase 2 will unwind up to this landingpad or return from
+  // _Unwind_RaiseException if none was found.
+
+  // The selector value of the catching landingpad that was found
+  // during the search phase.
+  ref<ConstantExpr> selectorValue;
+
+  // Used to know when we have to stop unwinding and to
+  // ensure that unwinding stops at the frame for which
+  // we first found a handler in the search phase.
+  const std::size_t catchingStackIndex;
+
+  CleanupPhaseUnwindingInformation(ref<ConstantExpr> exceptionObject,
+                                   ref<ConstantExpr> selectorValue,
+                                   const std::size_t catchingStackIndex)
+      : UnwindingInformation(exceptionObject,
+                             UnwindingInformation::Kind::CleanupPhase),
+        selectorValue(selectorValue),
+        catchingStackIndex(catchingStackIndex) {}
+
+  std::unique_ptr<UnwindingInformation> cloned() const {
+    return std::make_unique<CleanupPhaseUnwindingInformation>(*this);
+  }
+
+  static bool classof(const UnwindingInformation *u) {
+    return u->getKind() == UnwindingInformation::Kind::CleanupPhase;
+  }
+};
+
 /// @brief ExecutionState representing a path under exploration
 class ExecutionState {
 #ifdef KLEE_UNITTEST
@@ -141,6 +219,9 @@ public:
   /// instruction was covered.
   std::uint32_t instsSinceCovNew;
 
+  /// @brief Keep track of unwinding state while unwinding, otherwise empty
+  std::unique_ptr<UnwindingInformation> unwindingInformation;
+
   /// @brief the global state counter
   static std::uint32_t nextID;