This patch supplies the {Make|config}-plugin.in files for the analyzer, along with the entrypoint to the plugin, and the driver logic for converting "--analyzer" into the option to inject the plugin.
gcc/ChangeLog: * analyzer/Make-plugin.in: New file. * analyzer/analyzer-plugin.cc: New file. * analyzer/config-plugin.in: New file. * gcc.c (driver_handle_option): Handle "--analyzer" by injecting the plugin, if available. --- gcc/analyzer/Make-plugin.in | 181 ++++++++++++++++++++++++++++++++++++++++ gcc/analyzer/analyzer-plugin.cc | 63 ++++++++++++++ gcc/analyzer/config-plugin.in | 34 ++++++++ gcc/gcc.c | 13 +++ 4 files changed, 291 insertions(+) create mode 100644 gcc/analyzer/Make-plugin.in create mode 100644 gcc/analyzer/analyzer-plugin.cc create mode 100644 gcc/analyzer/config-plugin.in diff --git a/gcc/analyzer/Make-plugin.in b/gcc/analyzer/Make-plugin.in new file mode 100644 index 0000000..08c96f1 --- /dev/null +++ b/gcc/analyzer/Make-plugin.in @@ -0,0 +1,181 @@ +# Top level -*- makefile -*- fragment for analyzer +# Copyright (C) 2013-2019 Free Software Foundation, Inc. + +#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/>. + +# This file provides the plugin dependent support in the main Makefile. +# Each plugin makefile fragment must provide the following targets: +# +# foo.all.cross, foo.start.encap, foo.rest.encap, +# foo.install-common, foo.install-man, foo.install-info, foo.install-pdf, +# foo.install-html, foo.info, foo.dvi, foo.pdf, foo.html, foo.uninstall, +# foo.mostlyclean, foo.clean, foo.distclean, +# foo.maintainer-clean, foo.stage1, foo.stage2, foo.stage3, foo.stage4 +# +# where `foo' is the name of the plugin. +# +# It should also provide rules for: +# +# - making any compiler driver (eg: g++) +# - the plugin proper (eg: analyzer_plugin.so) +# - define the names for selecting the plugin in PLUGINS. + +# +# Define the names for selecting analyzer in PLUGINS. +# Note that it would be nice to move the dependency on g++ +# into the analyzer rule, but that needs a little bit of work +# to do the right thing within all.cross. + +plugin_builddir = plugin + +ANALYZER_PLUGIN_SO = $(plugin_builddir)/analyzer_plugin.so + +analyzer: \ + $(FULL_DRIVER_NAME) \ + $(ANALYZER_PLUGIN_SO) + +# Tell GNU make to ignore these if they exist. +.PHONY: analyzer + +# Files that are linked into analyzer plugin + +analyzer_OBJS = \ + analyzer/analysis-plan.o \ + analyzer/analyzer.o \ + analyzer/analyzer-logging.o \ + analyzer/analyzer-pass.o \ + analyzer/analyzer-plugin.o \ + analyzer/analyzer-selftests.o \ + analyzer/call-string.o \ + analyzer/checker-path.o \ + analyzer/constraint-manager.o \ + analyzer/diagnostic-manager.o \ + analyzer/digraph.o \ + analyzer/graphviz.o \ + analyzer/engine.o \ + analyzer/pending-diagnostic.o \ + analyzer/program-point.o \ + analyzer/program-state.o \ + analyzer/region-model.o \ + analyzer/sm.o \ + analyzer/sm-file.o \ + analyzer/sm-malloc.o \ + analyzer/sm-pattern-test.o \ + analyzer/sm-sensitive.o \ + analyzer/sm-taint.o \ + analyzer/state-purge.o \ + analyzer/supergraph.o \ + analyzer/tristate.o \ + +# Use strict warnings for this plugin. +analyzer-warn = $(STRICT_WARN) + +# +# Build hooks: + +analyzer.all.cross: +analyzer.start.encap: +analyzer.rest.encap: + +$(plugin_builddir): + mkdir $@ + +$(ANALYZER_PLUGIN_SO): $(analyzer_OBJS) $(plugin_builddir) + $(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) \ + -o $@ \ + -shared \ + $(analyzer_OBJS) \ + -lpthread + +# If the analyzer is enabled, require the selftests to be run for it +# at each stage of the build: +selftest-analyzer: s-selftest-analyzer + +ANALYZER_SELFTEST_FLAGS = -xc $(SELFTEST_FLAGS) --analyzer +ANALYZER_SELFTEST_DEPS = cc1$(exeext) $(SELFTEST_DEPS) $(ANALYZER_PLUGIN_SO) + +# Run the analyzer selftests: +s-selftest-analyzer: $(ANALYZER_SELFTEST_DEPS) + $(GCC_FOR_TARGET) $(ANALYZER_SELFTEST_FLAGS) + $(STAMP) $@ + +# Convenience methods for running analyzer selftests under gdb: +.PHONY: selftest-analyzer-gdb +selftest-analyzer-gdb: $(ANALYZER_SELFTEST_DEPS) + $(GCC_FOR_TARGET) $(ANALYZER_SELFTEST_FLAGS) \ + -wrapper gdb,--args + +# Convenience methods for running analyzer selftests under valgrind: +.PHONY: selftest-analyzer-valgrind +selftest-analyzer-valgrind: $(ANALYZER_SELFTEST_DEPS) + $(GCC_FOR_TARGET) $(ANALYZER_SELFTEST_FLAGS) \ + -wrapper valgrind,--leak-check=full + +# Documentation build hooks. +analyzer.info: +analyzer.dvi: +analyzer.pdf: +analyzer.html: +analyzer.srcinfo: +analyzer.man: +analyzer.srcman: + +# Testing hooks: +lang_checks += check-analyzer + +# +# Install hooks: +analyzer.install-common: +analyzer.install-man: +analyzer.install-info: +analyzer.install-pdf: +analyzer.install-html: + +analyzer.install-plugin: installdirs + $(INSTALL_DATA) $(ANALYZER_PLUGIN_SO) $(DESTDIR)/$(plugin_resourcesdir)/analyzer_plugin.so + +analyzer.uninstall: + +# +# Clean hooks: +# A lot of the ancillary files are deleted by the main makefile. +# We just have to delete files specific to us. + +analyzer.mostlyclean: + +analyzer.clean: + +analyzer.distclean: + +analyzer.maintainer-clean: + +# +# Stage hooks: +# The main makefile has already created stage?/analyzer. + +analyzer.stage1: stage1-start + -mv analyzer/*$(objext) stage1/analyzer +analyzer.stage2: stage2-start + -mv analyzer/*$(objext) stage2/analyzer +analyzer.stage3: stage3-start + -mv analyzer/*$(objext) stage3/analyzer +analyzer.stage4: stage4-start + -mv analyzer/*$(objext) stage4/analyzer +analyzer.stageprofile: stageprofile-start + -mv analyzer/*$(objext) stageprofile/analyzer +analyzer.stagefeedback: stagefeedback-start + -mv analyzer/*$(objext) stagefeedback/analyzer diff --git a/gcc/analyzer/analyzer-plugin.cc b/gcc/analyzer/analyzer-plugin.cc new file mode 100644 index 0000000..1e7c56e --- /dev/null +++ b/gcc/analyzer/analyzer-plugin.cc @@ -0,0 +1,63 @@ +/* Top-level interface to the analyzer, as a GCC plugin. + Copyright (C) 2019 Free Software Foundation, Inc. + Contributed by David Malcolm <dmalc...@redhat.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 "gcc-plugin.h" +#include "system.h" +#include "coretypes.h" +#include "analyzer/analyzer.h" +#include "analyzer/analyzer-selftests.h" + +int plugin_is_GPL_compatible; + +#if CHECKING_P + +namespace selftest { + +/* Callback for running the analyzer's selftests. */ + +static void +analyzer_selftests_cb (void */*gcc_data*/, void */*user_data*/) +{ + run_analyzer_selftests (); +} + +} /* end of namespace selftest. */ + +#endif /* #if CHECKING_P */ + +/* Entrypoint to the pass. */ + +int +plugin_init (struct plugin_name_args *plugin_info ATTRIBUTE_UNUSED, + struct plugin_gcc_version */*version*/) +{ + /* Register our selftests. */ +#if CHECKING_P + register_callback (plugin_info->base_name, + PLUGIN_RUN_SELFTESTS, + selftest::analyzer_selftests_cb, NULL); +#endif /* #if CHECKING_P */ + + /* Register our pass. */ + register_analyzer_pass (); + + return 0; +} diff --git a/gcc/analyzer/config-plugin.in b/gcc/analyzer/config-plugin.in new file mode 100644 index 0000000..283e8e9 --- /dev/null +++ b/gcc/analyzer/config-plugin.in @@ -0,0 +1,34 @@ +# Top level configure fragment for static analyzer +# Copyright (C) 2013-2015 Free Software Foundation, Inc. + +#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/>. + +# Configure looks for the existence of this file to auto-config each plugin. +# We define several parameters used by configure: +# +# plugin - name of plugin as it would appear in $(PLUGINS) +# compilers - value to add to $(COMPILERS) + +plugin="analyzer" + +compilers="" + +target_libs="" + +gtfiles="" + +build_by_default="no" diff --git a/gcc/gcc.c b/gcc/gcc.c index c45a1df..733f080 100644 --- a/gcc/gcc.c +++ b/gcc/gcc.c @@ -4290,6 +4290,19 @@ driver_handle_option (struct gcc_options *opts, handle_foffload_option (arg); break; + case OPT__analyzer: + { + validated = true; +#ifdef ENABLE_ANALYZER + save_switch ("-fplugin=analyzer_plugin", 0, NULL, validated, true); +#else + sorry ("%qs was not enabled in this build of GCC" + " (missing configure-time option %qs)", + "--analyzer", "--enable-plugins=analyzer"); +#endif + } + break; + default: /* Various driver options need no special processing at this point, having been handled in a prescan above or being -- 1.8.5.3