VirtualBox

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

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

eol style native

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