gmodule-dl.c revision a6149403deed931b8c78b26aeb0e9c952cf3ef93
1/* GMODULE - GLIB wrapper code for dynamic module loading
2 * Copyright (C) 1998 Tim Janik
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library 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 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library 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#include <dlfcn.h>
20
21/* Perl includes <nlist.h> and <link.h> instead of <dlfcn.h> on some systmes? */
22
23
24/* dlerror() is not implemented on all systems
25 */
26#ifndef	G_MODULE_HAVE_DLERROR
27#  ifdef __NetBSD__
28#    define dlerror()	g_strerror (errno)
29#  else /* !__NetBSD__ */
30/* could we rely on errno's state here? */
31#    define dlerror()	"unknown dl-error"
32#  endif /* !__NetBSD__ */
33#endif	/* G_MODULE_HAVE_DLERROR */
34
35/* some flags are missing on some systems, so we provide
36 * harmless defaults.
37 * The Perl sources say, RTLD_LAZY needs to be defined as (1),
38 * at least for Solaris 1.
39 *
40 * Mandatory:
41 * RTLD_LAZY   - resolve undefined symbols as code from the dynamic library
42 *		 is executed.
43 * RTLD_NOW    - resolve all undefined symbols before dlopen returns, and fail
44 *		 if this cannot be done.
45 * Optionally:
46 * RTLD_GLOBAL - the external symbols defined in the library will be made
47 *		 available to subsequently loaded libraries.
48 */
49#ifndef	RTLD_GLOBAL
50#define	RTLD_GLOBAL	0
51#endif	/* RTLD_GLOBAL */
52#ifndef	RTLD_LAZY
53#define	RTLD_LAZY	1
54#endif	/* RTLD_LAZY */
55#ifndef	RTLD_NOW
56#define	RTLD_NOW	0
57#endif	/* RTLD_NOW */
58
59
60/* --- functions --- */
61static gpointer
62_g_module_open (const gchar    *file_name,
63		gboolean	bind_lazy)
64{
65  gpointer handle;
66
67  handle = dlopen (file_name, RTLD_GLOBAL | (bind_lazy ? RTLD_LAZY : RTLD_NOW));
68  if (!handle)
69    g_module_set_error (dlerror ());
70
71  return handle;
72}
73
74static gpointer
75_g_module_self (void)
76{
77  gpointer handle;
78
79  /* to query symbols from the program itself, special link options
80   * are required on some systems.
81   */
82
83  handle = dlopen (NULL, RTLD_GLOBAL | RTLD_LAZY);
84  if (!handle)
85    g_module_set_error (dlerror ());
86
87  return handle;
88}
89
90static void
91_g_module_close (gpointer	  handle,
92		 gboolean	  is_unref)
93{
94  /* are there any systems out there that have dlopen()/dlclose()
95   * without a reference count implementation?
96   */
97  is_unref |= 1;
98
99  if (is_unref)
100    {
101      if (dlclose (handle) != 0)
102	g_module_set_error (dlerror ());
103    }
104}
105
106static gpointer
107_g_module_symbol (gpointer	  handle,
108		  const gchar	 *symbol_name)
109{
110  gpointer p;
111
112  p = dlsym (handle, symbol_name);
113  if (!p)
114    g_module_set_error (dlerror ());
115
116  return p;
117}
118
119static gchar*
120_g_module_build_path (const gchar *directory,
121		      const gchar *module_name)
122{
123  if (directory)
124    return g_strconcat (directory, "/lib", module_name, ".so", NULL);
125  else
126    return g_strconcat ("lib", module_name, ".so", NULL);
127}
128