15ffd83dbSDimitry Andric //===-- DWARFDebugMacro.cpp -----------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric
90b57cec5SDimitry Andric #include "DWARFDebugMacro.h"
100b57cec5SDimitry Andric #include "SymbolFileDWARF.h"
110b57cec5SDimitry Andric
120b57cec5SDimitry Andric #include "lldb/Symbol/DebugMacros.h"
130b57cec5SDimitry Andric
140b57cec5SDimitry Andric #include "DWARFDataExtractor.h"
150b57cec5SDimitry Andric
160b57cec5SDimitry Andric using namespace lldb_private;
1781ad6265SDimitry Andric using namespace lldb_private::dwarf;
18*5f757f3fSDimitry Andric using namespace lldb_private::plugin::dwarf;
190b57cec5SDimitry Andric
200b57cec5SDimitry Andric DWARFDebugMacroHeader
ParseHeader(const DWARFDataExtractor & debug_macro_data,lldb::offset_t * offset)210b57cec5SDimitry Andric DWARFDebugMacroHeader::ParseHeader(const DWARFDataExtractor &debug_macro_data,
220b57cec5SDimitry Andric lldb::offset_t *offset) {
230b57cec5SDimitry Andric DWARFDebugMacroHeader header;
240b57cec5SDimitry Andric
250b57cec5SDimitry Andric // Skip over the version field in header.
260b57cec5SDimitry Andric header.m_version = debug_macro_data.GetU16(offset);
270b57cec5SDimitry Andric
280b57cec5SDimitry Andric uint8_t flags = debug_macro_data.GetU8(offset);
290b57cec5SDimitry Andric header.m_offset_is_64_bit = (flags & OFFSET_SIZE_MASK) != 0;
300b57cec5SDimitry Andric
310b57cec5SDimitry Andric if (flags & DEBUG_LINE_OFFSET_MASK) {
320b57cec5SDimitry Andric if (header.m_offset_is_64_bit)
330b57cec5SDimitry Andric header.m_debug_line_offset = debug_macro_data.GetU64(offset);
340b57cec5SDimitry Andric else
350b57cec5SDimitry Andric header.m_debug_line_offset = debug_macro_data.GetU32(offset);
360b57cec5SDimitry Andric }
370b57cec5SDimitry Andric
380b57cec5SDimitry Andric // Skip over the operands table if it is present.
390b57cec5SDimitry Andric if (flags & OPCODE_OPERANDS_TABLE_MASK)
400b57cec5SDimitry Andric SkipOperandTable(debug_macro_data, offset);
410b57cec5SDimitry Andric
420b57cec5SDimitry Andric return header;
430b57cec5SDimitry Andric }
440b57cec5SDimitry Andric
SkipOperandTable(const DWARFDataExtractor & debug_macro_data,lldb::offset_t * offset)450b57cec5SDimitry Andric void DWARFDebugMacroHeader::SkipOperandTable(
460b57cec5SDimitry Andric const DWARFDataExtractor &debug_macro_data, lldb::offset_t *offset) {
470b57cec5SDimitry Andric uint8_t entry_count = debug_macro_data.GetU8(offset);
480b57cec5SDimitry Andric for (uint8_t i = 0; i < entry_count; i++) {
490b57cec5SDimitry Andric // Skip over the opcode number.
500b57cec5SDimitry Andric debug_macro_data.GetU8(offset);
510b57cec5SDimitry Andric
520b57cec5SDimitry Andric uint64_t operand_count = debug_macro_data.GetULEB128(offset);
530b57cec5SDimitry Andric
540b57cec5SDimitry Andric for (uint64_t j = 0; j < operand_count; j++) {
550b57cec5SDimitry Andric // Skip over the operand form
560b57cec5SDimitry Andric debug_macro_data.GetU8(offset);
570b57cec5SDimitry Andric }
580b57cec5SDimitry Andric }
590b57cec5SDimitry Andric }
600b57cec5SDimitry Andric
ReadMacroEntries(const DWARFDataExtractor & debug_macro_data,const DWARFDataExtractor & debug_str_data,const bool offset_is_64_bit,lldb::offset_t * offset,SymbolFileDWARF * sym_file_dwarf,DebugMacrosSP & debug_macros_sp)610b57cec5SDimitry Andric void DWARFDebugMacroEntry::ReadMacroEntries(
620b57cec5SDimitry Andric const DWARFDataExtractor &debug_macro_data,
630b57cec5SDimitry Andric const DWARFDataExtractor &debug_str_data, const bool offset_is_64_bit,
640b57cec5SDimitry Andric lldb::offset_t *offset, SymbolFileDWARF *sym_file_dwarf,
650b57cec5SDimitry Andric DebugMacrosSP &debug_macros_sp) {
660b57cec5SDimitry Andric llvm::dwarf::MacroEntryType type =
670b57cec5SDimitry Andric static_cast<llvm::dwarf::MacroEntryType>(debug_macro_data.GetU8(offset));
680b57cec5SDimitry Andric while (type != 0) {
690b57cec5SDimitry Andric lldb::offset_t new_offset = 0, str_offset = 0;
700b57cec5SDimitry Andric uint32_t line = 0;
710b57cec5SDimitry Andric const char *macro_str = nullptr;
720b57cec5SDimitry Andric uint32_t debug_line_file_idx = 0;
730b57cec5SDimitry Andric
740b57cec5SDimitry Andric switch (type) {
750b57cec5SDimitry Andric case DW_MACRO_define:
760b57cec5SDimitry Andric case DW_MACRO_undef:
770b57cec5SDimitry Andric line = debug_macro_data.GetULEB128(offset);
780b57cec5SDimitry Andric macro_str = debug_macro_data.GetCStr(offset);
790b57cec5SDimitry Andric if (type == DW_MACRO_define)
800b57cec5SDimitry Andric debug_macros_sp->AddMacroEntry(
810b57cec5SDimitry Andric DebugMacroEntry::CreateDefineEntry(line, macro_str));
820b57cec5SDimitry Andric else
830b57cec5SDimitry Andric debug_macros_sp->AddMacroEntry(
840b57cec5SDimitry Andric DebugMacroEntry::CreateUndefEntry(line, macro_str));
850b57cec5SDimitry Andric break;
860b57cec5SDimitry Andric case DW_MACRO_define_strp:
870b57cec5SDimitry Andric case DW_MACRO_undef_strp:
880b57cec5SDimitry Andric line = debug_macro_data.GetULEB128(offset);
890b57cec5SDimitry Andric if (offset_is_64_bit)
900b57cec5SDimitry Andric str_offset = debug_macro_data.GetU64(offset);
910b57cec5SDimitry Andric else
920b57cec5SDimitry Andric str_offset = debug_macro_data.GetU32(offset);
930b57cec5SDimitry Andric macro_str = debug_str_data.GetCStr(&str_offset);
940b57cec5SDimitry Andric if (type == DW_MACRO_define_strp)
950b57cec5SDimitry Andric debug_macros_sp->AddMacroEntry(
960b57cec5SDimitry Andric DebugMacroEntry::CreateDefineEntry(line, macro_str));
970b57cec5SDimitry Andric else
980b57cec5SDimitry Andric debug_macros_sp->AddMacroEntry(
990b57cec5SDimitry Andric DebugMacroEntry::CreateUndefEntry(line, macro_str));
1000b57cec5SDimitry Andric break;
1010b57cec5SDimitry Andric case DW_MACRO_start_file:
1020b57cec5SDimitry Andric line = debug_macro_data.GetULEB128(offset);
1030b57cec5SDimitry Andric debug_line_file_idx = debug_macro_data.GetULEB128(offset);
1040b57cec5SDimitry Andric debug_macros_sp->AddMacroEntry(
1050b57cec5SDimitry Andric DebugMacroEntry::CreateStartFileEntry(line, debug_line_file_idx));
1060b57cec5SDimitry Andric break;
1070b57cec5SDimitry Andric case DW_MACRO_end_file:
1080b57cec5SDimitry Andric // This operation has no operands.
1090b57cec5SDimitry Andric debug_macros_sp->AddMacroEntry(DebugMacroEntry::CreateEndFileEntry());
1100b57cec5SDimitry Andric break;
1110b57cec5SDimitry Andric case DW_MACRO_import:
1120b57cec5SDimitry Andric if (offset_is_64_bit)
1130b57cec5SDimitry Andric new_offset = debug_macro_data.GetU64(offset);
1140b57cec5SDimitry Andric else
1150b57cec5SDimitry Andric new_offset = debug_macro_data.GetU32(offset);
1160b57cec5SDimitry Andric debug_macros_sp->AddMacroEntry(DebugMacroEntry::CreateIndirectEntry(
1170b57cec5SDimitry Andric sym_file_dwarf->ParseDebugMacros(&new_offset)));
1180b57cec5SDimitry Andric break;
1190b57cec5SDimitry Andric default:
1200b57cec5SDimitry Andric // TODO: Add support for other standard operations.
1210b57cec5SDimitry Andric // TODO: Provide mechanism to hook handling of non-standard/extension
1220b57cec5SDimitry Andric // operands.
1230b57cec5SDimitry Andric return;
1240b57cec5SDimitry Andric }
1250b57cec5SDimitry Andric type = static_cast<llvm::dwarf::MacroEntryType>(
1260b57cec5SDimitry Andric debug_macro_data.GetU8(offset));
1270b57cec5SDimitry Andric }
1280b57cec5SDimitry Andric }
129