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

int kLdrModOpenNativeByHandle ( KUPTR  uHandle,
PPKLDRMOD  ppMod 
)

Creates a native module interpret for an already module already loaded by the native loader.

Returns:
0 on success.

non-zero native or kLdr status code on failure.

Parameters:
pszFilename The filename or module name to be loaded.
ppMod Where to store the module interpreter instance pointer.
Remarks:
This will not make the native loader increment the load count.

Todo:
DosQueryHeaderInfo should be able to get us what we want on OS/2.

Todo:
get soname

Definition at line 234 of file kLdrModNative.c.

References KLDRSEG::Alignment, KLDRMOD::aSegments, KLDRSEG::cb, KLDRSEG::cbFile, KLDRSEG::cbMapped, KLDRMOD::cchFilename, KLDRMOD::cchName, KLDRSEG::cchName, KLDRMODNATIVE::cImportModules, KLDRMOD::cSegments, DWORD, KLDRMOD::enmArch, KLDRMOD::enmCpu, KLDRMOD::enmEndian, KLDRMOD::enmFmt, KLDRSEG::enmProt, KLDRMOD::enmType, KLDRMODNATIVE::f32Reserved, KLDRMODNATIVE::hmod, IMAGE_DOS_SIGNATURE, IMAGE_NT_SIGNATURE, K_ALIGN_Z, K_OFFSETOF, KCPUARCH_AMD64, KCPUARCH_X86_32, KERR_NO_MEMORY, KLDR_ERR_UNKNOWN_FORMAT, KLDRENDIAN_LITTLE, KLDRFMT_NATIVE, KLDRMODNATIVE_ASSERT, KLDRTYPE_EXECUTABLE_FIXED, KLDRTYPE_EXECUTABLE_RELOCATABLE, KLDRTYPE_SHARED_LIBRARY_FIXED, KLDRTYPE_SHARED_LIBRARY_RELOCATABLE, KPROT_EXECUTE, KPROT_EXECUTE_READ, KPROT_EXECUTE_READWRITE, KPROT_EXECUTE_WRITECOPY, KPROT_NOACCESS, KPROT_READONLY, KPROT_READWRITE, KPROT_WRITECOPY, KSIZE, KLDRSEG::LinkAddress, KLDRSEG::MapAddress, NIL_KLDRADDR, NULL, KLDRSEG::offFile, KLDRSEG::pchName, KLDRMODNATIVE::pMod, KLDRMOD::pOps, KLDRMOD::pRdr, KLDRMOD::pszFilename, KLDRMOD::pszName, KLDRMOD::pvData, KLDRSEG::pvUser, KLDRSEG::RVA, and KLDRMOD::u32Magic.

Referenced by kLdrModOpenNative().

