aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator
diff options
context:
space:
mode:
authorLukas Larsson <[email protected]>2013-08-13 17:14:11 +0200
committerLukas Larsson <[email protected]>2013-08-21 15:20:04 +0200
commit20e0509d4e04fada3019639bc82d78b89f06b0fc (patch)
treed780872721c18782e4bdb7d9fc0f340363acbe38 /erts/emulator
parenta27e9776c839aa9fed9e71e3d06a33720377e293 (diff)
downloadotp-20e0509d4e04fada3019639bc82d78b89f06b0fc.tar.gz
otp-20e0509d4e04fada3019639bc82d78b89f06b0fc.tar.bz2
otp-20e0509d4e04fada3019639bc82d78b89f06b0fc.zip
erts: Add option to include nifs statically
Both crypto and asn1 are supported.
Diffstat (limited to 'erts/emulator')
-rw-r--r--erts/emulator/Makefile.in36
-rw-r--r--erts/emulator/beam/erl_nif.c18
-rw-r--r--erts/emulator/beam/erl_nif.h15
-rwxr-xr-xerts/emulator/beam/global.h6
-rw-r--r--erts/emulator/beam/utils.c21
-rwxr-xr-xerts/emulator/utils/make_driver_tab55
6 files changed, 136 insertions, 15 deletions
diff --git a/erts/emulator/Makefile.in b/erts/emulator/Makefile.in
index 9751982103..db5642b9c3 100644
--- a/erts/emulator/Makefile.in
+++ b/erts/emulator/Makefile.in
@@ -136,6 +136,19 @@ endif
endif
endif
+STATIC_NIFS=@STATIC_NIFS@
+ifneq ($(STATIC_NIFS),no)
+ifeq ($(STATIC_NIFS),yes)
+STATIC_NIFS=$(ERL_TOP)/lib/asn1/priv/lib/$(TARGET)/asn1rt_nif.a \
+ $(ERL_TOP)/lib/crypto/priv/lib/$(TARGET)/crypto$(TYPEMARKER).a
+endif
+comma:=,
+space:=
+space+=
+STATIC_NIFS:=$(subst $(comma),$(space),$(STATIC_NIFS))
+endif
+
+
#
# NOTE: When adding a new type update ERL_BUILD_TYPE_MARKER in sys/unix/sys.c
#
@@ -557,8 +570,8 @@ $(TARGET)/erl_version.h: ../vsn.mk
GENERATE += $(TARGET)/erl_version.h
# driver table
-$(TTF_DIR)/driver_tab.c: Makefile.in
- $(gen_verbose)LANG=C $(PERL) utils/make_driver_tab -o $@ $(DRV_OBJS)
+$(TTF_DIR)/driver_tab.c: Makefile.in utils/make_driver_tab
+ $(gen_verbose)LANG=C $(PERL) utils/make_driver_tab -o $@ $(STATIC_NIF_LIBS) $(DRV_OBJS)
GENERATE += $(TTF_DIR)/driver_tab.c
@@ -797,6 +810,17 @@ endif
DRV_OBJS += $(OBJDIR)/ttsl_drv.o
+ifneq ($(STATIC_NIFS),no)
+STATIC_NIF_LIBS = $(STATIC_NIFS)
+DEPLIBS += $(STATIC_NIF_LIBS)
+
+$(STATIC_NIF_LIBS):
+ $(MAKE) BUILD_STATIC_LIBS=1 TYPE=$(TYPE) -C $(ERL_TOP)/lib/ static_lib
+
+else
+STATIC_NIF_LIBS=
+endif
+
ifeq ($(ERTS_ENABLE_KERNEL_POLL),yes)
OS_OBJS += $(OBJDIR)/erl_poll.kp.o \
$(OBJDIR)/erl_check_io.kp.o \
@@ -935,18 +959,18 @@ $(OBJDIR)/hipe_arm.o: hipe/hipe_arm.c
# ----------------------------------------------------------------------
# The emulator itself
+#
ifeq ($(TARGET), win32)
# Only the basic erlang to begin with eh?
$(BINDIR)/$(EMULATOR_EXECUTABLE): $(INIT_OBJS) $(OBJS) $(DEPLIBS)
$(ld_verbose)$(PURIFY) $(LD) -dll -def:sys/$(ERLANG_OSTYPE)/erl.def -implib:$(BINDIR)/erl_dll.lib -o $(BINDIR)/$(EMULATOR_EXECUTABLE) \
- $(LDFLAGS) $(DEXPORT) $(INIT_OBJS) $(OBJS) $(LIBS)
+ $(LDFLAGS) $(DEXPORT) $(INIT_OBJS) $(OBJS) $(STATIC_NIF_LIBS) $(LIBS)
else
-
-
$(BINDIR)/$(EMULATOR_EXECUTABLE): $(INIT_OBJS) $(OBJS) $(DEPLIBS)
$(ld_verbose)$(PURIFY) $(LD) -o $(BINDIR)/$(EMULATOR_EXECUTABLE) \
- $(HIPEBEAMLDFLAGS) $(LDFLAGS) $(DEXPORT) $(INIT_OBJS) $(OBJS) $(LIBS)
+ $(HIPEBEAMLDFLAGS) $(LDFLAGS) $(DEXPORT) $(INIT_OBJS) $(OBJS) \
+ $(STATIC_NIF_LIBS) $(LIBS)
endif
diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c
index 48f8be8dd3..673012a9af 100644
--- a/erts/emulator/beam/erl_nif.c
+++ b/erts/emulator/beam/erl_nif.c
@@ -1213,7 +1213,8 @@ static void close_lib(struct erl_module_nif* lib)
lib->entry->unload(&env, lib->priv_data);
post_nif_noproc(&env);
}
- erts_sys_ddll_close(lib->handle);
+ if (!erts_is_static_nif(lib->handle))
+ erts_sys_ddll_close(lib->handle);
lib->handle = NULL;
}
@@ -1564,7 +1565,7 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2)
static const char upgrade[] = "upgrade";
char* lib_name = NULL;
void* handle = NULL;
- void* init_func;
+ void* init_func = NULL;
ErlNifEntry* entry = NULL;
ErlNifEnv env;
int len, i, err;
@@ -1577,6 +1578,7 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2)
int veto;
struct erl_module_nif* lib = NULL;
int reload_warning = 0;
+ char tmp_buf[255];
len = list_length(BIF_ARG_1);
if (len < 0) {
@@ -1613,13 +1615,18 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2)
mod=erts_get_module(mod_atom, erts_active_code_ix());
ASSERT(mod != NULL);
+ init_func = erts_static_nif_get_nif_init(erts_basename(lib_name,tmp_buf));
+ if (init_func != NULL)
+ handle = init_func;
+
if (!in_area(caller, mod->curr.code, mod->curr.code_length)) {
ASSERT(in_area(caller, mod->old.code, mod->old.code_length));
ret = load_nif_error(BIF_P, "old_code", "Calling load_nif from old "
"module '%T' not allowed", mod_atom);
}
- else if ((err=erts_sys_ddll_open2(lib_name, &handle, &errdesc)) != ERL_DE_NO_ERROR) {
+ else if (init_func == NULL &&
+ (err=erts_sys_ddll_open2(lib_name, &handle, &errdesc)) != ERL_DE_NO_ERROR) {
const char slogan[] = "Failed to load NIF library";
if (strstr(errdesc.str, lib_name) != NULL) {
ret = load_nif_error(BIF_P, "load_failed", "%s: '%s'", slogan, errdesc.str);
@@ -1628,7 +1635,8 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2)
ret = load_nif_error(BIF_P, "load_failed", "%s %s: '%s'", slogan, lib_name, errdesc.str);
}
}
- else if (erts_sys_ddll_load_nif_init(handle, &init_func, &errdesc) != ERL_DE_NO_ERROR) {
+ else if (init_func == NULL &&
+ erts_sys_ddll_load_nif_init(handle, &init_func, &errdesc) != ERL_DE_NO_ERROR) {
ret = load_nif_error(BIF_P, bad_lib, "Failed to find library init"
" function: '%s'", errdesc.str);
@@ -1784,7 +1792,7 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2)
if (lib != NULL) {
erts_free(ERTS_ALC_T_NIF, lib);
}
- if (handle != NULL) {
+ if (handle != NULL && !erts_is_static_nif(handle)) {
erts_sys_ddll_close(handle);
}
erts_sys_ddll_free_error(&errdesc);
diff --git a/erts/emulator/beam/erl_nif.h b/erts/emulator/beam/erl_nif.h
index 8006741a63..5f4dc21d5c 100644
--- a/erts/emulator/beam/erl_nif.h
+++ b/erts/emulator/beam/erl_nif.h
@@ -168,7 +168,7 @@ extern TWinDynNifCallbacks WinDynNifCallbacks;
# undef ERL_NIF_API_FUNC_DECL
#endif
-#if (defined(__WIN32__) || defined(_WIN32) || defined(_WIN32_)) && !defined(STATIC_ERLANG_DRIVER)
+#if (defined(__WIN32__) || defined(_WIN32) || defined(_WIN32_)) && !defined(STATIC_ERLANG_DRIVER) && !defined(STATIC_ERLANG_NIF)
# define ERL_NIF_API_FUNC_MACRO(NAME) (WinDynNifCallbacks.NAME)
# include "erl_nif_api_funcs.h"
/* note that we have to keep ERL_NIF_API_FUNC_MACRO defined */
@@ -180,15 +180,22 @@ extern TWinDynNifCallbacks WinDynNifCallbacks;
# undef ERL_NIF_API_FUNC_DECL
#endif
-
#if (defined(__WIN32__) || defined(_WIN32) || defined(_WIN32_))
# define ERL_NIF_INIT_GLOB TWinDynNifCallbacks WinDynNifCallbacks;
-# define ERL_NIF_INIT_DECL(MODNAME) __declspec(dllexport) ErlNifEntry* nif_init(TWinDynNifCallbacks* callbacks)
+# ifdef STATIC_ERLANG_NIF
+# define ERL_NIF_INIT_DECL(MODNAME) __declspec(dllexport) ErlNifEntry* MODNAME ## _nif_init(TWinDynNifCallbacks* callbacks)
+# else
+# define ERL_NIF_INIT_DECL(MODNAME) __declspec(dllexport) ErlNifEntry* nif_init(TWinDynNifCallbacks* callbacks)
+# endif
# define ERL_NIF_INIT_BODY memcpy(&WinDynNifCallbacks,callbacks,sizeof(TWinDynNifCallbacks))
#else
# define ERL_NIF_INIT_GLOB
# define ERL_NIF_INIT_BODY
-# define ERL_NIF_INIT_DECL(MODNAME) ErlNifEntry* nif_init(void)
+# ifdef STATIC_ERLANG_NIF
+# define ERL_NIF_INIT_DECL(MODNAME) ErlNifEntry* MODNAME ## _nif_init(void)
+# else
+# define ERL_NIF_INIT_DECL(MODNAME) ErlNifEntry* nif_init(void)
+# endif
#endif
diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h
index 7f7b6f5d1e..2acc86cf42 100755
--- a/erts/emulator/beam/global.h
+++ b/erts/emulator/beam/global.h
@@ -852,11 +852,17 @@ Port *erts_get_heart_port(void);
void erts_lcnt_enable_io_lock_count(int enable);
#endif
+/* driver_tab.c */
+typedef void *(*ErtsStaticNifInitFPtr)(void);
+ErtsStaticNifInitFPtr erts_static_nif_get_nif_init(const char *name);
+int erts_is_static_nif(void *handle);
+
/* erl_drv_thread.c */
void erl_drv_thr_init(void);
/* utils.c */
void erts_cleanup_offheap(ErlOffHeap *offheap);
+const char *erts_basename(const char* path, char* buff);
Uint64 erts_timestamp_millis(void);
diff --git a/erts/emulator/beam/utils.c b/erts/emulator/beam/utils.c
index c71f8f0712..6293286c75 100644
--- a/erts/emulator/beam/utils.c
+++ b/erts/emulator/beam/utils.c
@@ -4019,6 +4019,27 @@ erts_smp_ensure_later_interval_acqb(erts_interval_t *icp, Uint64 ic)
#endif
}
+const char *erts_basename(const char* path, char* buff) {
+ /* This function is not compliant with bash basename. Edge cases like "//"
+ and "/path//" do not work properly.
+ */
+ int i;
+ int len = strlen(path);
+ const char *basename = path;
+ for (i = 0; path[i] != '\0'; i++) {
+ if (path[i] == '/') {
+ if (path[i+1] == '\0') {
+ memcpy(buff,basename,len - (basename-path));
+ buff[len - (basename-path)-1] = '\0';
+ basename = buff;
+ break;
+ } else { basename = path+i;}
+ }
+ }
+ if (basename == path)
+ return path;
+ return basename+1;
+}
/*
* A millisecond timestamp without time correction where there's no hrtime
diff --git a/erts/emulator/utils/make_driver_tab b/erts/emulator/utils/make_driver_tab
index fbbfa3e49e..06928a3a4a 100755
--- a/erts/emulator/utils/make_driver_tab
+++ b/erts/emulator/utils/make_driver_tab
@@ -27,7 +27,9 @@ use File::Basename;
# usage: make_driver_tab [-o filename] drivers...
my $file = "";
+my $nif = "";
my @drivers = ();
+my @nifs = ();
while (@ARGV) {
my $d = shift;
@@ -35,6 +37,12 @@ while (@ARGV) {
$file = shift or die("-o requires argument");
next;
}
+ if ( $d =~ /^.*\.a$/ ) {
+ $d = basename $d;
+ $d =~ s/\.a$//; # strip .a
+ push(@nifs, $d);
+ next;
+ }
$d = basename $d;
$d =~ s/drv(\..*|)$//; # strip drv.* or just drv
push(@drivers, $d);
@@ -52,6 +60,7 @@ print <<EOF;
#include <stdio.h>
#include "global.h"
+
EOF
# "extern" declarations
@@ -68,4 +77,50 @@ foreach (@drivers) {
print " NULL\n};\n";
+print <<EOF;
+
+typedef struct ErtsStaticNifEntry_ {
+ const char *nif_name;
+ ErtsStaticNifInitFPtr nif_init;
+} ErtsStaticNifEntry;
+
+EOF
+
+# prototypes
+foreach (@nifs) {
+ my $d = ${_};
+ $d =~ s/\.debug//; # strip .debug
+ print "void *".$d."_nif_init(void);\n";
+}
+
+# The array itself
+print "static ErtsStaticNifEntry static_nif_tab[DRIVER_TAB_SIZE] =\n{\n";
+
+foreach (@nifs) {
+ my $d = ${_};
+ $d =~ s/\.debug//; # strip .debug
+ print "{\"${_}\",&".$d."_nif_init},\n";
+}
+
+print " {NULL,NULL}\n};\n";
+
+print <<EOF;
+ErtsStaticNifInitFPtr erts_static_nif_get_nif_init(const char *name) {
+ int i;
+ for (i = 0; static_nif_tab[i].nif_name != NULL; i++)
+ if (strcmp(name,static_nif_tab[i].nif_name) == 0)
+ return static_nif_tab[i].nif_init;
+ return NULL;
+}
+
+int erts_is_static_nif(void *handle) {
+ int i;
+ for (i = 0; static_nif_tab[i].nif_name != NULL; i++)
+ if (((void*)static_nif_tab[i].nif_init) == handle)
+ return 1;
+ return 0;
+}
+
+EOF
+
# That's it