/* $Id: kLdr.h 2829 2006-10-23 17:04:04Z bird $ */ /** @file * * kLdr - The Dynamic Loader. * * 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 * */ #ifndef __kLdr_h__ #define __kLdr_h__ #ifdef __cplusplus extern "C" { #endif /* kLdr depend on size_t, [u]intNN_t, [u]intptr_t and some related constants. */ #include #include #ifdef _MSC_VER typedef signed char int8_t; typedef unsigned char uint8_t; typedef signed short int16_t; typedef unsigned short uint16_t; typedef signed int int32_t; typedef unsigned int uint32_t; typedef signed __int64 int64_t; typedef unsigned __int64 uint64_t; typedef uint64_t uintmax_t; #else # include #endif /** @defgroup grp_kLdrRdr kLdrRdr - The file provider * @{ */ typedef enum KLDRPROT { /** The usual invalid 0. */ KLDRPROT_INVALID = 0, /** No access (page not present). */ KLDRPROT_NOACCESS, /** Read only. */ KLDRPROT_READONLY, /** Read & write. */ KLDRPROT_READWRITE, /** Read & copy on write. */ KLDRPROT_WRITECOPY, /** Execute only. */ KLDRPROT_EXECUTE, /** Execute & read. */ KLDRPROT_EXECUTE_READONLY, /** Execute, read & write. */ KLDRPROT_EXECUTE_READWRITE, /** Execute, read & copy on write. */ KLDRPROT_EXECUTE_WRITECOPY, /** The usual end value. (exclusive) */ KLDRPROT_END, /** Blow the type up to 32-bits. */ KLDRPROT_32BIT_HACK = 0x7fffffff } KLDRPROT; /** Pointer to a file provider instance core. */ typedef struct KLDRRDR *PKLDRRDR; /** Pointer to a file provider instance core pointer. */ typedef struct KLDRRDR **PPKLDRRDR; /** * File provider instance operations. */ typedef struct KLDRRDROPS { /** The name of this file provider. */ const char *pszName; /** Pointer to the next file provider. */ const struct KLDRRDROPS *pNext; /** Try create a new file provider instance. * * @returns 0 on success, OS specific error code on failure. * @param ppRdr Where to store the file provider instance. * @param pszFilename The filename to open. */ int (* pfnCreate)( PPKLDRRDR ppRdr, const char *pszFilename); /** Destroy the file provider instance. * * @returns 0 on success, OS specific error code on failure. * On failure, the file provider instance will be in an indeterminate state - don't touch it! * @param pRdr The file provider instance. */ int (* pfnDestroy)( PKLDRRDR pRdr); /** Read bits from the file. * * @returns 0 on success, OS specific error code on failure. * @param pRdr The file provider instance. * @param pvBuf Where to put the bits. * @param cb The number of bytes to read. * @param off Where to start reading. */ int (* pfnRead)( PKLDRRDR pRdr, void *pvBuf, size_t cb, off_t off); /** Map all the file bits into memory (read only). * * @returns 0 on success, OS specific error code on failure. * @param pRdr The file provider instance. * @param ppvBits Where to store the address of the mapping. * The size can be obtained using pfnSize. */ int (* pfnAllMap)( PKLDRRDR pRdr, const void **ppvBits); /** Unmap a file bits mapping obtained by KLDRRDROPS::pfnAllMap. * * @returns 0 on success, OS specific error code on failure. * @param pRdr The file provider instance. * @param pvBits The mapping address. */ int (* pfnAllUnmap)(PKLDRRDR pRdr, const void *pvBits); /** Get the file size. * * @returns The file size. Returns -1 on failure. * @param pRdr The file provider instance. */ off_t (* pfnSize)( PKLDRRDR pRdr); /** Get the file pointer offset. * * @returns The file pointer offset. Returns -1 on failure. * @param pRdr The file provider instance. */ off_t (* pfnTell)( PKLDRRDR pRdr); /** Get the file name. * * @returns The file size. Returns -1 on failure. * @param pRdr The file provider instance. */ const char * (* pfnName)(PKLDRRDR pRdr); /** * Prepares a memory region to map file sections into. * * @returns 0 on success, OS specific error code on failure. * @param pRdr The file provider instance. * @param ppv If fFixed is set, *ppv contains the memory location which * the region should be based at. If fFixed is clear the OS * is free to choose the location. * On successful return *ppv contains address of the prepared * memory region. * @param cb The size of the memory region to prepare. * @param fFixed When set *ppv will contain the desired region address. * */ int (* pfnPrepare)(PKLDRRDR pRdr, void **ppv, size_t cb, unsigned fFixed); /** * Maps a section of the file into the memory region reserved by pfnPrepare. * * @returns 0 on success, OS specific error code on failure. * @param pRdr The file provider instance. * @param pv The address in the prepared region. * @param cb The size of the memory mapping. * @param enmProt The desired memory protection. * @param offFile The start of the raw file bytes. * @param cbFile The number of raw file bytes. This must be less or equal to cb. */ int (* pfnMap)(PKLDRRDR pRdr, void *pv, size_t cb, KLDRPROT enmProt, off_t offFile, size_t cbFile); /** * Changes the page protection of a section mapped using pfnMap. * * This is typically used for applying fixups and similar. * * @returns 0 on success, OS specific error code on failure. * @param pRdr The file provider instance. * @param pv The address passed to pfnMap. * @param cb The size passed to pfnMap. * @param enmProt The desired memory protection. */ int (* pfnProtect)(PKLDRRDR pRdr, void *pv, size_t cb, KLDRPROT enmProt); /** * Unmaps a section of the file previously mapped using pfnMap. * * @returns 0 on success, OS specific error code on failure. * @param pRdr The file provider instance. * @param pv The address passed to pfnMap. * @param cb The size passed to pfnMap. */ int (* pfnUnmap)(PKLDRRDR pRdr, void *pv, size_t cb); /** * Releases the memory region prepared by pfnPrepare(). * * Before calling this function, all sections mapped by pfnMap must first be unmapped by calling pfnUnmap. * * @returns 0 on success, OS specific error code on failure. * @param pRdr The file provider instance. * @param pv The address of the prepared region. * @param cb The size of the prepared region. */ int (* pfnUnprepare)(PKLDRRDR pRdr, void *pv, size_t cb); /** * We're done reading from the file but would like to keep file mappings. * * If the OS support closing the file handle while the file is mapped, * the reader should do so. * * @param pRdr The file provider instance. */ void (* pfnDone)(PKLDRRDR pRdr); /** The usual non-zero dummy that makes sure we've initialized all members. */ uint32_t u32Dummy; } KLDRRDROPS; /** Pointer to file provider operations. */ typedef KLDRRDROPS *PKLDRRDROPS; /** Pointer to const file provider operations. */ typedef const KLDRRDROPS *PCKLDRRDROPS; /** * File provider instance core. */ typedef struct KLDRRDR { /** Pointer to the file provider operations. */ PCKLDRRDROPS pOps; } KLDRRDR; void kLdrRdrAddProvider(PKLDRRDROPS pAdd); int kLdrRdrOpen( PPKLDRRDR ppRdr, const char *pszFilename); int kLdrRdrClose( PKLDRRDR pRdr); int kLdrRdrRead( PKLDRRDR pRdr, void *pvBuf, size_t cb, off_t off); int kLdrRdrAllMap( PKLDRRDR pRdr, const void **ppvBits); int kLdrRdrAllUnmap(PKLDRRDR pRdr, const void *pvBits); off_t kLdrRdrSize( PKLDRRDR pRdr); off_t kLdrRdrTell( PKLDRRDR pRdr); const char *kLdrRdrName(PKLDRRDR pRdr); /** @} */ /** @defgroup grp_kLdrMod kLdrMod - The executable image intepreter * @{ */ /** * Loader segment. */ typedef struct KLDRSEG { /** The segment load address. */ void *pv; /** The size of the segment. */ size_t cb; /** The segment is readable. */ uint32_t fRead : 1; /** The segment is writable. */ uint32_t fWrite : 1; /** The segment is executable. */ uint32_t fExecute : 1; /** Reserved for future use. */ uint32_t fReserved : 29; /** Reserved for future use. */ uint32_t u32Reserved; } KLDRSEG, *PKLDRSEG; /** * Loader module type. */ typedef enum KLDRTYPE { /** The usual invalid 0 type. */ KLDRTYPE_INVALID = 0, /** The native OS loader. */ KLDRTYPE_NATIVE, /** The LX loader. */ KLDRTYPE_LX, /** The end type (not included). */ KLDRTYPE_END, /** Hack to blow the type up to 32-bit. */ KLDRTYPE_32BIT_HACK = 0x7fffffff } KLDRTYPE; /** * Loader module. */ typedef struct KLDRMOD { /** Magic number. */ uint32_t u32Magic; /** The type of module this is. */ KLDRTYPE enmType; /** The module data. */ void *pvData; /** The filename length (bytes). */ uint32_t cchFilename; /** The filename. */ const char *pszFilename; /** The module name. */ const char *pszName; /** The module name length (bytes). */ uint32_t cchName; /** The number of segments in the module. */ uint32_t cSegments; /** Segments. (variable size, can be zero) */ KLDRSEG aSegments[1]; } KLDRMOD, *PKLDRMOD, **PPKLDRMOD; int kLdrModOpen(const char *pszFilename, PPKLDRMOD ppMod); int kLdrModClose(PKLDRMOD pMod); int kLdrModGetSymbol(PKLDRMOD pMod, const void *pvBits, uintmax_t BaseAddress, const char *pszSymbol, uintmax_t *pValue, unsigned *pfType); int kLdrModGetSymbol(PKLDRMOD pMod, const void *pvBits, uintmax_t BaseAddress, const char *pszSymbol, uintmax_t *pValue, unsigned *pfType); size_t kLdrModSize(PKLDRMOD pMod); typedef int FNKLDRMODGETIMPORT(PKLDRMOD pMod, const char *pszModule, const char *pszSymbol, unsigned uSymbol, uintmax_t *pValue, void *pvUser); typedef FNKLDRMODGETIMPORT *PFNKLDRMODGETIMPORT; int kLdrModGetBits(PKLDRMOD pMod, void *pvBits, uintmax_t BaseAddress, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser); int kLdrModRelocate(PKLDRMOD pMod, void *pvBits, uintmax_t NewBaseAddress, uintmax_t OldBaseAddress, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser); typedef int FNKLDRMODENUMSYMS(PKLDRMOD pMod, const char *pszSymbol, unsigned uSymbol, uintmax_t Value, void *pvUser); typedef FNKLDRMODENUMSYMS *PFNKLDRMODENUMSYMS; int kLdrModEnumSymbols(PKLDRMOD pMod, unsigned fFlags, const void *pvBits, uintmax_t BaseAddress, PFNKLDRMODENUMSYMS pfnCallback, void *pvUser); /** @name kLdrModEnumSymbols flags. * @{ */ /** Returns ALL kinds of symbols. The default is to only return public/exported symbols. */ #define KLDRMOD_ENUM_SYMBOL_FLAGS_ALL 0x00000001 /** @} */ /** @} */ /** @defgroup grp_kLdrDy kLdrDy - The dynamic loader * @{ */ /** The h*/ typedef struct KLDRDY *PKLDRDY; /* int kLdrLoadDll(const char *pszFilename, unsigned fFlags, unsigned long *pvmod); */ /** @name Process Bootstrapping * @{ */ /** * Argument package from the stub. */ typedef struct KLDREXEARGS { /** Flags. (Currently unused, MBZ.) */ uint32_t fFlags; /** The executable file that the stub is supposed to load. */ char szExecutable[260]; /** The LD_LIBRARY_PATH prefix for the process.. */ char szLibPath[4096 - 260 - sizeof(uint32_t)]; } KLDREXEARGS, *PKLDREXEARGS; void kLdrLoadExe(PKLDREXEARGS pArgs); /** @} */ /** @} */ /** @defgroup grp_kLdrErr kLdr Status Codes * kLdr uses a mix of native status codes and it's own status codes. * A status code of 0 means success, all other status codes means failure. * @{ */ #ifdef __OS2__ # define KLDR_ERR_BASE 0x7face000 #elif defined(__WIN__) # define KLDR_ERR_BASE 0x7face000 #else # error "port me" #endif /** The image format is unknown. */ #define KLDR_ERR_UNKNOWN_FORMAT (KLDR_ERR_BASE + 0) /** The MZ image format isn't supported by this kLdr build. */ #define KLDR_ERR_MZ_NOT_SUPPORTED (KLDR_ERR_BASE + 1) /** The NE image format isn't supported by this kLdr build. */ #define KLDR_ERR_NE_NOT_SUPPORTED (KLDR_ERR_BASE + 2) /** The LX image format isn't supported by this kLdr build. */ #define KLDR_ERR_LX_NOT_SUPPORTED (KLDR_ERR_BASE + 3) /** The LE image format isn't supported by this kLdr build. */ #define KLDR_ERR_LE_NOT_SUPPORTED (KLDR_ERR_BASE + 4) /** The PE image format isn't supported by this kLdr build. */ #define KLDR_ERR_PE_NOT_SUPPORTED (KLDR_ERR_BASE + 5) /** The ELF image format isn't supported by this kLdr build. */ #define KLDR_ERR_ELF_NOT_SUPPORTED (KLDR_ERR_BASE + 6) /** The mach-o image format isn't supported by this kLdr build. */ #define KLDR_ERR_MACHO_NOT_SUPPORTED (KLDR_ERR_BASE + 7) /** The mach-o image format isn't supported by this kLdr build. */ #define KLDR_ERR_AOUT_NOT_SUPPORTED (KLDR_ERR_BASE + 8) /** The mach-o image format isn't supported by this kLdr build. */ #define KLDR_ERR_BAD_FIXUP (KLDR_ERR_BASE + 32) /** @} */ #ifdef __cplusplus } #endif #endif