{
    KSIZE cb;
    KSIZE cchFilename;
    KU32 cSegments;
    PKLDRMOD pMod;
    PKLDRMODNATIVE pModNative;

    /*
     * Delcare variables, parse the module header or whatever and determin the
     * size of the module instance.
     */
#if K_OS == K_OS_OS2
    char szFilename[CCHMAXPATH];
    int rc;

    /* get the filename. */
    rc = DosQueryModuleName((HMODULE)uHandle, sizeof(szFilename), szFilename);
    if (rc)
    {
        KLDRMODNATIVE_ASSERT(rc);
        szFilename[0] = '\0';
    }

    /* get the segment count. */
    /** @todo DosQueryHeaderInfo should be able to get us what we want on OS/2. */
    cSegments = 1;

#elif K_OS == K_OS_WINDOWS
    DWORD                       dw;
    char                        szFilename[MAX_PATH];
    const IMAGE_NT_HEADERS     *pNtHdrs;
    const IMAGE_SECTION_HEADER *paShdrs;
    const IMAGE_DOS_HEADER     *pDosHdr = (const IMAGE_DOS_HEADER *)uHandle;
    unsigned                    i;

    /* get the filename. */
    dw = GetModuleFileName((HANDLE)uHandle, szFilename, sizeof(szFilename));
    if (dw <= 0)
    {
        KLDRMODNATIVE_ASSERT(dw <= 0);
        szFilename[0] = '\0';
    }

    /* get the segment count. */
    if (pDosHdr->e_magic == IMAGE_DOS_SIGNATURE)
        pNtHdrs = (const IMAGE_NT_HEADERS *)((KUPTR)pDosHdr + pDosHdr->e_lfanew);
    else
        pNtHdrs = (const IMAGE_NT_HEADERS *)pDosHdr;
    if (pNtHdrs->Signature != IMAGE_NT_SIGNATURE)
    {
        KLDRMODNATIVE_ASSERT(!"bad signature");
        return KLDR_ERR_UNKNOWN_FORMAT;
    }
    if (pNtHdrs->FileHeader.SizeOfOptionalHeader != sizeof(IMAGE_OPTIONAL_HEADER))
    {
        KLDRMODNATIVE_ASSERT(!"bad optional header size");
        return KLDR_ERR_UNKNOWN_FORMAT;
    }
    cSegments = pNtHdrs->FileHeader.NumberOfSections + 1;
    paShdrs = (const IMAGE_SECTION_HEADER *)(pNtHdrs + 1);

#elif K_OS == K_OS_DARWIN
    char    szFilename[1] = "";
    cSegments = 0; /** @todo Figure out the Mac OS X dynamic loader. */

#else
# error "Port me"
#endif

    /*
     * Calc the instance size, allocate and initialize it.
     */
    cchFilename = kHlpStrLen(szFilename);
    cb = K_ALIGN_Z(sizeof(KLDRMODNATIVE), 16)
       + K_OFFSETOF(KLDRMOD, aSegments[cSegments])
       + cchFilename + 1;
    pModNative = (PKLDRMODNATIVE)kHlpAlloc(cb);
    if (!pModNative)
        return KERR_NO_MEMORY;

    /* KLDRMOD */
    pMod = (PKLDRMOD)((KU8 *)pModNative + K_ALIGN_Z(sizeof(KLDRMODNATIVE), 16));
    pMod->pvData = pModNative;
    pMod->pRdr = NULL;
    pMod->pOps = NULL;      /* set upon success. */
    pMod->cSegments = cSegments;
    pMod->cchFilename = cchFilename;
    pMod->pszFilename = (char *)&pMod->aSegments[pMod->cSegments];
    kHlpMemCopy((char *)pMod->pszFilename, szFilename, cchFilename + 1);
    pMod->pszName = kHlpGetFilename(pMod->pszFilename); /** @todo get soname */
    pMod->cchName = cchFilename - (pMod->pszName - pMod->pszFilename);
#if defined(__i386__) || defined(__X86__) || defined(_M_IX86)
    pMod->enmCpu = KCPU_I386;
    pMod->enmArch = KCPUARCH_X86_32;
    pMod->enmEndian = KLDRENDIAN_LITTLE;
#elif defined(__X86_64__) || defined(__x86_64__) || defined(__AMD64__) || defined(_M_IX64)
    pMod->enmCpu = KCPU_K8;
    pMod->enmArch = KCPUARCH_AMD64;
    pMod->enmEndian = KLDRENDIAN_LITTLE;
#else
# error "Port me"
#endif
    pMod->enmFmt = KLDRFMT_NATIVE;
    pMod->enmType = KLDRTYPE_SHARED_LIBRARY_RELOCATABLE;
    pMod->u32Magic = 0;     /* set upon success. */

    /* KLDRMODNATIVE */
    pModNative->pMod = pMod;
    pModNative->f32Reserved = 0;
    pModNative->cImportModules = ~(KU32)0;

    /*
     * Set native instance data.
     */
#if K_OS == K_OS_OS2
    pModNative->hmod = (HMODULE)uHandle;

    /* just fake a segment for now. */
    pMod->aSegments[0].pvUser = NULL;
    pMod->aSegments[0].pchName = "fake";
    pMod->aSegments[0].cchName = sizeof("fake") - 1;
    pMod->aSegments[0].enmProt = KPROT_NOACCESS;
    pMod->aSegments[0].cb = 0;
    pMod->aSegments[0].Alignment = 0;
    pMod->aSegments[0].LinkAddress = NIL_KLDRADDR;
    pMod->aSegments[0].offFile = -1;
    pMod->aSegments[0].cbFile = 0;
    pMod->aSegments[0].RVA = NIL_KLDRADDR;
    pMod->aSegments[0].cbMapped = 0;
    pMod->aSegments[0].MapAddress = 0;

#elif K_OS == K_OS_WINDOWS
    pModNative->hmod = (HMODULE)uHandle;
    pModNative->pNtHdrs = pNtHdrs;
    pModNative->paShdrs = paShdrs;

    if (pNtHdrs->FileHeader.Characteristics & IMAGE_FILE_DLL)
        pMod->enmType = !(pNtHdrs->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
            ? KLDRTYPE_SHARED_LIBRARY_RELOCATABLE
            : KLDRTYPE_SHARED_LIBRARY_FIXED;
    else
        pMod->enmType = !(pNtHdrs->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
            ? KLDRTYPE_EXECUTABLE_RELOCATABLE
            : KLDRTYPE_EXECUTABLE_FIXED;

    /* The implied headers section. */
    pMod->aSegments[0].pvUser = NULL;
    pMod->aSegments[0].pchName = "TheHeaders";
    pMod->aSegments[0].cchName = sizeof("TheHeaders") - 1;
    pMod->aSegments[0].enmProt = KPROT_READONLY;
    pMod->aSegments[0].cb = pNtHdrs->OptionalHeader.SizeOfHeaders;
    pMod->aSegments[0].Alignment = pNtHdrs->OptionalHeader.SectionAlignment;
    pMod->aSegments[0].LinkAddress = pNtHdrs->OptionalHeader.ImageBase;
    pMod->aSegments[0].offFile = 0;
    pMod->aSegments[0].cbFile = pNtHdrs->OptionalHeader.SizeOfHeaders;
    pMod->aSegments[0].RVA = 0;
    if (pMod->cSegments > 1)
        pMod->aSegments[0].cbMapped = paShdrs[0].VirtualAddress;
    else
        pMod->aSegments[0].cbMapped = pNtHdrs->OptionalHeader.SizeOfHeaders;
    pMod->aSegments[0].MapAddress = 0;

    /* The section headers. */
    for (i = 0; i < pNtHdrs->FileHeader.NumberOfSections; i++)
    {
        const char *pch;

        /* unused */
        pMod->aSegments[i + 1].pvUser = NULL;
        pMod->aSegments[i + 1].MapAddress = 0;

        /* name */
        pMod->aSegments[i + 1].pchName = pch = &paShdrs[i].Name[0];
        cb = IMAGE_SIZEOF_SHORT_NAME;
        while (     cb > 0
               &&   (pch[cb - 1] == ' ' || pch[cb - 1] == '\0'))
            cb--;
        pMod->aSegments[i + 1].cchName = cb;

        /* size and addresses */
        if (!(paShdrs[i].Characteristics & IMAGE_SCN_TYPE_NOLOAD))
        {
            pMod->aSegments[i + 1].cb          = paShdrs[i].Misc.VirtualSize;
            pMod->aSegments[i + 1].LinkAddress = paShdrs[i].VirtualAddress
                                               + pNtHdrs->OptionalHeader.ImageBase;
            pMod->aSegments[i + 1].RVA         = paShdrs[i].VirtualAddress;
            pMod->aSegments[i + 1].cbMapped    = paShdrs[i].Misc.VirtualSize;
            if (i + 2 < pMod->cSegments)
                pMod->aSegments[i + 1].cbMapped= paShdrs[i + 1].VirtualAddress
                                               - paShdrs[i].VirtualAddress;
        }
        else
        {
            pMod->aSegments[i + 1].cb          = 0;
            pMod->aSegments[i + 1].cbMapped    = 0;
            pMod->aSegments[i + 1].LinkAddress = NIL_KLDRADDR;
            pMod->aSegments[i + 1].RVA         = 0;
        }

        /* file location */
        pMod->aSegments[i + 1].offFile = paShdrs[i].PointerToRawData;
        pMod->aSegments[i + 1].cbFile = paShdrs[i].SizeOfRawData;
        if (    pMod->aSegments[i + 1].cbMapped > 0 /* if mapped */
            &&  (KLDRSIZE)pMod->aSegments[i + 1].cbFile > pMod->aSegments[i + 1].cbMapped)
            pMod->aSegments[i + 1].cbFile = pMod->aSegments[i + 1].cbMapped;

        /* protection */
        switch (  paShdrs[i].Characteristics
                & (IMAGE_SCN_MEM_SHARED | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE))
        {
            case 0:
            case IMAGE_SCN_MEM_SHARED:
                pMod->aSegments[i + 1].enmProt = KPROT_NOACCESS;
                break;
            case IMAGE_SCN_MEM_READ:
            case IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_SHARED:
                pMod->aSegments[i + 1].enmProt = KPROT_READONLY;
                break;
            case IMAGE_SCN_MEM_WRITE:
            case IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_READ:
                pMod->aSegments[i + 1].enmProt = KPROT_WRITECOPY;
                break;
            case IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_SHARED:
            case IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_SHARED | IMAGE_SCN_MEM_READ:
                pMod->aSegments[i + 1].enmProt = KPROT_READWRITE;
                break;
            case IMAGE_SCN_MEM_EXECUTE:
            case IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_SHARED:
                pMod->aSegments[i + 1].enmProt = KPROT_EXECUTE;
                break;
            case IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ:
            case IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_SHARED:
                pMod->aSegments[i + 1].enmProt = KPROT_EXECUTE_READ;
                break;
            case IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_WRITE:
            case IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_READ:
                pMod->aSegments[i + 1].enmProt = KPROT_EXECUTE_WRITECOPY;
                break;
            case IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_SHARED:
            case IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_SHARED | IMAGE_SCN_MEM_READ:
                pMod->aSegments[i + 1].enmProt = KPROT_EXECUTE_READWRITE;
                break;
        }

        /* alignment. */
        switch (paShdrs[i].Characteristics & IMAGE_SCN_ALIGN_MASK)
        {
            case 0: /* hope this is right... */
                pMod->aSegments[i + 1].Alignment = pNtHdrs->OptionalHeader.SectionAlignment;
                break;
            case IMAGE_SCN_ALIGN_1BYTES:        pMod->aSegments[i + 1].Alignment = 1; break;
            case IMAGE_SCN_ALIGN_2BYTES:        pMod->aSegments[i + 1].Alignment = 2; break;
            case IMAGE_SCN_ALIGN_4BYTES:        pMod->aSegments[i + 1].Alignment = 4; break;
            case IMAGE_SCN_ALIGN_8BYTES:        pMod->aSegments[i + 1].Alignment = 8; break;
            case IMAGE_SCN_ALIGN_16BYTES:       pMod->aSegments[i + 1].Alignment = 16; break;
            case IMAGE_SCN_ALIGN_32BYTES:       pMod->aSegments[i + 1].Alignment = 32; break;
            case IMAGE_SCN_ALIGN_64BYTES:       pMod->aSegments[i + 1].Alignment = 64; break;
            case IMAGE_SCN_ALIGN_128BYTES:      pMod->aSegments[i + 1].Alignment = 128; break;
            case IMAGE_SCN_ALIGN_256BYTES:      pMod->aSegments[i + 1].Alignment = 256; break;
            case IMAGE_SCN_ALIGN_512BYTES:      pMod->aSegments[i + 1].Alignment = 512; break;
            case IMAGE_SCN_ALIGN_1024BYTES:     pMod->aSegments[i + 1].Alignment = 1024; break;
            case IMAGE_SCN_ALIGN_2048BYTES:     pMod->aSegments[i + 1].Alignment = 2048; break;
            case IMAGE_SCN_ALIGN_4096BYTES:     pMod->aSegments[i + 1].Alignment = 4096; break;
            case IMAGE_SCN_ALIGN_8192BYTES:     pMod->aSegments[i + 1].Alignment = 8192; break;
            default: kHlpAssert(0);          pMod->aSegments[i + 1].Alignment = 0; break;
        }
    }

#elif K_OS == K_OS_DARWIN
    /** @todo Figure out the Mac OS X dynamic loader. */

#else
# error "Port me"
#endif

    /*
     * We're done.
     */
    *ppMod = pMod;
    return 0;
}


Generated by  Doxygen 1.6.0   Back to index