blob: 31d8440b09980c7c8599af10772e0e4eacd6b1f1 [file] [log] [blame]
Rui Ueyama0ca149f2013-08-06 22:31:59 +00001//===- lib/ReaderWriter/CoreLinkingContext.cpp ----------------------------===//
2//
3// The LLVM Linker
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "lld/ReaderWriter/CoreLinkingContext.h"
11
12#include "lld/Core/Pass.h"
13#include "lld/Core/PassManager.h"
14#include "lld/Passes/LayoutPass.h"
Shankar Easwaran2bc24922013-10-29 05:12:14 +000015#include "lld/Passes/RoundTripYAMLPass.h"
16#include "lld/ReaderWriter/Simple.h"
Rui Ueyama0ca149f2013-08-06 22:31:59 +000017
18#include "llvm/ADT/ArrayRef.h"
19
20using namespace lld;
21
22namespace {
23
24/// \brief Simple atom created by the stubs pass.
25class TestingStubAtom : public DefinedAtom {
26public:
27 TestingStubAtom(const File &F, const Atom &) : _file(F) {
28 static uint32_t lastOrdinal = 0;
29 _ordinal = lastOrdinal++;
30 }
31
32 virtual const File &file() const { return _file; }
33
34 virtual StringRef name() const { return StringRef(); }
35
36 virtual uint64_t ordinal() const { return _ordinal; }
37
38 virtual uint64_t size() const { return 0; }
39
40 virtual Scope scope() const { return DefinedAtom::scopeLinkageUnit; }
41
42 virtual Interposable interposable() const { return DefinedAtom::interposeNo; }
43
44 virtual Merge merge() const { return DefinedAtom::mergeNo; }
45
46 virtual ContentType contentType() const { return DefinedAtom::typeStub; }
47
48 virtual Alignment alignment() const { return Alignment(0, 0); }
49
50 virtual SectionChoice sectionChoice() const {
51 return DefinedAtom::sectionBasedOnContent;
52 }
53
54 virtual StringRef customSectionName() const { return StringRef(); }
55
56 virtual SectionPosition sectionPosition() const { return sectionPositionAny; }
57
58 virtual DeadStripKind deadStrip() const {
59 return DefinedAtom::deadStripNormal;
60 }
61
62 virtual ContentPermissions permissions() const {
63 return DefinedAtom::permR_X;
64 }
65
66 virtual bool isAlias() const { return false; }
67
68 virtual ArrayRef<uint8_t> rawContent() const { return ArrayRef<uint8_t>(); }
69
70 virtual reference_iterator begin() const {
71 return reference_iterator(*this, nullptr);
72 }
73
74 virtual reference_iterator end() const {
75 return reference_iterator(*this, nullptr);
76 }
77
78 virtual const Reference *derefIterator(const void *iter) const {
79 return nullptr;
80 }
81
82 virtual void incrementIterator(const void *&iter) const {}
83
84private:
85 const File &_file;
86 uint32_t _ordinal;
87};
88
89/// \brief Simple atom created by the GOT pass.
90class TestingGOTAtom : public DefinedAtom {
91public:
92 TestingGOTAtom(const File &F, const Atom &) : _file(F) {
93 static uint32_t lastOrdinal = 0;
94 _ordinal = lastOrdinal++;
95 }
96
97 virtual const File &file() const { return _file; }
98
99 virtual StringRef name() const { return StringRef(); }
100
101 virtual uint64_t ordinal() const { return _ordinal; }
102
103 virtual uint64_t size() const { return 0; }
104
105 virtual Scope scope() const { return DefinedAtom::scopeLinkageUnit; }
106
107 virtual Interposable interposable() const { return DefinedAtom::interposeNo; }
108
109 virtual Merge merge() const { return DefinedAtom::mergeNo; }
110
111 virtual ContentType contentType() const { return DefinedAtom::typeGOT; }
112
113 virtual Alignment alignment() const { return Alignment(3, 0); }
114
115 virtual SectionChoice sectionChoice() const {
116 return DefinedAtom::sectionBasedOnContent;
117 }
118
119 virtual StringRef customSectionName() const { return StringRef(); }
120
121 virtual SectionPosition sectionPosition() const { return sectionPositionAny; }
122
123 virtual DeadStripKind deadStrip() const {
124 return DefinedAtom::deadStripNormal;
125 }
126
127 virtual ContentPermissions permissions() const {
128 return DefinedAtom::permRW_;
129 }
130
131 virtual bool isAlias() const { return false; }
132
133 virtual ArrayRef<uint8_t> rawContent() const { return ArrayRef<uint8_t>(); }
134
135 virtual reference_iterator begin() const {
136 return reference_iterator(*this, nullptr);
137 }
138
139 virtual reference_iterator end() const {
140 return reference_iterator(*this, nullptr);
141 }
142
143 virtual const Reference *derefIterator(const void *iter) const {
144 return nullptr;
145 }
146
147 virtual void incrementIterator(const void *&iter) const {}
148
149private:
150 const File &_file;
151 uint32_t _ordinal;
152};
153
Shankar Easwaran2bc24922013-10-29 05:12:14 +0000154class TestingPassFile : public SimpleFile {
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000155public:
Rui Ueyama170a1a82013-12-20 07:48:29 +0000156 TestingPassFile(const LinkingContext &ctx) : SimpleFile("Testing pass") {}
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000157
158 virtual void addAtom(const Atom &atom) {
159 if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(&atom))
160 _definedAtoms._atoms.push_back(defAtom);
161 else
162 llvm_unreachable("atom has unknown definition kind");
163 }
164
165 virtual DefinedAtomRange definedAtoms() {
166 return range<std::vector<const DefinedAtom *>::iterator>(
167 _definedAtoms._atoms.begin(), _definedAtoms._atoms.end());
168 }
169
170 virtual const atom_collection<DefinedAtom> &defined() const {
171 return _definedAtoms;
172 }
173 virtual const atom_collection<UndefinedAtom> &undefined() const {
174 return _undefinedAtoms;
175 }
176 virtual const atom_collection<SharedLibraryAtom> &sharedLibrary() const {
177 return _sharedLibraryAtoms;
178 }
179 virtual const atom_collection<AbsoluteAtom> &absolute() const {
180 return _absoluteAtoms;
181 }
182
183private:
184 atom_collection_vector<DefinedAtom> _definedAtoms;
185 atom_collection_vector<UndefinedAtom> _undefinedAtoms;
186 atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms;
187 atom_collection_vector<AbsoluteAtom> _absoluteAtoms;
188};
189
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000190
191class TestingStubsPass : public StubsPass {
192public:
Rui Ueyama352e7302013-08-27 00:04:42 +0000193 TestingStubsPass(const LinkingContext &ctx) : _file(TestingPassFile(ctx)) {}
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000194
195 virtual bool noTextRelocs() { return true; }
196
Nick Kledzike5552772013-12-19 21:58:00 +0000197 virtual bool isCallSite(const Reference &ref) {
198 if (ref.kindNamespace() != Reference::KindNamespace::testing)
199 return false;
200 return (ref.kindValue() == CoreLinkingContext::TEST_RELOC_CALL32);
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000201 }
202
203 virtual const DefinedAtom *getStub(const Atom &target) {
204 const DefinedAtom *result = new TestingStubAtom(_file, target);
205 _file.addAtom(*result);
206 return result;
207 }
208
209 virtual void addStubAtoms(MutableFile &mergedFile) {
210 for (const DefinedAtom *stub : _file.defined()) {
211 mergedFile.addAtom(*stub);
212 }
213 }
214
215private:
216 TestingPassFile _file;
217};
218
219class TestingGOTPass : public GOTPass {
220public:
Rui Ueyama352e7302013-08-27 00:04:42 +0000221 TestingGOTPass(const LinkingContext &ctx) : _file(TestingPassFile(ctx)) {}
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000222
223 virtual bool noTextRelocs() { return true; }
224
Nick Kledzike5552772013-12-19 21:58:00 +0000225 virtual bool isGOTAccess(const Reference &ref, bool &canBypassGOT) {
226 if (ref.kindNamespace() != Reference::KindNamespace::testing)
227 return false;
228 switch (ref.kindValue()) {
229 case CoreLinkingContext::TEST_RELOC_GOT_LOAD32:
230 canBypassGOT = true;
231 return true;
232 case CoreLinkingContext::TEST_RELOC_GOT_USE32:
233 canBypassGOT = false;
234 return true;
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000235 }
236 return false;
237 }
238
239 virtual void updateReferenceToGOT(const Reference *ref, bool targetIsNowGOT) {
Rui Ueyama170a1a82013-12-20 07:48:29 +0000240 const_cast<Reference *>(ref)->setKindValue(
241 targetIsNowGOT ? CoreLinkingContext::TEST_RELOC_PCREL32
242 : CoreLinkingContext::TEST_RELOC_LEA32_WAS_GOT);
243 }
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000244
245 virtual const DefinedAtom *makeGOTEntry(const Atom &target) {
246 return new TestingGOTAtom(_file, target);
247 }
248
249private:
250 TestingPassFile _file;
251};
252
253} // anonymous namespace
254
255CoreLinkingContext::CoreLinkingContext() {}
256
Shankar Easwaran7f1146c2013-10-08 15:43:48 +0000257bool CoreLinkingContext::validateImpl(raw_ostream &) {
Shankar Easwaran7f1146c2013-10-08 15:43:48 +0000258 _writer = createWriterYAML(*this);
Rui Ueyama8db1edd2013-09-24 23:26:34 +0000259 return true;
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000260}
261
Shankar Easwaran2bc24922013-10-29 05:12:14 +0000262void CoreLinkingContext::addPasses(PassManager &pm) {
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000263 for (StringRef name : _passNames) {
264 if (name.equals("layout"))
Nico Rieckb9d84f42014-02-24 21:14:37 +0000265 pm.add(std::unique_ptr<Pass>(new LayoutPass(registry())));
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000266 else if (name.equals("GOT"))
267 pm.add(std::unique_ptr<Pass>(new TestingGOTPass(*this)));
268 else if (name.equals("stubs"))
269 pm.add(std::unique_ptr<Pass>(new TestingStubsPass(*this)));
270 else
271 llvm_unreachable("bad pass name");
272 }
273}
274
Shankar Easwaran7f1146c2013-10-08 15:43:48 +0000275Writer &CoreLinkingContext::writer() const { return *_writer; }
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000276