daily update
[binutils-gdb.git] / bfd / elfxx-sparc.c
index 9155311c3818156292257ff7733df267bef70807..9684ffd7a4d9ef294769cbc4a605bdfd3d705b02 100644 (file)
@@ -53,7 +53,7 @@
 
 static bfd_reloc_status_type
 init_insn_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
-                PTR data, asection *input_section, bfd *output_bfd,
+                void * data, asection *input_section, bfd *output_bfd,
                 bfd_vma *prelocation, bfd_vma *pinsn)
 {
   bfd_vma relocation;
@@ -97,7 +97,7 @@ static bfd_reloc_status_type
 sparc_elf_notsup_reloc (bfd *abfd ATTRIBUTE_UNUSED,
                        arelent *reloc_entry ATTRIBUTE_UNUSED,
                        asymbol *symbol ATTRIBUTE_UNUSED,
-                       PTR data ATTRIBUTE_UNUSED,
+                       void * data ATTRIBUTE_UNUSED,
                        asection *input_section ATTRIBUTE_UNUSED,
                        bfd *output_bfd ATTRIBUTE_UNUSED,
                        char **error_message ATTRIBUTE_UNUSED)
@@ -109,7 +109,7 @@ sparc_elf_notsup_reloc (bfd *abfd ATTRIBUTE_UNUSED,
 
 static bfd_reloc_status_type
 sparc_elf_wdisp16_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
-                        PTR data, asection *input_section, bfd *output_bfd,
+                        void * data, asection *input_section, bfd *output_bfd,
                         char **error_message ATTRIBUTE_UNUSED)
 {
   bfd_vma relocation;
@@ -132,11 +132,39 @@ sparc_elf_wdisp16_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
     return bfd_reloc_ok;
 }
 
+/* Handle the WDISP10 reloc.  */
+
+static bfd_reloc_status_type
+sparc_elf_wdisp10_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
+                        void * data, asection *input_section, bfd *output_bfd,
+                        char **error_message ATTRIBUTE_UNUSED)
+{
+  bfd_vma relocation;
+  bfd_vma insn;
+  bfd_reloc_status_type status;
+
+  status = init_insn_reloc (abfd, reloc_entry, symbol, data,
+                           input_section, output_bfd, &relocation, &insn);
+  if (status != bfd_reloc_other)
+    return status;
+
+  insn &= ~ (bfd_vma) 0x181fe0;
+  insn |= (((relocation >> 2) & 0x300) << 11)
+         | (((relocation >> 2) & 0xff) << 5);
+  bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc_entry->address);
+
+  if ((bfd_signed_vma) relocation < - 0x1000
+      || (bfd_signed_vma) relocation > 0xfff)
+    return bfd_reloc_overflow;
+  else
+    return bfd_reloc_ok;
+}
+
 /* Handle the HIX22 reloc.  */
 
 static bfd_reloc_status_type
 sparc_elf_hix22_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
