Changeset 2846
- Timestamp:
- Nov 1, 2006, 7:26:35 PM (19 years ago)
- Location:
- trunk/kLdr
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kLdr/Makefile.kmk
r2836 r2846 94 94 kLdrDyldFind.c \ 95 95 kLdrDyldMod.c \ 96 kLdrDyldOS.c \ 96 97 kLdrHlp.c \ 97 98 kLdrHlpHeap.c \ -
trunk/kLdr/kLdr.h
r2845 r2846 269 269 { 270 270 /** The base address of the stack (sub) segment, link address. 271 * Set this to ~(uint ptr_t)0 if the module doesn't include any stack (sub)segment. */271 * Set this to ~(uintmax_t)0 if the module doesn't include any stack (sub)segment. */ 272 272 uintmax_t uLinkAddress; 273 273 /** The base address of the stack (sub) segment, actual load address. 274 * Set this to ~(uint ptr_t)0 if the module doesn't include any stack (sub)segment or if274 * Set this to ~(uintmax_t)0 if the module doesn't include any stack (sub)segment or if 275 275 * the module isn't mapped (loaded) yet. */ 276 276 uintmax_t uLoadAddress; … … 560 560 int kLdrModOpenNative(const char *pszFilename, PPKLDRMOD ppMod); 561 561 int kLdrModClose(PKLDRMOD pMod); 562 int kLdrMod GetSymbol(PKLDRMOD pMod, const void *pvBits, uintmax_t BaseAddress, const char *pszSymbol, uintmax_t *pValue, uint32_t *pfKind);562 int kLdrModQuerySymbol(PKLDRMOD pMod, const void *pvBits, uintmax_t BaseAddress, const char *pszSymbol, uintmax_t *pValue, uint32_t *pfKind); 563 563 int kLdrModEnumSymbols(PKLDRMOD pMod, unsigned fFlags, const void *pvBits, uintmax_t BaseAddress, PFNKLDRMODENUMSYMS pfnCallback, void *pvUser); 564 564 int kLdrModEnumImportModules(PKLDRMOD pMod, unsigned fFlags, const void *pvBits, FNKLDRMODENUMIMPMODS pfnCallback, void *pvUser); … … 571 571 int kLdrModCanExecuteOn(PKLDRMOD pMod, KLDRARCH enmArch, KLDRCPU enmCpu); 572 572 int kLdrModGetStackInfo(PKLDRMOD pMod, PKLDRSTACKINFO pStackInfo); 573 int kLdrModQueryMainEntrypoint(PKLDRMOD pMod, void *pvBits, uintmax_t uBaseAddress, uintmax_t *puValue); 574 int kLdrModAllocTLS(PKLDRMOD pMod); 575 int kLdrModFreeTLS(PKLDRMOD pMod); 576 int kLdrModReload(PKLDRMOD pMod); 577 int kLdrModCallInit(PKLDRMOD pMod); 578 int kLdrModCallTerm(PKLDRMOD pMod); 579 int kLdrModCallThread(PKLDRMOD pMod, unsigned fAttachingOrDetaching); 573 580 574 581 /** @} */ … … 771 778 /** Prerequisite recursed too deeply. */ 772 779 #define KLDR_ERR_PREREQUISITE_RECURSED_TOO_DEEPLY (KLDR_ERR_BASE + 43) 773 780 /** Failed to allocate the main stack. */ 781 #define KLDR_ERR_MAIN_STACK_ALLOC_FAILED (KLDR_ERR_BASE + 44) 782 /** Buffer overflow. */ 783 #define KLDR_ERR_BUFFER_OVERFLOW (KLDR_ERR_BASE + 45) 774 784 775 785 /** Encountered a bad fixup. */ -
trunk/kLdr/kLdrDyld.c
r2845 r2846 107 107 108 108 109 /** @name The main stack. 110 * @{ */ 111 /** Indicates that the other MainStack globals have been filled in. */ 112 unsigned g_fkLdrDyldDoneMainStack = 0; 113 /** Whether the stack was allocated seperatly or was part of the executable. */ 114 unsigned g_fkLdrDyldMainStackAllocated = 0; 115 /** Pointer to the main stack object. */ 116 void *g_pvkLdrDyldMainStack = NULL; 117 /** The size of the main stack object. */ 118 size_t g_cbkLdrDyldMainStack = 0; 119 /** @} */ 120 121 109 122 /** The load stack. 110 123 * This contains frames with modules affected by active loads. … … 186 199 kLdrDyldFlags = 0; 187 200 g_szkLdrDyldError[0] = '\0'; 201 202 g_fkLdrDyldDoneMainStack = 0; 203 g_fkLdrDyldMainStackAllocated = 0; 204 g_pvkLdrDyldMainStack = NULL; 205 g_cbkLdrDyldMainStack = 0; 206 188 207 return 0; 189 208 } … … 257 276 258 277 /* 259 * Query the stack informationand go to OS specific code to278 * Query the stack and go to OS specific code to 260 279 * setup and switch stack. The OS specific code will call us 261 280 * back at kldrDyldDoLoadExe. 262 281 */ 263 rc = kldrDyldModGet StackInfo(pExe, &pvStack, &cbStack);282 rc = kldrDyldModGetMainStack(pExe, &pvStack, &cbStack); 264 283 if (rc) 265 284 kldrDyldFailure(rc, "Failed to map the executable '%s', rc=%d", pExe->pMod->pszFilename, rc); -
trunk/kLdr/kLdrDyldMod.c
r2845 r2846 100 100 pMod->fAlreadySeen = 0; 101 101 pMod->fMapped = 0; 102 pMod->f26Reserved = 0; 102 pMod->fAllocatedTLS = 0; 103 pMod->f25Reserved = 0; 103 104 pMod->InitTerm.pNext = NULL; 104 105 pMod->InitTerm.pPrev = NULL; … … 249 250 pMod->InitTerm.pNext = NULL; 250 251 pMod->InitTerm.pPrev = NULL; 251 }252 253 254 /**255 * Adds a reference to the module making sure it won't be freed just yet.256 *257 * @param pMod The module.258 */259 void kldrDyldModAddRef(PKLDRDYLDMOD pMod)260 {261 pMod->cRefs++;262 }263 264 265 /**266 * Dereference a module.267 *268 * @param pMod269 */270 void kldrDyldModDeref(PKLDRDYLDMOD pMod)271 {272 /* validate input */273 KLDRDYLDMOD_ASSERT(pMod->cRefs > 0);274 KLDRDYLDMOD_ASSERT(pMod->cRefs >= pMod->cDepRefs + pMod->cDynRefs);275 KLDRDYLDMOD_ASSERT(pMod->enmState > KLDRSTATE_INVALID && pMod->enmState <= KLDRSTATE_END);276 277 /* decrement. */278 if (pMod->cRefs > 0)279 pMod->cRefs--;280 281 /* execute delayed freeing. */282 if ( pMod->enmState == KLDRSTATE_DESTROYED283 && !pMod->cRefs)284 kldrHlpFree(pMod);285 }286 287 288 /**289 * Increment the count of modules depending on this module.290 *291 * @param pMod The module.292 * @param pDep The module which depends on us.293 */294 void kldrDyldModAddDep(PKLDRDYLDMOD pMod, PKLDRDYLDMOD pDep)295 {296 (void)pDep;297 298 /* validate state */299 switch (pMod->enmState)300 {301 case KLDRSTATE_MAPPED:302 case KLDRSTATE_RELOADED:303 case KLDRSTATE_LOADED_PREREQUISITES:304 case KLDRSTATE_RELOADED_LOADED_PREREQUISITES:305 case KLDRSTATE_PENDING_INITIALIZATION:306 case KLDRSTATE_INITIALIZING:307 case KLDRSTATE_GOOD:308 break;309 default:310 KLDRDYLDMOD_ASSERT(!"invalid state");311 break;312 313 }314 KLDRDYLDMOD_ASSERT(pMod->enmState > KLDRSTATE_INVALID && pMod->enmState <= KLDRSTATE_END);315 pMod->cRefs++;316 pMod->cDepRefs++;317 }318 319 320 /**321 * Drop a dependency.322 *323 * @param pMod The module.324 * @param pDep The module which depends on us.325 */326 void kldrDyldModRemoveDep(PKLDRDYLDMOD pMod, PKLDRDYLDMOD pDep)327 {328 KLDRDYLDMOD_ASSERT(pMod->cDepRefs > 0);329 if (pMod->cDepRefs == 0)330 return;331 KLDRDYLDMOD_ASSERT(pMod->cDepRefs <= pMod->cRefs);332 KLDRDYLDMOD_ASSERT(pMod->enmState >= KLDRSTATE_MAPPED && pMod->enmState <= KLDRSTATE_PENDING_DESTROY);333 334 pMod->cRefs--;335 pMod->cDepRefs--;336 if ( pMod->cDepRefs > 0337 || pMod->cDynRefs > 0)338 return;339 340 /*341 * The module should be unloaded.342 */343 kldrDyldModUnloadPrerequisites(pMod);344 }345 346 347 /**348 * Increment the dynamic load count.349 *350 * @returns 0351 * @param pMod The module.352 */353 int kldrDyldModDynamicLoad(PKLDRDYLDMOD pMod)354 {355 KLDRDYLDMOD_ASSERT( pMod->enmState == KLDRSTATE_GOOD356 || pMod->enmState == KLDRSTATE_PENDING_INITIALIZATION357 || pMod->enmState == KLDRSTATE_INITIALIZING);358 pMod->cRefs++;359 pMod->cDynRefs++;360 return 0;361 }362 363 364 /**365 * Decrement the dynamic load count of the module and unload the module366 * if the total reference count reaches zero.367 *368 * This may cause a cascade of unloading to occure. See kldrDyldModUnloadPrerequisites().369 *370 * @returns status code.371 * @retval 0 on success.372 * @retval KLDR_ERR_NOT_LOADED_DYNAMICALLY if the module wasn't loaded dynamically.373 * @param pMod The module to unload.374 */375 int kldrDyldModDynamicUnload(PKLDRDYLDMOD pMod)376 {377 if (pMod->cDynRefs == 0)378 return KLDR_ERR_NOT_LOADED_DYNAMICALLY;379 KLDRDYLDMOD_ASSERT(pMod->cDynRefs <= pMod->cRefs);380 KLDRDYLDMOD_ASSERT(pMod->enmState == KLDRSTATE_GOOD);381 382 pMod->cRefs--;383 pMod->cDynRefs--;384 if ( pMod->cDynRefs > 0385 || pMod->cDepRefs > 0)386 return 0;387 388 /*389 * The module should be unloaded.390 */391 kldrDyldModUnloadPrerequisites(pMod);392 return 0;393 }394 395 396 /**397 * Worker for kldrDyldModUnloadPrerequisites.398 *399 * @returns The number of modules that now can be unloaded.400 * @param pMod The module in question.401 */402 static uint32_t kldrDyldModUnloadPrerequisitesOne(PKLDRDYLDMOD pMod)403 {404 PKLDRDYLDMOD pMod2;405 uint32_t cToUnload = 0;406 uint32_t i;407 408 KLDRDYLDMOD_ASSERT(pMod->papPrereqs);409 410 /*411 * Release the one in this module.412 */413 for (i = 0; i < pMod->cPrereqs; i++)414 {415 pMod2 = pMod->papPrereqs[i];416 if (pMod2)417 {418 /* do the derefering ourselves or we'll end up in a recursive loop here. */419 KLDRDYLDMOD_ASSERT(pMod2->cDepRefs > 0);420 KLDRDYLDMOD_ASSERT(pMod2->cRefs >= pMod2->cDepRefs);421 pMod2->cDepRefs--;422 pMod2->cRefs--;423 cToUnload += !pMod2->cRefs;424 }425 }426 427 /*428 * Change the state429 */430 switch (pMod->enmState)431 {432 case KLDRSTATE_LOADED_PREREQUISITES:433 case KLDRSTATE_FIXED_UP:434 pMod->enmState = KLDRSTATE_PENDING_DESTROY;435 kldrDyldModUnlink(pMod);436 break;437 438 case KLDRSTATE_PENDING_INITIALIZATION:439 pMod->enmState = KLDRSTATE_PENDING_GC;440 break;441 442 case KLDRSTATE_RELOADED_FIXED_UP:443 case KLDRSTATE_RELOADED_LOADED_PREREQUISITES:444 case KLDRSTATE_GOOD:445 pMod->enmState = KLDRSTATE_PENDING_TERMINATION;446 break;447 448 case KLDRSTATE_INITIALIZATION_FAILED:449 break;450 451 default:452 KLDRDYLDMOD_ASSERT(!"invalid state");453 break;454 }455 456 return cToUnload;457 }458 459 460 /**461 * This is the heart of the unload code.462 *463 * It will recursivly (using the load list) initiate module unloading464 * of all affected modules.465 *466 * This function will cause a state transition to PENDING_DESTROY, PENDING_GC467 * or PENDING_TERMINATION depending on the module state. There is one exception468 * to this, and that's INITIALIZATION_FAILED, where the state will not be changed.469 *470 * @param pMod The module which prerequisites should be unloaded.471 */472 void kldrDyldModUnloadPrerequisites(PKLDRDYLDMOD pMod)473 {474 uint32_t cToUnload;475 476 /* sanity */477 #ifdef KLDRDYLD_STRICT478 {479 PKLDRDYLDMOD pMod2;480 for (pMod2 = kLdrDyldHead; pMod2; pMod2 = pMod2->Load.pNext)481 KLDRDYLDMOD_ASSERT(pMod2->enmState != KLDRSTATE_GOOD || pMod2->cRefs);482 }483 #endif484 KLDRDYLDMOD_ASSERT(pMod->papPrereqs);485 486 /*487 * Unload prereqs of the module we're called on first.488 */489 cToUnload = kldrDyldModUnloadPrerequisitesOne(pMod);490 491 /*492 * Iterate the load list in a cyclic manner until there are no more493 * modules that can be pushed on into unloading.494 */495 while (cToUnload)496 {497 cToUnload = 0;498 for (pMod = kLdrDyldHead; pMod; pMod = pMod->Load.pNext)499 {500 if ( pMod->cRefs501 || pMod->enmState >= KLDRSTATE_PENDING_TERMINATION502 || pMod->enmState < KLDRSTATE_LOADED_PREREQUISITES)503 continue;504 cToUnload += kldrDyldModUnloadPrerequisitesOne(pMod);505 }506 }507 }508 509 510 int kldrDyldModLoadPrerequisites(PKLDRDYLDMOD pMod, const char *pszPrefix, const char *pszSuffix,511 KLDRDYLDSEARCH enmSearch, unsigned fFlags)512 {513 return -1;514 }515 516 517 int kldrDyldModCheckPrerequisites(PKLDRDYLDMOD pMod)518 {519 return -1;520 }521 522 523 /**524 * Marks the module as global instead of being specific.525 *526 * A global module can be a matching result when the request527 * doesn't specify a path. A specific module will not match528 * unless the path also matches.529 *530 * @param pMod The module.531 */532 void kldrDyldModMarkGlobal(PKLDRDYLDMOD pMod)533 {534 pMod->fGlobalOrSpecific = 1;535 }536 537 /**538 * Marks the module as specific instead of global.539 *540 * See kldrDyldModMarkGlobal for an explanation of the two terms.541 *542 * @param pMod The module.543 */544 void kldrDyldModMarkSpecific(PKLDRDYLDMOD pMod)545 {546 pMod->fGlobalOrSpecific = 0;547 252 } 548 253 … … 615 320 616 321 /** 322 * Marks the module as global instead of being specific. 323 * 324 * A global module can be a matching result when the request 325 * doesn't specify a path. A specific module will not match 326 * unless the path also matches. 327 * 328 * @param pMod The module. 329 */ 330 void kldrDyldModMarkGlobal(PKLDRDYLDMOD pMod) 331 { 332 pMod->fGlobalOrSpecific = 1; 333 } 334 335 336 /** 337 * Marks the module as specific instead of global. 338 * 339 * See kldrDyldModMarkGlobal for an explanation of the two terms. 340 * 341 * @param pMod The module. 342 */ 343 void kldrDyldModMarkSpecific(PKLDRDYLDMOD pMod) 344 { 345 pMod->fGlobalOrSpecific = 0; 346 } 347 348 349 /** 350 * Adds a reference to the module making sure it won't be freed just yet. 351 * 352 * @param pMod The module. 353 */ 354 void kldrDyldModAddRef(PKLDRDYLDMOD pMod) 355 { 356 pMod->cRefs++; 357 } 358 359 360 /** 361 * Dereference a module. 362 * 363 * @param pMod 364 */ 365 void kldrDyldModDeref(PKLDRDYLDMOD pMod) 366 { 367 /* validate input */ 368 KLDRDYLDMOD_ASSERT(pMod->cRefs > 0); 369 KLDRDYLDMOD_ASSERT(pMod->cRefs >= pMod->cDepRefs + pMod->cDynRefs); 370 KLDRDYLDMOD_ASSERT(pMod->enmState > KLDRSTATE_INVALID && pMod->enmState <= KLDRSTATE_END); 371 372 /* decrement. */ 373 if (pMod->cRefs > 0) 374 pMod->cRefs--; 375 376 /* execute delayed freeing. */ 377 if ( pMod->enmState == KLDRSTATE_DESTROYED 378 && !pMod->cRefs) 379 kldrHlpFree(pMod); 380 } 381 382 383 /** 384 * Increment the count of modules depending on this module. 385 * 386 * @param pMod The module. 387 * @param pDep The module which depends on us. 388 */ 389 void kldrDyldModAddDep(PKLDRDYLDMOD pMod, PKLDRDYLDMOD pDep) 390 { 391 (void)pDep; 392 393 /* validate state */ 394 switch (pMod->enmState) 395 { 396 case KLDRSTATE_MAPPED: 397 case KLDRSTATE_RELOADED: 398 case KLDRSTATE_LOADED_PREREQUISITES: 399 case KLDRSTATE_RELOADED_LOADED_PREREQUISITES: 400 case KLDRSTATE_PENDING_INITIALIZATION: 401 case KLDRSTATE_INITIALIZING: 402 case KLDRSTATE_GOOD: 403 break; 404 default: 405 KLDRDYLDMOD_ASSERT(!"invalid state"); 406 break; 407 408 } 409 KLDRDYLDMOD_ASSERT(pMod->enmState > KLDRSTATE_INVALID && pMod->enmState <= KLDRSTATE_END); 410 pMod->cRefs++; 411 pMod->cDepRefs++; 412 } 413 414 415 /** 416 * Drop a dependency. 417 * 418 * @param pMod The module. 419 * @param pDep The module which depends on us. 420 */ 421 void kldrDyldModRemoveDep(PKLDRDYLDMOD pMod, PKLDRDYLDMOD pDep) 422 { 423 KLDRDYLDMOD_ASSERT(pMod->cDepRefs > 0); 424 if (pMod->cDepRefs == 0) 425 return; 426 KLDRDYLDMOD_ASSERT(pMod->cDepRefs <= pMod->cRefs); 427 KLDRDYLDMOD_ASSERT(pMod->enmState >= KLDRSTATE_MAPPED && pMod->enmState <= KLDRSTATE_PENDING_DESTROY); 428 429 pMod->cRefs--; 430 pMod->cDepRefs--; 431 if ( pMod->cDepRefs > 0 432 || pMod->cDynRefs > 0) 433 return; 434 435 /* 436 * The module should be unloaded. 437 */ 438 kldrDyldModUnloadPrerequisites(pMod); 439 } 440 441 442 /** 443 * Increment the dynamic load count. 444 * 445 * @returns 0 446 * @param pMod The module. 447 */ 448 int kldrDyldModDynamicLoad(PKLDRDYLDMOD pMod) 449 { 450 KLDRDYLDMOD_ASSERT( pMod->enmState == KLDRSTATE_GOOD 451 || pMod->enmState == KLDRSTATE_PENDING_INITIALIZATION 452 || pMod->enmState == KLDRSTATE_INITIALIZING); 453 pMod->cRefs++; 454 pMod->cDynRefs++; 455 return 0; 456 } 457 458 459 /** 460 * Decrement the dynamic load count of the module and unload the module 461 * if the total reference count reaches zero. 462 * 463 * This may cause a cascade of unloading to occure. See kldrDyldModUnloadPrerequisites(). 464 * 465 * @returns status code. 466 * @retval 0 on success. 467 * @retval KLDR_ERR_NOT_LOADED_DYNAMICALLY if the module wasn't loaded dynamically. 468 * @param pMod The module to unload. 469 */ 470 int kldrDyldModDynamicUnload(PKLDRDYLDMOD pMod) 471 { 472 if (pMod->cDynRefs == 0) 473 return KLDR_ERR_NOT_LOADED_DYNAMICALLY; 474 KLDRDYLDMOD_ASSERT(pMod->cDynRefs <= pMod->cRefs); 475 KLDRDYLDMOD_ASSERT(pMod->enmState == KLDRSTATE_GOOD); 476 477 pMod->cRefs--; 478 pMod->cDynRefs--; 479 if ( pMod->cDynRefs > 0 480 || pMod->cDepRefs > 0) 481 return 0; 482 483 /* 484 * The module should be unloaded. 485 */ 486 kldrDyldModUnloadPrerequisites(pMod); 487 return 0; 488 } 489 490 491 /** 492 * Worker for kldrDyldModUnloadPrerequisites. 493 * 494 * @returns The number of modules that now can be unloaded. 495 * @param pMod The module in question. 496 */ 497 static uint32_t kldrDyldModUnloadPrerequisitesOne(PKLDRDYLDMOD pMod) 498 { 499 PKLDRDYLDMOD pMod2; 500 uint32_t cToUnload = 0; 501 uint32_t i; 502 503 KLDRDYLDMOD_ASSERT(pMod->papPrereqs); 504 505 /* 506 * Release the one in this module. 507 */ 508 for (i = 0; i < pMod->cPrereqs; i++) 509 { 510 pMod2 = pMod->papPrereqs[i]; 511 if (pMod2) 512 { 513 /* do the derefering ourselves or we'll end up in a recursive loop here. */ 514 KLDRDYLDMOD_ASSERT(pMod2->cDepRefs > 0); 515 KLDRDYLDMOD_ASSERT(pMod2->cRefs >= pMod2->cDepRefs); 516 pMod2->cDepRefs--; 517 pMod2->cRefs--; 518 cToUnload += !pMod2->cRefs; 519 } 520 } 521 522 /* 523 * Change the state 524 */ 525 switch (pMod->enmState) 526 { 527 case KLDRSTATE_LOADED_PREREQUISITES: 528 case KLDRSTATE_FIXED_UP: 529 pMod->enmState = KLDRSTATE_PENDING_DESTROY; 530 kldrDyldModUnlink(pMod); 531 break; 532 533 case KLDRSTATE_PENDING_INITIALIZATION: 534 pMod->enmState = KLDRSTATE_PENDING_GC; 535 break; 536 537 case KLDRSTATE_RELOADED_FIXED_UP: 538 case KLDRSTATE_RELOADED_LOADED_PREREQUISITES: 539 case KLDRSTATE_GOOD: 540 pMod->enmState = KLDRSTATE_PENDING_TERMINATION; 541 break; 542 543 case KLDRSTATE_INITIALIZATION_FAILED: 544 break; 545 546 default: 547 KLDRDYLDMOD_ASSERT(!"invalid state"); 548 break; 549 } 550 551 return cToUnload; 552 } 553 554 555 /** 556 * This is the heart of the unload code. 557 * 558 * It will recursivly (using the load list) initiate module unloading 559 * of all affected modules. 560 * 561 * This function will cause a state transition to PENDING_DESTROY, PENDING_GC 562 * or PENDING_TERMINATION depending on the module state. There is one exception 563 * to this, and that's INITIALIZATION_FAILED, where the state will not be changed. 564 * 565 * @param pMod The module which prerequisites should be unloaded. 566 */ 567 void kldrDyldModUnloadPrerequisites(PKLDRDYLDMOD pMod) 568 { 569 uint32_t cToUnload; 570 571 /* sanity */ 572 #ifdef KLDRDYLD_STRICT 573 { 574 PKLDRDYLDMOD pMod2; 575 for (pMod2 = kLdrDyldHead; pMod2; pMod2 = pMod2->Load.pNext) 576 KLDRDYLDMOD_ASSERT(pMod2->enmState != KLDRSTATE_GOOD || pMod2->cRefs); 577 } 578 #endif 579 KLDRDYLDMOD_ASSERT(pMod->papPrereqs); 580 581 /* 582 * Unload prereqs of the module we're called on first. 583 */ 584 cToUnload = kldrDyldModUnloadPrerequisitesOne(pMod); 585 586 /* 587 * Iterate the load list in a cyclic manner until there are no more 588 * modules that can be pushed on into unloading. 589 */ 590 while (cToUnload) 591 { 592 cToUnload = 0; 593 for (pMod = kLdrDyldHead; pMod; pMod = pMod->Load.pNext) 594 { 595 if ( pMod->cRefs 596 || pMod->enmState >= KLDRSTATE_PENDING_TERMINATION 597 || pMod->enmState < KLDRSTATE_LOADED_PREREQUISITES) 598 continue; 599 cToUnload += kldrDyldModUnloadPrerequisitesOne(pMod); 600 } 601 } 602 } 603 604 605 int kldrDyldModLoadPrerequisites(PKLDRDYLDMOD pMod, const char *pszPrefix, const char *pszSuffix, 606 KLDRDYLDSEARCH enmSearch, unsigned fFlags) 607 { 608 609 return -1; 610 } 611 612 613 int kldrDyldModCheckPrerequisites(PKLDRDYLDMOD pMod) 614 { 615 return -1; 616 } 617 618 619 /** 617 620 * Maps an open module. 618 621 * … … 637 640 if (!rc) 638 641 { 639 pMod->fMapped = 1; 640 pMod->enmState = KLDRSTATE_MAPPED; 642 rc = kLdrModAllocTLS(pMod->pMod); 643 if (!rc) 644 { 645 /** @todo TLS */ 646 pMod->fMapped = 1; 647 pMod->enmState = KLDRSTATE_MAPPED; 648 } 649 else 650 kLdrModUnmap(pMod->pMod); 641 651 } 642 652 return rc; … … 669 679 670 680 /* do the job. */ 671 rc = kLdrMod Unmap(pMod->pMod);681 rc = kLdrModFreeTLS(pMod->pMod); 672 682 if (!rc) 673 683 { 674 pMod->fMapped = 0;675 if ( pMod->enmState < KLDRSTATE_PENDING_DESTROY)684 rc = kLdrModUnmap(pMod->pMod); 685 if (!rc) 676 686 { 677 pMod->enmState = KLDRSTATE_PENDING_DESTROY; 678 kldrDyldModUnlink(pMod); 687 pMod->fMapped = 0; 688 if (pMod->enmState < KLDRSTATE_PENDING_DESTROY) 689 { 690 pMod->enmState = KLDRSTATE_PENDING_DESTROY; 691 kldrDyldModUnlink(pMod); 692 } 679 693 } 694 else 695 kLdrModAllocTLS(pMod->pMod); 680 696 } 681 697 return rc; 682 698 } 699 700 701 /** 702 * Reloads the module. 703 * 704 * Reloading means that all modified pages are restored to their original 705 * state. Whether this includes the code segments depends on whether the fixups 706 * depend on the addend in the place they are fixing up - so it's format specific. 707 * 708 * @returns 0 on success, non-zero native OS or kLdr status code on failure. 709 * @param pMod The module which needs to be unmapped and set pending for destruction. 710 */ 711 int kldrDyldModReload(PKLDRDYLDMOD pMod) 712 { 713 int rc; 714 715 /* sanity */ 716 KLDRDYLDMOD_ASSERT(pMod->cRefs > 0); 717 KLDRDYLDMOD_ASSERT(pMod->fMapped); 718 KLDRDYLDMOD_ASSERT(pMod->fAllocatedTLS); 719 720 switch (pMod->enmState) 721 { 722 case KLDRSTATE_MAPPED: 723 case KLDRSTATE_GC: 724 case KLDRSTATE_PENDING_DESTROY: 725 break; 726 default: 727 KLDRDYLDMOD_ASSERT(!"invalid state"); 728 return -1; 729 } 730 731 /* Let the module interpreter do the reloading of the mapping. */ 732 rc = kLdrModReload(pMod->pMod); 733 if (!rc) 734 { 735 /* Free and allocate the TLS anew to ensure we get clean entries. */ 736 if (pMod->fAllocatedTLS) 737 rc = kLdrModFreeTLS(pMod->pMod); 738 if (!rc) 739 { 740 pMod->fAllocatedTLS = 0; 741 rc = kLdrModAllocTLS(pMod->pMod); 742 if (!rc) 743 { 744 pMod->fAllocatedTLS = 1; 745 pMod->enmState = KLDRSTATE_RELOADED; 746 } 747 } 748 } 749 return rc; 750 } 751 683 752 684 753 … … 707 776 708 777 709 int kldrDyldModCallInit(PKLDRDYLDMOD pMod); 710 void kldrDyldModCallTerm(PKLDRDYLDMOD pMod); 711 712 int kldrDyldModReload(PKLDRDYLDMOD pMod); 713 int kldrDyldModAttachThread(PKLDRDYLDMOD pMod); 714 int kldrDyldModDetachThread(PKLDRDYLDMOD pMod); 715 int kldrDyldModGetStackInfo(PKLDRDYLDMOD pMod, void **ppvStack, size_t *pcbStack); 716 int kldrDyldModStartExe(PKLDRDYLDMOD pMod); 717 718 int kldrDyldModGetName(PKLDRDYLDMOD pMod, char *pszName, size_t cchName); 719 int kldrDyldModGetFilename(PKLDRDYLDMOD pMod, char *pszFilename, size_t cchFilename); 720 int kldrDyldModQuerySymbol(PKLDRDYLDMOD pMod, uint32_t uSymbolOrdinal, const char *pszSymbolName, uintptr_t *pValue, uint32_t *pfKind); 721 722 778 /** 779 * Calls the module initialization entry point if any. 780 * 781 * This is considered to be a module specific thing and leave if 782 * to the module interpreter. They will have to deal with different 783 * module init practices between platforms should there be any. 784 * 785 * @returns 0 and state changed to GOOD on success. 786 * Non-zero OS or kLdr status code and status changed to INITIALIZATION_FAILED on failure. 787 * @param pMod The module that should be initialized. 788 */ 789 int kldrDyldModCallInit(PKLDRDYLDMOD pMod) 790 { 791 int rc; 792 793 KLDRDYLDMOD_ASSERT(pMod->enmState == KLDRSTATE_INITIALIZING); 794 795 rc = kLdrModCallInit(pMod->pMod); 796 if (!rc) 797 pMod->enmState = KLDRSTATE_GOOD; 798 else 799 pMod->enmState = KLDRSTATE_INITIALIZATION_FAILED; 800 801 return rc; 802 } 803 804 805 /** 806 * Calls the module termination entry point if any. 807 * 808 * This'll change the module status to PENDING_GC. 809 * 810 * @param pMod The module that should be initialized. 811 */ 812 void kldrDyldModCallTerm(PKLDRDYLDMOD pMod) 813 { 814 KLDRDYLDMOD_ASSERT(pMod->enmState == KLDRSTATE_TERMINATING); 815 816 kLdrModCallTerm(pMod->pMod); 817 pMod->enmState = KLDRSTATE_PENDING_GC; 818 } 819 820 821 /** 822 * Calls the thread attach entry point if any. 823 * 824 * @returns 0 on success, non-zero on failure. 825 * @param pMod The module. 826 */ 827 int kldrDyldModAttachThread(PKLDRDYLDMOD pMod) 828 { 829 KLDRDYLDMOD_ASSERT(pMod->enmState == KLDRSTATE_GOOD); 830 831 return kLdrModCallThread(pMod->pMod, 1 /* attach */); 832 } 833 834 835 /** 836 * Calls the thread detach entry point if any. 837 * 838 * @returns 0 on success, non-zero on failure. 839 * @param pMod The module. 840 */ 841 void kldrDyldModDetachThread(PKLDRDYLDMOD pMod) 842 { 843 KLDRDYLDMOD_ASSERT(pMod->enmState == KLDRSTATE_GOOD); 844 845 kLdrModCallThread(pMod->pMod, 0 /* detach */); 846 } 847 848 849 /** 850 * Gets the main stack, allocate it if necessary. 851 * 852 * @returns 0 on success, non-zero native OS or kLdr status code on failure. 853 * @param pMod The module. 854 * @param ppvStack Where to store the address of the stack (lowest address). 855 * @param pcbStack Where to store the size of the stack. 856 */ 857 int kldrDyldModGetMainStack(PKLDRDYLDMOD pMod, void **ppvStack, size_t *pcbStack) 858 { 859 int rc = 0; 860 KLDRSTACKINFO StackInfo; 861 KLDRDYLDMOD_ASSERT(pMod->fExecutable); 862 863 /* 864 * Since we might have to allocate the stack ourselves, and there will only 865 * ever be one main stack, we'll be keeping the main stack info in globals. 866 */ 867 if (!g_fkLdrDyldDoneMainStack) 868 { 869 rc = kLdrModGetStackInfo(pMod->pMod, &StackInfo); 870 if (!rc) 871 { 872 /* check if there is a stack size override/default. */ 873 size_t cbDefOverride; 874 if (kldrHlpGetEnvUZ("KLDR_MAIN_STACK_SIZE", &cbDefOverride)) 875 cbDefOverride = 0; 876 877 878 /* needs allocating? */ 879 if ( StackInfo.uLinkAddress == ~(uintmax_t)0 880 || StackInfo.cbStack < cbDefOverride) 881 { 882 size_t cbStack = (size_t)KLDR_MAX(StackInfo.cbStack, cbDefOverride); 883 884 g_pvkLdrDyldMainStack = kldrDyldOSAllocStack(cbStack); 885 if (g_pvkLdrDyldMainStack) 886 { 887 g_cbkLdrDyldMainStack = cbStack; 888 g_fkLdrDyldMainStackAllocated = 1; 889 } 890 else 891 rc = KLDR_ERR_MAIN_STACK_ALLOC_FAILED; 892 } 893 else 894 { 895 KLDRDYLDMOD_ASSERT(StackInfo.uLoadAddress != ~(uintmax_t)0); 896 KLDRDYLDMOD_ASSERT(StackInfo.cbStack > 0); 897 898 g_fkLdrDyldMainStackAllocated = 0; 899 g_pvkLdrDyldMainStack = (void *)(uintptr_t)StackInfo.uLoadAddress; 900 KLDRDYLDMOD_ASSERT((uintptr_t)g_pvkLdrDyldMainStack == StackInfo.uLoadAddress); 901 902 g_cbkLdrDyldMainStack = (size_t)StackInfo.cbStack; 903 KLDRDYLDMOD_ASSERT(StackInfo.cbStack == g_cbkLdrDyldMainStack); 904 } 905 } 906 if (!rc) 907 g_fkLdrDyldDoneMainStack = 1; 908 } 909 910 if (!rc) 911 { 912 if (ppvStack) 913 *ppvStack = g_pvkLdrDyldMainStack; 914 if (pcbStack) 915 *pcbStack = g_cbkLdrDyldMainStack; 916 } 917 918 return rc; 919 } 920 921 922 /** 923 * This starts the executable module. 924 * 925 * @returns non-zero OS or kLdr status code on failure. 926 * (won't return on success.) 927 * @param pMod The executable module. 928 */ 929 int kldrDyldModStartExe(PKLDRDYLDMOD pMod) 930 { 931 int rc; 932 uintmax_t uValue; 933 void *pvStack; 934 size_t cbStack; 935 KLDRDYLDMOD_ASSERT(pMod->fExecutable); 936 937 rc = kLdrModQueryMainEntrypoint(pMod->pMod, NULL, KLDRMOD_BASEADDRESS_MAP, &uValue); 938 if (rc) 939 return rc; 940 rc = kldrDyldModGetMainStack(pMod, &pvStack, &cbStack); 941 if (rc) 942 return rc; 943 return kldrDyldOSStartExe((uintptr_t)uValue, pvStack, cbStack); 944 } 945 946 947 /** 948 * Gets the module name. 949 * 950 * @returns 0 on success, KLDR_ERR_BUFFER_OVERFLOW on failure. 951 * @param pMod The module. 952 * @param pszName Where to store the name. 953 * @param cchName The size of the name buffer. 954 */ 955 int kldrDyldModGetName(PKLDRDYLDMOD pMod, char *pszName, size_t cchName) 956 { 957 size_t cch = KLDR_MIN(cchName, pMod->pMod->cchName + 1); 958 if (cch) 959 { 960 kLdrHlpMemCopy(pszName, pMod->pMod->pszName, cch - 1); 961 pszName[cch - 1] = '\0'; 962 } 963 return cchName <= pMod->pMod->cchName ? KLDR_ERR_BUFFER_OVERFLOW : 0; 964 } 965 966 967 /** 968 * Gets the module filename. 969 * 970 * @returns 0 on success, KLDR_ERR_BUFFER_OVERFLOW on failure. 971 * @param pMod The module. 972 * @param pszFilename Where to store the filename. 973 * @param cchFilename The size of the filename buffer. 974 */ 975 int kldrDyldModGetFilename(PKLDRDYLDMOD pMod, char *pszFilename, size_t cchFilename) 976 { 977 size_t cch = KLDR_MIN(cchFilename, pMod->pMod->cchFilename + 1); 978 if (cch) 979 { 980 kLdrHlpMemCopy(pszFilename, pMod->pMod->pszFilename, cch - 1); 981 pszFilename[cch - 1] = '\0'; 982 } 983 return cchFilename <= pMod->pMod->cchFilename ? KLDR_ERR_BUFFER_OVERFLOW : 0; 984 } 985 986 987 /** 988 * Gets the address/value of a symbol in the specified module. 989 * 990 * @returns 0 on success, KLDR_ERR_SYMBOL_NOT_FOUND on failure. 991 * @param pMod The module. 992 * @param uSymbolOrdinal The symbol ordinal 0. This is ignored if the name is non-zero. 993 * @param pszSymbolName The symbol name. Can be NULL. 994 * @param puValue Where to store the value. optional. 995 * @param pfKind Where to store the symbol kind. optional. 996 */ 997 int kldrDyldModQuerySymbol(PKLDRDYLDMOD pMod, uint32_t uSymbolOrdinal, const char *pszSymbolName, 998 uintptr_t *puValue, uint32_t *pfKind) 999 { 1000 int rc; 1001 uintmax_t uValue = 0; 1002 uint32_t fKind = 0; 1003 1004 rc = kLdrModQuerySymbol(pMod->pMod, NULL, KLDRMOD_BASEADDRESS_MAP, 1005 pszSymbolName ? pszSymbolName : (const char *)uSymbolOrdinal, &uValue, pfKind); 1006 if (!rc) 1007 { 1008 if (puValue) 1009 { 1010 *puValue = (uintptr_t)uValue; 1011 KLDRDYLDMOD_ASSERT(*puValue == uValue); 1012 } 1013 if (pfKind) 1014 *pfKind = fKind; 1015 } 1016 1017 return rc; 1018 } 1019 -
trunk/kLdr/kLdrHlp.c
r2842 r2846 456 456 457 457 /** 458 * Gets an environment variable and converts it to a size_t. 459 * 460 * @returns 0 and *pcb on success. 461 * Some non-zero OS or kLdr status code on failure. 462 * @param pszVar The name of the variable. 463 * @param pcb Where to put the value. 464 */ 465 int kldrHlpGetEnvUZ(const char *pszVar, size_t *pcb) 466 { 467 size_t cb; 468 unsigned uBase; 469 char szVal[64]; 470 size_t cchVal = sizeof(szVal); 471 const char *psz; 472 int rc; 473 474 *pcb = 0; 475 rc = kldrHlpGetEnv(pszVar, szVal, &cchVal); 476 if (rc) 477 return rc; 478 479 /* figure out the base. */ 480 uBase = 10; 481 psz = szVal; 482 if ( *psz == '0' 483 && (psz[1] == 'x' || psz[1] == 'X')) 484 { 485 uBase = 16; 486 psz += 2; 487 } 488 489 /* convert it up to the first unknown char. */ 490 cb = 0; 491 for(;;) 492 { 493 const char ch = *psz; 494 unsigned uDigit; 495 if (!ch) 496 break; 497 else if (ch >= '0' && ch <= '9') 498 uDigit = ch - '0'; 499 else if (ch >= 'a' && ch <= 'z') 500 uDigit = ch - 'a' + 10; 501 else if (ch >= 'A' && ch <= 'Z') 502 uDigit = ch - 'A' + 10; 503 else 504 break; 505 if (uDigit >= uBase) 506 break; 507 508 /* add the digit */ 509 cb *= uBase; 510 cb += uDigit; 511 512 psz++; 513 } 514 515 /* check for unit */ 516 if (*psz == 'm' || *psz == 'M') 517 cb *= 1024*1024; 518 else if (*psz == 'k' ||*psz == 'K') 519 cb *= 1024; 520 else if (*psz == 'g' || *psz == 'G') 521 cb *= 1024*1024*1024; 522 523 *pcb = cb; 524 return 0; 525 } 526 527 528 /** 458 529 * Terminate the process. 459 530 * -
trunk/kLdr/kLdrHlp.h
r2836 r2846 35 35 /** Get the minimum of two values. */ 36 36 #define KLDR_MIN(a, b) ((a) <= (b) ? (a) : (b)) 37 /** Get the maximum of two values. */ 38 #define KLDR_MAX(a, b) ((a) >= (b) ? (a) : (b)) 37 39 /** Calculate the offset of a structure member. */ 38 40 #define KLDR_OFFSETOF(strct, memb) ( (size_t)( ((strct *)0)->memb ) ) … … 144 146 145 147 int kldrHlpGetEnv(const char *pszVar, char *pszVal, size_t *pcchVal); 148 int kldrHlpGetEnvUZ(const char *pszVar, size_t *pcb); 146 149 void kldrHlpExit(int rc); 147 150 void kldrHlpSleep(unsigned cMillies); -
trunk/kLdr/kLdrInternal.h
r2845 r2846 252 252 * This is used to avoid unnecessary calls to kLdrModUnmap during cleanup. */ 253 253 uint32_t fMapped : 1; 254 /** Set if TLS allocation has been done. (part of the mapping). */ 255 uint32_t fAllocatedTLS : 1; 254 256 /** Reserved for future use. */ 255 uint32_t f2 6Reserved : 26;257 uint32_t f25Reserved : 25; 256 258 /** The load list linkage. */ 257 259 struct … … 340 342 int kldrDyldModReload(PKLDRDYLDMOD pMod); 341 343 int kldrDyldModAttachThread(PKLDRDYLDMOD pMod); 342 intkldrDyldModDetachThread(PKLDRDYLDMOD pMod);343 int kldrDyldModGet StackInfo(PKLDRDYLDMOD pMod, void **ppvStack, size_t *pcbStack);344 void kldrDyldModDetachThread(PKLDRDYLDMOD pMod); 345 int kldrDyldModGetMainStack(PKLDRDYLDMOD pMod, void **ppvStack, size_t *pcbStack); 344 346 int kldrDyldModStartExe(PKLDRDYLDMOD pMod); 345 347 346 348 int kldrDyldModGetName(PKLDRDYLDMOD pMod, char *pszName, size_t cchName); 347 349 int kldrDyldModGetFilename(PKLDRDYLDMOD pMod, char *pszFilename, size_t cchFilename); 348 int kldrDyldModQuerySymbol(PKLDRDYLDMOD pMod, uint32_t uSymbolOrdinal, const char *pszSymbolName, uintptr_t *pValue, uint32_t *pfKind); 349 350 int kldrDyldModQuerySymbol(PKLDRDYLDMOD pMod, uint32_t uSymbolOrdinal, const char *pszSymbolName, uintptr_t *puValue, uint32_t *pfKind); 350 351 351 352 int kldrDyldFailure(int rc, const char *pszFormat, ...); 352 353 int kldrInit(void); 353 354 void kldrTerm(void); 355 356 357 int kldrDyldOSStartExe(uintptr_t uMainEntrypoint, void *pvStack, size_t cbStack); 358 void *kldrDyldOSAllocStack(size_t cb); 354 359 355 360 … … 379 384 extern PKLDRDYLDMOD g_pkLdrDyldBindTail; 380 385 386 /** Indicates that the other MainStack globals have been filled in. */ 387 extern unsigned g_fkLdrDyldDoneMainStack; 388 /** Whether the stack was allocated seperatly or was part of the executable. */ 389 extern unsigned g_fkLdrDyldMainStackAllocated; 390 /** Pointer to the main stack object. */ 391 extern void *g_pvkLdrDyldMainStack; 392 /** The size of the main stack object. */ 393 extern size_t g_cbkLdrDyldMainStack; 394 381 395 /** The global error buffer. */ 382 396 extern char g_szkLdrDyldError[1024];
Note:
See TracChangeset
for help on using the changeset viewer.