source: trunk/kLdr/kLdrDyldMod.c@ 2883

Last change on this file since 2883 was 2883, checked in by bird, 19 years ago

cleanup.

  • Property svn:keywords set to Id
File size: 37.3 KB
RevLine 
[2878]1/* $Id: kLdrDyldMod.c 2883 2006-11-18 11:21:33Z bird $ */
[2835]2/** @file
3 *
4 * kLdr - The Dynamic Loader, Dyld module methods.
5 *
6 * Copyright (c) 2006 knut st. osmundsen <bird-kbuild-src@anduin.net>
7 *
8 *
9 * This file is part of kLdr.
10 *
11 * kLdr is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * kLdr is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with kLdr; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 *
25 */
26
27
28
29/*******************************************************************************
30* Header Files *
31*******************************************************************************/
32#include <kLdr.h>
33#include "kLdrInternal.h"
34#include "kLdrHlp.h"
35
36
[2837]37/*******************************************************************************
38* Defined Constants And Macros *
39*******************************************************************************/
[2845]40/** @def KLDRDYLDMOD_STRICT
41 * Define KLDRDYLDMOD_STRICT to enabled strict checks in kLdrDyld. */
42#define KLDRDYLDMOD_STRICT 1
43
[2837]44/** @def KLDRDYLDMOD_ASSERT
45 * Assert that an expression is true when KLDRDYLD_STRICT is defined.
46 */
[2845]47#ifdef KLDRDYLDMOD_STRICT
[2837]48# define KLDRDYLDMOD_ASSERT(expr) kldrHlpAssert(expr)
49#else
50# define KLDRDYLDMOD_ASSERT(expr) do {} while (0)
51#endif
[2835]52
[2847]53/*******************************************************************************
54* Internal Functions *
55*******************************************************************************/
56static void kldrDyldModUnlink(PKLDRDYLDMOD pMod);
[2835]57
58
[2847]59
[2842]60/**
[2845]61 * Creates a module from the specified file provider instance.
62 *
63 * @returns 0 on success and *ppMod pointing to the new instance.
64 * On failure a non-zero kLdr status code is returned.
65 * @param pRdr The file provider instance.
[2868]66 * @param fFlags Load/search flags.
[2845]67 * @param ppMod Where to put the pointer to the new module on success.
68 */
[2868]69int kldrDyldModCreate(PKLDRRDR pRdr, uint32_t fFlags, PPKLDRDYLDMOD ppMod)
[2845]70{
71 PKLDRDYLDMOD pMod;
72 PKLDRMOD pRawMod;
73 int rc;
74
75 *ppMod = NULL;
76
[2868]77/** @todo deal with fFlags (exec/dll) */
78
[2845]79 /*
80 * Try open an module interpreter.
81 */
82 rc = kLdrModOpenFromRdr(pRdr, &pRawMod);
83 if (rc)
84 return kldrDyldFailure(rc, "%s: %rc", kLdrRdrName(pRdr), rc);
85
86 /*
[2870]87 * Match the module aginst the load flags.
88 */
89 switch (pRawMod->enmType)
90 {
91 case KLDRTYPE_EXECUTABLE_FIXED:
92 case KLDRTYPE_EXECUTABLE_RELOCATABLE:
93 case KLDRTYPE_EXECUTABLE_PIC:
94 if (!(fFlags & KLDRDYLD_LOAD_FLAGS_EXECUTABLE))
95 {
96 kLdrModClose(pRawMod);
97 return KLDR_ERR_NOT_EXE;
98 }
99 break;
100
101 case KLDRTYPE_OBJECT: /* We can handle these as DLLs. */
102 case KLDRTYPE_SHARED_LIBRARY_FIXED:
103 case KLDRTYPE_SHARED_LIBRARY_RELOCATABLE:
104 case KLDRTYPE_SHARED_LIBRARY_PIC:
105 case KLDRTYPE_FORWARDER_DLL:
106 if (fFlags & KLDRDYLD_LOAD_FLAGS_EXECUTABLE)
107 {
108 kLdrModClose(pRawMod);
109 return KLDR_ERR_NOT_DLL;
110 }
111 break;
112
113 default:
114 KLDRDYLDMOD_ASSERT(!"Bad enmType!");
115 case KLDRTYPE_CORE:
116 return fFlags & KLDRDYLD_LOAD_FLAGS_EXECUTABLE ? KLDR_ERR_NOT_EXE : KLDR_ERR_NOT_DLL;
117 }
118
119 /*
[2845]120 * Allocate a new dyld module.
121 */
122 pMod = (PKLDRDYLDMOD)kldrHlpAlloc(sizeof(*pMod));
123 if (pMod)
124 {
125 pMod->enmState = KLDRSTATE_OPEN;
126 pMod->pMod = pRawMod;
127 pMod->hMod = pMod;
128 pMod->cDepRefs = pMod->cDynRefs = pMod->cRefs = 0;
129 switch (pRawMod->enmType)
130 {
131 case KLDRTYPE_EXECUTABLE_FIXED:
132 case KLDRTYPE_EXECUTABLE_RELOCATABLE:
133 case KLDRTYPE_EXECUTABLE_PIC:
134 pMod->fExecutable = 1;
135 break;
[2883]136 default:
137 pMod->fExecutable = 0;
138 break;
[2845]139 }
140 pMod->fGlobalOrSpecific = 0;
141 pMod->fBindable = 0;
142 pMod->fInitList = 0;
143 pMod->fAlreadySeen = 0;
144 pMod->fMapped = 0;
[2846]145 pMod->fAllocatedTLS = 0;
146 pMod->f25Reserved = 0;
[2845]147 pMod->InitTerm.pNext = NULL;
148 pMod->InitTerm.pPrev = NULL;
149 pMod->Bind.pNext = NULL;
150 pMod->Bind.pPrev = NULL;
151 pMod->cPrereqs = 0;
152 pMod->papPrereqs = NULL;
153 pMod->u32MagicHead = KLDRDYMOD_MAGIC;
154 pMod->u32MagicTail = KLDRDYMOD_MAGIC;
155
156 /* it. */
157 pMod->Load.pNext = NULL;
158 pMod->Load.pPrev = kLdrDyldTail;
159 if (kLdrDyldTail)
160 kLdrDyldTail->Load.pNext = pMod;
161 else
162 kLdrDyldHead = pMod;
163 kLdrDyldTail = pMod;
164
[2870]165 /* deal with the remaining flags. */
166 if (fFlags & KLDRYDLD_LOAD_FLAGS_SPECIFIC_MODULE)
167 kldrDyldModMarkSpecific(pMod);
168 else
169 kldrDyldModMarkGlobal(pMod);
170
171 if (fFlags & KLDRYDLD_LOAD_FLAGS_GLOBAL_SYMBOLS)
172 kldrDyldModSetBindable(pMod, 0 /* not deep binable */);
173 else
174 kldrDyldModClearBindable(pMod);
175
176 /*
177 * We're good.
178 */
[2845]179 *ppMod = pMod;
180 rc = 0;
181 }
182 else
183 {
184 kLdrModClose(pRawMod);
185 rc = KLDR_ERR_NO_MEMORY;
186 }
187 return rc;
188}
189
190
191/**
192 * Creates a module for a native module.
193 *
194 * @returns 0 on success and *ppMod pointing to the new instance.
195 * On failure a non-zero kLdr status code is returned.
196 * @param hNativeModule The native handle.
197 * @param ppMod Where to put the pointer to the new module on success.
198 * @remark This function ain't finalized yet.
199 */
200int kldrDyldModCreateNative(uintptr_t hNativeModule)
201{
202#if 0
203 /*
204 * Check if this module is already loaded by the native OS loader.
205 */
206 rc = kld
207 {
208#ifdef __OS2__
209 HMODULE hmod = NULLHANDLE;
210 APIRET rc = DosQueryModuleHandle(kLdrRdrName(pRdr), &hmod);
211 if (!rc)
212
213#elif defined(__WIN__)
214 HMODULE hmod = NULL;
215 if (GetModuleHandle(kLdrRdrName(pRdr))
216
217#else
218# error "Port me"
219#endif
220 }
221#endif
222 return -1;
223}
224
225
226/**
227 * Destroys a module pending destruction.
228 *
229 * @param pMod The module in question.
230 */
231void kldrDyldModDestroy(PKLDRDYLDMOD pMod)
232{
[2847]233 int rc;
234
[2845]235 /*
236 * Validate the state.
237 */
238 switch (pMod->enmState)
239 {
240 case KLDRSTATE_PENDING_DESTROY:
241 case KLDRSTATE_GC:
242 break;
243 default:
244 KLDRDYLDMOD_ASSERT(!"Invalid state");
245 break;
246 }
247 KLDRDYLDMOD_ASSERT(!pMod->fInitList);
248 KLDRDYLDMOD_ASSERT(!pMod->cDynRefs);
249 KLDRDYLDMOD_ASSERT(!pMod->cDepRefs);
250
251 /*
252 * Ensure that the module is unmapped.
253 */
[2847]254 if (pMod->fAllocatedTLS)
255 {
256 kLdrModFreeTLS(pMod->pMod);
257 pMod->fAllocatedTLS = 0;
258 }
[2845]259 if (pMod->fMapped)
[2847]260 {
261 rc = kLdrModUnmap(pMod->pMod); KLDRDYLDMOD_ASSERT(!rc);
262 pMod->fMapped = 0;
263 }
264
265 /*
266 * Ensure it's unlinked from all chains.
267 */
268 if (pMod->enmState < KLDRSTATE_PENDING_DESTROY)
269 kldrDyldModUnlink(pMod);
270
271 /*
272 * Free everything associated with the module.
273 */
274 /* the prerequisite array. */
275 if (pMod->papPrereqs)
276 {
277 uint32_t i = pMod->cPrereqs;
278 while (i-- > 0)
279 {
280 KLDRDYLDMOD_ASSERT(pMod->papPrereqs[i] == NULL);
281 pMod->papPrereqs[i] = NULL;
282 }
283
284 kldrHlpFree(pMod->papPrereqs);
285 pMod->papPrereqs = NULL;
286 pMod->cPrereqs = 0;
287 }
288
289 /* the module interpreter. */
290 if (pMod->pMod)
291 {
292 rc = kLdrModClose(pMod->pMod); KLDRDYLDMOD_ASSERT(!rc);
293 pMod->pMod = NULL;
294 }
295
296
297 /*
298 * Finally, change the module state and free the module if
299 * there are not more references to it. If somebody is still
300 * referencing it, postpone the freeing to Deref.
301 */
302 pMod->enmState = KLDRSTATE_DESTROYED;
303 if (!pMod->cRefs)
304 {
305 pMod->u32MagicHead = 1;
306 pMod->u32MagicTail = 2;
307 kldrHlpFree(pMod);
308 }
[2845]309}
310
311
312/**
313 * Unlinks the module from any list it might be in.
314 * It is assumed that the module is at least linked into the load list.
315 *
316 * @param pMod The moduel.
317 */
318static void kldrDyldModUnlink(PKLDRDYLDMOD pMod)
319{
320 /* load list */
321 if (pMod->Load.pNext)
322 pMod->Load.pNext->Load.pPrev = pMod->Load.pPrev;
323 else
324 kLdrDyldTail = pMod->Load.pPrev;
325 if (pMod->Load.pPrev)
326 pMod->Load.pPrev->Load.pNext = pMod->Load.pNext;
327 else
328 kLdrDyldHead = pMod->Load.pNext;
329
330 /* bind list */
331 if (pMod->fBindable)
332 kldrDyldModClearBindable(pMod);
333
334 /* init term */
335 if (pMod->fInitList)
336 {
337 KLDRDYLDMOD_ASSERT(pMod->enmState < KLDRSTATE_INITIALIZATION_FAILED);
338 pMod->fInitList = 0;
339 if (pMod->InitTerm.pNext)
340 pMod->InitTerm.pNext->InitTerm.pPrev = pMod->InitTerm.pPrev;
341 else
342 g_pkLdrDyldInitTail = pMod->InitTerm.pPrev;
343 if (pMod->InitTerm.pPrev)
344 pMod->InitTerm.pPrev->InitTerm.pNext = pMod->InitTerm.pNext;
345 else
346 g_pkLdrDyldInitHead = pMod->InitTerm.pNext;
347 }
348 else if (pMod->enmState > KLDRSTATE_INITIALIZATION_FAILED)
349 {
350 KLDRDYLDMOD_ASSERT(pMod->enmState >= KLDRSTATE_GOOD);
351 if (pMod->InitTerm.pNext)
352 pMod->InitTerm.pNext->InitTerm.pPrev = pMod->InitTerm.pPrev;
353 else
354 g_pkLdrDyldTermTail = pMod->InitTerm.pPrev;
355 if (pMod->InitTerm.pPrev)
356 pMod->InitTerm.pPrev->InitTerm.pNext = pMod->InitTerm.pNext;
357 else
358 g_pkLdrDyldTermHead = pMod->InitTerm.pNext;
359 }
360 pMod->InitTerm.pNext = NULL;
361 pMod->InitTerm.pPrev = NULL;
362}
363
364
365/**
[2846]366 * Marks a module as bindable, i.e. it'll be considered when
367 * resolving names the unix way.
368 *
369 * @param pMod The module.
370 * @param fDeep When set the module will be inserted at the head of the
371 * module list used to resolve symbols. This means that the
372 * symbols in this module will be prefered of all the other
373 * modules.
374 */
375void kldrDyldModSetBindable(PKLDRDYLDMOD pMod, unsigned fDeep)
376{
377 KLDRDYLDMOD_ASSERT(pMod->enmState >= KLDRSTATE_OPEN && pMod->enmState < KLDRSTATE_PENDING_GC);
378 if (!pMod->fBindable)
379 {
380 pMod->fBindable = 1;
381 if (!fDeep)
382 {
383 pMod->Bind.pNext = NULL;
384 pMod->Bind.pPrev = g_pkLdrDyldBindTail;
385 if (g_pkLdrDyldBindTail)
386 g_pkLdrDyldBindTail->Bind.pNext = pMod;
387 else
388 g_pkLdrDyldBindHead = pMod;
389 g_pkLdrDyldBindTail = pMod;
390 }
391 else
392 {
393 pMod->Bind.pPrev = NULL;
394 pMod->Bind.pNext = g_pkLdrDyldBindHead;
395 if (g_pkLdrDyldBindHead)
396 g_pkLdrDyldBindHead->Bind.pPrev = pMod;
397 else
398 g_pkLdrDyldBindTail = pMod;
399 g_pkLdrDyldBindHead = pMod;
400 }
401 }
402}
403
404
405/**
406 * Marks a module as not bindable, i.e. it will not be considered when
407 * resolving names the unix way.
408 *
409 * @param pMod The module.
410 */
411void kldrDyldModClearBindable(PKLDRDYLDMOD pMod)
412{
413 KLDRDYLDMOD_ASSERT(pMod->enmState >= KLDRSTATE_OPEN && pMod->enmState < KLDRSTATE_PENDING_DESTROY);
414 if (pMod->fBindable)
415 {
416 pMod->fBindable = 0;
417 if (pMod->Bind.pPrev)
418 pMod->Bind.pPrev->Bind.pNext = pMod->Bind.pNext;
419 else
420 g_pkLdrDyldBindHead = pMod->Bind.pNext;
421 if (pMod->Bind.pNext)
422 pMod->Bind.pNext->Bind.pPrev = pMod->Bind.pPrev;
423 else
424 g_pkLdrDyldBindTail = pMod->Bind.pPrev;
425 pMod->Bind.pNext = NULL;
426 pMod->Bind.pPrev = NULL;
427 }
428}
429
430
431/**
432 * Marks the module as global instead of being specific.
433 *
434 * A global module can be a matching result when the request
435 * doesn't specify a path. A specific module will not match
436 * unless the path also matches.
437 *
438 * @param pMod The module.
439 */
440void kldrDyldModMarkGlobal(PKLDRDYLDMOD pMod)
441{
442 pMod->fGlobalOrSpecific = 1;
443}
444
445
446/**
447 * Marks the module as specific instead of global.
448 *
449 * See kldrDyldModMarkGlobal for an explanation of the two terms.
450 *
451 * @param pMod The module.
452 */
453void kldrDyldModMarkSpecific(PKLDRDYLDMOD pMod)
454{
455 pMod->fGlobalOrSpecific = 0;
456}
457
458
459/**
[2845]460 * Adds a reference to the module making sure it won't be freed just yet.
461 *
462 * @param pMod The module.
463 */
464void kldrDyldModAddRef(PKLDRDYLDMOD pMod)
465{
466 pMod->cRefs++;
467}
468
469
470/**
471 * Dereference a module.
472 *
473 * @param pMod
474 */
475void kldrDyldModDeref(PKLDRDYLDMOD pMod)
476{
477 /* validate input */
478 KLDRDYLDMOD_ASSERT(pMod->cRefs > 0);
479 KLDRDYLDMOD_ASSERT(pMod->cRefs >= pMod->cDepRefs + pMod->cDynRefs);
480 KLDRDYLDMOD_ASSERT(pMod->enmState > KLDRSTATE_INVALID && pMod->enmState <= KLDRSTATE_END);
481
482 /* decrement. */
483 if (pMod->cRefs > 0)
484 pMod->cRefs--;
485
486 /* execute delayed freeing. */
487 if ( pMod->enmState == KLDRSTATE_DESTROYED
488 && !pMod->cRefs)
[2847]489 {
490 pMod->u32MagicHead = 1;
491 pMod->u32MagicTail = 2;
[2845]492 kldrHlpFree(pMod);
[2847]493 }
[2845]494}
495
496
497/**
498 * Increment the count of modules depending on this module.
499 *
500 * @param pMod The module.
501 * @param pDep The module which depends on us.
502 */
503void kldrDyldModAddDep(PKLDRDYLDMOD pMod, PKLDRDYLDMOD pDep)
504{
505 (void)pDep;
506
507 /* validate state */
508 switch (pMod->enmState)
509 {
510 case KLDRSTATE_MAPPED:
511 case KLDRSTATE_RELOADED:
512 case KLDRSTATE_LOADED_PREREQUISITES:
513 case KLDRSTATE_RELOADED_LOADED_PREREQUISITES:
514 case KLDRSTATE_PENDING_INITIALIZATION:
515 case KLDRSTATE_INITIALIZING:
516 case KLDRSTATE_GOOD:
517 break;
518 default:
519 KLDRDYLDMOD_ASSERT(!"invalid state");
520 break;
521
522 }
523 KLDRDYLDMOD_ASSERT(pMod->enmState > KLDRSTATE_INVALID && pMod->enmState <= KLDRSTATE_END);
524 pMod->cRefs++;
525 pMod->cDepRefs++;
526}
527
528
529/**
530 * Drop a dependency.
531 *
532 * @param pMod The module.
533 * @param pDep The module which depends on us.
534 */
535void kldrDyldModRemoveDep(PKLDRDYLDMOD pMod, PKLDRDYLDMOD pDep)
536{
537 KLDRDYLDMOD_ASSERT(pMod->cDepRefs > 0);
538 if (pMod->cDepRefs == 0)
539 return;
540 KLDRDYLDMOD_ASSERT(pMod->cDepRefs <= pMod->cRefs);
541 KLDRDYLDMOD_ASSERT(pMod->enmState >= KLDRSTATE_MAPPED && pMod->enmState <= KLDRSTATE_PENDING_DESTROY);
542
543 pMod->cRefs--;
544 pMod->cDepRefs--;
545 if ( pMod->cDepRefs > 0
546 || pMod->cDynRefs > 0)
547 return;
548
549 /*
550 * The module should be unloaded.
551 */
552 kldrDyldModUnloadPrerequisites(pMod);
553}
554
555
556/**
557 * Increment the dynamic load count.
558 *
559 * @returns 0
560 * @param pMod The module.
561 */
562int kldrDyldModDynamicLoad(PKLDRDYLDMOD pMod)
563{
564 KLDRDYLDMOD_ASSERT( pMod->enmState == KLDRSTATE_GOOD
565 || pMod->enmState == KLDRSTATE_PENDING_INITIALIZATION
566 || pMod->enmState == KLDRSTATE_INITIALIZING);
567 pMod->cRefs++;
568 pMod->cDynRefs++;
569 return 0;
570}
571
572
573/**
[2842]574 * Decrement the dynamic load count of the module and unload the module
575 * if the total reference count reaches zero.
576 *
577 * This may cause a cascade of unloading to occure. See kldrDyldModUnloadPrerequisites().
578 *
579 * @returns status code.
580 * @retval 0 on success.
581 * @retval KLDR_ERR_NOT_LOADED_DYNAMICALLY if the module wasn't loaded dynamically.
582 * @param pMod The module to unload.
583 */
584int kldrDyldModDynamicUnload(PKLDRDYLDMOD pMod)
585{
586 if (pMod->cDynRefs == 0)
587 return KLDR_ERR_NOT_LOADED_DYNAMICALLY;
588 KLDRDYLDMOD_ASSERT(pMod->cDynRefs <= pMod->cRefs);
589 KLDRDYLDMOD_ASSERT(pMod->enmState == KLDRSTATE_GOOD);
[2837]590
[2842]591 pMod->cRefs--;
592 pMod->cDynRefs--;
[2845]593 if ( pMod->cDynRefs > 0
594 || pMod->cDepRefs > 0)
[2842]595 return 0;
596
597 /*
598 * The module should be unloaded.
599 */
600 kldrDyldModUnloadPrerequisites(pMod);
601 return 0;
602}
603
604
605/**
606 * Worker for kldrDyldModUnloadPrerequisites.
607 *
608 * @returns The number of modules that now can be unloaded.
609 * @param pMod The module in question.
610 */
611static uint32_t kldrDyldModUnloadPrerequisitesOne(PKLDRDYLDMOD pMod)
612{
613 PKLDRDYLDMOD pMod2;
614 uint32_t cToUnload = 0;
615 uint32_t i;
616
[2869]617 KLDRDYLDMOD_ASSERT(pMod->papPrereqs || !pMod->cPrereqs);
[2842]618
619 /*
620 * Release the one in this module.
621 */
622 for (i = 0; i < pMod->cPrereqs; i++)
623 {
624 pMod2 = pMod->papPrereqs[i];
625 if (pMod2)
626 {
[2847]627 pMod->papPrereqs[i] = NULL;
628
[2842]629 /* do the derefering ourselves or we'll end up in a recursive loop here. */
630 KLDRDYLDMOD_ASSERT(pMod2->cDepRefs > 0);
631 KLDRDYLDMOD_ASSERT(pMod2->cRefs >= pMod2->cDepRefs);
632 pMod2->cDepRefs--;
633 pMod2->cRefs--;
[2869]634 cToUnload += !pMod2->cDepRefs && !pMod2->cDynRefs;
[2842]635 }
636 }
637
638 /*
639 * Change the state
640 */
641 switch (pMod->enmState)
642 {
643 case KLDRSTATE_LOADED_PREREQUISITES:
644 case KLDRSTATE_FIXED_UP:
645 pMod->enmState = KLDRSTATE_PENDING_DESTROY;
646 kldrDyldModUnlink(pMod);
647 break;
648
649 case KLDRSTATE_PENDING_INITIALIZATION:
650 pMod->enmState = KLDRSTATE_PENDING_GC;
651 break;
652
653 case KLDRSTATE_RELOADED_FIXED_UP:
654 case KLDRSTATE_RELOADED_LOADED_PREREQUISITES:
655 case KLDRSTATE_GOOD:
656 pMod->enmState = KLDRSTATE_PENDING_TERMINATION;
657 break;
658
659 case KLDRSTATE_INITIALIZATION_FAILED:
660 break;
661
662 default:
663 KLDRDYLDMOD_ASSERT(!"invalid state");
664 break;
665 }
666
667 return cToUnload;
668}
669
670
671/**
672 * This is the heart of the unload code.
673 *
674 * It will recursivly (using the load list) initiate module unloading
675 * of all affected modules.
676 *
[2845]677 * This function will cause a state transition to PENDING_DESTROY, PENDING_GC
[2842]678 * or PENDING_TERMINATION depending on the module state. There is one exception
679 * to this, and that's INITIALIZATION_FAILED, where the state will not be changed.
680 *
681 * @param pMod The module which prerequisites should be unloaded.
682 */
[2837]683void kldrDyldModUnloadPrerequisites(PKLDRDYLDMOD pMod)
684{
[2842]685 uint32_t cToUnload;
[2837]686
[2842]687 /* sanity */
688#ifdef KLDRDYLD_STRICT
689 {
690 PKLDRDYLDMOD pMod2;
691 for (pMod2 = kLdrDyldHead; pMod2; pMod2 = pMod2->Load.pNext)
692 KLDRDYLDMOD_ASSERT(pMod2->enmState != KLDRSTATE_GOOD || pMod2->cRefs);
693 }
694#endif
695 KLDRDYLDMOD_ASSERT(pMod->papPrereqs);
696
697 /*
698 * Unload prereqs of the module we're called on first.
699 */
700 cToUnload = kldrDyldModUnloadPrerequisitesOne(pMod);
701
702 /*
703 * Iterate the load list in a cyclic manner until there are no more
704 * modules that can be pushed on into unloading.
705 */
706 while (cToUnload)
707 {
708 cToUnload = 0;
709 for (pMod = kLdrDyldHead; pMod; pMod = pMod->Load.pNext)
710 {
[2869]711 if ( pMod->cDepRefs
712 || pMod->cDynRefs
[2842]713 || pMod->enmState >= KLDRSTATE_PENDING_TERMINATION
714 || pMod->enmState < KLDRSTATE_LOADED_PREREQUISITES)
715 continue;
716 cToUnload += kldrDyldModUnloadPrerequisitesOne(pMod);
717 }
718 }
[2837]719}
720
721
[2847]722/**
723 * Loads the prerequisite modules this module depends on.
724 *
725 * To find each of the prerequisite modules this method calls
726 * kldrDyldGetPrerequisite() and it will make sure the modules
727 * are added to the load stack frame.
728 *
729 * @returns 0 on success, non-zero native OS or kLdr status code on failure.
730 * The state is changed to LOADED_PREREQUISITES or RELOADED_LOADED_PREREQUISITES.
731 * @param pMod The module.
732 * @param pszPrefix Prefix to use when searching.
733 * @param pszSuffix Suffix to use when searching.
734 * @param enmSearch Method to use when locating the module and any modules it may depend on.
735 * @param fFlags Flags, a combintation of the KLDRYDLD_LOAD_FLAGS_* \#defines.
736 */
[2845]737int kldrDyldModLoadPrerequisites(PKLDRDYLDMOD pMod, const char *pszPrefix, const char *pszSuffix,
738 KLDRDYLDSEARCH enmSearch, unsigned fFlags)
739{
[2847]740 int32_t cPrereqs;
741 uint32_t i;
742 int rc = 0;
[2846]743
[2847]744 /* sanity */
745 switch (pMod->enmState)
746 {
747 case KLDRSTATE_MAPPED:
748 case KLDRSTATE_RELOADED:
749 break;
750 default:
751 KLDRDYLDMOD_ASSERT(!"invalid state");
752 return -1;
753 }
[2842]754
[2847]755 /*
756 * Query number of prerequiste modules and allocate the array.
757 */
[2848]758 cPrereqs = kLdrModNumberOfImports(pMod->pMod, NULL);
[2847]759 kldrHlpAssert(cPrereqs >= 0);
760 if (pMod->cPrereqs != cPrereqs)
761 {
762 KLDRDYLDMOD_ASSERT(!pMod->papPrereqs);
763 pMod->papPrereqs = (PPKLDRDYLDMOD)kldrHlpAllocZ(sizeof(pMod->papPrereqs[0]) * cPrereqs);
764 if (!pMod->papPrereqs)
765 return KLDR_ERR_NO_MEMORY;
766 pMod->cPrereqs = cPrereqs;
767 }
768 else
769 KLDRDYLDMOD_ASSERT(pMod->papPrereqs || !pMod->cPrereqs);
[2842]770
[2847]771 /*
772 * Iterate the prerequisites and load them.
773 */
774 for (i = 0; i < pMod->cPrereqs; i++)
775 {
776 static char s_szPrereq[260];
777 PKLDRDYLDMOD pPrereqMod;
778
779 KLDRDYLDMOD_ASSERT(pMod->papPrereqs[i] == NULL);
[2848]780 rc = kLdrModGetImport(pMod->pMod, NULL, i, s_szPrereq, sizeof(s_szPrereq));
[2847]781 if (rc)
782 break;
783 rc = kldrDyldGetPrerequisite(s_szPrereq, pszPrefix, pszSuffix, enmSearch, fFlags, pMod, &pPrereqMod);
784 if (rc)
785 break;
786 pMod->papPrereqs[i] = pPrereqMod;
787 }
788
789 /* change the state regardless of what happend. */
790 if (pMod->enmState == KLDRSTATE_MAPPED)
791 pMod->enmState = KLDRSTATE_LOADED_PREREQUISITES;
792 else
793 pMod->enmState = KLDRSTATE_RELOADED_LOADED_PREREQUISITES;
794 return rc;
[2845]795}
[2842]796
[2845]797
798/**
[2846]799 * Maps an open module.
[2845]800 *
[2846]801 * On success the module will be in the MAPPED state.
[2845]802 *
[2846]803 * @returns 0 on success, non-zero native OS or kLdr status code on failure.
804 * @param pMod The module which needs to be unmapped and set pending for destruction.
[2845]805 */
[2846]806int kldrDyldModMap(PKLDRDYLDMOD pMod)
[2837]807{
[2846]808 int rc;
[2845]809
[2846]810 /* sanity */
811 KLDRDYLDMOD_ASSERT(pMod->enmState == KLDRSTATE_OPEN);
812 KLDRDYLDMOD_ASSERT(!pMod->fMapped);
813 if (pMod->fMapped)
814 return 0;
[2845]815
[2846]816 /* do the job. */
817 rc = kLdrModMap(pMod->pMod);
818 if (!rc)
[2845]819 {
[2846]820 rc = kLdrModAllocTLS(pMod->pMod);
821 if (!rc)
[2845]822 {
[2846]823 /** @todo TLS */
824 pMod->fMapped = 1;
825 pMod->enmState = KLDRSTATE_MAPPED;
[2845]826 }
827 else
[2846]828 kLdrModUnmap(pMod->pMod);
[2845]829 }
[2846]830 return rc;
[2845]831}
832
833
834/**
[2846]835 * Unmaps the module, unlinks it from everywhere marks it PENDING_DESTROY.
[2845]836 *
837 * @returns 0 on success, non-zero native OS or kLdr status code on failure.
838 * @param pMod The module which needs to be unmapped and set pending for destruction.
839 */
[2846]840int kldrDyldModUnmap(PKLDRDYLDMOD pMod)
[2845]841{
842 int rc;
843
844 /* sanity */
[2837]845 KLDRDYLDMOD_ASSERT(pMod->cRefs > 0);
[2846]846 KLDRDYLDMOD_ASSERT(pMod->fMapped);
847 switch (pMod->enmState)
848 {
849 case KLDRSTATE_MAPPED:
850 case KLDRSTATE_GC:
851 case KLDRSTATE_PENDING_DESTROY:
852 break;
853 default:
854 KLDRDYLDMOD_ASSERT(!"invalid state");
855 return -1;
856 }
[2837]857
[2845]858 /* do the job. */
[2847]859 if (pMod->fAllocatedTLS)
860 {
861 kLdrModFreeTLS(pMod->pMod);
862 pMod->fAllocatedTLS = 0;
863 }
864 rc = kLdrModUnmap(pMod->pMod);
[2845]865 if (!rc)
866 {
[2847]867 pMod->fMapped = 0;
868 if (pMod->enmState < KLDRSTATE_PENDING_DESTROY)
[2846]869 {
[2847]870 pMod->enmState = KLDRSTATE_PENDING_DESTROY;
871 kldrDyldModUnlink(pMod);
[2846]872 }
[2845]873 }
[2847]874
[2845]875 return rc;
876}
[2837]877
[2845]878
879/**
[2846]880 * Reloads the module.
[2845]881 *
[2846]882 * Reloading means that all modified pages are restored to their original
883 * state. Whether this includes the code segments depends on whether the fixups
884 * depend on the addend in the place they are fixing up - so it's format specific.
885 *
[2845]886 * @returns 0 on success, non-zero native OS or kLdr status code on failure.
887 * @param pMod The module which needs to be unmapped and set pending for destruction.
888 */
[2846]889int kldrDyldModReload(PKLDRDYLDMOD pMod)
[2845]890{
891 int rc;
892
893 /* sanity */
894 KLDRDYLDMOD_ASSERT(pMod->cRefs > 0);
895 KLDRDYLDMOD_ASSERT(pMod->fMapped);
[2846]896
[2837]897 switch (pMod->enmState)
898 {
899 case KLDRSTATE_MAPPED:
900 case KLDRSTATE_GC:
901 case KLDRSTATE_PENDING_DESTROY:
902 break;
903 default:
[2845]904 KLDRDYLDMOD_ASSERT(!"invalid state");
905 return -1;
[2837]906 }
907
[2847]908 /* Free TLS before reloading. */
909 if (pMod->fAllocatedTLS)
910 {
911 kLdrModFreeTLS(pMod->pMod);
912 pMod->fAllocatedTLS = 0;
913 }
914
[2846]915 /* Let the module interpreter do the reloading of the mapping. */
916 rc = kLdrModReload(pMod->pMod);
[2845]917 if (!rc)
[2837]918 {
[2847]919 rc = kLdrModAllocTLS(pMod->pMod);
[2846]920 if (!rc)
[2837]921 {
[2847]922 pMod->fAllocatedTLS = 1;
923 pMod->enmState = KLDRSTATE_RELOADED;
[2845]924 }
925 }
926 return rc;
927}
[2837]928
929
[2850]930/**
931 * @copydoc FNKLDRMODGETIMPORT
932 * pvUser points to the KLDRDYLDMOD.
933 */
[2859]934static int kldrDyldModFixupGetImportCallback(PKLDRMOD pMod, uint32_t iImport, uint32_t iSymbol, const char *pszSymbol,
[2850]935 PKLDRADDR puValue, uint32_t *pfKind, void *pvUser)
936{
[2854]937 static int s_cRecursiveCalls = 0;
938 PKLDRDYLDMOD pDyldMod = (PKLDRDYLDMOD)pvUser;
[2850]939 int rc;
[2846]940
[2854]941 /* guard against too deep forwarder recursion. */
942 if (s_cRecursiveCalls >= 5)
943 return KLDR_ERR_TOO_LONG_FORWARDER_CHAIN;
944 s_cRecursiveCalls++;
945
[2850]946 if (iImport != NIL_KLDRMOD_IMPORT)
947 {
948 /* specific import module search. */
949 PKLDRDYLDMOD pPrereqMod;
950
951 KLDRDYLDMOD_ASSERT(iImport < pDyldMod->cPrereqs);
952 pPrereqMod = pDyldMod->papPrereqs[iImport];
953
954 KLDRDYLDMOD_ASSERT(pPrereqMod);
955 KLDRDYLDMOD_ASSERT(pPrereqMod->u32MagicHead == KLDRDYMOD_MAGIC);
956 KLDRDYLDMOD_ASSERT(pPrereqMod->u32MagicTail == KLDRDYMOD_MAGIC);
957 KLDRDYLDMOD_ASSERT(pPrereqMod->enmState < KLDRSTATE_TERMINATING);
958
959 rc = kLdrModQuerySymbol(pPrereqMod->pMod, NULL, KLDRMOD_BASEADDRESS_MAP,
[2859]960 iSymbol, pszSymbol, kldrDyldModFixupGetImportCallback, pPrereqMod, puValue, pfKind);
[2850]961 if (rc)
962 {
963 if (pszSymbol)
964 kldrDyldFailure(rc, "%s[%d]->%s.%s", pDyldMod->pMod->pszName, iImport,
965 pPrereqMod->pMod->pszName, pszSymbol);
966 else
967 kldrDyldFailure(rc, "%s[%d]->%s.%d", pDyldMod->pMod->pszName, iImport,
[2859]968 pPrereqMod->pMod->pszName, iSymbol);
[2850]969 }
970 }
971 else
972 {
973 /* bind list search. */
974 unsigned fFound = 0;
975 PKLDRDYLDMOD pBindMod = g_pkLdrDyldBindHead;
976 rc = 0;
977 while (pBindMod)
978 {
979 uint32_t fKind;
980 KLDRADDR uValue;
981 rc = kLdrModQuerySymbol(pBindMod->pMod, NULL, KLDRMOD_BASEADDRESS_MAP,
[2859]982 iSymbol, pszSymbol, kldrDyldModFixupGetImportCallback, pBindMod, &uValue, &fKind);
[2850]983 if ( !rc
984 && ( !fFound
985 || !(fKind & KLDRSYMKIND_WEAK)
986 )
987 )
988 {
989 *pfKind = fKind;
990 *puValue = uValue;
991 fFound = 1;
992 if (!(fKind & KLDRSYMKIND_WEAK))
993 break;
994 }
995
996 /* next */
997 pBindMod = pBindMod->Bind.pNext;
998 }
999 rc = fFound ? 0 : KLDR_ERR_SYMBOL_NOT_FOUND;
1000 if (!fFound)
1001 {
1002 if (pszSymbol)
1003 kldrDyldFailure(rc, "%s->%s", pDyldMod->pMod->pszName, pszSymbol);
1004 else
[2859]1005 kldrDyldFailure(rc, "%s->%d", pDyldMod->pMod->pszName, iSymbol);
[2850]1006 }
1007 }
1008
[2854]1009 s_cRecursiveCalls--;
[2850]1010 return rc;
1011}
1012
1013
[2845]1014/**
1015 * Applies fixups to a module which prerequisistes has been
1016 * successfully loaded.
1017 *
1018 * @returns 0 on success, non-zero native OS or kLdr status code on failure.
1019 * @param pMod The module which needs to be unmapped and set pending for destruction.
1020 */
1021int kldrDyldModFixup(PKLDRDYLDMOD pMod)
1022{
1023 int rc;
[2837]1024
[2845]1025 /* sanity */
1026 KLDRDYLDMOD_ASSERT(pMod->cRefs > 0);
1027 KLDRDYLDMOD_ASSERT( pMod->enmState == KLDRSTATE_LOADED_PREREQUISITES
1028 || pMod->enmState == KLDRSTATE_RELOADED_LOADED_PREREQUISITES);
[2837]1029
[2845]1030 /* do the job */
[2883]1031 rc = kLdrModFixupMapping(pMod->pMod, kldrDyldModFixupGetImportCallback, pMod);/** @todo fixme. */
[2845]1032 if (!rc)
1033 pMod->enmState = KLDRSTATE_FIXED_UP;
1034 return rc;
1035}
[2837]1036
[2845]1037
[2846]1038/**
1039 * Calls the module initialization entry point if any.
1040 *
1041 * This is considered to be a module specific thing and leave if
1042 * to the module interpreter. They will have to deal with different
1043 * module init practices between platforms should there be any.
1044 *
1045 * @returns 0 and state changed to GOOD on success.
1046 * Non-zero OS or kLdr status code and status changed to INITIALIZATION_FAILED on failure.
1047 * @param pMod The module that should be initialized.
1048 */
1049int kldrDyldModCallInit(PKLDRDYLDMOD pMod)
1050{
1051 int rc;
[2845]1052
[2869]1053 KLDRDYLDMOD_ASSERT(pMod->enmState == KLDRSTATE_PENDING_INITIALIZATION);
[2871]1054 KLDRDYLDMOD_ASSERT(!pMod->fInitList);
[2845]1055
[2869]1056 pMod->enmState = KLDRSTATE_INITIALIZING;
[2856]1057 rc = kLdrModCallInit(pMod->pMod, (uintptr_t)pMod->hMod);
[2846]1058 if (!rc)
[2869]1059 {
[2846]1060 pMod->enmState = KLDRSTATE_GOOD;
[2869]1061 /* push it onto the termination list.*/
1062 pMod->InitTerm.pPrev = NULL;
1063 pMod->InitTerm.pNext = g_pkLdrDyldTermHead;
1064 if (g_pkLdrDyldTermHead)
1065 g_pkLdrDyldTermHead->InitTerm.pPrev = pMod;
1066 else
1067 g_pkLdrDyldTermTail = pMod;
1068 g_pkLdrDyldTermHead = pMod;
1069 }
[2846]1070 else
1071 pMod->enmState = KLDRSTATE_INITIALIZATION_FAILED;
[2845]1072
[2846]1073 return rc;
1074}
[2845]1075
[2846]1076
1077/**
1078 * Calls the module termination entry point if any.
1079 *
1080 * This'll change the module status to PENDING_GC.
1081 *
1082 * @param pMod The module that should be initialized.
1083 */
1084void kldrDyldModCallTerm(PKLDRDYLDMOD pMod)
1085{
[2869]1086 KLDRDYLDMOD_ASSERT(pMod->enmState == KLDRSTATE_PENDING_TERMINATION);
[2846]1087
[2869]1088 pMod->enmState = KLDRSTATE_TERMINATING;
[2856]1089 kLdrModCallTerm(pMod->pMod, (uintptr_t)pMod->hMod);
[2846]1090 pMod->enmState = KLDRSTATE_PENDING_GC;
[2869]1091 /* unlinking on destruction. */
[2846]1092}
1093
1094
1095/**
1096 * Calls the thread attach entry point if any.
1097 *
1098 * @returns 0 on success, non-zero on failure.
1099 * @param pMod The module.
1100 */
1101int kldrDyldModAttachThread(PKLDRDYLDMOD pMod)
1102{
1103 KLDRDYLDMOD_ASSERT(pMod->enmState == KLDRSTATE_GOOD);
1104
[2856]1105 return kLdrModCallThread(pMod->pMod, (uintptr_t)pMod->hMod, 1 /* attach */);
[2846]1106}
1107
1108
1109/**
1110 * Calls the thread detach entry point if any.
1111 *
1112 * @returns 0 on success, non-zero on failure.
1113 * @param pMod The module.
1114 */
1115void kldrDyldModDetachThread(PKLDRDYLDMOD pMod)
1116{
1117 KLDRDYLDMOD_ASSERT(pMod->enmState == KLDRSTATE_GOOD);
1118
[2856]1119 kLdrModCallThread(pMod->pMod, (uintptr_t)pMod->hMod, 0 /* detach */);
[2846]1120}
1121
1122
1123/**
1124 * Gets the main stack, allocate it if necessary.
1125 *
1126 * @returns 0 on success, non-zero native OS or kLdr status code on failure.
1127 * @param pMod The module.
1128 * @param ppvStack Where to store the address of the stack (lowest address).
1129 * @param pcbStack Where to store the size of the stack.
1130 */
1131int kldrDyldModGetMainStack(PKLDRDYLDMOD pMod, void **ppvStack, size_t *pcbStack)
1132{
1133 int rc = 0;
1134 KLDRSTACKINFO StackInfo;
1135 KLDRDYLDMOD_ASSERT(pMod->fExecutable);
1136
1137 /*
1138 * Since we might have to allocate the stack ourselves, and there will only
1139 * ever be one main stack, we'll be keeping the main stack info in globals.
1140 */
1141 if (!g_fkLdrDyldDoneMainStack)
1142 {
[2848]1143 rc = kLdrModGetStackInfo(pMod->pMod, NULL, KLDRMOD_BASEADDRESS_MAP, &StackInfo);
[2846]1144 if (!rc)
1145 {
1146 /* check if there is a stack size override/default. */
1147 size_t cbDefOverride;
1148 if (kldrHlpGetEnvUZ("KLDR_MAIN_STACK_SIZE", &cbDefOverride))
1149 cbDefOverride = 0;
1150
1151
1152 /* needs allocating? */
[2848]1153 if ( StackInfo.LinkAddress == NIL_KLDRADDR
[2846]1154 || StackInfo.cbStack < cbDefOverride)
1155 {
1156 size_t cbStack = (size_t)KLDR_MAX(StackInfo.cbStack, cbDefOverride);
1157
1158 g_pvkLdrDyldMainStack = kldrDyldOSAllocStack(cbStack);
1159 if (g_pvkLdrDyldMainStack)
1160 {
1161 g_cbkLdrDyldMainStack = cbStack;
1162 g_fkLdrDyldMainStackAllocated = 1;
1163 }
1164 else
1165 rc = KLDR_ERR_MAIN_STACK_ALLOC_FAILED;
1166 }
1167 else
1168 {
[2848]1169 KLDRDYLDMOD_ASSERT(StackInfo.Address != NIL_KLDRADDR);
[2846]1170 KLDRDYLDMOD_ASSERT(StackInfo.cbStack > 0);
1171
1172 g_fkLdrDyldMainStackAllocated = 0;
[2848]1173 g_pvkLdrDyldMainStack = (void *)(uintptr_t)StackInfo.Address;
1174 KLDRDYLDMOD_ASSERT((uintptr_t)g_pvkLdrDyldMainStack == StackInfo.Address);
[2846]1175
1176 g_cbkLdrDyldMainStack = (size_t)StackInfo.cbStack;
1177 KLDRDYLDMOD_ASSERT(StackInfo.cbStack == g_cbkLdrDyldMainStack);
1178 }
1179 }
1180 if (!rc)
1181 g_fkLdrDyldDoneMainStack = 1;
1182 }
1183
1184 if (!rc)
1185 {
1186 if (ppvStack)
1187 *ppvStack = g_pvkLdrDyldMainStack;
1188 if (pcbStack)
1189 *pcbStack = g_cbkLdrDyldMainStack;
1190 }
1191
1192 return rc;
1193}
1194
1195
1196/**
1197 * This starts the executable module.
1198 *
1199 * @returns non-zero OS or kLdr status code on failure.
1200 * (won't return on success.)
1201 * @param pMod The executable module.
1202 */
1203int kldrDyldModStartExe(PKLDRDYLDMOD pMod)
1204{
1205 int rc;
[2848]1206 KLDRADDR MainEPAddress;
[2846]1207 void *pvStack;
1208 size_t cbStack;
1209 KLDRDYLDMOD_ASSERT(pMod->fExecutable);
1210
[2848]1211 rc = kLdrModQueryMainEntrypoint(pMod->pMod, NULL, KLDRMOD_BASEADDRESS_MAP, &MainEPAddress);
[2846]1212 if (rc)
1213 return rc;
1214 rc = kldrDyldModGetMainStack(pMod, &pvStack, &cbStack);
1215 if (rc)
1216 return rc;
[2848]1217 return kldrDyldOSStartExe((uintptr_t)MainEPAddress, pvStack, cbStack);
[2846]1218}
1219
1220
1221/**
1222 * Gets the module name.
1223 *
1224 * @returns 0 on success, KLDR_ERR_BUFFER_OVERFLOW on failure.
1225 * @param pMod The module.
1226 * @param pszName Where to store the name.
1227 * @param cchName The size of the name buffer.
1228 */
1229int kldrDyldModGetName(PKLDRDYLDMOD pMod, char *pszName, size_t cchName)
1230{
1231 size_t cch = KLDR_MIN(cchName, pMod->pMod->cchName + 1);
1232 if (cch)
1233 {
1234 kLdrHlpMemCopy(pszName, pMod->pMod->pszName, cch - 1);
1235 pszName[cch - 1] = '\0';
1236 }
1237 return cchName <= pMod->pMod->cchName ? KLDR_ERR_BUFFER_OVERFLOW : 0;
1238}
1239
1240
1241/**
1242 * Gets the module filename.
1243 *
1244 * @returns 0 on success, KLDR_ERR_BUFFER_OVERFLOW on failure.
1245 * @param pMod The module.
1246 * @param pszFilename Where to store the filename.
1247 * @param cchFilename The size of the filename buffer.
1248 */
1249int kldrDyldModGetFilename(PKLDRDYLDMOD pMod, char *pszFilename, size_t cchFilename)
1250{
1251 size_t cch = KLDR_MIN(cchFilename, pMod->pMod->cchFilename + 1);
1252 if (cch)
1253 {
1254 kLdrHlpMemCopy(pszFilename, pMod->pMod->pszFilename, cch - 1);
1255 pszFilename[cch - 1] = '\0';
1256 }
1257 return cchFilename <= pMod->pMod->cchFilename ? KLDR_ERR_BUFFER_OVERFLOW : 0;
1258}
1259
1260
1261/**
1262 * Gets the address/value of a symbol in the specified module.
1263 *
1264 * @returns 0 on success, KLDR_ERR_SYMBOL_NOT_FOUND on failure.
1265 * @param pMod The module.
1266 * @param uSymbolOrdinal The symbol ordinal 0. This is ignored if the name is non-zero.
1267 * @param pszSymbolName The symbol name. Can be NULL.
1268 * @param puValue Where to store the value. optional.
1269 * @param pfKind Where to store the symbol kind. optional.
1270 */
1271int kldrDyldModQuerySymbol(PKLDRDYLDMOD pMod, uint32_t uSymbolOrdinal, const char *pszSymbolName,
1272 uintptr_t *puValue, uint32_t *pfKind)
1273{
1274 int rc;
[2848]1275 KLDRADDR uValue = 0;
[2846]1276 uint32_t fKind = 0;
1277
1278 rc = kLdrModQuerySymbol(pMod->pMod, NULL, KLDRMOD_BASEADDRESS_MAP,
[2855]1279 uSymbolOrdinal, pszSymbolName, kldrDyldModFixupGetImportCallback, pMod,
[2854]1280 &uValue, &fKind);
[2846]1281 if (!rc)
1282 {
1283 if (puValue)
1284 {
1285 *puValue = (uintptr_t)uValue;
1286 KLDRDYLDMOD_ASSERT(*puValue == uValue);
1287 }
1288 if (pfKind)
1289 *pfKind = fKind;
1290 }
1291
1292 return rc;
1293}
1294
Note: See TracBrowser for help on using the repository browser.