mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-01-20 23:13:33 +08:00
* plugin.cc (class Plugin_rescan): Define new class.
(Plugin_manager::claim_file): Set any_claimed_. (Plugin_manager::save_archive): New function. (Plugin_manager::save_input_group): New function. (Plugin_manager::all_symbols_read): Create Plugin_rescan task if necessary. (Plugin_manager::new_undefined_symbol): New function. (Plugin_manager::rescan): New function. (Plugin_manager::rescannable_defines): New function. (Plugin_manager::add_input_file): Set any_added_. * plugin.h (class Plugin_manager): define new fields rescannable_, undefined_symbols_, any_claimed_, and any_added_. Declare Plugin_rescan as friend. Declare new functions. (Plugin_manager::Rescannable): Define type. (Plugin_manager::Rescannable_list): Define type. (Plugin_manager::Undefined_symbol_list): Define type. (Plugin_manager::Plugin_manager): Initialize new fields. * archive.cc (Archive::defines_symbol): New function. (Add_archive_symbols::run): Pass archive to plugins if any. * archive.h (class Archive): Declare defines_symbol. * readsyms.cc (Input_group::~Input_group): New function. (Finish_group::run): Pass input_group to plugins if any. * readsyms.h (class Input_group): Declare destructor. * symtab.cc (add_from_object): Pass undefined symbol to plugins if any.
This commit is contained in:
parent
314d366acd
commit
0f3b89d87a
@ -1,3 +1,31 @@
|
|||||||
|
2011-01-24 Ian Lance Taylor <iant@google.com>
|
||||||
|
|
||||||
|
* plugin.cc (class Plugin_rescan): Define new class.
|
||||||
|
(Plugin_manager::claim_file): Set any_claimed_.
|
||||||
|
(Plugin_manager::save_archive): New function.
|
||||||
|
(Plugin_manager::save_input_group): New function.
|
||||||
|
(Plugin_manager::all_symbols_read): Create Plugin_rescan task if
|
||||||
|
necessary.
|
||||||
|
(Plugin_manager::new_undefined_symbol): New function.
|
||||||
|
(Plugin_manager::rescan): New function.
|
||||||
|
(Plugin_manager::rescannable_defines): New function.
|
||||||
|
(Plugin_manager::add_input_file): Set any_added_.
|
||||||
|
* plugin.h (class Plugin_manager): define new fields rescannable_,
|
||||||
|
undefined_symbols_, any_claimed_, and any_added_. Declare
|
||||||
|
Plugin_rescan as friend. Declare new functions.
|
||||||
|
(Plugin_manager::Rescannable): Define type.
|
||||||
|
(Plugin_manager::Rescannable_list): Define type.
|
||||||
|
(Plugin_manager::Undefined_symbol_list): Define type.
|
||||||
|
(Plugin_manager::Plugin_manager): Initialize new fields.
|
||||||
|
* archive.cc (Archive::defines_symbol): New function.
|
||||||
|
(Add_archive_symbols::run): Pass archive to plugins if any.
|
||||||
|
* archive.h (class Archive): Declare defines_symbol.
|
||||||
|
* readsyms.cc (Input_group::~Input_group): New function.
|
||||||
|
(Finish_group::run): Pass input_group to plugins if any.
|
||||||
|
* readsyms.h (class Input_group): Declare destructor.
|
||||||
|
* symtab.cc (add_from_object): Pass undefined symbol to plugins if
|
||||||
|
any.
|
||||||
|
|
||||||
2011-01-10 Ian Lance Taylor <iant@google.com>
|
2011-01-10 Ian Lance Taylor <iant@google.com>
|
||||||
|
|
||||||
* layout.cc (Layout::layout_eh_frame): Mark a writable .eh_frame
|
* layout.cc (Layout::layout_eh_frame): Mark a writable .eh_frame
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// archive.cc -- archive support for gold
|
// archive.cc -- archive support for gold
|
||||||
|
|
||||||
// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
|
// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||||
// Written by Ian Lance Taylor <iant@google.com>.
|
// Written by Ian Lance Taylor <iant@google.com>.
|
||||||
|
|
||||||
// This file is part of gold.
|
// This file is part of gold.
|
||||||
@ -779,6 +779,42 @@ Archive::add_symbols(Symbol_table* symtab, Layout* layout,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return whether the archive includes a member which defines the
|
||||||
|
// symbol SYM.
|
||||||
|
|
||||||
|
bool
|
||||||
|
Archive::defines_symbol(Symbol* sym) const
|
||||||
|
{
|
||||||
|
const char* symname = sym->name();
|
||||||
|
size_t symname_len = strlen(symname);
|
||||||
|
size_t armap_size = this->armap_.size();
|
||||||
|
for (size_t i = 0; i < armap_size; ++i)
|
||||||
|
{
|
||||||
|
if (this->armap_checked_[i])
|
||||||
|
continue;
|
||||||
|
const char* archive_symname = (this->armap_names_.data()
|
||||||
|
+ this->armap_[i].name_offset);
|
||||||
|
if (strncmp(archive_symname, symname, symname_len) != 0)
|
||||||
|
continue;
|
||||||
|
char c = archive_symname[symname_len];
|
||||||
|
if (c == '\0' && sym->version() == NULL)
|
||||||
|
return true;
|
||||||
|
if (c == '@')
|
||||||
|
{
|
||||||
|
const char* ver = archive_symname + symname_len + 1;
|
||||||
|
if (*ver == '@')
|
||||||
|
{
|
||||||
|
if (sym->version() == NULL)
|
||||||
|
return true;
|
||||||
|
++ver;
|
||||||
|
}
|
||||||
|
if (sym->version() != NULL && strcmp(sym->version(), ver) == 0)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Include all the archive members in the link. This is for --whole-archive.
|
// Include all the archive members in the link. This is for --whole-archive.
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -1001,8 +1037,18 @@ Add_archive_symbols::run(Workqueue* workqueue)
|
|||||||
if (incremental_inputs != NULL)
|
if (incremental_inputs != NULL)
|
||||||
incremental_inputs->report_archive_end(this->archive_);
|
incremental_inputs->report_archive_end(this->archive_);
|
||||||
|
|
||||||
// We no longer need to know about this archive.
|
if (!parameters->options().has_plugins()
|
||||||
delete this->archive_;
|
|| this->archive_->input_file()->options().whole_archive())
|
||||||
|
{
|
||||||
|
// We no longer need to know about this archive.
|
||||||
|
delete this->archive_;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// The plugin interface may want to rescan this archive.
|
||||||
|
parameters->options().plugins()->save_archive(this->archive_);
|
||||||
|
}
|
||||||
|
|
||||||
this->archive_ = NULL;
|
this->archive_ = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// archive.h -- archive support for gold -*- C++ -*-
|
// archive.h -- archive support for gold -*- C++ -*-
|
||||||
|
|
||||||
// Copyright 2006, 2007, 2008, 2010 Free Software Foundation, Inc.
|
// Copyright 2006, 2007, 2008, 2010, 2011 Free Software Foundation, Inc.
|
||||||
// Written by Ian Lance Taylor <iant@google.com>.
|
// Written by Ian Lance Taylor <iant@google.com>.
|
||||||
|
|
||||||
// This file is part of gold.
|
// This file is part of gold.
|
||||||
@ -152,6 +152,10 @@ class Archive
|
|||||||
bool
|
bool
|
||||||
add_symbols(Symbol_table*, Layout*, Input_objects*, Mapfile*);
|
add_symbols(Symbol_table*, Layout*, Input_objects*, Mapfile*);
|
||||||
|
|
||||||
|
// Return whether the archive defines the symbol.
|
||||||
|
bool
|
||||||
|
defines_symbol(Symbol*) const;
|
||||||
|
|
||||||
// Dump statistical information to stderr.
|
// Dump statistical information to stderr.
|
||||||
static void
|
static void
|
||||||
print_stats();
|
print_stats();
|
||||||
|
206
gold/plugin.cc
206
gold/plugin.cc
@ -1,6 +1,6 @@
|
|||||||
// plugin.cc -- plugin manager for gold -*- C++ -*-
|
// plugin.cc -- plugin manager for gold -*- C++ -*-
|
||||||
|
|
||||||
// Copyright 2008, 2009, 2010 Free Software Foundation, Inc.
|
// Copyright 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||||
// Written by Cary Coutant <ccoutant@google.com>.
|
// Written by Cary Coutant <ccoutant@google.com>.
|
||||||
|
|
||||||
// This file is part of gold.
|
// This file is part of gold.
|
||||||
@ -261,6 +261,45 @@ Plugin::cleanup()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This task is used to rescan archives as needed.
|
||||||
|
|
||||||
|
class Plugin_rescan : public Task
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Plugin_rescan(Task_token* this_blocker, Task_token* next_blocker)
|
||||||
|
: this_blocker_(this_blocker), next_blocker_(next_blocker)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
~Plugin_rescan()
|
||||||
|
{
|
||||||
|
delete this->this_blocker_;
|
||||||
|
}
|
||||||
|
|
||||||
|
Task_token*
|
||||||
|
is_runnable()
|
||||||
|
{
|
||||||
|
if (this->this_blocker_->is_blocked())
|
||||||
|
return this->this_blocker_;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
locks(Task_locker* tl)
|
||||||
|
{ tl->add(this, this->next_blocker_); }
|
||||||
|
|
||||||
|
void
|
||||||
|
run(Workqueue*)
|
||||||
|
{ parameters->options().plugins()->rescan(this); }
|
||||||
|
|
||||||
|
std::string
|
||||||
|
get_name() const
|
||||||
|
{ return "Plugin_rescan"; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Task_token* this_blocker_;
|
||||||
|
Task_token* next_blocker_;
|
||||||
|
};
|
||||||
|
|
||||||
// Plugin_manager methods.
|
// Plugin_manager methods.
|
||||||
|
|
||||||
Plugin_manager::~Plugin_manager()
|
Plugin_manager::~Plugin_manager()
|
||||||
@ -311,6 +350,8 @@ Plugin_manager::claim_file(Input_file* input_file, off_t offset,
|
|||||||
{
|
{
|
||||||
if ((*this->current_)->claim_file(&this->plugin_input_file_))
|
if ((*this->current_)->claim_file(&this->plugin_input_file_))
|
||||||
{
|
{
|
||||||
|
this->any_claimed_ = true;
|
||||||
|
|
||||||
if (this->objects_.size() > handle)
|
if (this->objects_.size() > handle)
|
||||||
return this->objects_[handle];
|
return this->objects_[handle];
|
||||||
|
|
||||||
@ -324,6 +365,31 @@ Plugin_manager::claim_file(Input_file* input_file, off_t offset,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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,
|
||||||
|
// and pull in the archive object.
|
||||||
|
|
||||||
|
void
|
||||||
|
Plugin_manager::save_archive(Archive* archive)
|
||||||
|
{
|
||||||
|
if (this->in_replacement_phase_ || !this->any_claimed_)
|
||||||
|
delete archive;
|
||||||
|
else
|
||||||
|
this->rescannable_.push_back(Rescannable(archive));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save an Input_group. This is like save_archive.
|
||||||
|
|
||||||
|
void
|
||||||
|
Plugin_manager::save_input_group(Input_group* input_group)
|
||||||
|
{
|
||||||
|
if (this->in_replacement_phase_ || !this->any_claimed_)
|
||||||
|
delete input_group;
|
||||||
|
else
|
||||||
|
this->rescannable_.push_back(Rescannable(input_group));
|
||||||
|
}
|
||||||
|
|
||||||
// Call the all-symbols-read handlers.
|
// Call the all-symbols-read handlers.
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -348,9 +414,146 @@ Plugin_manager::all_symbols_read(Workqueue* workqueue, Task* task,
|
|||||||
++this->current_)
|
++this->current_)
|
||||||
(*this->current_)->all_symbols_read();
|
(*this->current_)->all_symbols_read();
|
||||||
|
|
||||||
|
if (this->any_added_)
|
||||||
|
{
|
||||||
|
Task_token* next_blocker = new Task_token(true);
|
||||||
|
next_blocker->add_blocker();
|
||||||
|
workqueue->queue(new Plugin_rescan(this->this_blocker_, next_blocker));
|
||||||
|
this->this_blocker_ = next_blocker;
|
||||||
|
}
|
||||||
|
|
||||||
*last_blocker = this->this_blocker_;
|
*last_blocker = this->this_blocker_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is called when we see a new undefined symbol. If we are in
|
||||||
|
// the replacement phase, this means that we may need to rescan some
|
||||||
|
// archives we have previously seen.
|
||||||
|
|
||||||
|
void
|
||||||
|
Plugin_manager::new_undefined_symbol(Symbol* sym)
|
||||||
|
{
|
||||||
|
if (this->in_replacement_phase_)
|
||||||
|
this->undefined_symbols_.push_back(sym);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rescan archives as needed. This handles the case where a new
|
||||||
|
// object file added by a plugin has an undefined reference to some
|
||||||
|
// symbol defined in an archive.
|
||||||
|
|
||||||
|
void
|
||||||
|
Plugin_manager::rescan(Task* task)
|
||||||
|
{
|
||||||
|
size_t rescan_pos = 0;
|
||||||
|
size_t rescan_size = this->rescannable_.size();
|
||||||
|
while (!this->undefined_symbols_.empty())
|
||||||
|
{
|
||||||
|
if (rescan_pos >= rescan_size)
|
||||||
|
{
|
||||||
|
this->undefined_symbols_.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Undefined_symbol_list undefs;
|
||||||
|
undefs.reserve(this->undefined_symbols_.size());
|
||||||
|
this->undefined_symbols_.swap(undefs);
|
||||||
|
|
||||||
|
size_t min_rescan_pos = rescan_size;
|
||||||
|
|
||||||
|
for (Undefined_symbol_list::const_iterator p = undefs.begin();
|
||||||
|
p != undefs.end();
|
||||||
|
++p)
|
||||||
|
{
|
||||||
|
if (!(*p)->is_undefined())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
this->undefined_symbols_.push_back(*p);
|
||||||
|
|
||||||
|
// Find the first rescan archive which defines this symbol,
|
||||||
|
// starting at the current rescan position. The rescan position
|
||||||
|
// exists so that given -la -lb -lc we don't look for undefined
|
||||||
|
// symbols in -lb back in -la, but instead get the definition
|
||||||
|
// from -lc. Don't bother to look past the current minimum
|
||||||
|
// rescan position.
|
||||||
|
for (size_t i = rescan_pos; i < min_rescan_pos; ++i)
|
||||||
|
{
|
||||||
|
if (this->rescannable_defines(i, *p))
|
||||||
|
{
|
||||||
|
min_rescan_pos = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (min_rescan_pos >= rescan_size)
|
||||||
|
{
|
||||||
|
// We didn't find any rescannable archives which define any
|
||||||
|
// undefined symbols.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Rescannable& r(this->rescannable_[min_rescan_pos]);
|
||||||
|
if (r.is_archive)
|
||||||
|
{
|
||||||
|
Task_lock_obj<Archive> tl(task, r.u.archive);
|
||||||
|
r.u.archive->add_symbols(this->symtab_, this->layout_,
|
||||||
|
this->input_objects_, this->mapfile_);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
size_t next_saw_undefined = this->symtab_->saw_undefined();
|
||||||
|
size_t saw_undefined;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
saw_undefined = next_saw_undefined;
|
||||||
|
|
||||||
|
for (Input_group::const_iterator p = r.u.input_group->begin();
|
||||||
|
p != r.u.input_group->end();
|
||||||
|
++p)
|
||||||
|
{
|
||||||
|
Task_lock_obj<Archive> tl(task, *p);
|
||||||
|
|
||||||
|
(*p)->add_symbols(this->symtab_, this->layout_,
|
||||||
|
this->input_objects_, this->mapfile_);
|
||||||
|
}
|
||||||
|
|
||||||
|
next_saw_undefined = this->symtab_->saw_undefined();
|
||||||
|
}
|
||||||
|
while (saw_undefined != next_saw_undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = rescan_pos; i < min_rescan_pos + 1; ++i)
|
||||||
|
{
|
||||||
|
if (this->rescannable_[i].is_archive)
|
||||||
|
delete this->rescannable_[i].u.archive;
|
||||||
|
else
|
||||||
|
delete this->rescannable_[i].u.input_group;
|
||||||
|
}
|
||||||
|
|
||||||
|
rescan_pos = min_rescan_pos + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return whether the rescannable at index I defines SYM.
|
||||||
|
|
||||||
|
bool
|
||||||
|
Plugin_manager::rescannable_defines(size_t i, Symbol* sym)
|
||||||
|
{
|
||||||
|
const Rescannable& r(this->rescannable_[i]);
|
||||||
|
if (r.is_archive)
|
||||||
|
return r.u.archive->defines_symbol(sym);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (Input_group::const_iterator p = r.u.input_group->begin();
|
||||||
|
p != r.u.input_group->end();
|
||||||
|
++p)
|
||||||
|
{
|
||||||
|
if ((*p)->defines_symbol(sym))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Layout deferred objects.
|
// Layout deferred objects.
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -473,6 +676,7 @@ Plugin_manager::add_input_file(const char* pathname, bool is_lib)
|
|||||||
this->this_blocker_,
|
this->this_blocker_,
|
||||||
next_blocker));
|
next_blocker));
|
||||||
this->this_blocker_ = next_blocker;
|
this->this_blocker_ = next_blocker;
|
||||||
|
this->any_added_ = true;
|
||||||
return LDPS_OK;
|
return LDPS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// plugin.h -- plugin manager for gold -*- C++ -*-
|
// plugin.h -- plugin manager for gold -*- C++ -*-
|
||||||
|
|
||||||
// Copyright 2008, 2009, 2010 Free Software Foundation, Inc.
|
// Copyright 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||||
// Written by Cary Coutant <ccoutant@google.com>.
|
// Written by Cary Coutant <ccoutant@google.com>.
|
||||||
|
|
||||||
// This file is part of gold.
|
// This file is part of gold.
|
||||||
@ -36,12 +36,17 @@ namespace gold
|
|||||||
class General_options;
|
class General_options;
|
||||||
class Input_file;
|
class Input_file;
|
||||||
class Input_objects;
|
class Input_objects;
|
||||||
|
class Archive;
|
||||||
|
class Input_group;
|
||||||
|
class Symbol;
|
||||||
class Symbol_table;
|
class Symbol_table;
|
||||||
class Layout;
|
class Layout;
|
||||||
class Dirsearch;
|
class Dirsearch;
|
||||||
class Mapfile;
|
class Mapfile;
|
||||||
|
class Task;
|
||||||
class Task_token;
|
class Task_token;
|
||||||
class Pluginobj;
|
class Pluginobj;
|
||||||
|
class Plugin_rescan;
|
||||||
|
|
||||||
// This class represents a single plugin library.
|
// This class represents a single plugin library.
|
||||||
|
|
||||||
@ -124,7 +129,8 @@ class Plugin_manager
|
|||||||
public:
|
public:
|
||||||
Plugin_manager(const General_options& options)
|
Plugin_manager(const General_options& options)
|
||||||
: plugins_(), objects_(), deferred_layout_objects_(), input_file_(NULL),
|
: plugins_(), objects_(), deferred_layout_objects_(), input_file_(NULL),
|
||||||
plugin_input_file_(), in_replacement_phase_(false),
|
plugin_input_file_(), rescannable_(), undefined_symbols_(),
|
||||||
|
any_claimed_(false), in_replacement_phase_(false), any_added_(false),
|
||||||
options_(options), workqueue_(NULL), task_(NULL), input_objects_(NULL),
|
options_(options), workqueue_(NULL), task_(NULL), input_objects_(NULL),
|
||||||
symtab_(NULL), layout_(NULL), dirpath_(NULL), mapfile_(NULL),
|
symtab_(NULL), layout_(NULL), dirpath_(NULL), mapfile_(NULL),
|
||||||
this_blocker_(NULL), extra_search_path_()
|
this_blocker_(NULL), extra_search_path_()
|
||||||
@ -153,6 +159,16 @@ class Plugin_manager
|
|||||||
Pluginobj*
|
Pluginobj*
|
||||||
claim_file(Input_file* input_file, off_t offset, off_t filesize);
|
claim_file(Input_file* input_file, off_t offset, off_t filesize);
|
||||||
|
|
||||||
|
// Let the plugin manager save an archive for later rescanning.
|
||||||
|
// This takes ownership of the Archive pointer.
|
||||||
|
void
|
||||||
|
save_archive(Archive*);
|
||||||
|
|
||||||
|
// Let the plugin manager save an input group for later rescanning.
|
||||||
|
// This takes ownership of the Input_group pointer.
|
||||||
|
void
|
||||||
|
save_input_group(Input_group*);
|
||||||
|
|
||||||
// Call the all-symbols-read handlers.
|
// Call the all-symbols-read handlers.
|
||||||
void
|
void
|
||||||
all_symbols_read(Workqueue* workqueue, Task* task,
|
all_symbols_read(Workqueue* workqueue, Task* task,
|
||||||
@ -160,6 +176,11 @@ class Plugin_manager
|
|||||||
Layout* layout, Dirsearch* dirpath, Mapfile* mapfile,
|
Layout* layout, Dirsearch* dirpath, Mapfile* mapfile,
|
||||||
Task_token** last_blocker);
|
Task_token** last_blocker);
|
||||||
|
|
||||||
|
// Tell the plugin manager that we've a new undefined symbol which
|
||||||
|
// may require rescanning.
|
||||||
|
void
|
||||||
|
new_undefined_symbol(Symbol*);
|
||||||
|
|
||||||
// Run deferred layout.
|
// Run deferred layout.
|
||||||
void
|
void
|
||||||
layout_deferred_objects();
|
layout_deferred_objects();
|
||||||
@ -245,9 +266,42 @@ class Plugin_manager
|
|||||||
Plugin_manager(const Plugin_manager&);
|
Plugin_manager(const Plugin_manager&);
|
||||||
Plugin_manager& operator=(const Plugin_manager&);
|
Plugin_manager& operator=(const Plugin_manager&);
|
||||||
|
|
||||||
|
// Plugin_rescan is a Task which calls the private rescan method.
|
||||||
|
friend class Plugin_rescan;
|
||||||
|
|
||||||
|
// An archive or input group which may have to be rescanned if a
|
||||||
|
// plugin adds a new file.
|
||||||
|
struct Rescannable
|
||||||
|
{
|
||||||
|
bool is_archive;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
Archive* archive;
|
||||||
|
Input_group* input_group;
|
||||||
|
} u;
|
||||||
|
|
||||||
|
Rescannable(Archive* archive)
|
||||||
|
: is_archive(true)
|
||||||
|
{ this->u.archive = archive; }
|
||||||
|
|
||||||
|
Rescannable(Input_group* input_group)
|
||||||
|
: is_archive(false)
|
||||||
|
{ this->u.input_group = input_group; }
|
||||||
|
};
|
||||||
|
|
||||||
typedef std::list<Plugin*> Plugin_list;
|
typedef std::list<Plugin*> Plugin_list;
|
||||||
typedef std::vector<Pluginobj*> Object_list;
|
typedef std::vector<Pluginobj*> Object_list;
|
||||||
typedef std::vector<Relobj*> Deferred_layout_list;
|
typedef std::vector<Relobj*> Deferred_layout_list;
|
||||||
|
typedef std::vector<Rescannable> Rescannable_list;
|
||||||
|
typedef std::vector<Symbol*> Undefined_symbol_list;
|
||||||
|
|
||||||
|
// Rescan archives for undefined symbols.
|
||||||
|
void
|
||||||
|
rescan(Task*);
|
||||||
|
|
||||||
|
// See whether the rescannable at index I defines SYM.
|
||||||
|
bool
|
||||||
|
rescannable_defines(size_t i, Symbol* sym);
|
||||||
|
|
||||||
// The list of plugin libraries.
|
// The list of plugin libraries.
|
||||||
Plugin_list plugins_;
|
Plugin_list plugins_;
|
||||||
@ -265,11 +319,24 @@ class Plugin_manager
|
|||||||
Input_file* input_file_;
|
Input_file* input_file_;
|
||||||
struct ld_plugin_input_file plugin_input_file_;
|
struct ld_plugin_input_file plugin_input_file_;
|
||||||
|
|
||||||
// TRUE after the all symbols read event; indicates that we are
|
// A list of archives and input groups being saved for possible
|
||||||
// processing replacement files whose symbols should replace the
|
// later rescanning.
|
||||||
|
Rescannable_list rescannable_;
|
||||||
|
|
||||||
|
// A list of undefined symbols found in added files.
|
||||||
|
Undefined_symbol_list undefined_symbols_;
|
||||||
|
|
||||||
|
// Whether any input files have been claimed by a plugin.
|
||||||
|
bool any_claimed_;
|
||||||
|
|
||||||
|
// Set to true after the all symbols read event; indicates that we
|
||||||
|
// are processing replacement files whose symbols should replace the
|
||||||
// placeholder symbols from the Pluginobj objects.
|
// placeholder symbols from the Pluginobj objects.
|
||||||
bool in_replacement_phase_;
|
bool in_replacement_phase_;
|
||||||
|
|
||||||
|
// Whether any input files or libraries were added by a plugin.
|
||||||
|
bool any_added_;
|
||||||
|
|
||||||
const General_options& options_;
|
const General_options& options_;
|
||||||
Workqueue* workqueue_;
|
Workqueue* workqueue_;
|
||||||
Task* task_;
|
Task* task_;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// readsyms.cc -- read input file symbols for gold
|
// readsyms.cc -- read input file symbols for gold
|
||||||
|
|
||||||
// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
|
// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||||
// Written by Ian Lance Taylor <iant@google.com>.
|
// Written by Ian Lance Taylor <iant@google.com>.
|
||||||
|
|
||||||
// This file is part of gold.
|
// This file is part of gold.
|
||||||
@ -599,6 +599,19 @@ Add_symbols::run(Workqueue*)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Class Input_group.
|
||||||
|
|
||||||
|
// When we delete an Input_group we can delete the archive
|
||||||
|
// information.
|
||||||
|
|
||||||
|
Input_group::~Input_group()
|
||||||
|
{
|
||||||
|
for (Input_group::const_iterator p = this->begin();
|
||||||
|
p != this->end();
|
||||||
|
++p)
|
||||||
|
delete *p;
|
||||||
|
}
|
||||||
|
|
||||||
// Class Start_group.
|
// Class Start_group.
|
||||||
|
|
||||||
Start_group::~Start_group()
|
Start_group::~Start_group()
|
||||||
@ -680,8 +693,8 @@ Finish_group::run(Workqueue*)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now that we're done with the archives, record the incremental layout
|
// Now that we're done with the archives, record the incremental
|
||||||
// information, then delete them.
|
// layout information.
|
||||||
for (Input_group::const_iterator p = this->input_group_->begin();
|
for (Input_group::const_iterator p = this->input_group_->begin();
|
||||||
p != this->input_group_->end();
|
p != this->input_group_->end();
|
||||||
++p)
|
++p)
|
||||||
@ -691,10 +704,12 @@ Finish_group::run(Workqueue*)
|
|||||||
this->layout_->incremental_inputs();
|
this->layout_->incremental_inputs();
|
||||||
if (incremental_inputs != NULL)
|
if (incremental_inputs != NULL)
|
||||||
incremental_inputs->report_archive_end(*p);
|
incremental_inputs->report_archive_end(*p);
|
||||||
|
|
||||||
delete *p;
|
|
||||||
}
|
}
|
||||||
delete this->input_group_;
|
|
||||||
|
if (parameters->options().has_plugins())
|
||||||
|
parameters->options().plugins()->save_input_group(this->input_group_);
|
||||||
|
else
|
||||||
|
delete this->input_group_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Class Read_script
|
// Class Read_script
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// readsyms.h -- read input file symbols for gold -*- C++ -*-
|
// readsyms.h -- read input file symbols for gold -*- C++ -*-
|
||||||
|
|
||||||
// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
|
// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||||
// Written by Ian Lance Taylor <iant@google.com>.
|
// Written by Ian Lance Taylor <iant@google.com>.
|
||||||
|
|
||||||
// This file is part of gold.
|
// This file is part of gold.
|
||||||
@ -191,6 +191,8 @@ class Input_group
|
|||||||
: archives_()
|
: archives_()
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
~Input_group();
|
||||||
|
|
||||||
// Add an archive to the group.
|
// Add an archive to the group.
|
||||||
void
|
void
|
||||||
add_archive(Archive* arch)
|
add_archive(Archive* arch)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// symtab.cc -- the gold symbol table
|
// symtab.cc -- the gold symbol table
|
||||||
|
|
||||||
// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
|
// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||||
// Written by Ian Lance Taylor <iant@google.com>.
|
// Written by Ian Lance Taylor <iant@google.com>.
|
||||||
|
|
||||||
// This file is part of gold.
|
// This file is part of gold.
|
||||||
@ -1002,7 +1002,11 @@ Symbol_table::add_from_object(Object* object,
|
|||||||
// Record every time we see a new undefined symbol, to speed up
|
// Record every time we see a new undefined symbol, to speed up
|
||||||
// archive groups.
|
// archive groups.
|
||||||
if (!was_undefined && ret->is_undefined())
|
if (!was_undefined && ret->is_undefined())
|
||||||
++this->saw_undefined_;
|
{
|
||||||
|
++this->saw_undefined_;
|
||||||
|
if (parameters->options().has_plugins())
|
||||||
|
parameters->options().plugins()->new_undefined_symbol(ret);
|
||||||
|
}
|
||||||
|
|
||||||
// Keep track of common symbols, to speed up common symbol
|
// Keep track of common symbols, to speed up common symbol
|
||||||
// allocation.
|
// allocation.
|
||||||
|
Loading…
Reference in New Issue
Block a user