VirtualBox

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

Last change on this file since 35708 was 28800, checked in by vboxsync, 14 years ago

Automated rebranding to Oracle copyright/license strings via filemuncher

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