VirtualBox

source: vbox/trunk/src/VBox/Runtime/ldrkLdr.cpp@ 2981

Last change on this file since 2981 was 2981, checked in by vboxsync, 17 years ago

InnoTek -> innotek: all the headers and comments.

  • Property svn:keywords set to Id
File size: 23.7 KB
Line 
1/* $Id: ldrkLdr.cpp 2981 2007-06-01 16:01:28Z vboxsync $ */
2/** @file
3 * innotek Portable Runtime - Binary Image Loader, kLdr Interface.
4 */
5
6/*
7 * Copyright (C) 2006-2007 innotek GmbH
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License as published by the Free Software Foundation,
13 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
14 * distribution. VirtualBox OSE is distributed in the hope that it will
15 * be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * If you received this file as part of a commercial VirtualBox
18 * distribution, then only the terms of your commercial VirtualBox
19 * license agreement apply instead of the previous paragraph.
20 */
21
22
23/*******************************************************************************
24* Header Files *
25*******************************************************************************/
26#define LOG_GROUP RTLOGGROUP_LDR
27#include <iprt/ldr.h>
28#include <iprt/file.h>
29#include <iprt/alloc.h>
30#include <iprt/assert.h>
31#include <iprt/string.h>
32#include <iprt/path.h>
33#include <iprt/log.h>
34#include <iprt/param.h>
35#include <iprt/err.h>
36#include "internal/ldr.h"
37#define KLDR_NO_KLDR_H_INCLUDES
38#include <kLdr.h>
39#include "kLdrHlp.h"
40
41
42/*******************************************************************************
43* Structures and Typedefs *
44*******************************************************************************/
45/**
46 * kLdr file provider.
47 */
48typedef struct RTKLDRRDR
49{
50 /** The core. */
51 KLDRRDR Core;
52 /** The IPRT bit reader. */
53 PRTLDRREADER pReader;
54} RTKLDRRDR, *PRTKLDRRDR;
55
56/**
57 * IPRT module.
58 */
59typedef struct RTLDRMODKLDR
60{
61 /** The Core module structure. */
62 RTLDRMODINTERNAL Core;
63 /** The kLdr module. */
64 PKLDRMOD pMod;
65} RTLDRMODKLDR, *PRTLDRMODKLDR;
66
67
68/**
69 * Arguments for a RTLDRMODKLDR callback wrapper.
70 */
71typedef struct RTLDRMODKLDRARGS
72{
73 union
74 {
75 PFNRT pfn;
76 PFNRTLDRENUMSYMS pfnEnumSyms;
77 PFNRTLDRIMPORT pfnGetImport;
78 } u;
79 void *pvUser;
80 const void *pvBits;
81 PRTLDRMODKLDR pMod;
82} RTLDRMODKLDRARGS, *PRTLDRMODKLDRARGS;
83
84
85/*******************************************************************************
86* Internal Functions *
87*******************************************************************************/
88static int rtkldrConvertError(int krc);
89static int rtkldrConvertErrorFromIPRT(int rc);
90
91
92static int rtkldrRdrCreate( PPKLDRRDR ppRdr, const char *pszFilename);
93static int rtkldrRdrDestroy( PKLDRRDR pRdr);
94static int rtkldrRdrRead( PKLDRRDR pRdr, void *pvBuf, size_t cb, KLDRFOFF off);
95static int rtkldrRdrAllMap( PKLDRRDR pRdr, const void **ppvBits);
96static int rtkldrRdrAllUnmap(PKLDRRDR pRdr, const void *pvBits);
97static KLDRFOFF rtkldrRdrSize( PKLDRRDR pRdr);
98static KLDRFOFF rtkldrRdrTell( PKLDRRDR pRdr);
99static const char * rtkldrRdrName(PKLDRRDR pRdr);
100static size_t rtkldrRdrPageSize(PKLDRRDR pRdr);
101static int rtkldrRdrMap( PKLDRRDR pRdr, void **ppvBase, uint32_t cSegments, PCKLDRSEG paSegments, unsigned fFixed);
102static int rtkldrRdrRefresh( PKLDRRDR pRdr, void *pvBase, uint32_t cSegments, PCKLDRSEG paSegments);
103static int rtkldrRdrProtect( PKLDRRDR pRdr, void *pvBase, uint32_t cSegments, PCKLDRSEG paSegments, unsigned fUnprotectOrProtect);
104static int rtkldrRdrUnmap( PKLDRRDR pRdr, void *pvBase, uint32_t cSegments, PCKLDRSEG paSegments);
105static void rtkldrRdrDone( PKLDRRDR pRdr);
106
107
108static DECLCALLBACK(int) rtkldrClose(PRTLDRMODINTERNAL pMod);
109static DECLCALLBACK(int) rtkldrDone(PRTLDRMODINTERNAL pMod);
110static DECLCALLBACK(int) rtkldrEnumSymbols(PRTLDRMODINTERNAL pMod, unsigned fFlags, const void *pvBits,
111 RTUINTPTR BaseAddress,PFNRTLDRENUMSYMS pfnCallback, void *pvUser);
112static int rtkldrEnumSymbolsWrapper(PKLDRMOD pMod, uint32_t iSymbol,
113 const char *pchSymbol, size_t cchSymbol, const char *pszVersion,
114 KLDRADDR uValue, uint32_t fKind, void *pvUser);
115static DECLCALLBACK(size_t) rtkldrGetImageSize(PRTLDRMODINTERNAL pMod);
116static DECLCALLBACK(int) rtkldrGetBits(PRTLDRMODINTERNAL pMod, void *pvBits, RTUINTPTR BaseAddress,
117 PFNRTLDRIMPORT pfnGetImport, void *pvUser);
118static DECLCALLBACK(int) rtkldrRelocate(PRTLDRMODINTERNAL pMod, void *pvBits, RTUINTPTR NewBaseAddress,
119 RTUINTPTR OldBaseAddress, PFNRTLDRIMPORT pfnGetImport, void *pvUser);
120static int rtkldrGetImportWrapper(PKLDRMOD pMod, uint32_t iImport, uint32_t iSymbol, const char *pchSymbol, size_t cchSymbol,
121 const char *pszVersion, PKLDRADDR puValue, uint32_t *pfKind, void *pvUser);
122
123static DECLCALLBACK(int) rtkldrGetSymbolEx(PRTLDRMODINTERNAL pMod, const void *pvBits, RTUINTPTR BaseAddress,
124 const char *pszSymbol, RTUINTPTR *pValue);
125
126
127
128/**
129 * Converts a kLdr error code to an IPRT one.
130 */
131static int rtkldrConvertError(int krc)
132{
133 if (!krc)
134 return VINF_SUCCESS;
135 switch (krc)
136 {
137 case KLDR_ERR_INVALID_PARAMETER: return VERR_INVALID_PARAMETER;
138 case KLDR_ERR_INVALID_HANDLE: return VERR_INVALID_HANDLE;
139 case KLDR_ERR_NO_MEMORY: return VERR_NO_MEMORY;
140
141
142 case KLDR_ERR_UNKNOWN_FORMAT:
143 case KLDR_ERR_MZ_NOT_SUPPORTED: return VERR_MZ_EXE_NOT_SUPPORTED;
144 case KLDR_ERR_NE_NOT_SUPPORTED: return VERR_NE_EXE_NOT_SUPPORTED;
145 case KLDR_ERR_LX_NOT_SUPPORTED: return VERR_LX_EXE_NOT_SUPPORTED;
146 case KLDR_ERR_LE_NOT_SUPPORTED: return VERR_LE_EXE_NOT_SUPPORTED;
147 case KLDR_ERR_PE_NOT_SUPPORTED: return VERR_PE_EXE_NOT_SUPPORTED;
148 case KLDR_ERR_ELF_NOT_SUPPORTED: return VERR_ELF_EXE_NOT_SUPPORTED;
149 case KLDR_ERR_MACHO_NOT_SUPPORTED: return VERR_INVALID_EXE_SIGNATURE;
150 case KLDR_ERR_AOUT_NOT_SUPPORTED: return VERR_AOUT_EXE_NOT_SUPPORTED;
151
152 case KLDR_ERR_MODULE_NOT_FOUND: return VERR_MODULE_NOT_FOUND;
153 case KLDR_ERR_PREREQUISITE_MODULE_NOT_FOUND: return VERR_MODULE_NOT_FOUND;
154 case KLDR_ERR_MAIN_STACK_ALLOC_FAILED: return VERR_NO_MEMORY;
155 case KLDR_ERR_BUFFER_OVERFLOW: return VERR_BUFFER_OVERFLOW;
156 case KLDR_ERR_SYMBOL_NOT_FOUND: return VERR_SYMBOL_NOT_FOUND;
157 case KLDR_ERR_FORWARDER_SYMBOL: return VERR_BAD_EXE_FORMAT;
158 case KLDR_ERR_BAD_FIXUP: return VERR_BAD_EXE_FORMAT;
159 case KLDR_ERR_IMPORT_ORDINAL_OUT_OF_BOUNDS: return VERR_BAD_EXE_FORMAT;
160 case KLDR_ERR_NO_DEBUG_INFO: return VERR_FILE_NOT_FOUND;
161 case KLDR_ERR_ALREADY_MAPPED: return VERR_WRONG_ORDER;
162 case KLDR_ERR_NOT_MAPPED: return VERR_WRONG_ORDER;
163 case KLDR_ERR_ADDRESS_OVERFLOW: return VERR_NUMBER_TOO_BIG;
164
165 case KLDR_ERR_NOT_LOADED_DYNAMICALLY:
166 case KLDR_ERR_ARCH_CPU_NOT_COMPATIBLE:
167 case KLDR_ERR_TOO_LONG_FORWARDER_CHAIN:
168 case KLDR_ERR_MODULE_TERMINATING:
169 case KLDR_ERR_PREREQUISITE_MODULE_TERMINATING:
170 case KLDR_ERR_MODULE_INIT_FAILED:
171 case KLDR_ERR_PREREQUISITE_MODULE_INIT_FAILED:
172 case KLDR_ERR_MODULE_INIT_FAILED_ALREADY:
173 case KLDR_ERR_PREREQUISITE_MODULE_INIT_FAILED_ALREADY:
174 case KLDR_ERR_PREREQUISITE_RECURSED_TOO_DEEPLY:
175 case KLDR_ERR_THREAD_ATTACH_FAILED:
176 case KLDR_ERR_TOO_MANY_MAPPINGS:
177 case KLDR_ERR_NOT_DLL:
178 case KLDR_ERR_NOT_EXE:
179 return VERR_GENERAL_FAILURE;
180
181
182 case KLDR_ERR_PE_UNSUPPORTED_MACHINE:
183 case KLDR_ERR_PE_BAD_FILE_HEADER:
184 case KLDR_ERR_PE_BAD_OPTIONAL_HEADER:
185 case KLDR_ERR_PE_BAD_SECTION_HEADER:
186 case KLDR_ERR_PE_BAD_FORWARDER:
187 case KLDR_ERR_PE_FORWARDER_IMPORT_NOT_FOUND:
188 case KLDR_ERR_PE_BAD_FIXUP:
189 case KLDR_ERR_PE_BAD_IMPORT:
190 return VERR_GENERAL_FAILURE;
191
192 case KLDR_ERR_LX_BAD_HEADER:
193 case KLDR_ERR_LX_BAD_LOADER_SECTION:
194 case KLDR_ERR_LX_BAD_FIXUP_SECTION:
195 case KLDR_ERR_LX_BAD_OBJECT_TABLE:
196 case KLDR_ERR_LX_BAD_PAGE_MAP:
197 case KLDR_ERR_LX_BAD_ITERDATA:
198 case KLDR_ERR_LX_BAD_ITERDATA2:
199 case KLDR_ERR_LX_BAD_BUNDLE:
200 case KLDR_ERR_LX_NO_SONAME:
201 case KLDR_ERR_LX_BAD_SONAME:
202 case KLDR_ERR_LX_BAD_FORWARDER:
203 case KLDR_ERR_LX_NRICHAIN_NOT_SUPPORTED:
204 return VERR_GENERAL_FAILURE;
205
206 default:
207 if (RT_FAILURE(krc))
208 return krc;
209 AssertMsgFailed(("krc=%d (%#x)\n", krc, krc));
210 return VERR_NO_TRANSLATION;
211 }
212}
213
214
215/**
216 * Converts a IPRT error code to an kLdr one.
217 */
218static int rtkldrConvertErrorFromIPRT(int rc)
219{
220 if (RT_SUCCESS(rc))
221 return 0;
222 switch (rc)
223 {
224 case VERR_NO_MEMORY: return KLDR_ERR_NO_MEMORY;
225 case VERR_INVALID_PARAMETER: return KLDR_ERR_INVALID_PARAMETER;
226 case VERR_INVALID_HANDLE: return KLDR_ERR_INVALID_HANDLE;
227 case VERR_BUFFER_OVERFLOW: return KLDR_ERR_BUFFER_OVERFLOW;
228 default:
229 return rc;
230 }
231}
232
233
234/*
235 *
236 *
237 * Misc Helpers Implemented using IPRT instead of kLdr/native APIs.
238 *
239 *
240 *
241 */
242
243
244int kldrHlpPageAlloc(void **ppv, size_t cb, KLDRPROT enmProt, unsigned fFixed)
245{
246 AssertReturn(fFixed, KLDR_ERR_INVALID_PARAMETER); /* fixed address allocation not supported. */
247
248 void *pv = RTMemPageAlloc(cb);
249 if (!pv)
250 return KLDR_ERR_NO_MEMORY;
251
252 int rc = kldrHlpPageProtect(pv, cb, enmProt);
253 if (!rc)
254 *ppv = pv;
255 else
256 RTMemPageFree(pv);
257 return rc;
258}
259
260
261int kldrHlpPageProtect(void *pv, size_t cb, KLDRPROT enmProt)
262{
263 unsigned fProtect;
264 switch (enmProt)
265 {
266 case KLDRPROT_NOACCESS:
267 fProtect = RTMEM_PROT_NONE;
268 break;
269 case KLDRPROT_READONLY:
270 fProtect = RTMEM_PROT_READ;
271 break;
272 case KLDRPROT_READWRITE:
273 fProtect = RTMEM_PROT_READ | RTMEM_PROT_WRITE;
274 break;
275 case KLDRPROT_EXECUTE:
276 fProtect = RTMEM_PROT_EXEC;
277 break;
278 case KLDRPROT_EXECUTE_READ:
279 fProtect = RTMEM_PROT_EXEC | RTMEM_PROT_READ;
280 break;
281 case KLDRPROT_EXECUTE_READWRITE:
282 case KLDRPROT_EXECUTE_WRITECOPY:
283 fProtect = RTMEM_PROT_EXEC | RTMEM_PROT_READ | RTMEM_PROT_WRITE;
284 break;
285 default:
286 AssertMsgFailed(("enmProt=%d\n", enmProt));
287 return KLDR_ERR_INVALID_PARAMETER;
288 }
289
290 int rc = RTMemProtect(pv, cb, fProtect);
291 if (RT_SUCCESS(rc))
292 return 0;
293 return rtkldrConvertErrorFromIPRT(rc);
294}
295
296
297int kldrHlpPageFree(void *pv, size_t cb)
298{
299 if (pv)
300 RTMemPageFree(pv);
301 return 0;
302}
303
304
305void * kldrHlpAlloc(size_t cb)
306{
307 return RTMemAlloc(cb);
308}
309
310
311void * kldrHlpAllocZ(size_t cb)
312{
313 return RTMemAllocZ(cb);
314}
315
316
317void kldrHlpFree(void *pv)
318{
319 return RTMemFree(pv);
320}
321
322
323char *kldrHlpGetFilename(const char *pszFilename)
324{
325 return RTPathFilename(pszFilename);
326}
327
328
329void kldrHlpAssertMsg(const char *pszExpr, const char *pszFile, unsigned iLine, const char *pszFunction)
330{
331 AssertMsg1(pszExpr, iLine, pszFile, pszFunction);
332}
333
334
335
336
337
338
339/**
340 * The file reader operations.
341 * We provide our own based on IPRT instead of using the kLdr ones.
342 */
343extern "C" const KLDRRDROPS g_kLdrRdrFileOps;
344extern "C" const KLDRRDROPS g_kLdrRdrFileOps =
345{
346 /* .pszName = */ "IPRT",
347 /* .pNext = */ NULL,
348 /* .pfnCreate = */ rtkldrRdrCreate,
349 /* .pfnDestroy = */ rtkldrRdrDestroy,
350 /* .pfnRead = */ rtkldrRdrRead,
351 /* .pfnAllMap = */ rtkldrRdrAllMap,
352 /* .pfnAllUnmap = */ rtkldrRdrAllUnmap,
353 /* .pfnSize = */ rtkldrRdrSize,
354 /* .pfnTell = */ rtkldrRdrTell,
355 /* .pfnName = */ rtkldrRdrName,
356 /* .pfnPageSize = */ rtkldrRdrPageSize,
357 /* .pfnMap = */ rtkldrRdrMap,
358 /* .pfnRefresh = */ rtkldrRdrRefresh,
359 /* .pfnProtect = */ rtkldrRdrProtect,
360 /* .pfnUnmap = */ rtkldrRdrUnmap,
361 /* .pfnDone = */ rtkldrRdrDone,
362 /* .u32Dummy = */ 42
363};
364
365
366/** @copydoc KLDRRDROPS::pfnCreate
367 * @remark This is a dummy which isn't used. */
368static int rtkldrRdrCreate( PPKLDRRDR ppRdr, const char *pszFilename)
369{
370 AssertReleaseFailed();
371 return -1;
372}
373
374
375/** @copydoc KLDRRDROPS::pfnDestroy */
376static int rtkldrRdrDestroy( PKLDRRDR pRdr)
377{
378 PRTLDRREADER pReader = ((PRTKLDRRDR)pRdr)->pReader;
379 int rc = pReader->pfnDestroy(pReader);
380 return rtkldrConvertErrorFromIPRT(rc);
381}
382
383
384/** @copydoc KLDRRDROPS::pfnRead */
385static int rtkldrRdrRead( PKLDRRDR pRdr, void *pvBuf, size_t cb, KLDRFOFF off)
386{
387 PRTLDRREADER pReader = ((PRTKLDRRDR)pRdr)->pReader;
388 int rc = pReader->pfnRead(pReader, pvBuf, cb, off);
389 return rtkldrConvertErrorFromIPRT(rc);
390}
391
392
393/** @copydoc KLDRRDROPS::pfnAllMap */
394static int rtkldrRdrAllMap( PKLDRRDR pRdr, const void **ppvBits)
395{
396 PRTLDRREADER pReader = ((PRTKLDRRDR)pRdr)->pReader;
397 int rc = pReader->pfnMap(pReader, ppvBits);
398 return rtkldrConvertErrorFromIPRT(rc);
399}
400
401
402/** @copydoc KLDRRDROPS::pfnAllUnmap */
403static int rtkldrRdrAllUnmap(PKLDRRDR pRdr, const void *pvBits)
404{
405 PRTLDRREADER pReader = ((PRTKLDRRDR)pRdr)->pReader;
406 int rc = pReader->pfnUnmap(pReader, pvBits);
407 return rtkldrConvertErrorFromIPRT(rc);
408}
409
410
411/** @copydoc KLDRRDROPS::pfnSize */
412static KLDRFOFF rtkldrRdrSize( PKLDRRDR pRdr)
413{
414 PRTLDRREADER pReader = ((PRTKLDRRDR)pRdr)->pReader;
415 return (KLDRFOFF)pReader->pfnSize(pReader);
416}
417
418
419/** @copydoc KLDRRDROPS::pfnTell */
420static KLDRFOFF rtkldrRdrTell( PKLDRRDR pRdr)
421{
422 PRTLDRREADER pReader = ((PRTKLDRRDR)pRdr)->pReader;
423 return (KLDRFOFF)pReader->pfnTell(pReader);
424}
425
426
427/** @copydoc KLDRRDROPS::pfnName */
428static const char * rtkldrRdrName(PKLDRRDR pRdr)
429{
430 PRTLDRREADER pReader = ((PRTKLDRRDR)pRdr)->pReader;
431 return pReader->pfnLogName(pReader);
432}
433
434
435/** @copydoc KLDRRDROPS::pfnPageSize */
436static size_t rtkldrRdrPageSize(PKLDRRDR pRdr)
437{
438 return PAGE_SIZE;
439}
440
441
442/** @copydoc KLDRRDROPS::pfnMap */
443static int rtkldrRdrMap( PKLDRRDR pRdr, void **ppvBase, uint32_t cSegments, PCKLDRSEG paSegments, unsigned fFixed)
444{
445 //PRTLDRREADER pReader = ((PRTKLDRRDR)pRdr)->pReader;
446 AssertFailed();
447 return -1;
448}
449
450
451/** @copydoc KLDRRDROPS::pfnRefresh */
452static int rtkldrRdrRefresh( PKLDRRDR pRdr, void *pvBase, uint32_t cSegments, PCKLDRSEG paSegments)
453{
454 //PRTLDRREADER pReader = ((PRTKLDRRDR)pRdr)->pReader;
455 AssertFailed();
456 return -1;
457}
458
459
460/** @copydoc KLDRRDROPS::pfnProtect */
461static int rtkldrRdrProtect( PKLDRRDR pRdr, void *pvBase, uint32_t cSegments, PCKLDRSEG paSegments, unsigned fUnprotectOrProtect)
462{
463 //PRTLDRREADER pReader = ((PRTKLDRRDR)pRdr)->pReader;
464 AssertFailed();
465 return -1;
466}
467
468
469/** @copydoc KLDRRDROPS::pfnUnmap */
470static int rtkldrRdrUnmap( PKLDRRDR pRdr, void *pvBase, uint32_t cSegments, PCKLDRSEG paSegments)
471{
472 //PRTLDRREADER pReader = ((PRTKLDRRDR)pRdr)->pReader;
473 AssertFailed();
474 return -1;
475}
476
477/** @copydoc KLDRRDROPS::pfnDone */
478static void rtkldrRdrDone( PKLDRRDR pRdr)
479{
480 //PRTLDRREADER pReader = ((PRTKLDRRDR)pRdr)->pReader;
481}
482
483
484
485
486
487
488/**
489 * Operations for a kLdr module.
490 */
491static const RTLDROPS g_rtkldrOps =
492{
493 "kLdr",
494 rtkldrClose,
495 NULL,
496 rtkldrDone,
497 rtkldrEnumSymbols,
498 /* ext */
499 rtkldrGetImageSize,
500 rtkldrGetBits,
501 rtkldrRelocate,
502 rtkldrGetSymbolEx,
503 42
504};
505
506
507/** @copydoc RTLDROPS::pfnClose */
508static DECLCALLBACK(int) rtkldrClose(PRTLDRMODINTERNAL pMod)
509{
510 PKLDRMOD pModkLdr = ((PRTLDRMODKLDR)pMod)->pMod;
511 int rc = kLdrModClose(pModkLdr);
512 return rtkldrConvertError(rc);
513}
514
515
516/** @copydoc RTLDROPS::pfnDone */
517static DECLCALLBACK(int) rtkldrDone(PRTLDRMODINTERNAL pMod)
518{
519 PKLDRMOD pModkLdr = ((PRTLDRMODKLDR)pMod)->pMod;
520 int rc = kLdrModMostlyDone(pModkLdr);
521 return rtkldrConvertError(rc);
522}
523
524
525/** @copydoc RTLDROPS::pfnEnumSymbols */
526static DECLCALLBACK(int) rtkldrEnumSymbols(PRTLDRMODINTERNAL pMod, unsigned fFlags, const void *pvBits, RTUINTPTR BaseAddress,
527 PFNRTLDRENUMSYMS pfnCallback, void *pvUser)
528{
529 PKLDRMOD pModkLdr = ((PRTLDRMODKLDR)pMod)->pMod;
530 RTLDRMODKLDRARGS Args;
531 Args.pvUser = pvUser;
532 Args.u.pfnEnumSyms = pfnCallback;
533 Args.pMod = (PRTLDRMODKLDR)pMod;
534 Args.pvBits = pvBits;
535 int rc = kLdrModEnumSymbols(pModkLdr, pvBits, BaseAddress,
536 fFlags & RTLDR_ENUM_SYMBOL_FLAGS_ALL ? KLDRMOD_ENUM_SYMS_FLAGS_ALL : 0,
537 rtkldrEnumSymbolsWrapper, &Args);
538 return rtkldrConvertError(rc);
539}
540
541
542/** @copydoc FNKLDRMODENUMSYMS */
543static int rtkldrEnumSymbolsWrapper(PKLDRMOD pMod, uint32_t iSymbol,
544 const char *pchSymbol, size_t cchSymbol, const char *pszVersion,
545 KLDRADDR uValue, uint32_t fKind, void *pvUser)
546{
547 PRTLDRMODKLDRARGS pArgs = (PRTLDRMODKLDRARGS)pvUser;
548
549 /* If not zero terminated we'll have to use a temporary buffer. */
550 const char *pszSymbol = pchSymbol;
551 if (pchSymbol && pchSymbol[cchSymbol])
552 {
553 char *psz = (char *)alloca(cchSymbol) + 1;
554 memcpy(psz, pchSymbol, cchSymbol);
555 psz[cchSymbol] = '\0';
556 pszSymbol = psz;
557 }
558
559#if defined(__OS2__) || (defined(__DARWIN__) && defined(__X86__))
560 /* skip the underscore prefix. */
561 if (*pszSymbol == '_')
562 pszSymbol++;
563#endif
564
565 int rc = pArgs->u.pfnEnumSyms(&pArgs->pMod->Core, pszSymbol, iSymbol, uValue, pArgs->pvUser);
566 if (RT_FAILURE(rc))
567 return rc; /* don't bother converting. */
568 return 0;
569}
570
571
572/** @copydoc RTLDROPS::pfnGetImageSize */
573static DECLCALLBACK(size_t) rtkldrGetImageSize(PRTLDRMODINTERNAL pMod)
574{
575 PKLDRMOD pModkLdr = ((PRTLDRMODKLDR)pMod)->pMod;
576 return kLdrModSize(pModkLdr);
577}
578
579
580/** @copydoc RTLDROPS::pfnGetBits */
581static DECLCALLBACK(int) rtkldrGetBits(PRTLDRMODINTERNAL pMod, void *pvBits, RTUINTPTR BaseAddress,
582 PFNRTLDRIMPORT pfnGetImport, void *pvUser)
583{
584 PKLDRMOD pModkLdr = ((PRTLDRMODKLDR)pMod)->pMod;
585 RTLDRMODKLDRARGS Args;
586 Args.pvUser = pvUser;
587 Args.u.pfnGetImport = pfnGetImport;
588 Args.pMod = (PRTLDRMODKLDR)pMod;
589 Args.pvBits = pvBits;
590 int rc = kLdrModGetBits(pModkLdr, pvBits, BaseAddress, rtkldrGetImportWrapper, &Args);
591 return rtkldrConvertError(rc);
592}
593
594
595/** @copydoc RTLDROPS::pfnRelocate */
596static DECLCALLBACK(int) rtkldrRelocate(PRTLDRMODINTERNAL pMod, void *pvBits, RTUINTPTR NewBaseAddress,
597 RTUINTPTR OldBaseAddress, PFNRTLDRIMPORT pfnGetImport, void *pvUser)
598{
599 PKLDRMOD pModkLdr = ((PRTLDRMODKLDR)pMod)->pMod;
600 RTLDRMODKLDRARGS Args;
601 Args.pvUser = pvUser;
602 Args.u.pfnGetImport = pfnGetImport;
603 Args.pMod = (PRTLDRMODKLDR)pMod;
604 Args.pvBits = pvBits;
605 int rc = kLdrModRelocateBits(pModkLdr, pvBits, NewBaseAddress, OldBaseAddress, rtkldrGetImportWrapper, &Args);
606 return rtkldrConvertError(rc);
607}
608
609
610/** @copydoc FNKLDRMODGETIMPORT */
611static int rtkldrGetImportWrapper(PKLDRMOD pMod, uint32_t iImport, uint32_t iSymbol, const char *pchSymbol, size_t cchSymbol,
612 const char *pszVersion, PKLDRADDR puValue, uint32_t *pfKind, void *pvUser)
613{
614 PRTLDRMODKLDRARGS pArgs = (PRTLDRMODKLDRARGS)pvUser;
615
616 /* If not zero terminated we'll have to use a temporary buffer. */
617 const char *pszSymbol = pchSymbol;
618 if (pchSymbol && pchSymbol[cchSymbol])
619 {
620 char *psz = (char *)alloca(cchSymbol) + 1;
621 memcpy(psz, pchSymbol, cchSymbol);
622 psz[cchSymbol] = '\0';
623 pszSymbol = psz;
624 }
625
626#if defined(__OS2__) || (defined(__DARWIN__) && defined(__X86__))
627 /* skip the underscore prefix. */
628 if (*pszSymbol == '_')
629 pszSymbol++;
630#endif
631
632 /* get the import module name - TODO: cache this */
633 const char *pszModule = NULL;
634 if (iImport != NIL_KLDRMOD_IMPORT)
635 {
636 char *pszBuf = (char *)alloca(64);
637 int rc = kLdrModGetImport(pMod, pArgs->pvBits, iImport, pszBuf, 64);
638 if (rc)
639 return rc;
640 pszModule = pszBuf;
641 }
642
643 /* do the query */
644 RTUINTPTR Value;
645 int rc = pArgs->u.pfnGetImport(&pArgs->pMod->Core, pszModule, pszSymbol, pszSymbol ? ~0 : iSymbol, &Value, pArgs->pvUser);
646 if (RT_SUCCESS(rc))
647 {
648 *puValue = Value;
649 return 0;
650 }
651 return rtkldrConvertErrorFromIPRT(rc);
652}
653
654
655
656/** @copydoc RTLDROPS::pfnGetSymbolEx */
657static DECLCALLBACK(int) rtkldrGetSymbolEx(PRTLDRMODINTERNAL pMod, const void *pvBits, RTUINTPTR BaseAddress,
658 const char *pszSymbol, RTUINTPTR *pValue)
659{
660 PKLDRMOD pModkLdr = ((PRTLDRMODKLDR)pMod)->pMod;
661 KLDRADDR uValue;
662
663#if defined(__OS2__) || (defined(__DARWIN__) && defined(__X86__))
664 /*
665 * Add underscore prefix.
666 */
667 if (pszSymbol)
668 {
669 size_t cch = strlen(pszSymbol);
670 char *psz = (char *)alloca(cch + 2);
671 memcpy(psz + 1, pszSymbol, cch + 1);
672 *psz = '_';
673 pszSymbol = psz;
674 }
675#endif
676
677 int rc = kLdrModQuerySymbol(pModkLdr, pvBits, BaseAddress,
678 NIL_KLDRMOD_SYM_ORDINAL, pszSymbol, strlen(pszSymbol), NULL,
679 NULL, NULL, &uValue, NULL);
680 if (!rc)
681 {
682 *pValue = uValue;
683 return VINF_SUCCESS;
684 }
685 return rtkldrConvertError(rc);
686}
687
688
689
690/**
691 * Open a image using kLdr.
692 *
693 * @returns iprt status code.
694 * @param pReader The loader reader instance which will provide the raw image bits.
695 * @param phLdrMod Where to store the handle.
696 */
697int rtldrkLdrOpen(PRTLDRREADER pReader, PRTLDRMOD phLdrMod)
698{
699 /* Create a rtkldrRdr instance. */
700 PRTKLDRRDR pRdr = (PRTKLDRRDR)RTMemAllocZ(sizeof(*pRdr));
701 if (!pRdr)
702 return VERR_NO_MEMORY;
703 pRdr->Core.u32Magic = KLDRRDR_MAGIC;
704 pRdr->Core.pOps = &g_kLdrRdrFileOps;
705 pRdr->pReader = pReader;
706
707 /* Try open it. */
708 PKLDRMOD pMod;
709 int krc = kLdrModOpenFromRdr(&pRdr->Core, &pMod);
710 if (!krc)
711 {
712 /* Create a module wrapper for it. */
713 PRTLDRMODKLDR pNewMod = (PRTLDRMODKLDR)RTMemAllocZ(sizeof(*pNewMod));
714 if (pNewMod)
715 {
716 pNewMod->Core.u32Magic = RTLDRMOD_MAGIC;
717 pNewMod->Core.eState = LDR_STATE_OPENED;
718 pNewMod->Core.pOps = &g_rtkldrOps;
719 pNewMod->pMod = pMod;
720 *phLdrMod = &pNewMod->Core;
721 return VINF_SUCCESS;
722 }
723 kLdrModClose(pMod);
724 krc = KLDR_ERR_NO_MEMORY;
725 }
726 return rtkldrConvertError(krc);
727}
728
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