1 //===- DWARFDebugFrame.h - Parsing of .debug_frame --------------*- 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_DWARFDEBUGFRAME_H 10 #define LLVM_DEBUGINFO_DWARF_DWARFDEBUGFRAME_H 11 12 #include "llvm/ADT/SmallString.h" 13 #include "llvm/ADT/iterator.h" 14 #include "llvm/DebugInfo/DWARF/LowLevel/DWARFCFIProgram.h" 15 #include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h" 16 #include "llvm/DebugInfo/DWARF/LowLevel/DWARFUnwindTable.h" 17 #include "llvm/Support/Compiler.h" 18 #include "llvm/Support/Error.h" 19 #include "llvm/TargetParser/Triple.h" 20 #include <memory> 21 #include <vector> 22 23 namespace llvm { 24 25 class raw_ostream; 26 class DWARFDataExtractor; 27 class MCRegisterInfo; 28 struct DIDumpOptions; 29 30 namespace dwarf { 31 32 class CIE; 33 34 /// Create an UnwindTable from a Common Information Entry (CIE). 35 /// 36 /// \param Cie The Common Information Entry to extract the table from. The 37 /// CFIProgram is retrieved from the \a Cie object and used to create the 38 /// UnwindTable. 39 /// 40 /// \returns An error if the DWARF Call Frame Information opcodes have state 41 /// machine errors, or a valid UnwindTable otherwise. 42 LLVM_ABI Expected<UnwindTable> createUnwindTable(const CIE *Cie); 43 44 class FDE; 45 46 /// Create an UnwindTable from a Frame Descriptor Entry (FDE). 47 /// 48 /// \param Fde The Frame Descriptor Entry to extract the table from. The 49 /// CFIProgram is retrieved from the \a Fde object and used to create the 50 /// UnwindTable. 51 /// 52 /// \returns An error if the DWARF Call Frame Information opcodes have state 53 /// machine errors, or a valid UnwindTable otherwise. 54 LLVM_ABI Expected<UnwindTable> createUnwindTable(const FDE *Fde); 55 56 /// An entry in either debug_frame or eh_frame. This entry can be a CIE or an 57 /// FDE. 58 class FrameEntry { 59 public: 60 enum FrameKind { FK_CIE, FK_FDE }; 61 FrameEntry(FrameKind K,bool IsDWARF64,uint64_t Offset,uint64_t Length,uint64_t CodeAlign,int64_t DataAlign,Triple::ArchType Arch)62 FrameEntry(FrameKind K, bool IsDWARF64, uint64_t Offset, uint64_t Length, 63 uint64_t CodeAlign, int64_t DataAlign, Triple::ArchType Arch) 64 : Kind(K), IsDWARF64(IsDWARF64), Offset(Offset), Length(Length), 65 CFIs(CodeAlign, DataAlign, Arch) {} 66 67 virtual ~FrameEntry() = default; 68 getKind()69 FrameKind getKind() const { return Kind; } getOffset()70 uint64_t getOffset() const { return Offset; } getLength()71 uint64_t getLength() const { return Length; } cfis()72 const CFIProgram &cfis() const { return CFIs; } cfis()73 CFIProgram &cfis() { return CFIs; } 74 75 /// Dump the instructions in this CFI fragment 76 virtual void dump(raw_ostream &OS, DIDumpOptions DumpOpts) const = 0; 77 78 protected: 79 const FrameKind Kind; 80 81 const bool IsDWARF64; 82 83 /// Offset of this entry in the section. 84 const uint64_t Offset; 85 86 /// Entry length as specified in DWARF. 87 const uint64_t Length; 88 89 CFIProgram CFIs; 90 }; 91 92 /// DWARF Common Information Entry (CIE) 93 class LLVM_ABI CIE : public FrameEntry { 94 public: 95 // CIEs (and FDEs) are simply container classes, so the only sensible way to 96 // create them is by providing the full parsed contents in the constructor. CIE(bool IsDWARF64,uint64_t Offset,uint64_t Length,uint8_t Version,SmallString<8> Augmentation,uint8_t AddressSize,uint8_t SegmentDescriptorSize,uint64_t CodeAlignmentFactor,int64_t DataAlignmentFactor,uint64_t ReturnAddressRegister,SmallString<8> AugmentationData,uint32_t FDEPointerEncoding,uint32_t LSDAPointerEncoding,std::optional<uint64_t> Personality,std::optional<uint32_t> PersonalityEnc,Triple::ArchType Arch)97 CIE(bool IsDWARF64, uint64_t Offset, uint64_t Length, uint8_t Version, 98 SmallString<8> Augmentation, uint8_t AddressSize, 99 uint8_t SegmentDescriptorSize, uint64_t CodeAlignmentFactor, 100 int64_t DataAlignmentFactor, uint64_t ReturnAddressRegister, 101 SmallString<8> AugmentationData, uint32_t FDEPointerEncoding, 102 uint32_t LSDAPointerEncoding, std::optional<uint64_t> Personality, 103 std::optional<uint32_t> PersonalityEnc, Triple::ArchType Arch) 104 : FrameEntry(FK_CIE, IsDWARF64, Offset, Length, CodeAlignmentFactor, 105 DataAlignmentFactor, Arch), 106 Version(Version), Augmentation(std::move(Augmentation)), 107 AddressSize(AddressSize), SegmentDescriptorSize(SegmentDescriptorSize), 108 CodeAlignmentFactor(CodeAlignmentFactor), 109 DataAlignmentFactor(DataAlignmentFactor), 110 ReturnAddressRegister(ReturnAddressRegister), 111 AugmentationData(std::move(AugmentationData)), 112 FDEPointerEncoding(FDEPointerEncoding), 113 LSDAPointerEncoding(LSDAPointerEncoding), Personality(Personality), 114 PersonalityEnc(PersonalityEnc) {} 115 classof(const FrameEntry * FE)116 static bool classof(const FrameEntry *FE) { return FE->getKind() == FK_CIE; } 117 getAugmentationString()118 StringRef getAugmentationString() const { return Augmentation; } getCodeAlignmentFactor()119 uint64_t getCodeAlignmentFactor() const { return CodeAlignmentFactor; } getDataAlignmentFactor()120 int64_t getDataAlignmentFactor() const { return DataAlignmentFactor; } getVersion()121 uint8_t getVersion() const { return Version; } getReturnAddressRegister()122 uint64_t getReturnAddressRegister() const { return ReturnAddressRegister; } getPersonalityAddress()123 std::optional<uint64_t> getPersonalityAddress() const { return Personality; } getPersonalityEncoding()124 std::optional<uint32_t> getPersonalityEncoding() const { 125 return PersonalityEnc; 126 } 127 getAugmentationData()128 StringRef getAugmentationData() const { return AugmentationData; } 129 getFDEPointerEncoding()130 uint32_t getFDEPointerEncoding() const { return FDEPointerEncoding; } 131 getLSDAPointerEncoding()132 uint32_t getLSDAPointerEncoding() const { return LSDAPointerEncoding; } 133 134 void dump(raw_ostream &OS, DIDumpOptions DumpOpts) const override; 135 136 private: 137 /// The following fields are defined in section 6.4.1 of the DWARF standard v4 138 const uint8_t Version; 139 const SmallString<8> Augmentation; 140 const uint8_t AddressSize; 141 const uint8_t SegmentDescriptorSize; 142 const uint64_t CodeAlignmentFactor; 143 const int64_t DataAlignmentFactor; 144 const uint64_t ReturnAddressRegister; 145 146 // The following are used when the CIE represents an EH frame entry. 147 const SmallString<8> AugmentationData; 148 const uint32_t FDEPointerEncoding; 149 const uint32_t LSDAPointerEncoding; 150 const std::optional<uint64_t> Personality; 151 const std::optional<uint32_t> PersonalityEnc; 152 }; 153 154 /// DWARF Frame Description Entry (FDE) 155 class LLVM_ABI FDE : public FrameEntry { 156 public: FDE(bool IsDWARF64,uint64_t Offset,uint64_t Length,uint64_t CIEPointer,uint64_t InitialLocation,uint64_t AddressRange,CIE * Cie,std::optional<uint64_t> LSDAAddress,Triple::ArchType Arch)157 FDE(bool IsDWARF64, uint64_t Offset, uint64_t Length, uint64_t CIEPointer, 158 uint64_t InitialLocation, uint64_t AddressRange, CIE *Cie, 159 std::optional<uint64_t> LSDAAddress, Triple::ArchType Arch) 160 : FrameEntry(FK_FDE, IsDWARF64, Offset, Length, 161 Cie ? Cie->getCodeAlignmentFactor() : 0, 162 Cie ? Cie->getDataAlignmentFactor() : 0, Arch), 163 CIEPointer(CIEPointer), InitialLocation(InitialLocation), 164 AddressRange(AddressRange), LinkedCIE(Cie), LSDAAddress(LSDAAddress) {} 165 166 ~FDE() override = default; 167 getLinkedCIE()168 const CIE *getLinkedCIE() const { return LinkedCIE; } getCIEPointer()169 uint64_t getCIEPointer() const { return CIEPointer; } getInitialLocation()170 uint64_t getInitialLocation() const { return InitialLocation; } getAddressRange()171 uint64_t getAddressRange() const { return AddressRange; } getLSDAAddress()172 std::optional<uint64_t> getLSDAAddress() const { return LSDAAddress; } 173 174 void dump(raw_ostream &OS, DIDumpOptions DumpOpts) const override; 175 classof(const FrameEntry * FE)176 static bool classof(const FrameEntry *FE) { return FE->getKind() == FK_FDE; } 177 178 private: 179 /// The following fields are defined in section 6.4.1 of the DWARFv3 standard. 180 /// Note that CIE pointers in EH FDEs, unlike DWARF FDEs, contain relative 181 /// offsets to the linked CIEs. See the following link for more info: 182 /// https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html 183 const uint64_t CIEPointer; 184 const uint64_t InitialLocation; 185 const uint64_t AddressRange; 186 const CIE *LinkedCIE; 187 const std::optional<uint64_t> LSDAAddress; 188 }; 189 190 } // end namespace dwarf 191 192 /// A parsed .debug_frame or .eh_frame section 193 class DWARFDebugFrame { 194 const Triple::ArchType Arch; 195 // True if this is parsing an eh_frame section. 196 const bool IsEH; 197 // Not zero for sane pointer values coming out of eh_frame 198 const uint64_t EHFrameAddress; 199 200 std::vector<std::unique_ptr<dwarf::FrameEntry>> Entries; 201 using iterator = pointee_iterator<decltype(Entries)::const_iterator>; 202 203 /// Return the entry at the given offset or nullptr. 204 dwarf::FrameEntry *getEntryAtOffset(uint64_t Offset) const; 205 206 public: 207 // If IsEH is true, assume it is a .eh_frame section. Otherwise, 208 // it is a .debug_frame section. EHFrameAddress should be different 209 // than zero for correct parsing of .eh_frame addresses when they 210 // use a PC-relative encoding. 211 LLVM_ABI DWARFDebugFrame(Triple::ArchType Arch, bool IsEH = false, 212 uint64_t EHFrameAddress = 0); 213 LLVM_ABI ~DWARFDebugFrame(); 214 215 /// Dump the section data into the given stream. 216 LLVM_ABI void dump(raw_ostream &OS, DIDumpOptions DumpOpts, 217 std::optional<uint64_t> Offset) const; 218 219 /// Parse the section from raw data. \p Data is assumed to contain the whole 220 /// frame section contents to be parsed. 221 LLVM_ABI Error parse(DWARFDataExtractor Data); 222 223 /// Return whether the section has any entries. empty()224 bool empty() const { return Entries.empty(); } 225 226 /// DWARF Frame entries accessors begin()227 iterator begin() const { return Entries.begin(); } end()228 iterator end() const { return Entries.end(); } entries()229 iterator_range<iterator> entries() const { 230 return iterator_range<iterator>(Entries.begin(), Entries.end()); 231 } 232 getEHFrameAddress()233 uint64_t getEHFrameAddress() const { return EHFrameAddress; } 234 }; 235 236 } // end namespace llvm 237 238 #endif // LLVM_DEBUGINFO_DWARF_DWARFDEBUGFRAME_H 239