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