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