Changeset 2845


Ignore:
Timestamp:
Nov 1, 2006, 2:39:03 AM (19 years ago)
Author:
bird
Message:

kldrDyldMod* in progress.

Location:
trunk/kLdr
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/kLdr/kLdr.h

    r2843 r2845  
    557557
    558558int     kLdrModOpen(const char *pszFilename, PPKLDRMOD ppMod);
     559int     kLdrModOpenFromRdr(PKLDRRDR pRdr, PPKLDRMOD ppMod);
     560int     kLdrModOpenNative(const char *pszFilename, PPKLDRMOD ppMod);
    559561int     kLdrModClose(PKLDRMOD pMod);
    560562int     kLdrModGetSymbol(PKLDRMOD pMod, const void *pvBits, uintmax_t BaseAddress, const char *pszSymbol, uintmax_t *pValue, uint32_t *pfKind);
  • trunk/kLdr/kLdrDyld.c

    r2843 r2845  
    168168static int          kldrDyldStackAddModule(PKLDRDYLDMOD pMod);
    169169static int          kldrDyldStackFrameCompleted(void);
     170static void         kldrDyldStackCleanupOne(PKLDRDYLDMOD pMod, int rc);
    170171static void         kldrDyldStackDropFrame(uint32_t iLoad1st, uint32_t iLoadEnd, int rc);
    171172/** @} */
     
    627628        rc = kldrDyldDoLoad2(*ppMod, pszPrefix, pszSuffix, enmSearch, fFlags);
    628629    else
    629     {
    630         /** @todo this is probably not quite right. */
    631         /* If the reference count is 0 do a quick ref/deref to trigger destruction. */
    632         kldrDyldModAddRef(*ppMod);
    633         kldrDyldModDeref(*ppMod);
    634     }
     630        kldrDyldStackCleanupOne(*ppMod, rc);
    635631
    636632    /*
     
    656652    int rc = kldrDyldDoLoadPrerequisites(pLoadedMod, pszPrefix, pszSuffix, enmSearch, fFlags);
    657653    uint32_t iLoadEnd = kldrDyldStackFrameCompleted();
     654    if (rc)
     655        kldrDyldStackCleanupOne(pLoadedMod, rc); /* in case it didn't get pushed onto the stack. */
    658656
    659657    /*
     
    954952    if (!rc)
    955953    {
    956         rc = kldrDyldModAddDep(pMod, pDep);
    957         if (!rc)
    958             *ppMod = pMod;
     954        kldrDyldModAddDep(pMod, pDep);
     955        *ppMod = pMod;
    959956    }
    960957    return rc;
     
    10231020static int kldrDyldStackAddModule(PKLDRDYLDMOD pMod)
    10241021{
    1025     int rc;
    1026 
    10271022    /*
    10281023     * Grow the stack if necessary.
     
    10431038     * Add a reference and push the module onto the stack.
    10441039     */
    1045     rc = kldrDyldModAddRef(pMod);
    1046     if (!rc)
    1047         g_papStackMods[g_cStackMods++] = pMod;
    1048     return rc;
     1040    kldrDyldModAddRef(pMod);
     1041    g_papStackMods[g_cStackMods++] = pMod;
     1042    return 0;
    10491043}
    10501044
     
    10581052{
    10591053    return g_cStackMods;
     1054}
     1055
     1056
     1057/**
     1058 * Worker routine for kldrDyldStackDropFrame() and kldrDyldDoLoad().
     1059 *
     1060 * @param   pMod            The module to perform cleanups on.
     1061 * @param   rc              Used for state verification.
     1062 */
     1063static void kldrDyldStackCleanupOne(PKLDRDYLDMOD pMod, int rc)
     1064{
     1065    switch (pMod->enmState)
     1066    {
     1067        /*
     1068         * Just push it along to the PENDING_DESTROY state.
     1069         */
     1070        case KLDRSTATE_MAPPED:
     1071            KLDRDYLD_ASSERT(rc);
     1072            kldrDyldModUnmap(pMod);
     1073            KLDRDYLD_ASSERT(pMod->enmState == KLDRSTATE_PENDING_DESTROY);
     1074            break;
     1075
     1076        /*
     1077         * Move back to PENDING_GC.
     1078         */
     1079        case KLDRSTATE_RELOADED:
     1080            KLDRDYLD_ASSERT(rc);
     1081            pMod->enmState = KLDRSTATE_PENDING_GC;
     1082            break;
     1083
     1084        /*
     1085         * Unload prerequisites and unmap the modules.
     1086         */
     1087        case KLDRSTATE_LOADED_PREREQUISITES:
     1088        case KLDRSTATE_FIXED_UP:
     1089            KLDRDYLD_ASSERT(rc);
     1090            kldrDyldModUnloadPrerequisites(pMod);
     1091            KLDRDYLD_ASSERT(pMod->enmState == KLDRSTATE_PENDING_DESTROY);
     1092            kldrDyldModUnmap(pMod);
     1093            KLDRDYLD_ASSERT(pMod->enmState == KLDRSTATE_PENDING_DESTROY);
     1094            break;
     1095
     1096        /*
     1097         * Unload prerequisites and push it back to PENDING_GC.
     1098         */
     1099        case KLDRSTATE_RELOADED_LOADED_PREREQUISITES:
     1100        case KLDRSTATE_RELOADED_FIXED_UP:
     1101            kldrDyldModUnloadPrerequisites(pMod);
     1102            KLDRDYLD_ASSERT(pMod->enmState == KLDRSTATE_PENDING_GC);
     1103            break;
     1104
     1105        /*
     1106         * Nothing to do, just asserting sanity.
     1107         */
     1108        case KLDRSTATE_INITIALIZING:
     1109            /* Implies there is another load going on. */
     1110            KLDRDYLD_ASSERT(g_cActiveLoadCalls > 1);
     1111            break;
     1112        case KLDRSTATE_TERMINATING:
     1113            /* GC in progress. */
     1114            KLDRDYLD_ASSERT(g_fActiveGC);
     1115            break;
     1116        case KLDRSTATE_PENDING_TERMINATION:
     1117        case KLDRSTATE_PENDING_INITIALIZATION:
     1118        case KLDRSTATE_PENDING_GC:
     1119        case KLDRSTATE_PENDING_DESTROY:
     1120            KLDRDYLD_ASSERT(rc);
     1121            break;
     1122        case KLDRSTATE_GOOD:
     1123            break;
     1124
     1125        /*
     1126         * Bad states.
     1127         */
     1128        default:
     1129            KLDRDYLD_ASSERT(!"drop frame bad state (a)");
     1130            break;
     1131    }
    10601132}
    10611133
     
    10801152    {
    10811153        PKLDRDYLDMOD pMod = g_papStackMods[--iLoad1st];
    1082         switch (pMod->enmState)
    1083         {
    1084             /*
    1085              * Just push it along to the PENDING_DESTROY state.
    1086              */
    1087             case KLDRSTATE_MAPPED:
    1088                 KLDRDYLD_ASSERT(rc);
    1089                 kldrDyldModUnmap(pMod);
    1090                 KLDRDYLD_ASSERT(pMod->enmState == KLDRSTATE_PENDING_DESTROY);
    1091                 break;
    1092 
    1093             /*
    1094              * Move back to PENDING_GC.
    1095              */
    1096             case KLDRSTATE_RELOADED:
    1097                 KLDRDYLD_ASSERT(rc);
    1098                 pMod->enmState = KLDRSTATE_PENDING_GC;
    1099                 break;
    1100 
    1101             /*
    1102              * Unload prerequisites and unmap the modules.
    1103              */
    1104             case KLDRSTATE_LOADED_PREREQUISITES:
    1105             case KLDRSTATE_FIXED_UP:
    1106                 KLDRDYLD_ASSERT(rc);
    1107                 kldrDyldModUnloadPrerequisites(pMod);
    1108                 KLDRDYLD_ASSERT(pMod->enmState == KLDRSTATE_PENDING_DESTROY);
    1109                 kldrDyldModUnmap(pMod);
    1110                 KLDRDYLD_ASSERT(pMod->enmState == KLDRSTATE_PENDING_DESTROY);
    1111                 break;
    1112 
    1113             /*
    1114              * Unload prerequisites and push it back to PENDING_GC.
    1115              */
    1116             case KLDRSTATE_RELOADED_LOADED_PREREQUISITES:
    1117             case KLDRSTATE_RELOADED_FIXED_UP:
    1118                 kldrDyldModUnloadPrerequisites(pMod);
    1119                 KLDRDYLD_ASSERT(pMod->enmState == KLDRSTATE_PENDING_GC);
    1120                 break;
    1121 
    1122             /*
    1123              * Nothing to do, just asserting sanity.
    1124              */
    1125             case KLDRSTATE_INITIALIZING:
    1126                 /* Implies there is another load going on. */
    1127                 KLDRDYLD_ASSERT(g_cActiveLoadCalls > 1);
    1128                 break;
    1129             case KLDRSTATE_TERMINATING:
    1130                 /* GC in progress. */
    1131                 KLDRDYLD_ASSERT(g_fActiveGC);
    1132                 break;
    1133             case KLDRSTATE_PENDING_TERMINATION:
    1134             case KLDRSTATE_PENDING_INITIALIZATION:
    1135             case KLDRSTATE_PENDING_GC:
    1136             case KLDRSTATE_PENDING_DESTROY:
    1137                 KLDRDYLD_ASSERT(rc);
    1138                 break;
    1139             case KLDRSTATE_GOOD:
    1140                 break;
    1141 
    1142             /*
    1143              * Bad states.
    1144              */
    1145             default:
    1146                 KLDRDYLD_ASSERT(!"drop frame bad state (a)");
    1147                 break;
    1148         }
     1154        kldrDyldStackCleanupOne(pMod, rc);
    11491155    }
    11501156
     
    12771283    {
    12781284        PKLDRDYLDMOD pNext = pMod->Load.pNext;
     1285        kldrDyldModAddRef(pMod);
     1286
    12791287        switch (pMod->enmState)
    12801288        {
     
    12841292                pMod->enmState = KLDRSTATE_GC;
    12851293                kldrDyldModUnmap(pMod);
     1294                KLDRDYLD_ASSERT(pMod->enmState == KLDRSTATE_PENDING_DESTROY);
    12861295                kldrDyldModDestroy(pMod);
     1296                KLDRDYLD_ASSERT(pMod->enmState == KLDRSTATE_DESTROYED);
    12871297                break;
    12881298
     
    12931303                break;
    12941304        }
     1305
     1306        kldrDyldModDeref(pMod);
    12951307
    12961308        /* next */
  • trunk/kLdr/kLdrDyldMod.c

    r2842 r2845  
    3838*   Defined Constants And Macros                                               *
    3939*******************************************************************************/
     40/** @def KLDRDYLDMOD_STRICT
     41 * Define KLDRDYLDMOD_STRICT to enabled strict checks in kLdrDyld. */
     42#define KLDRDYLDMOD_STRICT 1
     43
    4044/** @def KLDRDYLDMOD_ASSERT
    4145 * Assert that an expression is true when KLDRDYLD_STRICT is defined.
    4246 */
    43 #ifdef KLDRDYLD_STRICT
     47#ifdef KLDRDYLDMOD_STRICT
    4448# define KLDRDYLDMOD_ASSERT(expr)  kldrHlpAssert(expr)
    4549#else
     
    5054
    5155/**
     56 * Creates a module from the specified file provider instance.
     57 *
     58 * @returns 0 on success and *ppMod pointing to the new instance.
     59 *          On failure a non-zero kLdr status code is returned.
     60 * @param   pRdr    The file provider instance.
     61 * @param   ppMod   Where to put the pointer to the new module on success.
     62 */
     63int kldrDyldModCreate(PKLDRRDR pRdr, PPKLDRDYLDMOD ppMod)
     64{
     65    PKLDRDYLDMOD pMod;
     66    PKLDRMOD pRawMod;
     67    int rc;
     68
     69    *ppMod = NULL;
     70
     71    /*
     72     * Try open an module interpreter.
     73     */
     74    rc = kLdrModOpenFromRdr(pRdr, &pRawMod);
     75    if (rc)
     76        return kldrDyldFailure(rc, "%s: %rc", kLdrRdrName(pRdr), rc);
     77
     78    /*
     79     * Allocate a new dyld module.
     80     */
     81    pMod = (PKLDRDYLDMOD)kldrHlpAlloc(sizeof(*pMod));
     82    if (pMod)
     83    {
     84        pMod->enmState = KLDRSTATE_OPEN;
     85        pMod->pMod = pRawMod;
     86        pMod->hMod = pMod;
     87        pMod->cDepRefs = pMod->cDynRefs = pMod->cRefs = 0;
     88        pMod->fExecutable = 0;
     89        switch (pRawMod->enmType)
     90        {
     91            case KLDRTYPE_EXECUTABLE_FIXED:
     92            case KLDRTYPE_EXECUTABLE_RELOCATABLE:
     93            case KLDRTYPE_EXECUTABLE_PIC:
     94                pMod->fExecutable = 1;
     95                break;
     96        }
     97        pMod->fGlobalOrSpecific = 0;
     98        pMod->fBindable = 0;
     99        pMod->fInitList = 0;
     100        pMod->fAlreadySeen = 0;
     101        pMod->fMapped = 0;
     102        pMod->f26Reserved = 0;
     103        pMod->InitTerm.pNext = NULL;
     104        pMod->InitTerm.pPrev = NULL;
     105        pMod->Bind.pNext = NULL;
     106        pMod->Bind.pPrev = NULL;
     107        pMod->cPrereqs = 0;
     108        pMod->papPrereqs = NULL;
     109        pMod->u32MagicHead = KLDRDYMOD_MAGIC;
     110        pMod->u32MagicTail = KLDRDYMOD_MAGIC;
     111
     112        /* it. */
     113        pMod->Load.pNext = NULL;
     114        pMod->Load.pPrev = kLdrDyldTail;
     115        if (kLdrDyldTail)
     116            kLdrDyldTail->Load.pNext = pMod;
     117        else
     118            kLdrDyldHead = pMod;
     119        kLdrDyldTail = pMod;
     120
     121        /* we're good. */
     122        *ppMod = pMod;
     123        rc = 0;
     124    }
     125    else
     126    {
     127        kLdrModClose(pRawMod);
     128        rc = KLDR_ERR_NO_MEMORY;
     129    }
     130    return rc;
     131}
     132
     133
     134/**
     135 * Creates a module for a native module.
     136 *
     137 * @returns 0 on success and *ppMod pointing to the new instance.
     138 *          On failure a non-zero kLdr status code is returned.
     139 * @param   hNativeModule   The native handle.
     140 * @param   ppMod           Where to put the pointer to the new module on success.
     141 * @remark  This function ain't finalized yet.
     142 */
     143int kldrDyldModCreateNative(uintptr_t hNativeModule)
     144{
     145#if 0
     146    /*
     147     * Check if this module is already loaded by the native OS loader.
     148     */
     149    rc = kld
     150    {
     151#ifdef __OS2__
     152    HMODULE hmod = NULLHANDLE;
     153    APIRET rc = DosQueryModuleHandle(kLdrRdrName(pRdr), &hmod);
     154    if (!rc)
     155
     156#elif defined(__WIN__)
     157    HMODULE hmod = NULL;
     158    if (GetModuleHandle(kLdrRdrName(pRdr))
     159
     160#else
     161# error "Port me"
     162#endif
     163    }
     164#endif
     165    return -1;
     166}
     167
     168
     169/**
     170 * Destroys a module pending destruction.
     171 *
     172 * @param   pMod        The module in question.
     173 */
     174void kldrDyldModDestroy(PKLDRDYLDMOD pMod)
     175{
     176    /*
     177     * Validate the state.
     178     */
     179    switch (pMod->enmState)
     180    {
     181        case KLDRSTATE_PENDING_DESTROY:
     182        case KLDRSTATE_GC:
     183            break;
     184        default:
     185            KLDRDYLDMOD_ASSERT(!"Invalid state");
     186            break;
     187    }
     188    KLDRDYLDMOD_ASSERT(!pMod->fInitList);
     189    KLDRDYLDMOD_ASSERT(!pMod->cDynRefs);
     190    KLDRDYLDMOD_ASSERT(!pMod->cDepRefs);
     191
     192
     193    /*
     194     * Ensure that the module is unmapped.
     195     */
     196    if (pMod->fMapped)
     197        kldrDyldModUnmap(pMod);
     198}
     199
     200
     201/**
     202 * Unlinks the module from any list it might be in.
     203 * It is assumed that the module is at least linked into the load list.
     204 *
     205 * @param   pMod    The moduel.
     206 */
     207static void kldrDyldModUnlink(PKLDRDYLDMOD pMod)
     208{
     209    /* load list */
     210    if (pMod->Load.pNext)
     211        pMod->Load.pNext->Load.pPrev = pMod->Load.pPrev;
     212    else
     213        kLdrDyldTail = pMod->Load.pPrev;
     214    if (pMod->Load.pPrev)
     215        pMod->Load.pPrev->Load.pNext = pMod->Load.pNext;
     216    else
     217        kLdrDyldHead = pMod->Load.pNext;
     218
     219    /* bind list */
     220    if (pMod->fBindable)
     221        kldrDyldModClearBindable(pMod);
     222
     223    /* init term */
     224    if (pMod->fInitList)
     225    {
     226        KLDRDYLDMOD_ASSERT(pMod->enmState < KLDRSTATE_INITIALIZATION_FAILED);
     227        pMod->fInitList = 0;
     228        if (pMod->InitTerm.pNext)
     229            pMod->InitTerm.pNext->InitTerm.pPrev = pMod->InitTerm.pPrev;
     230        else
     231            g_pkLdrDyldInitTail = pMod->InitTerm.pPrev;
     232        if (pMod->InitTerm.pPrev)
     233            pMod->InitTerm.pPrev->InitTerm.pNext = pMod->InitTerm.pNext;
     234        else
     235            g_pkLdrDyldInitHead = pMod->InitTerm.pNext;
     236    }
     237    else if (pMod->enmState > KLDRSTATE_INITIALIZATION_FAILED)
     238    {
     239        KLDRDYLDMOD_ASSERT(pMod->enmState >= KLDRSTATE_GOOD);
     240        if (pMod->InitTerm.pNext)
     241            pMod->InitTerm.pNext->InitTerm.pPrev = pMod->InitTerm.pPrev;
     242        else
     243            g_pkLdrDyldTermTail = pMod->InitTerm.pPrev;
     244        if (pMod->InitTerm.pPrev)
     245            pMod->InitTerm.pPrev->InitTerm.pNext = pMod->InitTerm.pNext;
     246        else
     247            g_pkLdrDyldTermHead = pMod->InitTerm.pNext;
     248    }
     249    pMod->InitTerm.pNext = NULL;
     250    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 */
     259void kldrDyldModAddRef(PKLDRDYLDMOD pMod)
     260{
     261    pMod->cRefs++;
     262}
     263
     264
     265/**
     266 * Dereference a module.
     267 *
     268 * @param   pMod
     269 */
     270void 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 */
     294void 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 */
     326void 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 */
     353int 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/**
    52365 * Decrement the dynamic load count of the module and unload the module
    53366 * if the total reference count reaches zero.
     
    69382    pMod->cRefs--;
    70383    pMod->cDynRefs--;
    71     if (pMod->cRefs > 0)
     384    if (    pMod->cDynRefs > 0
     385        ||  pMod->cDepRefs > 0)
    72386        return 0;
    73387
     
    150464 * of all affected modules.
    151465 *
    152  * This function will cause a state transition ot PENDING_DESTROY, PENDING_GC
     466 * This function will cause a state transition to PENDING_DESTROY, PENDING_GC
    153467 * or PENDING_TERMINATION depending on the module state. There is one exception
    154468 * to this, and that's INITIALIZATION_FAILED, where the state will not be changed.
     
    194508
    195509
    196 
    197 
    198 
    199 void kldrDyldModDeref(PKLDRDYLDMOD pMod)
    200 {
    201     /* validate input */
    202     KLDRDYLDMOD_ASSERT(pMod->enmState > KLDRSTATE_INVALID && pMod->enmState < KLDRSTATE_END);
     510int kldrDyldModLoadPrerequisites(PKLDRDYLDMOD pMod, const char *pszPrefix, const char *pszSuffix,
     511                                 KLDRDYLDSEARCH enmSearch, unsigned fFlags)
     512{
     513    return -1;
     514}
     515
     516
     517int 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 */
     532void 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 */
     544void kldrDyldModMarkSpecific(PKLDRDYLDMOD pMod)
     545{
     546    pMod->fGlobalOrSpecific = 0;
     547}
     548
     549
     550/**
     551 * Marks a module as bindable, i.e. it'll be considered when
     552 * resolving names the unix way.
     553 *
     554 * @param   pMod    The module.
     555 * @param   fDeep   When set the module will be inserted at the head of the
     556 *                  module list used to resolve symbols. This means that the
     557 *                  symbols in this module will be prefered of all the other
     558 *                  modules.
     559 */
     560void kldrDyldModSetBindable(PKLDRDYLDMOD pMod, unsigned fDeep)
     561{
     562    KLDRDYLDMOD_ASSERT(pMod->enmState >= KLDRSTATE_OPEN && pMod->enmState < KLDRSTATE_PENDING_GC);
     563    if (!pMod->fBindable)
     564    {
     565        pMod->fBindable = 1;
     566        if (!fDeep)
     567        {
     568            pMod->Bind.pNext = NULL;
     569            pMod->Bind.pPrev = g_pkLdrDyldBindTail;
     570            if (g_pkLdrDyldBindTail)
     571                g_pkLdrDyldBindTail->Bind.pNext = pMod;
     572            else
     573                g_pkLdrDyldBindHead = pMod;
     574            g_pkLdrDyldBindTail = pMod;
     575        }
     576        else
     577        {
     578            pMod->Bind.pPrev = NULL;
     579            pMod->Bind.pNext = g_pkLdrDyldBindHead;
     580            if (g_pkLdrDyldBindHead)
     581                g_pkLdrDyldBindHead->Bind.pPrev = pMod;
     582            else
     583                g_pkLdrDyldBindTail = pMod;
     584            g_pkLdrDyldBindHead = pMod;
     585        }
     586    }
     587}
     588
     589
     590/**
     591 * Marks a module as not bindable, i.e. it will not be considered when
     592 * resolving names the unix way.
     593 *
     594 * @param   pMod    The module.
     595 */
     596void kldrDyldModClearBindable(PKLDRDYLDMOD pMod)
     597{
     598    KLDRDYLDMOD_ASSERT(pMod->enmState >= KLDRSTATE_OPEN && pMod->enmState < KLDRSTATE_PENDING_DESTROY);
     599    if (pMod->fBindable)
     600    {
     601        pMod->fBindable = 0;
     602        if (pMod->Bind.pPrev)
     603            pMod->Bind.pPrev->Bind.pNext = pMod->Bind.pNext;
     604        else
     605            g_pkLdrDyldBindHead = pMod->Bind.pNext;
     606        if (pMod->Bind.pNext)
     607            pMod->Bind.pNext->Bind.pPrev = pMod->Bind.pPrev;
     608        else
     609            g_pkLdrDyldBindTail = pMod->Bind.pPrev;
     610        pMod->Bind.pNext = NULL;
     611        pMod->Bind.pPrev = NULL;
     612    }
     613}
     614
     615
     616/**
     617 * Maps an open module.
     618 *
     619 * On success the module will be in the MAPPED state.
     620 *
     621 * @returns 0 on success, non-zero native OS or kLdr status code on failure.
     622 * @param   pMod    The module which needs to be unmapped and set pending for destruction.
     623 */
     624int kldrDyldModMap(PKLDRDYLDMOD pMod)
     625{
     626    int rc;
     627
     628    /* sanity */
    203629    KLDRDYLDMOD_ASSERT(pMod->cRefs > 0);
    204     KLDRDYLDMOD_ASSERT(pMod->cRefs >= pMod->cDepRefs + pMod->cDynRefs);
    205 
    206     /* decrement. */
    207     if (pMod->cRefs > 0)
    208         pMod->cRefs--;
    209 
    210     /*
    211      * Drop prerequisites for stats that implies that no recursion can have taken place yet.
    212      * This ASSUMES that we're only dereferencing modules when an operation completes.
    213      * (This is *required* for the reloaded state.)
    214      */
     630    KLDRDYLDMOD_ASSERT(pMod->enmState == KLDRSTATE_OPEN);
     631    KLDRDYLDMOD_ASSERT(!pMod->fMapped);
     632    if (pMod->fMapped)
     633        return 0;
     634
     635    /* do the job. */
     636    rc = kLdrModMap(pMod->pMod);
     637    if (!rc)
     638    {
     639        pMod->fMapped = 1;
     640        pMod->enmState = KLDRSTATE_MAPPED;
     641    }
     642    return rc;
     643}
     644
     645
     646/**
     647 * Unmaps the module, unlinks it from everywhere marks it PENDING_DESTROY.
     648 *
     649 * @returns 0 on success, non-zero native OS or kLdr status code on failure.
     650 * @param   pMod    The module which needs to be unmapped and set pending for destruction.
     651 */
     652int kldrDyldModUnmap(PKLDRDYLDMOD pMod)
     653{
     654    int rc;
     655
     656    /* sanity */
     657    KLDRDYLDMOD_ASSERT(pMod->cRefs > 0);
     658    KLDRDYLDMOD_ASSERT(pMod->fMapped);
    215659    switch (pMod->enmState)
    216660    {
    217661        case KLDRSTATE_MAPPED:
    218         case KLDRSTATE_LOADED_PREREQUISITES:
    219         case KLDRSTATE_FIXED_UP:
    220         case KLDRSTATE_RELOADED:
    221             kldrDyldModUnloadPrerequisites(pMod);
    222             pMod->enmState = KLDRSTATE_PENDING_GC;
    223             break;
    224 
    225         case KLDRSTATE_PENDING_INITIALIZATION:
    226         case KLDRSTATE_INITIALIZING:
    227         case KLDRSTATE_GOOD:
    228         case KLDRSTATE_PENDING_TERMINATION:
    229         case KLDRSTATE_TERMINATING:
    230         case KLDRSTATE_PENDING_GC:
    231662        case KLDRSTATE_GC:
    232663        case KLDRSTATE_PENDING_DESTROY:
    233664            break;
    234 
    235665        default:
    236             KLDRDYLDMOD_ASSERT(!"Invalid deref state");
    237             break;
    238     }
    239 
    240     /*
    241      * Also drop prerequisites if noone is referencing the module.
    242      */
    243     if (!pMod->cDepRefs && !pMod->cDynRefs)
    244     {
    245         switch (pMod->enmState)
     666            KLDRDYLDMOD_ASSERT(!"invalid state");
     667            return -1;
     668    }
     669
     670    /* do the job. */
     671    rc = kLdrModUnmap(pMod->pMod);
     672    if (!rc)
     673    {
     674        pMod->fMapped = 0;
     675        if (pMod->enmState < KLDRSTATE_PENDING_DESTROY)
    246676        {
    247             case KLDRSTATE_MAPPED:
    248             case KLDRSTATE_LOADED_PREREQUISITES:
    249             case KLDRSTATE_FIXED_UP:
    250             case KLDRSTATE_RELOADED:
    251                 /* already dropped. */
    252                 break;
    253 
    254             case KLDRSTATE_PENDING_INITIALIZATION:
    255                 kldrDyldModUnloadPrerequisites(pMod);
    256                 pMod->enmState = KLDRSTATE_PENDING_GC;
    257                 break;
    258 
    259             case KLDRSTATE_GOOD:
    260                 pMod->enmState = KLDRSTATE_PENDING_TERMINATION;
    261             case KLDRSTATE_PENDING_TERMINATION:
    262             case KLDRSTATE_PENDING_GC:
    263                 kldrDyldModUnloadPrerequisites(pMod);
    264                 break;
    265 
    266             case KLDRSTATE_TERMINATING:
    267             case KLDRSTATE_GC:
    268             case KLDRSTATE_PENDING_DESTROY:
    269                 break;
    270 
    271             default:
    272                 KLDRDYLDMOD_ASSERT(!"Invalid deref state (b)");
    273                 break;
     677            pMod->enmState = KLDRSTATE_PENDING_DESTROY;
     678            kldrDyldModUnlink(pMod);
    274679        }
    275680    }
    276 
    277     /*
    278      * If there are no references whatsoever now and the module
    279      * is pending destruction, destroy it.
    280      */
    281     if (    !pMod->cRefs
    282         &&  (   pMod->enmState == KLDRSTATE_PENDING_DESTROY
    283              || pMod->enmState == KLDRSTATE_GC))
    284         kldrDyldModDestroy(pMod);
    285 }
     681    return rc;
     682}
     683
     684
     685/**
     686 * Applies fixups to a module which prerequisistes has been
     687 * successfully loaded.
     688 *
     689 * @returns 0 on success, non-zero native OS or kLdr status code on failure.
     690 * @param   pMod    The module which needs to be unmapped and set pending for destruction.
     691 */
     692int kldrDyldModFixup(PKLDRDYLDMOD pMod)
     693{
     694    int rc;
     695
     696    /* sanity */
     697    KLDRDYLDMOD_ASSERT(pMod->cRefs > 0);
     698    KLDRDYLDMOD_ASSERT(     pMod->enmState == KLDRSTATE_LOADED_PREREQUISITES
     699                       ||   pMod->enmState == KLDRSTATE_RELOADED_LOADED_PREREQUISITES);
     700
     701    /* do the job */
     702    rc = kLdrModFixupMapping(pMod->pMod, NULL, NULL);/// @todo fixme.
     703    if (!rc)
     704        pMod->enmState = KLDRSTATE_FIXED_UP;
     705    return rc;
     706}
     707
     708
     709int kldrDyldModCallInit(PKLDRDYLDMOD pMod);
     710void kldrDyldModCallTerm(PKLDRDYLDMOD pMod);
     711
     712int kldrDyldModReload(PKLDRDYLDMOD pMod);
     713int kldrDyldModAttachThread(PKLDRDYLDMOD pMod);
     714int kldrDyldModDetachThread(PKLDRDYLDMOD pMod);
     715int kldrDyldModGetStackInfo(PKLDRDYLDMOD pMod, void **ppvStack, size_t *pcbStack);
     716int kldrDyldModStartExe(PKLDRDYLDMOD pMod);
     717
     718int kldrDyldModGetName(PKLDRDYLDMOD pMod, char *pszName, size_t cchName);
     719int kldrDyldModGetFilename(PKLDRDYLDMOD pMod, char *pszFilename, size_t cchFilename);
     720int kldrDyldModQuerySymbol(PKLDRDYLDMOD pMod, uint32_t uSymbolOrdinal, const char *pszSymbolName, uintptr_t *pValue, uint32_t *pfKind);
     721
     722
  • trunk/kLdr/kLdrInternal.h

    r2843 r2845  
    201201    KLDRSTATE_PENDING_DESTROY,
    202202
    203     /** The module has been destroyed and is no longer valid.
     203    /** The module has been destroyed but not freed yet.
     204     *
     205     * This happens when a module ends up being destroyed when cRefs > 0. The
     206     * module structure will be freed when cRefs reaches 0.
    204207     *
    205208     * Prev state: GC, PENDING_DESTROY
     
    246249     * this module is already seen and shouldn't be processed again. */
    247250    uint32_t            fAlreadySeen : 1;
     251    /** Set if the module is currently mapped.
     252     * This is used to avoid unnecessary calls to kLdrModUnmap during cleanup. */
     253    uint32_t            fMapped : 1;
    248254    /** Reserved for future use. */
    249     uint32_t            fReserved : 27;
     255    uint32_t            f26Reserved : 26;
    250256    /** The load list linkage. */
    251257    struct
     
    312318
    313319int kldrDyldModCreate(PKLDRRDR pRdr, PPKLDRDYLDMOD ppMod);
    314 int kldrDyldModDestroy(PKLDRDYLDMOD pMod);
    315 int kldrDyldModAddRef(PKLDRDYLDMOD pMod);
     320void kldrDyldModDestroy(PKLDRDYLDMOD pMod);
     321void kldrDyldModAddRef(PKLDRDYLDMOD pMod);
    316322void kldrDyldModDeref(PKLDRDYLDMOD pMod);
    317 int kldrDyldModAddDep(PKLDRDYLDMOD pMod, PKLDRDYLDMOD pDep);
     323void kldrDyldModAddDep(PKLDRDYLDMOD pMod, PKLDRDYLDMOD pDep);
    318324void kldrDyldModRemoveDep(PKLDRDYLDMOD pMod, PKLDRDYLDMOD pDep);
    319325int kldrDyldModDynamicLoad(PKLDRDYLDMOD pMod);
    320326int kldrDyldModDynamicUnload(PKLDRDYLDMOD pMod);
    321 int kldrDyldModMarkGlobal(PKLDRDYLDMOD pMod);
    322 int kldrDyldModMarkSpecific(PKLDRDYLDMOD pMod);
    323 int kldrDyldModSetBindable(PKLDRDYLDMOD pMod);
    324 int kldrDyldModClearBindable(PKLDRDYLDMOD pMod);
    325 int kldrDyldModSetDeepBindable(PKLDRDYLDMOD pMod);
    326 int kldrDyldModClearDeepBindable(PKLDRDYLDMOD pMod);
     327void kldrDyldModMarkGlobal(PKLDRDYLDMOD pMod);
     328void kldrDyldModMarkSpecific(PKLDRDYLDMOD pMod);
     329void kldrDyldModSetBindable(PKLDRDYLDMOD pMod, unsigned fDeep);
     330void kldrDyldModClearBindable(PKLDRDYLDMOD pMod);
    327331int kldrDyldModMap(PKLDRDYLDMOD pMod);
    328332int kldrDyldModUnmap(PKLDRDYLDMOD pMod);
     
    345349
    346350
    347 int kldrDyldFailure(int rc, const char *pszFilename, ...);
     351int kldrDyldFailure(int rc, const char *pszFormat, ...);
    348352int kldrInit(void);
    349353void kldrTerm(void);
     
    356360 * (This is exported, so no prefix.) */
    357361extern PKLDRDYLDMOD     kLdrDyldTail;
     362/** Pointer to the head module of the initialization list.
     363 * The outermost load call will pop elements from this list in LIFO order (i.e.
     364 * from the tail). The list is only used during non-recursive initialization
     365 * and may therefore share the pNext/pPrev members with the termination list
     366 * since we don't push a module onto the termination list untill it has been
     367 * successfully initialized. */
     368extern PKLDRDYLDMOD     g_pkLdrDyldInitHead;
     369/** Pointer to the tail module of the initalization list. */
     370extern PKLDRDYLDMOD     g_pkLdrDyldInitTail;
    358371/** Pointer to the head module of the termination order list. */
    359372extern PKLDRDYLDMOD     g_pkLdrDyldTermHead;
Note: See TracChangeset for help on using the changeset viewer.