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 37*8bcb0991SDimitry Andric Error CFIProgram::parse(DWARFDataExtractor Data, uint64_t *Offset, 38*8bcb0991SDimitry Andric uint64_t EndOffset) { 390b57cec5SDimitry Andric while (*Offset < EndOffset) { 400b57cec5SDimitry Andric uint8_t Opcode = Data.getRelocatedValue(1, Offset); 410b57cec5SDimitry Andric // Some instructions have a primary opcode encoded in the top bits. 420b57cec5SDimitry Andric uint8_t Primary = Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK; 430b57cec5SDimitry Andric 440b57cec5SDimitry Andric if (Primary) { 450b57cec5SDimitry Andric // If it's a primary opcode, the first operand is encoded in the bottom 460b57cec5SDimitry Andric // bits of the opcode itself. 470b57cec5SDimitry Andric uint64_t Op1 = Opcode & DWARF_CFI_PRIMARY_OPERAND_MASK; 480b57cec5SDimitry Andric switch (Primary) { 490b57cec5SDimitry Andric default: 500b57cec5SDimitry Andric return createStringError(errc::illegal_byte_sequence, 510b57cec5SDimitry Andric "Invalid primary CFI opcode 0x%" PRIx8, 520b57cec5SDimitry Andric Primary); 530b57cec5SDimitry Andric case DW_CFA_advance_loc: 540b57cec5SDimitry Andric case DW_CFA_restore: 550b57cec5SDimitry Andric addInstruction(Primary, Op1); 560b57cec5SDimitry Andric break; 570b57cec5SDimitry Andric case DW_CFA_offset: 580b57cec5SDimitry Andric addInstruction(Primary, Op1, Data.getULEB128(Offset)); 590b57cec5SDimitry Andric break; 600b57cec5SDimitry Andric } 610b57cec5SDimitry Andric } else { 620b57cec5SDimitry Andric // Extended opcode - its value is Opcode itself. 630b57cec5SDimitry Andric switch (Opcode) { 640b57cec5SDimitry Andric default: 650b57cec5SDimitry Andric return createStringError(errc::illegal_byte_sequence, 660b57cec5SDimitry Andric "Invalid extended CFI opcode 0x%" PRIx8, 670b57cec5SDimitry Andric Opcode); 680b57cec5SDimitry Andric case DW_CFA_nop: 690b57cec5SDimitry Andric case DW_CFA_remember_state: 700b57cec5SDimitry Andric case DW_CFA_restore_state: 710b57cec5SDimitry Andric case DW_CFA_GNU_window_save: 720b57cec5SDimitry Andric // No operands 730b57cec5SDimitry Andric addInstruction(Opcode); 740b57cec5SDimitry Andric break; 750b57cec5SDimitry Andric case DW_CFA_set_loc: 760b57cec5SDimitry Andric // Operands: Address 770b57cec5SDimitry Andric addInstruction(Opcode, Data.getRelocatedAddress(Offset)); 780b57cec5SDimitry Andric break; 790b57cec5SDimitry Andric case DW_CFA_advance_loc1: 800b57cec5SDimitry Andric // Operands: 1-byte delta 810b57cec5SDimitry Andric addInstruction(Opcode, Data.getRelocatedValue(1, Offset)); 820b57cec5SDimitry Andric break; 830b57cec5SDimitry Andric case DW_CFA_advance_loc2: 840b57cec5SDimitry Andric // Operands: 2-byte delta 850b57cec5SDimitry Andric addInstruction(Opcode, Data.getRelocatedValue(2, Offset)); 860b57cec5SDimitry Andric break; 870b57cec5SDimitry Andric case DW_CFA_advance_loc4: 880b57cec5SDimitry Andric // Operands: 4-byte delta 890b57cec5SDimitry Andric addInstruction(Opcode, Data.getRelocatedValue(4, Offset)); 900b57cec5SDimitry Andric break; 910b57cec5SDimitry Andric case DW_CFA_restore_extended: 920b57cec5SDimitry Andric case DW_CFA_undefined: 930b57cec5SDimitry Andric case DW_CFA_same_value: 940b57cec5SDimitry Andric case DW_CFA_def_cfa_register: 950b57cec5SDimitry Andric case DW_CFA_def_cfa_offset: 960b57cec5SDimitry Andric case DW_CFA_GNU_args_size: 970b57cec5SDimitry Andric // Operands: ULEB128 980b57cec5SDimitry Andric addInstruction(Opcode, Data.getULEB128(Offset)); 990b57cec5SDimitry Andric break; 1000b57cec5SDimitry Andric case DW_CFA_def_cfa_offset_sf: 1010b57cec5SDimitry Andric // Operands: SLEB128 1020b57cec5SDimitry Andric addInstruction(Opcode, Data.getSLEB128(Offset)); 1030b57cec5SDimitry Andric break; 1040b57cec5SDimitry Andric case DW_CFA_offset_extended: 1050b57cec5SDimitry Andric case DW_CFA_register: 1060b57cec5SDimitry Andric case DW_CFA_def_cfa: 1070b57cec5SDimitry Andric case DW_CFA_val_offset: { 1080b57cec5SDimitry Andric // Operands: ULEB128, ULEB128 1090b57cec5SDimitry Andric // Note: We can not embed getULEB128 directly into function 1100b57cec5SDimitry Andric // argument list. getULEB128 changes Offset and order of evaluation 1110b57cec5SDimitry Andric // for arguments is unspecified. 1120b57cec5SDimitry Andric auto op1 = Data.getULEB128(Offset); 1130b57cec5SDimitry Andric auto op2 = Data.getULEB128(Offset); 1140b57cec5SDimitry Andric addInstruction(Opcode, op1, op2); 1150b57cec5SDimitry Andric break; 1160b57cec5SDimitry Andric } 1170b57cec5SDimitry Andric case DW_CFA_offset_extended_sf: 1180b57cec5SDimitry Andric case DW_CFA_def_cfa_sf: 1190b57cec5SDimitry Andric case DW_CFA_val_offset_sf: { 1200b57cec5SDimitry Andric // Operands: ULEB128, SLEB128 1210b57cec5SDimitry Andric // Note: see comment for the previous case 1220b57cec5SDimitry Andric auto op1 = Data.getULEB128(Offset); 1230b57cec5SDimitry Andric auto op2 = (uint64_t)Data.getSLEB128(Offset); 1240b57cec5SDimitry Andric addInstruction(Opcode, op1, op2); 1250b57cec5SDimitry Andric break; 1260b57cec5SDimitry Andric } 1270b57cec5SDimitry Andric case DW_CFA_def_cfa_expression: { 1280b57cec5SDimitry Andric uint32_t ExprLength = Data.getULEB128(Offset); 1290b57cec5SDimitry Andric addInstruction(Opcode, 0); 1300b57cec5SDimitry Andric DataExtractor Extractor( 1310b57cec5SDimitry Andric Data.getData().slice(*Offset, *Offset + ExprLength), 1320b57cec5SDimitry Andric Data.isLittleEndian(), Data.getAddressSize()); 1330b57cec5SDimitry Andric Instructions.back().Expression = DWARFExpression( 1340b57cec5SDimitry Andric Extractor, Data.getAddressSize(), dwarf::DWARF_VERSION); 1350b57cec5SDimitry Andric *Offset += ExprLength; 1360b57cec5SDimitry Andric break; 1370b57cec5SDimitry Andric } 1380b57cec5SDimitry Andric case DW_CFA_expression: 1390b57cec5SDimitry Andric case DW_CFA_val_expression: { 1400b57cec5SDimitry Andric auto RegNum = Data.getULEB128(Offset); 1410b57cec5SDimitry Andric auto BlockLength = Data.getULEB128(Offset); 1420b57cec5SDimitry Andric addInstruction(Opcode, RegNum, 0); 1430b57cec5SDimitry Andric DataExtractor Extractor( 1440b57cec5SDimitry Andric Data.getData().slice(*Offset, *Offset + BlockLength), 1450b57cec5SDimitry Andric Data.isLittleEndian(), Data.getAddressSize()); 1460b57cec5SDimitry Andric Instructions.back().Expression = DWARFExpression( 1470b57cec5SDimitry Andric Extractor, Data.getAddressSize(), dwarf::DWARF_VERSION); 1480b57cec5SDimitry Andric *Offset += BlockLength; 1490b57cec5SDimitry Andric break; 1500b57cec5SDimitry Andric } 1510b57cec5SDimitry Andric } 1520b57cec5SDimitry Andric } 1530b57cec5SDimitry Andric } 1540b57cec5SDimitry Andric 1550b57cec5SDimitry Andric return Error::success(); 1560b57cec5SDimitry Andric } 1570b57cec5SDimitry Andric 1580b57cec5SDimitry Andric namespace { 1590b57cec5SDimitry Andric 1600b57cec5SDimitry Andric 1610b57cec5SDimitry Andric } // end anonymous namespace 1620b57cec5SDimitry Andric 1630b57cec5SDimitry Andric ArrayRef<CFIProgram::OperandType[2]> CFIProgram::getOperandTypes() { 1640b57cec5SDimitry Andric static OperandType OpTypes[DW_CFA_restore+1][2]; 1650b57cec5SDimitry Andric static bool Initialized = false; 1660b57cec5SDimitry Andric if (Initialized) { 1670b57cec5SDimitry Andric return ArrayRef<OperandType[2]>(&OpTypes[0], DW_CFA_restore+1); 1680b57cec5SDimitry Andric } 1690b57cec5SDimitry Andric Initialized = true; 1700b57cec5SDimitry Andric 1710b57cec5SDimitry Andric #define DECLARE_OP2(OP, OPTYPE0, OPTYPE1) \ 1720b57cec5SDimitry Andric do { \ 1730b57cec5SDimitry Andric OpTypes[OP][0] = OPTYPE0; \ 1740b57cec5SDimitry Andric OpTypes[OP][1] = OPTYPE1; \ 1750b57cec5SDimitry Andric } while (false) 1760b57cec5SDimitry Andric #define DECLARE_OP1(OP, OPTYPE0) DECLARE_OP2(OP, OPTYPE0, OT_None) 1770b57cec5SDimitry Andric #define DECLARE_OP0(OP) DECLARE_OP1(OP, OT_None) 1780b57cec5SDimitry Andric 1790b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_set_loc, OT_Address); 1800b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_advance_loc, OT_FactoredCodeOffset); 1810b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_advance_loc1, OT_FactoredCodeOffset); 1820b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_advance_loc2, OT_FactoredCodeOffset); 1830b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_advance_loc4, OT_FactoredCodeOffset); 1840b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_MIPS_advance_loc8, OT_FactoredCodeOffset); 1850b57cec5SDimitry Andric DECLARE_OP2(DW_CFA_def_cfa, OT_Register, OT_Offset); 1860b57cec5SDimitry Andric DECLARE_OP2(DW_CFA_def_cfa_sf, OT_Register, OT_SignedFactDataOffset); 1870b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_def_cfa_register, OT_Register); 1880b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_def_cfa_offset, OT_Offset); 1890b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_def_cfa_offset_sf, OT_SignedFactDataOffset); 1900b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_def_cfa_expression, OT_Expression); 1910b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_undefined, OT_Register); 1920b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_same_value, OT_Register); 1930b57cec5SDimitry Andric DECLARE_OP2(DW_CFA_offset, OT_Register, OT_UnsignedFactDataOffset); 1940b57cec5SDimitry Andric DECLARE_OP2(DW_CFA_offset_extended, OT_Register, OT_UnsignedFactDataOffset); 1950b57cec5SDimitry Andric DECLARE_OP2(DW_CFA_offset_extended_sf, OT_Register, OT_SignedFactDataOffset); 1960b57cec5SDimitry Andric DECLARE_OP2(DW_CFA_val_offset, OT_Register, OT_UnsignedFactDataOffset); 1970b57cec5SDimitry Andric DECLARE_OP2(DW_CFA_val_offset_sf, OT_Register, OT_SignedFactDataOffset); 1980b57cec5SDimitry Andric DECLARE_OP2(DW_CFA_register, OT_Register, OT_Register); 1990b57cec5SDimitry Andric DECLARE_OP2(DW_CFA_expression, OT_Register, OT_Expression); 2000b57cec5SDimitry Andric DECLARE_OP2(DW_CFA_val_expression, OT_Register, OT_Expression); 2010b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_restore, OT_Register); 2020b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_restore_extended, OT_Register); 2030b57cec5SDimitry Andric DECLARE_OP0(DW_CFA_remember_state); 2040b57cec5SDimitry Andric DECLARE_OP0(DW_CFA_restore_state); 2050b57cec5SDimitry Andric DECLARE_OP0(DW_CFA_GNU_window_save); 2060b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_GNU_args_size, OT_Offset); 2070b57cec5SDimitry Andric DECLARE_OP0(DW_CFA_nop); 2080b57cec5SDimitry Andric 2090b57cec5SDimitry Andric #undef DECLARE_OP0 2100b57cec5SDimitry Andric #undef DECLARE_OP1 2110b57cec5SDimitry Andric #undef DECLARE_OP2 2120b57cec5SDimitry Andric 2130b57cec5SDimitry Andric return ArrayRef<OperandType[2]>(&OpTypes[0], DW_CFA_restore+1); 2140b57cec5SDimitry Andric } 2150b57cec5SDimitry Andric 2160b57cec5SDimitry Andric /// Print \p Opcode's operand number \p OperandIdx which has value \p Operand. 2170b57cec5SDimitry Andric void CFIProgram::printOperand(raw_ostream &OS, const MCRegisterInfo *MRI, 2180b57cec5SDimitry Andric bool IsEH, const Instruction &Instr, 2190b57cec5SDimitry Andric unsigned OperandIdx, uint64_t Operand) const { 2200b57cec5SDimitry Andric assert(OperandIdx < 2); 2210b57cec5SDimitry Andric uint8_t Opcode = Instr.Opcode; 2220b57cec5SDimitry Andric OperandType Type = getOperandTypes()[Opcode][OperandIdx]; 2230b57cec5SDimitry Andric 2240b57cec5SDimitry Andric switch (Type) { 2250b57cec5SDimitry Andric case OT_Unset: { 2260b57cec5SDimitry Andric OS << " Unsupported " << (OperandIdx ? "second" : "first") << " operand to"; 2270b57cec5SDimitry Andric auto OpcodeName = CallFrameString(Opcode, Arch); 2280b57cec5SDimitry Andric if (!OpcodeName.empty()) 2290b57cec5SDimitry Andric OS << " " << OpcodeName; 2300b57cec5SDimitry Andric else 2310b57cec5SDimitry Andric OS << format(" Opcode %x", Opcode); 2320b57cec5SDimitry Andric break; 2330b57cec5SDimitry Andric } 2340b57cec5SDimitry Andric case OT_None: 2350b57cec5SDimitry Andric break; 2360b57cec5SDimitry Andric case OT_Address: 2370b57cec5SDimitry Andric OS << format(" %" PRIx64, Operand); 2380b57cec5SDimitry Andric break; 2390b57cec5SDimitry Andric case OT_Offset: 2400b57cec5SDimitry Andric // The offsets are all encoded in a unsigned form, but in practice 2410b57cec5SDimitry Andric // consumers use them signed. It's most certainly legacy due to 2420b57cec5SDimitry Andric // the lack of signed variants in the first Dwarf standards. 2430b57cec5SDimitry Andric OS << format(" %+" PRId64, int64_t(Operand)); 2440b57cec5SDimitry Andric break; 2450b57cec5SDimitry Andric case OT_FactoredCodeOffset: // Always Unsigned 2460b57cec5SDimitry Andric if (CodeAlignmentFactor) 2470b57cec5SDimitry Andric OS << format(" %" PRId64, Operand * CodeAlignmentFactor); 2480b57cec5SDimitry Andric else 2490b57cec5SDimitry Andric OS << format(" %" PRId64 "*code_alignment_factor" , Operand); 2500b57cec5SDimitry Andric break; 2510b57cec5SDimitry Andric case OT_SignedFactDataOffset: 2520b57cec5SDimitry Andric if (DataAlignmentFactor) 2530b57cec5SDimitry Andric OS << format(" %" PRId64, int64_t(Operand) * DataAlignmentFactor); 2540b57cec5SDimitry Andric else 2550b57cec5SDimitry Andric OS << format(" %" PRId64 "*data_alignment_factor" , int64_t(Operand)); 2560b57cec5SDimitry Andric break; 2570b57cec5SDimitry Andric case OT_UnsignedFactDataOffset: 2580b57cec5SDimitry Andric if (DataAlignmentFactor) 2590b57cec5SDimitry Andric OS << format(" %" PRId64, Operand * DataAlignmentFactor); 2600b57cec5SDimitry Andric else 2610b57cec5SDimitry Andric OS << format(" %" PRId64 "*data_alignment_factor" , Operand); 2620b57cec5SDimitry Andric break; 2630b57cec5SDimitry Andric case OT_Register: 2640b57cec5SDimitry Andric OS << format(" reg%" PRId64, Operand); 2650b57cec5SDimitry Andric break; 2660b57cec5SDimitry Andric case OT_Expression: 2670b57cec5SDimitry Andric assert(Instr.Expression && "missing DWARFExpression object"); 2680b57cec5SDimitry Andric OS << " "; 2690b57cec5SDimitry Andric Instr.Expression->print(OS, MRI, nullptr, IsEH); 2700b57cec5SDimitry Andric break; 2710b57cec5SDimitry Andric } 2720b57cec5SDimitry Andric } 2730b57cec5SDimitry Andric 2740b57cec5SDimitry Andric void CFIProgram::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH, 2750b57cec5SDimitry Andric unsigned IndentLevel) const { 2760b57cec5SDimitry Andric for (const auto &Instr : Instructions) { 2770b57cec5SDimitry Andric uint8_t Opcode = Instr.Opcode; 2780b57cec5SDimitry Andric if (Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK) 2790b57cec5SDimitry Andric Opcode &= DWARF_CFI_PRIMARY_OPCODE_MASK; 2800b57cec5SDimitry Andric OS.indent(2 * IndentLevel); 2810b57cec5SDimitry Andric OS << CallFrameString(Opcode, Arch) << ":"; 2820b57cec5SDimitry Andric for (unsigned i = 0; i < Instr.Ops.size(); ++i) 2830b57cec5SDimitry Andric printOperand(OS, MRI, IsEH, Instr, i, Instr.Ops[i]); 2840b57cec5SDimitry Andric OS << '\n'; 2850b57cec5SDimitry Andric } 2860b57cec5SDimitry Andric } 2870b57cec5SDimitry Andric 2880b57cec5SDimitry Andric void CIE::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH) const { 2890b57cec5SDimitry Andric OS << format("%08x %08x %08x CIE", (uint32_t)Offset, (uint32_t)Length, 2900b57cec5SDimitry Andric DW_CIE_ID) 2910b57cec5SDimitry Andric << "\n"; 2920b57cec5SDimitry Andric OS << format(" Version: %d\n", Version); 2930b57cec5SDimitry Andric OS << " Augmentation: \"" << Augmentation << "\"\n"; 2940b57cec5SDimitry Andric if (Version >= 4) { 2950b57cec5SDimitry Andric OS << format(" Address size: %u\n", (uint32_t)AddressSize); 2960b57cec5SDimitry Andric OS << format(" Segment desc size: %u\n", 2970b57cec5SDimitry Andric (uint32_t)SegmentDescriptorSize); 2980b57cec5SDimitry Andric } 2990b57cec5SDimitry Andric OS << format(" Code alignment factor: %u\n", (uint32_t)CodeAlignmentFactor); 3000b57cec5SDimitry Andric OS << format(" Data alignment factor: %d\n", (int32_t)DataAlignmentFactor); 3010b57cec5SDimitry Andric OS << format(" Return address column: %d\n", (int32_t)ReturnAddressRegister); 3020b57cec5SDimitry Andric if (Personality) 3030b57cec5SDimitry Andric OS << format(" Personality Address: %016" PRIx64 "\n", *Personality); 3040b57cec5SDimitry Andric if (!AugmentationData.empty()) { 3050b57cec5SDimitry Andric OS << " Augmentation data: "; 3060b57cec5SDimitry Andric for (uint8_t Byte : AugmentationData) 3070b57cec5SDimitry Andric OS << ' ' << hexdigit(Byte >> 4) << hexdigit(Byte & 0xf); 3080b57cec5SDimitry Andric OS << "\n"; 3090b57cec5SDimitry Andric } 3100b57cec5SDimitry Andric OS << "\n"; 3110b57cec5SDimitry Andric CFIs.dump(OS, MRI, IsEH); 3120b57cec5SDimitry Andric OS << "\n"; 3130b57cec5SDimitry Andric } 3140b57cec5SDimitry Andric 3150b57cec5SDimitry Andric void FDE::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH) const { 3160b57cec5SDimitry Andric OS << format("%08x %08x %08x FDE ", (uint32_t)Offset, (uint32_t)Length, 3170b57cec5SDimitry Andric (int32_t)LinkedCIEOffset); 3180b57cec5SDimitry Andric OS << format("cie=%08x pc=%08x...%08x\n", (int32_t)LinkedCIEOffset, 3190b57cec5SDimitry Andric (uint32_t)InitialLocation, 3200b57cec5SDimitry Andric (uint32_t)InitialLocation + (uint32_t)AddressRange); 3210b57cec5SDimitry Andric if (LSDAAddress) 3220b57cec5SDimitry Andric OS << format(" LSDA Address: %016" PRIx64 "\n", *LSDAAddress); 3230b57cec5SDimitry Andric CFIs.dump(OS, MRI, IsEH); 3240b57cec5SDimitry Andric OS << "\n"; 3250b57cec5SDimitry Andric } 3260b57cec5SDimitry Andric 3270b57cec5SDimitry Andric DWARFDebugFrame::DWARFDebugFrame(Triple::ArchType Arch, 3280b57cec5SDimitry Andric bool IsEH, uint64_t EHFrameAddress) 3290b57cec5SDimitry Andric : Arch(Arch), IsEH(IsEH), EHFrameAddress(EHFrameAddress) {} 3300b57cec5SDimitry Andric 3310b57cec5SDimitry Andric DWARFDebugFrame::~DWARFDebugFrame() = default; 3320b57cec5SDimitry Andric 3330b57cec5SDimitry Andric static void LLVM_ATTRIBUTE_UNUSED dumpDataAux(DataExtractor Data, 334*8bcb0991SDimitry Andric uint64_t Offset, int Length) { 3350b57cec5SDimitry Andric errs() << "DUMP: "; 3360b57cec5SDimitry Andric for (int i = 0; i < Length; ++i) { 3370b57cec5SDimitry Andric uint8_t c = Data.getU8(&Offset); 3380b57cec5SDimitry Andric errs().write_hex(c); errs() << " "; 3390b57cec5SDimitry Andric } 3400b57cec5SDimitry Andric errs() << "\n"; 3410b57cec5SDimitry Andric } 3420b57cec5SDimitry Andric 3430b57cec5SDimitry Andric // This is a workaround for old compilers which do not allow 3440b57cec5SDimitry Andric // noreturn attribute usage in lambdas. Once the support for those 3450b57cec5SDimitry Andric // compilers are phased out, we can remove this and return back to 3460b57cec5SDimitry Andric // a ReportError lambda: [StartOffset](const char *ErrorMsg). 347*8bcb0991SDimitry Andric static void LLVM_ATTRIBUTE_NORETURN ReportError(uint64_t StartOffset, 3480b57cec5SDimitry Andric const char *ErrorMsg) { 3490b57cec5SDimitry Andric std::string Str; 3500b57cec5SDimitry Andric raw_string_ostream OS(Str); 3510b57cec5SDimitry Andric OS << format(ErrorMsg, StartOffset); 3520b57cec5SDimitry Andric OS.flush(); 3530b57cec5SDimitry Andric report_fatal_error(Str); 3540b57cec5SDimitry Andric } 3550b57cec5SDimitry Andric 3560b57cec5SDimitry Andric void DWARFDebugFrame::parse(DWARFDataExtractor Data) { 357*8bcb0991SDimitry Andric uint64_t Offset = 0; 358*8bcb0991SDimitry Andric DenseMap<uint64_t, CIE *> CIEs; 3590b57cec5SDimitry Andric 3600b57cec5SDimitry Andric while (Data.isValidOffset(Offset)) { 361*8bcb0991SDimitry Andric uint64_t StartOffset = Offset; 3620b57cec5SDimitry Andric 3630b57cec5SDimitry Andric bool IsDWARF64 = false; 3640b57cec5SDimitry Andric uint64_t Length = Data.getRelocatedValue(4, &Offset); 3650b57cec5SDimitry Andric uint64_t Id; 3660b57cec5SDimitry Andric 367*8bcb0991SDimitry Andric if (Length == dwarf::DW_LENGTH_DWARF64) { 3680b57cec5SDimitry Andric // DWARF-64 is distinguished by the first 32 bits of the initial length 3690b57cec5SDimitry Andric // field being 0xffffffff. Then, the next 64 bits are the actual entry 3700b57cec5SDimitry Andric // length. 3710b57cec5SDimitry Andric IsDWARF64 = true; 3720b57cec5SDimitry Andric Length = Data.getRelocatedValue(8, &Offset); 3730b57cec5SDimitry Andric } 3740b57cec5SDimitry Andric 3750b57cec5SDimitry Andric // At this point, Offset points to the next field after Length. 3760b57cec5SDimitry Andric // Length is the structure size excluding itself. Compute an offset one 3770b57cec5SDimitry Andric // past the end of the structure (needed to know how many instructions to 3780b57cec5SDimitry Andric // read). 379*8bcb0991SDimitry Andric uint64_t StartStructureOffset = Offset; 380*8bcb0991SDimitry Andric uint64_t EndStructureOffset = Offset + Length; 3810b57cec5SDimitry Andric 3820b57cec5SDimitry Andric // The Id field's size depends on the DWARF format 3830b57cec5SDimitry Andric Id = Data.getUnsigned(&Offset, (IsDWARF64 && !IsEH) ? 8 : 4); 3840b57cec5SDimitry Andric bool IsCIE = 3850b57cec5SDimitry Andric ((IsDWARF64 && Id == DW64_CIE_ID) || Id == DW_CIE_ID || (IsEH && !Id)); 3860b57cec5SDimitry Andric 3870b57cec5SDimitry Andric if (IsCIE) { 3880b57cec5SDimitry Andric uint8_t Version = Data.getU8(&Offset); 3890b57cec5SDimitry Andric const char *Augmentation = Data.getCStr(&Offset); 3900b57cec5SDimitry Andric StringRef AugmentationString(Augmentation ? Augmentation : ""); 3910b57cec5SDimitry Andric uint8_t AddressSize = Version < 4 ? Data.getAddressSize() : 3920b57cec5SDimitry Andric Data.getU8(&Offset); 3930b57cec5SDimitry Andric Data.setAddressSize(AddressSize); 3940b57cec5SDimitry Andric uint8_t SegmentDescriptorSize = Version < 4 ? 0 : Data.getU8(&Offset); 3950b57cec5SDimitry Andric uint64_t CodeAlignmentFactor = Data.getULEB128(&Offset); 3960b57cec5SDimitry Andric int64_t DataAlignmentFactor = Data.getSLEB128(&Offset); 3970b57cec5SDimitry Andric uint64_t ReturnAddressRegister = 3980b57cec5SDimitry Andric Version == 1 ? Data.getU8(&Offset) : Data.getULEB128(&Offset); 3990b57cec5SDimitry Andric 4000b57cec5SDimitry Andric // Parse the augmentation data for EH CIEs 4010b57cec5SDimitry Andric StringRef AugmentationData(""); 4020b57cec5SDimitry Andric uint32_t FDEPointerEncoding = DW_EH_PE_absptr; 4030b57cec5SDimitry Andric uint32_t LSDAPointerEncoding = DW_EH_PE_omit; 4040b57cec5SDimitry Andric Optional<uint64_t> Personality; 4050b57cec5SDimitry Andric Optional<uint32_t> PersonalityEncoding; 4060b57cec5SDimitry Andric if (IsEH) { 4070b57cec5SDimitry Andric Optional<uint64_t> AugmentationLength; 408*8bcb0991SDimitry Andric uint64_t StartAugmentationOffset; 409*8bcb0991SDimitry Andric uint64_t EndAugmentationOffset; 4100b57cec5SDimitry Andric 4110b57cec5SDimitry Andric // Walk the augmentation string to get all the augmentation data. 4120b57cec5SDimitry Andric for (unsigned i = 0, e = AugmentationString.size(); i != e; ++i) { 4130b57cec5SDimitry Andric switch (AugmentationString[i]) { 4140b57cec5SDimitry Andric default: 415*8bcb0991SDimitry Andric ReportError( 416*8bcb0991SDimitry Andric StartOffset, 417*8bcb0991SDimitry Andric "Unknown augmentation character in entry at %" PRIx64); 4180b57cec5SDimitry Andric case 'L': 4190b57cec5SDimitry Andric LSDAPointerEncoding = Data.getU8(&Offset); 4200b57cec5SDimitry Andric break; 4210b57cec5SDimitry Andric case 'P': { 4220b57cec5SDimitry Andric if (Personality) 4230b57cec5SDimitry Andric ReportError(StartOffset, 424*8bcb0991SDimitry Andric "Duplicate personality in entry at %" PRIx64); 4250b57cec5SDimitry Andric PersonalityEncoding = Data.getU8(&Offset); 4260b57cec5SDimitry Andric Personality = Data.getEncodedPointer( 4270b57cec5SDimitry Andric &Offset, *PersonalityEncoding, 4280b57cec5SDimitry Andric EHFrameAddress ? EHFrameAddress + Offset : 0); 4290b57cec5SDimitry Andric break; 4300b57cec5SDimitry Andric } 4310b57cec5SDimitry Andric case 'R': 4320b57cec5SDimitry Andric FDEPointerEncoding = Data.getU8(&Offset); 4330b57cec5SDimitry Andric break; 4340b57cec5SDimitry Andric case 'S': 4350b57cec5SDimitry Andric // Current frame is a signal trampoline. 4360b57cec5SDimitry Andric break; 4370b57cec5SDimitry Andric case 'z': 4380b57cec5SDimitry Andric if (i) 4390b57cec5SDimitry Andric ReportError(StartOffset, 440*8bcb0991SDimitry Andric "'z' must be the first character at %" PRIx64); 4410b57cec5SDimitry Andric // Parse the augmentation length first. We only parse it if 4420b57cec5SDimitry Andric // the string contains a 'z'. 4430b57cec5SDimitry Andric AugmentationLength = Data.getULEB128(&Offset); 4440b57cec5SDimitry Andric StartAugmentationOffset = Offset; 445*8bcb0991SDimitry Andric EndAugmentationOffset = Offset + *AugmentationLength; 4460b57cec5SDimitry Andric break; 4470b57cec5SDimitry Andric case 'B': 4480b57cec5SDimitry Andric // B-Key is used for signing functions associated with this 4490b57cec5SDimitry Andric // augmentation string 4500b57cec5SDimitry Andric break; 4510b57cec5SDimitry Andric } 4520b57cec5SDimitry Andric } 4530b57cec5SDimitry Andric 4540b57cec5SDimitry Andric if (AugmentationLength.hasValue()) { 4550b57cec5SDimitry Andric if (Offset != EndAugmentationOffset) 456*8bcb0991SDimitry Andric ReportError(StartOffset, 457*8bcb0991SDimitry Andric "Parsing augmentation data at %" PRIx64 " failed"); 4580b57cec5SDimitry Andric 4590b57cec5SDimitry Andric AugmentationData = Data.getData().slice(StartAugmentationOffset, 4600b57cec5SDimitry Andric EndAugmentationOffset); 4610b57cec5SDimitry Andric } 4620b57cec5SDimitry Andric } 4630b57cec5SDimitry Andric 464*8bcb0991SDimitry Andric auto Cie = std::make_unique<CIE>( 4650b57cec5SDimitry Andric StartOffset, Length, Version, AugmentationString, AddressSize, 4660b57cec5SDimitry Andric SegmentDescriptorSize, CodeAlignmentFactor, DataAlignmentFactor, 4670b57cec5SDimitry Andric ReturnAddressRegister, AugmentationData, FDEPointerEncoding, 4680b57cec5SDimitry Andric LSDAPointerEncoding, Personality, PersonalityEncoding, Arch); 4690b57cec5SDimitry Andric CIEs[StartOffset] = Cie.get(); 4700b57cec5SDimitry Andric Entries.emplace_back(std::move(Cie)); 4710b57cec5SDimitry Andric } else { 4720b57cec5SDimitry Andric // FDE 4730b57cec5SDimitry Andric uint64_t CIEPointer = Id; 4740b57cec5SDimitry Andric uint64_t InitialLocation = 0; 4750b57cec5SDimitry Andric uint64_t AddressRange = 0; 4760b57cec5SDimitry Andric Optional<uint64_t> LSDAAddress; 4770b57cec5SDimitry Andric CIE *Cie = CIEs[IsEH ? (StartStructureOffset - CIEPointer) : CIEPointer]; 4780b57cec5SDimitry Andric 4790b57cec5SDimitry Andric if (IsEH) { 4800b57cec5SDimitry Andric // The address size is encoded in the CIE we reference. 4810b57cec5SDimitry Andric if (!Cie) 482*8bcb0991SDimitry Andric ReportError(StartOffset, "Parsing FDE data at %" PRIx64 483*8bcb0991SDimitry Andric " failed due to missing CIE"); 4840b57cec5SDimitry Andric 4850b57cec5SDimitry Andric if (auto Val = Data.getEncodedPointer( 4860b57cec5SDimitry Andric &Offset, Cie->getFDEPointerEncoding(), 4870b57cec5SDimitry Andric EHFrameAddress ? EHFrameAddress + Offset : 0)) { 4880b57cec5SDimitry Andric InitialLocation = *Val; 4890b57cec5SDimitry Andric } 4900b57cec5SDimitry Andric if (auto Val = Data.getEncodedPointer( 4910b57cec5SDimitry Andric &Offset, Cie->getFDEPointerEncoding(), 0)) { 4920b57cec5SDimitry Andric AddressRange = *Val; 4930b57cec5SDimitry Andric } 4940b57cec5SDimitry Andric 4950b57cec5SDimitry Andric StringRef AugmentationString = Cie->getAugmentationString(); 4960b57cec5SDimitry Andric if (!AugmentationString.empty()) { 4970b57cec5SDimitry Andric // Parse the augmentation length and data for this FDE. 4980b57cec5SDimitry Andric uint64_t AugmentationLength = Data.getULEB128(&Offset); 4990b57cec5SDimitry Andric 500*8bcb0991SDimitry Andric uint64_t EndAugmentationOffset = Offset + AugmentationLength; 5010b57cec5SDimitry Andric 5020b57cec5SDimitry Andric // Decode the LSDA if the CIE augmentation string said we should. 5030b57cec5SDimitry Andric if (Cie->getLSDAPointerEncoding() != DW_EH_PE_omit) { 5040b57cec5SDimitry Andric LSDAAddress = Data.getEncodedPointer( 5050b57cec5SDimitry Andric &Offset, Cie->getLSDAPointerEncoding(), 5060b57cec5SDimitry Andric EHFrameAddress ? Offset + EHFrameAddress : 0); 5070b57cec5SDimitry Andric } 5080b57cec5SDimitry Andric 5090b57cec5SDimitry Andric if (Offset != EndAugmentationOffset) 510*8bcb0991SDimitry Andric ReportError(StartOffset, 511*8bcb0991SDimitry Andric "Parsing augmentation data at %" PRIx64 " failed"); 5120b57cec5SDimitry Andric } 5130b57cec5SDimitry Andric } else { 5140b57cec5SDimitry Andric InitialLocation = Data.getRelocatedAddress(&Offset); 5150b57cec5SDimitry Andric AddressRange = Data.getRelocatedAddress(&Offset); 5160b57cec5SDimitry Andric } 5170b57cec5SDimitry Andric 5180b57cec5SDimitry Andric Entries.emplace_back(new FDE(StartOffset, Length, CIEPointer, 5190b57cec5SDimitry Andric InitialLocation, AddressRange, 5200b57cec5SDimitry Andric Cie, LSDAAddress, Arch)); 5210b57cec5SDimitry Andric } 5220b57cec5SDimitry Andric 5230b57cec5SDimitry Andric if (Error E = 5240b57cec5SDimitry Andric Entries.back()->cfis().parse(Data, &Offset, EndStructureOffset)) { 5250b57cec5SDimitry Andric report_fatal_error(toString(std::move(E))); 5260b57cec5SDimitry Andric } 5270b57cec5SDimitry Andric 5280b57cec5SDimitry Andric if (Offset != EndStructureOffset) 529*8bcb0991SDimitry Andric ReportError(StartOffset, 530*8bcb0991SDimitry Andric "Parsing entry instructions at %" PRIx64 " failed"); 5310b57cec5SDimitry Andric } 5320b57cec5SDimitry Andric } 5330b57cec5SDimitry Andric 5340b57cec5SDimitry Andric FrameEntry *DWARFDebugFrame::getEntryAtOffset(uint64_t Offset) const { 5350b57cec5SDimitry Andric auto It = partition_point(Entries, [=](const std::unique_ptr<FrameEntry> &E) { 5360b57cec5SDimitry Andric return E->getOffset() < Offset; 5370b57cec5SDimitry Andric }); 5380b57cec5SDimitry Andric if (It != Entries.end() && (*It)->getOffset() == Offset) 5390b57cec5SDimitry Andric return It->get(); 5400b57cec5SDimitry Andric return nullptr; 5410b57cec5SDimitry Andric } 5420b57cec5SDimitry Andric 5430b57cec5SDimitry Andric void DWARFDebugFrame::dump(raw_ostream &OS, const MCRegisterInfo *MRI, 5440b57cec5SDimitry Andric Optional<uint64_t> Offset) const { 5450b57cec5SDimitry Andric if (Offset) { 5460b57cec5SDimitry Andric if (auto *Entry = getEntryAtOffset(*Offset)) 5470b57cec5SDimitry Andric Entry->dump(OS, MRI, IsEH); 5480b57cec5SDimitry Andric return; 5490b57cec5SDimitry Andric } 5500b57cec5SDimitry Andric 5510b57cec5SDimitry Andric OS << "\n"; 5520b57cec5SDimitry Andric for (const auto &Entry : Entries) 5530b57cec5SDimitry Andric Entry->dump(OS, MRI, IsEH); 5540b57cec5SDimitry Andric } 555