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