* object.cc (Sized_relobj::layout_section): New function.

(Sized_relobj::do_layout): Defer layout of input sections until after
	plugin has provided replacement files.
	(Sized_relobj::do_layout_deferred_sections): New function.
	* object.h (Relobj::set_section_offset): Remove virtual keyword.
	(Relobj::layout_deferred_sections): New function.
	(Relobj::do_layout_deferred_sections): New function.
	(Sized_relobj::do_layout_deferred_sections): New function.
	(Sized_relobj::layout_section): New function.
	(Sized_relobj::Deferred_layout): New structure.
	(Sized_relobj::deferred_layout_): New field.
	* plugin.cc (Plugin_manager::finish): Renamed, was cleanup.
	Change all callers.  Layout deferred sections.
	(class Plugin_finish): Renamed, was Plugin_cleanup.  Change all
	references.
	(Plugin_hook::run): Move code from do_plugin_hook inline.
	(Plugin_hook::do_plugin_hook): Remove.
	* plugin.h (Plugin_manager::Plugin_manager): Add missing initializers.
	(Plugin_manager::finish): Renamed, was cleanup.
	(Plugin_manager::should_defer_layout): New function.
	(Plugin_manager::add_deferred_layout_object): New function.
	(Plugin_manager::Deferred_layout_list): New type.
	(Plugin_manager::deferred_layout_objects_): New field.
	(Plugin_hook::do_plugin_hook): Remove.
This commit is contained in:
Cary Coutant 2008-12-23 02:02:20 +00:00
parent bce3bbcb76
commit 5995b57073
5 changed files with 193 additions and 42 deletions

View File

@ -1,3 +1,30 @@
2008-12-22 Cary Coutant <ccoutant@google.com>
* object.cc (Sized_relobj::layout_section): New function.
(Sized_relobj::do_layout): Defer layout of input sections until after
plugin has provided replacement files.
(Sized_relobj::do_layout_deferred_sections): New function.
* object.h (Relobj::set_section_offset): Remove virtual keyword.
(Relobj::layout_deferred_sections): New function.
(Relobj::do_layout_deferred_sections): New function.
(Sized_relobj::do_layout_deferred_sections): New function.
(Sized_relobj::layout_section): New function.
(Sized_relobj::Deferred_layout): New structure.
(Sized_relobj::deferred_layout_): New field.
* plugin.cc (Plugin_manager::finish): Renamed, was cleanup.
Change all callers. Layout deferred sections.
(class Plugin_finish): Renamed, was Plugin_cleanup. Change all
references.
(Plugin_hook::run): Move code from do_plugin_hook inline.
(Plugin_hook::do_plugin_hook): Remove.
* plugin.h (Plugin_manager::Plugin_manager): Add missing initializers.
(Plugin_manager::finish): Renamed, was cleanup.
(Plugin_manager::should_defer_layout): New function.
(Plugin_manager::add_deferred_layout_object): New function.
(Plugin_manager::Deferred_layout_list): New type.
(Plugin_manager::deferred_layout_objects_): New field.
(Plugin_hook::do_plugin_hook): Remove.
2008-12-17 Ian Lance Taylor <iant@google.com>
* options.h (class General_options): Add --no case for

View File

