xref: /src/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/Debugging/DebugInfoSupport.cpp (revision 647cbc5de815c5651677bf8582797f716ec7b48d)
1b1c73532SDimitry Andric //===--- DebugInfoSupport.cpp -- Utils for debug info support ---*- C++ -*-===//
2b1c73532SDimitry Andric //
3b1c73532SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4b1c73532SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5b1c73532SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6b1c73532SDimitry Andric //
7b1c73532SDimitry Andric //===----------------------------------------------------------------------===//
8b1c73532SDimitry Andric //
9b1c73532SDimitry Andric // Utilities to preserve and parse debug info from LinkGraphs.
10b1c73532SDimitry Andric //
11b1c73532SDimitry Andric //===----------------------------------------------------------------------===//
12b1c73532SDimitry Andric 
13b1c73532SDimitry Andric #include "llvm/ExecutionEngine/Orc/Debugging/DebugInfoSupport.h"
14b1c73532SDimitry Andric 
15b1c73532SDimitry Andric #include "llvm/Support/SmallVectorMemoryBuffer.h"
16b1c73532SDimitry Andric 
17b1c73532SDimitry Andric #define DEBUG_TYPE "orc"
18b1c73532SDimitry Andric 
19b1c73532SDimitry Andric using namespace llvm;
20b1c73532SDimitry Andric using namespace llvm::orc;
21b1c73532SDimitry Andric using namespace llvm::jitlink;
22b1c73532SDimitry Andric 
23b1c73532SDimitry Andric namespace {
24b1c73532SDimitry Andric static DenseSet<StringRef> DWARFSectionNames = {
25b1c73532SDimitry Andric #define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME, OPTION)        \
26b1c73532SDimitry Andric   StringRef(ELF_NAME),
27b1c73532SDimitry Andric #include "llvm/BinaryFormat/Dwarf.def"
28b1c73532SDimitry Andric #undef HANDLE_DWARF_SECTION
29b1c73532SDimitry Andric };
30b1c73532SDimitry Andric 
31b1c73532SDimitry Andric // We might be able to drop relocations to symbols that do end up
32b1c73532SDimitry Andric // being pruned by the linker, but for now we just preserve all
preserveDWARFSection(LinkGraph & G,Section & Sec)33b1c73532SDimitry Andric static void preserveDWARFSection(LinkGraph &G, Section &Sec) {
34b1c73532SDimitry Andric   DenseMap<Block *, Symbol *> Preserved;
35b1c73532SDimitry Andric   for (auto Sym : Sec.symbols()) {
36b1c73532SDimitry Andric     if (Sym->isLive())
37b1c73532SDimitry Andric       Preserved[&Sym->getBlock()] = Sym;
38b1c73532SDimitry Andric     else if (!Preserved.count(&Sym->getBlock()))
39b1c73532SDimitry Andric       Preserved[&Sym->getBlock()] = Sym;
40b1c73532SDimitry Andric   }
41b1c73532SDimitry Andric   for (auto Block : Sec.blocks()) {
42b1c73532SDimitry Andric     auto &PSym = Preserved[Block];
43b1c73532SDimitry Andric     if (!PSym)
44b1c73532SDimitry Andric       PSym = &G.addAnonymousSymbol(*Block, 0, 0, false, true);
45b1c73532SDimitry Andric     else if (!PSym->isLive())
46b1c73532SDimitry Andric       PSym->setLive(true);
47b1c73532SDimitry Andric   }
48b1c73532SDimitry Andric }
49b1c73532SDimitry Andric 
getSectionData(Section & Sec)50b1c73532SDimitry Andric static SmallVector<char, 0> getSectionData(Section &Sec) {
51b1c73532SDimitry Andric   SmallVector<char, 0> SecData;
52b1c73532SDimitry Andric   SmallVector<Block *, 8> SecBlocks(Sec.blocks().begin(), Sec.blocks().end());
53b1c73532SDimitry Andric   std::sort(SecBlocks.begin(), SecBlocks.end(), [](Block *LHS, Block *RHS) {
54b1c73532SDimitry Andric     return LHS->getAddress() < RHS->getAddress();
55b1c73532SDimitry Andric   });
56b1c73532SDimitry Andric   // Convert back to what object file would have, one blob of section content
57b1c73532SDimitry Andric   // Assumes all zerofill
58b1c73532SDimitry Andric   // TODO handle alignment?
59b1c73532SDimitry Andric   // TODO handle alignment offset?
60b1c73532SDimitry Andric   for (auto *Block : SecBlocks) {
61b1c73532SDimitry Andric     if (Block->isZeroFill())
62b1c73532SDimitry Andric       SecData.resize(SecData.size() + Block->getSize(), 0);
63b1c73532SDimitry Andric     else
64b1c73532SDimitry Andric       SecData.append(Block->getContent().begin(), Block->getContent().end());
65b1c73532SDimitry Andric   }
66b1c73532SDimitry Andric   return SecData;
67b1c73532SDimitry Andric }
68b1c73532SDimitry Andric 
dumpDWARFContext(DWARFContext & DC)69b1c73532SDimitry Andric static void dumpDWARFContext(DWARFContext &DC) {
70b1c73532SDimitry Andric   auto options = llvm::DIDumpOptions();
71b1c73532SDimitry Andric   options.DumpType &= ~DIDT_UUID;
72b1c73532SDimitry Andric   options.DumpType &= ~(1 << DIDT_ID_DebugFrame);
73b1c73532SDimitry Andric   LLVM_DEBUG(DC.dump(dbgs(), options));
74b1c73532SDimitry Andric }
75b1c73532SDimitry Andric 
76b1c73532SDimitry Andric } // namespace
77b1c73532SDimitry Andric 
preserveDebugSections(LinkGraph & G)78b1c73532SDimitry Andric Error llvm::orc::preserveDebugSections(LinkGraph &G) {
79b1c73532SDimitry Andric   if (!G.getTargetTriple().isOSBinFormatELF()) {
80b1c73532SDimitry Andric     return make_error<StringError>(
81b1c73532SDimitry Andric         "preserveDebugSections only supports ELF LinkGraphs!",
82b1c73532SDimitry Andric         inconvertibleErrorCode());
83b1c73532SDimitry Andric   }
84b1c73532SDimitry Andric   for (auto &Sec : G.sections()) {
85b1c73532SDimitry Andric     if (DWARFSectionNames.count(Sec.getName())) {
86b1c73532SDimitry Andric       LLVM_DEBUG(dbgs() << "Preserving DWARF section " << Sec.getName()
87b1c73532SDimitry Andric                         << "\n");
88b1c73532SDimitry Andric       preserveDWARFSection(G, Sec);
89b1c73532SDimitry Andric     }
90b1c73532SDimitry Andric   }
91b1c73532SDimitry Andric   return Error::success();
92b1c73532SDimitry Andric }
93b1c73532SDimitry Andric 
94b1c73532SDimitry Andric Expected<std::pair<std::unique_ptr<DWARFContext>,
95b1c73532SDimitry Andric                    StringMap<std::unique_ptr<MemoryBuffer>>>>
createDWARFContext(LinkGraph & G)96b1c73532SDimitry Andric llvm::orc::createDWARFContext(LinkGraph &G) {
97b1c73532SDimitry Andric   if (!G.getTargetTriple().isOSBinFormatELF()) {
98b1c73532SDimitry Andric     return make_error<StringError>(
99b1c73532SDimitry Andric         "createDWARFContext only supports ELF LinkGraphs!",
100b1c73532SDimitry Andric         inconvertibleErrorCode());
101b1c73532SDimitry Andric   }
102b1c73532SDimitry Andric   StringMap<std::unique_ptr<MemoryBuffer>> DWARFSectionData;
103b1c73532SDimitry Andric   for (auto &Sec : G.sections()) {
104b1c73532SDimitry Andric     if (DWARFSectionNames.count(Sec.getName())) {
105b1c73532SDimitry Andric       auto SecData = getSectionData(Sec);
106b1c73532SDimitry Andric       auto Name = Sec.getName();
107b1c73532SDimitry Andric       // DWARFContext expects the section name to not start with a dot
10877dbea07SDimitry Andric       Name.consume_front(".");
109b1c73532SDimitry Andric       LLVM_DEBUG(dbgs() << "Creating DWARFContext section " << Name
110b1c73532SDimitry Andric                         << " with size " << SecData.size() << "\n");
111b1c73532SDimitry Andric       DWARFSectionData[Name] =
112b1c73532SDimitry Andric           std::make_unique<SmallVectorMemoryBuffer>(std::move(SecData));
113b1c73532SDimitry Andric     }
114b1c73532SDimitry Andric   }
115b1c73532SDimitry Andric   auto Ctx =
116b1c73532SDimitry Andric       DWARFContext::create(DWARFSectionData, G.getPointerSize(),
117b1c73532SDimitry Andric                            G.getEndianness() == llvm::endianness::little);
118b1c73532SDimitry Andric   dumpDWARFContext(*Ctx);
119b1c73532SDimitry Andric   return std::make_pair(std::move(Ctx), std::move(DWARFSectionData));
120b1c73532SDimitry Andric }
121