1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
3 * Copyright (c) 2009 Apple Inc. All rights reserved.
5 * @APPLE_LICENSE_HEADER_START@
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
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.
22 * @APPLE_LICENSE_HEADER_END@
26 // already in ld::passes::stubs namespace
31 class FastBindingPointerAtom : public ld::Atom {
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); }
41 virtual const ld::File* file() const { return NULL; }
42 virtual bool translationUnitSource(const char** dir, const char** nm) const
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]; }
53 mutable ld::Fixup _fixup;
55 static ld::Section _s_section;
58 ld::Section FastBindingPointerAtom::_s_section("__DATA", "__nl_symbol_ptr", ld::Section::typeNonLazyPointer);
61 class ImageCachePointerAtom : public ld::Atom {
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); }
68 virtual const ld::File* file() const { return NULL; }
69 virtual bool translationUnitSource(const char** dir, const char** nm) const
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) { }
79 static ld::Section _s_section;
82 ld::Section ImageCachePointerAtom::_s_section("__DATA", "__nl_symbol_ptr", ld::Section::typeNonLazyPointer);
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.
93 class StubHelperHelperAtom : public ld::Atom {
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); }
103 virtual ld::File* file() const { return NULL; }
104 virtual bool translationUnitSource(const char** dir, const char** nm) const
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
117 buffer[7] = 0x41; // pushq %r11
119 buffer[9] = 0xFF; // jmp *_fast_lazy_bind(%rip)
125 buffer[15] = 0x90; // nop
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]; }
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;
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;
143 mutable ld::Fixup _fixup1;
146 static ld::Section _s_section;
149 ld::Section StubHelperHelperAtom::_s_section("__TEXT", "__stub_helper", ld::Section::typeStubHelper);
153 class StubHelperAtom : public ld::Atom {
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)),
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)) { }
165 virtual const ld::File* file() const { return _stubTo.file(); }
166 virtual bool translationUnitSource(const char** dir, const char** nm) const
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
177 buffer[5] = 0xE9; // jmp helperhelper
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]; }
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;
194 const ld::Atom& _stubTo;
195 mutable ld::Fixup _fixup1;
199 static ld::Section _s_section;
202 ld::Section StubHelperAtom::_s_section("__TEXT", "__stub_helper", ld::Section::typeStubHelper);
205 class ResolverHelperAtom : public ld::Atom {
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)),
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) { }
217 virtual const ld::File* file() const { return _stubTo.file(); }
218 virtual bool translationUnitSource(const char** dir, const char** nm) const
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
231 buffer[ 7] = 0x41; // push %r9
233 buffer[ 9] = 0xE8; // call foo
238 buffer[14] = 0x48; // movq %rax,foo$lazy_pointer(%rip)
245 buffer[21] = 0x41; // pop %r9
247 buffer[23] = 0x41; // pop %r8
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)
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]; }
267 const ld::Atom& _stubTo;
268 mutable ld::Fixup _fixup1;
272 static ld::Section _s_section;
275 ld::Section ResolverHelperAtom::_s_section("__TEXT", "__stub_helper", ld::Section::typeStubHelper);
279 class LazyPointerAtom : public ld::Atom {
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)),
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);
300 virtual const ld::File* file() const { return _stubTo.file(); }
301 virtual bool translationUnitSource(const char** dir, const char** ) const
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]; }
312 const ld::Atom& _stubTo;
313 StubHelperAtom _helper;
314 ResolverHelperAtom _resolverHelper;
315 mutable ld::Fixup _fixup1;
318 static ld::Section _s_section;
321 ld::Section LazyPointerAtom::_s_section("__DATA", "__la_symbol_ptr", ld::Section::typeLazyPointer);
324 class StubAtom : public ld::Atom {
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)),
332 _lazyPointer(pass, stubTo, stubToGlobalWeakDef, stubToResolver, weakImport),
333 _fixup(2, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressX86PCRel32, &_lazyPointer) { pass.addAtom(*this); }
335 virtual const ld::File* file() const { return _stubTo.file(); }
336 virtual bool translationUnitSource(const char** dir, const char** ) const
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)
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]; }
354 const ld::Atom& _stubTo;
355 LazyPointerAtom _lazyPointer;
356 mutable ld::Fixup _fixup;
358 static ld::Section _s_section;
361 ld::Section StubAtom::_s_section("__TEXT", "__stubs", ld::Section::typeStub);
365 } // namespace x86_64