From e9552f7ebbcd2438fe50dbf1fb4b1926c96adb75 Mon Sep 17 00:00:00 2001 From: Sriraman Tallam Date: Thu, 14 Jul 2011 00:55:18 +0000 Subject: [PATCH] 2011-07-13 Sriraman Tallam * plugin-api.h (ld_plugin_section): New struct. (ld_plugin_get_section_count): New typedef. (ld_plugin_get_section_type): New typedef. (ld_plugin_get_section_name): New typedef. (ld_plugin_get_section_contents): New typedef. (ld_plugin_update_section_order): New typedef. (ld_plugin_allow_section_ordering): New typedef. (LDPT_GET_SECTION_COUNT): New enum value. (LDPT_GET_SECTION_TYPE): New enum value. (LDPT_GET_SECTION_NAME): New enum value. (LDPT_GET_SECTION_CONTENTS): New enum value. (LDPT_UPDATE_SECTION_ORDER): New enum value. (LDPT_ALLOW_SECTION_ORDERING): New enum value. (tv_get_section_count): New struct members. (tv_get_section_type): New struct members. (tv_get_section_name): New struct members. (tv_get_section_contents): New struct members. (tv_update_section_order): New struct members. (tv_allow_section_ordering): New struct members. * archive.cc (Archive::get_elf_object_for_member): Add extra parameter to claim_file call. * layout.cc (Layout::Layout): Initialize section_ordering_specified_, input_section_position_, and input_section_glob_. (read_layout_from_file): Call function section_ordering_specified. * layout.h (is_section_ordering_specified): New function. (section_ordering_specified): New function. (section_ordering_specified_): New boolean member. * main.cc(main): Call load_plugins after layout object is defined. * output.cc (Output_section::add_input_section): Use function section_ordering_specified to check if section ordering is needed. * output.cc (Output_section::add_relaxed_input_section): Use function section_ordering_specified to check if section ordering is needed. (Output_section::update_section_layout): New function. (Output_section::sort_attached_input_sections): Check if input section must be reordered. * output.h (Output_section::update_section_layout): New function. * plugin.cc (get_section_count): New function. (get_section_type): New function. (get_section_name): New function. (get_section_contents): New function. (update_section_order): New function. (allow_section_ordering): New function. (Plugin::load): Add the new interfaces to the transfer vector. (Plugin_manager::load_plugins): New parameter. (Plugin_manager::all_symbols_read): New parameter. (Plugin_manager::claim_file): New parameter. Save the elf object for unclaimed objects. (Plugin_manager::get_elf_object): New function. (Plugin_manager::get_view): Change to directly use the bool to check if get_view is called from claim_file_hook. * plugin.h (input_objects): New function (Plugin__manager::load_plugins): New parameter. (Plugin_manager::claim_file): New parameter. (Plugin_manager::get_elf_object): New function. (Plugin_manager::in_claim_file_handler): New function. (Plugin_manager::in_claim_file_handler_): New member. (layout): New function. * readsyms.cc (Read_symbols::do_read_symbols): Call the claim_file handler with an extra parameter. Make the elf object before calling claim_file handler. * testsuite/plugin_test.c (get_section_count): New function pointer. (get_section_type): New function pointer. (get_section_name): New function pointer. (get_section_contents): New function pointer. (update_section_order): New function pointer. (allow_section_ordering): New function pointer. (onload): Check if the new interfaces exist. --- gold/ChangeLog | 53 +++++++ gold/archive.cc | 3 +- gold/layout.cc | 6 +- gold/layout.h | 13 ++ gold/main.cc | 8 +- gold/output.cc | 42 +++++- gold/output.h | 5 + gold/plugin.cc | 271 ++++++++++++++++++++++++++++++++--- gold/plugin.h | 35 ++++- gold/readsyms.cc | 38 +++-- gold/testsuite/plugin_test.c | 60 ++++++++ include/ChangeLog | 23 +++ include/plugin-api.h | 81 ++++++++++- 13 files changed, 592 insertions(+), 46 deletions(-) diff --git a/gold/ChangeLog b/gold/ChangeLog index ceb6eb3155e..69a4c59c522 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,56 @@ +2011-07-13 Sriraman Tallam + + * archive.cc (Archive::get_elf_object_for_member): Add extra parameter + to claim_file call. + * layout.cc (Layout::Layout): Initialize section_ordering_specified_, + input_section_position_, and input_section_glob_. + (read_layout_from_file): Call function section_ordering_specified. + * layout.h (is_section_ordering_specified): New function. + (section_ordering_specified): New function. + (section_ordering_specified_): New boolean member. + * main.cc(main): Call load_plugins after layout object is defined. + * output.cc (Output_section::add_input_section): Use + function section_ordering_specified to check if section ordering is + needed. + * output.cc (Output_section::add_relaxed_input_section): Use + function section_ordering_specified to check if section ordering is + needed. + (Output_section::update_section_layout): New function. + (Output_section::sort_attached_input_sections): Check if input section + must be reordered. + * output.h (Output_section::update_section_layout): New function. + * plugin.cc (get_section_count): New function. + (get_section_type): New function. + (get_section_name): New function. + (get_section_contents): New function. + (update_section_order): New function. + (allow_section_ordering): New function. + (Plugin::load): Add the new interfaces to the transfer vector. + (Plugin_manager::load_plugins): New parameter. + (Plugin_manager::all_symbols_read): New parameter. + (Plugin_manager::claim_file): New parameter. Save the elf object for + unclaimed objects. + (Plugin_manager::get_elf_object): New function. + (Plugin_manager::get_view): Change to directly use the bool to check + if get_view is called from claim_file_hook. + * plugin.h (input_objects): New function + (Plugin__manager::load_plugins): New parameter. + (Plugin_manager::claim_file): New parameter. + (Plugin_manager::get_elf_object): New function. + (Plugin_manager::in_claim_file_handler): New function. + (Plugin_manager::in_claim_file_handler_): New member. + (layout): New function. + * readsyms.cc (Read_symbols::do_read_symbols): Call the claim_file + handler with an extra parameter. Make the elf object before calling + claim_file handler. + * testsuite/plugin_test.c (get_section_count): New function pointer. + (get_section_type): New function pointer. + (get_section_name): New function pointer. + (get_section_contents): New function pointer. + (update_section_order): New function pointer. + (allow_section_ordering): New function pointer. + (onload): Check if the new interfaces exist. + 2011-07-13 Ian Lance Taylor * i386.cc (Target_i386::got_section): If -z now, make .got.plt a diff --git a/gold/archive.cc b/gold/archive.cc index c3f7b946742..c2e6ff63db2 100644 --- a/gold/archive.cc +++ b/gold/archive.cc @@ -653,7 +653,8 @@ Archive::get_elf_object_for_member(off_t off, bool* punconfigured) { Object* obj = parameters->options().plugins()->claim_file(input_file, memoff, - memsize); + memsize, + NULL); if (obj != NULL) { // The input file was claimed by a plugin, and its symbols diff --git a/gold/layout.cc b/gold/layout.cc index 8cdf1ec71b2..39aabf50e04 100644 --- a/gold/layout.cc +++ b/gold/layout.cc @@ -399,11 +399,14 @@ Layout::Layout(int number_of_input_files, Script_options* script_options) any_postprocessing_sections_(false), resized_signatures_(false), have_stabstr_section_(false), + section_ordering_specified_(false), incremental_inputs_(NULL), record_output_section_data_from_script_(false), script_output_section_data_list_(), segment_states_(NULL), relaxation_debug_check_(NULL), + input_section_position_(), + input_section_glob_(), incremental_base_(NULL), free_list_() { @@ -2209,7 +2212,7 @@ Layout::find_section_order_index(const std::string& section_name) } // Read the sequence of input sections from the file specified with -// --section-ordering-file. +// option --section-ordering-file. void Layout::read_layout_from_file() @@ -2225,6 +2228,7 @@ Layout::read_layout_from_file() std::getline(in, line); // this chops off the trailing \n, if any unsigned int position = 1; + this->set_section_ordering_specified(); while (in) { diff --git a/gold/layout.h b/gold/layout.h index a16bb5ca6b6..f2c170b988a 100644 --- a/gold/layout.h +++ b/gold/layout.h @@ -492,6 +492,14 @@ class Layout const char* name, const elfcpp::Shdr& shdr, unsigned int reloc_shndx, unsigned int reloc_type, off_t* offset); + bool + is_section_ordering_specified() + { return this->section_ordering_specified_; } + + void + set_section_ordering_specified() + { this->section_ordering_specified_ = true; } + // For incremental updates, allocate a block of memory from the // free list. Find a block starting at or after MINOFF. off_t @@ -501,6 +509,8 @@ class Layout unsigned int find_section_order_index(const std::string&); + // Read the sequence of input sections from the file specified with + // linker option --section-ordering-file. void read_layout_from_file(); @@ -1262,6 +1272,9 @@ class Layout bool resized_signatures_; // Whether we have created a .stab*str output section. bool have_stabstr_section_; + // True if the input sections in the output sections should be sorted + // as specified in a section ordering file. + bool section_ordering_specified_; // In incremental build, holds information check the inputs and build the // .gnu_incremental_inputs section. Incremental_inputs* incremental_inputs_; diff --git a/gold/main.cc b/gold/main.cc index 7de1b8779dc..d0f36e7633a 100644 --- a/gold/main.cc +++ b/gold/main.cc @@ -195,10 +195,6 @@ main(int argc, char** argv) if (parameters->options().relocatable()) command_line.script_options().version_script_info()->clear(); - // Load plugin libraries. - if (command_line.options().has_plugins()) - command_line.options().plugins()->load_plugins(); - // The work queue. Workqueue workqueue(command_line.options()); @@ -234,6 +230,10 @@ main(int argc, char** argv) if (parameters->options().section_ordering_file()) layout.read_layout_from_file(); + // Load plugin libraries. + if (command_line.options().has_plugins()) + command_line.options().plugins()->load_plugins(&layout); + // Get the search path from the -L options. Dirsearch search_path; search_path.initialize(&workqueue, &command_line.options().library_path()); diff --git a/gold/output.cc b/gold/output.cc index b72bd8d4768..affc6f7540d 100644 --- a/gold/output.cc +++ b/gold/output.cc @@ -2296,7 +2296,7 @@ Output_section::add_input_section(Layout* layout, && (sh_flags & elfcpp::SHF_EXECINSTR) != 0 && parameters->target().has_code_fill() && (parameters->target().may_relax() - || parameters->options().section_ordering_file())) + || layout->is_section_ordering_specified())) { gold_assert(this->fills_.empty()); this->generate_code_fills_at_write_ = true; @@ -2335,10 +2335,10 @@ Output_section::add_input_section(Layout* layout, || this->must_sort_attached_input_sections() || parameters->options().user_set_Map() || parameters->target().may_relax() - || parameters->options().section_ordering_file()) + || layout->is_section_ordering_specified()) { Input_section isecn(object, shndx, input_section_size, addralign); - if (parameters->options().section_ordering_file()) + if (layout->is_section_ordering_specified()) { unsigned int section_order_index = layout->find_section_order_index(std::string(secname)); @@ -2421,7 +2421,7 @@ Output_section::add_relaxed_input_section(Layout* layout, // If the --section-ordering-file option is used to specify the order of // sections, we need to keep track of sections. - if (parameters->options().section_ordering_file()) + if (layout->is_section_ordering_specified()) { unsigned int section_order_index = layout->find_section_order_index(name); @@ -3339,6 +3339,38 @@ Output_section::Input_section_sort_section_order_index_compare::operator()( return s1_secn_index < s2_secn_index; } +// This updates the section order index of input sections according to the +// the order specified in the mapping from Section id to order index. + +void +Output_section::update_section_layout( + const Section_layout_order& order_map) +{ + for (Input_section_list::iterator p = this->input_sections_.begin(); + p != this->input_sections_.end(); + ++p) + { + if (p->is_input_section() + || p->is_relaxed_input_section()) + { + Object* obj = (p->is_input_section() + ? p->relobj() + : p->relaxed_input_section()->relobj()); + unsigned int shndx = p->shndx(); + Section_layout_order::const_iterator it + = order_map.find(Section_id(obj, shndx)); + if (it == order_map.end()) + continue; + unsigned int section_order_index = it->second; + if (section_order_index != 0) + { + p->set_section_order_index(section_order_index); + this->set_input_section_order_specified(); + } + } + } +} + // Sort the input sections attached to an output section. void @@ -3381,7 +3413,7 @@ Output_section::sort_attached_input_sections() } else { - gold_assert(parameters->options().section_ordering_file()); + gold_assert(this->input_section_order_specified()); std::sort(sort_list.begin(), sort_list.end(), Input_section_sort_section_order_index_compare()); } diff --git a/gold/output.h b/gold/output.h index 7fb87de8097..20869e67075 100644 --- a/gold/output.h +++ b/gold/output.h @@ -2665,6 +2665,11 @@ class Output_section : public Output_data flags() const { return this->flags_; } + typedef std::map Section_layout_order; + + void + update_section_layout(const Section_layout_order& order_map); + // Update the output section flags based on input section flags. void update_flags_for_input_section(elfcpp::Elf_Xword flags); diff --git a/gold/plugin.cc b/gold/plugin.cc index 345df281554..8f6e87f6f56 100644 --- a/gold/plugin.cc +++ b/gold/plugin.cc @@ -89,6 +89,29 @@ set_extra_library_path(const char *path); static enum ld_plugin_status message(int level, const char *format, ...); +static enum ld_plugin_status +get_input_section_count(const void* handle, unsigned int* count); + +static enum ld_plugin_status +get_input_section_type(const struct ld_plugin_section section, + unsigned int* type); + +static enum ld_plugin_status +get_input_section_name(const struct ld_plugin_section section, + char** section_name_ptr); + +static enum ld_plugin_status +get_input_section_contents(const struct ld_plugin_section section, + const unsigned char** section_contents, + size_t* len); + +static enum ld_plugin_status +update_section_order(const struct ld_plugin_section *section_list, + unsigned int num_sections); + +static enum ld_plugin_status +allow_section_ordering(); + }; #endif // ENABLE_PLUGINS @@ -133,7 +156,8 @@ Plugin::load() sscanf(ver, "%d.%d", &major, &minor); // Allocate and populate a transfer vector. - const int tv_fixed_size = 17; + const int tv_fixed_size = 23; + int tv_size = this->args_.size() + tv_fixed_size; ld_plugin_tv* tv = new ld_plugin_tv[tv_size]; @@ -215,6 +239,30 @@ Plugin::load() tv[i].tv_tag = LDPT_SET_EXTRA_LIBRARY_PATH; tv[i].tv_u.tv_set_extra_library_path = set_extra_library_path; + ++i; + tv[i].tv_tag = LDPT_GET_INPUT_SECTION_COUNT; + tv[i].tv_u.tv_get_input_section_count = get_input_section_count; + + ++i; + tv[i].tv_tag = LDPT_GET_INPUT_SECTION_TYPE; + tv[i].tv_u.tv_get_input_section_type = get_input_section_type; + + ++i; + tv[i].tv_tag = LDPT_GET_INPUT_SECTION_NAME; + tv[i].tv_u.tv_get_input_section_name = get_input_section_name; + + ++i; + tv[i].tv_tag = LDPT_GET_INPUT_SECTION_CONTENTS; + tv[i].tv_u.tv_get_input_section_contents = get_input_section_contents; + + ++i; + tv[i].tv_tag = LDPT_UPDATE_SECTION_ORDER; + tv[i].tv_u.tv_update_section_order = update_section_order; + + ++i; + tv[i].tv_tag = LDPT_ALLOW_SECTION_ORDERING; + tv[i].tv_u.tv_allow_section_ordering = allow_section_ordering; + ++i; tv[i].tv_tag = LDPT_NULL; tv[i].tv_u.tv_val = 0; @@ -326,8 +374,9 @@ Plugin_manager::~Plugin_manager() // Load all plugin libraries. void -Plugin_manager::load_plugins() +Plugin_manager::load_plugins(Layout* layout) { + this->layout_ = layout; for (this->current_ = this->plugins_.begin(); this->current_ != this->plugins_.end(); ++this->current_) @@ -338,7 +387,7 @@ Plugin_manager::load_plugins() Pluginobj* Plugin_manager::claim_file(Input_file* input_file, off_t offset, - off_t filesize) + off_t filesize, Object* elf_object) { if (this->in_replacement_phase_) return NULL; @@ -350,6 +399,9 @@ Plugin_manager::claim_file(Input_file* input_file, off_t offset, this->plugin_input_file_.offset = offset; this->plugin_input_file_.filesize = filesize; this->plugin_input_file_.handle = reinterpret_cast(handle); + if (elf_object != NULL) + this->objects_.push_back(elf_object); + this->in_claim_file_handler_ = true; for (this->current_ = this->plugins_.begin(); this->current_ != this->plugins_.end(); @@ -358,9 +410,11 @@ Plugin_manager::claim_file(Input_file* input_file, off_t offset, if ((*this->current_)->claim_file(&this->plugin_input_file_)) { this->any_claimed_ = true; + this->in_claim_file_handler_ = false; - if (this->objects_.size() > handle) - return this->objects_[handle]; + if (this->objects_.size() > handle + && this->objects_[handle]->pluginobj() != NULL) + return this->objects_[handle]->pluginobj(); // If the plugin claimed the file but did not call the // add_symbols callback, we need to create the Pluginobj now. @@ -369,6 +423,7 @@ Plugin_manager::claim_file(Input_file* input_file, off_t offset, } } + this->in_claim_file_handler_ = false; return NULL; } @@ -402,7 +457,7 @@ Plugin_manager::save_input_group(Input_group* input_group) void Plugin_manager::all_symbols_read(Workqueue* workqueue, Task* task, Input_objects* input_objects, - Symbol_table* symtab, Layout* layout, + Symbol_table* symtab, Dirsearch* dirpath, Mapfile* mapfile, Task_token** last_blocker) { @@ -411,7 +466,6 @@ Plugin_manager::all_symbols_read(Workqueue* workqueue, Task* task, this->task_ = task; this->input_objects_ = input_objects; this->symtab_ = symtab; - this->layout_ = layout; this->dirpath_ = dirpath; this->mapfile_ = mapfile; this->this_blocker_ = NULL; @@ -599,12 +653,20 @@ Pluginobj* Plugin_manager::make_plugin_object(unsigned int handle) { // Make sure we aren't asked to make an object for the same handle twice. - if (this->objects_.size() != handle) + if (this->objects_.size() != handle + && this->objects_[handle]->pluginobj() != NULL) return NULL; Pluginobj* obj = make_sized_plugin_object(this->input_file_, this->plugin_input_file_.offset, this->plugin_input_file_.filesize); + + + // If the elf object for this file was pushed into the objects_ vector, delete + // it to make room for the Pluginobj as this file is claimed. + if (this->objects_.size() != handle) + this->objects_.pop_back(); + this->objects_.push_back(obj); return obj; } @@ -616,7 +678,7 @@ ld_plugin_status Plugin_manager::get_input_file(unsigned int handle, struct ld_plugin_input_file* file) { - Pluginobj* obj = this->object(handle); + Pluginobj* obj = this->object(handle)->pluginobj(); if (obj == NULL) return LDPS_BAD_HANDLE; @@ -634,7 +696,11 @@ Plugin_manager::get_input_file(unsigned int handle, ld_plugin_status Plugin_manager::release_input_file(unsigned int handle) { - Pluginobj* obj = this->object(handle); + if (this->object(handle) == NULL) + return LDPS_BAD_HANDLE; + + Pluginobj* obj = this->object(handle)->pluginobj(); + if (obj == NULL) return LDPS_BAD_HANDLE; @@ -642,13 +708,30 @@ Plugin_manager::release_input_file(unsigned int handle) return LDPS_OK; } +// Get the elf object corresponding to the handle. Return NULL if we +// found a Pluginobj instead. + +Object* +Plugin_manager::get_elf_object(const void* handle) +{ + Object* obj = this->object( + static_cast(reinterpret_cast(handle))); + + // The object should not be a Pluginobj. + if (obj == NULL + || obj->pluginobj() != NULL) + return NULL; + + return obj; +} + ld_plugin_status Plugin_manager::get_view(unsigned int handle, const void **viewp) { off_t offset; size_t filesize; Input_file *input_file; - if (this->objects_.size() == handle) + if (this->in_claim_file_handler_) { // We are being called from the claim_file hook. const struct ld_plugin_input_file &f = this->plugin_input_file_; @@ -659,7 +742,9 @@ Plugin_manager::get_view(unsigned int handle, const void **viewp) else { // An already claimed file. - Pluginobj* obj = this->object(handle); + if (this->object(handle) == NULL) + return LDPS_BAD_HANDLE; + Pluginobj* obj = this->object(handle)->pluginobj(); if (obj == NULL) return LDPS_BAD_HANDLE; offset = obj->offset(); @@ -1226,7 +1311,6 @@ Plugin_hook::run(Workqueue* workqueue) this, this->input_objects_, this->symtab_, - this->layout_, this->dirpath_, this->mapfile_, &this->this_blocker_); @@ -1320,11 +1404,14 @@ static enum ld_plugin_status get_symbols(const void* handle, int nsyms, ld_plugin_symbol* syms) { gold_assert(parameters->options().has_plugins()); - Pluginobj* obj = parameters->options().plugins()->object( - static_cast(reinterpret_cast(handle))); + Object* obj = parameters->options().plugins()->object( + static_cast(reinterpret_cast(handle))); if (obj == NULL) return LDPS_ERR; - return obj->get_symbol_resolution_info(nsyms, syms); + Pluginobj* plugin_obj = obj->pluginobj(); + if (plugin_obj == NULL) + return LDPS_ERR; + return plugin_obj->get_symbol_resolution_info(nsyms, syms); } // Add a new (real) input file generated by a plugin. @@ -1384,6 +1471,158 @@ message(int level, const char* format, ...) return LDPS_OK; } +// Get the section count of the object corresponding to the handle. This +// plugin interface can only be called in the claim_file handler of the plugin. + +static enum ld_plugin_status +get_input_section_count(const void* handle, unsigned int* count) +{ + gold_assert(parameters->options().has_plugins()); + + if (!parameters->options().plugins()->in_claim_file_handler()) + return LDPS_ERR; + + Object* obj = parameters->options().plugins()->get_elf_object(handle); + + if (obj == NULL) + return LDPS_ERR; + + *count = obj->shnum(); + return LDPS_OK; +} + +// Get the type of the specified section in the object corresponding +// to the handle. This plugin interface can only be called in the +// claim_file handler of the plugin. + +static enum ld_plugin_status +get_input_section_type(const struct ld_plugin_section section, + unsigned int* type) +{ + gold_assert(parameters->options().has_plugins()); + + if (!parameters->options().plugins()->in_claim_file_handler()) + return LDPS_ERR; + + Object* obj + = parameters->options().plugins()->get_elf_object(section.handle); + + if (obj == NULL) + return LDPS_BAD_HANDLE; + + *type = obj->section_type(section.shndx); + return LDPS_OK; +} + +// Get the name of the specified section in the object corresponding +// to the handle. This plugin interface can only be called in the +// claim_file handler of the plugin. + +static enum ld_plugin_status +get_input_section_name(const struct ld_plugin_section section, + char** section_name_ptr) +{ + gold_assert(parameters->options().has_plugins()); + + if (!parameters->options().plugins()->in_claim_file_handler()) + return LDPS_ERR; + + Object* obj + = parameters->options().plugins()->get_elf_object(section.handle); + + if (obj == NULL) + return LDPS_BAD_HANDLE; + + // Check if the object is locked before getting the section name. + gold_assert(obj->is_locked()); + + const std::string section_name = obj->section_name(section.shndx); + *section_name_ptr = static_cast(malloc(section_name.length() + 1)); + memcpy(*section_name_ptr, section_name.c_str(), section_name.length() + 1); + return LDPS_OK; +} + +// Get the contents of the specified section in the object corresponding +// to the handle. This plugin interface can only be called in the +// claim_file handler of the plugin. + +static enum ld_plugin_status +get_input_section_contents(const struct ld_plugin_section section, + const unsigned char** section_contents_ptr, + size_t* len) +{ + gold_assert(parameters->options().has_plugins()); + + if (!parameters->options().plugins()->in_claim_file_handler()) + return LDPS_ERR; + + Object* obj + = parameters->options().plugins()->get_elf_object(section.handle); + + if (obj == NULL) + return LDPS_BAD_HANDLE; + + // Check if the object is locked before getting the section contents. + gold_assert(obj->is_locked()); + + section_size_type plen; + *section_contents_ptr + = obj->section_contents(section.shndx, &plen, false); + *len = plen; + return LDPS_OK; +} + +// Specify the ordering of sections in the final layout. The sections are +// specified as (handle,shndx) pairs in the two arrays in the order in +// which they should appear in the final layout. + +static enum ld_plugin_status +update_section_order(const struct ld_plugin_section *section_list, + unsigned int num_sections) +{ + gold_assert(parameters->options().has_plugins()); + + if (num_sections == 0) + return LDPS_OK; + + if (section_list == NULL) + return LDPS_ERR; + + std::map order_map; + + for (unsigned int i = 0; i < num_sections; ++i) + { + Object* obj = parameters->options().plugins()->get_elf_object( + section_list[i].handle); + if (obj == NULL) + return LDPS_BAD_HANDLE; + unsigned int shndx = section_list[i].shndx; + Section_id secn_id(obj, shndx); + order_map[secn_id] = i + 1; + } + + Layout* layout = parameters->options().plugins()->layout(); + gold_assert (layout != NULL); + + for (Layout::Section_list::const_iterator p = layout->section_list().begin(); + p != layout->section_list().end(); + ++p) + (*p)->update_section_layout(order_map); + + return LDPS_OK; +} + +// Let the linker know that the sections could be reordered. + +static enum ld_plugin_status +allow_section_ordering() +{ + gold_assert(parameters->options().has_plugins()); + Layout* layout = parameters->options().plugins()->layout(); + layout->set_section_ordering_specified(); + return LDPS_OK; +} + #endif // ENABLE_PLUGINS // Allocate a Pluginobj object of the appropriate size and endianness. diff --git a/gold/plugin.h b/gold/plugin.h index 2ee0b5e8022..8f1db67d288 100644 --- a/gold/plugin.h +++ b/gold/plugin.h @@ -131,6 +131,7 @@ class Plugin_manager : plugins_(), objects_(), deferred_layout_objects_(), input_file_(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_() @@ -153,11 +154,22 @@ 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. @@ -173,7 +185,7 @@ class Plugin_manager void all_symbols_read(Workqueue* workqueue, Task* task, Input_objects* input_objects, Symbol_table* symtab, - Layout* layout, Dirsearch* dirpath, Mapfile* mapfile, + Dirsearch* dirpath, Mapfile* mapfile, Task_token** last_blocker); // Tell the plugin manager that we've a new undefined symbol which @@ -218,8 +230,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()) @@ -265,6 +277,14 @@ class Plugin_manager in_replacement_phase() const { return this->in_replacement_phase_; } + Input_objects* + input_objects() const + { return this->input_objects_; } + + Layout* + layout() + { return this->layout_; } + private: Plugin_manager(const Plugin_manager&); Plugin_manager& operator=(const Plugin_manager&); @@ -293,7 +313,7 @@ class Plugin_manager }; 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; @@ -340,6 +360,9 @@ class Plugin_manager // 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_; diff --git a/gold/readsyms.cc b/gold/readsyms.cc index 574cb729664..1e50942a281 100644 --- a/gold/readsyms.cc +++ b/gold/readsyms.cc @@ -320,12 +320,33 @@ Read_symbols::do_read_symbols(Workqueue* workqueue) } } + Object* elf_obj = NULL; + bool unconfigured; + bool* punconfigured = NULL; + if (is_elf) + { + // This is an ELF object. + + unconfigured = false; + punconfigured = (input_file->will_search_for() + ? &unconfigured + : NULL); + elf_obj = make_elf_object(input_file->filename(), + input_file, 0, ehdr, read_size, + punconfigured); + } + if (parameters->options().has_plugins()) { Pluginobj* obj = parameters->options().plugins()->claim_file(input_file, - 0, filesize); + 0, filesize, + elf_obj); if (obj != NULL) { + // Delete the elf_obj, this file has been claimed. + if (elf_obj != NULL) + delete elf_obj; + // The input file was claimed by a plugin, and its symbols // have been provided by the plugin. @@ -359,14 +380,7 @@ Read_symbols::do_read_symbols(Workqueue* workqueue) { // This is an ELF object. - bool unconfigured = false; - bool* punconfigured = (input_file->will_search_for() - ? &unconfigured - : NULL); - Object* obj = make_elf_object(input_file->filename(), - input_file, 0, ehdr, read_size, - punconfigured); - if (obj == NULL) + if (elf_obj == NULL) { if (unconfigured) { @@ -382,7 +396,7 @@ Read_symbols::do_read_symbols(Workqueue* workqueue) } Read_symbols_data* sd = new Read_symbols_data; - obj->read_symbols(sd); + elf_obj->read_symbols(sd); // Opening the file locked it, so now we need to unlock it. We // need to unlock it before queuing the Add_symbols task, @@ -397,7 +411,7 @@ Read_symbols::do_read_symbols(Workqueue* workqueue) if (this->member_ != NULL) { this->member_->sd_ = sd; - this->member_->obj_ = obj; + this->member_->obj_ = elf_obj; this->member_->arg_serial_ = this->input_argument_->file().arg_serial(); return true; @@ -412,7 +426,7 @@ Read_symbols::do_read_symbols(Workqueue* workqueue) this->dirindex_, this->mapfile_, this->input_argument_, - obj, + elf_obj, NULL, sd, this->this_blocker_, diff --git a/gold/testsuite/plugin_test.c b/gold/testsuite/plugin_test.c index 9d095e88244..619a160ba78 100644 --- a/gold/testsuite/plugin_test.c +++ b/gold/testsuite/plugin_test.c @@ -60,6 +60,12 @@ static ld_plugin_add_input_file add_input_file = NULL; static ld_plugin_message message = NULL; static ld_plugin_get_input_file get_input_file = NULL; static ld_plugin_release_input_file release_input_file = NULL; +static ld_plugin_get_input_section_count get_input_section_count = NULL; +static ld_plugin_get_input_section_type get_input_section_type = NULL; +static ld_plugin_get_input_section_name get_input_section_name = NULL; +static ld_plugin_get_input_section_contents get_input_section_contents = NULL; +static ld_plugin_update_section_order update_section_order = NULL; +static ld_plugin_allow_section_ordering allow_section_ordering = NULL; #define MAXOPTS 10 @@ -126,6 +132,24 @@ onload(struct ld_plugin_tv *tv) case LDPT_RELEASE_INPUT_FILE: release_input_file = entry->tv_u.tv_release_input_file; break; + case LDPT_GET_INPUT_SECTION_COUNT: + get_input_section_count = *entry->tv_u.tv_get_input_section_count; + break; + case LDPT_GET_INPUT_SECTION_TYPE: + get_input_section_type = *entry->tv_u.tv_get_input_section_type; + break; + case LDPT_GET_INPUT_SECTION_NAME: + get_input_section_name = *entry->tv_u.tv_get_input_section_name; + break; + case LDPT_GET_INPUT_SECTION_CONTENTS: + get_input_section_contents = *entry->tv_u.tv_get_input_section_contents; + break; + case LDPT_UPDATE_SECTION_ORDER: + update_section_order = *entry->tv_u.tv_update_section_order; + break; + case LDPT_ALLOW_SECTION_ORDERING: + allow_section_ordering = *entry->tv_u.tv_allow_section_ordering; + break; default: break; } @@ -179,6 +203,42 @@ onload(struct ld_plugin_tv *tv) return LDPS_ERR; } + if (get_input_section_count == NULL) + { + fprintf(stderr, "tv_get_input_section_count interface missing\n"); + return LDPS_ERR; + } + + if (get_input_section_type == NULL) + { + fprintf(stderr, "tv_get_input_section_type interface missing\n"); + return LDPS_ERR; + } + + if (get_input_section_name == NULL) + { + fprintf(stderr, "tv_get_input_section_name interface missing\n"); + return LDPS_ERR; + } + + if (get_input_section_contents == NULL) + { + fprintf(stderr, "tv_get_input_section_contents interface missing\n"); + return LDPS_ERR; + } + + if (update_section_order == NULL) + { + fprintf(stderr, "tv_update_section_order interface missing\n"); + return LDPS_ERR; + } + + if (allow_section_ordering == NULL) + { + fprintf(stderr, "tv_allow_section_ordering interface missing\n"); + return LDPS_ERR; + } + return LDPS_OK; } diff --git a/include/ChangeLog b/include/ChangeLog index 2a62d3f579b..7a4f83fc1ea 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,26 @@ +2011-07-13 Sriraman Tallam + + * plugin-api.h + (ld_plugin_section): New struct. + (ld_plugin_get_section_count): New typedef. + (ld_plugin_get_section_type): New typedef. + (ld_plugin_get_section_name): New typedef. + (ld_plugin_get_section_contents): New typedef. + (ld_plugin_update_section_order): New typedef. + (ld_plugin_allow_section_ordering): New typedef. + (LDPT_GET_SECTION_COUNT): New enum value. + (LDPT_GET_SECTION_TYPE): New enum value. + (LDPT_GET_SECTION_NAME): New enum value. + (LDPT_GET_SECTION_CONTENTS): New enum value. + (LDPT_UPDATE_SECTION_ORDER): New enum value. + (LDPT_ALLOW_SECTION_ORDERING): New enum value. + (tv_get_section_count): New struct members. + (tv_get_section_type): New struct members. + (tv_get_section_name): New struct members. + (tv_get_section_contents): New struct members. + (tv_update_section_order): New struct members. + (tv_allow_section_ordering): New struct members. + 2011-07-11 Catherine Moore * bfdlink.h (flag_type): New enumeration. diff --git a/include/plugin-api.h b/include/plugin-api.h index 7450a9e3838..df0039372f3 100644 --- a/include/plugin-api.h +++ b/include/plugin-api.h @@ -93,6 +93,14 @@ struct ld_plugin_symbol int resolution; }; +/* An object's section. */ + +struct ld_plugin_section +{ + const void* handle; + unsigned int shndx; +}; + /* Whether the symbol is a definition, reference, or common, weak or not. */ enum ld_plugin_symbol_kind @@ -244,6 +252,65 @@ typedef enum ld_plugin_status (*ld_plugin_message) (int level, const char *format, ...); +/* The linker's interface for retrieving the number of sections in an object. + The handle is obtained in the claim_file handler. This interface should + only be invoked in the claim_file handler. This function sets *COUNT to + the number of sections in the object. */ + +typedef +enum ld_plugin_status +(*ld_plugin_get_input_section_count) (const void* handle, unsigned int *count); + +/* The linker's interface for retrieving the section type of a specific + section in an object. This interface should only be invoked in the + claim_file handler. This function sets *TYPE to an ELF SHT_xxx value. */ + +typedef +enum ld_plugin_status +(*ld_plugin_get_input_section_type) (const struct ld_plugin_section section, + unsigned int *type); + +/* The linker's interface for retrieving the name of a specific section in + an object. This interface should only be invoked in the claim_file handler. + This function sets *SECTION_NAME_PTR to a null-terminated buffer allocated + by malloc. The plugin must free *SECTION_NAME_PTR. */ + +typedef +enum ld_plugin_status +(*ld_plugin_get_input_section_name) (const struct ld_plugin_section section, + char **section_name_ptr); + +/* The linker's interface for retrieving the contents of a specific section + in an object. This interface should only be invoked in the claim_file + handler. This function sets *SECTION_CONTENTS to point to a buffer that is + valid until clam_file handler returns. It sets *LEN to the size of the + buffer. */ + +typedef +enum ld_plugin_status +(*ld_plugin_get_input_section_contents) (const struct ld_plugin_section section, + const unsigned char **section_contents, + size_t* len); + +/* The linker's interface for specifying the desired order of sections. + The sections should be specifed using the array SECTION_LIST in the + order in which they should appear in the final layout. NUM_SECTIONS + specifies the number of entries in each array. This should be invoked + in the all_symbols_read handler. */ + +typedef +enum ld_plugin_status +(*ld_plugin_update_section_order) (const struct ld_plugin_section *section_list, + unsigned int num_sections); + +/* The linker's interface for specifying that reordering of sections is + desired so that the linker can prepare for it. This should be invoked + before update_section_order, preferably in the claim_file handler. */ + +typedef +enum ld_plugin_status +(*ld_plugin_allow_section_ordering) (void); + enum ld_plugin_level { LDPL_INFO, @@ -274,7 +341,13 @@ enum ld_plugin_tag LDPT_OUTPUT_NAME, LDPT_SET_EXTRA_LIBRARY_PATH, LDPT_GNU_LD_VERSION, - LDPT_GET_VIEW + LDPT_GET_VIEW, + LDPT_GET_INPUT_SECTION_COUNT, + LDPT_GET_INPUT_SECTION_TYPE, + LDPT_GET_INPUT_SECTION_NAME, + LDPT_GET_INPUT_SECTION_CONTENTS, + LDPT_UPDATE_SECTION_ORDER, + LDPT_ALLOW_SECTION_ORDERING }; /* The plugin transfer vector. */ @@ -298,6 +371,12 @@ struct ld_plugin_tv ld_plugin_release_input_file tv_release_input_file; ld_plugin_add_input_library tv_add_input_library; ld_plugin_set_extra_library_path tv_set_extra_library_path; + ld_plugin_get_input_section_count tv_get_input_section_count; + ld_plugin_get_input_section_type tv_get_input_section_type; + ld_plugin_get_input_section_name tv_get_input_section_name; + ld_plugin_get_input_section_contents tv_get_input_section_contents; + ld_plugin_update_section_order tv_update_section_order; + ld_plugin_allow_section_ordering tv_allow_section_ordering; } tv_u; }; -- 2.30.2