summaryrefslogtreecommitdiffstats
path: root/src/VBox/GuestHost/OpenGL/util/dll.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-06 03:01:46 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-06 03:01:46 +0000
commitf8fe689a81f906d1b91bb3220acde2a4ecb14c5b (patch)
tree26484e9d7e2c67806c2d1760196ff01aaa858e8c /src/VBox/GuestHost/OpenGL/util/dll.c
parentInitial commit. (diff)
downloadvirtualbox-upstream.tar.xz
virtualbox-upstream.zip
Adding upstream version 6.0.4-dfsg.upstream/6.0.4-dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/VBox/GuestHost/OpenGL/util/dll.c')
-rw-r--r--src/VBox/GuestHost/OpenGL/util/dll.c411
1 files changed, 411 insertions, 0 deletions
diff --git a/src/VBox/GuestHost/OpenGL/util/dll.c b/src/VBox/GuestHost/OpenGL/util/dll.c
new file mode 100644
index 00000000..b76c1558
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/util/dll.c
@@ -0,0 +1,411 @@
+/* Copyright (c) 2001, Stanford University
+ * All rights reserved
+ *
+ * See the file LICENSE.txt for information on redistributing this software.
+ */
+
+#include "cr_mem.h"
+#include "cr_error.h"
+#include "cr_dll.h"
+#include "cr_string.h"
+#include "stdio.h"
+
+#ifndef IN_GUEST
+#include <string.h>
+#endif
+
+#if defined(IRIX) || defined(IRIX64) || defined(Linux) || defined(FreeBSD) || defined(AIX) || defined(DARWIN) || defined(SunOS) || defined(OSF1)
+# include <iprt/assert.h>
+# include <iprt/errcore.h>
+# include <iprt/log.h>
+# include <iprt/path.h>
+#include <dlfcn.h>
+#endif
+
+#ifdef WINDOWS
+# ifdef VBOX
+# include <iprt/win/shlwapi.h>
+# else
+#include <Shlwapi.h>
+# endif
+#endif
+
+#ifdef DARWIN
+
+#include <Carbon/Carbon.h>
+#include <mach-o/dyld.h>
+
+char *__frameworkErr=NULL;
+
+CFBundleRef LoadFramework( const char *frameworkName ) {
+ CFBundleRef bundle;
+ CFURLRef bundleURL;
+ char fullfile[8096];
+
+ if( frameworkName[0] != '/' ) {
+ /* load a system framework */
+ /* XXX \todo should this folder be retrieved from somewhere else? */
+ crStrcpy( fullfile, "/System/Library/Frameworks/" );
+ crStrcat( fullfile, frameworkName );
+ } else {
+ /* load any framework */
+ crStrcpy( fullfile, frameworkName );
+ }
+
+ bundleURL = CFURLCreateWithString( NULL, CFStringCreateWithCStringNoCopy(NULL, fullfile, CFStringGetSystemEncoding(), NULL), NULL );
+ if( !bundleURL ) {
+ __frameworkErr = "Could not create OpenGL Framework bundle URL";
+ return NULL;
+ }
+
+ bundle = CFBundleCreate( kCFAllocatorDefault, bundleURL );
+ CFRelease( bundleURL );
+
+ if( !bundle ) {
+ __frameworkErr = "Could not create OpenGL Framework bundle";
+ return NULL;
+ }
+
+ if( !CFBundleLoadExecutable(bundle) ) {
+ __frameworkErr = "Could not load MachO executable";
+ return NULL;
+ }
+
+ return bundle;
+}
+
+char *__bundleErr=NULL;
+
+void *LoadBundle( const char *filename ) {
+ NSObjectFileImage fileImage;
+ NSModule handle = NULL;
+ char _filename[PATH_MAX];
+
+ __bundleErr = NULL;
+
+ if( filename[0] != '/' ) {
+ /* default to a chromium bundle */
+ crStrcpy( _filename, "/cr/lib/Darwin/" );
+ crStrcat( _filename, filename );
+ } else {
+ crStrcpy( _filename, filename );
+ }
+
+ switch( NSCreateObjectFileImageFromFile(_filename, &fileImage) ) {
+ default:
+ case NSObjectFileImageFailure:
+ __bundleErr = "NSObjectFileImageFailure: Failure.";
+ break;
+
+ case NSObjectFileImageInappropriateFile:
+ __bundleErr = "NSObjectFileImageInappropriateFile: The specified file is not of a valid type.";
+ break;
+
+ case NSObjectFileImageArch:
+ __bundleErr = "NSObjectFileImageArch: The specified file is for a different CPU architecture.";
+ break;
+
+ case NSObjectFileImageFormat:
+ __bundleErr = "NSObjectFileImageFormat: The specified file does not appear to be a Mach-O file";
+ break;
+
+ case NSObjectFileImageAccess:
+ __bundleErr = "NSObjectFileImageAccess: Permission to create image denied.";
+ break;
+
+ case NSObjectFileImageSuccess:
+ handle = NSLinkModule( fileImage, _filename,
+ NSLINKMODULE_OPTION_RETURN_ON_ERROR |
+ NSLINKMODULE_OPTION_PRIVATE );
+ NSDestroyObjectFileImage( fileImage );
+ if( !handle ) {
+ NSLinkEditErrors c;
+ int n;
+ const char *name;
+ NSLinkEditError(&c, &n, &name, (const char**)&__bundleErr);
+ }
+ break;
+ }
+
+ return handle;
+}
+
+int check_extension( const char *name, const char *extension ) {
+ int nam_len = crStrlen( name );
+ int ext_len = crStrlen( extension );
+ char *pos = crStrstr( name, extension );
+ return ( pos == &(name[nam_len-ext_len]) );
+}
+
+enum {
+ CR_DLL_NONE,
+ CR_DLL_FRAMEWORK,
+ CR_DLL_DYLIB,
+ CR_DLL_BUNDLE,
+ CR_DLL_UNKNOWN
+};
+
+#define NS_ADD 0
+
+int get_dll_type( const char *name ) {
+ if( check_extension(name, ".framework") )
+ return CR_DLL_FRAMEWORK;
+ if( check_extension(name, ".bundle") )
+ return CR_DLL_BUNDLE;
+ if( check_extension(name, ".dylib") )
+ return CR_DLL_DYLIB;
+ return CR_DLL_DYLIB;
+}
+
+#endif
+
+/*
+ * Open the named shared library.
+ * If resolveGlobal is non-zero, unresolved symbols can be satisfied by
+ * any matching symbol already defined globally. Otherwise, if resolveGlobal
+ * is zero, unresolved symbols should be resolved using symbols in that
+ * object (in preference to global symbols).
+ * NOTE: this came about because we found that for libGL, we need the
+ * global-resolve option but for SPU's we need the non-global option (consider
+ * the state tracker duplicated in the array, tilesort, etc. SPUs).
+ */
+CRDLL *crDLLOpen( const char *dllname, int resolveGlobal )
+{
+ CRDLL *dll;
+ char *dll_err;
+#if defined(WINDOWS)
+ WCHAR szwPath[MAX_PATH];
+ UINT cwcPath = 0;
+
+ (void) resolveGlobal;
+
+# ifndef CR_NO_GL_SYSTEM_PATH
+ if (PathIsRelative(dllname))
+ {
+ size_t cName = strlen(dllname) + 1;
+# ifdef IN_GUEST
+ cwcPath = GetSystemDirectoryW(szwPath, RT_ELEMENTS(szwPath));
+ if (!cwcPath || cwcPath >= MAX_PATH)
+ {
+ DWORD winEr = GetLastError();
+ crError("GetSystemDirectoryW failed err %d", winEr);
+ SetLastError(winEr);
+ return NULL;
+ }
+# else
+ WCHAR * pszwSlashFile;
+ cwcPath = GetModuleFileNameW(NULL, szwPath, RT_ELEMENTS(szwPath));
+ if (!cwcPath || cwcPath >= MAX_PATH)
+ {
+ DWORD winEr = GetLastError();
+ crError("GetModuleFileNameW failed err %d", winEr);
+ SetLastError(winEr);
+ return NULL;
+ }
+
+ pszwSlashFile = wcsrchr(szwPath, L'\\');
+ if (!pszwSlashFile)
+ {
+ crError("failed to match file name");
+ SetLastError(ERROR_PATH_NOT_FOUND);
+ return NULL;
+ }
+
+ cwcPath = pszwSlashFile - szwPath;
+# endif
+
+ if (cwcPath + 1 + cName > MAX_PATH)
+ {
+ crError("invalid path specified");
+ SetLastError(ERROR_FILENAME_EXCED_RANGE);
+ return NULL;
+ }
+ szwPath[cwcPath] = '\\';
+ ++cwcPath;
+ }
+# endif /* CR_NO_GL_SYSTEM_PATH */
+ if (!MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, dllname, -1, &szwPath[cwcPath], MAX_PATH - cwcPath))
+ {
+ DWORD winEr = GetLastError();
+ crError("MultiByteToWideChar failed err %d", winEr);
+ SetLastError(winEr);
+ return NULL;
+ }
+#endif
+
+ dll = (CRDLL *) crAlloc( sizeof( CRDLL ) );
+ dll->name = crStrdup( dllname );
+
+#if defined(WINDOWS)
+ dll->hinstLib = LoadLibraryW( szwPath );
+ if (!dll->hinstLib)
+ {
+ crError("failed to load dll %s", dllname);
+ }
+ dll_err = NULL;
+#elif defined(DARWIN)
+ /* XXX \todo Get better error handling in here */
+ dll->type = get_dll_type( dllname );
+ dll_err = NULL;
+
+ switch( dll->type ) {
+ case CR_DLL_FRAMEWORK:
+ dll->hinstLib = LoadFramework( dllname );
+ dll_err = __frameworkErr;
+ break;
+
+ case CR_DLL_BUNDLE:
+ dll->hinstLib = LoadBundle( dllname );
+ dll_err = __bundleErr;
+ break;
+
+ case CR_DLL_DYLIB:
+#if NS_ADD
+ dll->hinstLib = (void*)NSAddImage( dllname, NSADDIMAGE_OPTION_RETURN_ON_ERROR );
+#else
+ if( resolveGlobal )
+ dll->hinstLib = dlopen( dllname, RTLD_LAZY | RTLD_GLOBAL );
+ else
+ dll->hinstLib = dlopen( dllname, RTLD_LAZY | RTLD_LOCAL );
+ dll_err = (char*) dlerror();
+#endif
+ break;
+
+ default:
+ dll->hinstLib = NULL;
+ dll_err = "Unknown DLL type";
+ break;
+ };
+#elif defined(IRIX) || defined(IRIX64) || defined(Linux) || defined(FreeBSD) || defined(AIX) || defined(SunOS) || defined(OSF1)
+ {
+ int flags = RTLD_LAZY;
+ if (resolveGlobal)
+ flags |= RTLD_GLOBAL;
+ dll->hinstLib = dlopen( dllname, flags );
+# ifndef IN_GUEST
+ /* GCC address sanitiser breaks DT_RPATH. */
+ if (!dll->hinstLib) do {
+ char szPath[RTPATH_MAX];
+ int rc = RTPathSharedLibs(szPath, sizeof(szPath));
+ AssertLogRelMsgRCBreak(rc, ("RTPathSharedLibs() failed: %Rrc\n", rc));
+ rc = RTPathAppend(szPath, sizeof(szPath), dllname);
+ AssertLogRelMsgRCBreak(rc, ("RTPathAppend() failed: %Rrc\n", rc));
+ dll->hinstLib = dlopen( szPath, flags );
+ } while(0);
+# endif
+ dll_err = (char*) dlerror();
+ }
+#else
+#error DSO
+#endif
+
+ if (!dll->hinstLib)
+ {
+ if (dll_err)
+ {
+ crDebug( "DLL_ERROR(%s): %s", dllname, dll_err );
+ }
+ crError( "DLL Loader couldn't find/open %s", dllname );
+ crFree(dll);
+ dll = NULL;
+ }
+ return dll;
+}
+
+CRDLLFunc crDLLGetNoError( CRDLL *dll, const char *symname )
+{
+#if defined(WINDOWS)
+ return (CRDLLFunc) GetProcAddress( dll->hinstLib, symname );
+#elif defined(DARWIN)
+ NSSymbol nssym;
+
+ if( dll->type == CR_DLL_FRAMEWORK )
+ return (CRDLLFunc) CFBundleGetFunctionPointerForName( (CFBundleRef) dll->hinstLib, CFStringCreateWithCStringNoCopy(NULL, symname, CFStringGetSystemEncoding(), NULL) );
+
+ if( dll->type == CR_DLL_DYLIB )
+#if NS_ADD
+ nssym = NSLookupSymbolInImage( dll->hinstLib, symname, NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR );
+#else
+ return (CRDLLFunc) dlsym( dll->hinstLib, symname );
+#endif
+ else
+ nssym = NSLookupSymbolInModule( dll->hinstLib, symname );
+
+ if( !nssym ) {
+ char name[PATH_MAX];
+ crStrcpy( name, "_" );
+ crStrcat( name, symname );
+
+ if( dll->type == CR_DLL_DYLIB )
+ nssym = NSLookupSymbolInImage( dll->hinstLib, name, NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR );
+ else
+ nssym = NSLookupSymbolInModule( dll->hinstLib, name );
+ }
+
+ return (CRDLLFunc) NSAddressOfSymbol( nssym );
+
+#elif defined(IRIX) || defined(IRIX64) || defined(Linux) || defined(FreeBSD) || defined(AIX) || defined(SunOS) || defined(OSF1)
+ return (CRDLLFunc)(uintptr_t)dlsym( dll->hinstLib, symname );
+#else
+#error CR DLL ARCHITETECTURE
+#endif
+}
+
+CRDLLFunc crDLLGet( CRDLL *dll, const char *symname )
+{
+ CRDLLFunc data = crDLLGetNoError( dll, symname );
+ if (!data)
+ {
+ /* Are you sure there isn't some C++ mangling messing you up? */
+ crWarning( "Couldn't get symbol \"%s\" in \"%s\"", symname, dll->name );
+ }
+ return data;
+}
+
+void crDLLClose( CRDLL *dll )
+{
+ int dll_err = 0;
+
+ if (!dll) return;
+
+#if defined(WINDOWS)
+ FreeLibrary( dll->hinstLib );
+#elif defined(DARWIN)
+ switch( dll->type ) {
+ case CR_DLL_FRAMEWORK:
+ CFBundleUnloadExecutable( dll->hinstLib );
+ CFRelease(dll->hinstLib);
+ dll->hinstLib = NULL;
+ break;
+
+ case CR_DLL_DYLIB:
+#if !NS_ADD
+ dlclose( dll->hinstLib );
+#endif
+ break;
+
+ case CR_DLL_BUNDLE:
+ NSUnLinkModule( (NSModule) dll->hinstLib, 0L );
+ break;
+ }
+#elif defined(IRIX) || defined(IRIX64) || defined(Linux) || defined(FreeBSD) || defined(AIX) || defined(SunOS) || defined(OSF1)
+ /*
+ * Unloading Nvidia's libGL will crash VirtualBox later during shutdown.
+ * Therefore we will skip unloading it. It will be unloaded later anway
+ * because we are already freeing all resources and VirtualBox will terminate
+ * soon.
+ */
+#ifndef IN_GUEST
+ if (strncmp(dll->name, "libGL", 5))
+#endif
+ dll_err = dlclose( dll->hinstLib );
+#else
+#error DSO
+#endif
+
+ if (dll_err)
+ crWarning("Error closing DLL %s\n",dll->name);
+
+ crFree( dll->name );
+ crFree( dll );
+}