aboutsummaryrefslogtreecommitdiff
path: root/gcc/plugin-loader.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/plugin-loader.c')
-rw-r--r--gcc/plugin-loader.c140
1 files changed, 140 insertions, 0 deletions
diff --git a/gcc/plugin-loader.c b/gcc/plugin-loader.c
new file mode 100644
index 00000000000..673871b8f80
--- /dev/null
+++ b/gcc/plugin-loader.c
@@ -0,0 +1,140 @@
+/* [Legacy] environment-based interface for loading high-level plugins.
+ Copyright (C) 2009 Free Software Foundation, Inc.
+
+ Contributed by Inria.
+
+ Authors: Grigori Fursin <grigori.fursin@inria.fr>, Cupertino Miranda
+ <cupertinomiranda@gmail.com>, Zbigniew Chamski <zbigniew.chamski@gmail.com>.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "hashtab.h"
+#include "toplev.h"
+#include "gcc.h"
+#include "options.h" /* flag_ici */
+
+#include "highlev-plugin-internal.h"
+#include "feature-internal.h" /* init_features() */
+
+#include <dlfcn.h>
+
+int ici_loaded = 0;
+
+/* plugin initialization/cleanup function type */
+typedef void (*start_stop_func) (void);
+
+typedef union {
+ void *data_ptr;
+ start_stop_func function_ptr;
+} dl_symbol_t ;
+
+
+/* pointers to initialization/cleanup functions */
+start_stop_func ici_plugin_start = NULL;
+start_stop_func ici_plugin_stop = NULL;
+
+
+/* report any errors encountered during a dl* operation */
+static inline bool check_for_dlerror (void)
+{
+ const char *dlError;
+ dlError = dlerror ();
+ if (dlError)
+ {
+ fprintf (stderr, "Plugin manager error: DLerror: %s ...\n", dlError);
+ return true;
+ }
+ return false;
+}
+
+
+/* load the ICI plugin shared library file named 'dynlib_file'.
+ Return 0 if successful, and 1 otherwise. */
+static int
+load_ici_plugin_file (char *dynlib_file)
+{
+ void *dlhandle;
+ bool error = 0;
+ dl_symbol_t dl_symbol;
+
+ if (getenv ("ICI_VERBOSE") != NULL)
+ fprintf (stderr, "ICI: loading plugin ...\n");
+
+ dlhandle = dlopen (dynlib_file, RTLD_LAZY);
+ error |= check_for_dlerror ();
+
+ /* assignment of data pointers to function pointers is forbidden in strict
+ ANSI mode - use a union to work around this dlsym() issue. */
+
+ /* plugin initialization function */
+ dl_symbol.data_ptr = dlsym (dlhandle, "start");
+ ici_plugin_start = dl_symbol.function_ptr;
+ error |= check_for_dlerror ();
+
+ /* plugin cleanup function */
+ dl_symbol.data_ptr = dlsym (dlhandle, "stop");
+ ici_plugin_stop = dl_symbol.function_ptr;
+ error |= check_for_dlerror ();
+
+ /* if init and cleanup functions are correctly resolverd, initialize the feature list */
+ if (!error)
+ init_features ();
+
+ return error;
+}
+
+
+/* load a plugin speficied by envariable ICI_PLUGIN if either -fici was
+ given on the command line or envariable ICI_USE is set to '1'. */
+void load_ici_plugin (void)
+{
+ char *ici_use = getenv ("ICI_USE");
+
+ if ((ici_use != NULL) && (ici_use[0] == '1'))
+ flag_ici = true;
+
+ if (flag_ici)
+ {
+ char *dynlib_file = getenv ("ICI_PLUGIN");
+ if (dynlib_file != NULL)
+ {
+ if ((load_ici_plugin_file (dynlib_file) == 0) && ici_plugin_start)
+ {
+ ici_plugin_start ();
+ ici_loaded = 1;
+ }
+ }
+ else
+ {
+ fprintf (stderr, "ICI error: Environment variable ICI_PLUGIN is not defined ...\n");
+ exit (-1);
+ }
+ }
+}
+
+void unload_ici_plugin (void)
+{
+ if ((ici_loaded == 1) && ici_plugin_stop)
+ ici_plugin_stop ();
+
+ if (getenv ("ICI_VERBOSE") != NULL)
+ fprintf (stderr, "ICI: unloading plugin...\n");
+}
+