diff --git a/packages/devel/binutils/patches/binutils-backport-from-dev.patch b/packages/devel/binutils/patches/binutils-backport-from-dev.patch new file mode 100644 index 0000000000..ddc1a4761b --- /dev/null +++ b/packages/devel/binutils/patches/binutils-backport-from-dev.patch @@ -0,0 +1,2270 @@ +From 804b7fd4fdc545a6ed18aee3d4186574861634ef Mon Sep 17 00:00:00 2001 +From: Nick Clifton +Date: Sun, 16 Feb 2020 11:33:15 +0000 +Subject: [PATCH] Import fixes for using the LTO plugin with nm. + + PR 25355 + +bfd: + 2020-02-13 H.J. Lu + + * plugin.c (try_load_plugin): Make plugin_list_iter an argument + and use it if it isn't NULL. Remove has_plugin_p argument. Add + a build_list_p argument. Don't search plugin_list. Short circuit + when building the plugin list. + (has_plugin): Renamed to has_plugin_list. + (bfd_plugin_set_plugin): Don't set has_plugin. + (bfd_plugin_specified_p): Check plugin_list instead. + (build_plugin_list): New function. + (load_plugin): Call build_plugin_list and use plugin_list. + + 2020-02-11 H.J. Lu + + PR binutils/25355 + * plugin.c (try_claim): Always clean up for LTO wrapper. + (try_load_plugin): Treat each object as independent. Create a + copy for plugin name. + + 2020-02-11 H.J. Lu + + * plugin.c (add_symbols): Clear plugin_data memory. + + 2020-02-10 H.J. Lu + + PR binutils/25355 + * configure.ac (HAVE_EXECUTABLE_SUFFIX): New AC_DEFINE. + (EXECUTABLE_SUFFIX): Likewise. + * config.in: Regenerated. + * configure: Likewise. + * plugin.c (bfd_plugin_close_and_cleanup): Removed. + (plugin_list_entry): Add all_symbols_read, cleanup_handler, + gcc, lto_wrapper, resolution_file, resolution_option, gcc_env, + real_bfd, real_nsyms, real_syms, lto_nsyms and lto_syms. + (get_lto_wrapper): New. + (setup_lto_wrapper_env): Likewise. + (current_plugin): Likewise. + (register_all_symbols_read): Likewise. + (register_cleanup): Likewise. + (get_symbols): Likewise. + (add_input_file): Likewise. + (bfd_plugin_close_and_cleanup): Likewise. + (claim_file): Removed. + (register_claim_file): Set current_plugin->claim_file. + (add_symbols): Make a copy of LTO symbols. Set lto_nsyms and + lto_syms in current_plugin. + (try_claim): Use current_plugin->claim_file. Call LTO plugin + all_symbols_read handler. Copy real symbols to plugin_data. + Call LTO plugin cleanup handler. Clean up for LTO wrapper. + (try_load_plugin): Don't reuse the previous plugin for LTO + wrapper. Set up GCC LTO wrapper if possible. Don't set + plugin_list_iter->claim_file. + (bfd_plugin_canonicalize_symtab): Use real LTO symbols if + possible. + * plugin.h (plugin_data_struct): Add real_bfd, real_nsyms and + real_syms. + +ld: + 2020-02-10 H.J. Lu + + PR binutils/25355 + * testsuite/ld-plugin/lto.exp: Run PR binutils/25355 test. + * testsuite/ld-plugin/pr25355.c: New file. + * testsuite/ld-plugin/pr25355.d: Likewise. + * testsuite/lib/ld-lib.exp (run_cc_link_tests): Support compile + only dump. +--- + bfd/ChangeLog | 60 +++ + bfd/config.in | 6 + + bfd/configure | 10 + + bfd/configure.ac | 6 + + bfd/plugin.c | 606 +++++++++++++++++++++++++++---- + bfd/plugin.h | 3 + + ld/ChangeLog | 12 + + ld/testsuite/ld-plugin/lto.exp | 5 + + ld/testsuite/ld-plugin/pr25355.c | 2 + + ld/testsuite/ld-plugin/pr25355.d | 4 + + ld/testsuite/lib/ld-lib.exp | 1 + + 11 files changed, 638 insertions(+), 77 deletions(-) + create mode 100644 ld/testsuite/ld-plugin/pr25355.c + create mode 100644 ld/testsuite/ld-plugin/pr25355.d + +diff --git a/bfd/config.in b/bfd/config.in +index be572969fc04..e1dc0f0c445b 100644 +--- a/bfd/config.in ++++ b/bfd/config.in +@@ -18,6 +18,9 @@ + language is requested. */ + #undef ENABLE_NLS + ++/* Suffix used for executables, if any. */ ++#undef EXECUTABLE_SUFFIX ++ + /* Define to 1 if you have the header file. */ + #undef HAVE_ALLOCA_H + +@@ -95,6 +98,9 @@ + /* Define to 1 if you have the header file. */ + #undef HAVE_DLFCN_H + ++/* Does the platform use an executable suffix? */ ++#undef HAVE_EXECUTABLE_SUFFIX ++ + /* Define to 1 if you have the `fcntl' function. */ + #undef HAVE_FCNTL + +diff --git a/bfd/configure b/bfd/configure +index bc576b7894ab..7c0708e2f82c 100755 +--- a/bfd/configure ++++ b/bfd/configure +@@ -12813,6 +12813,16 @@ fi + + + ++if test -n "$EXEEXT"; then ++ ++$as_echo "#define HAVE_EXECUTABLE_SUFFIX 1" >>confdefs.h ++ ++fi ++ ++cat >>confdefs.h <<_ACEOF ++#define EXECUTABLE_SUFFIX "${EXEEXT}" ++_ACEOF ++ + + host64=false + target64=false +diff --git a/bfd/configure.ac b/bfd/configure.ac +index c5bfbd5d129c..af4d4b8c1354 100644 +--- a/bfd/configure.ac ++++ b/bfd/configure.ac +@@ -157,6 +157,12 @@ AM_MAINTAINER_MODE + AM_CONDITIONAL(GENINSRC_NEVER, false) + AM_INSTALL_LIBBFD + AC_EXEEXT ++if test -n "$EXEEXT"; then ++ AC_DEFINE(HAVE_EXECUTABLE_SUFFIX, 1, ++ [Does the platform use an executable suffix?]) ++fi ++AC_DEFINE_UNQUOTED(EXECUTABLE_SUFFIX, "${EXEEXT}", ++ [Suffix used for executables, if any.]) + + host64=false + target64=false +diff --git a/bfd/plugin.c b/bfd/plugin.c +index 537ab603110b..47c3439042c7 100644 +--- a/bfd/plugin.c ++++ b/bfd/plugin.c +@@ -69,7 +69,6 @@ dlerror (void) + + #endif /* !defined (HAVE_DLFCN_H) && defined (HAVE_WINDOWS_H) */ + +-#define bfd_plugin_close_and_cleanup _bfd_generic_close_and_cleanup + #define bfd_plugin_bfd_free_cached_info _bfd_generic_bfd_free_cached_info + #define bfd_plugin_new_section_hook _bfd_generic_new_section_hook + #define bfd_plugin_get_section_contents _bfd_generic_get_section_contents +@@ -124,13 +123,312 @@ message (int level ATTRIBUTE_UNUSED, + return LDPS_OK; + } + ++struct plugin_list_entry ++{ ++ /* These must be initialized for each IR object with LTO wrapper. */ ++ void *handle; ++ ld_plugin_claim_file_handler claim_file; ++ ld_plugin_all_symbols_read_handler all_symbols_read; ++ ld_plugin_all_symbols_read_handler cleanup_handler; ++ char *resolution_file; ++ char *resolution_option; ++ bfd *real_bfd; ++ long real_nsyms; ++ asymbol **real_syms; ++ int lto_nsyms; ++ const struct ld_plugin_symbol *lto_syms; ++ ++ struct plugin_list_entry *next; ++ ++ /* These can be reused for all IR objects. */ ++ const char *plugin_name; ++ char *gcc; ++ char *lto_wrapper; ++ char *gcc_env; ++ bfd_boolean initialized; ++}; ++ ++/* Use GCC LTO wrapper to covert LTO IR object to the real object. */ ++ ++static bfd_boolean ++get_lto_wrapper (struct plugin_list_entry *plugin) ++{ ++ struct stat st; ++ const char *real_name; ++ const char *base_name; ++ size_t length; ++ const char *target_start = NULL; ++ const char *target_end = NULL; ++ size_t target_length = 0; ++ char *gcc_name; ++ char *wrapper_name; ++ char *p; ++ char dir_seperator = '\0'; ++ char *resolution_file; ++ ++ if (plugin->initialized) ++ { ++ if (plugin->lto_wrapper) ++ { ++ resolution_file = make_temp_file (".res"); ++ if (resolution_file) ++ { ++ plugin->resolution_file = resolution_file; ++ plugin->resolution_option = concat ("-fresolution=", ++ resolution_file, NULL); ++ return TRUE; ++ } ++ else ++ { ++ /* Something is wrong. Give up. */ ++ free (plugin->gcc); ++ free (plugin->lto_wrapper); ++ free (plugin->gcc_env); ++ plugin->gcc = NULL; ++ plugin->gcc_env = NULL; ++ plugin->lto_wrapper = NULL; ++ } ++ } ++ ++ return FALSE; ++ } ++ ++ plugin->initialized = TRUE; ++ ++ /* Check for PREFIX/libexec/gcc/TARGET/VERSION/liblto_plugin.so. */ ++ real_name = lrealpath (plugin->plugin_name); ++ base_name = lbasename (real_name); ++ ++ /* The directory length in plugin pathname. */ ++ length = base_name - real_name; ++ ++ /* Skip if there is no PREFIX. */ ++ if (!length) ++ return FALSE; ++ ++ p = (char *) real_name + length - 1; ++ if (IS_DIR_SEPARATOR (*p)) ++ { ++ int level = 0; ++ for (; p != real_name; p--) ++ if (IS_DIR_SEPARATOR (*p)) ++ { ++ level++; ++ if (level == 2) ++ target_end = p; ++ else if (level == 3) ++ { ++ target_start = p + 1; ++ target_length = target_end - target_start; ++ } ++ else if (level == 5) ++ { ++ dir_seperator = *p; ++ break; ++ } ++ } ++ } ++ ++ /* Skip if there is no TARGET nor PREFIX. */ ++ if (!target_length || !dir_seperator) ++ return FALSE; ++ ++#ifdef HAVE_EXECUTABLE_SUFFIX ++# define GCC_EXECUTABLE "gcc" EXECUTABLE_SUFFIX ++# define LTO_WRAPPER_EXECUTABLE "lto-wrapper" EXECUTABLE_SUFFIX ++#else ++# define GCC_EXECUTABLE "gcc" ++# define LTO_WRAPPER_EXECUTABLE "lto-wrapper" ++#endif ++ gcc_name = bfd_malloc (length + target_length ++ + sizeof (GCC_EXECUTABLE)); ++ if (gcc_name == NULL) ++ return FALSE; ++ memcpy (gcc_name, real_name, length); ++ ++ /* Get PREFIX/bin/. */ ++ p += gcc_name - real_name; ++ memcpy (p + 1, "bin", 3); ++ p[4] = dir_seperator; ++ ++ /* Try PREFIX/bin/TARGET-gcc first. */ ++ memcpy (p + 5, target_start, target_length); ++ p[5 + target_length] = '-'; ++ memcpy (p + 5 + target_length + 1, GCC_EXECUTABLE, ++ sizeof (GCC_EXECUTABLE)); ++ if (stat (gcc_name, &st) != 0 || !S_ISREG (st.st_mode)) ++ { ++ /* Then try PREFIX/bin/gcc. */ ++ memcpy (p + 5, GCC_EXECUTABLE, sizeof (GCC_EXECUTABLE)); ++ if (stat (gcc_name, &st) != 0 || !S_ISREG (st.st_mode)) ++ { ++ free (gcc_name); ++ return FALSE; ++ } ++ } ++ ++ /* lto-wrapper should be in the same directory with LTO plugin. */ ++ wrapper_name = bfd_malloc (length + sizeof (LTO_WRAPPER_EXECUTABLE)); ++ if (wrapper_name == NULL) ++ { ++ free (gcc_name); ++ return FALSE; ++ } ++ memcpy (wrapper_name, real_name, length); ++ memcpy (wrapper_name + length, LTO_WRAPPER_EXECUTABLE, ++ sizeof (LTO_WRAPPER_EXECUTABLE)); ++ if (stat (wrapper_name, &st) == 0 && S_ISREG (st.st_mode)) ++ { ++ resolution_file = make_temp_file (".res"); ++ if (resolution_file) ++ { ++ plugin->gcc = gcc_name; ++ plugin->lto_wrapper = wrapper_name; ++ plugin->gcc_env = concat ("COLLECT_GCC=", gcc_name, NULL); ++ plugin->resolution_file = resolution_file; ++ plugin->resolution_option = concat ("-fresolution=", ++ resolution_file, NULL); ++ return TRUE; ++ } ++ } ++ ++ free (gcc_name); ++ free (wrapper_name); ++ return FALSE; ++} ++ ++/* Set environment variables for GCC LTO wrapper to covert LTO IR ++ object to the real object. */ ++ ++static int ++setup_lto_wrapper_env (struct plugin_list_entry *plugin) ++{ ++ return (putenv (plugin->gcc_env) ++ || putenv ("COLLECT_GCC_OPTIONS=")); ++} ++ ++static struct plugin_list_entry *plugin_list = NULL; ++static struct plugin_list_entry *current_plugin = NULL; ++ + /* Register a claim-file handler. */ +-static ld_plugin_claim_file_handler claim_file = NULL; + + static enum ld_plugin_status + register_claim_file (ld_plugin_claim_file_handler handler) + { +- claim_file = handler; ++ current_plugin->claim_file = handler; ++ return LDPS_OK; ++} ++ ++/* Register an all-symbols-read handler. */ ++ ++static enum ld_plugin_status ++register_all_symbols_read (ld_plugin_all_symbols_read_handler handler) ++{ ++ current_plugin->all_symbols_read = handler; ++ return LDPS_OK; ++} ++ ++/* Register a cleanup handler. */ ++ ++static enum ld_plugin_status ++register_cleanup (ld_plugin_all_symbols_read_handler handler) ++{ ++ current_plugin->cleanup_handler = handler; ++ return LDPS_OK; ++} ++ ++/* Get the symbol resolution info for a plugin-claimed input file. */ ++ ++static enum ld_plugin_status ++get_symbols (const void *handle ATTRIBUTE_UNUSED, int nsyms, ++ struct ld_plugin_symbol *syms) ++{ ++ if (syms) ++ { ++ int n; ++ for (n = 0; n < nsyms; n++) ++ { ++ switch (syms[n].def) ++ { ++ default: ++ BFD_ASSERT (0); ++ break; ++ case LDPK_UNDEF: ++ case LDPK_WEAKUNDEF: ++ syms[n].resolution = LDPR_UNDEF; ++ break; ++ case LDPK_DEF: ++ case LDPK_WEAKDEF: ++ case LDPK_COMMON: ++ /* Tell plugin that LTO symbol has references from regular ++ object code. */ ++ syms[n].resolution = LDPR_PREVAILING_DEF; ++ break; ++ } ++ } ++ } ++ ++ return LDPS_OK; ++} ++ ++/* Add a new (real) input file generated by a plugin. */ ++ ++static enum ld_plugin_status ++add_input_file (const char *pathname) ++{ ++ /* Get symbols from the real LTO object. */ ++ char **matching; ++ long real_symsize; ++ long real_nsyms; ++ asymbol **real_syms; ++ int lto_nsyms; ++ bfd_boolean lto_symbol_found = FALSE; ++ const struct ld_plugin_symbol *lto_syms; ++ bfd *rbfd; ++ int i, j; ++ ++ rbfd = bfd_openr (pathname, NULL); ++ if (!bfd_check_format_matches (rbfd, bfd_object, &matching)) ++ BFD_ASSERT (0); ++ ++ real_symsize = bfd_get_symtab_upper_bound (rbfd); ++ if (real_symsize < 0) ++ BFD_ASSERT (0); ++ ++ real_syms = (asymbol **) bfd_malloc (real_symsize); ++ if (real_syms) ++ { ++ real_nsyms = bfd_canonicalize_symtab (rbfd, real_syms); ++ if (real_nsyms < 0) ++ BFD_ASSERT (0); ++ ++ /* NB: LTO plugin may generate more than one real object from one ++ LTO IR object. We use the one which contains LTO symbols. */ ++ lto_syms = current_plugin->lto_syms; ++ lto_nsyms = current_plugin->lto_nsyms; ++ for (i = 0; i < lto_nsyms; i++) ++ for (j = 0; j < real_nsyms; j++) ++ if (real_syms[j]->name ++ && strcmp (lto_syms[i].name, real_syms[j]->name) == 0) ++ { ++ lto_symbol_found = TRUE; ++ break; ++ } ++ } ++ ++ if (lto_symbol_found) ++ { ++ current_plugin->real_nsyms = real_nsyms; ++ current_plugin->real_syms = real_syms; ++ /* NB: We can't close RBFD which own the real symbol info. */ ++ current_plugin->real_bfd = rbfd; ++ } ++ else ++ { ++ bfd_close (rbfd); ++ free (real_syms); ++ } ++ + return LDPS_OK; + } + +@@ -143,13 +441,52 @@ add_symbols (void * handle, + struct plugin_data_struct *plugin_data = + bfd_alloc (abfd, sizeof (plugin_data_struct)); + +- plugin_data->nsyms = nsyms; +- plugin_data->syms = syms; ++ if (plugin_data) ++ { ++ struct ld_plugin_symbol *sym_info; ++ char *strtab; ++ size_t sym_info_size, name_length; ++ int i; ++ ++ memset (plugin_data, 0, sizeof (*plugin_data)); ++ ++ abfd->tdata.plugin_data = plugin_data; ++ ++ /* NB: LTO symbols are owned by LTO plugin. Create a copy so ++ that we can use it in bfd_plugin_canonicalize_symtab. */ ++ sym_info_size = nsyms * sizeof (*syms); ++ ++ /* Allocate a string table */ ++ for (i = 0; i < nsyms; i++) ++ sym_info_size += strlen (syms[i].name) + 1; ++ ++ sym_info = bfd_alloc (abfd, sym_info_size); ++ if (sym_info) ++ { ++ /* Copy symbol table. */ ++ memcpy (sym_info, syms, nsyms * sizeof (*syms)); ++ ++ /* Copy symbol names in symbol table. */ ++ strtab = (char *) (sym_info + nsyms); ++ for (i = 0; i < nsyms; i++) ++ { ++ name_length = strlen (syms[i].name); ++ memcpy (strtab, syms[i].name, name_length + 1); ++ sym_info[i].name = strtab; ++ strtab += name_length + 1; ++ } ++ ++ plugin_data->nsyms = nsyms; ++ plugin_data->syms = sym_info; ++ ++ current_plugin->lto_nsyms = nsyms; ++ current_plugin->lto_syms = sym_info; ++ } ++ } + + if (nsyms != 0) + abfd->flags |= HAS_SYMS; + +- abfd->tdata.plugin_data = plugin_data; + return LDPS_OK; + } + +@@ -212,34 +549,72 @@ try_claim (bfd *abfd) + struct ld_plugin_input_file file; + + file.handle = abfd; +- if (!bfd_plugin_open_input (abfd, &file)) +- return 0; +- if (claim_file) +- claim_file (&file, &claimed); +- close (file.fd); ++ if (bfd_plugin_open_input (abfd, &file) ++ && current_plugin->claim_file) ++ { ++ current_plugin->claim_file (&file, &claimed); ++ if (claimed) ++ { ++ if (current_plugin->all_symbols_read) ++ { ++ struct plugin_data_struct *plugin_data ++ = abfd->tdata.plugin_data; ++ if (plugin_data) ++ { ++ /* Get real symbols from LTO wrapper. */ ++ current_plugin->all_symbols_read (); ++ ++ /* Copy real symbols to plugin_data. */ ++ plugin_data->real_bfd = current_plugin->real_bfd; ++ plugin_data->real_nsyms = current_plugin->real_nsyms; ++ plugin_data->real_syms = current_plugin->real_syms; ++ ++ /* Clean up LTO plugin. */ ++ if (current_plugin->cleanup_handler) ++ current_plugin->cleanup_handler (); ++ } ++ } ++ } ++ ++ close (file.fd); ++ } ++ ++ if (current_plugin->lto_wrapper) ++ { ++ /* Clean up for LTO wrapper. NB: Resolution file and option ++ have been created regardless if an IR object is claimed or ++ not. */ ++ unlink (current_plugin->resolution_file); ++ free (current_plugin->resolution_option); ++ } ++ + return claimed; + } + +-struct plugin_list_entry +-{ +- void * handle; +- ld_plugin_claim_file_handler claim_file; +- struct plugin_list_entry * next; +-}; +- +-static struct plugin_list_entry * plugin_list = NULL; +- + static int +-try_load_plugin (const char *pname, bfd *abfd, int *has_plugin_p) ++try_load_plugin (const char *pname, ++ struct plugin_list_entry *plugin_list_iter, ++ bfd *abfd, bfd_boolean build_list_p) + { + void *plugin_handle = NULL; +- struct ld_plugin_tv tv[4]; ++ struct ld_plugin_tv tv[12]; + int i; + ld_plugin_onload onload; + enum ld_plugin_status status; +- struct plugin_list_entry *plugin_list_iter; + +- *has_plugin_p = 0; ++ /* NB: Each object is independent. Reuse the previous plugin from ++ the last run will lead to wrong result. */ ++ if (current_plugin) ++ { ++ if (current_plugin->handle) ++ dlclose (current_plugin->handle); ++ memset (current_plugin, 0, ++ offsetof (struct plugin_list_entry, next)); ++ current_plugin = NULL; ++ } ++ ++ if (plugin_list_iter) ++ pname = plugin_list_iter->plugin_name; + + plugin_handle = dlopen (pname, RTLD_NOW); + if (!plugin_handle) +@@ -248,28 +623,30 @@ try_load_plugin (const char *pname, bfd *abfd, int *has_plugin_p) + return 0; + } + +- for (plugin_list_iter = plugin_list; +- plugin_list_iter; +- plugin_list_iter = plugin_list_iter->next) +- { +- if (plugin_handle == plugin_list_iter->handle) +- { +- dlclose (plugin_handle); +- if (!plugin_list_iter->claim_file) +- return 0; +- +- register_claim_file (plugin_list_iter->claim_file); +- goto have_claim_file; +- } +- } +- +- plugin_list_iter = bfd_malloc (sizeof *plugin_list_iter); + if (plugin_list_iter == NULL) +- return 0; ++ { ++ size_t length_plugin_name = strlen (pname) + 1; ++ char *plugin_name = bfd_malloc (length_plugin_name); ++ if (plugin_name == NULL) ++ return 0; ++ plugin_list_iter = bfd_malloc (sizeof *plugin_list_iter); ++ if (plugin_list_iter == NULL) ++ { ++ free (plugin_name); ++ return 0; ++ } ++ /* Make a copy of PNAME since PNAME from load_plugin () will be ++ freed. */ ++ memcpy (plugin_name, pname, length_plugin_name); ++ memset (plugin_list_iter, 0, sizeof (*plugin_list_iter)); ++ plugin_list_iter->plugin_name = plugin_name; ++ plugin_list_iter->next = plugin_list; ++ plugin_list = plugin_list_iter; ++ } ++ + plugin_list_iter->handle = plugin_handle; +- plugin_list_iter->claim_file = NULL; +- plugin_list_iter->next = plugin_list; +- plugin_list = plugin_list_iter; ++ if (build_list_p) ++ return 0; + + onload = dlsym (plugin_handle, "onload"); + if (!onload) +@@ -287,23 +664,60 @@ try_load_plugin (const char *pname, bfd *abfd, int *has_plugin_p) + tv[i].tv_tag = LDPT_ADD_SYMBOLS; + tv[i].tv_u.tv_add_symbols = add_symbols; + ++ if (get_lto_wrapper (plugin_list_iter)) ++ { ++ ++i; ++ tv[i].tv_tag = LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK; ++ tv[i].tv_u.tv_register_all_symbols_read = register_all_symbols_read; ++ ++ ++i; ++ tv[i].tv_tag = LDPT_REGISTER_CLEANUP_HOOK; ++ tv[i].tv_u.tv_register_cleanup = register_cleanup; ++ ++ ++i; ++ tv[i].tv_tag = LDPT_GET_SYMBOLS; ++ tv[i].tv_u.tv_get_symbols = get_symbols; ++ ++ ++i; ++ tv[i].tv_tag = LDPT_GET_SYMBOLS_V2; ++ tv[i].tv_u.tv_get_symbols = get_symbols; ++ ++ ++i; ++ tv[i].tv_tag = LDPT_OPTION; ++ tv[i].tv_u.tv_string = plugin_list_iter->lto_wrapper; ++ ++ ++i; ++ tv[i].tv_tag = LDPT_OPTION; ++ tv[i].tv_u.tv_string = plugin_list_iter->resolution_option; ++ ++ ++i; ++ tv[i].tv_tag = LDPT_LINKER_OUTPUT; ++ tv[i].tv_u.tv_val = LDPO_EXEC; ++ ++ ++i; ++ tv[i].tv_tag = LDPT_ADD_INPUT_FILE; ++ tv[i].tv_u.tv_add_input_file = add_input_file; ++ } ++ + ++i; + tv[i].tv_tag = LDPT_NULL; + tv[i].tv_u.tv_val = 0; + ++ current_plugin = plugin_list_iter; ++ ++ /* LTO plugin will call handler hooks to set up plugin handlers. */ + status = (*onload)(tv); + + if (status != LDPS_OK) + return 0; + +- plugin_list_iter->claim_file = claim_file; +- +-have_claim_file: +- *has_plugin_p = 1; ++ if (current_plugin->lto_wrapper ++ && setup_lto_wrapper_env (current_plugin)) ++ return 0; + + abfd->plugin_format = bfd_plugin_no; + +- if (!claim_file) ++ if (!current_plugin->claim_file) + return 0; + + if (!try_claim (abfd)) +@@ -314,8 +728,7 @@ have_claim_file: + } + + /* There may be plugin libraries in lib/bfd-plugins. */ +- +-static int has_plugin = -1; ++static int has_plugin_list = -1; + + static const bfd_target *(*ld_plugin_object_p) (bfd *); + +@@ -325,7 +738,6 @@ void + bfd_plugin_set_plugin (const char *p) + { + plugin_name = p; +- has_plugin = p != NULL; + } + + /* Return TRUE if a plugin library is used. */ +@@ -333,7 +745,7 @@ bfd_plugin_set_plugin (const char *p) + bfd_boolean + bfd_plugin_specified_p (void) + { +- return has_plugin > 0; ++ return plugin_list != NULL; + } + + /* Return TRUE if ABFD can be claimed by linker LTO plugin. */ +@@ -364,8 +776,8 @@ register_ld_plugin_object_p (const bfd_target *(*object_p) (bfd *)) + ld_plugin_object_p = object_p; + } + +-static int +-load_plugin (bfd *abfd) ++static void ++build_plugin_list (bfd *abfd) + { + /* The intent was to search ${libdir}/bfd-plugins for plugins, but + unfortunately the original implementation wasn't precisely that +@@ -374,17 +786,10 @@ load_plugin (bfd *abfd) + static const char *path[] + = { LIBDIR "/bfd-plugins", BINDIR "/../lib/bfd-plugins" }; + struct stat last_st; +- int found = 0; + unsigned int i; + +- if (!has_plugin) +- return found; +- +- if (plugin_name) +- return try_load_plugin (plugin_name, abfd, &has_plugin); +- +- if (plugin_program_name == NULL) +- return found; ++ if (has_plugin_list >= 0) ++ return; + + /* Try not to search the same dir twice, by looking at st_dev and + st_ino for the dir. If we are on a file system that always sets +@@ -419,26 +824,38 @@ load_plugin (bfd *abfd) + + full_name = concat (plugin_dir, "/", ent->d_name, NULL); + if (stat (full_name, &st) == 0 && S_ISREG (st.st_mode)) +- { +- int valid_plugin; +- +- found = try_load_plugin (full_name, abfd, &valid_plugin); +- if (has_plugin <= 0) +- has_plugin = valid_plugin; +- } ++ try_load_plugin (full_name, NULL, abfd, TRUE); + free (full_name); +- if (found) +- break; + } + closedir (d); + } + free (plugin_dir); + } +- if (found) +- break; + } + +- return found; ++ has_plugin_list = plugin_list != NULL; ++} ++ ++static int ++load_plugin (bfd *abfd) ++{ ++ struct plugin_list_entry *plugin_list_iter; ++ ++ if (plugin_name) ++ return try_load_plugin (plugin_name, plugin_list, abfd, FALSE); ++ ++ if (plugin_program_name == NULL) ++ return 0; ++ ++ build_plugin_list (abfd); ++ ++ for (plugin_list_iter = plugin_list; ++ plugin_list_iter; ++ plugin_list_iter = plugin_list_iter->next) ++ if (try_load_plugin (NULL, plugin_list_iter, abfd, FALSE)) ++ return 1; ++ ++ return 0; + } + + +@@ -562,7 +979,15 @@ bfd_plugin_canonicalize_symtab (bfd *abfd, + SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS); + static asection fake_common_section + = BFD_FAKE_SECTION (fake_common_section, NULL, "plug", 0, SEC_IS_COMMON); +- int i; ++ int i, j; ++ long real_nsyms; ++ asymbol **real_syms; ++ ++ real_syms = plugin_data->real_syms; ++ if (real_syms) ++ real_nsyms = plugin_data->real_nsyms; ++ else ++ real_nsyms = 0; + + for (i = 0; i < nsyms; i++) + { +@@ -587,6 +1012,15 @@ bfd_plugin_canonicalize_symtab (bfd *abfd, + case LDPK_DEF: + case LDPK_WEAKDEF: + s->section = &fake_section; ++ if (real_nsyms) ++ /* Use real LTO symbols if possible. */ ++ for (j = 0; j < real_nsyms; j++) ++ if (real_syms[j]->name ++ && strcmp (syms[i].name, real_syms[j]->name) == 0) ++ { ++ s->section = real_syms[j]->section; ++ break; ++ } + break; + default: + BFD_ASSERT (0); +@@ -635,6 +1069,24 @@ bfd_plugin_sizeof_headers (bfd *a ATTRIBUTE_UNUSED, + return 0; + } + ++static bfd_boolean ++bfd_plugin_close_and_cleanup (bfd *abfd) ++{ ++ struct plugin_data_struct *plugin_data; ++ ++ if (abfd->format != bfd_archive ++ && (plugin_data = abfd->tdata.plugin_data)) ++ { ++ if (plugin_data->real_bfd) ++ bfd_close (plugin_data->real_bfd); ++ ++ if (plugin_data->real_syms) ++ free (plugin_data->real_syms); ++ } ++ ++ return _bfd_generic_close_and_cleanup (abfd); ++} ++ + const bfd_target plugin_vec = + { + "plugin", /* Name. */ +diff --git a/bfd/plugin.h b/bfd/plugin.h +index 098bf0845548..05c3573933dc 100644 +--- a/bfd/plugin.h ++++ b/bfd/plugin.h +@@ -33,6 +33,9 @@ typedef struct plugin_data_struct + { + int nsyms; + const struct ld_plugin_symbol *syms; ++ bfd *real_bfd; ++ long real_nsyms; ++ asymbol **real_syms; + } + plugin_data_struct; + +diff --git a/ld/ChangeLog b/ld/ChangeLog +index a7963cc0a910..999e0f4e3355 100644 +--- a/ld/ChangeLog ++++ b/ld/ChangeLog +@@ -1,3 +1,15 @@ ++2020-02-14 Nick Clifton ++ ++ Import from the mainline: ++ 2020-02-10 H.J. Lu ++ ++ PR binutils/25355 ++ * testsuite/ld-plugin/lto.exp: Run PR binutils/25355 test. ++ * testsuite/ld-plugin/pr25355.c: New file. ++ * testsuite/ld-plugin/pr25355.d: Likewise. ++ * testsuite/lib/ld-lib.exp (run_cc_link_tests): Support compile ++ only dump. ++ + 2020-02-01 Nick Clifton + + * configure: Regenerate. +diff --git a/ld/testsuite/ld-plugin/lto.exp b/ld/testsuite/ld-plugin/lto.exp +index 9b03b7b39773..1b44b0da3fda 100644 +--- a/ld/testsuite/ld-plugin/lto.exp ++++ b/ld/testsuite/ld-plugin/lto.exp +@@ -234,6 +234,11 @@ set lto_link_tests [list \ + [list "Build pr24406-2b.o" \ + "" "-O2 -fno-lto" \ + {pr24406-2b.c}] \ ++ [list "pr25355.o" \ ++ "" \ ++ "-flto -fno-common $lto_no_fat" \ ++ {pr25355.c} \ ++ [list [list "nm" "$plug_opt" "pr25355.d"]]] \ + ] + + if { [at_least_gcc_version 4 7] } { +diff --git a/ld/testsuite/ld-plugin/pr25355.c b/ld/testsuite/ld-plugin/pr25355.c +new file mode 100644 +index 000000000000..99f01fb5c896 +--- /dev/null ++++ b/ld/testsuite/ld-plugin/pr25355.c +@@ -0,0 +1,2 @@ ++int nm_test_var; ++int nm_test_var2 = 1234; +diff --git a/ld/testsuite/ld-plugin/pr25355.d b/ld/testsuite/ld-plugin/pr25355.d +new file mode 100644 +index 000000000000..98d10aba1cf7 +--- /dev/null ++++ b/ld/testsuite/ld-plugin/pr25355.d +@@ -0,0 +1,4 @@ ++#... ++[0-9a-f]+ B _?nm_test_var ++[0-9a-f]+ D _?nm_test_var2 ++#pass +diff --git a/ld/testsuite/lib/ld-lib.exp b/ld/testsuite/lib/ld-lib.exp +index 6752a76483a9..e276bb589d88 100644 +--- a/ld/testsuite/lib/ld-lib.exp ++++ b/ld/testsuite/lib/ld-lib.exp +@@ -928,6 +928,7 @@ proc run_cc_link_tests { ldtests } { + + if { $binfile eq "tmpdir/" } { + # compile only ++ set binfile $objfile + } elseif { [regexp ".*\\.a$" $binfile] } { + if { ![ar_simple_create $ar $ldflags $binfile "$objfiles"] } { + set failed 1 +-- +2.27.0 + +From e2b46ba142d9901897d8189422f0bcc28e5660b8 Mon Sep 17 00:00:00 2001 +From: "H.J. Lu" +Date: Wed, 19 Feb 2020 03:29:51 -0800 +Subject: [PATCH] plugin: Call dlclose before return in try_load_plugin + +Since plugin can be used only once in try_load_plugin, call dlclose +before return. + + PR binutils/25355 + * plugin.c (plugin_list_entry): Remove handle. + (try_load_plugin): Call dlclose before return. + +(cherry picked from commit dcf06b89b9129da6988878a77afdd02d3acc2e30) +--- + bfd/ChangeLog | 6 ++++++ + bfd/plugin.c | 39 ++++++++++++++++++--------------------- + 2 files changed, 24 insertions(+), 21 deletions(-) + +diff --git a/bfd/plugin.c b/bfd/plugin.c +index 47c3439042c7..93d562b9fed3 100644 +--- a/bfd/plugin.c ++++ b/bfd/plugin.c +@@ -126,7 +126,6 @@ message (int level ATTRIBUTE_UNUSED, + struct plugin_list_entry + { + /* These must be initialized for each IR object with LTO wrapper. */ +- void *handle; + ld_plugin_claim_file_handler claim_file; + ld_plugin_all_symbols_read_handler all_symbols_read; + ld_plugin_all_symbols_read_handler cleanup_handler; +@@ -596,22 +595,18 @@ try_load_plugin (const char *pname, + struct plugin_list_entry *plugin_list_iter, + bfd *abfd, bfd_boolean build_list_p) + { +- void *plugin_handle = NULL; ++ void *plugin_handle; + struct ld_plugin_tv tv[12]; + int i; + ld_plugin_onload onload; + enum ld_plugin_status status; ++ int result = 0; + + /* NB: Each object is independent. Reuse the previous plugin from + the last run will lead to wrong result. */ + if (current_plugin) +- { +- if (current_plugin->handle) +- dlclose (current_plugin->handle); +- memset (current_plugin, 0, +- offsetof (struct plugin_list_entry, next)); +- current_plugin = NULL; +- } ++ memset (current_plugin, 0, ++ offsetof (struct plugin_list_entry, next)); + + if (plugin_list_iter) + pname = plugin_list_iter->plugin_name; +@@ -628,12 +623,12 @@ try_load_plugin (const char *pname, + size_t length_plugin_name = strlen (pname) + 1; + char *plugin_name = bfd_malloc (length_plugin_name); + if (plugin_name == NULL) +- return 0; ++ goto short_circuit; + plugin_list_iter = bfd_malloc (sizeof *plugin_list_iter); + if (plugin_list_iter == NULL) + { + free (plugin_name); +- return 0; ++ goto short_circuit; + } + /* Make a copy of PNAME since PNAME from load_plugin () will be + freed. */ +@@ -644,13 +639,13 @@ try_load_plugin (const char *pname, + plugin_list = plugin_list_iter; + } + +- plugin_list_iter->handle = plugin_handle; ++ current_plugin = plugin_list_iter; + if (build_list_p) +- return 0; ++ goto short_circuit; + + onload = dlsym (plugin_handle, "onload"); + if (!onload) +- return 0; ++ goto short_circuit; + + i = 0; + tv[i].tv_tag = LDPT_MESSAGE; +@@ -703,28 +698,30 @@ try_load_plugin (const char *pname, + tv[i].tv_tag = LDPT_NULL; + tv[i].tv_u.tv_val = 0; + +- current_plugin = plugin_list_iter; +- + /* LTO plugin will call handler hooks to set up plugin handlers. */ + status = (*onload)(tv); + + if (status != LDPS_OK) +- return 0; ++ goto short_circuit; + + if (current_plugin->lto_wrapper + && setup_lto_wrapper_env (current_plugin)) +- return 0; ++ goto short_circuit; + + abfd->plugin_format = bfd_plugin_no; + + if (!current_plugin->claim_file) +- return 0; ++ goto short_circuit; + + if (!try_claim (abfd)) +- return 0; ++ goto short_circuit; + + abfd->plugin_format = bfd_plugin_yes; +- return 1; ++ result = 1; ++ ++short_circuit: ++ dlclose (plugin_handle); ++ return result; + } + + /* There may be plugin libraries in lib/bfd-plugins. */ +-- +2.27.0 + +From 42b2380cdced1f828ede6fa1c7c7d1fdf0e331ca Mon Sep 17 00:00:00 2001 +From: "H.J. Lu" +Date: Tue, 25 Feb 2020 03:30:33 -0800 +Subject: [PATCH] Don't call lto-wrapper for ar and ranlib + +Since ar and ranlib don't need to know symbol types to work properly, +we should avoid calling lto-wrapper for them to speed them up. + +bfd/ + + PR binutils/25584 + * plugin.c (need_lto_wrapper_p): New. + (bfd_plugin_set_program_name): Add an int argument to set + need_lto_wrapper_p. + (get_lto_wrapper): Return FALSE if need_lto_wrapper_p isn't + set. + * plugin.h (bfd_plugin_set_program_name): Add an int argument. + +binutils/ + + PR binutils/25584 + * ar.c (main): Pass 0 to bfd_plugin_set_program_name. + * nm.c (main): Pass 1 to bfd_plugin_set_program_name. + +(cherry picked from commit ecda90163e2b0a6f0be96e3fc262c28820a27211) +--- + bfd/ChangeLog | 10 ++++++++++ + bfd/plugin.c | 22 ++++++++++++++-------- + bfd/plugin.h | 2 +- + binutils/ChangeLog | 6 ++++++ + binutils/ar.c | 2 +- + binutils/nm.c | 2 +- + 6 files changed, 33 insertions(+), 11 deletions(-) + +diff --git a/bfd/plugin.c b/bfd/plugin.c +index 93d562b9fed3..c79468fab87c 100644 +--- a/bfd/plugin.c ++++ b/bfd/plugin.c +@@ -147,6 +147,17 @@ struct plugin_list_entry + bfd_boolean initialized; + }; + ++static const char *plugin_program_name; ++static int need_lto_wrapper_p; ++ ++void ++bfd_plugin_set_program_name (const char *program_name, ++ int need_lto_wrapper) ++{ ++ plugin_program_name = program_name; ++ need_lto_wrapper_p = need_lto_wrapper; ++} ++ + /* Use GCC LTO wrapper to covert LTO IR object to the real object. */ + + static bfd_boolean +@@ -165,6 +176,9 @@ get_lto_wrapper (struct plugin_list_entry *plugin) + char dir_seperator = '\0'; + char *resolution_file; + ++ if (!need_lto_wrapper_p) ++ return FALSE; ++ + if (plugin->initialized) + { + if (plugin->lto_wrapper) +@@ -489,14 +503,6 @@ add_symbols (void * handle, + return LDPS_OK; + } + +-static const char *plugin_program_name; +- +-void +-bfd_plugin_set_program_name (const char *program_name) +-{ +- plugin_program_name = program_name; +-} +- + int + bfd_plugin_open_input (bfd *ibfd, struct ld_plugin_input_file *file) + { +diff --git a/bfd/plugin.h b/bfd/plugin.h +index 05c3573933dc..b2d5e50137f2 100644 +--- a/bfd/plugin.h ++++ b/bfd/plugin.h +@@ -21,7 +21,7 @@ + #ifndef _PLUGIN_H_ + #define _PLUGIN_H_ + +-void bfd_plugin_set_program_name (const char *); ++void bfd_plugin_set_program_name (const char *, int); + int bfd_plugin_open_input (bfd *, struct ld_plugin_input_file *); + void bfd_plugin_set_plugin (const char *); + bfd_boolean bfd_plugin_target_p (const bfd_target *); +diff --git a/binutils/ar.c b/binutils/ar.c +index 1057db9980ed..35dd51e04af4 100644 +--- a/binutils/ar.c ++++ b/binutils/ar.c +@@ -725,7 +725,7 @@ main (int argc, char **argv) + xmalloc_set_program_name (program_name); + bfd_set_error_program_name (program_name); + #if BFD_SUPPORTS_PLUGINS +- bfd_plugin_set_program_name (program_name); ++ bfd_plugin_set_program_name (program_name, 0); + #endif + + expandargv (&argc, &argv); +diff --git a/binutils/nm.c b/binutils/nm.c +index 0ee3f8838654..5b386592a615 100644 +--- a/binutils/nm.c ++++ b/binutils/nm.c +@@ -1701,7 +1701,7 @@ main (int argc, char **argv) + xmalloc_set_program_name (program_name); + bfd_set_error_program_name (program_name); + #if BFD_SUPPORTS_PLUGINS +- bfd_plugin_set_program_name (program_name); ++ bfd_plugin_set_program_name (program_name, 1); + #endif + + START_PROGRESS (program_name, 0); +-- +2.27.0 + +From e7c0ee5110c175cc8762a8d379bdf2e3405d45d3 Mon Sep 17 00:00:00 2001 +From: Martin Liska +Date: Wed, 25 Mar 2020 06:47:35 -0700 +Subject: [PATCH] Include: Sync lto-symtab.h and plugin-api.h with GCC + +2020-03-19 Martin Liska + + * lto-symtab.h (enum gcc_plugin_symbol_type): New. + (enum gcc_plugin_symbol_section_kind): Likewise. + +2020-03-19 Martin Liska + + * plugin-api.h (struct ld_plugin_symbol): Split + int def into 4 char fields. + (enum ld_plugin_symbol_type): New. + (enum ld_plugin_symbol_section_kind): New. + (enum ld_plugin_tag): Add LDPT_ADD_SYMBOLS_V2. + +(cherry picked from commit 3734bec8336f6f33927ab99460cb681035c2ca4f) +--- + include/ChangeLog | 13 +++++++++++++ + include/lto-symtab.h | 13 +++++++++++++ + include/plugin-api.h | 32 ++++++++++++++++++++++++++++++-- + 3 files changed, 56 insertions(+), 2 deletions(-) + +diff --git a/include/lto-symtab.h b/include/lto-symtab.h +index 0ce0de10121d..ef2e35f19c3e 100644 +--- a/include/lto-symtab.h ++++ b/include/lto-symtab.h +@@ -38,4 +38,17 @@ enum gcc_plugin_symbol_visibility + GCCPV_HIDDEN + }; + ++enum gcc_plugin_symbol_type ++{ ++ GCCST_UNKNOWN, ++ GCCST_FUNCTION, ++ GCCST_VARIABLE, ++}; ++ ++enum gcc_plugin_symbol_section_kind ++{ ++ GCCSSK_DEFAULT, ++ GCCSSK_BSS ++}; ++ + #endif /* GCC_LTO_SYMTAB_H */ +diff --git a/include/plugin-api.h b/include/plugin-api.h +index 09e1202df07a..f0f9667bf3b9 100644 +--- a/include/plugin-api.h ++++ b/include/plugin-api.h +@@ -87,7 +87,19 @@ struct ld_plugin_symbol + { + char *name; + char *version; +- int def; ++ /* This is for compatibility with older ABIs. The older ABI defined ++ only 'def' field. */ ++#ifdef __BIG_ENDIAN__ ++ char unused; ++ char section_kind; ++ char symbol_type; ++ char def; ++#else ++ char def; ++ char symbol_type; ++ char section_kind; ++ char unused; ++#endif + int visibility; + uint64_t size; + char *comdat_key; +@@ -123,6 +135,21 @@ enum ld_plugin_symbol_visibility + LDPV_HIDDEN + }; + ++/* The type of the symbol. */ ++ ++enum ld_plugin_symbol_type ++{ ++ LDST_UNKNOWN, ++ LDST_FUNCTION, ++ LDST_VARIABLE, ++}; ++ ++enum ld_plugin_symbol_section_kind ++{ ++ LDSSK_DEFAULT, ++ LDSSK_BSS ++}; ++ + /* How a symbol is resolved. */ + + enum ld_plugin_symbol_resolution +@@ -431,7 +458,8 @@ enum ld_plugin_tag + LDPT_GET_INPUT_SECTION_ALIGNMENT = 29, + LDPT_GET_INPUT_SECTION_SIZE = 30, + LDPT_REGISTER_NEW_INPUT_HOOK = 31, +- LDPT_GET_WRAP_SYMBOLS = 32 ++ LDPT_GET_WRAP_SYMBOLS = 32, ++ LDPT_ADD_SYMBOLS_V2 = 33 + }; + + /* The plugin transfer vector. */ +-- +2.27.0 + +From 64f5c0afcc4683f0003b60d6a5a299beb08f38de Mon Sep 17 00:00:00 2001 +From: "H.J. Lu" +Date: Wed, 25 Mar 2020 06:54:20 -0700 +Subject: [PATCH] plugin: Use LDPT_ADD_SYMBOLS_V2 to get symbol type + +Since LTO plugin may generate more than one ltrans.o file from one input +IR object as LTO wrapper ignores -flto-partition=none: + +lto-wrapper.c:608: + + 604 /* Drop arguments that we want to take from the link line. */ + 605 case OPT_flto_: + 606 case OPT_flto: + 607 case OPT_flto_partition_: + 608 continue; + +the LTO wrapper approach is not only slow but also unreliable. Since +the LTO plugin API has been extended to add LDPT_ADD_SYMBOLS_V2 with +symbol type and section kind, we can use LDPT_ADD_SYMBOLS_V2 to get +symbol type, instead of invoking the LTO wrapper. + + PR binutils/25640 + * plugin.c (plugin_list_entry): Add has_symbol_type. + (add_symbols_v2): New function. + (bfd_plugin_open_input): Don't invoke LTO wrapper if LTO plugin + provides symbol type. + (try_load_plugin): Add LDPT_ADD_SYMBOLS_V2. + (bfd_plugin_canonicalize_symtab): Use LTO plugin symbol type if + available. + +(cherry picked from commit c3a1714ce7806002726a60c0db09371425fe3097) +--- + bfd/ChangeLog | 11 +++++++++ + bfd/plugin.c | 66 ++++++++++++++++++++++++++++++++++++++++----------- + 2 files changed, 63 insertions(+), 14 deletions(-) + +diff --git a/bfd/plugin.c b/bfd/plugin.c +index c79468fab87c..0f045372b7e0 100644 +--- a/bfd/plugin.c ++++ b/bfd/plugin.c +@@ -136,6 +136,7 @@ struct plugin_list_entry + asymbol **real_syms; + int lto_nsyms; + const struct ld_plugin_symbol *lto_syms; ++ bfd_boolean has_symbol_type; + + struct plugin_list_entry *next; + +@@ -503,6 +504,14 @@ add_symbols (void * handle, + return LDPS_OK; + } + ++static enum ld_plugin_status ++add_symbols_v2 (void *handle, int nsyms, ++ const struct ld_plugin_symbol *syms) ++{ ++ current_plugin->has_symbol_type = TRUE; ++ return add_symbols (handle, nsyms, syms); ++} ++ + int + bfd_plugin_open_input (bfd *ibfd, struct ld_plugin_input_file *file) + { +@@ -560,7 +569,8 @@ try_claim (bfd *abfd) + current_plugin->claim_file (&file, &claimed); + if (claimed) + { +- if (current_plugin->all_symbols_read) ++ if (current_plugin->all_symbols_read ++ && !current_plugin->has_symbol_type) + { + struct plugin_data_struct *plugin_data + = abfd->tdata.plugin_data; +@@ -602,7 +612,7 @@ try_load_plugin (const char *pname, + bfd *abfd, bfd_boolean build_list_p) + { + void *plugin_handle; +- struct ld_plugin_tv tv[12]; ++ struct ld_plugin_tv tv[13]; + int i; + ld_plugin_onload onload; + enum ld_plugin_status status; +@@ -665,6 +675,10 @@ try_load_plugin (const char *pname, + tv[i].tv_tag = LDPT_ADD_SYMBOLS; + tv[i].tv_u.tv_add_symbols = add_symbols; + ++ ++i; ++ tv[i].tv_tag = LDPT_ADD_SYMBOLS_V2; ++ tv[i].tv_u.tv_add_symbols = add_symbols_v2; ++ + if (get_lto_wrapper (plugin_list_iter)) + { + ++i; +@@ -977,9 +991,15 @@ bfd_plugin_canonicalize_symtab (bfd *abfd, + struct plugin_data_struct *plugin_data = abfd->tdata.plugin_data; + long nsyms = plugin_data->nsyms; + const struct ld_plugin_symbol *syms = plugin_data->syms; +- static asection fake_section +- = BFD_FAKE_SECTION (fake_section, NULL, "plug", 0, ++ static asection fake_text_section ++ = BFD_FAKE_SECTION (fake_text_section, NULL, "plug", 0, + SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS); ++ static asection fake_data_section ++ = BFD_FAKE_SECTION (fake_data_section, NULL, "plug", 0, ++ SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS); ++ static asection fake_bss_section ++ = BFD_FAKE_SECTION (fake_bss_section, NULL, "plug", 0, ++ SEC_ALLOC); + static asection fake_common_section + = BFD_FAKE_SECTION (fake_common_section, NULL, "plug", 0, SEC_IS_COMMON); + int i, j; +@@ -1014,16 +1034,34 @@ bfd_plugin_canonicalize_symtab (bfd *abfd, + break; + case LDPK_DEF: + case LDPK_WEAKDEF: +- s->section = &fake_section; +- if (real_nsyms) +- /* Use real LTO symbols if possible. */ +- for (j = 0; j < real_nsyms; j++) +- if (real_syms[j]->name +- && strcmp (syms[i].name, real_syms[j]->name) == 0) +- { +- s->section = real_syms[j]->section; +- break; +- } ++ if (current_plugin->has_symbol_type) ++ switch (syms[i].symbol_type) ++ { ++ case LDST_UNKNOWN: ++ /* What is the best fake section for LDST_UNKNOWN? */ ++ case LDST_FUNCTION: ++ s->section = &fake_text_section; ++ break; ++ case LDST_VARIABLE: ++ if (syms[i].section_kind == LDSSK_BSS) ++ s->section = &fake_bss_section; ++ else ++ s->section = &fake_data_section; ++ break; ++ } ++ else ++ { ++ s->section = &fake_text_section; ++ if (real_nsyms) ++ /* Use real LTO symbols if possible. */ ++ for (j = 0; j < real_nsyms; j++) ++ if (real_syms[j]->name ++ && strcmp (syms[i].name, real_syms[j]->name) == 0) ++ { ++ s->section = real_syms[j]->section; ++ break; ++ } ++ } + break; + default: + BFD_ASSERT (0); +-- +2.27.0 + +From 23820109ced73d231b69ea6fa9a85b743d7843c8 Mon Sep 17 00:00:00 2001 +From: "H.J. Lu" +Date: Wed, 25 Mar 2020 06:58:19 -0700 +Subject: [PATCH] plugin: Don't invoke LTO-wrapper + +Don't invoke LTO-wrapper since the LTO wrapper approach is not only +slow but also unreliable. For GCC 10 or newer, LDPT_ADD_SYMBOLS_V2 +will be used. + +bfd/ + + * configure.ac (HAVE_EXECUTABLE_SUFFIX): Removed. + (EXECUTABLE_SUFFIX): Likewise. + * config.in: Regenerated. + * configure: Likewise. + * plugin.c (bfd_plugin_close_and_cleanup): Defined as + _bfd_generic_close_and_cleanup. + (plugin_list_entry): Remove resolution_file, resolution_option, + real_bfd, real_nsyms, real_syms, lto_nsyms, lto_syms, gcc, + lto_wrapper, gcc_env and initialized, + (need_lto_wrapper_p): Removed. + (get_lto_wrapper): Likewise. + (setup_lto_wrapper_env): Likewise. + (register_all_symbols_read): Likewise. + (egister_cleanup): Likewise. + (get_symbols): Likewise. + (add_input_file): Likewise. + (bfd_plugin_set_program_name): Remove need_lto_wrapper. + (add_symbols): Updated. + (try_claim): Likewise. + (try_load_plugin): Likewise. + (bfd_plugin_canonicalize_symtab): Likewise. + * plugin.h (bfd_plugin_set_program_name): Remove int argument. + (plugin_data_struct): Remove real_bfd, real_nsyms and + real_syms. + +binutils/ + + * ar.c (main): Update bfd_plugin_set_program_name call. + * nm.c (main): Likewise. + +ld/ + + * testsuite/ld-plugin/lto.exp (lto_link_tests): Run PR ld/25355 + test only for GCC 10 or newer. + +(cherry picked from commit 3d98c46092341c1373d960d0a66ca502d5b7ee7f) +--- + bfd/ChangeLog | 27 ++ + bfd/config.in | 6 - + bfd/configure | 10 - + bfd/configure.ac | 6 - + bfd/plugin.c | 453 +-------------------------------- + bfd/plugin.h | 5 +- + binutils/ChangeLog | 5 + + binutils/ar.c | 2 +- + binutils/nm.c | 2 +- + ld/ChangeLog | 5 + + ld/testsuite/ld-plugin/lto.exp | 15 +- + 11 files changed, 60 insertions(+), 476 deletions(-) + +diff --git a/bfd/config.in b/bfd/config.in +index e1dc0f0c445b..be572969fc04 100644 +--- a/bfd/config.in ++++ b/bfd/config.in +@@ -18,9 +18,6 @@ + language is requested. */ + #undef ENABLE_NLS + +-/* Suffix used for executables, if any. */ +-#undef EXECUTABLE_SUFFIX +- + /* Define to 1 if you have the header file. */ + #undef HAVE_ALLOCA_H + +@@ -98,9 +95,6 @@ + /* Define to 1 if you have the header file. */ + #undef HAVE_DLFCN_H + +-/* Does the platform use an executable suffix? */ +-#undef HAVE_EXECUTABLE_SUFFIX +- + /* Define to 1 if you have the `fcntl' function. */ + #undef HAVE_FCNTL + +diff --git a/bfd/configure b/bfd/configure +index 7c0708e2f82c..bc576b7894ab 100755 +--- a/bfd/configure ++++ b/bfd/configure +@@ -12813,16 +12813,6 @@ fi + + + +-if test -n "$EXEEXT"; then +- +-$as_echo "#define HAVE_EXECUTABLE_SUFFIX 1" >>confdefs.h +- +-fi +- +-cat >>confdefs.h <<_ACEOF +-#define EXECUTABLE_SUFFIX "${EXEEXT}" +-_ACEOF +- + + host64=false + target64=false +diff --git a/bfd/configure.ac b/bfd/configure.ac +index af4d4b8c1354..c5bfbd5d129c 100644 +--- a/bfd/configure.ac ++++ b/bfd/configure.ac +@@ -157,12 +157,6 @@ AM_MAINTAINER_MODE + AM_CONDITIONAL(GENINSRC_NEVER, false) + AM_INSTALL_LIBBFD + AC_EXEEXT +-if test -n "$EXEEXT"; then +- AC_DEFINE(HAVE_EXECUTABLE_SUFFIX, 1, +- [Does the platform use an executable suffix?]) +-fi +-AC_DEFINE_UNQUOTED(EXECUTABLE_SUFFIX, "${EXEEXT}", +- [Suffix used for executables, if any.]) + + host64=false + target64=false +diff --git a/bfd/plugin.c b/bfd/plugin.c +index 0f045372b7e0..b2b1630e355c 100644 +--- a/bfd/plugin.c ++++ b/bfd/plugin.c +@@ -69,6 +69,7 @@ dlerror (void) + + #endif /* !defined (HAVE_DLFCN_H) && defined (HAVE_WINDOWS_H) */ + ++#define bfd_plugin_close_and_cleanup _bfd_generic_close_and_cleanup + #define bfd_plugin_bfd_free_cached_info _bfd_generic_bfd_free_cached_info + #define bfd_plugin_new_section_hook _bfd_generic_new_section_hook + #define bfd_plugin_get_section_contents _bfd_generic_get_section_contents +@@ -129,196 +130,20 @@ struct plugin_list_entry + ld_plugin_claim_file_handler claim_file; + ld_plugin_all_symbols_read_handler all_symbols_read; + ld_plugin_all_symbols_read_handler cleanup_handler; +- char *resolution_file; +- char *resolution_option; +- bfd *real_bfd; +- long real_nsyms; +- asymbol **real_syms; +- int lto_nsyms; +- const struct ld_plugin_symbol *lto_syms; + bfd_boolean has_symbol_type; + + struct plugin_list_entry *next; + + /* These can be reused for all IR objects. */ + const char *plugin_name; +- char *gcc; +- char *lto_wrapper; +- char *gcc_env; +- bfd_boolean initialized; + }; + + static const char *plugin_program_name; +-static int need_lto_wrapper_p; + + void +-bfd_plugin_set_program_name (const char *program_name, +- int need_lto_wrapper) ++bfd_plugin_set_program_name (const char *program_name) + { + plugin_program_name = program_name; +- need_lto_wrapper_p = need_lto_wrapper; +-} +- +-/* Use GCC LTO wrapper to covert LTO IR object to the real object. */ +- +-static bfd_boolean +-get_lto_wrapper (struct plugin_list_entry *plugin) +-{ +- struct stat st; +- const char *real_name; +- const char *base_name; +- size_t length; +- const char *target_start = NULL; +- const char *target_end = NULL; +- size_t target_length = 0; +- char *gcc_name; +- char *wrapper_name; +- char *p; +- char dir_seperator = '\0'; +- char *resolution_file; +- +- if (!need_lto_wrapper_p) +- return FALSE; +- +- if (plugin->initialized) +- { +- if (plugin->lto_wrapper) +- { +- resolution_file = make_temp_file (".res"); +- if (resolution_file) +- { +- plugin->resolution_file = resolution_file; +- plugin->resolution_option = concat ("-fresolution=", +- resolution_file, NULL); +- return TRUE; +- } +- else +- { +- /* Something is wrong. Give up. */ +- free (plugin->gcc); +- free (plugin->lto_wrapper); +- free (plugin->gcc_env); +- plugin->gcc = NULL; +- plugin->gcc_env = NULL; +- plugin->lto_wrapper = NULL; +- } +- } +- +- return FALSE; +- } +- +- plugin->initialized = TRUE; +- +- /* Check for PREFIX/libexec/gcc/TARGET/VERSION/liblto_plugin.so. */ +- real_name = lrealpath (plugin->plugin_name); +- base_name = lbasename (real_name); +- +- /* The directory length in plugin pathname. */ +- length = base_name - real_name; +- +- /* Skip if there is no PREFIX. */ +- if (!length) +- return FALSE; +- +- p = (char *) real_name + length - 1; +- if (IS_DIR_SEPARATOR (*p)) +- { +- int level = 0; +- for (; p != real_name; p--) +- if (IS_DIR_SEPARATOR (*p)) +- { +- level++; +- if (level == 2) +- target_end = p; +- else if (level == 3) +- { +- target_start = p + 1; +- target_length = target_end - target_start; +- } +- else if (level == 5) +- { +- dir_seperator = *p; +- break; +- } +- } +- } +- +- /* Skip if there is no TARGET nor PREFIX. */ +- if (!target_length || !dir_seperator) +- return FALSE; +- +-#ifdef HAVE_EXECUTABLE_SUFFIX +-# define GCC_EXECUTABLE "gcc" EXECUTABLE_SUFFIX +-# define LTO_WRAPPER_EXECUTABLE "lto-wrapper" EXECUTABLE_SUFFIX +-#else +-# define GCC_EXECUTABLE "gcc" +-# define LTO_WRAPPER_EXECUTABLE "lto-wrapper" +-#endif +- gcc_name = bfd_malloc (length + target_length +- + sizeof (GCC_EXECUTABLE)); +- if (gcc_name == NULL) +- return FALSE; +- memcpy (gcc_name, real_name, length); +- +- /* Get PREFIX/bin/. */ +- p += gcc_name - real_name; +- memcpy (p + 1, "bin", 3); +- p[4] = dir_seperator; +- +- /* Try PREFIX/bin/TARGET-gcc first. */ +- memcpy (p + 5, target_start, target_length); +- p[5 + target_length] = '-'; +- memcpy (p + 5 + target_length + 1, GCC_EXECUTABLE, +- sizeof (GCC_EXECUTABLE)); +- if (stat (gcc_name, &st) != 0 || !S_ISREG (st.st_mode)) +- { +- /* Then try PREFIX/bin/gcc. */ +- memcpy (p + 5, GCC_EXECUTABLE, sizeof (GCC_EXECUTABLE)); +- if (stat (gcc_name, &st) != 0 || !S_ISREG (st.st_mode)) +- { +- free (gcc_name); +- return FALSE; +- } +- } +- +- /* lto-wrapper should be in the same directory with LTO plugin. */ +- wrapper_name = bfd_malloc (length + sizeof (LTO_WRAPPER_EXECUTABLE)); +- if (wrapper_name == NULL) +- { +- free (gcc_name); +- return FALSE; +- } +- memcpy (wrapper_name, real_name, length); +- memcpy (wrapper_name + length, LTO_WRAPPER_EXECUTABLE, +- sizeof (LTO_WRAPPER_EXECUTABLE)); +- if (stat (wrapper_name, &st) == 0 && S_ISREG (st.st_mode)) +- { +- resolution_file = make_temp_file (".res"); +- if (resolution_file) +- { +- plugin->gcc = gcc_name; +- plugin->lto_wrapper = wrapper_name; +- plugin->gcc_env = concat ("COLLECT_GCC=", gcc_name, NULL); +- plugin->resolution_file = resolution_file; +- plugin->resolution_option = concat ("-fresolution=", +- resolution_file, NULL); +- return TRUE; +- } +- } +- +- free (gcc_name); +- free (wrapper_name); +- return FALSE; +-} +- +-/* Set environment variables for GCC LTO wrapper to covert LTO IR +- object to the real object. */ +- +-static int +-setup_lto_wrapper_env (struct plugin_list_entry *plugin) +-{ +- return (putenv (plugin->gcc_env) +- || putenv ("COLLECT_GCC_OPTIONS=")); + } + + static struct plugin_list_entry *plugin_list = NULL; +@@ -333,119 +158,6 @@ register_claim_file (ld_plugin_claim_file_handler handler) + return LDPS_OK; + } + +-/* Register an all-symbols-read handler. */ +- +-static enum ld_plugin_status +-register_all_symbols_read (ld_plugin_all_symbols_read_handler handler) +-{ +- current_plugin->all_symbols_read = handler; +- return LDPS_OK; +-} +- +-/* Register a cleanup handler. */ +- +-static enum ld_plugin_status +-register_cleanup (ld_plugin_all_symbols_read_handler handler) +-{ +- current_plugin->cleanup_handler = handler; +- return LDPS_OK; +-} +- +-/* Get the symbol resolution info for a plugin-claimed input file. */ +- +-static enum ld_plugin_status +-get_symbols (const void *handle ATTRIBUTE_UNUSED, int nsyms, +- struct ld_plugin_symbol *syms) +-{ +- if (syms) +- { +- int n; +- for (n = 0; n < nsyms; n++) +- { +- switch (syms[n].def) +- { +- default: +- BFD_ASSERT (0); +- break; +- case LDPK_UNDEF: +- case LDPK_WEAKUNDEF: +- syms[n].resolution = LDPR_UNDEF; +- break; +- case LDPK_DEF: +- case LDPK_WEAKDEF: +- case LDPK_COMMON: +- /* Tell plugin that LTO symbol has references from regular +- object code. */ +- syms[n].resolution = LDPR_PREVAILING_DEF; +- break; +- } +- } +- } +- +- return LDPS_OK; +-} +- +-/* Add a new (real) input file generated by a plugin. */ +- +-static enum ld_plugin_status +-add_input_file (const char *pathname) +-{ +- /* Get symbols from the real LTO object. */ +- char **matching; +- long real_symsize; +- long real_nsyms; +- asymbol **real_syms; +- int lto_nsyms; +- bfd_boolean lto_symbol_found = FALSE; +- const struct ld_plugin_symbol *lto_syms; +- bfd *rbfd; +- int i, j; +- +- rbfd = bfd_openr (pathname, NULL); +- if (!bfd_check_format_matches (rbfd, bfd_object, &matching)) +- BFD_ASSERT (0); +- +- real_symsize = bfd_get_symtab_upper_bound (rbfd); +- if (real_symsize < 0) +- BFD_ASSERT (0); +- +- real_syms = (asymbol **) bfd_malloc (real_symsize); +- if (real_syms) +- { +- real_nsyms = bfd_canonicalize_symtab (rbfd, real_syms); +- if (real_nsyms < 0) +- BFD_ASSERT (0); +- +- /* NB: LTO plugin may generate more than one real object from one +- LTO IR object. We use the one which contains LTO symbols. */ +- lto_syms = current_plugin->lto_syms; +- lto_nsyms = current_plugin->lto_nsyms; +- for (i = 0; i < lto_nsyms; i++) +- for (j = 0; j < real_nsyms; j++) +- if (real_syms[j]->name +- && strcmp (lto_syms[i].name, real_syms[j]->name) == 0) +- { +- lto_symbol_found = TRUE; +- break; +- } +- } +- +- if (lto_symbol_found) +- { +- current_plugin->real_nsyms = real_nsyms; +- current_plugin->real_syms = real_syms; +- /* NB: We can't close RBFD which own the real symbol info. */ +- current_plugin->real_bfd = rbfd; +- } +- else +- { +- bfd_close (rbfd); +- free (real_syms); +- } +- +- return LDPS_OK; +-} +- + static enum ld_plugin_status + add_symbols (void * handle, + int nsyms, +@@ -455,52 +167,16 @@ add_symbols (void * handle, + struct plugin_data_struct *plugin_data = + bfd_alloc (abfd, sizeof (plugin_data_struct)); + +- if (plugin_data) +- { +- struct ld_plugin_symbol *sym_info; +- char *strtab; +- size_t sym_info_size, name_length; +- int i; ++ if (!plugin_data) ++ return LDPS_ERR; + +- memset (plugin_data, 0, sizeof (*plugin_data)); +- +- abfd->tdata.plugin_data = plugin_data; +- +- /* NB: LTO symbols are owned by LTO plugin. Create a copy so +- that we can use it in bfd_plugin_canonicalize_symtab. */ +- sym_info_size = nsyms * sizeof (*syms); +- +- /* Allocate a string table */ +- for (i = 0; i < nsyms; i++) +- sym_info_size += strlen (syms[i].name) + 1; +- +- sym_info = bfd_alloc (abfd, sym_info_size); +- if (sym_info) +- { +- /* Copy symbol table. */ +- memcpy (sym_info, syms, nsyms * sizeof (*syms)); +- +- /* Copy symbol names in symbol table. */ +- strtab = (char *) (sym_info + nsyms); +- for (i = 0; i < nsyms; i++) +- { +- name_length = strlen (syms[i].name); +- memcpy (strtab, syms[i].name, name_length + 1); +- sym_info[i].name = strtab; +- strtab += name_length + 1; +- } +- +- plugin_data->nsyms = nsyms; +- plugin_data->syms = sym_info; +- +- current_plugin->lto_nsyms = nsyms; +- current_plugin->lto_syms = sym_info; +- } +- } ++ plugin_data->nsyms = nsyms; ++ plugin_data->syms = syms; + + if (nsyms != 0) + abfd->flags |= HAS_SYMS; + ++ abfd->tdata.plugin_data = plugin_data; + return LDPS_OK; + } + +@@ -567,42 +243,9 @@ try_claim (bfd *abfd) + && current_plugin->claim_file) + { + current_plugin->claim_file (&file, &claimed); +- if (claimed) +- { +- if (current_plugin->all_symbols_read +- && !current_plugin->has_symbol_type) +- { +- struct plugin_data_struct *plugin_data +- = abfd->tdata.plugin_data; +- if (plugin_data) +- { +- /* Get real symbols from LTO wrapper. */ +- current_plugin->all_symbols_read (); +- +- /* Copy real symbols to plugin_data. */ +- plugin_data->real_bfd = current_plugin->real_bfd; +- plugin_data->real_nsyms = current_plugin->real_nsyms; +- plugin_data->real_syms = current_plugin->real_syms; +- +- /* Clean up LTO plugin. */ +- if (current_plugin->cleanup_handler) +- current_plugin->cleanup_handler (); +- } +- } +- } +- + close (file.fd); + } + +- if (current_plugin->lto_wrapper) +- { +- /* Clean up for LTO wrapper. NB: Resolution file and option +- have been created regardless if an IR object is claimed or +- not. */ +- unlink (current_plugin->resolution_file); +- free (current_plugin->resolution_option); +- } +- + return claimed; + } + +@@ -612,7 +255,7 @@ try_load_plugin (const char *pname, + bfd *abfd, bfd_boolean build_list_p) + { + void *plugin_handle; +- struct ld_plugin_tv tv[13]; ++ struct ld_plugin_tv tv[5]; + int i; + ld_plugin_onload onload; + enum ld_plugin_status status; +@@ -679,41 +322,6 @@ try_load_plugin (const char *pname, + tv[i].tv_tag = LDPT_ADD_SYMBOLS_V2; + tv[i].tv_u.tv_add_symbols = add_symbols_v2; + +- if (get_lto_wrapper (plugin_list_iter)) +- { +- ++i; +- tv[i].tv_tag = LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK; +- tv[i].tv_u.tv_register_all_symbols_read = register_all_symbols_read; +- +- ++i; +- tv[i].tv_tag = LDPT_REGISTER_CLEANUP_HOOK; +- tv[i].tv_u.tv_register_cleanup = register_cleanup; +- +- ++i; +- tv[i].tv_tag = LDPT_GET_SYMBOLS; +- tv[i].tv_u.tv_get_symbols = get_symbols; +- +- ++i; +- tv[i].tv_tag = LDPT_GET_SYMBOLS_V2; +- tv[i].tv_u.tv_get_symbols = get_symbols; +- +- ++i; +- tv[i].tv_tag = LDPT_OPTION; +- tv[i].tv_u.tv_string = plugin_list_iter->lto_wrapper; +- +- ++i; +- tv[i].tv_tag = LDPT_OPTION; +- tv[i].tv_u.tv_string = plugin_list_iter->resolution_option; +- +- ++i; +- tv[i].tv_tag = LDPT_LINKER_OUTPUT; +- tv[i].tv_u.tv_val = LDPO_EXEC; +- +- ++i; +- tv[i].tv_tag = LDPT_ADD_INPUT_FILE; +- tv[i].tv_u.tv_add_input_file = add_input_file; +- } +- + ++i; + tv[i].tv_tag = LDPT_NULL; + tv[i].tv_u.tv_val = 0; +@@ -724,10 +332,6 @@ try_load_plugin (const char *pname, + if (status != LDPS_OK) + goto short_circuit; + +- if (current_plugin->lto_wrapper +- && setup_lto_wrapper_env (current_plugin)) +- goto short_circuit; +- + abfd->plugin_format = bfd_plugin_no; + + if (!current_plugin->claim_file) +@@ -1002,15 +606,7 @@ bfd_plugin_canonicalize_symtab (bfd *abfd, + SEC_ALLOC); + static asection fake_common_section + = BFD_FAKE_SECTION (fake_common_section, NULL, "plug", 0, SEC_IS_COMMON); +- int i, j; +- long real_nsyms; +- asymbol **real_syms; +- +- real_syms = plugin_data->real_syms; +- if (real_syms) +- real_nsyms = plugin_data->real_nsyms; +- else +- real_nsyms = 0; ++ int i; + + for (i = 0; i < nsyms; i++) + { +@@ -1050,18 +646,7 @@ bfd_plugin_canonicalize_symtab (bfd *abfd, + break; + } + else +- { +- s->section = &fake_text_section; +- if (real_nsyms) +- /* Use real LTO symbols if possible. */ +- for (j = 0; j < real_nsyms; j++) +- if (real_syms[j]->name +- && strcmp (syms[i].name, real_syms[j]->name) == 0) +- { +- s->section = real_syms[j]->section; +- break; +- } +- } ++ s->section = &fake_text_section; + break; + default: + BFD_ASSERT (0); +@@ -1110,24 +695,6 @@ bfd_plugin_sizeof_headers (bfd *a ATTRIBUTE_UNUSED, + return 0; + } + +-static bfd_boolean +-bfd_plugin_close_and_cleanup (bfd *abfd) +-{ +- struct plugin_data_struct *plugin_data; +- +- if (abfd->format != bfd_archive +- && (plugin_data = abfd->tdata.plugin_data)) +- { +- if (plugin_data->real_bfd) +- bfd_close (plugin_data->real_bfd); +- +- if (plugin_data->real_syms) +- free (plugin_data->real_syms); +- } +- +- return _bfd_generic_close_and_cleanup (abfd); +-} +- + const bfd_target plugin_vec = + { + "plugin", /* Name. */ +diff --git a/bfd/plugin.h b/bfd/plugin.h +index b2d5e50137f2..098bf0845548 100644 +--- a/bfd/plugin.h ++++ b/bfd/plugin.h +@@ -21,7 +21,7 @@ + #ifndef _PLUGIN_H_ + #define _PLUGIN_H_ + +-void bfd_plugin_set_program_name (const char *, int); ++void bfd_plugin_set_program_name (const char *); + int bfd_plugin_open_input (bfd *, struct ld_plugin_input_file *); + void bfd_plugin_set_plugin (const char *); + bfd_boolean bfd_plugin_target_p (const bfd_target *); +@@ -33,9 +33,6 @@ typedef struct plugin_data_struct + { + int nsyms; + const struct ld_plugin_symbol *syms; +- bfd *real_bfd; +- long real_nsyms; +- asymbol **real_syms; + } + plugin_data_struct; + +diff --git a/binutils/ar.c b/binutils/ar.c +index 35dd51e04af4..1057db9980ed 100644 +--- a/binutils/ar.c ++++ b/binutils/ar.c +@@ -725,7 +725,7 @@ main (int argc, char **argv) + xmalloc_set_program_name (program_name); + bfd_set_error_program_name (program_name); + #if BFD_SUPPORTS_PLUGINS +- bfd_plugin_set_program_name (program_name, 0); ++ bfd_plugin_set_program_name (program_name); + #endif + + expandargv (&argc, &argv); +diff --git a/binutils/nm.c b/binutils/nm.c +index 5b386592a615..0ee3f8838654 100644 +--- a/binutils/nm.c ++++ b/binutils/nm.c +@@ -1701,7 +1701,7 @@ main (int argc, char **argv) + xmalloc_set_program_name (program_name); + bfd_set_error_program_name (program_name); + #if BFD_SUPPORTS_PLUGINS +- bfd_plugin_set_program_name (program_name, 1); ++ bfd_plugin_set_program_name (program_name); + #endif + + START_PROGRESS (program_name, 0); +diff --git a/ld/testsuite/ld-plugin/lto.exp b/ld/testsuite/ld-plugin/lto.exp +index 1b44b0da3fda..3f1d804223d2 100644 +--- a/ld/testsuite/ld-plugin/lto.exp ++++ b/ld/testsuite/ld-plugin/lto.exp +@@ -234,13 +234,18 @@ set lto_link_tests [list \ + [list "Build pr24406-2b.o" \ + "" "-O2 -fno-lto" \ + {pr24406-2b.c}] \ +- [list "pr25355.o" \ +- "" \ +- "-flto -fno-common $lto_no_fat" \ +- {pr25355.c} \ +- [list [list "nm" "$plug_opt" "pr25355.d"]]] \ + ] + ++if { [at_least_gcc_version 10 0] } { ++ set lto_link_tests [concat $lto_link_tests [list \ ++ [list "pr25355.o" \ ++ "" \ ++ "-flto -fno-common $lto_no_fat" \ ++ {pr25355.c} \ ++ [list [list "nm" "$plug_opt" "pr25355.d"]]] \ ++ ]] ++} ++ + if { [at_least_gcc_version 4 7] } { + set lto_link_tests [concat $lto_link_tests [list \ + [list "Compile PR ld/12942 (1)" \ +-- +2.27.0 +