Reclaim reloc space for symbols that have been forced local.
authorAlan Modra <amodra@gmail.com>
Sun, 27 Aug 2000 08:10:16 +0000 (08:10 +0000)
committerAlan Modra <amodra@gmail.com>
Sun, 27 Aug 2000 08:10:16 +0000 (08:10 +0000)
bfd/ChangeLog
bfd/elf32-i386.c

index e0ba4d1..74cdcec 100644 (file)
@@ -1,3 +1,15 @@
+2000-08-27  Alan Modra  <alan@linuxcare.com.au>
+
+       * elf32-i386.c (elf_i386_check_relocs): Keep info on relocs copied
+       for any shared link, not just shared -Bsymbolic.
+       (elf_i386_size_dynamic_sections): Call elf_i386_discard_copies on
+       any shared link, and pass link info to it.
+       (elf_i386_size_dynamic_sections): Update comment.
+       (elf_i386_discard_copies): Modify to discard relocs for symbols
+       that have been forced local.
+       (elf_i386_finish_dynamic_symbol): Don't copy relocs for symbols
+       that have been forced local.
+
 2000-08-24  Denis Chertykov  <denisc@overta.ru> & Nick Clifton  <nickc@redhat.com>
 
        * elflink.h (elf_link_add_object_symbols): Allow common
