1 // readsyms.cc -- read input file symbols for gold 2 3 // Copyright (C) 2006-2014 Free Software Foundation, Inc. 4 // Written by Ian Lance Taylor <iant (at) google.com>. 5 6 // This file is part of gold. 7 8 // This program is free software; you can redistribute it and/or modify 9 // it under the terms of the GNU General Public License as published by 10 // the Free Software Foundation; either version 3 of the License, or 11 // (at your option) any later version. 12 13 // This program is distributed in the hope that it will be useful, 14 // but WITHOUT ANY WARRANTY; without even the implied warranty of 15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 // GNU General Public License for more details. 17 18 // You should have received a copy of the GNU General Public License 19 // along with this program; if not, write to the Free Software 20 // Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 21 // MA 02110-1301, USA. 22 23 #include "gold.h" 24 25 #include <cstring> 26 27 #include "elfcpp.h" 28 #include "options.h" 29 #include "dirsearch.h" 30 #include "symtab.h" 31 #include "object.h" 32 #include "archive.h" 33 #include "script.h" 34 #include "readsyms.h" 35 #include "plugin.h" 36 #include "layout.h" 37 #include "incremental.h" 38 39 namespace gold 40 { 41 42 // If we fail to open the object, then we won't create an Add_symbols 43 // task. However, we still need to unblock the token, or else the 44 // link won't proceed to generate more error messages. We can only 45 // unblock tokens when the workqueue lock is held, so we need a dummy 46 // task to do that. The dummy task has to maintain the right sequence 47 // of blocks, so we need both this_blocker and next_blocker. 48 49 class Unblock_token : public Task 50 { 51 public: 52 Unblock_token(Task_token* this_blocker, Task_token* next_blocker) 53 : this_blocker_(this_blocker), next_blocker_(next_blocker) 54 { } 55 56 ~Unblock_token() 57 { 58 if (this->this_blocker_ != NULL) 59 delete this->this_blocker_; 60 } 61 62 Task_token* 63 is_runnable() 64 { 65 if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked()) 66 return this->this_blocker_; 67 return NULL; 68 } 69 70 void 71 locks(Task_locker* tl) 72 { tl->add(this, this->next_blocker_); } 73 74 void 75 run(Workqueue*) 76 { } 77 78 std::string 79 get_name() const 80 { return "Unblock_token"; } 81 82 private: 83 Task_token* this_blocker_; 84 Task_token* next_blocker_; 85 }; 86 87 // Class read_symbols. 88 89 Read_symbols::~Read_symbols() 90 { 91 // The this_blocker_ and next_blocker_ pointers are passed on to the 92 // Add_symbols task. 93 } 94 95 // If appropriate, issue a warning about skipping an incompatible 96 // file. 97 98 void 99 Read_symbols::incompatible_warning(const Input_argument* input_argument, 100 const Input_file* input_file) 101 { 102 if (parameters->options().warn_search_mismatch()) 103 gold_warning("skipping incompatible %s while searching for %s", 104 input_file->filename().c_str(), 105 input_argument->file().name()); 106 } 107 108 // Requeue a Read_symbols task to search for the next object with the 109 // same name. 110 111 void 112 Read_symbols::requeue(Workqueue* workqueue, Input_objects* input_objects, 113 Symbol_table* symtab, Layout* layout, Dirsearch* dirpath, 114 int dirindex, Mapfile* mapfile, 115 const Input_argument* input_argument, 116 Input_group* input_group, Task_token* next_blocker) 117 { 118 // Bump the directory search index. 119 ++dirindex; 120 121 // We don't need to worry about this_blocker, since we already 122 // reached it. However, we are removing the blocker on next_blocker 123 // because the calling task is completing. So we need to add a new 124 // blocker. Since next_blocker may be shared by several tasks, we 125 // need to increment the count with the workqueue lock held. 126 workqueue->add_blocker(next_blocker); 127 128 workqueue->queue(new Read_symbols(input_objects, symtab, layout, dirpath, 129 dirindex, mapfile, input_argument, 130 input_group, NULL, NULL, next_blocker)); 131 } 132 133 // Return whether a Read_symbols task is runnable. We can read an 134 // ordinary input file immediately. For an archive specified using 135 // -l, we have to wait until the search path is complete. 136 137 Task_token* 138 Read_symbols::is_runnable() 139 { 140 if (this->input_argument_->is_file() 141 && this->input_argument_->file().may_need_search() 142 && this->dirpath_->token()->is_blocked()) 143 return this->dirpath_->token(); 144 145 return NULL; 146 } 147 148 // Return a Task_locker for a Read_symbols task. We don't need any 149 // locks here. 150 151 void 152 Read_symbols::locks(Task_locker* tl) 153 { 154 if (this->member_ != NULL) 155 tl->add(this, this->next_blocker_); 156 } 157 158 // Run a Read_symbols task. 159 160 void 161 Read_symbols::run(Workqueue* workqueue) 162 { 163 // If we didn't queue a new task, then we need to explicitly unblock 164 // the token. If the object is a member of a lib group, however, 165 // the token was already added to the list of locks for the task, 166 // and it will be unblocked automatically at the end of the task. 167 if (!this->do_read_symbols(workqueue) && this->member_ == NULL) 168 workqueue->queue_soon(new Unblock_token(this->this_blocker_, 169 this->next_blocker_)); 170 } 171 172 // Handle a whole lib group. Other than collecting statistics, this just 173 // mimics what we do for regular object files in the command line. 174 175 bool 176 Read_symbols::do_whole_lib_group(Workqueue* workqueue) 177 { 178 const Input_file_lib* lib_group = this->input_argument_->lib(); 179 180 ++Lib_group::total_lib_groups; 181 182 Task_token* this_blocker = this->this_blocker_; 183 for (Input_file_lib::const_iterator i = lib_group->begin(); 184 i != lib_group->end(); 185 ++i) 186 { 187 ++Lib_group::total_members; 188 ++Lib_group::total_members_loaded; 189 190 const Input_argument* arg = &*i; 191 192 Task_token* next_blocker; 193 if (i != lib_group->end() - 1) 194 { 195 next_blocker = new Task_token(true); 196 next_blocker->add_blocker(); 197 } 198 else 199 next_blocker = this->next_blocker_; 200 201 workqueue->queue_soon(new Read_symbols(this->input_objects_, 202 this->symtab_, this->layout_, 203 this->dirpath_, this->dirindex_, 204 this->mapfile_, arg, NULL, 205 NULL, this_blocker, next_blocker)); 206 this_blocker = next_blocker; 207 } 208 209 return true; 210 } 211 212 // Handle a lib group. We set Read_symbols Tasks as usual, but have them 213 // just record the symbol data instead of adding the objects. We also start 214 // a Add_lib_group_symbols Task which runs after we've read all the symbols. 215 // In that task we process the members in a loop until we are done. 216 217 bool 218 Read_symbols::do_lib_group(Workqueue* workqueue) 219 { 220 const Input_file_lib* lib_group = this->input_argument_->lib(); 221 222 if (lib_group->options().whole_archive()) 223 return this->do_whole_lib_group(workqueue); 224 225 Lib_group* lib = new Lib_group(lib_group, this); 226 227 Add_lib_group_symbols* add_lib_group_symbols = 228 new Add_lib_group_symbols(this->symtab_, this->layout_, 229 this->input_objects_, 230 lib, this->next_blocker_); 231 232 233 Task_token* next_blocker = new Task_token(true); 234 int j = 0; 235 for (Input_file_lib::const_iterator i = lib_group->begin(); 236 i != lib_group->end(); 237 ++i, ++j) 238 { 239 const Input_argument* arg = &*i; 240 Archive_member* m = lib->get_member(j); 241 242 next_blocker->add_blocker(); 243 244 // Since this Read_symbols will not create an Add_symbols, 245 // just pass NULL as this_blocker. 246 workqueue->queue_soon(new Read_symbols(this->input_objects_, 247 this->symtab_, this->layout_, 248 this->dirpath_, this->dirindex_, 249 this->mapfile_, arg, NULL, 250 m, NULL, next_blocker)); 251 } 252 253 add_lib_group_symbols->set_blocker(next_blocker, this->this_blocker_); 254 workqueue->queue_soon(add_lib_group_symbols); 255 256 return true; 257 } 258 259 // Open the file and read the symbols. Return true if a new task was 260 // queued, false if that could not happen due to some error. 261 262 bool 263 Read_symbols::do_read_symbols(Workqueue* workqueue) 264 { 265 if (this->input_argument_->is_group()) 266 { 267 gold_assert(this->input_group_ == NULL); 268 this->do_group(workqueue); 269 return true; 270 } 271 272 if (this->input_argument_->is_lib()) 273 return this->do_lib_group(workqueue); 274 275 Input_file* input_file = new Input_file(&this->input_argument_->file()); 276 if (!input_file->open(*this->dirpath_, this, &this->dirindex_)) 277 return false; 278 279 // Read enough of the file to pick up the entire ELF header. 280 281 off_t filesize = input_file->file().filesize(); 282 283 if (filesize == 0) 284 { 285 gold_error(_("%s: file is empty"), 286 input_file->file().filename().c_str()); 287 return false; 288 } 289 290 const unsigned char* ehdr; 291 int read_size; 292 bool is_elf = is_elf_object(input_file, 0, &ehdr, &read_size); 293 294 if (read_size >= Archive::sarmag) 295 { 296 bool is_thin_archive 297 = memcmp(ehdr, Archive::armagt, Archive::sarmag) == 0; 298 if (is_thin_archive 299 || memcmp(ehdr, Archive::armag, Archive::sarmag) == 0) 300 { 301 // This is an archive. 302 Archive* arch = new Archive(this->input_argument_->file().name(), 303 input_file, is_thin_archive, 304 this->dirpath_, this); 305 arch->setup(); 306 307 // Unlock the archive so it can be used in the next task. 308 arch->unlock(this); 309 310 workqueue->queue_next(new Add_archive_symbols(this->symtab_, 311 this->layout_, 312 this->input_objects_, 313 this->dirpath_, 314 this->dirindex_, 315 this->mapfile_, 316 this->input_argument_, 317 arch, 318 this->input_group_, 319 this->this_blocker_, 320 this->next_blocker_)); 321 return true; 322 } 323 } 324 325 Object* elf_obj = NULL; 326 bool unconfigured; 327 bool* punconfigured = NULL; 328 if (is_elf) 329 { 330 // This is an ELF object. 331 332 unconfigured = false; 333 punconfigured = (input_file->will_search_for() 334 ? &unconfigured 335 : NULL); 336 elf_obj = make_elf_object(input_file->filename(), 337 input_file, 0, ehdr, read_size, 338 punconfigured); 339 } 340 341 if (parameters->options().has_plugins()) 342 { 343 Pluginobj* obj = parameters->options().plugins()->claim_file(input_file, 344 0, filesize, 345 elf_obj); 346 if (obj != NULL) 347 { 348 // Delete the elf_obj, this file has been claimed. 349 if (elf_obj != NULL) 350 delete elf_obj; 351 352 // The input file was claimed by a plugin, and its symbols 353 // have been provided by the plugin. 354 355 // We are done with the file at this point, so unlock it. 356 obj->unlock(this); 357 358 if (this->member_ != NULL) 359 { 360 this->member_->sd_ = NULL; 361 this->member_->obj_ = obj; 362 return true; 363 } 364 365 workqueue->queue_next(new Add_symbols(this->input_objects_, 366 this->symtab_, 367 this->layout_, 368 this->dirpath_, 369 this->dirindex_, 370 this->mapfile_, 371 this->input_argument_, 372 obj, 373 NULL, 374 NULL, 375 this->this_blocker_, 376 this->next_blocker_)); 377 return true; 378 } 379 } 380 381 if (is_elf) 382 { 383 // This is an ELF object. 384 385 if (elf_obj == NULL) 386 { 387 if (unconfigured) 388 { 389 Read_symbols::incompatible_warning(this->input_argument_, 390 input_file); 391 input_file->file().release(); 392 input_file->file().unlock(this); 393 delete input_file; 394 ++this->dirindex_; 395 return this->do_read_symbols(workqueue); 396 } 397 return false; 398 } 399 400 Read_symbols_data* sd = new Read_symbols_data; 401 elf_obj->read_symbols(sd); 402 403 // Opening the file locked it, so now we need to unlock it. We 404 // need to unlock it before queuing the Add_symbols task, 405 // because the workqueue doesn't know about our lock on the 406 // file. If we queue the Add_symbols task first, it will be 407 // stuck on the end of the file lock, but since the workqueue 408 // doesn't know about that lock, it will never release the 409 // Add_symbols task. 410 411 input_file->file().unlock(this); 412 413 if (this->member_ != NULL) 414 { 415 this->member_->sd_ = sd; 416 this->member_->obj_ = elf_obj; 417 this->member_->arg_serial_ = 418 this->input_argument_->file().arg_serial(); 419 return true; 420 } 421 422 // We use queue_next because everything is cached for this 423 // task to run right away if possible. 424 425 workqueue->queue_next(new Add_symbols(this->input_objects_, 426 this->symtab_, this->layout_, 427 this->dirpath_, 428 this->dirindex_, 429 this->mapfile_, 430 this->input_argument_, 431 elf_obj, 432 NULL, 433 sd, 434 this->this_blocker_, 435 this->next_blocker_)); 436 437 return true; 438 } 439 440 // Queue up a task to try to parse this file as a script. We use a 441 // separate task so that the script will be read in order with other 442 // objects named on the command line. Also so that we don't try to 443 // read multiple scripts simultaneously, which could lead to 444 // unpredictable changes to the General_options structure. 445 446 workqueue->queue_soon(new Read_script(this->symtab_, 447 this->layout_, 448 this->dirpath_, 449 this->dirindex_, 450 this->input_objects_, 451 this->mapfile_, 452 this->input_group_, 453 this->input_argument_, 454 input_file, 455 this->this_blocker_, 456 this->next_blocker_)); 457 return true; 458 } 459 460 // Handle a group. We need to walk through the arguments over and 461 // over until we don't see any new undefined symbols. We do this by 462 // setting off Read_symbols Tasks as usual, but recording the archive 463 // entries instead of deleting them. We also start a Finish_group 464 // Task which runs after we've read all the symbols. In that task we 465 // process the archives in a loop until we are done. 466 467 void 468 Read_symbols::do_group(Workqueue* workqueue) 469 { 470 Input_group* input_group = new Input_group(); 471 472 const Input_file_group* group = this->input_argument_->group(); 473 Task_token* this_blocker = this->this_blocker_; 474 475 Finish_group* finish_group = new Finish_group(this->input_objects_, 476 this->symtab_, 477 this->layout_, 478 this->mapfile_, 479 input_group, 480 this->next_blocker_); 481 482 Task_token* next_blocker = new Task_token(true); 483 next_blocker->add_blocker(); 484 workqueue->queue_soon(new Start_group(this->symtab_, finish_group, 485 this_blocker, next_blocker)); 486 this_blocker = next_blocker; 487 488 for (Input_file_group::const_iterator p = group->begin(); 489 p != group->end(); 490 ++p) 491 { 492 const Input_argument* arg = &*p; 493 gold_assert(arg->is_file()); 494 495 next_blocker = new Task_token(true); 496 next_blocker->add_blocker(); 497 workqueue->queue_soon(new Read_symbols(this->input_objects_, 498 this->symtab_, this->layout_, 499 this->dirpath_, this->dirindex_, 500 this->mapfile_, arg, input_group, 501 NULL, this_blocker, next_blocker)); 502 this_blocker = next_blocker; 503 } 504 505 finish_group->set_blocker(this_blocker); 506 507 workqueue->queue_soon(finish_group); 508 } 509 510 // Return a debugging name for a Read_symbols task. 511 512 std::string 513 Read_symbols::get_name() const 514 { 515 if (this->input_argument_->is_group()) 516 { 517 std::string ret("Read_symbols group ("); 518 bool add_space = false; 519 const Input_file_group* group = this->input_argument_->group(); 520 for (Input_file_group::const_iterator p = group->begin(); 521 p != group->end(); 522 ++p) 523 { 524 if (add_space) 525 ret += ' '; 526 ret += p->file().name(); 527 add_space = true; 528 } 529 return ret + ')'; 530 } 531 else if (this->input_argument_->is_lib()) 532 { 533 std::string ret("Read_symbols lib ("); 534 bool add_space = false; 535 const Input_file_lib* lib = this->input_argument_->lib(); 536 for (Input_file_lib::const_iterator p = lib->begin(); 537 p != lib->end(); 538 ++p) 539 { 540 if (add_space) 541 ret += ' '; 542 ret += p->file().name(); 543 add_space = true; 544 } 545 return ret + ')'; 546 } 547 else 548 { 549 std::string ret("Read_symbols "); 550 if (this->input_argument_->file().is_lib()) 551 ret += "-l"; 552 else if (this->input_argument_->file().is_searched_file()) 553 ret += "-l:"; 554 ret += this->input_argument_->file().name(); 555 return ret; 556 } 557 } 558 559 // Class Add_symbols. 560 561 Add_symbols::~Add_symbols() 562 { 563 if (this->this_blocker_ != NULL) 564 delete this->this_blocker_; 565 // next_blocker_ is deleted by the task associated with the next 566 // input file. 567 } 568 569 // We are blocked by this_blocker_. We block next_blocker_. We also 570 // lock the file. 571 572 Task_token* 573 Add_symbols::is_runnable() 574 { 575 if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked()) 576 return this->this_blocker_; 577 if (this->object_->is_locked()) 578 return this->object_->token(); 579 return NULL; 580 } 581 582 void 583 Add_symbols::locks(Task_locker* tl) 584 { 585 tl->add(this, this->next_blocker_); 586 Task_token* token = this->object_->token(); 587 if (token != NULL) 588 tl->add(this, token); 589 } 590 591 // Add the symbols in the object to the symbol table. 592 593 void 594 Add_symbols::run(Workqueue*) 595 { 596 Pluginobj* pluginobj = this->object_->pluginobj(); 597 if (pluginobj != NULL) 598 { 599 this->object_->add_symbols(this->symtab_, this->sd_, this->layout_); 600 return; 601 } 602 603 if (!this->input_objects_->add_object(this->object_)) 604 { 605 this->object_->discard_decompressed_sections(); 606 gold_assert(this->sd_ != NULL); 607 delete this->sd_; 608 this->sd_ = NULL; 609 this->object_->release(); 610 delete this->object_; 611 } 612 else 613 { 614 Incremental_inputs* incremental_inputs = 615 this->layout_->incremental_inputs(); 616 if (incremental_inputs != NULL) 617 { 618 if (this->library_ != NULL && !this->library_->is_reported()) 619 { 620 Incremental_binary* ibase = this->layout_->incremental_base(); 621 gold_assert(ibase != NULL); 622 unsigned int lib_serial = this->library_->arg_serial(); 623 unsigned int lib_index = this->library_->input_file_index(); 624 Script_info* lib_script_info = ibase->get_script_info(lib_index); 625 incremental_inputs->report_archive_begin(this->library_, 626 lib_serial, 627 lib_script_info); 628 } 629 unsigned int arg_serial = this->input_argument_->file().arg_serial(); 630 Script_info* script_info = this->input_argument_->script_info(); 631 incremental_inputs->report_object(this->object_, arg_serial, 632 this->library_, script_info); 633 } 634 this->object_->layout(this->symtab_, this->layout_, this->sd_); 635 this->object_->add_symbols(this->symtab_, this->sd_, this->layout_); 636 this->object_->discard_decompressed_sections(); 637 delete this->sd_; 638 this->sd_ = NULL; 639 this->object_->release(); 640 } 641 } 642 643 // Class Read_member. 644 645 Read_member::~Read_member() 646 { 647 if (this->this_blocker_ != NULL) 648 delete this->this_blocker_; 649 // next_blocker_ is deleted by the task associated with the next 650 // input file. 651 } 652 653 // Return whether a Read_member task is runnable. 654 655 Task_token* 656 Read_member::is_runnable() 657 { 658 if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked()) 659 return this->this_blocker_; 660 return NULL; 661 } 662 663 void 664 Read_member::locks(Task_locker* tl) 665 { 666 tl->add(this, this->next_blocker_); 667 } 668 669 // Run a Read_member task. 670 671 void 672 Read_member::run(Workqueue*) 673 { 674 // This task doesn't need to do anything for now. The Read_symbols task 675 // that is queued for the archive library will cause the archive to be 676 // processed from scratch. 677 } 678 679 // Class Check_script. 680 681 Check_script::~Check_script() 682 { 683 if (this->this_blocker_ != NULL) 684 delete this->this_blocker_; 685 // next_blocker_ is deleted by the task associated with the next 686 // input file. 687 } 688 689 // Return whether a Check_script task is runnable. 690 691 Task_token* 692 Check_script::is_runnable() 693 { 694 if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked()) 695 return this->this_blocker_; 696 return NULL; 697 } 698 699 void 700 Check_script::locks(Task_locker* tl) 701 { 702 tl->add(this, this->next_blocker_); 703 } 704 705 // Run a Check_script task. 706 707 void 708 Check_script::run(Workqueue*) 709 { 710 Incremental_inputs* incremental_inputs = this->layout_->incremental_inputs(); 711 gold_assert(incremental_inputs != NULL); 712 unsigned int arg_serial = this->input_reader_->arg_serial(); 713 Script_info* script_info = 714 this->ibase_->get_script_info(this->input_file_index_); 715 Timespec mtime = this->input_reader_->get_mtime(); 716 incremental_inputs->report_script(script_info, arg_serial, mtime); 717 } 718 719 // Class Check_library. 720 721 Check_library::~Check_library() 722 { 723 if (this->this_blocker_ != NULL) 724 delete this->this_blocker_; 725 // next_blocker_ is deleted by the task associated with the next 726 // input file. 727 } 728 729 // Return whether a Check_library task is runnable. 730 731 Task_token* 732 Check_library::is_runnable() 733 { 734 if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked()) 735 return this->this_blocker_; 736 return NULL; 737 } 738 739 void 740 Check_library::locks(Task_locker* tl) 741 { 742 tl->add(this, this->next_blocker_); 743 } 744 745 // Run a Check_library task. 746 747 void 748 Check_library::run(Workqueue*) 749 { 750 Incremental_inputs* incremental_inputs = this->layout_->incremental_inputs(); 751 gold_assert(incremental_inputs != NULL); 752 Incremental_library* lib = this->ibase_->get_library(this->input_file_index_); 753 gold_assert(lib != NULL); 754 lib->copy_unused_symbols(); 755 // FIXME: Check that unused symbols remain unused. 756 if (!lib->is_reported()) 757 { 758 unsigned int lib_serial = lib->arg_serial(); 759 unsigned int lib_index = lib->input_file_index(); 760 Script_info* script_info = this->ibase_->get_script_info(lib_index); 761 incremental_inputs->report_archive_begin(lib, lib_serial, script_info); 762 } 763 incremental_inputs->report_archive_end(lib); 764 } 765 766 // Class Input_group. 767 768 // When we delete an Input_group we can delete the archive 769 // information. 770 771 Input_group::~Input_group() 772 { 773 for (Input_group::const_iterator p = this->begin(); 774 p != this->end(); 775 ++p) 776 delete *p; 777 } 778 779 // Class Start_group. 780 781 Start_group::~Start_group() 782 { 783 if (this->this_blocker_ != NULL) 784 delete this->this_blocker_; 785 // next_blocker_ is deleted by the task associated with the first 786 // file in the group. 787 } 788 789 // We need to wait for THIS_BLOCKER_ and unblock NEXT_BLOCKER_. 790 791 Task_token* 792 Start_group::is_runnable() 793 { 794 if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked()) 795 return this->this_blocker_; 796 return NULL; 797 } 798 799 void 800 Start_group::locks(Task_locker* tl) 801 { 802 tl->add(this, this->next_blocker_); 803 } 804 805 // Store the number of undefined symbols we see now. 806 807 void 808 Start_group::run(Workqueue*) 809 { 810 this->finish_group_->set_saw_undefined(this->symtab_->saw_undefined()); 811 } 812 813 // Class Finish_group. 814 815 Finish_group::~Finish_group() 816 { 817 if (this->this_blocker_ != NULL) 818 delete this->this_blocker_; 819 // next_blocker_ is deleted by the task associated with the next 820 // input file following the group. 821 } 822 823 // We need to wait for THIS_BLOCKER_ and unblock NEXT_BLOCKER_. 824 825 Task_token* 826 Finish_group::is_runnable() 827 { 828 if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked()) 829 return this->this_blocker_; 830 return NULL; 831 } 832 833 void 834 Finish_group::locks(Task_locker* tl) 835 { 836 tl->add(this, this->next_blocker_); 837 } 838 839 // Loop over the archives until there are no new undefined symbols. 840 841 void 842 Finish_group::run(Workqueue*) 843 { 844 size_t saw_undefined = this->saw_undefined_; 845 while (saw_undefined != this->symtab_->saw_undefined()) 846 { 847 saw_undefined = this->symtab_->saw_undefined(); 848 849 for (Input_group::const_iterator p = this->input_group_->begin(); 850 p != this->input_group_->end(); 851 ++p) 852 { 853 Task_lock_obj<Archive> tl(this, *p); 854 855 (*p)->add_symbols(this->symtab_, this->layout_, 856 this->input_objects_, this->mapfile_); 857 } 858 } 859 860 // Now that we're done with the archives, record the incremental 861 // layout information. 862 for (Input_group::const_iterator p = this->input_group_->begin(); 863 p != this->input_group_->end(); 864 ++p) 865 { 866 // For an incremental link, finish recording the layout information. 867 Incremental_inputs* incremental_inputs = 868 this->layout_->incremental_inputs(); 869 if (incremental_inputs != NULL) 870 incremental_inputs->report_archive_end(*p); 871 } 872 873 if (parameters->options().has_plugins()) 874 parameters->options().plugins()->save_input_group(this->input_group_); 875 else 876 delete this->input_group_; 877 } 878 879 // Class Read_script 880 881 Read_script::~Read_script() 882 { 883 if (this->this_blocker_ != NULL) 884 delete this->this_blocker_; 885 // next_blocker_ is deleted by the task associated with the next 886 // input file. 887 } 888 889 // We are blocked by this_blocker_. 890 891 Task_token* 892 Read_script::is_runnable() 893 { 894 if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked()) 895 return this->this_blocker_; 896 return NULL; 897 } 898 899 // We don't unlock next_blocker_ here. If the script names any input 900 // files, then the last file will be responsible for unlocking it. 901 902 void 903 Read_script::locks(Task_locker*) 904 { 905 } 906 907 // Read the script, if it is a script. 908 909 void 910 Read_script::run(Workqueue* workqueue) 911 { 912 bool used_next_blocker; 913 if (!read_input_script(workqueue, this->symtab_, this->layout_, 914 this->dirpath_, this->dirindex_, this->input_objects_, 915 this->mapfile_, this->input_group_, 916 this->input_argument_, this->input_file_, 917 this->next_blocker_, &used_next_blocker)) 918 { 919 // Here we have to handle any other input file types we need. 920 gold_error(_("%s: not an object or archive"), 921 this->input_file_->file().filename().c_str()); 922 } 923 924 if (!used_next_blocker) 925 { 926 // Queue up a task to unlock next_blocker. We can't just unlock 927 // it here, as we don't hold the workqueue lock. 928 workqueue->queue_soon(new Unblock_token(NULL, this->next_blocker_)); 929 } 930 } 931 932 // Return a debugging name for a Read_script task. 933 934 std::string 935 Read_script::get_name() const 936 { 937 std::string ret("Read_script "); 938 if (this->input_argument_->file().is_lib()) 939 ret += "-l"; 940 else if (this->input_argument_->file().is_searched_file()) 941 ret += "-l:"; 942 ret += this->input_argument_->file().name(); 943 return ret; 944 } 945 946 } // End namespace gold. 947