VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/ldr/ldrEx.cpp@ 74642

Last change on this file since 74642 was 74638, checked in by vboxsync, 7 years ago

IPRT: Initial adaption of the kstuff loader code. bugref:9232

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 28.7 KB
Line 
1/* $Id: ldrEx.cpp 74638 2018-10-06 18:31:59Z vboxsync $ */
2/** @file
3 * IPRT - Binary Image Loader, Extended Features.
4 */
5
6/*
7 * Copyright (C) 2006-2017 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.215389.xyz. 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/assert.h>
36#include <iprt/dbg.h>
37#include <iprt/err.h>
38#include <iprt/log.h>
39#include <iprt/md5.h>
40#include <iprt/mem.h>
41#include <iprt/sha.h>
42#include <iprt/string.h>
43#include <iprt/formats/mz.h>
44#include <iprt/formats/mach-o.h>
45#include "internal/ldr.h"
46
47#ifdef LDR_ONLY_PE
48# undef LDR_WITH_PE
49# undef LDR_WITH_KLDR
50# undef LDR_WITH_ELF
51# undef LDR_WITH_LX
52# undef LDR_WITH_LE
53# undef LDR_WITH_NE
54# undef LDR_WITH_MZ
55# undef LDR_WITH_AOUT
56# define LDR_WITH_PE
57#endif
58
59
60RTDECL(int) RTLdrOpenWithReader(PRTLDRREADER pReader, uint32_t fFlags, RTLDRARCH enmArch, PRTLDRMOD phMod, PRTERRINFO pErrInfo)
61{
62 /*
63 * Resolve RTLDRARCH_HOST.
64 */
65 if (enmArch == RTLDRARCH_HOST)
66 enmArch = RTLdrGetHostArch();
67
68 /*
69 * Read and verify the file signature.
70 */
71 union
72 {
73 char ach[4];
74 uint16_t au16[2];
75 uint32_t u32;
76 } uSign;
77 int rc = pReader->pfnRead(pReader, &uSign, sizeof(uSign), 0);
78 if (RT_FAILURE(rc))
79 return rc;
80#ifndef LDR_WITH_KLDR
81 if ( uSign.au16[0] != IMAGE_DOS_SIGNATURE
82 && uSign.u32 != IMAGE_NT_SIGNATURE
83 && uSign.u32 != IMAGE_ELF_SIGNATURE
84 && uSign.au16[0] != IMAGE_LX_SIGNATURE
85 && uSign.u32 != IMAGE_MACHO64_SIGNATURE
86 && uSign.u32 != IMAGE_MACHO64_SIGNATURE_OE
87 && uSign.u32 != IMAGE_MACHO32_SIGNATURE
88 && uSign.u32 != IMAGE_MACHO32_SIGNATURE_OE
89 && uSign.u32 != IMAGE_FAT_SIGNATURE
90 && uSign.u32 != IMAGE_FAT_SIGNATURE_OE )
91 {
92 Log(("rtldrOpenWithReader: %s: unknown magic %#x / '%.4s\n", pReader->pfnLogName(pReader), uSign.u32, &uSign.ach[0]));
93 return VERR_INVALID_EXE_SIGNATURE;
94 }
95#endif
96 uint32_t offHdr = 0;
97 if (uSign.au16[0] == IMAGE_DOS_SIGNATURE)
98 {
99 rc = pReader->pfnRead(pReader, &offHdr, sizeof(offHdr), RT_UOFFSETOF(IMAGE_DOS_HEADER, e_lfanew));
100 if (RT_FAILURE(rc))
101 return rc;
102
103 if (offHdr <= sizeof(IMAGE_DOS_HEADER))
104 {
105 Log(("rtldrOpenWithReader: %s: no new header / invalid offset %#RX32\n", pReader->pfnLogName(pReader), offHdr));
106 return VERR_INVALID_EXE_SIGNATURE;
107 }
108 rc = pReader->pfnRead(pReader, &uSign, sizeof(uSign), offHdr);
109 if (RT_FAILURE(rc))
110 return rc;
111 if ( uSign.u32 != IMAGE_NT_SIGNATURE
112 && uSign.au16[0] != IMAGE_LX_SIGNATURE
113 && uSign.au16[0] != IMAGE_LE_SIGNATURE
114 && uSign.au16[0] != IMAGE_NE_SIGNATURE)
115 {
116 Log(("rtldrOpenWithReader: %s: unknown new magic %#x / '%.4s\n", pReader->pfnLogName(pReader), uSign.u32, &uSign.ach[0]));
117 return VERR_INVALID_EXE_SIGNATURE;
118 }
119 }
120
121 /*
122 * Create image interpreter instance depending on the signature.
123 */
124 if (uSign.u32 == IMAGE_NT_SIGNATURE)
125#ifdef LDR_WITH_PE
126 rc = rtldrPEOpen(pReader, fFlags, enmArch, offHdr, phMod, pErrInfo);
127#else
128 rc = VERR_PE_EXE_NOT_SUPPORTED;
129#endif
130 else if (uSign.u32 == IMAGE_ELF_SIGNATURE)
131#if defined(LDR_WITH_ELF)
132 rc = rtldrELFOpen(pReader, fFlags, enmArch, phMod, pErrInfo);
133#else
134 rc = VERR_ELF_EXE_NOT_SUPPORTED;
135#endif
136 else if ( uSign.u32 == IMAGE_MACHO64_SIGNATURE
137 || uSign.u32 == IMAGE_MACHO64_SIGNATURE_OE
138 || uSign.u32 == IMAGE_MACHO32_SIGNATURE
139 || uSign.u32 == IMAGE_MACHO32_SIGNATURE_OE)
140#if defined(LDR_WITH_MACHO)
141 rc = rtldrMachOOpen(pReader, fFlags, enmArch, offHdr, phMod, pErrInfo);
142#else
143 rc = VERR_INVALID_EXE_SIGNATURE;
144#endif
145 else if ( uSign.u32 == IMAGE_FAT_SIGNATURE
146 || uSign.u32 == IMAGE_FAT_SIGNATURE_OE)
147#if defined(LDR_WITH_MACHO)
148 rc = rtldrFatOpen(pReader, fFlags, enmArch, phMod, pErrInfo);
149#else
150 rc = VERR_INVALID_EXE_SIGNATURE;
151#endif
152 else if (uSign.au16[0] == IMAGE_LX_SIGNATURE)
153#ifdef LDR_WITH_LX
154 rc = rtldrLXOpen(pReader, fFlags, enmArch, offHdr, phMod, pErrInfo);
155#else
156 rc = VERR_LX_EXE_NOT_SUPPORTED;
157#endif
158 else if (uSign.au16[0] == IMAGE_LE_SIGNATURE)
159#ifdef LDR_WITH_LE
160 rc = rtldrLEOpen(pReader, fFlags, enmArch, phMod, pErrInfo);
161#else
162 rc = VERR_LE_EXE_NOT_SUPPORTED;
163#endif
164 else if (uSign.au16[0] == IMAGE_NE_SIGNATURE)
165#ifdef LDR_WITH_NE
166 rc = rtldrNEOpen(pReader, fFlags, enmArch, phMod, pErrInfo);
167#else
168 rc = VERR_NE_EXE_NOT_SUPPORTED;
169#endif
170 else if (uSign.au16[0] == IMAGE_DOS_SIGNATURE)
171#ifdef LDR_WITH_MZ
172 rc = rtldrMZOpen(pReader, fFlags, enmArch, phMod, pErrInfo);
173#else
174 rc = VERR_MZ_EXE_NOT_SUPPORTED;
175#endif
176 else if (/* uSign.u32 == IMAGE_AOUT_A_SIGNATURE
177 || uSign.u32 == IMAGE_AOUT_Z_SIGNATURE*/ /** @todo find the aout magics in emx or binutils. */
178 0)
179#ifdef LDR_WITH_AOUT
180 rc = rtldrAOUTOpen(pReader, fFlags, enmArch, phMod, pErrInfo);
181#else
182 rc = VERR_AOUT_EXE_NOT_SUPPORTED;
183#endif
184 else
185 {
186#ifndef LDR_WITH_KLDR
187 Log(("rtldrOpenWithReader: %s: the format isn't implemented %#x / '%.4s\n", pReader->pfnLogName(pReader), uSign.u32, &uSign.ach[0]));
188#endif
189 rc = VERR_INVALID_EXE_SIGNATURE;
190 }
191
192#ifdef LDR_WITH_KLDR
193 /* Try kLdr if it's a format we don't recognize. */
194 if (rc <= VERR_INVALID_EXE_SIGNATURE && rc > VERR_BAD_EXE_FORMAT)
195 {
196 int rc2 = rtldrkLdrOpen(pReader, fFlags, enmArch, phMod, pErrInfo);
197 if ( RT_SUCCESS(rc2)
198 || (rc == VERR_INVALID_EXE_SIGNATURE && rc2 != VERR_MZ_EXE_NOT_SUPPORTED /* Quick fix for bad return code. */)
199 || rc2 > VERR_INVALID_EXE_SIGNATURE
200 || rc2 <= VERR_BAD_EXE_FORMAT)
201 rc = rc2;
202 }
203#endif
204
205 LogFlow(("rtldrOpenWithReader: %s: returns %Rrc *phMod=%p\n", pReader->pfnLogName(pReader), rc, *phMod));
206 return rc;
207}
208
209
210RTDECL(size_t) RTLdrSize(RTLDRMOD hLdrMod)
211{
212 LogFlow(("RTLdrSize: hLdrMod=%RTldrm\n", hLdrMod));
213
214 /*
215 * Validate input.
216 */
217 AssertMsgReturn(rtldrIsValid(hLdrMod), ("hLdrMod=%p\n", hLdrMod), ~(size_t)0);
218 PRTLDRMODINTERNAL pMod = (PRTLDRMODINTERNAL)hLdrMod;
219 AssertMsgReturn(pMod->eState == LDR_STATE_OPENED, ("eState=%d\n", pMod->eState), ~(size_t)0);
220
221 /*
222 * Do it.
223 */
224 size_t cb = pMod->pOps->pfnGetImageSize(pMod);
225 LogFlow(("RTLdrSize: returns %zu\n", cb));
226 return cb;
227}
228RT_EXPORT_SYMBOL(RTLdrSize);
229
230
231/**
232 * Loads the image into a buffer provided by the user and applies fixups
233 * for the given base address.
234 *
235 * @returns iprt status code.
236 * @param hLdrMod The load module handle.
237 * @param pvBits Where to put the bits.
238 * Must be as large as RTLdrSize() suggests.
239 * @param BaseAddress The base address.
240 * @param pfnGetImport Callback function for resolving imports one by one.
241 * If this is NULL, imports will not be resolved.
242 * @param pvUser User argument for the callback.
243 * @remark Not supported for RTLdrLoad() images.
244 */
245RTDECL(int) RTLdrGetBits(RTLDRMOD hLdrMod, void *pvBits, RTLDRADDR BaseAddress, PFNRTLDRIMPORT pfnGetImport, void *pvUser)
246{
247 LogFlow(("RTLdrGetBits: hLdrMod=%RTldrm pvBits=%p BaseAddress=%RTptr pfnGetImport=%p pvUser=%p\n",
248 hLdrMod, pvBits, BaseAddress, pfnGetImport, pvUser));
249
250 /*
251 * Validate input.
252 */
253 AssertMsgReturn(rtldrIsValid(hLdrMod), ("hLdrMod=%p\n", hLdrMod), VERR_INVALID_HANDLE);
254 AssertPtrReturn(pvBits, VERR_INVALID_POINTER);
255 AssertPtrNullReturn(pfnGetImport, VERR_INVALID_POINTER);
256 PRTLDRMODINTERNAL pMod = (PRTLDRMODINTERNAL)hLdrMod;
257 AssertMsgReturn(pMod->eState == LDR_STATE_OPENED, ("eState=%d\n", pMod->eState), VERR_WRONG_ORDER);
258
259 /*
260 * Do it.
261 */
262 int rc = pMod->pOps->pfnGetBits(pMod, pvBits, BaseAddress, pfnGetImport, pvUser);
263 LogFlow(("RTLdrGetBits: returns %Rrc\n",rc));
264 return rc;
265}
266RT_EXPORT_SYMBOL(RTLdrGetBits);
267
268
269/**
270 * Relocates bits after getting them.
271 * Useful for code which moves around a bit.
272 *
273 * @returns iprt status code.
274 * @param hLdrMod The loader module handle.
275 * @param pvBits Where the image bits are.
276 * Must have been passed to RTLdrGetBits().
277 * @param NewBaseAddress The new base address.
278 * @param OldBaseAddress The old base address.
279 * @param pfnGetImport Callback function for resolving imports one by one.
280 * @param pvUser User argument for the callback.
281 * @remark Not supported for RTLdrLoad() images.
282 */
283RTDECL(int) RTLdrRelocate(RTLDRMOD hLdrMod, void *pvBits, RTLDRADDR NewBaseAddress, RTLDRADDR OldBaseAddress,
284 PFNRTLDRIMPORT pfnGetImport, void *pvUser)
285{
286 LogFlow(("RTLdrRelocate: hLdrMod=%RTldrm pvBits=%p NewBaseAddress=%RTptr OldBaseAddress=%RTptr pfnGetImport=%p pvUser=%p\n",
287 hLdrMod, pvBits, NewBaseAddress, OldBaseAddress, pfnGetImport, pvUser));
288
289 /*
290 * Validate input.
291 */
292 AssertMsgReturn(rtldrIsValid(hLdrMod), ("hLdrMod=%p\n", hLdrMod), VERR_INVALID_HANDLE);
293 AssertMsgReturn(VALID_PTR(pvBits), ("pvBits=%p\n", pvBits), VERR_INVALID_PARAMETER);
294 AssertMsgReturn(VALID_PTR(pfnGetImport), ("pfnGetImport=%p\n", pfnGetImport), VERR_INVALID_PARAMETER);
295 PRTLDRMODINTERNAL pMod = (PRTLDRMODINTERNAL)hLdrMod;
296 AssertMsgReturn(pMod->eState == LDR_STATE_OPENED, ("eState=%d\n", pMod->eState), VERR_WRONG_ORDER);
297
298 /*
299 * Do it.
300 */
301 int rc = pMod->pOps->pfnRelocate(pMod, pvBits, NewBaseAddress, OldBaseAddress, pfnGetImport, pvUser);
302 LogFlow(("RTLdrRelocate: returns %Rrc\n", rc));
303 return rc;
304}
305RT_EXPORT_SYMBOL(RTLdrRelocate);
306
307
308RTDECL(int) RTLdrGetSymbolEx(RTLDRMOD hLdrMod, const void *pvBits, RTLDRADDR BaseAddress,
309 uint32_t iOrdinal, const char *pszSymbol, PRTLDRADDR pValue)
310{
311 LogFlow(("RTLdrGetSymbolEx: hLdrMod=%RTldrm pvBits=%p BaseAddress=%RTptr iOrdinal=%#x pszSymbol=%p:{%s} pValue=%p\n",
312 hLdrMod, pvBits, BaseAddress, iOrdinal, pszSymbol, pszSymbol, pValue));
313
314 /*
315 * Validate input.
316 */
317 AssertMsgReturn(rtldrIsValid(hLdrMod), ("hLdrMod=%p\n", hLdrMod), VERR_INVALID_HANDLE);
318 AssertPtrNullReturn(pvBits, VERR_INVALID_POINTER);
319 AssertPtrNullReturn(pszSymbol, VERR_INVALID_POINTER);
320 AssertReturn(pszSymbol || iOrdinal != UINT32_MAX, VERR_INVALID_PARAMETER);
321 AssertPtrReturn(pValue, VERR_INVALID_POINTER);
322 PRTLDRMODINTERNAL pMod = (PRTLDRMODINTERNAL)hLdrMod;
323
324 /*
325 * Do it.
326 */
327 int rc;
328 if (pMod->pOps->pfnGetSymbolEx)
329 rc = pMod->pOps->pfnGetSymbolEx(pMod, pvBits, BaseAddress, iOrdinal, pszSymbol, pValue);
330 else if (!BaseAddress && !pvBits && iOrdinal == UINT32_MAX)
331 {
332 void *pvValue;
333 rc = pMod->pOps->pfnGetSymbol(pMod, pszSymbol, &pvValue);
334 if (RT_SUCCESS(rc))
335 *pValue = (uintptr_t)pvValue;
336 }
337 else
338 AssertMsgFailedReturn(("BaseAddress=%RTptr pvBits=%p\n", BaseAddress, pvBits), VERR_INVALID_FUNCTION);
339 LogFlow(("RTLdrGetSymbolEx: returns %Rrc *pValue=%p\n", rc, *pValue));
340 return rc;
341}
342RT_EXPORT_SYMBOL(RTLdrGetSymbolEx);
343
344
345RTDECL(int) RTLdrQueryForwarderInfo(RTLDRMOD hLdrMod, const void *pvBits, uint32_t iOrdinal, const char *pszSymbol,
346 PRTLDRIMPORTINFO pInfo, size_t cbInfo)
347{
348 LogFlow(("RTLdrQueryForwarderInfo: hLdrMod=%RTldrm pvBits=%p iOrdinal=%#x pszSymbol=%p:{%s} pInfo=%p cbInfo=%zu\n",
349 hLdrMod, pvBits, iOrdinal, pszSymbol, pszSymbol, pInfo, cbInfo));
350
351 /*
352 * Validate input.
353 */
354 AssertMsgReturn(rtldrIsValid(hLdrMod), ("hLdrMod=%p\n", hLdrMod), VERR_INVALID_HANDLE);
355 AssertPtrNullReturn(pvBits, VERR_INVALID_POINTER);
356 AssertMsgReturn(pszSymbol, ("pszSymbol=%p\n", pszSymbol), VERR_INVALID_PARAMETER);
357 AssertPtrReturn(pInfo, VERR_INVALID_PARAMETER);
358 AssertReturn(cbInfo >= sizeof(*pInfo), VERR_INVALID_PARAMETER);
359 PRTLDRMODINTERNAL pMod = (PRTLDRMODINTERNAL)hLdrMod;
360
361 /*
362 * Do it.
363 */
364 int rc;
365 if (pMod->pOps->pfnQueryForwarderInfo)
366 {
367 rc = pMod->pOps->pfnQueryForwarderInfo(pMod, pvBits, iOrdinal, pszSymbol, pInfo, cbInfo);
368 if (RT_SUCCESS(rc))
369 LogFlow(("RTLdrQueryForwarderInfo: returns %Rrc pInfo={%#x,%#x,%s,%s}\n", rc,
370 pInfo->iSelfOrdinal, pInfo->iOrdinal, pInfo->pszSymbol, pInfo->szModule));
371 else
372 LogFlow(("RTLdrQueryForwarderInfo: returns %Rrc\n", rc));
373 }
374 else
375 {
376 LogFlow(("RTLdrQueryForwarderInfo: returns VERR_NOT_SUPPORTED\n"));
377 rc = VERR_NOT_SUPPORTED;
378 }
379 return rc;
380
381}
382RT_EXPORT_SYMBOL(RTLdrQueryForwarderInfo);
383
384
385/**
386 * Enumerates all symbols in a module.
387 *
388 * @returns iprt status code.
389 * @param hLdrMod The loader module handle.
390 * @param fFlags Flags indicating what to return and such.
391 * @param pvBits Optional pointer to the loaded image.
392 * Set this to NULL if no RTLdrGetBits() processed image bits are available.
393 * @param BaseAddress Image load address.
394 * @param pfnCallback Callback function.
395 * @param pvUser User argument for the callback.
396 * @remark Not supported for RTLdrLoad() images.
397 */
398RTDECL(int) RTLdrEnumSymbols(RTLDRMOD hLdrMod, unsigned fFlags, const void *pvBits, RTLDRADDR BaseAddress,
399 PFNRTLDRENUMSYMS pfnCallback, void *pvUser)
400{
401 LogFlow(("RTLdrEnumSymbols: hLdrMod=%RTldrm fFlags=%#x pvBits=%p BaseAddress=%RTptr pfnCallback=%p pvUser=%p\n",
402 hLdrMod, fFlags, pvBits, BaseAddress, pfnCallback, pvUser));
403
404 /*
405 * Validate input.
406 */
407 AssertMsgReturn(rtldrIsValid(hLdrMod), ("hLdrMod=%p\n", hLdrMod), VERR_INVALID_HANDLE);
408 AssertMsgReturn(!pvBits || VALID_PTR(pvBits), ("pvBits=%p\n", pvBits), VERR_INVALID_PARAMETER);
409 AssertMsgReturn(VALID_PTR(pfnCallback), ("pfnCallback=%p\n", pfnCallback), VERR_INVALID_PARAMETER);
410 PRTLDRMODINTERNAL pMod = (PRTLDRMODINTERNAL)hLdrMod;
411 //AssertMsgReturn(pMod->eState == LDR_STATE_OPENED, ("eState=%d\n", pMod->eState), VERR_WRONG_ORDER);
412
413 /*
414 * Do it.
415 */
416 int rc = pMod->pOps->pfnEnumSymbols(pMod, fFlags, pvBits, BaseAddress, pfnCallback, pvUser);
417 LogFlow(("RTLdrEnumSymbols: returns %Rrc\n", rc));
418 return rc;
419}
420RT_EXPORT_SYMBOL(RTLdrEnumSymbols);
421
422
423RTDECL(int) RTLdrEnumDbgInfo(RTLDRMOD hLdrMod, const void *pvBits, PFNRTLDRENUMDBG pfnCallback, void *pvUser)
424{
425 LogFlow(("RTLdrEnumDbgInfo: hLdrMod=%RTldrm pvBits=%p pfnCallback=%p pvUser=%p\n",
426 hLdrMod, pvBits, pfnCallback, pvUser));
427
428 /*
429 * Validate input.
430 */
431 AssertMsgReturn(rtldrIsValid(hLdrMod), ("hLdrMod=%p\n", hLdrMod), VERR_INVALID_HANDLE);
432 AssertMsgReturn(!pvBits || RT_VALID_PTR(pvBits), ("pvBits=%p\n", pvBits), VERR_INVALID_PARAMETER);
433 AssertMsgReturn(RT_VALID_PTR(pfnCallback), ("pfnCallback=%p\n", pfnCallback), VERR_INVALID_PARAMETER);
434 PRTLDRMODINTERNAL pMod = (PRTLDRMODINTERNAL)hLdrMod;
435 //AssertMsgReturn(pMod->eState == LDR_STATE_OPENED, ("eState=%d\n", pMod->eState), VERR_WRONG_ORDER);
436
437 /*
438 * Do it.
439 */
440 int rc;
441 if (pMod->pOps->pfnEnumDbgInfo)
442 rc = pMod->pOps->pfnEnumDbgInfo(pMod, pvBits, pfnCallback, pvUser);
443 else
444 rc = VERR_NOT_SUPPORTED;
445
446 LogFlow(("RTLdrEnumDbgInfo: returns %Rrc\n", rc));
447 return rc;
448}
449RT_EXPORT_SYMBOL(RTLdrEnumDbgInfo);
450
451
452RTDECL(int) RTLdrEnumSegments(RTLDRMOD hLdrMod, PFNRTLDRENUMSEGS pfnCallback, void *pvUser)
453{
454 LogFlow(("RTLdrEnumSegments: hLdrMod=%RTldrm pfnCallback=%p pvUser=%p\n",
455 hLdrMod, pfnCallback, pvUser));
456
457 /*
458 * Validate input.
459 */
460 AssertMsgReturn(rtldrIsValid(hLdrMod), ("hLdrMod=%p\n", hLdrMod), VERR_INVALID_HANDLE);
461 AssertMsgReturn(RT_VALID_PTR(pfnCallback), ("pfnCallback=%p\n", pfnCallback), VERR_INVALID_PARAMETER);
462 PRTLDRMODINTERNAL pMod = (PRTLDRMODINTERNAL)hLdrMod;
463 //AssertMsgReturn(pMod->eState == LDR_STATE_OPENED, ("eState=%d\n", pMod->eState), VERR_WRONG_ORDER);
464
465 /*
466 * Do it.
467 */
468 int rc;
469 if (pMod->pOps->pfnEnumSegments)
470 rc = pMod->pOps->pfnEnumSegments(pMod, pfnCallback, pvUser);
471 else
472 rc = VERR_NOT_SUPPORTED;
473
474 LogFlow(("RTLdrEnumSegments: returns %Rrc\n", rc));
475 return rc;
476
477}
478RT_EXPORT_SYMBOL(RTLdrEnumSegments);
479
480
481RTDECL(int) RTLdrLinkAddressToSegOffset(RTLDRMOD hLdrMod, RTLDRADDR LinkAddress, uint32_t *piSeg, PRTLDRADDR poffSeg)
482{
483 LogFlow(("RTLdrLinkAddressToSegOffset: hLdrMod=%RTldrm LinkAddress=%RTptr piSeg=%p poffSeg=%p\n",
484 hLdrMod, LinkAddress, piSeg, poffSeg));
485
486 /*
487 * Validate input.
488 */
489 AssertMsgReturn(rtldrIsValid(hLdrMod), ("hLdrMod=%p\n", hLdrMod), VERR_INVALID_HANDLE);
490 AssertPtrReturn(piSeg, VERR_INVALID_POINTER);
491 AssertPtrReturn(poffSeg, VERR_INVALID_POINTER);
492
493 PRTLDRMODINTERNAL pMod = (PRTLDRMODINTERNAL)hLdrMod;
494 //AssertMsgReturn(pMod->eState == LDR_STATE_OPENED, ("eState=%d\n", pMod->eState), VERR_WRONG_ORDER);
495
496 *piSeg = UINT32_MAX;
497 *poffSeg = ~(RTLDRADDR)0;
498
499 /*
500 * Do it.
501 */
502 int rc;
503 if (pMod->pOps->pfnLinkAddressToSegOffset)
504 rc = pMod->pOps->pfnLinkAddressToSegOffset(pMod, LinkAddress, piSeg, poffSeg);
505 else
506 rc = VERR_NOT_SUPPORTED;
507
508 LogFlow(("RTLdrLinkAddressToSegOffset: returns %Rrc %#x:%RTptr\n", rc, *piSeg, *poffSeg));
509 return rc;
510}
511RT_EXPORT_SYMBOL(RTLdrLinkAddressToSegOffset);
512
513
514RTDECL(int) RTLdrLinkAddressToRva(RTLDRMOD hLdrMod, RTLDRADDR LinkAddress, PRTLDRADDR pRva)
515{
516 LogFlow(("RTLdrLinkAddressToRva: hLdrMod=%RTldrm LinkAddress=%RTptr pRva=%p\n",
517 hLdrMod, LinkAddress, pRva));
518
519 /*
520 * Validate input.
521 */
522 AssertMsgReturn(rtldrIsValid(hLdrMod), ("hLdrMod=%p\n", hLdrMod), VERR_INVALID_HANDLE);
523 AssertPtrReturn(pRva, VERR_INVALID_POINTER);
524
525 PRTLDRMODINTERNAL pMod = (PRTLDRMODINTERNAL)hLdrMod;
526 //AssertMsgReturn(pMod->eState == LDR_STATE_OPENED, ("eState=%d\n", pMod->eState), VERR_WRONG_ORDER);
527
528 *pRva = ~(RTLDRADDR)0;
529
530 /*
531 * Do it.
532 */
533 int rc;
534 if (pMod->pOps->pfnLinkAddressToRva)
535 rc = pMod->pOps->pfnLinkAddressToRva(pMod, LinkAddress, pRva);
536 else
537 rc = VERR_NOT_SUPPORTED;
538
539 LogFlow(("RTLdrLinkAddressToRva: returns %Rrc %RTptr\n", rc, *pRva));
540 return rc;
541}
542RT_EXPORT_SYMBOL(RTLdrLinkAddressToRva);
543
544
545RTDECL(int) RTLdrSegOffsetToRva(RTLDRMOD hLdrMod, uint32_t iSeg, RTLDRADDR offSeg, PRTLDRADDR pRva)
546{
547 LogFlow(("RTLdrSegOffsetToRva: hLdrMod=%RTldrm iSeg=%#x offSeg=%RTptr pRva=%p\n", hLdrMod, iSeg, offSeg, pRva));
548
549 /*
550 * Validate input.
551 */
552 AssertMsgReturn(rtldrIsValid(hLdrMod), ("hLdrMod=%p\n", hLdrMod), VERR_INVALID_HANDLE);
553 AssertPtrReturn(pRva, VERR_INVALID_POINTER);
554
555 PRTLDRMODINTERNAL pMod = (PRTLDRMODINTERNAL)hLdrMod;
556 //AssertMsgReturn(pMod->eState == LDR_STATE_OPENED, ("eState=%d\n", pMod->eState), VERR_WRONG_ORDER);
557
558 *pRva = ~(RTLDRADDR)0;
559
560 /*
561 * Do it.
562 */
563 int rc;
564 if (pMod->pOps->pfnSegOffsetToRva)
565 rc = pMod->pOps->pfnSegOffsetToRva(pMod, iSeg, offSeg, pRva);
566 else
567 rc = VERR_NOT_SUPPORTED;
568
569 LogFlow(("RTLdrSegOffsetToRva: returns %Rrc %RTptr\n", rc, *pRva));
570 return rc;
571}
572RT_EXPORT_SYMBOL(RTLdrSegOffsetToRva);
573
574RTDECL(int) RTLdrRvaToSegOffset(RTLDRMOD hLdrMod, RTLDRADDR Rva, uint32_t *piSeg, PRTLDRADDR poffSeg)
575{
576 LogFlow(("RTLdrRvaToSegOffset: hLdrMod=%RTldrm Rva=%RTptr piSeg=%p poffSeg=%p\n",
577 hLdrMod, Rva, piSeg, poffSeg));
578
579 /*
580 * Validate input.
581 */
582 AssertMsgReturn(rtldrIsValid(hLdrMod), ("hLdrMod=%p\n", hLdrMod), VERR_INVALID_HANDLE);
583 AssertPtrReturn(piSeg, VERR_INVALID_POINTER);
584 AssertPtrReturn(poffSeg, VERR_INVALID_POINTER);
585
586 PRTLDRMODINTERNAL pMod = (PRTLDRMODINTERNAL)hLdrMod;
587 //AssertMsgReturn(pMod->eState == LDR_STATE_OPENED, ("eState=%d\n", pMod->eState), VERR_WRONG_ORDER);
588
589 *piSeg = UINT32_MAX;
590 *poffSeg = ~(RTLDRADDR)0;
591
592 /*
593 * Do it.
594 */
595 int rc;
596 if (pMod->pOps->pfnRvaToSegOffset)
597 rc = pMod->pOps->pfnRvaToSegOffset(pMod, Rva, piSeg, poffSeg);
598 else
599 rc = VERR_NOT_SUPPORTED;
600
601 LogFlow(("RTLdrRvaToSegOffset: returns %Rrc %#x:%RTptr\n", rc, *piSeg, *poffSeg));
602 return rc;
603}
604RT_EXPORT_SYMBOL(RTLdrRvaToSegOffset);
605
606
607RTDECL(int) RTLdrQueryProp(RTLDRMOD hLdrMod, RTLDRPROP enmProp, void *pvBuf, size_t cbBuf)
608{
609 return RTLdrQueryPropEx(hLdrMod, enmProp, NULL /*pvBits*/, pvBuf, cbBuf, NULL);
610}
611RT_EXPORT_SYMBOL(RTLdrQueryProp);
612
613
614RTDECL(int) RTLdrQueryPropEx(RTLDRMOD hLdrMod, RTLDRPROP enmProp, void *pvBits, void *pvBuf, size_t cbBuf, size_t *pcbRet)
615{
616 AssertMsgReturn(rtldrIsValid(hLdrMod), ("hLdrMod=%p\n", hLdrMod), RTLDRENDIAN_INVALID);
617 PRTLDRMODINTERNAL pMod = (PRTLDRMODINTERNAL)hLdrMod;
618
619 AssertPtrNullReturn(pcbRet, VERR_INVALID_POINTER);
620 size_t cbRet;
621 if (!pcbRet)
622 pcbRet = &cbRet;
623
624 /*
625 * Do some pre screening of the input
626 */
627 switch (enmProp)
628 {
629 case RTLDRPROP_UUID:
630 *pcbRet = sizeof(RTUUID);
631 AssertReturn(cbBuf == sizeof(RTUUID), VERR_INVALID_PARAMETER);
632 break;
633 case RTLDRPROP_TIMESTAMP_SECONDS:
634 *pcbRet = sizeof(int64_t);
635 AssertReturn(cbBuf == sizeof(int32_t) || cbBuf == sizeof(int64_t), VERR_INVALID_PARAMETER);
636 *pcbRet = cbBuf;
637 break;
638 case RTLDRPROP_IS_SIGNED:
639 *pcbRet = sizeof(bool);
640 AssertReturn(cbBuf == sizeof(bool), VERR_INVALID_PARAMETER);
641 break;
642 case RTLDRPROP_PKCS7_SIGNED_DATA:
643 *pcbRet = 0;
644 break;
645 case RTLDRPROP_SIGNATURE_CHECKS_ENFORCED:
646 *pcbRet = sizeof(bool);
647 AssertReturn(cbBuf == sizeof(bool), VERR_INVALID_PARAMETER);
648 break;
649 case RTLDRPROP_IMPORT_COUNT:
650 *pcbRet = sizeof(uint32_t);
651 AssertReturn(cbBuf == sizeof(uint32_t), VERR_INVALID_PARAMETER);
652 break;
653 case RTLDRPROP_IMPORT_MODULE:
654 *pcbRet = sizeof(uint32_t);
655 AssertReturn(cbBuf >= sizeof(uint32_t), VERR_INVALID_PARAMETER);
656 break;
657 case RTLDRPROP_FILE_OFF_HEADER:
658 *pcbRet = sizeof(uint64_t);
659 AssertReturn(cbBuf == sizeof(uint32_t) || cbBuf == sizeof(uint64_t), VERR_INVALID_PARAMETER);
660 break;
661 case RTLDRPROP_INTERNAL_NAME:
662 case RTLDRPROP_UNWIND_TABLE:
663 *pcbRet = 0;
664 break;
665
666 case RTLDRPROP_UNWIND_INFO:
667 AssertReturn(pvBuf, VERR_INVALID_POINTER);
668 AssertReturn(cbBuf >= sizeof(uint32_t), VERR_INVALID_PARAMETER);
669 *pcbRet = 0;
670 break;
671
672 default:
673 AssertFailedReturn(VERR_INVALID_FUNCTION);
674 }
675 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);
676
677 /*
678 * Call the image specific worker, if there is one.
679 */
680 if (!pMod->pOps->pfnQueryProp)
681 return VERR_NOT_SUPPORTED;
682 return pMod->pOps->pfnQueryProp(pMod, enmProp, pvBits, pvBuf, cbBuf, pcbRet);
683}
684RT_EXPORT_SYMBOL(RTLdrQueryPropEx);
685
686
687RTDECL(int) RTLdrVerifySignature(RTLDRMOD hLdrMod, PFNRTLDRVALIDATESIGNEDDATA pfnCallback, void *pvUser, PRTERRINFO pErrInfo)
688{
689 AssertMsgReturn(rtldrIsValid(hLdrMod), ("hLdrMod=%p\n", hLdrMod), VERR_INVALID_HANDLE);
690 PRTLDRMODINTERNAL pMod = (PRTLDRMODINTERNAL)hLdrMod;
691 AssertPtrReturn(pfnCallback, VERR_INVALID_POINTER);
692
693 /*
694 * Call the image specific worker, if there is one.
695 */
696 if (!pMod->pOps->pfnVerifySignature)
697 return VERR_NOT_SUPPORTED;
698 return pMod->pOps->pfnVerifySignature(pMod, pfnCallback, pvUser, pErrInfo);
699}
700RT_EXPORT_SYMBOL(RTLdrVerifySignature);
701
702
703RTDECL(int) RTLdrHashImage(RTLDRMOD hLdrMod, RTDIGESTTYPE enmDigest, char *pszDigest, size_t cbDigest)
704{
705 AssertMsgReturn(rtldrIsValid(hLdrMod), ("hLdrMod=%p\n", hLdrMod), VERR_INVALID_HANDLE);
706 PRTLDRMODINTERNAL pMod = (PRTLDRMODINTERNAL)hLdrMod;
707
708 /*
709 * Make sure there is sufficient space for the wanted digest and that
710 * it's supported.
711 */
712 switch (enmDigest)
713 {
714 case RTDIGESTTYPE_MD5: AssertReturn(cbDigest >= RTMD5_DIGEST_LEN + 1, VERR_BUFFER_OVERFLOW); break;
715 case RTDIGESTTYPE_SHA1: AssertReturn(cbDigest >= RTSHA1_DIGEST_LEN + 1, VERR_BUFFER_OVERFLOW); break;
716 case RTDIGESTTYPE_SHA256: AssertReturn(cbDigest >= RTSHA256_DIGEST_LEN + 1, VERR_BUFFER_OVERFLOW); break;
717 case RTDIGESTTYPE_SHA512: AssertReturn(cbDigest >= RTSHA512_DIGEST_LEN + 1, VERR_BUFFER_OVERFLOW); break;
718 default:
719 if (enmDigest > RTDIGESTTYPE_INVALID && enmDigest < RTDIGESTTYPE_END)
720 return VERR_NOT_SUPPORTED;
721 AssertFailedReturn(VERR_INVALID_PARAMETER);
722 }
723 AssertPtrReturn(pszDigest, VERR_INVALID_POINTER);
724
725 /*
726 * Call the image specific worker, if there is one.
727 */
728 if (!pMod->pOps->pfnHashImage)
729 return VERR_NOT_SUPPORTED;
730 return pMod->pOps->pfnHashImage(pMod, enmDigest, pszDigest, cbDigest);
731}
732RT_EXPORT_SYMBOL(RTLdrHashImage);
733
734
735RTDECL(int) RTLdrUnwindFrame(RTLDRMOD hLdrMod, void const *pvBits, uint32_t iSeg, RTLDRADDR off, PRTDBGUNWINDSTATE pState)
736{
737 /*
738 * Validate.
739 */
740 AssertMsgReturn(rtldrIsValid(hLdrMod), ("hLdrMod=%p\n", hLdrMod), VERR_INVALID_HANDLE);
741 PRTLDRMODINTERNAL pMod = (PRTLDRMODINTERNAL)hLdrMod;
742 AssertPtr(pState);
743 AssertReturn(pState->u32Magic == RTDBGUNWINDSTATE_MAGIC, VERR_INVALID_MAGIC);
744
745 /*
746 * Pass on the work.
747 */
748 if (pMod->pOps->pfnUnwindFrame)
749 return pMod->pOps->pfnUnwindFrame(pMod, pvBits, iSeg, off, pState);
750 return VERR_DBG_NO_UNWIND_INFO;
751}
752RT_EXPORT_SYMBOL(RTLdrUnwindFrame);
753
754
755/**
756 * Internal method used by the IPRT debug bits.
757 *
758 * @returns IPRT status code.
759 * @param hLdrMod The loader handle which executable we wish to
760 * read from.
761 * @param pvBuf The output buffer.
762 * @param iDbgInfo The debug info ordinal number if the request
763 * corresponds exactly to a debug info part from
764 * pfnEnumDbgInfo. Otherwise, pass UINT32_MAX.
765 * @param off Where in the executable file to start reading.
766 * @param cb The number of bytes to read.
767 *
768 * @remarks Fixups will only be applied if @a iDbgInfo is specified.
769 */
770DECLHIDDEN(int) rtLdrReadAt(RTLDRMOD hLdrMod, void *pvBuf, uint32_t iDbgInfo, RTFOFF off, size_t cb)
771{
772 AssertMsgReturn(rtldrIsValid(hLdrMod), ("hLdrMod=%p\n", hLdrMod), VERR_INVALID_HANDLE);
773 PRTLDRMODINTERNAL pMod = (PRTLDRMODINTERNAL)hLdrMod;
774
775 if (iDbgInfo != UINT32_MAX)
776 {
777 AssertReturn(pMod->pOps->pfnReadDbgInfo, VERR_NOT_SUPPORTED);
778 return pMod->pOps->pfnReadDbgInfo(pMod, iDbgInfo, off, cb, pvBuf);
779 }
780
781 AssertReturn(pMod->pReader, VERR_NOT_SUPPORTED);
782 return pMod->pReader->pfnRead(pMod->pReader, pvBuf, cb, off);
783}
784
785
786/**
787 * Translates a RTLDRARCH value to a string.
788 *
789 * @returns Name corresponding to @a enmArch
790 * @param enmArch The value to name.
791 */
792RTDECL(const char *) RTLdrArchName(RTLDRARCH enmArch)
793{
794 switch (enmArch)
795 {
796 case RTLDRARCH_INVALID: return "INVALID";
797 case RTLDRARCH_WHATEVER: return "WHATEVER";
798 case RTLDRARCH_HOST: return "HOST";
799 case RTLDRARCH_AMD64: return "AMD64";
800 case RTLDRARCH_X86_16: return "X86_16";
801 case RTLDRARCH_X86_32: return "X86_32";
802 case RTLDRARCH_ARM32: return "ARM32";
803 case RTLDRARCH_ARM64: return "ARM64";
804
805 case RTLDRARCH_END:
806 case RTLDRARCH_32BIT_HACK:
807 break;
808 }
809 return "UNKNOWN";
810}
811RT_EXPORT_SYMBOL(RTLdrArchName);
812
Note: See TracBrowser for help on using the repository browser.

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