1*0b57cec5SDimitry Andric //===- DWARFDebugFrame.h - Parsing of .debug_frame ------------------------===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric 9*0b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h" 10*0b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h" 11*0b57cec5SDimitry Andric #include "llvm/ADT/Optional.h" 12*0b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h" 13*0b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 14*0b57cec5SDimitry Andric #include "llvm/BinaryFormat/Dwarf.h" 15*0b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 16*0b57cec5SDimitry Andric #include "llvm/Support/Compiler.h" 17*0b57cec5SDimitry Andric #include "llvm/Support/DataExtractor.h" 18*0b57cec5SDimitry Andric #include "llvm/Support/Errc.h" 19*0b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 20*0b57cec5SDimitry Andric #include "llvm/Support/Format.h" 21*0b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 22*0b57cec5SDimitry Andric #include <algorithm> 23*0b57cec5SDimitry Andric #include <cassert> 24*0b57cec5SDimitry Andric #include <cinttypes> 25*0b57cec5SDimitry Andric #include <cstdint> 26*0b57cec5SDimitry Andric #include <string> 27*0b57cec5SDimitry Andric #include <vector> 28*0b57cec5SDimitry Andric 29*0b57cec5SDimitry Andric using namespace llvm; 30*0b57cec5SDimitry Andric using namespace dwarf; 31*0b57cec5SDimitry Andric 32*0b57cec5SDimitry Andric 33*0b57cec5SDimitry Andric // See DWARF standard v3, section 7.23 34*0b57cec5SDimitry Andric const uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK = 0xc0; 35*0b57cec5SDimitry Andric const uint8_t DWARF_CFI_PRIMARY_OPERAND_MASK = 0x3f; 36*0b57cec5SDimitry Andric 37*0b57cec5SDimitry Andric Error CFIProgram::parse(DWARFDataExtractor Data, uint32_t *Offset, 38*0b57cec5SDimitry Andric uint32_t EndOffset) { 39*0b57cec5SDimitry Andric while (*Offset < EndOffset) { 40*0b57cec5SDimitry Andric uint8_t Opcode = Data.getRelocatedValue(1, Offset); 41*0b57cec5SDimitry Andric // Some instructions have a primary opcode encoded in the top bits. 42*0b57cec5SDimitry Andric uint8_t Primary = Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK; 43*0b57cec5SDimitry Andric 44*0b57cec5SDimitry Andric if (Primary) { 45*0b57cec5SDimitry Andric // If it's a primary opcode, the first operand is encoded in the bottom 46*0b57cec5SDimitry Andric // bits of the opcode itself. 47*0b57cec5SDimitry Andric uint64_t Op1 = Opcode & DWARF_CFI_PRIMARY_OPERAND_MASK; 48*0b57cec5SDimitry Andric switch (Primary) { 49*0b57cec5SDimitry Andric default: 50*0b57cec5SDimitry Andric return createStringError(errc::illegal_byte_sequence, 51*0b57cec5SDimitry Andric "Invalid primary CFI opcode 0x%" PRIx8, 52*0b57cec5SDimitry Andric Primary); 53*0b57cec5SDimitry Andric case DW_CFA_advance_loc: 54*0b57cec5SDimitry Andric case DW_CFA_restore: 55*0b57cec5SDimitry Andric addInstruction(Primary, Op1); 56*0b57cec5SDimitry Andric break; 57*0b57cec5SDimitry Andric case DW_CFA_offset: 58*0b57cec5SDimitry Andric addInstruction(Primary, Op1, Data.getULEB128(Offset)); 59*0b57cec5SDimitry Andric break; 60*0b57cec5SDimitry Andric } 61*0b57cec5SDimitry Andric } else { 62*0b57cec5SDimitry Andric // Extended opcode - its value is Opcode itself. 63*0b57cec5SDimitry Andric switch (Opcode) { 64*0b57cec5SDimitry Andric default: 65*0b57cec5SDimitry Andric return createStringError(errc::illegal_byte_sequence, 66*0b57cec5SDimitry Andric "Invalid extended CFI opcode 0x%" PRIx8, 67*0b57cec5SDimitry Andric Opcode); 68*0b57cec5SDimitry Andric case DW_CFA_nop: 69*0b57cec5SDimitry Andric case DW_CFA_remember_state: 70*0b57cec5SDimitry Andric case DW_CFA_restore_state: 71*0b57cec5SDimitry Andric case DW_CFA_GNU_window_save: 72*0b57cec5SDimitry Andric // No operands 73*0b57cec5SDimitry Andric addInstruction(Opcode); 74*0b57cec5SDimitry Andric break; 75*0b57cec5SDimitry Andric case DW_CFA_set_loc: 76*0b57cec5SDimitry Andric // Operands: Address 77*0b57cec5SDimitry Andric addInstruction(Opcode, Data.getRelocatedAddress(Offset)); 78*0b57cec5SDimitry Andric break; 79*0b57cec5SDimitry Andric case DW_CFA_advance_loc1: 80*0b57cec5SDimitry Andric // Operands: 1-byte delta 81*0b57cec5SDimitry Andric addInstruction(Opcode, Data.getRelocatedValue(1, Offset)); 82*0b57cec5SDimitry Andric break; 83*0b57cec5SDimitry Andric case DW_CFA_advance_loc2: 84*0b57cec5SDimitry Andric // Operands: 2-byte delta 85*0b57cec5SDimitry Andric addInstruction(Opcode, Data.getRelocatedValue(2, Offset)); 86*0b57cec5SDimitry Andric break; 87*0b57cec5SDimitry Andric case DW_CFA_advance_loc4: 88*0b57cec5SDimitry Andric // Operands: 4-byte delta 89*0b57cec5SDimitry Andric addInstruction(Opcode, Data.getRelocatedValue(4, Offset)); 90*0b57cec5SDimitry Andric break; 91*0b57cec5SDimitry Andric case DW_CFA_restore_extended: 92*0b57cec5SDimitry Andric case DW_CFA_undefined: 93*0b57cec5SDimitry Andric case DW_CFA_same_value: 94*0b57cec5SDimitry Andric case DW_CFA_def_cfa_register: 95*0b57cec5SDimitry Andric case DW_CFA_def_cfa_offset: 96*0b57cec5SDimitry Andric case DW_CFA_GNU_args_size: 97*0b57cec5SDimitry Andric // Operands: ULEB128 98*0b57cec5SDimitry Andric addInstruction(Opcode, Data.getULEB128(Offset)); 99*0b57cec5SDimitry Andric break; 100*0b57cec5SDimitry Andric case DW_CFA_def_cfa_offset_sf: 101*0b57cec5SDimitry Andric // Operands: SLEB128 102*0b57cec5SDimitry Andric addInstruction(Opcode, Data.getSLEB128(Offset)); 103*0b57cec5SDimitry Andric break; 104*0b57cec5SDimitry Andric case DW_CFA_offset_extended: 105*0b57cec5SDimitry Andric case DW_CFA_register: 106*0b57cec5SDimitry Andric case DW_CFA_def_cfa: 107*0b57cec5SDimitry Andric case DW_CFA_val_offset: { 108*0b57cec5SDimitry Andric // Operands: ULEB128, ULEB128 109*0b57cec5SDimitry Andric // Note: We can not embed getULEB128 directly into function 110*0b57cec5SDimitry Andric // argument list. getULEB128 changes Offset and order of evaluation 111*0b57cec5SDimitry Andric // for arguments is unspecified. 112*0b57cec5SDimitry Andric auto op1 = Data.getULEB128(Offset); 113*0b57cec5SDimitry Andric auto op2 = Data.getULEB128(Offset); 114*0b57cec5SDimitry Andric addInstruction(Opcode, op1, op2); 115*0b57cec5SDimitry Andric break; 116*0b57cec5SDimitry Andric } 117*0b57cec5SDimitry Andric case DW_CFA_offset_extended_sf: 118*0b57cec5SDimitry Andric case DW_CFA_def_cfa_sf: 119*0b57cec5SDimitry Andric case DW_CFA_val_offset_sf: { 120*0b57cec5SDimitry Andric // Operands: ULEB128, SLEB128 121*0b57cec5SDimitry Andric // Note: see comment for the previous case 122*0b57cec5SDimitry Andric auto op1 = Data.getULEB128(Offset); 123*0b57cec5SDimitry Andric auto op2 = (uint64_t)Data.getSLEB128(Offset); 124*0b57cec5SDimitry Andric addInstruction(Opcode, op1, op2); 125*0b57cec5SDimitry Andric break; 126*0b57cec5SDimitry Andric } 127*0b57cec5SDimitry Andric case DW_CFA_def_cfa_expression: { 128*0b57cec5SDimitry Andric uint32_t ExprLength = Data.getULEB128(Offset); 129*0b57cec5SDimitry Andric addInstruction(Opcode, 0); 130*0b57cec5SDimitry Andric DataExtractor Extractor( 131*0b57cec5SDimitry Andric Data.getData().slice(*Offset, *Offset + ExprLength), 132*0b57cec5SDimitry Andric Data.isLittleEndian(), Data.getAddressSize()); 133*0b57cec5SDimitry Andric Instructions.back().Expression = DWARFExpression( 134*0b57cec5SDimitry Andric Extractor, Data.getAddressSize(), dwarf::DWARF_VERSION); 135*0b57cec5SDimitry Andric *Offset += ExprLength; 136*0b57cec5SDimitry Andric break; 137*0b57cec5SDimitry Andric } 138*0b57cec5SDimitry Andric case DW_CFA_expression: 139*0b57cec5SDimitry Andric case DW_CFA_val_expression: { 140*0b57cec5SDimitry Andric auto RegNum = Data.getULEB128(Offset); 141*0b57cec5SDimitry Andric auto BlockLength = Data.getULEB128(Offset); 142*0b57cec5SDimitry Andric addInstruction(Opcode, RegNum, 0); 143*0b57cec5SDimitry Andric DataExtractor Extractor( 144*0b57cec5SDimitry Andric Data.getData().slice(*Offset, *Offset + BlockLength), 145*0b57cec5SDimitry Andric Data.isLittleEndian(), Data.getAddressSize()); 146*0b57cec5SDimitry Andric Instructions.back().Expression = DWARFExpression( 147*0b57cec5SDimitry Andric Extractor, Data.getAddressSize(), dwarf::DWARF_VERSION); 148*0b57cec5SDimitry Andric *Offset += BlockLength; 149*0b57cec5SDimitry Andric break; 150*0b57cec5SDimitry Andric } 151*0b57cec5SDimitry Andric } 152*0b57cec5SDimitry Andric } 153*0b57cec5SDimitry Andric } 154*0b57cec5SDimitry Andric 155*0b57cec5SDimitry Andric return Error::success(); 156*0b57cec5SDimitry Andric } 157*0b57cec5SDimitry Andric 158*0b57cec5SDimitry Andric namespace { 159*0b57cec5SDimitry Andric 160*0b57cec5SDimitry Andric 161*0b57cec5SDimitry Andric } // end anonymous namespace 162*0b57cec5SDimitry Andric 163*0b57cec5SDimitry Andric ArrayRef<CFIProgram::OperandType[2]> CFIProgram::getOperandTypes() { 164*0b57cec5SDimitry Andric static OperandType OpTypes[DW_CFA_restore+1][2]; 165*0b57cec5SDimitry Andric static bool Initialized = false; 166*0b57cec5SDimitry Andric if (Initialized) { 167*0b57cec5SDimitry Andric return ArrayRef<OperandType[2]>(&OpTypes[0], DW_CFA_restore+1); 168*0b57cec5SDimitry Andric } 169*0b57cec5SDimitry Andric Initialized = true; 170*0b57cec5SDimitry Andric 171*0b57cec5SDimitry Andric #define DECLARE_OP2(OP, OPTYPE0, OPTYPE1) \ 172*0b57cec5SDimitry Andric do { \ 173*0b57cec5SDimitry Andric OpTypes[OP][0] = OPTYPE0; \ 174*0b57cec5SDimitry Andric OpTypes[OP][1] = OPTYPE1; \ 175*0b57cec5SDimitry Andric } while (false) 176*0b57cec5SDimitry Andric #define DECLARE_OP1(OP, OPTYPE0) DECLARE_OP2(OP, OPTYPE0, OT_None) 177*0b57cec5SDimitry Andric #define DECLARE_OP0(OP) DECLARE_OP1(OP, OT_None) 178*0b57cec5SDimitry Andric 179*0b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_set_loc, OT_Address); 180*0b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_advance_loc, OT_FactoredCodeOffset); 181*0b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_advance_loc1, OT_FactoredCodeOffset); 182*0b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_advance_loc2, OT_FactoredCodeOffset); 183*0b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_advance_loc4, OT_FactoredCodeOffset); 184*0b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_MIPS_advance_loc8, OT_FactoredCodeOffset); 185*0b57cec5SDimitry Andric DECLARE_OP2(DW_CFA_def_cfa, OT_Register, OT_Offset); 186*0b57cec5SDimitry Andric DECLARE_OP2(DW_CFA_def_cfa_sf, OT_Register, OT_SignedFactDataOffset); 187*0b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_def_cfa_register, OT_Register); 188*0b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_def_cfa_offset, OT_Offset); 189*0b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_def_cfa_offset_sf, OT_SignedFactDataOffset); 190*0b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_def_cfa_expression, OT_Expression); 191*0b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_undefined, OT_Register); 192*0b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_same_value, OT_Register); 193*0b57cec5SDimitry Andric DECLARE_OP2(DW_CFA_offset, OT_Register, OT_UnsignedFactDataOffset); 194*0b57cec5SDimitry Andric DECLARE_OP2(DW_CFA_offset_extended, OT_Register, OT_UnsignedFactDataOffset); 195*0b57cec5SDimitry Andric DECLARE_OP2(DW_CFA_offset_extended_sf, OT_Register, OT_SignedFactDataOffset); 196*0b57cec5SDimitry Andric DECLARE_OP2(DW_CFA_val_offset, OT_Register, OT_UnsignedFactDataOffset); 197*0b57cec5SDimitry Andric DECLARE_OP2(DW_CFA_val_offset_sf, OT_Register, OT_SignedFactDataOffset); 198*0b57cec5SDimitry Andric DECLARE_OP2(DW_CFA_register, OT_Register, OT_Register); 199*0b57cec5SDimitry Andric DECLARE_OP2(DW_CFA_expression, OT_Register, OT_Expression); 200*0b57cec5SDimitry Andric DECLARE_OP2(DW_CFA_val_expression, OT_Register, OT_Expression); 201*0b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_restore, OT_Register); 202*0b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_restore_extended, OT_Register); 203*0b57cec5SDimitry Andric DECLARE_OP0(DW_CFA_remember_state); 204*0b57cec5SDimitry Andric DECLARE_OP0(DW_CFA_restore_state); 205*0b57cec5SDimitry Andric DECLARE_OP0(DW_CFA_GNU_window_save); 206*0b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_GNU_args_size, OT_Offset); 207*0b57cec5SDimitry Andric DECLARE_OP0(DW_CFA_nop); 208*0b57cec5SDimitry Andric 209*0b57cec5SDimitry Andric #undef DECLARE_OP0 210*0b57cec5SDimitry Andric #undef DECLARE_OP1 211*0b57cec5SDimitry Andric #undef DECLARE_OP2 212*0b57cec5SDimitry Andric 213*0b57cec5SDimitry Andric return ArrayRef<OperandType[2]>(&OpTypes[0], DW_CFA_restore+1); 214*0b57cec5SDimitry Andric } 215*0b57cec5SDimitry Andric 216*0b57cec5SDimitry Andric /// Print \p Opcode's operand number \p OperandIdx which has value \p Operand. 217*0b57cec5SDimitry Andric void CFIProgram::printOperand(raw_ostream &OS, const MCRegisterInfo *MRI, 218*0b57cec5SDimitry Andric bool IsEH, const Instruction &Instr, 219*0b57cec5SDimitry Andric unsigned OperandIdx, uint64_t Operand) const { 220*0b57cec5SDimitry Andric assert(OperandIdx < 2); 221*0b57cec5SDimitry Andric uint8_t Opcode = Instr.Opcode; 222*0b57cec5SDimitry Andric OperandType Type = getOperandTypes()[Opcode][OperandIdx]; 223*0b57cec5SDimitry Andric 224*0b57cec5SDimitry Andric switch (Type) { 225*0b57cec5SDimitry Andric case OT_Unset: { 226*0b57cec5SDimitry Andric OS << " Unsupported " << (OperandIdx ? "second" : "first") << " operand to"; 227*0b57cec5SDimitry Andric auto OpcodeName = CallFrameString(Opcode, Arch); 228*0b57cec5SDimitry Andric if (!OpcodeName.empty()) 229*0b57cec5SDimitry Andric OS << " " << OpcodeName; 230*0b57cec5SDimitry Andric else 231*0b57cec5SDimitry Andric OS << format(" Opcode %x", Opcode); 232*0b57cec5SDimitry Andric break; 233*0b57cec5SDimitry Andric } 234*0b57cec5SDimitry Andric case OT_None: 235*0b57cec5SDimitry Andric break; 236*0b57cec5SDimitry Andric case OT_Address: 237*0b57cec5SDimitry Andric OS << format(" %" PRIx64, Operand); 238*0b57cec5SDimitry Andric break; 239*0b57cec5SDimitry Andric case OT_Offset: 240*0b57cec5SDimitry Andric // The offsets are all encoded in a unsigned form, but in practice 241*0b57cec5SDimitry Andric // consumers use them signed. It's most certainly legacy due to 242*0b57cec5SDimitry Andric // the lack of signed variants in the first Dwarf standards. 243*0b57cec5SDimitry Andric OS << format(" %+" PRId64, int64_t(Operand)); 244*0b57cec5SDimitry Andric break; 245*0b57cec5SDimitry Andric case OT_FactoredCodeOffset: // Always Unsigned 246*0b57cec5SDimitry Andric if (CodeAlignmentFactor) 247*0b57cec5SDimitry Andric OS << format(" %" PRId64, Operand * CodeAlignmentFactor); 248*0b57cec5SDimitry Andric else 249*0b57cec5SDimitry Andric OS << format(" %" PRId64 "*code_alignment_factor" , Operand); 250*0b57cec5SDimitry Andric break; 251*0b57cec5SDimitry Andric case OT_SignedFactDataOffset: 252*0b57cec5SDimitry Andric if (DataAlignmentFactor) 253*0b57cec5SDimitry Andric OS << format(" %" PRId64, int64_t(Operand) * DataAlignmentFactor); 254*0b57cec5SDimitry Andric else 255*0b57cec5SDimitry Andric OS << format(" %" PRId64 "*data_alignment_factor" , int64_t(Operand)); 256*0b57cec5SDimitry Andric break; 257*0b57cec5SDimitry Andric case OT_UnsignedFactDataOffset: 258*0b57cec5SDimitry Andric if (DataAlignmentFactor) 259*0b57cec5SDimitry Andric OS << format(" %" PRId64, Operand * DataAlignmentFactor); 260*0b57cec5SDimitry Andric else 261*0b57cec5SDimitry Andric OS << format(" %" PRId64 "*data_alignment_factor" , Operand); 262*0b57cec5SDimitry Andric break; 263*0b57cec5SDimitry Andric case OT_Register: 264*0b57cec5SDimitry Andric OS << format(" reg%" PRId64, Operand); 265*0b57cec5SDimitry Andric break; 266*0b57cec5SDimitry Andric case OT_Expression: 267*0b57cec5SDimitry Andric assert(Instr.Expression && "missing DWARFExpression object"); 268*0b57cec5SDimitry Andric OS << " "; 269*0b57cec5SDimitry Andric Instr.Expression->print(OS, MRI, nullptr, IsEH); 270*0b57cec5SDimitry Andric break; 271*0b57cec5SDimitry Andric } 272*0b57cec5SDimitry Andric } 273*0b57cec5SDimitry Andric 274*0b57cec5SDimitry Andric void CFIProgram::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH, 275*0b57cec5SDimitry Andric unsigned IndentLevel) const { 276*0b57cec5SDimitry Andric for (const auto &Instr : Instructions) { 277*0b57cec5SDimitry Andric uint8_t Opcode = Instr.Opcode; 278*0b57cec5SDimitry Andric if (Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK) 279*0b57cec5SDimitry Andric Opcode &= DWARF_CFI_PRIMARY_OPCODE_MASK; 280*0b57cec5SDimitry Andric OS.indent(2 * IndentLevel); 281*0b57cec5SDimitry Andric OS << CallFrameString(Opcode, Arch) << ":"; 282*0b57cec5SDimitry Andric for (unsigned i = 0; i < Instr.Ops.size(); ++i) 283*0b57cec5SDimitry Andric printOperand(OS, MRI, IsEH, Instr, i, Instr.Ops[i]); 284*0b57cec5SDimitry Andric OS << '\n'; 285*0b57cec5SDimitry Andric } 286*0b57cec5SDimitry Andric } 287*0b57cec5SDimitry Andric 288*0b57cec5SDimitry Andric void CIE::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH) const { 289*0b57cec5SDimitry Andric OS << format("%08x %08x %08x CIE", (uint32_t)Offset, (uint32_t)Length, 290*0b57cec5SDimitry Andric DW_CIE_ID) 291*0b57cec5SDimitry Andric << "\n"; 292*0b57cec5SDimitry Andric OS << format(" Version: %d\n", Version); 293*0b57cec5SDimitry Andric OS << " Augmentation: \"" << Augmentation << "\"\n"; 294*0b57cec5SDimitry Andric if (Version >= 4) { 295*0b57cec5SDimitry Andric OS << format(" Address size: %u\n", (uint32_t)AddressSize); 296*0b57cec5SDimitry Andric OS << format(" Segment desc size: %u\n", 297*0b57cec5SDimitry Andric (uint32_t)SegmentDescriptorSize); 298*0b57cec5SDimitry Andric } 299*0b57cec5SDimitry Andric OS << format(" Code alignment factor: %u\n", (uint32_t)CodeAlignmentFactor); 300*0b57cec5SDimitry Andric OS << format(" Data alignment factor: %d\n", (int32_t)DataAlignmentFactor); 301*0b57cec5SDimitry Andric OS << format(" Return address column: %d\n", (int32_t)ReturnAddressRegister); 302*0b57cec5SDimitry Andric if (Personality) 303*0b57cec5SDimitry Andric OS << format(" Personality Address: %016" PRIx64 "\n", *Personality); 304*0b57cec5SDimitry Andric if (!AugmentationData.empty()) { 305*0b57cec5SDimitry Andric OS << " Augmentation data: "; 306*0b57cec5SDimitry Andric for (uint8_t Byte : AugmentationData) 307*0b57cec5SDimitry Andric OS << ' ' << hexdigit(Byte >> 4) << hexdigit(Byte & 0xf); 308*0b57cec5SDimitry Andric OS << "\n"; 309*0b57cec5SDimitry Andric } 310*0b57cec5SDimitry Andric OS << "\n"; 311*0b57cec5SDimitry Andric CFIs.dump(OS, MRI, IsEH); 312*0b57cec5SDimitry Andric OS << "\n"; 313*0b57cec5SDimitry Andric } 314*0b57cec5SDimitry Andric 315*0b57cec5SDimitry Andric void FDE::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH) const { 316*0b57cec5SDimitry Andric OS << format("%08x %08x %08x FDE ", (uint32_t)Offset, (uint32_t)Length, 317*0b57cec5SDimitry Andric (int32_t)LinkedCIEOffset); 318*0b57cec5SDimitry Andric OS << format("cie=%08x pc=%08x...%08x\n", (int32_t)LinkedCIEOffset, 319*0b57cec5SDimitry Andric (uint32_t)InitialLocation, 320*0b57cec5SDimitry Andric (uint32_t)InitialLocation + (uint32_t)AddressRange); 321*0b57cec5SDimitry Andric if (LSDAAddress) 322*0b57cec5SDimitry Andric OS << format(" LSDA Address: %016" PRIx64 "\n", *LSDAAddress); 323*0b57cec5SDimitry Andric CFIs.dump(OS, MRI, IsEH); 324*0b57cec5SDimitry Andric OS << "\n"; 325*0b57cec5SDimitry Andric } 326*0b57cec5SDimitry Andric 327*0b57cec5SDimitry Andric DWARFDebugFrame::DWARFDebugFrame(Triple::ArchType Arch, 328*0b57cec5SDimitry Andric bool IsEH, uint64_t EHFrameAddress) 329*0b57cec5SDimitry Andric : Arch(Arch), IsEH(IsEH), EHFrameAddress(EHFrameAddress) {} 330*0b57cec5SDimitry Andric 331*0b57cec5SDimitry Andric DWARFDebugFrame::~DWARFDebugFrame() = default; 332*0b57cec5SDimitry Andric 333*0b57cec5SDimitry Andric static void LLVM_ATTRIBUTE_UNUSED dumpDataAux(DataExtractor Data, 334*0b57cec5SDimitry Andric uint32_t Offset, int Length) { 335*0b57cec5SDimitry Andric errs() << "DUMP: "; 336*0b57cec5SDimitry Andric for (int i = 0; i < Length; ++i) { 337*0b57cec5SDimitry Andric uint8_t c = Data.getU8(&Offset); 338*0b57cec5SDimitry Andric errs().write_hex(c); errs() << " "; 339*0b57cec5SDimitry Andric } 340*0b57cec5SDimitry Andric errs() << "\n"; 341*0b57cec5SDimitry Andric } 342*0b57cec5SDimitry Andric 343*0b57cec5SDimitry Andric // This is a workaround for old compilers which do not allow 344*0b57cec5SDimitry Andric // noreturn attribute usage in lambdas. Once the support for those 345*0b57cec5SDimitry Andric // compilers are phased out, we can remove this and return back to 346*0b57cec5SDimitry Andric // a ReportError lambda: [StartOffset](const char *ErrorMsg). 347*0b57cec5SDimitry Andric static void LLVM_ATTRIBUTE_NORETURN ReportError(uint32_t StartOffset, 348*0b57cec5SDimitry Andric const char *ErrorMsg) { 349*0b57cec5SDimitry Andric std::string Str; 350*0b57cec5SDimitry Andric raw_string_ostream OS(Str); 351*0b57cec5SDimitry Andric OS << format(ErrorMsg, StartOffset); 352*0b57cec5SDimitry Andric OS.flush(); 353*0b57cec5SDimitry Andric report_fatal_error(Str); 354*0b57cec5SDimitry Andric } 355*0b57cec5SDimitry Andric 356*0b57cec5SDimitry Andric void DWARFDebugFrame::parse(DWARFDataExtractor Data) { 357*0b57cec5SDimitry Andric uint32_t Offset = 0; 358*0b57cec5SDimitry Andric DenseMap<uint32_t, CIE *> CIEs; 359*0b57cec5SDimitry Andric 360*0b57cec5SDimitry Andric while (Data.isValidOffset(Offset)) { 361*0b57cec5SDimitry Andric uint32_t StartOffset = Offset; 362*0b57cec5SDimitry Andric 363*0b57cec5SDimitry Andric bool IsDWARF64 = false; 364*0b57cec5SDimitry Andric uint64_t Length = Data.getRelocatedValue(4, &Offset); 365*0b57cec5SDimitry Andric uint64_t Id; 366*0b57cec5SDimitry Andric 367*0b57cec5SDimitry Andric if (Length == UINT32_MAX) { 368*0b57cec5SDimitry Andric // DWARF-64 is distinguished by the first 32 bits of the initial length 369*0b57cec5SDimitry Andric // field being 0xffffffff. Then, the next 64 bits are the actual entry 370*0b57cec5SDimitry Andric // length. 371*0b57cec5SDimitry Andric IsDWARF64 = true; 372*0b57cec5SDimitry Andric Length = Data.getRelocatedValue(8, &Offset); 373*0b57cec5SDimitry Andric } 374*0b57cec5SDimitry Andric 375*0b57cec5SDimitry Andric // At this point, Offset points to the next field after Length. 376*0b57cec5SDimitry Andric // Length is the structure size excluding itself. Compute an offset one 377*0b57cec5SDimitry Andric // past the end of the structure (needed to know how many instructions to 378*0b57cec5SDimitry Andric // read). 379*0b57cec5SDimitry Andric // TODO: For honest DWARF64 support, DataExtractor will have to treat 380*0b57cec5SDimitry Andric // offset_ptr as uint64_t* 381*0b57cec5SDimitry Andric uint32_t StartStructureOffset = Offset; 382*0b57cec5SDimitry Andric uint32_t EndStructureOffset = Offset + static_cast<uint32_t>(Length); 383*0b57cec5SDimitry Andric 384*0b57cec5SDimitry Andric // The Id field's size depends on the DWARF format 385*0b57cec5SDimitry Andric Id = Data.getUnsigned(&Offset, (IsDWARF64 && !IsEH) ? 8 : 4); 386*0b57cec5SDimitry Andric bool IsCIE = 387*0b57cec5SDimitry Andric ((IsDWARF64 && Id == DW64_CIE_ID) || Id == DW_CIE_ID || (IsEH && !Id)); 388*0b57cec5SDimitry Andric 389*0b57cec5SDimitry Andric if (IsCIE) { 390*0b57cec5SDimitry Andric uint8_t Version = Data.getU8(&Offset); 391*0b57cec5SDimitry Andric const char *Augmentation = Data.getCStr(&Offset); 392*0b57cec5SDimitry Andric StringRef AugmentationString(Augmentation ? Augmentation : ""); 393*0b57cec5SDimitry Andric uint8_t AddressSize = Version < 4 ? Data.getAddressSize() : 394*0b57cec5SDimitry Andric Data.getU8(&Offset); 395*0b57cec5SDimitry Andric Data.setAddressSize(AddressSize); 396*0b57cec5SDimitry Andric uint8_t SegmentDescriptorSize = Version < 4 ? 0 : Data.getU8(&Offset); 397*0b57cec5SDimitry Andric uint64_t CodeAlignmentFactor = Data.getULEB128(&Offset); 398*0b57cec5SDimitry Andric int64_t DataAlignmentFactor = Data.getSLEB128(&Offset); 399*0b57cec5SDimitry Andric uint64_t ReturnAddressRegister = 400*0b57cec5SDimitry Andric Version == 1 ? Data.getU8(&Offset) : Data.getULEB128(&Offset); 401*0b57cec5SDimitry Andric 402*0b57cec5SDimitry Andric // Parse the augmentation data for EH CIEs 403*0b57cec5SDimitry Andric StringRef AugmentationData(""); 404*0b57cec5SDimitry Andric uint32_t FDEPointerEncoding = DW_EH_PE_absptr; 405*0b57cec5SDimitry Andric uint32_t LSDAPointerEncoding = DW_EH_PE_omit; 406*0b57cec5SDimitry Andric Optional<uint64_t> Personality; 407*0b57cec5SDimitry Andric Optional<uint32_t> PersonalityEncoding; 408*0b57cec5SDimitry Andric if (IsEH) { 409*0b57cec5SDimitry Andric Optional<uint64_t> AugmentationLength; 410*0b57cec5SDimitry Andric uint32_t StartAugmentationOffset; 411*0b57cec5SDimitry Andric uint32_t EndAugmentationOffset; 412*0b57cec5SDimitry Andric 413*0b57cec5SDimitry Andric // Walk the augmentation string to get all the augmentation data. 414*0b57cec5SDimitry Andric for (unsigned i = 0, e = AugmentationString.size(); i != e; ++i) { 415*0b57cec5SDimitry Andric switch (AugmentationString[i]) { 416*0b57cec5SDimitry Andric default: 417*0b57cec5SDimitry Andric ReportError(StartOffset, 418*0b57cec5SDimitry Andric "Unknown augmentation character in entry at %lx"); 419*0b57cec5SDimitry Andric case 'L': 420*0b57cec5SDimitry Andric LSDAPointerEncoding = Data.getU8(&Offset); 421*0b57cec5SDimitry Andric break; 422*0b57cec5SDimitry Andric case 'P': { 423*0b57cec5SDimitry Andric if (Personality) 424*0b57cec5SDimitry Andric ReportError(StartOffset, 425*0b57cec5SDimitry Andric "Duplicate personality in entry at %lx"); 426*0b57cec5SDimitry Andric PersonalityEncoding = Data.getU8(&Offset); 427*0b57cec5SDimitry Andric Personality = Data.getEncodedPointer( 428*0b57cec5SDimitry Andric &Offset, *PersonalityEncoding, 429*0b57cec5SDimitry Andric EHFrameAddress ? EHFrameAddress + Offset : 0); 430*0b57cec5SDimitry Andric break; 431*0b57cec5SDimitry Andric } 432*0b57cec5SDimitry Andric case 'R': 433*0b57cec5SDimitry Andric FDEPointerEncoding = Data.getU8(&Offset); 434*0b57cec5SDimitry Andric break; 435*0b57cec5SDimitry Andric case 'S': 436*0b57cec5SDimitry Andric // Current frame is a signal trampoline. 437*0b57cec5SDimitry Andric break; 438*0b57cec5SDimitry Andric case 'z': 439*0b57cec5SDimitry Andric if (i) 440*0b57cec5SDimitry Andric ReportError(StartOffset, 441*0b57cec5SDimitry Andric "'z' must be the first character at %lx"); 442*0b57cec5SDimitry Andric // Parse the augmentation length first. We only parse it if 443*0b57cec5SDimitry Andric // the string contains a 'z'. 444*0b57cec5SDimitry Andric AugmentationLength = Data.getULEB128(&Offset); 445*0b57cec5SDimitry Andric StartAugmentationOffset = Offset; 446*0b57cec5SDimitry Andric EndAugmentationOffset = Offset + 447*0b57cec5SDimitry Andric static_cast<uint32_t>(*AugmentationLength); 448*0b57cec5SDimitry Andric break; 449*0b57cec5SDimitry Andric case 'B': 450*0b57cec5SDimitry Andric // B-Key is used for signing functions associated with this 451*0b57cec5SDimitry Andric // augmentation string 452*0b57cec5SDimitry Andric break; 453*0b57cec5SDimitry Andric } 454*0b57cec5SDimitry Andric } 455*0b57cec5SDimitry Andric 456*0b57cec5SDimitry Andric if (AugmentationLength.hasValue()) { 457*0b57cec5SDimitry Andric if (Offset != EndAugmentationOffset) 458*0b57cec5SDimitry Andric ReportError(StartOffset, "Parsing augmentation data at %lx failed"); 459*0b57cec5SDimitry Andric 460*0b57cec5SDimitry Andric AugmentationData = Data.getData().slice(StartAugmentationOffset, 461*0b57cec5SDimitry Andric EndAugmentationOffset); 462*0b57cec5SDimitry Andric } 463*0b57cec5SDimitry Andric } 464*0b57cec5SDimitry Andric 465*0b57cec5SDimitry Andric auto Cie = llvm::make_unique<CIE>( 466*0b57cec5SDimitry Andric StartOffset, Length, Version, AugmentationString, AddressSize, 467*0b57cec5SDimitry Andric SegmentDescriptorSize, CodeAlignmentFactor, DataAlignmentFactor, 468*0b57cec5SDimitry Andric ReturnAddressRegister, AugmentationData, FDEPointerEncoding, 469*0b57cec5SDimitry Andric LSDAPointerEncoding, Personality, PersonalityEncoding, Arch); 470*0b57cec5SDimitry Andric CIEs[StartOffset] = Cie.get(); 471*0b57cec5SDimitry Andric Entries.emplace_back(std::move(Cie)); 472*0b57cec5SDimitry Andric } else { 473*0b57cec5SDimitry Andric // FDE 474*0b57cec5SDimitry Andric uint64_t CIEPointer = Id; 475*0b57cec5SDimitry Andric uint64_t InitialLocation = 0; 476*0b57cec5SDimitry Andric uint64_t AddressRange = 0; 477*0b57cec5SDimitry Andric Optional<uint64_t> LSDAAddress; 478*0b57cec5SDimitry Andric CIE *Cie = CIEs[IsEH ? (StartStructureOffset - CIEPointer) : CIEPointer]; 479*0b57cec5SDimitry Andric 480*0b57cec5SDimitry Andric if (IsEH) { 481*0b57cec5SDimitry Andric // The address size is encoded in the CIE we reference. 482*0b57cec5SDimitry Andric if (!Cie) 483*0b57cec5SDimitry Andric ReportError(StartOffset, 484*0b57cec5SDimitry Andric "Parsing FDE data at %lx failed due to missing CIE"); 485*0b57cec5SDimitry Andric 486*0b57cec5SDimitry Andric if (auto Val = Data.getEncodedPointer( 487*0b57cec5SDimitry Andric &Offset, Cie->getFDEPointerEncoding(), 488*0b57cec5SDimitry Andric EHFrameAddress ? EHFrameAddress + Offset : 0)) { 489*0b57cec5SDimitry Andric InitialLocation = *Val; 490*0b57cec5SDimitry Andric } 491*0b57cec5SDimitry Andric if (auto Val = Data.getEncodedPointer( 492*0b57cec5SDimitry Andric &Offset, Cie->getFDEPointerEncoding(), 0)) { 493*0b57cec5SDimitry Andric AddressRange = *Val; 494*0b57cec5SDimitry Andric } 495*0b57cec5SDimitry Andric 496*0b57cec5SDimitry Andric StringRef AugmentationString = Cie->getAugmentationString(); 497*0b57cec5SDimitry Andric if (!AugmentationString.empty()) { 498*0b57cec5SDimitry Andric // Parse the augmentation length and data for this FDE. 499*0b57cec5SDimitry Andric uint64_t AugmentationLength = Data.getULEB128(&Offset); 500*0b57cec5SDimitry Andric 501*0b57cec5SDimitry Andric uint32_t EndAugmentationOffset = 502*0b57cec5SDimitry Andric Offset + static_cast<uint32_t>(AugmentationLength); 503*0b57cec5SDimitry Andric 504*0b57cec5SDimitry Andric // Decode the LSDA if the CIE augmentation string said we should. 505*0b57cec5SDimitry Andric if (Cie->getLSDAPointerEncoding() != DW_EH_PE_omit) { 506*0b57cec5SDimitry Andric LSDAAddress = Data.getEncodedPointer( 507*0b57cec5SDimitry Andric &Offset, Cie->getLSDAPointerEncoding(), 508*0b57cec5SDimitry Andric EHFrameAddress ? Offset + EHFrameAddress : 0); 509*0b57cec5SDimitry Andric } 510*0b57cec5SDimitry Andric 511*0b57cec5SDimitry Andric if (Offset != EndAugmentationOffset) 512*0b57cec5SDimitry Andric ReportError(StartOffset, "Parsing augmentation data at %lx failed"); 513*0b57cec5SDimitry Andric } 514*0b57cec5SDimitry Andric } else { 515*0b57cec5SDimitry Andric InitialLocation = Data.getRelocatedAddress(&Offset); 516*0b57cec5SDimitry Andric AddressRange = Data.getRelocatedAddress(&Offset); 517*0b57cec5SDimitry Andric } 518*0b57cec5SDimitry Andric 519*0b57cec5SDimitry Andric Entries.emplace_back(new FDE(StartOffset, Length, CIEPointer, 520*0b57cec5SDimitry Andric InitialLocation, AddressRange, 521*0b57cec5SDimitry Andric Cie, LSDAAddress, Arch)); 522*0b57cec5SDimitry Andric } 523*0b57cec5SDimitry Andric 524*0b57cec5SDimitry Andric if (Error E = 525*0b57cec5SDimitry Andric Entries.back()->cfis().parse(Data, &Offset, EndStructureOffset)) { 526*0b57cec5SDimitry Andric report_fatal_error(toString(std::move(E))); 527*0b57cec5SDimitry Andric } 528*0b57cec5SDimitry Andric 529*0b57cec5SDimitry Andric if (Offset != EndStructureOffset) 530*0b57cec5SDimitry Andric ReportError(StartOffset, "Parsing entry instructions at %lx failed"); 531*0b57cec5SDimitry Andric } 532*0b57cec5SDimitry Andric } 533*0b57cec5SDimitry Andric 534*0b57cec5SDimitry Andric FrameEntry *DWARFDebugFrame::getEntryAtOffset(uint64_t Offset) const { 535*0b57cec5SDimitry Andric auto It = partition_point(Entries, [=](const std::unique_ptr<FrameEntry> &E) { 536*0b57cec5SDimitry Andric return E->getOffset() < Offset; 537*0b57cec5SDimitry Andric }); 538*0b57cec5SDimitry Andric if (It != Entries.end() && (*It)->getOffset() == Offset) 539*0b57cec5SDimitry Andric return It->get(); 540*0b57cec5SDimitry Andric return nullptr; 541*0b57cec5SDimitry Andric } 542*0b57cec5SDimitry Andric 543*0b57cec5SDimitry Andric void DWARFDebugFrame::dump(raw_ostream &OS, const MCRegisterInfo *MRI, 544*0b57cec5SDimitry Andric Optional<uint64_t> Offset) const { 545*0b57cec5SDimitry Andric if (Offset) { 546*0b57cec5SDimitry Andric if (auto *Entry = getEntryAtOffset(*Offset)) 547*0b57cec5SDimitry Andric Entry->dump(OS, MRI, IsEH); 548*0b57cec5SDimitry Andric return; 549*0b57cec5SDimitry Andric } 550*0b57cec5SDimitry Andric 551*0b57cec5SDimitry Andric OS << "\n"; 552*0b57cec5SDimitry Andric for (const auto &Entry : Entries) 553*0b57cec5SDimitry Andric Entry->dump(OS, MRI, IsEH); 554*0b57cec5SDimitry Andric } 555