Avoid multiple definition errors from linkonce sections.
This commit is contained in:
parent
774a49c047
commit
a783673bd6
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 ""
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue