X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gold%2Fplugin.h;h=d2b9f228f76ffa57790cd11ceb7a27bcc6d7d961;hb=15a7492a25589fe5721322b73f05a4eeb8899a6f;hp=2ea0370878c3a3797adac6938460e33c00b47e5d;hpb=483620e86f09fcb4bc923c9f4b0c211e10efd334;p=external%2Fbinutils.git diff --git a/gold/plugin.h b/gold/plugin.h index 2ea0370..d2b9f22 100644 --- a/gold/plugin.h +++ b/gold/plugin.h @@ -1,6 +1,6 @@ // plugin.h -- plugin manager for gold -*- C++ -*- -// Copyright 2008 Free Software Foundation, Inc. +// Copyright (C) 2008-2019 Free Software Foundation, Inc. // Written by Cary Coutant . // This file is part of gold. @@ -36,12 +36,18 @@ namespace gold class General_options; class Input_file; class Input_objects; +class Archive; +class Input_group; +class Symbol; class Symbol_table; class Layout; class Dirsearch; class Mapfile; +class Task; class Task_token; class Pluginobj; +class Plugin_rescan; +class Plugin_recorder; // This class represents a single plugin library. @@ -54,7 +60,9 @@ class Plugin args_(), claim_file_handler_(NULL), all_symbols_read_handler_(NULL), - cleanup_handler_(NULL) + cleanup_handler_(NULL), + new_input_handler_(NULL), + cleanup_done_(false) { } ~Plugin() @@ -66,12 +74,16 @@ class Plugin // Call the claim-file handler. bool - claim_file(struct ld_plugin_input_file *plugin_input_file); + claim_file(struct ld_plugin_input_file* plugin_input_file); // Call the all-symbols-read handler. void all_symbols_read(); + // Call the new_input handler. + void + new_input(struct ld_plugin_input_file* plugin_input_file); + // Call the cleanup handler. void cleanup(); @@ -91,13 +103,22 @@ class Plugin set_cleanup_handler(ld_plugin_cleanup_handler handler) { this->cleanup_handler_ = handler; } + // Register a new_input handler. + void + set_new_input_handler(ld_plugin_new_input_handler handler) + { this->new_input_handler_ = handler; } + // Add an argument void - add_option(const char *arg) + add_option(const char* arg) { this->args_.push_back(arg); } + const std::string& + filename() const + { return this->filename_; } + private: Plugin(const Plugin&); Plugin& operator=(const Plugin&); @@ -112,6 +133,9 @@ class Plugin ld_plugin_claim_file_handler claim_file_handler_; ld_plugin_all_symbols_read_handler all_symbols_read_handler_; ld_plugin_cleanup_handler cleanup_handler_; + ld_plugin_new_input_handler new_input_handler_; + // TRUE if the cleanup handlers have been called. + bool cleanup_done_; }; // A manager class for plugins. @@ -121,13 +145,25 @@ class Plugin_manager public: Plugin_manager(const General_options& options) : plugins_(), objects_(), deferred_layout_objects_(), input_file_(NULL), - plugin_input_file_(), in_replacement_phase_(false), cleanup_done_(false), - options_(options), workqueue_(NULL), input_objects_(NULL), symtab_(NULL), - layout_(NULL), dirpath_(NULL), mapfile_(NULL), this_blocker_(NULL) + plugin_input_file_(), rescannable_(), undefined_symbols_(), + any_claimed_(false), in_replacement_phase_(false), any_added_(false), + in_claim_file_handler_(false), + options_(options), workqueue_(NULL), task_(NULL), input_objects_(NULL), + symtab_(NULL), layout_(NULL), dirpath_(NULL), mapfile_(NULL), + this_blocker_(NULL), extra_search_path_(), lock_(NULL), + initialize_lock_(&lock_), defsym_defines_set_(), + recorder_(NULL) { this->current_ = plugins_.end(); } ~Plugin_manager(); + // Returns true if the symbol name is used in the LHS of a defsym. + bool + is_defsym_def(const char* sym_name) const + { + return defsym_defines_set_.find(sym_name) != defsym_defines_set_.end(); + } + // Add a plugin library. void add_plugin(const char* filename) @@ -143,17 +179,44 @@ class Plugin_manager // Load all plugin libraries. void - load_plugins(); + load_plugins(Layout* layout); // Call the plugin claim-file handlers in turn to see if any claim the file. Pluginobj* - claim_file(Input_file *input_file, off_t offset, off_t filesize); + claim_file(Input_file* input_file, off_t offset, off_t filesize, + Object* elf_object); + + // Get the object associated with the handle and check if it is an elf object. + // If it is not a Pluginobj, it is an elf object. + Object* + get_elf_object(const void* handle); + + // True if the claim_file handler of the plugins is being called. + bool + in_claim_file_handler() + { return in_claim_file_handler_; } + + // Let the plugin manager save an archive for later rescanning. + // This takes ownership of the Archive pointer. + void + save_archive(Archive*); + + // Let the plugin manager save an input group for later rescanning. + // This takes ownership of the Input_group pointer. + void + save_input_group(Input_group*); // Call the all-symbols-read handlers. void - all_symbols_read(Workqueue* workqueue, Input_objects* input_objects, - Symbol_table* symtab, Layout* layout, Dirsearch* dirpath, - Mapfile* mapfile, Task_token** last_blocker); + all_symbols_read(Workqueue* workqueue, Task* task, + Input_objects* input_objects, Symbol_table* symtab, + Dirsearch* dirpath, Mapfile* mapfile, + Task_token** last_blocker); + + // Tell the plugin manager that we've a new undefined symbol which + // may require rescanning. + void + new_undefined_symbol(Symbol*); // Run deferred layout. void @@ -179,6 +242,14 @@ class Plugin_manager (*this->current_)->set_all_symbols_read_handler(handler); } + // Register a new_input handler. + void + set_new_input_handler(ld_plugin_new_input_handler handler) + { + gold_assert(this->current_ != plugins_.end()); + (*this->current_)->set_new_input_handler(handler); + } + // Register a claim-file handler. void set_cleanup_handler(ld_plugin_cleanup_handler handler) @@ -192,8 +263,8 @@ class Plugin_manager Pluginobj* make_plugin_object(unsigned int handle); - // Return the Pluginobj associated with the given HANDLE. - Pluginobj* + // Return the object associated with the given HANDLE. + Object* object(unsigned int handle) const { if (handle >= this->objects_.size()) @@ -205,7 +276,7 @@ class Plugin_manager // and we are still in the initial input phase. bool should_defer_layout() const - { return !this->objects_.empty() && !this->in_replacement_phase_; } + { return this->any_claimed_ && !this->in_replacement_phase_; } // Add a regular object to the deferred layout list. These are // objects whose layout has been deferred until after the @@ -214,22 +285,87 @@ class Plugin_manager add_deferred_layout_object(Relobj* obj) { this->deferred_layout_objects_.push_back(obj); } + // Get input file information with an open (possibly re-opened) + // file descriptor. + ld_plugin_status + get_input_file(unsigned int handle, struct ld_plugin_input_file* file); + + ld_plugin_status + get_view(unsigned int handle, const void **viewp); + + // Release an input file. + ld_plugin_status + release_input_file(unsigned int handle); + // Add a new input file. ld_plugin_status - add_input_file(char *pathname); + add_input_file(const char* pathname, bool is_lib); + + // Set the extra library path. + ld_plugin_status + set_extra_library_path(const char* path); // Return TRUE if we are in the replacement phase. bool in_replacement_phase() const { return this->in_replacement_phase_; } + Input_objects* + input_objects() const + { return this->input_objects_; } + + Symbol_table* + symtab() + { return this->symtab_; } + + Layout* + layout() + { return this->layout_; } + + Plugin_recorder* + recorder() const + { return this->recorder_; } + private: Plugin_manager(const Plugin_manager&); Plugin_manager& operator=(const Plugin_manager&); + // Plugin_rescan is a Task which calls the private rescan method. + friend class Plugin_rescan; + + // An archive or input group which may have to be rescanned if a + // plugin adds a new file. + struct Rescannable + { + bool is_archive; + union + { + Archive* archive; + Input_group* input_group; + } u; + + Rescannable(Archive* archive) + : is_archive(true) + { this->u.archive = archive; } + + Rescannable(Input_group* input_group) + : is_archive(false) + { this->u.input_group = input_group; } + }; + typedef std::list Plugin_list; - typedef std::vector Object_list; + typedef std::vector Object_list; typedef std::vector Deferred_layout_list; + typedef std::vector Rescannable_list; + typedef std::vector Undefined_symbol_list; + + // Rescan archives for undefined symbols. + void + rescan(Task*); + + // See whether the rescannable at index I defines SYM. + bool + rescannable_defines(size_t i, Symbol* sym); // The list of plugin libraries. Plugin_list plugins_; @@ -247,22 +383,49 @@ class Plugin_manager Input_file* input_file_; struct ld_plugin_input_file plugin_input_file_; - // TRUE after the all symbols read event; indicates that we are - // processing replacement files whose symbols should replace the + // A list of archives and input groups being saved for possible + // later rescanning. + Rescannable_list rescannable_; + + // A list of undefined symbols found in added files. + Undefined_symbol_list undefined_symbols_; + + // Whether any input files have been claimed by a plugin. + bool any_claimed_; + + // Set to true after the all symbols read event; indicates that we + // are processing replacement files whose symbols should replace the // placeholder symbols from the Pluginobj objects. bool in_replacement_phase_; - // TRUE if the cleanup handlers have been called. - bool cleanup_done_; + // Whether any input files or libraries were added by a plugin. + bool any_added_; + + // Set to true when the claim_file handler of a plugin is called. + bool in_claim_file_handler_; const General_options& options_; Workqueue* workqueue_; + Task* task_; Input_objects* input_objects_; Symbol_table* symtab_; Layout* layout_; Dirsearch* dirpath_; Mapfile* mapfile_; Task_token* this_blocker_; + + // An extra directory to search for the libraries passed by + // add_input_library. + std::string extra_search_path_; + Lock* lock_; + Initialize_lock initialize_lock_; + + // Keep track of all symbols defined by defsym. + typedef Unordered_set Defsym_defines_set; + Defsym_defines_set defsym_defines_set_; + + // Class to record plugin actions. + Plugin_recorder* recorder_; }; @@ -275,16 +438,15 @@ class Pluginobj : public Object typedef std::vector Symbols; - Pluginobj(const std::string& name, Input_file* input_file, off_t offset); + Pluginobj(const std::string& name, Input_file* input_file, off_t offset, + off_t filesize); // Fill in the symbol resolution status for the given plugin symbols. ld_plugin_status - get_symbol_resolution_info(int nsyms, ld_plugin_symbol* syms) const; - - // Add symbol information to the global symbol table. - void - add_symbols(Symbol_table* symtab, Layout* layout) - { this->do_add_symbols(symtab, layout); } + get_symbol_resolution_info(Symbol_table* symtab, + int nsyms, + ld_plugin_symbol* syms, + int version) const; // Store the incoming symbols from the plugin for later processing. void @@ -299,20 +461,40 @@ class Pluginobj : public Object bool include_comdat_group(std::string comdat_key, Layout* layout); + // Return the filename. + const std::string& + filename() const + { return this->input_file()->filename(); } + + // Return the file descriptor. + int + descriptor() + { return this->input_file()->file().descriptor(); } + + // Return the size of the file or archive member. + off_t + filesize() + { return this->filesize_; } + + // Return the word size of the object file. + int + elfsize() const + { gold_unreachable(); } + + // Return TRUE if this is a big-endian object file. + bool + is_big_endian() const + { gold_unreachable(); } + protected: // Return TRUE if this is an object claimed by a plugin. virtual Pluginobj* do_pluginobj() { return this; } - // Add symbol information to the global symbol table--implemented by - // child class. - virtual void - do_add_symbols(Symbol_table*, Layout*) = 0; - // The number of symbols provided by the plugin. int nsyms_; - + // The symbols provided by the plugin. const struct ld_plugin_symbol* syms_; @@ -320,6 +502,8 @@ class Pluginobj : public Object Symbols symbols_; private: + // Size of the file (or archive member). + off_t filesize_; // Map a comdat key symbol to a boolean indicating whether the comdat // group in this object with that key should be kept. typedef Unordered_map Comdat_map; @@ -333,7 +517,7 @@ class Sized_pluginobj : public Pluginobj { public: Sized_pluginobj(const std::string& name, Input_file* input_file, - off_t offset); + off_t offset, off_t filesize); // Read the symbols. void @@ -345,10 +529,21 @@ class Sized_pluginobj : public Pluginobj // Add the symbols to the symbol table. void - do_add_symbols(Symbol_table*, Read_symbols_data*); + do_add_symbols(Symbol_table*, Read_symbols_data*, Layout*); + + Archive::Should_include + do_should_include_member(Symbol_table* symtab, Layout*, Read_symbols_data*, + std::string* why); + + // Iterate over global symbols, calling a visitor class V for each. + void + do_for_all_global_symbols(Read_symbols_data* sd, + Library_base::Symbol_visitor_base* v); + // Iterate over local symbols, calling a visitor class V for each GOT offset + // associated with a local symbol. void - do_add_symbols(Symbol_table*, Layout*); + do_for_all_local_got_entries(Got_offset_list::Visitor* v) const; // Get the size of a section. uint64_t @@ -356,16 +551,21 @@ class Sized_pluginobj : public Pluginobj // Get the name of a section. std::string - do_section_name(unsigned int shndx); + do_section_name(unsigned int shndx) const; // Return a view of the contents of a section. - Object::Location - do_section_contents(unsigned int shndx); + const unsigned char* + do_section_contents(unsigned int shndx, section_size_type* plen, + bool cache); // Return section flags. uint64_t do_section_flags(unsigned int shndx); + // Return section entsize. + uint64_t + do_section_entsize(unsigned int shndx); + // Return section address. uint64_t do_section_address(unsigned int shndx); @@ -394,6 +594,10 @@ class Sized_pluginobj : public Pluginobj void do_get_global_symbol_counts(const Symbol_table*, size_t*, size_t*) const; + // Get global symbols. + const Symbols* + do_get_global_symbols() const; + // Add placeholder symbols from a claimed file. ld_plugin_status add_symbols_from_plugin(int nsyms, const ld_plugin_symbol* syms); @@ -403,50 +607,6 @@ class Sized_pluginobj : public Pluginobj private: }; -// This Task handles adding the symbols to the symbol table. These -// tasks must be run in the same order as the arguments appear on the -// command line. - -class Add_plugin_symbols : public Task -{ - public: - // THIS_BLOCKER is used to prevent this task from running before the - // one for the previous input file. NEXT_BLOCKER is used to prevent - // the next task from running. - Add_plugin_symbols(Symbol_table* symtab, - Layout* layout, - Pluginobj* obj, - Task_token* this_blocker, - Task_token* next_blocker) - : symtab_(symtab), layout_(layout), obj_(obj), - this_blocker_(this_blocker), next_blocker_(next_blocker) - { } - - ~Add_plugin_symbols(); - - // The standard Task methods. - - Task_token* - is_runnable(); - - void - locks(Task_locker*); - - void - run(Workqueue*); - - std::string - get_name() const - { return "Add_plugin_symbols " + this->obj_->name(); } - -private: - Symbol_table* symtab_; - Layout* layout_; - Pluginobj* obj_; - Task_token* this_blocker_; - Task_token* next_blocker_; -}; - // This Task handles handles the "all symbols read" event hook. // The plugin may add additional input files at this time, which must // be queued for reading. @@ -455,11 +615,11 @@ class Plugin_hook : public Task { public: Plugin_hook(const General_options& options, Input_objects* input_objects, - Symbol_table* symtab, Layout* layout, Dirsearch* dirpath, + Symbol_table* symtab, Layout* /*layout*/, Dirsearch* dirpath, Mapfile* mapfile, Task_token* this_blocker, Task_token* next_blocker) : options_(options), input_objects_(input_objects), symtab_(symtab), - layout_(layout), dirpath_(dirpath), mapfile_(mapfile), + dirpath_(dirpath), mapfile_(mapfile), this_blocker_(this_blocker), next_blocker_(next_blocker) { } @@ -484,7 +644,6 @@ class Plugin_hook : public Task const General_options& options_; Input_objects* input_objects_; Symbol_table* symtab_; - Layout* layout_; Dirsearch* dirpath_; Mapfile* mapfile_; Task_token* this_blocker_;