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