ROSE  0.11.21.0
BinaryUnparserBase.h
1 #ifndef ROSE_BinaryAnalysis_UnparserBase_H
2 #define ROSE_BinaryAnalysis_UnparserBase_H
3 
4 #include <featureTests.h>
5 #ifdef ROSE_ENABLE_BINARY_ANALYSIS
6 
7 #include <BinaryEdgeArrows.h>
8 #include <BinaryReachability.h>
9 #include <BinaryUnparser.h>
10 #include <BitFlags.h>
11 #include <Partitioner2/BasicTypes.h>
12 #include <Partitioner2/ControlFlowGraph.h>
13 #include <Partitioner2/FunctionCallGraph.h>
14 #include <Sawyer/Map.h>
15 #include <Sawyer/Message.h>
16 #include <Sawyer/SharedObject.h>
17 #include <Progress.h>
18 #include <Registers.h>
19 
20 namespace Rose {
21 namespace BinaryAnalysis {
22 
24 namespace Unparser {
25 
27 extern Sawyer::Message::Facility mlog;
28 
29 // used internally to initialize mlog
30 void initDiagnostics();
31 
33 // Margins containing arrows
35 
37 class ArrowMargin {
38 public:
40  enum Flags {
45  POINTABLE_ENTITY_START = 0x00000001,
46 
50  POINTABLE_ENTITY_END = 0x00000002,
51 
53  POINTABLE_ENTITY_INSIDE = 0x00000004,
54 
57  ALWAYS_RENDER = 0x00000008
58  };
59 
60  EdgeArrows arrows;
61  BitFlags<Flags> flags;
67  void reset() {
68  arrows.reset();
69  flags = 0;
70  latestEntity = Sawyer::Nothing();
71  }
72 
78  std::string render(Sawyer::Optional<EdgeArrows::VertexId> currentEntity);
79 };
80 
82 // Output style
84 
86 class StyleStack {
87  std::vector<Style> stack_;
88  Style current_;
89  Color::Colorization colorization_;
90 
91 public:
92  StyleStack() {}
93 
97  Color::Colorization colorization() const { return colorization_; }
98  void colorization(const Color::Colorization c) { colorization_ = c; }
104  size_t push(const Style&);
105 
109  void pop();
110 
112  void popTo(size_t);
113 
115  void reset();
116 
118  size_t size() const;
119 
125  const Style& current() const;
126 
127 private:
128  void merge(const Style &style); // merge style into current_
129  void mergeAll(); // recalculate current_ based on stack_
130 };
131 
133 class StyleGuard {
134  StyleStack &stack_;
135  size_t n_;
136  Style current_;
137  Style previous_;
138 public:
143  StyleGuard(StyleStack &stack, const Style &style)
144  : stack_(stack) {
145  previous_ = stack_.current();
146  n_ = stack_.push(style);
147  current_ = stack_.current();
148  }
149 
150  StyleGuard(StyleStack &stack, const Style &first, const Style &second)
151  : stack_(stack) {
152  previous_ = stack_.current();
153  n_ = stack_.push(first);
154  stack_.push(second);
155  current_ = stack_.current();
156  }
157 
158  ~StyleGuard() {
159  stack_.popTo(n_);
160  }
161 
163  std::string render() const;
164 
166  std::string restore() const;
167 
169  const Style& current() const {
170  return current_;
171  }
172 
174  const Style& previous() const {
175  return previous_;
176  }
177 };
178 
180 // State of the unparser (the unparser itself is const during unparsing)
182 
187 class State {
188 public:
191 private:
192  const Partitioner2::Partitioner &partitioner_;
193  Partitioner2::FunctionCallGraph cg_;
194  Partitioner2::FunctionPtr currentFunction_;
195  Partitioner2::BasicBlockPtr currentBasicBlock_;
196  Sawyer::Optional<EdgeArrows::VertexId> currentPredSuccId_;
197  std::string nextInsnLabel_;
198  AddrString basicBlockLabels_;
199  RegisterNames registerNames_;
200  const Base &frontUnparser_;
201  std::vector<Reachability::ReasonFlags> cfgVertexReachability_;
202  Sawyer::Container::Map<Reachability::ReasonFlags::Vector, std::string> reachabilityNames_; // map reachability value to name
203  ArrowMargin intraFunctionCfgArrows_; // arrows for the intra-function control flow graphs
204  ArrowMargin intraFunctionBlockArrows_; // user-defined intra-function arrows to/from blocks
205  ArrowMargin globalBlockArrows_; // user-defined global arrows to/from blocks
206  bool cfgArrowsPointToInsns_; // arrows point to insns? else predecessor/successor lines
207  StyleStack styleStack_; // styles
208 
209 public:
210  State(const Partitioner2::Partitioner&, const Settings&, const Base &frontUnparser);
211  State(const Partitioner2::Partitioner&, const RegisterDictionary*, const Settings&, const Base &frontUnparser);
212  virtual ~State();
213 
214  const Partitioner2::Partitioner& partitioner() const;
215 
216  const Partitioner2::FunctionCallGraph& cg() const;
217 
224  const std::vector<Reachability::ReasonFlags> cfgVertexReachability() const;
225  void cfgVertexReachability(const std::vector<Reachability::ReasonFlags>&);
232  Reachability::ReasonFlags isCfgVertexReachable(size_t vertexId) const;
233 
246  const ArrowMargin& intraFunctionCfgArrows() const { return intraFunctionCfgArrows_; }
247  ArrowMargin& intraFunctionCfgArrows() { return intraFunctionCfgArrows_; }
263  const ArrowMargin& intraFunctionBlockArrows() const { return intraFunctionBlockArrows_; }
264  ArrowMargin& intraFunctionBlockArrows() { return intraFunctionBlockArrows_; }
275  const ArrowMargin& globalBlockArrows() const { return globalBlockArrows_; }
276  ArrowMargin& globalBlockArrows() { return globalBlockArrows_; }
280  void thisIsBasicBlockFirstInstruction();
281 
283  void thisIsBasicBlockLastInstruction();
284 
292  Sawyer::Optional<EdgeArrows::VertexId> currentPredSuccId() const { return currentPredSuccId_; }
293  void currentPredSuccId(Sawyer::Optional<EdgeArrows::VertexId> id) { currentPredSuccId_ = id; }
303  bool cfgArrowsPointToInsns() const { return cfgArrowsPointToInsns_; }
304  void cfgArrowsPointToInsns(bool b) { cfgArrowsPointToInsns_ = b; }
310  const StyleStack& styleStack() const { return styleStack_; }
311  StyleStack& styleStack() { return styleStack_; }
328  void reachabilityName(Reachability::Reason value, const std::string &name);
329  std::string reachabilityName(Reachability::ReasonFlags value) const;
332  Partitioner2::FunctionPtr currentFunction() const;
333  void currentFunction(const Partitioner2::FunctionPtr&);
334 
335  Partitioner2::BasicBlockPtr currentBasicBlock() const;
336  void currentBasicBlock(const Partitioner2::BasicBlockPtr&);
337 
338  const std::string& nextInsnLabel() const;
339  void nextInsnLabel(const std::string&);
340 
341  const RegisterNames& registerNames() const;
342  void registerNames(const RegisterNames &r);
343 
344  const AddrString& basicBlockLabels() const;
345  AddrString& basicBlockLabels();
346 
347  const Base& frontUnparser() const;
348 };
349 
351 // Base unparser
353 
400 class Base: public Sawyer::SharedObject {
401 public:
403 
404 private:
405  Ptr nextUnparser_;
406 
407 protected:
408  Base();
409  explicit Base(const Ptr &nextUnparser);
410 
411 public:
412  virtual Ptr copy() const = 0;
413  virtual ~Base();
414 
424  virtual const Settings& settings() const = 0;
425  virtual Settings& settings() = 0;
426  void settings(const Settings &s) {
427  settings() = s;
428  }
438  Ptr nextUnparser() const { return nextUnparser_; }
439  void nextUnparser(Ptr next) { nextUnparser_ = next; }
449  void operator()(std::ostream &out, const Partitioner2::Partitioner &p) const /*final*/ {
450  unparse(out, p);
451  }
452  void operator()(std::ostream &out, const Partitioner2::Partitioner &p,
453  SgAsmInstruction *insn) const /*final*/ {
454  unparse(out, p, insn);
455  }
456  void operator()(std::ostream &out, const Partitioner2::Partitioner &p,
457  const Partitioner2::BasicBlockPtr &bb) const /*final*/{
458  unparse(out, p, bb);
459  }
460  void operator()(std::ostream &out, const Partitioner2::Partitioner &p,
461  const Partitioner2::DataBlockPtr &db) const /*final*/ {
462  unparse(out, p, db);
463  }
464  void operator()(std::ostream &out, const Partitioner2::Partitioner &p,
465  const Partitioner2::FunctionPtr &f) const /*final*/ {
466  unparse(out, p, f);
467  }
475  std::string operator()(const Partitioner2::Partitioner &p, const Progress::Ptr &progress = Progress::Ptr()) const /*final*/ {
476  return unparse(p, progress);
477  }
478  std::string operator()(const Partitioner2::Partitioner &p, SgAsmInstruction *insn) const /*final*/ {
479  return unparse(p, insn);
480  }
481  std::string operator()(const Partitioner2::Partitioner &p, const Partitioner2::BasicBlockPtr &bb) const /*final*/ {
482  return unparse(p, bb);
483  }
484  std::string operator()(const Partitioner2::Partitioner &p, const Partitioner2::DataBlockPtr &db) const /*final*/ {
485  return unparse(p, db);
486  }
487  std::string operator()(const Partitioner2::Partitioner &p, const Partitioner2::FunctionPtr &f) const /*final*/ {
488  return unparse(p, f);
489  }
495 public:
501  void unparse(std::ostream&, const Partitioner2::Partitioner&, const Progress::Ptr &progress = Progress::Ptr()) const /*final*/;
502  void unparse(std::ostream&, const Partitioner2::Partitioner&, SgAsmInstruction*) const /*final*/;
503  void unparse(std::ostream&, const Partitioner2::Partitioner&, const Partitioner2::BasicBlockPtr&) const /*final*/;
504  void unparse(std::ostream&, const Partitioner2::Partitioner&, const Partitioner2::DataBlockPtr&) const /*final*/;
505  void unparse(std::ostream&, const Partitioner2::Partitioner&, const Partitioner2::FunctionPtr&) const /*final*/;
506 
507  std::string unparse(const Partitioner2::Partitioner&, const Progress::Ptr &progress = Progress::Ptr()) const /*final*/;
508  std::string unparse(const Partitioner2::Partitioner&, SgAsmInstruction*) const /*final*/;
509  std::string unparse(const Partitioner2::Partitioner&, const Partitioner2::BasicBlockPtr&) const /*final*/;
510  std::string unparse(const Partitioner2::Partitioner&, const Partitioner2::DataBlockPtr&) const /*final*/;
511  std::string unparse(const Partitioner2::Partitioner&, const Partitioner2::FunctionPtr&) const /*final*/;
514 public:
537  virtual void emitFunction(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
538  virtual void emitFunctionPrologue(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
539  virtual void emitFunctionBody(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
540  virtual void emitFunctionEpilogue(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
541 
542  virtual void emitFunctionSourceLocation(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
543  virtual void emitFunctionReasons(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
544  virtual void emitFunctionCallers(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
545  virtual void emitFunctionCallees(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
546  virtual void emitFunctionComment(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
547  virtual void emitFunctionStackDelta(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
548  virtual void emitFunctionCallingConvention(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
549  virtual void emitFunctionNoopAnalysis(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
550  virtual void emitFunctionMayReturn(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
551 
552  virtual void emitDataBlockSourceLocation(std::ostream&, const Partitioner2::DataBlockPtr&, State&) const;
553  virtual void emitDataBlock(std::ostream&, const Partitioner2::DataBlockPtr&, State&) const;
554  virtual void emitDataBlockPrologue(std::ostream&, const Partitioner2::DataBlockPtr&, State&) const;
555  virtual void emitDataBlockBody(std::ostream&, const Partitioner2::DataBlockPtr&, State&) const;
556  virtual void emitDataBlockEpilogue(std::ostream&, const Partitioner2::DataBlockPtr&, State&) const;
557 
558  virtual void emitBasicBlock(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
559  virtual void emitBasicBlockPrologue(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
560  virtual void emitBasicBlockBody(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
561  virtual void emitBasicBlockEpilogue(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
562 
563  virtual void emitBasicBlockSourceLocation(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
564  virtual void emitBasicBlockComment(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
565  virtual void emitBasicBlockSharing(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
566  virtual void emitBasicBlockPredecessors(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
567  virtual void emitBasicBlockSuccessors(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
568  virtual void emitBasicBlockReachability(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
569 
570  virtual void emitInstruction(std::ostream&, SgAsmInstruction*, State&) const;
571  virtual void emitInstructionPrologue(std::ostream&, SgAsmInstruction*, State&) const;
572  virtual void emitInstructionBody(std::ostream&, SgAsmInstruction*, State&) const;
573  virtual void emitInstructionEpilogue(std::ostream&, SgAsmInstruction*, State&) const;
574 
575  virtual void emitInstructionAddress(std::ostream&, SgAsmInstruction*, State&) const;
576  virtual void emitInstructionBytes(std::ostream&, SgAsmInstruction*, State&) const;
577  virtual void emitInstructionStackDelta(std::ostream&, SgAsmInstruction*, State&) const;
578  virtual void emitInstructionMnemonic(std::ostream&, SgAsmInstruction*, State&) const;
579  virtual void emitInstructionOperands(std::ostream&, SgAsmInstruction*, State&) const;
580  virtual void emitInstructionComment(std::ostream&, SgAsmInstruction*, State&) const;
581 
582  virtual void emitInstructionSemantics(std::ostream&, SgAsmInstruction*, State&) const;
583 
584  virtual void emitOperand(std::ostream&, SgAsmExpression*, State&) const;
585  virtual void emitOperandPrologue(std::ostream&, SgAsmExpression*, State&) const;
586  virtual void emitOperandBody(std::ostream&, SgAsmExpression*, State&) const;
587  virtual void emitOperandEpilogue(std::ostream&, SgAsmExpression*, State&) const;
588 
589  virtual void emitRegister(std::ostream&, RegisterDescriptor, State&) const;
590  virtual std::vector<std::string> emitUnsignedInteger(std::ostream&, const Sawyer::Container::BitVector&, State&) const;
591  virtual std::vector<std::string> emitSignedInteger(std::ostream&, const Sawyer::Container::BitVector&, State&) const;
592  virtual std::vector<std::string> emitInteger(std::ostream&, const Sawyer::Container::BitVector&, State&,
593  bool isSigned) const;
594  virtual bool emitAddress(std::ostream&, rose_addr_t, State&, bool always=true) const;
595  virtual bool emitAddress(std::ostream&, const Sawyer::Container::BitVector&, State&, bool always=true) const;
596  virtual void emitCommentBlock(std::ostream&, const std::string&, State&, const std::string &prefix = ";;; ") const;
597  virtual void emitTypeName(std::ostream&, SgAsmType*, State&) const;
598 
599  virtual void emitLinePrefix(std::ostream&, State&) const;
602  //----- Other overrridable things -----
603 public:
609  virtual void initializeState(State&) const;
610 
616  virtual void updateIntraFunctionArrows(State&) const;
617 
618  //----- Utility functions -----
619 public:
621  static std::string leftJustify(const std::string&, size_t nchars);
622 
628  static std::string juxtaposeColumns(const std::vector<std::string> &content, const std::vector<size_t> &minWidths,
629  const std::vector<std::pair<std::string, std::string> > &colorEscapes,
630  const std::string &columnSeparator = " ");
631 
637  static bool ascendingSourceAddress(Partitioner2::ControlFlowGraph::ConstEdgeIterator a,
638  Partitioner2::ControlFlowGraph::ConstEdgeIterator b);
639 
645  static bool ascendingTargetAddress(Partitioner2::ControlFlowGraph::ConstEdgeIterator a,
646  Partitioner2::ControlFlowGraph::ConstEdgeIterator b);
647 
652  static std::vector<Partitioner2::ControlFlowGraph::ConstEdgeIterator>
653  orderedBlockPredecessors(const Partitioner2::Partitioner&, const Partitioner2::BasicBlock::Ptr&);
654 
659  static std::vector<Partitioner2::ControlFlowGraph::ConstEdgeIterator>
660  orderedBlockSuccessors(const Partitioner2::Partitioner&, const Partitioner2::BasicBlock::Ptr&);
661 };
662 
663 
665 // Python API wrappers and functions
667 
668 #ifdef ROSE_ENABLE_PYTHON_API
669 class PythonBase {
670  Base::Ptr base_;
671 
672 public:
673  PythonBase() {}
674 
675  explicit PythonBase(const Base::Ptr &base)
676  : base_(base) {
677  ASSERT_not_null(base);
678  }
679 
680  std::string unparse(const Partitioner2::Partitioner &p) const {
681  return base_->unparse(p);
682  }
683 
684  void print(const Partitioner2::Partitioner &p) const {
685  base_->unparse(std::cout, p);
686  }
687 };
688 #endif
689 
690 } // namespace
691 } // namespace
692 } // namespace
693 
694 #endif
695 #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:1599
STL namespace.
Holds a value or nothing.
Definition: Optional.h:49
void reset()
Reset as if default-constructed.
Definition: Optional.h:181
void print(const StackVariables &, const Partitioner2::Partitioner &, std::ostream &out, const std::string &prefix="")
Print info about multiple local variables.
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:500
BitFlags< Reason, uint32_t > ReasonFlags
Bit flags for reachability.
Base class for expressions.
Base class for binary types.
Base class for reference counted objects.
Definition: SharedObject.h:64
const char * Flags(int64_t)
Convert QDocumentCursorHandle::Flags enum constant to a string.
Definition: stringify.C:7467
Represents no value.
Definition: Optional.h:32
Sawyer::SharedPointer< Progress > Ptr
Progress objects are reference counted.
Definition: Progress.h:168