VirtualBox

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

Last change on this file since 56290 was 56290, checked in by vboxsync, 10 years ago

IPRT: Updated (C) year.

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