/* If plugin support is not enabled, do not try to execute any code
that may reference libdl. The generic code is still compiled in to
- avoid including to many conditional compilation paths in the rest
+ avoid including too many conditional compilation paths in the rest
of the compiler. */
#ifdef ENABLE_PLUGIN
#include <dlfcn.h>
"PLUGIN_GGC_MARKING",
"PLUGIN_GGC_END",
"PLUGIN_REGISTER_GGC_ROOTS",
+ "PLUGIN_START_UNIT",
"PLUGIN_EVENT_LAST"
};
/* Each plugin should define an initialization function with exactly
this name. */
static const char *str_plugin_init_func_name = "plugin_init";
+
+/* Each plugin should define this symbol to assert that it is
+ distributed under a GPL-compatible license. */
+static const char *str_license = "plugin_is_GPL_compatible";
#endif
/* Helper function for the hash table that compares the base_name of the
case PASS_POS_INSERT_AFTER:
new_pass->next = pass->next;
pass->next = new_pass;
+
+ /* Skip newly inserted pass to avoid repeated
+ insertions in the case where the new pass and the
+ existing one have the same name. */
+ pass = new_pass;
break;
case PASS_POS_INSERT_BEFORE:
new_pass->next = pass;
ggc_register_root_tab ((const struct ggc_root_tab*) user_data);
break;
case PLUGIN_FINISH_TYPE:
+ case PLUGIN_START_UNIT:
case PLUGIN_FINISH_UNIT:
case PLUGIN_CXX_CP_PRE_GENERICIZE:
case PLUGIN_GGC_START:
switch (event)
{
case PLUGIN_FINISH_TYPE:
+ case PLUGIN_START_UNIT:
case PLUGIN_FINISH_UNIT:
case PLUGIN_CXX_CP_PRE_GENERICIZE:
case PLUGIN_ATTRIBUTES:
char *err;
PTR_UNION_TYPE (plugin_init_func) plugin_init_union;
- dl_handle = dlopen (plugin->full_name, RTLD_NOW);
+ /* We use RTLD_NOW to accelerate binding and detect any mismatch
+ between the API expected by the plugin and the GCC API; we use
+ RTLD_GLOBAL which is useful to plugins which themselves call
+ dlopen. */
+ dl_handle = dlopen (plugin->full_name, RTLD_NOW | RTLD_GLOBAL);
if (!dl_handle)
{
error ("Cannot load plugin %s\n%s", plugin->full_name, dlerror ());
/* Clear any existing error. */
dlerror ();
+ /* Check the plugin license. */
+ if (dlsym (dl_handle, str_license) == NULL)
+ fatal_error ("plugin %s is not licensed under a GPL-compatible license\n"
+ "%s", plugin->full_name, dlerror ());
+
PTR_UNION_AS_VOID_PTR (plugin_init_union) =
dlsym (dl_handle, str_plugin_init_func_name);
plugin_init = PTR_UNION_AS_CAST_PTR (plugin_init_union);