* elflink.h (elf_link_add_object_symbols): If a symbol is a weak
authorIan Lance Taylor <ian@airs.com>
Mon, 14 Aug 1995 15:57:17 +0000 (15:57 +0000)
committerIan Lance Taylor <ian@airs.com>
Mon, 14 Aug 1995 15:57:17 +0000 (15:57 +0000)
definition, add it to the dynamic symbol table if any dynamic
object mentions it.  If we do add it, make sure we add the
corresponding real symbol.
(elf_adjust_dynamic_symbol): Adjust a weak defined symbol which we
put in the dynamic symbol table, even if no regular object refers
to it.
* elf32-i386.c (elf_i386_check_relocs): When creating a shared
library, don't allocate space for a PC relative reloc against a
local symbol.
* elf32-m68k.c (elf_m68k_check_relocs): Likewise.
* elf32-sparc.c (elf32_sparc_check_relocs): Likewise.
* elf32-i386.c (elf_i386_adjust_dynamic_symbol): Change assertion
to accept symbol with weakdef set.
* elf32-m68k.c (elf_m68k_adjust_dynamic_symbol): Likewise.
* elf32-sparc.c (elf32_sparc_adjust_dynamic_symbol): Likewise.
* elf32-m68k.c (elf_m68k_relocate_section): When creating a shared
libary, don't copy over a PC relative reloc against a local
symbol.
* elf32-sparc.c (elf32_sparc_relocate_section): Likewise.
PR 7711.

bfd/ChangeLog
bfd/elf32-i386.c
bfd/elflink.h

index 13270c1f9d67cc59423cd310750edcaedb9e5490..789137a3eec41e5ea18ce02061f4787e8e7f078a 100644 (file)
@@ -1,3 +1,26 @@
+Mon Aug 14 11:39:24 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * elflink.h (elf_link_add_object_symbols): If a symbol is a weak
+       definition, add it to the dynamic symbol table if any dynamic
+       object mentions it.  If we do add it, make sure we add the
+       corresponding real symbol.
+       (elf_adjust_dynamic_symbol): Adjust a weak defined symbol which we
+       put in the dynamic symbol table, even if no regular object refers
+       to it.
+       * elf32-i386.c (elf_i386_check_relocs): When creating a shared
+       library, don't allocate space for a PC relative reloc against a
+       local symbol.
+       * elf32-m68k.c (elf_m68k_check_relocs): Likewise.
+       * elf32-sparc.c (elf32_sparc_check_relocs): Likewise.
+       * elf32-i386.c (elf_i386_adjust_dynamic_symbol): Change assertion
+       to accept symbol with weakdef set.
+       * elf32-m68k.c (elf_m68k_adjust_dynamic_symbol): Likewise.
+       * elf32-sparc.c (elf32_sparc_adjust_dynamic_symbol): Likewise.
+       * elf32-m68k.c (elf_m68k_relocate_section): When creating a shared
+       libary, don't copy over a PC relative reloc against a local
+       symbol.
+       * elf32-sparc.c (elf32_sparc_relocate_section): Likewise.
+
 Sun Aug 13 00:40:58 1995  Jeff Law  (law@snake.cs.utah.edu)
 
        * som.h (R_HPPA_BEGIN_BRTAB): Define.
index a3622620c75e8097117242b48ac9c5b1248e15c8..e20651605d5cbeb4830f97b98172959932bcc265 100644 (file)
@@ -417,7 +417,8 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
        case R_386_32:
        case R_386_PC32:
          if (info->shared
-             && (sec->flags & SEC_ALLOC) != 0)
+             && (sec->flags & SEC_ALLOC) != 0
+             && (r_type != R_386_PC32 || h != NULL))
            {
              /* When creating a shared object, we must copy these
                  reloc types into the output file.  We create a reloc
@@ -486,6 +487,7 @@ elf_i386_adjust_dynamic_symbol (info, h)
   /* Make sure we know what is going on here.  */
   BFD_ASSERT (dynobj != NULL
              && ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT)
+                 || h->weakdef != NULL
                  || ((h->elf_link_hash_flags
                       & ELF_LINK_HASH_DEF_DYNAMIC) != 0
                      && (h->elf_link_hash_flags
@@ -909,7 +911,11 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
                  || (r_type == R_386_PLT32
                      && h->plt_offset != (bfd_vma) -1)
                  || (r_type == R_386_GOT32
-                     && elf_hash_table (info)->dynamic_sections_created)
+                     && elf_hash_table (info)->dynamic_sections_created
+                     && (! info->shared
+                         || ! info->symbolic
+                         || (h->elf_link_hash_flags
+                             & ELF_LINK_HASH_DEF_REGULAR) == 0))
                  || (info->shared
                      && (r_type == R_386_32
                          || r_type == R_386_PC32)
@@ -927,7 +933,7 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
            }
          else if (h->root.type == bfd_link_hash_undefweak)
            relocation = 0;
-         else if (info->shared)
+         else if (info->shared && !info->symbolic)
            relocation = 0;
          else
            {
@@ -957,13 +963,18 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
              off = h->got_offset;
              BFD_ASSERT (off != (bfd_vma) -1);
 
-             if (! elf_hash_table (info)->dynamic_sections_created)
+             if (! elf_hash_table (info)->dynamic_sections_created
+                 || (info->shared
+                     && info->symbolic
+                     && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)))
                {
-                 /* This is actually a static link.  We must
-                    initialize this entry in the global offset table.
-                    Since the offset must always be a multiple of 4,
-                    we use the least significant bit to record
-                    whether we have initialized it already.
+                 /* This is actually a static link, or it is a
+                    -Bsymbolic link and the symbol is defined
+                    locally.  We must initialize this entry in the
+                    global offset table.  Since the offset must
+                    always be a multiple of 4, we use the least
+                    significant bit to record whether we have
+                    initialized it already.
 
                     When doing a dynamic link, we create a .rel.got
                     relocation entry to initialize the value.  This
@@ -1069,7 +1080,8 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
          if (h->plt_offset == (bfd_vma) -1)
            {
              /* We didn't make a PLT entry for this symbol.  This
-                 happens when statically linking PIC code.  */
+                 happens when statically linking PIC code, or when
+                 using -Bsymbolic.  */
              break;
            }
 
@@ -1304,12 +1316,24 @@ elf_i386_finish_dynamic_symbol (output_bfd, info, h, sym)
       srel = bfd_get_section_by_name (dynobj, ".rel.got");
       BFD_ASSERT (sgot != NULL && srel != NULL);
 
-      bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + h->got_offset);
-
       rel.r_offset = (sgot->output_section->vma
                      + sgot->output_offset
-                     + h->got_offset);
-      rel.r_info = ELF32_R_INFO (h->dynindx, R_386_GLOB_DAT);
+                     + (h->got_offset &~ 1));
+
+      /* If this is a -Bsymbolic link, and the symbol is defined
+        locally, we just want to emit a RELATIVE reloc.  The entry in
+        the global offset table will already have been initialized in
+        the relocate_section function.  */
+      if (info->shared
+         && info->symbolic
+         && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))
+       rel.r_info = ELF32_R_INFO (0, R_386_RELATIVE);
+      else
+       {
+         bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + h->got_offset);
+         rel.r_info = ELF32_R_INFO (h->dynindx, R_386_GLOB_DAT);
+       }
+
       bfd_elf32_swap_reloc_out (output_bfd, &rel,
                                ((Elf32_External_Rel *) srel->contents
                                 + srel->reloc_count));
