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