X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bfd%2Fplugin.c;h=537ab603110b88550032cf49d8a7c6a354c3f09a;hb=78f2c40a12179d26d3065c09f054b7e751b2732f;hp=7422da0a4aa4b6f3d3efc2e7cd05f6fb633856f8;hpb=07d6d2b8345ef3dc82eab49635acac9ee67dbb18;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/plugin.c b/bfd/plugin.c index 7422da0a4a..537ab60311 100644 --- a/bfd/plugin.c +++ b/bfd/plugin.c @@ -1,5 +1,5 @@ /* Plugin support for BFD. - Copyright (C) 2009-2017 Free Software Foundation, Inc. + Copyright (C) 2009-2020 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -80,7 +80,7 @@ dlerror (void) #define bfd_plugin_bfd_set_private_flags _bfd_generic_bfd_set_private_flags #define bfd_plugin_core_file_matches_executable_p generic_core_file_matches_executable_p #define bfd_plugin_bfd_is_local_label_name _bfd_nosymbols_bfd_is_local_label_name -#define bfd_plugin_bfd_is_target_special_symbol ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false) +#define bfd_plugin_bfd_is_target_special_symbol _bfd_bool_bfd_asymbol_false #define bfd_plugin_get_lineno _bfd_nosymbols_get_lineno #define bfd_plugin_find_nearest_line _bfd_nosymbols_find_nearest_line #define bfd_plugin_find_line _bfd_nosymbols_find_line @@ -102,9 +102,11 @@ dlerror (void) #define bfd_plugin_bfd_lookup_section_flags bfd_generic_lookup_section_flags #define bfd_plugin_bfd_merge_sections bfd_generic_merge_sections #define bfd_plugin_bfd_is_group_section bfd_generic_is_group_section +#define bfd_plugin_bfd_group_name bfd_generic_group_name #define bfd_plugin_bfd_discard_group bfd_generic_discard_group #define bfd_plugin_section_already_linked _bfd_generic_section_already_linked #define bfd_plugin_bfd_define_common_symbol bfd_generic_define_common_symbol +#define bfd_plugin_bfd_link_hide_symbol _bfd_generic_link_hide_symbol #define bfd_plugin_bfd_define_start_stop bfd_generic_define_start_stop #define bfd_plugin_bfd_copy_link_hash_symbol_type _bfd_generic_copy_link_hash_symbol_type #define bfd_plugin_bfd_link_check_relocs _bfd_generic_link_check_relocs @@ -123,7 +125,7 @@ message (int level ATTRIBUTE_UNUSED, } /* Register a claim-file handler. */ -static ld_plugin_claim_file_handler claim_file; +static ld_plugin_claim_file_handler claim_file = NULL; static enum ld_plugin_status register_claim_file (ld_plugin_claim_file_handler handler) @@ -165,20 +167,33 @@ bfd_plugin_open_input (bfd *ibfd, struct ld_plugin_input_file *file) bfd *iobfd; iobfd = ibfd; - if (ibfd->my_archive && !bfd_is_thin_archive (ibfd->my_archive)) - iobfd = ibfd->my_archive; + while (iobfd->my_archive + && !bfd_is_thin_archive (iobfd->my_archive)) + iobfd = iobfd->my_archive; file->name = iobfd->filename; if (!iobfd->iostream && !bfd_open_file (iobfd)) return 0; - file->fd = fileno ((FILE *) iobfd->iostream); + /* The plugin API expects that the file descriptor won't be closed + and reused as done by the bfd file cache. So open it again. + dup isn't good enough. plugin IO uses lseek/read while BFD uses + fseek/fread. It isn't wise to mix the unistd and stdio calls on + the same underlying file descriptor. */ + file->fd = open (file->name, O_RDONLY | O_BINARY); + if (file->fd < 0) + return 0; if (iobfd == ibfd) { struct stat stat_buf; + if (fstat (file->fd, &stat_buf)) - return 0; + { + close(file->fd); + return 0; + } + file->offset = 0; file->filesize = stat_buf.st_size; } @@ -196,23 +211,33 @@ try_claim (bfd *abfd) int claimed = 0; struct ld_plugin_input_file file; + file.handle = abfd; if (!bfd_plugin_open_input (abfd, &file)) return 0; - file.handle = abfd; - off_t cur_offset = lseek (file.fd, 0, SEEK_CUR); - claim_file (&file, &claimed); - lseek (file.fd, cur_offset, SEEK_SET); + if (claim_file) + 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) { - void *plugin_handle; + void *plugin_handle = NULL; struct ld_plugin_tv tv[4]; int i; ld_plugin_onload onload; enum ld_plugin_status status; + struct plugin_list_entry *plugin_list_iter; *has_plugin_p = 0; @@ -223,9 +248,32 @@ 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; + plugin_list_iter->handle = plugin_handle; + plugin_list_iter->claim_file = NULL; + plugin_list_iter->next = plugin_list; + plugin_list = plugin_list_iter; + onload = dlsym (plugin_handle, "onload"); if (!onload) - goto err; + return 0; i = 0; tv[i].tv_tag = LDPT_MESSAGE; @@ -246,24 +294,23 @@ try_load_plugin (const char *pname, bfd *abfd, int *has_plugin_p) status = (*onload)(tv); if (status != LDPS_OK) - goto err; + return 0; + plugin_list_iter->claim_file = claim_file; + +have_claim_file: *has_plugin_p = 1; abfd->plugin_format = bfd_plugin_no; if (!claim_file) - goto err; + return 0; if (!try_claim (abfd)) - goto err; + return 0; abfd->plugin_format = bfd_plugin_yes; - return 1; - - err: - return 0; } /* There may be plugin libraries in lib/bfd-plugins. */ @@ -320,11 +367,15 @@ register_ld_plugin_object_p (const bfd_target *(*object_p) (bfd *)) static int load_plugin (bfd *abfd) { - char *plugin_dir; - char *p; - DIR *d; - struct dirent *ent; + /* The intent was to search ${libdir}/bfd-plugins for plugins, but + unfortunately the original implementation wasn't precisely that + when configuring binutils using --libdir. Search in the proper + path first, then the old one for backwards compatibility. */ + 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; @@ -335,38 +386,58 @@ load_plugin (bfd *abfd) if (plugin_program_name == NULL) return found; - plugin_dir = concat (BINDIR, "/../lib/bfd-plugins", NULL); - p = make_relative_prefix (plugin_program_name, - BINDIR, - plugin_dir); - free (plugin_dir); - plugin_dir = NULL; - - d = opendir (p); - if (!d) - goto out; - - while ((ent = readdir (d))) + /* 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 + st_ino to zero or the actual st_ino is zero we might waste some + time, but that doesn't matter too much. */ + last_st.st_dev = 0; + last_st.st_ino = 0; + for (i = 0; i < sizeof (path) / sizeof (path[0]); i++) { - char *full_name; - struct stat s; - int valid_plugin; - - full_name = concat (p, "/", ent->d_name, NULL); - if (stat(full_name, &s) == 0 && S_ISREG (s.st_mode)) - found = try_load_plugin (full_name, abfd, &valid_plugin); - if (has_plugin <= 0) - has_plugin = valid_plugin; - free (full_name); + char *plugin_dir = make_relative_prefix (plugin_program_name, + BINDIR, + path[i]); + if (plugin_dir) + { + struct stat st; + DIR *d; + + if (stat (plugin_dir, &st) == 0 + && S_ISDIR (st.st_mode) + && !(last_st.st_dev == st.st_dev + && last_st.st_ino == st.st_ino + && st.st_ino != 0) + && (d = opendir (plugin_dir)) != NULL) + { + struct dirent *ent; + + last_st.st_dev = st.st_dev; + last_st.st_ino = st.st_ino; + while ((ent = readdir (d)) != NULL) + { + char *full_name; + + 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; + } + free (full_name); + if (found) + break; + } + closedir (d); + } + free (plugin_dir); + } if (found) break; } - out: - free (p); - if (d) - closedir (d); - return found; } @@ -486,13 +557,13 @@ 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; - static asection fake_common_section; + static asection fake_section + = BFD_FAKE_SECTION (fake_section, NULL, "plug", 0, + 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; - fake_section.name = ".text"; - fake_common_section.flags = SEC_IS_COMMON; - for (i = 0; i < nsyms; i++) { asymbol *s = bfd_alloc (abfd, sizeof (asymbol)); @@ -594,16 +665,16 @@ const bfd_target plugin_vec = _bfd_dummy_target }, { /* bfd_set_format. */ - bfd_false, - bfd_false, + _bfd_bool_bfd_false_error, + _bfd_bool_bfd_false_error, _bfd_generic_mkarchive, - bfd_false, + _bfd_bool_bfd_false_error, }, { /* bfd_write_contents. */ - bfd_false, - bfd_false, + _bfd_bool_bfd_false_error, + _bfd_bool_bfd_false_error, _bfd_write_archive_contents, - bfd_false, + _bfd_bool_bfd_false_error, }, BFD_JUMP_TABLE_GENERIC (bfd_plugin),