]> git.saurik.com Git - apple/ld64.git/blame - src/ld/passes/stubs/stub_x86.hpp
ld64-127.2.tar.gz
[apple/ld64.git] / src / ld / passes / stubs / stub_x86.hpp
CommitLineData
a645023d
A
1/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
2 *
3 * Copyright (c) 2009-2010 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 {
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(2)),
37 _fixup(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressLittleEndian32,
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** ) const
43 { return false; }
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]; }
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(2)) { pass.addAtom(*this); }
67
68 virtual const ld::File* file() const { return NULL; }
69 virtual bool translationUnitSource(const char** dir, const char** ) const
70 { return false; }
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) { }
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(1, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressLittleEndian32, compressedImageCache(pass)),
100 _fixup2(7, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressLittleEndian32, compressedFastBinder(pass))
101 { pass.addAtom(*this); }
102
103 virtual ld::File* file() const { return NULL; }
104 virtual bool translationUnitSource(const char** dir, const char** ) const
105 { return false; }
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
111 buffer[1] = 0x00;
112 buffer[2] = 0x00;
113 buffer[3] = 0x00;
114 buffer[4] = 0x00;
115 buffer[5] = 0xFF; // jmp *_fast_lazy_bind
116 buffer[6] = 0x25;
117 buffer[7] = 0x00;
118 buffer[8] = 0x00;
119 buffer[9] = 0x00;
120 buffer[10] = 0x00;
121 buffer[11] = 0x90; // nop
122 }
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]; }
126
127private:
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;
132 }
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;
137 }
138
139 mutable ld::Fixup _fixup1;
140 ld::Fixup _fixup2;
141
142 static ld::Section _s_section;
143};
144
145ld::Section StubHelperHelperAtom::_s_section("__TEXT", "__stub_helper", ld::Section::typeStubHelper);
146
147
148
149class StubHelperAtom : public ld::Atom {
150public:
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)),
156 _stubTo(stubTo),
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)) { }
160
161 virtual const ld::File* file() const { return _stubTo.file(); }
162 virtual bool translationUnitSource(const char** dir, const char** ) const
163 { return false; }
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
169 buffer[1] = 0x00;
170 buffer[2] = 0x00;
171 buffer[3] = 0x00;
172 buffer[4] = 0x00;
173 buffer[5] = 0xE9; // jmp helperhelper
174 buffer[6] = 0x00;
175 buffer[7] = 0x00;
176 buffer[8] = 0x00;
177 buffer[9] = 0x00;
178 }
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]; }
182
183private:
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;
188 }
189
190 const ld::Atom& _stubTo;
191 mutable ld::Fixup _fixup1;
192 ld::Fixup _fixup2;
193 ld::Fixup _fixup3;
194
195 static ld::Section _s_section;
196};
197
198ld::Section StubHelperAtom::_s_section("__TEXT", "__stub_helper", ld::Section::typeStubHelper);
199
200
201class ResolverHelperAtom : public ld::Atom {
202public:
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)),
208 _stubTo(stubTo),
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) { }
212
213 virtual const ld::File* file() const { return _stubTo.file(); }
214 virtual bool translationUnitSource(const char** dir, const char** ) const
215 { return false; }
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
224 buffer[ 4] = 0x00;
225 buffer[ 5] = 0x00;
226 buffer[ 6] = 0x00;
227 buffer[ 7] = 0x00;
228 buffer[ 8] = 0xA3; // movl %eax,foo$lazy_ptr
229 buffer[ 9] = 0x00;
230 buffer[10] = 0x00;
231 buffer[11] = 0x00;
232 buffer[12] = 0x00;
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
237 buffer[17] = 0x25;
238 buffer[18] = 0x00;
239 buffer[19] = 0x00;
240 buffer[20] = 0x00;
241 buffer[21] = 0x00;
242 }
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]; }
246
247private:
248
249 const ld::Atom& _stubTo;
250 mutable ld::Fixup _fixup1;
251 ld::Fixup _fixup2;
252 ld::Fixup _fixup3;
253
254 static ld::Section _s_section;
255};
256
257ld::Section ResolverHelperAtom::_s_section("__TEXT", "__stub_helper", ld::Section::typeStubHelper);
258
259
260
261class LazyPointerAtom : public ld::Atom {
262public:
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)),
268 _stubTo(stubTo),
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);
279 }
280
281 virtual const ld::File* file() const { return _stubTo.file(); }
282 virtual bool translationUnitSource(const char** dir, const char** ) const
283 { return false; }
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]; }
291
292private:
293 const ld::Atom& _stubTo;
294 StubHelperAtom _helper;
295 ResolverHelperAtom _resolverHelper;
296 mutable ld::Fixup _fixup1;
297 ld::Fixup _fixup2;
298
299 static ld::Section _s_section;
300};
301
302ld::Section LazyPointerAtom::_s_section("__DATA", "__la_symbol_ptr", ld::Section::typeLazyPointer);
303
304
305class StubAtom : public ld::Atom {
306public:
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)),
312 _stubTo(stubTo),
313 _lazyPointer(pass, stubTo, stubToGlobalWeakDef, stubToResolver, weakImport),
314 _fixup(2, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressLittleEndian32, &_lazyPointer) { pass.addAtom(*this); }
315
316 virtual const ld::File* file() const { return _stubTo.file(); }
317 virtual bool translationUnitSource(const char** dir, const char** ) const
318 { return false; }
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
324 buffer[1] = 0x25;
325 buffer[2] = 0x00;
326 buffer[3] = 0x00;
327 buffer[4] = 0x00;
328 buffer[5] = 0x00;
329 }
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]; }
333
334private:
335 const ld::Atom& _stubTo;
336 LazyPointerAtom _lazyPointer;
337 mutable ld::Fixup _fixup;
338
339 static ld::Section _s_section;
340};
341
342ld::Section StubAtom::_s_section("__TEXT", "__symbol_stub", ld::Section::typeStub);
343
344
345
346} // namespace x86
347