source: trunk/kLdr/kLdrModNative.c@ 2878

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

Keywords.

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