-                      PTR data, asection *input_section, bfd *output_bfd,
+                      void * data, asection *input_section, bfd *output_bfd,
                       char **error_message ATTRIBUTE_UNUSED)
 {
   bfd_vma relocation;
@@ -162,7 +190,7 @@ sparc_elf_hix22_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
 
 static bfd_reloc_status_type
 sparc_elf_lox10_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
-                      PTR data, asection *input_section, bfd *output_bfd,
+                      void * data, asection *input_section, bfd *output_bfd,
                       char **error_message ATTRIBUTE_UNUSED)
 {
   bfd_vma relocation;
@@ -267,6 +295,10 @@ static reloc_howto_type _bfd_sparc_elf_howto_table[] =
   HOWTO(R_SPARC_GOTDATA_OP_HIX22,0,2,0,FALSE,0,complain_overflow_bitfield,sparc_elf_hix22_reloc,"R_SPARC_GOTDATA_OP_HIX22",FALSE,0,0x003fffff, FALSE),
   HOWTO(R_SPARC_GOTDATA_OP_LOX10,0,2,0,FALSE,0,complain_overflow_dont,  sparc_elf_lox10_reloc,  "R_SPARC_GOTDATA_OP_LOX10",FALSE,0,0x000003ff, FALSE),
   HOWTO(R_SPARC_GOTDATA_OP,0,0, 0,FALSE,0,complain_overflow_dont,   bfd_elf_generic_reloc,  "R_SPARC_GOTDATA_OP",FALSE,0,0x00000000,TRUE),
+  HOWTO(R_SPARC_H34,12,2,22,FALSE,0,complain_overflow_unsigned,bfd_elf_generic_reloc,"R_SPARC_H34",FALSE,0,0x003fffff,FALSE),
+  HOWTO(R_SPARC_SIZE32,0,2,32,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc,"R_SPARC_SIZE32",FALSE,0,0xffffffff,TRUE),
+  HOWTO(R_SPARC_SIZE64,0,4,64,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc,"R_SPARC_SIZE64",FALSE,0,MINUS_ONE, TRUE),
+  HOWTO(R_SPARC_WDISP10,2,2,10,TRUE, 0,complain_overflow_signed,sparc_elf_wdisp10_reloc,"R_SPARC_WDISP10",FALSE,0,0x00000000,TRUE),
 };
 static reloc_howto_type sparc_jmp_irel_howto =
   HOWTO(R_SPARC_JMP_IREL,  0,0,00,FALSE,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_JMP_IREL",FALSE,0,0x00000000,TRUE);
@@ -524,6 +556,18 @@ _bfd_sparc_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
     case BFD_RELOC_SPARC_GOTDATA_OP:
       return &_bfd_sparc_elf_howto_table[R_SPARC_GOTDATA_OP];
 
+    case BFD_RELOC_SPARC_H34:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_H34];
+
+    case BFD_RELOC_SPARC_SIZE32:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_SIZE32];
+
+    case BFD_RELOC_SPARC_SIZE64:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_SIZE64];
+
+    case BFD_RELOC_SPARC_WDISP10:
+      return &_bfd_sparc_elf_howto_table[R_SPARC_WDISP10];
+
     case BFD_RELOC_SPARC_JMP_IREL:
       return &sparc_jmp_irel_howto;
 
@@ -1163,9 +1207,9 @@ _bfd_sparc_elf_create_dynamic_sections (bfd *dynobj,
   if (!_bfd_elf_create_dynamic_sections (dynobj, info))
     return FALSE;
 
-  htab->sdynbss = bfd_get_section_by_name (dynobj, ".dynbss");
+  htab->sdynbss = bfd_get_linker_section (dynobj, ".dynbss");
   if (!info->shared)
-    htab->srelbss = bfd_get_section_by_name (dynobj, ".rela.bss");
+    htab->srelbss = bfd_get_linker_section (dynobj, ".rela.bss");
 
   if (htab->is_vxworks)
     {
@@ -1389,7 +1433,7 @@ _bfd_sparc_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
                                                TRUE);
              if (h == NULL)
                return FALSE;
-             
+
              /* Fake a STT_GNU_IFUNC symbol.  */
              h->type = STT_GNU_IFUNC;
              h->def_regular = 1;
@@ -1656,6 +1700,7 @@ _bfd_sparc_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
        case R_SPARC_WDISP22:
        case R_SPARC_WDISP19:
        case R_SPARC_WDISP16:
+       case R_SPARC_WDISP10:
        case R_SPARC_8:
        case R_SPARC_16:
        case R_SPARC_32:
@@ -1680,6 +1725,7 @@ _bfd_sparc_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
        case R_SPARC_H44:
        case R_SPARC_M44:
        case R_SPARC_L44:
+       case R_SPARC_H34:
        case R_SPARC_UA64:
          if (h != NULL)
            h->non_got_ref = 1;
@@ -1827,6 +1873,29 @@ _bfd_sparc_elf_gc_mark_hook (asection *sec,
        return NULL;
       }
 
+  /* FIXME: The test here, in check_relocs and in relocate_section
+     dealing with TLS optimization, ought to be !info->executable.  */
+  if (info->shared)
+    {
+      switch (SPARC_ELF_R_TYPE (rel->r_info))
+       {
+       case R_SPARC_TLS_GD_CALL:
+       case R_SPARC_TLS_LDM_CALL:
+         /* This reloc implicitly references __tls_get_addr.  We know
+            another reloc will reference the same symbol as the one
+            on this reloc, so the real symbol and section will be
+            gc marked when processing the other reloc.  That lets
+            us handle __tls_get_addr here.  */
+         h = elf_link_hash_lookup (elf_hash_table (info), "__tls_get_addr",
+                                   FALSE, FALSE, TRUE);
+         BFD_ASSERT (h != NULL);
+         h->mark = 1;
+         if (h->u.weakdef != NULL)
+           h->u.weakdef->mark = 1;
+         sym = NULL;
+       }
+    }
+
   return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
 }
 
