Add new port: crx-elf
[deliverable/binutils-gdb.git] / bfd / elf32-xtensa.c
index 364e681a76724f0931ead49b39c350b5b10e3910..c2596625ee3c4105aac9ae0ba80d589d4bc684b3 100644 (file)
@@ -1,5 +1,5 @@
 /* Xtensa-specific support for 32-bit ELF.
-   Copyright 2003 Free Software Foundation, Inc.
+   Copyright 2003, 2004 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
@@ -47,9 +47,6 @@ static bfd_boolean elf_xtensa_check_relocs
           const Elf_Internal_Rela *));
 static void elf_xtensa_hide_symbol
   PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *, bfd_boolean));
-static void elf_xtensa_copy_indirect_symbol
-  PARAMS ((struct elf_backend_data *, struct elf_link_hash_entry *,
-          struct elf_link_hash_entry *));
 static asection *elf_xtensa_gc_mark_hook
   PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
           struct elf_link_hash_entry *, Elf_Internal_Sym *));
@@ -63,7 +60,7 @@ static bfd_boolean elf_xtensa_adjust_dynamic_symbol
 static bfd_boolean elf_xtensa_size_dynamic_sections
   PARAMS ((bfd *, struct bfd_link_info *));
 static bfd_boolean elf_xtensa_modify_segment_map
-  PARAMS ((bfd *));
+  PARAMS ((bfd *, struct bfd_link_info *));
 static bfd_boolean elf_xtensa_relocate_section
   PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
           Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
@@ -102,6 +99,8 @@ static bfd_boolean elf_xtensa_new_section_hook
 
 /* Local helper functions.  */
 
+static bfd_boolean xtensa_elf_dynamic_symbol_p
+  PARAMS ((struct elf_link_hash_entry *, struct bfd_link_info *));
 static int property_table_compare
   PARAMS ((const PTR, const PTR));
 static bfd_boolean elf_xtensa_in_literal_pool
@@ -131,8 +130,6 @@ static void do_fix_for_relocatable_link
   PARAMS ((Elf_Internal_Rela *, bfd *, asection *));
 static void do_fix_for_final_link
   PARAMS ((Elf_Internal_Rela *, asection *, bfd_vma *));
-static bfd_boolean xtensa_elf_dynamic_symbol_p
-  PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
 static bfd_vma elf_xtensa_create_plt_entry
   PARAMS ((bfd *, bfd *, unsigned));
 static int elf_xtensa_combine_prop_entries
@@ -212,10 +209,8 @@ static bfd_boolean is_literal_section
   PARAMS ((asection *));
 static int internal_reloc_compare
   PARAMS ((const PTR, const PTR));
-static bfd_boolean get_is_linkonce_section
-  PARAMS ((bfd *, asection *));
 extern char *xtensa_get_property_section_name
-  PARAMS ((bfd *, asection *, const char *));
+  PARAMS ((asection *, const char *));
 
 /* Other functions called directly by the linker.  */
 
@@ -449,6 +444,21 @@ static const bfd_byte elf_xtensa_le_plt_entry[PLT_ENTRY_SIZE] =
   0                    /* unused */
 };
 
+
+static inline bfd_boolean
+xtensa_elf_dynamic_symbol_p (h, info)
+     struct elf_link_hash_entry *h;
+     struct bfd_link_info *info;
+{
+  /* Check if we should do dynamic things to this symbol.  The
+     "ignore_protected" argument need not be set, because Xtensa code
+     does not require special handling of STV_PROTECTED to make function
+     pointer comparisons work properly.  The PLT addresses are never
+     used for function pointers.  */
+
+  return _bfd_elf_dynamic_symbol_p (h, info, 0);
+}
+
 \f
 static int
 property_table_compare (ap, bp)
@@ -487,12 +497,14 @@ xtensa_read_table_entries (abfd, section, table_p, sec_name)
   int block_count;
   bfd_size_type num_records;
   Elf_Internal_Rela *internal_relocs;
+  bfd_vma section_addr;
 
   table_section_name = 
-    xtensa_get_property_section_name (abfd, section, sec_name);
+    xtensa_get_property_section_name (section, sec_name);
   table_section = bfd_get_section_by_name (abfd, table_section_name);
+  free (table_section_name);
   if (table_section != NULL)
-    table_size = bfd_get_section_size_before_reloc (table_section);
+    table_size = table_section->size;
   
   if (table_size == 0) 
     {
@@ -500,16 +512,18 @@ xtensa_read_table_entries (abfd, section, table_p, sec_name)
       return 0;
     }
 
-  num_records = table_size / sizeof (property_table_entry);
+  num_records = table_size / 8;
   table_data = retrieve_contents (abfd, table_section, TRUE);
   blocks = (property_table_entry *)
     bfd_malloc (num_records * sizeof (property_table_entry));
   block_count = 0;
   
+  section_addr = section->output_section->vma + section->output_offset;
+
   /* If the file has not yet been relocated, process the relocations
      and sort out the table entries that apply to the specified section.  */
   internal_relocs = retrieve_internal_relocs (abfd, table_section, TRUE);
-  if (internal_relocs)
+  if (internal_relocs && !table_section->reloc_done)
     {
       unsigned i;
 
@@ -528,7 +542,7 @@ xtensa_read_table_entries (abfd, section, table_p, sec_name)
            {
              bfd_vma sym_off = get_elf_r_symndx_offset (abfd, r_symndx);
              blocks[block_count].address =
-               (section->vma + sym_off + rel->r_addend
+               (section_addr + sym_off + rel->r_addend
                 + bfd_get_32 (abfd, table_data + rel->r_offset));
              blocks[block_count].size =
                bfd_get_32 (abfd, table_data + rel->r_offset + 4);
@@ -538,16 +552,16 @@ xtensa_read_table_entries (abfd, section, table_p, sec_name)
     }
   else
     {
-      /* No relocations.  Presumably the file has been relocated
-        and the addresses are already in the table.  */
+      /* The file has already been relocated and the addresses are
+        already in the table.  */
       bfd_vma off;
 
-      for (off = 0; off < table_size; off += sizeof (property_table_entry)
+      for (off = 0; off < table_size; off += 8
        {
          bfd_vma address = bfd_get_32 (abfd, table_data + off);
 
-         if (address >= section->vma
-             && address < ( section->vma + section->_raw_size))
+         if (address >= section_addr
+             && address < section_addr + section->size)
            {
              blocks[block_count].address = address;
              blocks[block_count].size =
@@ -608,8 +622,6 @@ 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;
@@ -617,11 +629,6 @@ 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++)
     {
@@ -658,11 +665,6 @@ 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
@@ -678,11 +680,6 @@ 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;
@@ -725,14 +722,6 @@ 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;
 
@@ -747,14 +736,14 @@ elf_xtensa_check_relocs (abfd, info, sec, relocs)
        case R_XTENSA_GNU_VTINHERIT:
          /* This relocation describes the C++ object vtable hierarchy.
             Reconstruct it for later use during GC.  */
-         if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
+         if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
            return FALSE;
          break;
 
        case R_XTENSA_GNU_VTENTRY:
          /* This relocation describes which C++ vtable entries are actually
             used.  Record for later use during GC.  */
-         if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
+         if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
            return FALSE;
          break;
 
@@ -763,7 +752,6 @@ elf_xtensa_check_relocs (abfd, info, sec, relocs)
        }
     }
 
-  free (lit_table);
   return TRUE;
 }
 
@@ -782,19 +770,6 @@ elf_xtensa_hide_symbol (info, h, force_local)
 }
 
 
-static void
-elf_xtensa_copy_indirect_symbol (bed, dir, ind)
-     struct elf_backend_data *bed;
-     struct elf_link_hash_entry *dir, *ind;
-{
-  _bfd_elf_link_hash_copy_indirect (bed, dir, ind);
-
-  /* The standard function doesn't copy the NEEDS_PLT flag.  */
-  dir->elf_link_hash_flags |=
-    (ind->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT);
-}
-
-
 /* Return the section that should be marked against GC for a given
    relocation.  */
 
@@ -1046,7 +1021,6 @@ 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;
     }
@@ -1063,14 +1037,9 @@ elf_xtensa_fix_refcounts (h, arg)
   if (h->root.type == bfd_link_hash_warning)
     h = (struct elf_link_hash_entry *) h->root.u.i.link;
 
-  if (! xtensa_elf_dynamic_symbol_p (info, h))
+  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;
 }
 
@@ -1086,7 +1055,7 @@ elf_xtensa_allocate_plt_size (h, arg)
     h = (struct elf_link_hash_entry *) h->root.u.i.link;
 
   if (h->plt.refcount > 0)
-    srelplt->_raw_size += (h->plt.refcount * sizeof (Elf32_External_Rela));
+    srelplt->size += (h->plt.refcount * sizeof (Elf32_External_Rela));
 
   return TRUE;
 }
