ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-7.2/src/dynlink.c
Revision: 166
Committed: Fri Oct 21 04:20:48 2005 UTC (19 years, 10 months ago) by db
Content type: text/x-csrc
File size: 10348 byte(s)
Log Message:
Backported from HEAD

- committed configure changes by nenolod (William Pitcock)
  to check for HAVE_DLINFO
- fixed logic for picking up address for the mod_list


File Contents

# User Rev Content
1 adx 30 /*
2     * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3     * dynlink.c: A module loader.
4     *
5     * Copyright (C) 2002 by the past and present ircd coders, and others.
6     *
7     * This program is free software; you can redistribute it and/or modify
8     * it under the terms of the GNU General Public License as published by
9     * the Free Software Foundation; either version 2 of the License, or
10     * (at your option) any later version.
11     *
12     * This program 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
15     * GNU General Public License for more details.
16     *
17     * You should have received a copy of the GNU General Public License
18     * along with this program; if not, write to the Free Software
19     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20     * USA
21     *
22 knight 31 * $Id$
23 adx 30 *
24     */
25     #include "stdinc.h"
26     #include "tools.h"
27     #include "irc_string.h"
28     #include "modules.h"
29     #include "s_log.h"
30     #include "client.h"
31     #include "send.h"
32    
33     #ifndef RTLD_NOW
34     #define RTLD_NOW RTLD_LAZY /* openbsd deficiency */
35     #endif
36    
37 db 166 #if defined(HAVE_DLINFO) && defined(HAVE_LINK_H)
38     # include <link.h>
39     #endif
40    
41 adx 30 extern dlink_list mod_list;
42    
43     static char unknown_ver[] = "<unknown>";
44    
45     /* This file contains the core functions to use dynamic libraries.
46     * -TimeMr14C
47     */
48    
49     #if !defined(HAVE_SHL_LOAD) && !defined(HAVE_DLFUNC)
50     /*
51     * Fake dlfunc(3) if we don't have it, cause it's happy.
52     */
53     typedef void (*__function_p)(void);
54    
55     static __function_p
56     dlfunc(void *myHandle, const char *functionName)
57     {
58     /* XXX This is not guaranteed to work, but with
59     * traditional dl*(3), it is the best we can do.
60     * -jmallett
61     */
62     void *symbolp;
63    
64     symbolp = dlsym(myHandle, functionName);
65     return((__function_p)(uintptr_t)symbolp);
66     }
67     #endif
68    
69     #ifdef HAVE_MACH_O_DYLD_H
70     /*
71     ** jmallett's dl*(3) shims for NSModule(3) systems.
72     */
73     #include <mach-o/dyld.h>
74    
75     #ifndef HAVE_DLOPEN
76     #ifndef RTLD_LAZY
77     #define RTLD_LAZY 2185 /* built-in dl*(3) don't care */
78     #endif
79    
80     void undefinedErrorHandler(const char *);
81     NSModule multipleErrorHandler(NSSymbol, NSModule, NSModule);
82     void linkEditErrorHandler(NSLinkEditErrors, int, const char *, const char *);
83     char *dlerror(void);
84     void *dlopen(char *, int);
85     int dlclose(void *);
86     void *dlsym(void *, char *);
87    
88     static int firstLoad = TRUE;
89     static int myDlError;
90     static const char *myErrorTable[] =
91     {
92     "Loading file as object failed\n",
93     "Loading file as object succeeded\n",
94     "Not a valid shared object\n",
95     "Architecture of object invalid on this architecture\n",
96     "Invalid or corrupt image\n",
97     "Could not access object\n",
98     "NSCreateObjectFileImageFromFile failed\n",
99     NULL
100     };
101    
102     void
103     undefinedErrorHandler(const char *symbolName)
104     {
105     sendto_realops_flags(UMODE_ALL, L_ALL, "Undefined symbol: %s", symbolName);
106     ilog(L_WARN, "Undefined symbol: %s", symbolName);
107     return;
108     }
109    
110     NSModule
111     multipleErrorHandler(NSSymbol s, NSModule old, NSModule new)
112     {
113     /* XXX
114     ** This results in substantial leaking of memory... Should free one
115     ** module, maybe?
116     */
117     sendto_realops_flags(UMODE_ALL, L_ALL, "Symbol `%s' found in `%s' and `%s'",
118     NSNameOfSymbol(s), NSNameOfModule(old), NSNameOfModule(new));
119     ilog(L_WARN, "Symbol `%s' found in `%s' and `%s'", NSNameOfSymbol(s),
120     NSNameOfModule(old), NSNameOfModule(new));
121     /* We return which module should be considered valid, I believe */
122     return(new);
123     }
124    
125     void
126     linkEditErrorHandler(NSLinkEditErrors errorClass, int errnum,
127     const char *fileName, const char *errorString)
128     {
129     sendto_realops_flags(UMODE_ALL, L_ALL, "Link editor error: %s for %s",
130     errorString, fileName);
131     ilog(L_WARN, "Link editor error: %s for %s", errorString, fileName);
132     return;
133     }
134    
135     char *
136     dlerror(void)
137     {
138     return(myDlError == NSObjectFileImageSuccess ? NULL : myErrorTable[myDlError % 7]);
139     }
140    
141     void *
142     dlopen(char *filename, int unused)
143     {
144     NSObjectFileImage myImage;
145     NSModule myModule;
146    
147     if (firstLoad)
148     {
149     /* If we are loading our first symbol (huzzah!) we should go ahead
150     * and install link editor error handling!
151     */
152     NSLinkEditErrorHandlers linkEditorErrorHandlers;
153    
154     linkEditorErrorHandlers.undefined = undefinedErrorHandler;
155     linkEditorErrorHandlers.multiple = multipleErrorHandler;
156     linkEditorErrorHandlers.linkEdit = linkEditErrorHandler;
157     NSInstallLinkEditErrorHandlers(&linkEditorErrorHandlers);
158     firstLoad = FALSE;
159     }
160    
161     myDlError = NSCreateObjectFileImageFromFile(filename, &myImage);
162    
163     if (myDlError != NSObjectFileImageSuccess)
164     return(NULL);
165    
166     myModule = NSLinkModule(myImage, filename, NSLINKMODULE_OPTION_PRIVATE);
167     return((void *)myModule);
168     }
169    
170     int
171     dlclose(void *myModule)
172     {
173     NSUnLinkModule(myModule, FALSE);
174     return(0);
175     }
176    
177     void *
178     dlsym(void *myModule, char *mySymbolName)
179     {
180     NSSymbol mySymbol;
181    
182     mySymbol = NSLookupSymbolInModule((NSModule)myModule, mySymbolName);
183     return NSAddressOfSymbol(mySymbol);
184     }
185     #endif
186     #endif
187    
188     /* unload_one_module()
189     *
190     * inputs - name of module to unload
191     * - 1 to say modules unloaded, 0 to not
192     * output - 0 if successful, -1 if error
193     * side effects - module is unloaded
194     */
195     int
196     unload_one_module(char *name, int warn)
197     {
198     dlink_node *ptr = NULL;
199     struct module *modp = NULL;
200    
201     if ((ptr = findmodule_byname(name)) == NULL)
202     return -1;
203    
204     modp = ptr->data;
205    
206     if (modp->modremove)
207     (*modp->modremove)();
208    
209     #ifdef HAVE_SHL_LOAD
210     /* shl_* and friends have a slightly different format than dl*. But it does not
211     * require creation of a totally new modules.c, instead proper usage of
212     * defines solve this case. -TimeMr14C
213     */
214     shl_unload((shl_t) & (modp->address));
215     #else
216     /* We use FreeBSD's dlfunc(3) interface, or fake it as we
217     * used to here if it isn't there. The interface should
218     * be standardised some day, and so it eventually will be
219     * providing something guaranteed to do the right thing here.
220     * -jmallett
221     */
222     dlclose(modp->address);
223     #endif
224     assert(dlink_list_length(&mod_list) > 0);
225     dlinkDelete(ptr, &mod_list);
226     MyFree(modp->name);
227     MyFree(modp);
228    
229     if (warn == 1)
230     {
231     ilog(L_INFO, "Module %s unloaded", name);
232     sendto_realops_flags(UMODE_ALL, L_ALL, "Module %s unloaded", name);
233     }
234    
235     return 0;
236     }
237    
238     /* load_a_module()
239     *
240     * inputs - path name of module, int to notice, int of core
241     * output - -1 if error 0 if success
242     * side effects - loads a module if successful
243     */
244     int
245     load_a_module(char *path, int warn, int core)
246     {
247 db 166 #ifdef HAVE_DLINFO
248     Link_map *map;
249     #endif
250 adx 30 #ifdef HAVE_SHL_LOAD
251     shl_t tmpptr;
252     #else
253     void *tmpptr = NULL;
254     #endif
255 db 166 void *addr = NULL;
256 adx 30 char *mod_basename;
257     void (*initfunc)(void) = NULL;
258     void (*mod_deinit)(void) = NULL;
259     char **verp;
260     char *ver;
261     struct module *modp;
262    
263     mod_basename = basename(path);
264    
265     if (findmodule_byname(mod_basename) != NULL)
266     return(1);
267    
268     #ifdef HAVE_SHL_LOAD
269     tmpptr = shl_load(path, BIND_IMMEDIATE, NULL);
270     #else
271     tmpptr = dlopen(path, RTLD_NOW);
272     #endif
273    
274     if (tmpptr == NULL)
275     {
276     #ifdef HAVE_SHL_LOAD
277     const char *err = strerror(errno);
278     #else
279     const char *err = dlerror();
280     #endif
281     sendto_realops_flags(UMODE_ALL, L_ALL, "Error loading module %s: %s",
282     mod_basename, err);
283     ilog(L_WARN, "Error loading module %s: %s", mod_basename, err);
284    
285     return(-1);
286     }
287    
288     #ifdef HAVE_SHL_LOAD
289     if (shl_findsym(&tmpptr, "_modinit", TYPE_UNDEFINED, (void *)&initfunc) == -1)
290     {
291     if (shl_findsym(&tmpptr, "__modinit", TYPE_UNDEFINED, (void *)&initfunc) == -1)
292     {
293     ilog(L_WARN, "Module %s has no _modinit() function", mod_basename);
294     sendto_realops_flags(UMODE_ALL, L_ALL, "Module %s has no _modinit() function",
295     mod_basename);
296     shl_unload(tmpptr);
297     return(-1);
298     }
299     }
300    
301     if (shl_findsym(&tmpptr, "_moddeinit", TYPE_UNDEFINED, (void *)&mod_deinit) == -1)
302     {
303     if (shl_findsym(&tmpptr, "__moddeinit", TYPE_UNDEFINED, (void *)&mod_deinit) == -1)
304     {
305     ilog(L_WARN, "Module %s has no _moddeinit() function", mod_basename);
306     sendto_realops_flags(UMODE_ALL, L_ALL, "Module %s has no _moddeinit() function",
307     mod_basename);
308     /* this is a soft error. we're allowed not to have one, i guess.
309     * (judging by the code in unload_one_module() */
310     mod_deinit = NULL;
311     }
312     }
313    
314     if (shl_findsym(&tmpptr, "_version", TYPE_UNDEFINED, &verp) == -1)
315     {
316     if (shl_findsym(&tmpptr, "__version", TYPE_UNDEFINED, &verp) == -1)
317     ver = unknown_ver;
318     else
319     ver = *verp;
320     }
321     else
322     ver = *verp;
323     #else
324     if ((initfunc = (void(*)(void))dlfunc(tmpptr, "_modinit")) == NULL &&
325     /* Only for compatibility, because some systems have underscore
326     * prepended symbol names */
327     (initfunc = (void(*)(void))dlfunc(tmpptr, "__modinit")) == NULL)
328     {
329     sendto_realops_flags(UMODE_ALL, L_ALL, "Module %s has no _modinit() function",
330     mod_basename);
331     ilog(L_WARN, "Module %s has no _modinit() function", mod_basename);
332     dlclose(tmpptr);
333     return(-1);
334     }
335    
336     mod_deinit = (void(*)(void))dlfunc(tmpptr, "_moddeinit");
337    
338     if (mod_deinit == NULL && (mod_deinit = (void(*)(void))dlfunc(tmpptr, "__moddeinit")) == NULL)
339     {
340     sendto_realops_flags(UMODE_ALL, L_ALL, "Module %s has no _moddeinit() function",
341     mod_basename);
342     ilog(L_WARN, "Module %s has no _moddeinit() function", mod_basename);
343     /* blah blah soft error, see above. */
344     mod_deinit = NULL;
345     }
346    
347     verp = (char **)dlsym(tmpptr, "_version");
348    
349     if (verp == NULL && (verp = (char **)dlsym(tmpptr, "__version")) == NULL)
350     ver = unknown_ver;
351     else
352     ver = *verp;
353     #endif
354    
355     modp = MyMalloc(sizeof(struct module));
356 db 166 #ifdef HAVE_DLINFO
357     dlinfo(tmpptr, RTLD_DI_LINKMAP, &map);
358     if (map != NULL)
359     addr = map->l_addr;
360     else
361     addr = tmpptr;
362     #endif
363    
364     modp->address = addr;
365 adx 30 modp->version = ver;
366     modp->core = core;
367     modp->modremove = mod_deinit;
368    
369     DupString(modp->name, mod_basename);
370     dlinkAdd(modp, &modp->node, &mod_list);
371    
372     initfunc();
373    
374     if (warn == 1)
375     {
376     sendto_realops_flags(UMODE_ALL, L_ALL,
377     "Module %s [version: %s] loaded at %p",
378 db 166 mod_basename, ver, addr);
379 adx 30 ilog(L_WARN, "Module %s [version: %s] loaded at %p",
380 db 166 mod_basename, ver, addr);
381 adx 30 }
382    
383     return(0);
384     }

Properties

Name Value
svn:eol-style native
svn:keywords Id Revision