1ff0cc061SDimitry Andric //===-- DWARFDebugFrame.h - Parsing of .debug_frame -------------*- C++ -*-===// 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/DebugInfo/DWARF/DWARFDebugFrame.h" 11ff0cc061SDimitry Andric #include "llvm/ADT/ArrayRef.h" 12ff0cc061SDimitry Andric #include "llvm/ADT/DenseMap.h" 133ca95b02SDimitry Andric #include "llvm/ADT/Optional.h" 14ff0cc061SDimitry Andric #include "llvm/ADT/SmallString.h" 153ca95b02SDimitry Andric #include "llvm/ADT/StringExtras.h" 16ff0cc061SDimitry Andric #include "llvm/Support/Casting.h" 17ff0cc061SDimitry Andric #include "llvm/Support/DataTypes.h" 18ff0cc061SDimitry Andric #include "llvm/Support/Dwarf.h" 19ff0cc061SDimitry Andric #include "llvm/Support/ErrorHandling.h" 20ff0cc061SDimitry Andric #include "llvm/Support/Format.h" 21ff0cc061SDimitry Andric #include "llvm/Support/raw_ostream.h" 22ff0cc061SDimitry Andric #include <string> 233ca95b02SDimitry Andric #include <utility> 24ff0cc061SDimitry Andric #include <vector> 25ff0cc061SDimitry Andric 26ff0cc061SDimitry Andric using namespace llvm; 27ff0cc061SDimitry Andric using namespace dwarf; 28ff0cc061SDimitry Andric 29ff0cc061SDimitry Andric 30ff0cc061SDimitry Andric /// \brief Abstract frame entry defining the common interface concrete 31ff0cc061SDimitry Andric /// entries implement. 32ff0cc061SDimitry Andric class llvm::FrameEntry { 33ff0cc061SDimitry Andric public: 34ff0cc061SDimitry Andric enum FrameKind {FK_CIE, FK_FDE}; 35ff0cc061SDimitry Andric FrameEntry(FrameKind K, uint64_t Offset, uint64_t Length) 36ff0cc061SDimitry Andric : Kind(K), Offset(Offset), Length(Length) {} 37ff0cc061SDimitry Andric 38ff0cc061SDimitry Andric virtual ~FrameEntry() { 39ff0cc061SDimitry Andric } 40ff0cc061SDimitry Andric 41ff0cc061SDimitry Andric FrameKind getKind() const { return Kind; } 42ff0cc061SDimitry Andric virtual uint64_t getOffset() const { return Offset; } 43ff0cc061SDimitry Andric 44ff0cc061SDimitry Andric /// \brief Parse and store a sequence of CFI instructions from Data, 45ff0cc061SDimitry Andric /// starting at *Offset and ending at EndOffset. If everything 46ff0cc061SDimitry Andric /// goes well, *Offset should be equal to EndOffset when this method 47ff0cc061SDimitry Andric /// returns. Otherwise, an error occurred. 48ff0cc061SDimitry Andric virtual void parseInstructions(DataExtractor Data, uint32_t *Offset, 49ff0cc061SDimitry Andric uint32_t EndOffset); 50ff0cc061SDimitry Andric 51ff0cc061SDimitry Andric /// \brief Dump the entry header to the given output stream. 52ff0cc061SDimitry Andric virtual void dumpHeader(raw_ostream &OS) const = 0; 53ff0cc061SDimitry Andric 54ff0cc061SDimitry Andric /// \brief Dump the entry's instructions to the given output stream. 55ff0cc061SDimitry Andric virtual void dumpInstructions(raw_ostream &OS) const; 56ff0cc061SDimitry Andric 57ff0cc061SDimitry Andric protected: 58ff0cc061SDimitry Andric const FrameKind Kind; 59ff0cc061SDimitry Andric 60ff0cc061SDimitry Andric /// \brief Offset of this entry in the section. 61ff0cc061SDimitry Andric uint64_t Offset; 62ff0cc061SDimitry Andric 63ff0cc061SDimitry Andric /// \brief Entry length as specified in DWARF. 64ff0cc061SDimitry Andric uint64_t Length; 65ff0cc061SDimitry Andric 66ff0cc061SDimitry Andric /// An entry may contain CFI instructions. An instruction consists of an 67ff0cc061SDimitry Andric /// opcode and an optional sequence of operands. 68ff0cc061SDimitry Andric typedef std::vector<uint64_t> Operands; 69ff0cc061SDimitry Andric struct Instruction { 70ff0cc061SDimitry Andric Instruction(uint8_t Opcode) 71ff0cc061SDimitry Andric : Opcode(Opcode) 72ff0cc061SDimitry Andric {} 73ff0cc061SDimitry Andric 74ff0cc061SDimitry Andric uint8_t Opcode; 75ff0cc061SDimitry Andric Operands Ops; 76ff0cc061SDimitry Andric }; 77ff0cc061SDimitry Andric 78ff0cc061SDimitry Andric std::vector<Instruction> Instructions; 79ff0cc061SDimitry Andric 80ff0cc061SDimitry Andric /// Convenience methods to add a new instruction with the given opcode and 81ff0cc061SDimitry Andric /// operands to the Instructions vector. 82ff0cc061SDimitry Andric void addInstruction(uint8_t Opcode) { 83ff0cc061SDimitry Andric Instructions.push_back(Instruction(Opcode)); 84ff0cc061SDimitry Andric } 85ff0cc061SDimitry Andric 86ff0cc061SDimitry Andric void addInstruction(uint8_t Opcode, uint64_t Operand1) { 87ff0cc061SDimitry Andric Instructions.push_back(Instruction(Opcode)); 88ff0cc061SDimitry Andric Instructions.back().Ops.push_back(Operand1); 89ff0cc061SDimitry Andric } 90ff0cc061SDimitry Andric 91ff0cc061SDimitry Andric void addInstruction(uint8_t Opcode, uint64_t Operand1, uint64_t Operand2) { 92ff0cc061SDimitry Andric Instructions.push_back(Instruction(Opcode)); 93ff0cc061SDimitry Andric Instructions.back().Ops.push_back(Operand1); 94ff0cc061SDimitry Andric Instructions.back().Ops.push_back(Operand2); 95ff0cc061SDimitry Andric } 96ff0cc061SDimitry Andric }; 97ff0cc061SDimitry Andric 98ff0cc061SDimitry Andric 99ff0cc061SDimitry Andric // See DWARF standard v3, section 7.23 100ff0cc061SDimitry Andric const uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK = 0xc0; 101ff0cc061SDimitry Andric const uint8_t DWARF_CFI_PRIMARY_OPERAND_MASK = 0x3f; 102ff0cc061SDimitry Andric 103ff0cc061SDimitry Andric void FrameEntry::parseInstructions(DataExtractor Data, uint32_t *Offset, 104ff0cc061SDimitry Andric uint32_t EndOffset) { 105ff0cc061SDimitry Andric while (*Offset < EndOffset) { 106ff0cc061SDimitry Andric uint8_t Opcode = Data.getU8(Offset); 107ff0cc061SDimitry Andric // Some instructions have a primary opcode encoded in the top bits. 108ff0cc061SDimitry Andric uint8_t Primary = Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK; 109ff0cc061SDimitry Andric 110ff0cc061SDimitry Andric if (Primary) { 111ff0cc061SDimitry Andric // If it's a primary opcode, the first operand is encoded in the bottom 112ff0cc061SDimitry Andric // bits of the opcode itself. 113ff0cc061SDimitry Andric uint64_t Op1 = Opcode & DWARF_CFI_PRIMARY_OPERAND_MASK; 114ff0cc061SDimitry Andric switch (Primary) { 115ff0cc061SDimitry Andric default: llvm_unreachable("Impossible primary CFI opcode"); 116ff0cc061SDimitry Andric case DW_CFA_advance_loc: 117ff0cc061SDimitry Andric case DW_CFA_restore: 118ff0cc061SDimitry Andric addInstruction(Primary, Op1); 119ff0cc061SDimitry Andric break; 120ff0cc061SDimitry Andric case DW_CFA_offset: 121ff0cc061SDimitry Andric addInstruction(Primary, Op1, Data.getULEB128(Offset)); 122ff0cc061SDimitry Andric break; 123ff0cc061SDimitry Andric } 124ff0cc061SDimitry Andric } else { 125ff0cc061SDimitry Andric // Extended opcode - its value is Opcode itself. 126ff0cc061SDimitry Andric switch (Opcode) { 127ff0cc061SDimitry Andric default: llvm_unreachable("Invalid extended CFI opcode"); 128ff0cc061SDimitry Andric case DW_CFA_nop: 129ff0cc061SDimitry Andric case DW_CFA_remember_state: 130ff0cc061SDimitry Andric case DW_CFA_restore_state: 131ff0cc061SDimitry Andric case DW_CFA_GNU_window_save: 132ff0cc061SDimitry Andric // No operands 133ff0cc061SDimitry Andric addInstruction(Opcode); 134ff0cc061SDimitry Andric break; 135ff0cc061SDimitry Andric case DW_CFA_set_loc: 136ff0cc061SDimitry Andric // Operands: Address 137ff0cc061SDimitry Andric addInstruction(Opcode, Data.getAddress(Offset)); 138ff0cc061SDimitry Andric break; 139ff0cc061SDimitry Andric case DW_CFA_advance_loc1: 140ff0cc061SDimitry Andric // Operands: 1-byte delta 141ff0cc061SDimitry Andric addInstruction(Opcode, Data.getU8(Offset)); 142ff0cc061SDimitry Andric break; 143ff0cc061SDimitry Andric case DW_CFA_advance_loc2: 144ff0cc061SDimitry Andric // Operands: 2-byte delta 145ff0cc061SDimitry Andric addInstruction(Opcode, Data.getU16(Offset)); 146ff0cc061SDimitry Andric break; 147ff0cc061SDimitry Andric case DW_CFA_advance_loc4: 148ff0cc061SDimitry Andric // Operands: 4-byte delta 149ff0cc061SDimitry Andric addInstruction(Opcode, Data.getU32(Offset)); 150ff0cc061SDimitry Andric break; 151ff0cc061SDimitry Andric case DW_CFA_restore_extended: 152ff0cc061SDimitry Andric case DW_CFA_undefined: 153ff0cc061SDimitry Andric case DW_CFA_same_value: 154ff0cc061SDimitry Andric case DW_CFA_def_cfa_register: 155ff0cc061SDimitry Andric case DW_CFA_def_cfa_offset: 156ff0cc061SDimitry Andric // Operands: ULEB128 157ff0cc061SDimitry Andric addInstruction(Opcode, Data.getULEB128(Offset)); 158ff0cc061SDimitry Andric break; 159ff0cc061SDimitry Andric case DW_CFA_def_cfa_offset_sf: 160ff0cc061SDimitry Andric // Operands: SLEB128 161ff0cc061SDimitry Andric addInstruction(Opcode, Data.getSLEB128(Offset)); 162ff0cc061SDimitry Andric break; 163ff0cc061SDimitry Andric case DW_CFA_offset_extended: 164ff0cc061SDimitry Andric case DW_CFA_register: 165ff0cc061SDimitry Andric case DW_CFA_def_cfa: 1663ca95b02SDimitry Andric case DW_CFA_val_offset: { 167ff0cc061SDimitry Andric // Operands: ULEB128, ULEB128 1683ca95b02SDimitry Andric // Note: We can not embed getULEB128 directly into function 1693ca95b02SDimitry Andric // argument list. getULEB128 changes Offset and order of evaluation 1703ca95b02SDimitry Andric // for arguments is unspecified. 1713ca95b02SDimitry Andric auto op1 = Data.getULEB128(Offset); 1723ca95b02SDimitry Andric auto op2 = Data.getULEB128(Offset); 1733ca95b02SDimitry Andric addInstruction(Opcode, op1, op2); 174ff0cc061SDimitry Andric break; 1753ca95b02SDimitry Andric } 176ff0cc061SDimitry Andric case DW_CFA_offset_extended_sf: 177ff0cc061SDimitry Andric case DW_CFA_def_cfa_sf: 1783ca95b02SDimitry Andric case DW_CFA_val_offset_sf: { 179ff0cc061SDimitry Andric // Operands: ULEB128, SLEB128 1803ca95b02SDimitry Andric // Note: see comment for the previous case 1813ca95b02SDimitry Andric auto op1 = Data.getULEB128(Offset); 1823ca95b02SDimitry Andric auto op2 = (uint64_t)Data.getSLEB128(Offset); 1833ca95b02SDimitry Andric addInstruction(Opcode, op1, op2); 184ff0cc061SDimitry Andric break; 1853ca95b02SDimitry Andric } 186ff0cc061SDimitry Andric case DW_CFA_def_cfa_expression: 187ff0cc061SDimitry Andric case DW_CFA_expression: 188ff0cc061SDimitry Andric case DW_CFA_val_expression: 189ff0cc061SDimitry Andric // TODO: implement this 190ff0cc061SDimitry Andric report_fatal_error("Values with expressions not implemented yet!"); 191ff0cc061SDimitry Andric } 192ff0cc061SDimitry Andric } 193ff0cc061SDimitry Andric } 194ff0cc061SDimitry Andric } 195ff0cc061SDimitry Andric 196ff0cc061SDimitry Andric namespace { 197ff0cc061SDimitry Andric /// \brief DWARF Common Information Entry (CIE) 198ff0cc061SDimitry Andric class CIE : public FrameEntry { 199ff0cc061SDimitry Andric public: 200ff0cc061SDimitry Andric // CIEs (and FDEs) are simply container classes, so the only sensible way to 201ff0cc061SDimitry Andric // create them is by providing the full parsed contents in the constructor. 202ff0cc061SDimitry Andric CIE(uint64_t Offset, uint64_t Length, uint8_t Version, 203ff0cc061SDimitry Andric SmallString<8> Augmentation, uint8_t AddressSize, 204ff0cc061SDimitry Andric uint8_t SegmentDescriptorSize, uint64_t CodeAlignmentFactor, 2053ca95b02SDimitry Andric int64_t DataAlignmentFactor, uint64_t ReturnAddressRegister, 2063ca95b02SDimitry Andric SmallString<8> AugmentationData, uint32_t FDEPointerEncoding, 2073ca95b02SDimitry Andric uint32_t LSDAPointerEncoding) 208ff0cc061SDimitry Andric : FrameEntry(FK_CIE, Offset, Length), Version(Version), 2093ca95b02SDimitry Andric Augmentation(std::move(Augmentation)), AddressSize(AddressSize), 210ff0cc061SDimitry Andric SegmentDescriptorSize(SegmentDescriptorSize), 211ff0cc061SDimitry Andric CodeAlignmentFactor(CodeAlignmentFactor), 212ff0cc061SDimitry Andric DataAlignmentFactor(DataAlignmentFactor), 2133ca95b02SDimitry Andric ReturnAddressRegister(ReturnAddressRegister), 2143ca95b02SDimitry Andric AugmentationData(std::move(AugmentationData)), 2153ca95b02SDimitry Andric FDEPointerEncoding(FDEPointerEncoding), 2163ca95b02SDimitry Andric LSDAPointerEncoding(LSDAPointerEncoding) {} 217ff0cc061SDimitry Andric 218ff0cc061SDimitry Andric ~CIE() override {} 219ff0cc061SDimitry Andric 2203ca95b02SDimitry Andric StringRef getAugmentationString() const { return Augmentation; } 221ff0cc061SDimitry Andric uint64_t getCodeAlignmentFactor() const { return CodeAlignmentFactor; } 222ff0cc061SDimitry Andric int64_t getDataAlignmentFactor() const { return DataAlignmentFactor; } 2233ca95b02SDimitry Andric uint32_t getFDEPointerEncoding() const { 2243ca95b02SDimitry Andric return FDEPointerEncoding; 2253ca95b02SDimitry Andric } 2263ca95b02SDimitry Andric uint32_t getLSDAPointerEncoding() const { 2273ca95b02SDimitry Andric return LSDAPointerEncoding; 2283ca95b02SDimitry Andric } 229ff0cc061SDimitry Andric 230ff0cc061SDimitry Andric void dumpHeader(raw_ostream &OS) const override { 231ff0cc061SDimitry Andric OS << format("%08x %08x %08x CIE", 232ff0cc061SDimitry Andric (uint32_t)Offset, (uint32_t)Length, DW_CIE_ID) 233ff0cc061SDimitry Andric << "\n"; 234ff0cc061SDimitry Andric OS << format(" Version: %d\n", Version); 235ff0cc061SDimitry Andric OS << " Augmentation: \"" << Augmentation << "\"\n"; 236ff0cc061SDimitry Andric if (Version >= 4) { 237ff0cc061SDimitry Andric OS << format(" Address size: %u\n", 238ff0cc061SDimitry Andric (uint32_t)AddressSize); 239ff0cc061SDimitry Andric OS << format(" Segment desc size: %u\n", 240ff0cc061SDimitry Andric (uint32_t)SegmentDescriptorSize); 241ff0cc061SDimitry Andric } 242ff0cc061SDimitry Andric OS << format(" Code alignment factor: %u\n", 243ff0cc061SDimitry Andric (uint32_t)CodeAlignmentFactor); 244ff0cc061SDimitry Andric OS << format(" Data alignment factor: %d\n", 245ff0cc061SDimitry Andric (int32_t)DataAlignmentFactor); 246ff0cc061SDimitry Andric OS << format(" Return address column: %d\n", 247ff0cc061SDimitry Andric (int32_t)ReturnAddressRegister); 2483ca95b02SDimitry Andric if (!AugmentationData.empty()) { 2493ca95b02SDimitry Andric OS << " Augmentation data: "; 2503ca95b02SDimitry Andric for (uint8_t Byte : AugmentationData) 2513ca95b02SDimitry Andric OS << ' ' << hexdigit(Byte >> 4) << hexdigit(Byte & 0xf); 2523ca95b02SDimitry Andric OS << "\n"; 2533ca95b02SDimitry Andric } 254ff0cc061SDimitry Andric OS << "\n"; 255ff0cc061SDimitry Andric } 256ff0cc061SDimitry Andric 257ff0cc061SDimitry Andric static bool classof(const FrameEntry *FE) { 258ff0cc061SDimitry Andric return FE->getKind() == FK_CIE; 259ff0cc061SDimitry Andric } 260ff0cc061SDimitry Andric 261ff0cc061SDimitry Andric private: 262ff0cc061SDimitry Andric /// The following fields are defined in section 6.4.1 of the DWARF standard v4 263ff0cc061SDimitry Andric uint8_t Version; 264ff0cc061SDimitry Andric SmallString<8> Augmentation; 265ff0cc061SDimitry Andric uint8_t AddressSize; 266ff0cc061SDimitry Andric uint8_t SegmentDescriptorSize; 267ff0cc061SDimitry Andric uint64_t CodeAlignmentFactor; 268ff0cc061SDimitry Andric int64_t DataAlignmentFactor; 269ff0cc061SDimitry Andric uint64_t ReturnAddressRegister; 2703ca95b02SDimitry Andric 2713ca95b02SDimitry Andric // The following are used when the CIE represents an EH frame entry. 2723ca95b02SDimitry Andric SmallString<8> AugmentationData; 2733ca95b02SDimitry Andric uint32_t FDEPointerEncoding; 2743ca95b02SDimitry Andric uint32_t LSDAPointerEncoding; 275ff0cc061SDimitry Andric }; 276ff0cc061SDimitry Andric 277ff0cc061SDimitry Andric 278ff0cc061SDimitry Andric /// \brief DWARF Frame Description Entry (FDE) 279ff0cc061SDimitry Andric class FDE : public FrameEntry { 280ff0cc061SDimitry Andric public: 281ff0cc061SDimitry Andric // Each FDE has a CIE it's "linked to". Our FDE contains is constructed with 282ff0cc061SDimitry Andric // an offset to the CIE (provided by parsing the FDE header). The CIE itself 283ff0cc061SDimitry Andric // is obtained lazily once it's actually required. 284ff0cc061SDimitry Andric FDE(uint64_t Offset, uint64_t Length, int64_t LinkedCIEOffset, 285ff0cc061SDimitry Andric uint64_t InitialLocation, uint64_t AddressRange, 286ff0cc061SDimitry Andric CIE *Cie) 287ff0cc061SDimitry Andric : FrameEntry(FK_FDE, Offset, Length), LinkedCIEOffset(LinkedCIEOffset), 288ff0cc061SDimitry Andric InitialLocation(InitialLocation), AddressRange(AddressRange), 289ff0cc061SDimitry Andric LinkedCIE(Cie) {} 290ff0cc061SDimitry Andric 291ff0cc061SDimitry Andric ~FDE() override {} 292ff0cc061SDimitry Andric 293ff0cc061SDimitry Andric CIE *getLinkedCIE() const { return LinkedCIE; } 294ff0cc061SDimitry Andric 295ff0cc061SDimitry Andric void dumpHeader(raw_ostream &OS) const override { 296ff0cc061SDimitry Andric OS << format("%08x %08x %08x FDE ", 297ff0cc061SDimitry Andric (uint32_t)Offset, (uint32_t)Length, (int32_t)LinkedCIEOffset); 298ff0cc061SDimitry Andric OS << format("cie=%08x pc=%08x...%08x\n", 299ff0cc061SDimitry Andric (int32_t)LinkedCIEOffset, 300ff0cc061SDimitry Andric (uint32_t)InitialLocation, 301ff0cc061SDimitry Andric (uint32_t)InitialLocation + (uint32_t)AddressRange); 302ff0cc061SDimitry Andric } 303ff0cc061SDimitry Andric 304ff0cc061SDimitry Andric static bool classof(const FrameEntry *FE) { 305ff0cc061SDimitry Andric return FE->getKind() == FK_FDE; 306ff0cc061SDimitry Andric } 307ff0cc061SDimitry Andric 308ff0cc061SDimitry Andric private: 309ff0cc061SDimitry Andric /// The following fields are defined in section 6.4.1 of the DWARF standard v3 310ff0cc061SDimitry Andric uint64_t LinkedCIEOffset; 311ff0cc061SDimitry Andric uint64_t InitialLocation; 312ff0cc061SDimitry Andric uint64_t AddressRange; 313ff0cc061SDimitry Andric CIE *LinkedCIE; 314ff0cc061SDimitry Andric }; 315ff0cc061SDimitry Andric 316ff0cc061SDimitry Andric /// \brief Types of operands to CF instructions. 317ff0cc061SDimitry Andric enum OperandType { 318ff0cc061SDimitry Andric OT_Unset, 319ff0cc061SDimitry Andric OT_None, 320ff0cc061SDimitry Andric OT_Address, 321ff0cc061SDimitry Andric OT_Offset, 322ff0cc061SDimitry Andric OT_FactoredCodeOffset, 323ff0cc061SDimitry Andric OT_SignedFactDataOffset, 324ff0cc061SDimitry Andric OT_UnsignedFactDataOffset, 325ff0cc061SDimitry Andric OT_Register, 326ff0cc061SDimitry Andric OT_Expression 327ff0cc061SDimitry Andric }; 328ff0cc061SDimitry Andric 329ff0cc061SDimitry Andric } // end anonymous namespace 330ff0cc061SDimitry Andric 331ff0cc061SDimitry Andric /// \brief Initialize the array describing the types of operands. 332ff0cc061SDimitry Andric static ArrayRef<OperandType[2]> getOperandTypes() { 333ff0cc061SDimitry Andric static OperandType OpTypes[DW_CFA_restore+1][2]; 334ff0cc061SDimitry Andric 335ff0cc061SDimitry Andric #define DECLARE_OP2(OP, OPTYPE0, OPTYPE1) \ 336ff0cc061SDimitry Andric do { \ 337ff0cc061SDimitry Andric OpTypes[OP][0] = OPTYPE0; \ 338ff0cc061SDimitry Andric OpTypes[OP][1] = OPTYPE1; \ 339ff0cc061SDimitry Andric } while (0) 340ff0cc061SDimitry Andric #define DECLARE_OP1(OP, OPTYPE0) DECLARE_OP2(OP, OPTYPE0, OT_None) 341ff0cc061SDimitry Andric #define DECLARE_OP0(OP) DECLARE_OP1(OP, OT_None) 342ff0cc061SDimitry Andric 343ff0cc061SDimitry Andric DECLARE_OP1(DW_CFA_set_loc, OT_Address); 344ff0cc061SDimitry Andric DECLARE_OP1(DW_CFA_advance_loc, OT_FactoredCodeOffset); 345ff0cc061SDimitry Andric DECLARE_OP1(DW_CFA_advance_loc1, OT_FactoredCodeOffset); 346ff0cc061SDimitry Andric DECLARE_OP1(DW_CFA_advance_loc2, OT_FactoredCodeOffset); 347ff0cc061SDimitry Andric DECLARE_OP1(DW_CFA_advance_loc4, OT_FactoredCodeOffset); 348ff0cc061SDimitry Andric DECLARE_OP1(DW_CFA_MIPS_advance_loc8, OT_FactoredCodeOffset); 349ff0cc061SDimitry Andric DECLARE_OP2(DW_CFA_def_cfa, OT_Register, OT_Offset); 350ff0cc061SDimitry Andric DECLARE_OP2(DW_CFA_def_cfa_sf, OT_Register, OT_SignedFactDataOffset); 351ff0cc061SDimitry Andric DECLARE_OP1(DW_CFA_def_cfa_register, OT_Register); 352ff0cc061SDimitry Andric DECLARE_OP1(DW_CFA_def_cfa_offset, OT_Offset); 353ff0cc061SDimitry Andric DECLARE_OP1(DW_CFA_def_cfa_offset_sf, OT_SignedFactDataOffset); 354ff0cc061SDimitry Andric DECLARE_OP1(DW_CFA_def_cfa_expression, OT_Expression); 355ff0cc061SDimitry Andric DECLARE_OP1(DW_CFA_undefined, OT_Register); 356ff0cc061SDimitry Andric DECLARE_OP1(DW_CFA_same_value, OT_Register); 357ff0cc061SDimitry Andric DECLARE_OP2(DW_CFA_offset, OT_Register, OT_UnsignedFactDataOffset); 358ff0cc061SDimitry Andric DECLARE_OP2(DW_CFA_offset_extended, OT_Register, OT_UnsignedFactDataOffset); 359ff0cc061SDimitry Andric DECLARE_OP2(DW_CFA_offset_extended_sf, OT_Register, OT_SignedFactDataOffset); 360ff0cc061SDimitry Andric DECLARE_OP2(DW_CFA_val_offset, OT_Register, OT_UnsignedFactDataOffset); 361ff0cc061SDimitry Andric DECLARE_OP2(DW_CFA_val_offset_sf, OT_Register, OT_SignedFactDataOffset); 362ff0cc061SDimitry Andric DECLARE_OP2(DW_CFA_register, OT_Register, OT_Register); 363ff0cc061SDimitry Andric DECLARE_OP2(DW_CFA_expression, OT_Register, OT_Expression); 364ff0cc061SDimitry Andric DECLARE_OP2(DW_CFA_val_expression, OT_Register, OT_Expression); 365ff0cc061SDimitry Andric DECLARE_OP1(DW_CFA_restore, OT_Register); 366ff0cc061SDimitry Andric DECLARE_OP1(DW_CFA_restore_extended, OT_Register); 367ff0cc061SDimitry Andric DECLARE_OP0(DW_CFA_remember_state); 368ff0cc061SDimitry Andric DECLARE_OP0(DW_CFA_restore_state); 369ff0cc061SDimitry Andric DECLARE_OP0(DW_CFA_GNU_window_save); 370ff0cc061SDimitry Andric DECLARE_OP1(DW_CFA_GNU_args_size, OT_Offset); 371ff0cc061SDimitry Andric DECLARE_OP0(DW_CFA_nop); 372ff0cc061SDimitry Andric 373ff0cc061SDimitry Andric #undef DECLARE_OP0 374ff0cc061SDimitry Andric #undef DECLARE_OP1 375ff0cc061SDimitry Andric #undef DECLARE_OP2 376ff0cc061SDimitry Andric return ArrayRef<OperandType[2]>(&OpTypes[0], DW_CFA_restore+1); 377ff0cc061SDimitry Andric } 378ff0cc061SDimitry Andric 379ff0cc061SDimitry Andric static ArrayRef<OperandType[2]> OpTypes = getOperandTypes(); 380ff0cc061SDimitry Andric 381ff0cc061SDimitry Andric /// \brief Print \p Opcode's operand number \p OperandIdx which has 382ff0cc061SDimitry Andric /// value \p Operand. 383ff0cc061SDimitry Andric static void printOperand(raw_ostream &OS, uint8_t Opcode, unsigned OperandIdx, 384ff0cc061SDimitry Andric uint64_t Operand, uint64_t CodeAlignmentFactor, 385ff0cc061SDimitry Andric int64_t DataAlignmentFactor) { 386ff0cc061SDimitry Andric assert(OperandIdx < 2); 387ff0cc061SDimitry Andric OperandType Type = OpTypes[Opcode][OperandIdx]; 388ff0cc061SDimitry Andric 389ff0cc061SDimitry Andric switch (Type) { 390ff0cc061SDimitry Andric case OT_Unset: 391ff0cc061SDimitry Andric OS << " Unsupported " << (OperandIdx ? "second" : "first") << " operand to"; 392ff0cc061SDimitry Andric if (const char *OpcodeName = CallFrameString(Opcode)) 393ff0cc061SDimitry Andric OS << " " << OpcodeName; 394ff0cc061SDimitry Andric else 395ff0cc061SDimitry Andric OS << format(" Opcode %x", Opcode); 396ff0cc061SDimitry Andric break; 397ff0cc061SDimitry Andric case OT_None: 398ff0cc061SDimitry Andric break; 399ff0cc061SDimitry Andric case OT_Address: 400ff0cc061SDimitry Andric OS << format(" %" PRIx64, Operand); 401ff0cc061SDimitry Andric break; 402ff0cc061SDimitry Andric case OT_Offset: 403ff0cc061SDimitry Andric // The offsets are all encoded in a unsigned form, but in practice 404ff0cc061SDimitry Andric // consumers use them signed. It's most certainly legacy due to 405ff0cc061SDimitry Andric // the lack of signed variants in the first Dwarf standards. 406ff0cc061SDimitry Andric OS << format(" %+" PRId64, int64_t(Operand)); 407ff0cc061SDimitry Andric break; 408ff0cc061SDimitry Andric case OT_FactoredCodeOffset: // Always Unsigned 409ff0cc061SDimitry Andric if (CodeAlignmentFactor) 410ff0cc061SDimitry Andric OS << format(" %" PRId64, Operand * CodeAlignmentFactor); 411ff0cc061SDimitry Andric else 412ff0cc061SDimitry Andric OS << format(" %" PRId64 "*code_alignment_factor" , Operand); 413ff0cc061SDimitry Andric break; 414ff0cc061SDimitry Andric case OT_SignedFactDataOffset: 415ff0cc061SDimitry Andric if (DataAlignmentFactor) 416ff0cc061SDimitry Andric OS << format(" %" PRId64, int64_t(Operand) * DataAlignmentFactor); 417ff0cc061SDimitry Andric else 418ff0cc061SDimitry Andric OS << format(" %" PRId64 "*data_alignment_factor" , int64_t(Operand)); 419ff0cc061SDimitry Andric break; 420ff0cc061SDimitry Andric case OT_UnsignedFactDataOffset: 421ff0cc061SDimitry Andric if (DataAlignmentFactor) 422ff0cc061SDimitry Andric OS << format(" %" PRId64, Operand * DataAlignmentFactor); 423ff0cc061SDimitry Andric else 424ff0cc061SDimitry Andric OS << format(" %" PRId64 "*data_alignment_factor" , Operand); 425ff0cc061SDimitry Andric break; 426ff0cc061SDimitry Andric case OT_Register: 427ff0cc061SDimitry Andric OS << format(" reg%" PRId64, Operand); 428ff0cc061SDimitry Andric break; 429ff0cc061SDimitry Andric case OT_Expression: 430ff0cc061SDimitry Andric OS << " expression"; 431ff0cc061SDimitry Andric break; 432ff0cc061SDimitry Andric } 433ff0cc061SDimitry Andric } 434ff0cc061SDimitry Andric 435ff0cc061SDimitry Andric void FrameEntry::dumpInstructions(raw_ostream &OS) const { 436ff0cc061SDimitry Andric uint64_t CodeAlignmentFactor = 0; 437ff0cc061SDimitry Andric int64_t DataAlignmentFactor = 0; 438ff0cc061SDimitry Andric const CIE *Cie = dyn_cast<CIE>(this); 439ff0cc061SDimitry Andric 440ff0cc061SDimitry Andric if (!Cie) 441ff0cc061SDimitry Andric Cie = cast<FDE>(this)->getLinkedCIE(); 442ff0cc061SDimitry Andric if (Cie) { 443ff0cc061SDimitry Andric CodeAlignmentFactor = Cie->getCodeAlignmentFactor(); 444ff0cc061SDimitry Andric DataAlignmentFactor = Cie->getDataAlignmentFactor(); 445ff0cc061SDimitry Andric } 446ff0cc061SDimitry Andric 447ff0cc061SDimitry Andric for (const auto &Instr : Instructions) { 448ff0cc061SDimitry Andric uint8_t Opcode = Instr.Opcode; 449ff0cc061SDimitry Andric if (Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK) 450ff0cc061SDimitry Andric Opcode &= DWARF_CFI_PRIMARY_OPCODE_MASK; 451ff0cc061SDimitry Andric OS << " " << CallFrameString(Opcode) << ":"; 452ff0cc061SDimitry Andric for (unsigned i = 0; i < Instr.Ops.size(); ++i) 453ff0cc061SDimitry Andric printOperand(OS, Opcode, i, Instr.Ops[i], CodeAlignmentFactor, 454ff0cc061SDimitry Andric DataAlignmentFactor); 455ff0cc061SDimitry Andric OS << '\n'; 456ff0cc061SDimitry Andric } 457ff0cc061SDimitry Andric } 458ff0cc061SDimitry Andric 4593ca95b02SDimitry Andric DWARFDebugFrame::DWARFDebugFrame(bool IsEH) : IsEH(IsEH) { 460ff0cc061SDimitry Andric } 461ff0cc061SDimitry Andric 462ff0cc061SDimitry Andric DWARFDebugFrame::~DWARFDebugFrame() { 463ff0cc061SDimitry Andric } 464ff0cc061SDimitry Andric 465ff0cc061SDimitry Andric static void LLVM_ATTRIBUTE_UNUSED dumpDataAux(DataExtractor Data, 466ff0cc061SDimitry Andric uint32_t Offset, int Length) { 467ff0cc061SDimitry Andric errs() << "DUMP: "; 468ff0cc061SDimitry Andric for (int i = 0; i < Length; ++i) { 469ff0cc061SDimitry Andric uint8_t c = Data.getU8(&Offset); 470ff0cc061SDimitry Andric errs().write_hex(c); errs() << " "; 471ff0cc061SDimitry Andric } 472ff0cc061SDimitry Andric errs() << "\n"; 473ff0cc061SDimitry Andric } 474ff0cc061SDimitry Andric 4753ca95b02SDimitry Andric static unsigned getSizeForEncoding(const DataExtractor &Data, 4763ca95b02SDimitry Andric unsigned symbolEncoding) { 4773ca95b02SDimitry Andric unsigned format = symbolEncoding & 0x0f; 4783ca95b02SDimitry Andric switch (format) { 4793ca95b02SDimitry Andric default: llvm_unreachable("Unknown Encoding"); 4803ca95b02SDimitry Andric case dwarf::DW_EH_PE_absptr: 4813ca95b02SDimitry Andric case dwarf::DW_EH_PE_signed: 4823ca95b02SDimitry Andric return Data.getAddressSize(); 4833ca95b02SDimitry Andric case dwarf::DW_EH_PE_udata2: 4843ca95b02SDimitry Andric case dwarf::DW_EH_PE_sdata2: 4853ca95b02SDimitry Andric return 2; 4863ca95b02SDimitry Andric case dwarf::DW_EH_PE_udata4: 4873ca95b02SDimitry Andric case dwarf::DW_EH_PE_sdata4: 4883ca95b02SDimitry Andric return 4; 4893ca95b02SDimitry Andric case dwarf::DW_EH_PE_udata8: 4903ca95b02SDimitry Andric case dwarf::DW_EH_PE_sdata8: 4913ca95b02SDimitry Andric return 8; 4923ca95b02SDimitry Andric } 4933ca95b02SDimitry Andric } 4943ca95b02SDimitry Andric 4953ca95b02SDimitry Andric static uint64_t readPointer(const DataExtractor &Data, uint32_t &Offset, 4963ca95b02SDimitry Andric unsigned Encoding) { 4973ca95b02SDimitry Andric switch (getSizeForEncoding(Data, Encoding)) { 4983ca95b02SDimitry Andric case 2: 4993ca95b02SDimitry Andric return Data.getU16(&Offset); 5003ca95b02SDimitry Andric case 4: 5013ca95b02SDimitry Andric return Data.getU32(&Offset); 5023ca95b02SDimitry Andric case 8: 5033ca95b02SDimitry Andric return Data.getU64(&Offset); 5043ca95b02SDimitry Andric default: 5053ca95b02SDimitry Andric llvm_unreachable("Illegal data size"); 5063ca95b02SDimitry Andric } 5073ca95b02SDimitry Andric } 508ff0cc061SDimitry Andric 509ff0cc061SDimitry Andric void DWARFDebugFrame::parse(DataExtractor Data) { 510ff0cc061SDimitry Andric uint32_t Offset = 0; 511ff0cc061SDimitry Andric DenseMap<uint32_t, CIE *> CIEs; 512ff0cc061SDimitry Andric 513ff0cc061SDimitry Andric while (Data.isValidOffset(Offset)) { 514ff0cc061SDimitry Andric uint32_t StartOffset = Offset; 515ff0cc061SDimitry Andric 5163ca95b02SDimitry Andric auto ReportError = [StartOffset](const char *ErrorMsg) { 5173ca95b02SDimitry Andric std::string Str; 5183ca95b02SDimitry Andric raw_string_ostream OS(Str); 5193ca95b02SDimitry Andric OS << format(ErrorMsg, StartOffset); 5203ca95b02SDimitry Andric OS.flush(); 5213ca95b02SDimitry Andric report_fatal_error(Str); 5223ca95b02SDimitry Andric }; 5233ca95b02SDimitry Andric 524ff0cc061SDimitry Andric bool IsDWARF64 = false; 525ff0cc061SDimitry Andric uint64_t Length = Data.getU32(&Offset); 526ff0cc061SDimitry Andric uint64_t Id; 527ff0cc061SDimitry Andric 528ff0cc061SDimitry Andric if (Length == UINT32_MAX) { 529ff0cc061SDimitry Andric // DWARF-64 is distinguished by the first 32 bits of the initial length 530ff0cc061SDimitry Andric // field being 0xffffffff. Then, the next 64 bits are the actual entry 531ff0cc061SDimitry Andric // length. 532ff0cc061SDimitry Andric IsDWARF64 = true; 533ff0cc061SDimitry Andric Length = Data.getU64(&Offset); 534ff0cc061SDimitry Andric } 535ff0cc061SDimitry Andric 536ff0cc061SDimitry Andric // At this point, Offset points to the next field after Length. 537ff0cc061SDimitry Andric // Length is the structure size excluding itself. Compute an offset one 538ff0cc061SDimitry Andric // past the end of the structure (needed to know how many instructions to 539ff0cc061SDimitry Andric // read). 540ff0cc061SDimitry Andric // TODO: For honest DWARF64 support, DataExtractor will have to treat 541ff0cc061SDimitry Andric // offset_ptr as uint64_t* 5423ca95b02SDimitry Andric uint32_t StartStructureOffset = Offset; 543ff0cc061SDimitry Andric uint32_t EndStructureOffset = Offset + static_cast<uint32_t>(Length); 544ff0cc061SDimitry Andric 545ff0cc061SDimitry Andric // The Id field's size depends on the DWARF format 5463ca95b02SDimitry Andric Id = Data.getUnsigned(&Offset, (IsDWARF64 && !IsEH) ? 8 : 4); 5473ca95b02SDimitry Andric bool IsCIE = ((IsDWARF64 && Id == DW64_CIE_ID) || 5483ca95b02SDimitry Andric Id == DW_CIE_ID || 5493ca95b02SDimitry Andric (IsEH && !Id)); 550ff0cc061SDimitry Andric 551ff0cc061SDimitry Andric if (IsCIE) { 552ff0cc061SDimitry Andric uint8_t Version = Data.getU8(&Offset); 553ff0cc061SDimitry Andric const char *Augmentation = Data.getCStr(&Offset); 5543ca95b02SDimitry Andric StringRef AugmentationString(Augmentation ? Augmentation : ""); 5553ca95b02SDimitry Andric uint8_t AddressSize = Version < 4 ? Data.getAddressSize() : 5563ca95b02SDimitry Andric Data.getU8(&Offset); 557ff0cc061SDimitry Andric Data.setAddressSize(AddressSize); 558ff0cc061SDimitry Andric uint8_t SegmentDescriptorSize = Version < 4 ? 0 : Data.getU8(&Offset); 559ff0cc061SDimitry Andric uint64_t CodeAlignmentFactor = Data.getULEB128(&Offset); 560ff0cc061SDimitry Andric int64_t DataAlignmentFactor = Data.getSLEB128(&Offset); 561ff0cc061SDimitry Andric uint64_t ReturnAddressRegister = Data.getULEB128(&Offset); 562ff0cc061SDimitry Andric 5633ca95b02SDimitry Andric // Parse the augmentation data for EH CIEs 5643ca95b02SDimitry Andric StringRef AugmentationData(""); 5653ca95b02SDimitry Andric uint32_t FDEPointerEncoding = DW_EH_PE_omit; 5663ca95b02SDimitry Andric uint32_t LSDAPointerEncoding = DW_EH_PE_omit; 5673ca95b02SDimitry Andric if (IsEH) { 5683ca95b02SDimitry Andric Optional<uint32_t> PersonalityEncoding; 5693ca95b02SDimitry Andric Optional<uint64_t> Personality; 5703ca95b02SDimitry Andric 5713ca95b02SDimitry Andric Optional<uint64_t> AugmentationLength; 5723ca95b02SDimitry Andric uint32_t StartAugmentationOffset; 5733ca95b02SDimitry Andric uint32_t EndAugmentationOffset; 5743ca95b02SDimitry Andric 5753ca95b02SDimitry Andric // Walk the augmentation string to get all the augmentation data. 5763ca95b02SDimitry Andric for (unsigned i = 0, e = AugmentationString.size(); i != e; ++i) { 5773ca95b02SDimitry Andric switch (AugmentationString[i]) { 5783ca95b02SDimitry Andric default: 5793ca95b02SDimitry Andric ReportError("Unknown augmentation character in entry at %lx"); 5803ca95b02SDimitry Andric case 'L': 5813ca95b02SDimitry Andric LSDAPointerEncoding = Data.getU8(&Offset); 5823ca95b02SDimitry Andric break; 5833ca95b02SDimitry Andric case 'P': { 5843ca95b02SDimitry Andric if (Personality) 5853ca95b02SDimitry Andric ReportError("Duplicate personality in entry at %lx"); 5863ca95b02SDimitry Andric PersonalityEncoding = Data.getU8(&Offset); 5873ca95b02SDimitry Andric Personality = readPointer(Data, Offset, *PersonalityEncoding); 5883ca95b02SDimitry Andric break; 5893ca95b02SDimitry Andric } 5903ca95b02SDimitry Andric case 'R': 5913ca95b02SDimitry Andric FDEPointerEncoding = Data.getU8(&Offset); 5923ca95b02SDimitry Andric break; 5933ca95b02SDimitry Andric case 'z': 5943ca95b02SDimitry Andric if (i) 5953ca95b02SDimitry Andric ReportError("'z' must be the first character at %lx"); 5963ca95b02SDimitry Andric // Parse the augmentation length first. We only parse it if 5973ca95b02SDimitry Andric // the string contains a 'z'. 5983ca95b02SDimitry Andric AugmentationLength = Data.getULEB128(&Offset); 5993ca95b02SDimitry Andric StartAugmentationOffset = Offset; 6003ca95b02SDimitry Andric EndAugmentationOffset = Offset + 6013ca95b02SDimitry Andric static_cast<uint32_t>(*AugmentationLength); 6023ca95b02SDimitry Andric } 6033ca95b02SDimitry Andric } 6043ca95b02SDimitry Andric 6053ca95b02SDimitry Andric if (AugmentationLength.hasValue()) { 6063ca95b02SDimitry Andric if (Offset != EndAugmentationOffset) 6073ca95b02SDimitry Andric ReportError("Parsing augmentation data at %lx failed"); 6083ca95b02SDimitry Andric 6093ca95b02SDimitry Andric AugmentationData = Data.getData().slice(StartAugmentationOffset, 6103ca95b02SDimitry Andric EndAugmentationOffset); 6113ca95b02SDimitry Andric } 6123ca95b02SDimitry Andric } 6133ca95b02SDimitry Andric 614ff0cc061SDimitry Andric auto Cie = make_unique<CIE>(StartOffset, Length, Version, 6153ca95b02SDimitry Andric AugmentationString, AddressSize, 616ff0cc061SDimitry Andric SegmentDescriptorSize, CodeAlignmentFactor, 6173ca95b02SDimitry Andric DataAlignmentFactor, ReturnAddressRegister, 6183ca95b02SDimitry Andric AugmentationData, FDEPointerEncoding, 6193ca95b02SDimitry Andric LSDAPointerEncoding); 620ff0cc061SDimitry Andric CIEs[StartOffset] = Cie.get(); 621ff0cc061SDimitry Andric Entries.emplace_back(std::move(Cie)); 622ff0cc061SDimitry Andric } else { 623ff0cc061SDimitry Andric // FDE 624ff0cc061SDimitry Andric uint64_t CIEPointer = Id; 6253ca95b02SDimitry Andric uint64_t InitialLocation = 0; 6263ca95b02SDimitry Andric uint64_t AddressRange = 0; 6273ca95b02SDimitry Andric CIE *Cie = CIEs[IsEH ? (StartStructureOffset - CIEPointer) : CIEPointer]; 6283ca95b02SDimitry Andric 6293ca95b02SDimitry Andric if (IsEH) { 6303ca95b02SDimitry Andric // The address size is encoded in the CIE we reference. 6313ca95b02SDimitry Andric if (!Cie) 6323ca95b02SDimitry Andric ReportError("Parsing FDE data at %lx failed due to missing CIE"); 6333ca95b02SDimitry Andric 6343ca95b02SDimitry Andric InitialLocation = readPointer(Data, Offset, 6353ca95b02SDimitry Andric Cie->getFDEPointerEncoding()); 6363ca95b02SDimitry Andric AddressRange = readPointer(Data, Offset, 6373ca95b02SDimitry Andric Cie->getFDEPointerEncoding()); 6383ca95b02SDimitry Andric 6393ca95b02SDimitry Andric StringRef AugmentationString = Cie->getAugmentationString(); 6403ca95b02SDimitry Andric if (!AugmentationString.empty()) { 6413ca95b02SDimitry Andric // Parse the augmentation length and data for this FDE. 6423ca95b02SDimitry Andric uint64_t AugmentationLength = Data.getULEB128(&Offset); 6433ca95b02SDimitry Andric 6443ca95b02SDimitry Andric uint32_t EndAugmentationOffset = 6453ca95b02SDimitry Andric Offset + static_cast<uint32_t>(AugmentationLength); 6463ca95b02SDimitry Andric 6473ca95b02SDimitry Andric // Decode the LSDA if the CIE augmentation string said we should. 6483ca95b02SDimitry Andric if (Cie->getLSDAPointerEncoding() != DW_EH_PE_omit) 6493ca95b02SDimitry Andric readPointer(Data, Offset, Cie->getLSDAPointerEncoding()); 6503ca95b02SDimitry Andric 6513ca95b02SDimitry Andric if (Offset != EndAugmentationOffset) 6523ca95b02SDimitry Andric ReportError("Parsing augmentation data at %lx failed"); 6533ca95b02SDimitry Andric } 6543ca95b02SDimitry Andric } else { 6553ca95b02SDimitry Andric InitialLocation = Data.getAddress(&Offset); 6563ca95b02SDimitry Andric AddressRange = Data.getAddress(&Offset); 6573ca95b02SDimitry Andric } 658ff0cc061SDimitry Andric 659ff0cc061SDimitry Andric Entries.emplace_back(new FDE(StartOffset, Length, CIEPointer, 660ff0cc061SDimitry Andric InitialLocation, AddressRange, 6613ca95b02SDimitry Andric Cie)); 662ff0cc061SDimitry Andric } 663ff0cc061SDimitry Andric 664ff0cc061SDimitry Andric Entries.back()->parseInstructions(Data, &Offset, EndStructureOffset); 665ff0cc061SDimitry Andric 6663ca95b02SDimitry Andric if (Offset != EndStructureOffset) 6673ca95b02SDimitry Andric ReportError("Parsing entry instructions at %lx failed"); 668ff0cc061SDimitry Andric } 669ff0cc061SDimitry Andric } 670ff0cc061SDimitry Andric 671ff0cc061SDimitry Andric 672ff0cc061SDimitry Andric void DWARFDebugFrame::dump(raw_ostream &OS) const { 673ff0cc061SDimitry Andric OS << "\n"; 674ff0cc061SDimitry Andric for (const auto &Entry : Entries) { 675ff0cc061SDimitry Andric Entry->dumpHeader(OS); 676ff0cc061SDimitry Andric Entry->dumpInstructions(OS); 677ff0cc061SDimitry Andric OS << "\n"; 678ff0cc061SDimitry Andric } 679ff0cc061SDimitry Andric } 680ff0cc061SDimitry Andric 681