* readsyms.cc (Read_symbols::incompatible_warning): New function.

(Read_symbols::requeue): New function.
	(Read_symbols::do_read_symbols): If make_elf_object fails because
	the target type is not configured, and the file was searched for,
	issue a warning and retry with the next directory.
	(Add_symbols::run): If the file has an incompatible format, and
	it was searched for, requeue the Read_symbols task.  On error,
	release the object.
	* readsyms.h (class Read_symbols): Add dirindex_ field.  Add
	dirindex parameter to constructor.  Change all callers.  Declare
	incompatible_warning and requeue.
	(class Add_symbols): Add dirpath_, dirindex_, mapfile_,
	input_argument_ and input_group_ fields.  Add them to
	constructor.  Change all callers.
	(class Read_script): Add dirindex_ field.  Add it to constructor.
	Change all callers.
	* archive.cc (Archive::setup): Remove input_objects parameter.
	Change all callers.
	(Archive::get_file_and_offset): Likewise.
	(Archive::read_all_symbols): Likewise.
	(Archive::read_symbols): Likewise.
	(Archive::get_elf_object_for_member): Remove input_objects
	parameter.  Add punconfigured parameter.  Change all callers.
	(Archive::add_symbols): Change return type to bool.  Check return
	value of include_member.
	(Archive::include_all_members): Likewise.
	(Archive::include_member): Change return type to bool.  Return
	false if first included object has incompatible target.  Set
	included_member_ field.
	(Add_archive_symbols::run): If add_symbols returns false, requeue
	Read_symbols task.
	* archive.h (class Archive): Add included_member_ field.
	Initialize it in constructor.  Add input_file and searched_for
	methods.  Update declarations.
	(class Add_archive_symbols): Add dirpath_, dirindex_, and
	input_argument_ fields.  Add them to constructor.  Change all
	callers.
	* script.cc: Include "target-select.h".
	(class Parser_closure): Add skip_on_incompatible_target_ and
	found_incompatible_target_ fields.  Add
	skip_on_incompatible_target parameter to constructor.  Change all
	callers.  Add methods skip_on_incompatible_target,
	clear_skip_on_incompatible_target, found_incompatible_target, and
	set_found_incompatible_target.
	(read_input_script): Add dirindex parameter.  Change all callers.
	If parser finds an incompatible target, requeue Read_symbols
	task.
	(script_set_symbol): Clear skip_on_incompatible_target in
	closure.
	(script_add_assertion, script_parse_option): Likewise.
	(script_start_sections, script_add_phdr): Likewise.
	(script_check_output_format): New function.
	* script.h (read_input_script): Update declaration.
	* script-c.h (script_check_output_format): Declare.
	* yyscript.y (file_cmd): Handle OUTPUT_FORMAT.
	(ignore_cmd): Remove OUTPUT_FORMAT.
	* fileread.cc (Input_file::Input_file): Add explicit this.
	(Input_file::will_search_for): New function.
	(Input_file::open): Add pindex parameter.  Change all callers.
	* fileread.h (class Input_file): Add input_file_argument method.
	Declare will_search_for.  Update declarations.
	* object.cc (make_elf_object): Add punconfigured parameter.
	Change all callers.
	* object.h (class Object): Make input_file public.  Add
	searched_for method.
	(make_elf_object): Update declaration.
	* dirsearch.cc (Dirsearch::find): Add pindex parameter.  Use it to
	restart search.
	* dirsearch.h (class Dirsearch): Update declaration.
	* options.h (class General_options): Add --warn-search-mismatch.
	* parameters.cc (Parameters::is_compatible_target): New function.
	* parameters.h (class Parameters): Declare is_compatible_target.
	* workqueue.cc (Workqueue::add_blocker): New function.
	* workqueue.h (class Workqueue): Declare add_blocker.
This commit is contained in:
Ian Lance Taylor 2009-03-14 05:56:46 +00:00
parent 2f563b5100
commit 15f8229bbf
24 changed files with 588 additions and 140 deletions

View File

@ -1,5 +1,80 @@
2009-03-13 Ian Lance Taylor <iant@google.com>
* readsyms.cc (Read_symbols::incompatible_warning): New function.
(Read_symbols::requeue): New function.
(Read_symbols::do_read_symbols): If make_elf_object fails because
the target type is not configured, and the file was searched for,
issue a warning and retry with the next directory.
(Add_symbols::run): If the file has an incompatible format, and
it was searched for, requeue the Read_symbols task. On error,
release the object.
* readsyms.h (class Read_symbols): Add dirindex_ field. Add
dirindex parameter to constructor. Change all callers. Declare
incompatible_warning and requeue.
(class Add_symbols): Add dirpath_, dirindex_, mapfile_,
input_argument_ and input_group_ fields. Add them to
constructor. Change all callers.
(class Read_script): Add dirindex_ field. Add it to constructor.
Change all callers.
* archive.cc (Archive::setup): Remove input_objects parameter.
Change all callers.
(Archive::get_file_and_offset): Likewise.
(Archive::read_all_symbols): Likewise.
(Archive::read_symbols): Likewise.
(Archive::get_elf_object_for_member): Remove input_objects
parameter. Add punconfigured parameter. Change all callers.
(Archive::add_symbols): Change return type to bool. Check return
value of include_member.
(Archive::include_all_members): Likewise.
(Archive::include_member): Change return type to bool. Return
false if first included object has incompatible target. Set
included_member_ field.
(Add_archive_symbols::run): If add_symbols returns false, requeue
Read_symbols task.
* archive.h (class Archive): Add included_member_ field.
Initialize it in constructor. Add input_file and searched_for
methods. Update declarations.
(class Add_archive_symbols): Add dirpath_, dirindex_, and
input_argument_ fields. Add them to constructor. Change all
callers.
* script.cc: Include "target-select.h".
(class Parser_closure): Add skip_on_incompatible_target_ and
found_incompatible_target_ fields. Add
skip_on_incompatible_target parameter to constructor. Change all
callers. Add methods skip_on_incompatible_target,
clear_skip_on_incompatible_target, found_incompatible_target, and
set_found_incompatible_target.
(read_input_script): Add dirindex parameter. Change all callers.
If parser finds an incompatible target, requeue Read_symbols
task.
(script_set_symbol): Clear skip_on_incompatible_target in
closure.
(script_add_assertion, script_parse_option): Likewise.
(script_start_sections, script_add_phdr): Likewise.
(script_check_output_format): New function.
* script.h (read_input_script): Update declaration.
* script-c.h (script_check_output_format): Declare.
* yyscript.y (file_cmd): Handle OUTPUT_FORMAT.
(ignore_cmd): Remove OUTPUT_FORMAT.
* fileread.cc (Input_file::Input_file): Add explicit this.
(Input_file::will_search_for): New function.
(Input_file::open): Add pindex parameter. Change all callers.
* fileread.h (class Input_file): Add input_file_argument method.
Declare will_search_for. Update declarations.
* object.cc (make_elf_object): Add punconfigured parameter.
Change all callers.
* object.h (class Object): Make input_file public. Add
searched_for method.
(make_elf_object): Update declaration.
* dirsearch.cc (Dirsearch::find): Add pindex parameter. Use it to
restart search.
* dirsearch.h (class Dirsearch): Update declaration.
* options.h (class General_options): Add --warn-search-mismatch.
* parameters.cc (Parameters::is_compatible_target): New function.
* parameters.h (class Parameters): Declare is_compatible_target.
* workqueue.cc (Workqueue::add_blocker): New function.
* workqueue.h (class Workqueue): Declare add_blocker.
* fileread.cc (Input_file::open): Remove options parameter.
Change all callers.
(Input_file::open_binary): Likewise.

