VirtualBox

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

Last change on this file since 25528 was 21337, checked in by vboxsync, 15 years ago

IPRT,HostDrv,AddDrv: Export public IPRT symbols for the linux kernel (pain).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 13.8 KB
Line 
1/* $Id: ldrEx.cpp 21337 2009-07-07 14:58:27Z vboxsync $ */
2/** @file
3 * IPRT - Binary Image Loader, Extended Features.
4 */
5
6/*
7 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
27 * Clara, CA 95054 USA or visit http://www.sun.com if you need
28 * additional information or have any questions.
29 */
30
31
32/*******************************************************************************
33* Header Files *
34*******************************************************************************/
35#define LOG_GROUP RTLOGGROUP_LDR
36#include <iprt/ldr.h>
37#include "internal/iprt.h"
38
39#include <iprt/alloc.h>
40#include <iprt/assert.h>
41#include <iprt/log.h>
42#include <iprt/string.h>
43#include <iprt/err.h>
44#include "internal/ldr.h"
45#include "internal/ldrMZ.h"
46
47
48/**
49 * Open part with reader.
50 *
51 * @returns iprt status code.
52 * @param pReader The loader reader instance which will provide the raw image bits.
53 * @param fFlags Reserved, MBZ.
54 * @param enmArch Architecture specifier.
55 * @param phMod Where to store the handle.
56 */
57int rtldrOpenWithReader(PRTLDRREADER pReader, uint32_t fFlags, RTLDRARCH enmArch, PRTLDRMOD phMod)
58{
59 /*
60 * Read and verify the file signature.
61 */
62 union
63 {
64 char ach[4];
65 uint16_t au16[2];
66 uint32_t u32;
67 } uSign;
68 int rc = pReader->pfnRead(pReader, &uSign, sizeof(uSign), 0);
69 if (RT_FAILURE(rc))
70 return rc;
71#ifndef LDR_WITH_KLDR
72 if ( uSign.au16[0] != IMAGE_DOS_SIGNATURE
73 && uSign.u32 != IMAGE_NT_SIGNATURE
74 && uSign.u32 != IMAGE_ELF_SIGNATURE
75 && uSign.au16[0] != IMAGE_LX_SIGNATURE)
76 {
77 Log(("rtldrOpenWithReader: %s: unknown magic %#x / '%.4s\n", pReader->pfnLogName(pReader), uSign.u32, &uSign.ach[0]));
78 return VERR_INVALID_EXE_SIGNATURE;
79 }
80#endif
81 uint32_t offHdr = 0;
82 if (uSign.au16[0] == IMAGE_DOS_SIGNATURE)
83 {
84 rc = pReader->pfnRead(pReader, &offHdr, sizeof(offHdr), RT_OFFSETOF(IMAGE_DOS_HEADER, e_lfanew));
85 if (RT_FAILURE(rc))
86 return rc;
87
88 if (offHdr <= sizeof(IMAGE_DOS_HEADER))
89 {
90 Log(("rtldrOpenWithReader: %s: no new header / invalid offset %#RX32\n", pReader->pfnLogName(pReader), offHdr));
91 return VERR_INVALID_EXE_SIGNATURE;
92 }
93 rc = pReader->pfnRead(pReader, &uSign, sizeof(uSign), offHdr);
94 if (RT_FAILURE(rc))
95 return rc;
96 if ( uSign.u32 != IMAGE_NT_SIGNATURE
97 && uSign.au16[0] != IMAGE_LX_SIGNATURE
98 && uSign.au16[0] != IMAGE_LE_SIGNATURE
99 && uSign.au16[0] != IMAGE_NE_SIGNATURE)
100 {
101 Log(("rtldrOpenWithReader: %s: unknown new magic %#x / '%.4s\n", pReader->pfnLogName(pReader), uSign.u32, &uSign.ach[0]));
102 return VERR_INVALID_EXE_SIGNATURE;
103 }
104 }
105
106 /*
107 * Create image intepreter instance depending on the signature.
108 */
109 if (uSign.u32 == IMAGE_NT_SIGNATURE)
110#ifdef LDR_WITH_PE
111 rc = rtldrPEOpen(pReader, fFlags, enmArch, offHdr, phMod);
112#else
113 rc = VERR_PE_EXE_NOT_SUPPORTED;
114#endif
115 else if (uSign.u32 == IMAGE_ELF_SIGNATURE)
116#if defined(LDR_WITH_ELF)
117 rc = rtldrELFOpen(pReader, fFlags, enmArch, phMod);
118#else
119 rc = VERR_ELF_EXE_NOT_SUPPORTED;
120#endif
121 else if (uSign.au16[0] == IMAGE_LX_SIGNATURE)
122#ifdef LDR_WITH_LX
123 rc = rtldrLXOpen(pReader, fFlags, enmArch, offHdr, phMod);
124#else
125 rc = VERR_LX_EXE_NOT_SUPPORTED;
126#endif
127 else if (uSign.au16[0] == IMAGE_LE_SIGNATURE)
128#ifdef LDR_WITH_LE
129 rc = rtldrLEOpen(pReader, fFlags, enmArch, phMod);
130#else
131 rc = VERR_LE_EXE_NOT_SUPPORTED;
132#endif
133 else if (uSign.au16[0] == IMAGE_NE_SIGNATURE)
134#ifdef LDR_WITH_NE
135 rc = rtldrNEOpen(pReader, fFlags, enmArch, phMod);
136#else
137 rc = VERR_NE_EXE_NOT_SUPPORTED;
138#endif
139 else if (uSign.au16[0] == IMAGE_DOS_SIGNATURE)
140#ifdef LDR_WITH_MZ
141 rc = rtldrMZOpen(pReader, fFlags, enmArch, phMod);
142#else
143 rc = VERR_MZ_EXE_NOT_SUPPORTED;
144#endif
145 else if (/* uSign.u32 == IMAGE_AOUT_A_SIGNATURE
146 || uSign.u32 == IMAGE_AOUT_Z_SIGNATURE*/ /** @todo find the aout magics in emx or binutils. */
147 0)
148#ifdef LDR_WITH_AOUT
149 rc = rtldrAOUTOpen(pReader, fFlags, enmArch, phMod);
150#else
151 rc = VERR_AOUT_EXE_NOT_SUPPORTED;
152#endif
153 else
154 {
155#ifndef LDR_WITH_KLDR
156 Log(("rtldrOpenWithReader: %s: the format isn't implemented %#x / '%.4s\n", pReader->pfnLogName(pReader), uSign.u32, &uSign.ach[0]));
157#endif
158 rc = VERR_INVALID_EXE_SIGNATURE;
159 }
160
161#ifdef LDR_WITH_KLDR
162 /* Try kLdr if it's a format we don't recognize. */
163 if (rc <= VERR_INVALID_EXE_SIGNATURE && rc > VERR_BAD_EXE_FORMAT)
164 rc = rtldrkLdrOpen(pReader, fFlags, enmArch, phMod);
165#endif
166
167 LogFlow(("rtldrOpenWithReader: %s: returns %Rrc *phMod=%p\n", pReader->pfnLogName(pReader), rc, *phMod));
168 return rc;
169}
170
171
172/**
173 * Gets the size of the loaded image.
174 * This is only supported for modules which has been opened using RTLdrOpen() and RTLdrOpenBits().
175 *
176 * @returns image size (in bytes).
177 * @returns ~(size_t)0 on if not opened by RTLdrOpen().
178 * @param hLdrMod Handle to the loader module.
179 * @remark Not supported for RTLdrLoad() images.
180 */
181RTDECL(size_t) RTLdrSize(RTLDRMOD hLdrMod)
182{
183 LogFlow(("RTLdrSize: hLdrMod=%RTldrm\n", hLdrMod));
184
185 /*
186 * Validate input.
187 */
188 AssertMsgReturn(rtldrIsValid(hLdrMod), ("hLdrMod=%p\n", hLdrMod), ~(size_t)0);
189 PRTLDRMODINTERNAL pMod = (PRTLDRMODINTERNAL)hLdrMod;
190 AssertMsgReturn(pMod->eState == LDR_STATE_OPENED, ("eState=%d\n", pMod->eState), ~(size_t)0);
191
192 /*
193 * Do it.
194 */
195 size_t cb = pMod->pOps->pfnGetImageSize(pMod);
196 LogFlow(("RTLdrSize: returns %zu\n", cb));
197 return cb;
198}
199RT_EXPORT_SYMBOL(RTLdrSize);
200
201
202/**
203 * Loads the image into a buffer provided by the user and applies fixups
204 * for the given base address.
205 *
206 * @returns iprt status code.
207 * @param hLdrMod The load module handle.
208 * @param pvBits Where to put the bits.
209 * Must be as large as RTLdrSize() suggests.
210 * @param BaseAddress The base address.
211 * @param pfnGetImport Callback function for resolving imports one by one.
212 * @param pvUser User argument for the callback.
213 * @remark Not supported for RTLdrLoad() images.
214 */
215RTDECL(int) RTLdrGetBits(RTLDRMOD hLdrMod, void *pvBits, RTUINTPTR BaseAddress, PFNRTLDRIMPORT pfnGetImport, void *pvUser)
216{
217 LogFlow(("RTLdrGetBits: hLdrMod=%RTldrm pvBits=%p BaseAddress=%RTptr pfnGetImport=%p pvUser=%p\n",
218 hLdrMod, pvBits, BaseAddress, pfnGetImport, pvUser));
219
220 /*
221 * Validate input.
222 */
223 AssertMsgReturn(rtldrIsValid(hLdrMod), ("hLdrMod=%p\n", hLdrMod), VERR_INVALID_HANDLE);
224 AssertMsgReturn(VALID_PTR(pvBits), ("pvBits=%p\n", pvBits), VERR_INVALID_PARAMETER);
225 AssertMsgReturn(VALID_PTR(pfnGetImport), ("pfnGetImport=%p\n", pfnGetImport), VERR_INVALID_PARAMETER);
226 PRTLDRMODINTERNAL pMod = (PRTLDRMODINTERNAL)hLdrMod;
227 AssertMsgReturn(pMod->eState == LDR_STATE_OPENED, ("eState=%d\n", pMod->eState), VERR_WRONG_ORDER);
228
229 /*
230 * Do it.
231 */
232 int rc = pMod->pOps->pfnGetBits(pMod, pvBits, BaseAddress, pfnGetImport, pvUser);
233 LogFlow(("RTLdrGetBits: returns %Rrc\n",rc));
234 return rc;
235}
236RT_EXPORT_SYMBOL(RTLdrGetBits);
237
238
239/**
240 * Relocates bits after getting them.
241 * Useful for code which moves around a bit.
242 *
243 * @returns iprt status code.
244 * @param hLdrMod The loader module handle.
245 * @param pvBits Where the image bits are.
246 * Must've been passed to RTLdrGetBits().
247 * @param NewBaseAddress The new base address.
248 * @param OldBaseAddress The old base address.
249 * @param pfnGetImport Callback function for resolving imports one by one.
250 * @param pvUser User argument for the callback.
251 * @remark Not supported for RTLdrLoad() images.
252 */
253RTDECL(int) RTLdrRelocate(RTLDRMOD hLdrMod, void *pvBits, RTUINTPTR NewBaseAddress, RTUINTPTR OldBaseAddress,
254 PFNRTLDRIMPORT pfnGetImport, void *pvUser)
255{
256 LogFlow(("RTLdrRelocate: hLdrMod=%RTldrm pvBits=%p NewBaseAddress=%RTptr OldBaseAddress=%RTptr pfnGetImport=%p pvUser=%p\n",
257 hLdrMod, pvBits, NewBaseAddress, OldBaseAddress, pfnGetImport, pvUser));
258
259 /*
260 * Validate input.
261 */
262 AssertMsgReturn(rtldrIsValid(hLdrMod), ("hLdrMod=%p\n", hLdrMod), VERR_INVALID_HANDLE);
263 AssertMsgReturn(VALID_PTR(pvBits), ("pvBits=%p\n", pvBits), VERR_INVALID_PARAMETER);
264 AssertMsgReturn(VALID_PTR(pfnGetImport), ("pfnGetImport=%p\n", pfnGetImport), VERR_INVALID_PARAMETER);
265 PRTLDRMODINTERNAL pMod = (PRTLDRMODINTERNAL)hLdrMod;
266 AssertMsgReturn(pMod->eState == LDR_STATE_OPENED, ("eState=%d\n", pMod->eState), VERR_WRONG_ORDER);
267
268 /*
269 * Do it.
270 */
271 int rc = pMod->pOps->pfnRelocate(pMod, pvBits, NewBaseAddress, OldBaseAddress, pfnGetImport, pvUser);
272 LogFlow(("RTLdrRelocate: returns %Rrc\n", rc));
273 return rc;
274}
275RT_EXPORT_SYMBOL(RTLdrRelocate);
276
277
278/**
279 * Gets the address of a named exported symbol.
280 *
281 * This function differs from the plain one in that it can deal with
282 * both GC and HC address sizes, and that it can calculate the symbol
283 * value relative to any given base address.
284 *
285 * @returns iprt status code.
286 * @param hLdrMod The loader module handle.
287 * @param pvBits Optional pointer to the loaded image.
288 * Set this to NULL if no RTLdrGetBits() processed image bits are available.
289 * Not supported for RTLdrLoad() images and must be NULL.
290 * @param BaseAddress Image load address.
291 * Not supported for RTLdrLoad() images and must be 0.
292 * @param pszSymbol Symbol name.
293 * @param pValue Where to store the symbol value.
294 */
295RTDECL(int) RTLdrGetSymbolEx(RTLDRMOD hLdrMod, const void *pvBits, RTUINTPTR BaseAddress, const char *pszSymbol, RTUINTPTR *pValue)
296{
297 LogFlow(("RTLdrGetSymbolEx: hLdrMod=%RTldrm pvBits=%p BaseAddress=%RTptr pszSymbol=%p:{%s} pValue\n",
298 hLdrMod, pvBits, BaseAddress, pszSymbol, pszSymbol, pValue));
299
300 /*
301 * Validate input.
302 */
303 AssertMsgReturn(rtldrIsValid(hLdrMod), ("hLdrMod=%p\n", hLdrMod), VERR_INVALID_HANDLE);
304 AssertMsgReturn(!pvBits || VALID_PTR(pvBits), ("pvBits=%p\n", pvBits), VERR_INVALID_PARAMETER);
305 AssertMsgReturn(pszSymbol, ("pszSymbol=%p\n", pszSymbol), VERR_INVALID_PARAMETER);
306 AssertMsgReturn(VALID_PTR(pValue), ("pValue=%p\n", pvBits), VERR_INVALID_PARAMETER);
307 PRTLDRMODINTERNAL pMod = (PRTLDRMODINTERNAL)hLdrMod;
308 //AssertMsgReturn(pMod->eState == LDR_STATE_OPENED, ("eState=%d\n", pMod->eState), VERR_WRONG_ORDER);
309
310 /*
311 * Do it.
312 */
313 int rc;
314 if (pMod->pOps->pfnGetSymbolEx)
315 rc = pMod->pOps->pfnGetSymbolEx(pMod, pvBits, BaseAddress, pszSymbol, pValue);
316 else if (!BaseAddress && !pvBits)
317 {
318 void *pvValue;
319 rc = pMod->pOps->pfnGetSymbol(pMod, pszSymbol, &pvValue);
320 if (RT_SUCCESS(rc))
321 *pValue = (uintptr_t)pvValue;
322 }
323 else
324 AssertMsgFailedReturn(("BaseAddress=%RTptr pvBits=%p\n", BaseAddress, pvBits), VERR_INVALID_FUNCTION);
325 LogFlow(("RTLdrGetSymbolEx: returns %Rrc *pValue=%p\n", rc, *pValue));
326 return rc;
327}
328RT_EXPORT_SYMBOL(RTLdrGetSymbolEx);
329
330
331/**
332 * Enumerates all symbols in a module.
333 *
334 * @returns iprt status code.
335 * @param hLdrMod The loader module handle.
336 * @param fFlags Flags indicating what to return and such.
337 * @param pvBits Optional pointer to the loaded image.
338 * Set this to NULL if no RTLdrGetBits() processed image bits are available.
339 * @param BaseAddress Image load address.
340 * @param pfnCallback Callback function.
341 * @param pvUser User argument for the callback.
342 * @remark Not supported for RTLdrLoad() images.
343 */
344RTDECL(int) RTLdrEnumSymbols(RTLDRMOD hLdrMod, unsigned fFlags, const void *pvBits, RTUINTPTR BaseAddress, PFNRTLDRENUMSYMS pfnCallback, void *pvUser)
345{
346 LogFlow(("RTLdrEnumSymbols: hLdrMod=%RTldrm fFlags=%#x pvBit=%p BaseAddress=%RTptr pfnCallback=%p pvUser=%p\n",
347 hLdrMod, fFlags, pvBits, BaseAddress, pfnCallback, pvUser));
348
349 /*
350 * Validate input.
351 */
352 AssertMsgReturn(rtldrIsValid(hLdrMod), ("hLdrMod=%p\n", hLdrMod), VERR_INVALID_HANDLE);
353 AssertMsgReturn(!pvBits || VALID_PTR(pvBits), ("pvBits=%p\n", pvBits), VERR_INVALID_PARAMETER);
354 AssertMsgReturn(VALID_PTR(pfnCallback), ("pfnCallback=%p\n", pfnCallback), VERR_INVALID_PARAMETER);
355 PRTLDRMODINTERNAL pMod = (PRTLDRMODINTERNAL)hLdrMod;
356 //AssertMsgReturn(pMod->eState == LDR_STATE_OPENED, ("eState=%d\n", pMod->eState), VERR_WRONG_ORDER);
357
358 /*
359 * Do it.
360 */
361 int rc = pMod->pOps->pfnEnumSymbols(pMod, fFlags, pvBits, BaseAddress, pfnCallback, pvUser);
362 LogFlow(("RTLdrEnumSymbols: returns %Rrc\n", rc));
363 return rc;
364}
365RT_EXPORT_SYMBOL(RTLdrEnumSymbols);
366
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