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