VirtualBox

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

Last change on this file since 21743 was 21337, checked in by vboxsync, 15 years ago

IPRT,HostDrv,AddDrv: Export public IPRT symbols for the linux kernel (pain).

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