Tue Jun 16 13:06:21 1998 Alan Modra <alan@spri.levels.unisa.edu.au>
[binutils-gdb.git] / bfd / elf32-i386.c
index 9914ea6fe2cd4a497ed00eaeab789ef89b7297be..4d5324a0a8838eb11631de868a2daded4db483f6 100644 (file)
@@ -643,7 +643,8 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
                  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 (h != NULL && info->symbolic
+                 && ELF32_R_TYPE (rel->r_info) == R_386_PC32)
                {
                  struct elf_i386_link_hash_entry *eh;
                  struct elf_i386_pcrel_relocs_copied *p;
@@ -1178,15 +1179,16 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
                  || (r_type == R_386_GOT32
                      && elf_hash_table (info)->dynamic_sections_created
                      && (! info->shared
-                         || ! info->symbolic
+                         || (! info->symbolic && h->dynindx != -1)
                          || (h->elf_link_hash_flags
                              & ELF_LINK_HASH_DEF_REGULAR) == 0))
                  || (info->shared
-                     && (! info->symbolic
+                     && ((! info->symbolic && h->dynindx != -1)
                          || (h->elf_link_hash_flags
                              & ELF_LINK_HASH_DEF_REGULAR) == 0)
                      && (r_type == R_386_32
-                         || r_type == R_386_PC32)))
+                         || r_type == R_386_PC32)
+                     && (input_section->flags & SEC_ALLOC) != 0))
                {
                  /* In these cases, we don't need the relocation
                      value.  We check specially because in some
@@ -1240,15 +1242,16 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
 
              if (! elf_hash_table (info)->dynamic_sections_created
                  || (info->shared
-                     && info->symbolic
+                     && (info->symbolic || h->dynindx == -1)
                      && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)))
                {
                  /* 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
+                    locally, or the symbol was forced to be local
+                    because of a version file.  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
@@ -1437,7 +1440,10 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
              else if (r_type == R_386_PC32)
                {
                  BFD_ASSERT (h != NULL && h->dynindx != -1);
-                 relocate = false;
+                 if ((input_section->flags & SEC_ALLOC) != 0)
+                   relocate = false;
+                 else
+                   relocate = true;
                  outrel.r_info = ELF32_R_INFO (h->dynindx, R_386_PC32);
                }
              else
@@ -1455,7 +1461,10 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
                  else
                    {
                      BFD_ASSERT (h->dynindx != -1);
-                     relocate = false;
+                     if ((input_section->flags & SEC_ALLOC) != 0)
+                       relocate = false;
+                     else
+                       relocate = true;
                      outrel.r_info = ELF32_R_INFO (h->dynindx, R_386_32);
                    }
                }
@@ -1622,8 +1631,6 @@ elf_i386_finish_dynamic_symbol (output_bfd, info, h, sym)
       /* This symbol has an entry in the global offset table.  Set it
         up.  */
 
-      BFD_ASSERT (h->dynindx != -1);
-
       sgot = bfd_get_section_by_name (dynobj, ".got");
       srel = bfd_get_section_by_name (dynobj, ".rel.got");
       BFD_ASSERT (sgot != NULL && srel != NULL);
@@ -1633,11 +1640,12 @@ elf_i386_finish_dynamic_symbol (output_bfd, info, h, sym)
                      + (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.  */
+        locally, we just want to emit a RELATIVE reloc.  Likewise if
+        the symbol was forced to be local because of a version file.
+        The entry in the global offset table will already have been
+        initialized in the relocate_section function.  */
       if (info->shared
-         && info->symbolic
+         && (info->symbolic || h->dynindx == -1)
          && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))
        rel.r_info = ELF32_R_INFO (0, R_386_RELATIVE);
       else