source: trunk/kLdr/kLdrModNative.c@ 2893

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

made it compile again.

  • Property svn:keywords set to Id
File size: 35.2 KB
RevLine 
[2878]1/* $Id: kLdrModNative.c 2893 2006-12-22 18:01:38Z bird $ */
[2877]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__
[2883]35# define INCL_BASE
[2877]36# include <os2.h>
37
[2883]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
[2877]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
[2883]57# endif
[2877]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
[2883]176 rc = DosLoadModule(NULL, 0, (PCSZ)pszFilename, &hmod);
[2877]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. */
[2883]227 rc = DosQueryModuleName((HMODULE)uHandle, sizeof(szFilename), szFilename);
[2877]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__
[2883]322 pModNative->hmod = (HMODULE)uHandle;
[2877]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,
[2893]513 const char *pchSymbol, size_t cchSymbol, const char *pszVersion,
514 PFNKLDRMODGETIMPORT pfnGetForwarder, void *pvUser, PKLDRADDR puValue, uint32_t *pfKind)
[2877]515{
516 PKLDRMODNATIVE pModNative = (PKLDRMODNATIVE)pMod->pvData;
[2893]517 const char *pszSymbol = pchSymbol;
[2877]518#ifdef __OS2__
519 APIRET rc;
520 PFN pfn;
[2893]521#elif defined(__WIN__)
522 FARPROC pfn;
523#else
524# error "Port me"
525#endif
[2877]526
[2893]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)
[2877]538 return KLDR_ERR_SYMBOL_NOT_FOUND;
539
540 if (puValue)
541 {
542 rc = DosQueryProcAddr(pModNative->hmod,
543 pszSymbol ? 0 : iSymbol,
[2883]544 (PCSZ)pszSymbol,
[2877]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,
[2883]555 (PCSZ)pszSymbol,
[2877]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. */
[2883]595 (void)pModNative;
[2877]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 if (paOrdinals[iName] != iFunction)
647 continue;
648 fFoundName = 1;
649 rc = pfnCallback(pMod, iFunction + pExpDir->Base,
650 KLDRMODNATIVE_RVA2TYPE(pModNative->hmod, paRVANames[iName], const char *),
651 uValue, fKind, pvUser);
652 if (rc)
653 return rc;
654 }
655
656 /*
657 * If no names, call once with the ordinal only.
658 */
659 if (!fFoundName)
660 {
661 rc = pfnCallback(pMod, iFunction + pExpDir->Base, NULL, uValue, fKind, pvUser);
662 if (rc)
663 return rc;
664 }
665 }
666 return 0;
667
668#else
669# error "Port me"
670#endif
671
672}
673
674
675/** @copydoc kLdrModGetImport */
676static int kldrModNativeGetImport(PKLDRMOD pMod, const void *pvBits, uint32_t iImport, char *pszName, size_t cchName)
677{
678 PKLDRMODNATIVE pModNative = (PKLDRMODNATIVE)pMod->pvData;
679#ifdef __OS2__
680
681 /** @todo implement export enumeration on OS/2. */
[2883]682 (void)pModNative;
[2877]683 return ERROR_NOT_SUPPORTED;
684
685#elif defined(__WIN__) || defined(__NT__)
686 const IMAGE_IMPORT_DESCRIPTOR *pImpDesc;
687 const char *pszImportName;
688 size_t cchImportName;
689 int rc;
690
691 /*
692 * Simple bounds check.
693 */
694 if (iImport >= (uint32_t)kldrModNativeNumberOfImports(pMod, pvBits))
695 return KLDR_ERR_IMPORT_ORDINAL_OUT_OF_BOUNDS;
696
697 /*
698 * Get the name.
699 */
700 pImpDesc = KLDRMODNATIVE_RVA2TYPE(pModNative->hmod,
701 pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress
702 + sizeof(IMAGE_IMPORT_DESCRIPTOR) * iImport,
703 const IMAGE_IMPORT_DESCRIPTOR *);
704 pszImportName = KLDRMODNATIVE_RVA2TYPE(pModNative->hmod, pImpDesc->Name, const char *);
[2883]705 cchImportName = kLdrHlpStrLen(pszImportName);
[2877]706 if (cchImportName < cchName)
707 {
708 kLdrHlpMemCopy(pszName, pszImportName, cchImportName + 1);
709 rc = 0;
710 }
711 else
712 {
713 kLdrHlpMemCopy(pszName, pszImportName, cchName);
714 if (cchName)
715 pszName[cchName - 1] = '\0';
716 rc = KLDR_ERR_BUFFER_OVERFLOW;
717 }
718
719 return rc;
720
721#else
722# error "Port me"
723#endif
724}
725
726
727/** @copydoc kLdrModNumberOfImports */
728static int32_t kldrModNativeNumberOfImports(PKLDRMOD pMod, const void *pvBits)
729{
730 PKLDRMODNATIVE pModNative = (PKLDRMODNATIVE)pMod->pvData;
731#ifdef __OS2__
732
733 /** @todo implement export enumeration on OS/2. */
[2883]734 (void)pModNative;
[2877]735 return -1;
736
737#elif defined(__WIN__) || defined(__NT__)
738 if (pModNative->cImportModules == ~(uint32_t)0)
739 {
740 /*
741 * We'll have to walk the import descriptors to figure out their number.
742 */
743 pModNative->cImportModules = 0;
744 if ( pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size
745 && pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
746 {
747 const IMAGE_IMPORT_DESCRIPTOR *pImpDesc;
748
749 pImpDesc = KLDRMODNATIVE_RVA2TYPE(pModNative->hmod,
750 pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress,
751 const IMAGE_IMPORT_DESCRIPTOR *);
752 while (pImpDesc->Name && pImpDesc->FirstThunk)
753 {
754 pModNative->cImportModules++;
755 pImpDesc++;
756 }
757 }
758 }
759 return pModNative->cImportModules;
760
761#else
762# error "Port me"
763#endif
764}
765
766
767/** @copydoc kLdrModGetStackInfo */
768static int kldrModNativeGetStackInfo(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, PKLDRSTACKINFO pStackInfo)
769{
770 PKLDRMODNATIVE pModNative = (PKLDRMODNATIVE)pMod->pvData;
771#ifdef __OS2__
772
773 /** @todo implement export enumeration on OS/2. */
[2883]774 (void)pModNative;
[2877]775 return ERROR_NOT_SUPPORTED;
776
777#elif defined(__WIN__) || defined(__NT__)
778 pStackInfo->Address = NIL_KLDRADDR;
779 pStackInfo->LinkAddress = NIL_KLDRADDR;
780 pStackInfo->cbStack = pStackInfo->cbStackThread = pModNative->pNtHdrs->OptionalHeader.SizeOfStackReserve;
781
782 return 0;
783
784#else
785# error "Port me"
786#endif
787}
788
789
790/** @copydoc kLdrModQueryMainEntrypoint */
791static int kldrModNativeQueryMainEntrypoint(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, PKLDRADDR pMainEPAddress)
792{
793 PKLDRMODNATIVE pModNative = (PKLDRMODNATIVE)pMod->pvData;
794#ifdef __OS2__
795
796 /** @todo implement export enumeration on OS/2. */
[2883]797 (void)pModNative;
[2877]798 return ERROR_NOT_SUPPORTED;
799
800#elif defined(__WIN__) || defined(__NT__)
801 /*
802 * Convert the address from the header.
803 */
804 *pMainEPAddress = pModNative->pNtHdrs->OptionalHeader.AddressOfEntryPoint
805 ? BaseAddress + pModNative->pNtHdrs->OptionalHeader.AddressOfEntryPoint
806 : NIL_KLDRADDR;
807 return 0;
808
809#else
810# error "Port me"
811#endif
812}
813
814
815/** @copydoc kLdrModEnumDbgInfo */
816static int kldrModNativeEnumDbgInfo(PKLDRMOD pMod, const void *pvBits, PFNKLDRENUMDBG pfnCallback, void *pvUser)
817{
818 PKLDRMODNATIVE pModNative = (PKLDRMODNATIVE)pMod->pvData;
819#ifdef __OS2__
820
821 /** @todo implement export enumeration on OS/2. */
[2883]822 (void)pModNative;
[2877]823 return ERROR_NOT_SUPPORTED;
824
825#elif defined(__WIN__) || defined(__NT__)
826 const IMAGE_DEBUG_DIRECTORY *pDbgDir;
827 uint32_t iDbgInfo;
828 uint32_t cb;
829 int rc;
830
831 /*
832 * Check that there is a debug directory first.
833 */
834 cb = pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
835 if ( cb < sizeof(IMAGE_DEBUG_DIRECTORY) /* screw borland linkers */
836 || !pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress)
837 return 0;
838
839 /*
840 * Enumerate the debug directory.
841 */
842 pDbgDir = KLDRMODNATIVE_RVA2TYPE(pModNative->hmod,
843 pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress,
844 const IMAGE_DEBUG_DIRECTORY *);
845 for (iDbgInfo = 0;; iDbgInfo++, pDbgDir++, cb -= sizeof(IMAGE_DEBUG_DIRECTORY))
846 {
847 KLDRDBGINFOTYPE enmDbgInfoType;
848
849 /* convert the type. */
850 switch (pDbgDir->Type)
851 {
852 case IMAGE_DEBUG_TYPE_UNKNOWN:
853 case IMAGE_DEBUG_TYPE_FPO:
[2883]854 case IMAGE_DEBUG_TYPE_COFF: /*stabs dialect??*/
[2877]855 case IMAGE_DEBUG_TYPE_MISC:
856 case IMAGE_DEBUG_TYPE_EXCEPTION:
857 case IMAGE_DEBUG_TYPE_FIXUP:
858 case IMAGE_DEBUG_TYPE_BORLAND:
859 default:
860 enmDbgInfoType = KLDRDBGINFOTYPE_UNKNOWN;
861 break;
862 case IMAGE_DEBUG_TYPE_CODEVIEW:
863 enmDbgInfoType = KLDRDBGINFOTYPE_CODEVIEW;
864 break;
865 }
866
867 rc = pfnCallback(pMod, iDbgInfo,
868 enmDbgInfoType, pDbgDir->MajorVersion, pDbgDir->MinorVersion,
869 pDbgDir->PointerToRawData ? pDbgDir->PointerToRawData : -1,
870 pDbgDir->AddressOfRawData ? pDbgDir->AddressOfRawData : NIL_KLDRADDR,
871 pDbgDir->SizeOfData,
872 NULL,
873 pvUser);
874 if (rc)
875 break;
876
877 /* next */
878 if (cb <= sizeof(IMAGE_DEBUG_DIRECTORY))
879 break;
880 }
881
882 return rc;
883
884#else
885# error "Port me"
886#endif
887}
888
889
890/** @copydoc kLdrModHasDbgInfo */
891static int kldrModNativeHasDbgInfo(PKLDRMOD pMod, const void *pvBits)
892{
893 PKLDRMODNATIVE pModNative = (PKLDRMODNATIVE)pMod->pvData;
894#ifdef __OS2__
895
896 /** @todo implement export enumeration on OS/2. */
[2883]897 (void)pModNative;
[2877]898 return KLDR_ERR_NO_DEBUG_INFO;
899
900#elif defined(__WIN__) || defined(__NT__)
901 /*
902 * Base this entirely on the presence of a debug directory.
903 */
904 if ( pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size
905 < sizeof(IMAGE_DEBUG_DIRECTORY) /* screw borland linkers */
906 || !pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress)
907 return KLDR_ERR_NO_DEBUG_INFO;
908 return 0;
909#else
910# error "Port me"
911#endif
912}
913
914
915/** @copydoc kLdrModMap */
916static int kldrModNativeMap(PKLDRMOD pMod)
917{
918 return 0;
919}
920
921
922/** @copydoc kLdrModUnmap */
923static int kldrModNativeUnmap(PKLDRMOD pMod)
924{
925 return 0;
926}
927
928
929/** @copydoc kLdrModAllocTLS */
930static int kldrModNativeAllocTLS(PKLDRMOD pMod)
931{
932 return 0;
933}
934
935
936/** @copydoc kLdrModFreeTLS */
937static void kldrModNativeFreeTLS(PKLDRMOD pMod)
938{
939}
940
941
942/** @copydoc kLdrModReload */
943static int kldrModNativeReload(PKLDRMOD pMod)
944{
945 return 0;
946}
947
948
949/** @copydoc kLdrModFixupMapping */
950static int kldrModNativeFixupMapping(PKLDRMOD pMod, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
951{
952 return 0;
953}
954
955
956/** @copydoc kLdrModCallInit */
957static int kldrModNativeCallInit(PKLDRMOD pMod, uintptr_t uHandle)
958{
959 return 0;
960}
961
962
963/** @copydoc kLdrModCallTerm */
964static int kldrModNativeCallTerm(PKLDRMOD pMod, uintptr_t uHandle)
965{
966 return 0;
967}
968
969
970/** @copydoc kLdrModCallThread */
971static int kldrModNativeCallThread(PKLDRMOD pMod, uintptr_t uHandle, unsigned fAttachingOrDetaching)
972{
973 return 0;
974}
975
976
977/** @copydoc kLdrModSize */
978static KLDRADDR kldrModNativeSize(PKLDRMOD pMod)
979{
980#ifdef __OS2__
981 return 0; /* don't bother */
982
983#elif defined(__WIN__) || defined(__NT__)
984 /* just because we can. */
985 PKLDRMODNATIVE pModNative = (PKLDRMODNATIVE)pMod->pvData;
986 return pModNative->pNtHdrs->OptionalHeader.SizeOfImage;
987
988#else
989# error "Port me"
990#endif
991}
992
993
994/** @copydoc kLdrModGetBits */
995static int kldrModNativeGetBits(PKLDRMOD pMod, void *pvBits, KLDRADDR BaseAddress, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
996{
997#ifdef __OS2__
998 return ERROR_NOT_SUPPORTED; /* don't bother */
999
1000#elif defined(__WIN__) || defined(__NT__)
1001 return ERROR_NOT_SUPPORTED; /* don't bother even if we could implement this. */
1002#else
1003# error "Port me"
1004#endif
1005}
1006
1007
1008/** @copydoc kLdrModRelocateBits */
1009static int kldrModNativeRelocateBits(PKLDRMOD pMod, void *pvBits, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress,
1010 PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
1011{
1012#ifdef __OS2__
1013 return ERROR_NOT_SUPPORTED; /* don't bother */
1014
1015#elif defined(__WIN__) || defined(__NT__)
1016 return ERROR_NOT_SUPPORTED; /* don't bother even if we could implement this. */
1017#else
1018# error "Port me"
1019#endif
1020}
1021
1022
1023/**
1024 * The native module interpreter method table.
1025 */
1026KLDRMODOPS g_kLdrModNativeOps =
1027{
1028 "Native",
1029 NULL,
1030 kldrModNativeCreate,
1031 kldrModNativeDestroy,
1032 kldrModNativeQuerySymbol,
1033 kldrModNativeEnumSymbols,
1034 kldrModNativeGetImport,
1035 kldrModNativeNumberOfImports,
1036 NULL /* can execute one is optional */,
1037 kldrModNativeGetStackInfo,
1038 kldrModNativeQueryMainEntrypoint,
[2893]1039 NULL /* fixme */,
1040 NULL /* fixme */,
[2877]1041 kldrModNativeEnumDbgInfo,
1042 kldrModNativeHasDbgInfo,
1043 kldrModNativeMap,
1044 kldrModNativeUnmap,
1045 kldrModNativeAllocTLS,
1046 kldrModNativeFreeTLS,
1047 kldrModNativeReload,
1048 kldrModNativeFixupMapping,
1049 kldrModNativeCallInit,
1050 kldrModNativeCallTerm,
1051 kldrModNativeCallThread,
1052 kldrModNativeSize,
1053 kldrModNativeGetBits,
1054 kldrModNativeRelocateBits,
[2893]1055 NULL /* fixme */,
[2877]1056 42 /* the end */
1057};
1058
Note: See TracBrowser for help on using the repository browser.