* elflink.h (struct elf_link_sort_rela): Turn rel and rela
[deliverable/binutils-gdb.git] / bfd / elf64-sparc.c
index 0742e22790d1d18d669602e8d592939d39a504a4..f79d76c30bd244658d8fdda7203dc1ca119eb1da 100644 (file)
@@ -1,5 +1,5 @@
 /* SPARC-specific support for 64-bit ELF
-   Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+   Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
    Free Software Foundation, Inc.
 
 This file is part of BFD, the Binary File Descriptor library.
@@ -69,11 +69,12 @@ static boolean sparc64_elf_output_arch_syms
 static void sparc64_elf_symbol_processing
   PARAMS ((bfd *, asymbol *));
 
-static boolean sparc64_elf_copy_private_bfd_data
-  PARAMS ((bfd *, bfd *));
 static boolean sparc64_elf_merge_private_bfd_data
   PARAMS ((bfd *, bfd *));
 
+static boolean sparc64_elf_fake_sections
+  PARAMS ((bfd *, Elf32_Internal_Shdr *, asection *));
+
 static const char *sparc64_elf_print_symbol_all
   PARAMS ((bfd *, PTR, asymbol *));
 static boolean sparc64_elf_relax_section
@@ -96,7 +97,8 @@ static boolean sparc64_elf_slurp_reloc_table
 static long sparc64_elf_canonicalize_dynamic_reloc
   PARAMS ((bfd *, arelent **, asymbol **));
 static void sparc64_elf_write_relocs PARAMS ((bfd *, asection *, PTR));
-static enum elf_reloc_type_class sparc64_elf_reloc_type_class PARAMS ((int));
+static enum elf_reloc_type_class sparc64_elf_reloc_type_class
+  PARAMS ((const Elf_Internal_Rela *));
 \f
 /* The relocation "howto" table.  */
 
