blob: 28a462815e1c4c9caa2f1e1059d07a7a75458a1e (
plain)
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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
|
//===- lib/ReaderWriter/ELF/ExecutableWriter.h ----------------------------===//
//
// The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLD_READER_WRITER_ELF_EXECUTABLE_WRITER_H
#define LLD_READER_WRITER_ELF_EXECUTABLE_WRITER_H
#include "OutputELFWriter.h"
namespace lld {
namespace elf {
using namespace llvm;
using namespace llvm::object;
template<class ELFT>
class ExecutableWriter;
//===----------------------------------------------------------------------===//
// ExecutableWriter Class
//===----------------------------------------------------------------------===//
template<class ELFT>
class ExecutableWriter : public OutputELFWriter<ELFT> {
public:
ExecutableWriter(const ELFLinkingContext &context)
: OutputELFWriter<ELFT>(context), _runtimeFile(context) {}
private:
virtual void addDefaultAtoms();
virtual void addFiles(InputFiles &);
virtual void finalizeDefaultAtomValues();
virtual void createDefaultSections();
LLD_UNIQUE_BUMP_PTR(InterpSection<ELFT>) _interpSection;
CRuntimeFile<ELFT> _runtimeFile;
};
//===----------------------------------------------------------------------===//
// ExecutableWriter
//===----------------------------------------------------------------------===//
/// \brief Add absolute symbols by default. These are linker added
/// absolute symbols
template<class ELFT>
void ExecutableWriter<ELFT>::addDefaultAtoms() {
_runtimeFile.addUndefinedAtom(this->_context.entrySymbolName());
_runtimeFile.addAbsoluteAtom("__bss_start");
_runtimeFile.addAbsoluteAtom("__bss_end");
_runtimeFile.addAbsoluteAtom("_end");
_runtimeFile.addAbsoluteAtom("end");
_runtimeFile.addAbsoluteAtom("__preinit_array_start");
_runtimeFile.addAbsoluteAtom("__preinit_array_end");
_runtimeFile.addAbsoluteAtom("__init_array_start");
_runtimeFile.addAbsoluteAtom("__init_array_end");
_runtimeFile.addAbsoluteAtom("__rela_iplt_start");
_runtimeFile.addAbsoluteAtom("__rela_iplt_end");
_runtimeFile.addAbsoluteAtom("__fini_array_start");
_runtimeFile.addAbsoluteAtom("__fini_array_end");
}
/// \brief Hook in lld to add CRuntime file
template <class ELFT>
void ExecutableWriter<ELFT>::addFiles(InputFiles &inputFiles) {
// Add the default atoms as defined by executables
addDefaultAtoms();
// Add the runtime file
inputFiles.prependFile(_runtimeFile);
// Add the Linker internal file for symbols that are defined by
// command line options
OutputELFWriter<ELFT>::addFiles(inputFiles);
}
template <class ELFT> void ExecutableWriter<ELFT>::createDefaultSections() {
OutputELFWriter<ELFT>::createDefaultSections();
if (this->_context.isDynamic()) {
_interpSection.reset(new (this->_alloc) InterpSection<ELFT>(
this->_context, ".interp", DefaultLayout<ELFT>::ORDER_INTERP,
this->_context.getInterpreter()));
this->_layout->addSection(_interpSection.get());
}
}
/// Finalize the value of all the absolute symbols that we
/// created
template <class ELFT> void ExecutableWriter<ELFT>::finalizeDefaultAtomValues() {
auto bssStartAtomIter = this->_layout->findAbsoluteAtom("__bss_start");
auto bssEndAtomIter = this->_layout->findAbsoluteAtom("__bss_end");
auto underScoreEndAtomIter = this->_layout->findAbsoluteAtom("_end");
auto endAtomIter = this->_layout->findAbsoluteAtom("end");
auto startEnd = [&](StringRef sym, StringRef sec) -> void {
// TODO: This looks like a good place to use Twine...
std::string start("__"), end("__");
start += sym;
start += "_start";
end += sym;
end += "_end";
auto s = this->_layout->findAbsoluteAtom(start);
auto e = this->_layout->findAbsoluteAtom(end);
auto section = this->_layout->findOutputSection(sec);
if (section) {
(*s)->_virtualAddr = section->virtualAddr();
(*e)->_virtualAddr = section->virtualAddr() + section->memSize();
} else {
(*s)->_virtualAddr = 0;
(*e)->_virtualAddr = 0;
}
};
startEnd("preinit_array", ".preinit_array");
startEnd("init_array", ".init_array");
startEnd("rela_iplt", ".rela.plt");
startEnd("fini_array", ".fini_array");
assert(!(bssStartAtomIter == this->_layout->absoluteAtoms().end() ||
bssEndAtomIter == this->_layout->absoluteAtoms().end() ||
underScoreEndAtomIter == this->_layout->absoluteAtoms().end() ||
endAtomIter == this->_layout->absoluteAtoms().end()) &&
"Unable to find the absolute atoms that have been added by lld");
auto bssSection = this->_layout->findOutputSection(".bss");
// If we dont find a bss section, then dont set these values
if (bssSection) {
(*bssStartAtomIter)->_virtualAddr = bssSection->virtualAddr();
(*bssEndAtomIter)->_virtualAddr =
bssSection->virtualAddr() + bssSection->memSize();
(*underScoreEndAtomIter)->_virtualAddr = (*bssEndAtomIter)->_virtualAddr;
(*endAtomIter)->_virtualAddr = (*bssEndAtomIter)->_virtualAddr;
}
// Give a chance for the target to finalize its atom values
this->_targetHandler.finalizeSymbolValues();
}
} // namespace elf
} // namespace lld
#endif // LLD_READER_WRITER_ELF_EXECUTABLE_WRITER_H
|