Home | History | Annotate | Download | only in gmodule
      1 /* GMODULE - GLIB wrapper code for dynamic module loading
      2  * Copyright (C) 1998, 2000 Tim Janik
      3  *
      4  * BeOS GMODULE implementation
      5  * Copyright (C) 1999 Richard Offer and Shawn T. Amundson (amundson (at) gtk.org)
      6  *
      7  * This library is free software; you can redistribute it and/or
      8  * modify it under the terms of the GNU Lesser General Public
      9  * License as published by the Free Software Foundation; either
     10  * version 2 of the License, or (at your option) any later version.
     11  *
     12  * This library is distributed in the hope that it will be useful,
     13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
     15  * Lesser General Public License for more details.
     16  *
     17  * You should have received a copy of the GNU Lesser General Public
     18  * License along with this library; if not, write to the
     19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
     20  * Boston, MA 02111-1307, USA.
     21  */
     22 
     23 /*
     24  * MT safe
     25  */
     26 #include "config.h"
     27 
     28 #include <be/kernel/image.h> /* image (aka DSO) handling functions... */
     29 
     30 /*
     31  * The BeOS doesn't use the same symantics as Unix's dlopen....
     32  *
     33  */
     34 #ifndef	RTLD_GLOBAL
     35 #define	RTLD_GLOBAL	0
     36 #endif	/* RTLD_GLOBAL */
     37 #ifndef	RTLD_LAZY
     38 #define	RTLD_LAZY	1
     39 #endif	/* RTLD_LAZY */
     40 #ifndef	RTLD_NOW
     41 #define	RTLD_NOW	0
     42 #endif	/* RTLD_NOW */
     43 
     44 
     45 /*
     46  * Points to Ponder
     47  *
     48  * You can load the same DSO more than once, in which case you'll have
     49  * different image_id's. While this means that we don't have to worry about
     50  * reference counts, it could lead to problems in the future....
     51  * richard.
     52  *
     53  * load_add_on() apparently does not support lazy or local binding.  Need
     54  * to confirm that the actual behavior is non-lazy/local.  --ds
     55  */
     56 
     57 #include <Errors.h>
     58 #include <stdio.h>
     59 
     60 /* --- functions --- */
     61 static gpointer
     62 _g_module_open (const gchar *file_name,
     63 		gboolean     bind_lazy,
     64 		gboolean     bind_local)
     65 {
     66   image_id handle;
     67 
     68   handle = load_add_on (file_name);
     69   if (handle < B_OK)
     70     {
     71       gchar *msg = g_strdup_printf ("failed to load_add_on(%s): %s",
     72 				    file_name,
     73 				    strerror (handle));
     74 
     75       g_module_set_error (msg);
     76       g_free (msg);
     77 
     78       return NULL;
     79     }
     80 
     81   return (gpointer) handle;
     82 }
     83 
     84 static gpointer
     85 _g_module_self (void)
     86 {
     87   image_info info;
     88   int32 cookie = 0;
     89   status_t status;
     90 
     91   /* Is it always the first one?  I'm guessing yes. */
     92   status = get_next_image_info (0, &cookie, &info);
     93   if (status == B_OK)
     94     return (gpointer) info.id;
     95   else
     96     {
     97       gchar *msg = g_strdup_printf ("failed to get_next_image_info(self): %s",
     98 				    strerror (status));
     99 
    100       g_module_set_error (msg);
    101       g_free (msg);
    102 
    103       return NULL;
    104     }
    105 }
    106 
    107 static void
    108 _g_module_close (gpointer handle,
    109 		 gboolean is_unref)
    110 {
    111   image_info info;
    112   gchar *name;
    113 
    114   if (unload_add_on ((image_id) handle) != B_OK)
    115     {
    116       gchar *msg;
    117 
    118       /* Try and get the name of the image. */
    119       if (get_image_info ((image_id) handle, &info) != B_OK)
    120 	name = g_strdup ("unknown");
    121       else
    122 	name = g_strdup (info.name);
    123 
    124       msg = g_strdup_printf ("failed to unload_add_on(%s): %s", name, strerror (status));
    125       g_module_set_error (msg);
    126       g_free (msg);
    127       g_free (name);
    128     }
    129 }
    130 
    131 static gpointer
    132 _g_module_symbol (gpointer     handle,
    133 		  const gchar *symbol_name)
    134 {
    135   image_id id;
    136   status_t status;
    137   image_info info;
    138   int32 type, name_len;
    139   void *p;
    140   gchar *msg, name[256];
    141   gint n, l;
    142 
    143   id = (image_id) handle;
    144 
    145   status = get_image_info (id, &info);
    146   if (status != B_OK)
    147     {
    148       msg = g_strdup_printf ("failed to get_image_info(): %s", strerror (status));
    149       g_module_set_error (msg);
    150       g_free (msg);
    151 
    152       return NULL;
    153     }
    154 
    155   l = strlen (symbol_name);
    156   name_len = 256;
    157   type = B_SYMBOL_TYPE_ANY;
    158   n = 0;
    159   status = get_nth_image_symbol (id, n, name, &name_len, &type, &p);
    160   while (status == B_OK)
    161     {
    162       if (p && strncmp (name, symbol_name, l) == 0)
    163 	return p;
    164 
    165       if (strcmp (name, "_end") == 0)
    166         {
    167 	  msg = g_strdup_printf ("unmatched symbol name `%s'", symbol_name);
    168           g_module_set_error (msg);
    169 	  g_free (msg);
    170 
    171 	  return NULL;
    172         }
    173 
    174       name_len = 256;
    175       type = B_SYMBOL_TYPE_ANY;
    176       n++;
    177       status = get_nth_image_symbol (id, n, name, &name_len, &type, &p);
    178     }
    179 
    180   msg = g_strdup_printf ("failed to get_image_symbol(%s): %s", symbol_name, strerror (status));
    181   g_module_set_error (msg);
    182   g_free (msg);
    183 
    184   return NULL;
    185 }
    186 
    187 static gchar*
    188 _g_module_build_path (const gchar *directory,
    189 		      const gchar *module_name)
    190 {
    191   g_warning ("_g_module_build_path() untested for BeOS!");
    192 
    193   if (directory && *directory)
    194     {
    195       if (strncmp (module_name, "lib", 3) == 0)
    196 	return g_strconcat (directory, "/", module_name, NULL);
    197       else
    198 	return g_strconcat (directory, "/lib", module_name, "." G_MODULE_SUFFIX, NULL);
    199     }
    200   else if (strncmp (module_name, "lib", 3) == 0)
    201     return g_strdup (module_name);
    202   else
    203     return g_strconcat ("lib", module_name, "." G_MODULE_SUFFIX, NULL);
    204 }
    205