diff options
| author | Felix Rath <felix.rath@comsys.rwth-aachen.de> | 2020-05-22 14:09:10 +0200 |
|---|---|---|
| committer | MartinNowack <2443641+MartinNowack@users.noreply.github.com> | 2020-10-12 11:19:24 +0100 |
| commit | c09306ffd894f95be195723327d5b17dca73ebd1 (patch) | |
| tree | 592773383280012bce8856b28503ab61de0deb98 /lib/Core/ExecutionState.h | |
| parent | d920e049fa955877f772188fdc58cab1b31aabc9 (diff) | |
| download | klee-c09306ffd894f95be195723327d5b17dca73ebd1.tar.gz | |
Implemented support for C++ Exceptions
We implement the Itanium ABI unwinding base-API, and leave the C++-specific parts to libcxxabi. Co-authored-by: Lukas Wölfer <lukas.woelfer@rwth-aachen.de>
Diffstat (limited to 'lib/Core/ExecutionState.h')
| -rw-r--r-- | lib/Core/ExecutionState.h | 81 |
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; |
