1//===-- DWARFDebugMacro.cpp -------------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "DWARFDebugMacro.h"
10#include "SymbolFileDWARF.h"
11
12#include "lldb/Symbol/DebugMacros.h"
13
14#include "DWARFDataExtractor.h"
15
16using namespace lldb_private;
17
18DWARFDebugMacroHeader
19DWARFDebugMacroHeader::ParseHeader(const DWARFDataExtractor &debug_macro_data,
20                                   lldb::offset_t *offset) {
21  DWARFDebugMacroHeader header;
22
23  // Skip over the version field in header.
24  header.m_version = debug_macro_data.GetU16(offset);
25
26  uint8_t flags = debug_macro_data.GetU8(offset);
27  header.m_offset_is_64_bit = (flags & OFFSET_SIZE_MASK) != 0;
28
29  if (flags & DEBUG_LINE_OFFSET_MASK) {
30    if (header.m_offset_is_64_bit)
31      header.m_debug_line_offset = debug_macro_data.GetU64(offset);
32    else
33      header.m_debug_line_offset = debug_macro_data.GetU32(offset);
34  }
35
36  // Skip over the operands table if it is present.
37  if (flags & OPCODE_OPERANDS_TABLE_MASK)
38    SkipOperandTable(debug_macro_data, offset);
39
40  return header;
41}
42
43void DWARFDebugMacroHeader::SkipOperandTable(
44    const DWARFDataExtractor &debug_macro_data, lldb::offset_t *offset) {
45  uint8_t entry_count = debug_macro_data.GetU8(offset);
46  for (uint8_t i = 0; i < entry_count; i++) {
47    // Skip over the opcode number.
48    debug_macro_data.GetU8(offset);
49
50    uint64_t operand_count = debug_macro_data.GetULEB128(offset);
51
52    for (uint64_t j = 0; j < operand_count; j++) {
53      // Skip over the operand form
54      debug_macro_data.GetU8(offset);
55    }
56  }
57}
58
59void DWARFDebugMacroEntry::ReadMacroEntries(
60    const DWARFDataExtractor &debug_macro_data,
61    const DWARFDataExtractor &debug_str_data, const bool offset_is_64_bit,
62    lldb::offset_t *offset, SymbolFileDWARF *sym_file_dwarf,
63    DebugMacrosSP &debug_macros_sp) {
64  llvm::dwarf::MacroEntryType type =
65      static_cast<llvm::dwarf::MacroEntryType>(debug_macro_data.GetU8(offset));
66  while (type != 0) {
67    lldb::offset_t new_offset = 0, str_offset = 0;
68    uint32_t line = 0;
69    const char *macro_str = nullptr;
70    uint32_t debug_line_file_idx = 0;
71
72    switch (type) {
73    case DW_MACRO_define:
74    case DW_MACRO_undef:
75      line = debug_macro_data.GetULEB128(offset);
76      macro_str = debug_macro_data.GetCStr(offset);
77      if (type == DW_MACRO_define)
78        debug_macros_sp->AddMacroEntry(
79            DebugMacroEntry::CreateDefineEntry(line, macro_str));
80      else
81        debug_macros_sp->AddMacroEntry(
82            DebugMacroEntry::CreateUndefEntry(line, macro_str));
83      break;
84    case DW_MACRO_define_strp:
85    case DW_MACRO_undef_strp:
86      line = debug_macro_data.GetULEB128(offset);
87      if (offset_is_64_bit)
88        str_offset = debug_macro_data.GetU64(offset);
89      else
90        str_offset = debug_macro_data.GetU32(offset);
91      macro_str = debug_str_data.GetCStr(&str_offset);
92      if (type == DW_MACRO_define_strp)
93        debug_macros_sp->AddMacroEntry(
94            DebugMacroEntry::CreateDefineEntry(line, macro_str));
95      else
96        debug_macros_sp->AddMacroEntry(
97            DebugMacroEntry::CreateUndefEntry(line, macro_str));
98      break;
99    case DW_MACRO_start_file:
100      line = debug_macro_data.GetULEB128(offset);
101      debug_line_file_idx = debug_macro_data.GetULEB128(offset);
102      debug_macros_sp->AddMacroEntry(
103          DebugMacroEntry::CreateStartFileEntry(line, debug_line_file_idx));
104      break;
105    case DW_MACRO_end_file:
106      // This operation has no operands.
107      debug_macros_sp->AddMacroEntry(DebugMacroEntry::CreateEndFileEntry());
108      break;
109    case DW_MACRO_import:
110      if (offset_is_64_bit)
111        new_offset = debug_macro_data.GetU64(offset);
112      else
113        new_offset = debug_macro_data.GetU32(offset);
114      debug_macros_sp->AddMacroEntry(DebugMacroEntry::CreateIndirectEntry(
115          sym_file_dwarf->ParseDebugMacros(&new_offset)));
116      break;
117    default:
118      // TODO: Add support for other standard operations.
119      // TODO: Provide mechanism to hook handling of non-standard/extension
120      // operands.
121      return;
122    }
123    type = static_cast<llvm::dwarf::MacroEntryType>(
124        debug_macro_data.GetU8(offset));
125  }
126}
127