xref: /freebsd/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/Debugging/DebugInfoSupport.cpp (revision 770cf0a5f02dc8983a89c6568d741fbc25baa999)
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 
13 #include "llvm/ExecutionEngine/Orc/Debugging/DebugInfoSupport.h"
14 
15 #include "llvm/Support/SmallVectorMemoryBuffer.h"
16 
17 #define DEBUG_TYPE "orc"
18 
19 using namespace llvm;
20 using namespace llvm::orc;
21 using namespace llvm::jitlink;
22 
23 namespace {
24 static 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
33 static void preserveDWARFSection(LinkGraph &G, Section &Sec) {
34   DenseMap<Block *, Symbol *> Preserved;
35   for (auto Sym : Sec.symbols()) {
36     auto [It, Inserted] = Preserved.try_emplace(&Sym->getBlock());
37     if (Inserted || Sym->isLive())
38       It->second = Sym;
39   }
40   for (auto Block : Sec.blocks()) {
41     auto &PSym = Preserved[Block];
42     if (!PSym)
43       PSym = &G.addAnonymousSymbol(*Block, 0, 0, false, true);
44     else if (!PSym->isLive())
45       PSym->setLive(true);
46   }
47 }
48 
49 static SmallVector<char, 0> getSectionData(Section &Sec) {
50   SmallVector<char, 0> SecData;
51   SmallVector<Block *, 8> SecBlocks(Sec.blocks().begin(), Sec.blocks().end());
52   std::sort(SecBlocks.begin(), SecBlocks.end(), [](Block *LHS, Block *RHS) {
53     return LHS->getAddress() < RHS->getAddress();
54   });
55   // Convert back to what object file would have, one blob of section content
56   // Assumes all zerofill
57   // TODO handle alignment?
58   // TODO handle alignment offset?
59   for (auto *Block : SecBlocks) {
60     if (Block->isZeroFill())
61       SecData.resize(SecData.size() + Block->getSize(), 0);
62     else
63       SecData.append(Block->getContent().begin(), Block->getContent().end());
64   }
65   return SecData;
66 }
67 
68 static void dumpDWARFContext(DWARFContext &DC) {
69   auto options = llvm::DIDumpOptions();
70   options.DumpType &= ~DIDT_UUID;
71   options.DumpType &= ~(1 << DIDT_ID_DebugFrame);
72   LLVM_DEBUG(DC.dump(dbgs(), options));
73 }
74 
75 } // namespace
76 
77 Error llvm::orc::preserveDebugSections(LinkGraph &G) {
78   if (!G.getTargetTriple().isOSBinFormatELF()) {
79     return make_error<StringError>(
80         "preserveDebugSections only supports ELF LinkGraphs!",
81         inconvertibleErrorCode());
82   }
83   for (auto &Sec : G.sections()) {
84     if (DWARFSectionNames.count(Sec.getName())) {
85       LLVM_DEBUG(dbgs() << "Preserving DWARF section " << Sec.getName()
86                         << "\n");
87       preserveDWARFSection(G, Sec);
88     }
89   }
90   return Error::success();
91 }
92 
93 Expected<std::pair<std::unique_ptr<DWARFContext>,
94                    StringMap<std::unique_ptr<MemoryBuffer>>>>
95 llvm::orc::createDWARFContext(LinkGraph &G) {
96   if (!G.getTargetTriple().isOSBinFormatELF()) {
97     return make_error<StringError>(
98         "createDWARFContext only supports ELF LinkGraphs!",
99         inconvertibleErrorCode());
100   }
101   StringMap<std::unique_ptr<MemoryBuffer>> DWARFSectionData;
102   for (auto &Sec : G.sections()) {
103     if (DWARFSectionNames.count(Sec.getName())) {
104       auto SecData = getSectionData(Sec);
105       auto Name = Sec.getName();
106       // DWARFContext expects the section name to not start with a dot
107       Name.consume_front(".");
108       LLVM_DEBUG(dbgs() << "Creating DWARFContext section " << Name
109                         << " with size " << SecData.size() << "\n");
110       DWARFSectionData[Name] =
111           std::make_unique<SmallVectorMemoryBuffer>(std::move(SecData));
112     }
113   }
114   auto Ctx =
115       DWARFContext::create(DWARFSectionData, G.getPointerSize(),
116                            G.getEndianness() == llvm::endianness::little);
117   dumpDWARFContext(*Ctx);
118   return std::make_pair(std::move(Ctx), std::move(DWARFSectionData));
119 }
120