source: trunk/kStuff/kLdr/kLdrModNative.c@ 3573

Last change on this file since 3573 was 3573, checked in by bird, 18 years ago

kHlp work...

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