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/r3/posix/ldrNative-posix.cpp | 207 ++++++++++++++++++++++++++ 1 file changed, 207 insertions(+) create mode 100644 src/VBox/Runtime/r3/posix/ldrNative-posix.cpp (limited to 'src/VBox/Runtime/r3/posix/ldrNative-posix.cpp') diff --git a/src/VBox/Runtime/r3/posix/ldrNative-posix.cpp b/src/VBox/Runtime/r3/posix/ldrNative-posix.cpp new file mode 100644 index 00000000..9b33a0ff --- /dev/null +++ b/src/VBox/Runtime/r3/posix/ldrNative-posix.cpp @@ -0,0 +1,207 @@ +/* $Id: ldrNative-posix.cpp $ */ +/** @file + * IPRT - Binary Image Loader, POSIX native. + */ + +/* + * 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 +#include +#include +#include +#include +#include +#include +#include "internal/ldr.h" + + +/********************************************************************************************************************************* +* Global Variables * +*********************************************************************************************************************************/ +#if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS) +static const char g_szSuff[] = ".DLL"; +#elif defined(RT_OS_L4) +static const char g_szSuff[] = ".s.so"; +#elif defined(RT_OS_DARWIN) +static const char g_szSuff[] = ".dylib"; +#else +static const char g_szSuff[] = ".so"; +#endif + + +DECLHIDDEN(int) rtldrNativeLoad(const char *pszFilename, uintptr_t *phHandle, uint32_t fFlags, PRTERRINFO pErrInfo) +{ + /* + * Do we need to add an extension? + */ + if (!RTPathHasSuffix(pszFilename) && !(fFlags & RTLDRLOAD_FLAGS_NO_SUFFIX)) + { + size_t cch = strlen(pszFilename); + char *psz = (char *)alloca(cch + sizeof(g_szSuff)); + if (!psz) + return RTErrInfoSet(pErrInfo, VERR_NO_MEMORY, "alloca failed"); + memcpy(psz, pszFilename, cch); + memcpy(psz + cch, g_szSuff, sizeof(g_szSuff)); + pszFilename = psz; + } + + /* + * Attempt load. + */ + int fFlagsNative = RTLD_NOW; + if (fFlags & RTLDRLOAD_FLAGS_GLOBAL) + fFlagsNative |= RTLD_GLOBAL; + else + fFlagsNative |= RTLD_LOCAL; + void *pvMod = dlopen(pszFilename, fFlagsNative); + if (pvMod) + { + *phHandle = (uintptr_t)pvMod; + return VINF_SUCCESS; + } + + const char *pszDlError = dlerror(); + RTErrInfoSet(pErrInfo, VERR_FILE_NOT_FOUND, pszDlError); + LogRel(("rtldrNativeLoad: dlopen('%s', RTLD_NOW | RTLD_LOCAL) failed: %s\n", pszFilename, pszDlError)); + return VERR_FILE_NOT_FOUND; +} + + +DECLCALLBACK(int) rtldrNativeGetSymbol(PRTLDRMODINTERNAL pMod, const char *pszSymbol, void **ppvValue) +{ + PRTLDRMODNATIVE pModNative = (PRTLDRMODNATIVE)pMod; +#ifdef RT_OS_OS2 + /* Prefix the symbol with an underscore (assuming __cdecl/gcc-default). */ + size_t cch = strlen(pszSymbol); + char *psz = (char *)alloca(cch + 2); + psz[0] = '_'; + memcpy(psz + 1, pszSymbol, cch + 1); + pszSymbol = psz; +#endif + *ppvValue = dlsym((void *)pModNative->hNative, pszSymbol); + if (*ppvValue) + return VINF_SUCCESS; + return VERR_SYMBOL_NOT_FOUND; +} + + +DECLCALLBACK(int) rtldrNativeClose(PRTLDRMODINTERNAL pMod) +{ + PRTLDRMODNATIVE pModNative = (PRTLDRMODNATIVE)pMod; +#ifdef __SANITIZE_ADDRESS__ + /* If we are compiled with enabled address sanitizer (gcc/llvm), don't + * unload the module to prevent in the stack trace */ + pModNative->fFlags |= RTLDRLOAD_FLAGS_NO_UNLOAD; +#endif + if ( (pModNative->fFlags & RTLDRLOAD_FLAGS_NO_UNLOAD) + || !dlclose((void *)pModNative->hNative)) + { + pModNative->hNative = (uintptr_t)0; + return VINF_SUCCESS; + } + Log(("rtldrNativeFree: dlclose(%p) failed: %s\n", pModNative->hNative, dlerror())); + return VERR_GENERAL_FAILURE; +} + + +DECLHIDDEN(int) rtldrNativeLoadSystem(const char *pszFilename, const char *pszExt, uint32_t fFlags, PRTLDRMOD phLdrMod) +{ + /* + * For the present we ASSUME that we can trust dlopen to load what we want + * when not specifying a path. There seems to be very little we can do to + * restrict the places dlopen will search for library without doing + * auditing (linux) or something like that. + */ + Assert(strchr(pszFilename, '/') == NULL); + + uint32_t const fFlags2 = fFlags & ~(RTLDRLOAD_FLAGS_SO_VER_BEGIN_MASK | RTLDRLOAD_FLAGS_SO_VER_END_MASK); + + /* + * If no suffix is given and we haven't got any RTLDRLOAD_FLAGS_SO_VER_ range to work + * with, we can call RTLdrLoadEx directly. + */ + if (!pszExt) + { +#if !defined(RT_OS_DARWIN) && !defined(RT_OS_OS2) && !defined(RT_OS_WINDOWS) + if ( (fFlags & RTLDRLOAD_FLAGS_SO_VER_BEGIN_MASK) >> RTLDRLOAD_FLAGS_SO_VER_BEGIN_SHIFT + == (fFlags & RTLDRLOAD_FLAGS_SO_VER_END_MASK) >> RTLDRLOAD_FLAGS_SO_VER_END_SHIFT) +#endif + return RTLdrLoadEx(pszFilename, phLdrMod, fFlags2, NULL); + pszExt = ""; + } + + /* + * Combine filename and suffix and then do the loading. + */ + size_t const cchFilename = strlen(pszFilename); + size_t const cchSuffix = strlen(pszExt); + char *pszTmp = (char *)alloca(cchFilename + cchSuffix + 16 + 1); + memcpy(pszTmp, pszFilename, cchFilename); + memcpy(&pszTmp[cchFilename], pszExt, cchSuffix); + pszTmp[cchFilename + cchSuffix] = '\0'; + + int rc = RTLdrLoadEx(pszTmp, phLdrMod, fFlags2, NULL); + +#if !defined(RT_OS_DARWIN) && !defined(RT_OS_OS2) && !defined(RT_OS_WINDOWS) + /* + * If no version was given after the .so and do .so.MAJOR search according + * to the range in the fFlags. + */ + if (RT_FAILURE(rc) && !(fFlags & RTLDRLOAD_FLAGS_NO_SUFFIX)) + { + const char *pszActualSuff = RTPathSuffix(pszTmp); + if (pszActualSuff && strcmp(pszActualSuff, ".so") == 0) + { + int32_t const iBegin = (fFlags & RTLDRLOAD_FLAGS_SO_VER_BEGIN_MASK) >> RTLDRLOAD_FLAGS_SO_VER_BEGIN_SHIFT; + int32_t const iEnd = (fFlags & RTLDRLOAD_FLAGS_SO_VER_END_MASK) >> RTLDRLOAD_FLAGS_SO_VER_END_SHIFT; + int32_t const iIncr = iBegin <= iEnd ? 1 : -1; + for (int32_t iMajorVer = iBegin; iMajorVer != iEnd; iMajorVer += iIncr) + { + RTStrPrintf(&pszTmp[cchFilename + cchSuffix], 16 + 1, ".%d", iMajorVer); + rc = RTLdrLoadEx(pszTmp, phLdrMod, fFlags2, NULL); + if (RT_SUCCESS(rc)) + break; + } + } + } +#endif + + return rc; +} + -- cgit v1.2.3