ROSE  0.11.2.0
BinaryUnparserBase.h
1 #ifndef ROSE_BinaryAnalysis_UnparserBase_H
2 #define ROSE_BinaryAnalysis_UnparserBase_H
3 
4 #include <rosePublicConfig.h>
5 #ifdef ROSE_BUILD_BINARY_ANALYSIS_SUPPORT
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 // State of the unparser (the unparser itself is const during unparsing)
84 
89 class State {
90 public:
93 private:
94  const Partitioner2::Partitioner &partitioner_;
95  Partitioner2::FunctionCallGraph cg_;
96  Partitioner2::FunctionPtr currentFunction_;
97  Partitioner2::BasicBlockPtr currentBasicBlock_;
98  Sawyer::Optional<EdgeArrows::VertexId> currentPredSuccId_;
99  std::string nextInsnLabel_;
100  AddrString basicBlockLabels_;
101  RegisterNames registerNames_;
102  const Base &frontUnparser_;
103  std::vector<Reachability::ReasonFlags> cfgVertexReachability_;
104  Sawyer::Container::Map<Reachability::ReasonFlags::Vector, std::string> reachabilityNames_; // map reachability value to name
105  ArrowMargin intraFunctionCfgArrows_; // arrows for the intra-function control flow graphs
106  ArrowMargin intraFunctionBlockArrows_; // user-defined intra-function arrows to/from blocks
107  ArrowMargin globalBlockArrows_; // user-defined global arrows to/from blocks
108  bool cfgArrowsPointToInsns_; // arrows point to insns? else predecessor/successor lines
109 
110 public:
111  State(const Partitioner2::Partitioner&, const Settings&, const Base &frontUnparser);
112  State(const Partitioner2::Partitioner&, const RegisterDictionary*, const Settings&, const Base &frontUnparser);
113  virtual ~State();
114 
115  const Partitioner2::Partitioner& partitioner() const;
116 
117  const Partitioner2::FunctionCallGraph& cg() const;
118 
125  const std::vector<Reachability::ReasonFlags> cfgVertexReachability() const;
126  void cfgVertexReachability(const std::vector<Reachability::ReasonFlags>&);
133  Reachability::ReasonFlags isCfgVertexReachable(size_t vertexId) const;
134 
147  const ArrowMargin& intraFunctionCfgArrows() const { return intraFunctionCfgArrows_; }
148  ArrowMargin& intraFunctionCfgArrows() { return intraFunctionCfgArrows_; }
164  const ArrowMargin& intraFunctionBlockArrows() const { return intraFunctionBlockArrows_; }
165  ArrowMargin& intraFunctionBlockArrows() { return intraFunctionBlockArrows_; }
176  const ArrowMargin& globalBlockArrows() const { return globalBlockArrows_; }
177  ArrowMargin& globalBlockArrows() { return globalBlockArrows_; }
181  void thisIsBasicBlockFirstInstruction();
182 
184  void thisIsBasicBlockLastInstruction();
185 
193  Sawyer::Optional<EdgeArrows::VertexId> currentPredSuccId() const { return currentPredSuccId_; }
194  void currentPredSuccId(Sawyer::Optional<EdgeArrows::VertexId> id) { currentPredSuccId_ = id; }
204  bool cfgArrowsPointToInsns() const { return cfgArrowsPointToInsns_; }
205  void cfgArrowsPointToInsns(bool b) { cfgArrowsPointToInsns_ = b; }
222  void reachabilityName(Reachability::Reason value, const std::string &name);
223  std::string reachabilityName(Reachability::ReasonFlags value) const;
226  Partitioner2::FunctionPtr currentFunction() const;
227  void currentFunction(const Partitioner2::FunctionPtr&);
228 
229  Partitioner2::BasicBlockPtr currentBasicBlock() const;
230  void currentBasicBlock(const Partitioner2::BasicBlockPtr&);
231 
232  const std::string& nextInsnLabel() const;
233  void nextInsnLabel(const std::string&);
234 
235  const RegisterNames& registerNames() const;
236  void registerNames(const RegisterNames &r);
237 
238  const AddrString& basicBlockLabels() const;
239  AddrString& basicBlockLabels();
240 
241  const Base& frontUnparser() const;
242 };
243 
245 // Base unparser
247 
294 class Base: public Sawyer::SharedObject {
295 public:
297 
298 private:
299  Ptr nextUnparser_;
300 
301 protected:
302  Base();
303  explicit Base(const Ptr &nextUnparser);
304 
305 public:
306  virtual Ptr copy() const = 0;
307  virtual ~Base();
308 
316  virtual const Settings& settings() const = 0;
317  virtual Settings& settings() = 0;
318  void settings(const Settings &s) {
319  settings() = s;
320  }
330  Ptr nextUnparser() const { return nextUnparser_; }
331  void nextUnparser(Ptr next) { nextUnparser_ = next; }
341  void operator()(std::ostream &out, const Partitioner2::Partitioner &p) const /*final*/ {
342  unparse(out, p);
343  }
344  void operator()(std::ostream &out, const Partitioner2::Partitioner &p,
345  SgAsmInstruction *insn) const /*final*/ {
346  unparse(out, p, insn);
347  }
348  void operator()(std::ostream &out, const Partitioner2::Partitioner &p,
349  const Partitioner2::BasicBlockPtr &bb) const /*final*/{
350  unparse(out, p, bb);
351  }
352  void operator()(std::ostream &out, const Partitioner2::Partitioner &p,
353  const Partitioner2::DataBlockPtr &db) const /*final*/ {
354  unparse(out, p, db);
355  }
356  void operator()(std::ostream &out, const Partitioner2::Partitioner &p,
357  const Partitioner2::FunctionPtr &f) const /*final*/ {
358  unparse(out, p, f);
359  }
367  std::string operator()(const Partitioner2::Partitioner &p, const Progress::Ptr &progress = Progress::Ptr()) const /*final*/ {
368  return unparse(p, progress);
369  }
370  std::string operator()(const Partitioner2::Partitioner &p, SgAsmInstruction *insn) const /*final*/ {
371  return unparse(p, insn);
372  }
373  std::string operator()(const Partitioner2::Partitioner &p, const Partitioner2::BasicBlockPtr &bb) const /*final*/ {
374  return unparse(p, bb);
375  }
376  std::string operator()(const Partitioner2::Partitioner &p, const Partitioner2::DataBlockPtr &db) const /*final*/ {
377  return unparse(p, db);
378  }
379  std::string operator()(const Partitioner2::Partitioner &p, const Partitioner2::FunctionPtr &f) const /*final*/ {
380  return unparse(p, f);
381  }
387 public:
393  void unparse(std::ostream&, const Partitioner2::Partitioner&, const Progress::Ptr &progress = Progress::Ptr()) const /*final*/;
394  void unparse(std::ostream&, const Partitioner2::Partitioner&, SgAsmInstruction*) const /*final*/;
395  void unparse(std::ostream&, const Partitioner2::Partitioner&, const Partitioner2::BasicBlockPtr&) const /*final*/;
396  void unparse(std::ostream&, const Partitioner2::Partitioner&, const Partitioner2::DataBlockPtr&) const /*final*/;
397  void unparse(std::ostream&, const Partitioner2::Partitioner&, const Partitioner2::FunctionPtr&) const /*final*/;
398 
399  std::string unparse(const Partitioner2::Partitioner&, const Progress::Ptr &progress = Progress::Ptr()) const /*final*/;
400  std::string unparse(const Partitioner2::Partitioner&, SgAsmInstruction*) const /*final*/;
401  std::string unparse(const Partitioner2::Partitioner&, const Partitioner2::BasicBlockPtr&) const /*final*/;
402  std::string unparse(const Partitioner2::Partitioner&, const Partitioner2::DataBlockPtr&) const /*final*/;
403  std::string unparse(const Partitioner2::Partitioner&, const Partitioner2::FunctionPtr&) const /*final*/;
406 public:
429  virtual void emitFunction(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
430  virtual void emitFunctionPrologue(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
431  virtual void emitFunctionBody(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
432  virtual void emitFunctionEpilogue(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
433 
434  virtual void emitFunctionSourceLocation(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
435  virtual void emitFunctionReasons(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
436  virtual void emitFunctionCallers(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
437  virtual void emitFunctionCallees(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
438  virtual void emitFunctionComment(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
439  virtual void emitFunctionStackDelta(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
440  virtual void emitFunctionCallingConvention(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
441  virtual void emitFunctionNoopAnalysis(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
442  virtual void emitFunctionMayReturn(std::ostream&, const Partitioner2::FunctionPtr&, State&) const;
443 
444  virtual void emitDataBlockSourceLocation(std::ostream&, const Partitioner2::DataBlockPtr&, State&) const;
445  virtual void emitDataBlock(std::ostream&, const Partitioner2::DataBlockPtr&, State&) const;
446  virtual void emitDataBlockPrologue(std::ostream&, const Partitioner2::DataBlockPtr&, State&) const;
447  virtual void emitDataBlockBody(std::ostream&, const Partitioner2::DataBlockPtr&, State&) const;
448  virtual void emitDataBlockEpilogue(std::ostream&, const Partitioner2::DataBlockPtr&, State&) const;
449 
450  virtual void emitBasicBlock(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
451  virtual void emitBasicBlockPrologue(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
452  virtual void emitBasicBlockBody(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
453  virtual void emitBasicBlockEpilogue(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
454 
455  virtual void emitBasicBlockSourceLocation(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
456  virtual void emitBasicBlockComment(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
457  virtual void emitBasicBlockSharing(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
458  virtual void emitBasicBlockPredecessors(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
459  virtual void emitBasicBlockSuccessors(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
460  virtual void emitBasicBlockReachability(std::ostream&, const Partitioner2::BasicBlockPtr&, State&) const;
461 
462  virtual void emitInstruction(std::ostream&, SgAsmInstruction*, State&) const;
463  virtual void emitInstructionPrologue(std::ostream&, SgAsmInstruction*, State&) const;
464  virtual void emitInstructionBody(std::ostream&, SgAsmInstruction*, State&) const;
465  virtual void emitInstructionEpilogue(std::ostream&, SgAsmInstruction*, State&) const;
466 
467  virtual void emitInstructionAddress(std::ostream&, SgAsmInstruction*, State&) const;
468  virtual void emitInstructionBytes(std::ostream&, SgAsmInstruction*, State&) const;
469  virtual void emitInstructionStackDelta(std::ostream&, SgAsmInstruction*, State&) const;
470  virtual void emitInstructionMnemonic(std::ostream&, SgAsmInstruction*, State&) const;
471  virtual void emitInstructionOperands(std::ostream&, SgAsmInstruction*, State&) const;
472  virtual void emitInstructionComment(std::ostream&, SgAsmInstruction*, State&) const;
473 
474  virtual void emitInstructionSemantics(std::ostream&, SgAsmInstruction*, State&) const;
475 
476  virtual void emitOperand(std::ostream&, SgAsmExpression*, State&) const;
477  virtual void emitOperandPrologue(std::ostream&, SgAsmExpression*, State&) const;
478  virtual void emitOperandBody(std::ostream&, SgAsmExpression*, State&) const;
479  virtual void emitOperandEpilogue(std::ostream&, SgAsmExpression*, State&) const;
480 
481  virtual void emitRegister(std::ostream&, RegisterDescriptor, State&) const;
482  virtual std::vector<std::string> emitUnsignedInteger(std::ostream&, const Sawyer::Container::BitVector&, State&) const;
483  virtual std::vector<std::string> emitSignedInteger(std::ostream&, const Sawyer::Container::BitVector&, State&) const;
484  virtual std::vector<std::string> emitInteger(std::ostream&, const Sawyer::Container::BitVector&, State&,
485  bool isSigned) const;
486  virtual bool emitAddress(std::ostream&, rose_addr_t, State&, bool always=true) const;
487  virtual bool emitAddress(std::ostream&, const Sawyer::Container::BitVector&, State&, bool always=true) const;
488  virtual void emitCommentBlock(std::ostream&, const std::string&, State&, const std::string &prefix = ";;; ") const;
489  virtual void emitTypeName(std::ostream&, SgAsmType*, State&) const;
490 
491  virtual void emitLinePrefix(std::ostream&, State&) const;
494  //----- Other overrridable things -----
495 public:
501  virtual void initializeState(State&) const;
502 
508  virtual void updateIntraFunctionArrows(State&) const;
509 
510  //----- Utility functions -----
511 public:
513  static std::string leftJustify(const std::string&, size_t nchars);
514 
519  static std::string juxtaposeColumns(const std::vector<std::string> &content, const std::vector<size_t> &minWidths,
520  const std::string &columnSeparator = " ");
521 
527  static bool ascendingSourceAddress(Partitioner2::ControlFlowGraph::ConstEdgeIterator a,
528  Partitioner2::ControlFlowGraph::ConstEdgeIterator b);
529 
535  static bool ascendingTargetAddress(Partitioner2::ControlFlowGraph::ConstEdgeIterator a,
536  Partitioner2::ControlFlowGraph::ConstEdgeIterator b);
537 
542  static std::vector<Partitioner2::ControlFlowGraph::ConstEdgeIterator>
543  orderedBlockPredecessors(const Partitioner2::Partitioner&, const Partitioner2::BasicBlock::Ptr&);
544 
549  static std::vector<Partitioner2::ControlFlowGraph::ConstEdgeIterator>
550  orderedBlockSuccessors(const Partitioner2::Partitioner&, const Partitioner2::BasicBlock::Ptr&);
551 };
552 
553 
555 // Python API wrappers and functions
557 
558 #ifdef ROSE_ENABLE_PYTHON_API
559 class PythonBase {
560  Base::Ptr base_;
561 
562 public:
563  PythonBase() {}
564 
565  explicit PythonBase(const Base::Ptr &base)
566  : base_(base) {
567  ASSERT_not_null(base);
568  }
569 
570  std::string unparse(const Partitioner2::Partitioner &p) const {
571  return base_->unparse(p);
572  }
573 
574  void print(const Partitioner2::Partitioner &p) const {
575  base_->unparse(std::cout, p);
576  }
577 };
578 #endif
579 
580 } // namespace
581 } // namespace
582 } // namespace
583 
584 #endif
585 #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:492
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:7465
Represents no value.
Definition: Optional.h:32
Sawyer::SharedPointer< Progress > Ptr
Progress objects are reference counted.
Definition: Progress.h:168