xref: /freebsd/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.cpp (revision f5f40dd63bc7acbb5312b26ac1ea1103c12352a6)
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 using namespace lldb_private::plugin::dwarf;
19 
20 DWARFDebugMacroHeader
21 DWARFDebugMacroHeader::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 
45 void 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 
61 void 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