From f215e02bf85f68d3a6106c2a1f4f7f063f819064 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 11 Apr 2024 10:17:27 +0200 Subject: Adding upstream version 7.0.14-dfsg. Signed-off-by: Daniel Baumann --- src/VBox/Runtime/common/ldr/ldrFile.cpp | 317 ++++++++++++++++++++++++++++++++ 1 file changed, 317 insertions(+) create mode 100644 src/VBox/Runtime/common/ldr/ldrFile.cpp (limited to 'src/VBox/Runtime/common/ldr/ldrFile.cpp') diff --git a/src/VBox/Runtime/common/ldr/ldrFile.cpp b/src/VBox/Runtime/common/ldr/ldrFile.cpp new file mode 100644 index 00000000..ea570524 --- /dev/null +++ b/src/VBox/Runtime/common/ldr/ldrFile.cpp @@ -0,0 +1,317 @@ +/* $Id: ldrFile.cpp $ */ +/** @file + * IPRT - Binary Image Loader, The File Oriented Parts. + */ + +/* + * Copyright (C) 2006-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#define LOG_GROUP RTLOGGROUP_LDR +#include +#include "internal/iprt.h" + +#include +#include +#include +#include +#include +#include +#include +#include "internal/ldr.h" + + +/********************************************************************************************************************************* +* Structures and Typedefs * +*********************************************************************************************************************************/ +/** + * File Reader instance. + * This provides raw image bits from a file. + */ +typedef struct RTLDRREADERFILE +{ + /** The core. */ + RTLDRREADER Core; + /** The file. */ + RTFILE hFile; + /** The file size. */ + uint64_t cbFile; + /** The current offset. */ + RTFOFF off; + /** Number of users or the mapping. */ + RTUINT cMappings; + /** Pointer to the in memory mapping. */ + void *pvMapping; + /** The filename (variable size). */ + char szFilename[1]; +} RTLDRREADERFILE, *PRTLDRREADERFILE; + + +/** @copydoc RTLDRREADER::pfnRead */ +static DECLCALLBACK(int) rtldrFileRead(PRTLDRREADER pReader, void *pvBuf, size_t cb, RTFOFF off) +{ + PRTLDRREADERFILE pFileReader = (PRTLDRREADERFILE)pReader; + + /* + * Seek. + */ + if (pFileReader->off != off) + { + int rc = RTFileSeek(pFileReader->hFile, off, RTFILE_SEEK_BEGIN, NULL); + if (RT_FAILURE(rc)) + { + pFileReader->off = -1; + return rc; + } + pFileReader->off = off; + } + + /* + * Read. + */ + int rc = RTFileRead(pFileReader->hFile, pvBuf, cb, NULL); + if (RT_SUCCESS(rc)) + pFileReader->off += cb; + else + pFileReader->off = -1; + return rc; +} + + +/** @copydoc RTLDRREADER::pfnTell */ +static DECLCALLBACK(RTFOFF) rtldrFileTell(PRTLDRREADER pReader) +{ + PRTLDRREADERFILE pFileReader = (PRTLDRREADERFILE)pReader; + return pFileReader->off; +} + + +/** @copydoc RTLDRREADER::pfnSize */ +static DECLCALLBACK(uint64_t) rtldrFileSize(PRTLDRREADER pReader) +{ + PRTLDRREADERFILE pFileReader = (PRTLDRREADERFILE)pReader; + return pFileReader->cbFile; +} + + +/** @copydoc RTLDRREADER::pfnLogName */ +static DECLCALLBACK(const char *) rtldrFileLogName(PRTLDRREADER pReader) +{ + PRTLDRREADERFILE pFileReader = (PRTLDRREADERFILE)pReader; + return pFileReader->szFilename; +} + + +/** @copydoc RTLDRREADER::pfnMap */ +static DECLCALLBACK(int) rtldrFileMap(PRTLDRREADER pReader, const void **ppvBits) +{ + PRTLDRREADERFILE pFileReader = (PRTLDRREADERFILE)pReader; + + /* + * Already mapped? + */ + if (pFileReader->pvMapping) + { + pFileReader->cMappings++; + *ppvBits = pFileReader->pvMapping; + return VINF_SUCCESS; + } + + /* + * Allocate memory. + */ + size_t cb = (size_t)pFileReader->cbFile; + if ((uint64_t)cb != pFileReader->cbFile) + return VERR_IMAGE_TOO_BIG; + pFileReader->pvMapping = RTMemAlloc(cb); + if (!pFileReader->pvMapping) + return VERR_NO_MEMORY; + int rc = rtldrFileRead(pReader, pFileReader->pvMapping, cb, 0); + if (RT_SUCCESS(rc)) + { + pFileReader->cMappings = 1; + *ppvBits = pFileReader->pvMapping; + } + else + { + RTMemFree(pFileReader->pvMapping); + pFileReader->pvMapping = NULL; + } + + return rc; +} + + +/** @copydoc RTLDRREADER::pfnUnmap */ +static DECLCALLBACK(int) rtldrFileUnmap(PRTLDRREADER pReader, const void *pvBits) +{ + PRTLDRREADERFILE pFileReader = (PRTLDRREADERFILE)pReader; + AssertReturn(pFileReader->cMappings > 0, VERR_INVALID_PARAMETER); + + if (!--pFileReader->cMappings) + { + RTMemFree(pFileReader->pvMapping); + pFileReader->pvMapping = NULL; + } + + NOREF(pvBits); + return VINF_SUCCESS; +} + + +/** @copydoc RTLDRREADER::pfnDestroy */ +static DECLCALLBACK(int) rtldrFileDestroy(PRTLDRREADER pReader) +{ + int rc = VINF_SUCCESS; + PRTLDRREADERFILE pFileReader = (PRTLDRREADERFILE)pReader; + + Assert(!pFileReader->cMappings); + + if (pFileReader->hFile != NIL_RTFILE) + { + rc = RTFileClose(pFileReader->hFile); + AssertRC(rc); + pFileReader->hFile = NIL_RTFILE; + } + + if (pFileReader->pvMapping) + { + RTMemFree(pFileReader->pvMapping); + pFileReader->pvMapping = NULL; + } + + RTMemFree(pFileReader); + return rc; +} + + +/** + * Opens a loader file reader. + * + * @returns iprt status code. + * @param ppReader Where to store the reader instance on success. + * @param pszFilename The file to open. + */ +static int rtldrFileCreate(PRTLDRREADER *ppReader, const char *pszFilename) +{ + size_t cchFilename = strlen(pszFilename); + int rc = VERR_NO_MEMORY; + PRTLDRREADERFILE pFileReader = (PRTLDRREADERFILE)RTMemAlloc(sizeof(*pFileReader) + cchFilename); + if (pFileReader) + { + memcpy(pFileReader->szFilename, pszFilename, cchFilename + 1); + rc = RTFileOpen(&pFileReader->hFile, pszFilename, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE); + if (RT_SUCCESS(rc)) + { + rc = RTFileQuerySize(pFileReader->hFile, &pFileReader->cbFile); + if (RT_SUCCESS(rc)) + { + pFileReader->Core.uMagic = RTLDRREADER_MAGIC; + pFileReader->Core.pfnRead = rtldrFileRead; + pFileReader->Core.pfnTell = rtldrFileTell; + pFileReader->Core.pfnSize = rtldrFileSize; + pFileReader->Core.pfnLogName = rtldrFileLogName; + pFileReader->Core.pfnMap = rtldrFileMap; + pFileReader->Core.pfnUnmap = rtldrFileUnmap; + pFileReader->Core.pfnDestroy = rtldrFileDestroy; + pFileReader->off = 0; + pFileReader->cMappings = 0; + pFileReader->pvMapping = NULL; + *ppReader = &pFileReader->Core; + return VINF_SUCCESS; + } + + RTFileClose(pFileReader->hFile); + } + RTMemFree(pFileReader); + } + *ppReader = NULL; + return rc; +} + + +/** + * Open a binary image file. + * + * @returns iprt status code. + * @param pszFilename Image filename. + * @param fFlags Valid RTLDR_O_XXX combination. + * @param enmArch CPU architecture specifier for the image to be loaded. + * @param phLdrMod Where to store the handle to the loader module. + */ +RTDECL(int) RTLdrOpen(const char *pszFilename, uint32_t fFlags, RTLDRARCH enmArch, PRTLDRMOD phLdrMod) +{ + return RTLdrOpenEx(pszFilename, fFlags, enmArch, phLdrMod, NULL /*pErrInfo*/); +} +RT_EXPORT_SYMBOL(RTLdrOpen); + + +/** + * Open a binary image file, extended version. + * + * @returns iprt status code. + * @param pszFilename Image filename. + * @param fFlags Valid RTLDR_O_XXX combination. + * @param enmArch CPU architecture specifier for the image to be loaded. + * @param phLdrMod Where to store the handle to the loader module. + * @param pErrInfo Where to return extended error information. Optional. + */ +RTDECL(int) RTLdrOpenEx(const char *pszFilename, uint32_t fFlags, RTLDRARCH enmArch, PRTLDRMOD phLdrMod, PRTERRINFO pErrInfo) +{ + LogFlow(("RTLdrOpenEx: pszFilename=%p:{%s} fFlags=%#x enmArch=%d phLdrMod=%p\n", + pszFilename, pszFilename, fFlags, enmArch, phLdrMod)); + AssertMsgReturn(!(fFlags & ~RTLDR_O_VALID_MASK), ("%#x\n", fFlags), VERR_INVALID_PARAMETER); + AssertMsgReturn(enmArch > RTLDRARCH_INVALID && enmArch < RTLDRARCH_END, ("%d\n", enmArch), VERR_INVALID_PARAMETER); + + /* + * Create file reader & invoke worker which identifies and calls the image interpreter. + */ + PRTLDRREADER pReader; + int rc = rtldrFileCreate(&pReader, pszFilename); + if (RT_SUCCESS(rc)) + { + rc = RTLdrOpenWithReader(pReader, fFlags, enmArch, phLdrMod, pErrInfo); + if (RT_SUCCESS(rc)) + { + LogFlow(("RTLdrOpenEx: return %Rrc *phLdrMod=%p\n", rc, *phLdrMod)); + return rc; + } + pReader->pfnDestroy(pReader); + } + *phLdrMod = NIL_RTLDRMOD; + LogFlow(("RTLdrOpenEx: return %Rrc\n", rc)); + return rc; +} +RT_EXPORT_SYMBOL(RTLdrOpenEx); + -- cgit v1.2.3