@@ -1956,6 +2025,7 @@ _bfd_sparc_elf_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
        case R_SPARC_WDISP22:
        case R_SPARC_WDISP19:
        case R_SPARC_WDISP16:
+       case R_SPARC_WDISP10:
        case R_SPARC_8:
        case R_SPARC_16:
        case R_SPARC_32:
@@ -1981,6 +2051,7 @@ _bfd_sparc_elf_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
        case R_SPARC_H44:
        case R_SPARC_M44:
        case R_SPARC_L44:
+       case R_SPARC_H34:
        case R_SPARC_UA64:
          if (info->shared)
            break;
@@ -2143,7 +2214,7 @@ _bfd_sparc_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
    dynamic relocs.  */
 
 static bfd_boolean
-allocate_dynrelocs (struct elf_link_hash_entry *h, PTR inf)
+allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
 {
   struct bfd_link_info *info;
   struct _bfd_sparc_elf_link_hash_table *htab;
@@ -2423,7 +2494,7 @@ allocate_local_dynrelocs (void **slot, void *inf)
 /* Find any dynamic relocs that apply to read-only sections.  */
 
 static bfd_boolean
-readonly_dynrelocs (struct elf_link_hash_entry *h, PTR inf)
+readonly_dynrelocs (struct elf_link_hash_entry *h, void * inf)
 {
   struct _bfd_sparc_elf_link_hash_entry *eh;
   struct _bfd_sparc_elf_dyn_relocs *p;
@@ -2484,7 +2555,7 @@ _bfd_sparc_elf_size_dynamic_sections (bfd *output_bfd,
       /* Set the contents of the .interp section to the interpreter.  */
       if (info->executable)
        {
-         s = bfd_get_section_by_name (dynobj, ".interp");
+         s = bfd_get_linker_section (dynobj, ".interp");
          BFD_ASSERT (s != NULL);
          s->size = htab->dynamic_interpreter_size;
          s->contents = (unsigned char *) htab->dynamic_interpreter;
@@ -2579,7 +2650,7 @@ _bfd_sparc_elf_size_dynamic_sections (bfd *output_bfd,
 
   /* Allocate global sym .plt and .got entries, and space for global
      sym dynamic relocs.  */
-  elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, (PTR) info);
+  elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, info);
 
   /* Allocate .plt and .got entries, and space for local symbols.  */
   htab_traverse (htab->loc_hash_table, allocate_local_dynrelocs, info);
@@ -2694,8 +2765,7 @@ _bfd_sparc_elf_size_dynamic_sections (bfd *output_bfd,
       /* If any dynamic relocs apply to a read-only section,
         then we need a DT_TEXTREL entry.  */
       if ((info->flags & DF_TEXTREL) == 0)
-       elf_link_hash_traverse (&htab->elf, readonly_dynrelocs,
-                               (PTR) info);
+       elf_link_hash_traverse (&htab->elf, readonly_dynrelocs, info);
 
       if (info->flags & DF_TEXTREL)
        {
@@ -2938,7 +3008,7 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd,
              if (h == NULL)
                abort ();
 
-             /* Set STT_GNU_IFUNC symbol value.  */ 
+             /* Set STT_GNU_IFUNC symbol value.  */
              h->root.u.def.value = sym->st_value;
              h->root.u.def.section = sec;
            }
@@ -2963,9 +3033,9 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd,
            }
        }
 
-      if (sec != NULL && elf_discarded_section (sec))
+      if (sec != NULL && discarded_section (sec))
        RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-                                        rel, relend, howto, contents);
+                                        rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
        continue;
@@ -3231,7 +3301,7 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd,
              if (h == NULL)
                break;
            }
-         /* PR 7027: We need similar behaviour for 64-bit binaries.  */ 
+         /* PR 7027: We need similar behaviour for 64-bit binaries.  */
          else if (r_type == R_SPARC_WPLT30 && h == NULL)
            break;
          else
