Пример #1
0
/**
 * Open a image using kLdr.
 *
 * @returns iprt status code.
 * @param   pReader     The loader reader instance which will provide the raw image bits.
 * @param   fFlags      Reserved, MBZ.
 * @param   enmArch     CPU architecture specifier for the image to be loaded.
 * @param   phLdrMod    Where to store the handle.
 */
int rtldrkLdrOpen(PRTLDRREADER pReader, uint32_t fFlags, RTLDRARCH enmArch, PRTLDRMOD phLdrMod)
{
    /* Convert enmArch to k-speak. */
    KCPUARCH enmCpuArch;
    switch (enmArch)
    {
        case RTLDRARCH_WHATEVER:
            enmCpuArch = KCPUARCH_UNKNOWN;
            break;
        case RTLDRARCH_X86_32:
            enmCpuArch = KCPUARCH_X86_32;
            break;
        case RTLDRARCH_AMD64:
            enmCpuArch = KCPUARCH_AMD64;
            break;
        default:
            return VERR_INVALID_PARAMETER;
    }

    /* Create a rtkldrRdr_ instance. */
    PRTKLDRRDR pRdr = (PRTKLDRRDR)RTMemAllocZ(sizeof(*pRdr));
    if (!pRdr)
        return VERR_NO_MEMORY;
    pRdr->Core.u32Magic = KRDR_MAGIC;
    pRdr->Core.pOps = &g_kLdrRdrFileOps;
    pRdr->pReader = pReader;

    /* Try open it. */
    PKLDRMOD pMod;
    int krc = kLdrModOpenFromRdr(&pRdr->Core, fFlags, enmCpuArch, &pMod);
    if (!krc)
    {
        /* Create a module wrapper for it. */
        PRTLDRMODKLDR pNewMod = (PRTLDRMODKLDR)RTMemAllocZ(sizeof(*pNewMod));
        if (pNewMod)
        {
            pNewMod->Core.u32Magic = RTLDRMOD_MAGIC;
            pNewMod->Core.eState = LDR_STATE_OPENED;
            pNewMod->Core.pOps = &g_rtkldrOps;
            pNewMod->pMod = pMod;
            *phLdrMod = &pNewMod->Core;

#ifdef LOG_ENABLED
            Log(("rtldrkLdrOpen: '%s' (%s) %u segments\n",
                 pMod->pszName, pMod->pszFilename, pMod->cSegments));
            for (unsigned iSeg = 0; iSeg < pMod->cSegments; iSeg++)
            {
                Log(("Segment #%-2u: RVA=%08llx cb=%08llx '%.*s'\n", iSeg,
                     pMod->aSegments[iSeg].RVA,
                     pMod->aSegments[iSeg].cb,
                     pMod->aSegments[iSeg].cchName,
                     pMod->aSegments[iSeg].pchName));
            }
#endif
            return VINF_SUCCESS;
        }
        kLdrModClose(pMod);
        krc = KERR_NO_MEMORY;
    }
    return rtkldrConvertError(krc);
}
/**
 * Open a image using kLdr.
 *
 * @returns iprt status code.
 * @param   pReader     The loader reader instance which will provide the raw image bits.
 * @param   fFlags      Reserved, MBZ.
 * @param   enmArch     CPU architecture specifier for the image to be loaded.
 * @param   phLdrMod    Where to store the handle.
 * @param   pErrInfo    Where to return extended error information. Optional.
 */
