source: trunk/kLdr/kLdrModNative.c@ 2883

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

cleanup.

  • Property svn:keywords set to Id
File size: 34.7 KB
Line 
1/* $Id: kLdrModNative.c 2883 2006-11-18 11:21:33Z 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 *pszSymbol, PFNKLDRMODGETIMPORT pfnGetForwarder, void *pvUser,
514 PKLDRADDR puValue, uint32_t *pfKind)
515{
516 PKLDRMODNATIVE pModNative = (PKLDRMODNATIVE)pMod->pvData;
517#ifdef __OS2__
518 APIRET rc;
519 PFN pfn;
520
521 if (!pszSymbol && iSymbol >= 0x10000)
522 return KLDR_ERR_SYMBOL_NOT_FOUND;
523
524 if (puValue)
525 {
526 rc = DosQueryProcAddr(pModNative->hmod,
527 pszSymbol ? 0 : iSymbol,
528 (PCSZ)pszSymbol,
529 &pfn);
530 if (rc)
531 return rc == ERROR_PROC_NOT_FOUND ? KLDR_ERR_SYMBOL_NOT_FOUND : rc;
532 *puValue = (uintptr_t)pfn;
533 }
534 if (pfKind)
535 {
536 ULONG ulProcType;
537 rc = DosQueryProcType(pModNative->hmod,
538 pszSymbol ? 0 : iSymbol,
539 (PCSZ)pszSymbol,
540 &ulProcType);
541 if (rc)
542 {
543 if (puValue)
544 *puValue = 0;
545 return rc == ERROR_PROC_NOT_FOUND ? KLDR_ERR_SYMBOL_NOT_FOUND : rc;
546 }
547 *pfKind = (ulProcType & PT_32BIT ? KLDRSYMKIND_32BIT : KLDRSYMKIND_16BIT)
548 | KLDRSYMKIND_NO_TYPE;
549 }
550
551#elif defined(__WIN__)
552 FARPROC pfn;
553
554 if (!pszSymbol && iSymbol >= 0x10000)
555 return KLDR_ERR_SYMBOL_NOT_FOUND;
556
557 pfn = GetProcAddress(pModNative->hmod, pszSymbol ? pszSymbol : (const char *)(uintptr_t)iSymbol);
558 if (puValue)
559 *puValue = (uintptr_t)pfn;
560 if (pfKind)
561 *pfKind = (pModNative->pNtHdrs->FileHeader.SizeOfOptionalHeader == sizeof(IMAGE_OPTIONAL_HEADER32)
562 ? KLDRSYMKIND_32BIT : KLDRSYMKIND_16BIT)
563 | KLDRSYMKIND_NO_TYPE;
564
565#else
566# error "Port me"
567#endif
568
569 return 0;
570}
571
572
573/** @copydoc kLdrModEnumSymbols */
574static int kldrModNativeEnumSymbols(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress,
575 uint32_t fFlags, PFNKLDRMODENUMSYMS pfnCallback, void *pvUser)
576{
577 PKLDRMODNATIVE pModNative = (PKLDRMODNATIVE)pMod->pvData;
578#ifdef __OS2__
579
580 /** @todo implement export enumeration on OS/2. */
581 (void)pModNative;
582 return ERROR_NOT_SUPPORTED;
583
584#elif defined(__WIN__) || defined(__NT__)
585 const uint32_t *paFunctions;
586 const IMAGE_EXPORT_DIRECTORY *pExpDir;
587 const uint32_t *paRVANames;
588 const uint16_t *paOrdinals;
589 uint32_t iFunction;
590 uint32_t cFunctions;
591 uint32_t cNames;
592 int rc;
593
594 /*
595 * Make sure we've got mapped bits and resolve any base address aliases.
596 */
597 if ( pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size
598 < sizeof(IMAGE_EXPORT_DIRECTORY))
599 return 0; /* no exports to enumerate, return success. */
600
601 pExpDir = KLDRMODNATIVE_RVA2TYPE(pModNative->hmod,
602 pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress,
603 PIMAGE_EXPORT_DIRECTORY);
604
605 /*
606 * Enumerate the ordinal exports.
607 */
608 paRVANames = KLDRMODNATIVE_RVA2TYPE(pModNative->hmod, pExpDir->AddressOfNames, const uint32_t *);
609 paOrdinals = KLDRMODNATIVE_RVA2TYPE(pModNative->hmod, pExpDir->AddressOfNameOrdinals, const uint16_t *);
610 paFunctions = KLDRMODNATIVE_RVA2TYPE(pModNative->hmod, pExpDir->AddressOfFunctions, const uint32_t *);
611 cFunctions = pExpDir->NumberOfFunctions;
612 cNames = pExpDir->NumberOfNames;
613 for (iFunction = 0; iFunction < cFunctions; iFunction++)
614 {
615 unsigned fFoundName;
616 uint32_t iName;
617 const uint32_t uRVA = paFunctions[iFunction];
618 const KLDRADDR uValue = BaseAddress + uRVA;
619 uint32_t fKind = (pModNative->pNtHdrs->FileHeader.SizeOfOptionalHeader == sizeof(IMAGE_OPTIONAL_HEADER32)
620 ? KLDRSYMKIND_32BIT : KLDRSYMKIND_64BIT)
621 | KLDRSYMKIND_NO_TYPE;
622 if ( uRVA - pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress
623 < pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size)
624 fKind |= KLDRSYMKIND_FORWARDER;
625
626 /*
627 * Any symbol names?
628 */
629 fFoundName = 0;
630 for (iName = 0; iName < cNames; iName++)
631 {
632 if (paOrdinals[iName] != iFunction)
633 continue;
634 fFoundName = 1;
635 rc = pfnCallback(pMod, iFunction + pExpDir->Base,
636 KLDRMODNATIVE_RVA2TYPE(pModNative->hmod, paRVANames[iName], const char *),
637 uValue, fKind, pvUser);
638 if (rc)
639 return rc;
640 }
641
642 /*
643 * If no names, call once with the ordinal only.
644 */
645 if (!fFoundName)
646 {
647 rc = pfnCallback(pMod, iFunction + pExpDir->Base, NULL, uValue, fKind, pvUser);
648 if (rc)
649 return rc;
650 }
651 }
652 return 0;
653
654#else
655# error "Port me"
656#endif
657
658}
659
660
661/** @copydoc kLdrModGetImport */
662static int kldrModNativeGetImport(PKLDRMOD pMod, const void *pvBits, uint32_t iImport, char *pszName, size_t cchName)
663{
664 PKLDRMODNATIVE pModNative = (PKLDRMODNATIVE)pMod->pvData;
665#ifdef __OS2__
666
667 /** @todo implement export enumeration on OS/2. */
668 (void)pModNative;
669 return ERROR_NOT_SUPPORTED;
670
671#elif defined(__WIN__) || defined(__NT__)
672 const IMAGE_IMPORT_DESCRIPTOR *pImpDesc;
673 const char *pszImportName;
674 size_t cchImportName;
675 int rc;
676
677 /*
678 * Simple bounds check.
679 */
680 if (iImport >= (uint32_t)kldrModNativeNumberOfImports(pMod, pvBits))
681 return KLDR_ERR_IMPORT_ORDINAL_OUT_OF_BOUNDS;
682
683 /*
684 * Get the name.
685 */
686 pImpDesc = KLDRMODNATIVE_RVA2TYPE(pModNative->hmod,
687 pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress
688 + sizeof(IMAGE_IMPORT_DESCRIPTOR) * iImport,
689 const IMAGE_IMPORT_DESCRIPTOR *);
690 pszImportName = KLDRMODNATIVE_RVA2TYPE(pModNative->hmod, pImpDesc->Name, const char *);
691 cchImportName = kLdrHlpStrLen(pszImportName);
692 if (cchImportName < cchName)
693 {
694 kLdrHlpMemCopy(pszName, pszImportName, cchImportName + 1);
695 rc = 0;
696 }
697 else
698 {
699 kLdrHlpMemCopy(pszName, pszImportName, cchName);
700 if (cchName)
701 pszName[cchName - 1] = '\0';
702 rc = KLDR_ERR_BUFFER_OVERFLOW;
703 }
704
705 return rc;
706
707#else
708# error "Port me"
709#endif
710}
711
712
713/** @copydoc kLdrModNumberOfImports */
714static int32_t kldrModNativeNumberOfImports(PKLDRMOD pMod, const void *pvBits)
715{
716 PKLDRMODNATIVE pModNative = (PKLDRMODNATIVE)pMod->pvData;
717#ifdef __OS2__
718
719 /** @todo implement export enumeration on OS/2. */
720 (void)pModNative;
721 return -1;
722
723#elif defined(__WIN__) || defined(__NT__)
724 if (pModNative->cImportModules == ~(uint32_t)0)
725 {
726 /*
727 * We'll have to walk the import descriptors to figure out their number.
728 */
729 pModNative->cImportModules = 0;
730 if ( pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size
731 && pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
732 {
733 const IMAGE_IMPORT_DESCRIPTOR *pImpDesc;
734
735 pImpDesc = KLDRMODNATIVE_RVA2TYPE(pModNative->hmod,
736 pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress,
737 const IMAGE_IMPORT_DESCRIPTOR *);
738 while (pImpDesc->Name && pImpDesc->FirstThunk)
739 {
740 pModNative->cImportModules++;
741 pImpDesc++;
742 }
743 }
744 }
745 return pModNative->cImportModules;
746
747#else
748# error "Port me"
749#endif
750}
751
752
753/** @copydoc kLdrModGetStackInfo */
754static int kldrModNativeGetStackInfo(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, PKLDRSTACKINFO pStackInfo)
755{
756 PKLDRMODNATIVE pModNative = (PKLDRMODNATIVE)pMod->pvData;
757#ifdef __OS2__
758
759 /** @todo implement export enumeration on OS/2. */
760 (void)pModNative;
761 return ERROR_NOT_SUPPORTED;
762
763#elif defined(__WIN__) || defined(__NT__)
764 pStackInfo->Address = NIL_KLDRADDR;
765 pStackInfo->LinkAddress = NIL_KLDRADDR;
766 pStackInfo->cbStack = pStackInfo->cbStackThread = pModNative->pNtHdrs->OptionalHeader.SizeOfStackReserve;
767
768 return 0;
769
770#else
771# error "Port me"
772#endif
773}
774
775
776/** @copydoc kLdrModQueryMainEntrypoint */
777static int kldrModNativeQueryMainEntrypoint(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, PKLDRADDR pMainEPAddress)
778{
779 PKLDRMODNATIVE pModNative = (PKLDRMODNATIVE)pMod->pvData;
780#ifdef __OS2__
781
782 /** @todo implement export enumeration on OS/2. */
783 (void)pModNative;
784 return ERROR_NOT_SUPPORTED;
785
786#elif defined(__WIN__) || defined(__NT__)
787 /*
788 * Convert the address from the header.
789 */
790 *pMainEPAddress = pModNative->pNtHdrs->OptionalHeader.AddressOfEntryPoint
791 ? BaseAddress + pModNative->pNtHdrs->OptionalHeader.AddressOfEntryPoint
792 : NIL_KLDRADDR;
793 return 0;
794
795#else
796# error "Port me"
797#endif
798}
799
800
801/** @copydoc kLdrModEnumDbgInfo */
802static int kldrModNativeEnumDbgInfo(PKLDRMOD pMod, const void *pvBits, PFNKLDRENUMDBG pfnCallback, void *pvUser)
803{
804 PKLDRMODNATIVE pModNative = (PKLDRMODNATIVE)pMod->pvData;
805#ifdef __OS2__
806
807 /** @todo implement export enumeration on OS/2. */
808 (void)pModNative;
809 return ERROR_NOT_SUPPORTED;
810
811#elif defined(__WIN__) || defined(__NT__)
812 const IMAGE_DEBUG_DIRECTORY *pDbgDir;
813 uint32_t iDbgInfo;
814 uint32_t cb;
815 int rc;
816
817 /*
818 * Check that there is a debug directory first.
819 */
820 cb = pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
821 if ( cb < sizeof(IMAGE_DEBUG_DIRECTORY) /* screw borland linkers */
822 || !pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress)
823 return 0;
824
825 /*
826 * Enumerate the debug directory.
827 */
828 pDbgDir = KLDRMODNATIVE_RVA2TYPE(pModNative->hmod,
829 pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress,
830 const IMAGE_DEBUG_DIRECTORY *);
831 for (iDbgInfo = 0;; iDbgInfo++, pDbgDir++, cb -= sizeof(IMAGE_DEBUG_DIRECTORY))
832 {
833 KLDRDBGINFOTYPE enmDbgInfoType;
834
835 /* convert the type. */
836 switch (pDbgDir->Type)
837 {
838 case IMAGE_DEBUG_TYPE_UNKNOWN:
839 case IMAGE_DEBUG_TYPE_FPO:
840 case IMAGE_DEBUG_TYPE_COFF: /*stabs dialect??*/
841 case IMAGE_DEBUG_TYPE_MISC:
842 case IMAGE_DEBUG_TYPE_EXCEPTION:
843 case IMAGE_DEBUG_TYPE_FIXUP:
844 case IMAGE_DEBUG_TYPE_BORLAND:
845 default:
846 enmDbgInfoType = KLDRDBGINFOTYPE_UNKNOWN;
847 break;
848 case IMAGE_DEBUG_TYPE_CODEVIEW:
849 enmDbgInfoType = KLDRDBGINFOTYPE_CODEVIEW;
850 break;
851 }
852
853 rc = pfnCallback(pMod, iDbgInfo,
854 enmDbgInfoType, pDbgDir->MajorVersion, pDbgDir->MinorVersion,
855 pDbgDir->PointerToRawData ? pDbgDir->PointerToRawData : -1,
856 pDbgDir->AddressOfRawData ? pDbgDir->AddressOfRawData : NIL_KLDRADDR,
857 pDbgDir->SizeOfData,
858 NULL,
859 pvUser);
860 if (rc)
861 break;
862
863 /* next */
864 if (cb <= sizeof(IMAGE_DEBUG_DIRECTORY))
865 break;
866 }
867
868 return rc;
869
870#else
871# error "Port me"
872#endif
873}
874
875
876/** @copydoc kLdrModHasDbgInfo */
877static int kldrModNativeHasDbgInfo(PKLDRMOD pMod, const void *pvBits)
878{
879 PKLDRMODNATIVE pModNative = (PKLDRMODNATIVE)pMod->pvData;
880#ifdef __OS2__
881
882 /** @todo implement export enumeration on OS/2. */
883 (void)pModNative;
884 return KLDR_ERR_NO_DEBUG_INFO;
885
886#elif defined(__WIN__) || defined(__NT__)
887 /*
888 * Base this entirely on the presence of a debug directory.
889 */
890 if ( pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size
891 < sizeof(IMAGE_DEBUG_DIRECTORY) /* screw borland linkers */
892 || !pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress)
893 return KLDR_ERR_NO_DEBUG_INFO;
894 return 0;
895#else
896# error "Port me"
897#endif
898}
899
900
901/** @copydoc kLdrModMap */
902static int kldrModNativeMap(PKLDRMOD pMod)
903{
904 return 0;
905}
906
907
908/** @copydoc kLdrModUnmap */
909static int kldrModNativeUnmap(PKLDRMOD pMod)
910{
911 return 0;
912}
913
914
915/** @copydoc kLdrModAllocTLS */
916static int kldrModNativeAllocTLS(PKLDRMOD pMod)
917{
918 return 0;
919}
920
921
922/** @copydoc kLdrModFreeTLS */
923static void kldrModNativeFreeTLS(PKLDRMOD pMod)
924{
925}
926
927
928/** @copydoc kLdrModReload */
929static int kldrModNativeReload(PKLDRMOD pMod)
930{
931 return 0;
932}
933
934
935/** @copydoc kLdrModFixupMapping */
936static int kldrModNativeFixupMapping(PKLDRMOD pMod, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
937{
938 return 0;
939}
940
941
942/** @copydoc kLdrModCallInit */
943static int kldrModNativeCallInit(PKLDRMOD pMod, uintptr_t uHandle)
944{
945 return 0;
946}
947
948
949/** @copydoc kLdrModCallTerm */
950static int kldrModNativeCallTerm(PKLDRMOD pMod, uintptr_t uHandle)
951{
952 return 0;
953}
954
955
956/** @copydoc kLdrModCallThread */
957static int kldrModNativeCallThread(PKLDRMOD pMod, uintptr_t uHandle, unsigned fAttachingOrDetaching)
958{
959 return 0;
960}
961
962
963/** @copydoc kLdrModSize */
964static KLDRADDR kldrModNativeSize(PKLDRMOD pMod)
965{
966#ifdef __OS2__
967 return 0; /* don't bother */
968
969#elif defined(__WIN__) || defined(__NT__)
970 /* just because we can. */
971 PKLDRMODNATIVE pModNative = (PKLDRMODNATIVE)pMod->pvData;
972 return pModNative->pNtHdrs->OptionalHeader.SizeOfImage;
973
974#else
975# error "Port me"
976#endif
977}
978
979
980/** @copydoc kLdrModGetBits */
981static int kldrModNativeGetBits(PKLDRMOD pMod, void *pvBits, KLDRADDR BaseAddress, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
982{
983#ifdef __OS2__
984 return ERROR_NOT_SUPPORTED; /* don't bother */
985
986#elif defined(__WIN__) || defined(__NT__)
987 return ERROR_NOT_SUPPORTED; /* don't bother even if we could implement this. */
988#else
989# error "Port me"
990#endif
991}
992
993
994/** @copydoc kLdrModRelocateBits */
995static int kldrModNativeRelocateBits(PKLDRMOD pMod, void *pvBits, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress,
996 PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
997{
998#ifdef __OS2__
999 return ERROR_NOT_SUPPORTED; /* don't bother */
1000
1001#elif defined(__WIN__) || defined(__NT__)
1002 return ERROR_NOT_SUPPORTED; /* don't bother even if we could implement this. */
1003#else
1004# error "Port me"
1005#endif
1006}
1007
1008
1009/**
1010 * The native module interpreter method table.
1011 */
1012KLDRMODOPS g_kLdrModNativeOps =
1013{
1014 "Native",
1015 NULL,
1016 kldrModNativeCreate,
1017 kldrModNativeDestroy,
1018 kldrModNativeQuerySymbol,
1019 kldrModNativeEnumSymbols,
1020 kldrModNativeGetImport,
1021 kldrModNativeNumberOfImports,
1022 NULL /* can execute one is optional */,
1023 kldrModNativeGetStackInfo,
1024 kldrModNativeQueryMainEntrypoint,
1025 kldrModNativeEnumDbgInfo,
1026 kldrModNativeHasDbgInfo,
1027 kldrModNativeMap,
1028 kldrModNativeUnmap,
1029 kldrModNativeAllocTLS,
1030 kldrModNativeFreeTLS,
1031 kldrModNativeReload,
1032 kldrModNativeFixupMapping,
1033 kldrModNativeCallInit,
1034 kldrModNativeCallTerm,
1035 kldrModNativeCallThread,
1036 kldrModNativeSize,
1037 kldrModNativeGetBits,
1038 kldrModNativeRelocateBits,
1039 42 /* the end */
1040};
1041
Note: See TracBrowser for help on using the repository browser.