aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTobias Brunner <tobias@strongswan.org>2017-04-28 17:41:57 +0200
committerTobias Brunner <tobias@strongswan.org>2017-05-23 18:29:12 +0200
commit1a06bf03f9a0be7f54bdc412475f537f623ca99f (patch)
tree3a6a7575f561613a51c5d2a9be3b30ea89421f1e
parent6ce649a8a6f913a56ccf5b4e60d44f01f21ff8a3 (diff)
downloadstrongswan-1a06bf03f9a0be7f54bdc412475f537f623ca99f.tar.bz2
strongswan-1a06bf03f9a0be7f54bdc412475f537f623ca99f.tar.xz
plugin-loader: Add facility to register plugin constructors
Enabled when building monolithically and statically. This should allow us to work around the -whole-archive issue with libtool. If the libraries register the plugin constructors they provide they reference the constructors and will therefore prevent the linker from removing these seemingly unused symbols from the final executable. For use cases where dlsym() can be used, e.g. because the static libraries are manually linked with -whole-archive (Linux) or -force-load (Apple), this can be disabled by passing ss_cv_static_plugin_constructors=no to the configure script.
-rw-r--r--configure.ac19
-rw-r--r--src/libstrongswan/plugins/plugin_loader.c62
-rw-r--r--src/libstrongswan/plugins/plugin_loader.h10
3 files changed, 87 insertions, 4 deletions
diff --git a/configure.ac b/configure.ac
index 56738bdf3..07df3a672 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2007-2015 Tobias Brunner
+# Copyright (C) 2007-2017 Tobias Brunner
# Copyright (C) 2006-2016 Andreas Steffen
# Copyright (C) 2006-2014 Martin Willi
# HSR Hochschule fuer Technik Rapperswil
@@ -1303,6 +1303,19 @@ AM_CONDITIONAL(PYTHON_EGGS_INSTALL, [test "x$python_eggs_install" = xtrue])
AM_CONDITIONAL(PERL_CPAN_INSTALL, [test "x$perl_cpan_install" = xtrue])
+AC_CACHE_CHECK(
+ [if plugin constructors should be resolved statically],
+ [ss_cv_static_plugin_constructors],
+ [if test x$monolithic = xtrue -a x$enable_static = xyes; then
+ ss_cv_static_plugin_constructors=yes
+ else
+ ss_cv_static_plugin_constructors="no (enabled for static, monolithic builds)"
+ fi]
+)
+if test "x$ss_cv_static_plugin_constructors" = xyes; then
+ static_plugin_constructors=true
+fi
+
# ===============================================
# collect plugin list for strongSwan components
# ===============================================
@@ -1678,6 +1691,7 @@ AM_CONDITIONAL(USE_IMCV, test x$imcv = xtrue)
AM_CONDITIONAL(USE_TROUSERS, test x$tss_trousers = xtrue)
AM_CONDITIONAL(USE_TSS2, test x$tss_tss2 = xtrue)
AM_CONDITIONAL(MONOLITHIC, test x$monolithic = xtrue)
+AM_CONDITIONAL(STATIC_PLUGIN_CONSTRUCTORS, test x$static_plugin_constructors = xtrue)
AM_CONDITIONAL(USE_SILENT_RULES, test x$enable_silent_rules = xyes)
AM_CONDITIONAL(COVERAGE, test x$coverage = xtrue)
AM_CONDITIONAL(USE_DBGHELP, test x$dbghelp_backtraces = xtrue)
@@ -1709,6 +1723,9 @@ fi
if test x$monolithic = xtrue; then
AC_DEFINE([MONOLITHIC], [], [monolithic build embedding plugins])
fi
+if test x$static_plugin_constructors = xtrue; then
+ AC_DEFINE([STATIC_PLUGIN_CONSTRUCTORS], [], [static plugin constructors])
+fi
if test x$ikev1 = xtrue; then
AC_DEFINE([USE_IKEV1], [], [support for IKEv1 protocol])
fi
diff --git a/src/libstrongswan/plugins/plugin_loader.c b/src/libstrongswan/plugins/plugin_loader.c
index e4698fac0..e78762b2c 100644
--- a/src/libstrongswan/plugins/plugin_loader.c
+++ b/src/libstrongswan/plugins/plugin_loader.c
@@ -40,6 +40,13 @@ typedef struct registered_feature_t registered_feature_t;
typedef struct provided_feature_t provided_feature_t;
typedef struct plugin_entry_t plugin_entry_t;
+#ifdef STATIC_PLUGIN_CONSTRUCTORS
+/**
+ * Statically registered constructors
+ */
+static hashtable_t *plugin_constructors = NULL;
+#endif
+
/**
* private data of plugin_loader
*/
@@ -298,6 +305,46 @@ static plugin_t *static_features_create(const char *name,
return &this->public;
}
+#ifdef STATIC_PLUGIN_CONSTRUCTORS
+/*
+ * Described in header.
+ */
+void plugin_constructor_register(char *name, void *constructor)
+{
+ bool old = FALSE;
+
+ if (lib && lib->leak_detective)
+ {
+ old = lib->leak_detective->set_state(lib->leak_detective, FALSE);
+ }
+
+ if (!plugin_constructors)
+ {
+ chunk_hash_seed();
+ plugin_constructors = hashtable_create(hashtable_hash_str,
+ hashtable_equals_str, 32);
+ }
+ if (constructor)
+ {
+ plugin_constructors->put(plugin_constructors, name, constructor);
+ }
+ else
+ {
+ plugin_constructors->remove(plugin_constructors, name);
+ if (!plugin_constructors->get_count(plugin_constructors))
+ {
+ plugin_constructors->destroy(plugin_constructors);
+ plugin_constructors = NULL;
+ }
+ }
+
+ if (lib && lib->leak_detective)
+ {
+ lib->leak_detective->set_state(lib->leak_detective, old);
+ }
+}
+#endif
+
/**
* create a plugin
* returns: NOT_FOUND, if the constructor was not found
@@ -309,7 +356,7 @@ static status_t create_plugin(private_plugin_loader_t *this, void *handle,
{
char create[128];
plugin_t *plugin;
- plugin_constructor_t constructor;
+ plugin_constructor_t constructor = NULL;
if (snprintf(create, sizeof(create), "%s_plugin_create",
name) >= sizeof(create))
@@ -317,8 +364,17 @@ static status_t create_plugin(private_plugin_loader_t *this, void *handle,
return FAILED;
}
translate(create, "-", "_");
- constructor = dlsym(handle, create);
- if (constructor == NULL)
+#ifdef STATIC_PLUGIN_CONSTRUCTORS
+ if (plugin_constructors)
+ {
+ constructor = plugin_constructors->get(plugin_constructors, name);
+ }
+ if (!constructor)
+#endif
+ {
+ constructor = dlsym(handle, create);
+ }
+ if (!constructor)
{
return NOT_FOUND;
}
diff --git a/src/libstrongswan/plugins/plugin_loader.h b/src/libstrongswan/plugins/plugin_loader.h
index 6be6a909c..92a860615 100644
--- a/src/libstrongswan/plugins/plugin_loader.h
+++ b/src/libstrongswan/plugins/plugin_loader.h
@@ -168,4 +168,14 @@ plugin_loader_t *plugin_loader_create();
*/
void plugin_loader_add_plugindirs(char *basedir, char *plugins);
+#ifdef STATIC_PLUGIN_CONSTRUCTORS
+/**
+ * Register a plugin constructor in case of static builds.
+ *
+ * @param name name of the plugin
+ * @param constructor constructor to register (set to NULL to unregister)
+ */
+void plugin_constructor_register(char *name, void *constructor);
+#endif
+
#endif /** PLUGIN_LOADER_H_ @}*/