Mercurial > hg > CbC > CbC_gcc
diff gcc/plugin.c @ 131:84e7813d76e9
gcc-8.2
author | mir3636 |
---|---|
date | Thu, 25 Oct 2018 07:37:49 +0900 |
parents | 04ced10e8804 |
children | 1830386684a0 |
line wrap: on
line diff
--- a/gcc/plugin.c Fri Oct 27 22:46:09 2017 +0900 +++ b/gcc/plugin.c Thu Oct 25 07:37:49 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