readsyms.cc 26 KB

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