1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
3 * Copyright (c) 2009-2010 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(2)),
37 _fixup(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressLittleEndian32,
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** ) const
44 virtual const char* name() const { return "fast binder pointer"; }
45 virtual uint64_t size() const { return 4; }
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(2)) { pass.addAtom(*this); }
68 virtual const ld::File* file() const { return NULL; }
69 virtual bool translationUnitSource(const char** dir, const char** ) const
71 virtual const char* name() const { return "image cache pointer"; }
72 virtual uint64_t size() const { return 4; }
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(1, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressLittleEndian32, compressedImageCache(pass)),
100 _fixup2(7, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressLittleEndian32, compressedFastBinder(pass))
101 { pass.addAtom(*this); }
103 virtual ld::File* file() const { return NULL; }
104 virtual bool translationUnitSource(const char** dir, const char** ) const
106 virtual const char* name() const { return "helper helper"; }
107 virtual uint64_t size() const { return 12; }
108 virtual uint64_t objectAddress() const { return 0; }
109 virtual void copyRawContent(uint8_t buffer[]) const {
110 buffer[0] = 0x68; // pushl $dyld_ImageLoaderCache
115 buffer[5] = 0xFF; // jmp *_fast_lazy_bind
121 buffer[11] = 0x90; // nop
123 virtual void setScope(Scope) { }
124 virtual ld::Fixup::iterator fixupsBegin() const { return &_fixup1; }
125 virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup2)[1]; }
128 static ld::Atom* compressedImageCache(ld::passes::stubs::Pass& pass) {
129 if ( pass.compressedImageCache == NULL )
130 pass.compressedImageCache = new ImageCachePointerAtom(pass);
131 return pass.compressedImageCache;
133 static ld::Atom* compressedFastBinder(ld::passes::stubs::Pass& pass) {
134 if ( pass.compressedFastBinderPointer == NULL )
135 pass.compressedFastBinderPointer = new FastBindingPointerAtom(pass);
136 return pass.compressedFastBinderPointer;
139 mutable ld::Fixup _fixup1;
142 static ld::Section _s_section;
145 ld::Section StubHelperHelperAtom::_s_section("__TEXT", "__stub_helper", ld::Section::typeStubHelper);
149 class StubHelperAtom : public ld::Atom {
151 StubHelperAtom(ld::passes::stubs::Pass& pass, const ld::Atom* lazyPointer,
152 const ld::Atom& stubTo)
153 : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever,
154 ld::Atom::scopeLinkageUnit, ld::Atom::typeStubHelper,
155 symbolTableNotIn, false, false, false, ld::Atom::Alignment(1)),
157 _fixup1(1, ld::Fixup::k1of2, ld::Fixup::kindSetLazyOffset, lazyPointer),
158 _fixup2(1, ld::Fixup::k2of2, ld::Fixup::kindStoreLittleEndian32),
159 _fixup3(6, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressX86BranchPCRel32, helperHelper(pass)) { }
161 virtual const ld::File* file() const { return _stubTo.file(); }
162 virtual bool translationUnitSource(const char** dir, const char** ) const
164 virtual const char* name() const { return _stubTo.name(); }
165 virtual uint64_t size() const { return 10; }
166 virtual uint64_t objectAddress() const { return 0; }
167 virtual void copyRawContent(uint8_t buffer[]) const {
168 buffer[0] = 0x68; // pushl $lazy-info-offset
173 buffer[5] = 0xE9; // jmp helperhelper
179 virtual void setScope(Scope) { }
180 virtual ld::Fixup::iterator fixupsBegin() const { return &_fixup1; }
181 virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup3)[1]; }
184 static ld::Atom* helperHelper(ld::passes::stubs::Pass& pass) {
185 if ( pass.compressedHelperHelper == NULL )
186 pass.compressedHelperHelper = new StubHelperHelperAtom(pass);
187 return pass.compressedHelperHelper;
190 const ld::Atom& _stubTo;
191 mutable ld::Fixup _fixup1;
195 static ld::Section _s_section;
198 ld::Section StubHelperAtom::_s_section("__TEXT", "__stub_helper", ld::Section::typeStubHelper);
201 class ResolverHelperAtom : public ld::Atom {
203 ResolverHelperAtom(ld::passes::stubs::Pass& pass, const ld::Atom* lazyPointer,
204 const ld::Atom& stubTo)
205 : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever,
206 ld::Atom::scopeLinkageUnit, ld::Atom::typeStubHelper,
207 symbolTableNotIn, false, false, false, ld::Atom::Alignment(1)),
209 _fixup1(4, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressX86BranchPCRel32, &stubTo),
210 _fixup2(9, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressLittleEndian32, lazyPointer),
211 _fixup3(18, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressLittleEndian32, lazyPointer) { }
213 virtual const ld::File* file() const { return _stubTo.file(); }
214 virtual bool translationUnitSource(const char** dir, const char** ) const
216 virtual const char* name() const { return _stubTo.name(); }
217 virtual uint64_t size() const { return 22; }
218 virtual uint64_t objectAddress() const { return 0; }
219 virtual void copyRawContent(uint8_t buffer[]) const {
220 buffer[ 0] = 0x50; // push %eax
221 buffer[ 1] = 0x51; // push %ecx
222 buffer[ 2] = 0x52; // push %edx
223 buffer[ 3] = 0xE8; // call foo
228 buffer[ 8] = 0xA3; // movl %eax,foo$lazy_ptr
233 buffer[13] = 0x5A; // pop %edx
234 buffer[14] = 0x59; // pop %ecx
235 buffer[15] = 0x58; // pop %eax
236 buffer[16] = 0xFF; // jmp *foo$lazy_ptr
243 virtual void setScope(Scope) { }
244 virtual ld::Fixup::iterator fixupsBegin() const { return &_fixup1; }
245 virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup3)[1]; }
249 const ld::Atom& _stubTo;
250 mutable ld::Fixup _fixup1;
254 static ld::Section _s_section;
257 ld::Section ResolverHelperAtom::_s_section("__TEXT", "__stub_helper", ld::Section::typeStubHelper);
261 class LazyPointerAtom : public ld::Atom {
263 LazyPointerAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo,
264 bool stubToGlobalWeakDef, bool stubToResolver, bool weakImport)
265 : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever,
266 ld::Atom::scopeTranslationUnit, ld::Atom::typeLazyPointer,
267 symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)),
269 _helper(pass, this, stubTo),
270 _resolverHelper(pass, this, stubTo),
271 _fixup1(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressLittleEndian32,
272 stubToResolver ? &_resolverHelper : (stubToGlobalWeakDef ? &stubTo : &_helper)),
273 _fixup2(0, ld::Fixup::k1of1, ld::Fixup::kindLazyTarget, &stubTo) {
274 _fixup2.weakImport = weakImport; pass.addAtom(*this);
275 if ( stubToResolver )
276 pass.addAtom(_resolverHelper);
277 else if ( !stubToGlobalWeakDef )
278 pass.addAtom(_helper);
281 virtual const ld::File* file() const { return _stubTo.file(); }
282 virtual bool translationUnitSource(const char** dir, const char** ) const
284 virtual const char* name() const { return _stubTo.name(); }
285 virtual uint64_t size() const { return 4; }
286 virtual uint64_t objectAddress() const { return 0; }
287 virtual void copyRawContent(uint8_t buffer[]) const { }
288 virtual void setScope(Scope) { }
289 virtual ld::Fixup::iterator fixupsBegin() const { return &_fixup1; }
290 virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup2)[1]; }
293 const ld::Atom& _stubTo;
294 StubHelperAtom _helper;
295 ResolverHelperAtom _resolverHelper;
296 mutable ld::Fixup _fixup1;
299 static ld::Section _s_section;
302 ld::Section LazyPointerAtom::_s_section("__DATA", "__la_symbol_ptr", ld::Section::typeLazyPointer);
305 class StubAtom : public ld::Atom {
307 StubAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo,
308 bool stubToGlobalWeakDef, bool stubToResolver, bool weakImport)
309 : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever,
310 ld::Atom::scopeLinkageUnit, ld::Atom::typeStub,
311 symbolTableNotIn, false, false, false, ld::Atom::Alignment(1)),
313 _lazyPointer(pass, stubTo, stubToGlobalWeakDef, stubToResolver, weakImport),
314 _fixup(2, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressLittleEndian32, &_lazyPointer) { pass.addAtom(*this); }
316 virtual const ld::File* file() const { return _stubTo.file(); }
317 virtual bool translationUnitSource(const char** dir, const char** ) const
319 virtual const char* name() const { return _stubTo.name(); }
320 virtual uint64_t size() const { return 6; }
321 virtual uint64_t objectAddress() const { return 0; }
322 virtual void copyRawContent(uint8_t buffer[]) const {
323 buffer[0] = 0xFF; // jmp *foo$lazy_pointer
330 virtual void setScope(Scope) { }
331 virtual ld::Fixup::iterator fixupsBegin() const { return &_fixup; }
332 virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup)[1]; }
335 const ld::Atom& _stubTo;
336 LazyPointerAtom _lazyPointer;
337 mutable ld::Fixup _fixup;
339 static ld::Section _s_section;
342 ld::Section StubAtom::_s_section("__TEXT", "__symbol_stub", ld::Section::typeStub);