LLVM  11.0.0git
DWARFDebugMacro.cpp
Go to the documentation of this file.
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 
13 #include "llvm/Support/WithColor.h"
15 #include <cstdint>
16 
17 using namespace llvm;
18 using namespace dwarf;
19 
20 void DWARFDebugMacro::MacroHeader::dumpMacroHeader(raw_ostream &OS) const {
21  // FIXME: Add support for dumping opcode_operands_table
22  OS << format("macro header: version = 0x%04" PRIx16 ", flags = 0x%02" PRIx8,
23  Version, Flags);
24  if (Flags & MACRO_DEBUG_LINE_OFFSET)
25  OS << format(", debug_line_offset = 0x%04" PRIx64 "\n", DebugLineOffset);
26  else
27  OS << "\n";
28 }
29 
31  unsigned IndLevel = 0;
32  for (const auto &Macros : MacroLists) {
33  OS << format("0x%08" PRIx64 ":\n", Macros.Offset);
34  if (Macros.Header.Version >= 5)
35  Macros.Header.dumpMacroHeader(OS);
36  for (const Entry &E : Macros.Macros) {
37  // There should not be DW_MACINFO_end_file when IndLevel is Zero. However,
38  // this check handles the case of corrupted ".debug_macinfo" section.
39  if (IndLevel > 0)
40  IndLevel -= (E.Type == DW_MACINFO_end_file);
41  // Print indentation.
42  for (unsigned I = 0; I < IndLevel; I++)
43  OS << " ";
44  IndLevel += (E.Type == DW_MACINFO_start_file);
45  // Based on which version we are handling choose appropriate macro forms.
46  if (Macros.Header.Version >= 5)
48  else
50  switch (E.Type) {
51  default:
52  // Got a corrupted ".debug_macinfo/.debug_macro" section (invalid
53  // macinfo type).
54  break;
55  // debug_macro and debug_macinfo share some common encodings.
56  // DW_MACRO_define == DW_MACINFO_define
57  // DW_MACRO_undef == DW_MACINFO_undef
58  // DW_MACRO_start_file == DW_MACINFO_start_file
59  // DW_MACRO_end_file == DW_MACINFO_end_file
60  // For readability/uniformity we are using DW_MACRO_*.
61  case DW_MACRO_define:
62  case DW_MACRO_undef:
63  case DW_MACRO_define_strp:
64  case DW_MACRO_undef_strp:
65  case DW_MACRO_define_strx:
66  case DW_MACRO_undef_strx:
67  OS << " - lineno: " << E.Line;
68  OS << " macro: " << E.MacroStr;
69  break;
70  case DW_MACRO_start_file:
71  OS << " - lineno: " << E.Line;
72  OS << " filenum: " << E.File;
73  break;
74  case DW_MACRO_import:
75  OS << format(" - import offset: 0x%08" PRIx64, E.ImportOffset);
76  break;
77  case DW_MACRO_end_file:
78  break;
80  OS << " - constant: " << E.ExtConstant;
81  OS << " string: " << E.ExtStr;
82  break;
83  }
84  OS << "\n";
85  }
86  }
87 }
88 
89 Error DWARFDebugMacro::parseImpl(
92  bool IsMacro) {
93  uint64_t Offset = 0;
94  MacroList *M = nullptr;
95  using MacroToUnitsMap = DenseMap<uint64_t, DWARFUnit *>;
96  MacroToUnitsMap MacroToUnits;
97  if (IsMacro && Data.isValidOffset(Offset)) {
98  // Keep a mapping from Macro contribution to CUs, this will
99  // be needed while retrieving macro from DW_MACRO_define_strx form.
100  for (const auto &U : Units.getValue())
101  if (auto CUDIE = U->getUnitDIE())
102  // Skip units which does not contibutes to macro section.
103  if (auto MacroOffset = toSectionOffset(CUDIE.find(DW_AT_macros)))
104  MacroToUnits.try_emplace(*MacroOffset, U.get());
105  }
106  while (Data.isValidOffset(Offset)) {
107  if (!M) {
108  MacroLists.emplace_back();
109  M = &MacroLists.back();
110  M->Offset = Offset;
111  if (IsMacro) {
112  auto Err = M->Header.parseMacroHeader(Data, &Offset);
113  if (Err)
114  return Err;
115  }
116  }
117  // A macro list entry consists of:
118  M->Macros.emplace_back();
119  Entry &E = M->Macros.back();
120  // 1. Macinfo type
121  E.Type = Data.getULEB128(&Offset);
122 
123  if (E.Type == 0) {
124  // Reached end of a ".debug_macinfo/debug_macro" section contribution.
125  M = nullptr;
126  continue;
127  }
128 
129  switch (E.Type) {
130  default:
131  // Got a corrupted ".debug_macinfo" section (invalid macinfo type).
132  // Push the corrupted entry to the list and halt parsing.
133  E.Type = DW_MACINFO_invalid;
134  return Error::success();
135  // debug_macro and debug_macinfo share some common encodings.
136  // DW_MACRO_define == DW_MACINFO_define
137  // DW_MACRO_undef == DW_MACINFO_undef
138  // DW_MACRO_start_file == DW_MACINFO_start_file
139  // DW_MACRO_end_file == DW_MACINFO_end_file
140  // For readibility/uniformity we are using DW_MACRO_*.
141  case DW_MACRO_define:
142  case DW_MACRO_undef:
143  // 2. Source line
144  E.Line = Data.getULEB128(&Offset);
145  // 3. Macro string
146  E.MacroStr = Data.getCStr(&Offset);
147  break;
148  case DW_MACRO_define_strp:
149  case DW_MACRO_undef_strp: {
150  if (!IsMacro) {
151  // DW_MACRO_define_strp is a new form introduced in DWARFv5, it is
152  // not supported in debug_macinfo[.dwo] sections. Assume it as an
153  // invalid entry, push it and halt parsing.
154  E.Type = DW_MACINFO_invalid;
155  return Error::success();
156  }
157  uint64_t StrOffset = 0;
158  // 2. Source line
159  E.Line = Data.getULEB128(&Offset);
160  // 3. Macro string
161  // FIXME: Add support for DWARF64
162  StrOffset = Data.getRelocatedValue(/*OffsetSize=*/4, &Offset);
163  assert(StringExtractor && "String Extractor not found");
164  E.MacroStr = StringExtractor->getCStr(&StrOffset);
165  break;
166  }
167  case DW_MACRO_define_strx:
168  case DW_MACRO_undef_strx: {
169  if (!IsMacro) {
170  // DW_MACRO_define_strx is a new form introduced in DWARFv5, it is
171  // not supported in debug_macinfo[.dwo] sections. Assume it as an
172  // invalid entry, push it and halt parsing.
173  E.Type = DW_MACINFO_invalid;
174  return Error::success();
175  }
176  E.Line = Data.getULEB128(&Offset);
177  auto MacroContributionOffset = MacroToUnits.find(M->Offset);
178  if (MacroContributionOffset == MacroToUnits.end())
180  "Macro contribution of the unit not found");
181  Optional<uint64_t> StrOffset =
182  MacroContributionOffset->second->getStringOffsetSectionItem(
183  Data.getULEB128(&Offset));
184  if (!StrOffset)
185  return createStringError(
187  "String offsets contribution of the unit not found");
188  E.MacroStr =
189  MacroContributionOffset->second->getStringExtractor().getCStr(
190  &*StrOffset);
191  break;
192  }
193  case DW_MACRO_start_file:
194  // 2. Source line
195  E.Line = Data.getULEB128(&Offset);
196  // 3. Source file id
197  E.File = Data.getULEB128(&Offset);
198  break;
199  case DW_MACRO_end_file:
200  break;
201  case DW_MACRO_import:
202  // FIXME: Add support for DWARF64
203  E.ImportOffset = Data.getRelocatedValue(/*OffsetSize=*/4, &Offset);
204  break;
206  // 2. Vendor extension constant
207  E.ExtConstant = Data.getULEB128(&Offset);
208  // 3. Vendor extension string
209  E.ExtStr = Data.getCStr(&Offset);
210  break;
211  }
212  }
213  return Error::success();
214 }
215 
216 Error DWARFDebugMacro::MacroHeader::parseMacroHeader(DWARFDataExtractor Data,
217  uint64_t *Offset) {
218  Version = Data.getU16(Offset);
219  uint8_t FlagData = Data.getU8(Offset);
220  // FIXME: Add support for DWARF64
221  if (FlagData & MACRO_OFFSET_SIZE)
222  return createStringError(errc::not_supported, "DWARF64 is not supported");
223 
224  // FIXME: Add support for parsing opcode_operands_table
225  if (FlagData & MACRO_OPCODE_OPERANDS_TABLE)
227  "opcode_operands_table is not supported");
228  Flags = FlagData;
229  if (Flags & MACRO_DEBUG_LINE_OFFSET)
230  DebugLineOffset = Data.getU32(Offset);
231  return Error::success();
232 }
uint8_t getU8(uint64_t *offset_ptr, Error *Err=nullptr) const
Extract a uint8_t value from *offset_ptr.
uint16_t getU16(uint64_t *offset_ptr, Error *Err=nullptr) const
Extract a uint16_t value from *offset_ptr.
This class represents lattice values for constants.
Definition: AllocatorList.h:23
An RAII object that temporarily switches an output stream to a specific color.
Definition: WithColor.h:38
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:124
uint32_t getU32(uint64_t *offset_ptr, Error *Err=nullptr) const
Extract a uint32_t value from *offset_ptr.
const T & getValue() const LLVM_LVALUE_FUNCTION
Definition: Optional.h:255
uint64_t getRelocatedValue(uint32_t Size, uint64_t *Off, uint64_t *SectionIndex=nullptr, Error *Err=nullptr) const
Extracts a value and applies a relocation to the result if one exists for the given offset...
StringRef MacroString(unsigned Encoding)
Definition: Dwarf.cpp:480
raw_ostream & get()
Definition: WithColor.h:65
Optional< uint64_t > toSectionOffset(const Optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract an section offset.
const char * getCStr(uint64_t *OffsetPtr, Error *Err=nullptr) const
Extract a C string from *offset_ptr.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
uint64_t getULEB128(uint64_t *offset_ptr, llvm::Error *Err=nullptr) const
Extract a unsigned LEB128 value from *offset_ptr.
void dump(raw_ostream &OS) const
Print the macro list found within the debug_macinfo/debug_macro section.
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&... Args)
Definition: DenseMap.h:222
A DataExtractor (typically for an in-memory copy of an object-file section) plus a relocation map for...
static ErrorSuccess success()
Create a success value.
Definition: Error.h:332
bool isValidOffset(uint64_t offset) const
Test the validity of offset.
This file contains constants used for implementing Dwarf debug support.
#define I(x, y, z)
Definition: MD5.cpp:59
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:46
StringRef MacinfoString(unsigned Encoding)
Definition: Dwarf.cpp:451
const uint64_t Version
Definition: InstrProf.h:988
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition: Error.h:1202