ROSE 0.11.145.147
BinaryAnalysis/Partitioner2/Utility.h
1#ifndef ROSE_BinaryAnalysis_Partitioner2_Utility_H
2#define ROSE_BinaryAnalysis_Partitioner2_Utility_H
3#include <featureTests.h>
4#ifdef ROSE_ENABLE_BINARY_ANALYSIS
5#include <Rose/BinaryAnalysis/Partitioner2/BasicTypes.h>
6
7#include <Rose/BinaryAnalysis/Partitioner2/Function.h>
8#include <Rose/CommandLine/IntervalParser.h>
9
10#include <Rose/Diagnostics.h>
11
12#include <algorithm>
13#include <ostream>
14
15namespace Rose {
16namespace BinaryAnalysis {
17namespace Partitioner2 {
18
20void initDiagnostics();
21
22bool sortBasicBlocksByAddress(const BasicBlockPtr&, const BasicBlockPtr&);
23bool sortDataBlocks(const DataBlockPtr&, const DataBlockPtr&);
24bool sortFunctionsByAddress(const FunctionPtr&, const FunctionPtr&);
25bool sortFunctionNodesByAddress(const SgAsmFunction*, const SgAsmFunction*);
26bool sortByExpression(const BasicBlockSuccessor&, const BasicBlockSuccessor&);
27bool sortBlocksForAst(SgAsmBlock*, SgAsmBlock*);
28bool sortInstructionsByAddress(SgAsmInstruction*, SgAsmInstruction*);
29
30template<class Container, class Comparator>
31static bool
32isSorted(const Container &container, Comparator sorted, bool distinct=true) {
33 typename Container::const_iterator current = container.begin();
34 if (current!=container.end()) {
35 typename Container::const_iterator next = current;
36 while (++next != container.end()) {
37 if ((distinct && !sorted(*current, *next)) || sorted(*next, *current))
38 return false;
39 ++current;
40 }
41 }
42 return true;
43}
44
45template<class Container, class Value, class Comparator>
46typename Container::const_iterator
47lowerBound(const Container &container, const Value &item, Comparator cmp) {
48 return std::lower_bound(container.begin(), container.end(), item, cmp);
49}
50template<class Container, class Value, class Comparator>
51typename Container::iterator
52lowerBound(Container &container, const Value &item, Comparator cmp) {
53 return std::lower_bound(container.begin(), container.end(), item, cmp);
54}
55
56// Return true if two container elements are equal according to the sorting comparator
57template<class Value, class Comparator>
58bool
59equalUnique(const Value &a, const Value &b, Comparator cmp) {
60 return !cmp(a, b) && !cmp(b, a); // equal iff neither one is less than the other
61}
62
63// Insert an item into a sorted container if it doesn't exist yet in the container. Returns true iff inserted.
64template<class Container, class Value, class Comparator>
65bool
66insertUnique(Container &container, const Value &item, Comparator cmp) {
67 ASSERT_require(!ROSE_PARTITIONER_EXPENSIVE_CHECKS || isSorted(container, cmp, true)); // unique, sorted items
68 typename Container::iterator lb = lowerBound(container, item, cmp);
69 if (lb==container.end() || !equalUnique(*lb, item, cmp)) {
70 container.insert(lb, item);
71 ASSERT_require(!ROSE_PARTITIONER_EXPENSIVE_CHECKS || isSorted(container, cmp, true));
72 return true;
73 }
74 return false;
75}
76
77// Insert an intem into a sorted continer, replacing any existing item that compares equal to it.
78template<class Container, class Value, class Comparator>
79void
80replaceOrInsert(Container &container, const Value &item, Comparator cmp) {
81 ASSERT_require(!ROSE_PARTITIONER_EXPENSIVE_CHECKS || isSorted(container, cmp, true)); // unique, sorted items
82 typename Container::iterator lb = lowerBound(container, item, cmp);
83 if (lb == container.end() || !equalUnique(*lb, item, cmp)) {
84 container.insert(lb, item);
85 } else {
86 *lb = item;
87 }
88 ASSERT_require(!ROSE_PARTITIONER_EXPENSIVE_CHECKS || isSorted(container, cmp, true));
89}
90
91// Erase an item from a sorted container if it doesn't exist yet in the container. Returns true iff erased.
92template<class Container, class Value, class Comparator>
93bool
94eraseUnique(Container &container, const Value &item, Comparator cmp) {
95 ASSERT_require(!ROSE_PARTITIONER_EXPENSIVE_CHECKS || isSorted(container, cmp, true)); // unique, sorted items
96 typename Container::iterator lb = lowerBound(container, item, cmp);
97 if (lb!=container.end() && equalUnique(*lb, item, cmp)) {
98 container.erase(lb);
99 return true;
100 }
101 return false;
102}
103
104// Check existence of an item in a sorted container. Returns true iff the item exists.
105template<class Container, class Value, class Comparator>
106bool
107existsUnique(const Container &container, const Value &item, Comparator cmp) {
108 if (item==NULL)
109 return false;
110 ASSERT_require(!ROSE_PARTITIONER_EXPENSIVE_CHECKS || isSorted(container, cmp, true)); // unique, sorted items
111 typename Container::const_iterator lb = lowerBound(container, item, cmp);
112 if (lb==container.end() || cmp(*lb, item) || cmp(item, *lb))
113 return false;
114 return true;
115}
116
117// Retrieve an item from a sorted container
118template<class Container, class Value, class Comparator>
120getUnique(const Container &container, const Value &item, Comparator cmp) {
121 if (item==NULL)
122 return Sawyer::Nothing();
123 ASSERT_require(!ROSE_PARTITIONER_EXPENSIVE_CHECKS || isSorted(container, cmp, true)); // unique, sorted items
124 typename Container::const_iterator lb = lowerBound(container, item, cmp);
125 if (lb==container.end() || cmp(*lb, item) || cmp(item, *lb))
126 return Sawyer::Nothing();
127 return *lb;
128}
129
130// Find an existing item if possible and return the item. If not found, insert the item and return false.
131template<class Container, class Value, class Comparator>
133getOrInsertUnique(Container &container, const Value &item, Comparator cmp) {
134 ASSERT_require(!ROSE_PARTITIONER_EXPENSIVE_CHECKS || isSorted(container, cmp, true)); // unique, sorted items
135 typename Container::iterator lb = lowerBound(container, item, cmp);
136 if (lb != container.end() && equalUnique(*lb, item, cmp)) {
137 return *lb;
138 } else {
139 container.insert(lb, item);
140 ASSERT_require(!ROSE_PARTITIONER_EXPENSIVE_CHECKS || isSorted(container, cmp, true));
141 return Sawyer::Nothing();
142 }
143}
144
145template<class Container, class Comparator>
146bool
147isSupersetUnique(const Container &sup, const Container &sub, Comparator lessThan) {
148 ASSERT_require(!ROSE_PARTITIONER_EXPENSIVE_CHECKS || isSorted(sup, lessThan, true)); // unique, sorted items
149 ASSERT_require(!ROSE_PARTITIONER_EXPENSIVE_CHECKS || isSorted(sub, lessThan, true)); // unique, sorted items
150 typename Container::const_iterator isup = sup.begin(), isub = sub.begin();
151 while (isup != sup.end() && isub != sub.end()) {
152 while (isup != sup.end() && lessThan(*isup, *isub))
153 ++isup;
154 if (isup == sup.end() || lessThan(*isub, *isup))
155 return false;
156 ++isup, ++isub;
157 }
158 return isub == sub.end();
159}
160
161std::ostream& operator<<(std::ostream&, const AddressUser&);
162std::ostream& operator<<(std::ostream&, const AddressUsers&);
163std::ostream& operator<<(std::ostream&, const AddressUsageMap&);
164
199
200AddressIntervalParser::Ptr addressIntervalParser(AddressInterval &storage);
201AddressIntervalParser::Ptr addressIntervalParser(std::vector<AddressInterval> &storage);
202AddressIntervalParser::Ptr addressIntervalParser(AddressIntervalSet &storage);
203AddressIntervalParser::Ptr addressIntervalParser();
204
206class Trigger {
207public:
208 typedef AddressInterval SizeInterval; // okay to use 64-bit integers for the counters
209 struct Settings {
210 SizeInterval when; // when to trigger based on nCalls_
211 Settings(): when(0) {}
212 };
213private:
214 size_t nCalls_; // number of times called
215 Settings settings_;
216public:
218 Trigger(): nCalls_(0) {}
219
221 explicit Trigger(const Settings &settings): nCalls_(0), settings_(settings) {}
222
224 Trigger(size_t nSkip, size_t nTimes): nCalls_(0) {
225 settings_.when = nTimes ? SizeInterval::baseSize(nSkip, nTimes) : SizeInterval();
226 }
227
229 static Trigger once() { return Trigger(0, 1); }
230
232 static Trigger always() { return Trigger(0, size_t(-1)); }
233
235 static Trigger never() { return Trigger(); }
236
238 bool isArmed() const { return !settings_.when.isEmpty() && nCalls_<=settings_.when.greatest(); }
239
241 bool shouldTrigger() { return settings_.when.contains(nCalls_++); }
242
244 size_t nCalls() const { return nCalls_; }
245
247 void reset() { nCalls_ = 0; }
248
251
253 static std::string docString();
254};
255
258
262boost::logic::tribool
263hasAnyCalleeReturn(const PartitionerConstPtr&, const ControlFlowGraph::ConstVertexIterator&);
264
268bool
269hasCallReturnEdges(const ControlFlowGraph::ConstVertexIterator&);
270
271
272} // namespace
273} // namespace
274} // namespace
275
276#endif
277#endif
static Ptr instance(const Sawyer::CommandLine::ValueSaver::Ptr &valueSaver)
Allocating constructor.
static std::string docString()
Runtime documentation.
Sawyer::SharedPointer< AddressIntervalParser > Ptr
Shared-ownership pointer to an AddressIntervalParser.
static Sawyer::CommandLine::SwitchGroup switches(Settings &)
Command-line switches to initialize settings.
Trigger(size_t nSkip, size_t nTimes)
Armed for triggering after nSkip calls but not more than nTimes times.
Trigger(const Settings &settings)
Armed for triggering when number of calls falls within when.
static std::string docString()
Documentation for command-line switches.
bool shouldTrigger()
Increment calls and return true if triggering.
A collection of related switch declarations.
const ValueSaver::Ptr valueSaver() const
Property: functor responsible for saving a parsed value in user storage.
T greatest() const
Returns upper limit.
Definition Interval.h:224
static Interval baseSize(Address lo, Address size)
Construct an interval from one endpoint and a size.
Definition Interval.h:173
bool contains(const Interval &other) const
Containment predicate.
Definition Interval.h:257
bool isEmpty() const
True if interval is empty.
Definition Interval.h:230
Collection of streams.
Definition Message.h:1606
Represents no value.
Definition Optional.h:36
Holds a value or nothing.
Definition Optional.h:56
Instruction basic block.
Represents a synthesized function.
Base class for machine instructions.
bool hasCallReturnEdges(const ControlFlowGraph::ConstVertexIterator &)
Test whether vertex has at least one call-return edge.
Sawyer::SharedPointer< Function > FunctionPtr
Shared-ownership pointer for Function.
boost::logic::tribool hasAnyCalleeReturn(const PartitionerConstPtr &, const ControlFlowGraph::ConstVertexIterator &)
May-return status for function callees.
size_t serialNumber()
Return the next serial number.
Sawyer::SharedPointer< DataBlock > DataBlockPtr
Shared-ownership pointer for DataBlock.
Sawyer::SharedPointer< BasicBlock > BasicBlockPtr
Shared-ownersip pointer for BasicBlock.
void initDiagnostics()
Initialize diagnostics.
ROSE_DLL_API Sawyer::Message::Facility mlog
Diagnostic facility for the ROSE library as a whole.
The ROSE library.