readsyms.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492
  1. // readsyms.h -- read input file symbols for gold -*- C++ -*-
  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. #ifndef GOLD_READSYMS_H
  18. #define GOLD_READSYMS_H
  19. #include <vector>
  20. #include "workqueue.h"
  21. #include "object.h"
  22. #include "incremental.h"
  23. namespace gold
  24. {
  25. class Input_objects;
  26. class Symbol_table;
  27. class Input_group;
  28. class Archive;
  29. class Finish_group;
  30. // This Task is responsible for reading the symbols from an input
  31. // file. This also includes reading the relocations so that we can
  32. // check for any that require a PLT and/or a GOT. After the data has
  33. // been read, this queues up another task to actually add the symbols
  34. // to the symbol table. The tasks are separated because the file
  35. // reading can occur in parallel but adding the symbols must be done
  36. // in the order of the input files.
  37. class Read_symbols : public Task
  38. {
  39. public:
  40. // DIRPATH is the list of directories to search for libraries.
  41. // INPUT is the file to read. INPUT_GROUP is not NULL if we are in
  42. // the middle of an input group. THIS_BLOCKER is used to prevent
  43. // the associated Add_symbols task from running before the previous
  44. // one has completed; it will be NULL for the first task.
  45. // NEXT_BLOCKER is used to block the next input file from adding
  46. // symbols.
  47. Read_symbols(Input_objects* input_objects, Symbol_table* symtab,
  48. Layout* layout, Dirsearch* dirpath, int dirindex,
  49. Mapfile* mapfile, const Input_argument* input_argument,
  50. Input_group* input_group, Archive_member* member,
  51. Task_token* this_blocker, Task_token* next_blocker)
  52. : input_objects_(input_objects), symtab_(symtab), layout_(layout),
  53. dirpath_(dirpath), dirindex_(dirindex), mapfile_(mapfile),
  54. input_argument_(input_argument), input_group_(input_group),
  55. member_(member), this_blocker_(this_blocker),
  56. next_blocker_(next_blocker)
  57. { }
  58. ~Read_symbols();
  59. // If appropriate, issue a warning about skipping an incompatible
  60. // object.
  61. static void
  62. incompatible_warning(const Input_argument*, const Input_file*);
  63. // Requeue a Read_symbols task to search for the next object with
  64. // the same name.
  65. static void
  66. requeue(Workqueue*, Input_objects*, Symbol_table*, Layout*, Dirsearch*,
  67. int dirindex, Mapfile*, const Input_argument*, Input_group*,
  68. Task_token* next_blocker);
  69. // The standard Task methods.
  70. Task_token*
  71. is_runnable();
  72. void
  73. locks(Task_locker*);
  74. void
  75. run(Workqueue*);
  76. std::string
  77. get_name() const;
  78. private:
  79. // Handle an archive group.
  80. void
  81. do_group(Workqueue*);
  82. // Handle --start-lib ... --end-lib
  83. bool
  84. do_lib_group(Workqueue*);
  85. // Handle --whole-archive --start-lib ... --end-lib --no-whole-archive
  86. bool
  87. do_whole_lib_group(Workqueue*);
  88. // Open and identify the file.
  89. bool
  90. do_read_symbols(Workqueue*);
  91. Input_objects* input_objects_;
  92. Symbol_table* symtab_;
  93. Layout* layout_;
  94. Dirsearch* dirpath_;
  95. int dirindex_;
  96. Mapfile* mapfile_;
  97. const Input_argument* input_argument_;
  98. Input_group* input_group_;
  99. Archive_member* member_;
  100. Task_token* this_blocker_;
  101. Task_token* next_blocker_;
  102. };
  103. // This Task handles adding the symbols to the symbol table. These
  104. // tasks must be run in the same order as the arguments appear on the
  105. // command line.
  106. class Add_symbols : public Task
  107. {
  108. public:
  109. // THIS_BLOCKER is used to prevent this task from running before the
  110. // one for the previous input file. NEXT_BLOCKER is used to prevent
  111. // the next task from running.
  112. Add_symbols(Input_objects* input_objects, Symbol_table* symtab,
  113. Layout* layout, Dirsearch* /*dirpath*/, int /*dirindex*/,
  114. Mapfile* /*mapfile*/, const Input_argument* input_argument,
  115. Object* object, Incremental_library* library,
  116. Read_symbols_data* sd, Task_token* this_blocker,
  117. Task_token* next_blocker)
  118. : input_objects_(input_objects), symtab_(symtab), layout_(layout),
  119. input_argument_(input_argument), object_(object), library_(library),
  120. sd_(sd), this_blocker_(this_blocker), next_blocker_(next_blocker)
  121. { }
  122. ~Add_symbols();
  123. // The standard Task methods.
  124. Task_token*
  125. is_runnable();
  126. void
  127. locks(Task_locker*);
  128. void
  129. run(Workqueue*);
  130. std::string
  131. get_name() const
  132. { return "Add_symbols " + this->object_->name(); }
  133. private:
  134. Input_objects* input_objects_;
  135. Symbol_table* symtab_;
  136. Layout* layout_;
  137. const Input_argument* input_argument_;
  138. Object* object_;
  139. Incremental_library* library_;
  140. Read_symbols_data* sd_;
  141. Task_token* this_blocker_;
  142. Task_token* next_blocker_;
  143. };
  144. // This Task is responsible for reading the symbols from an archive
  145. // member that has changed since the last incremental link.
  146. class Read_member : public Task
  147. {
  148. public:
  149. // INPUT is the file to read. INPUT_GROUP is not NULL if we are in
  150. // the middle of an input group. THIS_BLOCKER is used to prevent
  151. // the associated Add_symbols task from running before the previous
  152. // one has completed; it will be NULL for the first task.
  153. // NEXT_BLOCKER is used to block the next input file from adding
  154. // symbols.
  155. Read_member(Input_objects* /*input_objects*/, Symbol_table* /*symtab*/,
  156. Layout* /*layout*/, Mapfile* /*mapfile*/,
  157. const Incremental_binary::Input_reader* input_reader,
  158. Task_token* this_blocker, Task_token* next_blocker)
  159. : input_reader_(input_reader),
  160. this_blocker_(this_blocker), next_blocker_(next_blocker)
  161. { }
  162. ~Read_member();
  163. // The standard Task methods.
  164. Task_token*
  165. is_runnable();
  166. void
  167. locks(Task_locker*);
  168. void
  169. run(Workqueue*);
  170. std::string
  171. get_name() const
  172. {
  173. return (std::string("Read_member ") + this->input_reader_->filename());
  174. }
  175. private:
  176. const Incremental_binary::Input_reader* input_reader_;
  177. Task_token* this_blocker_;
  178. Task_token* next_blocker_;
  179. };
  180. // This Task is responsible for processing an input script file that has
  181. // not changed since the last incremental link.
  182. class Check_script : public Task
  183. {
  184. public:
  185. Check_script(Layout* layout, Incremental_binary* ibase,
  186. unsigned int input_file_index,
  187. const Incremental_binary::Input_reader* input_reader,
  188. Task_token* this_blocker, Task_token* next_blocker)
  189. : layout_(layout), ibase_(ibase), input_file_index_(input_file_index),
  190. input_reader_(input_reader), this_blocker_(this_blocker),
  191. next_blocker_(next_blocker)
  192. {
  193. this->filename_ = std::string(this->input_reader_->filename());
  194. }
  195. ~Check_script();
  196. // The standard Task methods.
  197. Task_token*
  198. is_runnable();
  199. void
  200. locks(Task_locker*);
  201. void
  202. run(Workqueue*);
  203. std::string
  204. get_name() const
  205. {
  206. return (std::string("Check_script ") + this->input_reader_->filename());
  207. }
  208. private:
  209. std::string filename_;
  210. Layout* layout_;
  211. Incremental_binary* ibase_;
  212. unsigned int input_file_index_;
  213. const Incremental_binary::Input_reader* input_reader_;
  214. Task_token* this_blocker_;
  215. Task_token* next_blocker_;
  216. };
  217. // This Task is responsible for processing an archive library that has
  218. // not changed since the last incremental link.
  219. class Check_library : public Task
  220. {
  221. public:
  222. Check_library(Symbol_table* /*symtab*/, Layout* layout,
  223. Incremental_binary* ibase,
  224. unsigned int input_file_index,
  225. const Incremental_binary::Input_reader* input_reader,
  226. Task_token* this_blocker, Task_token* next_blocker)
  227. : layout_(layout), ibase_(ibase),
  228. input_file_index_(input_file_index), input_reader_(input_reader),
  229. this_blocker_(this_blocker), next_blocker_(next_blocker)
  230. { }
  231. ~Check_library();
  232. // The standard Task methods.
  233. Task_token*
  234. is_runnable();
  235. void
  236. locks(Task_locker*);
  237. void
  238. run(Workqueue*);
  239. std::string
  240. get_name() const
  241. {
  242. return (std::string("Check_library ") + this->input_reader_->filename());
  243. }
  244. private:
  245. Layout* layout_;
  246. Incremental_binary* ibase_;
  247. unsigned int input_file_index_;
  248. const Incremental_binary::Input_reader* input_reader_;
  249. Task_token* this_blocker_;
  250. Task_token* next_blocker_;
  251. };
  252. // This class is used to track the archives in a group.
  253. class Input_group
  254. {
  255. public:
  256. typedef std::vector<Archive*> Archives;
  257. typedef Archives::const_iterator const_iterator;
  258. Input_group()
  259. : archives_()
  260. { }
  261. ~Input_group();
  262. // Add an archive to the group.
  263. void
  264. add_archive(Archive* arch)
  265. { this->archives_.push_back(arch); }
  266. // Loop over the archives in the group.
  267. const_iterator
  268. begin() const
  269. { return this->archives_.begin(); }
  270. const_iterator
  271. end() const
  272. { return this->archives_.end(); }
  273. private:
  274. Archives archives_;
  275. };
  276. // This class starts the handling of a group. It exists only to pick
  277. // up the number of undefined symbols at that point, so that we only
  278. // run back through the group if we saw a new undefined symbol.
  279. class Start_group : public Task
  280. {
  281. public:
  282. Start_group(Symbol_table* symtab, Finish_group* finish_group,
  283. Task_token* this_blocker, Task_token* next_blocker)
  284. : symtab_(symtab), finish_group_(finish_group),
  285. this_blocker_(this_blocker), next_blocker_(next_blocker)
  286. { }
  287. ~Start_group();
  288. // The standard Task methods.
  289. Task_token*
  290. is_runnable();
  291. void
  292. locks(Task_locker*);
  293. void
  294. run(Workqueue*);
  295. std::string
  296. get_name() const
  297. { return "Start_group"; }
  298. private:
  299. Symbol_table* symtab_;
  300. Finish_group* finish_group_;
  301. Task_token* this_blocker_;
  302. Task_token* next_blocker_;
  303. };
  304. // This class is used to finish up handling a group. It is just a
  305. // closure.
  306. class Finish_group : public Task
  307. {
  308. public:
  309. Finish_group(Input_objects* input_objects, Symbol_table* symtab,
  310. Layout* layout, Mapfile* mapfile, Input_group* input_group,
  311. Task_token* next_blocker)
  312. : input_objects_(input_objects), symtab_(symtab),
  313. layout_(layout), mapfile_(mapfile), input_group_(input_group),
  314. saw_undefined_(0), this_blocker_(NULL), next_blocker_(next_blocker)
  315. { }
  316. ~Finish_group();
  317. // Set the number of undefined symbols when we start processing the
  318. // group. This is called by the Start_group task.
  319. void
  320. set_saw_undefined(size_t saw_undefined)
  321. { this->saw_undefined_ = saw_undefined; }
  322. // Set the blocker to use for this task.
  323. void
  324. set_blocker(Task_token* this_blocker)
  325. {
  326. gold_assert(this->this_blocker_ == NULL);
  327. this->this_blocker_ = this_blocker;
  328. }
  329. // The standard Task methods.
  330. Task_token*
  331. is_runnable();
  332. void
  333. locks(Task_locker*);
  334. void
  335. run(Workqueue*);
  336. std::string
  337. get_name() const
  338. { return "Finish_group"; }
  339. private:
  340. Input_objects* input_objects_;
  341. Symbol_table* symtab_;
  342. Layout* layout_;
  343. Mapfile* mapfile_;
  344. Input_group* input_group_;
  345. size_t saw_undefined_;
  346. Task_token* this_blocker_;
  347. Task_token* next_blocker_;
  348. };
  349. // This class is used to read a file which was not recognized as an
  350. // object or archive. It tries to read it as a linker script, using
  351. // the tokens to serialize with the calls to Add_symbols.
  352. class Read_script : public Task
  353. {
  354. public:
  355. Read_script(Symbol_table* symtab, Layout* layout, Dirsearch* dirpath,
  356. int dirindex, Input_objects* input_objects, Mapfile* mapfile,
  357. Input_group* input_group, const Input_argument* input_argument,
  358. Input_file* input_file, Task_token* this_blocker,
  359. Task_token* next_blocker)
  360. : symtab_(symtab), layout_(layout), dirpath_(dirpath), dirindex_(dirindex),
  361. input_objects_(input_objects), mapfile_(mapfile),
  362. input_group_(input_group), input_argument_(input_argument),
  363. input_file_(input_file), this_blocker_(this_blocker),
  364. next_blocker_(next_blocker)
  365. { }
  366. ~Read_script();
  367. // The standard Task methods.
  368. Task_token*
  369. is_runnable();
  370. void
  371. locks(Task_locker*);
  372. void
  373. run(Workqueue*);
  374. std::string
  375. get_name() const;
  376. private:
  377. Symbol_table* symtab_;
  378. Layout* layout_;
  379. Dirsearch* dirpath_;
  380. int dirindex_;
  381. Input_objects* input_objects_;
  382. Mapfile* mapfile_;
  383. Input_group* input_group_;
  384. const Input_argument* input_argument_;
  385. Input_file* input_file_;
  386. Task_token* this_blocker_;
  387. Task_token* next_blocker_;
  388. };
  389. } // end namespace gold
  390. #endif // !defined(GOLD_READSYMS_H)