@ -37,6 +37,7 @@
#include "reloc.h"
#include "object.h"
#include "dynobj.h"
#include "plugin.h"
namespace gold
{
@ -784,6 +785,34 @@ Sized_relobj<size, big_endian>::include_linkonce_section(
return include1 && include2;
}
// Layout an input section.
template<int size, bool big_endian>
inline void
Sized_relobj<size, big_endian>::layout_section(Layout* layout,
unsigned int shndx,
const char* name,
typename This::Shdr& shdr,
unsigned int reloc_shndx,
unsigned int reloc_type)
{
off_t offset;
Output_section* os = layout->layout(this, shndx, name, shdr,
reloc_shndx, reloc_type, &offset);
this->output_sections()[shndx] = os;
if (offset == -1)
this->section_offsets_[shndx] = invalid_address;
else
this->section_offsets_[shndx] = convert_types<Address, off_t>(offset);
// If this section requires special handling, and if there are
// relocs that apply to it, then we must do the special handling
// before we apply the relocs.
if (offset == -1 && reloc_shndx != 0)
this->set_relocs_must_follow_section_writes();
}
// Lay out the input sections. We walk through the sections and check
// whether they should be included in the link. If they should, we
// pass them to the Layout object, which will return an output section
@ -807,6 +836,13 @@ Sized_relobj<size, big_endian>::do_layout(Symbol_table* symtab,
const unsigned char* pnamesu = sd->section_names->data();
const char* pnames = reinterpret_cast<const char*>(pnamesu);
// If any input files have been claimed by plugins, we need to defer
// actual layout until the replacement files have arrived.
const bool should_defer_layout =
(parameters->options().has_plugins()
&& parameters->options().plugins()->should_defer_layout());
unsigned int num_sections_to_defer = 0;
// For each section, record the index of the reloc section if any.
// Use 0 to mean that there is no reloc section, -1U to mean that
// there is more than one.
@ -818,6 +854,10 @@ Sized_relobj<size, big_endian>::do_layout(Symbol_table* symtab,
{
typename This::Shdr shdr(pshdrs);
// Count the number of sections whose layout will be deferred.
if (should_defer_layout && (shdr.get_sh_flags() & elfcpp::SHF_ALLOC))
++num_sections_to_defer;
unsigned int sh_type = shdr.get_sh_type();
if (sh_type == elfcpp::SHT_REL || sh_type == elfcpp::SHT_RELA)
{
@ -856,6 +896,12 @@ Sized_relobj<size, big_endian>::do_layout(Symbol_table* symtab,
return;
}
if (num_sections_to_defer > 0)
{
parameters->options().plugins()->add_deferred_layout_object(this);
this->deferred_layout_.reserve(num_sections_to_defer);
}
// Whether we've seen a .note.GNU-stack section.
bool seen_gnu_stack = false;
// The flags of a .note.GNU-stack section.
@ -960,22 +1006,22 @@ Sized_relobj<size, big_endian>::do_layout(Symbol_table* symtab,
continue;
}
off_t offset;
Output_section* os = layout->layout(this, i, name, shdr,
reloc_shndx[i], reloc_type[i],
&offset);
if (should_defer_layout && (shdr.get_sh_flags() & elfcpp::SHF_ALLOC))
{
this->deferred_layout_.push_back(Deferred_layout(i, name, pshdrs,
reloc_shndx[i],
reloc_type[i]));
out_sections[i] = os;
if (offset == -1)
out_section_offsets[i] = invalid_address;
// Put dummy values here; real values will be supplied by
// do_layout_deferred_sections.
out_sections[i] = reinterpret_cast<Output_section*>(1);
out_section_offsets[i] = invalid_address;
}
else
out_section_offsets[i] = convert_types<Address, off_t>(offset);
// If this section requires special handling, and if there are
// relocs that apply to it, then we must do the special handling
// before we apply the relocs.
if (offset == -1 && reloc_shndx[i] != 0)
this->set_relocs_must_follow_section_writes();
{
this->layout_section(layout, i, name, shdr, reloc_shndx[i],
reloc_type[i]);
}
}
layout->layout_gnu_stack(seen_gnu_stack, gnu_stack_flags);
@ -1059,6 +1105,27 @@ Sized_relobj<size, big_endian>::do_layout(Symbol_table* symtab,
sd->section_names = NULL;
}
// Layout sections whose layout was deferred while waiting for
// input files from a plugin.
template<int size, bool big_endian>
void
Sized_relobj<size, big_endian>::do_layout_deferred_sections(Layout* layout)
{
typename std::vector<Deferred_layout>::iterator deferred;
for (deferred = this->deferred_layout_.begin();
deferred != this->deferred_layout_.end();
++deferred)
{
typename This::Shdr shdr(deferred->shdr_data_);
this->layout_section(layout, deferred->shndx_, deferred->name_.c_str(),
shdr, deferred->reloc_shndx_, deferred->reloc_type_);
}
this->deferred_layout_.clear();
}
// Add the symbols to the symbol table.
template<int size, bool big_endian>

View File

@ -671,7 +671,7 @@ class Relobj : public Object
{ return this->do_output_section_offset(shndx); }
// Set the offset of an input section within its output section.
virtual void
void
set_section_offset(unsigned int shndx, uint64_t off)
{ this->do_set_section_offset(shndx, off); }
@ -712,6 +712,12 @@ class Relobj : public Object
return (*this->map_to_relocatable_relocs_)[reloc_shndx];
}
// Layout sections whose layout was deferred while waiting for
// input files from a plugin.
void
layout_deferred_sections(Layout* layout)
{ this->do_layout_deferred_sections(layout); }
protected:
// The output section to be used for each input section, indexed by
// the input section number. The output section is NULL if the
@ -764,6 +770,11 @@ class Relobj : public Object
virtual void
do_set_section_offset(unsigned int shndx, uint64_t off) = 0;
// Layout sections whose layout was deferred while waiting for
// input files from a plugin--implemented by child class.
virtual void
do_layout_deferred_sections(Layout*) = 0;
// Return the vector mapping input sections to output sections.
Output_sections&
output_sections()
@ -1368,6 +1379,11 @@ class Sized_relobj : public Relobj
void
do_layout(Symbol_table*, Layout*, Read_symbols_data*);
// Layout sections whose layout was deferred while waiting for
// input files from a plugin.
void
do_layout_deferred_sections(Layout*);
// Add the symbols to the symbol table.
void
do_add_symbols(Symbol_table*, Read_symbols_data*);
@ -1558,6 +1574,12 @@ class Sized_relobj : public Relobj
include_linkonce_section(Layout*, unsigned int, const char*,
const elfcpp::Shdr<size, big_endian>&);
// Layout an input section.
void
layout_section(Layout* layout, unsigned int shndx, const char* name,
typename This::Shdr& shdr, unsigned int reloc_shndx,
unsigned int reloc_type);
// Views and sizes when relocating.
struct View_size
{
@ -1681,6 +1703,25 @@ class Sized_relobj : public Relobj
};
typedef Unordered_map<unsigned int, Tls_got_entry> Local_tls_got_offsets;
// Saved information for sections whose layout was deferred.
struct Deferred_layout
{
static const int shdr_size = elfcpp::Elf_sizes<size>::shdr_size;
Deferred_layout(unsigned int shndx, const char* name,
const unsigned char* pshdr,
unsigned int reloc_shndx, unsigned int reloc_type)
: shndx_(shndx), name_(name), reloc_shndx_(reloc_shndx),
reloc_type_(reloc_type)
{
memcpy(this->shdr_data_, pshdr, shdr_size);
}
unsigned int shndx_;
std::string name_;
unsigned int reloc_shndx_;
unsigned int reloc_type_;
unsigned char shdr_data_[shdr_size];
};
// General access to the ELF file.
elfcpp::Elf_file<size, big_endian, Object> elf_file_;
// Index of SHT_SYMTAB section.
@ -1715,6 +1756,8 @@ class Sized_relobj : public Relobj
Comdat_group_table comdat_groups_;
// Whether this object has a GNU style .eh_frame section.
bool has_eh_frame_;
// The list of sections whose layout was deferred.
std::vector<Deferred_layout> deferred_layout_;
};
// A class to manage the list of all objects.

View File

@ -306,11 +306,18 @@ Plugin_manager::all_symbols_read(Workqueue* workqueue,
*last_blocker = this->this_blocker_;
}
// Call the cleanup handlers.
// Layout deferred sections and call the cleanup handlers.
void
Plugin_manager::cleanup()
Plugin_manager::finish()
{
Deferred_layout_list::iterator obj;
for (obj = this->deferred_layout_objects_.begin();
obj != this->deferred_layout_objects_.end();
++obj)
(*obj)->layout_deferred_sections(this->layout_);
for (this->current_ = this->plugins_.begin();
this->current_ != this->plugins_.end();
++this->current_)
@ -713,17 +720,18 @@ Add_plugin_symbols::run(Workqueue*)
this->obj_->add_symbols(this->symtab_, this->layout_);
}
// Class Plugin_cleanup. This task calls the plugin cleanup hooks once all
// replacement files have been added.
// Class Plugin_finish. This task runs after all replacement files have
// been added. It calls Layout::layout for any deferred sections and
// calls each plugin's cleanup handler.
class Plugin_cleanup : public Task
class Plugin_finish : public Task
{
public:
Plugin_cleanup(Task_token* this_blocker, Task_token* next_blocker)
Plugin_finish(Task_token* this_blocker, Task_token* next_blocker)
: this_blocker_(this_blocker), next_blocker_(next_blocker)
{ }
~Plugin_cleanup()
~Plugin_finish()
{
if (this->this_blocker_ != NULL)
delete this->this_blocker_;
@ -743,11 +751,11 @@ class Plugin_cleanup : public Task
void
run(Workqueue*)
{ parameters->options().plugins()->cleanup(); }
{ parameters->options().plugins()->finish(); }
std::string
get_name() const
{ return "Plugin_cleanup"; }
{ return "Plugin_finish"; }
private:
Task_token* this_blocker_;
@ -778,18 +786,10 @@ Plugin_hook::locks(Task_locker*)
{
}
// Run a Plugin_hook task.
void
Plugin_hook::run(Workqueue* workqueue)
{
this->do_plugin_hook(workqueue);
}
// Run the "all symbols read" plugin hook.
void
Plugin_hook::do_plugin_hook(Workqueue* workqueue)
Plugin_hook::run(Workqueue* workqueue)
{
gold_assert(this->options_.has_plugins());
this->options_.plugins()->all_symbols_read(workqueue,
@ -799,8 +799,8 @@ Plugin_hook::do_plugin_hook(Workqueue* workqueue)
this->dirpath_,
this->mapfile_,
&this->this_blocker_);
workqueue->queue_soon(new Plugin_cleanup(this->this_blocker_,
this->next_blocker_));
workqueue->queue_soon(new Plugin_finish(this->this_blocker_,
this->next_blocker_));
}
// The C interface routines called by the plugins.

View File

@ -120,7 +120,8 @@ class Plugin_manager
{
public:
Plugin_manager(const General_options& options)
: plugins_(), in_replacement_phase_(false), options_(options),
: plugins_(), objects_(), deferred_layout_objects_(), input_file_(NULL),
plugin_input_file_(), in_replacement_phase_(false), options_(options),
workqueue_(NULL), input_objects_(NULL), symtab_(NULL), layout_(NULL),
dirpath_(NULL), mapfile_(NULL), this_blocker_(NULL)
{ this->current_ = plugins_.end(); }
@ -154,9 +155,9 @@ class Plugin_manager
Symbol_table* symtab, Layout* layout, Dirsearch* dirpath,
Mapfile* mapfile, Task_token** last_blocker);
// Call the cleanup handlers.
// Run deferred layout and call the cleanup handlers.
void
cleanup();
finish();
// Register a claim-file handler.
void
@ -196,6 +197,19 @@ class Plugin_manager
return this->objects_[handle];
}
// Return TRUE if any input files have been claimed by a plugin
// and we are still in the initial input phase.
bool
should_defer_layout() const
{ return !this->objects_.empty() && !this->in_replacement_phase_; }
// Add a regular object to the deferred layout list. These are
// objects whose layout has been deferred until after the
// replacement files have arrived.
void
add_deferred_layout_object(Relobj* obj)
{ this->deferred_layout_objects_.push_back(obj); }
// Add a new input file.
ld_plugin_status
add_input_file(char *pathname);
@ -211,6 +225,7 @@ class Plugin_manager
typedef std::list<Plugin*> Plugin_list;
typedef std::vector<Pluginobj*> Object_list;
typedef std::vector<Relobj*> Deferred_layout_list;
// The list of plugin libraries.
Plugin_list plugins_;
@ -221,6 +236,9 @@ class Plugin_manager
// serves as the "handle" that we pass to the plugins.
Object_list objects_;
// The list of regular objects whose layout has been deferred.
Deferred_layout_list deferred_layout_objects_;
// The file currently up for claim by the plugins.
Input_file* input_file_;
struct ld_plugin_input_file plugin_input_file_;
@ -456,10 +474,6 @@ class Plugin_hook : public Task
{ return "Plugin_hook"; }
private:
// Call the plugin hook.
void
do_plugin_hook(Workqueue*);
const General_options& options_;
Input_objects* input_objects_;
Symbol_table* symtab_;