source: trunk/kLdr/kLdrMod.c@ 2854

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

Hacking away on the PE module interpreter.

  • Property svn:keywords set to Id
File size: 22.0 KB
Line 
1/* $Id: kLdrMod.c 2854 2006-11-03 03:39:12Z bird $ */
2/** @file
3 *
4 * kLdr - The Module Interpreter.
5 *
6 * Copyright (c) 2006 knut st. osmundsen <bird-kbuild-src@anduin.net>
7 *
8 *
9 * This file is part of kLdr.
10 *
11 * kLdr is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * kLdr is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with kLdr; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 *
25 */
26
27
28/*******************************************************************************
29* Header Files *
30*******************************************************************************/
31#include <kLdr.h>
32#include "kLdrHlp.h"
33#include "kLdrInternal.h"
34#include "kLdrModMZ.h"
35#if 1 /* testing headers */
36# include "kLdrModPE.h"
37# include "kLdrModLX.h"
38# include "kLdrModELF32.h"
39# include "kLdrModELF64.h"
40#endif
41
42
43/*******************************************************************************
44* Defined Constants And Macros *
45*******************************************************************************/
46/** @def KLDRMOD_STRICT
47 * Define KLDRMOD_STRICT to enabled strict checks in KLDRMOD. */
48#define KLDRMOD_STRICT 1
49
50/** @def KLDRMOD_ASSERT
51 * Assert that an expression is true when KLDR_STRICT is defined.
52 */
53#ifdef KLDRMOD_STRICT
54# define KLDRMOD_ASSERT(expr) kldrHlpAssert(expr)
55#else
56# define KLDRMOD_ASSERT(expr) do {} while (0)
57#endif
58
59/** Return / crash validation of a module argument. */
60#define KLDRMOD_VALIDATE_EX(pMod, rc) \
61 do { \
62 if ( (pMod)->u32Magic != KLDRMOD_MAGIC \
63 || (pMod)->pOps == NULL \
64 )\
65 { \
66 return (rc); \
67 } \
68 } while (0)
69
70/** Return / crash validation of a module argument. */
71#define KLDRMOD_VALIDATE(pMod) \
72 KLDRMOD_VALIDATE_EX(pMod, KLDR_ERR_INVALID_PARAMETER)
73
74/** Return / crash validation of a module argument. */
75#define KLDRMOD_VALIDATE_VOID(pMod) \
76 do { \
77 if ( (pMod)->u32Magic != KLDRMOD_MAGIC \
78 || (pMod)->pOps == NULL \
79 )\
80 { \
81 return; \
82 } \
83 } while (0)
84
85
86/*******************************************************************************
87* Global Variables *
88*******************************************************************************/
89/** The list of module interpreters. */
90static PCKLDRMODOPS g_pModInterpreterHead = NULL;
91
92
93
94/*******************************************************************************
95* Internal Functions *
96*******************************************************************************/
97
98
99
100/**
101 * Open a executable image by file name.
102 *
103 * @returns 0 on success and *ppMod pointing to a module instance.
104 * On failure, a non-zero OS specific error code is returned.
105 * @param pszFilename The filename to open.
106 * @param ppMod Where to store the module handle.
107 */
108int kLdrModOpen(const char *pszFilename, PPKLDRMOD ppMod)
109{
110 /*
111 * Open the file using a bit provider.
112 */
113 PKLDRRDR pRdr;
114 int rc = kLdrRdrOpen(&pRdr, pszFilename);
115 if (!rc)
116 {
117 rc = kLdrModOpenFromRdr(pRdr, ppMod);
118 if (!rc)
119 return 0;
120 kLdrRdrClose(pRdr);
121 }
122 return rc;
123}
124
125
126/**
127 * Open a executable image from a file provider instance.
128 *
129 * @returns 0 on success and *ppMod pointing to a module instance.
130 * On failure, a non-zero OS specific error code is returned.
131 * @param pRdr The file provider instance to use.
132 * On success, the ownership of the instance is taken by the
133 * module and the caller must not ever touch it again.
134 * (The instance is not closed on failure, the call has to do that.)
135 * @param ppMod Where to store the module handle.
136 */
137int kLdrModOpenFromRdr(PKLDRRDR pRdr, PPKLDRMOD ppMod)
138{
139 union
140 {
141 uint32_t u32;
142 uint16_t u16;
143 uint16_t au16[2];
144 uint8_t au8[4];
145 } u;
146 off_t offHdr = 0;
147 int rc;
148
149 /*
150 * Try figure out what kind of image this is.
151 * Always read the 'new header' if we encounter MZ.
152 */
153 rc = kLdrRdrRead(pRdr, &u, sizeof(u), 0);
154 if (rc)
155 return rc;
156 if ( u.u16 == IMAGE_DOS_SIGNATURE
157 && kLdrRdrSize(pRdr) > sizeof(IMAGE_DOS_HEADER))
158 {
159 rc = kLdrRdrRead(pRdr, &u, sizeof(u.u32), KLDR_OFFSETOF(IMAGE_DOS_HEADER, e_lfanew));
160 if (rc)
161 return rc;
162 if ((off_t)u.u32 < kLdrRdrSize(pRdr))
163 {
164 offHdr = u.u32;
165 rc = kLdrRdrRead(pRdr, &u, sizeof(u.u32), offHdr);
166 if (rc)
167 return rc;
168 }
169 else
170 u.u16 = IMAGE_DOS_SIGNATURE;
171 }
172
173 /*
174 * Use the magic to select the appropriate image interpreter head on.
175 */
176 if (u.u16 == IMAGE_DOS_SIGNATURE)
177 rc = KLDR_ERR_MZ_NOT_SUPPORTED;
178 else if (u.u16 == IMAGE_NE_SIGNATURE)
179 rc = KLDR_ERR_NE_NOT_SUPPORTED;
180 else if (u.u16 == IMAGE_LX_SIGNATURE)
181 rc = KLDR_ERR_LX_NOT_SUPPORTED;
182 else if (u.u16 == IMAGE_LE_SIGNATURE)
183 rc = KLDR_ERR_LE_NOT_SUPPORTED;
184 else if (u.u32 == IMAGE_NT_SIGNATURE)
185 rc = KLDR_ERR_PE_NOT_SUPPORTED;
186 else if (u.u32 == IMAGE_ELF_SIGNATURE)
187 rc = KLDR_ERR_ELF_NOT_SUPPORTED;
188 else
189 rc = KLDR_ERR_UNKNOWN_FORMAT;
190
191 /*
192 * If no head on hit, let each interpreter have a go.
193 */
194 if (rc)
195 {
196 PCKLDRMODOPS pOps;
197 for (pOps = g_pModInterpreterHead; pOps; pOps = pOps->pNext)
198 {
199 int rc2 = pOps->pfnCreate(pOps, pRdr, offHdr, ppMod);
200 if (!rc2)
201 return rc;
202 }
203 *ppMod = NULL;
204 }
205 return rc;
206}
207
208
209/**
210 * Open a executable image using the native loader (if any).
211 *
212 * @returns 0 on success and *ppMod pointing to a module instance.
213 * On failure, a non-zero OS specific error code is returned.
214 * @param pszFilename The filename to open.
215 * @param ppMod Where to store the module handle.
216 */
217int kLdrModOpenNative(const char *pszFilename, PPKLDRMOD ppMod)
218{
219#ifdef __OS2__
220
221 //DosLoadModule()
222#elif defined(__WIN__)
223
224#else
225# error "Port me"
226#endif
227 return -1;
228}
229
230
231
232/**
233 * Closes an open module.
234 *
235 * The caller is responsible for calling kLdrModUnmap() and kLdrFreeTLS()
236 * before closing the module.
237 *
238 * @returns 0 on success, non-zero on failure. The module instance state
239 * is unknown on failure, it's best not to touch it.
240 * @param pMod The module.
241 */
242int kLdrModClose(PKLDRMOD pMod)
243{
244 KLDRMOD_VALIDATE(pMod);
245 return pMod->pOps->pfnDestroy(pMod);
246}
247
248
249/**
250 * Queries a symbol by name or ordinal number.
251 *
252 * @returns 0 and *puValue and *pfKind on success.
253 * KLDR_ERR_SYMBOL_NOT_FOUND is returned if the symbol wasn't found.
254 * Other failures could stem from bad executable format failures,
255 * read failure in case pvBits isn't specified and no mapping should be used.
256 * @param pMod The module.
257 * @param pvBits Optional pointer to bits returned by kLdrModGetBits() currently located at BaseAddress.
258 * This can be used by some module interpreters to reduce memory consumption.
259 * @param BaseAddress The module base address to use when calculating the symbol value.
260 * There are two special values that can be used:
261 * KLDRMOD_BASEADDRESS_LINK and KLDRMOD_BASEADDRESS_MAP.
262 * @param uSymbol The symbol ordinal. (optional)
263 * @param pszSymbol The symbol name. (optional)
264 * @param pfnGetForwarder The callback to use when resolving a forwarder symbol. This is optional
265 * and if not specified KLDR_ERR_FORWARDER is returned instead.
266 * @param pvUser The user argument for the pfnGetForwarder callback.
267 * @param puValue Where to store the symbol value. (optional)
268 * @param pfKind Where to store the symbol kind. (optional)
269 */
270int kLdrModQuerySymbol(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, uint32_t uSymbol,
271 const char *pszSymbol, PFNKLDRMODGETIMPORT pfnGetForwarder, void *pvUser,
272 PKLDRADDR puValue, uint32_t *pfKind)
273{
274 KLDRMOD_VALIDATE(pMod);
275 if (!puValue && !pfKind)
276 return KLDR_ERR_INVALID_PARAMETER;
277 if (puValue)
278 *puValue = 0;
279 if (pfKind)
280 *pfKind = 0;
281 return pMod->pOps->pfnQuerySymbol(pMod, pvBits, BaseAddress, uSymbol, pszSymbol, pfnGetForwarder, pvUser, puValue, pfKind);
282}
283
284
285/**
286 * Enumerate the symbols in the module.
287 *
288 * @returns 0 on success and non-zero a status code on failure.
289 * @param pMod The module which symbols should be enumerated.
290 * @param pvBits Optional pointer to bits returned by kLdrModGetBits() currently located at BaseAddress.
291 * This can be used by some module interpreters to reduce memory consumption.
292 * @param BaseAddress The module base address to use when calculating the symbol values.
293 * There are two special values that could be can:
294 * KLDRMOD_BASEADDRESS_LINK and KLDRMOD_BASEADDRESS_MAP.
295 * @param fFlags The enumeration flags. A combination of the KLDRMOD_ENUM_SYMS_FLAGS_* \#defines.
296 * @param pfnCallback The enumeration callback function.
297 * @param pvUser The user argument to the callback function.
298 */
299int kLdrModEnumSymbols(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, uint32_t fFlags,
300 PFNKLDRMODENUMSYMS pfnCallback, void *pvUser)
301{
302 KLDRMOD_VALIDATE(pMod);
303 KLDRHLP_VALIDATE_FLAGS(fFlags, KLDRMOD_ENUM_SYMS_FLAGS_ALL);
304 return pMod->pOps->pfnEnumSymbols(pMod, pvBits, BaseAddress, fFlags, pfnCallback, pvUser);
305}
306
307
308/**
309 * Get the name of an import module by ordinal number.
310 *
311 * @returns 0 and name in pszName on success.
312 * On buffer overruns KLDR_ERR_BUFFER_OVERFLOW will be returned.
313 * On other failures and appropriate error code is returned.
314 * @param pMod The module.
315 * @param pvBits Optional pointer to bits returned by kLdrModGetBits().
316 * This can be used by some module interpreters to reduce memory consumption.
317 * @param iImport The import module ordinal number.
318 * @param pszName Where to store the name.
319 * @param cchName The size of the name buffer.
320 */
321int kLdrModGetImport(PKLDRMOD pMod, void *pvBits, uint32_t iImport, const char *pszName, size_t cchName)
322{
323 KLDRMOD_VALIDATE(pMod);
324 return pMod->pOps->pfnGetImport(pMod, pvBits, iImport, pszName, cchName);
325}
326
327
328/**
329 * Get the number of import modules.
330 *
331 * @returns The number of import modules. -1 if something really bad happens.
332 * @param pMod The module.
333 * @param pvBits Optional pointer to bits returned by kLdrModGetBits().
334 * This can be used by some module interpreters to reduce memory consumption.
335 */
336int32_t kLdrModNumberOfImports(PKLDRMOD pMod, void *pvBits)
337{
338 KLDRMOD_VALIDATE(pMod);
339 return pMod->pOps->pfnNumberOfImports(pMod, pvBits);
340}
341
342
343/**
344 * Checks if this module can be executed by the specified arch+cpu.
345 *
346 * @returns 0 if it can, KLDR_ERR_ARCH_CPU_NOT_COMPATIBLE if it can't.
347 * Other failures may occur and cause other return values.
348 * @param pMod The module.
349 * @param pvBits Optional pointer to bits returned by kLdrModGetBits().
350 * This can be used by some module interpreters to reduce memory consumption.
351 */
352int kLdrModCanExecuteOn(PKLDRMOD pMod, void *pvBits, KLDRARCH enmArch, KLDRCPU enmCpu)
353{
354 KLDRMOD_VALIDATE(pMod);
355 return pMod->pOps->pfnCanExecuteOn(pMod, pvBits, enmArch, enmCpu);
356}
357
358
359/**
360 * Gets the image stack info.
361 *
362 * @returns 0 on success, non-zero on failure.
363 * @param pMod
364 * @param pvBits Optional pointer to bits returned by kLdrModGetBits() currently located at BaseAddress.
365 * This can be used by some module interpreters to reduce memory consumption.
366 * @param BaseAddress The module base address to use when calculating the stack address.
367 * There are two special values that can be used:
368 * KLDRMOD_BASEADDRESS_LINK and KLDRMOD_BASEADDRESS_MAP.
369 * @param pStackInfo The stack information.
370 */
371int kLdrModGetStackInfo(PKLDRMOD pMod, void *pvBits, KLDRADDR BaseAddress, PKLDRSTACKINFO pStackInfo)
372{
373 KLDRMOD_VALIDATE(pMod);
374 return pMod->pOps->pfnGetStackInfo(pMod, pvBits, BaseAddress, pStackInfo);
375}
376
377
378/**
379 * Queries the main entrypoint of the module.
380 *
381 * Only executable are supposed to have an main entrypoint, though some object and DLL
382 * formats will also allow this.
383 *
384 * @returns 0 and *pMainEPAddress on success. Non-zero status code on failure.
385 * @param pMod The module.
386 * @param pvBits Optional pointer to bits returned by kLdrModGetBits() currently located at BaseAddress.
387 * This can be used by some module interpreters to reduce memory consumption.
388 * @param BaseAddress The module base address to use when calculating the entrypoint address.
389 * There are two special values that can be used:
390 * KLDRMOD_BASEADDRESS_LINK and KLDRMOD_BASEADDRESS_MAP.
391 * @param pMainEPAddress Where to store the entry point address.
392 */
393int kLdrModQueryMainEntrypoint(PKLDRMOD pMod, void *pvBits, KLDRADDR BaseAddress, PKLDRADDR pMainEPAddress)
394{
395 KLDRMOD_VALIDATE(pMod);
396 *pMainEPAddress = 0;
397 return pMod->pOps->pfnQueryMainEntrypoint(pMod, pvBits, BaseAddress, pMainEPAddress);
398}
399
400
401/**
402 * Enumerate the debug info formats contained in the executable image.
403 *
404 * @returns 0 on success, non-zero OS or kLdr status code on failure, or non-zero callback status.
405 * @param pMod The module.
406 * @param pvBits Optional pointer to bits returned by kLdrModGetBits().
407 * This can be used by some module interpreters to reduce memory consumption.
408 * @param pfnCallback The callback function.
409 * @param pvUser The user argument.
410 * @see pg_kDbg for the debug info reader.
411 */
412int kLdrModEnumDbgInfo(PKLDRMOD pMod, void *pvBits, PFNKLDRENUMDBG pfnCallback, void *pvUser)
413{
414 KLDRMOD_VALIDATE(pMod);
415 return pMod->pOps->pfnEnumDbgInfo(pMod, pvBits, pfnCallback, pvUser);
416}
417
418
419/**
420 * Checks if the module has debug info embedded or otherwise associated with it.
421 *
422 * @returns 0 if it has debug info, KLDR_ERR_NO_DEBUG_INFO if no debug info,
423 * and non-zero OS or kLdr status code on failure.
424 * @param pMod The module.
425 * @param pvBits Optional pointer to bits returned by kLdrModGetBits().
426 * This can be used by some module interpreters to reduce memory consumption.
427 */
428int kLdrModHasDbgInfo(PKLDRMOD pMod, void *pvBits)
429{
430 KLDRMOD_VALIDATE(pMod);
431 return pMod->pOps->pfnHasDbgInfo(pMod, pvBits);
432}
433
434
435/**
436 * Maps the module into the memory of the caller.
437 *
438 * On success the actual addresses for the segments can be found in MapAddress
439 * member of each segment in the segment array.
440 *
441 * @returns 0 on success, non-zero OS or kLdr status code on failure.
442 * @param pMod The module to be mapped.
443 * @remark kLdr only supports one mapping at a time of a module.
444 */
445int kLdrModMap(PKLDRMOD pMod)
446{
447 KLDRMOD_VALIDATE(pMod);
448 return pMod->pOps->pfnMap(pMod);
449}
450
451
452/**
453 * Unmaps a module previously mapped by kLdrModMap().
454 *
455 * @returns 0 on success, non-zero OS or kLdr status code on failure.
456 * @param pMod The module to unmap.
457 */
458int kLdrModUnmap(PKLDRMOD pMod)
459{
460 KLDRMOD_VALIDATE(pMod);
461 return pMod->pOps->pfnUnmap(pMod);
462}
463
464
465/**
466 * Allocates Thread Local Storage for module mapped by kLdrModMap().
467 *
468 * Calling kLdrModAllocTLS() more than once without calling kLdrModFreeTLS()
469 * between each invocation is not supported.
470 *
471 * @returns 0 on success, non-zero OS or kLdr status code on failure.
472 * @param pMod The module.
473 */
474int kLdrModAllocTLS(PKLDRMOD pMod)
475{
476 KLDRMOD_VALIDATE(pMod);
477 return pMod->pOps->pfnAllocTLS(pMod);
478}
479
480
481/**
482 * Frees Thread Local Storage previously allocated by kLdrModAllocTLS().
483 *
484 * The caller is responsible for only calling kLdrModFreeTLS() once
485 * after calling kLdrModAllocTLS().
486 *
487 * @returns 0 on success, non-zero OS or kLdr status code on failure.
488 * @param pMod The module.
489 */
490void kLdrModFreeTLS(PKLDRMOD pMod)
491{
492 KLDRMOD_VALIDATE_VOID(pMod);
493 pMod->pOps->pfnFreeTLS(pMod);
494}
495
496
497/**
498 * Reloads all dirty pages in a module previously mapped by kLdrModMap().
499 *
500 * The module interpreter may omit code pages if it can safely apply code
501 * fixups again in a subsequent kLdrModFixupMapping() call.
502 *
503 * The caller is responsible for freeing TLS before calling this function.
504 *
505 * @returns 0 on success, non-zero OS or kLdr status code on failure.
506 * @param pMod The module.
507 */
508int kLdrModReload(PKLDRMOD pMod)
509{
510 KLDRMOD_VALIDATE(pMod);
511 return pMod->pOps->pfnReload(pMod);
512}
513
514
515/**
516 * Fixup the mapping made by kLdrModMap().
517 *
518 * The caller is only responsible for not calling this function more than
519 * once without doing kLDrModReload() inbetween.
520 *
521 * @returns 0 on success, non-zero OS or kLdr status code on failure.
522 * @param pMod The module.
523 * @param pfnGetImport The callback for resolving external (imported) symbols.
524 * @param pvUser The callback user argument.
525 */
526int kLdrModFixupMapping(PKLDRMOD pMod, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
527{
528 KLDRMOD_VALIDATE(pMod);
529 return pMod->pOps->pfnFixupMapping(pMod, pfnGetImport, pvUser);
530}
531
532
533/**
534 * Call the module initializiation function of a mapped module (if any).
535 *
536 * @returns 0 on success or no init function, non-zero on init function failure or invalid pMod.
537 * @param pMod The module.
538 */
539int kLdrModCallInit(PKLDRMOD pMod)
540{
541 KLDRMOD_VALIDATE(pMod);
542 return pMod->pOps->pfnCallInit(pMod);
543}
544
545
546/**
547 * Call the module termination function of a mapped module (if any).
548 *
549 * @returns 0 on success or no term function, non-zero on invalid pMod.
550 * @param pMod The module.
551 *
552 * @remark Termination function failure will be ignored by the module interpreter.
553 */
554int kLdrModCallTerm(PKLDRMOD pMod)
555{
556 KLDRMOD_VALIDATE(pMod);
557 return pMod->pOps->pfnCallTerm(pMod);
558}
559
560
561/**
562 * Call the thread attach or detach function of a mapped module (if any).
563 *
564 * @returns 0 on success or no attach/detach function, non-zero on attach failure or invalid pMod.
565 * @param pMod The module.
566 *
567 * @remark Detach function failure will be ignored by the module interpreter.
568 */
569int kLdrModCallThread(PKLDRMOD pMod, unsigned fAttachingOrDetaching)
570{
571 KLDRMOD_VALIDATE(pMod);
572 KLDRHLP_VALIDATE_FLAGS(fAttachingOrDetaching, 1);
573 return pMod->pOps->pfnCallThread(pMod, fAttachingOrDetaching);
574}
575
576
577/**
578 * Get the size of the mapped module.
579 *
580 * @returns The size of the mapped module (in bytes).
581 * @param pMod The module.
582 */
583size_t kLdrModSize(PKLDRMOD pMod)
584{
585 KLDRMOD_VALIDATE_EX(pMod, 0);
586 return pMod->pOps->pfnSize(pMod);
587}
588
589
590/**
591 * Gets the module bits.
592 *
593 * The module interpreter will fill a mapping allocated by the caller with the
594 * module bits reallocated to the specified address.
595 *
596 * @returns 0 on succes, non-zero OS or kLdr status code on failure.
597 * @param pMod The module.
598 * @param pvBits Where to put the bits.
599 * @param BaseAddress The base address that should correspond to the first byte in pvBits
600 * upon return.
601 * @param pfnGetImport The callback ufor resolving external (imported) symbols.
602 * @param pvUser The callback user argument.
603 */
604int kLdrModGetBits(PKLDRMOD pMod, void *pvBits, KLDRADDR BaseAddress, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
605{
606 KLDRMOD_VALIDATE(pMod);
607 return pMod->pOps->pfnGetBits(pMod, pvBits, BaseAddress, pfnGetImport, pvUser);
608}
609
610
611/**
612 * Relocates the module bits previously obtained by kLdrModGetBits().
613 *
614 * @returns 0 on succes, non-zero OS or kLdr status code on failure.
615 * @param pMod The module.
616 * @param pvBits Where to put the bits.
617 * @param NewBaseAddress The new base address.
618 * @param OldBaseAddress The old base address (i.e. the one specified to kLdrModGetBits() or as
619 * NewBaseAddressto the previous kLdrModRelocateBits() call).
620 * @param pfnGetImport The callback ufor resolving external (imported) symbols.
621 * @param pvUser The callback user argument.
622 */
623int kLdrModRelocateBits(PKLDRMOD pMod, void *pvBits, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress,
624 PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
625{
626 KLDRMOD_VALIDATE(pMod);
627 return pMod->pOps->pfnRelocateBits(pMod, pvBits, NewBaseAddress, OldBaseAddress, pfnGetImport, pvUser);
628}
629
Note: See TracBrowser for help on using the repository browser.