diff gcc/plugin.c @ 132:d34655255c78

update gcc-8.2
author mir3636
date Thu, 25 Oct 2018 10:21:07 +0900
parents 84e7813d76e9
children 1830386684a0
line wrap: on
line diff
--- a/gcc/plugin.c	Thu Oct 25 08:08:40 2018 +0900
+++ b/gcc/plugin.c	Thu Oct 25 10:21:07 2018 +0900
@@ -1,5 +1,5 @@
 /* Support for GCC plugin mechanism.
-   Copyright (C) 2009-2017 Free Software Foundation, Inc.
+   Copyright (C) 2009-2018 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -34,6 +34,16 @@
 #include "plugin-version.h"
 #endif
 
+#ifdef __MINGW32__
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+#ifndef NOMINMAX
+#define NOMINMAX
+#endif
+#include <windows.h>
+#endif
+
 #define GCC_PLUGIN_STRINGIFY0(X) #X
 #define GCC_PLUGIN_STRINGIFY1(X) GCC_PLUGIN_STRINGIFY0 (X)
 
@@ -144,7 +154,7 @@
   /* First get the base name part of the full-path name, i.e. NAME.so.  */
   char *base_name = xstrdup (lbasename (full_name));
 
-  /* Then get rid of '.so' part of the name.  */
+  /* Then get rid of the extension in the name, e.g., .so.  */
   strip_off_ending (base_name, strlen (base_name));
 
   return base_name;
@@ -175,12 +185,27 @@
   if (name_is_short)
     {
       base_name = CONST_CAST (char*, plugin_name);
-      /* FIXME: the ".so" suffix is currently builtin, since plugins
-	 only work on ELF host systems like e.g. Linux or Solaris.
-	 When plugins shall be available on non ELF systems such as
-	 Windows or MacOS, this code has to be greatly improved.  */
+
+#if defined(__MINGW32__)
+      static const char plugin_ext[] = ".dll";
+#elif defined(__APPLE__)
+      /* Mac OS has two types of libraries: dynamic libraries (.dylib) and
+         plugins (.bundle). Both can be used with dlopen()/dlsym() but the
+         former cannot be linked at build time (i.e., with the -lfoo linker
+         option). A GCC plugin is therefore probably a Mac OS plugin but their
+         use seems to be quite rare and the .bundle extension is more of a
+         recommendation rather than the rule. This raises the questions of how
+         well they are supported by tools (e.g., libtool). So to avoid
+         complications let's use the .dylib extension for now. In the future,
+         if this proves to be an issue, we can always check for both
+         extensions.  */
+      static const char plugin_ext[] = ".dylib";
+#else
+      static const char plugin_ext[] = ".so";
+#endif
+
       plugin_name = concat (default_plugin_dir_name (), "/",
-			    plugin_name, ".so", NULL);
+			    plugin_name, plugin_ext, NULL);
       if (access (plugin_name, R_OK))
 	fatal_error
 	  (input_location,
@@ -573,6 +598,85 @@
 }
 
 #ifdef ENABLE_PLUGIN
+
+/* Try to initialize PLUGIN. Return true if successful. */
+
+#ifdef __MINGW32__
+
+// Return a message string for last error or NULL if unknown. Must be freed
+// with LocalFree().
+static inline char *
+win32_error_msg ()
+{
+  char *msg;
+  return FormatMessageA (FORMAT_MESSAGE_ALLOCATE_BUFFER |
+			 FORMAT_MESSAGE_FROM_SYSTEM |
+			 FORMAT_MESSAGE_IGNORE_INSERTS |
+			 FORMAT_MESSAGE_MAX_WIDTH_MASK,
+			 0,
+			 GetLastError (),
+			 MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
+			 (char*)&msg,
+			 0,
+			 0)
+    ? msg
+    : NULL;
+}
+
+static bool
+try_init_one_plugin (struct plugin_name_args *plugin)
+{
+  HMODULE dl_handle;
+  plugin_init_func plugin_init;
+
+  dl_handle = LoadLibrary (plugin->full_name);
+  if (!dl_handle)
+    {
+      char *err = win32_error_msg ();
+      error ("cannot load plugin %s\n%s", plugin->full_name, err);
+      LocalFree (err);
+      return false;
+    }
+
+  /* Check the plugin license. Unlike the name suggests, GetProcAddress()
+     can be used for both functions and variables.  */
+  if (GetProcAddress (dl_handle, str_license) == NULL)
+    {
+      char *err = win32_error_msg ();
+      fatal_error (input_location,
+		   "plugin %s is not licensed under a GPL-compatible license\n"
+		   "%s", plugin->full_name, err);
+    }
+
+  /* Unlike dlsym(), GetProcAddress() returns a pointer to a function so we
+     can cast directly without union tricks.  */
+  plugin_init = (plugin_init_func)
+    GetProcAddress (dl_handle, str_plugin_init_func_name);
+
+  if (plugin_init == NULL)
+    {
+      char *err = win32_error_msg ();
+      FreeLibrary (dl_handle);
+      error ("cannot find %s in plugin %s\n%s", str_plugin_init_func_name,
+             plugin->full_name, err);
+      LocalFree (err);
+      return false;
+    }
+
+  /* Call the plugin-provided initialization routine with the arguments.  */
+  if ((*plugin_init) (plugin, &gcc_version))
+    {
+      FreeLibrary (dl_handle);
+      error ("fail to initialize plugin %s", plugin->full_name);
+      return false;
+    }
+  /* Leak dl_handle on purpose to ensure the plugin is loaded for the
+     entire run of the compiler. */
+  return true;
+}
+
+#else // POSIX-like with dlopen()/dlsym().
+
 /* We need a union to cast dlsym return value to a function pointer
    as ISO C forbids assignment between function pointer and 'void *'.
    Use explicit union instead of __extension__(<union_cast>) for
@@ -581,8 +685,6 @@
 #define PTR_UNION_AS_VOID_PTR(NAME) (NAME._q)
 #define PTR_UNION_AS_CAST_PTR(NAME) (NAME._nq)
 
-/* Try to initialize PLUGIN. Return true if successful. */
-
 static bool
 try_init_one_plugin (struct plugin_name_args *plugin)
 {
@@ -634,7 +736,7 @@
      entire run of the compiler. */
   return true;
 }
-
+#endif
 
 /* Routine to dlopen and initialize one plugin. This function is passed to
    (and called by) the hash table traverse routine. Return 1 for the