VirtualBox

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

Last change on this file since 40 was 29, checked in by bird, 16 years ago

Finally got around execute the switch to the MIT license.

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette