10b57cec5SDimitry Andric //===- DWARFDebugFrame.h - Parsing of .debug_frame --------------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #ifndef LLVM_DEBUGINFO_DWARF_DWARFDEBUGFRAME_H 100b57cec5SDimitry Andric #define LLVM_DEBUGINFO_DWARF_DWARFDEBUGFRAME_H 110b57cec5SDimitry Andric 120b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h" 130b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h" 14fe6060f1SDimitry Andric #include "llvm/ADT/iterator.h" 150b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFExpression.h" 160b57cec5SDimitry Andric #include "llvm/Support/Error.h" 1706c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h" 18fe6060f1SDimitry Andric #include <map> 190b57cec5SDimitry Andric #include <memory> 200b57cec5SDimitry Andric #include <vector> 210b57cec5SDimitry Andric 220b57cec5SDimitry Andric namespace llvm { 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric class raw_ostream; 2581ad6265SDimitry Andric class DWARFDataExtractor; 2681ad6265SDimitry Andric class MCRegisterInfo; 2781ad6265SDimitry Andric struct DIDumpOptions; 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric namespace dwarf { 300b57cec5SDimitry Andric 31fe6060f1SDimitry Andric constexpr uint32_t InvalidRegisterNumber = UINT32_MAX; 32fe6060f1SDimitry Andric 33fe6060f1SDimitry Andric /// A class that represents a location for the Call Frame Address (CFA) or a 34fe6060f1SDimitry Andric /// register. This is decoded from the DWARF Call Frame Information 35fe6060f1SDimitry Andric /// instructions and put into an UnwindRow. 36fe6060f1SDimitry Andric class UnwindLocation { 37fe6060f1SDimitry Andric public: 38fe6060f1SDimitry Andric enum Location { 39fe6060f1SDimitry Andric /// Not specified. 40fe6060f1SDimitry Andric Unspecified, 41fe6060f1SDimitry Andric /// Register is not available and can't be recovered. 42fe6060f1SDimitry Andric Undefined, 43fe6060f1SDimitry Andric /// Register value is in the register, nothing needs to be done to unwind 44fe6060f1SDimitry Andric /// it: 45fe6060f1SDimitry Andric /// reg = reg 46fe6060f1SDimitry Andric Same, 47fe6060f1SDimitry Andric /// Register is in or at the CFA plus an offset: 48fe6060f1SDimitry Andric /// reg = CFA + offset 49fe6060f1SDimitry Andric /// reg = defef(CFA + offset) 50fe6060f1SDimitry Andric CFAPlusOffset, 51fe6060f1SDimitry Andric /// Register or CFA is in or at a register plus offset, optionally in 52fe6060f1SDimitry Andric /// an address space: 53fe6060f1SDimitry Andric /// reg = reg + offset [in addrspace] 54fe6060f1SDimitry Andric /// reg = deref(reg + offset [in addrspace]) 55fe6060f1SDimitry Andric RegPlusOffset, 56fe6060f1SDimitry Andric /// Register or CFA value is in or at a value found by evaluating a DWARF 57fe6060f1SDimitry Andric /// expression: 58fe6060f1SDimitry Andric /// reg = eval(dwarf_expr) 59fe6060f1SDimitry Andric /// reg = deref(eval(dwarf_expr)) 60fe6060f1SDimitry Andric DWARFExpr, 61fe6060f1SDimitry Andric /// Value is a constant value contained in "Offset": 62fe6060f1SDimitry Andric /// reg = Offset 63fe6060f1SDimitry Andric Constant, 64fe6060f1SDimitry Andric }; 65fe6060f1SDimitry Andric 66fe6060f1SDimitry Andric private: 67fe6060f1SDimitry Andric Location Kind; /// The type of the location that describes how to unwind it. 68fe6060f1SDimitry Andric uint32_t RegNum; /// The register number for Kind == RegPlusOffset. 69fe6060f1SDimitry Andric int32_t Offset; /// The offset for Kind == CFAPlusOffset or RegPlusOffset. 70bdd1243dSDimitry Andric std::optional<uint32_t> AddrSpace; /// The address space for Kind == 71bdd1243dSDimitry Andric /// RegPlusOffset for CFA. 72bdd1243dSDimitry Andric std::optional<DWARFExpression> Expr; /// The DWARF expression for Kind == 73fe6060f1SDimitry Andric /// DWARFExpression. 74fe6060f1SDimitry Andric bool Dereference; /// If true, the resulting location must be dereferenced 75fe6060f1SDimitry Andric /// after the location value is computed. 76fe6060f1SDimitry Andric 77fe6060f1SDimitry Andric // Constructors are private to force people to use the create static 78fe6060f1SDimitry Andric // functions. UnwindLocation(Location K)79fe6060f1SDimitry Andric UnwindLocation(Location K) 80bdd1243dSDimitry Andric : Kind(K), RegNum(InvalidRegisterNumber), Offset(0), 81bdd1243dSDimitry Andric AddrSpace(std::nullopt), Dereference(false) {} 82fe6060f1SDimitry Andric UnwindLocation(Location K,uint32_t Reg,int32_t Off,std::optional<uint32_t> AS,bool Deref)83bdd1243dSDimitry Andric UnwindLocation(Location K, uint32_t Reg, int32_t Off, 84bdd1243dSDimitry Andric std::optional<uint32_t> AS, bool Deref) 85fe6060f1SDimitry Andric : Kind(K), RegNum(Reg), Offset(Off), AddrSpace(AS), Dereference(Deref) {} 86fe6060f1SDimitry Andric UnwindLocation(DWARFExpression E,bool Deref)87fe6060f1SDimitry Andric UnwindLocation(DWARFExpression E, bool Deref) 88fe6060f1SDimitry Andric : Kind(DWARFExpr), RegNum(InvalidRegisterNumber), Offset(0), Expr(E), 89fe6060f1SDimitry Andric Dereference(Deref) {} 90fe6060f1SDimitry Andric 91fe6060f1SDimitry Andric public: 92fe6060f1SDimitry Andric /// Create a location whose rule is set to Unspecified. This means the 93fe6060f1SDimitry Andric /// register value might be in the same register but it wasn't specified in 94fe6060f1SDimitry Andric /// the unwind opcodes. 95fe6060f1SDimitry Andric static UnwindLocation createUnspecified(); 96fe6060f1SDimitry Andric /// Create a location where the value is undefined and not available. This can 97fe6060f1SDimitry Andric /// happen when a register is volatile and can't be recovered. 98fe6060f1SDimitry Andric static UnwindLocation createUndefined(); 99fe6060f1SDimitry Andric /// Create a location where the value is known to be in the register itself. 100fe6060f1SDimitry Andric static UnwindLocation createSame(); 101fe6060f1SDimitry Andric /// Create a location that is in (Deref == false) or at (Deref == true) the 102fe6060f1SDimitry Andric /// CFA plus an offset. Most registers that are spilled onto the stack use 103fe6060f1SDimitry Andric /// this rule. The rule for the register will use this rule and specify a 104fe6060f1SDimitry Andric /// unique offset from the CFA with \a Deref set to true. This value will be 105fe6060f1SDimitry Andric /// relative to a CFA value which is typically defined using the register 106fe6060f1SDimitry Andric /// plus offset location. \see createRegisterPlusOffset(...) for more 107fe6060f1SDimitry Andric /// information. 108fe6060f1SDimitry Andric static UnwindLocation createIsCFAPlusOffset(int32_t Off); 109fe6060f1SDimitry Andric static UnwindLocation createAtCFAPlusOffset(int32_t Off); 110fe6060f1SDimitry Andric /// Create a location where the saved value is in (Deref == false) or at 111fe6060f1SDimitry Andric /// (Deref == true) a regiser plus an offset and, optionally, in the specified 112fe6060f1SDimitry Andric /// address space (used mostly for the CFA). 113fe6060f1SDimitry Andric /// 114fe6060f1SDimitry Andric /// The CFA is usually defined using this rule by using the stack pointer or 115fe6060f1SDimitry Andric /// frame pointer as the register, with an offset that accounts for all 116fe6060f1SDimitry Andric /// spilled registers and all local variables in a function, and Deref == 117fe6060f1SDimitry Andric /// false. 118fe6060f1SDimitry Andric static UnwindLocation 119fe6060f1SDimitry Andric createIsRegisterPlusOffset(uint32_t Reg, int32_t Off, 120bdd1243dSDimitry Andric std::optional<uint32_t> AddrSpace = std::nullopt); 121fe6060f1SDimitry Andric static UnwindLocation 122fe6060f1SDimitry Andric createAtRegisterPlusOffset(uint32_t Reg, int32_t Off, 123bdd1243dSDimitry Andric std::optional<uint32_t> AddrSpace = std::nullopt); 124fe6060f1SDimitry Andric /// Create a location whose value is the result of evaluating a DWARF 125fe6060f1SDimitry Andric /// expression. This allows complex expressions to be evaluated in order to 126fe6060f1SDimitry Andric /// unwind a register or CFA value. 127fe6060f1SDimitry Andric static UnwindLocation createIsDWARFExpression(DWARFExpression Expr); 128fe6060f1SDimitry Andric static UnwindLocation createAtDWARFExpression(DWARFExpression Expr); 129fe6060f1SDimitry Andric static UnwindLocation createIsConstant(int32_t Value); 130fe6060f1SDimitry Andric getLocation()131fe6060f1SDimitry Andric Location getLocation() const { return Kind; } getRegister()132fe6060f1SDimitry Andric uint32_t getRegister() const { return RegNum; } getOffset()133fe6060f1SDimitry Andric int32_t getOffset() const { return Offset; } getAddressSpace()134fe6060f1SDimitry Andric uint32_t getAddressSpace() const { 13581ad6265SDimitry Andric assert(Kind == RegPlusOffset && AddrSpace); 136fe6060f1SDimitry Andric return *AddrSpace; 137fe6060f1SDimitry Andric } getConstant()138fe6060f1SDimitry Andric int32_t getConstant() const { return Offset; } 139fe6060f1SDimitry Andric /// Some opcodes will modify the CFA location's register only, so we need 140fe6060f1SDimitry Andric /// to be able to modify the CFA register when evaluating DWARF Call Frame 141fe6060f1SDimitry Andric /// Information opcodes. setRegister(uint32_t NewRegNum)142fe6060f1SDimitry Andric void setRegister(uint32_t NewRegNum) { RegNum = NewRegNum; } 143fe6060f1SDimitry Andric /// Some opcodes will modify the CFA location's offset only, so we need 144fe6060f1SDimitry Andric /// to be able to modify the CFA offset when evaluating DWARF Call Frame 145fe6060f1SDimitry Andric /// Information opcodes. setOffset(int32_t NewOffset)146fe6060f1SDimitry Andric void setOffset(int32_t NewOffset) { Offset = NewOffset; } 147fe6060f1SDimitry Andric /// Some opcodes modify a constant value and we need to be able to update 148fe6060f1SDimitry Andric /// the constant value (DW_CFA_GNU_window_save which is also known as 149fe6060f1SDimitry Andric // DW_CFA_AARCH64_negate_ra_state). setConstant(int32_t Value)150fe6060f1SDimitry Andric void setConstant(int32_t Value) { Offset = Value; } 151fe6060f1SDimitry Andric getDWARFExpressionBytes()152bdd1243dSDimitry Andric std::optional<DWARFExpression> getDWARFExpressionBytes() const { 153bdd1243dSDimitry Andric return Expr; 154bdd1243dSDimitry Andric } 155fe6060f1SDimitry Andric /// Dump a location expression as text and use the register information if 156fe6060f1SDimitry Andric /// some is provided. 157fe6060f1SDimitry Andric /// 158fe6060f1SDimitry Andric /// \param OS the stream to use for output. 159fe6060f1SDimitry Andric /// 160fe6060f1SDimitry Andric /// \param MRI register information that helps emit register names insteead 161fe6060f1SDimitry Andric /// of raw register numbers. 162fe6060f1SDimitry Andric /// 163fe6060f1SDimitry Andric /// \param IsEH true if the DWARF Call Frame Information is from .eh_frame 164fe6060f1SDimitry Andric /// instead of from .debug_frame. This is needed for register number 165fe6060f1SDimitry Andric /// conversion because some register numbers differ between the two sections 166fe6060f1SDimitry Andric /// for certain architectures like x86. 167bdd1243dSDimitry Andric void dump(raw_ostream &OS, DIDumpOptions DumpOpts) const; 168fe6060f1SDimitry Andric 169fe6060f1SDimitry Andric bool operator==(const UnwindLocation &RHS) const; 170fe6060f1SDimitry Andric }; 171fe6060f1SDimitry Andric 172fe6060f1SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const UnwindLocation &R); 173fe6060f1SDimitry Andric 174fe6060f1SDimitry Andric /// A class that can track all registers with locations in a UnwindRow object. 175fe6060f1SDimitry Andric /// 176fe6060f1SDimitry Andric /// Register locations use a map where the key is the register number and the 177fe6060f1SDimitry Andric /// the value is a UnwindLocation. 178fe6060f1SDimitry Andric /// 179fe6060f1SDimitry Andric /// The register maps are put into a class so that all register locations can 180fe6060f1SDimitry Andric /// be copied when parsing the unwind opcodes DW_CFA_remember_state and 181fe6060f1SDimitry Andric /// DW_CFA_restore_state. 182fe6060f1SDimitry Andric class RegisterLocations { 183fe6060f1SDimitry Andric std::map<uint32_t, UnwindLocation> Locations; 184fe6060f1SDimitry Andric 185fe6060f1SDimitry Andric public: 186fe6060f1SDimitry Andric /// Return the location for the register in \a RegNum if there is a location. 187fe6060f1SDimitry Andric /// 188fe6060f1SDimitry Andric /// \param RegNum the register number to find a location for. 189fe6060f1SDimitry Andric /// 190bdd1243dSDimitry Andric /// \returns A location if one is available for \a RegNum, or std::nullopt 191fe6060f1SDimitry Andric /// otherwise. getRegisterLocation(uint32_t RegNum)192bdd1243dSDimitry Andric std::optional<UnwindLocation> getRegisterLocation(uint32_t RegNum) const { 193fe6060f1SDimitry Andric auto Pos = Locations.find(RegNum); 194fe6060f1SDimitry Andric if (Pos == Locations.end()) 195bdd1243dSDimitry Andric return std::nullopt; 196fe6060f1SDimitry Andric return Pos->second; 197fe6060f1SDimitry Andric } 198fe6060f1SDimitry Andric 199fe6060f1SDimitry Andric /// Set the location for the register in \a RegNum to \a Location. 200fe6060f1SDimitry Andric /// 201fe6060f1SDimitry Andric /// \param RegNum the register number to set the location for. 202fe6060f1SDimitry Andric /// 203fe6060f1SDimitry Andric /// \param Location the UnwindLocation that describes how to unwind the value. setRegisterLocation(uint32_t RegNum,const UnwindLocation & Location)204fe6060f1SDimitry Andric void setRegisterLocation(uint32_t RegNum, const UnwindLocation &Location) { 205fe6060f1SDimitry Andric Locations.erase(RegNum); 206fe6060f1SDimitry Andric Locations.insert(std::make_pair(RegNum, Location)); 207fe6060f1SDimitry Andric } 208fe6060f1SDimitry Andric 209fe6060f1SDimitry Andric /// Removes any rule for the register in \a RegNum. 210fe6060f1SDimitry Andric /// 211fe6060f1SDimitry Andric /// \param RegNum the register number to remove the location for. removeRegisterLocation(uint32_t RegNum)212fe6060f1SDimitry Andric void removeRegisterLocation(uint32_t RegNum) { Locations.erase(RegNum); } 213fe6060f1SDimitry Andric 214fe6060f1SDimitry Andric /// Dump all registers + locations that are currently defined in this object. 215fe6060f1SDimitry Andric /// 216fe6060f1SDimitry Andric /// \param OS the stream to use for output. 217fe6060f1SDimitry Andric /// 218fe6060f1SDimitry Andric /// \param MRI register information that helps emit register names insteead 219fe6060f1SDimitry Andric /// of raw register numbers. 220fe6060f1SDimitry Andric /// 221fe6060f1SDimitry Andric /// \param IsEH true if the DWARF Call Frame Information is from .eh_frame 222fe6060f1SDimitry Andric /// instead of from .debug_frame. This is needed for register number 223fe6060f1SDimitry Andric /// conversion because some register numbers differ between the two sections 224fe6060f1SDimitry Andric /// for certain architectures like x86. 225bdd1243dSDimitry Andric void dump(raw_ostream &OS, DIDumpOptions DumpOpts) const; 226fe6060f1SDimitry Andric 227fe6060f1SDimitry Andric /// Returns true if we have any register locations in this object. hasLocations()228fe6060f1SDimitry Andric bool hasLocations() const { return !Locations.empty(); } 229fe6060f1SDimitry Andric size()230fe6060f1SDimitry Andric size_t size() const { return Locations.size(); } 231fe6060f1SDimitry Andric 232fe6060f1SDimitry Andric bool operator==(const RegisterLocations &RHS) const { 233fe6060f1SDimitry Andric return Locations == RHS.Locations; 234fe6060f1SDimitry Andric } 235fe6060f1SDimitry Andric }; 236fe6060f1SDimitry Andric 237fe6060f1SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const RegisterLocations &RL); 238fe6060f1SDimitry Andric 239fe6060f1SDimitry Andric /// A class that represents a single row in the unwind table that is decoded by 240fe6060f1SDimitry Andric /// parsing the DWARF Call Frame Information opcodes. 241fe6060f1SDimitry Andric /// 242fe6060f1SDimitry Andric /// The row consists of an optional address, the rule to unwind the CFA and all 243fe6060f1SDimitry Andric /// rules to unwind any registers. If the address doesn't have a value, this 244fe6060f1SDimitry Andric /// row represents the initial instructions for a CIE. If the address has a 245fe6060f1SDimitry Andric /// value the UnwindRow represents a row in the UnwindTable for a FDE. The 246fe6060f1SDimitry Andric /// address is the first address for which the CFA location and register rules 247fe6060f1SDimitry Andric /// are valid within a function. 248fe6060f1SDimitry Andric /// 249fe6060f1SDimitry Andric /// UnwindRow objects are created by parsing opcodes in the DWARF Call Frame 250fe6060f1SDimitry Andric /// Information and UnwindRow objects are lazily populated and pushed onto a 251fe6060f1SDimitry Andric /// stack in the UnwindTable when evaluating this state machine. Accessors are 252fe6060f1SDimitry Andric /// needed for the address, CFA value, and register locations as the opcodes 253fe6060f1SDimitry Andric /// encode a state machine that produces a sorted array of UnwindRow objects 254fe6060f1SDimitry Andric /// \see UnwindTable. 255fe6060f1SDimitry Andric class UnwindRow { 256fe6060f1SDimitry Andric /// The address will be valid when parsing the instructions in a FDE. If 257fe6060f1SDimitry Andric /// invalid, this object represents the initial instructions of a CIE. 258bdd1243dSDimitry Andric std::optional<uint64_t> Address; ///< Address for row in FDE, invalid for CIE. 259fe6060f1SDimitry Andric UnwindLocation CFAValue; ///< How to unwind the Call Frame Address (CFA). 260fe6060f1SDimitry Andric RegisterLocations RegLocs; ///< How to unwind all registers in this list. 261fe6060f1SDimitry Andric 262fe6060f1SDimitry Andric public: UnwindRow()263fe6060f1SDimitry Andric UnwindRow() : CFAValue(UnwindLocation::createUnspecified()) {} 264fe6060f1SDimitry Andric 265fe6060f1SDimitry Andric /// Returns true if the address is valid in this object. hasAddress()26681ad6265SDimitry Andric bool hasAddress() const { return Address.has_value(); } 267fe6060f1SDimitry Andric 268fe6060f1SDimitry Andric /// Get the address for this row. 269fe6060f1SDimitry Andric /// 270fe6060f1SDimitry Andric /// Clients should only call this function after verifying it has a valid 271fe6060f1SDimitry Andric /// address with a call to \see hasAddress(). getAddress()272fe6060f1SDimitry Andric uint64_t getAddress() const { return *Address; } 273fe6060f1SDimitry Andric 274fe6060f1SDimitry Andric /// Set the address for this UnwindRow. 275fe6060f1SDimitry Andric /// 276fe6060f1SDimitry Andric /// The address represents the first address for which the CFAValue and 277fe6060f1SDimitry Andric /// RegLocs are valid within a function. setAddress(uint64_t Addr)278fe6060f1SDimitry Andric void setAddress(uint64_t Addr) { Address = Addr; } 279fe6060f1SDimitry Andric 280fe6060f1SDimitry Andric /// Offset the address for this UnwindRow. 281fe6060f1SDimitry Andric /// 282fe6060f1SDimitry Andric /// The address represents the first address for which the CFAValue and 283fe6060f1SDimitry Andric /// RegLocs are valid within a function. Clients must ensure that this object 284fe6060f1SDimitry Andric /// already has an address (\see hasAddress()) prior to calling this 285fe6060f1SDimitry Andric /// function. slideAddress(uint64_t Offset)286fe6060f1SDimitry Andric void slideAddress(uint64_t Offset) { *Address += Offset; } getCFAValue()287fe6060f1SDimitry Andric UnwindLocation &getCFAValue() { return CFAValue; } getCFAValue()288fe6060f1SDimitry Andric const UnwindLocation &getCFAValue() const { return CFAValue; } getRegisterLocations()289fe6060f1SDimitry Andric RegisterLocations &getRegisterLocations() { return RegLocs; } getRegisterLocations()290fe6060f1SDimitry Andric const RegisterLocations &getRegisterLocations() const { return RegLocs; } 291fe6060f1SDimitry Andric 292fe6060f1SDimitry Andric /// Dump the UnwindRow to the stream. 293fe6060f1SDimitry Andric /// 294fe6060f1SDimitry Andric /// \param OS the stream to use for output. 295fe6060f1SDimitry Andric /// 296fe6060f1SDimitry Andric /// \param MRI register information that helps emit register names insteead 297fe6060f1SDimitry Andric /// of raw register numbers. 298fe6060f1SDimitry Andric /// 299fe6060f1SDimitry Andric /// \param IsEH true if the DWARF Call Frame Information is from .eh_frame 300fe6060f1SDimitry Andric /// instead of from .debug_frame. This is needed for register number 301fe6060f1SDimitry Andric /// conversion because some register numbers differ between the two sections 302fe6060f1SDimitry Andric /// for certain architectures like x86. 303fe6060f1SDimitry Andric /// 304fe6060f1SDimitry Andric /// \param IndentLevel specify the indent level as an integer. The UnwindRow 305fe6060f1SDimitry Andric /// will be output to the stream preceded by 2 * IndentLevel number of spaces. 306bdd1243dSDimitry Andric void dump(raw_ostream &OS, DIDumpOptions DumpOpts, 307fe6060f1SDimitry Andric unsigned IndentLevel = 0) const; 308fe6060f1SDimitry Andric }; 309fe6060f1SDimitry Andric 310fe6060f1SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const UnwindRow &Row); 311fe6060f1SDimitry Andric 312fe6060f1SDimitry Andric class CFIProgram; 313fe6060f1SDimitry Andric class CIE; 314fe6060f1SDimitry Andric class FDE; 315fe6060f1SDimitry Andric 316fe6060f1SDimitry Andric /// A class that contains all UnwindRow objects for an FDE or a single unwind 317fe6060f1SDimitry Andric /// row for a CIE. To unwind an address the rows, which are sorted by start 318fe6060f1SDimitry Andric /// address, can be searched to find the UnwindRow with the lowest starting 319fe6060f1SDimitry Andric /// address that is greater than or equal to the address that is being looked 320fe6060f1SDimitry Andric /// up. 321fe6060f1SDimitry Andric class UnwindTable { 322fe6060f1SDimitry Andric public: 323fe6060f1SDimitry Andric using RowContainer = std::vector<UnwindRow>; 324fe6060f1SDimitry Andric using iterator = RowContainer::iterator; 325fe6060f1SDimitry Andric using const_iterator = RowContainer::const_iterator; 326fe6060f1SDimitry Andric size()327fe6060f1SDimitry Andric size_t size() const { return Rows.size(); } begin()328fe6060f1SDimitry Andric iterator begin() { return Rows.begin(); } begin()329fe6060f1SDimitry Andric const_iterator begin() const { return Rows.begin(); } end()330fe6060f1SDimitry Andric iterator end() { return Rows.end(); } end()331fe6060f1SDimitry Andric const_iterator end() const { return Rows.end(); } 332fe6060f1SDimitry Andric const UnwindRow &operator[](size_t Index) const { 333fe6060f1SDimitry Andric assert(Index < size()); 334fe6060f1SDimitry Andric return Rows[Index]; 335fe6060f1SDimitry Andric } 336fe6060f1SDimitry Andric 337fe6060f1SDimitry Andric /// Dump the UnwindTable to the stream. 338fe6060f1SDimitry Andric /// 339fe6060f1SDimitry Andric /// \param OS the stream to use for output. 340fe6060f1SDimitry Andric /// 341fe6060f1SDimitry Andric /// \param MRI register information that helps emit register names insteead 342fe6060f1SDimitry Andric /// of raw register numbers. 343fe6060f1SDimitry Andric /// 344fe6060f1SDimitry Andric /// \param IsEH true if the DWARF Call Frame Information is from .eh_frame 345fe6060f1SDimitry Andric /// instead of from .debug_frame. This is needed for register number 346fe6060f1SDimitry Andric /// conversion because some register numbers differ between the two sections 347fe6060f1SDimitry Andric /// for certain architectures like x86. 348fe6060f1SDimitry Andric /// 349fe6060f1SDimitry Andric /// \param IndentLevel specify the indent level as an integer. The UnwindRow 350fe6060f1SDimitry Andric /// will be output to the stream preceded by 2 * IndentLevel number of spaces. 351bdd1243dSDimitry Andric void dump(raw_ostream &OS, DIDumpOptions DumpOpts, 352fe6060f1SDimitry Andric unsigned IndentLevel = 0) const; 353fe6060f1SDimitry Andric 354fe6060f1SDimitry Andric /// Create an UnwindTable from a Common Information Entry (CIE). 355fe6060f1SDimitry Andric /// 356fe6060f1SDimitry Andric /// \param Cie The Common Information Entry to extract the table from. The 357fe6060f1SDimitry Andric /// CFIProgram is retrieved from the \a Cie object and used to create the 358fe6060f1SDimitry Andric /// UnwindTable. 359fe6060f1SDimitry Andric /// 360fe6060f1SDimitry Andric /// \returns An error if the DWARF Call Frame Information opcodes have state 361fe6060f1SDimitry Andric /// machine errors, or a valid UnwindTable otherwise. 362fe6060f1SDimitry Andric static Expected<UnwindTable> create(const CIE *Cie); 363fe6060f1SDimitry Andric 364fe6060f1SDimitry Andric /// Create an UnwindTable from a Frame Descriptor Entry (FDE). 365fe6060f1SDimitry Andric /// 366fe6060f1SDimitry Andric /// \param Fde The Frame Descriptor Entry to extract the table from. The 367fe6060f1SDimitry Andric /// CFIProgram is retrieved from the \a Fde object and used to create the 368fe6060f1SDimitry Andric /// UnwindTable. 369fe6060f1SDimitry Andric /// 370fe6060f1SDimitry Andric /// \returns An error if the DWARF Call Frame Information opcodes have state 371fe6060f1SDimitry Andric /// machine errors, or a valid UnwindTable otherwise. 372fe6060f1SDimitry Andric static Expected<UnwindTable> create(const FDE *Fde); 373fe6060f1SDimitry Andric 374fe6060f1SDimitry Andric private: 375fe6060f1SDimitry Andric RowContainer Rows; 376fe6060f1SDimitry Andric /// The end address when data is extracted from a FDE. This value will be 377fe6060f1SDimitry Andric /// invalid when a UnwindTable is extracted from a CIE. 378bdd1243dSDimitry Andric std::optional<uint64_t> EndAddress; 379fe6060f1SDimitry Andric 380fe6060f1SDimitry Andric /// Parse the information in the CFIProgram and update the CurrRow object 381fe6060f1SDimitry Andric /// that the state machine describes. 382fe6060f1SDimitry Andric /// 383fe6060f1SDimitry Andric /// This is an internal implementation that emulates the state machine 384fe6060f1SDimitry Andric /// described in the DWARF Call Frame Information opcodes and will push 385fe6060f1SDimitry Andric /// CurrRow onto the Rows container when needed. 386fe6060f1SDimitry Andric /// 387fe6060f1SDimitry Andric /// \param CFIP the CFI program that contains the opcodes from a CIE or FDE. 388fe6060f1SDimitry Andric /// 389fe6060f1SDimitry Andric /// \param CurrRow the current row to modify while parsing the state machine. 390fe6060f1SDimitry Andric /// 391fe6060f1SDimitry Andric /// \param InitialLocs If non-NULL, we are parsing a FDE and this contains 392fe6060f1SDimitry Andric /// the initial register locations from the CIE. If NULL, then a CIE's 393fe6060f1SDimitry Andric /// opcodes are being parsed and this is not needed. This is used for the 394fe6060f1SDimitry Andric /// DW_CFA_restore and DW_CFA_restore_extended opcodes. 395fe6060f1SDimitry Andric Error parseRows(const CFIProgram &CFIP, UnwindRow &CurrRow, 396fe6060f1SDimitry Andric const RegisterLocations *InitialLocs); 397fe6060f1SDimitry Andric }; 398fe6060f1SDimitry Andric 399fe6060f1SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const UnwindTable &Rows); 400fe6060f1SDimitry Andric 4010b57cec5SDimitry Andric /// Represent a sequence of Call Frame Information instructions that, when read 4020b57cec5SDimitry Andric /// in order, construct a table mapping PC to frame state. This can also be 4030b57cec5SDimitry Andric /// referred to as "CFI rules" in DWARF literature to avoid confusion with 4040b57cec5SDimitry Andric /// computer programs in the broader sense, and in this context each instruction 4050b57cec5SDimitry Andric /// would be a rule to establish the mapping. Refer to pg. 172 in the DWARF5 4060b57cec5SDimitry Andric /// manual, "6.4.1 Structure of Call Frame Information". 4070b57cec5SDimitry Andric class CFIProgram { 4080b57cec5SDimitry Andric public: 409fe6060f1SDimitry Andric static constexpr size_t MaxOperands = 3; 410fe6060f1SDimitry Andric typedef SmallVector<uint64_t, MaxOperands> Operands; 4110b57cec5SDimitry Andric 4120b57cec5SDimitry Andric /// An instruction consists of a DWARF CFI opcode and an optional sequence of 4130b57cec5SDimitry Andric /// operands. If it refers to an expression, then this expression has its own 4140b57cec5SDimitry Andric /// sequence of operations and operands handled separately by DWARFExpression. 4150b57cec5SDimitry Andric struct Instruction { InstructionInstruction4160b57cec5SDimitry Andric Instruction(uint8_t Opcode) : Opcode(Opcode) {} 4170b57cec5SDimitry Andric 4180b57cec5SDimitry Andric uint8_t Opcode; 4190b57cec5SDimitry Andric Operands Ops; 4200b57cec5SDimitry Andric // Associated DWARF expression in case this instruction refers to one 421bdd1243dSDimitry Andric std::optional<DWARFExpression> Expression; 422fe6060f1SDimitry Andric 423fe6060f1SDimitry Andric Expected<uint64_t> getOperandAsUnsigned(const CFIProgram &CFIP, 424fe6060f1SDimitry Andric uint32_t OperandIdx) const; 425fe6060f1SDimitry Andric 426fe6060f1SDimitry Andric Expected<int64_t> getOperandAsSigned(const CFIProgram &CFIP, 427fe6060f1SDimitry Andric uint32_t OperandIdx) const; 4280b57cec5SDimitry Andric }; 4290b57cec5SDimitry Andric 4300b57cec5SDimitry Andric using InstrList = std::vector<Instruction>; 4310b57cec5SDimitry Andric using iterator = InstrList::iterator; 4320b57cec5SDimitry Andric using const_iterator = InstrList::const_iterator; 4330b57cec5SDimitry Andric begin()4340b57cec5SDimitry Andric iterator begin() { return Instructions.begin(); } begin()4350b57cec5SDimitry Andric const_iterator begin() const { return Instructions.begin(); } end()4360b57cec5SDimitry Andric iterator end() { return Instructions.end(); } end()4370b57cec5SDimitry Andric const_iterator end() const { return Instructions.end(); } 4380b57cec5SDimitry Andric size()4390b57cec5SDimitry Andric unsigned size() const { return (unsigned)Instructions.size(); } empty()4400b57cec5SDimitry Andric bool empty() const { return Instructions.empty(); } codeAlign()441fe6060f1SDimitry Andric uint64_t codeAlign() const { return CodeAlignmentFactor; } dataAlign()442fe6060f1SDimitry Andric int64_t dataAlign() const { return DataAlignmentFactor; } triple()443fe6060f1SDimitry Andric Triple::ArchType triple() const { return Arch; } 4440b57cec5SDimitry Andric CFIProgram(uint64_t CodeAlignmentFactor,int64_t DataAlignmentFactor,Triple::ArchType Arch)4450b57cec5SDimitry Andric CFIProgram(uint64_t CodeAlignmentFactor, int64_t DataAlignmentFactor, 4460b57cec5SDimitry Andric Triple::ArchType Arch) 4470b57cec5SDimitry Andric : CodeAlignmentFactor(CodeAlignmentFactor), 4480b57cec5SDimitry Andric DataAlignmentFactor(DataAlignmentFactor), 4490b57cec5SDimitry Andric Arch(Arch) {} 4500b57cec5SDimitry Andric 4510b57cec5SDimitry Andric /// Parse and store a sequence of CFI instructions from Data, 4520b57cec5SDimitry Andric /// starting at *Offset and ending at EndOffset. *Offset is updated 4530b57cec5SDimitry Andric /// to EndOffset upon successful parsing, or indicates the offset 4540b57cec5SDimitry Andric /// where a problem occurred in case an error is returned. 4558bcb0991SDimitry Andric Error parse(DWARFDataExtractor Data, uint64_t *Offset, uint64_t EndOffset); 4560b57cec5SDimitry Andric 457*0fca6ea1SDimitry Andric void dump(raw_ostream &OS, DIDumpOptions DumpOpts, unsigned IndentLevel, 458*0fca6ea1SDimitry Andric std::optional<uint64_t> InitialLocation) const; 4590b57cec5SDimitry Andric addInstruction(const Instruction & I)460fe6060f1SDimitry Andric void addInstruction(const Instruction &I) { Instructions.push_back(I); } 461fe6060f1SDimitry Andric 462fe6060f1SDimitry Andric /// Get a DWARF CFI call frame string for the given DW_CFA opcode. 463fe6060f1SDimitry Andric StringRef callFrameString(unsigned Opcode) const; 464fe6060f1SDimitry Andric 4650b57cec5SDimitry Andric private: 4660b57cec5SDimitry Andric std::vector<Instruction> Instructions; 4670b57cec5SDimitry Andric const uint64_t CodeAlignmentFactor; 4680b57cec5SDimitry Andric const int64_t DataAlignmentFactor; 4690b57cec5SDimitry Andric Triple::ArchType Arch; 4700b57cec5SDimitry Andric 4710b57cec5SDimitry Andric /// Convenience method to add a new instruction with the given opcode. addInstruction(uint8_t Opcode)4720b57cec5SDimitry Andric void addInstruction(uint8_t Opcode) { 4730b57cec5SDimitry Andric Instructions.push_back(Instruction(Opcode)); 4740b57cec5SDimitry Andric } 4750b57cec5SDimitry Andric 4760b57cec5SDimitry Andric /// Add a new single-operand instruction. addInstruction(uint8_t Opcode,uint64_t Operand1)4770b57cec5SDimitry Andric void addInstruction(uint8_t Opcode, uint64_t Operand1) { 4780b57cec5SDimitry Andric Instructions.push_back(Instruction(Opcode)); 4790b57cec5SDimitry Andric Instructions.back().Ops.push_back(Operand1); 4800b57cec5SDimitry Andric } 4810b57cec5SDimitry Andric 4820b57cec5SDimitry Andric /// Add a new instruction that has two operands. addInstruction(uint8_t Opcode,uint64_t Operand1,uint64_t Operand2)4830b57cec5SDimitry Andric void addInstruction(uint8_t Opcode, uint64_t Operand1, uint64_t Operand2) { 4840b57cec5SDimitry Andric Instructions.push_back(Instruction(Opcode)); 4850b57cec5SDimitry Andric Instructions.back().Ops.push_back(Operand1); 4860b57cec5SDimitry Andric Instructions.back().Ops.push_back(Operand2); 4870b57cec5SDimitry Andric } 4880b57cec5SDimitry Andric 489fe6060f1SDimitry Andric /// Add a new instruction that has three operands. addInstruction(uint8_t Opcode,uint64_t Operand1,uint64_t Operand2,uint64_t Operand3)490fe6060f1SDimitry Andric void addInstruction(uint8_t Opcode, uint64_t Operand1, uint64_t Operand2, 491fe6060f1SDimitry Andric uint64_t Operand3) { 492fe6060f1SDimitry Andric Instructions.push_back(Instruction(Opcode)); 493fe6060f1SDimitry Andric Instructions.back().Ops.push_back(Operand1); 494fe6060f1SDimitry Andric Instructions.back().Ops.push_back(Operand2); 495fe6060f1SDimitry Andric Instructions.back().Ops.push_back(Operand3); 496fe6060f1SDimitry Andric } 497fe6060f1SDimitry Andric 4980b57cec5SDimitry Andric /// Types of operands to CFI instructions 4990b57cec5SDimitry Andric /// In DWARF, this type is implicitly tied to a CFI instruction opcode and 500*0fca6ea1SDimitry Andric /// thus this type doesn't need to be explicitly written to the file (this is 5010b57cec5SDimitry Andric /// not a DWARF encoding). The relationship of instrs to operand types can 5020b57cec5SDimitry Andric /// be obtained from getOperandTypes() and is only used to simplify 5030b57cec5SDimitry Andric /// instruction printing. 5040b57cec5SDimitry Andric enum OperandType { 5050b57cec5SDimitry Andric OT_Unset, 5060b57cec5SDimitry Andric OT_None, 5070b57cec5SDimitry Andric OT_Address, 5080b57cec5SDimitry Andric OT_Offset, 5090b57cec5SDimitry Andric OT_FactoredCodeOffset, 5100b57cec5SDimitry Andric OT_SignedFactDataOffset, 5110b57cec5SDimitry Andric OT_UnsignedFactDataOffset, 5120b57cec5SDimitry Andric OT_Register, 513fe6060f1SDimitry Andric OT_AddressSpace, 5140b57cec5SDimitry Andric OT_Expression 5150b57cec5SDimitry Andric }; 5160b57cec5SDimitry Andric 517fe6060f1SDimitry Andric /// Get the OperandType as a "const char *". 518fe6060f1SDimitry Andric static const char *operandTypeString(OperandType OT); 519fe6060f1SDimitry Andric 5200b57cec5SDimitry Andric /// Retrieve the array describing the types of operands according to the enum 5210b57cec5SDimitry Andric /// above. This is indexed by opcode. 522fe6060f1SDimitry Andric static ArrayRef<OperandType[MaxOperands]> getOperandTypes(); 5230b57cec5SDimitry Andric 5240b57cec5SDimitry Andric /// Print \p Opcode's operand number \p OperandIdx which has value \p Operand. 525e8d8bef9SDimitry Andric void printOperand(raw_ostream &OS, DIDumpOptions DumpOpts, 5260b57cec5SDimitry Andric const Instruction &Instr, unsigned OperandIdx, 527*0fca6ea1SDimitry Andric uint64_t Operand, std::optional<uint64_t> &Address) const; 5280b57cec5SDimitry Andric }; 5290b57cec5SDimitry Andric 5300b57cec5SDimitry Andric /// An entry in either debug_frame or eh_frame. This entry can be a CIE or an 5310b57cec5SDimitry Andric /// FDE. 5320b57cec5SDimitry Andric class FrameEntry { 5330b57cec5SDimitry Andric public: 5340b57cec5SDimitry Andric enum FrameKind { FK_CIE, FK_FDE }; 5350b57cec5SDimitry Andric FrameEntry(FrameKind K,bool IsDWARF64,uint64_t Offset,uint64_t Length,uint64_t CodeAlign,int64_t DataAlign,Triple::ArchType Arch)5365ffd83dbSDimitry Andric FrameEntry(FrameKind K, bool IsDWARF64, uint64_t Offset, uint64_t Length, 5375ffd83dbSDimitry Andric uint64_t CodeAlign, int64_t DataAlign, Triple::ArchType Arch) 5385ffd83dbSDimitry Andric : Kind(K), IsDWARF64(IsDWARF64), Offset(Offset), Length(Length), 5390b57cec5SDimitry Andric CFIs(CodeAlign, DataAlign, Arch) {} 5400b57cec5SDimitry Andric 5411fd87a68SDimitry Andric virtual ~FrameEntry() = default; 5420b57cec5SDimitry Andric getKind()5430b57cec5SDimitry Andric FrameKind getKind() const { return Kind; } getOffset()5440b57cec5SDimitry Andric uint64_t getOffset() const { return Offset; } getLength()5450b57cec5SDimitry Andric uint64_t getLength() const { return Length; } cfis()5460b57cec5SDimitry Andric const CFIProgram &cfis() const { return CFIs; } cfis()5470b57cec5SDimitry Andric CFIProgram &cfis() { return CFIs; } 5480b57cec5SDimitry Andric 5490b57cec5SDimitry Andric /// Dump the instructions in this CFI fragment 550bdd1243dSDimitry Andric virtual void dump(raw_ostream &OS, DIDumpOptions DumpOpts) const = 0; 5510b57cec5SDimitry Andric 5520b57cec5SDimitry Andric protected: 5530b57cec5SDimitry Andric const FrameKind Kind; 5540b57cec5SDimitry Andric 5555ffd83dbSDimitry Andric const bool IsDWARF64; 5565ffd83dbSDimitry Andric 5570b57cec5SDimitry Andric /// Offset of this entry in the section. 5580b57cec5SDimitry Andric const uint64_t Offset; 5590b57cec5SDimitry Andric 5600b57cec5SDimitry Andric /// Entry length as specified in DWARF. 5610b57cec5SDimitry Andric const uint64_t Length; 5620b57cec5SDimitry Andric 5630b57cec5SDimitry Andric CFIProgram CFIs; 5640b57cec5SDimitry Andric }; 5650b57cec5SDimitry Andric 5660b57cec5SDimitry Andric /// DWARF Common Information Entry (CIE) 5670b57cec5SDimitry Andric class CIE : public FrameEntry { 5680b57cec5SDimitry Andric public: 5690b57cec5SDimitry Andric // CIEs (and FDEs) are simply container classes, so the only sensible way to 5700b57cec5SDimitry Andric // create them is by providing the full parsed contents in the constructor. CIE(bool IsDWARF64,uint64_t Offset,uint64_t Length,uint8_t Version,SmallString<8> Augmentation,uint8_t AddressSize,uint8_t SegmentDescriptorSize,uint64_t CodeAlignmentFactor,int64_t DataAlignmentFactor,uint64_t ReturnAddressRegister,SmallString<8> AugmentationData,uint32_t FDEPointerEncoding,uint32_t LSDAPointerEncoding,std::optional<uint64_t> Personality,std::optional<uint32_t> PersonalityEnc,Triple::ArchType Arch)5715ffd83dbSDimitry Andric CIE(bool IsDWARF64, uint64_t Offset, uint64_t Length, uint8_t Version, 5720b57cec5SDimitry Andric SmallString<8> Augmentation, uint8_t AddressSize, 5730b57cec5SDimitry Andric uint8_t SegmentDescriptorSize, uint64_t CodeAlignmentFactor, 5740b57cec5SDimitry Andric int64_t DataAlignmentFactor, uint64_t ReturnAddressRegister, 5750b57cec5SDimitry Andric SmallString<8> AugmentationData, uint32_t FDEPointerEncoding, 576bdd1243dSDimitry Andric uint32_t LSDAPointerEncoding, std::optional<uint64_t> Personality, 577bdd1243dSDimitry Andric std::optional<uint32_t> PersonalityEnc, Triple::ArchType Arch) 5785ffd83dbSDimitry Andric : FrameEntry(FK_CIE, IsDWARF64, Offset, Length, CodeAlignmentFactor, 5790b57cec5SDimitry Andric DataAlignmentFactor, Arch), 5800b57cec5SDimitry Andric Version(Version), Augmentation(std::move(Augmentation)), 5810b57cec5SDimitry Andric AddressSize(AddressSize), SegmentDescriptorSize(SegmentDescriptorSize), 5820b57cec5SDimitry Andric CodeAlignmentFactor(CodeAlignmentFactor), 5830b57cec5SDimitry Andric DataAlignmentFactor(DataAlignmentFactor), 5840b57cec5SDimitry Andric ReturnAddressRegister(ReturnAddressRegister), 5850b57cec5SDimitry Andric AugmentationData(std::move(AugmentationData)), 5860b57cec5SDimitry Andric FDEPointerEncoding(FDEPointerEncoding), 5870b57cec5SDimitry Andric LSDAPointerEncoding(LSDAPointerEncoding), Personality(Personality), 5880b57cec5SDimitry Andric PersonalityEnc(PersonalityEnc) {} 5890b57cec5SDimitry Andric classof(const FrameEntry * FE)5900b57cec5SDimitry Andric static bool classof(const FrameEntry *FE) { return FE->getKind() == FK_CIE; } 5910b57cec5SDimitry Andric getAugmentationString()5920b57cec5SDimitry Andric StringRef getAugmentationString() const { return Augmentation; } getCodeAlignmentFactor()5930b57cec5SDimitry Andric uint64_t getCodeAlignmentFactor() const { return CodeAlignmentFactor; } getDataAlignmentFactor()5940b57cec5SDimitry Andric int64_t getDataAlignmentFactor() const { return DataAlignmentFactor; } getVersion()5950b57cec5SDimitry Andric uint8_t getVersion() const { return Version; } getReturnAddressRegister()5960b57cec5SDimitry Andric uint64_t getReturnAddressRegister() const { return ReturnAddressRegister; } getPersonalityAddress()597bdd1243dSDimitry Andric std::optional<uint64_t> getPersonalityAddress() const { return Personality; } getPersonalityEncoding()598bdd1243dSDimitry Andric std::optional<uint32_t> getPersonalityEncoding() const { 599bdd1243dSDimitry Andric return PersonalityEnc; 600bdd1243dSDimitry Andric } 601bdd1243dSDimitry Andric getAugmentationData()602bdd1243dSDimitry Andric StringRef getAugmentationData() const { return AugmentationData; } 6030b57cec5SDimitry Andric getFDEPointerEncoding()6040b57cec5SDimitry Andric uint32_t getFDEPointerEncoding() const { return FDEPointerEncoding; } 6050b57cec5SDimitry Andric getLSDAPointerEncoding()6060b57cec5SDimitry Andric uint32_t getLSDAPointerEncoding() const { return LSDAPointerEncoding; } 6070b57cec5SDimitry Andric 608bdd1243dSDimitry Andric void dump(raw_ostream &OS, DIDumpOptions DumpOpts) const override; 6090b57cec5SDimitry Andric 6100b57cec5SDimitry Andric private: 6110b57cec5SDimitry Andric /// The following fields are defined in section 6.4.1 of the DWARF standard v4 6120b57cec5SDimitry Andric const uint8_t Version; 6130b57cec5SDimitry Andric const SmallString<8> Augmentation; 6140b57cec5SDimitry Andric const uint8_t AddressSize; 6150b57cec5SDimitry Andric const uint8_t SegmentDescriptorSize; 6160b57cec5SDimitry Andric const uint64_t CodeAlignmentFactor; 6170b57cec5SDimitry Andric const int64_t DataAlignmentFactor; 6180b57cec5SDimitry Andric const uint64_t ReturnAddressRegister; 6190b57cec5SDimitry Andric 6200b57cec5SDimitry Andric // The following are used when the CIE represents an EH frame entry. 6210b57cec5SDimitry Andric const SmallString<8> AugmentationData; 6220b57cec5SDimitry Andric const uint32_t FDEPointerEncoding; 6230b57cec5SDimitry Andric const uint32_t LSDAPointerEncoding; 624bdd1243dSDimitry Andric const std::optional<uint64_t> Personality; 625bdd1243dSDimitry Andric const std::optional<uint32_t> PersonalityEnc; 6260b57cec5SDimitry Andric }; 6270b57cec5SDimitry Andric 6280b57cec5SDimitry Andric /// DWARF Frame Description Entry (FDE) 6290b57cec5SDimitry Andric class FDE : public FrameEntry { 6300b57cec5SDimitry Andric public: FDE(bool IsDWARF64,uint64_t Offset,uint64_t Length,uint64_t CIEPointer,uint64_t InitialLocation,uint64_t AddressRange,CIE * Cie,std::optional<uint64_t> LSDAAddress,Triple::ArchType Arch)6315ffd83dbSDimitry Andric FDE(bool IsDWARF64, uint64_t Offset, uint64_t Length, uint64_t CIEPointer, 6320b57cec5SDimitry Andric uint64_t InitialLocation, uint64_t AddressRange, CIE *Cie, 633bdd1243dSDimitry Andric std::optional<uint64_t> LSDAAddress, Triple::ArchType Arch) 6345ffd83dbSDimitry Andric : FrameEntry(FK_FDE, IsDWARF64, Offset, Length, 6350b57cec5SDimitry Andric Cie ? Cie->getCodeAlignmentFactor() : 0, 636bdd1243dSDimitry Andric Cie ? Cie->getDataAlignmentFactor() : 0, Arch), 6375ffd83dbSDimitry Andric CIEPointer(CIEPointer), InitialLocation(InitialLocation), 6380b57cec5SDimitry Andric AddressRange(AddressRange), LinkedCIE(Cie), LSDAAddress(LSDAAddress) {} 6390b57cec5SDimitry Andric 6400b57cec5SDimitry Andric ~FDE() override = default; 6410b57cec5SDimitry Andric getLinkedCIE()6420b57cec5SDimitry Andric const CIE *getLinkedCIE() const { return LinkedCIE; } getCIEPointer()643bdd1243dSDimitry Andric uint64_t getCIEPointer() const { return CIEPointer; } getInitialLocation()6440b57cec5SDimitry Andric uint64_t getInitialLocation() const { return InitialLocation; } getAddressRange()6450b57cec5SDimitry Andric uint64_t getAddressRange() const { return AddressRange; } getLSDAAddress()646bdd1243dSDimitry Andric std::optional<uint64_t> getLSDAAddress() const { return LSDAAddress; } 6470b57cec5SDimitry Andric 648bdd1243dSDimitry Andric void dump(raw_ostream &OS, DIDumpOptions DumpOpts) const override; 6490b57cec5SDimitry Andric classof(const FrameEntry * FE)6500b57cec5SDimitry Andric static bool classof(const FrameEntry *FE) { return FE->getKind() == FK_FDE; } 6510b57cec5SDimitry Andric 6520b57cec5SDimitry Andric private: 6535ffd83dbSDimitry Andric /// The following fields are defined in section 6.4.1 of the DWARFv3 standard. 6545ffd83dbSDimitry Andric /// Note that CIE pointers in EH FDEs, unlike DWARF FDEs, contain relative 6555ffd83dbSDimitry Andric /// offsets to the linked CIEs. See the following link for more info: 6565ffd83dbSDimitry Andric /// https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html 6575ffd83dbSDimitry Andric const uint64_t CIEPointer; 6580b57cec5SDimitry Andric const uint64_t InitialLocation; 6590b57cec5SDimitry Andric const uint64_t AddressRange; 6600b57cec5SDimitry Andric const CIE *LinkedCIE; 661bdd1243dSDimitry Andric const std::optional<uint64_t> LSDAAddress; 6620b57cec5SDimitry Andric }; 6630b57cec5SDimitry Andric 6640b57cec5SDimitry Andric } // end namespace dwarf 6650b57cec5SDimitry Andric 6660b57cec5SDimitry Andric /// A parsed .debug_frame or .eh_frame section 6670b57cec5SDimitry Andric class DWARFDebugFrame { 6680b57cec5SDimitry Andric const Triple::ArchType Arch; 6690b57cec5SDimitry Andric // True if this is parsing an eh_frame section. 6700b57cec5SDimitry Andric const bool IsEH; 6710b57cec5SDimitry Andric // Not zero for sane pointer values coming out of eh_frame 6720b57cec5SDimitry Andric const uint64_t EHFrameAddress; 6730b57cec5SDimitry Andric 6740b57cec5SDimitry Andric std::vector<std::unique_ptr<dwarf::FrameEntry>> Entries; 6750b57cec5SDimitry Andric using iterator = pointee_iterator<decltype(Entries)::const_iterator>; 6760b57cec5SDimitry Andric 6770b57cec5SDimitry Andric /// Return the entry at the given offset or nullptr. 6780b57cec5SDimitry Andric dwarf::FrameEntry *getEntryAtOffset(uint64_t Offset) const; 6790b57cec5SDimitry Andric 6800b57cec5SDimitry Andric public: 6810b57cec5SDimitry Andric // If IsEH is true, assume it is a .eh_frame section. Otherwise, 6820b57cec5SDimitry Andric // it is a .debug_frame section. EHFrameAddress should be different 6830b57cec5SDimitry Andric // than zero for correct parsing of .eh_frame addresses when they 6840b57cec5SDimitry Andric // use a PC-relative encoding. 6850b57cec5SDimitry Andric DWARFDebugFrame(Triple::ArchType Arch, 6860b57cec5SDimitry Andric bool IsEH = false, uint64_t EHFrameAddress = 0); 6870b57cec5SDimitry Andric ~DWARFDebugFrame(); 6880b57cec5SDimitry Andric 6890b57cec5SDimitry Andric /// Dump the section data into the given stream. 690bdd1243dSDimitry Andric void dump(raw_ostream &OS, DIDumpOptions DumpOpts, 691bdd1243dSDimitry Andric std::optional<uint64_t> Offset) const; 6920b57cec5SDimitry Andric 6930b57cec5SDimitry Andric /// Parse the section from raw data. \p Data is assumed to contain the whole 6940b57cec5SDimitry Andric /// frame section contents to be parsed. 6955ffd83dbSDimitry Andric Error parse(DWARFDataExtractor Data); 6960b57cec5SDimitry Andric 6970b57cec5SDimitry Andric /// Return whether the section has any entries. empty()6980b57cec5SDimitry Andric bool empty() const { return Entries.empty(); } 6990b57cec5SDimitry Andric 7000b57cec5SDimitry Andric /// DWARF Frame entries accessors begin()7010b57cec5SDimitry Andric iterator begin() const { return Entries.begin(); } end()7020b57cec5SDimitry Andric iterator end() const { return Entries.end(); } entries()7030b57cec5SDimitry Andric iterator_range<iterator> entries() const { 7040b57cec5SDimitry Andric return iterator_range<iterator>(Entries.begin(), Entries.end()); 7050b57cec5SDimitry Andric } 7060b57cec5SDimitry Andric getEHFrameAddress()7070b57cec5SDimitry Andric uint64_t getEHFrameAddress() const { return EHFrameAddress; } 7080b57cec5SDimitry Andric }; 7090b57cec5SDimitry Andric 7100b57cec5SDimitry Andric } // end namespace llvm 7110b57cec5SDimitry Andric 7120b57cec5SDimitry Andric #endif // LLVM_DEBUGINFO_DWARF_DWARFDEBUGFRAME_H 713