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/ArrayRef.h" |
13 | #include "llvm/ADT/SmallString.h" |
14 | #include "llvm/ADT/Triple.h" |
15 | #include "llvm/ADT/iterator.h" |
16 | #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" |
17 | #include "llvm/DebugInfo/DWARF/DWARFExpression.h" |
18 | #include "llvm/Support/Error.h" |
19 | #include <map> |
20 | #include <memory> |
21 | #include <vector> |
22 | |
23 | namespace llvm { |
24 | |
25 | class raw_ostream; |
26 | |
27 | namespace dwarf { |
28 | |
29 | constexpr uint32_t InvalidRegisterNumber = UINT32_MAX; |
30 | |
31 | /// A class that represents a location for the Call Frame Address (CFA) or a |
32 | /// register. This is decoded from the DWARF Call Frame Information |
33 | /// instructions and put into an UnwindRow. |
34 | class UnwindLocation { |
35 | public: |
36 | enum Location { |
37 | /// Not specified. |
38 | Unspecified, |
39 | /// Register is not available and can't be recovered. |
40 | Undefined, |
41 | /// Register value is in the register, nothing needs to be done to unwind |
42 | /// it: |
43 | /// reg = reg |
44 | Same, |
45 | /// Register is in or at the CFA plus an offset: |
46 | /// reg = CFA + offset |
47 | /// reg = defef(CFA + offset) |
48 | CFAPlusOffset, |
49 | /// Register it in or at a register plus offset: |
50 | /// reg = reg + offset |
51 | /// reg = deref(reg + offset) |
52 | RegPlusOffset, |
53 | /// Register value is in or at a value found by evaluating a DWARF |
54 | /// expression: |
55 | /// reg = eval(dwarf_expr) |
56 | /// reg = deref(eval(dwarf_expr)) |
57 | DWARFExpr, |
58 | /// Value is a constant value contained in "Offset": |
59 | /// reg = Offset |
60 | Constant, |
61 | }; |
62 | |
63 | private: |
64 | Location Kind; /// The type of the location that describes how to unwind it. |
65 | uint32_t RegNum; /// The register number for Kind == RegPlusOffset. |
66 | int32_t Offset; /// The offset for Kind == CFAPlusOffset or RegPlusOffset. |
67 | Optional<DWARFExpression> Expr; /// The DWARF expression for Kind == |
68 | /// DWARFExpression. |
69 | bool Dereference; /// If true, the resulting location must be dereferenced |
70 | /// after the location value is computed. |
71 | |
72 | // Constructors are private to force people to use the create static |
73 | // functions. |
74 | UnwindLocation(Location K) |
75 | : Kind(K), RegNum(InvalidRegisterNumber), Offset(0), Dereference(false) {} |
76 | |
77 | UnwindLocation(Location K, uint32_t Reg, int32_t Off, bool Deref) |
78 | : Kind(K), RegNum(Reg), Offset(Off), Dereference(Deref) {} |
79 | |
80 | UnwindLocation(DWARFExpression E, bool Deref) |
81 | : Kind(DWARFExpr), RegNum(InvalidRegisterNumber), Offset(0), Expr(E), |
82 | Dereference(Deref) {} |
83 | |
84 | public: |
85 | /// Create a location whose rule is set to Unspecified. This means the |
86 | /// register value might be in the same register but it wasn't specified in |
87 | /// the unwind opcodes. |
88 | static UnwindLocation createUnspecified(); |
89 | /// Create a location where the value is undefined and not available. This can |
90 | /// happen when a register is volatile and can't be recovered. |
91 | static UnwindLocation createUndefined(); |
92 | /// Create a location where the value is known to be in the register itself. |
93 | static UnwindLocation createSame(); |
94 | /// Create a location that is in (Deref == false) or at (Deref == true) the |
95 | /// CFA plus an offset. Most registers that are spilled onto the stack use |
96 | /// this rule. The rule for the register will use this rule and specify a |
97 | /// unique offset from the CFA with \a Deref set to true. This value will be |
98 | /// relative to a CFA value which is typically defined using the register |
99 | /// plus offset location. \see createRegisterPlusOffset(...) for more |
100 | /// information. |
101 | static UnwindLocation createIsCFAPlusOffset(int32_t Off); |
102 | static UnwindLocation createAtCFAPlusOffset(int32_t Off); |
103 | /// Create a location where the saved value is in (Deref == false) or at |
104 | /// (Deref == true) a regiser plus an offset. |
105 | /// |
106 | /// The CFA is usually defined using this rule by using the stack pointer or |
107 | /// frame pointer as the register, with an offset that accounts for all |
108 | /// spilled registers and all local variables in a function, and Deref == |
109 | /// false. |
110 | static UnwindLocation createIsRegisterPlusOffset(uint32_t Reg, int32_t Off); |
111 | static UnwindLocation createAtRegisterPlusOffset(uint32_t Reg, int32_t Off); |
112 | /// Create a location whose value is the result of evaluating a DWARF |
113 | /// expression. This allows complex expressions to be evaluated in order to |
114 | /// unwind a register or CFA value. |
115 | static UnwindLocation createIsDWARFExpression(DWARFExpression Expr); |
116 | static UnwindLocation createAtDWARFExpression(DWARFExpression Expr); |
117 | static UnwindLocation createIsConstant(int32_t Value); |
118 | |
119 | Location getLocation() const { return Kind; } |
120 | uint32_t getRegister() const { return RegNum; } |
121 | int32_t getOffset() const { return Offset; } |
122 | int32_t getConstant() const { return Offset; } |
123 | /// Some opcodes will modify the CFA location's register only, so we need |
124 | /// to be able to modify the CFA register when evaluating DWARF Call Frame |
125 | /// Information opcodes. |
126 | void setRegister(uint32_t NewRegNum) { RegNum = NewRegNum; } |
127 | /// Some opcodes will modify the CFA location's offset only, so we need |
128 | /// to be able to modify the CFA register when evaluating DWARF Call Frame |
129 | /// Information opcodes. |
130 | void setOffset(int32_t NewOffset) { Offset = NewOffset; } |
131 | /// Some opcodes modify a constant value and we need to be able to update |
132 | /// the constant value (DW_CFA_GNU_window_save which is also known as |
133 | // DW_CFA_AARCH64_negate_ra_state). |
134 | void setConstant(int32_t Value) { Offset = Value; } |
135 | |
136 | Optional<DWARFExpression> getDWARFExpressionBytes() const { return Expr; } |
137 | /// Dump a location expression as text and use the register information if |
138 | /// some is provided. |
139 | /// |
140 | /// \param OS the stream to use for output. |
141 | /// |
142 | /// \param MRI register information that helps emit register names insteead |
143 | /// of raw register numbers. |
144 | /// |
145 | /// \param IsEH true if the DWARF Call Frame Information is from .eh_frame |
146 | /// instead of from .debug_frame. This is needed for register number |
147 | /// conversion because some register numbers differ between the two sections |
148 | /// for certain architectures like x86. |
149 | void dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH) const; |
150 | |
151 | bool operator==(const UnwindLocation &RHS) const; |
152 | }; |
153 | |
154 | raw_ostream &operator<<(raw_ostream &OS, const UnwindLocation &R); |
155 | |
156 | /// A class that can track all registers with locations in a UnwindRow object. |
157 | /// |
158 | /// Register locations use a map where the key is the register number and the |
159 | /// the value is a UnwindLocation. |
160 | /// |
161 | /// The register maps are put into a class so that all register locations can |
162 | /// be copied when parsing the unwind opcodes DW_CFA_remember_state and |
163 | /// DW_CFA_restore_state. |
164 | class RegisterLocations { |
165 | std::map<uint32_t, UnwindLocation> Locations; |
166 | |
167 | public: |
168 | /// Return the location for the register in \a RegNum if there is a location. |
169 | /// |
170 | /// \param RegNum the register number to find a location for. |
171 | /// |
172 | /// \returns A location if one is available for \a RegNum, or llvm::None |
173 | /// otherwise. |
174 | Optional<UnwindLocation> getRegisterLocation(uint32_t RegNum) const { |
175 | auto Pos = Locations.find(RegNum); |
176 | if (Pos == Locations.end()) |
177 | return llvm::None; |
178 | return Pos->second; |
179 | } |
180 | |
181 | /// Set the location for the register in \a RegNum to \a Location. |
182 | /// |
183 | /// \param RegNum the register number to set the location for. |
184 | /// |
185 | /// \param Location the UnwindLocation that describes how to unwind the value. |
186 | void setRegisterLocation(uint32_t RegNum, const UnwindLocation &Location) { |
187 | Locations.erase(RegNum); |
188 | Locations.insert(std::make_pair(RegNum, Location)); |
189 | } |
190 | |
191 | /// Removes any rule for the register in \a RegNum. |
192 | /// |
193 | /// \param RegNum the register number to remove the location for. |
194 | void removeRegisterLocation(uint32_t RegNum) { Locations.erase(RegNum); } |
195 | |
196 | /// Dump all registers + locations that are currently defined in this object. |
197 | /// |
198 | /// \param OS the stream to use for output. |
199 | /// |
200 | /// \param MRI register information that helps emit register names insteead |
201 | /// of raw register numbers. |
202 | /// |
203 | /// \param IsEH true if the DWARF Call Frame Information is from .eh_frame |
204 | /// instead of from .debug_frame. This is needed for register number |
205 | /// conversion because some register numbers differ between the two sections |
206 | /// for certain architectures like x86. |
207 | void dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH) const; |
208 | |
209 | /// Returns true if we have any register locations in this object. |
210 | bool hasLocations() const { return !Locations.empty(); } |
211 | |
212 | size_t size() const { return Locations.size(); } |
213 | |
214 | bool operator==(const RegisterLocations &RHS) const { |
215 | return Locations == RHS.Locations; |
216 | } |
217 | }; |
218 | |
219 | raw_ostream &operator<<(raw_ostream &OS, const RegisterLocations &RL); |
220 | |
221 | /// A class that represents a single row in the unwind table that is decoded by |
222 | /// parsing the DWARF Call Frame Information opcodes. |
223 | /// |
224 | /// The row consists of an optional address, the rule to unwind the CFA and all |
225 | /// rules to unwind any registers. If the address doesn't have a value, this |
226 | /// row represents the initial instructions for a CIE. If the address has a |
227 | /// value the UnwindRow represents a row in the UnwindTable for a FDE. The |
228 | /// address is the first address for which the CFA location and register rules |
229 | /// are valid within a function. |
230 | /// |
231 | /// UnwindRow objects are created by parsing opcodes in the DWARF Call Frame |
232 | /// Information and UnwindRow objects are lazily populated and pushed onto a |
233 | /// stack in the UnwindTable when evaluating this state machine. Accessors are |
234 | /// needed for the address, CFA value, and register locations as the opcodes |
235 | /// encode a state machine that produces a sorted array of UnwindRow objects |
236 | /// \see UnwindTable. |
237 | class UnwindRow { |
238 | /// The address will be valid when parsing the instructions in a FDE. If |
239 | /// invalid, this object represents the initial instructions of a CIE. |
240 | Optional<uint64_t> Address; ///< Address for row in FDE, invalid for CIE. |
241 | UnwindLocation CFAValue; ///< How to unwind the Call Frame Address (CFA). |
242 | RegisterLocations RegLocs; ///< How to unwind all registers in this list. |
243 | |
244 | public: |
245 | UnwindRow() : CFAValue(UnwindLocation::createUnspecified()) {} |
246 | |
247 | /// Returns true if the address is valid in this object. |
248 | bool hasAddress() const { return Address.hasValue(); } |
249 | |
250 | /// Get the address for this row. |
251 | /// |
252 | /// Clients should only call this function after verifying it has a valid |
253 | /// address with a call to \see hasAddress(). |
254 | uint64_t getAddress() const { return *Address; } |
255 | |
256 | /// Set the address for this UnwindRow. |
257 | /// |
258 | /// The address represents the first address for which the CFAValue and |
259 | /// RegLocs are valid within a function. |
260 | void setAddress(uint64_t Addr) { Address = Addr; } |
261 | |
262 | /// Offset the address for this UnwindRow. |
263 | /// |
264 | /// The address represents the first address for which the CFAValue and |
265 | /// RegLocs are valid within a function. Clients must ensure that this object |
266 | /// already has an address (\see hasAddress()) prior to calling this |
267 | /// function. |
268 | void slideAddress(uint64_t Offset) { *Address += Offset; } |
269 | UnwindLocation &getCFAValue() { return CFAValue; } |
270 | const UnwindLocation &getCFAValue() const { return CFAValue; } |
271 | RegisterLocations &getRegisterLocations() { return RegLocs; } |
272 | const RegisterLocations &getRegisterLocations() const { return RegLocs; } |
273 | |
274 | /// Dump the UnwindRow to the stream. |
275 | /// |
276 | /// \param OS the stream to use for output. |
277 | /// |
278 | /// \param MRI register information that helps emit register names insteead |
279 | /// of raw register numbers. |
280 | /// |
281 | /// \param IsEH true if the DWARF Call Frame Information is from .eh_frame |
282 | /// instead of from .debug_frame. This is needed for register number |
283 | /// conversion because some register numbers differ between the two sections |
284 | /// for certain architectures like x86. |
285 | /// |
286 | /// \param IndentLevel specify the indent level as an integer. The UnwindRow |
287 | /// will be output to the stream preceded by 2 * IndentLevel number of spaces. |
288 | void dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH, |
289 | unsigned IndentLevel = 0) const; |
290 | }; |
291 | |
292 | raw_ostream &operator<<(raw_ostream &OS, const UnwindRow &Row); |
293 | |
294 | class CFIProgram; |
295 | class CIE; |
296 | class FDE; |
297 | |
298 | /// A class that contains all UnwindRow objects for an FDE or a single unwind |
299 | /// row for a CIE. To unwind an address the rows, which are sorted by start |
300 | /// address, can be searched to find the UnwindRow with the lowest starting |
301 | /// address that is greater than or equal to the address that is being looked |
302 | /// up. |
303 | class UnwindTable { |
304 | public: |
305 | using RowContainer = std::vector<UnwindRow>; |
306 | using iterator = RowContainer::iterator; |
307 | using const_iterator = RowContainer::const_iterator; |
308 | |
309 | size_t size() const { return Rows.size(); } |
310 | iterator begin() { return Rows.begin(); } |
311 | const_iterator begin() const { return Rows.begin(); } |
312 | iterator end() { return Rows.end(); } |
313 | const_iterator end() const { return Rows.end(); } |
314 | const UnwindRow &operator[](size_t Index) const { |
315 | assert(Index < size()); |
316 | return Rows[Index]; |
317 | } |
318 | |
319 | /// Dump the UnwindTable to the stream. |
320 | /// |
321 | /// \param OS the stream to use for output. |
322 | /// |
323 | /// \param MRI register information that helps emit register names insteead |
324 | /// of raw register numbers. |
325 | /// |
326 | /// \param IsEH true if the DWARF Call Frame Information is from .eh_frame |
327 | /// instead of from .debug_frame. This is needed for register number |
328 | /// conversion because some register numbers differ between the two sections |
329 | /// for certain architectures like x86. |
330 | /// |
331 | /// \param IndentLevel specify the indent level as an integer. The UnwindRow |
332 | /// will be output to the stream preceded by 2 * IndentLevel number of spaces. |
333 | void dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH, |
334 | unsigned IndentLevel = 0) const; |
335 | |
336 | /// Create an UnwindTable from a Common Information Entry (CIE). |
337 | /// |
338 | /// \param Cie The Common Information Entry to extract the table from. The |
339 | /// CFIProgram is retrieved from the \a Cie object and used to create the |
340 | /// UnwindTable. |
341 | /// |
342 | /// \returns An error if the DWARF Call Frame Information opcodes have state |
343 | /// machine errors, or a valid UnwindTable otherwise. |
344 | static Expected<UnwindTable> create(const CIE *Cie); |
345 | |
346 | /// Create an UnwindTable from a Frame Descriptor Entry (FDE). |
347 | /// |
348 | /// \param Fde The Frame Descriptor Entry to extract the table from. The |
349 | /// CFIProgram is retrieved from the \a Fde object and used to create the |
350 | /// UnwindTable. |
351 | /// |
352 | /// \returns An error if the DWARF Call Frame Information opcodes have state |
353 | /// machine errors, or a valid UnwindTable otherwise. |
354 | static Expected<UnwindTable> create(const FDE *Fde); |
355 | |
356 | private: |
357 | RowContainer Rows; |
358 | /// The end address when data is extracted from a FDE. This value will be |
359 | /// invalid when a UnwindTable is extracted from a CIE. |
360 | Optional<uint64_t> EndAddress; |
361 | |
362 | /// Parse the information in the CFIProgram and update the CurrRow object |
363 | /// that the state machine describes. |
364 | /// |
365 | /// This is an internal implementation that emulates the state machine |
366 | /// described in the DWARF Call Frame Information opcodes and will push |
367 | /// CurrRow onto the Rows container when needed. |
368 | /// |
369 | /// \param CFIP the CFI program that contains the opcodes from a CIE or FDE. |
370 | /// |
371 | /// \param CurrRow the current row to modify while parsing the state machine. |
372 | /// |
373 | /// \param InitialLocs If non-NULL, we are parsing a FDE and this contains |
374 | /// the initial register locations from the CIE. If NULL, then a CIE's |
375 | /// opcodes are being parsed and this is not needed. This is used for the |
376 | /// DW_CFA_restore and DW_CFA_restore_extended opcodes. |
377 | Error parseRows(const CFIProgram &CFIP, UnwindRow &CurrRow, |
378 | const RegisterLocations *InitialLocs); |
379 | }; |
380 | |
381 | raw_ostream &operator<<(raw_ostream &OS, const UnwindTable &Rows); |
382 | |
383 | /// Represent a sequence of Call Frame Information instructions that, when read |
384 | /// in order, construct a table mapping PC to frame state. This can also be |
385 | /// referred to as "CFI rules" in DWARF literature to avoid confusion with |
386 | /// computer programs in the broader sense, and in this context each instruction |
387 | /// would be a rule to establish the mapping. Refer to pg. 172 in the DWARF5 |
388 | /// manual, "6.4.1 Structure of Call Frame Information". |
389 | class CFIProgram { |
390 | public: |
391 | typedef SmallVector<uint64_t, 2> Operands; |
392 | |
393 | /// An instruction consists of a DWARF CFI opcode and an optional sequence of |
394 | /// operands. If it refers to an expression, then this expression has its own |
395 | /// sequence of operations and operands handled separately by DWARFExpression. |
396 | struct Instruction { |
397 | Instruction(uint8_t Opcode) : Opcode(Opcode) {} |
398 | |
399 | uint8_t Opcode; |
400 | Operands Ops; |
401 | // Associated DWARF expression in case this instruction refers to one |
402 | Optional<DWARFExpression> Expression; |
403 | |
404 | Expected<uint64_t> getOperandAsUnsigned(const CFIProgram &CFIP, |
405 | uint32_t OperandIdx) const; |
406 | |
407 | Expected<int64_t> getOperandAsSigned(const CFIProgram &CFIP, |
408 | uint32_t OperandIdx) const; |
409 | }; |
410 | |
411 | using InstrList = std::vector<Instruction>; |
412 | using iterator = InstrList::iterator; |
413 | using const_iterator = InstrList::const_iterator; |
414 | |
415 | iterator begin() { return Instructions.begin(); } |
416 | const_iterator begin() const { return Instructions.begin(); } |
417 | iterator end() { return Instructions.end(); } |
418 | const_iterator end() const { return Instructions.end(); } |
419 | |
420 | unsigned size() const { return (unsigned)Instructions.size(); } |
421 | bool empty() const { return Instructions.empty(); } |
422 | uint64_t codeAlign() const { return CodeAlignmentFactor; } |
423 | int64_t dataAlign() const { return DataAlignmentFactor; } |
424 | Triple::ArchType triple() const { return Arch; } |
425 | |
426 | CFIProgram(uint64_t CodeAlignmentFactor, int64_t DataAlignmentFactor, |
427 | Triple::ArchType Arch) |
428 | : CodeAlignmentFactor(CodeAlignmentFactor), |
429 | DataAlignmentFactor(DataAlignmentFactor), |
430 | Arch(Arch) {} |
431 | |
432 | /// Parse and store a sequence of CFI instructions from Data, |
433 | /// starting at *Offset and ending at EndOffset. *Offset is updated |
434 | /// to EndOffset upon successful parsing, or indicates the offset |
435 | /// where a problem occurred in case an error is returned. |
436 | Error (DWARFDataExtractor Data, uint64_t *Offset, uint64_t EndOffset); |
437 | |
438 | void dump(raw_ostream &OS, DIDumpOptions DumpOpts, const MCRegisterInfo *MRI, |
439 | bool IsEH, unsigned IndentLevel = 1) const; |
440 | |
441 | void addInstruction(const Instruction &I) { Instructions.push_back(I); } |
442 | |
443 | /// Get a DWARF CFI call frame string for the given DW_CFA opcode. |
444 | StringRef callFrameString(unsigned Opcode) const; |
445 | |
446 | private: |
447 | std::vector<Instruction> Instructions; |
448 | const uint64_t CodeAlignmentFactor; |
449 | const int64_t DataAlignmentFactor; |
450 | Triple::ArchType Arch; |
451 | |
452 | /// Convenience method to add a new instruction with the given opcode. |
453 | void addInstruction(uint8_t Opcode) { |
454 | Instructions.push_back(Instruction(Opcode)); |
455 | } |
456 | |
457 | /// Add a new single-operand instruction. |
458 | void addInstruction(uint8_t Opcode, uint64_t Operand1) { |
459 | Instructions.push_back(Instruction(Opcode)); |
460 | Instructions.back().Ops.push_back(Operand1); |
461 | } |
462 | |
463 | /// Add a new instruction that has two operands. |
464 | void addInstruction(uint8_t Opcode, uint64_t Operand1, uint64_t Operand2) { |
465 | Instructions.push_back(Instruction(Opcode)); |
466 | Instructions.back().Ops.push_back(Operand1); |
467 | Instructions.back().Ops.push_back(Operand2); |
468 | } |
469 | |
470 | /// Types of operands to CFI instructions |
471 | /// In DWARF, this type is implicitly tied to a CFI instruction opcode and |
472 | /// thus this type doesn't need to be explictly written to the file (this is |
473 | /// not a DWARF encoding). The relationship of instrs to operand types can |
474 | /// be obtained from getOperandTypes() and is only used to simplify |
475 | /// instruction printing. |
476 | enum OperandType { |
477 | OT_Unset, |
478 | OT_None, |
479 | OT_Address, |
480 | OT_Offset, |
481 | OT_FactoredCodeOffset, |
482 | OT_SignedFactDataOffset, |
483 | OT_UnsignedFactDataOffset, |
484 | OT_Register, |
485 | OT_Expression |
486 | }; |
487 | |
488 | /// Get the OperandType as a "const char *". |
489 | static const char *operandTypeString(OperandType OT); |
490 | |
491 | /// Retrieve the array describing the types of operands according to the enum |
492 | /// above. This is indexed by opcode. |
493 | static ArrayRef<OperandType[2]> getOperandTypes(); |
494 | |
495 | /// Print \p Opcode's operand number \p OperandIdx which has value \p Operand. |
496 | void printOperand(raw_ostream &OS, DIDumpOptions DumpOpts, |
497 | const MCRegisterInfo *MRI, bool IsEH, |
498 | const Instruction &Instr, unsigned OperandIdx, |
499 | uint64_t Operand) const; |
500 | }; |
501 | |
502 | /// An entry in either debug_frame or eh_frame. This entry can be a CIE or an |
503 | /// FDE. |
504 | class FrameEntry { |
505 | public: |
506 | enum FrameKind { FK_CIE, FK_FDE }; |
507 | |
508 | FrameEntry(FrameKind K, bool IsDWARF64, uint64_t Offset, uint64_t Length, |
509 | uint64_t CodeAlign, int64_t DataAlign, Triple::ArchType Arch) |
510 | : Kind(K), IsDWARF64(IsDWARF64), Offset(Offset), Length(Length), |
511 | CFIs(CodeAlign, DataAlign, Arch) {} |
512 | |
513 | virtual ~FrameEntry() {} |
514 | |
515 | FrameKind getKind() const { return Kind; } |
516 | uint64_t getOffset() const { return Offset; } |
517 | uint64_t getLength() const { return Length; } |
518 | const CFIProgram &cfis() const { return CFIs; } |
519 | CFIProgram &cfis() { return CFIs; } |
520 | |
521 | /// Dump the instructions in this CFI fragment |
522 | virtual void dump(raw_ostream &OS, DIDumpOptions DumpOpts, |
523 | const MCRegisterInfo *MRI, bool IsEH) const = 0; |
524 | |
525 | protected: |
526 | const FrameKind Kind; |
527 | |
528 | const bool IsDWARF64; |
529 | |
530 | /// Offset of this entry in the section. |
531 | const uint64_t Offset; |
532 | |
533 | /// Entry length as specified in DWARF. |
534 | const uint64_t Length; |
535 | |
536 | CFIProgram CFIs; |
537 | }; |
538 | |
539 | /// DWARF Common Information Entry (CIE) |
540 | class CIE : public FrameEntry { |
541 | public: |
542 | // CIEs (and FDEs) are simply container classes, so the only sensible way to |
543 | // create them is by providing the full parsed contents in the constructor. |
544 | CIE(bool IsDWARF64, uint64_t Offset, uint64_t Length, uint8_t Version, |
545 | SmallString<8> Augmentation, uint8_t AddressSize, |
546 | uint8_t SegmentDescriptorSize, uint64_t CodeAlignmentFactor, |
547 | int64_t DataAlignmentFactor, uint64_t ReturnAddressRegister, |
548 | SmallString<8> AugmentationData, uint32_t FDEPointerEncoding, |
549 | uint32_t LSDAPointerEncoding, Optional<uint64_t> Personality, |
550 | Optional<uint32_t> PersonalityEnc, Triple::ArchType Arch) |
551 | : FrameEntry(FK_CIE, IsDWARF64, Offset, Length, CodeAlignmentFactor, |
552 | DataAlignmentFactor, Arch), |
553 | Version(Version), Augmentation(std::move(Augmentation)), |
554 | AddressSize(AddressSize), SegmentDescriptorSize(SegmentDescriptorSize), |
555 | CodeAlignmentFactor(CodeAlignmentFactor), |
556 | DataAlignmentFactor(DataAlignmentFactor), |
557 | ReturnAddressRegister(ReturnAddressRegister), |
558 | AugmentationData(std::move(AugmentationData)), |
559 | FDEPointerEncoding(FDEPointerEncoding), |
560 | LSDAPointerEncoding(LSDAPointerEncoding), Personality(Personality), |
561 | PersonalityEnc(PersonalityEnc) {} |
562 | |
563 | static bool classof(const FrameEntry *FE) { return FE->getKind() == FK_CIE; } |
564 | |
565 | StringRef getAugmentationString() const { return Augmentation; } |
566 | uint64_t getCodeAlignmentFactor() const { return CodeAlignmentFactor; } |
567 | int64_t getDataAlignmentFactor() const { return DataAlignmentFactor; } |
568 | uint8_t getVersion() const { return Version; } |
569 | uint64_t getReturnAddressRegister() const { return ReturnAddressRegister; } |
570 | Optional<uint64_t> getPersonalityAddress() const { return Personality; } |
571 | Optional<uint32_t> getPersonalityEncoding() const { return PersonalityEnc; } |
572 | |
573 | uint32_t getFDEPointerEncoding() const { return FDEPointerEncoding; } |
574 | |
575 | uint32_t getLSDAPointerEncoding() const { return LSDAPointerEncoding; } |
576 | |
577 | void dump(raw_ostream &OS, DIDumpOptions DumpOpts, const MCRegisterInfo *MRI, |
578 | bool IsEH) const override; |
579 | |
580 | private: |
581 | /// The following fields are defined in section 6.4.1 of the DWARF standard v4 |
582 | const uint8_t Version; |
583 | const SmallString<8> Augmentation; |
584 | const uint8_t AddressSize; |
585 | const uint8_t SegmentDescriptorSize; |
586 | const uint64_t CodeAlignmentFactor; |
587 | const int64_t DataAlignmentFactor; |
588 | const uint64_t ReturnAddressRegister; |
589 | |
590 | // The following are used when the CIE represents an EH frame entry. |
591 | const SmallString<8> AugmentationData; |
592 | const uint32_t FDEPointerEncoding; |
593 | const uint32_t LSDAPointerEncoding; |
594 | const Optional<uint64_t> Personality; |
595 | const Optional<uint32_t> PersonalityEnc; |
596 | }; |
597 | |
598 | /// DWARF Frame Description Entry (FDE) |
599 | class FDE : public FrameEntry { |
600 | public: |
601 | FDE(bool IsDWARF64, uint64_t Offset, uint64_t Length, uint64_t CIEPointer, |
602 | uint64_t InitialLocation, uint64_t AddressRange, CIE *Cie, |
603 | Optional<uint64_t> LSDAAddress, Triple::ArchType Arch) |
604 | : FrameEntry(FK_FDE, IsDWARF64, Offset, Length, |
605 | Cie ? Cie->getCodeAlignmentFactor() : 0, |
606 | Cie ? Cie->getDataAlignmentFactor() : 0, |
607 | Arch), |
608 | CIEPointer(CIEPointer), InitialLocation(InitialLocation), |
609 | AddressRange(AddressRange), LinkedCIE(Cie), LSDAAddress(LSDAAddress) {} |
610 | |
611 | ~FDE() override = default; |
612 | |
613 | const CIE *getLinkedCIE() const { return LinkedCIE; } |
614 | uint64_t getInitialLocation() const { return InitialLocation; } |
615 | uint64_t getAddressRange() const { return AddressRange; } |
616 | Optional<uint64_t> getLSDAAddress() const { return LSDAAddress; } |
617 | |
618 | void dump(raw_ostream &OS, DIDumpOptions DumpOpts, const MCRegisterInfo *MRI, |
619 | bool IsEH) const override; |
620 | |
621 | static bool classof(const FrameEntry *FE) { return FE->getKind() == FK_FDE; } |
622 | |
623 | private: |
624 | /// The following fields are defined in section 6.4.1 of the DWARFv3 standard. |
625 | /// Note that CIE pointers in EH FDEs, unlike DWARF FDEs, contain relative |
626 | /// offsets to the linked CIEs. See the following link for more info: |
627 | /// https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html |
628 | const uint64_t CIEPointer; |
629 | const uint64_t InitialLocation; |
630 | const uint64_t AddressRange; |
631 | const CIE *LinkedCIE; |
632 | const Optional<uint64_t> LSDAAddress; |
633 | }; |
634 | |
635 | } // end namespace dwarf |
636 | |
637 | /// A parsed .debug_frame or .eh_frame section |
638 | class DWARFDebugFrame { |
639 | const Triple::ArchType Arch; |
640 | // True if this is parsing an eh_frame section. |
641 | const bool IsEH; |
642 | // Not zero for sane pointer values coming out of eh_frame |
643 | const uint64_t EHFrameAddress; |
644 | |
645 | std::vector<std::unique_ptr<dwarf::FrameEntry>> Entries; |
646 | using iterator = pointee_iterator<decltype(Entries)::const_iterator>; |
647 | |
648 | /// Return the entry at the given offset or nullptr. |
649 | dwarf::FrameEntry *getEntryAtOffset(uint64_t Offset) const; |
650 | |
651 | public: |
652 | // If IsEH is true, assume it is a .eh_frame section. Otherwise, |
653 | // it is a .debug_frame section. EHFrameAddress should be different |
654 | // than zero for correct parsing of .eh_frame addresses when they |
655 | // use a PC-relative encoding. |
656 | DWARFDebugFrame(Triple::ArchType Arch, |
657 | bool IsEH = false, uint64_t EHFrameAddress = 0); |
658 | ~DWARFDebugFrame(); |
659 | |
660 | /// Dump the section data into the given stream. |
661 | void dump(raw_ostream &OS, DIDumpOptions DumpOpts, const MCRegisterInfo *MRI, |
662 | Optional<uint64_t> Offset) const; |
663 | |
664 | /// Parse the section from raw data. \p Data is assumed to contain the whole |
665 | /// frame section contents to be parsed. |
666 | Error (DWARFDataExtractor Data); |
667 | |
668 | /// Return whether the section has any entries. |
669 | bool empty() const { return Entries.empty(); } |
670 | |
671 | /// DWARF Frame entries accessors |
672 | iterator begin() const { return Entries.begin(); } |
673 | iterator end() const { return Entries.end(); } |
674 | iterator_range<iterator> entries() const { |
675 | return iterator_range<iterator>(Entries.begin(), Entries.end()); |
676 | } |
677 | |
678 | uint64_t getEHFrameAddress() const { return EHFrameAddress; } |
679 | }; |
680 | |
681 | } // end namespace llvm |
682 | |
683 | #endif // LLVM_DEBUGINFO_DWARF_DWARFDEBUGFRAME_H |
684 | |