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" 15*e8d8bef9SDimitry Andric #include "llvm/MC/MCRegisterInfo.h" 160b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 170b57cec5SDimitry Andric #include "llvm/Support/Compiler.h" 180b57cec5SDimitry Andric #include "llvm/Support/DataExtractor.h" 190b57cec5SDimitry Andric #include "llvm/Support/Errc.h" 200b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 210b57cec5SDimitry Andric #include "llvm/Support/Format.h" 220b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 230b57cec5SDimitry Andric #include <algorithm> 240b57cec5SDimitry Andric #include <cassert> 250b57cec5SDimitry Andric #include <cinttypes> 260b57cec5SDimitry Andric #include <cstdint> 270b57cec5SDimitry Andric #include <string> 280b57cec5SDimitry Andric #include <vector> 290b57cec5SDimitry Andric 300b57cec5SDimitry Andric using namespace llvm; 310b57cec5SDimitry Andric using namespace dwarf; 320b57cec5SDimitry Andric 33*e8d8bef9SDimitry Andric static void printRegister(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH, 34*e8d8bef9SDimitry Andric unsigned RegNum) { 35*e8d8bef9SDimitry Andric if (MRI) { 36*e8d8bef9SDimitry Andric if (Optional<unsigned> LLVMRegNum = MRI->getLLVMRegNum(RegNum, IsEH)) { 37*e8d8bef9SDimitry Andric if (const char *RegName = MRI->getName(*LLVMRegNum)) { 38*e8d8bef9SDimitry Andric OS << RegName; 39*e8d8bef9SDimitry Andric return; 40*e8d8bef9SDimitry Andric } 41*e8d8bef9SDimitry Andric } 42*e8d8bef9SDimitry Andric } 43*e8d8bef9SDimitry Andric OS << "reg" << RegNum; 44*e8d8bef9SDimitry Andric } 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric // See DWARF standard v3, section 7.23 470b57cec5SDimitry Andric const uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK = 0xc0; 480b57cec5SDimitry Andric const uint8_t DWARF_CFI_PRIMARY_OPERAND_MASK = 0x3f; 490b57cec5SDimitry Andric 508bcb0991SDimitry Andric Error CFIProgram::parse(DWARFDataExtractor Data, uint64_t *Offset, 518bcb0991SDimitry Andric uint64_t EndOffset) { 525ffd83dbSDimitry Andric DataExtractor::Cursor C(*Offset); 535ffd83dbSDimitry Andric while (C && C.tell() < EndOffset) { 545ffd83dbSDimitry Andric uint8_t Opcode = Data.getRelocatedValue(C, 1); 555ffd83dbSDimitry Andric if (!C) 565ffd83dbSDimitry Andric break; 570b57cec5SDimitry Andric 585ffd83dbSDimitry Andric // Some instructions have a primary opcode encoded in the top bits. 595ffd83dbSDimitry Andric if (uint8_t Primary = Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK) { 600b57cec5SDimitry Andric // If it's a primary opcode, the first operand is encoded in the bottom 610b57cec5SDimitry Andric // bits of the opcode itself. 620b57cec5SDimitry Andric uint64_t Op1 = Opcode & DWARF_CFI_PRIMARY_OPERAND_MASK; 630b57cec5SDimitry Andric switch (Primary) { 640b57cec5SDimitry Andric case DW_CFA_advance_loc: 650b57cec5SDimitry Andric case DW_CFA_restore: 660b57cec5SDimitry Andric addInstruction(Primary, Op1); 670b57cec5SDimitry Andric break; 680b57cec5SDimitry Andric case DW_CFA_offset: 695ffd83dbSDimitry Andric addInstruction(Primary, Op1, Data.getULEB128(C)); 700b57cec5SDimitry Andric break; 715ffd83dbSDimitry Andric default: 725ffd83dbSDimitry Andric llvm_unreachable("invalid primary CFI opcode"); 730b57cec5SDimitry Andric } 745ffd83dbSDimitry Andric continue; 755ffd83dbSDimitry Andric } 765ffd83dbSDimitry Andric 770b57cec5SDimitry Andric // Extended opcode - its value is Opcode itself. 780b57cec5SDimitry Andric switch (Opcode) { 790b57cec5SDimitry Andric default: 800b57cec5SDimitry Andric return createStringError(errc::illegal_byte_sequence, 815ffd83dbSDimitry Andric "invalid extended CFI opcode 0x%" PRIx8, Opcode); 820b57cec5SDimitry Andric case DW_CFA_nop: 830b57cec5SDimitry Andric case DW_CFA_remember_state: 840b57cec5SDimitry Andric case DW_CFA_restore_state: 850b57cec5SDimitry Andric case DW_CFA_GNU_window_save: 860b57cec5SDimitry Andric // No operands 870b57cec5SDimitry Andric addInstruction(Opcode); 880b57cec5SDimitry Andric break; 890b57cec5SDimitry Andric case DW_CFA_set_loc: 900b57cec5SDimitry Andric // Operands: Address 915ffd83dbSDimitry Andric addInstruction(Opcode, Data.getRelocatedAddress(C)); 920b57cec5SDimitry Andric break; 930b57cec5SDimitry Andric case DW_CFA_advance_loc1: 940b57cec5SDimitry Andric // Operands: 1-byte delta 955ffd83dbSDimitry Andric addInstruction(Opcode, Data.getRelocatedValue(C, 1)); 960b57cec5SDimitry Andric break; 970b57cec5SDimitry Andric case DW_CFA_advance_loc2: 980b57cec5SDimitry Andric // Operands: 2-byte delta 995ffd83dbSDimitry Andric addInstruction(Opcode, Data.getRelocatedValue(C, 2)); 1000b57cec5SDimitry Andric break; 1010b57cec5SDimitry Andric case DW_CFA_advance_loc4: 1020b57cec5SDimitry Andric // Operands: 4-byte delta 1035ffd83dbSDimitry Andric addInstruction(Opcode, Data.getRelocatedValue(C, 4)); 1040b57cec5SDimitry Andric break; 1050b57cec5SDimitry Andric case DW_CFA_restore_extended: 1060b57cec5SDimitry Andric case DW_CFA_undefined: 1070b57cec5SDimitry Andric case DW_CFA_same_value: 1080b57cec5SDimitry Andric case DW_CFA_def_cfa_register: 1090b57cec5SDimitry Andric case DW_CFA_def_cfa_offset: 1100b57cec5SDimitry Andric case DW_CFA_GNU_args_size: 1110b57cec5SDimitry Andric // Operands: ULEB128 1125ffd83dbSDimitry Andric addInstruction(Opcode, Data.getULEB128(C)); 1130b57cec5SDimitry Andric break; 1140b57cec5SDimitry Andric case DW_CFA_def_cfa_offset_sf: 1150b57cec5SDimitry Andric // Operands: SLEB128 1165ffd83dbSDimitry Andric addInstruction(Opcode, Data.getSLEB128(C)); 1170b57cec5SDimitry Andric break; 1180b57cec5SDimitry Andric case DW_CFA_offset_extended: 1190b57cec5SDimitry Andric case DW_CFA_register: 1200b57cec5SDimitry Andric case DW_CFA_def_cfa: 1210b57cec5SDimitry Andric case DW_CFA_val_offset: { 1220b57cec5SDimitry Andric // Operands: ULEB128, ULEB128 1230b57cec5SDimitry Andric // Note: We can not embed getULEB128 directly into function 1240b57cec5SDimitry Andric // argument list. getULEB128 changes Offset and order of evaluation 1250b57cec5SDimitry Andric // for arguments is unspecified. 1265ffd83dbSDimitry Andric uint64_t op1 = Data.getULEB128(C); 1275ffd83dbSDimitry Andric uint64_t op2 = Data.getULEB128(C); 1280b57cec5SDimitry Andric addInstruction(Opcode, op1, op2); 1290b57cec5SDimitry Andric break; 1300b57cec5SDimitry Andric } 1310b57cec5SDimitry Andric case DW_CFA_offset_extended_sf: 1320b57cec5SDimitry Andric case DW_CFA_def_cfa_sf: 1330b57cec5SDimitry Andric case DW_CFA_val_offset_sf: { 1340b57cec5SDimitry Andric // Operands: ULEB128, SLEB128 1350b57cec5SDimitry Andric // Note: see comment for the previous case 1365ffd83dbSDimitry Andric uint64_t op1 = Data.getULEB128(C); 1375ffd83dbSDimitry Andric uint64_t op2 = (uint64_t)Data.getSLEB128(C); 1380b57cec5SDimitry Andric addInstruction(Opcode, op1, op2); 1390b57cec5SDimitry Andric break; 1400b57cec5SDimitry Andric } 1410b57cec5SDimitry Andric case DW_CFA_def_cfa_expression: { 1425ffd83dbSDimitry Andric uint64_t ExprLength = Data.getULEB128(C); 1430b57cec5SDimitry Andric addInstruction(Opcode, 0); 1445ffd83dbSDimitry Andric StringRef Expression = Data.getBytes(C, ExprLength); 1455ffd83dbSDimitry Andric 1465ffd83dbSDimitry Andric DataExtractor Extractor(Expression, Data.isLittleEndian(), 1475ffd83dbSDimitry Andric Data.getAddressSize()); 1485ffd83dbSDimitry Andric // Note. We do not pass the DWARF format to DWARFExpression, because 1495ffd83dbSDimitry Andric // DW_OP_call_ref, the only operation which depends on the format, is 1505ffd83dbSDimitry Andric // prohibited in call frame instructions, see sec. 6.4.2 in DWARFv5. 1515ffd83dbSDimitry Andric Instructions.back().Expression = 1525ffd83dbSDimitry Andric DWARFExpression(Extractor, Data.getAddressSize()); 1530b57cec5SDimitry Andric break; 1540b57cec5SDimitry Andric } 1550b57cec5SDimitry Andric case DW_CFA_expression: 1560b57cec5SDimitry Andric case DW_CFA_val_expression: { 1575ffd83dbSDimitry Andric uint64_t RegNum = Data.getULEB128(C); 1580b57cec5SDimitry Andric addInstruction(Opcode, RegNum, 0); 1595ffd83dbSDimitry Andric 1605ffd83dbSDimitry Andric uint64_t BlockLength = Data.getULEB128(C); 1615ffd83dbSDimitry Andric StringRef Expression = Data.getBytes(C, BlockLength); 1625ffd83dbSDimitry Andric DataExtractor Extractor(Expression, Data.isLittleEndian(), 1635ffd83dbSDimitry Andric Data.getAddressSize()); 1645ffd83dbSDimitry Andric // Note. We do not pass the DWARF format to DWARFExpression, because 1655ffd83dbSDimitry Andric // DW_OP_call_ref, the only operation which depends on the format, is 1665ffd83dbSDimitry Andric // prohibited in call frame instructions, see sec. 6.4.2 in DWARFv5. 1675ffd83dbSDimitry Andric Instructions.back().Expression = 1685ffd83dbSDimitry Andric DWARFExpression(Extractor, Data.getAddressSize()); 1690b57cec5SDimitry Andric break; 1700b57cec5SDimitry Andric } 1710b57cec5SDimitry Andric } 1720b57cec5SDimitry Andric } 1730b57cec5SDimitry Andric 1745ffd83dbSDimitry Andric *Offset = C.tell(); 1755ffd83dbSDimitry Andric return C.takeError(); 1760b57cec5SDimitry Andric } 1770b57cec5SDimitry Andric 1780b57cec5SDimitry Andric namespace { 1790b57cec5SDimitry Andric 1800b57cec5SDimitry Andric 1810b57cec5SDimitry Andric } // end anonymous namespace 1820b57cec5SDimitry Andric 1830b57cec5SDimitry Andric ArrayRef<CFIProgram::OperandType[2]> CFIProgram::getOperandTypes() { 1840b57cec5SDimitry Andric static OperandType OpTypes[DW_CFA_restore+1][2]; 1850b57cec5SDimitry Andric static bool Initialized = false; 1860b57cec5SDimitry Andric if (Initialized) { 1870b57cec5SDimitry Andric return ArrayRef<OperandType[2]>(&OpTypes[0], DW_CFA_restore+1); 1880b57cec5SDimitry Andric } 1890b57cec5SDimitry Andric Initialized = true; 1900b57cec5SDimitry Andric 1910b57cec5SDimitry Andric #define DECLARE_OP2(OP, OPTYPE0, OPTYPE1) \ 1920b57cec5SDimitry Andric do { \ 1930b57cec5SDimitry Andric OpTypes[OP][0] = OPTYPE0; \ 1940b57cec5SDimitry Andric OpTypes[OP][1] = OPTYPE1; \ 1950b57cec5SDimitry Andric } while (false) 1960b57cec5SDimitry Andric #define DECLARE_OP1(OP, OPTYPE0) DECLARE_OP2(OP, OPTYPE0, OT_None) 1970b57cec5SDimitry Andric #define DECLARE_OP0(OP) DECLARE_OP1(OP, OT_None) 1980b57cec5SDimitry Andric 1990b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_set_loc, OT_Address); 2000b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_advance_loc, OT_FactoredCodeOffset); 2010b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_advance_loc1, OT_FactoredCodeOffset); 2020b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_advance_loc2, OT_FactoredCodeOffset); 2030b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_advance_loc4, OT_FactoredCodeOffset); 2040b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_MIPS_advance_loc8, OT_FactoredCodeOffset); 2050b57cec5SDimitry Andric DECLARE_OP2(DW_CFA_def_cfa, OT_Register, OT_Offset); 2060b57cec5SDimitry Andric DECLARE_OP2(DW_CFA_def_cfa_sf, OT_Register, OT_SignedFactDataOffset); 2070b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_def_cfa_register, OT_Register); 2080b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_def_cfa_offset, OT_Offset); 2090b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_def_cfa_offset_sf, OT_SignedFactDataOffset); 2100b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_def_cfa_expression, OT_Expression); 2110b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_undefined, OT_Register); 2120b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_same_value, OT_Register); 2130b57cec5SDimitry Andric DECLARE_OP2(DW_CFA_offset, OT_Register, OT_UnsignedFactDataOffset); 2140b57cec5SDimitry Andric DECLARE_OP2(DW_CFA_offset_extended, OT_Register, OT_UnsignedFactDataOffset); 2150b57cec5SDimitry Andric DECLARE_OP2(DW_CFA_offset_extended_sf, OT_Register, OT_SignedFactDataOffset); 2160b57cec5SDimitry Andric DECLARE_OP2(DW_CFA_val_offset, OT_Register, OT_UnsignedFactDataOffset); 2170b57cec5SDimitry Andric DECLARE_OP2(DW_CFA_val_offset_sf, OT_Register, OT_SignedFactDataOffset); 2180b57cec5SDimitry Andric DECLARE_OP2(DW_CFA_register, OT_Register, OT_Register); 2190b57cec5SDimitry Andric DECLARE_OP2(DW_CFA_expression, OT_Register, OT_Expression); 2200b57cec5SDimitry Andric DECLARE_OP2(DW_CFA_val_expression, OT_Register, OT_Expression); 2210b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_restore, OT_Register); 2220b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_restore_extended, OT_Register); 2230b57cec5SDimitry Andric DECLARE_OP0(DW_CFA_remember_state); 2240b57cec5SDimitry Andric DECLARE_OP0(DW_CFA_restore_state); 2250b57cec5SDimitry Andric DECLARE_OP0(DW_CFA_GNU_window_save); 2260b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_GNU_args_size, OT_Offset); 2270b57cec5SDimitry Andric DECLARE_OP0(DW_CFA_nop); 2280b57cec5SDimitry Andric 2290b57cec5SDimitry Andric #undef DECLARE_OP0 2300b57cec5SDimitry Andric #undef DECLARE_OP1 2310b57cec5SDimitry Andric #undef DECLARE_OP2 2320b57cec5SDimitry Andric 2330b57cec5SDimitry Andric return ArrayRef<OperandType[2]>(&OpTypes[0], DW_CFA_restore+1); 2340b57cec5SDimitry Andric } 2350b57cec5SDimitry Andric 2360b57cec5SDimitry Andric /// Print \p Opcode's operand number \p OperandIdx which has value \p Operand. 237*e8d8bef9SDimitry Andric void CFIProgram::printOperand(raw_ostream &OS, DIDumpOptions DumpOpts, 238*e8d8bef9SDimitry Andric const MCRegisterInfo *MRI, bool IsEH, 239*e8d8bef9SDimitry Andric const Instruction &Instr, unsigned OperandIdx, 240*e8d8bef9SDimitry Andric uint64_t Operand) const { 2410b57cec5SDimitry Andric assert(OperandIdx < 2); 2420b57cec5SDimitry Andric uint8_t Opcode = Instr.Opcode; 2430b57cec5SDimitry Andric OperandType Type = getOperandTypes()[Opcode][OperandIdx]; 2440b57cec5SDimitry Andric 2450b57cec5SDimitry Andric switch (Type) { 2460b57cec5SDimitry Andric case OT_Unset: { 2470b57cec5SDimitry Andric OS << " Unsupported " << (OperandIdx ? "second" : "first") << " operand to"; 2480b57cec5SDimitry Andric auto OpcodeName = CallFrameString(Opcode, Arch); 2490b57cec5SDimitry Andric if (!OpcodeName.empty()) 2500b57cec5SDimitry Andric OS << " " << OpcodeName; 2510b57cec5SDimitry Andric else 2520b57cec5SDimitry Andric OS << format(" Opcode %x", Opcode); 2530b57cec5SDimitry Andric break; 2540b57cec5SDimitry Andric } 2550b57cec5SDimitry Andric case OT_None: 2560b57cec5SDimitry Andric break; 2570b57cec5SDimitry Andric case OT_Address: 2580b57cec5SDimitry Andric OS << format(" %" PRIx64, Operand); 2590b57cec5SDimitry Andric break; 2600b57cec5SDimitry Andric case OT_Offset: 2610b57cec5SDimitry Andric // The offsets are all encoded in a unsigned form, but in practice 2620b57cec5SDimitry Andric // consumers use them signed. It's most certainly legacy due to 2630b57cec5SDimitry Andric // the lack of signed variants in the first Dwarf standards. 2640b57cec5SDimitry Andric OS << format(" %+" PRId64, int64_t(Operand)); 2650b57cec5SDimitry Andric break; 2660b57cec5SDimitry Andric case OT_FactoredCodeOffset: // Always Unsigned 2670b57cec5SDimitry Andric if (CodeAlignmentFactor) 2680b57cec5SDimitry Andric OS << format(" %" PRId64, Operand * CodeAlignmentFactor); 2690b57cec5SDimitry Andric else 2700b57cec5SDimitry Andric OS << format(" %" PRId64 "*code_alignment_factor" , Operand); 2710b57cec5SDimitry Andric break; 2720b57cec5SDimitry Andric case OT_SignedFactDataOffset: 2730b57cec5SDimitry Andric if (DataAlignmentFactor) 2740b57cec5SDimitry Andric OS << format(" %" PRId64, int64_t(Operand) * DataAlignmentFactor); 2750b57cec5SDimitry Andric else 2760b57cec5SDimitry Andric OS << format(" %" PRId64 "*data_alignment_factor" , int64_t(Operand)); 2770b57cec5SDimitry Andric break; 2780b57cec5SDimitry Andric case OT_UnsignedFactDataOffset: 2790b57cec5SDimitry Andric if (DataAlignmentFactor) 2800b57cec5SDimitry Andric OS << format(" %" PRId64, Operand * DataAlignmentFactor); 2810b57cec5SDimitry Andric else 2820b57cec5SDimitry Andric OS << format(" %" PRId64 "*data_alignment_factor" , Operand); 2830b57cec5SDimitry Andric break; 2840b57cec5SDimitry Andric case OT_Register: 285*e8d8bef9SDimitry Andric OS << ' '; 286*e8d8bef9SDimitry Andric printRegister(OS, MRI, IsEH, Operand); 2870b57cec5SDimitry Andric break; 2880b57cec5SDimitry Andric case OT_Expression: 2890b57cec5SDimitry Andric assert(Instr.Expression && "missing DWARFExpression object"); 2900b57cec5SDimitry Andric OS << " "; 291*e8d8bef9SDimitry Andric Instr.Expression->print(OS, DumpOpts, MRI, nullptr, IsEH); 2920b57cec5SDimitry Andric break; 2930b57cec5SDimitry Andric } 2940b57cec5SDimitry Andric } 2950b57cec5SDimitry Andric 296*e8d8bef9SDimitry Andric void CFIProgram::dump(raw_ostream &OS, DIDumpOptions DumpOpts, 297*e8d8bef9SDimitry Andric const MCRegisterInfo *MRI, bool IsEH, 2980b57cec5SDimitry Andric unsigned IndentLevel) const { 2990b57cec5SDimitry Andric for (const auto &Instr : Instructions) { 3000b57cec5SDimitry Andric uint8_t Opcode = Instr.Opcode; 3010b57cec5SDimitry Andric if (Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK) 3020b57cec5SDimitry Andric Opcode &= DWARF_CFI_PRIMARY_OPCODE_MASK; 3030b57cec5SDimitry Andric OS.indent(2 * IndentLevel); 3040b57cec5SDimitry Andric OS << CallFrameString(Opcode, Arch) << ":"; 3050b57cec5SDimitry Andric for (unsigned i = 0; i < Instr.Ops.size(); ++i) 306*e8d8bef9SDimitry Andric printOperand(OS, DumpOpts, MRI, IsEH, Instr, i, Instr.Ops[i]); 3070b57cec5SDimitry Andric OS << '\n'; 3080b57cec5SDimitry Andric } 3090b57cec5SDimitry Andric } 3100b57cec5SDimitry Andric 3115ffd83dbSDimitry Andric // Returns the CIE identifier to be used by the requested format. 3125ffd83dbSDimitry Andric // CIE ids for .debug_frame sections are defined in Section 7.24 of DWARFv5. 3135ffd83dbSDimitry Andric // For CIE ID in .eh_frame sections see 3145ffd83dbSDimitry Andric // https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html 3155ffd83dbSDimitry Andric constexpr uint64_t getCIEId(bool IsDWARF64, bool IsEH) { 3165ffd83dbSDimitry Andric if (IsEH) 3175ffd83dbSDimitry Andric return 0; 3185ffd83dbSDimitry Andric if (IsDWARF64) 3195ffd83dbSDimitry Andric return DW64_CIE_ID; 3205ffd83dbSDimitry Andric return DW_CIE_ID; 3215ffd83dbSDimitry Andric } 3225ffd83dbSDimitry Andric 323*e8d8bef9SDimitry Andric void CIE::dump(raw_ostream &OS, DIDumpOptions DumpOpts, 324*e8d8bef9SDimitry Andric const MCRegisterInfo *MRI, bool IsEH) const { 3255ffd83dbSDimitry Andric // A CIE with a zero length is a terminator entry in the .eh_frame section. 3265ffd83dbSDimitry Andric if (IsEH && Length == 0) { 3275ffd83dbSDimitry Andric OS << format("%08" PRIx64, Offset) << " ZERO terminator\n"; 3285ffd83dbSDimitry Andric return; 3295ffd83dbSDimitry Andric } 3305ffd83dbSDimitry Andric 3315ffd83dbSDimitry Andric OS << format("%08" PRIx64, Offset) 3325ffd83dbSDimitry Andric << format(" %0*" PRIx64, IsDWARF64 ? 16 : 8, Length) 3335ffd83dbSDimitry Andric << format(" %0*" PRIx64, IsDWARF64 && !IsEH ? 16 : 8, 3345ffd83dbSDimitry Andric getCIEId(IsDWARF64, IsEH)) 3355ffd83dbSDimitry Andric << " CIE\n" 3365ffd83dbSDimitry Andric << " Format: " << FormatString(IsDWARF64) << "\n" 3375ffd83dbSDimitry Andric << format(" Version: %d\n", Version) 3385ffd83dbSDimitry Andric << " Augmentation: \"" << Augmentation << "\"\n"; 3390b57cec5SDimitry Andric if (Version >= 4) { 3400b57cec5SDimitry Andric OS << format(" Address size: %u\n", (uint32_t)AddressSize); 3410b57cec5SDimitry Andric OS << format(" Segment desc size: %u\n", 3420b57cec5SDimitry Andric (uint32_t)SegmentDescriptorSize); 3430b57cec5SDimitry Andric } 3440b57cec5SDimitry Andric OS << format(" Code alignment factor: %u\n", (uint32_t)CodeAlignmentFactor); 3450b57cec5SDimitry Andric OS << format(" Data alignment factor: %d\n", (int32_t)DataAlignmentFactor); 3460b57cec5SDimitry Andric OS << format(" Return address column: %d\n", (int32_t)ReturnAddressRegister); 3470b57cec5SDimitry Andric if (Personality) 3480b57cec5SDimitry Andric OS << format(" Personality Address: %016" PRIx64 "\n", *Personality); 3490b57cec5SDimitry Andric if (!AugmentationData.empty()) { 3500b57cec5SDimitry Andric OS << " Augmentation data: "; 3510b57cec5SDimitry Andric for (uint8_t Byte : AugmentationData) 3520b57cec5SDimitry Andric OS << ' ' << hexdigit(Byte >> 4) << hexdigit(Byte & 0xf); 3530b57cec5SDimitry Andric OS << "\n"; 3540b57cec5SDimitry Andric } 3550b57cec5SDimitry Andric OS << "\n"; 356*e8d8bef9SDimitry Andric CFIs.dump(OS, DumpOpts, MRI, IsEH); 3570b57cec5SDimitry Andric OS << "\n"; 3580b57cec5SDimitry Andric } 3590b57cec5SDimitry Andric 360*e8d8bef9SDimitry Andric void FDE::dump(raw_ostream &OS, DIDumpOptions DumpOpts, 361*e8d8bef9SDimitry Andric const MCRegisterInfo *MRI, bool IsEH) const { 3625ffd83dbSDimitry Andric OS << format("%08" PRIx64, Offset) 3635ffd83dbSDimitry Andric << format(" %0*" PRIx64, IsDWARF64 ? 16 : 8, Length) 3645ffd83dbSDimitry Andric << format(" %0*" PRIx64, IsDWARF64 && !IsEH ? 16 : 8, CIEPointer) 3655ffd83dbSDimitry Andric << " FDE cie="; 3665ffd83dbSDimitry Andric if (LinkedCIE) 3675ffd83dbSDimitry Andric OS << format("%08" PRIx64, LinkedCIE->getOffset()); 3685ffd83dbSDimitry Andric else 3695ffd83dbSDimitry Andric OS << "<invalid offset>"; 3705ffd83dbSDimitry Andric OS << format(" pc=%08" PRIx64 "...%08" PRIx64 "\n", InitialLocation, 3715ffd83dbSDimitry Andric InitialLocation + AddressRange); 3725ffd83dbSDimitry Andric OS << " Format: " << FormatString(IsDWARF64) << "\n"; 3730b57cec5SDimitry Andric if (LSDAAddress) 3740b57cec5SDimitry Andric OS << format(" LSDA Address: %016" PRIx64 "\n", *LSDAAddress); 375*e8d8bef9SDimitry Andric CFIs.dump(OS, DumpOpts, MRI, IsEH); 3760b57cec5SDimitry Andric OS << "\n"; 3770b57cec5SDimitry Andric } 3780b57cec5SDimitry Andric 3790b57cec5SDimitry Andric DWARFDebugFrame::DWARFDebugFrame(Triple::ArchType Arch, 3800b57cec5SDimitry Andric bool IsEH, uint64_t EHFrameAddress) 3810b57cec5SDimitry Andric : Arch(Arch), IsEH(IsEH), EHFrameAddress(EHFrameAddress) {} 3820b57cec5SDimitry Andric 3830b57cec5SDimitry Andric DWARFDebugFrame::~DWARFDebugFrame() = default; 3840b57cec5SDimitry Andric 3850b57cec5SDimitry Andric static void LLVM_ATTRIBUTE_UNUSED dumpDataAux(DataExtractor Data, 3868bcb0991SDimitry Andric uint64_t Offset, int Length) { 3870b57cec5SDimitry Andric errs() << "DUMP: "; 3880b57cec5SDimitry Andric for (int i = 0; i < Length; ++i) { 3890b57cec5SDimitry Andric uint8_t c = Data.getU8(&Offset); 3900b57cec5SDimitry Andric errs().write_hex(c); errs() << " "; 3910b57cec5SDimitry Andric } 3920b57cec5SDimitry Andric errs() << "\n"; 3930b57cec5SDimitry Andric } 3940b57cec5SDimitry Andric 3955ffd83dbSDimitry Andric Error DWARFDebugFrame::parse(DWARFDataExtractor Data) { 3968bcb0991SDimitry Andric uint64_t Offset = 0; 3978bcb0991SDimitry Andric DenseMap<uint64_t, CIE *> CIEs; 3980b57cec5SDimitry Andric 3990b57cec5SDimitry Andric while (Data.isValidOffset(Offset)) { 4008bcb0991SDimitry Andric uint64_t StartOffset = Offset; 4010b57cec5SDimitry Andric 4025ffd83dbSDimitry Andric uint64_t Length; 4035ffd83dbSDimitry Andric DwarfFormat Format; 4045ffd83dbSDimitry Andric std::tie(Length, Format) = Data.getInitialLength(&Offset); 4055ffd83dbSDimitry Andric bool IsDWARF64 = Format == DWARF64; 4060b57cec5SDimitry Andric 4075ffd83dbSDimitry Andric // If the Length is 0, then this CIE is a terminator. We add it because some 4085ffd83dbSDimitry Andric // dumper tools might need it to print something special for such entries 4095ffd83dbSDimitry Andric // (e.g. llvm-objdump --dwarf=frames prints "ZERO terminator"). 4105ffd83dbSDimitry Andric if (Length == 0) { 4115ffd83dbSDimitry Andric auto Cie = std::make_unique<CIE>( 4125ffd83dbSDimitry Andric IsDWARF64, StartOffset, 0, 0, SmallString<8>(), 0, 0, 0, 0, 0, 4135ffd83dbSDimitry Andric SmallString<8>(), 0, 0, None, None, Arch); 4145ffd83dbSDimitry Andric CIEs[StartOffset] = Cie.get(); 4155ffd83dbSDimitry Andric Entries.push_back(std::move(Cie)); 4165ffd83dbSDimitry Andric break; 4170b57cec5SDimitry Andric } 4180b57cec5SDimitry Andric 4190b57cec5SDimitry Andric // At this point, Offset points to the next field after Length. 4200b57cec5SDimitry Andric // Length is the structure size excluding itself. Compute an offset one 4210b57cec5SDimitry Andric // past the end of the structure (needed to know how many instructions to 4220b57cec5SDimitry Andric // read). 4238bcb0991SDimitry Andric uint64_t StartStructureOffset = Offset; 4248bcb0991SDimitry Andric uint64_t EndStructureOffset = Offset + Length; 4250b57cec5SDimitry Andric 4260b57cec5SDimitry Andric // The Id field's size depends on the DWARF format 4275ffd83dbSDimitry Andric Error Err = Error::success(); 4285ffd83dbSDimitry Andric uint64_t Id = Data.getRelocatedValue((IsDWARF64 && !IsEH) ? 8 : 4, &Offset, 4295ffd83dbSDimitry Andric /*SectionIndex=*/nullptr, &Err); 4305ffd83dbSDimitry Andric if (Err) 4315ffd83dbSDimitry Andric return Err; 4320b57cec5SDimitry Andric 4335ffd83dbSDimitry Andric if (Id == getCIEId(IsDWARF64, IsEH)) { 4340b57cec5SDimitry Andric uint8_t Version = Data.getU8(&Offset); 4350b57cec5SDimitry Andric const char *Augmentation = Data.getCStr(&Offset); 4360b57cec5SDimitry Andric StringRef AugmentationString(Augmentation ? Augmentation : ""); 4375ffd83dbSDimitry Andric // TODO: we should provide a way to report a warning and continue dumping. 4385ffd83dbSDimitry Andric if (IsEH && Version != 1) 4395ffd83dbSDimitry Andric return createStringError(errc::not_supported, 4405ffd83dbSDimitry Andric "unsupported CIE version: %" PRIu8, Version); 4415ffd83dbSDimitry Andric 4420b57cec5SDimitry Andric uint8_t AddressSize = Version < 4 ? Data.getAddressSize() : 4430b57cec5SDimitry Andric Data.getU8(&Offset); 4440b57cec5SDimitry Andric Data.setAddressSize(AddressSize); 4450b57cec5SDimitry Andric uint8_t SegmentDescriptorSize = Version < 4 ? 0 : Data.getU8(&Offset); 4460b57cec5SDimitry Andric uint64_t CodeAlignmentFactor = Data.getULEB128(&Offset); 4470b57cec5SDimitry Andric int64_t DataAlignmentFactor = Data.getSLEB128(&Offset); 4480b57cec5SDimitry Andric uint64_t ReturnAddressRegister = 4490b57cec5SDimitry Andric Version == 1 ? Data.getU8(&Offset) : Data.getULEB128(&Offset); 4500b57cec5SDimitry Andric 4510b57cec5SDimitry Andric // Parse the augmentation data for EH CIEs 4520b57cec5SDimitry Andric StringRef AugmentationData(""); 4530b57cec5SDimitry Andric uint32_t FDEPointerEncoding = DW_EH_PE_absptr; 4540b57cec5SDimitry Andric uint32_t LSDAPointerEncoding = DW_EH_PE_omit; 4550b57cec5SDimitry Andric Optional<uint64_t> Personality; 4560b57cec5SDimitry Andric Optional<uint32_t> PersonalityEncoding; 4570b57cec5SDimitry Andric if (IsEH) { 4580b57cec5SDimitry Andric Optional<uint64_t> AugmentationLength; 4598bcb0991SDimitry Andric uint64_t StartAugmentationOffset; 4608bcb0991SDimitry Andric uint64_t EndAugmentationOffset; 4610b57cec5SDimitry Andric 4620b57cec5SDimitry Andric // Walk the augmentation string to get all the augmentation data. 4630b57cec5SDimitry Andric for (unsigned i = 0, e = AugmentationString.size(); i != e; ++i) { 4640b57cec5SDimitry Andric switch (AugmentationString[i]) { 4650b57cec5SDimitry Andric default: 4665ffd83dbSDimitry Andric return createStringError( 4675ffd83dbSDimitry Andric errc::invalid_argument, 4685ffd83dbSDimitry Andric "unknown augmentation character in entry at 0x%" PRIx64, 4695ffd83dbSDimitry Andric StartOffset); 4700b57cec5SDimitry Andric case 'L': 4710b57cec5SDimitry Andric LSDAPointerEncoding = Data.getU8(&Offset); 4720b57cec5SDimitry Andric break; 4730b57cec5SDimitry Andric case 'P': { 4740b57cec5SDimitry Andric if (Personality) 4755ffd83dbSDimitry Andric return createStringError( 4765ffd83dbSDimitry Andric errc::invalid_argument, 4775ffd83dbSDimitry Andric "duplicate personality in entry at 0x%" PRIx64, StartOffset); 4780b57cec5SDimitry Andric PersonalityEncoding = Data.getU8(&Offset); 4790b57cec5SDimitry Andric Personality = Data.getEncodedPointer( 4800b57cec5SDimitry Andric &Offset, *PersonalityEncoding, 4810b57cec5SDimitry Andric EHFrameAddress ? EHFrameAddress + Offset : 0); 4820b57cec5SDimitry Andric break; 4830b57cec5SDimitry Andric } 4840b57cec5SDimitry Andric case 'R': 4850b57cec5SDimitry Andric FDEPointerEncoding = Data.getU8(&Offset); 4860b57cec5SDimitry Andric break; 4870b57cec5SDimitry Andric case 'S': 4880b57cec5SDimitry Andric // Current frame is a signal trampoline. 4890b57cec5SDimitry Andric break; 4900b57cec5SDimitry Andric case 'z': 4910b57cec5SDimitry Andric if (i) 4925ffd83dbSDimitry Andric return createStringError( 4935ffd83dbSDimitry Andric errc::invalid_argument, 4945ffd83dbSDimitry Andric "'z' must be the first character at 0x%" PRIx64, StartOffset); 4950b57cec5SDimitry Andric // Parse the augmentation length first. We only parse it if 4960b57cec5SDimitry Andric // the string contains a 'z'. 4970b57cec5SDimitry Andric AugmentationLength = Data.getULEB128(&Offset); 4980b57cec5SDimitry Andric StartAugmentationOffset = Offset; 4998bcb0991SDimitry Andric EndAugmentationOffset = Offset + *AugmentationLength; 5000b57cec5SDimitry Andric break; 5010b57cec5SDimitry Andric case 'B': 5020b57cec5SDimitry Andric // B-Key is used for signing functions associated with this 5030b57cec5SDimitry Andric // augmentation string 5040b57cec5SDimitry Andric break; 5050b57cec5SDimitry Andric } 5060b57cec5SDimitry Andric } 5070b57cec5SDimitry Andric 5080b57cec5SDimitry Andric if (AugmentationLength.hasValue()) { 5090b57cec5SDimitry Andric if (Offset != EndAugmentationOffset) 5105ffd83dbSDimitry Andric return createStringError(errc::invalid_argument, 5115ffd83dbSDimitry Andric "parsing augmentation data at 0x%" PRIx64 5125ffd83dbSDimitry Andric " failed", 5135ffd83dbSDimitry Andric StartOffset); 5140b57cec5SDimitry Andric AugmentationData = Data.getData().slice(StartAugmentationOffset, 5150b57cec5SDimitry Andric EndAugmentationOffset); 5160b57cec5SDimitry Andric } 5170b57cec5SDimitry Andric } 5180b57cec5SDimitry Andric 5198bcb0991SDimitry Andric auto Cie = std::make_unique<CIE>( 5205ffd83dbSDimitry Andric IsDWARF64, StartOffset, Length, Version, AugmentationString, 5215ffd83dbSDimitry Andric AddressSize, SegmentDescriptorSize, CodeAlignmentFactor, 5225ffd83dbSDimitry Andric DataAlignmentFactor, ReturnAddressRegister, AugmentationData, 5235ffd83dbSDimitry Andric FDEPointerEncoding, LSDAPointerEncoding, Personality, 5245ffd83dbSDimitry Andric PersonalityEncoding, Arch); 5250b57cec5SDimitry Andric CIEs[StartOffset] = Cie.get(); 5260b57cec5SDimitry Andric Entries.emplace_back(std::move(Cie)); 5270b57cec5SDimitry Andric } else { 5280b57cec5SDimitry Andric // FDE 5290b57cec5SDimitry Andric uint64_t CIEPointer = Id; 5300b57cec5SDimitry Andric uint64_t InitialLocation = 0; 5310b57cec5SDimitry Andric uint64_t AddressRange = 0; 5320b57cec5SDimitry Andric Optional<uint64_t> LSDAAddress; 5330b57cec5SDimitry Andric CIE *Cie = CIEs[IsEH ? (StartStructureOffset - CIEPointer) : CIEPointer]; 5340b57cec5SDimitry Andric 5350b57cec5SDimitry Andric if (IsEH) { 5360b57cec5SDimitry Andric // The address size is encoded in the CIE we reference. 5370b57cec5SDimitry Andric if (!Cie) 5385ffd83dbSDimitry Andric return createStringError(errc::invalid_argument, 5395ffd83dbSDimitry Andric "parsing FDE data at 0x%" PRIx64 5405ffd83dbSDimitry Andric " failed due to missing CIE", 5415ffd83dbSDimitry Andric StartOffset); 542*e8d8bef9SDimitry Andric if (auto Val = 543*e8d8bef9SDimitry Andric Data.getEncodedPointer(&Offset, Cie->getFDEPointerEncoding(), 544*e8d8bef9SDimitry Andric EHFrameAddress + Offset)) { 5450b57cec5SDimitry Andric InitialLocation = *Val; 5460b57cec5SDimitry Andric } 5470b57cec5SDimitry Andric if (auto Val = Data.getEncodedPointer( 5480b57cec5SDimitry Andric &Offset, Cie->getFDEPointerEncoding(), 0)) { 5490b57cec5SDimitry Andric AddressRange = *Val; 5500b57cec5SDimitry Andric } 5510b57cec5SDimitry Andric 5520b57cec5SDimitry Andric StringRef AugmentationString = Cie->getAugmentationString(); 5530b57cec5SDimitry Andric if (!AugmentationString.empty()) { 5540b57cec5SDimitry Andric // Parse the augmentation length and data for this FDE. 5550b57cec5SDimitry Andric uint64_t AugmentationLength = Data.getULEB128(&Offset); 5560b57cec5SDimitry Andric 5578bcb0991SDimitry Andric uint64_t EndAugmentationOffset = Offset + AugmentationLength; 5580b57cec5SDimitry Andric 5590b57cec5SDimitry Andric // Decode the LSDA if the CIE augmentation string said we should. 5600b57cec5SDimitry Andric if (Cie->getLSDAPointerEncoding() != DW_EH_PE_omit) { 5610b57cec5SDimitry Andric LSDAAddress = Data.getEncodedPointer( 5620b57cec5SDimitry Andric &Offset, Cie->getLSDAPointerEncoding(), 5630b57cec5SDimitry Andric EHFrameAddress ? Offset + EHFrameAddress : 0); 5640b57cec5SDimitry Andric } 5650b57cec5SDimitry Andric 5660b57cec5SDimitry Andric if (Offset != EndAugmentationOffset) 5675ffd83dbSDimitry Andric return createStringError(errc::invalid_argument, 5685ffd83dbSDimitry Andric "parsing augmentation data at 0x%" PRIx64 5695ffd83dbSDimitry Andric " failed", 5705ffd83dbSDimitry Andric StartOffset); 5710b57cec5SDimitry Andric } 5720b57cec5SDimitry Andric } else { 5730b57cec5SDimitry Andric InitialLocation = Data.getRelocatedAddress(&Offset); 5740b57cec5SDimitry Andric AddressRange = Data.getRelocatedAddress(&Offset); 5750b57cec5SDimitry Andric } 5760b57cec5SDimitry Andric 5775ffd83dbSDimitry Andric Entries.emplace_back(new FDE(IsDWARF64, StartOffset, Length, CIEPointer, 5785ffd83dbSDimitry Andric InitialLocation, AddressRange, Cie, 5795ffd83dbSDimitry Andric LSDAAddress, Arch)); 5800b57cec5SDimitry Andric } 5810b57cec5SDimitry Andric 5820b57cec5SDimitry Andric if (Error E = 5835ffd83dbSDimitry Andric Entries.back()->cfis().parse(Data, &Offset, EndStructureOffset)) 5845ffd83dbSDimitry Andric return E; 5850b57cec5SDimitry Andric 5860b57cec5SDimitry Andric if (Offset != EndStructureOffset) 5875ffd83dbSDimitry Andric return createStringError( 5885ffd83dbSDimitry Andric errc::invalid_argument, 5895ffd83dbSDimitry Andric "parsing entry instructions at 0x%" PRIx64 " failed", StartOffset); 5900b57cec5SDimitry Andric } 5915ffd83dbSDimitry Andric 5925ffd83dbSDimitry Andric return Error::success(); 5930b57cec5SDimitry Andric } 5940b57cec5SDimitry Andric 5950b57cec5SDimitry Andric FrameEntry *DWARFDebugFrame::getEntryAtOffset(uint64_t Offset) const { 5960b57cec5SDimitry Andric auto It = partition_point(Entries, [=](const std::unique_ptr<FrameEntry> &E) { 5970b57cec5SDimitry Andric return E->getOffset() < Offset; 5980b57cec5SDimitry Andric }); 5990b57cec5SDimitry Andric if (It != Entries.end() && (*It)->getOffset() == Offset) 6000b57cec5SDimitry Andric return It->get(); 6010b57cec5SDimitry Andric return nullptr; 6020b57cec5SDimitry Andric } 6030b57cec5SDimitry Andric 604*e8d8bef9SDimitry Andric void DWARFDebugFrame::dump(raw_ostream &OS, DIDumpOptions DumpOpts, 605*e8d8bef9SDimitry Andric const MCRegisterInfo *MRI, 6060b57cec5SDimitry Andric Optional<uint64_t> Offset) const { 6070b57cec5SDimitry Andric if (Offset) { 6080b57cec5SDimitry Andric if (auto *Entry = getEntryAtOffset(*Offset)) 609*e8d8bef9SDimitry Andric Entry->dump(OS, DumpOpts, MRI, IsEH); 6100b57cec5SDimitry Andric return; 6110b57cec5SDimitry Andric } 6120b57cec5SDimitry Andric 6130b57cec5SDimitry Andric OS << "\n"; 6140b57cec5SDimitry Andric for (const auto &Entry : Entries) 615*e8d8bef9SDimitry Andric Entry->dump(OS, DumpOpts, MRI, IsEH); 6160b57cec5SDimitry Andric } 617