VirtualBox

source: vbox/trunk/src/VBox/Runtime/ldrkLdr.cpp@ 4071

最後變更 在這個檔案從4071是 4071,由 vboxsync 提交於 18 年 前

Biggest check-in ever. New source code headers for all (C) innotek files.

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

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