Add plugin API for processing plugin-added input files
Gold plugins may wish to further process an input file added by a plugin. For example, the plugin may need to assign a unique segment for sections in a plugin-generated input file. This patch adds a plugin callback that the linker will call when reading symbols from a new input file added after the all_symbols_read event (i.e. an input file added by a plugin). 2017-12-11 Stephen Crane <sjc@immunant.com> * plugin-api.h: Add new plugin hook to allow processing of input files added by a plugin. (ld_plugin_new_input_handler): New function hook type. (ld_plugin_register_new_input): New interface. (LDPT_REGISTER_NEW_INPUT_HOOK): New enum val. (tv_register_new_input): New member. * plugin.cc (Plugin::load): Include hooks for register_new_input in transfer vector. (Plugin::new_input): New function. (register_new_input): New function. (Plugin_manager::claim_file): Call Plugin::new_input if in replacement phase. * plugin.h (Plugin::set_new_input_handler): New function. * testsuite/plugin_new_section_layout.c: New plugin to test new_input plugin API. * testsuite/plugin_final_layout.sh: Add new input test. * testsuite/Makefile.am (plugin_layout_new_file): New test case. * testsuite/Makefile.in: Regenerate.
This commit is contained in:
parent
4c5ae11b42
commit
c4e648430f
9 changed files with 333 additions and 20 deletions
|
@ -167,6 +167,9 @@ static enum ld_plugin_status
|
|||
get_input_section_size(const struct ld_plugin_section section,
|
||||
uint64_t* secsize);
|
||||
|
||||
static enum ld_plugin_status
|
||||
register_new_input(ld_plugin_new_input_handler handler);
|
||||
|
||||
};
|
||||
|
||||
#endif // ENABLE_PLUGINS
|
||||
|
@ -211,7 +214,7 @@ Plugin::load()
|
|||
sscanf(ver, "%d.%d", &major, &minor);
|
||||
|
||||
// Allocate and populate a transfer vector.
|
||||
const int tv_fixed_size = 29;
|
||||
const int tv_fixed_size = 30;
|
||||
|
||||
int tv_size = this->args_.size() + tv_fixed_size;
|
||||
ld_plugin_tv* tv = new ld_plugin_tv[tv_size];
|
||||
|
@ -345,6 +348,10 @@ Plugin::load()
|
|||
tv[i].tv_tag = LDPT_GET_INPUT_SECTION_SIZE;
|
||||
tv[i].tv_u.tv_get_input_section_size = get_input_section_size;
|
||||
|
||||
++i;
|
||||
tv[i].tv_tag = LDPT_REGISTER_NEW_INPUT_HOOK;
|
||||
tv[i].tv_u.tv_register_new_input = register_new_input;
|
||||
|
||||
++i;
|
||||
tv[i].tv_tag = LDPT_NULL;
|
||||
tv[i].tv_u.tv_val = 0;
|
||||
|
@ -383,6 +390,15 @@ Plugin::all_symbols_read()
|
|||
(*this->all_symbols_read_handler_)();
|
||||
}
|
||||
|
||||
// Call the new_input handler.
|
||||
|
||||
inline void
|
||||
Plugin::new_input(struct ld_plugin_input_file* plugin_input_file)
|
||||
{
|
||||
if (this->new_input_handler_ != NULL)
|
||||
(*this->new_input_handler_)(plugin_input_file);
|
||||
}
|
||||
|
||||
// Call the cleanup handler.
|
||||
|
||||
inline void
|
||||
|
@ -476,8 +492,6 @@ Plugin_manager::claim_file(Input_file* input_file, off_t offset,
|
|||
|
||||
gold_assert(lock_initialized);
|
||||
Hold_lock hl(*this->lock_);
|
||||
if (this->in_replacement_phase_)
|
||||
return NULL;
|
||||
|
||||
unsigned int handle = this->objects_.size();
|
||||
this->input_file_ = input_file;
|
||||
|
@ -494,19 +508,28 @@ Plugin_manager::claim_file(Input_file* input_file, off_t offset,
|
|||
this->current_ != this->plugins_.end();
|
||||
++this->current_)
|
||||
{
|
||||
if ((*this->current_)->claim_file(&this->plugin_input_file_))
|
||||
// If we aren't yet in replacement phase, allow plugins to claim input
|
||||
// files, otherwise notify the plugin of the new input file, if needed.
|
||||
if (!this->in_replacement_phase_)
|
||||
{
|
||||
this->any_claimed_ = true;
|
||||
this->in_claim_file_handler_ = false;
|
||||
if ((*this->current_)->claim_file(&this->plugin_input_file_))
|
||||
{
|
||||
this->any_claimed_ = true;
|
||||
this->in_claim_file_handler_ = false;
|
||||
|
||||
if (this->objects_.size() > handle
|
||||
&& this->objects_[handle]->pluginobj() != NULL)
|
||||
return this->objects_[handle]->pluginobj();
|
||||
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.
|
||||
Pluginobj* obj = this->make_plugin_object(handle);
|
||||
return obj;
|
||||
// If the plugin claimed the file but did not call the
|
||||
// add_symbols callback, we need to create the Pluginobj now.
|
||||
Pluginobj* obj = this->make_plugin_object(handle);
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
(*this->current_)->new_input(&this->plugin_input_file_);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1905,6 +1928,16 @@ unique_segment_for_sections(const char* segment_name,
|
|||
return LDPS_OK;
|
||||
}
|
||||
|
||||
// Register a new_input handler.
|
||||
|
||||
static enum ld_plugin_status
|
||||
register_new_input(ld_plugin_new_input_handler handler)
|
||||
{
|
||||
gold_assert(parameters->options().has_plugins());
|
||||
parameters->options().plugins()->set_new_input_handler(handler);
|
||||
return LDPS_OK;
|
||||
}
|
||||
|
||||
#endif // ENABLE_PLUGINS
|
||||
|
||||
// Allocate a Pluginobj object of the appropriate size and endianness.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue