diff options
author | Ian Lance Taylor <ian@airs.com> | 2009-03-14 05:56:46 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@airs.com> | 2009-03-14 05:56:46 +0000 |
commit | 15f8229bbf3f6fff866cbc04b07ddde9f6e41941 (patch) | |
tree | baff1a2307ed76fd05a8c579ada97c1605affcb4 /gold/archive.cc | |
parent | 2f563b5100820d5ca2d8ca0d3dd399e5ba6c798b (diff) | |
download | gdb-15f8229bbf3f6fff866cbc04b07ddde9f6e41941.zip gdb-15f8229bbf3f6fff866cbc04b07ddde9f6e41941.tar.gz gdb-15f8229bbf3f6fff866cbc04b07ddde9f6e41941.tar.bz2 |
* 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.
Diffstat (limited to 'gold/archive.cc')
-rw-r--r-- | gold/archive.cc | 146 |
1 files changed, 100 insertions, 46 deletions
diff --git a/gold/archive.cc b/gold/archive.cc index 33a752e..73fa676 100644 --- a/gold/archive.cc +++ b/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 |