@@ -1103,7 +1072,7 @@ elf_xtensa_allocate_got_size (h, arg)
     h = (struct elf_link_hash_entry *) h->root.u.i.link;
 
   if (h->got.refcount > 0)
-    srelgot->_raw_size += (h->got.refcount * sizeof (Elf32_External_Rela));
+    srelgot->size += (h->got.refcount * sizeof (Elf32_External_Rela));
 
   return TRUE;
 }
@@ -1132,8 +1101,8 @@ elf_xtensa_allocate_local_got_size (info, srelgot)
       for (j = 0; j < cnt; ++j)
        {
          if (local_got_refcounts[j] > 0)
-           srelgot->_raw_size += (local_got_refcounts[j]
-                                  * sizeof (Elf32_External_Rela));
+           srelgot->size += (local_got_refcounts[j]
+                             * sizeof (Elf32_External_Rela));
        }
     }
 }
@@ -1162,12 +1131,12 @@ elf_xtensa_size_dynamic_sections (output_bfd, info)
   if (elf_hash_table (info)->dynamic_sections_created)
     {
       /* Set the contents of the .interp section to the interpreter.  */
-      if (! info->shared)
+      if (info->executable)
        {
          s = bfd_get_section_by_name (dynobj, ".interp");
          if (s == NULL)
            abort ();
-         s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER;
+         s->size = sizeof ELF_DYNAMIC_INTERPRETER;
          s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
        }
 
@@ -1175,7 +1144,7 @@ elf_xtensa_size_dynamic_sections (output_bfd, info)
       s = bfd_get_section_by_name (dynobj, ".got");
       if (s == NULL)
        abort ();
-      s->_raw_size = 4;
+      s->size = 4;
 
       /* Adjust refcounts for symbols that we now know are not "dynamic".  */
       elf_link_hash_traverse (elf_hash_table (info),
@@ -1214,7 +1183,7 @@ elf_xtensa_size_dynamic_sections (output_bfd, info)
       if (spltlittbl == NULL)
        abort ();
 
-      plt_entries = srelplt->_raw_size / sizeof (Elf32_External_Rela);
+      plt_entries = srelplt->size / sizeof (Elf32_External_Rela);
       plt_chunks =
        (plt_entries + PLT_ENTRIES_PER_CHUNK - 1) / PLT_ENTRIES_PER_CHUNK;
 
@@ -1240,15 +1209,15 @@ elf_xtensa_size_dynamic_sections (output_bfd, info)
 
          if (chunk_entries != 0)
            {
-             sgotplt->_raw_size = 4 * (chunk_entries + 2);
-             splt->_raw_size = PLT_ENTRY_SIZE * chunk_entries;
-             srelgot->_raw_size += 2 * sizeof (Elf32_External_Rela);
-             spltlittbl->_raw_size += 8;
+             sgotplt->size = 4 * (chunk_entries + 2);
+             splt->size = PLT_ENTRY_SIZE * chunk_entries;
+             srelgot->size += 2 * sizeof (Elf32_External_Rela);
+             spltlittbl->size += 8;
            }
          else
            {
-             sgotplt->_raw_size = 0;
-             splt->_raw_size = 0;
+             sgotplt->size = 0;
+             splt->size = 0;
            }
        }
 
@@ -1257,7 +1226,7 @@ elf_xtensa_size_dynamic_sections (output_bfd, info)
       sgotloc = bfd_get_section_by_name (dynobj, ".got.loc");
       if (sgotloc == NULL)
        abort ();
-      sgotloc->_raw_size = spltlittbl->_raw_size;
+      sgotloc->size = spltlittbl->size;
       for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link_next)
        {
          if (abfd->flags & DYNAMIC)
@@ -1267,7 +1236,7 @@ elf_xtensa_size_dynamic_sections (output_bfd, info)
              if (! elf_discarded_section (s)
                  && xtensa_is_littable_section (s)
                  && s != spltlittbl)
-               sgotloc->_raw_size += s->_raw_size;
+               sgotloc->size += s->size;
            }
        }
     }
@@ -1303,7 +1272,7 @@ elf_xtensa_size_dynamic_sections (output_bfd, info)
       else if (strncmp (name, ".plt.", 5) == 0
               || strncmp (name, ".got.plt.", 9) == 0)
        {
-         if (s->_raw_size == 0)
+         if (s->size == 0)
            {
              /* If we don't need this section, strip it from the output
                 file.  We must create the ".plt*" and ".got.plt*"
@@ -1332,8 +1301,8 @@ elf_xtensa_size_dynamic_sections (output_bfd, info)
       else
        {
          /* Allocate memory for the section contents.  */
-         s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size);
-         if (s->contents == NULL && s->_raw_size != 0)
+         s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size);
+         if (s->contents == NULL && s->size != 0)
            return FALSE;
        }
     }
@@ -1368,7 +1337,7 @@ elf_xtensa_size_dynamic_sections (output_bfd, info)
         the .dynamic section.  The DT_DEBUG entry is filled in by the
         dynamic linker and used by the debugger.  */
 #define add_dynamic_entry(TAG, VAL) \
