blob: 0d4fb9934453021474f00ca20d3ee0afd123967d [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 Ueyama352e7302013-08-27 00:04:42 +0000156 TestingPassFile(const LinkingContext &ctx)
Nick Kledzike5552772013-12-19 21:58:00 +0000157 : SimpleFile("Testing pass") {}
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000158
159 virtual void addAtom(const Atom &atom) {
160 if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(&atom))
161 _definedAtoms._atoms.push_back(defAtom);
162 else
163 llvm_unreachable("atom has unknown definition kind");
164 }
165
166 virtual DefinedAtomRange definedAtoms() {
167 return range<std::vector<const DefinedAtom *>::iterator>(
168 _definedAtoms._atoms.begin(), _definedAtoms._atoms.end());
169 }
170
171 virtual const atom_collection<DefinedAtom> &defined() const {
172 return _definedAtoms;
173 }
174 virtual const atom_collection<UndefinedAtom> &undefined() const {
175 return _undefinedAtoms;
176 }
177 virtual const atom_collection<SharedLibraryAtom> &sharedLibrary() const {
178 return _sharedLibraryAtoms;
179 }
180 virtual const atom_collection<AbsoluteAtom> &absolute() const {
181 return _absoluteAtoms;
182 }
183
184private:
185 atom_collection_vector<DefinedAtom> _definedAtoms;
186 atom_collection_vector<UndefinedAtom> _undefinedAtoms;
187 atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms;
188 atom_collection_vector<AbsoluteAtom> _absoluteAtoms;
189};
190
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000191
192class TestingStubsPass : public StubsPass {
193public:
Rui Ueyama352e7302013-08-27 00:04:42 +0000194 TestingStubsPass(const LinkingContext &ctx) : _file(TestingPassFile(ctx)) {}
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000195
196 virtual bool noTextRelocs() { return true; }
197
Nick Kledzike5552772013-12-19 21:58:00 +0000198 virtual bool isCallSite(const Reference &ref) {
199 if (ref.kindNamespace() != Reference::KindNamespace::testing)
200 return false;
201 return (ref.kindValue() == CoreLinkingContext::TEST_RELOC_CALL32);
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000202 }
203
204 virtual const DefinedAtom *getStub(const Atom &target) {
205 const DefinedAtom *result = new TestingStubAtom(_file, target);
206 _file.addAtom(*result);
207 return result;
208 }
209
210 virtual void addStubAtoms(MutableFile &mergedFile) {
211 for (const DefinedAtom *stub : _file.defined()) {
212 mergedFile.addAtom(*stub);
213 }
214 }
215
216private:
217 TestingPassFile _file;
218};
219
220class TestingGOTPass : public GOTPass {
221public:
Rui Ueyama352e7302013-08-27 00:04:42 +0000222 TestingGOTPass(const LinkingContext &ctx) : _file(TestingPassFile(ctx)) {}
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000223
224 virtual bool noTextRelocs() { return true; }
225
Nick Kledzike5552772013-12-19 21:58:00 +0000226 virtual bool isGOTAccess(const Reference &ref, bool &canBypassGOT) {
227 if (ref.kindNamespace() != Reference::KindNamespace::testing)
228 return false;
229 switch (ref.kindValue()) {
230 case CoreLinkingContext::TEST_RELOC_GOT_LOAD32:
231 canBypassGOT = true;
232 return true;
233 case CoreLinkingContext::TEST_RELOC_GOT_USE32:
234 canBypassGOT = false;
235 return true;
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000236 }
237 return false;
238 }
239
240 virtual void updateReferenceToGOT(const Reference *ref, bool targetIsNowGOT) {
Nick Kledzike5552772013-12-19 21:58:00 +0000241 const_cast<Reference *>(ref)->setKindValue(targetIsNowGOT ?
242 CoreLinkingContext::TEST_RELOC_PCREL32 :
243 CoreLinkingContext::TEST_RELOC_LEA32_WAS_GOT);
244 }
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000245
246 virtual const DefinedAtom *makeGOTEntry(const Atom &target) {
247 return new TestingGOTAtom(_file, target);
248 }
249
250private:
251 TestingPassFile _file;
252};
253
254} // anonymous namespace
255
256CoreLinkingContext::CoreLinkingContext() {}
257
Shankar Easwaran7f1146c2013-10-08 15:43:48 +0000258bool CoreLinkingContext::validateImpl(raw_ostream &) {
Shankar Easwaran7f1146c2013-10-08 15:43:48 +0000259 _writer = createWriterYAML(*this);
Rui Ueyama8db1edd2013-09-24 23:26:34 +0000260 return true;
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000261}
262
Shankar Easwaran2bc24922013-10-29 05:12:14 +0000263void CoreLinkingContext::addPasses(PassManager &pm) {
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000264 for (StringRef name : _passNames) {
265 if (name.equals("layout"))
266 pm.add(std::unique_ptr<Pass>((new LayoutPass())));
267 else if (name.equals("GOT"))
268 pm.add(std::unique_ptr<Pass>(new TestingGOTPass(*this)));
269 else if (name.equals("stubs"))
270 pm.add(std::unique_ptr<Pass>(new TestingStubsPass(*this)));
271 else
272 llvm_unreachable("bad pass name");
273 }
274}
275
Shankar Easwaran7f1146c2013-10-08 15:43:48 +0000276Writer &CoreLinkingContext::writer() const { return *_writer; }
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000277