diff --git a/src/acconfig.h b/src/acconfig.h index b2d63be008d4b50bbc1dbf3b1dd252d098771440..a02047153dfb0892b3545a5a198a21aa27956317 100644 --- a/src/acconfig.h +++ b/src/acconfig.h @@ -73,6 +73,9 @@ /* Define this to enable the internal Pike security system */ #undef PIKE_SECURITY +/* Define this to simulate dynamic module loading with static modules. */ +#undef USE_SEMIDYNAMIC_MODULES + /* Define this to enable the internal bignum conversion */ #undef AUTO_BIGNUM diff --git a/src/configure.in b/src/configure.in index 943d3391fb7d8d83f69f00b860e7f6f1ac327e6d..0874ffdf070e3310484bbf54c449b372a2e7d580 100644 --- a/src/configure.in +++ b/src/configure.in @@ -8514,11 +8514,12 @@ if test x$with_dynamic_modules = xyes ; then POST_MODULE_BUILD_TYPE=dynamic STATIC_POST_MODULES_LINKOPTS= else - dmmsrc="modules/static_module_makefile.in" + AC_DEFINE(USE_SEMIDYNAMIC_MODULES) + dmmsrc="modules/semidynamic_module_makefile.in" PIKE_LIB="libpike.a" MODULE_O=module.o BUILD_PIKE=tpike$EXEEXT - POST_MODULE_BUILD_TYPE=static + POST_MODULE_BUILD_TYPE=dynamic STATIC_POST_MODULES_LINKOPTS=post_modules/linker_options DYNAMIC_MODULE_FLAGS="" fi diff --git a/src/dynamic_load.c b/src/dynamic_load.c index c4e51d93c176af67d38a4b44bc16bd98b09bdacb..72f88fd67c4f41a00ce75dd3217ea942749dff2e 100644 --- a/src/dynamic_load.c +++ b/src/dynamic_load.c @@ -36,38 +36,37 @@ #include <string.h> #endif /* HAVE_STRING_H */ -#if !defined(HAVE_DLOPEN) +#if !defined(HAVE_DLOPEN) || defined(USE_SEMIDYNAMIC_MODULES) -#if defined(HAVE_DLD_LINK) && defined(HAVE_DLD_GET_FUNC) +#ifdef USE_SEMIDYNAMIC_MODULES +#undef HAVE_DLOPEN +#define USE_STATIC_MODULES +#define HAVE_SOME_DLOPEN +#define EMULATE_DLOPEN +#define USE_DYNAMIC_MODULES +#elif defined(HAVE_DLD_LINK) && defined(HAVE_DLD_GET_FUNC) #define USE_DLD #define HAVE_SOME_DLOPEN #define EMULATE_DLOPEN -#else -#if defined(HAVE_SHL_LOAD) && defined(HAVE_DL_H) +#elif defined(HAVE_SHL_LOAD) && defined(HAVE_DL_H) #define USE_HPUX_DL #define HAVE_SOME_DLOPEN #define EMULATE_DLOPEN -#else - -#ifdef USE_DLL -#if defined(HAVE_LOADLIBRARY) && defined(HAVE_FREELIBRARY) && \ - defined(HAVE_GETPROCADDRESS) && defined(HAVE_WINBASE_H) +#elif defined(USE_DLL) && \ + 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 - -#ifdef HAVE_MACH_O_DYLD_H +#elif defined(HAVE_MACH_O_DYLD_H) /* MacOS X... */ #define USE_DYLD #define HAVE_SOME_DLOPEN #define EMULATE_DLOPEN -#endif /* HAVE_MACH_O_DYLD_H */ - -#endif #endif + #else +/* HAVE_DLOPEN */ #define HAVE_SOME_DLOPEN #endif @@ -76,7 +75,54 @@ typedef void (*modfun)(void); -#ifdef USE_LOADLIBRARY +#ifdef USE_STATIC_MODULES + +static void *dlopen(const char *foo, int how) +{ + struct pike_string *s = low_read_file(foo); + char *name, *end; + void *res; + + if (!s) return NULL; + if (strncmp(s->str, "PMODULE=\"", 9)) { + free_string(s); + return NULL; + } + name = s->str + 9; + if (!(end = strchr(name, '\"'))) { + free_string(s); + return NULL; + } + + res = find_semidynamic_module(name, end - name); + free_string(s); + return res; +} + +static char *dlerror(void) +{ + return "Invalid dynamic module."; +} + +static void *dlsym(void *module, char *function) +{ + if (!strcmp(function, "pike_module_init")) + return get_semidynamic_init_fun(module); + if (!strcmp(function, "pike_module_exit")) + return get_semidynamic_exit_fun(module); + return NULL; +} + +static int dlinit(void) +{ + return 1; +} + +static void dlclose(void *module) +{ +} + +#elif defined(USE_LOADLIBRARY) #include <windows.h> static TCHAR *convert_string(const char *str, ptrdiff_t len) diff --git a/src/module.c b/src/module.c index 6b19542d7d33da29766c9f6c0cdb34e524735003..1f6f02293e5593621bc16ab05b4cc136ff51e1bc 100644 --- a/src/module.c +++ b/src/module.c @@ -373,16 +373,47 @@ struct static_module char *name; modfun init; modfun exit; + int semidynamic; }; static const struct static_module module_list[] = { - { "Builtin", init_builtin_modules, exit_builtin_modules } + { "Builtin", init_builtin_modules, exit_builtin_modules, 0 } #include "modules/modlist.h" #ifndef PRE_PIKE #include "post_modules/modlist.h" #endif }; +/* The follwing are used to simulate dlopen() et al. */ + +const struct static_module *find_semidynamic_module(const char *name, int namelen) +{ + unsigned int e; + for(e=0;e<NELEM(module_list);e++) { + if (module_list[e].semidynamic && + !strncmp(module_list[e].name, name, namelen) && + !module_list[e].name[namelen]) { + TRACE((stderr, "Found semidynamic module #%d: \"%s\"...\n", + e, module_list[e].name)); + return module_list+e; + } + } + return NULL; +} + +void *get_semidynamic_init_fun(const struct static_module *sm) +{ + if (!sm) return NULL; + return sm->init; +} + +void *get_semidynamic_exit_fun(const struct static_module *sm) +{ + if (!sm) return NULL; + return sm->exit; +} + + /*! @decl object _static_modules *! *! This is an object containing the classes for all static @@ -419,6 +450,7 @@ void init_modules(void) start_new_program(); p = Pike_compiler->new_program; } + if (module_list[e].semidynamic) continue; if(SETJMP(recovery)) { /* FIXME: We could loop here until we find p. */ free_program(end_program()); @@ -502,6 +534,7 @@ void exit_modules(void) for(e=NELEM(module_list)-1;e>=0;e--) { + if (module_list[e].semidynamic) continue; if(SETJMP(recovery)) call_handle_error(); else { diff --git a/src/module.h b/src/module.h index da04937947fb83453e1b00a273a10d31a0eafc24..97afb8680df45f9a371db99feb2ffe6e912405b8 100644 --- a/src/module.h +++ b/src/module.h @@ -19,6 +19,10 @@ /* Prototypes begin here */ struct static_module; +const struct static_module *find_semidynamic_module(const char *name, + int namelen); +void *get_semidynamic_init_fun(const struct static_module *sm); +void *get_semidynamic_exit_fun(const struct static_module *sm); void init_modules(void); void exit_modules(void); PIKE_MODULE_INIT; diff --git a/src/modules/Makefile.in b/src/modules/Makefile.in index e2ecccb801ac2956705cdd74e35003dffcceff1c..1d32c62fb25e87c5fc7eb928de5912272cf06b74 100644 --- a/src/modules/Makefile.in +++ b/src/modules/Makefile.in @@ -49,10 +49,10 @@ modlist.h: $(MODULE_SEGMENTS) @echo 'Updating $(MY_DIR)/modlist.h'; \ cat $(MODULE_SEGMENTS) </dev/null >modlist.h -modlist_headers.h: $(MODULE_SEGMENTS) +modlist_headers.h: $(MODULE_SEGMENTS) Makefile @echo 'Updating $(MY_DIR)/modlist_headers.h'; \ cat $(MODULE_SEGMENTS) </dev/null | \ - sed -e 's/^.*{.*,\(.*\),\(.*\)}.*$$/void \1(void),\2(void);/' >modlist_headers.h + sed -e 's/^.*{.*,\(.*\),\(.*\),\(.*\)}.*$$/void \1(void),\2(void);/' >modlist_headers.h linker_options: $(MODULE_LINKOPTS) @echo 'Updating $(MY_DIR)/linker_options'; \ diff --git a/src/modules/semidynamic_module_makefile.in b/src/modules/semidynamic_module_makefile.in new file mode 100644 index 0000000000000000000000000000000000000000..299d10d636777fce0bbdc2b1abb2468772650477 --- /dev/null +++ b/src/modules/semidynamic_module_makefile.in @@ -0,0 +1,122 @@ +LC_REQ=@LC_REQ@ + +UNIQUE_MODNAME=$(MODNAME) + +LINKAGE_CPPFLAGS=-Dpike_module_init=pike_module_$(UNIQUE_MODNAME)_init -Dpike_module_exit=pike_module_$(UNIQUE_MODNAME)_exit +LINKAGE_CFLAGS= + +MODULE_PROGRAM=.$(MODULE_WRAPPER_PREFIX)$(MODNAME) +MODULE_TARGET=$(TMP_MODULE_BASE)/$(MODDIR)$(MODULE_WRAPPER_PREFIX)$(MODNAME).so + +# The reason for this is that we can't use targets directly to specify +# the build type; many module makefiles depend on being able to +# override the default target. +all: + @case "x$$MODULE_BUILD_TYPE" in \ + xstatic) $(MAKE) $(MAKE_FLAGS) static;; \ + xdynamic) $(MAKE) $(MAKE_FLAGS) dynamic;; \ + x) $(MAKE) $(MAKE_FLAGS) static dynamic;; \ + *) \ + echo "Invalid MODULE_BUILD_TYPE: $$MODULE_BUILD_TYPE" >&2; \ + exit 1;; \ + esac + +@common_module_makefile@ + +build_type: + @echo semidynamic > build_type + +static: Makefile $(DUMMY) module-preamble module-main + @: + +# Depend on $(DUMMY) here too for the sake of post modules, where the +# static target never gets called. +dynamic: $(DUMMY) module-main + @: + +linker_options: Makefile module.a $(MODULE_ARCHIVES) + @linkopts="";\ + for a in "`pwd`/module.a" $(MODULE_ARCHIVES); do \ + if test "x$$a" = "x"; then :; else \ + case "$$a" in \ + /*) \ + linkopts="$$linkopts $$a" \ + ;; \ + *) \ + linkopts="$$linkopts `pwd`/$$a" \ + ;; \ + esac; \ + fi; \ + done; \ + linkopts="$$linkopts `echo '$(MODULE_LDFLAGS)' | sed -e 's@$(BASE_LDFLAGS)@@'`"; \ + echo "echo $$linkopts > linker_options"; \ + echo $$linkopts > linker_options + +modlist_segment: Makefile + @echo >modlist_segment " ,{ \"$(MODULE_PROGRAM)\", pike_module_$(UNIQUE_MODNAME)_init, pike_module_$(UNIQUE_MODNAME)_exit, 1 } " + +# Can't depend on $(SRCDIR)/$(CONFIG_HEADERS).in since +# $(CONFIG_HEADERS) isn't always used. +Makefile: $(MODULE_BASE)/dynamic_module_makefile $(SRCDIR)/Makefile.in $(SRCDIR)/dependencies make_variables config.status + CONFIG_FILES=Makefile CONFIG_HEADERS="$(CONFIG_HEADERS)" ./config.status + touch remake + @echo "Run make again" >&2 + @exit 1 + +$(MODULE_TARGET): module.so module.a + @if test "x$(OBJS)" = "x" ; then \ + exit 0; \ + fi; \ + if test "x$(PIKE_EXTERNAL_MODULE)" = "x" ; then \ + $(TMP_BINDIR)/install_module module.so $(MODULE_TARGET) && \ + if [ -f $(MODNAME).pdb ]; then \ + cp $(MODNAME).pdb `echo "$(MODULE_TARGET)" | sed -e 's,[^/]*$$,,'`; \ + else :; fi; \ + fi + +module.a: $(OBJS) + -rm -f module.a + $(AR) cq module.a $(OBJS) + -@RANLIB@ module.a + if test -f linker_options ; then touch linker_options ; else :; fi + +module.so: + @echo "PMODULE=\"$(MODULE_PROGRAM)\"" >module.so + +$(OBJS): propagated_variables + +# +# install a standard module with optional c component in the system module path +# +install: $(MODULE_INSTALL) + @if test "x$(OBJS)" != "x" ; then \ + $(TMP_BINDIR)/install_module module.so $(SYSTEM_MODULE_PATH)/$(MODDIR)$(MODULE_WRAPPER_PREFIX)$(MODNAME).so && \ + fi; \ + if test "x$(MODULE_PMOD_IN)" != "x"; then \ + $(TMP_BINDIR)/install_module module.pmod $(SYSTEM_MODULE_PATH)/$(MODDIR)$(MODNAME).pmod ;\ + fi; + +# +# install the module in LOCAL_MODULE_PATH, creating it if it doesn't already exist. +# +local_install: $(MODULE_INSTALL) + if test ! -d "$(LOCAL_MODULE_PATH)" ; then \ + mkdir -p $(LOCAL_MODULE_PATH) ; \ + fi; if test "x$(OBJS)" != "x" ; then \ + $(TMP_BINDIR)/install_module module.so $(LOCAL_MODULE_PATH)/$(MODDIR)$(MODULE_WRAPPER_PREFIX)$(MODNAME).so && \ + fi; \ + if test "x$(MODULE_PMOD_IN)" != "x"; then \ + $(TMP_BINDIR)/install_module module.pmod $(LOCAL_MODULE_PATH)/$(MODDIR)$(MODNAME).pmod ;\ + fi + +dump_module: install + -rm -f dumpmodule.log + args=$${args:-"--log-file --update-only=dumpversion --report-failed"}; \ + $(FINAL_PIKE) -x dump $$args \ + --recursive "$(SYSTEM_MODULE_PATH)/$(MODDIR)$(MODNAME).pmod" + +dump_local_module: install + -rm -f dumpmodule.log + args=$${args:-"--log-file --update-only=dumpversion --report-failed"}; \ + $(FINAL_PIKE) -x dump $$args \ + --recursive "$(LOCAL_MODULE_PATH)/$(MODDIR)$(MODNAME).pmod" diff --git a/src/modules/static_module_makefile.in b/src/modules/static_module_makefile.in index b14a8f27fc489c2d515c39a6a910141116718374..88b79745e5c08399c6a495e792871adc82251f40 100644 --- a/src/modules/static_module_makefile.in +++ b/src/modules/static_module_makefile.in @@ -49,7 +49,7 @@ linker_options: Makefile $(MODULE_ARCHIVES) echo $$linkopts > linker_options modlist_segment: Makefile - @echo >modlist_segment " ,{ \"$(MODULE_PROGRAM)\", pike_module_$(UNIQUE_MODNAME)_init, pike_module_$(UNIQUE_MODNAME)_exit } " + @echo >modlist_segment " ,{ \"$(MODULE_PROGRAM)\", pike_module_$(UNIQUE_MODNAME)_init, pike_module_$(UNIQUE_MODNAME)_exit, 0 } " # Can't depend on $(SRC_DIR)/$(CONFIG_HEADERS).in since diff --git a/src/object.c b/src/object.c index 3495a012a0e52c14e2f8fb665ea07f579ff76ac5..3e79e23d3876a6ade6fbdf81b4e6003b6a11fbfe 100644 --- a/src/object.c +++ b/src/object.c @@ -457,7 +457,7 @@ struct object *decode_value_clone_object(struct svalue *prog) return o; } -static struct pike_string *low_read_file(const char *file) +struct pike_string *low_read_file(const char *file) { struct pike_string *s; PIKE_OFF_T len; diff --git a/src/object.h b/src/object.h index 2d214113430a20586efab4d6dbe93233b4a485aa..83108e2d265d976798cf886511c3e30b87c18b33 100644 --- a/src/object.h +++ b/src/object.h @@ -92,6 +92,7 @@ PMOD_EXPORT struct object *parent_clone_object(struct program *p, int args); PMOD_EXPORT struct object *clone_object_from_object(struct object *o, int args); struct object *decode_value_clone_object(struct svalue *prog); +struct pike_string *low_read_file(const char *file); PMOD_EXPORT struct object *get_master(void); PMOD_EXPORT struct object *debug_master(void); struct destroy_called_mark;