Details | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 14 | pmbaty | 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/DWARFExpression.h" |
||
| 17 | #include "llvm/Support/Error.h" |
||
| 18 | #include <map> |
||
| 19 | #include <memory> |
||
| 20 | #include <vector> |
||
| 21 | |||
| 22 | namespace llvm { |
||
| 23 | |||
| 24 | class raw_ostream; |
||
| 25 | class DWARFDataExtractor; |
||
| 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(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(RegNum); |
||
| 206 | Locations.insert(std::make_pair(RegNum, 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(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 parse(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(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(Instruction(Opcode)); |
||
| 474 | } |
||
| 475 | |||
| 476 | /// Add a new single-operand instruction. |
||
| 477 | void addInstruction(uint8_t Opcode, uint64_t Operand1) { |
||
| 478 | Instructions.push_back(Instruction(Opcode)); |
||
| 479 | Instructions.back().Ops.push_back(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(Instruction(Opcode)); |
||
| 485 | Instructions.back().Ops.push_back(Operand1); |
||
| 486 | Instructions.back().Ops.push_back(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(Instruction(Opcode)); |
||
| 493 | Instructions.back().Ops.push_back(Operand1); |
||
| 494 | Instructions.back().Ops.push_back(Operand2); |
||
| 495 | Instructions.back().Ops.push_back(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 parse(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 |