VirtualBox

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

Last change on this file was 98103, checked in by vboxsync, 17 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 9.8 KB
Line 
1/* $Id: ldrFile.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * IPRT - Binary Image Loader, The File Oriented Parts.
4 */
5
6/*
7 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41#define LOG_GROUP RTLOGGROUP_LDR
42#include <iprt/ldr.h>
43#include "internal/iprt.h"
44
45#include <iprt/alloc.h>
46#include <iprt/file.h>
47#include <iprt/assert.h>
48#include <iprt/log.h>
49#include <iprt/err.h>
50#include <iprt/string.h>
51#include <iprt/formats/mz.h>
52#include "internal/ldr.h"
53
54
55/*********************************************************************************************************************************
56* Structures and Typedefs *
57*********************************************************************************************************************************/
58/**
59 * File Reader instance.
60 * This provides raw image bits from a file.
61 */
62typedef struct RTLDRREADERFILE
63{
64 /** The core. */
65 RTLDRREADER Core;
66 /** The file. */
67 RTFILE hFile;
68 /** The file size. */
69 uint64_t cbFile;
70 /** The current offset. */
71 RTFOFF off;
72 /** Number of users or the mapping. */
73 RTUINT cMappings;
74 /** Pointer to the in memory mapping. */
75 void *pvMapping;
76 /** The filename (variable size). */
77 char szFilename[1];
78} RTLDRREADERFILE, *PRTLDRREADERFILE;
79
80
81/** @copydoc RTLDRREADER::pfnRead */
82static DECLCALLBACK(int) rtldrFileRead(PRTLDRREADER pReader, void *pvBuf, size_t cb, RTFOFF off)
83{
84 PRTLDRREADERFILE pFileReader = (PRTLDRREADERFILE)pReader;
85
86 /*
87 * Seek.
88 */
89 if (pFileReader->off != off)
90 {
91 int rc = RTFileSeek(pFileReader->hFile, off, RTFILE_SEEK_BEGIN, NULL);
92 if (RT_FAILURE(rc))
93 {
94 pFileReader->off = -1;
95 return rc;
96 }
97 pFileReader->off = off;
98 }
99
100 /*
101 * Read.
102 */
103 int rc = RTFileRead(pFileReader->hFile, pvBuf, cb, NULL);
104 if (RT_SUCCESS(rc))
105 pFileReader->off += cb;
106 else
107 pFileReader->off = -1;
108 return rc;
109}
110
111
112/** @copydoc RTLDRREADER::pfnTell */
113static DECLCALLBACK(RTFOFF) rtldrFileTell(PRTLDRREADER pReader)
114{
115 PRTLDRREADERFILE pFileReader = (PRTLDRREADERFILE)pReader;
116 return pFileReader->off;
117}
118
119
120/** @copydoc RTLDRREADER::pfnSize */
121static DECLCALLBACK(uint64_t) rtldrFileSize(PRTLDRREADER pReader)
122{
123 PRTLDRREADERFILE pFileReader = (PRTLDRREADERFILE)pReader;
124 return pFileReader->cbFile;
125}
126
127
128/** @copydoc RTLDRREADER::pfnLogName */
129static DECLCALLBACK(const char *) rtldrFileLogName(PRTLDRREADER pReader)
130{
131 PRTLDRREADERFILE pFileReader = (PRTLDRREADERFILE)pReader;
132 return pFileReader->szFilename;
133}
134
135
136/** @copydoc RTLDRREADER::pfnMap */
137static DECLCALLBACK(int) rtldrFileMap(PRTLDRREADER pReader, const void **ppvBits)
138{
139 PRTLDRREADERFILE pFileReader = (PRTLDRREADERFILE)pReader;
140
141 /*
142 * Already mapped?
143 */
144 if (pFileReader->pvMapping)
145 {
146 pFileReader->cMappings++;
147 *ppvBits = pFileReader->pvMapping;
148 return VINF_SUCCESS;
149 }
150
151 /*
152 * Allocate memory.
153 */
154 size_t cb = (size_t)pFileReader->cbFile;
155 if ((uint64_t)cb != pFileReader->cbFile)
156 return VERR_IMAGE_TOO_BIG;
157 pFileReader->pvMapping = RTMemAlloc(cb);
158 if (!pFileReader->pvMapping)
159 return VERR_NO_MEMORY;
160 int rc = rtldrFileRead(pReader, pFileReader->pvMapping, cb, 0);
161 if (RT_SUCCESS(rc))
162 {
163 pFileReader->cMappings = 1;
164 *ppvBits = pFileReader->pvMapping;
165 }
166 else
167 {
168 RTMemFree(pFileReader->pvMapping);
169 pFileReader->pvMapping = NULL;
170 }
171
172 return rc;
173}
174
175
176/** @copydoc RTLDRREADER::pfnUnmap */
177static DECLCALLBACK(int) rtldrFileUnmap(PRTLDRREADER pReader, const void *pvBits)
178{
179 PRTLDRREADERFILE pFileReader = (PRTLDRREADERFILE)pReader;
180 AssertReturn(pFileReader->cMappings > 0, VERR_INVALID_PARAMETER);
181
182 if (!--pFileReader->cMappings)
183 {
184 RTMemFree(pFileReader->pvMapping);
185 pFileReader->pvMapping = NULL;
186 }
187
188 NOREF(pvBits);
189 return VINF_SUCCESS;
190}
191
192
193/** @copydoc RTLDRREADER::pfnDestroy */
194static DECLCALLBACK(int) rtldrFileDestroy(PRTLDRREADER pReader)
195{
196 int rc = VINF_SUCCESS;
197 PRTLDRREADERFILE pFileReader = (PRTLDRREADERFILE)pReader;
198
199 Assert(!pFileReader->cMappings);
200
201 if (pFileReader->hFile != NIL_RTFILE)
202 {
203 rc = RTFileClose(pFileReader->hFile);
204 AssertRC(rc);
205 pFileReader->hFile = NIL_RTFILE;
206 }
207
208 if (pFileReader->pvMapping)
209 {
210 RTMemFree(pFileReader->pvMapping);
211 pFileReader->pvMapping = NULL;
212 }
213
214 RTMemFree(pFileReader);
215 return rc;
216}
217
218
219/**
220 * Opens a loader file reader.
221 *
222 * @returns iprt status code.
223 * @param ppReader Where to store the reader instance on success.
224 * @param pszFilename The file to open.
225 */
226static int rtldrFileCreate(PRTLDRREADER *ppReader, const char *pszFilename)
227{
228 size_t cchFilename = strlen(pszFilename);
229 int rc = VERR_NO_MEMORY;
230 PRTLDRREADERFILE pFileReader = (PRTLDRREADERFILE)RTMemAlloc(sizeof(*pFileReader) + cchFilename);
231 if (pFileReader)
232 {
233 memcpy(pFileReader->szFilename, pszFilename, cchFilename + 1);
234 rc = RTFileOpen(&pFileReader->hFile, pszFilename, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE);
235 if (RT_SUCCESS(rc))
236 {
237 rc = RTFileQuerySize(pFileReader->hFile, &pFileReader->cbFile);
238 if (RT_SUCCESS(rc))
239 {
240 pFileReader->Core.uMagic = RTLDRREADER_MAGIC;
241 pFileReader->Core.pfnRead = rtldrFileRead;
242 pFileReader->Core.pfnTell = rtldrFileTell;
243 pFileReader->Core.pfnSize = rtldrFileSize;
244 pFileReader->Core.pfnLogName = rtldrFileLogName;
245 pFileReader->Core.pfnMap = rtldrFileMap;
246 pFileReader->Core.pfnUnmap = rtldrFileUnmap;
247 pFileReader->Core.pfnDestroy = rtldrFileDestroy;
248 pFileReader->off = 0;
249 pFileReader->cMappings = 0;
250 pFileReader->pvMapping = NULL;
251 *ppReader = &pFileReader->Core;
252 return VINF_SUCCESS;
253 }
254
255 RTFileClose(pFileReader->hFile);
256 }
257 RTMemFree(pFileReader);
258 }
259 *ppReader = NULL;
260 return rc;
261}
262
263
264/**
265 * Open a binary image file.
266 *
267 * @returns iprt status code.
268 * @param pszFilename Image filename.
269 * @param fFlags Valid RTLDR_O_XXX combination.
270 * @param enmArch CPU architecture specifier for the image to be loaded.
271 * @param phLdrMod Where to store the handle to the loader module.
272 */
273RTDECL(int) RTLdrOpen(const char *pszFilename, uint32_t fFlags, RTLDRARCH enmArch, PRTLDRMOD phLdrMod)
274{
275 return RTLdrOpenEx(pszFilename, fFlags, enmArch, phLdrMod, NULL /*pErrInfo*/);
276}
277RT_EXPORT_SYMBOL(RTLdrOpen);
278
279
280/**
281 * Open a binary image file, extended version.
282 *
283 * @returns iprt status code.
284 * @param pszFilename Image filename.
285 * @param fFlags Valid RTLDR_O_XXX combination.
286 * @param enmArch CPU architecture specifier for the image to be loaded.
287 * @param phLdrMod Where to store the handle to the loader module.
288 * @param pErrInfo Where to return extended error information. Optional.
289 */
290RTDECL(int) RTLdrOpenEx(const char *pszFilename, uint32_t fFlags, RTLDRARCH enmArch, PRTLDRMOD phLdrMod, PRTERRINFO pErrInfo)
291{
292 LogFlow(("RTLdrOpenEx: pszFilename=%p:{%s} fFlags=%#x enmArch=%d phLdrMod=%p\n",
293 pszFilename, pszFilename, fFlags, enmArch, phLdrMod));
294 AssertMsgReturn(!(fFlags & ~RTLDR_O_VALID_MASK), ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
295 AssertMsgReturn(enmArch > RTLDRARCH_INVALID && enmArch < RTLDRARCH_END, ("%d\n", enmArch), VERR_INVALID_PARAMETER);
296
297 /*
298 * Create file reader & invoke worker which identifies and calls the image interpreter.
299 */
300 PRTLDRREADER pReader;
301 int rc = rtldrFileCreate(&pReader, pszFilename);
302 if (RT_SUCCESS(rc))
303 {
304 rc = RTLdrOpenWithReader(pReader, fFlags, enmArch, phLdrMod, pErrInfo);
305 if (RT_SUCCESS(rc))
306 {
307 LogFlow(("RTLdrOpenEx: return %Rrc *phLdrMod=%p\n", rc, *phLdrMod));
308 return rc;
309 }
310 pReader->pfnDestroy(pReader);
311 }
312 *phLdrMod = NIL_RTLDRMOD;
313 LogFlow(("RTLdrOpenEx: return %Rrc\n", rc));
314 return rc;
315}
316RT_EXPORT_SYMBOL(RTLdrOpenEx);
317
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use