VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/ldr/ldrkStuff.cpp@ 7689

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

The Giant CDDL Dual-License Header Change.

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