reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
//===-- DWARFDebugMacro.cpp -------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "DWARFDebugMacro.h"
#include "SymbolFileDWARF.h"

#include "lldb/Symbol/DebugMacros.h"

#include "DWARFDataExtractor.h"

using namespace lldb_private;

DWARFDebugMacroHeader
DWARFDebugMacroHeader::ParseHeader(const DWARFDataExtractor &debug_macro_data,
                                   lldb::offset_t *offset) {
  DWARFDebugMacroHeader header;

  // Skip over the version field in header.
  header.m_version = debug_macro_data.GetU16(offset);

  uint8_t flags = debug_macro_data.GetU8(offset);
  header.m_offset_is_64_bit = (flags & OFFSET_SIZE_MASK) != 0;

  if (flags & DEBUG_LINE_OFFSET_MASK) {
    if (header.m_offset_is_64_bit)
      header.m_debug_line_offset = debug_macro_data.GetU64(offset);
    else
      header.m_debug_line_offset = debug_macro_data.GetU32(offset);
  }

  // Skip over the operands table if it is present.
  if (flags & OPCODE_OPERANDS_TABLE_MASK)
    SkipOperandTable(debug_macro_data, offset);

  return header;
}

void DWARFDebugMacroHeader::SkipOperandTable(
    const DWARFDataExtractor &debug_macro_data, lldb::offset_t *offset) {
  uint8_t entry_count = debug_macro_data.GetU8(offset);
  for (uint8_t i = 0; i < entry_count; i++) {
    // Skip over the opcode number.
    debug_macro_data.GetU8(offset);

    uint64_t operand_count = debug_macro_data.GetULEB128(offset);

    for (uint64_t j = 0; j < operand_count; j++) {
      // Skip over the operand form
      debug_macro_data.GetU8(offset);
    }
  }
}

void DWARFDebugMacroEntry::ReadMacroEntries(
    const DWARFDataExtractor &debug_macro_data,
    const DWARFDataExtractor &debug_str_data, const bool offset_is_64_bit,
    lldb::offset_t *offset, SymbolFileDWARF *sym_file_dwarf,
    DebugMacrosSP &debug_macros_sp) {
  llvm::dwarf::MacroEntryType type =
      static_cast<llvm::dwarf::MacroEntryType>(debug_macro_data.GetU8(offset));
  while (type != 0) {
    lldb::offset_t new_offset = 0, str_offset = 0;
    uint32_t line = 0;
    const char *macro_str = nullptr;
    uint32_t debug_line_file_idx = 0;

    switch (type) {
    case DW_MACRO_define:
    case DW_MACRO_undef:
      line = debug_macro_data.GetULEB128(offset);
      macro_str = debug_macro_data.GetCStr(offset);
      if (type == DW_MACRO_define)
        debug_macros_sp->AddMacroEntry(
            DebugMacroEntry::CreateDefineEntry(line, macro_str));
      else
        debug_macros_sp->AddMacroEntry(
            DebugMacroEntry::CreateUndefEntry(line, macro_str));
      break;
    case DW_MACRO_define_strp:
    case DW_MACRO_undef_strp:
      line = debug_macro_data.GetULEB128(offset);
      if (offset_is_64_bit)
        str_offset = debug_macro_data.GetU64(offset);
      else
        str_offset = debug_macro_data.GetU32(offset);
      macro_str = debug_str_data.GetCStr(&str_offset);
      if (type == DW_MACRO_define_strp)
        debug_macros_sp->AddMacroEntry(
            DebugMacroEntry::CreateDefineEntry(line, macro_str));
      else
        debug_macros_sp->AddMacroEntry(
            DebugMacroEntry::CreateUndefEntry(line, macro_str));
      break;
    case DW_MACRO_start_file:
      line = debug_macro_data.GetULEB128(offset);
      debug_line_file_idx = debug_macro_data.GetULEB128(offset);
      debug_macros_sp->AddMacroEntry(
          DebugMacroEntry::CreateStartFileEntry(line, debug_line_file_idx));
      break;
    case DW_MACRO_end_file:
      // This operation has no operands.
      debug_macros_sp->AddMacroEntry(DebugMacroEntry::CreateEndFileEntry());
      break;
    case DW_MACRO_import:
      if (offset_is_64_bit)
        new_offset = debug_macro_data.GetU64(offset);
      else
        new_offset = debug_macro_data.GetU32(offset);
      debug_macros_sp->AddMacroEntry(DebugMacroEntry::CreateIndirectEntry(
          sym_file_dwarf->ParseDebugMacros(&new_offset)));
      break;
    default:
      // TODO: Add support for other standard operations.
      // TODO: Provide mechanism to hook handling of non-standard/extension
      // operands.
      return;
    }
    type = static_cast<llvm::dwarf::MacroEntryType>(
        debug_macro_data.GetU8(offset));
  }
}