LLVM 22.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 <cstdint>
55#include <deque>
56#include <map>
57#include <string>
58#include <utility>
59#include <vector>
60
61using namespace llvm;
62using namespace dwarf;
63using namespace object;
64
65#define DEBUG_TYPE "dwarf"
66
68using FileLineInfoKind = DILineInfoSpecifier::FileLineInfoKind;
69using FunctionNameKind = DILineInfoSpecifier::FunctionNameKind;
70
71
74 using EntryMap = DenseMap<uint32_t, EntryType>;
75 EntryMap Map;
76 const auto &DObj = C.getDWARFObj();
77 if (DObj.getCUIndexSection().empty())
78 return;
79
80 uint64_t Offset = 0;
81 uint32_t TruncOffset = 0;
82 DObj.forEachInfoDWOSections([&](const DWARFSection &S) {
83 if (!(C.getParseCUTUIndexManually() ||
84 S.Data.size() >= std::numeric_limits<uint32_t>::max()))
85 return;
86
87 DWARFDataExtractor Data(DObj, S, C.isLittleEndian(), 0);
88 while (Data.isValidOffset(Offset)) {
89 DWARFUnitHeader Header;
90 if (Error ExtractionErr = Header.extract(
91 C, Data, &Offset, DWARFSectionKind::DW_SECT_INFO)) {
92 C.getWarningHandler()(
93 createError("Failed to parse CU header in DWP file: " +
94 toString(std::move(ExtractionErr))));
95 Map.clear();
96 break;
97 }
98
99 auto Iter = Map.insert({TruncOffset,
100 {Header.getOffset(), Header.getNextUnitOffset() -
101 Header.getOffset()}});
102 if (!Iter.second) {
104 createError("Collision occured between for truncated offset 0x" +
105 Twine::utohexstr(TruncOffset)),
106 errs());
107 Map.clear();
108 return;
109 }
110
111 Offset = Header.getNextUnitOffset();
112 TruncOffset = Offset;
113 }
114 });
115
116 if (Map.empty())
117 return;
118
119 for (DWARFUnitIndex::Entry &E : Index.getMutableRows()) {
120 if (!E.isValid())
121 continue;
122 DWARFUnitIndex::Entry::SectionContribution &CUOff = E.getContribution();
123 auto Iter = Map.find(CUOff.getOffset());
124 if (Iter == Map.end()) {
125 logAllUnhandledErrors(createError("Could not find CU offset 0x" +
126 Twine::utohexstr(CUOff.getOffset()) +
127 " in the Map"),
128 errs());
129 break;
130 }
131 CUOff.setOffset(Iter->second.getOffset());
132 if (CUOff.getOffset() != Iter->second.getOffset())
133 logAllUnhandledErrors(createError("Length of CU in CU index doesn't "
134 "match calculated length at offset 0x" +
135 Twine::utohexstr(CUOff.getOffset())),
136 errs());
137 }
138}
139
142
143 const auto &DObj = C.getDWARFObj();
144 DObj.forEachInfoDWOSections([&](const DWARFSection &S) {
145 if (!(C.getParseCUTUIndexManually() ||
146 S.Data.size() >= std::numeric_limits<uint32_t>::max()))
147 return;
148 DWARFDataExtractor Data(DObj, S, C.isLittleEndian(), 0);
149 uint64_t Offset = 0;
150 while (Data.isValidOffset(Offset)) {
151 DWARFUnitHeader Header;
152 if (Error ExtractionErr = Header.extract(
153 C, Data, &Offset, DWARFSectionKind::DW_SECT_INFO)) {
154 C.getWarningHandler()(
155 createError("Failed to parse CU header in DWP file: " +
156 toString(std::move(ExtractionErr))));
157 break;
158 }
159 bool CU = Header.getUnitType() == DW_UT_split_compile;
160 uint64_t Sig = CU ? *Header.getDWOId() : Header.getTypeHash();
161 Map[Sig] = Header.getOffset();
162 Offset = Header.getNextUnitOffset();
163 }
164 });
165 if (Map.empty())
166 return;
167 for (DWARFUnitIndex::Entry &E : Index.getMutableRows()) {
168 if (!E.isValid())
169 continue;
170 DWARFUnitIndex::Entry::SectionContribution &CUOff = E.getContribution();
171 auto Iter = Map.find(E.getSignature());
172 if (Iter == Map.end()) {
174 createError("Could not find unit with signature 0x" +
175 Twine::utohexstr(E.getSignature()) + " in the Map"),
176 errs());
177 break;
178 }
179 CUOff.setOffset(Iter->second);
180 }
181}
182
184 if (Index.getVersion() < 5)
186 else
188}
189
190template <typename T>
191static T &getAccelTable(std::unique_ptr<T> &Cache, const DWARFObject &Obj,
192 const DWARFSection &Section, StringRef StringSection,
193 bool IsLittleEndian) {
194 if (Cache)
195 return *Cache;
196 DWARFDataExtractor AccelSection(Obj, Section, IsLittleEndian, 0);
197 DataExtractor StrData(StringSection, IsLittleEndian, 0);
198 Cache = std::make_unique<T>(AccelSection, StrData);
199 if (Error E = Cache->extract())
200 llvm::consumeError(std::move(E));
201 return *Cache;
202}
203
204
205std::unique_ptr<DWARFDebugMacro>
207 auto Macro = std::make_unique<DWARFDebugMacro>();
208 auto ParseAndDump = [&](DWARFDataExtractor &Data, bool IsMacro) {
209 if (Error Err = IsMacro ? Macro->parseMacro(SectionType == MacroSection
210 ? D.compile_units()
211 : D.dwo_compile_units(),
212 SectionType == MacroSection
213 ? D.getStringExtractor()
214 : D.getStringDWOExtractor(),
215 Data)
216 : Macro->parseMacinfo(Data)) {
217 D.getRecoverableErrorHandler()(std::move(Err));
218 Macro = nullptr;
219 }
220 };
221 const DWARFObject &DObj = D.getDWARFObj();
222 switch (SectionType) {
223 case MacinfoSection: {
224 DWARFDataExtractor Data(DObj.getMacinfoSection(), D.isLittleEndian(), 0);
225 ParseAndDump(Data, /*IsMacro=*/false);
226 break;
227 }
228 case MacinfoDwoSection: {
229 DWARFDataExtractor Data(DObj.getMacinfoDWOSection(), D.isLittleEndian(), 0);
230 ParseAndDump(Data, /*IsMacro=*/false);
231 break;
232 }
233 case MacroSection: {
234 DWARFDataExtractor Data(DObj, DObj.getMacroSection(), D.isLittleEndian(),
235 0);
236 ParseAndDump(Data, /*IsMacro=*/true);
237 break;
238 }
239 case MacroDwoSection: {
240 DWARFDataExtractor Data(DObj.getMacroDWOSection(), D.isLittleEndian(), 0);
241 ParseAndDump(Data, /*IsMacro=*/true);
242 break;
243 }
244 }
245 return Macro;
246}
247
248namespace {
249class ThreadUnsafeDWARFContextState : public DWARFContext::DWARFContextState {
250
251 DWARFUnitVector NormalUnits;
252 std::optional<DenseMap<uint64_t, DWARFTypeUnit *>> NormalTypeUnits;
253 std::unique_ptr<DWARFUnitIndex> CUIndex;
254 std::unique_ptr<DWARFGdbIndex> GdbIndex;
255 std::unique_ptr<DWARFUnitIndex> TUIndex;
256 std::unique_ptr<DWARFDebugAbbrev> Abbrev;
257 std::unique_ptr<DWARFDebugLoc> Loc;
258 std::unique_ptr<DWARFDebugAranges> Aranges;
259 std::unique_ptr<DWARFDebugLine> Line;
260 std::unique_ptr<DWARFDebugFrame> DebugFrame;
261 std::unique_ptr<DWARFDebugFrame> EHFrame;
262 std::unique_ptr<DWARFDebugMacro> Macro;
263 std::unique_ptr<DWARFDebugMacro> Macinfo;
264 std::unique_ptr<DWARFDebugNames> Names;
265 std::unique_ptr<AppleAcceleratorTable> AppleNames;
266 std::unique_ptr<AppleAcceleratorTable> AppleTypes;
267 std::unique_ptr<AppleAcceleratorTable> AppleNamespaces;
268 std::unique_ptr<AppleAcceleratorTable> AppleObjC;
269 DWARFUnitVector DWOUnits;
270 std::optional<DenseMap<uint64_t, DWARFTypeUnit *>> DWOTypeUnits;
271 std::unique_ptr<DWARFDebugAbbrev> AbbrevDWO;
272 std::unique_ptr<DWARFDebugMacro> MacinfoDWO;
273 std::unique_ptr<DWARFDebugMacro> MacroDWO;
274 struct DWOFile {
276 std::unique_ptr<DWARFContext> Context;
277 };
279 std::weak_ptr<DWOFile> DWP;
280 bool CheckedForDWP = false;
281 std::string DWPName;
282
283public:
284 ThreadUnsafeDWARFContextState(DWARFContext &DC, std::string &DWP) :
285 DWARFContext::DWARFContextState(DC),
286 DWPName(std::move(DWP)) {}
287
288 DWARFUnitVector &getNormalUnits() override {
289 if (NormalUnits.empty()) {
290 const DWARFObject &DObj = D.getDWARFObj();
291 DObj.forEachInfoSections([&](const DWARFSection &S) {
292 NormalUnits.addUnitsForSection(D, S, DW_SECT_INFO);
293 });
294 NormalUnits.finishedInfoUnits();
295 DObj.forEachTypesSections([&](const DWARFSection &S) {
296 NormalUnits.addUnitsForSection(D, S, DW_SECT_EXT_TYPES);
297 });
298 }
299 return NormalUnits;
300 }
301
302 DWARFUnitVector &getDWOUnits(bool Lazy) override {
303 if (DWOUnits.empty()) {
304 const DWARFObject &DObj = D.getDWARFObj();
305
306 DObj.forEachInfoDWOSections([&](const DWARFSection &S) {
307 DWOUnits.addUnitsForDWOSection(D, S, DW_SECT_INFO, Lazy);
308 });
309 DWOUnits.finishedInfoUnits();
310 DObj.forEachTypesDWOSections([&](const DWARFSection &S) {
311 DWOUnits.addUnitsForDWOSection(D, S, DW_SECT_EXT_TYPES, Lazy);
312 });
313 }
314 return DWOUnits;
315 }
316
317 const DWARFDebugAbbrev *getDebugAbbrevDWO() override {
318 if (AbbrevDWO)
319 return AbbrevDWO.get();
320 const DWARFObject &DObj = D.getDWARFObj();
321 DataExtractor abbrData(DObj.getAbbrevDWOSection(), D.isLittleEndian(), 0);
322 AbbrevDWO = std::make_unique<DWARFDebugAbbrev>(abbrData);
323 return AbbrevDWO.get();
324 }
325
326 const DWARFUnitIndex &getCUIndex() override {
327 if (CUIndex)
328 return *CUIndex;
329
330 DataExtractor Data(D.getDWARFObj().getCUIndexSection(),
331 D.isLittleEndian(), 0);
332 CUIndex = std::make_unique<DWARFUnitIndex>(DW_SECT_INFO);
333 if (CUIndex->parse(Data))
334 fixupIndex(D, *CUIndex);
335 return *CUIndex;
336 }
337 const DWARFUnitIndex &getTUIndex() override {
338 if (TUIndex)
339 return *TUIndex;
340
341 DataExtractor Data(D.getDWARFObj().getTUIndexSection(),
342 D.isLittleEndian(), 0);
343 TUIndex = std::make_unique<DWARFUnitIndex>(DW_SECT_EXT_TYPES);
344 bool isParseSuccessful = TUIndex->parse(Data);
345 // If we are parsing TU-index and for .debug_types section we don't need
346 // to do anything.
347 if (isParseSuccessful && TUIndex->getVersion() != 2)
348 fixupIndex(D, *TUIndex);
349 return *TUIndex;
350 }
351
352 DWARFGdbIndex &getGdbIndex() override {
353 if (GdbIndex)
354 return *GdbIndex;
355
356 DataExtractor Data(D.getDWARFObj().getGdbIndexSection(), true /*LE*/, 0);
357 GdbIndex = std::make_unique<DWARFGdbIndex>();
358 GdbIndex->parse(Data);
359 return *GdbIndex;
360 }
361
362 const DWARFDebugAbbrev *getDebugAbbrev() override {
363 if (Abbrev)
364 return Abbrev.get();
365
366 DataExtractor Data(D.getDWARFObj().getAbbrevSection(),
367 D.isLittleEndian(), 0);
368 Abbrev = std::make_unique<DWARFDebugAbbrev>(Data);
369 return Abbrev.get();
370 }
371
372 const DWARFDebugLoc *getDebugLoc() override {
373 if (Loc)
374 return Loc.get();
375
376 const DWARFObject &DObj = D.getDWARFObj();
377 // Assume all units have the same address byte size.
378 auto Data =
379 D.getNumCompileUnits()
380 ? DWARFDataExtractor(DObj, DObj.getLocSection(), D.isLittleEndian(),
381 D.getUnitAtIndex(0)->getAddressByteSize())
382 : DWARFDataExtractor("", D.isLittleEndian(), 0);
383 Loc = std::make_unique<DWARFDebugLoc>(std::move(Data));
384 return Loc.get();
385 }
386
387 const DWARFDebugAranges *getDebugAranges() override {
388 if (Aranges)
389 return Aranges.get();
390
391 Aranges = std::make_unique<DWARFDebugAranges>();
392 Aranges->generate(&D);
393 return Aranges.get();
394 }
395
396 Expected<const DWARFDebugLine::LineTable *>
397 getLineTableForUnit(DWARFUnit *U, function_ref<void(Error)> RecoverableErrorHandler) override {
398 if (!Line)
399 Line = std::make_unique<DWARFDebugLine>();
400
401 auto UnitDIE = U->getUnitDIE();
402 if (!UnitDIE)
403 return nullptr;
404
405 auto Offset = toSectionOffset(UnitDIE.find(DW_AT_stmt_list));
406 if (!Offset)
407 return nullptr; // No line table for this compile unit.
408
409 uint64_t stmtOffset = *Offset + U->getLineTableOffset();
410 // See if the line table is cached.
411 if (const DWARFLineTable *lt = Line->getLineTable(stmtOffset))
412 return lt;
413
414 // Make sure the offset is good before we try to parse.
415 if (stmtOffset >= U->getLineSection().Data.size())
416 return nullptr;
417
418 // We have to parse it first.
419 DWARFDataExtractor Data(U->getContext().getDWARFObj(), U->getLineSection(),
420 U->isLittleEndian(), U->getAddressByteSize());
421 return Line->getOrParseLineTable(Data, stmtOffset, U->getContext(), U,
422 RecoverableErrorHandler);
423
424 }
425
426 void clearLineTableForUnit(DWARFUnit *U) override {
427 if (!Line)
428 return;
429
430 auto UnitDIE = U->getUnitDIE();
431 if (!UnitDIE)
432 return;
433
434 auto Offset = toSectionOffset(UnitDIE.find(DW_AT_stmt_list));
435 if (!Offset)
436 return;
437
438 uint64_t stmtOffset = *Offset + U->getLineTableOffset();
439 Line->clearLineTable(stmtOffset);
440 }
441
442 Expected<const DWARFDebugFrame *> getDebugFrame() override {
443 if (DebugFrame)
444 return DebugFrame.get();
445 const DWARFObject &DObj = D.getDWARFObj();
446 const DWARFSection &DS = DObj.getFrameSection();
447
448 // There's a "bug" in the DWARFv3 standard with respect to the target address
449 // size within debug frame sections. While DWARF is supposed to be independent
450 // of its container, FDEs have fields with size being "target address size",
451 // which isn't specified in DWARF in general. It's only specified for CUs, but
452 // .eh_frame can appear without a .debug_info section. Follow the example of
453 // other tools (libdwarf) and extract this from the container (ObjectFile
454 // provides this information). This problem is fixed in DWARFv4
455 // See this dwarf-discuss discussion for more details:
456 // http://lists.dwarfstd.org/htdig.cgi/dwarf-discuss-dwarfstd.org/2011-December/001173.html
457 DWARFDataExtractor Data(DObj, DS, D.isLittleEndian(),
458 DObj.getAddressSize());
459 auto DF =
460 std::make_unique<DWARFDebugFrame>(D.getArch(), /*IsEH=*/false,
461 DS.Address);
462 if (Error E = DF->parse(Data))
463 return std::move(E);
464
465 DebugFrame.swap(DF);
466 return DebugFrame.get();
467 }
468
469 Expected<const DWARFDebugFrame *> getEHFrame() override {
470 if (EHFrame)
471 return EHFrame.get();
472 const DWARFObject &DObj = D.getDWARFObj();
473
474 const DWARFSection &DS = DObj.getEHFrameSection();
475 DWARFDataExtractor Data(DObj, DS, D.isLittleEndian(),
476 DObj.getAddressSize());
477 auto DF =
478 std::make_unique<DWARFDebugFrame>(D.getArch(), /*IsEH=*/true,
479 DS.Address);
480 if (Error E = DF->parse(Data))
481 return std::move(E);
482 EHFrame.swap(DF);
483 return EHFrame.get();
484 }
485
486 const DWARFDebugMacro *getDebugMacinfo() override {
487 if (!Macinfo)
488 Macinfo = parseMacroOrMacinfo(MacinfoSection);
489 return Macinfo.get();
490 }
491 const DWARFDebugMacro *getDebugMacinfoDWO() override {
492 if (!MacinfoDWO)
493 MacinfoDWO = parseMacroOrMacinfo(MacinfoDwoSection);
494 return MacinfoDWO.get();
495 }
496 const DWARFDebugMacro *getDebugMacro() override {
497 if (!Macro)
498 Macro = parseMacroOrMacinfo(MacroSection);
499 return Macro.get();
500 }
501 const DWARFDebugMacro *getDebugMacroDWO() override {
502 if (!MacroDWO)
503 MacroDWO = parseMacroOrMacinfo(MacroDwoSection);
504 return MacroDWO.get();
505 }
506 const DWARFDebugNames &getDebugNames() override {
507 const DWARFObject &DObj = D.getDWARFObj();
508 return getAccelTable(Names, DObj, DObj.getNamesSection(),
509 DObj.getStrSection(), D.isLittleEndian());
510 }
511 const AppleAcceleratorTable &getAppleNames() override {
512 const DWARFObject &DObj = D.getDWARFObj();
513 return getAccelTable(AppleNames, DObj, DObj.getAppleNamesSection(),
514 DObj.getStrSection(), D.isLittleEndian());
515
516 }
517 const AppleAcceleratorTable &getAppleTypes() override {
518 const DWARFObject &DObj = D.getDWARFObj();
519 return getAccelTable(AppleTypes, DObj, DObj.getAppleTypesSection(),
520 DObj.getStrSection(), D.isLittleEndian());
521
522 }
523 const AppleAcceleratorTable &getAppleNamespaces() override {
524 const DWARFObject &DObj = D.getDWARFObj();
525 return getAccelTable(AppleNamespaces, DObj,
527 DObj.getStrSection(), D.isLittleEndian());
528
529 }
530 const AppleAcceleratorTable &getAppleObjC() override {
531 const DWARFObject &DObj = D.getDWARFObj();
532 return getAccelTable(AppleObjC, DObj, DObj.getAppleObjCSection(),
533 DObj.getStrSection(), D.isLittleEndian());
534 }
535
536 std::shared_ptr<DWARFContext>
537 getDWOContext(StringRef AbsolutePath) override {
538 if (auto S = DWP.lock()) {
539 DWARFContext *Ctxt = S->Context.get();
540 return std::shared_ptr<DWARFContext>(std::move(S), Ctxt);
541 }
542
543 std::weak_ptr<DWOFile> *Entry = &DWOFiles[AbsolutePath];
544
545 if (auto S = Entry->lock()) {
546 DWARFContext *Ctxt = S->Context.get();
547 return std::shared_ptr<DWARFContext>(std::move(S), Ctxt);
548 }
549
550 const DWARFObject &DObj = D.getDWARFObj();
551
552 Expected<OwningBinary<ObjectFile>> Obj = [&] {
553 if (!CheckedForDWP) {
554 SmallString<128> DWPName;
556 this->DWPName.empty()
557 ? (DObj.getFileName() + ".dwp").toStringRef(DWPName)
558 : StringRef(this->DWPName));
559 if (Obj) {
560 Entry = &DWP;
561 return Obj;
562 } else {
563 CheckedForDWP = true;
564 // TODO: Should this error be handled (maybe in a high verbosity mode)
565 // before falling back to .dwo files?
566 consumeError(Obj.takeError());
567 }
568 }
569
570 return object::ObjectFile::createObjectFile(AbsolutePath);
571 }();
572
573 if (!Obj) {
574 // TODO: Actually report errors helpfully.
575 consumeError(Obj.takeError());
576 return nullptr;
577 }
578
579 auto S = std::make_shared<DWOFile>();
580 S->File = std::move(Obj.get());
581 // Allow multi-threaded access if there is a .dwp file as the CU index and
582 // TU index might be accessed from multiple threads.
583 bool ThreadSafe = isThreadSafe();
584 S->Context = DWARFContext::create(
585 *S->File.getBinary(), DWARFContext::ProcessDebugRelocations::Ignore,
588 *Entry = S;
589 auto *Ctxt = S->Context.get();
590 return std::shared_ptr<DWARFContext>(std::move(S), Ctxt);
591 }
592
593 bool isThreadSafe() const override { return false; }
594
595 const DenseMap<uint64_t, DWARFTypeUnit *> &getNormalTypeUnitMap() {
596 if (!NormalTypeUnits) {
597 NormalTypeUnits.emplace();
598 for (const auto &U :D.normal_units()) {
599 if (DWARFTypeUnit *TU = dyn_cast<DWARFTypeUnit>(U.get()))
600 (*NormalTypeUnits)[TU->getTypeHash()] = TU;
601 }
602 }
603 return *NormalTypeUnits;
604 }
605
606 const DenseMap<uint64_t, DWARFTypeUnit *> &getDWOTypeUnitMap() {
607 if (!DWOTypeUnits) {
608 DWOTypeUnits.emplace();
609 for (const auto &U :D.dwo_units()) {
610 if (DWARFTypeUnit *TU = dyn_cast<DWARFTypeUnit>(U.get()))
611 (*DWOTypeUnits)[TU->getTypeHash()] = TU;
612 }
613 }
614 return *DWOTypeUnits;
615 }
616
617 const DenseMap<uint64_t, DWARFTypeUnit *> &
618 getTypeUnitMap(bool IsDWO) override {
619 if (IsDWO)
620 return getDWOTypeUnitMap();
621 else
622 return getNormalTypeUnitMap();
623 }
624};
625
626class ThreadSafeState : public ThreadUnsafeDWARFContextState {
627 std::recursive_mutex Mutex;
628
629public:
630 ThreadSafeState(DWARFContext &DC, std::string &DWP) :
631 ThreadUnsafeDWARFContextState(DC, DWP) {}
632
633 DWARFUnitVector &getNormalUnits() override {
634 std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
635 return ThreadUnsafeDWARFContextState::getNormalUnits();
636 }
637 DWARFUnitVector &getDWOUnits(bool Lazy) override {
638 std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
639 // We need to not do lazy parsing when we need thread safety as
640 // DWARFUnitVector, in lazy mode, will slowly add things to itself and
641 // will cause problems in a multi-threaded environment.
642 return ThreadUnsafeDWARFContextState::getDWOUnits(false);
643 }
644 const DWARFUnitIndex &getCUIndex() override {
645 std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
646 return ThreadUnsafeDWARFContextState::getCUIndex();
647 }
648 const DWARFDebugAbbrev *getDebugAbbrevDWO() override {
649 std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
650 return ThreadUnsafeDWARFContextState::getDebugAbbrevDWO();
651 }
652
653 const DWARFUnitIndex &getTUIndex() override {
654 std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
655 return ThreadUnsafeDWARFContextState::getTUIndex();
656 }
657 DWARFGdbIndex &getGdbIndex() override {
658 std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
659 return ThreadUnsafeDWARFContextState::getGdbIndex();
660 }
661 const DWARFDebugAbbrev *getDebugAbbrev() override {
662 std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
663 return ThreadUnsafeDWARFContextState::getDebugAbbrev();
664 }
665 const DWARFDebugLoc *getDebugLoc() override {
666 std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
667 return ThreadUnsafeDWARFContextState::getDebugLoc();
668 }
669 const DWARFDebugAranges *getDebugAranges() override {
670 std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
671 return ThreadUnsafeDWARFContextState::getDebugAranges();
672 }
673 Expected<const DWARFDebugLine::LineTable *>
674 getLineTableForUnit(DWARFUnit *U, function_ref<void(Error)> RecoverableErrorHandler) override {
675 std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
676 return ThreadUnsafeDWARFContextState::getLineTableForUnit(U, RecoverableErrorHandler);
677 }
678 void clearLineTableForUnit(DWARFUnit *U) override {
679 std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
680 return ThreadUnsafeDWARFContextState::clearLineTableForUnit(U);
681 }
682 Expected<const DWARFDebugFrame *> getDebugFrame() override {
683 std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
684 return ThreadUnsafeDWARFContextState::getDebugFrame();
685 }
686 Expected<const DWARFDebugFrame *> getEHFrame() override {
687 std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
688 return ThreadUnsafeDWARFContextState::getEHFrame();
689 }
690 const DWARFDebugMacro *getDebugMacinfo() override {
691 std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
692 return ThreadUnsafeDWARFContextState::getDebugMacinfo();
693 }
694 const DWARFDebugMacro *getDebugMacinfoDWO() override {
695 std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
696 return ThreadUnsafeDWARFContextState::getDebugMacinfoDWO();
697 }
698 const DWARFDebugMacro *getDebugMacro() override {
699 std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
700 return ThreadUnsafeDWARFContextState::getDebugMacro();
701 }
702 const DWARFDebugMacro *getDebugMacroDWO() override {
703 std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
704 return ThreadUnsafeDWARFContextState::getDebugMacroDWO();
705 }
706 const DWARFDebugNames &getDebugNames() override {
707 std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
708 return ThreadUnsafeDWARFContextState::getDebugNames();
709 }
710 const AppleAcceleratorTable &getAppleNames() override {
711 std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
712 return ThreadUnsafeDWARFContextState::getAppleNames();
713 }
714 const AppleAcceleratorTable &getAppleTypes() override {
715 std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
716 return ThreadUnsafeDWARFContextState::getAppleTypes();
717 }
718 const AppleAcceleratorTable &getAppleNamespaces() override {
719 std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
720 return ThreadUnsafeDWARFContextState::getAppleNamespaces();
721 }
722 const AppleAcceleratorTable &getAppleObjC() override {
723 std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
724 return ThreadUnsafeDWARFContextState::getAppleObjC();
725 }
726 std::shared_ptr<DWARFContext>
727 getDWOContext(StringRef AbsolutePath) override {
728 std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
729 return ThreadUnsafeDWARFContextState::getDWOContext(AbsolutePath);
730 }
731
732 bool isThreadSafe() const override { return true; }
733
734 const DenseMap<uint64_t, DWARFTypeUnit *> &
735 getTypeUnitMap(bool IsDWO) override {
736 std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
737 return ThreadUnsafeDWARFContextState::getTypeUnitMap(IsDWO);
738 }
739};
740} // namespace
741
742DWARFContext::DWARFContext(std::unique_ptr<const DWARFObject> DObj,
743 std::string DWPName,
744 std::function<void(Error)> RecoverableErrorHandler,
745 std::function<void(Error)> WarningHandler,
746 bool ThreadSafe)
748 RecoverableErrorHandler(RecoverableErrorHandler),
749 WarningHandler(WarningHandler), DObj(std::move(DObj)) {
750 if (ThreadSafe)
751 State = std::make_unique<ThreadSafeState>(*this, DWPName);
752 else
753 State = std::make_unique<ThreadUnsafeDWARFContextState>(*this, DWPName);
754 }
755
757
758/// Dump the UUID load command.
759static void dumpUUID(raw_ostream &OS, const ObjectFile &Obj) {
760 auto *MachO = dyn_cast<MachOObjectFile>(&Obj);
761 if (!MachO)
762 return;
763 for (auto LC : MachO->load_commands()) {
765 if (LC.C.cmd == MachO::LC_UUID) {
766 if (LC.C.cmdsize < sizeof(UUID) + sizeof(LC.C)) {
767 OS << "error: UUID load command is too short.\n";
768 return;
769 }
770 OS << "UUID: ";
771 memcpy(&UUID, LC.Ptr+sizeof(LC.C), sizeof(UUID));
772 OS.write_uuid(UUID);
773 Triple T = MachO->getArchTriple();
774 OS << " (" << T.getArchName() << ')';
775 OS << ' ' << MachO->getFileName() << '\n';
776 }
777 }
778}
779
781 std::vector<std::optional<StrOffsetsContributionDescriptor>>;
782
783// Collect all the contributions to the string offsets table from all units,
784// sort them by their starting offsets and remove duplicates.
787 ContributionCollection Contributions;
788 for (const auto &U : Units)
789 if (const auto &C = U->getStringOffsetsTableContribution())
790 Contributions.push_back(C);
791 // Sort the contributions so that any invalid ones are placed at
792 // the start of the contributions vector. This way they are reported
793 // first.
794 llvm::sort(Contributions,
795 [](const std::optional<StrOffsetsContributionDescriptor> &L,
796 const std::optional<StrOffsetsContributionDescriptor> &R) {
797 if (L && R)
798 return L->Base < R->Base;
799 return R.has_value();
800 });
801
802 // Uniquify contributions, as it is possible that units (specifically
803 // type units in dwo or dwp files) share contributions. We don't want
804 // to report them more than once.
805 Contributions.erase(
807 Contributions,
808 [](const std::optional<StrOffsetsContributionDescriptor> &L,
809 const std::optional<StrOffsetsContributionDescriptor> &R) {
810 if (L && R)
811 return L->Base == R->Base && L->Size == R->Size;
812 return false;
813 }),
814 Contributions.end());
815 return Contributions;
816}
817
818// Dump a DWARF string offsets section. This may be a DWARF v5 formatted
819// string offsets section, where each compile or type unit contributes a
820// number of entries (string offsets), with each contribution preceded by
821// a header containing size and version number. Alternatively, it may be a
822// monolithic series of string offsets, as generated by the pre-DWARF v5
823// implementation of split DWARF; however, in that case we still need to
824// collect contributions of units because the size of the offsets (4 or 8
825// bytes) depends on the format of the referencing unit (DWARF32 or DWARF64).
828 const DWARFObject &Obj,
829 const DWARFSection &StringOffsetsSection,
830 StringRef StringSection,
832 bool LittleEndian) {
833 auto Contributions = collectContributionData(Units);
834 DWARFDataExtractor StrOffsetExt(Obj, StringOffsetsSection, LittleEndian, 0);
835 DataExtractor StrData(StringSection, LittleEndian, 0);
836 uint64_t SectionSize = StringOffsetsSection.Data.size();
837 uint64_t Offset = 0;
838 for (auto &Contribution : Contributions) {
839 // Report an ill-formed contribution.
840 if (!Contribution) {
841 OS << "error: invalid contribution to string offsets table in section ."
842 << SectionName << ".\n";
843 return;
844 }
845
846 dwarf::DwarfFormat Format = Contribution->getFormat();
847 int OffsetDumpWidth = 2 * dwarf::getDwarfOffsetByteSize(Format);
848 uint16_t Version = Contribution->getVersion();
849 uint64_t ContributionHeader = Contribution->Base;
850 // In DWARF v5 there is a contribution header that immediately precedes
851 // the string offsets base (the location we have previously retrieved from
852 // the CU DIE's DW_AT_str_offsets attribute). The header is located either
853 // 8 or 16 bytes before the base, depending on the contribution's format.
854 if (Version >= 5)
855 ContributionHeader -= Format == DWARF32 ? 8 : 16;
856
857 // Detect overlapping contributions.
858 if (Offset > ContributionHeader) {
861 "overlapping contributions to string offsets table in section .%s.",
862 SectionName.data()));
863 }
864 // Report a gap in the table.
865 if (Offset < ContributionHeader) {
866 OS << format("0x%8.8" PRIx64 ": Gap, length = ", Offset);
867 OS << (ContributionHeader - Offset) << "\n";
868 }
869 OS << format("0x%8.8" PRIx64 ": ", ContributionHeader);
870 // In DWARF v5 the contribution size in the descriptor does not equal
871 // the originally encoded length (it does not contain the length of the
872 // version field and the padding, a total of 4 bytes). Add them back in
873 // for reporting.
874 OS << "Contribution size = " << (Contribution->Size + (Version < 5 ? 0 : 4))
875 << ", Format = " << dwarf::FormatString(Format)
876 << ", Version = " << Version << "\n";
877
878 Offset = Contribution->Base;
879 unsigned EntrySize = Contribution->getDwarfOffsetByteSize();
880 while (Offset - Contribution->Base < Contribution->Size) {
881 OS << format("0x%8.8" PRIx64 ": ", Offset);
882 uint64_t StringOffset =
883 StrOffsetExt.getRelocatedValue(EntrySize, &Offset);
884 OS << format("%0*" PRIx64 " ", OffsetDumpWidth, StringOffset);
885 const char *S = StrData.getCStr(&StringOffset);
886 if (S)
887 OS << format("\"%s\"", S);
888 OS << "\n";
889 }
890 }
891 // Report a gap at the end of the table.
892 if (Offset < SectionSize) {
893 OS << format("0x%8.8" PRIx64 ": Gap, length = ", Offset);
894 OS << (SectionSize - Offset) << "\n";
895 }
896}
897
898// Dump the .debug_addr section.
900 DIDumpOptions DumpOpts, uint16_t Version,
901 uint8_t AddrSize) {
902 uint64_t Offset = 0;
903 while (AddrData.isValidOffset(Offset)) {
904 DWARFDebugAddrTable AddrTable;
905 uint64_t TableOffset = Offset;
906 if (Error Err = AddrTable.extract(AddrData, &Offset, Version, AddrSize,
907 DumpOpts.WarningHandler)) {
908 DumpOpts.RecoverableErrorHandler(std::move(Err));
909 // Keep going after an error, if we can, assuming that the length field
910 // could be read. If it couldn't, stop reading the section.
911 if (auto TableLength = AddrTable.getFullLength()) {
912 Offset = TableOffset + *TableLength;
913 continue;
914 }
915 break;
916 }
917 AddrTable.dump(OS, DumpOpts);
918 }
919}
920
921// Dump the .debug_rnglists or .debug_rnglists.dwo section (DWARF v5).
923 raw_ostream &OS, DWARFDataExtractor &rnglistData,
924 llvm::function_ref<std::optional<object::SectionedAddress>(uint32_t)>
925 LookupPooledAddress,
926 DIDumpOptions DumpOpts) {
927 uint64_t Offset = 0;
928 while (rnglistData.isValidOffset(Offset)) {
930 uint64_t TableOffset = Offset;
931 if (Error Err = Rnglists.extract(rnglistData, &Offset)) {
932 DumpOpts.RecoverableErrorHandler(std::move(Err));
933 uint64_t Length = Rnglists.length();
934 // Keep going after an error, if we can, assuming that the length field
935 // could be read. If it couldn't, stop reading the section.
936 if (Length == 0)
937 break;
938 Offset = TableOffset + Length;
939 } else {
940 Rnglists.dump(rnglistData, OS, LookupPooledAddress, DumpOpts);
941 }
942 }
943}
944
945
948 std::optional<uint64_t> DumpOffset) {
949 uint64_t Offset = 0;
950
951 while (Data.isValidOffset(Offset)) {
952 DWARFListTableHeader Header(".debug_loclists", "locations");
953 if (Error E = Header.extract(Data, &Offset)) {
954 DumpOpts.RecoverableErrorHandler(std::move(E));
955 return;
956 }
957
958 Header.dump(Data, OS, DumpOpts);
959
960 uint64_t EndOffset = Header.length() + Header.getHeaderOffset();
961 Data.setAddressSize(Header.getAddrSize());
962 DWARFDebugLoclists Loc(Data, Header.getVersion());
963 if (DumpOffset) {
964 if (DumpOffset >= Offset && DumpOffset < EndOffset) {
965 Offset = *DumpOffset;
966 Loc.dumpLocationList(&Offset, OS, /*BaseAddr=*/std::nullopt, Obj,
967 nullptr, DumpOpts, /*Indent=*/0);
968 OS << "\n";
969 return;
970 }
971 } else {
972 Loc.dumpRange(Offset, EndOffset - Offset, OS, Obj, DumpOpts);
973 }
974 Offset = EndOffset;
975 }
976}
977
979 DWARFDataExtractor Data, bool GnuStyle) {
980 DWARFDebugPubTable Table;
981 Table.extract(Data, GnuStyle, DumpOpts.RecoverableErrorHandler);
982 Table.dump(OS);
983}
984
986 raw_ostream &OS, DIDumpOptions DumpOpts,
987 std::array<std::optional<uint64_t>, DIDT_ID_Count> DumpOffsets) {
988 uint64_t DumpType = DumpOpts.DumpType;
989
990 StringRef Extension = sys::path::extension(DObj->getFileName());
991 bool IsDWO = (Extension == ".dwo") || (Extension == ".dwp");
992
993 // Print UUID header.
994 const auto *ObjFile = DObj->getFile();
995 if (DumpType & DIDT_UUID)
996 dumpUUID(OS, *ObjFile);
997
998 // Print a header for each explicitly-requested section.
999 // Otherwise just print one for non-empty sections.
1000 // Only print empty .dwo section headers when dumping a .dwo file.
1001 bool Explicit = DumpType != DIDT_All && !IsDWO;
1002 bool ExplicitDWO = Explicit && IsDWO;
1003 auto shouldDump = [&](bool Explicit, const char *Name, unsigned ID,
1004 StringRef Section) -> std::optional<uint64_t> * {
1005 unsigned Mask = 1U << ID;
1006 bool Should = (DumpType & Mask) && (Explicit || !Section.empty());
1007 if (!Should)
1008 return nullptr;
1009 OS << "\n" << Name << " contents:\n";
1010 return &DumpOffsets[ID];
1011 };
1012
1013 // Dump individual sections.
1014 if (shouldDump(Explicit, ".debug_abbrev", DIDT_ID_DebugAbbrev,
1015 DObj->getAbbrevSection()))
1016 getDebugAbbrev()->dump(OS);
1017 if (shouldDump(ExplicitDWO, ".debug_abbrev.dwo", DIDT_ID_DebugAbbrev,
1018 DObj->getAbbrevDWOSection()))
1019 getDebugAbbrevDWO()->dump(OS);
1020
1021 auto dumpDebugInfo = [&](const char *Name, unit_iterator_range Units) {
1022 OS << '\n' << Name << " contents:\n";
1023 if (auto DumpOffset = DumpOffsets[DIDT_ID_DebugInfo])
1024 for (const auto &U : Units) {
1025 U->getDIEForOffset(*DumpOffset)
1026 .dump(OS, 0, DumpOpts.noImplicitRecursion());
1027 DWARFDie CUDie = U->getUnitDIE(false);
1028 DWARFDie CUNonSkeletonDie = U->getNonSkeletonUnitDIE(false);
1029 if (CUNonSkeletonDie && CUDie != CUNonSkeletonDie) {
1030 CUNonSkeletonDie.getDwarfUnit()
1031 ->getDIEForOffset(*DumpOffset)
1032 .dump(OS, 0, DumpOpts.noImplicitRecursion());
1033 }
1034 }
1035 else
1036 for (const auto &U : Units)
1037 U->dump(OS, DumpOpts);
1038 };
1039 if ((DumpType & DIDT_DebugInfo)) {
1040 if (Explicit || getNumCompileUnits())
1041 dumpDebugInfo(".debug_info", info_section_units());
1042 if (ExplicitDWO || getNumDWOCompileUnits())
1043 dumpDebugInfo(".debug_info.dwo", dwo_info_section_units());
1044 }
1045
1046 auto dumpDebugType = [&](const char *Name, unit_iterator_range Units) {
1047 OS << '\n' << Name << " contents:\n";
1048 for (const auto &U : Units)
1049 if (auto DumpOffset = DumpOffsets[DIDT_ID_DebugTypes])
1050 U->getDIEForOffset(*DumpOffset)
1051 .dump(OS, 0, DumpOpts.noImplicitRecursion());
1052 else
1053 U->dump(OS, DumpOpts);
1054 };
1055 if ((DumpType & DIDT_DebugTypes)) {
1056 if (Explicit || getNumTypeUnits())
1057 dumpDebugType(".debug_types", types_section_units());
1058 if (ExplicitDWO || getNumDWOTypeUnits())
1059 dumpDebugType(".debug_types.dwo", dwo_types_section_units());
1060 }
1061
1062 DIDumpOptions LLDumpOpts = DumpOpts;
1063 if (LLDumpOpts.Verbose)
1064 LLDumpOpts.DisplayRawContents = true;
1065
1066 if (const auto *Off = shouldDump(Explicit, ".debug_loc", DIDT_ID_DebugLoc,
1067 DObj->getLocSection().Data)) {
1068 getDebugLoc()->dump(OS, *DObj, LLDumpOpts, *Off);
1069 }
1070 if (const auto *Off =
1071 shouldDump(Explicit, ".debug_loclists", DIDT_ID_DebugLoclists,
1072 DObj->getLoclistsSection().Data)) {
1073 DWARFDataExtractor Data(*DObj, DObj->getLoclistsSection(), isLittleEndian(),
1074 0);
1075 dumpLoclistsSection(OS, LLDumpOpts, Data, *DObj, *Off);
1076 }
1077 if (const auto *Off =
1078 shouldDump(ExplicitDWO, ".debug_loclists.dwo", DIDT_ID_DebugLoclists,
1079 DObj->getLoclistsDWOSection().Data)) {
1080 DWARFDataExtractor Data(*DObj, DObj->getLoclistsDWOSection(),
1081 isLittleEndian(), 0);
1082 dumpLoclistsSection(OS, LLDumpOpts, Data, *DObj, *Off);
1083 }
1084
1085 if (const auto *Off =
1086 shouldDump(ExplicitDWO, ".debug_loc.dwo", DIDT_ID_DebugLoc,
1087 DObj->getLocDWOSection().Data)) {
1088 DWARFDataExtractor Data(*DObj, DObj->getLocDWOSection(), isLittleEndian(),
1089 4);
1090 DWARFDebugLoclists Loc(Data, /*Version=*/4);
1091 if (*Off) {
1092 uint64_t Offset = **Off;
1093 Loc.dumpLocationList(&Offset, OS,
1094 /*BaseAddr=*/std::nullopt, *DObj, nullptr,
1095 LLDumpOpts,
1096 /*Indent=*/0);
1097 OS << "\n";
1098 } else {
1099 Loc.dumpRange(0, Data.getData().size(), OS, *DObj, LLDumpOpts);
1100 }
1101 }
1102
1103 if (const std::optional<uint64_t> *Off =
1104 shouldDump(Explicit, ".debug_frame", DIDT_ID_DebugFrame,
1105 DObj->getFrameSection().Data)) {
1107 (*DF)->dump(OS, DumpOpts, *Off);
1108 else
1109 RecoverableErrorHandler(DF.takeError());
1110 }
1111
1112 if (const std::optional<uint64_t> *Off =
1113 shouldDump(Explicit, ".eh_frame", DIDT_ID_DebugFrame,
1114 DObj->getEHFrameSection().Data)) {
1116 (*DF)->dump(OS, DumpOpts, *Off);
1117 else
1118 RecoverableErrorHandler(DF.takeError());
1119 }
1120
1121 if (shouldDump(Explicit, ".debug_macro", DIDT_ID_DebugMacro,
1122 DObj->getMacroSection().Data)) {
1123 if (auto Macro = getDebugMacro())
1124 Macro->dump(OS);
1125 }
1126
1127 if (shouldDump(Explicit, ".debug_macro.dwo", DIDT_ID_DebugMacro,
1128 DObj->getMacroDWOSection())) {
1129 if (auto MacroDWO = getDebugMacroDWO())
1130 MacroDWO->dump(OS);
1131 }
1132
1133 if (shouldDump(Explicit, ".debug_macinfo", DIDT_ID_DebugMacro,
1134 DObj->getMacinfoSection())) {
1135 if (auto Macinfo = getDebugMacinfo())
1136 Macinfo->dump(OS);
1137 }
1138
1139 if (shouldDump(Explicit, ".debug_macinfo.dwo", DIDT_ID_DebugMacro,
1140 DObj->getMacinfoDWOSection())) {
1141 if (auto MacinfoDWO = getDebugMacinfoDWO())
1142 MacinfoDWO->dump(OS);
1143 }
1144
1145 if (shouldDump(Explicit, ".debug_aranges", DIDT_ID_DebugAranges,
1146 DObj->getArangesSection())) {
1147 uint64_t offset = 0;
1148 DWARFDataExtractor arangesData(DObj->getArangesSection(), isLittleEndian(),
1149 0);
1151 while (arangesData.isValidOffset(offset)) {
1152 if (Error E =
1153 set.extract(arangesData, &offset, DumpOpts.WarningHandler)) {
1154 RecoverableErrorHandler(std::move(E));
1155 break;
1156 }
1157 set.dump(OS);
1158 }
1159 }
1160
1161 auto DumpLineSection = [&](DWARFDebugLine::SectionParser Parser,
1162 DIDumpOptions DumpOpts,
1163 std::optional<uint64_t> DumpOffset) {
1164 while (!Parser.done()) {
1165 if (DumpOffset && Parser.getOffset() != *DumpOffset) {
1166 Parser.skip(DumpOpts.WarningHandler, DumpOpts.WarningHandler);
1167 continue;
1168 }
1169 OS << "debug_line[" << format("0x%8.8" PRIx64, Parser.getOffset())
1170 << "]\n";
1171 Parser.parseNext(DumpOpts.WarningHandler, DumpOpts.WarningHandler, &OS,
1172 DumpOpts.Verbose);
1173 }
1174 };
1175
1176 auto DumpStrSection = [&](StringRef Section) {
1177 DataExtractor StrData(Section, isLittleEndian(), 0);
1178 uint64_t Offset = 0;
1179 uint64_t StrOffset = 0;
1180 while (StrData.isValidOffset(Offset)) {
1181 Error Err = Error::success();
1182 const char *CStr = StrData.getCStr(&Offset, &Err);
1183 if (Err) {
1184 DumpOpts.WarningHandler(std::move(Err));
1185 return;
1186 }
1187 OS << format("0x%8.8" PRIx64 ": \"", StrOffset);
1188 OS.write_escaped(CStr);
1189 OS << "\"\n";
1190 StrOffset = Offset;
1191 }
1192 };
1193
1194 if (const auto *Off = shouldDump(Explicit, ".debug_line", DIDT_ID_DebugLine,
1195 DObj->getLineSection().Data)) {
1196 DWARFDataExtractor LineData(*DObj, DObj->getLineSection(), isLittleEndian(),
1197 0);
1199 DumpLineSection(Parser, DumpOpts, *Off);
1200 }
1201
1202 if (const auto *Off =
1203 shouldDump(ExplicitDWO, ".debug_line.dwo", DIDT_ID_DebugLine,
1204 DObj->getLineDWOSection().Data)) {
1205 DWARFDataExtractor LineData(*DObj, DObj->getLineDWOSection(),
1206 isLittleEndian(), 0);
1208 DumpLineSection(Parser, DumpOpts, *Off);
1209 }
1210
1211 if (shouldDump(Explicit, ".debug_cu_index", DIDT_ID_DebugCUIndex,
1212 DObj->getCUIndexSection())) {
1213 getCUIndex().dump(OS);
1214 }
1215
1216 if (shouldDump(Explicit, ".debug_tu_index", DIDT_ID_DebugTUIndex,
1217 DObj->getTUIndexSection())) {
1218 getTUIndex().dump(OS);
1219 }
1220
1221 if (shouldDump(Explicit, ".debug_str", DIDT_ID_DebugStr,
1222 DObj->getStrSection()))
1223 DumpStrSection(DObj->getStrSection());
1224
1225 if (shouldDump(ExplicitDWO, ".debug_str.dwo", DIDT_ID_DebugStr,
1226 DObj->getStrDWOSection()))
1227 DumpStrSection(DObj->getStrDWOSection());
1228
1229 if (shouldDump(Explicit, ".debug_line_str", DIDT_ID_DebugLineStr,
1230 DObj->getLineStrSection()))
1231 DumpStrSection(DObj->getLineStrSection());
1232
1233 if (shouldDump(Explicit, ".debug_addr", DIDT_ID_DebugAddr,
1234 DObj->getAddrSection().Data)) {
1235 DWARFDataExtractor AddrData(*DObj, DObj->getAddrSection(),
1236 isLittleEndian(), 0);
1237 dumpAddrSection(OS, AddrData, DumpOpts, getMaxVersion(), getCUAddrSize());
1238 }
1239
1240 if (shouldDump(Explicit, ".debug_ranges", DIDT_ID_DebugRanges,
1241 DObj->getRangesSection().Data)) {
1242 uint8_t savedAddressByteSize = getCUAddrSize();
1243 DWARFDataExtractor rangesData(*DObj, DObj->getRangesSection(),
1244 isLittleEndian(), savedAddressByteSize);
1245 uint64_t offset = 0;
1246 DWARFDebugRangeList rangeList;
1247 while (rangesData.isValidOffset(offset)) {
1248 if (Error E = rangeList.extract(rangesData, &offset)) {
1249 DumpOpts.RecoverableErrorHandler(std::move(E));
1250 break;
1251 }
1252 rangeList.dump(OS);
1253 }
1254 }
1255
1256 auto LookupPooledAddress =
1257 [&](uint32_t Index) -> std::optional<SectionedAddress> {
1258 const auto &CUs = compile_units();
1259 auto I = CUs.begin();
1260 if (I == CUs.end())
1261 return std::nullopt;
1262 return (*I)->getAddrOffsetSectionItem(Index);
1263 };
1264
1265 if (shouldDump(Explicit, ".debug_rnglists", DIDT_ID_DebugRnglists,
1266 DObj->getRnglistsSection().Data)) {
1267 DWARFDataExtractor RnglistData(*DObj, DObj->getRnglistsSection(),
1268 isLittleEndian(), 0);
1269 dumpRnglistsSection(OS, RnglistData, LookupPooledAddress, DumpOpts);
1270 }
1271
1272 if (shouldDump(ExplicitDWO, ".debug_rnglists.dwo", DIDT_ID_DebugRnglists,
1273 DObj->getRnglistsDWOSection().Data)) {
1274 DWARFDataExtractor RnglistData(*DObj, DObj->getRnglistsDWOSection(),
1275 isLittleEndian(), 0);
1276 dumpRnglistsSection(OS, RnglistData, LookupPooledAddress, DumpOpts);
1277 }
1278
1279 if (shouldDump(Explicit, ".debug_pubnames", DIDT_ID_DebugPubnames,
1280 DObj->getPubnamesSection().Data)) {
1281 DWARFDataExtractor PubTableData(*DObj, DObj->getPubnamesSection(),
1282 isLittleEndian(), 0);
1283 dumpPubTableSection(OS, DumpOpts, PubTableData, /*GnuStyle=*/false);
1284 }
1285
1286 if (shouldDump(Explicit, ".debug_pubtypes", DIDT_ID_DebugPubtypes,
1287 DObj->getPubtypesSection().Data)) {
1288 DWARFDataExtractor PubTableData(*DObj, DObj->getPubtypesSection(),
1289 isLittleEndian(), 0);
1290 dumpPubTableSection(OS, DumpOpts, PubTableData, /*GnuStyle=*/false);
1291 }
1292
1293 if (shouldDump(Explicit, ".debug_gnu_pubnames", DIDT_ID_DebugGnuPubnames,
1294 DObj->getGnuPubnamesSection().Data)) {
1295 DWARFDataExtractor PubTableData(*DObj, DObj->getGnuPubnamesSection(),
1296 isLittleEndian(), 0);
1297 dumpPubTableSection(OS, DumpOpts, PubTableData, /*GnuStyle=*/true);
1298 }
1299
1300 if (shouldDump(Explicit, ".debug_gnu_pubtypes", DIDT_ID_DebugGnuPubtypes,
1301 DObj->getGnuPubtypesSection().Data)) {
1302 DWARFDataExtractor PubTableData(*DObj, DObj->getGnuPubtypesSection(),
1303 isLittleEndian(), 0);
1304 dumpPubTableSection(OS, DumpOpts, PubTableData, /*GnuStyle=*/true);
1305 }
1306
1307 if (shouldDump(Explicit, ".debug_str_offsets", DIDT_ID_DebugStrOffsets,
1308 DObj->getStrOffsetsSection().Data))
1310 OS, DumpOpts, "debug_str_offsets", *DObj, DObj->getStrOffsetsSection(),
1311 DObj->getStrSection(), normal_units(), isLittleEndian());
1312 if (shouldDump(ExplicitDWO, ".debug_str_offsets.dwo", DIDT_ID_DebugStrOffsets,
1313 DObj->getStrOffsetsDWOSection().Data))
1314 dumpStringOffsetsSection(OS, DumpOpts, "debug_str_offsets.dwo", *DObj,
1315 DObj->getStrOffsetsDWOSection(),
1316 DObj->getStrDWOSection(), dwo_units(),
1317 isLittleEndian());
1318
1319 if (shouldDump(Explicit, ".gdb_index", DIDT_ID_GdbIndex,
1320 DObj->getGdbIndexSection())) {
1321 getGdbIndex().dump(OS);
1322 }
1323
1324 if (shouldDump(Explicit, ".apple_names", DIDT_ID_AppleNames,
1325 DObj->getAppleNamesSection().Data))
1326 getAppleNames().dump(OS);
1327
1328 if (shouldDump(Explicit, ".apple_types", DIDT_ID_AppleTypes,
1329 DObj->getAppleTypesSection().Data))
1330 getAppleTypes().dump(OS);
1331
1332 if (shouldDump(Explicit, ".apple_namespaces", DIDT_ID_AppleNamespaces,
1333 DObj->getAppleNamespacesSection().Data))
1335
1336 if (shouldDump(Explicit, ".apple_objc", DIDT_ID_AppleObjC,
1337 DObj->getAppleObjCSection().Data))
1338 getAppleObjC().dump(OS);
1339 if (shouldDump(Explicit, ".debug_names", DIDT_ID_DebugNames,
1340 DObj->getNamesSection().Data))
1341 getDebugNames().dump(OS);
1342}
1343
1345 DWARFUnitVector &DWOUnits = State->getDWOUnits();
1346 if (const auto &TUI = getTUIndex()) {
1347 if (const auto *R = TUI.getFromHash(Hash))
1349 DWOUnits.getUnitForIndexEntry(*R));
1350 return nullptr;
1351 }
1352 return State->getTypeUnitMap(IsDWO).lookup(Hash);
1353}
1354
1356 DWARFUnitVector &DWOUnits = State->getDWOUnits(LazyParse);
1357
1358 if (const auto &CUI = getCUIndex()) {
1359 if (const auto *R = CUI.getFromHash(Hash))
1361 DWOUnits.getUnitForIndexEntry(*R));
1362 return nullptr;
1363 }
1364
1365 // If there's no index, just search through the CUs in the DWO - there's
1366 // probably only one unless this is something like LTO - though an in-process
1367 // built/cached lookup table could be used in that case to improve repeated
1368 // lookups of different CUs in the DWO.
1369 for (const auto &DWOCU : dwo_compile_units()) {
1370 // Might not have parsed DWO ID yet.
1371 if (!DWOCU->getDWOId()) {
1372 if (std::optional<uint64_t> DWOId =
1373 toUnsigned(DWOCU->getUnitDIE().find(DW_AT_GNU_dwo_id)))
1374 DWOCU->setDWOId(*DWOId);
1375 else
1376 // No DWO ID?
1377 continue;
1378 }
1379 if (DWOCU->getDWOId() == Hash)
1380 return dyn_cast<DWARFCompileUnit>(DWOCU.get());
1381 }
1382 return nullptr;
1383}
1384
1386 if (auto *CU = State->getNormalUnits().getUnitForOffset(Offset))
1387 return CU->getDIEForOffset(Offset);
1388 return DWARFDie();
1389}
1390
1392 bool Success = true;
1393 DWARFVerifier verifier(OS, *this, DumpOpts);
1394
1395 Success &= verifier.handleDebugAbbrev();
1396 if (DumpOpts.DumpType & DIDT_DebugCUIndex)
1397 Success &= verifier.handleDebugCUIndex();
1398 if (DumpOpts.DumpType & DIDT_DebugTUIndex)
1399 Success &= verifier.handleDebugTUIndex();
1400 if (DumpOpts.DumpType & DIDT_DebugInfo)
1401 Success &= verifier.handleDebugInfo();
1402 if (DumpOpts.DumpType & DIDT_DebugLine)
1403 Success &= verifier.handleDebugLine();
1404 if (DumpOpts.DumpType & DIDT_DebugStrOffsets)
1405 Success &= verifier.handleDebugStrOffsets();
1406 Success &= verifier.handleAccelTables();
1407 verifier.summarize();
1408 return Success;
1409}
1410
1412 return State->getCUIndex();
1413}
1414
1416 return State->getTUIndex();
1417}
1418
1420 return State->getGdbIndex();
1421}
1422
1424 return State->getDebugAbbrev();
1425}
1426
1428 return State->getDebugAbbrevDWO();
1429}
1430
1432 return State->getDebugLoc();
1433}
1434
1436 return State->getDebugAranges();
1437}
1438
1440 return State->getDebugFrame();
1441}
1442
1444 return State->getEHFrame();
1445}
1446
1448 return State->getDebugMacro();
1449}
1450
1452 return State->getDebugMacroDWO();
1453}
1454
1456 return State->getDebugMacinfo();
1457}
1458
1460 return State->getDebugMacinfoDWO();
1461}
1462
1463
1465 return State->getDebugNames();
1466}
1467
1469 return State->getAppleNames();
1470}
1471
1473 return State->getAppleTypes();
1474}
1475
1477 return State->getAppleNamespaces();
1478}
1479
1481 return State->getAppleObjC();
1482}
1483
1487 getLineTableForUnit(U, WarningHandler);
1488 if (!ExpectedLineTable) {
1489 WarningHandler(ExpectedLineTable.takeError());
1490 return nullptr;
1491 }
1492 return *ExpectedLineTable;
1493}
1494
1496 DWARFUnit *U, function_ref<void(Error)> RecoverableErrorHandler) {
1497 return State->getLineTableForUnit(U, RecoverableErrorHandler);
1498}
1499
1501 return State->clearLineTableForUnit(U);
1502}
1503
1504DWARFUnitVector &DWARFContext::getDWOUnits(bool Lazy) {
1505 return State->getDWOUnits(Lazy);
1506}
1507
1509 return State->getNormalUnits().getUnitForOffset(Offset);
1510}
1511
1515
1520
1523 if (DWARFCompileUnit *OffsetCU = getCompileUnitForOffset(CUOffset))
1524 return OffsetCU;
1525
1526 // Global variables are often missed by the above search, for one of two
1527 // reasons:
1528 // 1. .debug_aranges may not include global variables. On clang, it seems we
1529 // put the globals in the aranges, but this isn't true for gcc.
1530 // 2. Even if the global variable is in a .debug_arange, global variables
1531 // may not be captured in the [start, end) addresses described by the
1532 // parent compile unit.
1533 //
1534 // So, we walk the CU's and their child DI's manually, looking for the
1535 // specific global variable.
1536 for (std::unique_ptr<DWARFUnit> &CU : compile_units()) {
1537 if (CU->getVariableForAddress(Address)) {
1538 return static_cast<DWARFCompileUnit *>(CU.get());
1539 }
1540 }
1541 return nullptr;
1542}
1543
1545 bool CheckDWO) {
1546 DIEsForAddress Result;
1547
1549 if (!CU)
1550 return Result;
1551
1552 if (CheckDWO) {
1553 // We were asked to check the DWO file and this debug information is more
1554 // complete that any information in the skeleton compile unit, so search the
1555 // DWO first to see if we have a match.
1556 DWARFDie CUDie = CU->getUnitDIE(false);
1557 DWARFDie CUDwoDie = CU->getNonSkeletonUnitDIE(false);
1558 if (CheckDWO && CUDwoDie && CUDie != CUDwoDie) {
1559 // We have a DWO file, lets search it.
1560 DWARFCompileUnit *CUDwo =
1562 if (CUDwo) {
1563 Result.FunctionDIE = CUDwo->getSubroutineForAddress(Address);
1564 if (Result.FunctionDIE)
1565 Result.CompileUnit = CUDwo;
1566 }
1567 }
1568 }
1569
1570 // Search the normal DWARF if we didn't find a match in the DWO file or if
1571 // we didn't check the DWO file above.
1572 if (!Result) {
1573 Result.CompileUnit = CU;
1574 Result.FunctionDIE = CU->getSubroutineForAddress(Address);
1575 }
1576
1577 std::vector<DWARFDie> Worklist;
1578 Worklist.push_back(Result.FunctionDIE);
1579 while (!Worklist.empty()) {
1580 DWARFDie DIE = Worklist.back();
1581 Worklist.pop_back();
1582
1583 if (!DIE.isValid())
1584 continue;
1585
1586 if (DIE.getTag() == DW_TAG_lexical_block &&
1587 DIE.addressRangeContainsAddress(Address)) {
1588 Result.BlockDIE = DIE;
1589 break;
1590 }
1591
1592 append_range(Worklist, DIE);
1593 }
1594
1595 return Result;
1596}
1597
1598/// TODO: change input parameter from "uint64_t Address"
1599/// into "SectionedAddress Address"
1601 DWARFCompileUnit *CU, uint64_t Address, FunctionNameKind Kind,
1603 std::string &FunctionName, std::string &StartFile, uint32_t &StartLine,
1604 std::optional<uint64_t> &StartAddress) {
1605 // The address may correspond to instruction in some inlined function,
1606 // so we have to build the chain of inlined functions and take the
1607 // name of the topmost function in it.
1608 SmallVector<DWARFDie, 4> InlinedChain;
1609 CU->getInlinedChainForAddress(Address, InlinedChain);
1610 if (InlinedChain.empty())
1611 return false;
1612
1613 const DWARFDie &DIE = InlinedChain[0];
1614 bool FoundResult = false;
1615 const char *Name = nullptr;
1616 if (Kind != FunctionNameKind::None && (Name = DIE.getSubroutineName(Kind))) {
1617 FunctionName = Name;
1618 FoundResult = true;
1619 }
1620 std::string DeclFile = DIE.getDeclFile(FileNameKind);
1621 if (!DeclFile.empty()) {
1622 StartFile = DeclFile;
1623 FoundResult = true;
1624 }
1625 if (auto DeclLineResult = DIE.getDeclLine()) {
1626 StartLine = DeclLineResult;
1627 FoundResult = true;
1628 }
1629 if (auto LowPcAddr = toSectionedAddress(DIE.find(DW_AT_low_pc)))
1630 StartAddress = LowPcAddr->Address;
1631 return FoundResult;
1632}
1633
1634static std::optional<int64_t>
1636 std::optional<unsigned> FrameBaseReg) {
1637 if (!Expr.empty() &&
1638 (Expr[0] == DW_OP_fbreg ||
1639 (FrameBaseReg && Expr[0] == DW_OP_breg0 + *FrameBaseReg))) {
1640 unsigned Count;
1641 int64_t Offset = decodeSLEB128(Expr.data() + 1, &Count, Expr.end());
1642 // A single DW_OP_fbreg or DW_OP_breg.
1643 if (Expr.size() == Count + 1)
1644 return Offset;
1645 // Same + DW_OP_deref (Fortran arrays look like this).
1646 if (Expr.size() == Count + 2 && Expr[Count + 1] == DW_OP_deref)
1647 return Offset;
1648 // Fallthrough. Do not accept ex. (DW_OP_breg W29, DW_OP_stack_value)
1649 }
1650 return std::nullopt;
1651}
1652
1653void DWARFContext::addLocalsForDie(DWARFCompileUnit *CU, DWARFDie Subprogram,
1654 DWARFDie Die, std::vector<DILocal> &Result) {
1655 if (Die.getTag() == DW_TAG_variable ||
1656 Die.getTag() == DW_TAG_formal_parameter) {
1657 DILocal Local;
1658 if (const char *Name = Subprogram.getSubroutineName(DINameKind::ShortName))
1659 Local.FunctionName = Name;
1660
1661 std::optional<unsigned> FrameBaseReg;
1662 if (auto FrameBase = Subprogram.find(DW_AT_frame_base))
1663 if (std::optional<ArrayRef<uint8_t>> Expr = FrameBase->getAsBlock())
1664 if (!Expr->empty() && (*Expr)[0] >= DW_OP_reg0 &&
1665 (*Expr)[0] <= DW_OP_reg31) {
1666 FrameBaseReg = (*Expr)[0] - DW_OP_reg0;
1667 }
1668
1669 if (Expected<std::vector<DWARFLocationExpression>> Loc =
1670 Die.getLocations(DW_AT_location)) {
1671 for (const auto &Entry : *Loc) {
1672 if (std::optional<int64_t> FrameOffset =
1673 getExpressionFrameOffset(Entry.Expr, FrameBaseReg)) {
1674 Local.FrameOffset = *FrameOffset;
1675 break;
1676 }
1677 }
1678 } else {
1679 // FIXME: missing DW_AT_location is OK here, but other errors should be
1680 // reported to the user.
1681 consumeError(Loc.takeError());
1682 }
1683
1684 if (auto TagOffsetAttr = Die.find(DW_AT_LLVM_tag_offset))
1685 Local.TagOffset = TagOffsetAttr->getAsUnsignedConstant();
1686
1687 if (auto Origin =
1688 Die.getAttributeValueAsReferencedDie(DW_AT_abstract_origin))
1689 Die = Origin;
1690 if (auto NameAttr = Die.find(DW_AT_name))
1691 if (std::optional<const char *> Name = dwarf::toString(*NameAttr))
1692 Local.Name = *Name;
1693 if (auto Type = Die.getAttributeValueAsReferencedDie(DW_AT_type))
1694 Local.Size = Type.getTypeSize(getCUAddrSize());
1695 if (auto DeclFileAttr = Die.find(DW_AT_decl_file)) {
1696 if (const auto *LT = CU->getContext().getLineTableForUnit(CU))
1697 LT->getFileNameByIndex(
1698 *DeclFileAttr->getAsUnsignedConstant(), CU->getCompilationDir(),
1700 Local.DeclFile);
1701 }
1702 if (auto DeclLineAttr = Die.find(DW_AT_decl_line))
1703 Local.DeclLine = *DeclLineAttr->getAsUnsignedConstant();
1704
1705 Result.push_back(Local);
1706 return;
1707 }
1708
1709 if (Die.getTag() == DW_TAG_inlined_subroutine)
1710 if (auto Origin =
1711 Die.getAttributeValueAsReferencedDie(DW_AT_abstract_origin))
1712 Subprogram = Origin;
1713
1714 for (auto Child : Die)
1715 addLocalsForDie(CU, Subprogram, Child, Result);
1716}
1717
1718std::vector<DILocal>
1720 std::vector<DILocal> Result;
1722 if (!CU)
1723 return Result;
1724
1725 DWARFDie Subprogram = CU->getSubroutineForAddress(Address.Address);
1726 if (Subprogram.isValid())
1727 addLocalsForDie(CU, Subprogram, Subprogram, Result);
1728 return Result;
1729}
1730
1731std::optional<DILineInfo>
1735 if (!CU)
1736 return std::nullopt;
1737
1738 DILineInfo Result;
1740 CU, Address.Address, Spec.FNKind, Spec.FLIKind, Result.FunctionName,
1741 Result.StartFileName, Result.StartLine, Result.StartAddress);
1742 if (Spec.FLIKind != FileLineInfoKind::None) {
1743 if (const DWARFLineTable *LineTable = getLineTableForUnit(CU)) {
1744 LineTable->getFileLineInfoForAddress(
1745 {Address.Address, Address.SectionIndex}, Spec.ApproximateLine,
1746 CU->getCompilationDir(), Spec.FLIKind, Result);
1747 }
1748 }
1749
1750 return Result;
1751}
1752
1753std::optional<DILineInfo>
1755 DILineInfo Result;
1757 if (!CU)
1758 return Result;
1759
1760 if (DWARFDie Die = CU->getVariableForAddress(Address.Address)) {
1761 Result.FileName = Die.getDeclFile(FileLineInfoKind::AbsoluteFilePath);
1762 Result.Line = Die.getDeclLine();
1763 }
1764
1765 return Result;
1766}
1767
1770 DILineInfoTable Lines;
1772 if (!CU)
1773 return Lines;
1774
1775 uint32_t StartLine = 0;
1776 std::string StartFileName;
1777 std::string FunctionName(DILineInfo::BadString);
1778 std::optional<uint64_t> StartAddress;
1780 Spec.FLIKind, FunctionName,
1781 StartFileName, StartLine, StartAddress);
1782
1783 // If the Specifier says we don't need FileLineInfo, just
1784 // return the top-most function at the starting address.
1785 if (Spec.FLIKind == FileLineInfoKind::None) {
1786 DILineInfo Result;
1787 Result.FunctionName = FunctionName;
1788 Result.StartFileName = StartFileName;
1789 Result.StartLine = StartLine;
1790 Result.StartAddress = StartAddress;
1791 Lines.push_back(std::make_pair(Address.Address, Result));
1792 return Lines;
1793 }
1794
1795 const DWARFLineTable *LineTable = getLineTableForUnit(CU);
1796
1797 // Get the index of row we're looking for in the line table.
1798 std::vector<uint32_t> RowVector;
1799 if (!LineTable->lookupAddressRange({Address.Address, Address.SectionIndex},
1800 Size, RowVector)) {
1801 return Lines;
1802 }
1803
1804 for (uint32_t RowIndex : RowVector) {
1805 // Take file number and line/column from the row.
1806 const DWARFDebugLine::Row &Row = LineTable->Rows[RowIndex];
1807 DILineInfo Result;
1808 LineTable->getFileNameByIndex(Row.File, CU->getCompilationDir(),
1809 Spec.FLIKind, Result.FileName);
1810 Result.FunctionName = FunctionName;
1811 Result.Line = Row.Line;
1812 Result.Column = Row.Column;
1813 Result.StartFileName = StartFileName;
1814 Result.StartLine = StartLine;
1815 Result.StartAddress = StartAddress;
1816 Lines.push_back(std::make_pair(Row.Address.Address, Result));
1817 }
1818
1819 return Lines;
1820}
1821
1825 DIInliningInfo InliningInfo;
1826
1828 if (!CU)
1829 return InliningInfo;
1830
1831 const DWARFLineTable *LineTable = nullptr;
1832 SmallVector<DWARFDie, 4> InlinedChain;
1833 CU->getInlinedChainForAddress(Address.Address, InlinedChain);
1834 if (InlinedChain.size() == 0) {
1835 // If there is no DIE for address (e.g. it is in unavailable .dwo file),
1836 // try to at least get file/line info from symbol table.
1837 if (Spec.FLIKind != FileLineInfoKind::None) {
1838 DILineInfo Frame;
1839 LineTable = getLineTableForUnit(CU);
1840 if (LineTable &&
1841 LineTable->getFileLineInfoForAddress(
1842 {Address.Address, Address.SectionIndex}, Spec.ApproximateLine,
1843 CU->getCompilationDir(), Spec.FLIKind, Frame))
1844 InliningInfo.addFrame(Frame);
1845 }
1846 return InliningInfo;
1847 }
1848
1849 uint32_t CallFile = 0, CallLine = 0, CallColumn = 0, CallDiscriminator = 0;
1850 for (uint32_t i = 0, n = InlinedChain.size(); i != n; i++) {
1851 DWARFDie &FunctionDIE = InlinedChain[i];
1852 DILineInfo Frame;
1853 // Get function name if necessary.
1854 if (const char *Name = FunctionDIE.getSubroutineName(Spec.FNKind))
1855 Frame.FunctionName = Name;
1856 if (auto DeclLineResult = FunctionDIE.getDeclLine())
1857 Frame.StartLine = DeclLineResult;
1858 Frame.StartFileName = FunctionDIE.getDeclFile(Spec.FLIKind);
1859 if (auto LowPcAddr = toSectionedAddress(FunctionDIE.find(DW_AT_low_pc)))
1860 Frame.StartAddress = LowPcAddr->Address;
1861 if (Spec.FLIKind != FileLineInfoKind::None) {
1862 if (i == 0) {
1863 // For the topmost frame, initialize the line table of this
1864 // compile unit and fetch file/line info from it.
1865 LineTable = getLineTableForUnit(CU);
1866 // For the topmost routine, get file/line info from line table.
1867 if (LineTable)
1868 LineTable->getFileLineInfoForAddress(
1869 {Address.Address, Address.SectionIndex}, Spec.ApproximateLine,
1870 CU->getCompilationDir(), Spec.FLIKind, Frame);
1871 } else {
1872 // Otherwise, use call file, call line and call column from
1873 // previous DIE in inlined chain.
1874 if (LineTable)
1875 LineTable->getFileNameByIndex(CallFile, CU->getCompilationDir(),
1876 Spec.FLIKind, Frame.FileName);
1877 Frame.Line = CallLine;
1878 Frame.Column = CallColumn;
1879 Frame.Discriminator = CallDiscriminator;
1880 }
1881 // Get call file/line/column of a current DIE.
1882 if (i + 1 < n) {
1883 FunctionDIE.getCallerFrame(CallFile, CallLine, CallColumn,
1884 CallDiscriminator);
1885 }
1886 }
1887 InliningInfo.addFrame(Frame);
1888 }
1889 return InliningInfo;
1890}
1891
1892std::shared_ptr<DWARFContext>
1894 return State->getDWOContext(AbsolutePath);
1895}
1896
1897static Error createError(const Twine &Reason, llvm::Error E) {
1898 return make_error<StringError>(Reason + toString(std::move(E)),
1900}
1901
1902/// SymInfo contains information about symbol: it's address
1903/// and section index which is -1LL for absolute symbols.
1908
1909/// Returns the address of symbol relocation used against and a section index.
1910/// Used for futher relocations computation. Symbol's section load address is
1912 const RelocationRef &Reloc,
1913 const LoadedObjectInfo *L,
1914 std::map<SymbolRef, SymInfo> &Cache) {
1915 SymInfo Ret = {0, (uint64_t)-1LL};
1917 object::symbol_iterator Sym = Reloc.getSymbol();
1918
1919 std::map<SymbolRef, SymInfo>::iterator CacheIt = Cache.end();
1920 // First calculate the address of the symbol or section as it appears
1921 // in the object file
1922 if (Sym != Obj.symbol_end()) {
1923 bool New;
1924 std::tie(CacheIt, New) = Cache.try_emplace(*Sym);
1925 if (!New)
1926 return CacheIt->second;
1927
1928 Expected<uint64_t> SymAddrOrErr = Sym->getAddress();
1929 if (!SymAddrOrErr)
1930 return createError("failed to compute symbol address: ",
1931 SymAddrOrErr.takeError());
1932
1933 // Also remember what section this symbol is in for later
1934 auto SectOrErr = Sym->getSection();
1935 if (!SectOrErr)
1936 return createError("failed to get symbol section: ",
1937 SectOrErr.takeError());
1938
1939 RSec = *SectOrErr;
1940 Ret.Address = *SymAddrOrErr;
1941 } else if (auto *MObj = dyn_cast<MachOObjectFile>(&Obj)) {
1942 RSec = MObj->getRelocationSection(Reloc.getRawDataRefImpl());
1943 Ret.Address = RSec->getAddress();
1944 }
1945
1946 if (RSec != Obj.section_end())
1947 Ret.SectionIndex = RSec->getIndex();
1948
1949 // If we are given load addresses for the sections, we need to adjust:
1950 // SymAddr = (Address of Symbol Or Section in File) -
1951 // (Address of Section in File) +
1952 // (Load Address of Section)
1953 // RSec is now either the section being targeted or the section
1954 // containing the symbol being targeted. In either case,
1955 // we need to perform the same computation.
1956 if (L && RSec != Obj.section_end())
1957 if (uint64_t SectionLoadAddress = L->getSectionLoadAddress(*RSec))
1958 Ret.Address += SectionLoadAddress - RSec->getAddress();
1959
1960 if (CacheIt != Cache.end())
1961 CacheIt->second = Ret;
1962
1963 return Ret;
1964}
1965
1967 const RelocationRef &Reloc) {
1968 const MachOObjectFile *MachObj = dyn_cast<MachOObjectFile>(&Obj);
1969 if (!MachObj)
1970 return false;
1971 // MachO also has relocations that point to sections and
1972 // scattered relocations.
1973 auto RelocInfo = MachObj->getRelocation(Reloc.getRawDataRefImpl());
1974 return MachObj->isRelocationScattered(RelocInfo);
1975}
1976
1977namespace {
1978struct DWARFSectionMap final : public DWARFSection {
1979 RelocAddrMap Relocs;
1980};
1981
1982class DWARFObjInMemory final : public DWARFObject {
1983 bool IsLittleEndian;
1984 uint8_t AddressSize;
1985 StringRef FileName;
1986 const object::ObjectFile *Obj = nullptr;
1987 std::vector<SectionName> SectionNames;
1988
1989 using InfoSectionMap = MapVector<object::SectionRef, DWARFSectionMap,
1990 std::map<object::SectionRef, unsigned>>;
1991
1992 InfoSectionMap InfoSections;
1993 InfoSectionMap TypesSections;
1994 InfoSectionMap InfoDWOSections;
1995 InfoSectionMap TypesDWOSections;
1996
1997 DWARFSectionMap LocSection;
1998 DWARFSectionMap LoclistsSection;
1999 DWARFSectionMap LoclistsDWOSection;
2000 DWARFSectionMap LineSection;
2001 DWARFSectionMap RangesSection;
2002 DWARFSectionMap RnglistsSection;
2003 DWARFSectionMap StrOffsetsSection;
2004 DWARFSectionMap LineDWOSection;
2005 DWARFSectionMap FrameSection;
2006 DWARFSectionMap EHFrameSection;
2007 DWARFSectionMap LocDWOSection;
2008 DWARFSectionMap StrOffsetsDWOSection;
2009 DWARFSectionMap RangesDWOSection;
2010 DWARFSectionMap RnglistsDWOSection;
2011 DWARFSectionMap AddrSection;
2012 DWARFSectionMap AppleNamesSection;
2013 DWARFSectionMap AppleTypesSection;
2014 DWARFSectionMap AppleNamespacesSection;
2015 DWARFSectionMap AppleObjCSection;
2016 DWARFSectionMap NamesSection;
2017 DWARFSectionMap PubnamesSection;
2018 DWARFSectionMap PubtypesSection;
2019 DWARFSectionMap GnuPubnamesSection;
2020 DWARFSectionMap GnuPubtypesSection;
2021 DWARFSectionMap MacroSection;
2022
2023 DWARFSectionMap *mapNameToDWARFSection(StringRef Name) {
2024 return StringSwitch<DWARFSectionMap *>(Name)
2025 .Case("debug_loc", &LocSection)
2026 .Case("debug_loclists", &LoclistsSection)
2027 .Case("debug_loclists.dwo", &LoclistsDWOSection)
2028 .Case("debug_line", &LineSection)
2029 .Case("debug_frame", &FrameSection)
2030 .Case("eh_frame", &EHFrameSection)
2031 .Case("debug_str_offsets", &StrOffsetsSection)
2032 .Case("debug_ranges", &RangesSection)
2033 .Case("debug_rnglists", &RnglistsSection)
2034 .Case("debug_loc.dwo", &LocDWOSection)
2035 .Case("debug_line.dwo", &LineDWOSection)
2036 .Case("debug_names", &NamesSection)
2037 .Case("debug_rnglists.dwo", &RnglistsDWOSection)
2038 .Case("debug_str_offsets.dwo", &StrOffsetsDWOSection)
2039 .Case("debug_addr", &AddrSection)
2040 .Case("apple_names", &AppleNamesSection)
2041 .Case("debug_pubnames", &PubnamesSection)
2042 .Case("debug_pubtypes", &PubtypesSection)
2043 .Case("debug_gnu_pubnames", &GnuPubnamesSection)
2044 .Case("debug_gnu_pubtypes", &GnuPubtypesSection)
2045 .Case("apple_types", &AppleTypesSection)
2046 .Case("apple_namespaces", &AppleNamespacesSection)
2047 .Case("apple_namespac", &AppleNamespacesSection)
2048 .Case("apple_objc", &AppleObjCSection)
2049 .Case("debug_macro", &MacroSection)
2050 .Default(nullptr);
2051 }
2052
2053 StringRef AbbrevSection;
2054 StringRef ArangesSection;
2055 StringRef StrSection;
2056 StringRef MacinfoSection;
2057 StringRef MacinfoDWOSection;
2058 StringRef MacroDWOSection;
2059 StringRef AbbrevDWOSection;
2060 StringRef StrDWOSection;
2061 StringRef CUIndexSection;
2062 StringRef GdbIndexSection;
2063 StringRef TUIndexSection;
2064 StringRef LineStrSection;
2065
2066 // A deque holding section data whose iterators are not invalidated when
2067 // new decompressed sections are inserted at the end.
2068 std::deque<SmallString<0>> UncompressedSections;
2069
2070 StringRef *mapSectionToMember(StringRef Name) {
2071 if (DWARFSection *Sec = mapNameToDWARFSection(Name))
2072 return &Sec->Data;
2073 return StringSwitch<StringRef *>(Name)
2074 .Case("debug_abbrev", &AbbrevSection)
2075 .Case("debug_aranges", &ArangesSection)
2076 .Case("debug_str", &StrSection)
2077 .Case("debug_macinfo", &MacinfoSection)
2078 .Case("debug_macinfo.dwo", &MacinfoDWOSection)
2079 .Case("debug_macro.dwo", &MacroDWOSection)
2080 .Case("debug_abbrev.dwo", &AbbrevDWOSection)
2081 .Case("debug_str.dwo", &StrDWOSection)
2082 .Case("debug_cu_index", &CUIndexSection)
2083 .Case("debug_tu_index", &TUIndexSection)
2084 .Case("gdb_index", &GdbIndexSection)
2085 .Case("debug_line_str", &LineStrSection)
2086 // Any more debug info sections go here.
2087 .Default(nullptr);
2088 }
2089
2090 /// If Sec is compressed section, decompresses and updates its contents
2091 /// provided by Data. Otherwise leaves it unchanged.
2092 Error maybeDecompress(const object::SectionRef &Sec, StringRef Name,
2093 StringRef &Data) {
2094 if (!Sec.isCompressed())
2095 return Error::success();
2096
2097 Expected<Decompressor> Decompressor =
2098 Decompressor::create(Name, Data, IsLittleEndian, AddressSize == 8);
2099 if (!Decompressor)
2100 return Decompressor.takeError();
2101
2102 SmallString<0> Out;
2103 if (auto Err = Decompressor->resizeAndDecompress(Out))
2104 return Err;
2105
2106 UncompressedSections.push_back(std::move(Out));
2107 Data = UncompressedSections.back();
2108
2109 return Error::success();
2110 }
2111
2112public:
2113 DWARFObjInMemory(const StringMap<std::unique_ptr<MemoryBuffer>> &Sections,
2114 uint8_t AddrSize, bool IsLittleEndian)
2115 : IsLittleEndian(IsLittleEndian) {
2116 for (const auto &SecIt : Sections) {
2117 if (StringRef *SectionData = mapSectionToMember(SecIt.first()))
2118 *SectionData = SecIt.second->getBuffer();
2119 else if (SecIt.first() == "debug_info")
2120 // Find debug_info and debug_types data by section rather than name as
2121 // there are multiple, comdat grouped, of these sections.
2122 InfoSections[SectionRef()].Data = SecIt.second->getBuffer();
2123 else if (SecIt.first() == "debug_info.dwo")
2124 InfoDWOSections[SectionRef()].Data = SecIt.second->getBuffer();
2125 else if (SecIt.first() == "debug_types")
2126 TypesSections[SectionRef()].Data = SecIt.second->getBuffer();
2127 else if (SecIt.first() == "debug_types.dwo")
2128 TypesDWOSections[SectionRef()].Data = SecIt.second->getBuffer();
2129 }
2130 }
2131 DWARFObjInMemory(const object::ObjectFile &Obj, const LoadedObjectInfo *L,
2132 function_ref<void(Error)> HandleError,
2133 function_ref<void(Error)> HandleWarning,
2135 : IsLittleEndian(Obj.isLittleEndian()),
2136 AddressSize(Obj.getBytesInAddress()), FileName(Obj.getFileName()),
2137 Obj(&Obj) {
2138
2139 StringMap<unsigned> SectionAmountMap;
2140 for (const SectionRef &Section : Obj.sections()) {
2141 StringRef Name;
2142 if (auto NameOrErr = Section.getName())
2143 Name = *NameOrErr;
2144 else
2145 consumeError(NameOrErr.takeError());
2146
2147 ++SectionAmountMap[Name];
2148 SectionNames.push_back({ Name, true });
2149
2150 // Skip BSS and Virtual sections, they aren't interesting.
2151 if (Section.isBSS() || Section.isVirtual())
2152 continue;
2153
2154 // Skip sections stripped by dsymutil.
2155 if (Section.isStripped())
2156 continue;
2157
2158 StringRef Data;
2159 Expected<section_iterator> SecOrErr = Section.getRelocatedSection();
2160 if (!SecOrErr) {
2161 HandleError(createError("failed to get relocated section: ",
2162 SecOrErr.takeError()));
2163 continue;
2164 }
2165
2166 // Try to obtain an already relocated version of this section.
2167 // Else use the unrelocated section from the object file. We'll have to
2168 // apply relocations ourselves later.
2169 section_iterator RelocatedSection =
2170 Obj.isRelocatableObject() ? *SecOrErr : Obj.section_end();
2171 if (!L || !L->getLoadedSectionContents(*RelocatedSection, Data)) {
2172 Expected<StringRef> E = Section.getContents();
2173 if (E)
2174 Data = *E;
2175 else
2176 // maybeDecompress below will error.
2177 consumeError(E.takeError());
2178 }
2179
2180 if (auto Err = maybeDecompress(Section, Name, Data)) {
2181 HandleError(createError("failed to decompress '" + Name + "', ",
2182 std::move(Err)));
2183 continue;
2184 }
2185
2186 // Map platform specific debug section names to DWARF standard section
2187 // names.
2188 Name = Name.substr(Name.find_first_not_of("._"));
2189 Name = Obj.mapDebugSectionName(Name);
2190
2191 if (StringRef *SectionData = mapSectionToMember(Name)) {
2192 *SectionData = Data;
2193 if (Name == "debug_ranges") {
2194 // FIXME: Use the other dwo range section when we emit it.
2195 RangesDWOSection.Data = Data;
2196 } else if (Name == "debug_frame" || Name == "eh_frame") {
2197 if (DWARFSection *S = mapNameToDWARFSection(Name))
2198 S->Address = Section.getAddress();
2199 }
2200 } else if (InfoSectionMap *Sections =
2201 StringSwitch<InfoSectionMap *>(Name)
2202 .Case("debug_info", &InfoSections)
2203 .Case("debug_info.dwo", &InfoDWOSections)
2204 .Case("debug_types", &TypesSections)
2205 .Case("debug_types.dwo", &TypesDWOSections)
2206 .Default(nullptr)) {
2207 // Find debug_info and debug_types data by section rather than name as
2208 // there are multiple, comdat grouped, of these sections.
2209 DWARFSectionMap &S = (*Sections)[Section];
2210 S.Data = Data;
2211 }
2212
2213 if (RelocatedSection == Obj.section_end() ||
2214 (RelocAction == DWARFContext::ProcessDebugRelocations::Ignore))
2215 continue;
2216
2217 StringRef RelSecName;
2218 if (auto NameOrErr = RelocatedSection->getName())
2219 RelSecName = *NameOrErr;
2220 else
2221 consumeError(NameOrErr.takeError());
2222
2223 // If the section we're relocating was relocated already by the JIT,
2224 // then we used the relocated version above, so we do not need to process
2225 // relocations for it now.
2226 StringRef RelSecData;
2227 if (L && L->getLoadedSectionContents(*RelocatedSection, RelSecData))
2228 continue;
2229
2230 // In Mach-o files, the relocations do not need to be applied if
2231 // there is no load offset to apply. The value read at the
2232 // relocation point already factors in the section address
2233 // (actually applying the relocations will produce wrong results
2234 // as the section address will be added twice).
2235 if (!L && isa<MachOObjectFile>(&Obj))
2236 continue;
2237
2238 if (!Section.relocations().empty() && Name.ends_with(".dwo") &&
2239 RelSecName.starts_with(".debug")) {
2240 HandleWarning(createError("unexpected relocations for dwo section '" +
2241 RelSecName + "'"));
2242 }
2243
2244 // TODO: Add support for relocations in other sections as needed.
2245 // Record relocations for the debug_info and debug_line sections.
2246 RelSecName = RelSecName.substr(RelSecName.find_first_not_of("._"));
2247 DWARFSectionMap *Sec = mapNameToDWARFSection(RelSecName);
2248 RelocAddrMap *Map = Sec ? &Sec->Relocs : nullptr;
2249 if (!Map) {
2250 // Find debug_info and debug_types relocs by section rather than name
2251 // as there are multiple, comdat grouped, of these sections.
2252 if (RelSecName == "debug_info")
2253 Map = &static_cast<DWARFSectionMap &>(InfoSections[*RelocatedSection])
2254 .Relocs;
2255 else if (RelSecName == "debug_types")
2256 Map =
2257 &static_cast<DWARFSectionMap &>(TypesSections[*RelocatedSection])
2258 .Relocs;
2259 else
2260 continue;
2261 }
2262
2263 if (Section.relocations().empty())
2264 continue;
2265
2266 // Symbol to [address, section index] cache mapping.
2267 std::map<SymbolRef, SymInfo> AddrCache;
2268 SupportsRelocation Supports;
2269 RelocationResolver Resolver;
2270 std::tie(Supports, Resolver) = getRelocationResolver(Obj);
2271 for (const RelocationRef &Reloc : Section.relocations()) {
2272 // FIXME: it's not clear how to correctly handle scattered
2273 // relocations.
2274 if (isRelocScattered(Obj, Reloc))
2275 continue;
2276
2277 Expected<SymInfo> SymInfoOrErr =
2278 getSymbolInfo(Obj, Reloc, L, AddrCache);
2279 if (!SymInfoOrErr) {
2280 HandleError(SymInfoOrErr.takeError());
2281 continue;
2282 }
2283
2284 // Check if Resolver can handle this relocation type early so as not to
2285 // handle invalid cases in DWARFDataExtractor.
2286 //
2287 // TODO Don't store Resolver in every RelocAddrEntry.
2288 if (Supports && Supports(Reloc.getType())) {
2289 auto I = Map->try_emplace(
2290 Reloc.getOffset(),
2291 RelocAddrEntry{
2292 SymInfoOrErr->SectionIndex, Reloc, SymInfoOrErr->Address,
2293 std::optional<object::RelocationRef>(), 0, Resolver});
2294 // If we didn't successfully insert that's because we already had a
2295 // relocation for that offset. Store it as a second relocation in the
2296 // same RelocAddrEntry instead.
2297 if (!I.second) {
2298 RelocAddrEntry &entry = I.first->getSecond();
2299 if (entry.Reloc2) {
2300 HandleError(createError(
2301 "At most two relocations per offset are supported"));
2302 }
2303 entry.Reloc2 = Reloc;
2304 entry.SymbolValue2 = SymInfoOrErr->Address;
2305 }
2306 } else {
2308 Reloc.getTypeName(Type);
2309 // FIXME: Support more relocations & change this to an error
2310 HandleWarning(
2311 createError("failed to compute relocation: " + Type + ", ",
2312 errorCodeToError(object_error::parse_failed)));
2313 }
2314 }
2315 }
2316
2317 for (SectionName &S : SectionNames)
2318 if (SectionAmountMap[S.Name] > 1)
2319 S.IsNameUnique = false;
2320 }
2321
2322 std::optional<RelocAddrEntry> find(const DWARFSection &S,
2323 uint64_t Pos) const override {
2324 auto &Sec = static_cast<const DWARFSectionMap &>(S);
2325 RelocAddrMap::const_iterator AI = Sec.Relocs.find(Pos);
2326 if (AI == Sec.Relocs.end())
2327 return std::nullopt;
2328 return AI->second;
2329 }
2330
2331 const object::ObjectFile *getFile() const override { return Obj; }
2332
2333 ArrayRef<SectionName> getSectionNames() const override {
2334 return SectionNames;
2335 }
2336
2337 bool isLittleEndian() const override { return IsLittleEndian; }
2338 StringRef getAbbrevDWOSection() const override { return AbbrevDWOSection; }
2339 const DWARFSection &getLineDWOSection() const override {
2340 return LineDWOSection;
2341 }
2342 const DWARFSection &getLocDWOSection() const override {
2343 return LocDWOSection;
2344 }
2345 StringRef getStrDWOSection() const override { return StrDWOSection; }
2346 const DWARFSection &getStrOffsetsDWOSection() const override {
2347 return StrOffsetsDWOSection;
2348 }
2349 const DWARFSection &getRangesDWOSection() const override {
2350 return RangesDWOSection;
2351 }
2352 const DWARFSection &getRnglistsDWOSection() const override {
2353 return RnglistsDWOSection;
2354 }
2355 const DWARFSection &getLoclistsDWOSection() const override {
2356 return LoclistsDWOSection;
2357 }
2358 const DWARFSection &getAddrSection() const override { return AddrSection; }
2359 StringRef getCUIndexSection() const override { return CUIndexSection; }
2360 StringRef getGdbIndexSection() const override { return GdbIndexSection; }
2361 StringRef getTUIndexSection() const override { return TUIndexSection; }
2362
2363 // DWARF v5
2364 const DWARFSection &getStrOffsetsSection() const override {
2365 return StrOffsetsSection;
2366 }
2367 StringRef getLineStrSection() const override { return LineStrSection; }
2368
2369 // Sections for DWARF5 split dwarf proposal.
2370 void forEachInfoDWOSections(
2371 function_ref<void(const DWARFSection &)> F) const override {
2372 for (auto &P : InfoDWOSections)
2373 F(P.second);
2374 }
2375 void forEachTypesDWOSections(
2376 function_ref<void(const DWARFSection &)> F) const override {
2377 for (auto &P : TypesDWOSections)
2378 F(P.second);
2379 }
2380
2381 StringRef getAbbrevSection() const override { return AbbrevSection; }
2382 const DWARFSection &getLocSection() const override { return LocSection; }
2383 const DWARFSection &getLoclistsSection() const override { return LoclistsSection; }
2384 StringRef getArangesSection() const override { return ArangesSection; }
2385 const DWARFSection &getFrameSection() const override {
2386 return FrameSection;
2387 }
2388 const DWARFSection &getEHFrameSection() const override {
2389 return EHFrameSection;
2390 }
2391 const DWARFSection &getLineSection() const override { return LineSection; }
2392 StringRef getStrSection() const override { return StrSection; }
2393 const DWARFSection &getRangesSection() const override { return RangesSection; }
2394 const DWARFSection &getRnglistsSection() const override {
2395 return RnglistsSection;
2396 }
2397 const DWARFSection &getMacroSection() const override { return MacroSection; }
2398 StringRef getMacroDWOSection() const override { return MacroDWOSection; }
2399 StringRef getMacinfoSection() const override { return MacinfoSection; }
2400 StringRef getMacinfoDWOSection() const override { return MacinfoDWOSection; }
2401 const DWARFSection &getPubnamesSection() const override { return PubnamesSection; }
2402 const DWARFSection &getPubtypesSection() const override { return PubtypesSection; }
2403 const DWARFSection &getGnuPubnamesSection() const override {
2404 return GnuPubnamesSection;
2405 }
2406 const DWARFSection &getGnuPubtypesSection() const override {
2407 return GnuPubtypesSection;
2408 }
2409 const DWARFSection &getAppleNamesSection() const override {
2410 return AppleNamesSection;
2411 }
2412 const DWARFSection &getAppleTypesSection() const override {
2413 return AppleTypesSection;
2414 }
2415 const DWARFSection &getAppleNamespacesSection() const override {
2416 return AppleNamespacesSection;
2417 }
2418 const DWARFSection &getAppleObjCSection() const override {
2419 return AppleObjCSection;
2420 }
2421 const DWARFSection &getNamesSection() const override {
2422 return NamesSection;
2423 }
2424
2425 StringRef getFileName() const override { return FileName; }
2426 uint8_t getAddressSize() const override { return AddressSize; }
2427 void forEachInfoSections(
2428 function_ref<void(const DWARFSection &)> F) const override {
2429 for (auto &P : InfoSections)
2430 F(P.second);
2431 }
2432 void forEachTypesSections(
2433 function_ref<void(const DWARFSection &)> F) const override {
2434 for (auto &P : TypesSections)
2435 F(P.second);
2436 }
2437};
2438} // namespace
2439
2440std::unique_ptr<DWARFContext>
2442 ProcessDebugRelocations RelocAction,
2443 const LoadedObjectInfo *L, std::string DWPName,
2444 std::function<void(Error)> RecoverableErrorHandler,
2445 std::function<void(Error)> WarningHandler,
2446 bool ThreadSafe) {
2447 auto DObj = std::make_unique<DWARFObjInMemory>(
2448 Obj, L, RecoverableErrorHandler, WarningHandler, RelocAction);
2449 return std::make_unique<DWARFContext>(std::move(DObj),
2450 std::move(DWPName),
2451 RecoverableErrorHandler,
2452 WarningHandler,
2453 ThreadSafe);
2454}
2455
2456std::unique_ptr<DWARFContext>
2457DWARFContext::create(const StringMap<std::unique_ptr<MemoryBuffer>> &Sections,
2458 uint8_t AddrSize, bool isLittleEndian,
2459 std::function<void(Error)> RecoverableErrorHandler,
2460 std::function<void(Error)> WarningHandler,
2461 bool ThreadSafe) {
2462 auto DObj =
2463 std::make_unique<DWARFObjInMemory>(Sections, AddrSize, isLittleEndian);
2464 return std::make_unique<DWARFContext>(
2465 std::move(DObj), "", RecoverableErrorHandler, WarningHandler, ThreadSafe);
2466}
2467
2469 // In theory, different compile units may have different address byte
2470 // sizes, but for simplicity we just use the address byte size of the
2471 // first compile unit. In practice the address size field is repeated across
2472 // various DWARF headers (at least in version 5) to make it easier to dump
2473 // them independently, not to enable varying the address size.
2474 auto CUs = compile_units();
2475 return CUs.empty() ? 0 : (*CUs.begin())->getAddressByteSize();
2476}
2477
2478bool DWARFContext::isDWP() const { return !DObj->getCUIndexSection().empty(); }
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
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.
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)
void fixupIndex(DWARFContext &C, DWARFUnitIndex &Index)
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)
void fixupIndexV4(DWARFContext &C, DWARFUnitIndex &Index)
static ContributionCollection collectContributionData(DWARFContext::unit_iterator_range Units)
std::vector< std::optional< StrOffsetsContributionDescriptor > > ContributionCollection
DWARFDebugLine::LineTable DWARFLineTable
static bool isRelocScattered(const object::ObjectFile &Obj, const RelocationRef &Reloc)
static std::optional< int64_t > getExpressionFrameOffset(ArrayRef< uint8_t > Expr, std::optional< unsigned > FrameBaseReg)
void fixupIndexV5(DWARFContext &C, DWARFUnitIndex &Index)
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
This file contains constants used for implementing Dwarf debug support.
#define F(x, y, z)
Definition MD5.cpp:55
#define I(x, y, z)
Definition MD5.cpp:58
static DebugLoc getDebugLoc(MachineBasicBlock::instr_iterator FirstMI, MachineBasicBlock::instr_iterator LastMI)
Return the first found DebugLoc that has a DILocation, given a range of instructions.
This file implements a map that provides insertion order iteration.
#define T
#define P(N)
if(PassOpts->AAPipeline)
This file contains some templates that are useful if you are working with the STL at all.
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:136
size_t size() const
size - Get the array size.
Definition ArrayRef.h:147
bool empty() const
empty - Check if the array is empty.
Definition ArrayRef.h:142
const T * data() const
Definition ArrayRef.h:144
DIContext(DIContextKind K)
Definition DIContext.h:244
A structured debug information entry.
Definition DIE.h:828
dwarf::Tag getTag() const
Definition DIE.h:864
A format-neutral container for inlined code description.
Definition DIContext.h:94
void addFrame(const DILineInfo &Frame)
Definition DIContext.h:114
DWARFContextState This structure contains all member variables for DWARFContext that need to be prote...
MacroSecType
Helper enum to distinguish between macro[.dwo] and macinfo[.dwo] section.
LLVM_ABI std::unique_ptr< DWARFDebugMacro > parseMacroOrMacinfo(MacroSecType SectionType)
Parse a macro[.dwo] or macinfo[.dwo] section.
DWARFContext This data structure is the top level entity that deals with dwarf debug information pars...
DWARFCompileUnit * getCompileUnitForCodeAddress(uint64_t Address)
Return the compile unit which contains instruction with provided address.
uint8_t getCUAddrSize()
Get address size from CUs.
std::optional< DILineInfo > getLineInfoForDataAddress(object::SectionedAddress Address) override
DIInliningInfo getInliningInfoForAddress(object::SectionedAddress Address, DILineInfoSpecifier Specifier=DILineInfoSpecifier()) override
Expected< const DWARFDebugFrame * > getDebugFrame()
Get a pointer to the parsed frame information object.
DWARFGdbIndex & getGdbIndex()
unsigned getNumCompileUnits()
Get the number of compile units in this context.
~DWARFContext() override
DWARFContext(std::unique_ptr< const DWARFObject > DObj, std::string DWPName="", std::function< void(Error)> RecoverableErrorHandler=WithColor::defaultErrorHandler, std::function< void(Error)> WarningHandler=WithColor::defaultWarningHandler, bool ThreadSafe=false)
DWARFDie getDIEForOffset(uint64_t Offset)
Get a DIE given an exact offset.
unsigned getNumTypeUnits()
Get the number of type units in this context.
DWARFUnitVector::iterator_range unit_iterator_range
const DWARFDebugAbbrev * getDebugAbbrevDWO()
Get a pointer to the parsed dwo abbreviations object.
compile_unit_range compile_units()
Get compile units in this context.
const AppleAcceleratorTable & getAppleObjC()
Get a reference to the parsed accelerator table object.
const DWARFUnitIndex & getTUIndex()
unsigned getMaxVersion()
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
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.
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 isDWP() const
Return true of this DWARF context is a DWP file.
bool isLittleEndian() const
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.
DWARFUnit * getUnitForOffset(uint64_t Offset)
Return the DWARF unit that includes an offset (relative to .debug_info).
compile_unit_range dwo_compile_units()
Get compile units in the DWO context.
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.
void dump(raw_ostream &OS, DIDumpOptions DumpOpts, std::array< std::optional< uint64_t >, DIDT_ID_Count > DumpOffsets)
Dump a textual representation to OS.
DWARFTypeUnit * getTypeUnitForHash(uint64_t Hash, bool IsDWO)
unit_iterator_range normal_units()
Get all normal compile/type units in this context.
unit_iterator_range types_section_units()
Get units from .debug_types in this context.
std::shared_ptr< DWARFContext > getDWOContext(StringRef AbsolutePath)
DWARFCompileUnit * getDWOCompileUnitForHash(uint64_t Hash)
unsigned getNumDWOCompileUnits()
Get the number of compile units in the DWO context.
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.
DIEsForAddress getDIEsForAddress(uint64_t Address, bool CheckDWO=false)
Get the compilation unit, the function DIE and lexical block DIE for the given address where applicab...
unit_iterator_range info_section_units()
Get units from .debug_info in this context.
unit_iterator_range dwo_info_section_units()
Get units from .debug_info..dwo in the DWO context.
const AppleAcceleratorTable & getAppleNamespaces()
Get a reference to the parsed accelerator table object.
const DWARFDebugMacro * getDebugMacro()
Get a pointer to the parsed DebugMacro information object.
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, bool ThreadSafe=false)
const DWARFDebugMacro * getDebugMacinfo()
Get a pointer to the parsed DebugMacinfo information object.
unit_iterator_range dwo_units()
Get all units in the DWO context.
std::optional< DILineInfo > getLineInfoForAddress(object::SectionedAddress Address, DILineInfoSpecifier Specifier=DILineInfoSpecifier()) override
uint64_t getRelocatedValue(uint32_t Size, uint64_t *Off, uint64_t *SectionIndex=nullptr, Error *Err=nullptr) const
Extracts a value and returns it as adjusted by the Relocator.
A DWARFDataExtractor (typically for an in-memory copy of an object-file section) plus a relocation ma...
LLVM_ABI 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.
LLVM_ABI void dump(raw_ostream &OS) const
LLVM_ABI Error extract(DWARFDataExtractor data, uint64_t *offset_ptr, function_ref< void(Error)> WarningHandler=nullptr)
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.
.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.
LLVM_ABI void extract(DWARFDataExtractor Data, bool GnuStyle, function_ref< void(Error)> RecoverableErrorHandler)
LLVM_ABI void dump(raw_ostream &OS) const
LLVM_ABI Error extract(const DWARFDataExtractor &data, uint64_t *offset_ptr)
LLVM_ABI 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:43
LLVM_ABI DWARFDie getAttributeValueAsReferencedDie(dwarf::Attribute Attr) const
Extract the specified attribute from this DIE as the referenced DIE.
Definition DWARFDie.cpp:306
LLVM_ABI std::optional< DWARFFormValue > find(dwarf::Attribute Attr) const
Extract the specified attribute from this DIE.
Definition DWARFDie.cpp:250
DWARFUnit * getDwarfUnit() const
Definition DWARFDie.h:55
LLVM_ABI 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:457
LLVM_ABI 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:502
LLVM_ABI std::string getDeclFile(DILineInfoSpecifier::FileLineInfoKind Kind) const
Definition DWARFDie.cpp:495
LLVM_ABI uint64_t getDeclLine() const
Returns the declaration line (start line) for a DIE, assuming it specifies a subprogram.
Definition DWARFDie.cpp:490
dwarf::Tag getTag() const
Definition DWARFDie.h:73
LLVM_ABI Expected< DWARFLocationExpressionsVector > getLocations(dwarf::Attribute Attr) const
Definition DWARFDie.cpp:427
bool isValid() const
Definition DWARFDie.h:52
LLVM_ABI void dump(raw_ostream &OS, unsigned indent=0, DIDumpOptions DumpOpts=DIDumpOptions()) const
Dump the DIE and all of its attributes to the supplied stream.
Definition DWARFDie.cpp:595
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 ....
virtual StringRef getFileName() const
Definition DWARFObject.h:31
virtual StringRef getAbbrevDWOSection() const
Definition DWARFObject.h:64
virtual const DWARFSection & getFrameSection() const
Definition DWARFObject.h:44
virtual const DWARFSection & getNamesSection() const
Definition DWARFObject.h:80
virtual const DWARFSection & getAppleNamespacesSection() const
Definition DWARFObject.h:77
virtual void forEachInfoDWOSections(function_ref< void(const DWARFSection &)> F) const
Definition DWARFObject.h:61
virtual const DWARFSection & getAppleTypesSection() const
Definition DWARFObject.h:76
virtual void forEachInfoSections(function_ref< void(const DWARFSection &)> F) const
Definition DWARFObject.h:37
virtual const DWARFSection & getAppleNamesSection() const
Definition DWARFObject.h:75
virtual const DWARFSection & getEHFrameSection() const
Definition DWARFObject.h:45
virtual void forEachTypesSections(function_ref< void(const DWARFSection &)> F) const
Definition DWARFObject.h:39
virtual const DWARFSection & getLocSection() const
Definition DWARFObject.h:41
virtual const DWARFSection & getAppleObjCSection() const
Definition DWARFObject.h:81
virtual void forEachTypesDWOSections(function_ref< void(const DWARFSection &)> F) const
Definition DWARFObject.h:63
virtual StringRef getStrSection() const
Definition DWARFObject.h:48
virtual uint8_t getAddressSize() const
Definition DWARFObject.h:35
Base class describing the header of any kind of "unit." Some information is specific to certain unit ...
Definition DWARFUnit.h:56
LLVM_ABI void dump(raw_ostream &OS) const
Describe a collection of units.
Definition DWARFUnit.h:130
void finishedInfoUnits()
Indicate that parsing .debug_info[.dwo] is done, and remaining units will be from ....
Definition DWARFUnit.h:178
LLVM_ABI void addUnitsForSection(DWARFContext &C, const DWARFSection &Section, DWARFSectionKind SectionKind)
Read units from a .debug_info or .debug_types section.
Definition DWARFUnit.cpp:42
LLVM_ABI 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
LLVM_ABI DWARFUnit * getUnitForIndexEntry(const DWARFUnitIndex::Entry &E)
DWARFContext & getContext() const
Definition DWARFUnit.h:323
DWARFDie getDIEForOffset(uint64_t Offset)
Return the DIE object for a given offset Offset inside the unit's DIE vector.
Definition DWARFUnit.h:537
const char * getCompilationDir()
DWARFDie getSubroutineForAddress(uint64_t Address)
Returns subprogram DIE with address range encompassing the provided address.
A class that verifies DWARF debug information given a DWARF Context.
LLVM_ABI bool handleAccelTables()
Verify the information in accelerator tables, if they exist.
LLVM_ABI bool handleDebugTUIndex()
Verify the information in the .debug_tu_index section.
LLVM_ABI bool handleDebugStrOffsets()
Verify the information in the .debug_str_offsets[.dwo].
LLVM_ABI bool handleDebugCUIndex()
Verify the information in the .debug_cu_index section.
LLVM_ABI bool handleDebugInfo()
Verify the information in the .debug_info and .debug_types sections.
LLVM_ABI bool handleDebugLine()
Verify the information in the .debug_line section.
LLVM_ABI void summarize()
Emits any aggregate information collected, depending on the dump options.
LLVM_ABI 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.
LLVM_ABI DILocation * get() const
Get the underlying DILocation.
Definition DebugLoc.cpp:50
DenseMapIterator< KeyT, ValueT, KeyInfoT, BucketT, true > const_iterator
Definition DenseMap.h:75
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
static ErrorSuccess success()
Create a success value.
Definition Error.h:336
Tagged union holding either a T or a Error.
Definition Error.h:485
Error takeError()
Take ownership of the stored error.
Definition Error.h:612
reference get()
Returns a reference to the stored T value.
Definition Error.h:582
An inferface for inquiring the load address of a loaded object file to be used by the DIContext imple...
Definition DIContext.h:280
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition SmallString.h:26
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
Definition StringMap.h:133
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition StringRef.h:581
constexpr size_t size() const
size - Get the string size.
Definition StringRef.h:154
Triple - Helper class for working with autoconf configuration names.
Definition Triple.h:47
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
static Twine utohexstr(uint64_t Val)
Definition Twine.h:388
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:45
static LLVM_ABI void defaultWarningHandler(Error Warning)
Implement default handling for Warning.
static LLVM_ABI void defaultErrorHandler(Error Err)
Implement default handling for Error.
An efficient, type-erasing, non-owning reference to a callable.
static LLVM_ABI 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:231
virtual section_iterator section_end() const =0
section_iterator_range sections() const
Definition ObjectFile.h:331
static Expected< OwningBinary< ObjectFile > > createObjectFile(StringRef ObjectPath)
virtual StringRef mapDebugSectionName(StringRef Name) const
Maps a debug section name to a standard DWARF section name.
Definition ObjectFile.h:357
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:54
uint64_t getIndex() const
Definition ObjectFile.h:530
bool isCompressed() const
Definition ObjectFile.h:551
uint64_t getAddress() const
Definition ObjectFile.h:526
Expected< StringRef > getName() const
Definition ObjectFile.h:522
Expected< uint64_t > getAddress() const
Returns the symbol virtual address (i.e.
Definition ObjectFile.h:469
Expected< section_iterator > getSection() const
Get section this symbol is defined in reference to.
Definition ObjectFile.h:485
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:53
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.
LLVM_ABI StringRef FormatString(DwarfFormat Format)
Definition Dwarf.cpp:889
@ Entry
Definition COFF.h:862
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
static constexpr StringLiteral SectionNames[SectionKindsNum]
Calculates the starting offsets for various sections within the .debug_names section.
Definition Dwarf.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:92
@ DWARF32
Definition Dwarf.h:92
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:1080
std::optional< uint64_t > toUnsigned(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract an unsigned constant.
content_iterator< SectionRef > section_iterator
Definition ObjectFile.h:49
Error createError(const Twine &Err)
Definition Error.h:86
uint64_t(*)(uint64_t Type, uint64_t Offset, uint64_t S, uint64_t LocData, int64_t Addend) RelocationResolver
LLVM_ABI std::pair< SupportsRelocation, RelocationResolver > getRelocationResolver(const ObjectFile &Obj)
bool(*)(uint64_t) SupportsRelocation
LLVM_ABI StringRef extension(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get extension.
Definition Path.cpp:590
SmartMutex< false > Mutex
Mutex - A standard, always enforced mutex.
Definition Mutex.h:66
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:477
@ Length
Definition DWP.cpp:477
LLVM_ABI void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner={})
Log all errors (if any) in E to OS.
Definition Error.cpp:65
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:1733
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:649
LLVM_ABI std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
Definition Error.cpp:98
SmallVector< std::pair< uint64_t, DILineInfo >, 16 > DILineInfoTable
Definition DIContext.h:91
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition STLExtras.h:2118
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:166
auto unique(Range &&R, Predicate P)
Definition STLExtras.h:2058
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition Error.h:1305
@ DW_SECT_EXT_TYPES
@ invalid_argument
Definition Errc.h:56
auto dyn_cast_or_null(const Y &Val)
Definition Casting.h:759
void sort(IteratorTy Start, IteratorTy End)
Definition STLExtras.h:1632
static Error createError(const Twine &Err)
Definition APFloat.cpp:415
FunctionAddr VTableAddr Count
Definition InstrProf.h:139
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:548
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition Format.h:126
@ Success
The lock was released successfully.
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
Definition Error.h:340
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
FunctionAddr VTableAddr uintptr_t uintptr_t Data
Definition InstrProf.h:189
std::string toString(const APInt &I, unsigned Radix, bool Signed, bool formatAsCLiteral=false, bool UpperCase=true, bool InsertSeparators=false)
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:1849
LLVM_ABI Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
Definition Error.cpp:111
@ DIDT_ID_Count
Definition DIContext.h:179
@ DIDT_All
Definition DIContext.h:186
@ DIDT_UUID
Definition DIContext.h:191
DenseMap< uint64_t, RelocAddrEntry > RelocAddrMap
In place of applying the relocations to the data we've read from disk we use a separate mapping table...
void consumeError(Error Err)
Consume a Error without doing anything.
Definition Error.h:1083
Implement std::hash so that hash_code can be used in STL containers.
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:196
std::function< void(Error)> WarningHandler
Definition DIContext.h:237
std::function< void(Error)> RecoverableErrorHandler
Definition DIContext.h:235
DIDumpOptions noImplicitRecursion() const
Return the options with RecurseDepth set to 0 unless explicitly required.
Definition DIContext.h:226
Controls which fields of DILineInfo container should be filled with data.
Definition DIContext.h:146
A format-neutral container for source line information.
Definition DIContext.h:32
static constexpr const char *const BadString
Definition DIContext.h:35
std::optional< uint64_t > StartAddress
Definition DIContext.h:49
uint32_t Discriminator
Definition DIContext.h:52
uint32_t Line
Definition DIContext.h:46
std::string FileName
Definition DIContext.h:38
std::string FunctionName
Definition DIContext.h:39
uint32_t Column
Definition DIContext.h:47
uint32_t StartLine
Definition DIContext.h:48
std::string StartFileName
Definition DIContext.h:40
Wraps the returned DIEs for a given address.
LLVM_ABI bool getFileLineInfoForAddress(object::SectionedAddress Address, bool Approximate, 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.
LLVM_ABI bool lookupAddressRange(object::SectionedAddress Address, uint64_t Size, std::vector< uint32_t > &Result, std::optional< uint64_t > StmtSequenceOffset=std::nullopt) const
Fills the Result argument with the indices of the rows that correspond to the address range specified...
Standard .debug_line state machine structure.