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)) {
1348 if (TUI.getVersion() >= 5) {
1350 DWOUnits.getUnitForIndexEntry(*R, DW_SECT_INFO));
1351 } else {
1352 DWARFUnit *TypesUnit = nullptr;
1354 if (!TypesUnit)
1355 TypesUnit =
1356 DWOUnits.getUnitForIndexEntry(*R, DW_SECT_EXT_TYPES, &S);
1357 });
1358 return dyn_cast_or_null<DWARFTypeUnit>(TypesUnit);
1359 }
1360 }
1361 return nullptr;
1362 }
1363 return State->getTypeUnitMap(IsDWO).lookup(Hash);
1364}
1365
1367 DWARFUnitVector &DWOUnits = State->getDWOUnits(LazyParse);
1368
1369 if (const auto &CUI = getCUIndex()) {
1370 if (const auto *R = CUI.getFromHash(Hash))
1372 DWOUnits.getUnitForIndexEntry(*R, DW_SECT_INFO));
1373 return nullptr;
1374 }
1375
1376 // If there's no index, just search through the CUs in the DWO - there's
1377 // probably only one unless this is something like LTO - though an in-process
1378 // built/cached lookup table could be used in that case to improve repeated
1379 // lookups of different CUs in the DWO.
1380 for (const auto &DWOCU : dwo_compile_units()) {
1381 // Might not have parsed DWO ID yet.
1382 if (!DWOCU->getDWOId()) {
1383 if (std::optional<uint64_t> DWOId =
1384 toUnsigned(DWOCU->getUnitDIE().find(DW_AT_GNU_dwo_id)))
1385 DWOCU->setDWOId(*DWOId);
1386 else
1387 // No DWO ID?
1388 continue;
1389 }
1390 if (DWOCU->getDWOId() == Hash)
1391 return dyn_cast<DWARFCompileUnit>(DWOCU.get());
1392 }
1393 return nullptr;
1394}
1395
1397 if (auto *CU = State->getNormalUnits().getUnitForOffset(Offset))
1398 return CU->getDIEForOffset(Offset);
1399 return DWARFDie();
1400}
1401
1403 bool Success = true;
1404 DWARFVerifier verifier(OS, *this, DumpOpts);
1405
1406 Success &= verifier.handleDebugAbbrev();
1407 if (DumpOpts.DumpType & DIDT_DebugCUIndex)
1408 Success &= verifier.handleDebugCUIndex();
1409 if (DumpOpts.DumpType & DIDT_DebugTUIndex)
1410 Success &= verifier.handleDebugTUIndex();
1411 if (DumpOpts.DumpType & DIDT_DebugInfo)
1412 Success &= verifier.handleDebugInfo();
1413 if (DumpOpts.DumpType & DIDT_DebugLine)
1414 Success &= verifier.handleDebugLine();
1415 if (DumpOpts.DumpType & DIDT_DebugStrOffsets)
1416 Success &= verifier.handleDebugStrOffsets();
1417 Success &= verifier.handleAccelTables();
1418 verifier.summarize();
1419 return Success;
1420}
1421
1423 return State->getCUIndex();
1424}
1425
1427 return State->getTUIndex();
1428}
1429
1431 return State->getGdbIndex();
1432}
1433
1435 return State->getDebugAbbrev();
1436}
1437
1439 return State->getDebugAbbrevDWO();
1440}
1441
1443 return State->getDebugLoc();
1444}
1445
1447 return State->getDebugAranges();
1448}
1449
1451 return State->getDebugFrame();
1452}
1453
1455 return State->getEHFrame();
1456}
1457
1459 return State->getDebugMacro();
1460}
1461
1463 return State->getDebugMacroDWO();
1464}
1465
1467 return State->getDebugMacinfo();
1468}
1469
1471 return State->getDebugMacinfoDWO();
1472}
1473
1474
1476 return State->getDebugNames();
1477}
1478
1480 return State->getAppleNames();
1481}
1482
1484 return State->getAppleTypes();
1485}
1486
1488 return State->getAppleNamespaces();
1489}
1490
1492 return State->getAppleObjC();
1493}
1494
1498 getLineTableForUnit(U, WarningHandler);
1499 if (!ExpectedLineTable) {
1500 WarningHandler(ExpectedLineTable.takeError());
1501 return nullptr;
1502 }
1503 return *ExpectedLineTable;
1504}
1505
1507 DWARFUnit *U, function_ref<void(Error)> RecoverableErrorHandler) {
1508 return State->getLineTableForUnit(U, RecoverableErrorHandler);
1509}
1510
1512 return State->clearLineTableForUnit(U);
1513}
1514
1515DWARFUnitVector &DWARFContext::getDWOUnits(bool Lazy) {
1516 return State->getDWOUnits(Lazy);
1517}
1518
1520 return State->getNormalUnits().getUnitForOffset(Offset);
1521}
1522
1526
1531
1534 if (DWARFCompileUnit *OffsetCU = getCompileUnitForOffset(CUOffset))
1535 return OffsetCU;
1536
1537 // Global variables are often missed by the above search, for one of two
1538 // reasons:
1539 // 1. .debug_aranges may not include global variables. On clang, it seems we
1540 // put the globals in the aranges, but this isn't true for gcc.
1541 // 2. Even if the global variable is in a .debug_arange, global variables
1542 // may not be captured in the [start, end) addresses described by the
1543 // parent compile unit.
1544 //
1545 // So, we walk the CU's and their child DI's manually, looking for the
1546 // specific global variable.
1547 for (std::unique_ptr<DWARFUnit> &CU : compile_units()) {
1548 if (CU->getVariableForAddress(Address)) {
1549 return static_cast<DWARFCompileUnit *>(CU.get());
1550 }
1551 }
1552 return nullptr;
1553}
1554
1556 bool CheckDWO) {
1557 DIEsForAddress Result;
1558
1560 if (!CU)
1561 return Result;
1562
1563 if (CheckDWO) {
1564 // We were asked to check the DWO file and this debug information is more
1565 // complete that any information in the skeleton compile unit, so search the
1566 // DWO first to see if we have a match.
1567 DWARFDie CUDie = CU->getUnitDIE(false);
1568 DWARFDie CUDwoDie = CU->getNonSkeletonUnitDIE(false);
1569 if (CheckDWO && CUDwoDie && CUDie != CUDwoDie) {
1570 // We have a DWO file, lets search it.
1571 DWARFCompileUnit *CUDwo =
1573 if (CUDwo) {
1574 Result.FunctionDIE = CUDwo->getSubroutineForAddress(Address);
1575 if (Result.FunctionDIE)
1576 Result.CompileUnit = CUDwo;
1577 }
1578 }
1579 }
1580
1581 // Search the normal DWARF if we didn't find a match in the DWO file or if
1582 // we didn't check the DWO file above.
1583 if (!Result) {
1584 Result.CompileUnit = CU;
1585 Result.FunctionDIE = CU->getSubroutineForAddress(Address);
1586 }
1587
1588 std::vector<DWARFDie> Worklist;
1589 Worklist.push_back(Result.FunctionDIE);
1590 while (!Worklist.empty()) {
1591 DWARFDie DIE = Worklist.back();
1592 Worklist.pop_back();
1593
1594 if (!DIE.isValid())
1595 continue;
1596
1597 if (DIE.getTag() == DW_TAG_lexical_block &&
1598 DIE.addressRangeContainsAddress(Address)) {
1599 Result.BlockDIE = DIE;
1600 break;
1601 }
1602
1603 append_range(Worklist, DIE);
1604 }
1605
1606 return Result;
1607}
1608
1609/// TODO: change input parameter from "uint64_t Address"
1610/// into "SectionedAddress Address"
1612 DWARFCompileUnit *CU, uint64_t Address, FunctionNameKind Kind,
1614 std::string &FunctionName, std::string &StartFile, uint32_t &StartLine,
1615 std::optional<uint64_t> &StartAddress) {
1616 // The address may correspond to instruction in some inlined function,
1617 // so we have to build the chain of inlined functions and take the
1618 // name of the topmost function in it.
1619 SmallVector<DWARFDie, 4> InlinedChain;
1620 CU->getInlinedChainForAddress(Address, InlinedChain);
1621 if (InlinedChain.empty())
1622 return false;
1623
1624 const DWARFDie &DIE = InlinedChain[0];
1625 bool FoundResult = false;
1626 const char *Name = nullptr;
1627 if (Kind != FunctionNameKind::None && (Name = DIE.getSubroutineName(Kind))) {
1628 FunctionName = Name;
1629 FoundResult = true;
1630 }
1631 std::string DeclFile = DIE.getDeclFile(FileNameKind);
1632 if (!DeclFile.empty()) {
1633 StartFile = DeclFile;
1634 FoundResult = true;
1635 }
1636 if (auto DeclLineResult = DIE.getDeclLine()) {
1637 StartLine = DeclLineResult;
1638 FoundResult = true;
1639 }
1640 if (auto LowPcAddr = toSectionedAddress(DIE.find(DW_AT_low_pc)))
1641 StartAddress = LowPcAddr->Address;
1642 return FoundResult;
1643}
1644
1645static std::optional<int64_t>
1647 std::optional<unsigned> FrameBaseReg) {
1648 if (!Expr.empty() &&
1649 (Expr[0] == DW_OP_fbreg ||
1650 (FrameBaseReg && Expr[0] == DW_OP_breg0 + *FrameBaseReg))) {
1651 unsigned Count;
1652 int64_t Offset = decodeSLEB128(Expr.data() + 1, &Count, Expr.end());
1653 // A single DW_OP_fbreg or DW_OP_breg.
1654 if (Expr.size() == Count + 1)
1655 return Offset;
1656 // Same + DW_OP_deref (Fortran arrays look like this).
1657 if (Expr.size() == Count + 2 && Expr[Count + 1] == DW_OP_deref)
1658 return Offset;
1659 // Fallthrough. Do not accept ex. (DW_OP_breg W29, DW_OP_stack_value)
1660 }
1661 return std::nullopt;
1662}
1663
1664void DWARFContext::addLocalsForDie(DWARFCompileUnit *CU, DWARFDie Subprogram,
1665 DWARFDie Die, std::vector<DILocal> &Result) {
1666 if (Die.getTag() == DW_TAG_variable ||
1667 Die.getTag() == DW_TAG_formal_parameter) {
1668 DILocal Local;
1669 if (const char *Name = Subprogram.getSubroutineName(DINameKind::ShortName))
1670 Local.FunctionName = Name;
1671
1672 std::optional<unsigned> FrameBaseReg;
1673 if (auto FrameBase = Subprogram.find(DW_AT_frame_base))
1674 if (std::optional<ArrayRef<uint8_t>> Expr = FrameBase->getAsBlock())
1675 if (!Expr->empty() && (*Expr)[0] >= DW_OP_reg0 &&
1676 (*Expr)[0] <= DW_OP_reg31) {
1677 FrameBaseReg = (*Expr)[0] - DW_OP_reg0;
1678 }
1679
1680 if (Expected<std::vector<DWARFLocationExpression>> Loc =
1681 Die.getLocations(DW_AT_location)) {
1682 for (const auto &Entry : *Loc) {
1683 if (std::optional<int64_t> FrameOffset =
1684 getExpressionFrameOffset(Entry.Expr, FrameBaseReg)) {
1685 Local.FrameOffset = *FrameOffset;
1686 break;
1687 }
1688 }
1689 } else {
1690 // FIXME: missing DW_AT_location is OK here, but other errors should be
1691 // reported to the user.
1692 consumeError(Loc.takeError());
1693 }
1694
1695 if (auto TagOffsetAttr = Die.find(DW_AT_LLVM_tag_offset))
1696 Local.TagOffset = TagOffsetAttr->getAsUnsignedConstant();
1697
1698 if (auto Origin =
1699 Die.getAttributeValueAsReferencedDie(DW_AT_abstract_origin))
1700 Die = Origin;
1701 if (auto NameAttr = Die.find(DW_AT_name))
1702 if (std::optional<const char *> Name = dwarf::toString(*NameAttr))
1703 Local.Name = *Name;
1704 if (auto Type = Die.getAttributeValueAsReferencedDie(DW_AT_type))
1705 Local.Size = Type.getTypeSize(getCUAddrSize());
1706 if (auto DeclFileAttr = Die.find(DW_AT_decl_file)) {
1707 if (const auto *LT = CU->getContext().getLineTableForUnit(CU))
1708 LT->getFileNameByIndex(
1709 *DeclFileAttr->getAsUnsignedConstant(), CU->getCompilationDir(),
1711 Local.DeclFile);
1712 }
1713 if (auto DeclLineAttr = Die.find(DW_AT_decl_line))
1714 Local.DeclLine = *DeclLineAttr->getAsUnsignedConstant();
1715
1716 Result.push_back(Local);
1717 return;
1718 }
1719
1720 if (Die.getTag() == DW_TAG_inlined_subroutine)
1721 if (auto Origin =
1722 Die.getAttributeValueAsReferencedDie(DW_AT_abstract_origin))
1723 Subprogram = Origin;
1724
1725 for (auto Child : Die)
1726 addLocalsForDie(CU, Subprogram, Child, Result);
1727}
1728
1729std::vector<DILocal>
1731 std::vector<DILocal> Result;
1733 if (!CU)
1734 return Result;
1735
1736 DWARFDie Subprogram = CU->getSubroutineForAddress(Address.Address);
1737 if (Subprogram.isValid())
1738 addLocalsForDie(CU, Subprogram, Subprogram, Result);
1739 return Result;
1740}
1741
1742std::optional<DILineInfo>
1746 if (!CU)
1747 return std::nullopt;
1748
1749 DILineInfo Result;
1751 CU, Address.Address, Spec.FNKind, Spec.FLIKind, Result.FunctionName,
1752 Result.StartFileName, Result.StartLine, Result.StartAddress);
1753 if (Spec.FLIKind != FileLineInfoKind::None) {
1754 if (const DWARFLineTable *LineTable = getLineTableForUnit(CU)) {
1755 LineTable->getFileLineInfoForAddress(
1756 {Address.Address, Address.SectionIndex}, Spec.ApproximateLine,
1757 CU->getCompilationDir(), Spec.FLIKind, Result);
1758 }
1759 }
1760
1761 return Result;
1762}
1763
1764std::optional<DILineInfo>
1766 DILineInfo Result;
1768 if (!CU)
1769 return Result;
1770
1771 if (DWARFDie Die = CU->getVariableForAddress(Address.Address)) {
1772 Result.FileName = Die.getDeclFile(FileLineInfoKind::AbsoluteFilePath);
1773 Result.Line = Die.getDeclLine();
1774 }
1775
1776 return Result;
1777}
1778
1781 DILineInfoTable Lines;
1783 if (!CU)
1784 return Lines;
1785
1786 uint32_t StartLine = 0;
1787 std::string StartFileName;
1788 std::string FunctionName(DILineInfo::BadString);
1789 std::optional<uint64_t> StartAddress;
1791 Spec.FLIKind, FunctionName,
1792 StartFileName, StartLine, StartAddress);
1793
1794 // If the Specifier says we don't need FileLineInfo, just
1795 // return the top-most function at the starting address.
1796 if (Spec.FLIKind == FileLineInfoKind::None) {
1797 DILineInfo Result;
1798 Result.FunctionName = FunctionName;
1799 Result.StartFileName = StartFileName;
1800 Result.StartLine = StartLine;
1801 Result.StartAddress = StartAddress;
1802 Lines.push_back(std::make_pair(Address.Address, Result));
1803 return Lines;
1804 }
1805
1806 const DWARFLineTable *LineTable = getLineTableForUnit(CU);
1807
1808 // Get the index of row we're looking for in the line table.
1809 std::vector<uint32_t> RowVector;
1810 if (!LineTable->lookupAddressRange({Address.Address, Address.SectionIndex},
1811 Size, RowVector)) {
1812 return Lines;
1813 }
1814
1815 for (uint32_t RowIndex : RowVector) {
1816 // Take file number and line/column from the row.
1817 const DWARFDebugLine::Row &Row = LineTable->Rows[RowIndex];
1818 DILineInfo Result;
1819 LineTable->getFileNameByIndex(Row.File, CU->getCompilationDir(),
1820 Spec.FLIKind, Result.FileName);
1821 Result.FunctionName = FunctionName;
1822 Result.Line = Row.Line;
1823 Result.Column = Row.Column;
1824 Result.StartFileName = StartFileName;
1825 Result.StartLine = StartLine;
1826 Result.StartAddress = StartAddress;
1827 Lines.push_back(std::make_pair(Row.Address.Address, Result));
1828 }
1829
1830 return Lines;
1831}
1832
1836 DIInliningInfo InliningInfo;
1837
1839 if (!CU)
1840 return InliningInfo;
1841
1842 const DWARFLineTable *LineTable = nullptr;
1843 SmallVector<DWARFDie, 4> InlinedChain;
1844 CU->getInlinedChainForAddress(Address.Address, InlinedChain);
1845 if (InlinedChain.size() == 0) {
1846 // If there is no DIE for address (e.g. it is in unavailable .dwo file),
1847 // try to at least get file/line info from symbol table.
1848 if (Spec.FLIKind != FileLineInfoKind::None) {
1849 DILineInfo Frame;
1850 LineTable = getLineTableForUnit(CU);
1851 if (LineTable &&
1852 LineTable->getFileLineInfoForAddress(
1853 {Address.Address, Address.SectionIndex}, Spec.ApproximateLine,
1854 CU->getCompilationDir(), Spec.FLIKind, Frame))
1855 InliningInfo.addFrame(Frame);
1856 }
1857 return InliningInfo;
1858 }
1859
1860 uint32_t CallFile = 0, CallLine = 0, CallColumn = 0, CallDiscriminator = 0;
1861 for (uint32_t i = 0, n = InlinedChain.size(); i != n; i++) {
1862 DWARFDie &FunctionDIE = InlinedChain[i];
1863 DILineInfo Frame;
1864 // Get function name if necessary.
1865 if (const char *Name = FunctionDIE.getSubroutineName(Spec.FNKind))
1866 Frame.FunctionName = Name;
1867 if (auto DeclLineResult = FunctionDIE.getDeclLine())
1868 Frame.StartLine = DeclLineResult;
1869 Frame.StartFileName = FunctionDIE.getDeclFile(Spec.FLIKind);
1870 if (auto LowPcAddr = toSectionedAddress(FunctionDIE.find(DW_AT_low_pc)))
1871 Frame.StartAddress = LowPcAddr->Address;
1872 if (Spec.FLIKind != FileLineInfoKind::None) {
1873 if (i == 0) {
1874 // For the topmost frame, initialize the line table of this
1875 // compile unit and fetch file/line info from it.
1876 LineTable = getLineTableForUnit(CU);
1877 // For the topmost routine, get file/line info from line table.
1878 if (LineTable)
1879 LineTable->getFileLineInfoForAddress(
1880 {Address.Address, Address.SectionIndex}, Spec.ApproximateLine,
1881 CU->getCompilationDir(), Spec.FLIKind, Frame);
1882 } else {
1883 // Otherwise, use call file, call line and call column from
1884 // previous DIE in inlined chain.
1885 if (LineTable)
1886 LineTable->getFileNameByIndex(CallFile, CU->getCompilationDir(),
1887 Spec.FLIKind, Frame.FileName);
1888 Frame.Line = CallLine;
1889 Frame.Column = CallColumn;
1890 Frame.Discriminator = CallDiscriminator;
1891 }
1892 // Get call file/line/column of a current DIE.
1893 if (i + 1 < n) {
1894 FunctionDIE.getCallerFrame(CallFile, CallLine, CallColumn,
1895 CallDiscriminator);
1896 }
1897 }
1898 InliningInfo.addFrame(Frame);
1899 }
1900 return InliningInfo;
1901}
1902
1903std::shared_ptr<DWARFContext>
1905 return State->getDWOContext(AbsolutePath);
1906}
1907
1908static Error createError(const Twine &Reason, llvm::Error E) {
1909 return make_error<StringError>(Reason + toString(std::move(E)),
1911}
1912
1913/// SymInfo contains information about symbol: it's address
1914/// and section index which is -1LL for absolute symbols.
1919
1920/// Returns the address of symbol relocation used against and a section index.
1921/// Used for futher relocations computation. Symbol's section load address is
1923 const RelocationRef &Reloc,
1924 const LoadedObjectInfo *L,
1925 std::map<SymbolRef, SymInfo> &Cache) {
1926 SymInfo Ret = {0, (uint64_t)-1LL};
1928 object::symbol_iterator Sym = Reloc.getSymbol();
1929
1930 std::map<SymbolRef, SymInfo>::iterator CacheIt = Cache.end();
1931 // First calculate the address of the symbol or section as it appears
1932 // in the object file
1933 if (Sym != Obj.symbol_end()) {
1934 bool New;
1935 std::tie(CacheIt, New) = Cache.try_emplace(*Sym);
1936 if (!New)
1937 return CacheIt->second;
1938
1939 Expected<uint64_t> SymAddrOrErr = Sym->getAddress();
1940 if (!SymAddrOrErr)
1941 return createError("failed to compute symbol address: ",
1942 SymAddrOrErr.takeError());
1943
1944 // Also remember what section this symbol is in for later
1945 auto SectOrErr = Sym->getSection();
1946 if (!SectOrErr)
1947 return createError("failed to get symbol section: ",
1948 SectOrErr.takeError());
1949
1950 RSec = *SectOrErr;
1951 Ret.Address = *SymAddrOrErr;
1952 } else if (auto *MObj = dyn_cast<MachOObjectFile>(&Obj)) {
1953 RSec = MObj->getRelocationSection(Reloc.getRawDataRefImpl());
1954 Ret.Address = RSec->getAddress();
1955 }
1956
1957 if (RSec != Obj.section_end())
1958 Ret.SectionIndex = RSec->getIndex();
1959
1960 // If we are given load addresses for the sections, we need to adjust:
1961 // SymAddr = (Address of Symbol Or Section in File) -
1962 // (Address of Section in File) +
1963 // (Load Address of Section)
1964 // RSec is now either the section being targeted or the section
1965 // containing the symbol being targeted. In either case,
1966 // we need to perform the same computation.
1967 if (L && RSec != Obj.section_end())
1968 if (uint64_t SectionLoadAddress = L->getSectionLoadAddress(*RSec))
1969 Ret.Address += SectionLoadAddress - RSec->getAddress();
1970
1971 if (CacheIt != Cache.end())
1972 CacheIt->second = Ret;
1973
1974 return Ret;
1975}
1976
1978 const RelocationRef &Reloc) {
1979 const MachOObjectFile *MachObj = dyn_cast<MachOObjectFile>(&Obj);
1980 if (!MachObj)
1981 return false;
1982 // MachO also has relocations that point to sections and
1983 // scattered relocations.
1984 auto RelocInfo = MachObj->getRelocation(Reloc.getRawDataRefImpl());
1985 return MachObj->isRelocationScattered(RelocInfo);
1986}
1987
1988namespace {
1989struct DWARFSectionMap final : public DWARFSection {
1990 RelocAddrMap Relocs;
1991};
1992
1993class DWARFObjInMemory final : public DWARFObject {
1994 bool IsLittleEndian;
1995 uint8_t AddressSize;
1996 StringRef FileName;
1997 const object::ObjectFile *Obj = nullptr;
1998 std::vector<SectionName> SectionNames;
1999
2000 using InfoSectionMap = MapVector<object::SectionRef, DWARFSectionMap,
2001 std::map<object::SectionRef, unsigned>>;
2002
2003 InfoSectionMap InfoSections;
2004 InfoSectionMap TypesSections;
2005 InfoSectionMap InfoDWOSections;
2006 InfoSectionMap TypesDWOSections;
2007
2008 DWARFSectionMap LocSection;
2009 DWARFSectionMap LoclistsSection;
2010 DWARFSectionMap LoclistsDWOSection;
2011 DWARFSectionMap LineSection;
2012 DWARFSectionMap RangesSection;
2013 DWARFSectionMap RnglistsSection;
2014 DWARFSectionMap StrOffsetsSection;
2015 DWARFSectionMap LineDWOSection;
2016 DWARFSectionMap FrameSection;
2017 DWARFSectionMap EHFrameSection;
2018 DWARFSectionMap LocDWOSection;
2019 DWARFSectionMap StrOffsetsDWOSection;
2020 DWARFSectionMap RangesDWOSection;
2021 DWARFSectionMap RnglistsDWOSection;
2022 DWARFSectionMap AddrSection;
2023 DWARFSectionMap AppleNamesSection;
2024 DWARFSectionMap AppleTypesSection;
2025 DWARFSectionMap AppleNamespacesSection;
2026 DWARFSectionMap AppleObjCSection;
2027 DWARFSectionMap NamesSection;
2028 DWARFSectionMap PubnamesSection;
2029 DWARFSectionMap PubtypesSection;
2030 DWARFSectionMap GnuPubnamesSection;
2031 DWARFSectionMap GnuPubtypesSection;
2032 DWARFSectionMap MacroSection;
2033
2034 DWARFSectionMap *mapNameToDWARFSection(StringRef Name) {
2035 return StringSwitch<DWARFSectionMap *>(Name)
2036 .Case("debug_loc", &LocSection)
2037 .Case("debug_loclists", &LoclistsSection)
2038 .Case("debug_loclists.dwo", &LoclistsDWOSection)
2039 .Case("debug_line", &LineSection)
2040 .Case("debug_frame", &FrameSection)
2041 .Case("eh_frame", &EHFrameSection)
2042 .Case("debug_str_offsets", &StrOffsetsSection)
2043 .Case("debug_ranges", &RangesSection)
2044 .Case("debug_rnglists", &RnglistsSection)
2045 .Case("debug_loc.dwo", &LocDWOSection)
2046 .Case("debug_line.dwo", &LineDWOSection)
2047 .Case("debug_names", &NamesSection)
2048 .Case("debug_rnglists.dwo", &RnglistsDWOSection)
2049 .Case("debug_str_offsets.dwo", &StrOffsetsDWOSection)
2050 .Case("debug_addr", &AddrSection)
2051 .Case("apple_names", &AppleNamesSection)
2052 .Case("debug_pubnames", &PubnamesSection)
2053 .Case("debug_pubtypes", &PubtypesSection)
2054 .Case("debug_gnu_pubnames", &GnuPubnamesSection)
2055 .Case("debug_gnu_pubtypes", &GnuPubtypesSection)
2056 .Case("apple_types", &AppleTypesSection)
2057 .Case("apple_namespaces", &AppleNamespacesSection)
2058 .Case("apple_namespac", &AppleNamespacesSection)
2059 .Case("apple_objc", &AppleObjCSection)
2060 .Case("debug_macro", &MacroSection)
2061 .Default(nullptr);
2062 }
2063
2064 StringRef AbbrevSection;
2065 StringRef ArangesSection;
2066 StringRef StrSection;
2067 StringRef MacinfoSection;
2068 StringRef MacinfoDWOSection;
2069 StringRef MacroDWOSection;
2070 StringRef AbbrevDWOSection;
2071 StringRef StrDWOSection;
2072 StringRef CUIndexSection;
2073 StringRef GdbIndexSection;
2074 StringRef TUIndexSection;
2075 StringRef LineStrSection;
2076
2077 // A deque holding section data whose iterators are not invalidated when
2078 // new decompressed sections are inserted at the end.
2079 std::deque<SmallString<0>> UncompressedSections;
2080
2081 StringRef *mapSectionToMember(StringRef Name) {
2082 if (DWARFSection *Sec = mapNameToDWARFSection(Name))
2083 return &Sec->Data;
2084 return StringSwitch<StringRef *>(Name)
2085 .Case("debug_abbrev", &AbbrevSection)
2086 .Case("debug_aranges", &ArangesSection)
2087 .Case("debug_str", &StrSection)
2088 .Case("debug_macinfo", &MacinfoSection)
2089 .Case("debug_macinfo.dwo", &MacinfoDWOSection)
2090 .Case("debug_macro.dwo", &MacroDWOSection)
2091 .Case("debug_abbrev.dwo", &AbbrevDWOSection)
2092 .Case("debug_str.dwo", &StrDWOSection)
2093 .Case("debug_cu_index", &CUIndexSection)
2094 .Case("debug_tu_index", &TUIndexSection)
2095 .Case("gdb_index", &GdbIndexSection)
2096 .Case("debug_line_str", &LineStrSection)
2097 // Any more debug info sections go here.
2098 .Default(nullptr);
2099 }
2100
2101 /// If Sec is compressed section, decompresses and updates its contents
2102 /// provided by Data. Otherwise leaves it unchanged.
2103 Error maybeDecompress(const object::SectionRef &Sec, StringRef Name,
2104 StringRef &Data) {
2105 if (!Sec.isCompressed())
2106 return Error::success();
2107
2108 Expected<Decompressor> Decompressor =
2109 Decompressor::create(Name, Data, IsLittleEndian, AddressSize == 8);
2110 if (!Decompressor)
2111 return Decompressor.takeError();
2112
2113 SmallString<0> Out;
2114 if (auto Err = Decompressor->resizeAndDecompress(Out))
2115 return Err;
2116
2117 UncompressedSections.push_back(std::move(Out));
2118 Data = UncompressedSections.back();
2119
2120 return Error::success();
2121 }
2122
2123public:
2124 DWARFObjInMemory(const StringMap<std::unique_ptr<MemoryBuffer>> &Sections,
2125 uint8_t AddrSize, bool IsLittleEndian)
2126 : IsLittleEndian(IsLittleEndian) {
2127 for (const auto &SecIt : Sections) {
2128 if (StringRef *SectionData = mapSectionToMember(SecIt.first()))
2129 *SectionData = SecIt.second->getBuffer();
2130 else if (SecIt.first() == "debug_info")
2131 // Find debug_info and debug_types data by section rather than name as
2132 // there are multiple, comdat grouped, of these sections.
2133 InfoSections[SectionRef()].Data = SecIt.second->getBuffer();
2134 else if (SecIt.first() == "debug_info.dwo")
2135 InfoDWOSections[SectionRef()].Data = SecIt.second->getBuffer();
2136 else if (SecIt.first() == "debug_types")
2137 TypesSections[SectionRef()].Data = SecIt.second->getBuffer();
2138 else if (SecIt.first() == "debug_types.dwo")
2139 TypesDWOSections[SectionRef()].Data = SecIt.second->getBuffer();
2140 }
2141 }
2142 DWARFObjInMemory(const object::ObjectFile &Obj, const LoadedObjectInfo *L,
2143 function_ref<void(Error)> HandleError,
2144 function_ref<void(Error)> HandleWarning,
2146 : IsLittleEndian(Obj.isLittleEndian()),
2147 AddressSize(Obj.getBytesInAddress()), FileName(Obj.getFileName()),
2148 Obj(&Obj) {
2149
2150 StringMap<unsigned> SectionAmountMap;
2151 for (const SectionRef &Section : Obj.sections()) {
2152 StringRef Name;
2153 if (auto NameOrErr = Section.getName())
2154 Name = *NameOrErr;
2155 else
2156 consumeError(NameOrErr.takeError());
2157
2158 ++SectionAmountMap[Name];
2159 SectionNames.push_back({ Name, true });
2160
2161 // Skip BSS and Virtual sections, they aren't interesting.
2162 if (Section.isBSS() || Section.isVirtual())
2163 continue;
2164
2165 // Skip sections stripped by dsymutil.
2166 if (Section.isStripped())
2167 continue;
2168
2169 StringRef Data;
2170 Expected<section_iterator> SecOrErr = Section.getRelocatedSection();
2171 if (!SecOrErr) {
2172 HandleError(createError("failed to get relocated section: ",
2173 SecOrErr.takeError()));
2174 continue;
2175 }
2176
2177 // Try to obtain an already relocated version of this section.
2178 // Else use the unrelocated section from the object file. We'll have to
2179 // apply relocations ourselves later.
2180 section_iterator RelocatedSection =
2181 Obj.isRelocatableObject() ? *SecOrErr : Obj.section_end();
2182 if (!L || !L->getLoadedSectionContents(*RelocatedSection, Data)) {
2183 Expected<StringRef> E = Section.getContents();
2184 if (E)
2185 Data = *E;
2186 else
2187 // maybeDecompress below will error.
2188 consumeError(E.takeError());
2189 }
2190
2191 if (auto Err = maybeDecompress(Section, Name, Data)) {
2192 HandleError(createError("failed to decompress '" + Name + "', ",
2193 std::move(Err)));
2194 continue;
2195 }
2196
2197 // Map platform specific debug section names to DWARF standard section
2198 // names.
2199 Name = Name.substr(Name.find_first_not_of("._"));
2200 Name = Obj.mapDebugSectionName(Name);
2201
2202 if (StringRef *SectionData = mapSectionToMember(Name)) {
2203 *SectionData = Data;
2204 if (Name == "debug_ranges") {
2205 // FIXME: Use the other dwo range section when we emit it.
2206 RangesDWOSection.Data = Data;
2207 } else if (Name == "debug_frame" || Name == "eh_frame") {
2208 if (DWARFSection *S = mapNameToDWARFSection(Name))
2209 S->Address = Section.getAddress();
2210 }
2211 } else if (InfoSectionMap *Sections =
2212 StringSwitch<InfoSectionMap *>(Name)
2213 .Case("debug_info", &InfoSections)
2214 .Case("debug_info.dwo", &InfoDWOSections)
2215 .Case("debug_types", &TypesSections)
2216 .Case("debug_types.dwo", &TypesDWOSections)
2217 .Default(nullptr)) {
2218 // Find debug_info and debug_types data by section rather than name as
2219 // there are multiple, comdat grouped, of these sections.
2220 DWARFSectionMap &S = (*Sections)[Section];
2221 S.Data = Data;
2222 }
2223
2224 if (RelocatedSection == Obj.section_end() ||
2225 (RelocAction == DWARFContext::ProcessDebugRelocations::Ignore))
2226 continue;
2227
2228 StringRef RelSecName;
2229 if (auto NameOrErr = RelocatedSection->getName())
2230 RelSecName = *NameOrErr;
2231 else
2232 consumeError(NameOrErr.takeError());
2233
2234 // If the section we're relocating was relocated already by the JIT,
2235 // then we used the relocated version above, so we do not need to process
2236 // relocations for it now.
2237 StringRef RelSecData;
2238 if (L && L->getLoadedSectionContents(*RelocatedSection, RelSecData))
2239 continue;
2240
2241 // In Mach-o files, the relocations do not need to be applied if
2242 // there is no load offset to apply. The value read at the
2243 // relocation point already factors in the section address
2244 // (actually applying the relocations will produce wrong results
2245 // as the section address will be added twice).
2246 if (!L && isa<MachOObjectFile>(&Obj))
2247 continue;
2248
2249 if (!Section.relocations().empty() && Name.ends_with(".dwo") &&
2250 RelSecName.starts_with(".debug")) {
2251 HandleWarning(createError("unexpected relocations for dwo section '" +
2252 RelSecName + "'"));
2253 }
2254
2255 // TODO: Add support for relocations in other sections as needed.
2256 // Record relocations for the debug_info and debug_line sections.
2257 RelSecName = RelSecName.substr(RelSecName.find_first_not_of("._"));
2258 DWARFSectionMap *Sec = mapNameToDWARFSection(RelSecName);
2259 RelocAddrMap *Map = Sec ? &Sec->Relocs : nullptr;
2260 if (!Map) {
2261 // Find debug_info and debug_types relocs by section rather than name
2262 // as there are multiple, comdat grouped, of these sections.
2263 if (RelSecName == "debug_info")
2264 Map = &static_cast<DWARFSectionMap &>(InfoSections[*RelocatedSection])
2265 .Relocs;
2266 else if (RelSecName == "debug_types")
2267 Map =
2268 &static_cast<DWARFSectionMap &>(TypesSections[*RelocatedSection])
2269 .Relocs;
2270 else
2271 continue;
2272 }
2273
2274 if (Section.relocations().empty())
2275 continue;
2276
2277 // Symbol to [address, section index] cache mapping.
2278 std::map<SymbolRef, SymInfo> AddrCache;
2279 SupportsRelocation Supports;
2280 RelocationResolver Resolver;
2281 std::tie(Supports, Resolver) = getRelocationResolver(Obj);
2282 for (const RelocationRef &Reloc : Section.relocations()) {
2283 // FIXME: it's not clear how to correctly handle scattered
2284 // relocations.
2285 if (isRelocScattered(Obj, Reloc))
2286 continue;
2287
2288 Expected<SymInfo> SymInfoOrErr =
2289 getSymbolInfo(Obj, Reloc, L, AddrCache);
2290 if (!SymInfoOrErr) {
2291 HandleError(SymInfoOrErr.takeError());
2292 continue;
2293 }
2294
2295 // Check if Resolver can handle this relocation type early so as not to
2296 // handle invalid cases in DWARFDataExtractor.
2297 //
2298 // TODO Don't store Resolver in every RelocAddrEntry.
2299 if (Supports && Supports(Reloc.getType())) {
2300 auto I = Map->try_emplace(
2301 Reloc.getOffset(),
2302 RelocAddrEntry{
2303 SymInfoOrErr->SectionIndex, Reloc, SymInfoOrErr->Address,
2304 std::optional<object::RelocationRef>(), 0, Resolver});
2305 // If we didn't successfully insert that's because we already had a
2306 // relocation for that offset. Store it as a second relocation in the
2307 // same RelocAddrEntry instead.
2308 if (!I.second) {
2309 RelocAddrEntry &entry = I.first->getSecond();
2310 if (entry.Reloc2) {
2311 HandleError(createError(
2312 "At most two relocations per offset are supported"));
2313 }
2314 entry.Reloc2 = Reloc;
2315 entry.SymbolValue2 = SymInfoOrErr->Address;
2316 }
2317 } else {
2319 Reloc.getTypeName(Type);
2320 // FIXME: Support more relocations & change this to an error
2321 HandleWarning(
2322 createError("failed to compute relocation: " + Type + ", ",
2323 errorCodeToError(object_error::parse_failed)));
2324 }
2325 }
2326 }
2327
2328 for (SectionName &S : SectionNames)
2329 if (SectionAmountMap[S.Name] > 1)
2330 S.IsNameUnique = false;
2331 }
2332
2333 std::optional<RelocAddrEntry> find(const DWARFSection &S,
2334 uint64_t Pos) const override {
2335 auto &Sec = static_cast<const DWARFSectionMap &>(S);
2336 RelocAddrMap::const_iterator AI = Sec.Relocs.find(Pos);
2337 if (AI == Sec.Relocs.end())
2338 return std::nullopt;
2339 return AI->second;
2340 }
2341
2342 const object::ObjectFile *getFile() const override { return Obj; }
2343
2344 ArrayRef<SectionName> getSectionNames() const override {
2345 return SectionNames;
2346 }
2347
2348 bool isLittleEndian() const override { return IsLittleEndian; }
2349 StringRef getAbbrevDWOSection() const override { return AbbrevDWOSection; }
2350 const DWARFSection &getLineDWOSection() const override {
2351 return LineDWOSection;
2352 }
2353 const DWARFSection &getLocDWOSection() const override {
2354 return LocDWOSection;
2355 }
2356 StringRef getStrDWOSection() const override { return StrDWOSection; }
2357 const DWARFSection &getStrOffsetsDWOSection() const override {
2358 return StrOffsetsDWOSection;
2359 }
2360 const DWARFSection &getRangesDWOSection() const override {
2361 return RangesDWOSection;
2362 }
2363 const DWARFSection &getRnglistsDWOSection() const override {
2364 return RnglistsDWOSection;
2365 }
2366 const DWARFSection &getLoclistsDWOSection() const override {
2367 return LoclistsDWOSection;
2368 }
2369 const DWARFSection &getAddrSection() const override { return AddrSection; }
2370 StringRef getCUIndexSection() const override { return CUIndexSection; }
2371 StringRef getGdbIndexSection() const override { return GdbIndexSection; }
2372 StringRef getTUIndexSection() const override { return TUIndexSection; }
2373
2374 // DWARF v5
2375 const DWARFSection &getStrOffsetsSection() const override {
2376 return StrOffsetsSection;
2377 }
2378 StringRef getLineStrSection() const override { return LineStrSection; }
2379
2380 // Sections for DWARF5 split dwarf proposal.
2381 void forEachInfoDWOSections(
2382 function_ref<void(const DWARFSection &)> F) const override {
2383 for (auto &P : InfoDWOSections)
2384 F(P.second);
2385 }
2386 void forEachTypesDWOSections(
2387 function_ref<void(const DWARFSection &)> F) const override {
2388 for (auto &P : TypesDWOSections)
2389 F(P.second);
2390 }
2391
2392 StringRef getAbbrevSection() const override { return AbbrevSection; }
2393 const DWARFSection &getLocSection() const override { return LocSection; }
2394 const DWARFSection &getLoclistsSection() const override { return LoclistsSection; }
2395 StringRef getArangesSection() const override { return ArangesSection; }
2396 const DWARFSection &getFrameSection() const override {
2397 return FrameSection;
2398 }
2399 const DWARFSection &getEHFrameSection() const override {
2400 return EHFrameSection;
2401 }
2402 const DWARFSection &getLineSection() const override { return LineSection; }
2403 StringRef getStrSection() const override { return StrSection; }
2404 const DWARFSection &getRangesSection() const override { return RangesSection; }
2405 const DWARFSection &getRnglistsSection() const override {
2406 return RnglistsSection;
2407 }
2408 const DWARFSection &getMacroSection() const override { return MacroSection; }
2409 StringRef getMacroDWOSection() const override { return MacroDWOSection; }
2410 StringRef getMacinfoSection() const override { return MacinfoSection; }
2411 StringRef getMacinfoDWOSection() const override { return MacinfoDWOSection; }
2412 const DWARFSection &getPubnamesSection() const override { return PubnamesSection; }
2413 const DWARFSection &getPubtypesSection() const override { return PubtypesSection; }
2414 const DWARFSection &getGnuPubnamesSection() const override {
2415 return GnuPubnamesSection;
2416 }
2417 const DWARFSection &getGnuPubtypesSection() const override {
2418 return GnuPubtypesSection;
2419 }
2420 const DWARFSection &getAppleNamesSection() const override {
2421 return AppleNamesSection;
2422 }
2423 const DWARFSection &getAppleTypesSection() const override {
2424 return AppleTypesSection;
2425 }
2426 const DWARFSection &getAppleNamespacesSection() const override {
2427 return AppleNamespacesSection;
2428 }
2429 const DWARFSection &getAppleObjCSection() const override {
2430 return AppleObjCSection;
2431 }
2432 const DWARFSection &getNamesSection() const override {
2433 return NamesSection;
2434 }
2435
2436 StringRef getFileName() const override { return FileName; }
2437 uint8_t getAddressSize() const override { return AddressSize; }
2438 void forEachInfoSections(
2439 function_ref<void(const DWARFSection &)> F) const override {
2440 for (auto &P : InfoSections)
2441 F(P.second);
2442 }
2443 void forEachTypesSections(
2444 function_ref<void(const DWARFSection &)> F) const override {
2445 for (auto &P : TypesSections)
2446 F(P.second);
2447 }
2448};
2449} // namespace
2450
2451std::unique_ptr<DWARFContext>
2453 ProcessDebugRelocations RelocAction,
2454 const LoadedObjectInfo *L, std::string DWPName,
2455 std::function<void(Error)> RecoverableErrorHandler,
2456 std::function<void(Error)> WarningHandler,
2457 bool ThreadSafe) {
2458 auto DObj = std::make_unique<DWARFObjInMemory>(
2459 Obj, L, RecoverableErrorHandler, WarningHandler, RelocAction);
2460 return std::make_unique<DWARFContext>(std::move(DObj),
2461 std::move(DWPName),
2462 RecoverableErrorHandler,
2463 WarningHandler,
2464 ThreadSafe);
2465}
2466
2467std::unique_ptr<DWARFContext>
2468DWARFContext::create(const StringMap<std::unique_ptr<MemoryBuffer>> &Sections,
2469 uint8_t AddrSize, bool isLittleEndian,
2470 std::function<void(Error)> RecoverableErrorHandler,
2471 std::function<void(Error)> WarningHandler,
2472 bool ThreadSafe) {
2473 auto DObj =
2474 std::make_unique<DWARFObjInMemory>(Sections, AddrSize, isLittleEndian);
2475 return std::make_unique<DWARFContext>(
2476 std::move(DObj), "", RecoverableErrorHandler, WarningHandler, ThreadSafe);
2477}
2478
2480 // In theory, different compile units may have different address byte
2481 // sizes, but for simplicity we just use the address byte size of the
2482 // first compile unit. In practice the address size field is repeated across
2483 // various DWARF headers (at least in version 5) to make it easier to dump
2484 // them independently, not to enable varying the address size.
2485 auto CUs = compile_units();
2486 return CUs.empty() ? 0 : (*CUs.begin())->getAddressByteSize();
2487}
2488
2489bool 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.
const DWARFObject & getDWARFObj() const
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:346
LLVM_ABI std::optional< DWARFFormValue > find(dwarf::Attribute Attr) const
Extract the specified attribute from this DIE.
Definition DWARFDie.cpp:290
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:497
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:542
LLVM_ABI std::string getDeclFile(DILineInfoSpecifier::FileLineInfoKind Kind) const
Definition DWARFDie.cpp:535
LLVM_ABI uint64_t getDeclLine() const
Returns the declaration line (start line) for a DIE, assuming it specifies a subprogram.
Definition DWARFDie.cpp:530
dwarf::Tag getTag() const
Definition DWARFDie.h:73
LLVM_ABI Expected< DWARFLocationExpressionsVector > getLocations(dwarf::Attribute Attr) const
Definition DWARFDie.cpp:467
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:635
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:182
LLVM_ABI DWARFUnit * getUnitForIndexEntry(const DWARFUnitIndex::Entry &E, DWARFSectionKind Sec, const DWARFSection *Section=nullptr)
Returns the Unit from the .debug_info or .debug_types section by the index entry.
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
DWARFContext & getContext() const
Definition DWARFUnit.h:327
DWARFDie getDIEForOffset(uint64_t Offset)
Return the DIE object for a given offset Offset inside the unit's DIE vector.
Definition DWARFUnit.h:541
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:573
constexpr size_t size() const
size - Get the string size.
Definition StringRef.h:146
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:385
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:1022
@ 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:35
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:93
@ DWARF32
Definition Dwarf.h:93
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:1097
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:1751
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
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:2136
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:2076
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:753
void sort(IteratorTy Start, IteratorTy End)
Definition STLExtras.h:1622
static Error createError(const Twine &Err)
Definition APFloat.cpp:387
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:547
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition Format.h:129
@ 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:1867
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:867
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.