/* GMODULE - GLIB wrapper code for dynamic module loading * Copyright (C) 1998, 2000 Tim Janik * * BeOS GMODULE implementation * Copyright (C) 1999 Richard Offer and Shawn T. Amundson (amundson@gtk.org) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ /* * MT safe */ #include "config.h" #include <be/kernel/image.h> /* image (aka DSO) handling functions... */ /* * The BeOS doesn't use the same symantics as Unix's dlopen.... * */ #ifndef RTLD_GLOBAL #define RTLD_GLOBAL 0 #endif /* RTLD_GLOBAL */ #ifndef RTLD_LAZY #define RTLD_LAZY 1 #endif /* RTLD_LAZY */ #ifndef RTLD_NOW #define RTLD_NOW 0 #endif /* RTLD_NOW */ /* * Points to Ponder * * You can load the same DSO more than once, in which case you'll have * different image_id's. While this means that we don't have to worry about * reference counts, it could lead to problems in the future.... * richard. * * load_add_on() apparently does not support lazy or local binding. Need * to confirm that the actual behavior is non-lazy/local. --ds */ #include <Errors.h> #include <stdio.h> /* --- functions --- */ static gpointer _g_module_open (const gchar *file_name, gboolean bind_lazy, gboolean bind_local) { 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 _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); } } 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 gchar* _g_module_build_path (const gchar *directory, const gchar *module_name) { g_warning ("_g_module_build_path() untested for BeOS!"); if (directory && *directory) { if (strncmp (module_name, "lib", 3) == 0) return g_strconcat (directory, "/", module_name, NULL); else return g_strconcat (directory, "/lib", module_name, "." G_MODULE_SUFFIX, NULL); } else if (strncmp (module_name, "lib", 3) == 0) return g_strdup (module_name); else return g_strconcat ("lib", module_name, "." G_MODULE_SUFFIX, NULL); }