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