]> git.saurik.com Git - apple/ld64.git/blame - src/ld/passes/stubs/stub_x86_64.hpp
ld64-128.2.tar.gz
[apple/ld64.git] / src / ld / passes / stubs / stub_x86_64.hpp
CommitLineData
a645023d
A
1/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
2 *
3 * Copyright (c) 2009 Apple Inc. All rights reserved.
4 *
5 * @APPLE_LICENSE_HEADER_START@
6 *
7 * This file contains Original Code and/or Modifications of Original Code
8 * as defined in and that are subject to the Apple Public Source License
9 * Version 2.0 (the 'License'). You may not use this file except in
10 * compliance with the License. Please obtain a copy of the License at
11 * http://www.opensource.apple.com/apsl/ and read it before using this
12 * file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
19 * Please see the License for the specific language governing rights and
20 * limitations under the License.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24
25
26// already in ld::passes::stubs namespace
27namespace x86_64 {
28
29
30
31class FastBindingPointerAtom : public ld::Atom {
32public:
33 FastBindingPointerAtom(ld::passes::stubs::Pass& pass)
34 : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever,
35 ld::Atom::scopeLinkageUnit, ld::Atom::typeNonLazyPointer,
36 symbolTableNotIn, false, false, false, ld::Atom::Alignment(3)),
37 _fixup(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressLittleEndian64,
38 pass.internal()->compressedFastBinderProxy)
39 { pass.addAtom(*this); }
40
41 virtual const ld::File* file() const { return NULL; }
42 virtual bool translationUnitSource(const char** dir, const char** nm) const
43 { return false; }
44 virtual const char* name() const { return "fast binder pointer"; }
45 virtual uint64_t size() const { return 8; }
46 virtual uint64_t objectAddress() const { return 0; }
47 virtual void copyRawContent(uint8_t buffer[]) const { }
48 virtual void setScope(Scope) { }
49 virtual ld::Fixup::iterator fixupsBegin() const { return &_fixup; }
50 virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup)[1]; }
51
52private:
53 mutable ld::Fixup _fixup;
54
55 static ld::Section _s_section;
56};
57
58ld::Section FastBindingPointerAtom::_s_section("__DATA", "__nl_symbol_ptr", ld::Section::typeNonLazyPointer);
59
60
61class ImageCachePointerAtom : public ld::Atom {
62public:
63 ImageCachePointerAtom(ld::passes::stubs::Pass& pass)
64 : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever,
65 ld::Atom::scopeLinkageUnit, ld::Atom::typeNonLazyPointer,
66 symbolTableNotIn, false, false, false, ld::Atom::Alignment(3)) { pass.addAtom(*this); }
67
68 virtual const ld::File* file() const { return NULL; }
69 virtual bool translationUnitSource(const char** dir, const char** nm) const
70 { return false; }
71 virtual const char* name() const { return "image cache pointer"; }
72 virtual uint64_t size() const { return 8; }
73 virtual uint64_t objectAddress() const { return 0; }
74 virtual void copyRawContent(uint8_t buffer[]) const { }
75 virtual void setScope(Scope) { }
76
77private:
78
79 static ld::Section _s_section;
80};
81
82ld::Section ImageCachePointerAtom::_s_section("__DATA", "__nl_symbol_ptr", ld::Section::typeNonLazyPointer);
83
84
85
86
87
88//
89// The stub-helper-helper is the common code factored out of each helper function.
90// It is in the same section as the stub-helpers.
91// Similar to the PLT0 entry in ELF.
92//
93class StubHelperHelperAtom : public ld::Atom {
94public:
95 StubHelperHelperAtom(ld::passes::stubs::Pass& pass)
96 : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever,
97 ld::Atom::scopeLinkageUnit, ld::Atom::typeStubHelper,
98 symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)),
99 _fixup1(3, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressX86PCRel32, compressedImageCache(pass)),
100 _fixup2(11, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressX86PCRel32, compressedFastBinder(pass))
101 { pass.addAtom(*this); }
102
103 virtual ld::File* file() const { return NULL; }
104 virtual bool translationUnitSource(const char** dir, const char** nm) const
105 { return false; }
106 virtual const char* name() const { return "helper helper"; }
107 virtual uint64_t size() const { return 16; }
108 virtual uint64_t objectAddress() const { return 0; }
109 virtual void copyRawContent(uint8_t buffer[]) const {
110 buffer[0] = 0x4C; // leaq dyld_mageLoaderCache(%rip),%r11
111 buffer[1] = 0x8D;
112 buffer[2] = 0x1D;
113 buffer[3] = 0x00;
114 buffer[4] = 0x00;
115 buffer[5] = 0x00;
116 buffer[6] = 0x00;
117 buffer[7] = 0x41; // pushq %r11
118 buffer[8] = 0x53;
119 buffer[9] = 0xFF; // jmp *_fast_lazy_bind(%rip)
120 buffer[10] = 0x25;
121 buffer[11] = 0x00;
122 buffer[12] = 0x00;
123 buffer[13] = 0x00;
124 buffer[14] = 0x00;
125 buffer[15] = 0x90; // nop
126 }
127 virtual void setScope(Scope) { }
128 virtual ld::Fixup::iterator fixupsBegin() const { return &_fixup1; }
129 virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup2)[1]; }
130
131private:
132 static ld::Atom* compressedImageCache(ld::passes::stubs::Pass& pass) {
133 if ( pass.compressedImageCache == NULL )
134 pass.compressedImageCache = new ImageCachePointerAtom(pass);
135 return pass.compressedImageCache;
136 }
137 static ld::Atom* compressedFastBinder(ld::passes::stubs::Pass& pass) {
138 if ( pass.compressedFastBinderPointer == NULL )
139 pass.compressedFastBinderPointer = new FastBindingPointerAtom(pass);
140 return pass.compressedFastBinderPointer;
141 }
142
143 mutable ld::Fixup _fixup1;
144 ld::Fixup _fixup2;
145
146 static ld::Section _s_section;
147};
148
149ld::Section StubHelperHelperAtom::_s_section("__TEXT", "__stub_helper", ld::Section::typeStubHelper);
150
151
152
153class StubHelperAtom : public ld::Atom {
154public:
155 StubHelperAtom(ld::passes::stubs::Pass& pass, const ld::Atom* lazyPointer,
156 const ld::Atom& stubTo)
157 : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever,
158 ld::Atom::scopeLinkageUnit, ld::Atom::typeStubHelper,
159 symbolTableNotIn, false, false, false, ld::Atom::Alignment(1)),
160 _stubTo(stubTo),
161 _fixup1(1, ld::Fixup::k1of2, ld::Fixup::kindSetLazyOffset, lazyPointer),
162 _fixup2(1, ld::Fixup::k2of2, ld::Fixup::kindStoreLittleEndian32),
163 _fixup3(6, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressX86BranchPCRel32, helperHelper(pass)) { }
164
165 virtual const ld::File* file() const { return _stubTo.file(); }
166 virtual bool translationUnitSource(const char** dir, const char** nm) const
167 { return false; }
168 virtual const char* name() const { return _stubTo.name(); }
169 virtual uint64_t size() const { return 10; }
170 virtual uint64_t objectAddress() const { return 0; }
171 virtual void copyRawContent(uint8_t buffer[]) const {
172 buffer[0] = 0x68; // pushq $lazy-info-offset
173 buffer[1] = 0x00;
174 buffer[2] = 0x00;
175 buffer[3] = 0x00;
176 buffer[4] = 0x00;
177 buffer[5] = 0xE9; // jmp helperhelper
178 buffer[6] = 0x00;
179 buffer[7] = 0x00;
180 buffer[8] = 0x00;
181 buffer[9] = 0x00;
182 }
183 virtual void setScope(Scope) { }
184 virtual ld::Fixup::iterator fixupsBegin() const { return &_fixup1; }
185 virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup3)[1]; }
186
187private:
188 static ld::Atom* helperHelper(ld::passes::stubs::Pass& pass) {
189 if ( pass.compressedHelperHelper == NULL )
190 pass.compressedHelperHelper = new StubHelperHelperAtom(pass);
191 return pass.compressedHelperHelper;
192 }
193
194 const ld::Atom& _stubTo;
195 mutable ld::Fixup _fixup1;
196 ld::Fixup _fixup2;
197 ld::Fixup _fixup3;
198
199 static ld::Section _s_section;
200};
201
202ld::Section StubHelperAtom::_s_section("__TEXT", "__stub_helper", ld::Section::typeStubHelper);
203
204
205class ResolverHelperAtom : public ld::Atom {
206public:
207 ResolverHelperAtom(ld::passes::stubs::Pass& pass, const ld::Atom* lazyPointer,
208 const ld::Atom& stubTo)
209 : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever,
210 ld::Atom::scopeLinkageUnit, ld::Atom::typeStubHelper,
211 symbolTableNotIn, false, false, false, ld::Atom::Alignment(1)),
212 _stubTo(stubTo),
213 _fixup1(10, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressX86BranchPCRel32, &stubTo),
214 _fixup2(17, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressX86PCRel32, lazyPointer),
215 _fixup3(32, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressX86PCRel32, lazyPointer) { }
216
217 virtual const ld::File* file() const { return _stubTo.file(); }
218 virtual bool translationUnitSource(const char** dir, const char** nm) const
219 { return false; }
220 virtual const char* name() const { return _stubTo.name(); }
221 virtual uint64_t size() const { return 36; }
222 virtual uint64_t objectAddress() const { return 0; }
223 virtual void copyRawContent(uint8_t buffer[]) const {
224 buffer[ 0] = 0x50; // push %rax
225 buffer[ 1] = 0x57; // push %rdi
226 buffer[ 2] = 0x56; // push %rsi
227 buffer[ 3] = 0x52; // push %rdx
228 buffer[ 4] = 0x51; // push %rcx
229 buffer[ 5] = 0x41; // push %r8
230 buffer[ 6] = 0x50;
231 buffer[ 7] = 0x41; // push %r9
232 buffer[ 8] = 0x51;
233 buffer[ 9] = 0xE8; // call foo
234 buffer[10] = 0x00;
235 buffer[11] = 0x00;
236 buffer[12] = 0x00;
237 buffer[13] = 0x00;
238 buffer[14] = 0x48; // movq %rax,foo$lazy_pointer(%rip)
239 buffer[15] = 0x89;
240 buffer[16] = 0x05;
241 buffer[17] = 0x00;
242 buffer[18] = 0x00;
243 buffer[19] = 0x00;
244 buffer[20] = 0x00;
245 buffer[21] = 0x41; // pop %r9
246 buffer[22] = 0x59;
247 buffer[23] = 0x41; // pop %r8
248 buffer[24] = 0x58;
249 buffer[25] = 0x59; // pop %rcx
250 buffer[26] = 0x5A; // pop %rdx
251 buffer[27] = 0x5E; // pop %rsi
252 buffer[28] = 0x5F; // pop %rdi
253 buffer[29] = 0x58; // pop %rax
254 buffer[30] = 0xFF; // jmp *foo$lazy_ptr(%rip)
255 buffer[31] = 0x25;
256 buffer[32] = 0x00;
257 buffer[33] = 0x00;
258 buffer[34] = 0x00;
259 buffer[35] = 0x00;
260 }
261 virtual void setScope(Scope) { }
262 virtual ld::Fixup::iterator fixupsBegin() const { return &_fixup1; }
263 virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup3)[1]; }
264
265private:
266
267 const ld::Atom& _stubTo;
268 mutable ld::Fixup _fixup1;
269 ld::Fixup _fixup2;
270 ld::Fixup _fixup3;
271
272 static ld::Section _s_section;
273};
274
275ld::Section ResolverHelperAtom::_s_section("__TEXT", "__stub_helper", ld::Section::typeStubHelper);
276
277
278
279class LazyPointerAtom : public ld::Atom {
280public:
281 LazyPointerAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo,
282 bool stubToGlobalWeakDef, bool stubToResolver, bool weakImport)
283 : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever,
284 ld::Atom::scopeTranslationUnit, ld::Atom::typeLazyPointer,
285 symbolTableNotIn, false, false, false, ld::Atom::Alignment(3)),
286 _stubTo(stubTo),
287 _helper(pass, this, stubTo),
288 _resolverHelper(pass, this, stubTo),
289 _fixup1(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressLittleEndian64,
290 stubToResolver ? &_resolverHelper :
291 (stubToGlobalWeakDef ? &stubTo : &_helper)),
292 _fixup2(0, ld::Fixup::k1of1, ld::Fixup::kindLazyTarget, &stubTo) {
293 _fixup2.weakImport = weakImport; pass.addAtom(*this);
294 if ( stubToResolver )
295 pass.addAtom(_resolverHelper);
296 else if ( !stubToGlobalWeakDef )
297 pass.addAtom(_helper);
298 }
299
300 virtual const ld::File* file() const { return _stubTo.file(); }
301 virtual bool translationUnitSource(const char** dir, const char** ) const
302 { return false; }
303 virtual const char* name() const { return _stubTo.name(); }
304 virtual uint64_t size() const { return 8; }
305 virtual uint64_t objectAddress() const { return 0; }
306 virtual void copyRawContent(uint8_t buffer[]) const { }
307 virtual void setScope(Scope) { }
308 virtual ld::Fixup::iterator fixupsBegin() const { return &_fixup1; }
309 virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup2)[1]; }
310
311private:
312 const ld::Atom& _stubTo;
313 StubHelperAtom _helper;
314 ResolverHelperAtom _resolverHelper;
315 mutable ld::Fixup _fixup1;
316 ld::Fixup _fixup2;
317
318 static ld::Section _s_section;
319};
320
321ld::Section LazyPointerAtom::_s_section("__DATA", "__la_symbol_ptr", ld::Section::typeLazyPointer);
322
323
324class StubAtom : public ld::Atom {
325public:
326 StubAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo,
327 bool stubToGlobalWeakDef, bool stubToResolver, bool weakImport)
328 : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever,
329 ld::Atom::scopeLinkageUnit, ld::Atom::typeStub,
330 symbolTableNotIn, false, false, false, ld::Atom::Alignment(1)),
331 _stubTo(stubTo),
332 _lazyPointer(pass, stubTo, stubToGlobalWeakDef, stubToResolver, weakImport),
333 _fixup(2, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressX86PCRel32, &_lazyPointer) { pass.addAtom(*this); }
334
335 virtual const ld::File* file() const { return _stubTo.file(); }
336 virtual bool translationUnitSource(const char** dir, const char** ) const
337 { return false; }
338 virtual const char* name() const { return _stubTo.name(); }
339 virtual uint64_t size() const { return 6; }
340 virtual uint64_t objectAddress() const { return 0; }
341 virtual void copyRawContent(uint8_t buffer[]) const {
342 buffer[0] = 0xFF; // jmp *foo$lazy_pointer(%rip)
343 buffer[1] = 0x25;
344 buffer[2] = 0x00;
345 buffer[3] = 0x00;
346 buffer[4] = 0x00;
347 buffer[5] = 0x00;
348 }
349 virtual void setScope(Scope) { }
350 virtual ld::Fixup::iterator fixupsBegin() const { return &_fixup; }
351 virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup)[1]; }
352
353private:
354 const ld::Atom& _stubTo;
355 LazyPointerAtom _lazyPointer;
356 mutable ld::Fixup _fixup;
357
358 static ld::Section _s_section;
359};
360
361ld::Section StubAtom::_s_section("__TEXT", "__stubs", ld::Section::typeStub);
362
363
364
365} // namespace x86_64
366