source: trunk/kLdr/kLdrMod.c@ 2856

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

More code.

  • Property svn:keywords set to Id
File size: 22.7 KB
RevLine 
[2826]1/* $Id: kLdrMod.c 2856 2006-11-04 22:19:33Z bird $ */
[2825]2/** @file
3 *
[2854]4 * kLdr - The Module Interpreter.
[2825]5 *
6 * Copyright (c) 2006 knut st. osmundsen <[email protected]>
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"
[2827]34#include "kLdrModMZ.h"
35#if 1 /* testing headers */
36# include "kLdrModPE.h"
[2828]37# include "kLdrModLX.h"
[2827]38# include "kLdrModELF32.h"
39# include "kLdrModELF64.h"
40#endif
[2825]41
42
[2851]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
[2827]100/**
[2848]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/**
[2827]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 /*
[2851]174 * Use the magic to select the appropriate image interpreter head on.
[2827]175 */
176 if (u.u16 == IMAGE_DOS_SIGNATURE)
[2851]177 rc = KLDR_ERR_MZ_NOT_SUPPORTED;
[2827]178 else if (u.u16 == IMAGE_NE_SIGNATURE)
[2851]179 rc = KLDR_ERR_NE_NOT_SUPPORTED;
[2827]180 else if (u.u16 == IMAGE_LX_SIGNATURE)
[2851]181 rc = KLDR_ERR_LX_NOT_SUPPORTED;
[2827]182 else if (u.u16 == IMAGE_LE_SIGNATURE)
[2851]183 rc = KLDR_ERR_LE_NOT_SUPPORTED;
[2827]184 else if (u.u32 == IMAGE_NT_SIGNATURE)
[2851]185 rc = KLDR_ERR_PE_NOT_SUPPORTED;
[2827]186 else if (u.u32 == IMAGE_ELF_SIGNATURE)
[2851]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;
[2827]206}
207
208
209/**
[2848]210 * Open a executable image using the native loader (if any).
[2827]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 */
[2848]217int kLdrModOpenNative(const char *pszFilename, PPKLDRMOD ppMod)
[2825]218{
[2848]219#ifdef __OS2__
220
221 //DosLoadModule()
222#elif defined(__WIN__)
223
224#else
225# error "Port me"
226#endif
227 return -1;
[2825]228}
229
[2848]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 *
[2851]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.
[2848]240 * @param pMod The module.
241 */
242int kLdrModClose(PKLDRMOD pMod)
243{
[2851]244 KLDRMOD_VALIDATE(pMod);
245 return pMod->pOps->pfnDestroy(pMod);
[2848]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)
[2854]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.
[2848]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,
[2854]271 const char *pszSymbol, PFNKLDRMODGETIMPORT pfnGetForwarder, void *pvUser,
272 PKLDRADDR puValue, uint32_t *pfKind)
[2848]273{
[2851]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;
[2854]281 return pMod->pOps->pfnQuerySymbol(pMod, pvBits, BaseAddress, uSymbol, pszSymbol, pfnGetForwarder, pvUser, puValue, pfKind);
[2848]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.
[2854]295 * @param fFlags The enumeration flags. A combination of the KLDRMOD_ENUM_SYMS_FLAGS_* \#defines.
[2848]296 * @param pfnCallback The enumeration callback function.
297 * @param pvUser The user argument to the callback function.
298 */
[2854]299int kLdrModEnumSymbols(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, uint32_t fFlags,
[2848]300 PFNKLDRMODENUMSYMS pfnCallback, void *pvUser)
301{
[2851]302 KLDRMOD_VALIDATE(pMod);
303 KLDRHLP_VALIDATE_FLAGS(fFlags, KLDRMOD_ENUM_SYMS_FLAGS_ALL);
[2854]304 return pMod->pOps->pfnEnumSymbols(pMod, pvBits, BaseAddress, fFlags, pfnCallback, pvUser);
[2848]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 */
[2855]321int kLdrModGetImport(PKLDRMOD pMod, const void *pvBits, uint32_t iImport, char *pszName, size_t cchName)
[2848]322{
[2851]323 KLDRMOD_VALIDATE(pMod);
324 return pMod->pOps->pfnGetImport(pMod, pvBits, iImport, pszName, cchName);
[2848]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 */
[2855]336int32_t kLdrModNumberOfImports(PKLDRMOD pMod, const void *pvBits)
[2848]337{
[2851]338 KLDRMOD_VALIDATE(pMod);
339 return pMod->pOps->pfnNumberOfImports(pMod, pvBits);
[2848]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 */
[2855]352int kLdrModCanExecuteOn(PKLDRMOD pMod, const void *pvBits, KLDRARCH enmArch, KLDRCPU enmCpu)
[2848]353{
[2851]354 KLDRMOD_VALIDATE(pMod);
[2855]355 if (pMod->pOps->pfnCanExecuteOn)