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 "llvm/DebugInfo/DWARF/DWARFDebugMacro.h"
10 #include "llvm/BinaryFormat/Dwarf.h"
11 #include "llvm/Support/WithColor.h"
12 #include "llvm/Support/raw_ostream.h"
13 #include <cstdint>
14 
15 using namespace llvm;
16 using namespace dwarf;
17 
18 void DWARFDebugMacro::dump(raw_ostream &OS) const {
19   unsigned IndLevel = 0;
20   for (const auto &Macros : MacroLists) {
21     OS << format("0x%08" PRIx64 ":\n", Macros.Offset);
22     for (const Entry &E : Macros.Macros) {
23       // There should not be DW_MACINFO_end_file when IndLevel is Zero. However,
24       // this check handles the case of corrupted ".debug_macinfo" section.
25       if (IndLevel > 0)
26         IndLevel -= (E.Type == DW_MACINFO_end_file);
27       // Print indentation.
28       for (unsigned I = 0; I < IndLevel; I++)
29         OS << "  ";
30       IndLevel += (E.Type == DW_MACINFO_start_file);
31 
32       WithColor(OS, HighlightColor::Macro).get() << MacinfoString(E.Type);
33       switch (E.Type) {
34       default:
35         // Got a corrupted ".debug_macinfo" section (invalid macinfo type).
36         break;
37       case DW_MACINFO_define:
38       case DW_MACINFO_undef:
39         OS << " - lineno: " << E.Line;
40         OS << " macro: " << E.MacroStr;
41         break;
42       case DW_MACINFO_start_file:
43         OS << " - lineno: " << E.Line;
44         OS << " filenum: " << E.File;
45         break;
46       case DW_MACINFO_end_file:
47         break;
48       case DW_MACINFO_vendor_ext:
49         OS << " - constant: " << E.ExtConstant;
50         OS << " string: " << E.ExtStr;
51         break;
52       }
53       OS << "\n";
54     }
55   }
56 }
57 
58 void DWARFDebugMacro::parse(DataExtractor data) {
59   uint64_t Offset = 0;
60   MacroList *M = nullptr;
61   while (data.isValidOffset(Offset)) {
62     if (!M) {
63       MacroLists.emplace_back();
64       M = &MacroLists.back();
65       M->Offset = Offset;
66     }
67     // A macro list entry consists of:
68     M->Macros.emplace_back();
69     Entry &E = M->Macros.back();
70     // 1. Macinfo type
71     E.Type = data.getULEB128(&Offset);
72 
73     if (E.Type == 0) {
74       // Reached end of a ".debug_macinfo" section contribution.
75       M = nullptr;
76       continue;
77     }
78 
79     switch (E.Type) {
80     default:
81       // Got a corrupted ".debug_macinfo" section (invalid macinfo type).
82       // Push the corrupted entry to the list and halt parsing.
83       E.Type = DW_MACINFO_invalid;
84       return;
85     case DW_MACINFO_define:
86     case DW_MACINFO_undef:
87       // 2. Source line
88       E.Line = data.getULEB128(&Offset);
89       // 3. Macro string
90       E.MacroStr = data.getCStr(&Offset);
91       break;
92     case DW_MACINFO_start_file:
93       // 2. Source line
94       E.Line = data.getULEB128(&Offset);
95       // 3. Source file id
96       E.File = data.getULEB128(&Offset);
97       break;
98     case DW_MACINFO_end_file:
99       break;
100     case DW_MACINFO_vendor_ext:
101       // 2. Vendor extension constant
102       E.ExtConstant = data.getULEB128(&Offset);
103       // 3. Vendor extension string
104       E.ExtStr = data.getCStr(&Offset);
105       break;
106     }
107   }
108 }
109