Mercurial > hg > CbC > CbC_llvm
comparison lib/DebugInfo/DWARF/DWARFDie.cpp @ 147:c2174574ed3a
LLVM 10
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Wed, 14 Aug 2019 16:55:33 +0900 |
parents | 3a76565eade5 |
children |
comparison
equal
deleted
inserted
replaced
134:3a76565eade5 | 147:c2174574ed3a |
---|---|
1 //===- DWARFDie.cpp -------------------------------------------------------===// | 1 //===- DWARFDie.cpp -------------------------------------------------------===// |
2 // | 2 // |
3 // The LLVM Compiler Infrastructure | 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 // | 4 // See https://llvm.org/LICENSE.txt for license information. |
5 // This file is distributed under the University of Illinois Open Source | 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 // License. See LICENSE.TXT for details. | |
7 // | 6 // |
8 //===----------------------------------------------------------------------===// | 7 //===----------------------------------------------------------------------===// |
9 | 8 |
10 #include "llvm/DebugInfo/DWARF/DWARFDie.h" | 9 #include "llvm/DebugInfo/DWARF/DWARFDie.h" |
11 #include "SyntaxHighlighting.h" | |
12 #include "llvm/ADT/None.h" | 10 #include "llvm/ADT/None.h" |
13 #include "llvm/ADT/Optional.h" | 11 #include "llvm/ADT/Optional.h" |
12 #include "llvm/ADT/SmallSet.h" | |
14 #include "llvm/ADT/StringRef.h" | 13 #include "llvm/ADT/StringRef.h" |
15 #include "llvm/BinaryFormat/Dwarf.h" | 14 #include "llvm/BinaryFormat/Dwarf.h" |
16 #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" | 15 #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" |
17 #include "llvm/DebugInfo/DWARF/DWARFContext.h" | 16 #include "llvm/DebugInfo/DWARF/DWARFContext.h" |
18 #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" | 17 #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" |
20 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" | 19 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" |
21 #include "llvm/DebugInfo/DWARF/DWARFUnit.h" | 20 #include "llvm/DebugInfo/DWARF/DWARFUnit.h" |
22 #include "llvm/Object/ObjectFile.h" | 21 #include "llvm/Object/ObjectFile.h" |
23 #include "llvm/Support/DataExtractor.h" | 22 #include "llvm/Support/DataExtractor.h" |
24 #include "llvm/Support/Format.h" | 23 #include "llvm/Support/Format.h" |
24 #include "llvm/Support/FormatVariadic.h" | |
25 #include "llvm/Support/MathExtras.h" | 25 #include "llvm/Support/MathExtras.h" |
26 #include "llvm/Support/WithColor.h" | |
26 #include "llvm/Support/raw_ostream.h" | 27 #include "llvm/Support/raw_ostream.h" |
27 #include <algorithm> | 28 #include <algorithm> |
28 #include <cassert> | 29 #include <cassert> |
29 #include <cinttypes> | 30 #include <cinttypes> |
30 #include <cstdint> | 31 #include <cstdint> |
32 #include <utility> | 33 #include <utility> |
33 | 34 |
34 using namespace llvm; | 35 using namespace llvm; |
35 using namespace dwarf; | 36 using namespace dwarf; |
36 using namespace object; | 37 using namespace object; |
37 using namespace syntax; | |
38 | 38 |
39 static void dumpApplePropertyAttribute(raw_ostream &OS, uint64_t Val) { | 39 static void dumpApplePropertyAttribute(raw_ostream &OS, uint64_t Val) { |
40 OS << " ("; | 40 OS << " ("; |
41 do { | 41 do { |
42 uint64_t Shift = countTrailingZeros(Val); | 42 uint64_t Shift = countTrailingZeros(Val); |
56 | 56 |
57 static void dumpRanges(const DWARFObject &Obj, raw_ostream &OS, | 57 static void dumpRanges(const DWARFObject &Obj, raw_ostream &OS, |
58 const DWARFAddressRangesVector &Ranges, | 58 const DWARFAddressRangesVector &Ranges, |
59 unsigned AddressSize, unsigned Indent, | 59 unsigned AddressSize, unsigned Indent, |
60 const DIDumpOptions &DumpOpts) { | 60 const DIDumpOptions &DumpOpts) { |
61 if (!DumpOpts.ShowAddresses) | |
62 return; | |
63 | |
61 ArrayRef<SectionName> SectionNames; | 64 ArrayRef<SectionName> SectionNames; |
62 if (DumpOpts.Verbose) | 65 if (DumpOpts.Verbose) |
63 SectionNames = Obj.getSectionNames(); | 66 SectionNames = Obj.getSectionNames(); |
64 | 67 |
65 for (const DWARFAddressRange &R : Ranges) { | 68 for (const DWARFAddressRange &R : Ranges) { |
66 | |
67 OS << '\n'; | 69 OS << '\n'; |
68 OS.indent(Indent); | 70 OS.indent(Indent); |
69 R.dump(OS, AddressSize); | 71 R.dump(OS, AddressSize); |
70 | 72 |
71 if (SectionNames.empty() || R.SectionIndex == -1ULL) | 73 DWARFFormValue::dumpAddressSection(Obj, OS, DumpOpts, R.SectionIndex); |
72 continue; | |
73 | |
74 StringRef Name = SectionNames[R.SectionIndex].Name; | |
75 OS << " \"" << Name << '\"'; | |
76 | |
77 // Print section index if name is not unique. | |
78 if (!SectionNames[R.SectionIndex].IsNameUnique) | |
79 OS << format(" [%" PRIu64 "]", R.SectionIndex); | |
80 } | 74 } |
81 } | 75 } |
82 | 76 |
83 static void dumpLocation(raw_ostream &OS, DWARFFormValue &FormValue, | 77 static void dumpLocation(raw_ostream &OS, DWARFFormValue &FormValue, |
84 DWARFUnit *U, unsigned Indent, | 78 DWARFUnit *U, unsigned Indent, |
90 FormValue.isFormClass(DWARFFormValue::FC_Exprloc)) { | 84 FormValue.isFormClass(DWARFFormValue::FC_Exprloc)) { |
91 ArrayRef<uint8_t> Expr = *FormValue.getAsBlock(); | 85 ArrayRef<uint8_t> Expr = *FormValue.getAsBlock(); |
92 DataExtractor Data(StringRef((const char *)Expr.data(), Expr.size()), | 86 DataExtractor Data(StringRef((const char *)Expr.data(), Expr.size()), |
93 Ctx.isLittleEndian(), 0); | 87 Ctx.isLittleEndian(), 0); |
94 DWARFExpression(Data, U->getVersion(), U->getAddressByteSize()) | 88 DWARFExpression(Data, U->getVersion(), U->getAddressByteSize()) |
95 .print(OS, MRI); | 89 .print(OS, MRI, U); |
96 return; | 90 return; |
97 } | 91 } |
98 | 92 |
99 FormValue.dump(OS, DumpOpts); | 93 FormValue.dump(OS, DumpOpts); |
100 if (FormValue.isFormClass(DWARFFormValue::FC_SectionOffset)) { | 94 if (FormValue.isFormClass(DWARFFormValue::FC_SectionOffset)) { |
101 const DWARFSection &LocSection = Obj.getLocSection(); | 95 uint64_t Offset = *FormValue.getAsSectionOffset(); |
102 const DWARFSection &LocDWOSection = Obj.getLocDWOSection(); | 96 if (!U->isDWOUnit() && !U->getLocSection()->Data.empty()) { |
103 uint32_t Offset = *FormValue.getAsSectionOffset(); | |
104 | |
105 if (!LocSection.Data.empty()) { | |
106 DWARFDebugLoc DebugLoc; | 97 DWARFDebugLoc DebugLoc; |
107 DWARFDataExtractor Data(Obj, LocSection, Ctx.isLittleEndian(), | 98 DWARFDataExtractor Data(Obj, *U->getLocSection(), Ctx.isLittleEndian(), |
108 Obj.getAddressSize()); | 99 Obj.getAddressSize()); |
109 auto LL = DebugLoc.parseOneLocationList(Data, &Offset); | 100 auto LL = DebugLoc.parseOneLocationList(Data, &Offset); |
101 if (LL) { | |
102 uint64_t BaseAddr = 0; | |
103 if (Optional<object::SectionedAddress> BA = U->getBaseAddress()) | |
104 BaseAddr = BA->Address; | |
105 LL->dump(OS, Ctx.isLittleEndian(), Obj.getAddressSize(), MRI, U, | |
106 BaseAddr, Indent); | |
107 } else | |
108 OS << "error extracting location list."; | |
109 return; | |
110 } | |
111 | |
112 bool UseLocLists = !U->isDWOUnit(); | |
113 StringRef LoclistsSectionData = | |
114 UseLocLists ? Obj.getLoclistsSection().Data : U->getLocSectionData(); | |
115 | |
116 if (!LoclistsSectionData.empty()) { | |
117 DataExtractor Data(LoclistsSectionData, Ctx.isLittleEndian(), | |
118 Obj.getAddressSize()); | |
119 | |
120 // Old-style location list were used in DWARF v4 (.debug_loc.dwo section). | |
121 // Modern locations list (.debug_loclists) are used starting from v5. | |
122 // Ideally we should take the version from the .debug_loclists section | |
123 // header, but using CU's version for simplicity. | |
124 auto LL = DWARFDebugLoclists::parseOneLocationList( | |
125 Data, &Offset, UseLocLists ? U->getVersion() : 4); | |
126 | |
127 uint64_t BaseAddr = 0; | |
128 if (Optional<object::SectionedAddress> BA = U->getBaseAddress()) | |
129 BaseAddr = BA->Address; | |
130 | |
110 if (LL) | 131 if (LL) |
111 LL->dump(OS, Ctx.isLittleEndian(), Obj.getAddressSize(), MRI, Indent); | 132 LL->dump(OS, BaseAddr, Ctx.isLittleEndian(), Obj.getAddressSize(), MRI, |
112 else | 133 U, Indent); |
113 OS << "error extracting location list."; | |
114 } else if (!LocDWOSection.Data.empty()) { | |
115 DataExtractor Data(LocDWOSection.Data, Ctx.isLittleEndian(), 0); | |
116 auto LL = DWARFDebugLocDWO::parseOneLocationList(Data, &Offset); | |
117 if (LL) | |
118 LL->dump(OS, Ctx.isLittleEndian(), Obj.getAddressSize(), MRI, Indent); | |
119 else | 134 else |
120 OS << "error extracting location list."; | 135 OS << "error extracting location list."; |
121 } | 136 } |
122 } | 137 } |
123 } | 138 } |
128 if (!TagStr.startswith("DW_TAG_") || !TagStr.endswith("_type")) | 143 if (!TagStr.startswith("DW_TAG_") || !TagStr.endswith("_type")) |
129 return; | 144 return; |
130 OS << TagStr.substr(7, TagStr.size() - 12) << " "; | 145 OS << TagStr.substr(7, TagStr.size() - 12) << " "; |
131 } | 146 } |
132 | 147 |
148 static void dumpArrayType(raw_ostream &OS, const DWARFDie &D) { | |
149 Optional<uint64_t> Bound; | |
150 for (const DWARFDie &C : D.children()) | |
151 if (C.getTag() == DW_TAG_subrange_type) { | |
152 Optional<uint64_t> LB; | |
153 Optional<uint64_t> Count; | |
154 Optional<uint64_t> UB; | |
155 Optional<unsigned> DefaultLB; | |
156 if (Optional<DWARFFormValue> L = C.find(DW_AT_lower_bound)) | |
157 LB = L->getAsUnsignedConstant(); | |
158 if (Optional<DWARFFormValue> CountV = C.find(DW_AT_count)) | |
159 Count = CountV->getAsUnsignedConstant(); | |
160 if (Optional<DWARFFormValue> UpperV = C.find(DW_AT_upper_bound)) | |
161 UB = UpperV->getAsUnsignedConstant(); | |
162 if (Optional<DWARFFormValue> LV = | |
163 D.getDwarfUnit()->getUnitDIE().find(DW_AT_language)) | |
164 if (Optional<uint64_t> LC = LV->getAsUnsignedConstant()) | |
165 if ((DefaultLB = | |
166 LanguageLowerBound(static_cast<dwarf::SourceLanguage>(*LC)))) | |
167 if (LB && *LB == *DefaultLB) | |
168 LB = None; | |
169 if (!LB && !Count && !UB) | |
170 OS << "[]"; | |
171 else if (!LB && (Count || UB) && DefaultLB) | |
172 OS << '[' << (Count ? *Count : *UB - *DefaultLB + 1) << ']'; | |
173 else { | |
174 OS << "[["; | |
175 if (LB) | |
176 OS << *LB; | |
177 else | |
178 OS << '?'; | |
179 OS << ", "; | |
180 if (Count) | |
181 if (LB) | |
182 OS << *LB + *Count; | |
183 else | |
184 OS << "? + " << *Count; | |
185 else if (UB) | |
186 OS << *UB + 1; | |
187 else | |
188 OS << '?'; | |
189 OS << ")]"; | |
190 } | |
191 } | |
192 } | |
193 | |
133 /// Recursively dump the DIE type name when applicable. | 194 /// Recursively dump the DIE type name when applicable. |
134 static void dumpTypeName(raw_ostream &OS, const DWARFDie &Die) { | 195 static void dumpTypeName(raw_ostream &OS, const DWARFDie &D) { |
135 DWARFDie D = Die.getAttributeValueAsReferencedDie(DW_AT_type); | |
136 | |
137 if (!D.isValid()) | 196 if (!D.isValid()) |
138 return; | 197 return; |
139 | 198 |
140 if (const char *Name = D.getName(DINameKind::LinkageName)) { | 199 if (const char *Name = D.getName(DINameKind::LinkageName)) { |
141 OS << Name; | 200 OS << Name; |
149 case DW_TAG_array_type: | 208 case DW_TAG_array_type: |
150 case DW_TAG_pointer_type: | 209 case DW_TAG_pointer_type: |
151 case DW_TAG_ptr_to_member_type: | 210 case DW_TAG_ptr_to_member_type: |
152 case DW_TAG_reference_type: | 211 case DW_TAG_reference_type: |
153 case DW_TAG_rvalue_reference_type: | 212 case DW_TAG_rvalue_reference_type: |
213 case DW_TAG_subroutine_type: | |
154 break; | 214 break; |
155 default: | 215 default: |
156 dumpTypeTagName(OS, T); | 216 dumpTypeTagName(OS, T); |
157 } | 217 } |
158 | 218 |
159 // Follow the DW_AT_type if possible. | 219 // Follow the DW_AT_type if possible. |
160 dumpTypeName(OS, D); | 220 DWARFDie TypeDie = D.getAttributeValueAsReferencedDie(DW_AT_type); |
221 dumpTypeName(OS, TypeDie); | |
161 | 222 |
162 switch (T) { | 223 switch (T) { |
163 case DW_TAG_array_type: | 224 case DW_TAG_subroutine_type: { |
164 OS << "[]"; | 225 if (!TypeDie) |
226 OS << "void"; | |
227 OS << '('; | |
228 bool First = true; | |
229 for (const DWARFDie &C : D.children()) { | |
230 if (C.getTag() == DW_TAG_formal_parameter) { | |
231 if (!First) | |
232 OS << ", "; | |
233 First = false; | |
234 dumpTypeName(OS, C.getAttributeValueAsReferencedDie(DW_AT_type)); | |
235 } | |
236 } | |
237 OS << ')'; | |
165 break; | 238 break; |
239 } | |
240 case DW_TAG_array_type: { | |
241 dumpArrayType(OS, D); | |
242 break; | |
243 } | |
166 case DW_TAG_pointer_type: | 244 case DW_TAG_pointer_type: |
167 OS << '*'; | 245 OS << '*'; |
168 break; | 246 break; |
169 case DW_TAG_ptr_to_member_type: | 247 case DW_TAG_ptr_to_member_type: |
248 if (DWARFDie Cont = | |
249 D.getAttributeValueAsReferencedDie(DW_AT_containing_type)) { | |
250 dumpTypeName(OS << ' ', Cont); | |
251 OS << "::"; | |
252 } | |
170 OS << '*'; | 253 OS << '*'; |
171 break; | 254 break; |
172 case DW_TAG_reference_type: | 255 case DW_TAG_reference_type: |
173 OS << '&'; | 256 OS << '&'; |
174 break; | 257 break; |
179 break; | 262 break; |
180 } | 263 } |
181 } | 264 } |
182 | 265 |
183 static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die, | 266 static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die, |
184 uint32_t *OffsetPtr, dwarf::Attribute Attr, | 267 uint64_t *OffsetPtr, dwarf::Attribute Attr, |
185 dwarf::Form Form, unsigned Indent, | 268 dwarf::Form Form, unsigned Indent, |
186 DIDumpOptions DumpOpts) { | 269 DIDumpOptions DumpOpts) { |
187 if (!Die.isValid()) | 270 if (!Die.isValid()) |
188 return; | 271 return; |
189 const char BaseIndent[] = " "; | 272 const char BaseIndent[] = " "; |
190 OS << BaseIndent; | 273 OS << BaseIndent; |
191 OS.indent(Indent + 2); | 274 OS.indent(Indent + 2); |
192 auto attrString = AttributeString(Attr); | 275 WithColor(OS, HighlightColor::Attribute) << formatv("{0}", Attr); |
193 if (!attrString.empty()) | 276 |
194 WithColor(OS, syntax::Attribute) << attrString; | 277 if (DumpOpts.Verbose || DumpOpts.ShowForm) |
195 else | 278 OS << formatv(" [{0}]", Form); |
196 WithColor(OS, syntax::Attribute).get() << format("DW_AT_Unknown_%x", Attr); | |
197 | |
198 if (DumpOpts.Verbose || DumpOpts.ShowForm) { | |
199 auto formString = FormEncodingString(Form); | |
200 if (!formString.empty()) | |
201 OS << " [" << formString << ']'; | |
202 else | |
203 OS << format(" [DW_FORM_Unknown_%x]", Form); | |
204 } | |
205 | 279 |
206 DWARFUnit *U = Die.getDwarfUnit(); | 280 DWARFUnit *U = Die.getDwarfUnit(); |
207 DWARFFormValue formValue(Form); | 281 DWARFFormValue FormValue = DWARFFormValue::createFromUnit(Form, U, OffsetPtr); |
208 | |
209 if (!formValue.extractValue(U->getDebugInfoExtractor(), OffsetPtr, | |
210 U->getFormParams(), U)) | |
211 return; | |
212 | 282 |
213 OS << "\t("; | 283 OS << "\t("; |
214 | 284 |
215 StringRef Name; | 285 StringRef Name; |
216 std::string File; | 286 std::string File; |
217 auto Color = syntax::Enumerator; | 287 auto Color = HighlightColor::Enumerator; |
218 if (Attr == DW_AT_decl_file || Attr == DW_AT_call_file) { | 288 if (Attr == DW_AT_decl_file || Attr == DW_AT_call_file) { |
219 Color = syntax::String; | 289 Color = HighlightColor::String; |
220 if (const auto *LT = U->getContext().getLineTableForUnit(U)) | 290 if (const auto *LT = U->getContext().getLineTableForUnit(U)) |
221 if (LT->getFileNameByIndex( | 291 if (LT->getFileNameByIndex( |
222 formValue.getAsUnsignedConstant().getValue(), | 292 FormValue.getAsUnsignedConstant().getValue(), |
223 U->getCompilationDir(), | 293 U->getCompilationDir(), |
224 DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, File)) { | 294 DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, File)) { |
225 File = '"' + File + '"'; | 295 File = '"' + File + '"'; |
226 Name = File; | 296 Name = File; |
227 } | 297 } |
228 } else if (Optional<uint64_t> Val = formValue.getAsUnsignedConstant()) | 298 } else if (Optional<uint64_t> Val = FormValue.getAsUnsignedConstant()) |
229 Name = AttributeValueString(Attr, *Val); | 299 Name = AttributeValueString(Attr, *Val); |
230 | 300 |
231 if (!Name.empty()) | 301 if (!Name.empty()) |
232 WithColor(OS, Color) << Name; | 302 WithColor(OS, Color) << Name; |
233 else if (Attr == DW_AT_decl_line || Attr == DW_AT_call_line) | 303 else if (Attr == DW_AT_decl_line || Attr == DW_AT_call_line) |
234 OS << *formValue.getAsUnsignedConstant(); | 304 OS << *FormValue.getAsUnsignedConstant(); |
235 else if (Attr == DW_AT_high_pc && !DumpOpts.ShowForm && !DumpOpts.Verbose && | 305 else if (Attr == DW_AT_high_pc && !DumpOpts.ShowForm && !DumpOpts.Verbose && |
236 formValue.getAsUnsignedConstant()) { | 306 FormValue.getAsUnsignedConstant()) { |
237 if (DumpOpts.ShowAddresses) { | 307 if (DumpOpts.ShowAddresses) { |
238 // Print the actual address rather than the offset. | 308 // Print the actual address rather than the offset. |
239 uint64_t LowPC, HighPC, Index; | 309 uint64_t LowPC, HighPC, Index; |
240 if (Die.getLowAndHighPC(LowPC, HighPC, Index)) | 310 if (Die.getLowAndHighPC(LowPC, HighPC, Index)) |
241 OS << format("0x%016" PRIx64, HighPC); | 311 OS << format("0x%016" PRIx64, HighPC); |
242 else | 312 else |
243 formValue.dump(OS, DumpOpts); | 313 FormValue.dump(OS, DumpOpts); |
244 } | 314 } |
245 } else if (Attr == DW_AT_location || Attr == DW_AT_frame_base || | 315 } else if (DWARFAttribute::mayHaveLocationDescription(Attr)) |
246 Attr == DW_AT_data_member_location || | 316 dumpLocation(OS, FormValue, U, sizeof(BaseIndent) + Indent + 4, DumpOpts); |
247 Attr == DW_AT_GNU_call_site_value) | |
248 dumpLocation(OS, formValue, U, sizeof(BaseIndent) + Indent + 4, DumpOpts); | |
249 else | 317 else |
250 formValue.dump(OS, DumpOpts); | 318 FormValue.dump(OS, DumpOpts); |
319 | |
320 std::string Space = DumpOpts.ShowAddresses ? " " : ""; | |
251 | 321 |
252 // We have dumped the attribute raw value. For some attributes | 322 // We have dumped the attribute raw value. For some attributes |
253 // having both the raw value and the pretty-printed value is | 323 // having both the raw value and the pretty-printed value is |
254 // interesting. These attributes are handled below. | 324 // interesting. These attributes are handled below. |
255 if (Attr == DW_AT_specification || Attr == DW_AT_abstract_origin) { | 325 if (Attr == DW_AT_specification || Attr == DW_AT_abstract_origin) { |
256 if (const char *Name = Die.getAttributeValueAsReferencedDie(Attr).getName( | 326 if (const char *Name = |
257 DINameKind::LinkageName)) | 327 Die.getAttributeValueAsReferencedDie(FormValue).getName( |
258 OS << " \"" << Name << '\"'; | 328 DINameKind::LinkageName)) |
329 OS << Space << "\"" << Name << '\"'; | |
259 } else if (Attr == DW_AT_type) { | 330 } else if (Attr == DW_AT_type) { |
260 OS << " \""; | 331 OS << Space << "\""; |
261 dumpTypeName(OS, Die); | 332 dumpTypeName(OS, Die.getAttributeValueAsReferencedDie(FormValue)); |
262 OS << '"'; | 333 OS << '"'; |
263 } else if (Attr == DW_AT_APPLE_property_attribute) { | 334 } else if (Attr == DW_AT_APPLE_property_attribute) { |
264 if (Optional<uint64_t> OptVal = formValue.getAsUnsignedConstant()) | 335 if (Optional<uint64_t> OptVal = FormValue.getAsUnsignedConstant()) |
265 dumpApplePropertyAttribute(OS, *OptVal); | 336 dumpApplePropertyAttribute(OS, *OptVal); |
266 } else if (Attr == DW_AT_ranges) { | 337 } else if (Attr == DW_AT_ranges) { |
267 const DWARFObject &Obj = Die.getDwarfUnit()->getContext().getDWARFObj(); | 338 const DWARFObject &Obj = Die.getDwarfUnit()->getContext().getDWARFObj(); |
268 dumpRanges(Obj, OS, Die.getAddressRanges(), U->getAddressByteSize(), | 339 // For DW_FORM_rnglistx we need to dump the offset separately, since |
269 sizeof(BaseIndent) + Indent + 4, DumpOpts); | 340 // we have only dumped the index so far. |
341 if (FormValue.getForm() == DW_FORM_rnglistx) | |
342 if (auto RangeListOffset = | |
343 U->getRnglistOffset(*FormValue.getAsSectionOffset())) { | |
344 DWARFFormValue FV = DWARFFormValue::createFromUValue( | |
345 dwarf::DW_FORM_sec_offset, *RangeListOffset); | |
346 FV.dump(OS, DumpOpts); | |
347 } | |
348 if (auto RangesOrError = Die.getAddressRanges()) | |
349 dumpRanges(Obj, OS, RangesOrError.get(), U->getAddressByteSize(), | |
350 sizeof(BaseIndent) + Indent + 4, DumpOpts); | |
351 else | |
352 WithColor::error() << "decoding address ranges: " | |
353 << toString(RangesOrError.takeError()) << '\n'; | |
270 } | 354 } |
271 | 355 |
272 OS << ")\n"; | 356 OS << ")\n"; |
273 } | 357 } |
274 | 358 |
302 return None; | 386 return None; |
303 } | 387 } |
304 | 388 |
305 Optional<DWARFFormValue> | 389 Optional<DWARFFormValue> |
306 DWARFDie::findRecursively(ArrayRef<dwarf::Attribute> Attrs) const { | 390 DWARFDie::findRecursively(ArrayRef<dwarf::Attribute> Attrs) const { |
307 if (!isValid()) | 391 std::vector<DWARFDie> Worklist; |
308 return None; | 392 Worklist.push_back(*this); |
309 if (auto Value = find(Attrs)) | 393 |
310 return Value; | 394 // Keep track if DIEs already seen to prevent infinite recursion. |
311 if (auto Die = getAttributeValueAsReferencedDie(DW_AT_abstract_origin)) { | 395 // Empirically we rarely see a depth of more than 3 when dealing with valid |
312 if (auto Value = Die.findRecursively(Attrs)) | 396 // DWARF. This corresponds to following the DW_AT_abstract_origin and |
397 // DW_AT_specification just once. | |
398 SmallSet<DWARFDie, 3> Seen; | |
399 Seen.insert(*this); | |
400 | |
401 while (!Worklist.empty()) { | |
402 DWARFDie Die = Worklist.back(); | |
403 Worklist.pop_back(); | |
404 | |
405 if (!Die.isValid()) | |
406 continue; | |
407 | |
408 if (auto Value = Die.find(Attrs)) | |
313 return Value; | 409 return Value; |
314 } | 410 |
315 if (auto Die = getAttributeValueAsReferencedDie(DW_AT_specification)) { | 411 if (auto D = Die.getAttributeValueAsReferencedDie(DW_AT_abstract_origin)) |
316 if (auto Value = Die.findRecursively(Attrs)) | 412 if (Seen.insert(D).second) |
317 return Value; | 413 Worklist.push_back(D); |
318 } | 414 |
415 if (auto D = Die.getAttributeValueAsReferencedDie(DW_AT_specification)) | |
416 if (Seen.insert(D).second) | |
417 Worklist.push_back(D); | |
418 } | |
419 | |
319 return None; | 420 return None; |
320 } | 421 } |
321 | 422 |
322 DWARFDie | 423 DWARFDie |
323 DWARFDie::getAttributeValueAsReferencedDie(dwarf::Attribute Attr) const { | 424 DWARFDie::getAttributeValueAsReferencedDie(dwarf::Attribute Attr) const { |
324 if (auto SpecRef = toReference(find(Attr))) { | 425 if (Optional<DWARFFormValue> F = find(Attr)) |
325 if (auto SpecUnit = U->getUnitSection().getUnitForOffset(*SpecRef)) | 426 return getAttributeValueAsReferencedDie(*F); |
326 return SpecUnit->getDIEForOffset(*SpecRef); | 427 return DWARFDie(); |
428 } | |
429 | |
430 DWARFDie | |
431 DWARFDie::getAttributeValueAsReferencedDie(const DWARFFormValue &V) const { | |
432 if (auto SpecRef = V.getAsRelativeReference()) { | |
433 if (SpecRef->Unit) | |
434 return SpecRef->Unit->getDIEForOffset(SpecRef->Unit->getOffset() + SpecRef->Offset); | |
435 if (auto SpecUnit = U->getUnitVector().getUnitForOffset(SpecRef->Offset)) | |
436 return SpecUnit->getDIEForOffset(SpecRef->Offset); | |
327 } | 437 } |
328 return DWARFDie(); | 438 return DWARFDie(); |
329 } | 439 } |
330 | 440 |
331 Optional<uint64_t> DWARFDie::getRangesBaseAttribute() const { | 441 Optional<uint64_t> DWARFDie::getRangesBaseAttribute() const { |
347 } | 457 } |
348 | 458 |
349 bool DWARFDie::getLowAndHighPC(uint64_t &LowPC, uint64_t &HighPC, | 459 bool DWARFDie::getLowAndHighPC(uint64_t &LowPC, uint64_t &HighPC, |
350 uint64_t &SectionIndex) const { | 460 uint64_t &SectionIndex) const { |
351 auto F = find(DW_AT_low_pc); | 461 auto F = find(DW_AT_low_pc); |
352 auto LowPcAddr = toAddress(F); | 462 auto LowPcAddr = toSectionedAddress(F); |
353 if (!LowPcAddr) | 463 if (!LowPcAddr) |
354 return false; | 464 return false; |
355 if (auto HighPcAddr = getHighPC(*LowPcAddr)) { | 465 if (auto HighPcAddr = getHighPC(LowPcAddr->Address)) { |
356 LowPC = *LowPcAddr; | 466 LowPC = LowPcAddr->Address; |
357 HighPC = *HighPcAddr; | 467 HighPC = *HighPcAddr; |
358 SectionIndex = F->getSectionIndex(); | 468 SectionIndex = LowPcAddr->SectionIndex; |
359 return true; | 469 return true; |
360 } | 470 } |
361 return false; | 471 return false; |
362 } | 472 } |
363 | 473 |
364 DWARFAddressRangesVector DWARFDie::getAddressRanges() const { | 474 Expected<DWARFAddressRangesVector> DWARFDie::getAddressRanges() const { |
365 if (isNULL()) | 475 if (isNULL()) |
366 return DWARFAddressRangesVector(); | 476 return DWARFAddressRangesVector(); |
367 // Single range specified by low/high PC. | 477 // Single range specified by low/high PC. |
368 uint64_t LowPC, HighPC, Index; | 478 uint64_t LowPC, HighPC, Index; |
369 if (getLowAndHighPC(LowPC, HighPC, Index)) | 479 if (getLowAndHighPC(LowPC, HighPC, Index)) |
370 return {{LowPC, HighPC, Index}}; | 480 return DWARFAddressRangesVector{{LowPC, HighPC, Index}}; |
371 | 481 |
372 // Multiple ranges from .debug_ranges section. | 482 Optional<DWARFFormValue> Value = find(DW_AT_ranges); |
373 auto RangesOffset = toSectionOffset(find(DW_AT_ranges)); | 483 if (Value) { |
374 if (RangesOffset) { | 484 if (Value->getForm() == DW_FORM_rnglistx) |
375 DWARFDebugRangeList RangeList; | 485 return U->findRnglistFromIndex(*Value->getAsSectionOffset()); |
376 if (U->extractRangeList(*RangesOffset, RangeList)) | 486 return U->findRnglistFromOffset(*Value->getAsSectionOffset()); |
377 return RangeList.getAbsoluteRanges(U->getBaseAddress()); | |
378 } | 487 } |
379 return DWARFAddressRangesVector(); | 488 return DWARFAddressRangesVector(); |
380 } | 489 } |
381 | 490 |
382 void DWARFDie::collectChildrenAddressRanges( | 491 void DWARFDie::collectChildrenAddressRanges( |
383 DWARFAddressRangesVector &Ranges) const { | 492 DWARFAddressRangesVector &Ranges) const { |
384 if (isNULL()) | 493 if (isNULL()) |
385 return; | 494 return; |
386 if (isSubprogramDIE()) { | 495 if (isSubprogramDIE()) { |
387 const auto &DIERanges = getAddressRanges(); | 496 if (auto DIERangesOrError = getAddressRanges()) |
388 Ranges.insert(Ranges.end(), DIERanges.begin(), DIERanges.end()); | 497 Ranges.insert(Ranges.end(), DIERangesOrError.get().begin(), |
498 DIERangesOrError.get().end()); | |
499 else | |
500 llvm::consumeError(DIERangesOrError.takeError()); | |
389 } | 501 } |
390 | 502 |
391 for (auto Child : children()) | 503 for (auto Child : children()) |
392 Child.collectChildrenAddressRanges(Ranges); | 504 Child.collectChildrenAddressRanges(Ranges); |
393 } | 505 } |
394 | 506 |
395 bool DWARFDie::addressRangeContainsAddress(const uint64_t Address) const { | 507 bool DWARFDie::addressRangeContainsAddress(const uint64_t Address) const { |
396 for (const auto &R : getAddressRanges()) { | 508 auto RangesOrError = getAddressRanges(); |
509 if (!RangesOrError) { | |
510 llvm::consumeError(RangesOrError.takeError()); | |
511 return false; | |
512 } | |
513 | |
514 for (const auto &R : RangesOrError.get()) | |
397 if (R.LowPC <= Address && Address < R.HighPC) | 515 if (R.LowPC <= Address && Address < R.HighPC) |
398 return true; | 516 return true; |
399 } | |
400 return false; | 517 return false; |
401 } | 518 } |
402 | 519 |
403 const char *DWARFDie::getSubroutineName(DINameKind Kind) const { | 520 const char *DWARFDie::getSubroutineName(DINameKind Kind) const { |
404 if (!isSubroutineDIE()) | 521 if (!isSubroutineDIE()) |
434 CallDiscriminator = toUnsigned(find(DW_AT_GNU_discriminator), 0); | 551 CallDiscriminator = toUnsigned(find(DW_AT_GNU_discriminator), 0); |
435 } | 552 } |
436 | 553 |
437 /// Helper to dump a DIE with all of its parents, but no siblings. | 554 /// Helper to dump a DIE with all of its parents, but no siblings. |
438 static unsigned dumpParentChain(DWARFDie Die, raw_ostream &OS, unsigned Indent, | 555 static unsigned dumpParentChain(DWARFDie Die, raw_ostream &OS, unsigned Indent, |
439 DIDumpOptions DumpOpts) { | 556 DIDumpOptions DumpOpts, unsigned Depth = 0) { |
440 if (!Die) | 557 if (!Die) |
441 return Indent; | 558 return Indent; |
442 Indent = dumpParentChain(Die.getParent(), OS, Indent, DumpOpts); | 559 if (DumpOpts.ParentRecurseDepth > 0 && Depth >= DumpOpts.ParentRecurseDepth) |
560 return Indent; | |
561 Indent = dumpParentChain(Die.getParent(), OS, Indent, DumpOpts, Depth + 1); | |
443 Die.dump(OS, Indent, DumpOpts); | 562 Die.dump(OS, Indent, DumpOpts); |
444 return Indent + 2; | 563 return Indent + 2; |
445 } | 564 } |
446 | 565 |
447 void DWARFDie::dump(raw_ostream &OS, unsigned Indent, | 566 void DWARFDie::dump(raw_ostream &OS, unsigned Indent, |
448 DIDumpOptions DumpOpts) const { | 567 DIDumpOptions DumpOpts) const { |
449 if (!isValid()) | 568 if (!isValid()) |
450 return; | 569 return; |
451 DWARFDataExtractor debug_info_data = U->getDebugInfoExtractor(); | 570 DWARFDataExtractor debug_info_data = U->getDebugInfoExtractor(); |
452 const uint32_t Offset = getOffset(); | 571 const uint64_t Offset = getOffset(); |
453 uint32_t offset = Offset; | 572 uint64_t offset = Offset; |
454 if (DumpOpts.ShowParents) { | 573 if (DumpOpts.ShowParents) { |
455 DumpOpts.ShowParents = false; | 574 DIDumpOptions ParentDumpOpts = DumpOpts; |
456 Indent = dumpParentChain(getParent(), OS, Indent, DumpOpts); | 575 ParentDumpOpts.ShowParents = false; |
576 ParentDumpOpts.ShowChildren = false; | |
577 Indent = dumpParentChain(getParent(), OS, Indent, ParentDumpOpts); | |
457 } | 578 } |
458 | 579 |
459 if (debug_info_data.isValidOffset(offset)) { | 580 if (debug_info_data.isValidOffset(offset)) { |
460 uint32_t abbrCode = debug_info_data.getULEB128(&offset); | 581 uint32_t abbrCode = debug_info_data.getULEB128(&offset); |
461 if (DumpOpts.ShowAddresses) | 582 if (DumpOpts.ShowAddresses) |
462 WithColor(OS, syntax::Address).get() << format("\n0x%8.8x: ", Offset); | 583 WithColor(OS, HighlightColor::Address).get() |
584 << format("\n0x%8.8" PRIx64 ": ", Offset); | |
463 | 585 |
464 if (abbrCode) { | 586 if (abbrCode) { |
465 auto AbbrevDecl = getAbbreviationDeclarationPtr(); | 587 auto AbbrevDecl = getAbbreviationDeclarationPtr(); |
466 if (AbbrevDecl) { | 588 if (AbbrevDecl) { |
467 auto tagString = TagString(getTag()); | 589 WithColor(OS, HighlightColor::Tag).get().indent(Indent) |
468 if (!tagString.empty()) | 590 << formatv("{0}", getTag()); |
469 WithColor(OS, syntax::Tag).get().indent(Indent) << tagString; | |
470 else | |
471 WithColor(OS, syntax::Tag).get().indent(Indent) | |
472 << format("DW_TAG_Unknown_%x", getTag()); | |
473 | |
474 if (DumpOpts.Verbose) | 591 if (DumpOpts.Verbose) |
475 OS << format(" [%u] %c", abbrCode, | 592 OS << format(" [%u] %c", abbrCode, |
476 AbbrevDecl->hasChildren() ? '*' : ' '); | 593 AbbrevDecl->hasChildren() ? '*' : ' '); |
477 OS << '\n'; | 594 OS << '\n'; |
478 | 595 |
487 dumpAttribute(OS, *this, &offset, AttrSpec.Attr, AttrSpec.Form, | 604 dumpAttribute(OS, *this, &offset, AttrSpec.Attr, AttrSpec.Form, |
488 Indent, DumpOpts); | 605 Indent, DumpOpts); |
489 } | 606 } |
490 | 607 |
491 DWARFDie child = getFirstChild(); | 608 DWARFDie child = getFirstChild(); |
492 if (DumpOpts.ShowChildren && DumpOpts.RecurseDepth > 0 && child) { | 609 if (DumpOpts.ShowChildren && DumpOpts.ChildRecurseDepth > 0 && child) { |
493 DumpOpts.RecurseDepth--; | 610 DumpOpts.ChildRecurseDepth--; |
611 DIDumpOptions ChildDumpOpts = DumpOpts; | |
612 ChildDumpOpts.ShowParents = false; | |
494 while (child) { | 613 while (child) { |
495 child.dump(OS, Indent + 2, DumpOpts); | 614 child.dump(OS, Indent + 2, ChildDumpOpts); |
496 child = child.getSibling(); | 615 child = child.getSibling(); |
497 } | 616 } |
498 } | 617 } |
499 } else { | 618 } else { |
500 OS << "Abbreviation code not found in 'debug_abbrev' class for code: " | 619 OS << "Abbreviation code not found in 'debug_abbrev' class for code: " |
518 if (isValid()) | 637 if (isValid()) |
519 return U->getSibling(Die); | 638 return U->getSibling(Die); |
520 return DWARFDie(); | 639 return DWARFDie(); |
521 } | 640 } |
522 | 641 |
642 DWARFDie DWARFDie::getPreviousSibling() const { | |
643 if (isValid()) | |
644 return U->getPreviousSibling(Die); | |
645 return DWARFDie(); | |
646 } | |
647 | |
523 DWARFDie DWARFDie::getFirstChild() const { | 648 DWARFDie DWARFDie::getFirstChild() const { |
524 if (isValid()) | 649 if (isValid()) |
525 return U->getFirstChild(Die); | 650 return U->getFirstChild(Die); |
526 return DWARFDie(); | 651 return DWARFDie(); |
527 } | 652 } |
528 | 653 |
654 DWARFDie DWARFDie::getLastChild() const { | |
655 if (isValid()) | |
656 return U->getLastChild(Die); | |
657 return DWARFDie(); | |
658 } | |
659 | |
529 iterator_range<DWARFDie::attribute_iterator> DWARFDie::attributes() const { | 660 iterator_range<DWARFDie::attribute_iterator> DWARFDie::attributes() const { |
530 return make_range(attribute_iterator(*this, false), | 661 return make_range(attribute_iterator(*this, false), |
531 attribute_iterator(*this, true)); | 662 attribute_iterator(*this, true)); |
532 } | 663 } |
533 | 664 |
534 DWARFDie::attribute_iterator::attribute_iterator(DWARFDie D, bool End) | 665 DWARFDie::attribute_iterator::attribute_iterator(DWARFDie D, bool End) |
535 : Die(D), AttrValue(0), Index(0) { | 666 : Die(D), Index(0) { |
536 auto AbbrDecl = Die.getAbbreviationDeclarationPtr(); | 667 auto AbbrDecl = Die.getAbbreviationDeclarationPtr(); |
537 assert(AbbrDecl && "Must have abbreviation declaration"); | 668 assert(AbbrDecl && "Must have abbreviation declaration"); |
538 if (End) { | 669 if (End) { |
539 // This is the end iterator so we set the index to the attribute count. | 670 // This is the end iterator so we set the index to the attribute count. |
540 Index = AbbrDecl->getNumAttributes(); | 671 Index = AbbrDecl->getNumAttributes(); |
552 auto NumAttrs = AbbrDecl.getNumAttributes(); | 683 auto NumAttrs = AbbrDecl.getNumAttributes(); |
553 if (Index < NumAttrs) { | 684 if (Index < NumAttrs) { |
554 AttrValue.Attr = AbbrDecl.getAttrByIndex(Index); | 685 AttrValue.Attr = AbbrDecl.getAttrByIndex(Index); |
555 // Add the previous byte size of any previous attribute value. | 686 // Add the previous byte size of any previous attribute value. |
556 AttrValue.Offset += AttrValue.ByteSize; | 687 AttrValue.Offset += AttrValue.ByteSize; |
557 AttrValue.Value.setForm(AbbrDecl.getFormByIndex(Index)); | 688 uint64_t ParseOffset = AttrValue.Offset; |
558 uint32_t ParseOffset = AttrValue.Offset; | |
559 auto U = Die.getDwarfUnit(); | 689 auto U = Die.getDwarfUnit(); |
560 assert(U && "Die must have valid DWARF unit"); | 690 assert(U && "Die must have valid DWARF unit"); |
561 bool b = AttrValue.Value.extractValue(U->getDebugInfoExtractor(), | 691 AttrValue.Value = DWARFFormValue::createFromUnit( |
562 &ParseOffset, U->getFormParams(), U); | 692 AbbrDecl.getFormByIndex(Index), U, &ParseOffset); |
563 (void)b; | |
564 assert(b && "extractValue cannot fail on fully parsed DWARF"); | |
565 AttrValue.ByteSize = ParseOffset - AttrValue.Offset; | 693 AttrValue.ByteSize = ParseOffset - AttrValue.Offset; |
566 } else { | 694 } else { |
567 assert(Index == NumAttrs && "Indexes should be [0, NumAttrs) only"); | 695 assert(Index == NumAttrs && "Indexes should be [0, NumAttrs) only"); |
568 AttrValue.clear(); | 696 AttrValue = {}; |
569 } | 697 } |
570 } | 698 } |
571 | 699 |
572 DWARFDie::attribute_iterator &DWARFDie::attribute_iterator::operator++() { | 700 DWARFDie::attribute_iterator &DWARFDie::attribute_iterator::operator++() { |
573 if (auto AbbrDecl = Die.getAbbreviationDeclarationPtr()) | 701 if (auto AbbrDecl = Die.getAbbreviationDeclarationPtr()) |
574 updateForIndex(*AbbrDecl, Index + 1); | 702 updateForIndex(*AbbrDecl, Index + 1); |
575 return *this; | 703 return *this; |
576 } | 704 } |
705 | |
706 bool DWARFAttribute::mayHaveLocationDescription(dwarf::Attribute Attr) { | |
707 switch (Attr) { | |
708 // From the DWARF v5 specification. | |
709 case DW_AT_location: | |
710 case DW_AT_byte_size: | |
711 case DW_AT_bit_size: | |
712 case DW_AT_string_length: | |
713 case DW_AT_lower_bound: | |
714 case DW_AT_return_addr: | |
715 case DW_AT_bit_stride: | |
716 case DW_AT_upper_bound: | |
717 case DW_AT_count: | |
718 case DW_AT_data_member_location: | |
719 case DW_AT_frame_base: | |
720 case DW_AT_segment: | |
721 case DW_AT_static_link: | |
722 case DW_AT_use_location: | |
723 case DW_AT_vtable_elem_location: | |
724 case DW_AT_allocated: | |
725 case DW_AT_associated: | |
726 case DW_AT_byte_stride: | |
727 case DW_AT_rank: | |
728 case DW_AT_call_value: | |
729 case DW_AT_call_origin: | |
730 case DW_AT_call_target: | |
731 case DW_AT_call_target_clobbered: | |
732 case DW_AT_call_data_location: | |
733 case DW_AT_call_data_value: | |
734 // Extensions. | |
735 case DW_AT_GNU_call_site_value: | |
736 case DW_AT_GNU_call_site_target: | |
737 return true; | |
738 default: | |
739 return false; | |
740 } | |
741 } |