Home | History | Annotate | Line # | Download | only in DWARF
      1 //===--- DWARFExpression.h - DWARF Expression handling ----------*- C++ -*-===//
      2 //
      3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4 // See https://llvm.org/LICENSE.txt for license information.
      5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 
      9 #ifndef LLVM_DEBUGINFO_DWARF_DWARFEXPRESSION_H
     10 #define LLVM_DEBUGINFO_DWARF_DWARFEXPRESSION_H
     11 
     12 #include "llvm/ADT/ArrayRef.h"
     13 #include "llvm/ADT/Optional.h"
     14 #include "llvm/ADT/iterator.h"
     15 #include "llvm/ADT/iterator_range.h"
     16 #include "llvm/BinaryFormat/Dwarf.h"
     17 #include "llvm/DebugInfo/DIContext.h"
     18 #include "llvm/Support/DataExtractor.h"
     19 
     20 namespace llvm {
     21 class DWARFUnit;
     22 class MCRegisterInfo;
     23 class raw_ostream;
     24 
     25 class DWARFExpression {
     26 public:
     27   class iterator;
     28 
     29   /// This class represents an Operation in the Expression. Each operation can
     30   /// have up to 2 oprerands.
     31   ///
     32   /// An Operation can be in Error state (check with isError()). This
     33   /// means that it couldn't be decoded successfully and if it is the
     34   /// case, all others fields contain undefined values.
     35   class Operation {
     36   public:
     37     /// Size and signedness of expression operations' operands.
     38     enum Encoding : uint8_t {
     39       Size1 = 0,
     40       Size2 = 1,
     41       Size4 = 2,
     42       Size8 = 3,
     43       SizeLEB = 4,
     44       SizeAddr = 5,
     45       SizeRefAddr = 6,
     46       SizeBlock = 7, ///< Preceding operand contains block size
     47       BaseTypeRef = 8,
     48       WasmLocationArg = 30,
     49       SignBit = 0x80,
     50       SignedSize1 = SignBit | Size1,
     51       SignedSize2 = SignBit | Size2,
     52       SignedSize4 = SignBit | Size4,
     53       SignedSize8 = SignBit | Size8,
     54       SignedSizeLEB = SignBit | SizeLEB,
     55       SizeNA = 0xFF ///< Unused operands get this encoding.
     56     };
     57 
     58     enum DwarfVersion : uint8_t {
     59       DwarfNA, ///< Serves as a marker for unused entries
     60       Dwarf2 = 2,
     61       Dwarf3,
     62       Dwarf4,
     63       Dwarf5
     64     };
     65 
     66     /// Description of the encoding of one expression Op.
     67     struct Description {
     68       DwarfVersion Version; ///< Dwarf version where the Op was introduced.
     69       Encoding Op[2];       ///< Encoding for Op operands, or SizeNA.
     70 
     71       Description(DwarfVersion Version = DwarfNA, Encoding Op1 = SizeNA,
     72                   Encoding Op2 = SizeNA)
     73           : Version(Version) {
     74         Op[0] = Op1;
     75         Op[1] = Op2;
     76       }
     77     };
     78 
     79   private:
     80     friend class DWARFExpression::iterator;
     81     uint8_t Opcode; ///< The Op Opcode, DW_OP_<something>.
     82     Description Desc;
     83     bool Error = false;
     84     uint64_t EndOffset;
     85     uint64_t Operands[2];
     86     uint64_t OperandEndOffsets[2];
     87 
     88   public:
     89     Description &getDescription() { return Desc; }
     90     uint8_t getCode() { return Opcode; }
     91     uint64_t getRawOperand(unsigned Idx) { return Operands[Idx]; }
     92     uint64_t getOperandEndOffset(unsigned Idx) { return OperandEndOffsets[Idx]; }
     93     uint64_t getEndOffset() { return EndOffset; }
     94     bool extract(DataExtractor Data, uint8_t AddressSize, uint64_t Offset,
     95                  Optional<dwarf::DwarfFormat> Format);
     96     bool isError() { return Error; }
     97     bool print(raw_ostream &OS, DIDumpOptions DumpOpts,
     98                const DWARFExpression *Expr, const MCRegisterInfo *RegInfo,
     99                DWARFUnit *U, bool isEH);
    100     bool verify(DWARFUnit *U);
    101   };
    102 
    103   /// An iterator to go through the expression operations.
    104   class iterator
    105       : public iterator_facade_base<iterator, std::forward_iterator_tag,
    106                                     Operation> {
    107     friend class DWARFExpression;
    108     const DWARFExpression *Expr;
    109     uint64_t Offset;
    110     Operation Op;
    111     iterator(const DWARFExpression *Expr, uint64_t Offset)
    112         : Expr(Expr), Offset(Offset) {
    113       Op.Error =
    114           Offset >= Expr->Data.getData().size() ||
    115           !Op.extract(Expr->Data, Expr->AddressSize, Offset, Expr->Format);
    116     }
    117 
    118   public:
    119     class Operation &operator++() {
    120       Offset = Op.isError() ? Expr->Data.getData().size() : Op.EndOffset;
    121       Op.Error =
    122           Offset >= Expr->Data.getData().size() ||
    123           !Op.extract(Expr->Data, Expr->AddressSize, Offset, Expr->Format);
    124       return Op;
    125     }
    126 
    127     class Operation &operator*() {
    128       return Op;
    129     }
    130 
    131     iterator skipBytes(uint64_t Add) {
    132       return iterator(Expr, Op.EndOffset + Add);
    133     }
    134 
    135     // Comparison operators are provided out of line.
    136     friend bool operator==(const iterator &, const iterator &);
    137   };
    138 
    139   DWARFExpression(DataExtractor Data, uint8_t AddressSize,
    140                   Optional<dwarf::DwarfFormat> Format = None)
    141       : Data(Data), AddressSize(AddressSize), Format(Format) {
    142     assert(AddressSize == 8 || AddressSize == 4 || AddressSize == 2);
    143   }
    144 
    145   iterator begin() const { return iterator(this, 0); }
    146   iterator end() const { return iterator(this, Data.getData().size()); }
    147 
    148   void print(raw_ostream &OS, DIDumpOptions DumpOpts,
    149              const MCRegisterInfo *RegInfo, DWARFUnit *U,
    150              bool IsEH = false) const;
    151 
    152   /// Print the expression in a format intended to be compact and useful to a
    153   /// user, but not perfectly unambiguous, or capable of representing every
    154   /// valid DWARF expression. Returns true if the expression was sucessfully
    155   /// printed.
    156   bool printCompact(raw_ostream &OS, const MCRegisterInfo &RegInfo);
    157 
    158   bool verify(DWARFUnit *U);
    159 
    160   bool operator==(const DWARFExpression &RHS) const;
    161 
    162 private:
    163   DataExtractor Data;
    164   uint8_t AddressSize;
    165   Optional<dwarf::DwarfFormat> Format;
    166 };
    167 
    168 inline bool operator==(const DWARFExpression::iterator &LHS,
    169                        const DWARFExpression::iterator &RHS) {
    170   return LHS.Expr == RHS.Expr && LHS.Offset == RHS.Offset;
    171 }
    172 }
    173 #endif
    174