index bed0315..bdc27f7 100644 (file)
@@ -636,17 +636,19 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
            h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF;
 
          /* If we are creating a shared library, and this is a reloc
-             against a global symbol, or a non PC relative reloc
-             against a local symbol, then we need to copy the reloc
-             into the shared library.  However, if we are linking with
-             -Bsymbolic, we do not need to copy a reloc against a
-             global symbol which is defined in an object we are
-             including in the link (i.e., DEF_REGULAR is set).  At
-             this point we have not seen all the input files, so it is
-             possible that DEF_REGULAR is not set now but will be set
-             later (it is never cleared).  We account for that
-             possibility below by storing information in the
-             pcrel_relocs_copied field of the hash table entry.  */
+            against a global symbol, or a non PC relative reloc
+            against a local symbol, then we need to copy the reloc
+            into the shared library.  However, if we are linking with
+            -Bsymbolic, we do not need to copy a reloc against a
+            global symbol which is defined in an object we are
+            including in the link (i.e., DEF_REGULAR is set).  At
+            this point we have not seen all the input files, so it is
+            possible that DEF_REGULAR is not set now but will be set
+            later (it is never cleared).  We account for that
+            possibility below by storing information in the
+            pcrel_relocs_copied field of the hash table entry.
+            A similar situation occurs when creating shared libraries
+            and symbol visibility changes render the symbol local.  */
          if (info->shared
              && (sec->flags & SEC_ALLOC) != 0
              && (ELF32_R_TYPE (rel->r_info) != R_386_PC32
@@ -656,8 +658,8 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
                              & ELF_LINK_HASH_DEF_REGULAR) == 0))))
            {
              /* When creating a shared object, we must copy these
-                 reloc types into the output file.  We create a reloc
-                 section in dynobj and make room for this reloc.  */
+                reloc types into the output file.  We create a reloc
+                section in dynobj and make room for this reloc.  */
              if (sreloc == NULL)
                {
                  const char *name;
@@ -692,15 +694,13 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
 
              sreloc->_raw_size += sizeof (Elf32_External_Rel);
 
-             /* If we are linking with -Bsymbolic, and this is a
-                 global symbol, we count the number of PC relative
-                 relocations we have entered for this symbol, so that
-                 we can discard them again if the symbol is later
-                 defined by a regular object.  Note that this function
-                 is only called if we are using an elf_i386 linker
-                 hash table, which means that h is really a pointer to
-                 an elf_i386_link_hash_entry.  */
-             if (h != NULL && info->symbolic
+             /* If this is a global symbol, we count the number of PC
+                relative relocations we have entered for this symbol,
+                so that we can discard them later as necessary.  Note
+                that this function is only called if we are using an
+                elf_i386 linker hash table, which means that h is
+                really a pointer to an elf_i386_link_hash_entry.  */
+             if (h != NULL
                  && ELF32_R_TYPE (rel->r_info) == R_386_PC32)
                {
                  struct elf_i386_link_hash_entry *eh;
@@ -1100,10 +1100,10 @@ elf_i386_size_dynamic_sections (output_bfd, info)
      PC relative relocs against symbols defined in a regular object.
      We allocated space for them in the check_relocs routine, but we
      will not fill them in in the relocate_section routine.  */
-  if (info->shared && info->symbolic)
+  if (info->shared)
     elf_i386_link_hash_traverse (elf_i386_hash_table (info),
                                 elf_i386_discard_copies,
-                                (PTR) NULL);
+                                (PTR) info);
 
   /* The check_relocs and adjust_dynamic_symbol entry points have
      determined the sizes of the various dynamic sections.  Allocate
@@ -1197,12 +1197,11 @@ elf_i386_size_dynamic_sections (output_bfd, info)
          continue;
        }
 
-      /* Allocate memory for the section contents.  */
-      /* FIXME: This should be a call to bfd_alloc not bfd_zalloc.
-        Unused entries should be reclaimed before the section's contents
-        are written out, but at the moment this does not happen.  Thus in
-        order to prevent writing out garbage, we initialise the section's
-        contents to zero.  */
+      /* Allocate memory for the section contents.  We use bfd_zalloc
+        here in case unused entries are not reclaimed before the
+        section's contents are written out.  This should not happen,
+        but this way if it does, we get a R_386_NONE reloc instead
+        of garbage.  */
       s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size);
       if (s->contents == NULL && s->_raw_size != 0)
        return false;
@@ -1251,26 +1250,33 @@ elf_i386_size_dynamic_sections (output_bfd, info)
 }
 
 /* This function is called via elf_i386_link_hash_traverse if we are
-   creating a shared object with -Bsymbolic.  It discards the space
-   allocated to copy PC relative relocs against symbols which are
-   defined in regular objects.  We allocated space for them in the
+   creating a shared object.  In the -Bsymbolic case, it discards the
+   space allocated to copy PC relative relocs against symbols which
+   are defined in regular objects.  For the normal non-symbolic case,
+   we also discard space for relocs that have become local due to
+   symbol visibility changes.  We allocated space for them in the 
    check_relocs routine, but we won't fill them in in the
    relocate_section routine.  */
 
 /*ARGSUSED*/
 static boolean
-elf_i386_discard_copies (h, ignore)
+elf_i386_discard_copies (h, inf)
      struct elf_i386_link_hash_entry *h;
-     PTR ignore ATTRIBUTE_UNUSED;
+     PTR inf;
 {
   struct elf_i386_pcrel_relocs_copied *s;
-
-  /* We only discard relocs for symbols defined in a regular object.  */
-  if ((h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
-    return true;
-
-  for (s = h->pcrel_relocs_copied; s != NULL; s = s->next)
-    s->section->_raw_size -= s->count * sizeof (Elf32_External_Rel);
+  struct bfd_link_info *info = (struct bfd_link_info *) inf;
+
+  /* If a symbol has been forced local or we have found a regular
+     definition for the symbolic link case, then we won't be needing
+     any relocs.  */
+  if ((h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0
+      && ((h->root.elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0
+         || info->symbolic))
+    {
+      for (s = h->pcrel_relocs_copied; s != NULL; s = s->next)
+       s->section->_raw_size -= s->count * sizeof (Elf32_External_Rel);
+    }
 
   return true;
 }
@@ -1878,7 +1884,9 @@ elf_i386_finish_dynamic_symbol (output_bfd, info, h, sym)
       ++srel->reloc_count;
     }
 
-  if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_COPY) != 0)
+  if ((h->elf_link_hash_flags & (ELF_LINK_HASH_NEEDS_COPY
+                                | ELF_LINK_FORCED_LOCAL))
+      == ELF_LINK_HASH_NEEDS_COPY)
     {
       asection *s;
       Elf_Internal_Rel rel;