1 /*****************************************************************************
2 * os.c : Low-level dynamic library handling
3 *****************************************************************************
4 * Copyright (C) 2001-2007 the VideoLAN team
7 * Authors: Sam Hocevar <sam@zoy.org>
8 * Ethan C. Baldridge <BaldridgeE@cadmus.com>
9 * Hans-Peter Jansen <hpj@urpla.net>
10 * Gildas Bazin <gbazin@videolan.org>
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
25 *****************************************************************************/
35 #include <stdlib.h> /* free(), strtol() */
36 #include <stdio.h> /* sprintf() */
37 #include <string.h> /* strdup() */
39 #ifdef HAVE_SYS_TYPES_H
40 # include <sys/types.h>
43 #if !defined(HAVE_DYNAMIC_PLUGINS)
44 /* no support for plugins */
45 #elif defined(HAVE_DL_DYLD)
46 # if defined(HAVE_MACH_O_DYLD_H)
47 # include <mach-o/dyld.h>
49 #elif defined(HAVE_DL_BEOS)
50 # if defined(HAVE_IMAGE_H)
53 #elif defined(HAVE_DL_WINDOWS)
55 #elif defined(HAVE_DL_DLOPEN)
56 # if defined(HAVE_DLFCN_H) /* Linux, BSD, Hurd */
59 # if defined(HAVE_SYS_DL_H)
62 #elif defined(HAVE_DL_SHL_LOAD)
63 # if defined(HAVE_DL_H)
68 /*****************************************************************************
70 *****************************************************************************/
71 #ifdef HAVE_DYNAMIC_PLUGINS
72 static void * GetSymbol ( module_handle_t, const char * );
74 #if defined(HAVE_DL_WINDOWS)
75 static char * GetWindowsError ( void );
78 /*****************************************************************************
79 * module_Call: call an entry point.
80 *****************************************************************************
81 * This function calls a symbol given its name and a module structure. The
82 * symbol MUST refer to a function returning int and taking a module_t* as
84 *****************************************************************************/
85 int module_Call( module_t * p_module )
87 static const char psz_name[] = "vlc_entry" MODULE_SUFFIX;
88 int (* pf_symbol) ( module_t * p_module );
90 /* Try to resolve the symbol */
91 pf_symbol = (int (*)(module_t *)) GetSymbol( p_module->handle, psz_name );
93 if( pf_symbol == NULL )
95 #if defined(HAVE_DL_DYLD) || defined(HAVE_DL_BEOS)
96 msg_Warn( p_module, "cannot find symbol \"%s\" in file `%s'",
97 psz_name, p_module->psz_filename );
98 #elif defined(HAVE_DL_WINDOWS)
99 char *psz_error = GetWindowsError();
100 msg_Warn( p_module, "cannot find symbol \"%s\" in file `%s' (%s)",
101 psz_name, p_module->psz_filename, psz_error );
103 #elif defined(HAVE_DL_DLOPEN)
104 msg_Warn( p_module, "cannot find symbol \"%s\" in file `%s' (%s)",
105 psz_name, p_module->psz_filename, dlerror() );
106 #elif defined(HAVE_DL_SHL_LOAD)
107 msg_Warn( p_module, "cannot find symbol \"%s\" in file `%s' (%m)",
108 psz_name, p_module->psz_filename );
110 # error "Something is wrong in modules.c"
115 /* We can now try to call the symbol */
116 if( pf_symbol( p_module ) != 0 )
118 /* With a well-written module we shouldn't have to print an
119 * additional error message here, but just make sure. */
120 msg_Err( p_module, "Failed to call symbol \"%s\" in file `%s'",
121 psz_name, p_module->psz_filename );
125 /* Everything worked fine, we can return */
129 /*****************************************************************************
130 * module_Load: loads a dynamic library
131 *****************************************************************************
132 * This function loads a dynamically linked library using a system dependant
133 * method. Will return 0 on success as well as the module handle.
134 *****************************************************************************/
135 int module_Load( vlc_object_t *p_this, const char *psz_file,
136 module_handle_t *p_handle )
138 module_handle_t handle;
140 #if defined(HAVE_DL_DYLD)
141 NSObjectFileImage image;
142 NSObjectFileImageReturnCode ret;
144 ret = NSCreateObjectFileImageFromFile( psz_file, &image );
146 if( ret != NSObjectFileImageSuccess )
148 msg_Warn( p_this, "cannot create image from `%s'", psz_file );
152 /* Open the dynamic module */
153 handle = NSLinkModule( image, psz_file,
154 NSLINKMODULE_OPTION_RETURN_ON_ERROR );
158 NSLinkEditErrors errors;
159 const char *psz_file, *psz_err;
161 NSLinkEditError( &errors, &i_errnum, &psz_file, &psz_err );
162 msg_Warn( p_this, "cannot link module `%s' (%s)", psz_file, psz_err );
163 NSDestroyObjectFileImage( image );
167 /* Destroy our image, we won't need it */
168 NSDestroyObjectFileImage( image );
170 #elif defined(HAVE_DL_BEOS)
171 handle = load_add_on( psz_file );
174 msg_Warn( p_this, "cannot load module `%s'", psz_file );
178 #elif defined(HAVE_DL_WINDOWS)
181 wchar_t psz_wfile[MAX_PATH];
182 MultiByteToWideChar( CP_ACP, 0, psz_file, -1, psz_wfile, MAX_PATH );
183 handle = LoadLibrary( psz_wfile );
186 handle = LoadLibrary( psz_file );
190 char *psz_err = GetWindowsError();
191 msg_Warn( p_this, "cannot load module `%s' (%s)", psz_file, psz_err );
196 #elif defined(HAVE_DL_DLOPEN) && defined(RTLD_NOW)
197 /* static is OK, we are called atomically */
198 handle = dlopen( psz_file, RTLD_NOW );
201 msg_Warn( p_this, "cannot load module `%s' (%s)",
202 psz_file, dlerror() );
206 #elif defined(HAVE_DL_DLOPEN)
207 # if defined(DL_LAZY)
208 handle = dlopen( psz_file, DL_LAZY );
210 handle = dlopen( psz_file, 0 );
214 msg_Warn( p_this, "cannot load module `%s' (%s)",
215 psz_file, dlerror() );
219 #elif defined(HAVE_DL_SHL_LOAD)
220 handle = shl_load( psz_file, BIND_IMMEDIATE | BIND_NONFATAL, NULL );
223 msg_Warn( p_this, "cannot load module `%s' (%m)", psz_file );
228 # error "Something is wrong in modules.c"
236 /*****************************************************************************
237 * CloseModule: unload a dynamic library
238 *****************************************************************************
239 * This function unloads a previously opened dynamically linked library
240 * using a system dependant method. No return value is taken in consideration,
241 * since some libraries sometimes refuse to close properly.
242 *****************************************************************************/
243 void module_Unload( module_handle_t handle )
245 #if defined(HAVE_DL_DYLD)
246 NSUnLinkModule( handle, FALSE );
248 #elif defined(HAVE_DL_BEOS)
249 unload_add_on( handle );
251 #elif defined(HAVE_DL_WINDOWS)
252 FreeLibrary( handle );
254 #elif defined(HAVE_DL_DLOPEN)
259 #elif defined(HAVE_DL_SHL_LOAD)
260 shl_unload( handle );
266 /*****************************************************************************
267 * GetSymbol: get a symbol from a dynamic library
268 *****************************************************************************
269 * This function queries a loaded library for a symbol specified in a
270 * string, and returns a pointer to it. We don't check for dlerror() or
271 * similar functions, since we want a non-NULL symbol anyway.
272 *****************************************************************************/
273 static void * _module_getsymbol( module_handle_t, const char * );
275 static void * GetSymbol( module_handle_t handle, const char * psz_function )
277 void * p_symbol = _module_getsymbol( handle, psz_function );
279 /* MacOS X dl library expects symbols to begin with "_". So do
280 * some other operating systems. That's really lame, but hey, what
282 if( p_symbol == NULL )
284 char psz_call[strlen( psz_function ) + 2];
287 memcpy( psz_call + 1, psz_function, sizeof (psz_call) - 1 );
288 p_symbol = _module_getsymbol( handle, psz_call );
294 static void * _module_getsymbol( module_handle_t handle,
295 const char * psz_function )
297 #if defined(HAVE_DL_DYLD)
298 NSSymbol sym = NSLookupSymbolInModule( handle, psz_function );
299 return NSAddressOfSymbol( sym );
301 #elif defined(HAVE_DL_BEOS)
303 if( B_OK == get_image_symbol( handle, psz_function,
304 B_SYMBOL_TYPE_TEXT, &p_symbol ) )
313 #elif defined(HAVE_DL_WINDOWS) && defined(UNDER_CE)
314 wchar_t psz_real[256];
315 MultiByteToWideChar( CP_ACP, 0, psz_function, -1, psz_real, 256 );
317 return (void *)GetProcAddress( handle, psz_real );
319 #elif defined(HAVE_DL_WINDOWS) && defined(WIN32)
320 return (void *)GetProcAddress( handle, (char *)psz_function );
322 #elif defined(HAVE_DL_DLOPEN)
323 return dlsym( handle, psz_function );
325 #elif defined(HAVE_DL_SHL_LOAD)
327 shl_findsym( &handle, psz_function, TYPE_UNDEFINED, &p_sym );
333 #if defined(HAVE_DL_WINDOWS)
334 static char * GetWindowsError( void )
336 #if defined(UNDER_CE)
337 wchar_t psz_tmp[MAX_PATH];
338 char * psz_buffer = malloc( MAX_PATH );
340 char * psz_tmp = malloc( MAX_PATH );
342 int i = 0, i_error = GetLastError();
344 FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
345 NULL, i_error, MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
346 (LPTSTR)psz_tmp, MAX_PATH, NULL );
348 /* Go to the end of the string */
349 while( psz_tmp[i] && psz_tmp[i] != _T('\r') && psz_tmp[i] != _T('\n') )
356 #if defined(UNDER_CE)
357 swprintf( psz_tmp + i, L" (error %i)", i_error );
358 psz_tmp[ 255 ] = L'\0';
360 snprintf( psz_tmp + i, 256 - i, " (error %i)", i_error );
361 psz_tmp[ 255 ] = '\0';
365 #if defined(UNDER_CE)
366 wcstombs( psz_buffer, psz_tmp, MAX_PATH );
372 #endif /* HAVE_DL_WINDOWS */
373 #endif /* HAVE_DYNAMIC_PLUGINS */