VirtualBox

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

Last change on this file since 70836 was 68859, checked in by vboxsync, 7 years ago

Additions/WDDM: Loading of DEBUG versions of VBoxOGL*.dll libraries corrected, bugref:8998

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