Home | History | Annotate | Download | only in DWARF
      1 //===--- DWARFExpression.h - DWARF Expression handling ----------*- 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 #ifndef LLVM_DEBUGINFO_DWARFEXPRESSION_H
     11 #define LLVM_DEBUGINFO_DWARFEXPRESSION_H
     12 
     13 #include "llvm/ADT/ArrayRef.h"
     14 #include "llvm/ADT/iterator.h"
     15 #include "llvm/ADT/iterator_range.h"
     16 #include "llvm/Support/DataExtractor.h"
     17 
     18 namespace llvm {
     19 class DWARFUnit;
     20 class MCRegisterInfo;
     21 class raw_ostream;
     22 
     23 class DWARFExpression {
     24 public:
     25   class iterator;
     26 
     27   /// This class represents an Operation in the Expression. Each operation can
     28   /// have up to 2 oprerands.
     29   ///
     30   /// An Operation can be in Error state (check with isError()). This
     31   /// means that it couldn't be decoded successfully and if it is the
     32   /// case, all others fields contain undefined values.
     33   class Operation {
     34   public:
     35     /// Size and signedness of expression operations' operands.
     36     enum Encoding : uint8_t {
     37       Size1 = 0,
     38       Size2 = 1,
     39       Size4 = 2,
     40       Size8 = 3,
     41       SizeLEB = 4,
     42       SizeAddr = 5,
     43       SizeRefAddr = 6,
     44       SizeBlock = 7, ///< Preceding operand contains block size
     45       SignBit = 0x8,
     46       SignedSize1 = SignBit | Size1,
     47       SignedSize2 = SignBit | Size2,
     48       SignedSize4 = SignBit | Size4,
     49       SignedSize8 = SignBit | Size8,
     50       SignedSizeLEB = SignBit | SizeLEB,
     51       SizeNA = 0xFF ///< Unused operands get this encoding.
     52     };
     53 
     54     enum DwarfVersion : uint8_t {
     55       DwarfNA, ///< Serves as a marker for unused entries
     56       Dwarf2 = 2,
     57       Dwarf3,
     58       Dwarf4
     59     };
     60 
     61     /// Description of the encoding of one expression Op.
     62     struct Description {
     63       DwarfVersion Version; ///< Dwarf version where the Op was introduced.
     64       Encoding Op[2];       ///< Encoding for Op operands, or SizeNA.
     65 
     66       Description(DwarfVersion Version = DwarfNA, Encoding Op1 = SizeNA,
     67                   Encoding Op2 = SizeNA)
     68           : Version(Version) {
     69         Op[0] = Op1;
     70         Op[1] = Op2;
     71       }
     72     };
     73 
     74   private:
     75     friend class DWARFExpression::iterator;
     76     uint8_t Opcode; ///< The Op Opcode, DW_OP_<something>.
     77     Description Desc;
     78     bool Error;
     79     uint32_t EndOffset;
     80     uint64_t Operands[2];
     81 
     82   public:
     83     Description &getDescription() { return Desc; }
     84     uint8_t getCode() { return Opcode; }
     85     uint64_t getRawOperand(unsigned Idx) { return Operands[Idx]; }
     86     uint32_t getEndOffset() { return EndOffset; }
     87     bool extract(DataExtractor Data, uint16_t Version, uint8_t AddressSize,
     88                  uint32_t Offset);
     89     bool isError() { return Error; }
     90     bool print(raw_ostream &OS, const DWARFExpression *U,
     91                const MCRegisterInfo *RegInfo, bool isEH);
     92   };
     93 
     94   /// An iterator to go through the expression operations.
     95   class iterator
     96       : public iterator_facade_base<iterator, std::forward_iterator_tag, Operation> {
     97     friend class DWARFExpression;
     98     DWARFExpression *Expr;
     99     uint32_t Offset;
    100     Operation Op;
    101     iterator(DWARFExpression *Expr, uint32_t Offset)
    102         : Expr(Expr), Offset(Offset) {
    103       Op.Error =
    104           Offset >= Expr->Data.getData().size() ||
    105           !Op.extract(Expr->Data, Expr->Version, Expr->AddressSize, Offset);
    106     }
    107 
    108   public:
    109     class Operation &operator++() {
    110       Offset = Op.isError() ? Expr->Data.getData().size() : Op.EndOffset;
    111       Op.Error =
    112           Offset >= Expr->Data.getData().size() ||
    113           !Op.extract(Expr->Data, Expr->Version, Expr->AddressSize, Offset);
    114       return Op;
    115     }
    116 
    117     class Operation &operator*() {
    118       return Op;
    119     }
    120 
    121     // Comparison operators are provided out of line.
    122     friend bool operator==(const iterator &, const iterator &);
    123   };
    124 
    125   DWARFExpression(DataExtractor Data, uint16_t Version, uint8_t AddressSize)
    126       : Data(Data), Version(Version), AddressSize(AddressSize) {
    127     assert(AddressSize == 8 || AddressSize == 4);
    128   }
    129 
    130   iterator begin() { return iterator(this, 0); }
    131   iterator end() { return iterator(this, Data.getData().size()); }
    132 
    133   void print(raw_ostream &OS, const MCRegisterInfo *RegInfo);
    134 
    135 private:
    136   DataExtractor Data;
    137   uint16_t Version;
    138   uint8_t AddressSize;
    139 };
    140 
    141 inline bool operator==(const DWARFExpression::iterator &LHS,
    142                        const DWARFExpression::iterator &RHS) {
    143   return LHS.Expr == RHS.Expr && LHS.Offset == RHS.Offset;
    144 }
    145 
    146 inline bool operator!=(const DWARFExpression::iterator &LHS,
    147                        const DWARFExpression::iterator &RHS) {
    148   return !(LHS == RHS);
    149 }
    150 }
    151 #endif
    152