]>
Commit | Line | Data |
---|---|---|
f80fe69f A |
1 | /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- |
2 | * | |
3 | * Copyright (c) 2010-2013 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 | |
27 | namespace arm64 { | |
28 | ||
29 | ||
30 | ||
31 | class FastBindingPointerAtom : public ld::Atom { | |
32 | public: | |
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); } | |
40 | ||
41 | virtual const ld::File* file() const { return NULL; } | |
42 | virtual const char* name() const { return "fast binder pointer"; } | |
43 | virtual uint64_t size() const { return 8; } | |
44 | virtual uint64_t objectAddress() const { return 0; } | |
45 | virtual void copyRawContent(uint8_t buffer[]) const { } | |
46 | virtual void setScope(Scope) { } | |
47 | virtual ld::Fixup::iterator fixupsBegin() const { return &_fixup; } | |
48 | virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup)[1]; } | |
49 | ||
50 | private: | |
51 | mutable ld::Fixup _fixup; | |
52 | ||
53 | static ld::Section _s_section; | |
54 | }; | |
55 | ||
56 | ld::Section FastBindingPointerAtom::_s_section("__DATA", "__got", ld::Section::typeNonLazyPointer); | |
57 | ||
58 | ||
59 | class ImageCachePointerAtom : public ld::Atom { | |
60 | public: | |
61 | ImageCachePointerAtom(ld::passes::stubs::Pass& pass) | |
62 | : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, | |
63 | ld::Atom::scopeLinkageUnit, ld::Atom::typeNonLazyPointer, | |
64 | symbolTableNotIn, false, false, false, ld::Atom::Alignment(3)) { pass.addAtom(*this); } | |
65 | ||
66 | virtual const ld::File* file() const { return NULL; } | |
67 | virtual const char* name() const { return "image cache pointer"; } | |
68 | virtual uint64_t size() const { return 8; } | |
69 | virtual uint64_t objectAddress() const { return 0; } | |
70 | virtual void copyRawContent(uint8_t buffer[]) const { } | |
71 | virtual void setScope(Scope) { } | |
72 | ||
73 | private: | |
74 | ||
75 | static ld::Section _s_section; | |
76 | }; | |
77 | ||
78 | ld::Section ImageCachePointerAtom::_s_section("__DATA", "__got", ld::Section::typeNonLazyPointer); | |
79 | ||
80 | ||
81 | ||
82 | ||
83 | ||
84 | // | |
85 | // The stub-helper-helper is the common code factored out of each helper function. | |
86 | // It is in the same section as the stub-helpers. | |
87 | // Similar to the PLT0 entry in ELF. | |
88 | // | |
89 | class StubHelperHelperAtom : public ld::Atom { | |
90 | public: | |
91 | StubHelperHelperAtom(ld::passes::stubs::Pass& pass) | |
92 | : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, | |
93 | ld::Atom::scopeLinkageUnit, ld::Atom::typeStubHelper, | |
94 | symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)), | |
95 | _fixup1(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64Page21, compressedImageCache(pass)), | |
96 | _fixup2(4, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64PageOff12, compressedImageCache(pass)), | |
97 | _fixup3(12, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64Page21, compressedFastBinder(pass)), | |
9543cb2f A |
98 | _fixup4(16, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64PageOff12, compressedFastBinder(pass)), |
99 | _fixup5(ld::Fixup::kindLinkerOptimizationHint, LOH_ARM64_ADRP_ADD, 0, 4), | |
100 | _fixup6(ld::Fixup::kindLinkerOptimizationHint, LOH_ARM64_ADRP_LDR, 12, 16) | |
f80fe69f A |
101 | { pass.addAtom(*this); } |
102 | ||
103 | virtual ld::File* file() const { return NULL; } | |
104 | virtual const char* name() const { return "helper helper"; } | |
105 | virtual uint64_t size() const { return 24; } | |
106 | virtual uint64_t objectAddress() const { return 0; } | |
107 | virtual void copyRawContent(uint8_t buffer[]) const { | |
108 | OSWriteLittleInt32(&buffer[ 0], 0, 0x90000011); // ADRP X17, dyld_mageLoaderCache@page | |
109 | OSWriteLittleInt32(&buffer[ 4], 0, 0x91000231); // ADD X17, X17, dyld_mageLoaderCache@pageoff | |
110 | OSWriteLittleInt32(&buffer[ 8], 0, 0xA9BF47F0); // STP X16/X17, [SP, #-16]! | |
111 | OSWriteLittleInt32(&buffer[12], 0, 0x90000010); // ADRP X16, _fast_lazy_bind@page | |
112 | OSWriteLittleInt32(&buffer[16], 0, 0xF9400210); // LDR X16, [X16,_fast_lazy_bind@pageoff] | |
113 | OSWriteLittleInt32(&buffer[20], 0, 0xD61F0200); // BR X16 | |
114 | } | |
115 | virtual void setScope(Scope) { } | |
116 | virtual ld::Fixup::iterator fixupsBegin() const { return &_fixup1; } | |
9543cb2f | 117 | virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup6)[1]; } |
f80fe69f A |
118 | |
119 | private: | |
120 | static ld::Atom* compressedImageCache(ld::passes::stubs::Pass& pass) { | |
121 | if ( pass.compressedImageCache == NULL ) | |
122 | pass.compressedImageCache = new ImageCachePointerAtom(pass); | |
123 | return pass.compressedImageCache; | |
124 | } | |
125 | static ld::Atom* compressedFastBinder(ld::passes::stubs::Pass& pass) { | |
126 | if ( pass.compressedFastBinderPointer == NULL ) | |
127 | pass.compressedFastBinderPointer = new FastBindingPointerAtom(pass); | |
128 | return pass.compressedFastBinderPointer; | |
129 | } | |
130 | ||
131 | mutable ld::Fixup _fixup1; | |
132 | ld::Fixup _fixup2; | |
133 | ld::Fixup _fixup3; | |
134 | ld::Fixup _fixup4; | |
9543cb2f A |
135 | ld::Fixup _fixup5; |
136 | ld::Fixup _fixup6; | |
f80fe69f A |
137 | |
138 | static ld::Section _s_section; | |
139 | }; | |
140 | ||
141 | ld::Section StubHelperHelperAtom::_s_section("__TEXT", "__stub_helper", ld::Section::typeStubHelper); | |
142 | ||
143 | ||
144 | ||
145 | class StubHelperAtom : public ld::Atom { | |
146 | public: | |
147 | StubHelperAtom(ld::passes::stubs::Pass& pass, const ld::Atom* lazyPointer, | |
148 | const ld::Atom& stubTo) | |
149 | : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, | |
150 | ld::Atom::scopeLinkageUnit, ld::Atom::typeStubHelper, | |
e456bf10 | 151 | symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)), |
f80fe69f A |
152 | _stubTo(stubTo), |
153 | _fixup1(4, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64Branch26, helperHelper(pass)), | |
154 | _fixup2(8, ld::Fixup::k1of2, ld::Fixup::kindSetLazyOffset, lazyPointer), | |
155 | _fixup3(8, ld::Fixup::k2of2, ld::Fixup::kindStoreLittleEndian32) { } | |
156 | ||
157 | virtual const ld::File* file() const { return _stubTo.file(); } | |
158 | virtual const char* name() const { return _stubTo.name(); } | |
159 | virtual uint64_t size() const { return 12; } | |
160 | virtual uint64_t objectAddress() const { return 0; } | |
161 | virtual void copyRawContent(uint8_t buffer[]) const { | |
162 | OSWriteLittleInt32(&buffer[0], 0, 0x18000050); // LDR W16, L0 | |
163 | OSWriteLittleInt32(&buffer[4], 0, 0x14000000); // B helperhelper | |
164 | OSWriteLittleInt32(&buffer[8], 0, 0x00000000); // L0: .long 0 | |
165 | } | |
166 | virtual void setScope(Scope) { } | |
167 | virtual ld::Fixup::iterator fixupsBegin() const { return &_fixup1; } | |
168 | virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup3)[1]; } | |
169 | ||
170 | private: | |
171 | static ld::Atom* helperHelper(ld::passes::stubs::Pass& pass) { | |
172 | if ( pass.compressedHelperHelper == NULL ) | |
173 | pass.compressedHelperHelper = new StubHelperHelperAtom(pass); | |
174 | return pass.compressedHelperHelper; | |
175 | } | |
176 | ||
177 | const ld::Atom& _stubTo; | |
178 | mutable ld::Fixup _fixup1; | |
179 | ld::Fixup _fixup2; | |
180 | ld::Fixup _fixup3; | |
181 | ||
182 | static ld::Section _s_section; | |
183 | }; | |
184 | ||
185 | ld::Section StubHelperAtom::_s_section("__TEXT", "__stub_helper", ld::Section::typeStubHelper); | |
186 | ||
187 | ||
188 | class ResolverHelperAtom : public ld::Atom { | |
189 | public: | |
190 | ResolverHelperAtom(ld::passes::stubs::Pass& pass, const ld::Atom* lazyPointer, | |
191 | const ld::Atom& stubTo) | |
192 | : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, | |
193 | ld::Atom::scopeLinkageUnit, ld::Atom::typeStubHelper, | |
e456bf10 | 194 | symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)), |
f80fe69f A |
195 | _stubTo(stubTo), |
196 | _fixup1(24, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64Branch26, &stubTo), | |
197 | _fixup2(28, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64Page21, lazyPointer), | |
198 | _fixup3(32, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64PageOff12, lazyPointer) { } | |
199 | ||
200 | virtual const ld::File* file() const { return _stubTo.file(); } | |
201 | virtual const char* name() const { return _stubTo.name(); } | |
202 | virtual uint64_t size() const { return 68; } | |
203 | virtual uint64_t objectAddress() const { return 0; } | |
204 | virtual void copyRawContent(uint8_t buffer[]) const { | |
205 | OSWriteLittleInt32(&buffer[ 0], 0, 0xa9bf7bfd); // stp fp, lr, [sp, #-16]! | |
206 | OSWriteLittleInt32(&buffer[ 4], 0, 0x910003fd); // mov fp, sp | |
207 | OSWriteLittleInt32(&buffer[ 8], 0, 0xa9bf03e1); // stp x1, x0, [sp, #-16]! | |
208 | OSWriteLittleInt32(&buffer[12], 0, 0xa9bf0be3); // stp x3, x2, [sp, #-16]! | |
209 | OSWriteLittleInt32(&buffer[16], 0, 0xa9bf13e5); // stp x5, x4, [sp, #-16]! | |
210 | OSWriteLittleInt32(&buffer[20], 0, 0xa9bf1be7); // stp x7, x6, [sp, #-16]! | |
211 | OSWriteLittleInt32(&buffer[24], 0, 0x94000000); // bl _foo | |
212 | OSWriteLittleInt32(&buffer[28], 0, 0x90000010); // adrp x16, lazy_pointer@PAGE | |
213 | OSWriteLittleInt32(&buffer[32], 0, 0x91000210); // add x16, x16, lazy_pointer@PAGEOFF | |
214 | OSWriteLittleInt32(&buffer[36], 0, 0xf9000200); // str x0, [x16] | |
215 | OSWriteLittleInt32(&buffer[40], 0, 0xaa0003f0); // mov x16, x0 | |
216 | OSWriteLittleInt32(&buffer[44], 0, 0xa8c11be7); // ldp x7, x6, [sp], #16 | |
217 | OSWriteLittleInt32(&buffer[48], 0, 0xa8c113e5); // ldp x5, x4, [sp], #16 | |
218 | OSWriteLittleInt32(&buffer[52], 0, 0xa8c10be3); // ldp x3, x2, [sp], #16 | |
219 | OSWriteLittleInt32(&buffer[56], 0, 0xa8c103e1); // ldp x1, x0, [sp], #16 | |
220 | OSWriteLittleInt32(&buffer[60], 0, 0xa8c17bfd); // ldp fp, lr, [sp], #16 | |
221 | OSWriteLittleInt32(&buffer[64], 0, 0xd61f0200); // br x16 | |
222 | } | |
223 | virtual void setScope(Scope) { } | |
224 | virtual ld::Fixup::iterator fixupsBegin() const { return &_fixup1; } | |
225 | virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup3)[1]; } | |
226 | ||
227 | private: | |
228 | ||
229 | const ld::Atom& _stubTo; | |
230 | mutable ld::Fixup _fixup1; | |
231 | ld::Fixup _fixup2; | |
232 | ld::Fixup _fixup3; | |
233 | ||
234 | static ld::Section _s_section; | |
235 | }; | |
236 | ||
237 | ld::Section ResolverHelperAtom::_s_section("__TEXT", "__stub_helper", ld::Section::typeStubHelper); | |
238 | ||
239 | ||
240 | ||
241 | class LazyPointerAtom : public ld::Atom { | |
242 | public: | |
243 | LazyPointerAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo, | |
eaf282aa A |
244 | bool stubToGlobalWeakDef, bool stubToResolver, bool weakImport, bool dataConstUsed) |
245 | : ld::Atom(selectSection(stubToGlobalWeakDef, stubToResolver, dataConstUsed), | |
246 | ld::Atom::definitionRegular, ld::Atom::combineNever, | |
f80fe69f A |
247 | ld::Atom::scopeTranslationUnit, ld::Atom::typeLazyPointer, |
248 | symbolTableNotIn, false, false, false, ld::Atom::Alignment(3)), | |
249 | _stubTo(stubTo), | |
250 | _helper(pass, this, stubTo), | |
251 | _resolverHelper(pass, this, stubTo), | |
252 | _fixup1(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressLittleEndian64, | |
253 | stubToResolver ? &_resolverHelper : | |
254 | (stubToGlobalWeakDef ? &stubTo : &_helper)), | |
255 | _fixup2(0, ld::Fixup::k1of1, ld::Fixup::kindLazyTarget, &stubTo) { | |
256 | _fixup2.weakImport = weakImport; pass.addAtom(*this); | |
257 | if ( stubToResolver ) | |
258 | pass.addAtom(_resolverHelper); | |
259 | else if ( !stubToGlobalWeakDef ) | |
260 | pass.addAtom(_helper); | |
261 | } | |
262 | ||
263 | virtual const ld::File* file() const { return _stubTo.file(); } | |
264 | virtual const char* name() const { return _stubTo.name(); } | |
265 | virtual uint64_t size() const { return 8; } | |
266 | virtual uint64_t objectAddress() const { return 0; } | |
267 | virtual void copyRawContent(uint8_t buffer[]) const { } | |
268 | virtual void setScope(Scope) { } | |
269 | virtual ld::Fixup::iterator fixupsBegin() const { return &_fixup1; } | |
270 | virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup2)[1]; } | |
271 | ||
272 | private: | |
eaf282aa A |
273 | static ld::Section& selectSection(bool stubToGlobalWeakDef, bool stubToResolver, bool dataConstUsed) { |
274 | if ( stubToGlobalWeakDef && dataConstUsed ) | |
275 | return _s_sectionWeak; | |
276 | else if ( stubToResolver && dataConstUsed ) | |
277 | return _s_sectionResolver; | |
278 | else | |
279 | return _s_section; | |
280 | } | |
281 | ||
f80fe69f A |
282 | const ld::Atom& _stubTo; |
283 | StubHelperAtom _helper; | |
284 | ResolverHelperAtom _resolverHelper; | |
285 | mutable ld::Fixup _fixup1; | |
286 | ld::Fixup _fixup2; | |
287 | ||
288 | static ld::Section _s_section; | |
eaf282aa A |
289 | static ld::Section _s_sectionResolver; |
290 | static ld::Section _s_sectionWeak; | |
f80fe69f A |
291 | }; |
292 | ||
293 | ld::Section LazyPointerAtom::_s_section("__DATA", "__la_symbol_ptr", ld::Section::typeLazyPointer); | |
eaf282aa A |
294 | ld::Section LazyPointerAtom::_s_sectionResolver("__DATA_DIRTY", "__la_resolver", ld::Section::typeLazyPointer); |
295 | ld::Section LazyPointerAtom::_s_sectionWeak("__DATA", "__la_weak_ptr", ld::Section::typeLazyPointer); | |
f80fe69f A |
296 | |
297 | ||
298 | class StubAtom : public ld::Atom { | |
299 | public: | |
300 | StubAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo, | |
eaf282aa | 301 | bool stubToGlobalWeakDef, bool stubToResolver, bool weakImport, bool dataConstUsed) |
f80fe69f A |
302 | : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, |
303 | ld::Atom::scopeLinkageUnit, ld::Atom::typeStub, | |
e456bf10 | 304 | symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)), |
f80fe69f | 305 | _stubTo(stubTo), |
eaf282aa | 306 | _lazyPointer(pass, stubTo, stubToGlobalWeakDef, stubToResolver, weakImport, dataConstUsed), |
f80fe69f | 307 | _fixup1(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64Page21, &_lazyPointer), |
9543cb2f A |
308 | _fixup2(4, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64PageOff12, &_lazyPointer), |
309 | _fixup3(ld::Fixup::kindLinkerOptimizationHint, LOH_ARM64_ADRP_LDR, 0, 4) | |
310 | { pass.addAtom(*this); } | |
f80fe69f A |
311 | |
312 | virtual const ld::File* file() const { return _stubTo.file(); } | |
313 | virtual const char* name() const { return _stubTo.name(); } | |
314 | virtual uint64_t size() const { return 12; } | |
315 | virtual uint64_t objectAddress() const { return 0; } | |
316 | virtual void copyRawContent(uint8_t buffer[]) const { | |
317 | OSWriteLittleInt32(&buffer[0], 0, 0x90000010); // ADRP X16, lazy_pointer@page | |
318 | OSWriteLittleInt32(&buffer[4], 0, 0xF9400210); // LDR X16, [X16, lazy_pointer@pageoff] | |
319 | OSWriteLittleInt32(&buffer[8], 0, 0xD61F0200); // BR X16 | |
320 | } | |
321 | virtual void setScope(Scope) { } | |
322 | virtual ld::Fixup::iterator fixupsBegin() const { return &_fixup1; } | |
9543cb2f | 323 | virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup3)[1]; } |
f80fe69f A |
324 | |
325 | private: | |
326 | const ld::Atom& _stubTo; | |
327 | LazyPointerAtom _lazyPointer; | |
328 | mutable ld::Fixup _fixup1; | |
329 | mutable ld::Fixup _fixup2; | |
9543cb2f | 330 | mutable ld::Fixup _fixup3; |
f80fe69f A |
331 | |
332 | static ld::Section _s_section; | |
333 | }; | |
334 | ||
335 | ld::Section StubAtom::_s_section("__TEXT", "__stubs", ld::Section::typeStub); | |
336 | ||
337 | ||
338 | ||
339 | class NonLazyPointerAtom : public ld::Atom { | |
340 | public: | |
e456bf10 A |
341 | NonLazyPointerAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo, |
342 | bool weakImport) | |
f80fe69f A |
343 | : ld::Atom(_s_section, ld::Atom::definitionRegular, |
344 | ld::Atom::combineNever, ld::Atom::scopeLinkageUnit, ld::Atom::typeNonLazyPointer, | |
345 | symbolTableNotIn, false, false, false, ld::Atom::Alignment(3)), | |
346 | _stubTo(stubTo), | |
347 | _fixup1(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressLittleEndian64, &stubTo) { | |
e456bf10 | 348 | _fixup1.weakImport = weakImport; |
f80fe69f A |
349 | pass.addAtom(*this); |
350 | } | |
351 | ||
352 | virtual const ld::File* file() const { return _stubTo.file(); } | |
353 | virtual const char* name() const { return _stubTo.name(); } | |
354 | virtual uint64_t size() const { return 8; } | |
355 | virtual uint64_t objectAddress() const { return 0; } | |
356 | virtual void copyRawContent(uint8_t buffer[]) const { } | |
357 | virtual void setScope(Scope) { } | |
358 | virtual ld::Fixup::iterator fixupsBegin() const { return (ld::Fixup*)&_fixup1; } | |
359 | virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup1)[1]; } | |
360 | ||
361 | private: | |
362 | const ld::Atom& _stubTo; | |
363 | ld::Fixup _fixup1; | |
364 | ||
365 | static ld::Section _s_section; | |
366 | }; | |
367 | ||
368 | ld::Section NonLazyPointerAtom::_s_section("__DATA", "__got", ld::Section::typeNonLazyPointer); | |
369 | ||
370 | ||
e456bf10 | 371 | class NonLazyStubAtom : public ld::Atom { |
f80fe69f | 372 | public: |
e456bf10 A |
373 | NonLazyStubAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo, |
374 | bool weakImport) | |
f80fe69f A |
375 | : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, |
376 | ld::Atom::scopeLinkageUnit, ld::Atom::typeStub, | |
e456bf10 | 377 | symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)), |
f80fe69f | 378 | _stubTo(stubTo), |
e456bf10 | 379 | _nonLazyPointer(pass, stubTo, weakImport), |
f80fe69f | 380 | _fixup1(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64Page21, &_nonLazyPointer), |
e456bf10 | 381 | _fixup2(4, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64PageOff12, &_nonLazyPointer) { |
f80fe69f | 382 | asprintf((char**)&_name, "%s.stub", _stubTo.name()); |
e456bf10 | 383 | pass.addAtom(*this); |
f80fe69f A |
384 | } |
385 | ||
386 | virtual const ld::File* file() const { return _stubTo.file(); } | |
387 | virtual const char* name() const { return _name; } | |
388 | virtual uint64_t size() const { return 12; } | |
389 | virtual uint64_t objectAddress() const { return 0; } | |
390 | virtual void copyRawContent(uint8_t buffer[]) const { | |
391 | OSWriteLittleInt32(&buffer[0], 0, 0x90000010); // ADRP X16, non_lazy_pointer@page | |
392 | OSWriteLittleInt32(&buffer[4], 0, 0xF9400210); // LDR X16, [X16, non_lazy_pointer@pageoff] | |
393 | OSWriteLittleInt32(&buffer[8], 0, 0xD61F0200); // BR X16 | |
394 | } | |
395 | virtual void setScope(Scope) { } | |
396 | virtual ld::Fixup::iterator fixupsBegin() const { return &_fixup1; } | |
397 | virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup2)[1]; } | |
398 | ||
399 | private: | |
400 | const ld::Atom& _stubTo; | |
401 | const char* _name; | |
402 | NonLazyPointerAtom _nonLazyPointer; | |
403 | mutable ld::Fixup _fixup1; | |
404 | mutable ld::Fixup _fixup2; | |
405 | ||
406 | static ld::Section _s_section; | |
407 | }; | |
408 | ||
e456bf10 | 409 | ld::Section NonLazyStubAtom::_s_section("__TEXT", "__stubs", ld::Section::typeStub); |
f80fe69f A |
410 | |
411 | ||
0a8dc3df | 412 | } // namespace arm64 |
f80fe69f | 413 | |
e456bf10 A |
414 | #if SUPPORT_ARCH_arm64e |
415 | ||
416 | // already in ld::passes::stubs namespace | |
417 | namespace arm64e { | |
418 | ||
419 | ||
420 | ||
421 | class FastBindingPointerAtom : public ld::Atom { | |
422 | public: | |
423 | FastBindingPointerAtom(ld::passes::stubs::Pass& pass) | |
424 | : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, | |
425 | ld::Atom::scopeLinkageUnit, ld::Atom::typeNonLazyPointer, | |
426 | symbolTableNotIn, false, false, false, ld::Atom::Alignment(3)), | |
427 | _fixup(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressLittleEndian64, | |
428 | pass.internal()->compressedFastBinderProxy) | |
429 | { pass.addAtom(*this); } | |
430 | ||
431 | virtual const ld::File* file() const { return NULL; } | |
432 | virtual const char* name() const { return "fast binder pointer"; } | |
433 | virtual uint64_t size() const { return 8; } | |
434 | virtual uint64_t objectAddress() const { return 0; } | |
435 | virtual void copyRawContent(uint8_t buffer[]) const { } | |
436 | virtual void setScope(Scope) { } | |
437 | virtual ld::Fixup::iterator fixupsBegin() const { return &_fixup; } | |
438 | virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup)[1]; } | |
439 | ||
440 | private: | |
441 | mutable ld::Fixup _fixup; | |
442 | ||
443 | static ld::Section _s_section; | |
444 | }; | |
445 | ||
446 | ld::Section FastBindingPointerAtom::_s_section("__DATA", "__got", ld::Section::typeNonLazyPointer); | |
447 | ||
448 | ||
449 | class ImageCachePointerAtom : public ld::Atom { | |
450 | public: | |
451 | ImageCachePointerAtom(ld::passes::stubs::Pass& pass) | |
452 | : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, | |
453 | ld::Atom::scopeLinkageUnit, ld::Atom::typeNonLazyPointer, | |
454 | symbolTableNotIn, false, false, false, ld::Atom::Alignment(3)) { pass.addAtom(*this); } | |
455 | ||
456 | virtual const ld::File* file() const { return NULL; } | |
457 | virtual const char* name() const { return "image cache pointer"; } | |
458 | virtual uint64_t size() const { return 8; } | |
459 | virtual uint64_t objectAddress() const { return 0; } | |
460 | virtual void copyRawContent(uint8_t buffer[]) const { } | |
461 | virtual void setScope(Scope) { } | |
462 | ||
463 | private: | |
464 | ||
465 | static ld::Section _s_section; | |
466 | }; | |
467 | ||
468 | ld::Section ImageCachePointerAtom::_s_section("__DATA", "__got", ld::Section::typeNonLazyPointer); | |
469 | ||
470 | ||
471 | ||
472 | ||
473 | ||
474 | // | |
475 | // The stub-helper-helper is the common code factored out of each helper function. | |
476 | // It is in the same section as the stub-helpers. | |
477 | // Similar to the PLT0 entry in ELF. | |
478 | // | |
479 | class StubHelperHelperAtom : public ld::Atom { | |
480 | public: | |
481 | StubHelperHelperAtom(ld::passes::stubs::Pass& pass) | |
482 | : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, | |
483 | ld::Atom::scopeLinkageUnit, ld::Atom::typeStubHelper, | |
484 | symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)), | |
485 | _fixup1(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64Page21, compressedImageCache(pass)), | |
486 | _fixup2(4, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64PageOff12, compressedImageCache(pass)), | |
487 | _fixup3(12, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64Page21, compressedFastBinder(pass)), | |
488 | _fixup4(16, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64PageOff12, compressedFastBinder(pass)), | |
489 | _fixup5(ld::Fixup::kindLinkerOptimizationHint, LOH_ARM64_ADRP_ADD, 0, 4), | |
490 | _fixup6(ld::Fixup::kindLinkerOptimizationHint, LOH_ARM64_ADRP_LDR, 12, 16) | |
491 | { pass.addAtom(*this); } | |
492 | ||
493 | virtual ld::File* file() const { return NULL; } | |
494 | virtual const char* name() const { return "helper helper"; } | |
495 | virtual uint64_t size() const { return 24; } | |
496 | virtual uint64_t objectAddress() const { return 0; } | |
497 | virtual void copyRawContent(uint8_t buffer[]) const { | |
498 | OSWriteLittleInt32(&buffer[ 0], 0, 0x90000011); // ADRP X17, dyld_mageLoaderCache@page | |
499 | OSWriteLittleInt32(&buffer[ 4], 0, 0x91000231); // ADD X17, X17, dyld_mageLoaderCache@pageoff | |
500 | OSWriteLittleInt32(&buffer[ 8], 0, 0xA9BF47F0); // STP X16/X17, [SP, #-16]! | |
501 | OSWriteLittleInt32(&buffer[12], 0, 0x90000010); // ADRP X16, _fast_lazy_bind@page | |
502 | OSWriteLittleInt32(&buffer[16], 0, 0xF9400210); // LDR X16, [X16,_fast_lazy_bind@pageoff] | |
503 | OSWriteLittleInt32(&buffer[20], 0, 0xD61F0200); // BR X16 | |
504 | } | |
505 | virtual void setScope(Scope) { } | |
506 | virtual ld::Fixup::iterator fixupsBegin() const { return &_fixup1; } | |
507 | virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup6)[1]; } | |
508 | ||
509 | private: | |
510 | static ld::Atom* compressedImageCache(ld::passes::stubs::Pass& pass) { | |
511 | if ( pass.compressedImageCache == NULL ) | |
512 | pass.compressedImageCache = new ImageCachePointerAtom(pass); | |
513 | return pass.compressedImageCache; | |
514 | } | |
515 | static ld::Atom* compressedFastBinder(ld::passes::stubs::Pass& pass) { | |
516 | if ( pass.compressedFastBinderPointer == NULL ) | |
517 | pass.compressedFastBinderPointer = new FastBindingPointerAtom(pass); | |
518 | return pass.compressedFastBinderPointer; | |
519 | } | |
520 | ||
521 | mutable ld::Fixup _fixup1; | |
522 | ld::Fixup _fixup2; | |
523 | ld::Fixup _fixup3; | |
524 | ld::Fixup _fixup4; | |
525 | ld::Fixup _fixup5; | |
526 | ld::Fixup _fixup6; | |
527 | ||
528 | static ld::Section _s_section; | |
529 | }; | |
530 | ||
531 | ld::Section StubHelperHelperAtom::_s_section("__TEXT", "__stub_helper", ld::Section::typeStubHelper); | |
532 | ||
533 | ||
534 | ||
535 | class StubHelperAtom : public ld::Atom { | |
536 | public: | |
537 | StubHelperAtom(ld::passes::stubs::Pass& pass, const ld::Atom* lazyPointer, | |
538 | const ld::Atom& stubTo) | |
539 | : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, | |
540 | ld::Atom::scopeLinkageUnit, ld::Atom::typeStubHelper, | |
541 | symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)), | |
542 | _stubTo(stubTo), | |
543 | _fixup1(4, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64Branch26, helperHelper(pass)), | |
544 | _fixup2(8, ld::Fixup::k1of2, ld::Fixup::kindSetLazyOffset, lazyPointer), | |
545 | _fixup3(8, ld::Fixup::k2of2, ld::Fixup::kindStoreLittleEndian32) { } | |
546 | ||
547 | virtual const ld::File* file() const { return _stubTo.file(); } | |
548 | virtual const char* name() const { return _stubTo.name(); } | |
549 | virtual uint64_t size() const { return 12; } | |
550 | virtual uint64_t objectAddress() const { return 0; } | |
551 | virtual void copyRawContent(uint8_t buffer[]) const { | |
552 | OSWriteLittleInt32(&buffer[0], 0, 0x18000050); // LDR W16, L0 | |
553 | OSWriteLittleInt32(&buffer[4], 0, 0x14000000); // B helperhelper | |
554 | OSWriteLittleInt32(&buffer[8], 0, 0x00000000); // L0: .long 0 | |
555 | } | |
556 | virtual void setScope(Scope) { } | |
557 | virtual ld::Fixup::iterator fixupsBegin() const { return &_fixup1; } | |
558 | virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup3)[1]; } | |
559 | ||
560 | private: | |
561 | static ld::Atom* helperHelper(ld::passes::stubs::Pass& pass) { | |
562 | if ( pass.compressedHelperHelper == NULL ) | |
563 | pass.compressedHelperHelper = new StubHelperHelperAtom(pass); | |
564 | return pass.compressedHelperHelper; | |
565 | } | |
566 | ||
567 | const ld::Atom& _stubTo; | |
568 | mutable ld::Fixup _fixup1; | |
569 | ld::Fixup _fixup2; | |
570 | ld::Fixup _fixup3; | |
571 | ||
572 | static ld::Section _s_section; | |
573 | }; | |
574 | ||
575 | ld::Section StubHelperAtom::_s_section("__TEXT", "__stub_helper", ld::Section::typeStubHelper); | |
576 | ||
577 | ||
578 | class ResolverHelperAtom : public ld::Atom { | |
579 | public: | |
580 | ResolverHelperAtom(ld::passes::stubs::Pass& pass, const ld::Atom* lazyPointer, | |
581 | const ld::Atom& stubTo) | |
582 | : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, | |
583 | ld::Atom::scopeLinkageUnit, ld::Atom::typeStubHelper, | |
584 | symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)), | |
585 | _stubTo(stubTo), | |
586 | _fixup1(24, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64Branch26, &stubTo), | |
587 | _fixup2(28, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64Page21, lazyPointer), | |
588 | _fixup3(32, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64PageOff12, lazyPointer) { } | |
589 | ||
590 | virtual const ld::File* file() const { return _stubTo.file(); } | |
591 | virtual const char* name() const { return _stubTo.name(); } | |
592 | virtual uint64_t size() const { return 68; } | |
593 | virtual uint64_t objectAddress() const { return 0; } | |
594 | virtual void copyRawContent(uint8_t buffer[]) const { | |
595 | OSWriteLittleInt32(&buffer[ 0], 0, 0xa9bf7bfd); // stp fp, lr, [sp, #-16]! | |
596 | OSWriteLittleInt32(&buffer[ 4], 0, 0x910003fd); // mov fp, sp | |
597 | OSWriteLittleInt32(&buffer[ 8], 0, 0xa9bf03e1); // stp x1, x0, [sp, #-16]! | |
598 | OSWriteLittleInt32(&buffer[12], 0, 0xa9bf0be3); // stp x3, x2, [sp, #-16]! | |
599 | OSWriteLittleInt32(&buffer[16], 0, 0xa9bf13e5); // stp x5, x4, [sp, #-16]! | |
600 | OSWriteLittleInt32(&buffer[20], 0, 0xa9bf1be7); // stp x7, x6, [sp, #-16]! | |
601 | OSWriteLittleInt32(&buffer[24], 0, 0x94000000); // bl _foo | |
602 | OSWriteLittleInt32(&buffer[28], 0, 0x90000010); // adrp x16, lazy_pointer@PAGE | |
603 | OSWriteLittleInt32(&buffer[32], 0, 0x91000210); // add x16, x16, lazy_pointer@PAGEOFF | |
604 | OSWriteLittleInt32(&buffer[36], 0, 0xf9000200); // str x0, [x16] | |
605 | OSWriteLittleInt32(&buffer[40], 0, 0xaa0003f0); // mov x16, x0 | |
606 | OSWriteLittleInt32(&buffer[44], 0, 0xa8c11be7); // ldp x7, x6, [sp], #16 | |
607 | OSWriteLittleInt32(&buffer[48], 0, 0xa8c113e5); // ldp x5, x4, [sp], #16 | |
608 | OSWriteLittleInt32(&buffer[52], 0, 0xa8c10be3); // ldp x3, x2, [sp], #16 | |
609 | OSWriteLittleInt32(&buffer[56], 0, 0xa8c103e1); // ldp x1, x0, [sp], #16 | |
610 | OSWriteLittleInt32(&buffer[60], 0, 0xa8c17bfd); // ldp fp, lr, [sp], #16 | |
611 | OSWriteLittleInt32(&buffer[64], 0, 0xD61F0A1F); // braaz x16 | |
612 | } | |
613 | ||
614 | virtual void setScope(Scope) { } | |
615 | virtual ld::Fixup::iterator fixupsBegin() const { return &_fixup1; } | |
616 | virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup3)[1]; } | |
617 | ||
618 | private: | |
619 | ||
620 | const ld::Atom& _stubTo; | |
621 | mutable ld::Fixup _fixup1; | |
622 | ld::Fixup _fixup2; | |
623 | ld::Fixup _fixup3; | |
624 | ||
625 | static ld::Section _s_section; | |
626 | }; | |
627 | ||
628 | ld::Section ResolverHelperAtom::_s_section("__TEXT", "__stub_helper", ld::Section::typeStubHelper); | |
629 | ||
630 | ||
631 | ||
632 | class LazyPointerAtom : public ld::Atom { | |
633 | public: | |
634 | LazyPointerAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo, | |
635 | bool stubToGlobalWeakDef, bool stubToResolver, bool weakImport, bool dataConstUsed) | |
636 | : ld::Atom(selectSection(stubToGlobalWeakDef, stubToResolver, dataConstUsed), | |
637 | ld::Atom::definitionRegular, ld::Atom::combineNever, | |
638 | ld::Atom::scopeTranslationUnit, ld::Atom::typeLazyPointer, | |
639 | symbolTableNotIn, false, false, false, ld::Atom::Alignment(3)), | |
640 | _stubTo(stubTo), | |
641 | _helper(pass, this, stubTo), | |
642 | _resolverHelper(pass, this, stubTo), | |
643 | _fixup1(0, ld::Fixup::k1of2, ld::Fixup::kindSetAuthData, (ld::Fixup::AuthData){ 0, false, ld::Fixup::AuthData::ptrauth_key_asia }), | |
644 | _fixup2(0, ld::Fixup::k2of2, ld::Fixup::kindStoreTargetAddressLittleEndianAuth64, | |
645 | stubToResolver ? &_resolverHelper : (stubToGlobalWeakDef ? &stubTo : &_helper)), | |
646 | _fixup3(0, ld::Fixup::k1of1, ld::Fixup::kindLazyTarget, &stubTo) { | |
647 | _fixup2.weakImport = weakImport; pass.addAtom(*this); | |
648 | if ( stubToResolver ) | |
649 | pass.addAtom(_resolverHelper); | |
650 | else if ( !stubToGlobalWeakDef ) | |
651 | pass.addAtom(_helper); | |
652 | } | |
653 | ||
654 | virtual const ld::File* file() const { return _stubTo.file(); } | |
655 | virtual const char* name() const { return _stubTo.name(); } | |
656 | virtual uint64_t size() const { return 8; } | |
657 | virtual uint64_t objectAddress() const { return 0; } | |
658 | virtual void copyRawContent(uint8_t buffer[]) const { } | |
659 | virtual void setScope(Scope) { } | |
660 | virtual ld::Fixup::iterator fixupsBegin() const { return &_fixup1; } | |
661 | virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup3)[1]; } | |
662 | ||
663 | private: | |
664 | static ld::Section& selectSection(bool stubToGlobalWeakDef, bool stubToResolver, bool dataConstUsed) { | |
665 | if ( stubToGlobalWeakDef && dataConstUsed ) | |
666 | return _s_sectionWeak; | |
667 | else if ( stubToResolver && dataConstUsed ) | |
668 | return _s_sectionResolver; | |
669 | else | |
670 | return _s_section; | |
671 | } | |
672 | ||
673 | const ld::Atom& _stubTo; | |
674 | StubHelperAtom _helper; | |
675 | ResolverHelperAtom _resolverHelper; | |
676 | mutable ld::Fixup _fixup1; | |
677 | ld::Fixup _fixup2; | |
678 | ld::Fixup _fixup3; | |
679 | ||
680 | static ld::Section _s_section; | |
681 | static ld::Section _s_sectionResolver; | |
682 | static ld::Section _s_sectionWeak; | |
683 | }; | |
684 | ||
685 | ld::Section LazyPointerAtom::_s_section("__DATA", "__la_symbol_ptr", ld::Section::typeLazyPointer); | |
686 | ld::Section LazyPointerAtom::_s_sectionResolver("__DATA_DIRTY", "__la_resolver", ld::Section::typeLazyPointer); | |
687 | ld::Section LazyPointerAtom::_s_sectionWeak("__DATA", "__la_weak_ptr", ld::Section::typeLazyPointer); | |
688 | ||
689 | ||
690 | class StubAtom : public ld::Atom { | |
691 | public: | |
692 | StubAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo, | |
693 | bool stubToGlobalWeakDef, bool stubToResolver, bool weakImport, bool dataConstUsed) | |
694 | : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, | |
695 | ld::Atom::scopeLinkageUnit, ld::Atom::typeStub, | |
696 | symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)), | |
697 | _stubTo(stubTo), | |
698 | _lazyPointer(pass, stubTo, stubToGlobalWeakDef, stubToResolver, weakImport, dataConstUsed), | |
699 | _fixup1(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64Page21, &_lazyPointer), | |
700 | _fixup2(4, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64PageOff12, &_lazyPointer), | |
701 | _fixup3(ld::Fixup::kindLinkerOptimizationHint, LOH_ARM64_ADRP_LDR, 0, 4) | |
702 | { pass.addAtom(*this); } | |
703 | ||
704 | virtual const ld::File* file() const { return _stubTo.file(); } | |
705 | virtual const char* name() const { return _stubTo.name(); } | |
706 | virtual uint64_t size() const { return 12; } | |
707 | virtual uint64_t objectAddress() const { return 0; } | |
708 | virtual void copyRawContent(uint8_t buffer[]) const { | |
709 | OSWriteLittleInt32(&buffer[0], 0, 0x90000010); // ADRP X16, lazy_pointer@page | |
710 | OSWriteLittleInt32(&buffer[4], 0, 0xF9400210); // LDR X16, [X16, lazy_pointer@pageoff] | |
711 | OSWriteLittleInt32(&buffer[8], 0, 0xD61F0A1F); // BRAAZ X16 | |
712 | } | |
713 | virtual void setScope(Scope) { } | |
714 | virtual ld::Fixup::iterator fixupsBegin() const { return &_fixup1; } | |
715 | virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup3)[1]; } | |
716 | ||
717 | private: | |
718 | const ld::Atom& _stubTo; | |
719 | LazyPointerAtom _lazyPointer; | |
720 | mutable ld::Fixup _fixup1; | |
721 | mutable ld::Fixup _fixup2; | |
722 | mutable ld::Fixup _fixup3; | |
723 | ||
724 | static ld::Section _s_section; | |
725 | }; | |
726 | ||
727 | ld::Section StubAtom::_s_section("__TEXT", "__stubs", ld::Section::typeStub); | |
728 | ||
729 | ||
730 | ||
731 | class NonLazyPointerAtom : public ld::Atom { | |
732 | public: | |
733 | NonLazyPointerAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo, | |
734 | bool weakImport) | |
735 | : ld::Atom(_s_section, ld::Atom::definitionRegular, | |
736 | ld::Atom::combineNever, ld::Atom::scopeLinkageUnit, ld::Atom::typeNonLazyPointer, | |
737 | symbolTableNotIn, false, false, false, ld::Atom::Alignment(3)), | |
738 | _stubTo(stubTo), | |
739 | _fixup1(0, ld::Fixup::k1of2, ld::Fixup::kindSetAuthData, (ld::Fixup::AuthData){ 0, true, ld::Fixup::AuthData::ptrauth_key_asia }), | |
740 | _fixup2(0, ld::Fixup::k2of2, ld::Fixup::kindStoreTargetAddressLittleEndianAuth64, &stubTo) { | |
741 | _fixup2.weakImport = weakImport; | |
742 | pass.addAtom(*this); | |
743 | } | |
744 | ||
745 | virtual const ld::File* file() const { return _stubTo.file(); } | |
746 | virtual const char* name() const { return _stubTo.name(); } | |
747 | virtual uint64_t size() const { return 8; } | |
748 | virtual uint64_t objectAddress() const { return 0; } | |
749 | virtual void copyRawContent(uint8_t buffer[]) const { } | |
750 | virtual void setScope(Scope) { } | |
751 | virtual ld::Fixup::iterator fixupsBegin() const { return (ld::Fixup*)&_fixup1; } | |
752 | virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup2)[1]; } | |
753 | ||
754 | private: | |
755 | const ld::Atom& _stubTo; | |
756 | ld::Fixup _fixup1; | |
757 | ld::Fixup _fixup2; | |
758 | ||
759 | static ld::Section _s_section; | |
760 | }; | |
761 | ||
762 | ld::Section NonLazyPointerAtom::_s_section("__DATA", "__auth_got", ld::Section::typeNonLazyPointer); | |
763 | ||
764 | ||
765 | class NonLazyStubAtom : public ld::Atom { | |
766 | public: | |
767 | NonLazyStubAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo, | |
768 | bool weakImport) | |
769 | : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, | |
770 | ld::Atom::scopeLinkageUnit, ld::Atom::typeStub, | |
771 | symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)), | |
772 | _stubTo(stubTo), | |
773 | _nonLazyPointer(pass, stubTo, weakImport), | |
774 | _fixup1(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64Page21, &_nonLazyPointer), | |
775 | _fixup2(4, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64PageOff12, &_nonLazyPointer) { | |
776 | asprintf((char**)&_name, "%s.stub", _stubTo.name()); | |
777 | pass.addAtom(*this); | |
778 | } | |
779 | ||
780 | virtual const ld::File* file() const { return _stubTo.file(); } | |
781 | virtual const char* name() const { return _name; } | |
782 | virtual uint64_t size() const { return 16; } | |
783 | virtual uint64_t objectAddress() const { return 0; } | |
784 | virtual void copyRawContent(uint8_t buffer[]) const { | |
785 | OSWriteLittleInt32(&buffer[ 0], 0, 0x90000011); // ADRP X17, dyld_mageLoaderCache@page | |
786 | OSWriteLittleInt32(&buffer[ 4], 0, 0x91000231); // ADD X17, X17, dyld_mageLoaderCache@pageoff | |
787 | OSWriteLittleInt32(&buffer[ 8], 0, 0xF9400230); // LDR X16, [X17] | |
788 | OSWriteLittleInt32(&buffer[12], 0, 0xD71F0A11); // BRAA X16, X17 | |
789 | } | |
790 | virtual void setScope(Scope) { } | |
791 | virtual ld::Fixup::iterator fixupsBegin() const { return &_fixup1; } | |
792 | virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup2)[1]; } | |
793 | ||
794 | private: | |
795 | const ld::Atom& _stubTo; | |
796 | const char* _name; | |
797 | NonLazyPointerAtom _nonLazyPointer; | |
798 | mutable ld::Fixup _fixup1; | |
799 | mutable ld::Fixup _fixup2; | |
800 | ||
801 | static ld::Section _s_section; | |
802 | }; | |
803 | ||
804 | ld::Section NonLazyStubAtom::_s_section("__TEXT", "__auth_stubs", ld::Section::typeStub); | |
805 | ||
806 | ||
807 | } // namespace arm64e | |
808 | #endif | |
809 |