aboutsummaryrefslogtreecommitdiff
path: root/gold/plugin.cc
diff options
context:
space:
mode:
authorSriraman Tallam <tmsriram@google.com>2011-07-14 00:55:18 +0000
committerSriraman Tallam <tmsriram@google.com>2011-07-14 00:55:18 +0000
commite9552f7ebbcd2438fe50dbf1fb4b1926c96adb75 (patch)
tree3011912bed63e6f4668b55cafab0fd7c3efcc1e5 /gold/plugin.cc
parent41d1d0bd9b0e58444eb9abedcf8bc02c78deaced (diff)
downloadgdb-e9552f7ebbcd2438fe50dbf1fb4b1926c96adb75.zip
gdb-e9552f7ebbcd2438fe50dbf1fb4b1926c96adb75.tar.gz
gdb-e9552f7ebbcd2438fe50dbf1fb4b1926c96adb75.tar.bz2
2011-07-13 Sriraman Tallam <tmsriram@google.com>
* 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.
Diffstat (limited to 'gold/plugin.cc')
-rw-r--r--gold/plugin.cc271
1 files changed, 255 insertions, 16 deletions
diff --git a/gold/plugin.cc b/gold/plugin.cc
index 345df28..8f6e87f 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];
@@ -216,6 +240,30 @@ Plugin::load()
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<void*>(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<unsigned int>(reinterpret_cast<intptr_t>(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<unsigned int>(reinterpret_cast<intptr_t>(handle)));
+ Object* obj = parameters->options().plugins()->object(
+ static_cast<unsigned int>(reinterpret_cast<intptr_t>(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<char*>(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<Section_id, unsigned int> 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.