17a7e6055SDimitry Andric //===- DWARFDebugFrame.h - Parsing of .debug_frame ------------------------===// 2ff0cc061SDimitry Andric // 3ff0cc061SDimitry Andric // The LLVM Compiler Infrastructure 4ff0cc061SDimitry Andric // 5ff0cc061SDimitry Andric // This file is distributed under the University of Illinois Open Source 6ff0cc061SDimitry Andric // License. See LICENSE.TXT for details. 7ff0cc061SDimitry Andric // 8ff0cc061SDimitry Andric //===----------------------------------------------------------------------===// 9ff0cc061SDimitry Andric 10ff0cc061SDimitry Andric #include "llvm/ADT/ArrayRef.h" 11ff0cc061SDimitry Andric #include "llvm/ADT/DenseMap.h" 123ca95b02SDimitry Andric #include "llvm/ADT/Optional.h" 13ff0cc061SDimitry Andric #include "llvm/ADT/SmallString.h" 14d88c1a5aSDimitry Andric #include "llvm/ADT/STLExtras.h" 153ca95b02SDimitry Andric #include "llvm/ADT/StringExtras.h" 16d88c1a5aSDimitry Andric #include "llvm/ADT/StringRef.h" 177a7e6055SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h" 18ff0cc061SDimitry Andric #include "llvm/Support/Casting.h" 19d88c1a5aSDimitry Andric #include "llvm/Support/Compiler.h" 20d88c1a5aSDimitry Andric #include "llvm/Support/DataExtractor.h" 21ff0cc061SDimitry Andric #include "llvm/Support/Dwarf.h" 22ff0cc061SDimitry Andric #include "llvm/Support/ErrorHandling.h" 23ff0cc061SDimitry Andric #include "llvm/Support/Format.h" 24ff0cc061SDimitry Andric #include "llvm/Support/raw_ostream.h" 25d88c1a5aSDimitry Andric #include <algorithm> 26d88c1a5aSDimitry Andric #include <cassert> 27d88c1a5aSDimitry Andric #include <cinttypes> 28d88c1a5aSDimitry Andric #include <cstdint> 29ff0cc061SDimitry Andric #include <string> 30ff0cc061SDimitry Andric #include <vector> 31ff0cc061SDimitry Andric 32ff0cc061SDimitry Andric using namespace llvm; 33ff0cc061SDimitry Andric using namespace dwarf; 34ff0cc061SDimitry Andric 35ff0cc061SDimitry Andric /// \brief Abstract frame entry defining the common interface concrete 36ff0cc061SDimitry Andric /// entries implement. 37ff0cc061SDimitry Andric class llvm::FrameEntry { 38ff0cc061SDimitry Andric public: 39ff0cc061SDimitry Andric enum FrameKind {FK_CIE, FK_FDE}; 40d88c1a5aSDimitry Andric 41ff0cc061SDimitry Andric FrameEntry(FrameKind K, uint64_t Offset, uint64_t Length) 42ff0cc061SDimitry Andric : Kind(K), Offset(Offset), Length(Length) {} 43ff0cc061SDimitry Andric 44d88c1a5aSDimitry Andric virtual ~FrameEntry() = default; 45ff0cc061SDimitry Andric 46ff0cc061SDimitry Andric FrameKind getKind() const { return Kind; } 47ff0cc061SDimitry Andric virtual uint64_t getOffset() const { return Offset; } 48ff0cc061SDimitry Andric 49ff0cc061SDimitry Andric /// \brief Parse and store a sequence of CFI instructions from Data, 50ff0cc061SDimitry Andric /// starting at *Offset and ending at EndOffset. If everything 51ff0cc061SDimitry Andric /// goes well, *Offset should be equal to EndOffset when this method 52ff0cc061SDimitry Andric /// returns. Otherwise, an error occurred. 53ff0cc061SDimitry Andric virtual void parseInstructions(DataExtractor Data, uint32_t *Offset, 54ff0cc061SDimitry Andric uint32_t EndOffset); 55ff0cc061SDimitry Andric 56ff0cc061SDimitry Andric /// \brief Dump the entry header to the given output stream. 57ff0cc061SDimitry Andric virtual void dumpHeader(raw_ostream &OS) const = 0; 58ff0cc061SDimitry Andric 59ff0cc061SDimitry Andric /// \brief Dump the entry's instructions to the given output stream. 60ff0cc061SDimitry Andric virtual void dumpInstructions(raw_ostream &OS) const; 61ff0cc061SDimitry Andric 62ff0cc061SDimitry Andric protected: 63ff0cc061SDimitry Andric const FrameKind Kind; 64ff0cc061SDimitry Andric 65ff0cc061SDimitry Andric /// \brief Offset of this entry in the section. 66ff0cc061SDimitry Andric uint64_t Offset; 67ff0cc061SDimitry Andric 68ff0cc061SDimitry Andric /// \brief Entry length as specified in DWARF. 69ff0cc061SDimitry Andric uint64_t Length; 70ff0cc061SDimitry Andric 71ff0cc061SDimitry Andric /// An entry may contain CFI instructions. An instruction consists of an 72ff0cc061SDimitry Andric /// opcode and an optional sequence of operands. 73ff0cc061SDimitry Andric typedef std::vector<uint64_t> Operands; 74ff0cc061SDimitry Andric struct Instruction { 75ff0cc061SDimitry Andric Instruction(uint8_t Opcode) 76ff0cc061SDimitry Andric : Opcode(Opcode) 77ff0cc061SDimitry Andric {} 78ff0cc061SDimitry Andric 79ff0cc061SDimitry Andric uint8_t Opcode; 80ff0cc061SDimitry Andric Operands Ops; 81ff0cc061SDimitry Andric }; 82ff0cc061SDimitry Andric 83ff0cc061SDimitry Andric std::vector<Instruction> Instructions; 84ff0cc061SDimitry Andric 85ff0cc061SDimitry Andric /// Convenience methods to add a new instruction with the given opcode and 86ff0cc061SDimitry Andric /// operands to the Instructions vector. 87ff0cc061SDimitry Andric void addInstruction(uint8_t Opcode) { 88ff0cc061SDimitry Andric Instructions.push_back(Instruction(Opcode)); 89ff0cc061SDimitry Andric } 90ff0cc061SDimitry Andric 91ff0cc061SDimitry Andric void addInstruction(uint8_t Opcode, uint64_t Operand1) { 92ff0cc061SDimitry Andric Instructions.push_back(Instruction(Opcode)); 93ff0cc061SDimitry Andric Instructions.back().Ops.push_back(Operand1); 94ff0cc061SDimitry Andric } 95ff0cc061SDimitry Andric 96ff0cc061SDimitry Andric void addInstruction(uint8_t Opcode, uint64_t Operand1, uint64_t Operand2) { 97ff0cc061SDimitry Andric Instructions.push_back(Instruction(Opcode)); 98ff0cc061SDimitry Andric Instructions.back().Ops.push_back(Operand1); 99ff0cc061SDimitry Andric Instructions.back().Ops.push_back(Operand2); 100ff0cc061SDimitry Andric } 101ff0cc061SDimitry Andric }; 102ff0cc061SDimitry Andric 103ff0cc061SDimitry Andric // See DWARF standard v3, section 7.23 104ff0cc061SDimitry Andric const uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK = 0xc0; 105ff0cc061SDimitry Andric const uint8_t DWARF_CFI_PRIMARY_OPERAND_MASK = 0x3f; 106ff0cc061SDimitry Andric 107ff0cc061SDimitry Andric void FrameEntry::parseInstructions(DataExtractor Data, uint32_t *Offset, 108ff0cc061SDimitry Andric uint32_t EndOffset) { 109ff0cc061SDimitry Andric while (*Offset < EndOffset) { 110ff0cc061SDimitry Andric uint8_t Opcode = Data.getU8(Offset); 111ff0cc061SDimitry Andric // Some instructions have a primary opcode encoded in the top bits. 112ff0cc061SDimitry Andric uint8_t Primary = Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK; 113ff0cc061SDimitry Andric 114ff0cc061SDimitry Andric if (Primary) { 115ff0cc061SDimitry Andric // If it's a primary opcode, the first operand is encoded in the bottom 116ff0cc061SDimitry Andric // bits of the opcode itself. 117ff0cc061SDimitry Andric uint64_t Op1 = Opcode & DWARF_CFI_PRIMARY_OPERAND_MASK; 118ff0cc061SDimitry Andric switch (Primary) { 119ff0cc061SDimitry Andric default: llvm_unreachable("Impossible primary CFI opcode"); 120ff0cc061SDimitry Andric case DW_CFA_advance_loc: 121ff0cc061SDimitry Andric case DW_CFA_restore: 122ff0cc061SDimitry Andric addInstruction(Primary, Op1); 123ff0cc061SDimitry Andric break; 124ff0cc061SDimitry Andric case DW_CFA_offset: 125ff0cc061SDimitry Andric addInstruction(Primary, Op1, Data.getULEB128(Offset)); 126ff0cc061SDimitry Andric break; 127ff0cc061SDimitry Andric } 128ff0cc061SDimitry Andric } else { 129ff0cc061SDimitry Andric // Extended opcode - its value is Opcode itself. 130ff0cc061SDimitry Andric switch (Opcode) { 131ff0cc061SDimitry Andric default: llvm_unreachable("Invalid extended CFI opcode"); 132ff0cc061SDimitry Andric case DW_CFA_nop: 133ff0cc061SDimitry Andric case DW_CFA_remember_state: 134ff0cc061SDimitry Andric case DW_CFA_restore_state: 135ff0cc061SDimitry Andric case DW_CFA_GNU_window_save: 136ff0cc061SDimitry Andric // No operands 137ff0cc061SDimitry Andric addInstruction(Opcode); 138ff0cc061SDimitry Andric break; 139ff0cc061SDimitry Andric case DW_CFA_set_loc: 140ff0cc061SDimitry Andric // Operands: Address 141ff0cc061SDimitry Andric addInstruction(Opcode, Data.getAddress(Offset)); 142ff0cc061SDimitry Andric break; 143ff0cc061SDimitry Andric case DW_CFA_advance_loc1: 144ff0cc061SDimitry Andric // Operands: 1-byte delta 145ff0cc061SDimitry Andric addInstruction(Opcode, Data.getU8(Offset)); 146ff0cc061SDimitry Andric break; 147ff0cc061SDimitry Andric case DW_CFA_advance_loc2: 148ff0cc061SDimitry Andric // Operands: 2-byte delta 149ff0cc061SDimitry Andric addInstruction(Opcode, Data.getU16(Offset)); 150ff0cc061SDimitry Andric break; 151ff0cc061SDimitry Andric case DW_CFA_advance_loc4: 152ff0cc061SDimitry Andric // Operands: 4-byte delta 153ff0cc061SDimitry Andric addInstruction(Opcode, Data.getU32(Offset)); 154ff0cc061SDimitry Andric break; 155ff0cc061SDimitry Andric case DW_CFA_restore_extended: 156ff0cc061SDimitry Andric case DW_CFA_undefined: 157ff0cc061SDimitry Andric case DW_CFA_same_value: 158ff0cc061SDimitry Andric case DW_CFA_def_cfa_register: 159ff0cc061SDimitry Andric case DW_CFA_def_cfa_offset: 160ff0cc061SDimitry Andric // Operands: ULEB128 161ff0cc061SDimitry Andric addInstruction(Opcode, Data.getULEB128(Offset)); 162ff0cc061SDimitry Andric break; 163ff0cc061SDimitry Andric case DW_CFA_def_cfa_offset_sf: 164ff0cc061SDimitry Andric // Operands: SLEB128 165ff0cc061SDimitry Andric addInstruction(Opcode, Data.getSLEB128(Offset)); 166ff0cc061SDimitry Andric break; 167ff0cc061SDimitry Andric case DW_CFA_offset_extended: 168ff0cc061SDimitry Andric case DW_CFA_register: 169ff0cc061SDimitry Andric case DW_CFA_def_cfa: 1703ca95b02SDimitry Andric case DW_CFA_val_offset: { 171ff0cc061SDimitry Andric // Operands: ULEB128, ULEB128 1723ca95b02SDimitry Andric // Note: We can not embed getULEB128 directly into function 1733ca95b02SDimitry Andric // argument list. getULEB128 changes Offset and order of evaluation 1743ca95b02SDimitry Andric // for arguments is unspecified. 1753ca95b02SDimitry Andric auto op1 = Data.getULEB128(Offset); 1763ca95b02SDimitry Andric auto op2 = Data.getULEB128(Offset); 1773ca95b02SDimitry Andric addInstruction(Opcode, op1, op2); 178ff0cc061SDimitry Andric break; 1793ca95b02SDimitry Andric } 180ff0cc061SDimitry Andric case DW_CFA_offset_extended_sf: 181ff0cc061SDimitry Andric case DW_CFA_def_cfa_sf: 1823ca95b02SDimitry Andric case DW_CFA_val_offset_sf: { 183ff0cc061SDimitry Andric // Operands: ULEB128, SLEB128 1843ca95b02SDimitry Andric // Note: see comment for the previous case 1853ca95b02SDimitry Andric auto op1 = Data.getULEB128(Offset); 1863ca95b02SDimitry Andric auto op2 = (uint64_t)Data.getSLEB128(Offset); 1873ca95b02SDimitry Andric addInstruction(Opcode, op1, op2); 188ff0cc061SDimitry Andric break; 1893ca95b02SDimitry Andric } 190ff0cc061SDimitry Andric case DW_CFA_def_cfa_expression: 191ff0cc061SDimitry Andric case DW_CFA_expression: 192ff0cc061SDimitry Andric case DW_CFA_val_expression: 193ff0cc061SDimitry Andric // TODO: implement this 194ff0cc061SDimitry Andric report_fatal_error("Values with expressions not implemented yet!"); 195ff0cc061SDimitry Andric } 196ff0cc061SDimitry Andric } 197ff0cc061SDimitry Andric } 198ff0cc061SDimitry Andric } 199ff0cc061SDimitry Andric 200ff0cc061SDimitry Andric namespace { 201d88c1a5aSDimitry Andric 202ff0cc061SDimitry Andric /// \brief DWARF Common Information Entry (CIE) 203ff0cc061SDimitry Andric class CIE : public FrameEntry { 204ff0cc061SDimitry Andric public: 205ff0cc061SDimitry Andric // CIEs (and FDEs) are simply container classes, so the only sensible way to 206ff0cc061SDimitry Andric // create them is by providing the full parsed contents in the constructor. 207ff0cc061SDimitry Andric CIE(uint64_t Offset, uint64_t Length, uint8_t Version, 208ff0cc061SDimitry Andric SmallString<8> Augmentation, uint8_t AddressSize, 209ff0cc061SDimitry Andric uint8_t SegmentDescriptorSize, uint64_t CodeAlignmentFactor, 2103ca95b02SDimitry Andric int64_t DataAlignmentFactor, uint64_t ReturnAddressRegister, 2113ca95b02SDimitry Andric SmallString<8> AugmentationData, uint32_t FDEPointerEncoding, 2123ca95b02SDimitry Andric uint32_t LSDAPointerEncoding) 213ff0cc061SDimitry Andric : FrameEntry(FK_CIE, Offset, Length), Version(Version), 2143ca95b02SDimitry Andric Augmentation(std::move(Augmentation)), AddressSize(AddressSize), 215ff0cc061SDimitry Andric SegmentDescriptorSize(SegmentDescriptorSize), 216ff0cc061SDimitry Andric CodeAlignmentFactor(CodeAlignmentFactor), 217ff0cc061SDimitry Andric DataAlignmentFactor(DataAlignmentFactor), 2183ca95b02SDimitry Andric ReturnAddressRegister(ReturnAddressRegister), 2193ca95b02SDimitry Andric AugmentationData(std::move(AugmentationData)), 2203ca95b02SDimitry Andric FDEPointerEncoding(FDEPointerEncoding), 2213ca95b02SDimitry Andric LSDAPointerEncoding(LSDAPointerEncoding) {} 222ff0cc061SDimitry Andric 223d88c1a5aSDimitry Andric ~CIE() override = default; 224ff0cc061SDimitry Andric 2253ca95b02SDimitry Andric StringRef getAugmentationString() const { return Augmentation; } 226ff0cc061SDimitry Andric uint64_t getCodeAlignmentFactor() const { return CodeAlignmentFactor; } 227ff0cc061SDimitry Andric int64_t getDataAlignmentFactor() const { return DataAlignmentFactor; } 228d88c1a5aSDimitry Andric 2293ca95b02SDimitry Andric uint32_t getFDEPointerEncoding() const { 2303ca95b02SDimitry Andric return FDEPointerEncoding; 2313ca95b02SDimitry Andric } 232d88c1a5aSDimitry Andric 2333ca95b02SDimitry Andric uint32_t getLSDAPointerEncoding() const { 2343ca95b02SDimitry Andric return LSDAPointerEncoding; 2353ca95b02SDimitry Andric } 236ff0cc061SDimitry Andric 237ff0cc061SDimitry Andric void dumpHeader(raw_ostream &OS) const override { 238ff0cc061SDimitry Andric OS << format("%08x %08x %08x CIE", 239ff0cc061SDimitry Andric (uint32_t)Offset, (uint32_t)Length, DW_CIE_ID) 240ff0cc061SDimitry Andric << "\n"; 241ff0cc061SDimitry Andric OS << format(" Version: %d\n", Version); 242ff0cc061SDimitry Andric OS << " Augmentation: \"" << Augmentation << "\"\n"; 243ff0cc061SDimitry Andric if (Version >= 4) { 244ff0cc061SDimitry Andric OS << format(" Address size: %u\n", 245ff0cc061SDimitry Andric (uint32_t)AddressSize); 246ff0cc061SDimitry Andric OS << format(" Segment desc size: %u\n", 247ff0cc061SDimitry Andric (uint32_t)SegmentDescriptorSize); 248ff0cc061SDimitry Andric } 249ff0cc061SDimitry Andric OS << format(" Code alignment factor: %u\n", 250ff0cc061SDimitry Andric (uint32_t)CodeAlignmentFactor); 251ff0cc061SDimitry Andric OS << format(" Data alignment factor: %d\n", 252ff0cc061SDimitry Andric (int32_t)DataAlignmentFactor); 253ff0cc061SDimitry Andric OS << format(" Return address column: %d\n", 254ff0cc061SDimitry Andric (int32_t)ReturnAddressRegister); 2553ca95b02SDimitry Andric if (!AugmentationData.empty()) { 2563ca95b02SDimitry Andric OS << " Augmentation data: "; 2573ca95b02SDimitry Andric for (uint8_t Byte : AugmentationData) 2583ca95b02SDimitry Andric OS << ' ' << hexdigit(Byte >> 4) << hexdigit(Byte & 0xf); 2593ca95b02SDimitry Andric OS << "\n"; 2603ca95b02SDimitry Andric } 261ff0cc061SDimitry Andric OS << "\n"; 262ff0cc061SDimitry Andric } 263ff0cc061SDimitry Andric 264ff0cc061SDimitry Andric static bool classof(const FrameEntry *FE) { 265ff0cc061SDimitry Andric return FE->getKind() == FK_CIE; 266ff0cc061SDimitry Andric } 267ff0cc061SDimitry Andric 268ff0cc061SDimitry Andric private: 269ff0cc061SDimitry Andric /// The following fields are defined in section 6.4.1 of the DWARF standard v4 270ff0cc061SDimitry Andric uint8_t Version; 271ff0cc061SDimitry Andric SmallString<8> Augmentation; 272ff0cc061SDimitry Andric uint8_t AddressSize; 273ff0cc061SDimitry Andric uint8_t SegmentDescriptorSize; 274ff0cc061SDimitry Andric uint64_t CodeAlignmentFactor; 275ff0cc061SDimitry Andric int64_t DataAlignmentFactor; 276ff0cc061SDimitry Andric uint64_t ReturnAddressRegister; 2773ca95b02SDimitry Andric 2783ca95b02SDimitry Andric // The following are used when the CIE represents an EH frame entry. 2793ca95b02SDimitry Andric SmallString<8> AugmentationData; 2803ca95b02SDimitry Andric uint32_t FDEPointerEncoding; 2813ca95b02SDimitry Andric uint32_t LSDAPointerEncoding; 282ff0cc061SDimitry Andric }; 283ff0cc061SDimitry Andric 284ff0cc061SDimitry Andric /// \brief DWARF Frame Description Entry (FDE) 285ff0cc061SDimitry Andric class FDE : public FrameEntry { 286ff0cc061SDimitry Andric public: 287ff0cc061SDimitry Andric // Each FDE has a CIE it's "linked to". Our FDE contains is constructed with 288ff0cc061SDimitry Andric // an offset to the CIE (provided by parsing the FDE header). The CIE itself 289ff0cc061SDimitry Andric // is obtained lazily once it's actually required. 290ff0cc061SDimitry Andric FDE(uint64_t Offset, uint64_t Length, int64_t LinkedCIEOffset, 291ff0cc061SDimitry Andric uint64_t InitialLocation, uint64_t AddressRange, 292ff0cc061SDimitry Andric CIE *Cie) 293ff0cc061SDimitry Andric : FrameEntry(FK_FDE, Offset, Length), LinkedCIEOffset(LinkedCIEOffset), 294ff0cc061SDimitry Andric InitialLocation(InitialLocation), AddressRange(AddressRange), 295ff0cc061SDimitry Andric LinkedCIE(Cie) {} 296ff0cc061SDimitry Andric 297d88c1a5aSDimitry Andric ~FDE() override = default; 298ff0cc061SDimitry Andric 299ff0cc061SDimitry Andric CIE *getLinkedCIE() const { return LinkedCIE; } 300ff0cc061SDimitry Andric 301ff0cc061SDimitry Andric void dumpHeader(raw_ostream &OS) const override { 302ff0cc061SDimitry Andric OS << format("%08x %08x %08x FDE ", 303ff0cc061SDimitry Andric (uint32_t)Offset, (uint32_t)Length, (int32_t)LinkedCIEOffset); 304ff0cc061SDimitry Andric OS << format("cie=%08x pc=%08x...%08x\n", 305ff0cc061SDimitry Andric (int32_t)LinkedCIEOffset, 306ff0cc061SDimitry Andric (uint32_t)InitialLocation, 307ff0cc061SDimitry Andric (uint32_t)InitialLocation + (uint32_t)AddressRange); 308ff0cc061SDimitry Andric } 309ff0cc061SDimitry Andric 310ff0cc061SDimitry Andric static bool classof(const FrameEntry *FE) { 311ff0cc061SDimitry Andric return FE->getKind() == FK_FDE; 312ff0cc061SDimitry Andric } 313ff0cc061SDimitry Andric 314ff0cc061SDimitry Andric private: 315ff0cc061SDimitry Andric /// The following fields are defined in section 6.4.1 of the DWARF standard v3 316ff0cc061SDimitry Andric uint64_t LinkedCIEOffset; 317ff0cc061SDimitry Andric uint64_t InitialLocation; 318ff0cc061SDimitry Andric uint64_t AddressRange; 319ff0cc061SDimitry Andric CIE *LinkedCIE; 320ff0cc061SDimitry Andric }; 321ff0cc061SDimitry Andric 322ff0cc061SDimitry Andric /// \brief Types of operands to CF instructions. 323ff0cc061SDimitry Andric enum OperandType { 324ff0cc061SDimitry Andric OT_Unset, 325ff0cc061SDimitry Andric OT_None, 326ff0cc061SDimitry Andric OT_Address, 327ff0cc061SDimitry Andric OT_Offset, 328ff0cc061SDimitry Andric OT_FactoredCodeOffset, 329ff0cc061SDimitry Andric OT_SignedFactDataOffset, 330ff0cc061SDimitry Andric OT_UnsignedFactDataOffset, 331ff0cc061SDimitry Andric OT_Register, 332ff0cc061SDimitry Andric OT_Expression 333ff0cc061SDimitry Andric }; 334ff0cc061SDimitry Andric 335ff0cc061SDimitry Andric } // end anonymous namespace 336ff0cc061SDimitry Andric 337ff0cc061SDimitry Andric /// \brief Initialize the array describing the types of operands. 338ff0cc061SDimitry Andric static ArrayRef<OperandType[2]> getOperandTypes() { 339ff0cc061SDimitry Andric static OperandType OpTypes[DW_CFA_restore+1][2]; 340ff0cc061SDimitry Andric 341ff0cc061SDimitry Andric #define DECLARE_OP2(OP, OPTYPE0, OPTYPE1) \ 342ff0cc061SDimitry Andric do { \ 343ff0cc061SDimitry Andric OpTypes[OP][0] = OPTYPE0; \ 344ff0cc061SDimitry Andric OpTypes[OP][1] = OPTYPE1; \ 345d88c1a5aSDimitry Andric } while (false) 346ff0cc061SDimitry Andric #define DECLARE_OP1(OP, OPTYPE0) DECLARE_OP2(OP, OPTYPE0, OT_None) 347ff0cc061SDimitry Andric #define DECLARE_OP0(OP) DECLARE_OP1(OP, OT_None) 348ff0cc061SDimitry Andric 349ff0cc061SDimitry Andric DECLARE_OP1(DW_CFA_set_loc, OT_Address); 350ff0cc061SDimitry Andric DECLARE_OP1(DW_CFA_advance_loc, OT_FactoredCodeOffset); 351ff0cc061SDimitry Andric DECLARE_OP1(DW_CFA_advance_loc1, OT_FactoredCodeOffset); 352ff0cc061SDimitry Andric DECLARE_OP1(DW_CFA_advance_loc2, OT_FactoredCodeOffset); 353ff0cc061SDimitry Andric DECLARE_OP1(DW_CFA_advance_loc4, OT_FactoredCodeOffset); 354ff0cc061SDimitry Andric DECLARE_OP1(DW_CFA_MIPS_advance_loc8, OT_FactoredCodeOffset); 355ff0cc061SDimitry Andric DECLARE_OP2(DW_CFA_def_cfa, OT_Register, OT_Offset); 356ff0cc061SDimitry Andric DECLARE_OP2(DW_CFA_def_cfa_sf, OT_Register, OT_SignedFactDataOffset); 357ff0cc061SDimitry Andric DECLARE_OP1(DW_CFA_def_cfa_register, OT_Register); 358ff0cc061SDimitry Andric DECLARE_OP1(DW_CFA_def_cfa_offset, OT_Offset); 359ff0cc061SDimitry Andric DECLARE_OP1(DW_CFA_def_cfa_offset_sf, OT_SignedFactDataOffset); 360ff0cc061SDimitry Andric DECLARE_OP1(DW_CFA_def_cfa_expression, OT_Expression); 361ff0cc061SDimitry Andric DECLARE_OP1(DW_CFA_undefined, OT_Register); 362ff0cc061SDimitry Andric DECLARE_OP1(DW_CFA_same_value, OT_Register); 363ff0cc061SDimitry Andric DECLARE_OP2(DW_CFA_offset, OT_Register, OT_UnsignedFactDataOffset); 364ff0cc061SDimitry Andric DECLARE_OP2(DW_CFA_offset_extended, OT_Register, OT_UnsignedFactDataOffset); 365ff0cc061SDimitry Andric DECLARE_OP2(DW_CFA_offset_extended_sf, OT_Register, OT_SignedFactDataOffset); 366ff0cc061SDimitry Andric DECLARE_OP2(DW_CFA_val_offset, OT_Register, OT_UnsignedFactDataOffset); 367ff0cc061SDimitry Andric DECLARE_OP2(DW_CFA_val_offset_sf, OT_Register, OT_SignedFactDataOffset); 368ff0cc061SDimitry Andric DECLARE_OP2(DW_CFA_register, OT_Register, OT_Register); 369ff0cc061SDimitry Andric DECLARE_OP2(DW_CFA_expression, OT_Register, OT_Expression); 370ff0cc061SDimitry Andric DECLARE_OP2(DW_CFA_val_expression, OT_Register, OT_Expression); 371ff0cc061SDimitry Andric DECLARE_OP1(DW_CFA_restore, OT_Register); 372ff0cc061SDimitry Andric DECLARE_OP1(DW_CFA_restore_extended, OT_Register); 373ff0cc061SDimitry Andric DECLARE_OP0(DW_CFA_remember_state); 374ff0cc061SDimitry Andric DECLARE_OP0(DW_CFA_restore_state); 375ff0cc061SDimitry Andric DECLARE_OP0(DW_CFA_GNU_window_save); 376ff0cc061SDimitry Andric DECLARE_OP1(DW_CFA_GNU_args_size, OT_Offset); 377ff0cc061SDimitry Andric DECLARE_OP0(DW_CFA_nop); 378ff0cc061SDimitry Andric 379ff0cc061SDimitry Andric #undef DECLARE_OP0 380ff0cc061SDimitry Andric #undef DECLARE_OP1 381ff0cc061SDimitry Andric #undef DECLARE_OP2 382d88c1a5aSDimitry Andric 383ff0cc061SDimitry Andric return ArrayRef<OperandType[2]>(&OpTypes[0], DW_CFA_restore+1); 384ff0cc061SDimitry Andric } 385ff0cc061SDimitry Andric 386ff0cc061SDimitry Andric static ArrayRef<OperandType[2]> OpTypes = getOperandTypes(); 387ff0cc061SDimitry Andric 388ff0cc061SDimitry Andric /// \brief Print \p Opcode's operand number \p OperandIdx which has 389ff0cc061SDimitry Andric /// value \p Operand. 390ff0cc061SDimitry Andric static void printOperand(raw_ostream &OS, uint8_t Opcode, unsigned OperandIdx, 391ff0cc061SDimitry Andric uint64_t Operand, uint64_t CodeAlignmentFactor, 392ff0cc061SDimitry Andric int64_t DataAlignmentFactor) { 393ff0cc061SDimitry Andric assert(OperandIdx < 2); 394ff0cc061SDimitry Andric OperandType Type = OpTypes[Opcode][OperandIdx]; 395ff0cc061SDimitry Andric 396ff0cc061SDimitry Andric switch (Type) { 397d88c1a5aSDimitry Andric case OT_Unset: { 398ff0cc061SDimitry Andric OS << " Unsupported " << (OperandIdx ? "second" : "first") << " operand to"; 399d88c1a5aSDimitry Andric auto OpcodeName = CallFrameString(Opcode); 400d88c1a5aSDimitry Andric if (!OpcodeName.empty()) 401ff0cc061SDimitry Andric OS << " " << OpcodeName; 402ff0cc061SDimitry Andric else 403ff0cc061SDimitry Andric OS << format(" Opcode %x", Opcode); 404ff0cc061SDimitry Andric break; 405d88c1a5aSDimitry Andric } 406ff0cc061SDimitry Andric case OT_None: 407ff0cc061SDimitry Andric break; 408ff0cc061SDimitry Andric case OT_Address: 409ff0cc061SDimitry Andric OS << format(" %" PRIx64, Operand); 410ff0cc061SDimitry Andric break; 411ff0cc061SDimitry Andric case OT_Offset: 412ff0cc061SDimitry Andric // The offsets are all encoded in a unsigned form, but in practice 413ff0cc061SDimitry Andric // consumers use them signed. It's most certainly legacy due to 414ff0cc061SDimitry Andric // the lack of signed variants in the first Dwarf standards. 415ff0cc061SDimitry Andric OS << format(" %+" PRId64, int64_t(Operand)); 416ff0cc061SDimitry Andric break; 417ff0cc061SDimitry Andric case OT_FactoredCodeOffset: // Always Unsigned 418ff0cc061SDimitry Andric if (CodeAlignmentFactor) 419ff0cc061SDimitry Andric OS << format(" %" PRId64, Operand * CodeAlignmentFactor); 420ff0cc061SDimitry Andric else 421ff0cc061SDimitry Andric OS << format(" %" PRId64 "*code_alignment_factor" , Operand); 422ff0cc061SDimitry Andric break; 423ff0cc061SDimitry Andric case OT_SignedFactDataOffset: 424ff0cc061SDimitry Andric if (DataAlignmentFactor) 425ff0cc061SDimitry Andric OS << format(" %" PRId64, int64_t(Operand) * DataAlignmentFactor); 426ff0cc061SDimitry Andric else 427ff0cc061SDimitry Andric OS << format(" %" PRId64 "*data_alignment_factor" , int64_t(Operand)); 428ff0cc061SDimitry Andric break; 429ff0cc061SDimitry Andric case OT_UnsignedFactDataOffset: 430ff0cc061SDimitry Andric if (DataAlignmentFactor) 431ff0cc061SDimitry Andric OS << format(" %" PRId64, Operand * DataAlignmentFactor); 432ff0cc061SDimitry Andric else 433ff0cc061SDimitry Andric OS << format(" %" PRId64 "*data_alignment_factor" , Operand); 434ff0cc061SDimitry Andric break; 435ff0cc061SDimitry Andric case OT_Register: 436ff0cc061SDimitry Andric OS << format(" reg%" PRId64, Operand); 437ff0cc061SDimitry Andric break; 438ff0cc061SDimitry Andric case OT_Expression: 439ff0cc061SDimitry Andric OS << " expression"; 440ff0cc061SDimitry Andric break; 441ff0cc061SDimitry Andric } 442ff0cc061SDimitry Andric } 443ff0cc061SDimitry Andric 444ff0cc061SDimitry Andric void FrameEntry::dumpInstructions(raw_ostream &OS) const { 445ff0cc061SDimitry Andric uint64_t CodeAlignmentFactor = 0; 446ff0cc061SDimitry Andric int64_t DataAlignmentFactor = 0; 447ff0cc061SDimitry Andric const CIE *Cie = dyn_cast<CIE>(this); 448ff0cc061SDimitry Andric 449ff0cc061SDimitry Andric if (!Cie) 450ff0cc061SDimitry Andric Cie = cast<FDE>(this)->getLinkedCIE(); 451ff0cc061SDimitry Andric if (Cie) { 452ff0cc061SDimitry Andric CodeAlignmentFactor = Cie->getCodeAlignmentFactor(); 453ff0cc061SDimitry Andric DataAlignmentFactor = Cie->getDataAlignmentFactor(); 454ff0cc061SDimitry Andric } 455ff0cc061SDimitry Andric 456ff0cc061SDimitry Andric for (const auto &Instr : Instructions) { 457ff0cc061SDimitry Andric uint8_t Opcode = Instr.Opcode; 458ff0cc061SDimitry Andric if (Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK) 459ff0cc061SDimitry Andric Opcode &= DWARF_CFI_PRIMARY_OPCODE_MASK; 460ff0cc061SDimitry Andric OS << " " << CallFrameString(Opcode) << ":"; 461ff0cc061SDimitry Andric for (unsigned i = 0; i < Instr.Ops.size(); ++i) 462ff0cc061SDimitry Andric printOperand(OS, Opcode, i, Instr.Ops[i], CodeAlignmentFactor, 463ff0cc061SDimitry Andric DataAlignmentFactor); 464ff0cc061SDimitry Andric OS << '\n'; 465ff0cc061SDimitry Andric } 466ff0cc061SDimitry Andric } 467ff0cc061SDimitry Andric 4687a7e6055SDimitry Andric DWARFDebugFrame::DWARFDebugFrame(bool IsEH) : IsEH(IsEH) {} 469ff0cc061SDimitry Andric 470d88c1a5aSDimitry Andric DWARFDebugFrame::~DWARFDebugFrame() = default; 471ff0cc061SDimitry Andric 472ff0cc061SDimitry Andric static void LLVM_ATTRIBUTE_UNUSED dumpDataAux(DataExtractor Data, 473ff0cc061SDimitry Andric uint32_t Offset, int Length) { 474ff0cc061SDimitry Andric errs() << "DUMP: "; 475ff0cc061SDimitry Andric for (int i = 0; i < Length; ++i) { 476ff0cc061SDimitry Andric uint8_t c = Data.getU8(&Offset); 477ff0cc061SDimitry Andric errs().write_hex(c); errs() << " "; 478ff0cc061SDimitry Andric } 479ff0cc061SDimitry Andric errs() << "\n"; 480ff0cc061SDimitry Andric } 481ff0cc061SDimitry Andric 4823ca95b02SDimitry Andric static unsigned getSizeForEncoding(const DataExtractor &Data, 4833ca95b02SDimitry Andric unsigned symbolEncoding) { 4843ca95b02SDimitry Andric unsigned format = symbolEncoding & 0x0f; 4853ca95b02SDimitry Andric switch (format) { 4863ca95b02SDimitry Andric default: llvm_unreachable("Unknown Encoding"); 4877a7e6055SDimitry Andric case DW_EH_PE_absptr: 4887a7e6055SDimitry Andric case DW_EH_PE_signed: 4893ca95b02SDimitry Andric return Data.getAddressSize(); 4907a7e6055SDimitry Andric case DW_EH_PE_udata2: 4917a7e6055SDimitry Andric case DW_EH_PE_sdata2: 4923ca95b02SDimitry Andric return 2; 4937a7e6055SDimitry Andric case DW_EH_PE_udata4: 4947a7e6055SDimitry Andric case DW_EH_PE_sdata4: 4953ca95b02SDimitry Andric return 4; 4967a7e6055SDimitry Andric case DW_EH_PE_udata8: 4977a7e6055SDimitry Andric case DW_EH_PE_sdata8: 4983ca95b02SDimitry Andric return 8; 4993ca95b02SDimitry Andric } 5003ca95b02SDimitry Andric } 5013ca95b02SDimitry Andric 5023ca95b02SDimitry Andric static uint64_t readPointer(const DataExtractor &Data, uint32_t &Offset, 5033ca95b02SDimitry Andric unsigned Encoding) { 5043ca95b02SDimitry Andric switch (getSizeForEncoding(Data, Encoding)) { 5053ca95b02SDimitry Andric case 2: 5063ca95b02SDimitry Andric return Data.getU16(&Offset); 5073ca95b02SDimitry Andric case 4: 5083ca95b02SDimitry Andric return Data.getU32(&Offset); 5093ca95b02SDimitry Andric case 8: 5103ca95b02SDimitry Andric return Data.getU64(&Offset); 5113ca95b02SDimitry Andric default: 5123ca95b02SDimitry Andric llvm_unreachable("Illegal data size"); 5133ca95b02SDimitry Andric } 5143ca95b02SDimitry Andric } 515ff0cc061SDimitry Andric 516ff0cc061SDimitry Andric void DWARFDebugFrame::parse(DataExtractor Data) { 517ff0cc061SDimitry Andric uint32_t Offset = 0; 518ff0cc061SDimitry Andric DenseMap<uint32_t, CIE *> CIEs; 519ff0cc061SDimitry Andric 520ff0cc061SDimitry Andric while (Data.isValidOffset(Offset)) { 521ff0cc061SDimitry Andric uint32_t StartOffset = Offset; 522ff0cc061SDimitry Andric 5233ca95b02SDimitry Andric auto ReportError = [StartOffset](const char *ErrorMsg) { 5243ca95b02SDimitry Andric std::string Str; 5253ca95b02SDimitry Andric raw_string_ostream OS(Str); 5263ca95b02SDimitry Andric OS << format(ErrorMsg, StartOffset); 5273ca95b02SDimitry Andric OS.flush(); 5283ca95b02SDimitry Andric report_fatal_error(Str); 5293ca95b02SDimitry Andric }; 5303ca95b02SDimitry Andric 531ff0cc061SDimitry Andric bool IsDWARF64 = false; 532ff0cc061SDimitry Andric uint64_t Length = Data.getU32(&Offset); 533ff0cc061SDimitry Andric uint64_t Id; 534ff0cc061SDimitry Andric 535ff0cc061SDimitry Andric if (Length == UINT32_MAX) { 536ff0cc061SDimitry Andric // DWARF-64 is distinguished by the first 32 bits of the initial length 537ff0cc061SDimitry Andric // field being 0xffffffff. Then, the next 64 bits are the actual entry 538ff0cc061SDimitry Andric // length. 539ff0cc061SDimitry Andric IsDWARF64 = true; 540ff0cc061SDimitry Andric Length = Data.getU64(&Offset); 541ff0cc061SDimitry Andric } 542ff0cc061SDimitry Andric 543ff0cc061SDimitry Andric // At this point, Offset points to the next field after Length. 544ff0cc061SDimitry Andric // Length is the structure size excluding itself. Compute an offset one 545ff0cc061SDimitry Andric // past the end of the structure (needed to know how many instructions to 546ff0cc061SDimitry Andric // read). 547ff0cc061SDimitry Andric // TODO: For honest DWARF64 support, DataExtractor will have to treat 548ff0cc061SDimitry Andric // offset_ptr as uint64_t* 5493ca95b02SDimitry Andric uint32_t StartStructureOffset = Offset; 550ff0cc061SDimitry Andric uint32_t EndStructureOffset = Offset + static_cast<uint32_t>(Length); 551ff0cc061SDimitry Andric 552ff0cc061SDimitry Andric // The Id field's size depends on the DWARF format 5533ca95b02SDimitry Andric Id = Data.getUnsigned(&Offset, (IsDWARF64 && !IsEH) ? 8 : 4); 5543ca95b02SDimitry Andric bool IsCIE = ((IsDWARF64 && Id == DW64_CIE_ID) || 5553ca95b02SDimitry Andric Id == DW_CIE_ID || 5563ca95b02SDimitry Andric (IsEH && !Id)); 557ff0cc061SDimitry Andric 558ff0cc061SDimitry Andric if (IsCIE) { 559ff0cc061SDimitry Andric uint8_t Version = Data.getU8(&Offset); 560ff0cc061SDimitry Andric const char *Augmentation = Data.getCStr(&Offset); 5613ca95b02SDimitry Andric StringRef AugmentationString(Augmentation ? Augmentation : ""); 5623ca95b02SDimitry Andric uint8_t AddressSize = Version < 4 ? Data.getAddressSize() : 5633ca95b02SDimitry Andric Data.getU8(&Offset); 564ff0cc061SDimitry Andric Data.setAddressSize(AddressSize); 565ff0cc061SDimitry Andric uint8_t SegmentDescriptorSize = Version < 4 ? 0 : Data.getU8(&Offset); 566ff0cc061SDimitry Andric uint64_t CodeAlignmentFactor = Data.getULEB128(&Offset); 567ff0cc061SDimitry Andric int64_t DataAlignmentFactor = Data.getSLEB128(&Offset); 568ff0cc061SDimitry Andric uint64_t ReturnAddressRegister = Data.getULEB128(&Offset); 569ff0cc061SDimitry Andric 5703ca95b02SDimitry Andric // Parse the augmentation data for EH CIEs 5713ca95b02SDimitry Andric StringRef AugmentationData(""); 5723ca95b02SDimitry Andric uint32_t FDEPointerEncoding = DW_EH_PE_omit; 5733ca95b02SDimitry Andric uint32_t LSDAPointerEncoding = DW_EH_PE_omit; 5743ca95b02SDimitry Andric if (IsEH) { 5753ca95b02SDimitry Andric Optional<uint32_t> PersonalityEncoding; 5763ca95b02SDimitry Andric Optional<uint64_t> Personality; 5773ca95b02SDimitry Andric 5783ca95b02SDimitry Andric Optional<uint64_t> AugmentationLength; 5793ca95b02SDimitry Andric uint32_t StartAugmentationOffset; 5803ca95b02SDimitry Andric uint32_t EndAugmentationOffset; 5813ca95b02SDimitry Andric 5823ca95b02SDimitry Andric // Walk the augmentation string to get all the augmentation data. 5833ca95b02SDimitry Andric for (unsigned i = 0, e = AugmentationString.size(); i != e; ++i) { 5843ca95b02SDimitry Andric switch (AugmentationString[i]) { 5853ca95b02SDimitry Andric default: 5863ca95b02SDimitry Andric ReportError("Unknown augmentation character in entry at %lx"); 5873ca95b02SDimitry Andric case 'L': 5883ca95b02SDimitry Andric LSDAPointerEncoding = Data.getU8(&Offset); 5893ca95b02SDimitry Andric break; 5903ca95b02SDimitry Andric case 'P': { 5913ca95b02SDimitry Andric if (Personality) 5923ca95b02SDimitry Andric ReportError("Duplicate personality in entry at %lx"); 5933ca95b02SDimitry Andric PersonalityEncoding = Data.getU8(&Offset); 5943ca95b02SDimitry Andric Personality = readPointer(Data, Offset, *PersonalityEncoding); 5953ca95b02SDimitry Andric break; 5963ca95b02SDimitry Andric } 5973ca95b02SDimitry Andric case 'R': 5983ca95b02SDimitry Andric FDEPointerEncoding = Data.getU8(&Offset); 5993ca95b02SDimitry Andric break; 6003ca95b02SDimitry Andric case 'z': 6013ca95b02SDimitry Andric if (i) 6023ca95b02SDimitry Andric ReportError("'z' must be the first character at %lx"); 6033ca95b02SDimitry Andric // Parse the augmentation length first. We only parse it if 6043ca95b02SDimitry Andric // the string contains a 'z'. 6053ca95b02SDimitry Andric AugmentationLength = Data.getULEB128(&Offset); 6063ca95b02SDimitry Andric StartAugmentationOffset = Offset; 6073ca95b02SDimitry Andric EndAugmentationOffset = Offset + 6083ca95b02SDimitry Andric static_cast<uint32_t>(*AugmentationLength); 6093ca95b02SDimitry Andric } 6103ca95b02SDimitry Andric } 6113ca95b02SDimitry Andric 6123ca95b02SDimitry Andric if (AugmentationLength.hasValue()) { 6133ca95b02SDimitry Andric if (Offset != EndAugmentationOffset) 6143ca95b02SDimitry Andric ReportError("Parsing augmentation data at %lx failed"); 6153ca95b02SDimitry Andric 6163ca95b02SDimitry Andric AugmentationData = Data.getData().slice(StartAugmentationOffset, 6173ca95b02SDimitry Andric EndAugmentationOffset); 6183ca95b02SDimitry Andric } 6193ca95b02SDimitry Andric } 6203ca95b02SDimitry Andric 621d88c1a5aSDimitry Andric auto Cie = llvm::make_unique<CIE>(StartOffset, Length, Version, 6223ca95b02SDimitry Andric AugmentationString, AddressSize, 623d88c1a5aSDimitry Andric SegmentDescriptorSize, 624d88c1a5aSDimitry Andric CodeAlignmentFactor, 625d88c1a5aSDimitry Andric DataAlignmentFactor, 626d88c1a5aSDimitry Andric ReturnAddressRegister, 6273ca95b02SDimitry Andric AugmentationData, FDEPointerEncoding, 6283ca95b02SDimitry Andric LSDAPointerEncoding); 629ff0cc061SDimitry Andric CIEs[StartOffset] = Cie.get(); 630ff0cc061SDimitry Andric Entries.emplace_back(std::move(Cie)); 631ff0cc061SDimitry Andric } else { 632ff0cc061SDimitry Andric // FDE 633ff0cc061SDimitry Andric uint64_t CIEPointer = Id; 6343ca95b02SDimitry Andric uint64_t InitialLocation = 0; 6353ca95b02SDimitry Andric uint64_t AddressRange = 0; 6363ca95b02SDimitry Andric CIE *Cie = CIEs[IsEH ? (StartStructureOffset - CIEPointer) : CIEPointer]; 6373ca95b02SDimitry Andric 6383ca95b02SDimitry Andric if (IsEH) { 6393ca95b02SDimitry Andric // The address size is encoded in the CIE we reference. 6403ca95b02SDimitry Andric if (!Cie) 6413ca95b02SDimitry Andric ReportError("Parsing FDE data at %lx failed due to missing CIE"); 6423ca95b02SDimitry Andric 6433ca95b02SDimitry Andric InitialLocation = readPointer(Data, Offset, 6443ca95b02SDimitry Andric Cie->getFDEPointerEncoding()); 6453ca95b02SDimitry Andric AddressRange = readPointer(Data, Offset, 6463ca95b02SDimitry Andric Cie->getFDEPointerEncoding()); 6473ca95b02SDimitry Andric 6483ca95b02SDimitry Andric StringRef AugmentationString = Cie->getAugmentationString(); 6493ca95b02SDimitry Andric if (!AugmentationString.empty()) { 6503ca95b02SDimitry Andric // Parse the augmentation length and data for this FDE. 6513ca95b02SDimitry Andric uint64_t AugmentationLength = Data.getULEB128(&Offset); 6523ca95b02SDimitry Andric 6533ca95b02SDimitry Andric uint32_t EndAugmentationOffset = 6543ca95b02SDimitry Andric Offset + static_cast<uint32_t>(AugmentationLength); 6553ca95b02SDimitry Andric 6563ca95b02SDimitry Andric // Decode the LSDA if the CIE augmentation string said we should. 6573ca95b02SDimitry Andric if (Cie->getLSDAPointerEncoding() != DW_EH_PE_omit) 6583ca95b02SDimitry Andric readPointer(Data, Offset, Cie->getLSDAPointerEncoding()); 6593ca95b02SDimitry Andric 6603ca95b02SDimitry Andric if (Offset != EndAugmentationOffset) 6613ca95b02SDimitry Andric ReportError("Parsing augmentation data at %lx failed"); 6623ca95b02SDimitry Andric } 6633ca95b02SDimitry Andric } else { 6643ca95b02SDimitry Andric InitialLocation = Data.getAddress(&Offset); 6653ca95b02SDimitry Andric AddressRange = Data.getAddress(&Offset); 6663ca95b02SDimitry Andric } 667ff0cc061SDimitry Andric 668ff0cc061SDimitry Andric Entries.emplace_back(new FDE(StartOffset, Length, CIEPointer, 669ff0cc061SDimitry Andric InitialLocation, AddressRange, 6703ca95b02SDimitry Andric Cie)); 671ff0cc061SDimitry Andric } 672ff0cc061SDimitry Andric 673ff0cc061SDimitry Andric Entries.back()->parseInstructions(Data, &Offset, EndStructureOffset); 674ff0cc061SDimitry Andric 6753ca95b02SDimitry Andric if (Offset != EndStructureOffset) 6763ca95b02SDimitry Andric ReportError("Parsing entry instructions at %lx failed"); 677ff0cc061SDimitry Andric } 678ff0cc061SDimitry Andric } 679ff0cc061SDimitry Andric 680ff0cc061SDimitry Andric void DWARFDebugFrame::dump(raw_ostream &OS) const { 681ff0cc061SDimitry Andric OS << "\n"; 682ff0cc061SDimitry Andric for (const auto &Entry : Entries) { 683ff0cc061SDimitry Andric Entry->dumpHeader(OS); 684ff0cc061SDimitry Andric Entry->dumpInstructions(OS); 685ff0cc061SDimitry Andric OS << "\n"; 686ff0cc061SDimitry Andric } 687ff0cc061SDimitry Andric } 688