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 {
47 bool debugNull =
false;
50 bool solverMemoization =
false;
51 bool traceSemantics =
false;
54class SemanticCallbacks;
79 Partitioner2::FunctionPtr function_;
80 Address initialStackPointer_ = 0;
83 Variables::StackVariables stackVariables_;
88 const Variables::StackVariables&);
91 Partitioner2::FunctionPtr function()
const;
96 Address initialStackPointer()
const;
99 const Variables::StackVariables& stackVariables()
const;
106 Address framePointerDelta()
const;
107 void framePointerDelta(Address);
113 Address 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_ENABLE_BOOST_SERIALIZATION
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&);
346 SemanticCallbacks* semanticCallbacks()
const;
353 bool computeMemoryRegions()
const;
354 void computeMemoryRegions(
bool);
364 void checkNullAccess(
const InstructionSemantics::BaseSemantics::SValuePtr &addr, TestMode, IoMode);
369 void checkOobAccess(
const InstructionSemantics::BaseSemantics::SValuePtr &addr, TestMode, IoMode,
size_t nBytes);
374 void checkUninitVar(
const InstructionSemantics::BaseSemantics::SValuePtr &addr, TestMode,
size_t nBytes);
382 size_t nInstructions()
const;
383 void nInstructions(
size_t);
387 void maybeInitCallStack(Address insnVa);
404 size_t pruneCallStack();
407 void printCallStack(std::ostream&,
const std::string &prefix);
423 InstructionSemantics::BaseSemantics::SValuePtr
424 assignRegion(
const InstructionSemantics::BaseSemantics::SValuePtr &result);
426 InstructionSemantics::BaseSemantics::SValuePtr
427 assignRegion(
const InstructionSemantics::BaseSemantics::SValuePtr &result,
428 const InstructionSemantics::BaseSemantics::SValuePtr &a);
430 InstructionSemantics::BaseSemantics::SValuePtr
431 assignRegion(
const InstructionSemantics::BaseSemantics::SValuePtr &result,
432 const InstructionSemantics::BaseSemantics::SValuePtr &a,
433 const InstructionSemantics::BaseSemantics::SValuePtr &b);
439 virtual InstructionSemantics::BaseSemantics::SValuePtr
440 number_(
size_t nBits, uint64_t value)
override;
442 virtual InstructionSemantics::BaseSemantics::SValuePtr
443 extract(
const InstructionSemantics::BaseSemantics::SValuePtr&,
size_t begin,
size_t end)
override;
445 virtual InstructionSemantics::BaseSemantics::SValuePtr
446 concat(
const InstructionSemantics::BaseSemantics::SValuePtr &lowBits,
447 const InstructionSemantics::BaseSemantics::SValuePtr &highBits)
override;
449 virtual InstructionSemantics::BaseSemantics::SValuePtr
450 shiftLeft(
const InstructionSemantics::BaseSemantics::SValuePtr &a,
451 const InstructionSemantics::BaseSemantics::SValuePtr &nBits)
override;
453 virtual InstructionSemantics::BaseSemantics::SValuePtr
454 shiftRight(
const InstructionSemantics::BaseSemantics::SValuePtr &a,
455 const InstructionSemantics::BaseSemantics::SValuePtr &nBits)
override;
457 virtual InstructionSemantics::BaseSemantics::SValuePtr
459 const InstructionSemantics::BaseSemantics::SValuePtr &nBits)
override;
461 virtual InstructionSemantics::BaseSemantics::SValuePtr
462 unsignedExtend(
const InstructionSemantics::BaseSemantics::SValue::Ptr &a,
size_t newWidth)
override;
464 virtual InstructionSemantics::BaseSemantics::SValuePtr
465 signExtend(
const InstructionSemantics::BaseSemantics::SValue::Ptr &a,
size_t newWidth)
override;
467 virtual InstructionSemantics::BaseSemantics::SValuePtr
468 add(
const InstructionSemantics::BaseSemantics::SValuePtr &a,
469 const InstructionSemantics::BaseSemantics::SValuePtr &b)
override;
471 virtual InstructionSemantics::BaseSemantics::SValuePtr
472 addCarry(
const InstructionSemantics::BaseSemantics::SValuePtr &a,
473 const InstructionSemantics::BaseSemantics::SValuePtr &b,
474 InstructionSemantics::BaseSemantics::SValuePtr &carryOut ,
475 InstructionSemantics::BaseSemantics::SValuePtr &overflowed )
override;
477 virtual InstructionSemantics::BaseSemantics::SValuePtr
478 subtract(
const InstructionSemantics::BaseSemantics::SValuePtr &a,
479 const InstructionSemantics::BaseSemantics::SValuePtr &b)
override;
481 virtual InstructionSemantics::BaseSemantics::SValuePtr
482 subtractCarry(
const InstructionSemantics::BaseSemantics::SValuePtr &a,
483 const InstructionSemantics::BaseSemantics::SValuePtr &b,
484 InstructionSemantics::BaseSemantics::SValuePtr &carryOut ,
485 InstructionSemantics::BaseSemantics::SValuePtr &overflowed )
override;
487 virtual InstructionSemantics::BaseSemantics::SValuePtr
488 addWithCarries(
const InstructionSemantics::BaseSemantics::SValuePtr &a,
489 const InstructionSemantics::BaseSemantics::SValuePtr &b,
490 const InstructionSemantics::BaseSemantics::SValuePtr &c,
491 InstructionSemantics::BaseSemantics::SValuePtr &carryOut )
override;
493 virtual InstructionSemantics::BaseSemantics::SValuePtr
494 readRegister(RegisterDescriptor,
const InstructionSemantics::BaseSemantics::SValuePtr&)
override;
497 writeRegister(RegisterDescriptor,
const InstructionSemantics::BaseSemantics::SValuePtr&)
override;
499 virtual InstructionSemantics::BaseSemantics::SValuePtr
500 readMemory(RegisterDescriptor segreg,
const InstructionSemantics::BaseSemantics::SValuePtr &addr,
501 const InstructionSemantics::BaseSemantics::SValuePtr &dflt,
502 const InstructionSemantics::BaseSemantics::SValuePtr &cond)
override;
505 writeMemory(RegisterDescriptor segreg,
const InstructionSemantics::BaseSemantics::SValuePtr &addr,
506 const InstructionSemantics::BaseSemantics::SValuePtr &value,
507 const InstructionSemantics::BaseSemantics::SValuePtr &cond)
override;
515class SemanticCallbacks:
public Rose::BinaryAnalysis::ModelChecker::SemanticCallbacks {
517 using Ptr = SemanticCallbacksPtr;
522 Partitioner2::PartitionerConstPtr partitioner_;
523 SmtSolver::Memoizer::Ptr smtMemoizer_;
526 mutable SAWYER_THREAD_TRAITS::Mutex unitsMutex_;
529 mutable SAWYER_THREAD_TRAITS::Mutex mutex_;
530 std::set<uint64_t> seenStates_;
531 size_t nDuplicateStates_ = 0;
532 size_t nSolverFailures_ = 0;
533 UnitCounts unitsReached_;
534 Variables::VariableFinderPtr variableFinder_;
535 Variables::GlobalVariables gvars_;
543 bool followingOnePath_ =
false;
544 std::list<ExecutionUnitPtr> onePath_;
547 SemanticCallbacks(
const ModelChecker::SettingsPtr&,
const Settings&,
const Partitioner2::PartitionerConstPtr&);
549 ~SemanticCallbacks();
552 static Ptr instance(
const ModelChecker::SettingsPtr&,
const Settings&,
const Partitioner2::PartitionerConstPtr&);
556 Partitioner2::PartitionerConstPtr partitioner()
const;
560 const Settings& p2Settings()
const;
577 void followOnePath(
const std::list<ExecutionUnitPtr>&);
590 bool followingOnePath()
const;
591 void followingOnePath(
bool);
601 SmtSolver::Memoizer::Ptr smtMemoizer()
const;
602 void smtMemoizer(
const SmtSolver::Memoizer::Ptr&);
617 size_t nDuplicateStates()
const;
626 size_t nSolverFailures()
const;
636 size_t nUnitsReached()
const;
644 UnitCounts unitsReached()
const;
653 virtual bool filterNullDeref(
const InstructionSemantics::BaseSemantics::SValuePtr &addr,
SgAsmInstruction*,
654 TestMode testMode, IoMode ioMode);
671 virtual bool filterOobAccess(
const InstructionSemantics::BaseSemantics::SValuePtr &addr,
672 const AddressInterval &referencedRegion,
const AddressInterval &accessedRegion,
674 const FoundVariable &intendedVariable,
const FoundVariable &accessedVariable);
676 virtual bool filterUninitVar(
const InstructionSemantics::BaseSemantics::SValuePtr &addr,
677 const AddressInterval &referencedREgion,
const AddressInterval &accessedRegion,
678 SgAsmInstruction *insn, TestMode testMode,
const FoundVariable &accessedVariable);
681 virtual void reset()
override;
683 virtual InstructionSemantics::BaseSemantics::SValuePtr protoval()
override;
685 virtual InstructionSemantics::BaseSemantics::RegisterStatePtr createInitialRegisters()
override;
687 virtual InstructionSemantics::BaseSemantics::MemoryStatePtr createInitialMemory()
override;
689 virtual InstructionSemantics::BaseSemantics::StatePtr createInitialState()
override;
691 virtual InstructionSemantics::BaseSemantics::RiscOperatorsPtr createRiscOperators()
override;
693 virtual InstructionSemantics::BaseSemantics::RiscOperatorsPtr
694 configureRiscOperators(
const InstructionSemantics::BaseSemantics::RiscOperatorsPtr&)
override;
697 initializeState(
const InstructionSemantics::BaseSemantics::RiscOperatorsPtr&)
override;
699 virtual InstructionSemantics::BaseSemantics::DispatcherPtr
700 createDispatcher(
const InstructionSemantics::BaseSemantics::RiscOperatorsPtr&)
override;
702 virtual SmtSolver::Ptr createSolver()
override;
704 virtual void attachModelCheckerSolver(
const InstructionSemantics::BaseSemantics::RiscOperatorsPtr&,
705 const SmtSolver::Ptr&)
override;
707 virtual CodeAddresses
708 nextCodeAddresses(
const InstructionSemantics::BaseSemantics::RiscOperatorsPtr&)
override;
710 virtual std::vector<TagPtr>
711 preExecute(
const PathNodePtr&,
const InstructionSemantics::BaseSemantics::RiscOperatorsPtr&)
override;
713 virtual std::vector<TagPtr>
714 postExecute(
const PathNodePtr&,
const InstructionSemantics::BaseSemantics::RiscOperatorsPtr&)
override;
716 virtual InstructionSemantics::BaseSemantics::SValuePtr
717 instructionPointer(
const InstructionSemantics::BaseSemantics::RiscOperatorsPtr&)
override;
719 virtual std::vector<NextUnit>
720 nextUnits(
const PathPtr&,
const InstructionSemantics::BaseSemantics::RiscOperatorsPtr&,
const SmtSolver::Ptr&)
override;
722#ifdef ROSE_HAVE_YAMLCPP
723 virtual std::list<ExecutionUnitPtr>
724 parsePath(
const YAML::Node&,
const std::string &sourceName)
override;
727 virtual std::list<ExecutionUnitPtr>
728 parsePath(
const Yaml::Node&,
const std::string &sourceName)
override;
731 Variables::VariableFinderPtr variableFinder()
const;
732 Variables::GlobalVariables& globalVariables();
736 bool seenState(
const InstructionSemantics::BaseSemantics::RiscOperatorsPtr&);
739 ExecutionUnitPtr findUnit(Address 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.
std::uint64_t Address
Address.
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.