From fd6c00bac275fc94e197aa8496a2e7b5638405fe Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Fri, 16 May 1997 16:13:33 +0000 Subject: [PATCH] * 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. --- bfd/ChangeLog | 9 +++++ bfd/elflink.h | 106 ++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 107 insertions(+), 8 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 84f3d403a55..4451ef0283e 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,12 @@ +Fri May 16 12:10:52 1997 Ian Lance Taylor + + * 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 * cpu-arm.c (compatible): Allow default machine to be polymorphed diff --git a/bfd/elflink.h b/bfd/elflink.h index 78f57ffc63e..a6d06b1633d 100644 --- a/bfd/elflink.h +++ b/bfd/elflink.h @@ -695,6 +695,7 @@ elf_link_add_object_symbols (abfd, info) boolean definition; boolean size_change_ok, type_change_ok; boolean new_weakdef; + unsigned int old_alignment; elf_swap_symbol_in (abfd, esym, &sym); @@ -782,6 +783,7 @@ elf_link_add_object_symbols (abfd, info) size_change_ok = false; type_change_ok = get_elf_backend_data (abfd)->type_change_ok; + old_alignment = 0; if (info->hash->creator->flavour == bfd_target_elf_flavour) { Elf_Internal_Versym iver; @@ -860,6 +862,9 @@ elf_link_add_object_symbols (abfd, info) || h->root.type == bfd_link_hash_warning) 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 definition, or if the current definition is weak (and hence might be ignored). */ @@ -875,6 +880,9 @@ elf_link_add_object_symbols (abfd, info) || h->root.type == bfd_link_hash_undefined) size_change_ok = true; + if (h->root.type == bfd_link_hash_common) + old_alignment = h->root.u.c.p->alignment_power; + override = false; /* 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 || 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; sec = bfd_und_section_ptr; definition = false; @@ -925,12 +966,12 @@ elf_link_add_object_symbols (abfd, info) size_change_ok = true; } - /* Similarly, if we are not looking at a dynamic object, and - we have a definition, we want to override any definition - we may have from a dynamic object. Symbols from regular - files always take precedence over symbols from dynamic - objects, even if they are defined after the dynamic - object in the link. */ + /* If we are not looking at a dynamic object, and we have a + definition, we want to override any definition we may + have from a dynamic object. Symbols from regular files + always take precedence over symbols from dynamic objects, + even if they are defined after the dynamic object in the + link. */ if (! dynamic && (definition || (bfd_is_com_section (sec) @@ -958,6 +999,49 @@ elf_link_add_object_symbols (abfd, info) 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 && ! override && vernum > 1 @@ -1001,10 +1085,16 @@ elf_link_add_object_symbols (abfd, info) new_weakdef = true; } - /* Get the alignment of a common symbol. */ + /* Set the alignment of a common symbol. */ if (sym.st_shndx == SHN_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) { -- 2.30.2