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