* aout-adobe.c (aout_32_bfd_reloc_name_lookup): Define.
[deliverable/binutils-gdb.git] / bfd / elf64-mmix.c
index 992a32115611a0e2f4620b84221de0dff36226f1..e55257c1327e0dca08e37a5543ac91fca1f430ed 100644 (file)
@@ -1,5 +1,6 @@
 /* MMIX-specific support for 64-bit ELF.
-   Copyright 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+   Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007
+   Free Software Foundation, Inc.
    Contributed by Hans-Peter Nilsson <hp@bitrange.com>
 
 This file is part of BFD, the Binary File Descriptor library.
@@ -16,7 +17,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.  */
+Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
 
 /* No specific ABI or "processor-specific supplement" defined.  */
 
@@ -186,14 +187,6 @@ static bfd_boolean mmix_elf_relocate_section
   PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
           Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
 
-static asection * mmix_elf_gc_mark_hook
-  PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
-          struct elf_link_hash_entry *, Elf_Internal_Sym *));
-
-static bfd_boolean mmix_elf_gc_sweep_hook
-  PARAMS ((bfd *, struct bfd_link_info *, asection *,
-          const Elf_Internal_Rela *));
-
 static bfd_reloc_status_type mmix_final_link_relocate
   PARAMS ((reloc_howto_type *, asection *, bfd_byte *,
           bfd_vma, bfd_signed_vma, bfd_vma, const char *, asection *));
@@ -229,10 +222,6 @@ static void
 mmix_set_relaxable_size
   PARAMS ((bfd *, asection *, void *));
 
-static bfd_boolean
-mmix_elf_get_section_contents
-  PARAMS ((bfd *, sec_ptr, void *, file_ptr, bfd_size_type));
-
 
 /* Watch out: this currently needs to have elements with the same index as
    their R_MMIX_ number.  */
@@ -859,18 +848,37 @@ bfd_elf64_bfd_reloc_type_lookup (abfd, code)
   return NULL;
 }
 
+static reloc_howto_type *
+bfd_elf64_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+                                const char *r_name)
+{
+  unsigned int i;
+
+  for (i = 0;
+       i < sizeof (elf_mmix_howto_table) / sizeof (elf_mmix_howto_table[0]);
+       i++)
+    if (elf_mmix_howto_table[i].name != NULL
+       && strcasecmp (elf_mmix_howto_table[i].name, r_name) == 0)
+      return &elf_mmix_howto_table[i];
+
+  return NULL;
+}
+
 static bfd_boolean
 mmix_elf_new_section_hook (abfd, sec)
      bfd *abfd;
      asection *sec;
 {
-  struct _mmix_elf_section_data *sdata;
-  bfd_size_type amt = sizeof (*sdata);
+  if (!sec->used_by_bfd)
+    {
+      struct _mmix_elf_section_data *sdata;
+      bfd_size_type amt = sizeof (*sdata);
 
-  sdata = (struct _mmix_elf_section_data *) bfd_zalloc (abfd, amt);
-  if (sdata == NULL)
-    return FALSE;
-  sec->used_by_bfd = (PTR) sdata;
+      sdata = bfd_zalloc (abfd, amt);
+      if (sdata == NULL)
+       return FALSE;
+      sec->used_by_bfd = sdata;
+    }
 
   return _bfd_elf_new_section_hook (abfd, sec);
 }
