add symbol qualifiers for mach-o to bfd/gas
[deliverable/binutils-gdb.git] / bfd / elf64-mmix.c
index 881ba38b034277c8e4723ec3d5e6c68d9c87ece6..ecc9ad07d5cb3045b981e76737e453aa6d002bec 100644 (file)
@@ -1,23 +1,25 @@
 /* MMIX-specific support for 64-bit ELF.
-   Copyright 2001, 2002, 2003, 2004, 2005, 2006
+   Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010
    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.  */
 
@@ -27,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"
@@ -73,6 +75,13 @@ struct _mmix_elf_section_data
        stubs_size_sum for relocation.  */
     bfd_size_type stub_offset;
   } pjs;
+
+  /* Whether there has been a warning that this section could not be
+     linked due to a specific cause.  FIXME: a way to access the
+     linker info or output section, then stuff the limiter guard
+     there. */
+  bfd_boolean has_warned_bpo;
+  bfd_boolean has_warned_pushj;
 };
 
 #define mmix_elf_section_data(sec) \
@@ -157,7 +166,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 *));
 
@@ -187,20 +196,12 @@ 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 *));
+  (reloc_howto_type *, asection *, bfd_byte *, bfd_vma, bfd_signed_vma,
+   bfd_vma, const char *, asection *, char **);
 
 static bfd_reloc_status_type mmix_elf_perform_relocation
-  PARAMS ((asection *, reloc_howto_type *, PTR, bfd_vma, bfd_vma));
+  (asection *, reloc_howto_type *, void *, bfd_vma, bfd_vma, char **);
 
 static bfd_boolean mmix_elf_section_from_bfd_section
   PARAMS ((bfd *, asection *, int *));
@@ -856,6 +857,22 @@ 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;
@@ -924,12 +941,9 @@ mmix_elf_new_section_hook (abfd, sec)
    R_MMIX_ADDR19 and R_MMIX_ADDR27 are just filled in.  */
 
 static bfd_reloc_status_type
-mmix_elf_perform_relocation (isec, howto, datap, addr, value)
-     asection *isec;
-     reloc_howto_type *howto;
-     PTR datap;
-     bfd_vma addr;
-     bfd_vma value;
+mmix_elf_perform_relocation (asection *isec, reloc_howto_type *howto,
+                            void *datap, bfd_vma addr, bfd_vma value,
+                            char **error_message)
 {
   bfd *abfd = isec->owner;
   bfd_reloc_status_type flag = bfd_reloc_ok;
@@ -1003,6 +1017,36 @@ mmix_elf_perform_relocation (isec, howto, datap, addr, value)
               + mmix_elf_section_data (isec)->pjs.stub_offset);
          bfd_vma stubaddr;
 
+         if (mmix_elf_section_data (isec)->pjs.n_pushj_relocs == 0)
+           {
+             /* This shouldn't happen when linking to ELF or mmo, so
+                this is an attempt to link to "binary", right?  We
+                can't access the output bfd, so we can't verify that
+                assumption.  We only know that the critical
+                mmix_elf_check_common_relocs has not been called,
+                which happens when the output format is different
+                from the input format (and is not mmo).  */
+             if (! mmix_elf_section_data (isec)->has_warned_pushj)
+               {
+                 /* For the first such error per input section, produce
+                    a verbose message.  */
+                 *error_message
+                   = _("invalid input relocation when producing"
+                       " non-ELF, non-mmo format output."
+                       "\n Please use the objcopy program to convert from"
+                       " ELF or mmo,"
+                       "\n or assemble using"
+                       " \"-no-expand\" (for gcc, \"-Wa,-no-expand\"");
+                 mmix_elf_section_data (isec)->has_warned_pushj = TRUE;
+                 return bfd_reloc_dangerous;
+               }
+
+             /* For subsequent errors, return this one, which is
+                rate-limited but looks a little bit different,
+                hopefully without affecting user-friendliness.  */
+             return bfd_reloc_overflow;
+           }
+
          /* The address doesn't fit, so redirect the PUSHJ to the
             location of the stub.  */
          r = mmix_elf_perform_relocation (isec,
@@ -1015,7 +1059,8 @@ mmix_elf_perform_relocation (isec, howto, datap, addr, value)
                                           + size
                                           + (mmix_elf_section_data (isec)
                                              ->pjs.stub_offset)
-                                          - addr);
+                                          - addr,
+                                          error_message);
          if (r != bfd_reloc_ok)
            return r;
 
