* 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:
parent
bce3bbcb76
commit
5995b57073
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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_;
|
||||
|
Loading…
Reference in New Issue
Block a user