source: trunk/kLdr/kLdrDy.c@ 2833

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

Wrote the kLdrDyld verification routines and made it build on win32.

  • Property svn:keywords set to Id
File size: 14.1 KB
Line 
1/* $Id: kLdrDy.c 2833 2006-10-26 00:08:09Z bird $ */
2/** @file
3 *
4 * kLdr - The Dynamic Loader.
5 *
6 * Copyright (c) 2006 knut st. osmundsen <bird@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
35
36/*******************************************************************************
37* Global Variables *
38*******************************************************************************/
39/** Pointer to the head module (the executable).
40 * (This is exported, so no prefix.) */
41PKLDRDYLDMOD kLdrDyldHead = NULL;
42/** Pointer to the tail module.
43 * (This is exported, so no prefix.) */
44PKLDRDYLDMOD kLdrDyldTail = NULL;
45/** The Library search path. */
46char kLdrDyldLibraryPath[4096];
47/** The executable flags. */
48uint32_t kLdrDyldFlags;
49
50
51/*******************************************************************************
52* Internal Functions *
53*******************************************************************************/
54static int kldrDyldLoad(const char *pszDll, const char *pszDefPrefix, const char *pszDefSuffix, KLDRDYLDSEARCH enmSearch,
55 unsigned fFlags, PPKLDRDYLDMOD ppMod, char *pszErr, size_t cchErr);
56static int kldrDyldUnload(PKLDRDYLDMOD pMod);
57static int kldrDyldFindByName(const char *pszDll, const char *pszDefPrefix, const char *pszDefSuffix, KLDRDYLDSEARCH enmSearch, PPKLDRDYLDMOD ppMod);
58static int kldrDyldFindByAddress(uintptr_t Address, PPKLDRDYLDMOD ppMod, uint32_t *piSegment, uintptr_t *poffSegment);
59static int kldrDyldGetName(PKLDRDYLDMOD pMod, char *pszName, size_t cchName);
60static int kldrDyldGetFilename(PKLDRDYLDMOD pMod, char *pszFilename, size_t cchFilename);
61static int kldrDyldQuerySymbol(PKLDRDYLDMOD pMod, uint32_t uSymbolOrdinal, const char *pszSymbolName, uintptr_t *pValue, uint32_t *pfKind);
62
63
64
65/**
66 * Initialize the dynamic loader.
67 */
68int kldrDyInit(void)
69{
70 kLdrDyldHead = NULL;
71 kLdrDyldTail = NULL;
72 kLdrDyldFlags = 0;
73 return 0;
74}
75
76
77/**
78 * Terminate the dynamic loader.
79 */
80void kldrDyTerm(void)
81{
82
83}
84
85
86/**
87 * Loads a module into the current process.
88 *
89 * @returns 0 on success, non-zero native OS status code or kLdr status code on failure.
90 * @param pszDll The name of the dll to open.
91 * @param pszDefPrefix Prefix to use when searching.
92 * @param pszDefSuffix Suffix to use when searching.
93 * @param enmSearch Method to use when locating the module and any modules it may depend on.
94 * @param fFlags Flags, a combintation of the KLDRYDLD_LOAD_FLAGS_* \#defines.
95 * @param phMod Where to store the handle to the loaded module.
96 * @param pszErr Where to store extended error information. (optional)
97 * @param cchErr The size of the buffer pointed to by pszErr.
98 */
99int kLdrDyldLoad(const char *pszDll, const char *pszDefPrefix, const char *pszDefSuffix, KLDRDYLDSEARCH enmSearch,
100 unsigned fFlags, PHKLDRMOD phMod, char *pszErr, size_t cchErr)
101{
102 int rc;
103
104 /* validate arguments and initialize return values. */
105 if (pszErr && cchErr)
106 *pszErr = '\0';
107 *phMod = NIL_HKLDRMOD;
108 KLDRHLP_VALIDATE_STRING(pszDll);
109 KLDRHLP_VALIDATE_OPTIONAL_STRING(pszDefPrefix);
110 KLDRHLP_VALIDATE_OPTIONAL_STRING(pszDefSuffix);
111 KLDRHLP_VALIDATE_ENUM(enmSearch, KLDRDYLD_SEARCH);
112 KLDRHLP_VALIDATE_OPTIONAL_BUFFER(pszErr, cchErr);
113
114 /* get the semaphore and do the job. */
115 rc = kldrHlpSemRequest();
116 if (!rc)
117 {
118 PKLDRDYLDMOD pMod = NULL;
119 rc = kldrDyldLoad(pszDll, pszDefPrefix, pszDefSuffix, enmSearch, fFlags, phMod, pszErr, cchErr);
120 kldrHlpSemRelease();
121 *phMod = pMod;
122 }
123 return rc;
124}
125
126
127/**
128 * Unloads a module loaded by kLdrDyldLoad.
129 *
130 * @returns 0 on success, non-zero native OS status code or kLdr status code on failure.
131 * @param hMod Module handle.
132 */
133int kLdrDyldUnload(HKLDRMOD hMod)
134{
135 int rc;
136
137 /* validate */
138 KLDRDYLD_VALIDATE_HKLDRMOD(hMod);
139
140 /* get sem & do work */
141 rc = kldrHlpSemRequest();
142 if (!rc)
143 {
144 rc = kldrDyldUnload(hMod);
145 kldrHlpSemRelease();
146 }
147 return rc;
148}
149
150
151/**
152 * Finds a module by name or filename.
153 *
154 * This call does not increase any reference counters and must not be
155 * paired with kLdrDyldUnload() like kLdrDyldLoad().
156 *
157 * @returns 0 on success.
158 * @returns KLDR_ERR_MODULE_NOT_FOUND on failure.
159 * @param pszDll The name of the dll to look for.
160 * @param pszDefPrefix Prefix to use when searching.
161 * @param pszDefSuffix Suffix to use when searching.
162 * @param enmSearch Method to use when locating the module.
163 * @param phMod Where to store the handle of the module on success.
164 */
165int kLdrDyldFindByName(const char *pszDll, const char *pszDefPrefix, const char *pszDefSuffix, KLDRDYLDSEARCH enmSearch, PHKLDRMOD phMod)
166{
167 int rc;
168
169 /* validate & initialize */
170 *phMod = NIL_HKLDRMOD;
171 KLDRHLP_VALIDATE_STRING(pszDll);
172
173 /* get sem & do work */
174 rc = kldrHlpSemRequest();
175 if (!rc)
176 {
177 PKLDRDYLDMOD pMod = NULL;
178 rc = kldrDyldFindByName(pszDll, pszDefPrefix, pszDefSuffix, enmSearch, phMod);
179 kldrHlpSemRelease();
180 *phMod = pMod;
181 }
182 return rc;
183}
184
185
186/**
187 * Finds a module by address.
188 *
189 * This call does not increase any reference counters and must not be
190 * paired with kLdrDyldUnload() like kLdrDyldLoad().
191 *
192 * @returns 0 on success.
193 * @returns KLDR_ERR_MODULE_NOT_FOUND on failure.
194 * @param Address The address believed to be within some module.
195 * @param phMod Where to store the module handle on success.
196 * @param piSegment Where to store the segment number. (optional)
197 * @param poffSegment Where to store the offset into the segment. (optional)
198 */
199int kLdrDyldFindByAddress(uintptr_t Address, PHKLDRMOD phMod, uint32_t *piSegment, uintptr_t *poffSegment)
200{
201 int rc;
202
203 /* validate & initialize */
204 *phMod = NIL_HKLDRMOD;
205 if (piSegment)
206 *piSegment = ~(uint32_t)0;
207 if (poffSegment)
208 *poffSegment = ~(uintptr_t)0;
209
210 /* get sem & do work */
211 rc = kldrHlpSemRequest();
212 if (!rc)
213 {
214 PKLDRDYLDMOD pMod = NULL;
215 rc = kldrDyldFindByAddress(Address, &pMod, piSegment, poffSegment);
216 kldrHlpSemRelease();
217 *phMod = pMod;
218 }
219 return rc;
220}
221
222
223/**
224 * Gets the module name.
225 *
226 * @returns 0 on success and pszName filled with the name.
227 * @returns KLDR_ERR_INVALID_HANDLE or KLDR_ERR_BUFFER_OVERFLOW on failure.
228 * @param hMod The module handle.
229 * @param pszName Where to put the name.
230 * @param cchName The size of the name buffer.
231 * @see kLdrDyldGetFilename
232 */
233int kLdrDyldGetName(HKLDRMOD hMod, char *pszName, size_t cchName)
234{
235 int rc;
236
237 /* validate */
238 if (pszName && cchName)
239 *pszName = '\0';
240 KLDRDYLD_VALIDATE_HKLDRMOD(hMod);
241 KLDRHLP_VALIDATE_BUFFER(pszName, cchName);
242
243 /* get sem & do work */
244 rc = kldrHlpSemRequest();
245 if (!rc)
246 {
247 rc = kldrDyldGetName(hMod, pszName, cchName);
248 kldrHlpSemRelease();
249 }
250 return rc;
251}
252
253
254/**
255 * Gets the module filename.
256 *
257 * @returns 0 on success and pszFilename filled with the name.
258 * @returns KLDR_ERR_INVALID_HANDLE or KLDR_ERR_BUFFER_OVERFLOW on failure.
259 * @param hMod The module handle.
260 * @param pszFilename Where to put the filename.
261 * @param cchFilename The size of the filename buffer.
262 * @see kLdrDyldGetName
263 */
264int kLdrDyldGetFilename(HKLDRMOD hMod, char *pszFilename, size_t cchFilename)
265{
266 int rc;
267
268 /* validate & initialize */
269 if (pszFilename && cchFilename);
270 *pszFilename = '\0';
271 KLDRDYLD_VALIDATE_HKLDRMOD(hMod);
272 KLDRHLP_VALIDATE_BUFFER(pszFilename, cchFilename);
273
274 /* get sem & do work */
275 rc = kldrHlpSemRequest();
276 if (!rc)
277 {
278 rc = kldrDyldGetFilename(hMod, pszFilename, cchFilename);
279 kldrHlpSemRelease();
280 }
281 return rc;
282}
283
284
285/**
286 * Queries the value and type of a symbol.
287 *
288 * @returns 0 on success and pValue and pfKind set.
289 * @returns KLDR_ERR_INVALID_HANDLE or KLDR_ERR_SYMBOL_NOT_FOUND on failure.
290 * @param hMod The module handle.
291 * @param uSymbolOrdinal The symbol ordinal. This is ignored if pszSymbolName is non-zero.
292 * @param pszSymbolName The symbol name.
293 * @param pValue Where to put the symbol value. Optional if pfKind is non-zero.
294 * @param pfKind Where to put the symbol kind flags. Optional if pValue is non-zero.
295 */
296int kLdrDyldQuerySymbol(HKLDRMOD hMod, uint32_t uSymbolOrdinal, const char *pszSymbolName, uintptr_t *pValue, uint32_t *pfKind)
297{
298 int rc;
299
300 /* validate & initialize */
301 if (pfKind)
302 *pfKind = 0;
303 if (pValue)
304 *pValue = 0;
305 if (!pfKind && !pValue)
306 return KLDR_ERR_INVALID_PARAMETER;
307 KLDRDYLD_VALIDATE_HKLDRMOD(hMod);
308 KLDRHLP_VALIDATE_OPTIONAL_STRING(pszSymbolName);
309
310 /* get sem & do work */
311 rc = kldrHlpSemRequest();
312 if (!rc)
313 {
314 rc = kldrDyldQuerySymbol(hMod, uSymbolOrdinal, pszSymbolName, pValue, pfKind);
315 kldrHlpSemRelease();
316 }
317 return rc;
318}
319
320
321
322
323
324
325/**
326 * Worker for kldrDyldLoad().
327 * @internal
328 */
329static int kldrDyldLoad(const char *pszDll, const char *pszDefPrefix, const char *pszDefSuffix, KLDRDYLDSEARCH enmSearch,
330 unsigned fFlags, PPKLDRDYLDMOD ppMod, char *pszErr, size_t cchErr)
331{
332 /*
333 * Open the module.
334 */
335
336
337 return -1;
338}
339
340
341/**
342 * Worker for kldrDyldUnload().
343 * @internal
344 */
345static int kldrDyldUnload(HKLDRMOD hMod)
346{
347 return -1;
348}
349
350
351/**
352 * Worker for kLdrDyldFindByName().
353 * @internal
354 */
355static int kldrDyldFindByName(const char *pszDll, const char *pszDefPrefix, const char *pszDefSuffix, KLDRDYLDSEARCH enmSearch, PPKLDRDYLDMOD ppMod)
356{
357 return -1;
358}
359
360
361/**
362 * Worker for kLdrDyldFindByAddress().
363 * @internal
364 */
365static int kldrDyldFindByAddress(uintptr_t Address, PPKLDRDYLDMOD ppMod, uint32_t *piSegment, uintptr_t *poffSegment)
366{
367 return -1;
368}
369
370
371/**
372 * Worker for kLdrDyldGetName().
373 * @internal
374 */
375static int kldrDyldGetName(PKLDRDYLDMOD pMod, char *pszName, size_t cchName)
376{
377 return -1;
378}
379
380
381/**
382 * Worker for kLdrDyldGetFilename().
383 * @internal
384 */
385static int kldrDyldGetFilename(PKLDRDYLDMOD pMod, char *pszFilename, size_t cchFilename)
386{
387 return -1;
388}
389
390
391/**
392 * Worker for kLdrDyldQuerySymbol().
393 * @internal
394 */
395static int kldrDyldQuerySymbol(PKLDRDYLDMOD pMod, uint32_t uSymbolOrdinal, const char *pszSymbolName, uintptr_t *pValue, uint32_t *pfKind)
396{
397 return -1;
398}
399
400
401#if 0
402void kldrLoadExe(PKLDREXEARGS pArgs)
403{
404 /*
405 * Copy the arguments into the globals and do load init.
406 */
407 kLdrFlags = pArgs->fFlags;
408 kLdrHlpMemCopy(kLdrLibraryPath, pArgs->szLibPath, KLDR_MIN(sizeof(pArgs->szLibPath), sizeof(kLdrLibraryPath)));
409 int rc = kldrInit();
410 if (rc)
411 kldrFailure(rc, "kLdr: Init failure, rc=%d\n", rc);
412
413 /*
414 * Open the executable module.
415 */
416 PKLDRMOD pExe;
417 kldrOpenExe(pArgs->szExecutable, &pExe);
418
419 /* Map the segments. */
420 kldrModMapSegments(pExe);
421
422 /*
423 * This is the point where we switch to the executable
424 * stack, allocating it if necessary.
425 */
426 void *pvBottom;
427 kldrModSetupStack(pExe, &pvBottom);
428 kldrLoadExecSwitchStack(pvBottom);
429}
430
431
432void kldrLoadExeOnNewStack(void)
433{
434 /*
435 * Load all dependant modules.
436 */
437 PKLDRMOD pCur;
438 do for (pCur = kLdrModuleHead; pCur; pCur = pCur->pNext)
439 {
440 if (pCur->enmState >= KLDRSTATE_DEPS)
441 continue;
442 kldrModLoadDeps(pCur);
443 }
444 while (pCur);
445
446 /*
447 * Do fixups (FIFO).
448 */
449 for (pCur = kLdrModuleHead; pCur; pCur = pCur->pNext)
450 {
451 if (pCur->enmState >= KLDRSTATE_FIXED)
452 continue;
453 kldrModFixup(pCur, 0);
454 }
455
456 /*
457 * Do module initialization.
458 */
459 for (pCur = kLdrModuleTail; pCur != kLdrModuleTail; pCur = pCur->pPrev)
460 {
461 if (pCur->enmState >= KLDRSTATE_INITED)
462 continue;
463 kldrModCallInit(pCur);
464 }
465
466 /*
467 * Get the executable start address and commit the work that's been done.
468 */
469 void *pvEntry;
470 kldrModGetExeEntry(&pvEntry);
471
472 for (pCur = kLdrModuleHead; pCur; pCur = pCur->pNext)
473 if (pCur->enmState == KLDRSTATE_INITED)
474 pCur->enmState = KLDRSTATE_LOADED;
475
476 kldrHlpSemRelease();
477
478 /*
479 * We're now ready for starting the executable code.
480 */
481 kldrOSStartExe(pLdrModuleHead, pvEntry);
482}
483
484
485/**
486 * Panic / failure
487 *
488 * @returns rc if we're in a position where we can return.
489 * @param rc Return code.
490 * @param pszFormat Message string. Limited fprintf like formatted.
491 * @param ... Message string arguments.
492 */
493int kldrFailure(int rc, const char *pszFormat, ...)
494{
495 kldrExit(1);
496 return rc;
497}
498
499#endif
500
Note: See TracBrowser for help on using the repository browser.