ROSE 0.11.145.237
Reachability.h
1#ifndef ROSE_BinaryAnalysis_Reachability_H
2#define ROSE_BinaryAnalysis_Reachability_H
3#include <featureTests.h>
4#ifdef ROSE_ENABLE_BINARY_ANALYSIS
5
6#include <Rose/BinaryAnalysis/Address.h>
7#include <Rose/BinaryAnalysis/BasicTypes.h>
8#include <Rose/BinaryAnalysis/ByteOrder.h>
9#include <Rose/BinaryAnalysis/Partitioner2/BasicTypes.h>
10#include <Rose/BitFlags.h>
11
12#include <Sawyer/CommandLine.h>
13#include <Sawyer/Map.h>
14#include <Sawyer/Message.h>
15#include <Sawyer/Tracker.h>
16
17#ifdef ROSE_ENABLE_BOOST_SERIALIZATION
18#include <boost/serialization/access.hpp>
19#include <boost/serialization/split_member.hpp>
20#endif
21
22#include <set>
23#include <string>
24#include <vector>
25
26namespace Rose {
27namespace BinaryAnalysis {
28
34public:
36 enum Reason {
37 // Predefined reasons
39 PROGRAM_ENTRY_POINT = 0x00000001,
40 EXPORTED_FUNCTION = 0x00000002,
41 SIGNAL_HANDLER = 0x00000004,
42 ASSUMED = 0x00000080,
43 EXPLICIT_MEM_CONSTANT = 0x00000100,
47 // User-defined reasons
48 USER_DEFINED_0 = 0x00010000,
49 USER_DEFINED_1 = 0x00020000,
50 USER_DEFINED_2 = 0x00040000,
51 USER_DEFINED_3 = 0x00080000,
52 USER_DEFINED_4 = 0x00100000,
53 USER_DEFINED_5 = 0x00200000,
54 USER_DEFINED_6 = 0x00400000,
55 USER_DEFINED_7 = 0x00800000,
56 USER_DEFINED_8 = 0x01000000,
57 USER_DEFINED_9 = 0x02000000,
58 USER_DEFINED_10 = 0x04000000,
59 USER_DEFINED_11 = 0x08000000,
60 USER_DEFINED_12 = 0x10000000,
61 USER_DEFINED_13 = 0x20000000,
62 USER_DEFINED_14 = 0x40000000,
63 USER_DEFINED_15 = 0x80000000
64 };
65
68
98
99 /* Mapping from functions to sets of CFG vertex IDs. */
100 typedef Sawyer::Container::Map<Partitioner2::FunctionPtr, std::set<size_t/*vertexId*/> > FunctionToVertexMap;
101
102public:
105
106private:
107 Settings settings_; // settings that affect behavior
108 std::vector<ReasonFlags> intrinsicReachability_; // intrinsic reachability of each vertex in the CFG
109 std::vector<ReasonFlags> reachability_; // computed reachability of each vertex in the CFG
110 FunctionToVertexMap dfReferents_; // results from findImplicitFunctionReferents
111 Sawyer::Container::Tracker<size_t> scannedVertexIds_; // vertex IDs that have been used for marking intrinsic reachability
112
113#ifdef ROSE_ENABLE_BOOST_SERIALIZATION
114private:
115 friend class boost::serialization::access;
116
117 template<class S>
118 void serialize(S &s, const unsigned version) {
119 // Version zero files are no longer supported. I don't think there are two many of these around anyway and supporting
120 // backward compatibility for version 0 is not trivial.
121 if (version < 1) {
122 mlog[Sawyer::Message::FATAL] <<"cannot de-serialized version " <<version <<" object\n";
123 ASSERT_not_reachable("aborting due to unsupported old serialization file format");
124 }
125 s & BOOST_SERIALIZATION_NVP(intrinsicReachability_);
126 s & BOOST_SERIALIZATION_NVP(reachability_);
127 s & BOOST_SERIALIZATION_NVP(intrinsicReachability_);
128 s & BOOST_SERIALIZATION_NVP(reachability_);
129 // s & BOOST_SERIALIZATION_NVP(settings_); -- not serialized
130 // s & BOOST_SERIALIZATION_NVP(dfReferents_); -- not serialized
131 // s & BOOST_SERIALIZATION_NVP(scannedVertexIds_); -- not serialized
132 }
133#endif
134
135public:
136 ~Reachability();
137
142
146 static void initDiagnostics();
147
151 const Settings& settings() const { return settings_; }
152 Settings& settings() { return settings_; }
153 void settings(const Settings &s) { settings_ = s; }
162
167 static std::string reasonArgument(Reason);
168
176
180 static std::string reasonArgumentDocumentation();
181
189 static void insertReasonSwitch(Sawyer::CommandLine::SwitchGroup&, const std::string &switchName, ReasonFlags &storage,
190 Reason dfltArg, const std::string &doc);
191
197 static std::string reasonDocumentation(Reason dflt);
198
202 void clear();
203
208
236
243
250
261 size_t markExplicitMemoryReferents(const Partitioner2::PartitionerConstPtr&, const MemoryMapPtr&, size_t bytesPerWord = 0,
262 size_t alignment = 0, ByteOrder::Endianness sex = ByteOrder::ORDER_UNSPECIFIED,
264
272
278 size_t markSpecifiedVas(const Partitioner2::PartitionerConstPtr&, const std::vector<AddressInterval>&, ReasonFlags);
279
287 size_t intrinsicallyReachable(size_t vertexId, ReasonFlags how);
288
292 template<class ForwardIterator>
293 size_t intrinsicallyReachable(ForwardIterator begin, ForwardIterator end, ReasonFlags how) {
294 size_t nChanged = 0;
295 while (begin != end)
296 nChanged += intrinsicallyReachable(*begin++, how);
297 return nChanged;
298 }
299
310 static bool hasReasons(ReasonFlags reasons,
312
316 bool isIntrinsicallyReachable(size_t vertexId,
318 ReasonFlags none = ReasonFlags()) const;
319
323 bool isReachable(size_t vertexId,
325 ReasonFlags none = ReasonFlags()) const;
326
335 ReasonFlags intrinsicReachability(size_t vertexId) const;
336 const std::vector<ReasonFlags>& intrinsicReachability() const;
347 ReasonFlags reachability(size_t vertexId) const;
348 const std::vector<ReasonFlags>& reachability() const;
357 ReasonFlags none = ReasonFlags()) const;
358
368 size_t propagate(const Partitioner2::PartitionerConstPtr&, std::vector<size_t> &changedVertexIds /*in,out*/);
377
382 static std::set<size_t>
384
391 std::set<size_t>
393 size_t alignment = 0, ByteOrder::Endianness sex = ByteOrder::ORDER_UNSPECIFIED);
394
399 static std::set<size_t>
401
402private:
403 // Implementation of the "propagate" functions
404 size_t propagateImpl(const Partitioner2::PartitionerConstPtr&, std::vector<size_t>*);
405
406 // Resize vectors based on partitioner CFG size
407 void resize(const Partitioner2::PartitionerConstPtr&);
408
409 // Run findImplicitFunctionReferents on all (or specified) functions in parallel and cache the results
410 void cacheAllImplicitFunctionReferents(const Partitioner2::PartitionerConstPtr&);
411 void cacheImplicitFunctionReferents(const Partitioner2::PartitionerConstPtr&, const std::set<Partitioner2::FunctionPtr>&);
412
413 // Do the marking part of the "iterate" function.
414 size_t iterationMarking(const Partitioner2::PartitionerConstPtr&, const std::vector<size_t> &vertexIds);
415};
416
417} // namespace
418} // namespace
419
420// Class versions must be at global scope
421#ifdef ROSE_ENABLE_BOOST_SERIALIZATION
422BOOST_CLASS_VERSION(Rose::BinaryAnalysis::Reachability, 1);
423#endif
424
425#endif
426#endif
Analysis that computes reachability of CFG vertices.
bool isIntrinsicallyReachable(size_t vertexId, ReasonFlags any=ReasonFlags(), ReasonFlags all=ReasonFlags(), ReasonFlags none=ReasonFlags()) const
Query whether a vertex is intrinsic reachable.
size_t intrinsicallyReachable(size_t vertexId, ReasonFlags how)
Change intrinsic reachability for one vertex.
std::vector< size_t > reachableVertices(ReasonFlags any=ReasonFlags(), ReasonFlags all=ReasonFlags(), ReasonFlags none=ReasonFlags()) const
Return a list of reachable vertex IDs.
const std::vector< ReasonFlags > & reachability() const
Query computed reachability.
size_t markStartingPoints(const Partitioner2::PartitionerConstPtr &)
Mark starting points as intrinsically reachable according to settings.
const std::vector< ReasonFlags > & intrinsicReachability() const
Query intrinsic reachability.
void clearReachability()
Clear all reachability.
ReasonFlags intrinsicReachability(size_t vertexId) const
Query intrinsic reachability.
size_t markEntryFunctions(const Partitioner2::PartitionerConstPtr &, ReasonFlags how=PROGRAM_ENTRY_POINT)
Mark entry points as intrinsically reachable.
Settings & settings()
Property: Settings that influence the analysis.
BitFlags< Reason, uint32_t > ReasonFlags
Bit flags for reachability.
void clear()
Clear previous results.
Reason
Predefined bit flags for why something is reachable.
@ USER_DEFINED_14
User-defined reason.
@ USER_DEFINED_7
User-defined reason.
@ USER_DEFINED_3
User-defined reason.
@ EXPORTED_FUNCTION
Vertex is an exported function.
@ IMPLICIT_FUNC_CONSTANT
Address appears during data-flow in some reachable function.
@ USER_DEFINED_10
User-defined reason.
@ USER_DEFINED_5
User-defined reason.
@ NOT_REACHABLE
Vertex is not reachable.
@ USER_DEFINED_8
User-defined reason.
@ USER_DEFINED_12
User-defined reason.
@ USER_DEFINED_9
User-defined reason.
@ USER_DEFINED_11
User-defined reason.
@ USER_DEFINED_4
User-defined reason.
@ USER_DEFINED_0
User-defined reason.
@ USER_DEFINED_13
User-defined reason.
@ USER_DEFINED_1
User-defined reason.
@ USER_DEFINED_15
User-defined reason.
@ USER_DEFINED_6
User-defined reason.
@ EXPLICIT_INSN_CONSTANT
Address appears as a constant in some reachable instruction.
@ USER_DEFINED_2
User-defined reason.
@ SIGNAL_HANDLER
Vertex is a signal handler.
@ PROGRAM_ENTRY_POINT
Vertex is a program entry point.
@ EXPLICIT_MEM_CONSTANT
Address appears in memory.
@ ASSUMED
Assumed reachable for cases when the analysis wasn't run.
size_t propagate(const Partitioner2::PartitionerConstPtr &, std::vector< size_t > &changedVertexIds)
Propagate intrinsic reachability through the graph.
size_t intrinsicallyReachable(ForwardIterator begin, ForwardIterator end, ReasonFlags how)
Change intrinsic reachabability for multiple vertices.
size_t markImplicitFunctionReferents(const Partitioner2::PartitionerConstPtr &, const Partitioner2::FunctionPtr &, ReasonFlags how=IMPLICIT_FUNC_CONSTANT)
Mark vertices whose addressses appear in a function.
static Sawyer::Message::Facility mlog
Facility for emitting diagnostics.
size_t markExportFunctions(const Partitioner2::PartitionerConstPtr &, ReasonFlags how=EXPORTED_FUNCTION)
Mark exported functions as intrinsically reachable.
static void initDiagnostics()
Initialize diagnostic streams.
size_t markExplicitInstructionReferents(const Partitioner2::PartitionerConstPtr &, const Partitioner2::BasicBlockPtr &, ReasonFlags how=EXPLICIT_INSN_CONSTANT)
Mark vertices whose addresses appear in instructions.
void settings(const Settings &s)
Property: Settings that influence the analysis.
static std::string reasonArgument(Reason)
Convert a reachability reason enum constant to a parsable reason name.
static Sawyer::CommandLine::SwitchGroup commandLineSwitches(Settings &settings)
Describes how to parse switches related to reachability.
static Sawyer::CommandLine::ValueParser::Ptr reasonParser(ReasonFlags &storage)
Creates a command-line parser for reachability reason names.
void iterate(const Partitioner2::PartitionerConstPtr &partitioner)
Iteratively propagate and mark.
static void insertReasonSwitch(Sawyer::CommandLine::SwitchGroup &, const std::string &switchName, ReasonFlags &storage, Reason dfltArg, const std::string &doc)
Insert a switch that takes a reason argument.
bool isReachable(size_t vertexId, ReasonFlags any=ReasonFlags(), ReasonFlags all=ReasonFlags(), ReasonFlags none=ReasonFlags()) const
Query whether a vertex is reachable.
static std::set< size_t > findExplicitInstructionReferents(const Partitioner2::PartitionerConstPtr &, const Partitioner2::BasicBlockPtr &)
Find all CFG vertices mentioned explicitly in a basic block.
size_t markSpecifiedVas(const Partitioner2::PartitionerConstPtr &, const std::vector< AddressInterval > &, ReasonFlags)
Mark all basic blocks with in the specified ranges.
const Settings & settings() const
Property: Settings that influence the analysis.
static std::string reasonDocumentation(Reason dflt)
Generate documentation for the command-line switches.
static std::set< size_t > findImplicitFunctionReferents(const Partitioner2::PartitionerConstPtr &, const Partitioner2::FunctionPtr &)
Find all CFG vertices referenced from a function.
size_t propagate(const Partitioner2::PartitionerConstPtr &)
Propagate intrinsic reachability through the graph.
std::set< size_t > findExplicitMemoryReferents(const Partitioner2::PartitionerConstPtr &, const MemoryMapPtr &, size_t bytesPerWord=0, size_t alignment=0, ByteOrder::Endianness sex=ByteOrder::ORDER_UNSPECIFIED)
Find all CFG vertices mentioned in memory.
ReasonFlags reachability(size_t vertexId) const
Query computed reachability.
size_t markExplicitMemoryReferents(const Partitioner2::PartitionerConstPtr &, const MemoryMapPtr &, size_t bytesPerWord=0, size_t alignment=0, ByteOrder::Endianness sex=ByteOrder::ORDER_UNSPECIFIED, ReasonFlags how=EXPLICIT_MEM_CONSTANT)
Mark vertices whose addresses appear in memory.
size_t markStartingPoints(const Partitioner2::PartitionerConstPtr &, const MemoryMapPtr &)
Mark starting points as intrinsically reachable according to settings.
static std::string reasonArgumentDocumentation()
Documentation for the possible reason arguments.
static bool hasReasons(ReasonFlags reasons, ReasonFlags any=ReasonFlags(), ReasonFlags all=ReasonFlags(), ReasonFlags none=ReasonFlags())
Predicate to match reason flags.
Reachability()
Default constructor.
Stores a vector of enum bit flags.
A collection of related switch declarations.
Container associating values with keys.
Definition Sawyer/Map.h:72
Tracks whether something has been seen before.
Definition Tracker.h:167
Collection of streams.
Definition Message.h:1606
Holds a value or nothing.
Definition Optional.h:56
@ ORDER_UNSPECIFIED
Endianness is unspecified and unknown.
Definition ByteOrder.h:21
Sawyer::SharedPointer< Function > FunctionPtr
Shared-ownership pointer for Function.
std::uint64_t Address
Address.
Definition Address.h:11
The ROSE library.
@ FATAL
Messages that indicate an abnormal situation from which the program was unable to recover.
Definition Message.h:332
Settings controlling the analysis.
Address addressAlignment
Alignment when reading constants from virtual memory.
ReasonFlags markingImplicitFunctionReferents
If not empty, run markImplicitFunctionReferents during iteration.
ReasonFlags markingExplicitMemoryReferents
If not empty, run markExplicitMemoryReferents at startup.
ReasonFlags markingExplicitInstructionReferents
If not empty, run markExplicitInstructionReferents during iteration.
ReasonFlags markingExportFunctions
If not empty, run markExportFunctions at startup.
bool precomputeImplicitFunctionReferents
Implicit function referents are precomputed in parallel.
ByteOrder::Endianness byteOrder
Byte order to use when reading constants from virtual memory.
Sawyer::Optional< size_t > nThreads
Parallelism; 0 means system; unset means use global value.
size_t addressNBytes
Size of addresses when reading constants from virtual memory.
ReasonFlags markingEntryFunctions
If not empty, run markEntryFunctions at startup.