ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/src/dynlink.c
Revision: 165
Committed: Fri Oct 21 03:50:50 2005 UTC (20 years, 9 months ago) by db
Content type: text/x-csrc
File size: 10213 byte(s)
Log Message:
- 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 "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     int
238     load_a_module(char *path, int warn, int core)
239     {
240 db 165 #ifdef HAVE_DLINFO
241 db 164 Link_map *map;
242     #endif
243 adx 30 #ifdef HAVE_SHL_LOAD
244     shl_t tmpptr;
245     #else
246     void *tmpptr = NULL;
247     #endif
248 db 165 void *addr = NULL;
249 adx 30 char *mod_basename;
250     void (*initfunc)(void) = NULL;
251     void (*mod_deinit)(void) = NULL;
252     char **verp;
253     char *ver;
254     struct module *modp;
255    
256     mod_basename = basename(path);
257    
258     if (findmodule_byname(mod_basename) != NULL)
259     return(1);
260    
261     #ifdef HAVE_SHL_LOAD
262     tmpptr = shl_load(path, BIND_IMMEDIATE, NULL);
263     #else
264     tmpptr = dlopen(path, RTLD_NOW);
265     #endif
266    
267     if (tmpptr == NULL)
268     {
269     #ifdef HAVE_SHL_LOAD
270     const char *err = strerror(errno);
271     #else
272     const char *err = dlerror();
273     #endif
274     sendto_realops_flags(UMODE_ALL, L_ALL, "Error loading module %s: %s",
275     mod_basename, err);
276     ilog(L_WARN, "Error loading module %s: %s", mod_basename, err);
277    
278     return(-1);
279     }
280    
281     #ifdef HAVE_SHL_LOAD
282     if (shl_findsym(&tmpptr, "_modinit", TYPE_UNDEFINED, (void *)&initfunc) == -1)
283     {
284     if (shl_findsym(&tmpptr, "__modinit", TYPE_UNDEFINED, (void *)&initfunc) == -1)
285     {
286     ilog(L_WARN, "Module %s has no _modinit() function", mod_basename);
287     sendto_realops_flags(UMODE_ALL, L_ALL, "Module %s has no _modinit() function",
288     mod_basename);
289     shl_unload(tmpptr);
290     return(-1);
291     }
292     }
293    
294     if (shl_findsym(&tmpptr, "_moddeinit", TYPE_UNDEFINED, (void *)&mod_deinit) == -1)
295     {
296     if (shl_findsym(&tmpptr, "__moddeinit", TYPE_UNDEFINED, (void *)&mod_deinit) == -1)
297     {
298     ilog(L_WARN, "Module %s has no _moddeinit() function", mod_basename);
299     sendto_realops_flags(UMODE_ALL, L_ALL, "Module %s has no _moddeinit() function",
300     mod_basename);
301     /* this is a soft error. we're allowed not to have one, i guess.
302     * (judging by the code in unload_one_module() */
303     mod_deinit = NULL;
304     }
305     }
306    
307     if (shl_findsym(&tmpptr, "_version", TYPE_UNDEFINED, &verp) == -1)
308     {
309     if (shl_findsym(&tmpptr, "__version", TYPE_UNDEFINED, &verp) == -1)
310     ver = unknown_ver;
311     else
312     ver = *verp;
313     }
314     else
315     ver = *verp;
316     #else
317     if ((initfunc = (void(*)(void))dlfunc(tmpptr, "_modinit")) == NULL &&
318     /* Only for compatibility, because some systems have underscore
319     * prepended symbol names */
320     (initfunc = (void(*)(void))dlfunc(tmpptr, "__modinit")) == NULL)
321     {
322     sendto_realops_flags(UMODE_ALL, L_ALL, "Module %s has no _modinit() function",
323     mod_basename);
324     ilog(L_WARN, "Module %s has no _modinit() function", mod_basename);
325     dlclose(tmpptr);
326     return(-1);
327     }
328    
329     mod_deinit = (void(*)(void))dlfunc(tmpptr, "_moddeinit");
330    
331     if (mod_deinit == NULL && (mod_deinit = (void(*)(void))dlfunc(tmpptr, "__moddeinit")) == NULL)
332     {
333     sendto_realops_flags(UMODE_ALL, L_ALL, "Module %s has no _moddeinit() function",
334     mod_basename);
335     ilog(L_WARN, "Module %s has no _moddeinit() function", mod_basename);
336     /* blah blah soft error, see above. */
337     mod_deinit = NULL;
338     }
339    
340     verp = (char **)dlsym(tmpptr, "_version");
341    
342     if (verp == NULL && (verp = (char **)dlsym(tmpptr, "__version")) == NULL)
343     ver = unknown_ver;
344     else
345     ver = *verp;
346     #endif
347    
348 db 164
349 adx 30 modp = MyMalloc(sizeof(struct module));
350 db 165 #ifdef HAVE_DLINFO
351 db 164 dlinfo(tmpptr, RTLD_DI_LINKMAP, &map);
352     if (map != NULL)
353 db 165 addr = map->l_addr;
354 db 164 else
355 db 165 addr = tmpptr;
356 db 164 #endif
357 db 165
358     modp->address = addr;
359 adx 30 modp->version = ver;
360     modp->core = core;
361     modp->modremove = mod_deinit;
362    
363     DupString(modp->name, mod_basename);
364     dlinkAdd(modp, &modp->node, &mod_list);
365    
366     initfunc();
367    
368     if (warn == 1)
369     {
370     sendto_realops_flags(UMODE_ALL, L_ALL,
371     "Module %s [version: %s] loaded at %p",
372 db 165 mod_basename, ver, addr);
373 adx 30 ilog(L_WARN, "Module %s [version: %s] loaded at %p",
374 db 165 mod_basename, ver, addr);
375 adx 30 }
376    
377     return(0);
378     }

Properties

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