-  bfd_elf32_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL))
+  _bfd_elf_add_dynamic_entry (info, TAG, VAL)
 
       if (! info->shared)
        {
@@ -1393,12 +1362,6 @@ 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;
@@ -1417,8 +1380,9 @@ elf_xtensa_size_dynamic_sections (output_bfd, info)
    this and it probably ought to be moved into elf.c as well.  */
 
 static bfd_boolean
-elf_xtensa_modify_segment_map (abfd)
+elf_xtensa_modify_segment_map (abfd, info)
      bfd *abfd;
+     struct bfd_link_info *info ATTRIBUTE_UNUSED;
 {
   struct elf_segment_map **m_p;
 
@@ -1474,7 +1438,7 @@ elf_xtensa_do_reloc (howto, abfd, input_section, relocation,
          /* Check for windowed CALL across a 1GB boundary.  */
          xtensa_opcode opcode =
            get_expanded_call_opcode (contents + address,
-                                     input_section->_raw_size - address);
+                                     input_section->size - address);
          if (is_windowed_call_opcode (opcode))
            {
              self_address = (input_section->output_section->vma
@@ -1495,8 +1459,7 @@ elf_xtensa_do_reloc (howto, abfd, input_section, relocation,
       { 
         /* Convert the L32R/CALLX to CALL.  */
        bfd_reloc_status_type retval = 
-         elf_xtensa_do_asm_simplify (contents, address,
-                                     input_section->_raw_size);
+         elf_xtensa_do_asm_simplify (contents, address, input_section->size);
        if (retval != bfd_reloc_ok)
          return retval;
 
@@ -1711,11 +1674,10 @@ bfd_elf_xtensa_reloc (abfd, reloc_entry, symbol, data, input_section,
     }
 
   /* Is the address of the relocation really within the section?  */
-  if (reloc_entry->address > (input_section->_cooked_size
-                             / bfd_octets_per_byte (abfd)))
+  if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
     return bfd_reloc_outofrange;
 
-  /* Work out which section the relocation is targetted at and the
+  /* Work out which section the relocation is targeted at and the
      initial relocation command value.  */
 
   /* Get symbol value.  (Common symbols are special.)  */
@@ -1830,17 +1792,6 @@ elf_xtensa_create_plt_entry (dynobj, output_bfd, reloc_index)
 }
 
 
-static bfd_boolean
-xtensa_elf_dynamic_symbol_p (info, h)
-     struct bfd_link_info *info;
-     struct elf_link_hash_entry *h;
-{
-  /* ??? What, if anything, needs to happen wrt STV_PROTECTED and PLT
-     entries?  For now assume the worst.  */
-  return _bfd_elf_dynamic_symbol_p (h, info, 1);
-}
-
-
 /* Relocate an Xtensa ELF section.  This is invoked by the linker for
    both relocatable and final links.  */
 
@@ -1863,6 +1814,8 @@ 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)
@@ -1880,6 +1833,14 @@ 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++)
@@ -1931,7 +1892,7 @@ elf_xtensa_relocate_section (output_bfd, info, input_bfd,
            {
              /* Convert ASM_SIMPLIFY into the simpler relocation
                 so that they never escape a relaxing link.  */
-             contract_asm_expansion (contents, input_section->_raw_size, rel);
+             contract_asm_expansion (contents, input_section->size, rel);
              r_type = ELF32_R_TYPE (rel->r_info);
            }
 
@@ -2001,49 +1962,19 @@ elf_xtensa_relocate_section (output_bfd, info, input_bfd,
        {
          sym = local_syms + r_symndx;
          sec = local_sections[r_symndx];
-         relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel);
+         relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
        }
       else
        {
-         h = sym_hashes[r_symndx - symtab_hdr->sh_info];
-
-         while (h->root.type == bfd_link_hash_indirect
-                || h->root.type == bfd_link_hash_warning)
-           h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
-         relocation = 0;
-         if (h->root.type == bfd_link_hash_defined
-             || h->root.type == bfd_link_hash_defweak)
-           {
-             sec = h->root.u.def.section;
-
-             if (sec->output_section == NULL)
-               /* Set a flag that will be cleared later if we find a
-                  relocation value for this symbol.  output_section
-                  is typically NULL for symbols satisfied by a shared
-                  library.  */
-               unresolved_reloc = TRUE;
-             else
-               relocation = (h->root.u.def.value
-                             + sec->output_section->vma
-                             + sec->output_offset);
-           }
-         else if (h->root.type == bfd_link_hash_undefweak)
+         RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
+                                  r_symndx, symtab_hdr, sym_hashes,
+                                  h, sec, relocation,
+                                  unresolved_reloc, warned);
+
+         if (relocation == 0
+             && !unresolved_reloc
+             && h->root.type == bfd_link_hash_undefweak)
            is_weak_undef = TRUE;
-         else if (info->shared
-                  && !info->no_undefined
-                  && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
-           ;
-         else
-           {
-             if (! ((*info->callbacks->undefined_symbol)
-                    (info, h->root.root.string, input_bfd,
-                     input_section, rel->r_offset,
-                     (!info->shared || info->no_undefined
-                      || ELF_ST_VISIBILITY (h->other)))))
-               return FALSE;
-             warned = TRUE;
-           }
        }
 
       if (relaxing_section)
@@ -2057,7 +1988,7 @@ elf_xtensa_relocate_section (output_bfd, info, input_bfd,
        }
 
       /* Sanity check the address.  */
-      if (rel->r_offset >= input_section->_raw_size
+      if (rel->r_offset >= bfd_get_section_limit (input_bfd, input_section)
          && ELF32_R_TYPE (rel->r_info) != R_XTENSA_NONE)
        {
          bfd_set_error (bfd_error_bad_value);
@@ -2067,7 +1998,7 @@ elf_xtensa_relocate_section (output_bfd, info, input_bfd,
       /* Generate dynamic relocations.  */
       if (elf_hash_table (info)->dynamic_sections_created)
        {
-         bfd_boolean dynamic_symbol = xtensa_elf_dynamic_symbol_p (info, h);
+         bfd_boolean dynamic_symbol = xtensa_elf_dynamic_symbol_p (h, info);
 
          if (dynamic_symbol && (r_type == R_XTENSA_OP0
                                 || r_type == R_XTENSA_OP1
@@ -2107,8 +2038,22 @@ elf_xtensa_relocate_section (output_bfd, info, input_bfd,
                memset (&outrel, 0, sizeof outrel);
              else
                {
-                 outrel.r_offset = (input_section->output_section->vma
-                                    + input_section->output_offset);
+                 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,
+                                                     outrel.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)
                    {
@@ -2147,7 +2092,7 @@ elf_xtensa_relocate_section (output_bfd, info, input_bfd,
                     + srel->reloc_count++ * sizeof (Elf32_External_Rela));
              bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
              BFD_ASSERT (sizeof (Elf32_External_Rela) * srel->reloc_count
-                         <= srel->_cooked_size);
+                         <= srel->size);
            }
        }
 
@@ -2197,6 +2142,11 @@ elf_xtensa_relocate_section (output_bfd, info, input_bfd,
        }
     }
 
+  if (lit_table)
+    free (lit_table);
+
+  input_section->reloc_done = TRUE;
+
   return TRUE;
 }
 
@@ -2248,13 +2198,11 @@ elf_xtensa_combine_prop_entries (output_bfd, sxtlit, sgotloc)
   bfd_vma offset;
   int n, m, num;
 
-  section_size = (sxtlit->_cooked_size != 0
-                 ? sxtlit->_cooked_size : sxtlit->_raw_size);
+  section_size = sxtlit->size;
   BFD_ASSERT (section_size % 8 == 0);
   num = section_size / 8;
 
-  sgotloc_size = (sgotloc->_cooked_size != 0
-                 ? sgotloc->_cooked_size : sgotloc->_raw_size);
+  sgotloc_size = sgotloc->size;
   if (sgotloc_size != section_size)
     {
       (*_bfd_error_handler)
@@ -2262,20 +2210,22 @@ elf_xtensa_combine_prop_entries (output_bfd, sxtlit, sgotloc)
       return -1;
     }
 
-  contents = (bfd_byte *) bfd_malloc (section_size);
-  table = (property_table_entry *)
-    bfd_malloc (num * sizeof (property_table_entry));
-  if (contents == 0 || table == 0)
+  table = bfd_malloc (num * sizeof (property_table_entry));
+  if (table == 0)
     return -1;
 
   /* The ".xt.lit.plt" section has the SEC_IN_MEMORY flag set and this
      propagates to the output section, where it doesn't really apply and
-     where it breaks the following call to bfd_get_section_contents.  */
+     where it breaks the following call to bfd_malloc_and_get_section.  */
   sxtlit->flags &= ~SEC_IN_MEMORY;
 
-  if (! bfd_get_section_contents (output_bfd, sxtlit, contents, 0,
-                                 section_size))
-    return -1;
+  if (!bfd_malloc_and_get_section (output_bfd, sxtlit, &contents))
+    {
+      if (contents != 0)
+       free (contents);
+      free (table);
+      return -1;
+    }
 
   /* There should never be any relocations left at this point, so this
      is quite a bit easier than what is done during relaxation.  */
@@ -2327,10 +2277,7 @@ elf_xtensa_combine_prop_entries (output_bfd, sxtlit, sgotloc)
 
   /* Clear the removed bytes.  */
   if ((bfd_size_type) (num * 8) < section_size)
-    {
-      memset (&contents[num * 8], 0, section_size - num * 8);
-      sxtlit->_cooked_size = num * 8;
-    }
+    memset (&contents[num * 8], 0, section_size - num * 8);
 
   if (! bfd_set_section_contents (output_bfd, sxtlit, contents, 0,
                                  section_size))
@@ -2340,6 +2287,7 @@ elf_xtensa_combine_prop_entries (output_bfd, sxtlit, sgotloc)
   memcpy (sgotloc->contents, contents, section_size);
 
   free (contents);
+  free (table);
   return num;
 }
 
@@ -2368,7 +2316,7 @@ elf_xtensa_finish_dynamic_sections (output_bfd, info)
   sgot = bfd_get_section_by_name (dynobj, ".got");
   if (sgot)
     {
-      BFD_ASSERT (sgot->_raw_size == 4);
+      BFD_ASSERT (sgot->size == 4);
       if (sdyn == NULL)
        bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents);
       else
@@ -2378,7 +2326,7 @@ elf_xtensa_finish_dynamic_sections (output_bfd, info)
     }
 
   srelplt = bfd_get_section_by_name (dynobj, ".rela.plt");
-  if (srelplt != NULL && srelplt->_raw_size != 0)
+  if (srelplt != NULL && srelplt->size != 0)
     {
       asection *sgotplt, *srelgot, *spltlittbl;
       int chunk, plt_chunks, plt_entries;
@@ -2403,7 +2351,7 @@ elf_xtensa_finish_dynamic_sections (output_bfd, info)
        }
       BFD_ASSERT (rtld_reloc < srelgot->reloc_count);
 
-      plt_entries = (srelplt->_raw_size / sizeof (Elf32_External_Rela));
+      plt_entries = srelplt->size / sizeof (Elf32_External_Rela);
       plt_chunks =
        (plt_entries + PLT_ENTRIES_PER_CHUNK - 1) / PLT_ENTRIES_PER_CHUNK;
 
@@ -2445,7 +2393,7 @@ elf_xtensa_finish_dynamic_sections (output_bfd, info)
          else
            chunk_entries = plt_entries - (chunk * PLT_ENTRIES_PER_CHUNK);
 
-         BFD_ASSERT ((unsigned) (chunk + 1) * 8 <= spltlittbl->_cooked_size);
+         BFD_ASSERT ((unsigned) (chunk + 1) * 8 <= spltlittbl->size);
          bfd_put_32 (output_bfd,
                      sgotplt->output_section->vma + sgotplt->output_offset,
                      spltlittbl->contents + (chunk * 8) + 0);
@@ -2456,10 +2404,10 @@ elf_xtensa_finish_dynamic_sections (output_bfd, info)
 
       /* All the dynamic relocations have been emitted at this point.
         Make sure the relocation sections are the correct size.  */
-      if (srelgot->_cooked_size != (sizeof (Elf32_External_Rela)
-                                   * srelgot->reloc_count)
-         || srelplt->_cooked_size != (sizeof (Elf32_External_Rela)
-                                      * srelplt->reloc_count))
+      if (srelgot->size != (sizeof (Elf32_External_Rela)
+                           * srelgot->reloc_count)
+         || srelplt->size != (sizeof (Elf32_External_Rela)
+                              * srelplt->reloc_count))
        abort ();
 
      /* The .xt.lit.plt section has just been modified.  This must
@@ -2470,7 +2418,7 @@ elf_xtensa_finish_dynamic_sections (output_bfd, info)
                                      spltlittbl->output_section,
                                      spltlittbl->contents,
                                      spltlittbl->output_offset,
-                                     spltlittbl->_raw_size))
+                                     spltlittbl->size))
        return FALSE;
       /* Clear SEC_HAS_CONTENTS so the contents won't be output again.  */
       spltlittbl->flags &= ~SEC_HAS_CONTENTS;
@@ -2487,7 +2435,7 @@ elf_xtensa_finish_dynamic_sections (output_bfd, info)
     return FALSE;
 
   dyncon = (Elf32_External_Dyn *) sdyn->contents;
-  dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->_raw_size);
+  dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->size);
   for (; dyncon < dynconend; dyncon++)
     {
       Elf_Internal_Dyn dyn;
@@ -2522,7 +2470,7 @@ elf_xtensa_finish_dynamic_sections (output_bfd, info)
        case DT_PLTRELSZ:
          s = bfd_get_section_by_name (output_bfd, ".rela.plt");
          BFD_ASSERT (s);
-         dyn.d_un.d_val = (s->_cooked_size ? s->_cooked_size : s->_raw_size);
+         dyn.d_un.d_val = s->size;
          break;
 
        case DT_RELASZ:
@@ -2534,10 +2482,7 @@ elf_xtensa_finish_dynamic_sections (output_bfd, info)
             don't have to worry about changing the DT_RELA entry.  */
          s = bfd_get_section_by_name (output_bfd, ".rela.plt");
          if (s)
-           {
-             dyn.d_un.d_val -=
-               (s->_cooked_size ? s->_cooked_size : s->_raw_size);
-           }
+           dyn.d_un.d_val -= s->size;
          break;
        }
 
@@ -2733,7 +2678,7 @@ elf_xtensa_discard_info_for_section (abfd, cookie, info, sec)
   bfd_vma offset, actual_offset;
   size_t removed_bytes = 0;
 
-  section_size = (sec->_cooked_size ? sec->_cooked_size : sec->_raw_size);
+  section_size = sec->size;
   if (section_size == 0 || section_size % 8 != 0)
     return FALSE;
 
@@ -2771,7 +2716,7 @@ elf_xtensa_discard_info_for_section (abfd, cookie, info, sec)
       while (cookie->rel < cookie->relend
             && cookie->rel->r_offset == offset)
        {
-         if (_bfd_elf32_reloc_symbol_deleted_p (offset, cookie))
+         if (bfd_elf_reloc_symbol_deleted_p (offset, cookie))
            {
              /* Remove the table entry.  (If the reloc type is NONE, then
                 the entry has already been merged with another and deleted
@@ -2821,9 +2766,8 @@ elf_xtensa_discard_info_for_section (abfd, cookie, info, sec)
       pin_contents (sec, contents);
       pin_internal_relocs (sec, cookie->rels);
 
-      sec->_cooked_size = section_size - removed_bytes;
-      /* Also shrink _raw_size.  See comments in relax_property_section.  */
-      sec->_raw_size = sec->_cooked_size;
+      /* Shrink size.  */
+      sec->size = section_size - removed_bytes;
 
       if (xtensa_is_littable_section (sec))
        {
@@ -2833,13 +2777,7 @@ elf_xtensa_discard_info_for_section (abfd, cookie, info, sec)
              asection *sgotloc =
                bfd_get_section_by_name (dynobj, ".got.loc");
              if (sgotloc)
-               {
-                 bfd_size_type sgotloc_size =
-                   (sgotloc->_cooked_size ? sgotloc->_cooked_size
-                    : sgotloc->_raw_size);
-                 sgotloc->_cooked_size = sgotloc_size - removed_bytes;
-                 sgotloc->_raw_size = sgotloc_size - removed_bytes;
-               }
+               sgotloc->size -= removed_bytes;
            }
        }
     }
@@ -2891,7 +2829,7 @@ elf_xtensa_grok_prstatus (abfd, note)
      Elf_Internal_Note *note;
 {
   int offset;
-  unsigned int raw_size;
+  unsigned int size;
 
   /* The size for Xtensa is variable, so don't try to recognize the format
      based on the size.  Just assume this is GNU/Linux.  */
@@ -2904,11 +2842,11 @@ elf_xtensa_grok_prstatus (abfd, note)
 
   /* pr_reg */
   offset = 72;
-  raw_size = note->descsz - offset - 4;
+  size = note->descsz - offset - 4;
 
   /* Make a ".reg/999" section.  */
   return _bfd_elfcore_make_pseudosection (abfd, ".reg",
-                                         raw_size, note->descpos + offset);
+                                         size, note->descpos + offset);
 }
 
 
@@ -3070,7 +3008,7 @@ get_relocation_opcode (sec, contents, irel)
   if (contents == NULL)
     return XTENSA_UNDEFINED;
 
-  if (sec->_raw_size <= irel->r_offset)
+  if (sec->size <= irel->r_offset)
     return XTENSA_UNDEFINED;
 
   if (ibuff == NULL)
@@ -3482,7 +3420,7 @@ struct value_map_hash_table_struct
 
 
 static bfd_boolean is_same_value
-  PARAMS ((const literal_value *, const literal_value *));
+  PARAMS ((const literal_value *, const literal_value *, bfd_boolean));
 static value_map_hash_table *value_map_hash_table_init
   PARAMS ((void));
 static unsigned hash_literal_value
@@ -3490,16 +3428,20 @@ static unsigned hash_literal_value
 static unsigned hash_bfd_vma
   PARAMS ((bfd_vma));
 static value_map *get_cached_value
-  PARAMS ((value_map_hash_table *, const literal_value *));
+  PARAMS ((value_map_hash_table *, const literal_value *, bfd_boolean));
 static value_map *add_value_map
-  PARAMS ((value_map_hash_table *, const literal_value *, const r_reloc *));
+  PARAMS ((value_map_hash_table *, const literal_value *, const r_reloc *,
+          bfd_boolean));
 
 
 static bfd_boolean
-is_same_value (src1, src2)
+is_same_value (src1, src2, final_static_link)
      const literal_value *src1;
      const literal_value *src2;
+     bfd_boolean final_static_link;
 {
+  struct elf_link_hash_entry *h1, *h2;
+
   if (r_reloc_is_const (&src1->r_rel) != r_reloc_is_const (&src2->r_rel)) 
     return FALSE;
 
@@ -3517,8 +3459,14 @@ is_same_value (src1, src2)
   if (src1->value != src2->value)
     return FALSE;
   
-  /* Now check for the same section and the same elf_hash.  */
-  if (r_reloc_is_defined (&src1->r_rel))
+  /* Now check for the same section (if defined) or the same elf_hash
+     (if undefined or weak).  */
+  h1 = r_reloc_get_hash_entry (&src1->r_rel);
+  h2 = r_reloc_get_hash_entry (&src2->r_rel);
+  if (r_reloc_is_defined (&src1->r_rel)
+      && (final_static_link
+         || ((!h1 || h1->root.type != bfd_link_hash_defweak)
+             && (!h2 || h2->root.type != bfd_link_hash_defweak))))
     {
       if (r_reloc_get_section (&src1->r_rel)
          != r_reloc_get_section (&src2->r_rel))
@@ -3526,11 +3474,8 @@ is_same_value (src1, src2)
     }
   else
     {
-      if (r_reloc_get_hash_entry (&src1->r_rel)
-         != r_reloc_get_hash_entry (&src2->r_rel))
-       return FALSE;
-
-      if (r_reloc_get_hash_entry (&src1->r_rel) == 0)
+      /* Require that the hash entries (i.e., symbols) be identical.  */
+      if (h1 != h2 || h1 == 0)
        return FALSE;
     }
 
@@ -3571,6 +3516,7 @@ hash_literal_value (src)
      const literal_value *src;
 {
   unsigned hash_val;
+
   if (r_reloc_is_const (&src->r_rel))
     return hash_bfd_vma (src->value);
 
@@ -3579,9 +3525,9 @@ hash_literal_value (src)
   
   /* Now check for the same section and the same elf_hash.  */
   if (r_reloc_is_defined (&src->r_rel))
-    hash_val += hash_bfd_vma ((bfd_vma) r_reloc_get_section (&src->r_rel));
+    hash_val += hash_bfd_vma ((bfd_vma) (unsigned) r_reloc_get_section (&src->r_rel));
   else
-    hash_val += hash_bfd_vma ((bfd_vma) r_reloc_get_hash_entry (&src->r_rel));
+    hash_val += hash_bfd_vma ((bfd_vma) (unsigned) r_reloc_get_hash_entry (&src->r_rel));
 
   return hash_val;
 }
@@ -3590,9 +3536,10 @@ hash_literal_value (src)
 /* Check if the specified literal_value has been seen before.  */
 
 static value_map *
-get_cached_value (map, val)
+get_cached_value (map, val, final_static_link)
      value_map_hash_table *map;
      const literal_value *val;
+     bfd_boolean final_static_link;
 {
   value_map *map_e;
   value_map *bucket;
@@ -3603,7 +3550,7 @@ get_cached_value (map, val)
   bucket = map->buckets[idx];
   for (map_e = bucket; map_e; map_e = map_e->next)
     {
-      if (is_same_value (&map_e->val, val))
+      if (is_same_value (&map_e->val, val, final_static_link))
        return map_e;
     }
   return NULL;
@@ -3614,17 +3561,18 @@ get_cached_value (map, val)
    already has an entry here.  */
 
 static value_map *
-add_value_map (map, val, loc)
+add_value_map (map, val, loc, final_static_link)
      value_map_hash_table *map;
      const literal_value *val;
      const r_reloc *loc;
+     bfd_boolean final_static_link;
 {
   value_map **bucket_p;
   unsigned idx;
 
   value_map *val_e = (value_map *) bfd_zmalloc (sizeof (value_map));
 
-  BFD_ASSERT (get_cached_value (map, val) == NULL);
+  BFD_ASSERT (get_cached_value (map, val, final_static_link) == NULL);
   val_e->val = *val;
   val_e->loc = *loc;
 
@@ -3994,20 +3942,16 @@ retrieve_contents (abfd, sec, keep_memory)
 
   contents = elf_section_data (sec)->this_hdr.contents;
   
-  if (contents == NULL && sec->_raw_size != 0)
+  if (contents == NULL && sec->size != 0)
     {
-      contents = (bfd_byte *) bfd_malloc (sec->_raw_size);
-      if (contents != NULL)
+      if (!bfd_malloc_and_get_section (abfd, sec, &contents))
        {
-         if (! bfd_get_section_contents (abfd, sec, contents,
-                                         (file_ptr) 0, sec->_raw_size))
-           {
-             free (contents);
-             return NULL;
-           }
-         if (keep_memory) 
-           elf_section_data (sec)->this_hdr.contents = contents;
+         if (contents != NULL)
+           free (contents);
+         return NULL;
        }
+      if (keep_memory) 
+       elf_section_data (sec)->this_hdr.contents = contents;
     }
   return contents;
 }
@@ -4211,7 +4155,7 @@ analyze_relocations (link_info)
    expensive and unnecessary unless the target section is actually going
    to be relaxed.  This pass identifies all such sections by checking if
    they have L32Rs pointing to them.  In the process, the total number
-   of relocations targetting each section is also counted so that we
+   of relocations targeting each section is also counted so that we
    know how much space to allocate for source_relocs against each
    relaxable literal section.  */
 
@@ -4233,7 +4177,7 @@ find_relaxable_sections (abfd, sec, link_info, is_relaxable_p)
     return ok;
 
   contents = retrieve_contents (abfd, sec, link_info->keep_memory);
-  if (contents == NULL && sec->_raw_size != 0)
+  if (contents == NULL && sec->size != 0)
     {
       ok = FALSE;
       goto error_return;
@@ -4294,7 +4238,7 @@ collect_source_relocs (abfd, sec, link_info)
     return ok;
 
   contents = retrieve_contents (abfd, sec, link_info->keep_memory);
-  if (contents == NULL && sec->_raw_size != 0)
+  if (contents == NULL && sec->size != 0)
     {
       ok = FALSE;
       goto error_return;
@@ -4442,7 +4386,7 @@ is_resolvable_asm_expansion (abfd, sec, contents, irel, link_info,
     return FALSE;
   
   opcode = get_expanded_call_opcode (contents + irel->r_offset,
-                                    sec->_raw_size - irel->r_offset);
+                                    sec->size - irel->r_offset);
   
   direct_call_opcode = swap_callx_for_call_opcode (opcode);
   if (direct_call_opcode == XTENSA_UNDEFINED)
@@ -4530,6 +4474,7 @@ remove_literals (abfd, sec, link_info, values)
   bfd_byte *contents;
   Elf_Internal_Rela *internal_relocs;
   source_reloc *src_relocs;
+  bfd_boolean final_static_link;
   bfd_boolean ok = TRUE;
   int i;
 
@@ -4544,12 +4489,16 @@ remove_literals (abfd, sec, link_info, values)
                                              link_info->keep_memory);
 
   contents = retrieve_contents (abfd, sec, link_info->keep_memory);
-  if (contents == NULL && sec->_raw_size != 0)
+  if (contents == NULL && sec->size != 0)
     {
       ok = FALSE;
       goto error_return;
     }
 
+  final_static_link =
+    (!link_info->relocatable
+     && !elf_hash_table (link_info)->dynamic_sections_created);
+
   /* Sort the source_relocs by target offset.  */
   src_relocs = relax_info->src_relocs;
   qsort (src_relocs, relax_info->src_count,
@@ -4598,11 +4547,11 @@ remove_literals (abfd, sec, link_info, values)
 
       /* Find the literal value.  */
       r_reloc_init (&val.r_rel, abfd, irel);
-      BFD_ASSERT (rel->r_rel.target_offset < sec->_raw_size);
+      BFD_ASSERT (rel->r_rel.target_offset < sec->size);
       val.value = bfd_get_32 (abfd, contents + rel->r_rel.target_offset);
           
       /* Check if we've seen another literal with the same value.  */
-      val_map = get_cached_value (values, &val);
+      val_map = get_cached_value (values, &val, final_static_link);
       if (val_map != NULL) 
        {
          /* First check that THIS and all the other relocs to this
@@ -4625,7 +4574,7 @@ remove_literals (abfd, sec, link_info, values)
        {
          /* This is the first time we've seen this literal value.  */
          BFD_ASSERT (sec == r_reloc_get_section (&rel->r_rel));
-         add_value_map (values, &val, &rel->r_rel);
+         add_value_map (values, &val, &rel->r_rel, final_static_link);
        }
     }
 
@@ -4754,7 +4703,7 @@ relax_section (abfd, sec, link_info)
   internal_relocs = retrieve_internal_relocs (abfd, sec, 
                                              link_info->keep_memory);
   contents = retrieve_contents (abfd, sec, link_info->keep_memory);
-  if (contents == NULL && sec->_raw_size != 0)
+  if (contents == NULL && sec->size != 0)
     {
       ok = FALSE;
       goto error_return;
@@ -4833,13 +4782,13 @@ relax_section (abfd, sec, link_info)
       /* Walk through the contents and delete literals that are not needed 
          anymore.  */
 
-      unsigned long size = sec->_cooked_size;
+      unsigned long size = sec->size;
       unsigned long removed = 0;
 
       removed_literal *reloc = relax_info->removed_list.head;
       for (; reloc; reloc = reloc->next) 
        {
-         unsigned long upper = sec->_raw_size;
+         unsigned long upper = sec->size;
          bfd_vma start = reloc->from.target_offset + 4;
          if (reloc->next)
            upper = reloc->next->from.target_offset;
@@ -4856,13 +4805,7 @@ relax_section (abfd, sec, link_info)
        }
 
       /* Change the section size.  */
-      sec->_cooked_size = size;
-      /* Also shrink _raw_size.  (The code in relocate_section that
-        checks that relocations are within the section must use
-        _raw_size because of the way the stabs sections are relaxed;
-        shrinking _raw_size means that these checks will not be
-        unnecessarily lax.)  */
-      sec->_raw_size = size;
+      sec->size = size;
     }
   
  error_return:
@@ -4963,7 +4906,7 @@ shrink_dynamic_reloc_sections (info, abfd, input_section, rel)
   else
     h = sym_hashes[r_symndx - symtab_hdr->sh_info];
 
-  dynamic_symbol = xtensa_elf_dynamic_symbol_p (info, h);
+  dynamic_symbol = xtensa_elf_dynamic_symbol_p (h, info);
 
   if ((r_type == R_XTENSA_32 || r_type == R_XTENSA_PLT)
       && (input_section->flags & SEC_ALLOC) != 0
@@ -4988,13 +4931,8 @@ shrink_dynamic_reloc_sections (info, abfd, input_section, rel)
       /* Reduce size of the .rela.* section by one reloc.  */
       srel = bfd_get_section_by_name (dynobj, srel_name);
       BFD_ASSERT (srel != NULL);
-      BFD_ASSERT (srel->_cooked_size >= sizeof (Elf32_External_Rela));
-      srel->_cooked_size -= sizeof (Elf32_External_Rela);
-
-      /* Also shrink _raw_size.  (This seems wrong but other bfd code seems
-        to assume that linker-created sections will never be relaxed and
-        hence _raw_size must always equal _cooked_size.) */
-      srel->_raw_size = srel->_cooked_size;
+      BFD_ASSERT (srel->size >= sizeof (Elf32_External_Rela));
+      srel->size -= sizeof (Elf32_External_Rela);
 
       if (is_plt)
        {
@@ -5007,7 +4945,7 @@ shrink_dynamic_reloc_sections (info, abfd, input_section, rel)
             = size - 1" since the index starts at zero, but in this
             context, the size has just been decremented so there's no
             need to subtract one.  */
-         reloc_index = srel->_cooked_size / sizeof (Elf32_External_Rela);
+         reloc_index = srel->size / sizeof (Elf32_External_Rela);
 
          chunk = reloc_index / PLT_ENTRIES_PER_CHUNK;
          splt = elf_xtensa_get_plt_section (dynobj, chunk);
@@ -5021,27 +4959,20 @@ shrink_dynamic_reloc_sections (info, abfd, input_section, rel)
              srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
              BFD_ASSERT (srelgot != NULL);
              srelgot->reloc_count -= 2;
-             srelgot->_cooked_size -= 2 * sizeof (Elf32_External_Rela);
-             /* Shrink _raw_size (see comment above).  */
-             srelgot->_raw_size = srelgot->_cooked_size;
-
-             sgotplt->_cooked_size -= 8;
+             srelgot->size -= 2 * sizeof (Elf32_External_Rela);
+             sgotplt->size -= 8;
 
              /* There should be only one entry left (and it will be
                 removed below).  */
-             BFD_ASSERT (sgotplt->_cooked_size == 4);
-             BFD_ASSERT (splt->_cooked_size == PLT_ENTRY_SIZE);
+             BFD_ASSERT (sgotplt->size == 4);
+             BFD_ASSERT (splt->size == PLT_ENTRY_SIZE);
            }
 
-         BFD_ASSERT (sgotplt->_cooked_size >= 4);
-         BFD_ASSERT (splt->_cooked_size >= PLT_ENTRY_SIZE);
+         BFD_ASSERT (sgotplt->size >= 4);
+         BFD_ASSERT (splt->size >= PLT_ENTRY_SIZE);
 
-         sgotplt->_cooked_size -= 4;
-         splt->_cooked_size -= PLT_ENTRY_SIZE;
-
-         /* Shrink _raw_sizes (see comment above).  */
-         sgotplt->_raw_size = sgotplt->_cooked_size;
-         splt->_raw_size = splt->_cooked_size;
+         sgotplt->size -= 4;
+         splt->size -= PLT_ENTRY_SIZE;
        }
     }
 }
@@ -5066,7 +4997,7 @@ relax_property_section (abfd, sec, link_info)
   internal_relocs = retrieve_internal_relocs (abfd, sec, 
                                              link_info->keep_memory);
   contents = retrieve_contents (abfd, sec, link_info->keep_memory);
-  if (contents == NULL && sec->_raw_size != 0)
+  if (contents == NULL && sec->size != 0)
     {
       ok = FALSE;
       goto error_return;
@@ -5157,7 +5088,7 @@ relax_property_section (abfd, sec, link_info)
       pin_contents (sec, contents);
 
       last_irel_offset = (bfd_vma) -1;
-      section_size = (sec->_cooked_size ? sec->_cooked_size : sec->_raw_size);
+      section_size = sec->size;
       BFD_ASSERT (section_size % 8 == 0);
 
       for (offset = 0; offset < section_size; offset += 8)
@@ -5289,13 +5220,7 @@ relax_property_section (abfd, sec, link_info)
          /* Clear the removed bytes.  */
          memset (&contents[section_size - removed_bytes], 0, removed_bytes);
 
-         sec->_cooked_size = section_size - removed_bytes;
-         /* Also shrink _raw_size.  (The code in relocate_section that
-            checks that relocations are within the section must use
-            _raw_size because of the way the stabs sections are
-            relaxed; shrinking _raw_size means that these checks will
-            not be unnecessarily lax.)  */
-         sec->_raw_size = sec->_cooked_size;
+         sec->size = section_size - removed_bytes;
 
          if (xtensa_is_littable_section (sec))
            {
@@ -5305,13 +5230,7 @@ relax_property_section (abfd, sec, link_info)
                  asection *sgotloc =
                    bfd_get_section_by_name (dynobj, ".got.loc");
                  if (sgotloc)
-                   {
-                     bfd_size_type sgotloc_size =
-                       (sgotloc->_cooked_size ? sgotloc->_cooked_size
-                        : sgotloc->_raw_size);
-                     sgotloc->_cooked_size = sgotloc_size - removed_bytes;
-                     sgotloc->_raw_size = sgotloc_size - removed_bytes;
-                   }
+                   sgotloc->size -= removed_bytes;
                }
            }
        }
@@ -5630,25 +5549,25 @@ pcrel_reloc_fits (opnd, self_address, dest_address)
 }
 
 
+static int linkonce_len = sizeof (".gnu.linkonce.") - 1;
+static int insn_sec_len = sizeof (XTENSA_INSN_SEC_NAME) - 1;
+static int lit_sec_len = sizeof (XTENSA_LIT_SEC_NAME) - 1;
+
+
 static bfd_boolean 
 xtensa_is_property_section (sec)
      asection *sec;
 {
-  static int linkonce_len = sizeof (".gnu.linkonce.") - 1;
+  if (strncmp (XTENSA_INSN_SEC_NAME, sec->name, insn_sec_len) == 0
+      || strncmp (XTENSA_LIT_SEC_NAME, sec->name, lit_sec_len) == 0)
+    return TRUE;
 
-  if (strncmp (".xt.insn", sec->name, 8) == 0
-      || strncmp (".xt.lit", sec->name, 7) == 0)
+  if (strncmp (".gnu.linkonce.", sec->name, linkonce_len) == 0
+      && (sec->name[linkonce_len] == 'x'
+         || sec->name[linkonce_len] == 'p')
+      && sec->name[linkonce_len + 1] == '.')
     return TRUE;
 
-  if (strncmp (".gnu.linkonce.", sec->name, linkonce_len) == 0)
-    {
-      if (strncmp ("x.", sec->name + linkonce_len, 2) == 0
-         || strncmp ("p.", sec->name + linkonce_len, 2) == 0)
-       return TRUE;
-      if (strstr (sec->name + linkonce_len, ".xt.insn") != NULL
-         || strstr (sec->name + linkonce_len, ".xt.lit") != NULL)
-       return TRUE;
-    }
   return FALSE;
 }
 
@@ -5657,18 +5576,14 @@ static bfd_boolean
 xtensa_is_littable_section (sec)
      asection *sec;
 {
-  static int linkonce_len = sizeof (".gnu.linkonce.") - 1;
+  if (strncmp (XTENSA_LIT_SEC_NAME, sec->name, lit_sec_len) == 0)
+    return TRUE;
 
-  if (strncmp (".xt.lit", sec->name, 7) == 0)
+  if (strncmp (".gnu.linkonce.", sec->name, linkonce_len) == 0
+      && sec->name[linkonce_len] == 'p'
+      && sec->name[linkonce_len + 1] == '.')
     return TRUE;
 
-  if (strncmp (".gnu.linkonce.", sec->name, linkonce_len) == 0)
-    {
-      if (strncmp ("p.", sec->name + linkonce_len, 2) == 0)
-       return TRUE;
-      if (strstr (sec->name + linkonce_len, ".xt.lit") != NULL)
-       return TRUE;
-    }
   return FALSE;
 }
 
@@ -5696,78 +5611,40 @@ internal_reloc_compare (ap, bp)
 }
 
 
