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

static int kldrModPEDoCreate ( PKRDR  pRdr,
KLDRFOFF  offNewHdr,
PKLDRMODPE ppModPE 
) [static]

Separate function for reading creating the PE module instance to simplify cleanup on failure.

Definition at line 176 of file kLdrModPE.c.

References KLDRSEG::Alignment, KLDRMOD::aSegments, KLDRMODPE::aShdrs, KLDRSEG::cb, KLDRSEG::cbFile, KLDRSEG::cbMapped, KLDRMOD::cchFilename, KLDRMOD::cchName, KLDRSEG::cchName, KLDRMODPE::cImportModules, KLDRMOD::cSegments, KLDRMOD::enmArch, KLDRMOD::enmCpu, KLDRMOD::enmEndian, KLDRMOD::enmFmt, KLDRSEG::enmProt, KLDRMOD::enmType, KLDRMODPE::f32Reserved, KLDRSEG::fFlags, KLDRMODPE::Hdrs, IMAGE_NT_SIGNATURE, K_ALIGN_Z, K_OFFSETOF, KCPUARCH_AMD64, KCPUARCH_X86_32, KERR_NO_MEMORY, KLDR_ERR_PE_BAD_FILE_HEADER, KLDR_ERR_PE_UNSUPPORTED_MACHINE, KLDR_ERR_UNKNOWN_FORMAT, KLDRENDIAN_LITTLE, KLDRFMT_PE, kldrModPEDoOptionalHeaderConversion(), kLdrModPEDoOptionalHeaderValidation(), kLdrModPEDoSectionHeadersValidation(), 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, KLDRMODPE::offHdrs, KLDRSEG::pchName, KLDRMODPE::pMod, KLDRMOD::pOps, KLDRMOD::pRdr, KLDRMOD::pszFilename, KLDRMOD::pszName, KLDRMODPE::pvBits, KLDRMOD::pvData, KLDRMODPE::pvMapping, KLDRSEG::pvUser, KLDRSEG::RVA, KLDRSEG::Sel16bit, KLDRSEG::SelFlat, KLDRMOD::u32Magic, and while().

Referenced by kldrModPECreate().

