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 10db17bf38SDimitry 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" 14db17bf38SDimitry Andric #include "llvm/ADT/SmallString.h" 153ca95b02SDimitry Andric #include "llvm/ADT/StringExtras.h" 16d88c1a5aSDimitry Andric #include "llvm/ADT/StringRef.h" 17db17bf38SDimitry Andric #include "llvm/BinaryFormat/Dwarf.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/ErrorHandling.h" 22ff0cc061SDimitry Andric #include "llvm/Support/Format.h" 23ff0cc061SDimitry Andric #include "llvm/Support/raw_ostream.h" 24d88c1a5aSDimitry Andric #include <algorithm> 25d88c1a5aSDimitry Andric #include <cassert> 26d88c1a5aSDimitry Andric #include <cinttypes> 27d88c1a5aSDimitry Andric #include <cstdint> 28ff0cc061SDimitry Andric #include <string> 29ff0cc061SDimitry Andric #include <vector> 30ff0cc061SDimitry Andric 31ff0cc061SDimitry Andric using namespace llvm; 32ff0cc061SDimitry Andric using namespace dwarf; 33ff0cc061SDimitry Andric 34ff0cc061SDimitry Andric /// \brief Abstract frame entry defining the common interface concrete 35ff0cc061SDimitry Andric /// entries implement. 36ff0cc061SDimitry Andric class llvm::FrameEntry { 37ff0cc061SDimitry Andric public: 38ff0cc061SDimitry Andric enum FrameKind {FK_CIE, FK_FDE}; 39d88c1a5aSDimitry Andric 40ff0cc061SDimitry Andric FrameEntry(FrameKind K, uint64_t Offset, uint64_t Length) 41ff0cc061SDimitry Andric : Kind(K), Offset(Offset), Length(Length) {} 42ff0cc061SDimitry Andric 43d88c1a5aSDimitry Andric virtual ~FrameEntry() = default; 44ff0cc061SDimitry Andric 45ff0cc061SDimitry Andric FrameKind getKind() const { return Kind; } 46ff0cc061SDimitry Andric virtual uint64_t getOffset() const { return Offset; } 47ff0cc061SDimitry Andric 482cab237bSDimitry Andric /// Parse and store a sequence of CFI instructions from Data, 49ff0cc061SDimitry Andric /// starting at *Offset and ending at EndOffset. If everything 50ff0cc061SDimitry Andric /// goes well, *Offset should be equal to EndOffset when this method 51ff0cc061SDimitry Andric /// returns. Otherwise, an error occurred. 52ff0cc061SDimitry Andric virtual void parseInstructions(DataExtractor Data, uint32_t *Offset, 53ff0cc061SDimitry Andric uint32_t EndOffset); 54ff0cc061SDimitry Andric 552cab237bSDimitry Andric /// Dump the entry header to the given output stream. 56ff0cc061SDimitry Andric virtual void dumpHeader(raw_ostream &OS) const = 0; 57ff0cc061SDimitry Andric 582cab237bSDimitry Andric /// Dump the entry's instructions to the given output stream. 59ff0cc061SDimitry Andric virtual void dumpInstructions(raw_ostream &OS) const; 60ff0cc061SDimitry Andric 612cab237bSDimitry Andric /// Dump the entire entry to the given output stream. 622cab237bSDimitry Andric void dump(raw_ostream &OS) const { 632cab237bSDimitry Andric dumpHeader(OS); 642cab237bSDimitry Andric dumpInstructions(OS); 652cab237bSDimitry Andric OS << "\n"; 662cab237bSDimitry Andric } 672cab237bSDimitry Andric 68ff0cc061SDimitry Andric protected: 69ff0cc061SDimitry Andric const FrameKind Kind; 70ff0cc061SDimitry Andric 71ff0cc061SDimitry Andric /// \brief Offset of this entry in the section. 72ff0cc061SDimitry Andric uint64_t Offset; 73ff0cc061SDimitry Andric 74ff0cc061SDimitry Andric /// \brief Entry length as specified in DWARF. 75ff0cc061SDimitry Andric uint64_t Length; 76ff0cc061SDimitry Andric 77ff0cc061SDimitry Andric /// An entry may contain CFI instructions. An instruction consists of an 78ff0cc061SDimitry Andric /// opcode and an optional sequence of operands. 79edd7eaddSDimitry Andric using Operands = std::vector<uint64_t>; 80ff0cc061SDimitry Andric struct Instruction { 81ff0cc061SDimitry Andric Instruction(uint8_t Opcode) 82ff0cc061SDimitry Andric : Opcode(Opcode) 83ff0cc061SDimitry Andric {} 84ff0cc061SDimitry Andric 85ff0cc061SDimitry Andric uint8_t Opcode; 86ff0cc061SDimitry Andric Operands Ops; 87ff0cc061SDimitry Andric }; 88ff0cc061SDimitry Andric 89ff0cc061SDimitry Andric std::vector<Instruction> Instructions; 90ff0cc061SDimitry Andric 91ff0cc061SDimitry Andric /// Convenience methods to add a new instruction with the given opcode and 92ff0cc061SDimitry Andric /// operands to the Instructions vector. 93ff0cc061SDimitry Andric void addInstruction(uint8_t Opcode) { 94ff0cc061SDimitry Andric Instructions.push_back(Instruction(Opcode)); 95ff0cc061SDimitry Andric } 96ff0cc061SDimitry Andric 97ff0cc061SDimitry Andric void addInstruction(uint8_t Opcode, uint64_t Operand1) { 98ff0cc061SDimitry Andric Instructions.push_back(Instruction(Opcode)); 99ff0cc061SDimitry Andric Instructions.back().Ops.push_back(Operand1); 100ff0cc061SDimitry Andric } 101ff0cc061SDimitry Andric 102ff0cc061SDimitry Andric void addInstruction(uint8_t Opcode, uint64_t Operand1, uint64_t Operand2) { 103ff0cc061SDimitry Andric Instructions.push_back(Instruction(Opcode)); 104ff0cc061SDimitry Andric Instructions.back().Ops.push_back(Operand1); 105ff0cc061SDimitry Andric Instructions.back().Ops.push_back(Operand2); 106ff0cc061SDimitry Andric } 107ff0cc061SDimitry Andric }; 108ff0cc061SDimitry Andric 109ff0cc061SDimitry Andric // See DWARF standard v3, section 7.23 110ff0cc061SDimitry Andric const uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK = 0xc0; 111ff0cc061SDimitry Andric const uint8_t DWARF_CFI_PRIMARY_OPERAND_MASK = 0x3f; 112ff0cc061SDimitry Andric 113ff0cc061SDimitry Andric void FrameEntry::parseInstructions(DataExtractor Data, uint32_t *Offset, 114ff0cc061SDimitry Andric uint32_t EndOffset) { 115ff0cc061SDimitry Andric while (*Offset < EndOffset) { 116ff0cc061SDimitry Andric uint8_t Opcode = Data.getU8(Offset); 117ff0cc061SDimitry Andric // Some instructions have a primary opcode encoded in the top bits. 118ff0cc061SDimitry Andric uint8_t Primary = Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK; 119ff0cc061SDimitry Andric 120ff0cc061SDimitry Andric if (Primary) { 121ff0cc061SDimitry Andric // If it's a primary opcode, the first operand is encoded in the bottom 122ff0cc061SDimitry Andric // bits of the opcode itself. 123ff0cc061SDimitry Andric uint64_t Op1 = Opcode & DWARF_CFI_PRIMARY_OPERAND_MASK; 124ff0cc061SDimitry Andric switch (Primary) { 125ff0cc061SDimitry Andric default: llvm_unreachable("Impossible primary CFI opcode"); 126ff0cc061SDimitry Andric case DW_CFA_advance_loc: 127ff0cc061SDimitry Andric case DW_CFA_restore: 128ff0cc061SDimitry Andric addInstruction(Primary, Op1); 129ff0cc061SDimitry Andric break; 130ff0cc061SDimitry Andric case DW_CFA_offset: 131ff0cc061SDimitry Andric addInstruction(Primary, Op1, Data.getULEB128(Offset)); 132ff0cc061SDimitry Andric break; 133ff0cc061SDimitry Andric } 134ff0cc061SDimitry Andric } else { 135ff0cc061SDimitry Andric // Extended opcode - its value is Opcode itself. 136ff0cc061SDimitry Andric switch (Opcode) { 137ff0cc061SDimitry Andric default: llvm_unreachable("Invalid extended CFI opcode"); 138ff0cc061SDimitry Andric case DW_CFA_nop: 139ff0cc061SDimitry Andric case DW_CFA_remember_state: 140ff0cc061SDimitry Andric case DW_CFA_restore_state: 141ff0cc061SDimitry Andric case DW_CFA_GNU_window_save: 142ff0cc061SDimitry Andric // No operands 143ff0cc061SDimitry Andric addInstruction(Opcode); 144ff0cc061SDimitry Andric break; 145ff0cc061SDimitry Andric case DW_CFA_set_loc: 146ff0cc061SDimitry Andric // Operands: Address 147ff0cc061SDimitry Andric addInstruction(Opcode, Data.getAddress(Offset)); 148ff0cc061SDimitry Andric break; 149ff0cc061SDimitry Andric case DW_CFA_advance_loc1: 150ff0cc061SDimitry Andric // Operands: 1-byte delta 151ff0cc061SDimitry Andric addInstruction(Opcode, Data.getU8(Offset)); 152ff0cc061SDimitry Andric break; 153ff0cc061SDimitry Andric case DW_CFA_advance_loc2: 154ff0cc061SDimitry Andric // Operands: 2-byte delta 155ff0cc061SDimitry Andric addInstruction(Opcode, Data.getU16(Offset)); 156ff0cc061SDimitry Andric break; 157ff0cc061SDimitry Andric case DW_CFA_advance_loc4: 158ff0cc061SDimitry Andric // Operands: 4-byte delta 159ff0cc061SDimitry Andric addInstruction(Opcode, Data.getU32(Offset)); 160ff0cc061SDimitry Andric break; 161ff0cc061SDimitry Andric case DW_CFA_restore_extended: 162ff0cc061SDimitry Andric case DW_CFA_undefined: 163ff0cc061SDimitry Andric case DW_CFA_same_value: 164ff0cc061SDimitry Andric case DW_CFA_def_cfa_register: 165ff0cc061SDimitry Andric case DW_CFA_def_cfa_offset: 1662cab237bSDimitry Andric case DW_CFA_GNU_args_size: 167ff0cc061SDimitry Andric // Operands: ULEB128 168ff0cc061SDimitry Andric addInstruction(Opcode, Data.getULEB128(Offset)); 169ff0cc061SDimitry Andric break; 170ff0cc061SDimitry Andric case DW_CFA_def_cfa_offset_sf: 171ff0cc061SDimitry Andric // Operands: SLEB128 172ff0cc061SDimitry Andric addInstruction(Opcode, Data.getSLEB128(Offset)); 173ff0cc061SDimitry Andric break; 174ff0cc061SDimitry Andric case DW_CFA_offset_extended: 175ff0cc061SDimitry Andric case DW_CFA_register: 176ff0cc061SDimitry Andric case DW_CFA_def_cfa: 1773ca95b02SDimitry Andric case DW_CFA_val_offset: { 178ff0cc061SDimitry Andric // Operands: ULEB128, ULEB128 1793ca95b02SDimitry Andric // Note: We can not embed getULEB128 directly into function 1803ca95b02SDimitry Andric // argument list. getULEB128 changes Offset and order of evaluation 1813ca95b02SDimitry Andric // for arguments is unspecified. 1823ca95b02SDimitry Andric auto op1 = Data.getULEB128(Offset); 1833ca95b02SDimitry Andric auto op2 = Data.getULEB128(Offset); 1843ca95b02SDimitry Andric addInstruction(Opcode, op1, op2); 185ff0cc061SDimitry Andric break; 1863ca95b02SDimitry Andric } 187ff0cc061SDimitry Andric case DW_CFA_offset_extended_sf: 188ff0cc061SDimitry Andric case DW_CFA_def_cfa_sf: 1893ca95b02SDimitry Andric case DW_CFA_val_offset_sf: { 190ff0cc061SDimitry Andric // Operands: ULEB128, SLEB128 1913ca95b02SDimitry Andric // Note: see comment for the previous case 1923ca95b02SDimitry Andric auto op1 = Data.getULEB128(Offset); 1933ca95b02SDimitry Andric auto op2 = (uint64_t)Data.getSLEB128(Offset); 1943ca95b02SDimitry Andric addInstruction(Opcode, op1, op2); 195ff0cc061SDimitry Andric break; 1963ca95b02SDimitry Andric } 197ff0cc061SDimitry Andric case DW_CFA_def_cfa_expression: 1982cab237bSDimitry Andric // FIXME: Parse the actual instruction. 1992cab237bSDimitry Andric *Offset += Data.getULEB128(Offset); 2002cab237bSDimitry Andric break; 201ff0cc061SDimitry Andric case DW_CFA_expression: 2022cab237bSDimitry Andric case DW_CFA_val_expression: { 2032cab237bSDimitry Andric // FIXME: Parse the actual instruction. 2042cab237bSDimitry Andric Data.getULEB128(Offset); 2052cab237bSDimitry Andric *Offset += Data.getULEB128(Offset); 2062cab237bSDimitry Andric break; 2072cab237bSDimitry Andric } 208ff0cc061SDimitry Andric } 209ff0cc061SDimitry Andric } 210ff0cc061SDimitry Andric } 211ff0cc061SDimitry Andric } 212ff0cc061SDimitry Andric 213ff0cc061SDimitry Andric namespace { 214d88c1a5aSDimitry Andric 215ff0cc061SDimitry Andric /// \brief DWARF Common Information Entry (CIE) 216ff0cc061SDimitry Andric class CIE : public FrameEntry { 217ff0cc061SDimitry Andric public: 218ff0cc061SDimitry Andric // CIEs (and FDEs) are simply container classes, so the only sensible way to 219ff0cc061SDimitry Andric // create them is by providing the full parsed contents in the constructor. 220ff0cc061SDimitry Andric CIE(uint64_t Offset, uint64_t Length, uint8_t Version, 221ff0cc061SDimitry Andric SmallString<8> Augmentation, uint8_t AddressSize, 222ff0cc061SDimitry Andric uint8_t SegmentDescriptorSize, uint64_t CodeAlignmentFactor, 2233ca95b02SDimitry Andric int64_t DataAlignmentFactor, uint64_t ReturnAddressRegister, 2243ca95b02SDimitry Andric SmallString<8> AugmentationData, uint32_t FDEPointerEncoding, 2253ca95b02SDimitry Andric uint32_t LSDAPointerEncoding) 226ff0cc061SDimitry Andric : FrameEntry(FK_CIE, Offset, Length), Version(Version), 2273ca95b02SDimitry Andric Augmentation(std::move(Augmentation)), AddressSize(AddressSize), 228ff0cc061SDimitry Andric SegmentDescriptorSize(SegmentDescriptorSize), 229ff0cc061SDimitry Andric CodeAlignmentFactor(CodeAlignmentFactor), 230ff0cc061SDimitry Andric DataAlignmentFactor(DataAlignmentFactor), 2313ca95b02SDimitry Andric ReturnAddressRegister(ReturnAddressRegister), 2323ca95b02SDimitry Andric AugmentationData(std::move(AugmentationData)), 2333ca95b02SDimitry Andric FDEPointerEncoding(FDEPointerEncoding), 2343ca95b02SDimitry Andric LSDAPointerEncoding(LSDAPointerEncoding) {} 235ff0cc061SDimitry Andric 236d88c1a5aSDimitry Andric ~CIE() override = default; 237ff0cc061SDimitry Andric 2383ca95b02SDimitry Andric StringRef getAugmentationString() const { return Augmentation; } 239ff0cc061SDimitry Andric uint64_t getCodeAlignmentFactor() const { return CodeAlignmentFactor; } 240ff0cc061SDimitry Andric int64_t getDataAlignmentFactor() const { return DataAlignmentFactor; } 241d88c1a5aSDimitry Andric 2423ca95b02SDimitry Andric uint32_t getFDEPointerEncoding() const { 2433ca95b02SDimitry Andric return FDEPointerEncoding; 2443ca95b02SDimitry Andric } 245d88c1a5aSDimitry Andric 2463ca95b02SDimitry Andric uint32_t getLSDAPointerEncoding() const { 2473ca95b02SDimitry Andric return LSDAPointerEncoding; 2483ca95b02SDimitry Andric } 249ff0cc061SDimitry Andric 250ff0cc061SDimitry Andric void dumpHeader(raw_ostream &OS) const override { 251ff0cc061SDimitry Andric OS << format("%08x %08x %08x CIE", 252ff0cc061SDimitry Andric (uint32_t)Offset, (uint32_t)Length, DW_CIE_ID) 253ff0cc061SDimitry Andric << "\n"; 254ff0cc061SDimitry Andric OS << format(" Version: %d\n", Version); 255ff0cc061SDimitry Andric OS << " Augmentation: \"" << Augmentation << "\"\n"; 256ff0cc061SDimitry Andric if (Version >= 4) { 257ff0cc061SDimitry Andric OS << format(" Address size: %u\n", 258ff0cc061SDimitry Andric (uint32_t)AddressSize); 259ff0cc061SDimitry Andric OS << format(" Segment desc size: %u\n", 260ff0cc061SDimitry Andric (uint32_t)SegmentDescriptorSize); 261ff0cc061SDimitry Andric } 262ff0cc061SDimitry Andric OS << format(" Code alignment factor: %u\n", 263ff0cc061SDimitry Andric (uint32_t)CodeAlignmentFactor); 264ff0cc061SDimitry Andric OS << format(" Data alignment factor: %d\n", 265ff0cc061SDimitry Andric (int32_t)DataAlignmentFactor); 266ff0cc061SDimitry Andric OS << format(" Return address column: %d\n", 267ff0cc061SDimitry Andric (int32_t)ReturnAddressRegister); 2683ca95b02SDimitry Andric if (!AugmentationData.empty()) { 2693ca95b02SDimitry Andric OS << " Augmentation data: "; 2703ca95b02SDimitry Andric for (uint8_t Byte : AugmentationData) 2713ca95b02SDimitry Andric OS << ' ' << hexdigit(Byte >> 4) << hexdigit(Byte & 0xf); 2723ca95b02SDimitry Andric OS << "\n"; 2733ca95b02SDimitry Andric } 274ff0cc061SDimitry Andric OS << "\n"; 275ff0cc061SDimitry Andric } 276ff0cc061SDimitry Andric 277ff0cc061SDimitry Andric static bool classof(const FrameEntry *FE) { 278ff0cc061SDimitry Andric return FE->getKind() == FK_CIE; 279ff0cc061SDimitry Andric } 280ff0cc061SDimitry Andric 281ff0cc061SDimitry Andric private: 282ff0cc061SDimitry Andric /// The following fields are defined in section 6.4.1 of the DWARF standard v4 283ff0cc061SDimitry Andric uint8_t Version; 284ff0cc061SDimitry Andric SmallString<8> Augmentation; 285ff0cc061SDimitry Andric uint8_t AddressSize; 286ff0cc061SDimitry Andric uint8_t SegmentDescriptorSize; 287ff0cc061SDimitry Andric uint64_t CodeAlignmentFactor; 288ff0cc061SDimitry Andric int64_t DataAlignmentFactor; 289ff0cc061SDimitry Andric uint64_t ReturnAddressRegister; 2903ca95b02SDimitry Andric 2913ca95b02SDimitry Andric // The following are used when the CIE represents an EH frame entry. 2923ca95b02SDimitry Andric SmallString<8> AugmentationData; 2933ca95b02SDimitry Andric uint32_t FDEPointerEncoding; 2943ca95b02SDimitry Andric uint32_t LSDAPointerEncoding; 295ff0cc061SDimitry Andric }; 296ff0cc061SDimitry Andric 297ff0cc061SDimitry Andric /// \brief DWARF Frame Description Entry (FDE) 298ff0cc061SDimitry Andric class FDE : public FrameEntry { 299ff0cc061SDimitry Andric public: 300ff0cc061SDimitry Andric // Each FDE has a CIE it's "linked to". Our FDE contains is constructed with 301ff0cc061SDimitry Andric // an offset to the CIE (provided by parsing the FDE header). The CIE itself 302ff0cc061SDimitry Andric // is obtained lazily once it's actually required. 303ff0cc061SDimitry Andric FDE(uint64_t Offset, uint64_t Length, int64_t LinkedCIEOffset, 304ff0cc061SDimitry Andric uint64_t InitialLocation, uint64_t AddressRange, 305ff0cc061SDimitry Andric CIE *Cie) 306ff0cc061SDimitry Andric : FrameEntry(FK_FDE, Offset, Length), LinkedCIEOffset(LinkedCIEOffset), 307ff0cc061SDimitry Andric InitialLocation(InitialLocation), AddressRange(AddressRange), 308ff0cc061SDimitry Andric LinkedCIE(Cie) {} 309ff0cc061SDimitry Andric 310d88c1a5aSDimitry Andric ~FDE() override = default; 311ff0cc061SDimitry Andric 312ff0cc061SDimitry Andric CIE *getLinkedCIE() const { return LinkedCIE; } 313ff0cc061SDimitry Andric 314ff0cc061SDimitry Andric void dumpHeader(raw_ostream &OS) const override { 315ff0cc061SDimitry Andric OS << format("%08x %08x %08x FDE ", 316ff0cc061SDimitry Andric (uint32_t)Offset, (uint32_t)Length, (int32_t)LinkedCIEOffset); 317ff0cc061SDimitry Andric OS << format("cie=%08x pc=%08x...%08x\n", 318ff0cc061SDimitry Andric (int32_t)LinkedCIEOffset, 319ff0cc061SDimitry Andric (uint32_t)InitialLocation, 320ff0cc061SDimitry Andric (uint32_t)InitialLocation + (uint32_t)AddressRange); 321ff0cc061SDimitry Andric } 322ff0cc061SDimitry Andric 323ff0cc061SDimitry Andric static bool classof(const FrameEntry *FE) { 324ff0cc061SDimitry Andric return FE->getKind() == FK_FDE; 325ff0cc061SDimitry Andric } 326ff0cc061SDimitry Andric 327ff0cc061SDimitry Andric private: 328ff0cc061SDimitry Andric /// The following fields are defined in section 6.4.1 of the DWARF standard v3 329ff0cc061SDimitry Andric uint64_t LinkedCIEOffset; 330ff0cc061SDimitry Andric uint64_t InitialLocation; 331ff0cc061SDimitry Andric uint64_t AddressRange; 332ff0cc061SDimitry Andric CIE *LinkedCIE; 333ff0cc061SDimitry Andric }; 334ff0cc061SDimitry Andric 335ff0cc061SDimitry Andric /// \brief Types of operands to CF instructions. 336ff0cc061SDimitry Andric enum OperandType { 337ff0cc061SDimitry Andric OT_Unset, 338ff0cc061SDimitry Andric OT_None, 339ff0cc061SDimitry Andric OT_Address, 340ff0cc061SDimitry Andric OT_Offset, 341ff0cc061SDimitry Andric OT_FactoredCodeOffset, 342ff0cc061SDimitry Andric OT_SignedFactDataOffset, 343ff0cc061SDimitry Andric OT_UnsignedFactDataOffset, 344ff0cc061SDimitry Andric OT_Register, 345ff0cc061SDimitry Andric OT_Expression 346ff0cc061SDimitry Andric }; 347ff0cc061SDimitry Andric 348ff0cc061SDimitry Andric } // end anonymous namespace 349ff0cc061SDimitry Andric 350ff0cc061SDimitry Andric /// \brief Initialize the array describing the types of operands. 351ff0cc061SDimitry Andric static ArrayRef<OperandType[2]> getOperandTypes() { 352ff0cc061SDimitry Andric static OperandType OpTypes[DW_CFA_restore+1][2]; 353ff0cc061SDimitry Andric 354ff0cc061SDimitry Andric #define DECLARE_OP2(OP, OPTYPE0, OPTYPE1) \ 355ff0cc061SDimitry Andric do { \ 356ff0cc061SDimitry Andric OpTypes[OP][0] = OPTYPE0; \ 357ff0cc061SDimitry Andric OpTypes[OP][1] = OPTYPE1; \ 358d88c1a5aSDimitry Andric } while (false) 359ff0cc061SDimitry Andric #define DECLARE_OP1(OP, OPTYPE0) DECLARE_OP2(OP, OPTYPE0, OT_None) 360ff0cc061SDimitry Andric #define DECLARE_OP0(OP) DECLARE_OP1(OP, OT_None) 361ff0cc061SDimitry Andric 362ff0cc061SDimitry Andric DECLARE_OP1(DW_CFA_set_loc, OT_Address); 363ff0cc061SDimitry Andric DECLARE_OP1(DW_CFA_advance_loc, OT_FactoredCodeOffset); 364ff0cc061SDimitry Andric DECLARE_OP1(DW_CFA_advance_loc1, OT_FactoredCodeOffset); 365ff0cc061SDimitry Andric DECLARE_OP1(DW_CFA_advance_loc2, OT_FactoredCodeOffset); 366ff0cc061SDimitry Andric DECLARE_OP1(DW_CFA_advance_loc4, OT_FactoredCodeOffset); 367ff0cc061SDimitry Andric DECLARE_OP1(DW_CFA_MIPS_advance_loc8, OT_FactoredCodeOffset); 368ff0cc061SDimitry Andric DECLARE_OP2(DW_CFA_def_cfa, OT_Register, OT_Offset); 369ff0cc061SDimitry Andric DECLARE_OP2(DW_CFA_def_cfa_sf, OT_Register, OT_SignedFactDataOffset); 370ff0cc061SDimitry Andric DECLARE_OP1(DW_CFA_def_cfa_register, OT_Register); 371ff0cc061SDimitry Andric DECLARE_OP1(DW_CFA_def_cfa_offset, OT_Offset); 372ff0cc061SDimitry Andric DECLARE_OP1(DW_CFA_def_cfa_offset_sf, OT_SignedFactDataOffset); 373ff0cc061SDimitry Andric DECLARE_OP1(DW_CFA_def_cfa_expression, OT_Expression); 374ff0cc061SDimitry Andric DECLARE_OP1(DW_CFA_undefined, OT_Register); 375ff0cc061SDimitry Andric DECLARE_OP1(DW_CFA_same_value, OT_Register); 376ff0cc061SDimitry Andric DECLARE_OP2(DW_CFA_offset, OT_Register, OT_UnsignedFactDataOffset); 377ff0cc061SDimitry Andric DECLARE_OP2(DW_CFA_offset_extended, OT_Register, OT_UnsignedFactDataOffset); 378ff0cc061SDimitry Andric DECLARE_OP2(DW_CFA_offset_extended_sf, OT_Register, OT_SignedFactDataOffset); 379ff0cc061SDimitry Andric DECLARE_OP2(DW_CFA_val_offset, OT_Register, OT_UnsignedFactDataOffset); 380ff0cc061SDimitry Andric DECLARE_OP2(DW_CFA_val_offset_sf, OT_Register, OT_SignedFactDataOffset); 381ff0cc061SDimitry Andric DECLARE_OP2(DW_CFA_register, OT_Register, OT_Register); 382ff0cc061SDimitry Andric DECLARE_OP2(DW_CFA_expression, OT_Register, OT_Expression); 383ff0cc061SDimitry Andric DECLARE_OP2(DW_CFA_val_expression, OT_Register, OT_Expression); 384ff0cc061SDimitry Andric DECLARE_OP1(DW_CFA_restore, OT_Register); 385ff0cc061SDimitry Andric DECLARE_OP1(DW_CFA_restore_extended, OT_Register); 386ff0cc061SDimitry Andric DECLARE_OP0(DW_CFA_remember_state); 387ff0cc061SDimitry Andric DECLARE_OP0(DW_CFA_restore_state); 388ff0cc061SDimitry Andric DECLARE_OP0(DW_CFA_GNU_window_save); 389ff0cc061SDimitry Andric DECLARE_OP1(DW_CFA_GNU_args_size, OT_Offset); 390ff0cc061SDimitry Andric DECLARE_OP0(DW_CFA_nop); 391ff0cc061SDimitry Andric 392ff0cc061SDimitry Andric #undef DECLARE_OP0 393ff0cc061SDimitry Andric #undef DECLARE_OP1 394ff0cc061SDimitry Andric #undef DECLARE_OP2 395d88c1a5aSDimitry Andric 396ff0cc061SDimitry Andric return ArrayRef<OperandType[2]>(&OpTypes[0], DW_CFA_restore+1); 397ff0cc061SDimitry Andric } 398ff0cc061SDimitry Andric 399ff0cc061SDimitry Andric static ArrayRef<OperandType[2]> OpTypes = getOperandTypes(); 400ff0cc061SDimitry Andric 401ff0cc061SDimitry Andric /// \brief Print \p Opcode's operand number \p OperandIdx which has 402ff0cc061SDimitry Andric /// value \p Operand. 403ff0cc061SDimitry Andric static void printOperand(raw_ostream &OS, uint8_t Opcode, unsigned OperandIdx, 404ff0cc061SDimitry Andric uint64_t Operand, uint64_t CodeAlignmentFactor, 405ff0cc061SDimitry Andric int64_t DataAlignmentFactor) { 406ff0cc061SDimitry Andric assert(OperandIdx < 2); 407ff0cc061SDimitry Andric OperandType Type = OpTypes[Opcode][OperandIdx]; 408ff0cc061SDimitry Andric 409ff0cc061SDimitry Andric switch (Type) { 410d88c1a5aSDimitry Andric case OT_Unset: { 411ff0cc061SDimitry Andric OS << " Unsupported " << (OperandIdx ? "second" : "first") << " operand to"; 412d88c1a5aSDimitry Andric auto OpcodeName = CallFrameString(Opcode); 413d88c1a5aSDimitry Andric if (!OpcodeName.empty()) 414ff0cc061SDimitry Andric OS << " " << OpcodeName; 415ff0cc061SDimitry Andric else 416ff0cc061SDimitry Andric OS << format(" Opcode %x", Opcode); 417ff0cc061SDimitry Andric break; 418d88c1a5aSDimitry Andric } 419ff0cc061SDimitry Andric case OT_None: 420ff0cc061SDimitry Andric break; 421ff0cc061SDimitry Andric case OT_Address: 422ff0cc061SDimitry Andric OS << format(" %" PRIx64, Operand); 423ff0cc061SDimitry Andric break; 424ff0cc061SDimitry Andric case OT_Offset: 425ff0cc061SDimitry Andric // The offsets are all encoded in a unsigned form, but in practice 426ff0cc061SDimitry Andric // consumers use them signed. It's most certainly legacy due to 427ff0cc061SDimitry Andric // the lack of signed variants in the first Dwarf standards. 428ff0cc061SDimitry Andric OS << format(" %+" PRId64, int64_t(Operand)); 429ff0cc061SDimitry Andric break; 430ff0cc061SDimitry Andric case OT_FactoredCodeOffset: // Always Unsigned 431ff0cc061SDimitry Andric if (CodeAlignmentFactor) 432ff0cc061SDimitry Andric OS << format(" %" PRId64, Operand * CodeAlignmentFactor); 433ff0cc061SDimitry Andric else 434ff0cc061SDimitry Andric OS << format(" %" PRId64 "*code_alignment_factor" , Operand); 435ff0cc061SDimitry Andric break; 436ff0cc061SDimitry Andric case OT_SignedFactDataOffset: 437ff0cc061SDimitry Andric if (DataAlignmentFactor) 438ff0cc061SDimitry Andric OS << format(" %" PRId64, int64_t(Operand) * DataAlignmentFactor); 439ff0cc061SDimitry Andric else 440ff0cc061SDimitry Andric OS << format(" %" PRId64 "*data_alignment_factor" , int64_t(Operand)); 441ff0cc061SDimitry Andric break; 442ff0cc061SDimitry Andric case OT_UnsignedFactDataOffset: 443ff0cc061SDimitry Andric if (DataAlignmentFactor) 444ff0cc061SDimitry Andric OS << format(" %" PRId64, Operand * DataAlignmentFactor); 445ff0cc061SDimitry Andric else 446ff0cc061SDimitry Andric OS << format(" %" PRId64 "*data_alignment_factor" , Operand); 447ff0cc061SDimitry Andric break; 448ff0cc061SDimitry Andric case OT_Register: 449ff0cc061SDimitry Andric OS << format(" reg%" PRId64, Operand); 450ff0cc061SDimitry Andric break; 451ff0cc061SDimitry Andric case OT_Expression: 452ff0cc061SDimitry Andric OS << " expression"; 453ff0cc061SDimitry Andric break; 454ff0cc061SDimitry Andric } 455ff0cc061SDimitry Andric } 456ff0cc061SDimitry Andric 457ff0cc061SDimitry Andric void FrameEntry::dumpInstructions(raw_ostream &OS) const { 458ff0cc061SDimitry Andric uint64_t CodeAlignmentFactor = 0; 459ff0cc061SDimitry Andric int64_t DataAlignmentFactor = 0; 460ff0cc061SDimitry Andric const CIE *Cie = dyn_cast<CIE>(this); 461ff0cc061SDimitry Andric 462ff0cc061SDimitry Andric if (!Cie) 463ff0cc061SDimitry Andric Cie = cast<FDE>(this)->getLinkedCIE(); 464ff0cc061SDimitry Andric if (Cie) { 465ff0cc061SDimitry Andric CodeAlignmentFactor = Cie->getCodeAlignmentFactor(); 466ff0cc061SDimitry Andric DataAlignmentFactor = Cie->getDataAlignmentFactor(); 467ff0cc061SDimitry Andric } 468ff0cc061SDimitry Andric 469ff0cc061SDimitry Andric for (const auto &Instr : Instructions) { 470ff0cc061SDimitry Andric uint8_t Opcode = Instr.Opcode; 471ff0cc061SDimitry Andric if (Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK) 472ff0cc061SDimitry Andric Opcode &= DWARF_CFI_PRIMARY_OPCODE_MASK; 473ff0cc061SDimitry Andric OS << " " << CallFrameString(Opcode) << ":"; 474ff0cc061SDimitry Andric for (unsigned i = 0; i < Instr.Ops.size(); ++i) 475ff0cc061SDimitry Andric printOperand(OS, Opcode, i, Instr.Ops[i], CodeAlignmentFactor, 476ff0cc061SDimitry Andric DataAlignmentFactor); 477ff0cc061SDimitry Andric OS << '\n'; 478ff0cc061SDimitry Andric } 479ff0cc061SDimitry Andric } 480ff0cc061SDimitry Andric 4817a7e6055SDimitry Andric DWARFDebugFrame::DWARFDebugFrame(bool IsEH) : IsEH(IsEH) {} 482ff0cc061SDimitry Andric 483d88c1a5aSDimitry Andric DWARFDebugFrame::~DWARFDebugFrame() = default; 484ff0cc061SDimitry Andric 485ff0cc061SDimitry Andric static void LLVM_ATTRIBUTE_UNUSED dumpDataAux(DataExtractor Data, 486ff0cc061SDimitry Andric uint32_t Offset, int Length) { 487ff0cc061SDimitry Andric errs() << "DUMP: "; 488ff0cc061SDimitry Andric for (int i = 0; i < Length; ++i) { 489ff0cc061SDimitry Andric uint8_t c = Data.getU8(&Offset); 490ff0cc061SDimitry Andric errs().write_hex(c); errs() << " "; 491ff0cc061SDimitry Andric } 492ff0cc061SDimitry Andric errs() << "\n"; 493ff0cc061SDimitry Andric } 494ff0cc061SDimitry Andric 4953ca95b02SDimitry Andric static unsigned getSizeForEncoding(const DataExtractor &Data, 4963ca95b02SDimitry Andric unsigned symbolEncoding) { 4973ca95b02SDimitry Andric unsigned format = symbolEncoding & 0x0f; 4983ca95b02SDimitry Andric switch (format) { 4993ca95b02SDimitry Andric default: llvm_unreachable("Unknown Encoding"); 5007a7e6055SDimitry Andric case DW_EH_PE_absptr: 5017a7e6055SDimitry Andric case DW_EH_PE_signed: 5023ca95b02SDimitry Andric return Data.getAddressSize(); 5037a7e6055SDimitry Andric case DW_EH_PE_udata2: 5047a7e6055SDimitry Andric case DW_EH_PE_sdata2: 5053ca95b02SDimitry Andric return 2; 5067a7e6055SDimitry Andric case DW_EH_PE_udata4: 5077a7e6055SDimitry Andric case DW_EH_PE_sdata4: 5083ca95b02SDimitry Andric return 4; 5097a7e6055SDimitry Andric case DW_EH_PE_udata8: 5107a7e6055SDimitry Andric case DW_EH_PE_sdata8: 5113ca95b02SDimitry Andric return 8; 5123ca95b02SDimitry Andric } 5133ca95b02SDimitry Andric } 5143ca95b02SDimitry Andric 5153ca95b02SDimitry Andric static uint64_t readPointer(const DataExtractor &Data, uint32_t &Offset, 5163ca95b02SDimitry Andric unsigned Encoding) { 5173ca95b02SDimitry Andric switch (getSizeForEncoding(Data, Encoding)) { 5183ca95b02SDimitry Andric case 2: 5193ca95b02SDimitry Andric return Data.getU16(&Offset); 5203ca95b02SDimitry Andric case 4: 5213ca95b02SDimitry Andric return Data.getU32(&Offset); 5223ca95b02SDimitry Andric case 8: 5233ca95b02SDimitry Andric return Data.getU64(&Offset); 5243ca95b02SDimitry Andric default: 5253ca95b02SDimitry Andric llvm_unreachable("Illegal data size"); 5263ca95b02SDimitry Andric } 5273ca95b02SDimitry Andric } 528ff0cc061SDimitry Andric 52924d58133SDimitry Andric // This is a workaround for old compilers which do not allow 53024d58133SDimitry Andric // noreturn attribute usage in lambdas. Once the support for those 53124d58133SDimitry Andric // compilers are phased out, we can remove this and return back to 53224d58133SDimitry Andric // a ReportError lambda: [StartOffset](const char *ErrorMsg). 533edd7eaddSDimitry Andric static void LLVM_ATTRIBUTE_NORETURN ReportError(uint32_t StartOffset, 534edd7eaddSDimitry Andric const char *ErrorMsg) { 53524d58133SDimitry Andric std::string Str; 53624d58133SDimitry Andric raw_string_ostream OS(Str); 53724d58133SDimitry Andric OS << format(ErrorMsg, StartOffset); 53824d58133SDimitry Andric OS.flush(); 53924d58133SDimitry Andric report_fatal_error(Str); 54024d58133SDimitry Andric } 54124d58133SDimitry Andric 542ff0cc061SDimitry Andric void DWARFDebugFrame::parse(DataExtractor Data) { 543ff0cc061SDimitry Andric uint32_t Offset = 0; 544ff0cc061SDimitry Andric DenseMap<uint32_t, CIE *> CIEs; 545ff0cc061SDimitry Andric 546ff0cc061SDimitry Andric while (Data.isValidOffset(Offset)) { 547ff0cc061SDimitry Andric uint32_t StartOffset = Offset; 548ff0cc061SDimitry Andric 549ff0cc061SDimitry Andric bool IsDWARF64 = false; 550ff0cc061SDimitry Andric uint64_t Length = Data.getU32(&Offset); 551ff0cc061SDimitry Andric uint64_t Id; 552ff0cc061SDimitry Andric 553ff0cc061SDimitry Andric if (Length == UINT32_MAX) { 554ff0cc061SDimitry Andric // DWARF-64 is distinguished by the first 32 bits of the initial length 555ff0cc061SDimitry Andric // field being 0xffffffff. Then, the next 64 bits are the actual entry 556ff0cc061SDimitry Andric // length. 557ff0cc061SDimitry Andric IsDWARF64 = true; 558ff0cc061SDimitry Andric Length = Data.getU64(&Offset); 559ff0cc061SDimitry Andric } 560ff0cc061SDimitry Andric 561ff0cc061SDimitry Andric // At this point, Offset points to the next field after Length. 562ff0cc061SDimitry Andric // Length is the structure size excluding itself. Compute an offset one 563ff0cc061SDimitry Andric // past the end of the structure (needed to know how many instructions to 564ff0cc061SDimitry Andric // read). 565ff0cc061SDimitry Andric // TODO: For honest DWARF64 support, DataExtractor will have to treat 566ff0cc061SDimitry Andric // offset_ptr as uint64_t* 5673ca95b02SDimitry Andric uint32_t StartStructureOffset = Offset; 568ff0cc061SDimitry Andric uint32_t EndStructureOffset = Offset + static_cast<uint32_t>(Length); 569ff0cc061SDimitry Andric 570ff0cc061SDimitry Andric // The Id field's size depends on the DWARF format 5713ca95b02SDimitry Andric Id = Data.getUnsigned(&Offset, (IsDWARF64 && !IsEH) ? 8 : 4); 5723ca95b02SDimitry Andric bool IsCIE = ((IsDWARF64 && Id == DW64_CIE_ID) || 5733ca95b02SDimitry Andric Id == DW_CIE_ID || 5743ca95b02SDimitry Andric (IsEH && !Id)); 575ff0cc061SDimitry Andric 576ff0cc061SDimitry Andric if (IsCIE) { 577ff0cc061SDimitry Andric uint8_t Version = Data.getU8(&Offset); 578ff0cc061SDimitry Andric const char *Augmentation = Data.getCStr(&Offset); 5793ca95b02SDimitry Andric StringRef AugmentationString(Augmentation ? Augmentation : ""); 5803ca95b02SDimitry Andric uint8_t AddressSize = Version < 4 ? Data.getAddressSize() : 5813ca95b02SDimitry Andric Data.getU8(&Offset); 582ff0cc061SDimitry Andric Data.setAddressSize(AddressSize); 583ff0cc061SDimitry Andric uint8_t SegmentDescriptorSize = Version < 4 ? 0 : Data.getU8(&Offset); 584ff0cc061SDimitry Andric uint64_t CodeAlignmentFactor = Data.getULEB128(&Offset); 585ff0cc061SDimitry Andric int64_t DataAlignmentFactor = Data.getSLEB128(&Offset); 586ff0cc061SDimitry Andric uint64_t ReturnAddressRegister = Data.getULEB128(&Offset); 587ff0cc061SDimitry Andric 5883ca95b02SDimitry Andric // Parse the augmentation data for EH CIEs 5893ca95b02SDimitry Andric StringRef AugmentationData(""); 5903ca95b02SDimitry Andric uint32_t FDEPointerEncoding = DW_EH_PE_omit; 5913ca95b02SDimitry Andric uint32_t LSDAPointerEncoding = DW_EH_PE_omit; 5923ca95b02SDimitry Andric if (IsEH) { 5933ca95b02SDimitry Andric Optional<uint32_t> PersonalityEncoding; 5943ca95b02SDimitry Andric Optional<uint64_t> Personality; 5953ca95b02SDimitry Andric 5963ca95b02SDimitry Andric Optional<uint64_t> AugmentationLength; 5973ca95b02SDimitry Andric uint32_t StartAugmentationOffset; 5983ca95b02SDimitry Andric uint32_t EndAugmentationOffset; 5993ca95b02SDimitry Andric 6003ca95b02SDimitry Andric // Walk the augmentation string to get all the augmentation data. 6013ca95b02SDimitry Andric for (unsigned i = 0, e = AugmentationString.size(); i != e; ++i) { 6023ca95b02SDimitry Andric switch (AugmentationString[i]) { 6033ca95b02SDimitry Andric default: 604edd7eaddSDimitry Andric ReportError(StartOffset, 605edd7eaddSDimitry Andric "Unknown augmentation character in entry at %lx"); 6063ca95b02SDimitry Andric case 'L': 6073ca95b02SDimitry Andric LSDAPointerEncoding = Data.getU8(&Offset); 6083ca95b02SDimitry Andric break; 6093ca95b02SDimitry Andric case 'P': { 6103ca95b02SDimitry Andric if (Personality) 611edd7eaddSDimitry Andric ReportError(StartOffset, 612edd7eaddSDimitry Andric "Duplicate personality in entry at %lx"); 6133ca95b02SDimitry Andric PersonalityEncoding = Data.getU8(&Offset); 6143ca95b02SDimitry Andric Personality = readPointer(Data, Offset, *PersonalityEncoding); 6153ca95b02SDimitry Andric break; 6163ca95b02SDimitry Andric } 6173ca95b02SDimitry Andric case 'R': 6183ca95b02SDimitry Andric FDEPointerEncoding = Data.getU8(&Offset); 6193ca95b02SDimitry Andric break; 6203ca95b02SDimitry Andric case 'z': 6213ca95b02SDimitry Andric if (i) 622edd7eaddSDimitry Andric ReportError(StartOffset, 623edd7eaddSDimitry Andric "'z' must be the first character at %lx"); 6243ca95b02SDimitry Andric // Parse the augmentation length first. We only parse it if 6253ca95b02SDimitry Andric // the string contains a 'z'. 6263ca95b02SDimitry Andric AugmentationLength = Data.getULEB128(&Offset); 6273ca95b02SDimitry Andric StartAugmentationOffset = Offset; 6283ca95b02SDimitry Andric EndAugmentationOffset = Offset + 6293ca95b02SDimitry Andric static_cast<uint32_t>(*AugmentationLength); 6303ca95b02SDimitry Andric } 6313ca95b02SDimitry Andric } 6323ca95b02SDimitry Andric 6333ca95b02SDimitry Andric if (AugmentationLength.hasValue()) { 6343ca95b02SDimitry Andric if (Offset != EndAugmentationOffset) 635edd7eaddSDimitry Andric ReportError(StartOffset, "Parsing augmentation data at %lx failed"); 6363ca95b02SDimitry Andric 6373ca95b02SDimitry Andric AugmentationData = Data.getData().slice(StartAugmentationOffset, 6383ca95b02SDimitry Andric EndAugmentationOffset); 6393ca95b02SDimitry Andric } 6403ca95b02SDimitry Andric } 6413ca95b02SDimitry Andric 642d88c1a5aSDimitry Andric auto Cie = llvm::make_unique<CIE>(StartOffset, Length, Version, 6433ca95b02SDimitry Andric AugmentationString, AddressSize, 644d88c1a5aSDimitry Andric SegmentDescriptorSize, 645d88c1a5aSDimitry Andric CodeAlignmentFactor, 646d88c1a5aSDimitry Andric DataAlignmentFactor, 647d88c1a5aSDimitry Andric ReturnAddressRegister, 6483ca95b02SDimitry Andric AugmentationData, FDEPointerEncoding, 6493ca95b02SDimitry Andric LSDAPointerEncoding); 650ff0cc061SDimitry Andric CIEs[StartOffset] = Cie.get(); 651ff0cc061SDimitry Andric Entries.emplace_back(std::move(Cie)); 652ff0cc061SDimitry Andric } else { 653ff0cc061SDimitry Andric // FDE 654ff0cc061SDimitry Andric uint64_t CIEPointer = Id; 6553ca95b02SDimitry Andric uint64_t InitialLocation = 0; 6563ca95b02SDimitry Andric uint64_t AddressRange = 0; 6573ca95b02SDimitry Andric CIE *Cie = CIEs[IsEH ? (StartStructureOffset - CIEPointer) : CIEPointer]; 6583ca95b02SDimitry Andric 6593ca95b02SDimitry Andric if (IsEH) { 6603ca95b02SDimitry Andric // The address size is encoded in the CIE we reference. 6613ca95b02SDimitry Andric if (!Cie) 662edd7eaddSDimitry Andric ReportError(StartOffset, 663edd7eaddSDimitry Andric "Parsing FDE data at %lx failed due to missing CIE"); 6643ca95b02SDimitry Andric 6653ca95b02SDimitry Andric InitialLocation = readPointer(Data, Offset, 6663ca95b02SDimitry Andric Cie->getFDEPointerEncoding()); 6673ca95b02SDimitry Andric AddressRange = readPointer(Data, Offset, 6683ca95b02SDimitry Andric Cie->getFDEPointerEncoding()); 6693ca95b02SDimitry Andric 6703ca95b02SDimitry Andric StringRef AugmentationString = Cie->getAugmentationString(); 6713ca95b02SDimitry Andric if (!AugmentationString.empty()) { 6723ca95b02SDimitry Andric // Parse the augmentation length and data for this FDE. 6733ca95b02SDimitry Andric uint64_t AugmentationLength = Data.getULEB128(&Offset); 6743ca95b02SDimitry Andric 6753ca95b02SDimitry Andric uint32_t EndAugmentationOffset = 6763ca95b02SDimitry Andric Offset + static_cast<uint32_t>(AugmentationLength); 6773ca95b02SDimitry Andric 6783ca95b02SDimitry Andric // Decode the LSDA if the CIE augmentation string said we should. 6793ca95b02SDimitry Andric if (Cie->getLSDAPointerEncoding() != DW_EH_PE_omit) 6803ca95b02SDimitry Andric readPointer(Data, Offset, Cie->getLSDAPointerEncoding()); 6813ca95b02SDimitry Andric 6823ca95b02SDimitry Andric if (Offset != EndAugmentationOffset) 683edd7eaddSDimitry Andric ReportError(StartOffset, "Parsing augmentation data at %lx failed"); 6843ca95b02SDimitry Andric } 6853ca95b02SDimitry Andric } else { 6863ca95b02SDimitry Andric InitialLocation = Data.getAddress(&Offset); 6873ca95b02SDimitry Andric AddressRange = Data.getAddress(&Offset); 6883ca95b02SDimitry Andric } 689ff0cc061SDimitry Andric 690ff0cc061SDimitry Andric Entries.emplace_back(new FDE(StartOffset, Length, CIEPointer, 691ff0cc061SDimitry Andric InitialLocation, AddressRange, 6923ca95b02SDimitry Andric Cie)); 693ff0cc061SDimitry Andric } 694ff0cc061SDimitry Andric 695ff0cc061SDimitry Andric Entries.back()->parseInstructions(Data, &Offset, EndStructureOffset); 696ff0cc061SDimitry Andric 6973ca95b02SDimitry Andric if (Offset != EndStructureOffset) 698edd7eaddSDimitry Andric ReportError(StartOffset, "Parsing entry instructions at %lx failed"); 699ff0cc061SDimitry Andric } 700ff0cc061SDimitry Andric } 701ff0cc061SDimitry Andric 7022cab237bSDimitry Andric FrameEntry *DWARFDebugFrame::getEntryAtOffset(uint64_t Offset) const { 7032cab237bSDimitry Andric auto It = 7042cab237bSDimitry Andric std::lower_bound(Entries.begin(), Entries.end(), Offset, 7052cab237bSDimitry Andric [](const std::unique_ptr<FrameEntry> &E, 7062cab237bSDimitry Andric uint64_t Offset) { return E->getOffset() < Offset; }); 7072cab237bSDimitry Andric if (It != Entries.end() && (*It)->getOffset() == Offset) 7082cab237bSDimitry Andric return It->get(); 7092cab237bSDimitry Andric return nullptr; 710ff0cc061SDimitry Andric } 7112cab237bSDimitry Andric 7122cab237bSDimitry Andric void DWARFDebugFrame::dump(raw_ostream &OS, Optional<uint64_t> Offset) const { 7132cab237bSDimitry Andric if (Offset) { 7142cab237bSDimitry Andric if (auto *Entry = getEntryAtOffset(*Offset)) 7152cab237bSDimitry Andric Entry->dump(OS); 7162cab237bSDimitry Andric return; 7172cab237bSDimitry Andric } 7182cab237bSDimitry Andric 7192cab237bSDimitry Andric OS << "\n"; 7202cab237bSDimitry Andric for (const auto &Entry : Entries) 7212cab237bSDimitry Andric Entry->dump(OS); 722ff0cc061SDimitry Andric } 723