VirtualBox

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

Last change on this file since 16404 was 16404, checked in by vboxsync, 16 years ago

kStuff: some preps for the 64-bit mach-o code.

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette