blob: 0adaa017672b6215c220dbcdf79c2cd7837971d3 [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"
Rui Ueyamae05d3802014-06-11 21:47:51 +000014#include "lld/Core/Simple.h"
Rui Ueyama0ca149f2013-08-06 22:31:59 +000015#include "lld/Passes/LayoutPass.h"
Shankar Easwaran2bc24922013-10-29 05:12:14 +000016#include "lld/Passes/RoundTripYAMLPass.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
Rui Ueyama16e543b2014-03-06 21:14:04 +000032 const File &file() const override { return _file; }
Rui Ueyama0ca149f2013-08-06 22:31:59 +000033
Rui Ueyama16e543b2014-03-06 21:14:04 +000034 StringRef name() const override { return StringRef(); }
Rui Ueyama0ca149f2013-08-06 22:31:59 +000035
Rui Ueyama16e543b2014-03-06 21:14:04 +000036 uint64_t ordinal() const override { return _ordinal; }
Rui Ueyama0ca149f2013-08-06 22:31:59 +000037
Rui Ueyama16e543b2014-03-06 21:14:04 +000038 uint64_t size() const override { return 0; }
Rui Ueyama0ca149f2013-08-06 22:31:59 +000039
Rui Ueyama16e543b2014-03-06 21:14:04 +000040 Scope scope() const override { return DefinedAtom::scopeLinkageUnit; }
Rui Ueyama0ca149f2013-08-06 22:31:59 +000041
Rui Ueyama16e543b2014-03-06 21:14:04 +000042 Interposable interposable() const override { return DefinedAtom::interposeNo; }
Rui Ueyama0ca149f2013-08-06 22:31:59 +000043
Rui Ueyama16e543b2014-03-06 21:14:04 +000044 Merge merge() const override { return DefinedAtom::mergeNo; }
Rui Ueyama0ca149f2013-08-06 22:31:59 +000045
Rui Ueyama16e543b2014-03-06 21:14:04 +000046 ContentType contentType() const override { return DefinedAtom::typeStub; }
Rui Ueyama0ca149f2013-08-06 22:31:59 +000047
Rui Ueyama16e543b2014-03-06 21:14:04 +000048 Alignment alignment() const override { return Alignment(0, 0); }
Rui Ueyama0ca149f2013-08-06 22:31:59 +000049
Rui Ueyama16e543b2014-03-06 21:14:04 +000050 SectionChoice sectionChoice() const override {
Rui Ueyama0ca149f2013-08-06 22:31:59 +000051 return DefinedAtom::sectionBasedOnContent;
52 }
53
Rui Ueyama16e543b2014-03-06 21:14:04 +000054 StringRef customSectionName() const override { return StringRef(); }
Rui Ueyama0ca149f2013-08-06 22:31:59 +000055
Rui Ueyama16e543b2014-03-06 21:14:04 +000056 SectionPosition sectionPosition() const override { return sectionPositionAny; }
Rui Ueyama0ca149f2013-08-06 22:31:59 +000057
Rui Ueyama16e543b2014-03-06 21:14:04 +000058 DeadStripKind deadStrip() const override {
Rui Ueyama0ca149f2013-08-06 22:31:59 +000059 return DefinedAtom::deadStripNormal;
60 }
61
Rui Ueyama16e543b2014-03-06 21:14:04 +000062 ContentPermissions permissions() const override {
Rui Ueyama0ca149f2013-08-06 22:31:59 +000063 return DefinedAtom::permR_X;
64 }
65
Rui Ueyama16e543b2014-03-06 21:14:04 +000066 ArrayRef<uint8_t> rawContent() const override { return ArrayRef<uint8_t>(); }
Rui Ueyama0ca149f2013-08-06 22:31:59 +000067
Rui Ueyama16e543b2014-03-06 21:14:04 +000068 reference_iterator begin() const override {
Rui Ueyama0ca149f2013-08-06 22:31:59 +000069 return reference_iterator(*this, nullptr);
70 }
71
Rui Ueyama16e543b2014-03-06 21:14:04 +000072 reference_iterator end() const override {
Rui Ueyama0ca149f2013-08-06 22:31:59 +000073 return reference_iterator(*this, nullptr);
74 }
75
Rui Ueyama16e543b2014-03-06 21:14:04 +000076 const Reference *derefIterator(const void *iter) const override {
Rui Ueyama0ca149f2013-08-06 22:31:59 +000077 return nullptr;
78 }
79
Rui Ueyama16e543b2014-03-06 21:14:04 +000080 void incrementIterator(const void *&iter) const override {}
Rui Ueyama0ca149f2013-08-06 22:31:59 +000081
82private:
83 const File &_file;
84 uint32_t _ordinal;
85};
86
87/// \brief Simple atom created by the GOT pass.
88class TestingGOTAtom : public DefinedAtom {
89public:
90 TestingGOTAtom(const File &F, const Atom &) : _file(F) {
91 static uint32_t lastOrdinal = 0;
92 _ordinal = lastOrdinal++;
93 }
94
Rui Ueyama16e543b2014-03-06 21:14:04 +000095 const File &file() const override { return _file; }
Rui Ueyama0ca149f2013-08-06 22:31:59 +000096
Rui Ueyama16e543b2014-03-06 21:14:04 +000097 StringRef name() const override { return StringRef(); }
Rui Ueyama0ca149f2013-08-06 22:31:59 +000098
Rui Ueyama16e543b2014-03-06 21:14:04 +000099 uint64_t ordinal() const override { return _ordinal; }
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000100
Rui Ueyama16e543b2014-03-06 21:14:04 +0000101 uint64_t size() const override { return 0; }
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000102
Rui Ueyama16e543b2014-03-06 21:14:04 +0000103 Scope scope() const override { return DefinedAtom::scopeLinkageUnit; }
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000104
Rui Ueyama16e543b2014-03-06 21:14:04 +0000105 Interposable interposable() const override { return DefinedAtom::interposeNo; }
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000106
Rui Ueyama16e543b2014-03-06 21:14:04 +0000107 Merge merge() const override { return DefinedAtom::mergeNo; }
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000108
Rui Ueyama16e543b2014-03-06 21:14:04 +0000109 ContentType contentType() const override { return DefinedAtom::typeGOT; }
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000110
Rui Ueyama16e543b2014-03-06 21:14:04 +0000111 Alignment alignment() const override { return Alignment(3, 0); }
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000112
Rui Ueyama16e543b2014-03-06 21:14:04 +0000113 SectionChoice sectionChoice() const override {
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000114 return DefinedAtom::sectionBasedOnContent;
115 }
116
Rui Ueyama16e543b2014-03-06 21:14:04 +0000117 StringRef customSectionName() const override { return StringRef(); }
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000118
Rui Ueyama16e543b2014-03-06 21:14:04 +0000119 SectionPosition sectionPosition() const override { return sectionPositionAny; }
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000120
Rui Ueyama16e543b2014-03-06 21:14:04 +0000121 DeadStripKind deadStrip() const override {
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000122 return DefinedAtom::deadStripNormal;
123 }
124
Rui Ueyama16e543b2014-03-06 21:14:04 +0000125 ContentPermissions permissions() const override {
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000126 return DefinedAtom::permRW_;
127 }
128
Rui Ueyama16e543b2014-03-06 21:14:04 +0000129 ArrayRef<uint8_t> rawContent() const override { return ArrayRef<uint8_t>(); }
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000130
Rui Ueyama16e543b2014-03-06 21:14:04 +0000131 reference_iterator begin() const override {
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000132 return reference_iterator(*this, nullptr);
133 }
134
Rui Ueyama16e543b2014-03-06 21:14:04 +0000135 reference_iterator end() const override {
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000136 return reference_iterator(*this, nullptr);
137 }
138
Rui Ueyama16e543b2014-03-06 21:14:04 +0000139 const Reference *derefIterator(const void *iter) const override {
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000140 return nullptr;
141 }
142
Rui Ueyama16e543b2014-03-06 21:14:04 +0000143 void incrementIterator(const void *&iter) const override {}
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000144
145private:
146 const File &_file;
147 uint32_t _ordinal;
148};
149
Shankar Easwaran2bc24922013-10-29 05:12:14 +0000150class TestingPassFile : public SimpleFile {
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000151public:
Rui Ueyama170a1a82013-12-20 07:48:29 +0000152 TestingPassFile(const LinkingContext &ctx) : SimpleFile("Testing pass") {}
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000153
Rui Ueyama16e543b2014-03-06 21:14:04 +0000154 void addAtom(const Atom &atom) override {
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000155 if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(&atom))
156 _definedAtoms._atoms.push_back(defAtom);
157 else
158 llvm_unreachable("atom has unknown definition kind");
159 }
160
Rui Ueyama16e543b2014-03-06 21:14:04 +0000161 DefinedAtomRange definedAtoms() override {
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000162 return range<std::vector<const DefinedAtom *>::iterator>(
163 _definedAtoms._atoms.begin(), _definedAtoms._atoms.end());
164 }
165
Rui Ueyama16e543b2014-03-06 21:14:04 +0000166 const atom_collection<DefinedAtom> &defined() const override {
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000167 return _definedAtoms;
168 }
Rui Ueyama16e543b2014-03-06 21:14:04 +0000169 const atom_collection<UndefinedAtom> &undefined() const override {
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000170 return _undefinedAtoms;
171 }
Rui Ueyama16e543b2014-03-06 21:14:04 +0000172 const atom_collection<SharedLibraryAtom> &sharedLibrary() const override {
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000173 return _sharedLibraryAtoms;
174 }
Rui Ueyama16e543b2014-03-06 21:14:04 +0000175 const atom_collection<AbsoluteAtom> &absolute() const override {
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000176 return _absoluteAtoms;
177 }
178
179private:
180 atom_collection_vector<DefinedAtom> _definedAtoms;
181 atom_collection_vector<UndefinedAtom> _undefinedAtoms;
182 atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms;
183 atom_collection_vector<AbsoluteAtom> _absoluteAtoms;
184};
185
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000186
187class TestingStubsPass : public StubsPass {
188public:
Simon Atanasyan842a90d2014-06-10 13:43:24 +0000189 TestingStubsPass(const LinkingContext &ctx) : _file(ctx) {}
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000190
Rui Ueyama16e543b2014-03-06 21:14:04 +0000191 bool noTextRelocs() override { return true; }
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000192
Rui Ueyama16e543b2014-03-06 21:14:04 +0000193 bool isCallSite(const Reference &ref) override {
Nick Kledzike5552772013-12-19 21:58:00 +0000194 if (ref.kindNamespace() != Reference::KindNamespace::testing)
195 return false;
196 return (ref.kindValue() == CoreLinkingContext::TEST_RELOC_CALL32);
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000197 }
198
Rui Ueyama16e543b2014-03-06 21:14:04 +0000199 const DefinedAtom *getStub(const Atom &target) override {
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000200 const DefinedAtom *result = new TestingStubAtom(_file, target);
201 _file.addAtom(*result);
202 return result;
203 }
204
Rui Ueyama16e543b2014-03-06 21:14:04 +0000205 void addStubAtoms(MutableFile &mergedFile) override {
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000206 for (const DefinedAtom *stub : _file.defined()) {
207 mergedFile.addAtom(*stub);
208 }
209 }
210
211private:
212 TestingPassFile _file;
213};
214
215class TestingGOTPass : public GOTPass {
216public:
Simon Atanasyan842a90d2014-06-10 13:43:24 +0000217 TestingGOTPass(const LinkingContext &ctx) : _file(ctx) {}
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000218
Rui Ueyama16e543b2014-03-06 21:14:04 +0000219 bool noTextRelocs() override { return true; }
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000220
Rui Ueyama16e543b2014-03-06 21:14:04 +0000221 bool isGOTAccess(const Reference &ref, bool &canBypassGOT) override {
Nick Kledzike5552772013-12-19 21:58:00 +0000222 if (ref.kindNamespace() != Reference::KindNamespace::testing)
223 return false;
224 switch (ref.kindValue()) {
225 case CoreLinkingContext::TEST_RELOC_GOT_LOAD32:
226 canBypassGOT = true;
227 return true;
228 case CoreLinkingContext::TEST_RELOC_GOT_USE32:
229 canBypassGOT = false;
230 return true;
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000231 }
232 return false;
233 }
234
Rui Ueyama16e543b2014-03-06 21:14:04 +0000235 void updateReferenceToGOT(const Reference *ref, bool targetIsNowGOT) override {
Rui Ueyama170a1a82013-12-20 07:48:29 +0000236 const_cast<Reference *>(ref)->setKindValue(
237 targetIsNowGOT ? CoreLinkingContext::TEST_RELOC_PCREL32
238 : CoreLinkingContext::TEST_RELOC_LEA32_WAS_GOT);
239 }
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000240
Rui Ueyama16e543b2014-03-06 21:14:04 +0000241 const DefinedAtom *makeGOTEntry(const Atom &target) override {
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000242 return new TestingGOTAtom(_file, target);
243 }
244
245private:
246 TestingPassFile _file;
247};
248
249} // anonymous namespace
250
251CoreLinkingContext::CoreLinkingContext() {}
252
Shankar Easwaran7f1146c2013-10-08 15:43:48 +0000253bool CoreLinkingContext::validateImpl(raw_ostream &) {
Shankar Easwaran7f1146c2013-10-08 15:43:48 +0000254 _writer = createWriterYAML(*this);
Rui Ueyama8db1edd2013-09-24 23:26:34 +0000255 return true;
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000256}
257
Shankar Easwaran2bc24922013-10-29 05:12:14 +0000258void CoreLinkingContext::addPasses(PassManager &pm) {
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000259 for (StringRef name : _passNames) {
260 if (name.equals("layout"))
Nico Rieckb9d84f42014-02-24 21:14:37 +0000261 pm.add(std::unique_ptr<Pass>(new LayoutPass(registry())));
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000262 else if (name.equals("GOT"))
263 pm.add(std::unique_ptr<Pass>(new TestingGOTPass(*this)));
264 else if (name.equals("stubs"))
265 pm.add(std::unique_ptr<Pass>(new TestingStubsPass(*this)));
266 else
267 llvm_unreachable("bad pass name");
268 }
269}
270
Shankar Easwaran7f1146c2013-10-08 15:43:48 +0000271Writer &CoreLinkingContext::writer() const { return *_writer; }