Home | History | Annotate | Download | only in MCAnalysis
      1 //===-- MCAtom.h ------------------------------------------------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file contains the declaration of the MCAtom class, which is used to
     11 // represent a contiguous region in a decoded object that is uniformly data or
     12 // instructions.
     13 //
     14 //===----------------------------------------------------------------------===//
     15 
     16 #ifndef LLVM_MC_MCANALYSIS_MCATOM_H
     17 #define LLVM_MC_MCANALYSIS_MCATOM_H
     18 
     19 #include "llvm/ADT/ArrayRef.h"
     20 #include "llvm/MC/MCInst.h"
     21 #include "llvm/Support/DataTypes.h"
     22 #include <vector>
     23 
     24 namespace llvm {
     25 
     26 class MCModule;
     27 
     28 class MCAtom;
     29 class MCTextAtom;
     30 class MCDataAtom;
     31 
     32 /// \brief Represents a contiguous range of either instructions (a TextAtom)
     33 /// or data (a DataAtom).  Address ranges are expressed as _closed_ intervals.
     34 class MCAtom {
     35   virtual void anchor();
     36 public:
     37   virtual ~MCAtom() {}
     38 
     39   enum AtomKind { TextAtom, DataAtom };
     40   AtomKind getKind() const { return Kind; }
     41 
     42   /// \brief Get the start address of the atom.
     43   uint64_t getBeginAddr() const { return Begin; }
     44   /// \brief Get the end address, i.e. the last one inside the atom.
     45   uint64_t getEndAddr() const { return End; }
     46 
     47   /// \name Atom modification methods:
     48   /// When modifying a TextAtom, keep instruction boundaries in mind.
     49   /// For instance, split must me given the start address of an instruction.
     50   /// @{
     51 
     52   /// \brief Splits the atom in two at a given address.
     53   /// \param SplitPt Address at which to start a new atom, splitting this one.
     54   /// \returns The newly created atom starting at \p SplitPt.
     55   virtual MCAtom *split(uint64_t SplitPt) = 0;
     56 
     57   /// \brief Truncates an atom, discarding everything after \p TruncPt.
     58   /// \param TruncPt Last byte address to be contained in this atom.
     59   virtual void truncate(uint64_t TruncPt) = 0;
     60   /// @}
     61 
     62   /// \name Naming:
     63   ///
     64   /// This is mostly for display purposes, and may contain anything that hints
     65   /// at what the atom contains: section or symbol name, BB start address, ..
     66   /// @{
     67   StringRef getName() const { return Name; }
     68   void setName(StringRef NewName) { Name = NewName.str(); }
     69   /// @}
     70 
     71 protected:
     72   const AtomKind Kind;
     73   std::string Name;
     74   MCModule *Parent;
     75   uint64_t Begin, End;
     76 
     77   friend class MCModule;
     78   MCAtom(AtomKind K, MCModule *P, uint64_t B, uint64_t E)
     79     : Kind(K), Name("(unknown)"), Parent(P), Begin(B), End(E) { }
     80 
     81   /// \name Atom remapping helpers
     82   /// @{
     83 
     84   /// \brief Remap the atom, using the given range, updating Begin/End.
     85   /// One or both of the bounds can remain the same, but overlapping with other
     86   /// atoms in the module is still forbidden.
     87   void remap(uint64_t NewBegin, uint64_t NewEnd);
     88 
     89   /// \brief Remap the atom to prepare for a truncation at TruncPt.
     90   /// Equivalent to:
     91   /// \code
     92   ///   // Bound checks
     93   ///   remap(Begin, TruncPt);
     94   /// \endcode
     95   void remapForTruncate(uint64_t TruncPt);
     96 
     97   /// \brief Remap the atom to prepare for a split at SplitPt.
     98   /// The bounds for the resulting atoms are returned in {L,R}{Begin,End}.
     99   /// The current atom is truncated to \p LEnd.
    100   void remapForSplit(uint64_t SplitPt,
    101                      uint64_t &LBegin, uint64_t &LEnd,
    102                      uint64_t &RBegin, uint64_t &REnd);
    103   /// @}
    104 };
    105 
    106 /// \name Text atom
    107 /// @{
    108 
    109 /// \brief An entry in an MCTextAtom: a disassembled instruction.
    110 /// NOTE: Both the Address and Size field are actually redundant when taken in
    111 /// the context of the text atom, and may better be exposed in an iterator
    112 /// instead of stored in the atom, which would replace this class.
    113 class MCDecodedInst {
    114 public:
    115   MCInst Inst;
    116   uint64_t Address;
    117   uint64_t Size;
    118   MCDecodedInst(const MCInst &Inst, uint64_t Address, uint64_t Size)
    119     : Inst(Inst), Address(Address), Size(Size) {}
    120 };
    121 
    122 /// \brief An atom consisting of disassembled instructions.
    123 class MCTextAtom : public MCAtom {
    124 private:
    125   typedef std::vector<MCDecodedInst> InstListTy;
    126   InstListTy Insts;
    127 
    128   /// \brief The address of the next appended instruction, i.e., the
    129   /// address immediately after the last instruction in the atom.
    130   uint64_t NextInstAddress;
    131 public:
    132   /// Append an instruction, expanding the atom if necessary.
    133   void addInst(const MCInst &Inst, uint64_t Size);
    134 
    135   /// \name Instruction list access
    136   /// @{
    137   typedef InstListTy::const_iterator const_iterator;
    138   const_iterator begin() const { return Insts.begin(); }
    139   const_iterator end()   const { return Insts.end(); }
    140 
    141   const MCDecodedInst &back() const { return Insts.back(); }
    142   const MCDecodedInst &at(size_t n) const { return Insts.at(n); }
    143   size_t size() const { return Insts.size(); }
    144   /// @}
    145 
    146   /// \name Atom type specific split/truncate logic.
    147   /// @{
    148   MCTextAtom *split(uint64_t SplitPt) override;
    149   void     truncate(uint64_t TruncPt) override;
    150   /// @}
    151 
    152   // Class hierarchy.
    153   static bool classof(const MCAtom *A) { return A->getKind() == TextAtom; }
    154 private:
    155   friend class MCModule;
    156   // Private constructor - only callable by MCModule
    157   MCTextAtom(MCModule *P, uint64_t Begin, uint64_t End)
    158     : MCAtom(TextAtom, P, Begin, End), NextInstAddress(Begin) {}
    159 };
    160 /// @}
    161 
    162 /// \name Data atom
    163 /// @{
    164 
    165 /// \brief An entry in an MCDataAtom.
    166 // NOTE: This may change to a more complex type in the future.
    167 typedef uint8_t MCData;
    168 
    169 /// \brief An atom consising of a sequence of bytes.
    170 class MCDataAtom : public MCAtom {
    171   std::vector<MCData> Data;
    172 
    173 public:
    174   /// Append a data entry, expanding the atom if necessary.
    175   void addData(const MCData &D);
    176 
    177   /// Get a reference to the data in this atom.
    178   ArrayRef<MCData> getData() const { return Data; }
    179 
    180   /// \name Atom type specific split/truncate logic.
    181   /// @{
    182   MCDataAtom *split(uint64_t SplitPt) override;
    183   void     truncate(uint64_t TruncPt) override;
    184   /// @}
    185 
    186   // Class hierarchy.
    187   static bool classof(const MCAtom *A) { return A->getKind() == DataAtom; }
    188 private:
    189   friend class MCModule;
    190   // Private constructor - only callable by MCModule
    191   MCDataAtom(MCModule *P, uint64_t Begin, uint64_t End)
    192     : MCAtom(DataAtom, P, Begin, End) {
    193     Data.reserve(End + 1 - Begin);
    194   }
    195 };
    196 
    197 }
    198 
    199 #endif
    200