ROSE  0.11.145.0
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 
15 namespace Rose {
16 namespace BinaryAnalysis {
17 namespace Partitioner2 {
18 
20 void initDiagnostics();
21 
22 bool sortBasicBlocksByAddress(const BasicBlockPtr&, const BasicBlockPtr&);
23 bool sortDataBlocks(const DataBlockPtr&, const DataBlockPtr&);
24 bool sortFunctionsByAddress(const FunctionPtr&, const FunctionPtr&);
25 bool sortFunctionNodesByAddress(const SgAsmFunction*, const SgAsmFunction*);
26 bool sortByExpression(const BasicBlockSuccessor&, const BasicBlockSuccessor&);
27 bool sortBlocksForAst(SgAsmBlock*, SgAsmBlock*);
28 bool sortInstructionsByAddress(SgAsmInstruction*, SgAsmInstruction*);
29 
30 template<class Container, class Comparator>
31 static bool
32 isSorted(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 
45 template<class Container, class Value, class Comparator>
46 typename Container::const_iterator
47 lowerBound(const Container &container, const Value &item, Comparator cmp) {
48  return std::lower_bound(container.begin(), container.end(), item, cmp);
49 }
50 template<class Container, class Value, class Comparator>
51 typename Container::iterator
52 lowerBound(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
57 template<class Value, class Comparator>
58 bool
59 equalUnique(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.
64 template<class Container, class Value, class Comparator>
65 bool
66 insertUnique(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.
78 template<class Container, class Value, class Comparator>
79 void
80 replaceOrInsert(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.
92 template<class Container, class Value, class Comparator>
93 bool
94 eraseUnique(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.
105 template<class Container, class Value, class Comparator>
106 bool
107 existsUnique(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
118 template<class Container, class Value, class Comparator>
120 getUnique(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.
131 template<class Container, class Value, class Comparator>
133 getOrInsertUnique(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 
145 template<class Container, class Comparator>
146 bool
147 isSupersetUnique(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 
161 std::ostream& operator<<(std::ostream&, const AddressUser&);
162 std::ostream& operator<<(std::ostream&, const AddressUsers&);
163 std::ostream& operator<<(std::ostream&, const AddressUsageMap&);
164 
177 
178 protected:
181  : Super(valueSaver) {}
182 public:
185 
187  static Ptr instance() {
188  return Ptr(new AddressIntervalParser);
189  }
190 
193  return Ptr(new AddressIntervalParser(valueSaver));
194  }
195 
197  static std::string docString();
198 };
199 
200 AddressIntervalParser::Ptr addressIntervalParser(AddressInterval &storage);
201 AddressIntervalParser::Ptr addressIntervalParser(std::vector<AddressInterval> &storage);
202 AddressIntervalParser::Ptr addressIntervalParser(AddressIntervalSet &storage);
203 AddressIntervalParser::Ptr addressIntervalParser();
204 
206 class Trigger {
207 public:
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  };
213 private:
214  size_t nCalls_; // number of times called
215  Settings settings_;
216 public:
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 
250  static Sawyer::CommandLine::SwitchGroup switches(Settings&);
251 
253  static std::string docString();
254 };
255 
257 size_t serialNumber();
258 
262 boost::logic::tribool
263 hasAnyCalleeReturn(const PartitionerConstPtr&, const ControlFlowGraph::ConstVertexIterator&);
264 
268 bool
269 hasCallReturnEdges(const ControlFlowGraph::ConstVertexIterator&);
270 
271 
272 } // namespace
273 } // namespace
274 } // namespace
275 
276 #endif
277 #endif
Instruction basic block.
const ValueSaver::Ptr valueSaver() const
Property: functor responsible for saving a parsed value in user storage.
bool isEmpty() const
True if interval is empty.
Definition: Interval.h:219
Trigger(const Settings &settings)
Armed for triggering when number of calls falls within when.
Base class for machine instructions.
Collection of streams.
Definition: Message.h:1606
Sawyer::SharedPointer< AddressIntervalParser > Ptr
Shared-ownership pointer to an AddressIntervalParser.
ROSE_DLL_API Sawyer::Message::Facility mlog
Diagnostic facility for the ROSE library as a whole.
A collection of related switch declarations.
Represents a synthesized function.
Main namespace for the ROSE library.
static Interval baseSize(rose_addr_t lo, rose_addr_t size)
Construct an interval from one endpoint and a size.
Definition: Interval.h:162
Sawyer::SharedPointer< Function > FunctionPtr
Shared-ownership pointer for Function.
Sawyer::SharedPointer< BasicBlock > BasicBlockPtr
Shared-ownersip pointer for BasicBlock.
bool contains(const Interval &other) const
Containment predicate.
Definition: Interval.h:246
size_t serialNumber()
Return the next serial number.
Sawyer::SharedPointer< const Partitioner > PartitionerConstPtr
Shared-ownership pointer for Partitioner.
static std::string docString()
Documentation for command-line switches.
static Ptr instance(const Sawyer::CommandLine::ValueSaver::Ptr &valueSaver)
Allocating constructor.
bool hasCallReturnEdges(const ControlFlowGraph::ConstVertexIterator &)
Test whether vertex has at least one call-return edge.
boost::logic::tribool hasAnyCalleeReturn(const PartitionerConstPtr &, const ControlFlowGraph::ConstVertexIterator &)
May-return status for function callees.
void initDiagnostics()
Initialize diagnostics.
static Sawyer::CommandLine::SwitchGroup switches(Settings &)
Command-line switches to initialize settings.
static std::string docString()
Runtime documentation.
Sawyer::SharedPointer< DataBlock > DataBlockPtr
Shared-ownership pointer for DataBlock.
Represents no value.
Definition: Optional.h:32
T greatest() const
Returns upper limit.
Definition: Interval.h:213
bool shouldTrigger()
Increment calls and return true if triggering.
Trigger(size_t nSkip, size_t nTimes)
Armed for triggering after nSkip calls but not more than nTimes times.