ROSE 0.11.145.192
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#include <boost/serialization/access.hpp>
18#include <boost/serialization/split_member.hpp>
19
20#include <set>
21#include <string>
22#include <vector>
23
24namespace Rose {
25namespace BinaryAnalysis {
26
32public:
34 enum Reason {
35 // Predefined reasons
37 PROGRAM_ENTRY_POINT = 0x00000001,
38 EXPORTED_FUNCTION = 0x00000002,
39 SIGNAL_HANDLER = 0x00000004,
40 ASSUMED = 0x00000080,
41 EXPLICIT_MEM_CONSTANT = 0x00000100,
45 // User-defined reasons
46 USER_DEFINED_0 = 0x00010000,
47 USER_DEFINED_1 = 0x00020000,
48 USER_DEFINED_2 = 0x00040000,
49 USER_DEFINED_3 = 0x00080000,
50 USER_DEFINED_4 = 0x00100000,
51 USER_DEFINED_5 = 0x00200000,
52 USER_DEFINED_6 = 0x00400000,
53 USER_DEFINED_7 = 0x00800000,
54 USER_DEFINED_8 = 0x01000000,
55 USER_DEFINED_9 = 0x02000000,
56 USER_DEFINED_10 = 0x04000000,
57 USER_DEFINED_11 = 0x08000000,
58 USER_DEFINED_12 = 0x10000000,
59 USER_DEFINED_13 = 0x20000000,
60 USER_DEFINED_14 = 0x40000000,
61 USER_DEFINED_15 = 0x80000000
62 };
63
66
96
97 /* Mapping from functions to sets of CFG vertex IDs. */
98 typedef Sawyer::Container::Map<Partitioner2::FunctionPtr, std::set<size_t/*vertexId*/> > FunctionToVertexMap;
99
100public:
103
104private:
105 Settings settings_; // settings that affect behavior
106 std::vector<ReasonFlags> intrinsicReachability_; // intrinsic reachability of each vertex in the CFG
107 std::vector<ReasonFlags> reachability_; // computed reachability of each vertex in the CFG
108 FunctionToVertexMap dfReferents_; // results from findImplicitFunctionReferents
109 Sawyer::Container::Tracker<size_t> scannedVertexIds_; // vertex IDs that have been used for marking intrinsic reachability
110
111#ifdef ROSE_HAVE_BOOST_SERIALIZATION_LIB
112private:
113 friend class boost::serialization::access;
114
115 template<class S>
116 void serialize(S &s, const unsigned version) {
117 // Version zero files are no longer supported. I don't think there are two many of these around anyway and supporting
118 // backward compatibility for version 0 is not trivial.
119 if (version < 1) {
120 mlog[Sawyer::Message::FATAL] <<"cannot de-serialized version " <<version <<" object\n";
121 ASSERT_not_reachable("aborting due to unsupported old serialization file format");
122 }
123 s & BOOST_SERIALIZATION_NVP(intrinsicReachability_);
124 s & BOOST_SERIALIZATION_NVP(reachability_);
125 s & BOOST_SERIALIZATION_NVP(intrinsicReachability_);
126 s & BOOST_SERIALIZATION_NVP(reachability_);
127 // s & BOOST_SERIALIZATION_NVP(settings_); -- not serialized
128 // s & BOOST_SERIALIZATION_NVP(dfReferents_); -- not serialized
129 // s & BOOST_SERIALIZATION_NVP(scannedVertexIds_); -- not serialized
130 }
131#endif
132
133public:
134 ~Reachability();
135
140
144 static void initDiagnostics();
145
149 const Settings& settings() const { return settings_; }
150 Settings& settings() { return settings_; }
151 void settings(const Settings &s) { settings_ = s; }
160
165 static std::string reasonArgument(Reason);
166
174
178 static std::string reasonArgumentDocumentation();
179
187 static void insertReasonSwitch(Sawyer::CommandLine::SwitchGroup&, const std::string &switchName, ReasonFlags &storage,
188 Reason dfltArg, const std::string &doc);
189
195 static std::string reasonDocumentation(Reason dflt);
196
200 void clear();
201
206
234
241
248
259 size_t markExplicitMemoryReferents(const Partitioner2::PartitionerConstPtr&, const MemoryMapPtr&, size_t bytesPerWord = 0,
260 size_t alignment = 0, ByteOrder::Endianness sex = ByteOrder::ORDER_UNSPECIFIED,
262
270
276 size_t markSpecifiedVas(const Partitioner2::PartitionerConstPtr&, const std::vector<AddressInterval>&, ReasonFlags);
277
285 size_t intrinsicallyReachable(size_t vertexId, ReasonFlags how);
286
290 template<class ForwardIterator>
291 size_t intrinsicallyReachable(ForwardIterator begin, ForwardIterator end, ReasonFlags how) {
292 size_t nChanged = 0;
293 while (begin != end)
294 nChanged += intrinsicallyReachable(*begin++, how);
295 return nChanged;
296 }
297
308 static bool hasReasons(ReasonFlags reasons,
310
314 bool isIntrinsicallyReachable(size_t vertexId,
316 ReasonFlags none = ReasonFlags()) const;
317
321 bool isReachable(size_t vertexId,
323 ReasonFlags none = ReasonFlags()) const;
324
333 ReasonFlags intrinsicReachability(size_t vertexId) const;
334 const std::vector<ReasonFlags>& intrinsicReachability() const;
345 ReasonFlags reachability(size_t vertexId) const;
346 const std::vector<ReasonFlags>& reachability() const;
355 ReasonFlags none = ReasonFlags()) const;
356
366 size_t propagate(const Partitioner2::PartitionerConstPtr&, std::vector<size_t> &changedVertexIds /*in,out*/);
375
380 static std::set<size_t>
382
389 std::set<size_t>
391 size_t alignment = 0, ByteOrder::Endianness sex = ByteOrder::ORDER_UNSPECIFIED);
392
397 static std::set<size_t>
399
400private:
401 // Implementation of the "propagate" functions
402 size_t propagateImpl(const Partitioner2::PartitionerConstPtr&, std::vector<size_t>*);
403
404 // Resize vectors based on partitioner CFG size
405 void resize(const Partitioner2::PartitionerConstPtr&);
406
407 // Run findImplicitFunctionReferents on all (or specified) functions in parallel and cache the results
408 void cacheAllImplicitFunctionReferents(const Partitioner2::PartitionerConstPtr&);
409 void cacheImplicitFunctionReferents(const Partitioner2::PartitionerConstPtr&, const std::set<Partitioner2::FunctionPtr>&);
410
411 // Do the marking part of the "iterate" function.
412 size_t iterationMarking(const Partitioner2::PartitionerConstPtr&, const std::vector<size_t> &vertexIds);
413};
414
415} // namespace
416} // namespace
417
418// Class versions must be at global scope
419BOOST_CLASS_VERSION(Rose::BinaryAnalysis::Reachability, 1);
420
421#endif
422#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.
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.
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.
rose_addr_t addressAlignment
Alignment 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.