static gpointer _g_module_symbol (gpointer handle, const gchar *symbol_name) { image_id id; status_t status; image_info info; int32 type, name_len; void *p; gchar *msg, name[256]; gint n, l; id = (image_id) handle; status = get_image_info (id, &info); if (status != B_OK) { msg = g_strdup_printf ("failed to get_image_info(): %s", strerror (status)); g_module_set_error (msg); g_free (msg); return NULL; } l = strlen (symbol_name); name_len = 256; type = B_SYMBOL_TYPE_ANY; n = 0; status = get_nth_image_symbol (id, n, name, &name_len, &type, &p); while (status == B_OK) { if (p && strncmp (name, symbol_name, l) == 0) return p; if (strcmp (name, "_end") == 0) { msg = g_strdup_printf ("unmatched symbol name `%s'", symbol_name); g_module_set_error (msg); g_free (msg); return NULL; } name_len = 256; type = B_SYMBOL_TYPE_ANY; n++; status = get_nth_image_symbol (id, n, name, &name_len, &type, &p); } msg = g_strdup_printf ("failed to get_image_symbol(%s): %s", symbol_name, strerror (status)); g_module_set_error (msg); g_free (msg); return NULL; }
static gpointer _g_module_symbol (gpointer handle, const gchar *symbol_name) { gpointer p = NULL; /* should we restrict lookups to TYPE_PROCEDURE? */ if (handle == PROG_HANDLE) { /* PROG_HANDLE will only lookup symbols in the program itself, not honouring * libraries. passing NULL as a handle will also try to lookup the symbol * in currently loaded libraries. fix pointed out and supplied by: * David Gero <*****@*****.**> */ handle = NULL; } if (shl_findsym ((shl_t*) &handle, symbol_name, TYPE_UNDEFINED, &p) != 0 || handle == NULL || p == NULL) { /* the hp-docs say we should better abort() if errno==ENOSYM ;( */ g_module_set_error (g_strerror (errno)); } return p; }
static gpointer _g_module_open (const gchar *file_name, gboolean bind_lazy, gboolean bind_local) { gpointer handle; gchar* member; gchar* full_name; /* extract name of first member of archive */ member = _g_module_get_member (file_name); if (member != NULL) { full_name = g_strconcat (file_name, "(", member, ")", NULL); g_free (member); } else full_name = g_strdup (file_name); handle = dlopen (full_name, (bind_local ? RTLD_LOCAL : RTLD_GLOBAL) | RTLD_MEMBER | (bind_lazy ? RTLD_LAZY : RTLD_NOW)); g_free (full_name); if (!handle) g_module_set_error (fetch_dlerror (TRUE)); return handle; }
static void set_error (void) { gchar *error = g_win32_error_message (GetLastError ()); g_module_set_error (error); g_free (error); }
static void _g_module_close (gpointer handle, gboolean is_unref) { if (!is_unref) { if (shl_unload ((shl_t) handle) != 0) g_module_set_error (g_strerror (errno)); } }
static gpointer _g_module_self (void) { gpointer handle; handle = dlopen (NULL, RTLD_GLOBAL | RTLD_LAZY); if (!handle) g_module_set_error (fetch_dlerror (TRUE)); return handle; }
static gpointer _g_module_self (void) { shl_t shl_handle; shl_handle = PROG_HANDLE; if (!shl_handle) g_module_set_error (g_strerror (errno)); return shl_handle; }
static gpointer _g_module_symbol (gpointer handle, const gchar *symbol_name) { gpointer p; p = dlsym (handle, symbol_name); if (!p) g_module_set_error (fetch_dlerror ()); return p; }
static gpointer _g_module_open (const gchar *file_name, gboolean bind_lazy) { gpointer handle; handle = dlopen (file_name, RTLD_GLOBAL | (bind_lazy ? RTLD_LAZY : RTLD_NOW)); if (!handle) g_module_set_error (fetch_dlerror ()); return handle; }
static gpointer _g_module_symbol (gpointer handle, const gchar *symbol_name) { gpointer p; gchar *msg; fetch_dlerror (FALSE); p = dlsym (handle, symbol_name); msg = fetch_dlerror (FALSE); if (msg) g_module_set_error (msg); return p; }
static gpointer _g_module_self (void) { gpointer handle; /* to query symbols from the program itself, special link options * are required on some systems. */ /* XXX, not supported */ handle = NULL; g_module_set_error ("module handle for self not supported"); return handle; }
static gpointer _g_module_self (void) { gpointer handle; /* to query symbols from the program itself, special link options * are required on some systems. */ handle = dlopen (NULL, RTLD_GLOBAL | RTLD_LAZY); if (!handle) g_module_set_error (fetch_dlerror ()); return handle; }
static void _g_module_close (gpointer handle, gboolean is_unref) { /* are there any systems out there that have dlopen()/dlclose() * without a reference count implementation? */ is_unref |= 1; if (is_unref) { if (dlclose (handle) != 0) g_module_set_error (fetch_dlerror ()); } }
/* * shl_load() does not appear to support making symbols invisible to * the global namespace. However, the default is to put the library * last in the search order, which is approximately what we want, * since it will cause symbols that conflict with existing symbols to * be invisible. It is unclear if BIND_FIRST should be used when * bind_local==0, since it may cause the loaded symbols to be used * preferentially to the application's symbols, which is Almost * Always Wrong. --ds */ static gpointer _g_module_open (const gchar *file_name, gboolean bind_lazy, gboolean bind_local) { shl_t shl_handle; shl_handle = shl_load (file_name, (bind_lazy ? BIND_DEFERRED : BIND_IMMEDIATE) | OPT_BIND_FLAGS, 0); if (!shl_handle) { /* the hp-docs say we should better abort() if errno==ENOSYM ;( */ g_module_set_error (g_strerror (errno)); } return (gpointer) shl_handle; }
gboolean g_module_symbol (GModule *module, const gchar *symbol_name, gpointer *symbol) { const gchar *module_error; if (symbol) *symbol = NULL; SUPPORT_OR_RETURN (FALSE); g_return_val_if_fail (module != NULL, FALSE); g_return_val_if_fail (symbol_name != NULL, FALSE); g_return_val_if_fail (symbol != NULL, FALSE); g_static_rec_mutex_lock (&g_module_global_lock); #ifdef G_MODULE_NEED_USCORE { gchar *name; name = g_strconcat ("_", symbol_name, NULL); *symbol = _g_module_symbol (module->handle, name); g_free (name); } #else /* !G_MODULE_NEED_USCORE */ *symbol = _g_module_symbol (module->handle, symbol_name); #endif /* !G_MODULE_NEED_USCORE */ module_error = g_module_error (); if (module_error) { gchar *error; error = g_strconcat ("`", symbol_name, "': ", module_error, NULL); g_module_set_error (error); g_free (error); *symbol = NULL; } g_static_rec_mutex_unlock (&g_module_global_lock); return !module_error; }
/* --- functions --- */ static gpointer _g_module_open (const gchar *file_name, gboolean bind_lazy) { image_id handle; handle = load_add_on (file_name); if (handle < B_OK) { gchar *msg = g_strdup_printf ("failed to load_add_on(%s): %s", file_name, strerror (handle)); g_module_set_error (msg); g_free (msg); return NULL; } return (gpointer) handle; }
static gpointer _g_module_self (void) { image_info info; int32 cookie = 0; status_t status; /* Is it always the first one? I'm guessing yes. */ status = get_next_image_info (0, &cookie, &info); if (status == B_OK) return (gpointer) info.id; else { gchar *msg = g_strdup_printf ("failed to get_next_image_info(self): %s", strerror (status)); g_module_set_error (msg); g_free (msg); return NULL; } }
static void set_error (const gchar *format, ...) { gchar *error; gchar *detail; gchar *message; va_list args; error = g_win32_error_message (GetLastError ()); va_start (args, format); detail = g_strdup_vprintf (format, args); va_end (args); message = g_strconcat (detail, error, NULL); g_module_set_error (message); g_free (message); g_free (detail); g_free (error); }
static void _g_module_close (gpointer handle, gboolean is_unref) { image_info info; gchar *name; if (unload_add_on ((image_id) handle) != B_OK) { gchar *msg; /* Try and get the name of the image. */ if (get_image_info ((image_id) handle, &info) != B_OK) name = g_strdup ("unknown"); else name = g_strdup (info.name); msg = g_strdup_printf ("failed to unload_add_on(%s): %s", name, strerror (status)); g_module_set_error (msg); g_free (msg); g_free (name); } }
GModule* g_module_open (const gchar *file_name, GModuleFlags flags) { GModule *module; gpointer handle = NULL; gchar *name = NULL; SUPPORT_OR_RETURN (NULL); g_static_rec_mutex_lock (&g_module_global_lock); if (G_UNLIKELY (!module_debug_initialized)) _g_module_debug_init (); if (module_debug_flags & G_MODULE_DEBUG_BIND_NOW_MODULES) flags &= ~G_MODULE_BIND_LAZY; if (!file_name) { if (!main_module) { handle = _g_module_self (); if (handle) { main_module = g_new (GModule, 1); main_module->file_name = NULL; #ifdef G_OS_WIN32 main_module->cp_file_name = NULL; #endif main_module->handle = handle; main_module->ref_count = 1; main_module->is_resident = TRUE; main_module->unload = NULL; main_module->next = NULL; } } else main_module->ref_count++; g_static_rec_mutex_unlock (&g_module_global_lock); return main_module; } /* we first search the module list by name */ module = g_module_find_by_name (file_name); if (module) { module->ref_count++; g_static_rec_mutex_unlock (&g_module_global_lock); return module; } /* check whether we have a readable file right away */ if (g_file_test (file_name, G_FILE_TEST_IS_REGULAR)) name = g_strdup (file_name); /* try completing file name with standard library suffix */ if (!name) { name = g_strconcat (file_name, "." G_MODULE_SUFFIX, NULL); if (!g_file_test (name, G_FILE_TEST_IS_REGULAR)) { g_free (name); name = NULL; } } /* try completing by appending libtool suffix */ if (!name) { name = g_strconcat (file_name, ".la", NULL); if (!g_file_test (name, G_FILE_TEST_IS_REGULAR)) { g_free (name); name = NULL; } } /* we can't access() the file, lets hope the platform backends finds * it via library paths */ if (!name) { gchar *dot = strrchr (file_name, '.'); gchar *slash = strrchr (file_name, G_DIR_SEPARATOR); /* make sure the name has a suffix */ if (!dot || dot < slash) name = g_strconcat (file_name, "." G_MODULE_SUFFIX, NULL); else name = g_strdup (file_name); } /* ok, try loading the module */ if (name) { /* if it's a libtool archive, figure library file to load */ if (str_check_suffix (name, ".la")) /* libtool archive? */ { gchar *real_name = parse_libtool_archive (name); /* real_name might be NULL, but then module error is already set */ if (real_name) { g_free (name); name = real_name; } } if (name) handle = _g_module_open (name, (flags & G_MODULE_BIND_LAZY) != 0, (flags & G_MODULE_BIND_LOCAL) != 0); } else { gchar *display_file_name = g_filename_display_name (file_name); g_module_set_error_unduped (g_strdup_printf ("unable to access file \"%s\"", display_file_name)); g_free (display_file_name); } g_free (name); if (handle) { gchar *saved_error; GModuleCheckInit check_init; const gchar *check_failed = NULL; /* search the module list by handle, since file names are not unique */ module = g_module_find_by_handle (handle); if (module) { _g_module_close (module->handle, TRUE); module->ref_count++; g_module_set_error (NULL); g_static_rec_mutex_unlock (&g_module_global_lock); return module; } saved_error = g_strdup (g_module_error ()); g_module_set_error (NULL); module = g_new (GModule, 1); module->file_name = g_strdup (file_name); #ifdef G_OS_WIN32 module->cp_file_name = g_locale_from_utf8 (file_name, -1, NULL, NULL, NULL); #endif module->handle = handle; module->ref_count = 1; module->is_resident = FALSE; module->unload = NULL; module->next = modules; modules = module; /* check initialization */ if (g_module_symbol (module, "g_module_check_init", (gpointer) &check_init) && check_init != NULL) check_failed = check_init (module); /* we don't call unload() if the initialization check failed. */ if (!check_failed) g_module_symbol (module, "g_module_unload", (gpointer) &module->unload); if (check_failed) { gchar *error; error = g_strconcat ("GModule (", file_name ? file_name : "NULL", ") initialization check failed: ", check_failed, NULL); g_module_close (module); module = NULL; g_module_set_error (error); g_free (error); } else g_module_set_error (saved_error); g_free (saved_error); } if (module != NULL && (module_debug_flags & G_MODULE_DEBUG_RESIDENT_MODULES)) g_module_make_resident (module); g_static_rec_mutex_unlock (&g_module_global_lock); return module; }