This commit was manufactured by cvs2svn to create tag
[external/binutils.git] / bfd / elf32-xtensa.c
index c376a17..44450c5 100644 (file)
@@ -1,5 +1,5 @@
 /* Xtensa-specific support for 32-bit ELF.
-   Copyright 2003, 2004 Free Software Foundation, Inc.
+   Copyright 2003 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
@@ -619,6 +619,8 @@ elf_xtensa_check_relocs (abfd, info, sec, relocs)
   struct elf_link_hash_entry **sym_hashes;
   const Elf_Internal_Rela *rel;
   const Elf_Internal_Rela *rel_end;
+  property_table_entry *lit_table;
+  int ltblsize;
 
   if (info->relocatable)
     return TRUE;
@@ -626,6 +628,11 @@ elf_xtensa_check_relocs (abfd, info, sec, relocs)
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
   sym_hashes = elf_sym_hashes (abfd);
 
+  ltblsize = xtensa_read_table_entries (abfd, sec, &lit_table,
+                                       XTENSA_LIT_SEC_NAME);
+  if (ltblsize < 0)
+    return FALSE;
+
   rel_end = relocs + sec->reloc_count;
   for (rel = relocs; rel < rel_end; rel++)
     {
@@ -662,6 +669,11 @@ elf_xtensa_check_relocs (abfd, info, sec, relocs)
 
          if ((sec->flags & SEC_ALLOC) != 0)
            {
+             if ((sec->flags & SEC_READONLY) != 0
+                 && !elf_xtensa_in_literal_pool (lit_table, ltblsize,
+                                                 sec->vma + rel->r_offset))
+               h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF;
+
              if (h->got.refcount <= 0)
                h->got.refcount = 1;
              else
@@ -677,6 +689,11 @@ elf_xtensa_check_relocs (abfd, info, sec, relocs)
 
          if ((sec->flags & SEC_ALLOC) != 0)
            {
+             if ((sec->flags & SEC_READONLY) != 0
+                 && !elf_xtensa_in_literal_pool (lit_table, ltblsize,
+                                                 sec->vma + rel->r_offset))
+               h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF;
+
              if (h->plt.refcount <= 0)
                {
                  h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
@@ -719,6 +736,14 @@ elf_xtensa_check_relocs (abfd, info, sec, relocs)
                  elf_local_got_refcounts (abfd) = local_got_refcounts;
                }
              local_got_refcounts[r_symndx] += 1;
+
+             /* If the relocation is not inside the GOT, the DF_TEXTREL
+                flag needs to be set.  */
+             if (info->shared
+                 && (sec->flags & SEC_READONLY) != 0
+                 && !elf_xtensa_in_literal_pool (lit_table, ltblsize,
+                                                 sec->vma + rel->r_offset))
+               info->flags |= DF_TEXTREL;
            }
          break;
 
@@ -749,6 +774,7 @@ elf_xtensa_check_relocs (abfd, info, sec, relocs)
        }
     }
 
+  free (lit_table);
   return TRUE;
 }
 
@@ -1018,6 +1044,7 @@ elf_xtensa_make_sym_local (info, h)
   else
     {
       /* Don't need any dynamic relocations at all.  */
+      h->elf_link_hash_flags &= ~ELF_LINK_NON_GOT_REF;
       h->plt.refcount = 0;
       h->got.refcount = 0;
     }
@@ -1037,6 +1064,11 @@ elf_xtensa_fix_refcounts (h, arg)
   if (! xtensa_elf_dynamic_symbol_p (h, info))
     elf_xtensa_make_sym_local (info, h);
 
+  /* If the symbol has a relocation outside the GOT, set the
+     DF_TEXTREL flag.  */
+  if ((h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) != 0)
+    info->flags |= DF_TEXTREL;
+
   return TRUE;
 }
 
@@ -1359,6 +1391,12 @@ elf_xtensa_size_dynamic_sections (output_bfd, info)
            return FALSE;
        }
 
+      if ((info->flags & DF_TEXTREL) != 0)
+       {
+         if (!add_dynamic_entry (DT_TEXTREL, 0))
+           return FALSE;
+       }
+
       if (!add_dynamic_entry (DT_XTENSA_GOT_LOC_OFF, 0)
          || !add_dynamic_entry (DT_XTENSA_GOT_LOC_SZ, 0))
        return FALSE;
@@ -1813,8 +1851,6 @@ elf_xtensa_relocate_section (output_bfd, info, input_bfd,
   struct elf_link_hash_entry **sym_hashes;
   asection *srelgot, *srelplt;
   bfd *dynobj;
-  property_table_entry *lit_table = 0;
-  int ltblsize = 0;
   char *error_message = NULL;
 
   if (xtensa_default_isa == NULL)
@@ -1832,14 +1868,6 @@ elf_xtensa_relocate_section (output_bfd, info, input_bfd,
       srelplt = bfd_get_section_by_name (dynobj, ".rela.plt");
     }
 
-  if (elf_hash_table (info)->dynamic_sections_created)
-    {
-      ltblsize = xtensa_read_table_entries (input_bfd, input_section,
-                                           &lit_table, XTENSA_LIT_SEC_NAME);
-      if (ltblsize < 0)
-       return FALSE;
-    }
-
   rel = relocs;
   relend = relocs + input_section->reloc_count;
   for (; rel < relend; rel++)
@@ -1965,10 +1993,10 @@ elf_xtensa_relocate_section (output_bfd, info, input_bfd,
        }
       else
        {
-         RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
-                                  r_symndx, symtab_hdr, sym_hashes,
-                                  h, sec, relocation,
-                                  unresolved_reloc, warned);
+         RELOC_FOR_GLOBAL_SYMBOL (h, sym_hashes, r_symndx,
+                                  symtab_hdr, relocation, sec,
+                                  unresolved_reloc, info,
+                                  warned);
 
          if (relocation == 0
              && !unresolved_reloc
@@ -2040,21 +2068,6 @@ elf_xtensa_relocate_section (output_bfd, info, input_bfd,
                  outrel.r_offset += (input_section->output_section->vma
                                      + input_section->output_offset);
 
-                 /* Complain if the relocation is in a read-only section
-                    and not in a literal pool.  */
-                 if ((input_section->flags & SEC_READONLY) != 0
-                     && !elf_xtensa_in_literal_pool (lit_table, ltblsize,
-                                                     input_section->vma
-                                                     + rel->r_offset))
-                   {
-                     error_message =
-                       _("dynamic relocation in read-only section");
-                     if (!((*info->callbacks->reloc_dangerous)
-                           (info, error_message, input_bfd, input_section,
-                            rel->r_offset)))
-                       return FALSE;
-                   }
-
                  if (dynamic_symbol)
                    {
                      outrel.r_addend = rel->r_addend;
@@ -2142,9 +2155,6 @@ elf_xtensa_relocate_section (output_bfd, info, input_bfd,
        }
     }
 
-  if (lit_table)
-    free (lit_table);
-
   return TRUE;
 }