1/* GMODULE - GLIB wrapper code for dynamic module loading
2 * Copyright (C) 1998, 2000 Tim Janik
3 *
4 * dyld (Darwin) GMODULE implementation
5 * Copyright (C) 2001 Dan Winship
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#include "config.h"
23
24#include <mach-o/dyld.h>
25
26static gpointer self_module = GINT_TO_POINTER (1);
27
28static gpointer
29_g_module_open (const gchar *file_name,
30		gboolean     bind_lazy,
31		gboolean     bind_local)
32{
33  NSObjectFileImage image;
34  NSObjectFileImageReturnCode ret;
35  NSModule module;
36  unsigned long options;
37  char *msg;
38
39  ret = NSCreateObjectFileImageFromFile (file_name, &image);
40  if (ret != NSObjectFileImageSuccess)
41    {
42      switch (ret)
43	{
44	case NSObjectFileImageInappropriateFile:
45	case NSObjectFileImageFormat:
46	  msg = g_strdup_printf ("%s is not a loadable module", file_name);
47	  break;
48
49	case NSObjectFileImageArch:
50	  msg = g_strdup_printf ("%s is not built for this architecture",
51				 file_name);
52	  break;
53
54	case NSObjectFileImageAccess:
55	  if (access (file_name, F_OK) == 0)
56	    msg = g_strdup_printf ("%s: permission denied", file_name);
57	  else
58	    msg = g_strdup_printf ("%s: no such file or directory", file_name);
59	  break;
60
61	default:
62	  msg = g_strdup_printf ("unknown error for %s", file_name);
63	  break;
64	}
65
66      g_module_set_error (msg);
67      g_free (msg);
68      return NULL;
69    }
70
71  options = NSLINKMODULE_OPTION_RETURN_ON_ERROR;
72  if (bind_local)
73    options |= NSLINKMODULE_OPTION_PRIVATE;
74  if (!bind_lazy)
75    options |= NSLINKMODULE_OPTION_BINDNOW;
76  module = NSLinkModule (image, file_name, options);
77  NSDestroyObjectFileImage (image);
78  if (!module)
79    {
80      NSLinkEditErrors c;
81      int error_number;
82      const char *file, *error;
83
84      NSLinkEditError (&c, &error_number, &file, &error);
85      msg = g_strdup_printf ("could not link %s: %s", file_name, error);
86      g_module_set_error (msg);
87      g_free (msg);
88      return NULL;
89    }
90
91  return module;
92}
93
94static gpointer
95_g_module_self (void)
96{
97  return &self_module;
98}
99
100static void
101_g_module_close (gpointer handle,
102		 gboolean is_unref)
103{
104  if (handle == &self_module)
105    return;
106
107  if (!NSUnLinkModule (handle, 0))
108    g_module_set_error ("could not unlink module");
109}
110
111static gpointer
112_g_module_symbol (gpointer     handle,
113		  const gchar *symbol_name)
114{
115  NSSymbol sym;
116  char *msg;
117
118  if (handle == &self_module)
119    {
120      if (NSIsSymbolNameDefined (symbol_name))
121	sym = NSLookupAndBindSymbol (symbol_name);
122      else
123	sym = NULL;
124    }
125  else
126    sym = NSLookupSymbolInModule (handle, symbol_name);
127
128  if (!sym)
129    {
130      msg = g_strdup_printf ("no such symbol %s", symbol_name);
131      g_module_set_error (msg);
132      g_free (msg);
133      return NULL;
134    }
135
136  return NSAddressOfSymbol (sym);
137}
138
139static gchar*
140_g_module_build_path (const gchar *directory,
141		      const gchar *module_name)
142{
143  if (directory && *directory)
144    {
145      if (strncmp (module_name, "lib", 3) == 0)
146	return g_strconcat (directory, "/", module_name, NULL);
147      else
148	return g_strconcat (directory, "/lib", module_name, "." G_MODULE_SUFFIX, NULL);
149    }
150  else if (strncmp (module_name, "lib", 3) == 0)
151    return g_strdup (module_name);
152  else
153    return g_strconcat ("lib", module_name, "." G_MODULE_SUFFIX, NULL);
154}
155