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