From 880cd20d40938ea13ff9d5dbb9393f80cfb98b75 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Sat, 9 Jan 2010 00:13:48 +0000 Subject: [PATCH] PR 11108 * symtab.h (class Symbol): Remove fields is_target_special_ and has_plt_offset_. Add field is_defined_in_discarded_section_. (Symbol::is_defined_in_discarded_section): New function. (Symbol::set_is_defined_in_discarded_section): New function. (Symbol::has_plt_offset): Rewrite. (Symbol::set_plt_offset): Verify that new offset is not -1U. * symtab.cc (Symbol::init_fields): Initialize plt_offset_ to -1U. Don't initialize is_target_special_ or has_plt_offset_. Initialize is_defined_in_discarded_section_. (Symbol_table::add_from_relobj): If appropriate, set is_defined_in_discarded_section. * resolve.cc (Symbol::override_base_with_special): Don't test is_target_special_. Change has_plt_offset_ to has_plt_offset(). * target-reloc.h (relocate_section): Do special handling for symbols defined in discarded sections for global symbols as well as local symbols. --- gold/ChangeLog | 20 +++++++++++ gold/resolve.cc | 3 +- gold/symtab.cc | 14 +++++--- gold/symtab.h | 64 +++++++++++++++++++--------------- gold/target-reloc.h | 83 +++++++++++++++++++++++++++------------------ 5 files changed, 117 insertions(+), 67 deletions(-) diff --git a/gold/ChangeLog b/gold/ChangeLog index 046d87aceaa..37a28f11e61 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,23 @@ +2010-01-08 Ian Lance Taylor + + PR 11108 + * symtab.h (class Symbol): Remove fields is_target_special_ and + has_plt_offset_. Add field is_defined_in_discarded_section_. + (Symbol::is_defined_in_discarded_section): New function. + (Symbol::set_is_defined_in_discarded_section): New function. + (Symbol::has_plt_offset): Rewrite. + (Symbol::set_plt_offset): Verify that new offset is not -1U. + * symtab.cc (Symbol::init_fields): Initialize plt_offset_ to -1U. + Don't initialize is_target_special_ or has_plt_offset_. + Initialize is_defined_in_discarded_section_. + (Symbol_table::add_from_relobj): If appropriate, set + is_defined_in_discarded_section. + * resolve.cc (Symbol::override_base_with_special): Don't test + is_target_special_. Change has_plt_offset_ to has_plt_offset(). + * target-reloc.h (relocate_section): Do special handling for + symbols defined in discarded sections for global symbols as well + as local symbols. + 2010-01-08 Ian Lance Taylor * dynobj.cc (big_endian>::find_dynsym_sections): Set pi to NULL in diff --git a/gold/resolve.cc b/gold/resolve.cc index ca71264d4df..9a402f39277 100644 --- a/gold/resolve.cc +++ b/gold/resolve.cc @@ -859,9 +859,8 @@ Symbol::override_base_with_special(const Symbol* from) // We shouldn't see these flags. If we do, we need to handle them // somehow. - gold_assert(!from->is_target_special_ || this->is_target_special_); gold_assert(!from->is_forwarder_); - gold_assert(!from->has_plt_offset_); + gold_assert(!from->has_plt_offset()); gold_assert(!from->has_warning_); gold_assert(!from->is_copied_from_dynobj_); gold_assert(!from->is_forced_local_); diff --git a/gold/symtab.cc b/gold/symtab.cc index 984843863e8..92a91bc1012 100644 --- a/gold/symtab.cc +++ b/gold/symtab.cc @@ -59,24 +59,23 @@ Symbol::init_fields(const char* name, const char* version, this->symtab_index_ = 0; this->dynsym_index_ = 0; this->got_offsets_.init(); - this->plt_offset_ = 0; + this->plt_offset_ = -1U; this->type_ = type; this->binding_ = binding; this->visibility_ = visibility; this->nonvis_ = nonvis; - this->is_target_special_ = false; this->is_def_ = false; this->is_forwarder_ = false; this->has_alias_ = false; this->needs_dynsym_entry_ = false; this->in_reg_ = false; this->in_dyn_ = false; - this->has_plt_offset_ = false; this->has_warning_ = false; this->is_copied_from_dynobj_ = false; this->is_forced_local_ = false; this->is_ordinary_shndx_ = false; this->in_real_elf_ = false; + this->is_defined_in_discarded_section_ = false; } // Return the demangled version of the symbol's name, but only @@ -1070,10 +1069,14 @@ Symbol_table::add_from_relobj( // A symbol defined in a section which we are not including must // be treated as an undefined symbol. + bool is_defined_in_discarded_section = false; if (st_shndx != elfcpp::SHN_UNDEF && is_ordinary && !relobj->is_section_included(st_shndx)) - st_shndx = elfcpp::SHN_UNDEF; + { + st_shndx = elfcpp::SHN_UNDEF; + is_defined_in_discarded_section = true; + } // In an object file, an '@' in the name separates the symbol // name from the version name. If there are two '@' characters, @@ -1190,6 +1193,9 @@ Symbol_table::add_from_relobj( if (is_forced_local) this->force_local(res); + if (is_defined_in_discarded_section) + res->set_is_defined_in_discarded_section(); + (*sympointers)[i] = res; } } diff --git a/gold/symtab.h b/gold/symtab.h index f79fc8d2653..c8aac26bd8e 100644 --- a/gold/symtab.h +++ b/gold/symtab.h @@ -1,6 +1,6 @@ // symtab.h -- the gold symbol table -*- C++ -*- -// Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. // Written by Ian Lance Taylor . // This file is part of gold. @@ -308,6 +308,18 @@ class Symbol set_in_real_elf() { this->in_real_elf_ = true; } + // Return whether this symbol was defined in a section that was + // discarded from the link. This is used to control some error + // reporting. + bool + is_defined_in_discarded_section() const + { return this->is_defined_in_discarded_section_; } + + // Mark this symbol as having been defined in a discarded section. + void + set_is_defined_in_discarded_section() + { this->is_defined_in_discarded_section_ = true; } + // Return the index of this symbol in the output file symbol table. // A value of -1U means that this symbol is not going into the // output file. This starts out as zero, and is set to a non-zero @@ -383,7 +395,7 @@ class Symbol // Return whether this symbol has an entry in the PLT section. bool has_plt_offset() const - { return this->has_plt_offset_; } + { return this->plt_offset_ != -1U; } // Return the offset into the PLT section of this symbol. unsigned int @@ -397,7 +409,7 @@ class Symbol void set_plt_offset(unsigned int plt_offset) { - this->has_plt_offset_ = true; + gold_assert(plt_offset != -1U); this->plt_offset_ = plt_offset; } @@ -870,16 +882,14 @@ class Symbol // non-zero value during Layout::finalize. unsigned int dynsym_index_; - // If this symbol has an entry in the GOT section (has_got_offset_ - // is true), this holds the offset from the start of the GOT section. - // A symbol may have more than one GOT offset (e.g., when mixing - // modules compiled with two different TLS models), but will usually - // have at most one. + // The GOT section entries for this symbol. A symbol may have more + // than one GOT offset (e.g., when mixing modules compiled with two + // different TLS models), but will usually have at most one. Got_offset_list got_offsets_; - // If this symbol has an entry in the PLT section (has_plt_offset_ - // is true), then this is the offset from the start of the PLT - // section. + // If this symbol has an entry in the PLT section, then this is the + // offset from the start of the PLT section. This is -1U if there + // is no PLT entry. unsigned int plt_offset_; // Symbol type (bits 0 to 3). @@ -892,10 +902,7 @@ class Symbol unsigned int nonvis_ : 6; // The type of symbol (bits 16 to 18). Source source_ : 3; - // True if this symbol always requires special target-specific - // handling (bit 19). - bool is_target_special_ : 1; - // True if this is the default version of the symbol (bit 20). + // True if this is the default version of the symbol (bit 19). bool is_def_ : 1; // True if this symbol really forwards to another symbol. This is // used when we discover after the fact that two different entries @@ -903,37 +910,38 @@ class Symbol // never be set for a symbol found in the hash table, but may be set // for a symbol found in the list of symbols attached to an Object. // It forwards to the symbol found in the forwarders_ map of - // Symbol_table (bit 21). + // Symbol_table (bit 20). bool is_forwarder_ : 1; // True if the symbol has an alias in the weak_aliases table in - // Symbol_table (bit 22). + // Symbol_table (bit 21). bool has_alias_ : 1; // True if this symbol needs to be in the dynamic symbol table (bit - // 23). + // 22). bool needs_dynsym_entry_ : 1; - // True if we've seen this symbol in a regular object (bit 24). + // True if we've seen this symbol in a regular object (bit 23). bool in_reg_ : 1; - // True if we've seen this symbol in a dynamic object (bit 25). + // True if we've seen this symbol in a dynamic object (bit 24). bool in_dyn_ : 1; - // True if the symbol has an entry in the PLT section (bit 26). - bool has_plt_offset_ : 1; // True if this is a dynamic symbol which needs a special value in - // the dynamic symbol table (bit 27). + // the dynamic symbol table (bit 25). bool needs_dynsym_value_ : 1; - // True if there is a warning for this symbol (bit 28). + // True if there is a warning for this symbol (bit 26). bool has_warning_ : 1; // True if we are using a COPY reloc for this symbol, so that the - // real definition lives in a dynamic object (bit 29). + // real definition lives in a dynamic object (bit 27). bool is_copied_from_dynobj_ : 1; // True if this symbol was forced to local visibility by a version - // script (bit 30). + // script (bit 28). bool is_forced_local_ : 1; // True if the field u_.from_object.shndx is an ordinary section // index, not one of the special codes from SHN_LORESERVE to - // SHN_HIRESERVE (bit 31). + // SHN_HIRESERVE (bit 29). bool is_ordinary_shndx_ : 1; - // True if we've seen this symbol in a real ELF object. + // True if we've seen this symbol in a real ELF object (bit 30). bool in_real_elf_ : 1; + // True if this symbol is defined in a section which was discarded + // (bit 31). + bool is_defined_in_discarded_section_ : 1; }; // The parts of a symbol which are size specific. Using a template diff --git a/gold/target-reloc.h b/gold/target-reloc.h index 25b3ac43532..06597e2124f 100644 --- a/gold/target-reloc.h +++ b/gold/target-reloc.h @@ -1,6 +1,6 @@ // target-reloc.h -- target specific relocation support -*- C++ -*- -// Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. // Written by Ian Lance Taylor . // This file is part of gold. @@ -217,6 +217,8 @@ relocate_section( Symbol_value symval; const Symbol_value *psymval; + bool is_defined_in_discarded_section; + unsigned int shndx; if (r_sym < local_count && (reloc_symbol_changes == NULL || (*reloc_symbol_changes)[i] == NULL)) @@ -230,38 +232,12 @@ relocate_section( // counterpart in the kept section. The symbol must not // correspond to a section we are folding. bool is_ordinary; - unsigned int shndx = psymval->input_shndx(&is_ordinary); - if (is_ordinary - && shndx != elfcpp::SHN_UNDEF - && !object->is_section_included(shndx) - && !(relinfo->symtab->is_section_folded(object, shndx))) - { - if (comdat_behavior == CB_UNDETERMINED) - { - std::string name = object->section_name(relinfo->data_shndx); - comdat_behavior = get_comdat_behavior(name.c_str()); - } - if (comdat_behavior == CB_PRETEND) - { - bool found; - typename elfcpp::Elf_types::Elf_Addr value = - object->map_to_kept_section(shndx, &found); - if (found) - symval.set_output_value(value + psymval->input_value()); - else - symval.set_output_value(0); - } - else - { - if (comdat_behavior == CB_WARNING) - gold_warning_at_location(relinfo, i, offset, - _("relocation refers to discarded " - "comdat section")); - symval.set_output_value(0); - } - symval.set_no_output_symtab_entry(); - psymval = &symval; - } + shndx = psymval->input_shndx(&is_ordinary); + is_defined_in_discarded_section = + (is_ordinary + && shndx != elfcpp::SHN_UNDEF + && !object->is_section_included(shndx) + && !relinfo->symtab->is_section_folded(object, shndx)); } else { @@ -284,6 +260,46 @@ relocate_section( symval.set_no_output_symtab_entry(); symval.set_output_value(sym->value()); psymval = &symval; + + is_defined_in_discarded_section = + (gsym->is_defined_in_discarded_section() + && gsym->is_undefined()); + shndx = 0; + } + + Symbol_value symval2; + if (is_defined_in_discarded_section) + { + if (comdat_behavior == CB_UNDETERMINED) + { + std::string name = object->section_name(relinfo->data_shndx); + comdat_behavior = get_comdat_behavior(name.c_str()); + } + if (comdat_behavior == CB_PRETEND) + { + // FIXME: This case does not work for global symbols. + // We have no place to store the original section index. + // Fortunately this does not matter for comdat sections, + // only for sections explicitly discarded by a linker + // script. + bool found; + typename elfcpp::Elf_types::Elf_Addr value = + object->map_to_kept_section(shndx, &found); + if (found) + symval2.set_output_value(value + psymval->input_value()); + else + symval2.set_output_value(0); + } + else + { + if (comdat_behavior == CB_WARNING) + gold_warning_at_location(relinfo, i, offset, + _("relocation refers to discarded " + "section")); + symval2.set_output_value(0); + } + symval2.set_no_output_symtab_entry(); + psymval = &symval2; } if (!relocate.relocate(relinfo, target, output_section, i, reloc, @@ -302,6 +318,7 @@ relocate_section( if (sym != NULL && sym->is_undefined() && sym->binding() != elfcpp::STB_WEAK + && !is_defined_in_discarded_section && !target->is_defined_by_abi(sym) && (!parameters->options().shared() // -shared || parameters->options().defs())) // -z defs -- 2.30.2