/** @copydoc RTLDROPS::pfnGetSymbolEx */ static DECLCALLBACK(int) rtkldr_GetSymbolEx(PRTLDRMODINTERNAL pMod, const void *pvBits, RTUINTPTR BaseAddress, const char *pszSymbol, RTUINTPTR *pValue) { PKLDRMOD pModkLdr = ((PRTLDRMODKLDR)pMod)->pMod; KLDRADDR uValue; #if defined(RT_OS_OS2) || defined(RT_OS_DARWIN) /* * Add underscore prefix. */ if (pszSymbol) { size_t cch = strlen(pszSymbol); char *psz = (char *)alloca(cch + 2); memcpy(psz + 1, pszSymbol, cch + 1); *psz = '_'; pszSymbol = psz; } #endif int rc = kLdrModQuerySymbol(pModkLdr, pvBits, BaseAddress, NIL_KLDRMOD_SYM_ORDINAL, pszSymbol, strlen(pszSymbol), NULL, NULL, NULL, &uValue, NULL); if (!rc) { *pValue = uValue; return VINF_SUCCESS; } return rtkldrConvertError(rc); }
/** @copydoc RTLDROPS::pfnRelocate */ static DECLCALLBACK(int) rtkldr_Relocate(PRTLDRMODINTERNAL pMod, void *pvBits, RTUINTPTR NewBaseAddress, RTUINTPTR OldBaseAddress, PFNRTLDRIMPORT pfnGetImport, void *pvUser) { PKLDRMOD pModkLdr = ((PRTLDRMODKLDR)pMod)->pMod; RTLDRMODKLDRARGS Args; Args.pvUser = pvUser; Args.u.pfnGetImport = pfnGetImport; Args.pMod = (PRTLDRMODKLDR)pMod; Args.pvBits = pvBits; Args.rc = VINF_SUCCESS; int rc = kLdrModRelocateBits(pModkLdr, pvBits, NewBaseAddress, OldBaseAddress, rtkldrGetImportWrapper, &Args); if (Args.rc != VINF_SUCCESS) rc = Args.rc; else rc = rtkldrConvertError(rc); return rc; }
/** @copydoc RTLDROPS::pfnEnumSymbols */ static DECLCALLBACK(int) rtkldr_EnumSymbols(PRTLDRMODINTERNAL pMod, unsigned fFlags, const void *pvBits, RTUINTPTR BaseAddress, PFNRTLDRENUMSYMS pfnCallback, void *pvUser) { PKLDRMOD pModkLdr = ((PRTLDRMODKLDR)pMod)->pMod; RTLDRMODKLDRARGS Args; Args.pvUser = pvUser; Args.u.pfnEnumSyms = pfnCallback; Args.pMod = (PRTLDRMODKLDR)pMod; Args.pvBits = pvBits; Args.rc = VINF_SUCCESS; int rc = kLdrModEnumSymbols(pModkLdr, pvBits, BaseAddress, fFlags & RTLDR_ENUM_SYMBOL_FLAGS_ALL ? KLDRMOD_ENUM_SYMS_FLAGS_ALL : 0, rtkldrEnumSymbolsWrapper, &Args); if (Args.rc != VINF_SUCCESS) rc = Args.rc; else rc = rtkldrConvertError(rc); return rc; }
/** * 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); }
/** @copydoc RTLDROPS::pfnDone */ static DECLCALLBACK(int) rtkldr_Done(PRTLDRMODINTERNAL pMod) { PKLDRMOD pModkLdr = ((PRTLDRMODKLDR)pMod)->pMod; int rc = kLdrModMostlyDone(pModkLdr); return rtkldrConvertError(rc); }
/** * 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); }