plugin.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655
  1. // plugin.h -- plugin manager for gold -*- C++ -*-
  2. // Copyright (C) 2008-2022 Free Software Foundation, Inc.
  3. // Written by Cary Coutant <ccoutant@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_PLUGIN_H
  18. #define GOLD_PLUGIN_H
  19. #include <list>
  20. #include <string>
  21. #include "object.h"
  22. #include "plugin-api.h"
  23. #include "workqueue.h"
  24. namespace gold
  25. {
  26. class General_options;
  27. class Input_file;
  28. class Input_objects;
  29. class Archive;
  30. class Input_group;
  31. class Symbol;
  32. class Symbol_table;
  33. class Layout;
  34. class Dirsearch;
  35. class Mapfile;
  36. class Task;
  37. class Task_token;
  38. class Pluginobj;
  39. class Plugin_rescan;
  40. class Plugin_recorder;
  41. // This class represents a single plugin library.
  42. class Plugin
  43. {
  44. public:
  45. Plugin(const char* filename)
  46. : handle_(NULL),
  47. filename_(filename),
  48. args_(),
  49. claim_file_handler_(NULL),
  50. all_symbols_read_handler_(NULL),
  51. cleanup_handler_(NULL),
  52. new_input_handler_(NULL),
  53. cleanup_done_(false)
  54. { }
  55. ~Plugin()
  56. { }
  57. // Load the library and call its entry point.
  58. void
  59. load();
  60. // Call the claim-file handler.
  61. bool
  62. claim_file(struct ld_plugin_input_file* plugin_input_file);
  63. // Call the all-symbols-read handler.
  64. void
  65. all_symbols_read();
  66. // Call the new_input handler.
  67. void
  68. new_input(struct ld_plugin_input_file* plugin_input_file);
  69. // Call the cleanup handler.
  70. void
  71. cleanup();
  72. // Register a claim-file handler.
  73. void
  74. set_claim_file_handler(ld_plugin_claim_file_handler handler)
  75. { this->claim_file_handler_ = handler; }
  76. // Register an all-symbols-read handler.
  77. void
  78. set_all_symbols_read_handler(ld_plugin_all_symbols_read_handler handler)
  79. { this->all_symbols_read_handler_ = handler; }
  80. // Register a claim-file handler.
  81. void
  82. set_cleanup_handler(ld_plugin_cleanup_handler handler)
  83. { this->cleanup_handler_ = handler; }
  84. // Register a new_input handler.
  85. void
  86. set_new_input_handler(ld_plugin_new_input_handler handler)
  87. { this->new_input_handler_ = handler; }
  88. // Add an argument
  89. void
  90. add_option(const char* arg)
  91. {
  92. this->args_.push_back(arg);
  93. }
  94. const std::string&
  95. filename() const
  96. { return this->filename_; }
  97. private:
  98. Plugin(const Plugin&);
  99. Plugin& operator=(const Plugin&);
  100. // The shared library handle returned by dlopen.
  101. void* handle_;
  102. // The argument string given to --plugin.
  103. std::string filename_;
  104. // The list of argument string given to --plugin-opt.
  105. std::vector<std::string> args_;
  106. // The plugin's event handlers.
  107. ld_plugin_claim_file_handler claim_file_handler_;
  108. ld_plugin_all_symbols_read_handler all_symbols_read_handler_;
  109. ld_plugin_cleanup_handler cleanup_handler_;
  110. ld_plugin_new_input_handler new_input_handler_;
  111. // TRUE if the cleanup handlers have been called.
  112. bool cleanup_done_;
  113. };
  114. // A manager class for plugins.
  115. class Plugin_manager
  116. {
  117. public:
  118. Plugin_manager(const General_options& options)
  119. : plugins_(), objects_(), deferred_layout_objects_(), input_file_(NULL),
  120. plugin_input_file_(), rescannable_(), undefined_symbols_(),
  121. any_claimed_(false), in_replacement_phase_(false), any_added_(false),
  122. in_claim_file_handler_(false),
  123. options_(options), workqueue_(NULL), task_(NULL), input_objects_(NULL),
  124. symtab_(NULL), layout_(NULL), dirpath_(NULL), mapfile_(NULL),
  125. this_blocker_(NULL), extra_search_path_(), lock_(NULL),
  126. initialize_lock_(&lock_), defsym_defines_set_(),
  127. recorder_(NULL)
  128. { this->current_ = plugins_.end(); }
  129. ~Plugin_manager();
  130. // Returns true if the symbol name is used in the LHS of a defsym.
  131. bool
  132. is_defsym_def(const char* sym_name) const
  133. {
  134. return defsym_defines_set_.find(sym_name) != defsym_defines_set_.end();
  135. }
  136. // Add a plugin library.
  137. void
  138. add_plugin(const char* filename)
  139. { this->plugins_.push_back(new Plugin(filename)); }
  140. // Add an argument to the current plugin.
  141. void
  142. add_plugin_option(const char* opt)
  143. {
  144. Plugin* last = this->plugins_.back();
  145. last->add_option(opt);
  146. }
  147. // Load all plugin libraries.
  148. void
  149. load_plugins(Layout* layout);
  150. // Call the plugin claim-file handlers in turn to see if any claim the file.
  151. Pluginobj*
  152. claim_file(Input_file* input_file, off_t offset, off_t filesize,
  153. Object* elf_object);
  154. // Get the object associated with the handle and check if it is an elf object.
  155. // If it is not a Pluginobj, it is an elf object.
  156. Object*
  157. get_elf_object(const void* handle);
  158. // True if the claim_file handler of the plugins is being called.
  159. bool
  160. in_claim_file_handler()
  161. { return in_claim_file_handler_; }
  162. // Let the plugin manager save an archive for later rescanning.
  163. // This takes ownership of the Archive pointer.
  164. void
  165. save_archive(Archive*);
  166. // Let the plugin manager save an input group for later rescanning.
  167. // This takes ownership of the Input_group pointer.
  168. void
  169. save_input_group(Input_group*);
  170. // Call the all-symbols-read handlers.
  171. void
  172. all_symbols_read(Workqueue* workqueue, Task* task,
  173. Input_objects* input_objects, Symbol_table* symtab,
  174. Dirsearch* dirpath, Mapfile* mapfile,
  175. Task_token** last_blocker);
  176. // Tell the plugin manager that we've a new undefined symbol which
  177. // may require rescanning.
  178. void
  179. new_undefined_symbol(Symbol*);
  180. // Run deferred layout.
  181. void
  182. layout_deferred_objects();
  183. // Call the cleanup handlers.
  184. void
  185. cleanup();
  186. // Register a claim-file handler.
  187. void
  188. set_claim_file_handler(ld_plugin_claim_file_handler handler)
  189. {
  190. gold_assert(this->current_ != plugins_.end());
  191. (*this->current_)->set_claim_file_handler(handler);
  192. }
  193. // Register an all-symbols-read handler.
  194. void
  195. set_all_symbols_read_handler(ld_plugin_all_symbols_read_handler handler)
  196. {
  197. gold_assert(this->current_ != plugins_.end());
  198. (*this->current_)->set_all_symbols_read_handler(handler);
  199. }
  200. // Register a new_input handler.
  201. void
  202. set_new_input_handler(ld_plugin_new_input_handler handler)
  203. {
  204. gold_assert(this->current_ != plugins_.end());
  205. (*this->current_)->set_new_input_handler(handler);
  206. }
  207. // Register a claim-file handler.
  208. void
  209. set_cleanup_handler(ld_plugin_cleanup_handler handler)
  210. {
  211. gold_assert(this->current_ != plugins_.end());
  212. (*this->current_)->set_cleanup_handler(handler);
  213. }
  214. // Make a new Pluginobj object. This is called when the plugin calls
  215. // the add_symbols API.
  216. Pluginobj*
  217. make_plugin_object(unsigned int handle);
  218. // Return the object associated with the given HANDLE.
  219. Object*
  220. object(unsigned int handle) const
  221. {
  222. if (handle >= this->objects_.size())
  223. return NULL;
  224. return this->objects_[handle];
  225. }
  226. // Return TRUE if any input files have been claimed by a plugin
  227. // and we are still in the initial input phase.
  228. bool
  229. should_defer_layout() const
  230. { return this->any_claimed_ && !this->in_replacement_phase_; }
  231. // Add a regular object to the deferred layout list. These are
  232. // objects whose layout has been deferred until after the
  233. // replacement files have arrived.
  234. void
  235. add_deferred_layout_object(Relobj* obj)
  236. { this->deferred_layout_objects_.push_back(obj); }
  237. // Get input file information with an open (possibly re-opened)
  238. // file descriptor.
  239. ld_plugin_status
  240. get_input_file(unsigned int handle, struct ld_plugin_input_file* file);
  241. ld_plugin_status
  242. get_view(unsigned int handle, const void **viewp);
  243. // Release an input file.
  244. ld_plugin_status
  245. release_input_file(unsigned int handle);
  246. // Add a new input file.
  247. ld_plugin_status
  248. add_input_file(const char* pathname, bool is_lib);
  249. // Set the extra library path.
  250. ld_plugin_status
  251. set_extra_library_path(const char* path);
  252. // Return TRUE if we are in the replacement phase.
  253. bool
  254. in_replacement_phase() const
  255. { return this->in_replacement_phase_; }
  256. Input_objects*
  257. input_objects() const
  258. { return this->input_objects_; }
  259. Symbol_table*
  260. symtab()
  261. { return this->symtab_; }
  262. Layout*
  263. layout()
  264. { return this->layout_; }
  265. Plugin_recorder*
  266. recorder() const
  267. { return this->recorder_; }
  268. private:
  269. Plugin_manager(const Plugin_manager&);
  270. Plugin_manager& operator=(const Plugin_manager&);
  271. // Plugin_rescan is a Task which calls the private rescan method.
  272. friend class Plugin_rescan;
  273. // An archive or input group which may have to be rescanned if a
  274. // plugin adds a new file.
  275. struct Rescannable
  276. {
  277. bool is_archive;
  278. union
  279. {
  280. Archive* archive;
  281. Input_group* input_group;
  282. } u;
  283. Rescannable(Archive* archive)
  284. : is_archive(true)
  285. { this->u.archive = archive; }
  286. Rescannable(Input_group* input_group)
  287. : is_archive(false)
  288. { this->u.input_group = input_group; }
  289. };
  290. typedef std::list<Plugin*> Plugin_list;
  291. typedef std::vector<Object*> Object_list;
  292. typedef std::vector<Relobj*> Deferred_layout_list;
  293. typedef std::vector<Rescannable> Rescannable_list;
  294. typedef std::vector<Symbol*> Undefined_symbol_list;
  295. // Rescan archives for undefined symbols.
  296. void
  297. rescan(Task*);
  298. // See whether the rescannable at index I defines SYM.
  299. bool
  300. rescannable_defines(size_t i, Symbol* sym);
  301. // The list of plugin libraries.
  302. Plugin_list plugins_;
  303. // A pointer to the current plugin. Used while loading plugins.
  304. Plugin_list::iterator current_;
  305. // The list of plugin objects. The index of an item in this list
  306. // serves as the "handle" that we pass to the plugins.
  307. Object_list objects_;
  308. // The list of regular objects whose layout has been deferred.
  309. Deferred_layout_list deferred_layout_objects_;
  310. // The file currently up for claim by the plugins.
  311. Input_file* input_file_;
  312. struct ld_plugin_input_file plugin_input_file_;
  313. // A list of archives and input groups being saved for possible
  314. // later rescanning.
  315. Rescannable_list rescannable_;
  316. // A list of undefined symbols found in added files.
  317. Undefined_symbol_list undefined_symbols_;
  318. // Whether any input files have been claimed by a plugin.
  319. bool any_claimed_;
  320. // Set to true after the all symbols read event; indicates that we
  321. // are processing replacement files whose symbols should replace the
  322. // placeholder symbols from the Pluginobj objects.
  323. bool in_replacement_phase_;
  324. // Whether any input files or libraries were added by a plugin.
  325. bool any_added_;
  326. // Set to true when the claim_file handler of a plugin is called.
  327. bool in_claim_file_handler_;
  328. const General_options& options_;
  329. Workqueue* workqueue_;
  330. Task* task_;
  331. Input_objects* input_objects_;
  332. Symbol_table* symtab_;
  333. Layout* layout_;
  334. Dirsearch* dirpath_;
  335. Mapfile* mapfile_;
  336. Task_token* this_blocker_;
  337. // An extra directory to search for the libraries passed by
  338. // add_input_library.
  339. std::string extra_search_path_;
  340. Lock* lock_;
  341. Initialize_lock initialize_lock_;
  342. // Keep track of all symbols defined by defsym.
  343. typedef Unordered_set<std::string> Defsym_defines_set;
  344. Defsym_defines_set defsym_defines_set_;
  345. // Class to record plugin actions.
  346. Plugin_recorder* recorder_;
  347. };
  348. // An object file claimed by a plugin. This is an abstract base class.
  349. // The implementation is the template class Sized_pluginobj.
  350. class Pluginobj : public Object
  351. {
  352. public:
  353. typedef std::vector<Symbol*> Symbols;
  354. Pluginobj(const std::string& name, Input_file* input_file, off_t offset,
  355. off_t filesize);
  356. // Fill in the symbol resolution status for the given plugin symbols.
  357. ld_plugin_status
  358. get_symbol_resolution_info(Symbol_table* symtab,
  359. int nsyms,
  360. ld_plugin_symbol* syms,
  361. int version) const;
  362. // Store the incoming symbols from the plugin for later processing.
  363. void
  364. store_incoming_symbols(int nsyms, const struct ld_plugin_symbol* syms)
  365. {
  366. this->nsyms_ = nsyms;
  367. this->syms_ = syms;
  368. }
  369. // Return TRUE if the comdat group with key COMDAT_KEY from this object
  370. // should be kept.
  371. bool
  372. include_comdat_group(std::string comdat_key, Layout* layout);
  373. // Return the filename.
  374. const std::string&
  375. filename() const
  376. { return this->input_file()->filename(); }
  377. // Return the file descriptor.
  378. int
  379. descriptor()
  380. { return this->input_file()->file().descriptor(); }
  381. // Return the size of the file or archive member.
  382. off_t
  383. filesize()
  384. { return this->filesize_; }
  385. // Return the word size of the object file.
  386. int
  387. elfsize() const
  388. { gold_unreachable(); }
  389. // Return TRUE if this is a big-endian object file.
  390. bool
  391. is_big_endian() const
  392. { gold_unreachable(); }
  393. protected:
  394. // Return TRUE if this is an object claimed by a plugin.
  395. virtual Pluginobj*
  396. do_pluginobj()
  397. { return this; }
  398. // The number of symbols provided by the plugin.
  399. int nsyms_;
  400. // The symbols provided by the plugin.
  401. const struct ld_plugin_symbol* syms_;
  402. // The entries in the symbol table for the external symbols.
  403. Symbols symbols_;
  404. private:
  405. // Size of the file (or archive member).
  406. off_t filesize_;
  407. // Map a comdat key symbol to a boolean indicating whether the comdat
  408. // group in this object with that key should be kept.
  409. typedef Unordered_map<std::string, bool> Comdat_map;
  410. Comdat_map comdat_map_;
  411. };
  412. // A plugin object, size-specific version.
  413. template<int size, bool big_endian>
  414. class Sized_pluginobj : public Pluginobj
  415. {
  416. public:
  417. Sized_pluginobj(const std::string& name, Input_file* input_file,
  418. off_t offset, off_t filesize);
  419. // Read the symbols.
  420. void
  421. do_read_symbols(Read_symbols_data*);
  422. // Lay out the input sections.
  423. void
  424. do_layout(Symbol_table*, Layout*, Read_symbols_data*);
  425. // Add the symbols to the symbol table.
  426. void
  427. do_add_symbols(Symbol_table*, Read_symbols_data*, Layout*);
  428. Archive::Should_include
  429. do_should_include_member(Symbol_table* symtab, Layout*, Read_symbols_data*,
  430. std::string* why);
  431. // Iterate over global symbols, calling a visitor class V for each.
  432. void
  433. do_for_all_global_symbols(Read_symbols_data* sd,
  434. Library_base::Symbol_visitor_base* v);
  435. // Iterate over local symbols, calling a visitor class V for each GOT offset
  436. // associated with a local symbol.
  437. void
  438. do_for_all_local_got_entries(Got_offset_list::Visitor* v) const;
  439. // Get the size of a section.
  440. uint64_t
  441. do_section_size(unsigned int shndx);
  442. // Get the name of a section.
  443. std::string
  444. do_section_name(unsigned int shndx) const;
  445. // Return a view of the contents of a section.
  446. const unsigned char*
  447. do_section_contents(unsigned int shndx, section_size_type* plen,
  448. bool cache);
  449. // Return section flags.
  450. uint64_t
  451. do_section_flags(unsigned int shndx);
  452. // Return section entsize.
  453. uint64_t
  454. do_section_entsize(unsigned int shndx);
  455. // Return section address.
  456. uint64_t
  457. do_section_address(unsigned int shndx);
  458. // Return section type.
  459. unsigned int
  460. do_section_type(unsigned int shndx);
  461. // Return the section link field.
  462. unsigned int
  463. do_section_link(unsigned int shndx);
  464. // Return the section link field.
  465. unsigned int
  466. do_section_info(unsigned int shndx);
  467. // Return the section alignment.
  468. uint64_t
  469. do_section_addralign(unsigned int shndx);
  470. // Return the Xindex structure to use.
  471. Xindex*
  472. do_initialize_xindex();
  473. // Get symbol counts.
  474. void
  475. do_get_global_symbol_counts(const Symbol_table*, size_t*, size_t*) const;
  476. // Get global symbols.
  477. const Symbols*
  478. do_get_global_symbols() const;
  479. // Add placeholder symbols from a claimed file.
  480. ld_plugin_status
  481. add_symbols_from_plugin(int nsyms, const ld_plugin_symbol* syms);
  482. protected:
  483. private:
  484. };
  485. // This Task handles handles the "all symbols read" event hook.
  486. // The plugin may add additional input files at this time, which must
  487. // be queued for reading.
  488. class Plugin_hook : public Task
  489. {
  490. public:
  491. Plugin_hook(const General_options& options, Input_objects* input_objects,
  492. Symbol_table* symtab, Layout* /*layout*/, Dirsearch* dirpath,
  493. Mapfile* mapfile, Task_token* this_blocker,
  494. Task_token* next_blocker)
  495. : options_(options), input_objects_(input_objects), symtab_(symtab),
  496. dirpath_(dirpath), mapfile_(mapfile),
  497. this_blocker_(this_blocker), next_blocker_(next_blocker)
  498. { }
  499. ~Plugin_hook();
  500. // The standard Task methods.
  501. Task_token*
  502. is_runnable();
  503. void
  504. locks(Task_locker*);
  505. void
  506. run(Workqueue*);
  507. std::string
  508. get_name() const
  509. { return "Plugin_hook"; }
  510. private:
  511. const General_options& options_;
  512. Input_objects* input_objects_;
  513. Symbol_table* symtab_;
  514. Dirsearch* dirpath_;
  515. Mapfile* mapfile_;
  516. Task_token* this_blocker_;
  517. Task_token* next_blocker_;
  518. };
  519. } // End namespace gold.
  520. #endif // !defined(GOLD_PLUGIN_H)