ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/src/dynlink.c
Revision: 164
Committed: Thu Oct 20 21:34:25 2005 UTC (20 years, 9 months ago) by db
Content type: text/x-csrc
File size: 10357 byte(s)
Log Message:
- Use dlinfo() to get the actual load address of the module i.e. its
  library base. The previous code was using the "handle" which is wrong.
  Hopefully should compile on linux as well, perhaps we should also have
  an HAVE_DLINFO checked for in configure.


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

Properties

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