VirtualBox

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

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

Biggest check-in ever. New source code headers for all (C) innotek files.

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