Logo Search packages:      
Sourcecode: virtualbox-ose version File versions  Download package

static int kldrDyldDoLoadPrerequisites ( PKLDRDYLDMOD  pMod,
const char *  pszPrefix,
const char *  pszSuffix,
KLDRDYLDSEARCH  enmSearch,
unsigned  fFlags 
) [static]

kldrDyldDoLoad() helper which will load prerequisites and build the initialization array / list.

Returns:
0 on success, non-zero error code on failure.
Parameters:
pMod The module to start at.
pszPrefix Prefix to use when searching.
pszSuffix Suffix to use when searching.
enmSearch Method to use when locating the module and any modules it may depend on.
fFlags Flags, a combintation of the KLDRYDLD_LOAD_FLAGS_* #defines.

The module.

The number of prerequisite modules left to process. This starts at ~0U to inidicate that we need to load/check prerequisistes.

Definition at line 800 of file kLdrDyld.c.

References KLDRDYLDMOD::cPrereqs, KLDRDYLDMOD::enmState, KLDRDYLDMOD::fAlreadySeen, KLDRDYLDMOD::fInitList, KLDRDYLDMOD::InitTerm, KLDR_ERR_PREREQUISITE_RECURSED_TOO_DEEPLY, KLDRDYLD_ASSERT, KLDRDYLD_LOAD_FLAGS_EXECUTABLE, KLDRDYLD_LOAD_FLAGS_RECURSIVE_INIT, kldrDyldModLoadPrerequisites(), kldrDyldStackAddModule(), KLDRSTATE_GOOD, KLDRSTATE_INITIALIZING, KLDRSTATE_LOADED_PREREQUISITES, KLDRSTATE_MAPPED, KLDRSTATE_PENDING_INITIALIZATION, KLDRSTATE_PENDING_TERMINATION, KLDRSTATE_RELOADED, KLDRSTATE_RELOADED_LOADED_PREREQUISITES, KLDRYDLD_LOAD_FLAGS_SPECIFIC_MODULE, NULL, KLDRDYLDMOD::papPrereqs, KLDRDYLDMOD::pMod, KLDRDYLDMOD::pNext, and KLDRDYLDMOD::pPrev.

Referenced by kldrDyldDoLoad2().

{
    static struct
    {
        /** The module. */
        PKLDRDYLDMOD    pMod;
        /** The number of prerequisite modules left to process.
         * This starts at ~0U to inidicate that we need to load/check prerequisistes. */
        unsigned        cLeft;
    }               s_aEntries[64];
    unsigned        cEntries;
    int             rc = 0;

    /* Prerequisites are always global and they just aren't executables. */
    fFlags &= ~(KLDRYDLD_LOAD_FLAGS_SPECIFIC_MODULE | KLDRDYLD_LOAD_FLAGS_EXECUTABLE);

    /* push the first entry. */
    s_aEntries[0].pMod = pMod;
    s_aEntries[0].cLeft = ~0U;
    cEntries = 1;

    /*
     * The recursion loop.
     */
    while (!rc && cEntries > 0)
    {
        const unsigned i = cEntries - 1;
        pMod = s_aEntries[i].pMod;
        if (s_aEntries[i].cLeft == ~0U)
        {
            /*
             * Load prerequisite modules.
             */
            switch (pMod->enmState)
            {
                /*
                 * Load immediate prerequisite modules and push the ones needing
                 * attention onto the stack.
                 */
                case KLDRSTATE_MAPPED:
                case KLDRSTATE_RELOADED:
                case KLDRSTATE_PENDING_TERMINATION:
                    rc = kldrDyldModLoadPrerequisites(pMod, pszPrefix, pszSuffix, enmSearch, fFlags);
                    KLDRDYLD_ASSERT(    pMod->enmState == KLDRSTATE_GOOD
                                    ||  pMod->enmState == KLDRSTATE_RELOADED_LOADED_PREREQUISITES
                                    ||  pMod->enmState == KLDRSTATE_LOADED_PREREQUISITES
                                    ||  rc);
                    if (!rc)
                        s_aEntries[i].cLeft = pMod->cPrereqs;
                    break;

                /*
                 * Check its prerequisite modules the first time around.
                 */
                case KLDRSTATE_PENDING_INITIALIZATION:
                    if (pMod->fAlreadySeen)
                        break;
                    pMod->fAlreadySeen = 1;
                    s_aEntries[i].cLeft = pMod->cPrereqs;
                    break;

                /*
                 * These are ok.
                 */
                case KLDRSTATE_LOADED_PREREQUISITES:
                case KLDRSTATE_RELOADED_LOADED_PREREQUISITES:
                case KLDRSTATE_INITIALIZING:
                case KLDRSTATE_GOOD:
                    s_aEntries[i].cLeft = 0;
                    break;

                /*
                 * All other stats are invalid.
                 */
                default:
                    KLDRDYLD_ASSERT(!"invalid state");
                    break;
            }
        }
        else if (s_aEntries[i].cLeft > 0)
        {
            /*
             * Recurse down into the next prereq.
             */
            KLDRDYLD_ASSERT(s_aEntries[i].cLeft <= pMod->cPrereqs);
            if (cEntries < sizeof(s_aEntries) / sizeof(s_aEntries[0]))
            {
                s_aEntries[cEntries].cLeft = ~(KU32)0;
                s_aEntries[cEntries].pMod = pMod->papPrereqs[pMod->cPrereqs - s_aEntries[i].cLeft];
                s_aEntries[i].cLeft--;
                cEntries++;
            }
            else
                rc = KLDR_ERR_PREREQUISITE_RECURSED_TOO_DEEPLY;
        }
        else
        {
            /*
             * We're done with this module, record it for init/cleanup.
             */
            cEntries--;
            if (pMod->enmState != KLDRSTATE_GOOD)
            {
                kldrDyldStackAddModule(pMod);
                if  (   !(fFlags & KLDRDYLD_LOAD_FLAGS_RECURSIVE_INIT)
                     && !pMod->fInitList)
                {
                    pMod->fInitList = 1;
                    pMod->InitTerm.pNext = NULL;
                    pMod->InitTerm.pPrev = g_pkLdrDyldInitTail;
                    if (g_pkLdrDyldInitTail)
                        g_pkLdrDyldInitTail->InitTerm.pNext = pMod;
                    else
                        g_pkLdrDyldInitHead = pMod;
                    g_pkLdrDyldInitTail = pMod;
                }
            }
        }
    }

    return rc;
}


Generated by  Doxygen 1.6.0   Back to index