Imported Upstream version 2.55.0
[platform/upstream/glib.git] / gmodule / gmodule.c
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 Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 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, see <http://www.gnu.org/licenses/>.
16  */
17
18 /*
19  * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
20  * file for a list of people on the GLib Team.  See the ChangeLog
21  * files for a list of changes.  These files are distributed with
22  * GLib at ftp://ftp.gtk.org/pub/gtk/. 
23  */
24
25 /* 
26  * MT safe
27  */
28
29 #include "config.h"
30
31 #include "glib.h"
32 #include "gmodule.h"
33
34 #include <errno.h>
35 #include <string.h>
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <fcntl.h>
39 #ifdef G_OS_UNIX
40 #include <unistd.h>
41 #endif
42 #ifdef G_OS_WIN32
43 #include <io.h>         /* For open() and close() prototypes. */
44 #endif
45
46 #include "gmoduleconf.h"
47 #include "gstdio.h"
48
49 /**
50  * SECTION:modules
51  * @title: Dynamic Loading of Modules
52  * @short_description: portable method for dynamically loading 'plug-ins'
53  *
54  * These functions provide a portable way to dynamically load object files
55  * (commonly known as 'plug-ins'). The current implementation supports all
56  * systems that provide an implementation of dlopen() (e.g. Linux/Sun), as
57  * well as Windows platforms via DLLs.
58  *
59  * A program which wants to use these functions must be linked to the
60  * libraries output by the command `pkg-config --libs gmodule-2.0`.
61  *
62  * To use them you must first determine whether dynamic loading
63  * is supported on the platform by calling g_module_supported().
64  * If it is, you can open a module with g_module_open(),
65  * find the module's symbols (e.g. function names) with g_module_symbol(),
66  * and later close the module with g_module_close().
67  * g_module_name() will return the file name of a currently opened module.
68  *
69  * If any of the above functions fail, the error status can be found with
70  * g_module_error().
71  *
72  * The #GModule implementation features reference counting for opened modules,
73  * and supports hook functions within a module which are called when the
74  * module is loaded and unloaded (see #GModuleCheckInit and #GModuleUnload).
75  *
76  * If your module introduces static data to common subsystems in the running
77  * program, e.g. through calling
78  * `g_quark_from_static_string ("my-module-stuff")`,
79  * it must ensure that it is never unloaded, by calling g_module_make_resident().
80  *
81  * Example: Calling a function defined in a GModule
82  * |[<!-- language="C" --> 
83  * // the function signature for 'say_hello'
84  * typedef void (* SayHelloFunc) (const char *message);
85  *
86  * gboolean
87  * just_say_hello (const char *filename, GError **error)
88  * {
89  *   SayHelloFunc  say_hello;
90  *   GModule      *module;
91  *
92  *   module = g_module_open (filename, G_MODULE_BIND_LAZY);
93  *   if (!module)
94  *     {
95  *       g_set_error (error, FOO_ERROR, FOO_ERROR_BLAH,
96  *                    "%s", g_module_error ());
97  *       return FALSE;
98  *     }
99  *
100  *   if (!g_module_symbol (module, "say_hello", (gpointer *)&say_hello))
101  *     {
102  *       g_set_error (error, SAY_ERROR, SAY_ERROR_OPEN,
103  *                    "%s: %s", filename, g_module_error ());
104  *       if (!g_module_close (module))
105  *         g_warning ("%s: %s", filename, g_module_error ());
106  *       return FALSE;
107  *     }
108  *
109  *   if (say_hello == NULL)
110  *     {
111  *       g_set_error (error, SAY_ERROR, SAY_ERROR_OPEN,
112  *                    "symbol say_hello is NULL");
113  *       if (!g_module_close (module))
114  *         g_warning ("%s: %s", filename, g_module_error ());
115  *       return FALSE;
116  *     }
117  *
118  *   // call our function in the module
119  *   say_hello ("Hello world!");
120  *
121  *   if (!g_module_close (module))
122  *     g_warning ("%s: %s", filename, g_module_error ());
123  *   return TRUE;
124  *  }
125  * ]|
126  */
127
128 /**
129  * GModule:
130  *
131  * The #GModule struct is an opaque data structure to represent a
132  * [dynamically-loaded module][glib-Dynamic-Loading-of-Modules].
133  * It should only be accessed via the following functions.
134  */
135
136 /**
137  * GModuleCheckInit:
138  * @module: the #GModule corresponding to the module which has just been loaded
139  *
140  * Specifies the type of the module initialization function.
141  * If a module contains a function named g_module_check_init() it is called
142  * automatically when the module is loaded. It is passed the #GModule structure
143  * and should return %NULL on success or a string describing the initialization
144  * error.
145  *
146  * Returns: %NULL on success, or a string describing the initialization error
147  */
148
149 /**
150  * GModuleUnload:
151  * @module: the #GModule about to be unloaded
152  *
153  * Specifies the type of the module function called when it is unloaded.
154  * If a module contains a function named g_module_unload() it is called
155  * automatically when the module is unloaded.
156  * It is passed the #GModule structure.
157  */
158
159 /**
160  * G_MODULE_SUFFIX:
161  *
162  * Expands to the proper shared library suffix for the current platform
163  * without the leading dot. For most Unices and Linux this is "so", and
164  * for Windows this is "dll".
165  */
166
167 /**
168  * G_MODULE_EXPORT:
169  *
170  * Used to declare functions exported by libraries or modules.
171  *
172  * When compiling for Windows, it marks the symbol as `dllexport`.
173  *
174  * When compiling for Linux and Unices, it marks the symbol as having `default`
175  * visibility. This is no-op unless the code is being compiled with a
176  * non-default
177  * [visibility flag](https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#index-fvisibility-1260)
178  * such as `hidden`.
179  */
180
181 /**
182  * G_MODULE_IMPORT:
183  *
184  * Used to declare functions imported from modules.
185  */
186
187 /* We maintain a list of modules, so we can reference count them.
188  * That's needed because some platforms don't support references counts on
189  * modules. Also, the module for the program itself is kept seperately for
190  * faster access and because it has special semantics.
191  */
192
193
194 /* --- structures --- */
195 struct _GModule
196 {
197   gchar *file_name;
198   gpointer handle;
199   guint ref_count : 31;
200   guint is_resident : 1;
201   GModuleUnload unload;
202   GModule *next;
203 };
204
205
206 /* --- prototypes --- */
207 static gpointer         _g_module_open          (const gchar    *file_name,
208                                                  gboolean        bind_lazy,
209                                                  gboolean        bind_local);
210 static void             _g_module_close         (gpointer        handle,
211                                                  gboolean        is_unref);
212 static gpointer         _g_module_self          (void);
213 static gpointer         _g_module_symbol        (gpointer        handle,
214                                                  const gchar    *symbol_name);
215 static gchar*           _g_module_build_path    (const gchar    *directory,
216                                                  const gchar    *module_name);
217 static inline void      g_module_set_error      (const gchar    *error);
218 static inline GModule*  g_module_find_by_handle (gpointer        handle);
219 static inline GModule*  g_module_find_by_name   (const gchar    *name);
220
221
222 /* --- variables --- */
223 static GModule       *modules = NULL;
224 static GModule       *main_module = NULL;
225 static GPrivate       module_error_private = G_PRIVATE_INIT (g_free);
226 static gboolean       module_debug_initialized = FALSE;
227 static guint          module_debug_flags = 0;
228
229
230 /* --- inline functions --- */
231 static inline GModule*
232 g_module_find_by_handle (gpointer handle)
233 {
234   GModule *module;
235   GModule *retval = NULL;
236   
237   if (main_module && main_module->handle == handle)
238     retval = main_module;
239   else
240     for (module = modules; module; module = module->next)
241       if (handle == module->handle)
242         {
243           retval = module;
244           break;
245         }
246
247   return retval;
248 }
249
250 static inline GModule*
251 g_module_find_by_name (const gchar *name)
252 {
253   GModule *module;
254   GModule *retval = NULL;
255   
256   for (module = modules; module; module = module->next)
257     if (strcmp (name, module->file_name) == 0)
258         {
259           retval = module;
260           break;
261         }
262
263   return retval;
264 }
265
266 static inline void
267 g_module_set_error_unduped (gchar *error)
268 {
269   g_private_replace (&module_error_private, error);
270   errno = 0;
271 }
272
273 static inline void
274 g_module_set_error (const gchar *error)
275 {
276   g_module_set_error_unduped (g_strdup (error));
277 }
278
279
280 /* --- include platform specifc code --- */
281 #define SUPPORT_OR_RETURN(rv)   { g_module_set_error (NULL); }
282 #if     (G_MODULE_IMPL == G_MODULE_IMPL_DL)
283 #include "gmodule-dl.c"
284 #elif   (G_MODULE_IMPL == G_MODULE_IMPL_WIN32)
285 #include "gmodule-win32.c"
286 #elif   (G_MODULE_IMPL == G_MODULE_IMPL_DYLD)
287 #include "gmodule-dyld.c"
288 #elif   (G_MODULE_IMPL == G_MODULE_IMPL_AR)
289 #include "gmodule-ar.c"
290 #else
291 #undef  SUPPORT_OR_RETURN
292 #define SUPPORT_OR_RETURN(rv)   { g_module_set_error ("dynamic modules are " \
293                                               "not supported by this system"); return rv; }
294 static gpointer
295 _g_module_open (const gchar     *file_name,
296                 gboolean         bind_lazy,
297                 gboolean         bind_local)
298 {
299   return NULL;
300 }
301 static void
302 _g_module_close (gpointer        handle,
303                  gboolean        is_unref)
304 {
305 }
306 static gpointer
307 _g_module_self (void)
308 {
309   return NULL;
310 }
311 static gpointer
312 _g_module_symbol (gpointer       handle,
313                   const gchar   *symbol_name)
314 {
315   return NULL;
316 }
317 static gchar*
318 _g_module_build_path (const gchar *directory,
319                       const gchar *module_name)
320 {
321   return NULL;
322 }
323 #endif  /* no implementation */
324
325 /* --- functions --- */
326
327 /**
328  * g_module_supported:
329  *
330  * Checks if modules are supported on the current platform.
331  *
332  * Returns: %TRUE if modules are supported
333  */
334 gboolean
335 g_module_supported (void)
336 {
337   SUPPORT_OR_RETURN (FALSE);
338   
339   return TRUE;
340 }
341
342 static gchar*
343 parse_libtool_archive (const gchar* libtool_name)
344 {
345   const guint TOKEN_DLNAME = G_TOKEN_LAST + 1;
346   const guint TOKEN_INSTALLED = G_TOKEN_LAST + 2;
347   const guint TOKEN_LIBDIR = G_TOKEN_LAST + 3;
348   gchar *lt_dlname = NULL;
349   gboolean lt_installed = TRUE;
350   gchar *lt_libdir = NULL;
351   gchar *name;
352   GTokenType token;
353   GScanner *scanner;
354   
355   int fd = g_open (libtool_name, O_RDONLY, 0);
356   if (fd < 0)
357     {
358       gchar *display_libtool_name = g_filename_display_name (libtool_name);
359       g_module_set_error_unduped (g_strdup_printf ("failed to open libtool archive \"%s\"", display_libtool_name));
360       g_free (display_libtool_name);
361       return NULL;
362     }
363   /* search libtool's dlname specification  */
364   scanner = g_scanner_new (NULL);
365   g_scanner_input_file (scanner, fd);
366   scanner->config->symbol_2_token = TRUE;
367   g_scanner_scope_add_symbol (scanner, 0, "dlname", 
368                               GUINT_TO_POINTER (TOKEN_DLNAME));
369   g_scanner_scope_add_symbol (scanner, 0, "installed", 
370                               GUINT_TO_POINTER (TOKEN_INSTALLED));
371   g_scanner_scope_add_symbol (scanner, 0, "libdir", 
372                               GUINT_TO_POINTER (TOKEN_LIBDIR));
373   while (!g_scanner_eof (scanner))
374     {
375       token = g_scanner_get_next_token (scanner);
376       if (token == TOKEN_DLNAME || token == TOKEN_INSTALLED || 
377           token == TOKEN_LIBDIR)
378         {
379           if (g_scanner_get_next_token (scanner) != '=' ||
380               g_scanner_get_next_token (scanner) != 
381               (token == TOKEN_INSTALLED ? 
382                G_TOKEN_IDENTIFIER : G_TOKEN_STRING))
383             {
384               gchar *display_libtool_name = g_filename_display_name (libtool_name);
385               g_module_set_error_unduped (g_strdup_printf ("unable to parse libtool archive \"%s\"", display_libtool_name));
386               g_free (display_libtool_name);
387
388               g_free (lt_dlname);
389               g_free (lt_libdir);
390               g_scanner_destroy (scanner);
391               close (fd);
392
393               return NULL;
394             }
395           else
396             {
397               if (token == TOKEN_DLNAME)
398                 {
399                   g_free (lt_dlname);
400                   lt_dlname = g_strdup (scanner->value.v_string);
401                 }
402               else if (token == TOKEN_INSTALLED)
403                 lt_installed = 
404                   strcmp (scanner->value.v_identifier, "yes") == 0;
405               else /* token == TOKEN_LIBDIR */
406                 {
407                   g_free (lt_libdir);
408                   lt_libdir = g_strdup (scanner->value.v_string);
409                 }
410             }
411         }      
412     }
413
414   if (!lt_installed)
415     {
416       gchar *dir = g_path_get_dirname (libtool_name);
417       g_free (lt_libdir);
418       lt_libdir = g_strconcat (dir, G_DIR_SEPARATOR_S ".libs", NULL);
419       g_free (dir);
420     }
421
422   name = g_strconcat (lt_libdir, G_DIR_SEPARATOR_S, lt_dlname, NULL);
423   
424   g_free (lt_dlname);
425   g_free (lt_libdir);
426   g_scanner_destroy (scanner);
427   close (fd);
428
429   return name;
430 }
431
432 static inline gboolean
433 str_check_suffix (const gchar* string,
434                   const gchar* suffix)
435 {
436   gsize string_len = strlen (string);    
437   gsize suffix_len = strlen (suffix);    
438
439   return string_len >= suffix_len && 
440     strcmp (string + string_len - suffix_len, suffix) == 0;
441 }
442
443 enum
444 {
445   G_MODULE_DEBUG_RESIDENT_MODULES = 1 << 0,
446   G_MODULE_DEBUG_BIND_NOW_MODULES = 1 << 1
447 };
448
449 static void
450 _g_module_debug_init (void)
451 {
452   const GDebugKey keys[] = {
453     { "resident-modules", G_MODULE_DEBUG_RESIDENT_MODULES },
454     { "bind-now-modules", G_MODULE_DEBUG_BIND_NOW_MODULES }
455   };
456   const gchar *env;
457
458   env = g_getenv ("G_DEBUG");
459
460   module_debug_flags =
461     !env ? 0 : g_parse_debug_string (env, keys, G_N_ELEMENTS (keys));
462
463   module_debug_initialized = TRUE;
464 }
465
466 static GRecMutex g_module_global_lock;
467
468 /**
469  * g_module_open:
470  * @file_name: (nullable): the name of the file containing the module, or %NULL
471  *     to obtain a #GModule representing the main program itself
472  * @flags: the flags used for opening the module. This can be the
473  *     logical OR of any of the #GModuleFlags
474  *
475  * Opens a module. If the module has already been opened,
476  * its reference count is incremented.
477  *
478  * First of all g_module_open() tries to open @file_name as a module.
479  * If that fails and @file_name has the ".la"-suffix (and is a libtool
480  * archive) it tries to open the corresponding module. If that fails
481  * and it doesn't have the proper module suffix for the platform
482  * (#G_MODULE_SUFFIX), this suffix will be appended and the corresponding
483  * module will be opended. If that fails and @file_name doesn't have the
484  * ".la"-suffix, this suffix is appended and g_module_open() tries to open
485  * the corresponding module. If eventually that fails as well, %NULL is
486  * returned.
487  *
488  * Returns: a #GModule on success, or %NULL on failure
489  */
490 GModule*
491 g_module_open (const gchar    *file_name,
492                GModuleFlags    flags)
493 {
494   GModule *module;
495   gpointer handle = NULL;
496   gchar *name = NULL;
497   
498   SUPPORT_OR_RETURN (NULL);
499   
500   g_rec_mutex_lock (&g_module_global_lock);
501
502   if (G_UNLIKELY (!module_debug_initialized))
503     _g_module_debug_init ();
504
505   if (module_debug_flags & G_MODULE_DEBUG_BIND_NOW_MODULES)
506     flags &= ~G_MODULE_BIND_LAZY;
507
508   if (!file_name)
509     {      
510       if (!main_module)
511         {
512           handle = _g_module_self ();
513 /* On Android 64 bit, RTLD_DEFAULT is (void *)0x0
514  * so it always fails to create main_module if file_name is NULL */
515 #if !defined(__BIONIC__) || !defined(__LP64__)
516           if (handle)
517 #endif
518             {
519               main_module = g_new (GModule, 1);
520               main_module->file_name = NULL;
521               main_module->handle = handle;
522               main_module->ref_count = 1;
523               main_module->is_resident = TRUE;
524               main_module->unload = NULL;
525               main_module->next = NULL;
526             }
527         }
528       else
529         main_module->ref_count++;
530
531       g_rec_mutex_unlock (&g_module_global_lock);
532       return main_module;
533     }
534   
535   /* we first search the module list by name */
536   module = g_module_find_by_name (file_name);
537   if (module)
538     {
539       module->ref_count++;
540       
541       g_rec_mutex_unlock (&g_module_global_lock);
542       return module;
543     }
544
545   /* check whether we have a readable file right away */
546   if (g_file_test (file_name, G_FILE_TEST_IS_REGULAR))
547     name = g_strdup (file_name);
548   /* try completing file name with standard library suffix */
549   if (!name)
550     {
551       name = g_strconcat (file_name, "." G_MODULE_SUFFIX, NULL);
552       if (!g_file_test (name, G_FILE_TEST_IS_REGULAR))
553         {
554           g_free (name);
555           name = NULL;
556         }
557     }
558   /* try completing by appending libtool suffix */
559   if (!name)
560     {
561       name = g_strconcat (file_name, ".la", NULL);
562       if (!g_file_test (name, G_FILE_TEST_IS_REGULAR))
563         {
564           g_free (name);
565           name = NULL;
566         }
567     }
568   /* we can't access() the file, lets hope the platform backends finds
569    * it via library paths
570    */
571   if (!name)
572     {
573       gchar *dot = strrchr (file_name, '.');
574       gchar *slash = strrchr (file_name, G_DIR_SEPARATOR);
575       
576       /* make sure the name has a suffix */
577       if (!dot || dot < slash)
578         name = g_strconcat (file_name, "." G_MODULE_SUFFIX, NULL);
579       else
580         name = g_strdup (file_name);
581     }
582
583   /* ok, try loading the module */
584   if (name)
585     {
586       /* if it's a libtool archive, figure library file to load */
587       if (str_check_suffix (name, ".la")) /* libtool archive? */
588         {
589           gchar *real_name = parse_libtool_archive (name);
590
591           /* real_name might be NULL, but then module error is already set */
592           if (real_name)
593             {
594               g_free (name);
595               name = real_name;
596             }
597         }
598       if (name)
599         handle = _g_module_open (name, (flags & G_MODULE_BIND_LAZY) != 0,
600                         (flags & G_MODULE_BIND_LOCAL) != 0);
601     }
602   else
603     {
604       gchar *display_file_name = g_filename_display_name (file_name);
605       g_module_set_error_unduped (g_strdup_printf ("unable to access file \"%s\"", display_file_name));
606       g_free (display_file_name);
607     }
608   g_free (name);
609
610   if (handle)
611     {
612       gchar *saved_error;
613       GModuleCheckInit check_init;
614       const gchar *check_failed = NULL;
615       
616       /* search the module list by handle, since file names are not unique */
617       module = g_module_find_by_handle (handle);
618       if (module)
619         {
620           _g_module_close (module->handle, TRUE);
621           module->ref_count++;
622           g_module_set_error (NULL);
623           
624           g_rec_mutex_unlock (&g_module_global_lock);
625           return module;
626         }
627       
628       saved_error = g_strdup (g_module_error ());
629       g_module_set_error (NULL);
630       
631       module = g_new (GModule, 1);
632       module->file_name = g_strdup (file_name);
633       module->handle = handle;
634       module->ref_count = 1;
635       module->is_resident = FALSE;
636       module->unload = NULL;
637       module->next = modules;
638       modules = module;
639       
640       /* check initialization */
641       if (g_module_symbol (module, "g_module_check_init", (gpointer) &check_init) && check_init != NULL)
642         check_failed = check_init (module);
643       
644       /* we don't call unload() if the initialization check failed. */
645       if (!check_failed)
646         g_module_symbol (module, "g_module_unload", (gpointer) &module->unload);
647       
648       if (check_failed)
649         {
650           gchar *error;
651
652           error = g_strconcat ("GModule (", file_name, ") ",
653                                "initialization check failed: ",
654                                check_failed, NULL);
655           g_module_close (module);
656           module = NULL;
657           g_module_set_error (error);
658           g_free (error);
659         }
660       else
661         g_module_set_error (saved_error);
662
663       g_free (saved_error);
664     }
665
666   if (module != NULL &&
667       (module_debug_flags & G_MODULE_DEBUG_RESIDENT_MODULES))
668     g_module_make_resident (module);
669
670   g_rec_mutex_unlock (&g_module_global_lock);
671   return module;
672 }
673
674 /**
675  * g_module_close:
676  * @module: a #GModule to close
677  *
678  * Closes a module.
679  *
680  * Returns: %TRUE on success
681  */
682 gboolean
683 g_module_close (GModule *module)
684 {
685   SUPPORT_OR_RETURN (FALSE);
686   
687   g_return_val_if_fail (module != NULL, FALSE);
688   g_return_val_if_fail (module->ref_count > 0, FALSE);
689   
690   g_rec_mutex_lock (&g_module_global_lock);
691
692   module->ref_count--;
693   
694   if (!module->ref_count && !module->is_resident && module->unload)
695     {
696       GModuleUnload unload;
697
698       unload = module->unload;
699       module->unload = NULL;
700       unload (module);
701     }
702
703   if (!module->ref_count && !module->is_resident)
704     {
705       GModule *last;
706       GModule *node;
707       
708       last = NULL;
709       
710       node = modules;
711       while (node)
712         {
713           if (node == module)
714             {
715               if (last)
716                 last->next = node->next;
717               else
718                 modules = node->next;
719               break;
720             }
721           last = node;
722           node = last->next;
723         }
724       module->next = NULL;
725       
726       _g_module_close (module->handle, FALSE);
727       g_free (module->file_name);
728       g_free (module);
729     }
730   
731   g_rec_mutex_unlock (&g_module_global_lock);
732   return g_module_error() == NULL;
733 }
734
735 /**
736  * g_module_make_resident:
737  * @module: a #GModule to make permanently resident
738  *
739  * Ensures that a module will never be unloaded.
740  * Any future g_module_close() calls on the module will be ignored.
741  */
742 void
743 g_module_make_resident (GModule *module)
744 {
745   g_return_if_fail (module != NULL);
746
747   module->is_resident = TRUE;
748 }
749
750 /**
751  * g_module_error:
752  *
753  * Gets a string describing the last module error.
754  *
755  * Returns: a string describing the last module error
756  */
757 const gchar *
758 g_module_error (void)
759 {
760   return g_private_get (&module_error_private);
761 }
762
763 /**
764  * g_module_symbol:
765  * @module: a #GModule
766  * @symbol_name: the name of the symbol to find
767  * @symbol: (out): returns the pointer to the symbol value
768  *
769  * Gets a symbol pointer from a module, such as one exported
770  * by #G_MODULE_EXPORT. Note that a valid symbol can be %NULL.
771  *
772  * Returns: %TRUE on success
773  */
774 gboolean
775 g_module_symbol (GModule     *module,
776                  const gchar *symbol_name,
777                  gpointer    *symbol)
778 {
779   const gchar *module_error;
780
781   if (symbol)
782     *symbol = NULL;
783   SUPPORT_OR_RETURN (FALSE);
784   
785   g_return_val_if_fail (module != NULL, FALSE);
786   g_return_val_if_fail (symbol_name != NULL, FALSE);
787   g_return_val_if_fail (symbol != NULL, FALSE);
788   
789   g_rec_mutex_lock (&g_module_global_lock);
790
791 #ifdef  G_MODULE_NEED_USCORE
792   {
793     gchar *name;
794
795     name = g_strconcat ("_", symbol_name, NULL);
796     *symbol = _g_module_symbol (module->handle, name);
797     g_free (name);
798   }
799 #else   /* !G_MODULE_NEED_USCORE */
800   *symbol = _g_module_symbol (module->handle, symbol_name);
801 #endif  /* !G_MODULE_NEED_USCORE */
802   
803   module_error = g_module_error ();
804   if (module_error)
805     {
806       gchar *error;
807
808       error = g_strconcat ("'", symbol_name, "': ", module_error, NULL);
809       g_module_set_error (error);
810       g_free (error);
811       *symbol = NULL;
812     }
813   
814   g_rec_mutex_unlock (&g_module_global_lock);
815   return !module_error;
816 }
817
818 /**
819  * g_module_name:
820  * @module: a #GModule
821  *
822  * Returns the filename that the module was opened with.
823  *
824  * If @module refers to the application itself, "main" is returned.
825  *
826  * Returns: (transfer none): the filename of the module
827  */
828 const gchar *
829 g_module_name (GModule *module)
830 {
831   g_return_val_if_fail (module != NULL, NULL);
832   
833   if (module == main_module)
834     return "main";
835   
836   return module->file_name;
837 }
838
839 /**
840  * g_module_build_path:
841  * @directory: (nullable): the directory where the module is. This can be
842  *     %NULL or the empty string to indicate that the standard platform-specific
843  *     directories will be used, though that is not recommended
844  * @module_name: the name of the module
845  *
846  * A portable way to build the filename of a module. The platform-specific
847  * prefix and suffix are added to the filename, if needed, and the result
848  * is added to the directory, using the correct separator character.
849  *
850  * The directory should specify the directory where the module can be found.
851  * It can be %NULL or an empty string to indicate that the module is in a
852  * standard platform-specific directory, though this is not recommended
853  * since the wrong module may be found.
854  *
855  * For example, calling g_module_build_path() on a Linux system with a
856  * @directory of `/lib` and a @module_name of "mylibrary" will return
857  * `/lib/libmylibrary.so`. On a Windows system, using `\Windows` as the
858  * directory it will return `\Windows\mylibrary.dll`.
859  *
860  * Returns: the complete path of the module, including the standard library
861  *     prefix and suffix. This should be freed when no longer needed
862  */
863 gchar *
864 g_module_build_path (const gchar *directory,
865                      const gchar *module_name)
866 {
867   g_return_val_if_fail (module_name != NULL, NULL);
868   
869   return _g_module_build_path (directory, module_name);
870 }
871
872
873 #ifdef G_OS_WIN32
874
875 /* Binary compatibility versions. Not for newly compiled code. */
876
877 _GLIB_EXTERN GModule *    g_module_open_utf8 (const gchar  *file_name,
878                                               GModuleFlags  flags);
879
880 _GLIB_EXTERN const gchar *g_module_name_utf8 (GModule      *module);
881
882 GModule*
883 g_module_open_utf8 (const gchar    *file_name,
884                     GModuleFlags    flags)
885 {
886   return g_module_open (file_name, flags);
887 }
888
889 const gchar *
890 g_module_name_utf8 (GModule *module)
891 {
892   return g_module_name (module);
893 }
894
895 #endif