home *** CD-ROM | disk | FTP | other *** search
- /*
- *
- * d y n l o a d . c -- All the stuff dealing with
- * dynamic loading
- *
- * Copyright ⌐ 1993-1996 Erick Gallesio - I3S-CNRS/ESSI <eg@unice.fr>
- *
- *
- * Permission to use, copy, and/or distribute this software and its
- * documentation for any purpose and without fee is hereby granted, provided
- * that both the above copyright notice and this permission notice appear in
- * all copies and derived works. Fees for distribution or use of this
- * software or derived works may only be charged with express written
- * permission of the copyright holder.
- * This software is provided ``as is'' without express or implied warranty.
- *
- * This software is a derivative work of other copyrighted softwares; the
- * copyright notices of these softwares are placed in the file COPYRIGHTS
- *
- *
- * Author: Erick Gallesio [eg@kaolin.unice.fr]
- * Creation date: 23-Jan-1994 19:09
- * Last file update: 21-Jul-1996 21:24
- */
-
- /* Support for HPUX is due to Dipankar Gupta <dg@hplb.hpl.hp.com> */
- /* Support for NETBSD is from Franke Ruediger (Ruediger.Franke@rz.tu-ilmenau.de) */
- /* Support for FreeBsD is due to Amancio Hasty Jr (hasty@netcom.com) */
- /* Support for Linux is inspired from Patrick Nguyen (pnguyen@elde.epfl.ch) */
-
-
- #if defined(SUNOS4) || defined(SUNOS5) || defined(IRIX5) || defined(OSF1)
- #include <dlfcn.h>
- #endif
-
- #if defined(LINUX_DLD)
- #include <dld.h>
- #endif
-
- #if defined(NETBSD1)
- #include <sys/types.h>
- #include <nlist.h>
- #include <link.h>
- #define dlerror() "dlerror" /* dlerror() isn't implemented in NetBSD 1.0 */
- #endif
-
- #ifdef HPUX
- #include <dl.h>
- #endif
-
- #include "stk.h"
-
- #ifdef USE_DYNLOAD
- static SCM list_of_files = NULL;
-
- #if defined(SUNOS4) || defined(SUNOS5) || defined(NETBSD1) || defined(FREEBSD) || defined(IRIX5) || defined(OSF1) ||defined(LINUX_ELF)
-
- static void load_and_call(char *path, char *fct_name)
- {
- static void *self_handle= NULL;
- void *handle;
- void (*init_fct)();
- SCM str;
-
- /* Test if fct_name is already defined in the core interpreter
- /* Don't do a dlopen with NULL more than one time since it seems to break
- /* Solaris 2.3. (Moises Lejter <mlm@cs.brown.edu>) */
- if (self_handle == NULL)
- if ((self_handle = (void *) dlopen(NULL,1)) == NULL)
- Err("Cannot open myself !!!", NIL);
-
- if ((init_fct = (void (*)()) dlsym(self_handle, fct_name)) != NULL)
- Err("Module is already (statically) loaded", STk_makestring(path));
-
- /* Try to avoid multiple loading */
- if (!list_of_files) {
- STk_gc_protect(&list_of_files);
- list_of_files = NIL;
- }
- str = STk_makestring(path);
- if (STk_member(str, list_of_files) != Ntruth) {
- Err("Module is already (dynamically) loaded", str);
- }
-
- /* Load file */
- if ((handle = (void *) dlopen(path, 1)) == NULL) {
- char msg[MAX_PATH_LENGTH];
- #ifdef FREEBSD
- sprintf(msg, "Cannot open object file");
- #else
- sprintf(msg, "Cannot open object file (%s)", dlerror());
- #endif
- Err(msg, str);
- }
-
- if ((init_fct = (void (*)()) dlsym(handle, fct_name)) == NULL) {
- char msg[MAX_PATH_LENGTH];
-
- sprintf(msg, "Cannot find function \"%s\" in object file", fct_name);
- Err(msg, NIL);
- }
- /* Call the init code */
- (*init_fct)();
-
- list_of_files = Cons(str, list_of_files);
- }
- #endif
-
- #if defined(LINUX_DLD)
- /*
- * This code is for Linux, using the dld package. This code should not be used
- * anymore when ELF will be completely accepted under Linux. In the meanwhile...
- *
- * This code is inspired from a code sent by Patrick Nguyen pnguyen@elde.epfl.ch.
- *
- */
-
- static void load_and_call(char *path, char *fct_name)
- {
- void *handle;
- void (*init_fct)();
- SCM str;
- static dld_already_initialized = FALSE;
-
- /* Try to avoid multiple loading */
- if (!list_of_files) {
- STk_gc_protect(&list_of_files);
- list_of_files = NIL;
- }
- str = STk_makestring(path);
- if (STk_member(str, list_of_files) != Ntruth) {
- Err("Module is already (dynamically) loaded", str);
- }
-
- /* Dld must be initialized at first call */
- if(!dld_already_initialized) {
- if (dld_init (dld_find_executable (STk_Argv0)))
- dld_perror("dld: failed to init dld");
- else
- dld_already_initialized = TRUE;
- }
-
- /* Load file */
- if (dld_link(path)) dld_perror("dld: cannot link");
-
- /* And get a pointer on function "fct_name" */
- init_fct = (void (*) ()) dld_get_func(fct_name);
- if (init_fct) {
- /* When loading a function. It can induce some unresolved references
- * Most of the time, the unresolved references come from fucntions
- * which are in the libc but which are not used by the core interpreter.
- * For instance, if loaded module uses fork, which is not loaded in
- * the interpreter, we will have an unresolve reference for _fork.
- * To avoid this problem, we make again a link against standard libc
- * Note: in general situation is more complicated than this, unresolved
- * symbols could be elsewhere than the libc....
- * Those situation are not handled by current code, but I hope that ELF
- * will supplant this way of doing dynamic loading soon...
- */
- if (dld_function_executable_p (fct_name))
- /* Call the init code */
- (*init_fct) ();
- else {
- /* Function is notexecutable = we have unresolved references */
- if (dld_link("/usr/lib/libc.a") && dld_link("/usr/lib/libc.sa"))
- dld_perror("dld: cannot link");
-
- if (dld_function_executable_p (fct_name)) {
- init_fct = (void (*) ()) dld_get_func(fct_name);
- (*init_fct) ();
- }
- else {
- char **unresolved;
- extern int dld_undefined_sym_count;
- int i;
- fprintf(STk_stderr, "dld: function %s not executable!\n", fct_name);
- fprintf(STk_stderr, "Unresolved symbols are:\n");
-
- unresolved= dld_list_undefined_sym();
- for (i = 0; i < dld_undefined_sym_count; i++)
- fprintf(STk_stderr, "\t%s\n",unresolved[i]);
- free(unresolved);
- Err("dld: link aborted", NIL);
- }
- }
- }
- else {
- char msg[MAX_PATH_LENGTH];
- sprintf(msg, "Cannot find function \"%s\" in object file", fct_name);
- Err(msg, NIL);
- }
-
- list_of_files = Cons(str, list_of_files);
- }
- #endif /* LINUX_DLD */
-
- #ifdef HPUX
- static void load_and_call(char *path, char *fct_name)
- {
- shl_t handle;
- void (*init_fct)();
-
- if ((handle = shl_load(path, BIND_IMMEDIATE | BIND_VERBOSE, 0L)) == NULL)
- Err("Cannot open file", STk_makestring(path));
-
- handle = NULL;
- if (shl_findsym(&handle, fct_name, TYPE_PROCEDURE, &init_fct) == -1) {
- char msg[MAX_PATH_LENGTH];
-
- sprintf(msg, "Cannot find function %s in object file", fct_name);
- Err(msg, NIL);
- }
- /* Call the init code */
- (*init_fct)();
- }
- #endif
-
- void STk_load_object_file(char *path)
- {
- char fct_name[1024], *p, *slash, *dot;
-
- /* Load the file as an object one */
-
- for (p = path, slash = p-1; *p; p++) /* Find position of last '/' */
- if (*p == '/') slash = p;
-
- #if defined(NETBSD1) || defined(FREEBSD)
- sprintf(fct_name, "_STk_init_%s", slash + 1);
- #else
- sprintf(fct_name, "STk_init_%s", slash + 1);
- #endif
-
- for (p = fct_name; *p; p++) /* Delete suffix it it exists */
- if (*p == '.') { *p = '\0'; break; }
-
- load_and_call(path, fct_name);
- }
-
- #else /* not DYNLOAD */
- void STk_load_object_file(char *path)
- {
- Err("load: Loading of object file is not defined on this architecture", NIL);
- }
- #endif
-