ROSE  0.11.109.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/Partitioner2/BasicTypes.h>
9 #include <Rose/BinaryAnalysis/Partitioner2/ControlFlowGraph.h>
10 #include <Rose/BinaryAnalysis/Partitioner2/FunctionCallGraph.h>
11 #include <Rose/BinaryAnalysis/Reachability.h>
12 #include <Rose/BinaryAnalysis/RegisterNames.h>
13 #include <Rose/BinaryAnalysis/Unparser/EdgeArrows.h>
14 #include <Rose/BinaryAnalysis/Unparser/Settings.h>
15 #include <Rose/BitFlags.h>
16 #include <Rose/Progress.h>
17 
18 #include <Sawyer/Map.h>
19 #include <Sawyer/Message.h>
20 #include <Sawyer/SharedObject.h>
21 
22 namespace Rose {
23 namespace BinaryAnalysis {
24 
26 namespace Unparser {
27 
29 typedef std::map<uint64_t, std::string> LabelMap;
30 
33 
34 // used internally to initialize mlog
35 void initDiagnostics();
36 
38 // Supporting functions
40 
44 std::string invalidRegister(SgAsmInstruction*, RegisterDescriptor, const RegisterDictionaryPtr&);
45 
47 // Margins containing arrows
49 
51 class ArrowMargin {
52 public:
54  enum Flags {
59  POINTABLE_ENTITY_START = 0x00000001,
60 
64  POINTABLE_ENTITY_END = 0x00000002,
65 
67  POINTABLE_ENTITY_INSIDE = 0x00000004,
68 
71  ALWAYS_RENDER = 0x00000008
72  };
73 
74  EdgeArrows arrows;
75  BitFlags<Flags> flags;
81  void reset() {
82  arrows.reset();
83  flags = 0;
84  latestEntity = Sawyer::Nothing();
85  }
86 
92  std::string render(Sawyer::Optional<EdgeArrows::VertexId> currentEntity);
93 };
94 
96 // Output style
98 
100 class StyleStack {
101  std::vector<Style> stack_;
102  Style current_;
103  Color::Colorization colorization_;
104 
105 public:
106  StyleStack() {}
107 
111  Color::Colorization colorization() const { return colorization_; }
112  void colorization(const Color::Colorization c) { colorization_ = c; }
118  size_t push(const Style&);
119 
123  void pop();
124 
126  void popTo(size_t);
127 
129  void reset();
130 
132  size_t size() const;
133 
139  const Style& current() const;
140 
141 private:
142  void merge(const Style &style); // merge style into current_
143  void mergeAll(); // recalculate current_ based on stack_
144 };
145 
147 class StyleGuard {
148  StyleStack &stack_;
149  size_t n_;
150  Style current_;
151  Style previous_;
152 public:
157  StyleGuard(StyleStack &stack, const Style &style)
158  : stack_(stack) {
159  previous_ = stack_.current();
160  n_ = stack_.push(style);
161  current_ = stack_.current();
162  }
163 
164  StyleGuard(StyleStack &stack, const Style &first, const Style &second)
165  : stack_(stack) {
166  previous_ = stack_.current();
167  n_ = stack_.push(first);
168  stack_.push(second);
169  current_ = stack_.current();
170  }
171 
172  ~StyleGuard() {
173  stack_.popTo(n_);
174  }
175 
177  std::string render() const;
178 
180  std::string restore() const;
181 
183  const Style& current() const {
184  return current_;
185  }
186 
188  const Style& previous() const {
189  return previous_;
190  }
191 };
192 
194 // State of the unparser (the unparser itself is const during unparsing)
196 
201 class State {
202 public:
205 private:
206  const Partitioner2::Partitioner &partitioner_;
207  Partitioner2::FunctionCallGraph cg_;
208  Partitioner2::FunctionPtr currentFunction_;
209  Partitioner2::BasicBlockPtr currentBasicBlock_;
210  Sawyer::Optional<EdgeArrows::VertexId> currentPredSuccId_;
211  std::string nextInsnLabel_;
212  AddrString basicBlockLabels_;
213  RegisterNames registerNames_;
214  const Base &frontUnparser_;
215  std::vector<Reachability::ReasonFlags> cfgVertexReachability_;
216  Sawyer::Container::Map<Reachability::ReasonFlags::Vector, std::string> reachabilityNames_; // map reachability value to name
217  ArrowMargin intraFunctionCfgArrows_; // arrows for the intra-function control flow graphs
218  ArrowMargin intraFunctionBlockArrows_; // user-defined intra-function arrows to/from blocks
219  ArrowMargin globalBlockArrows_; // user-defined global arrows to/from blocks
220  bool cfgArrowsPointToInsns_; // arrows point to insns? else predecessor/successor lines
221  StyleStack styleStack_; // styles
222 
223 public:
224  State(const Partitioner2::Partitioner&, const Settings&, const Base &frontUnparser);
225  State(const Partitioner2::Partitioner&, const RegisterDictionaryPtr&, const Settings&, const Base &frontUnparser);
226  virtual ~State();
227 
228  const Partitioner2::Partitioner& partitioner() const;
229 
230  const Partitioner2::FunctionCallGraph& cg() const;
231 
238  const std::vector<Reachability::ReasonFlags> cfgVertexReachability() const;
239  void cfgVertexReachability(const std::vector<Reachability::ReasonFlags>&);
246  Reachability::ReasonFlags isCfgVertexReachable(size_t vertexId) const;
247 
260  const ArrowMargin& intraFunctionCfgArrows() const { return intraFunctionCfgArrows_; }
261  ArrowMargin& intraFunctionCfgArrows() { return intraFunctionCfgArrows_; }
277  const ArrowMargin& intraFunctionBlockArrows() const { return intraFunctionBlockArrows_; }
278  ArrowMargin& intraFunctionBlockArrows() { return intraFunctionBlockArrows_; }
289  const ArrowMargin& globalBlockArrows() const { return globalBlockArrows_; }
290  ArrowMargin& globalBlockArrows() { return globalBlockArrows_; }
294  void thisIsBasicBlockFirstInstruction();
295 
297  void thisIsBasicBlockLastInstruction();
298 
306  Sawyer::Optional<EdgeArrows::VertexId> currentPredSuccId() const { return currentPredSuccId_; }
307  void currentPredSuccId(Sawyer::Optional<EdgeArrows::VertexId> id) { currentPredSuccId_ = id; }
317  bool cfgArrowsPointToInsns() const { return cfgArrowsPointToInsns_; }
318  void cfgArrowsPointToInsns(bool b) { cfgArrowsPointToInsns_ = b; }
324  const StyleStack& styleStack() const { return styleStack_; }
325  StyleStack& styleStack() { return styleStack_; }
342  void reachabilityName(Reachability::Reason value, const std::string &name);
343  std::string reachabilityName(Reachability::ReasonFlags value) const;
346  Partitioner2::FunctionPtr currentFunction() const;
347  void currentFunction(const Partitioner2::FunctionPtr&);
348 
349  Partitioner2::BasicBlockPtr currentBasicBlock() const;
350  void currentBasicBlock(const Partitioner2::BasicBlockPtr&);
351 
352  const std::string& nextInsnLabel() const;
353  void nextInsnLabel(const std::string&);
354 
355  const RegisterNames& registerNames() const;
356  void registerNames(const RegisterNames &r);
357 
358  const AddrString& basicBlockLabels() const;
359  AddrString& basicBlockLabels();
360 
361  const Base& frontUnparser() const;
362 };
363 
365 // Base unparser
367 
414 class Base: public Sawyer::SharedObject {
415 public:
417 
418 private:
419  Ptr nextUnparser_;
420 
421 protected:
422  Base();
423  explicit Base(const Ptr &nextUnparser);
424 
425 public:
426  virtual Ptr copy() const = 0;
427  virtual ~Base();
428 
438  virtual const Settings& settings() const = 0;
439  virtual Settings& settings() = 0;
440  void settings(const Settings &s) {
441  settings() = s;
442  }
452  Ptr nextUnparser() const { return nextUnparser_; }
453  void nextUnparser(Ptr next) { nextUnparser_ = next; }
463  void operator()(std::ostream &out, const Partitioner2::Partitioner &p) const /*final*/ {
464  unparse(out, p);
465  }
466  void operator()(std::ostream &out, const Partitioner2::Partitioner &p,
467  SgAsmInstruction *insn) const /*final*/ {
468  unparse(out, p, insn);
469  }
470  void operator()(std::ostream &out, const Partitioner2::Partitioner &p,
471  const Partitioner2::BasicBlockPtr &bb) const /*final*/{
472  unparse(out, p, bb);
473  }
474  void operator()(std::ostream &out, const Partitioner2::Partitioner &p,
475  const Partitioner2::DataBlockPtr &db) const /*final*/ {
476  unparse(out, p, db);
477  }
478  void operator()(std::ostream &out, const Partitioner2::Partitioner &p,
479  const Partitioner2::FunctionPtr &f) const /*final*/ {
480  unparse(out, p, f);
481  }
489  std::string operator()(const Partitioner2::Partitioner &p, const Progress::Ptr &progress = Progress::Ptr()) const /*final*/ {
490  return unparse(p, progress);
491  }
492  std::string operator()(const Partitioner2::Partitioner &p, SgAsmInstruction *insn) const /*final*/ {
493  return unparse(p, insn);
494  }
495  std::string operator()(const Partitioner2::Partitioner &p, const Partitioner2::BasicBlockPtr &bb) const /*final*/ {
496  return unparse(p, bb);
497  }
498  std::string operator()(const Partitioner2::Partitioner &p, const Partitioner2::DataBlockPtr &db) const /*final*/ {
499  return unparse(p, db);
500  }
501  std::string operator()(const Partitioner2::Partitioner &p, const Partitioner2::FunctionPtr &f) const /*final*/ {
502  return unparse(p, f);
503  }
509 public:
515  void unparse(std::ostream&, const Partitioner2::Partitioner&, const Progress::Ptr &progress = Progress::Ptr()) const /*final*/;
516  void unparse(std::ostream&, const Partitioner2::Partitioner&, SgAsmInstruction*) const /*final*/;
517  void unparse(std::ostream&, const Partitioner2::Partitioner&, const Partitioner2::BasicBlockPtr&) const /*final*/;
518  void unparse(std::ostream&, const Partitioner2::Partitioner&, const Partitioner2::DataBlockPtr&) const /*final*/;
519  void unparse(std::ostream&, const Partitioner2::Partitioner&, const Partitioner2::FunctionPtr&) const /*final*/;
520 
521  std::string unparse(const Partitioner2::Partitioner&, const Progress::Ptr &progress = Progress::Ptr()) const /*final*/;
522  std::string unparse(const Partitioner2::Partitioner&, SgAsmInstruction*) const /*final*/;
523  std::string unparse(const Partitioner2::Partitioner&, const Partitioner2::BasicBlockPtr&) const /*final*/;
524  std::string unparse(const Partitioner2::Partitioner&, const Partitioner2::DataBlockPtr&) const /*final*/;
525  std::string unparse(const Partitioner2::Partitioner&, const Partitioner2::FunctionPtr&) const /*final*/;
528 public:
551  virtual void emitFunction(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
552  virtual void emitFunctionPrologue(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
553  virtual void emitFunctionBody(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
554  virtual void emitFunctionEpilogue(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
555 
556  virtual void emitFunctionSourceLocation(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
557  virtual void emitFunctionReasons(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
558  virtual void emitFunctionCallers(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
559  virtual void emitFunctionCallees(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
560  virtual void emitFunctionComment(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
561  virtual void emitFunctionStackDelta(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
562  virtual void emitFunctionCallingConvention(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
563  virtual void emitFunctionNoopAnalysis(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
564  virtual void emitFunctionMayReturn(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
565 
566  virtual void emitDataBlockSourceLocation(std::ostream&, const Partitioner2::DataBlockPtr&, State&) const;
567  virtual void emitDataBlock(std::ostream&, const Partitioner2::DataBlockPtr&, State&) const;
568  virtual void emitDataBlockPrologue(std::ostream&, const Partitioner2::DataBlockPtr&, State&) const;
569  virtual void emitDataBlockBody(std::ostream&, const Partitioner2::DataBlockPtr&, State&) const;
570  virtual void emitDataBlockEpilogue(std::ostream&, const Partitioner2::DataBlockPtr&, State&) const;
571 
572  virtual void emitBasicBlock(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
573  virtual void emitBasicBlockPrologue(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
574  virtual void emitBasicBlockBody(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
575  virtual void emitBasicBlockEpilogue(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
576 
577  virtual void emitBasicBlockSourceLocation(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
578  virtual void emitBasicBlockComment(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
579  virtual void emitBasicBlockSharing(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
580  virtual void emitBasicBlockPredecessors(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
581  virtual void emitBasicBlockSuccessors(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
582  virtual void emitBasicBlockReachability(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
583 
584  virtual void emitInstruction(std::ostream&, SgAsmInstruction*, State&) const;
585  virtual void emitInstructionPrologue(std::ostream&, SgAsmInstruction*, State&) const;
586  virtual void emitInstructionBody(std::ostream&, SgAsmInstruction*, State&) const;
587  virtual void emitInstructionEpilogue(std::ostream&, SgAsmInstruction*, State&) const;
588 
589  virtual void emitInstructionAddress(std::ostream&, SgAsmInstruction*, State&) const;
590  virtual void emitInstructionBytes(std::ostream&, SgAsmInstruction*, State&) const;
591  virtual void emitInstructionStackDelta(std::ostream&, SgAsmInstruction*, State&) const;
592  virtual void emitInstructionMnemonic(std::ostream&, SgAsmInstruction*, State&) const;
593  virtual void emitInstructionOperands(std::ostream&, SgAsmInstruction*, State&) const;
594  virtual void emitInstructionComment(std::ostream&, SgAsmInstruction*, State&) const;
595 
596  virtual void emitInstructionSemantics(std::ostream&, SgAsmInstruction*, State&) const;
597 
598  virtual void emitOperand(std::ostream&, SgAsmExpression*, State&) const;
599  virtual void emitOperandPrologue(std::ostream&, SgAsmExpression*, State&) const;
600  virtual void emitOperandBody(std::ostream&, SgAsmExpression*, State&) const;
601  virtual void emitOperandEpilogue(std::ostream&, SgAsmExpression*, State&) const;
602 
603  virtual void emitRegister(std::ostream&, RegisterDescriptor, State&) const;
604  virtual std::vector<std::string> emitUnsignedInteger(std::ostream&, const Sawyer::Container::BitVector&, State&) const;
605  virtual std::vector<std::string> emitSignedInteger(std::ostream&, const Sawyer::Container::BitVector&, State&) const;
606  virtual std::vector<std::string> emitInteger(std::ostream&, const Sawyer::Container::BitVector&, State&,
607  bool isSigned) const;
608  virtual bool emitAddress(std::ostream&, rose_addr_t, State&, bool always=true) const;
609  virtual bool emitAddress(std::ostream&, const Sawyer::Container::BitVector&, State&, bool always=true) const;
610  virtual void emitCommentBlock(std::ostream&, const std::string&, State&, const std::string &prefix = ";;; ") const;
611  virtual void emitTypeName(std::ostream&, SgAsmType*, State&) const;
612 
613  virtual void emitLinePrefix(std::ostream&, State&) const;
616  //----- Other overrridable things -----
617 public:
623  virtual void initializeState(State&) const;
624 
630  virtual void updateIntraFunctionArrows(State&) const;
631 
632  //----- Utility functions -----
633 public:
635  static std::string leftJustify(const std::string&, size_t nchars);
636 
642  static std::string juxtaposeColumns(const std::vector<std::string> &content, const std::vector<size_t> &minWidths,
643  const std::vector<std::pair<std::string, std::string> > &colorEscapes,
644  const std::string &columnSeparator = " ");
645 
651  static bool ascendingSourceAddress(Partitioner2::ControlFlowGraph::ConstEdgeIterator a,
652  Partitioner2::ControlFlowGraph::ConstEdgeIterator b);
653 
659  static bool ascendingTargetAddress(Partitioner2::ControlFlowGraph::ConstEdgeIterator a,
660  Partitioner2::ControlFlowGraph::ConstEdgeIterator b);
661 
666  static std::vector<Partitioner2::ControlFlowGraph::ConstEdgeIterator>
667  orderedBlockPredecessors(const Partitioner2::Partitioner&, const Partitioner2::BasicBlock::Ptr&);
668 
673  static std::vector<Partitioner2::ControlFlowGraph::ConstEdgeIterator>
674  orderedBlockSuccessors(const Partitioner2::Partitioner&, const Partitioner2::BasicBlock::Ptr&);
675 };
676 
677 
679 // Python API wrappers and functions
681 
682 #ifdef ROSE_ENABLE_PYTHON_API
683 class PythonBase {
684  Base::Ptr base_;
685 
686 public:
687  PythonBase() {}
688 
689  explicit PythonBase(const Base::Ptr &base)
690  : base_(base) {
691  ASSERT_not_null(base);
692  }
693 
694  std::string unparse(const Partitioner2::Partitioner &p) const {
695  return base_->unparse(p);
696  }
697 
698  void print(const Partitioner2::Partitioner &p) const {
699  base_->unparse(std::cout, p);
700  }
701 };
702 #endif
703 
704 } // namespace
705 } // namespace
706 } // namespace
707 
708 #endif
709 #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
Sawyer::SharedPointer< RegisterDictionary > RegisterDictionaryPtr
Reference counting pointer.
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:767
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.
BitFlags< Reason, uint32_t > ReasonFlags
Bit flags for reachability.
Definition: Reachability.h:56
Base class for expressions.
0x57: "Pop the top operand stack value"
Base class for binary types.
Base class for reference counted objects.
Definition: SharedObject.h:64
void initDiagnostics()
Initialize diagnostics.
Sawyer::SharedPointer< Node > Ptr
Reference counting pointer.
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
const char * Flags(int64_t)
Convert Rose::BinaryAnalysis::Unparser::ArrowMargin::Flags enum constant to a string.