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>
11#include <Sawyer/CommandLine.h>
12#include <Sawyer/Stack.h>
15namespace BinaryAnalysis {
16namespace ModelChecker {
26namespace PartitionerModel {
45 rose_addr_t maxNullAddress = 4095;
46 bool debugNull =
false;
49 bool solverMemoization =
false;
50 bool traceSemantics =
false;
53class SemanticCallbacks;
78 Partitioner2::FunctionPtr function_;
79 rose_addr_t initialStackPointer_ = 0;
80 rose_addr_t framePointerDelta_ = (rose_addr_t)(-4);
82 Variables::StackVariables stackVariables_;
87 const Variables::StackVariables&);
90 Partitioner2::FunctionPtr function()
const;
95 rose_addr_t initialStackPointer()
const;
98 const Variables::StackVariables& stackVariables()
const;
105 rose_addr_t framePointerDelta()
const;
106 void framePointerDelta(rose_addr_t);
112 rose_addr_t framePointer(
size_t nBits)
const;
122 std::string printableName(
size_t nBits)
const;
137class SValue:
public InstructionSemantics::SymbolicSemantics::SValue {
140 using Super = InstructionSemantics::SymbolicSemantics::SValue;
148#ifdef ROSE_HAVE_BOOST_SERIALIZATION_LIB
150 friend class boost::serialization::access;
154 s & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Super);
155 s & BOOST_SERIALIZATION_NVP(region_);
165 SValue(
size_t nBits, uint64_t number);
167 explicit SValue(
const SymbolicExpression::Ptr&);
173 static Ptr instance();
176 static Ptr instanceBottom(
size_t nBits);
179 static Ptr instanceUndefined(
size_t nBits);
182 static Ptr instanceUnspecified(
size_t nBits);
185 static Ptr instanceInteger(
size_t nBits, uint64_t value);
188 static Ptr instanceSymbolic(
const SymbolicExpression::Ptr &value);
191 virtual InstructionSemantics::BaseSemantics::SValuePtr bottom_(
size_t nBits)
const override {
192 return instanceBottom(nBits);
195 virtual InstructionSemantics::BaseSemantics::SValuePtr undefined_(
size_t nBits)
const override {
196 return instanceUndefined(nBits);
199 virtual InstructionSemantics::BaseSemantics::SValuePtr unspecified_(
size_t nBits)
const override {
200 return instanceUnspecified(nBits);
203 virtual InstructionSemantics::BaseSemantics::SValuePtr number_(
size_t nBits, uint64_t value)
const override {
204 return instanceInteger(nBits, value);
207 virtual InstructionSemantics::BaseSemantics::SValuePtr boolean_(
bool value)
const override {
208 return instanceInteger(1, value ? 1 : 0);
211 virtual InstructionSemantics::BaseSemantics::SValuePtr
copy(
size_t newNBits = 0)
const override;
214 createOptionalMerge(
const InstructionSemantics::BaseSemantics::SValuePtr &other,
215 const InstructionSemantics::BaseSemantics::MergerPtr&,
216 const SmtSolverPtr&)
const override;
222 static Ptr promote(
const InstructionSemantics::BaseSemantics::SValuePtr &v) {
224 ASSERT_not_null(retval);
236 void region(
const AddressInterval&);
240 virtual void print(std::ostream&, InstructionSemantics::BaseSemantics::Formatter&)
const override;
241 virtual void hash(Combinatorics::Hasher&)
const override;
249using StatePtr = boost::shared_ptr<class State>;
252class State:
public InstructionSemantics::SymbolicSemantics::State {
255 using Super = InstructionSemantics::SymbolicSemantics::State;
258 using Ptr = StatePtr;
261 FunctionCallStack callStack_;
265 State(
const InstructionSemantics::BaseSemantics::RegisterStatePtr&,
266 const InstructionSemantics::BaseSemantics::MemoryStatePtr&);
273 static Ptr instance(
const InstructionSemantics::BaseSemantics::RegisterStatePtr&,
274 const InstructionSemantics::BaseSemantics::MemoryStatePtr&);
277 static Ptr instance(
const StatePtr&);
280 virtual InstructionSemantics::BaseSemantics::StatePtr
281 create(
const InstructionSemantics::BaseSemantics::RegisterStatePtr ®isters,
282 const InstructionSemantics::BaseSemantics::MemoryStatePtr &memory)
const override {
283 return instance(registers, memory);
287 virtual InstructionSemantics::BaseSemantics::StatePtr clone()
const override;
290 static Ptr promote(
const InstructionSemantics::BaseSemantics::StatePtr&);
298 const FunctionCallStack& callStack()
const;
299 FunctionCallStack& callStack();
308class RiscOperators:
public InstructionSemantics::SymbolicSemantics::RiscOperators {
310 using Super = InstructionSemantics::SymbolicSemantics::RiscOperators;
315 const Settings settings_;
316 Partitioner2::PartitionerConstPtr partitioner_;
317 SmtSolver::Ptr modelCheckerSolver_;
318 size_t nInstructions_ = 0;
319 SemanticCallbacks *semantics_ =
nullptr;
321 bool computeMemoryRegions_ =
false;
322 const Variables::GlobalVariables &gvars_;
324 mutable SAWYER_THREAD_TRAITS::Mutex variableFinderMutex_;
325 Variables::VariableFinderPtr variableFinder_unsync;
328 RiscOperators(
const Settings&,
const Partitioner2::PartitionerConstPtr&, ModelChecker::SemanticCallbacks*,
329 const InstructionSemantics::BaseSemantics::SValuePtr &protoval,
const SmtSolverPtr&,
330 const Variables::VariableFinderPtr&,
const Variables::GlobalVariables&);
335 static Ptr instance(
const Settings&,
const Partitioner2::PartitionerConstPtr&, ModelChecker::SemanticCallbacks*,
336 const InstructionSemantics::BaseSemantics::SValuePtr &protoval,
const SmtSolverPtr&,
337 const Variables::VariableFinderPtr&,
const Variables::GlobalVariables&);
339 virtual InstructionSemantics::BaseSemantics::RiscOperatorsPtr
340 create(
const InstructionSemantics::BaseSemantics::SValuePtr&,
const SmtSolverPtr&)
const override;
342 virtual InstructionSemantics::BaseSemantics::RiscOperatorsPtr
343 create(
const InstructionSemantics::BaseSemantics::StatePtr&,
const SmtSolverPtr&)
const override;
345 static Ptr promote(
const InstructionSemantics::BaseSemantics::RiscOperatorsPtr &x);
351 Partitioner2::PartitionerConstPtr partitioner()
const;
359 SmtSolver::Ptr modelCheckerSolver()
const;
360 void modelCheckerSolver(
const SmtSolver::Ptr&);
368 bool computeMemoryRegions()
const;
369 void computeMemoryRegions(
bool);
379 void checkNullAccess(
const InstructionSemantics::BaseSemantics::SValuePtr &addr, TestMode, IoMode);
384 void checkOobAccess(
const InstructionSemantics::BaseSemantics::SValuePtr &addr, TestMode, IoMode,
size_t nBytes);
389 void checkUninitVar(
const InstructionSemantics::BaseSemantics::SValuePtr &addr, TestMode,
size_t nBytes);
397 size_t nInstructions()
const;
398 void nInstructions(
size_t);
402 void maybeInitCallStack(rose_addr_t insnVa);
419 size_t pruneCallStack();
422 void printCallStack(std::ostream&,
const std::string &prefix);
438 InstructionSemantics::BaseSemantics::SValuePtr
439 assignRegion(
const InstructionSemantics::BaseSemantics::SValuePtr &result);
441 InstructionSemantics::BaseSemantics::SValuePtr
442 assignRegion(
const InstructionSemantics::BaseSemantics::SValuePtr &result,
443 const InstructionSemantics::BaseSemantics::SValuePtr &a);
445 InstructionSemantics::BaseSemantics::SValuePtr
446 assignRegion(
const InstructionSemantics::BaseSemantics::SValuePtr &result,
447 const InstructionSemantics::BaseSemantics::SValuePtr &a,
448 const InstructionSemantics::BaseSemantics::SValuePtr &b);
454 virtual InstructionSemantics::BaseSemantics::SValuePtr
455 number_(
size_t nBits, uint64_t value)
override;
457 virtual InstructionSemantics::BaseSemantics::SValuePtr
458 extract(
const InstructionSemantics::BaseSemantics::SValuePtr&,
size_t begin,
size_t end)
override;
460 virtual InstructionSemantics::BaseSemantics::SValuePtr
461 concat(
const InstructionSemantics::BaseSemantics::SValuePtr &lowBits,
462 const InstructionSemantics::BaseSemantics::SValuePtr &highBits)
override;
464 virtual InstructionSemantics::BaseSemantics::SValuePtr
465 shiftLeft(
const InstructionSemantics::BaseSemantics::SValuePtr &a,
466 const InstructionSemantics::BaseSemantics::SValuePtr &nBits)
override;
468 virtual InstructionSemantics::BaseSemantics::SValuePtr
469 shiftRight(
const InstructionSemantics::BaseSemantics::SValuePtr &a,
470 const InstructionSemantics::BaseSemantics::SValuePtr &nBits)
override;
472 virtual InstructionSemantics::BaseSemantics::SValuePtr
474 const InstructionSemantics::BaseSemantics::SValuePtr &nBits)
override;
476 virtual InstructionSemantics::BaseSemantics::SValuePtr
477 unsignedExtend(
const InstructionSemantics::BaseSemantics::SValue::Ptr &a,
size_t newWidth)
override;
479 virtual InstructionSemantics::BaseSemantics::SValuePtr
480 signExtend(
const InstructionSemantics::BaseSemantics::SValue::Ptr &a,
size_t newWidth)
override;
482 virtual InstructionSemantics::BaseSemantics::SValuePtr
483 add(
const InstructionSemantics::BaseSemantics::SValuePtr &a,
484 const InstructionSemantics::BaseSemantics::SValuePtr &b)
override;
486 virtual InstructionSemantics::BaseSemantics::SValuePtr
487 addCarry(
const InstructionSemantics::BaseSemantics::SValuePtr &a,
488 const InstructionSemantics::BaseSemantics::SValuePtr &b,
489 InstructionSemantics::BaseSemantics::SValuePtr &carryOut ,
490 InstructionSemantics::BaseSemantics::SValuePtr &overflowed )
override;
492 virtual InstructionSemantics::BaseSemantics::SValuePtr
493 subtract(
const InstructionSemantics::BaseSemantics::SValuePtr &a,
494 const InstructionSemantics::BaseSemantics::SValuePtr &b)
override;
496 virtual InstructionSemantics::BaseSemantics::SValuePtr
497 subtractCarry(
const InstructionSemantics::BaseSemantics::SValuePtr &a,
498 const InstructionSemantics::BaseSemantics::SValuePtr &b,
499 InstructionSemantics::BaseSemantics::SValuePtr &carryOut ,
500 InstructionSemantics::BaseSemantics::SValuePtr &overflowed )
override;
502 virtual InstructionSemantics::BaseSemantics::SValuePtr
503 addWithCarries(
const InstructionSemantics::BaseSemantics::SValuePtr &a,
504 const InstructionSemantics::BaseSemantics::SValuePtr &b,
505 const InstructionSemantics::BaseSemantics::SValuePtr &c,
506 InstructionSemantics::BaseSemantics::SValuePtr &carryOut )
override;
508 virtual InstructionSemantics::BaseSemantics::SValuePtr
509 readRegister(RegisterDescriptor,
const InstructionSemantics::BaseSemantics::SValuePtr&)
override;
512 writeRegister(RegisterDescriptor,
const InstructionSemantics::BaseSemantics::SValuePtr&)
override;
514 virtual InstructionSemantics::BaseSemantics::SValuePtr
515 readMemory(RegisterDescriptor segreg,
const InstructionSemantics::BaseSemantics::SValuePtr &addr,
516 const InstructionSemantics::BaseSemantics::SValuePtr &dflt,
517 const InstructionSemantics::BaseSemantics::SValuePtr &cond)
override;
520 writeMemory(RegisterDescriptor segreg,
const InstructionSemantics::BaseSemantics::SValuePtr &addr,
521 const InstructionSemantics::BaseSemantics::SValuePtr &value,
522 const InstructionSemantics::BaseSemantics::SValuePtr &cond)
override;
530class SemanticCallbacks:
public Rose::BinaryAnalysis::ModelChecker::SemanticCallbacks {
532 using Ptr = SemanticCallbacksPtr;
537 Partitioner2::PartitionerConstPtr partitioner_;
538 SmtSolver::Memoizer::Ptr smtMemoizer_;
540 mutable SAWYER_THREAD_TRAITS::Mutex unitsMutex_;
543 mutable SAWYER_THREAD_TRAITS::Mutex mutex_;
544 std::set<uint64_t> seenStates_;
545 size_t nDuplicateStates_ = 0;
546 size_t nSolverFailures_ = 0;
547 UnitCounts unitsReached_;
548 Variables::VariableFinderPtr variableFinder_;
549 Variables::GlobalVariables gvars_;
557 bool followingOnePath_ =
false;
558 std::list<ExecutionUnitPtr> onePath_;
561 SemanticCallbacks(
const ModelChecker::SettingsPtr&,
const Settings&,
const Partitioner2::PartitionerConstPtr&);
563 ~SemanticCallbacks();
566 static Ptr instance(
const ModelChecker::SettingsPtr&,
const Settings&,
const Partitioner2::PartitionerConstPtr&);
570 Partitioner2::PartitionerConstPtr partitioner()
const;
588 void followOnePath(
const std::list<ExecutionUnitPtr>&);
601 bool followingOnePath()
const;
602 void followingOnePath(
bool);
612 SmtSolver::Memoizer::Ptr smtMemoizer()
const;
613 void smtMemoizer(
const SmtSolver::Memoizer::Ptr&);
623 size_t nDuplicateStates()
const;
632 size_t nSolverFailures()
const;
642 size_t nUnitsReached()
const;
650 UnitCounts unitsReached()
const;
659 virtual bool filterNullDeref(
const InstructionSemantics::BaseSemantics::SValuePtr &addr,
SgAsmInstruction*,
660 TestMode testMode, IoMode ioMode);
677 virtual bool filterOobAccess(
const InstructionSemantics::BaseSemantics::SValuePtr &addr,
678 const AddressInterval &referencedRegion,
const AddressInterval &accessedRegion,
680 const FoundVariable &intendedVariable,
const FoundVariable &accessedVariable);
682 virtual bool filterUninitVar(
const InstructionSemantics::BaseSemantics::SValuePtr &addr,
683 const AddressInterval &referencedREgion,
const AddressInterval &accessedRegion,
684 SgAsmInstruction *insn, TestMode testMode,
const FoundVariable &accessedVariable);
687 virtual void reset()
override;
689 virtual InstructionSemantics::BaseSemantics::SValuePtr protoval()
override;
691 virtual InstructionSemantics::BaseSemantics::RegisterStatePtr createInitialRegisters()
override;
693 virtual InstructionSemantics::BaseSemantics::MemoryStatePtr createInitialMemory()
override;
695 virtual InstructionSemantics::BaseSemantics::StatePtr createInitialState()
override;
697 virtual InstructionSemantics::BaseSemantics::RiscOperatorsPtr createRiscOperators()
override;
700 initializeState(
const InstructionSemantics::BaseSemantics::RiscOperatorsPtr&)
override;
702 virtual InstructionSemantics::BaseSemantics::DispatcherPtr
703 createDispatcher(
const InstructionSemantics::BaseSemantics::RiscOperatorsPtr&)
override;
705 virtual SmtSolver::Ptr createSolver()
override;
707 virtual void attachModelCheckerSolver(
const InstructionSemantics::BaseSemantics::RiscOperatorsPtr&,
708 const SmtSolver::Ptr&)
override;
710 virtual CodeAddresses
711 nextCodeAddresses(
const InstructionSemantics::BaseSemantics::RiscOperatorsPtr&)
override;
713 virtual std::vector<TagPtr>
714 preExecute(
const ExecutionUnitPtr&,
const InstructionSemantics::BaseSemantics::RiscOperatorsPtr&)
override;
716 virtual std::vector<TagPtr>
717 postExecute(
const ExecutionUnitPtr&,
const InstructionSemantics::BaseSemantics::RiscOperatorsPtr&)
override;
719 virtual InstructionSemantics::BaseSemantics::SValuePtr
720 instructionPointer(
const InstructionSemantics::BaseSemantics::RiscOperatorsPtr&)
override;
722 virtual std::vector<NextUnit>
723 nextUnits(
const PathPtr&,
const InstructionSemantics::BaseSemantics::RiscOperatorsPtr&,
const SmtSolver::Ptr&)
override;
725#ifdef ROSE_HAVE_YAMLCPP
726 virtual std::list<ExecutionUnitPtr>
727 parsePath(
const YAML::Node&,
const std::string &sourceName)
override;
730 virtual std::list<ExecutionUnitPtr>
731 parsePath(
const Yaml::Node&,
const std::string &sourceName)
override;
735 bool seenState(
const InstructionSemantics::BaseSemantics::RiscOperatorsPtr&);
738 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.
SharedPointer< U > dynamicCast() const
Dynamic cast.
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 StackVariables &, const Partitioner2::PartitionerConstPtr &, std::ostream &out, const std::string &prefix="")
Print info about multiple local 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.