X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bfd%2Fplugin.c;h=97f1c9c7731bbe575300aeeb6ce26b726f2bb5a5;hb=190eb1ddba41aad3a31edead9392473ae9d3bbe3;hp=5f059befb40ecb454bdb74fd8ed95ae197f7bfee;hpb=41f37a6fb71f2a3de388108f5cdfca9cbe6e9d51;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/plugin.c b/bfd/plugin.c index 5f059befb4..97f1c9c773 100644 --- a/bfd/plugin.c +++ b/bfd/plugin.c @@ -1,5 +1,5 @@ /* Plugin support for BFD. - Copyright (C) 2009-2019 Free Software Foundation, Inc. + Copyright (C) 2009-2020 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -124,13 +124,37 @@ message (int level ATTRIBUTE_UNUSED, return LDPS_OK; } +struct plugin_list_entry +{ + /* These must be initialized for each IR object with LTO wrapper. */ + ld_plugin_claim_file_handler claim_file; + ld_plugin_all_symbols_read_handler all_symbols_read; + ld_plugin_all_symbols_read_handler cleanup_handler; + bfd_boolean has_symbol_type; + + struct plugin_list_entry *next; + + /* These can be reused for all IR objects. */ + const char *plugin_name; +}; + +static const char *plugin_program_name; + +void +bfd_plugin_set_program_name (const char *program_name) +{ + plugin_program_name = program_name; +} + +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; } @@ -143,6 +167,9 @@ add_symbols (void * handle, struct plugin_data_struct *plugin_data = bfd_alloc (abfd, sizeof (plugin_data_struct)); + if (!plugin_data) + return LDPS_ERR; + plugin_data->nsyms = nsyms; plugin_data->syms = syms; @@ -153,12 +180,12 @@ add_symbols (void * handle, return LDPS_OK; } -static const char *plugin_program_name; - -void -bfd_plugin_set_program_name (const char *program_name) +static enum ld_plugin_status +add_symbols_v2 (void *handle, int nsyms, + const struct ld_plugin_symbol *syms) { - plugin_program_name = program_name; + current_plugin->has_symbol_type = TRUE; + return add_symbols (handle, nsyms, syms); } int @@ -170,7 +197,7 @@ bfd_plugin_open_input (bfd *ibfd, struct ld_plugin_input_file *file) while (iobfd->my_archive && !bfd_is_thin_archive (iobfd->my_archive)) iobfd = iobfd->my_archive; - file->name = iobfd->filename; + file->name = bfd_get_filename (iobfd); if (!iobfd->iostream && !bfd_open_file (iobfd)) return 0; @@ -212,68 +239,73 @@ 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); + close (file.fd); + } + 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]; + void *plugin_handle; + struct ld_plugin_tv tv[5]; int i; ld_plugin_onload onload; enum ld_plugin_status status; - struct plugin_list_entry *plugin_list_iter; + int result = 0; + + /* NB: Each object is independent. Reuse the previous plugin from + the last run will lead to wrong result. */ + if (current_plugin) + memset (current_plugin, 0, + offsetof (struct plugin_list_entry, next)); - *has_plugin_p = 0; + if (plugin_list_iter) + pname = plugin_list_iter->plugin_name; plugin_handle = dlopen (pname, RTLD_NOW); if (!plugin_handle) { - _bfd_error_handler ("%s\n", dlerror ()); + _bfd_error_handler ("Failed to load plugin '%s', reason: %s\n", + pname, dlerror ()); return 0; } - for (plugin_list_iter = plugin_list; - plugin_list_iter; - plugin_list_iter = plugin_list_iter->next) + if (plugin_list_iter == NULL) { - if (plugin_handle == plugin_list_iter->handle) + size_t length_plugin_name = strlen (pname) + 1; + char *plugin_name = bfd_malloc (length_plugin_name); + if (plugin_name == NULL) + goto short_circuit; + plugin_list_iter = bfd_malloc (sizeof *plugin_list_iter); + if (plugin_list_iter == NULL) { - dlclose (plugin_handle); - if (!plugin_list_iter->claim_file) - return 0; - - register_claim_file (plugin_list_iter->claim_file); - goto have_claim_file; + free (plugin_name); + goto short_circuit; } + /* 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 = bfd_malloc (sizeof *plugin_list_iter); - if (plugin_list_iter == NULL) - return 0; - plugin_list_iter->handle = plugin_handle; - plugin_list_iter->claim_file = NULL; - plugin_list_iter->next = plugin_list; - plugin_list = plugin_list_iter; + current_plugin = plugin_list_iter; + if (build_list_p) + goto short_circuit; onload = dlsym (plugin_handle, "onload"); if (!onload) - return 0; + goto short_circuit; i = 0; tv[i].tv_tag = LDPT_MESSAGE; @@ -287,37 +319,40 @@ 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; + ++i; + tv[i].tv_tag = LDPT_ADD_SYMBOLS_V2; + tv[i].tv_u.tv_add_symbols = add_symbols_v2; + ++i; tv[i].tv_tag = LDPT_NULL; tv[i].tv_u.tv_val = 0; + /* 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; + goto short_circuit; abfd->plugin_format = bfd_plugin_no; - if (!claim_file) - return 0; + if (!current_plugin->claim_file) + 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. */ +static int has_plugin_list = -1; -static int has_plugin = -1; - -static const bfd_target *(*ld_plugin_object_p) (bfd *); +static bfd_cleanup (*ld_plugin_object_p) (bfd *); static const char *plugin_name; @@ -325,7 +360,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 +367,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. */ @@ -359,13 +393,13 @@ bfd_plugin_target_p (const bfd_target *target) /* Register OBJECT_P to be used by bfd_plugin_object_p. */ void -register_ld_plugin_object_p (const bfd_target *(*object_p) (bfd *)) +register_ld_plugin_object_p (bfd_cleanup (*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 +408,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,30 +446,42 @@ 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; } -static const bfd_target * +static bfd_cleanup bfd_plugin_object_p (bfd *abfd) { if (ld_plugin_object_p) @@ -451,7 +490,7 @@ bfd_plugin_object_p (bfd *abfd) if (abfd->plugin_format == bfd_plugin_unknown && !load_plugin (abfd)) return NULL; - return abfd->plugin_format == bfd_plugin_yes ? abfd->xvec : NULL; + return abfd->plugin_format == bfd_plugin_yes ? _bfd_no_cleanup : NULL; } /* Copy any private info we understand from the input bfd @@ -557,9 +596,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; @@ -586,7 +631,23 @@ bfd_plugin_canonicalize_symtab (bfd *abfd, break; case LDPK_DEF: case LDPK_WEAKDEF: - s->section = &fake_section; + 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; break; default: BFD_ASSERT (0);