lto-plugin.c revision 1.1.1.1
1/* LTO plugin for gold. 2 Copyright (C) 2009 Free Software Foundation, Inc. 3 Contributed by Rafael Avila de Espindola (espindola@google.com). 4 5This program is free software; you can redistribute it and/or modify 6it under the terms of the GNU General Public License as published by 7the Free Software Foundation; either version 3, or (at your option) 8any later version. 9 10This program is distributed in the hope that it will be useful, but 11WITHOUT ANY WARRANTY; without even the implied warranty of 12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13General Public License for more details. 14 15You should have received a copy of the GNU General Public License 16along with this program; see the file COPYING3. If not see 17<http://www.gnu.org/licenses/>. */ 18 19/* The plugin has only one external function: onload. Gold passes it an array of 20 function that the plugin uses to communicate back to gold. 21 22 With the functions provided by gold, the plugin can be notified when 23 gold first analyzes a file and pass a symbol table back to gold. The plugin 24 is also notified when all symbols have been read and it is time to generate 25 machine code for the necessary symbols. 26 27 More information at http://gcc.gnu.org/wiki/whopr/driver. 28 29 This plugin should be passed the lto-wrapper options and will forward them. 30 It also has 2 options of its own: 31 -debug: Print the command line used to run lto-wrapper. 32 -nop: Instead of running lto-wrapper, pass the original to the plugin. This 33 only works if the input files are hybrid. */ 34 35#include <assert.h> 36#include <string.h> 37#include <stdlib.h> 38#include <stdio.h> 39#include <inttypes.h> 40#include <sys/stat.h> 41#include <unistd.h> 42#include <fcntl.h> 43#include <sys/types.h> 44#include <sys/wait.h> 45#include <stdbool.h> 46#include <libiberty.h> 47 48/* The presence of gelf.h is checked by the toplevel configure script. */ 49#include <gelf.h> 50 51#include "plugin-api.h" 52#include "../gcc/lto/common.h" 53 54/* The part of the symbol table the plugin has to keep track of. Note that we 55 must keep SYMS until all_symbols_read is called to give the linker time to 56 copy the symbol information. */ 57 58struct plugin_symtab 59{ 60 int nsyms; 61 uint32_t *slots; 62 struct ld_plugin_symbol *syms; 63}; 64 65/* All that we have to remember about a file. */ 66 67struct plugin_file_info 68{ 69 char *name; 70 void *handle; 71 struct plugin_symtab symtab; 72}; 73 74 75static char *arguments_file_name; 76static ld_plugin_register_claim_file register_claim_file; 77static ld_plugin_add_symbols add_symbols; 78static ld_plugin_register_all_symbols_read register_all_symbols_read; 79static ld_plugin_get_symbols get_symbols; 80static ld_plugin_register_cleanup register_cleanup; 81static ld_plugin_add_input_file add_input_file; 82static ld_plugin_add_input_library add_input_library; 83static ld_plugin_message message; 84 85static struct plugin_file_info *claimed_files = NULL; 86static unsigned int num_claimed_files = 0; 87 88static char **output_files = NULL; 89static unsigned int num_output_files = 0; 90 91static char **lto_wrapper_argv; 92static int lto_wrapper_num_args; 93 94static char **pass_through_items = NULL; 95static unsigned int num_pass_through_items; 96 97static bool debug; 98static bool nop; 99static char *resolution_file = NULL; 100 101static void 102check (bool gate, enum ld_plugin_level level, const char *text) 103{ 104 if (gate) 105 return; 106 107 if (message) 108 message (level, text); 109 else 110 { 111 /* If there is no nicer way to inform the user, fallback to stderr. */ 112 fprintf (stderr, "%s\n", text); 113 if (level == LDPL_FATAL) 114 abort (); 115 } 116} 117 118/* Parse an entry of the IL symbol table. The data to be parsed is pointed 119 by P and the result is written in ENTRY. The slot number is stored in SLOT. 120 Returns the address of the next entry. */ 121 122static char * 123parse_table_entry (char *p, struct ld_plugin_symbol *entry, uint32_t *slot) 124{ 125 unsigned char t; 126 enum ld_plugin_symbol_kind translate_kind[] = 127 { 128 LDPK_DEF, 129 LDPK_WEAKDEF, 130 LDPK_UNDEF, 131 LDPK_WEAKUNDEF, 132 LDPK_COMMON 133 }; 134 135 enum ld_plugin_symbol_visibility translate_visibility[] = 136 { 137 LDPV_DEFAULT, 138 LDPV_PROTECTED, 139 LDPV_INTERNAL, 140 LDPV_HIDDEN 141 }; 142 143 entry->name = strdup (p); 144 while (*p) 145 p++; 146 p++; 147 148 entry->version = NULL; 149 150 entry->comdat_key = p; 151 while (*p) 152 p++; 153 p++; 154 155 if (strlen (entry->comdat_key) == 0) 156 entry->comdat_key = NULL; 157 else 158 entry->comdat_key = strdup (entry->comdat_key); 159 160 t = *p; 161 check (t <= 4, LDPL_FATAL, "invalid symbol kind found"); 162 entry->def = translate_kind[t]; 163 p++; 164 165 t = *p; 166 check (t <= 3, LDPL_FATAL, "invalid symbol visibility found"); 167 entry->visibility = translate_visibility[t]; 168 p++; 169 170 entry->size = *(uint64_t *) p; 171 p += 8; 172 173 *slot = *(uint32_t *) p; 174 p += 4; 175 176 entry->resolution = LDPR_UNKNOWN; 177 178 return p; 179} 180 181/* Return the section in ELF that is named NAME. */ 182 183static Elf_Scn * 184get_section (Elf *elf, const char *name) 185{ 186 Elf_Scn *section = 0; 187 GElf_Ehdr header; 188 GElf_Ehdr *t = gelf_getehdr (elf, &header); 189 if (t == NULL) 190 return NULL; 191 assert (t == &header); 192 193 while ((section = elf_nextscn(elf, section)) != 0) 194 { 195 GElf_Shdr shdr; 196 GElf_Shdr *tshdr = gelf_getshdr (section, &shdr); 197 const char *t; 198 assert (tshdr == &shdr); 199 t = elf_strptr (elf, header.e_shstrndx, shdr.sh_name); 200 assert (t != NULL); 201 if (strcmp (t, name) == 0) 202 return section; 203 } 204 return NULL; 205} 206 207/* Returns the IL symbol table of file ELF. */ 208 209static Elf_Data * 210get_symtab (Elf *elf) 211{ 212 Elf_Data *data = 0; 213 Elf_Scn *section = get_section (elf, ".gnu.lto_.symtab"); 214 if (!section) 215 return NULL; 216 217 data = elf_getdata (section, data); 218 assert (data); 219 return data; 220} 221 222/* Translate the IL symbol table SYMTAB. Write the slots and symbols in OUT. */ 223 224static void 225translate (Elf_Data *symtab, struct plugin_symtab *out) 226{ 227 uint32_t *slots = NULL; 228 char *data = symtab->d_buf; 229 char *end = data + symtab->d_size; 230 struct ld_plugin_symbol *syms = NULL; 231 int n = 0; 232 233 while (data < end) 234 { 235 n++; 236 syms = realloc (syms, n * sizeof (struct ld_plugin_symbol)); 237 check (syms, LDPL_FATAL, "could not allocate memory"); 238 slots = realloc (slots, n * sizeof (uint32_t)); 239 check (slots, LDPL_FATAL, "could not allocate memory"); 240 data = parse_table_entry (data, &syms[n - 1], &slots[n - 1]); 241 } 242 243 out->nsyms = n; 244 out->syms = syms; 245 out->slots = slots; 246} 247 248/* Free all memory that is no longer needed after writing the symbol 249 resolution. */ 250 251static void 252free_1 (void) 253{ 254 unsigned int i; 255 for (i = 0; i < num_claimed_files; i++) 256 { 257 struct plugin_file_info *info = &claimed_files[i]; 258 struct plugin_symtab *symtab = &info->symtab; 259 unsigned int j; 260 for (j = 0; j < symtab->nsyms; j++) 261 { 262 struct ld_plugin_symbol *s = &symtab->syms[j]; 263 free (s->name); 264 if (s->comdat_key) 265 free (s->comdat_key); 266 } 267 free (symtab->syms); 268 symtab->syms = NULL; 269 } 270} 271 272/* Free all remaining memory. */ 273 274static void 275free_2 (void) 276{ 277 unsigned int i; 278 for (i = 0; i < num_claimed_files; i++) 279 { 280 struct plugin_file_info *info = &claimed_files[i]; 281 struct plugin_symtab *symtab = &info->symtab; 282 free (symtab->slots); 283 free (info->name); 284 } 285 286 for (i = 0; i < num_output_files; i++) 287 free (output_files[i]); 288 free (output_files); 289 290 free (claimed_files); 291 claimed_files = NULL; 292 num_claimed_files = 0; 293 294 if (arguments_file_name) 295 free (arguments_file_name); 296 arguments_file_name = NULL; 297 298 if (resolution_file) 299 { 300 free (resolution_file); 301 resolution_file = NULL; 302 } 303} 304 305/* Writes the relocations to disk. */ 306 307static void 308write_resolution (void) 309{ 310 unsigned int i; 311 FILE *f; 312 313 f = fopen (resolution_file, "w"); 314 check (f, LDPL_FATAL, "could not open file"); 315 316 fprintf (f, "%d\n", num_claimed_files); 317 318 for (i = 0; i < num_claimed_files; i++) 319 { 320 struct plugin_file_info *info = &claimed_files[i]; 321 struct plugin_symtab *symtab = &info->symtab; 322 struct ld_plugin_symbol *syms = symtab->syms; 323 unsigned j; 324 325 get_symbols (info->handle, symtab->nsyms, syms); 326 327 fprintf (f, "%s %d\n", info->name, info->symtab.nsyms); 328 329 for (j = 0; j < info->symtab.nsyms; j++) 330 { 331 uint32_t slot = symtab->slots[j]; 332 unsigned int resolution = syms[j].resolution; 333 fprintf (f, "%d %s %s\n", slot, lto_resolution_str[resolution], syms[j].name); 334 } 335 } 336 fclose (f); 337} 338 339/* Pass files generated by the lto-wrapper to the linker. FD is lto-wrapper's 340 stdout. */ 341 342static void 343add_output_files (FILE *f) 344{ 345 char fname[1000]; /* FIXME: Remove this restriction. */ 346 347 for (;;) 348 { 349 size_t len; 350 char *s = fgets (fname, sizeof (fname), f); 351 if (!s) 352 break; 353 354 len = strlen (s); 355 check (s[len - 1] == '\n', LDPL_FATAL, "file name too long"); 356 s[len - 1] = '\0'; 357 358 num_output_files++; 359 output_files = realloc (output_files, num_output_files * sizeof (char *)); 360 output_files[num_output_files - 1] = strdup (s); 361 add_input_file (output_files[num_output_files - 1]); 362 } 363} 364 365/* Execute the lto-wrapper. ARGV[0] is the binary. The rest of ARGV is the 366 argument list. */ 367 368static void 369exec_lto_wrapper (char *argv[]) 370{ 371 int t, i; 372 int status; 373 char *at_args; 374 FILE *args; 375 FILE *wrapper_output; 376 char *new_argv[3]; 377 struct pex_obj *pex; 378 const char *errmsg; 379 380 /* Write argv to a file to avoid a command line that is too long. */ 381 arguments_file_name = make_temp_file (""); 382 check (arguments_file_name, LDPL_FATAL, 383 "Failed to generate a temorary file name"); 384 385 args = fopen (arguments_file_name, "w"); 386 check (args, LDPL_FATAL, "could not open arguments file"); 387 388 t = writeargv (&argv[1], args); 389 check (t == 0, LDPL_FATAL, "could not write arguments"); 390 t = fclose (args); 391 check (t == 0, LDPL_FATAL, "could not close arguments file"); 392 393 at_args = concat ("@", arguments_file_name, NULL); 394 check (at_args, LDPL_FATAL, "could not allocate"); 395 396 for (i = 1; argv[i]; i++) 397 { 398 char *a = argv[i]; 399 if (a[0] == '-' && a[1] == 'v' && a[2] == '\0') 400 { 401 for (i = 0; argv[i]; i++) 402 fprintf (stderr, "%s ", argv[i]); 403 fprintf (stderr, "\n"); 404 break; 405 } 406 } 407 408 new_argv[0] = argv[0]; 409 new_argv[1] = at_args; 410 new_argv[2] = NULL; 411 412 if (debug) 413 { 414 for (i = 0; new_argv[i]; i++) 415 fprintf (stderr, "%s ", new_argv[i]); 416 fprintf (stderr, "\n"); 417 } 418 419 420 pex = pex_init (PEX_USE_PIPES, "lto-wrapper", NULL); 421 check (pex != NULL, LDPL_FATAL, "could not pex_init lto-wrapper"); 422 423 errmsg = pex_run (pex, 0, new_argv[0], new_argv, NULL, NULL, &t); 424 check (errmsg == NULL, LDPL_FATAL, "could not run lto-wrapper"); 425 check (t == 0, LDPL_FATAL, "could not run lto-wrapper"); 426 427 wrapper_output = pex_read_output (pex, 0); 428 check (wrapper_output, LDPL_FATAL, "could not read lto-wrapper output"); 429 430 add_output_files (wrapper_output); 431 432 t = pex_get_status (pex, 1, &status); 433 check (t == 1, LDPL_FATAL, "could not get lto-wrapper exit status"); 434 check (WIFEXITED (status) && WEXITSTATUS (status) == 0, LDPL_FATAL, 435 "lto-wrapper failed"); 436 437 pex_free (pex); 438 439 free (at_args); 440} 441 442/* Pass the original files back to the linker. */ 443 444static void 445use_original_files (void) 446{ 447 unsigned i; 448 for (i = 0; i < num_claimed_files; i++) 449 { 450 struct plugin_file_info *info = &claimed_files[i]; 451 add_input_file (info->name); 452 } 453} 454 455 456/* Called by the linker once all symbols have been read. */ 457 458static enum ld_plugin_status 459all_symbols_read_handler (void) 460{ 461 unsigned i; 462 unsigned num_lto_args = num_claimed_files + lto_wrapper_num_args + 2 + 1; 463 char **lto_argv; 464 const char **lto_arg_ptr; 465 if (num_claimed_files == 0) 466 return LDPS_OK; 467 468 if (nop) 469 { 470 use_original_files (); 471 return LDPS_OK; 472 } 473 474 lto_argv = (char **) calloc (sizeof (char *), num_lto_args); 475 lto_arg_ptr = (const char **) lto_argv; 476 assert (lto_wrapper_argv); 477 478 resolution_file = make_temp_file (""); 479 480 write_resolution (); 481 482 free_1 (); 483 484 for (i = 0; i < lto_wrapper_num_args; i++) 485 *lto_arg_ptr++ = lto_wrapper_argv[i]; 486 487 *lto_arg_ptr++ = "-fresolution"; 488 *lto_arg_ptr++ = resolution_file; 489 490 for (i = 0; i < num_claimed_files; i++) 491 { 492 struct plugin_file_info *info = &claimed_files[i]; 493 494 *lto_arg_ptr++ = info->name; 495 } 496 497 *lto_arg_ptr++ = NULL; 498 exec_lto_wrapper (lto_argv); 499 500 free (lto_argv); 501 502 if (pass_through_items) 503 { 504 unsigned int i; 505 for (i = 0; i < num_pass_through_items; i++) 506 { 507 if (strncmp (pass_through_items[i], "-l", 2) == 0) 508 add_input_library (pass_through_items[i] + 2); 509 else 510 add_input_file (pass_through_items[i]); 511 free (pass_through_items[i]); 512 pass_through_items[i] = NULL; 513 } 514 free (pass_through_items); 515 pass_through_items = NULL; 516 } 517 518 return LDPS_OK; 519} 520 521/* Remove temporary files at the end of the link. */ 522 523static enum ld_plugin_status 524cleanup_handler (void) 525{ 526 unsigned int i; 527 int t; 528 529 if (debug) 530 return LDPS_OK; 531 532 if (arguments_file_name) 533 { 534 t = unlink (arguments_file_name); 535 check (t == 0, LDPL_FATAL, "could not unlink arguments file"); 536 } 537 538 if (resolution_file) 539 { 540 t = unlink (resolution_file); 541 check (t == 0, LDPL_FATAL, "could not unlink resolution file"); 542 } 543 544 for (i = 0; i < num_output_files; i++) 545 { 546 t = unlink (output_files[i]); 547 check (t == 0, LDPL_FATAL, "could not unlink output file"); 548 } 549 550 free_2 (); 551 return LDPS_OK; 552} 553 554/* Callback used by gold to check if the plugin will claim FILE. Writes 555 the result in CLAIMED. */ 556 557static enum ld_plugin_status 558claim_file_handler (const struct ld_plugin_input_file *file, int *claimed) 559{ 560 enum ld_plugin_status status; 561 Elf *elf; 562 struct plugin_file_info lto_file; 563 Elf_Data *symtab; 564 565 if (file->offset != 0) 566 { 567 char *objname; 568 Elf *archive; 569 off_t offset; 570 /* We pass the offset of the actual file, not the archive header. */ 571 int t = asprintf (&objname, "%s@0x%" PRIx64, file->name, 572 (int64_t) file->offset); 573 check (t >= 0, LDPL_FATAL, "asprintf failed"); 574 lto_file.name = objname; 575 576 archive = elf_begin (file->fd, ELF_C_READ, NULL); 577 check (elf_kind (archive) == ELF_K_AR, LDPL_FATAL, 578 "Not an archive and offset not 0"); 579 580 /* elf_rand expects the offset to point to the ar header, not the 581 object itself. Subtract the size of the ar header (60 bytes). 582 We don't uses sizeof (struct ar_hd) to avoid including ar.h */ 583 584 offset = file->offset - 60; 585 check (offset == elf_rand (archive, offset), LDPL_FATAL, 586 "could not seek in archive"); 587 elf = elf_begin (file->fd, ELF_C_READ, archive); 588 check (elf != NULL, LDPL_FATAL, "could not find archive member"); 589 elf_end (archive); 590 } 591 else 592 { 593 lto_file.name = strdup (file->name); 594 elf = elf_begin (file->fd, ELF_C_READ, NULL); 595 } 596 lto_file.handle = file->handle; 597 598 *claimed = 0; 599 600 if (!elf) 601 goto err; 602 603 symtab = get_symtab (elf); 604 if (!symtab) 605 goto err; 606 607 translate (symtab, <o_file.symtab); 608 609 status = add_symbols (file->handle, lto_file.symtab.nsyms, 610 lto_file.symtab.syms); 611 check (status == LDPS_OK, LDPL_FATAL, "could not add symbols"); 612 613 *claimed = 1; 614 num_claimed_files++; 615 claimed_files = 616 realloc (claimed_files, 617 num_claimed_files * sizeof (struct plugin_file_info)); 618 claimed_files[num_claimed_files - 1] = lto_file; 619 620 goto cleanup; 621 622 err: 623 free (lto_file.name); 624 625 cleanup: 626 if (elf) 627 elf_end (elf); 628 629 return LDPS_OK; 630} 631 632/* Parse the plugin options. */ 633 634static void 635process_option (const char *option) 636{ 637 if (strcmp (option, "-debug") == 0) 638 debug = 1; 639 else if (strcmp (option, "-nop") == 0) 640 nop = 1; 641 else if (!strncmp (option, "-pass-through=", strlen("-pass-through="))) 642 { 643 num_pass_through_items++; 644 pass_through_items = realloc (pass_through_items, 645 num_pass_through_items * sizeof (char *)); 646 pass_through_items[num_pass_through_items - 1] = 647 strdup (option + strlen ("-pass-through=")); 648 } 649 else 650 { 651 int size; 652 lto_wrapper_num_args += 1; 653 size = lto_wrapper_num_args * sizeof (char *); 654 lto_wrapper_argv = (char **) realloc (lto_wrapper_argv, size); 655 lto_wrapper_argv[lto_wrapper_num_args - 1] = strdup(option); 656 } 657} 658 659/* Called by gold after loading the plugin. TV is the transfer vector. */ 660 661enum ld_plugin_status 662onload (struct ld_plugin_tv *tv) 663{ 664 struct ld_plugin_tv *p; 665 enum ld_plugin_status status; 666 667 unsigned version = elf_version (EV_CURRENT); 668 check (version != EV_NONE, LDPL_FATAL, "invalid ELF version"); 669 670 p = tv; 671 while (p->tv_tag) 672 { 673 switch (p->tv_tag) 674 { 675 case LDPT_MESSAGE: 676 message = p->tv_u.tv_message; 677 break; 678 case LDPT_REGISTER_CLAIM_FILE_HOOK: 679 register_claim_file = p->tv_u.tv_register_claim_file; 680 break; 681 case LDPT_ADD_SYMBOLS: 682 add_symbols = p->tv_u.tv_add_symbols; 683 break; 684 case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK: 685 register_all_symbols_read = p->tv_u.tv_register_all_symbols_read; 686 break; 687 case LDPT_GET_SYMBOLS: 688 get_symbols = p->tv_u.tv_get_symbols; 689 break; 690 case LDPT_REGISTER_CLEANUP_HOOK: 691 register_cleanup = p->tv_u.tv_register_cleanup; 692 break; 693 case LDPT_ADD_INPUT_FILE: 694 add_input_file = p->tv_u.tv_add_input_file; 695 break; 696 case LDPT_ADD_INPUT_LIBRARY: 697 add_input_library = p->tv_u.tv_add_input_library; 698 break; 699 case LDPT_OPTION: 700 process_option (p->tv_u.tv_string); 701 break; 702 default: 703 break; 704 } 705 p++; 706 } 707 708 check (register_claim_file, LDPL_FATAL, "register_claim_file not found"); 709 check (add_symbols, LDPL_FATAL, "add_symbols not found"); 710 status = register_claim_file (claim_file_handler); 711 check (status == LDPS_OK, LDPL_FATAL, 712 "could not register the claim_file callback"); 713 714 if (register_cleanup) 715 { 716 status = register_cleanup (cleanup_handler); 717 check (status == LDPS_OK, LDPL_FATAL, 718 "could not register the cleanup callback"); 719 } 720 721 if (register_all_symbols_read) 722 { 723 check (get_symbols, LDPL_FATAL, "get_symbols not found"); 724 status = register_all_symbols_read (all_symbols_read_handler); 725 check (status == LDPS_OK, LDPL_FATAL, 726 "could not register the all_symbols_read callback"); 727 } 728 729 return LDPS_OK; 730} 731