1 //===- DWARFContext.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
9 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
10 #include "llvm/ADT/MapVector.h"
11 #include "llvm/ADT/STLExtras.h"
12 #include "llvm/ADT/SmallString.h"
13 #include "llvm/ADT/SmallVector.h"
14 #include "llvm/ADT/StringRef.h"
15 #include "llvm/ADT/StringSwitch.h"
16 #include "llvm/BinaryFormat/Dwarf.h"
17 #include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
18 #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
19 #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
20 #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
21 #include "llvm/DebugInfo/DWARF/DWARFDebugAddr.h"
22 #include "llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h"
23 #include "llvm/DebugInfo/DWARF/DWARFDebugAranges.h"
24 #include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h"
25 #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
26 #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
27 #include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h"
28 #include "llvm/DebugInfo/DWARF/DWARFDebugPubTable.h"
29 #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
30 #include "llvm/DebugInfo/DWARF/DWARFDebugRnglists.h"
31 #include "llvm/DebugInfo/DWARF/DWARFDie.h"
32 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
33 #include "llvm/DebugInfo/DWARF/DWARFGdbIndex.h"
34 #include "llvm/DebugInfo/DWARF/DWARFListTable.h"
35 #include "llvm/DebugInfo/DWARF/DWARFLocationExpression.h"
36 #include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
37 #include "llvm/DebugInfo/DWARF/DWARFSection.h"
38 #include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h"
39 #include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
40 #include "llvm/DebugInfo/DWARF/DWARFVerifier.h"
41 #include "llvm/MC/TargetRegistry.h"
42 #include "llvm/Object/Decompressor.h"
43 #include "llvm/Object/MachO.h"
44 #include "llvm/Object/ObjectFile.h"
45 #include "llvm/Object/RelocationResolver.h"
46 #include "llvm/Support/Casting.h"
47 #include "llvm/Support/DataExtractor.h"
48 #include "llvm/Support/Error.h"
49 #include "llvm/Support/Format.h"
50 #include "llvm/Support/LEB128.h"
51 #include "llvm/Support/MemoryBuffer.h"
52 #include "llvm/Support/Path.h"
53 #include "llvm/Support/raw_ostream.h"
54 #include <algorithm>
55 #include <cstdint>
56 #include <deque>
57 #include <map>
58 #include <string>
59 #include <utility>
60 #include <vector>
61
62 using namespace llvm;
63 using namespace dwarf;
64 using namespace object;
65
66 #define DEBUG_TYPE "dwarf"
67
68 using DWARFLineTable = DWARFDebugLine::LineTable;
69 using FileLineInfoKind = DILineInfoSpecifier::FileLineInfoKind;
70 using FunctionNameKind = DILineInfoSpecifier::FunctionNameKind;
71
DWARFContext(std::unique_ptr<const DWARFObject> DObj,std::string DWPName,std::function<void (Error)> RecoverableErrorHandler,std::function<void (Error)> WarningHandler)72 DWARFContext::DWARFContext(std::unique_ptr<const DWARFObject> DObj,
73 std::string DWPName,
74 std::function<void(Error)> RecoverableErrorHandler,
75 std::function<void(Error)> WarningHandler)
76 : DIContext(CK_DWARF), DWPName(std::move(DWPName)),
77 RecoverableErrorHandler(RecoverableErrorHandler),
78 WarningHandler(WarningHandler), DObj(std::move(DObj)) {}
79
80 DWARFContext::~DWARFContext() = default;
81
82 /// Dump the UUID load command.
dumpUUID(raw_ostream & OS,const ObjectFile & Obj)83 static void dumpUUID(raw_ostream &OS, const ObjectFile &Obj) {
84 auto *MachO = dyn_cast<MachOObjectFile>(&Obj);
85 if (!MachO)
86 return;
87 for (auto LC : MachO->load_commands()) {
88 raw_ostream::uuid_t UUID;
89 if (LC.C.cmd == MachO::LC_UUID) {
90 if (LC.C.cmdsize < sizeof(UUID) + sizeof(LC.C)) {
91 OS << "error: UUID load command is too short.\n";
92 return;
93 }
94 OS << "UUID: ";
95 memcpy(&UUID, LC.Ptr+sizeof(LC.C), sizeof(UUID));
96 OS.write_uuid(UUID);
97 Triple T = MachO->getArchTriple();
98 OS << " (" << T.getArchName() << ')';
99 OS << ' ' << MachO->getFileName() << '\n';
100 }
101 }
102 }
103
104 using ContributionCollection =
105 std::vector<std::optional<StrOffsetsContributionDescriptor>>;
106
107 // Collect all the contributions to the string offsets table from all units,
108 // sort them by their starting offsets and remove duplicates.
109 static ContributionCollection
collectContributionData(DWARFContext::unit_iterator_range Units)110 collectContributionData(DWARFContext::unit_iterator_range Units) {
111 ContributionCollection Contributions;
112 for (const auto &U : Units)
113 if (const auto &C = U->getStringOffsetsTableContribution())
114 Contributions.push_back(C);
115 // Sort the contributions so that any invalid ones are placed at
116 // the start of the contributions vector. This way they are reported
117 // first.
118 llvm::sort(Contributions,
119 [](const std::optional<StrOffsetsContributionDescriptor> &L,
120 const std::optional<StrOffsetsContributionDescriptor> &R) {
121 if (L && R)
122 return L->Base < R->Base;
123 return R.has_value();
124 });
125
126 // Uniquify contributions, as it is possible that units (specifically
127 // type units in dwo or dwp files) share contributions. We don't want
128 // to report them more than once.
129 Contributions.erase(
130 std::unique(Contributions.begin(), Contributions.end(),
131 [](const std::optional<StrOffsetsContributionDescriptor> &L,
132 const std::optional<StrOffsetsContributionDescriptor> &R) {
133 if (L && R)
134 return L->Base == R->Base && L->Size == R->Size;
135 return false;
136 }),
137 Contributions.end());
138 return Contributions;
139 }
140
141 // Dump a DWARF string offsets section. This may be a DWARF v5 formatted
142 // string offsets section, where each compile or type unit contributes a
143 // number of entries (string offsets), with each contribution preceded by
144 // a header containing size and version number. Alternatively, it may be a
145 // monolithic series of string offsets, as generated by the pre-DWARF v5
146 // implementation of split DWARF; however, in that case we still need to
147 // collect contributions of units because the size of the offsets (4 or 8
148 // bytes) depends on the format of the referencing unit (DWARF32 or DWARF64).
dumpStringOffsetsSection(raw_ostream & OS,DIDumpOptions DumpOpts,StringRef SectionName,const DWARFObject & Obj,const DWARFSection & StringOffsetsSection,StringRef StringSection,DWARFContext::unit_iterator_range Units,bool LittleEndian)149 static void dumpStringOffsetsSection(raw_ostream &OS, DIDumpOptions DumpOpts,
150 StringRef SectionName,
151 const DWARFObject &Obj,
152 const DWARFSection &StringOffsetsSection,
153 StringRef StringSection,
154 DWARFContext::unit_iterator_range Units,
155 bool LittleEndian) {
156 auto Contributions = collectContributionData(Units);
157 DWARFDataExtractor StrOffsetExt(Obj, StringOffsetsSection, LittleEndian, 0);
158 DataExtractor StrData(StringSection, LittleEndian, 0);
159 uint64_t SectionSize = StringOffsetsSection.Data.size();
160 uint64_t Offset = 0;
161 for (auto &Contribution : Contributions) {
162 // Report an ill-formed contribution.
163 if (!Contribution) {
164 OS << "error: invalid contribution to string offsets table in section ."
165 << SectionName << ".\n";
166 return;
167 }
168
169 dwarf::DwarfFormat Format = Contribution->getFormat();
170 int OffsetDumpWidth = 2 * dwarf::getDwarfOffsetByteSize(Format);
171 uint16_t Version = Contribution->getVersion();
172 uint64_t ContributionHeader = Contribution->Base;
173 // In DWARF v5 there is a contribution header that immediately precedes
174 // the string offsets base (the location we have previously retrieved from
175 // the CU DIE's DW_AT_str_offsets attribute). The header is located either
176 // 8 or 16 bytes before the base, depending on the contribution's format.
177 if (Version >= 5)
178 ContributionHeader -= Format == DWARF32 ? 8 : 16;
179
180 // Detect overlapping contributions.
181 if (Offset > ContributionHeader) {
182 DumpOpts.RecoverableErrorHandler(createStringError(
183 errc::invalid_argument,
184 "overlapping contributions to string offsets table in section .%s.",
185 SectionName.data()));
186 }
187 // Report a gap in the table.
188 if (Offset < ContributionHeader) {
189 OS << format("0x%8.8" PRIx64 ": Gap, length = ", Offset);
190 OS << (ContributionHeader - Offset) << "\n";
191 }
192 OS << format("0x%8.8" PRIx64 ": ", ContributionHeader);
193 // In DWARF v5 the contribution size in the descriptor does not equal
194 // the originally encoded length (it does not contain the length of the
195 // version field and the padding, a total of 4 bytes). Add them back in
196 // for reporting.
197 OS << "Contribution size = " << (Contribution->Size + (Version < 5 ? 0 : 4))
198 << ", Format = " << dwarf::FormatString(Format)
199 << ", Version = " << Version << "\n";
200
201 Offset = Contribution->Base;
202 unsigned EntrySize = Contribution->getDwarfOffsetByteSize();
203 while (Offset - Contribution->Base < Contribution->Size) {
204 OS << format("0x%8.8" PRIx64 ": ", Offset);
205 uint64_t StringOffset =
206 StrOffsetExt.getRelocatedValue(EntrySize, &Offset);
207 OS << format("%0*" PRIx64 " ", OffsetDumpWidth, StringOffset);
208 const char *S = StrData.getCStr(&StringOffset);
209 if (S)
210 OS << format("\"%s\"", S);
211 OS << "\n";
212 }
213 }
214 // Report a gap at the end of the table.
215 if (Offset < SectionSize) {
216 OS << format("0x%8.8" PRIx64 ": Gap, length = ", Offset);
217 OS << (SectionSize - Offset) << "\n";
218 }
219 }
220
221 // Dump the .debug_addr section.
dumpAddrSection(raw_ostream & OS,DWARFDataExtractor & AddrData,DIDumpOptions DumpOpts,uint16_t Version,uint8_t AddrSize)222 static void dumpAddrSection(raw_ostream &OS, DWARFDataExtractor &AddrData,
223 DIDumpOptions DumpOpts, uint16_t Version,
224 uint8_t AddrSize) {
225 uint64_t Offset = 0;
226 while (AddrData.isValidOffset(Offset)) {
227 DWARFDebugAddrTable AddrTable;
228 uint64_t TableOffset = Offset;
229 if (Error Err = AddrTable.extract(AddrData, &Offset, Version, AddrSize,
230 DumpOpts.WarningHandler)) {
231 DumpOpts.RecoverableErrorHandler(std::move(Err));
232 // Keep going after an error, if we can, assuming that the length field
233 // could be read. If it couldn't, stop reading the section.
234 if (auto TableLength = AddrTable.getFullLength()) {
235 Offset = TableOffset + *TableLength;
236 continue;
237 }
238 break;
239 }
240 AddrTable.dump(OS, DumpOpts);
241 }
242 }
243
244 // Dump the .debug_rnglists or .debug_rnglists.dwo section (DWARF v5).
dumpRnglistsSection(raw_ostream & OS,DWARFDataExtractor & rnglistData,llvm::function_ref<std::optional<object::SectionedAddress> (uint32_t)> LookupPooledAddress,DIDumpOptions DumpOpts)245 static void dumpRnglistsSection(
246 raw_ostream &OS, DWARFDataExtractor &rnglistData,
247 llvm::function_ref<std::optional<object::SectionedAddress>(uint32_t)>
248 LookupPooledAddress,
249 DIDumpOptions DumpOpts) {
250 uint64_t Offset = 0;
251 while (rnglistData.isValidOffset(Offset)) {
252 llvm::DWARFDebugRnglistTable Rnglists;
253 uint64_t TableOffset = Offset;
254 if (Error Err = Rnglists.extract(rnglistData, &Offset)) {
255 DumpOpts.RecoverableErrorHandler(std::move(Err));
256 uint64_t Length = Rnglists.length();
257 // Keep going after an error, if we can, assuming that the length field
258 // could be read. If it couldn't, stop reading the section.
259 if (Length == 0)
260 break;
261 Offset = TableOffset + Length;
262 } else {
263 Rnglists.dump(rnglistData, OS, LookupPooledAddress, DumpOpts);
264 }
265 }
266 }
267
268 std::unique_ptr<DWARFDebugMacro>
parseMacroOrMacinfo(MacroSecType SectionType)269 DWARFContext::parseMacroOrMacinfo(MacroSecType SectionType) {
270 auto Macro = std::make_unique<DWARFDebugMacro>();
271 auto ParseAndDump = [&](DWARFDataExtractor &Data, bool IsMacro) {
272 if (Error Err = IsMacro ? Macro->parseMacro(SectionType == MacroSection
273 ? compile_units()
274 : dwo_compile_units(),
275 SectionType == MacroSection
276 ? getStringExtractor()
277 : getStringDWOExtractor(),
278 Data)
279 : Macro->parseMacinfo(Data)) {
280 RecoverableErrorHandler(std::move(Err));
281 Macro = nullptr;
282 }
283 };
284 switch (SectionType) {
285 case MacinfoSection: {
286 DWARFDataExtractor Data(DObj->getMacinfoSection(), isLittleEndian(), 0);
287 ParseAndDump(Data, /*IsMacro=*/false);
288 break;
289 }
290 case MacinfoDwoSection: {
291 DWARFDataExtractor Data(DObj->getMacinfoDWOSection(), isLittleEndian(), 0);
292 ParseAndDump(Data, /*IsMacro=*/false);
293 break;
294 }
295 case MacroSection: {
296 DWARFDataExtractor Data(*DObj, DObj->getMacroSection(), isLittleEndian(),
297 0);
298 ParseAndDump(Data, /*IsMacro=*/true);
299 break;
300 }
301 case MacroDwoSection: {
302 DWARFDataExtractor Data(DObj->getMacroDWOSection(), isLittleEndian(), 0);
303 ParseAndDump(Data, /*IsMacro=*/true);
304 break;
305 }
306 }
307 return Macro;
308 }
309
dumpLoclistsSection(raw_ostream & OS,DIDumpOptions DumpOpts,DWARFDataExtractor Data,const DWARFObject & Obj,std::optional<uint64_t> DumpOffset)310 static void dumpLoclistsSection(raw_ostream &OS, DIDumpOptions DumpOpts,
311 DWARFDataExtractor Data, const DWARFObject &Obj,
312 std::optional<uint64_t> DumpOffset) {
313 uint64_t Offset = 0;
314
315 while (Data.isValidOffset(Offset)) {
316 DWARFListTableHeader Header(".debug_loclists", "locations");
317 if (Error E = Header.extract(Data, &Offset)) {
318 DumpOpts.RecoverableErrorHandler(std::move(E));
319 return;
320 }
321
322 Header.dump(Data, OS, DumpOpts);
323
324 uint64_t EndOffset = Header.length() + Header.getHeaderOffset();
325 Data.setAddressSize(Header.getAddrSize());
326 DWARFDebugLoclists Loc(Data, Header.getVersion());
327 if (DumpOffset) {
328 if (DumpOffset >= Offset && DumpOffset < EndOffset) {
329 Offset = *DumpOffset;
330 Loc.dumpLocationList(&Offset, OS, /*BaseAddr=*/std::nullopt, Obj,
331 nullptr, DumpOpts, /*Indent=*/0);
332 OS << "\n";
333 return;
334 }
335 } else {
336 Loc.dumpRange(Offset, EndOffset - Offset, OS, Obj, DumpOpts);
337 }
338 Offset = EndOffset;
339 }
340 }
341
dumpPubTableSection(raw_ostream & OS,DIDumpOptions DumpOpts,DWARFDataExtractor Data,bool GnuStyle)342 static void dumpPubTableSection(raw_ostream &OS, DIDumpOptions DumpOpts,
343 DWARFDataExtractor Data, bool GnuStyle) {
344 DWARFDebugPubTable Table;
345 Table.extract(Data, GnuStyle, DumpOpts.RecoverableErrorHandler);
346 Table.dump(OS);
347 }
348
dump(raw_ostream & OS,DIDumpOptions DumpOpts,std::array<std::optional<uint64_t>,DIDT_ID_Count> DumpOffsets)349 void DWARFContext::dump(
350 raw_ostream &OS, DIDumpOptions DumpOpts,
351 std::array<std::optional<uint64_t>, DIDT_ID_Count> DumpOffsets) {
352 uint64_t DumpType = DumpOpts.DumpType;
353
354 StringRef Extension = sys::path::extension(DObj->getFileName());
355 bool IsDWO = (Extension == ".dwo") || (Extension == ".dwp");
356
357 // Print UUID header.
358 const auto *ObjFile = DObj->getFile();
359 if (DumpType & DIDT_UUID)
360 dumpUUID(OS, *ObjFile);
361
362 // Print a header for each explicitly-requested section.
363 // Otherwise just print one for non-empty sections.
364 // Only print empty .dwo section headers when dumping a .dwo file.
365 bool Explicit = DumpType != DIDT_All && !IsDWO;
366 bool ExplicitDWO = Explicit && IsDWO;
367 auto shouldDump = [&](bool Explicit, const char *Name, unsigned ID,
368 StringRef Section) -> std::optional<uint64_t> * {
369 unsigned Mask = 1U << ID;
370 bool Should = (DumpType & Mask) && (Explicit || !Section.empty());
371 if (!Should)
372 return nullptr;
373 OS << "\n" << Name << " contents:\n";
374 return &DumpOffsets[ID];
375 };
376
377 // Dump individual sections.
378 if (shouldDump(Explicit, ".debug_abbrev", DIDT_ID_DebugAbbrev,
379 DObj->getAbbrevSection()))
380 getDebugAbbrev()->dump(OS);
381 if (shouldDump(ExplicitDWO, ".debug_abbrev.dwo", DIDT_ID_DebugAbbrev,
382 DObj->getAbbrevDWOSection()))
383 getDebugAbbrevDWO()->dump(OS);
384
385 auto dumpDebugInfo = [&](const char *Name, unit_iterator_range Units) {
386 OS << '\n' << Name << " contents:\n";
387 if (auto DumpOffset = DumpOffsets[DIDT_ID_DebugInfo])
388 for (const auto &U : Units)
389 U->getDIEForOffset(*DumpOffset)
390 .dump(OS, 0, DumpOpts.noImplicitRecursion());
391 else
392 for (const auto &U : Units)
393 U->dump(OS, DumpOpts);
394 };
395 if ((DumpType & DIDT_DebugInfo)) {
396 if (Explicit || getNumCompileUnits())
397 dumpDebugInfo(".debug_info", info_section_units());
398 if (ExplicitDWO || getNumDWOCompileUnits())
399 dumpDebugInfo(".debug_info.dwo", dwo_info_section_units());
400 }
401
402 auto dumpDebugType = [&](const char *Name, unit_iterator_range Units) {
403 OS << '\n' << Name << " contents:\n";
404 for (const auto &U : Units)
405 if (auto DumpOffset = DumpOffsets[DIDT_ID_DebugTypes])
406 U->getDIEForOffset(*DumpOffset)
407 .dump(OS, 0, DumpOpts.noImplicitRecursion());
408 else
409 U->dump(OS, DumpOpts);
410 };
411 if ((DumpType & DIDT_DebugTypes)) {
412 if (Explicit || getNumTypeUnits())
413 dumpDebugType(".debug_types", types_section_units());
414 if (ExplicitDWO || getNumDWOTypeUnits())
415 dumpDebugType(".debug_types.dwo", dwo_types_section_units());
416 }
417
418 DIDumpOptions LLDumpOpts = DumpOpts;
419 if (LLDumpOpts.Verbose)
420 LLDumpOpts.DisplayRawContents = true;
421
422 if (const auto *Off = shouldDump(Explicit, ".debug_loc", DIDT_ID_DebugLoc,
423 DObj->getLocSection().Data)) {
424 getDebugLoc()->dump(OS, *DObj, LLDumpOpts, *Off);
425 }
426 if (const auto *Off =
427 shouldDump(Explicit, ".debug_loclists", DIDT_ID_DebugLoclists,
428 DObj->getLoclistsSection().Data)) {
429 DWARFDataExtractor Data(*DObj, DObj->getLoclistsSection(), isLittleEndian(),
430 0);
431 dumpLoclistsSection(OS, LLDumpOpts, Data, *DObj, *Off);
432 }
433 if (const auto *Off =
434 shouldDump(ExplicitDWO, ".debug_loclists.dwo", DIDT_ID_DebugLoclists,
435 DObj->getLoclistsDWOSection().Data)) {
436 DWARFDataExtractor Data(*DObj, DObj->getLoclistsDWOSection(),
437 isLittleEndian(), 0);
438 dumpLoclistsSection(OS, LLDumpOpts, Data, *DObj, *Off);
439 }
440
441 if (const auto *Off =
442 shouldDump(ExplicitDWO, ".debug_loc.dwo", DIDT_ID_DebugLoc,
443 DObj->getLocDWOSection().Data)) {
444 DWARFDataExtractor Data(*DObj, DObj->getLocDWOSection(), isLittleEndian(),
445 4);
446 DWARFDebugLoclists Loc(Data, /*Version=*/4);
447 if (*Off) {
448 uint64_t Offset = **Off;
449 Loc.dumpLocationList(&Offset, OS,
450 /*BaseAddr=*/std::nullopt, *DObj, nullptr,
451 LLDumpOpts,
452 /*Indent=*/0);
453 OS << "\n";
454 } else {
455 Loc.dumpRange(0, Data.getData().size(), OS, *DObj, LLDumpOpts);
456 }
457 }
458
459 if (const std::optional<uint64_t> *Off =
460 shouldDump(Explicit, ".debug_frame", DIDT_ID_DebugFrame,
461 DObj->getFrameSection().Data)) {
462 if (Expected<const DWARFDebugFrame *> DF = getDebugFrame())
463 (*DF)->dump(OS, DumpOpts, *Off);
464 else
465 RecoverableErrorHandler(DF.takeError());
466 }
467
468 if (const std::optional<uint64_t> *Off =
469 shouldDump(Explicit, ".eh_frame", DIDT_ID_DebugFrame,
470 DObj->getEHFrameSection().Data)) {
471 if (Expected<const DWARFDebugFrame *> DF = getEHFrame())
472 (*DF)->dump(OS, DumpOpts, *Off);
473 else
474 RecoverableErrorHandler(DF.takeError());
475 }
476
477 if (shouldDump(Explicit, ".debug_macro", DIDT_ID_DebugMacro,
478 DObj->getMacroSection().Data)) {
479 if (auto Macro = getDebugMacro())
480 Macro->dump(OS);
481 }
482
483 if (shouldDump(Explicit, ".debug_macro.dwo", DIDT_ID_DebugMacro,
484 DObj->getMacroDWOSection())) {
485 if (auto MacroDWO = getDebugMacroDWO())
486 MacroDWO->dump(OS);
487 }
488
489 if (shouldDump(Explicit, ".debug_macinfo", DIDT_ID_DebugMacro,
490 DObj->getMacinfoSection())) {
491 if (auto Macinfo = getDebugMacinfo())
492 Macinfo->dump(OS);
493 }
494
495 if (shouldDump(Explicit, ".debug_macinfo.dwo", DIDT_ID_DebugMacro,
496 DObj->getMacinfoDWOSection())) {
497 if (auto MacinfoDWO = getDebugMacinfoDWO())
498 MacinfoDWO->dump(OS);
499 }
500
501 if (shouldDump(Explicit, ".debug_aranges", DIDT_ID_DebugAranges,
502 DObj->getArangesSection())) {
503 uint64_t offset = 0;
504 DWARFDataExtractor arangesData(DObj->getArangesSection(), isLittleEndian(),
505 0);
506 DWARFDebugArangeSet set;
507 while (arangesData.isValidOffset(offset)) {
508 if (Error E =
509 set.extract(arangesData, &offset, DumpOpts.WarningHandler)) {
510 RecoverableErrorHandler(std::move(E));
511 break;
512 }
513 set.dump(OS);
514 }
515 }
516
517 auto DumpLineSection = [&](DWARFDebugLine::SectionParser Parser,
518 DIDumpOptions DumpOpts,
519 std::optional<uint64_t> DumpOffset) {
520 while (!Parser.done()) {
521 if (DumpOffset && Parser.getOffset() != *DumpOffset) {
522 Parser.skip(DumpOpts.WarningHandler, DumpOpts.WarningHandler);
523 continue;
524 }
525 OS << "debug_line[" << format("0x%8.8" PRIx64, Parser.getOffset())
526 << "]\n";
527 Parser.parseNext(DumpOpts.WarningHandler, DumpOpts.WarningHandler, &OS,
528 DumpOpts.Verbose);
529 }
530 };
531
532 auto DumpStrSection = [&](StringRef Section) {
533 DataExtractor StrData(Section, isLittleEndian(), 0);
534 uint64_t Offset = 0;
535 uint64_t StrOffset = 0;
536 while (StrData.isValidOffset(Offset)) {
537 Error Err = Error::success();
538 const char *CStr = StrData.getCStr(&Offset, &Err);
539 if (Err) {
540 DumpOpts.WarningHandler(std::move(Err));
541 return;
542 }
543 OS << format("0x%8.8" PRIx64 ": \"", StrOffset);
544 OS.write_escaped(CStr);
545 OS << "\"\n";
546 StrOffset = Offset;
547 }
548 };
549
550 if (const auto *Off = shouldDump(Explicit, ".debug_line", DIDT_ID_DebugLine,
551 DObj->getLineSection().Data)) {
552 DWARFDataExtractor LineData(*DObj, DObj->getLineSection(), isLittleEndian(),
553 0);
554 DWARFDebugLine::SectionParser Parser(LineData, *this, normal_units());
555 DumpLineSection(Parser, DumpOpts, *Off);
556 }
557
558 if (const auto *Off =
559 shouldDump(ExplicitDWO, ".debug_line.dwo", DIDT_ID_DebugLine,
560 DObj->getLineDWOSection().Data)) {
561 DWARFDataExtractor LineData(*DObj, DObj->getLineDWOSection(),
562 isLittleEndian(), 0);
563 DWARFDebugLine::SectionParser Parser(LineData, *this, dwo_units());
564 DumpLineSection(Parser, DumpOpts, *Off);
565 }
566
567 if (shouldDump(Explicit, ".debug_cu_index", DIDT_ID_DebugCUIndex,
568 DObj->getCUIndexSection())) {
569 getCUIndex().dump(OS);
570 }
571
572 if (shouldDump(Explicit, ".debug_tu_index", DIDT_ID_DebugTUIndex,
573 DObj->getTUIndexSection())) {
574 getTUIndex().dump(OS);
575 }
576
577 if (shouldDump(Explicit, ".debug_str", DIDT_ID_DebugStr,
578 DObj->getStrSection()))
579 DumpStrSection(DObj->getStrSection());
580
581 if (shouldDump(ExplicitDWO, ".debug_str.dwo", DIDT_ID_DebugStr,
582 DObj->getStrDWOSection()))
583 DumpStrSection(DObj->getStrDWOSection());
584
585 if (shouldDump(Explicit, ".debug_line_str", DIDT_ID_DebugLineStr,
586 DObj->getLineStrSection()))
587 DumpStrSection(DObj->getLineStrSection());
588
589 if (shouldDump(Explicit, ".debug_addr", DIDT_ID_DebugAddr,
590 DObj->getAddrSection().Data)) {
591 DWARFDataExtractor AddrData(*DObj, DObj->getAddrSection(),
592 isLittleEndian(), 0);
593 dumpAddrSection(OS, AddrData, DumpOpts, getMaxVersion(), getCUAddrSize());
594 }
595
596 if (shouldDump(Explicit, ".debug_ranges", DIDT_ID_DebugRanges,
597 DObj->getRangesSection().Data)) {
598 uint8_t savedAddressByteSize = getCUAddrSize();
599 DWARFDataExtractor rangesData(*DObj, DObj->getRangesSection(),
600 isLittleEndian(), savedAddressByteSize);
601 uint64_t offset = 0;
602 DWARFDebugRangeList rangeList;
603 while (rangesData.isValidOffset(offset)) {
604 if (Error E = rangeList.extract(rangesData, &offset)) {
605 DumpOpts.RecoverableErrorHandler(std::move(E));
606 break;
607 }
608 rangeList.dump(OS);
609 }
610 }
611
612 auto LookupPooledAddress =
613 [&](uint32_t Index) -> std::optional<SectionedAddress> {
614 const auto &CUs = compile_units();
615 auto I = CUs.begin();
616 if (I == CUs.end())
617 return std::nullopt;
618 return (*I)->getAddrOffsetSectionItem(Index);
619 };
620
621 if (shouldDump(Explicit, ".debug_rnglists", DIDT_ID_DebugRnglists,
622 DObj->getRnglistsSection().Data)) {
623 DWARFDataExtractor RnglistData(*DObj, DObj->getRnglistsSection(),
624 isLittleEndian(), 0);
625 dumpRnglistsSection(OS, RnglistData, LookupPooledAddress, DumpOpts);
626 }
627
628 if (shouldDump(ExplicitDWO, ".debug_rnglists.dwo", DIDT_ID_DebugRnglists,
629 DObj->getRnglistsDWOSection().Data)) {
630 DWARFDataExtractor RnglistData(*DObj, DObj->getRnglistsDWOSection(),
631 isLittleEndian(), 0);
632 dumpRnglistsSection(OS, RnglistData, LookupPooledAddress, DumpOpts);
633 }
634
635 if (shouldDump(Explicit, ".debug_pubnames", DIDT_ID_DebugPubnames,
636 DObj->getPubnamesSection().Data)) {
637 DWARFDataExtractor PubTableData(*DObj, DObj->getPubnamesSection(),
638 isLittleEndian(), 0);
639 dumpPubTableSection(OS, DumpOpts, PubTableData, /*GnuStyle=*/false);
640 }
641
642 if (shouldDump(Explicit, ".debug_pubtypes", DIDT_ID_DebugPubtypes,
643 DObj->getPubtypesSection().Data)) {
644 DWARFDataExtractor PubTableData(*DObj, DObj->getPubtypesSection(),
645 isLittleEndian(), 0);
646 dumpPubTableSection(OS, DumpOpts, PubTableData, /*GnuStyle=*/false);
647 }
648
649 if (shouldDump(Explicit, ".debug_gnu_pubnames", DIDT_ID_DebugGnuPubnames,
650 DObj->getGnuPubnamesSection().Data)) {
651 DWARFDataExtractor PubTableData(*DObj, DObj->getGnuPubnamesSection(),
652 isLittleEndian(), 0);
653 dumpPubTableSection(OS, DumpOpts, PubTableData, /*GnuStyle=*/true);
654 }
655
656 if (shouldDump(Explicit, ".debug_gnu_pubtypes", DIDT_ID_DebugGnuPubtypes,
657 DObj->getGnuPubtypesSection().Data)) {
658 DWARFDataExtractor PubTableData(*DObj, DObj->getGnuPubtypesSection(),
659 isLittleEndian(), 0);
660 dumpPubTableSection(OS, DumpOpts, PubTableData, /*GnuStyle=*/true);
661 }
662
663 if (shouldDump(Explicit, ".debug_str_offsets", DIDT_ID_DebugStrOffsets,
664 DObj->getStrOffsetsSection().Data))
665 dumpStringOffsetsSection(
666 OS, DumpOpts, "debug_str_offsets", *DObj, DObj->getStrOffsetsSection(),
667 DObj->getStrSection(), normal_units(), isLittleEndian());
668 if (shouldDump(ExplicitDWO, ".debug_str_offsets.dwo", DIDT_ID_DebugStrOffsets,
669 DObj->getStrOffsetsDWOSection().Data))
670 dumpStringOffsetsSection(OS, DumpOpts, "debug_str_offsets.dwo", *DObj,
671 DObj->getStrOffsetsDWOSection(),
672 DObj->getStrDWOSection(), dwo_units(),
673 isLittleEndian());
674
675 if (shouldDump(Explicit, ".gdb_index", DIDT_ID_GdbIndex,
676 DObj->getGdbIndexSection())) {
677 getGdbIndex().dump(OS);
678 }
679
680 if (shouldDump(Explicit, ".apple_names", DIDT_ID_AppleNames,
681 DObj->getAppleNamesSection().Data))
682 getAppleNames().dump(OS);
683
684 if (shouldDump(Explicit, ".apple_types", DIDT_ID_AppleTypes,
685 DObj->getAppleTypesSection().Data))
686 getAppleTypes().dump(OS);
687
688 if (shouldDump(Explicit, ".apple_namespaces", DIDT_ID_AppleNamespaces,
689 DObj->getAppleNamespacesSection().Data))
690 getAppleNamespaces().dump(OS);
691
692 if (shouldDump(Explicit, ".apple_objc", DIDT_ID_AppleObjC,
693 DObj->getAppleObjCSection().Data))
694 getAppleObjC().dump(OS);
695 if (shouldDump(Explicit, ".debug_names", DIDT_ID_DebugNames,
696 DObj->getNamesSection().Data))
697 getDebugNames().dump(OS);
698 }
699
getTypeUnitForHash(uint16_t Version,uint64_t Hash,bool IsDWO)700 DWARFTypeUnit *DWARFContext::getTypeUnitForHash(uint16_t Version, uint64_t Hash,
701 bool IsDWO) {
702 parseDWOUnits(LazyParse);
703
704 if (const auto &TUI = getTUIndex()) {
705 if (const auto *R = TUI.getFromHash(Hash))
706 return dyn_cast_or_null<DWARFTypeUnit>(
707 DWOUnits.getUnitForIndexEntry(*R));
708 return nullptr;
709 }
710
711 struct UnitContainers {
712 const DWARFUnitVector &Units;
713 std::optional<DenseMap<uint64_t, DWARFTypeUnit *>> ⤅
714 };
715 UnitContainers Units = IsDWO ? UnitContainers{DWOUnits, DWOTypeUnits}
716 : UnitContainers{NormalUnits, NormalTypeUnits};
717 if (!Units.Map) {
718 Units.Map.emplace();
719 for (const auto &U : IsDWO ? dwo_units() : normal_units()) {
720 if (DWARFTypeUnit *TU = dyn_cast<DWARFTypeUnit>(U.get()))
721 (*Units.Map)[TU->getTypeHash()] = TU;
722 }
723 }
724
725 return (*Units.Map)[Hash];
726 }
727
getDWOCompileUnitForHash(uint64_t Hash)728 DWARFCompileUnit *DWARFContext::getDWOCompileUnitForHash(uint64_t Hash) {
729 parseDWOUnits(LazyParse);
730
731 if (const auto &CUI = getCUIndex()) {
732 if (const auto *R = CUI.getFromHash(Hash))
733 return dyn_cast_or_null<DWARFCompileUnit>(
734 DWOUnits.getUnitForIndexEntry(*R));
735 return nullptr;
736 }
737
738 // If there's no index, just search through the CUs in the DWO - there's
739 // probably only one unless this is something like LTO - though an in-process
740 // built/cached lookup table could be used in that case to improve repeated
741 // lookups of different CUs in the DWO.
742 for (const auto &DWOCU : dwo_compile_units()) {
743 // Might not have parsed DWO ID yet.
744 if (!DWOCU->getDWOId()) {
745 if (std::optional<uint64_t> DWOId =
746 toUnsigned(DWOCU->getUnitDIE().find(DW_AT_GNU_dwo_id)))
747 DWOCU->setDWOId(*DWOId);
748 else
749 // No DWO ID?
750 continue;
751 }
752 if (DWOCU->getDWOId() == Hash)
753 return dyn_cast<DWARFCompileUnit>(DWOCU.get());
754 }
755 return nullptr;
756 }
757
getDIEForOffset(uint64_t Offset)758 DWARFDie DWARFContext::getDIEForOffset(uint64_t Offset) {
759 parseNormalUnits();
760 if (auto *CU = NormalUnits.getUnitForOffset(Offset))
761 return CU->getDIEForOffset(Offset);
762 return DWARFDie();
763 }
764
verify(raw_ostream & OS,DIDumpOptions DumpOpts)765 bool DWARFContext::verify(raw_ostream &OS, DIDumpOptions DumpOpts) {
766 bool Success = true;
767 DWARFVerifier verifier(OS, *this, DumpOpts);
768
769 Success &= verifier.handleDebugAbbrev();
770 if (DumpOpts.DumpType & DIDT_DebugCUIndex)
771 Success &= verifier.handleDebugCUIndex();
772 if (DumpOpts.DumpType & DIDT_DebugTUIndex)
773 Success &= verifier.handleDebugTUIndex();
774 if (DumpOpts.DumpType & DIDT_DebugInfo)
775 Success &= verifier.handleDebugInfo();
776 if (DumpOpts.DumpType & DIDT_DebugLine)
777 Success &= verifier.handleDebugLine();
778 Success &= verifier.handleAccelTables();
779 return Success;
780 }
781
fixupIndex(const DWARFObject & DObj,DWARFContext & C,DWARFUnitIndex & Index)782 void fixupIndex(const DWARFObject &DObj, DWARFContext &C,
783 DWARFUnitIndex &Index) {
784 using EntryType = DWARFUnitIndex::Entry::SectionContribution;
785 using EntryMap = DenseMap<uint32_t, EntryType>;
786 EntryMap Map;
787 if (DObj.getCUIndexSection().empty())
788 return;
789
790 uint64_t Offset = 0;
791 uint32_t TruncOffset = 0;
792 DObj.forEachInfoDWOSections([&](const DWARFSection &S) {
793 if (!(C.getParseCUTUIndexManually() ||
794 S.Data.size() >= std::numeric_limits<uint32_t>::max()))
795 return;
796
797 DWARFDataExtractor Data(DObj, S, C.isLittleEndian(), 0);
798 while (Data.isValidOffset(Offset)) {
799 DWARFUnitHeader Header;
800 if (!Header.extract(C, Data, &Offset, DWARFSectionKind::DW_SECT_INFO)) {
801 logAllUnhandledErrors(
802 createError("Failed to parse CU header in DWP file"), errs());
803 Map.clear();
804 break;
805 }
806
807 auto Iter = Map.insert({TruncOffset,
808 {Header.getOffset(), Header.getNextUnitOffset() -
809 Header.getOffset()}});
810 if (!Iter.second) {
811 logAllUnhandledErrors(
812 createError("Collision occured between for truncated offset 0x" +
813 Twine::utohexstr(TruncOffset)),
814 errs());
815 Map.clear();
816 return;
817 }
818
819 Offset = Header.getNextUnitOffset();
820 TruncOffset = Offset;
821 }
822 });
823
824 if (Map.empty())
825 return;
826
827 for (DWARFUnitIndex::Entry &E : Index.getMutableRows()) {
828 if (!E.isValid())
829 continue;
830 DWARFUnitIndex::Entry::SectionContribution &CUOff = E.getContribution();
831 auto Iter = Map.find(CUOff.getOffset());
832 if (Iter == Map.end()) {
833 logAllUnhandledErrors(createError("Could not find CU offset 0x" +
834 Twine::utohexstr(CUOff.getOffset()) +
835 " in the Map"),
836 errs());
837 break;
838 }
839 CUOff.setOffset(Iter->second.getOffset());
840 if (CUOff.getOffset() != Iter->second.getOffset())
841 logAllUnhandledErrors(createError("Length of CU in CU index doesn't "
842 "match calculated length at offset 0x" +
843 Twine::utohexstr(CUOff.getOffset())),
844 errs());
845 }
846
847 return;
848 }
849
getCUIndex()850 const DWARFUnitIndex &DWARFContext::getCUIndex() {
851 if (CUIndex)
852 return *CUIndex;
853
854 DataExtractor CUIndexData(DObj->getCUIndexSection(), isLittleEndian(), 0);
855 CUIndex = std::make_unique<DWARFUnitIndex>(DW_SECT_INFO);
856 CUIndex->parse(CUIndexData);
857 fixupIndex(*DObj, *this, *CUIndex.get());
858 return *CUIndex;
859 }
860
getTUIndex()861 const DWARFUnitIndex &DWARFContext::getTUIndex() {
862 if (TUIndex)
863 return *TUIndex;
864
865 DataExtractor TUIndexData(DObj->getTUIndexSection(), isLittleEndian(), 0);
866 TUIndex = std::make_unique<DWARFUnitIndex>(DW_SECT_EXT_TYPES);
867 bool isParseSuccessful = TUIndex->parse(TUIndexData);
868 // If we are parsing TU-index and for .debug_types section we don't need
869 // to do anything.
870 if (isParseSuccessful && TUIndex->getVersion() != 2)
871 fixupIndex(*DObj, *this, *TUIndex.get());
872 return *TUIndex;
873 }
874
getGdbIndex()875 DWARFGdbIndex &DWARFContext::getGdbIndex() {
876 if (GdbIndex)
877 return *GdbIndex;
878
879 DataExtractor GdbIndexData(DObj->getGdbIndexSection(), true /*LE*/, 0);
880 GdbIndex = std::make_unique<DWARFGdbIndex>();
881 GdbIndex->parse(GdbIndexData);
882 return *GdbIndex;
883 }
884
getDebugAbbrev()885 const DWARFDebugAbbrev *DWARFContext::getDebugAbbrev() {
886 if (Abbrev)
887 return Abbrev.get();
888
889 DataExtractor abbrData(DObj->getAbbrevSection(), isLittleEndian(), 0);
890
891 Abbrev.reset(new DWARFDebugAbbrev());
892 Abbrev->extract(abbrData);
893 return Abbrev.get();
894 }
895
getDebugAbbrevDWO()896 const DWARFDebugAbbrev *DWARFContext::getDebugAbbrevDWO() {
897 if (AbbrevDWO)
898 return AbbrevDWO.get();
899
900 DataExtractor abbrData(DObj->getAbbrevDWOSection(), isLittleEndian(), 0);
901 AbbrevDWO.reset(new DWARFDebugAbbrev());
902 AbbrevDWO->extract(abbrData);
903 return AbbrevDWO.get();
904 }
905
getDebugLoc()906 const DWARFDebugLoc *DWARFContext::getDebugLoc() {
907 if (Loc)
908 return Loc.get();
909
910 // Assume all units have the same address byte size.
911 auto LocData =
912 getNumCompileUnits()
913 ? DWARFDataExtractor(*DObj, DObj->getLocSection(), isLittleEndian(),
914 getUnitAtIndex(0)->getAddressByteSize())
915 : DWARFDataExtractor("", isLittleEndian(), 0);
916 Loc.reset(new DWARFDebugLoc(std::move(LocData)));
917 return Loc.get();
918 }
919
getDebugAranges()920 const DWARFDebugAranges *DWARFContext::getDebugAranges() {
921 if (Aranges)
922 return Aranges.get();
923
924 Aranges.reset(new DWARFDebugAranges());
925 Aranges->generate(this);
926 return Aranges.get();
927 }
928
getDebugFrame()929 Expected<const DWARFDebugFrame *> DWARFContext::getDebugFrame() {
930 if (DebugFrame)
931 return DebugFrame.get();
932
933 const DWARFSection &DS = DObj->getFrameSection();
934
935 // There's a "bug" in the DWARFv3 standard with respect to the target address
936 // size within debug frame sections. While DWARF is supposed to be independent
937 // of its container, FDEs have fields with size being "target address size",
938 // which isn't specified in DWARF in general. It's only specified for CUs, but
939 // .eh_frame can appear without a .debug_info section. Follow the example of
940 // other tools (libdwarf) and extract this from the container (ObjectFile
941 // provides this information). This problem is fixed in DWARFv4
942 // See this dwarf-discuss discussion for more details:
943 // http://lists.dwarfstd.org/htdig.cgi/dwarf-discuss-dwarfstd.org/2011-December/001173.html
944 DWARFDataExtractor DebugFrameData(*DObj, DS, isLittleEndian(),
945 DObj->getAddressSize());
946 auto DF =
947 std::make_unique<DWARFDebugFrame>(getArch(), /*IsEH=*/false, DS.Address);
948 if (Error E = DF->parse(DebugFrameData))
949 return std::move(E);
950
951 DebugFrame.swap(DF);
952 return DebugFrame.get();
953 }
954
getEHFrame()955 Expected<const DWARFDebugFrame *> DWARFContext::getEHFrame() {
956 if (EHFrame)
957 return EHFrame.get();
958
959 const DWARFSection &DS = DObj->getEHFrameSection();
960 DWARFDataExtractor DebugFrameData(*DObj, DS, isLittleEndian(),
961 DObj->getAddressSize());
962
963 auto DF =
964 std::make_unique<DWARFDebugFrame>(getArch(), /*IsEH=*/true, DS.Address);
965 if (Error E = DF->parse(DebugFrameData))
966 return std::move(E);
967 DebugFrame.swap(DF);
968 return DebugFrame.get();
969 }
970
getDebugMacro()971 const DWARFDebugMacro *DWARFContext::getDebugMacro() {
972 if (!Macro)
973 Macro = parseMacroOrMacinfo(MacroSection);
974 return Macro.get();
975 }
976
getDebugMacroDWO()977 const DWARFDebugMacro *DWARFContext::getDebugMacroDWO() {
978 if (!MacroDWO)
979 MacroDWO = parseMacroOrMacinfo(MacroDwoSection);
980 return MacroDWO.get();
981 }
982
getDebugMacinfo()983 const DWARFDebugMacro *DWARFContext::getDebugMacinfo() {
984 if (!Macinfo)
985 Macinfo = parseMacroOrMacinfo(MacinfoSection);
986 return Macinfo.get();
987 }
988
getDebugMacinfoDWO()989 const DWARFDebugMacro *DWARFContext::getDebugMacinfoDWO() {
990 if (!MacinfoDWO)
991 MacinfoDWO = parseMacroOrMacinfo(MacinfoDwoSection);
992 return MacinfoDWO.get();
993 }
994
995 template <typename T>
getAccelTable(std::unique_ptr<T> & Cache,const DWARFObject & Obj,const DWARFSection & Section,StringRef StringSection,bool IsLittleEndian)996 static T &getAccelTable(std::unique_ptr<T> &Cache, const DWARFObject &Obj,
997 const DWARFSection &Section, StringRef StringSection,
998 bool IsLittleEndian) {
999 if (Cache)
1000 return *Cache;
1001 DWARFDataExtractor AccelSection(Obj, Section, IsLittleEndian, 0);
1002 DataExtractor StrData(StringSection, IsLittleEndian, 0);
1003 Cache.reset(new T(AccelSection, StrData));
1004 if (Error E = Cache->extract())
1005 llvm::consumeError(std::move(E));
1006 return *Cache;
1007 }
1008
getDebugNames()1009 const DWARFDebugNames &DWARFContext::getDebugNames() {
1010 return getAccelTable(Names, *DObj, DObj->getNamesSection(),
1011 DObj->getStrSection(), isLittleEndian());
1012 }
1013
getAppleNames()1014 const AppleAcceleratorTable &DWARFContext::getAppleNames() {
1015 return getAccelTable(AppleNames, *DObj, DObj->getAppleNamesSection(),
1016 DObj->getStrSection(), isLittleEndian());
1017 }
1018
getAppleTypes()1019 const AppleAcceleratorTable &DWARFContext::getAppleTypes() {
1020 return getAccelTable(AppleTypes, *DObj, DObj->getAppleTypesSection(),
1021 DObj->getStrSection(), isLittleEndian());
1022 }
1023
getAppleNamespaces()1024 const AppleAcceleratorTable &DWARFContext::getAppleNamespaces() {
1025 return getAccelTable(AppleNamespaces, *DObj,
1026 DObj->getAppleNamespacesSection(),
1027 DObj->getStrSection(), isLittleEndian());
1028 }
1029
getAppleObjC()1030 const AppleAcceleratorTable &DWARFContext::getAppleObjC() {
1031 return getAccelTable(AppleObjC, *DObj, DObj->getAppleObjCSection(),
1032 DObj->getStrSection(), isLittleEndian());
1033 }
1034
1035 const DWARFDebugLine::LineTable *
getLineTableForUnit(DWARFUnit * U)1036 DWARFContext::getLineTableForUnit(DWARFUnit *U) {
1037 Expected<const DWARFDebugLine::LineTable *> ExpectedLineTable =
1038 getLineTableForUnit(U, WarningHandler);
1039 if (!ExpectedLineTable) {
1040 WarningHandler(ExpectedLineTable.takeError());
1041 return nullptr;
1042 }
1043 return *ExpectedLineTable;
1044 }
1045
getLineTableForUnit(DWARFUnit * U,function_ref<void (Error)> RecoverableErrorHandler)1046 Expected<const DWARFDebugLine::LineTable *> DWARFContext::getLineTableForUnit(
1047 DWARFUnit *U, function_ref<void(Error)> RecoverableErrorHandler) {
1048 if (!Line)
1049 Line.reset(new DWARFDebugLine);
1050
1051 auto UnitDIE = U->getUnitDIE();
1052 if (!UnitDIE)
1053 return nullptr;
1054
1055 auto Offset = toSectionOffset(UnitDIE.find(DW_AT_stmt_list));
1056 if (!Offset)
1057 return nullptr; // No line table for this compile unit.
1058
1059 uint64_t stmtOffset = *Offset + U->getLineTableOffset();
1060 // See if the line table is cached.
1061 if (const DWARFLineTable *lt = Line->getLineTable(stmtOffset))
1062 return lt;
1063
1064 // Make sure the offset is good before we try to parse.
1065 if (stmtOffset >= U->getLineSection().Data.size())
1066 return nullptr;
1067
1068 // We have to parse it first.
1069 DWARFDataExtractor lineData(*DObj, U->getLineSection(), isLittleEndian(),
1070 U->getAddressByteSize());
1071 return Line->getOrParseLineTable(lineData, stmtOffset, *this, U,
1072 RecoverableErrorHandler);
1073 }
1074
clearLineTableForUnit(DWARFUnit * U)1075 void DWARFContext::clearLineTableForUnit(DWARFUnit *U) {
1076 if (!Line)
1077 return;
1078
1079 auto UnitDIE = U->getUnitDIE();
1080 if (!UnitDIE)
1081 return;
1082
1083 auto Offset = toSectionOffset(UnitDIE.find(DW_AT_stmt_list));
1084 if (!Offset)
1085 return;
1086
1087 uint64_t stmtOffset = *Offset + U->getLineTableOffset();
1088 Line->clearLineTable(stmtOffset);
1089 }
1090
parseNormalUnits()1091 void DWARFContext::parseNormalUnits() {
1092 if (!NormalUnits.empty())
1093 return;
1094 DObj->forEachInfoSections([&](const DWARFSection &S) {
1095 NormalUnits.addUnitsForSection(*this, S, DW_SECT_INFO);
1096 });
1097 NormalUnits.finishedInfoUnits();
1098 DObj->forEachTypesSections([&](const DWARFSection &S) {
1099 NormalUnits.addUnitsForSection(*this, S, DW_SECT_EXT_TYPES);
1100 });
1101 }
1102
parseDWOUnits(bool Lazy)1103 void DWARFContext::parseDWOUnits(bool Lazy) {
1104 if (!DWOUnits.empty())
1105 return;
1106 DObj->forEachInfoDWOSections([&](const DWARFSection &S) {
1107 DWOUnits.addUnitsForDWOSection(*this, S, DW_SECT_INFO, Lazy);
1108 });
1109 DWOUnits.finishedInfoUnits();
1110 DObj->forEachTypesDWOSections([&](const DWARFSection &S) {
1111 DWOUnits.addUnitsForDWOSection(*this, S, DW_SECT_EXT_TYPES, Lazy);
1112 });
1113 }
1114
getCompileUnitForOffset(uint64_t Offset)1115 DWARFCompileUnit *DWARFContext::getCompileUnitForOffset(uint64_t Offset) {
1116 parseNormalUnits();
1117 return dyn_cast_or_null<DWARFCompileUnit>(
1118 NormalUnits.getUnitForOffset(Offset));
1119 }
1120
getCompileUnitForAddress(uint64_t Address)1121 DWARFCompileUnit *DWARFContext::getCompileUnitForAddress(uint64_t Address) {
1122 // First, get the offset of the compile unit.
1123 uint64_t CUOffset = getDebugAranges()->findAddress(Address);
1124 // Retrieve the compile unit.
1125 if (DWARFCompileUnit *OffsetCU = getCompileUnitForOffset(CUOffset))
1126 return OffsetCU;
1127
1128 // Global variables are often not found by the above search, for one of two
1129 // reasons:
1130 // 1. .debug_aranges may not include global variables. On clang, it seems we
1131 // put the globals in the aranges, but this isn't true for gcc.
1132 // 2. Even if the global variable is in a .debug_arange, global variables
1133 // may not be captured in the [start, end) addresses described by the
1134 // parent compile unit.
1135 //
1136 // So, we walk the CU's and their child DI's manually, looking for the
1137 // specific global variable.
1138 for (std::unique_ptr<DWARFUnit> &CU : compile_units()) {
1139 if (DWARFDie Die = CU->getVariableForAddress(Address)) {
1140 return static_cast<DWARFCompileUnit *>(CU.get());
1141 }
1142 }
1143 return nullptr;
1144 }
1145
getDIEsForAddress(uint64_t Address)1146 DWARFContext::DIEsForAddress DWARFContext::getDIEsForAddress(uint64_t Address) {
1147 DIEsForAddress Result;
1148
1149 DWARFCompileUnit *CU = getCompileUnitForAddress(Address);
1150 if (!CU)
1151 return Result;
1152
1153 Result.CompileUnit = CU;
1154 Result.FunctionDIE = CU->getSubroutineForAddress(Address);
1155
1156 std::vector<DWARFDie> Worklist;
1157 Worklist.push_back(Result.FunctionDIE);
1158 while (!Worklist.empty()) {
1159 DWARFDie DIE = Worklist.back();
1160 Worklist.pop_back();
1161
1162 if (!DIE.isValid())
1163 continue;
1164
1165 if (DIE.getTag() == DW_TAG_lexical_block &&
1166 DIE.addressRangeContainsAddress(Address)) {
1167 Result.BlockDIE = DIE;
1168 break;
1169 }
1170
1171 append_range(Worklist, DIE);
1172 }
1173
1174 return Result;
1175 }
1176
1177 /// TODO: change input parameter from "uint64_t Address"
1178 /// into "SectionedAddress Address"
getFunctionNameAndStartLineForAddress(DWARFCompileUnit * CU,uint64_t Address,FunctionNameKind Kind,DILineInfoSpecifier::FileLineInfoKind FileNameKind,std::string & FunctionName,std::string & StartFile,uint32_t & StartLine,std::optional<uint64_t> & StartAddress)1179 static bool getFunctionNameAndStartLineForAddress(
1180 DWARFCompileUnit *CU, uint64_t Address, FunctionNameKind Kind,
1181 DILineInfoSpecifier::FileLineInfoKind FileNameKind,
1182 std::string &FunctionName, std::string &StartFile, uint32_t &StartLine,
1183 std::optional<uint64_t> &StartAddress) {
1184 // The address may correspond to instruction in some inlined function,
1185 // so we have to build the chain of inlined functions and take the
1186 // name of the topmost function in it.
1187 SmallVector<DWARFDie, 4> InlinedChain;
1188 CU->getInlinedChainForAddress(Address, InlinedChain);
1189 if (InlinedChain.empty())
1190 return false;
1191
1192 const DWARFDie &DIE = InlinedChain[0];
1193 bool FoundResult = false;
1194 const char *Name = nullptr;
1195 if (Kind != FunctionNameKind::None && (Name = DIE.getSubroutineName(Kind))) {
1196 FunctionName = Name;
1197 FoundResult = true;
1198 }
1199 std::string DeclFile = DIE.getDeclFile(FileNameKind);
1200 if (!DeclFile.empty()) {
1201 StartFile = DeclFile;
1202 FoundResult = true;
1203 }
1204 if (auto DeclLineResult = DIE.getDeclLine()) {
1205 StartLine = DeclLineResult;
1206 FoundResult = true;
1207 }
1208 if (auto LowPcAddr = toSectionedAddress(DIE.find(DW_AT_low_pc)))
1209 StartAddress = LowPcAddr->Address;
1210 return FoundResult;
1211 }
1212
1213 static std::optional<int64_t>
getExpressionFrameOffset(ArrayRef<uint8_t> Expr,std::optional<unsigned> FrameBaseReg)1214 getExpressionFrameOffset(ArrayRef<uint8_t> Expr,
1215 std::optional<unsigned> FrameBaseReg) {
1216 if (!Expr.empty() &&
1217 (Expr[0] == DW_OP_fbreg ||
1218 (FrameBaseReg && Expr[0] == DW_OP_breg0 + *FrameBaseReg))) {
1219 unsigned Count;
1220 int64_t Offset = decodeSLEB128(Expr.data() + 1, &Count, Expr.end());
1221 // A single DW_OP_fbreg or DW_OP_breg.
1222 if (Expr.size() == Count + 1)
1223 return Offset;
1224 // Same + DW_OP_deref (Fortran arrays look like this).
1225 if (Expr.size() == Count + 2 && Expr[Count + 1] == DW_OP_deref)
1226 return Offset;
1227 // Fallthrough. Do not accept ex. (DW_OP_breg W29, DW_OP_stack_value)
1228 }
1229 return std::nullopt;
1230 }
1231
addLocalsForDie(DWARFCompileUnit * CU,DWARFDie Subprogram,DWARFDie Die,std::vector<DILocal> & Result)1232 void DWARFContext::addLocalsForDie(DWARFCompileUnit *CU, DWARFDie Subprogram,
1233 DWARFDie Die, std::vector<DILocal> &Result) {
1234 if (Die.getTag() == DW_TAG_variable ||
1235 Die.getTag() == DW_TAG_formal_parameter) {
1236 DILocal Local;
1237 if (const char *Name = Subprogram.getSubroutineName(DINameKind::ShortName))
1238 Local.FunctionName = Name;
1239
1240 std::optional<unsigned> FrameBaseReg;
1241 if (auto FrameBase = Subprogram.find(DW_AT_frame_base))
1242 if (std::optional<ArrayRef<uint8_t>> Expr = FrameBase->getAsBlock())
1243 if (!Expr->empty() && (*Expr)[0] >= DW_OP_reg0 &&
1244 (*Expr)[0] <= DW_OP_reg31) {
1245 FrameBaseReg = (*Expr)[0] - DW_OP_reg0;
1246 }
1247
1248 if (Expected<std::vector<DWARFLocationExpression>> Loc =
1249 Die.getLocations(DW_AT_location)) {
1250 for (const auto &Entry : *Loc) {
1251 if (std::optional<int64_t> FrameOffset =
1252 getExpressionFrameOffset(Entry.Expr, FrameBaseReg)) {
1253 Local.FrameOffset = *FrameOffset;
1254 break;
1255 }
1256 }
1257 } else {
1258 // FIXME: missing DW_AT_location is OK here, but other errors should be
1259 // reported to the user.
1260 consumeError(Loc.takeError());
1261 }
1262
1263 if (auto TagOffsetAttr = Die.find(DW_AT_LLVM_tag_offset))
1264 Local.TagOffset = TagOffsetAttr->getAsUnsignedConstant();
1265
1266 if (auto Origin =
1267 Die.getAttributeValueAsReferencedDie(DW_AT_abstract_origin))
1268 Die = Origin;
1269 if (auto NameAttr = Die.find(DW_AT_name))
1270 if (std::optional<const char *> Name = dwarf::toString(*NameAttr))
1271 Local.Name = *Name;
1272 if (auto Type = Die.getAttributeValueAsReferencedDie(DW_AT_type))
1273 Local.Size = Type.getTypeSize(getCUAddrSize());
1274 if (auto DeclFileAttr = Die.find(DW_AT_decl_file)) {
1275 if (const auto *LT = CU->getContext().getLineTableForUnit(CU))
1276 LT->getFileNameByIndex(
1277 *DeclFileAttr->getAsUnsignedConstant(), CU->getCompilationDir(),
1278 DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath,
1279 Local.DeclFile);
1280 }
1281 if (auto DeclLineAttr = Die.find(DW_AT_decl_line))
1282 Local.DeclLine = *DeclLineAttr->getAsUnsignedConstant();
1283
1284 Result.push_back(Local);
1285 return;
1286 }
1287
1288 if (Die.getTag() == DW_TAG_inlined_subroutine)
1289 if (auto Origin =
1290 Die.getAttributeValueAsReferencedDie(DW_AT_abstract_origin))
1291 Subprogram = Origin;
1292
1293 for (auto Child : Die)
1294 addLocalsForDie(CU, Subprogram, Child, Result);
1295 }
1296
1297 std::vector<DILocal>
getLocalsForAddress(object::SectionedAddress Address)1298 DWARFContext::getLocalsForAddress(object::SectionedAddress Address) {
1299 std::vector<DILocal> Result;
1300 DWARFCompileUnit *CU = getCompileUnitForAddress(Address.Address);
1301 if (!CU)
1302 return Result;
1303
1304 DWARFDie Subprogram = CU->getSubroutineForAddress(Address.Address);
1305 if (Subprogram.isValid())
1306 addLocalsForDie(CU, Subprogram, Subprogram, Result);
1307 return Result;
1308 }
1309
getLineInfoForAddress(object::SectionedAddress Address,DILineInfoSpecifier Spec)1310 DILineInfo DWARFContext::getLineInfoForAddress(object::SectionedAddress Address,
1311 DILineInfoSpecifier Spec) {
1312 DILineInfo Result;
1313 DWARFCompileUnit *CU = getCompileUnitForAddress(Address.Address);
1314 if (!CU)
1315 return Result;
1316
1317 getFunctionNameAndStartLineForAddress(
1318 CU, Address.Address, Spec.FNKind, Spec.FLIKind, Result.FunctionName,
1319 Result.StartFileName, Result.StartLine, Result.StartAddress);
1320 if (Spec.FLIKind != FileLineInfoKind::None) {
1321 if (const DWARFLineTable *LineTable = getLineTableForUnit(CU)) {
1322 LineTable->getFileLineInfoForAddress(
1323 {Address.Address, Address.SectionIndex}, CU->getCompilationDir(),
1324 Spec.FLIKind, Result);
1325 }
1326 }
1327
1328 return Result;
1329 }
1330
1331 DILineInfo
getLineInfoForDataAddress(object::SectionedAddress Address)1332 DWARFContext::getLineInfoForDataAddress(object::SectionedAddress Address) {
1333 DILineInfo Result;
1334 DWARFCompileUnit *CU = getCompileUnitForAddress(Address.Address);
1335 if (!CU)
1336 return Result;
1337
1338 if (DWARFDie Die = CU->getVariableForAddress(Address.Address)) {
1339 Result.FileName = Die.getDeclFile(FileLineInfoKind::AbsoluteFilePath);
1340 Result.Line = Die.getDeclLine();
1341 }
1342
1343 return Result;
1344 }
1345
getLineInfoForAddressRange(object::SectionedAddress Address,uint64_t Size,DILineInfoSpecifier Spec)1346 DILineInfoTable DWARFContext::getLineInfoForAddressRange(
1347 object::SectionedAddress Address, uint64_t Size, DILineInfoSpecifier Spec) {
1348 DILineInfoTable Lines;
1349 DWARFCompileUnit *CU = getCompileUnitForAddress(Address.Address);
1350 if (!CU)
1351 return Lines;
1352
1353 uint32_t StartLine = 0;
1354 std::string StartFileName;
1355 std::string FunctionName(DILineInfo::BadString);
1356 std::optional<uint64_t> StartAddress;
1357 getFunctionNameAndStartLineForAddress(CU, Address.Address, Spec.FNKind,
1358 Spec.FLIKind, FunctionName,
1359 StartFileName, StartLine, StartAddress);
1360
1361 // If the Specifier says we don't need FileLineInfo, just
1362 // return the top-most function at the starting address.
1363 if (Spec.FLIKind == FileLineInfoKind::None) {
1364 DILineInfo Result;
1365 Result.FunctionName = FunctionName;
1366 Result.StartFileName = StartFileName;
1367 Result.StartLine = StartLine;
1368 Result.StartAddress = StartAddress;
1369 Lines.push_back(std::make_pair(Address.Address, Result));
1370 return Lines;
1371 }
1372
1373 const DWARFLineTable *LineTable = getLineTableForUnit(CU);
1374
1375 // Get the index of row we're looking for in the line table.
1376 std::vector<uint32_t> RowVector;
1377 if (!LineTable->lookupAddressRange({Address.Address, Address.SectionIndex},
1378 Size, RowVector)) {
1379 return Lines;
1380 }
1381
1382 for (uint32_t RowIndex : RowVector) {
1383 // Take file number and line/column from the row.
1384 const DWARFDebugLine::Row &Row = LineTable->Rows[RowIndex];
1385 DILineInfo Result;
1386 LineTable->getFileNameByIndex(Row.File, CU->getCompilationDir(),
1387 Spec.FLIKind, Result.FileName);
1388 Result.FunctionName = FunctionName;
1389 Result.Line = Row.Line;
1390 Result.Column = Row.Column;
1391 Result.StartFileName = StartFileName;
1392 Result.StartLine = StartLine;
1393 Result.StartAddress = StartAddress;
1394 Lines.push_back(std::make_pair(Row.Address.Address, Result));
1395 }
1396
1397 return Lines;
1398 }
1399
1400 DIInliningInfo
getInliningInfoForAddress(object::SectionedAddress Address,DILineInfoSpecifier Spec)1401 DWARFContext::getInliningInfoForAddress(object::SectionedAddress Address,
1402 DILineInfoSpecifier Spec) {
1403 DIInliningInfo InliningInfo;
1404
1405 DWARFCompileUnit *CU = getCompileUnitForAddress(Address.Address);
1406 if (!CU)
1407 return InliningInfo;
1408
1409 const DWARFLineTable *LineTable = nullptr;
1410 SmallVector<DWARFDie, 4> InlinedChain;
1411 CU->getInlinedChainForAddress(Address.Address, InlinedChain);
1412 if (InlinedChain.size() == 0) {
1413 // If there is no DIE for address (e.g. it is in unavailable .dwo file),
1414 // try to at least get file/line info from symbol table.
1415 if (Spec.FLIKind != FileLineInfoKind::None) {
1416 DILineInfo Frame;
1417 LineTable = getLineTableForUnit(CU);
1418 if (LineTable && LineTable->getFileLineInfoForAddress(
1419 {Address.Address, Address.SectionIndex},
1420 CU->getCompilationDir(), Spec.FLIKind, Frame))
1421 InliningInfo.addFrame(Frame);
1422 }
1423 return InliningInfo;
1424 }
1425
1426 uint32_t CallFile = 0, CallLine = 0, CallColumn = 0, CallDiscriminator = 0;
1427 for (uint32_t i = 0, n = InlinedChain.size(); i != n; i++) {
1428 DWARFDie &FunctionDIE = InlinedChain[i];
1429 DILineInfo Frame;
1430 // Get function name if necessary.
1431 if (const char *Name = FunctionDIE.getSubroutineName(Spec.FNKind))
1432 Frame.FunctionName = Name;
1433 if (auto DeclLineResult = FunctionDIE.getDeclLine())
1434 Frame.StartLine = DeclLineResult;
1435 Frame.StartFileName = FunctionDIE.getDeclFile(Spec.FLIKind);
1436 if (auto LowPcAddr = toSectionedAddress(FunctionDIE.find(DW_AT_low_pc)))
1437 Frame.StartAddress = LowPcAddr->Address;
1438 if (Spec.FLIKind != FileLineInfoKind::None) {
1439 if (i == 0) {
1440 // For the topmost frame, initialize the line table of this
1441 // compile unit and fetch file/line info from it.
1442 LineTable = getLineTableForUnit(CU);
1443 // For the topmost routine, get file/line info from line table.
1444 if (LineTable)
1445 LineTable->getFileLineInfoForAddress(
1446 {Address.Address, Address.SectionIndex}, CU->getCompilationDir(),
1447 Spec.FLIKind, Frame);
1448 } else {
1449 // Otherwise, use call file, call line and call column from
1450 // previous DIE in inlined chain.
1451 if (LineTable)
1452 LineTable->getFileNameByIndex(CallFile, CU->getCompilationDir(),
1453 Spec.FLIKind, Frame.FileName);
1454 Frame.Line = CallLine;
1455 Frame.Column = CallColumn;
1456 Frame.Discriminator = CallDiscriminator;
1457 }
1458 // Get call file/line/column of a current DIE.
1459 if (i + 1 < n) {
1460 FunctionDIE.getCallerFrame(CallFile, CallLine, CallColumn,
1461 CallDiscriminator);
1462 }
1463 }
1464 InliningInfo.addFrame(Frame);
1465 }
1466 return InliningInfo;
1467 }
1468
1469 std::shared_ptr<DWARFContext>
getDWOContext(StringRef AbsolutePath)1470 DWARFContext::getDWOContext(StringRef AbsolutePath) {
1471 if (auto S = DWP.lock()) {
1472 DWARFContext *Ctxt = S->Context.get();
1473 return std::shared_ptr<DWARFContext>(std::move(S), Ctxt);
1474 }
1475
1476 std::weak_ptr<DWOFile> *Entry = &DWOFiles[AbsolutePath];
1477
1478 if (auto S = Entry->lock()) {
1479 DWARFContext *Ctxt = S->Context.get();
1480 return std::shared_ptr<DWARFContext>(std::move(S), Ctxt);
1481 }
1482
1483 Expected<OwningBinary<ObjectFile>> Obj = [&] {
1484 if (!CheckedForDWP) {
1485 SmallString<128> DWPName;
1486 auto Obj = object::ObjectFile::createObjectFile(
1487 this->DWPName.empty()
1488 ? (DObj->getFileName() + ".dwp").toStringRef(DWPName)
1489 : StringRef(this->DWPName));
1490 if (Obj) {
1491 Entry = &DWP;
1492 return Obj;
1493 } else {
1494 CheckedForDWP = true;
1495 // TODO: Should this error be handled (maybe in a high verbosity mode)
1496 // before falling back to .dwo files?
1497 consumeError(Obj.takeError());
1498 }
1499 }
1500
1501 return object::ObjectFile::createObjectFile(AbsolutePath);
1502 }();
1503
1504 if (!Obj) {
1505 // TODO: Actually report errors helpfully.
1506 consumeError(Obj.takeError());
1507 return nullptr;
1508 }
1509
1510 auto S = std::make_shared<DWOFile>();
1511 S->File = std::move(Obj.get());
1512 S->Context = DWARFContext::create(*S->File.getBinary(),
1513 ProcessDebugRelocations::Ignore);
1514 *Entry = S;
1515 auto *Ctxt = S->Context.get();
1516 return std::shared_ptr<DWARFContext>(std::move(S), Ctxt);
1517 }
1518
createError(const Twine & Reason,llvm::Error E)1519 static Error createError(const Twine &Reason, llvm::Error E) {
1520 return make_error<StringError>(Reason + toString(std::move(E)),
1521 inconvertibleErrorCode());
1522 }
1523
1524 /// SymInfo contains information about symbol: it's address
1525 /// and section index which is -1LL for absolute symbols.
1526 struct SymInfo {
1527 uint64_t Address;
1528 uint64_t SectionIndex;
1529 };
1530
1531 /// Returns the address of symbol relocation used against and a section index.
1532 /// Used for futher relocations computation. Symbol's section load address is
getSymbolInfo(const object::ObjectFile & Obj,const RelocationRef & Reloc,const LoadedObjectInfo * L,std::map<SymbolRef,SymInfo> & Cache)1533 static Expected<SymInfo> getSymbolInfo(const object::ObjectFile &Obj,
1534 const RelocationRef &Reloc,
1535 const LoadedObjectInfo *L,
1536 std::map<SymbolRef, SymInfo> &Cache) {
1537 SymInfo Ret = {0, (uint64_t)-1LL};
1538 object::section_iterator RSec = Obj.section_end();
1539 object::symbol_iterator Sym = Reloc.getSymbol();
1540
1541 std::map<SymbolRef, SymInfo>::iterator CacheIt = Cache.end();
1542 // First calculate the address of the symbol or section as it appears
1543 // in the object file
1544 if (Sym != Obj.symbol_end()) {
1545 bool New;
1546 std::tie(CacheIt, New) = Cache.insert({*Sym, {0, 0}});
1547 if (!New)
1548 return CacheIt->second;
1549
1550 Expected<uint64_t> SymAddrOrErr = Sym->getAddress();
1551 if (!SymAddrOrErr)
1552 return createError("failed to compute symbol address: ",
1553 SymAddrOrErr.takeError());
1554
1555 // Also remember what section this symbol is in for later
1556 auto SectOrErr = Sym->getSection();
1557 if (!SectOrErr)
1558 return createError("failed to get symbol section: ",
1559 SectOrErr.takeError());
1560
1561 RSec = *SectOrErr;
1562 Ret.Address = *SymAddrOrErr;
1563 } else if (auto *MObj = dyn_cast<MachOObjectFile>(&Obj)) {
1564 RSec = MObj->getRelocationSection(Reloc.getRawDataRefImpl());
1565 Ret.Address = RSec->getAddress();
1566 }
1567
1568 if (RSec != Obj.section_end())
1569 Ret.SectionIndex = RSec->getIndex();
1570
1571 // If we are given load addresses for the sections, we need to adjust:
1572 // SymAddr = (Address of Symbol Or Section in File) -
1573 // (Address of Section in File) +
1574 // (Load Address of Section)
1575 // RSec is now either the section being targeted or the section
1576 // containing the symbol being targeted. In either case,
1577 // we need to perform the same computation.
1578 if (L && RSec != Obj.section_end())
1579 if (uint64_t SectionLoadAddress = L->getSectionLoadAddress(*RSec))
1580 Ret.Address += SectionLoadAddress - RSec->getAddress();
1581
1582 if (CacheIt != Cache.end())
1583 CacheIt->second = Ret;
1584
1585 return Ret;
1586 }
1587
isRelocScattered(const object::ObjectFile & Obj,const RelocationRef & Reloc)1588 static bool isRelocScattered(const object::ObjectFile &Obj,
1589 const RelocationRef &Reloc) {
1590 const MachOObjectFile *MachObj = dyn_cast<MachOObjectFile>(&Obj);
1591 if (!MachObj)
1592 return false;
1593 // MachO also has relocations that point to sections and
1594 // scattered relocations.
1595 auto RelocInfo = MachObj->getRelocation(Reloc.getRawDataRefImpl());
1596 return MachObj->isRelocationScattered(RelocInfo);
1597 }
1598
1599 namespace {
1600 struct DWARFSectionMap final : public DWARFSection {
1601 RelocAddrMap Relocs;
1602 };
1603
1604 class DWARFObjInMemory final : public DWARFObject {
1605 bool IsLittleEndian;
1606 uint8_t AddressSize;
1607 StringRef FileName;
1608 const object::ObjectFile *Obj = nullptr;
1609 std::vector<SectionName> SectionNames;
1610
1611 using InfoSectionMap = MapVector<object::SectionRef, DWARFSectionMap,
1612 std::map<object::SectionRef, unsigned>>;
1613
1614 InfoSectionMap InfoSections;
1615 InfoSectionMap TypesSections;
1616 InfoSectionMap InfoDWOSections;
1617 InfoSectionMap TypesDWOSections;
1618
1619 DWARFSectionMap LocSection;
1620 DWARFSectionMap LoclistsSection;
1621 DWARFSectionMap LoclistsDWOSection;
1622 DWARFSectionMap LineSection;
1623 DWARFSectionMap RangesSection;
1624 DWARFSectionMap RnglistsSection;
1625 DWARFSectionMap StrOffsetsSection;
1626 DWARFSectionMap LineDWOSection;
1627 DWARFSectionMap FrameSection;
1628 DWARFSectionMap EHFrameSection;
1629 DWARFSectionMap LocDWOSection;
1630 DWARFSectionMap StrOffsetsDWOSection;
1631 DWARFSectionMap RangesDWOSection;
1632 DWARFSectionMap RnglistsDWOSection;
1633 DWARFSectionMap AddrSection;
1634 DWARFSectionMap AppleNamesSection;
1635 DWARFSectionMap AppleTypesSection;
1636 DWARFSectionMap AppleNamespacesSection;
1637 DWARFSectionMap AppleObjCSection;
1638 DWARFSectionMap NamesSection;
1639 DWARFSectionMap PubnamesSection;
1640 DWARFSectionMap PubtypesSection;
1641 DWARFSectionMap GnuPubnamesSection;
1642 DWARFSectionMap GnuPubtypesSection;
1643 DWARFSectionMap MacroSection;
1644
mapNameToDWARFSection(StringRef Name)1645 DWARFSectionMap *mapNameToDWARFSection(StringRef Name) {
1646 return StringSwitch<DWARFSectionMap *>(Name)
1647 .Case("debug_loc", &LocSection)
1648 .Case("debug_loclists", &LoclistsSection)
1649 .Case("debug_loclists.dwo", &LoclistsDWOSection)
1650 .Case("debug_line", &LineSection)
1651 .Case("debug_frame", &FrameSection)
1652 .Case("eh_frame", &EHFrameSection)
1653 .Case("debug_str_offsets", &StrOffsetsSection)
1654 .Case("debug_ranges", &RangesSection)
1655 .Case("debug_rnglists", &RnglistsSection)
1656 .Case("debug_loc.dwo", &LocDWOSection)
1657 .Case("debug_line.dwo", &LineDWOSection)
1658 .Case("debug_names", &NamesSection)
1659 .Case("debug_rnglists.dwo", &RnglistsDWOSection)
1660 .Case("debug_str_offsets.dwo", &StrOffsetsDWOSection)
1661 .Case("debug_addr", &AddrSection)
1662 .Case("apple_names", &AppleNamesSection)
1663 .Case("debug_pubnames", &PubnamesSection)
1664 .Case("debug_pubtypes", &PubtypesSection)
1665 .Case("debug_gnu_pubnames", &GnuPubnamesSection)
1666 .Case("debug_gnu_pubtypes", &GnuPubtypesSection)
1667 .Case("apple_types", &AppleTypesSection)
1668 .Case("apple_namespaces", &AppleNamespacesSection)
1669 .Case("apple_namespac", &AppleNamespacesSection)
1670 .Case("apple_objc", &AppleObjCSection)
1671 .Case("debug_macro", &MacroSection)
1672 .Default(nullptr);
1673 }
1674
1675 StringRef AbbrevSection;
1676 StringRef ArangesSection;
1677 StringRef StrSection;
1678 StringRef MacinfoSection;
1679 StringRef MacinfoDWOSection;
1680 StringRef MacroDWOSection;
1681 StringRef AbbrevDWOSection;
1682 StringRef StrDWOSection;
1683 StringRef CUIndexSection;
1684 StringRef GdbIndexSection;
1685 StringRef TUIndexSection;
1686 StringRef LineStrSection;
1687
1688 // A deque holding section data whose iterators are not invalidated when
1689 // new decompressed sections are inserted at the end.
1690 std::deque<SmallString<0>> UncompressedSections;
1691
mapSectionToMember(StringRef Name)1692 StringRef *mapSectionToMember(StringRef Name) {
1693 if (DWARFSection *Sec = mapNameToDWARFSection(Name))
1694 return &Sec->Data;
1695 return StringSwitch<StringRef *>(Name)
1696 .Case("debug_abbrev", &AbbrevSection)
1697 .Case("debug_aranges", &ArangesSection)
1698 .Case("debug_str", &StrSection)
1699 .Case("debug_macinfo", &MacinfoSection)
1700 .Case("debug_macinfo.dwo", &MacinfoDWOSection)
1701 .Case("debug_macro.dwo", &MacroDWOSection)
1702 .Case("debug_abbrev.dwo", &AbbrevDWOSection)
1703 .Case("debug_str.dwo", &StrDWOSection)
1704 .Case("debug_cu_index", &CUIndexSection)
1705 .Case("debug_tu_index", &TUIndexSection)
1706 .Case("gdb_index", &GdbIndexSection)
1707 .Case("debug_line_str", &LineStrSection)
1708 // Any more debug info sections go here.
1709 .Default(nullptr);
1710 }
1711
1712 /// If Sec is compressed section, decompresses and updates its contents
1713 /// provided by Data. Otherwise leaves it unchanged.
maybeDecompress(const object::SectionRef & Sec,StringRef Name,StringRef & Data)1714 Error maybeDecompress(const object::SectionRef &Sec, StringRef Name,
1715 StringRef &Data) {
1716 if (!Sec.isCompressed())
1717 return Error::success();
1718
1719 Expected<Decompressor> Decompressor =
1720 Decompressor::create(Name, Data, IsLittleEndian, AddressSize == 8);
1721 if (!Decompressor)
1722 return Decompressor.takeError();
1723
1724 SmallString<0> Out;
1725 if (auto Err = Decompressor->resizeAndDecompress(Out))
1726 return Err;
1727
1728 UncompressedSections.push_back(std::move(Out));
1729 Data = UncompressedSections.back();
1730
1731 return Error::success();
1732 }
1733
1734 public:
DWARFObjInMemory(const StringMap<std::unique_ptr<MemoryBuffer>> & Sections,uint8_t AddrSize,bool IsLittleEndian)1735 DWARFObjInMemory(const StringMap<std::unique_ptr<MemoryBuffer>> &Sections,
1736 uint8_t AddrSize, bool IsLittleEndian)
1737 : IsLittleEndian(IsLittleEndian) {
1738 for (const auto &SecIt : Sections) {
1739 if (StringRef *SectionData = mapSectionToMember(SecIt.first()))
1740 *SectionData = SecIt.second->getBuffer();
1741 else if (SecIt.first() == "debug_info")
1742 // Find debug_info and debug_types data by section rather than name as
1743 // there are multiple, comdat grouped, of these sections.
1744 InfoSections[SectionRef()].Data = SecIt.second->getBuffer();
1745 else if (SecIt.first() == "debug_info.dwo")
1746 InfoDWOSections[SectionRef()].Data = SecIt.second->getBuffer();
1747 else if (SecIt.first() == "debug_types")
1748 TypesSections[SectionRef()].Data = SecIt.second->getBuffer();
1749 else if (SecIt.first() == "debug_types.dwo")
1750 TypesDWOSections[SectionRef()].Data = SecIt.second->getBuffer();
1751 }
1752 }
DWARFObjInMemory(const object::ObjectFile & Obj,const LoadedObjectInfo * L,function_ref<void (Error)> HandleError,function_ref<void (Error)> HandleWarning,DWARFContext::ProcessDebugRelocations RelocAction)1753 DWARFObjInMemory(const object::ObjectFile &Obj, const LoadedObjectInfo *L,
1754 function_ref<void(Error)> HandleError,
1755 function_ref<void(Error)> HandleWarning,
1756 DWARFContext::ProcessDebugRelocations RelocAction)
1757 : IsLittleEndian(Obj.isLittleEndian()),
1758 AddressSize(Obj.getBytesInAddress()), FileName(Obj.getFileName()),
1759 Obj(&Obj) {
1760
1761 StringMap<unsigned> SectionAmountMap;
1762 for (const SectionRef &Section : Obj.sections()) {
1763 StringRef Name;
1764 if (auto NameOrErr = Section.getName())
1765 Name = *NameOrErr;
1766 else
1767 consumeError(NameOrErr.takeError());
1768
1769 ++SectionAmountMap[Name];
1770 SectionNames.push_back({ Name, true });
1771
1772 // Skip BSS and Virtual sections, they aren't interesting.
1773 if (Section.isBSS() || Section.isVirtual())
1774 continue;
1775
1776 // Skip sections stripped by dsymutil.
1777 if (Section.isStripped())
1778 continue;
1779
1780 StringRef Data;
1781 Expected<section_iterator> SecOrErr = Section.getRelocatedSection();
1782 if (!SecOrErr) {
1783 HandleError(createError("failed to get relocated section: ",
1784 SecOrErr.takeError()));
1785 continue;
1786 }
1787
1788 // Try to obtain an already relocated version of this section.
1789 // Else use the unrelocated section from the object file. We'll have to
1790 // apply relocations ourselves later.
1791 section_iterator RelocatedSection =
1792 Obj.isRelocatableObject() ? *SecOrErr : Obj.section_end();
1793 if (!L || !L->getLoadedSectionContents(*RelocatedSection, Data)) {
1794 Expected<StringRef> E = Section.getContents();
1795 if (E)
1796 Data = *E;
1797 else
1798 // maybeDecompress below will error.
1799 consumeError(E.takeError());
1800 }
1801
1802 if (auto Err = maybeDecompress(Section, Name, Data)) {
1803 HandleError(createError("failed to decompress '" + Name + "', ",
1804 std::move(Err)));
1805 continue;
1806 }
1807
1808 // Compressed sections names in GNU style starts from ".z",
1809 // at this point section is decompressed and we drop compression prefix.
1810 Name = Name.substr(
1811 Name.find_first_not_of("._z")); // Skip ".", "z" and "_" prefixes.
1812
1813 // Map platform specific debug section names to DWARF standard section
1814 // names.
1815 Name = Obj.mapDebugSectionName(Name);
1816
1817 if (StringRef *SectionData = mapSectionToMember(Name)) {
1818 *SectionData = Data;
1819 if (Name == "debug_ranges") {
1820 // FIXME: Use the other dwo range section when we emit it.
1821 RangesDWOSection.Data = Data;
1822 } else if (Name == "debug_frame" || Name == "eh_frame") {
1823 if (DWARFSection *S = mapNameToDWARFSection(Name))
1824 S->Address = Section.getAddress();
1825 }
1826 } else if (InfoSectionMap *Sections =
1827 StringSwitch<InfoSectionMap *>(Name)
1828 .Case("debug_info", &InfoSections)
1829 .Case("debug_info.dwo", &InfoDWOSections)
1830 .Case("debug_types", &TypesSections)
1831 .Case("debug_types.dwo", &TypesDWOSections)
1832 .Default(nullptr)) {
1833 // Find debug_info and debug_types data by section rather than name as
1834 // there are multiple, comdat grouped, of these sections.
1835 DWARFSectionMap &S = (*Sections)[Section];
1836 S.Data = Data;
1837 }
1838
1839 if (RelocatedSection != Obj.section_end() && Name.contains(".dwo"))
1840 HandleWarning(
1841 createError("Unexpected relocations for dwo section " + Name));
1842
1843 if (RelocatedSection == Obj.section_end() ||
1844 (RelocAction == DWARFContext::ProcessDebugRelocations::Ignore))
1845 continue;
1846
1847 StringRef RelSecName;
1848 if (auto NameOrErr = RelocatedSection->getName())
1849 RelSecName = *NameOrErr;
1850 else
1851 consumeError(NameOrErr.takeError());
1852
1853 // If the section we're relocating was relocated already by the JIT,
1854 // then we used the relocated version above, so we do not need to process
1855 // relocations for it now.
1856 StringRef RelSecData;
1857 if (L && L->getLoadedSectionContents(*RelocatedSection, RelSecData))
1858 continue;
1859
1860 // In Mach-o files, the relocations do not need to be applied if
1861 // there is no load offset to apply. The value read at the
1862 // relocation point already factors in the section address
1863 // (actually applying the relocations will produce wrong results
1864 // as the section address will be added twice).
1865 if (!L && isa<MachOObjectFile>(&Obj))
1866 continue;
1867
1868 RelSecName = RelSecName.substr(
1869 RelSecName.find_first_not_of("._z")); // Skip . and _ prefixes.
1870
1871 // TODO: Add support for relocations in other sections as needed.
1872 // Record relocations for the debug_info and debug_line sections.
1873 DWARFSectionMap *Sec = mapNameToDWARFSection(RelSecName);
1874 RelocAddrMap *Map = Sec ? &Sec->Relocs : nullptr;
1875 if (!Map) {
1876 // Find debug_info and debug_types relocs by section rather than name
1877 // as there are multiple, comdat grouped, of these sections.
1878 if (RelSecName == "debug_info")
1879 Map = &static_cast<DWARFSectionMap &>(InfoSections[*RelocatedSection])
1880 .Relocs;
1881 else if (RelSecName == "debug_types")
1882 Map =
1883 &static_cast<DWARFSectionMap &>(TypesSections[*RelocatedSection])
1884 .Relocs;
1885 else
1886 continue;
1887 }
1888
1889 if (Section.relocation_begin() == Section.relocation_end())
1890 continue;
1891
1892 // Symbol to [address, section index] cache mapping.
1893 std::map<SymbolRef, SymInfo> AddrCache;
1894 SupportsRelocation Supports;
1895 RelocationResolver Resolver;
1896 std::tie(Supports, Resolver) = getRelocationResolver(Obj);
1897 for (const RelocationRef &Reloc : Section.relocations()) {
1898 // FIXME: it's not clear how to correctly handle scattered
1899 // relocations.
1900 if (isRelocScattered(Obj, Reloc))
1901 continue;
1902
1903 Expected<SymInfo> SymInfoOrErr =
1904 getSymbolInfo(Obj, Reloc, L, AddrCache);
1905 if (!SymInfoOrErr) {
1906 HandleError(SymInfoOrErr.takeError());
1907 continue;
1908 }
1909
1910 // Check if Resolver can handle this relocation type early so as not to
1911 // handle invalid cases in DWARFDataExtractor.
1912 //
1913 // TODO Don't store Resolver in every RelocAddrEntry.
1914 if (Supports && Supports(Reloc.getType())) {
1915 auto I = Map->try_emplace(
1916 Reloc.getOffset(),
1917 RelocAddrEntry{
1918 SymInfoOrErr->SectionIndex, Reloc, SymInfoOrErr->Address,
1919 std::optional<object::RelocationRef>(), 0, Resolver});
1920 // If we didn't successfully insert that's because we already had a
1921 // relocation for that offset. Store it as a second relocation in the
1922 // same RelocAddrEntry instead.
1923 if (!I.second) {
1924 RelocAddrEntry &entry = I.first->getSecond();
1925 if (entry.Reloc2) {
1926 HandleError(createError(
1927 "At most two relocations per offset are supported"));
1928 }
1929 entry.Reloc2 = Reloc;
1930 entry.SymbolValue2 = SymInfoOrErr->Address;
1931 }
1932 } else {
1933 SmallString<32> Type;
1934 Reloc.getTypeName(Type);
1935 // FIXME: Support more relocations & change this to an error
1936 HandleWarning(
1937 createError("failed to compute relocation: " + Type + ", ",
1938 errorCodeToError(object_error::parse_failed)));
1939 }
1940 }
1941 }
1942
1943 for (SectionName &S : SectionNames)
1944 if (SectionAmountMap[S.Name] > 1)
1945 S.IsNameUnique = false;
1946 }
1947
find(const DWARFSection & S,uint64_t Pos) const1948 std::optional<RelocAddrEntry> find(const DWARFSection &S,
1949 uint64_t Pos) const override {
1950 auto &Sec = static_cast<const DWARFSectionMap &>(S);
1951 RelocAddrMap::const_iterator AI = Sec.Relocs.find(Pos);
1952 if (AI == Sec.Relocs.end())
1953 return std::nullopt;
1954 return AI->second;
1955 }
1956
getFile() const1957 const object::ObjectFile *getFile() const override { return Obj; }
1958
getSectionNames() const1959 ArrayRef<SectionName> getSectionNames() const override {
1960 return SectionNames;
1961 }
1962
isLittleEndian() const1963 bool isLittleEndian() const override { return IsLittleEndian; }
getAbbrevDWOSection() const1964 StringRef getAbbrevDWOSection() const override { return AbbrevDWOSection; }
getLineDWOSection() const1965 const DWARFSection &getLineDWOSection() const override {
1966 return LineDWOSection;
1967 }
getLocDWOSection() const1968 const DWARFSection &getLocDWOSection() const override {
1969 return LocDWOSection;
1970 }
getStrDWOSection() const1971 StringRef getStrDWOSection() const override { return StrDWOSection; }
getStrOffsetsDWOSection() const1972 const DWARFSection &getStrOffsetsDWOSection() const override {
1973 return StrOffsetsDWOSection;
1974 }
getRangesDWOSection() const1975 const DWARFSection &getRangesDWOSection() const override {
1976 return RangesDWOSection;
1977 }
getRnglistsDWOSection() const1978 const DWARFSection &getRnglistsDWOSection() const override {
1979 return RnglistsDWOSection;
1980 }
getLoclistsDWOSection() const1981 const DWARFSection &getLoclistsDWOSection() const override {
1982 return LoclistsDWOSection;
1983 }
getAddrSection() const1984 const DWARFSection &getAddrSection() const override { return AddrSection; }
getCUIndexSection() const1985 StringRef getCUIndexSection() const override { return CUIndexSection; }
getGdbIndexSection() const1986 StringRef getGdbIndexSection() const override { return GdbIndexSection; }
getTUIndexSection() const1987 StringRef getTUIndexSection() const override { return TUIndexSection; }
1988
1989 // DWARF v5
getStrOffsetsSection() const1990 const DWARFSection &getStrOffsetsSection() const override {
1991 return StrOffsetsSection;
1992 }
getLineStrSection() const1993 StringRef getLineStrSection() const override { return LineStrSection; }
1994
1995 // Sections for DWARF5 split dwarf proposal.
forEachInfoDWOSections(function_ref<void (const DWARFSection &)> F) const1996 void forEachInfoDWOSections(
1997 function_ref<void(const DWARFSection &)> F) const override {
1998 for (auto &P : InfoDWOSections)
1999 F(P.second);
2000 }
forEachTypesDWOSections(function_ref<void (const DWARFSection &)> F) const2001 void forEachTypesDWOSections(
2002 function_ref<void(const DWARFSection &)> F) const override {
2003 for (auto &P : TypesDWOSections)
2004 F(P.second);
2005 }
2006
getAbbrevSection() const2007 StringRef getAbbrevSection() const override { return AbbrevSection; }
getLocSection() const2008 const DWARFSection &getLocSection() const override { return LocSection; }
getLoclistsSection() const2009 const DWARFSection &getLoclistsSection() const override { return LoclistsSection; }
getArangesSection() const2010 StringRef getArangesSection() const override { return ArangesSection; }
getFrameSection() const2011 const DWARFSection &getFrameSection() const override {
2012 return FrameSection;
2013 }
getEHFrameSection() const2014 const DWARFSection &getEHFrameSection() const override {
2015 return EHFrameSection;
2016 }
getLineSection() const2017 const DWARFSection &getLineSection() const override { return LineSection; }
getStrSection() const2018 StringRef getStrSection() const override { return StrSection; }
getRangesSection() const2019 const DWARFSection &getRangesSection() const override { return RangesSection; }
getRnglistsSection() const2020 const DWARFSection &getRnglistsSection() const override {
2021 return RnglistsSection;
2022 }
getMacroSection() const2023 const DWARFSection &getMacroSection() const override { return MacroSection; }
getMacroDWOSection() const2024 StringRef getMacroDWOSection() const override { return MacroDWOSection; }
getMacinfoSection() const2025 StringRef getMacinfoSection() const override { return MacinfoSection; }
getMacinfoDWOSection() const2026 StringRef getMacinfoDWOSection() const override { return MacinfoDWOSection; }
getPubnamesSection() const2027 const DWARFSection &getPubnamesSection() const override { return PubnamesSection; }
getPubtypesSection() const2028 const DWARFSection &getPubtypesSection() const override { return PubtypesSection; }
getGnuPubnamesSection() const2029 const DWARFSection &getGnuPubnamesSection() const override {
2030 return GnuPubnamesSection;
2031 }
getGnuPubtypesSection() const2032 const DWARFSection &getGnuPubtypesSection() const override {
2033 return GnuPubtypesSection;
2034 }
getAppleNamesSection() const2035 const DWARFSection &getAppleNamesSection() const override {
2036 return AppleNamesSection;
2037 }
getAppleTypesSection() const2038 const DWARFSection &getAppleTypesSection() const override {
2039 return AppleTypesSection;
2040 }
getAppleNamespacesSection() const2041 const DWARFSection &getAppleNamespacesSection() const override {
2042 return AppleNamespacesSection;
2043 }
getAppleObjCSection() const2044 const DWARFSection &getAppleObjCSection() const override {
2045 return AppleObjCSection;
2046 }
getNamesSection() const2047 const DWARFSection &getNamesSection() const override {
2048 return NamesSection;
2049 }
2050
getFileName() const2051 StringRef getFileName() const override { return FileName; }
getAddressSize() const2052 uint8_t getAddressSize() const override { return AddressSize; }
forEachInfoSections(function_ref<void (const DWARFSection &)> F) const2053 void forEachInfoSections(
2054 function_ref<void(const DWARFSection &)> F) const override {
2055 for (auto &P : InfoSections)
2056 F(P.second);
2057 }
forEachTypesSections(function_ref<void (const DWARFSection &)> F) const2058 void forEachTypesSections(
2059 function_ref<void(const DWARFSection &)> F) const override {
2060 for (auto &P : TypesSections)
2061 F(P.second);
2062 }
2063 };
2064 } // namespace
2065
2066 std::unique_ptr<DWARFContext>
create(const object::ObjectFile & Obj,ProcessDebugRelocations RelocAction,const LoadedObjectInfo * L,std::string DWPName,std::function<void (Error)> RecoverableErrorHandler,std::function<void (Error)> WarningHandler)2067 DWARFContext::create(const object::ObjectFile &Obj,
2068 ProcessDebugRelocations RelocAction,
2069 const LoadedObjectInfo *L, std::string DWPName,
2070 std::function<void(Error)> RecoverableErrorHandler,
2071 std::function<void(Error)> WarningHandler) {
2072 auto DObj = std::make_unique<DWARFObjInMemory>(
2073 Obj, L, RecoverableErrorHandler, WarningHandler, RelocAction);
2074 return std::make_unique<DWARFContext>(std::move(DObj), std::move(DWPName),
2075 RecoverableErrorHandler,
2076 WarningHandler);
2077 }
2078
2079 std::unique_ptr<DWARFContext>
create(const StringMap<std::unique_ptr<MemoryBuffer>> & Sections,uint8_t AddrSize,bool isLittleEndian,std::function<void (Error)> RecoverableErrorHandler,std::function<void (Error)> WarningHandler)2080 DWARFContext::create(const StringMap<std::unique_ptr<MemoryBuffer>> &Sections,
2081 uint8_t AddrSize, bool isLittleEndian,
2082 std::function<void(Error)> RecoverableErrorHandler,
2083 std::function<void(Error)> WarningHandler) {
2084 auto DObj =
2085 std::make_unique<DWARFObjInMemory>(Sections, AddrSize, isLittleEndian);
2086 return std::make_unique<DWARFContext>(
2087 std::move(DObj), "", RecoverableErrorHandler, WarningHandler);
2088 }
2089
getCUAddrSize()2090 uint8_t DWARFContext::getCUAddrSize() {
2091 // In theory, different compile units may have different address byte
2092 // sizes, but for simplicity we just use the address byte size of the
2093 // first compile unit. In practice the address size field is repeated across
2094 // various DWARF headers (at least in version 5) to make it easier to dump
2095 // them independently, not to enable varying the address size.
2096 auto CUs = compile_units();
2097 return CUs.empty() ? 0 : (*CUs.begin())->getAddressByteSize();
2098 }
2099