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