index ecacfbbddd640e63af8a0e410d45b75434ad6713..07ab9bbb9899bd75666c0170e2c8d3ca142e9084 100644 (file)
@@ -16,6 +16,7 @@ GNU General Public License for more details.
 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
 /* ELF linker code.  */
 
 static boolean elf_link_add_object_symbols
@@ -507,6 +508,7 @@ elf_link_add_object_symbols (abfd, info)
       const char *name;
       struct elf_link_hash_entry *h = NULL;
       boolean definition;
+      boolean new_weakdef;
 
       elf_swap_symbol_in (abfd, esym, &sym);
 
@@ -646,6 +648,7 @@ elf_link_add_object_symbols (abfd, info)
              false, collect, (struct bfd_link_hash_entry **) sym_hash)))
        goto error_return;
 
+      new_weakdef = false;
       if (dynamic
          && definition
          && (flags & BSF_WEAK) != 0
@@ -667,6 +670,7 @@ elf_link_add_object_symbols (abfd, info)
 
          (*sym_hash)->weakdef = weaks;
          weaks = *sym_hash;
+         new_weakdef = true;
        }
 
       /* Get the alignment of a common symbol.  */
@@ -721,7 +725,10 @@ elf_link_add_object_symbols (abfd, info)
                new_flag = ELF_LINK_HASH_DEF_DYNAMIC;
              if ((old_flags & new_flag) != 0
                  || (old_flags & (ELF_LINK_HASH_DEF_REGULAR
-                                  | ELF_LINK_HASH_REF_REGULAR)) != 0)
+                                  | ELF_LINK_HASH_REF_REGULAR)) != 0
+                 || (h->weakdef != NULL
+                     && (old_flags & (ELF_LINK_HASH_DEF_DYNAMIC
+                                      | ELF_LINK_HASH_REF_DYNAMIC)) != 0))
                dynsym = true;
            }
 
@@ -730,6 +737,14 @@ elf_link_add_object_symbols (abfd, info)
            {
              if (! _bfd_elf_link_record_dynamic_symbol (info, h))
                goto error_return;
+             if (h->weakdef != NULL
+                 && ! new_weakdef
+                 && h->weakdef->dynindx == -1)
+               {
+                 if (! _bfd_elf_link_record_dynamic_symbol (info,
+                                                            h->weakdef))
+                   goto error_return;
+               }
            }
        }
     }
@@ -1432,13 +1447,16 @@ elf_adjust_dynamic_symbol (h, data)
 
   /* If this symbol does not require a PLT entry, and it is not
      defined by a dynamic object, or is not referenced by a regular
-     object, ignore it.  FIXME: Do we need to worry about symbols
-     which are defined by one dynamic object and referenced by another
-     one?  */
+     object, ignore it.  We do have to handle a weak defined symbol,
+     even if no regular object refers to it, if we decided to add it
+     to the dynamic symbol table.  FIXME: Do we normally need to worry
+     about symbols which are defined by one dynamic object and
+     referenced by another one?  */
   if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) == 0
       && ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0
          || (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) == 0
-         || (h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) == 0))
+         || ((h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) == 0
+             && (h->weakdef == NULL || h->weakdef->dynindx == -1))))
     return true;
 
   /* If we've already adjusted this symbol, don't do it again.  This