glib/gmodule/gmodule-dl.c
changeset 18 47c74d1534e1
equal deleted inserted replaced
0:e4d67989cc36 18:47c74d1534e1
       
     1 /* GMODULE - GLIB wrapper code for dynamic module loading
       
     2  * Copyright (C) 1998, 2000 Tim Janik
       
     3  * Portions copyright (c) 2006-2009 Nokia Corporation.  All rights reserved.
       
     4  * This library is free software; you can redistribute it and/or
       
     5  * modify it under the terms of the GNU Lesser General Public
       
     6  * License as published by the Free Software Foundation; either
       
     7  * version 2 of the License, or (at your option) any later version.
       
     8  *
       
     9  * This library is distributed in the hope that it will be useful,
       
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
       
    12  * Lesser General Public License for more details.
       
    13  *
       
    14  * You should have received a copy of the GNU Lesser General Public
       
    15  * License along with this library; if not, write to the
       
    16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
       
    17  * Boston, MA 02111-1307, USA.
       
    18  */
       
    19 
       
    20 /*
       
    21  * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
       
    22  * file for a list of people on the GLib Team.  See the ChangeLog
       
    23  * files for a list of changes.  These files are distributed with
       
    24  * GLib at ftp://ftp.gtk.org/pub/gtk/. 
       
    25  */
       
    26 
       
    27 /* 
       
    28  * MT safe
       
    29  */
       
    30 #include "config.h"
       
    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 = 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   gchar *msg;
       
   145 
       
   146   fetch_dlerror (FALSE);
       
   147   p = dlsym (handle, symbol_name);
       
   148   msg = fetch_dlerror (FALSE);
       
   149   if (msg)
       
   150     g_module_set_error (msg);
       
   151   
       
   152   return p;
       
   153 }
       
   154 
       
   155 static gchar*
       
   156 _g_module_build_path (const gchar *directory,
       
   157 		      const gchar *module_name)
       
   158 {
       
   159   if (directory && *directory) {
       
   160     #ifdef __SYMBIAN32__
       
   161 	return g_strconcat (directory, "\\", module_name, "." G_MODULE_SUFFIX, NULL);
       
   162     #else
       
   163     if (strncmp (module_name, "lib", 3) == 0)
       
   164       return g_strconcat (directory, "/", module_name, NULL);
       
   165     else
       
   166       return g_strconcat (directory, "/lib", module_name, "." G_MODULE_SUFFIX, NULL);
       
   167     #endif /* __SYMBIAN32__ */
       
   168   } else if (strncmp (module_name, "lib", 3) == 0)
       
   169     return g_strdup (module_name);
       
   170   else
       
   171     #ifdef __SYMBIAN32__
       
   172     return g_strconcat (module_name, "." G_MODULE_SUFFIX, NULL);
       
   173     #else
       
   174     return g_strconcat ("lib", module_name, "." G_MODULE_SUFFIX, NULL);
       
   175     #endif /* __SYMBIAN32__ */
       
   176 }