VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/ldr/ldrFile.cpp@ 17951

Last change on this file since 17951 was 16933, checked in by vboxsync, 16 years ago

IPRT/PDM,SUPLIb,REM: Extended RTLdrOpen with an architecture argument for use with FAT R0.r0 images later some day. Also added fFlags argument that's currently MBZ case.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 10.2 KB
Line 
1/* $Id: ldrFile.cpp 16933 2009-02-18 23:42:57Z vboxsync $ */
2/** @file
3 * IPRT - Binary Image Loader, The File Oriented Parts.
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* Header Files *
33*******************************************************************************/
34#define LOG_GROUP RTLOGGROUP_LDR
35#include <iprt/ldr.h>
36#include <iprt/alloc.h>
37#include <iprt/file.h>
38#include <iprt/assert.h>
39#include <iprt/log.h>
40#include <iprt/err.h>
41#include <iprt/string.h>
42#include "internal/ldr.h"
43#include "internal/ldrMZ.h"
44
45
46/*******************************************************************************
47* Structures and Typedefs *
48*******************************************************************************/
49/**
50 * File Reader instance.
51 * This provides raw image bits from a file.
52 */
53typedef struct RTLDRREADERFILE
54{
55 /** The core. */
56 RTLDRREADER Core;
57 /** The file. */
58 RTFILE File;
59 /** The file size. */
60 RTFOFF cbFile;
61 /** The current offset. */
62 RTFOFF off;
63 /** Number of users or the mapping. */
64 RTUINT cMappings;
65 /** Pointer to the in memory mapping. */
66 void *pvMapping;
67 /** The filename (variable size). */
68 char szFilename[1];
69} RTLDRREADERFILE, *PRTLDRREADERFILE;
70
71
72/** @copydoc RTLDRREADER::pfnRead */
73static DECLCALLBACK(int) rtldrFileRead(PRTLDRREADER pReader, void *pvBuf, size_t cb, RTFOFF off)
74{
75 PRTLDRREADERFILE pFileReader = (PRTLDRREADERFILE)pReader;
76
77 /*
78 * Seek.
79 */
80 if (pFileReader->off != off)
81 {
82 int rc = RTFileSeek(pFileReader->File, off, RTFILE_SEEK_BEGIN, NULL);
83 if (RT_FAILURE(rc))
84 {
85 pFileReader->off = -1;
86 return rc;
87 }
88 pFileReader->off = off;
89 }
90
91 /*
92 * Read.
93 */
94 int rc = RTFileRead(pFileReader->File, pvBuf, cb, NULL);
95 if (RT_SUCCESS(rc))
96 pFileReader->off += cb;
97 else
98 pFileReader->off = -1;
99 return rc;
100}
101
102
103/** @copydoc RTLDRREADER::pfnTell */
104static DECLCALLBACK(RTFOFF) rtldrFileTell(PRTLDRREADER pReader)
105{
106 PRTLDRREADERFILE pFileReader = (PRTLDRREADERFILE)pReader;
107 return pFileReader->off;
108}
109
110
111/** @copydoc RTLDRREADER::pfnSize */
112static DECLCALLBACK(RTFOFF) rtldrFileSize(PRTLDRREADER pReader)
113{
114 PRTLDRREADERFILE pFileReader = (PRTLDRREADERFILE)pReader;
115 return pFileReader->cbFile;
116}
117
118
119/** @copydoc RTLDRREADER::pfnLogName */
120static DECLCALLBACK(const char *) rtldrFileLogName(PRTLDRREADER pReader)
121{
122 PRTLDRREADERFILE pFileReader = (PRTLDRREADERFILE)pReader;
123 return pFileReader->szFilename;
124}
125
126
127/** @copydoc RTLDRREADER::pfnMap */
128static DECLCALLBACK(int) rtldrFileMap(PRTLDRREADER pReader, const void **ppvBits)
129{
130 PRTLDRREADERFILE pFileReader = (PRTLDRREADERFILE)pReader;
131
132 /*
133 * Already mapped?
134 */
135 if (pFileReader->pvMapping)
136 {
137 pFileReader->cMappings++;
138 *ppvBits = pFileReader->pvMapping;
139 return VINF_SUCCESS;
140 }
141
142 /*
143 * Allocate memory.
144 */
145 size_t cb = (size_t)pFileReader->cbFile;
146 if ((RTFOFF)cb != pFileReader->cbFile)
147 return VERR_IMAGE_TOO_BIG;
148 pFileReader->pvMapping = RTMemAlloc(cb);
149 if (!pFileReader->pvMapping)
150 return VERR_NO_MEMORY;
151 int rc = rtldrFileRead(pReader, pFileReader->pvMapping, cb, 0);
152 if (RT_SUCCESS(rc))
153 {
154 pFileReader->cMappings = 1;
155 *ppvBits = pFileReader->pvMapping;
156 }
157 else
158 {
159 RTMemFree(pFileReader->pvMapping);
160 pFileReader->pvMapping = NULL;
161 }
162
163 return rc;
164}
165
166
167/** @copydoc RTLDRREADER::pfnUnmap */
168static DECLCALLBACK(int) rtldrFileUnmap(PRTLDRREADER pReader, const void *pvBits)
169{
170 PRTLDRREADERFILE pFileReader = (PRTLDRREADERFILE)pReader;
171 AssertReturn(pFileReader->cMappings > 0, VERR_INVALID_PARAMETER);
172
173 if (!--pFileReader->cMappings)
174 {
175 RTMemFree(pFileReader->pvMapping);
176 pFileReader->pvMapping = NULL;
177 }
178
179 return VINF_SUCCESS;
180}
181
182
183/** @copydoc RTLDRREADER::pfnDestroy */
184static DECLCALLBACK(int) rtldrFileDestroy(PRTLDRREADER pReader)
185{
186 int rc = VINF_SUCCESS;
187 PRTLDRREADERFILE pFileReader = (PRTLDRREADERFILE)pReader;
188 if (pFileReader->File != NIL_RTFILE)
189 {
190 rc = RTFileClose(pFileReader->File);
191 AssertRC(rc);
192 pFileReader->File = NIL_RTFILE;
193 }
194 RTMemFree(pFileReader);
195 return rc;
196}
197
198
199/**
200 * Opens a loader file reader.
201 *
202 * @returns iprt status code.
203 * @param ppReader Where to store the reader instance on success.
204 * @param pszFilename The file to open.
205 */
206static int rtldrFileCreate(PRTLDRREADER *ppReader, const char *pszFilename)
207{
208 size_t cchFilename = strlen(pszFilename);
209 int rc = VERR_NO_MEMORY;
210 PRTLDRREADERFILE pFileReader = (PRTLDRREADERFILE)RTMemAlloc(sizeof(*pFileReader) + cchFilename);
211 if (pFileReader)
212 {
213 memcpy(pFileReader->szFilename, pszFilename, cchFilename + 1);
214 rc = RTFileOpen(&pFileReader->File, pszFilename, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE);
215 if (RT_SUCCESS(rc))
216 {
217 rc = RTFileGetSize(pFileReader->File, (uint64_t *)&pFileReader->cbFile);
218 if (RT_SUCCESS(rc))
219 {
220 pFileReader->Core.pfnRead = rtldrFileRead;
221 pFileReader->Core.pfnTell = rtldrFileTell;
222 pFileReader->Core.pfnSize = rtldrFileSize;
223 pFileReader->Core.pfnLogName = rtldrFileLogName;
224 pFileReader->Core.pfnMap = rtldrFileMap;
225 pFileReader->Core.pfnUnmap = rtldrFileUnmap;
226 pFileReader->Core.pfnDestroy = rtldrFileDestroy;
227 pFileReader->off = 0;
228 pFileReader->cMappings = 0;
229 pFileReader->pvMapping = NULL;
230 *ppReader = &pFileReader->Core;
231 return VINF_SUCCESS;
232 }
233 RTFileClose(pFileReader->File);
234 }
235 RTMemFree(pFileReader);
236 }
237 *ppReader = NULL;
238 return rc;
239}
240
241
242/**
243 * Open a binary image file, extended version.
244 *
245 * @returns iprt status code.
246 * @param pszFilename Image filename.
247 * @param fFlags Reserved, MBZ.
248 * @param enmArch CPU architecture specifier for the image to be loaded.
249 * @param phLdrMod Where to store the handle to the loader module.
250 */
251RTDECL(int) RTLdrOpen(const char *pszFilename, uint32_t fFlags, RTLDRARCH enmArch, PRTLDRMOD phLdrMod)
252{
253 LogFlow(("RTLdrOpen: pszFilename=%p:{%s} fFlags=%#x enmArch=%d phLdrMod=%p\n",
254 pszFilename, pszFilename, fFlags, enmArch, phLdrMod));
255 AssertMsgReturn(!fFlags, ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
256 AssertMsgReturn(enmArch > RTLDRARCH_INVALID && enmArch < RTLDRARCH_END, ("%d\n", enmArch), VERR_INVALID_PARAMETER);
257
258 /*
259 * Resolve RTLDRARCH_HOST.
260 */
261 if (enmArch == RTLDRARCH_HOST)
262#if defined(RT_ARCH_AMD64)
263 enmArch = RTLDRARCH_AMD64;
264#elif defined(RT_ARCH_X86)
265 enmArch = RTLDRARCH_X86_32;
266#else
267 enmArch = RTLDRARCH_WHATEVER;
268#endif
269
270 /*
271 * Create file reader & invoke worker which identifies and calls the image interpreter.
272 */
273 PRTLDRREADER pReader;
274 int rc = rtldrFileCreate(&pReader, pszFilename);
275 if (RT_SUCCESS(rc))
276 {
277 rc = rtldrOpenWithReader(pReader, fFlags, enmArch, phLdrMod);
278 if (RT_SUCCESS(rc))
279 {
280 LogFlow(("RTLdrOpen: return %Rrc *phLdrMod\n", rc, *phLdrMod));
281 return rc;
282 }
283 pReader->pfnDestroy(pReader);
284 }
285 *phLdrMod = NIL_RTLDRMOD;
286 LogFlow(("RTLdrOpen: return %Rrc\n", rc));
287 return rc;
288}
289
290
291/**
292 * Opens a binary image file using kLdr.
293 *
294 * @returns iprt status code.
295 * @param pszFilename Image filename.
296 * @param fFlags Reserved, MBZ.
297 * @param enmArch CPU architecture specifier for the image to be loaded.
298 * @param phLdrMod Where to store the handle to the loaded module.
299 * @remark Primarily for testing the loader.
300 */
301RTDECL(int) RTLdrOpenkLdr(const char *pszFilename, uint32_t fFlags, RTLDRARCH enmArch, PRTLDRMOD phLdrMod)
302{
303#ifdef LDR_WITH_KLDR
304 LogFlow(("RTLdrOpenkLdr: pszFilename=%p:{%s} fFlags=%#x enmArch=%d phLdrMod=%p\n",
305 pszFilename, pszFilename, fFlags, enmArch, phLdrMod));
306
307 /*
308 * Resolve RTLDRARCH_HOST.
309 */
310 if (enmArch == RTLDRARCH_HOST)
311# if defined(RT_ARCH_AMD64)
312 enmArch = RTLDRARCH_AMD64;
313# elif defined(RT_ARCH_X86)
314 enmArch = RTLDRARCH_X86_32;
315# else
316 enmArch = RTLDRARCH_WHATEVER;
317# endif
318
319 /*
320 * Create file reader & invoke worker which identifies and calls the image interpreter.
321 */
322 PRTLDRREADER pReader;
323 int rc = rtldrFileCreate(&pReader, pszFilename);
324 if (RT_SUCCESS(rc))
325 {
326 rc = rtldrkLdrOpen(pReader, fFlags, enmArch, phLdrMod);
327 if (RT_SUCCESS(rc))
328 {
329 LogFlow(("RTLdrOpenkLdr: return %Rrc *phLdrMod\n", rc, *phLdrMod));
330 return rc;
331 }
332 pReader->pfnDestroy(pReader);
333 }
334 *phLdrMod = NIL_RTLDRMOD;
335 LogFlow(("RTLdrOpenkLdr: return %Rrc\n", rc));
336 return rc;
337
338#else
339 return RTLdrOpen(pszFilename, fFlags, enmArch, phLdrMod);
340#endif
341}
342
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