VirtualBox

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

Last change on this file since 73494 was 73494, checked in by vboxsync, 6 years ago

IPRT: Added single stack frame unwind function to RTDbgMod and RTLdr, copying over the PoC from DBGFRStack.cpp. bugref:3897

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