* elflink.h (elf_link_add_object_symbols): Don't decrease the

alignment of a common symbol.  If two symbols that look like
 	common symbols are found in two shared libraries, and the size is
 	different, use the larger size, and warn if --warn-common.  If a
	common symbol overrides a definition in a shared library, set the
	size to the larger size, and warn if --warn-common.
This commit is contained in:
Ian Lance Taylor
1997-05-16 16:13:33 +00:00
parent 37a684b84d
commit fd6c00bac2
2 changed files with 107 additions and 8 deletions

@ -1,3 +1,12 @@
Fri May 16 12:10:52 1997 Ian Lance Taylor <ian@cygnus.com>
* elflink.h (elf_link_add_object_symbols): Don't decrease the
alignment of a common symbol. If two symbols that look like
common symbols are found in two shared libraries, and the size is
different, use the larger size, and warn if --warn-common. If a
common symbol overrides a definition in a shared library, set the
size to the larger size, and warn if --warn-common.
Thu May 15 14:31:28 1997 Nick Clifton <nickc@cygnus.com> Thu May 15 14:31:28 1997 Nick Clifton <nickc@cygnus.com>
* cpu-arm.c (compatible): Allow default machine to be polymorphed * cpu-arm.c (compatible): Allow default machine to be polymorphed

