]>
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, | |
151 | symbolTableNotIn, false, false, false, ld::Atom::Alignment(1)), | |
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, | |
194 | symbolTableNotIn, false, false, false, ld::Atom::Alignment(1)), | |
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, | |
244 | bool stubToGlobalWeakDef, bool stubToResolver, bool weakImport) | |
245 | : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, | |
246 | ld::Atom::scopeTranslationUnit, ld::Atom::typeLazyPointer, | |
247 | symbolTableNotIn, false, false, false, ld::Atom::Alignment(3)), | |
248 | _stubTo(stubTo), | |
249 | _helper(pass, this, stubTo), | |
250 | _resolverHelper(pass, this, stubTo), | |
251 | _fixup1(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressLittleEndian64, | |
252 | stubToResolver ? &_resolverHelper : | |
253 | (stubToGlobalWeakDef ? &stubTo : &_helper)), | |
254 | _fixup2(0, ld::Fixup::k1of1, ld::Fixup::kindLazyTarget, &stubTo) { | |
255 | _fixup2.weakImport = weakImport; pass.addAtom(*this); | |
256 | if ( stubToResolver ) | |
257 | pass.addAtom(_resolverHelper); | |
258 | else if ( !stubToGlobalWeakDef ) | |
259 | pass.addAtom(_helper); | |
260 | } | |
261 | ||
262 | virtual const ld::File* file() const { return _stubTo.file(); } | |
263 | virtual const char* name() const { return _stubTo.name(); } | |
264 | virtual uint64_t size() const { return 8; } | |
265 | virtual uint64_t objectAddress() const { return 0; } | |
266 | virtual void copyRawContent(uint8_t buffer[]) const { } | |
267 | virtual void setScope(Scope) { } | |
268 | virtual ld::Fixup::iterator fixupsBegin() const { return &_fixup1; } | |
269 | virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup2)[1]; } | |
270 | ||
271 | private: | |
272 | const ld::Atom& _stubTo; | |
273 | StubHelperAtom _helper; | |
274 | ResolverHelperAtom _resolverHelper; | |
275 | mutable ld::Fixup _fixup1; | |
276 | ld::Fixup _fixup2; | |
277 | ||
278 | static ld::Section _s_section; | |
279 | }; | |
280 | ||
281 | ld::Section LazyPointerAtom::_s_section("__DATA", "__la_symbol_ptr", ld::Section::typeLazyPointer); | |
282 | ||
283 | ||
284 | class StubAtom : public ld::Atom { | |
285 | public: | |
286 | StubAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo, | |
287 | bool stubToGlobalWeakDef, bool stubToResolver, bool weakImport) | |
288 | : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, | |
289 | ld::Atom::scopeLinkageUnit, ld::Atom::typeStub, | |
290 | symbolTableNotIn, false, false, false, ld::Atom::Alignment(1)), | |
291 | _stubTo(stubTo), | |
292 | _lazyPointer(pass, stubTo, stubToGlobalWeakDef, stubToResolver, weakImport), | |
293 | _fixup1(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64Page21, &_lazyPointer), | |
9543cb2f A |
294 | _fixup2(4, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64PageOff12, &_lazyPointer), |
295 | _fixup3(ld::Fixup::kindLinkerOptimizationHint, LOH_ARM64_ADRP_LDR, 0, 4) | |
296 | { pass.addAtom(*this); } | |
f80fe69f A |
297 | |
298 | virtual const ld::File* file() const { return _stubTo.file(); } | |
299 | virtual const char* name() const { return _stubTo.name(); } | |
300 | virtual uint64_t size() const { return 12; } | |
301 | virtual uint64_t objectAddress() const { return 0; } | |
302 | virtual void copyRawContent(uint8_t buffer[]) const { | |
303 | OSWriteLittleInt32(&buffer[0], 0, 0x90000010); // ADRP X16, lazy_pointer@page | |
304 | OSWriteLittleInt32(&buffer[4], 0, 0xF9400210); // LDR X16, [X16, lazy_pointer@pageoff] | |
305 | OSWriteLittleInt32(&buffer[8], 0, 0xD61F0200); // BR X16 | |
306 | } | |
307 | virtual void setScope(Scope) { } | |
308 | virtual ld::Fixup::iterator fixupsBegin() const { return &_fixup1; } | |
9543cb2f | 309 | virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup3)[1]; } |
f80fe69f A |
310 | |
311 | private: | |
312 | const ld::Atom& _stubTo; | |
313 | LazyPointerAtom _lazyPointer; | |
314 | mutable ld::Fixup _fixup1; | |
315 | mutable ld::Fixup _fixup2; | |
9543cb2f | 316 | mutable ld::Fixup _fixup3; |
f80fe69f A |
317 | |
318 | static ld::Section _s_section; | |
319 | }; | |
320 | ||
321 | ld::Section StubAtom::_s_section("__TEXT", "__stubs", ld::Section::typeStub); | |
322 | ||
323 | ||
324 | ||
325 | class NonLazyPointerAtom : public ld::Atom { | |
326 | public: | |
327 | NonLazyPointerAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo) | |
328 | : ld::Atom(_s_section, ld::Atom::definitionRegular, | |
329 | ld::Atom::combineNever, ld::Atom::scopeLinkageUnit, ld::Atom::typeNonLazyPointer, | |
330 | symbolTableNotIn, false, false, false, ld::Atom::Alignment(3)), | |
331 | _stubTo(stubTo), | |
332 | _fixup1(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressLittleEndian64, &stubTo) { | |
333 | pass.addAtom(*this); | |
334 | } | |
335 | ||
336 | virtual const ld::File* file() const { return _stubTo.file(); } | |
337 | virtual const char* name() const { return _stubTo.name(); } | |
338 | virtual uint64_t size() const { return 8; } | |
339 | virtual uint64_t objectAddress() const { return 0; } | |
340 | virtual void copyRawContent(uint8_t buffer[]) const { } | |
341 | virtual void setScope(Scope) { } | |
342 | virtual ld::Fixup::iterator fixupsBegin() const { return (ld::Fixup*)&_fixup1; } | |
343 | virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup1)[1]; } | |
344 | ||
345 | private: | |
346 | const ld::Atom& _stubTo; | |
347 | ld::Fixup _fixup1; | |
348 | ||
349 | static ld::Section _s_section; | |
350 | }; | |
351 | ||
352 | ld::Section NonLazyPointerAtom::_s_section("__DATA", "__got", ld::Section::typeNonLazyPointer); | |
353 | ||
354 | ||
355 | class KextStubAtom : public ld::Atom { | |
356 | public: | |
357 | KextStubAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo) | |
358 | : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, | |
359 | ld::Atom::scopeLinkageUnit, ld::Atom::typeStub, | |
360 | symbolTableIn, false, false, false, ld::Atom::Alignment(1)), | |
361 | _stubTo(stubTo), | |
362 | _nonLazyPointer(pass, stubTo), | |
363 | _fixup1(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64Page21, &_nonLazyPointer), | |
364 | _fixup2(4, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64PageOff12, &_nonLazyPointer) { | |
365 | pass.addAtom(*this); | |
366 | asprintf((char**)&_name, "%s.stub", _stubTo.name()); | |
367 | } | |
368 | ||
369 | virtual const ld::File* file() const { return _stubTo.file(); } | |
370 | virtual const char* name() const { return _name; } | |
371 | virtual uint64_t size() const { return 12; } | |
372 | virtual uint64_t objectAddress() const { return 0; } | |
373 | virtual void copyRawContent(uint8_t buffer[]) const { | |
374 | OSWriteLittleInt32(&buffer[0], 0, 0x90000010); // ADRP X16, non_lazy_pointer@page | |
375 | OSWriteLittleInt32(&buffer[4], 0, 0xF9400210); // LDR X16, [X16, non_lazy_pointer@pageoff] | |
376 | OSWriteLittleInt32(&buffer[8], 0, 0xD61F0200); // BR X16 | |
377 | } | |
378 | virtual void setScope(Scope) { } | |
379 | virtual ld::Fixup::iterator fixupsBegin() const { return &_fixup1; } | |
380 | virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup2)[1]; } | |
381 | ||
382 | private: | |
383 | const ld::Atom& _stubTo; | |
384 | const char* _name; | |
385 | NonLazyPointerAtom _nonLazyPointer; | |
386 | mutable ld::Fixup _fixup1; | |
387 | mutable ld::Fixup _fixup2; | |
388 | ||
389 | static ld::Section _s_section; | |
390 | }; | |
391 | ||
392 | ld::Section KextStubAtom::_s_section("__TEXT", "__stubs", ld::Section::typeCode); | |
393 | ||
394 | ||
395 | } // namespace x86_64 | |
396 |