1 /* $Id: kLdrModNative.c 82 2016-08-22 21:01:51Z bird $ */
2 /** @file
3  * kLdr - The Module Interpreter for the Native Loaders.
4  */
5 
6 /*
7  * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net>
8  *
9  * Permission is hereby granted, free of charge, to any person
10  * obtaining a copy of this software and associated documentation
11  * files (the "Software"), to deal in the Software without
12  * restriction, including without limitation the rights to use,
13  * copy, modify, merge, publish, distribute, sublicense, and/or sell
14  * copies of the Software, and to permit persons to whom the
15  * Software is furnished to do so, subject to the following
16  * conditions:
17  *
18  * The above copyright notice and this permission notice shall be
19  * included in all copies or substantial portions of the Software.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28  * OTHER DEALINGS IN THE SOFTWARE.
29  */
30 
31 /*******************************************************************************
32 *   Header Files                                                               *
33 *******************************************************************************/
34 #include <k/kLdr.h>
35 #include "kLdrInternal.h"
36 
37 #if K_OS == K_OS_OS2
38 # define INCL_BASE
39 # include <os2.h>
40 
41 # ifndef LIBPATHSTRICT
42 #  define LIBPATHSTRICT 3
43 # endif
44   extern APIRET DosQueryHeaderInfo(HMODULE hmod, ULONG ulIndex, PVOID pvBuffer, ULONG cbBuffer, ULONG ulSubFunction);
45 # define QHINF_EXEINFO       1 /* NE exeinfo. */
46 # define QHINF_READRSRCTBL   2 /* Reads from the resource table. */
47 # define QHINF_READFILE      3 /* Reads from the executable file. */
48 # define QHINF_LIBPATHLENGTH 4 /* Gets the libpath length. */
49 # define QHINF_LIBPATH       5 /* Gets the entire libpath. */
50 # define QHINF_FIXENTRY      6 /* NE only */
51 # define QHINF_STE           7 /* NE only */
52 # define QHINF_MAPSEL        8 /* NE only */
53 
54 #elif K_OS == K_OS_WINDOWS
55 # undef IMAGE_NT_SIGNATURE
56 # undef IMAGE_DOS_SIGNATURE
57 # include <windows.h>
58 # ifndef IMAGE_SCN_TYPE_NOLOAD
59 #  define IMAGE_SCN_TYPE_NOLOAD 0x00000002
60 # endif
61 
62 /*#elif defined(__NT__)
63 #include <winnt.h> */
64 
65 #elif K_OS == K_OS_DARWIN
66 # include <dlfcn.h>
67 # include <errno.h>
68 
69 #else
70 # error "port me"
71 #endif
72 
73 
74 
75 /*******************************************************************************
76 *   Defined Constants And Macros                                               *
77 *******************************************************************************/
78 /** @def KLDRMODNATIVE_STRICT
79  * Define KLDRMODNATIVE_STRICT to enabled strict checks in KLDRMODNATIVE. */
80 #define KLDRMODNATIVE_STRICT 1
81 
82 /** @def KLDRMODNATIVE_ASSERT
83  * Assert that an expression is true when KLDR_STRICT is defined.
84  */
85 #ifdef KLDRMODNATIVE_STRICT
86 # define KLDRMODNATIVE_ASSERT(expr)  kHlpAssert(expr)
87 #else
88 # define KLDRMODNATIVE_ASSERT(expr)  do {} while (0)
89 #endif
90 
91 #if K_OS == K_OS_WINDOWS
92 /** @def KLDRMODNATIVE_RVA2TYPE
93  * Converts a RVA to a pointer of the specified type.
94  * @param   pvBits      The bits (image base).
95  * @param   uRVA        The image relative virtual address.
96  * @param   type        The type to cast to.
97  */
98 # define KLDRMODNATIVE_RVA2TYPE(pvBits, uRVA, type) \
99         ( (type) ((KUPTR)(pvBits) + (uRVA)) )
100 
101 #endif /* PE OSes */
102 
103 
104 
105 /*******************************************************************************
106 *   Structures and Typedefs                                                    *
107 *******************************************************************************/
108 /**
109  * Instance data for the module interpreter for the Native Loaders.
110  */
111 typedef struct KLDRMODNATIVE
112 {
113     /** Pointer to the module. (Follows the section table.) */
114     PKLDRMOD                    pMod;
115     /** Reserved flags. */
116     KU32                        f32Reserved;
117     /** The number of imported modules.
118      * If ~(KU32)0 this hasn't been determined yet. */
119     KU32                        cImportModules;
120 #if K_OS == K_OS_OS2
121     /** The module handle. */
122     HMODULE                     hmod;
123 
124 #elif K_OS == K_OS_WINDOWS
125     /** The module handle. */
126     HANDLE                      hmod;
127     /** Pointer to the NT headers. */
128     const IMAGE_NT_HEADERS     *pNtHdrs;
129     /** Pointer to the section header array. */
130     const IMAGE_SECTION_HEADER *paShdrs;
131 
132 #elif K_OS == K_OS_DARWIN
133     /** The dlopen() handle.*/
134     void                       *pvMod;
135 
136 #else
137 # error "Port me"
138 #endif
139 } KLDRMODNATIVE, *PKLDRMODNATIVE;
140 
141 
142 /*******************************************************************************
143 *   Internal Functions                                                         *
144 *******************************************************************************/
145 static KI32 kldrModNativeNumberOfImports(PKLDRMOD pMod, const void *pvBits);
146 
147 /*********************************************************************************************************************************
148 *   Global Variables                                                                                                             *
149 *********************************************************************************************************************************/
150 extern KLDRMODOPS g_kLdrModNativeOps;
151 
152 
153 
154 /**
155  * Use native loader to load the file opened by pRdr.
156  *
157  * @returns 0 on success and *ppMod pointing to a module instance.
158  *          On failure, a non-zero OS specific error code is returned.
159  * @param   pOps            Pointer to the registered method table.
160  * @param   pRdr            The file provider instance to use.
161  * @param   offNewHdr       The offset of the new header in MZ files. -1 if not found.
162  * @param   ppMod           Where to store the module instance pointer.
163  */
kldrModNativeCreate(PCKLDRMODOPS pOps,PKRDR pRdr,KU32 fFlags,KCPUARCH enmCpuArch,KLDRFOFF offNewHdr,PPKLDRMOD ppMod)164 static int kldrModNativeCreate(PCKLDRMODOPS pOps, PKRDR pRdr, KU32 fFlags, KCPUARCH enmCpuArch,
165                                KLDRFOFF offNewHdr, PPKLDRMOD ppMod)
166 {
167     int rc = kLdrModOpenNative(kRdrName(pRdr), ppMod);
168     if (rc)
169         return rc;
170     rc = kRdrClose(pRdr);
171     KLDRMODNATIVE_ASSERT(!rc);
172     return 0;
173 }
174 
175 
176 /**
177  * Loads a module using the native module loader.
178  *
179  * @returns 0 on success.
180  * @returns non-zero native or kLdr status code on failure.
181  * @param   pszFilename         The filename or module name to be loaded.
182  * @param   ppMod               Where to store the module interpreter instance pointer.
183  */
kLdrModOpenNative(const char * pszFilename,PPKLDRMOD ppMod)184 int kLdrModOpenNative(const char *pszFilename, PPKLDRMOD ppMod)
185 {
186     int rc;
187 
188     /*
189      * Load the image.
190      */
191 #if K_OS == K_OS_OS2
192     HMODULE hmod;
193 
194     rc = DosLoadModule(NULL, 0, (PCSZ)pszFilename, &hmod);
195     if (rc)
196         return rc;
197     rc = kLdrModOpenNativeByHandle((KUPTR)hmod, ppMod);
198     if (rc)
199         DosFreeModule(hmod);
200 
201 #elif K_OS == K_OS_WINDOWS
202     HMODULE hmod;
203 
204     hmod = LoadLibrary(pszFilename);
205     if (!hmod)
206         return GetLastError();
207     rc = kLdrModOpenNativeByHandle((KUPTR)hmod, ppMod);
208     if (rc)
209         FreeLibrary(hmod);
210 
211 #elif K_OS == K_OS_DARWIN
212     void *pvMod;
213 
214     pvMod = dlopen(pszFilename, 0);
215     if (!pvMod)
216         return ENOENT;
217     rc = kLdrModOpenNativeByHandle((KUPTR)pvMod, ppMod);
218     if (rc)
219         dlclose(pvMod);
220 
221 #else
222 # error "Port me"
223 #endif
224     return rc;
225 }
226 
227 
228 /**
229  * Creates a native module interpret for an already module already
230  * loaded by the native loader.
231  *
232  * @returns 0 on success.
233  * @returns non-zero native or kLdr status code on failure.
234  * @param   pszFilename         The filename or module name to be loaded.
235  * @param   ppMod               Where to store the module interpreter instance pointer.
236  * @remark  This will not make the native loader increment the load count.
237  */
kLdrModOpenNativeByHandle(KUPTR uHandle,PPKLDRMOD ppMod)238 int kLdrModOpenNativeByHandle(KUPTR uHandle, PPKLDRMOD ppMod)
239 {
240     KSIZE cb;
241     KU32 cchFilename;
242     KU32 cSegments;
243     PKLDRMOD pMod;
244     PKLDRMODNATIVE pModNative;
245 
246     /*
247      * Delcare variables, parse the module header or whatever and determin the
248      * size of the module instance.
249      */
250 #if K_OS == K_OS_OS2
251     char szFilename[CCHMAXPATH];
252     int rc;
253 
254     /* get the filename. */
255     rc = DosQueryModuleName((HMODULE)uHandle, sizeof(szFilename), szFilename);
256     if (rc)
257     {
258         KLDRMODNATIVE_ASSERT(rc);
259         szFilename[0] = '\0';
260     }
261 
262     /* get the segment count. */
263     /** @todo DosQueryHeaderInfo should be able to get us what we want on OS/2. */
264     cSegments = 1;
265 
266 #elif K_OS == K_OS_WINDOWS
267     DWORD                       dw;
268     char                        szFilename[MAX_PATH];
269     const IMAGE_NT_HEADERS     *pNtHdrs;
270     const IMAGE_SECTION_HEADER *paShdrs;
271     const IMAGE_DOS_HEADER     *pDosHdr = (const IMAGE_DOS_HEADER *)uHandle;
272     unsigned                    i;
273 
274     /* get the filename. */
275     dw = GetModuleFileName((HANDLE)uHandle, szFilename, sizeof(szFilename));
276     if (dw <= 0)
277     {
278         KLDRMODNATIVE_ASSERT(dw <= 0);
279         szFilename[0] = '\0';
280     }
281 
282     /* get the segment count. */
283     if (pDosHdr->e_magic == IMAGE_DOS_SIGNATURE)
284         pNtHdrs = (const IMAGE_NT_HEADERS *)((KUPTR)pDosHdr + pDosHdr->e_lfanew);
285     else
286         pNtHdrs = (const IMAGE_NT_HEADERS *)pDosHdr;
287     if (pNtHdrs->Signature != IMAGE_NT_SIGNATURE)
288     {
289         KLDRMODNATIVE_ASSERT(!"bad signature");
290         return KLDR_ERR_UNKNOWN_FORMAT;
291     }
292     if (pNtHdrs->FileHeader.SizeOfOptionalHeader != sizeof(IMAGE_OPTIONAL_HEADER))
293     {
294         KLDRMODNATIVE_ASSERT(!"bad optional header size");
295         return KLDR_ERR_UNKNOWN_FORMAT;
296     }
297     cSegments = pNtHdrs->FileHeader.NumberOfSections + 1;
298     paShdrs = (const IMAGE_SECTION_HEADER *)(pNtHdrs + 1);
299 
300 #elif K_OS == K_OS_DARWIN
301     char    szFilename[1] = "";
302     cSegments = 0; /** @todo Figure out the Mac OS X dynamic loader. */
303 
304 #else
305 # error "Port me"
306 #endif
307 
308     /*
309      * Calc the instance size, allocate and initialize it.
310      */
311     cchFilename = (KU32)kHlpStrLen(szFilename);
312     cb = K_ALIGN_Z(sizeof(KLDRMODNATIVE), 16)
313        + K_OFFSETOF(KLDRMOD, aSegments[cSegments])
314        + cchFilename + 1;
315     pModNative = (PKLDRMODNATIVE)kHlpAlloc(cb);
316     if (!pModNative)
317         return KERR_NO_MEMORY;
318 
319     /* KLDRMOD */
320     pMod = (PKLDRMOD)((KU8 *)pModNative + K_ALIGN_Z(sizeof(KLDRMODNATIVE), 16));
321     pMod->pvData = pModNative;
322     pMod->pRdr = NULL;
323     pMod->pOps = NULL;      /* set upon success. */
324     pMod->cSegments = cSegments;
325     pMod->cchFilename = cchFilename;
326     pMod->pszFilename = (char *)&pMod->aSegments[pMod->cSegments];
327     kHlpMemCopy((char *)pMod->pszFilename, szFilename, cchFilename + 1);
328     pMod->pszName = kHlpGetFilename(pMod->pszFilename); /** @todo get soname */
329     pMod->cchName = cchFilename - (KU32)(pMod->pszName - pMod->pszFilename);
330     pMod->fFlags = 0;
331 #if defined(__i386__) || defined(__X86__) || defined(_M_IX86)
332     pMod->enmCpu = KCPU_I386;
333     pMod->enmArch = KCPUARCH_X86_32;
334     pMod->enmEndian = KLDRENDIAN_LITTLE;
335 #elif defined(__X86_64__) || defined(__x86_64__) || defined(__AMD64__) || defined(_M_IX64)
336     pMod->enmCpu = KCPU_K8;
337     pMod->enmArch = KCPUARCH_AMD64;
338     pMod->enmEndian = KLDRENDIAN_LITTLE;
339 #else
340 # error "Port me"
341 #endif
342     pMod->enmFmt = KLDRFMT_NATIVE;
343     pMod->enmType = KLDRTYPE_SHARED_LIBRARY_RELOCATABLE;
344     pMod->u32Magic = 0;     /* set upon success. */
345 
346     /* KLDRMODNATIVE */
347     pModNative->pMod = pMod;
348     pModNative->f32Reserved = 0;
349     pModNative->cImportModules = ~(KU32)0;
350 
351     /*
352      * Set native instance data.
353      */
354 #if K_OS == K_OS_OS2
355     pModNative->hmod = (HMODULE)uHandle;
356 
357     /* just fake a segment for now. */
358     pMod->aSegments[0].pvUser = NULL;
359     pMod->aSegments[0].pchName = "fake";
360     pMod->aSegments[0].cchName = sizeof("fake") - 1;
361     pMod->aSegments[0].enmProt = KPROT_NOACCESS;
362     pMod->aSegments[0].cb = 0;
363     pMod->aSegments[0].Alignment = 0;
364     pMod->aSegments[0].LinkAddress = NIL_KLDRADDR;
365     pMod->aSegments[0].offFile = -1;
366     pMod->aSegments[0].cbFile = 0;
367     pMod->aSegments[0].RVA = NIL_KLDRADDR;
368     pMod->aSegments[0].cbMapped = 0;
369     pMod->aSegments[0].MapAddress = 0;
370 
371 #elif K_OS == K_OS_WINDOWS
372     pModNative->hmod = (HMODULE)uHandle;
373     pModNative->pNtHdrs = pNtHdrs;
374     pModNative->paShdrs = paShdrs;
375 
376     if (pNtHdrs->FileHeader.Characteristics & IMAGE_FILE_DLL)
377         pMod->enmType = !(pNtHdrs->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
378             ? KLDRTYPE_SHARED_LIBRARY_RELOCATABLE
379             : KLDRTYPE_SHARED_LIBRARY_FIXED;
380     else
381         pMod->enmType = !(pNtHdrs->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
382             ? KLDRTYPE_EXECUTABLE_RELOCATABLE
383             : KLDRTYPE_EXECUTABLE_FIXED;
384 
385     /* The implied headers section. */
386     pMod->aSegments[0].pvUser = NULL;
387     pMod->aSegments[0].pchName = "TheHeaders";
388     pMod->aSegments[0].cchName = sizeof("TheHeaders") - 1;
389     pMod->aSegments[0].enmProt = KPROT_READONLY;
390     pMod->aSegments[0].cb = pNtHdrs->OptionalHeader.SizeOfHeaders;
391     pMod->aSegments[0].Alignment = pNtHdrs->OptionalHeader.SectionAlignment;
392     pMod->aSegments[0].LinkAddress = pNtHdrs->OptionalHeader.ImageBase;
393     pMod->aSegments[0].offFile = 0;
394     pMod->aSegments[0].cbFile = pNtHdrs->OptionalHeader.SizeOfHeaders;
395     pMod->aSegments[0].RVA = 0;
396     if (pMod->cSegments > 1)
397         pMod->aSegments[0].cbMapped = paShdrs[0].VirtualAddress;
398     else
399         pMod->aSegments[0].cbMapped = pNtHdrs->OptionalHeader.SizeOfHeaders;
400     pMod->aSegments[0].MapAddress = uHandle;
401 
402     /* The section headers. */
403     for (i = 0; i < pNtHdrs->FileHeader.NumberOfSections; i++)
404     {
405         const char *pch;
406         KU32        cchSegName;
407 
408         /* unused */
409         pMod->aSegments[i + 1].pvUser = NULL;
410 
411         /* name */
412         pMod->aSegments[i + 1].pchName = pch = &paShdrs[i].Name[0];
413         cchSegName = IMAGE_SIZEOF_SHORT_NAME;
414         while (    cchSegName > 0
415                && (pch[cchSegName - 1] == ' ' || pch[cchSegName - 1] == '\0'))
416             cchSegName--;
417         pMod->aSegments[i + 1].cchName = cchSegName;
418 
419         /* size and addresses */
420         if (!(paShdrs[i].Characteristics & IMAGE_SCN_TYPE_NOLOAD))
421         {
422             pMod->aSegments[i + 1].cb          = paShdrs[i].Misc.VirtualSize;
423             pMod->aSegments[i + 1].RVA         = paShdrs[i].VirtualAddress;
424             pMod->aSegments[i + 1].LinkAddress = paShdrs[i].VirtualAddress + pNtHdrs->OptionalHeader.ImageBase;
425             pMod->aSegments[i + 1].MapAddress  = paShdrs[i].VirtualAddress + uHandle;
426             pMod->aSegments[i + 1].cbMapped    = paShdrs[i].Misc.VirtualSize;
427             if (i + 2 < pMod->cSegments)
428                 pMod->aSegments[i + 1].cbMapped = paShdrs[i + 1].VirtualAddress
429                                                 - paShdrs[i].VirtualAddress;
430         }
431         else
432         {
433             pMod->aSegments[i + 1].cb          = 0;
434             pMod->aSegments[i + 1].cbMapped    = 0;
435             pMod->aSegments[i + 1].LinkAddress = NIL_KLDRADDR;
436             pMod->aSegments[i + 1].RVA         = 0;
437             pMod->aSegments[i + 1].MapAddress  = 0;
438         }
439 
440         /* file location */
441         pMod->aSegments[i + 1].offFile = paShdrs[i].PointerToRawData;
442         pMod->aSegments[i + 1].cbFile  = paShdrs[i].SizeOfRawData;
443         if (    pMod->aSegments[i + 1].cbMapped > 0 /* if mapped */
444             &&  (KLDRSIZE)pMod->aSegments[i + 1].cbFile > pMod->aSegments[i + 1].cbMapped)
445             pMod->aSegments[i + 1].cbFile = (KLDRFOFF)pMod->aSegments[i + 1].cbMapped;
446 
447         /* protection */
448         switch (  paShdrs[i].Characteristics
449                 & (IMAGE_SCN_MEM_SHARED | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE))
450         {
451             case 0:
452             case IMAGE_SCN_MEM_SHARED:
453                 pMod->aSegments[i + 1].enmProt = KPROT_NOACCESS;
454                 break;
455             case IMAGE_SCN_MEM_READ:
456             case IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_SHARED:
457                 pMod->aSegments[i + 1].enmProt = KPROT_READONLY;
458                 break;
459             case IMAGE_SCN_MEM_WRITE:
460             case IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_READ:
461                 pMod->aSegments[i + 1].enmProt = KPROT_WRITECOPY;
462                 break;
463             case IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_SHARED:
464             case IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_SHARED | IMAGE_SCN_MEM_READ:
465                 pMod->aSegments[i + 1].enmProt = KPROT_READWRITE;
466                 break;
467             case IMAGE_SCN_MEM_EXECUTE:
468             case IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_SHARED:
469                 pMod->aSegments[i + 1].enmProt = KPROT_EXECUTE;
470                 break;
471             case IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ:
472             case IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_SHARED:
473                 pMod->aSegments[i + 1].enmProt = KPROT_EXECUTE_READ;
474                 break;
475             case IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_WRITE:
476             case IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_READ:
477                 pMod->aSegments[i + 1].enmProt = KPROT_EXECUTE_WRITECOPY;
478                 break;
479             case IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_SHARED:
480             case IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_SHARED | IMAGE_SCN_MEM_READ:
481                 pMod->aSegments[i + 1].enmProt = KPROT_EXECUTE_READWRITE;
482                 break;
483         }
484 
485         /* alignment. */
486         switch (paShdrs[i].Characteristics & IMAGE_SCN_ALIGN_MASK)
487         {
488             case 0: /* hope this is right... */
489                 pMod->aSegments[i + 1].Alignment = pNtHdrs->OptionalHeader.SectionAlignment;
490                 break;
491             case IMAGE_SCN_ALIGN_1BYTES:        pMod->aSegments[i + 1].Alignment = 1; break;
492             case IMAGE_SCN_ALIGN_2BYTES:        pMod->aSegments[i + 1].Alignment = 2; break;
493             case IMAGE_SCN_ALIGN_4BYTES:        pMod->aSegments[i + 1].Alignment = 4; break;
494             case IMAGE_SCN_ALIGN_8BYTES:        pMod->aSegments[i + 1].Alignment = 8; break;
495             case IMAGE_SCN_ALIGN_16BYTES:       pMod->aSegments[i + 1].Alignment = 16; break;
496             case IMAGE_SCN_ALIGN_32BYTES:       pMod->aSegments[i + 1].Alignment = 32; break;
497             case IMAGE_SCN_ALIGN_64BYTES:       pMod->aSegments[i + 1].Alignment = 64; break;
498             case IMAGE_SCN_ALIGN_128BYTES:      pMod->aSegments[i + 1].Alignment = 128; break;
499             case IMAGE_SCN_ALIGN_256BYTES:      pMod->aSegments[i + 1].Alignment = 256; break;
500             case IMAGE_SCN_ALIGN_512BYTES:      pMod->aSegments[i + 1].Alignment = 512; break;
501             case IMAGE_SCN_ALIGN_1024BYTES:     pMod->aSegments[i + 1].Alignment = 1024; break;
502             case IMAGE_SCN_ALIGN_2048BYTES:     pMod->aSegments[i + 1].Alignment = 2048; break;
503             case IMAGE_SCN_ALIGN_4096BYTES:     pMod->aSegments[i + 1].Alignment = 4096; break;
504             case IMAGE_SCN_ALIGN_8192BYTES:     pMod->aSegments[i + 1].Alignment = 8192; break;
505             default: kHlpAssert(0);          pMod->aSegments[i + 1].Alignment = 0; break;
506         }
507     }
508 
509 #elif K_OS == K_OS_DARWIN
510     /** @todo Figure out the Mac OS X dynamic loader. */
511 
512 #else
513 # error "Port me"
514 #endif
515 
516     /*
517      * We're done.
518      */
519     pMod->u32Magic = KLDRMOD_MAGIC;
520     pMod->pOps = &g_kLdrModNativeOps;
521     *ppMod = pMod;
522     return 0;
523 }
524 
525 
526 /** @copydoc KLDRMODOPS::pfnDestroy */
kldrModNativeDestroy(PKLDRMOD pMod)527 static int kldrModNativeDestroy(PKLDRMOD pMod)
528 {
529     PKLDRMODNATIVE pModNative = (PKLDRMODNATIVE)pMod->pvData;
530     int rc;
531 
532 #if K_OS == K_OS_OS2
533     rc = DosFreeModule(pModNative->hmod);
534 
535 #elif K_OS == K_OS_WINDOWS
536     if (FreeLibrary(pModNative->hmod))
537         rc = 0;
538     else
539         rc = GetLastError();
540 
541 #elif K_OS == K_OS_DARWIN
542     dlclose(pModNative->pvMod);
543 
544 #else
545 # error "Port me"
546 #endif
547 
548     pMod->u32Magic = 0;
549     pMod->pOps = NULL;
550     kHlpFree(pModNative);
551     return rc;
552 }
553 
554 
555 /** @copydoc kLdrModQuerySymbol */
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)556 static int kldrModNativeQuerySymbol(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, KU32 iSymbol,
557                                     const char *pchSymbol, KSIZE cchSymbol, const char *pszVersion,
558                                     PFNKLDRMODGETIMPORT pfnGetForwarder, void *pvUser, PKLDRADDR puValue, KU32 *pfKind)
559 {
560     PKLDRMODNATIVE pModNative = (PKLDRMODNATIVE)pMod->pvData;
561     const char *pszSymbol = pchSymbol;
562 #if K_OS == K_OS_OS2
563     APIRET rc;
564     PFN pfn;
565 #elif K_OS == K_OS_WINDOWS
566     FARPROC pfn;
567 #elif K_OS == K_OS_DARWIN
568     void *pfn;
569 #else
570 # error "Port me"
571 #endif
572 
573     /* make stack copy of the symbol if it isn't zero terminated. */
574     if (pszSymbol && pszSymbol[cchSymbol])
575     {
576         char *pszCopy = kHlpAllocA(cchSymbol + 1);
577         kHlpMemCopy(pszCopy, pchSymbol, cchSymbol);
578         pszCopy[cchSymbol] = '\0';
579         pszSymbol = pszCopy;
580     }
581 
582 #if K_OS == K_OS_OS2
583     if (!pchSymbol && iSymbol >= 0x10000)
584         return KLDR_ERR_SYMBOL_NOT_FOUND;
585 
586     if (puValue)
587     {
588         rc = DosQueryProcAddr(pModNative->hmod,
589                               pszSymbol ? 0 : iSymbol,
590                               (PCSZ)pszSymbol,
591                               &pfn);
592         if (rc)
593             return rc == ERROR_PROC_NOT_FOUND ? KLDR_ERR_SYMBOL_NOT_FOUND : rc;
594         *puValue = (KUPTR)pfn;
595     }
596     if (pfKind)
597     {
598         ULONG ulProcType;
599         rc = DosQueryProcType(pModNative->hmod,
600                               pszSymbol ? 0 : iSymbol,
601                               (PCSZ)pszSymbol,
602                               &ulProcType);
603         if (rc)
604         {
605             if (puValue)
606                 *puValue = 0;
607             return rc == ERROR_PROC_NOT_FOUND ? KLDR_ERR_SYMBOL_NOT_FOUND : rc;
608         }
609         *pfKind = (ulProcType & PT_32BIT ? KLDRSYMKIND_32BIT : KLDRSYMKIND_16BIT)
610                 | KLDRSYMKIND_NO_TYPE;
611     }
612 
613 #elif K_OS == K_OS_WINDOWS
614     if (!pszSymbol && iSymbol >= 0x10000)
615         return KLDR_ERR_SYMBOL_NOT_FOUND;
616 
617     pfn = GetProcAddress(pModNative->hmod, pszSymbol ? pszSymbol : (const char *)(KUPTR)iSymbol);
618     if (puValue)
619         *puValue = (KUPTR)pfn;
620     if (pfKind)
621         *pfKind = (pModNative->pNtHdrs->FileHeader.SizeOfOptionalHeader == sizeof(IMAGE_OPTIONAL_HEADER32)
622                    ? KLDRSYMKIND_32BIT : KLDRSYMKIND_16BIT)
623                 | KLDRSYMKIND_NO_TYPE;
624 
625 #elif K_OS == K_OS_DARWIN
626     if (!pszSymbol && iSymbol != NIL_KLDRMOD_SYM_ORDINAL)
627         return KLDR_ERR_SYMBOL_NOT_FOUND;
628 
629     pfn = dlsym(pModNative->pvMod, pszSymbol);
630     if (!pfn)
631         return KLDR_ERR_SYMBOL_NOT_FOUND;
632     if (puValue)
633         *puValue = (KUPTR)pfn;
634     if (pfKind)
635         *pfKind = (sizeof(KUPTR) == 4 ? KLDRSYMKIND_32BIT : KLDRSYMKIND_64BIT)
636                 | KLDRSYMKIND_NO_TYPE;
637 
638 #else
639 # error "Port me"
640 #endif
641 
642     return 0;
643 }
644 
645 
646 /** @copydoc kLdrModEnumSymbols */
kldrModNativeEnumSymbols(PKLDRMOD pMod,const void * pvBits,KLDRADDR BaseAddress,KU32 fFlags,PFNKLDRMODENUMSYMS pfnCallback,void * pvUser)647 static int kldrModNativeEnumSymbols(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress,
648                                     KU32 fFlags, PFNKLDRMODENUMSYMS pfnCallback, void *pvUser)
649 {
650     PKLDRMODNATIVE                  pModNative = (PKLDRMODNATIVE)pMod->pvData;
651 #if K_OS == K_OS_OS2
652 
653     /** @todo implement export enumeration on OS/2. */
654     (void)pModNative;
655     return ERROR_NOT_SUPPORTED;
656 
657 #elif K_OS == K_OS_WINDOWS || defined(__NT__)
658     const KU32                     *paFunctions;
659     const IMAGE_EXPORT_DIRECTORY   *pExpDir;
660     const KU32                     *paRVANames;
661     const KU16                     *paOrdinals;
662     KU32                            iFunction;
663     KU32                            cFunctions;
664     KU32                            cNames;
665     int                             rc;
666 
667     /*
668      * Make sure we've got mapped bits and resolve any base address aliases.
669      */
670     if (    pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size
671         <   sizeof(IMAGE_EXPORT_DIRECTORY))
672         return 0; /* no exports to enumerate, return success. */
673 
674     pExpDir = KLDRMODNATIVE_RVA2TYPE(pModNative->hmod,
675                                      pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress,
676                                      PIMAGE_EXPORT_DIRECTORY);
677 
678     /*
679      * Enumerate the ordinal exports.
680      */
681     paRVANames = KLDRMODNATIVE_RVA2TYPE(pModNative->hmod, pExpDir->AddressOfNames, const KU32 *);
682     paOrdinals = KLDRMODNATIVE_RVA2TYPE(pModNative->hmod, pExpDir->AddressOfNameOrdinals, const KU16 *);
683     paFunctions = KLDRMODNATIVE_RVA2TYPE(pModNative->hmod, pExpDir->AddressOfFunctions, const KU32 *);
684     cFunctions = pExpDir->NumberOfFunctions;
685     cNames = pExpDir->NumberOfNames;
686     for (iFunction = 0; iFunction < cFunctions; iFunction++)
687     {
688         unsigned        fFoundName;
689         KU32            iName;
690         const KU32      uRVA = paFunctions[iFunction];
691         const KLDRADDR  uValue = BaseAddress + uRVA;
692         KU32            fKind = (pModNative->pNtHdrs->FileHeader.SizeOfOptionalHeader == sizeof(IMAGE_OPTIONAL_HEADER32)
693                               ? KLDRSYMKIND_32BIT : KLDRSYMKIND_64BIT)
694                               | KLDRSYMKIND_NO_TYPE;
695         if (    uRVA - pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress
696             <   pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size)
697             fKind |= KLDRSYMKIND_FORWARDER;
698 
699         /*
700          * Any symbol names?
701          */
702         fFoundName = 0;
703         for (iName = 0; iName < cNames; iName++)
704         {
705             const char *pszName;
706             if (paOrdinals[iName] != iFunction)
707                 continue;
708             fFoundName = 1;
709 
710             pszName = KLDRMODNATIVE_RVA2TYPE(pModNative->hmod, paRVANames[iName], const char *);
711             rc = pfnCallback(pMod, iFunction + pExpDir->Base, pszName, strlen(pszName), NULL,
712                              uValue, fKind, pvUser);
713             if (rc)
714                 return rc;
715         }
716 
717         /*
718          * If no names, call once with the ordinal only.
719          */
720         if (!fFoundName)
721         {
722             rc = pfnCallback(pMod, iFunction + pExpDir->Base, NULL, 0, NULL, uValue, fKind, pvUser);
723             if (rc)
724                 return rc;
725         }
726     }
727     return 0;
728 
729 #elif K_OS == K_OS_DARWIN
730     /** @todo implement enumeration on darwin. */
731     (void)pModNative;
732     return KLDR_ERR_TODO;
733 
734 #else
735 # error "Port me"
736 #endif
737 
738 }
739 
740 
741 /** @copydoc kLdrModGetImport */
kldrModNativeGetImport(PKLDRMOD pMod,const void * pvBits,KU32 iImport,char * pszName,KSIZE cchName)742 static int kldrModNativeGetImport(PKLDRMOD pMod, const void *pvBits, KU32 iImport, char *pszName, KSIZE cchName)
743 {
744     PKLDRMODNATIVE                  pModNative = (PKLDRMODNATIVE)pMod->pvData;
745 #if K_OS == K_OS_OS2
746 
747     /** @todo implement import enumeration on OS/2. */
748     (void)pModNative;
749     return ERROR_NOT_SUPPORTED;
750 
751 #elif K_OS == K_OS_WINDOWS || defined(__NT__)
752     const IMAGE_IMPORT_DESCRIPTOR  *pImpDesc;
753     const char                     *pszImportName;
754     KSIZE                           cchImportName;
755     int                             rc;
756 
757     /*
758      * Simple bounds check.
759      */
760     if (iImport >= (KU32)kldrModNativeNumberOfImports(pMod, pvBits))
761         return KLDR_ERR_IMPORT_ORDINAL_OUT_OF_BOUNDS;
762 
763     /*
764      * Get the name.
765      */
766     pImpDesc = KLDRMODNATIVE_RVA2TYPE(pModNative->hmod,
767                                       pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress
768                                       + sizeof(IMAGE_IMPORT_DESCRIPTOR) * iImport,
769                                       const IMAGE_IMPORT_DESCRIPTOR *);
770     pszImportName = KLDRMODNATIVE_RVA2TYPE(pModNative->hmod, pImpDesc->Name, const char *);
771     cchImportName = kHlpStrLen(pszImportName);
772     if (cchImportName < cchName)
773     {
774         kHlpMemCopy(pszName, pszImportName, cchImportName + 1);
775         rc = 0;
776     }
777     else
778     {
779         kHlpMemCopy(pszName, pszImportName, cchName);
780         if (cchName)
781             pszName[cchName - 1] = '\0';
782         rc = KERR_BUFFER_OVERFLOW;
783     }
784 
785     return rc;
786 
787 #elif K_OS == K_OS_DARWIN
788     /** @todo Implement import enumeration on darwin. */
789     (void)pModNative;
790     return KLDR_ERR_TODO;
791 
792 #else
793 # error "Port me"
794 #endif
795 }
796 
797 
798 /** @copydoc kLdrModNumberOfImports */
kldrModNativeNumberOfImports(PKLDRMOD pMod,const void * pvBits)799 static KI32 kldrModNativeNumberOfImports(PKLDRMOD pMod, const void *pvBits)
800 {
801     PKLDRMODNATIVE pModNative = (PKLDRMODNATIVE)pMod->pvData;
802 #if K_OS == K_OS_OS2
803 
804     /** @todo implement import counting on OS/2. */
805     (void)pModNative;
806     return -1;
807 
808 #elif K_OS == K_OS_WINDOWS || defined(__NT__)
809     if (pModNative->cImportModules == ~(KU32)0)
810     {
811         /*
812          * We'll have to walk the import descriptors to figure out their number.
813          */
814         pModNative->cImportModules = 0;
815         if (    pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size
816             &&  pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
817         {
818             const IMAGE_IMPORT_DESCRIPTOR  *pImpDesc;
819 
820             pImpDesc = KLDRMODNATIVE_RVA2TYPE(pModNative->hmod,
821                                               pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress,
822                                               const IMAGE_IMPORT_DESCRIPTOR *);
823             while (pImpDesc->Name && pImpDesc->FirstThunk)
824             {
825                 pModNative->cImportModules++;
826                 pImpDesc++;
827             }
828         }
829     }
830     return pModNative->cImportModules;
831 
832 #elif K_OS == K_OS_DARWIN
833     /** @todo Implement import counting on Darwin. */
834     (void)pModNative;
835     return -1;
836 
837 #else
838 # error "Port me"
839 #endif
840 }
841 
842 
843 /** @copydoc kLdrModGetStackInfo */
kldrModNativeGetStackInfo(PKLDRMOD pMod,const void * pvBits,KLDRADDR BaseAddress,PKLDRSTACKINFO pStackInfo)844 static int kldrModNativeGetStackInfo(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, PKLDRSTACKINFO pStackInfo)
845 {
846     PKLDRMODNATIVE pModNative = (PKLDRMODNATIVE)pMod->pvData;
847 #if K_OS == K_OS_OS2
848 
849     /** @todo implement stack info on OS/2. */
850     (void)pModNative;
851     return ERROR_NOT_SUPPORTED;
852 
853 #elif K_OS == K_OS_WINDOWS || defined(__NT__)
854     pStackInfo->Address = NIL_KLDRADDR;
855     pStackInfo->LinkAddress = NIL_KLDRADDR;
856     pStackInfo->cbStack = pStackInfo->cbStackThread = pModNative->pNtHdrs->OptionalHeader.SizeOfStackReserve;
857 
858     return 0;
859 
860 #elif K_OS == K_OS_DARWIN
861     /** @todo Implement stack info on Darwin. */
862     (void)pModNative;
863     return KLDR_ERR_TODO;
864 
865 #else
866 # error "Port me"
867 #endif
868 }
869 
870 
871 /** @copydoc kLdrModQueryMainEntrypoint */
kldrModNativeQueryMainEntrypoint(PKLDRMOD pMod,const void * pvBits,KLDRADDR BaseAddress,PKLDRADDR pMainEPAddress)872 static int kldrModNativeQueryMainEntrypoint(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, PKLDRADDR pMainEPAddress)
873 {
874     PKLDRMODNATIVE pModNative = (PKLDRMODNATIVE)pMod->pvData;
875 #if K_OS == K_OS_OS2
876 
877     /** @todo implement me on OS/2. */
878     (void)pModNative;
879     return ERROR_NOT_SUPPORTED;
880 
881 #elif K_OS == K_OS_WINDOWS || defined(__NT__)
882     /*
883      * Convert the address from the header.
884      */
885     *pMainEPAddress = pModNative->pNtHdrs->OptionalHeader.AddressOfEntryPoint
886         ? BaseAddress + pModNative->pNtHdrs->OptionalHeader.AddressOfEntryPoint
887         : NIL_KLDRADDR;
888     return 0;
889 
890 #elif K_OS == K_OS_DARWIN
891     /** @todo Implement me on Darwin. */
892     (void)pModNative;
893     return KLDR_ERR_TODO;
894 
895 #else
896 # error "Port me"
897 #endif
898 }
899 
900 
901 /** @copydoc kLdrModEnumDbgInfo */
kldrModNativeEnumDbgInfo(PKLDRMOD pMod,const void * pvBits,PFNKLDRENUMDBG pfnCallback,void * pvUser)902 static int kldrModNativeEnumDbgInfo(PKLDRMOD pMod, const void *pvBits, PFNKLDRENUMDBG pfnCallback, void *pvUser)
903 {
904     PKLDRMODNATIVE                  pModNative = (PKLDRMODNATIVE)pMod->pvData;
905 #if K_OS == K_OS_OS2
906 
907     /** @todo implement me on OS/2. */
908     (void)pModNative;
909     return ERROR_NOT_SUPPORTED;
910 
911 #elif K_OS == K_OS_WINDOWS || defined(__NT__)
912     const IMAGE_DEBUG_DIRECTORY    *pDbgDir;
913     KU32                            iDbgInfo;
914     KU32                            cb;
915     int                             rc;
916 
917     /*
918      * Check that there is a debug directory first.
919      */
920     cb = pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
921     if (    cb < sizeof(IMAGE_DEBUG_DIRECTORY) /* screw borland linkers */
922         ||  !pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress)
923         return 0;
924 
925     /*
926      * Enumerate the debug directory.
927      */
928     pDbgDir = KLDRMODNATIVE_RVA2TYPE(pModNative->hmod,
929                                      pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress,
930                                      const IMAGE_DEBUG_DIRECTORY *);
931     for (iDbgInfo = 0;; iDbgInfo++, pDbgDir++, cb -= sizeof(IMAGE_DEBUG_DIRECTORY))
932     {
933         KLDRDBGINFOTYPE     enmDbgInfoType;
934 
935         /* convert the type. */
936         switch (pDbgDir->Type)
937         {
938             case IMAGE_DEBUG_TYPE_UNKNOWN:
939             case IMAGE_DEBUG_TYPE_FPO:
940             case IMAGE_DEBUG_TYPE_COFF: /*stabs dialect??*/
941             case IMAGE_DEBUG_TYPE_MISC:
942             case IMAGE_DEBUG_TYPE_EXCEPTION:
943             case IMAGE_DEBUG_TYPE_FIXUP:
944             case IMAGE_DEBUG_TYPE_BORLAND:
945             default:
946                 enmDbgInfoType = KLDRDBGINFOTYPE_UNKNOWN;
947                 break;
948             case IMAGE_DEBUG_TYPE_CODEVIEW:
949                 enmDbgInfoType = KLDRDBGINFOTYPE_CODEVIEW;
950                 break;
951         }
952 
953         rc = pfnCallback(pMod, iDbgInfo,
954                          enmDbgInfoType, pDbgDir->MajorVersion, pDbgDir->MinorVersion, NULL /*pszPartNm*/,
955                          pDbgDir->PointerToRawData ? pDbgDir->PointerToRawData : -1,
956                          pDbgDir->AddressOfRawData ? pDbgDir->AddressOfRawData : NIL_KLDRADDR,
957                          pDbgDir->SizeOfData,
958                          NULL /*pszExtFile*/, pvUser);
959         if (rc)
960             break;
961 
962         /* next */
963         if (cb <= sizeof(IMAGE_DEBUG_DIRECTORY))
964             break;
965     }
966 
967     return rc;
968 
969 #elif K_OS == K_OS_DARWIN
970     /** @todo Implement me on Darwin. */
971     (void)pModNative;
972     return KLDR_ERR_TODO;
973 
974 #else
975 # error "Port me"
976 #endif
977 }
978 
979 
980 /** @copydoc kLdrModHasDbgInfo */
kldrModNativeHasDbgInfo(PKLDRMOD pMod,const void * pvBits)981 static int kldrModNativeHasDbgInfo(PKLDRMOD pMod, const void *pvBits)
982 {
983     PKLDRMODNATIVE pModNative = (PKLDRMODNATIVE)pMod->pvData;
984 #if K_OS == K_OS_OS2
985 
986     /** @todo implement me on OS/2. */
987     (void)pModNative;
988     return KLDR_ERR_NO_DEBUG_INFO;
989 
990 #elif K_OS == K_OS_WINDOWS || defined(__NT__)
991     /*
992      * Base this entirely on the presence of a debug directory.
993      */
994     if (    pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size
995             < sizeof(IMAGE_DEBUG_DIRECTORY) /* screw borland linkers */
996         ||  !pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress)
997         return KLDR_ERR_NO_DEBUG_INFO;
998     return 0;
999 
1000 #elif K_OS == K_OS_DARWIN
1001     /** @todo Implement me on Darwin. */
1002     (void)pModNative;
1003     return KLDR_ERR_NO_DEBUG_INFO;
1004 
1005 #else
1006 # error "Port me"
1007 #endif
1008 }
1009 
1010 
1011 /** @copydoc kLdrModMap */
kldrModNativeMap(PKLDRMOD pMod)1012 static int kldrModNativeMap(PKLDRMOD pMod)
1013 {
1014     return 0;
1015 }
1016 
1017 
1018 /** @copydoc kLdrModUnmap */
kldrModNativeUnmap(PKLDRMOD pMod)1019 static int kldrModNativeUnmap(PKLDRMOD pMod)
1020 {
1021     return 0;
1022 }
1023 
1024 
1025 /** @copydoc kLdrModAllocTLS */
kldrModNativeAllocTLS(PKLDRMOD pMod,void * pvMapping)1026 static int kldrModNativeAllocTLS(PKLDRMOD pMod, void *pvMapping)
1027 {
1028     return 0;
1029 }
1030 
1031 
1032 /** @copydoc kLdrModFreeTLS */
kldrModNativeFreeTLS(PKLDRMOD pMod,void * pvMapping)1033 static void kldrModNativeFreeTLS(PKLDRMOD pMod, void *pvMapping)
1034 {
1035 }
1036 
1037 
1038 /** @copydoc kLdrModReload */
kldrModNativeReload(PKLDRMOD pMod)1039 static int kldrModNativeReload(PKLDRMOD pMod)
1040 {
1041     return 0;
1042 }
1043 
1044 
1045 /** @copydoc kLdrModFixupMapping */
kldrModNativeFixupMapping(PKLDRMOD pMod,PFNKLDRMODGETIMPORT pfnGetImport,void * pvUser)1046 static int kldrModNativeFixupMapping(PKLDRMOD pMod, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
1047 {
1048     return 0;
1049 }
1050 
1051 
1052 /** @copydoc kLdrModCallInit */
kldrModNativeCallInit(PKLDRMOD pMod,void * pvMapping,KUPTR uHandle)1053 static int kldrModNativeCallInit(PKLDRMOD pMod, void *pvMapping, KUPTR uHandle)
1054 {
1055     return 0;
1056 }
1057 
1058 
1059 /** @copydoc kLdrModCallTerm */
kldrModNativeCallTerm(PKLDRMOD pMod,void * pvMapping,KUPTR uHandle)1060 static int kldrModNativeCallTerm(PKLDRMOD pMod, void *pvMapping, KUPTR uHandle)
1061 {
1062     return 0;
1063 }
1064 
1065 
1066 /** @copydoc kLdrModCallThread */
kldrModNativeCallThread(PKLDRMOD pMod,void * pvMapping,KUPTR uHandle,unsigned fAttachingOrDetaching)1067 static int kldrModNativeCallThread(PKLDRMOD pMod, void *pvMapping, KUPTR uHandle, unsigned fAttachingOrDetaching)
1068 {
1069     return 0;
1070 }
1071 
1072 
1073 /** @copydoc kLdrModSize */
kldrModNativeSize(PKLDRMOD pMod)1074 static KLDRADDR kldrModNativeSize(PKLDRMOD pMod)
1075 {
1076 #if K_OS == K_OS_OS2
1077     return 0; /* don't bother */
1078 
1079 #elif K_OS == K_OS_WINDOWS || defined(__NT__)
1080     /* just because we can. */
1081     PKLDRMODNATIVE pModNative = (PKLDRMODNATIVE)pMod->pvData;
1082     return pModNative->pNtHdrs->OptionalHeader.SizeOfImage;
1083 
1084 #elif K_OS == K_OS_DARWIN
1085     /** @todo Implement me on Darwin. */
1086     return 0;
1087 
1088 #else
1089 # error "Port me"
1090 #endif
1091 }
1092 
1093 
1094 /** @copydoc kLdrModGetBits */
kldrModNativeGetBits(PKLDRMOD pMod,void * pvBits,KLDRADDR BaseAddress,PFNKLDRMODGETIMPORT pfnGetImport,void * pvUser)1095 static int kldrModNativeGetBits(PKLDRMOD pMod, void *pvBits, KLDRADDR BaseAddress, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
1096 {
1097 #if K_OS == K_OS_OS2
1098     return ERROR_NOT_SUPPORTED; /* don't bother */
1099 
1100 #elif K_OS == K_OS_WINDOWS || defined(__NT__)
1101     return ERROR_NOT_SUPPORTED; /* don't bother even if we could implement this. */
1102 
1103 #elif K_OS == K_OS_DARWIN
1104     return KLDR_ERR_TODO; /* don't bother. */
1105 
1106 #else
1107 # error "Port me"
1108 #endif
1109 }
1110 
1111 
1112 /** @copydoc kLdrModRelocateBits */
kldrModNativeRelocateBits(PKLDRMOD pMod,void * pvBits,KLDRADDR NewBaseAddress,KLDRADDR OldBaseAddress,PFNKLDRMODGETIMPORT pfnGetImport,void * pvUser)1113 static int kldrModNativeRelocateBits(PKLDRMOD pMod, void *pvBits, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress,
1114                                      PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
1115 {
1116 #if K_OS == K_OS_OS2
1117     return ERROR_NOT_SUPPORTED; /* don't bother */
1118 
1119 #elif K_OS == K_OS_WINDOWS || defined(__NT__)
1120     return ERROR_NOT_SUPPORTED; /* don't bother even if we could implement this. */
1121 
1122 #elif K_OS == K_OS_DARWIN
1123     return KLDR_ERR_TODO; /* don't bother. */
1124 
1125 #else
1126 # error "Port me"
1127 #endif
1128 }
1129 
1130 
1131 /**
1132  * The native module interpreter method table.
1133  */
1134 KLDRMODOPS g_kLdrModNativeOps =
1135 {
1136     "Native",
1137     NULL,
1138     kldrModNativeCreate,
1139     kldrModNativeDestroy,
1140     kldrModNativeQuerySymbol,
1141     kldrModNativeEnumSymbols,
1142     kldrModNativeGetImport,
1143     kldrModNativeNumberOfImports,
1144     NULL /* can execute one is optional */,
1145     kldrModNativeGetStackInfo,
1146     kldrModNativeQueryMainEntrypoint,
1147     NULL /* pfnQueryImageUuid */,
1148     NULL /* fixme */,
1149     NULL /* fixme */,
1150     kldrModNativeEnumDbgInfo,
1151     kldrModNativeHasDbgInfo,
1152     kldrModNativeMap,
1153     kldrModNativeUnmap,
1154     kldrModNativeAllocTLS,
1155     kldrModNativeFreeTLS,
1156     kldrModNativeReload,
1157     kldrModNativeFixupMapping,
1158     kldrModNativeCallInit,
1159     kldrModNativeCallTerm,
1160     kldrModNativeCallThread,
1161     kldrModNativeSize,
1162     kldrModNativeGetBits,
1163     kldrModNativeRelocateBits,
1164     NULL /* fixme */,
1165     42 /* the end */
1166 };
1167 
1168