Remove dlfcn implementation for AIX since nowadays AIX have dlopen()
Also drop license and copyright statement
This commit is contained in:
		| @@ -409,23 +409,6 @@ Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge. | ||||
| (GEnie : OUTER; CIS : [71755,204]) Graven Imagery, 1992. | ||||
|  | ||||
|  | ||||
| @end verbatim | ||||
| @copynext | ||||
|  | ||||
| @heading Jens-Uwe Mager, Helios Software GmbH | ||||
|  | ||||
| AIX dlfcn in libkafs | ||||
|  | ||||
| @verbatim | ||||
|  | ||||
| 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. | ||||
|  | ||||
| @end verbatim | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -24,11 +24,7 @@ AFS_EXTRA_LD = -e _nostart | ||||
| endif | ||||
|  | ||||
| if AIX_DYNAMIC_AFS | ||||
| if HAVE_DLOPEN | ||||
| AIX_SRC =  | ||||
| else | ||||
| AIX_SRC = dlfcn.c | ||||
| endif | ||||
| AFS_EXTRA_LIBS = afslib.so | ||||
| AFS_EXTRA_DEFS = | ||||
| else | ||||
| @@ -73,9 +69,9 @@ dist_libkafs_la_SOURCES =			\ | ||||
|  | ||||
| nodist_libkafs_la_SOURCES = $(ROKEN_SRCS) | ||||
|  | ||||
| EXTRA_libkafs_la_SOURCES = afskrb5.c dlfcn.c afslib.c dlfcn.h | ||||
| EXTRA_libkafs_la_SOURCES = afskrb5.c afslib.c | ||||
|  | ||||
| EXTRA_DIST = README.dlfcn afsl.exp afslib.exp $(man_MANS) | ||||
| EXTRA_DIST = afsl.exp afslib.exp $(man_MANS) | ||||
|  | ||||
| man_MANS = kafs.3 | ||||
|  | ||||
|   | ||||
| @@ -1,246 +0,0 @@ | ||||
| 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 <jwe@bevo.che.wisc.edu> 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 | ||||
|  | ||||
							
								
								
									
										584
									
								
								lib/kafs/dlfcn.c
									
									
									
									
									
								
							
							
						
						
									
										584
									
								
								lib/kafs/dlfcn.c
									
									
									
									
									
								
							| @@ -1,584 +0,0 @@ | ||||
