xref: /freebsd/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.cpp (revision cfd6422a5217410fbd66f7a7a8a64d9d85e61229)
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 
18 DWARFDebugMacroHeader
19 DWARFDebugMacroHeader::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 
43 void 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 
59 void 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