VirtualBox

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

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

kStuff,IPRT: kStuff r23 -> r26, kLdrModOpenFromRdr got image selection support (for FAT/universal Mach-O images).

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