source: trunk/kLdr/kLdrMod.c@ 2851

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

kLdrMod done.

  • Property svn:keywords set to Id
File size: 21.6 KB
Line 
1/* $Id: kLdrMod.c 2851 2006-11-02 03:21:54Z bird $ */
2/** @file
3 *
4 * kLdr - The Dynamic Loader, 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 puValue Where to store the symbol value. (optional)
265 * @param pfKind Where to store the symbol kind. (optional)
266 */
267int kLdrModQuerySymbol(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, uint32_t uSymbol,
268 const char *pszSymbol, PKLDRADDR puValue, uint32_t *pfKind)
269{
270 KLDRMOD_VALIDATE(pMod);
271 if (!puValue && !pfKind)
272 return KLDR_ERR_INVALID_PARAMETER;
273 if (puValue)
274 *puValue = 0;
275 if (pfKind)
276 *pfKind = 0;
277 return pMod->pOps->pfnDestroy(pMod);
278}
279
280
281/**
282 * Enumerate the symbols in the module.
283 *
284 * @returns 0 on success and non-zero a status code on failure.
285 * @param pMod The module which symbols should be enumerated.
286 * @param fFlags The enumeration flags. A combination of the KLDRMOD_ENUM_SYMS_FLAGS_* \#defines.
287 * @param pvBits Optional pointer to bits returned by kLdrModGetBits() currently located at BaseAddress.
288 * This can be used by some module interpreters to reduce memory consumption.
289 * @param BaseAddress The module base address to use when calculating the symbol values.
290 * There are two special values that could be can:
291 * KLDRMOD_BASEADDRESS_LINK and KLDRMOD_BASEADDRESS_MAP.
292 * @param pfnCallback The enumeration callback function.
293 * @param pvUser The user argument to the callback function.
294 */
295int kLdrModEnumSymbols(PKLDRMOD pMod, uint32_t fFlags, const void *pvBits, KLDRADDR BaseAddress,
296 PFNKLDRMODENUMSYMS pfnCallback, void *pvUser)
297{
298 KLDRMOD_VALIDATE(pMod);
299 KLDRHLP_VALIDATE_FLAGS(fFlags, KLDRMOD_ENUM_SYMS_FLAGS_ALL);
300 return pMod->pOps->pfnEnumSymbols(pMod, fFlags, pvBits, BaseAddress, pfnCallback, pvUser);
301}
302
303
304/**
305 * Get the name of an import module by ordinal number.
306 *
307 * @returns 0 and name in pszName on success.
308 * On buffer overruns KLDR_ERR_BUFFER_OVERFLOW will be returned.
309 * On other failures and appropriate error code is returned.
310 * @param pMod The module.
311 * @param pvBits Optional pointer to bits returned by kLdrModGetBits().
312 * This can be used by some module interpreters to reduce memory consumption.
313 * @param iImport The import module ordinal number.
314 * @param pszName Where to store the name.
315 * @param cchName The size of the name buffer.
316 */
317int kLdrModGetImport(PKLDRMOD pMod, void *pvBits, uint32_t iImport, const char *pszName, size_t cchName)
318{
319 KLDRMOD_VALIDATE(pMod);
320 return pMod->pOps->pfnGetImport(pMod, pvBits, iImport, pszName, cchName);
321}
322
323
324/**
325 * Get the number of import modules.
326 *
327 * @returns The number of import modules. -1 if something really bad happens.
328 * @param pMod The module.
329 * @param pvBits Optional pointer to bits returned by kLdrModGetBits().
330 * This can be used by some module interpreters to reduce memory consumption.
331 */
332int32_t kLdrModNumberOfImports(PKLDRMOD pMod, void *pvBits)
333{
334 KLDRMOD_VALIDATE(pMod);
335 return pMod->pOps->pfnNumberOfImports(pMod, pvBits);
336}
337
338
339/**
340 * Checks if this module can be executed by the specified arch+cpu.
341 *
342 * @returns 0 if it can, KLDR_ERR_ARCH_CPU_NOT_COMPATIBLE if it can't.
343 * Other failures may occur and cause other return values.
344 * @param pMod The module.
345 * @param pvBits Optional pointer to bits returned by kLdrModGetBits().
346 * This can be used by some module interpreters to reduce memory consumption.
347 */
348int kLdrModCanExecuteOn(PKLDRMOD pMod, void *pvBits, KLDRARCH enmArch, KLDRCPU enmCpu)
349{
350 KLDRMOD_VALIDATE(pMod);
351 return pMod->pOps->pfnCanExecuteOn(pMod, pvBits, enmArch, enmCpu);
352}
353
354
355/**
356 * Gets the image stack info.
357 *
358 * @returns 0 on success, non-zero on failure.
359 * @param pMod
360 * @param pvBits Optional pointer to bits returned by kLdrModGetBits() currently located at BaseAddress.
361 * This can be used by some module interpreters to reduce memory consumption.
362 * @param BaseAddress The module base address to use when calculating the stack address.
363 * There are two special values that can be used:
364 * KLDRMOD_BASEADDRESS_LINK and KLDRMOD_BASEADDRESS_MAP.
365 * @param pStackInfo The stack information.
366 */
367int kLdrModGetStackInfo(PKLDRMOD pMod, void *pvBits, KLDRADDR BaseAddress, PKLDRSTACKINFO pStackInfo)
368{
369 KLDRMOD_VALIDATE(pMod);
370 return pMod->pOps->pfnGetStackInfo(pMod, pvBits, BaseAddress, pStackInfo);
371}
372
373
374/**
375 * Queries the main entrypoint of the module.
376 *
377 * Only executable are supposed to have an main entrypoint, though some object and DLL
378 * formats will also allow this.
379 *
380 * @returns 0 and *pMainEPAddress on success. Non-zero status code on failure.
381 * @param pMod The module.
382 * @param pvBits Optional pointer to bits returned by kLdrModGetBits() currently located at BaseAddress.
383 * This can be used by some module interpreters to reduce memory consumption.
384 * @param BaseAddress The module base address to use when calculating the entrypoint address.
385 * There are two special values that can be used:
386 * KLDRMOD_BASEADDRESS_LINK and KLDRMOD_BASEADDRESS_MAP.
387 * @param pMainEPAddress Where to store the entry point address.
388 */
389int kLdrModQueryMainEntrypoint(PKLDRMOD pMod, void *pvBits, KLDRADDR BaseAddress, PKLDRADDR pMainEPAddress)
390{
391 KLDRMOD_VALIDATE(pMod);
392 *pMainEPAddress = 0;
393 return pMod->pOps->pfnQueryMainEntrypoint(pMod, pvBits, BaseAddress, pMainEPAddress);
394}
395
396
397/**
398 * Enumerate the debug info formats contained in the executable image.
399 *
400 * @returns 0 on success, non-zero OS or kLdr status code on failure, or non-zero callback status.
401 * @param pMod The module.
402 * @param pvBits Optional pointer to bits returned by kLdrModGetBits().
403 * This can be used by some module interpreters to reduce memory consumption.
404 * @param pfnCallback The callback function.
405 * @param pvUser The user argument.
406 * @see pg_kDbg for the debug info reader.
407 */
408int kLdrModEnumDbgInfo(PKLDRMOD pMod, void *pvBits, PFNKLDRENUMDBG pfnCallback, void *pvUser)
409{
410 KLDRMOD_VALIDATE(pMod);
411 return pMod->pOps->pfnEnumDbgInfo(pMod, pvBits, pfnCallback, pvUser);
412}
413
414
415/**
416 * Checks if the module has debug info embedded or otherwise associated with it.
417 *
418 * @returns 0 if it has debug info, KLDR_ERR_NO_DEBUG_INFO if no debug info,
419 * and non-zero OS or kLdr status code on failure.
420 * @param pMod The module.
421 * @param pvBits Optional pointer to bits returned by kLdrModGetBits().
422 * This can be used by some module interpreters to reduce memory consumption.
423 */
424int kLdrModHasDbgInfo(PKLDRMOD pMod, void *pvBits)
425{
426 KLDRMOD_VALIDATE(pMod);
427 return pMod->pOps->pfnHasDbgInfo(pMod, pvBits);
428}
429
430
431/**
432 * Maps the module into the memory of the caller.
433 *
434 * On success the actual addresses for the segments can be found in MapAddress
435 * member of each segment in the segment array.
436 *
437 * @returns 0 on success, non-zero OS or kLdr status code on failure.
438 * @param pMod The module to be mapped.
439 * @remark kLdr only supports one mapping at a time of a module.
440 */
441int kLdrModMap(PKLDRMOD pMod)
442{
443 KLDRMOD_VALIDATE(pMod);
444 return pMod->pOps->pfnMap(pMod);
445}
446
447
448/**
449 * Unmaps a module previously mapped by kLdrModMap().
450 *
451 * @returns 0 on success, non-zero OS or kLdr status code on failure.
452 * @param pMod The module to unmap.
453 */
454int kLdrModUnmap(PKLDRMOD pMod)
455{
456 KLDRMOD_VALIDATE(pMod);
457 return pMod->pOps->pfnUnmap(pMod);
458}
459
460
461/**
462 * Allocates Thread Local Storage for module mapped by kLdrModMap().
463 *
464 * Calling kLdrModAllocTLS() more than once without calling kLdrModFreeTLS()
465 * between each invocation is not supported.
466 *
467 * @returns 0 on success, non-zero OS or kLdr status code on failure.
468 * @param pMod The module.
469 */
470int kLdrModAllocTLS(PKLDRMOD pMod)
471{
472 KLDRMOD_VALIDATE(pMod);
473 return pMod->pOps->pfnAllocTLS(pMod);
474}
475
476
477/**
478 * Frees Thread Local Storage previously allocated by kLdrModAllocTLS().
479 *
480 * The caller is responsible for only calling kLdrModFreeTLS() once
481 * after calling kLdrModAllocTLS().
482 *
483 * @returns 0 on success, non-zero OS or kLdr status code on failure.
484 * @param pMod The module.
485 */
486void kLdrModFreeTLS(PKLDRMOD pMod)
487{
488 KLDRMOD_VALIDATE_VOID(pMod);
489 pMod->pOps->pfnFreeTLS(pMod);
490}
491
492
493/**
494 * Reloads all dirty pages in a module previously mapped by kLdrModMap().
495 *
496 * The module interpreter may omit code pages if it can safely apply code
497 * fixups again in a subsequent kLdrModFixupMapping() call.
498 *
499 * The caller is responsible for freeing TLS before calling this function.
500 *
501 * @returns 0 on success, non-zero OS or kLdr status code on failure.
502 * @param pMod The module.
503 */
504int kLdrModReload(PKLDRMOD pMod)
505{
506 KLDRMOD_VALIDATE(pMod);
507 return pMod->pOps->pfnReload(pMod);
508}
509
510
511/**
512 * Fixup the mapping made by kLdrModMap().
513 *
514 * The caller is only responsible for not calling this function more than
515 * once without doing kLDrModReload() inbetween.
516 *
517 * @returns 0 on success, non-zero OS or kLdr status code on failure.
518 * @param pMod The module.
519 * @param pfnGetImport The callback for resolving external (imported) symbols.
520 * @param pvUser The callback user argument.
521 */
522int kLdrModFixupMapping(PKLDRMOD pMod, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
523{
524 KLDRMOD_VALIDATE(pMod);
525 return pMod->pOps->pfnFixupMapping(pMod, pfnGetImport, pvUser);
526}
527
528
529/**
530 * Call the module initializiation function of a mapped module (if any).
531 *
532 * @returns 0 on success or no init function, non-zero on init function failure or invalid pMod.
533 * @param pMod The module.
534 */
535int kLdrModCallInit(PKLDRMOD pMod)
536{
537 KLDRMOD_VALIDATE(pMod);
538 return pMod->pOps->pfnCallInit(pMod);
539}
540
541
542/**
543 * Call the module termination function of a mapped module (if any).
544 *
545 * @returns 0 on success or no term function, non-zero on invalid pMod.
546 * @param pMod The module.
547 *
548 * @remark Termination function failure will be ignored by the module interpreter.
549 */
550int kLdrModCallTerm(PKLDRMOD pMod)
551{
552 KLDRMOD_VALIDATE(pMod);
553 return pMod->pOps->pfnCallTerm(pMod);
554}
555
556
557/**
558 * Call the thread attach or detach function of a mapped module (if any).
559 *
560 * @returns 0 on success or no attach/detach function, non-zero on attach failure or invalid pMod.
561 * @param pMod The module.
562 *
563 * @remark Detach function failure will be ignored by the module interpreter.
564 */
565int kLdrModCallThread(PKLDRMOD pMod, unsigned fAttachingOrDetaching)
566{
567 KLDRMOD_VALIDATE(pMod);
568 KLDRHLP_VALIDATE_FLAGS(fAttachingOrDetaching, 1);
569 return pMod->pOps->pfnCallThread(pMod, fAttachingOrDetaching);
570}
571
572
573/**
574 * Get the size of the mapped module.
575 *
576 * @returns The size of the mapped module (in bytes).
577 * @param pMod The module.
578 */
579size_t kLdrModSize(PKLDRMOD pMod)
580{
581 KLDRMOD_VALIDATE_EX(pMod, 0);
582 return pMod->pOps->pfnSize(pMod);
583}
584
585
586/**
587 * Gets the module bits.
588 *
589 * The module interpreter will fill a mapping allocated by the caller with the
590 * module bits reallocated to the specified address.
591 *
592 * @returns 0 on succes, non-zero OS or kLdr status code on failure.
593 * @param pMod The module.
594 * @param pvBits Where to put the bits.
595 * @param BaseAddress The base address that should correspond to the first byte in pvBits
596 * upon return.
597 * @param pfnGetImport The callback ufor resolving external (imported) symbols.
598 * @param pvUser The callback user argument.
599 */
600int kLdrModGetBits(PKLDRMOD pMod, void *pvBits, KLDRADDR BaseAddress, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
601{
602 KLDRMOD_VALIDATE(pMod);
603 return pMod->pOps->pfnGetBits(pMod, pvBits, BaseAddress, pfnGetImport, pvUser);
604}
605
606
607/**
608 * Relocates the module bits previously obtained by kLdrModGetBits().
609 *
610 * @returns 0 on succes, non-zero OS or kLdr status code on failure.
611 * @param pMod The module.
612 * @param pvBits Where to put the bits.
613 * @param NewBaseAddress The new base address.
614 * @param OldBaseAddress The old base address (i.e. the one specified to kLdrModGetBits() or as
615 * NewBaseAddressto the previous kLdrModRelocateBits() call).
616 * @param pfnGetImport The callback ufor resolving external (imported) symbols.
617 * @param pvUser The callback user argument.
618 */
619int kLdrModRelocateBits(PKLDRMOD pMod, void *pvBits, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress,
620 PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
621{
622 KLDRMOD_VALIDATE(pMod);
623 return pMod->pOps->pfnRelocateBits(pMod, pvBits, NewBaseAddress, OldBaseAddress, pfnGetImport, pvUser);
624}
625
Note: See TracBrowser for help on using the repository browser.