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