{
    struct
    {
        KU32                Signature;
        IMAGE_FILE_HEADER   FileHdr;
    } s;
    PKLDRMODPE pModPE;
    PKLDRMOD pMod;
    KSIZE cb;
    KSIZE cchFilename;
    KLDRFOFF off;
    KU32 i;
    int rc;
    *ppModPE = NULL;

    /*
     * Read the signature and file header.
     */
    rc = kRdrRead(pRdr, &s, sizeof(s), offNewHdr > 0 ? offNewHdr : 0);
    if (rc)
        return rc;
    if (s.Signature != IMAGE_NT_SIGNATURE)
        return KLDR_ERR_UNKNOWN_FORMAT;

    /* sanity checks. */
    if (    s.FileHdr.NumberOfSections > 4096
        ||  (   s.FileHdr.SizeOfOptionalHeader != sizeof(IMAGE_OPTIONAL_HEADER32)
             && s.FileHdr.SizeOfOptionalHeader != sizeof(IMAGE_OPTIONAL_HEADER64))
        ||  !(s.FileHdr.Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE)
       )
        return KLDR_ERR_PE_BAD_FILE_HEADER;
    if (    s.FileHdr.Machine != IMAGE_FILE_MACHINE_I386
        &&  s.FileHdr.Machine != IMAGE_FILE_MACHINE_AMD64
       )
        return KLDR_ERR_PE_UNSUPPORTED_MACHINE;

    /*
     * Calc the instance size, allocate and initialize it.
     */
    cchFilename = kHlpStrLen(kRdrName(pRdr));
    cb = K_ALIGN_Z(K_OFFSETOF(KLDRMODPE, aShdrs[s.FileHdr.NumberOfSections]), 16)
       + K_OFFSETOF(KLDRMOD, aSegments[s.FileHdr.NumberOfSections + 1])
       + cchFilename + 1;
    pModPE = (PKLDRMODPE)kHlpAlloc(cb);
    if (!pModPE)
        return KERR_NO_MEMORY;
    *ppModPE = pModPE;

    /* KLDRMOD */
    pMod = (PKLDRMOD)((KU8 *)pModPE + K_ALIGN_Z(K_OFFSETOF(KLDRMODPE, aShdrs[s.FileHdr.NumberOfSections]), 16));
    pMod->pvData = pModPE;
    pMod->pRdr = pRdr;
    pMod->pOps = NULL;      /* set upon success. */
    pMod->cSegments = s.FileHdr.NumberOfSections + 1;
    pMod->cchFilename = cchFilename;
    pMod->pszFilename = (char *)&pMod->aSegments[pMod->cSegments];
    kHlpMemCopy((char *)pMod->pszFilename, kRdrName(pRdr), cchFilename + 1);
    pMod->pszName = kHlpGetFilename(pMod->pszFilename);
    pMod->cchName = cchFilename - (pMod->pszName - pMod->pszFilename);
    switch (s.FileHdr.Machine)
    {
        case IMAGE_FILE_MACHINE_I386:
            pMod->enmCpu = KCPU_I386;
            pMod->enmArch = KCPUARCH_X86_32;
            pMod->enmEndian = KLDRENDIAN_LITTLE;
            break;

        case IMAGE_FILE_MACHINE_AMD64:
            pMod->enmCpu = KCPU_K8;
            pMod->enmArch = KCPUARCH_AMD64;
            pMod->enmEndian = KLDRENDIAN_LITTLE;
            break;
        default:
            kHlpAssert(0);
            break;
    }
    pMod->enmFmt = KLDRFMT_PE;
    if (s.FileHdr.Characteristics & IMAGE_FILE_DLL)
        pMod->enmType = !(s.FileHdr.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
            ? KLDRTYPE_SHARED_LIBRARY_RELOCATABLE
            : KLDRTYPE_SHARED_LIBRARY_FIXED;
    else
        pMod->enmType = !(s.FileHdr.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
            ? KLDRTYPE_EXECUTABLE_RELOCATABLE
            : KLDRTYPE_EXECUTABLE_FIXED;
    pMod->u32Magic = 0;     /* set upon success. */

    /* KLDRMODPE */
    pModPE->pMod = pMod;
    pModPE->pvBits = NULL;
    pModPE->pvMapping = NULL;
    pModPE->f32Reserved = 0;
    pModPE->cImportModules = ~(KU32)0;
    pModPE->offHdrs = offNewHdr >= 0 ? offNewHdr : 0;
    pModPE->Hdrs.Signature = s.Signature;
    pModPE->Hdrs.FileHeader = s.FileHdr;

    /*
     * Read the optional header and the section table.
     */
    off = pModPE->offHdrs + sizeof(pModPE->Hdrs.Signature) + sizeof(pModPE->Hdrs.FileHeader);
    rc = kRdrRead(pRdr, &pModPE->Hdrs.OptionalHeader, pModPE->Hdrs.FileHeader.SizeOfOptionalHeader, off);
    if (rc)
        return rc;
    if (pModPE->Hdrs.FileHeader.SizeOfOptionalHeader != sizeof(pModPE->Hdrs.OptionalHeader))
        kldrModPEDoOptionalHeaderConversion(&pModPE->Hdrs.OptionalHeader);
    off += pModPE->Hdrs.FileHeader.SizeOfOptionalHeader;
    rc = kRdrRead(pRdr, &pModPE->aShdrs[0], sizeof(IMAGE_SECTION_HEADER) * pModPE->Hdrs.FileHeader.NumberOfSections, off);
    if (rc)
        return rc;

    /*
     * Validate the two.
     */
    rc = kLdrModPEDoOptionalHeaderValidation(pModPE);
    if (rc)
        return rc;
    for (i = 0; i < pModPE->Hdrs.FileHeader.NumberOfSections; i++)
    {
        rc = kLdrModPEDoSectionHeadersValidation(pModPE);
        if (rc)
            return rc;
    }

    /*
     * Setup the KLDRMOD segment array.
     */
    /* 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 = pModPE->Hdrs.OptionalHeader.SizeOfHeaders;
    pMod->aSegments[0].Alignment = pModPE->Hdrs.OptionalHeader.SectionAlignment;
    pMod->aSegments[0].LinkAddress = pModPE->Hdrs.OptionalHeader.ImageBase;
    pMod->aSegments[0].offFile = 0;
    pMod->aSegments[0].cbFile = pModPE->Hdrs.OptionalHeader.SizeOfHeaders;
    pMod->aSegments[0].RVA = 0;
    if (pMod->cSegments > 1)
        pMod->aSegments[0].cbMapped = pModPE->aShdrs[0].VirtualAddress;
    else
        pMod->aSegments[0].cbMapped = pModPE->Hdrs.OptionalHeader.SizeOfHeaders;
    pMod->aSegments[0].MapAddress = 0;

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

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

        /* name */
        pMod->aSegments[i + 1].pchName = pch = (const char *)&pModPE->aShdrs[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 (!(pModPE->aShdrs[i].Characteristics & IMAGE_SCN_TYPE_NOLOAD))
        {
            pMod->aSegments[i + 1].cb          = pModPE->aShdrs[i].Misc.VirtualSize;
            pMod->aSegments[i + 1].LinkAddress = pModPE->aShdrs[i].VirtualAddress
                                               + pModPE->Hdrs.OptionalHeader.ImageBase;
            pMod->aSegments[i + 1].RVA         = pModPE->aShdrs[i].VirtualAddress;
            pMod->aSegments[i + 1].cbMapped    = pModPE->aShdrs[i].Misc.VirtualSize;
            if (i + 2 < pMod->cSegments)
                pMod->aSegments[i + 1].cbMapped= pModPE->aShdrs[i + 1].VirtualAddress
                                               - pModPE->aShdrs[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 = pModPE->aShdrs[i].PointerToRawData;
        pMod->aSegments[i + 1].cbFile = pModPE->aShdrs[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 (  pModPE->aShdrs[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 (pModPE->aShdrs[i].Characteristics & IMAGE_SCN_ALIGN_MASK)
        {
            case 0: /* hope this is right... */
                pMod->aSegments[i + 1].Alignment = pModPE->Hdrs.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;
        }
    }

    /*
     * We're done.
     */
    *ppModPE = pModPE;
    return 0;
}


Generated by  Doxygen 1.6.0   Back to index