source: trunk/kLdr/kLdrModNative.c@ 2898

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

Made it build on windows.

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