daily update
[deliverable/binutils-gdb.git] / bfd / elf64-mmix.c
index c37130c2e29e1b341113bc7abb8bc3a148dbfbed..b090f23bee496bfff0002d648bd48333125feebc 100644 (file)
@@ -1,22 +1,25 @@
 /* MMIX-specific support for 64-bit ELF.
-   Copyright 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009
+   Free Software Foundation, Inc.
    Contributed by Hans-Peter Nilsson <hp@bitrange.com>
 
-This file is part of BFD, the Binary File Descriptor library.
+   This file is part of BFD, the Binary File Descriptor library.
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
 
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   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., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
 
-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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
 
 /* No specific ABI or "processor-specific supplement" defined.  */
 
@@ -26,8 +29,8 @@ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
    - GETA stub relaxation (call a stub for out of range new
      R_MMIX_GETA_STUBBABLE).  */
 
-#include "bfd.h"
 #include "sysdep.h"
+#include "bfd.h"
 #include "libbfd.h"
 #include "elf-bfd.h"
 #include "elf/mmix.h"
@@ -156,7 +159,7 @@ struct bpo_greg_section_info
     struct bpo_reloc_request *reloc_request;
   };
 
-static bfd_boolean mmix_elf_link_output_symbol_hook
+static int mmix_elf_link_output_symbol_hook
   PARAMS ((struct bfd_link_info *, const char *, Elf_Internal_Sym *,
           asection *, struct elf_link_hash_entry *));
 
@@ -186,14 +189,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 *));
@@ -855,18 +850,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);
 }
@@ -1369,22 +1383,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
@@ -1458,35 +1503,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);
@@ -1740,40 +1756,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
@@ -1782,11 +1779,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;
@@ -1890,19 +1886,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))
@@ -1984,15 +1978,12 @@ mmix_elf_check_relocs (abfd, info, sec, relocs)
      const Elf_Internal_Rela *relocs;
 {
   Elf_Internal_Shdr *symtab_hdr;
-  struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
+  struct elf_link_hash_entry **sym_hashes;
   const Elf_Internal_Rela *rel;
   const Elf_Internal_Rela *rel_end;
 
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
   sym_hashes = elf_sym_hashes (abfd);
-  sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof(Elf64_External_Sym);
-  if (!elf_bad_symtab (abfd))
-    sym_hashes_end -= symtab_hdr->sh_info;
 
   /* First we sort the relocs so that any register relocs come before
      expansion-relocs to the same insn.  FIXME: Not done for mmo.  */
@@ -2016,7 +2007,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))
        {
@@ -2030,7 +2026,9 @@ mmix_elf_check_relocs (abfd, info, sec, relocs)
         /* This relocation describes which C++ vtable entries are actually
            used.  Record for later use during GC.  */
         case R_MMIX_GNU_VTENTRY:
-          if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
+          BFD_ASSERT (h != NULL);
+          if (h != NULL
+              && !bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
             return FALSE;
           break;
        }
@@ -2084,7 +2082,7 @@ _bfd_mmix_check_all_relocs (abfd, info)
    the register section, and scale them down to correspond to the register
    number.  */
 
-static bfd_boolean
+static int
 mmix_elf_link_output_symbol_hook (info, name, sym, input_sec, h)
      struct bfd_link_info *info ATTRIBUTE_UNUSED;
      const char *name ATTRIBUTE_UNUSED;
@@ -2101,7 +2099,7 @@ mmix_elf_link_output_symbol_hook (info, name, sym, input_sec, h)
       sym->st_shndx = SHN_REGISTER;
     }
 
-  return TRUE;
+  return 1;
 }
 
 /* We fake a register section that holds values that are register numbers.
@@ -2181,10 +2179,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,
@@ -2258,9 +2258,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.  */
-      bfd_section_list_remove (abfd, reg_section);
-      --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))
@@ -2554,7 +2557,7 @@ mmix_dump_bpo_gregs (link_info, pf)
    when the last such reloc is done, an index-array is sorted according to
    the values and iterated over to produce register numbers (indexed by 0
    from the first allocated register number) and offsets for use in real
-   relocation.
+   relocation.  (N.B.: Relocatable runs are handled, not just punted.)
 
    PUSHJ stub accounting is also done here.
 
@@ -2932,6 +2935,8 @@ mmix_elf_relax_section (abfd, sec, link_info, again)
 
 #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
This page took 0.02972 seconds and 4 git commands to generate.