VirtualBox

source: vbox/trunk/src/VBox/Runtime/ldrFile.cpp@ 3460

Last change on this file since 3460 was 2981, checked in by vboxsync, 18 years ago

InnoTek -> innotek: all the headers and comments.

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