From 15f8229bbf3f6fff866cbc04b07ddde9f6e41941 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Sat, 14 Mar 2009 05:56:46 +0000 Subject: * 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. --- gold/archive.cc | 146 ++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 100 insertions(+), 46 deletions(-) (limited to 'gold/archive.cc') 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 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 -- cgit v1.1