source: trunk/kLdr/kLdrModNative.c@ 3232

Last change on this file since 3232 was 2974, checked in by bird, 19 years ago

off_t -> KLDRFOFF.

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