@@ -991,16 +999,13 @@ mmix_elf_perform_relocation (isec, howto, datap, addr, value)
        goto pcrel_mmix_reloc_fits;
       else
        {
-         bfd_size_type size
-           = (isec->size
-              - (mmix_elf_section_data (isec)->pjs.n_pushj_relocs
-                 * MAX_PUSHJ_STUB_SIZE));
+         bfd_size_type size = isec->rawsize ? isec->rawsize : isec->size;
 
          /* We have the bytes at the PUSHJ insn and need to get the
             position for the stub.  There's supposed to be room allocated
             for the stub.  */
          bfd_byte *stubcontents
-           = ((char *) datap
+           = ((bfd_byte *) datap
               - (addr - (isec->output_section->vma + isec->output_offset))
               + size
               + mmix_elf_section_data (isec)->pjs.stub_offset);
@@ -1261,7 +1266,6 @@ mmix_elf_reloc (abfd, reloc_entry, symbol, data, input_section,
   bfd_reloc_status_type flag = bfd_reloc_ok;
   bfd_vma output_base = 0;
   bfd_vma addr;
-  bfd_size_type sz;
 
   r = bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
                             input_section, output_bfd, error_message);
@@ -1277,8 +1281,7 @@ mmix_elf_reloc (abfd, reloc_entry, symbol, data, input_section,
     return bfd_reloc_undefined;
 
   /* Is the address of the relocation really within the section?  */
-  sz = input_section->rawsize ? input_section->rawsize : input_section->size;
-  if (reloc_entry->address > sz)
+  if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
     return bfd_reloc_outofrange;
 
   /* Work out which section the relocation is targeted at and the
@@ -1343,16 +1346,20 @@ mmix_elf_relocate_section (output_bfd, info, input_bfd, input_section,
   struct elf_link_hash_entry **sym_hashes;
   Elf_Internal_Rela *rel;
   Elf_Internal_Rela *relend;
-  bfd_size_type size
-    = (input_section->size
-       - (mmix_elf_section_data (input_section)->pjs.n_pushj_relocs
-         * MAX_PUSHJ_STUB_SIZE));
+  bfd_size_type size;
   size_t pjsno = 0;
 
+  size = input_section->rawsize ? input_section->rawsize : input_section->size;
   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
   sym_hashes = elf_sym_hashes (input_bfd);
   relend = relocs + input_section->reloc_count;
 
+  /* Zero the stub area before we start.  */
+  if (input_section->rawsize != 0
+      && input_section->size > input_section->rawsize)
+    memset (contents + input_section->rawsize, 0,
+           input_section->size - input_section->rawsize);
+
   for (rel = relocs; rel < relend; rel ++)
     {
       reloc_howto_type *howto;
@@ -1374,22 +1381,53 @@ mmix_elf_relocate_section (output_bfd, info, input_bfd, input_section,
 
       r_symndx = ELF64_R_SYM (rel->r_info);
 
+      howto = elf_mmix_howto_table + ELF64_R_TYPE (rel->r_info);
+      h = NULL;
+      sym = NULL;
+      sec = NULL;
+
+      if (r_symndx < symtab_hdr->sh_info)
+       {
+         sym = local_syms + r_symndx;
+         sec = local_sections [r_symndx];
+         relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
+
+         name = bfd_elf_string_from_elf_section (input_bfd,
+                                                 symtab_hdr->sh_link,
+                                                 sym->st_name);
+         if (name == NULL)
+           name = bfd_section_name (input_bfd, sec);
+       }
+      else
+       {
+         bfd_boolean unresolved_reloc;
+
+         RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
+                                  r_symndx, symtab_hdr, sym_hashes,
+                                  h, sec, relocation,
+                                  unresolved_reloc, undefined_signalled);
+         name = h->root.root.string;
+       }
+
+      if (sec != NULL && elf_discarded_section (sec))
+       {
+         /* For relocs against symbols from removed linkonce sections,
+            or sections discarded by a linker script, we just want the
+            section contents zeroed.  Avoid any special processing.  */
+         _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
+         rel->r_info = 0;
+         rel->r_addend = 0;
+         continue;
+       }
+
       if (info->relocatable)
        {
          /* This is a relocatable link.  For most relocs we don't have to
             change anything, unless the reloc is against a section
             symbol, in which case we have to adjust according to where
             the section symbol winds up in the output section.  */
-         if (r_symndx < symtab_hdr->sh_info)
-           {
-             sym = local_syms + r_symndx;
-
-             if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
-               {
-                 sec = local_sections [r_symndx];
-                 rel->r_addend += sec->output_offset + sym->st_value;
-               }
-           }
+         if (sym != NULL && ELF_ST_TYPE (sym->st_info) == STT_SECTION)
+           rel->r_addend += sec->output_offset;
 
          /* For PUSHJ stub relocs however, we may need to change the
             reloc and the section contents, if the reloc doesn't reach
@@ -1463,35 +1501,6 @@ mmix_elf_relocate_section (output_bfd, info, input_bfd, input_section,
          continue;
        }
 
-      /* This is a final link.  */
-      howto = elf_mmix_howto_table + ELF64_R_TYPE (rel->r_info);
-      h = NULL;
-      sym = NULL;
-      sec = NULL;
-
-      if (r_symndx < symtab_hdr->sh_info)
-       {
-         sym = local_syms + r_symndx;
-         sec = local_sections [r_symndx];
-         relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
-
-         name = bfd_elf_string_from_elf_section (input_bfd,
-                                                 symtab_hdr->sh_link,
-                                                 sym->st_name);
-         if (name == NULL)
-           name = bfd_section_name (input_bfd, sec);
-       }
-      else
-       {
-         bfd_boolean unresolved_reloc;
-
-         RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
-                                  r_symndx, symtab_hdr, sym_hashes,
-                                  h, sec, relocation,
-                                  unresolved_reloc, undefined_signalled);
-         name = h->root.root.string;
-       }
-
       r = mmix_final_link_relocate (howto, input_section,
                                    contents, rel->r_offset,
                                    rel->r_addend, relocation, name, sec);
@@ -1505,8 +1514,8 @@ mmix_elf_relocate_section (output_bfd, info, input_bfd, input_section,
            {
            case bfd_reloc_overflow:
              check_ok = info->callbacks->reloc_overflow
-               (info, name, howto->name, (bfd_vma) 0,
-                input_bfd, input_section, rel->r_offset);
+               (info, (h ? &h->root : NULL), name, howto->name,
+                (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
              break;
 
            case bfd_reloc_undefined:
@@ -1745,40 +1754,21 @@ mmix_final_link_relocate (howto, input_section, contents,
    relocation.  */
 
 static asection *
-mmix_elf_gc_mark_hook (sec, info, rel, h, sym)
-     asection *sec;
-     struct bfd_link_info *info ATTRIBUTE_UNUSED;
-     Elf_Internal_Rela *rel;
-     struct elf_link_hash_entry *h;
-     Elf_Internal_Sym *sym;
+mmix_elf_gc_mark_hook (asection *sec,
+                      struct bfd_link_info *info,
+                      Elf_Internal_Rela *rel,
+                      struct elf_link_hash_entry *h,
+                      Elf_Internal_Sym *sym)
 {
   if (h != NULL)
-    {
-      switch (ELF64_R_TYPE (rel->r_info))
-       {
-       case R_MMIX_GNU_VTINHERIT:
-       case R_MMIX_GNU_VTENTRY:
-         break;
-
-       default:
-         switch (h->root.type)
-           {
-           case bfd_link_hash_defined:
-           case bfd_link_hash_defweak:
-             return h->root.u.def.section;
-
-           case bfd_link_hash_common:
-             return h->root.u.c.p->section;
-
-           default:
-             break;
-           }
-       }
-    }
-  else
-    return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
+    switch (ELF64_R_TYPE (rel->r_info))
+      {
+      case R_MMIX_GNU_VTINHERIT:
+      case R_MMIX_GNU_VTENTRY:
+       return NULL;
+      }
 
-  return NULL;
+  return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
 }
 
 /* Update relocation info for a GC-excluded section.  We could supposedly
@@ -1787,11 +1777,10 @@ mmix_elf_gc_mark_hook (sec, info, rel, h, sym)
    present.  Better to waste some memory and (perhaps) a little time.  */
 
 static bfd_boolean
-mmix_elf_gc_sweep_hook (abfd, info, sec, relocs)
-     bfd *abfd ATTRIBUTE_UNUSED;
-     struct bfd_link_info *info ATTRIBUTE_UNUSED;
-     asection *sec ATTRIBUTE_UNUSED;
-     const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED;
+mmix_elf_gc_sweep_hook (bfd *abfd ATTRIBUTE_UNUSED,
+                       struct bfd_link_info *info ATTRIBUTE_UNUSED,
+                       asection *sec,
+                       const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED)
 {
   struct bpo_reloc_section_info *bpodata
     = mmix_elf_section_data (sec)->bpo.reloc;
@@ -1895,19 +1884,17 @@ mmix_elf_check_common_relocs  (abfd, info, sec, relocs)
          if (allocated_gregs_section == NULL)
            {
              allocated_gregs_section
-               = bfd_make_section (bpo_greg_owner,
-                                   MMIX_LD_ALLOCATED_REG_CONTENTS_SECTION_NAME);
+               = bfd_make_section_with_flags (bpo_greg_owner,
+                                              MMIX_LD_ALLOCATED_REG_CONTENTS_SECTION_NAME,
+                                              (SEC_HAS_CONTENTS
+                                               | SEC_IN_MEMORY
+                                               | SEC_LINKER_CREATED));
              /* Setting both SEC_ALLOC and SEC_LOAD means the section is
                 treated like any other section, and we'd get errors for
                 address overlap with the text section.  Let's set none of
                 those flags, as that is what currently happens for usual
                 GREG allocations, and that works.  */
              if (allocated_gregs_section == NULL
-                 || !bfd_set_section_flags (bpo_greg_owner,
-                                            allocated_gregs_section,
-                                            (SEC_HAS_CONTENTS
-                                             | SEC_IN_MEMORY
-                                             | SEC_LINKER_CREATED))
                  || !bfd_set_section_alignment (bpo_greg_owner,
                                                 allocated_gregs_section,
                                                 3))
@@ -2021,7 +2008,12 @@ mmix_elf_check_relocs (abfd, info, sec, relocs)
       if (r_symndx < symtab_hdr->sh_info)
         h = NULL;
       else
-        h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+       {
+         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;
+       }
 
       switch (ELF64_R_TYPE (rel->r_info))
        {
@@ -2186,10 +2178,12 @@ mmix_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
      bfd_vma *valp ATTRIBUTE_UNUSED;
 {
   if (sym->st_shndx == SHN_REGISTER)
-    *secp = bfd_make_section_old_way (abfd, MMIX_REG_SECTION_NAME);
+    {
+      *secp = bfd_make_section_old_way (abfd, MMIX_REG_SECTION_NAME);
+      (*secp)->flags |= SEC_LINKER_CREATED;
+    }
   else if ((*namep)[0] == '_' && (*namep)[1] == '_' && (*namep)[2] == '.'
-          && strncmp (*namep, MMIX_LOC_SECTION_START_SYMBOL_PREFIX,
-                      strlen (MMIX_LOC_SECTION_START_SYMBOL_PREFIX)) == 0)
+          && CONST_STRNEQ (*namep, MMIX_LOC_SECTION_START_SYMBOL_PREFIX))
     {
       /* See if we have another one.  */
       struct bfd_link_hash_entry *h = bfd_link_hash_lookup (info->hash,
@@ -2254,7 +2248,6 @@ mmix_elf_final_link (abfd, info)
   /* We never output a register section, though we create one for
      temporary measures.  Check that nobody entered contents into it.  */
   asection *reg_section;
-  asection **secpp;
 
   reg_section = bfd_get_section_by_name (abfd, MMIX_REG_SECTION_NAME);
 
@@ -2264,13 +2257,12 @@ mmix_elf_final_link (abfd, info)
       if (bfd_get_section_flags (abfd, reg_section) & SEC_HAS_CONTENTS)
        _bfd_abort (__FILE__, __LINE__, _("Register section has contents\n"));
 
-      /* Really remove the section.  */
-      for (secpp = &abfd->sections;
-          *secpp != reg_section;
-          secpp = &(*secpp)->next)
-       ;
-      bfd_section_list_remove (abfd, secpp);
-      --abfd->section_count;
+      /* Really remove the section, if it hasn't already been done.  */
+      if (!bfd_section_removed_from_list (abfd, reg_section))
+       {
+         bfd_section_list_remove (abfd, reg_section);
+         --abfd->section_count;
+       }
     }
 
   if (! bfd_elf_final_link (abfd, info))
@@ -2310,6 +2302,7 @@ mmix_set_relaxable_size (abfd, sec, ptr)
   if (mmix_elf_section_data (sec)->pjs.n_pushj_relocs == 0)
     return;
 
+  sec->rawsize = sec->size;
   sec->size += (mmix_elf_section_data (sec)->pjs.n_pushj_relocs
                * MAX_PUSHJ_STUB_SIZE);
 
@@ -2589,9 +2582,7 @@ mmix_elf_relax_section (abfd, sec, link_info, again)
   size_t pjsno = 0;
   bfd *bpo_greg_owner;
   Elf_Internal_Sym *isymbuf = NULL;
-  bfd_size_type size = (sec->size
-                       - (mmix_elf_section_data (sec)->pjs.n_pushj_relocs
-                          * MAX_PUSHJ_STUB_SIZE));
+  bfd_size_type size = sec->rawsize ? sec->rawsize : sec->size;
 
   mmix_elf_section_data (sec)->pjs.stubs_size_sum = 0;
 
@@ -2669,7 +2660,7 @@ mmix_elf_relax_section (abfd, sec, link_info, again)
                                      0,
                                      bfd_arch_bits_per_address (abfd),
                                      /* Output-stub location.  */
-                                     sec->output_section->size
+                                     sec->output_section->rawsize
                                      + (mmix_elf_section_data (sec
                                                               ->output_section)
                                         ->pjs.stubs_size_sum)
@@ -2910,52 +2901,6 @@ mmix_elf_relax_section (abfd, sec, link_info, again)
     free (internal_relocs);
   return FALSE;
 }
-
-/* Because we set size to include the max size of pushj stubs,
-   i.e. larger than the actual section input size (see
-   mmix_set_relaxablesize), we have to take care of that when reading
-   the section.  */
-
-static bfd_boolean
-mmix_elf_get_section_contents (abfd, section, location, offset, count)
-     bfd *abfd;
-     sec_ptr section;
-     void *location;
-     file_ptr offset;
-     bfd_size_type count;
-{
-  bfd_size_type size = (section->size
-                       - (mmix_elf_section_data (section)->pjs.n_pushj_relocs
-                          * MAX_PUSHJ_STUB_SIZE));
-
-  if (offset + count > section->size)
-    {
-      abort();
-      bfd_set_error (bfd_error_invalid_operation);
-      return FALSE;
-    }
-
-  /* Check bounds against the faked size.  */
-  if (offset + count > size)
-    {
-      /* Clear the part in the faked area.  */
-      memset (location + size - offset, 0, count - (size - offset));
-
-      /* If there's no initial part within the "real" contents, we're
-         done.  */
-      if ((bfd_size_type) offset >= size)
-       return TRUE;
-
-      /* Else adjust the count and fall through to call the generic
-         function.  */
-      count = size - offset;
-    }
-
-  return
-    _bfd_generic_get_section_contents (abfd, section, location, offset,
-                                      count);
-}
-
 \f
 #define ELF_ARCH               bfd_arch_mmix
 #define ELF_MACHINE_CODE       EM_MMIX
@@ -2989,6 +2934,8 @@ mmix_elf_get_section_contents (abfd, section, location, offset, count)
 
 #define elf_backend_check_relocs       mmix_elf_check_relocs
 #define elf_backend_symbol_processing  mmix_elf_symbol_processing
+#define elf_backend_omit_section_dynsym \
+  ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true)
 
 #define bfd_elf64_bfd_is_local_label_name \
        mmix_elf_is_local_label_name
@@ -3004,6 +2951,5 @@ mmix_elf_get_section_contents (abfd, section, location, offset, count)
 #define bfd_elf64_new_section_hook     mmix_elf_new_section_hook
 #define bfd_elf64_bfd_final_link       mmix_elf_final_link
 #define bfd_elf64_bfd_relax_section    mmix_elf_relax_section
-#define bfd_elf64_get_section_contents mmix_elf_get_section_contents
 
 #include "elf64-target.h"
This page took 0.035748 seconds and 4 git commands to generate.