ROSE  0.9.11.42
BinaryUnparserBase.h
1 #ifndef ROSE_BinaryAnalysis_UnparserBase_H
2 #define ROSE_BinaryAnalysis_UnparserBase_H
3 
4 #include <BinaryEdgeArrows.h>
5 #include <BinaryReachability.h>
6 #include <BinaryUnparser.h>
7 #include <BitFlags.h>
8 #include <Partitioner2/BasicTypes.h>
9 #include <Partitioner2/ControlFlowGraph.h>
10 #include <Partitioner2/FunctionCallGraph.h>
11 #include <Sawyer/Map.h>
12 #include <Sawyer/Message.h>
13 #include <Sawyer/SharedObject.h>
14 #include <Progress.h>
15 #include <Registers.h>
16 
17 namespace Rose {
18 namespace BinaryAnalysis {
19 
21 namespace Unparser {
22 
24 extern Sawyer::Message::Facility mlog;
25 
26 // used internally to initialize mlog
27 void initDiagnostics();
28 
30 // Margins containing arrows
32 
34 class ArrowMargin {
35 public:
37  enum Flags {
42  POINTABLE_ENTITY_START = 0x00000001,
43 
47  POINTABLE_ENTITY_END = 0x00000002,
48 
50  POINTABLE_ENTITY_INSIDE = 0x00000004,
51 
54  ALWAYS_RENDER = 0x00000008
55  };
56 
57  EdgeArrows arrows;
58  BitFlags<Flags> flags;
64  void reset() {
65  arrows.reset();
66  flags = 0;
67  latestEntity = Sawyer::Nothing();
68  }
69 
75  std::string render(Sawyer::Optional<EdgeArrows::VertexId> currentEntity);
76 };
77 
79 // State of the unparser (the unparser itself is const during unparsing)
81 
86 class State {
87 public:
90 private:
91  const Partitioner2::Partitioner &partitioner_;
92  Partitioner2::FunctionCallGraph cg_;
93  Partitioner2::FunctionPtr currentFunction_;
94  Partitioner2::BasicBlockPtr currentBasicBlock_;
95  Sawyer::Optional<EdgeArrows::VertexId> currentPredSuccId_;
96  std::string nextInsnLabel_;
97  AddrString basicBlockLabels_;
98  RegisterNames registerNames_;
99  const Base &frontUnparser_;
100  std::vector<Reachability::ReasonFlags> cfgVertexReachability_;
101  Sawyer::Container::Map<Reachability::ReasonFlags::Vector, std::string> reachabilityNames_; // map reachability value to name
102  ArrowMargin intraFunctionCfgArrows_; // arrows for the intra-function control flow graphs
103  ArrowMargin intraFunctionBlockArrows_; // user-defined intra-function arrows to/from blocks
104  ArrowMargin globalBlockArrows_; // user-defined global arrows to/from blocks
105  bool cfgArrowsPointToInsns_; // arrows point to insns? else predecessor/successor lines
106 
107 public:
108  State(const Partitioner2::Partitioner&, const Settings&, const Base &frontUnparser);
109  virtual ~State();
110 
111  const Partitioner2::Partitioner& partitioner() const;
112 
113  const Partitioner2::FunctionCallGraph& cg() const;
114 
121  const std::vector<Reachability::ReasonFlags> cfgVertexReachability() const;
122  void cfgVertexReachability(const std::vector<Reachability::ReasonFlags>&);
129  Reachability::ReasonFlags isCfgVertexReachable(size_t vertexId) const;
130 
143  const ArrowMargin& intraFunctionCfgArrows() const { return intraFunctionCfgArrows_; }
144  ArrowMargin& intraFunctionCfgArrows() { return intraFunctionCfgArrows_; }
160  const ArrowMargin& intraFunctionBlockArrows() const { return intraFunctionBlockArrows_; }
161  ArrowMargin& intraFunctionBlockArrows() { return intraFunctionBlockArrows_; }
172  const ArrowMargin& globalBlockArrows() const { return globalBlockArrows_; }
173  ArrowMargin& globalBlockArrows() { return globalBlockArrows_; }
177  void thisIsBasicBlockFirstInstruction();
178 
180  void thisIsBasicBlockLastInstruction();
181 
189  Sawyer::Optional<EdgeArrows::VertexId> currentPredSuccId() const { return currentPredSuccId_; }
190  void currentPredSuccId(Sawyer::Optional<EdgeArrows::VertexId> id) { currentPredSuccId_ = id; }
200  bool cfgArrowsPointToInsns() const { return cfgArrowsPointToInsns_; }
201  void cfgArrowsPointToInsns(bool b) { cfgArrowsPointToInsns_ = b; }
218  void reachabilityName(Reachability::Reason value, const std::string &name);
219  std::string reachabilityName(Reachability::ReasonFlags value) const;
222  Partitioner2::FunctionPtr currentFunction() const;
223  void currentFunction(const Partitioner2::FunctionPtr&);
224 
225  Partitioner2::BasicBlockPtr currentBasicBlock() const;
226  void currentBasicBlock(const Partitioner2::BasicBlockPtr&);
227 
228  const std::string& nextInsnLabel() const;
229  void nextInsnLabel(const std::string&);
230 
231  const RegisterNames& registerNames() const;
232  void registerNames(const RegisterNames &r);
233 
234  const AddrString& basicBlockLabels() const;
235  AddrString& basicBlockLabels();
236 
237  const Base& frontUnparser() const;
238 };
239 
241 // Base unparser
243 
290 class Base: public Sawyer::SharedObject {
291 public:
293 
294 private:
295  Ptr nextUnparser_;
296 
297 protected:
298  Base();
299  explicit Base(const Ptr &nextUnparser);
300 
301 public:
302  virtual Ptr copy() const = 0;
303  virtual ~Base();
304 
312  virtual const Settings& settings() const = 0;
313  virtual Settings& settings() = 0;
323  Ptr nextUnparser() const { return nextUnparser_; }
324  void nextUnparser(Ptr next) { nextUnparser_ = next; }
334  void operator()(std::ostream &out, const Partitioner2::Partitioner &p) const /*final*/ {
335  unparse(out, p);
336  }
337  void operator()(std::ostream &out, const Partitioner2::Partitioner &p,
338  SgAsmInstruction *insn) const /*final*/ {
339  unparse(out, p, insn);
340  }
341  void operator()(std::ostream &out, const Partitioner2::Partitioner &p,
342  const Partitioner2::BasicBlockPtr &bb) const /*final*/{
343  unparse(out, p, bb);
344  }
345  void operator()(std::ostream &out, const Partitioner2::Partitioner &p,
346  const Partitioner2::DataBlockPtr &db) const /*final*/ {
347  unparse(out, p, db);
348  }
349  void operator()(std::ostream &out, const Partitioner2::Partitioner &p,
350  const Partitioner2::FunctionPtr &f) const /*final*/ {
351  unparse(out, p, f);
352  }
360  std::string operator()(const Partitioner2::Partitioner &p, const Progress::Ptr &progress = Progress::Ptr()) const /*final*/ {
361  return unparse(p, progress);
362  }
363  std::string operator()(const Partitioner2::Partitioner &p, SgAsmInstruction *insn) const /*final*/ {
364  return unparse(p, insn);
365  }
366  std::string operator()(const Partitioner2::Partitioner &p, const Partitioner2::BasicBlockPtr &bb) const /*final*/ {
367  return unparse(p, bb);
368  }
369  std::string operator()(const Partitioner2::Partitioner &p, const Partitioner2::DataBlockPtr &db) const /*final*/ {
370  return unparse(p, db);
371  }
372  std::string operator()(const Partitioner2::Partitioner &p, const Partitioner2::FunctionPtr &f) const /*final*/ {
373  return unparse(p, f);
374  }
380 public:
386  void unparse(std::ostream&, const Partitioner2::Partitioner&, const Progress::Ptr &progress = Progress::Ptr()) const /*final*/;
387  void unparse(std::ostream&, const Partitioner2::Partitioner&, SgAsmInstruction*) const /*final*/;
388  void unparse(std::ostream&, const Partitioner2::Partitioner&, const Partitioner2::BasicBlockPtr&) const /*final*/;
389  void unparse(std::ostream&, const Partitioner2::Partitioner&, const Partitioner2::DataBlockPtr&) const /*final*/;
390  void unparse(std::ostream&, const Partitioner2::Partitioner&, const Partitioner2::FunctionPtr&) const /*final*/;
391 
392  std::string unparse(const Partitioner2::Partitioner&, const Progress::Ptr &progress = Progress::Ptr()) const /*final*/;
393  std::string unparse(const Partitioner2::Partitioner&, SgAsmInstruction*) const /*final*/;
394  std::string unparse(const Partitioner2::Partitioner&, const Partitioner2::BasicBlockPtr&) const /*final*/;
395  std::string unparse(const Partitioner2::Partitioner&, const Partitioner2::DataBlockPtr&) const /*final*/;
396  std::string unparse(const Partitioner2::Partitioner&, const Partitioner2::FunctionPtr&) const /*final*/;
399 public:
422  virtual void emitFunction(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
423  virtual void emitFunctionPrologue(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
424  virtual void emitFunctionBody(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
425  virtual void emitFunctionEpilogue(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
426 
427  virtual void emitFunctionReasons(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
428  virtual void emitFunctionCallers(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
429  virtual void emitFunctionCallees(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
430  virtual void emitFunctionComment(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
431  virtual void emitFunctionStackDelta(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
432  virtual void emitFunctionCallingConvention(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
433  virtual void emitFunctionNoopAnalysis(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
434  virtual void emitFunctionMayReturn(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
435 
436  virtual void emitDataBlock(std::ostream&, const Partitioner2::DataBlockPtr&, State&) const;
437  virtual void emitDataBlockPrologue(std::ostream&, const Partitioner2::DataBlockPtr&, State&) const;
438  virtual void emitDataBlockBody(std::ostream&, const Partitioner2::DataBlockPtr&, State&) const;
439  virtual void emitDataBlockEpilogue(std::ostream&, const Partitioner2::DataBlockPtr&, State&) const;
440 
441  virtual void emitBasicBlock(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
442  virtual void emitBasicBlockPrologue(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
443  virtual void emitBasicBlockBody(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
444  virtual void emitBasicBlockEpilogue(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
445 
446  virtual void emitBasicBlockComment(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
447  virtual void emitBasicBlockSharing(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
448  virtual void emitBasicBlockPredecessors(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
449  virtual void emitBasicBlockSuccessors(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
450  virtual void emitBasicBlockReachability(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
451 
452  virtual void emitInstruction(std::ostream&, SgAsmInstruction*, State&) const;
453  virtual void emitInstructionPrologue(std::ostream&, SgAsmInstruction*, State&) const;
454  virtual void emitInstructionBody(std::ostream&, SgAsmInstruction*, State&) const;
455  virtual void emitInstructionEpilogue(std::ostream&, SgAsmInstruction*, State&) const;
456 
457  virtual void emitInstructionAddress(std::ostream&, SgAsmInstruction*, State&) const;
458  virtual void emitInstructionBytes(std::ostream&, SgAsmInstruction*, State&) const;
459  virtual void emitInstructionStackDelta(std::ostream&, SgAsmInstruction*, State&) const;
460  virtual void emitInstructionMnemonic(std::ostream&, SgAsmInstruction*, State&) const;
461  virtual void emitInstructionOperands(std::ostream&, SgAsmInstruction*, State&) const;
462  virtual void emitInstructionComment(std::ostream&, SgAsmInstruction*, State&) const;
463 
464  virtual void emitInstructionSemantics(std::ostream&, SgAsmInstruction*, State&) const;
465 
466  virtual void emitOperand(std::ostream&, SgAsmExpression*, State&) const;
467  virtual void emitOperandPrologue(std::ostream&, SgAsmExpression*, State&) const;
468  virtual void emitOperandBody(std::ostream&, SgAsmExpression*, State&) const;
469  virtual void emitOperandEpilogue(std::ostream&, SgAsmExpression*, State&) const;
470 
471  virtual void emitRegister(std::ostream&, RegisterDescriptor, State&) const;
472  virtual std::vector<std::string> emitUnsignedInteger(std::ostream&, const Sawyer::Container::BitVector&, State&) const;
473  virtual std::vector<std::string> emitSignedInteger(std::ostream&, const Sawyer::Container::BitVector&, State&) const;
474  virtual std::vector<std::string> emitInteger(std::ostream&, const Sawyer::Container::BitVector&, State&,
475  bool isSigned) const;
476  virtual bool emitAddress(std::ostream&, rose_addr_t, State&, bool always=true) const;
477  virtual bool emitAddress(std::ostream&, const Sawyer::Container::BitVector&, State&, bool always=true) const;
478  virtual void emitCommentBlock(std::ostream&, const std::string&, State&, const std::string &prefix = ";;; ") const;
479  virtual void emitTypeName(std::ostream&, SgAsmType*, State&) const;
480 
481  virtual void emitLinePrefix(std::ostream&, State&) const;
484  //----- Other overrridable things -----
485 public:
491  virtual void initializeState(State&) const;
492 
498  virtual void updateIntraFunctionArrows(State&) const;
499 
500  //----- Utility functions -----
501 public:
503  static std::string leftJustify(const std::string&, size_t nchars);
504 
509  static std::string juxtaposeColumns(const std::vector<std::string> &content, const std::vector<size_t> &minWidths,
510  const std::string &columnSeparator = " ");
511 
517  static bool ascendingSourceAddress(Partitioner2::ControlFlowGraph::ConstEdgeIterator a,
518  Partitioner2::ControlFlowGraph::ConstEdgeIterator b);
519 
525  static bool ascendingTargetAddress(Partitioner2::ControlFlowGraph::ConstEdgeIterator a,
526  Partitioner2::ControlFlowGraph::ConstEdgeIterator b);
527 
532  static std::vector<Partitioner2::ControlFlowGraph::ConstEdgeIterator>
533  orderedBlockPredecessors(const Partitioner2::Partitioner&, const Partitioner2::BasicBlock::Ptr&);
534 
539  static std::vector<Partitioner2::ControlFlowGraph::ConstEdgeIterator>
540  orderedBlockSuccessors(const Partitioner2::Partitioner&, const Partitioner2::BasicBlock::Ptr&);
541 };
542 
543 
545 // Python API wrappers and functions
547 
548 #ifdef ROSE_ENABLE_PYTHON_API
549 class PythonBase {
550  Base::Ptr base_;
551 
552 public:
553  PythonBase() {}
554 
555  explicit PythonBase(const Base::Ptr &base)
556  : base_(base) {
557  ASSERT_not_null(base);
558  }
559 
560  std::string unparse(const Partitioner2::Partitioner &p) const {
561  return base_->unparse(p);
562  }
563 
564  void print(const Partitioner2::Partitioner &p) const {
565  base_->unparse(std::cout, p);
566  }
567 };
568 #endif
569 
570 } // namespace
571 } // namespace
572 } // namespace
573 
574 #endif
Sawyer::SharedPointer< Node > Ptr
Shared-ownership pointer to an expression Node.
void copy(const Word *src, const BitRange &srcRange, Word *dst, const BitRange &dstRange)
Copy some bits.
Base class for machine instructions.
Collection of streams.
Definition: Message.h:1579
STL namespace.
Holds a value or nothing.
Definition: Optional.h:49
Main namespace for the ROSE library.
Reason
Predefined bit flags for why something is reachable.
Name space for the entire library.
Sawyer::SharedPointer< Function > FunctionPtr
Shared-ownership pointer for function.
Definition: BasicTypes.h:458
BitFlags< Reason, uint32_t > ReasonFlags
Bit flags for reachability.
Base class for expressions.
const char * Flags(int64_t)
Convert Rose::BinaryAnalysis::Unparser::ArrowMargin::Flags enum constant to a string.
Definition: stringify.C:9
Base class for binary types.
Base class for reference counted objects.
Definition: SharedObject.h:64
Represents no value.
Definition: Optional.h:32
Sawyer::SharedPointer< Progress > Ptr
Progress objects are reference counted.
Definition: Progress.h:167