1//===--- DWARFVisitor.cpp ---------------------------------------*- C++ -*-===//
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//===----------------------------------------------------------------------===//
10
11#include "DWARFVisitor.h"
12#include "llvm/ObjectYAML/DWARFYAML.h"
13
14using namespace llvm;
15
16template <typename T>
17void DWARFYAML::VisitorImpl<T>::onVariableSizeValue(uint64_t U, unsigned Size) {
18  switch (Size) {
19  case 8:
20    onValue((uint64_t)U);
21    break;
22  case 4:
23    onValue((uint32_t)U);
24    break;
25  case 2:
26    onValue((uint16_t)U);
27    break;
28  case 1:
29    onValue((uint8_t)U);
30    break;
31  default:
32    llvm_unreachable("Invalid integer write size.");
33  }
34}
35
36static unsigned getOffsetSize(const DWARFYAML::Unit &Unit) {
37  return Unit.Length.isDWARF64() ? 8 : 4;
38}
39
40static unsigned getRefSize(const DWARFYAML::Unit &Unit) {
41  if (Unit.Version == 2)
42    return Unit.AddrSize;
43  return getOffsetSize(Unit);
44}
45
46template <typename T> void DWARFYAML::VisitorImpl<T>::traverseDebugInfo() {
47  for (auto &Unit : DebugInfo.CompileUnits) {
48    onStartCompileUnit(Unit);
49    auto FirstAbbrevCode = Unit.Entries[0].AbbrCode;
50
51    for (auto &Entry : Unit.Entries) {
52      onStartDIE(Unit, Entry);
53      if (Entry.AbbrCode == 0u)
54        continue;
55      auto &Abbrev = DebugInfo.AbbrevDecls[Entry.AbbrCode - FirstAbbrevCode];
56      auto FormVal = Entry.Values.begin();
57      auto AbbrForm = Abbrev.Attributes.begin();
58      for (;
59           FormVal != Entry.Values.end() && AbbrForm != Abbrev.Attributes.end();
60           ++FormVal, ++AbbrForm) {
61        onForm(*AbbrForm, *FormVal);
62        dwarf::Form Form = AbbrForm->Form;
63        bool Indirect;
64        do {
65          Indirect = false;
66          switch (Form) {
67          case dwarf::DW_FORM_addr:
68            onVariableSizeValue(FormVal->Value, Unit.AddrSize);
69            break;
70          case dwarf::DW_FORM_ref_addr:
71            onVariableSizeValue(FormVal->Value, getRefSize(Unit));
72            break;
73          case dwarf::DW_FORM_exprloc:
74          case dwarf::DW_FORM_block:
75            onValue((uint64_t)FormVal->BlockData.size(), true);
76            onValue(
77                MemoryBufferRef(StringRef((const char *)&FormVal->BlockData[0],
78                                          FormVal->BlockData.size()),
79                                ""));
80            break;
81          case dwarf::DW_FORM_block1: {
82            auto writeSize = FormVal->BlockData.size();
83            onValue((uint8_t)writeSize);
84            onValue(
85                MemoryBufferRef(StringRef((const char *)&FormVal->BlockData[0],
86                                          FormVal->BlockData.size()),
87                                ""));
88            break;
89          }
90          case dwarf::DW_FORM_block2: {
91            auto writeSize = FormVal->BlockData.size();
92            onValue((uint16_t)writeSize);
93            onValue(
94                MemoryBufferRef(StringRef((const char *)&FormVal->BlockData[0],
95                                          FormVal->BlockData.size()),
96                                ""));
97            break;
98          }
99          case dwarf::DW_FORM_block4: {
100            auto writeSize = FormVal->BlockData.size();
101            onValue((uint32_t)writeSize);
102            onValue(
103                MemoryBufferRef(StringRef((const char *)&FormVal->BlockData[0],
104                                          FormVal->BlockData.size()),
105                                ""));
106            break;
107          }
108          case dwarf::DW_FORM_data1:
109          case dwarf::DW_FORM_ref1:
110          case dwarf::DW_FORM_flag:
111          case dwarf::DW_FORM_strx1:
112          case dwarf::DW_FORM_addrx1:
113            onValue((uint8_t)FormVal->Value);
114            break;
115          case dwarf::DW_FORM_data2:
116          case dwarf::DW_FORM_ref2:
117          case dwarf::DW_FORM_strx2:
118          case dwarf::DW_FORM_addrx2:
119            onValue((uint16_t)FormVal->Value);
120            break;
121          case dwarf::DW_FORM_data4:
122          case dwarf::DW_FORM_ref4:
123          case dwarf::DW_FORM_ref_sup4:
124          case dwarf::DW_FORM_strx4:
125          case dwarf::DW_FORM_addrx4:
126            onValue((uint32_t)FormVal->Value);
127            break;
128          case dwarf::DW_FORM_data8:
129          case dwarf::DW_FORM_ref8:
130          case dwarf::DW_FORM_ref_sup8:
131            onValue((uint64_t)FormVal->Value);
132            break;
133          case dwarf::DW_FORM_sdata:
134            onValue((int64_t)FormVal->Value, true);
135            break;
136          case dwarf::DW_FORM_udata:
137          case dwarf::DW_FORM_ref_udata:
138            onValue((uint64_t)FormVal->Value, true);
139            break;
140          case dwarf::DW_FORM_string:
141            onValue(FormVal->CStr);
142            break;
143          case dwarf::DW_FORM_indirect:
144            onValue((uint64_t)FormVal->Value, true);
145            Indirect = true;
146            Form = static_cast<dwarf::Form>((uint64_t)FormVal->Value);
147            ++FormVal;
148            break;
149          case dwarf::DW_FORM_strp:
150          case dwarf::DW_FORM_sec_offset:
151          case dwarf::DW_FORM_GNU_ref_alt:
152          case dwarf::DW_FORM_GNU_strp_alt:
153          case dwarf::DW_FORM_line_strp:
154          case dwarf::DW_FORM_strp_sup:
155            onVariableSizeValue(FormVal->Value, getOffsetSize(Unit));
156            break;
157          case dwarf::DW_FORM_ref_sig8:
158            onValue((uint64_t)FormVal->Value);
159            break;
160          case dwarf::DW_FORM_GNU_addr_index:
161          case dwarf::DW_FORM_GNU_str_index:
162            onValue((uint64_t)FormVal->Value, true);
163            break;
164          default:
165            break;
166          }
167        } while (Indirect);
168      }
169      onEndDIE(Unit, Entry);
170    }
171    onEndCompileUnit(Unit);
172  }
173}
174
175// Explicitly instantiate the two template expansions.
176template class DWARFYAML::VisitorImpl<DWARFYAML::Data>;
177template class DWARFYAML::VisitorImpl<const DWARFYAML::Data>;
178