diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-11 08:21:29 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-11 08:21:29 +0000 |
commit | 29cd838eab01ed7110f3ccb2e8c6a35c8a31dbcc (patch) | |
tree | 63ef546b10a81d461e5cf5ed9e98a68cd7dee1aa /src/lib/kStuff/kLdr/kLdrModNative.c | |
parent | Initial commit. (diff) | |
download | kbuild-29cd838eab01ed7110f3ccb2e8c6a35c8a31dbcc.tar.xz kbuild-29cd838eab01ed7110f3ccb2e8c6a35c8a31dbcc.zip |
Adding upstream version 1:0.1.9998svn3589+dfsg.upstream/1%0.1.9998svn3589+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | src/lib/kStuff/kLdr/kLdrModNative.c | 1206 |
1 files changed, 1206 insertions, 0 deletions
diff --git a/src/lib/kStuff/kLdr/kLdrModNative.c b/src/lib/kStuff/kLdr/kLdrModNative.c new file mode 100644 index 0000000..01ff4a6 --- /dev/null +++ b/src/lib/kStuff/kLdr/kLdrModNative.c @@ -0,0 +1,1206 @@ +/* $Id: kLdrModNative.c 117 2020-03-15 15:23:36Z bird $ */ +/** @file + * kLdr - The Module Interpreter for the Native Loaders. + */ + +/* + * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/******************************************************************************* +* Header Files * +*******************************************************************************/ +#include <k/kLdr.h> +#include "kLdrInternal.h" + +#if K_OS == K_OS_OS2 +# define INCL_BASE +# include <os2.h> + +# ifndef LIBPATHSTRICT +# define LIBPATHSTRICT 3 +# endif + extern APIRET DosQueryHeaderInfo(HMODULE hmod, ULONG ulIndex, PVOID pvBuffer, ULONG cbBuffer, ULONG ulSubFunction); +# define QHINF_EXEINFO 1 /* NE exeinfo. */ +# define QHINF_READRSRCTBL 2 /* Reads from the resource table. */ +# define QHINF_READFILE 3 /* Reads from the executable file. */ +# define QHINF_LIBPATHLENGTH 4 /* Gets the libpath length. */ +# define QHINF_LIBPATH 5 /* Gets the entire libpath. */ +# define QHINF_FIXENTRY 6 /* NE only */ +# define QHINF_STE 7 /* NE only */ +# define QHINF_MAPSEL 8 /* NE only */ + +#elif K_OS == K_OS_WINDOWS +# undef IMAGE_NT_SIGNATURE +# undef IMAGE_DOS_SIGNATURE +# include <windows.h> +# ifndef IMAGE_SCN_TYPE_NOLOAD +# define IMAGE_SCN_TYPE_NOLOAD 0x00000002 +# endif + +/*#elif defined(__NT__) +#include <winnt.h> */ + +#elif K_OS == K_OS_DARWIN +# include <dlfcn.h> +# include <errno.h> + +#else +# error "port me" +#endif + + + +/******************************************************************************* +* Defined Constants And Macros * +*******************************************************************************/ +/** @def KLDRMODNATIVE_STRICT + * Define KLDRMODNATIVE_STRICT to enabled strict checks in KLDRMODNATIVE. */ +#define KLDRMODNATIVE_STRICT 1 + +/** @def KLDRMODNATIVE_ASSERT + * Assert that an expression is true when KLDR_STRICT is defined. + */ +#ifdef KLDRMODNATIVE_STRICT +# define KLDRMODNATIVE_ASSERT(expr) kHlpAssert(expr) +#else +# define KLDRMODNATIVE_ASSERT(expr) do {} while (0) +#endif + +#if K_OS == K_OS_WINDOWS +/** @def KLDRMODNATIVE_RVA2TYPE + * Converts a RVA to a pointer of the specified type. + * @param pvBits The bits (image base). + * @param uRVA The image relative virtual address. + * @param type The type to cast to. + */ +# define KLDRMODNATIVE_RVA2TYPE(pvBits, uRVA, type) \ + ( (type) ((KUPTR)(pvBits) + (uRVA)) ) + +#endif /* PE OSes */ + + + +/******************************************************************************* +* Structures and Typedefs * +*******************************************************************************/ +/** + * Instance data for the module interpreter for the Native Loaders. + */ +typedef struct KLDRMODNATIVE +{ + /** Pointer to the module. (Follows the section table.) */ + PKLDRMOD pMod; + /** Reserved flags. */ + KU32 f32Reserved; + /** The number of imported modules. + * If ~(KU32)0 this hasn't been determined yet. */ + KU32 cImportModules; +#if K_OS == K_OS_OS2 + /** The module handle. */ + HMODULE hmod; + +#elif K_OS == K_OS_WINDOWS + /** The module handle. */ + HANDLE hmod; + /** Pointer to the NT headers. */ + const IMAGE_NT_HEADERS *pNtHdrs; + /** Pointer to the section header array. */ + const IMAGE_SECTION_HEADER *paShdrs; + +#elif K_OS == K_OS_DARWIN + /** The dlopen() handle.*/ + void *pvMod; + +#else +# error "Port me" +#endif +} KLDRMODNATIVE, *PKLDRMODNATIVE; + + +/******************************************************************************* +* Internal Functions * +*******************************************************************************/ +static KI32 kldrModNativeNumberOfImports(PKLDRMOD pMod, const void *pvBits); + +/********************************************************************************************************************************* +* Global Variables * +*********************************************************************************************************************************/ +extern KLDRMODOPS g_kLdrModNativeOps; + + + +/** + * Use native loader to load the file opened by pRdr. + * + * @returns 0 on success and *ppMod pointing to a module instance. + * On failure, a non-zero OS specific error code is returned. + * @param pOps Pointer to the registered method table. + * @param pRdr The file provider instance to use. + * @param offNewHdr The offset of the new header in MZ files. -1 if not found. + * @param ppMod Where to store the module instance pointer. + */ +static int kldrModNativeCreate(PCKLDRMODOPS pOps, PKRDR pRdr, KU32 fFlags, KCPUARCH enmCpuArch, + KLDRFOFF offNewHdr, PPKLDRMOD ppMod) +{ + int rc = kLdrModOpenNative(kRdrName(pRdr), fFlags, ppMod); + if (rc) + return rc; + rc = kRdrClose(pRdr); + KLDRMODNATIVE_ASSERT(!rc); + return 0; +} + + +/** + * Loads a module using the native module loader. + * + * @returns 0 on success. + * @returns non-zero native or kLdr status code on failure. + * @param pszFilename The filename or module name to be loaded. + * @param fFlags Module open flags, KLDRMOD_OPEN_FLAGS_XXX. + * @param ppMod Where to store the module interpreter instance pointer. + */ +int kLdrModOpenNative(const char *pszFilename, KU32 fFlags, PPKLDRMOD ppMod) +{ + int rc; + + /* + * Load the image. + */ +#if K_OS == K_OS_OS2 + HMODULE hmod; + kHlpAssertReturn(!(fFlags & ~KLDRMOD_OPEN_FLAGS_VALID_MASK), KERR_INVALID_PARAMETER); + + rc = DosLoadModule(NULL, 0, (PCSZ)pszFilename, &hmod); + if (rc) + return rc; + rc = kLdrModOpenNativeByHandle((KUPTR)hmod, fFlags, ppMod); + if (rc) + DosFreeModule(hmod); + +#elif K_OS == K_OS_WINDOWS + HMODULE hmod; + kHlpAssertReturn(!(fFlags & ~KLDRMOD_OPEN_FLAGS_VALID_MASK), KERR_INVALID_PARAMETER); + + hmod = LoadLibrary(pszFilename); + if (!hmod) + return GetLastError(); + rc = kLdrModOpenNativeByHandle((KUPTR)hmod, fFlags, ppMod); + if (rc) + FreeLibrary(hmod); + +#elif K_OS == K_OS_DARWIN + void *pvMod; + kHlpAssertReturn(!(fFlags & ~KLDRMOD_OPEN_FLAGS_VALID_MASK), KERR_INVALID_PARAMETER); + + pvMod = dlopen(pszFilename, 0); + if (!pvMod) + return ENOENT; + rc = kLdrModOpenNativeByHandle((KUPTR)pvMod, fFlags, ppMod); + if (rc) + dlclose(pvMod); + +#else +# error "Port me" +#endif + return rc; +} + + +/** + * Creates a native module interpret for an already module already + * loaded by the native loader. + * + * @returns 0 on success. + * @returns non-zero native or kLdr status code on failure. + * @param pszFilename The filename or module name to be loaded. + * @param fFlags Module open flags, KLDRMOD_OPEN_FLAGS_XXX. + * @param ppMod Where to store the module interpreter instance pointer. + * @remark This will not make the native loader increment the load count. + */ +int kLdrModOpenNativeByHandle(KUPTR uHandle, KU32 fFlags, PPKLDRMOD ppMod) +{ + KSIZE cb; + KU32 cchFilename; + KU32 cSegments; + PKLDRMOD pMod; + PKLDRMODNATIVE pModNative; + + /* + * Delcare variables, parse the module header or whatever and determin the + * size of the module instance. + */ +#if K_OS == K_OS_OS2 + char szFilename[CCHMAXPATH]; + int rc; + + /* get the filename. */ + rc = DosQueryModuleName((HMODULE)uHandle, sizeof(szFilename), szFilename); + if (rc) + { + KLDRMODNATIVE_ASSERT(rc); + szFilename[0] = '\0'; + } + + /* get the segment count. */ + /** @todo DosQueryHeaderInfo should be able to get us what we want on OS/2. */ + cSegments = 1; + +#elif K_OS == K_OS_WINDOWS + DWORD dw; + char szFilename[MAX_PATH]; + const IMAGE_NT_HEADERS *pNtHdrs; + const IMAGE_SECTION_HEADER *paShdrs; + const IMAGE_DOS_HEADER *pDosHdr = (const IMAGE_DOS_HEADER *)uHandle; + unsigned i; + + /* get the filename. */ + dw = GetModuleFileName((HANDLE)uHandle, szFilename, sizeof(szFilename)); + if (dw <= 0) + { + KLDRMODNATIVE_ASSERT(dw <= 0); + szFilename[0] = '\0'; + } + + /* get the segment count. */ + if (pDosHdr->e_magic == IMAGE_DOS_SIGNATURE) + pNtHdrs = (const IMAGE_NT_HEADERS *)((KUPTR)pDosHdr + pDosHdr->e_lfanew); + else + pNtHdrs = (const IMAGE_NT_HEADERS *)pDosHdr; + if (pNtHdrs->Signature != IMAGE_NT_SIGNATURE) + { + KLDRMODNATIVE_ASSERT(!"bad signature"); + return KLDR_ERR_UNKNOWN_FORMAT; + } + if (pNtHdrs->FileHeader.SizeOfOptionalHeader != sizeof(IMAGE_OPTIONAL_HEADER)) + { + KLDRMODNATIVE_ASSERT(!"bad optional header size"); + return KLDR_ERR_UNKNOWN_FORMAT; + } + cSegments = pNtHdrs->FileHeader.NumberOfSections + 1; + paShdrs = (const IMAGE_SECTION_HEADER *)(pNtHdrs + 1); + +#elif K_OS == K_OS_DARWIN + char szFilename[1] = ""; + cSegments = 0; /** @todo Figure out the Mac OS X dynamic loader. */ + +#else +# error "Port me" +#endif + + kHlpAssertReturn(!(fFlags & ~KLDRMOD_OPEN_FLAGS_VALID_MASK), KERR_INVALID_PARAMETER); + + /* + * Calc the instance size, allocate and initialize it. + */ + cchFilename = (KU32)kHlpStrLen(szFilename); + cb = K_ALIGN_Z(sizeof(KLDRMODNATIVE), 16) + + K_OFFSETOF(KLDRMOD, aSegments[cSegments]) + + cchFilename + 1; + pModNative = (PKLDRMODNATIVE)kHlpAlloc(cb); + if (!pModNative) + return KERR_NO_MEMORY; + + /* KLDRMOD */ + pMod = (PKLDRMOD)((KU8 *)pModNative + K_ALIGN_Z(sizeof(KLDRMODNATIVE), 16)); + pMod->pvData = pModNative; + pMod->pRdr = NULL; + pMod->pOps = NULL; /* set upon success. */ + pMod->cSegments = cSegments; + pMod->cchFilename = cchFilename; + pMod->pszFilename = (char *)&pMod->aSegments[pMod->cSegments]; + kHlpMemCopy((char *)pMod->pszFilename, szFilename, cchFilename + 1); + pMod->pszName = kHlpGetFilename(pMod->pszFilename); /** @todo get soname */ + pMod->cchName = cchFilename - (KU32)(pMod->pszName - pMod->pszFilename); + pMod->fFlags = fFlags; +#if defined(__i386__) || defined(__X86__) || defined(_M_IX86) + pMod->enmCpu = KCPU_I386; + pMod->enmArch = KCPUARCH_X86_32; + pMod->enmEndian = KLDRENDIAN_LITTLE; +#elif defined(__X86_64__) || defined(__x86_64__) || defined(__AMD64__) || defined(_M_IX64) + pMod->enmCpu = KCPU_K8; + pMod->enmArch = KCPUARCH_AMD64; + pMod->enmEndian = KLDRENDIAN_LITTLE; +#else +# error "Port me" +#endif + pMod->enmFmt = KLDRFMT_NATIVE; + pMod->enmType = KLDRTYPE_SHARED_LIBRARY_RELOCATABLE; + pMod->u32Magic = 0; /* set upon success. */ + + /* KLDRMODNATIVE */ + pModNative->pMod = pMod; + pModNative->f32Reserved = 0; + pModNative->cImportModules = ~(KU32)0; + + /* + * Set native instance data. + */ +#if K_OS == K_OS_OS2 + pModNative->hmod = (HMODULE)uHandle; + + /* just fake a segment for now. */ + pMod->aSegments[0].pvUser = NULL; + pMod->aSegments[0].pchName = "fake"; + pMod->aSegments[0].cchName = sizeof("fake") - 1; + pMod->aSegments[0].enmProt = KPROT_NOACCESS; + pMod->aSegments[0].cb = 0; + pMod->aSegments[0].Alignment = 0; + pMod->aSegments[0].LinkAddress = NIL_KLDRADDR; + pMod->aSegments[0].offFile = -1; + pMod->aSegments[0].cbFile = 0; + pMod->aSegments[0].RVA = NIL_KLDRADDR; + pMod->aSegments[0].cbMapped = 0; + pMod->aSegments[0].MapAddress = 0; + +#elif K_OS == K_OS_WINDOWS + pModNative->hmod = (HMODULE)uHandle; + pModNative->pNtHdrs = pNtHdrs; + pModNative->paShdrs = paShdrs; + + if (pNtHdrs->FileHeader.Characteristics & IMAGE_FILE_DLL) + pMod->enmType = !(pNtHdrs->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED) + ? KLDRTYPE_SHARED_LIBRARY_RELOCATABLE + : KLDRTYPE_SHARED_LIBRARY_FIXED; + else + pMod->enmType = !(pNtHdrs->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED) + ? KLDRTYPE_EXECUTABLE_RELOCATABLE + : KLDRTYPE_EXECUTABLE_FIXED; + + /* 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 = pNtHdrs->OptionalHeader.SizeOfHeaders; + pMod->aSegments[0].Alignment = pNtHdrs->OptionalHeader.SectionAlignment; + pMod->aSegments[0].LinkAddress = pNtHdrs->OptionalHeader.ImageBase; + pMod->aSegments[0].offFile = 0; + pMod->aSegments[0].cbFile = pNtHdrs->OptionalHeader.SizeOfHeaders; + pMod->aSegments[0].RVA = 0; + if (pMod->cSegments > 1) + pMod->aSegments[0].cbMapped = paShdrs[0].VirtualAddress; + else + pMod->aSegments[0].cbMapped = pNtHdrs->OptionalHeader.SizeOfHeaders; + pMod->aSegments[0].MapAddress = uHandle; + + /* The section headers. */ + for (i = 0; i < pNtHdrs->FileHeader.NumberOfSections; i++) + { + const char *pch; + KU32 cchSegName; + + /* unused */ + pMod->aSegments[i + 1].pvUser = NULL; + + /* name */ + pMod->aSegments[i + 1].pchName = pch = &paShdrs[i].Name[0]; + cchSegName = IMAGE_SIZEOF_SHORT_NAME; + while ( cchSegName > 0 + && (pch[cchSegName - 1] == ' ' || pch[cchSegName - 1] == '\0')) + cchSegName--; + pMod->aSegments[i + 1].cchName = cchSegName; + + /* size and addresses */ + if (!(paShdrs[i].Characteristics & IMAGE_SCN_TYPE_NOLOAD)) + { + pMod->aSegments[i + 1].cb = paShdrs[i].Misc.VirtualSize; + pMod->aSegments[i + 1].RVA = paShdrs[i].VirtualAddress; + pMod->aSegments[i + 1].LinkAddress = paShdrs[i].VirtualAddress + pNtHdrs->OptionalHeader.ImageBase; + pMod->aSegments[i + 1].MapAddress = paShdrs[i].VirtualAddress + uHandle; + pMod->aSegments[i + 1].cbMapped = paShdrs[i].Misc.VirtualSize; + if (i + 2 < pMod->cSegments) + pMod->aSegments[i + 1].cbMapped = paShdrs[i + 1].VirtualAddress + - paShdrs[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; + pMod->aSegments[i + 1].MapAddress = 0; + } + + /* file location */ + pMod->aSegments[i + 1].offFile = paShdrs[i].PointerToRawData; + pMod->aSegments[i + 1].cbFile = paShdrs[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 = (KLDRFOFF)pMod->aSegments[i + 1].cbMapped; + + /* protection */ + switch ( paShdrs[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 (paShdrs[i].Characteristics & IMAGE_SCN_ALIGN_MASK) + { + case 0: /* hope this is right... */ + pMod->aSegments[i + 1].Alignment = pNtHdrs->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; + } + } + +#elif K_OS == K_OS_DARWIN + /** @todo Figure out the Mac OS X dynamic loader. */ + +#else +# error "Port me" +#endif + + /* + * We're done. + */ + pMod->u32Magic = KLDRMOD_MAGIC; + pMod->pOps = &g_kLdrModNativeOps; + *ppMod = pMod; + return 0; +} + + +/** @copydoc KLDRMODOPS::pfnDestroy */ +static int kldrModNativeDestroy(PKLDRMOD pMod) +{ + PKLDRMODNATIVE pModNative = (PKLDRMODNATIVE)pMod->pvData; + int rc; + +#if K_OS == K_OS_OS2 + rc = DosFreeModule(pModNative->hmod); + +#elif K_OS == K_OS_WINDOWS + if (FreeLibrary(pModNative->hmod)) + rc = 0; + else + rc = GetLastError(); + +#elif K_OS == K_OS_DARWIN + dlclose(pModNative->pvMod); + +#else +# error "Port me" +#endif + + pMod->u32Magic = 0; + pMod->pOps = NULL; + kHlpFree(pModNative); + return rc; +} + + +/** @copydoc kLdrModQuerySymbol */ +static int kldrModNativeQuerySymbol(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, KU32 iSymbol, + const char *pchSymbol, KSIZE cchSymbol, const char *pszVersion, + PFNKLDRMODGETIMPORT pfnGetForwarder, void *pvUser, PKLDRADDR puValue, KU32 *pfKind) +{ + PKLDRMODNATIVE pModNative = (PKLDRMODNATIVE)pMod->pvData; + const char *pszSymbol = pchSymbol; +#if K_OS == K_OS_OS2 + APIRET rc; + PFN pfn; +#elif K_OS == K_OS_WINDOWS + FARPROC pfn; +#elif K_OS == K_OS_DARWIN + void *pfn; +#else +# error "Port me" +#endif + + /* make stack copy of the symbol if it isn't zero terminated. */ + if (pszSymbol && pszSymbol[cchSymbol]) + { + char *pszCopy = kHlpAllocA(cchSymbol + 1); + kHlpMemCopy(pszCopy, pchSymbol, cchSymbol); + pszCopy[cchSymbol] = '\0'; + pszSymbol = pszCopy; + } + +#if K_OS == K_OS_OS2 + if (!pchSymbol && iSymbol >= 0x10000) + return KLDR_ERR_SYMBOL_NOT_FOUND; + + if (puValue) + { + rc = DosQueryProcAddr(pModNative->hmod, + pszSymbol ? 0 : iSymbol, + (PCSZ)pszSymbol, + &pfn); + if (rc) + return rc == ERROR_PROC_NOT_FOUND ? KLDR_ERR_SYMBOL_NOT_FOUND : rc; + *puValue = (KUPTR)pfn; + } + if (pfKind) + { + ULONG ulProcType; + rc = DosQueryProcType(pModNative->hmod, + pszSymbol ? 0 : iSymbol, + (PCSZ)pszSymbol, + &ulProcType); + if (rc) + { + if (puValue) + *puValue = 0; + return rc == ERROR_PROC_NOT_FOUND ? KLDR_ERR_SYMBOL_NOT_FOUND : rc; + } + *pfKind = (ulProcType & PT_32BIT ? KLDRSYMKIND_32BIT : KLDRSYMKIND_16BIT) + | KLDRSYMKIND_NO_TYPE; + } + +#elif K_OS == K_OS_WINDOWS + if (!pszSymbol && iSymbol >= 0x10000) + return KLDR_ERR_SYMBOL_NOT_FOUND; + + pfn = GetProcAddress(pModNative->hmod, pszSymbol ? pszSymbol : (const char *)(KUPTR)iSymbol); + if (puValue) + *puValue = (KUPTR)pfn; + if (pfKind) + *pfKind = (pModNative->pNtHdrs->FileHeader.SizeOfOptionalHeader == sizeof(IMAGE_OPTIONAL_HEADER32) + ? KLDRSYMKIND_32BIT : KLDRSYMKIND_16BIT) + | KLDRSYMKIND_NO_TYPE; + +#elif K_OS == K_OS_DARWIN + if (!pszSymbol && iSymbol != NIL_KLDRMOD_SYM_ORDINAL) + return KLDR_ERR_SYMBOL_NOT_FOUND; + + pfn = dlsym(pModNative->pvMod, pszSymbol); + if (!pfn) + return KLDR_ERR_SYMBOL_NOT_FOUND; + if (puValue) + *puValue = (KUPTR)pfn; + if (pfKind) + *pfKind = (sizeof(KUPTR) == 4 ? KLDRSYMKIND_32BIT : KLDRSYMKIND_64BIT) + | KLDRSYMKIND_NO_TYPE; + +#else +# error "Port me" +#endif + + return 0; +} + + +/** @copydoc kLdrModEnumSymbols */ +static int kldrModNativeEnumSymbols(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, + KU32 fFlags, PFNKLDRMODENUMSYMS pfnCallback, void *pvUser) +{ + PKLDRMODNATIVE pModNative = (PKLDRMODNATIVE)pMod->pvData; +#if K_OS == K_OS_OS2 + + /** @todo implement export enumeration on OS/2. */ + (void)pModNative; + return ERROR_NOT_SUPPORTED; + +#elif K_OS == K_OS_WINDOWS || defined(__NT__) + const KU32 *paFunctions; + const IMAGE_EXPORT_DIRECTORY *pExpDir; + const KU32 *paRVANames; + const KU16 *paOrdinals; + KU32 iFunction; + KU32 cFunctions; + KU32 cNames; + int rc; + + /* + * Make sure we've got mapped bits and resolve any base address aliases. + */ + if ( pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size + < sizeof(IMAGE_EXPORT_DIRECTORY)) + return 0; /* no exports to enumerate, return success. */ + + pExpDir = KLDRMODNATIVE_RVA2TYPE(pModNative->hmod, + pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress, + PIMAGE_EXPORT_DIRECTORY); + + /* + * Enumerate the ordinal exports. + */ + paRVANames = KLDRMODNATIVE_RVA2TYPE(pModNative->hmod, pExpDir->AddressOfNames, const KU32 *); + paOrdinals = KLDRMODNATIVE_RVA2TYPE(pModNative->hmod, pExpDir->AddressOfNameOrdinals, const KU16 *); + paFunctions = KLDRMODNATIVE_RVA2TYPE(pModNative->hmod, pExpDir->AddressOfFunctions, const KU32 *); + cFunctions = pExpDir->NumberOfFunctions; + cNames = pExpDir->NumberOfNames; + for (iFunction = 0; iFunction < cFunctions; iFunction++) + { + unsigned fFoundName; + KU32 iName; + const KU32 uRVA = paFunctions[iFunction]; + const KLDRADDR uValue = BaseAddress + uRVA; + KU32 fKind = (pModNative->pNtHdrs->FileHeader.SizeOfOptionalHeader == sizeof(IMAGE_OPTIONAL_HEADER32) + ? KLDRSYMKIND_32BIT : KLDRSYMKIND_64BIT) + | KLDRSYMKIND_NO_TYPE; + if ( uRVA - pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress + < pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size) + fKind |= KLDRSYMKIND_FORWARDER; + + /* + * Any symbol names? + */ + fFoundName = 0; + for (iName = 0; iName < cNames; iName++) + { + const char *pszName; + if (paOrdinals[iName] != iFunction) + continue; + fFoundName = 1; + + pszName = KLDRMODNATIVE_RVA2TYPE(pModNative->hmod, paRVANames[iName], const char *); + rc = pfnCallback(pMod, iFunction + pExpDir->Base, pszName, strlen(pszName), NULL, + uValue, fKind, pvUser); + if (rc) + return rc; + } + + /* + * If no names, call once with the ordinal only. + */ + if (!fFoundName) + { + rc = pfnCallback(pMod, iFunction + pExpDir->Base, NULL, 0, NULL, uValue, fKind, pvUser); + if (rc) + return rc; + } + } + return 0; + +#elif K_OS == K_OS_DARWIN + /** @todo implement enumeration on darwin. */ + (void)pModNative; + return KLDR_ERR_TODO; + +#else +# error "Port me" +#endif + +} + + +/** @copydoc kLdrModGetImport */ +static int kldrModNativeGetImport(PKLDRMOD pMod, const void *pvBits, KU32 iImport, char *pszName, KSIZE cchName) +{ + PKLDRMODNATIVE pModNative = (PKLDRMODNATIVE)pMod->pvData; +#if K_OS == K_OS_OS2 + + /** @todo implement import enumeration on OS/2. */ + (void)pModNative; + return ERROR_NOT_SUPPORTED; + +#elif K_OS == K_OS_WINDOWS || defined(__NT__) + const IMAGE_IMPORT_DESCRIPTOR *pImpDesc; + const char *pszImportName; + KSIZE cchImportName; + int rc; + + /* + * Simple bounds check. + */ + if (iImport >= (KU32)kldrModNativeNumberOfImports(pMod, pvBits)) + return KLDR_ERR_IMPORT_ORDINAL_OUT_OF_BOUNDS; + + /* + * Get the name. + */ + pImpDesc = KLDRMODNATIVE_RVA2TYPE(pModNative->hmod, + pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress + + sizeof(IMAGE_IMPORT_DESCRIPTOR) * iImport, + const IMAGE_IMPORT_DESCRIPTOR *); + pszImportName = KLDRMODNATIVE_RVA2TYPE(pModNative->hmod, pImpDesc->Name, const char *); + cchImportName = kHlpStrLen(pszImportName); + if (cchImportName < cchName) + { + kHlpMemCopy(pszName, pszImportName, cchImportName + 1); + rc = 0; + } + else + { + kHlpMemCopy(pszName, pszImportName, cchName); + if (cchName) + pszName[cchName - 1] = '\0'; + rc = KERR_BUFFER_OVERFLOW; + } + + return rc; + +#elif K_OS == K_OS_DARWIN + /** @todo Implement import enumeration on darwin. */ + (void)pModNative; + return KLDR_ERR_TODO; + +#else +# error "Port me" +#endif +} + + +/** @copydoc kLdrModNumberOfImports */ +static KI32 kldrModNativeNumberOfImports(PKLDRMOD pMod, const void *pvBits) +{ + PKLDRMODNATIVE pModNative = (PKLDRMODNATIVE)pMod->pvData; +#if K_OS == K_OS_OS2 + + /** @todo implement import counting on OS/2. */ + (void)pModNative; + return -1; + +#elif K_OS == K_OS_WINDOWS || defined(__NT__) + if (pModNative->cImportModules == ~(KU32)0) + { + /* + * We'll have to walk the import descriptors to figure out their number. + */ + pModNative->cImportModules = 0; + if ( pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size + && pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress) + { + const IMAGE_IMPORT_DESCRIPTOR *pImpDesc; + + pImpDesc = KLDRMODNATIVE_RVA2TYPE(pModNative->hmod, + pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress, + const IMAGE_IMPORT_DESCRIPTOR *); + while (pImpDesc->Name && pImpDesc->FirstThunk) + { + pModNative->cImportModules++; + pImpDesc++; + } + } + } + return pModNative->cImportModules; + +#elif K_OS == K_OS_DARWIN + /** @todo Implement import counting on Darwin. */ + (void)pModNative; + return -1; + +#else +# error "Port me" +#endif +} + + +/** @copydoc kLdrModGetStackInfo */ +static int kldrModNativeGetStackInfo(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, PKLDRSTACKINFO pStackInfo) +{ + PKLDRMODNATIVE pModNative = (PKLDRMODNATIVE)pMod->pvData; +#if K_OS == K_OS_OS2 + + /** @todo implement stack info on OS/2. */ + (void)pModNative; + return ERROR_NOT_SUPPORTED; + +#elif K_OS == K_OS_WINDOWS || defined(__NT__) + pStackInfo->Address = NIL_KLDRADDR; + pStackInfo->LinkAddress = NIL_KLDRADDR; + pStackInfo->cbStack = pStackInfo->cbStackThread = pModNative->pNtHdrs->OptionalHeader.SizeOfStackReserve; + + return 0; + +#elif K_OS == K_OS_DARWIN + /** @todo Implement stack info on Darwin. */ + (void)pModNative; + return KLDR_ERR_TODO; + +#else +# error "Port me" +#endif +} + + +/** @copydoc kLdrModQueryMainEntrypoint */ +static int kldrModNativeQueryMainEntrypoint(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, PKLDRADDR pMainEPAddress) +{ + PKLDRMODNATIVE pModNative = (PKLDRMODNATIVE)pMod->pvData; +#if K_OS == K_OS_OS2 + + /** @todo implement me on OS/2. */ + (void)pModNative; + return ERROR_NOT_SUPPORTED; + +#elif K_OS == K_OS_WINDOWS || defined(__NT__) + /* + * Convert the address from the header. + */ + *pMainEPAddress = pModNative->pNtHdrs->OptionalHeader.AddressOfEntryPoint + ? BaseAddress + pModNative->pNtHdrs->OptionalHeader.AddressOfEntryPoint + : NIL_KLDRADDR; + return 0; + +#elif K_OS == K_OS_DARWIN + /** @todo Implement me on Darwin. */ + (void)pModNative; + return KLDR_ERR_TODO; + +#else +# error "Port me" +#endif +} + + +/** @copydoc kLdrModEnumDbgInfo */ +static int kldrModNativeEnumDbgInfo(PKLDRMOD pMod, const void *pvBits, PFNKLDRENUMDBG pfnCallback, void *pvUser) +{ + PKLDRMODNATIVE pModNative = (PKLDRMODNATIVE)pMod->pvData; +#if K_OS == K_OS_OS2 + + /** @todo implement me on OS/2. */ + (void)pModNative; + return ERROR_NOT_SUPPORTED; + +#elif K_OS == K_OS_WINDOWS || defined(__NT__) + const IMAGE_DEBUG_DIRECTORY *pDbgDir; + KU32 iDbgInfo; + KU32 cb; + int rc; + + /* + * Check that there is a debug directory first. + */ + cb = pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size; + if ( cb < sizeof(IMAGE_DEBUG_DIRECTORY) /* screw borland linkers */ + || !pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress) + return 0; + + /* + * Enumerate the debug directory. + */ + pDbgDir = KLDRMODNATIVE_RVA2TYPE(pModNative->hmod, + pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress, + const IMAGE_DEBUG_DIRECTORY *); + for (iDbgInfo = 0;; iDbgInfo++, pDbgDir++, cb -= sizeof(IMAGE_DEBUG_DIRECTORY)) + { + KLDRDBGINFOTYPE enmDbgInfoType; + + /* convert the type. */ + switch (pDbgDir->Type) + { + case IMAGE_DEBUG_TYPE_UNKNOWN: + case IMAGE_DEBUG_TYPE_FPO: + case IMAGE_DEBUG_TYPE_COFF: /*stabs dialect??*/ + case IMAGE_DEBUG_TYPE_MISC: + case IMAGE_DEBUG_TYPE_EXCEPTION: + case IMAGE_DEBUG_TYPE_FIXUP: + case IMAGE_DEBUG_TYPE_BORLAND: + default: + enmDbgInfoType = KLDRDBGINFOTYPE_UNKNOWN; + break; + case IMAGE_DEBUG_TYPE_CODEVIEW: + enmDbgInfoType = KLDRDBGINFOTYPE_CODEVIEW; + break; + } + + rc = pfnCallback(pMod, iDbgInfo, + enmDbgInfoType, pDbgDir->MajorVersion, pDbgDir->MinorVersion, NULL /*pszPartNm*/, + pDbgDir->PointerToRawData ? pDbgDir->PointerToRawData : -1, + pDbgDir->AddressOfRawData ? pDbgDir->AddressOfRawData : NIL_KLDRADDR, + pDbgDir->SizeOfData, + NULL /*pszExtFile*/, pvUser); + if (rc) + break; + + /* next */ + if (cb <= sizeof(IMAGE_DEBUG_DIRECTORY)) + break; + } + + return rc; + +#elif K_OS == K_OS_DARWIN + /** @todo Implement me on Darwin. */ + (void)pModNative; + return KLDR_ERR_TODO; + +#else +# error "Port me" +#endif +} + + +/** @copydoc kLdrModHasDbgInfo */ +static int kldrModNativeHasDbgInfo(PKLDRMOD pMod, const void *pvBits) +{ + PKLDRMODNATIVE pModNative = (PKLDRMODNATIVE)pMod->pvData; +#if K_OS == K_OS_OS2 + + /** @todo implement me on OS/2. */ + (void)pModNative; + return KLDR_ERR_NO_DEBUG_INFO; + +#elif K_OS == K_OS_WINDOWS || defined(__NT__) + /* + * Base this entirely on the presence of a debug directory. + */ + if ( pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size + < sizeof(IMAGE_DEBUG_DIRECTORY) /* screw borland linkers */ + || !pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress) + return KLDR_ERR_NO_DEBUG_INFO; + return 0; + +#elif K_OS == K_OS_DARWIN + /** @todo Implement me on Darwin. */ + (void)pModNative; + return KLDR_ERR_NO_DEBUG_INFO; + +#else +# error "Port me" +#endif +} + + +/** @copydoc kLdrModMap */ +static int kldrModNativeMap(PKLDRMOD pMod) +{ + return 0; +} + + +/** @copydoc kLdrModUnmap */ +static int kldrModNativeUnmap(PKLDRMOD pMod) +{ + return 0; +} + + +/** @copydoc kLdrModAllocTLS */ +static int kldrModNativeAllocTLS(PKLDRMOD pMod, void *pvMapping) +{ + return 0; +} + + +/** @copydoc kLdrModFreeTLS */ +static void kldrModNativeFreeTLS(PKLDRMOD pMod, void *pvMapping) +{ +} + + +/** @copydoc kLdrModReload */ +static int kldrModNativeReload(PKLDRMOD pMod) +{ + return 0; +} + + +/** @copydoc kLdrModFixupMapping */ +static int kldrModNativeFixupMapping(PKLDRMOD pMod, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser) +{ + return 0; +} + + +#if K_OS == K_OS_OS2 || K_OS == K_OS_WINDOWS || defined(__NT__) +/** Common worker on platforms where there is one entrypoint which does both. */ +static int kLdrModNativeCallInitTerm(PKLDRMODNATIVE pModNative, KUPTR uHandle, KBOOL fInit) +{ +# if K_OS == K_OS_WINDOWS || defined(__NT__) + /* No TLS init/term for now. */ + KU32 const uRvaEntrypoint = pModNative->pNtHdrs->OptionalHeader.AddressOfEntryPoint; + if ( uRvaEntrypoint != 0 + && uRvaEntrypoint < pModNative->pNtHdrs->OptionalHeader.SizeOfCode + && (pModNative->pNtHdrs->FileHeader.Characteristics & IMAGE_FILE_DLL)) + { + KI32 rc = kldrModPEDoCall(uRvaEntrypoint + (KUPTR)pModNative->hmod, uHandle, + fInit ? DLL_PROCESS_ATTACH : DLL_PROCESS_DETACH, NULL /*pvReserved*/); + if (rc) + return 0; + return fInit ? KLDR_ERR_MODULE_INIT_FAILED : KLDR_ERR_THREAD_ATTACH_FAILED; + } +# elif K_OS == K_OS_OS2 + //KI32 kldrModLXDoCall(KUPTR uEntrypoint, KUPTR uHandle, KU32 uOp, void *pvReserved) +# endif + return 0; +} +#endif + +/** @copydoc kLdrModCallInit */ +static int kldrModNativeCallInit(PKLDRMOD pMod, void *pvMapping, KUPTR uHandle) +{ +#if K_OS == K_OS_OS2 || K_OS == K_OS_WINDOWS || defined(__NT__) + if (pMod->fFlags & KLDRMOD_OPEN_FLAGS_NATIVE_ALLOW_INIT_TERM) + return kLdrModNativeCallInitTerm((PKLDRMODNATIVE)pMod->pvData, uHandle, K_TRUE /*fInit*/); +#endif + return 0; +} + + +/** @copydoc kLdrModCallTerm */ +static int kldrModNativeCallTerm(PKLDRMOD pMod, void *pvMapping, KUPTR uHandle) +{ +#if K_OS == K_OS_OS2 || K_OS == K_OS_WINDOWS || defined(__NT__) + if (pMod->fFlags & KLDRMOD_OPEN_FLAGS_NATIVE_ALLOW_INIT_TERM) + return kLdrModNativeCallInitTerm((PKLDRMODNATIVE)pMod->pvData, uHandle, K_FALSE /*fInit*/); +#endif + return 0; +} + + +/** @copydoc kLdrModCallThread */ +static int kldrModNativeCallThread(PKLDRMOD pMod, void *pvMapping, KUPTR uHandle, unsigned fAttachingOrDetaching) +{ + return 0; +} + + +/** @copydoc kLdrModSize */ +static KLDRADDR kldrModNativeSize(PKLDRMOD pMod) +{ +#if K_OS == K_OS_OS2 + return 0; /* don't bother */ + +#elif K_OS == K_OS_WINDOWS || defined(__NT__) + /* just because we can. */ + PKLDRMODNATIVE pModNative = (PKLDRMODNATIVE)pMod->pvData; + return pModNative->pNtHdrs->OptionalHeader.SizeOfImage; + +#elif K_OS == K_OS_DARWIN + /** @todo Implement me on Darwin. */ + return 0; + +#else +# error "Port me" +#endif +} + + +/** @copydoc kLdrModGetBits */ +static int kldrModNativeGetBits(PKLDRMOD pMod, void *pvBits, KLDRADDR BaseAddress, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser) +{ +#if K_OS == K_OS_OS2 + return ERROR_NOT_SUPPORTED; /* don't bother */ + +#elif K_OS == K_OS_WINDOWS || defined(__NT__) + return ERROR_NOT_SUPPORTED; /* don't bother even if we could implement this. */ + +#elif K_OS == K_OS_DARWIN + return KLDR_ERR_TODO; /* don't bother. */ + +#else +# error "Port me" +#endif +} + + +/** @copydoc kLdrModRelocateBits */ +static int kldrModNativeRelocateBits(PKLDRMOD pMod, void *pvBits, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress, + PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser) +{ +#if K_OS == K_OS_OS2 + return ERROR_NOT_SUPPORTED; /* don't bother */ + +#elif K_OS == K_OS_WINDOWS || defined(__NT__) + return ERROR_NOT_SUPPORTED; /* don't bother even if we could implement this. */ + +#elif K_OS == K_OS_DARWIN + return KLDR_ERR_TODO; /* don't bother. */ + +#else +# error "Port me" +#endif +} + + +/** + * The native module interpreter method table. + */ +KLDRMODOPS g_kLdrModNativeOps = +{ + "Native", + NULL, + kldrModNativeCreate, + kldrModNativeDestroy, + kldrModNativeQuerySymbol, + kldrModNativeEnumSymbols, + kldrModNativeGetImport, + kldrModNativeNumberOfImports, + NULL /* can execute one is optional */, + kldrModNativeGetStackInfo, + kldrModNativeQueryMainEntrypoint, + NULL /* pfnQueryImageUuid */, + NULL /* fixme */, + NULL /* fixme */, + kldrModNativeEnumDbgInfo, + kldrModNativeHasDbgInfo, + kldrModNativeMap, + kldrModNativeUnmap, + kldrModNativeAllocTLS, + kldrModNativeFreeTLS, + kldrModNativeReload, + kldrModNativeFixupMapping, + kldrModNativeCallInit, + kldrModNativeCallTerm, + kldrModNativeCallThread, + kldrModNativeSize, + kldrModNativeGetBits, + kldrModNativeRelocateBits, + NULL /* fixme */, + 42 /* the end */ +}; + |