e1195f1997-03-23Fredrik Hübinette (Hubbe) #ifndef TESTING # include "global.h" # include "interpret.h" # include "constants.h" # include "error.h" # include "module.h" # include "stralloc.h" # include "pike_macros.h"
6559821999-02-01Per Hedbor # include "main.h"
24ddc71998-03-28Henrik Grubbström (Grubba) 
5561812000-02-16Fredrik Hübinette (Hubbe) RCSID("$Id: dynamic_load.c,v 1.38 2000/02/17 00:32:42 hubbe Exp $");
24ddc71998-03-28Henrik Grubbström (Grubba) 
79f71c1998-07-09Francesco Chemolli #endif /* !TESTING */ #ifdef HAVE_ERRNO_H #include <errno.h> #endif /* HAVE_ERRNO_H */ #ifdef HAVE_STRING_H #include <string.h> #endif /* HAVE_STRING_H */
ca74dd1996-10-08Fredrik Hübinette (Hubbe) 
9649491998-02-27Fredrik Hübinette (Hubbe) #if !defined(HAVE_DLOPEN) #if defined(HAVE_DLD_LINK) && defined(HAVE_DLD_GET_FUNC)
7860031997-01-22Bernhard Fastenrath #define USE_DLD
9649491998-02-27Fredrik Hübinette (Hubbe) #define HAVE_SOME_DLOPEN #define EMULATE_DLOPEN #else
79f71c1998-07-09Francesco Chemolli #if defined(HAVE_SHL_LOAD) && defined(HAVE_DL_H) #define USE_HPUX_DL #define HAVE_SOME_DLOPEN #define EMULATE_DLOPEN #else
9649491998-02-27Fredrik Hübinette (Hubbe) #if defined(HAVE_LOADLIBRARY) && defined(HAVE_FREELIBRARY) && \ defined(HAVE_GETPROCADDRESS) && defined(HAVE_WINBASE_H) #define USE_LOADLIBRARY #define HAVE_SOME_DLOPEN #define EMULATE_DLOPEN #endif #endif
79f71c1998-07-09Francesco Chemolli #endif
9649491998-02-27Fredrik Hübinette (Hubbe) #else #define HAVE_SOME_DLOPEN
7860031997-01-22Bernhard Fastenrath #endif
9649491998-02-27Fredrik Hübinette (Hubbe)  #ifdef HAVE_SOME_DLOPEN
2631a61996-10-09Fredrik Hübinette (Hubbe) 
e1195f1997-03-23Fredrik Hübinette (Hubbe) typedef void (*modfun)(void);
9649491998-02-27Fredrik Hübinette (Hubbe) #ifdef USE_LOADLIBRARY #include <windows.h> static TCHAR *convert_string(char *str, int len) { int e; TCHAR *ret=(TCHAR *)xalloc((len+1) * sizeof(TCHAR)); for(e=0;e<len;e++) ret[e]=EXTRACT_UCHAR(str+e); ret[e]=0; return ret; }
01a9572000-02-03Henrik Grubbström (Grubba) static void *dlopen(const char *foo, int how)
9649491998-02-27Fredrik Hübinette (Hubbe) { TCHAR *tmp; HINSTANCE ret; tmp=convert_string(foo, strlen(foo)); ret=LoadLibrary(tmp); free((char *)tmp); return (void *)ret; } static char * dlerror(void) { static char buffer[200]; sprintf(buffer,"LoadLibrary failed with error: %d",GetLastError()); return buffer; } static void *dlsym(void *module, char * function) { return (void *)GetProcAddress((HMODULE)module, function); } static void dlclose(void *module) { FreeLibrary((HMODULE)module); } #define dlinit()
79f71c1998-07-09Francesco Chemolli #endif /* USE_LOADLIBRARY */
9649491998-02-27Fredrik Hübinette (Hubbe) 
e1195f1997-03-23Fredrik Hübinette (Hubbe) #ifdef USE_DLD #include <dld.h>
01a9572000-02-03Henrik Grubbström (Grubba) static void *dlopen(const char *module_name, int how)
e1195f1997-03-23Fredrik Hübinette (Hubbe) { dld_create_reference("pike_module_init"); if(dld_link(module_name)) { return (void *)strdup(module_name); }else{ return 0; } } static char *dlerror(void) { return dld_strerror(dld_errno); } static void *dlsym(void *module, char *function) { return dld_get_func(function); } static void *dlclose(void *module) { if(!module) return; dld_unlink_by_file((char *)module); free(module); } static void dlinit(void) { extern char ** ARGV; if(dld_init(dld_find_executable(ARGV[0]))) { fprintf(stderr,"Failed to init dld\n"); exit(1); } }
79f71c1998-07-09Francesco Chemolli #endif /* USE_DLD */ #ifdef USE_HPUX_DL #include <dl.h>
513a2b1998-07-09Henrik Grubbström (Grubba) #if defined(BIND_VERBOSE)
79f71c1998-07-09Francesco Chemolli #define RTLD_NOW BIND_IMMEDIATE | BIND_VERBOSE #else #define RTLD_NOW BIND_IMMEDIATE
513a2b1998-07-09Henrik Grubbström (Grubba) #endif /* BIND_VERBOSE */
79f71c1998-07-09Francesco Chemolli  extern int errno;
01a9572000-02-03Henrik Grubbström (Grubba) static void *dlopen(const char *libname, int how)
79f71c1998-07-09Francesco Chemolli { shl_t lib; lib = shl_load(libname, how, 0L); return (void *)lib; }
e1195f1997-03-23Fredrik Hübinette (Hubbe) 
79f71c1998-07-09Francesco Chemolli static char *dlerror(void) { #ifdef HAVE_STRERROR return strerror(errno); #else return ""; /* I hope it's better than null..*/
9649491998-02-27Fredrik Hübinette (Hubbe) #endif
79f71c1998-07-09Francesco Chemolli } static void *dlsym(void *module, char *function) { void *func; int result; shl_t mod = (shl_t)module; result = shl_findsym(&mod, function, TYPE_UNDEFINED, &func); if (result == -1) return NULL; return func; } static void dlclose(void *module) { shl_unload((shl_t)module); } #define dlinit() #endif /* USE_HPUX_DL */
9649491998-02-27Fredrik Hübinette (Hubbe)  #ifndef EMULATE_DLOPEN
2631a61996-10-09Fredrik Hübinette (Hubbe) #ifdef HAVE_DLFCN_H
ca74dd1996-10-08Fredrik Hübinette (Hubbe) #include <dlfcn.h>
2631a61996-10-09Fredrik Hübinette (Hubbe) #endif
ca74dd1996-10-08Fredrik Hübinette (Hubbe) 
e1195f1997-03-23Fredrik Hübinette (Hubbe) #define dlinit()
79f71c1998-07-09Francesco Chemolli #endif /* !EMULATE_DLOPEN */
7860031997-01-22Bernhard Fastenrath 
58dd661998-09-18Fredrik Hübinette (Hubbe) #endif /* HAVE_SOME_DLOPEN */
e1195f1997-03-23Fredrik Hübinette (Hubbe) #ifndef RTLD_NOW #define RTLD_NOW 0 #endif
5aeade1999-02-01Per Hedbor #ifndef RTLD_LAZY #define RTLD_LAZY 0 #endif #ifndef RTLD_GLOBAL #define RTLD_GLOBAL 0 #endif
e1195f1997-03-23Fredrik Hübinette (Hubbe) #ifndef TESTING
79f71c1998-07-09Francesco Chemolli #if defined(HAVE_DLOPEN) || defined(USE_DLD) || defined(USE_HPUX_DL)
6cf83a1997-02-06Fredrik Hübinette (Hubbe) 
ca74dd1996-10-08Fredrik Hübinette (Hubbe) struct module_list { struct module_list * next;
368fe71997-01-26Fredrik Hübinette (Hubbe)  void *module;
6cf83a1997-02-06Fredrik Hübinette (Hubbe)  modfun init, exit;
368fe71997-01-26Fredrik Hübinette (Hubbe) }; struct module_list *dynamic_module_list = 0;
418a371999-04-25Henrik Grubbström (Grubba) #ifdef NO_CAST_TO_FUN /* Function pointers can't be casted to scalar pointers according to * ISO-C (probably to support true Harward achitecture machines). */ static modfun CAST_TO_FUN(void *ptr) { union { void *ptr; modfun fun; } u; u.ptr = ptr; return u.fun; } #else /* !NO_CAST_TO_FUN */ #define CAST_TO_FUN(X) ((modfun)X) #endif /* NO_CAST_TO_FUN */
368fe71997-01-26Fredrik Hübinette (Hubbe) void f_load_module(INT32 args) {
ca74dd1996-10-08Fredrik Hübinette (Hubbe)  void *module;
6cf83a1997-02-06Fredrik Hübinette (Hubbe)  modfun init, exit;
368fe71997-01-26Fredrik Hübinette (Hubbe)  struct module_list *new_module; const char *module_name; if(sp[-args].type != T_STRING) error("Bad argument 1 to load_module()\n"); module_name = sp[-args].u.string->str;
5aeade1999-02-01Per Hedbor  module=dlopen(module_name,
5561812000-02-16Fredrik Hübinette (Hubbe)  (d_flag ? RTLD_NOW : RTLD_LAZY) /* |RTLD_GLOBAL */ );
ef78b01997-11-03Henrik Grubbström (Grubba) 
368fe71997-01-26Fredrik Hübinette (Hubbe)  if(!module) {
466a321997-09-07Henrik Grubbström (Grubba)  const char *err = dlerror();
e1195f1997-03-23Fredrik Hübinette (Hubbe)  if(!err) err = "Unknown reason";
14160c1998-05-15Henrik Grubbström (Grubba)  if (sp[-args].u.string->len < 1024) { error("load_module(\"%s\") failed: %s\n", sp[-args].u.string->str, err); } else { error("load_module() failed: %s\n", err); }
368fe71997-01-26Fredrik Hübinette (Hubbe)  }
418a371999-04-25Henrik Grubbström (Grubba)  init = CAST_TO_FUN(dlsym(module, "pike_module_init"));
fb84a71997-03-04Henrik Grubbström (Grubba)  if (!init) {
418a371999-04-25Henrik Grubbström (Grubba)  init = CAST_TO_FUN(dlsym(module, "_pike_module_init"));
fb84a71997-03-04Henrik Grubbström (Grubba)  }
418a371999-04-25Henrik Grubbström (Grubba)  exit = CAST_TO_FUN(dlsym(module, "pike_module_exit"));
fb84a71997-03-04Henrik Grubbström (Grubba)  if (!exit) {
418a371999-04-25Henrik Grubbström (Grubba)  exit = CAST_TO_FUN(dlsym(module, "_pike_module_exit"));
fb84a71997-03-04Henrik Grubbström (Grubba)  }
368fe71997-01-26Fredrik Hübinette (Hubbe)  if(!init || !exit) { dlclose(module);
14160c1998-05-15Henrik Grubbström (Grubba) 
b2b8951998-05-15Henrik Grubbström (Grubba)  if (strlen(module_name) < 1024) {
14160c1998-05-15Henrik Grubbström (Grubba)  error("Failed to initialize dynamic module \"%s\".\n", module_name); } else { error("Failed to initialize dynamic module.\n"); }
368fe71997-01-26Fredrik Hübinette (Hubbe)  } new_module=ALLOC_STRUCT(module_list); new_module->next=dynamic_module_list; dynamic_module_list=new_module; new_module->module=module;
6cf83a1997-02-06Fredrik Hübinette (Hubbe)  new_module->init=init; new_module->exit=exit;
368fe71997-01-26Fredrik Hübinette (Hubbe)  start_new_program();
044c621999-04-14Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG { struct svalue *save_sp=sp; #endif
6cf83a1997-02-06Fredrik Hübinette (Hubbe)  (*(modfun)init)();
044c621999-04-14Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG if(sp != save_sp) fatal("load_module(%s) left %d droppings on stack!\n", module_name, sp-save_sp); } #endif
6cf83a1997-02-06Fredrik Hübinette (Hubbe) 
044c621999-04-14Fredrik Hübinette (Hubbe)  pop_n_elems(args);
6cf83a1997-02-06Fredrik Hübinette (Hubbe)  push_program(end_program());
368fe71997-01-26Fredrik Hübinette (Hubbe) }
79f71c1998-07-09Francesco Chemolli #endif /* HAVE_DLOPEN || USE_DLD || USE_HPUX_DL */
368fe71997-01-26Fredrik Hübinette (Hubbe) 
e1195f1997-03-23Fredrik Hübinette (Hubbe) void init_dynamic_load(void)
368fe71997-01-26Fredrik Hübinette (Hubbe) {
79f71c1998-07-09Francesco Chemolli #if defined(HAVE_DLOPEN) || defined(USE_DLD) || defined(USE_HPUX_DL)
e1195f1997-03-23Fredrik Hübinette (Hubbe)  dlinit();
368fe71997-01-26Fredrik Hübinette (Hubbe) 
45ee5d1999-02-10Fredrik Hübinette (Hubbe)  /* function(string:program) */ ADD_EFUN("load_module",f_load_module,tFunc(tStr,tPrg),OPT_EXTERNAL_DEPEND);
368fe71997-01-26Fredrik Hübinette (Hubbe) #endif }
be478c1997-08-30Henrik Grubbström (Grubba) void exit_dynamic_load(void)
368fe71997-01-26Fredrik Hübinette (Hubbe) {
79f71c1998-07-09Francesco Chemolli #if defined(HAVE_DLOPEN) || defined(USE_DLD) || defined(USE_HPUX_DL)
368fe71997-01-26Fredrik Hübinette (Hubbe)  while(dynamic_module_list) { struct module_list *tmp=dynamic_module_list; dynamic_module_list=tmp->next;
6cf83a1997-02-06Fredrik Hübinette (Hubbe)  (*tmp->exit)();
3c0c281998-01-26Fredrik Hübinette (Hubbe) #ifndef DEBUG_MALLOC
368fe71997-01-26Fredrik Hübinette (Hubbe)  dlclose(tmp->module);
3c0c281998-01-26Fredrik Hübinette (Hubbe) #endif
368fe71997-01-26Fredrik Hübinette (Hubbe)  free((char *)tmp); }
7860031997-01-22Bernhard Fastenrath #endif
368fe71997-01-26Fredrik Hübinette (Hubbe) }
e1195f1997-03-23Fredrik Hübinette (Hubbe) #else /* TESTING */ #include <stdio.h>
368fe71997-01-26Fredrik Hübinette (Hubbe) 
e1195f1997-03-23Fredrik Hübinette (Hubbe) int main()
368fe71997-01-26Fredrik Hübinette (Hubbe) {
e1195f1997-03-23Fredrik Hübinette (Hubbe)  void *module,*fun; dlinit(); module=dlopen("./myconftest.so",RTLD_NOW); if(!module)
ca74dd1996-10-08Fredrik Hübinette (Hubbe)  {
e1195f1997-03-23Fredrik Hübinette (Hubbe)  fprintf(stderr,"Failed to link myconftest.so: %s\n",dlerror()); exit(1);
a69b791996-12-28Henrik Grubbström (Grubba)  }
e1195f1997-03-23Fredrik Hübinette (Hubbe)  fun=dlsym(module,"testfunc"); if(!fun) fun=dlsym(module,"_testfunc"); if(!fun)
ca74dd1996-10-08Fredrik Hübinette (Hubbe)  {
e1195f1997-03-23Fredrik Hübinette (Hubbe)  fprintf(stderr,"Failed to find function testfunc: %s\n",dlerror()); exit(1);
ca74dd1996-10-08Fredrik Hübinette (Hubbe)  }
a991451997-07-08Fredrik Hübinette (Hubbe)  fprintf(stderr,"Calling testfunc\n");
e1195f1997-03-23Fredrik Hübinette (Hubbe)  ((void (*)(void))fun)();
a991451997-07-08Fredrik Hübinette (Hubbe)  fprintf(stderr,"testfunc returned!\n");
e1195f1997-03-23Fredrik Hübinette (Hubbe)  exit(1);
ca74dd1996-10-08Fredrik Hübinette (Hubbe) }
368fe71997-01-26Fredrik Hübinette (Hubbe) #endif