-static bfd_boolean
-get_is_linkonce_section (abfd, sec)
-     bfd *abfd ATTRIBUTE_UNUSED;
-     asection *sec;
-{
-  flagword flags, link_once_flags;
-  bfd_boolean is_linkonce = FALSE;;
-
-  flags = bfd_get_section_flags (abfd, sec);
-  link_once_flags = (flags & SEC_LINK_ONCE);
-  if (link_once_flags != 0)
-    is_linkonce = TRUE;
-
-  /* In order for this to be useful to the assembler
-     before the linkonce flag is set we need to
-     check for the GNU extension name.  */
-  if (!is_linkonce &&
-      strncmp (sec->name, ".gnu.linkonce", sizeof ".gnu.linkonce" - 1) == 0)
-    is_linkonce = TRUE;
-  
-  return is_linkonce;
-}
-
-
 char *
-xtensa_get_property_section_name (abfd, sec, base_name)
-     bfd *abfd;
+xtensa_get_property_section_name (sec, base_name)
      asection *sec;
-     const char * base_name;
+     const char *base_name;
 {
-  char *table_sec_name = NULL;
-  bfd_boolean is_linkonce;
+  if (strncmp (sec->name, ".gnu.linkonce.", linkonce_len) == 0)
+    {
+      char *prop_sec_name;
+      const char *suffix;
+      char linkonce_kind = 0;
+
+      if (strcmp (base_name, XTENSA_INSN_SEC_NAME) == 0) 
+       linkonce_kind = 'x';
+      else if (strcmp (base_name, XTENSA_LIT_SEC_NAME) == 0) 
+       linkonce_kind = 'p';
+      else
+       abort ();
 
-  is_linkonce = get_is_linkonce_section (abfd, sec);
+      prop_sec_name = (char *) bfd_malloc (strlen (sec->name) + 1);
+      memcpy (prop_sec_name, ".gnu.linkonce.", linkonce_len);
+      prop_sec_name[linkonce_len] = linkonce_kind;
+      prop_sec_name[linkonce_len + 1] = '.';
 
-  if (!is_linkonce)
-    {
-      table_sec_name = strdup (base_name);
-    }
-  else
-    {
-      static size_t prefix_len = sizeof (".gnu.linkonce.t.") - 1;
-      size_t len = strlen (sec->name) + 1;
-      char repl_char = '\0';
-      const char *segname = sec->name;
+      suffix = sec->name + linkonce_len;
+      /* For backward compatibility, replace "t." instead of inserting
+        the new linkonce_kind.  */
+      if (strncmp (suffix, "t.", 2) == 0)
+       suffix += 2;
+      strcpy (prop_sec_name + linkonce_len + 2, suffix);
 
-      if (strncmp (segname, ".gnu.linkonce.t.", prefix_len) == 0)
-       {
-         if (strcmp (base_name, ".xt.insn") == 0) 
-           repl_char = 'x';
-         else if (strcmp (base_name, ".xt.lit") == 0) 
-           repl_char = 'p';
-       }
-      
-      if (repl_char != '\0')
-       {
-         char *name = (char *) bfd_malloc (len);
-         memcpy (name, sec->name, len);
-         name[prefix_len - 2] = repl_char;
-         table_sec_name = name;
-       }
-      else
-       {
-         size_t base_len = strlen (base_name) + 1;
-         char *name = (char *) bfd_malloc (len + base_len);
-         memcpy (name, sec->name, len - 1);
-         memcpy (name + len - 1, base_name, base_len);
-         table_sec_name = name;
-       }
+      return prop_sec_name;
     }
 
-  return table_sec_name;
+  return strdup (base_name);
 }
 
 \f
@@ -5812,7 +5689,7 @@ xtensa_callback_required_dependence (abfd, sec, link_info, callback, closure)
       /* Assume worst-case offsets: L32R at the very end of the ".plt"
         section referencing a literal at the very beginning of
         ".got.plt".  This is very close to the real dependence, anyway.  */
-      (*callback) (sec, sec->_raw_size, sgotplt, 0, closure);
+      (*callback) (sec, sec->size, sgotplt, 0, closure);
     }
 
   internal_relocs = retrieve_internal_relocs (abfd, sec, 
@@ -5823,7 +5700,7 @@ xtensa_callback_required_dependence (abfd, sec, link_info, callback, closure)
 
   /* Cache the contents for the duration of this scan.  */
   contents = retrieve_contents (abfd, sec, link_info->keep_memory);
-  if (contents == NULL && sec->_raw_size != 0)
+  if (contents == NULL && sec->size != 0)
     {
       ok = FALSE;
       goto error_return;
@@ -5861,6 +5738,17 @@ xtensa_callback_required_dependence (abfd, sec, link_info, callback, closure)
   return ok;
 }
 
+/* The default literal sections should always be marked as "code" (i.e.,
+   SHF_EXECINSTR).  This is particularly important for the Linux kernel
+   module loader so that the literals are not placed after the text.  */
+static struct bfd_elf_special_section const elf_xtensa_special_sections[]=
+{
+  { ".literal",       8, 0, SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR },
+  { ".init.literal", 13, 0, SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR },
+  { ".fini.literal", 13, 0, SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR },
+  { NULL,             0, 0, 0,            0 }
+};
+
 \f
 #ifndef ELF_ARCH
 #define TARGET_LITTLE_SYM              bfd_elf32_xtensa_le_vec
@@ -5894,7 +5782,6 @@ xtensa_callback_required_dependence (abfd, sec, link_info, callback, closure)
 
 #define elf_info_to_howto                   elf_xtensa_info_to_howto_rela
 
-#define bfd_elf32_bfd_final_link            bfd_elf32_bfd_final_link
 #define bfd_elf32_bfd_merge_private_bfd_data elf_xtensa_merge_private_bfd_data
 #define bfd_elf32_new_section_hook          elf_xtensa_new_section_hook
 #define bfd_elf32_bfd_print_private_bfd_data elf_xtensa_print_private_bfd_data
@@ -5904,7 +5791,6 @@ xtensa_callback_required_dependence (abfd, sec, link_info, callback, closure)
 
 #define elf_backend_adjust_dynamic_symbol    elf_xtensa_adjust_dynamic_symbol
 #define elf_backend_check_relocs            elf_xtensa_check_relocs
-#define elf_backend_copy_indirect_symbol     elf_xtensa_copy_indirect_symbol
 #define elf_backend_create_dynamic_sections  elf_xtensa_create_dynamic_sections
 #define elf_backend_discard_info            elf_xtensa_discard_info
 #define elf_backend_ignore_discarded_relocs  elf_xtensa_ignore_discarded_relocs
@@ -5921,5 +5807,6 @@ xtensa_callback_required_dependence (abfd, sec, link_info, callback, closure)
 #define elf_backend_reloc_type_class        elf_xtensa_reloc_type_class
 #define elf_backend_relocate_section        elf_xtensa_relocate_section
 #define elf_backend_size_dynamic_sections    elf_xtensa_size_dynamic_sections
+#define elf_backend_special_sections        elf_xtensa_special_sections
 
 #include "elf32-target.h"
This page took 0.065799 seconds and 4 git commands to generate.