@@ -117,7 +119,7 @@ static reloc_howto_type sparc64_elf_howto_table[] =
   HOWTO(R_SPARC_32,        0,2,32,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_32",      false,0,0xffffffff,true),
   HOWTO(R_SPARC_DISP8,     0,0, 8,true, 0,complain_overflow_signed,  bfd_elf_generic_reloc,  "R_SPARC_DISP8",   false,0,0x000000ff,true),
   HOWTO(R_SPARC_DISP16,    0,1,16,true, 0,complain_overflow_signed,  bfd_elf_generic_reloc,  "R_SPARC_DISP16",  false,0,0x0000ffff,true),
-  HOWTO(R_SPARC_DISP32,    0,2,32,true, 0,complain_overflow_signed,  bfd_elf_generic_reloc,  "R_SPARC_DISP32",  false,0,0x00ffffff,true),
+  HOWTO(R_SPARC_DISP32,    0,2,32,true, 0,complain_overflow_signed,  bfd_elf_generic_reloc,  "R_SPARC_DISP32",  false,0,0xffffffff,true),
   HOWTO(R_SPARC_WDISP30,   2,2,30,true, 0,complain_overflow_signed,  bfd_elf_generic_reloc,  "R_SPARC_WDISP30", false,0,0x3fffffff,true),
   HOWTO(R_SPARC_WDISP22,   2,2,22,true, 0,complain_overflow_signed,  bfd_elf_generic_reloc,  "R_SPARC_WDISP22", false,0,0x003fffff,true),
   HOWTO(R_SPARC_HI22,     10,2,22,false,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_HI22",    false,0,0x003fffff,true),
@@ -136,8 +138,8 @@ static reloc_howto_type sparc64_elf_howto_table[] =
   HOWTO(R_SPARC_RELATIVE,  0,0,00,false,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_RELATIVE",false,0,0x00000000,true),
   HOWTO(R_SPARC_UA32,      0,2,32,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_UA32",    false,0,0xffffffff,true),
 #ifndef SPARC64_OLD_RELOCS
+  HOWTO(R_SPARC_PLT32,     0,2,32,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_PLT32",   false,0,0xffffffff,true),
   /* These aren't implemented yet.  */
-  HOWTO(R_SPARC_PLT32,     0,0,00,false,0,complain_overflow_dont,    sparc_elf_notsup_reloc, "R_SPARC_PLT32",    false,0,0x00000000,true),
   HOWTO(R_SPARC_HIPLT22,   0,0,00,false,0,complain_overflow_dont,    sparc_elf_notsup_reloc, "R_SPARC_HIPLT22",  false,0,0x00000000,true),
   HOWTO(R_SPARC_LOPLT10,   0,0,00,false,0,complain_overflow_dont,    sparc_elf_notsup_reloc, "R_SPARC_LOPLT10",  false,0,0x00000000,true),
   HOWTO(R_SPARC_PCPLT32,   0,0,00,false,0,complain_overflow_dont,    sparc_elf_notsup_reloc, "R_SPARC_PCPLT32",  false,0,0x00000000,true),
@@ -161,7 +163,7 @@ static reloc_howto_type sparc64_elf_howto_table[] =
   HOWTO(R_SPARC_5,         0,2, 5,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_5",       false,0,0x0000001f,true),
   HOWTO(R_SPARC_6,         0,2, 6,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_6",       false,0,0x0000003f,true),
   HOWTO(R_SPARC_DISP64,    0,4,64,true, 0,complain_overflow_signed,  bfd_elf_generic_reloc,  "R_SPARC_DISP64",  false,0,MINUS_ONE, true),
-  HOWTO(R_SPARC_PLT64,     0,4,64,false,0,complain_overflow_bitfield,sparc_elf_notsup_reloc, "R_SPARC_PLT64",   false,0,MINUS_ONE, false),
+  HOWTO(R_SPARC_PLT64,     0,4,64,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_PLT64",   false,0,MINUS_ONE, true),
   HOWTO(R_SPARC_HIX22,     0,4, 0,false,0,complain_overflow_bitfield,sparc_elf_hix22_reloc,  "R_SPARC_HIX22",   false,0,MINUS_ONE, false),
   HOWTO(R_SPARC_LOX10,     0,4, 0,false,0,complain_overflow_dont,    sparc_elf_lox10_reloc,  "R_SPARC_LOX10",   false,0,MINUS_ONE, false),
   HOWTO(R_SPARC_H44,      22,2,22,false,0,complain_overflow_unsigned,bfd_elf_generic_reloc,  "R_SPARC_H44",     false,0,0x003fffff,false),
@@ -181,6 +183,7 @@ static const struct elf_reloc_map sparc_reloc_map[] =
 {
   { BFD_RELOC_NONE, R_SPARC_NONE, },
   { BFD_RELOC_16, R_SPARC_16, },
+  { BFD_RELOC_16_PCREL, R_SPARC_DISP16 },
   { BFD_RELOC_8, R_SPARC_8 },
   { BFD_RELOC_8_PCREL, R_SPARC_DISP8 },
   { BFD_RELOC_CTOR, R_SPARC_64 },
@@ -189,6 +192,7 @@ static const struct elf_reloc_map sparc_reloc_map[] =
   { BFD_RELOC_HI22, R_SPARC_HI22 },
   { BFD_RELOC_LO10, R_SPARC_LO10, },
   { BFD_RELOC_32_PCREL_S2, R_SPARC_WDISP30 },
+  { BFD_RELOC_64_PCREL, R_SPARC_DISP64 },
   { BFD_RELOC_SPARC22, R_SPARC_22 },
   { BFD_RELOC_SPARC13, R_SPARC_13 },
   { BFD_RELOC_SPARC_GOT10, R_SPARC_GOT10 },
@@ -221,6 +225,9 @@ static const struct elf_reloc_map sparc_reloc_map[] =
   { BFD_RELOC_SPARC_5, R_SPARC_5 },
   { BFD_RELOC_SPARC_6, R_SPARC_6 },
   { BFD_RELOC_SPARC_DISP64, R_SPARC_DISP64 },
+#ifndef SPARC64_OLD_RELOCS
+  { BFD_RELOC_SPARC_PLT32, R_SPARC_PLT32 },
+#endif
   { BFD_RELOC_SPARC_PLT64, R_SPARC_PLT64 },
   { BFD_RELOC_SPARC_HIX22, R_SPARC_HIX22 },
   { BFD_RELOC_SPARC_LOX10, R_SPARC_LOX10 },
@@ -655,14 +662,14 @@ sparc64_elf_bfd_link_hash_table_create (abfd)
   struct sparc64_elf_link_hash_table *ret;
   bfd_size_type amt = sizeof (struct sparc64_elf_link_hash_table);
 
-  ret = (struct sparc64_elf_link_hash_table *) bfd_zalloc (abfd, amt);
+  ret = (struct sparc64_elf_link_hash_table *) bfd_zmalloc (amt);
   if (ret == (struct sparc64_elf_link_hash_table *) NULL)
     return NULL;
 
   if (! _bfd_elf_link_hash_table_init (&ret->root, abfd,
                                       _bfd_elf_link_hash_newfunc))
     {
-      bfd_release (abfd, ret);
+      free (ret);
       return NULL;
     }
 
@@ -707,7 +714,7 @@ init_insn_reloc (abfd,
       return bfd_reloc_ok;
     }
 
-  /* This works because partial_inplace == false.  */
+  /* This works because partial_inplace is false.  */
   if (output_bfd != NULL)
     return bfd_reloc_continue;
 
@@ -920,8 +927,8 @@ sparc64_elf_build_plt (output_bfd, contents, nentries)
          entry = contents + i*PLT_ENTRY_SIZE + j*4*6;
          ptr = contents + i*PLT_ENTRY_SIZE + block*4*6 + j*8;
 
-         /* ldx [%o7 + ptr - entry+4], %g1 */
-         ldx = 0xc25be000 | ((ptr - entry+4) & 0x1fff);
+         /* ldx [%o7 + ptr - (entry+4)], %g1 */
+         ldx = 0xc25be000 | ((ptr - (entry+4)) & 0x1fff);
 
          /* mov %o7,%g5
             call .+8
@@ -1168,8 +1175,10 @@ sparc64_elf_check_relocs (abfd, info, sec, relocs)
            }
 
          h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
-         break;
-
+         if (ELF64_R_TYPE_ID (rel->r_info) != R_SPARC_PLT32
+             && ELF64_R_TYPE_ID (rel->r_info) != R_SPARC_PLT64)
+           break;
+         /* Fall through.  */
        case R_SPARC_PC10:
        case R_SPARC_PC22:
        case R_SPARC_PC_HH22:
@@ -1269,7 +1278,7 @@ sparc64_elf_check_relocs (abfd, info, sec, relocs)
 
        default:
          (*_bfd_error_handler) (_("%s: check_relocs: unhandled reloc type %d"),
-                               bfd_get_filename(abfd),
+                               bfd_archive_filename (abfd),
                                ELF64_R_TYPE_ID (rel->r_info));
          return false;
        }
@@ -1291,7 +1300,7 @@ sparc64_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
      asection **secp ATTRIBUTE_UNUSED;
      bfd_vma *valp ATTRIBUTE_UNUSED;
 {
-  static char *stt_types[] = { "NOTYPE", "OBJECT", "FUNCTION" };
+  static const char *const stt_types[] = { "NOTYPE", "OBJECT", "FUNCTION" };
 
   if (ELF_ST_TYPE (sym->st_info) == STT_REGISTER)
     {
@@ -1306,7 +1315,7 @@ sparc64_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
        default:
           (*_bfd_error_handler)
             (_("%s: Only registers %%g[2367] can be declared using STT_REGISTER"),
-             bfd_get_filename (abfd));
+             bfd_archive_filename (abfd));
          return false;
        }
 
@@ -1325,11 +1334,10 @@ sparc64_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
       if (p->name != NULL && strcmp (p->name, *namep))
        {
           (*_bfd_error_handler)
-            (_("Register %%g%d used incompatibly: "
-               "previously declared in %s to %s, in %s redefined to %s"),
-             (int)sym->st_value,
-             bfd_get_filename (p->abfd), *p->name ? p->name : "#scratch",
-             bfd_get_filename (abfd), **namep ? *namep : "#scratch");
+            (_("Register %%g%d used incompatibly: %s in %s, previously %s in %s"),
+             (int) sym->st_value,
+             **namep ? *namep : "#scratch", bfd_archive_filename (abfd),
+             *p->name ? p->name : "#scratch", bfd_archive_filename (p->abfd));
          return false;
        }
 
@@ -1346,11 +1354,12 @@ sparc64_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
                {
                  unsigned char type = h->type;
 
-                 if (type > STT_FUNC) type = 0;
+                 if (type > STT_FUNC)
+                   type = 0;
                  (*_bfd_error_handler)
-                   (_("Symbol `%s' has differing types: "
-                      "previously %s, REGISTER in %s"),
-                    *namep, stt_types [type], bfd_get_filename (abfd));
+                   (_("Symbol `%s' has differing types: REGISTER in %s, previously %s in %s"),
+                    *namep, bfd_archive_filename (abfd),
+                    stt_types[type], bfd_archive_filename (p->abfd));
                  return false;
                }
 
@@ -1379,9 +1388,8 @@ sparc64_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
       *namep = NULL;
       return true;
     }
-  else if (! *namep || ! **namep)
-    return true;
-  else
+  else if (*namep && **namep
+          && info->hash->creator == abfd->xvec)
     {
       int i;
       struct sparc64_elf_app_reg *p;
@@ -1392,12 +1400,12 @@ sparc64_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
          {
            unsigned char type = ELF_ST_TYPE (sym->st_info);
 
-           if (type > STT_FUNC) type = 0;
+           if (type > STT_FUNC)
+             type = 0;
            (*_bfd_error_handler)
-             (_("Symbol `%s' has differing types: "
-                "REGISTER in %s, %s in %s"),
-              *namep, bfd_get_filename (p->abfd), stt_types [type],
-              bfd_get_filename (abfd));
+             (_("Symbol `%s' has differing types: %s in %s, previously REGISTER in %s"),
+              *namep, stt_types[type], bfd_archive_filename (abfd),
+              bfd_archive_filename (p->abfd));
            return false;
          }
     }
@@ -1779,7 +1787,7 @@ sparc64_elf_size_dynamic_sections (output_bfd, info)
 
       int reg;
       struct sparc64_elf_app_reg * app_regs;
-      struct bfd_strtab_hash *dynstr;
+      struct elf_strtab_hash *dynstr;
       struct elf_link_hash_table *eht = elf_hash_table (info);
 
       if (!info->shared)
@@ -1833,7 +1841,7 @@ sparc64_elf_size_dynamic_sections (output_bfd, info)
            entry->isym.st_size = 0;
            if (*app_regs [reg].name != '\0')
              entry->isym.st_name
-               = _bfd_stringtab_add (dynstr, app_regs[reg].name, true, false);
+               = _bfd_elf_strtab_add (dynstr, app_regs[reg].name, false);
            else
              entry->isym.st_name = 0;
            entry->isym.st_other = 0;
@@ -1875,6 +1883,17 @@ sparc64_elf_relax_section (abfd, section, link_info, again)
   return true;
 }
 \f
+/* This is the condition under which finish_dynamic_symbol will be called
+   from elflink.h.  If elflink.h doesn't call our finish_dynamic_symbol
+   routine, we'll need to do something about initializing any .plt and
+   .got entries in relocate_section.  */
+#define WILL_CALL_FINISH_DYNAMIC_SYMBOL(DYN, INFO, H)                  \
+  ((DYN)                                                               \
+   && ((INFO)->shared                                                  \
+       || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)     \
+   && ((H)->dynindx != -1                                              \
+       || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0))
+
 /* Relocate a SPARC64 ELF section.  */
 
 static boolean
@@ -1900,6 +1919,9 @@ sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
   Elf_Internal_Rela *rel;
   Elf_Internal_Rela *relend;
 
+  if (info->relocateable)
+    return true;
+
   dynobj = elf_hash_table (info)->dynobj;
   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
   sym_hashes = elf_sym_hashes (input_bfd);
@@ -1922,8 +1944,10 @@ sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
       struct elf_link_hash_entry *h;
       Elf_Internal_Sym *sym;
       asection *sec;
-      bfd_vma relocation;
+      bfd_vma relocation, off;
       bfd_reloc_status_type r;
+      boolean is_plt = false;
+      boolean unresolved_reloc;
 
       r_type = ELF64_R_TYPE_ID (rel->r_info);
       if (r_type < 0 || r_type >= (int) R_SPARC_max_std)
@@ -1933,38 +1957,17 @@ sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
        }
       howto = sparc64_elf_howto_table + r_type;
 
-      r_symndx = ELF64_R_SYM (rel->r_info);
-
-      if (info->relocateable)
-       {
-         /* This is a relocateable link.  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;
-               }
-           }
-
-         continue;
-       }
-
       /* This is a final link.  */
+      r_symndx = ELF64_R_SYM (rel->r_info);
       h = NULL;
       sym = NULL;
       sec = NULL;
+      unresolved_reloc = false;
       if (r_symndx < symtab_hdr->sh_info)
        {
          sym = local_syms + r_symndx;
          sec = local_sections[r_symndx];
-         relocation = (sec->output_section->vma
-                       + sec->output_offset
-                       + sym->st_value);
+         relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel);
        }
       else
        {
@@ -1972,107 +1975,30 @@ sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
          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)
            {
-             boolean skip_it = false;
              sec = h->root.u.def.section;
-
-             switch (r_type)
-               {
-               case R_SPARC_WPLT30:
-               case R_SPARC_PLT32:
-               case R_SPARC_HIPLT22:
-               case R_SPARC_LOPLT10:
-               case R_SPARC_PCPLT32:
-               case R_SPARC_PCPLT22:
-               case R_SPARC_PCPLT10:
-               case R_SPARC_PLT64:
-                 if (h->plt.offset != (bfd_vma) -1)
-                   skip_it = true;
-                 break;
-
-               case R_SPARC_GOT10:
-               case R_SPARC_GOT13:
-               case R_SPARC_GOT22:
-                 if (elf_hash_table(info)->dynamic_sections_created
-                     && (!info->shared
-                         || (!info->symbolic && h->dynindx != -1)
-                         || !(h->elf_link_hash_flags
-                              & ELF_LINK_HASH_DEF_REGULAR)))
-                   skip_it = true;
-                 break;
-
-               case R_SPARC_PC10:
-               case R_SPARC_PC22:
-               case R_SPARC_PC_HH22:
-               case R_SPARC_PC_HM10:
-               case R_SPARC_PC_LM22:
-                 if (!strcmp(h->root.root.string, "_GLOBAL_OFFSET_TABLE_"))
-                   break;
-                 /* FALLTHRU */
-
-               case R_SPARC_8:
-               case R_SPARC_16:
-               case R_SPARC_32:
-               case R_SPARC_DISP8:
-               case R_SPARC_DISP16:
-               case R_SPARC_DISP32:
-               case R_SPARC_WDISP30:
-               case R_SPARC_WDISP22:
-               case R_SPARC_HI22:
-               case R_SPARC_22:
-               case R_SPARC_13:
-               case R_SPARC_LO10:
-               case R_SPARC_UA32:
-               case R_SPARC_10:
-               case R_SPARC_11:
-               case R_SPARC_64:
-               case R_SPARC_OLO10:
-               case R_SPARC_HH22:
-               case R_SPARC_HM10:
-               case R_SPARC_LM22:
-               case R_SPARC_WDISP19:
-               case R_SPARC_WDISP16:
-               case R_SPARC_7:
-               case R_SPARC_5:
-               case R_SPARC_6:
-               case R_SPARC_DISP64:
-               case R_SPARC_HIX22:
-               case R_SPARC_LOX10:
-               case R_SPARC_H44:
-               case R_SPARC_M44:
-               case R_SPARC_L44:
-               case R_SPARC_UA64:
-               case R_SPARC_UA16:
-                 if (info->shared
-                     && ((!info->symbolic && h->dynindx != -1)
-                         || !(h->elf_link_hash_flags
-                              & ELF_LINK_HASH_DEF_REGULAR)))
-                   skip_it = true;
-                 break;
-               }
-
-             if (skip_it)
-               {
-                 /* In these cases, we don't need the relocation
-                     value.  We check specially because in some
-                     obscure cases sec->output_section will be NULL.  */
-                 relocation = 0;
-               }
+             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);
-               }
+               relocation = (h->root.u.def.value
+                             + sec->output_section->vma
+                             + sec->output_offset);
            }
          else if (h->root.type == bfd_link_hash_undefweak)
-           relocation = 0;
-         else if (info->shared && !info->symbolic
+           ;
+         else if (info->shared
+                  && (!info->symbolic || info->allow_shlib_undefined)
                   && !info->no_undefined
                   && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
-           relocation = 0;
+           ;
          else
            {
              if (! ((*info->callbacks->undefined_symbol)
@@ -2093,9 +2019,10 @@ sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
            }
        }
 
+ do_dynreloc:
       /* When generating a shared object, these relocations are copied
         into the output file to be resolved at run time.  */
-      if (info->shared && (input_section->flags & SEC_ALLOC))
+      if (info->shared && r_symndx != 0 && (input_section->flags & SEC_ALLOC))
        {
          switch (r_type)
            {
@@ -2111,11 +2038,11 @@ sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
            case R_SPARC_DISP8:
            case R_SPARC_DISP16:
            case R_SPARC_DISP32:
+           case R_SPARC_DISP64:
            case R_SPARC_WDISP30:
            case R_SPARC_WDISP22:
            case R_SPARC_WDISP19:
            case R_SPARC_WDISP16:
-           case R_SPARC_DISP64:
              if (h == NULL)
                break;
              /* Fall through.  */
@@ -2146,7 +2073,7 @@ sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
            case R_SPARC_UA16:
              {
                Elf_Internal_Rela outrel;
-               boolean skip;
+               boolean skip, relocate;
 
                if (sreloc == NULL)
                  {
@@ -2169,22 +2096,15 @@ sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                  }
 
                skip = false;
+               relocate = false;
 
-               if (elf_section_data (input_section)->stab_info == NULL)
-                 outrel.r_offset = rel->r_offset;
-               else
-                 {
-                   bfd_vma off;
-
-                   off = (_bfd_stab_section_offset
-                          (output_bfd, &elf_hash_table (info)->stab_info,
-                           input_section,
-                           &elf_section_data (input_section)->stab_info,
-                           rel->r_offset));
-                   if (off == MINUS_ONE)
-                     skip = true;
-                   outrel.r_offset = off;
-                 }
+               outrel.r_offset =
+                 _bfd_elf_section_offset (output_bfd, info, input_section,
+                                          rel->r_offset);
+               if (outrel.r_offset == (bfd_vma) -1)
+                 skip = true;
+               else if (outrel.r_offset == (bfd_vma) -2)
+                 skip = true, relocate = true;
 
                outrel.r_offset += (input_section->output_section->vma
                                    + input_section->output_offset);
@@ -2211,13 +2131,25 @@ sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                  case R_SPARC_UA64:
                    if (!(outrel.r_offset & 7)) r_type = R_SPARC_64;
                    break;
+                 case R_SPARC_DISP8:
+                 case R_SPARC_DISP16:
+                 case R_SPARC_DISP32:
+                 case R_SPARC_DISP64:
+                   /* If the symbol is not dynamic, we should not keep
+                      a dynamic relocation.  But an .rela.* slot has been
+                      allocated for it, output R_SPARC_NONE.
+                      FIXME: Add code tracking needed dynamic relocs as
+                      e.g. i386 has.  */
+                   if (h->dynindx == -1)
+                     skip = true, relocate = true;
+                   break;
                  }
 
                if (skip)
                  memset (&outrel, 0, sizeof outrel);
                /* h->dynindx may be -1 if the symbol was marked to
                   become local.  */
-               else if (h != NULL
+               else if (h != NULL && ! is_plt
                         && ((! info->symbolic && h->dynindx != -1)
                             || (h->elf_link_hash_flags
                                 & ELF_LINK_HASH_DEF_REGULAR) == 0))
@@ -2241,7 +2173,9 @@ sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                      {
                        long indx;
 
-                       if (h == NULL)
+                       if (is_plt)
+                         sec = splt;
+                       else if (h == NULL)
                          sec = local_sections[r_symndx];
                        else
                          {
@@ -2271,7 +2205,7 @@ sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                                BFD_FAIL ();
                                (*_bfd_error_handler)
                                  (_("%s: probably compiled without -fPIC?"),
-                                  bfd_get_filename (input_bfd));
+                                  bfd_archive_filename (input_bfd));
                                bfd_set_error (bfd_error_bad_value);
                                return false;
                              }
@@ -2294,7 +2228,8 @@ sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
 
                /* This reloc will be computed at runtime, so there's no
                   need to do anything now.  */
-               continue;
+               if (! relocate)
+                 continue;
              }
            break;
            }
@@ -2315,14 +2250,18 @@ sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
 
          if (h != NULL)
            {
-             bfd_vma off = h->got.offset;
+             boolean dyn;
+
+             off = h->got.offset;
              BFD_ASSERT (off != (bfd_vma) -1);
+             dyn = elf_hash_table (info)->dynamic_sections_created;
 
-             if (! elf_hash_table (info)->dynamic_sections_created
+             if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h)
                  || (info->shared
-                     && (info->symbolic || h->dynindx == -1)
-                     && (h->elf_link_hash_flags
-                         & ELF_LINK_HASH_DEF_REGULAR)))
+                     && (info->symbolic
+                         || h->dynindx == -1
+                         || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL))
+                     && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)))
                {
                  /* This is actually a static link, or it is a -Bsymbolic
                     link and the symbol is defined locally, or the symbol
@@ -2345,12 +2284,11 @@ sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                      h->got.offset |= 1;
                    }
                }
-             relocation = sgot->output_offset + off - got_base;
+             else
+               unresolved_reloc = false;
            }
          else
            {
-             bfd_vma off;
-
              BFD_ASSERT (local_got_offsets != NULL);
              off = local_got_offsets[r_symndx];
              BFD_ASSERT (off != (bfd_vma) -1);
@@ -2396,8 +2334,8 @@ sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                  else
                    bfd_put_64 (output_bfd, relocation, sgot->contents + off);
                }
-             relocation = sgot->output_offset + off - got_base;
            }
+         relocation = sgot->output_offset + off - got_base;
          goto do_default;
 
        case R_SPARC_WPLT30:
@@ -2429,8 +2367,15 @@ sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
          relocation = (splt->output_section->vma
                        + splt->output_offset
                        + sparc64_elf_plt_entry_offset (h->plt.offset));
+         unresolved_reloc = false;
          if (r_type == R_SPARC_WPLT30)
            goto do_wplt30;
+         if (r_type == R_SPARC_PLT32 || r_type == R_SPARC_PLT64)
+           {
+             r_type = r_type == R_SPARC_PLT32 ? R_SPARC_32 : R_SPARC_64;
+             is_plt = true;
+             goto do_dynreloc;
+           }
          goto do_default;
 
        case R_SPARC_OLO10:
@@ -2606,6 +2551,19 @@ sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
          break;
        }
 
+      /* Dynamic relocs are not propagated for SEC_DEBUGGING sections
+        because such sections are not SEC_ALLOC and thus ld.so will
+        not process them.  */
+      if (unresolved_reloc
+         && !((input_section->flags & SEC_DEBUGGING) != 0
+              && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0))
+       (*_bfd_error_handler)
+         (_("%s(%s+0x%lx): unresolvable relocation against symbol `%s'"),
+          bfd_archive_filename (input_bfd),
+          bfd_get_section_name (input_bfd, input_section),
+          (long) rel->r_offset,
+          h->root.root.string);
+
       switch (r)
        {
        case bfd_reloc_ok:
@@ -2619,6 +2577,16 @@ sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
          {
            const char *name;
 
+           /* The Solaris native linker silently disregards
+              overflows.  We don't, but this breaks stabs debugging
+              info, whose relocations are only 32-bits wide.  Ignore
+              overflows in this case.  */
+           if (r_type == R_SPARC_32
+               && (input_section->flags & SEC_DEBUGGING) != 0
+               && strcmp (bfd_section_name (input_bfd, input_section),
+                          ".stab") == 0)
+             break;
+
            if (h != NULL)
              {
                if (h->root.type == bfd_link_hash_undefweak
@@ -2759,11 +2727,12 @@ sparc64_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
        }
       else
        {
-         bfd_put_64 (output_bfd, (bfd_vma) 0, sgot->contents + h->got.offset);
          rela.r_info = ELF64_R_INFO (h->dynindx, R_SPARC_GLOB_DAT);
          rela.r_addend = 0;
        }
 
+      bfd_put_64 (output_bfd, (bfd_vma) 0,
+                 sgot->contents + (h->got.offset &~ (bfd_vma) 1));
       bfd_elf64_swap_reloca_out (output_bfd, &rela,
                                 ((Elf64_External_Rela *) srela->contents
                                  + srela->reloc_count));
@@ -2910,10 +2879,10 @@ sparc64_elf_finish_dynamic_sections (output_bfd, info)
 }
 
 static enum elf_reloc_type_class
-sparc64_elf_reloc_type_class (type)
-     int type;
+sparc64_elf_reloc_type_class (rela)
+     const Elf_Internal_Rela *rela;
 {
-  switch (type)
+  switch ((int) ELF64_R_TYPE (rela->r_info))
     {
     case R_SPARC_RELATIVE:
       return reloc_class_relative;
@@ -2928,24 +2897,6 @@ sparc64_elf_reloc_type_class (type)
 \f
 /* Functions for dealing with the e_flags field.  */
 
-/* Copy backend specific data from one object module to another */
-static boolean
-sparc64_elf_copy_private_bfd_data (ibfd, obfd)
-     bfd *ibfd, *obfd;
-{
-  if (   bfd_get_flavour (ibfd) != bfd_target_elf_flavour
-      || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
-    return true;
-
-  BFD_ASSERT (!elf_flags_init (obfd)
-              || (elf_elfheader (obfd)->e_flags
-                  == elf_elfheader (ibfd)->e_flags));
-
-  elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
-  elf_flags_init (obfd) = true;
-  return true;
-}
-
 /* Merge backend specific data from an object file to the output
    object file when linking.  */
 
@@ -3001,7 +2952,7 @@ sparc64_elf_merge_private_bfd_data (ibfd, obfd)
              error = true;
              (*_bfd_error_handler)
                (_("%s: linking UltraSPARC specific with HAL specific code"),
-                bfd_get_filename (ibfd));
+                bfd_archive_filename (ibfd));
            }
          /* Choose the most restrictive memory ordering.  */
          old_mm = (old_flags & EF_SPARCV9_MM);
@@ -3020,7 +2971,7 @@ sparc64_elf_merge_private_bfd_data (ibfd, obfd)
           error = true;
           (*_bfd_error_handler)
             (_("%s: uses different e_flags (0x%lx) fields than previous modules (0x%lx)"),
-             bfd_get_filename (ibfd), (long)new_flags, (long)old_flags);
+             bfd_archive_filename (ibfd), (long) new_flags, (long) old_flags);
         }
 
       elf_elfheader (obfd)->e_flags = old_flags;
@@ -3033,6 +2984,27 @@ sparc64_elf_merge_private_bfd_data (ibfd, obfd)
     }
   return true;
 }
+
+/* MARCO: Set the correct entry size for the .stab section.  */
+
+static boolean
+sparc64_elf_fake_sections (abfd, hdr, sec)
+     bfd *abfd ATTRIBUTE_UNUSED;
+     Elf32_Internal_Shdr *hdr ATTRIBUTE_UNUSED;
+     asection *sec;
+{
+  const char *name;
+
+  name = bfd_get_section_name (abfd, sec);
+
+  if (strcmp (name, ".stab") == 0)
+    {
+      /* Even in the 64bit case the stab entries are only 12 bytes long.  */
+      elf_section_data (sec)->this_hdr.sh_entsize = 12;
+    }
+  
+  return true;
+}
 \f
 /* Print a STT_REGISTER symbol to file FILE.  */
 
@@ -3105,6 +3077,7 @@ const struct elf_size_info sparc64_elf_size_info =
   bfd_elf64_write_out_phdrs,
   bfd_elf64_write_shdrs_and_ehdr,
   sparc64_elf_write_relocs,
+  bfd_elf64_swap_symbol_in,
   bfd_elf64_swap_symbol_out,
   sparc64_elf_slurp_reloc_table,
   bfd_elf64_slurp_symbol_table,
@@ -3167,10 +3140,10 @@ const struct elf_size_info sparc64_elf_size_info =
   sparc64_elf_print_symbol_all
 #define elf_backend_output_arch_syms \
   sparc64_elf_output_arch_syms
-#define bfd_elf64_bfd_copy_private_bfd_data \
-  sparc64_elf_copy_private_bfd_data
 #define bfd_elf64_bfd_merge_private_bfd_data \
   sparc64_elf_merge_private_bfd_data
+#define elf_backend_fake_sections \
+  sparc64_elf_fake_sections
 
 #define elf_backend_size_info \
   sparc64_elf_size_info
@@ -3182,6 +3155,7 @@ const struct elf_size_info sparc64_elf_size_info =
 #define elf_backend_want_got_plt 0
 #define elf_backend_plt_readonly 0
 #define elf_backend_want_plt_sym 1
+#define elf_backend_rela_normal 1
 
 /* Section 5.2.4 of the ABI specifies a 256-byte boundary for the table.  */
 #define elf_backend_plt_alignment 8
This page took 0.034721 seconds and 4 git commands to generate.