VirtualBox

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

Last change on this file since 331 was 1, checked in by vboxsync, 55 years ago

import

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