xref: /openbsd-src/gnu/usr.bin/binutils-2.17/bfd/elf64-sparc.c (revision 4f14f31be99dfbc7a75261c38db8eef97af1c125)
13d8817e4Smiod /* SPARC-specific support for 64-bit ELF
23d8817e4Smiod    Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
33d8817e4Smiod    2003, 2004, 2005 Free Software Foundation, Inc.
43d8817e4Smiod 
53d8817e4Smiod    This file is part of BFD, the Binary File Descriptor library.
63d8817e4Smiod 
73d8817e4Smiod    This program is free software; you can redistribute it and/or modify
83d8817e4Smiod    it under the terms of the GNU General Public License as published by
93d8817e4Smiod    the Free Software Foundation; either version 2 of the License, or
103d8817e4Smiod    (at your option) any later version.
113d8817e4Smiod 
123d8817e4Smiod    This program is distributed in the hope that it will be useful,
133d8817e4Smiod    but WITHOUT ANY WARRANTY; without even the implied warranty of
143d8817e4Smiod    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
153d8817e4Smiod    GNU General Public License for more details.
163d8817e4Smiod 
173d8817e4Smiod    You should have received a copy of the GNU General Public License
183d8817e4Smiod    along with this program; if not, write to the Free Software
193d8817e4Smiod    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
203d8817e4Smiod 
213d8817e4Smiod #include "bfd.h"
223d8817e4Smiod #include "sysdep.h"
233d8817e4Smiod #include "libbfd.h"
243d8817e4Smiod #include "elf-bfd.h"
253d8817e4Smiod #include "elf/sparc.h"
263d8817e4Smiod #include "opcode/sparc.h"
273d8817e4Smiod #include "elfxx-sparc.h"
283d8817e4Smiod 
293d8817e4Smiod /* In case we're on a 32-bit machine, construct a 64-bit "-1" value.  */
303d8817e4Smiod #define MINUS_ONE (~ (bfd_vma) 0)
313d8817e4Smiod 
323d8817e4Smiod /* Due to the way how we handle R_SPARC_OLO10, each entry in a SHT_RELA
333d8817e4Smiod    section can represent up to two relocs, we must tell the user to allocate
343d8817e4Smiod    more space.  */
353d8817e4Smiod 
363d8817e4Smiod static long
elf64_sparc_get_reloc_upper_bound(bfd * abfd ATTRIBUTE_UNUSED,asection * sec)373d8817e4Smiod elf64_sparc_get_reloc_upper_bound (bfd *abfd ATTRIBUTE_UNUSED, asection *sec)
383d8817e4Smiod {
393d8817e4Smiod   return (sec->reloc_count * 2 + 1) * sizeof (arelent *);
403d8817e4Smiod }
413d8817e4Smiod 
423d8817e4Smiod static long
elf64_sparc_get_dynamic_reloc_upper_bound(bfd * abfd)433d8817e4Smiod elf64_sparc_get_dynamic_reloc_upper_bound (bfd *abfd)
443d8817e4Smiod {
453d8817e4Smiod   return _bfd_elf_get_dynamic_reloc_upper_bound (abfd) * 2;
463d8817e4Smiod }
473d8817e4Smiod 
483d8817e4Smiod /* Read  relocations for ASECT from REL_HDR.  There are RELOC_COUNT of
493d8817e4Smiod    them.  We cannot use generic elf routines for this,  because R_SPARC_OLO10
503d8817e4Smiod    has secondary addend in ELF64_R_TYPE_DATA.  We handle it as two relocations
513d8817e4Smiod    for the same location,  R_SPARC_LO10 and R_SPARC_13.  */
523d8817e4Smiod 
533d8817e4Smiod static bfd_boolean
elf64_sparc_slurp_one_reloc_table(bfd * abfd,asection * asect,Elf_Internal_Shdr * rel_hdr,asymbol ** symbols,bfd_boolean dynamic)543d8817e4Smiod elf64_sparc_slurp_one_reloc_table (bfd *abfd, asection *asect,
553d8817e4Smiod 				   Elf_Internal_Shdr *rel_hdr,
563d8817e4Smiod 				   asymbol **symbols, bfd_boolean dynamic)
573d8817e4Smiod {
583d8817e4Smiod   PTR allocated = NULL;
593d8817e4Smiod   bfd_byte *native_relocs;
603d8817e4Smiod   arelent *relent;
613d8817e4Smiod   unsigned int i;
623d8817e4Smiod   int entsize;
633d8817e4Smiod   bfd_size_type count;
643d8817e4Smiod   arelent *relents;
653d8817e4Smiod 
663d8817e4Smiod   allocated = (PTR) bfd_malloc (rel_hdr->sh_size);
673d8817e4Smiod   if (allocated == NULL)
683d8817e4Smiod     goto error_return;
693d8817e4Smiod 
703d8817e4Smiod   if (bfd_seek (abfd, rel_hdr->sh_offset, SEEK_SET) != 0
713d8817e4Smiod       || bfd_bread (allocated, rel_hdr->sh_size, abfd) != rel_hdr->sh_size)
723d8817e4Smiod     goto error_return;
733d8817e4Smiod 
743d8817e4Smiod   native_relocs = (bfd_byte *) allocated;
753d8817e4Smiod 
763d8817e4Smiod   relents = asect->relocation + canon_reloc_count (asect);
773d8817e4Smiod 
783d8817e4Smiod   entsize = rel_hdr->sh_entsize;
793d8817e4Smiod   BFD_ASSERT (entsize == sizeof (Elf64_External_Rela));
803d8817e4Smiod 
813d8817e4Smiod   count = rel_hdr->sh_size / entsize;
823d8817e4Smiod 
833d8817e4Smiod   for (i = 0, relent = relents; i < count;
843d8817e4Smiod        i++, relent++, native_relocs += entsize)
853d8817e4Smiod     {
863d8817e4Smiod       Elf_Internal_Rela rela;
873d8817e4Smiod       unsigned int r_type;
883d8817e4Smiod 
893d8817e4Smiod       bfd_elf64_swap_reloca_in (abfd, native_relocs, &rela);
903d8817e4Smiod 
913d8817e4Smiod       /* The address of an ELF reloc is section relative for an object
923d8817e4Smiod 	 file, and absolute for an executable file or shared library.
933d8817e4Smiod 	 The address of a normal BFD reloc is always section relative,
943d8817e4Smiod 	 and the address of a dynamic reloc is absolute..  */
953d8817e4Smiod       if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0 || dynamic)
963d8817e4Smiod 	relent->address = rela.r_offset;
973d8817e4Smiod       else
983d8817e4Smiod 	relent->address = rela.r_offset - asect->vma;
993d8817e4Smiod 
1003d8817e4Smiod       if (ELF64_R_SYM (rela.r_info) == 0)
1013d8817e4Smiod 	relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
1023d8817e4Smiod       else
1033d8817e4Smiod 	{
1043d8817e4Smiod 	  asymbol **ps, *s;
1053d8817e4Smiod 
1063d8817e4Smiod 	  ps = symbols + ELF64_R_SYM (rela.r_info) - 1;
1073d8817e4Smiod 	  s = *ps;
1083d8817e4Smiod 
1093d8817e4Smiod 	  /* Canonicalize ELF section symbols.  FIXME: Why?  */
1103d8817e4Smiod 	  if ((s->flags & BSF_SECTION_SYM) == 0)
1113d8817e4Smiod 	    relent->sym_ptr_ptr = ps;
1123d8817e4Smiod 	  else
1133d8817e4Smiod 	    relent->sym_ptr_ptr = s->section->symbol_ptr_ptr;
1143d8817e4Smiod 	}
1153d8817e4Smiod 
1163d8817e4Smiod       relent->addend = rela.r_addend;
1173d8817e4Smiod 
1183d8817e4Smiod       r_type = ELF64_R_TYPE_ID (rela.r_info);
1193d8817e4Smiod       if (r_type == R_SPARC_OLO10)
1203d8817e4Smiod 	{
1213d8817e4Smiod 	  relent->howto = _bfd_sparc_elf_info_to_howto_ptr (R_SPARC_LO10);
1223d8817e4Smiod 	  relent[1].address = relent->address;
1233d8817e4Smiod 	  relent++;
1243d8817e4Smiod 	  relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
1253d8817e4Smiod 	  relent->addend = ELF64_R_TYPE_DATA (rela.r_info);
1263d8817e4Smiod 	  relent->howto = _bfd_sparc_elf_info_to_howto_ptr (R_SPARC_13);
1273d8817e4Smiod 	}
1283d8817e4Smiod       else
1293d8817e4Smiod 	relent->howto = _bfd_sparc_elf_info_to_howto_ptr (r_type);
1303d8817e4Smiod     }
1313d8817e4Smiod 
1323d8817e4Smiod   canon_reloc_count (asect) += relent - relents;
1333d8817e4Smiod 
1343d8817e4Smiod   if (allocated != NULL)
1353d8817e4Smiod     free (allocated);
1363d8817e4Smiod 
1373d8817e4Smiod   return TRUE;
1383d8817e4Smiod 
1393d8817e4Smiod  error_return:
1403d8817e4Smiod   if (allocated != NULL)
1413d8817e4Smiod     free (allocated);
1423d8817e4Smiod   return FALSE;
1433d8817e4Smiod }
1443d8817e4Smiod 
1453d8817e4Smiod /* Read in and swap the external relocs.  */
1463d8817e4Smiod 
1473d8817e4Smiod static bfd_boolean
elf64_sparc_slurp_reloc_table(bfd * abfd,asection * asect,asymbol ** symbols,bfd_boolean dynamic)1483d8817e4Smiod elf64_sparc_slurp_reloc_table (bfd *abfd, asection *asect,
1493d8817e4Smiod 			       asymbol **symbols, bfd_boolean dynamic)
1503d8817e4Smiod {
1513d8817e4Smiod   struct bfd_elf_section_data * const d = elf_section_data (asect);
1523d8817e4Smiod   Elf_Internal_Shdr *rel_hdr;
1533d8817e4Smiod   Elf_Internal_Shdr *rel_hdr2;
1543d8817e4Smiod   bfd_size_type amt;
1553d8817e4Smiod 
1563d8817e4Smiod   if (asect->relocation != NULL)
1573d8817e4Smiod     return TRUE;
1583d8817e4Smiod 
1593d8817e4Smiod   if (! dynamic)
1603d8817e4Smiod     {
1613d8817e4Smiod       if ((asect->flags & SEC_RELOC) == 0
1623d8817e4Smiod 	  || asect->reloc_count == 0)
1633d8817e4Smiod 	return TRUE;
1643d8817e4Smiod 
1653d8817e4Smiod       rel_hdr = &d->rel_hdr;
1663d8817e4Smiod       rel_hdr2 = d->rel_hdr2;
1673d8817e4Smiod 
1683d8817e4Smiod       BFD_ASSERT (asect->rel_filepos == rel_hdr->sh_offset
1693d8817e4Smiod 		  || (rel_hdr2 && asect->rel_filepos == rel_hdr2->sh_offset));
1703d8817e4Smiod     }
1713d8817e4Smiod   else
1723d8817e4Smiod     {
1733d8817e4Smiod       /* Note that ASECT->RELOC_COUNT tends not to be accurate in this
1743d8817e4Smiod 	 case because relocations against this section may use the
1753d8817e4Smiod 	 dynamic symbol table, and in that case bfd_section_from_shdr
1763d8817e4Smiod 	 in elf.c does not update the RELOC_COUNT.  */
1773d8817e4Smiod       if (asect->size == 0)
1783d8817e4Smiod 	return TRUE;
1793d8817e4Smiod 
1803d8817e4Smiod       rel_hdr = &d->this_hdr;
1813d8817e4Smiod       asect->reloc_count = NUM_SHDR_ENTRIES (rel_hdr);
1823d8817e4Smiod       rel_hdr2 = NULL;
1833d8817e4Smiod     }
1843d8817e4Smiod 
1853d8817e4Smiod   amt = asect->reloc_count;
1863d8817e4Smiod   amt *= 2 * sizeof (arelent);
1873d8817e4Smiod   asect->relocation = (arelent *) bfd_alloc (abfd, amt);
1883d8817e4Smiod   if (asect->relocation == NULL)
1893d8817e4Smiod     return FALSE;
1903d8817e4Smiod 
1913d8817e4Smiod   /* The elf64_sparc_slurp_one_reloc_table routine increments
1923d8817e4Smiod      canon_reloc_count.  */
1933d8817e4Smiod   canon_reloc_count (asect) = 0;
1943d8817e4Smiod 
1953d8817e4Smiod   if (!elf64_sparc_slurp_one_reloc_table (abfd, asect, rel_hdr, symbols,
1963d8817e4Smiod 					  dynamic))
1973d8817e4Smiod     return FALSE;
1983d8817e4Smiod 
1993d8817e4Smiod   if (rel_hdr2
2003d8817e4Smiod       && !elf64_sparc_slurp_one_reloc_table (abfd, asect, rel_hdr2, symbols,
2013d8817e4Smiod 					     dynamic))
2023d8817e4Smiod     return FALSE;
2033d8817e4Smiod 
2043d8817e4Smiod   return TRUE;
2053d8817e4Smiod }
2063d8817e4Smiod 
2073d8817e4Smiod /* Canonicalize the relocs.  */
2083d8817e4Smiod 
2093d8817e4Smiod static long
elf64_sparc_canonicalize_reloc(bfd * abfd,sec_ptr section,arelent ** relptr,asymbol ** symbols)2103d8817e4Smiod elf64_sparc_canonicalize_reloc (bfd *abfd, sec_ptr section,
2113d8817e4Smiod 				arelent **relptr, asymbol **symbols)
2123d8817e4Smiod {
2133d8817e4Smiod   arelent *tblptr;
2143d8817e4Smiod   unsigned int i;
2153d8817e4Smiod   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
2163d8817e4Smiod 
2173d8817e4Smiod   if (! bed->s->slurp_reloc_table (abfd, section, symbols, FALSE))
2183d8817e4Smiod     return -1;
2193d8817e4Smiod 
2203d8817e4Smiod   tblptr = section->relocation;
2213d8817e4Smiod   for (i = 0; i < canon_reloc_count (section); i++)
2223d8817e4Smiod     *relptr++ = tblptr++;
2233d8817e4Smiod 
2243d8817e4Smiod   *relptr = NULL;
2253d8817e4Smiod 
2263d8817e4Smiod   return canon_reloc_count (section);
2273d8817e4Smiod }
2283d8817e4Smiod 
2293d8817e4Smiod 
2303d8817e4Smiod /* Canonicalize the dynamic relocation entries.  Note that we return
2313d8817e4Smiod    the dynamic relocations as a single block, although they are
2323d8817e4Smiod    actually associated with particular sections; the interface, which
2333d8817e4Smiod    was designed for SunOS style shared libraries, expects that there
2343d8817e4Smiod    is only one set of dynamic relocs.  Any section that was actually
2353d8817e4Smiod    installed in the BFD, and has type SHT_REL or SHT_RELA, and uses
2363d8817e4Smiod    the dynamic symbol table, is considered to be a dynamic reloc
2373d8817e4Smiod    section.  */
2383d8817e4Smiod 
2393d8817e4Smiod static long
elf64_sparc_canonicalize_dynamic_reloc(bfd * abfd,arelent ** storage,asymbol ** syms)2403d8817e4Smiod elf64_sparc_canonicalize_dynamic_reloc (bfd *abfd, arelent **storage,
2413d8817e4Smiod 					asymbol **syms)
2423d8817e4Smiod {
2433d8817e4Smiod   asection *s;
2443d8817e4Smiod   long ret;
2453d8817e4Smiod 
2463d8817e4Smiod   if (elf_dynsymtab (abfd) == 0)
2473d8817e4Smiod     {
2483d8817e4Smiod       bfd_set_error (bfd_error_invalid_operation);
2493d8817e4Smiod       return -1;
2503d8817e4Smiod     }
2513d8817e4Smiod 
2523d8817e4Smiod   ret = 0;
2533d8817e4Smiod   for (s = abfd->sections; s != NULL; s = s->next)
2543d8817e4Smiod     {
2553d8817e4Smiod       if (elf_section_data (s)->this_hdr.sh_link == elf_dynsymtab (abfd)
2563d8817e4Smiod 	  && (elf_section_data (s)->this_hdr.sh_type == SHT_RELA))
2573d8817e4Smiod 	{
2583d8817e4Smiod 	  arelent *p;
2593d8817e4Smiod 	  long count, i;
2603d8817e4Smiod 
2613d8817e4Smiod 	  if (! elf64_sparc_slurp_reloc_table (abfd, s, syms, TRUE))
2623d8817e4Smiod 	    return -1;
2633d8817e4Smiod 	  count = canon_reloc_count (s);
2643d8817e4Smiod 	  p = s->relocation;
2653d8817e4Smiod 	  for (i = 0; i < count; i++)
2663d8817e4Smiod 	    *storage++ = p++;
2673d8817e4Smiod 	  ret += count;
2683d8817e4Smiod 	}
2693d8817e4Smiod     }
2703d8817e4Smiod 
2713d8817e4Smiod   *storage = NULL;
2723d8817e4Smiod 
2733d8817e4Smiod   return ret;
2743d8817e4Smiod }
2753d8817e4Smiod 
2763d8817e4Smiod /* Write out the relocs.  */
2773d8817e4Smiod 
2783d8817e4Smiod static void
elf64_sparc_write_relocs(bfd * abfd,asection * sec,PTR data)2793d8817e4Smiod elf64_sparc_write_relocs (bfd *abfd, asection *sec, PTR data)
2803d8817e4Smiod {
2813d8817e4Smiod   bfd_boolean *failedp = (bfd_boolean *) data;
2823d8817e4Smiod   Elf_Internal_Shdr *rela_hdr;
2833d8817e4Smiod   bfd_vma addr_offset;
2843d8817e4Smiod   Elf64_External_Rela *outbound_relocas, *src_rela;
2853d8817e4Smiod   unsigned int idx, count;
2863d8817e4Smiod   asymbol *last_sym = 0;
2873d8817e4Smiod   int last_sym_idx = 0;
2883d8817e4Smiod 
2893d8817e4Smiod   /* If we have already failed, don't do anything.  */
2903d8817e4Smiod   if (*failedp)
2913d8817e4Smiod     return;
2923d8817e4Smiod 
2933d8817e4Smiod   if ((sec->flags & SEC_RELOC) == 0)
2943d8817e4Smiod     return;
2953d8817e4Smiod 
2963d8817e4Smiod   /* The linker backend writes the relocs out itself, and sets the
2973d8817e4Smiod      reloc_count field to zero to inhibit writing them here.  Also,
2983d8817e4Smiod      sometimes the SEC_RELOC flag gets set even when there aren't any
2993d8817e4Smiod      relocs.  */
3003d8817e4Smiod   if (sec->reloc_count == 0)
3013d8817e4Smiod     return;
3023d8817e4Smiod 
3033d8817e4Smiod   /* We can combine two relocs that refer to the same address
3043d8817e4Smiod      into R_SPARC_OLO10 if first one is R_SPARC_LO10 and the
3053d8817e4Smiod      latter is R_SPARC_13 with no associated symbol.  */
3063d8817e4Smiod   count = 0;
3073d8817e4Smiod   for (idx = 0; idx < sec->reloc_count; idx++)
3083d8817e4Smiod     {
3093d8817e4Smiod       bfd_vma addr;
3103d8817e4Smiod 
3113d8817e4Smiod       ++count;
3123d8817e4Smiod 
3133d8817e4Smiod       addr = sec->orelocation[idx]->address;
3143d8817e4Smiod       if (sec->orelocation[idx]->howto->type == R_SPARC_LO10
3153d8817e4Smiod 	  && idx < sec->reloc_count - 1)
3163d8817e4Smiod 	{
3173d8817e4Smiod 	  arelent *r = sec->orelocation[idx + 1];
3183d8817e4Smiod 
3193d8817e4Smiod 	  if (r->howto->type == R_SPARC_13
3203d8817e4Smiod 	      && r->address == addr
3213d8817e4Smiod 	      && bfd_is_abs_section ((*r->sym_ptr_ptr)->section)
3223d8817e4Smiod 	      && (*r->sym_ptr_ptr)->value == 0)
3233d8817e4Smiod 	    ++idx;
3243d8817e4Smiod 	}
3253d8817e4Smiod     }
3263d8817e4Smiod 
3273d8817e4Smiod   rela_hdr = &elf_section_data (sec)->rel_hdr;
3283d8817e4Smiod 
3293d8817e4Smiod   rela_hdr->sh_size = rela_hdr->sh_entsize * count;
3303d8817e4Smiod   rela_hdr->contents = (PTR) bfd_alloc (abfd, rela_hdr->sh_size);
3313d8817e4Smiod   if (rela_hdr->contents == NULL)
3323d8817e4Smiod     {
3333d8817e4Smiod       *failedp = TRUE;
3343d8817e4Smiod       return;
3353d8817e4Smiod     }
3363d8817e4Smiod 
3373d8817e4Smiod   /* Figure out whether the relocations are RELA or REL relocations.  */
3383d8817e4Smiod   if (rela_hdr->sh_type != SHT_RELA)
3393d8817e4Smiod     abort ();
3403d8817e4Smiod 
3413d8817e4Smiod   /* The address of an ELF reloc is section relative for an object
3423d8817e4Smiod      file, and absolute for an executable file or shared library.
3433d8817e4Smiod      The address of a BFD reloc is always section relative.  */
3443d8817e4Smiod   addr_offset = 0;
3453d8817e4Smiod   if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0)
3463d8817e4Smiod     addr_offset = sec->vma;
3473d8817e4Smiod 
3483d8817e4Smiod   /* orelocation has the data, reloc_count has the count...  */
3493d8817e4Smiod   outbound_relocas = (Elf64_External_Rela *) rela_hdr->contents;
3503d8817e4Smiod   src_rela = outbound_relocas;
3513d8817e4Smiod 
3523d8817e4Smiod   for (idx = 0; idx < sec->reloc_count; idx++)
3533d8817e4Smiod     {
3543d8817e4Smiod       Elf_Internal_Rela dst_rela;
3553d8817e4Smiod       arelent *ptr;
3563d8817e4Smiod       asymbol *sym;
3573d8817e4Smiod       int n;
3583d8817e4Smiod 
3593d8817e4Smiod       ptr = sec->orelocation[idx];
3603d8817e4Smiod       sym = *ptr->sym_ptr_ptr;
3613d8817e4Smiod       if (sym == last_sym)
3623d8817e4Smiod 	n = last_sym_idx;
3633d8817e4Smiod       else if (bfd_is_abs_section (sym->section) && sym->value == 0)
3643d8817e4Smiod 	n = STN_UNDEF;
3653d8817e4Smiod       else
3663d8817e4Smiod 	{
3673d8817e4Smiod 	  last_sym = sym;
3683d8817e4Smiod 	  n = _bfd_elf_symbol_from_bfd_symbol (abfd, &sym);
3693d8817e4Smiod 	  if (n < 0)
3703d8817e4Smiod 	    {
3713d8817e4Smiod 	      *failedp = TRUE;
3723d8817e4Smiod 	      return;
3733d8817e4Smiod 	    }
3743d8817e4Smiod 	  last_sym_idx = n;
3753d8817e4Smiod 	}
3763d8817e4Smiod 
3773d8817e4Smiod       if ((*ptr->sym_ptr_ptr)->the_bfd != NULL
3783d8817e4Smiod 	  && (*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec
3793d8817e4Smiod 	  && ! _bfd_elf_validate_reloc (abfd, ptr))
3803d8817e4Smiod 	{
3813d8817e4Smiod 	  *failedp = TRUE;
3823d8817e4Smiod 	  return;
3833d8817e4Smiod 	}
3843d8817e4Smiod 
3853d8817e4Smiod       if (ptr->howto->type == R_SPARC_LO10
3863d8817e4Smiod 	  && idx < sec->reloc_count - 1)
3873d8817e4Smiod 	{
3883d8817e4Smiod 	  arelent *r = sec->orelocation[idx + 1];
3893d8817e4Smiod 
3903d8817e4Smiod 	  if (r->howto->type == R_SPARC_13
3913d8817e4Smiod 	      && r->address == ptr->address
3923d8817e4Smiod 	      && bfd_is_abs_section ((*r->sym_ptr_ptr)->section)
3933d8817e4Smiod 	      && (*r->sym_ptr_ptr)->value == 0)
3943d8817e4Smiod 	    {
3953d8817e4Smiod 	      idx++;
3963d8817e4Smiod 	      dst_rela.r_info
3973d8817e4Smiod 		= ELF64_R_INFO (n, ELF64_R_TYPE_INFO (r->addend,
3983d8817e4Smiod 						      R_SPARC_OLO10));
3993d8817e4Smiod 	    }
4003d8817e4Smiod 	  else
4013d8817e4Smiod 	    dst_rela.r_info = ELF64_R_INFO (n, R_SPARC_LO10);
4023d8817e4Smiod 	}
4033d8817e4Smiod       else
4043d8817e4Smiod 	dst_rela.r_info = ELF64_R_INFO (n, ptr->howto->type);
4053d8817e4Smiod 
4063d8817e4Smiod       dst_rela.r_offset = ptr->address + addr_offset;
4073d8817e4Smiod       dst_rela.r_addend = ptr->addend;
4083d8817e4Smiod 
4093d8817e4Smiod       bfd_elf64_swap_reloca_out (abfd, &dst_rela, (bfd_byte *) src_rela);
4103d8817e4Smiod       ++src_rela;
4113d8817e4Smiod     }
4123d8817e4Smiod }
4133d8817e4Smiod 
4143d8817e4Smiod /* Hook called by the linker routine which adds symbols from an object
4153d8817e4Smiod    file.  We use it for STT_REGISTER symbols.  */
4163d8817e4Smiod 
4173d8817e4Smiod static bfd_boolean
elf64_sparc_add_symbol_hook(bfd * abfd,struct bfd_link_info * info,Elf_Internal_Sym * sym,const char ** namep,flagword * flagsp ATTRIBUTE_UNUSED,asection ** secp ATTRIBUTE_UNUSED,bfd_vma * valp ATTRIBUTE_UNUSED)4183d8817e4Smiod elf64_sparc_add_symbol_hook (bfd *abfd, struct bfd_link_info *info,
4193d8817e4Smiod 			     Elf_Internal_Sym *sym, const char **namep,
4203d8817e4Smiod 			     flagword *flagsp ATTRIBUTE_UNUSED,
4213d8817e4Smiod 			     asection **secp ATTRIBUTE_UNUSED,
4223d8817e4Smiod 			     bfd_vma *valp ATTRIBUTE_UNUSED)
4233d8817e4Smiod {
4243d8817e4Smiod   static const char *const stt_types[] = { "NOTYPE", "OBJECT", "FUNCTION" };
4253d8817e4Smiod 
4263d8817e4Smiod   if (ELF_ST_TYPE (sym->st_info) == STT_REGISTER)
4273d8817e4Smiod     {
4283d8817e4Smiod       int reg;
4293d8817e4Smiod       struct _bfd_sparc_elf_app_reg *p;
4303d8817e4Smiod 
4313d8817e4Smiod       reg = (int)sym->st_value;
4323d8817e4Smiod       switch (reg & ~1)
4333d8817e4Smiod 	{
4343d8817e4Smiod 	case 2: reg -= 2; break;
4353d8817e4Smiod 	case 6: reg -= 4; break;
4363d8817e4Smiod 	default:
4373d8817e4Smiod           (*_bfd_error_handler)
4383d8817e4Smiod             (_("%B: Only registers %%g[2367] can be declared using STT_REGISTER"),
4393d8817e4Smiod              abfd);
4403d8817e4Smiod 	  return FALSE;
4413d8817e4Smiod 	}
4423d8817e4Smiod 
4433d8817e4Smiod       if (info->hash->creator != abfd->xvec
4443d8817e4Smiod 	  || (abfd->flags & DYNAMIC) != 0)
4453d8817e4Smiod         {
4463d8817e4Smiod 	  /* STT_REGISTER only works when linking an elf64_sparc object.
4473d8817e4Smiod 	     If STT_REGISTER comes from a dynamic object, don't put it into
4483d8817e4Smiod 	     the output bfd.  The dynamic linker will recheck it.  */
4493d8817e4Smiod 	  *namep = NULL;
4503d8817e4Smiod 	  return TRUE;
4513d8817e4Smiod         }
4523d8817e4Smiod 
4533d8817e4Smiod       p = _bfd_sparc_elf_hash_table(info)->app_regs + reg;
4543d8817e4Smiod 
4553d8817e4Smiod       if (p->name != NULL && strcmp (p->name, *namep))
4563d8817e4Smiod 	{
4573d8817e4Smiod           (*_bfd_error_handler)
4583d8817e4Smiod             (_("Register %%g%d used incompatibly: %s in %B, previously %s in %B"),
4593d8817e4Smiod              abfd, p->abfd, (int) sym->st_value,
4603d8817e4Smiod              **namep ? *namep : "#scratch",
4613d8817e4Smiod              *p->name ? p->name : "#scratch");
4623d8817e4Smiod 	  return FALSE;
4633d8817e4Smiod 	}
4643d8817e4Smiod 
4653d8817e4Smiod       if (p->name == NULL)
4663d8817e4Smiod 	{
4673d8817e4Smiod 	  if (**namep)
4683d8817e4Smiod 	    {
4693d8817e4Smiod 	      struct elf_link_hash_entry *h;
4703d8817e4Smiod 
4713d8817e4Smiod 	      h = (struct elf_link_hash_entry *)
4723d8817e4Smiod 		bfd_link_hash_lookup (info->hash, *namep, FALSE, FALSE, FALSE);
4733d8817e4Smiod 
4743d8817e4Smiod 	      if (h != NULL)
4753d8817e4Smiod 		{
4763d8817e4Smiod 		  unsigned char type = h->type;
4773d8817e4Smiod 
4783d8817e4Smiod 		  if (type > STT_FUNC)
4793d8817e4Smiod 		    type = 0;
4803d8817e4Smiod 		  (*_bfd_error_handler)
4813d8817e4Smiod 		    (_("Symbol `%s' has differing types: REGISTER in %B, previously %s in %B"),
4823d8817e4Smiod 		     abfd, p->abfd, *namep, stt_types[type]);
4833d8817e4Smiod 		  return FALSE;
4843d8817e4Smiod 		}
4853d8817e4Smiod 
4863d8817e4Smiod 	      p->name = bfd_hash_allocate (&info->hash->table,
4873d8817e4Smiod 					   strlen (*namep) + 1);
4883d8817e4Smiod 	      if (!p->name)
4893d8817e4Smiod 		return FALSE;
4903d8817e4Smiod 
4913d8817e4Smiod 	      strcpy (p->name, *namep);
4923d8817e4Smiod 	    }
4933d8817e4Smiod 	  else
4943d8817e4Smiod 	    p->name = "";
4953d8817e4Smiod 	  p->bind = ELF_ST_BIND (sym->st_info);
4963d8817e4Smiod 	  p->abfd = abfd;
4973d8817e4Smiod 	  p->shndx = sym->st_shndx;
4983d8817e4Smiod 	}
4993d8817e4Smiod       else
5003d8817e4Smiod 	{
5013d8817e4Smiod 	  if (p->bind == STB_WEAK
5023d8817e4Smiod 	      && ELF_ST_BIND (sym->st_info) == STB_GLOBAL)
5033d8817e4Smiod 	    {
5043d8817e4Smiod 	      p->bind = STB_GLOBAL;
5053d8817e4Smiod 	      p->abfd = abfd;
5063d8817e4Smiod 	    }
5073d8817e4Smiod 	}
5083d8817e4Smiod       *namep = NULL;
5093d8817e4Smiod       return TRUE;
5103d8817e4Smiod     }
5113d8817e4Smiod   else if (*namep && **namep
5123d8817e4Smiod 	   && info->hash->creator == abfd->xvec)
5133d8817e4Smiod     {
5143d8817e4Smiod       int i;
5153d8817e4Smiod       struct _bfd_sparc_elf_app_reg *p;
5163d8817e4Smiod 
5173d8817e4Smiod       p = _bfd_sparc_elf_hash_table(info)->app_regs;
5183d8817e4Smiod       for (i = 0; i < 4; i++, p++)
5193d8817e4Smiod 	if (p->name != NULL && ! strcmp (p->name, *namep))
5203d8817e4Smiod 	  {
5213d8817e4Smiod 	    unsigned char type = ELF_ST_TYPE (sym->st_info);
5223d8817e4Smiod 
5233d8817e4Smiod 	    if (type > STT_FUNC)
5243d8817e4Smiod 	      type = 0;
5253d8817e4Smiod 	    (*_bfd_error_handler)
5263d8817e4Smiod 	      (_("Symbol `%s' has differing types: %s in %B, previously REGISTER in %B"),
5273d8817e4Smiod 	       abfd, p->abfd, *namep, stt_types[type]);
5283d8817e4Smiod 	    return FALSE;
5293d8817e4Smiod 	  }
5303d8817e4Smiod     }
5313d8817e4Smiod   return TRUE;
5323d8817e4Smiod }
5333d8817e4Smiod 
5343d8817e4Smiod /* This function takes care of emitting STT_REGISTER symbols
5353d8817e4Smiod    which we cannot easily keep in the symbol hash table.  */
5363d8817e4Smiod 
5373d8817e4Smiod static bfd_boolean
elf64_sparc_output_arch_syms(bfd * output_bfd ATTRIBUTE_UNUSED,struct bfd_link_info * info,PTR finfo,bfd_boolean (* func)(PTR,const char *,Elf_Internal_Sym *,asection *,struct elf_link_hash_entry *))5383d8817e4Smiod elf64_sparc_output_arch_syms (bfd *output_bfd ATTRIBUTE_UNUSED,
5393d8817e4Smiod 			      struct bfd_link_info *info,
5403d8817e4Smiod 			      PTR finfo, bfd_boolean (*func) (PTR, const char *,
5413d8817e4Smiod 							      Elf_Internal_Sym *,
5423d8817e4Smiod 							      asection *,
5433d8817e4Smiod 							      struct elf_link_hash_entry *))
5443d8817e4Smiod {
5453d8817e4Smiod   int reg;
5463d8817e4Smiod   struct _bfd_sparc_elf_app_reg *app_regs =
5473d8817e4Smiod     _bfd_sparc_elf_hash_table(info)->app_regs;
5483d8817e4Smiod   Elf_Internal_Sym sym;
5493d8817e4Smiod 
5503d8817e4Smiod   /* We arranged in size_dynamic_sections to put the STT_REGISTER entries
5513d8817e4Smiod      at the end of the dynlocal list, so they came at the end of the local
5523d8817e4Smiod      symbols in the symtab.  Except that they aren't STB_LOCAL, so we need
5533d8817e4Smiod      to back up symtab->sh_info.  */
5543d8817e4Smiod   if (elf_hash_table (info)->dynlocal)
5553d8817e4Smiod     {
5563d8817e4Smiod       bfd * dynobj = elf_hash_table (info)->dynobj;
5573d8817e4Smiod       asection *dynsymsec = bfd_get_section_by_name (dynobj, ".dynsym");
5583d8817e4Smiod       struct elf_link_local_dynamic_entry *e;
5593d8817e4Smiod 
5603d8817e4Smiod       for (e = elf_hash_table (info)->dynlocal; e ; e = e->next)
5613d8817e4Smiod 	if (e->input_indx == -1)
5623d8817e4Smiod 	  break;
5633d8817e4Smiod       if (e)
5643d8817e4Smiod 	{
5653d8817e4Smiod 	  elf_section_data (dynsymsec->output_section)->this_hdr.sh_info
5663d8817e4Smiod 	    = e->dynindx;
5673d8817e4Smiod 	}
5683d8817e4Smiod     }
5693d8817e4Smiod 
5703d8817e4Smiod   if (info->strip == strip_all)
5713d8817e4Smiod     return TRUE;
5723d8817e4Smiod 
5733d8817e4Smiod   for (reg = 0; reg < 4; reg++)
5743d8817e4Smiod     if (app_regs [reg].name != NULL)
5753d8817e4Smiod       {
5763d8817e4Smiod 	if (info->strip == strip_some
5773d8817e4Smiod 	    && bfd_hash_lookup (info->keep_hash,
5783d8817e4Smiod 				app_regs [reg].name,
5793d8817e4Smiod 				FALSE, FALSE) == NULL)
5803d8817e4Smiod 	  continue;
5813d8817e4Smiod 
5823d8817e4Smiod 	sym.st_value = reg < 2 ? reg + 2 : reg + 4;
5833d8817e4Smiod 	sym.st_size = 0;
5843d8817e4Smiod 	sym.st_other = 0;
5853d8817e4Smiod 	sym.st_info = ELF_ST_INFO (app_regs [reg].bind, STT_REGISTER);
5863d8817e4Smiod 	sym.st_shndx = app_regs [reg].shndx;
5873d8817e4Smiod 	if (! (*func) (finfo, app_regs [reg].name, &sym,
5883d8817e4Smiod 		       sym.st_shndx == SHN_ABS
5893d8817e4Smiod 			 ? bfd_abs_section_ptr : bfd_und_section_ptr,
5903d8817e4Smiod 		       NULL))
5913d8817e4Smiod 	  return FALSE;
5923d8817e4Smiod       }
5933d8817e4Smiod 
5943d8817e4Smiod   return TRUE;
5953d8817e4Smiod }
5963d8817e4Smiod 
5973d8817e4Smiod static int
elf64_sparc_get_symbol_type(Elf_Internal_Sym * elf_sym,int type)5983d8817e4Smiod elf64_sparc_get_symbol_type (Elf_Internal_Sym *elf_sym, int type)
5993d8817e4Smiod {
6003d8817e4Smiod   if (ELF_ST_TYPE (elf_sym->st_info) == STT_REGISTER)
6013d8817e4Smiod     return STT_REGISTER;
6023d8817e4Smiod   else
6033d8817e4Smiod     return type;
6043d8817e4Smiod }
6053d8817e4Smiod 
6063d8817e4Smiod /* A STB_GLOBAL,STT_REGISTER symbol should be BSF_GLOBAL
6073d8817e4Smiod    even in SHN_UNDEF section.  */
6083d8817e4Smiod 
6093d8817e4Smiod static void
elf64_sparc_symbol_processing(bfd * abfd ATTRIBUTE_UNUSED,asymbol * asym)6103d8817e4Smiod elf64_sparc_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED, asymbol *asym)
6113d8817e4Smiod {
6123d8817e4Smiod   elf_symbol_type *elfsym;
6133d8817e4Smiod 
6143d8817e4Smiod   elfsym = (elf_symbol_type *) asym;
6153d8817e4Smiod   if (elfsym->internal_elf_sym.st_info
6163d8817e4Smiod       == ELF_ST_INFO (STB_GLOBAL, STT_REGISTER))
6173d8817e4Smiod     {
6183d8817e4Smiod       asym->flags |= BSF_GLOBAL;
6193d8817e4Smiod     }
6203d8817e4Smiod }
6213d8817e4Smiod 
6223d8817e4Smiod 
6233d8817e4Smiod /* Functions for dealing with the e_flags field.  */
6243d8817e4Smiod 
6253d8817e4Smiod /* Merge backend specific data from an object file to the output
6263d8817e4Smiod    object file when linking.  */
6273d8817e4Smiod 
6283d8817e4Smiod static bfd_boolean
elf64_sparc_merge_private_bfd_data(bfd * ibfd,bfd * obfd)6293d8817e4Smiod elf64_sparc_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
6303d8817e4Smiod {
6313d8817e4Smiod   bfd_boolean error;
6323d8817e4Smiod   flagword new_flags, old_flags;
6333d8817e4Smiod   int new_mm, old_mm;
6343d8817e4Smiod 
6353d8817e4Smiod   if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
6363d8817e4Smiod       || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
6373d8817e4Smiod     return TRUE;
6383d8817e4Smiod 
6393d8817e4Smiod   new_flags = elf_elfheader (ibfd)->e_flags;
6403d8817e4Smiod   old_flags = elf_elfheader (obfd)->e_flags;
6413d8817e4Smiod 
6423d8817e4Smiod   if (!elf_flags_init (obfd))   /* First call, no flags set */
6433d8817e4Smiod     {
6443d8817e4Smiod       elf_flags_init (obfd) = TRUE;
6453d8817e4Smiod       elf_elfheader (obfd)->e_flags = new_flags;
6463d8817e4Smiod     }
6473d8817e4Smiod 
6483d8817e4Smiod   else if (new_flags == old_flags)      /* Compatible flags are ok */
6493d8817e4Smiod     ;
6503d8817e4Smiod 
6513d8817e4Smiod   else                                  /* Incompatible flags */
6523d8817e4Smiod     {
6533d8817e4Smiod       error = FALSE;
6543d8817e4Smiod 
6553d8817e4Smiod #define EF_SPARC_ISA_EXTENSIONS \
6563d8817e4Smiod   (EF_SPARC_SUN_US1 | EF_SPARC_SUN_US3 | EF_SPARC_HAL_R1)
6573d8817e4Smiod 
6583d8817e4Smiod       if ((ibfd->flags & DYNAMIC) != 0)
6593d8817e4Smiod 	{
6603d8817e4Smiod 	  /* We don't want dynamic objects memory ordering and
6613d8817e4Smiod 	     architecture to have any role. That's what dynamic linker
6623d8817e4Smiod 	     should do.  */
6633d8817e4Smiod 	  new_flags &= ~(EF_SPARCV9_MM | EF_SPARC_ISA_EXTENSIONS);
6643d8817e4Smiod 	  new_flags |= (old_flags
6653d8817e4Smiod 			& (EF_SPARCV9_MM | EF_SPARC_ISA_EXTENSIONS));
6663d8817e4Smiod 	}
6673d8817e4Smiod       else
6683d8817e4Smiod 	{
6693d8817e4Smiod 	  /* Choose the highest architecture requirements.  */
6703d8817e4Smiod 	  old_flags |= (new_flags & EF_SPARC_ISA_EXTENSIONS);
6713d8817e4Smiod 	  new_flags |= (old_flags & EF_SPARC_ISA_EXTENSIONS);
6723d8817e4Smiod 	  if ((old_flags & (EF_SPARC_SUN_US1 | EF_SPARC_SUN_US3))
6733d8817e4Smiod 	      && (old_flags & EF_SPARC_HAL_R1))
6743d8817e4Smiod 	    {
6753d8817e4Smiod 	      error = TRUE;
6763d8817e4Smiod 	      (*_bfd_error_handler)
6773d8817e4Smiod 		(_("%B: linking UltraSPARC specific with HAL specific code"),
6783d8817e4Smiod 		 ibfd);
6793d8817e4Smiod 	    }
6803d8817e4Smiod 	  /* Choose the most restrictive memory ordering.  */
6813d8817e4Smiod 	  old_mm = (old_flags & EF_SPARCV9_MM);
6823d8817e4Smiod 	  new_mm = (new_flags & EF_SPARCV9_MM);
6833d8817e4Smiod 	  old_flags &= ~EF_SPARCV9_MM;
6843d8817e4Smiod 	  new_flags &= ~EF_SPARCV9_MM;
6853d8817e4Smiod 	  if (new_mm < old_mm)
6863d8817e4Smiod 	    old_mm = new_mm;
6873d8817e4Smiod 	  old_flags |= old_mm;
6883d8817e4Smiod 	  new_flags |= old_mm;
6893d8817e4Smiod 	}
6903d8817e4Smiod 
6913d8817e4Smiod       /* Warn about any other mismatches */
6923d8817e4Smiod       if (new_flags != old_flags)
6933d8817e4Smiod         {
6943d8817e4Smiod           error = TRUE;
6953d8817e4Smiod           (*_bfd_error_handler)
6963d8817e4Smiod             (_("%B: uses different e_flags (0x%lx) fields than previous modules (0x%lx)"),
6973d8817e4Smiod              ibfd, (long) new_flags, (long) old_flags);
6983d8817e4Smiod         }
6993d8817e4Smiod 
7003d8817e4Smiod       elf_elfheader (obfd)->e_flags = old_flags;
7013d8817e4Smiod 
7023d8817e4Smiod       if (error)
7033d8817e4Smiod         {
7043d8817e4Smiod           bfd_set_error (bfd_error_bad_value);
7053d8817e4Smiod           return FALSE;
7063d8817e4Smiod         }
7073d8817e4Smiod     }
7083d8817e4Smiod   return TRUE;
7093d8817e4Smiod }
7103d8817e4Smiod 
7113d8817e4Smiod /* MARCO: Set the correct entry size for the .stab section.  */
7123d8817e4Smiod 
7133d8817e4Smiod static bfd_boolean
elf64_sparc_fake_sections(bfd * abfd ATTRIBUTE_UNUSED,Elf_Internal_Shdr * hdr ATTRIBUTE_UNUSED,asection * sec)7143d8817e4Smiod elf64_sparc_fake_sections (bfd *abfd ATTRIBUTE_UNUSED,
7153d8817e4Smiod 			   Elf_Internal_Shdr *hdr ATTRIBUTE_UNUSED,
7163d8817e4Smiod 			   asection *sec)
7173d8817e4Smiod {
7183d8817e4Smiod   const char *name;
7193d8817e4Smiod 
7203d8817e4Smiod   name = bfd_get_section_name (abfd, sec);
7213d8817e4Smiod 
7223d8817e4Smiod   if (strcmp (name, ".stab") == 0)
7233d8817e4Smiod     {
7243d8817e4Smiod       /* Even in the 64bit case the stab entries are only 12 bytes long.  */
7253d8817e4Smiod       elf_section_data (sec)->this_hdr.sh_entsize = 12;
7263d8817e4Smiod     }
7273d8817e4Smiod 
7283d8817e4Smiod   return TRUE;
7293d8817e4Smiod }
7303d8817e4Smiod 
7313d8817e4Smiod /* Print a STT_REGISTER symbol to file FILE.  */
7323d8817e4Smiod 
7333d8817e4Smiod static const char *
elf64_sparc_print_symbol_all(bfd * abfd ATTRIBUTE_UNUSED,PTR filep,asymbol * symbol)7343d8817e4Smiod elf64_sparc_print_symbol_all (bfd *abfd ATTRIBUTE_UNUSED, PTR filep,
7353d8817e4Smiod 			      asymbol *symbol)
7363d8817e4Smiod {
7373d8817e4Smiod   FILE *file = (FILE *) filep;
7383d8817e4Smiod   int reg, type;
7393d8817e4Smiod 
7403d8817e4Smiod   if (ELF_ST_TYPE (((elf_symbol_type *) symbol)->internal_elf_sym.st_info)
7413d8817e4Smiod       != STT_REGISTER)
7423d8817e4Smiod     return NULL;
7433d8817e4Smiod 
7443d8817e4Smiod   reg = ((elf_symbol_type *) symbol)->internal_elf_sym.st_value;
7453d8817e4Smiod   type = symbol->flags;
7463d8817e4Smiod   fprintf (file, "REG_%c%c%11s%c%c    R", "GOLI" [reg / 8], '0' + (reg & 7), "",
7473d8817e4Smiod 		 ((type & BSF_LOCAL)
7483d8817e4Smiod 		  ? (type & BSF_GLOBAL) ? '!' : 'l'
7493d8817e4Smiod 	          : (type & BSF_GLOBAL) ? 'g' : ' '),
7503d8817e4Smiod 	         (type & BSF_WEAK) ? 'w' : ' ');
7513d8817e4Smiod   if (symbol->name == NULL || symbol->name [0] == '\0')
7523d8817e4Smiod     return "#scratch";
7533d8817e4Smiod   else
7543d8817e4Smiod     return symbol->name;
7553d8817e4Smiod }
7563d8817e4Smiod 
7573d8817e4Smiod static enum elf_reloc_type_class
elf64_sparc_reloc_type_class(const Elf_Internal_Rela * rela)7583d8817e4Smiod elf64_sparc_reloc_type_class (const Elf_Internal_Rela *rela)
7593d8817e4Smiod {
7603d8817e4Smiod   switch ((int) ELF64_R_TYPE (rela->r_info))
7613d8817e4Smiod     {
7623d8817e4Smiod     case R_SPARC_RELATIVE:
7633d8817e4Smiod       return reloc_class_relative;
7643d8817e4Smiod     case R_SPARC_JMP_SLOT:
7653d8817e4Smiod       return reloc_class_plt;
7663d8817e4Smiod     case R_SPARC_COPY:
7673d8817e4Smiod       return reloc_class_copy;
7683d8817e4Smiod     default:
7693d8817e4Smiod       return reloc_class_normal;
7703d8817e4Smiod     }
7713d8817e4Smiod }
7723d8817e4Smiod 
7733d8817e4Smiod /* Relocations in the 64 bit SPARC ELF ABI are more complex than in
7743d8817e4Smiod    standard ELF, because R_SPARC_OLO10 has secondary addend in
7753d8817e4Smiod    ELF64_R_TYPE_DATA field.  This structure is used to redirect the
7763d8817e4Smiod    relocation handling routines.  */
7773d8817e4Smiod 
7783d8817e4Smiod const struct elf_size_info elf64_sparc_size_info =
7793d8817e4Smiod {
7803d8817e4Smiod   sizeof (Elf64_External_Ehdr),
7813d8817e4Smiod   sizeof (Elf64_External_Phdr),
7823d8817e4Smiod   sizeof (Elf64_External_Shdr),
7833d8817e4Smiod   sizeof (Elf64_External_Rel),
7843d8817e4Smiod   sizeof (Elf64_External_Rela),
7853d8817e4Smiod   sizeof (Elf64_External_Sym),
7863d8817e4Smiod   sizeof (Elf64_External_Dyn),
7873d8817e4Smiod   sizeof (Elf_External_Note),
7883d8817e4Smiod   4,		/* hash-table entry size.  */
7893d8817e4Smiod   /* Internal relocations per external relocations.
7903d8817e4Smiod      For link purposes we use just 1 internal per
7913d8817e4Smiod      1 external, for assembly and slurp symbol table
7923d8817e4Smiod      we use 2.  */
7933d8817e4Smiod   1,
7943d8817e4Smiod   64,		/* arch_size.  */
7953d8817e4Smiod   3,		/* log_file_align.  */
7963d8817e4Smiod   ELFCLASS64,
7973d8817e4Smiod   EV_CURRENT,
7983d8817e4Smiod   bfd_elf64_write_out_phdrs,
7993d8817e4Smiod   bfd_elf64_write_shdrs_and_ehdr,
8003d8817e4Smiod   elf64_sparc_write_relocs,
8013d8817e4Smiod   bfd_elf64_swap_symbol_in,
8023d8817e4Smiod   bfd_elf64_swap_symbol_out,
8033d8817e4Smiod   elf64_sparc_slurp_reloc_table,
8043d8817e4Smiod   bfd_elf64_slurp_symbol_table,
8053d8817e4Smiod   bfd_elf64_swap_dyn_in,
8063d8817e4Smiod   bfd_elf64_swap_dyn_out,
8073d8817e4Smiod   bfd_elf64_swap_reloc_in,
8083d8817e4Smiod   bfd_elf64_swap_reloc_out,
8093d8817e4Smiod   bfd_elf64_swap_reloca_in,
8103d8817e4Smiod   bfd_elf64_swap_reloca_out
8113d8817e4Smiod };
8123d8817e4Smiod 
8133d8817e4Smiod #define TARGET_BIG_SYM	bfd_elf64_sparc_vec
8143d8817e4Smiod #define TARGET_BIG_NAME	"elf64-sparc"
8153d8817e4Smiod #define ELF_ARCH	bfd_arch_sparc
8163d8817e4Smiod #define ELF_MAXPAGESIZE 0x100000
8173d8817e4Smiod 
8183d8817e4Smiod /* This is the official ABI value.  */
8193d8817e4Smiod #define ELF_MACHINE_CODE EM_SPARCV9
8203d8817e4Smiod 
8213d8817e4Smiod /* This is the value that we used before the ABI was released.  */
8223d8817e4Smiod #define ELF_MACHINE_ALT1 EM_OLD_SPARCV9
8233d8817e4Smiod 
8243d8817e4Smiod #define elf_backend_reloc_type_class \
8253d8817e4Smiod   elf64_sparc_reloc_type_class
8263d8817e4Smiod #define bfd_elf64_get_reloc_upper_bound \
8273d8817e4Smiod   elf64_sparc_get_reloc_upper_bound
8283d8817e4Smiod #define bfd_elf64_get_dynamic_reloc_upper_bound \
8293d8817e4Smiod   elf64_sparc_get_dynamic_reloc_upper_bound
8303d8817e4Smiod #define bfd_elf64_canonicalize_reloc \
8313d8817e4Smiod   elf64_sparc_canonicalize_reloc
8323d8817e4Smiod #define bfd_elf64_canonicalize_dynamic_reloc \
8333d8817e4Smiod   elf64_sparc_canonicalize_dynamic_reloc
8343d8817e4Smiod #define elf_backend_add_symbol_hook \
8353d8817e4Smiod   elf64_sparc_add_symbol_hook
8363d8817e4Smiod #define elf_backend_get_symbol_type \
8373d8817e4Smiod   elf64_sparc_get_symbol_type
8383d8817e4Smiod #define elf_backend_symbol_processing \
8393d8817e4Smiod   elf64_sparc_symbol_processing
8403d8817e4Smiod #define elf_backend_print_symbol_all \
8413d8817e4Smiod   elf64_sparc_print_symbol_all
8423d8817e4Smiod #define elf_backend_output_arch_syms \
8433d8817e4Smiod   elf64_sparc_output_arch_syms
8443d8817e4Smiod #define bfd_elf64_bfd_merge_private_bfd_data \
8453d8817e4Smiod   elf64_sparc_merge_private_bfd_data
8463d8817e4Smiod #define elf_backend_fake_sections \
8473d8817e4Smiod   elf64_sparc_fake_sections
8483d8817e4Smiod #define elf_backend_size_info \
8493d8817e4Smiod   elf64_sparc_size_info
8503d8817e4Smiod 
8513d8817e4Smiod #define elf_backend_plt_sym_val	\
8523d8817e4Smiod   _bfd_sparc_elf_plt_sym_val
8533d8817e4Smiod #define bfd_elf64_bfd_link_hash_table_create \
8543d8817e4Smiod   _bfd_sparc_elf_link_hash_table_create
8553d8817e4Smiod #define elf_info_to_howto \
8563d8817e4Smiod   _bfd_sparc_elf_info_to_howto
8573d8817e4Smiod #define elf_backend_copy_indirect_symbol \
8583d8817e4Smiod   _bfd_sparc_elf_copy_indirect_symbol
8593d8817e4Smiod #define bfd_elf64_bfd_reloc_type_lookup \
8603d8817e4Smiod   _bfd_sparc_elf_reloc_type_lookup
8613d8817e4Smiod #define bfd_elf64_bfd_relax_section \
8623d8817e4Smiod   _bfd_sparc_elf_relax_section
8633d8817e4Smiod #define bfd_elf64_new_section_hook \
8643d8817e4Smiod   _bfd_sparc_elf_new_section_hook
8653d8817e4Smiod 
8663d8817e4Smiod #define elf_backend_create_dynamic_sections \
8673d8817e4Smiod   _bfd_sparc_elf_create_dynamic_sections
8683d8817e4Smiod #define elf_backend_check_relocs \
8693d8817e4Smiod   _bfd_sparc_elf_check_relocs
8703d8817e4Smiod #define elf_backend_adjust_dynamic_symbol \
8713d8817e4Smiod   _bfd_sparc_elf_adjust_dynamic_symbol
8723d8817e4Smiod #define elf_backend_omit_section_dynsym \
8733d8817e4Smiod   _bfd_sparc_elf_omit_section_dynsym
8743d8817e4Smiod #define elf_backend_size_dynamic_sections \
8753d8817e4Smiod   _bfd_sparc_elf_size_dynamic_sections
8763d8817e4Smiod #define elf_backend_relocate_section \
8773d8817e4Smiod   _bfd_sparc_elf_relocate_section
8783d8817e4Smiod #define elf_backend_finish_dynamic_symbol \
8793d8817e4Smiod   _bfd_sparc_elf_finish_dynamic_symbol
8803d8817e4Smiod #define elf_backend_finish_dynamic_sections \
8813d8817e4Smiod   _bfd_sparc_elf_finish_dynamic_sections
8823d8817e4Smiod 
8833d8817e4Smiod #define bfd_elf64_mkobject \
8843d8817e4Smiod   _bfd_sparc_elf_mkobject
8853d8817e4Smiod #define elf_backend_object_p \
8863d8817e4Smiod   _bfd_sparc_elf_object_p
8873d8817e4Smiod #define elf_backend_gc_mark_hook \
8883d8817e4Smiod   _bfd_sparc_elf_gc_mark_hook
8893d8817e4Smiod #define elf_backend_gc_sweep_hook \
8903d8817e4Smiod   _bfd_sparc_elf_gc_sweep_hook
8913d8817e4Smiod 
8923d8817e4Smiod #define elf_backend_can_gc_sections 1
8933d8817e4Smiod #define elf_backend_can_refcount 1
8943d8817e4Smiod #define elf_backend_want_got_plt 0
895*4f14f31bSkettenis #define elf_backend_plt_readonly 0
8963d8817e4Smiod #define elf_backend_want_plt_sym 1
8973d8817e4Smiod #define elf_backend_got_header_size 8
8983d8817e4Smiod #define elf_backend_rela_normal 1
8993d8817e4Smiod 
9003d8817e4Smiod /* Section 5.2.4 of the ABI specifies a 256-byte boundary for the table.  */
9013d8817e4Smiod #define elf_backend_plt_alignment 8
9023d8817e4Smiod 
9033d8817e4Smiod #include "elf64-target.h"
904