diff options
author | Ian Lance Taylor <iant@google.com> | 2006-10-10 18:54:06 +0000 |
---|---|---|
committer | Ian Lance Taylor <iant@google.com> | 2006-10-10 18:54:06 +0000 |
commit | a783673bd6247d3fcbf2cfe54fe7574d36b97691 (patch) | |
tree | 382ad6bd357c8bd20581d864b0f2c4ada8d303b7 /gold | |
parent | 774a49c04797335bacdeb48d2438dc2863c8a9fe (diff) | |
download | fsf-binutils-gdb-a783673bd6247d3fcbf2cfe54fe7574d36b97691.zip fsf-binutils-gdb-a783673bd6247d3fcbf2cfe54fe7574d36b97691.tar.gz fsf-binutils-gdb-a783673bd6247d3fcbf2cfe54fe7574d36b97691.tar.bz2 |
Avoid multiple definition errors from linkonce sections.
Diffstat (limited to 'gold')
-rw-r--r-- | gold/object.cc | 6 | ||||
-rw-r--r-- | gold/object.h | 35 | ||||
-rw-r--r-- | gold/po/gold.pot | 6 | ||||
-rw-r--r-- | gold/symtab.cc | 49 | ||||
-rw-r--r-- | gold/target-reloc.h | 1 |
5 files changed, 64 insertions, 33 deletions
diff --git a/gold/object.cc b/gold/object.cc index d8658e9..8f1241a 100644 --- a/gold/object.cc +++ b/gold/object.cc @@ -346,9 +346,9 @@ Sized_object<size, big_endian>::include_linkonce_section( const elfcpp::Shdr<size, big_endian>&) { const char* symname = strrchr(name, '.') + 1; - bool omit1 = layout->add_comdat(symname, false); - bool omit2 = layout->add_comdat(name, true); - return omit1 || omit2; + bool include1 = layout->add_comdat(symname, false); + bool include2 = layout->add_comdat(name, true); + return include1 && include2; } // Lay out the input sections. We walk through the sections and check diff --git a/gold/object.h b/gold/object.h index dfcb944..ca227c5 100644 --- a/gold/object.h +++ b/gold/object.h @@ -127,6 +127,21 @@ class Object const Stringpool* sympool, Output_file* of) { return this->do_relocate(options, symtab, sympool, of); } + // Return whether an input section is being included in the link. + bool + is_section_included(unsigned int shnum) const + { + assert(shnum < this->map_to_output_.size()); + return this->map_to_output_[shnum].output_section != NULL; + } + + // Given a section index, return the corresponding Output_section + // (which will be NULL if the section is not included in the link) + // and set *POFF to the offset within that section. + inline Output_section* + output_section(unsigned int shnum, off_t* poff); + + protected: // What we need to know to map an input section to an output // section. We keep an array of these, one for each input section, // indexed by the input section number. @@ -139,16 +154,6 @@ class Object off_t offset; }; - // Given a section index, return the corresponding Map_to_output - // information. - const Map_to_output* - section_output_info(unsigned int shnum) const - { - assert(shnum < this->map_to_output_.size()); - return &this->map_to_output_[shnum]; - } - - protected: // Read the symbols--implemented by child class. virtual void do_read_symbols(Read_symbols_data*) = 0; @@ -248,6 +253,16 @@ Object::sized_target(ACCEPT_SIZE_ENDIAN_ONLY) return static_cast<Sized_target<size, big_endian>*>(this->target_); } +// Implement Object::output_section inline for efficiency. +inline Output_section* +Object::output_section(unsigned int shnum, off_t* poff) +{ + assert(shnum < this->map_to_output_.size()); + const Map_to_output& mo(this->map_to_output_[shnum]); + *poff = mo.offset; + return mo.output_section; +} + // A regular object file. This is size and endian specific. template<int size, bool big_endian> diff --git a/gold/po/gold.pot b/gold/po/gold.pot index 48bc987..f086e6d 100644 --- a/gold/po/gold.pot +++ b/gold/po/gold.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2006-10-04 08:37-0700\n" +"POT-Creation-Date: 2006-10-10 11:40-0700\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -403,7 +403,7 @@ msgstr "" msgid "%s: %s: mixing 32-bit and 64-bit ELF objects\n" msgstr "" -#: symtab.cc:317 +#: symtab.cc:320 #, c-format msgid "%s: %s: bad global symbol name offset %u at %lu\n" msgstr "" @@ -413,7 +413,7 @@ msgstr "" msgid "%s: %s: reloc %zu has bad offset %lu\n" msgstr "" -#: target-reloc.h:106 +#: target-reloc.h:107 #, c-format msgid "%s: %s: undefined reference to '%s'\n" msgstr "" diff --git a/gold/symtab.cc b/gold/symtab.cc index 2251ea7..748218d 100644 --- a/gold/symtab.cc +++ b/gold/symtab.cc @@ -305,12 +305,15 @@ Symbol_table::add_from_object( gold_exit(false); } + const int sym_size = elfcpp::Elf_sizes<size>::sym_size; + const unsigned char* p = reinterpret_cast<const unsigned char*>(syms); - for (size_t i = 0; i < count; ++i) + for (size_t i = 0; i < count; ++i, p += sym_size) { elfcpp::Sym<size, big_endian> sym(p); + elfcpp::Sym<size, big_endian>* psym = &sym; - unsigned int st_name = sym.get_st_name(); + unsigned int st_name = psym->get_st_name(); if (st_name >= sym_name_size) { fprintf(stderr, @@ -320,6 +323,21 @@ Symbol_table::add_from_object( gold_exit(false); } + // A symbol defined in a section which we are not including must + // be treated as an undefined symbol. + unsigned char symbuf[sym_size]; + elfcpp::Sym<size, big_endian> sym2(symbuf); + unsigned int st_shndx = psym->get_st_shndx(); + if (st_shndx != elfcpp::SHN_UNDEF + && st_shndx < elfcpp::SHN_LORESERVE + && !object->is_section_included(st_shndx)) + { + memcpy(symbuf, p, sym_size); + elfcpp::Sym_write<size, big_endian> sw(symbuf); + sw.put_st_shndx(elfcpp::SHN_UNDEF); + psym = &sym2; + } + const char* name = sym_names + st_name; // In an object file, an '@' in the name separates the symbol @@ -331,7 +349,7 @@ Symbol_table::add_from_object( if (ver == NULL) { name = this->namepool_.add(name); - res = this->add_from_object(object, name, NULL, false, sym); + res = this->add_from_object(object, name, NULL, false, *psym); } else { @@ -344,12 +362,10 @@ Symbol_table::add_from_object( ++ver; } ver = this->namepool_.add(ver); - res = this->add_from_object(object, name, ver, def, sym); + res = this->add_from_object(object, name, ver, def, *psym); } *sympointers++ = res; - - p += elfcpp::Elf_sizes<size>::sym_size; } } @@ -393,10 +409,11 @@ Symbol_table::sized_finalize(off_t off, Stringpool* pool) continue; } - const Object::Map_to_output* mo = - sym->object()->section_output_info(sym->shnum()); + off_t secoff; + Output_section* os = sym->object()->output_section(sym->shnum(), + &secoff); - if (mo->output_section == NULL) + if (os == NULL) { // We should be able to erase this symbol from the symbol // table, but at least with gcc 4.0.2 @@ -407,9 +424,7 @@ Symbol_table::sized_finalize(off_t off, Stringpool* pool) } else { - sym->set_value(sym->value() - + mo->output_section->address() - + mo->offset); + sym->set_value(sym->value() + os->address() + secoff); pool->add(sym->name()); ++p; ++count; @@ -470,10 +485,10 @@ Symbol_table::sized_write_globals(const Target*, if (sym->shnum() >= elfcpp::SHN_LORESERVE) continue; - const Object::Map_to_output* mo = - sym->object()->section_output_info(sym->shnum()); - - if (mo->output_section == NULL) + off_t secoff; + Output_section* os = sym->object()->output_section(sym->shnum(), + &secoff); + if (os == NULL) continue; elfcpp::Sym_write<size, big_endian> osym(ps); @@ -482,7 +497,7 @@ Symbol_table::sized_write_globals(const Target*, osym.put_st_size(sym->symsize()); osym.put_st_info(elfcpp::elf_st_info(sym->binding(), sym->type())); osym.put_st_other(elfcpp::elf_st_other(sym->visibility(), sym->other())); - osym.put_st_shndx(mo->output_section->shndx()); + osym.put_st_shndx(os->shndx()); ps += sym_size; } diff --git a/gold/target-reloc.h b/gold/target-reloc.h index 66ff78c..f972b11 100644 --- a/gold/target-reloc.h +++ b/gold/target-reloc.h @@ -94,6 +94,7 @@ relocate_section( else { Symbol* gsym = global_syms[r_sym - local_count]; + assert(gsym != NULL); if (gsym->is_forwarder()) gsym = symtab->resolve_forwards(gsym); |