160bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky//===-- DWARFDebugFrame.h - Parsing of .debug_frame -------------*- C++ -*-===//
260bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky//
360bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky//                     The LLVM Compiler Infrastructure
460bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky//
560bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky// This file is distributed under the University of Illinois Open Source
660bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky// License. See LICENSE.TXT for details.
760bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky//
860bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky//===----------------------------------------------------------------------===//
960bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky
1060bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky#include "DWARFDebugFrame.h"
1160bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky#include "llvm/ADT/SmallString.h"
1260bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky#include "llvm/Support/DataTypes.h"
1360bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky#include "llvm/Support/Dwarf.h"
1436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/Support/ErrorHandling.h"
1560bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky#include "llvm/Support/Format.h"
167bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky#include "llvm/Support/raw_ostream.h"
177bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky#include <string>
187bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky#include <vector>
1960bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky
2060bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Benderskyusing namespace llvm;
2160bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Benderskyusing namespace dwarf;
2260bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky
2360bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky
242e402d5b5f2fce8bfe29509cc771b9919946003bEli Bendersky/// \brief Abstract frame entry defining the common interface concrete
252e402d5b5f2fce8bfe29509cc771b9919946003bEli Bendersky/// entries implement.
2660bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Benderskyclass llvm::FrameEntry {
2760bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Benderskypublic:
2860bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky  enum FrameKind {FK_CIE, FK_FDE};
29dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  FrameEntry(FrameKind K, uint64_t Offset, uint64_t Length)
30dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      : Kind(K), Offset(Offset), Length(Length) {}
3160bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky
328a0329e6ffc290fb177fd058a64b4cf81d4b620aEli Bendersky  virtual ~FrameEntry() {
338a0329e6ffc290fb177fd058a64b4cf81d4b620aEli Bendersky  }
348a0329e6ffc290fb177fd058a64b4cf81d4b620aEli Bendersky
3560bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky  FrameKind getKind() const { return Kind; }
367bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky  virtual uint64_t getOffset() const { return Offset; }
3760bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky
38dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  /// \brief Parse and store a sequence of CFI instructions from Data,
39dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  /// starting at *Offset and ending at EndOffset. If everything
4046e0d1d58c9c1f288cbf943e4c930efd1a2968afEli Bendersky  /// goes well, *Offset should be equal to EndOffset when this method
417bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky  /// returns. Otherwise, an error occurred.
42dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  virtual void parseInstructions(DataExtractor Data, uint32_t *Offset,
43dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                                 uint32_t EndOffset);
447bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky
457bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky  /// \brief Dump the entry header to the given output stream.
4660bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky  virtual void dumpHeader(raw_ostream &OS) const = 0;
47ba42625074aa7f4f1324a5d6666bd0e302b57f2bEli Bendersky
487bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky  /// \brief Dump the entry's instructions to the given output stream.
497bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky  virtual void dumpInstructions(raw_ostream &OS) const;
507bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky
5160bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Benderskyprotected:
5260bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky  const FrameKind Kind;
53ba42625074aa7f4f1324a5d6666bd0e302b57f2bEli Bendersky
54ba42625074aa7f4f1324a5d6666bd0e302b57f2bEli Bendersky  /// \brief Offset of this entry in the section.
5560bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky  uint64_t Offset;
56ba42625074aa7f4f1324a5d6666bd0e302b57f2bEli Bendersky
57ba42625074aa7f4f1324a5d6666bd0e302b57f2bEli Bendersky  /// \brief Entry length as specified in DWARF.
5860bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky  uint64_t Length;
597bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky
607bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky  /// An entry may contain CFI instructions. An instruction consists of an
617bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky  /// opcode and an optional sequence of operands.
627bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky  typedef std::vector<uint64_t> Operands;
637bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky  struct Instruction {
647bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky    Instruction(uint8_t Opcode)
657bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky      : Opcode(Opcode)
667bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky    {}
677bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky
687bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky    uint8_t Opcode;
697bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky    Operands Ops;
707bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky  };
717bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky
727bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky  std::vector<Instruction> Instructions;
737bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky
747bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky  /// Convenience methods to add a new instruction with the given opcode and
757bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky  /// operands to the Instructions vector.
767bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky  void addInstruction(uint8_t Opcode) {
777bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky    Instructions.push_back(Instruction(Opcode));
787bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky  }
797bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky
807bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky  void addInstruction(uint8_t Opcode, uint64_t Operand1) {
817bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky    Instructions.push_back(Instruction(Opcode));
827bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky    Instructions.back().Ops.push_back(Operand1);
837bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky  }
847bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky
857bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky  void addInstruction(uint8_t Opcode, uint64_t Operand1, uint64_t Operand2) {
867bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky    Instructions.push_back(Instruction(Opcode));
877bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky    Instructions.back().Ops.push_back(Operand1);
887bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky    Instructions.back().Ops.push_back(Operand2);
897bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky  }
9060bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky};
9160bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky
927bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky
937bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky// See DWARF standard v3, section 7.23
947bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Benderskyconst uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK = 0xc0;
957bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Benderskyconst uint8_t DWARF_CFI_PRIMARY_OPERAND_MASK = 0x3f;
967bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky
97dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesvoid FrameEntry::parseInstructions(DataExtractor Data, uint32_t *Offset,
98dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                                   uint32_t EndOffset) {
9946e0d1d58c9c1f288cbf943e4c930efd1a2968afEli Bendersky  while (*Offset < EndOffset) {
10046e0d1d58c9c1f288cbf943e4c930efd1a2968afEli Bendersky    uint8_t Opcode = Data.getU8(Offset);
1017bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky    // Some instructions have a primary opcode encoded in the top bits.
1027bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky    uint8_t Primary = Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK;
1037bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky
1047bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky    if (Primary) {
1057bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky      // If it's a primary opcode, the first operand is encoded in the bottom
1067bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky      // bits of the opcode itself.
1077bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky      uint64_t Op1 = Opcode & DWARF_CFI_PRIMARY_OPERAND_MASK;
1087bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky      switch (Primary) {
1097bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky        default: llvm_unreachable("Impossible primary CFI opcode");
1107bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky        case DW_CFA_advance_loc:
1117bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky        case DW_CFA_restore:
1127bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky          addInstruction(Primary, Op1);
1137bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky          break;
1147bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky        case DW_CFA_offset:
11546e0d1d58c9c1f288cbf943e4c930efd1a2968afEli Bendersky          addInstruction(Primary, Op1, Data.getULEB128(Offset));
1167bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky          break;
1177bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky      }
1187bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky    } else {
1197bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky      // Extended opcode - its value is Opcode itself.
1207bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky      switch (Opcode) {
1217bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky        default: llvm_unreachable("Invalid extended CFI opcode");
1227bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky        case DW_CFA_nop:
1237bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky        case DW_CFA_remember_state:
1247bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky        case DW_CFA_restore_state:
12536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        case DW_CFA_GNU_window_save:
1267bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky          // No operands
1277bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky          addInstruction(Opcode);
1287bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky          break;
1297bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky        case DW_CFA_set_loc:
1307bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky          // Operands: Address
13146e0d1d58c9c1f288cbf943e4c930efd1a2968afEli Bendersky          addInstruction(Opcode, Data.getAddress(Offset));
1327bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky          break;
1337bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky        case DW_CFA_advance_loc1:
1347bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky          // Operands: 1-byte delta
13546e0d1d58c9c1f288cbf943e4c930efd1a2968afEli Bendersky          addInstruction(Opcode, Data.getU8(Offset));
1367bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky          break;
1377bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky        case DW_CFA_advance_loc2:
1387bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky          // Operands: 2-byte delta
13946e0d1d58c9c1f288cbf943e4c930efd1a2968afEli Bendersky          addInstruction(Opcode, Data.getU16(Offset));
1407bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky          break;
1417bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky        case DW_CFA_advance_loc4:
1427bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky          // Operands: 4-byte delta
14346e0d1d58c9c1f288cbf943e4c930efd1a2968afEli Bendersky          addInstruction(Opcode, Data.getU32(Offset));
1447bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky          break;
1457bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky        case DW_CFA_restore_extended:
1467bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky        case DW_CFA_undefined:
1477bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky        case DW_CFA_same_value:
1487bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky        case DW_CFA_def_cfa_register:
1497bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky        case DW_CFA_def_cfa_offset:
1507bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky          // Operands: ULEB128
15146e0d1d58c9c1f288cbf943e4c930efd1a2968afEli Bendersky          addInstruction(Opcode, Data.getULEB128(Offset));
1527bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky          break;
1537bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky        case DW_CFA_def_cfa_offset_sf:
1547bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky          // Operands: SLEB128
15546e0d1d58c9c1f288cbf943e4c930efd1a2968afEli Bendersky          addInstruction(Opcode, Data.getSLEB128(Offset));
1567bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky          break;
1577bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky        case DW_CFA_offset_extended:
1587bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky        case DW_CFA_register:
1597bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky        case DW_CFA_def_cfa:
1607bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky        case DW_CFA_val_offset:
1617bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky          // Operands: ULEB128, ULEB128
16246e0d1d58c9c1f288cbf943e4c930efd1a2968afEli Bendersky          addInstruction(Opcode, Data.getULEB128(Offset),
16346e0d1d58c9c1f288cbf943e4c930efd1a2968afEli Bendersky                                 Data.getULEB128(Offset));
1647bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky          break;
1657bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky        case DW_CFA_offset_extended_sf:
1667bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky        case DW_CFA_def_cfa_sf:
1677bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky        case DW_CFA_val_offset_sf:
1687bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky          // Operands: ULEB128, SLEB128
16946e0d1d58c9c1f288cbf943e4c930efd1a2968afEli Bendersky          addInstruction(Opcode, Data.getULEB128(Offset),
17046e0d1d58c9c1f288cbf943e4c930efd1a2968afEli Bendersky                                 Data.getSLEB128(Offset));
1717bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky          break;
1727bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky        case DW_CFA_def_cfa_expression:
1737bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky        case DW_CFA_expression:
1747bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky        case DW_CFA_val_expression:
1757bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky          // TODO: implement this
1767bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky          report_fatal_error("Values with expressions not implemented yet!");
1777bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky      }
1787bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky    }
1797bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky  }
1807bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky}
1817bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky
1827bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky
1837bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Benderskyvoid FrameEntry::dumpInstructions(raw_ostream &OS) const {
1847bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky  // TODO: at the moment only instruction names are dumped. Expand this to
1857bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky  // dump operands as well.
18636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  for (const auto &Instr : Instructions) {
18736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    uint8_t Opcode = Instr.Opcode;
1887bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky    if (Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK)
1897bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky      Opcode &= DWARF_CFI_PRIMARY_OPCODE_MASK;
1907bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky    OS << "  " << CallFrameString(Opcode) << ":\n";
1917bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky  }
1927bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky}
1937bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky
1947bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky
19574b3c8da4800c7e8ba8f019879db29738ecc5f74Benjamin Kramernamespace {
1962e402d5b5f2fce8bfe29509cc771b9919946003bEli Bendersky/// \brief DWARF Common Information Entry (CIE)
19760bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Benderskyclass CIE : public FrameEntry {
19860bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Benderskypublic:
19960bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky  // CIEs (and FDEs) are simply container classes, so the only sensible way to
20060bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky  // create them is by providing the full parsed contents in the constructor.
201dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  CIE(uint64_t Offset, uint64_t Length, uint8_t Version,
20260bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky      SmallString<8> Augmentation, uint64_t CodeAlignmentFactor,
20360bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky      int64_t DataAlignmentFactor, uint64_t ReturnAddressRegister)
204dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      : FrameEntry(FK_CIE, Offset, Length), Version(Version),
205dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        Augmentation(Augmentation), CodeAlignmentFactor(CodeAlignmentFactor),
206dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        DataAlignmentFactor(DataAlignmentFactor),
207dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        ReturnAddressRegister(ReturnAddressRegister) {}
20860bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky
2098a0329e6ffc290fb177fd058a64b4cf81d4b620aEli Bendersky  ~CIE() {
2108a0329e6ffc290fb177fd058a64b4cf81d4b620aEli Bendersky  }
2118a0329e6ffc290fb177fd058a64b4cf81d4b620aEli Bendersky
21236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  void dumpHeader(raw_ostream &OS) const override {
21390e01ac0ea5bdc6dd6bccd9c59c3acb04e339666NAKAMURA Takumi    OS << format("%08x %08x %08x CIE",
21490e01ac0ea5bdc6dd6bccd9c59c3acb04e339666NAKAMURA Takumi                 (uint32_t)Offset, (uint32_t)Length, DW_CIE_ID)
21590e01ac0ea5bdc6dd6bccd9c59c3acb04e339666NAKAMURA Takumi       << "\n";
21660bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky    OS << format("  Version:               %d\n", Version);
21760bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky    OS << "  Augmentation:          \"" << Augmentation << "\"\n";
2187bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky    OS << format("  Code alignment factor: %u\n",
2197bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky                 (uint32_t)CodeAlignmentFactor);
2207bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky    OS << format("  Data alignment factor: %d\n",
2217bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky                 (int32_t)DataAlignmentFactor);
2227bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky    OS << format("  Return address column: %d\n",
2237bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky                 (int32_t)ReturnAddressRegister);
22460bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky    OS << "\n";
22560bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky  }
22660bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky
22760bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky  static bool classof(const FrameEntry *FE) {
22860bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky    return FE->getKind() == FK_CIE;
229dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  }
230ba42625074aa7f4f1324a5d6666bd0e302b57f2bEli Bendersky
23160bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Benderskyprivate:
232ba42625074aa7f4f1324a5d6666bd0e302b57f2bEli Bendersky  /// The following fields are defined in section 6.4.1 of the DWARF standard v3
23360bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky  uint8_t Version;
23460bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky  SmallString<8> Augmentation;
23560bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky  uint64_t CodeAlignmentFactor;
23660bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky  int64_t DataAlignmentFactor;
23760bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky  uint64_t ReturnAddressRegister;
23860bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky};
23960bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky
24060bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky
2412e402d5b5f2fce8bfe29509cc771b9919946003bEli Bendersky/// \brief DWARF Frame Description Entry (FDE)
24260bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Benderskyclass FDE : public FrameEntry {
24360bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Benderskypublic:
24460bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky  // Each FDE has a CIE it's "linked to". Our FDE contains is constructed with
24560bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky  // an offset to the CIE (provided by parsing the FDE header). The CIE itself
24660bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky  // is obtained lazily once it's actually required.
247dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  FDE(uint64_t Offset, uint64_t Length, int64_t LinkedCIEOffset,
248dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      uint64_t InitialLocation, uint64_t AddressRange)
249dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      : FrameEntry(FK_FDE, Offset, Length), LinkedCIEOffset(LinkedCIEOffset),
250dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        InitialLocation(InitialLocation), AddressRange(AddressRange),
251dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        LinkedCIE(nullptr) {}
25260bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky
2538a0329e6ffc290fb177fd058a64b4cf81d4b620aEli Bendersky  ~FDE() {
2548a0329e6ffc290fb177fd058a64b4cf81d4b620aEli Bendersky  }
2558a0329e6ffc290fb177fd058a64b4cf81d4b620aEli Bendersky
25636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  void dumpHeader(raw_ostream &OS) const override {
25790e01ac0ea5bdc6dd6bccd9c59c3acb04e339666NAKAMURA Takumi    OS << format("%08x %08x %08x FDE ",
258d9a8d43ed3e7c6c32f52ab5d0f627f7b1cdb6aacNAKAMURA Takumi                 (uint32_t)Offset, (uint32_t)Length, (int32_t)LinkedCIEOffset);
25960bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky    OS << format("cie=%08x pc=%08x...%08x\n",
260d9a8d43ed3e7c6c32f52ab5d0f627f7b1cdb6aacNAKAMURA Takumi                 (int32_t)LinkedCIEOffset,
2618ff0631967c64d51b193b862aa0a6f1e8eb06f78NAKAMURA Takumi                 (uint32_t)InitialLocation,
2628ff0631967c64d51b193b862aa0a6f1e8eb06f78NAKAMURA Takumi                 (uint32_t)InitialLocation + (uint32_t)AddressRange);
263b2ac7c09b17efadea2a9f90f45801d9d2ee687aaEli Bendersky    if (LinkedCIE) {
264b2ac7c09b17efadea2a9f90f45801d9d2ee687aaEli Bendersky      OS << format("%p\n", LinkedCIE);
265b2ac7c09b17efadea2a9f90f45801d9d2ee687aaEli Bendersky    }
26660bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky  }
26760bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky
26860bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky  static bool classof(const FrameEntry *FE) {
26960bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky    return FE->getKind() == FK_FDE;
270dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  }
271ba42625074aa7f4f1324a5d6666bd0e302b57f2bEli Bendersky
272dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesprivate:
273ba42625074aa7f4f1324a5d6666bd0e302b57f2bEli Bendersky  /// The following fields are defined in section 6.4.1 of the DWARF standard v3
27460bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky  uint64_t LinkedCIEOffset;
27560bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky  uint64_t InitialLocation;
27660bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky  uint64_t AddressRange;
27760bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky  CIE *LinkedCIE;
27860bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky};
27974b3c8da4800c7e8ba8f019879db29738ecc5f74Benjamin Kramer} // end anonymous namespace
28060bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky
28160bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky
282ba42625074aa7f4f1324a5d6666bd0e302b57f2bEli BenderskyDWARFDebugFrame::DWARFDebugFrame() {
28360bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky}
28460bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky
285ba42625074aa7f4f1324a5d6666bd0e302b57f2bEli BenderskyDWARFDebugFrame::~DWARFDebugFrame() {
28660bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky}
28760bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky
28860bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Benderskystatic void LLVM_ATTRIBUTE_UNUSED dumpDataAux(DataExtractor Data,
28960bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky                                              uint32_t Offset, int Length) {
29060bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky  errs() << "DUMP: ";
29160bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky  for (int i = 0; i < Length; ++i) {
29260bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky    uint8_t c = Data.getU8(&Offset);
29360bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky    errs().write_hex(c); errs() << " ";
29460bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky  }
29560bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky  errs() << "\n";
29660bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky}
29760bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky
29860bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky
29960bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Benderskyvoid DWARFDebugFrame::parse(DataExtractor Data) {
30060bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky  uint32_t Offset = 0;
30160bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky
30260bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky  while (Data.isValidOffset(Offset)) {
30360bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky    uint32_t StartOffset = Offset;
30460bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky
30560bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky    bool IsDWARF64 = false;
30660bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky    uint64_t Length = Data.getU32(&Offset);
30760bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky    uint64_t Id;
30860bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky
30960bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky    if (Length == UINT32_MAX) {
31060bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky      // DWARF-64 is distinguished by the first 32 bits of the initial length
31160bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky      // field being 0xffffffff. Then, the next 64 bits are the actual entry
31260bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky      // length.
31360bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky      IsDWARF64 = true;
31460bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky      Length = Data.getU64(&Offset);
31560bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky    }
31660bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky
31760bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky    // At this point, Offset points to the next field after Length.
31860bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky    // Length is the structure size excluding itself. Compute an offset one
31960bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky    // past the end of the structure (needed to know how many instructions to
32060bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky    // read).
32160bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky    // TODO: For honest DWARF64 support, DataExtractor will have to treat
32260bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky    //       offset_ptr as uint64_t*
32360bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky    uint32_t EndStructureOffset = Offset + static_cast<uint32_t>(Length);
32460bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky
32560bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky    // The Id field's size depends on the DWARF format
32660bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky    Id = Data.getUnsigned(&Offset, IsDWARF64 ? 8 : 4);
32760bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky    bool IsCIE = ((IsDWARF64 && Id == DW64_CIE_ID) || Id == DW_CIE_ID);
32860bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky
32960bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky    if (IsCIE) {
33060bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky      // Note: this is specifically DWARFv3 CIE header structure. It was
33146e0d1d58c9c1f288cbf943e4c930efd1a2968afEli Bendersky      // changed in DWARFv4. We currently don't support reading DWARFv4
33246e0d1d58c9c1f288cbf943e4c930efd1a2968afEli Bendersky      // here because LLVM itself does not emit it (and LLDB doesn't
33346e0d1d58c9c1f288cbf943e4c930efd1a2968afEli Bendersky      // support it either).
33460bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky      uint8_t Version = Data.getU8(&Offset);
33560bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky      const char *Augmentation = Data.getCStr(&Offset);
33660bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky      uint64_t CodeAlignmentFactor = Data.getULEB128(&Offset);
33760bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky      int64_t DataAlignmentFactor = Data.getSLEB128(&Offset);
33860bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky      uint64_t ReturnAddressRegister = Data.getULEB128(&Offset);
33960bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky
340dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      Entries.emplace_back(new CIE(StartOffset, Length, Version,
341dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                                   StringRef(Augmentation), CodeAlignmentFactor,
342dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                                   DataAlignmentFactor, ReturnAddressRegister));
34360bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky    } else {
34460bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky      // FDE
34560bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky      uint64_t CIEPointer = Id;
34660bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky      uint64_t InitialLocation = Data.getAddress(&Offset);
34760bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky      uint64_t AddressRange = Data.getAddress(&Offset);
34860bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky
349dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      Entries.emplace_back(new FDE(StartOffset, Length, CIEPointer,
350dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                                   InitialLocation, AddressRange));
35160bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky    }
35260bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky
353dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    Entries.back()->parseInstructions(Data, &Offset, EndStructureOffset);
3547bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky
355dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    if (Offset != EndStructureOffset) {
3567bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky      std::string Str;
3577bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky      raw_string_ostream OS(Str);
358dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      OS << format("Parsing entry instructions at %lx failed", StartOffset);
3597bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky      report_fatal_error(Str);
3607bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky    }
36160bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky  }
36260bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky}
36360bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky
36460bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky
36560bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Benderskyvoid DWARFDebugFrame::dump(raw_ostream &OS) const {
36660bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky  OS << "\n";
36736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  for (const auto &Entry : Entries) {
3687bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky    Entry->dumpHeader(OS);
3697bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky    Entry->dumpInstructions(OS);
3707bf3d6a0438485df61c438f26cfbaef2f8d8a3c4Eli Bendersky    OS << "\n";
37160bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky  }
37260bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky}
37360bdc5b16e2fc17be184b515a00c2e2a2eb40b89Eli Bendersky
374