ROSE  0.11.124.0
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.
static Ptr instance()
Default allocating constructor.
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.
size_t nCalls() const
Number of times called.
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.
Trigger based on number of times called.
Sawyer::SharedPointer< const Partitioner > PartitionerConstPtr
Shared-ownership pointer for Partitioner.
static std::string docString()
Documentation for command-line switches.
bool isArmed() const
True if trigger is armed.
Trigger()
Trigger armed for single call.
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
static Trigger always()
Armed to always trigger.
static Trigger never()
Armed to never trigger.
bool shouldTrigger()
Increment calls and return true if triggering.
static Trigger once()
Armed for one call.
void reset()
Reset number of calls to zero.
Trigger(size_t nSkip, size_t nTimes)
Armed for triggering after nSkip calls but not more than nTimes times.