@ -695,6 +695,7 @@ elf_link_add_object_symbols (abfd, info)
boolean definition; boolean definition;
boolean size_change_ok, type_change_ok; boolean size_change_ok, type_change_ok;
boolean new_weakdef; boolean new_weakdef;
unsigned int old_alignment;
elf_swap_symbol_in (abfd, esym, &sym); elf_swap_symbol_in (abfd, esym, &sym);
@ -782,6 +783,7 @@ elf_link_add_object_symbols (abfd, info)
size_change_ok = false; size_change_ok = false;
type_change_ok = get_elf_backend_data (abfd)->type_change_ok; type_change_ok = get_elf_backend_data (abfd)->type_change_ok;
old_alignment = 0;
if (info->hash->creator->flavour == bfd_target_elf_flavour) if (info->hash->creator->flavour == bfd_target_elf_flavour)
{ {
Elf_Internal_Versym iver; Elf_Internal_Versym iver;
@ -860,6 +862,9 @@ elf_link_add_object_symbols (abfd, info)
|| h->root.type == bfd_link_hash_warning) || h->root.type == bfd_link_hash_warning)
h = (struct elf_link_hash_entry *) h->root.u.i.link; h = (struct elf_link_hash_entry *) h->root.u.i.link;
/* FIXME: There are too many cases here, and it's too
confusing. This code needs to be reorganized somehow. */
/* It's OK to change the type if it used to be a weak /* It's OK to change the type if it used to be a weak
definition, or if the current definition is weak (and definition, or if the current definition is weak (and
hence might be ignored). */ hence might be ignored). */
@ -875,6 +880,9 @@ elf_link_add_object_symbols (abfd, info)
|| h->root.type == bfd_link_hash_undefined) || h->root.type == bfd_link_hash_undefined)
size_change_ok = true; size_change_ok = true;
if (h->root.type == bfd_link_hash_common)
old_alignment = h->root.u.c.p->alignment_power;
override = false; override = false;
/* If we are looking at a dynamic object, and this is a /* If we are looking at a dynamic object, and this is a
@ -896,6 +904,39 @@ elf_link_add_object_symbols (abfd, info)
&& (bind == STB_WEAK && (bind == STB_WEAK
|| ELF_ST_TYPE (sym.st_info) == STT_FUNC))) || ELF_ST_TYPE (sym.st_info) == STT_FUNC)))
{ {
/* In the special case of two symbols which look
like common symbols in a dynamic object, set the
size of the symbol to the larger of the two. */
if ((sec->flags & SEC_ALLOC) != 0
&& (sec->flags & SEC_LOAD) == 0
&& sym.st_size > 0
&& bind != STB_WEAK
&& ELF_ST_TYPE (sym.st_info) != STT_FUNC
&& h->root.type == bfd_link_hash_defined
&& (h->elf_link_hash_flags
& ELF_LINK_HASH_DEF_DYNAMIC) != 0
&& (h->root.u.def.section->owner->flags & DYNAMIC) != 0
&& (h->root.u.def.section->flags & SEC_ALLOC) != 0
&& (h->root.u.def.section->flags & SEC_LOAD) == 0
&& h->size > 0
&& h->type != STT_FUNC
&& sym.st_size != h->size)
{
/* Note that we only warn if the size is
different. If the size is the same, then we
simply let the first shared library override
the second. */
if (! ((*info->callbacks->multiple_common)
(info, h->root.root.string,
h->root.u.def.section->owner,
bfd_link_hash_common,
h->size, abfd, bfd_link_hash_common,
sym.st_size)))
goto error_return;
if (sym.st_size > h->size)
h->size = sym.st_size;
}
override = true; override = true;
sec = bfd_und_section_ptr; sec = bfd_und_section_ptr;
definition = false; definition = false;
@ -925,12 +966,12 @@ elf_link_add_object_symbols (abfd, info)
size_change_ok = true; size_change_ok = true;
} }
/* Similarly, if we are not looking at a dynamic object, and /* If we are not looking at a dynamic object, and we have a
we have a definition, we want to override any definition definition, we want to override any definition we may
we may have from a dynamic object. Symbols from regular have from a dynamic object. Symbols from regular files
files always take precedence over symbols from dynamic always take precedence over symbols from dynamic objects,
objects, even if they are defined after the dynamic even if they are defined after the dynamic object in the
object in the link. */ link. */
if (! dynamic if (! dynamic
&& (definition && (definition
|| (bfd_is_com_section (sec) || (bfd_is_com_section (sec)
@ -958,6 +999,49 @@ elf_link_add_object_symbols (abfd, info)
h->verinfo.vertree = NULL; h->verinfo.vertree = NULL;
} }
/* If we are not looking at a shared library and we have a
common symbol, and the symbol in the shared library is in
an uninitialized section, then treat the shared library
symbol as a common symbol. This will not always be
correct, but it should do little harm. Note that the
above condition already handled cases in which a common
symbol should simply override the definition in the
shared library. */
if (! dynamic
&& ! override
&& bfd_is_com_section (sec)
&& h->root.type == bfd_link_hash_defined
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0
&& (h->root.u.def.section->owner->flags & DYNAMIC) != 0
&& (h->root.u.def.section->flags & SEC_ALLOC) != 0
&& (h->root.u.def.section->flags & SEC_LOAD) == 0
&& h->size > 0
&& h->type != STT_FUNC)
{
/* It would be best if we could set the hash table entry
to a common symbol, but we don't know what to use for
the section or the alignment. */
if (! ((*info->callbacks->multiple_common)
(info, h->root.root.string,
h->root.u.def.section->owner, bfd_link_hash_common,
h->size, abfd, bfd_link_hash_common, value)))
goto error_return;
if (h->size > value)
value = h->size;
/* FIXME: We no longer know the alignment required by
the symbol in the shared library, so we just wind up
using the one from the regular object. */
override = true;
h->root.type = bfd_link_hash_undefined;
h->root.u.undef.abfd = h->root.u.def.section->owner;
size_change_ok = true;
type_change_ok = true;
h->verinfo.vertree = NULL;
}
if (ever != NULL if (ever != NULL
&& ! override && ! override
&& vernum > 1 && vernum > 1
@ -1001,10 +1085,16 @@ elf_link_add_object_symbols (abfd, info)
new_weakdef = true; new_weakdef = true;
} }
/* Get the alignment of a common symbol. */ /* Set the alignment of a common symbol. */
if (sym.st_shndx == SHN_COMMON if (sym.st_shndx == SHN_COMMON
&& h->root.type == bfd_link_hash_common) && h->root.type == bfd_link_hash_common)
h->root.u.c.p->alignment_power = bfd_log2 (sym.st_value); {
unsigned int align;
align = bfd_log2 (sym.st_value);
if (align > old_alignment)
h->root.u.c.p->alignment_power = align;
}
if (info->hash->creator->flavour == bfd_target_elf_flavour) if (info->hash->creator->flavour == bfd_target_elf_flavour)
{ {