Home | History | Annotate | Line # | Download | only in gcc
plugin.cc revision 1.1.1.1
      1 /* Support for GCC plugin mechanism.
      2    Copyright (C) 2009-2022 Free Software Foundation, Inc.
      3 
      4 This file is part of GCC.
      5 
      6 GCC is free software; you can redistribute it and/or modify
      7 it under the terms of the GNU General Public License as published by
      8 the Free Software Foundation; either version 3, or (at your option)
      9 any later version.
     10 
     11 GCC is distributed in the hope that it will be useful,
     12 but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14 GNU General Public License for more details.
     15 
     16 You should have received a copy of the GNU General Public License
     17 along with GCC; see the file COPYING3.  If not see
     18 <http://www.gnu.org/licenses/>.  */
     19 
     20 /* This file contains the support for GCC plugin mechanism based on the
     21    APIs described in doc/plugin.texi.  */
     22 
     23 #include "config.h"
     24 #include "system.h"
     25 #include "coretypes.h"
     26 #include "options.h"
     27 #include "tree-pass.h"
     28 #include "diagnostic-core.h"
     29 #include "flags.h"
     30 #include "intl.h"
     31 #include "plugin.h"
     32 
     33 #ifdef ENABLE_PLUGIN
     34 #include "plugin-version.h"
     35 #endif
     36 
     37 #ifdef __MINGW32__
     38 #ifndef WIN32_LEAN_AND_MEAN
     39 #define WIN32_LEAN_AND_MEAN
     40 #endif
     41 #ifndef NOMINMAX
     42 #define NOMINMAX
     43 #endif
     44 #include <windows.h>
     45 #endif
     46 
     47 #define GCC_PLUGIN_STRINGIFY0(X) #X
     48 #define GCC_PLUGIN_STRINGIFY1(X) GCC_PLUGIN_STRINGIFY0 (X)
     49 
     50 /* Event names as strings.  Keep in sync with enum plugin_event.  */
     51 static const char *plugin_event_name_init[] =
     52 {
     53 # define DEFEVENT(NAME) GCC_PLUGIN_STRINGIFY1 (NAME),
     54 # include "plugin.def"
     55 # undef DEFEVENT
     56 };
     57 
     58 /* A printf format large enough for the largest event above.  */
     59 #define FMT_FOR_PLUGIN_EVENT "%-32s"
     60 
     61 const char **plugin_event_name = plugin_event_name_init;
     62 
     63 /* Event hashtable helpers.  */
     64 
     65 struct event_hasher : nofree_ptr_hash <const char *>
     66 {
     67   static inline hashval_t hash (const char **);
     68   static inline bool equal (const char **, const char **);
     69 };
     70 
     71 /* Helper function for the event hash table that hashes the entry V.  */
     72 
     73 inline hashval_t
     74 event_hasher::hash (const char **v)
     75 {
     76   return htab_hash_string (*v);
     77 }
     78 
     79 /* Helper function for the event hash table that compares the name of an
     80    existing entry (S1) with the given string (S2).  */
     81 
     82 inline bool
     83 event_hasher::equal (const char **s1, const char **s2)
     84 {
     85   return !strcmp (*s1, *s2);
     86 }
     87 
     88 /* A hash table to map event names to the position of the names in the
     89    plugin_event_name table.  */
     90 static hash_table<event_hasher> *event_tab;
     91 
     92 /* Keep track of the limit of allocated events and space ready for
     93    allocating events.  */
     94 static int event_last = PLUGIN_EVENT_FIRST_DYNAMIC;
     95 static int event_horizon = PLUGIN_EVENT_FIRST_DYNAMIC;
     96 
     97 /* Hash table for the plugin_name_args objects created during command-line
     98    parsing.  */
     99 static htab_t plugin_name_args_tab = NULL;
    100 
    101 /* List node for keeping track of plugin-registered callback.  */
    102 struct callback_info
    103 {
    104   const char *plugin_name;   /* Name of plugin that registers the callback.  */
    105   plugin_callback_func func; /* Callback to be called.  */
    106   void *user_data;           /* plugin-specified data.  */
    107   struct callback_info *next;
    108 };
    109 
    110 /* An array of lists of 'callback_info' objects indexed by the event id.  */
    111 static struct callback_info *plugin_callbacks_init[PLUGIN_EVENT_FIRST_DYNAMIC];
    112 static struct callback_info **plugin_callbacks = plugin_callbacks_init;
    113 
    114 /* For invoke_plugin_callbacks(), see plugin.h.  */
    115 bool flag_plugin_added = false;
    116 
    117 #ifdef ENABLE_PLUGIN
    118 /* Each plugin should define an initialization function with exactly
    119    this name.  */
    120 static const char *str_plugin_init_func_name = "plugin_init";
    121 
    122 /* Each plugin should define this symbol to assert that it is
    123    distributed under a GPL-compatible license.  */
    124 static const char *str_license = "plugin_is_GPL_compatible";
    125 #endif
    126 
    127 /* Helper function for hashing the base_name of the plugin_name_args
    128    structure to be inserted into the hash table.  */
    129 
    130 static hashval_t
    131 htab_hash_plugin (const PTR p)
    132 {
    133   const struct plugin_name_args *plugin = (const struct plugin_name_args *) p;
    134   return htab_hash_string (plugin->base_name);
    135  }
    136 
    137 /* Helper function for the hash table that compares the base_name of the
    138    existing entry (S1) with the given string (S2).  */
    139 
    140 static int
    141 htab_str_eq (const void *s1, const void *s2)
    142 {
    143   const struct plugin_name_args *plugin = (const struct plugin_name_args *) s1;
    144   return !strcmp (plugin->base_name, (const char *) s2);
    145 }
    146 
    147 
    148 /* Given a plugin's full-path name FULL_NAME, e.g. /pass/to/NAME.so,
    149    return NAME.  */
    150 
    151 static char *
    152 get_plugin_base_name (const char *full_name)
    153 {
    154   /* First get the base name part of the full-path name, i.e. NAME.so.  */
    155   char *base_name = xstrdup (lbasename (full_name));
    156 
    157   /* Then get rid of the extension in the name, e.g., .so.  */
    158   strip_off_ending (base_name, strlen (base_name));
    159 
    160   return base_name;
    161 }
    162 
    163 
    164 /* Create a plugin_name_args object for the given plugin and insert it
    165    to the hash table. This function is called when
    166    -fplugin=/path/to/NAME.so or -fplugin=NAME option is processed.  */
    167 
    168 void
    169 add_new_plugin (const char* plugin_name)
    170 {
    171   struct plugin_name_args *plugin;
    172   void **slot;
    173   char *base_name;
    174   bool name_is_short;
    175   const char *pc;
    176 
    177   flag_plugin_added = true;
    178 
    179   /* Replace short names by their full path when relevant.  */
    180   name_is_short  = !IS_ABSOLUTE_PATH (plugin_name);
    181   for (pc = plugin_name; name_is_short && *pc; pc++)
    182     if (*pc == '.' || IS_DIR_SEPARATOR (*pc))
    183       name_is_short = false;
    184 
    185   if (name_is_short)
    186     {
    187       base_name = CONST_CAST (char*, plugin_name);
    188 
    189 #if defined(__MINGW32__)
    190       static const char plugin_ext[] = ".dll";
    191 #elif defined(__APPLE__)
    192       /* Mac OS has two types of libraries: dynamic libraries (.dylib) and
    193          plugins (.bundle). Both can be used with dlopen()/dlsym() but the
    194          former cannot be linked at build time (i.e., with the -lfoo linker
    195          option). A GCC plugin is therefore probably a Mac OS plugin but their
    196          use seems to be quite rare and the .bundle extension is more of a
    197          recommendation rather than the rule. This raises the questions of how
    198          well they are supported by tools (e.g., libtool). So to avoid
    199          complications let's use the .dylib extension for now. In the future,
    200          if this proves to be an issue, we can always check for both
    201          extensions.  */
    202       static const char plugin_ext[] = ".dylib";
    203 #else
    204       static const char plugin_ext[] = ".so";
    205 #endif
    206 
    207       plugin_name = concat (default_plugin_dir_name (), "/",
    208 			    plugin_name, plugin_ext, NULL);
    209       if (access (plugin_name, R_OK))
    210 	fatal_error
    211 	  (input_location,
    212 	   "inaccessible plugin file %s expanded from short plugin name %s: %m",
    213 	   plugin_name, base_name);
    214     }
    215   else
    216     base_name = get_plugin_base_name (plugin_name);
    217 
    218   /* If this is the first -fplugin= option we encounter, create
    219      'plugin_name_args_tab' hash table.  */
    220   if (!plugin_name_args_tab)
    221     plugin_name_args_tab = htab_create (10, htab_hash_plugin, htab_str_eq,
    222                                         NULL);
    223 
    224   slot = htab_find_slot_with_hash (plugin_name_args_tab, base_name,
    225 				   htab_hash_string (base_name), INSERT);
    226 
    227   /* If the same plugin (name) has been specified earlier, either emit an
    228      error or a warning message depending on if they have identical full
    229      (path) names.  */
    230   if (*slot)
    231     {
    232       plugin = (struct plugin_name_args *) *slot;
    233       if (strcmp (plugin->full_name, plugin_name))
    234 	error ("plugin %qs was specified with different paths: %qs and %qs",
    235                plugin->base_name, plugin->full_name, plugin_name);
    236       return;
    237     }
    238 
    239   plugin = XCNEW (struct plugin_name_args);
    240   plugin->base_name = base_name;
    241   plugin->full_name = plugin_name;
    242 
    243   *slot = plugin;
    244 }
    245 
    246 
    247 /* Parse the -fplugin-arg-<name>-<key>[=<value>] option and create a
    248    'plugin_argument' object for the parsed key-value pair. ARG is
    249    the <name>-<key>[=<value>] part of the option.  */
    250 
    251 void
    252 parse_plugin_arg_opt (const char *arg)
    253 {
    254   size_t len = 0, name_len = 0, key_len = 0, value_len = 0;
    255   const char *ptr, *name_start = arg, *key_start = NULL, *value_start = NULL;
    256   char *name, *key, *value;
    257   void **slot;
    258   bool name_parsed = false, key_parsed = false;
    259 
    260   /* Iterate over the ARG string and identify the starting character position
    261      of 'name', 'key', and 'value' and their lengths.  */
    262   for (ptr = arg; *ptr; ++ptr)
    263     {
    264       /* Only the first '-' encountered is considered a separator between
    265          'name' and 'key'. All the subsequent '-'s are considered part of
    266          'key'. For example, given -fplugin-arg-foo-bar-primary-key=value,
    267          the plugin name is 'foo' and the key is 'bar-primary-key'.  */
    268       if (*ptr == '-' && !name_parsed)
    269         {
    270           name_len = len;
    271           len = 0;
    272           key_start = ptr + 1;
    273           name_parsed = true;
    274           continue;
    275         }
    276       else if (*ptr == '=')
    277         {
    278 	  if (!key_parsed)
    279 	    {
    280 	      key_len = len;
    281 	      len = 0;
    282 	      value_start = ptr + 1;
    283 	      key_parsed = true;
    284 	    }
    285           continue;
    286         }
    287       else
    288         ++len;
    289     }
    290 
    291   if (!key_start)
    292     {
    293       error ("malformed option %<-fplugin-arg-%s%>: "
    294 	     "missing %<-<key>[=<value>]%>",
    295              arg);
    296       return;
    297     }
    298 
    299   /* If the option doesn't contain the 'value' part, LEN is the KEY_LEN.
    300      Otherwise, it is the VALUE_LEN.  */
    301   if (!value_start)
    302     key_len = len;
    303   else
    304     value_len = len;
    305 
    306   name = XNEWVEC (char, name_len + 1);
    307   strncpy (name, name_start, name_len);
    308   name[name_len] = '\0';
    309 
    310   /* Check if the named plugin has already been specified earlier in the
    311      command-line.  */
    312   if (plugin_name_args_tab
    313       && ((slot = htab_find_slot_with_hash (plugin_name_args_tab, name,
    314 					    htab_hash_string (name), NO_INSERT))
    315           != NULL))
    316     {
    317       struct plugin_name_args *plugin = (struct plugin_name_args *) *slot;
    318 
    319       key = XNEWVEC (char, key_len + 1);
    320       strncpy (key, key_start, key_len);
    321       key[key_len] = '\0';
    322       if (value_start)
    323         {
    324           value = XNEWVEC (char, value_len + 1);
    325           strncpy (value, value_start, value_len);
    326           value[value_len] = '\0';
    327         }
    328       else
    329         value = NULL;
    330 
    331       /* Create a plugin_argument object for the parsed key-value pair.
    332          If there are already arguments for this plugin, we will need to
    333          adjust the argument array size by creating a new array and deleting
    334          the old one. If the performance ever becomes an issue, we can
    335          change the code by pre-allocating a larger array first.  */
    336       if (plugin->argc > 0)
    337         {
    338           struct plugin_argument *args = XNEWVEC (struct plugin_argument,
    339                                                   plugin->argc + 1);
    340           memcpy (args, plugin->argv,
    341                   sizeof (struct plugin_argument) * plugin->argc);
    342           XDELETEVEC (plugin->argv);
    343           plugin->argv = args;
    344           ++plugin->argc;
    345         }
    346       else
    347         {
    348           gcc_assert (plugin->argv == NULL);
    349           plugin->argv = XNEWVEC (struct plugin_argument, 1);
    350           plugin->argc = 1;
    351         }
    352 
    353       plugin->argv[plugin->argc - 1].key = key;
    354       plugin->argv[plugin->argc - 1].value = value;
    355     }
    356   else
    357     error ("plugin %s should be specified before %<-fplugin-arg-%s%> "
    358            "in the command line", name, arg);
    359 
    360   /* We don't need the plugin's name anymore. Just release it.  */
    361   XDELETEVEC (name);
    362 }
    363 
    364 /* Register additional plugin information. NAME is the name passed to
    365    plugin_init. INFO is the information that should be registered. */
    366 
    367 static void
    368 register_plugin_info (const char* name, struct plugin_info *info)
    369 {
    370   void **slot = htab_find_slot_with_hash (plugin_name_args_tab, name,
    371 					  htab_hash_string (name), NO_INSERT);
    372   struct plugin_name_args *plugin;
    373 
    374   if (slot == NULL)
    375     {
    376       error ("unable to register info for plugin %qs - plugin name not found",
    377 	     name);
    378       return;
    379     }
    380   plugin = (struct plugin_name_args *) *slot;
    381   plugin->version = info->version;
    382   plugin->help = info->help;
    383 }
    384 
    385 /* Look up the event id for NAME.  If the name is not found, return -1
    386    if INSERT is NO_INSERT.  */
    387 
    388 int
    389 get_named_event_id (const char *name, enum insert_option insert)
    390 {
    391   const char ***slot;
    392 
    393   if (!event_tab)
    394     {
    395       int i;
    396 
    397       event_tab = new hash_table<event_hasher> (150);
    398       for (i = 0; i < event_last; i++)
    399 	{
    400 	  slot = event_tab->find_slot (&plugin_event_name[i], INSERT);
    401 	  gcc_assert (*slot == HTAB_EMPTY_ENTRY);
    402 	  *slot = &plugin_event_name[i];
    403 	}
    404     }
    405   slot = event_tab->find_slot (&name, insert);
    406   if (slot == NULL)
    407     return -1;
    408   if (*slot != HTAB_EMPTY_ENTRY)
    409     return *slot - &plugin_event_name[0];
    410 
    411   if (event_last >= event_horizon)
    412     {
    413       event_horizon = event_last * 2;
    414       if (plugin_event_name == plugin_event_name_init)
    415 	{
    416 	  plugin_event_name = XNEWVEC (const char *, event_horizon);
    417 	  memcpy (plugin_event_name, plugin_event_name_init,
    418 		  sizeof plugin_event_name_init);
    419 	  plugin_callbacks = XNEWVEC (struct callback_info *, event_horizon);
    420 	  memcpy (plugin_callbacks, plugin_callbacks_init,
    421 		  sizeof plugin_callbacks_init);
    422 	}
    423       else
    424 	{
    425 	  plugin_event_name
    426 	    = XRESIZEVEC (const char *, plugin_event_name, event_horizon);
    427 	  plugin_callbacks = XRESIZEVEC (struct callback_info *,
    428 					 plugin_callbacks, event_horizon);
    429 	}
    430       /* All the pointers in the hash table will need to be updated.  */
    431       delete event_tab;
    432       event_tab = NULL;
    433     }
    434   else
    435     *slot = &plugin_event_name[event_last];
    436   plugin_event_name[event_last] = name;
    437   return event_last++;
    438 }
    439 
    440 /* Called from the plugin's initialization code. Register a single callback.
    441    This function can be called multiple times.
    442 
    443    PLUGIN_NAME - display name for this plugin
    444    EVENT       - which event the callback is for
    445    CALLBACK    - the callback to be called at the event
    446    USER_DATA   - plugin-provided data   */
    447 
    448 void
    449 register_callback (const char *plugin_name,
    450 		   int event,
    451                    plugin_callback_func callback,
    452                    void *user_data)
    453 {
    454   switch (event)
    455     {
    456       case PLUGIN_PASS_MANAGER_SETUP:
    457 	gcc_assert (!callback);
    458         register_pass ((struct register_pass_info *) user_data);
    459         break;
    460       case PLUGIN_INFO:
    461 	gcc_assert (!callback);
    462 	register_plugin_info (plugin_name, (struct plugin_info *) user_data);
    463 	break;
    464       case PLUGIN_REGISTER_GGC_ROOTS:
    465 	gcc_assert (!callback);
    466         ggc_register_root_tab ((const struct ggc_root_tab*) user_data);
    467 	break;
    468       case PLUGIN_EVENT_FIRST_DYNAMIC:
    469       default:
    470 	if (event < PLUGIN_EVENT_FIRST_DYNAMIC || event >= event_last)
    471 	  {
    472 	    error ("unknown callback event registered by plugin %s",
    473 		   plugin_name);
    474 	    return;
    475 	  }
    476       /* Fall through.  */
    477       case PLUGIN_START_PARSE_FUNCTION:
    478       case PLUGIN_FINISH_PARSE_FUNCTION:
    479       case PLUGIN_FINISH_TYPE:
    480       case PLUGIN_FINISH_DECL:
    481       case PLUGIN_START_UNIT:
    482       case PLUGIN_FINISH_UNIT:
    483       case PLUGIN_PRE_GENERICIZE:
    484       case PLUGIN_GGC_START:
    485       case PLUGIN_GGC_MARKING:
    486       case PLUGIN_GGC_END:
    487       case PLUGIN_ATTRIBUTES:
    488       case PLUGIN_PRAGMAS:
    489       case PLUGIN_FINISH:
    490       case PLUGIN_ALL_PASSES_START:
    491       case PLUGIN_ALL_PASSES_END:
    492       case PLUGIN_ALL_IPA_PASSES_START:
    493       case PLUGIN_ALL_IPA_PASSES_END:
    494       case PLUGIN_OVERRIDE_GATE:
    495       case PLUGIN_PASS_EXECUTION:
    496       case PLUGIN_EARLY_GIMPLE_PASSES_START:
    497       case PLUGIN_EARLY_GIMPLE_PASSES_END:
    498       case PLUGIN_NEW_PASS:
    499       case PLUGIN_INCLUDE_FILE:
    500       case PLUGIN_ANALYZER_INIT:
    501         {
    502           struct callback_info *new_callback;
    503           if (!callback)
    504             {
    505               error ("plugin %s registered a null callback function "
    506 		     "for event %s", plugin_name, plugin_event_name[event]);
    507               return;
    508             }
    509           new_callback = XNEW (struct callback_info);
    510           new_callback->plugin_name = plugin_name;
    511           new_callback->func = callback;
    512           new_callback->user_data = user_data;
    513           new_callback->next = plugin_callbacks[event];
    514           plugin_callbacks[event] = new_callback;
    515         }
    516         break;
    517     }
    518 }
    519 
    520 /* Remove a callback for EVENT which has been registered with for a plugin
    521    PLUGIN_NAME.  Return PLUGEVT_SUCCESS if a matching callback was
    522    found & removed, PLUGEVT_NO_CALLBACK if the event does not have a matching
    523    callback, and PLUGEVT_NO_SUCH_EVENT if EVENT is invalid.  */
    524 int
    525 unregister_callback (const char *plugin_name, int event)
    526 {
    527   struct callback_info *callback, **cbp;
    528 
    529   if (event >= event_last)
    530     return PLUGEVT_NO_SUCH_EVENT;
    531 
    532   for (cbp = &plugin_callbacks[event]; (callback = *cbp); cbp = &callback->next)
    533     if (strcmp (callback->plugin_name, plugin_name) == 0)
    534       {
    535 	*cbp = callback->next;
    536 	return PLUGEVT_SUCCESS;
    537       }
    538   return PLUGEVT_NO_CALLBACK;
    539 }
    540 
    541 /* Invoke all plugin callbacks registered with the specified event,
    542    called from invoke_plugin_callbacks().  */
    543 
    544 int
    545 invoke_plugin_callbacks_full (int event, void *gcc_data)
    546 {
    547   int retval = PLUGEVT_SUCCESS;
    548 
    549   timevar_push (TV_PLUGIN_RUN);
    550 
    551   switch (event)
    552     {
    553       case PLUGIN_EVENT_FIRST_DYNAMIC:
    554       default:
    555 	gcc_assert (event >= PLUGIN_EVENT_FIRST_DYNAMIC);
    556 	gcc_assert (event < event_last);
    557       /* Fall through.  */
    558       case PLUGIN_START_PARSE_FUNCTION:
    559       case PLUGIN_FINISH_PARSE_FUNCTION:
    560       case PLUGIN_FINISH_TYPE:
    561       case PLUGIN_FINISH_DECL:
    562       case PLUGIN_START_UNIT:
    563       case PLUGIN_FINISH_UNIT:
    564       case PLUGIN_PRE_GENERICIZE:
    565       case PLUGIN_ATTRIBUTES:
    566       case PLUGIN_PRAGMAS:
    567       case PLUGIN_FINISH:
    568       case PLUGIN_GGC_START:
    569       case PLUGIN_GGC_MARKING:
    570       case PLUGIN_GGC_END:
    571       case PLUGIN_ALL_PASSES_START:
    572       case PLUGIN_ALL_PASSES_END:
    573       case PLUGIN_ALL_IPA_PASSES_START:
    574       case PLUGIN_ALL_IPA_PASSES_END:
    575       case PLUGIN_OVERRIDE_GATE:
    576       case PLUGIN_PASS_EXECUTION:
    577       case PLUGIN_EARLY_GIMPLE_PASSES_START:
    578       case PLUGIN_EARLY_GIMPLE_PASSES_END:
    579       case PLUGIN_NEW_PASS:
    580       case PLUGIN_INCLUDE_FILE:
    581       case PLUGIN_ANALYZER_INIT:
    582         {
    583           /* Iterate over every callback registered with this event and
    584              call it.  */
    585           struct callback_info *callback = plugin_callbacks[event];
    586 
    587 	  if (!callback)
    588 	    retval = PLUGEVT_NO_CALLBACK;
    589           for ( ; callback; callback = callback->next)
    590             (*callback->func) (gcc_data, callback->user_data);
    591         }
    592         break;
    593 
    594       case PLUGIN_PASS_MANAGER_SETUP:
    595       case PLUGIN_REGISTER_GGC_ROOTS:
    596         gcc_assert (false);
    597     }
    598 
    599   timevar_pop (TV_PLUGIN_RUN);
    600   return retval;
    601 }
    602 
    603 #ifdef ENABLE_PLUGIN
    604 
    605 /* Try to initialize PLUGIN. Return true if successful. */
    606 
    607 #ifdef __MINGW32__
    608 
    609 // Return a message string for last error or NULL if unknown. Must be freed
    610 // with LocalFree().
    611 static inline char *
    612 win32_error_msg ()
    613 {
    614   char *msg;
    615   return FormatMessageA (FORMAT_MESSAGE_ALLOCATE_BUFFER |
    616 			 FORMAT_MESSAGE_FROM_SYSTEM |
    617 			 FORMAT_MESSAGE_IGNORE_INSERTS |
    618 			 FORMAT_MESSAGE_MAX_WIDTH_MASK,
    619 			 0,
    620 			 GetLastError (),
    621 			 MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
    622 			 (char*)&msg,
    623 			 0,
    624 			 0)
    625     ? msg
    626     : NULL;
    627 }
    628 
    629 static bool
    630 try_init_one_plugin (struct plugin_name_args *plugin)
    631 {
    632   HMODULE dl_handle;
    633   plugin_init_func plugin_init;
    634 
    635   dl_handle = LoadLibrary (plugin->full_name);
    636   if (!dl_handle)
    637     {
    638       char *err = win32_error_msg ();
    639       error ("cannot load plugin %s\n%s", plugin->full_name, err);
    640       LocalFree (err);
    641       return false;
    642     }
    643 
    644   /* Check the plugin license. Unlike the name suggests, GetProcAddress()
    645      can be used for both functions and variables.  */
    646   if (GetProcAddress (dl_handle, str_license) == NULL)
    647     {
    648       char *err = win32_error_msg ();
    649       fatal_error (input_location,
    650 		   "plugin %s is not licensed under a GPL-compatible license\n"
    651 		   "%s", plugin->full_name, err);
    652     }
    653 
    654   /* Unlike dlsym(), GetProcAddress() returns a pointer to a function so we
    655      can cast directly without union tricks.  */
    656   plugin_init = (plugin_init_func)
    657     GetProcAddress (dl_handle, str_plugin_init_func_name);
    658 
    659   if (plugin_init == NULL)
    660     {
    661       char *err = win32_error_msg ();
    662       FreeLibrary (dl_handle);
    663       error ("cannot find %s in plugin %s\n%s", str_plugin_init_func_name,
    664              plugin->full_name, err);
    665       LocalFree (err);
    666       return false;
    667     }
    668 
    669   /* Call the plugin-provided initialization routine with the arguments.  */
    670   if ((*plugin_init) (plugin, &gcc_version))
    671     {
    672       FreeLibrary (dl_handle);
    673       error ("fail to initialize plugin %s", plugin->full_name);
    674       return false;
    675     }
    676   /* Leak dl_handle on purpose to ensure the plugin is loaded for the
    677      entire run of the compiler. */
    678   return true;
    679 }
    680 
    681 #else // POSIX-like with dlopen()/dlsym().
    682 
    683 /* We need a union to cast dlsym return value to a function pointer
    684    as ISO C forbids assignment between function pointer and 'void *'.
    685    Use explicit union instead of __extension__(<union_cast>) for
    686    portability.  */
    687 #define PTR_UNION_TYPE(TOTYPE) union { void *_q; TOTYPE _nq; }
    688 #define PTR_UNION_AS_VOID_PTR(NAME) (NAME._q)
    689 #define PTR_UNION_AS_CAST_PTR(NAME) (NAME._nq)
    690 
    691 static bool
    692 try_init_one_plugin (struct plugin_name_args *plugin)
    693 {
    694   void *dl_handle;
    695   plugin_init_func plugin_init;
    696   const char *err;
    697   PTR_UNION_TYPE (plugin_init_func) plugin_init_union;
    698 
    699   /* We use RTLD_NOW to accelerate binding and detect any mismatch
    700      between the API expected by the plugin and the GCC API; we use
    701      RTLD_GLOBAL which is useful to plugins which themselves call
    702      dlopen.  */
    703   dl_handle = dlopen (plugin->full_name, RTLD_NOW | RTLD_GLOBAL);
    704   if (!dl_handle)
    705     {
    706       error ("cannot load plugin %s: %s", plugin->full_name, dlerror ());
    707       return false;
    708     }
    709 
    710   /* Clear any existing error.  */
    711   dlerror ();
    712 
    713   /* Check the plugin license.  */
    714   if (dlsym (dl_handle, str_license) == NULL)
    715     fatal_error (input_location,
    716 		 "plugin %s is not licensed under a GPL-compatible license"
    717 		 " %s", plugin->full_name, dlerror ());
    718 
    719   PTR_UNION_AS_VOID_PTR (plugin_init_union)
    720     = dlsym (dl_handle, str_plugin_init_func_name);
    721   plugin_init = PTR_UNION_AS_CAST_PTR (plugin_init_union);
    722 
    723   if ((err = dlerror ()) != NULL)
    724     {
    725       dlclose(dl_handle);
    726       error ("cannot find %s in plugin %s: %s", str_plugin_init_func_name,
    727              plugin->full_name, err);
    728       return false;
    729     }
    730 
    731   /* Call the plugin-provided initialization routine with the arguments.  */
    732   if ((*plugin_init) (plugin, &gcc_version))
    733     {
    734       dlclose(dl_handle);
    735       error ("failed to initialize plugin %s", plugin->full_name);
    736       return false;
    737     }
    738   /* leak dl_handle on purpose to ensure the plugin is loaded for the
    739      entire run of the compiler. */
    740   return true;
    741 }
    742 #endif
    743 
    744 /* Routine to dlopen and initialize one plugin. This function is passed to
    745    (and called by) the hash table traverse routine. Return 1 for the
    746    htab_traverse to continue scan, 0 to stop.
    747 
    748    SLOT - slot of the hash table element
    749    INFO - auxiliary pointer handed to hash table traverse routine
    750           (unused in this function)  */
    751 
    752 static int
    753 init_one_plugin (void **slot, void * ARG_UNUSED (info))
    754 {
    755   struct plugin_name_args *plugin = (struct plugin_name_args *) *slot;
    756   bool ok = try_init_one_plugin (plugin);
    757   if (!ok)
    758     {
    759       htab_remove_elt_with_hash (plugin_name_args_tab, plugin->base_name,
    760 				 htab_hash_string (plugin->base_name));
    761       XDELETE (plugin);
    762     }
    763   return 1;
    764 }
    765 
    766 #endif	/* ENABLE_PLUGIN  */
    767 
    768 /* Main plugin initialization function.  Called from compile_file() in
    769    toplev.cc.  */
    770 
    771 void
    772 initialize_plugins (void)
    773 {
    774   /* If no plugin was specified in the command-line, simply return.  */
    775   if (!plugin_name_args_tab)
    776     return;
    777 
    778   timevar_push (TV_PLUGIN_INIT);
    779 
    780 #ifdef ENABLE_PLUGIN
    781   /* Traverse and initialize each plugin specified in the command-line.  */
    782   htab_traverse_noresize (plugin_name_args_tab, init_one_plugin, NULL);
    783 #endif
    784 
    785   timevar_pop (TV_PLUGIN_INIT);
    786 }
    787 
    788 /* Release memory used by one plugin. */
    789 
    790 static int
    791 finalize_one_plugin (void **slot, void * ARG_UNUSED (info))
    792 {
    793   struct plugin_name_args *plugin = (struct plugin_name_args *) *slot;
    794   XDELETE (plugin);
    795   return 1;
    796 }
    797 
    798 /* Free memory allocated by the plugin system. */
    799 
    800 void
    801 finalize_plugins (void)
    802 {
    803   if (!plugin_name_args_tab)
    804     return;
    805 
    806   /* We can now delete the plugin_name_args object as it will no longer
    807      be used. Note that base_name and argv fields (both of which were also
    808      dynamically allocated) are not freed as they could still be used by
    809      the plugin code.  */
    810 
    811   htab_traverse_noresize (plugin_name_args_tab, finalize_one_plugin, NULL);
    812 
    813   /* PLUGIN_NAME_ARGS_TAB is no longer needed, just delete it.  */
    814   htab_delete (plugin_name_args_tab);
    815   plugin_name_args_tab = NULL;
    816 }
    817 
    818 /* Used to pass options to htab_traverse callbacks. */
    819 
    820 struct print_options
    821 {
    822   FILE *file;
    823   const char *indent;
    824 };
    825 
    826 /* Print the version of one plugin. */
    827 
    828 static int
    829 print_version_one_plugin (void **slot, void *data)
    830 {
    831   struct print_options *opt = (struct print_options *) data;
    832   struct plugin_name_args *plugin = (struct plugin_name_args *) *slot;
    833   const char *version = plugin->version ? plugin->version : "Unknown version.";
    834 
    835   fprintf (opt->file, " %s%s: %s\n", opt->indent, plugin->base_name, version);
    836   return 1;
    837 }
    838 
    839 /* Print the version of each plugin. */
    840 
    841 void
    842 print_plugins_versions (FILE *file, const char *indent)
    843 {
    844   struct print_options opt;
    845   opt.file = file;
    846   opt.indent = indent;
    847   if (!plugin_name_args_tab || htab_elements (plugin_name_args_tab) == 0)
    848     return;
    849 
    850   fprintf (file, "%sVersions of loaded plugins:\n", indent);
    851   htab_traverse_noresize (plugin_name_args_tab, print_version_one_plugin, &opt);
    852 }
    853 
    854 /* Print help for one plugin. SLOT is the hash table slot. DATA is the
    855    argument to htab_traverse_noresize. */
    856 
    857 static int
    858 print_help_one_plugin (void **slot, void *data)
    859 {
    860   struct print_options *opt = (struct print_options *) data;
    861   struct plugin_name_args *plugin = (struct plugin_name_args *) *slot;
    862   const char *help = plugin->help ? plugin->help : "No help available .";
    863 
    864   char *dup = xstrdup (help);
    865   char *p, *nl;
    866   fprintf (opt->file, " %s%s:\n", opt->indent, plugin->base_name);
    867 
    868   for (p = nl = dup; nl; p = nl)
    869     {
    870       nl = strchr (nl, '\n');
    871       if (nl)
    872 	{
    873 	  *nl = '\0';
    874 	  nl++;
    875 	}
    876       fprintf (opt->file, "   %s %s\n", opt->indent, p);
    877     }
    878 
    879   free (dup);
    880   return 1;
    881 }
    882 
    883 /* Print help for each plugin. The output goes to FILE and every line starts
    884    with INDENT. */
    885 
    886 void
    887 print_plugins_help (FILE *file, const char *indent)
    888 {
    889   struct print_options opt;
    890   opt.file = file;
    891   opt.indent = indent;
    892   if (!plugin_name_args_tab || htab_elements (plugin_name_args_tab) == 0)
    893     return;
    894 
    895   fprintf (file, "%sHelp for the loaded plugins:\n", indent);
    896   htab_traverse_noresize (plugin_name_args_tab, print_help_one_plugin, &opt);
    897 }
    898 
    899 
    900 /* Return true if plugins have been loaded.  */
    901 
    902 bool
    903 plugins_active_p (void)
    904 {
    905   int event;
    906 
    907   for (event = PLUGIN_PASS_MANAGER_SETUP; event < event_last; event++)
    908     if (plugin_callbacks[event])
    909       return true;
    910 
    911   return false;
    912 }
    913 
    914 
    915 /* Dump to FILE the names and associated events for all the active
    916    plugins.  */
    917 
    918 DEBUG_FUNCTION void
    919 dump_active_plugins (FILE *file)
    920 {
    921   int event;
    922 
    923   if (!plugins_active_p ())
    924     return;
    925 
    926   fprintf (file, FMT_FOR_PLUGIN_EVENT " | %s\n", _("Event"), _("Plugins"));
    927   for (event = PLUGIN_PASS_MANAGER_SETUP; event < event_last; event++)
    928     if (plugin_callbacks[event])
    929       {
    930 	struct callback_info *ci;
    931 
    932 	fprintf (file, FMT_FOR_PLUGIN_EVENT " |", plugin_event_name[event]);
    933 
    934 	for (ci = plugin_callbacks[event]; ci; ci = ci->next)
    935 	  fprintf (file, " %s", ci->plugin_name);
    936 
    937 	putc ('\n', file);
    938       }
    939 }
    940 
    941 
    942 /* Dump active plugins to stderr.  */
    943 
    944 DEBUG_FUNCTION void
    945 debug_active_plugins (void)
    946 {
    947   dump_active_plugins (stderr);
    948 }
    949 
    950 /* Give a warning if plugins are present, before an ICE message asking
    951    to submit a bug report.  */
    952 
    953 void
    954 warn_if_plugins (void)
    955 {
    956   if (plugins_active_p ())
    957     {
    958       fnotice (stderr, "*** WARNING *** there are active plugins, do not report"
    959 	       " this as a bug unless you can reproduce it without enabling"
    960 	       " any plugins.\n");
    961       dump_active_plugins (stderr);
    962     }
    963 
    964 }
    965 
    966 /* The default version check. Compares every field in VERSION. */
    967 
    968 bool
    969 plugin_default_version_check (struct plugin_gcc_version *gcc_version,
    970 			      struct plugin_gcc_version *plugin_version)
    971 {
    972   if (!gcc_version || !plugin_version)
    973     return false;
    974 
    975   if (strcmp (gcc_version->basever, plugin_version->basever))
    976     return false;
    977   if (strcmp (gcc_version->datestamp, plugin_version->datestamp))
    978     return false;
    979   if (strcmp (gcc_version->devphase, plugin_version->devphase))
    980     return false;
    981   if (strcmp (gcc_version->revision, plugin_version->revision))
    982     return false;
    983   if (strcmp (gcc_version->configuration_arguments,
    984 	      plugin_version->configuration_arguments))
    985     return false;
    986   return true;
    987 }
    988 
    989 
    990 /* Return the current value of event_last, so that plugins which provide
    991    additional functionality for events for the benefit of high-level plugins
    992    know how many valid entries plugin_event_name holds.  */
    993 
    994 int
    995 get_event_last (void)
    996 {
    997   return event_last;
    998 }
    999 
   1000 
   1001 /* Retrieve the default plugin directory.  The gcc driver should have passed
   1002    it as -iplugindir <dir> to the cc1 program, and it is queriable through the
   1003    -print-file-name=plugin option to gcc.  */
   1004 const char*
   1005 default_plugin_dir_name (void)
   1006 {
   1007   if (!plugindir_string)
   1008     fatal_error (input_location,
   1009 		 "%<-iplugindir%> option not passed from the gcc driver");
   1010   return plugindir_string;
   1011 }
   1012