LLVM 17.0.0git
DWARFContext.cpp
Go to the documentation of this file.
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
10#include "llvm/ADT/MapVector.h"
11#include "llvm/ADT/STLExtras.h"
14#include "llvm/ADT/StringRef.h"
43#include "llvm/Object/MachO.h"
48#include "llvm/Support/Error.h"
49#include "llvm/Support/Format.h"
50#include "llvm/Support/LEB128.h"
52#include "llvm/Support/Path.h"
54#include <algorithm>
55#include <cstdint>
56#include <deque>
57#include <map>
58#include <string>
59#include <utility>
60#include <vector>
61
62using namespace llvm;
63using namespace dwarf;
64using namespace object;
65
66#define DEBUG_TYPE "dwarf"
67
71
72DWARFContext::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
81
82/// Dump the UUID load command.
83static 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()) {
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));
97 Triple T = MachO->getArchTriple();
98 OS << " (" << T.getArchName() << ')';
99 OS << ' ' << MachO->getFileName() << '\n';
100 }
101 }
102}
103
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.
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).
151 const DWARFObject &Obj,
152 const DWARFSection &StringOffsetsSection,
153 StringRef StringSection,
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) {
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.
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).
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)) {
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
268std::unique_ptr<DWARFDebugMacro>
269DWARFContext::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()
275 SectionType == MacroSection
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
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
343 DWARFDataExtractor Data, bool GnuStyle) {
344 DWARFDebugPubTable Table;
345 Table.extract(Data, GnuStyle, DumpOpts.RecoverableErrorHandler);
346 Table.dump(OS);
347}
348
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()))
381 if (shouldDump(ExplicitDWO, ".debug_abbrev.dwo", DIDT_ID_DebugAbbrev,
382 DObj->getAbbrevDWOSection()))
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;
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)) {
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)) {
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);
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);
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);
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))
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(),
674
675 if (shouldDump(Explicit, ".gdb_index", DIDT_ID_GdbIndex,
676 DObj->getGdbIndexSection())) {
678 }
679
680 if (shouldDump(Explicit, ".apple_names", DIDT_ID_AppleNames,
681 DObj->getAppleNamesSection().Data))
683
684 if (shouldDump(Explicit, ".apple_types", DIDT_ID_AppleTypes,
685 DObj->getAppleTypesSection().Data))
687
688 if (shouldDump(Explicit, ".apple_namespaces", DIDT_ID_AppleNamespaces,
689 DObj->getAppleNamespacesSection().Data))
691
692 if (shouldDump(Explicit, ".apple_objc", DIDT_ID_AppleObjC,
693 DObj->getAppleObjCSection().Data))
695 if (shouldDump(Explicit, ".debug_names", DIDT_ID_DebugNames,
696 DObj->getNamesSection().Data))
698}
699
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 *>> &Map;
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
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
759 parseNormalUnits();
760 if (auto *CU = NormalUnits.getUnitForOffset(Offset))
761 return CU->getDIEForOffset(Offset);
762 return DWARFDie();
763}
764
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
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
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
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
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
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
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
907 if (Loc)
908 return Loc.get();
909
910 // Assume all units have the same address byte size.
911 auto LocData =
913 ? DWARFDataExtractor(*DObj, DObj->getLocSection(), isLittleEndian(),
914 getUnitAtIndex(0)->getAddressByteSize())
916 Loc.reset(new DWARFDebugLoc(std::move(LocData)));
917 return Loc.get();
918}
919
921 if (Aranges)
922 return Aranges.get();
923
924 Aranges.reset(new DWARFDebugAranges());
925 Aranges->generate(this);
926 return Aranges.get();
927}
928
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
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
972 if (!Macro)
973 Macro = parseMacroOrMacinfo(MacroSection);
974 return Macro.get();
975}
976
978 if (!MacroDWO)
979 MacroDWO = parseMacroOrMacinfo(MacroDwoSection);
980 return MacroDWO.get();
981}
982
984 if (!Macinfo)
985 Macinfo = parseMacroOrMacinfo(MacinfoSection);
986 return Macinfo.get();
987}
988
990 if (!MacinfoDWO)
991 MacinfoDWO = parseMacroOrMacinfo(MacinfoDwoSection);
992 return MacinfoDWO.get();
993}
994
995template <typename T>
996static 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
1010 return getAccelTable(Names, *DObj, DObj->getNamesSection(),
1011 DObj->getStrSection(), isLittleEndian());
1012}
1013
1015 return getAccelTable(AppleNames, *DObj, DObj->getAppleNamesSection(),
1016 DObj->getStrSection(), isLittleEndian());
1017}
1018
1020 return getAccelTable(AppleTypes, *DObj, DObj->getAppleTypesSection(),
1021 DObj->getStrSection(), isLittleEndian());
1022}
1023
1025 return getAccelTable(AppleNamespaces, *DObj,
1026 DObj->getAppleNamespacesSection(),
1027 DObj->getStrSection(), isLittleEndian());
1028}
1029
1031 return getAccelTable(AppleObjC, *DObj, DObj->getAppleObjCSection(),
1032 DObj->getStrSection(), isLittleEndian());
1033}
1034
1038 getLineTableForUnit(U, WarningHandler);
1039 if (!ExpectedLineTable) {
1040 WarningHandler(ExpectedLineTable.takeError());
1041 return nullptr;
1042 }
1043 return *ExpectedLineTable;
1044}
1045
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
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
1091void 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
1103void 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
1116 parseNormalUnits();
1117 return dyn_cast_or_null<DWARFCompileUnit>(
1118 NormalUnits.getUnitForOffset(Offset));
1119}
1120
1123 return getCompileUnitForOffset(CUOffset);
1124}
1125
1128 if (DWARFCompileUnit *OffsetCU = getCompileUnitForOffset(CUOffset))
1129 return OffsetCU;
1130
1131 // Global variables are often missed by the above search, for one of two
1132 // reasons:
1133 // 1. .debug_aranges may not include global variables. On clang, it seems we
1134 // put the globals in the aranges, but this isn't true for gcc.
1135 // 2. Even if the global variable is in a .debug_arange, global variables
1136 // may not be captured in the [start, end) addresses described by the
1137 // parent compile unit.
1138 //
1139 // So, we walk the CU's and their child DI's manually, looking for the
1140 // specific global variable.
1141 for (std::unique_ptr<DWARFUnit> &CU : compile_units()) {
1142 if (DWARFDie Die = CU->getVariableForAddress(Address)) {
1143 return static_cast<DWARFCompileUnit *>(CU.get());
1144 }
1145 }
1146 return nullptr;
1147}
1148
1150 DIEsForAddress Result;
1151
1153 if (!CU)
1154 return Result;
1155
1156 Result.CompileUnit = CU;
1157 Result.FunctionDIE = CU->getSubroutineForAddress(Address);
1158
1159 std::vector<DWARFDie> Worklist;
1160 Worklist.push_back(Result.FunctionDIE);
1161 while (!Worklist.empty()) {
1162 DWARFDie DIE = Worklist.back();
1163 Worklist.pop_back();
1164
1165 if (!DIE.isValid())
1166 continue;
1167
1168 if (DIE.getTag() == DW_TAG_lexical_block &&
1169 DIE.addressRangeContainsAddress(Address)) {
1170 Result.BlockDIE = DIE;
1171 break;
1172 }
1173
1174 append_range(Worklist, DIE);
1175 }
1176
1177 return Result;
1178}
1179
1180/// TODO: change input parameter from "uint64_t Address"
1181/// into "SectionedAddress Address"
1185 std::string &FunctionName, std::string &StartFile, uint32_t &StartLine,
1186 std::optional<uint64_t> &StartAddress) {
1187 // The address may correspond to instruction in some inlined function,
1188 // so we have to build the chain of inlined functions and take the
1189 // name of the topmost function in it.
1190 SmallVector<DWARFDie, 4> InlinedChain;
1191 CU->getInlinedChainForAddress(Address, InlinedChain);
1192 if (InlinedChain.empty())
1193 return false;
1194
1195 const DWARFDie &DIE = InlinedChain[0];
1196 bool FoundResult = false;
1197 const char *Name = nullptr;
1198 if (Kind != FunctionNameKind::None && (Name = DIE.getSubroutineName(Kind))) {
1199 FunctionName = Name;
1200 FoundResult = true;
1201 }
1202 std::string DeclFile = DIE.getDeclFile(FileNameKind);
1203 if (!DeclFile.empty()) {
1204 StartFile = DeclFile;
1205 FoundResult = true;
1206 }
1207 if (auto DeclLineResult = DIE.getDeclLine()) {
1208 StartLine = DeclLineResult;
1209 FoundResult = true;
1210 }
1211 if (auto LowPcAddr = toSectionedAddress(DIE.find(DW_AT_low_pc)))
1212 StartAddress = LowPcAddr->Address;
1213 return FoundResult;
1214}
1215
1216static std::optional<int64_t>
1218 std::optional<unsigned> FrameBaseReg) {
1219 if (!Expr.empty() &&
1220 (Expr[0] == DW_OP_fbreg ||
1221 (FrameBaseReg && Expr[0] == DW_OP_breg0 + *FrameBaseReg))) {
1222 unsigned Count;
1223 int64_t Offset = decodeSLEB128(Expr.data() + 1, &Count, Expr.end());
1224 // A single DW_OP_fbreg or DW_OP_breg.
1225 if (Expr.size() == Count + 1)
1226 return Offset;
1227 // Same + DW_OP_deref (Fortran arrays look like this).
1228 if (Expr.size() == Count + 2 && Expr[Count + 1] == DW_OP_deref)
1229 return Offset;
1230 // Fallthrough. Do not accept ex. (DW_OP_breg W29, DW_OP_stack_value)
1231 }
1232 return std::nullopt;
1233}
1234
1235void DWARFContext::addLocalsForDie(DWARFCompileUnit *CU, DWARFDie Subprogram,
1236 DWARFDie Die, std::vector<DILocal> &Result) {
1237 if (Die.getTag() == DW_TAG_variable ||
1238 Die.getTag() == DW_TAG_formal_parameter) {
1239 DILocal Local;
1240 if (const char *Name = Subprogram.getSubroutineName(DINameKind::ShortName))
1241 Local.FunctionName = Name;
1242
1243 std::optional<unsigned> FrameBaseReg;
1244 if (auto FrameBase = Subprogram.find(DW_AT_frame_base))
1245 if (std::optional<ArrayRef<uint8_t>> Expr = FrameBase->getAsBlock())
1246 if (!Expr->empty() && (*Expr)[0] >= DW_OP_reg0 &&
1247 (*Expr)[0] <= DW_OP_reg31) {
1248 FrameBaseReg = (*Expr)[0] - DW_OP_reg0;
1249 }
1250
1251 if (Expected<std::vector<DWARFLocationExpression>> Loc =
1252 Die.getLocations(DW_AT_location)) {
1253 for (const auto &Entry : *Loc) {
1254 if (std::optional<int64_t> FrameOffset =
1255 getExpressionFrameOffset(Entry.Expr, FrameBaseReg)) {
1256 Local.FrameOffset = *FrameOffset;
1257 break;
1258 }
1259 }
1260 } else {
1261 // FIXME: missing DW_AT_location is OK here, but other errors should be
1262 // reported to the user.
1263 consumeError(Loc.takeError());
1264 }
1265
1266 if (auto TagOffsetAttr = Die.find(DW_AT_LLVM_tag_offset))
1267 Local.TagOffset = TagOffsetAttr->getAsUnsignedConstant();
1268
1269 if (auto Origin =
1270 Die.getAttributeValueAsReferencedDie(DW_AT_abstract_origin))
1271 Die = Origin;
1272 if (auto NameAttr = Die.find(DW_AT_name))
1273 if (std::optional<const char *> Name = dwarf::toString(*NameAttr))
1274 Local.Name = *Name;
1275 if (auto Type = Die.getAttributeValueAsReferencedDie(DW_AT_type))
1276 Local.Size = Type.getTypeSize(getCUAddrSize());
1277 if (auto DeclFileAttr = Die.find(DW_AT_decl_file)) {
1278 if (const auto *LT = CU->getContext().getLineTableForUnit(CU))
1279 LT->getFileNameByIndex(
1280 *DeclFileAttr->getAsUnsignedConstant(), CU->getCompilationDir(),
1281 DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath,
1282 Local.DeclFile);
1283 }
1284 if (auto DeclLineAttr = Die.find(DW_AT_decl_line))
1285 Local.DeclLine = *DeclLineAttr->getAsUnsignedConstant();
1286
1287 Result.push_back(Local);
1288 return;
1289 }
1290
1291 if (Die.getTag() == DW_TAG_inlined_subroutine)
1292 if (auto Origin =
1293 Die.getAttributeValueAsReferencedDie(DW_AT_abstract_origin))
1294 Subprogram = Origin;
1295
1296 for (auto Child : Die)
1297 addLocalsForDie(CU, Subprogram, Child, Result);
1298}
1299
1300std::vector<DILocal>
1302 std::vector<DILocal> Result;
1304 if (!CU)
1305 return Result;
1306
1307 DWARFDie Subprogram = CU->getSubroutineForAddress(Address.Address);
1308 if (Subprogram.isValid())
1309 addLocalsForDie(CU, Subprogram, Subprogram, Result);
1310 return Result;
1311}
1312
1315 DILineInfo Result;
1317 if (!CU)
1318 return Result;
1319
1321 CU, Address.Address, Spec.FNKind, Spec.FLIKind, Result.FunctionName,
1322 Result.StartFileName, Result.StartLine, Result.StartAddress);
1323 if (Spec.FLIKind != FileLineInfoKind::None) {
1324 if (const DWARFLineTable *LineTable = getLineTableForUnit(CU)) {
1325 LineTable->getFileLineInfoForAddress(
1326 {Address.Address, Address.SectionIndex}, CU->getCompilationDir(),
1327 Spec.FLIKind, Result);
1328 }
1329 }
1330
1331 return Result;
1332}
1333
1336 DILineInfo Result;
1338 if (!CU)
1339 return Result;
1340
1341 if (DWARFDie Die = CU->getVariableForAddress(Address.Address)) {
1342 Result.FileName = Die.getDeclFile(FileLineInfoKind::AbsoluteFilePath);
1343 Result.Line = Die.getDeclLine();
1344 }
1345
1346 return Result;
1347}
1348
1351 DILineInfoTable Lines;
1353 if (!CU)
1354 return Lines;
1355
1356 uint32_t StartLine = 0;
1357 std::string StartFileName;
1358 std::string FunctionName(DILineInfo::BadString);
1359 std::optional<uint64_t> StartAddress;
1361 Spec.FLIKind, FunctionName,
1362 StartFileName, StartLine, StartAddress);
1363
1364 // If the Specifier says we don't need FileLineInfo, just
1365 // return the top-most function at the starting address.
1366 if (Spec.FLIKind == FileLineInfoKind::None) {
1367 DILineInfo Result;
1368 Result.FunctionName = FunctionName;
1369 Result.StartFileName = StartFileName;
1370 Result.StartLine = StartLine;
1371 Result.StartAddress = StartAddress;
1372 Lines.push_back(std::make_pair(Address.Address, Result));
1373 return Lines;
1374 }
1375
1376 const DWARFLineTable *LineTable = getLineTableForUnit(CU);
1377
1378 // Get the index of row we're looking for in the line table.
1379 std::vector<uint32_t> RowVector;
1380 if (!LineTable->lookupAddressRange({Address.Address, Address.SectionIndex},
1381 Size, RowVector)) {
1382 return Lines;
1383 }
1384
1385 for (uint32_t RowIndex : RowVector) {
1386 // Take file number and line/column from the row.
1387 const DWARFDebugLine::Row &Row = LineTable->Rows[RowIndex];
1388 DILineInfo Result;
1389 LineTable->getFileNameByIndex(Row.File, CU->getCompilationDir(),
1390 Spec.FLIKind, Result.FileName);
1391 Result.FunctionName = FunctionName;
1392 Result.Line = Row.Line;
1393 Result.Column = Row.Column;
1394 Result.StartFileName = StartFileName;
1395 Result.StartLine = StartLine;
1396 Result.StartAddress = StartAddress;
1397 Lines.push_back(std::make_pair(Row.Address.Address, Result));
1398 }
1399
1400 return Lines;
1401}
1402
1406 DIInliningInfo InliningInfo;
1407
1409 if (!CU)
1410 return InliningInfo;
1411
1412 const DWARFLineTable *LineTable = nullptr;
1413 SmallVector<DWARFDie, 4> InlinedChain;
1414 CU->getInlinedChainForAddress(Address.Address, InlinedChain);
1415 if (InlinedChain.size() == 0) {
1416 // If there is no DIE for address (e.g. it is in unavailable .dwo file),
1417 // try to at least get file/line info from symbol table.
1418 if (Spec.FLIKind != FileLineInfoKind::None) {
1419 DILineInfo Frame;
1420 LineTable = getLineTableForUnit(CU);
1421 if (LineTable && LineTable->getFileLineInfoForAddress(
1422 {Address.Address, Address.SectionIndex},
1423 CU->getCompilationDir(), Spec.FLIKind, Frame))
1424 InliningInfo.addFrame(Frame);
1425 }
1426 return InliningInfo;
1427 }
1428
1429 uint32_t CallFile = 0, CallLine = 0, CallColumn = 0, CallDiscriminator = 0;
1430 for (uint32_t i = 0, n = InlinedChain.size(); i != n; i++) {
1431 DWARFDie &FunctionDIE = InlinedChain[i];
1432 DILineInfo Frame;
1433 // Get function name if necessary.
1434 if (const char *Name = FunctionDIE.getSubroutineName(Spec.FNKind))
1435 Frame.FunctionName = Name;
1436 if (auto DeclLineResult = FunctionDIE.getDeclLine())
1437 Frame.StartLine = DeclLineResult;
1438 Frame.StartFileName = FunctionDIE.getDeclFile(Spec.FLIKind);
1439 if (auto LowPcAddr = toSectionedAddress(FunctionDIE.find(DW_AT_low_pc)))
1440 Frame.StartAddress = LowPcAddr->Address;
1441 if (Spec.FLIKind != FileLineInfoKind::None) {
1442 if (i == 0) {
1443 // For the topmost frame, initialize the line table of this
1444 // compile unit and fetch file/line info from it.
1445 LineTable = getLineTableForUnit(CU);
1446 // For the topmost routine, get file/line info from line table.
1447 if (LineTable)
1448 LineTable->getFileLineInfoForAddress(
1449 {Address.Address, Address.SectionIndex}, CU->getCompilationDir(),
1450 Spec.FLIKind, Frame);
1451 } else {
1452 // Otherwise, use call file, call line and call column from
1453 // previous DIE in inlined chain.
1454 if (LineTable)
1455 LineTable->getFileNameByIndex(CallFile, CU->getCompilationDir(),
1456 Spec.FLIKind, Frame.FileName);
1457 Frame.Line = CallLine;
1458 Frame.Column = CallColumn;
1459 Frame.Discriminator = CallDiscriminator;
1460 }
1461 // Get call file/line/column of a current DIE.
1462 if (i + 1 < n) {
1463 FunctionDIE.getCallerFrame(CallFile, CallLine, CallColumn,
1464 CallDiscriminator);
1465 }
1466 }
1467 InliningInfo.addFrame(Frame);
1468 }
1469 return InliningInfo;
1470}
1471
1472std::shared_ptr<DWARFContext>
1474 if (auto S = DWP.lock()) {
1475 DWARFContext *Ctxt = S->Context.get();
1476 return std::shared_ptr<DWARFContext>(std::move(S), Ctxt);
1477 }
1478
1479 std::weak_ptr<DWOFile> *Entry = &DWOFiles[AbsolutePath];
1480
1481 if (auto S = Entry->lock()) {
1482 DWARFContext *Ctxt = S->Context.get();
1483 return std::shared_ptr<DWARFContext>(std::move(S), Ctxt);
1484 }
1485
1487 if (!CheckedForDWP) {
1488 SmallString<128> DWPName;
1490 this->DWPName.empty()
1491 ? (DObj->getFileName() + ".dwp").toStringRef(DWPName)
1492 : StringRef(this->DWPName));
1493 if (Obj) {
1494 Entry = &DWP;
1495 return Obj;
1496 } else {
1497 CheckedForDWP = true;
1498 // TODO: Should this error be handled (maybe in a high verbosity mode)
1499 // before falling back to .dwo files?
1500 consumeError(Obj.takeError());
1501 }
1502 }
1503
1504 return object::ObjectFile::createObjectFile(AbsolutePath);
1505 }();
1506
1507 if (!Obj) {
1508 // TODO: Actually report errors helpfully.
1509 consumeError(Obj.takeError());
1510 return nullptr;
1511 }
1512
1513 auto S = std::make_shared<DWOFile>();
1514 S->File = std::move(Obj.get());
1515 S->Context = DWARFContext::create(*S->File.getBinary(),
1517 *Entry = S;
1518 auto *Ctxt = S->Context.get();
1519 return std::shared_ptr<DWARFContext>(std::move(S), Ctxt);
1520}
1521
1522static Error createError(const Twine &Reason, llvm::Error E) {
1523 return make_error<StringError>(Reason + toString(std::move(E)),
1525}
1526
1527/// SymInfo contains information about symbol: it's address
1528/// and section index which is -1LL for absolute symbols.
1529struct SymInfo {
1532};
1533
1534/// Returns the address of symbol relocation used against and a section index.
1535/// Used for futher relocations computation. Symbol's section load address is
1537 const RelocationRef &Reloc,
1538 const LoadedObjectInfo *L,
1539 std::map<SymbolRef, SymInfo> &Cache) {
1540 SymInfo Ret = {0, (uint64_t)-1LL};
1542 object::symbol_iterator Sym = Reloc.getSymbol();
1543
1544 std::map<SymbolRef, SymInfo>::iterator CacheIt = Cache.end();
1545 // First calculate the address of the symbol or section as it appears
1546 // in the object file
1547 if (Sym != Obj.symbol_end()) {
1548 bool New;
1549 std::tie(CacheIt, New) = Cache.insert({*Sym, {0, 0}});
1550 if (!New)
1551 return CacheIt->second;
1552
1553 Expected<uint64_t> SymAddrOrErr = Sym->getAddress();
1554 if (!SymAddrOrErr)
1555 return createError("failed to compute symbol address: ",
1556 SymAddrOrErr.takeError());
1557
1558 // Also remember what section this symbol is in for later
1559 auto SectOrErr = Sym->getSection();
1560 if (!SectOrErr)
1561 return createError("failed to get symbol section: ",
1562 SectOrErr.takeError());
1563
1564 RSec = *SectOrErr;
1565 Ret.Address = *SymAddrOrErr;
1566 } else if (auto *MObj = dyn_cast<MachOObjectFile>(&Obj)) {
1567 RSec = MObj->getRelocationSection(Reloc.getRawDataRefImpl());
1568 Ret.Address = RSec->getAddress();
1569 }
1570
1571 if (RSec != Obj.section_end())
1572 Ret.SectionIndex = RSec->getIndex();
1573
1574 // If we are given load addresses for the sections, we need to adjust:
1575 // SymAddr = (Address of Symbol Or Section in File) -
1576 // (Address of Section in File) +
1577 // (Load Address of Section)
1578 // RSec is now either the section being targeted or the section
1579 // containing the symbol being targeted. In either case,
1580 // we need to perform the same computation.
1581 if (L && RSec != Obj.section_end())
1582 if (uint64_t SectionLoadAddress = L->getSectionLoadAddress(*RSec))
1583 Ret.Address += SectionLoadAddress - RSec->getAddress();
1584
1585 if (CacheIt != Cache.end())
1586 CacheIt->second = Ret;
1587
1588 return Ret;
1589}
1590
1592 const RelocationRef &Reloc) {
1593 const MachOObjectFile *MachObj = dyn_cast<MachOObjectFile>(&Obj);
1594 if (!MachObj)
1595 return false;
1596 // MachO also has relocations that point to sections and
1597 // scattered relocations.
1598 auto RelocInfo = MachObj->getRelocation(Reloc.getRawDataRefImpl());
1599 return MachObj->isRelocationScattered(RelocInfo);
1600}
1601
1602namespace {
1603struct DWARFSectionMap final : public DWARFSection {
1604 RelocAddrMap Relocs;
1605};
1606
1607class DWARFObjInMemory final : public DWARFObject {
1608 bool IsLittleEndian;
1609 uint8_t AddressSize;
1610 StringRef FileName;
1611 const object::ObjectFile *Obj = nullptr;
1612 std::vector<SectionName> SectionNames;
1613
1614 using InfoSectionMap = MapVector<object::SectionRef, DWARFSectionMap,
1615 std::map<object::SectionRef, unsigned>>;
1616
1617 InfoSectionMap InfoSections;
1618 InfoSectionMap TypesSections;
1619 InfoSectionMap InfoDWOSections;
1620 InfoSectionMap TypesDWOSections;
1621
1622 DWARFSectionMap LocSection;
1623 DWARFSectionMap LoclistsSection;
1624 DWARFSectionMap LoclistsDWOSection;
1625 DWARFSectionMap LineSection;
1626 DWARFSectionMap RangesSection;
1627 DWARFSectionMap RnglistsSection;
1628 DWARFSectionMap StrOffsetsSection;
1629 DWARFSectionMap LineDWOSection;
1630 DWARFSectionMap FrameSection;
1631 DWARFSectionMap EHFrameSection;
1632 DWARFSectionMap LocDWOSection;
1633 DWARFSectionMap StrOffsetsDWOSection;
1634 DWARFSectionMap RangesDWOSection;
1635 DWARFSectionMap RnglistsDWOSection;
1636 DWARFSectionMap AddrSection;
1637 DWARFSectionMap AppleNamesSection;
1638 DWARFSectionMap AppleTypesSection;
1639 DWARFSectionMap AppleNamespacesSection;
1640 DWARFSectionMap AppleObjCSection;
1641 DWARFSectionMap NamesSection;
1642 DWARFSectionMap PubnamesSection;
1643 DWARFSectionMap PubtypesSection;
1644 DWARFSectionMap GnuPubnamesSection;
1645 DWARFSectionMap GnuPubtypesSection;
1646 DWARFSectionMap MacroSection;
1647
1648 DWARFSectionMap *mapNameToDWARFSection(StringRef Name) {
1650 .Case("debug_loc", &LocSection)
1651 .Case("debug_loclists", &LoclistsSection)
1652 .Case("debug_loclists.dwo", &LoclistsDWOSection)
1653 .Case("debug_line", &LineSection)
1654 .Case("debug_frame", &FrameSection)
1655 .Case("eh_frame", &EHFrameSection)
1656 .Case("debug_str_offsets", &StrOffsetsSection)
1657 .Case("debug_ranges", &RangesSection)
1658 .Case("debug_rnglists", &RnglistsSection)
1659 .Case("debug_loc.dwo", &LocDWOSection)
1660 .Case("debug_line.dwo", &LineDWOSection)
1661 .Case("debug_names", &NamesSection)
1662 .Case("debug_rnglists.dwo", &RnglistsDWOSection)
1663 .Case("debug_str_offsets.dwo", &StrOffsetsDWOSection)
1664 .Case("debug_addr", &AddrSection)
1665 .Case("apple_names", &AppleNamesSection)
1666 .Case("debug_pubnames", &PubnamesSection)
1667 .Case("debug_pubtypes", &PubtypesSection)
1668 .Case("debug_gnu_pubnames", &GnuPubnamesSection)
1669 .Case("debug_gnu_pubtypes", &GnuPubtypesSection)
1670 .Case("apple_types", &AppleTypesSection)
1671 .Case("apple_namespaces", &AppleNamespacesSection)
1672 .Case("apple_namespac", &AppleNamespacesSection)
1673 .Case("apple_objc", &AppleObjCSection)
1674 .Case("debug_macro", &MacroSection)
1675 .Default(nullptr);
1676 }
1677
1678 StringRef AbbrevSection;
1679 StringRef ArangesSection;
1680 StringRef StrSection;
1681 StringRef MacinfoSection;
1682 StringRef MacinfoDWOSection;
1683 StringRef MacroDWOSection;
1684 StringRef AbbrevDWOSection;
1685 StringRef StrDWOSection;
1686 StringRef CUIndexSection;
1687 StringRef GdbIndexSection;
1688 StringRef TUIndexSection;
1689 StringRef LineStrSection;
1690
1691 // A deque holding section data whose iterators are not invalidated when
1692 // new decompressed sections are inserted at the end.
1693 std::deque<SmallString<0>> UncompressedSections;
1694
1695 StringRef *mapSectionToMember(StringRef Name) {
1696 if (DWARFSection *Sec = mapNameToDWARFSection(Name))
1697 return &Sec->Data;
1699 .Case("debug_abbrev", &AbbrevSection)
1700 .Case("debug_aranges", &ArangesSection)
1701 .Case("debug_str", &StrSection)
1702 .Case("debug_macinfo", &MacinfoSection)
1703 .Case("debug_macinfo.dwo", &MacinfoDWOSection)
1704 .Case("debug_macro.dwo", &MacroDWOSection)
1705 .Case("debug_abbrev.dwo", &AbbrevDWOSection)
1706 .Case("debug_str.dwo", &StrDWOSection)
1707 .Case("debug_cu_index", &CUIndexSection)
1708 .Case("debug_tu_index", &TUIndexSection)
1709 .Case("gdb_index", &GdbIndexSection)
1710 .Case("debug_line_str", &LineStrSection)
1711 // Any more debug info sections go here.
1712 .Default(nullptr);
1713 }
1714
1715 /// If Sec is compressed section, decompresses and updates its contents
1716 /// provided by Data. Otherwise leaves it unchanged.
1717 Error maybeDecompress(const object::SectionRef &Sec, StringRef Name,
1718 StringRef &Data) {
1719 if (!Sec.isCompressed())
1720 return Error::success();
1721
1723 Decompressor::create(Name, Data, IsLittleEndian, AddressSize == 8);
1724 if (!Decompressor)
1725 return Decompressor.takeError();
1726
1727 SmallString<0> Out;
1728 if (auto Err = Decompressor->resizeAndDecompress(Out))
1729 return Err;
1730
1731 UncompressedSections.push_back(std::move(Out));
1732 Data = UncompressedSections.back();
1733
1734 return Error::success();
1735 }
1736
1737public:
1738 DWARFObjInMemory(const StringMap<std::unique_ptr<MemoryBuffer>> &Sections,
1739 uint8_t AddrSize, bool IsLittleEndian)
1740 : IsLittleEndian(IsLittleEndian) {
1741 for (const auto &SecIt : Sections) {
1742 if (StringRef *SectionData = mapSectionToMember(SecIt.first()))
1743 *SectionData = SecIt.second->getBuffer();
1744 else if (SecIt.first() == "debug_info")
1745 // Find debug_info and debug_types data by section rather than name as
1746 // there are multiple, comdat grouped, of these sections.
1747 InfoSections[SectionRef()].Data = SecIt.second->getBuffer();
1748 else if (SecIt.first() == "debug_info.dwo")
1749 InfoDWOSections[SectionRef()].Data = SecIt.second->getBuffer();
1750 else if (SecIt.first() == "debug_types")
1751 TypesSections[SectionRef()].Data = SecIt.second->getBuffer();
1752 else if (SecIt.first() == "debug_types.dwo")
1753 TypesDWOSections[SectionRef()].Data = SecIt.second->getBuffer();
1754 }
1755 }
1756 DWARFObjInMemory(const object::ObjectFile &Obj, const LoadedObjectInfo *L,
1757 function_ref<void(Error)> HandleError,
1758 function_ref<void(Error)> HandleWarning,
1760 : IsLittleEndian(Obj.isLittleEndian()),
1761 AddressSize(Obj.getBytesInAddress()), FileName(Obj.getFileName()),
1762 Obj(&Obj) {
1763
1764 StringMap<unsigned> SectionAmountMap;
1765 for (const SectionRef &Section : Obj.sections()) {
1767 if (auto NameOrErr = Section.getName())
1768 Name = *NameOrErr;
1769 else
1770 consumeError(NameOrErr.takeError());
1771
1772 ++SectionAmountMap[Name];
1773 SectionNames.push_back({ Name, true });
1774
1775 // Skip BSS and Virtual sections, they aren't interesting.
1776 if (Section.isBSS() || Section.isVirtual())
1777 continue;
1778
1779 // Skip sections stripped by dsymutil.
1780 if (Section.isStripped())
1781 continue;
1782
1784 Expected<section_iterator> SecOrErr = Section.getRelocatedSection();
1785 if (!SecOrErr) {
1786 HandleError(createError("failed to get relocated section: ",
1787 SecOrErr.takeError()));
1788 continue;
1789 }
1790
1791 // Try to obtain an already relocated version of this section.
1792 // Else use the unrelocated section from the object file. We'll have to
1793 // apply relocations ourselves later.
1794 section_iterator RelocatedSection =
1795 Obj.isRelocatableObject() ? *SecOrErr : Obj.section_end();
1796 if (!L || !L->getLoadedSectionContents(*RelocatedSection, Data)) {
1797 Expected<StringRef> E = Section.getContents();
1798 if (E)
1799 Data = *E;
1800 else
1801 // maybeDecompress below will error.
1802 consumeError(E.takeError());
1803 }
1804
1805 if (auto Err = maybeDecompress(Section, Name, Data)) {
1806 HandleError(createError("failed to decompress '" + Name + "', ",
1807 std::move(Err)));
1808 continue;
1809 }
1810
1811 // Compressed sections names in GNU style starts from ".z",
1812 // at this point section is decompressed and we drop compression prefix.
1813 Name = Name.substr(
1814 Name.find_first_not_of("._z")); // Skip ".", "z" and "_" prefixes.
1815
1816 // Map platform specific debug section names to DWARF standard section
1817 // names.
1819
1820 if (StringRef *SectionData = mapSectionToMember(Name)) {
1821 *SectionData = Data;
1822 if (Name == "debug_ranges") {
1823 // FIXME: Use the other dwo range section when we emit it.
1824 RangesDWOSection.Data = Data;
1825 } else if (Name == "debug_frame" || Name == "eh_frame") {
1826 if (DWARFSection *S = mapNameToDWARFSection(Name))
1827 S->Address = Section.getAddress();
1828 }
1829 } else if (InfoSectionMap *Sections =
1831 .Case("debug_info", &InfoSections)
1832 .Case("debug_info.dwo", &InfoDWOSections)
1833 .Case("debug_types", &TypesSections)
1834 .Case("debug_types.dwo", &TypesDWOSections)
1835 .Default(nullptr)) {
1836 // Find debug_info and debug_types data by section rather than name as
1837 // there are multiple, comdat grouped, of these sections.
1838 DWARFSectionMap &S = (*Sections)[Section];
1839 S.Data = Data;
1840 }
1841
1842 if (RelocatedSection != Obj.section_end() && Name.contains(".dwo"))
1843 HandleWarning(
1844 createError("Unexpected relocations for dwo section " + Name));
1845
1846 if (RelocatedSection == Obj.section_end() ||
1847 (RelocAction == DWARFContext::ProcessDebugRelocations::Ignore))
1848 continue;
1849
1850 StringRef RelSecName;
1851 if (auto NameOrErr = RelocatedSection->getName())
1852 RelSecName = *NameOrErr;
1853 else
1854 consumeError(NameOrErr.takeError());
1855
1856 // If the section we're relocating was relocated already by the JIT,
1857 // then we used the relocated version above, so we do not need to process
1858 // relocations for it now.
1859 StringRef RelSecData;
1860 if (L && L->getLoadedSectionContents(*RelocatedSection, RelSecData))
1861 continue;
1862
1863 // In Mach-o files, the relocations do not need to be applied if
1864 // there is no load offset to apply. The value read at the
1865 // relocation point already factors in the section address
1866 // (actually applying the relocations will produce wrong results
1867 // as the section address will be added twice).
1868 if (!L && isa<MachOObjectFile>(&Obj))
1869 continue;
1870
1871 RelSecName = RelSecName.substr(
1872 RelSecName.find_first_not_of("._z")); // Skip . and _ prefixes.
1873
1874 // TODO: Add support for relocations in other sections as needed.
1875 // Record relocations for the debug_info and debug_line sections.
1876 DWARFSectionMap *Sec = mapNameToDWARFSection(RelSecName);
1877 RelocAddrMap *Map = Sec ? &Sec->Relocs : nullptr;
1878 if (!Map) {
1879 // Find debug_info and debug_types relocs by section rather than name
1880 // as there are multiple, comdat grouped, of these sections.
1881 if (RelSecName == "debug_info")
1882 Map = &static_cast<DWARFSectionMap &>(InfoSections[*RelocatedSection])
1883 .Relocs;
1884 else if (RelSecName == "debug_types")
1885 Map =
1886 &static_cast<DWARFSectionMap &>(TypesSections[*RelocatedSection])
1887 .Relocs;
1888 else
1889 continue;
1890 }
1891
1892 if (Section.relocation_begin() == Section.relocation_end())
1893 continue;
1894
1895 // Symbol to [address, section index] cache mapping.
1896 std::map<SymbolRef, SymInfo> AddrCache;
1897 SupportsRelocation Supports;
1899 std::tie(Supports, Resolver) = getRelocationResolver(Obj);
1900 for (const RelocationRef &Reloc : Section.relocations()) {
1901 // FIXME: it's not clear how to correctly handle scattered
1902 // relocations.
1903 if (isRelocScattered(Obj, Reloc))
1904 continue;
1905
1906 Expected<SymInfo> SymInfoOrErr =
1907 getSymbolInfo(Obj, Reloc, L, AddrCache);
1908 if (!SymInfoOrErr) {
1909 HandleError(SymInfoOrErr.takeError());
1910 continue;
1911 }
1912
1913 // Check if Resolver can handle this relocation type early so as not to
1914 // handle invalid cases in DWARFDataExtractor.
1915 //
1916 // TODO Don't store Resolver in every RelocAddrEntry.
1917 if (Supports && Supports(Reloc.getType())) {
1918 auto I = Map->try_emplace(
1919 Reloc.getOffset(),
1921 SymInfoOrErr->SectionIndex, Reloc, SymInfoOrErr->Address,
1922 std::optional<object::RelocationRef>(), 0, Resolver});
1923 // If we didn't successfully insert that's because we already had a
1924 // relocation for that offset. Store it as a second relocation in the
1925 // same RelocAddrEntry instead.
1926 if (!I.second) {
1927 RelocAddrEntry &entry = I.first->getSecond();
1928 if (entry.Reloc2) {
1929 HandleError(createError(
1930 "At most two relocations per offset are supported"));
1931 }
1932 entry.Reloc2 = Reloc;
1933 entry.SymbolValue2 = SymInfoOrErr->Address;
1934 }
1935 } else {
1937 Reloc.getTypeName(Type);
1938 // FIXME: Support more relocations & change this to an error
1939 HandleWarning(
1940 createError("failed to compute relocation: " + Type + ", ",
1941 errorCodeToError(object_error::parse_failed)));
1942 }
1943 }
1944 }
1945
1946 for (SectionName &S : SectionNames)
1947 if (SectionAmountMap[S.Name] > 1)
1948 S.IsNameUnique = false;
1949 }
1950
1951 std::optional<RelocAddrEntry> find(const DWARFSection &S,
1952 uint64_t Pos) const override {
1953 auto &Sec = static_cast<const DWARFSectionMap &>(S);
1954 RelocAddrMap::const_iterator AI = Sec.Relocs.find(Pos);
1955 if (AI == Sec.Relocs.end())
1956 return std::nullopt;
1957 return AI->second;
1958 }
1959
1960 const object::ObjectFile *getFile() const override { return Obj; }
1961
1962 ArrayRef<SectionName> getSectionNames() const override {
1963 return SectionNames;
1964 }
1965
1966 bool isLittleEndian() const override { return IsLittleEndian; }
1967 StringRef getAbbrevDWOSection() const override { return AbbrevDWOSection; }
1968 const DWARFSection &getLineDWOSection() const override {
1969 return LineDWOSection;
1970 }
1971 const DWARFSection &getLocDWOSection() const override {
1972 return LocDWOSection;
1973 }
1974 StringRef getStrDWOSection() const override { return StrDWOSection; }
1975 const DWARFSection &getStrOffsetsDWOSection() const override {
1976 return StrOffsetsDWOSection;
1977 }
1978 const DWARFSection &getRangesDWOSection() const override {
1979 return RangesDWOSection;
1980 }
1981 const DWARFSection &getRnglistsDWOSection() const override {
1982 return RnglistsDWOSection;
1983 }
1984 const DWARFSection &getLoclistsDWOSection() const override {
1985 return LoclistsDWOSection;
1986 }
1987 const DWARFSection &getAddrSection() const override { return AddrSection; }
1988 StringRef getCUIndexSection() const override { return CUIndexSection; }
1989 StringRef getGdbIndexSection() const override { return GdbIndexSection; }
1990 StringRef getTUIndexSection() const override { return TUIndexSection; }
1991
1992 // DWARF v5
1993 const DWARFSection &getStrOffsetsSection() const override {
1994 return StrOffsetsSection;
1995 }
1996 StringRef getLineStrSection() const override { return LineStrSection; }
1997
1998 // Sections for DWARF5 split dwarf proposal.
1999 void forEachInfoDWOSections(
2000 function_ref<void(const DWARFSection &)> F) const override {
2001 for (auto &P : InfoDWOSections)
2002 F(P.second);
2003 }
2004 void forEachTypesDWOSections(
2005 function_ref<void(const DWARFSection &)> F) const override {
2006 for (auto &P : TypesDWOSections)
2007 F(P.second);
2008 }
2009
2010 StringRef getAbbrevSection() const override { return AbbrevSection; }
2011 const DWARFSection &getLocSection() const override { return LocSection; }
2012 const DWARFSection &getLoclistsSection() const override { return LoclistsSection; }
2013 StringRef getArangesSection() const override { return ArangesSection; }
2014 const DWARFSection &getFrameSection() const override {
2015 return FrameSection;
2016 }
2017 const DWARFSection &getEHFrameSection() const override {
2018 return EHFrameSection;
2019 }
2020 const DWARFSection &getLineSection() const override { return LineSection; }
2021 StringRef getStrSection() const override { return StrSection; }
2022 const DWARFSection &getRangesSection() const override { return RangesSection; }
2023 const DWARFSection &getRnglistsSection() const override {
2024 return RnglistsSection;
2025 }
2026 const DWARFSection &getMacroSection() const override { return MacroSection; }
2027 StringRef getMacroDWOSection() const override { return MacroDWOSection; }
2028 StringRef getMacinfoSection() const override { return MacinfoSection; }
2029 StringRef getMacinfoDWOSection() const override { return MacinfoDWOSection; }
2030 const DWARFSection &getPubnamesSection() const override { return PubnamesSection; }
2031 const DWARFSection &getPubtypesSection() const override { return PubtypesSection; }
2032 const DWARFSection &getGnuPubnamesSection() const override {
2033 return GnuPubnamesSection;
2034 }
2035 const DWARFSection &getGnuPubtypesSection() const override {
2036 return GnuPubtypesSection;
2037 }
2038 const DWARFSection &getAppleNamesSection() const override {
2039 return AppleNamesSection;
2040 }
2041 const DWARFSection &getAppleTypesSection() const override {
2042 return AppleTypesSection;
2043 }
2044 const DWARFSection &getAppleNamespacesSection() const override {
2045 return AppleNamespacesSection;
2046 }
2047 const DWARFSection &getAppleObjCSection() const override {
2048 return AppleObjCSection;
2049 }
2050 const DWARFSection &getNamesSection() const override {
2051 return NamesSection;
2052 }
2053
2054 StringRef getFileName() const override { return FileName; }
2055 uint8_t getAddressSize() const override { return AddressSize; }
2056 void forEachInfoSections(
2057 function_ref<void(const DWARFSection &)> F) const override {
2058 for (auto &P : InfoSections)
2059 F(P.second);
2060 }
2061 void forEachTypesSections(
2062 function_ref<void(const DWARFSection &)> F) const override {
2063 for (auto &P : TypesSections)
2064 F(P.second);
2065 }
2066};
2067} // namespace
2068
2069std::unique_ptr<DWARFContext>
2071 ProcessDebugRelocations RelocAction,
2072 const LoadedObjectInfo *L, std::string DWPName,
2073 std::function<void(Error)> RecoverableErrorHandler,
2074 std::function<void(Error)> WarningHandler) {
2075 auto DObj = std::make_unique<DWARFObjInMemory>(
2076 Obj, L, RecoverableErrorHandler, WarningHandler, RelocAction);
2077 return std::make_unique<DWARFContext>(std::move(DObj), std::move(DWPName),
2078 RecoverableErrorHandler,
2079 WarningHandler);
2080}
2081
2082std::unique_ptr<DWARFContext>
2083DWARFContext::create(const StringMap<std::unique_ptr<MemoryBuffer>> &Sections,
2084 uint8_t AddrSize, bool isLittleEndian,
2085 std::function<void(Error)> RecoverableErrorHandler,
2086 std::function<void(Error)> WarningHandler) {
2087 auto DObj =
2088 std::make_unique<DWARFObjInMemory>(Sections, AddrSize, isLittleEndian);
2089 return std::make_unique<DWARFContext>(
2090 std::move(DObj), "", RecoverableErrorHandler, WarningHandler);
2091}
2092
2094 // In theory, different compile units may have different address byte
2095 // sizes, but for simplicity we just use the address byte size of the
2096 // first compile unit. In practice the address size field is repeated across
2097 // various DWARF headers (at least in version 5) to make it easier to dump
2098 // them independently, not to enable varying the address size.
2099 auto CUs = compile_units();
2100 return CUs.empty() ? 0 : (*CUs.begin())->getAddressByteSize();
2101}
#define Success
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static Expected< StringRef > getFileName(const DebugStringTableSubsectionRef &Strings, const DebugChecksumsSubsectionRef &Checksums, uint32_t FileID)
static void dumpLoclistsSection(raw_ostream &OS, DIDumpOptions DumpOpts, DWARFDataExtractor Data, const DWARFObject &Obj, std::optional< uint64_t > DumpOffset)
static void dumpRnglistsSection(raw_ostream &OS, DWARFDataExtractor &rnglistData, llvm::function_ref< std::optional< object::SectionedAddress >(uint32_t)> LookupPooledAddress, DIDumpOptions DumpOpts)
static void dumpUUID(raw_ostream &OS, const ObjectFile &Obj)
Dump the UUID load command.
void fixupIndex(const DWARFObject &DObj, DWARFContext &C, DWARFUnitIndex &Index)
static bool 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)
TODO: change input parameter from "uint64_t Address" into "SectionedAddress Address".
static void dumpPubTableSection(raw_ostream &OS, DIDumpOptions DumpOpts, DWARFDataExtractor Data, bool GnuStyle)
static Expected< SymInfo > getSymbolInfo(const object::ObjectFile &Obj, const RelocationRef &Reloc, const LoadedObjectInfo *L, std::map< SymbolRef, SymInfo > &Cache)
Returns the address of symbol relocation used against and a section index.
static void dumpAddrSection(raw_ostream &OS, DWARFDataExtractor &AddrData, DIDumpOptions DumpOpts, uint16_t Version, uint8_t AddrSize)
static T & getAccelTable(std::unique_ptr< T > &Cache, const DWARFObject &Obj, const DWARFSection &Section, StringRef StringSection, bool IsLittleEndian)
std::vector< std::optional< StrOffsetsContributionDescriptor > > ContributionCollection
static ContributionCollection collectContributionData(DWARFContext::unit_iterator_range Units)
static bool isRelocScattered(const object::ObjectFile &Obj, const RelocationRef &Reloc)
static std::optional< int64_t > getExpressionFrameOffset(ArrayRef< uint8_t > Expr, std::optional< unsigned > FrameBaseReg)
static void dumpStringOffsetsSection(raw_ostream &OS, DIDumpOptions DumpOpts, StringRef SectionName, const DWARFObject &Obj, const DWARFSection &StringOffsetsSection, StringRef StringSection, DWARFContext::unit_iterator_range Units, bool LittleEndian)
static RegisterPass< DebugifyFunctionPass > DF("debugify-function", "Attach debug info to a function")
@ Default
Definition: DwarfDebug.cpp:86
This file contains constants used for implementing Dwarf debug support.
std::string Name
uint64_t Size
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
This file implements a map that provides insertion order iteration.
print Instructions which execute on loop entry
#define P(N)
This file contains some templates that are useful if you are working with the STL at all.
raw_pwrite_stream & OS
This file defines the SmallString class.
This file defines the SmallVector class.
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
std::pair< llvm::MachO::Target, std::string > UUID
This implements the Apple accelerator table format, a precursor of the DWARF 5 accelerator table form...
void dump(raw_ostream &OS) const override
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
iterator end() const
Definition: ArrayRef.h:152
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:163
bool empty() const
empty - Check if the array is empty.
Definition: ArrayRef.h:158
const T * data() const
Definition: ArrayRef.h:160
A structured debug information entry.
Definition: DIE.h:744
dwarf::Tag getTag() const
Definition: DIE.h:780
A format-neutral container for inlined code description.
Definition: DIContext.h:88
void addFrame(const DILineInfo &Frame)
Definition: DIContext.h:108
DWARFContext This data structure is the top level entity that deals with dwarf debug information pars...
Definition: DWARFContext.h:46
DWARFCompileUnit * getCompileUnitForCodeAddress(uint64_t Address)
Return the compile unit which contains instruction with provided address.
uint8_t getCUAddrSize()
Get address size from CUs.
DIInliningInfo getInliningInfoForAddress(object::SectionedAddress Address, DILineInfoSpecifier Specifier=DILineInfoSpecifier()) override
Expected< const DWARFDebugFrame * > getDebugFrame()
Get a pointer to the parsed frame information object.
Triple::ArchType getArch() const
Definition: DWARFContext.h:440
DWARFGdbIndex & getGdbIndex()
unsigned getNumCompileUnits()
Get the number of compile units in this context.
Definition: DWARFContext.h:216
~DWARFContext() override
DWARFDie getDIEForOffset(uint64_t Offset)
Get a DIE given an exact offset.
unsigned getNumTypeUnits()
Get the number of type units in this context.
Definition: DWARFContext.h:222
DIEsForAddress getDIEsForAddress(uint64_t Address)
Get the compilation unit, the function DIE and lexical block DIE for the given address where applicab...
DILineInfo getLineInfoForAddress(object::SectionedAddress Address, DILineInfoSpecifier Specifier=DILineInfoSpecifier()) override
const DWARFDebugAbbrev * getDebugAbbrevDWO()
Get a pointer to the parsed dwo abbreviations object.
compile_unit_range compile_units()
Get compile units in this context.
Definition: DWARFContext.h:168
const AppleAcceleratorTable & getAppleObjC()
Get a reference to the parsed accelerator table object.
const DWARFUnitIndex & getTUIndex()
DWARFContext(std::unique_ptr< const DWARFObject > DObj, std::string DWPName="", std::function< void(Error)> RecoverableErrorHandler=WithColor::defaultErrorHandler, std::function< void(Error)> WarningHandler=WithColor::defaultWarningHandler)
unsigned getMaxVersion()
Definition: DWARFContext.h:260
DWARFCompileUnit * getCompileUnitForDataAddress(uint64_t Address)
Return the compile unit which contains data with the provided address.
const DWARFDebugAbbrev * getDebugAbbrev()
Get a pointer to the parsed DebugAbbrev object.
std::vector< DILocal > getLocalsForAddress(object::SectionedAddress Address) override
DataExtractor getStringExtractor() const
Definition: DWARFContext.h:340
static std::unique_ptr< DWARFContext > create(const object::ObjectFile &Obj, ProcessDebugRelocations RelocAction=ProcessDebugRelocations::Process, const LoadedObjectInfo *L=nullptr, std::string DWPName="", std::function< void(Error)> RecoverableErrorHandler=WithColor::defaultErrorHandler, std::function< void(Error)> WarningHandler=WithColor::defaultWarningHandler)
DWARFCompileUnit * getCompileUnitForOffset(uint64_t Offset)
Return the compile unit that includes an offset (relative to .debug_info).
const DWARFDebugNames & getDebugNames()
Get a reference to the parsed accelerator table object.
unsigned getNumDWOTypeUnits()
Get the number of type units in the DWO context.
Definition: DWARFContext.h:234
const DWARFDebugMacro * getDebugMacroDWO()
Get a pointer to the parsed DebugMacroDWO information object.
DILineInfoTable getLineInfoForAddressRange(object::SectionedAddress Address, uint64_t Size, DILineInfoSpecifier Specifier=DILineInfoSpecifier()) override
bool isLittleEndian() const
Definition: DWARFContext.h:379
DWARFUnit * getUnitAtIndex(unsigned index)
Get the unit at the specified index.
Definition: DWARFContext.h:240
const DWARFDebugLine::LineTable * getLineTableForUnit(DWARFUnit *U)
Get a pointer to a parsed line table corresponding to a compile unit.
void clearLineTableForUnit(DWARFUnit *U)
const AppleAcceleratorTable & getAppleTypes()
Get a reference to the parsed accelerator table object.
const AppleAcceleratorTable & getAppleNames()
Get a reference to the parsed accelerator table object.
compile_unit_range dwo_compile_units()
Get compile units in the DWO context.
Definition: DWARFContext.h:201
const DWARFDebugLoc * getDebugLoc()
Get a pointer to the parsed DebugLoc object.
const DWARFDebugMacro * getDebugMacinfoDWO()
Get a pointer to the parsed DebugMacinfoDWO information object.
bool verify(raw_ostream &OS, DIDumpOptions DumpOpts={}) override
unit_iterator_range dwo_types_section_units()
Get units from .debug_types.dwo in the DWO context.
Definition: DWARFContext.h:194
void dump(raw_ostream &OS, DIDumpOptions DumpOpts, std::array< std::optional< uint64_t >, DIDT_ID_Count > DumpOffsets)
Dump a textual representation to OS.
unit_iterator_range normal_units()
Get all normal compile/type units in this context.
Definition: DWARFContext.h:176
unit_iterator_range types_section_units()
Get units from .debug_types in this context.
Definition: DWARFContext.h:161
std::shared_ptr< DWARFContext > getDWOContext(StringRef AbsolutePath)
DWARFCompileUnit * getDWOCompileUnitForHash(uint64_t Hash)
unsigned getNumDWOCompileUnits()
Get the number of compile units in the DWO context.
Definition: DWARFContext.h:228
DILineInfo getLineInfoForDataAddress(object::SectionedAddress Address) override
const DWARFDebugAranges * getDebugAranges()
Get a pointer to the parsed DebugAranges object.
const DWARFUnitIndex & getCUIndex()
Expected< const DWARFDebugFrame * > getEHFrame()
Get a pointer to the parsed eh frame information object.
unit_iterator_range info_section_units()
Get units from .debug_info in this context.
Definition: DWARFContext.h:148
DWARFTypeUnit * getTypeUnitForHash(uint16_t Version, uint64_t Hash, bool IsDWO)
unit_iterator_range dwo_info_section_units()
Get units from .debug_info..dwo in the DWO context.
Definition: DWARFContext.h:182
DataExtractor getStringDWOExtractor() const
Definition: DWARFContext.h:343
const AppleAcceleratorTable & getAppleNamespaces()
Get a reference to the parsed accelerator table object.
const DWARFDebugMacro * getDebugMacro()
Get a pointer to the parsed DebugMacro information object.
const DWARFDebugMacro * getDebugMacinfo()
Get a pointer to the parsed DebugMacinfo information object.
unit_iterator_range dwo_units()
Get all units in the DWO context.
Definition: DWARFContext.h:210
A DataExtractor (typically for an in-memory copy of an object-file section) plus a relocation map for...
uint64_t getRelocatedValue(uint32_t Size, uint64_t *Off, uint64_t *SectionIndex=nullptr, Error *Err=nullptr) const
Extracts a value and applies a relocation to the result if one exists for the given offset.
void dump(raw_ostream &OS) const
A class representing an address table as specified in DWARF v5.
void dump(raw_ostream &OS, DIDumpOptions DumpOpts={}) const
Error extract(const DWARFDataExtractor &Data, uint64_t *OffsetPtr, uint16_t CUVersion, uint8_t CUAddrSize, std::function< void(Error)> WarnCallback)
Extract the entire table, including all addresses.
std::optional< uint64_t > getFullLength() const
Return the full length of this table, including the length field.
Error extract(DWARFDataExtractor data, uint64_t *offset_ptr, function_ref< void(Error)> WarningHandler)
void dump(raw_ostream &OS) const
uint64_t findAddress(uint64_t Address) const
Helper to allow for parsing of an entire .debug_line section in sequence.
void dump(raw_ostream &OS, const DWARFObject &Obj, DIDumpOptions DumpOpts, std::optional< uint64_t > Offset) const
Print the location lists found within the debug_loc section.
void dumpRange(uint64_t StartOffset, uint64_t Size, raw_ostream &OS, const DWARFObject &Obj, DIDumpOptions DumpOpts)
Dump all location lists within the given range.
.debug_names section consists of one or more units.
void dump(raw_ostream &OS) const override
Represents structure for holding and parsing .debug_pub* tables.
void extract(DWARFDataExtractor Data, bool GnuStyle, function_ref< void(Error)> RecoverableErrorHandler)
void dump(raw_ostream &OS) const
Error extract(const DWARFDataExtractor &data, uint64_t *offset_ptr)
void dump(raw_ostream &OS) const
Utility class that carries the DWARF compile/type unit and the debug info entry in an object.
Definition: DWARFDie.h:42
DWARFDie getAttributeValueAsReferencedDie(dwarf::Attribute Attr) const
Extract the specified attribute from this DIE as the referenced DIE.
Definition: DWARFDie.cpp:304
std::optional< DWARFFormValue > find(dwarf::Attribute Attr) const
Extract the specified attribute from this DIE.
Definition: DWARFDie.cpp:247
const char * getSubroutineName(DINameKind Kind) const
If a DIE represents a subprogram (or inlined subroutine), returns its mangled name (or short name,...
Definition: DWARFDie.cpp:436
void getCallerFrame(uint32_t &CallFile, uint32_t &CallLine, uint32_t &CallColumn, uint32_t &CallDiscriminator) const
Retrieves values of DW_AT_call_file, DW_AT_call_line and DW_AT_call_column from DIE (or zeroes if the...
Definition: DWARFDie.cpp:481
std::string getDeclFile(DILineInfoSpecifier::FileLineInfoKind Kind) const
Definition: DWARFDie.cpp:474
uint64_t getDeclLine() const
Returns the declaration line (start line) for a DIE, assuming it specifies a subprogram.
Definition: DWARFDie.cpp:469
dwarf::Tag getTag() const
Definition: DWARFDie.h:71
Expected< DWARFLocationExpressionsVector > getLocations(dwarf::Attribute Attr) const
Definition: DWARFDie.cpp:406
bool isValid() const
Definition: DWARFDie.h:50
void dump(raw_ostream &OS)
Error extract(DWARFDataExtractor Data, uint64_t *OffsetPtr)
Extract an entire table, including all list entries.
void dump(DWARFDataExtractor Data, raw_ostream &OS, llvm::function_ref< std::optional< object::SectionedAddress >(uint32_t)> LookupPooledAddress, DIDumpOptions DumpOpts={}) const
A class representing the header of a list table such as the range list table in the ....
bool dumpLocationList(uint64_t *Offset, raw_ostream &OS, std::optional< object::SectionedAddress > BaseAddr, const DWARFObject &Obj, DWARFUnit *U, DIDumpOptions DumpOpts, unsigned Indent) const
Dump the location list at the given Offset.
virtual void forEachInfoDWOSections(function_ref< void(const DWARFSection &)> F) const
Definition: DWARFObject.h:61
virtual StringRef getCUIndexSection() const
Definition: DWARFObject.h:82
void dump(raw_ostream &OS) const
Describe a collection of units.
Definition: DWARFUnit.h:123
void finishedInfoUnits()
Indicate that parsing .debug_info[.dwo] is done, and remaining units will be from ....
Definition: DWARFUnit.h:169
void addUnitsForSection(DWARFContext &C, const DWARFSection &Section, DWARFSectionKind SectionKind)
Read units from a .debug_info or .debug_types section.
Definition: DWARFUnit.cpp:42
DWARFUnit * getUnitForOffset(uint64_t Offset) const
Definition: DWARFUnit.cpp:145
void addUnitsForDWOSection(DWARFContext &C, const DWARFSection &DWOSection, DWARFSectionKind SectionKind, bool Lazy=false)
Read units from a .debug_info.dwo or .debug_types.dwo section.
Definition: DWARFUnit.cpp:53
DWARFUnit * getUnitForIndexEntry(const DWARFUnitIndex::Entry &E)
Definition: DWARFUnit.cpp:158
A class that verifies DWARF debug information given a DWARF Context.
Definition: DWARFVerifier.h:34
bool handleAccelTables()
Verify the information in accelerator tables, if they exist.
bool handleDebugTUIndex()
Verify the information in the .debug_tu_index section.
bool handleDebugCUIndex()
Verify the information in the .debug_cu_index section.
bool handleDebugInfo()
Verify the information in the .debug_info and .debug_types sections.
bool handleDebugLine()
Verify the information in the .debug_line section.
bool handleDebugAbbrev()
Verify the information in any of the following sections, if available: .debug_abbrev,...
const char * getCStr(uint64_t *OffsetPtr, Error *Err=nullptr) const
Extract a C string from *offset_ptr.
bool isValidOffset(uint64_t offset) const
Test the validity of offset.
Lightweight error class with error context and mandatory checking.
Definition: Error.h:156
static ErrorSuccess success()
Create a success value.
Definition: Error.h:330
Tagged union holding either a T or a Error.
Definition: Error.h:470
Error takeError()
Take ownership of the stored error.
Definition: Error.h:597
reference get()
Returns a reference to the stored T value.
Definition: Error.h:567
An inferface for inquiring the load address of a loaded object file to be used by the DIContext imple...
Definition: DIContext.h:267
This class implements a map that also provides access to all stored values in a deterministic order.
Definition: MapVector.h:37
Interface for looking up the initializer for a variable name, used by Init::resolveReferences.
Definition: Record.h:2148
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition: SmallString.h:26
bool empty() const
Definition: SmallVector.h:94
size_t size() const
Definition: SmallVector.h:91
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1200
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
Definition: StringMap.h:111
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition: StringRef.h:558
constexpr bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:134
constexpr size_t size() const
size - Get the string size.
Definition: StringRef.h:137
size_t find_first_not_of(char C, size_t From=0) const
Find the first character in the string that is not C or npos if not found.
Definition: StringRef.cpp:251
A switch()-like statement whose cases are string literals.
Definition: StringSwitch.h:44
StringSwitch & Case(StringLiteral S, T Value)
Definition: StringSwitch.h:69
R Default(T Value)
Definition: StringSwitch.h:182
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:44
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
static Twine utohexstr(const uint64_t &Val)
Definition: Twine.h:404
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
An efficient, type-erasing, non-owning reference to a callable.
A range adaptor for a pair of iterators.
Decompressor helps to handle decompression of compressed sections.
Definition: Decompressor.h:21
Error resizeAndDecompress(T &Out)
Resize the buffer and uncompress section data into it.
Definition: Decompressor.h:33
static Expected< Decompressor > create(StringRef Name, StringRef Data, bool IsLE, bool Is64Bit)
Create decompressor object.
MachO::any_relocation_info getRelocation(DataRefImpl Rel) const
bool isRelocationScattered(const MachO::any_relocation_info &RE) const
This class is the base class for all object file types.
Definition: ObjectFile.h:228
virtual section_iterator section_end() const =0
section_iterator_range sections() const
Definition: ObjectFile.h:327
static Expected< OwningBinary< ObjectFile > > createObjectFile(StringRef ObjectPath)
Definition: ObjectFile.cpp:194
virtual StringRef mapDebugSectionName(StringRef Name) const
Maps a debug section name to a standard DWARF section name.
Definition: ObjectFile.h:352
virtual bool isRelocatableObject() const =0
True if this is a relocatable object (.o/.obj).
This is a value type class that represents a single relocation in the list of relocations in the obje...
Definition: ObjectFile.h:51
symbol_iterator getSymbol() const
Definition: ObjectFile.h:567
DataRefImpl getRawDataRefImpl() const
Definition: ObjectFile.h:579
This is a value type class that represents a single section in the list of sections in the object fil...
Definition: ObjectFile.h:80
bool isCompressed() const
Definition: ObjectFile.h:489
Expected< uint64_t > getAddress() const
Returns the symbol virtual address (i.e.
Definition: ObjectFile.h:407
Expected< section_iterator > getSection() const
Get section this symbol is defined in reference to.
Definition: ObjectFile.h:423
virtual basic_symbol_iterator symbol_end() const =0
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
raw_ostream & write_uuid(const uuid_t UUID)
raw_ostream & write_escaped(StringRef Str, bool UseHexEscapes=false)
Output Str, turning '\', '\t', ' ', '"', and anything that doesn't satisfy llvm::isPrint into an esca...
uint8_t[16] uuid_t
Output a formatted UUID with dash separators.
Definition: raw_ostream.h:283
StringRef FormatString(DwarfFormat Format)
Definition: Dwarf.cpp:792
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
std::optional< const char * > toString(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract a string value from it.
std::optional< object::SectionedAddress > toSectionedAddress(const std::optional< DWARFFormValue > &V)
DwarfFormat
Constants that define the DWARF format as 32 or 64 bit.
Definition: Dwarf.h:91
@ DWARF32
Definition: Dwarf.h:91
std::optional< uint64_t > toSectionOffset(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract an section offset.
uint8_t getDwarfOffsetByteSize(DwarfFormat Format)
The size of a reference determined by the DWARF 32/64-bit format.
Definition: Dwarf.h:718
std::optional< uint64_t > toUnsigned(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract an unsigned constant.
uint64_t(*)(uint64_t Type, uint64_t Offset, uint64_t S, uint64_t LocData, int64_t Addend) RelocationResolver
Error createError(const Twine &Err)
Definition: Error.h:84
bool(*)(uint64_t) SupportsRelocation
std::pair< SupportsRelocation, RelocationResolver > getRelocationResolver(const ObjectFile &Obj)
StringRef extension(StringRef path, Style style=Style::native)
Get extension.
Definition: Path.cpp:590
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:406
@ Length
Definition: DWP.cpp:406
void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner={})
Log all errors (if any) in E to OS.
Definition: Error.cpp:63
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1802
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
Definition: Error.cpp:79
void append_range(Container &C, Range &&R)
Wrapper function to append a range to a container.
Definition: STLExtras.h:2092
int64_t decodeSLEB128(const uint8_t *p, unsigned *n=nullptr, const uint8_t *end=nullptr, const char **error=nullptr)
Utility function to decode a SLEB128 value.
Definition: LEB128.h:161
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition: Error.h:1246
@ DW_SECT_EXT_TYPES
void sort(IteratorTy Start, IteratorTy End)
Definition: STLExtras.h:1730
static Error createError(const Twine &Err)
Definition: APFloat.cpp:320
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:124
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
DINameKind
A DINameKind is passed to name search methods to specify a preference regarding the type of name reso...
Definition: DIContext.h:136
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1909
Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
Definition: Error.cpp:92
@ DIDT_ID_Count
Definition: DIContext.h:172
@ DIDT_All
Definition: DIContext.h:179
@ DIDT_UUID
Definition: DIContext.h:184
void consumeError(Error Err)
Consume a Error without doing anything.
Definition: Error.h:1043
Definition: BitVector.h:851
SymInfo contains information about symbol: it's address and section index which is -1LL for absolute ...
uint64_t Address
uint64_t SectionIndex
Container for dump options that control which debug information will be dumped.
Definition: DIContext.h:189
std::function< void(Error)> WarningHandler
Definition: DIContext.h:226
std::function< void(Error)> RecoverableErrorHandler
Definition: DIContext.h:224
DIDumpOptions noImplicitRecursion() const
Return the options with RecurseDepth set to 0 unless explicitly required.
Definition: DIContext.h:215
Controls which fields of DILineInfo container should be filled with data.
Definition: DIContext.h:140
DINameKind FunctionNameKind
Definition: DIContext.h:151
A format-neutral container for source line information.
Definition: DIContext.h:32
static constexpr const char *const BadString
Definition: DIContext.h:34
std::optional< uint64_t > StartAddress
Definition: DIContext.h:44
uint32_t Discriminator
Definition: DIContext.h:47
uint32_t Line
Definition: DIContext.h:41
std::string FileName
Definition: DIContext.h:37
std::string FunctionName
Definition: DIContext.h:38
uint32_t Column
Definition: DIContext.h:42
uint32_t StartLine
Definition: DIContext.h:43
std::string StartFileName
Definition: DIContext.h:39
Wraps the returned DIEs for a given address.
Definition: DWARFContext.h:351
bool getFileLineInfoForAddress(object::SectionedAddress Address, const char *CompDir, DILineInfoSpecifier::FileLineInfoKind Kind, DILineInfo &Result) const
Fills the Result argument with the file and line information corresponding to Address.
bool getFileNameByIndex(uint64_t FileIndex, StringRef CompDir, DILineInfoSpecifier::FileLineInfoKind Kind, std::string &Result) const
Extracts filename by its index in filename table in prologue.
bool lookupAddressRange(object::SectionedAddress Address, uint64_t Size, std::vector< uint32_t > &Result) const
Standard .debug_line state machine structure.
RelocAddrEntry contains relocated value and section index.
Definition: DWARFRelocMap.h:21