]> git.saurik.com Git - apple/ld64.git/blame - src/ld/passes/stubs/stub_arm.hpp
ld64-409.12.tar.gz
[apple/ld64.git] / src / ld / passes / stubs / stub_arm.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// already in ld::passes::stubs namespace
26namespace arm {
27
28
29class FastBindingPointerAtom : public ld::Atom {
30public:
31 FastBindingPointerAtom(ld::passes::stubs::Pass& pass)
32 : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever,
33 ld::Atom::scopeLinkageUnit, ld::Atom::typeNonLazyPointer,
34 symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)),
35 _fixup(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressLittleEndian32, pass.internal()->compressedFastBinderProxy)
36 { pass.addAtom(*this); }
37
38 virtual const ld::File* file() const { return NULL; }
a645023d
A
39 virtual const char* name() const { return "fast binder pointer"; }
40 virtual uint64_t size() const { return 4; }
41 virtual uint64_t objectAddress() const { return 0; }
42 virtual void copyRawContent(uint8_t buffer[]) const { }
43 virtual void setScope(Scope) { }
44 virtual ld::Fixup::iterator fixupsBegin() const { return (ld::Fixup*)&_fixup; }
45 virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup)[1]; }
46
47private:
48 ld::Fixup _fixup;
49
50 static ld::Section _s_section;
51};
52
53ld::Section FastBindingPointerAtom::_s_section("__DATA", "__nl_symbol_ptr", ld::Section::typeNonLazyPointer);
54
55
56class ImageCachePointerAtom : public ld::Atom {
57public:
58 ImageCachePointerAtom(ld::passes::stubs::Pass& pass)
59 : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever,
60 ld::Atom::scopeLinkageUnit, ld::Atom::typeNonLazyPointer,
61 symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)) { pass.addAtom(*this); }
62
63 virtual const ld::File* file() const { return NULL; }
a645023d
A
64 virtual const char* name() const { return "non-lazy pointer"; }
65 virtual uint64_t size() const { return 4; }
66 virtual uint64_t objectAddress() const { return 0; }
67 virtual void copyRawContent(uint8_t buffer[]) const { }
68 virtual void setScope(Scope) { }
69
70private:
71
72 static ld::Section _s_section;
73};
74
75ld::Section ImageCachePointerAtom::_s_section("__DATA", "__nl_symbol_ptr", ld::Section::typeNonLazyPointer);
76
77
78
79class StubHelperHelperAtom : public ld::Atom {
80public:
81 StubHelperHelperAtom(ld::passes::stubs::Pass& pass)
82 : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever,
83 ld::Atom::scopeLinkageUnit, ld::Atom::typeStubHelper,
84 ld::Atom::symbolTableIn, false, false, false, ld::Atom::Alignment(2)),
85 _fixup1(28, ld::Fixup::k1of4, ld::Fixup::kindSetTargetAddress, compressedImageCache(pass)),
86 _fixup2(28, ld::Fixup::k2of4, ld::Fixup::kindSubtractTargetAddress, this),
87 _fixup3(28, ld::Fixup::k3of4, ld::Fixup::kindSubtractAddend, 16),
88 _fixup4(28, ld::Fixup::k4of4, ld::Fixup::kindStoreLittleEndian32),
89 _fixup5(32, ld::Fixup::k1of4, ld::Fixup::kindSetTargetAddress, compressedFastBinder(pass)),
90 _fixup6(32, ld::Fixup::k2of4, ld::Fixup::kindSubtractTargetAddress, this),
91 _fixup7(32, ld::Fixup::k3of4, ld::Fixup::kindSubtractAddend, 28),
92 _fixup8(32, ld::Fixup::k4of4, ld::Fixup::kindStoreLittleEndian32)
93 { pass.addAtom(*this); }
94
95 virtual ld::File* file() const { return NULL; }
a645023d
A
96 virtual const char* name() const { return " stub helpers"; }
97 virtual uint64_t size() const { return 36; }
98 virtual uint64_t objectAddress() const { return 0; }
99 virtual void copyRawContent(uint8_t buffer[]) const {
100 // push lazy-info-offset
101 OSWriteLittleInt32(&buffer[ 0], 0, 0xe52dc004); // str ip, [sp, #-4]!
102 // push address of dyld_mageLoaderCache
103 OSWriteLittleInt32(&buffer[ 4], 0, 0xe59fc010); // ldr ip, L1
104 OSWriteLittleInt32(&buffer[ 8], 0, 0xe08fc00c); // add ip, pc, ip
105 OSWriteLittleInt32(&buffer[12], 0, 0xe52dc004); // str ip, [sp, #-4]!
106 // jump through _fast_lazy_bind
107 OSWriteLittleInt32(&buffer[16], 0, 0xe59fc008); // ldr ip, L2
108 OSWriteLittleInt32(&buffer[20], 0, 0xe08fc00c); // add ip, pc, ip
109 OSWriteLittleInt32(&buffer[24], 0, 0xe59cf000); // ldr pc, [ip]
110 OSWriteLittleInt32(&buffer[28], 0, 0x00000000); // L1: .long fFastStubGOTAtom - (helperhelper+16)
111 OSWriteLittleInt32(&buffer[32], 0, 0x00000000); // L2: .long _fast_lazy_bind - (helperhelper+28)
112 }
113 virtual void setScope(Scope) { }
114 virtual ld::Fixup::iterator fixupsBegin() const { return (ld::Fixup*)&_fixup1; }
115 virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup8)[1]; }
116
117private:
118 static ld::Atom* compressedImageCache(ld::passes::stubs::Pass& pass) {
119 if ( pass.compressedImageCache == NULL )
120 pass.compressedImageCache = new ImageCachePointerAtom(pass);
121 return pass.compressedImageCache;
122 }
123 static ld::Atom* compressedFastBinder(ld::passes::stubs::Pass& pass) {
124 if ( pass.compressedFastBinderPointer == NULL )
125 pass.compressedFastBinderPointer = new FastBindingPointerAtom(pass);
126 return pass.compressedFastBinderPointer;
127 }
128
129 ld::Fixup _fixup1;
130 ld::Fixup _fixup2;
131 ld::Fixup _fixup3;
132 ld::Fixup _fixup4;
133 ld::Fixup _fixup5;
134 ld::Fixup _fixup6;
135 ld::Fixup _fixup7;
136 ld::Fixup _fixup8;
137
138 static ld::Section _s_section;
139};
140
141ld::Section StubHelperHelperAtom::_s_section("__TEXT", "__stub_helper", ld::Section::typeStubHelper);
142
143
144class StubHelperAtom : public ld::Atom {
145public:
146 StubHelperAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo,
147 const ld::Atom* lazyPointer)
148 : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever,
149 ld::Atom::scopeLinkageUnit, ld::Atom::typeStubHelper,
150 symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)),
151 _stubTo(stubTo),
152 _fixup1(4, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARMBranch24, helperHelper(pass)),
153 _fixup2(8, ld::Fixup::k1of2, ld::Fixup::kindSetLazyOffset, lazyPointer),
154 _fixup3(8, ld::Fixup::k2of2, ld::Fixup::kindStoreLittleEndian32) { }
155
156 virtual const ld::File* file() const { return _stubTo.file(); }
a645023d
A
157 virtual const char* name() const { return _stubTo.name(); }
158 virtual uint64_t size() const { return 12; }
159 virtual uint64_t objectAddress() const { return 0; }
160 virtual void copyRawContent(uint8_t buffer[]) const {
161 OSWriteLittleInt32(&buffer[0], 0, 0xe59fc000); // ldr ip, [pc, #0]
162 OSWriteLittleInt32(&buffer[4], 0, 0xea000000); // b _helperhelper
163 OSWriteLittleInt32(&buffer[8], 0, 0); // .long lazy-info-offset
164 }
165 virtual void setScope(Scope) { }
166 virtual ld::Fixup::iterator fixupsBegin() const { return (ld::Fixup*)&_fixup1; }
167 virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup3)[1]; }
168
169private:
170 static ld::Atom* helperHelper(ld::passes::stubs::Pass& pass) {
171 if ( pass.compressedHelperHelper == NULL )
172 pass.compressedHelperHelper = new StubHelperHelperAtom(pass);
173 return pass.compressedHelperHelper;
174 }
175 const ld::Atom& _stubTo;
176 ld::Fixup _fixup1;
177 ld::Fixup _fixup2;
178 ld::Fixup _fixup3;
179
180 static ld::Section _s_section;
181};
182
183ld::Section StubHelperAtom::_s_section("__TEXT", "__stub_helper", ld::Section::typeStubHelper);
184
185
186class ResolverHelperAtom : public ld::Atom {
187public:
188 ResolverHelperAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo,
189 const ld::Atom* lazyPointer)
190 : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever,
191 ld::Atom::scopeLinkageUnit, ld::Atom::typeStubHelper,
192 ld::Atom::symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)),
193 _stubTo(stubTo),
194 _fixup1( 4, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARMBranch24, &stubTo),
195 _fixup2(32, ld::Fixup::k1of4, ld::Fixup::kindSetTargetAddress, lazyPointer),
196 _fixup3(32, ld::Fixup::k2of4, ld::Fixup::kindSubtractTargetAddress, this),
197 _fixup4(32, ld::Fixup::k3of4, ld::Fixup::kindSubtractAddend, 20),
198 _fixup5(32, ld::Fixup::k4of4, ld::Fixup::kindStoreLittleEndian32) { }
199
200 virtual const ld::File* file() const { return _stubTo.file(); }
a645023d
A
201 virtual const char* name() const { return _stubTo.name(); }
202 virtual uint64_t size() const { return 36; }
203 virtual uint64_t objectAddress() const { return 0; }
204 virtual void copyRawContent(uint8_t buffer[]) const {
205 OSWriteLittleInt32(&buffer[ 0], 0, 0xe92d400f); // push {r0, r1, r2, r3, lr}
206 OSWriteLittleInt32(&buffer[ 4], 0, 0xebfffffd); // bl _foo
207 OSWriteLittleInt32(&buffer[ 8], 0, 0xe59fc010); // ldr ip, [pc, #16]
208 OSWriteLittleInt32(&buffer[12], 0, 0xe08fc00c); // add ip, pc, ip
209 OSWriteLittleInt32(&buffer[16], 0, 0xe58c0000); // str r0, [ip]
210 OSWriteLittleInt32(&buffer[20], 0, 0xe1a0c000); // mov ip, r0
211 OSWriteLittleInt32(&buffer[24], 0, 0xe8bd400f); // pop {r0, r1, r2, r3, lr}
212 OSWriteLittleInt32(&buffer[28], 0, 0xe12fff1c); // bx ip
213 OSWriteLittleInt32(&buffer[32], 0, 0x00000000); // .long foo$lazyptr - helper + 20
214 }
215 virtual void setScope(Scope) { }
216 virtual ld::Fixup::iterator fixupsBegin() const { return (ld::Fixup*)&_fixup1; }
217 virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup5)[1]; }
218
219private:
220 const ld::Atom& _stubTo;
221 ld::Fixup _fixup1;
222 ld::Fixup _fixup2;
223 ld::Fixup _fixup3;
224 ld::Fixup _fixup4;
225 ld::Fixup _fixup5;
226
227 static ld::Section _s_section;
228};
229
230ld::Section ResolverHelperAtom::_s_section("__TEXT", "__stub_helper", ld::Section::typeStubHelper);
231
232
233class LazyPointerAtom : public ld::Atom {
234public:
235 LazyPointerAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo,
236 bool stubToGlobalWeakDef, bool stubToResolver,
eaf282aa
A
237 bool weakImport, bool close, bool usingDataConst)
238 : ld::Atom(selectSection(close, stubToGlobalWeakDef, stubToResolver, usingDataConst),
239 ld::Atom::definitionRegular,
a645023d
A
240 ld::Atom::combineNever, ld::Atom::scopeLinkageUnit, ld::Atom::typeLazyPointer,
241 symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)),
242 _stubTo(stubTo),
243 _helper(pass, stubTo, this),
244 _resolverHelper(pass, stubTo, this),
245 _fixup1(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressLittleEndian32,
246 stubToResolver ? &_resolverHelper : (stubToGlobalWeakDef ? &stubTo : &_helper)),
eaf282aa 247 _fixup2(0, ld::Fixup::k1of1, ld::Fixup::kindLazyTarget, &stubTo) {
a645023d
A
248 _fixup2.weakImport = weakImport; pass.addAtom(*this);
249 if ( stubToResolver )
250 pass.addAtom(_resolverHelper);
251 else if ( !stubToGlobalWeakDef )
252 pass.addAtom(_helper);
253 }
254
255 virtual const ld::File* file() const { return _stubTo.file(); }
a645023d
A
256 virtual const char* name() const { return _stubTo.name(); }
257 virtual uint64_t size() const { return 4; }
258 virtual uint64_t objectAddress() const { return 0; }
259 virtual void copyRawContent(uint8_t buffer[]) const { }
260 virtual void setScope(Scope) { }
261 virtual ld::Fixup::iterator fixupsBegin() const { return (ld::Fixup*)&_fixup1; }
262 virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup2)[1]; }
263
264private:
eaf282aa
A
265 static ld::Section& selectSection(bool close, bool stubToGlobalWeakDef, bool stubToResolver, bool usingDataConst) {
266 if ( close )
267 return _s_sectionClose;
268 else if ( stubToGlobalWeakDef && usingDataConst )
269 return _s_sectionWeak;
270 else if ( stubToResolver && usingDataConst )
271 return _s_sectionResolver;
272 else
273 return _s_section;
274 }
275
a645023d
A
276 const ld::Atom& _stubTo;
277 StubHelperAtom _helper;
278 ResolverHelperAtom _resolverHelper;
279 ld::Fixup _fixup1;
280 ld::Fixup _fixup2;
281
282 static ld::Section _s_section;
283 static ld::Section _s_sectionClose;
eaf282aa
A
284 static ld::Section _s_sectionResolver;
285 static ld::Section _s_sectionWeak;
a645023d
A
286};
287
288ld::Section LazyPointerAtom::_s_section("__DATA", "__la_symbol_ptr", ld::Section::typeLazyPointer);
289ld::Section LazyPointerAtom::_s_sectionClose("__DATA", "__lazy_symbol", ld::Section::typeLazyPointerClose);
eaf282aa
A
290ld::Section LazyPointerAtom::_s_sectionResolver("__DATA_DIRTY", "__la_resolver", ld::Section::typeLazyPointer);
291ld::Section LazyPointerAtom::_s_sectionWeak("__DATA", "__la_weak_ptr", ld::Section::typeLazyPointer);
a645023d
A
292
293
ebf6f434
A
294class NonLazyPointerAtom : public ld::Atom {
295public:
e456bf10
A
296 NonLazyPointerAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo,
297 bool weakImport)
ebf6f434
A
298 : ld::Atom(_s_section, ld::Atom::definitionRegular,
299 ld::Atom::combineNever, ld::Atom::scopeLinkageUnit, ld::Atom::typeLazyPointer,
300 symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)),
301 _stubTo(stubTo),
302 _fixup1(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressLittleEndian32, &stubTo) {
e456bf10 303 _fixup1.weakImport = weakImport;
ebf6f434
A
304 pass.addAtom(*this);
305 }
306
307 virtual const ld::File* file() const { return _stubTo.file(); }
ebf6f434
A
308 virtual const char* name() const { return _stubTo.name(); }
309 virtual uint64_t size() const { return 4; }
310 virtual uint64_t objectAddress() const { return 0; }
311 virtual void copyRawContent(uint8_t buffer[]) const { }
312 virtual void setScope(Scope) { }
313 virtual ld::Fixup::iterator fixupsBegin() const { return (ld::Fixup*)&_fixup1; }
314 virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup1)[1]; }
315
316private:
317 const ld::Atom& _stubTo;
318 ld::Fixup _fixup1;
319
320 static ld::Section _s_section;
321 static ld::Section _s_sectionClose;
322};
323
324ld::Section NonLazyPointerAtom::_s_section("__DATA", "__nl_symbol_ptr", ld::Section::typeNonLazyPointer);
325
326
327class StubPICKextAtom : public ld::Atom {
328public:
e456bf10
A
329 StubPICKextAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo,
330 bool weakImport)
ebf6f434
A
331 : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever,
332 ld::Atom::scopeLinkageUnit, ld::Atom::typeStub,
e456bf10 333 symbolTableNotIn, false, true, false, ld::Atom::Alignment(2)),
ebf6f434 334 _stubTo(stubTo),
e456bf10 335 _nonLazyPointer(pass, stubTo, weakImport),
ebf6f434
A
336 _fixup1(0, ld::Fixup::k1of4, ld::Fixup::kindSetTargetAddress, &_nonLazyPointer),
337 _fixup2(0, ld::Fixup::k2of4, ld::Fixup::kindSubtractTargetAddress, this),
338 _fixup3(0, ld::Fixup::k3of4, ld::Fixup::kindSubtractAddend, 12),
339 _fixup4(0, ld::Fixup::k4of4, ld::Fixup::kindStoreThumbLow16),
340 _fixup5(4, ld::Fixup::k1of4, ld::Fixup::kindSetTargetAddress, &_nonLazyPointer),
341 _fixup6(4, ld::Fixup::k2of4, ld::Fixup::kindSubtractTargetAddress, this),
342 _fixup7(4, ld::Fixup::k3of4, ld::Fixup::kindSubtractAddend, 12),
343 _fixup8(4, ld::Fixup::k4of4, ld::Fixup::kindStoreThumbHigh16) {
ebf6f434 344 asprintf((char**)&_name, "%s.stub", _stubTo.name());
e456bf10 345 pass.addAtom(*this);
ebf6f434
A
346 }
347
348 virtual const ld::File* file() const { return _stubTo.file(); }
ebf6f434
A
349 virtual const char* name() const { return _name; }
350 virtual uint64_t size() const { return 16; }
351 virtual uint64_t objectAddress() const { return 0; }
352 virtual void copyRawContent(uint8_t buffer[]) const {
353 OSWriteLittleInt32(&buffer[ 0], 0, 0x0c00f240); // movw ip, #lo(nlp - L1)
354 OSWriteLittleInt32(&buffer[ 4], 0, 0x0c00f2c0); // movt ip, #hi(nlp - L1)
355 OSWriteLittleInt16(&buffer[ 8], 0, 0x44fc); // add ip, pc
356 OSWriteLittleInt32(&buffer[10], 0, 0xc000f8dc); // ldr.w ip, [ip]
357 OSWriteLittleInt16(&buffer[14], 0, 0x4760); // bx ip
358 }
359 virtual void setScope(Scope) { }
360 virtual ld::Fixup::iterator fixupsBegin() const { return (ld::Fixup*)&_fixup1; }
361 virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup8)[1]; }
362
363private:
364 const ld::Atom& _stubTo;
365 const char* _name;
366 NonLazyPointerAtom _nonLazyPointer;
367 ld::Fixup _fixup1;
368 ld::Fixup _fixup2;
369 ld::Fixup _fixup3;
370 ld::Fixup _fixup4;
371 ld::Fixup _fixup5;
372 ld::Fixup _fixup6;
373 ld::Fixup _fixup7;
374 ld::Fixup _fixup8;
375
376 static ld::Section _s_section;
377};
378
379ld::Section StubPICKextAtom::_s_section("__TEXT", "__stub", ld::Section::typeCode);
380
381
a645023d
A
382
383class StubPICAtom : public ld::Atom {
384public:
385 StubPICAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo,
eaf282aa 386 bool stubToGlobalWeakDef, bool stubToResolver, bool weakImport, bool usingDataConst)
a645023d
A
387 : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever,
388 ld::Atom::scopeLinkageUnit, ld::Atom::typeStub,
389 symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)),
390 _stubTo(stubTo),
eaf282aa 391 _lazyPointer(pass, stubTo, stubToGlobalWeakDef, stubToResolver, weakImport, false, usingDataConst),
a645023d
A
392 _fixup1(12, ld::Fixup::k1of4, ld::Fixup::kindSetTargetAddress, &_lazyPointer),
393 _fixup2(12, ld::Fixup::k2of4, ld::Fixup::kindSubtractTargetAddress, this),
394 _fixup3(12, ld::Fixup::k3of4, ld::Fixup::kindSubtractAddend, 12),
395 _fixup4(12, ld::Fixup::k4of4, ld::Fixup::kindStoreLittleEndian32)
396 { pass.addAtom(*this); }
397
398 virtual const ld::File* file() const { return _stubTo.file(); }
a645023d
A
399 virtual const char* name() const { return _stubTo.name(); }
400 virtual uint64_t size() const { return 16; }
401 virtual uint64_t objectAddress() const { return 0; }
402 virtual void copyRawContent(uint8_t buffer[]) const {
403 OSWriteLittleInt32(&buffer[ 0], 0, 0xe59fc004); // ldr ip, pc + 12
404 OSWriteLittleInt32(&buffer[ 4], 0, 0xe08fc00c); // add ip, pc, ip
405 OSWriteLittleInt32(&buffer[ 8], 0, 0xe59cf000); // ldr pc, [ip]
406 OSWriteLittleInt32(&buffer[12], 0, 0x00000000); // .long L_foo$lazy_ptr - (L1$scv + 8)
407 }
408 virtual void setScope(Scope) { }
409 virtual ld::Fixup::iterator fixupsBegin() const { return (ld::Fixup*)&_fixup1; }
410 virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup4)[1]; }
411
412private:
413 const ld::Atom& _stubTo;
414 LazyPointerAtom _lazyPointer;
415 ld::Fixup _fixup1;
416 ld::Fixup _fixup2;
417 ld::Fixup _fixup3;
418 ld::Fixup _fixup4;
419
420 static ld::Section _s_section;
421};
422
423ld::Section StubPICAtom::_s_section("__TEXT", "__picsymbolstub4", ld::Section::typeStub);
424
425
426
427class StubNoPICAtom : public ld::Atom {
428public:
429 StubNoPICAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo,
430 bool stubToGlobalWeakDef, bool stubToResolver, bool weakImport)
431 : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever,
432 ld::Atom::scopeLinkageUnit, ld::Atom::typeStub,
433 symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)),
434 _stubTo(stubTo),
eaf282aa 435 _lazyPointer(pass, stubTo, stubToGlobalWeakDef, stubToResolver, weakImport, false, false),
a645023d
A
436 _fixup(8, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressLittleEndian32, &_lazyPointer)
437 { pass.addAtom(*this); }
438
439 virtual const ld::File* file() const { return _stubTo.file(); }
a645023d
A
440 virtual const char* name() const { return _stubTo.name(); }
441 virtual uint64_t size() const { return 12; }
442 virtual uint64_t objectAddress() const { return 0; }
443 virtual void copyRawContent(uint8_t buffer[]) const {
444 OSWriteLittleInt32(&buffer[ 0], 0, 0xe59fc000); // ldr ip, [pc, #0]
445 OSWriteLittleInt32(&buffer[ 4], 0, 0xe59cf000); // ldr pc, [ip]
446 OSWriteLittleInt32(&buffer[ 8], 0, 0x00000000); // .long L_foo$lazy_ptr
447 }
448 virtual void setScope(Scope) { }
449 virtual ld::Fixup::iterator fixupsBegin() const { return (ld::Fixup*)&_fixup; }
450 virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup)[1]; }
451
452private:
453 const ld::Atom& _stubTo;
454 LazyPointerAtom _lazyPointer;
455 ld::Fixup _fixup;
456
457 static ld::Section _s_section;
458};
459
460ld::Section StubNoPICAtom::_s_section("__TEXT", "__symbol_stub4", ld::Section::typeStub);
461
462
463
464
465class StubCloseAtom : public ld::Atom {
466public:
467 StubCloseAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo,
468 bool stubToGlobalWeakDef, bool stubToResolver, bool weakImport)
469 : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever,
470 ld::Atom::scopeLinkageUnit, ld::Atom::typeStub,
471 symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)),
472 _stubTo(stubTo),
eaf282aa 473 _lazyPointer(pass, stubTo, stubToGlobalWeakDef, stubToResolver, weakImport, true, false),
a645023d
A
474 _fixup(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARMLoad12, &_lazyPointer)
475 { pass.addAtom(*this); }
476
477 virtual const ld::File* file() const { return _stubTo.file(); }
a645023d
A
478 virtual const char* name() const { return _stubTo.name(); }
479 virtual uint64_t size() const { return 4; }
480 virtual uint64_t objectAddress() const { return 0; }
481 virtual void copyRawContent(uint8_t buffer[]) const {
482 OSWriteLittleInt32(&buffer[ 0], 0, 0xE59FF000); // ldr pc, [pc, #foo$lazy_ptr]
483 }
484 virtual void setScope(Scope) { }
485 virtual ld::Fixup::iterator fixupsBegin() const { return (ld::Fixup*)&_fixup; }
486 virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup)[1]; }
487
488private:
489 const ld::Atom& _stubTo;
490 LazyPointerAtom _lazyPointer;
491 ld::Fixup _fixup;
492
493 static ld::Section _s_section;
494};
495
496ld::Section StubCloseAtom::_s_section("__TEXT", "__symbolstub1", ld::Section::typeStubClose);
497
498
499
500
501} // namespace arm
502