LLVM 20.0.0git
DebugInfoSupport.cpp
Go to the documentation of this file.
1//===--- DebugInfoSupport.cpp -- Utils for debug info support ---*- C++ -*-===//
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//
9// Utilities to preserve and parse debug info from LinkGraphs.
10//
11//===----------------------------------------------------------------------===//
12
14
16
17#define DEBUG_TYPE "orc"
18
19using namespace llvm;
20using namespace llvm::orc;
21using namespace llvm::jitlink;
22
23namespace {
24static DenseSet<StringRef> DWARFSectionNames = {
25#define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME, OPTION) \
26 StringRef(ELF_NAME),
27#include "llvm/BinaryFormat/Dwarf.def"
28#undef HANDLE_DWARF_SECTION
29};
30
31// We might be able to drop relocations to symbols that do end up
32// being pruned by the linker, but for now we just preserve all
33static void preserveDWARFSection(LinkGraph &G, Section &Sec) {
35 for (auto Sym : Sec.symbols()) {
36 if (Sym->isLive())
37 Preserved[&Sym->getBlock()] = Sym;
38 else if (!Preserved.count(&Sym->getBlock()))
39 Preserved[&Sym->getBlock()] = Sym;
40 }
41 for (auto Block : Sec.blocks()) {
42 auto &PSym = Preserved[Block];
43 if (!PSym)
44 PSym = &G.addAnonymousSymbol(*Block, 0, 0, false, true);
45 else if (!PSym->isLive())
46 PSym->setLive(true);
47 }
48}
49
50static SmallVector<char, 0> getSectionData(Section &Sec) {
52 SmallVector<Block *, 8> SecBlocks(Sec.blocks().begin(), Sec.blocks().end());
53 std::sort(SecBlocks.begin(), SecBlocks.end(), [](Block *LHS, Block *RHS) {
54 return LHS->getAddress() < RHS->getAddress();
55 });
56 // Convert back to what object file would have, one blob of section content
57 // Assumes all zerofill
58 // TODO handle alignment?
59 // TODO handle alignment offset?
60 for (auto *Block : SecBlocks) {
61 if (Block->isZeroFill())
62 SecData.resize(SecData.size() + Block->getSize(), 0);
63 else
64 SecData.append(Block->getContent().begin(), Block->getContent().end());
65 }
66 return SecData;
67}
68
69static void dumpDWARFContext(DWARFContext &DC) {
70 auto options = llvm::DIDumpOptions();
71 options.DumpType &= ~DIDT_UUID;
72 options.DumpType &= ~(1 << DIDT_ID_DebugFrame);
73 LLVM_DEBUG(DC.dump(dbgs(), options));
74}
75
76} // namespace
77
79 if (!G.getTargetTriple().isOSBinFormatELF()) {
80 return make_error<StringError>(
81 "preserveDebugSections only supports ELF LinkGraphs!",
83 }
84 for (auto &Sec : G.sections()) {
85 if (DWARFSectionNames.count(Sec.getName())) {
86 LLVM_DEBUG(dbgs() << "Preserving DWARF section " << Sec.getName()
87 << "\n");
88 preserveDWARFSection(G, Sec);
89 }
90 }
91 return Error::success();
92}
93
97 if (!G.getTargetTriple().isOSBinFormatELF()) {
98 return make_error<StringError>(
99 "createDWARFContext only supports ELF LinkGraphs!",
101 }
103 for (auto &Sec : G.sections()) {
104 if (DWARFSectionNames.count(Sec.getName())) {
105 auto SecData = getSectionData(Sec);
106 auto Name = Sec.getName();
107 // DWARFContext expects the section name to not start with a dot
108 Name.consume_front(".");
109 LLVM_DEBUG(dbgs() << "Creating DWARFContext section " << Name
110 << " with size " << SecData.size() << "\n");
111 DWARFSectionData[Name] =
112 std::make_unique<SmallVectorMemoryBuffer>(std::move(SecData));
113 }
114 }
115 auto Ctx =
116 DWARFContext::create(DWARFSectionData, G.getPointerSize(),
117 G.getEndianness() == llvm::endianness::little);
118 dumpDWARFContext(*Ctx);
119 return std::make_pair(std::move(Ctx), std::move(DWARFSectionData));
120}
#define LLVM_DEBUG(X)
Definition: Debug.h:101
std::string Name
Symbol * Sym
Definition: ELF_riscv.cpp:479
#define G(x, y, z)
Definition: MD5.cpp:56
Value * RHS
Value * LHS
iterator end() const
Definition: ArrayRef.h:154
iterator begin() const
Definition: ArrayRef.h:153
DWARFContext This data structure is the top level entity that deals with dwarf debug information pars...
Definition: DWARFContext.h:48
void dump(raw_ostream &OS, DIDumpOptions DumpOpts, std::array< std::optional< uint64_t >, DIDT_ID_Count > DumpOffsets)
Dump a textual representation to OS.
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)
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
Definition: DenseMap.h:151
Implements a dense probed hash-table based set.
Definition: DenseSet.h:271
Lightweight error class with error context and mandatory checking.
Definition: Error.h:160
static ErrorSuccess success()
Create a success value.
Definition: Error.h:337
Tagged union holding either a T or a Error.
Definition: Error.h:481
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1209
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
Definition: StringMap.h:128
Error preserveDebugSections(jitlink::LinkGraph &G)
Expected< std::pair< std::unique_ptr< DWARFContext >, StringMap< std::unique_ptr< MemoryBuffer > > > > createDWARFContext(jitlink::LinkGraph &G)
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
Definition: Error.cpp:98
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
Container for dump options that control which debug information will be dumped.
Definition: DIContext.h:196