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