LCOV - code coverage report
Current view: top level - include/llvm/DebugInfo/DWARF - DWARFDebugFrame.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 33 46 71.7 %
Date: 2018-10-20 13:21:21 Functions: 6 21 28.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- DWARFDebugFrame.h - Parsing of .debug_frame --------------*- 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_DWARF_DWARFDEBUGFRAME_H
      11             : #define LLVM_DEBUGINFO_DWARF_DWARFDEBUGFRAME_H
      12             : 
      13             : #include "llvm/ADT/ArrayRef.h"
      14             : #include "llvm/ADT/iterator.h"
      15             : #include "llvm/ADT/SmallString.h"
      16             : #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
      17             : #include "llvm/DebugInfo/DWARF/DWARFExpression.h"
      18             : #include "llvm/Support/Error.h"
      19             : #include <memory>
      20             : #include <vector>
      21             : 
      22             : namespace llvm {
      23             : 
      24             : class raw_ostream;
      25             : 
      26             : namespace dwarf {
      27             : 
      28             : /// Represent a sequence of Call Frame Information instructions that, when read
      29             : /// in order, construct a table mapping PC to frame state. This can also be
      30             : /// referred to as "CFI rules" in DWARF literature to avoid confusion with
      31             : /// computer programs in the broader sense, and in this context each instruction
      32             : /// would be a rule to establish the mapping. Refer to pg. 172 in the DWARF5
      33             : /// manual, "6.4.1 Structure of Call Frame Information".
      34         285 : class CFIProgram {
      35             : public:
      36             :   typedef SmallVector<uint64_t, 2> Operands;
      37             : 
      38             :   /// An instruction consists of a DWARF CFI opcode and an optional sequence of
      39             :   /// operands. If it refers to an expression, then this expression has its own
      40             :   /// sequence of operations and operands handled separately by DWARFExpression.
      41        6378 :   struct Instruction {
      42        2895 :     Instruction(uint8_t Opcode) : Opcode(Opcode) {}
      43             : 
      44             :     uint8_t Opcode;
      45             :     Operands Ops;
      46             :     // Associated DWARF expression in case this instruction refers to one
      47             :     Optional<DWARFExpression> Expression;
      48             :   };
      49             : 
      50             :   using InstrList = std::vector<Instruction>;
      51             :   using iterator = InstrList::iterator;
      52             :   using const_iterator = InstrList::const_iterator;
      53             : 
      54             :   iterator begin() { return Instructions.begin(); }
      55             :   const_iterator begin() const { return Instructions.begin(); }
      56             :   iterator end() { return Instructions.end(); }
      57             :   const_iterator end() const { return Instructions.end(); }
      58             : 
      59             :   unsigned size() const { return (unsigned)Instructions.size(); }
      60             :   bool empty() const { return Instructions.empty(); }
      61             : 
      62             :   CFIProgram(uint64_t CodeAlignmentFactor, int64_t DataAlignmentFactor)
      63         425 :       : CodeAlignmentFactor(CodeAlignmentFactor),
      64         425 :         DataAlignmentFactor(DataAlignmentFactor) {}
      65             : 
      66             :   /// Parse and store a sequence of CFI instructions from Data,
      67             :   /// starting at *Offset and ending at EndOffset. *Offset is updated
      68             :   /// to EndOffset upon successful parsing, or indicates the offset
      69             :   /// where a problem occurred in case an error is returned.
      70             :   Error parse(DataExtractor Data, uint32_t *Offset, uint32_t EndOffset);
      71             : 
      72             :   void dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH,
      73             :             unsigned IndentLevel = 1) const;
      74             : 
      75             : private:
      76             :   std::vector<Instruction> Instructions;
      77             :   const uint64_t CodeAlignmentFactor;
      78             :   const int64_t DataAlignmentFactor;
      79             : 
      80             :   /// Convenience method to add a new instruction with the given opcode.
      81        1449 :   void addInstruction(uint8_t Opcode) {
      82        1449 :     Instructions.push_back(Instruction(Opcode));
      83        1449 :   }
      84             : 
      85             :   /// Add a new single-operand instruction.
      86         937 :   void addInstruction(uint8_t Opcode, uint64_t Operand1) {
      87        1874 :     Instructions.push_back(Instruction(Opcode));
      88         937 :     Instructions.back().Ops.push_back(Operand1);
      89         937 :   }
      90             : 
      91             :   /// Add a new instruction that has two operands.
      92         509 :   void addInstruction(uint8_t Opcode, uint64_t Operand1, uint64_t Operand2) {
      93        1018 :     Instructions.push_back(Instruction(Opcode));
      94         509 :     Instructions.back().Ops.push_back(Operand1);
      95         509 :     Instructions.back().Ops.push_back(Operand2);
      96         509 :   }
      97             : 
      98             :   /// Types of operands to CFI instructions
      99             :   /// In DWARF, this type is implicitly tied to a CFI instruction opcode and
     100             :   /// thus this type doesn't need to be explictly written to the file (this is
     101             :   /// not a DWARF encoding). The relationship of instrs to operand types can
     102             :   /// be obtained from getOperandTypes() and is only used to simplify
     103             :   /// instruction printing.
     104             :   enum OperandType {
     105             :     OT_Unset,
     106             :     OT_None,
     107             :     OT_Address,
     108             :     OT_Offset,
     109             :     OT_FactoredCodeOffset,
     110             :     OT_SignedFactDataOffset,
     111             :     OT_UnsignedFactDataOffset,
     112             :     OT_Register,
     113             :     OT_Expression
     114             :   };
     115             : 
     116             :   /// Retrieve the array describing the types of operands according to the enum
     117             :   /// above. This is indexed by opcode.
     118             :   static ArrayRef<OperandType[2]> getOperandTypes();
     119             : 
     120             :   /// Print \p Opcode's operand number \p OperandIdx which has value \p Operand.
     121             :   void printOperand(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH,
     122             :                     const Instruction &Instr, unsigned OperandIdx,
     123             :                     uint64_t Operand) const;
     124             : };
     125             : 
     126             : /// An entry in either debug_frame or eh_frame. This entry can be a CIE or an
     127             : /// FDE.
     128             : class FrameEntry {
     129             : public:
     130             :   enum FrameKind { FK_CIE, FK_FDE };
     131             : 
     132             :   FrameEntry(FrameKind K, uint64_t Offset, uint64_t Length, uint64_t CodeAlign,
     133             :              int64_t DataAlign)
     134         285 :       : Kind(K), Offset(Offset), Length(Length), CFIs(CodeAlign, DataAlign) {}
     135             : 
     136         285 :   virtual ~FrameEntry() {}
     137             : 
     138           0 :   FrameKind getKind() const { return Kind; }
     139           0 :   uint64_t getOffset() const { return Offset; }
     140           0 :   uint64_t getLength() const { return Length; }
     141           9 :   const CFIProgram &cfis() const { return CFIs; }
     142         425 :   CFIProgram &cfis() { return CFIs; }
     143             : 
     144             :   /// Dump the instructions in this CFI fragment
     145             :   virtual void dump(raw_ostream &OS, const MCRegisterInfo *MRI,
     146             :                     bool IsEH) const = 0;
     147             : 
     148             : protected:
     149             :   const FrameKind Kind;
     150             : 
     151             :   /// Offset of this entry in the section.
     152             :   const uint64_t Offset;
     153             : 
     154             :   /// Entry length as specified in DWARF.
     155             :   const uint64_t Length;
     156             : 
     157             :   CFIProgram CFIs;
     158             : };
     159             : 
     160             : /// DWARF Common Information Entry (CIE)
     161             : class CIE : public FrameEntry {
     162             : public:
     163             :   // CIEs (and FDEs) are simply container classes, so the only sensible way to
     164             :   // create them is by providing the full parsed contents in the constructor.
     165         140 :   CIE(uint64_t Offset, uint64_t Length, uint8_t Version,
     166             :       SmallString<8> Augmentation, uint8_t AddressSize,
     167             :       uint8_t SegmentDescriptorSize, uint64_t CodeAlignmentFactor,
     168             :       int64_t DataAlignmentFactor, uint64_t ReturnAddressRegister,
     169             :       SmallString<8> AugmentationData, uint32_t FDEPointerEncoding,
     170             :       uint32_t LSDAPointerEncoding, Optional<uint64_t> Personality,
     171             :       Optional<uint32_t> PersonalityEnc)
     172         140 :       : FrameEntry(FK_CIE, Offset, Length, CodeAlignmentFactor,
     173             :                    DataAlignmentFactor),
     174             :         Version(Version), Augmentation(std::move(Augmentation)),
     175             :         AddressSize(AddressSize), SegmentDescriptorSize(SegmentDescriptorSize),
     176             :         CodeAlignmentFactor(CodeAlignmentFactor),
     177             :         DataAlignmentFactor(DataAlignmentFactor),
     178             :         ReturnAddressRegister(ReturnAddressRegister),
     179             :         AugmentationData(std::move(AugmentationData)),
     180             :         FDEPointerEncoding(FDEPointerEncoding),
     181             :         LSDAPointerEncoding(LSDAPointerEncoding), Personality(Personality),
     182         322 :         PersonalityEnc(PersonalityEnc) {}
     183             : 
     184           9 :   static bool classof(const FrameEntry *FE) { return FE->getKind() == FK_CIE; }
     185             : 
     186             :   StringRef getAugmentationString() const { return Augmentation; }
     187           0 :   uint64_t getCodeAlignmentFactor() const { return CodeAlignmentFactor; }
     188           0 :   int64_t getDataAlignmentFactor() const { return DataAlignmentFactor; }
     189           0 :   uint8_t getVersion() const { return Version; }
     190           0 :   uint64_t getReturnAddressRegister() const { return ReturnAddressRegister; }
     191             :   Optional<uint64_t> getPersonalityAddress() const { return Personality; }
     192             :   Optional<uint32_t> getPersonalityEncoding() const { return PersonalityEnc; }
     193             : 
     194           0 :   uint32_t getFDEPointerEncoding() const { return FDEPointerEncoding; }
     195             : 
     196           0 :   uint32_t getLSDAPointerEncoding() const { return LSDAPointerEncoding; }
     197             : 
     198             :   void dump(raw_ostream &OS, const MCRegisterInfo *MRI,
     199             :             bool IsEH) const override;
     200             : 
     201             : private:
     202             :   /// The following fields are defined in section 6.4.1 of the DWARF standard v4
     203             :   const uint8_t Version;
     204             :   const SmallString<8> Augmentation;
     205             :   const uint8_t AddressSize;
     206             :   const uint8_t SegmentDescriptorSize;
     207             :   const uint64_t CodeAlignmentFactor;
     208             :   const int64_t DataAlignmentFactor;
     209             :   const uint64_t ReturnAddressRegister;
     210             : 
     211             :   // The following are used when the CIE represents an EH frame entry.
     212             :   const SmallString<8> AugmentationData;
     213             :   const uint32_t FDEPointerEncoding;
     214             :   const uint32_t LSDAPointerEncoding;
     215             :   const Optional<uint64_t> Personality;
     216             :   const Optional<uint32_t> PersonalityEnc;
     217             : };
     218             : 
     219             : /// DWARF Frame Description Entry (FDE)
     220             : class FDE : public FrameEntry {
     221             : public:
     222             :   // Each FDE has a CIE it's "linked to". Our FDE contains is constructed with
     223             :   // an offset to the CIE (provided by parsing the FDE header). The CIE itself
     224             :   // is obtained lazily once it's actually required.
     225             :   FDE(uint64_t Offset, uint64_t Length, int64_t LinkedCIEOffset,
     226             :       uint64_t InitialLocation, uint64_t AddressRange, CIE *Cie,
     227             :       Optional<uint64_t> LSDAAddress)
     228         285 :       : FrameEntry(FK_FDE, Offset, Length,
     229         285 :                    Cie ? Cie->getCodeAlignmentFactor() : 0,
     230         285 :                    Cie ? Cie->getDataAlignmentFactor() : 0),
     231             :         LinkedCIEOffset(LinkedCIEOffset), InitialLocation(InitialLocation),
     232         855 :         AddressRange(AddressRange), LinkedCIE(Cie), LSDAAddress(LSDAAddress) {}
     233             : 
     234         285 :   ~FDE() override = default;
     235             : 
     236           0 :   const CIE *getLinkedCIE() const { return LinkedCIE; }
     237           0 :   uint64_t getInitialLocation() const { return InitialLocation; }
     238           0 :   uint64_t getAddressRange() const { return AddressRange; }
     239             :   Optional<uint64_t> getLSDAAddress() const { return LSDAAddress; }
     240             : 
     241             :   void dump(raw_ostream &OS, const MCRegisterInfo *MRI,
     242             :             bool IsEH) const override;
     243             : 
     244           0 :   static bool classof(const FrameEntry *FE) { return FE->getKind() == FK_FDE; }
     245             : 
     246             : private:
     247             :   /// The following fields are defined in section 6.4.1 of the DWARF standard v3
     248             :   const uint64_t LinkedCIEOffset;
     249             :   const uint64_t InitialLocation;
     250             :   const uint64_t AddressRange;
     251             :   const CIE *LinkedCIE;
     252             :   const Optional<uint64_t> LSDAAddress;
     253             : };
     254             : 
     255             : } // end namespace dwarf
     256             : 
     257             : /// A parsed .debug_frame or .eh_frame section
     258         142 : class DWARFDebugFrame {
     259             :   // True if this is parsing an eh_frame section.
     260             :   const bool IsEH;
     261             :   // Not zero for sane pointer values coming out of eh_frame
     262             :   const uint64_t EHFrameAddress;
     263             : 
     264             :   std::vector<std::unique_ptr<dwarf::FrameEntry>> Entries;
     265             :   using iterator = pointee_iterator<decltype(Entries)::const_iterator>;
     266             : 
     267             :   /// Return the entry at the given offset or nullptr.
     268             :   dwarf::FrameEntry *getEntryAtOffset(uint64_t Offset) const;
     269             : 
     270             : public:
     271             :   // If IsEH is true, assume it is a .eh_frame section. Otherwise,
     272             :   // it is a .debug_frame section. EHFrameAddress should be different
     273             :   // than zero for correct parsing of .eh_frame addresses when they
     274             :   // use a PC-relative encoding.
     275             :   DWARFDebugFrame(bool IsEH = false, uint64_t EHFrameAddress = 0);
     276             :   ~DWARFDebugFrame();
     277             : 
     278             :   /// Dump the section data into the given stream.
     279             :   void dump(raw_ostream &OS, const MCRegisterInfo *MRI,
     280             :             Optional<uint64_t> Offset) const;
     281             : 
     282             :   /// Parse the section from raw data. \p Data is assumed to contain the whole
     283             :   /// frame section contents to be parsed.
     284             :   void parse(DWARFDataExtractor Data);
     285             : 
     286             :   /// Return whether the section has any entries.
     287             :   bool empty() const { return Entries.empty(); }
     288             : 
     289             :   /// DWARF Frame entries accessors
     290           1 :   iterator begin() const { return Entries.begin(); }
     291           1 :   iterator end() const { return Entries.end(); }
     292             :   iterator_range<iterator> entries() const {
     293             :     return iterator_range<iterator>(Entries.begin(), Entries.end());
     294             :   }
     295             : 
     296             :   uint64_t getEHFrameAddress() const { return EHFrameAddress; }
     297             : };
     298             : 
     299             : } // end namespace llvm
     300             : 
     301             : #endif // LLVM_DEBUGINFO_DWARF_DWARFDEBUGFRAME_H

Generated by: LCOV version 1.13