int rtldrkLdrOpen(PRTLDRREADER pReader, uint32_t fFlags, RTLDRARCH enmArch, PRTLDRMOD phLdrMod, PRTERRINFO pErrInfo)
{
    /* Convert enmArch to k-speak. */
    KCPUARCH enmCpuArch;
    switch (enmArch)
    {
    case RTLDRARCH_WHATEVER:
        enmCpuArch = KCPUARCH_UNKNOWN;
        break;
    case RTLDRARCH_X86_32:
        enmCpuArch = KCPUARCH_X86_32;
        break;
    case RTLDRARCH_AMD64:
        enmCpuArch = KCPUARCH_AMD64;
        break;
    default:
        return VERR_INVALID_PARAMETER;
    }
    KU32 fKFlags = 0;
    if (fFlags & RTLDR_O_FOR_DEBUG)
        fKFlags |= KLDRMOD_OPEN_FLAGS_FOR_INFO;

    /* Create a rtkldrRdr_ instance. */
    PRTKLDRRDR pRdr = (PRTKLDRRDR)RTMemAllocZ(sizeof(*pRdr));
    if (!pRdr)
        return VERR_NO_MEMORY;
    pRdr->Core.u32Magic = KRDR_MAGIC;
    pRdr->Core.pOps = &g_kLdrRdrFileOps;
    pRdr->pReader = pReader;

    /* Try open it. */
    PKLDRMOD pMod;
    int krc = kLdrModOpenFromRdr(&pRdr->Core, fKFlags, enmCpuArch, &pMod);
    if (!krc)
    {
        /* Create a module wrapper for it. */
        PRTLDRMODKLDR pNewMod = (PRTLDRMODKLDR)RTMemAllocZ(sizeof(*pNewMod));
        if (pNewMod)
        {
            pNewMod->Core.u32Magic = RTLDRMOD_MAGIC;
            pNewMod->Core.eState   = LDR_STATE_OPENED;
            pNewMod->Core.pOps     = &g_rtkldrOps;
            pNewMod->Core.pReader  = pReader;
            switch (pMod->enmFmt)
            {
            case KLDRFMT_NATIVE:
                pNewMod->Core.enmFormat = RTLDRFMT_NATIVE;
                break;
            case KLDRFMT_AOUT:
                pNewMod->Core.enmFormat = RTLDRFMT_AOUT;
                break;
            case KLDRFMT_ELF:
                pNewMod->Core.enmFormat = RTLDRFMT_ELF;
                break;
            case KLDRFMT_LX:
                pNewMod->Core.enmFormat = RTLDRFMT_LX;
                break;
            case KLDRFMT_MACHO:
                pNewMod->Core.enmFormat = RTLDRFMT_MACHO;
                break;
            case KLDRFMT_PE:
                pNewMod->Core.enmFormat = RTLDRFMT_PE;
                break;
            default:
                AssertMsgFailed(("%d\n", pMod->enmFmt));
                pNewMod->Core.enmFormat = RTLDRFMT_NATIVE;
                break;
            }
            switch (pMod->enmType)
            {
            case KLDRTYPE_OBJECT:
                pNewMod->Core.enmType = RTLDRTYPE_OBJECT;
                break;
            case KLDRTYPE_EXECUTABLE_FIXED:
                pNewMod->Core.enmType = RTLDRTYPE_EXECUTABLE_FIXED;
                break;
            case KLDRTYPE_EXECUTABLE_RELOCATABLE:
                pNewMod->Core.enmType = RTLDRTYPE_EXECUTABLE_RELOCATABLE;
                break;
            case KLDRTYPE_EXECUTABLE_PIC:
                pNewMod->Core.enmType = RTLDRTYPE_EXECUTABLE_PIC;
                break;
            case KLDRTYPE_SHARED_LIBRARY_FIXED:
                pNewMod->Core.enmType = RTLDRTYPE_SHARED_LIBRARY_FIXED;
                break;
            case KLDRTYPE_SHARED_LIBRARY_RELOCATABLE:
                pNewMod->Core.enmType = RTLDRTYPE_SHARED_LIBRARY_RELOCATABLE;
                break;
            case KLDRTYPE_SHARED_LIBRARY_PIC:
                pNewMod->Core.enmType = RTLDRTYPE_SHARED_LIBRARY_PIC;
                break;
            case KLDRTYPE_FORWARDER_DLL:
                pNewMod->Core.enmType = RTLDRTYPE_FORWARDER_DLL;
                break;
            case KLDRTYPE_CORE:
                pNewMod->Core.enmType = RTLDRTYPE_CORE;
                break;
            case KLDRTYPE_DEBUG_INFO:
                pNewMod->Core.enmType = RTLDRTYPE_DEBUG_INFO;
                break;
            default:
                AssertMsgFailed(("%d\n", pMod->enmType));
                pNewMod->Core.enmType = RTLDRTYPE_OBJECT;
                break;
            }
            switch (pMod->enmEndian)
            {
            case KLDRENDIAN_LITTLE:
                pNewMod->Core.enmEndian = RTLDRENDIAN_LITTLE;
                break;
            case KLDRENDIAN_BIG:
                pNewMod->Core.enmEndian = RTLDRENDIAN_BIG;
                break;
            case KLDRENDIAN_NA:
                pNewMod->Core.enmEndian = RTLDRENDIAN_NA;
                break;
            default:
                AssertMsgFailed(("%d\n", pMod->enmEndian));
                pNewMod->Core.enmEndian = RTLDRENDIAN_NA;
                break;
            }
            switch (pMod->enmArch)
            {
            case KCPUARCH_X86_32:
                pNewMod->Core.enmArch   = RTLDRARCH_X86_32;
                break;
            case KCPUARCH_AMD64:
                pNewMod->Core.enmArch   = RTLDRARCH_AMD64;
                break;
            default:
                AssertMsgFailed(("%d\n", pMod->enmArch));
                pNewMod->Core.enmArch = RTLDRARCH_WHATEVER;
                break;
            }
            pNewMod->pMod          = pMod;
            *phLdrMod = &pNewMod->Core;

#ifdef LOG_ENABLED
            Log(("rtldrkLdrOpen: '%s' (%s) %u segments\n",
                 pMod->pszName, pMod->pszFilename, pMod->cSegments));
            for (unsigned iSeg = 0; iSeg < pMod->cSegments; iSeg++)
            {
                Log(("Segment #%-2u: RVA=%08llx cb=%08llx '%.*s'\n", iSeg,
                     pMod->aSegments[iSeg].RVA,
                     pMod->aSegments[iSeg].cb,
                     pMod->aSegments[iSeg].cchName,
                     pMod->aSegments[iSeg].pchName));
            }
#endif
            return VINF_SUCCESS;
        }

        /* bail out */
        kLdrModClose(pMod);
        krc = KERR_NO_MEMORY;
    }
    else
        RTMemFree(pRdr);

    return rtkldrConvertError(krc);
}