Changeset 2846


Ignore:
Timestamp:
Nov 1, 2006, 7:26:35 PM (19 years ago)
Author:
bird
Message:

nearly done with kLdrDyldMod.

Location:
trunk/kLdr
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/kLdr/Makefile.kmk

    r2836 r2846  
    9494        kLdrDyldFind.c \
    9595        kLdrDyldMod.c \
     96        kLdrDyldOS.c \
    9697        kLdrHlp.c \
    9798        kLdrHlpHeap.c \
  • trunk/kLdr/kLdr.h

    r2845 r2846  
    269269{
    270270    /** The base address of the stack (sub) segment, link address.
    271      * Set this to ~(uintptr_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. */
    272272    uintmax_t           uLinkAddress;
    273273    /** The base address of the stack (sub) segment, actual load address.
    274      * Set this to ~(uintptr_t)0 if the module doesn't include any stack (sub)segment or if
     274     * Set this to ~(uintmax_t)0 if the module doesn't include any stack (sub)segment or if
    275275     * the module isn't mapped (loaded) yet. */
    276276    uintmax_t           uLoadAddress;
     
    560560int     kLdrModOpenNative(const char *pszFilename, PPKLDRMOD ppMod);
    561561int     kLdrModClose(PKLDRMOD pMod);
    562 int     kLdrModGetSymbol(PKLDRMOD pMod, const void *pvBits, uintmax_t BaseAddress, const char *pszSymbol, uintmax_t *pValue, uint32_t *pfKind);
     562int     kLdrModQuerySymbol(PKLDRMOD pMod, const void *pvBits, uintmax_t BaseAddress, const char *pszSymbol, uintmax_t *pValue, uint32_t *pfKind);
    563563int     kLdrModEnumSymbols(PKLDRMOD pMod, unsigned fFlags, const void *pvBits, uintmax_t BaseAddress, PFNKLDRMODENUMSYMS pfnCallback, void *pvUser);
    564564int     kLdrModEnumImportModules(PKLDRMOD pMod, unsigned fFlags, const void *pvBits, FNKLDRMODENUMIMPMODS pfnCallback, void *pvUser);
     
    571571int     kLdrModCanExecuteOn(PKLDRMOD pMod, KLDRARCH enmArch, KLDRCPU enmCpu);
    572572int     kLdrModGetStackInfo(PKLDRMOD pMod, PKLDRSTACKINFO pStackInfo);
     573int     kLdrModQueryMainEntrypoint(PKLDRMOD pMod, void *pvBits, uintmax_t uBaseAddress, uintmax_t *puValue);
     574int     kLdrModAllocTLS(PKLDRMOD pMod);
     575int     kLdrModFreeTLS(PKLDRMOD pMod);
     576int     kLdrModReload(PKLDRMOD pMod);
     577int     kLdrModCallInit(PKLDRMOD pMod);
     578int     kLdrModCallTerm(PKLDRMOD pMod);
     579int     kLdrModCallThread(PKLDRMOD pMod, unsigned fAttachingOrDetaching);
    573580
    574581/** @} */
     
    771778/** Prerequisite recursed too deeply. */
    772779#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)
    774784
    775785/** Encountered a bad fixup. */
  • trunk/kLdr/kLdrDyld.c

    r2845 r2846  
    107107
    108108
     109/** @name The main stack.
     110 * @{ */
     111/** Indicates that the other MainStack globals have been filled in. */
     112unsigned        g_fkLdrDyldDoneMainStack = 0;
     113/** Whether the stack was allocated seperatly or was part of the executable. */
     114unsigned        g_fkLdrDyldMainStackAllocated = 0;
     115/** Pointer to the main stack object. */
     116void           *g_pvkLdrDyldMainStack = NULL;
     117/** The size of the main stack object. */
     118size_t          g_cbkLdrDyldMainStack = 0;
     119/** @} */
     120
     121
    109122/** The load stack.
    110123 * This contains frames with modules affected by active loads.
     
    186199    kLdrDyldFlags = 0;
    187200    g_szkLdrDyldError[0] = '\0';
     201
     202    g_fkLdrDyldDoneMainStack = 0;
     203    g_fkLdrDyldMainStackAllocated = 0;
     204    g_pvkLdrDyldMainStack = NULL;
     205    g_cbkLdrDyldMainStack = 0;
     206
    188207    return 0;
    189208}
     
    257276
    258277    /*
    259      * Query the stack information and go to OS specific code to
     278     * Query the stack and go to OS specific code to
    260279     * setup and switch stack. The OS specific code will call us
    261280     * back at kldrDyldDoLoadExe.
    262281     */
    263     rc = kldrDyldModGetStackInfo(pExe, &pvStack, &cbStack);
     282    rc = kldrDyldModGetMainStack(pExe, &pvStack, &cbStack);
    264283    if (rc)
    265284        kldrDyldFailure(rc, "Failed to map the executable '%s', rc=%d", pExe->pMod->pszFilename, rc);
  • trunk/kLdr/kLdrDyldMod.c

    r2845 r2846  
    100100        pMod->fAlreadySeen = 0;
    101101        pMod->fMapped = 0;
    102         pMod->f26Reserved = 0;
     102        pMod->fAllocatedTLS = 0;
     103        pMod->f25Reserved = 0;
    103104        pMod->InitTerm.pNext = NULL;
    104105        pMod->InitTerm.pPrev = NULL;
     
    249250    pMod->InitTerm.pNext = NULL;
    250251    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   pMod
    269  */
    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_DESTROYED
    283         &&  !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 > 0
    337         ||  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 0
    351  * @param   pMod    The module.
    352  */
    353 int kldrDyldModDynamicLoad(PKLDRDYLDMOD pMod)
    354 {
    355     KLDRDYLDMOD_ASSERT(     pMod->enmState == KLDRSTATE_GOOD
    356                        ||   pMod->enmState == KLDRSTATE_PENDING_INITIALIZATION
    357                        ||   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 module
    366  * 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 > 0
    385         ||  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 state
    429      */
    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 unloading
    464  * of all affected modules.
    465  *
    466  * This function will cause a state transition to PENDING_DESTROY, PENDING_GC
    467  * or PENDING_TERMINATION depending on the module state. There is one exception
    468  * 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_STRICT
    478     {
    479     PKLDRDYLDMOD pMod2;
    480     for (pMod2 = kLdrDyldHead; pMod2; pMod2 = pMod2->Load.pNext)
    481         KLDRDYLDMOD_ASSERT(pMod2->enmState != KLDRSTATE_GOOD || pMod2->cRefs);
    482     }
    483 #endif
    484     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 more
    493      * 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->cRefs
    501                 ||  pMod->enmState >= KLDRSTATE_PENDING_TERMINATION
    502                 ||  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 request
    527  * doesn't specify a path. A specific module will not match
    528  * 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;
    547252}
    548253
     
    615320
    616321/**
     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 */
     330void 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 */
     343void 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 */
     354void kldrDyldModAddRef(PKLDRDYLDMOD pMod)
     355{
     356    pMod->cRefs++;
     357}
     358
     359
     360/**
     361 * Dereference a module.
     362 *
     363 * @param   pMod
     364 */
     365void 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 */
     389void 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 */
     421void 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 */
     448int 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 */
     470int 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 */
     497static 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 */
     567void 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
     605int kldrDyldModLoadPrerequisites(PKLDRDYLDMOD pMod, const char *pszPrefix, const char *pszSuffix,
     606                                 KLDRDYLDSEARCH enmSearch, unsigned fFlags)
     607{
     608
     609    return -1;
     610}
     611
     612
     613int kldrDyldModCheckPrerequisites(PKLDRDYLDMOD pMod)
     614{
     615    return -1;
     616}
     617
     618
     619/**
    617620 * Maps an open module.
    618621 *
     
    637640    if (!rc)
    638641    {
    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);
    641651    }
    642652    return rc;
     
    669679
    670680    /* do the job. */
    671     rc = kLdrModUnmap(pMod->pMod);
     681    rc = kLdrModFreeTLS(pMod->pMod);
    672682    if (!rc)
    673683    {
    674         pMod->fMapped = 0;
    675         if (pMod->enmState < KLDRSTATE_PENDING_DESTROY)
     684        rc = kLdrModUnmap(pMod->pMod);
     685        if (!rc)
    676686        {
    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            }
    679693        }
     694        else
     695            kLdrModAllocTLS(pMod->pMod);
    680696    }
    681697    return rc;
    682698}
     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 */
     711int 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
    683752
    684753
     
    707776
    708777
    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 */
     789int 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 */
     812void 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 */
     827int 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 */
     841void 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 */
     857int 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 */
     929int 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 */
     955int 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 */
     975int 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 */
     997int 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  
    456456
    457457/**
     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 */
     465int     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/**
    458529 * Terminate the process.
    459530 *
  • trunk/kLdr/kLdrHlp.h

    r2836 r2846  
    3535/** Get the minimum of two values. */
    3636#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))
    3739/** Calculate the offset of a structure member. */
    3840#define KLDR_OFFSETOF(strct, memb)  ( (size_t)( ((strct *)0)->memb ) )
     
    144146
    145147int     kldrHlpGetEnv(const char *pszVar, char *pszVal, size_t *pcchVal);
     148int     kldrHlpGetEnvUZ(const char *pszVar, size_t *pcb);
    146149void    kldrHlpExit(int rc);
    147150void    kldrHlpSleep(unsigned cMillies);
  • trunk/kLdr/kLdrInternal.h

    r2845 r2846  
    252252     * This is used to avoid unnecessary calls to kLdrModUnmap during cleanup. */
    253253    uint32_t            fMapped : 1;
     254    /** Set if TLS allocation has been done. (part of the mapping). */
     255    uint32_t            fAllocatedTLS : 1;
    254256    /** Reserved for future use. */
    255     uint32_t            f26Reserved : 26;
     257    uint32_t            f25Reserved : 25;
    256258    /** The load list linkage. */
    257259    struct
     
    340342int kldrDyldModReload(PKLDRDYLDMOD pMod);
    341343int kldrDyldModAttachThread(PKLDRDYLDMOD pMod);
    342 int kldrDyldModDetachThread(PKLDRDYLDMOD pMod);
    343 int kldrDyldModGetStackInfo(PKLDRDYLDMOD pMod, void **ppvStack, size_t *pcbStack);
     344void kldrDyldModDetachThread(PKLDRDYLDMOD pMod);
     345int kldrDyldModGetMainStack(PKLDRDYLDMOD pMod, void **ppvStack, size_t *pcbStack);
    344346int kldrDyldModStartExe(PKLDRDYLDMOD pMod);
    345347
    346348int kldrDyldModGetName(PKLDRDYLDMOD pMod, char *pszName, size_t cchName);
    347349int 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 
     350int kldrDyldModQuerySymbol(PKLDRDYLDMOD pMod, uint32_t uSymbolOrdinal, const char *pszSymbolName, uintptr_t *puValue, uint32_t *pfKind);
    350351
    351352int kldrDyldFailure(int rc, const char *pszFormat, ...);
    352353int kldrInit(void);
    353354void kldrTerm(void);
     355
     356
     357int kldrDyldOSStartExe(uintptr_t uMainEntrypoint, void *pvStack, size_t cbStack);
     358void *kldrDyldOSAllocStack(size_t cb);
    354359
    355360
     
    379384extern PKLDRDYLDMOD     g_pkLdrDyldBindTail;
    380385
     386/** Indicates that the other MainStack globals have been filled in. */
     387extern unsigned         g_fkLdrDyldDoneMainStack;
     388/** Whether the stack was allocated seperatly or was part of the executable. */
     389extern unsigned         g_fkLdrDyldMainStackAllocated;
     390/** Pointer to the main stack object. */
     391extern void            *g_pvkLdrDyldMainStack;
     392/** The size of the main stack object. */
     393extern size_t           g_cbkLdrDyldMainStack;
     394
    381395/** The global error buffer. */
    382396extern char             g_szkLdrDyldError[1024];
Note: See TracChangeset for help on using the changeset viewer.