1 #ifndef ROSE_BinaryAnalysis_Partitioner2_ParallelPartitioner_H
2 #define ROSE_BinaryAnalysis_Partitioner2_ParallelPartitioner_H
3 #include <featureTests.h>
4 #if defined(ROSE_ENABLE_BINARY_ANALYSIS) && __cplusplus >= 201103L
6 #include <Rose/BinaryAnalysis/InstructionCache.h>
7 #include <Rose/Progress.h>
9 #include <Rose/BinaryAnalysis/Partitioner2/BasicTypes.h>
10 #include <Rose/BinaryAnalysis/Partitioner2/Semantics.h>
11 #include <Sawyer/Attribute.h>
12 #include <Sawyer/Graph.h>
13 #include <Sawyer/IntervalSetMap.h>
14 #include <Sawyer/Message.h>
15 #include <Sawyer/SharedObject.h>
18 namespace BinaryAnalysis {
19 namespace Partitioner2 {
20 namespace Experimental {
21 namespace ParallelPartitioner {
37 using FunctionReasons = BitFlags<SgAsmFunction::FunctionReason>;
41 size_t maxAnalysisBBlockSize = 20;
42 Accuracy successorAccuracy = Accuracy::LOW;
43 Accuracy functionCallDetectionAccuracy = Accuracy::LOW;
44 size_t minHoleSearch = 8;
63 template<
class V,
class K>
71 mutable SAWYER_THREAD_TRAITS::Mutex mutex_;
79 void set(
const Key &key,
const Value &value) {
80 SAWYER_THREAD_TRAITS::LockGuard lock(mutex_);
91 bool maybeSet(
const Key &key,
const Value &value) {
92 SAWYER_THREAD_TRAITS::LockGuard lock(mutex_);
93 if (key_ && *key_ == key) {
105 OptionalValue
get(
const Key &key)
const {
106 SAWYER_THREAD_TRAITS::LockGuard lock(mutex_);
107 if (key_ && *key_ == key)
115 OptionalValue take(
const Key &key) {
116 SAWYER_THREAD_TRAITS::LockGuard lock(mutex_);
117 if (key_ && *key_ == key) {
118 auto retval = value_;
130 SAWYER_THREAD_TRAITS::LockGuard lock(mutex_);
138 bool exists(
const Key &key)
const {
139 SAWYER_THREAD_TRAITS::LockGuard lock(mutex_);
140 return key_ && *key_ == key;
146 class CachedItem<V, void> {
153 mutable SAWYER_THREAD_TRAITS::Mutex mutex_;
154 OptionalValue value_;
157 void set(
const Value &value) {
158 SAWYER_THREAD_TRAITS::LockGuard lock(mutex_);
162 bool maybeSet(
const Value &value) {
163 SAWYER_THREAD_TRAITS::LockGuard lock(mutex_);
172 OptionalValue
get()
const {
173 SAWYER_THREAD_TRAITS::LockGuard lock(mutex_);
177 OptionalValue take()
const {
178 SAWYER_THREAD_TRAITS::LockGuard lock(mutex_);
179 auto retval = value_;
185 SAWYER_THREAD_TRAITS::LockGuard lock(mutex_);
189 bool exists()
const {
190 SAWYER_THREAD_TRAITS::LockGuard lock(mutex_);
199 template<
class Cache>
202 typename Cache::Key key_;
203 typename Cache::OptionalValue value_;
208 Borrowed(Cache &cache,
typename Cache::Key key)
209 : cache_(cache), key_(key), value_(cache_.take(key)), canceled_(false) {}
212 Borrowed(Cache &cache,
typename Cache::Key key,
const typename Cache::Value &value)
213 : cache_(cache), key_(key), value_(value), canceled_(false) {}
233 if (!canceled_ && value_ && !cache_.maybeSet(key_, *value_)) {
244 const typename Cache::OptionalValue&
get()
const {
252 template<
class Cache>
253 Borrowed<Cache> borrow(Cache &cache,
typename Cache::Key key) {
254 return Borrowed<Cache>(cache, key);
261 template<
class Cache>
262 Borrowed<Cache> borrow(Cache &cache,
typename Cache::Key key,
const typename Cache::Value &value) {
263 return Borrowed<Cache>(cache, key, value);
271 class InsnInfo: boost::noncopyable {
273 using Ptr = std::shared_ptr<InsnInfo>;
274 using List = std::vector<Ptr>;
283 struct Cached: boost::noncopyable {
284 CachedItem<bool, uint64_t> isFunctionCall;
285 CachedItem<Semantics::RiscOperatorsPtr, uint64_t> semantics;
290 const rose_addr_t va_;
293 mutable SAWYER_THREAD_TRAITS::Mutex mutex_;
296 FunctionReasons functionReasons_;
304 explicit InsnInfo(
const InstructionPtr &insn)
305 : ast_(insn), va_(insn->get_address()), size_(insn->get_size()), wasDecoded_(false) {
306 ASSERT_not_null(insn);
307 ASSERT_require(size_ > 0);
311 explicit InsnInfo(rose_addr_t va)
312 : va_(va), size_(0), wasDecoded_(false) {}
321 rose_addr_t address()
const {
351 FunctionReasons functionReasons()
const;
352 void functionReasons(FunctionReasons);
353 void insertFunctionReasons(FunctionReasons);
354 void eraseFunctionReasons(FunctionReasons);
362 const Cached& cached()
const {
return cached_; }
363 Cached& cached() {
return cached_; }
379 bool wasDecoded()
const;
390 InstructionPtr ast()
const;
397 static bool addressOrder(
const Ptr &a,
const Ptr &b);
404 static uint64_t
hash(
const List&);
407 friend class Partitioner;
416 InstructionPtr setAstMaybe(
const InstructionPtr&);
426 using EdgeTypes = BitFlags<EdgeType>;
436 void merge(
const CfgEdge &other) {
437 types_.set(other.types_);
440 EdgeTypes types()
const {
444 void types(EdgeTypes x) {
448 friend std::ostream& operator<<(std::ostream&,
const CfgEdge&);
459 InsnInfoKey(
const InsnInfo::Ptr &insnInfo)
460 : va_(insnInfo->address()) {}
461 InsnInfoKey(rose_addr_t va)
465 bool operator<(
const InsnInfoKey &other)
const {
466 return va_ < other.va_;
493 DiscoverInstruction = 0,
498 Partitioner &partitioner_;
510 WorkItem(Partitioner &partitioner, Priority priority, uint64_t sort)
511 : partitioner_(partitioner), priority_(priority), sort_(sort) {}
513 virtual ~WorkItem() {}
516 Partitioner& partitioner()
const {
529 bool operator<(
const WorkItem&)
const;
535 virtual void run() = 0;
538 virtual std::string title()
const = 0;
550 class DecodeInstruction:
public WorkItem {
555 DecodeInstruction(Partitioner &partitioner, rose_addr_t va)
556 : WorkItem(partitioner, WorkItem::
Priority::DiscoverInstruction,
571 std::string title()
const override {
586 class NextUnusedRegion:
public WorkItem {
591 NextUnusedRegion(Partitioner &partitioner,
const AddressInterval &where)
592 : WorkItem(partitioner, WorkItem::
Priority::NextUnusedVa, where ? where.least() : uint64_t(0)), where(where) {}
594 std::string title()
const override {
605 class WorkItemSorter {
607 bool operator()(
const std::shared_ptr<WorkItem>&,
const std::shared_ptr<WorkItem>&)
const;
616 class Scheduler final {
618 using Item = std::shared_ptr<WorkItem>;
619 using Container = std::vector<Item>;
620 using Queue = std::priority_queue<Item, Container, WorkItemSorter>;
623 mutable SAWYER_THREAD_TRAITS::Mutex mutex_;
628 void insert(
const Item&);
631 bool isEmpty()
const;
637 void reportStatus(std::ostream&)
const;
650 void operator()(std::shared_ptr<WorkItem> work, Scheduler&) {
675 Scheduler scheduler_;
676 std::shared_ptr<InstructionCache> insnCache_;
678 rose_addr_t nExeVas_;
680 mutable SAWYER_THREAD_TRAITS::Mutex mutex_;
705 const Settings&
settings()
const {
return settings_; }
706 Settings&
settings() {
return settings_; }
713 static Accuracy choose(Accuracy a, Accuracy b);
732 void statusReports();
751 size_t nDecodedAddresses()
const;
774 InstructionPtr decodeInstruction(rose_addr_t);
793 InsnInfo::Ptr makeInstruction(rose_addr_t);
794 InsnInfo::Ptr makeInstruction(rose_addr_t,
const InstructionPtr&);
803 InsnInfo::Ptr existingInstruction(rose_addr_t);
812 InstructionPtr existingInstructionAst(rose_addr_t);
819 InstructionCache& instructionCache()
const;
823 std::vector<LockedInstruction> locks;
824 std::vector<SgAsmInstruction*> insns;
845 LockInCache lockInCache(
const InsnInfo::List&);
848 struct CreateLinkedCfgVertices {
849 bool createdSource =
false;
850 bool createdTarget =
false;
851 bool createdEdge =
false;
852 InsnInfo::Ptr source;
853 InsnInfo::Ptr target;
863 CreateLinkedCfgVertices createLinkedCfgVertices(rose_addr_t sourceVa, rose_addr_t targetVa,
const CfgEdge&);
871 void scheduleDecodeInstruction(rose_addr_t insnVa);
891 InsnInfo::List basicBlockEndingAt(rose_addr_t,
size_t maxInsns =
UNLIMITED)
const;
899 InsnInfo::List basicBlockContaining(rose_addr_t)
const;
914 Borrowed<CachedItem<Semantics::RiscOperatorsPtr, uint64_t>> basicBlockSemantics(
const InsnInfo::List&);
929 std::vector<SymbolicExpression::Ptr> computeSuccessors(
const InsnInfo::List&, Accuracy accuracy);
930 std::vector<SymbolicExpression::Ptr> computeSuccessors(rose_addr_t insnVa, Accuracy accuracy);
943 AddressSet computedConcreteSuccessors(rose_addr_t insnVa, Accuracy accuracy);
952 bool isFunctionCall(rose_addr_t insnVa, Accuracy accuracy);
974 void run(
size_t maxWorkers);
981 bool isRunning()
const;
985 void isRunning(
bool b);
1002 const InsnCfg& insnCfg()
const;
1009 void printInsnCfg(std::ostream&)
const;
1025 std::vector<InsnInfo::List> allBasicBlocks()
const;
1032 std::map<rose_addr_t , rose_addr_t > calculateInsnToBbMap()
const;
1038 static bool addressOrder(
const InsnInfo::List &a,
const InsnInfo::List &b);
1047 std::map<rose_addr_t , AddressSet > assignFunctions();
1061 rose_addr_t remap();
Graph containing user-defined vertices and edges.
EdgeType
Partitioner control flow edge types.
boost::shared_ptr< RiscOperators > RiscOperatorsPtr
Shared-ownership pointer to a RISC operators object.
ROSE_DLL_API Sawyer::Message::Facility mlog
Diagnostic facility for the ROSE library as a whole.
Mapping from integers to sets.
High precision, but slow.
void reset()
Reset as if default-constructed.
Settings settings
Command-line settings for the rosebud tool.
Main namespace for the ROSE library.
const size_t UNLIMITED(static_cast< size_t >(-1))
Effictively unlimited size.
Reference-counting intrusive smart pointer.
Name space for the entire library.
size_t fastRandomIndex(size_t n, size_t seed=0)
Thread-safe random number generator.
ROSE_DLL_API void merge(SgProject *project)
Performs sharing of AST nodes followed by linking accross translation units.
MemoryMapPtr Ptr
Reference counting pointer.
ROSE_UTIL_API std::string addrToString(uint64_t value, size_t nbits=0)
Convert a virtual address to a string.
SemanticMemoryParadigm
Organization of semantic memory.
Normal control flow edge, nothing special.
Base class for reference counted objects.
void initDiagnostics()
Initialize diagnostics.
Sawyer::SharedPointer< Node > Ptr
Reference counting pointer.
void set(Word *words, const BitRange &where)
Set some bits.
API and storage for attributes.
Sawyer::SharedPointer< Base > BasePtr
Reference counted pointer for disassemblers.
Partitions instructions into basic blocks and functions.
const char * Priority(int64_t)
Convert Rose::BinaryAnalysis::Partitioner2::Experimental::ParallelPartitioner::WorkItem::Priority enu...
const char * Accuracy(int64_t)
Convert Rose::BinaryAnalysis::Partitioner2::Experimental::ParallelPartitioner::Accuracy enum constant...
ProgressPtr Ptr
Progress objects are reference counted.
Hash hash(const std::vector< Ptr > &)
Hash zero or more expressions.