@@ -3276,6 +3346,7 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd,
        case R_SPARC_WDISP22:
        case R_SPARC_WDISP19:
        case R_SPARC_WDISP16:
+       case R_SPARC_WDISP10:
        case R_SPARC_8:
        case R_SPARC_16:
        case R_SPARC_32:
@@ -3300,6 +3371,7 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd,
        case R_SPARC_H44:
        case R_SPARC_M44:
        case R_SPARC_L44:
+       case R_SPARC_H34:
        case R_SPARC_UA64:
        r_sparc_plt32:
          if ((input_section->flags & SEC_ALLOC) == 0
@@ -3866,6 +3938,25 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd,
                | ((relocation >> 2) & 0x3fff));
          bfd_put_32 (input_bfd, x, contents + rel->r_offset);
 
+         r = bfd_check_overflow (howto->complain_on_overflow,
+                                 howto->bitsize, howto->rightshift,
+                                 bfd_arch_bits_per_address (input_bfd),
+                                 relocation);
+       }
+      else if (r_type == R_SPARC_WDISP10)
+       {
+         bfd_vma x;
+
+         relocation += rel->r_addend;
+         relocation -= (input_section->output_section->vma
+                        + input_section->output_offset);
+         relocation -= rel->r_offset;
+
+         x = bfd_get_32 (input_bfd, contents + rel->r_offset);
+         x |= ((((relocation >> 2) & 0x300) << 11)
+               | (((relocation >> 2) & 0xff) << 5));
+         bfd_put_32 (input_bfd, x, contents + rel->r_offset);
+
          r = bfd_check_overflow (howto->complain_on_overflow,
                                  howto->bitsize, howto->rightshift,
                                  bfd_arch_bits_per_address (input_bfd),
@@ -4058,7 +4149,7 @@ do_relocation:
              {
                const char *name;
 
-               /* The Solaris native linker silently disregards overflows. 
+               /* 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 and also for discarded entries.  */
@@ -4427,8 +4518,8 @@ _bfd_sparc_elf_finish_dynamic_symbol (bfd *output_bfd,
       /* This symbols needs a copy reloc.  Set it up.  */
       BFD_ASSERT (h->dynindx != -1);
 
-      s = bfd_get_section_by_name (h->root.u.def.section->owner,
-                                  ".rela.bss");
+      s = bfd_get_linker_section (h->root.u.def.section->owner,
+                                 ".rela.bss");
       BFD_ASSERT (s != NULL);
 
       rela.r_offset = (h->root.u.def.value
@@ -4443,7 +4534,7 @@ _bfd_sparc_elf_finish_dynamic_symbol (bfd *output_bfd,
      _GLOBAL_OFFSET_TABLE_ is not absolute: it is relative to the
      ".got" section.  Likewise _PROCEDURE_LINKAGE_TABLE_ and ".plt".  */
   if (sym != NULL
-      && (strcmp (h->root.root.string, "_DYNAMIC") == 0
+      && (h == htab->elf.hdynamic
          || (!htab->is_vxworks
              && (h == htab->elf.hgot || h == htab->elf.hplt))))
     sym->st_shndx = SHN_ABS;
@@ -4650,7 +4741,7 @@ finish_local_dynamic_symbol (void **slot, void *inf)
   struct elf_link_hash_entry *h
     = (struct elf_link_hash_entry *) *slot;
   struct bfd_link_info *info
-    = (struct bfd_link_info *) inf; 
+    = (struct bfd_link_info *) inf;
 
   return _bfd_sparc_elf_finish_dynamic_symbol (info->output_bfd, info,
                                               h, NULL);
@@ -4667,13 +4758,13 @@ _bfd_sparc_elf_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *i
   BFD_ASSERT (htab != NULL);
   dynobj = htab->elf.dynobj;
 
-  sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
+  sdyn = bfd_get_linker_section (dynobj, ".dynamic");
 
   if (elf_hash_table (info)->dynamic_sections_created)
     {
       asection *splt;
 
-      splt = bfd_get_section_by_name (dynobj, ".plt");
+      splt = htab->elf.splt;
       BFD_ASSERT (splt != NULL && sdyn != NULL);
 
       if (!sparc_finish_dyn (output_bfd, info, dynobj, sdyn, splt))