VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/ldr/ldrVfsFile.cpp@ 106579

Last change on this file since 106579 was 106061, checked in by vboxsync, 3 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 10.3 KB
Line 
1/* $Id: ldrVfsFile.cpp 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 * IPRT - Binary Image Loader, The File Oriented Parts, VFS variant.
4 */
5
6/*
7 * Copyright (C) 2006-2024 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/vfs.h>
52#include <iprt/formats/mz.h>
53#include "internal/ldr.h"
54
55
56/*********************************************************************************************************************************
57* Structures and Typedefs *
58*********************************************************************************************************************************/
59/**
60 * VFS file Reader instance.
61 * This provides raw image bits from a file.
62 */
63typedef struct RTLDRREADERVFSFILE
64{
65 /** The core. */
66 RTLDRREADER Core;
67 /** The VFS file. */
68 RTVFSFILE hVfsFile;
69 /** Number of users or the mapping. */
70 RTUINT cMappings;
71 /** Pointer to the in memory mapping. */
72 void *pvMapping;
73 /** The filename (variable size). */
74 char szFilename[1];
75} RTLDRREADERVFSFILE;
76typedef RTLDRREADERVFSFILE *PRTLDRREADERVFSFILE;
77
78
79/** @copydoc RTLDRREADER::pfnRead */
80static DECLCALLBACK(int) rtldrVfsFileRead(PRTLDRREADER pReader, void *pvBuf, size_t cb, RTFOFF off)
81{
82 PRTLDRREADERVFSFILE pFileReader = (PRTLDRREADERVFSFILE)pReader;
83 return RTVfsFileReadAt(pFileReader->hVfsFile, off, pvBuf, cb, NULL);
84}
85
86
87/** @copydoc RTLDRREADER::pfnTell */
88static DECLCALLBACK(RTFOFF) rtldrVfsFileTell(PRTLDRREADER pReader)
89{
90 PRTLDRREADERVFSFILE pFileReader = (PRTLDRREADERVFSFILE)pReader;
91 return RTVfsFileTell(pFileReader->hVfsFile);
92}
93
94
95/** @copydoc RTLDRREADER::pfnSize */
96static DECLCALLBACK(uint64_t) rtldrVfsFileSize(PRTLDRREADER pReader)
97{
98 PRTLDRREADERVFSFILE pFileReader = (PRTLDRREADERVFSFILE)pReader;
99 uint64_t cbFile;
100 int rc = RTVfsFileQuerySize(pFileReader->hVfsFile, &cbFile);
101 if (RT_SUCCESS(rc))
102 return cbFile;
103 return 0;
104}
105
106
107/** @copydoc RTLDRREADER::pfnLogName */
108static DECLCALLBACK(const char *) rtldrVfsFileLogName(PRTLDRREADER pReader)
109{
110 PRTLDRREADERVFSFILE pFileReader = (PRTLDRREADERVFSFILE)pReader;
111 return pFileReader->szFilename;
112}
113
114
115/** @copydoc RTLDRREADER::pfnMap */
116static DECLCALLBACK(int) rtldrVfsFileMap(PRTLDRREADER pReader, const void **ppvBits)
117{
118 PRTLDRREADERVFSFILE pFileReader = (PRTLDRREADERVFSFILE)pReader;
119
120 /*
121 * Already mapped?
122 */
123 if (pFileReader->pvMapping)
124 {
125 pFileReader->cMappings++;
126 *ppvBits = pFileReader->pvMapping;
127 return VINF_SUCCESS;
128 }
129
130 /*
131 * Allocate memory.
132 */
133 uint64_t cbFile = rtldrVfsFileSize(pReader);
134 size_t cb = (size_t)cbFile;
135 if ((uint64_t)cb != cbFile)
136 return VERR_IMAGE_TOO_BIG;
137 pFileReader->pvMapping = RTMemAlloc(cb);
138 if (!pFileReader->pvMapping)
139 return VERR_NO_MEMORY;
140 int rc = rtldrVfsFileRead(pReader, pFileReader->pvMapping, cb, 0);
141 if (RT_SUCCESS(rc))
142 {
143 pFileReader->cMappings = 1;
144 *ppvBits = pFileReader->pvMapping;
145 }
146 else
147 {
148 RTMemFree(pFileReader->pvMapping);
149 pFileReader->pvMapping = NULL;
150 }
151
152 return rc;
153}
154
155
156/** @copydoc RTLDRREADER::pfnUnmap */
157static DECLCALLBACK(int) rtldrVfsFileUnmap(PRTLDRREADER pReader, const void *pvBits)
158{
159 PRTLDRREADERVFSFILE pFileReader = (PRTLDRREADERVFSFILE)pReader;
160 AssertReturn(pFileReader->cMappings > 0, VERR_INVALID_PARAMETER);
161
162 if (!--pFileReader->cMappings)
163 {
164 RTMemFree(pFileReader->pvMapping);
165 pFileReader->pvMapping = NULL;
166 }
167
168 NOREF(pvBits);
169 return VINF_SUCCESS;
170}
171
172
173/** @copydoc RTLDRREADER::pfnDestroy */
174static DECLCALLBACK(int) rtldrVfsFileDestroy(PRTLDRREADER pReader)
175{
176 PRTLDRREADERVFSFILE pFileReader = (PRTLDRREADERVFSFILE)pReader;
177 if (pFileReader->hVfsFile != NIL_RTVFSFILE)
178 {
179 RTVfsFileRelease(pFileReader->hVfsFile);
180 pFileReader->hVfsFile = NIL_RTVFSFILE;
181 }
182 RTMemFree(pFileReader);
183 return VINF_SUCCESS;
184}
185
186
187/**
188 * Opens a loader file reader.
189 *
190 * @returns iprt status code.
191 * @param pszFilename The file to open, can be VFS chain.
192 * @param ppReader Where to store the reader instance on success.
193 * @param poffError Where to return the offset into @a pszFilename of an VFS
194 * chain element causing trouble. Optional.
195 * @param pErrInfo Where to return extended error information. Optional.
196 */
197static int rtldrVfsFileCreate(const char *pszFilename, PRTLDRREADER *ppReader, uint32_t *poffError, PRTERRINFO pErrInfo)
198{
199 size_t cbFilename = strlen(pszFilename) + 1;
200 int rc = VERR_NO_MEMORY;
201 PRTLDRREADERVFSFILE pFileReader = (PRTLDRREADERVFSFILE)RTMemAlloc(RT_UOFFSETOF_DYN(RTLDRREADERVFSFILE, szFilename[cbFilename]));
202 if (pFileReader)
203 {
204 memcpy(pFileReader->szFilename, pszFilename, cbFilename);
205 pFileReader->szFilename[0] = '\0';
206 rc = RTVfsChainOpenFile(pszFilename, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE, &pFileReader->hVfsFile,
207 poffError, pErrInfo);
208 if (RT_SUCCESS(rc))
209 {
210 pFileReader->Core.uMagic = RTLDRREADER_MAGIC;
211 pFileReader->Core.pfnRead = rtldrVfsFileRead;
212 pFileReader->Core.pfnTell = rtldrVfsFileTell;
213 pFileReader->Core.pfnSize = rtldrVfsFileSize;
214 pFileReader->Core.pfnLogName = rtldrVfsFileLogName;
215 pFileReader->Core.pfnMap = rtldrVfsFileMap;
216 pFileReader->Core.pfnUnmap = rtldrVfsFileUnmap;
217 pFileReader->Core.pfnDestroy = rtldrVfsFileDestroy;
218 pFileReader->cMappings = 0;
219 pFileReader->pvMapping = NULL;
220 *ppReader = &pFileReader->Core;
221 return VINF_SUCCESS;
222 }
223 RTMemFree(pFileReader);
224 }
225 *ppReader = NULL;
226 return rc;
227}
228
229
230/**
231 * Open a binary image file allowing VFS chains in the filename.
232 *
233 * @returns iprt status code.
234 * @param pszFilename Image filename, VFS chain specifiers allowed.
235 * @param fFlags Valid RTLDR_O_XXX combination.
236 * @param enmArch CPU architecture specifier for the image to be loaded.
237 * @param phLdrMod Where to store the handle to the loader module.
238 * @param poffError Where to return the offset into @a pszFilename of an VFS
239 * chain element causing trouble. Optional.
240 * @param pErrInfo Where to return extended error information. Optional.
241 */
242RTDECL(int) RTLdrOpenVfsChain(const char *pszFilename, uint32_t fFlags, RTLDRARCH enmArch,
243 PRTLDRMOD phLdrMod, uint32_t *poffError, PRTERRINFO pErrInfo)
244{
245 LogFlow(("RTLdrOpenVfsChain: pszFilename=%p:{%s} fFlags=%#x enmArch=%d phLdrMod=%p\n",
246 pszFilename, pszFilename, fFlags, enmArch, phLdrMod));
247 AssertMsgReturn(!(fFlags & ~RTLDR_O_VALID_MASK), ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
248 AssertMsgReturn(enmArch > RTLDRARCH_INVALID && enmArch < RTLDRARCH_END, ("%d\n", enmArch), VERR_INVALID_PARAMETER);
249
250 /*
251 * Create file reader & invoke worker which identifies and calls the image interpreter.
252 */
253 PRTLDRREADER pReader;
254 int rc = rtldrVfsFileCreate(pszFilename, &pReader, poffError, pErrInfo);
255 if (RT_SUCCESS(rc))
256 {
257 if (poffError)
258 *poffError = 0;
259 rc = RTLdrOpenWithReader(pReader, fFlags, enmArch, phLdrMod, pErrInfo);
260 if (RT_SUCCESS(rc))
261 {
262 LogFlow(("RTLdrOpenEx: return %Rrc *phLdrMod=%p\n", rc, *phLdrMod));
263 return rc;
264 }
265 pReader->pfnDestroy(pReader);
266 }
267 *phLdrMod = NIL_RTLDRMOD;
268 LogFlow(("RTLdrOpenEx: return %Rrc\n", rc));
269 return rc;
270}
271RT_EXPORT_SYMBOL(RTLdrOpenVfsChain);
272
273
274/**
275 * Open a binary image file using kLdr allowing VFS chains in the filename.
276 *
277 * @returns iprt status code.
278 * @param pszFilename Image filename.
279 * @param fFlags Reserved, MBZ.
280 * @param enmArch CPU architecture specifier for the image to be loaded.
281 * @param phLdrMod Where to store the handle to the loaded module.
282 * @param poffError Where to return the offset into @a pszFilename of an VFS
283 * chain element causing trouble. Optional.
284 * @param pErrInfo Where to return extended error information. Optional.
285 * @remark Primarily for testing the loader.
286 */
287RTDECL(int) RTLdrOpenVfsChainkLdr(const char *pszFilename, uint32_t fFlags, RTLDRARCH enmArch,
288 PRTLDRMOD phLdrMod, uint32_t *poffError, PRTERRINFO pErrInfo)
289{
290 return RTLdrOpenVfsChain(pszFilename, fFlags, enmArch, phLdrMod, poffError, pErrInfo);
291}
292RT_EXPORT_SYMBOL(RTLdrOpenVfsChainkLdr);
293
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