VirtualBox

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

Last change on this file since 46741 was 46660, checked in by vboxsync, 12 years ago

crOpenGL: bugfix

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette