VirtualBox

source: vbox/trunk/src/VBox/GuestHost/OpenGL/util/dll.c@ 76541

Last change on this file since 76541 was 76474, checked in by vboxsync, 6 years ago

scm --fix-err-h src/ (bugref:9344)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.5 KB
Line 
1/* Copyright (c) 2001, Stanford University
2 * All rights reserved
3 *
4 * See the file LICENSE.txt for information on redistributing this software.
5 */
6
7#include "cr_mem.h"
8#include "cr_error.h"
9#include "cr_dll.h"
10#include "cr_string.h"
11#include "stdio.h"
12
13#ifndef IN_GUEST
14#include <string.h>
15#endif
16
17#if defined(IRIX) || defined(IRIX64) || defined(Linux) || defined(FreeBSD) || defined(AIX) || defined(DARWIN) || defined(SunOS) || defined(OSF1)
18# include <iprt/assert.h>
19# include <iprt/errcore.h>
20# include <iprt/log.h>
21# include <iprt/path.h>
22#include <dlfcn.h>
23#endif
24
25#ifdef WINDOWS
26# ifdef VBOX
27# include <iprt/win/shlwapi.h>
28# else
29#include <Shlwapi.h>
30# endif
31#endif
32
33#ifdef DARWIN
34
35#include <Carbon/Carbon.h>
36#include <mach-o/dyld.h>
37
38char *__frameworkErr=NULL;
39
40CFBundleRef LoadFramework( const char *frameworkName ) {
41 CFBundleRef bundle;
42 CFURLRef bundleURL;
43 char fullfile[8096];
44
45 if( frameworkName[0] != '/' ) {
46 /* load a system framework */
47 /* XXX \todo should this folder be retrieved from somewhere else? */
48 crStrcpy( fullfile, "/System/Library/Frameworks/" );
49 crStrcat( fullfile, frameworkName );
50 } else {
51 /* load any framework */
52 crStrcpy( fullfile, frameworkName );
53 }
54
55 bundleURL = CFURLCreateWithString( NULL, CFStringCreateWithCStringNoCopy(NULL, fullfile, CFStringGetSystemEncoding(), NULL), NULL );
56 if( !bundleURL ) {
57 __frameworkErr = "Could not create OpenGL Framework bundle URL";
58 return NULL;
59 }
60
61 bundle = CFBundleCreate( kCFAllocatorDefault, bundleURL );
62 CFRelease( bundleURL );
63
64 if( !bundle ) {
65 __frameworkErr = "Could not create OpenGL Framework bundle";
66 return NULL;
67 }
68
69 if( !CFBundleLoadExecutable(bundle) ) {
70 __frameworkErr = "Could not load MachO executable";
71 return NULL;
72 }
73
74 return bundle;
75}
76
77char *__bundleErr=NULL;
78
79void *LoadBundle( const char *filename ) {
80 NSObjectFileImage fileImage;
81 NSModule handle = NULL;
82 char _filename[PATH_MAX];
83
84 __bundleErr = NULL;
85
86 if( filename[0] != '/' ) {
87 /* default to a chromium bundle */
88 crStrcpy( _filename, "/cr/lib/Darwin/" );
89 crStrcat( _filename, filename );
90 } else {
91 crStrcpy( _filename, filename );
92 }
93
94 switch( NSCreateObjectFileImageFromFile(_filename, &fileImage) ) {
95 default:
96 case NSObjectFileImageFailure:
97 __bundleErr = "NSObjectFileImageFailure: Failure.";
98 break;
99
100 case NSObjectFileImageInappropriateFile:
101 __bundleErr = "NSObjectFileImageInappropriateFile: The specified file is not of a valid type.";
102 break;
103
104 case NSObjectFileImageArch:
105 __bundleErr = "NSObjectFileImageArch: The specified file is for a different CPU architecture.";
106 break;
107
108 case NSObjectFileImageFormat:
109 __bundleErr = "NSObjectFileImageFormat: The specified file does not appear to be a Mach-O file";
110 break;
111
112 case NSObjectFileImageAccess:
113 __bundleErr = "NSObjectFileImageAccess: Permission to create image denied.";
114 break;
115
116 case NSObjectFileImageSuccess:
117 handle = NSLinkModule( fileImage, _filename,
118 NSLINKMODULE_OPTION_RETURN_ON_ERROR |
119 NSLINKMODULE_OPTION_PRIVATE );
120 NSDestroyObjectFileImage( fileImage );
121 if( !handle ) {
122 NSLinkEditErrors c;
123 int n;
124 const char *name;
125 NSLinkEditError(&c, &n, &name, (const char**)&__bundleErr);
126 }
127 break;
128 }
129
130 return handle;
131}
132
133int check_extension( const char *name, const char *extension ) {
134 int nam_len = crStrlen( name );
135 int ext_len = crStrlen( extension );
136 char *pos = crStrstr( name, extension );
137 return ( pos == &(name[nam_len-ext_len]) );
138}
139
140enum {
141 CR_DLL_NONE,
142 CR_DLL_FRAMEWORK,
143 CR_DLL_DYLIB,
144 CR_DLL_BUNDLE,
145 CR_DLL_UNKNOWN
146};
147
148#define NS_ADD 0
149
150int get_dll_type( const char *name ) {
151 if( check_extension(name, ".framework") )
152 return CR_DLL_FRAMEWORK;
153 if( check_extension(name, ".bundle") )
154 return CR_DLL_BUNDLE;
155 if( check_extension(name, ".dylib") )
156 return CR_DLL_DYLIB;
157 return CR_DLL_DYLIB;
158}
159
160#endif
161
162/*
163 * Open the named shared library.
164 * If resolveGlobal is non-zero, unresolved symbols can be satisfied by
165 * any matching symbol already defined globally. Otherwise, if resolveGlobal
166 * is zero, unresolved symbols should be resolved using symbols in that
167 * object (in preference to global symbols).
168 * NOTE: this came about because we found that for libGL, we need the
169 * global-resolve option but for SPU's we need the non-global option (consider
170 * the state tracker duplicated in the array, tilesort, etc. SPUs).
171 */
172CRDLL *crDLLOpen( const char *dllname, int resolveGlobal )
173{
174 CRDLL *dll;
175 char *dll_err;
176#if defined(WINDOWS)
177 WCHAR szwPath[MAX_PATH];
178 UINT cwcPath = 0;
179
180 (void) resolveGlobal;
181
182# ifndef CR_NO_GL_SYSTEM_PATH
183 if (PathIsRelative(dllname))
184 {
185 size_t cName = strlen(dllname) + 1;
186# ifdef IN_GUEST
187 cwcPath = GetSystemDirectoryW(szwPath, RT_ELEMENTS(szwPath));
188 if (!cwcPath || cwcPath >= MAX_PATH)
189 {
190 DWORD winEr = GetLastError();
191 crError("GetSystemDirectoryW failed err %d", winEr);
192 SetLastError(winEr);
193 return NULL;
194 }
195# else
196 WCHAR * pszwSlashFile;
197 cwcPath = GetModuleFileNameW(NULL, szwPath, RT_ELEMENTS(szwPath));
198 if (!cwcPath || cwcPath >= MAX_PATH)
199 {
200 DWORD winEr = GetLastError();
201 crError("GetModuleFileNameW failed err %d", winEr);
202 SetLastError(winEr);
203 return NULL;
204 }
205
206 pszwSlashFile = wcsrchr(szwPath, L'\\');
207 if (!pszwSlashFile)
208 {
209 crError("failed to match file name");
210 SetLastError(ERROR_PATH_NOT_FOUND);
211 return NULL;
212 }
213
214 cwcPath = pszwSlashFile - szwPath;
215# endif
216
217 if (cwcPath + 1 + cName > MAX_PATH)
218 {
219 crError("invalid path specified");
220 SetLastError(ERROR_FILENAME_EXCED_RANGE);
221 return NULL;
222 }
223 szwPath[cwcPath] = '\\';
224 ++cwcPath;
225 }
226# endif /* CR_NO_GL_SYSTEM_PATH */
227 if (!MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, dllname, -1, &szwPath[cwcPath], MAX_PATH - cwcPath))
228 {
229 DWORD winEr = GetLastError();
230 crError("MultiByteToWideChar failed err %d", winEr);
231 SetLastError(winEr);
232 return NULL;
233 }
234#endif
235
236 dll = (CRDLL *) crAlloc( sizeof( CRDLL ) );
237 dll->name = crStrdup( dllname );
238
239#if defined(WINDOWS)
240 dll->hinstLib = LoadLibraryW( szwPath );
241 if (!dll->hinstLib)
242 {
243 crError("failed to load dll %s", dllname);
244 }
245 dll_err = NULL;
246#elif defined(DARWIN)
247 /* XXX \todo Get better error handling in here */
248 dll->type = get_dll_type( dllname );
249 dll_err = NULL;
250
251 switch( dll->type ) {
252 case CR_DLL_FRAMEWORK:
253 dll->hinstLib = LoadFramework( dllname );
254 dll_err = __frameworkErr;
255 break;
256
257 case CR_DLL_BUNDLE:
258 dll->hinstLib = LoadBundle( dllname );
259 dll_err = __bundleErr;
260 break;
261
262 case CR_DLL_DYLIB:
263#if NS_ADD
264 dll->hinstLib = (void*)NSAddImage( dllname, NSADDIMAGE_OPTION_RETURN_ON_ERROR );
265#else
266 if( resolveGlobal )
267 dll->hinstLib = dlopen( dllname, RTLD_LAZY | RTLD_GLOBAL );
268 else
269 dll->hinstLib = dlopen( dllname, RTLD_LAZY | RTLD_LOCAL );
270 dll_err = (char*) dlerror();
271#endif
272 break;
273
274 default:
275 dll->hinstLib = NULL;
276 dll_err = "Unknown DLL type";
277 break;
278 };
279#elif defined(IRIX) || defined(IRIX64) || defined(Linux) || defined(FreeBSD) || defined(AIX) || defined(SunOS) || defined(OSF1)
280 {
281 int flags = RTLD_LAZY;
282 if (resolveGlobal)
283 flags |= RTLD_GLOBAL;
284 dll->hinstLib = dlopen( dllname, flags );
285# ifndef IN_GUEST
286 /* GCC address sanitiser breaks DT_RPATH. */
287 if (!dll->hinstLib) do {
288 char szPath[RTPATH_MAX];
289 int rc = RTPathSharedLibs(szPath, sizeof(szPath));
290 AssertLogRelMsgRCBreak(rc, ("RTPathSharedLibs() failed: %Rrc\n", rc));
291 rc = RTPathAppend(szPath, sizeof(szPath), dllname);
292 AssertLogRelMsgRCBreak(rc, ("RTPathAppend() failed: %Rrc\n", rc));
293 dll->hinstLib = dlopen( szPath, flags );
294 } while(0);
295# endif
296 dll_err = (char*) dlerror();
297 }
298#else
299#error DSO
300#endif
301
302 if (!dll->hinstLib)
303 {
304 if (dll_err)
305 {
306 crDebug( "DLL_ERROR(%s): %s", dllname, dll_err );
307 }
308 crError( "DLL Loader couldn't find/open %s", dllname );
309 crFree(dll);
310 dll = NULL;
311 }
312 return dll;
313}
314
315CRDLLFunc crDLLGetNoError( CRDLL *dll, const char *symname )
316{
317#if defined(WINDOWS)
318 return (CRDLLFunc) GetProcAddress( dll->hinstLib, symname );
319#elif defined(DARWIN)
320 NSSymbol nssym;
321
322 if( dll->type == CR_DLL_FRAMEWORK )
323 return (CRDLLFunc) CFBundleGetFunctionPointerForName( (CFBundleRef) dll->hinstLib, CFStringCreateWithCStringNoCopy(NULL, symname, CFStringGetSystemEncoding(), NULL) );
324
325 if( dll->type == CR_DLL_DYLIB )
326#if NS_ADD
327 nssym = NSLookupSymbolInImage( dll->hinstLib, symname, NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR );
328#else
329 return (CRDLLFunc) dlsym( dll->hinstLib, symname );
330#endif
331 else
332 nssym = NSLookupSymbolInModule( dll->hinstLib, symname );
333
334 if( !nssym ) {
335 char name[PATH_MAX];
336 crStrcpy( name, "_" );
337 crStrcat( name, symname );
338
339 if( dll->type == CR_DLL_DYLIB )
340 nssym = NSLookupSymbolInImage( dll->hinstLib, name, NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR );
341 else
342 nssym = NSLookupSymbolInModule( dll->hinstLib, name );
343 }
344
345 return (CRDLLFunc) NSAddressOfSymbol( nssym );
346
347#elif defined(IRIX) || defined(IRIX64) || defined(Linux) || defined(FreeBSD) || defined(AIX) || defined(SunOS) || defined(OSF1)
348 return (CRDLLFunc)(uintptr_t)dlsym( dll->hinstLib, symname );
349#else
350#error CR DLL ARCHITETECTURE
351#endif
352}
353
354CRDLLFunc crDLLGet( CRDLL *dll, const char *symname )
355{
356 CRDLLFunc data = crDLLGetNoError( dll, symname );
357 if (!data)
358 {
359 /* Are you sure there isn't some C++ mangling messing you up? */
360 crWarning( "Couldn't get symbol \"%s\" in \"%s\"", symname, dll->name );
361 }
362 return data;
363}
364
365void crDLLClose( CRDLL *dll )
366{
367 int dll_err = 0;
368
369 if (!dll) return;
370
371#if defined(WINDOWS)
372 FreeLibrary( dll->hinstLib );
373#elif defined(DARWIN)
374 switch( dll->type ) {
375 case CR_DLL_FRAMEWORK:
376 CFBundleUnloadExecutable( dll->hinstLib );
377 CFRelease(dll->hinstLib);
378 dll->hinstLib = NULL;
379 break;
380
381 case CR_DLL_DYLIB:
382#if !NS_ADD
383 dlclose( dll->hinstLib );
384#endif
385 break;
386
387 case CR_DLL_BUNDLE:
388 NSUnLinkModule( (NSModule) dll->hinstLib, 0L );
389 break;
390 }
391#elif defined(IRIX) || defined(IRIX64) || defined(Linux) || defined(FreeBSD) || defined(AIX) || defined(SunOS) || defined(OSF1)
392 /*
393 * Unloading Nvidia's libGL will crash VirtualBox later during shutdown.
394 * Therefore we will skip unloading it. It will be unloaded later anway
395 * because we are already freeing all resources and VirtualBox will terminate
396 * soon.
397 */
398#ifndef IN_GUEST
399 if (strncmp(dll->name, "libGL", 5))
400#endif
401 dll_err = dlclose( dll->hinstLib );
402#else
403#error DSO
404#endif
405
406 if (dll_err)
407 crWarning("Error closing DLL %s\n",dll->name);
408
409 crFree( dll->name );
410 crFree( dll );
411}
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