ROSE  0.11.51.0
Base.h
1 #ifndef ROSE_BinaryAnalysis_Unparser_Base_H
2 #define ROSE_BinaryAnalysis_Unparser_Base_H
3 
4 #include <featureTests.h>
5 #ifdef ROSE_ENABLE_BINARY_ANALYSIS
6 
7 #include <Rose/BinaryAnalysis/Unparser/EdgeArrows.h>
8 #include <Rose/BinaryAnalysis/Reachability.h>
9 #include <Rose/BinaryAnalysis/Unparser/Settings.h>
10 #include <Rose/BitFlags.h>
11 #include <Rose/BinaryAnalysis/Partitioner2/BasicTypes.h>
12 #include <Rose/BinaryAnalysis/Partitioner2/ControlFlowGraph.h>
13 #include <Rose/BinaryAnalysis/Partitioner2/FunctionCallGraph.h>
14 #include <Sawyer/Map.h>
15 #include <Sawyer/Message.h>
16 #include <Sawyer/SharedObject.h>
17 #include <Rose/Progress.h>
18 #include <Rose/BinaryAnalysis/Registers.h>
19 
20 namespace Rose {
21 namespace BinaryAnalysis {
22 
24 namespace Unparser {
25 
27 typedef std::map<uint64_t, std::string> LabelMap;
28 
31 
32 // used internally to initialize mlog
33 void initDiagnostics();
34 
36 // Supporting functions
38 
42 std::string invalidRegister(SgAsmInstruction*, RegisterDescriptor, const RegisterDictionary*);
43 
45 // Margins containing arrows
47 
49 class ArrowMargin {
50 public:
52  enum Flags {
57  POINTABLE_ENTITY_START = 0x00000001,
58 
62  POINTABLE_ENTITY_END = 0x00000002,
63 
65  POINTABLE_ENTITY_INSIDE = 0x00000004,
66 
69  ALWAYS_RENDER = 0x00000008
70  };
71 
72  EdgeArrows arrows;
73  BitFlags<Flags> flags;
79  void reset() {
80  arrows.reset();
81  flags = 0;
82  latestEntity = Sawyer::Nothing();
83  }
84 
90  std::string render(Sawyer::Optional<EdgeArrows::VertexId> currentEntity);
91 };
92 
94 // Output style
96 
98 class StyleStack {
99  std::vector<Style> stack_;
100  Style current_;
101  Color::Colorization colorization_;
102 
103 public:
104  StyleStack() {}
105 
109  Color::Colorization colorization() const { return colorization_; }
110  void colorization(const Color::Colorization c) { colorization_ = c; }
116  size_t push(const Style&);
117 
121  void pop();
122 
124  void popTo(size_t);
125 
127  void reset();
128 
130  size_t size() const;
131 
137  const Style& current() const;
138 
139 private:
140  void merge(const Style &style); // merge style into current_
141  void mergeAll(); // recalculate current_ based on stack_
142 };
143 
145 class StyleGuard {
146  StyleStack &stack_;
147  size_t n_;
148  Style current_;
149  Style previous_;
150 public:
155  StyleGuard(StyleStack &stack, const Style &style)
156  : stack_(stack) {
157  previous_ = stack_.current();
158  n_ = stack_.push(style);
159  current_ = stack_.current();
160  }
161 
162  StyleGuard(StyleStack &stack, const Style &first, const Style &second)
163  : stack_(stack) {
164  previous_ = stack_.current();
165  n_ = stack_.push(first);
166  stack_.push(second);
167  current_ = stack_.current();
168  }
169 
170  ~StyleGuard() {
171  stack_.popTo(n_);
172  }
173 
175  std::string render() const;
176 
178  std::string restore() const;
179 
181  const Style& current() const {
182  return current_;
183  }
184 
186  const Style& previous() const {
187  return previous_;
188  }
189 };
190 
192 // State of the unparser (the unparser itself is const during unparsing)
194 
199 class State {
200 public:
203 private:
204  const Partitioner2::Partitioner &partitioner_;
205  Partitioner2::FunctionCallGraph cg_;
206  Partitioner2::FunctionPtr currentFunction_;
207  Partitioner2::BasicBlockPtr currentBasicBlock_;
208  Sawyer::Optional<EdgeArrows::VertexId> currentPredSuccId_;
209  std::string nextInsnLabel_;
210  AddrString basicBlockLabels_;
211  RegisterNames registerNames_;
212  const Base &frontUnparser_;
213  std::vector<Reachability::ReasonFlags> cfgVertexReachability_;
214  Sawyer::Container::Map<Reachability::ReasonFlags::Vector, std::string> reachabilityNames_; // map reachability value to name
215  ArrowMargin intraFunctionCfgArrows_; // arrows for the intra-function control flow graphs
216  ArrowMargin intraFunctionBlockArrows_; // user-defined intra-function arrows to/from blocks
217  ArrowMargin globalBlockArrows_; // user-defined global arrows to/from blocks
218  bool cfgArrowsPointToInsns_; // arrows point to insns? else predecessor/successor lines
219  StyleStack styleStack_; // styles
220 
221 public:
222  State(const Partitioner2::Partitioner&, const Settings&, const Base &frontUnparser);
223  State(const Partitioner2::Partitioner&, const RegisterDictionary*, const Settings&, const Base &frontUnparser);
224  virtual ~State();
225 
226  const Partitioner2::Partitioner& partitioner() const;
227 
228  const Partitioner2::FunctionCallGraph& cg() const;
229 
236  const std::vector<Reachability::ReasonFlags> cfgVertexReachability() const;
237  void cfgVertexReachability(const std::vector<Reachability::ReasonFlags>&);
244  Reachability::ReasonFlags isCfgVertexReachable(size_t vertexId) const;
245 
258  const ArrowMargin& intraFunctionCfgArrows() const { return intraFunctionCfgArrows_; }
259  ArrowMargin& intraFunctionCfgArrows() { return intraFunctionCfgArrows_; }
275  const ArrowMargin& intraFunctionBlockArrows() const { return intraFunctionBlockArrows_; }
276  ArrowMargin& intraFunctionBlockArrows() { return intraFunctionBlockArrows_; }
287  const ArrowMargin& globalBlockArrows() const { return globalBlockArrows_; }
288  ArrowMargin& globalBlockArrows() { return globalBlockArrows_; }
292  void thisIsBasicBlockFirstInstruction();
293 
295  void thisIsBasicBlockLastInstruction();
296 
304  Sawyer::Optional<EdgeArrows::VertexId> currentPredSuccId() const { return currentPredSuccId_; }
305  void currentPredSuccId(Sawyer::Optional<EdgeArrows::VertexId> id) { currentPredSuccId_ = id; }
315  bool cfgArrowsPointToInsns() const { return cfgArrowsPointToInsns_; }
316  void cfgArrowsPointToInsns(bool b) { cfgArrowsPointToInsns_ = b; }
322  const StyleStack& styleStack() const { return styleStack_; }
323  StyleStack& styleStack() { return styleStack_; }
340  void reachabilityName(Reachability::Reason value, const std::string &name);
341  std::string reachabilityName(Reachability::ReasonFlags value) const;
344  Partitioner2::FunctionPtr currentFunction() const;
345  void currentFunction(const Partitioner2::FunctionPtr&);
346 
347  Partitioner2::BasicBlockPtr currentBasicBlock() const;
348  void currentBasicBlock(const Partitioner2::BasicBlockPtr&);
349 
350  const std::string& nextInsnLabel() const;
351  void nextInsnLabel(const std::string&);
352 
353  const RegisterNames& registerNames() const;
354  void registerNames(const RegisterNames &r);
355 
356  const AddrString& basicBlockLabels() const;
357  AddrString& basicBlockLabels();
358 
359  const Base& frontUnparser() const;
360 };
361 
363 // Base unparser
365 
412 class Base: public Sawyer::SharedObject {
413 public:
415 
416 private:
417  Ptr nextUnparser_;
418 
419 protected:
420  Base();
421  explicit Base(const Ptr &nextUnparser);
422 
423 public:
424  virtual Ptr copy() const = 0;
425  virtual ~Base();
426 
436  virtual const Settings& settings() const = 0;
437  virtual Settings& settings() = 0;
438  void settings(const Settings &s) {
439  settings() = s;
440  }
450  Ptr nextUnparser() const { return nextUnparser_; }
451  void nextUnparser(Ptr next) { nextUnparser_ = next; }
461  void operator()(std::ostream &out, const Partitioner2::Partitioner &p) const /*final*/ {
462  unparse(out, p);
463  }
464  void operator()(std::ostream &out, const Partitioner2::Partitioner &p,
465  SgAsmInstruction *insn) const /*final*/ {
466  unparse(out, p, insn);
467  }
468  void operator()(std::ostream &out, const Partitioner2::Partitioner &p,
469  const Partitioner2::BasicBlockPtr &bb) const /*final*/{
470  unparse(out, p, bb);
471  }
472  void operator()(std::ostream &out, const Partitioner2::Partitioner &p,
473  const Partitioner2::DataBlockPtr &db) const /*final*/ {
474  unparse(out, p, db);
475  }
476  void operator()(std::ostream &out, const Partitioner2::Partitioner &p,
477  const Partitioner2::FunctionPtr &f) const /*final*/ {
478  unparse(out, p, f);
479  }
487  std::string operator()(const Partitioner2::Partitioner &p, const Progress::Ptr &progress = Progress::Ptr()) const /*final*/ {
488  return unparse(p, progress);
489  }
490  std::string operator()(const Partitioner2::Partitioner &p, SgAsmInstruction *insn) const /*final*/ {
491  return unparse(p, insn);
492  }
493  std::string operator()(const Partitioner2::Partitioner &p, const Partitioner2::BasicBlockPtr &bb) const /*final*/ {
494  return unparse(p, bb);
495  }
496  std::string operator()(const Partitioner2::Partitioner &p, const Partitioner2::DataBlockPtr &db) const /*final*/ {
497  return unparse(p, db);
498  }
499  std::string operator()(const Partitioner2::Partitioner &p, const Partitioner2::FunctionPtr &f) const /*final*/ {
500  return unparse(p, f);
501  }
507 public:
513  void unparse(std::ostream&, const Partitioner2::Partitioner&, const Progress::Ptr &progress = Progress::Ptr()) const /*final*/;
514  void unparse(std::ostream&, const Partitioner2::Partitioner&, SgAsmInstruction*) const /*final*/;
515  void unparse(std::ostream&, const Partitioner2::Partitioner&, const Partitioner2::BasicBlockPtr&) const /*final*/;
516  void unparse(std::ostream&, const Partitioner2::Partitioner&, const Partitioner2::DataBlockPtr&) const /*final*/;
517  void unparse(std::ostream&, const Partitioner2::Partitioner&, const Partitioner2::FunctionPtr&) const /*final*/;
518 
519  std::string unparse(const Partitioner2::Partitioner&, const Progress::Ptr &progress = Progress::Ptr()) const /*final*/;
520  std::string unparse(const Partitioner2::Partitioner&, SgAsmInstruction*) const /*final*/;
521  std::string unparse(const Partitioner2::Partitioner&, const Partitioner2::BasicBlockPtr&) const /*final*/;
522  std::string unparse(const Partitioner2::Partitioner&, const Partitioner2::DataBlockPtr&) const /*final*/;
523  std::string unparse(const Partitioner2::Partitioner&, const Partitioner2::FunctionPtr&) const /*final*/;
526 public:
549  virtual void emitFunction(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
550  virtual void emitFunctionPrologue(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
551  virtual void emitFunctionBody(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
552  virtual void emitFunctionEpilogue(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
553 
554  virtual void emitFunctionSourceLocation(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
555  virtual void emitFunctionReasons(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
556  virtual void emitFunctionCallers(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
557  virtual void emitFunctionCallees(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
558  virtual void emitFunctionComment(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
559  virtual void emitFunctionStackDelta(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
560  virtual void emitFunctionCallingConvention(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
561  virtual void emitFunctionNoopAnalysis(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
562  virtual void emitFunctionMayReturn(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
563 
564  virtual void emitDataBlockSourceLocation(std::ostream&, const Partitioner2::DataBlockPtr&, State&) const;
565  virtual void emitDataBlock(std::ostream&, const Partitioner2::DataBlockPtr&, State&) const;
566  virtual void emitDataBlockPrologue(std::ostream&, const Partitioner2::DataBlockPtr&, State&) const;
567  virtual void emitDataBlockBody(std::ostream&, const Partitioner2::DataBlockPtr&, State&) const;
568  virtual void emitDataBlockEpilogue(std::ostream&, const Partitioner2::DataBlockPtr&, State&) const;
569 
570  virtual void emitBasicBlock(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
571  virtual void emitBasicBlockPrologue(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
572  virtual void emitBasicBlockBody(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
573  virtual void emitBasicBlockEpilogue(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
574 
575  virtual void emitBasicBlockSourceLocation(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
576  virtual void emitBasicBlockComment(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
577  virtual void emitBasicBlockSharing(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
578  virtual void emitBasicBlockPredecessors(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
579  virtual void emitBasicBlockSuccessors(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
580  virtual void emitBasicBlockReachability(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
581 
582  virtual void emitInstruction(std::ostream&, SgAsmInstruction*, State&) const;
583  virtual void emitInstructionPrologue(std::ostream&, SgAsmInstruction*, State&) const;
584  virtual void emitInstructionBody(std::ostream&, SgAsmInstruction*, State&) const;
585  virtual void emitInstructionEpilogue(std::ostream&, SgAsmInstruction*, State&) const;
586 
587  virtual void emitInstructionAddress(std::ostream&, SgAsmInstruction*, State&) const;
588  virtual void emitInstructionBytes(std::ostream&, SgAsmInstruction*, State&) const;
589  virtual void emitInstructionStackDelta(std::ostream&, SgAsmInstruction*, State&) const;
590  virtual void emitInstructionMnemonic(std::ostream&, SgAsmInstruction*, State&) const;
591  virtual void emitInstructionOperands(std::ostream&, SgAsmInstruction*, State&) const;
592  virtual void emitInstructionComment(std::ostream&, SgAsmInstruction*, State&) const;
593 
594  virtual void emitInstructionSemantics(std::ostream&, SgAsmInstruction*, State&) const;
595 
596  virtual void emitOperand(std::ostream&, SgAsmExpression*, State&) const;
597  virtual void emitOperandPrologue(std::ostream&, SgAsmExpression*, State&) const;
598  virtual void emitOperandBody(std::ostream&, SgAsmExpression*, State&) const;
599  virtual void emitOperandEpilogue(std::ostream&, SgAsmExpression*, State&) const;
600 
601  virtual void emitRegister(std::ostream&, RegisterDescriptor, State&) const;
602  virtual std::vector<std::string> emitUnsignedInteger(std::ostream&, const Sawyer::Container::BitVector&, State&) const;
603  virtual std::vector<std::string> emitSignedInteger(std::ostream&, const Sawyer::Container::BitVector&, State&) const;
604  virtual std::vector<std::string> emitInteger(std::ostream&, const Sawyer::Container::BitVector&, State&,
605  bool isSigned) const;
606  virtual bool emitAddress(std::ostream&, rose_addr_t, State&, bool always=true) const;
607  virtual bool emitAddress(std::ostream&, const Sawyer::Container::BitVector&, State&, bool always=true) const;
608  virtual void emitCommentBlock(std::ostream&, const std::string&, State&, const std::string &prefix = ";;; ") const;
609  virtual void emitTypeName(std::ostream&, SgAsmType*, State&) const;
610 
611  virtual void emitLinePrefix(std::ostream&, State&) const;
614  //----- Other overrridable things -----
615 public:
621  virtual void initializeState(State&) const;
622 
628  virtual void updateIntraFunctionArrows(State&) const;
629 
630  //----- Utility functions -----
631 public:
633  static std::string leftJustify(const std::string&, size_t nchars);
634 
640  static std::string juxtaposeColumns(const std::vector<std::string> &content, const std::vector<size_t> &minWidths,
641  const std::vector<std::pair<std::string, std::string> > &colorEscapes,
642  const std::string &columnSeparator = " ");
643 
649  static bool ascendingSourceAddress(Partitioner2::ControlFlowGraph::ConstEdgeIterator a,
650  Partitioner2::ControlFlowGraph::ConstEdgeIterator b);
651 
657  static bool ascendingTargetAddress(Partitioner2::ControlFlowGraph::ConstEdgeIterator a,
658  Partitioner2::ControlFlowGraph::ConstEdgeIterator b);
659 
664  static std::vector<Partitioner2::ControlFlowGraph::ConstEdgeIterator>
665  orderedBlockPredecessors(const Partitioner2::Partitioner&, const Partitioner2::BasicBlock::Ptr&);
666 
671  static std::vector<Partitioner2::ControlFlowGraph::ConstEdgeIterator>
672  orderedBlockSuccessors(const Partitioner2::Partitioner&, const Partitioner2::BasicBlock::Ptr&);
673 };
674 
675 
677 // Python API wrappers and functions
679 
680 #ifdef ROSE_ENABLE_PYTHON_API
681 class PythonBase {
682  Base::Ptr base_;
683 
684 public:
685  PythonBase() {}
686 
687  explicit PythonBase(const Base::Ptr &base)
688  : base_(base) {
689  ASSERT_not_null(base);
690  }
691 
692  std::string unparse(const Partitioner2::Partitioner &p) const {
693  return base_->unparse(p);
694  }
695 
696  void print(const Partitioner2::Partitioner &p) const {
697  base_->unparse(std::cout, p);
698  }
699 };
700 #endif
701 
702 } // namespace
703 } // namespace
704 } // namespace
705 
706 #endif
707 #endif
Sawyer::SharedPointer< Node > Ptr
Shared-ownership pointer to an expression Node.
Definition: SymbolicExpr.h:156
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:1606
ROSE_DLL_API Sawyer::Message::Facility mlog
Diagnostic facility for the ROSE library as a whole.
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.
Definition: Reachability.h:25
Name space for the entire library.
Definition: FeasiblePath.h:787
Sawyer::SharedPointer< Function > FunctionPtr
Shared-ownership pointer for function.
const char * Flags(int64_t)
Convert QDocumentCursorHandle::Flags enum constant to a string.
BitFlags< Reason, uint32_t > ReasonFlags
Bit flags for reachability.
Definition: Reachability.h:56
Base class for expressions.
Base class for binary types.
Base class for reference counted objects.
Definition: SharedObject.h:64
void initDiagnostics()
Initialize diagnostics.
Represents no value.
Definition: Optional.h:32
Sawyer::SharedPointer< Progress > Ptr
Progress objects are reference counted.
State
Decoder state.
Definition: String.h:198