xref: /freebsd/contrib/llvm-project/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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