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