xref: /freebsd/contrib/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp (revision e8d8bef961a50d4dc22501cde4fb9fb0be1b2532)
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