/* $Id: kLdrMod.c 2848 2006-11-02 00:08:16Z bird $ */ /** @file * * kLdr - The Dynamic Loader, The module interpreter. * * Copyright (c) 2006 knut st. osmundsen * * * This file is part of kLdr. * * kLdr is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * kLdr is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with kLdr; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /******************************************************************************* * Header Files * *******************************************************************************/ #include #include "kLdrHlp.h" #include "kLdrInternal.h" #include "kLdrModMZ.h" #if 1 /* testing headers */ # include "kLdrModPE.h" # include "kLdrModLX.h" # include "kLdrModELF32.h" # include "kLdrModELF64.h" #endif /** * Open a executable image by file name. * * @returns 0 on success and *ppMod pointing to a module instance. * On failure, a non-zero OS specific error code is returned. * @param pszFilename The filename to open. * @param ppMod Where to store the module handle. */ int kLdrModOpen(const char *pszFilename, PPKLDRMOD ppMod) { /* * Open the file using a bit provider. */ PKLDRRDR pRdr; int rc = kLdrRdrOpen(&pRdr, pszFilename); if (!rc) { rc = kLdrModOpenFromRdr(pRdr, ppMod); if (!rc) return 0; kLdrRdrClose(pRdr); } return rc; } /** * Open a executable image from a file provider instance. * * @returns 0 on success and *ppMod pointing to a module instance. * On failure, a non-zero OS specific error code is returned. * @param pRdr The file provider instance to use. * On success, the ownership of the instance is taken by the * module and the caller must not ever touch it again. * (The instance is not closed on failure, the call has to do that.) * @param ppMod Where to store the module handle. */ int kLdrModOpenFromRdr(PKLDRRDR pRdr, PPKLDRMOD ppMod) { union { uint32_t u32; uint16_t u16; uint16_t au16[2]; uint8_t au8[4]; } u; off_t offHdr = 0; int rc; /* * Try figure out what kind of image this is. * Always read the 'new header' if we encounter MZ. */ rc = kLdrRdrRead(pRdr, &u, sizeof(u), 0); if (rc) return rc; if ( u.u16 == IMAGE_DOS_SIGNATURE && kLdrRdrSize(pRdr) > sizeof(IMAGE_DOS_HEADER)) { rc = kLdrRdrRead(pRdr, &u, sizeof(u.u32), KLDR_OFFSETOF(IMAGE_DOS_HEADER, e_lfanew)); if (rc) return rc; if ((off_t)u.u32 < kLdrRdrSize(pRdr)) { offHdr = u.u32; rc = kLdrRdrRead(pRdr, &u, sizeof(u.u32), offHdr); if (rc) return rc; } else u.u16 = IMAGE_DOS_SIGNATURE; } /* * Use the magic to select the appropriate image interpreter. */ if (u.u16 == IMAGE_DOS_SIGNATURE) return KLDR_ERR_MZ_NOT_SUPPORTED; else if (u.u16 == IMAGE_NE_SIGNATURE) return KLDR_ERR_NE_NOT_SUPPORTED; else if (u.u16 == IMAGE_LX_SIGNATURE) return KLDR_ERR_LX_NOT_SUPPORTED; else if (u.u16 == IMAGE_LE_SIGNATURE) return KLDR_ERR_LE_NOT_SUPPORTED; else if (u.u32 == IMAGE_NT_SIGNATURE) return KLDR_ERR_PE_NOT_SUPPORTED; else if (u.u32 == IMAGE_ELF_SIGNATURE) return KLDR_ERR_ELF_NOT_SUPPORTED; return KLDR_ERR_UNKNOWN_FORMAT; } /** * Open a executable image using the native loader (if any). * * @returns 0 on success and *ppMod pointing to a module instance. * On failure, a non-zero OS specific error code is returned. * @param pszFilename The filename to open. * @param ppMod Where to store the module handle. */ int kLdrModOpenNative(const char *pszFilename, PPKLDRMOD ppMod) { #ifdef __OS2__ //DosLoadModule() #elif defined(__WIN__) #else # error "Port me" #endif return -1; } /** * Closes an open module. * * The caller is responsible for calling kLdrModUnmap() and kLdrFreeTLS() * before closing the module. * * @returns 0 on success, * @param pMod The module. */ int kLdrModClose(PKLDRMOD pMod) { //pMod-> return -1; } /** * Queries a symbol by name or ordinal number. * * @returns 0 and *puValue and *pfKind on success. * KLDR_ERR_SYMBOL_NOT_FOUND is returned if the symbol wasn't found. * Other failures could stem from bad executable format failures, * read failure in case pvBits isn't specified and no mapping should be used. * @param pMod The module. * @param pvBits Optional pointer to bits returned by kLdrModGetBits() currently located at BaseAddress. * This can be used by some module interpreters to reduce memory consumption. * @param BaseAddress The module base address to use when calculating the symbol value. * There are two special values that can be used: * KLDRMOD_BASEADDRESS_LINK and KLDRMOD_BASEADDRESS_MAP. * @param uSymbol The symbol ordinal. (optional) * @param pszSymbol The symbol name. (optional) * @param puValue Where to store the symbol value. (optional) * @param pfKind Where to store the symbol kind. (optional) */ int kLdrModQuerySymbol(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, uint32_t uSymbol, const char *pszSymbol, PKLDRADDR puValue, uint32_t *pfKind) { return -1; } /** * Enumerate the symbols in the module. * * @returns 0 on success and non-zero a status code on failure. * @param pMod The module which symbols should be enumerated. * @param fFlags The enumeration flags. A combination of the KLDRMOD_ENUM_SYMS_FLAGS_* \#defines. * @param pvBits Optional pointer to bits returned by kLdrModGetBits() currently located at BaseAddress. * This can be used by some module interpreters to reduce memory consumption. * @param BaseAddress The module base address to use when calculating the symbol values. * There are two special values that could be can: * KLDRMOD_BASEADDRESS_LINK and KLDRMOD_BASEADDRESS_MAP. * @param pfnCallback The enumeration callback function. * @param pvUser The user argument to the callback function. */ int kLdrModEnumSymbols(PKLDRMOD pMod, uint32_t fFlags, const void *pvBits, KLDRADDR BaseAddress, PFNKLDRMODENUMSYMS pfnCallback, void *pvUser) { return -1; } /** * Get the name of an import module by ordinal number. * * @returns 0 and name in pszName on success. * On buffer overruns KLDR_ERR_BUFFER_OVERFLOW will be returned. * On other failures and appropriate error code is returned. * @param pMod The module. * @param pvBits Optional pointer to bits returned by kLdrModGetBits(). * This can be used by some module interpreters to reduce memory consumption. * @param iImport The import module ordinal number. * @param pszName Where to store the name. * @param cchName The size of the name buffer. */ int kLdrModGetImport(PKLDRMOD pMod, void *pvBits, uint32_t iImport, const char *pszName, size_t cchName) { return -1; } /** * Get the number of import modules. * * @returns The number of import modules. -1 if something really bad happens. * @param pMod The module. * @param pvBits Optional pointer to bits returned by kLdrModGetBits(). * This can be used by some module interpreters to reduce memory consumption. */ int32_t kLdrModNumberOfImports(PKLDRMOD pMod, void *pvBits) { return -1; } /** * Checks if this module can be executed by the specified arch+cpu. * * @returns 0 if it can, KLDR_ERR_ARCH_CPU_NOT_COMPATIBLE if it can't. * Other failures may occur and cause other return values. * @param pMod The module. * @param pvBits Optional pointer to bits returned by kLdrModGetBits(). * This can be used by some module interpreters to reduce memory consumption. */ int kLdrModCanExecuteOn(PKLDRMOD pMod, void *pvBits, KLDRARCH enmArch, KLDRCPU enmCpu) { //return KLDR_ERR_ARCH_CPU_NOT_COMPATIBLE; return 0; } /** * Gets the image stack info. * * @returns 0 on success, non-zero on failure. * @param pMod * @param pvBits Optional pointer to bits returned by kLdrModGetBits() currently located at BaseAddress. * This can be used by some module interpreters to reduce memory consumption. * @param BaseAddress The module base address to use when calculating the stack address. * There are two special values that can be used: * KLDRMOD_BASEADDRESS_LINK and KLDRMOD_BASEADDRESS_MAP. * @param pStackInfo The stack information. */ int kLdrModGetStackInfo(PKLDRMOD pMod, void *pvBits, KLDRADDR BaseAddress, PKLDRSTACKINFO pStackInfo) { return -1; } /** * Queries the main entrypoint of the module. * * Only executable are supposed to have an main entrypoint, though some object and DLL * formats will also allow this. * * @returns 0 and *pMainEPAddress on success. Non-zero status code on failure. * @param pMod The module. * @param pvBits Optional pointer to bits returned by kLdrModGetBits() currently located at BaseAddress. * This can be used by some module interpreters to reduce memory consumption. * @param BaseAddress The module base address to use when calculating the entrypoint address. * There are two special values that can be used: * KLDRMOD_BASEADDRESS_LINK and KLDRMOD_BASEADDRESS_MAP. * @param pMainEPAddress Where to store the entry point address. */ int kLdrModQueryMainEntrypoint(PKLDRMOD pMod, void *pvBits, KLDRADDR BaseAddress, PKLDRADDR pMainEPAddress) { return 1; } /** * Get the size of the mapped module. * * @returns The size of the mapped module (in bytes). * @param pMod The module. */ size_t kLdrModSize(PKLDRMOD pMod) { return 0; } /** * Maps the module into the memory of the caller. * * On success the actual addresses for the segments can be found in MapAddress * member of each segment in the segment array. * * @returns 0 on success, non-zero OS or kLdr status code on failure. * @param pMod The module to be mapped. * @remark kLdr only supports one mapping at a time of a module. */ int kLdrModMap(PKLDRMOD pMod) { return -1; } /** * Unmaps a module previously mapped by kLdrModMap(). * * @returns 0 on success, non-zero OS or kLdr status code on failure. * @param pMod The module to unmap. */ int kLdrModUnmap(PKLDRMOD pMod) { return -1; } /** * Allocates Thread Local Storage for module mapped by kLdrModMap(). * * Calling kLdrModAllocTLS() more than once without calling kLdrModFreeTLS() * between each invocation is not supported. * * @returns 0 on success, non-zero OS or kLdr status code on failure. * @param pMod The module. */ int kLdrModAllocTLS(PKLDRMOD pMod) { return 0; } /** * Frees Thread Local Storage previously allocated by kLdrModAllocTLS(). * * The caller is responsible for only calling kLdrModFreeTLS() once * after calling kLdrModAllocTLS(). * * @returns 0 on success, non-zero OS or kLdr status code on failure. * @param pMod The module. */ void kLdrModFreeTLS(PKLDRMOD pMod) { } /** * Reloads all dirty pages in a module previously mapped by kLdrModMap(). * * The module interpreter may omit code pages if it can safely apply code * fixups again in a subsequent kLdrModFixupMapping() call. * * The caller is responsible for freeing TLS before calling this function. * * @returns 0 on success, non-zero OS or kLdr status code on failure. * @param pMod The module. */ int kLdrModReload(PKLDRMOD pMod) { return -1; } /** * Fixup the mapping made by kLdrModMap(). * * The caller is only responsible for not calling this function more than * once without doing kLDrModReload() inbetween. * * @returns 0 on success, non-zero OS or kLdr status code on failure. * @param pMod The module. * @param pfnGetImport The callback for resolving external (imported) symbols. * @param pvUser The callback user argument. */ int kLdrModFixupMapping(PKLDRMOD pMod, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser) { return -1; } /** * Call the module initializiation function of a mapped module (if any). * * @returns 0 on success or no init function, non-zero on init function failure or invalid pMod. * @param pMod The module. */ int kLdrModCallInit(PKLDRMOD pMod) { return -1; } /** * Call the module termination function of a mapped module (if any). * * @returns 0 on success or no term function, non-zero on invalid pMod. * @param pMod The module. * * @remark Termination function failure will be ignored by the module interpreter. */ int kLdrModCallTerm(PKLDRMOD pMod) { return 0; } /** * Call the thread attach or detach function of a mapped module (if any). * * @returns 0 on success or no attach/detach function, non-zero on attach failure or invalid pMod. * @param pMod The module. * * @remark Detach function failure will be ignored by the module interpreter. */ int kLdrModCallThread(PKLDRMOD pMod, unsigned fAttachingOrDetaching) { return 0; } /** * Gets the module bits. * * The module interpreter will fill a mapping allocated by the caller with the * module bits reallocated to the specified address. * * @returns 0 on succes, non-zero OS or kLdr status code on failure. * @param pMod The module. * @param pvBits Where to put the bits. * @param BaseAddress The base address that should correspond to the first byte in pvBits * upon return. * @param pfnGetImport The callback ufor resolving external (imported) symbols. * @param pvUser The callback user argument. */ int kLdrModGetBits(PKLDRMOD pMod, void *pvBits, KLDRADDR BaseAddress, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser) { return -1; } /** * Relocates the module bits previously obtained by kLdrModGetBits(). * * @returns 0 on succes, non-zero OS or kLdr status code on failure. * @param pMod The module. * @param pvBits Where to put the bits. * @param NewBaseAddress The new base address. * @param OldBaseAddress The old base address (i.e. the one specified to kLdrModGetBits() or as * NewBaseAddressto the previous kLdrModRelocateBits() call). * @param pfnGetImport The callback ufor resolving external (imported) symbols. * @param pvUser The callback user argument. */ int kLdrModRelocateBits(PKLDRMOD pMod, void *pvBits, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser) { return -1; }