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

static int kldrModPEDoForwarderQuery ( PKLDRMODPE  pModPE,
const void *  pvBits,
const char *  pszForwarder,
PFNKLDRMODGETIMPORT  pfnGetForwarder,
void *  pvUser,
PKLDRADDR  puValue,
KU32 *  pfKind 
) [static]

Deal with a forwarder entry.

We do this seprately from kldrModPEQuerySymbol because the code is clumsy (as is all PE code thanks to the descriptive field names), and because it uses quite a bit more stack and we're trying to avoid allocating stack unless we have to.

Returns:
See kLdrModQuerySymbol.
Parameters:
pModPE The PE module interpreter instance.
pvBits Where to read the image from.
pszForwarder The forwarder entry name.
pfnGetForwarder The callback for resolving forwarder symbols. (optional)
pvUser The user argument for the callback.
puValue Where to put the value. (optional)
pfKind Where to put the symbol kind. (optional)

Definition at line 830 of file kLdrModPE.c.

References KLDRMODPE::cImportModules, KLDRMODPE::Hdrs, KLDR_ERR_FORWARDER_SYMBOL, KLDR_ERR_PE_BAD_FORWARDER, KLDR_ERR_PE_FORWARDER_IMPORT_NOT_FOUND, KLDRMODPE_RVA2TYPE, kldrModPENumberOfImports(), KLDRSYMKIND_FORWARDER, KSIZE, Name(), NIL_KLDRMOD_SYM_ORDINAL, NULL, and KLDRMODPE::pMod.

Referenced by kldrModPEQuerySymbol().

{
    const IMAGE_IMPORT_DESCRIPTOR *paImpDir;
    KU32            iImpModule;
    KU32            cchImpModule;
    const char     *pszSymbol;
    KU32            iSymbol;
    int             rc;

    if (!pfnGetForwarder)
        return KLDR_ERR_FORWARDER_SYMBOL;

    /*
     * Separate the name into a module name and a symbol name or ordinal.
     *
     * The module name ends at the first dot ('.').
     * After the dot follows either a symbol name or a hash ('#') + ordinal.
     */
    pszSymbol = pszForwarder;
    while (*pszSymbol != '.')
        pszSymbol++;
    if (!*pszSymbol)
        return KLDR_ERR_PE_BAD_FORWARDER;
    cchImpModule = pszSymbol - pszForwarder;

    pszSymbol++;                        /* skip the dot */
    if (!*pszSymbol)
        return KLDR_ERR_PE_BAD_FORWARDER;
    if (*pszSymbol == '#')
    {
        unsigned uBase;
        pszSymbol++;                    /* skip the hash */

        /* base detection */
        uBase = 10;
        if (pszSymbol[0] == '0' &&  (pszSymbol[1] == 'x' || pszSymbol[1] == 'X'))
        {
            uBase = 16;
            pszSymbol += 2;
        }

        /* ascii to integer */
        iSymbol = 0;
        for (;;)
        {
            /* convert char to digit. */
            unsigned uDigit = *pszSymbol++;
            if (uDigit >= '0' && uDigit <= '9')
                uDigit -= '0';
            else if (uDigit >= 'a' && uDigit <= 'z')
                uDigit -= 'a' + 10;
            else if (uDigit >= 'A' && uDigit <= 'Z')
                uDigit -= 'A' + 10;
            else if (!uDigit)
                break;
            else
                return KLDR_ERR_PE_BAD_FORWARDER;
            if (uDigit >= uBase)
                return KLDR_ERR_PE_BAD_FORWARDER;

            /* insert the digit */
            iSymbol *= uBase;
            iSymbol += uDigit;
        }

        pszSymbol = NULL;               /* no symbol name. */
    }
    else
        iSymbol = NIL_KLDRMOD_SYM_ORDINAL; /* no ordinal number. */


    /*
     * Find the import module name.
     *
     * We ASSUME the linker will make sure there is an import
     * entry for the module... not sure if this is right though.
     */
    if (    !pModPE->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size
        ||  !pModPE->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
        return KLDR_ERR_PE_FORWARDER_IMPORT_NOT_FOUND;
    paImpDir = KLDRMODPE_RVA2TYPE(pvBits,
                                  pModPE->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress,
                                  const IMAGE_IMPORT_DESCRIPTOR *);

    kldrModPENumberOfImports(pModPE->pMod, pvBits);
    for (iImpModule = 0; iImpModule < pModPE->cImportModules; iImpModule++)
    {
        const char *pszName = KLDRMODPE_RVA2TYPE(pvBits, paImpDir[iImpModule].Name, const char *);
        KSIZE       cchName = kHlpStrLen(pszName);
        if (    (   cchName == cchImpModule
                 || (   cchName > cchImpModule
                     && pszName[cchImpModule] == '.'
                     && (pszName[cchImpModule + 1] == 'd' || pszName[cchImpModule + 1] == 'D')
                     && (pszName[cchImpModule + 2] == 'l' || pszName[cchImpModule + 2] == 'L')
                     && (pszName[cchImpModule + 3] == 'l' || pszName[cchImpModule + 3] == 'L'))
                )
            &&  kHlpMemICompAscii(pszName, pszForwarder, cchImpModule)
           )
        {
            /*
             * Now the rest is up to the callback (almost).
             */
            rc = pfnGetForwarder(pModPE->pMod, iImpModule, iSymbol, pszSymbol,
                                 pszSymbol ? kHlpStrLen(pszSymbol) : 0, NULL, puValue, pfKind, pvUser);
            if (!rc && pfKind)
                *pfKind |= KLDRSYMKIND_FORWARDER;
            return rc;
        }
    }
    return KLDR_ERR_PE_FORWARDER_IMPORT_NOT_FOUND;
}


Generated by  Doxygen 1.6.0   Back to index