VirtualBox

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

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

IPRT: More debug info & ldr stuff.

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Id
檔案大小: 28.8 KB
 
1/* $Id: ldrkStuff.cpp 38581 2011-08-31 12:43:26Z 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.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 (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 PFNRTLDRENUMDBG pfnEnumDbgInfo;
89 PFNRTLDRENUMSYMS pfnEnumSyms;
90 PFNRTLDRIMPORT pfnGetImport;
91 } u;
92 void *pvUser;
93 const void *pvBits;
94 PRTLDRMODKLDR pMod;
95 int rc;
96} RTLDRMODKLDRARGS, *PRTLDRMODKLDRARGS;
97
98
99/**
100 * Converts a kLdr error code to an IPRT one.
101 */
102static int rtkldrConvertError(int krc)
103{
104 if (!krc)
105 return VINF_SUCCESS;
106 switch (krc)
107 {
108 case KERR_INVALID_PARAMETER: return VERR_INVALID_PARAMETER;
109 case KERR_INVALID_HANDLE: return VERR_INVALID_HANDLE;
110 case KERR_NO_MEMORY: return VERR_NO_MEMORY;
111
112
113 case KLDR_ERR_UNKNOWN_FORMAT:
114 case KLDR_ERR_MZ_NOT_SUPPORTED: return VERR_MZ_EXE_NOT_SUPPORTED;
115 case KLDR_ERR_NE_NOT_SUPPORTED: return VERR_NE_EXE_NOT_SUPPORTED;
116 case KLDR_ERR_LX_NOT_SUPPORTED: return VERR_LX_EXE_NOT_SUPPORTED;
117 case KLDR_ERR_LE_NOT_SUPPORTED: return VERR_LE_EXE_NOT_SUPPORTED;
118 case KLDR_ERR_PE_NOT_SUPPORTED: return VERR_PE_EXE_NOT_SUPPORTED;
119 case KLDR_ERR_ELF_NOT_SUPPORTED: return VERR_ELF_EXE_NOT_SUPPORTED;
120 case KLDR_ERR_MACHO_NOT_SUPPORTED: return VERR_INVALID_EXE_SIGNATURE;
121 case KLDR_ERR_AOUT_NOT_SUPPORTED: return VERR_AOUT_EXE_NOT_SUPPORTED;
122
123 case KLDR_ERR_MODULE_NOT_FOUND: return VERR_MODULE_NOT_FOUND;
124 case KLDR_ERR_PREREQUISITE_MODULE_NOT_FOUND: return VERR_MODULE_NOT_FOUND;
125 case KLDR_ERR_MAIN_STACK_ALLOC_FAILED: return VERR_NO_MEMORY;
126 case KERR_BUFFER_OVERFLOW: return VERR_BUFFER_OVERFLOW;
127 case KLDR_ERR_SYMBOL_NOT_FOUND: return VERR_SYMBOL_NOT_FOUND;
128 case KLDR_ERR_FORWARDER_SYMBOL: return VERR_BAD_EXE_FORMAT;
129 case KLDR_ERR_BAD_FIXUP: AssertMsgFailedReturn(("KLDR_ERR_BAD_FIXUP\n"), VERR_BAD_EXE_FORMAT);
130 case KLDR_ERR_IMPORT_ORDINAL_OUT_OF_BOUNDS: return VERR_BAD_EXE_FORMAT;
131 case KLDR_ERR_NO_DEBUG_INFO: return VERR_FILE_NOT_FOUND;
132 case KLDR_ERR_ALREADY_MAPPED: return VERR_WRONG_ORDER;
133 case KLDR_ERR_NOT_MAPPED: return VERR_WRONG_ORDER;
134 case KLDR_ERR_ADDRESS_OVERFLOW: return VERR_NUMBER_TOO_BIG;
135 case KLDR_ERR_TODO: return VERR_NOT_IMPLEMENTED;
136
137 case KLDR_ERR_NOT_LOADED_DYNAMICALLY:
138 case KCPU_ERR_ARCH_CPU_NOT_COMPATIBLE:
139 case KLDR_ERR_TOO_LONG_FORWARDER_CHAIN:
140 case KLDR_ERR_MODULE_TERMINATING:
141 case KLDR_ERR_PREREQUISITE_MODULE_TERMINATING:
142 case KLDR_ERR_MODULE_INIT_FAILED:
143 case KLDR_ERR_PREREQUISITE_MODULE_INIT_FAILED:
144 case KLDR_ERR_MODULE_INIT_FAILED_ALREADY:
145 case KLDR_ERR_PREREQUISITE_MODULE_INIT_FAILED_ALREADY:
146 case KLDR_ERR_PREREQUISITE_RECURSED_TOO_DEEPLY:
147 case KLDR_ERR_THREAD_ATTACH_FAILED:
148 case KRDR_ERR_TOO_MANY_MAPPINGS:
149 case KLDR_ERR_NOT_DLL:
150 case KLDR_ERR_NOT_EXE:
151 AssertMsgFailedReturn(("krc=%d (%#x): %s\n", krc, krc, kErrName(krc)), VERR_GENERAL_FAILURE);
152
153
154 case KLDR_ERR_PE_UNSUPPORTED_MACHINE:
155 case KLDR_ERR_PE_BAD_FILE_HEADER:
156 case KLDR_ERR_PE_BAD_OPTIONAL_HEADER:
157 case KLDR_ERR_PE_BAD_SECTION_HEADER:
158 case KLDR_ERR_PE_BAD_FORWARDER:
159 case KLDR_ERR_PE_FORWARDER_IMPORT_NOT_FOUND:
160 case KLDR_ERR_PE_BAD_FIXUP:
161 case KLDR_ERR_PE_BAD_IMPORT:
162 AssertMsgFailedReturn(("krc=%d (%#x): %s\n", krc, krc, kErrName(krc)), VERR_GENERAL_FAILURE);
163
164 case KLDR_ERR_LX_BAD_HEADER:
165 case KLDR_ERR_LX_BAD_LOADER_SECTION:
166 case KLDR_ERR_LX_BAD_FIXUP_SECTION:
167 case KLDR_ERR_LX_BAD_OBJECT_TABLE:
168 case KLDR_ERR_LX_BAD_PAGE_MAP:
169 case KLDR_ERR_LX_BAD_ITERDATA:
170 case KLDR_ERR_LX_BAD_ITERDATA2:
171 case KLDR_ERR_LX_BAD_BUNDLE:
172 case KLDR_ERR_LX_NO_SONAME:
173 case KLDR_ERR_LX_BAD_SONAME:
174 case KLDR_ERR_LX_BAD_FORWARDER:
175 case KLDR_ERR_LX_NRICHAIN_NOT_SUPPORTED:
176 AssertMsgFailedReturn(("krc=%d (%#x): %s\n", krc, krc, kErrName(krc)), VERR_GENERAL_FAILURE);
177
178 case KLDR_ERR_MACHO_OTHER_ENDIAN_NOT_SUPPORTED:
179 case KLDR_ERR_MACHO_BAD_HEADER:
180 case KLDR_ERR_MACHO_UNSUPPORTED_FILE_TYPE:
181 case KLDR_ERR_MACHO_UNSUPPORTED_MACHINE:
182 case KLDR_ERR_MACHO_BAD_LOAD_COMMAND:
183 case KLDR_ERR_MACHO_UNKNOWN_LOAD_COMMAND:
184 case KLDR_ERR_MACHO_UNSUPPORTED_LOAD_COMMAND:
185 case KLDR_ERR_MACHO_BAD_SECTION:
186 case KLDR_ERR_MACHO_UNSUPPORTED_SECTION:
187#ifdef KLDR_ERR_MACHO_UNSUPPORTED_INIT_SECTION
188 case KLDR_ERR_MACHO_UNSUPPORTED_INIT_SECTION:
189 case KLDR_ERR_MACHO_UNSUPPORTED_TERM_SECTION:
190#endif
191 case KLDR_ERR_MACHO_UNKNOWN_SECTION:
192 case KLDR_ERR_MACHO_BAD_SECTION_ORDER:
193 case KLDR_ERR_MACHO_BIT_MIX:
194 case KLDR_ERR_MACHO_BAD_OBJECT_FILE:
195 case KLDR_ERR_MACHO_BAD_SYMBOL:
196 case KLDR_ERR_MACHO_UNSUPPORTED_FIXUP_TYPE:
197 AssertMsgFailedReturn(("krc=%d (%#x): %s\n", krc, krc, kErrName(krc)), VERR_GENERAL_FAILURE);
198
199 default:
200 if (RT_FAILURE(krc))
201 return krc;
202 AssertMsgFailedReturn(("krc=%d (%#x): %s\n", krc, krc, kErrName(krc)), VERR_NO_TRANSLATION);
203 }
204}
205
206
207/**
208 * Converts a IPRT error code to an kLdr one.
209 */
210static int rtkldrConvertErrorFromIPRT(int rc)
211{
212 if (RT_SUCCESS(rc))
213 return 0;
214 switch (rc)
215 {
216 case VERR_NO_MEMORY: return KERR_NO_MEMORY;
217 case VERR_INVALID_PARAMETER: return KERR_INVALID_PARAMETER;
218 case VERR_INVALID_HANDLE: return KERR_INVALID_HANDLE;
219 case VERR_BUFFER_OVERFLOW: return KERR_BUFFER_OVERFLOW;
220 default:
221 return rc;
222 }
223}
224
225
226
227
228
229
230/** @copydoc KLDRRDROPS::pfnCreate
231 * @remark This is a dummy which isn't used. */
232static int rtkldrRdr_Create( PPKRDR ppRdr, const char *pszFilename)
233{
234 AssertReleaseFailed();
235 return -1;
236}
237
238
239/** @copydoc KLDRRDROPS::pfnDestroy */
240static int rtkldrRdr_Destroy( PKRDR pRdr)
241{
242 PRTLDRREADER pReader = ((PRTKLDRRDR)pRdr)->pReader;
243 int rc = pReader->pfnDestroy(pReader);
244 return rtkldrConvertErrorFromIPRT(rc);
245}
246
247
248/** @copydoc KLDRRDROPS::pfnRead */
249static int rtkldrRdr_Read( PKRDR pRdr, void *pvBuf, KSIZE cb, KFOFF off)
250{
251 PRTLDRREADER pReader = ((PRTKLDRRDR)pRdr)->pReader;
252 int rc = pReader->pfnRead(pReader, pvBuf, cb, off);
253 return rtkldrConvertErrorFromIPRT(rc);
254}
255
256
257/** @copydoc KLDRRDROPS::pfnAllMap */
258static int rtkldrRdr_AllMap( PKRDR pRdr, const void **ppvBits)
259{
260 PRTLDRREADER pReader = ((PRTKLDRRDR)pRdr)->pReader;
261 int rc = pReader->pfnMap(pReader, ppvBits);
262 return rtkldrConvertErrorFromIPRT(rc);
263}
264
265
266/** @copydoc KLDRRDROPS::pfnAllUnmap */
267static int rtkldrRdr_AllUnmap(PKRDR pRdr, const void *pvBits)
268{
269 PRTLDRREADER pReader = ((PRTKLDRRDR)pRdr)->pReader;
270 int rc = pReader->pfnUnmap(pReader, pvBits);
271 return rtkldrConvertErrorFromIPRT(rc);
272}
273
274
275/** @copydoc KLDRRDROPS::pfnSize */
276static KFOFF rtkldrRdr_Size( PKRDR pRdr)
277{
278 PRTLDRREADER pReader = ((PRTKLDRRDR)pRdr)->pReader;
279 return (KFOFF)pReader->pfnSize(pReader);
280}
281
282
283/** @copydoc KLDRRDROPS::pfnTell */
284static KFOFF rtkldrRdr_Tell( PKRDR pRdr)
285{
286 PRTLDRREADER pReader = ((PRTKLDRRDR)pRdr)->pReader;
287 return (KFOFF)pReader->pfnTell(pReader);
288}
289
290
291/** @copydoc KLDRRDROPS::pfnName */
292static const char * rtkldrRdr_Name(PKRDR pRdr)
293{
294 PRTLDRREADER pReader = ((PRTKLDRRDR)pRdr)->pReader;
295 return pReader->pfnLogName(pReader);
296}
297
298
299/** @copydoc KLDRRDROPS::pfnNativeFH */
300static KIPTR rtkldrRdr_NativeFH(PKRDR pRdr)
301{
302 AssertFailed();
303 return -1;
304}
305
306
307/** @copydoc KLDRRDROPS::pfnPageSize */
308static KSIZE rtkldrRdr_PageSize(PKRDR pRdr)
309{
310 return PAGE_SIZE;
311}
312
313
314/** @copydoc KLDRRDROPS::pfnMap */
315static int rtkldrRdr_Map( PKRDR pRdr, void **ppvBase, KU32 cSegments, PCKLDRSEG paSegments, KBOOL fFixed)
316{
317 //PRTLDRREADER pReader = ((PRTKLDRRDR)pRdr)->pReader;
318 AssertFailed();
319 return -1;
320}
321
322
323/** @copydoc KLDRRDROPS::pfnRefresh */
324static int rtkldrRdr_Refresh( PKRDR pRdr, void *pvBase, KU32 cSegments, PCKLDRSEG paSegments)
325{
326 //PRTLDRREADER pReader = ((PRTKLDRRDR)pRdr)->pReader;
327 AssertFailed();
328 return -1;
329}
330
331
332/** @copydoc KLDRRDROPS::pfnProtect */
333static int rtkldrRdr_Protect( PKRDR pRdr, void *pvBase, KU32 cSegments, PCKLDRSEG paSegments, KBOOL fUnprotectOrProtect)
334{
335 //PRTLDRREADER pReader = ((PRTKLDRRDR)pRdr)->pReader;
336 AssertFailed();
337 return -1;
338}
339
340
341/** @copydoc KLDRRDROPS::pfnUnmap */
342static int rtkldrRdr_Unmap( PKRDR pRdr, void *pvBase, KU32 cSegments, PCKLDRSEG paSegments)
343{
344 //PRTLDRREADER pReader = ((PRTKLDRRDR)pRdr)->pReader;
345 AssertFailed();
346 return -1;
347}
348
349/** @copydoc KLDRRDROPS::pfnDone */
350static void rtkldrRdr_Done( PKRDR pRdr)
351{
352 //PRTLDRREADER pReader = ((PRTKLDRRDR)pRdr)->pReader;
353}
354
355
356/**
357 * The file reader operations.
358 * We provide our own based on IPRT instead of using the kLdr ones.
359 */
360extern "C" const KRDROPS g_kLdrRdrFileOps;
361extern "C" const KRDROPS g_kLdrRdrFileOps =
362{
363 /* .pszName = */ "IPRT",
364 /* .pNext = */ NULL,
365 /* .pfnCreate = */ rtkldrRdr_Create,
366 /* .pfnDestroy = */ rtkldrRdr_Destroy,
367 /* .pfnRead = */ rtkldrRdr_Read,
368 /* .pfnAllMap = */ rtkldrRdr_AllMap,
369 /* .pfnAllUnmap = */ rtkldrRdr_AllUnmap,
370 /* .pfnSize = */ rtkldrRdr_Size,
371 /* .pfnTell = */ rtkldrRdr_Tell,
372 /* .pfnName = */ rtkldrRdr_Name,
373 /* .pfnNativeFH = */ rtkldrRdr_NativeFH,
374 /* .pfnPageSize = */ rtkldrRdr_PageSize,
375 /* .pfnMap = */ rtkldrRdr_Map,
376 /* .pfnRefresh = */ rtkldrRdr_Refresh,
377 /* .pfnProtect = */ rtkldrRdr_Protect,
378 /* .pfnUnmap = */ rtkldrRdr_Unmap,
379 /* .pfnDone = */ rtkldrRdr_Done,
380 /* .u32Dummy = */ 42
381};
382
383
384
385
386
387/** @copydoc RTLDROPS::pfnClose */
388static DECLCALLBACK(int) rtkldr_Close(PRTLDRMODINTERNAL pMod)
389{
390 PKLDRMOD pModkLdr = ((PRTLDRMODKLDR)pMod)->pMod;
391 int rc = kLdrModClose(pModkLdr);
392 return rtkldrConvertError(rc);
393}
394
395
396/** @copydoc RTLDROPS::pfnDone */
397static DECLCALLBACK(int) rtkldr_Done(PRTLDRMODINTERNAL pMod)
398{
399 PKLDRMOD pModkLdr = ((PRTLDRMODKLDR)pMod)->pMod;
400 int rc = kLdrModMostlyDone(pModkLdr);
401 return rtkldrConvertError(rc);
402}
403
404
405/** @copydoc FNKLDRMODENUMSYMS */
406static int rtkldrEnumSymbolsWrapper(PKLDRMOD pMod, uint32_t iSymbol,
407 const char *pchSymbol, KSIZE cchSymbol, const char *pszVersion,
408 KLDRADDR uValue, uint32_t fKind, void *pvUser)
409{
410 PRTLDRMODKLDRARGS pArgs = (PRTLDRMODKLDRARGS)pvUser;
411
412 /* If not zero terminated we'll have to use a temporary buffer. */
413 const char *pszSymbol = pchSymbol;
414 if (pchSymbol && pchSymbol[cchSymbol])
415 {
416 char *psz = (char *)alloca(cchSymbol) + 1;
417 memcpy(psz, pchSymbol, cchSymbol);
418 psz[cchSymbol] = '\0';
419 pszSymbol = psz;
420 }
421
422#if defined(RT_OS_OS2) || defined(RT_OS_DARWIN)
423 /* skip the underscore prefix. */
424 if (*pszSymbol == '_')
425 pszSymbol++;
426#endif
427
428 int rc = pArgs->u.pfnEnumSyms(&pArgs->pMod->Core, pszSymbol, iSymbol, uValue, pArgs->pvUser);
429 if (RT_FAILURE(rc))
430 return rc; /* don't bother converting. */
431 return 0;
432}
433
434
435/** @copydoc RTLDROPS::pfnEnumSymbols */
436static DECLCALLBACK(int) rtkldr_EnumSymbols(PRTLDRMODINTERNAL pMod, unsigned fFlags, const void *pvBits, RTUINTPTR BaseAddress,
437 PFNRTLDRENUMSYMS pfnCallback, void *pvUser)
438{
439 PKLDRMOD pModkLdr = ((PRTLDRMODKLDR)pMod)->pMod;
440 RTLDRMODKLDRARGS Args;
441 Args.pvUser = pvUser;
442 Args.u.pfnEnumSyms = pfnCallback;
443 Args.pMod = (PRTLDRMODKLDR)pMod;
444 Args.pvBits = pvBits;
445 Args.rc = VINF_SUCCESS;
446 int rc = kLdrModEnumSymbols(pModkLdr, pvBits, BaseAddress,
447 fFlags & RTLDR_ENUM_SYMBOL_FLAGS_ALL ? KLDRMOD_ENUM_SYMS_FLAGS_ALL : 0,
448 rtkldrEnumSymbolsWrapper, &Args);
449 if (Args.rc != VINF_SUCCESS)
450 rc = Args.rc;
451 else
452 rc = rtkldrConvertError(rc);
453 return rc;
454}
455
456
457/** @copydoc RTLDROPS::pfnGetImageSize */
458static DECLCALLBACK(size_t) rtkldr_GetImageSize(PRTLDRMODINTERNAL pMod)
459{
460 PKLDRMOD pModkLdr = ((PRTLDRMODKLDR)pMod)->pMod;
461 return kLdrModSize(pModkLdr);
462}
463
464
465/** @copydoc FNKLDRMODGETIMPORT */
466static int rtkldrGetImportWrapper(PKLDRMOD pMod, uint32_t iImport, uint32_t iSymbol, const char *pchSymbol, KSIZE cchSymbol,
467 const char *pszVersion, PKLDRADDR puValue, uint32_t *pfKind, void *pvUser)
468{
469 PRTLDRMODKLDRARGS pArgs = (PRTLDRMODKLDRARGS)pvUser;
470
471 /* If not zero terminated we'll have to use a temporary buffer. */
472 const char *pszSymbol = pchSymbol;
473 if (pchSymbol && pchSymbol[cchSymbol])
474 {
475 char *psz = (char *)alloca(cchSymbol) + 1;
476 memcpy(psz, pchSymbol, cchSymbol);
477 psz[cchSymbol] = '\0';
478 pszSymbol = psz;
479 }
480
481#if defined(RT_OS_OS2) || defined(RT_OS_DARWIN)
482 /* skip the underscore prefix. */
483 if (*pszSymbol == '_')
484 pszSymbol++;
485#endif
486
487 /* get the import module name - TODO: cache this */
488 const char *pszModule = NULL;
489 if (iImport != NIL_KLDRMOD_IMPORT)
490 {
491 char *pszBuf = (char *)alloca(64);
492 int rc = kLdrModGetImport(pMod, pArgs->pvBits, iImport, pszBuf, 64);
493 if (rc)
494 return rc;
495 pszModule = pszBuf;
496 }
497
498 /* do the query */
499 RTUINTPTR Value;
500 int rc = pArgs->u.pfnGetImport(&pArgs->pMod->Core, pszModule, pszSymbol, pszSymbol ? ~0 : iSymbol, &Value, pArgs->pvUser);
501 if (RT_SUCCESS(rc))
502 {
503 *puValue = Value;
504 return 0;
505 }
506 return rtkldrConvertErrorFromIPRT(rc);
507}
508
509
510/** @copydoc RTLDROPS::pfnGetBits */
511static DECLCALLBACK(int) rtkldr_GetBits(PRTLDRMODINTERNAL pMod, void *pvBits, RTUINTPTR BaseAddress,
512 PFNRTLDRIMPORT pfnGetImport, void *pvUser)
513{
514 PKLDRMOD pModkLdr = ((PRTLDRMODKLDR)pMod)->pMod;
515 RTLDRMODKLDRARGS Args;
516 Args.pvUser = pvUser;
517 Args.u.pfnGetImport = pfnGetImport;
518 Args.pMod = (PRTLDRMODKLDR)pMod;
519 Args.pvBits = pvBits;
520 Args.rc = VINF_SUCCESS;
521 int rc = kLdrModGetBits(pModkLdr, pvBits, BaseAddress, rtkldrGetImportWrapper, &Args);
522 if (Args.rc != VINF_SUCCESS)
523 rc = Args.rc;
524 else
525 rc = rtkldrConvertError(rc);
526 return rc;
527}
528
529
530/** @copydoc RTLDROPS::pfnRelocate */
531static DECLCALLBACK(int) rtkldr_Relocate(PRTLDRMODINTERNAL pMod, void *pvBits, RTUINTPTR NewBaseAddress,
532 RTUINTPTR OldBaseAddress, PFNRTLDRIMPORT pfnGetImport, void *pvUser)
533{
534 PKLDRMOD pModkLdr = ((PRTLDRMODKLDR)pMod)->pMod;
535 RTLDRMODKLDRARGS Args;
536 Args.pvUser = pvUser;
537 Args.u.pfnGetImport = pfnGetImport;
538 Args.pMod = (PRTLDRMODKLDR)pMod;
539 Args.pvBits = pvBits;
540 Args.rc = VINF_SUCCESS;
541 int rc = kLdrModRelocateBits(pModkLdr, pvBits, NewBaseAddress, OldBaseAddress, rtkldrGetImportWrapper, &Args);
542 if (Args.rc != VINF_SUCCESS)
543 rc = Args.rc;
544 else
545 rc = rtkldrConvertError(rc);
546 return rc;
547}
548
549
550/** @copydoc RTLDROPS::pfnGetSymbolEx */
551static DECLCALLBACK(int) rtkldr_GetSymbolEx(PRTLDRMODINTERNAL pMod, const void *pvBits, RTUINTPTR BaseAddress,
552 const char *pszSymbol, RTUINTPTR *pValue)
553{
554 PKLDRMOD pModkLdr = ((PRTLDRMODKLDR)pMod)->pMod;
555 KLDRADDR uValue;
556
557#if defined(RT_OS_OS2) || defined(RT_OS_DARWIN)
558 /*
559 * Add underscore prefix.
560 */
561 if (pszSymbol)
562 {
563 size_t cch = strlen(pszSymbol);
564 char *psz = (char *)alloca(cch + 2);
565 memcpy(psz + 1, pszSymbol, cch + 1);
566 *psz = '_';
567 pszSymbol = psz;
568 }
569#endif
570
571 int rc = kLdrModQuerySymbol(pModkLdr, pvBits, BaseAddress,
572 NIL_KLDRMOD_SYM_ORDINAL, pszSymbol, strlen(pszSymbol), NULL,
573 NULL, NULL, &uValue, NULL);
574 if (!rc)
575 {
576 *pValue = uValue;
577 return VINF_SUCCESS;
578 }
579 return rtkldrConvertError(rc);
580}
581
582
583/** @copydoc FNKLDRENUMDBG */
584static int rtkldrEnumDbgInfoWrapper(PKLDRMOD pMod, KU32 iDbgInfo, KLDRDBGINFOTYPE enmType, KI16 iMajorVer, KI16 iMinorVer,
585 const char *pszPartNm, KLDRFOFF offFile, KLDRADDR LinkAddress, KLDRSIZE cb,
586 const char *pszExtFile, void *pvUser)
587{
588 PRTLDRMODKLDRARGS pArgs = (PRTLDRMODKLDRARGS)pvUser;
589
590 RTLDRDBGINFOTYPE enmMyType;
591 switch (enmType)
592 {
593 case KLDRDBGINFOTYPE_UNKNOWN: enmMyType = RTLDRDBGINFOTYPE_UNKNOWN; break;
594 case KLDRDBGINFOTYPE_STABS: enmMyType = RTLDRDBGINFOTYPE_STABS; break;
595 case KLDRDBGINFOTYPE_DWARF: enmMyType = RTLDRDBGINFOTYPE_DWARF; break;
596 case KLDRDBGINFOTYPE_CODEVIEW: enmMyType = RTLDRDBGINFOTYPE_CODEVIEW; break;
597 case KLDRDBGINFOTYPE_WATCOM: enmMyType = RTLDRDBGINFOTYPE_WATCOM; break;
598 case KLDRDBGINFOTYPE_HLL: enmMyType = RTLDRDBGINFOTYPE_HLL; break;
599 default:
600 AssertFailed();
601 enmMyType = RTLDRDBGINFOTYPE_UNKNOWN;
602 break;
603 }
604
605 int rc = pArgs->u.pfnEnumDbgInfo(&pArgs->pMod->Core, iDbgInfo, enmMyType, iMajorVer, iMinorVer, pszPartNm,
606 offFile, LinkAddress, cb, pszExtFile, pArgs->pvUser);
607 if (RT_FAILURE(rc))
608 return rc; /* don't bother converting. */
609 return 0;
610}
611
612
613/** @copydoc RTLDROPS::pfnEnumDbgInfo */
614static DECLCALLBACK(int) rtkldr_EnumDbgInfo(PRTLDRMODINTERNAL pMod, const void *pvBits,
615 PFNRTLDRENUMDBG pfnCallback, void *pvUser)
616{
617 PRTLDRMODKLDR pThis = (PRTLDRMODKLDR)pMod;
618 RTLDRMODKLDRARGS Args;
619 Args.pvUser = pvUser;
620 Args.u.pfnEnumDbgInfo = pfnCallback;
621 Args.pvBits = pvBits;
622 Args.pMod = pThis;
623 Args.rc = VINF_SUCCESS;
624 int rc = kLdrModEnumDbgInfo(pThis->pMod, pvBits, rtkldrEnumDbgInfoWrapper, &Args);
625 if (Args.rc != VINF_SUCCESS)
626 rc = Args.rc;
627 return rc;
628}
629
630
631/** @copydoc RTLDROPS::pfnEnumSegments. */
632static DECLCALLBACK(int) rtkldr_EnumSegments(PRTLDRMODINTERNAL pMod, PFNRTLDRENUMSEGS pfnCallback, void *pvUser)
633{
634 PRTLDRMODKLDR pThis = (PRTLDRMODKLDR)pMod;
635 uint32_t const cSegments = pThis->pMod->cSegments;
636 PCKLDRSEG paSegments = &pThis->pMod->aSegments[0];
637
638 for (uint32_t iSeg = 0; iSeg < cSegments; iSeg++)
639 {
640 RTLDRSEG Seg;
641
642 Seg.pchName = paSegments[iSeg].pchName;
643 Seg.cchName = paSegments[iSeg].cchName;
644 Seg.SelFlat = paSegments[iSeg].SelFlat;
645 Seg.Sel16bit = paSegments[iSeg].Sel16bit;
646 Seg.fFlags = paSegments[iSeg].fFlags;
647 AssertCompile(KLDRSEG_FLAG_16BIT == RTLDRSEG_FLAG_16BIT );
648 AssertCompile(KLDRSEG_FLAG_OS2_ALIAS16 == RTLDRSEG_FLAG_OS2_ALIAS16);
649 AssertCompile(KLDRSEG_FLAG_OS2_CONFORM == RTLDRSEG_FLAG_OS2_CONFORM);
650 AssertCompile(KLDRSEG_FLAG_OS2_IOPL == RTLDRSEG_FLAG_OS2_IOPL );
651
652 switch (paSegments[iSeg].enmProt)
653 {
654 default:
655 AssertMsgFailed(("%d\n", paSegments[iSeg].enmProt));
656 case KPROT_NOACCESS:
657 Seg.fProt = 0;
658 break;
659
660 case KPROT_READONLY: Seg.fProt = RTMEM_PROT_READ; break;
661 case KPROT_READWRITE: Seg.fProt = RTMEM_PROT_READ | RTMEM_PROT_WRITE; break;
662 case KPROT_WRITECOPY: Seg.fProt = RTMEM_PROT_WRITE; break;
663 case KPROT_EXECUTE: Seg.fProt = RTMEM_PROT_EXEC; break;
664 case KPROT_EXECUTE_READ: Seg.fProt = RTMEM_PROT_EXEC | RTMEM_PROT_READ; break;
665 case KPROT_EXECUTE_READWRITE: Seg.fProt = RTMEM_PROT_EXEC | RTMEM_PROT_READ | RTMEM_PROT_WRITE; break;
666 case KPROT_EXECUTE_WRITECOPY: Seg.fProt = RTMEM_PROT_EXEC | RTMEM_PROT_WRITE; break;
667 }
668 Seg.cb = paSegments[iSeg].cb;
669 Seg.Alignment = paSegments[iSeg].Alignment;
670 Seg.LinkAddress = paSegments[iSeg].LinkAddress;
671 Seg.offFile = paSegments[iSeg].offFile;
672 Seg.cbFile = paSegments[iSeg].cbFile;
673 Seg.RVA = paSegments[iSeg].RVA;
674 Seg.cbMapped = paSegments[iSeg].cbMapped;
675
676 int rc = pfnCallback(pMod, &Seg, pvUser);
677 if (rc != VINF_SUCCESS)
678 return rc;
679 }
680
681 return VINF_SUCCESS;
682}
683
684
685/** @copydoc RTLDROPS::pfnLinkAddressToSegOffset. */
686static DECLCALLBACK(int) rtkldr_LinkAddressToSegOffset(PRTLDRMODINTERNAL pMod, RTLDRADDR LinkAddress,
687 uint32_t *piSeg, PRTLDRADDR poffSeg)
688{
689 PRTLDRMODKLDR pThis = (PRTLDRMODKLDR)pMod;
690 uint32_t const cSegments = pThis->pMod->cSegments;
691 PCKLDRSEG paSegments = &pThis->pMod->aSegments[0];
692
693 for (uint32_t iSeg = 0; iSeg < cSegments; iSeg++)
694 {
695 KLDRADDR offSeg = LinkAddress - paSegments[iSeg].LinkAddress;
696 if ( offSeg < paSegments[iSeg].cbMapped
697 || offSeg < paSegments[iSeg].cb)
698 {
699 *piSeg = iSeg;
700 *poffSeg = offSeg;
701 return VINF_SUCCESS;
702 }
703 }
704
705 return VERR_LDR_INVALID_LINK_ADDRESS;
706}
707
708
709/** @copydoc RTLDROPS::pfnLinkAddressToRva. */
710static DECLCALLBACK(int) rtkldr_LinkAddressToRva(PRTLDRMODINTERNAL pMod, RTLDRADDR LinkAddress, PRTLDRADDR pRva)
711{
712 PRTLDRMODKLDR pThis = (PRTLDRMODKLDR)pMod;
713 uint32_t const cSegments = pThis->pMod->cSegments;
714 PCKLDRSEG paSegments = &pThis->pMod->aSegments[0];
715
716 for (uint32_t iSeg = 0; iSeg < cSegments; iSeg++)
717 {
718 KLDRADDR offSeg = LinkAddress - paSegments[iSeg].LinkAddress;
719 if ( offSeg < paSegments[iSeg].cbMapped
720 || offSeg < paSegments[iSeg].cb)
721 {
722 *pRva = paSegments[iSeg].RVA + offSeg;
723 return VINF_SUCCESS;
724 }
725 }
726
727 return VERR_LDR_INVALID_RVA;
728}
729
730
731/** @copydoc RTLDROPS::pfnSegOffsetToRva. */
732static DECLCALLBACK(int) rtkldr_SegOffsetToRva(PRTLDRMODINTERNAL pMod, uint32_t iSeg, RTLDRADDR offSeg,
733 PRTLDRADDR pRva)
734{
735 PRTLDRMODKLDR pThis = (PRTLDRMODKLDR)pMod;
736
737 if (iSeg >= pThis->pMod->cSegments)
738 return VERR_LDR_INVALID_SEG_OFFSET;
739 PCKLDRSEG const pSegment = &pThis->pMod->aSegments[iSeg];
740
741 if ( offSeg > pSegment->cbMapped
742 && offSeg > pSegment->cb
743 && ( pSegment->cbFile < 0
744 || offSeg > (uint64_t)pSegment->cbFile))
745 return VERR_LDR_INVALID_SEG_OFFSET;
746
747 *pRva = pSegment->RVA + offSeg;
748 return VINF_SUCCESS;
749}
750
751
752/** @copydoc RTLDROPS::pfnRvaToSegOffset. */
753static DECLCALLBACK(int) rtkldr_RvaToSegOffset(PRTLDRMODINTERNAL pMod, RTLDRADDR Rva,
754 uint32_t *piSeg, PRTLDRADDR poffSeg)
755{
756 PRTLDRMODKLDR pThis = (PRTLDRMODKLDR)pMod;
757 uint32_t const cSegments = pThis->pMod->cSegments;
758 PCKLDRSEG paSegments = &pThis->pMod->aSegments[0];
759
760 for (uint32_t iSeg = 0; iSeg < cSegments; iSeg++)
761 {
762 KLDRADDR offSeg = Rva - paSegments[iSeg].RVA;
763 if ( offSeg < paSegments[iSeg].cbMapped
764 || offSeg < paSegments[iSeg].cb)
765 {
766 *piSeg = iSeg;
767 *poffSeg = offSeg;
768 return VINF_SUCCESS;
769 }
770 }
771
772 return VERR_LDR_INVALID_RVA;
773}
774
775
776/**
777 * Operations for a kLdr module.
778 */
779static const RTLDROPS g_rtkldrOps =
780{
781 "kLdr",
782 rtkldr_Close,
783 NULL,
784 rtkldr_Done,
785 rtkldr_EnumSymbols,
786 /* ext */
787 rtkldr_GetImageSize,
788 rtkldr_GetBits,
789 rtkldr_Relocate,
790 rtkldr_GetSymbolEx,
791 rtkldr_EnumDbgInfo,
792 rtkldr_EnumSegments,
793 rtkldr_LinkAddressToSegOffset,
794 rtkldr_LinkAddressToRva,
795 rtkldr_SegOffsetToRva,
796 rtkldr_RvaToSegOffset,
797 42
798};
799
800
801/**
802 * Open a image using kLdr.
803 *
804 * @returns iprt status code.
805 * @param pReader The loader reader instance which will provide the raw image bits.
806 * @param fFlags Reserved, MBZ.
807 * @param enmArch CPU architecture specifier for the image to be loaded.
808 * @param phLdrMod Where to store the handle.
809 */
810int rtldrkLdrOpen(PRTLDRREADER pReader, uint32_t fFlags, RTLDRARCH enmArch, PRTLDRMOD phLdrMod)
811{
812 /* Convert enmArch to k-speak. */
813 KCPUARCH enmCpuArch;
814 switch (enmArch)
815 {
816 case RTLDRARCH_WHATEVER:
817 enmCpuArch = KCPUARCH_UNKNOWN;
818 break;
819 case RTLDRARCH_X86_32:
820 enmCpuArch = KCPUARCH_X86_32;
821 break;
822 case RTLDRARCH_AMD64:
823 enmCpuArch = KCPUARCH_AMD64;
824 break;
825 default:
826 return VERR_INVALID_PARAMETER;
827 }
828
829 /* Create a rtkldrRdr_ instance. */
830 PRTKLDRRDR pRdr = (PRTKLDRRDR)RTMemAllocZ(sizeof(*pRdr));
831 if (!pRdr)
832 return VERR_NO_MEMORY;
833 pRdr->Core.u32Magic = KRDR_MAGIC;
834 pRdr->Core.pOps = &g_kLdrRdrFileOps;
835 pRdr->pReader = pReader;
836
837 /* Try open it. */
838 PKLDRMOD pMod;
839 int krc = kLdrModOpenFromRdr(&pRdr->Core, fFlags, enmCpuArch, &pMod);
840 if (!krc)
841 {
842 /* Create a module wrapper for it. */
843 PRTLDRMODKLDR pNewMod = (PRTLDRMODKLDR)RTMemAllocZ(sizeof(*pNewMod));
844 if (pNewMod)
845 {
846 pNewMod->Core.u32Magic = RTLDRMOD_MAGIC;
847 pNewMod->Core.eState = LDR_STATE_OPENED;
848 pNewMod->Core.pOps = &g_rtkldrOps;
849 pNewMod->pMod = pMod;
850 *phLdrMod = &pNewMod->Core;
851
852#ifdef LOG_ENABLED
853 Log(("rtldrkLdrOpen: '%s' (%s) %u segments\n",
854 pMod->pszName, pMod->pszFilename, pMod->cSegments));
855 for (unsigned iSeg = 0; iSeg < pMod->cSegments; iSeg++)
856 {
857 Log(("Segment #%-2u: RVA=%08llx cb=%08llx '%.*s'\n", iSeg,
858 pMod->aSegments[iSeg].RVA,
859 pMod->aSegments[iSeg].cb,
860 pMod->aSegments[iSeg].cchName,
861 pMod->aSegments[iSeg].pchName));
862 }
863#endif
864 return VINF_SUCCESS;
865 }
866 kLdrModClose(pMod);
867 krc = KERR_NO_MEMORY;
868 }
869 return rtkldrConvertError(krc);
870}
871
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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