View File

@ -87,7 +87,7 @@ const char Archive::arfmag[2] = { '`', '\n' };
// table.
void
Archive::setup(Input_objects* input_objects)
Archive::setup()
{
// We need to ignore empty archives.
if (this->input_file_->file().filesize() == sarmag)
@ -132,7 +132,7 @@ Archive::setup(Input_objects* input_objects)
preread_syms = false;
#endif
if (preread_syms)
this->read_all_symbols(input_objects);
this->read_all_symbols();
}
// Unlock any nested archives.
@ -441,8 +441,7 @@ Archive::end()
// to the name of the archive member. Return TRUE on success.
bool
Archive::get_file_and_offset(off_t off, Input_objects* input_objects,
Input_file** input_file, off_t* memoff,
Archive::get_file_and_offset(off_t off, Input_file** input_file, off_t* memoff,
off_t* memsize, std::string* member_name)
{
off_t nested_off;
@ -482,17 +481,18 @@ Archive::get_file_and_offset(off_t off, Input_objects* input_objects,
new Input_file_argument(member_name->c_str(), false, "", false,
parameters->options());
*input_file = new Input_file(input_file_arg);
if (!(*input_file)->open(*this->dirpath_, this->task_))
int dummy = 0;
if (!(*input_file)->open(*this->dirpath_, this->task_, &dummy))
return false;
arch = new Archive(*member_name, *input_file, false, this->dirpath_,
this->task_);
arch->setup(input_objects);
arch->setup();
std::pair<Nested_archive_table::iterator, bool> ins =
this->nested_archives_.insert(std::make_pair(*member_name, arch));
gold_assert(ins.second);
}
return arch->get_file_and_offset(nested_off, input_objects, input_file,
memoff, memsize, member_name);
return arch->get_file_and_offset(nested_off, input_file, memoff,
memsize, member_name);
}
// This is an external member of a thin archive. Open the
@ -501,7 +501,8 @@ Archive::get_file_and_offset(off_t off, Input_objects* input_objects,
new Input_file_argument(member_name->c_str(), false, "", false,
this->input_file_->options());
*input_file = new Input_file(input_file_arg);
if (!(*input_file)->open(*this->dirpath_, this->task_))
int dummy = 0;
if (!(*input_file)->open(*this->dirpath_, this->task_, &dummy))
return false;
*memoff = 0;
@ -509,19 +510,21 @@ Archive::get_file_and_offset(off_t off, Input_objects* input_objects,
return true;
}
// Return an ELF object for the member at offset OFF. Set *MEMBER_NAME to
// the name of the member.
// Return an ELF object for the member at offset OFF. If the ELF
// object has an unsupported target type, set *PUNCONFIGURED to true
// and return NULL.
Object*
Archive::get_elf_object_for_member(off_t off, Input_objects* input_objects)
Archive::get_elf_object_for_member(off_t off, bool* punconfigured)
{
std::string member_name;
*punconfigured = false;
Input_file* input_file;
off_t memoff;
off_t memsize;
if (!this->get_file_and_offset(off, input_objects, &input_file, &memoff,
&memsize, &member_name))
std::string member_name;
if (!this->get_file_and_offset(off, &input_file, &memoff, &memsize,
&member_name))
return NULL;
if (parameters->options().has_plugins())
@ -565,28 +568,30 @@ Archive::get_elf_object_for_member(off_t off, Input_objects* input_objects)
}
return make_elf_object((std::string(this->input_file_->filename())
+ "(" + member_name + ")"),
input_file, memoff, ehdr, read_size);
+ "(" + member_name + ")"),
input_file, memoff, ehdr, read_size,
punconfigured);
}
// Read the symbols from all the archive members in the link.
void
Archive::read_all_symbols(Input_objects* input_objects)
Archive::read_all_symbols()
{
for (Archive::const_iterator p = this->begin();
p != this->end();
++p)
this->read_symbols(input_objects, p->off);
this->read_symbols(p->off);
}
// Read the symbols from an archive member in the link. OFF is the file
// offset of the member header.
void
Archive::read_symbols(Input_objects* input_objects, off_t off)
Archive::read_symbols(off_t off)
{
Object* obj = this->get_elf_object_for_member(off, input_objects);
bool dummy;
Object* obj = this->get_elf_object_for_member(off, &dummy);
if (obj == NULL)
return;
@ -602,9 +607,11 @@ Archive::read_symbols(Input_objects* input_objects, off_t off)
// the symbol table. If it exists as a strong undefined symbol, we
// pull in the corresponding element. We have to do this in a loop,
// since pulling in one element may create new undefined symbols which
// may be satisfied by other objects in the archive.
// may be satisfied by other objects in the archive. Return true in
// the normal case, false if the first member we tried to add from
// this archive had an incompatible target.
void
bool
Archive::add_symbols(Symbol_table* symtab, Layout* layout,
Input_objects* input_objects, Mapfile* mapfile)
{
@ -677,8 +684,10 @@ Archive::add_symbols(Symbol_table* symtab, Layout* layout,
why = "-u ";
why += sym_name;
}
this->include_member(symtab, layout, input_objects,
last_seen_offset, mapfile, sym, why.c_str());
if (!this->include_member(symtab, layout, input_objects,
last_seen_offset, mapfile, sym,
why.c_str()))
return false;
added_new_object = true;
}
@ -686,11 +695,13 @@ Archive::add_symbols(Symbol_table* symtab, Layout* layout,
while (added_new_object);
input_objects->archive_stop(this);
return true;
}
// Include all the archive members in the link. This is for --whole-archive.
void
bool
Archive::include_all_members(Symbol_table* symtab, Layout* layout,
Input_objects* input_objects, Mapfile* mapfile)
{
@ -703,8 +714,9 @@ Archive::include_all_members(Symbol_table* symtab, Layout* layout,
p != this->members_.end();
++p)
{
this->include_member(symtab, layout, input_objects, p->first,
mapfile, NULL, "--whole-archive");
if (!this->include_member(symtab, layout, input_objects, p->first,
mapfile, NULL, "--whole-archive"))
return false;
++Archive::total_members;
}
}
@ -714,13 +726,16 @@ Archive::include_all_members(Symbol_table* symtab, Layout* layout,
p != this->end();
++p)
{
this->include_member(symtab, layout, input_objects, p->off,
mapfile, NULL, "--whole-archive");
if (!this->include_member(symtab, layout, input_objects, p->off,
mapfile, NULL, "--whole-archive"))
return false;
++Archive::total_members;
}
}
input_objects->archive_stop(this);
return true;
}
// Return the number of members in the archive. This is only used for
@ -739,8 +754,11 @@ Archive::count_members()
// Include an archive member in the link. OFF is the file offset of
// the member header. WHY is the reason we are including this member.
// Return true if we added the member or if we had an error, return
// false if this was the first member we tried to add from this
// archive and it had an incompatible format.
void
bool
Archive::include_member(Symbol_table* symtab, Layout* layout,
Input_objects* input_objects, off_t off,
Mapfile* mapfile, Symbol* sym, const char* why)
@ -751,6 +769,12 @@ Archive::include_member(Symbol_table* symtab, Layout* layout,
if (p != this->members_.end())
{
Object *obj = p->second.obj_;
if (!this->included_member_
&& this->searched_for()
&& !parameters->is_compatible_target(obj->target()))
return false;
Read_symbols_data *sd = p->second.sd_;
if (mapfile != NULL)
mapfile->report_include_archive_member(obj->name(), sym, why);
@ -758,14 +782,28 @@ Archive::include_member(Symbol_table* symtab, Layout* layout,
{
obj->layout(symtab, layout, sd);
obj->add_symbols(symtab, sd, layout);
this->included_member_ = true;
}
delete sd;
return;
return true;
}
bool unconfigured;
Object* obj = this->get_elf_object_for_member(off, &unconfigured);
if (!this->included_member_
&& this->searched_for()
&& (obj == NULL
? unconfigured
: !parameters->is_compatible_target(obj->target())))
{
if (obj != NULL)
delete obj;
return false;
}
Object* obj = this->get_elf_object_for_member(off, input_objects);
if (obj == NULL)
return;
return true;
if (mapfile != NULL)
mapfile->report_include_archive_member(obj->name(), sym, why);
@ -774,10 +812,13 @@ Archive::include_member(Symbol_table* symtab, Layout* layout,
if (pluginobj != NULL)
{
pluginobj->add_symbols(symtab, NULL, layout);
return;
this->included_member_ = true;
return true;
}
if (input_objects->add_object(obj))
if (!input_objects->add_object(obj))
delete obj;
else
{
Read_symbols_data sd;
obj->read_symbols(&sd);
@ -788,12 +829,11 @@ Archive::include_member(Symbol_table* symtab, Layout* layout,
// for the next task.
if (obj->offset() == 0)
obj->unlock(this->task_);
this->included_member_ = true;
}
else
{
// FIXME: We need to close the descriptor here.
delete obj;
}
return true;
}
// Print statistical information to stderr. This is used for --stats.
@ -838,16 +878,30 @@ Add_archive_symbols::locks(Task_locker* tl)
}
void
Add_archive_symbols::run(Workqueue*)
Add_archive_symbols::run(Workqueue* workqueue)
{
this->archive_->add_symbols(this->symtab_, this->layout_,
this->input_objects_, this->mapfile_);
bool added = this->archive_->add_symbols(this->symtab_, this->layout_,
this->input_objects_,
this->mapfile_);
this->archive_->unlock_nested_archives();
this->archive_->release();
this->archive_->clear_uncached_views();
if (!added)
{
// This archive holds object files which are incompatible with
// our output file.
Read_symbols::incompatible_warning(this->input_argument_,
this->archive_->input_file());
Read_symbols::requeue(workqueue, this->input_objects_, this->symtab_,
this->layout_, this->dirpath_, this->dirindex_,
this->mapfile_, this->input_argument_,
this->input_group_, this->next_blocker_);
delete this->archive_;
return;
}
if (this->input_group_ != NULL)
this->input_group_->add_archive(this->archive_);
else

View File

@ -33,6 +33,7 @@ namespace gold
{
class Task;
class Input_argument;
class Input_file;
class Input_objects;
class Input_group;
@ -51,8 +52,8 @@ class Archive
bool is_thin_archive, Dirsearch* dirpath, Task* task)
: name_(name), input_file_(input_file), armap_(), armap_names_(),
extended_names_(), armap_checked_(), seen_offsets_(), members_(),
is_thin_archive_(is_thin_archive), nested_archives_(),
dirpath_(dirpath), task_(task), num_members_(0)
is_thin_archive_(is_thin_archive), included_member_(false),
nested_archives_(), dirpath_(dirpath), task_(task), num_members_(0)
{ }
// The length of the magic string at the start of an archive.
@ -72,6 +73,11 @@ class Archive
name() const
{ return this->name_; }
// The input file.
const Input_file*
input_file() const
{ return this->input_file_; }
// The file name.
const std::string&
filename() const
@ -79,7 +85,7 @@ class Archive
// Set up the archive: read the symbol map.
void
setup(Input_objects*);
setup();
// Get a reference to the underlying file.
File_read&
@ -131,7 +137,7 @@ class Archive
// Select members from the archive as needed and add them to the
// link.
void
bool
add_symbols(Symbol_table*, Layout*, Input_objects*, Mapfile*);
// Dump statistical information to stderr.
@ -182,33 +188,36 @@ class Archive
// within that file (0 if not a nested archive), and *MEMBER_NAME
// to the name of the archive member. Return TRUE on success.
bool
get_file_and_offset(off_t off, Input_objects* input_objects,
Input_file** input_file, off_t* memoff,
get_file_and_offset(off_t off, Input_file** input_file, off_t* memoff,
off_t* memsize, std::string* member_name);
// Return an ELF object for the member at offset OFF. Set *MEMBER_NAME to
// the name of the member.
// Return an ELF object for the member at offset OFF.
Object*
get_elf_object_for_member(off_t off, Input_objects* input_objects);
get_elf_object_for_member(off_t off, bool*);
// Read the symbols from all the archive members in the link.
void
read_all_symbols(Input_objects* input_objects);
read_all_symbols();
// Read the symbols from an archive member in the link. OFF is the file
// offset of the member header.
void
read_symbols(Input_objects* input_objects, off_t off);
read_symbols(off_t off);
// Include all the archive members in the link.
void
bool
include_all_members(Symbol_table*, Layout*, Input_objects*, Mapfile*);
// Include an archive member in the link.
void
bool
include_member(Symbol_table*, Layout*, Input_objects*, off_t off,
Mapfile*, Symbol*, const char* why);
// Return whether we found this archive by searching a directory.
bool
searched_for() const
{ return this->input_file_->will_search_for(); }
// Iterate over archive members.
class const_iterator;
@ -274,6 +283,8 @@ class Archive
std::map<off_t, Archive_member> members_;
// True if this is a thin archive.
const bool is_thin_archive_;
// True if we have included at least one object from this archive.
bool included_member_;
// Table of nested archives, indexed by filename.
Nested_archive_table nested_archives_;
// The directory search path.
@ -291,13 +302,17 @@ class Add_archive_symbols : public Task
{
public:
Add_archive_symbols(Symbol_table* symtab, Layout* layout,
Input_objects* input_objects, Mapfile* mapfile,
Input_objects* input_objects, Dirsearch* dirpath,
int dirindex, Mapfile* mapfile,
const Input_argument* input_argument,
Archive* archive, Input_group* input_group,
Task_token* this_blocker,
Task_token* next_blocker)
: symtab_(symtab), layout_(layout), input_objects_(input_objects),
mapfile_(mapfile), archive_(archive), input_group_(input_group),
this_blocker_(this_blocker), next_blocker_(next_blocker)
dirpath_(dirpath), dirindex_(dirindex), mapfile_(mapfile),
input_argument_(input_argument), archive_(archive),
input_group_(input_group), this_blocker_(this_blocker),
next_blocker_(next_blocker)
{ }
~Add_archive_symbols();
@ -325,7 +340,10 @@ class Add_archive_symbols : public Task
Symbol_table* symtab_;
Layout* layout_;
Input_objects* input_objects_;
Dirsearch* dirpath_;
int dirindex_;
Mapfile* mapfile_;
const Input_argument* input_argument_;
Archive* archive_;
Input_group* input_group_;
Task_token* this_blocker_;

View File

@ -220,6 +220,8 @@ Dir_cache_task::run(gold::Workqueue*)
namespace gold
{
// Initialize.
void
Dirsearch::initialize(Workqueue* workqueue,
const General_options::Dir_list* directories)
@ -236,25 +238,28 @@ Dirsearch::initialize(Workqueue* workqueue,
}
}
// NOTE: we only log failed file-lookup attempts here. Successfully
// lookups will eventually get logged in File_read::open.
// Search for a file. NOTE: we only log failed file-lookup attempts
// here. Successfully lookups will eventually get logged in
// File_read::open.
std::string
Dirsearch::find(const std::string& n1, const std::string& n2,
bool *is_in_sysroot) const
bool* is_in_sysroot, int* pindex) const
{
gold_assert(!this->token_.is_blocked());
gold_assert(*pindex >= 0);
for (General_options::Dir_list::const_iterator p =
this->directories_->begin();
p != this->directories_->end();
++p)
for (unsigned int i = static_cast<unsigned int>(*pindex);
i < this->directories_->size();
++i)
{
const Search_directory* p = &this->directories_->at(i);
Dir_cache* pdc = caches->lookup(p->name().c_str());
gold_assert(pdc != NULL);
if (pdc->find(n1))
{
*is_in_sysroot = p->is_in_sysroot();
*pindex = i;
return p->name() + '/' + n1;
}
else
@ -266,6 +271,7 @@ Dirsearch::find(const std::string& n1, const std::string& n2,
if (pdc->find(n2))
{
*is_in_sysroot = p->is_in_sysroot();
*pindex = i;
return p->name() + '/' + n2;
}
else
@ -274,6 +280,7 @@ Dirsearch::find(const std::string& n1, const std::string& n2,
}
}
*pindex = -2;
return std::string();
}

View File

@ -53,9 +53,14 @@ class Dirsearch
// second one may be empty). Return a full path name for the file,
// or the empty string if it could not be found. This may only be
// called if the token is not blocked. Set *IS_IN_SYSROOT if the
// file was found in a directory which is in the sysroot.
// file was found in a directory which is in the sysroot. *PINDEX
// should be set to zero the first time this is called; it will be
// updated with the index of the directory where the file is found,
// and that value plus one may be used to find the next file with
// the same name(s).
std::string
find(const std::string&, const std::string& n2, bool *is_in_sysroot) const;
find(const std::string&, const std::string& n2, bool *is_in_sysroot,
int* pindex) const;
// Return the blocker token which controls access.
Task_token*

View File

@ -718,7 +718,7 @@ Input_file::Input_file(const Task* task, const char* name,
this->input_argument_ =
new Input_file_argument(name, false, "", false,
Position_dependent_options());
bool ok = file_.open(task, name, contents, size);
bool ok = this->file_.open(task, name, contents, size);
gold_assert(ok);
}
@ -756,6 +756,17 @@ Input_file::just_symbols() const
return this->input_argument_->just_symbols();
}
// Return whether this is a file that we will search for in the list
// of directories.
bool
Input_file::will_search_for() const
{
return (!IS_ABSOLUTE_PATH(this->input_argument_->name())
&& (this->input_argument_->is_lib()
|| this->input_argument_->extra_search_path() != NULL));
}
// Open the file.
// If the filename is not absolute, we assume it is in the current
@ -766,14 +777,14 @@ Input_file::just_symbols() const
// the file location, rather than the current directory.
bool
Input_file::open(const Dirsearch& dirpath, const Task* task)
Input_file::open(const Dirsearch& dirpath, const Task* task, int *pindex)
{
std::string name;
// Case 1: name is an absolute file, just try to open it
// Case 2: name is relative but is_lib is false and extra_search_path
// is empty
if (IS_ABSOLUTE_PATH (this->input_argument_->name())
if (IS_ABSOLUTE_PATH(this->input_argument_->name())
|| (!this->input_argument_->is_lib()
&& this->input_argument_->extra_search_path() == NULL))
{
@ -796,7 +807,7 @@ Input_file::open(const Dirsearch& dirpath, const Task* task)
n2 = n1 + ".a";
n1 += ".so";
}
name = dirpath.find(n1, n2, &this->is_in_sysroot_);
name = dirpath.find(n1, n2, &this->is_in_sysroot_, pindex);
if (name.empty())
{
gold_error(_("cannot find -l%s"),
@ -819,17 +830,21 @@ Input_file::open(const Dirsearch& dirpath, const Task* task)
name += '/';
name += this->input_argument_->name();
struct stat dummy_stat;
if (::stat(name.c_str(), &dummy_stat) < 0)
if (*pindex > 0 || ::stat(name.c_str(), &dummy_stat) < 0)
{
// extra_search_path failed, so check the normal search-path.
int index = *pindex;
if (index > 0)
--index;
name = dirpath.find(this->input_argument_->name(), "",
&this->is_in_sysroot_);
&this->is_in_sysroot_, &index);
if (name.empty())
{
gold_error(_("cannot find %s"),
this->input_argument_->name());
return false;
}
*pindex = index + 1;
}
this->found_name_ = this->input_argument_->name();
}

View File

@ -431,10 +431,23 @@ class Input_file
Input_file(const Task*, const char* name, const unsigned char* contents,
off_t size);
// Open the file. If the open fails, this will report an error and
// return false.
// Return the command line argument.
const Input_file_argument*
input_file_argument() const
{ return this->input_argument_; }
// Return whether this is a file that we will search for in the list
// of directories.
bool
open(const Dirsearch&, const Task*);
will_search_for() const;
// Open the file. If the open fails, this will report an error and
// return false. If there is a search, it starts at directory
// *PINDEX. *PINDEX should be initialized to zero. It may be
// restarted to find the next file with a matching name by
// incrementing the result and calling this again.
bool
open(const Dirsearch&, const Task*, int *pindex);
// Return the name given by the user. For -lc this will return "c".
const char*

View File

@ -183,7 +183,7 @@ queue_initial_tasks(const General_options& options,
Task_token* next_blocker = new Task_token(true);
next_blocker->add_blocker();
workqueue->queue(new Read_symbols(input_objects, symtab, layout,
&search_path, mapfile, &*p, NULL,
&search_path, 0, mapfile, &*p, NULL,
this_blocker, next_blocker));
this_blocker = next_blocker;
}

View File

@ -2104,8 +2104,12 @@ namespace gold
Object*
make_elf_object(const std::string& name, Input_file* input_file, off_t offset,
const unsigned char* p, section_offset_type bytes)
const unsigned char* p, section_offset_type bytes,
bool* punconfigured)
{
if (punconfigured != NULL)
*punconfigured = false;
if (bytes < elfcpp::EI_NIDENT)
{
gold_error(_("%s: ELF file too short"), name.c_str());
@ -2164,9 +2168,12 @@ make_elf_object(const std::string& name, Input_file* input_file, off_t offset,
return make_elf_sized_object<32, true>(name, input_file,
offset, ehdr);
#else
gold_error(_("%s: not configured to support "
"32-bit big-endian object"),
name.c_str());
if (punconfigured != NULL)
*punconfigured = true;
else
gold_error(_("%s: not configured to support "
"32-bit big-endian object"),
name.c_str());
return NULL;
#endif
}
@ -2177,9 +2184,12 @@ make_elf_object(const std::string& name, Input_file* input_file, off_t offset,
return make_elf_sized_object<32, false>(name, input_file,
offset, ehdr);
#else
gold_error(_("%s: not configured to support "
"32-bit little-endian object"),
name.c_str());
if (punconfigured != NULL)
*punconfigured = true;
else
gold_error(_("%s: not configured to support "
"32-bit little-endian object"),
name.c_str());
return NULL;
#endif
}
@ -2198,9 +2208,12 @@ make_elf_object(const std::string& name, Input_file* input_file, off_t offset,
return make_elf_sized_object<64, true>(name, input_file,
offset, ehdr);
#else
gold_error(_("%s: not configured to support "
"64-bit big-endian object"),
name.c_str());
if (punconfigured != NULL)
*punconfigured = true;
else
gold_error(_("%s: not configured to support "
"64-bit big-endian object"),
name.c_str());
return NULL;
#endif
}
@ -2211,9 +2224,12 @@ make_elf_object(const std::string& name, Input_file* input_file, off_t offset,
return make_elf_sized_object<64, false>(name, input_file,
offset, ehdr);
#else
gold_error(_("%s: not configured to support "
"64-bit little-endian object"),
name.c_str());
if (punconfigured != NULL)
*punconfigured = true;
else
gold_error(_("%s: not configured to support "
"64-bit little-endian object"),
name.c_str());
return NULL;
#endif
}

View File

@ -227,6 +227,15 @@ class Object
target() const
{ return this->target_; }
// Get the file. We pass on const-ness.
Input_file*
input_file()
{ return this->input_file_; }
const Input_file*
input_file() const
{ return this->input_file_; }
// Lock the underlying file.
void
lock(const Task* t)
@ -449,6 +458,11 @@ class Object
is_in_system_directory() const
{ return this->input_file()->is_in_system_directory(); }
// Return whether we found this object by searching a directory.
bool
searched_for() const
{ return this->input_file()->will_search_for(); }
protected:
// Returns NULL for Objects that are not plugin objects. This method
// is overridden in the Pluginobj class.
@ -514,15 +528,6 @@ class Object
virtual void
do_get_global_symbol_counts(const Symbol_table*, size_t*, size_t*) const = 0;
// Get the file. We pass on const-ness.
Input_file*
input_file()
{ return this->input_file_; }
const Input_file*
input_file() const
{ return this->input_file_; }
// Set the target.
void
set_target(int machine, int size, bool big_endian, int osabi,
@ -1917,12 +1922,15 @@ struct Relocate_info
};
// Return an Object appropriate for the input file. P is BYTES long,
// and holds the ELF header.
// and holds the ELF header. If PUNCONFIGURED is not NULL, then if
// this sees an object the linker is not configured to support, it
// sets *PUNCONFIGURED to true and returns NULL without giving an
// error message.
extern Object*
make_elf_object(const std::string& name, Input_file*,
off_t offset, const unsigned char* p,
section_offset_type bytes);
section_offset_type bytes, bool* punconfigured);
} // end namespace gold

View File

@ -854,6 +854,10 @@ class General_options
DEFINE_special(version_script, options::TWO_DASHES, '\0',
N_("Read version script"), N_("FILE"));
DEFINE_bool(warn_search_mismatch, options::TWO_DASHES, '\0', true,
N_("Warn when skipping an incompatible library"),
N_("Don't warn when skipping an incompatible library"));
DEFINE_bool(whole_archive, options::TWO_DASHES, '\0', false,
N_("Include all archive contents"),
N_("Include only needed archive contents"));

View File

@ -97,6 +97,16 @@ Parameters::default_target() const
return *target;
}
// Return whether TARGET is compatible with the target we are using.
bool
Parameters::is_compatible_target(const Target* target) const
{
if (this->target_ == NULL)
return true;
return target == this->target_;
}
Parameters::Target_size_endianness
Parameters::size_and_endianness() const
{

View File

@ -103,6 +103,10 @@ class Parameters
const Target&
default_target() const;
// Return true if TARGET is compatible with the current target.
bool
is_compatible_target(const Target*) const;
bool
doing_static_link() const
{

View File

@ -411,6 +411,7 @@ Plugin_manager::add_input_file(char *pathname)
this->symtab_,
this->layout_,
this->dirpath_,
0,
this->mapfile_,
input_argument,
NULL,

View File

@ -90,6 +90,44 @@ Read_symbols::~Read_symbols()
// Add_symbols task.
}
// If appropriate, issue a warning about skipping an incompatible
// file.
void
Read_symbols::incompatible_warning(const Input_argument* input_argument,
const Input_file* input_file)
{
if (parameters->options().warn_search_mismatch())
gold_warning("skipping incompatible %s while searching for %s",
input_file->filename().c_str(),
input_argument->file().name());
}
// Requeue a Read_symbols task to search for the next object with the
// same name.
void
Read_symbols::requeue(Workqueue* workqueue, Input_objects* input_objects,
Symbol_table* symtab, Layout* layout, Dirsearch* dirpath,
int dirindex, Mapfile* mapfile,
const Input_argument* input_argument,
Input_group* input_group, Task_token* next_blocker)
{
// Bump the directory search index.
++dirindex;
// We don't need to worry about this_blocker, since we already
// reached it. However, we are removing the blocker on next_blocker
// because the calling task is completing. So we need to add a new
// blocker. Since next_blocker may be shared by several tasks, we
// need to increment the count with the workqueue lock held.
workqueue->add_blocker(next_blocker);
workqueue->queue(new Read_symbols(input_objects, symtab, layout, dirpath,
dirindex, mapfile, input_argument,
input_group, NULL, next_blocker));
}
// Return whether a Read_symbols task is runnable. We can read an
// ordinary input file immediately. For an archive specified using
// -l, we have to wait until the search path is complete.
@ -139,7 +177,7 @@ Read_symbols::do_read_symbols(Workqueue* workqueue)
}
Input_file* input_file = new Input_file(&this->input_argument_->file());
if (!input_file->open(*this->dirpath_, this))
if (!input_file->open(*this->dirpath_, this, &this->dirindex_))
return false;
// Read enough of the file to pick up the entire ELF header.
@ -171,7 +209,7 @@ Read_symbols::do_read_symbols(Workqueue* workqueue)
Archive* arch = new Archive(this->input_argument_->file().name(),
input_file, is_thin_archive,
this->dirpath_, this);
arch->setup(this->input_objects_);
arch->setup();
// Unlock the archive so it can be used in the next task.
arch->unlock(this);
@ -179,7 +217,10 @@ Read_symbols::do_read_symbols(Workqueue* workqueue)
workqueue->queue_next(new Add_archive_symbols(this->symtab_,
this->layout_,
this->input_objects_,
this->dirpath_,
this->dirindex_,
this->mapfile_,
this->input_argument_,
arch,
this->input_group_,
this->this_blocker_,
@ -203,7 +244,13 @@ Read_symbols::do_read_symbols(Workqueue* workqueue)
workqueue->queue_next(new Add_symbols(this->input_objects_,
this->symtab_,
this->layout_,
obj, NULL,
this->dirpath_,
this->dirindex_,
this->mapfile_,
this->input_argument_,
this->input_group_,
obj,
NULL,
this->this_blocker_,
this->next_blocker_));
return true;
@ -221,10 +268,24 @@ Read_symbols::do_read_symbols(Workqueue* workqueue)
{
// This is an ELF object.
bool unconfigured;
Object* obj = make_elf_object(input_file->filename(),
input_file, 0, ehdr, read_size);
input_file, 0, ehdr, read_size,
&unconfigured);
if (obj == NULL)
return false;
{
if (unconfigured && input_file->will_search_for())
{
Read_symbols::incompatible_warning(this->input_argument_,
input_file);
input_file->file().release();
input_file->file().unlock(this);
delete input_file;
++this->dirindex_;
return this->do_read_symbols(workqueue);
}
return false;
}
Read_symbols_data* sd = new Read_symbols_data;
obj->read_symbols(sd);
@ -244,7 +305,13 @@ Read_symbols::do_read_symbols(Workqueue* workqueue)
workqueue->queue_next(new Add_symbols(this->input_objects_,
this->symtab_, this->layout_,
obj, sd,
this->dirpath_,
this->dirindex_,
this->mapfile_,
this->input_argument_,
this->input_group_,
obj,
sd,
this->this_blocker_,
this->next_blocker_));
@ -261,6 +328,7 @@ Read_symbols::do_read_symbols(Workqueue* workqueue)
workqueue->queue_soon(new Read_script(this->symtab_,
this->layout_,
this->dirpath_,
this->dirindex_,
this->input_objects_,
this->mapfile_,
this->input_group_,
@ -297,8 +365,8 @@ Read_symbols::do_group(Workqueue* workqueue)
next_blocker->add_blocker();
workqueue->queue_soon(new Read_symbols(this->input_objects_,
this->symtab_, this->layout_,
this->dirpath_, this->mapfile_,
arg, input_group,
this->dirpath_, this->dirindex_,
this->mapfile_, arg, input_group,
this_blocker, next_blocker));
this_blocker = next_blocker;
}
@ -376,7 +444,7 @@ Add_symbols::locks(Task_locker* tl)
// Add the symbols in the object to the symbol table.
void
Add_symbols::run(Workqueue*)
Add_symbols::run(Workqueue* workqueue)
{
Pluginobj* pluginobj = this->object_->pluginobj();
if (pluginobj != NULL)
@ -385,9 +453,23 @@ Add_symbols::run(Workqueue*)
return;
}
if (!this->input_objects_->add_object(this->object_))
// If this file has an incompatible format, try for another file
// with the same name.
if (this->object_->searched_for()
&& !parameters->is_compatible_target(this->object_->target()))
{
// FIXME: We need to close the descriptor here.
Read_symbols::incompatible_warning(this->input_argument_,
this->object_->input_file());
Read_symbols::requeue(workqueue, this->input_objects_, this->symtab_,
this->layout_, this->dirpath_, this->dirindex_,
this->mapfile_, this->input_argument_,
this->input_group_, this->next_blocker_);
this->object_->release();
delete this->object_;
}
else if (!this->input_objects_->add_object(this->object_))
{
this->object_->release();
delete this->object_;
}
else
@ -490,7 +572,7 @@ Read_script::run(Workqueue* workqueue)
{
bool used_next_blocker;
if (!read_input_script(workqueue, this->symtab_, this->layout_,
this->dirpath_, this->input_objects_,
this->dirpath_, this->dirindex_, this->input_objects_,
this->mapfile_, this->input_group_,
this->input_argument_, this->input_file_,
this->next_blocker_, &used_next_blocker))

View File

@ -55,18 +55,30 @@ class Read_symbols : public Task
// NEXT_BLOCKER is used to block the next input file from adding
// symbols.
Read_symbols(Input_objects* input_objects, Symbol_table* symtab,
Layout* layout, Dirsearch* dirpath, Mapfile* mapfile,
const Input_argument* input_argument,
Layout* layout, Dirsearch* dirpath, int dirindex,
Mapfile* mapfile, const Input_argument* input_argument,
Input_group* input_group, Task_token* this_blocker,
Task_token* next_blocker)
: input_objects_(input_objects), symtab_(symtab), layout_(layout),
dirpath_(dirpath), mapfile_(mapfile), input_argument_(input_argument),
input_group_(input_group), this_blocker_(this_blocker),
next_blocker_(next_blocker)
dirpath_(dirpath), dirindex_(dirindex), mapfile_(mapfile),
input_argument_(input_argument), input_group_(input_group),
this_blocker_(this_blocker), next_blocker_(next_blocker)
{ }
~Read_symbols();
// If appropriate, issue a warning about skipping an incompatible
// object.
static void
incompatible_warning(const Input_argument*, const Input_file*);
// Requeue a Read_symbols task to search for the next object with
// the same name.
static void
requeue(Workqueue*, Input_objects*, Symbol_table*, Layout*, Dirsearch*,
int dirindex, Mapfile*, const Input_argument*, Input_group*,
Task_token* next_blocker);
// The standard Task methods.
Task_token*
@ -94,6 +106,7 @@ class Read_symbols : public Task
Symbol_table* symtab_;
Layout* layout_;
Dirsearch* dirpath_;
int dirindex_;
Mapfile* mapfile_;
const Input_argument* input_argument_;
Input_group* input_group_;
@ -112,10 +125,14 @@ class Add_symbols : public Task
// one for the previous input file. NEXT_BLOCKER is used to prevent
// the next task from running.
Add_symbols(Input_objects* input_objects, Symbol_table* symtab,
Layout* layout, Object* object,
Layout* layout, Dirsearch* dirpath, int dirindex,
Mapfile* mapfile, const Input_argument* input_argument,
Input_group* input_group, Object* object,
Read_symbols_data* sd, Task_token* this_blocker,
Task_token* next_blocker)
: input_objects_(input_objects), symtab_(symtab), layout_(layout),
dirpath_(dirpath), dirindex_(dirindex), mapfile_(mapfile),
input_argument_(input_argument), input_group_(input_group),
object_(object), sd_(sd), this_blocker_(this_blocker),
next_blocker_(next_blocker)
{ }
@ -141,6 +158,11 @@ private:
Input_objects* input_objects_;
Symbol_table* symtab_;
Layout* layout_;
Dirsearch* dirpath_;
int dirindex_;
Mapfile* mapfile_;
const Input_argument* input_argument_;
Input_group* input_group_;
Object* object_;
Read_symbols_data* sd_;
Task_token* this_blocker_;
@ -230,11 +252,11 @@ class Read_script : public Task
{
public:
Read_script(Symbol_table* symtab, Layout* layout, Dirsearch* dirpath,
Input_objects* input_objects, Mapfile* mapfile,
int dirindex, Input_objects* input_objects, Mapfile* mapfile,
Input_group* input_group, const Input_argument* input_argument,
Input_file* input_file, Task_token* this_blocker,
Task_token* next_blocker)
: symtab_(symtab), layout_(layout), dirpath_(dirpath),
: symtab_(symtab), layout_(layout), dirpath_(dirpath), dirindex_(dirindex),
input_objects_(input_objects), mapfile_(mapfile),
input_group_(input_group), input_argument_(input_argument),
input_file_(input_file), this_blocker_(this_blocker),
@ -261,6 +283,7 @@ class Read_script : public Task
Symbol_table* symtab_;
Layout* layout_;
Dirsearch* dirpath_;
int dirindex_;
Input_objects* input_objects_;
Mapfile* mapfile_;
Input_group* input_group_;

View File

@ -245,6 +245,13 @@ script_set_common_allocation(void* closure, int);
extern void
script_parse_option(void* closure, const char*, size_t);
/* Called by the bison parser to handle OUTPUT_FORMAT. This return 0
if the parse should be aborted. */
extern int
script_check_output_format(void* closure, const char*, size_t,
const char*, size_t, const char*, size_t);
/* Called by the bison parser to handle SEARCH_DIR. */
extern void

View File

@ -40,6 +40,7 @@
#include "parameters.h"
#include "layout.h"
#include "symtab.h"
#include "target-select.h"
#include "script.h"
#include "script-c.h"
@ -1162,9 +1163,12 @@ class Parser_closure
bool in_group, bool is_in_sysroot,
Command_line* command_line,
Script_options* script_options,
Lex* lex)
Lex* lex,
bool skip_on_incompatible_target)
: filename_(filename), posdep_options_(posdep_options),
in_group_(in_group), is_in_sysroot_(is_in_sysroot),
skip_on_incompatible_target_(skip_on_incompatible_target),
found_incompatible_target_(false),
command_line_(command_line), script_options_(script_options),
version_script_info_(script_options->version_script_info()),
lex_(lex), lineno_(0), charpos_(0), lex_mode_stack_(), inputs_(NULL)
@ -1196,6 +1200,30 @@ class Parser_closure
is_in_sysroot() const
{ return this->is_in_sysroot_; }
// Whether to skip to the next file with the same name if we find an
// incompatible target in an OUTPUT_FORMAT statement.
bool
skip_on_incompatible_target() const
{ return this->skip_on_incompatible_target_; }
// Stop skipping to the next flie on an incompatible target. This
// is called when we make some unrevocable change to the data
// structures.
void
clear_skip_on_incompatible_target()
{ this->skip_on_incompatible_target_ = false; }
// Whether we found an incompatible target in an OUTPUT_FORMAT
// statement.
bool
found_incompatible_target() const
{ return this->found_incompatible_target_; }
// Note that we found an incompatible target.
void
set_found_incompatible_target()
{ this->found_incompatible_target_ = true; }
// Returns the Command_line structure passed in at constructor time.
// This value may be NULL. The caller may modify this, which modifies
// the passed-in Command_line object (not a copy).
@ -1296,6 +1324,12 @@ class Parser_closure
bool in_group_;
// Whether the script was found in a sysrooted directory.
bool is_in_sysroot_;
// If this is true, then if we find an OUTPUT_FORMAT with an
// incompatible target, then we tell the parser to abort so that we
// can search for the next file with the same name.
bool skip_on_incompatible_target_;
// True if we found an OUTPUT_FORMAT with an incompatible target.
bool found_incompatible_target_;
// May be NULL if the user chooses not to pass one in.
Command_line* command_line_;
// Options which may be set from any linker script.
@ -1322,8 +1356,9 @@ class Parser_closure
bool
read_input_script(Workqueue* workqueue, Symbol_table* symtab, Layout* layout,
Dirsearch* dirsearch, Input_objects* input_objects,
Mapfile* mapfile, Input_group* input_group,
Dirsearch* dirsearch, int dirindex,
Input_objects* input_objects, Mapfile* mapfile,
Input_group* input_group,
const Input_argument* input_argument,
Input_file* input_file, Task_token* next_blocker,
bool* used_next_blocker)
@ -1341,10 +1376,21 @@ read_input_script(Workqueue* workqueue, Symbol_table* symtab, Layout* layout,
input_file->is_in_sysroot(),
NULL,
layout->script_options(),
&lex);
&lex,
input_file->will_search_for());
if (yyparse(&closure) != 0)
return false;
{
if (closure.found_incompatible_target())
{
Read_symbols::incompatible_warning(input_argument, input_file);
Read_symbols::requeue(workqueue, input_objects, symtab, layout,
dirsearch, dirindex, mapfile, input_argument,
input_group, next_blocker);
return true;
}
return false;
}
if (!closure.saw_inputs())
return true;
@ -1363,7 +1409,7 @@ read_input_script(Workqueue* workqueue, Symbol_table* symtab, Layout* layout,
nb->add_blocker();
}
workqueue->queue_soon(new Read_symbols(input_objects, symtab,
layout, dirsearch, mapfile, &*p,
layout, dirsearch, 0, mapfile, &*p,
input_group, this_blocker, nb));
this_blocker = nb;
}
@ -1397,7 +1443,8 @@ read_script_file(const char* filename, Command_line* cmdline,
posdep.set_format_enum(General_options::OBJECT_FORMAT_ELF);
Input_file_argument input_argument(filename, false, "", false, posdep);
Input_file input_file(&input_argument);
if (!input_file.open(dirsearch, task))
int dummy = 0;
if (!input_file.open(dirsearch, task, &dummy))
return false;
std::string input_string;
@ -1412,7 +1459,8 @@ read_script_file(const char* filename, Command_line* cmdline,
input_file.is_in_sysroot(),
cmdline,
script_options,
&lex);
&lex,
false);
if (yyparse(&closure) != 0)
{
input_file.file().unlock(task);
@ -1471,7 +1519,7 @@ Script_options::define_symbol(const char* definition)
Position_dependent_options posdep_options;
Parser_closure closure("command line", posdep_options, false, false, NULL,
this, &lex);
this, &lex, false);
if (yyparse(&closure) != 0)
return false;
@ -2191,6 +2239,7 @@ script_set_symbol(void* closurev, const char* name, size_t length,
const bool hidden = hiddeni != 0;
closure->script_options()->add_symbol_assignment(name, length, value,
provide, hidden);
closure->clear_skip_on_incompatible_target();
}
// Called by the bison parser to add an assertion.
@ -2201,6 +2250,7 @@ script_add_assertion(void* closurev, Expression* check, const char* message,
{
Parser_closure* closure = static_cast<Parser_closure*>(closurev);
closure->script_options()->add_assertion(check, message, messagelen);
closure->clear_skip_on_incompatible_target();
}
// Called by the bison parser to parse an OPTION.
@ -2230,6 +2280,34 @@ script_parse_option(void* closurev, const char* option, size_t length)
// into mutable_option, so we can't free it. In cases the class
// does not store such a pointer, this is a memory leak. Alas. :(
}
closure->clear_skip_on_incompatible_target();
}
// Called by the bison parser to handle OUTPUT_FORMAT. OUTPUT_FORMAT
// takes either one or three arguments. In the three argument case,
// the format depends on the endianness option, which we don't
// currently support (FIXME). If we see an OUTPUT_FORMAT for the
// wrong format, then we want to search for a new file. Returning 0
// here will cause the parser to immediately abort.
extern "C" int
script_check_output_format(void* closurev,
const char* default_name, size_t default_length,
const char*, size_t, const char*, size_t)
{
Parser_closure* closure = static_cast<Parser_closure*>(closurev);
std::string name(default_name, default_length);
Target* target = select_target_by_name(name.c_str());
if (target == NULL || !parameters->is_compatible_target(target))
{
if (closure->skip_on_incompatible_target())
{
closure->set_found_incompatible_target();
return 0;
}
// FIXME: Should we warn about the unknown target?
}
return 1;
}
// Called by the bison parser to handle SEARCH_DIR. This is handled
@ -2388,6 +2466,7 @@ script_start_sections(void* closurev)
{
Parser_closure* closure = static_cast<Parser_closure*>(closurev);
closure->script_options()->script_sections()->start_sections();
closure->clear_skip_on_incompatible_target();
}
// Called by the bison parser to finish a SECTIONS clause.
@ -2580,6 +2659,7 @@ script_add_phdr(void* closurev, const char* name, size_t namelen,
Script_sections* ss = closure->script_options()->script_sections();
ss->add_phdr(name, namelen, type, includes_filehdr, includes_phdrs,
is_flags_valid, info->flags, info->load_address);
closure->clear_skip_on_incompatible_target();
}
// Convert a program header string to a type.

View File

@ -389,7 +389,7 @@ class Script_options
// whether the function took over NEXT_BLOCKER.
bool
read_input_script(Workqueue*, Symbol_table*, Layout*, Dirsearch*,
read_input_script(Workqueue*, Symbol_table*, Layout*, Dirsearch*, int,
Input_objects*, Mapfile*, Input_group*,
const Input_argument*, Input_file*,
Task_token* next_blocker, bool* used_next_blocker);

View File

@ -67,7 +67,7 @@ Sized_binary_test(Target* target)
binary.converted_size());
Object* object = make_elf_object("test.o", &input_file, 0,
binary.converted_data(),
binary.converted_size());
binary.converted_size(), NULL);
CHECK(object != NULL);
if (object == NULL)
return false;

View File

@ -43,7 +43,7 @@ Sized_object_test(const unsigned char* test_file, unsigned int test_file_size,
const Task* task = reinterpret_cast<const Task*>(-1);
Input_file input_file(task, "test.o", test_file, test_file_size);
Object* object = make_elf_object("test.o", &input_file, 0,
test_file, test_file_size);
test_file, test_file_size, NULL);
CHECK(object->name() == "test.o");
CHECK(!object->is_dynamic());
CHECK(object->target() == target_test_pointer);

View File

@ -494,4 +494,13 @@ Workqueue::set_thread_count(int threads)
this->condvar_.broadcast();
}
// Add a new blocker to an existing Task_token.
void
Workqueue::add_blocker(Task_token* token)
{
Hold_lock hl(this->lock_);
token->add_blocker();
}
} // End namespace gold.

View File

@ -227,6 +227,12 @@ class Workqueue
void
set_thread_count(int);
// Add a new blocker to an existing Task_token. This must be done
// with the workqueue lock held. This should not be done routinely,
// only in special circumstances.
void
add_blocker(Task_token*);
private:
// This class can not be copied.
Workqueue(const Workqueue&);

View File

@ -245,6 +245,19 @@ file_cmd:
| INPUT '(' input_list ')'
| OPTION '(' string ')'
{ script_parse_option(closure, $3.value, $3.length); }
| OUTPUT_FORMAT '(' string ')'
{
if (!script_check_output_format(closure, $3.value, $3.length,
NULL, 0, NULL, 0))
YYABORT;
}
| OUTPUT_FORMAT '(' string ',' string ',' string ')'
{
if (!script_check_output_format(closure, $3.value, $3.length,
$5.value, $5.length,
$7.value, $7.length))
YYABORT;
}
| PHDRS '{' phdrs_defs '}'
| SEARCH_DIR '(' string ')'
{ script_add_search_dir(closure, $3.value, $3.length); }
@ -266,9 +279,7 @@ file_cmd:
these is more-or-less OK since most scripts simply explicitly
choose the default. */
ignore_cmd:
OUTPUT_FORMAT '(' string ')'
| OUTPUT_FORMAT '(' string ',' string ',' string ')'
| OUTPUT_ARCH '(' string ')'
OUTPUT_ARCH '(' string ')'
;
/* A list of input file names. */