10b57cec5SDimitry Andric //===- DWARFDebugFrame.h - Parsing of .debug_frame ------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h" 100b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h" 110b57cec5SDimitry Andric #include "llvm/ADT/Optional.h" 120b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h" 130b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 140b57cec5SDimitry Andric #include "llvm/BinaryFormat/Dwarf.h" 150b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 160b57cec5SDimitry Andric #include "llvm/Support/Compiler.h" 170b57cec5SDimitry Andric #include "llvm/Support/DataExtractor.h" 180b57cec5SDimitry Andric #include "llvm/Support/Errc.h" 190b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 200b57cec5SDimitry Andric #include "llvm/Support/Format.h" 210b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 220b57cec5SDimitry Andric #include <algorithm> 230b57cec5SDimitry Andric #include <cassert> 240b57cec5SDimitry Andric #include <cinttypes> 250b57cec5SDimitry Andric #include <cstdint> 260b57cec5SDimitry Andric #include <string> 270b57cec5SDimitry Andric #include <vector> 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric using namespace llvm; 300b57cec5SDimitry Andric using namespace dwarf; 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric // See DWARF standard v3, section 7.23 340b57cec5SDimitry Andric const uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK = 0xc0; 350b57cec5SDimitry Andric const uint8_t DWARF_CFI_PRIMARY_OPERAND_MASK = 0x3f; 360b57cec5SDimitry Andric 378bcb0991SDimitry Andric Error CFIProgram::parse(DWARFDataExtractor Data, uint64_t *Offset, 388bcb0991SDimitry Andric uint64_t EndOffset) { 39*5ffd83dbSDimitry Andric DataExtractor::Cursor C(*Offset); 40*5ffd83dbSDimitry Andric while (C && C.tell() < EndOffset) { 41*5ffd83dbSDimitry Andric uint8_t Opcode = Data.getRelocatedValue(C, 1); 42*5ffd83dbSDimitry Andric if (!C) 43*5ffd83dbSDimitry Andric break; 440b57cec5SDimitry Andric 45*5ffd83dbSDimitry Andric // Some instructions have a primary opcode encoded in the top bits. 46*5ffd83dbSDimitry Andric if (uint8_t Primary = Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK) { 470b57cec5SDimitry Andric // If it's a primary opcode, the first operand is encoded in the bottom 480b57cec5SDimitry Andric // bits of the opcode itself. 490b57cec5SDimitry Andric uint64_t Op1 = Opcode & DWARF_CFI_PRIMARY_OPERAND_MASK; 500b57cec5SDimitry Andric switch (Primary) { 510b57cec5SDimitry Andric case DW_CFA_advance_loc: 520b57cec5SDimitry Andric case DW_CFA_restore: 530b57cec5SDimitry Andric addInstruction(Primary, Op1); 540b57cec5SDimitry Andric break; 550b57cec5SDimitry Andric case DW_CFA_offset: 56*5ffd83dbSDimitry Andric addInstruction(Primary, Op1, Data.getULEB128(C)); 570b57cec5SDimitry Andric break; 58*5ffd83dbSDimitry Andric default: 59*5ffd83dbSDimitry Andric llvm_unreachable("invalid primary CFI opcode"); 600b57cec5SDimitry Andric } 61*5ffd83dbSDimitry Andric continue; 62*5ffd83dbSDimitry Andric } 63*5ffd83dbSDimitry Andric 640b57cec5SDimitry Andric // Extended opcode - its value is Opcode itself. 650b57cec5SDimitry Andric switch (Opcode) { 660b57cec5SDimitry Andric default: 670b57cec5SDimitry Andric return createStringError(errc::illegal_byte_sequence, 68*5ffd83dbSDimitry Andric "invalid extended CFI opcode 0x%" PRIx8, Opcode); 690b57cec5SDimitry Andric case DW_CFA_nop: 700b57cec5SDimitry Andric case DW_CFA_remember_state: 710b57cec5SDimitry Andric case DW_CFA_restore_state: 720b57cec5SDimitry Andric case DW_CFA_GNU_window_save: 730b57cec5SDimitry Andric // No operands 740b57cec5SDimitry Andric addInstruction(Opcode); 750b57cec5SDimitry Andric break; 760b57cec5SDimitry Andric case DW_CFA_set_loc: 770b57cec5SDimitry Andric // Operands: Address 78*5ffd83dbSDimitry Andric addInstruction(Opcode, Data.getRelocatedAddress(C)); 790b57cec5SDimitry Andric break; 800b57cec5SDimitry Andric case DW_CFA_advance_loc1: 810b57cec5SDimitry Andric // Operands: 1-byte delta 82*5ffd83dbSDimitry Andric addInstruction(Opcode, Data.getRelocatedValue(C, 1)); 830b57cec5SDimitry Andric break; 840b57cec5SDimitry Andric case DW_CFA_advance_loc2: 850b57cec5SDimitry Andric // Operands: 2-byte delta 86*5ffd83dbSDimitry Andric addInstruction(Opcode, Data.getRelocatedValue(C, 2)); 870b57cec5SDimitry Andric break; 880b57cec5SDimitry Andric case DW_CFA_advance_loc4: 890b57cec5SDimitry Andric // Operands: 4-byte delta 90*5ffd83dbSDimitry Andric addInstruction(Opcode, Data.getRelocatedValue(C, 4)); 910b57cec5SDimitry Andric break; 920b57cec5SDimitry Andric case DW_CFA_restore_extended: 930b57cec5SDimitry Andric case DW_CFA_undefined: 940b57cec5SDimitry Andric case DW_CFA_same_value: 950b57cec5SDimitry Andric case DW_CFA_def_cfa_register: 960b57cec5SDimitry Andric case DW_CFA_def_cfa_offset: 970b57cec5SDimitry Andric case DW_CFA_GNU_args_size: 980b57cec5SDimitry Andric // Operands: ULEB128 99*5ffd83dbSDimitry Andric addInstruction(Opcode, Data.getULEB128(C)); 1000b57cec5SDimitry Andric break; 1010b57cec5SDimitry Andric case DW_CFA_def_cfa_offset_sf: 1020b57cec5SDimitry Andric // Operands: SLEB128 103*5ffd83dbSDimitry Andric addInstruction(Opcode, Data.getSLEB128(C)); 1040b57cec5SDimitry Andric break; 1050b57cec5SDimitry Andric case DW_CFA_offset_extended: 1060b57cec5SDimitry Andric case DW_CFA_register: 1070b57cec5SDimitry Andric case DW_CFA_def_cfa: 1080b57cec5SDimitry Andric case DW_CFA_val_offset: { 1090b57cec5SDimitry Andric // Operands: ULEB128, ULEB128 1100b57cec5SDimitry Andric // Note: We can not embed getULEB128 directly into function 1110b57cec5SDimitry Andric // argument list. getULEB128 changes Offset and order of evaluation 1120b57cec5SDimitry Andric // for arguments is unspecified. 113*5ffd83dbSDimitry Andric uint64_t op1 = Data.getULEB128(C); 114*5ffd83dbSDimitry Andric uint64_t op2 = Data.getULEB128(C); 1150b57cec5SDimitry Andric addInstruction(Opcode, op1, op2); 1160b57cec5SDimitry Andric break; 1170b57cec5SDimitry Andric } 1180b57cec5SDimitry Andric case DW_CFA_offset_extended_sf: 1190b57cec5SDimitry Andric case DW_CFA_def_cfa_sf: 1200b57cec5SDimitry Andric case DW_CFA_val_offset_sf: { 1210b57cec5SDimitry Andric // Operands: ULEB128, SLEB128 1220b57cec5SDimitry Andric // Note: see comment for the previous case 123*5ffd83dbSDimitry Andric uint64_t op1 = Data.getULEB128(C); 124*5ffd83dbSDimitry Andric uint64_t op2 = (uint64_t)Data.getSLEB128(C); 1250b57cec5SDimitry Andric addInstruction(Opcode, op1, op2); 1260b57cec5SDimitry Andric break; 1270b57cec5SDimitry Andric } 1280b57cec5SDimitry Andric case DW_CFA_def_cfa_expression: { 129*5ffd83dbSDimitry Andric uint64_t ExprLength = Data.getULEB128(C); 1300b57cec5SDimitry Andric addInstruction(Opcode, 0); 131*5ffd83dbSDimitry Andric StringRef Expression = Data.getBytes(C, ExprLength); 132*5ffd83dbSDimitry Andric 133*5ffd83dbSDimitry Andric DataExtractor Extractor(Expression, Data.isLittleEndian(), 134*5ffd83dbSDimitry Andric Data.getAddressSize()); 135*5ffd83dbSDimitry Andric // Note. We do not pass the DWARF format to DWARFExpression, because 136*5ffd83dbSDimitry Andric // DW_OP_call_ref, the only operation which depends on the format, is 137*5ffd83dbSDimitry Andric // prohibited in call frame instructions, see sec. 6.4.2 in DWARFv5. 138*5ffd83dbSDimitry Andric Instructions.back().Expression = 139*5ffd83dbSDimitry Andric DWARFExpression(Extractor, Data.getAddressSize()); 1400b57cec5SDimitry Andric break; 1410b57cec5SDimitry Andric } 1420b57cec5SDimitry Andric case DW_CFA_expression: 1430b57cec5SDimitry Andric case DW_CFA_val_expression: { 144*5ffd83dbSDimitry Andric uint64_t RegNum = Data.getULEB128(C); 1450b57cec5SDimitry Andric addInstruction(Opcode, RegNum, 0); 146*5ffd83dbSDimitry Andric 147*5ffd83dbSDimitry Andric uint64_t BlockLength = Data.getULEB128(C); 148*5ffd83dbSDimitry Andric StringRef Expression = Data.getBytes(C, BlockLength); 149*5ffd83dbSDimitry Andric DataExtractor Extractor(Expression, Data.isLittleEndian(), 150*5ffd83dbSDimitry Andric Data.getAddressSize()); 151*5ffd83dbSDimitry Andric // Note. We do not pass the DWARF format to DWARFExpression, because 152*5ffd83dbSDimitry Andric // DW_OP_call_ref, the only operation which depends on the format, is 153*5ffd83dbSDimitry Andric // prohibited in call frame instructions, see sec. 6.4.2 in DWARFv5. 154*5ffd83dbSDimitry Andric Instructions.back().Expression = 155*5ffd83dbSDimitry Andric DWARFExpression(Extractor, Data.getAddressSize()); 1560b57cec5SDimitry Andric break; 1570b57cec5SDimitry Andric } 1580b57cec5SDimitry Andric } 1590b57cec5SDimitry Andric } 1600b57cec5SDimitry Andric 161*5ffd83dbSDimitry Andric *Offset = C.tell(); 162*5ffd83dbSDimitry Andric return C.takeError(); 1630b57cec5SDimitry Andric } 1640b57cec5SDimitry Andric 1650b57cec5SDimitry Andric namespace { 1660b57cec5SDimitry Andric 1670b57cec5SDimitry Andric 1680b57cec5SDimitry Andric } // end anonymous namespace 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric ArrayRef<CFIProgram::OperandType[2]> CFIProgram::getOperandTypes() { 1710b57cec5SDimitry Andric static OperandType OpTypes[DW_CFA_restore+1][2]; 1720b57cec5SDimitry Andric static bool Initialized = false; 1730b57cec5SDimitry Andric if (Initialized) { 1740b57cec5SDimitry Andric return ArrayRef<OperandType[2]>(&OpTypes[0], DW_CFA_restore+1); 1750b57cec5SDimitry Andric } 1760b57cec5SDimitry Andric Initialized = true; 1770b57cec5SDimitry Andric 1780b57cec5SDimitry Andric #define DECLARE_OP2(OP, OPTYPE0, OPTYPE1) \ 1790b57cec5SDimitry Andric do { \ 1800b57cec5SDimitry Andric OpTypes[OP][0] = OPTYPE0; \ 1810b57cec5SDimitry Andric OpTypes[OP][1] = OPTYPE1; \ 1820b57cec5SDimitry Andric } while (false) 1830b57cec5SDimitry Andric #define DECLARE_OP1(OP, OPTYPE0) DECLARE_OP2(OP, OPTYPE0, OT_None) 1840b57cec5SDimitry Andric #define DECLARE_OP0(OP) DECLARE_OP1(OP, OT_None) 1850b57cec5SDimitry Andric 1860b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_set_loc, OT_Address); 1870b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_advance_loc, OT_FactoredCodeOffset); 1880b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_advance_loc1, OT_FactoredCodeOffset); 1890b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_advance_loc2, OT_FactoredCodeOffset); 1900b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_advance_loc4, OT_FactoredCodeOffset); 1910b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_MIPS_advance_loc8, OT_FactoredCodeOffset); 1920b57cec5SDimitry Andric DECLARE_OP2(DW_CFA_def_cfa, OT_Register, OT_Offset); 1930b57cec5SDimitry Andric DECLARE_OP2(DW_CFA_def_cfa_sf, OT_Register, OT_SignedFactDataOffset); 1940b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_def_cfa_register, OT_Register); 1950b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_def_cfa_offset, OT_Offset); 1960b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_def_cfa_offset_sf, OT_SignedFactDataOffset); 1970b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_def_cfa_expression, OT_Expression); 1980b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_undefined, OT_Register); 1990b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_same_value, OT_Register); 2000b57cec5SDimitry Andric DECLARE_OP2(DW_CFA_offset, OT_Register, OT_UnsignedFactDataOffset); 2010b57cec5SDimitry Andric DECLARE_OP2(DW_CFA_offset_extended, OT_Register, OT_UnsignedFactDataOffset); 2020b57cec5SDimitry Andric DECLARE_OP2(DW_CFA_offset_extended_sf, OT_Register, OT_SignedFactDataOffset); 2030b57cec5SDimitry Andric DECLARE_OP2(DW_CFA_val_offset, OT_Register, OT_UnsignedFactDataOffset); 2040b57cec5SDimitry Andric DECLARE_OP2(DW_CFA_val_offset_sf, OT_Register, OT_SignedFactDataOffset); 2050b57cec5SDimitry Andric DECLARE_OP2(DW_CFA_register, OT_Register, OT_Register); 2060b57cec5SDimitry Andric DECLARE_OP2(DW_CFA_expression, OT_Register, OT_Expression); 2070b57cec5SDimitry Andric DECLARE_OP2(DW_CFA_val_expression, OT_Register, OT_Expression); 2080b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_restore, OT_Register); 2090b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_restore_extended, OT_Register); 2100b57cec5SDimitry Andric DECLARE_OP0(DW_CFA_remember_state); 2110b57cec5SDimitry Andric DECLARE_OP0(DW_CFA_restore_state); 2120b57cec5SDimitry Andric DECLARE_OP0(DW_CFA_GNU_window_save); 2130b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_GNU_args_size, OT_Offset); 2140b57cec5SDimitry Andric DECLARE_OP0(DW_CFA_nop); 2150b57cec5SDimitry Andric 2160b57cec5SDimitry Andric #undef DECLARE_OP0 2170b57cec5SDimitry Andric #undef DECLARE_OP1 2180b57cec5SDimitry Andric #undef DECLARE_OP2 2190b57cec5SDimitry Andric 2200b57cec5SDimitry Andric return ArrayRef<OperandType[2]>(&OpTypes[0], DW_CFA_restore+1); 2210b57cec5SDimitry Andric } 2220b57cec5SDimitry Andric 2230b57cec5SDimitry Andric /// Print \p Opcode's operand number \p OperandIdx which has value \p Operand. 2240b57cec5SDimitry Andric void CFIProgram::printOperand(raw_ostream &OS, const MCRegisterInfo *MRI, 2250b57cec5SDimitry Andric bool IsEH, const Instruction &Instr, 2260b57cec5SDimitry Andric unsigned OperandIdx, uint64_t Operand) const { 2270b57cec5SDimitry Andric assert(OperandIdx < 2); 2280b57cec5SDimitry Andric uint8_t Opcode = Instr.Opcode; 2290b57cec5SDimitry Andric OperandType Type = getOperandTypes()[Opcode][OperandIdx]; 2300b57cec5SDimitry Andric 2310b57cec5SDimitry Andric switch (Type) { 2320b57cec5SDimitry Andric case OT_Unset: { 2330b57cec5SDimitry Andric OS << " Unsupported " << (OperandIdx ? "second" : "first") << " operand to"; 2340b57cec5SDimitry Andric auto OpcodeName = CallFrameString(Opcode, Arch); 2350b57cec5SDimitry Andric if (!OpcodeName.empty()) 2360b57cec5SDimitry Andric OS << " " << OpcodeName; 2370b57cec5SDimitry Andric else 2380b57cec5SDimitry Andric OS << format(" Opcode %x", Opcode); 2390b57cec5SDimitry Andric break; 2400b57cec5SDimitry Andric } 2410b57cec5SDimitry Andric case OT_None: 2420b57cec5SDimitry Andric break; 2430b57cec5SDimitry Andric case OT_Address: 2440b57cec5SDimitry Andric OS << format(" %" PRIx64, Operand); 2450b57cec5SDimitry Andric break; 2460b57cec5SDimitry Andric case OT_Offset: 2470b57cec5SDimitry Andric // The offsets are all encoded in a unsigned form, but in practice 2480b57cec5SDimitry Andric // consumers use them signed. It's most certainly legacy due to 2490b57cec5SDimitry Andric // the lack of signed variants in the first Dwarf standards. 2500b57cec5SDimitry Andric OS << format(" %+" PRId64, int64_t(Operand)); 2510b57cec5SDimitry Andric break; 2520b57cec5SDimitry Andric case OT_FactoredCodeOffset: // Always Unsigned 2530b57cec5SDimitry Andric if (CodeAlignmentFactor) 2540b57cec5SDimitry Andric OS << format(" %" PRId64, Operand * CodeAlignmentFactor); 2550b57cec5SDimitry Andric else 2560b57cec5SDimitry Andric OS << format(" %" PRId64 "*code_alignment_factor" , Operand); 2570b57cec5SDimitry Andric break; 2580b57cec5SDimitry Andric case OT_SignedFactDataOffset: 2590b57cec5SDimitry Andric if (DataAlignmentFactor) 2600b57cec5SDimitry Andric OS << format(" %" PRId64, int64_t(Operand) * DataAlignmentFactor); 2610b57cec5SDimitry Andric else 2620b57cec5SDimitry Andric OS << format(" %" PRId64 "*data_alignment_factor" , int64_t(Operand)); 2630b57cec5SDimitry Andric break; 2640b57cec5SDimitry Andric case OT_UnsignedFactDataOffset: 2650b57cec5SDimitry Andric if (DataAlignmentFactor) 2660b57cec5SDimitry Andric OS << format(" %" PRId64, Operand * DataAlignmentFactor); 2670b57cec5SDimitry Andric else 2680b57cec5SDimitry Andric OS << format(" %" PRId64 "*data_alignment_factor" , Operand); 2690b57cec5SDimitry Andric break; 2700b57cec5SDimitry Andric case OT_Register: 2710b57cec5SDimitry Andric OS << format(" reg%" PRId64, Operand); 2720b57cec5SDimitry Andric break; 2730b57cec5SDimitry Andric case OT_Expression: 2740b57cec5SDimitry Andric assert(Instr.Expression && "missing DWARFExpression object"); 2750b57cec5SDimitry Andric OS << " "; 2760b57cec5SDimitry Andric Instr.Expression->print(OS, MRI, nullptr, IsEH); 2770b57cec5SDimitry Andric break; 2780b57cec5SDimitry Andric } 2790b57cec5SDimitry Andric } 2800b57cec5SDimitry Andric 2810b57cec5SDimitry Andric void CFIProgram::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH, 2820b57cec5SDimitry Andric unsigned IndentLevel) const { 2830b57cec5SDimitry Andric for (const auto &Instr : Instructions) { 2840b57cec5SDimitry Andric uint8_t Opcode = Instr.Opcode; 2850b57cec5SDimitry Andric if (Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK) 2860b57cec5SDimitry Andric Opcode &= DWARF_CFI_PRIMARY_OPCODE_MASK; 2870b57cec5SDimitry Andric OS.indent(2 * IndentLevel); 2880b57cec5SDimitry Andric OS << CallFrameString(Opcode, Arch) << ":"; 2890b57cec5SDimitry Andric for (unsigned i = 0; i < Instr.Ops.size(); ++i) 2900b57cec5SDimitry Andric printOperand(OS, MRI, IsEH, Instr, i, Instr.Ops[i]); 2910b57cec5SDimitry Andric OS << '\n'; 2920b57cec5SDimitry Andric } 2930b57cec5SDimitry Andric } 2940b57cec5SDimitry Andric 295*5ffd83dbSDimitry Andric // Returns the CIE identifier to be used by the requested format. 296*5ffd83dbSDimitry Andric // CIE ids for .debug_frame sections are defined in Section 7.24 of DWARFv5. 297*5ffd83dbSDimitry Andric // For CIE ID in .eh_frame sections see 298*5ffd83dbSDimitry Andric // https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html 299*5ffd83dbSDimitry Andric constexpr uint64_t getCIEId(bool IsDWARF64, bool IsEH) { 300*5ffd83dbSDimitry Andric if (IsEH) 301*5ffd83dbSDimitry Andric return 0; 302*5ffd83dbSDimitry Andric if (IsDWARF64) 303*5ffd83dbSDimitry Andric return DW64_CIE_ID; 304*5ffd83dbSDimitry Andric return DW_CIE_ID; 305*5ffd83dbSDimitry Andric } 306*5ffd83dbSDimitry Andric 3070b57cec5SDimitry Andric void CIE::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH) const { 308*5ffd83dbSDimitry Andric // A CIE with a zero length is a terminator entry in the .eh_frame section. 309*5ffd83dbSDimitry Andric if (IsEH && Length == 0) { 310*5ffd83dbSDimitry Andric OS << format("%08" PRIx64, Offset) << " ZERO terminator\n"; 311*5ffd83dbSDimitry Andric return; 312*5ffd83dbSDimitry Andric } 313*5ffd83dbSDimitry Andric 314*5ffd83dbSDimitry Andric OS << format("%08" PRIx64, Offset) 315*5ffd83dbSDimitry Andric << format(" %0*" PRIx64, IsDWARF64 ? 16 : 8, Length) 316*5ffd83dbSDimitry Andric << format(" %0*" PRIx64, IsDWARF64 && !IsEH ? 16 : 8, 317*5ffd83dbSDimitry Andric getCIEId(IsDWARF64, IsEH)) 318*5ffd83dbSDimitry Andric << " CIE\n" 319*5ffd83dbSDimitry Andric << " Format: " << FormatString(IsDWARF64) << "\n" 320*5ffd83dbSDimitry Andric << format(" Version: %d\n", Version) 321*5ffd83dbSDimitry Andric << " Augmentation: \"" << Augmentation << "\"\n"; 3220b57cec5SDimitry Andric if (Version >= 4) { 3230b57cec5SDimitry Andric OS << format(" Address size: %u\n", (uint32_t)AddressSize); 3240b57cec5SDimitry Andric OS << format(" Segment desc size: %u\n", 3250b57cec5SDimitry Andric (uint32_t)SegmentDescriptorSize); 3260b57cec5SDimitry Andric } 3270b57cec5SDimitry Andric OS << format(" Code alignment factor: %u\n", (uint32_t)CodeAlignmentFactor); 3280b57cec5SDimitry Andric OS << format(" Data alignment factor: %d\n", (int32_t)DataAlignmentFactor); 3290b57cec5SDimitry Andric OS << format(" Return address column: %d\n", (int32_t)ReturnAddressRegister); 3300b57cec5SDimitry Andric if (Personality) 3310b57cec5SDimitry Andric OS << format(" Personality Address: %016" PRIx64 "\n", *Personality); 3320b57cec5SDimitry Andric if (!AugmentationData.empty()) { 3330b57cec5SDimitry Andric OS << " Augmentation data: "; 3340b57cec5SDimitry Andric for (uint8_t Byte : AugmentationData) 3350b57cec5SDimitry Andric OS << ' ' << hexdigit(Byte >> 4) << hexdigit(Byte & 0xf); 3360b57cec5SDimitry Andric OS << "\n"; 3370b57cec5SDimitry Andric } 3380b57cec5SDimitry Andric OS << "\n"; 3390b57cec5SDimitry Andric CFIs.dump(OS, MRI, IsEH); 3400b57cec5SDimitry Andric OS << "\n"; 3410b57cec5SDimitry Andric } 3420b57cec5SDimitry Andric 3430b57cec5SDimitry Andric void FDE::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH) const { 344*5ffd83dbSDimitry Andric OS << format("%08" PRIx64, Offset) 345*5ffd83dbSDimitry Andric << format(" %0*" PRIx64, IsDWARF64 ? 16 : 8, Length) 346*5ffd83dbSDimitry Andric << format(" %0*" PRIx64, IsDWARF64 && !IsEH ? 16 : 8, CIEPointer) 347*5ffd83dbSDimitry Andric << " FDE cie="; 348*5ffd83dbSDimitry Andric if (LinkedCIE) 349*5ffd83dbSDimitry Andric OS << format("%08" PRIx64, LinkedCIE->getOffset()); 350*5ffd83dbSDimitry Andric else 351*5ffd83dbSDimitry Andric OS << "<invalid offset>"; 352*5ffd83dbSDimitry Andric OS << format(" pc=%08" PRIx64 "...%08" PRIx64 "\n", InitialLocation, 353*5ffd83dbSDimitry Andric InitialLocation + AddressRange); 354*5ffd83dbSDimitry Andric OS << " Format: " << FormatString(IsDWARF64) << "\n"; 3550b57cec5SDimitry Andric if (LSDAAddress) 3560b57cec5SDimitry Andric OS << format(" LSDA Address: %016" PRIx64 "\n", *LSDAAddress); 3570b57cec5SDimitry Andric CFIs.dump(OS, MRI, IsEH); 3580b57cec5SDimitry Andric OS << "\n"; 3590b57cec5SDimitry Andric } 3600b57cec5SDimitry Andric 3610b57cec5SDimitry Andric DWARFDebugFrame::DWARFDebugFrame(Triple::ArchType Arch, 3620b57cec5SDimitry Andric bool IsEH, uint64_t EHFrameAddress) 3630b57cec5SDimitry Andric : Arch(Arch), IsEH(IsEH), EHFrameAddress(EHFrameAddress) {} 3640b57cec5SDimitry Andric 3650b57cec5SDimitry Andric DWARFDebugFrame::~DWARFDebugFrame() = default; 3660b57cec5SDimitry Andric 3670b57cec5SDimitry Andric static void LLVM_ATTRIBUTE_UNUSED dumpDataAux(DataExtractor Data, 3688bcb0991SDimitry Andric uint64_t Offset, int Length) { 3690b57cec5SDimitry Andric errs() << "DUMP: "; 3700b57cec5SDimitry Andric for (int i = 0; i < Length; ++i) { 3710b57cec5SDimitry Andric uint8_t c = Data.getU8(&Offset); 3720b57cec5SDimitry Andric errs().write_hex(c); errs() << " "; 3730b57cec5SDimitry Andric } 3740b57cec5SDimitry Andric errs() << "\n"; 3750b57cec5SDimitry Andric } 3760b57cec5SDimitry Andric 377*5ffd83dbSDimitry Andric Error DWARFDebugFrame::parse(DWARFDataExtractor Data) { 3788bcb0991SDimitry Andric uint64_t Offset = 0; 3798bcb0991SDimitry Andric DenseMap<uint64_t, CIE *> CIEs; 3800b57cec5SDimitry Andric 3810b57cec5SDimitry Andric while (Data.isValidOffset(Offset)) { 3828bcb0991SDimitry Andric uint64_t StartOffset = Offset; 3830b57cec5SDimitry Andric 384*5ffd83dbSDimitry Andric uint64_t Length; 385*5ffd83dbSDimitry Andric DwarfFormat Format; 386*5ffd83dbSDimitry Andric std::tie(Length, Format) = Data.getInitialLength(&Offset); 387*5ffd83dbSDimitry Andric bool IsDWARF64 = Format == DWARF64; 3880b57cec5SDimitry Andric 389*5ffd83dbSDimitry Andric // If the Length is 0, then this CIE is a terminator. We add it because some 390*5ffd83dbSDimitry Andric // dumper tools might need it to print something special for such entries 391*5ffd83dbSDimitry Andric // (e.g. llvm-objdump --dwarf=frames prints "ZERO terminator"). 392*5ffd83dbSDimitry Andric if (Length == 0) { 393*5ffd83dbSDimitry Andric auto Cie = std::make_unique<CIE>( 394*5ffd83dbSDimitry Andric IsDWARF64, StartOffset, 0, 0, SmallString<8>(), 0, 0, 0, 0, 0, 395*5ffd83dbSDimitry Andric SmallString<8>(), 0, 0, None, None, Arch); 396*5ffd83dbSDimitry Andric CIEs[StartOffset] = Cie.get(); 397*5ffd83dbSDimitry Andric Entries.push_back(std::move(Cie)); 398*5ffd83dbSDimitry Andric break; 3990b57cec5SDimitry Andric } 4000b57cec5SDimitry Andric 4010b57cec5SDimitry Andric // At this point, Offset points to the next field after Length. 4020b57cec5SDimitry Andric // Length is the structure size excluding itself. Compute an offset one 4030b57cec5SDimitry Andric // past the end of the structure (needed to know how many instructions to 4040b57cec5SDimitry Andric // read). 4058bcb0991SDimitry Andric uint64_t StartStructureOffset = Offset; 4068bcb0991SDimitry Andric uint64_t EndStructureOffset = Offset + Length; 4070b57cec5SDimitry Andric 4080b57cec5SDimitry Andric // The Id field's size depends on the DWARF format 409*5ffd83dbSDimitry Andric Error Err = Error::success(); 410*5ffd83dbSDimitry Andric uint64_t Id = Data.getRelocatedValue((IsDWARF64 && !IsEH) ? 8 : 4, &Offset, 411*5ffd83dbSDimitry Andric /*SectionIndex=*/nullptr, &Err); 412*5ffd83dbSDimitry Andric if (Err) 413*5ffd83dbSDimitry Andric return Err; 4140b57cec5SDimitry Andric 415*5ffd83dbSDimitry Andric if (Id == getCIEId(IsDWARF64, IsEH)) { 4160b57cec5SDimitry Andric uint8_t Version = Data.getU8(&Offset); 4170b57cec5SDimitry Andric const char *Augmentation = Data.getCStr(&Offset); 4180b57cec5SDimitry Andric StringRef AugmentationString(Augmentation ? Augmentation : ""); 419*5ffd83dbSDimitry Andric // TODO: we should provide a way to report a warning and continue dumping. 420*5ffd83dbSDimitry Andric if (IsEH && Version != 1) 421*5ffd83dbSDimitry Andric return createStringError(errc::not_supported, 422*5ffd83dbSDimitry Andric "unsupported CIE version: %" PRIu8, Version); 423*5ffd83dbSDimitry Andric 4240b57cec5SDimitry Andric uint8_t AddressSize = Version < 4 ? Data.getAddressSize() : 4250b57cec5SDimitry Andric Data.getU8(&Offset); 4260b57cec5SDimitry Andric Data.setAddressSize(AddressSize); 4270b57cec5SDimitry Andric uint8_t SegmentDescriptorSize = Version < 4 ? 0 : Data.getU8(&Offset); 4280b57cec5SDimitry Andric uint64_t CodeAlignmentFactor = Data.getULEB128(&Offset); 4290b57cec5SDimitry Andric int64_t DataAlignmentFactor = Data.getSLEB128(&Offset); 4300b57cec5SDimitry Andric uint64_t ReturnAddressRegister = 4310b57cec5SDimitry Andric Version == 1 ? Data.getU8(&Offset) : Data.getULEB128(&Offset); 4320b57cec5SDimitry Andric 4330b57cec5SDimitry Andric // Parse the augmentation data for EH CIEs 4340b57cec5SDimitry Andric StringRef AugmentationData(""); 4350b57cec5SDimitry Andric uint32_t FDEPointerEncoding = DW_EH_PE_absptr; 4360b57cec5SDimitry Andric uint32_t LSDAPointerEncoding = DW_EH_PE_omit; 4370b57cec5SDimitry Andric Optional<uint64_t> Personality; 4380b57cec5SDimitry Andric Optional<uint32_t> PersonalityEncoding; 4390b57cec5SDimitry Andric if (IsEH) { 4400b57cec5SDimitry Andric Optional<uint64_t> AugmentationLength; 4418bcb0991SDimitry Andric uint64_t StartAugmentationOffset; 4428bcb0991SDimitry Andric uint64_t EndAugmentationOffset; 4430b57cec5SDimitry Andric 4440b57cec5SDimitry Andric // Walk the augmentation string to get all the augmentation data. 4450b57cec5SDimitry Andric for (unsigned i = 0, e = AugmentationString.size(); i != e; ++i) { 4460b57cec5SDimitry Andric switch (AugmentationString[i]) { 4470b57cec5SDimitry Andric default: 448*5ffd83dbSDimitry Andric return createStringError( 449*5ffd83dbSDimitry Andric errc::invalid_argument, 450*5ffd83dbSDimitry Andric "unknown augmentation character in entry at 0x%" PRIx64, 451*5ffd83dbSDimitry Andric StartOffset); 4520b57cec5SDimitry Andric case 'L': 4530b57cec5SDimitry Andric LSDAPointerEncoding = Data.getU8(&Offset); 4540b57cec5SDimitry Andric break; 4550b57cec5SDimitry Andric case 'P': { 4560b57cec5SDimitry Andric if (Personality) 457*5ffd83dbSDimitry Andric return createStringError( 458*5ffd83dbSDimitry Andric errc::invalid_argument, 459*5ffd83dbSDimitry Andric "duplicate personality in entry at 0x%" PRIx64, StartOffset); 4600b57cec5SDimitry Andric PersonalityEncoding = Data.getU8(&Offset); 4610b57cec5SDimitry Andric Personality = Data.getEncodedPointer( 4620b57cec5SDimitry Andric &Offset, *PersonalityEncoding, 4630b57cec5SDimitry Andric EHFrameAddress ? EHFrameAddress + Offset : 0); 4640b57cec5SDimitry Andric break; 4650b57cec5SDimitry Andric } 4660b57cec5SDimitry Andric case 'R': 4670b57cec5SDimitry Andric FDEPointerEncoding = Data.getU8(&Offset); 4680b57cec5SDimitry Andric break; 4690b57cec5SDimitry Andric case 'S': 4700b57cec5SDimitry Andric // Current frame is a signal trampoline. 4710b57cec5SDimitry Andric break; 4720b57cec5SDimitry Andric case 'z': 4730b57cec5SDimitry Andric if (i) 474*5ffd83dbSDimitry Andric return createStringError( 475*5ffd83dbSDimitry Andric errc::invalid_argument, 476*5ffd83dbSDimitry Andric "'z' must be the first character at 0x%" PRIx64, StartOffset); 4770b57cec5SDimitry Andric // Parse the augmentation length first. We only parse it if 4780b57cec5SDimitry Andric // the string contains a 'z'. 4790b57cec5SDimitry Andric AugmentationLength = Data.getULEB128(&Offset); 4800b57cec5SDimitry Andric StartAugmentationOffset = Offset; 4818bcb0991SDimitry Andric EndAugmentationOffset = Offset + *AugmentationLength; 4820b57cec5SDimitry Andric break; 4830b57cec5SDimitry Andric case 'B': 4840b57cec5SDimitry Andric // B-Key is used for signing functions associated with this 4850b57cec5SDimitry Andric // augmentation string 4860b57cec5SDimitry Andric break; 4870b57cec5SDimitry Andric } 4880b57cec5SDimitry Andric } 4890b57cec5SDimitry Andric 4900b57cec5SDimitry Andric if (AugmentationLength.hasValue()) { 4910b57cec5SDimitry Andric if (Offset != EndAugmentationOffset) 492*5ffd83dbSDimitry Andric return createStringError(errc::invalid_argument, 493*5ffd83dbSDimitry Andric "parsing augmentation data at 0x%" PRIx64 494*5ffd83dbSDimitry Andric " failed", 495*5ffd83dbSDimitry Andric StartOffset); 4960b57cec5SDimitry Andric AugmentationData = Data.getData().slice(StartAugmentationOffset, 4970b57cec5SDimitry Andric EndAugmentationOffset); 4980b57cec5SDimitry Andric } 4990b57cec5SDimitry Andric } 5000b57cec5SDimitry Andric 5018bcb0991SDimitry Andric auto Cie = std::make_unique<CIE>( 502*5ffd83dbSDimitry Andric IsDWARF64, StartOffset, Length, Version, AugmentationString, 503*5ffd83dbSDimitry Andric AddressSize, SegmentDescriptorSize, CodeAlignmentFactor, 504*5ffd83dbSDimitry Andric DataAlignmentFactor, ReturnAddressRegister, AugmentationData, 505*5ffd83dbSDimitry Andric FDEPointerEncoding, LSDAPointerEncoding, Personality, 506*5ffd83dbSDimitry Andric PersonalityEncoding, Arch); 5070b57cec5SDimitry Andric CIEs[StartOffset] = Cie.get(); 5080b57cec5SDimitry Andric Entries.emplace_back(std::move(Cie)); 5090b57cec5SDimitry Andric } else { 5100b57cec5SDimitry Andric // FDE 5110b57cec5SDimitry Andric uint64_t CIEPointer = Id; 5120b57cec5SDimitry Andric uint64_t InitialLocation = 0; 5130b57cec5SDimitry Andric uint64_t AddressRange = 0; 5140b57cec5SDimitry Andric Optional<uint64_t> LSDAAddress; 5150b57cec5SDimitry Andric CIE *Cie = CIEs[IsEH ? (StartStructureOffset - CIEPointer) : CIEPointer]; 5160b57cec5SDimitry Andric 5170b57cec5SDimitry Andric if (IsEH) { 5180b57cec5SDimitry Andric // The address size is encoded in the CIE we reference. 5190b57cec5SDimitry Andric if (!Cie) 520*5ffd83dbSDimitry Andric return createStringError(errc::invalid_argument, 521*5ffd83dbSDimitry Andric "parsing FDE data at 0x%" PRIx64 522*5ffd83dbSDimitry Andric " failed due to missing CIE", 523*5ffd83dbSDimitry Andric StartOffset); 5240b57cec5SDimitry Andric if (auto Val = Data.getEncodedPointer( 5250b57cec5SDimitry Andric &Offset, Cie->getFDEPointerEncoding(), 5260b57cec5SDimitry Andric EHFrameAddress ? EHFrameAddress + Offset : 0)) { 5270b57cec5SDimitry Andric InitialLocation = *Val; 5280b57cec5SDimitry Andric } 5290b57cec5SDimitry Andric if (auto Val = Data.getEncodedPointer( 5300b57cec5SDimitry Andric &Offset, Cie->getFDEPointerEncoding(), 0)) { 5310b57cec5SDimitry Andric AddressRange = *Val; 5320b57cec5SDimitry Andric } 5330b57cec5SDimitry Andric 5340b57cec5SDimitry Andric StringRef AugmentationString = Cie->getAugmentationString(); 5350b57cec5SDimitry Andric if (!AugmentationString.empty()) { 5360b57cec5SDimitry Andric // Parse the augmentation length and data for this FDE. 5370b57cec5SDimitry Andric uint64_t AugmentationLength = Data.getULEB128(&Offset); 5380b57cec5SDimitry Andric 5398bcb0991SDimitry Andric uint64_t EndAugmentationOffset = Offset + AugmentationLength; 5400b57cec5SDimitry Andric 5410b57cec5SDimitry Andric // Decode the LSDA if the CIE augmentation string said we should. 5420b57cec5SDimitry Andric if (Cie->getLSDAPointerEncoding() != DW_EH_PE_omit) { 5430b57cec5SDimitry Andric LSDAAddress = Data.getEncodedPointer( 5440b57cec5SDimitry Andric &Offset, Cie->getLSDAPointerEncoding(), 5450b57cec5SDimitry Andric EHFrameAddress ? Offset + EHFrameAddress : 0); 5460b57cec5SDimitry Andric } 5470b57cec5SDimitry Andric 5480b57cec5SDimitry Andric if (Offset != EndAugmentationOffset) 549*5ffd83dbSDimitry Andric return createStringError(errc::invalid_argument, 550*5ffd83dbSDimitry Andric "parsing augmentation data at 0x%" PRIx64 551*5ffd83dbSDimitry Andric " failed", 552*5ffd83dbSDimitry Andric StartOffset); 5530b57cec5SDimitry Andric } 5540b57cec5SDimitry Andric } else { 5550b57cec5SDimitry Andric InitialLocation = Data.getRelocatedAddress(&Offset); 5560b57cec5SDimitry Andric AddressRange = Data.getRelocatedAddress(&Offset); 5570b57cec5SDimitry Andric } 5580b57cec5SDimitry Andric 559*5ffd83dbSDimitry Andric Entries.emplace_back(new FDE(IsDWARF64, StartOffset, Length, CIEPointer, 560*5ffd83dbSDimitry Andric InitialLocation, AddressRange, Cie, 561*5ffd83dbSDimitry Andric LSDAAddress, Arch)); 5620b57cec5SDimitry Andric } 5630b57cec5SDimitry Andric 5640b57cec5SDimitry Andric if (Error E = 565*5ffd83dbSDimitry Andric Entries.back()->cfis().parse(Data, &Offset, EndStructureOffset)) 566*5ffd83dbSDimitry Andric return E; 5670b57cec5SDimitry Andric 5680b57cec5SDimitry Andric if (Offset != EndStructureOffset) 569*5ffd83dbSDimitry Andric return createStringError( 570*5ffd83dbSDimitry Andric errc::invalid_argument, 571*5ffd83dbSDimitry Andric "parsing entry instructions at 0x%" PRIx64 " failed", StartOffset); 5720b57cec5SDimitry Andric } 573*5ffd83dbSDimitry Andric 574*5ffd83dbSDimitry Andric return Error::success(); 5750b57cec5SDimitry Andric } 5760b57cec5SDimitry Andric 5770b57cec5SDimitry Andric FrameEntry *DWARFDebugFrame::getEntryAtOffset(uint64_t Offset) const { 5780b57cec5SDimitry Andric auto It = partition_point(Entries, [=](const std::unique_ptr<FrameEntry> &E) { 5790b57cec5SDimitry Andric return E->getOffset() < Offset; 5800b57cec5SDimitry Andric }); 5810b57cec5SDimitry Andric if (It != Entries.end() && (*It)->getOffset() == Offset) 5820b57cec5SDimitry Andric return It->get(); 5830b57cec5SDimitry Andric return nullptr; 5840b57cec5SDimitry Andric } 5850b57cec5SDimitry Andric 5860b57cec5SDimitry Andric void DWARFDebugFrame::dump(raw_ostream &OS, const MCRegisterInfo *MRI, 5870b57cec5SDimitry Andric Optional<uint64_t> Offset) const { 5880b57cec5SDimitry Andric if (Offset) { 5890b57cec5SDimitry Andric if (auto *Entry = getEntryAtOffset(*Offset)) 5900b57cec5SDimitry Andric Entry->dump(OS, MRI, IsEH); 5910b57cec5SDimitry Andric return; 5920b57cec5SDimitry Andric } 5930b57cec5SDimitry Andric 5940b57cec5SDimitry Andric OS << "\n"; 5950b57cec5SDimitry Andric for (const auto &Entry : Entries) 5960b57cec5SDimitry Andric Entry->dump(OS, MRI, IsEH); 5970b57cec5SDimitry Andric } 598