mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2025-02-17 07:58:30 +00:00
* 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:
parent
2f563b5100
commit
15f8229bbf
@ -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.
|
||||
|
146
gold/archive.cc
146
gold/archive.cc
@ -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
|
||||
|
@ -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_;
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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*
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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*
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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"));
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -411,6 +411,7 @@ Plugin_manager::add_input_file(char *pathname)
|
||||
this->symtab_,
|
||||
this->layout_,
|
||||
this->dirpath_,
|
||||
0,
|
||||
this->mapfile_,
|
||||
input_argument,
|
||||
NULL,
|
||||
|
106
gold/readsyms.cc
106
gold/readsyms.cc
@ -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))
|
||||
|
@ -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_;
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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&);
|
||||
|
@ -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. */
|
||||
|
Loading…
x
Reference in New Issue
Block a user