Plugin interfaces to do Pettis Hansen style code layout in the gold linker.
Sriraman Tallam
tmsriram@google.com
Sun Mar 13 02:37:00 GMT 2011
Hi Cary,
Like we discussed, I made all the changes. I now have a separate
list of unclaimed objects in the Plugin manager and the handle will be
an index into it. I have also added a new hook called
"inspect_unclaimed_object". This handler allows the plugin to examine
the contents of an unclaimed object. Now, I have disallowed examining
claimed objects here as the methods to get their contents etc. are not
defined in Pluginobj. Also, I have kept the original interfaces to get
section count or type or contents. I think I would need this interface
for my work rather than only get contents based on filters. I guess
more interfaces can be added easily.
Thanks,
-Sri.
Change Log for plugin-api.h
* plugin-api.h
(ld_plugin_inspect_unclaimed_object_handler): New typedef.
(ld_plugin_register_inspect_unclaimed_object): New typedef.
(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_read_layout_from_file): New typedef.
(ld_plugin_allow_section_ordering): New typedef.
(LDPT_REGISTER_INSPECT_UNCLAIMED_OBJECT_HOOK): New enum value.
(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_READ_LAYOUT_FROM_FILE): 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_read_layout_from_file): New struct members.
(tv_allow_section_ordering): New struct members.
ChangeLog for gold:
* layout.cc (Layout::Layout): Initialize section_ordering_specified_,
input_section_position_, and input_section_glob_.
(Layout::update_layout_of_sections): New function.
(read_layout_from_file): Add parameter filename and call function
section_ordering_specified.
* layout.h (is_section_ordering_specified): New function.
(section_ordering_specified): New function.
(read_layout_from_file): Add parameter filename.
(update_layout_of_sections): New function.
(section_ordering_specified_): New boolean member.
* main.cc(main): Call load_plugins after layout object is defined.
Call read_layout_from_file when section ordering is specified.
* output.cc (Output_section::add_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 (register_inspect_unclaimed_object): New function.
(get_section_count): New function.
(get_section_type): New function.
(get_section_name): New function.
(get_section_contents): New function.
(read_layout_from_file): New function.
(allow_section_ordering): New function.
(Plugin::inspect_unclaimed_object): New function.
(Plugin_manager::inspect_unclaimed_object): New function.
(Plugin_manager::get_unclaimed_object): New function.
(Plugin::load): Add the new interfaces to the transfer vector.
(Plugin_manager::load_plugins): New parameter.
* plugin.h (input_objects): New function
(Plugin::inspect_unclaimed_object): New function.
(Plugin::set_inspect_unclaimed_object_handler): New function.
(Plugin__manager::load_plugins): New parameter.
(Plugin_manager::inspect_unclaimed_object): New function.
(Plugin_manager::get_unclaimed_object): New function.
(Plugin_manager::in_inspect_unclaimed_object_handler): New function.
(Plugin_manager::set_inspect_unclaimed_object_handler): New function.
(Plugin_manager::unclaimed_object): New function.
(Plugin_manager::Unclaimed_object_list): New typedef.
(Plugin_manager::unclaimed_objects_): New member.
(Plugin_manager::in_inspect_unclaimed_object_handler_): New member.
(layout): New function.
* readsyms.cc (Read_symbols::do_read_symbols): Call the plugin handler.
* testsuite/plugin_test.c (register_inspect_unclaimed_object_hook):
New function pointer.
(get_section_count): New function pointer.
(get_section_type): New function pointer.
(get_section_name): New function pointer.
(get_section_contents): New function pointer.
(read_layout_from_file): New function pointer.
(allow_section_ordering): New function pointer.
(inspect_unclaimed_object_hook): New function.
(onload): Check if the new interfaces exist.
On Wed, Mar 9, 2011 at 4:40 PM, Cary Coutant <ccoutant@google.com> wrote:
> Here are my comments on your patch. Thanks for working on this -- I
> think it's going to be valuable.
>
> -cary
>
>
>
> Index: plugin-api.h
> ===================================================================
>
> You'll need a separate ChangeLog entry for include/. Also, we use
> C-style coding conventions in include/plugin-api.h. In particular,
> "char* filename" should be "char *filename", etc.
>
> +/* The linker's interface for retrieving the handle (pointer) to an object. */
> +
> +typedef
> +enum ld_plugin_status
> +(*ld_plugin_get_object_handle) (const char* filename, void** handle);
>
> I'm curious how this interface is going to be used. Where does the
> plugin obtain a filename where it doesn't already have a handle? Are
> you going to claim the files, or merely observe them and pass them
> through unclaimed? If this is the case, why not just keep a list of
> the handles in your plugin, and arrange for the handles to remain
> valid even for unclaimed files (in the current plugin architecture,
> the handle is just an index into the list of claimed files)?
>
> +typedef
> +enum ld_plugin_status
> +(*ld_plugin_get_section_name) (void* handle, unsigned int shndx,
> + char** section_name_ptr);
> +/* The linker's interface for retrieving the contents of a specific section
> + in an object. */
>
> Missing blank line before this comment.
>
> +/* The linker's interface for specifying the desired order of sections
> + through a file. */
> +
> +typedef
> +enum ld_plugin_status
> +(*ld_plugin_read_layout_from_file) (const char* filename);
> +
> +/* The linker's interface for specifying that reordering of sections is
> + desired. */
> +
> +typedef
> +enum ld_plugin_status
> +(*ld_plugin_allow_section_ordering) (void);
>
> Why do we need both of these interfaces? Couldn't
> read_layout_from_file imply allow_section_ordering?
>
> Index: layout.cc
> ===================================================================
> + relaxation_debug_check_(NULL),
> + section_ordering_specified_(false),
> + input_section_position_(),
> + input_section_glob_()
> +
>
> Extra blank line here.
>
> + if ((*p) == NULL)
> + continue;
> + (*p)->update_section_layout(this);
>
> This could just be:
>
> + if ((*p) != NULL)
> + (*p)->update_section_layout(this);
>
> Index: layout.h
> ===================================================================
>
> + bool
> + is_section_ordering_specified()
> + { return section_ordering_specified_; }
> +
> + void
> + section_ordering_specified()
> + { section_ordering_specified_ = true; }
> +
> +
>
> Extra blank line here.
>
> unsigned int
> find_section_order_index(const std::string&);
>
> + void
> + read_layout_from_file(const char* filename);
> +
> void
> + update_layout_of_sections();
>
> These functions should all have comments.
>
> + bool section_ordering_specified_;
>
> Need a comment here, too.
>
> Index: main.cc
> ===================================================================
>
> + const char* section_ordering_file =
> parameters->options().section_ordering_file();
>
> Line too long.
>
> Index: output.cc
> ===================================================================
>
> + Object* obj = ((*p).is_input_section() ? (*p).relobj()
> + : (*p).relaxed_input_section()->relobj());
>
> I'd prefer to see this written like this:
>
> + Object* obj = ((*p).is_input_section()
> + ? (*p).relobj()
> + : (*p).relaxed_input_section()->relobj());
>
> + std::string section_name = obj->section_name((*p).shndx());
> + unsigned int section_order_index =
> + layout->find_section_order_index(std::string(section_name));
>
> section_name is already a string here -- no conversion necessary.
>
> Index: plugin.cc
> ===================================================================
>
> @@ -404,7 +458,7 @@ Plugin_manager::all_symbols_read(Workque
> - this->layout_ = layout;
> + gold_assert (this->layout_ == layout);
>
> Why not just drop layout from the parameter list for all_symbols_read?
>
> +// Find the object having the given name.
> +// Parameters :
> +// FILENAME : The name of the object whose handle needs to be
> +// retrieved.
> +// HANDLE : Storage for the retrieved handle.
>
> This comment formatting style doesn't match the rest of the file (or
> anywhere else in gold, except for icf.cc). I don't need to see it
> changed, though -- I'm not sure about Ian's preferences.
>
> + if (input_objects == NULL)
> + {
> + return LDPS_ERR;
> + }
>
> Excessive use of braces?
>
>
> + if (strcmp((*p)->name().c_str(), filename) == 0)
> + {
> + *handle = static_cast<void*>(*p);
> + break;
> + }
>
> You could just return LDPS_OK here, and return LDPS_ERR
> unconditionally below the loop.
>
> The handle returned here is very different from the handle returned by
> the existing set of interfaces, and you don't seem to do anything to
> tell them apart; this effectively makes it two separate and
> non-interoperable APIs. There also isn't any way for the linker side
> of the plugin interface to do a sanity check on the handle given it.
> I'd suggest keeping the notion of handle as an index into a list of
> objects, but extend that list to cover all objects rather than just
> the claimed ones.
>
> +static enum ld_plugin_status
> +get_section_type(void* handle, unsigned int shndx, unsigned int* type)
>
> +static enum ld_plugin_status
> +get_section_name(void* handle, unsigned int shndx, char** section_name_ptr)
>
> It's looking like you intend for the plugin to iterate over the
> sections one at a time, looking for a section by either type or name,
> or both. Depending on how you intend to actually use this (and keeping
> in mind generality for other potential uses), it might be better to
> replace these two interfaces with a single one that can find a section
> filtered by type, name, or both (with a provision for iterating
> through multiple results).
>
> Also note that the section_type() and section_name() object methods go
> to a File_view, and you need a task lock in order to call them (else
> you'll get a file descriptor leak). When during the link do you expect
> these interfaces to be used? If it's only from the claim-file handler,
> it should be OK, but if it's from the all-files-read handler, this is
> going to re-open the files. There should be some check in place to
> ensure it's called only when it's designed to be called.
>
-------------- next part --------------
Index: layout.cc
===================================================================
RCS file: /cvs/src/src/gold/layout.cc,v
retrieving revision 1.190
diff -u -u -p -r1.190 layout.cc
--- layout.cc 10 Jan 2011 21:57:31 -0000 1.190
+++ layout.cc 13 Mar 2011 02:31:36 -0000
@@ -207,7 +207,10 @@ Layout::Layout(int number_of_input_files
record_output_section_data_from_script_(false),
script_output_section_data_list_(),
segment_states_(NULL),
- relaxation_debug_check_(NULL)
+ relaxation_debug_check_(NULL),
+ section_ordering_specified_(false),
+ input_section_position_(),
+ input_section_glob_()
{
// Make space for more than enough segments for a typical file.
// This is just for efficiency--it's OK if we wind up needing more.
@@ -1817,13 +1820,28 @@ Layout::find_section_order_index(const s
return 0;
}
+// Updates the input section order of all output sections. This
+// is called when the section order is specified via plugins.
+
+void
+Layout::update_layout_of_sections()
+{
+ for (Section_list::iterator p = this->section_list_.begin();
+ p != this->section_list_.end();
+ ++p)
+ {
+ if ((*p) == NULL)
+ continue;
+ (*p)->update_section_layout(this);
+ }
+}
+
// Read the sequence of input sections from the file specified with
-// --section-ordering-file.
+// linker option --section-ordering-file.
void
-Layout::read_layout_from_file()
+Layout::read_layout_from_file(const char* filename)
{
- const char* filename = parameters->options().section_ordering_file();
std::ifstream in;
std::string line;
@@ -1834,6 +1852,7 @@ Layout::read_layout_from_file()
std::getline(in, line); // this chops off the trailing \n, if any
unsigned int position = 1;
+ this->section_ordering_specified();
while (in)
{
Index: layout.h
===================================================================
RCS file: /cvs/src/src/gold/layout.h,v
retrieving revision 1.88
diff -u -u -p -r1.88 layout.h
--- layout.h 14 Dec 2010 19:03:30 -0000 1.88
+++ layout.h 13 Mar 2011 02:31:36 -0000
@@ -414,11 +414,25 @@ class Layout
const char* name, const elfcpp::Shdr<size, big_endian>& shdr,
unsigned int reloc_shndx, unsigned int reloc_type, off_t* offset);
+ bool
+ is_section_ordering_specified()
+ { return section_ordering_specified_; }
+
+ void
+ section_ordering_specified()
+ { section_ordering_specified_ = true; }
+
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(const char* filename);
+
+ // Updates the order of input sections in the output sections.
void
- read_layout_from_file();
+ update_layout_of_sections();
// Layout an input reloc section when doing a relocatable link. The
// section is RELOC_SHNDX in OBJECT, with data in SHDR.
@@ -1147,6 +1161,9 @@ class Layout
Segment_states* segment_states_;
// A relaxation debug checker. We only create one when in debugging mode.
Relaxation_debug_check* relaxation_debug_check_;
+ // True if the input sections in the output sections should be sorted
+ // as specified in a section ordering file.
+ bool section_ordering_specified_;
// Hash a pattern to its position in the section ordering file.
Unordered_map<std::string, unsigned int> input_section_position_;
// Vector of glob only patterns in the section_ordering file.
Index: main.cc
===================================================================
RCS file: /cvs/src/src/gold/main.cc,v
retrieving revision 1.42
diff -u -u -p -r1.42 main.cc
--- main.cc 14 Dec 2010 19:03:30 -0000 1.42
+++ main.cc 13 Mar 2011 02:31:36 -0000
@@ -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());
@@ -231,8 +227,14 @@ main(int argc, char** argv)
if (layout.incremental_inputs() != NULL)
layout.incremental_inputs()->report_command_line(argc, 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);
+
+ const char* section_ordering_file
+ = parameters->options().section_ordering_file();
+ if (section_ordering_file)
+ layout.read_layout_from_file(section_ordering_file);
// Get the search path from the -L options.
Dirsearch search_path;
Index: output.cc
===================================================================
RCS file: /cvs/src/src/gold/output.cc,v
retrieving revision 1.140
diff -u -u -p -r1.140 output.cc
--- output.cc 12 Feb 2011 03:19:24 -0000 1.140
+++ output.cc 13 Mar 2011 02:31:36 -0000
@@ -2165,10 +2165,10 @@ Output_section::add_input_section(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));
@@ -3041,6 +3041,34 @@ Output_section::Input_section_sort_secti
return s1_secn_index < s2_secn_index;
}
+// Updates the ordering of input sections in this output section.
+
+void
+Output_section::update_section_layout(Layout* layout)
+{
+ 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());
+
+ std::string section_name = obj->section_name((*p).shndx());
+ unsigned int section_order_index =
+ layout->find_section_order_index(section_name);
+ 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
@@ -3083,7 +3111,7 @@ Output_section::sort_attached_input_sect
}
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());
}
Index: output.h
===================================================================
RCS file: /cvs/src/src/gold/output.h,v
retrieving revision 1.118
diff -u -u -p -r1.118 output.h
--- output.h 23 Dec 2010 19:56:14 -0000 1.118
+++ output.h 13 Mar 2011 02:31:36 -0000
@@ -2564,6 +2564,9 @@ class Output_section : public Output_dat
flags() const
{ return this->flags_; }
+ void
+ update_section_layout(Layout* layout);
+
// Update the output section flags based on input section flags.
void
update_flags_for_input_section(elfcpp::Elf_Xword flags);
Index: plugin.cc
===================================================================
RCS file: /cvs/src/src/gold/plugin.cc,v
retrieving revision 1.43
diff -u -u -p -r1.43 plugin.cc
--- plugin.cc 8 Feb 2011 05:03:19 -0000 1.43
+++ plugin.cc 13 Mar 2011 02:31:36 -0000
@@ -57,6 +57,9 @@ static enum ld_plugin_status
register_claim_file(ld_plugin_claim_file_handler handler);
static enum ld_plugin_status
+register_inspect_unclaimed_object(ld_plugin_inspect_unclaimed_object_handler handler);
+
+static enum ld_plugin_status
register_all_symbols_read(ld_plugin_all_symbols_read_handler handler);
static enum ld_plugin_status
@@ -86,6 +89,28 @@ set_extra_library_path(const char *path)
static enum ld_plugin_status
message(int level, const char *format, ...);
+static enum ld_plugin_status
+get_section_count(const void* handle, unsigned int* count);
+
+static enum ld_plugin_status
+get_section_type(void* handle, unsigned int shndx,
+ unsigned int* type);
+
+static enum ld_plugin_status
+get_section_name(void* handle, unsigned int shndx,
+ char** section_name_ptr);
+
+static enum ld_plugin_status
+get_section_contents(void* handle, unsigned int shndx,
+ unsigned char** section_contents,
+ unsigned int* len);
+
+static enum ld_plugin_status
+read_layout_from_file(const char* filename);
+
+static enum ld_plugin_status
+allow_section_ordering();
+
};
#endif // ENABLE_PLUGINS
@@ -130,7 +155,7 @@ Plugin::load()
sscanf(ver, "%d.%d", &major, &minor);
// Allocate and populate a transfer vector.
- const int tv_fixed_size = 16;
+ 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];
@@ -173,6 +198,11 @@ Plugin::load()
tv[i].tv_u.tv_register_claim_file = register_claim_file;
++i;
+ tv[i].tv_tag = LDPT_REGISTER_INSPECT_UNCLAIMED_OBJECT_HOOK;
+ tv[i].tv_u.tv_register_inspect_unclaimed_object
+ = register_inspect_unclaimed_object;
+
+ ++i;
tv[i].tv_tag = LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK;
tv[i].tv_u.tv_register_all_symbols_read = register_all_symbols_read;
@@ -209,6 +239,30 @@ Plugin::load()
tv[i].tv_u.tv_set_extra_library_path = set_extra_library_path;
++i;
+ tv[i].tv_tag = LDPT_GET_SECTION_COUNT;
+ tv[i].tv_u.tv_get_section_count = get_section_count;
+
+ ++i;
+ tv[i].tv_tag = LDPT_GET_SECTION_TYPE;
+ tv[i].tv_u.tv_get_section_type = get_section_type;
+
+ ++i;
+ tv[i].tv_tag = LDPT_GET_SECTION_NAME;
+ tv[i].tv_u.tv_get_section_name = get_section_name;
+
+ ++i;
+ tv[i].tv_tag = LDPT_GET_SECTION_CONTENTS;
+ tv[i].tv_u.tv_get_section_contents = get_section_contents;
+
+ ++i;
+ tv[i].tv_tag = LDPT_READ_LAYOUT_FROM_FILE;
+ tv[i].tv_u.tv_read_layout_from_file = read_layout_from_file;
+
+ ++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;
@@ -237,6 +291,16 @@ Plugin::claim_file(struct ld_plugin_inpu
return false;
}
+// Call the plugin inspect_unclaimed_object handler.
+
+inline void
+Plugin::inspect_unclaimed_object(unsigned int index)
+{
+ void* handle = reinterpret_cast<void*>(index);
+ if (this->inspect_unclaimed_object_handler_ != NULL)
+ (*this->inspect_unclaimed_object_handler_)(handle);
+}
+
// Call the all-symbols-read handler.
inline void
@@ -319,8 +383,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_)
@@ -365,6 +430,27 @@ Plugin_manager::claim_file(Input_file* i
return NULL;
}
+// Call the plugin inspect_unclaimed_object handlers to allow them to inspect
+// the unclaimed object. Pass the handle of the object which is the index
+// into the vector containing the unclaimed objects.
+
+void
+Plugin_manager::inspect_unclaimed_object(Object* obj)
+{
+ unsigned int index;
+ index = this->unclaimed_objects_.size();
+ this->unclaimed_objects_.push_back(obj);
+
+ this->in_inspect_unclaimed_object_handler_ = true;
+
+ for (this->current_ = this->plugins_.begin();
+ this->current_ != this->plugins_.end();
+ ++this->current_)
+ (*this->current_)->inspect_unclaimed_object(index);
+
+ this->in_inspect_unclaimed_object_handler_ = false;
+}
+
// Save an archive. This is used so that a plugin can add a file
// which refers to a symbol which was not previously referenced. In
// that case we want to pretend that the symbol was referenced before,
@@ -395,7 +481,7 @@ Plugin_manager::save_input_group(Input_g
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)
{
@@ -404,7 +490,6 @@ Plugin_manager::all_symbols_read(Workque
this->task_ = task;
this->input_objects_ = input_objects;
this->symtab_ = symtab;
- this->layout_ = layout;
this->dirpath_ = dirpath;
this->mapfile_ = mapfile;
this->this_blocker_ = NULL;
@@ -635,6 +720,20 @@ Plugin_manager::release_input_file(unsig
return LDPS_OK;
}
+// Get the object from the list of unclaimed objects with
+// index specified in handle.
+
+Object*
+Plugin_manager::get_unclaimed_object(const void* handle)
+{
+ unsigned int index = static_cast<unsigned int>(reinterpret_cast<intptr_t>(handle));
+ Object* obj = NULL;
+
+ obj = parameters->options().plugins()->unclaimed_object(index);
+
+ return obj;
+}
+
// Add a new library path.
ld_plugin_status
@@ -1168,7 +1267,6 @@ Plugin_hook::run(Workqueue* workqueue)
this,
this->input_objects_,
this->symtab_,
- this->layout_,
this->dirpath_,
this->mapfile_,
&this->this_blocker_);
@@ -1190,6 +1288,18 @@ register_claim_file(ld_plugin_claim_file
return LDPS_OK;
}
+//Register a inspect_unclaimed_object handler.
+
+static enum ld_plugin_status
+register_inspect_unclaimed_object
+ (ld_plugin_inspect_unclaimed_object_handler handler)
+{
+ gold_assert(parameters->options().has_plugins());
+ parameters->options().plugins()->set_inspect_unclaimed_object_handler(
+ handler);
+ return LDPS_OK;
+}
+
// Register an all-symbols-read handler.
static enum ld_plugin_status
@@ -1317,6 +1427,123 @@ 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 inspect_unclaimed_object
+// handler of the plugin.
+
+static enum ld_plugin_status
+get_section_count(const void* handle, unsigned int* count)
+{
+ gold_assert(parameters->options().has_plugins());
+
+ if (!parameters->options().plugins()->in_inspect_unclaimed_object_handler())
+ return LDPS_ERR;
+
+ Object* obj = parameters->options().plugins()->get_unclaimed_object(handle);
+
+ if (obj == NULL)
+ return LDPS_BAD_HANDLE;
+
+ *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
+// inspect_unclaimed_object handler of the plugin.
+
+static enum ld_plugin_status
+get_section_type(void* handle, unsigned int shndx, unsigned int* type)
+{
+ gold_assert(parameters->options().has_plugins());
+
+ if (!parameters->options().plugins()->in_inspect_unclaimed_object_handler())
+ return LDPS_ERR;
+
+ Object* obj = parameters->options().plugins()->get_unclaimed_object(handle);
+
+ if (obj == NULL)
+ return LDPS_BAD_HANDLE;
+
+ *type = obj->section_type(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
+// inspect_unclaimed_object handler of the plugin.
+
+static enum ld_plugin_status
+get_section_name(void* handle, unsigned int shndx, char** section_name_ptr)
+{
+ gold_assert(parameters->options().has_plugins());
+
+ if (!parameters->options().plugins()->in_inspect_unclaimed_object_handler())
+ return LDPS_ERR;
+
+ Object* obj = parameters->options().plugins()->get_unclaimed_object(handle);
+
+ if (obj == NULL)
+ return LDPS_BAD_HANDLE;
+
+ const char* section_name = obj->section_name(shndx).c_str();
+ *section_name_ptr = (char*)malloc(strlen(section_name) + 1);
+ strcpy(*section_name_ptr, section_name);
+ 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
+// inspect_unclaimed_object handler of the plugin.
+
+static enum ld_plugin_status
+get_section_contents(void* handle, unsigned int shndx,
+ unsigned char** section_contents_ptr,
+ unsigned int* len)
+{
+ gold_assert(parameters->options().has_plugins());
+
+ if (!parameters->options().plugins()->in_inspect_unclaimed_object_handler())
+ return LDPS_ERR;
+
+ Object* obj = parameters->options().plugins()->get_unclaimed_object(handle);
+
+ if (obj == NULL)
+ return LDPS_BAD_HANDLE;
+
+ section_size_type plen;
+ const unsigned char* section_contents = obj->section_contents(shndx, &plen,
+ false);
+ *section_contents_ptr = (unsigned char*)malloc(plen);
+ memcpy(*section_contents_ptr, section_contents, plen);
+ *len = plen;
+ return LDPS_OK;
+}
+
+// Specify the ordering of sections in the final layout in a file. This
+// does what the linker option --section-ordering-file does.
+
+static enum ld_plugin_status
+read_layout_from_file(const char* filename)
+{
+ gold_assert(parameters->options().has_plugins());
+ Layout* layout = parameters->options().plugins()->layout();
+ layout->read_layout_from_file(filename);
+ layout->update_layout_of_sections();
+ 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->section_ordering_specified();
+ return LDPS_OK;
+}
+
#endif // ENABLE_PLUGINS
// Allocate a Pluginobj object of the appropriate size and endianness.
Index: plugin.h
===================================================================
RCS file: /cvs/src/src/gold/plugin.h,v
retrieving revision 1.16
diff -u -u -p -r1.16 plugin.h
--- plugin.h 24 Jan 2011 21:48:40 -0000 1.16
+++ plugin.h 13 Mar 2011 02:31:36 -0000
@@ -58,6 +58,7 @@ class Plugin
filename_(filename),
args_(),
claim_file_handler_(NULL),
+ inspect_unclaimed_object_handler_(NULL),
all_symbols_read_handler_(NULL),
cleanup_handler_(NULL),
cleanup_done_(false)
@@ -74,6 +75,10 @@ class Plugin
bool
claim_file(struct ld_plugin_input_file* plugin_input_file);
+ // Call the inspect_unclaimed_object handler.
+ void
+ inspect_unclaimed_object(unsigned int index);
+
// Call the all-symbols-read handler.
void
all_symbols_read();
@@ -87,6 +92,12 @@ class Plugin
set_claim_file_handler(ld_plugin_claim_file_handler handler)
{ this->claim_file_handler_ = handler; }
+ // Register a inspect_unclaimed_object handler.
+ void
+ set_inspect_unclaimed_object_handler
+ (ld_plugin_inspect_unclaimed_object_handler handler)
+ { this->inspect_unclaimed_object_handler_ = handler; }
+
// Register an all-symbols-read handler.
void
set_all_symbols_read_handler(ld_plugin_all_symbols_read_handler handler)
@@ -116,6 +127,7 @@ class Plugin
std::vector<std::string> args_;
// The plugin's event handlers.
ld_plugin_claim_file_handler claim_file_handler_;
+ ld_plugin_inspect_unclaimed_object_handler inspect_unclaimed_object_handler_;
ld_plugin_all_symbols_read_handler all_symbols_read_handler_;
ld_plugin_cleanup_handler cleanup_handler_;
// TRUE if the cleanup handlers have been called.
@@ -128,9 +140,11 @@ class Plugin_manager
{
public:
Plugin_manager(const General_options& options)
- : plugins_(), objects_(), deferred_layout_objects_(), input_file_(NULL),
+ : plugins_(), objects_(), unclaimed_objects_(),
+ deferred_layout_objects_(), input_file_(NULL),
plugin_input_file_(), rescannable_(), undefined_symbols_(),
any_claimed_(false), in_replacement_phase_(false), any_added_(false),
+ in_inspect_unclaimed_object_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,12 +167,26 @@ 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);
+ // Call the plugin inspect_unclaimed_object handlers to allow them
+ // to inspect the file.
+ void
+ inspect_unclaimed_object(Object* obj);
+
+ Object*
+ get_unclaimed_object(const void* handle);
+
+ // True if the inspect_unclaimed_object handler of the plugins are being
+ // called.
+ bool
+ in_inspect_unclaimed_object_handler()
+ { return in_inspect_unclaimed_object_handler_; }
+
// Let the plugin manager save an archive for later rescanning.
// This takes ownership of the Archive pointer.
void
@@ -173,7 +201,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
@@ -197,6 +225,15 @@ class Plugin_manager
(*this->current_)->set_claim_file_handler(handler);
}
+ // Register a inspect_unclaimed_object handler.
+ void
+ set_inspect_unclaimed_object_handler
+ (ld_plugin_inspect_unclaimed_object_handler handler)
+ {
+ gold_assert(this->current_ != plugins_.end());
+ (*this->current_)->set_inspect_unclaimed_object_handler(handler);
+ }
+
// Register an all-symbols-read handler.
void
set_all_symbols_read_handler(ld_plugin_all_symbols_read_handler handler)
@@ -227,6 +264,15 @@ class Plugin_manager
return this->objects_[handle];
}
+ // Return the unclaimed object associated with the given HANDLE.
+ Object*
+ unclaimed_object(unsigned int handle) const
+ {
+ if (handle >= this->unclaimed_objects_.size())
+ return NULL;
+ return this->unclaimed_objects_[handle];
+ }
+
// Return TRUE if any input files have been claimed by a plugin
// and we are still in the initial input phase.
bool
@@ -262,6 +308,14 @@ class Plugin_manager
in_replacement_phase() const
{ return this->in_replacement_phase_; }
+ Input_objects*
+ input_objects() const
+ { return input_objects_; }
+
+ Layout*
+ layout()
+ { return layout_; }
+
private:
Plugin_manager(const Plugin_manager&);
Plugin_manager& operator=(const Plugin_manager&);
@@ -291,6 +345,7 @@ class Plugin_manager
typedef std::list<Plugin*> Plugin_list;
typedef std::vector<Pluginobj*> Object_list;
+ typedef std::vector<Object*> Unclaimed_object_list;
typedef std::vector<Relobj*> Deferred_layout_list;
typedef std::vector<Rescannable> Rescannable_list;
typedef std::vector<Symbol*> Undefined_symbol_list;
@@ -312,6 +367,12 @@ class Plugin_manager
// serves as the "handle" that we pass to the plugins.
Object_list objects_;
+ // The list of unclaimed objects. The negative of the index of an
+ // in this list serves as the "handle" that we pass to the plugins.
+ // Postive integer values for "handle" are for the claimed objects
+ // and negative values are for the unclaimed objects.
+ Unclaimed_object_list unclaimed_objects_;
+
// The list of regular objects whose layout has been deferred.
Deferred_layout_list deferred_layout_objects_;
@@ -337,6 +398,10 @@ class Plugin_manager
// Whether any input files or libraries were added by a plugin.
bool any_added_;
+ // Set to true when the inspect_unclaimed_object_handler of the plugins are being
+ // called.
+ bool in_inspect_unclaimed_object_handler_;
+
const General_options& options_;
Workqueue* workqueue_;
Task* task_;
Index: readsyms.cc
===================================================================
RCS file: /cvs/src/src/gold/readsyms.cc,v
retrieving revision 1.47
diff -u -u -p -r1.47 readsyms.cc
--- readsyms.cc 24 Jan 2011 21:48:40 -0000 1.47
+++ readsyms.cc 13 Mar 2011 02:31:36 -0000
@@ -380,6 +380,10 @@ Read_symbols::do_read_symbols(Workqueue*
return false;
}
+ // Allow the plugins to inspect the unclaimed object now.
+ if (parameters->options().has_plugins())
+ parameters->options().plugins()->inspect_unclaimed_object(obj);
+
Read_symbols_data* sd = new Read_symbols_data;
obj->read_symbols(sd);
cvs diff: Diffing po
cvs diff: Diffing testsuite
Index: testsuite/plugin_test.c
===================================================================
RCS file: /cvs/src/src/gold/testsuite/plugin_test.c,v
retrieving revision 1.4
diff -u -u -p -r1.4 plugin_test.c
--- testsuite/plugin_test.c 9 Nov 2009 16:11:34 -0000 1.4
+++ testsuite/plugin_test.c 13 Mar 2011 02:31:37 -0000
@@ -52,6 +52,8 @@ static struct claimed_file* first_claime
static struct claimed_file* last_claimed_file = NULL;
static ld_plugin_register_claim_file register_claim_file_hook = NULL;
+static ld_plugin_register_inspect_unclaimed_object
+ register_inspect_unclaimed_object_hook = NULL;
static ld_plugin_register_all_symbols_read register_all_symbols_read_hook = NULL;
static ld_plugin_register_cleanup register_cleanup_hook = NULL;
static ld_plugin_add_symbols add_symbols = NULL;
@@ -60,6 +62,12 @@ static ld_plugin_add_input_file add_inpu
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_section_count get_section_count = NULL;
+static ld_plugin_get_section_type get_section_type = NULL;
+static ld_plugin_get_section_name get_section_name = NULL;
+static ld_plugin_get_section_contents get_section_contents = NULL;
+static ld_plugin_read_layout_from_file read_layout_from_file = NULL;
+static ld_plugin_allow_section_ordering allow_section_ordering = NULL;
#define MAXOPTS 10
@@ -69,6 +77,7 @@ static int nopts = 0;
enum ld_plugin_status onload(struct ld_plugin_tv *tv);
enum ld_plugin_status claim_file_hook(const struct ld_plugin_input_file *file,
int *claimed);
+enum ld_plugin_status inspect_unclaimed_object_hook(void* handle);
enum ld_plugin_status all_symbols_read_hook(void);
enum ld_plugin_status cleanup_hook(void);
@@ -101,6 +110,10 @@ onload(struct ld_plugin_tv *tv)
case LDPT_REGISTER_CLAIM_FILE_HOOK:
register_claim_file_hook = entry->tv_u.tv_register_claim_file;
break;
+ case LDPT_REGISTER_INSPECT_UNCLAIMED_OBJECT_HOOK:
+ register_inspect_unclaimed_object_hook
+ = entry->tv_u.tv_register_inspect_unclaimed_object;
+ break;
case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK:
register_all_symbols_read_hook =
entry->tv_u.tv_register_all_symbols_read;
@@ -126,6 +139,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_SECTION_COUNT:
+ get_section_count = *entry->tv_u.tv_get_section_count;
+ break;
+ case LDPT_GET_SECTION_TYPE:
+ get_section_type = *entry->tv_u.tv_get_section_type;
+ break;
+ case LDPT_GET_SECTION_NAME:
+ get_section_name = *entry->tv_u.tv_get_section_name;
+ break;
+ case LDPT_GET_SECTION_CONTENTS:
+ get_section_contents = *entry->tv_u.tv_get_section_contents;
+ break;
+ case LDPT_READ_LAYOUT_FROM_FILE:
+ read_layout_from_file = *entry->tv_u.tv_read_layout_from_file;
+ break;
+ case LDPT_ALLOW_SECTION_ORDERING:
+ allow_section_ordering = *entry->tv_u.tv_allow_section_ordering;
+ break;
default:
break;
}
@@ -143,6 +174,13 @@ onload(struct ld_plugin_tv *tv)
return LDPS_ERR;
}
+ if (register_inspect_unclaimed_object_hook == NULL)
+ {
+ fprintf(stderr,
+ "tv_register_inspect_unclaimed_object_hook interface missing\n");
+ return LDPS_ERR;
+ }
+
if (register_all_symbols_read_hook == NULL)
{
fprintf(stderr, "tv_register_all_symbols_read_hook interface missing\n");
@@ -167,6 +205,14 @@ onload(struct ld_plugin_tv *tv)
return LDPS_ERR;
}
+ if ((*register_inspect_unclaimed_object_hook)
+ (inspect_unclaimed_object_hook) != LDPS_OK)
+ {
+ (*message)(LDPL_ERROR,
+ "error registering inspect unclaimed object hook");
+ return LDPS_ERR;
+ }
+
if ((*register_all_symbols_read_hook)(all_symbols_read_hook) != LDPS_OK)
{
(*message)(LDPL_ERROR, "error registering all symbols read hook");
@@ -179,10 +225,53 @@ onload(struct ld_plugin_tv *tv)
return LDPS_ERR;
}
+ if (get_section_count == NULL)
+ {
+ fprintf(stderr, "tv_get_section_count interface missing\n");
+ return LDPS_ERR;
+ }
+
+ if (get_section_type == NULL)
+ {
+ fprintf(stderr, "tv_get_section_type interface missing\n");
+ return LDPS_ERR;
+ }
+
+ if (get_section_name == NULL)
+ {
+ fprintf(stderr, "tv_get_section_name interface missing\n");
+ return LDPS_ERR;
+ }
+
+ if (get_section_contents == NULL)
+ {
+ fprintf(stderr, "tv_get_section_contents interface missing\n");
+ return LDPS_ERR;
+ }
+
+ if (read_layout_from_file == NULL)
+ {
+ fprintf(stderr, "tv_read_layout_from_file 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;
}
enum ld_plugin_status
+inspect_unclaimed_object_hook (void* handle)
+{
+ (*message)(LDPL_INFO, "Inspect unclaimed object hook called with handle: %p",
+ handle);
+ return LDPS_OK;
+}
+enum ld_plugin_status
claim_file_hook (const struct ld_plugin_input_file* file, int* claimed)
{
int len;
Index: plugin-api.h
===================================================================
RCS file: /cvs/src/src/include/plugin-api.h,v
retrieving revision 1.13
diff -u -u -p -r1.13 plugin-api.h
--- plugin-api.h 3 Jan 2011 21:05:50 -0000 1.13
+++ plugin-api.h 13 Mar 2011 02:24:32 -0000
@@ -157,6 +157,12 @@ enum ld_plugin_status
(*ld_plugin_claim_file_handler) (
const struct ld_plugin_input_file *file, int *claimed);
+/* The plugin library's "observe file" handler. */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_inspect_unclaimed_object_handler) (void *);
+
/* The plugin library's "all symbols read" handler. */
typedef
@@ -175,6 +181,13 @@ typedef
enum ld_plugin_status
(*ld_plugin_register_claim_file) (ld_plugin_claim_file_handler handler);
+/* The linker's interface for registering the "observe file" handler. */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_register_inspect_unclaimed_object)
+ (ld_plugin_inspect_unclaimed_object_handler handler);
+
/* The linker's interface for registering the "all symbols read" handler. */
typedef
@@ -240,6 +253,59 @@ 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 inspect_unclaimed_object_handler. This
+ interface should only be invoked in the inspect_unclaimed_object_handler. */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_get_section_count) (const void* handle, unsigned int* count);
+
+/* The linker's interface for retrieving the section type of a specific
+ section in an object. The handle is obtained in the
+ inspect_unclaimed_object_handler. This interface should only be
+ invoked in the inspect_unclaimed_object_handler. */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_get_section_type) (void* handle, unsigned int shndx,
+ unsigned int* type);
+
+/* The linker's interface for retrieving the name of specific section in
+ an object. The handle is obtained in the inspect_unclaimed_object_handler.
+ This interface should only be invoked in the
+ inspect_unclaimed_object_handler. */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_get_section_name) (void* handle, unsigned int shndx,
+ char** section_name_ptr);
+
+/* The linker's interface for retrieving the contents of a specific section
+ in an object. The handle is obtained in the
+ inspect_unclaimed_object_handler. This interface should only be invoked
+ in the inspect_unclaimed_object_handler. */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_get_section_contents) (void* handle, unsigned int shndx,
+ unsigned char** section_contents,
+ unsigned int* len);
+
+/* The linker's interface for specifying the desired order of sections
+ through a file. */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_read_layout_from_file) (const char* filename);
+
+/* The linker's interface for specifying that reordering of sections is
+ desired. */
+
+typedef
+enum ld_plugin_status
+(*ld_plugin_allow_section_ordering) (void);
+
enum ld_plugin_level
{
LDPL_INFO,
@@ -258,6 +324,7 @@ enum ld_plugin_tag
LDPT_LINKER_OUTPUT,
LDPT_OPTION,
LDPT_REGISTER_CLAIM_FILE_HOOK,
+ LDPT_REGISTER_INSPECT_UNCLAIMED_OBJECT_HOOK,
LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK,
LDPT_REGISTER_CLEANUP_HOOK,
LDPT_ADD_SYMBOLS,
@@ -269,7 +336,13 @@ enum ld_plugin_tag
LDPT_ADD_INPUT_LIBRARY,
LDPT_OUTPUT_NAME,
LDPT_SET_EXTRA_LIBRARY_PATH,
- LDPT_GNU_LD_VERSION
+ LDPT_GNU_LD_VERSION,
+ LDPT_GET_SECTION_COUNT,
+ LDPT_GET_SECTION_TYPE,
+ LDPT_GET_SECTION_NAME,
+ LDPT_GET_SECTION_CONTENTS,
+ LDPT_READ_LAYOUT_FROM_FILE,
+ LDPT_ALLOW_SECTION_ORDERING
};
/* The plugin transfer vector. */
@@ -282,6 +355,8 @@ struct ld_plugin_tv
int tv_val;
const char *tv_string;
ld_plugin_register_claim_file tv_register_claim_file;
+ ld_plugin_register_inspect_unclaimed_object
+ tv_register_inspect_unclaimed_object;
ld_plugin_register_all_symbols_read tv_register_all_symbols_read;
ld_plugin_register_cleanup tv_register_cleanup;
ld_plugin_add_symbols tv_add_symbols;
@@ -292,6 +367,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_section_count tv_get_section_count;
+ ld_plugin_get_section_type tv_get_section_type;
+ ld_plugin_get_section_name tv_get_section_name;
+ ld_plugin_get_section_contents tv_get_section_contents;
+ ld_plugin_read_layout_from_file tv_read_layout_from_file;
+ ld_plugin_allow_section_ordering tv_allow_section_ordering;
} tv_u;
};
More information about the Binutils
mailing list