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