source: trunk/kLdr/kLdrDyldMod.c@ 2878

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

Keywords.

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