@@ -1039,7 +1084,8 @@ mmix_elf_perform_relocation (isec, howto, datap, addr, value)
                                               [R_MMIX_ADDR27],
                                               stubcontents,
                                               stubaddr,
-                                              value + addr - stubaddr);
+                                              value + addr - stubaddr,
+                                              error_message);
              mmix_elf_section_data (isec)->pjs.stub_offset += 4;
 
              if (size + mmix_elf_section_data (isec)->pjs.stub_offset
@@ -1151,12 +1197,43 @@ mmix_elf_perform_relocation (isec, howto, datap, addr, value)
       {
        struct bpo_reloc_section_info *bpodata
          = mmix_elf_section_data (isec)->bpo.reloc;
-       asection *bpo_greg_section
-         = bpodata->bpo_greg_section;
-       struct bpo_greg_section_info *gregdata
-         = mmix_elf_section_data (bpo_greg_section)->bpo.greg;
-       size_t bpo_index
-         = gregdata->bpo_reloc_indexes[bpodata->bpo_index++];
+       asection *bpo_greg_section;
+       struct bpo_greg_section_info *gregdata;
+       size_t bpo_index;
+
+       if (bpodata == NULL)
+         {
+           /* This shouldn't happen when linking to ELF or mmo, so
+              this is an attempt to link to "binary", right?  We
+              can't access the output bfd, so we can't verify that
+              assumption.  We only know that the critical
+              mmix_elf_check_common_relocs has not been called, which
+              happens when the output format is different from the
+              input format (and is not mmo).  */
+           if (! mmix_elf_section_data (isec)->has_warned_bpo)
+             {
+               /* For the first such error per input section, produce
+                  a verbose message.  */
+               *error_message
+                 = _("invalid input relocation when producing"
+                     " non-ELF, non-mmo format output."
+                     "\n Please use the objcopy program to convert from"
+                     " ELF or mmo,"
+                     "\n or compile using the gcc-option"
+                     " \"-mno-base-addresses\".");
+               mmix_elf_section_data (isec)->has_warned_bpo = TRUE;
+               return bfd_reloc_dangerous;
+             }
+
+           /* For subsequent errors, return this one, which is
+              rate-limited but looks a little bit different,
+              hopefully without affecting user-friendliness.  */
+           return bfd_reloc_overflow;
+         }
+
+       bpo_greg_section = bpodata->bpo_greg_section;
+       gregdata = mmix_elf_section_data (bpo_greg_section)->bpo.greg;
+       bpo_index = gregdata->bpo_reloc_indexes[bpodata->bpo_index++];
 
        /* A consistency check: The value we now have in "relocation" must
           be the same as the value we stored for that relocation.  It
@@ -1250,14 +1327,13 @@ mmix_elf_reloc (abfd, reloc_entry, symbol, data, input_section,
      PTR data;
      asection *input_section;
      bfd *output_bfd;
-     char **error_message ATTRIBUTE_UNUSED;
+     char **error_message;
 {
   bfd_vma relocation;
   bfd_reloc_status_type r;
   asection *reloc_target_output_section;
   bfd_reloc_status_type flag = bfd_reloc_ok;
   bfd_vma output_base = 0;
-  bfd_vma addr;
 
   r = bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
                             input_section, output_bfd, error_message);
@@ -1296,9 +1372,6 @@ mmix_elf_reloc (abfd, reloc_entry, symbol, data, input_section,
 
   relocation += output_base + symbol->section->output_offset;
 
-  /* Get position of relocation.  */
-  addr = (reloc_entry->address + input_section->output_section->vma
-         + input_section->output_offset);
   if (output_bfd != (bfd *) NULL)
     {
       /* Add in supplied addend.  */
@@ -1316,7 +1389,8 @@ mmix_elf_reloc (abfd, reloc_entry, symbol, data, input_section,
                                   data, reloc_entry->address,
                                   reloc_entry->addend, relocation,
                                   bfd_asymbol_name (symbol),
-                                  reloc_target_output_section);
+                                  reloc_target_output_section,
+                                  error_message);
 }
 \f
 /* Relocate an MMIX ELF section.  Modified from elf32-fr30.c; look to it
@@ -1373,22 +1447,46 @@ 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))
+       RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
+                                        rel, relend, howto, contents);
+
       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
@@ -1424,7 +1522,7 @@ mmix_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                                                + size
                                                + mmix_elf_section_data (input_section)
                                                ->pjs.stub_offset,
-                                               NULL, NULL) != bfd_reloc_ok)
+                                               NULL, NULL, NULL) != bfd_reloc_ok)
                    return FALSE;
 
                  /* Put a JMP insn at the stub; it goes with the
@@ -1462,38 +1560,9 @@ 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);
+                                   rel->r_addend, relocation, name, sec, NULL);
 
       if (r != bfd_reloc_ok)
        {
@@ -1550,16 +1619,11 @@ mmix_elf_relocate_section (output_bfd, info, input_bfd, input_section,
    routines.  A few relocs we have to do ourselves.  */
 
 static bfd_reloc_status_type
-mmix_final_link_relocate (howto, input_section, contents,
-                         r_offset, r_addend, relocation, symname, symsec)
-     reloc_howto_type *howto;
-     asection *input_section;
-     bfd_byte *contents;
-     bfd_vma r_offset;
-     bfd_signed_vma r_addend;
-     bfd_vma relocation;
-     const char *symname;
-     asection *symsec;
+mmix_final_link_relocate (reloc_howto_type *howto, asection *input_section,
+                         bfd_byte *contents, bfd_vma r_offset,
+                         bfd_signed_vma r_addend, bfd_vma relocation,
+                         const char *symname, asection *symsec,
+                         char **error_message)
 {
   bfd_reloc_status_type r = bfd_reloc_ok;
   bfd_vma addr
@@ -1586,7 +1650,7 @@ mmix_final_link_relocate (howto, input_section, contents,
               + r_offset);
 
       r = mmix_elf_perform_relocation (input_section, howto, contents,
-                                      addr, srel);
+                                      addr, srel, error_message);
       break;
 
     case R_MMIX_BASE_PLUS_OFFSET:
@@ -1668,7 +1732,7 @@ mmix_final_link_relocate (howto, input_section, contents,
     do_mmix_reloc:
       contents += r_offset;
       r = mmix_elf_perform_relocation (input_section, howto, contents,
-                                      addr, srel);
+                                      addr, srel, error_message);
       break;
 
     case R_MMIX_LOCAL:
@@ -1744,40 +1808,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
@@ -1786,11 +1831,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;
@@ -1986,15 +2030,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.  */
@@ -2037,7 +2078,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;
        }
@@ -2091,7 +2134,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;
@@ -2108,7 +2151,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.
@@ -2566,7 +2609,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.
 
@@ -2590,7 +2633,6 @@ mmix_elf_relax_section (abfd, sec, link_info, again)
      spot a missing actual initialization.  */
   size_t bpono = (size_t) -1;
   size_t pjsno = 0;
-  bfd *bpo_greg_owner;
   Elf_Internal_Sym *isymbuf = NULL;
   bfd_size_type size = sec->rawsize ? sec->rawsize : sec->size;
 
@@ -2613,8 +2655,6 @@ mmix_elf_relax_section (abfd, sec, link_info, again)
 
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
 
-  bpo_greg_owner = (bfd *) link_info->base_file;
-
   if (bpodata != NULL)
     {
       bpo_gregs_section = bpodata->bpo_greg_section;
@@ -2944,6 +2984,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.030185 seconds and 4 git commands to generate.