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