VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/ldr/ldrMemory.cpp@ 46083

Last change on this file since 46083 was 46083, checked in by vboxsync, 12 years ago

Made it possible to find symbols for windows nt using a image-in-guest-memory loader fallback.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.0 KB
Line 
1/* $Id: ldrMemory.cpp 46083 2013-05-14 23:39:28Z vboxsync $ */
2/** @file
3 * IPRT - Binary Image Loader, The Memory/Debugger Oriented Parts.
4 */
5
6/*
7 * Copyright (C) 2006-2013 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/alloc.h>
36#include <iprt/assert.h>
37#include <iprt/log.h>
38#include <iprt/err.h>
39#include <iprt/string.h>
40#include "internal/ldr.h"
41
42
43/*******************************************************************************
44* Structures and Typedefs *
45*******************************************************************************/
46/**
47 * Memory reader (for debuggers) instance.
48 */
49typedef struct RTLDRRDRMEM
50{
51 /** The core. */
52 RTLDRREADER Core;
53 /** The size of the image. */
54 size_t cbImage;
55 /** The current offset. */
56 size_t offCur;
57
58 /** User parameter for the reader and destructor functions.*/
59 void *pvUser;
60 /** Read function. */
61 PFNRTLDRRDRMEMREAD pfnRead;
62 /** Destructor callback. */
63 PFNRTLDRRDRMEMDTOR pfnDtor;
64
65 /** Mapping of the file. */
66 void *pvMapping;
67 /** Mapping usage counter. */
68 uint32_t cMappings;
69
70 /** The fake filename (variable size). */
71 char szName[1];
72} RTLDRRDRMEM;
73/** Memory based loader reader instance data. */
74typedef RTLDRRDRMEM *PRTLDRRDRMEM;
75
76
77/** @callback_method_impl{FNRTLDRRDRMEMDTOR,
78 * Default destructor - pvUser points to the image memory block.}
79 */
80static DECLCALLBACK(void) rtldrRdrMemDefaultDtor(void *pvUser)
81{
82 RTMemFree(pvUser);
83}
84
85
86/** @callback_method_impl{FNRTLDRRDRMEMREAD,
87 * Default memory reader - pvUser points to the image memory block.}
88 */
89static DECLCALLBACK(int) rtldrRdrMemDefaultReader(void *pvBuf, size_t cb, size_t off, void *pvUser)
90{
91 memcpy(pvBuf, (uint8_t *)pvUser + off, cb);
92 return VINF_SUCCESS;
93}
94
95
96/** @copydoc RTLDRREADER::pfnRead */
97static DECLCALLBACK(int) rtldrRdrMem_Read(PRTLDRREADER pReader, void *pvBuf, size_t cb, RTFOFF off)
98{
99 PRTLDRRDRMEM pThis = (PRTLDRRDRMEM)pReader;
100
101 AssertReturn(off >= 0, VERR_INVALID_PARAMETER);
102 if ( cb > pThis->cbImage
103 || off > (RTFOFF)pThis->cbImage
104 || off + (RTFOFF)cb > (RTFOFF)pThis->cbImage)
105 {
106 pThis->offCur = pThis->cbImage;
107 return VERR_EOF;
108 }
109
110 int rc = pThis->pfnRead(pvBuf, cb, (size_t)off, pThis->pvUser);
111 if (RT_SUCCESS(rc))
112 pThis->offCur = (size_t)off + cb;
113 else
114 pThis->offCur = ~(size_t)0;
115 return rc;
116}
117
118
119/** @copydoc RTLDRREADER::pfnTell */
120static DECLCALLBACK(RTFOFF) rtldrRdrMem_Tell(PRTLDRREADER pReader)
121{
122 PRTLDRRDRMEM pThis = (PRTLDRRDRMEM)pReader;
123 return pThis->offCur;
124}
125
126
127/** @copydoc RTLDRREADER::pfnSize */
128static DECLCALLBACK(RTFOFF) rtldrRdrMem_Size(PRTLDRREADER pReader)
129{
130 PRTLDRRDRMEM pThis = (PRTLDRRDRMEM)pReader;
131 return pThis->cbImage;
132}
133
134
135/** @copydoc RTLDRREADER::pfnLogName */
136static DECLCALLBACK(const char *) rtldrRdrMem_LogName(PRTLDRREADER pReader)
137{
138 PRTLDRRDRMEM pThis = (PRTLDRRDRMEM)pReader;
139 return pThis->szName;
140}
141
142
143/** @copydoc RTLDRREADER::pfnMap */
144static DECLCALLBACK(int) rtldrRdrMem_Map(PRTLDRREADER pReader, const void **ppvBits)
145{
146 PRTLDRRDRMEM pThis = (PRTLDRRDRMEM)pReader;
147
148 /*
149 * Already mapped?
150 */
151 if (pThis->pvMapping)
152 {
153 pThis->cMappings++;
154 *ppvBits = pThis->pvMapping;
155 return VINF_SUCCESS;
156 }
157
158 /*
159 * Allocate memory.
160 */
161 pThis->pvMapping = RTMemAlloc(pThis->cbImage);
162 if (!pThis->pvMapping)
163 return VERR_NO_MEMORY;
164 int rc = rtldrRdrMem_Read(pReader, pThis->pvMapping, pThis->cbImage, 0);
165 if (RT_SUCCESS(rc))
166 {
167 pThis->cMappings = 1;
168 *ppvBits = pThis->pvMapping;
169 }
170 else
171 {
172 RTMemFree(pThis->pvMapping);
173 pThis->pvMapping = NULL;
174 }
175
176 return rc;
177}
178
179
180/** @copydoc RTLDRREADER::pfnUnmap */
181static DECLCALLBACK(int) rtldrRdrMem_Unmap(PRTLDRREADER pReader, const void *pvBits)
182{
183 PRTLDRRDRMEM pThis = (PRTLDRRDRMEM)pReader;
184 AssertReturn(pThis->cMappings > 0, VERR_INVALID_PARAMETER);
185
186 if (!--pThis->cMappings)
187 {
188 RTMemFree(pThis->pvMapping);
189 pThis->pvMapping = NULL;
190 }
191
192 NOREF(pvBits);
193 return VINF_SUCCESS;
194}
195
196
197/** @copydoc RTLDRREADER::pfnDestroy */
198static DECLCALLBACK(int) rtldrRdrMem_Destroy(PRTLDRREADER pReader)
199{
200 PRTLDRRDRMEM pThis = (PRTLDRRDRMEM)pReader;
201 pThis->pfnDtor(pThis->pvUser);
202 RTMemFree(pThis);
203 return VINF_SUCCESS;
204}
205
206
207/**
208 * Opens a memory based loader reader.
209 *
210 * @returns iprt status code.
211 * @param ppReader Where to store the reader instance on success.
212 * @param pszName The name to give the image.
213 * @param cbImage The image size.
214 * @param pfnRead The reader function. If NULL, a default reader is
215 * used that assumes pvUser points to a memory buffer
216 * of at least @a cbImage size.
217 * @param pfnDtor The destructor. If NULL, a default destructore is
218 * used that will call RTMemFree on @a pvUser.
219 * @param pvUser User argument. If either @a pfnRead or @a pfnDtor
220 * is NULL, this must be a pointer to readable memory
221 * (see above).
222 */
223static int rtldrRdrMem_Create(PRTLDRREADER *ppReader, const char *pszName, size_t cbImage,
224 PFNRTLDRRDRMEMREAD pfnRead, PFNRTLDRRDRMEMDTOR pfnDtor, void *pvUser)
225{
226 AssertReturn((RTFOFF)cbImage < RTFOFF_MAX, VERR_INVALID_PARAMETER);
227 AssertReturn((RTFOFF)cbImage > 0, VERR_INVALID_PARAMETER);
228
229 size_t cchName = strlen(pszName);
230 int rc = VERR_NO_MEMORY;
231 PRTLDRRDRMEM pThis = (PRTLDRRDRMEM)RTMemAlloc(sizeof(*pThis) + cchName);
232 if (pThis)
233 {
234 memcpy(pThis->szName, pszName, cchName + 1);
235 pThis->cbImage = cbImage;
236 pThis->pvUser = pvUser;
237 pThis->offCur = 0;
238 pThis->pvUser = pvUser;
239 pThis->pfnRead = pfnRead ? pfnRead : rtldrRdrMemDefaultReader;
240 pThis->pfnDtor = pfnDtor ? pfnDtor : rtldrRdrMemDefaultDtor;
241 pThis->pvMapping = NULL;
242 pThis->cMappings = 0;
243 pThis->Core.pszName = "rdrmem";
244 pThis->Core.pfnRead = rtldrRdrMem_Read;
245 pThis->Core.pfnTell = rtldrRdrMem_Tell;
246 pThis->Core.pfnSize = rtldrRdrMem_Size;
247 pThis->Core.pfnLogName = rtldrRdrMem_LogName;
248 pThis->Core.pfnMap = rtldrRdrMem_Map;
249 pThis->Core.pfnUnmap = rtldrRdrMem_Unmap;
250 pThis->Core.pfnDestroy = rtldrRdrMem_Destroy;
251 *ppReader = &pThis->Core;
252 return VINF_SUCCESS;
253 }
254
255 *ppReader = NULL;
256 return rc;
257}
258
259
260RTDECL(int) RTLdrOpenInMemory(const char *pszName, uint32_t fFlags, RTLDRARCH enmArch, size_t cbImage,
261 PFNRTLDRRDRMEMREAD pfnRead, PFNRTLDRRDRMEMDTOR pfnDtor, void *pvUser,
262 PRTLDRMOD phLdrMod)
263{
264 LogFlow(("RTLdrOpenInMemory: pszName=%p:{%s} fFlags=%#x enmArch=%d cbImage=%#zu pfnRead=%p pfnDtor=%p pvUser=%p phLdrMod=%p\n",
265 pszName, pszName, fFlags, enmArch, cbImage, pfnRead, pfnDtor, pvUser, phLdrMod));
266
267 if (!pfnRead || !pfnDtor)
268 AssertPtrReturn(pvUser, VERR_INVALID_POINTER);
269 if (!pfnDtor)
270 pfnDtor = rtldrRdrMemDefaultDtor;
271 else
272 AssertPtrReturn(pfnRead, VERR_INVALID_POINTER);
273
274 /* The rest of the validations will call the destructor. */
275 AssertMsgReturnStmt(!(fFlags & ~RTLDR_O_VALID_MASK), ("%#x\n", fFlags),
276 pfnDtor(pvUser), VERR_INVALID_PARAMETER);
277 AssertMsgReturnStmt(enmArch > RTLDRARCH_INVALID && enmArch < RTLDRARCH_END, ("%d\n", enmArch),
278 pfnDtor(pvUser), VERR_INVALID_PARAMETER);
279 if (!pfnRead)
280 pfnRead = rtldrRdrMemDefaultReader;
281 else
282 AssertReturnStmt(RT_VALID_PTR(pfnRead), pfnDtor(pvUser), VERR_INVALID_POINTER);
283 AssertReturnStmt(cbImage > 0, pfnDtor(pvUser), VERR_INVALID_PARAMETER);
284
285 /*
286 * Resolve RTLDRARCH_HOST.
287 */
288 if (enmArch == RTLDRARCH_HOST)
289#if defined(RT_ARCH_AMD64)
290 enmArch = RTLDRARCH_AMD64;
291#elif defined(RT_ARCH_X86)
292 enmArch = RTLDRARCH_X86_32;
293#else
294 enmArch = RTLDRARCH_WHATEVER;
295#endif
296
297 /*
298 * Create file reader & invoke worker which identifies and calls the image interpreter.
299 */
300 PRTLDRREADER pReader;
301 int rc = rtldrRdrMem_Create(&pReader, pszName, cbImage, pfnRead, pfnDtor, pvUser);
302 if (RT_SUCCESS(rc))
303 {
304 rc = rtldrOpenWithReader(pReader, fFlags, enmArch, phLdrMod);
305 if (RT_SUCCESS(rc))
306 {
307 LogFlow(("RTLdrOpen: return %Rrc *phLdrMod\n", rc, *phLdrMod));
308 return rc;
309 }
310
311 pReader->pfnDestroy(pReader);
312 }
313 else
314 pfnDtor(pvUser),
315 *phLdrMod = NIL_RTLDRMOD;
316
317 LogFlow(("RTLdrOpen: return %Rrc\n", rc));
318 return rc;
319}
320RT_EXPORT_SYMBOL(RTLdrOpenInMemory);
321
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