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