1*fae548d3Szrj /* Plugin support for BFD. 2*fae548d3Szrj Copyright (C) 2009-2020 Free Software Foundation, Inc. 3*fae548d3Szrj 4*fae548d3Szrj This file is part of BFD, the Binary File Descriptor library. 5*fae548d3Szrj 6*fae548d3Szrj This program is free software; you can redistribute it and/or modify 7*fae548d3Szrj it under the terms of the GNU General Public License as published by 8*fae548d3Szrj the Free Software Foundation; either version 3 of the License, or 9*fae548d3Szrj (at your option) any later version. 10*fae548d3Szrj 11*fae548d3Szrj This program is distributed in the hope that it will be useful, 12*fae548d3Szrj but WITHOUT ANY WARRANTY; without even the implied warranty of 13*fae548d3Szrj MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14*fae548d3Szrj GNU General Public License for more details. 15*fae548d3Szrj 16*fae548d3Szrj You should have received a copy of the GNU General Public License 17*fae548d3Szrj along with this program; if not, write to the Free Software 18*fae548d3Szrj Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 19*fae548d3Szrj MA 02110-1301, USA. */ 20*fae548d3Szrj 21*fae548d3Szrj #include "sysdep.h" 22*fae548d3Szrj #include "bfd.h" 23*fae548d3Szrj 24*fae548d3Szrj #if BFD_SUPPORTS_PLUGINS 25*fae548d3Szrj 26*fae548d3Szrj #include <assert.h> 27*fae548d3Szrj #ifdef HAVE_DLFCN_H 28*fae548d3Szrj #include <dlfcn.h> 29*fae548d3Szrj #elif defined (HAVE_WINDOWS_H) 30*fae548d3Szrj #include <windows.h> 31*fae548d3Szrj #else 32*fae548d3Szrj #error Unknown how to handle dynamic-load-libraries. 33*fae548d3Szrj #endif 34*fae548d3Szrj #include <stdarg.h> 35*fae548d3Szrj #include "plugin-api.h" 36*fae548d3Szrj #include "plugin.h" 37*fae548d3Szrj #include "libbfd.h" 38*fae548d3Szrj #include "libiberty.h" 39*fae548d3Szrj #include <dirent.h> 40*fae548d3Szrj 41*fae548d3Szrj #if !defined (HAVE_DLFCN_H) && defined (HAVE_WINDOWS_H) 42*fae548d3Szrj 43*fae548d3Szrj #define RTLD_NOW 0 /* Dummy value. */ 44*fae548d3Szrj 45*fae548d3Szrj static void * 46*fae548d3Szrj dlopen (const char *file, int mode ATTRIBUTE_UNUSED) 47*fae548d3Szrj { 48*fae548d3Szrj return LoadLibrary (file); 49*fae548d3Szrj } 50*fae548d3Szrj 51*fae548d3Szrj static void * 52*fae548d3Szrj dlsym (void *handle, const char *name) 53*fae548d3Szrj { 54*fae548d3Szrj return GetProcAddress (handle, name); 55*fae548d3Szrj } 56*fae548d3Szrj 57*fae548d3Szrj static int ATTRIBUTE_UNUSED 58*fae548d3Szrj dlclose (void *handle) 59*fae548d3Szrj { 60*fae548d3Szrj FreeLibrary (handle); 61*fae548d3Szrj return 0; 62*fae548d3Szrj } 63*fae548d3Szrj 64*fae548d3Szrj static const char * 65*fae548d3Szrj dlerror (void) 66*fae548d3Szrj { 67*fae548d3Szrj return "Unable to load DLL."; 68*fae548d3Szrj } 69*fae548d3Szrj 70*fae548d3Szrj #endif /* !defined (HAVE_DLFCN_H) && defined (HAVE_WINDOWS_H) */ 71*fae548d3Szrj 72*fae548d3Szrj #define bfd_plugin_close_and_cleanup _bfd_generic_close_and_cleanup 73*fae548d3Szrj #define bfd_plugin_bfd_free_cached_info _bfd_generic_bfd_free_cached_info 74*fae548d3Szrj #define bfd_plugin_new_section_hook _bfd_generic_new_section_hook 75*fae548d3Szrj #define bfd_plugin_get_section_contents _bfd_generic_get_section_contents 76*fae548d3Szrj #define bfd_plugin_get_section_contents_in_window _bfd_generic_get_section_contents_in_window 77*fae548d3Szrj #define bfd_plugin_bfd_copy_private_header_data _bfd_generic_bfd_copy_private_header_data 78*fae548d3Szrj #define bfd_plugin_bfd_merge_private_bfd_data _bfd_generic_bfd_merge_private_bfd_data 79*fae548d3Szrj #define bfd_plugin_bfd_copy_private_header_data _bfd_generic_bfd_copy_private_header_data 80*fae548d3Szrj #define bfd_plugin_bfd_set_private_flags _bfd_generic_bfd_set_private_flags 81*fae548d3Szrj #define bfd_plugin_core_file_matches_executable_p generic_core_file_matches_executable_p 82*fae548d3Szrj #define bfd_plugin_bfd_is_local_label_name _bfd_nosymbols_bfd_is_local_label_name 83*fae548d3Szrj #define bfd_plugin_bfd_is_target_special_symbol _bfd_bool_bfd_asymbol_false 84*fae548d3Szrj #define bfd_plugin_get_lineno _bfd_nosymbols_get_lineno 85*fae548d3Szrj #define bfd_plugin_find_nearest_line _bfd_nosymbols_find_nearest_line 86*fae548d3Szrj #define bfd_plugin_find_line _bfd_nosymbols_find_line 87*fae548d3Szrj #define bfd_plugin_find_inliner_info _bfd_nosymbols_find_inliner_info 88*fae548d3Szrj #define bfd_plugin_get_symbol_version_string _bfd_nosymbols_get_symbol_version_string 89*fae548d3Szrj #define bfd_plugin_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol 90*fae548d3Szrj #define bfd_plugin_read_minisymbols _bfd_generic_read_minisymbols 91*fae548d3Szrj #define bfd_plugin_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol 92*fae548d3Szrj #define bfd_plugin_set_arch_mach bfd_default_set_arch_mach 93*fae548d3Szrj #define bfd_plugin_set_section_contents _bfd_generic_set_section_contents 94*fae548d3Szrj #define bfd_plugin_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents 95*fae548d3Szrj #define bfd_plugin_bfd_relax_section bfd_generic_relax_section 96*fae548d3Szrj #define bfd_plugin_bfd_link_hash_table_create _bfd_generic_link_hash_table_create 97*fae548d3Szrj #define bfd_plugin_bfd_link_add_symbols _bfd_generic_link_add_symbols 98*fae548d3Szrj #define bfd_plugin_bfd_link_just_syms _bfd_generic_link_just_syms 99*fae548d3Szrj #define bfd_plugin_bfd_final_link _bfd_generic_final_link 100*fae548d3Szrj #define bfd_plugin_bfd_link_split_section _bfd_generic_link_split_section 101*fae548d3Szrj #define bfd_plugin_bfd_gc_sections bfd_generic_gc_sections 102*fae548d3Szrj #define bfd_plugin_bfd_lookup_section_flags bfd_generic_lookup_section_flags 103*fae548d3Szrj #define bfd_plugin_bfd_merge_sections bfd_generic_merge_sections 104*fae548d3Szrj #define bfd_plugin_bfd_is_group_section bfd_generic_is_group_section 105*fae548d3Szrj #define bfd_plugin_bfd_group_name bfd_generic_group_name 106*fae548d3Szrj #define bfd_plugin_bfd_discard_group bfd_generic_discard_group 107*fae548d3Szrj #define bfd_plugin_section_already_linked _bfd_generic_section_already_linked 108*fae548d3Szrj #define bfd_plugin_bfd_define_common_symbol bfd_generic_define_common_symbol 109*fae548d3Szrj #define bfd_plugin_bfd_link_hide_symbol _bfd_generic_link_hide_symbol 110*fae548d3Szrj #define bfd_plugin_bfd_define_start_stop bfd_generic_define_start_stop 111*fae548d3Szrj #define bfd_plugin_bfd_copy_link_hash_symbol_type _bfd_generic_copy_link_hash_symbol_type 112*fae548d3Szrj #define bfd_plugin_bfd_link_check_relocs _bfd_generic_link_check_relocs 113*fae548d3Szrj 114*fae548d3Szrj static enum ld_plugin_status 115*fae548d3Szrj message (int level ATTRIBUTE_UNUSED, 116*fae548d3Szrj const char * format, ...) 117*fae548d3Szrj { 118*fae548d3Szrj va_list args; 119*fae548d3Szrj va_start (args, format); 120*fae548d3Szrj printf ("bfd plugin: "); 121*fae548d3Szrj vprintf (format, args); 122*fae548d3Szrj putchar ('\n'); 123*fae548d3Szrj va_end (args); 124*fae548d3Szrj return LDPS_OK; 125*fae548d3Szrj } 126*fae548d3Szrj 127*fae548d3Szrj /* Register a claim-file handler. */ 128*fae548d3Szrj static ld_plugin_claim_file_handler claim_file = NULL; 129*fae548d3Szrj 130*fae548d3Szrj static enum ld_plugin_status 131*fae548d3Szrj register_claim_file (ld_plugin_claim_file_handler handler) 132*fae548d3Szrj { 133*fae548d3Szrj claim_file = handler; 134*fae548d3Szrj return LDPS_OK; 135*fae548d3Szrj } 136*fae548d3Szrj 137*fae548d3Szrj static enum ld_plugin_status 138*fae548d3Szrj add_symbols (void * handle, 139*fae548d3Szrj int nsyms, 140*fae548d3Szrj const struct ld_plugin_symbol * syms) 141*fae548d3Szrj { 142*fae548d3Szrj bfd *abfd = handle; 143*fae548d3Szrj struct plugin_data_struct *plugin_data = 144*fae548d3Szrj bfd_alloc (abfd, sizeof (plugin_data_struct)); 145*fae548d3Szrj 146*fae548d3Szrj plugin_data->nsyms = nsyms; 147*fae548d3Szrj plugin_data->syms = syms; 148*fae548d3Szrj 149*fae548d3Szrj if (nsyms != 0) 150*fae548d3Szrj abfd->flags |= HAS_SYMS; 151*fae548d3Szrj 152*fae548d3Szrj abfd->tdata.plugin_data = plugin_data; 153*fae548d3Szrj return LDPS_OK; 154*fae548d3Szrj } 155*fae548d3Szrj 156*fae548d3Szrj static const char *plugin_program_name; 157*fae548d3Szrj 158*fae548d3Szrj void 159*fae548d3Szrj bfd_plugin_set_program_name (const char *program_name) 160*fae548d3Szrj { 161*fae548d3Szrj plugin_program_name = program_name; 162*fae548d3Szrj } 163*fae548d3Szrj 164*fae548d3Szrj int 165*fae548d3Szrj bfd_plugin_open_input (bfd *ibfd, struct ld_plugin_input_file *file) 166*fae548d3Szrj { 167*fae548d3Szrj bfd *iobfd; 168*fae548d3Szrj 169*fae548d3Szrj iobfd = ibfd; 170*fae548d3Szrj while (iobfd->my_archive 171*fae548d3Szrj && !bfd_is_thin_archive (iobfd->my_archive)) 172*fae548d3Szrj iobfd = iobfd->my_archive; 173*fae548d3Szrj file->name = iobfd->filename; 174*fae548d3Szrj 175*fae548d3Szrj if (!iobfd->iostream && !bfd_open_file (iobfd)) 176*fae548d3Szrj return 0; 177*fae548d3Szrj 178*fae548d3Szrj /* The plugin API expects that the file descriptor won't be closed 179*fae548d3Szrj and reused as done by the bfd file cache. So open it again. 180*fae548d3Szrj dup isn't good enough. plugin IO uses lseek/read while BFD uses 181*fae548d3Szrj fseek/fread. It isn't wise to mix the unistd and stdio calls on 182*fae548d3Szrj the same underlying file descriptor. */ 183*fae548d3Szrj file->fd = open (file->name, O_RDONLY | O_BINARY); 184*fae548d3Szrj if (file->fd < 0) 185*fae548d3Szrj return 0; 186*fae548d3Szrj 187*fae548d3Szrj if (iobfd == ibfd) 188*fae548d3Szrj { 189*fae548d3Szrj struct stat stat_buf; 190*fae548d3Szrj 191*fae548d3Szrj if (fstat (file->fd, &stat_buf)) 192*fae548d3Szrj { 193*fae548d3Szrj close(file->fd); 194*fae548d3Szrj return 0; 195*fae548d3Szrj } 196*fae548d3Szrj 197*fae548d3Szrj file->offset = 0; 198*fae548d3Szrj file->filesize = stat_buf.st_size; 199*fae548d3Szrj } 200*fae548d3Szrj else 201*fae548d3Szrj { 202*fae548d3Szrj file->offset = ibfd->origin; 203*fae548d3Szrj file->filesize = arelt_size (ibfd); 204*fae548d3Szrj } 205*fae548d3Szrj return 1; 206*fae548d3Szrj } 207*fae548d3Szrj 208*fae548d3Szrj static int 209*fae548d3Szrj try_claim (bfd *abfd) 210*fae548d3Szrj { 211*fae548d3Szrj int claimed = 0; 212*fae548d3Szrj struct ld_plugin_input_file file; 213*fae548d3Szrj 214*fae548d3Szrj file.handle = abfd; 215*fae548d3Szrj if (!bfd_plugin_open_input (abfd, &file)) 216*fae548d3Szrj return 0; 217*fae548d3Szrj if (claim_file) 218*fae548d3Szrj claim_file (&file, &claimed); 219*fae548d3Szrj close (file.fd); 220*fae548d3Szrj return claimed; 221*fae548d3Szrj } 222*fae548d3Szrj 223*fae548d3Szrj struct plugin_list_entry 224*fae548d3Szrj { 225*fae548d3Szrj void * handle; 226*fae548d3Szrj ld_plugin_claim_file_handler claim_file; 227*fae548d3Szrj struct plugin_list_entry * next; 228*fae548d3Szrj }; 229*fae548d3Szrj 230*fae548d3Szrj static struct plugin_list_entry * plugin_list = NULL; 231*fae548d3Szrj 232*fae548d3Szrj static int 233*fae548d3Szrj try_load_plugin (const char *pname, bfd *abfd, int *has_plugin_p) 234*fae548d3Szrj { 235*fae548d3Szrj void *plugin_handle = NULL; 236*fae548d3Szrj struct ld_plugin_tv tv[4]; 237*fae548d3Szrj int i; 238*fae548d3Szrj ld_plugin_onload onload; 239*fae548d3Szrj enum ld_plugin_status status; 240*fae548d3Szrj struct plugin_list_entry *plugin_list_iter; 241*fae548d3Szrj 242*fae548d3Szrj *has_plugin_p = 0; 243*fae548d3Szrj 244*fae548d3Szrj plugin_handle = dlopen (pname, RTLD_NOW); 245*fae548d3Szrj if (!plugin_handle) 246*fae548d3Szrj { 247*fae548d3Szrj _bfd_error_handler ("%s\n", dlerror ()); 248*fae548d3Szrj return 0; 249*fae548d3Szrj } 250*fae548d3Szrj 251*fae548d3Szrj for (plugin_list_iter = plugin_list; 252*fae548d3Szrj plugin_list_iter; 253*fae548d3Szrj plugin_list_iter = plugin_list_iter->next) 254*fae548d3Szrj { 255*fae548d3Szrj if (plugin_handle == plugin_list_iter->handle) 256*fae548d3Szrj { 257*fae548d3Szrj dlclose (plugin_handle); 258*fae548d3Szrj if (!plugin_list_iter->claim_file) 259*fae548d3Szrj return 0; 260*fae548d3Szrj 261*fae548d3Szrj register_claim_file (plugin_list_iter->claim_file); 262*fae548d3Szrj goto have_claim_file; 263*fae548d3Szrj } 264*fae548d3Szrj } 265*fae548d3Szrj 266*fae548d3Szrj plugin_list_iter = bfd_malloc (sizeof *plugin_list_iter); 267*fae548d3Szrj if (plugin_list_iter == NULL) 268*fae548d3Szrj return 0; 269*fae548d3Szrj plugin_list_iter->handle = plugin_handle; 270*fae548d3Szrj plugin_list_iter->claim_file = NULL; 271*fae548d3Szrj plugin_list_iter->next = plugin_list; 272*fae548d3Szrj plugin_list = plugin_list_iter; 273*fae548d3Szrj 274*fae548d3Szrj onload = dlsym (plugin_handle, "onload"); 275*fae548d3Szrj if (!onload) 276*fae548d3Szrj return 0; 277*fae548d3Szrj 278*fae548d3Szrj i = 0; 279*fae548d3Szrj tv[i].tv_tag = LDPT_MESSAGE; 280*fae548d3Szrj tv[i].tv_u.tv_message = message; 281*fae548d3Szrj 282*fae548d3Szrj ++i; 283*fae548d3Szrj tv[i].tv_tag = LDPT_REGISTER_CLAIM_FILE_HOOK; 284*fae548d3Szrj tv[i].tv_u.tv_register_claim_file = register_claim_file; 285*fae548d3Szrj 286*fae548d3Szrj ++i; 287*fae548d3Szrj tv[i].tv_tag = LDPT_ADD_SYMBOLS; 288*fae548d3Szrj tv[i].tv_u.tv_add_symbols = add_symbols; 289*fae548d3Szrj 290*fae548d3Szrj ++i; 291*fae548d3Szrj tv[i].tv_tag = LDPT_NULL; 292*fae548d3Szrj tv[i].tv_u.tv_val = 0; 293*fae548d3Szrj 294*fae548d3Szrj status = (*onload)(tv); 295*fae548d3Szrj 296*fae548d3Szrj if (status != LDPS_OK) 297*fae548d3Szrj return 0; 298*fae548d3Szrj 299*fae548d3Szrj plugin_list_iter->claim_file = claim_file; 300*fae548d3Szrj 301*fae548d3Szrj have_claim_file: 302*fae548d3Szrj *has_plugin_p = 1; 303*fae548d3Szrj 304*fae548d3Szrj abfd->plugin_format = bfd_plugin_no; 305*fae548d3Szrj 306*fae548d3Szrj if (!claim_file) 307*fae548d3Szrj return 0; 308*fae548d3Szrj 309*fae548d3Szrj if (!try_claim (abfd)) 310*fae548d3Szrj return 0; 311*fae548d3Szrj 312*fae548d3Szrj abfd->plugin_format = bfd_plugin_yes; 313*fae548d3Szrj return 1; 314*fae548d3Szrj } 315*fae548d3Szrj 316*fae548d3Szrj /* There may be plugin libraries in lib/bfd-plugins. */ 317*fae548d3Szrj 318*fae548d3Szrj static int has_plugin = -1; 319*fae548d3Szrj 320*fae548d3Szrj static const bfd_target *(*ld_plugin_object_p) (bfd *); 321*fae548d3Szrj 322*fae548d3Szrj static const char *plugin_name; 323*fae548d3Szrj 324*fae548d3Szrj void 325*fae548d3Szrj bfd_plugin_set_plugin (const char *p) 326*fae548d3Szrj { 327*fae548d3Szrj plugin_name = p; 328*fae548d3Szrj has_plugin = p != NULL; 329*fae548d3Szrj } 330*fae548d3Szrj 331*fae548d3Szrj /* Return TRUE if a plugin library is used. */ 332*fae548d3Szrj 333*fae548d3Szrj bfd_boolean 334*fae548d3Szrj bfd_plugin_specified_p (void) 335*fae548d3Szrj { 336*fae548d3Szrj return has_plugin > 0; 337*fae548d3Szrj } 338*fae548d3Szrj 339*fae548d3Szrj /* Return TRUE if ABFD can be claimed by linker LTO plugin. */ 340*fae548d3Szrj 341*fae548d3Szrj bfd_boolean 342*fae548d3Szrj bfd_link_plugin_object_p (bfd *abfd) 343*fae548d3Szrj { 344*fae548d3Szrj if (ld_plugin_object_p) 345*fae548d3Szrj return ld_plugin_object_p (abfd) != NULL; 346*fae548d3Szrj return FALSE; 347*fae548d3Szrj } 348*fae548d3Szrj 349*fae548d3Szrj extern const bfd_target plugin_vec; 350*fae548d3Szrj 351*fae548d3Szrj /* Return TRUE if TARGET is a pointer to plugin_vec. */ 352*fae548d3Szrj 353*fae548d3Szrj bfd_boolean 354*fae548d3Szrj bfd_plugin_target_p (const bfd_target *target) 355*fae548d3Szrj { 356*fae548d3Szrj return target == &plugin_vec; 357*fae548d3Szrj } 358*fae548d3Szrj 359*fae548d3Szrj /* Register OBJECT_P to be used by bfd_plugin_object_p. */ 360*fae548d3Szrj 361*fae548d3Szrj void 362*fae548d3Szrj register_ld_plugin_object_p (const bfd_target *(*object_p) (bfd *)) 363*fae548d3Szrj { 364*fae548d3Szrj ld_plugin_object_p = object_p; 365*fae548d3Szrj } 366*fae548d3Szrj 367*fae548d3Szrj static int 368*fae548d3Szrj load_plugin (bfd *abfd) 369*fae548d3Szrj { 370*fae548d3Szrj /* The intent was to search ${libdir}/bfd-plugins for plugins, but 371*fae548d3Szrj unfortunately the original implementation wasn't precisely that 372*fae548d3Szrj when configuring binutils using --libdir. Search in the proper 373*fae548d3Szrj path first, then the old one for backwards compatibility. */ 374*fae548d3Szrj static const char *path[] 375*fae548d3Szrj = { LIBDIR "/bfd-plugins", BINDIR "/../lib/bfd-plugins" }; 376*fae548d3Szrj struct stat last_st; 377*fae548d3Szrj int found = 0; 378*fae548d3Szrj unsigned int i; 379*fae548d3Szrj 380*fae548d3Szrj if (!has_plugin) 381*fae548d3Szrj return found; 382*fae548d3Szrj 383*fae548d3Szrj if (plugin_name) 384*fae548d3Szrj return try_load_plugin (plugin_name, abfd, &has_plugin); 385*fae548d3Szrj 386*fae548d3Szrj if (plugin_program_name == NULL) 387*fae548d3Szrj return found; 388*fae548d3Szrj 389*fae548d3Szrj /* Try not to search the same dir twice, by looking at st_dev and 390*fae548d3Szrj st_ino for the dir. If we are on a file system that always sets 391*fae548d3Szrj st_ino to zero or the actual st_ino is zero we might waste some 392*fae548d3Szrj time, but that doesn't matter too much. */ 393*fae548d3Szrj last_st.st_dev = 0; 394*fae548d3Szrj last_st.st_ino = 0; 395*fae548d3Szrj for (i = 0; i < sizeof (path) / sizeof (path[0]); i++) 396*fae548d3Szrj { 397*fae548d3Szrj char *plugin_dir = make_relative_prefix (plugin_program_name, 398*fae548d3Szrj BINDIR, 399*fae548d3Szrj path[i]); 400*fae548d3Szrj if (plugin_dir) 401*fae548d3Szrj { 402*fae548d3Szrj struct stat st; 403*fae548d3Szrj DIR *d; 404*fae548d3Szrj 405*fae548d3Szrj if (stat (plugin_dir, &st) == 0 406*fae548d3Szrj && S_ISDIR (st.st_mode) 407*fae548d3Szrj && !(last_st.st_dev == st.st_dev 408*fae548d3Szrj && last_st.st_ino == st.st_ino 409*fae548d3Szrj && st.st_ino != 0) 410*fae548d3Szrj && (d = opendir (plugin_dir)) != NULL) 411*fae548d3Szrj { 412*fae548d3Szrj struct dirent *ent; 413*fae548d3Szrj 414*fae548d3Szrj last_st.st_dev = st.st_dev; 415*fae548d3Szrj last_st.st_ino = st.st_ino; 416*fae548d3Szrj while ((ent = readdir (d)) != NULL) 417*fae548d3Szrj { 418*fae548d3Szrj char *full_name; 419*fae548d3Szrj 420*fae548d3Szrj full_name = concat (plugin_dir, "/", ent->d_name, NULL); 421*fae548d3Szrj if (stat (full_name, &st) == 0 && S_ISREG (st.st_mode)) 422*fae548d3Szrj { 423*fae548d3Szrj int valid_plugin; 424*fae548d3Szrj 425*fae548d3Szrj found = try_load_plugin (full_name, abfd, &valid_plugin); 426*fae548d3Szrj if (has_plugin <= 0) 427*fae548d3Szrj has_plugin = valid_plugin; 428*fae548d3Szrj } 429*fae548d3Szrj free (full_name); 430*fae548d3Szrj if (found) 431*fae548d3Szrj break; 432*fae548d3Szrj } 433*fae548d3Szrj closedir (d); 434*fae548d3Szrj } 435*fae548d3Szrj free (plugin_dir); 436*fae548d3Szrj } 437*fae548d3Szrj if (found) 438*fae548d3Szrj break; 439*fae548d3Szrj } 440*fae548d3Szrj 441*fae548d3Szrj return found; 442*fae548d3Szrj } 443*fae548d3Szrj 444*fae548d3Szrj 445*fae548d3Szrj static const bfd_target * 446*fae548d3Szrj bfd_plugin_object_p (bfd *abfd) 447*fae548d3Szrj { 448*fae548d3Szrj if (ld_plugin_object_p) 449*fae548d3Szrj return ld_plugin_object_p (abfd); 450*fae548d3Szrj 451*fae548d3Szrj if (abfd->plugin_format == bfd_plugin_unknown && !load_plugin (abfd)) 452*fae548d3Szrj return NULL; 453*fae548d3Szrj 454*fae548d3Szrj return abfd->plugin_format == bfd_plugin_yes ? abfd->xvec : NULL; 455*fae548d3Szrj } 456*fae548d3Szrj 457*fae548d3Szrj /* Copy any private info we understand from the input bfd 458*fae548d3Szrj to the output bfd. */ 459*fae548d3Szrj 460*fae548d3Szrj static bfd_boolean 461*fae548d3Szrj bfd_plugin_bfd_copy_private_bfd_data (bfd *ibfd ATTRIBUTE_UNUSED, 462*fae548d3Szrj bfd *obfd ATTRIBUTE_UNUSED) 463*fae548d3Szrj { 464*fae548d3Szrj BFD_ASSERT (0); 465*fae548d3Szrj return TRUE; 466*fae548d3Szrj } 467*fae548d3Szrj 468*fae548d3Szrj /* Copy any private info we understand from the input section 469*fae548d3Szrj to the output section. */ 470*fae548d3Szrj 471*fae548d3Szrj static bfd_boolean 472*fae548d3Szrj bfd_plugin_bfd_copy_private_section_data (bfd *ibfd ATTRIBUTE_UNUSED, 473*fae548d3Szrj asection *isection ATTRIBUTE_UNUSED, 474*fae548d3Szrj bfd *obfd ATTRIBUTE_UNUSED, 475*fae548d3Szrj asection *osection ATTRIBUTE_UNUSED) 476*fae548d3Szrj { 477*fae548d3Szrj BFD_ASSERT (0); 478*fae548d3Szrj return TRUE; 479*fae548d3Szrj } 480*fae548d3Szrj 481*fae548d3Szrj /* Copy any private info we understand from the input symbol 482*fae548d3Szrj to the output symbol. */ 483*fae548d3Szrj 484*fae548d3Szrj static bfd_boolean 485*fae548d3Szrj bfd_plugin_bfd_copy_private_symbol_data (bfd *ibfd ATTRIBUTE_UNUSED, 486*fae548d3Szrj asymbol *isymbol ATTRIBUTE_UNUSED, 487*fae548d3Szrj bfd *obfd ATTRIBUTE_UNUSED, 488*fae548d3Szrj asymbol *osymbol ATTRIBUTE_UNUSED) 489*fae548d3Szrj { 490*fae548d3Szrj BFD_ASSERT (0); 491*fae548d3Szrj return TRUE; 492*fae548d3Szrj } 493*fae548d3Szrj 494*fae548d3Szrj static bfd_boolean 495*fae548d3Szrj bfd_plugin_bfd_print_private_bfd_data (bfd *abfd ATTRIBUTE_UNUSED, PTR ptr ATTRIBUTE_UNUSED) 496*fae548d3Szrj { 497*fae548d3Szrj BFD_ASSERT (0); 498*fae548d3Szrj return TRUE; 499*fae548d3Szrj } 500*fae548d3Szrj 501*fae548d3Szrj static char * 502*fae548d3Szrj bfd_plugin_core_file_failing_command (bfd *abfd ATTRIBUTE_UNUSED) 503*fae548d3Szrj { 504*fae548d3Szrj BFD_ASSERT (0); 505*fae548d3Szrj return NULL; 506*fae548d3Szrj } 507*fae548d3Szrj 508*fae548d3Szrj static int 509*fae548d3Szrj bfd_plugin_core_file_failing_signal (bfd *abfd ATTRIBUTE_UNUSED) 510*fae548d3Szrj { 511*fae548d3Szrj BFD_ASSERT (0); 512*fae548d3Szrj return 0; 513*fae548d3Szrj } 514*fae548d3Szrj 515*fae548d3Szrj static int 516*fae548d3Szrj bfd_plugin_core_file_pid (bfd *abfd ATTRIBUTE_UNUSED) 517*fae548d3Szrj { 518*fae548d3Szrj BFD_ASSERT (0); 519*fae548d3Szrj return 0; 520*fae548d3Szrj } 521*fae548d3Szrj 522*fae548d3Szrj static long 523*fae548d3Szrj bfd_plugin_get_symtab_upper_bound (bfd *abfd) 524*fae548d3Szrj { 525*fae548d3Szrj struct plugin_data_struct *plugin_data = abfd->tdata.plugin_data; 526*fae548d3Szrj long nsyms = plugin_data->nsyms; 527*fae548d3Szrj 528*fae548d3Szrj BFD_ASSERT (nsyms >= 0); 529*fae548d3Szrj 530*fae548d3Szrj return ((nsyms + 1) * sizeof (asymbol *)); 531*fae548d3Szrj } 532*fae548d3Szrj 533*fae548d3Szrj static flagword 534*fae548d3Szrj convert_flags (const struct ld_plugin_symbol *sym) 535*fae548d3Szrj { 536*fae548d3Szrj switch (sym->def) 537*fae548d3Szrj { 538*fae548d3Szrj case LDPK_DEF: 539*fae548d3Szrj case LDPK_COMMON: 540*fae548d3Szrj case LDPK_UNDEF: 541*fae548d3Szrj return BSF_GLOBAL; 542*fae548d3Szrj 543*fae548d3Szrj case LDPK_WEAKUNDEF: 544*fae548d3Szrj case LDPK_WEAKDEF: 545*fae548d3Szrj return BSF_GLOBAL | BSF_WEAK; 546*fae548d3Szrj 547*fae548d3Szrj default: 548*fae548d3Szrj BFD_ASSERT (0); 549*fae548d3Szrj return 0; 550*fae548d3Szrj } 551*fae548d3Szrj } 552*fae548d3Szrj 553*fae548d3Szrj static long 554*fae548d3Szrj bfd_plugin_canonicalize_symtab (bfd *abfd, 555*fae548d3Szrj asymbol **alocation) 556*fae548d3Szrj { 557*fae548d3Szrj struct plugin_data_struct *plugin_data = abfd->tdata.plugin_data; 558*fae548d3Szrj long nsyms = plugin_data->nsyms; 559*fae548d3Szrj const struct ld_plugin_symbol *syms = plugin_data->syms; 560*fae548d3Szrj static asection fake_section 561*fae548d3Szrj = BFD_FAKE_SECTION (fake_section, NULL, "plug", 0, 562*fae548d3Szrj SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS); 563*fae548d3Szrj static asection fake_common_section 564*fae548d3Szrj = BFD_FAKE_SECTION (fake_common_section, NULL, "plug", 0, SEC_IS_COMMON); 565*fae548d3Szrj int i; 566*fae548d3Szrj 567*fae548d3Szrj for (i = 0; i < nsyms; i++) 568*fae548d3Szrj { 569*fae548d3Szrj asymbol *s = bfd_alloc (abfd, sizeof (asymbol)); 570*fae548d3Szrj 571*fae548d3Szrj BFD_ASSERT (s); 572*fae548d3Szrj alocation[i] = s; 573*fae548d3Szrj 574*fae548d3Szrj s->the_bfd = abfd; 575*fae548d3Szrj s->name = syms[i].name; 576*fae548d3Szrj s->value = 0; 577*fae548d3Szrj s->flags = convert_flags (&syms[i]); 578*fae548d3Szrj switch (syms[i].def) 579*fae548d3Szrj { 580*fae548d3Szrj case LDPK_COMMON: 581*fae548d3Szrj s->section = &fake_common_section; 582*fae548d3Szrj break; 583*fae548d3Szrj case LDPK_UNDEF: 584*fae548d3Szrj case LDPK_WEAKUNDEF: 585*fae548d3Szrj s->section = bfd_und_section_ptr; 586*fae548d3Szrj break; 587*fae548d3Szrj case LDPK_DEF: 588*fae548d3Szrj case LDPK_WEAKDEF: 589*fae548d3Szrj s->section = &fake_section; 590*fae548d3Szrj break; 591*fae548d3Szrj default: 592*fae548d3Szrj BFD_ASSERT (0); 593*fae548d3Szrj } 594*fae548d3Szrj 595*fae548d3Szrj s->udata.p = (void *) &syms[i]; 596*fae548d3Szrj } 597*fae548d3Szrj 598*fae548d3Szrj return nsyms; 599*fae548d3Szrj } 600*fae548d3Szrj 601*fae548d3Szrj static void 602*fae548d3Szrj bfd_plugin_print_symbol (bfd *abfd ATTRIBUTE_UNUSED, 603*fae548d3Szrj PTR afile ATTRIBUTE_UNUSED, 604*fae548d3Szrj asymbol *symbol ATTRIBUTE_UNUSED, 605*fae548d3Szrj bfd_print_symbol_type how ATTRIBUTE_UNUSED) 606*fae548d3Szrj { 607*fae548d3Szrj BFD_ASSERT (0); 608*fae548d3Szrj } 609*fae548d3Szrj 610*fae548d3Szrj static void 611*fae548d3Szrj bfd_plugin_get_symbol_info (bfd *abfd ATTRIBUTE_UNUSED, 612*fae548d3Szrj asymbol *symbol, 613*fae548d3Szrj symbol_info *ret) 614*fae548d3Szrj { 615*fae548d3Szrj bfd_symbol_info (symbol, ret); 616*fae548d3Szrj } 617*fae548d3Szrj 618*fae548d3Szrj /* Make an empty symbol. */ 619*fae548d3Szrj 620*fae548d3Szrj static asymbol * 621*fae548d3Szrj bfd_plugin_make_empty_symbol (bfd *abfd) 622*fae548d3Szrj { 623*fae548d3Szrj asymbol *new_symbol = bfd_zalloc (abfd, sizeof (asymbol)); 624*fae548d3Szrj if (new_symbol == NULL) 625*fae548d3Szrj return new_symbol; 626*fae548d3Szrj new_symbol->the_bfd = abfd; 627*fae548d3Szrj return new_symbol; 628*fae548d3Szrj } 629*fae548d3Szrj 630*fae548d3Szrj static int 631*fae548d3Szrj bfd_plugin_sizeof_headers (bfd *a ATTRIBUTE_UNUSED, 632*fae548d3Szrj struct bfd_link_info *info ATTRIBUTE_UNUSED) 633*fae548d3Szrj { 634*fae548d3Szrj BFD_ASSERT (0); 635*fae548d3Szrj return 0; 636*fae548d3Szrj } 637*fae548d3Szrj 638*fae548d3Szrj const bfd_target plugin_vec = 639*fae548d3Szrj { 640*fae548d3Szrj "plugin", /* Name. */ 641*fae548d3Szrj bfd_target_unknown_flavour, 642*fae548d3Szrj BFD_ENDIAN_LITTLE, /* Target byte order. */ 643*fae548d3Szrj BFD_ENDIAN_LITTLE, /* Target headers byte order. */ 644*fae548d3Szrj (HAS_RELOC | EXEC_P | /* Object flags. */ 645*fae548d3Szrj HAS_LINENO | HAS_DEBUG | 646*fae548d3Szrj HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED), 647*fae548d3Szrj (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS 648*fae548d3Szrj | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* Section flags. */ 649*fae548d3Szrj 0, /* symbol_leading_char. */ 650*fae548d3Szrj '/', /* ar_pad_char. */ 651*fae548d3Szrj 15, /* ar_max_namelen. */ 652*fae548d3Szrj 255, /* match priority. */ 653*fae548d3Szrj 654*fae548d3Szrj bfd_getl64, bfd_getl_signed_64, bfd_putl64, 655*fae548d3Szrj bfd_getl32, bfd_getl_signed_32, bfd_putl32, 656*fae548d3Szrj bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */ 657*fae548d3Szrj bfd_getl64, bfd_getl_signed_64, bfd_putl64, 658*fae548d3Szrj bfd_getl32, bfd_getl_signed_32, bfd_putl32, 659*fae548d3Szrj bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */ 660*fae548d3Szrj 661*fae548d3Szrj { /* bfd_check_format. */ 662*fae548d3Szrj _bfd_dummy_target, 663*fae548d3Szrj bfd_plugin_object_p, 664*fae548d3Szrj bfd_generic_archive_p, 665*fae548d3Szrj _bfd_dummy_target 666*fae548d3Szrj }, 667*fae548d3Szrj { /* bfd_set_format. */ 668*fae548d3Szrj _bfd_bool_bfd_false_error, 669*fae548d3Szrj _bfd_bool_bfd_false_error, 670*fae548d3Szrj _bfd_generic_mkarchive, 671*fae548d3Szrj _bfd_bool_bfd_false_error, 672*fae548d3Szrj }, 673*fae548d3Szrj { /* bfd_write_contents. */ 674*fae548d3Szrj _bfd_bool_bfd_false_error, 675*fae548d3Szrj _bfd_bool_bfd_false_error, 676*fae548d3Szrj _bfd_write_archive_contents, 677*fae548d3Szrj _bfd_bool_bfd_false_error, 678*fae548d3Szrj }, 679*fae548d3Szrj 680*fae548d3Szrj BFD_JUMP_TABLE_GENERIC (bfd_plugin), 681*fae548d3Szrj BFD_JUMP_TABLE_COPY (bfd_plugin), 682*fae548d3Szrj BFD_JUMP_TABLE_CORE (bfd_plugin), 683*fae548d3Szrj #ifdef USE_64_BIT_ARCHIVE 684*fae548d3Szrj BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_64_bit), 685*fae548d3Szrj #else 686*fae548d3Szrj BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff), 687*fae548d3Szrj #endif 688*fae548d3Szrj BFD_JUMP_TABLE_SYMBOLS (bfd_plugin), 689*fae548d3Szrj BFD_JUMP_TABLE_RELOCS (_bfd_norelocs), 690*fae548d3Szrj BFD_JUMP_TABLE_WRITE (bfd_plugin), 691*fae548d3Szrj BFD_JUMP_TABLE_LINK (bfd_plugin), 692*fae548d3Szrj BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), 693*fae548d3Szrj 694*fae548d3Szrj NULL, 695*fae548d3Szrj 696*fae548d3Szrj NULL /* backend_data. */ 697*fae548d3Szrj }; 698*fae548d3Szrj #endif /* BFD_SUPPORTS_PLUGIN */ 699