VirtualBox

source: kStuff/trunk/kLdr/kLdrMod.c@ 25

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

A blind shot at FAT Mach-O images.

  • Property svn:keywords set to Id Revision
File size: 33.3 KB
Line 
1/* $Id: kLdrMod.c 25 2009-02-19 00:56:15Z bird $ */
2/** @file
3 * kLdr - The Module Interpreter.
4 */
5
6/*
7 * Copyright (c) 2006-2007 knut st. osmundsen <[email protected]>
8 *
9 * This file is part of kStuff.
10 *
11 * kStuff is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * In addition to the permissions in the GNU Lesser General Public
17 * License, you are granted unlimited permission to link the compiled
18 * version of this file into combinations with other programs, and to
19 * distribute those combinations without any restriction coming from
20 * the use of this file.
21 *
22 * kStuff is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25 * Lesser General Public License for more details.
26 *
27 * You should have received a copy of the GNU Lesser General Public
28 * License along with kStuff; if not, write to the Free Software
29 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
30 * 02110-1301, USA
31 */
32
33/*******************************************************************************
34* Header Files *
35*******************************************************************************/
36#include <k/kLdr.h>
37#include "kLdrInternal.h"
38#include <k/kCpu.h>
39#include <k/kLdrFmts/mz.h>
40#if 1 /* testing headers */
41# include <k/kLdrFmts/pe.h>
42# include <k/kLdrFmts/lx.h>
43# include <k/kLdrFmts/elf32.h>
44# include <k/kLdrFmts/elf64.h>
45# include <k/kLdrFmts/mach-o.h>
46#endif
47
48
49/*******************************************************************************
50* Defined Constants And Macros *
51*******************************************************************************/
52/** @def KLDRMOD_STRICT
53 * Define KLDRMOD_STRICT to enabled strict checks in KLDRMOD. */
54#define KLDRMOD_STRICT 1
55
56/** @def KLDRMOD_ASSERT
57 * Assert that an expression is true when KLDR_STRICT is defined.
58 */
59#ifdef KLDRMOD_STRICT
60# define KLDRMOD_ASSERT(expr) kHlpAssert(expr)
61#else
62# define KLDRMOD_ASSERT(expr) do {} while (0)
63#endif
64
65/** Return / crash validation of a module argument. */
66#define KLDRMOD_VALIDATE_EX(pMod, rc) \
67 do { \
68 if ( (pMod)->u32Magic != KLDRMOD_MAGIC \
69 || (pMod)->pOps == NULL \
70 )\
71 { \
72 return (rc); \
73 } \
74 } while (0)
75
76/** Return / crash validation of a module argument. */
77#define KLDRMOD_VALIDATE(pMod) \
78 KLDRMOD_VALIDATE_EX(pMod, KERR_INVALID_PARAMETER)
79
80/** Return / crash validation of a module argument. */
81#define KLDRMOD_VALIDATE_VOID(pMod) \
82 do { \
83 if ( (pMod)->u32Magic != KLDRMOD_MAGIC \
84 || (pMod)->pOps == NULL \
85 )\
86 { \
87 return; \
88 } \
89 } while (0)
90
91
92/*******************************************************************************
93* Global Variables *
94*******************************************************************************/
95/** The list of module interpreters. */
96static PCKLDRMODOPS g_pModInterpreterHead = NULL;
97
98
99
100/*******************************************************************************
101* Internal Functions *
102*******************************************************************************/
103
104
105
106/**
107 * Open a executable image by file name.
108 *
109 * @returns 0 on success and *ppMod pointing to a module instance.
110 * On failure, a non-zero OS specific error code is returned.
111 * @param pszFilename The filename to open.
112 * @param fFlags Flags, MBZ.
113 * @param enmCpuArch The desired CPU architecture. KCPUARCH_UNKNOWN means
114 * anything goes, but with a preference for the current
115 * host architecture.
116 * @param ppMod Where to store the module handle.
117 */
118int kLdrModOpen(const char *pszFilename, KU32 fFlags, KCPUARCH enmCpuArch, PPKLDRMOD ppMod)
119{
120 /*
121 * Open the file using a bit provider.
122 */
123 PKRDR pRdr;
124 int rc = kRdrOpen(&pRdr, pszFilename);
125 if (!rc)
126 {
127 rc = kLdrModOpenFromRdr(pRdr, fFlags, enmCpuArch, ppMod);
128 if (!rc)
129 return 0;
130 kRdrClose(pRdr);
131 }
132 return rc;
133}
134
135
136/**
137 * Select image from the FAT according to the enmCpuArch and fFlag.
138 *
139 * @returns 0 on success and *poffHdr set to the image header.
140 * On failure, a non-zero error code is returned.
141 *
142 * @param pRdr The file provider instance to use.
143 * @param fFlags Flags, MBZ.
144 * @param enmCpuArch The desired CPU architecture. KCPUARCH_UNKNOWN means
145 * anything goes, but with a preference for the current
146 * host architecture.
147 * @param u32Magic The FAT magic.
148 * @param poffHdr Where to store the offset of the selected image.
149 */
150static int kldrModOpenFromRdrSelectImageFromFAT(PKRDR pRdr, KU32 fFlags, KCPUARCH enmCpuArch, KU32 u32Magic, KLDRFOFF *poffHdr)
151{
152 int rcRet = KLDR_ERR_CPU_ARCH_MISMATCH;
153 KLDRFOFF off = *poffHdr + sizeof(KU32);
154 KLDRFOFF offEndFAT;
155 KBOOL fCpuArchWhatever;
156 KU32 cArchs;
157 KU32 iArch;
158 int rc;
159
160 /* Read fat_header_t::nfat_arch. */
161 rc = kRdrRead(pRdr, &cArchs, sizeof(cArchs), off);
162 if (rc)
163 return rc;
164 off += sizeof(KU32);
165 if (u32Magic == IMAGE_FAT_SIGNATURE_OE)
166 cArchs = K_E2E_U32(cArchs);
167 if (cArchs == 0)
168 return KLDR_ERR_FAT_INVALID;
169
170 /* Deal with KCPUARCH_UNKNOWN. */
171 fCpuArchWhatever = enmCpuArch == KCPUARCH_UNKNOWN;
172 if (fCpuArchWhatever)
173 {
174 KCPU enmCpuIgnored;
175 kCpuGetArchAndCpu(&enmCpuArch, &enmCpuIgnored);
176 }
177
178 /*
179 * Iterate the architecture list.
180 */
181 offEndFAT = off + cArchs * sizeof(fat_arch_t);
182 for (iArch = 0; iArch < cArchs; iArch++)
183 {
184 KCPUARCH enmEntryArch;
185 fat_arch_t Arch;
186 rc = kRdrRead(pRdr, &Arch, sizeof(Arch), off);
187 if (rc)
188 return rc;
189 off += sizeof(Arch);
190
191 if (u32Magic == IMAGE_FAT_SIGNATURE_OE)
192 {
193 Arch.cputype = K_E2E_U32(Arch.cputype);
194 Arch.cpusubtype = K_E2E_U32(Arch.cpusubtype);
195 Arch.offset = K_E2E_U32(Arch.offset);
196 Arch.size = K_E2E_U32(Arch.size);
197 Arch.align = K_E2E_U32(Arch.align);
198 }
199
200 /* Simple validation. */
201 if ( (KLDRFOFF)Arch.offset < offEndFAT
202 || (KLDRFOFF)Arch.offset >= kRdrSize(pRdr)
203 || Arch.align >= 32
204 || Arch.offset & ((KU32_C(1) << Arch.align) - KU32_C(1)))
205 return KLDR_ERR_FAT_INVALID;
206
207 /* deal with the cputype and cpusubtype. (See similar code in kLdrModMachO.c.) */
208 switch (Arch.cputype)
209 {
210 case CPU_TYPE_X86:
211 enmEntryArch = KCPUARCH_X86_32;
212 switch (Arch.cpusubtype)
213 {
214 case CPU_SUBTYPE_I386_ALL:
215 /*case CPU_SUBTYPE_386: ^^ ;*/
216 case CPU_SUBTYPE_486:
217 case CPU_SUBTYPE_486SX:
218 /*case CPU_SUBTYPE_586: vv */
219 case CPU_SUBTYPE_PENT:
220 case CPU_SUBTYPE_PENTPRO:
221 case CPU_SUBTYPE_PENTII_M3:
222 case CPU_SUBTYPE_PENTII_M5:
223 case CPU_SUBTYPE_CELERON:
224 case CPU_SUBTYPE_CELERON_MOBILE:
225 case CPU_SUBTYPE_PENTIUM_3:
226 case CPU_SUBTYPE_PENTIUM_3_M:
227 case CPU_SUBTYPE_PENTIUM_3_XEON:
228 case CPU_SUBTYPE_PENTIUM_M:
229 case CPU_SUBTYPE_PENTIUM_4:
230 case CPU_SUBTYPE_PENTIUM_4_M:
231 case CPU_SUBTYPE_XEON:
232 case CPU_SUBTYPE_XEON_MP:
233 break;
234 default:
235 return KLDR_ERR_FAT_UNSUPPORTED_CPU_SUBTYPE;
236 }
237 break;
238
239 case CPU_TYPE_X86_64:
240 enmEntryArch = KCPUARCH_AMD64;
241 switch (Arch.cpusubtype & ~CPU_SUBTYPE_MASK)
242 {
243 case CPU_SUBTYPE_X86_64_ALL:
244 break;
245 default:
246 return KLDR_ERR_FAT_UNSUPPORTED_CPU_SUBTYPE;
247 }
248 break;
249
250 default:
251 enmCpuArch = KCPUARCH_UNKNOWN;
252 break;
253 }
254
255 /*
256 * Finally the actual image selecting.
257 *
258 * Return immediately on a perfect match. Otherwise continue looking,
259 * if we're none too picky, remember the first image in case we don't
260 * get lucky.
261 */
262 if (enmCpuArch == KCPUARCH_X86_32)
263 {
264 *poffHdr = Arch.offset;
265 return 0;
266 }
267
268 if ( fCpuArchWhatever
269 && rcRet == KLDR_ERR_CPU_ARCH_MISMATCH)
270 {
271 *poffHdr = Arch.offset;
272 rcRet = 0;
273 }
274 }
275
276 return rcRet;
277}
278
279
280/**
281 * Open a executable image from a file provider instance.
282 *
283 * @returns 0 on success and *ppMod pointing to a module instance.
284 * On failure, a non-zero OS specific error code is returned.
285 * @param pRdr The file provider instance to use.
286 * On success, the ownership of the instance is taken by the
287 * module and the caller must not ever touch it again.
288 * (The instance is not closed on failure, the call has to do that.)
289 * @param fFlags Flags, MBZ.
290 * @param enmCpuArch The desired CPU architecture. KCPUARCH_UNKNOWN means
291 * anything goes, but with a preference for the current
292 * host architecture.
293 * @param ppMod Where to store the module handle.
294 */
295int kLdrModOpenFromRdr(PKRDR pRdr, KU32 fFlags, KCPUARCH enmCpuArch, PPKLDRMOD ppMod)
296{
297 union
298 {
299 KU32 u32;
300 KU16 u16;
301 KU16 au16[2];
302 KU8 au8[4];
303 } u;
304 KLDRFOFF offHdr = 0;
305 int rc;
306
307 for (;;)
308 {
309 /*
310 * Try figure out what kind of image this is.
311 * Always read the 'new header' if we encounter MZ.
312 */
313 rc = kRdrRead(pRdr, &u, sizeof(u), offHdr);
314 if (rc)
315 return rc;
316 if ( u.u16 == IMAGE_DOS_SIGNATURE
317 && kRdrSize(pRdr) > sizeof(IMAGE_DOS_HEADER))
318 {
319 rc = kRdrRead(pRdr, &u, sizeof(u.u32), K_OFFSETOF(IMAGE_DOS_HEADER, e_lfanew));
320 if (rc)
321 return rc;
322 if ((KLDRFOFF)u.u32 < kRdrSize(pRdr))
323 {
324 offHdr = u.u32;
325 rc = kRdrRead(pRdr, &u, sizeof(u.u32), offHdr);
326 if (rc)
327 return rc;
328 }
329 else
330 u.u16 = IMAGE_DOS_SIGNATURE;
331 }
332
333 /*
334 * Handle FAT images too here (one only).
335 */
336 if ( ( u.u32 == IMAGE_FAT_SIGNATURE
337 || u.u32 == IMAGE_FAT_SIGNATURE_OE)
338 && offHdr == 0)
339 {
340 rc = kldrModOpenFromRdrSelectImageFromFAT(pRdr, fFlags, enmCpuArch, u.u32, &offHdr);
341 if (rc)
342 return rc;
343 }
344 }
345
346
347 /*
348 * Use the magic to select the appropriate image interpreter head on.
349 */
350 if (u.u16 == IMAGE_DOS_SIGNATURE)
351 rc = KLDR_ERR_MZ_NOT_SUPPORTED;
352 else if (u.u16 == IMAGE_NE_SIGNATURE)
353 rc = KLDR_ERR_NE_NOT_SUPPORTED;
354 else if (u.u16 == IMAGE_LX_SIGNATURE)
355 rc = g_kLdrModLXOps.pfnCreate(&g_kLdrModLXOps, pRdr, fFlags, enmCpuArch, offHdr, ppMod);
356 else if (u.u16 == IMAGE_LE_SIGNATURE)
357 rc = KLDR_ERR_LE_NOT_SUPPORTED;
358 else if (u.u32 == IMAGE_NT_SIGNATURE)
359 rc = g_kLdrModPEOps.pfnCreate(&g_kLdrModPEOps, pRdr, fFlags, enmCpuArch, offHdr, ppMod);
360 else if ( u.u32 == IMAGE_MACHO32_SIGNATURE
361 || u.u32 == IMAGE_MACHO32_SIGNATURE_OE
362 || u.u32 == IMAGE_MACHO64_SIGNATURE
363 || u.u32 == IMAGE_MACHO64_SIGNATURE_OE)
364 rc = g_kLdrModMachOOps.pfnCreate(&g_kLdrModMachOOps, pRdr, fFlags, enmCpuArch, offHdr, ppMod);
365 else if (u.u32 == IMAGE_ELF_SIGNATURE)
366 rc = KLDR_ERR_ELF_NOT_SUPPORTED;
367 else
368 rc = KLDR_ERR_UNKNOWN_FORMAT;
369
370 /*
371 * If no head on hit, let each interpreter have a go.
372 */
373 if (rc)
374 {
375 PCKLDRMODOPS pOps;
376 for (pOps = g_pModInterpreterHead; pOps; pOps = pOps->pNext)
377 {
378 int rc2 = pOps->pfnCreate(pOps, pRdr, fFlags, enmCpuArch, offHdr, ppMod);
379 if (!rc2)
380 return rc;
381 }
382 *ppMod = NULL;
383 }
384 return rc;
385}
386
387
388/**
389 * Closes an open module.
390 *
391 * The caller is responsible for calling kLdrModUnmap() and kLdrFreeTLS()
392 * before closing the module.
393 *
394 * @returns 0 on success, non-zero on failure. The module instance state
395 * is unknown on failure, it's best not to touch it.
396 * @param pMod The module.
397 */
398int kLdrModClose(PKLDRMOD pMod)
399{
400 KLDRMOD_VALIDATE(pMod);
401 return pMod->pOps->pfnDestroy(pMod);
402}
403
404
405/**
406 * Queries a symbol by name or ordinal number.
407 *
408 * @returns 0 and *puValue and *pfKind on success.
409 * KLDR_ERR_SYMBOL_NOT_FOUND is returned if the symbol wasn't found.
410 * Other failures could stem from bad executable format failures,
411 * read failure in case pvBits isn't specified and no mapping should be used.
412 * @param pMod The module.
413 * @param pvBits Optional pointer to bits returned by kLdrModGetBits() currently located at BaseAddress.
414 * This can be used by some module interpreters to reduce memory consumption.
415 * @param BaseAddress The module base address to use when calculating the symbol value.
416 * There are two special values that can be used:
417 * KLDRMOD_BASEADDRESS_LINK and KLDRMOD_BASEADDRESS_MAP.
418 * @param iSymbol The symbol ordinal. (optional)
419 * @param pchSymbol The symbol name. (optional)
420 * Important, this doesn't have to be a null-terminated string.
421 * @param cchSymbol The length of the symbol name.
422 * @param pszVersion The symbol version. NULL if not versioned.
423 * @param pfnGetForwarder The callback to use when resolving a forwarder symbol. This is optional
424 * and if not specified KLDR_ERR_FORWARDER is returned instead.
425 * @param pvUser The user argument for the pfnGetForwarder callback.
426 * @param puValue Where to store the symbol value. (optional)
427 * @param pfKind On input one of the KLDRSYMKIND_REQ_* #defines.
428 * On output the symbol kind. (optional)
429 */
430int kLdrModQuerySymbol(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, KU32 iSymbol,
431 const char *pchSymbol, KSIZE cchSymbol, const char *pszVersion,
432 PFNKLDRMODGETIMPORT pfnGetForwarder, void *pvUser, PKLDRADDR puValue, KU32 *pfKind)
433{
434 KLDRMOD_VALIDATE(pMod);
435 if (!puValue && !pfKind)
436 return KERR_INVALID_PARAMETER;
437 if (puValue)
438 *puValue = 0;
439 if (pfKind)
440 K_VALIDATE_FLAGS(*pfKind, KLDRSYMKIND_REQ_SEGMENTED);
441 return pMod->pOps->pfnQuerySymbol(pMod, pvBits, BaseAddress, iSymbol, pchSymbol, cchSymbol, pszVersion,
442 pfnGetForwarder, pvUser, puValue, pfKind);
443}
444
445
446/**
447 * Enumerate the symbols in the module.
448 *
449 * @returns 0 on success and non-zero a status code on failure.
450 * @param pMod The module which symbols should be enumerated.
451 * @param pvBits Optional pointer to bits returned by kLdrModGetBits() currently located at BaseAddress.
452 * This can be used by some module interpreters to reduce memory consumption.
453 * @param BaseAddress The module base address to use when calculating the symbol values.
454 * There are two special values that could be can:
455 * KLDRMOD_BASEADDRESS_LINK and KLDRMOD_BASEADDRESS_MAP.
456 * @param fFlags The enumeration flags. A combination of the KLDRMOD_ENUM_SYMS_FLAGS_* \#defines.
457 * @param pfnCallback The enumeration callback function.
458 * @param pvUser The user argument to the callback function.
459 */
460int kLdrModEnumSymbols(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, KU32 fFlags,
461 PFNKLDRMODENUMSYMS pfnCallback, void *pvUser)
462{
463 KLDRMOD_VALIDATE(pMod);
464 K_VALIDATE_FLAGS(fFlags, KLDRMOD_ENUM_SYMS_FLAGS_ALL);
465 return pMod->pOps->pfnEnumSymbols(pMod, pvBits, BaseAddress, fFlags, pfnCallback, pvUser);
466}
467
468
469/**
470 * Get the name of an import module by ordinal number.
471 *
472 * @returns 0 and name in pszName on success.
473 * On buffer overruns KERR_BUFFER_OVERFLOW will be returned.
474 * On other failures and appropriate error code is returned.
475 * @param pMod The module.
476 * @param pvBits Optional pointer to bits returned by kLdrModGetBits().
477 * This can be used by some module interpreters to reduce memory consumption.
478 * @param iImport The import module ordinal number.
479 * @param pszName Where to store the name.
480 * @param cchName The size of the name buffer.
481 */
482int kLdrModGetImport(PKLDRMOD pMod, const void *pvBits, KU32 iImport, char *pszName, KSIZE cchName)
483{
484 KLDRMOD_VALIDATE(pMod);
485 return pMod->pOps->pfnGetImport(pMod, pvBits, iImport, pszName, cchName);
486}
487
488
489/**
490 * Get the number of import modules.
491 *
492 * @returns The number of import modules. -1 if something really bad happens.
493 * @param pMod The module.
494 * @param pvBits Optional pointer to bits returned by kLdrModGetBits().
495 * This can be used by some module interpreters to reduce memory consumption.
496 */
497KI32 kLdrModNumberOfImports(PKLDRMOD pMod, const void *pvBits)
498{
499 KLDRMOD_VALIDATE(pMod);
500 return pMod->pOps->pfnNumberOfImports(pMod, pvBits);
501}
502
503
504/**
505 * Checks if this module can be executed by the specified arch+cpu.
506 *
507 * @returns 0 if it can, KCPU_ERR_ARCH_CPU_NOT_COMPATIBLE if it can't.
508 * Other failures may occur and cause other return values.
509 * @param pMod The module.
510 * @param pvBits Optional pointer to bits returned by kLdrModGetBits().
511 * This can be used by some module interpreters to reduce memory consumption.
512 */
513int kLdrModCanExecuteOn(PKLDRMOD pMod, const void *pvBits, KCPUARCH enmArch, KCPU enmCpu)
514{
515 KLDRMOD_VALIDATE(pMod);
516 if (pMod->pOps->pfnCanExecuteOn)
517 return pMod->pOps->pfnCanExecuteOn(pMod, pvBits, enmArch, enmCpu);
518 return kCpuCompare(pMod->enmArch, pMod->enmCpu, enmArch, enmCpu);
519}
520
521
522/**
523 * Gets the image stack info.
524 *
525 * @returns 0 on success, non-zero on failure.
526 * @param pMod
527 * @param pvBits Optional pointer to bits returned by kLdrModGetBits() currently located at BaseAddress.
528 * This can be used by some module interpreters to reduce memory consumption.
529 * @param BaseAddress The module base address to use when calculating the stack address.
530 * There are two special values that can be used:
531 * KLDRMOD_BASEADDRESS_LINK and KLDRMOD_BASEADDRESS_MAP.
532 * @param pStackInfo The stack information.
533 */
534int kLdrModGetStackInfo(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, PKLDRSTACKINFO pStackInfo)
535{
536 KLDRMOD_VALIDATE(pMod);
537 return pMod->pOps->pfnGetStackInfo(pMod, pvBits, BaseAddress, pStackInfo);
538}
539
540
541/**
542 * Queries the main entrypoint of the module.
543 *
544 * Only executable are supposed to have an main entrypoint, though some object and DLL
545 * formats will also allow this.
546 *
547 * @returns 0 and *pMainEPAddress on success. Non-zero status code on failure.
548 * @param pMod The module.
549 * @param pvBits Optional pointer to bits returned by kLdrModGetBits() currently located at BaseAddress.
550 * This can be used by some module interpreters to reduce memory consumption.
551 * @param BaseAddress The module base address to use when calculating the entrypoint address.
552 * There are two special values that can be used:
553 * KLDRMOD_BASEADDRESS_LINK and KLDRMOD_BASEADDRESS_MAP.
554 * @param pMainEPAddress Where to store the entry point address.
555 */
556int kLdrModQueryMainEntrypoint(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, PKLDRADDR pMainEPAddress)
557{
558 KLDRMOD_VALIDATE(pMod);
559 *pMainEPAddress = 0;
560 return pMod->pOps->pfnQueryMainEntrypoint(pMod, pvBits, BaseAddress, pMainEPAddress);
561}
562
563
564/**
565 * Queries info about a resource.
566 *
567 * If there are multiple resources matching the criteria, the best or
568 * first match will be return.
569 *
570 *
571 * @returns 0 on success.
572 * @returns Whatever non-zero status returned by pfnCallback (enumeration was stopped).
573 * @returns non-zero kLdr or native status code on failure.
574 *
575 * @param pMod The module.
576 * @param pvBits Optional pointer to bits returned by kLdrModGetBits() currently located at BaseAddress.
577 * This can be used by some module interpreters to reduce memory consumption.
578 * @param BaseAddress The module base address to use when calculating the resource addresses.
579 * There are two special values that can be used:
580 * KLDRMOD_BASEADDRESS_LINK and KLDRMOD_BASEADDRESS_MAP.
581 * @param idType The resource type id to match if not NIL_KLDRMOD_RSRC_TYPE_ID.
582 * @param pszType The resource type name to match if no NULL.
583 * @param idName The resource name id to match if not NIL_KLDRMOD_RSRC_NAME_ID.
584 * @param pszName The resource name to match if not NULL.
585 * @param idLang The language id to match.
586 * @param pfnCallback The callback function.
587 * @param pvUser The user argument for the callback.
588 */
589int kLdrModQueryResource(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, KU32 idType, const char *pszType,
590 KU32 idName, const char *pszName, KU32 idLang, PKLDRADDR pAddrRsrc, KSIZE *pcbRsrc)
591{
592 KLDRMOD_VALIDATE(pMod);
593 if (!pAddrRsrc && !pcbRsrc)
594 return KERR_INVALID_PARAMETER;
595 if (pAddrRsrc)
596 *pAddrRsrc = NIL_KLDRADDR;
597 if (pcbRsrc)
598 *pcbRsrc = 0;
599 return pMod->pOps->pfnQueryResource(pMod, pvBits, BaseAddress, idType, pszType, idName, pszName, idLang, pAddrRsrc, pcbRsrc);
600}
601
602
603/**
604 * Enumerates the resources matching the specfied criteria.
605 *
606 *
607 * @returns 0 on success.
608 * @returns Whatever non-zero status returned by pfnCallback (enumeration was stopped).
609 * @returns non-zero kLdr or native status code on failure.
610 *
611 * @param pMod The module.
612 * @param pvBits Optional pointer to bits returned by kLdrModGetBits() currently located at BaseAddress.
613 * This can be used by some module interpreters to reduce memory consumption.
614 * @param BaseAddress The module base address to use when calculating the resource addresses.
615 * There are two special values that can be used:
616 * KLDRMOD_BASEADDRESS_LINK and KLDRMOD_BASEADDRESS_MAP.
617 * @param idType The resource type id to match if not NIL_KLDRMOD_RSRC_TYPE_ID.
618 * @param pszType The resource type name to match if no NULL.
619 * @param idName The resource name id to match if not NIL_KLDRMOD_RSRC_NAME_ID.
620 * @param pszName The resource name to match if not NULL.
621 * @param idLang The language id to match.
622 * @param pfnCallback The callback function.
623 * @param pvUser The user argument for the callback.
624 */
625int kLdrModEnumResources(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, KU32 idType, const char *pszType,
626 KU32 idName, const char *pszName, KU32 idLang, PFNKLDRENUMRSRC pfnCallback, void *pvUser)
627{
628 KLDRMOD_VALIDATE(pMod);
629 return pMod->pOps->pfnEnumResources(pMod, pvBits, BaseAddress, idType, pszType, idName, pszName, idLang, pfnCallback, pvUser);
630}
631
632
633/**
634 * Enumerate the debug info formats contained in the executable image.
635 *
636 * @returns 0 on success, non-zero OS or kLdr status code on failure, or non-zero callback status.
637 * @param pMod The module.
638 * @param pvBits Optional pointer to bits returned by kLdrModGetBits().
639 * This can be used by some module interpreters to reduce memory consumption.
640 * @param pfnCallback The callback function.
641 * @param pvUser The user argument.
642 * @see pg_kDbg for the debug info reader.
643 */
644int kLdrModEnumDbgInfo(PKLDRMOD pMod, const void *pvBits, PFNKLDRENUMDBG pfnCallback, void *pvUser)
645{
646 KLDRMOD_VALIDATE(pMod);
647 return pMod->pOps->pfnEnumDbgInfo(pMod, pvBits, pfnCallback, pvUser);
648}
649
650
651/**
652 * Checks if the module has debug info embedded or otherwise associated with it.
653 *
654 * @returns 0 if it has debug info, KLDR_ERR_NO_DEBUG_INFO if no debug info,
655 * and non-zero OS or kLdr status code on failure.
656 * @param pMod The module.
657 * @param pvBits Optional pointer to bits returned by kLdrModGetBits().
658 * This can be used by some module interpreters to reduce memory consumption.
659 */
660int kLdrModHasDbgInfo(PKLDRMOD pMod, const void *pvBits)
661{
662 KLDRMOD_VALIDATE(pMod);
663 return pMod->pOps->pfnHasDbgInfo(pMod, pvBits);
664}
665
666
667/**
668 * May free up some resources held by the module.
669 *
670 * @todo define exactly what it possible to do after this call.
671 *
672 * @returns 0 on success, KLDR_ERR_* on failure.
673 * @param pMod The module.
674 */
675int kLdrModMostlyDone(PKLDRMOD pMod)
676{
677 KLDRMOD_VALIDATE(pMod);
678 return pMod->pOps->pfnMostlyDone(pMod);
679}
680
681
682/**
683 * Maps the module into the memory of the caller.
684 *
685 * On success the actual addresses for the segments can be found in MapAddress
686 * member of each segment in the segment array.
687 *
688 * @returns 0 on success, non-zero OS or kLdr status code on failure.
689 * @param pMod The module to be mapped.
690 * @remark kLdr only supports one mapping at a time of a module.
691 */
692int kLdrModMap(PKLDRMOD pMod)
693{
694 KLDRMOD_VALIDATE(pMod);
695 return pMod->pOps->pfnMap(pMod);
696}
697
698
699/**
700 * Unmaps a module previously mapped by kLdrModMap().
701 *
702 * @returns 0 on success, non-zero OS or kLdr status code on failure.
703 * @param pMod The module to unmap.
704 */
705int kLdrModUnmap(PKLDRMOD pMod)
706{
707 KLDRMOD_VALIDATE(pMod);
708 return pMod->pOps->pfnUnmap(pMod);
709}
710
711
712/**
713 * Allocates Thread Local Storage for module mapped by kLdrModMap().
714 *
715 * Calling kLdrModAllocTLS() more than once without calling kLdrModFreeTLS()
716 * between each invocation is not supported.
717 *
718 * @returns 0 on success, non-zero OS or kLdr status code on failure.
719 * @param pMod The module.
720 */
721int kLdrModAllocTLS(PKLDRMOD pMod)
722{
723 KLDRMOD_VALIDATE(pMod);
724 return pMod->pOps->pfnAllocTLS(pMod);
725}
726
727
728/**
729 * Frees Thread Local Storage previously allocated by kLdrModAllocTLS().
730 *
731 * The caller is responsible for only calling kLdrModFreeTLS() once
732 * after calling kLdrModAllocTLS().
733 *
734 * @returns 0 on success, non-zero OS or kLdr status code on failure.
735 * @param pMod The module.
736 */
737void kLdrModFreeTLS(PKLDRMOD pMod)
738{
739 KLDRMOD_VALIDATE_VOID(pMod);
740 pMod->pOps->pfnFreeTLS(pMod);
741}
742
743
744/**
745 * Reloads all dirty pages in a module previously mapped by kLdrModMap().
746 *
747 * The module interpreter may omit code pages if it can safely apply code
748 * fixups again in a subsequent kLdrModFixupMapping() call.
749 *
750 * The caller is responsible for freeing TLS before calling this function.
751 *
752 * @returns 0 on success, non-zero OS or kLdr status code on failure.
753 * @param pMod The module.
754 */
755int kLdrModReload(PKLDRMOD pMod)
756{
757 KLDRMOD_VALIDATE(pMod);
758 return pMod->pOps->pfnReload(pMod);
759}
760
761
762/**
763 * Fixup the mapping made by kLdrModMap().
764 *
765 * The caller is only responsible for not calling this function more than
766 * once without doing kLDrModReload() inbetween.
767 *
768 * @returns 0 on success, non-zero OS or kLdr status code on failure.
769 * @param pMod The module.
770 * @param pfnGetImport The callback for resolving external (imported) symbols.
771 * @param pvUser The callback user argument.
772 */
773int kLdrModFixupMapping(PKLDRMOD pMod, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
774{
775 KLDRMOD_VALIDATE(pMod);
776 return pMod->pOps->pfnFixupMapping(pMod, pfnGetImport, pvUser);
777}
778
779
780/**
781 * Call the module initializiation function of a mapped module (if any).
782 *
783 * @returns 0 on success or no init function, non-zero on init function failure or invalid pMod.
784 * @param pMod The module.
785 * @param uHandle The module handle to use if any of the init functions requires the module handle.
786 */
787int kLdrModCallInit(PKLDRMOD pMod, KUPTR uHandle)
788{
789 KLDRMOD_VALIDATE(pMod);
790 return pMod->pOps->pfnCallInit(pMod, uHandle);
791}
792
793
794/**
795 * Call the module termination function of a mapped module (if any).
796 *
797 * @returns 0 on success or no term function, non-zero on invalid pMod.
798 * @param pMod The module.
799 * @param uHandle The module handle to use if any of the term functions requires the module handle.
800 *
801 * @remark Termination function failure will be ignored by the module interpreter.
802 */
803int kLdrModCallTerm(PKLDRMOD pMod, KUPTR uHandle)
804{
805 KLDRMOD_VALIDATE(pMod);
806 return pMod->pOps->pfnCallTerm(pMod, uHandle);
807}
808
809
810/**
811 * Call the thread attach or detach function of a mapped module (if any).
812 *
813 * Any per-thread TLS initialization/termination will have to be done at this time too.
814 *
815 * @returns 0 on success or no attach/detach function, non-zero on attach failure or invalid pMod.
816 * @param pMod The module.
817 * @param uHandle The module handle to use if any of the thread attach/detach functions
818 * requires the module handle.
819 *
820 * @remark Detach function failure will be ignored by the module interpreter.
821 */
822int kLdrModCallThread(PKLDRMOD pMod, KUPTR uHandle, unsigned fAttachingOrDetaching)
823{
824 KLDRMOD_VALIDATE(pMod);
825 K_VALIDATE_FLAGS(fAttachingOrDetaching, 1);
826 return pMod->pOps->pfnCallThread(pMod, uHandle, fAttachingOrDetaching);
827}
828
829
830/**
831 * Get the size of the mapped module.
832 *
833 * @returns The size of the mapped module (in bytes).
834 * @param pMod The module.
835 */
836KLDRADDR kLdrModSize(PKLDRMOD pMod)
837{
838 KLDRMOD_VALIDATE_EX(pMod, 0);
839 return pMod->pOps->pfnSize(pMod);
840}
841
842
843/**
844 * Gets the module bits.
845 *
846 * The module interpreter will fill a mapping allocated by the caller with the
847 * module bits reallocated to the specified address.
848 *
849 * @returns 0 on succes, non-zero OS or kLdr status code on failure.
850 * @param pMod The module.
851 * @param pvBits Where to put the bits.
852 * @param BaseAddress The base address that should correspond to the first byte in pvBits
853 * upon return.
854 * @param pfnGetImport The callback ufor resolving external (imported) symbols.
855 * @param pvUser The callback user argument.
856 */
857int kLdrModGetBits(PKLDRMOD pMod, void *pvBits, KLDRADDR BaseAddress, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
858{
859 KLDRMOD_VALIDATE(pMod);
860 return pMod->pOps->pfnGetBits(pMod, pvBits, BaseAddress, pfnGetImport, pvUser);
861}
862
863
864/**
865 * Relocates the module bits previously obtained by kLdrModGetBits().
866 *
867 * @returns 0 on succes, non-zero OS or kLdr status code on failure.
868 * @param pMod The module.
869 * @param pvBits Where to put the bits.
870 * @param NewBaseAddress The new base address.
871 * @param OldBaseAddress The old base address (i.e. the one specified to kLdrModGetBits() or as
872 * NewBaseAddressto the previous kLdrModRelocateBits() call).
873 * @param pfnGetImport The callback ufor resolving external (imported) symbols.
874 * @param pvUser The callback user argument.
875 */
876int kLdrModRelocateBits(PKLDRMOD pMod, void *pvBits, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress,
877 PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
878{
879 KLDRMOD_VALIDATE(pMod);
880 return pMod->pOps->pfnRelocateBits(pMod, pvBits, NewBaseAddress, OldBaseAddress, pfnGetImport, pvUser);
881}
882
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