VirtualBox

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

Last change on this file since 5999 was 5999, checked in by vboxsync, 17 years ago

The Giant CDDL Dual-License Header Change.

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette