ROSE  0.11.98.0
Unparser/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/BasicTypes.h>
8 #include <Rose/BinaryAnalysis/Unparser/EdgeArrows.h>
9 #include <Rose/BinaryAnalysis/Reachability.h>
10 #include <Rose/BinaryAnalysis/Unparser/Settings.h>
11 #include <Rose/BitFlags.h>
12 #include <Rose/BinaryAnalysis/Partitioner2/BasicTypes.h>
13 #include <Rose/BinaryAnalysis/Partitioner2/ControlFlowGraph.h>
14 #include <Rose/BinaryAnalysis/Partitioner2/FunctionCallGraph.h>
15 #include <Rose/BinaryAnalysis/RegisterNames.h>
16 #include <Sawyer/Map.h>
17 #include <Sawyer/Message.h>
18 #include <Sawyer/SharedObject.h>
19 #include <Rose/Progress.h>
20 
21 namespace Rose {
22 namespace BinaryAnalysis {
23 
25 namespace Unparser {
26 
28 typedef std::map<uint64_t, std::string> LabelMap;
29 
32 
33 // used internally to initialize mlog
34 void initDiagnostics();
35 
37 // Supporting functions
39 
43 std::string invalidRegister(SgAsmInstruction*, RegisterDescriptor, const RegisterDictionaryPtr&);
44 
46 // Margins containing arrows
48 
50 class ArrowMargin {
51 public:
53  enum Flags {
58  POINTABLE_ENTITY_START = 0x00000001,
59 
63  POINTABLE_ENTITY_END = 0x00000002,
64 
66  POINTABLE_ENTITY_INSIDE = 0x00000004,
67 
70  ALWAYS_RENDER = 0x00000008
71  };
72 
73  EdgeArrows arrows;
74  BitFlags<Flags> flags;
80  void reset() {
81  arrows.reset();
82  flags = 0;
83  latestEntity = Sawyer::Nothing();
84  }
85 
91  std::string render(Sawyer::Optional<EdgeArrows::VertexId> currentEntity);
92 };
93 
95 // Output style
97 
99 class StyleStack {
100  std::vector<Style> stack_;
101  Style current_;
102  Color::Colorization colorization_;
103 
104 public:
105  StyleStack() {}
106 
110  Color::Colorization colorization() const { return colorization_; }
111  void colorization(const Color::Colorization c) { colorization_ = c; }
117  size_t push(const Style&);
118 
122  void pop();
123 
125  void popTo(size_t);
126 
128  void reset();
129 
131  size_t size() const;
132 
138  const Style& current() const;
139 
140 private:
141  void merge(const Style &style); // merge style into current_
142  void mergeAll(); // recalculate current_ based on stack_
143 };
144 
146 class StyleGuard {
147  StyleStack &stack_;
148  size_t n_;
149  Style current_;
150  Style previous_;
151 public:
156  StyleGuard(StyleStack &stack, const Style &style)
157  : stack_(stack) {
158  previous_ = stack_.current();
159  n_ = stack_.push(style);
160  current_ = stack_.current();
161  }
162 
163  StyleGuard(StyleStack &stack, const Style &first, const Style &second)
164  : stack_(stack) {
165  previous_ = stack_.current();
166  n_ = stack_.push(first);
167  stack_.push(second);
168  current_ = stack_.current();
169  }
170 
171  ~StyleGuard() {
172  stack_.popTo(n_);
173  }
174 
176  std::string render() const;
177 
179  std::string restore() const;
180 
182  const Style& current() const {
183  return current_;
184  }
185 
187  const Style& previous() const {
188  return previous_;
189  }
190 };
191 
193 // State of the unparser (the unparser itself is const during unparsing)
195 
200 class State {
201 public:
204 private:
205  const Partitioner2::Partitioner &partitioner_;
206  Partitioner2::FunctionCallGraph cg_;
207  Partitioner2::FunctionPtr currentFunction_;
208  Partitioner2::BasicBlockPtr currentBasicBlock_;
209  Sawyer::Optional<EdgeArrows::VertexId> currentPredSuccId_;
210  std::string nextInsnLabel_;
211  AddrString basicBlockLabels_;
212  RegisterNames registerNames_;
213  const Base &frontUnparser_;
214  std::vector<Reachability::ReasonFlags> cfgVertexReachability_;
215  Sawyer::Container::Map<Reachability::ReasonFlags::Vector, std::string> reachabilityNames_; // map reachability value to name
216  ArrowMargin intraFunctionCfgArrows_; // arrows for the intra-function control flow graphs
217  ArrowMargin intraFunctionBlockArrows_; // user-defined intra-function arrows to/from blocks
218  ArrowMargin globalBlockArrows_; // user-defined global arrows to/from blocks
219  bool cfgArrowsPointToInsns_; // arrows point to insns? else predecessor/successor lines
220  StyleStack styleStack_; // styles
221 
222 public:
223  State(const Partitioner2::Partitioner&, const Settings&, const Base &frontUnparser);
224  State(const Partitioner2::Partitioner&, const RegisterDictionaryPtr&, const Settings&, const Base &frontUnparser);
225  virtual ~State();
226 
227  const Partitioner2::Partitioner& partitioner() const;
228 
229  const Partitioner2::FunctionCallGraph& cg() const;
230 
237  const std::vector<Reachability::ReasonFlags> cfgVertexReachability() const;
238  void cfgVertexReachability(const std::vector<Reachability::ReasonFlags>&);
245  Reachability::ReasonFlags isCfgVertexReachable(size_t vertexId) const;
246 
259  const ArrowMargin& intraFunctionCfgArrows() const { return intraFunctionCfgArrows_; }
260  ArrowMargin& intraFunctionCfgArrows() { return intraFunctionCfgArrows_; }
276  const ArrowMargin& intraFunctionBlockArrows() const { return intraFunctionBlockArrows_; }
277  ArrowMargin& intraFunctionBlockArrows() { return intraFunctionBlockArrows_; }
288  const ArrowMargin& globalBlockArrows() const { return globalBlockArrows_; }
289  ArrowMargin& globalBlockArrows() { return globalBlockArrows_; }
293  void thisIsBasicBlockFirstInstruction();
294 
296  void thisIsBasicBlockLastInstruction();
297 
305  Sawyer::Optional<EdgeArrows::VertexId> currentPredSuccId() const { return currentPredSuccId_; }
306  void currentPredSuccId(Sawyer::Optional<EdgeArrows::VertexId> id) { currentPredSuccId_ = id; }
316  bool cfgArrowsPointToInsns() const { return cfgArrowsPointToInsns_; }
317  void cfgArrowsPointToInsns(bool b) { cfgArrowsPointToInsns_ = b; }
323  const StyleStack& styleStack() const { return styleStack_; }
324  StyleStack& styleStack() { return styleStack_; }
341  void reachabilityName(Reachability::Reason value, const std::string &name);
342  std::string reachabilityName(Reachability::ReasonFlags value) const;
345  Partitioner2::FunctionPtr currentFunction() const;
346  void currentFunction(const Partitioner2::FunctionPtr&);
347 
348  Partitioner2::BasicBlockPtr currentBasicBlock() const;
349  void currentBasicBlock(const Partitioner2::BasicBlockPtr&);
350 
351  const std::string& nextInsnLabel() const;
352  void nextInsnLabel(const std::string&);
353 
354  const RegisterNames& registerNames() const;
355  void registerNames(const RegisterNames &r);
356 
357  const AddrString& basicBlockLabels() const;
358  AddrString& basicBlockLabels();
359 
360  const Base& frontUnparser() const;
361 };
362 
364 // Base unparser
366 
413 class Base: public Sawyer::SharedObject {
414 public:
416 
417 private:
418  Ptr nextUnparser_;
419 
420 protected:
421  Base();
422  explicit Base(const Ptr &nextUnparser);
423 
424 public:
425  virtual Ptr copy() const = 0;
426  virtual ~Base();
427 
437  virtual const Settings& settings() const = 0;
438  virtual Settings& settings() = 0;
439  void settings(const Settings &s) {
440  settings() = s;
441  }
451  Ptr nextUnparser() const { return nextUnparser_; }
452  void nextUnparser(Ptr next) { nextUnparser_ = next; }
462  void operator()(std::ostream &out, const Partitioner2::Partitioner &p) const /*final*/ {
463  unparse(out, p);
464  }
465  void operator()(std::ostream &out, const Partitioner2::Partitioner &p,
466  SgAsmInstruction *insn) const /*final*/ {
467  unparse(out, p, insn);
468  }
469  void operator()(std::ostream &out, const Partitioner2::Partitioner &p,
470  const Partitioner2::BasicBlockPtr &bb) const /*final*/{
471  unparse(out, p, bb);
472  }
473  void operator()(std::ostream &out, const Partitioner2::Partitioner &p,
474  const Partitioner2::DataBlockPtr &db) const /*final*/ {
475  unparse(out, p, db);
476  }
477  void operator()(std::ostream &out, const Partitioner2::Partitioner &p,
478  const Partitioner2::FunctionPtr &f) const /*final*/ {
479  unparse(out, p, f);
480  }
488  std::string operator()(const Partitioner2::Partitioner &p, const Progress::Ptr &progress = Progress::Ptr()) const /*final*/ {
489  return unparse(p, progress);
490  }
491  std::string operator()(const Partitioner2::Partitioner &p, SgAsmInstruction *insn) const /*final*/ {
492  return unparse(p, insn);
493  }
494  std::string operator()(const Partitioner2::Partitioner &p, const Partitioner2::BasicBlockPtr &bb) const /*final*/ {
495  return unparse(p, bb);
496  }
497  std::string operator()(const Partitioner2::Partitioner &p, const Partitioner2::DataBlockPtr &db) const /*final*/ {
498  return unparse(p, db);
499  }
500  std::string operator()(const Partitioner2::Partitioner &p, const Partitioner2::FunctionPtr &f) const /*final*/ {
501  return unparse(p, f);
502  }
508 public:
514  void unparse(std::ostream&, const Partitioner2::Partitioner&, const Progress::Ptr &progress = Progress::Ptr()) const /*final*/;
515  void unparse(std::ostream&, const Partitioner2::Partitioner&, SgAsmInstruction*) const /*final*/;
516  void unparse(std::ostream&, const Partitioner2::Partitioner&, const Partitioner2::BasicBlockPtr&) const /*final*/;
517  void unparse(std::ostream&, const Partitioner2::Partitioner&, const Partitioner2::DataBlockPtr&) const /*final*/;
518  void unparse(std::ostream&, const Partitioner2::Partitioner&, const Partitioner2::FunctionPtr&) const /*final*/;
519 
520  std::string unparse(const Partitioner2::Partitioner&, const Progress::Ptr &progress = Progress::Ptr()) const /*final*/;
521  std::string unparse(const Partitioner2::Partitioner&, SgAsmInstruction*) const /*final*/;
522  std::string unparse(const Partitioner2::Partitioner&, const Partitioner2::BasicBlockPtr&) const /*final*/;
523  std::string unparse(const Partitioner2::Partitioner&, const Partitioner2::DataBlockPtr&) const /*final*/;
524  std::string unparse(const Partitioner2::Partitioner&, const Partitioner2::FunctionPtr&) const /*final*/;
527 public:
550  virtual void emitFunction(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
551  virtual void emitFunctionPrologue(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
552  virtual void emitFunctionBody(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
553  virtual void emitFunctionEpilogue(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
554 
555  virtual void emitFunctionSourceLocation(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
556  virtual void emitFunctionReasons(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
557  virtual void emitFunctionCallers(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
558  virtual void emitFunctionCallees(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
559  virtual void emitFunctionComment(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
560  virtual void emitFunctionStackDelta(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
561  virtual void emitFunctionCallingConvention(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
562  virtual void emitFunctionNoopAnalysis(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
563  virtual void emitFunctionMayReturn(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
564 
565  virtual void emitDataBlockSourceLocation(std::ostream&, const Partitioner2::DataBlockPtr&, State&) const;
566  virtual void emitDataBlock(std::ostream&, const Partitioner2::DataBlockPtr&, State&) const;
567  virtual void emitDataBlockPrologue(std::ostream&, const Partitioner2::DataBlockPtr&, State&) const;
568  virtual void emitDataBlockBody(std::ostream&, const Partitioner2::DataBlockPtr&, State&) const;
569  virtual void emitDataBlockEpilogue(std::ostream&, const Partitioner2::DataBlockPtr&, State&) const;
570 
571  virtual void emitBasicBlock(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
572  virtual void emitBasicBlockPrologue(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
573  virtual void emitBasicBlockBody(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
574  virtual void emitBasicBlockEpilogue(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
575 
576  virtual void emitBasicBlockSourceLocation(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
577  virtual void emitBasicBlockComment(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
578  virtual void emitBasicBlockSharing(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
579  virtual void emitBasicBlockPredecessors(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
580  virtual void emitBasicBlockSuccessors(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
581  virtual void emitBasicBlockReachability(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
582 
583  virtual void emitInstruction(std::ostream&, SgAsmInstruction*, State&) const;
584  virtual void emitInstructionPrologue(std::ostream&, SgAsmInstruction*, State&) const;
585  virtual void emitInstructionBody(std::ostream&, SgAsmInstruction*, State&) const;
586  virtual void emitInstructionEpilogue(std::ostream&, SgAsmInstruction*, State&) const;
587 
588  virtual void emitInstructionAddress(std::ostream&, SgAsmInstruction*, State&) const;
589  virtual void emitInstructionBytes(std::ostream&, SgAsmInstruction*, State&) const;
590  virtual void emitInstructionStackDelta(std::ostream&, SgAsmInstruction*, State&) const;
591  virtual void emitInstructionMnemonic(std::ostream&, SgAsmInstruction*, State&) const;
592  virtual void emitInstructionOperands(std::ostream&, SgAsmInstruction*, State&) const;
593  virtual void emitInstructionComment(std::ostream&, SgAsmInstruction*, State&) const;
594 
595  virtual void emitInstructionSemantics(std::ostream&, SgAsmInstruction*, State&) const;
596 
597  virtual void emitOperand(std::ostream&, SgAsmExpression*, State&) const;
598  virtual void emitOperandPrologue(std::ostream&, SgAsmExpression*, State&) const;
599  virtual void emitOperandBody(std::ostream&, SgAsmExpression*, State&) const;
600  virtual void emitOperandEpilogue(std::ostream&, SgAsmExpression*, State&) const;
601 
602  virtual void emitRegister(std::ostream&, RegisterDescriptor, State&) const;
603  virtual std::vector<std::string> emitUnsignedInteger(std::ostream&, const Sawyer::Container::BitVector&, State&) const;
604  virtual std::vector<std::string> emitSignedInteger(std::ostream&, const Sawyer::Container::BitVector&, State&) const;
605  virtual std::vector<std::string> emitInteger(std::ostream&, const Sawyer::Container::BitVector&, State&,
606  bool isSigned) const;
607  virtual bool emitAddress(std::ostream&, rose_addr_t, State&, bool always=true) const;
608  virtual bool emitAddress(std::ostream&, const Sawyer::Container::BitVector&, State&, bool always=true) const;
609  virtual void emitCommentBlock(std::ostream&, const std::string&, State&, const std::string &prefix = ";;; ") const;
610  virtual void emitTypeName(std::ostream&, SgAsmType*, State&) const;
611 
612  virtual void emitLinePrefix(std::ostream&, State&) const;
615  //----- Other overrridable things -----
616 public:
622  virtual void initializeState(State&) const;
623 
629  virtual void updateIntraFunctionArrows(State&) const;
630 
631  //----- Utility functions -----
632 public:
634  static std::string leftJustify(const std::string&, size_t nchars);
635 
641  static std::string juxtaposeColumns(const std::vector<std::string> &content, const std::vector<size_t> &minWidths,
642  const std::vector<std::pair<std::string, std::string> > &colorEscapes,
643  const std::string &columnSeparator = " ");
644 
650  static bool ascendingSourceAddress(Partitioner2::ControlFlowGraph::ConstEdgeIterator a,
651  Partitioner2::ControlFlowGraph::ConstEdgeIterator b);
652 
658  static bool ascendingTargetAddress(Partitioner2::ControlFlowGraph::ConstEdgeIterator a,
659  Partitioner2::ControlFlowGraph::ConstEdgeIterator b);
660 
665  static std::vector<Partitioner2::ControlFlowGraph::ConstEdgeIterator>
666  orderedBlockPredecessors(const Partitioner2::Partitioner&, const Partitioner2::BasicBlock::Ptr&);
667 
672  static std::vector<Partitioner2::ControlFlowGraph::ConstEdgeIterator>
673  orderedBlockSuccessors(const Partitioner2::Partitioner&, const Partitioner2::BasicBlock::Ptr&);
674 };
675 
676 
678 // Python API wrappers and functions
680 
681 #ifdef ROSE_ENABLE_PYTHON_API
682 class PythonBase {
683  Base::Ptr base_;
684 
685 public:
686  PythonBase() {}
687 
688  explicit PythonBase(const Base::Ptr &base)
689  : base_(base) {
690  ASSERT_not_null(base);
691  }
692 
693  std::string unparse(const Partitioner2::Partitioner &p) const {
694  return base_->unparse(p);
695  }
696 
697  void print(const Partitioner2::Partitioner &p) const {
698  base_->unparse(std::cout, p);
699  }
700 };
701 #endif
702 
703 } // namespace
704 } // namespace
705 } // namespace
706 
707 #endif
708 #endif
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:773
Sawyer::SharedPointer< Function > FunctionPtr
Shared-ownership pointer for function.
ROSE_DLL_API void merge(SgProject *project)
Performs sharing of AST nodes followed by linking accross translation units.
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
Sawyer::SharedPointer< Node > Ptr
Reference counting pointer.
Base class for expressions.
Binary analysis.
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.
Definition: Progress.h:168
State
Decoder state.
Definition: String.h:198