VirtualBox

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

Last change on this file since 58 was 58, checked in by bird, 11 years ago

Mach-O: Carve segments from the mach-o segments instead of the sections inside them. This works better for non-object files.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 36.7 KB
Line 
1/* $Id: kLdrModNative.c 58 2013-10-12 20:18:21Z 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 pMod->fFlags = 0;
325#if defined(__i386__) || defined(__X86__) || defined(_M_IX86)
326 pMod->enmCpu = KCPU_I386;
327 pMod->enmArch = KCPUARCH_X86_32;
328 pMod->enmEndian = KLDRENDIAN_LITTLE;
329#elif defined(__X86_64__) || defined(__x86_64__) || defined(__AMD64__) || defined(_M_IX64)
330 pMod->enmCpu = KCPU_K8;
331 pMod->enmArch = KCPUARCH_AMD64;
332 pMod->enmEndian = KLDRENDIAN_LITTLE;
333#else
334# error "Port me"
335#endif
336 pMod->enmFmt = KLDRFMT_NATIVE;
337 pMod->enmType = KLDRTYPE_SHARED_LIBRARY_RELOCATABLE;
338 pMod->u32Magic = 0; /* set upon success. */
339
340 /* KLDRMODNATIVE */
341 pModNative->pMod = pMod;
342 pModNative->f32Reserved = 0;
343 pModNative->cImportModules = ~(KU32)0;
344
345 /*
346 * Set native instance data.
347 */
348#if K_OS == K_OS_OS2
349 pModNative->hmod = (HMODULE)uHandle;
350
351 /* just fake a segment for now. */
352 pMod->aSegments[0].pvUser = NULL;
353 pMod->aSegments[0].pchName = "fake";
354 pMod->aSegments[0].cchName = sizeof("fake") - 1;
355 pMod->aSegments[0].enmProt = KPROT_NOACCESS;
356 pMod->aSegments[0].cb = 0;
357 pMod->aSegments[0].Alignment = 0;
358 pMod->aSegments[0].LinkAddress = NIL_KLDRADDR;
359 pMod->aSegments[0].offFile = -1;
360 pMod->aSegments[0].cbFile = 0;
361 pMod->aSegments[0].RVA = NIL_KLDRADDR;
362 pMod->aSegments[0].cbMapped = 0;
363 pMod->aSegments[0].MapAddress = 0;
364
365#elif K_OS == K_OS_WINDOWS
366 pModNative->hmod = (HMODULE)uHandle;
367 pModNative->pNtHdrs = pNtHdrs;
368 pModNative->paShdrs = paShdrs;
369
370 if (pNtHdrs->FileHeader.Characteristics & IMAGE_FILE_DLL)
371 pMod->enmType = !(pNtHdrs->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
372 ? KLDRTYPE_SHARED_LIBRARY_RELOCATABLE
373 : KLDRTYPE_SHARED_LIBRARY_FIXED;
374 else
375 pMod->enmType = !(pNtHdrs->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
376 ? KLDRTYPE_EXECUTABLE_RELOCATABLE
377 : KLDRTYPE_EXECUTABLE_FIXED;
378
379 /* The implied headers section. */
380 pMod->aSegments[0].pvUser = NULL;
381 pMod->aSegments[0].pchName = "TheHeaders";
382 pMod->aSegments[0].cchName = sizeof("TheHeaders") - 1;
383 pMod->aSegments[0].enmProt = KPROT_READONLY;
384 pMod->aSegments[0].cb = pNtHdrs->OptionalHeader.SizeOfHeaders;
385 pMod->aSegments[0].Alignment = pNtHdrs->OptionalHeader.SectionAlignment;
386 pMod->aSegments[0].LinkAddress = pNtHdrs->OptionalHeader.ImageBase;
387 pMod->aSegments[0].offFile = 0;
388 pMod->aSegments[0].cbFile = pNtHdrs->OptionalHeader.SizeOfHeaders;
389 pMod->aSegments[0].RVA = 0;
390 if (pMod->cSegments > 1)
391 pMod->aSegments[0].cbMapped = paShdrs[0].VirtualAddress;
392 else
393 pMod->aSegments[0].cbMapped = pNtHdrs->OptionalHeader.SizeOfHeaders;
394 pMod->aSegments[0].MapAddress = 0;
395
396 /* The section headers. */
397 for (i = 0; i < pNtHdrs->FileHeader.NumberOfSections; i++)
398 {
399 const char *pch;
400
401 /* unused */
402 pMod->aSegments[i + 1].pvUser = NULL;
403 pMod->aSegments[i + 1].MapAddress = 0;
404
405 /* name */
406 pMod->aSegments[i + 1].pchName = pch = &paShdrs[i].Name[0];
407 cb = IMAGE_SIZEOF_SHORT_NAME;
408 while ( cb > 0
409 && (pch[cb - 1] == ' ' || pch[cb - 1] == '\0'))
410 cb--;
411 pMod->aSegments[i + 1].cchName = cb;
412
413 /* size and addresses */
414 if (!(paShdrs[i].Characteristics & IMAGE_SCN_TYPE_NOLOAD))
415 {
416 pMod->aSegments[i + 1].cb = paShdrs[i].Misc.VirtualSize;
417 pMod->aSegments[i + 1].LinkAddress = paShdrs[i].VirtualAddress
418 + pNtHdrs->OptionalHeader.ImageBase;
419 pMod->aSegments[i + 1].RVA = paShdrs[i].VirtualAddress;
420 pMod->aSegments[i + 1].cbMapped = paShdrs[i].Misc.VirtualSize;
421 if (i + 2 < pMod->cSegments)
422 pMod->aSegments[i + 1].cbMapped= paShdrs[i + 1].VirtualAddress
423 - paShdrs[i].VirtualAddress;
424 }
425 else
426 {
427 pMod->aSegments[i + 1].cb = 0;
428 pMod->aSegments[i + 1].cbMapped = 0;
429 pMod->aSegments[i + 1].LinkAddress = NIL_KLDRADDR;
430 pMod->aSegments[i + 1].RVA = 0;
431 }
432
433 /* file location */
434 pMod->aSegments[i + 1].offFile = paShdrs[i].PointerToRawData;
435 pMod->aSegments[i + 1].cbFile = paShdrs[i].SizeOfRawData;
436 if ( pMod->aSegments[i + 1].cbMapped > 0 /* if mapped */
437 && (KLDRSIZE)pMod->aSegments[i + 1].cbFile > pMod->aSegments[i + 1].cbMapped)
438 pMod->aSegments[i + 1].cbFile = pMod->aSegments[i + 1].cbMapped;
439
440 /* protection */
441 switch ( paShdrs[i].Characteristics
442 & (IMAGE_SCN_MEM_SHARED | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE))
443 {
444 case 0:
445 case IMAGE_SCN_MEM_SHARED:
446 pMod->aSegments[i + 1].enmProt = KPROT_NOACCESS;
447 break;
448 case IMAGE_SCN_MEM_READ:
449 case IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_SHARED:
450 pMod->aSegments[i + 1].enmProt = KPROT_READONLY;
451 break;
452 case IMAGE_SCN_MEM_WRITE:
453 case IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_READ:
454 pMod->aSegments[i + 1].enmProt = KPROT_WRITECOPY;
455 break;
456 case IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_SHARED:
457 case IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_SHARED | IMAGE_SCN_MEM_READ:
458 pMod->aSegments[i + 1].enmProt = KPROT_READWRITE;
459 break;
460 case IMAGE_SCN_MEM_EXECUTE:
461 case IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_SHARED:
462 pMod->aSegments[i + 1].enmProt = KPROT_EXECUTE;
463 break;
464 case IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ:
465 case IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_SHARED:
466 pMod->aSegments[i + 1].enmProt = KPROT_EXECUTE_READ;
467 break;
468 case IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_WRITE:
469 case IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_READ:
470 pMod->aSegments[i + 1].enmProt = KPROT_EXECUTE_WRITECOPY;
471 break;
472 case IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_SHARED:
473 case IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_SHARED | IMAGE_SCN_MEM_READ:
474 pMod->aSegments[i + 1].enmProt = KPROT_EXECUTE_READWRITE;
475 break;
476 }
477
478 /* alignment. */
479 switch (paShdrs[i].Characteristics & IMAGE_SCN_ALIGN_MASK)
480 {
481 case 0: /* hope this is right... */
482 pMod->aSegments[i + 1].Alignment = pNtHdrs->OptionalHeader.SectionAlignment;
483 break;
484 case IMAGE_SCN_ALIGN_1BYTES: pMod->aSegments[i + 1].Alignment = 1; break;
485 case IMAGE_SCN_ALIGN_2BYTES: pMod->aSegments[i + 1].Alignment = 2; break;
486 case IMAGE_SCN_ALIGN_4BYTES: pMod->aSegments[i + 1].Alignment = 4; break;
487 case IMAGE_SCN_ALIGN_8BYTES: pMod->aSegments[i + 1].Alignment = 8; break;
488 case IMAGE_SCN_ALIGN_16BYTES: pMod->aSegments[i + 1].Alignment = 16; break;
489 case IMAGE_SCN_ALIGN_32BYTES: pMod->aSegments[i + 1].Alignment = 32; break;
490 case IMAGE_SCN_ALIGN_64BYTES: pMod->aSegments[i + 1].Alignment = 64; break;
491 case IMAGE_SCN_ALIGN_128BYTES: pMod->aSegments[i + 1].Alignment = 128; break;
492 case IMAGE_SCN_ALIGN_256BYTES: pMod->aSegments[i + 1].Alignment = 256; break;
493 case IMAGE_SCN_ALIGN_512BYTES: pMod->aSegments[i + 1].Alignment = 512; break;
494 case IMAGE_SCN_ALIGN_1024BYTES: pMod->aSegments[i + 1].Alignment = 1024; break;
495 case IMAGE_SCN_ALIGN_2048BYTES: pMod->aSegments[i + 1].Alignment = 2048; break;
496 case IMAGE_SCN_ALIGN_4096BYTES: pMod->aSegments[i + 1].Alignment = 4096; break;
497 case IMAGE_SCN_ALIGN_8192BYTES: pMod->aSegments[i + 1].Alignment = 8192; break;
498 default: kHlpAssert(0); pMod->aSegments[i + 1].Alignment = 0; break;
499 }
500 }
501
502#elif K_OS == K_OS_DARWIN
503 /** @todo Figure out the Mac OS X dynamic loader. */
504
505#else
506# error "Port me"
507#endif
508
509 /*
510 * We're done.
511 */
512 *ppMod = pMod;
513 return 0;
514}
515
516
517/** @copydoc KLDRMODOPS::pfnDestroy */
518static int kldrModNativeDestroy(PKLDRMOD pMod)
519{
520 PKLDRMODNATIVE pModNative = (PKLDRMODNATIVE)pMod->pvData;
521 int rc;
522
523#if K_OS == K_OS_OS2
524 rc = DosFreeModule(pModNative->hmod);
525
526#elif K_OS == K_OS_WINDOWS
527 if (FreeLibrary(pModNative->hmod))
528 rc = 0;
529 else
530 rc = GetLastError();
531
532#elif K_OS == K_OS_DARWIN
533 dlclose(pModNative->pvMod);
534
535#else
536# error "Port me"
537#endif
538
539 pMod->u32Magic = 0;
540 pMod->pOps = NULL;
541 kHlpFree(pModNative);
542 return rc;
543}
544
545
546/** @copydoc kLdrModQuerySymbol */
547static int kldrModNativeQuerySymbol(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, KU32 iSymbol,
548 const char *pchSymbol, KSIZE cchSymbol, const char *pszVersion,
549 PFNKLDRMODGETIMPORT pfnGetForwarder, void *pvUser, PKLDRADDR puValue, KU32 *pfKind)
550{
551 PKLDRMODNATIVE pModNative = (PKLDRMODNATIVE)pMod->pvData;
552 const char *pszSymbol = pchSymbol;
553#if K_OS == K_OS_OS2
554 APIRET rc;
555 PFN pfn;
556#elif K_OS == K_OS_WINDOWS
557 FARPROC pfn;
558#elif K_OS == K_OS_DARWIN
559 void *pfn;
560#else
561# error "Port me"
562#endif
563
564 /* make stack copy of the symbol if it isn't zero terminated. */
565 if (pszSymbol && pszSymbol[cchSymbol])
566 {
567 char *pszCopy = kHlpAllocA(cchSymbol + 1);
568 kHlpMemCopy(pszCopy, pchSymbol, cchSymbol);
569 pszCopy[cchSymbol] = '\0';
570 pszSymbol = pszCopy;
571 }
572
573#if K_OS == K_OS_OS2
574 if (!pchSymbol && iSymbol >= 0x10000)
575 return KLDR_ERR_SYMBOL_NOT_FOUND;
576
577 if (puValue)
578 {
579 rc = DosQueryProcAddr(pModNative->hmod,
580 pszSymbol ? 0 : iSymbol,
581 (PCSZ)pszSymbol,
582 &pfn);
583 if (rc)
584 return rc == ERROR_PROC_NOT_FOUND ? KLDR_ERR_SYMBOL_NOT_FOUND : rc;
585 *puValue = (KUPTR)pfn;
586 }
587 if (pfKind)
588 {
589 ULONG ulProcType;
590 rc = DosQueryProcType(pModNative->hmod,
591 pszSymbol ? 0 : iSymbol,
592 (PCSZ)pszSymbol,
593 &ulProcType);
594 if (rc)
595 {
596 if (puValue)
597 *puValue = 0;
598 return rc == ERROR_PROC_NOT_FOUND ? KLDR_ERR_SYMBOL_NOT_FOUND : rc;
599 }
600 *pfKind = (ulProcType & PT_32BIT ? KLDRSYMKIND_32BIT : KLDRSYMKIND_16BIT)
601 | KLDRSYMKIND_NO_TYPE;
602 }
603
604#elif K_OS == K_OS_WINDOWS
605 if (!pszSymbol && iSymbol >= 0x10000)
606 return KLDR_ERR_SYMBOL_NOT_FOUND;
607
608 pfn = GetProcAddress(pModNative->hmod, pszSymbol ? pszSymbol : (const char *)(KUPTR)iSymbol);
609 if (puValue)
610 *puValue = (KUPTR)pfn;
611 if (pfKind)
612 *pfKind = (pModNative->pNtHdrs->FileHeader.SizeOfOptionalHeader == sizeof(IMAGE_OPTIONAL_HEADER32)
613 ? KLDRSYMKIND_32BIT : KLDRSYMKIND_16BIT)
614 | KLDRSYMKIND_NO_TYPE;
615
616#elif K_OS == K_OS_DARWIN
617 if (!pszSymbol && iSymbol != NIL_KLDRMOD_SYM_ORDINAL)
618 return KLDR_ERR_SYMBOL_NOT_FOUND;
619
620 pfn = dlsym(pModNative->pvMod, pszSymbol);
621 if (!pfn)
622 return KLDR_ERR_SYMBOL_NOT_FOUND;
623 if (puValue)
624 *puValue = (KUPTR)pfn;
625 if (pfKind)
626 *pfKind = (sizeof(KUPTR) == 4 ? KLDRSYMKIND_32BIT : KLDRSYMKIND_64BIT)
627 | KLDRSYMKIND_NO_TYPE;
628
629#else
630# error "Port me"
631#endif
632
633 return 0;
634}
635
636
637/** @copydoc kLdrModEnumSymbols */
638static int kldrModNativeEnumSymbols(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress,
639 KU32 fFlags, PFNKLDRMODENUMSYMS pfnCallback, void *pvUser)
640{
641 PKLDRMODNATIVE pModNative = (PKLDRMODNATIVE)pMod->pvData;
642#if K_OS == K_OS_OS2
643
644 /** @todo implement export enumeration on OS/2. */
645 (void)pModNative;
646 return ERROR_NOT_SUPPORTED;
647
648#elif K_OS == K_OS_WINDOWS || defined(__NT__)
649 const KU32 *paFunctions;
650 const IMAGE_EXPORT_DIRECTORY *pExpDir;
651 const KU32 *paRVANames;
652 const KU16 *paOrdinals;
653 KU32 iFunction;
654 KU32 cFunctions;
655 KU32 cNames;
656 int rc;
657
658 /*
659 * Make sure we've got mapped bits and resolve any base address aliases.
660 */
661 if ( pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size
662 < sizeof(IMAGE_EXPORT_DIRECTORY))
663 return 0; /* no exports to enumerate, return success. */
664
665 pExpDir = KLDRMODNATIVE_RVA2TYPE(pModNative->hmod,
666 pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress,
667 PIMAGE_EXPORT_DIRECTORY);
668
669 /*
670 * Enumerate the ordinal exports.
671 */
672 paRVANames = KLDRMODNATIVE_RVA2TYPE(pModNative->hmod, pExpDir->AddressOfNames, const KU32 *);
673 paOrdinals = KLDRMODNATIVE_RVA2TYPE(pModNative->hmod, pExpDir->AddressOfNameOrdinals, const KU16 *);
674 paFunctions = KLDRMODNATIVE_RVA2TYPE(pModNative->hmod, pExpDir->AddressOfFunctions, const KU32 *);
675 cFunctions = pExpDir->NumberOfFunctions;
676 cNames = pExpDir->NumberOfNames;
677 for (iFunction = 0; iFunction < cFunctions; iFunction++)
678 {
679 unsigned fFoundName;
680 KU32 iName;
681 const KU32 uRVA = paFunctions[iFunction];
682 const KLDRADDR uValue = BaseAddress + uRVA;
683 KU32 fKind = (pModNative->pNtHdrs->FileHeader.SizeOfOptionalHeader == sizeof(IMAGE_OPTIONAL_HEADER32)
684 ? KLDRSYMKIND_32BIT : KLDRSYMKIND_64BIT)
685 | KLDRSYMKIND_NO_TYPE;
686 if ( uRVA - pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress
687 < pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size)
688 fKind |= KLDRSYMKIND_FORWARDER;
689
690 /*
691 * Any symbol names?
692 */
693 fFoundName = 0;
694 for (iName = 0; iName < cNames; iName++)
695 {
696 const char *pszName;
697 if (paOrdinals[iName] != iFunction)
698 continue;
699 fFoundName = 1;
700
701 pszName = KLDRMODNATIVE_RVA2TYPE(pModNative->hmod, paRVANames[iName], const char *);
702 rc = pfnCallback(pMod, iFunction + pExpDir->Base, pszName, strlen(pszName), NULL,
703 uValue, fKind, pvUser);
704 if (rc)
705 return rc;
706 }
707
708 /*
709 * If no names, call once with the ordinal only.
710 */
711 if (!fFoundName)
712 {
713 rc = pfnCallback(pMod, iFunction + pExpDir->Base, NULL, 0, NULL, uValue, fKind, pvUser);
714 if (rc)
715 return rc;
716 }
717 }
718 return 0;
719
720#elif K_OS == K_OS_DARWIN
721 /** @todo implement enumeration on darwin. */
722 (void)pModNative;
723 return KLDR_ERR_TODO;
724
725#else
726# error "Port me"
727#endif
728
729}
730
731
732/** @copydoc kLdrModGetImport */
733static int kldrModNativeGetImport(PKLDRMOD pMod, const void *pvBits, KU32 iImport, char *pszName, KSIZE cchName)
734{
735 PKLDRMODNATIVE pModNative = (PKLDRMODNATIVE)pMod->pvData;
736#if K_OS == K_OS_OS2
737
738 /** @todo implement import enumeration on OS/2. */
739 (void)pModNative;
740 return ERROR_NOT_SUPPORTED;
741
742#elif K_OS == K_OS_WINDOWS || defined(__NT__)
743 const IMAGE_IMPORT_DESCRIPTOR *pImpDesc;
744 const char *pszImportName;
745 KSIZE cchImportName;
746 int rc;
747
748 /*
749 * Simple bounds check.
750 */
751 if (iImport >= (KU32)kldrModNativeNumberOfImports(pMod, pvBits))
752 return KLDR_ERR_IMPORT_ORDINAL_OUT_OF_BOUNDS;
753
754 /*
755 * Get the name.
756 */
757 pImpDesc = KLDRMODNATIVE_RVA2TYPE(pModNative->hmod,
758 pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress
759 + sizeof(IMAGE_IMPORT_DESCRIPTOR) * iImport,
760 const IMAGE_IMPORT_DESCRIPTOR *);
761 pszImportName = KLDRMODNATIVE_RVA2TYPE(pModNative->hmod, pImpDesc->Name, const char *);
762 cchImportName = kHlpStrLen(pszImportName);
763 if (cchImportName < cchName)
764 {
765 kHlpMemCopy(pszName, pszImportName, cchImportName + 1);
766 rc = 0;
767 }
768 else
769 {
770 kHlpMemCopy(pszName, pszImportName, cchName);
771 if (cchName)
772 pszName[cchName - 1] = '\0';
773 rc = KERR_BUFFER_OVERFLOW;
774 }
775
776 return rc;
777
778#elif K_OS == K_OS_DARWIN
779 /** @todo Implement import enumeration on darwin. */
780 (void)pModNative;
781 return KLDR_ERR_TODO;
782
783#else
784# error "Port me"
785#endif
786}
787
788
789/** @copydoc kLdrModNumberOfImports */
790static KI32 kldrModNativeNumberOfImports(PKLDRMOD pMod, const void *pvBits)
791{
792 PKLDRMODNATIVE pModNative = (PKLDRMODNATIVE)pMod->pvData;
793#if K_OS == K_OS_OS2
794
795 /** @todo implement import counting on OS/2. */
796 (void)pModNative;
797 return -1;
798
799#elif K_OS == K_OS_WINDOWS || defined(__NT__)
800 if (pModNative->cImportModules == ~(KU32)0)
801 {
802 /*
803 * We'll have to walk the import descriptors to figure out their number.
804 */
805 pModNative->cImportModules = 0;
806 if ( pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size
807 && pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
808 {
809 const IMAGE_IMPORT_DESCRIPTOR *pImpDesc;
810
811 pImpDesc = KLDRMODNATIVE_RVA2TYPE(pModNative->hmod,
812 pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress,
813 const IMAGE_IMPORT_DESCRIPTOR *);
814 while (pImpDesc->Name && pImpDesc->FirstThunk)
815 {
816 pModNative->cImportModules++;
817 pImpDesc++;
818 }
819 }
820 }
821 return pModNative->cImportModules;
822
823#elif K_OS == K_OS_DARWIN
824 /** @todo Implement import counting on Darwin. */
825 (void)pModNative;
826 return -1;
827
828#else
829# error "Port me"
830#endif
831}
832
833
834/** @copydoc kLdrModGetStackInfo */
835static int kldrModNativeGetStackInfo(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, PKLDRSTACKINFO pStackInfo)
836{
837 PKLDRMODNATIVE pModNative = (PKLDRMODNATIVE)pMod->pvData;
838#if K_OS == K_OS_OS2
839
840 /** @todo implement stack info on OS/2. */
841 (void)pModNative;
842 return ERROR_NOT_SUPPORTED;
843
844#elif K_OS == K_OS_WINDOWS || defined(__NT__)
845 pStackInfo->Address = NIL_KLDRADDR;
846 pStackInfo->LinkAddress = NIL_KLDRADDR;
847 pStackInfo->cbStack = pStackInfo->cbStackThread = pModNative->pNtHdrs->OptionalHeader.SizeOfStackReserve;
848
849 return 0;
850
851#elif K_OS == K_OS_DARWIN
852 /** @todo Implement stack info on Darwin. */
853 (void)pModNative;
854 return KLDR_ERR_TODO;
855
856#else
857# error "Port me"
858#endif
859}
860
861
862/** @copydoc kLdrModQueryMainEntrypoint */
863static int kldrModNativeQueryMainEntrypoint(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, PKLDRADDR pMainEPAddress)
864{
865 PKLDRMODNATIVE pModNative = (PKLDRMODNATIVE)pMod->pvData;
866#if K_OS == K_OS_OS2
867
868 /** @todo implement me on OS/2. */
869 (void)pModNative;
870 return ERROR_NOT_SUPPORTED;
871
872#elif K_OS == K_OS_WINDOWS || defined(__NT__)
873 /*
874 * Convert the address from the header.
875 */
876 *pMainEPAddress = pModNative->pNtHdrs->OptionalHeader.AddressOfEntryPoint
877 ? BaseAddress + pModNative->pNtHdrs->OptionalHeader.AddressOfEntryPoint
878 : NIL_KLDRADDR;
879 return 0;
880
881#elif K_OS == K_OS_DARWIN
882 /** @todo Implement me on Darwin. */
883 (void)pModNative;
884 return KLDR_ERR_TODO;
885
886#else
887# error "Port me"
888#endif
889}
890
891
892/** @copydoc kLdrModEnumDbgInfo */
893static int kldrModNativeEnumDbgInfo(PKLDRMOD pMod, const void *pvBits, PFNKLDRENUMDBG pfnCallback, void *pvUser)
894{
895 PKLDRMODNATIVE pModNative = (PKLDRMODNATIVE)pMod->pvData;
896#if K_OS == K_OS_OS2
897
898 /** @todo implement me on OS/2. */
899 (void)pModNative;
900 return ERROR_NOT_SUPPORTED;
901
902#elif K_OS == K_OS_WINDOWS || defined(__NT__)
903 const IMAGE_DEBUG_DIRECTORY *pDbgDir;
904 KU32 iDbgInfo;
905 KU32 cb;
906 int rc;
907
908 /*
909 * Check that there is a debug directory first.
910 */
911 cb = pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
912 if ( cb < sizeof(IMAGE_DEBUG_DIRECTORY) /* screw borland linkers */
913 || !pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress)
914 return 0;
915
916 /*
917 * Enumerate the debug directory.
918 */
919 pDbgDir = KLDRMODNATIVE_RVA2TYPE(pModNative->hmod,
920 pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress,
921 const IMAGE_DEBUG_DIRECTORY *);
922 for (iDbgInfo = 0;; iDbgInfo++, pDbgDir++, cb -= sizeof(IMAGE_DEBUG_DIRECTORY))
923 {
924 KLDRDBGINFOTYPE enmDbgInfoType;
925
926 /* convert the type. */
927 switch (pDbgDir->Type)
928 {
929 case IMAGE_DEBUG_TYPE_UNKNOWN:
930 case IMAGE_DEBUG_TYPE_FPO:
931 case IMAGE_DEBUG_TYPE_COFF: /*stabs dialect??*/
932 case IMAGE_DEBUG_TYPE_MISC:
933 case IMAGE_DEBUG_TYPE_EXCEPTION:
934 case IMAGE_DEBUG_TYPE_FIXUP:
935 case IMAGE_DEBUG_TYPE_BORLAND:
936 default:
937 enmDbgInfoType = KLDRDBGINFOTYPE_UNKNOWN;
938 break;
939 case IMAGE_DEBUG_TYPE_CODEVIEW:
940 enmDbgInfoType = KLDRDBGINFOTYPE_CODEVIEW;
941 break;
942 }
943
944 rc = pfnCallback(pMod, iDbgInfo,
945 enmDbgInfoType, pDbgDir->MajorVersion, pDbgDir->MinorVersion,
946 pDbgDir->PointerToRawData ? pDbgDir->PointerToRawData : -1,
947 pDbgDir->AddressOfRawData ? pDbgDir->AddressOfRawData : NIL_KLDRADDR,
948 pDbgDir->SizeOfData,
949 NULL,
950 pvUser);
951 if (rc)
952 break;
953
954 /* next */
955 if (cb <= sizeof(IMAGE_DEBUG_DIRECTORY))
956 break;
957 }
958
959 return rc;
960
961#elif K_OS == K_OS_DARWIN
962 /** @todo Implement me on Darwin. */
963 (void)pModNative;
964 return KLDR_ERR_TODO;
965
966#else
967# error "Port me"
968#endif
969}
970
971
972/** @copydoc kLdrModHasDbgInfo */
973static int kldrModNativeHasDbgInfo(PKLDRMOD pMod, const void *pvBits)
974{
975 PKLDRMODNATIVE pModNative = (PKLDRMODNATIVE)pMod->pvData;
976#if K_OS == K_OS_OS2
977
978 /** @todo implement me on OS/2. */
979 (void)pModNative;
980 return KLDR_ERR_NO_DEBUG_INFO;
981
982#elif K_OS == K_OS_WINDOWS || defined(__NT__)
983 /*
984 * Base this entirely on the presence of a debug directory.
985 */
986 if ( pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size
987 < sizeof(IMAGE_DEBUG_DIRECTORY) /* screw borland linkers */
988 || !pModNative->pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress)
989 return KLDR_ERR_NO_DEBUG_INFO;
990 return 0;
991
992#elif K_OS == K_OS_DARWIN
993 /** @todo Implement me on Darwin. */
994 (void)pModNative;
995 return KLDR_ERR_NO_DEBUG_INFO;
996
997#else
998# error "Port me"
999#endif
1000}
1001
1002
1003/** @copydoc kLdrModMap */
1004static int kldrModNativeMap(PKLDRMOD pMod)
1005{
1006 return 0;
1007}
1008
1009
1010/** @copydoc kLdrModUnmap */
1011static int kldrModNativeUnmap(PKLDRMOD pMod)
1012{
1013 return 0;
1014}
1015
1016
1017/** @copydoc kLdrModAllocTLS */
1018static int kldrModNativeAllocTLS(PKLDRMOD pMod)
1019{
1020 return 0;
1021}
1022
1023
1024/** @copydoc kLdrModFreeTLS */
1025static void kldrModNativeFreeTLS(PKLDRMOD pMod)
1026{
1027}
1028
1029
1030/** @copydoc kLdrModReload */
1031static int kldrModNativeReload(PKLDRMOD pMod)
1032{
1033 return 0;
1034}
1035
1036
1037/** @copydoc kLdrModFixupMapping */
1038static int kldrModNativeFixupMapping(PKLDRMOD pMod, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
1039{
1040 return 0;
1041}
1042
1043
1044/** @copydoc kLdrModCallInit */
1045static int kldrModNativeCallInit(PKLDRMOD pMod, KUPTR uHandle)
1046{
1047 return 0;
1048}
1049
1050
1051/** @copydoc kLdrModCallTerm */
1052static int kldrModNativeCallTerm(PKLDRMOD pMod, KUPTR uHandle)
1053{
1054 return 0;
1055}
1056
1057
1058/** @copydoc kLdrModCallThread */
1059static int kldrModNativeCallThread(PKLDRMOD pMod, KUPTR uHandle, unsigned fAttachingOrDetaching)
1060{
1061 return 0;
1062}
1063
1064
1065/** @copydoc kLdrModSize */
1066static KLDRADDR kldrModNativeSize(PKLDRMOD pMod)
1067{
1068#if K_OS == K_OS_OS2
1069 return 0; /* don't bother */
1070
1071#elif K_OS == K_OS_WINDOWS || defined(__NT__)
1072 /* just because we can. */
1073 PKLDRMODNATIVE pModNative = (PKLDRMODNATIVE)pMod->pvData;
1074 return pModNative->pNtHdrs->OptionalHeader.SizeOfImage;
1075
1076#elif K_OS == K_OS_DARWIN
1077 /** @todo Implement me on Darwin. */
1078 return 0;
1079
1080#else
1081# error "Port me"
1082#endif
1083}
1084
1085
1086/** @copydoc kLdrModGetBits */
1087static int kldrModNativeGetBits(PKLDRMOD pMod, void *pvBits, KLDRADDR BaseAddress, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
1088{
1089#if K_OS == K_OS_OS2
1090 return ERROR_NOT_SUPPORTED; /* don't bother */
1091
1092#elif K_OS == K_OS_WINDOWS || defined(__NT__)
1093 return ERROR_NOT_SUPPORTED; /* don't bother even if we could implement this. */
1094
1095#elif K_OS == K_OS_DARWIN
1096 return KLDR_ERR_TODO; /* don't bother. */
1097
1098#else
1099# error "Port me"
1100#endif
1101}
1102
1103
1104/** @copydoc kLdrModRelocateBits */
1105static int kldrModNativeRelocateBits(PKLDRMOD pMod, void *pvBits, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress,
1106 PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
1107{
1108#if K_OS == K_OS_OS2
1109 return ERROR_NOT_SUPPORTED; /* don't bother */
1110
1111#elif K_OS == K_OS_WINDOWS || defined(__NT__)
1112 return ERROR_NOT_SUPPORTED; /* don't bother even if we could implement this. */
1113
1114#elif K_OS == K_OS_DARWIN
1115 return KLDR_ERR_TODO; /* don't bother. */
1116
1117#else
1118# error "Port me"
1119#endif
1120}
1121
1122
1123/**
1124 * The native module interpreter method table.
1125 */
1126KLDRMODOPS g_kLdrModNativeOps =
1127{
1128 "Native",
1129 NULL,
1130 kldrModNativeCreate,
1131 kldrModNativeDestroy,
1132 kldrModNativeQuerySymbol,
1133 kldrModNativeEnumSymbols,
1134 kldrModNativeGetImport,
1135 kldrModNativeNumberOfImports,
1136 NULL /* can execute one is optional */,
1137 kldrModNativeGetStackInfo,
1138 kldrModNativeQueryMainEntrypoint,
1139 NULL /* pfnQueryImageUuid */,
1140 NULL /* fixme */,
1141 NULL /* fixme */,
1142 kldrModNativeEnumDbgInfo,
1143 kldrModNativeHasDbgInfo,
1144 kldrModNativeMap,
1145 kldrModNativeUnmap,
1146 kldrModNativeAllocTLS,
1147 kldrModNativeFreeTLS,
1148 kldrModNativeReload,
1149 kldrModNativeFixupMapping,
1150 kldrModNativeCallInit,
1151 kldrModNativeCallTerm,
1152 kldrModNativeCallThread,
1153 kldrModNativeSize,
1154 kldrModNativeGetBits,
1155 kldrModNativeRelocateBits,
1156 NULL /* fixme */,
1157 42 /* the end */
1158};
1159
Note: See TracBrowser for help on using the repository browser.

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