glib/libgmodule/src/gmodule-dl.c
branchRCL_3
changeset 57 2efc27d87e1c
parent 0 e4d67989cc36
equal deleted inserted replaced
56:acd3cd4aaceb 57:2efc27d87e1c
       
     1 /* GMODULE - GLIB wrapper code for dynamic module loading
       
     2  * Copyright (C) 1998, 2000 Tim Janik
       
     3  * Portions copyright (c) 2006 Nokia Corporation.  All rights reserved.
       
     4  *
       
     5  * This library is free software; you can redistribute it and/or
       
     6  * modify it under the terms of the GNU Lesser General Public
       
     7  * License as published by the Free Software Foundation; either
       
     8  * version 2 of the License, or (at your option) any later version.
       
     9  *
       
    10  * This library is distributed in the hope that it will be useful,
       
    11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
       
    13  * Lesser General Public License for more details.
       
    14  *
       
    15  * You should have received a copy of the GNU Lesser General Public
       
    16  * License along with this library; if not, write to the
       
    17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
       
    18  * Boston, MA 02111-1307, USA.
       
    19  */
       
    20 
       
    21 /*
       
    22  * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
       
    23  * file for a list of people on the GLib Team.  See the ChangeLog
       
    24  * files for a list of changes.  These files are distributed with
       
    25  * GLib at ftp://ftp.gtk.org/pub/gtk/. 
       
    26  */
       
    27 
       
    28 /* 
       
    29  * MT safe
       
    30  */
       
    31 
       
    32 #include <dlfcn.h>
       
    33 
       
    34 /* Perl includes <nlist.h> and <link.h> instead of <dlfcn.h> on some systmes? */
       
    35 
       
    36 
       
    37 /* dlerror() is not implemented on all systems
       
    38  */
       
    39 #ifndef	G_MODULE_HAVE_DLERROR
       
    40 #  ifdef __NetBSD__
       
    41 #    define dlerror()	g_strerror (errno)
       
    42 #  else /* !__NetBSD__ */
       
    43 /* could we rely on errno's state here? */
       
    44 #    define dlerror()	"unknown dl-error"
       
    45 #  endif /* !__NetBSD__ */
       
    46 #endif	/* G_MODULE_HAVE_DLERROR */
       
    47 
       
    48 /* some flags are missing on some systems, so we provide
       
    49  * harmless defaults.
       
    50  * The Perl sources say, RTLD_LAZY needs to be defined as (1),
       
    51  * at least for Solaris 1.
       
    52  *
       
    53  * Mandatory:
       
    54  * RTLD_LAZY   - resolve undefined symbols as code from the dynamic library
       
    55  *		 is executed.
       
    56  * RTLD_NOW    - resolve all undefined symbols before dlopen returns, and fail
       
    57  *		 if this cannot be done.
       
    58  * Optionally:
       
    59  * RTLD_GLOBAL - the external symbols defined in the library will be made
       
    60  *		 available to subsequently loaded libraries.
       
    61  */
       
    62 #ifndef	RTLD_LAZY
       
    63 #define	RTLD_LAZY	1
       
    64 #endif	/* RTLD_LAZY */
       
    65 #ifndef	RTLD_NOW
       
    66 #define	RTLD_NOW	0
       
    67 #endif	/* RTLD_NOW */
       
    68 /* some systems (OSF1 V5.0) have broken RTLD_GLOBAL linkage */
       
    69 #ifdef G_MODULE_BROKEN_RTLD_GLOBAL
       
    70 #undef	RTLD_GLOBAL
       
    71 #endif /* G_MODULE_BROKEN_RTLD_GLOBAL */
       
    72 #ifndef	RTLD_GLOBAL
       
    73 #define	RTLD_GLOBAL	0
       
    74 #endif	/* RTLD_GLOBAL */
       
    75 
       
    76 
       
    77 /* --- functions --- */
       
    78 static gchar*
       
    79 fetch_dlerror (gboolean replace_null)
       
    80 {
       
    81   gchar *msg = FIX_CASTING(char *)dlerror ();
       
    82 
       
    83   /* make sure we always return an error message != NULL, if
       
    84    * expected to do so. */
       
    85 
       
    86   if (!msg && replace_null)
       
    87     return "unknown dl-error";
       
    88 
       
    89   return msg;
       
    90 }
       
    91 
       
    92 static gpointer
       
    93 _g_module_open (const gchar *file_name,
       
    94 		gboolean     bind_lazy,
       
    95 		gboolean     bind_local)
       
    96 {
       
    97   gpointer handle;
       
    98   
       
    99   handle = dlopen (file_name,
       
   100 	(bind_local ? 0 : RTLD_GLOBAL) | (bind_lazy ? RTLD_LAZY : RTLD_NOW));
       
   101   if (!handle)
       
   102     g_module_set_error (fetch_dlerror (TRUE));
       
   103   
       
   104   return handle;
       
   105 }
       
   106 
       
   107 static gpointer
       
   108 _g_module_self (void)
       
   109 {
       
   110   gpointer handle;
       
   111   
       
   112   /* to query symbols from the program itself, special link options
       
   113    * are required on some systems.
       
   114    */
       
   115   
       
   116   handle = dlopen (NULL, RTLD_GLOBAL | RTLD_LAZY);
       
   117   if (!handle)
       
   118     g_module_set_error (fetch_dlerror (TRUE));
       
   119   
       
   120   return handle;
       
   121 }
       
   122 
       
   123 static void
       
   124 _g_module_close (gpointer handle,
       
   125 		 gboolean is_unref)
       
   126 {
       
   127   /* are there any systems out there that have dlopen()/dlclose()
       
   128    * without a reference count implementation?
       
   129    */
       
   130   is_unref |= 1;
       
   131   
       
   132   if (is_unref)
       
   133     {
       
   134       if (dlclose (handle) != 0)
       
   135 	g_module_set_error (fetch_dlerror (TRUE));
       
   136     }
       
   137 }
       
   138 
       
   139 static gpointer
       
   140 _g_module_symbol (gpointer     handle,
       
   141 		  const gchar *symbol_name)
       
   142 {
       
   143   gpointer p;
       
   144   
       
   145   p = dlsym (handle, symbol_name);
       
   146   if (!p)
       
   147     g_module_set_error (fetch_dlerror (FALSE));
       
   148   
       
   149   return p;
       
   150 }
       
   151 
       
   152 static gchar*
       
   153 _g_module_build_path (const gchar *directory,
       
   154 		      const gchar *module_name)
       
   155 {
       
   156   if (directory && *directory) {
       
   157     #ifdef __SYMBIAN32__
       
   158 	return g_strconcat (directory, "\\", module_name, "." G_MODULE_SUFFIX, NULL);
       
   159     #else
       
   160     if (strncmp (module_name, "lib", 3) == 0)
       
   161       return g_strconcat (directory, "/", module_name, NULL);
       
   162     else
       
   163       return g_strconcat (directory, "/lib", module_name, "." G_MODULE_SUFFIX, NULL);
       
   164     #endif /* __SYMBIAN32__ */
       
   165   } else if (strncmp (module_name, "lib", 3) == 0)
       
   166     return g_strdup (module_name);
       
   167   else
       
   168     #ifdef __SYMBIAN32__
       
   169     return g_strconcat (module_name, "." G_MODULE_SUFFIX, NULL);
       
   170     #else
       
   171     return g_strconcat ("lib", module_name, "." G_MODULE_SUFFIX, NULL);
       
   172     #endif /* __SYMBIAN32__ */
       
   173 }