Copyright (c) 1992,1993,1995,1996, Jens-Uwe Mager, Helios Software GmbH Not derived from licensed software. Permission is granted to freely use, copy, modify, and redistribute this software, provided that the author is not construed to be liable for any results of using the software, alterations are clearly marked as such, and this notice is not modified. libdl.a ------- This is an emulation library to emulate the SunOS/System V.4 functions to access the runtime linker. The functions are emulated by using the AIX load() function and by reading the .loader section of the loaded module to find the exports. The to be loaded module should be linked as follows (if using AIX 3): cc -o module.so -bM:SRE -bE:module.exp -e _nostart $(OBJS) For AIX 4: cc -o module.so -bM:SRE -bE:module.exp -bnoentry $(OBJS) If you want to reference symbols from the main part of the program in a loaded module, you will have to link against the export file of the main part: cc -o main -bE:main.exp $(MAIN_OBJS) cc -o module.so -bM:SRE -bI:main.exp -bE:module.exp -bnoentry $(OBJS) Note that you explicitely have to specify what functions are supposed to be accessible from your loaded modules, this is different from SunOS/System V.4 where any global is automatically exported. If you want to export all globals, the following script might be of help: #!/bin/sh /usr/ucb/nm -g $* | awk '$2 == "B" || $2 == "D" { print $3 }' The module export file contains the symbols to be exported. Because this library uses the loader section, the final module.so file can be stripped. C++ users should build their shared objects using the script makeC++SharedLib (part of the IBM C++ compiler), this will make sure that constructors and destructors for static and global objects will be called upon loading and unloading the module. GNU C++ users should use the -shared option to g++ to link the shared object: g++ -o module.so -shared $(OBJS) If the shared object does have permissions for anybody, the shared object will be loaded into the shared library segment and it will stay there even if the main application terminates. If you rebuild your shared object after a bugfix and you want to make sure that you really get the newest version you will have to use the "slibclean" command before starting the application again to garbage collect the shared library segment. If the performance utilities (bosperf) are installed you can use the following command to see what shared objects are loaded: /usr/lpp/bosperf/genkld | sort | uniq For easier debugging you can avoid loading the shared object into the shared library segment alltogether by removing permissions for others from the module.so file: chmod o-rwx module.so This will ensure you get a fresh copy of the shared object for every dlopen() call which is loaded into the application's data segment. Usage ----- void *dlopen(const char *path, int mode); This routine loads the module pointed to by path and reads its export table. If the path does not contain a '/' character, dlopen will search for the module using the LIBPATH environment variable. It returns an opaque handle to the module or NULL on error. The mode parameter can be either RTLD_LAZY (for lazy function binding) or RTLD_NOW for immediate function binding. The AIX implementation currently does treat RTLD_NOW the same as RTLD_LAZY. The flag RTLD_GLOBAL might be or'ed into the mode parameter to allow loaded modules to bind to global variables or functions in other loaded modules loaded by dlopen(). If RTLD_GLOBAL is not specified, only globals from the main part of the executable or shared libraries are used to look for undefined symbols in loaded modules. void *dlsym(void *handle, const char *symbol); This routine searches for the symbol in the module referred to by handle and returns its address. If the symbol could not be found, the function returns NULL. The return value must be casted to a proper function pointer before it can be used. SunOS/System V.4 allows handle to be a NULL pointer to refer to the module the call is made from, this is not implemented. int dlclose(void *handle); This routine unloads the module referred to by the handle and disposes of any local storage. this function returns -1 on failure. Any function pointers obtained through dlsym() should be considered invalid after closing a module. As AIX caches shared objects in the shared library segment, function pointers obtained through dlsym() might still work even though the module has been unloaded. This can introduce subtle bugs that will segment fault later if AIX garbage collects or immediatly on SunOS/System V.4 as the text segment is unmapped. char *dlerror(void); This routine can be used to retrieve a text message describing the most recent error that occured on on of the above routines. This function returns NULL if there is no error information. Initialization and termination handlers --------------------------------------- The emulation provides for an initialization and a termination handler. The dlfcn.h file contains a structure declaration named dl_info with following members: void (*init)(void); void (*fini)(void); The init function is called upon first referencing the library. The fini function is called at dlclose() time or when the process exits. The module should declare a variable named dl_info that contains this structure which must be exported. These functions correspond to the documented _init() and _fini() functions of SunOS 4.x, but these are appearently not implemented in SunOS. When using SunOS 5.0, these correspond to #pragma init and #pragma fini respectively. At the same time any static or global C++ object's constructors or destructors will be called. BUGS ---- Please note that there is currently a problem with implicitely loaded shared C++ libaries: if you refer to a shared C++ library from a loaded module that is not yet used by the main program, the dlopen() emulator does not notice this and does not call the static constructors for the implicitely loaded library. This can be easily demonstrated by referencing the C++ standard streams from a loaded module if the main program is a plain C program. Jens-Uwe Mager HELIOS Software GmbH Lavesstr. 80 30159 Hannover Germany Phone: +49 511 36482-0 FAX: +49 511 36482-69 AppleLink: helios.de/jum Internet: jum@helios.de Revison History --------------- SCCS/s.dlfcn.h: D 1.4 95/04/25 09:36:52 jum 4 3 00018/00004/00028 MRs: COMMENTS: added RTLD_GLOBAL, include and C++ guards D 1.3 92/12/27 20:58:32 jum 3 2 00001/00001/00031 MRs: COMMENTS: we always have prototypes on RS/6000 D 1.2 92/08/16 17:45:11 jum 2 1 00009/00000/00023 MRs: COMMENTS: added dl_info structure to implement initialize and terminate functions D 1.1 92/08/02 18:08:45 jum 1 0 00023/00000/00000 MRs: COMMENTS: Erstellungsdatum und -uhrzeit 92/08/02 18:08:45 von jum SCCS/s.dlfcn.c: D 1.11 96/04/10 20:12:51 jum 13 12 00037/00000/00533 MRs: COMMENTS: Integrated the changes from John W. Eaton to initialize g++ generated shared objects. D 1.10 96/02/15 17:42:44 jum 12 10 00012/00007/00521 MRs: COMMENTS: the C++ constructor and destructor chains are now called properly for either xlC 2 or xlC 3 (CSet++). D 1.9 95/09/22 11:09:38 markus 10 9 00001/00008/00527 MRs: COMMENTS: Fix version number D 1.8 95/09/22 10:14:34 markus 9 8 00008/00001/00527 MRs: COMMENTS: Added version number for dl lib D 1.7 95/08/14 19:08:38 jum 8 6 00026/00004/00502 MRs: COMMENTS: Integrated the fixes from Kirk Benell (kirk@rsinc.com) to allow loading of shared objects generated under AIX 4. Fixed bug that symbols with exactly 8 characters would use garbage characters from the following symbol value. D 1.6 95/04/25 09:38:03 jum 6 5 00046/00006/00460 MRs: COMMENTS: added handling of C++ static constructors and destructors, added RTLD_GLOBAL to bind against other loaded modules D 1.5 93/02/14 20:14:17 jum 5 4 00002/00000/00464 MRs: COMMENTS: added path to dlopen error message to make clear where there error occured. D 1.4 93/01/03 19:13:56 jum 4 3 00061/00005/00403 MRs: COMMENTS: to allow calling symbols in the main module call load with L_NOAUTODEFER and do a loadbind later with the main module. D 1.3 92/12/27 20:59:55 jum 3 2 00066/00008/00342 MRs: COMMENTS: added search by L_GETINFO if module got loaded by LIBPATH D 1.2 92/08/16 17:45:43 jum 2 1 00074/00006/00276 MRs: COMMENTS: implemented initialize and terminate functions, added reference counting to avoid multiple loads of the same library D 1.1 92/08/02 18:08:45 jum 1 0 00282/00000/00000 MRs: COMMENTS: Erstellungsdatum und -uhrzeit 92/08/02 18:08:45 von jum