OSDN Git Service

2d64422787eb43a9fae255175e64af86ec6f993e
[pf3gnuchains/gcc-fork.git] / gcc / plugin.c
1 /* Support for GCC plugin mechanism.
2    Copyright (C) 2009 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
26 /* If plugin support is not enabled, do not try to execute any code
27    that may reference libdl.  The generic code is still compiled in to
28    avoid including too many conditional compilation paths in the rest
29    of the compiler.  */
30 #ifdef ENABLE_PLUGIN
31 #include <dlfcn.h>
32 #endif
33
34 #include "coretypes.h"
35 #include "toplev.h"
36 #include "tree.h"
37 #include "tree-pass.h"
38 #include "intl.h"
39 #include "plugin.h"
40 #include "timevar.h"
41 #include "ggc.h"
42
43 #ifdef ENABLE_PLUGIN
44 #include "plugin-version.h"
45 #endif
46
47 /* Event names as strings.  Keep in sync with enum plugin_event.  */
48 const char *plugin_event_name[] =
49 {
50   "PLUGIN_PASS_MANAGER_SETUP",
51   "PLUGIN_FINISH_TYPE",
52   "PLUGIN_FINISH_UNIT",
53   "PLUGIN_CXX_CP_PRE_GENERICIZE",
54   "PLUGIN_FINISH",
55   "PLUGIN_INFO",
56   "PLUGIN_GGC_START",
57   "PLUGIN_GGC_MARKING",
58   "PLUGIN_GGC_END",
59   "PLUGIN_REGISTER_GGC_ROOTS",
60   "PLUGIN_REGISTER_GGC_CACHES",
61   "PLUGIN_ATTRIBUTES",
62   "PLUGIN_START_UNIT",
63   "PLUGIN_PRAGMAS",
64   "PLUGIN_EVENT_LAST"
65 };
66
67 /* Hash table for the plugin_name_args objects created during command-line
68    parsing.  */
69 static htab_t plugin_name_args_tab = NULL;
70
71 /* List node for keeping track of plugin-registered callback.  */
72 struct callback_info
73 {
74   const char *plugin_name;   /* Name of plugin that registers the callback.  */
75   plugin_callback_func func; /* Callback to be called.  */
76   void *user_data;           /* plugin-specified data.  */
77   struct callback_info *next;
78 };
79
80 /* An array of lists of 'callback_info' objects indexed by the event id.  */
81 static struct callback_info *plugin_callbacks[PLUGIN_EVENT_LAST] = { NULL };
82
83
84 #ifdef ENABLE_PLUGIN
85 /* Each plugin should define an initialization function with exactly
86    this name.  */
87 static const char *str_plugin_init_func_name = "plugin_init";
88
89 /* Each plugin should define this symbol to assert that it is
90    distributed under a GPL-compatible license.  */
91 static const char *str_license = "plugin_is_GPL_compatible";
92 #endif
93
94 /* Helper function for the hash table that compares the base_name of the
95    existing entry (S1) with the given string (S2).  */
96
97 static int
98 htab_str_eq (const void *s1, const void *s2)
99 {
100   const struct plugin_name_args *plugin = (const struct plugin_name_args *) s1;
101   return !strcmp (plugin->base_name, (const char *) s2);
102 }
103
104
105 /* Given a plugin's full-path name FULL_NAME, e.g. /pass/to/NAME.so,
106    return NAME.  */
107
108 static char *
109 get_plugin_base_name (const char *full_name)
110 {
111   /* First get the base name part of the full-path name, i.e. NAME.so.  */
112   char *base_name = xstrdup (lbasename (full_name));
113
114   /* Then get rid of '.so' part of the name.  */
115   strip_off_ending (base_name, strlen (base_name));
116
117   return base_name;
118 }
119
120
121 /* Create a plugin_name_args object for the give plugin and insert it to
122    the hash table. This function is called when -fplugin=/path/to/NAME.so
123    option is processed.  */
124
125 void
126 add_new_plugin (const char* plugin_name)
127 {
128   struct plugin_name_args *plugin;
129   void **slot;
130   char *base_name = get_plugin_base_name (plugin_name);
131
132   /* If this is the first -fplugin= option we encounter, create 
133      'plugin_name_args_tab' hash table.  */
134   if (!plugin_name_args_tab)
135     plugin_name_args_tab = htab_create (10, htab_hash_string, htab_str_eq,
136                                         NULL);
137
138   slot = htab_find_slot (plugin_name_args_tab, base_name, INSERT);
139
140   /* If the same plugin (name) has been specified earlier, either emit an
141      error or a warning message depending on if they have identical full
142      (path) names.  */
143   if (*slot)
144     {
145       plugin = (struct plugin_name_args *) *slot;
146       if (strcmp (plugin->full_name, plugin_name))
147         error ("Plugin %s was specified with different paths:\n%s\n%s",
148                plugin->base_name, plugin->full_name, plugin_name);
149       return;
150     }
151
152   plugin = XCNEW (struct plugin_name_args);
153   plugin->base_name = base_name;
154   plugin->full_name = plugin_name;
155
156   *slot = plugin;
157 }
158
159
160 /* Parse the -fplugin-arg-<name>-<key>[=<value>] option and create a
161    'plugin_argument' object for the parsed key-value pair. ARG is
162    the <name>-<key>[=<value>] part of the option.  */
163
164 void
165 parse_plugin_arg_opt (const char *arg)
166 {
167   size_t len = 0, name_len = 0, key_len = 0, value_len = 0;
168   const char *ptr, *name_start = arg, *key_start = NULL, *value_start = NULL;
169   char *name, *key, *value;
170   void **slot;
171   bool name_parsed = false, key_parsed = false;
172
173   /* Iterate over the ARG string and identify the starting character position
174      of 'name', 'key', and 'value' and their lengths.  */
175   for (ptr = arg; *ptr; ++ptr)
176     {
177       /* Only the first '-' encountered is considered a separator between
178          'name' and 'key'. All the subsequent '-'s are considered part of
179          'key'. For example, given -fplugin-arg-foo-bar-primary-key=value,
180          the plugin name is 'foo' and the key is 'bar-primary-key'.  */
181       if (*ptr == '-' && !name_parsed)
182         {
183           name_len = len;
184           len = 0;
185           key_start = ptr + 1;
186           name_parsed = true;
187           continue;
188         }
189       else if (*ptr == '=')
190         {
191           if (key_parsed)
192             {
193               error ("Malformed option -fplugin-arg-%s (multiple '=' signs)",
194                      arg);
195               return;
196             }
197           key_len = len;
198           len = 0;
199           value_start = ptr + 1;
200           key_parsed = true;
201           continue;
202         }
203       else
204         ++len;
205     }
206
207   if (!key_start)
208     {
209       error ("Malformed option -fplugin-arg-%s (missing -<key>[=<value>])",
210              arg);
211       return;
212     }
213
214   /* If the option doesn't contain the 'value' part, LEN is the KEY_LEN.
215      Otherwise, it is the VALUE_LEN.  */
216   if (!value_start)
217     key_len = len;
218   else
219     value_len = len;
220
221   name = XNEWVEC (char, name_len + 1);
222   strncpy (name, name_start, name_len);
223   name[name_len] = '\0';
224
225   /* Check if the named plugin has already been specified earlier in the
226      command-line.  */
227   if (plugin_name_args_tab
228       && ((slot = htab_find_slot (plugin_name_args_tab, name, NO_INSERT))
229           != NULL))
230     {
231       struct plugin_name_args *plugin = (struct plugin_name_args *) *slot;
232
233       key = XNEWVEC (char, key_len + 1);
234       strncpy (key, key_start, key_len);
235       key[key_len] = '\0';
236       if (value_start)
237         {
238           value = XNEWVEC (char, value_len + 1);
239           strncpy (value, value_start, value_len);
240           value[value_len] = '\0';
241         }
242       else
243         value = NULL;
244
245       /* Create a plugin_argument object for the parsed key-value pair.
246          If there are already arguments for this plugin, we will need to
247          adjust the argument array size by creating a new array and deleting
248          the old one. If the performance ever becomes an issue, we can
249          change the code by pre-allocating a larger array first.  */
250       if (plugin->argc > 0)
251         {
252           struct plugin_argument *args = XNEWVEC (struct plugin_argument,
253                                                   plugin->argc + 1);
254           memcpy (args, plugin->argv,
255                   sizeof (struct plugin_argument) * plugin->argc);
256           XDELETEVEC (plugin->argv);
257           plugin->argv = args;
258           ++plugin->argc;
259         }
260       else
261         {
262           gcc_assert (plugin->argv == NULL);
263           plugin->argv = XNEWVEC (struct plugin_argument, 1);
264           plugin->argc = 1;
265         }
266
267       plugin->argv[plugin->argc - 1].key = key;
268       plugin->argv[plugin->argc - 1].value = value;
269     }
270   else
271     error ("Plugin %s should be specified before -fplugin-arg-%s "
272            "in the command line", name, arg);
273
274   /* We don't need the plugin's name anymore. Just release it.  */
275   XDELETEVEC (name);
276 }
277
278 /* Register additional plugin information. NAME is the name passed to
279    plugin_init. INFO is the information that should be registered. */
280
281 static void
282 register_plugin_info (const char* name, struct plugin_info *info)
283 {
284   void **slot = htab_find_slot (plugin_name_args_tab, name, NO_INSERT);
285   struct plugin_name_args *plugin = (struct plugin_name_args *) *slot;
286   plugin->version = info->version;
287   plugin->help = info->help;
288 }
289
290 /* Called from the plugin's initialization code. Register a single callback.
291    This function can be called multiple times.
292
293    PLUGIN_NAME - display name for this plugin
294    EVENT       - which event the callback is for
295    CALLBACK    - the callback to be called at the event
296    USER_DATA   - plugin-provided data   */
297
298 void
299 register_callback (const char *plugin_name,
300                    enum plugin_event event,
301                    plugin_callback_func callback,
302                    void *user_data)
303 {
304   switch (event)
305     {
306       case PLUGIN_PASS_MANAGER_SETUP:
307         gcc_assert (!callback);
308         register_pass ((struct register_pass_info *) user_data);
309         break;
310       case PLUGIN_INFO:
311         gcc_assert (!callback);
312         register_plugin_info (plugin_name, (struct plugin_info *) user_data);
313         break;
314       case PLUGIN_REGISTER_GGC_ROOTS:
315         gcc_assert (!callback);
316         ggc_register_root_tab ((const struct ggc_root_tab*) user_data);
317         break;
318       case PLUGIN_REGISTER_GGC_CACHES:
319         gcc_assert (!callback);
320         ggc_register_cache_tab ((const struct ggc_cache_tab*) user_data);
321         break;
322       case PLUGIN_FINISH_TYPE:
323       case PLUGIN_START_UNIT:
324       case PLUGIN_FINISH_UNIT:
325       case PLUGIN_CXX_CP_PRE_GENERICIZE:
326       case PLUGIN_GGC_START:
327       case PLUGIN_GGC_MARKING:
328       case PLUGIN_GGC_END:
329       case PLUGIN_ATTRIBUTES:
330       case PLUGIN_PRAGMAS:
331       case PLUGIN_FINISH:
332         {
333           struct callback_info *new_callback;
334           if (!callback)
335             {
336               error ("Plugin %s registered a null callback function "
337                      "for event %s", plugin_name, plugin_event_name[event]);
338               return;
339             }
340           new_callback = XNEW (struct callback_info);
341           new_callback->plugin_name = plugin_name;
342           new_callback->func = callback;
343           new_callback->user_data = user_data;
344           new_callback->next = plugin_callbacks[event];
345           plugin_callbacks[event] = new_callback;
346         }
347         break;
348       case PLUGIN_EVENT_LAST:
349       default:
350         error ("Unknown callback event registered by plugin %s",
351                plugin_name);
352     }
353 }
354
355
356 /* Called from inside GCC.  Invoke all plug-in callbacks registered with
357    the specified event.
358
359    EVENT    - the event identifier
360    GCC_DATA - event-specific data provided by the compiler  */
361
362 void
363 invoke_plugin_callbacks (enum plugin_event event, void *gcc_data)
364 {
365   timevar_push (TV_PLUGIN_RUN);
366
367   switch (event)
368     {
369       case PLUGIN_FINISH_TYPE:
370       case PLUGIN_START_UNIT:
371       case PLUGIN_FINISH_UNIT:
372       case PLUGIN_CXX_CP_PRE_GENERICIZE:
373       case PLUGIN_ATTRIBUTES:
374       case PLUGIN_PRAGMAS:
375       case PLUGIN_FINISH:
376       case PLUGIN_GGC_START:
377       case PLUGIN_GGC_MARKING:
378       case PLUGIN_GGC_END:
379         {
380           /* Iterate over every callback registered with this event and
381              call it.  */
382           struct callback_info *callback = plugin_callbacks[event];
383           for ( ; callback; callback = callback->next)
384             (*callback->func) (gcc_data, callback->user_data);
385         }
386         break;
387
388       case PLUGIN_PASS_MANAGER_SETUP:
389       case PLUGIN_EVENT_LAST:
390       case PLUGIN_REGISTER_GGC_ROOTS:
391       case PLUGIN_REGISTER_GGC_CACHES:
392       default:
393         gcc_assert (false);
394     }
395
396   timevar_pop (TV_PLUGIN_RUN);
397 }
398
399 #ifdef ENABLE_PLUGIN
400 /* We need a union to cast dlsym return value to a function pointer
401    as ISO C forbids assignment between function pointer and 'void *'.
402    Use explicit union instead of __extension__(<union_cast>) for
403    portability.  */
404 #define PTR_UNION_TYPE(TOTYPE) union { void *_q; TOTYPE _nq; }
405 #define PTR_UNION_AS_VOID_PTR(NAME) (NAME._q)
406 #define PTR_UNION_AS_CAST_PTR(NAME) (NAME._nq)
407
408 /* Try to initialize PLUGIN. Return true if successful. */
409
410 static bool
411 try_init_one_plugin (struct plugin_name_args *plugin)
412 {
413   void *dl_handle;
414   plugin_init_func plugin_init;
415   const char *err;
416   PTR_UNION_TYPE (plugin_init_func) plugin_init_union;
417
418   /* We use RTLD_NOW to accelerate binding and detect any mismatch
419      between the API expected by the plugin and the GCC API; we use
420      RTLD_GLOBAL which is useful to plugins which themselves call
421      dlopen.  */
422   dl_handle = dlopen (plugin->full_name, RTLD_NOW | RTLD_GLOBAL);
423   if (!dl_handle)
424     {
425       error ("Cannot load plugin %s\n%s", plugin->full_name, dlerror ());
426       return false;
427     }
428
429   /* Clear any existing error.  */
430   dlerror ();
431
432   /* Check the plugin license.  */
433   if (dlsym (dl_handle, str_license) == NULL)
434     fatal_error ("plugin %s is not licensed under a GPL-compatible license\n"
435                  "%s", plugin->full_name, dlerror ());
436
437   PTR_UNION_AS_VOID_PTR (plugin_init_union) =
438       dlsym (dl_handle, str_plugin_init_func_name);
439   plugin_init = PTR_UNION_AS_CAST_PTR (plugin_init_union);
440
441   if ((err = dlerror ()) != NULL)
442     {
443       error ("Cannot find %s in plugin %s\n%s", str_plugin_init_func_name,
444              plugin->full_name, err);
445       return false;
446     }
447
448   /* Call the plugin-provided initialization routine with the arguments.  */
449   if ((*plugin_init) (plugin, &gcc_version))
450     {
451       error ("Fail to initialize plugin %s", plugin->full_name);
452       return false;
453     }
454
455   return true;
456 }
457
458
459 /* Routine to dlopen and initialize one plugin. This function is passed to
460    (and called by) the hash table traverse routine. Return 1 for the
461    htab_traverse to continue scan, 0 to stop.
462
463    SLOT - slot of the hash table element
464    INFO - auxiliary pointer handed to hash table traverse routine
465           (unused in this function)  */
466
467 static int
468 init_one_plugin (void **slot, void * ARG_UNUSED (info))
469 {
470   struct plugin_name_args *plugin = (struct plugin_name_args *) *slot;
471   bool ok = try_init_one_plugin (plugin);
472   if (!ok)
473     {
474       htab_remove_elt (plugin_name_args_tab, plugin->base_name);
475       XDELETE (plugin);
476     }
477   return 1;
478 }
479
480 #endif  /* ENABLE_PLUGIN  */
481
482 /* Main plugin initialization function.  Called from compile_file() in
483    toplev.c.  */
484
485 void
486 initialize_plugins (void)
487 {
488   /* If no plugin was specified in the command-line, simply return.  */
489   if (!plugin_name_args_tab)
490     return;
491
492   timevar_push (TV_PLUGIN_INIT);
493  
494 #ifdef ENABLE_PLUGIN
495   /* Traverse and initialize each plugin specified in the command-line.  */
496   htab_traverse_noresize (plugin_name_args_tab, init_one_plugin, NULL);
497 #endif
498
499   timevar_pop (TV_PLUGIN_INIT);
500 }
501
502 /* Release memory used by one plugin. */
503
504 static int
505 finalize_one_plugin (void **slot, void * ARG_UNUSED (info))
506 {
507   struct plugin_name_args *plugin = (struct plugin_name_args *) *slot;
508   XDELETE (plugin);
509   return 1;
510 }
511
512 /* Free memory allocated by the plugin system. */
513
514 void
515 finalize_plugins (void)
516 {
517   if (!plugin_name_args_tab)
518     return;
519
520   /* We can now delete the plugin_name_args object as it will no longer
521      be used. Note that base_name and argv fields (both of which were also
522      dynamically allocated) are not freed as they could still be used by
523      the plugin code.  */
524
525   htab_traverse_noresize (plugin_name_args_tab, finalize_one_plugin, NULL);
526
527   /* PLUGIN_NAME_ARGS_TAB is no longer needed, just delete it.  */
528   htab_delete (plugin_name_args_tab);
529   plugin_name_args_tab = NULL;
530 }
531
532 /* Used to pass options to htab_traverse callbacks. */
533
534 struct print_options
535 {
536   FILE *file;
537   const char *indent;
538 };
539
540 /* Print the version of one plugin. */
541
542 static int
543 print_version_one_plugin (void **slot, void *data)
544 {
545   struct print_options *opt = (struct print_options *) data;
546   struct plugin_name_args *plugin = (struct plugin_name_args *) *slot;
547   const char *version = plugin->version ? plugin->version : "Unknown version.";
548
549   fprintf (opt->file, " %s%s: %s\n", opt->indent, plugin->base_name, version);
550   return 1;
551 }
552
553 /* Print the version of each plugin. */
554
555 void
556 print_plugins_versions (FILE *file, const char *indent)
557 {
558   struct print_options opt;
559   opt.file = file;
560   opt.indent = indent;
561   if (!plugin_name_args_tab || htab_elements (plugin_name_args_tab) == 0)
562     return;
563
564   fprintf (file, "%sVersions of loaded plugins:\n", indent);
565   htab_traverse_noresize (plugin_name_args_tab, print_version_one_plugin, &opt);
566 }
567
568 /* Print help for one plugin. SLOT is the hash table slot. DATA is the
569    argument to htab_traverse_noresize. */
570
571 static int
572 print_help_one_plugin (void **slot, void *data)
573 {
574   struct print_options *opt = (struct print_options *) data;
575   struct plugin_name_args *plugin = (struct plugin_name_args *) *slot;
576   const char *help = plugin->help ? plugin->help : "No help available .";
577
578   char *dup = xstrdup (help);
579   char *p, *nl;
580   fprintf (opt->file, " %s%s:\n", opt->indent, plugin->base_name);
581
582   for (p = nl = dup; nl; p = nl)
583     {
584       nl = strchr (nl, '\n');
585       if (nl)
586         {
587           *nl = '\0';
588           nl++;
589         }
590       fprintf (opt->file, "   %s %s\n", opt->indent, p);
591     }
592
593   free (dup);
594   return 1;
595 }
596
597 /* Print help for each plugin. The output goes to FILE and every line starts
598    with INDENT. */
599
600 void
601 print_plugins_help (FILE *file, const char *indent)
602 {
603   struct print_options opt;
604   opt.file = file;
605   opt.indent = indent;
606   if (!plugin_name_args_tab || htab_elements (plugin_name_args_tab) == 0)
607     return;
608
609   fprintf (file, "%sHelp for the loaded plugins:\n", indent);
610   htab_traverse_noresize (plugin_name_args_tab, print_help_one_plugin, &opt);
611 }
612
613
614 /* Return true if plugins have been loaded.  */
615
616 bool
617 plugins_active_p (void)
618 {
619   int event;
620
621   for (event = PLUGIN_PASS_MANAGER_SETUP; event < PLUGIN_EVENT_LAST; event++)
622     if (plugin_callbacks[event])
623       return true;
624
625   return false;
626 }
627
628
629 /* Dump to FILE the names and associated events for all the active
630    plugins.  */
631
632 void
633 dump_active_plugins (FILE *file)
634 {
635   int event;
636
637   if (!plugins_active_p ())
638     return;
639
640   fprintf (stderr, "Event\t\t\tPlugins\n");
641   for (event = PLUGIN_PASS_MANAGER_SETUP; event < PLUGIN_EVENT_LAST; event++)
642     if (plugin_callbacks[event])
643       {
644         struct callback_info *ci;
645
646         fprintf (file, "%s\t", plugin_event_name[event]);
647
648         for (ci = plugin_callbacks[event]; ci; ci = ci->next)
649           fprintf (file, "%s ", ci->plugin_name);
650
651         fprintf (file, "\n");
652       }
653 }
654
655
656 /* Dump active plugins to stderr.  */
657
658 void
659 debug_active_plugins (void)
660 {
661   dump_active_plugins (stderr);
662 }
663
664 /* The default version check. Compares every field in VERSION. */
665
666 bool
667 plugin_default_version_check (struct plugin_gcc_version *gcc_version,
668                               struct plugin_gcc_version *plugin_version)
669 {
670   if (!gcc_version || !plugin_version)
671     return false;
672
673   if (strcmp (gcc_version->basever, plugin_version->basever))
674     return false;
675   if (strcmp (gcc_version->datestamp, plugin_version->datestamp))
676     return false;
677   if (strcmp (gcc_version->devphase, plugin_version->devphase))
678     return false;
679   if (strcmp (gcc_version->revision, plugin_version->revision))
680     return false;
681   if (strcmp (gcc_version->configuration_arguments,
682               plugin_version->configuration_arguments))
683     return false;
684   return true;
685 }