1#ifndef ROSE_BinaryAnalysis_ModelChecker_PartitionerModel_H
2#define ROSE_BinaryAnalysis_ModelChecker_PartitionerModel_H
3#include <featureTests.h>
4#ifdef ROSE_ENABLE_MODEL_CHECKER
6#include <Rose/BinaryAnalysis/InstructionSemantics/SymbolicSemantics.h>
7#include <Rose/BinaryAnalysis/ModelChecker/SemanticCallbacks.h>
8#include <Rose/BinaryAnalysis/ModelChecker/Variables.h>
9#include <Rose/BinaryAnalysis/Partitioner2/BasicTypes.h>
10#include <Rose/BinaryAnalysis/Variables.h>
12#include <Sawyer/CommandLine.h>
13#include <Sawyer/Stack.h>
16namespace BinaryAnalysis {
17namespace ModelChecker {
27namespace PartitionerModel {
46 rose_addr_t maxNullAddress = 4095;
47 bool debugNull =
false;
50 bool solverMemoization =
false;
51 bool traceSemantics =
false;
54class SemanticCallbacks;
79 Partitioner2::FunctionPtr function_;
80 rose_addr_t initialStackPointer_ = 0;
81 rose_addr_t framePointerDelta_ = (rose_addr_t)(-4);
83 Variables::StackVariables stackVariables_;
88 const Variables::StackVariables&);
91 Partitioner2::FunctionPtr function()
const;
96 rose_addr_t initialStackPointer()
const;
99 const Variables::StackVariables& stackVariables()
const;
106 rose_addr_t framePointerDelta()
const;
107 void framePointerDelta(rose_addr_t);
113 rose_addr_t framePointer(
size_t nBits)
const;
123 std::string printableName(
size_t nBits)
const;
138class SValue:
public InstructionSemantics::SymbolicSemantics::SValue {
141 using Super = InstructionSemantics::SymbolicSemantics::SValue;
149#ifdef ROSE_HAVE_BOOST_SERIALIZATION_LIB
151 friend class boost::serialization::access;
155 s & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Super);
156 s & BOOST_SERIALIZATION_NVP(region_);
166 SValue(
size_t nBits, uint64_t number);
168 explicit SValue(
const SymbolicExpression::Ptr&);
174 static Ptr instance();
177 static Ptr instanceBottom(
size_t nBits);
180 static Ptr instanceUndefined(
size_t nBits);
183 static Ptr instanceUnspecified(
size_t nBits);
186 static Ptr instanceInteger(
size_t nBits, uint64_t value);
189 static Ptr instanceSymbolic(
const SymbolicExpression::Ptr &value);
192 virtual InstructionSemantics::BaseSemantics::SValuePtr bottom_(
size_t nBits)
const override;
193 virtual InstructionSemantics::BaseSemantics::SValuePtr undefined_(
size_t nBits)
const override;
194 virtual InstructionSemantics::BaseSemantics::SValuePtr unspecified_(
size_t nBits)
const override;
195 virtual InstructionSemantics::BaseSemantics::SValuePtr number_(
size_t nBits, uint64_t value)
const override;
196 virtual InstructionSemantics::BaseSemantics::SValuePtr boolean_(
bool value)
const override;
197 virtual InstructionSemantics::BaseSemantics::SValuePtr
copy(
size_t newNBits = 0)
const override;
200 createOptionalMerge(
const InstructionSemantics::BaseSemantics::SValuePtr &other,
201 const InstructionSemantics::BaseSemantics::MergerPtr&,
202 const SmtSolverPtr&)
const override;
208 static Ptr promote(
const InstructionSemantics::BaseSemantics::SValuePtr&);
218 void region(
const AddressInterval&);
222 virtual void print(std::ostream&, InstructionSemantics::BaseSemantics::Formatter&)
const override;
223 virtual void hash(Combinatorics::Hasher&)
const override;
231using StatePtr = boost::shared_ptr<class State>;
234class State:
public InstructionSemantics::SymbolicSemantics::State {
237 using Super = InstructionSemantics::SymbolicSemantics::State;
240 using Ptr = StatePtr;
243 FunctionCallStack callStack_;
247 State(
const InstructionSemantics::BaseSemantics::RegisterStatePtr&,
248 const InstructionSemantics::BaseSemantics::MemoryStatePtr&);
255 static Ptr instance(
const InstructionSemantics::BaseSemantics::RegisterStatePtr&,
256 const InstructionSemantics::BaseSemantics::MemoryStatePtr&);
259 static Ptr instance(
const StatePtr&);
262 virtual InstructionSemantics::BaseSemantics::StatePtr
263 create(
const InstructionSemantics::BaseSemantics::RegisterStatePtr&,
264 const InstructionSemantics::BaseSemantics::MemoryStatePtr&)
const override;
267 virtual InstructionSemantics::BaseSemantics::StatePtr clone()
const override;
270 static Ptr promote(
const InstructionSemantics::BaseSemantics::StatePtr&);
278 const FunctionCallStack& callStack()
const;
279 FunctionCallStack& callStack();
288class RiscOperators:
public InstructionSemantics::SymbolicSemantics::RiscOperators {
290 using Super = InstructionSemantics::SymbolicSemantics::RiscOperators;
295 const Settings settings_;
296 Partitioner2::PartitionerConstPtr partitioner_;
297 SmtSolver::Ptr modelCheckerSolver_;
298 size_t nInstructions_ = 0;
299 SemanticCallbacks *semantics_ =
nullptr;
301 bool computeMemoryRegions_ =
false;
302 const Variables::GlobalVariables &gvars_;
304 mutable SAWYER_THREAD_TRAITS::Mutex variableFinderMutex_;
305 Variables::VariableFinderPtr variableFinder_unsync;
308 RiscOperators(
const Settings&,
const Partitioner2::PartitionerConstPtr&, ModelChecker::SemanticCallbacks*,
309 const InstructionSemantics::BaseSemantics::SValuePtr &protoval,
const SmtSolverPtr&,
310 const Variables::VariableFinderPtr&,
const Variables::GlobalVariables&);
315 static Ptr instance(
const Settings&,
const Partitioner2::PartitionerConstPtr&, ModelChecker::SemanticCallbacks*,
316 const InstructionSemantics::BaseSemantics::SValuePtr &protoval,
const SmtSolverPtr&,
317 const Variables::VariableFinderPtr&,
const Variables::GlobalVariables&);
319 virtual InstructionSemantics::BaseSemantics::RiscOperatorsPtr
320 create(
const InstructionSemantics::BaseSemantics::SValuePtr&,
const SmtSolverPtr&)
const override;
322 virtual InstructionSemantics::BaseSemantics::RiscOperatorsPtr
323 create(
const InstructionSemantics::BaseSemantics::StatePtr&,
const SmtSolverPtr&)
const override;
325 static Ptr promote(
const InstructionSemantics::BaseSemantics::RiscOperatorsPtr &x);
331 Partitioner2::PartitionerConstPtr partitioner()
const;
339 SmtSolver::Ptr modelCheckerSolver()
const;
340 void modelCheckerSolver(
const SmtSolver::Ptr&);
348 bool computeMemoryRegions()
const;
349 void computeMemoryRegions(
bool);
359 void checkNullAccess(
const InstructionSemantics::BaseSemantics::SValuePtr &addr, TestMode, IoMode);
364 void checkOobAccess(
const InstructionSemantics::BaseSemantics::SValuePtr &addr, TestMode, IoMode,
size_t nBytes);
369 void checkUninitVar(
const InstructionSemantics::BaseSemantics::SValuePtr &addr, TestMode,
size_t nBytes);
377 size_t nInstructions()
const;
378 void nInstructions(
size_t);
382 void maybeInitCallStack(rose_addr_t insnVa);
399 size_t pruneCallStack();
402 void printCallStack(std::ostream&,
const std::string &prefix);
418 InstructionSemantics::BaseSemantics::SValuePtr
419 assignRegion(
const InstructionSemantics::BaseSemantics::SValuePtr &result);
421 InstructionSemantics::BaseSemantics::SValuePtr
422 assignRegion(
const InstructionSemantics::BaseSemantics::SValuePtr &result,
423 const InstructionSemantics::BaseSemantics::SValuePtr &a);
425 InstructionSemantics::BaseSemantics::SValuePtr
426 assignRegion(
const InstructionSemantics::BaseSemantics::SValuePtr &result,
427 const InstructionSemantics::BaseSemantics::SValuePtr &a,
428 const InstructionSemantics::BaseSemantics::SValuePtr &b);
434 virtual InstructionSemantics::BaseSemantics::SValuePtr
435 number_(
size_t nBits, uint64_t value)
override;
437 virtual InstructionSemantics::BaseSemantics::SValuePtr
438 extract(
const InstructionSemantics::BaseSemantics::SValuePtr&,
size_t begin,
size_t end)
override;
440 virtual InstructionSemantics::BaseSemantics::SValuePtr
441 concat(
const InstructionSemantics::BaseSemantics::SValuePtr &lowBits,
442 const InstructionSemantics::BaseSemantics::SValuePtr &highBits)
override;
444 virtual InstructionSemantics::BaseSemantics::SValuePtr
445 shiftLeft(
const InstructionSemantics::BaseSemantics::SValuePtr &a,
446 const InstructionSemantics::BaseSemantics::SValuePtr &nBits)
override;
448 virtual InstructionSemantics::BaseSemantics::SValuePtr
449 shiftRight(
const InstructionSemantics::BaseSemantics::SValuePtr &a,
450 const InstructionSemantics::BaseSemantics::SValuePtr &nBits)
override;
452 virtual InstructionSemantics::BaseSemantics::SValuePtr
454 const InstructionSemantics::BaseSemantics::SValuePtr &nBits)
override;
456 virtual InstructionSemantics::BaseSemantics::SValuePtr
457 unsignedExtend(
const InstructionSemantics::BaseSemantics::SValue::Ptr &a,
size_t newWidth)
override;
459 virtual InstructionSemantics::BaseSemantics::SValuePtr
460 signExtend(
const InstructionSemantics::BaseSemantics::SValue::Ptr &a,
size_t newWidth)
override;
462 virtual InstructionSemantics::BaseSemantics::SValuePtr
463 add(
const InstructionSemantics::BaseSemantics::SValuePtr &a,
464 const InstructionSemantics::BaseSemantics::SValuePtr &b)
override;
466 virtual InstructionSemantics::BaseSemantics::SValuePtr
467 addCarry(
const InstructionSemantics::BaseSemantics::SValuePtr &a,
468 const InstructionSemantics::BaseSemantics::SValuePtr &b,
469 InstructionSemantics::BaseSemantics::SValuePtr &carryOut ,
470 InstructionSemantics::BaseSemantics::SValuePtr &overflowed )
override;
472 virtual InstructionSemantics::BaseSemantics::SValuePtr
473 subtract(
const InstructionSemantics::BaseSemantics::SValuePtr &a,
474 const InstructionSemantics::BaseSemantics::SValuePtr &b)
override;
476 virtual InstructionSemantics::BaseSemantics::SValuePtr
477 subtractCarry(
const InstructionSemantics::BaseSemantics::SValuePtr &a,
478 const InstructionSemantics::BaseSemantics::SValuePtr &b,
479 InstructionSemantics::BaseSemantics::SValuePtr &carryOut ,
480 InstructionSemantics::BaseSemantics::SValuePtr &overflowed )
override;
482 virtual InstructionSemantics::BaseSemantics::SValuePtr
483 addWithCarries(
const InstructionSemantics::BaseSemantics::SValuePtr &a,
484 const InstructionSemantics::BaseSemantics::SValuePtr &b,
485 const InstructionSemantics::BaseSemantics::SValuePtr &c,
486 InstructionSemantics::BaseSemantics::SValuePtr &carryOut )
override;
488 virtual InstructionSemantics::BaseSemantics::SValuePtr
489 readRegister(RegisterDescriptor,
const InstructionSemantics::BaseSemantics::SValuePtr&)
override;
492 writeRegister(RegisterDescriptor,
const InstructionSemantics::BaseSemantics::SValuePtr&)
override;
494 virtual InstructionSemantics::BaseSemantics::SValuePtr
495 readMemory(RegisterDescriptor segreg,
const InstructionSemantics::BaseSemantics::SValuePtr &addr,
496 const InstructionSemantics::BaseSemantics::SValuePtr &dflt,
497 const InstructionSemantics::BaseSemantics::SValuePtr &cond)
override;
500 writeMemory(RegisterDescriptor segreg,
const InstructionSemantics::BaseSemantics::SValuePtr &addr,
501 const InstructionSemantics::BaseSemantics::SValuePtr &value,
502 const InstructionSemantics::BaseSemantics::SValuePtr &cond)
override;
510class SemanticCallbacks:
public Rose::BinaryAnalysis::ModelChecker::SemanticCallbacks {
512 using Ptr = SemanticCallbacksPtr;
517 Partitioner2::PartitionerConstPtr partitioner_;
518 SmtSolver::Memoizer::Ptr smtMemoizer_;
520 mutable SAWYER_THREAD_TRAITS::Mutex unitsMutex_;
523 mutable SAWYER_THREAD_TRAITS::Mutex mutex_;
524 std::set<uint64_t> seenStates_;
525 size_t nDuplicateStates_ = 0;
526 size_t nSolverFailures_ = 0;
527 UnitCounts unitsReached_;
528 Variables::VariableFinderPtr variableFinder_;
529 Variables::GlobalVariables gvars_;
537 bool followingOnePath_ =
false;
538 std::list<ExecutionUnitPtr> onePath_;
541 SemanticCallbacks(
const ModelChecker::SettingsPtr&,
const Settings&,
const Partitioner2::PartitionerConstPtr&);
543 ~SemanticCallbacks();
546 static Ptr instance(
const ModelChecker::SettingsPtr&,
const Settings&,
const Partitioner2::PartitionerConstPtr&);
550 Partitioner2::PartitionerConstPtr partitioner()
const;
568 void followOnePath(
const std::list<ExecutionUnitPtr>&);
581 bool followingOnePath()
const;
582 void followingOnePath(
bool);
592 SmtSolver::Memoizer::Ptr smtMemoizer()
const;
593 void smtMemoizer(
const SmtSolver::Memoizer::Ptr&);
603 size_t nDuplicateStates()
const;
612 size_t nSolverFailures()
const;
622 size_t nUnitsReached()
const;
630 UnitCounts unitsReached()
const;
639 virtual bool filterNullDeref(
const InstructionSemantics::BaseSemantics::SValuePtr &addr,
SgAsmInstruction*,
640 TestMode testMode, IoMode ioMode);
657 virtual bool filterOobAccess(
const InstructionSemantics::BaseSemantics::SValuePtr &addr,
658 const AddressInterval &referencedRegion,
const AddressInterval &accessedRegion,
660 const FoundVariable &intendedVariable,
const FoundVariable &accessedVariable);
662 virtual bool filterUninitVar(
const InstructionSemantics::BaseSemantics::SValuePtr &addr,
663 const AddressInterval &referencedREgion,
const AddressInterval &accessedRegion,
664 SgAsmInstruction *insn, TestMode testMode,
const FoundVariable &accessedVariable);
667 virtual void reset()
override;
669 virtual InstructionSemantics::BaseSemantics::SValuePtr protoval()
override;
671 virtual InstructionSemantics::BaseSemantics::RegisterStatePtr createInitialRegisters()
override;
673 virtual InstructionSemantics::BaseSemantics::MemoryStatePtr createInitialMemory()
override;
675 virtual InstructionSemantics::BaseSemantics::StatePtr createInitialState()
override;
677 virtual InstructionSemantics::BaseSemantics::RiscOperatorsPtr createRiscOperators()
override;
680 initializeState(
const InstructionSemantics::BaseSemantics::RiscOperatorsPtr&)
override;
682 virtual InstructionSemantics::BaseSemantics::DispatcherPtr
683 createDispatcher(
const InstructionSemantics::BaseSemantics::RiscOperatorsPtr&)
override;
685 virtual SmtSolver::Ptr createSolver()
override;
687 virtual void attachModelCheckerSolver(
const InstructionSemantics::BaseSemantics::RiscOperatorsPtr&,
688 const SmtSolver::Ptr&)
override;
690 virtual CodeAddresses
691 nextCodeAddresses(
const InstructionSemantics::BaseSemantics::RiscOperatorsPtr&)
override;
693 virtual std::vector<TagPtr>
694 preExecute(
const ExecutionUnitPtr&,
const InstructionSemantics::BaseSemantics::RiscOperatorsPtr&)
override;
696 virtual std::vector<TagPtr>
697 postExecute(
const ExecutionUnitPtr&,
const InstructionSemantics::BaseSemantics::RiscOperatorsPtr&)
override;
699 virtual InstructionSemantics::BaseSemantics::SValuePtr
700 instructionPointer(
const InstructionSemantics::BaseSemantics::RiscOperatorsPtr&)
override;
702 virtual std::vector<NextUnit>
703 nextUnits(
const PathPtr&,
const InstructionSemantics::BaseSemantics::RiscOperatorsPtr&,
const SmtSolver::Ptr&)
override;
705#ifdef ROSE_HAVE_YAMLCPP
706 virtual std::list<ExecutionUnitPtr>
707 parsePath(
const YAML::Node&,
const std::string &sourceName)
override;
710 virtual std::list<ExecutionUnitPtr>
711 parsePath(
const Yaml::Node&,
const std::string &sourceName)
override;
715 bool seenState(
const InstructionSemantics::BaseSemantics::RiscOperatorsPtr&);
718 ExecutionUnitPtr findUnit(rose_addr_t va,
const Progress::Ptr&);
A collection of related switch declarations.
Container associating values with keys.
Holds a value or nothing.
Base class for machine instructions.
T shiftRightArithmetic(T value, size_t count)
Shifts bits of value right by count bits with sign extension.
T extract(T bits)
Extract bits from a value.
boost::shared_ptr< class RiscOperators > RiscOperatorsPtr
Shared-ownership pointer to concrete RISC operations.
Sawyer::SharedPointer< class SValue > SValuePtr
Smart-ownership pointer to a concrete semantic value.
Sawyer::SharedPointer< Node > Ptr
Reference counting pointer.
Hash hash(const std::vector< Ptr > &)
Hash zero or more expressions.
Sawyer::CommandLine::SwitchGroup commandLineSwitches(Settings &settings)
Command-line switches for unparser settings.
void print(const GlobalVariables &, const Partitioner2::PartitionerConstPtr &, std::ostream &out, const std::string &prefix="")
Print info about multiple global variables.
Sawyer::Container::Interval< Address > AddressInterval
An interval of addresses.
Unsigned shiftRight(Unsigned src, size_t n, bool b=false)
Right shift a value.
Unsigned signExtend(Unsigned src, size_t n)
Sign extend part of a value to the full width of the src type.
Unsigned shiftLeft(Unsigned src, size_t n, bool b=false)
Left shift a value.
void serialize(std::ostream &output, Graph &graph)
Serialize a graph into a stream of bytes.
void copy(const Word *src, const BitRange &srcRange, Word *dst, const BitRange &dstRange)
Copy some bits.
const char * MemoryType(int64_t)
Convert Rose::BinaryAnalysis::ModelChecker::PartitionerModel::Settings::MemoryType enum constant to a...
const char * TestMode(int64_t)
Convert Rose::BinaryAnalysis::ModelChecker::TestMode enum constant to a string.