| /* | ||||
|  * See README.dlfcn for license | ||||
|  */ | ||||
| /* | ||||
|  * @(#)dlfcn.c	1.11 revision of 96/04/10  20:12:51 | ||||
|  * This is an unpublished work copyright (c) 1992 HELIOS Software GmbH | ||||
|  * 30159 Hannover, Germany | ||||
|  */ | ||||
|  | ||||
| /* | ||||
|  * Changes marked with `--jwe' were made on April 7 1996 by John W. Eaton | ||||
|  * <jwe@bevo.che.wisc.edu> to support g++ and/or use with Octave. | ||||
|  */ | ||||
|  | ||||
| /* | ||||
|  * This makes my life easier with Octave.  --jwe | ||||
|  */ | ||||
| #ifdef HAVE_CONFIG_H | ||||
| #include <config.h> | ||||
| #endif | ||||
|  | ||||
| #include <stdio.h> | ||||
| #include <errno.h> | ||||
| #include <string.h> | ||||
| #include <stdlib.h> | ||||
| #include <sys/types.h> | ||||
| #include <sys/ldr.h> | ||||
| #include <a.out.h> | ||||
| #include <ldfcn.h> | ||||
| #include "dlfcn.h" | ||||
|  | ||||
| /* | ||||
|  * We simulate dlopen() et al. through a call to load. Because AIX has | ||||
|  * no call to find an exported symbol we read the loader section of the | ||||
|  * loaded module and build a list of exported symbols and their virtual | ||||
|  * address. | ||||
|  */ | ||||
|  | ||||
| typedef struct { | ||||
| 	char		*name;		/* the symbols's name */ | ||||
| 	void		*addr;		/* its relocated virtual address */ | ||||
| } Export, *ExportPtr; | ||||
|  | ||||
| /* | ||||
|  * xlC uses the following structure to list its constructors and | ||||
|  * destructors. This is gleaned from the output of munch. | ||||
|  */ | ||||
| typedef struct { | ||||
| 	void (*init)(void);		/* call static constructors */ | ||||
| 	void (*term)(void);		/* call static destructors */ | ||||
| } Cdtor, *CdtorPtr; | ||||
|  | ||||
| typedef void (*GccCDtorPtr)(void); | ||||
|  | ||||
| /* | ||||
|  * The void * handle returned from dlopen is actually a ModulePtr. | ||||
|  */ | ||||
| typedef struct Module { | ||||
| 	struct Module	*next; | ||||
| 	char		*name;		/* module name for refcounting */ | ||||
| 	int		refCnt;		/* the number of references */ | ||||
| 	void		*entry;		/* entry point from load */ | ||||
| 	struct dl_info	*info;		/* optional init/terminate functions */ | ||||
| 	CdtorPtr	cdtors;		/* optional C++ constructors */ | ||||
| 	GccCDtorPtr	gcc_ctor;	/* g++ constructors  --jwe */ | ||||
| 	GccCDtorPtr	gcc_dtor;	/* g++ destructors  --jwe */ | ||||
| 	int		nExports;	/* the number of exports found */ | ||||
| 	ExportPtr	exports;	/* the array of exports */ | ||||
| } Module, *ModulePtr; | ||||
|  | ||||
| /* | ||||
|  * We keep a list of all loaded modules to be able to call the fini | ||||
|  * handlers and destructors at atexit() time. | ||||
|  */ | ||||
| static ModulePtr modList; | ||||
|  | ||||
| /* | ||||
|  * The last error from one of the dl* routines is kept in static | ||||
|  * variables here. Each error is returned only once to the caller. | ||||
|  */ | ||||
| static char errbuf[BUFSIZ]; | ||||
| static int errvalid; | ||||
|  | ||||
| /* | ||||
|  * The `fixed' gcc header files on AIX 3.2.5 provide a prototype for | ||||
|  * strdup().  --jwe | ||||
|  */ | ||||
| #ifndef HAVE_STRDUP | ||||
| extern char *strdup(const char *); | ||||
| #endif | ||||
| static void caterr(char *); | ||||
| static int readExports(ModulePtr); | ||||
| static void terminate(void); | ||||
| static void *findMain(void); | ||||
|  | ||||
| void *dlopen(const char *path, int mode) | ||||
| { | ||||
| 	ModulePtr mp; | ||||
| 	static void *mainModule; | ||||
|  | ||||
| 	/* | ||||
| 	 * Upon the first call register a terminate handler that will | ||||
| 	 * close all libraries. Also get a reference to the main module | ||||
| 	 * for use with loadbind. | ||||
| 	 */ | ||||
| 	if (!mainModule) { | ||||
| 		if ((mainModule = findMain()) == NULL) | ||||
| 			return NULL; | ||||
| 		atexit(terminate); | ||||
| 	} | ||||
| 	/* | ||||
| 	 * Scan the list of modules if we have the module already loaded. | ||||
| 	 */ | ||||
| 	for (mp = modList; mp; mp = mp->next) | ||||
| 		if (strcmp(mp->name, path) == 0) { | ||||
| 			mp->refCnt++; | ||||
| 			return mp; | ||||
| 		} | ||||
| 	if ((mp = (ModulePtr)calloc(1, sizeof(*mp))) == NULL) { | ||||
| 		errvalid++; | ||||
| 		snprintf (errbuf, sizeof(errbuf), "calloc: %s", strerror(errno)); | ||||
| 		return NULL; | ||||
| 	} | ||||
| 	if ((mp->name = strdup(path)) == NULL) { | ||||
| 		errvalid++; | ||||
| 		snprintf (errbuf, sizeof(errbuf), "strdup: %s", strerror(errno)); | ||||
| 		free(mp); | ||||
| 		return NULL; | ||||
| 	} | ||||
| 	/* | ||||
| 	 * load should be declared load(const char *...). Thus we | ||||
| 	 * cast the path to a normal char *. Ugly. | ||||
| 	 */ | ||||
| 	if ((mp->entry = (void *)load((char *)path, L_NOAUTODEFER, NULL)) == NULL) { | ||||
| 		free(mp->name); | ||||
| 		free(mp); | ||||
| 		errvalid++; | ||||
| 		snprintf (errbuf, sizeof(errbuf), | ||||
| 			  "dlopen: %s: ", path); | ||||
| 		/* | ||||
| 		 * If AIX says the file is not executable, the error | ||||
| 		 * can be further described by querying the loader about | ||||
| 		 * the last error. | ||||
| 		 */ | ||||
| 		if (errno == ENOEXEC) { | ||||
| 			char *tmp[BUFSIZ/sizeof(char *)]; | ||||
| 			if (loadquery(L_GETMESSAGES, tmp, sizeof(tmp)) == -1) | ||||
| 				strlcpy(errbuf, | ||||
| 						strerror(errno), | ||||
| 						sizeof(errbuf)); | ||||
| 			else { | ||||
| 				char **p; | ||||
| 				for (p = tmp; *p; p++) | ||||
| 					caterr(*p); | ||||
| 			} | ||||
| 		} else | ||||
| 			strlcat(errbuf, | ||||
| 					strerror(errno), | ||||
| 					sizeof(errbuf)); | ||||
| 		return NULL; | ||||
| 	} | ||||
| 	mp->refCnt = 1; | ||||
| 	mp->next = modList; | ||||
| 	modList = mp; | ||||
| 	if (loadbind(0, mainModule, mp->entry) == -1) { | ||||
| 		dlclose(mp); | ||||
| 		errvalid++; | ||||
| 		snprintf (errbuf, sizeof(errbuf), | ||||
| 			  "loadbind: %s", strerror(errno)); | ||||
| 		return NULL; | ||||
| 	} | ||||
| 	/* | ||||
| 	 * If the user wants global binding, loadbind against all other | ||||
| 	 * loaded modules. | ||||
| 	 */ | ||||
| 	if (mode & RTLD_GLOBAL) { | ||||
| 		ModulePtr mp1; | ||||
| 		for (mp1 = mp->next; mp1; mp1 = mp1->next) | ||||
| 			if (loadbind(0, mp1->entry, mp->entry) == -1) { | ||||
| 				dlclose(mp); | ||||
| 				errvalid++; | ||||
| 				snprintf (errbuf, sizeof(errbuf), | ||||
| 					  "loadbind: %s", | ||||
| 					  strerror(errno)); | ||||
| 				return NULL; | ||||
| 			} | ||||
| 	} | ||||
| 	if (readExports(mp) == -1) { | ||||
| 		dlclose(mp); | ||||
| 		return NULL; | ||||
| 	} | ||||
| 	/* | ||||
| 	 * If there is a dl_info structure, call the init function. | ||||
| 	 */ | ||||
| 	if (mp->info = (struct dl_info *)dlsym(mp, "dl_info")) { | ||||
| 		if (mp->info->init) | ||||
| 			(*mp->info->init)(); | ||||
| 	} else | ||||
| 		errvalid = 0; | ||||
| 	/* | ||||
| 	 * If the shared object was compiled using xlC we will need | ||||
| 	 * to call static constructors (and later on dlclose destructors). | ||||
| 	 */ | ||||
| 	if (mp->cdtors = (CdtorPtr)dlsym(mp, "__cdtors")) { | ||||
| 		CdtorPtr cp = mp->cdtors; | ||||
| 		while (cp->init || cp->term) { | ||||
| 			if (cp->init && cp->init != (void (*)(void))0xffffffff) | ||||
| 				(*cp->init)(); | ||||
| 			cp++; | ||||
| 		} | ||||
| 	/* | ||||
| 	 * If the shared object was compiled using g++, we will need | ||||
| 	 * to call global constructors using the _GLOBAL__DI function, | ||||
| 	 * and later, global destructors using the _GLOBAL_DD | ||||
| 	 * funciton.  --jwe | ||||
| 	 */ | ||||
| 	} else if (mp->gcc_ctor = (GccCDtorPtr)dlsym(mp, "_GLOBAL__DI")) { | ||||
| 		(*mp->gcc_ctor)(); | ||||
| 		mp->gcc_dtor = (GccCDtorPtr)dlsym(mp, "_GLOBAL__DD"); | ||||
| 	} else | ||||
| 		errvalid = 0; | ||||
| 	return mp; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Attempt to decipher an AIX loader error message and append it | ||||
|  * to our static error message buffer. | ||||
|  */ | ||||
| static void caterr(char *s) | ||||
| { | ||||
| 	char *p = s; | ||||
|  | ||||
| 	while (*p >= '0' && *p <= '9') | ||||
| 		p++; | ||||
| 	switch(atoi(s)) { | ||||
| 	case L_ERROR_TOOMANY: | ||||
| 		strlcat(errbuf, "to many errors", sizeof(errbuf)); | ||||
| 		break; | ||||
| 	case L_ERROR_NOLIB: | ||||
| 		strlcat(errbuf, "can't load library", sizeof(errbuf)); | ||||
| 		strlcat(errbuf, p, sizeof(errbuf)); | ||||
| 		break; | ||||
| 	case L_ERROR_UNDEF: | ||||
| 		strlcat(errbuf, "can't find symbol", sizeof(errbuf)); | ||||
| 		strlcat(errbuf, p, sizeof(errbuf)); | ||||
| 		break; | ||||
| 	case L_ERROR_RLDBAD: | ||||
| 		strlcat(errbuf, "bad RLD", sizeof(errbuf)); | ||||
| 		strlcat(errbuf, p, sizeof(errbuf)); | ||||
| 		break; | ||||
| 	case L_ERROR_FORMAT: | ||||
| 		strlcat(errbuf, "bad exec format in", sizeof(errbuf)); | ||||
| 		strlcat(errbuf, p, sizeof(errbuf)); | ||||
| 		break; | ||||
| 	case L_ERROR_ERRNO: | ||||
| 		strlcat(errbuf, strerror(atoi(++p)), sizeof(errbuf)); | ||||
| 		break; | ||||
| 	default: | ||||
| 		strlcat(errbuf, s, sizeof(errbuf)); | ||||
| 		break; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void *dlsym(void *handle, const char *symbol) | ||||
| { | ||||
| 	ModulePtr mp = (ModulePtr)handle; | ||||
| 	ExportPtr ep; | ||||
| 	int i; | ||||
|  | ||||
| 	/* | ||||
| 	 * Could speed up the search, but I assume that one assigns | ||||
| 	 * the result to function pointers anyways. | ||||
| 	 */ | ||||
| 	for (ep = mp->exports, i = mp->nExports; i; i--, ep++) | ||||
| 		if (strcmp(ep->name, symbol) == 0) | ||||
| 			return ep->addr; | ||||
| 	errvalid++; | ||||
| 	snprintf (errbuf, sizeof(errbuf), | ||||
| 		  "dlsym: undefined symbol %s", symbol);		 | ||||
| 	return NULL; | ||||
| } | ||||
|  | ||||
| char *dlerror(void) | ||||
| { | ||||
| 	if (errvalid) { | ||||
| 		errvalid = 0; | ||||
| 		return errbuf; | ||||
| 	} | ||||
| 	return NULL; | ||||
| } | ||||
|  | ||||
| int dlclose(void *handle) | ||||
| { | ||||
| 	ModulePtr mp = (ModulePtr)handle; | ||||
| 	int result; | ||||
| 	ModulePtr mp1; | ||||
|  | ||||
| 	if (--mp->refCnt > 0) | ||||
| 		return 0; | ||||
| 	if (mp->info && mp->info->fini) | ||||
| 		(*mp->info->fini)(); | ||||
| 	if (mp->cdtors) { | ||||
| 		CdtorPtr cp = mp->cdtors; | ||||
| 		while (cp->init || cp->term) { | ||||
| 			if (cp->term && cp->init != (void (*)(void))0xffffffff) | ||||
| 				(*cp->term)(); | ||||
| 			cp++; | ||||
| 		} | ||||
| 	/* | ||||
| 	 * If the function to handle global destructors for g++ | ||||
| 	 * exists, call it.  --jwe | ||||
| 	 */ | ||||
| 	} else if (mp->gcc_dtor) { | ||||
| 	        (*mp->gcc_dtor)(); | ||||
| 	} | ||||
| 	result = unload(mp->entry); | ||||
| 	if (result == -1) { | ||||
| 		errvalid++; | ||||
| 		snprintf (errbuf, sizeof(errbuf), | ||||
| 			  "%s", strerror(errno)); | ||||
| 	} | ||||
| 	if (mp->exports) { | ||||
| 		ExportPtr ep; | ||||
| 		int i; | ||||
| 		for (ep = mp->exports, i = mp->nExports; i; i--, ep++) | ||||
| 			if (ep->name) | ||||
| 				free(ep->name); | ||||
| 		free(mp->exports); | ||||
| 	} | ||||
| 	if (mp == modList) | ||||
| 		modList = mp->next; | ||||
| 	else { | ||||
| 		for (mp1 = modList; mp1; mp1 = mp1->next) | ||||
| 			if (mp1->next == mp) { | ||||
| 				mp1->next = mp->next; | ||||
| 				break; | ||||
| 			} | ||||
| 	} | ||||
| 	free(mp->name); | ||||
| 	free(mp); | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
| static void terminate(void) | ||||
| { | ||||
| 	while (modList) | ||||
| 		dlclose(modList); | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Build the export table from the XCOFF .loader section. | ||||
|  */ | ||||
| static int readExports(ModulePtr mp) | ||||
| { | ||||
| 	LDFILE *ldp = NULL; | ||||
| 	SCNHDR sh, shdata; | ||||
| 	LDHDR *lhp; | ||||
| 	char *ldbuf; | ||||
| 	LDSYM *ls; | ||||
| 	int i; | ||||
| 	ExportPtr ep; | ||||
|  | ||||
| 	if ((ldp = ldopen(mp->name, ldp)) == NULL) { | ||||
| 		struct ld_info *lp; | ||||
| 		char *buf; | ||||
| 		int size = 4*1024; | ||||
| 		if (errno != ENOENT) { | ||||
| 			errvalid++; | ||||
| 			snprintf(errbuf, sizeof(errbuf), | ||||
| 				 "readExports: %s", | ||||
| 				 strerror(errno)); | ||||
| 			return -1; | ||||
| 		} | ||||
| 		/* | ||||
| 		 * The module might be loaded due to the LIBPATH | ||||
| 		 * environment variable. Search for the loaded | ||||
| 		 * module using L_GETINFO. | ||||
| 		 */ | ||||
| 		if ((buf = malloc(size)) == NULL) { | ||||
| 			errvalid++; | ||||
| 			snprintf(errbuf, sizeof(errbuf), | ||||
| 				 "readExports: %s", | ||||
| 				 strerror(errno)); | ||||
| 			return -1; | ||||
| 		} | ||||
| 		while ((i = loadquery(L_GETINFO, buf, size)) == -1 && errno == ENOMEM) { | ||||
| 			free(buf); | ||||
| 			size += 4*1024; | ||||
| 			if ((buf = malloc(size)) == NULL) { | ||||
| 				errvalid++; | ||||
| 				snprintf(errbuf, sizeof(errbuf), | ||||
| 					 "readExports: %s", | ||||
| 					 strerror(errno)); | ||||
| 				return -1; | ||||
| 			} | ||||
| 		} | ||||
| 		if (i == -1) { | ||||
| 			errvalid++; | ||||
| 			snprintf(errbuf, sizeof(errbuf), | ||||
| 				 "readExports: %s", | ||||
| 				 strerror(errno)); | ||||
| 			free(buf); | ||||
| 			return -1; | ||||
| 		} | ||||
| 		/* | ||||
| 		 * Traverse the list of loaded modules. The entry point | ||||
| 		 * returned by load() does actually point to the data | ||||
| 		 * segment origin. | ||||
| 		 */ | ||||
| 		lp = (struct ld_info *)buf; | ||||
| 		while (lp) { | ||||
| 			if (lp->ldinfo_dataorg == mp->entry) { | ||||
| 				ldp = ldopen(lp->ldinfo_filename, ldp); | ||||
| 				break; | ||||
| 			} | ||||
| 			if (lp->ldinfo_next == 0) | ||||
| 				lp = NULL; | ||||
| 			else | ||||
| 				lp = (struct ld_info *)((char *)lp + lp->ldinfo_next); | ||||
| 		} | ||||
| 		free(buf); | ||||
| 		if (!ldp) { | ||||
| 			errvalid++; | ||||
| 			snprintf (errbuf, sizeof(errbuf), | ||||
| 				  "readExports: %s", strerror(errno)); | ||||
| 			return -1; | ||||
| 		} | ||||
| 	} | ||||
| 	if (TYPE(ldp) != U802TOCMAGIC) { | ||||
| 		errvalid++; | ||||
| 		snprintf(errbuf, sizeof(errbuf), "readExports: bad magic"); | ||||
| 		while(ldclose(ldp) == FAILURE) | ||||
| 			; | ||||
| 		return -1; | ||||
| 	} | ||||
| 	/* | ||||
| 	 * Get the padding for the data section. This is needed for | ||||
| 	 * AIX 4.1 compilers. This is used when building the final | ||||
| 	 * function pointer to the exported symbol. | ||||
| 	 */ | ||||
| 	if (ldnshread(ldp, _DATA, &shdata) != SUCCESS) { | ||||
| 		errvalid++; | ||||
| 		snprintf(errbuf, sizeof(errbuf), | ||||
| 			 "readExports: cannot read data section header"); | ||||
| 		while(ldclose(ldp) == FAILURE) | ||||
| 			; | ||||
| 		return -1; | ||||
| 	} | ||||
| 	if (ldnshread(ldp, _LOADER, &sh) != SUCCESS) { | ||||
| 		errvalid++; | ||||
| 		snprintf(errbuf, sizeof(errbuf), | ||||
| 			 "readExports: cannot read loader section header"); | ||||
| 		while(ldclose(ldp) == FAILURE) | ||||
| 			; | ||||
| 		return -1; | ||||
| 	} | ||||
| 	/* | ||||
| 	 * We read the complete loader section in one chunk, this makes | ||||
| 	 * finding long symbol names residing in the string table easier. | ||||
| 	 */ | ||||
| 	if ((ldbuf = (char *)malloc(sh.s_size)) == NULL) { | ||||
| 		errvalid++; | ||||
| 		snprintf (errbuf, sizeof(errbuf), | ||||
| 			  "readExports: %s", strerror(errno)); | ||||
| 		while(ldclose(ldp) == FAILURE) | ||||
| 			; | ||||
| 		return -1; | ||||
| 	} | ||||
| 	if (FSEEK(ldp, sh.s_scnptr, BEGINNING) != OKFSEEK) { | ||||
| 		errvalid++; | ||||
| 		snprintf(errbuf, sizeof(errbuf), | ||||
| 			 "readExports: cannot seek to loader section"); | ||||
| 		free(ldbuf); | ||||
| 		while(ldclose(ldp) == FAILURE) | ||||
| 			; | ||||
| 		return -1; | ||||
| 	} | ||||
| 	if (FREAD(ldbuf, sh.s_size, 1, ldp) != 1) { | ||||
| 		errvalid++; | ||||
| 		snprintf(errbuf, sizeof(errbuf), | ||||
| 			 "readExports: cannot read loader section"); | ||||
| 		free(ldbuf); | ||||
| 		while(ldclose(ldp) == FAILURE) | ||||
| 			; | ||||
| 		return -1; | ||||
| 	} | ||||
| 	lhp = (LDHDR *)ldbuf; | ||||
| 	ls = (LDSYM *)(ldbuf+LDHDRSZ); | ||||
| 	/* | ||||
| 	 * Count the number of exports to include in our export table. | ||||
| 	 */ | ||||
| 	for (i = lhp->l_nsyms; i; i--, ls++) { | ||||
| 		if (!LDR_EXPORT(*ls)) | ||||
| 			continue; | ||||
| 		mp->nExports++; | ||||
| 	} | ||||
| 	if ((mp->exports = (ExportPtr)calloc(mp->nExports, sizeof(*mp->exports))) == NULL) { | ||||
| 		errvalid++; | ||||
| 		snprintf (errbuf, sizeof(errbuf), | ||||
| 			  "readExports: %s", strerror(errno)); | ||||
| 		free(ldbuf); | ||||
| 		while(ldclose(ldp) == FAILURE) | ||||
| 			; | ||||
| 		return -1; | ||||
| 	} | ||||
| 	/* | ||||
| 	 * Fill in the export table. All entries are relative to | ||||
| 	 * the entry point we got from load. | ||||
| 	 */ | ||||
| 	ep = mp->exports; | ||||
| 	ls = (LDSYM *)(ldbuf+LDHDRSZ); | ||||
| 	for (i = lhp->l_nsyms; i; i--, ls++) { | ||||
| 		char *symname; | ||||
| 		char tmpsym[SYMNMLEN+1]; | ||||
| 		if (!LDR_EXPORT(*ls)) | ||||
| 			continue; | ||||
| 		if (ls->l_zeroes == 0) | ||||
| 			symname = ls->l_offset+lhp->l_stoff+ldbuf; | ||||
| 		else { | ||||
| 			/* | ||||
| 			 * The l_name member is not zero terminated, we | ||||
| 			 * must copy the first SYMNMLEN chars and make | ||||
| 			 * sure we have a zero byte at the end. | ||||
| 			 */ | ||||
| 		        strlcpy (tmpsym, ls->l_name, | ||||
| 					 SYMNMLEN + 1); | ||||
| 			symname = tmpsym; | ||||
| 		} | ||||
| 		ep->name = strdup(symname); | ||||
| 		ep->addr = (void *)((unsigned long)mp->entry + | ||||
| 					ls->l_value - shdata.s_vaddr); | ||||
| 		ep++; | ||||
| 	} | ||||
| 	free(ldbuf); | ||||
| 	while(ldclose(ldp) == FAILURE) | ||||
| 		; | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Find the main modules entry point. This is used as export pointer | ||||
|  * for loadbind() to be able to resolve references to the main part. | ||||
|  */ | ||||
| static void * findMain(void) | ||||
| { | ||||
| 	struct ld_info *lp; | ||||
| 	char *buf; | ||||
| 	int size = 4*1024; | ||||
| 	int i; | ||||
| 	void *ret; | ||||
|  | ||||
| 	if ((buf = malloc(size)) == NULL) { | ||||
| 		errvalid++; | ||||
| 		snprintf (errbuf, sizeof(errbuf), | ||||
| 			  "findMail: %s", strerror(errno)); | ||||
| 		return NULL; | ||||
| 	} | ||||
| 	while ((i = loadquery(L_GETINFO, buf, size)) == -1 && errno == ENOMEM) { | ||||
| 		free(buf); | ||||
| 		size += 4*1024; | ||||
| 		if ((buf = malloc(size)) == NULL) { | ||||
| 			errvalid++; | ||||
| 			snprintf (errbuf, sizeof(errbuf), | ||||
| 				  "findMail: %s", strerror(errno)); | ||||
| 			return NULL; | ||||
| 		} | ||||
| 	} | ||||
| 	if (i == -1) { | ||||
| 		errvalid++; | ||||
| 		snprintf (errbuf, sizeof(errbuf), | ||||
| 			  "findMail: %s", strerror(errno)); | ||||
| 		free(buf); | ||||
| 		return NULL; | ||||
| 	} | ||||
| 	/* | ||||
| 	 * The first entry is the main module. The entry point | ||||
| 	 * returned by load() does actually point to the data | ||||
| 	 * segment origin. | ||||
| 	 */ | ||||
| 	lp = (struct ld_info *)buf; | ||||
| 	ret = lp->ldinfo_dataorg; | ||||
| 	free(buf); | ||||
| 	return ret; | ||||
| } | ||||
| @@ -1,49 +0,0 @@ | ||||
| /* | ||||
|  * See README.dlfcn for license | ||||
|  */ | ||||
| /* | ||||
|  * @(#)dlfcn.h	1.4 revision of 95/04/25  09:36:52 | ||||
|  * This is an unpublished work copyright (c) 1992 HELIOS Software GmbH | ||||
|  * 30159 Hannover, Germany | ||||
|  */ | ||||
|  | ||||
| #ifndef __dlfcn_h__ | ||||
| #define __dlfcn_h__ | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
|  | ||||
| /* | ||||
|  * Mode flags for the dlopen routine. | ||||
|  */ | ||||
| #define RTLD_LAZY	1	/* lazy function call binding */ | ||||
| #define RTLD_NOW	2	/* immediate function call binding */ | ||||
| #define RTLD_GLOBAL	0x100	/* allow symbols to be global */ | ||||
|  | ||||
| /* | ||||
|  * To be able to initialize, a library may provide a dl_info structure | ||||
|  * that contains functions to be called to initialize and terminate. | ||||
|  */ | ||||
| struct dl_info { | ||||
| 	void (*init)(void); | ||||
| 	void (*fini)(void); | ||||
| }; | ||||
|  | ||||
| #if __STDC__ || defined(_IBMR2) | ||||
| void *dlopen(const char *path, int mode); | ||||
| void *dlsym(void *handle, const char *symbol); | ||||
| char *dlerror(void); | ||||
| int dlclose(void *handle); | ||||
| #else | ||||
| void *dlopen(); | ||||
| void *dlsym(); | ||||
| char *dlerror(); | ||||
| int dlclose(); | ||||
| #endif | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
|  | ||||
| #endif /* __dlfcn_h__ */ | ||||
		Reference in New Issue
	
	Block a user
	 Love Hornquist Astrand
					Love Hornquist Astrand