elf32-sparc.c revision 77298
159024Sobrien/* SPARC-specific support for 32-bit ELF
260484Sobrien   Copyright (C) 1993, 94, 95, 96, 97, 98, 99, 2000
360484Sobrien   Free Software Foundation, Inc.
459024Sobrien
559024SobrienThis file is part of BFD, the Binary File Descriptor library.
659024Sobrien
759024SobrienThis program is free software; you can redistribute it and/or modify
859024Sobrienit under the terms of the GNU General Public License as published by
959024Sobrienthe Free Software Foundation; either version 2 of the License, or
1059024Sobrien(at your option) any later version.
1159024Sobrien
1259024SobrienThis program is distributed in the hope that it will be useful,
1359024Sobrienbut WITHOUT ANY WARRANTY; without even the implied warranty of
1459024SobrienMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1559024SobrienGNU General Public License for more details.
1659024Sobrien
1759024SobrienYou should have received a copy of the GNU General Public License
1859024Sobrienalong with this program; if not, write to the Free Software
1959024SobrienFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
2059024Sobrien
2159024Sobrien#include "bfd.h"
2259024Sobrien#include "sysdep.h"
2359024Sobrien#include "bfdlink.h"
2459024Sobrien#include "libbfd.h"
2559024Sobrien#include "elf-bfd.h"
2659024Sobrien#include "elf/sparc.h"
2777298Sobrien#include "opcode/sparc.h"
2859024Sobrien
2959024Sobrienstatic reloc_howto_type *elf32_sparc_reloc_type_lookup
3059024Sobrien  PARAMS ((bfd *, bfd_reloc_code_real_type));
3159024Sobrienstatic void elf32_sparc_info_to_howto
3259024Sobrien  PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
3359024Sobrienstatic boolean elf32_sparc_check_relocs
3459024Sobrien  PARAMS ((bfd *, struct bfd_link_info *, asection *,
3559024Sobrien	   const Elf_Internal_Rela *));
3659024Sobrienstatic boolean elf32_sparc_adjust_dynamic_symbol
3759024Sobrien  PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
3859024Sobrienstatic boolean elf32_sparc_size_dynamic_sections
3959024Sobrien  PARAMS ((bfd *, struct bfd_link_info *));
4077298Sobrienstatic boolean elf32_sparc_relax_section
4177298Sobrien  PARAMS ((bfd *, asection *, struct bfd_link_info *, boolean *));
4259024Sobrienstatic boolean elf32_sparc_relocate_section
4359024Sobrien  PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
4459024Sobrien	   Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
4559024Sobrienstatic boolean elf32_sparc_finish_dynamic_symbol
4659024Sobrien  PARAMS ((bfd *, struct bfd_link_info *, struct elf_link_hash_entry *,
4759024Sobrien	   Elf_Internal_Sym *));
4859024Sobrienstatic boolean elf32_sparc_finish_dynamic_sections
4959024Sobrien  PARAMS ((bfd *, struct bfd_link_info *));
5059024Sobrienstatic boolean elf32_sparc_merge_private_bfd_data PARAMS ((bfd *, bfd *));
5159024Sobrienstatic boolean elf32_sparc_object_p
5259024Sobrien  PARAMS ((bfd *));
5359024Sobrienstatic void elf32_sparc_final_write_processing
5459024Sobrien  PARAMS ((bfd *, boolean));
5559024Sobrien
5659024Sobrien/* The relocation "howto" table.  */
5759024Sobrien
5859024Sobrienstatic bfd_reloc_status_type sparc_elf_notsupported_reloc
5959024Sobrien  PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
6059024Sobrienstatic bfd_reloc_status_type sparc_elf_wdisp16_reloc
6159024Sobrien  PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
6259024Sobrien
6359024Sobrienreloc_howto_type _bfd_sparc_elf_howto_table[] =
6459024Sobrien{
6559024Sobrien  HOWTO(R_SPARC_NONE,      0,0, 0,false,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_NONE",    false,0,0x00000000,true),
6659024Sobrien  HOWTO(R_SPARC_8,         0,0, 8,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_8",       false,0,0x000000ff,true),
6759024Sobrien  HOWTO(R_SPARC_16,        0,1,16,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_16",      false,0,0x0000ffff,true),
6859024Sobrien  HOWTO(R_SPARC_32,        0,2,32,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_32",      false,0,0xffffffff,true),
6959024Sobrien  HOWTO(R_SPARC_DISP8,     0,0, 8,true, 0,complain_overflow_signed,  bfd_elf_generic_reloc,  "R_SPARC_DISP8",   false,0,0x000000ff,true),
7059024Sobrien  HOWTO(R_SPARC_DISP16,    0,1,16,true, 0,complain_overflow_signed,  bfd_elf_generic_reloc,  "R_SPARC_DISP16",  false,0,0x0000ffff,true),
7159024Sobrien  HOWTO(R_SPARC_DISP32,    0,2,32,true, 0,complain_overflow_signed,  bfd_elf_generic_reloc,  "R_SPARC_DISP32",  false,0,0x00ffffff,true),
7259024Sobrien  HOWTO(R_SPARC_WDISP30,   2,2,30,true, 0,complain_overflow_signed,  bfd_elf_generic_reloc,  "R_SPARC_WDISP30", false,0,0x3fffffff,true),
7359024Sobrien  HOWTO(R_SPARC_WDISP22,   2,2,22,true, 0,complain_overflow_signed,  bfd_elf_generic_reloc,  "R_SPARC_WDISP22", false,0,0x003fffff,true),
7459024Sobrien  HOWTO(R_SPARC_HI22,     10,2,22,false,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_HI22",    false,0,0x003fffff,true),
7559024Sobrien  HOWTO(R_SPARC_22,        0,2,22,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_22",      false,0,0x003fffff,true),
7659024Sobrien  HOWTO(R_SPARC_13,        0,2,13,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_13",      false,0,0x00001fff,true),
7759024Sobrien  HOWTO(R_SPARC_LO10,      0,2,10,false,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_LO10",    false,0,0x000003ff,true),
7859024Sobrien  HOWTO(R_SPARC_GOT10,     0,2,10,false,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_GOT10",   false,0,0x000003ff,true),
7959024Sobrien  HOWTO(R_SPARC_GOT13,     0,2,13,false,0,complain_overflow_signed,  bfd_elf_generic_reloc,  "R_SPARC_GOT13",   false,0,0x00001fff,true),
8059024Sobrien  HOWTO(R_SPARC_GOT22,    10,2,22,false,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_GOT22",   false,0,0x003fffff,true),
8159024Sobrien  HOWTO(R_SPARC_PC10,      0,2,10,true, 0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_PC10",    false,0,0x000003ff,true),
8259024Sobrien  HOWTO(R_SPARC_PC22,     10,2,22,true, 0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_PC22",    false,0,0x003fffff,true),
8359024Sobrien  HOWTO(R_SPARC_WPLT30,    2,2,30,true, 0,complain_overflow_signed,  bfd_elf_generic_reloc,  "R_SPARC_WPLT30",  false,0,0x3fffffff,true),
8459024Sobrien  HOWTO(R_SPARC_COPY,      0,0,00,false,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_COPY",    false,0,0x00000000,true),
8559024Sobrien  HOWTO(R_SPARC_GLOB_DAT,  0,0,00,false,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_GLOB_DAT",false,0,0x00000000,true),
8659024Sobrien  HOWTO(R_SPARC_JMP_SLOT,  0,0,00,false,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_JMP_SLOT",false,0,0x00000000,true),
8759024Sobrien  HOWTO(R_SPARC_RELATIVE,  0,0,00,false,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_RELATIVE",false,0,0x00000000,true),
8859024Sobrien  HOWTO(R_SPARC_UA32,      0,0,00,false,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_UA32",    false,0,0x00000000,true),
8959024Sobrien  HOWTO(R_SPARC_PLT32,     0,0,00,false,0,complain_overflow_dont,    sparc_elf_notsupported_reloc,  "R_SPARC_PLT32",    false,0,0x00000000,true),
9059024Sobrien  HOWTO(R_SPARC_HIPLT22,   0,0,00,false,0,complain_overflow_dont,    sparc_elf_notsupported_reloc,  "R_SPARC_HIPLT22",  false,0,0x00000000,true),
9159024Sobrien  HOWTO(R_SPARC_LOPLT10,   0,0,00,false,0,complain_overflow_dont,    sparc_elf_notsupported_reloc,  "R_SPARC_LOPLT10",  false,0,0x00000000,true),
9259024Sobrien  HOWTO(R_SPARC_PCPLT32,   0,0,00,false,0,complain_overflow_dont,    sparc_elf_notsupported_reloc,  "R_SPARC_PCPLT32",  false,0,0x00000000,true),
9359024Sobrien  HOWTO(R_SPARC_PCPLT22,   0,0,00,false,0,complain_overflow_dont,    sparc_elf_notsupported_reloc,  "R_SPARC_PCPLT22",  false,0,0x00000000,true),
9459024Sobrien  HOWTO(R_SPARC_PCPLT10,   0,0,00,false,0,complain_overflow_dont,    sparc_elf_notsupported_reloc,  "R_SPARC_PCPLT10",  false,0,0x00000000,true),
9559024Sobrien  HOWTO(R_SPARC_10,        0,2,10,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_10",      false,0,0x000003ff,true),
9659024Sobrien  HOWTO(R_SPARC_11,        0,2,11,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_11",      false,0,0x000007ff,true),
9759024Sobrien  /* These are for sparc64 in a 64 bit environment.
9859024Sobrien     Values need to be here because the table is indexed by reloc number.  */
9959024Sobrien  HOWTO(R_SPARC_64,        0,0,00,false,0,complain_overflow_dont,    sparc_elf_notsupported_reloc,  "R_SPARC_64",      false,0,0x00000000,true),
10059024Sobrien  HOWTO(R_SPARC_OLO10,     0,0,00,false,0,complain_overflow_dont,    sparc_elf_notsupported_reloc,  "R_SPARC_OLO10",   false,0,0x00000000,true),
10159024Sobrien  HOWTO(R_SPARC_HH22,      0,0,00,false,0,complain_overflow_dont,    sparc_elf_notsupported_reloc,  "R_SPARC_HH22",    false,0,0x00000000,true),
10259024Sobrien  HOWTO(R_SPARC_HM10,      0,0,00,false,0,complain_overflow_dont,    sparc_elf_notsupported_reloc,  "R_SPARC_HM10",    false,0,0x00000000,true),
10359024Sobrien  HOWTO(R_SPARC_LM22,      0,0,00,false,0,complain_overflow_dont,    sparc_elf_notsupported_reloc,  "R_SPARC_LM22",    false,0,0x00000000,true),
10459024Sobrien  HOWTO(R_SPARC_PC_HH22,   0,0,00,false,0,complain_overflow_dont,    sparc_elf_notsupported_reloc,  "R_SPARC_PC_HH22", false,0,0x00000000,true),
10559024Sobrien  HOWTO(R_SPARC_PC_HM10,   0,0,00,false,0,complain_overflow_dont,    sparc_elf_notsupported_reloc,  "R_SPARC_PC_HM10", false,0,0x00000000,true),
10659024Sobrien  HOWTO(R_SPARC_PC_LM22,   0,0,00,false,0,complain_overflow_dont,    sparc_elf_notsupported_reloc,  "R_SPARC_PC_LM22", false,0,0x00000000,true),
10759024Sobrien  /* End sparc64 in 64 bit environment values.
10859024Sobrien     The following are for sparc64 in a 32 bit environment.  */
10959024Sobrien  HOWTO(R_SPARC_WDISP16,   2,2,16,true, 0,complain_overflow_signed,  sparc_elf_wdisp16_reloc,"R_SPARC_WDISP16", false,0,0x00000000,true),
11059024Sobrien  HOWTO(R_SPARC_WDISP19,   2,2,19,true, 0,complain_overflow_signed,  bfd_elf_generic_reloc,  "R_SPARC_WDISP19", false,0,0x0007ffff,true),
11159024Sobrien  HOWTO(R_SPARC_UNUSED_42, 0,0, 0,false,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_UNUSED_42",false,0,0x00000000,true),
11259024Sobrien  HOWTO(R_SPARC_7,         0,2, 7,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_7",       false,0,0x0000007f,true),
11359024Sobrien  HOWTO(R_SPARC_5,         0,2, 5,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_5",       false,0,0x0000001f,true),
11460484Sobrien  HOWTO(R_SPARC_6,         0,2, 6,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_6",       false,0,0x0000003f,true),
11560484Sobrien  HOWTO(R_SPARC_NONE,      0,0, 0,false,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_NONE",    false,0,0x00000000,true),
11660484Sobrien  HOWTO(R_SPARC_NONE,      0,0, 0,false,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_NONE",    false,0,0x00000000,true),
11760484Sobrien  HOWTO(R_SPARC_NONE,      0,0, 0,false,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_NONE",    false,0,0x00000000,true),
11860484Sobrien  HOWTO(R_SPARC_NONE,      0,0, 0,false,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_NONE",    false,0,0x00000000,true),
11960484Sobrien  HOWTO(R_SPARC_NONE,      0,0, 0,false,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_NONE",    false,0,0x00000000,true),
12060484Sobrien  HOWTO(R_SPARC_NONE,      0,0, 0,false,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_NONE",    false,0,0x00000000,true),
12160484Sobrien  HOWTO(R_SPARC_NONE,      0,0, 0,false,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_NONE",    false,0,0x00000000,true),
12260484Sobrien  HOWTO(R_SPARC_NONE,      0,0, 0,false,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_NONE",    false,0,0x00000000,true),
12360484Sobrien  HOWTO(R_SPARC_NONE,      0,0, 0,false,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_NONE",    false,0,0x00000000,true),
12460484Sobrien  HOWTO(R_SPARC_NONE,      0,0, 0,false,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_NONE",    false,0,0x00000000,true),
12560484Sobrien  HOWTO(R_SPARC_REV32,      0,2,32,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_REV32",      false,0,0xffffffff,true),
12659024Sobrien};
12760484Sobrienstatic reloc_howto_type elf32_sparc_vtinherit_howto =
12860484Sobrien  HOWTO (R_SPARC_GNU_VTINHERIT, 0,2,0,false,0,complain_overflow_dont, NULL, "R_SPARC_GNU_VTINHERIT", false,0, 0, false);
12960484Sobrienstatic reloc_howto_type elf32_sparc_vtentry_howto =
13060484Sobrien  HOWTO (R_SPARC_GNU_VTENTRY, 0,2,0,false,0,complain_overflow_dont, _bfd_elf_rel_vtable_reloc_fn,"R_SPARC_GNU_VTENTRY", false,0,0, false);
13159024Sobrien
13259024Sobrienstruct elf_reloc_map {
13360484Sobrien  bfd_reloc_code_real_type bfd_reloc_val;
13459024Sobrien  unsigned char elf_reloc_val;
13559024Sobrien};
13659024Sobrien
13759024Sobrienstatic CONST struct elf_reloc_map sparc_reloc_map[] =
13859024Sobrien{
13959024Sobrien  { BFD_RELOC_NONE, R_SPARC_NONE, },
14059024Sobrien  { BFD_RELOC_16, R_SPARC_16, },
14159024Sobrien  { BFD_RELOC_8, R_SPARC_8 },
14259024Sobrien  { BFD_RELOC_8_PCREL, R_SPARC_DISP8 },
14359024Sobrien  { BFD_RELOC_CTOR, R_SPARC_32 },
14459024Sobrien  { BFD_RELOC_32, R_SPARC_32 },
14559024Sobrien  { BFD_RELOC_32_PCREL, R_SPARC_DISP32 },
14659024Sobrien  { BFD_RELOC_HI22, R_SPARC_HI22 },
14759024Sobrien  { BFD_RELOC_LO10, R_SPARC_LO10, },
14859024Sobrien  { BFD_RELOC_32_PCREL_S2, R_SPARC_WDISP30 },
14959024Sobrien  { BFD_RELOC_SPARC22, R_SPARC_22 },
15059024Sobrien  { BFD_RELOC_SPARC13, R_SPARC_13 },
15159024Sobrien  { BFD_RELOC_SPARC_GOT10, R_SPARC_GOT10 },
15259024Sobrien  { BFD_RELOC_SPARC_GOT13, R_SPARC_GOT13 },
15359024Sobrien  { BFD_RELOC_SPARC_GOT22, R_SPARC_GOT22 },
15459024Sobrien  { BFD_RELOC_SPARC_PC10, R_SPARC_PC10 },
15559024Sobrien  { BFD_RELOC_SPARC_PC22, R_SPARC_PC22 },
15659024Sobrien  { BFD_RELOC_SPARC_WPLT30, R_SPARC_WPLT30 },
15759024Sobrien  { BFD_RELOC_SPARC_COPY, R_SPARC_COPY },
15859024Sobrien  { BFD_RELOC_SPARC_GLOB_DAT, R_SPARC_GLOB_DAT },
15959024Sobrien  { BFD_RELOC_SPARC_JMP_SLOT, R_SPARC_JMP_SLOT },
16059024Sobrien  { BFD_RELOC_SPARC_RELATIVE, R_SPARC_RELATIVE },
16159024Sobrien  { BFD_RELOC_SPARC_WDISP22, R_SPARC_WDISP22 },
16259024Sobrien  /* ??? Doesn't dwarf use this?  */
16359024Sobrien/*{ BFD_RELOC_SPARC_UA32, R_SPARC_UA32 }, not used?? */
16459024Sobrien  {BFD_RELOC_SPARC_10, R_SPARC_10},
16559024Sobrien  {BFD_RELOC_SPARC_11, R_SPARC_11},
16659024Sobrien  {BFD_RELOC_SPARC_64, R_SPARC_64},
16759024Sobrien  {BFD_RELOC_SPARC_OLO10, R_SPARC_OLO10},
16859024Sobrien  {BFD_RELOC_SPARC_HH22, R_SPARC_HH22},
16959024Sobrien  {BFD_RELOC_SPARC_HM10, R_SPARC_HM10},
17059024Sobrien  {BFD_RELOC_SPARC_LM22, R_SPARC_LM22},
17159024Sobrien  {BFD_RELOC_SPARC_PC_HH22, R_SPARC_PC_HH22},
17259024Sobrien  {BFD_RELOC_SPARC_PC_HM10, R_SPARC_PC_HM10},
17359024Sobrien  {BFD_RELOC_SPARC_PC_LM22, R_SPARC_PC_LM22},
17459024Sobrien  {BFD_RELOC_SPARC_WDISP16, R_SPARC_WDISP16},
17559024Sobrien  {BFD_RELOC_SPARC_WDISP19, R_SPARC_WDISP19},
17659024Sobrien  {BFD_RELOC_SPARC_7, R_SPARC_7},
17759024Sobrien  {BFD_RELOC_SPARC_5, R_SPARC_5},
17860484Sobrien  {BFD_RELOC_SPARC_6, R_SPARC_6},
17960484Sobrien  {BFD_RELOC_SPARC_REV32, R_SPARC_REV32 },
18060484Sobrien  {BFD_RELOC_VTABLE_INHERIT, R_SPARC_GNU_VTINHERIT},
18160484Sobrien  {BFD_RELOC_VTABLE_ENTRY, R_SPARC_GNU_VTENTRY},
18259024Sobrien};
18359024Sobrien
18459024Sobrienstatic reloc_howto_type *
18559024Sobrienelf32_sparc_reloc_type_lookup (abfd, code)
18660484Sobrien     bfd *abfd ATTRIBUTE_UNUSED;
18759024Sobrien     bfd_reloc_code_real_type code;
18859024Sobrien{
18959024Sobrien  unsigned int i;
19077298Sobrien
19160484Sobrien  switch (code)
19259024Sobrien    {
19360484Sobrien    case BFD_RELOC_VTABLE_INHERIT:
19460484Sobrien      return &elf32_sparc_vtinherit_howto;
19560484Sobrien
19660484Sobrien    case BFD_RELOC_VTABLE_ENTRY:
19760484Sobrien      return &elf32_sparc_vtentry_howto;
19860484Sobrien
19960484Sobrien    default:
20060484Sobrien      for (i = 0; i < sizeof (sparc_reloc_map) / sizeof (struct elf_reloc_map); i++)
20160484Sobrien        {
20260484Sobrien          if (sparc_reloc_map[i].bfd_reloc_val == code)
20360484Sobrien	    return &_bfd_sparc_elf_howto_table[(int) sparc_reloc_map[i].elf_reloc_val];
20460484Sobrien        }
20559024Sobrien    }
20660484Sobrien    bfd_set_error (bfd_error_bad_value);
20760484Sobrien    return NULL;
20859024Sobrien}
20959024Sobrien
21059024Sobrien/* We need to use ELF32_R_TYPE so we have our own copy of this function,
21159024Sobrien   and elf64-sparc.c has its own copy.  */
21259024Sobrien
21359024Sobrienstatic void
21459024Sobrienelf32_sparc_info_to_howto (abfd, cache_ptr, dst)
21560484Sobrien     bfd *abfd ATTRIBUTE_UNUSED;
21659024Sobrien     arelent *cache_ptr;
21759024Sobrien     Elf_Internal_Rela *dst;
21859024Sobrien{
21960484Sobrien  switch (ELF32_R_TYPE(dst->r_info))
22060484Sobrien    {
22160484Sobrien    case R_SPARC_GNU_VTINHERIT:
22260484Sobrien      cache_ptr->howto = &elf32_sparc_vtinherit_howto;
22360484Sobrien      break;
22460484Sobrien
22560484Sobrien    case R_SPARC_GNU_VTENTRY:
22660484Sobrien      cache_ptr->howto = &elf32_sparc_vtentry_howto;
22760484Sobrien      break;
22860484Sobrien
22960484Sobrien    default:
23060484Sobrien      BFD_ASSERT (ELF32_R_TYPE(dst->r_info) < (unsigned int) R_SPARC_max_std);
23160484Sobrien      cache_ptr->howto = &_bfd_sparc_elf_howto_table[ELF32_R_TYPE(dst->r_info)];
23260484Sobrien    }
23359024Sobrien}
23459024Sobrien
23559024Sobrien/* For unsupported relocs.  */
23659024Sobrien
23759024Sobrienstatic bfd_reloc_status_type
23859024Sobriensparc_elf_notsupported_reloc (abfd,
23959024Sobrien			     reloc_entry,
24059024Sobrien			     symbol,
24159024Sobrien			     data,
24259024Sobrien			     input_section,
24359024Sobrien			     output_bfd,
24459024Sobrien			     error_message)
24560484Sobrien     bfd *abfd ATTRIBUTE_UNUSED;
24660484Sobrien     arelent *reloc_entry ATTRIBUTE_UNUSED;
24760484Sobrien     asymbol *symbol ATTRIBUTE_UNUSED;
24860484Sobrien     PTR data ATTRIBUTE_UNUSED;
24960484Sobrien     asection *input_section ATTRIBUTE_UNUSED;
25060484Sobrien     bfd *output_bfd ATTRIBUTE_UNUSED;
25160484Sobrien     char **error_message ATTRIBUTE_UNUSED;
25259024Sobrien{
25359024Sobrien  return bfd_reloc_notsupported;
25459024Sobrien}
25559024Sobrien
25659024Sobrien/* Handle the WDISP16 reloc.  */
25759024Sobrien
25859024Sobrienstatic bfd_reloc_status_type
25959024Sobriensparc_elf_wdisp16_reloc (abfd,
26059024Sobrien			 reloc_entry,
26159024Sobrien			 symbol,
26259024Sobrien			 data,
26359024Sobrien			 input_section,
26459024Sobrien			 output_bfd,
26559024Sobrien			 error_message)
26659024Sobrien     bfd *abfd;
26759024Sobrien     arelent *reloc_entry;
26859024Sobrien     asymbol *symbol;
26959024Sobrien     PTR data;
27059024Sobrien     asection *input_section;
27159024Sobrien     bfd *output_bfd;
27260484Sobrien     char **error_message ATTRIBUTE_UNUSED;
27359024Sobrien{
27459024Sobrien  bfd_vma relocation;
27559024Sobrien  bfd_vma x;
27659024Sobrien
27759024Sobrien  if (output_bfd != (bfd *) NULL
27859024Sobrien      && (symbol->flags & BSF_SECTION_SYM) == 0
27959024Sobrien      && (! reloc_entry->howto->partial_inplace
28059024Sobrien	  || reloc_entry->addend == 0))
28159024Sobrien    {
28259024Sobrien      reloc_entry->address += input_section->output_offset;
28359024Sobrien      return bfd_reloc_ok;
28459024Sobrien    }
28559024Sobrien
28659024Sobrien  if (output_bfd != NULL)
28759024Sobrien    return bfd_reloc_continue;
28859024Sobrien
28959024Sobrien  if (reloc_entry->address > input_section->_cooked_size)
29059024Sobrien    return bfd_reloc_outofrange;
29159024Sobrien
29259024Sobrien  relocation = (symbol->value
29359024Sobrien		+ symbol->section->output_section->vma
29459024Sobrien		+ symbol->section->output_offset);
29559024Sobrien  relocation += reloc_entry->addend;
29659024Sobrien  relocation -=	(input_section->output_section->vma
29759024Sobrien		 + input_section->output_offset);
29859024Sobrien  relocation -= reloc_entry->address;
29959024Sobrien
30059024Sobrien  x = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
30159024Sobrien  x |= ((((relocation >> 2) & 0xc000) << 6)
30259024Sobrien	| ((relocation >> 2) & 0x3fff));
30359024Sobrien  bfd_put_32 (abfd, x, (bfd_byte *) data + reloc_entry->address);
30459024Sobrien
30559024Sobrien  if ((bfd_signed_vma) relocation < - 0x40000
30659024Sobrien      || (bfd_signed_vma) relocation > 0x3ffff)
30759024Sobrien    return bfd_reloc_overflow;
30859024Sobrien  else
30959024Sobrien    return bfd_reloc_ok;
31059024Sobrien}
31159024Sobrien
31259024Sobrien/* Functions for the SPARC ELF linker.  */
31359024Sobrien
31459024Sobrien/* The name of the dynamic interpreter.  This is put in the .interp
31559024Sobrien   section.  */
31659024Sobrien
31759024Sobrien#define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1"
31859024Sobrien
31959024Sobrien/* The nop opcode we use.  */
32059024Sobrien
32159024Sobrien#define SPARC_NOP 0x01000000
32259024Sobrien
32359024Sobrien/* The size in bytes of an entry in the procedure linkage table.  */
32459024Sobrien
32559024Sobrien#define PLT_ENTRY_SIZE 12
32659024Sobrien
32759024Sobrien/* The first four entries in a procedure linkage table are reserved,
32859024Sobrien   and the initial contents are unimportant (we zero them out).
32959024Sobrien   Subsequent entries look like this.  See the SVR4 ABI SPARC
33059024Sobrien   supplement to see how this works.  */
33159024Sobrien
33259024Sobrien/* sethi %hi(.-.plt0),%g1.  We fill in the address later.  */
33359024Sobrien#define PLT_ENTRY_WORD0 0x03000000
33459024Sobrien/* b,a .plt0.  We fill in the offset later.  */
33559024Sobrien#define PLT_ENTRY_WORD1 0x30800000
33659024Sobrien/* nop.  */
33759024Sobrien#define PLT_ENTRY_WORD2 SPARC_NOP
33859024Sobrien
33959024Sobrien/* Look through the relocs for a section during the first phase, and
34059024Sobrien   allocate space in the global offset table or procedure linkage
34159024Sobrien   table.  */
34259024Sobrien
34359024Sobrienstatic boolean
34459024Sobrienelf32_sparc_check_relocs (abfd, info, sec, relocs)
34559024Sobrien     bfd *abfd;
34659024Sobrien     struct bfd_link_info *info;
34759024Sobrien     asection *sec;
34859024Sobrien     const Elf_Internal_Rela *relocs;
34959024Sobrien{
35059024Sobrien  bfd *dynobj;
35159024Sobrien  Elf_Internal_Shdr *symtab_hdr;
35259024Sobrien  struct elf_link_hash_entry **sym_hashes;
35359024Sobrien  bfd_vma *local_got_offsets;
35459024Sobrien  const Elf_Internal_Rela *rel;
35559024Sobrien  const Elf_Internal_Rela *rel_end;
35659024Sobrien  asection *sgot;
35759024Sobrien  asection *srelgot;
35859024Sobrien  asection *sreloc;
35959024Sobrien
36059024Sobrien  if (info->relocateable)
36159024Sobrien    return true;
36259024Sobrien
36359024Sobrien  dynobj = elf_hash_table (info)->dynobj;
36459024Sobrien  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
36559024Sobrien  sym_hashes = elf_sym_hashes (abfd);
36659024Sobrien  local_got_offsets = elf_local_got_offsets (abfd);
36759024Sobrien
36859024Sobrien  sgot = NULL;
36959024Sobrien  srelgot = NULL;
37059024Sobrien  sreloc = NULL;
37159024Sobrien
37259024Sobrien  rel_end = relocs + sec->reloc_count;
37359024Sobrien  for (rel = relocs; rel < rel_end; rel++)
37459024Sobrien    {
37559024Sobrien      unsigned long r_symndx;
37659024Sobrien      struct elf_link_hash_entry *h;
37759024Sobrien
37859024Sobrien      r_symndx = ELF32_R_SYM (rel->r_info);
37959024Sobrien      if (r_symndx < symtab_hdr->sh_info)
38059024Sobrien	h = NULL;
38159024Sobrien      else
38259024Sobrien	h = sym_hashes[r_symndx - symtab_hdr->sh_info];
38359024Sobrien
38459024Sobrien      switch (ELF32_R_TYPE (rel->r_info))
38559024Sobrien	{
38659024Sobrien	case R_SPARC_GOT10:
38759024Sobrien	case R_SPARC_GOT13:
38859024Sobrien	case R_SPARC_GOT22:
38959024Sobrien	  /* This symbol requires a global offset table entry.  */
39059024Sobrien
39159024Sobrien	  if (dynobj == NULL)
39259024Sobrien	    {
39359024Sobrien	      /* Create the .got section.  */
39459024Sobrien	      elf_hash_table (info)->dynobj = dynobj = abfd;
39559024Sobrien	      if (! _bfd_elf_create_got_section (dynobj, info))
39659024Sobrien		return false;
39759024Sobrien	    }
39859024Sobrien
39959024Sobrien	  if (sgot == NULL)
40059024Sobrien	    {
40159024Sobrien	      sgot = bfd_get_section_by_name (dynobj, ".got");
40259024Sobrien	      BFD_ASSERT (sgot != NULL);
40359024Sobrien	    }
40459024Sobrien
40559024Sobrien	  if (srelgot == NULL
40659024Sobrien	      && (h != NULL || info->shared))
40759024Sobrien	    {
40859024Sobrien	      srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
40959024Sobrien	      if (srelgot == NULL)
41059024Sobrien		{
41159024Sobrien		  srelgot = bfd_make_section (dynobj, ".rela.got");
41259024Sobrien		  if (srelgot == NULL
41359024Sobrien		      || ! bfd_set_section_flags (dynobj, srelgot,
41459024Sobrien						  (SEC_ALLOC
41559024Sobrien						   | SEC_LOAD
41659024Sobrien						   | SEC_HAS_CONTENTS
41759024Sobrien						   | SEC_IN_MEMORY
41859024Sobrien						   | SEC_LINKER_CREATED
41959024Sobrien						   | SEC_READONLY))
42059024Sobrien		      || ! bfd_set_section_alignment (dynobj, srelgot, 2))
42159024Sobrien		    return false;
42259024Sobrien		}
42359024Sobrien	    }
42459024Sobrien
42559024Sobrien	  if (h != NULL)
42659024Sobrien	    {
42760484Sobrien	      if (h->got.offset != (bfd_vma) -1)
42859024Sobrien		{
42959024Sobrien		  /* We have already allocated space in the .got.  */
43059024Sobrien		  break;
43159024Sobrien		}
43260484Sobrien	      h->got.offset = sgot->_raw_size;
43359024Sobrien
43459024Sobrien	      /* Make sure this symbol is output as a dynamic symbol.  */
43559024Sobrien	      if (h->dynindx == -1)
43659024Sobrien		{
43759024Sobrien		  if (! bfd_elf32_link_record_dynamic_symbol (info, h))
43859024Sobrien		    return false;
43959024Sobrien		}
44059024Sobrien
44159024Sobrien	      srelgot->_raw_size += sizeof (Elf32_External_Rela);
44259024Sobrien	    }
44359024Sobrien	  else
44459024Sobrien	    {
44559024Sobrien	      /* This is a global offset table entry for a local
44659024Sobrien                 symbol.  */
44759024Sobrien	      if (local_got_offsets == NULL)
44859024Sobrien		{
44959024Sobrien		  size_t size;
45059024Sobrien		  register unsigned int i;
45159024Sobrien
45259024Sobrien		  size = symtab_hdr->sh_info * sizeof (bfd_vma);
45359024Sobrien		  local_got_offsets = (bfd_vma *) bfd_alloc (abfd, size);
45459024Sobrien		  if (local_got_offsets == NULL)
45559024Sobrien		    return false;
45659024Sobrien		  elf_local_got_offsets (abfd) = local_got_offsets;
45759024Sobrien		  for (i = 0; i < symtab_hdr->sh_info; i++)
45859024Sobrien		    local_got_offsets[i] = (bfd_vma) -1;
45959024Sobrien		}
46059024Sobrien	      if (local_got_offsets[r_symndx] != (bfd_vma) -1)
46159024Sobrien		{
46259024Sobrien		  /* We have already allocated space in the .got.  */
46359024Sobrien		  break;
46459024Sobrien		}
46559024Sobrien	      local_got_offsets[r_symndx] = sgot->_raw_size;
46659024Sobrien
46759024Sobrien	      if (info->shared)
46859024Sobrien		{
46959024Sobrien		  /* If we are generating a shared object, we need to
47059024Sobrien                     output a R_SPARC_RELATIVE reloc so that the
47159024Sobrien                     dynamic linker can adjust this GOT entry.  */
47259024Sobrien		  srelgot->_raw_size += sizeof (Elf32_External_Rela);
47359024Sobrien		}
47459024Sobrien	    }
47559024Sobrien
47659024Sobrien	  sgot->_raw_size += 4;
47759024Sobrien
47859024Sobrien	  /* If the .got section is more than 0x1000 bytes, we add
47959024Sobrien	     0x1000 to the value of _GLOBAL_OFFSET_TABLE_, so that 13
48059024Sobrien	     bit relocations have a greater chance of working.  */
48159024Sobrien	  if (sgot->_raw_size >= 0x1000
48259024Sobrien	      && elf_hash_table (info)->hgot->root.u.def.value == 0)
48359024Sobrien	    elf_hash_table (info)->hgot->root.u.def.value = 0x1000;
48459024Sobrien
48559024Sobrien	  break;
48659024Sobrien
48759024Sobrien	case R_SPARC_WPLT30:
48859024Sobrien	  /* This symbol requires a procedure linkage table entry.  We
48959024Sobrien             actually build the entry in adjust_dynamic_symbol,
49059024Sobrien             because this might be a case of linking PIC code without
49159024Sobrien             linking in any dynamic objects, in which case we don't
49259024Sobrien             need to generate a procedure linkage table after all.  */
49359024Sobrien
49459024Sobrien	  if (h == NULL)
49559024Sobrien	    {
49660484Sobrien	      /* The Solaris native assembler will generate a WPLT30
49760484Sobrien                 reloc for a local symbol if you assemble a call from
49860484Sobrien                 one section to another when using -K pic.  We treat
49960484Sobrien                 it as WDISP30.  */
50060484Sobrien	      break;
50159024Sobrien	    }
50259024Sobrien
50359024Sobrien	  /* Make sure this symbol is output as a dynamic symbol.  */
50459024Sobrien	  if (h->dynindx == -1)
50559024Sobrien	    {
50659024Sobrien	      if (! bfd_elf32_link_record_dynamic_symbol (info, h))
50759024Sobrien		return false;
50859024Sobrien	    }
50959024Sobrien
51059024Sobrien	  h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
51159024Sobrien
51259024Sobrien	  break;
51359024Sobrien
51459024Sobrien	case R_SPARC_PC10:
51559024Sobrien	case R_SPARC_PC22:
51660484Sobrien	  if (h != NULL)
51760484Sobrien	    h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF;
51860484Sobrien
51959024Sobrien	  if (h != NULL
52059024Sobrien	      && strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
52159024Sobrien	    break;
52259024Sobrien	  /* Fall through.  */
52359024Sobrien	case R_SPARC_DISP8:
52459024Sobrien	case R_SPARC_DISP16:
52559024Sobrien	case R_SPARC_DISP32:
52659024Sobrien	case R_SPARC_WDISP30:
52759024Sobrien	case R_SPARC_WDISP22:
52859024Sobrien	case R_SPARC_WDISP19:
52959024Sobrien	case R_SPARC_WDISP16:
53060484Sobrien	  if (h != NULL)
53160484Sobrien	    h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF;
53260484Sobrien
53359024Sobrien	  /* If we are linking with -Bsymbolic, we do not need to copy
53459024Sobrien             a PC relative reloc against a global symbol which is
53559024Sobrien             defined in an object we are including in the link (i.e.,
53659024Sobrien             DEF_REGULAR is set).  FIXME: At this point we have not
53759024Sobrien             seen all the input files, so it is possible that
53859024Sobrien             DEF_REGULAR is not set now but will be set later (it is
53959024Sobrien             never cleared).  This needs to be handled as in
54059024Sobrien             elf32-i386.c.  */
54159024Sobrien	  if (h == NULL
54259024Sobrien	      || (info->symbolic
54359024Sobrien		  && (h->elf_link_hash_flags
54459024Sobrien		      & ELF_LINK_HASH_DEF_REGULAR) != 0))
54559024Sobrien	    break;
54659024Sobrien	  /* Fall through.  */
54759024Sobrien	case R_SPARC_8:
54859024Sobrien	case R_SPARC_16:
54959024Sobrien	case R_SPARC_32:
55059024Sobrien	case R_SPARC_HI22:
55159024Sobrien	case R_SPARC_22:
55259024Sobrien	case R_SPARC_13:
55359024Sobrien	case R_SPARC_LO10:
55459024Sobrien	case R_SPARC_UA32:
55560484Sobrien	  if (h != NULL)
55660484Sobrien	    h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF;
55760484Sobrien
55859024Sobrien	  if (info->shared)
55959024Sobrien	    {
56059024Sobrien	      /* When creating a shared object, we must copy these
56159024Sobrien                 relocs into the output file.  We create a reloc
56259024Sobrien                 section in dynobj and make room for the reloc.  */
56359024Sobrien	      if (sreloc == NULL)
56459024Sobrien		{
56559024Sobrien		  const char *name;
56659024Sobrien
56759024Sobrien		  name = (bfd_elf_string_from_elf_section
56859024Sobrien			  (abfd,
56959024Sobrien			   elf_elfheader (abfd)->e_shstrndx,
57059024Sobrien			   elf_section_data (sec)->rel_hdr.sh_name));
57159024Sobrien		  if (name == NULL)
57259024Sobrien		    return false;
57359024Sobrien
57459024Sobrien		  BFD_ASSERT (strncmp (name, ".rela", 5) == 0
57559024Sobrien			      && strcmp (bfd_get_section_name (abfd, sec),
57659024Sobrien					 name + 5) == 0);
57759024Sobrien
57859024Sobrien		  sreloc = bfd_get_section_by_name (dynobj, name);
57959024Sobrien		  if (sreloc == NULL)
58059024Sobrien		    {
58159024Sobrien		      flagword flags;
58259024Sobrien
58359024Sobrien		      sreloc = bfd_make_section (dynobj, name);
58459024Sobrien		      flags = (SEC_HAS_CONTENTS | SEC_READONLY
58559024Sobrien			       | SEC_IN_MEMORY | SEC_LINKER_CREATED);
58659024Sobrien		      if ((sec->flags & SEC_ALLOC) != 0)
58759024Sobrien			flags |= SEC_ALLOC | SEC_LOAD;
58859024Sobrien		      if (sreloc == NULL
58959024Sobrien			  || ! bfd_set_section_flags (dynobj, sreloc, flags)
59059024Sobrien			  || ! bfd_set_section_alignment (dynobj, sreloc, 2))
59159024Sobrien			return false;
59259024Sobrien		    }
59359024Sobrien		}
59459024Sobrien
59559024Sobrien	      sreloc->_raw_size += sizeof (Elf32_External_Rela);
59659024Sobrien	    }
59759024Sobrien
59859024Sobrien	  break;
59959024Sobrien
60060484Sobrien        case R_SPARC_GNU_VTINHERIT:
60160484Sobrien          if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
60260484Sobrien            return false;
60360484Sobrien          break;
60460484Sobrien
60560484Sobrien        case R_SPARC_GNU_VTENTRY:
60660484Sobrien          if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
60760484Sobrien            return false;
60860484Sobrien          break;
60960484Sobrien
61059024Sobrien	default:
61159024Sobrien	  break;
61259024Sobrien	}
61359024Sobrien    }
61459024Sobrien
61559024Sobrien  return true;
61659024Sobrien}
61759024Sobrien
61860484Sobrienstatic asection *
61960484Sobrienelf32_sparc_gc_mark_hook (abfd, info, rel, h, sym)
62060484Sobrien       bfd *abfd;
62160484Sobrien       struct bfd_link_info *info ATTRIBUTE_UNUSED;
62260484Sobrien       Elf_Internal_Rela *rel;
62360484Sobrien       struct elf_link_hash_entry *h;
62460484Sobrien       Elf_Internal_Sym *sym;
62560484Sobrien{
62660484Sobrien
62760484Sobrien  if (h != NULL)
62860484Sobrien    {
62960484Sobrien      switch (ELF32_R_TYPE (rel->r_info))
63060484Sobrien      {
63160484Sobrien      case R_SPARC_GNU_VTINHERIT:
63260484Sobrien      case R_SPARC_GNU_VTENTRY:
63360484Sobrien        break;
63460484Sobrien
63560484Sobrien      default:
63660484Sobrien        switch (h->root.type)
63760484Sobrien          {
63860484Sobrien          case bfd_link_hash_defined:
63960484Sobrien          case bfd_link_hash_defweak:
64060484Sobrien            return h->root.u.def.section;
64160484Sobrien
64260484Sobrien          case bfd_link_hash_common:
64360484Sobrien            return h->root.u.c.p->section;
64460484Sobrien
64560484Sobrien	  default:
64660484Sobrien	    break;
64760484Sobrien          }
64860484Sobrien       }
64960484Sobrien     }
65060484Sobrien   else
65160484Sobrien     {
65260484Sobrien       if (!(elf_bad_symtab (abfd)
65360484Sobrien           && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
65460484Sobrien         && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
65560484Sobrien                && sym->st_shndx != SHN_COMMON))
65660484Sobrien          {
65760484Sobrien            return bfd_section_from_elf_index (abfd, sym->st_shndx);
65860484Sobrien          }
65960484Sobrien      }
66060484Sobrien
66160484Sobrien  return NULL;
66260484Sobrien}
66360484Sobrien
66460484Sobrien/* Update the got entry reference counts for the section being removed.  */
66560484Sobrienstatic boolean
66660484Sobrienelf32_sparc_gc_sweep_hook (abfd, info, sec, relocs)
66760484Sobrien     bfd *abfd;
66860484Sobrien     struct bfd_link_info *info ATTRIBUTE_UNUSED;
66960484Sobrien     asection *sec;
67060484Sobrien     const Elf_Internal_Rela *relocs;
67160484Sobrien{
67260484Sobrien
67360484Sobrien  Elf_Internal_Shdr *symtab_hdr;
67460484Sobrien  struct elf_link_hash_entry **sym_hashes;
67560484Sobrien  bfd_signed_vma *local_got_refcounts;
67660484Sobrien  const Elf_Internal_Rela *rel, *relend;
67760484Sobrien  unsigned long r_symndx;
67860484Sobrien  struct elf_link_hash_entry *h;
67960484Sobrien
68060484Sobrien  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
68160484Sobrien  sym_hashes = elf_sym_hashes (abfd);
68260484Sobrien  local_got_refcounts = elf_local_got_refcounts (abfd);
68360484Sobrien
68460484Sobrien  relend = relocs + sec->reloc_count;
68560484Sobrien  for (rel = relocs; rel < relend; rel++)
68660484Sobrien    switch (ELF32_R_TYPE (rel->r_info))
68760484Sobrien      {
68860484Sobrien      case R_SPARC_GOT10:
68960484Sobrien      case R_SPARC_GOT13:
69060484Sobrien      case R_SPARC_GOT22:
69160484Sobrien	r_symndx = ELF32_R_SYM (rel->r_info);
69260484Sobrien	if (r_symndx >= symtab_hdr->sh_info)
69360484Sobrien	  {
69460484Sobrien	    h = sym_hashes[r_symndx - symtab_hdr->sh_info];
69560484Sobrien	    if (h->got.refcount > 0)
69660484Sobrien	      h->got.refcount--;
69760484Sobrien	  }
69860484Sobrien	else
69960484Sobrien	  {
70060484Sobrien	    if (local_got_refcounts[r_symndx] > 0)
70160484Sobrien	      local_got_refcounts[r_symndx]--;
70260484Sobrien	  }
70360484Sobrien        break;
70460484Sobrien
70560484Sobrien      case R_SPARC_PLT32:
70660484Sobrien      case R_SPARC_HIPLT22:
70760484Sobrien      case R_SPARC_LOPLT10:
70860484Sobrien      case R_SPARC_PCPLT32:
70960484Sobrien      case R_SPARC_PCPLT10:
71060484Sobrien	r_symndx = ELF32_R_SYM (rel->r_info);
71160484Sobrien	if (r_symndx >= symtab_hdr->sh_info)
71260484Sobrien	  {
71360484Sobrien	    h = sym_hashes[r_symndx - symtab_hdr->sh_info];
71460484Sobrien	    if (h->plt.refcount > 0)
71560484Sobrien	      h->plt.refcount--;
71660484Sobrien	  }
71760484Sobrien	break;
71860484Sobrien
71960484Sobrien      default:
72060484Sobrien	break;
72160484Sobrien      }
72260484Sobrien
72360484Sobrien  return true;
72460484Sobrien}
72560484Sobrien
72659024Sobrien/* Adjust a symbol defined by a dynamic object and referenced by a
72759024Sobrien   regular object.  The current definition is in some section of the
72859024Sobrien   dynamic object, but we're not including those sections.  We have to
72959024Sobrien   change the definition to something the rest of the link can
73059024Sobrien   understand.  */
73159024Sobrien
73259024Sobrienstatic boolean
73359024Sobrienelf32_sparc_adjust_dynamic_symbol (info, h)
73459024Sobrien     struct bfd_link_info *info;
73559024Sobrien     struct elf_link_hash_entry *h;
73659024Sobrien{
73759024Sobrien  bfd *dynobj;
73859024Sobrien  asection *s;
73959024Sobrien  unsigned int power_of_two;
74059024Sobrien
74159024Sobrien  dynobj = elf_hash_table (info)->dynobj;
74259024Sobrien
74359024Sobrien  /* Make sure we know what is going on here.  */
74459024Sobrien  BFD_ASSERT (dynobj != NULL
74559024Sobrien	      && ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT)
74659024Sobrien		  || h->weakdef != NULL
74759024Sobrien		  || ((h->elf_link_hash_flags
74859024Sobrien		       & ELF_LINK_HASH_DEF_DYNAMIC) != 0
74959024Sobrien		      && (h->elf_link_hash_flags
75059024Sobrien			  & ELF_LINK_HASH_REF_REGULAR) != 0
75159024Sobrien		      && (h->elf_link_hash_flags
75259024Sobrien			  & ELF_LINK_HASH_DEF_REGULAR) == 0)));
75359024Sobrien
75459024Sobrien  /* If this is a function, put it in the procedure linkage table.  We
75559024Sobrien     will fill in the contents of the procedure linkage table later
75659024Sobrien     (although we could actually do it here).  The STT_NOTYPE
75759024Sobrien     condition is a hack specifically for the Oracle libraries
75859024Sobrien     delivered for Solaris; for some inexplicable reason, they define
75959024Sobrien     some of their functions as STT_NOTYPE when they really should be
76059024Sobrien     STT_FUNC.  */
76159024Sobrien  if (h->type == STT_FUNC
76259024Sobrien      || (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0
76359024Sobrien      || (h->type == STT_NOTYPE
76459024Sobrien	  && (h->root.type == bfd_link_hash_defined
76559024Sobrien	      || h->root.type == bfd_link_hash_defweak)
76659024Sobrien	  && (h->root.u.def.section->flags & SEC_CODE) != 0))
76759024Sobrien    {
76859024Sobrien      if (! elf_hash_table (info)->dynamic_sections_created
76959024Sobrien	  || ((!info->shared || info->symbolic || h->dynindx == -1)
77059024Sobrien	      && (h->elf_link_hash_flags
77159024Sobrien		  & ELF_LINK_HASH_DEF_REGULAR) != 0))
77259024Sobrien	{
77359024Sobrien	  /* This case can occur if we saw a WPLT30 reloc in an input
77459024Sobrien	     file, but none of the input files were dynamic objects.
77559024Sobrien	     Or, when linking the main application or a -Bsymbolic
77659024Sobrien	     shared library against PIC code.  Or when a global symbol
77759024Sobrien	     has been made private, e.g. via versioning.
77859024Sobrien
77959024Sobrien	     In these cases we know what value the symbol will resolve
78059024Sobrien	     to, so we don't actually need to build a procedure linkage
78159024Sobrien	     table, and we can just do a WDISP30 reloc instead.  */
78259024Sobrien
78359024Sobrien	  h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
78459024Sobrien	  return true;
78559024Sobrien	}
78659024Sobrien
78759024Sobrien      s = bfd_get_section_by_name (dynobj, ".plt");
78859024Sobrien      BFD_ASSERT (s != NULL);
78959024Sobrien
79059024Sobrien      /* The first four entries in .plt are reserved.  */
79159024Sobrien      if (s->_raw_size == 0)
79259024Sobrien	s->_raw_size = 4 * PLT_ENTRY_SIZE;
79359024Sobrien
79459024Sobrien      /* The procedure linkage table has a maximum size.  */
79559024Sobrien      if (s->_raw_size >= 0x400000)
79659024Sobrien	{
79759024Sobrien	  bfd_set_error (bfd_error_bad_value);
79859024Sobrien	  return false;
79959024Sobrien	}
80059024Sobrien
80159024Sobrien     /* If this symbol is not defined in a regular file, and we are
80259024Sobrien       not generating a shared library, then set the symbol to this
80359024Sobrien       location in the .plt.  This is required to make function
80459024Sobrien       pointers compare as equal between the normal executable and
80559024Sobrien       the shared library.  */
80659024Sobrien     if (! info->shared
80759024Sobrien	&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
80859024Sobrien      {
80959024Sobrien	h->root.u.def.section = s;
81059024Sobrien	h->root.u.def.value = s->_raw_size;
81159024Sobrien      }
81259024Sobrien
81360484Sobrien      h->plt.offset = s->_raw_size;
81459024Sobrien
81559024Sobrien      /* Make room for this entry.  */
81659024Sobrien      s->_raw_size += PLT_ENTRY_SIZE;
81759024Sobrien
81859024Sobrien      /* We also need to make an entry in the .rela.plt section.  */
81959024Sobrien
82059024Sobrien      s = bfd_get_section_by_name (dynobj, ".rela.plt");
82159024Sobrien      BFD_ASSERT (s != NULL);
82259024Sobrien      s->_raw_size += sizeof (Elf32_External_Rela);
82359024Sobrien
82459024Sobrien      return true;
82559024Sobrien    }
82659024Sobrien
82759024Sobrien  /* If this is a weak symbol, and there is a real definition, the
82859024Sobrien     processor independent code will have arranged for us to see the
82959024Sobrien     real definition first, and we can just use the same value.  */
83059024Sobrien  if (h->weakdef != NULL)
83159024Sobrien    {
83259024Sobrien      BFD_ASSERT (h->weakdef->root.type == bfd_link_hash_defined
83359024Sobrien		  || h->weakdef->root.type == bfd_link_hash_defweak);
83459024Sobrien      h->root.u.def.section = h->weakdef->root.u.def.section;
83559024Sobrien      h->root.u.def.value = h->weakdef->root.u.def.value;
83659024Sobrien      return true;
83759024Sobrien    }
83859024Sobrien
83959024Sobrien  /* This is a reference to a symbol defined by a dynamic object which
84059024Sobrien     is not a function.  */
84159024Sobrien
84259024Sobrien  /* If we are creating a shared library, we must presume that the
84359024Sobrien     only references to the symbol are via the global offset table.
84459024Sobrien     For such cases we need not do anything here; the relocations will
84559024Sobrien     be handled correctly by relocate_section.  */
84659024Sobrien  if (info->shared)
84759024Sobrien    return true;
84859024Sobrien
84960484Sobrien  /* If there are no references to this symbol that do not use the
85060484Sobrien     GOT, we don't need to generate a copy reloc.  */
85160484Sobrien  if ((h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0)
85260484Sobrien    return true;
85360484Sobrien
85459024Sobrien  /* We must allocate the symbol in our .dynbss section, which will
85559024Sobrien     become part of the .bss section of the executable.  There will be
85659024Sobrien     an entry for this symbol in the .dynsym section.  The dynamic
85759024Sobrien     object will contain position independent code, so all references
85859024Sobrien     from the dynamic object to this symbol will go through the global
85959024Sobrien     offset table.  The dynamic linker will use the .dynsym entry to
86059024Sobrien     determine the address it must put in the global offset table, so
86159024Sobrien     both the dynamic object and the regular object will refer to the
86259024Sobrien     same memory location for the variable.  */
86359024Sobrien
86459024Sobrien  s = bfd_get_section_by_name (dynobj, ".dynbss");
86559024Sobrien  BFD_ASSERT (s != NULL);
86659024Sobrien
86759024Sobrien  /* We must generate a R_SPARC_COPY reloc to tell the dynamic linker
86859024Sobrien     to copy the initial value out of the dynamic object and into the
86959024Sobrien     runtime process image.  We need to remember the offset into the
87059024Sobrien     .rel.bss section we are going to use.  */
87159024Sobrien  if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
87259024Sobrien    {
87359024Sobrien      asection *srel;
87459024Sobrien
87559024Sobrien      srel = bfd_get_section_by_name (dynobj, ".rela.bss");
87659024Sobrien      BFD_ASSERT (srel != NULL);
87759024Sobrien      srel->_raw_size += sizeof (Elf32_External_Rela);
87859024Sobrien      h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_COPY;
87959024Sobrien    }
88059024Sobrien
88159024Sobrien  /* We need to figure out the alignment required for this symbol.  I
88259024Sobrien     have no idea how ELF linkers handle this.  */
88359024Sobrien  power_of_two = bfd_log2 (h->size);
88459024Sobrien  if (power_of_two > 3)
88559024Sobrien    power_of_two = 3;
88659024Sobrien
88759024Sobrien  /* Apply the required alignment.  */
88859024Sobrien  s->_raw_size = BFD_ALIGN (s->_raw_size,
88959024Sobrien			    (bfd_size_type) (1 << power_of_two));
89059024Sobrien  if (power_of_two > bfd_get_section_alignment (dynobj, s))
89159024Sobrien    {
89259024Sobrien      if (! bfd_set_section_alignment (dynobj, s, power_of_two))
89359024Sobrien	return false;
89459024Sobrien    }
89559024Sobrien
89659024Sobrien  /* Define the symbol as being at this point in the section.  */
89759024Sobrien  h->root.u.def.section = s;
89859024Sobrien  h->root.u.def.value = s->_raw_size;
89959024Sobrien
90059024Sobrien  /* Increment the section size to make room for the symbol.  */
90159024Sobrien  s->_raw_size += h->size;
90259024Sobrien
90359024Sobrien  return true;
90459024Sobrien}
90559024Sobrien
90659024Sobrien/* Set the sizes of the dynamic sections.  */
90759024Sobrien
90859024Sobrienstatic boolean
90959024Sobrienelf32_sparc_size_dynamic_sections (output_bfd, info)
91059024Sobrien     bfd *output_bfd;
91159024Sobrien     struct bfd_link_info *info;
91259024Sobrien{
91359024Sobrien  bfd *dynobj;
91459024Sobrien  asection *s;
91559024Sobrien  boolean reltext;
91659024Sobrien  boolean relplt;
91759024Sobrien
91859024Sobrien  dynobj = elf_hash_table (info)->dynobj;
91959024Sobrien  BFD_ASSERT (dynobj != NULL);
92059024Sobrien
92159024Sobrien  if (elf_hash_table (info)->dynamic_sections_created)
92259024Sobrien    {
92359024Sobrien      /* Set the contents of the .interp section to the interpreter.  */
92459024Sobrien      if (! info->shared)
92559024Sobrien	{
92659024Sobrien	  s = bfd_get_section_by_name (dynobj, ".interp");
92759024Sobrien	  BFD_ASSERT (s != NULL);
92859024Sobrien	  s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER;
92959024Sobrien	  s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
93059024Sobrien	}
93159024Sobrien
93259024Sobrien      /* Make space for the trailing nop in .plt.  */
93359024Sobrien      s = bfd_get_section_by_name (dynobj, ".plt");
93459024Sobrien      BFD_ASSERT (s != NULL);
93559024Sobrien      if (s->_raw_size > 0)
93659024Sobrien	s->_raw_size += 4;
93759024Sobrien    }
93859024Sobrien  else
93959024Sobrien    {
94059024Sobrien      /* We may have created entries in the .rela.got section.
94159024Sobrien         However, if we are not creating the dynamic sections, we will
94259024Sobrien         not actually use these entries.  Reset the size of .rela.got,
94359024Sobrien         which will cause it to get stripped from the output file
94459024Sobrien         below.  */
94559024Sobrien      s = bfd_get_section_by_name (dynobj, ".rela.got");
94659024Sobrien      if (s != NULL)
94759024Sobrien	s->_raw_size = 0;
94859024Sobrien    }
94959024Sobrien
95059024Sobrien  /* The check_relocs and adjust_dynamic_symbol entry points have
95159024Sobrien     determined the sizes of the various dynamic sections.  Allocate
95259024Sobrien     memory for them.  */
95359024Sobrien  reltext = false;
95459024Sobrien  relplt = false;
95559024Sobrien  for (s = dynobj->sections; s != NULL; s = s->next)
95659024Sobrien    {
95759024Sobrien      const char *name;
95859024Sobrien      boolean strip;
95959024Sobrien
96059024Sobrien      if ((s->flags & SEC_LINKER_CREATED) == 0)
96159024Sobrien	continue;
96259024Sobrien
96359024Sobrien      /* It's OK to base decisions on the section name, because none
96459024Sobrien	 of the dynobj section names depend upon the input files.  */
96559024Sobrien      name = bfd_get_section_name (dynobj, s);
96659024Sobrien
96759024Sobrien      strip = false;
96859024Sobrien
96959024Sobrien      if (strncmp (name, ".rela", 5) == 0)
97059024Sobrien	{
97159024Sobrien	  if (s->_raw_size == 0)
97259024Sobrien	    {
97359024Sobrien	      /* If we don't need this section, strip it from the
97459024Sobrien		 output file.  This is to handle .rela.bss and
97559024Sobrien		 .rel.plt.  We must create it in
97659024Sobrien		 create_dynamic_sections, because it must be created
97759024Sobrien		 before the linker maps input sections to output
97859024Sobrien		 sections.  The linker does that before
97959024Sobrien		 adjust_dynamic_symbol is called, and it is that
98059024Sobrien		 function which decides whether anything needs to go
98159024Sobrien		 into these sections.  */
98259024Sobrien	      strip = true;
98359024Sobrien	    }
98459024Sobrien	  else
98559024Sobrien	    {
98659024Sobrien	      const char *outname;
98759024Sobrien	      asection *target;
98859024Sobrien
98959024Sobrien	      /* If this relocation section applies to a read only
99059024Sobrien		 section, then we probably need a DT_TEXTREL entry.  */
99159024Sobrien	      outname = bfd_get_section_name (output_bfd,
99259024Sobrien					      s->output_section);
99359024Sobrien	      target = bfd_get_section_by_name (output_bfd, outname + 5);
99459024Sobrien	      if (target != NULL
99559024Sobrien		  && (target->flags & SEC_READONLY) != 0
99659024Sobrien		  && (target->flags & SEC_ALLOC) != 0)
99759024Sobrien		reltext = true;
99859024Sobrien
99959024Sobrien	      if (strcmp (name, ".rela.plt") == 0)
100059024Sobrien		relplt = true;
100159024Sobrien
100259024Sobrien	      /* We use the reloc_count field as a counter if we need
100359024Sobrien		 to copy relocs into the output file.  */
100459024Sobrien	      s->reloc_count = 0;
100559024Sobrien	    }
100659024Sobrien	}
100759024Sobrien      else if (strcmp (name, ".plt") != 0
100859024Sobrien	       && strcmp (name, ".got") != 0)
100959024Sobrien	{
101059024Sobrien	  /* It's not one of our sections, so don't allocate space.  */
101159024Sobrien	  continue;
101259024Sobrien	}
101359024Sobrien
101459024Sobrien      if (strip)
101559024Sobrien	{
101660484Sobrien	  _bfd_strip_section_from_output (info, s);
101759024Sobrien	  continue;
101859024Sobrien	}
101959024Sobrien
102059024Sobrien      /* Allocate memory for the section contents.  */
102177298Sobrien      /* FIXME: This should be a call to bfd_alloc not bfd_zalloc.
102277298Sobrien	 Unused entries should be reclaimed before the section's contents
102377298Sobrien	 are written out, but at the moment this does not happen.  Thus in
102477298Sobrien	 order to prevent writing out garbage, we initialise the section's
102577298Sobrien	 contents to zero.  */
102677298Sobrien      s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size);
102759024Sobrien      if (s->contents == NULL && s->_raw_size != 0)
102859024Sobrien	return false;
102959024Sobrien    }
103059024Sobrien
103159024Sobrien  if (elf_hash_table (info)->dynamic_sections_created)
103259024Sobrien    {
103359024Sobrien      /* Add some entries to the .dynamic section.  We fill in the
103459024Sobrien	 values later, in elf32_sparc_finish_dynamic_sections, but we
103559024Sobrien	 must add the entries now so that we get the correct size for
103659024Sobrien	 the .dynamic section.  The DT_DEBUG entry is filled in by the
103759024Sobrien	 dynamic linker and used by the debugger.  */
103859024Sobrien      if (! info->shared)
103959024Sobrien	{
104059024Sobrien	  if (! bfd_elf32_add_dynamic_entry (info, DT_DEBUG, 0))
104159024Sobrien	    return false;
104259024Sobrien	}
104359024Sobrien
104459024Sobrien      if (relplt)
104559024Sobrien	{
104659024Sobrien	  if (! bfd_elf32_add_dynamic_entry (info, DT_PLTGOT, 0)
104759024Sobrien	      || ! bfd_elf32_add_dynamic_entry (info, DT_PLTRELSZ, 0)
104859024Sobrien	      || ! bfd_elf32_add_dynamic_entry (info, DT_PLTREL, DT_RELA)
104959024Sobrien	      || ! bfd_elf32_add_dynamic_entry (info, DT_JMPREL, 0))
105059024Sobrien	    return false;
105159024Sobrien	}
105259024Sobrien
105359024Sobrien      if (! bfd_elf32_add_dynamic_entry (info, DT_RELA, 0)
105459024Sobrien	  || ! bfd_elf32_add_dynamic_entry (info, DT_RELASZ, 0)
105559024Sobrien	  || ! bfd_elf32_add_dynamic_entry (info, DT_RELAENT,
105659024Sobrien					    sizeof (Elf32_External_Rela)))
105759024Sobrien	return false;
105859024Sobrien
105959024Sobrien      if (reltext)
106059024Sobrien	{
106159024Sobrien	  if (! bfd_elf32_add_dynamic_entry (info, DT_TEXTREL, 0))
106259024Sobrien	    return false;
106377298Sobrien	  info->flags |= DF_TEXTREL;
106459024Sobrien	}
106559024Sobrien    }
106659024Sobrien
106759024Sobrien  return true;
106859024Sobrien}
106959024Sobrien
107077298Sobrien#define SET_SEC_DO_RELAX(section) do { elf_section_data(section)->tdata = (void *)1; } while (0)
107177298Sobrien#define SEC_DO_RELAX(section) (elf_section_data(section)->tdata == (void *)1)
107277298Sobrien
107377298Sobrienstatic boolean
107477298Sobrienelf32_sparc_relax_section (abfd, section, link_info, again)
107577298Sobrien     bfd *abfd ATTRIBUTE_UNUSED;
107677298Sobrien     asection *section ATTRIBUTE_UNUSED;
107777298Sobrien     struct bfd_link_info *link_info ATTRIBUTE_UNUSED;
107877298Sobrien     boolean *again;
107977298Sobrien{
108077298Sobrien  *again = false;
108177298Sobrien  SET_SEC_DO_RELAX (section);
108277298Sobrien  return true;
108377298Sobrien}
108477298Sobrien
108559024Sobrien/* Relocate a SPARC ELF section.  */
108659024Sobrien
108759024Sobrienstatic boolean
108859024Sobrienelf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section,
108959024Sobrien			      contents, relocs, local_syms, local_sections)
109059024Sobrien     bfd *output_bfd;
109159024Sobrien     struct bfd_link_info *info;
109259024Sobrien     bfd *input_bfd;
109359024Sobrien     asection *input_section;
109459024Sobrien     bfd_byte *contents;
109559024Sobrien     Elf_Internal_Rela *relocs;
109659024Sobrien     Elf_Internal_Sym *local_syms;
109759024Sobrien     asection **local_sections;
109859024Sobrien{
109959024Sobrien  bfd *dynobj;
110059024Sobrien  Elf_Internal_Shdr *symtab_hdr;
110159024Sobrien  struct elf_link_hash_entry **sym_hashes;
110259024Sobrien  bfd_vma *local_got_offsets;
110359024Sobrien  bfd_vma got_base;
110459024Sobrien  asection *sgot;
110559024Sobrien  asection *splt;
110659024Sobrien  asection *sreloc;
110759024Sobrien  Elf_Internal_Rela *rel;
110859024Sobrien  Elf_Internal_Rela *relend;
110959024Sobrien
111059024Sobrien  dynobj = elf_hash_table (info)->dynobj;
111159024Sobrien  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
111259024Sobrien  sym_hashes = elf_sym_hashes (input_bfd);
111359024Sobrien  local_got_offsets = elf_local_got_offsets (input_bfd);
111459024Sobrien
111559024Sobrien  if (elf_hash_table (info)->hgot == NULL)
111659024Sobrien    got_base = 0;
111759024Sobrien  else
111859024Sobrien    got_base = elf_hash_table (info)->hgot->root.u.def.value;
111959024Sobrien
112059024Sobrien  sgot = NULL;
112159024Sobrien  splt = NULL;
112259024Sobrien  sreloc = NULL;
112359024Sobrien
112459024Sobrien  rel = relocs;
112559024Sobrien  relend = relocs + input_section->reloc_count;
112659024Sobrien  for (; rel < relend; rel++)
112759024Sobrien    {
112859024Sobrien      int r_type;
112959024Sobrien      reloc_howto_type *howto;
113059024Sobrien      unsigned long r_symndx;
113159024Sobrien      struct elf_link_hash_entry *h;
113259024Sobrien      Elf_Internal_Sym *sym;
113359024Sobrien      asection *sec;
113459024Sobrien      bfd_vma relocation;
113559024Sobrien      bfd_reloc_status_type r;
113659024Sobrien
113759024Sobrien      r_type = ELF32_R_TYPE (rel->r_info);
113860484Sobrien
113977298Sobrien      if (r_type == R_SPARC_GNU_VTINHERIT
114060484Sobrien          || r_type == R_SPARC_GNU_VTENTRY)
114160484Sobrien        continue;
114260484Sobrien
114360484Sobrien      if (r_type < 0 || r_type >= (int) R_SPARC_max_std)
114459024Sobrien	{
114559024Sobrien	  bfd_set_error (bfd_error_bad_value);
114659024Sobrien	  return false;
114759024Sobrien	}
114859024Sobrien      howto = _bfd_sparc_elf_howto_table + r_type;
114959024Sobrien
115059024Sobrien      r_symndx = ELF32_R_SYM (rel->r_info);
115159024Sobrien
115259024Sobrien      if (info->relocateable)
115359024Sobrien	{
115459024Sobrien	  /* This is a relocateable link.  We don't have to change
115559024Sobrien	     anything, unless the reloc is against a section symbol,
115659024Sobrien	     in which case we have to adjust according to where the
115759024Sobrien	     section symbol winds up in the output section.  */
115859024Sobrien	  if (r_symndx < symtab_hdr->sh_info)
115959024Sobrien	    {
116059024Sobrien	      sym = local_syms + r_symndx;
116159024Sobrien	      if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
116259024Sobrien		{
116359024Sobrien		  sec = local_sections[r_symndx];
116459024Sobrien		  rel->r_addend += sec->output_offset + sym->st_value;
116559024Sobrien		}
116659024Sobrien	    }
116759024Sobrien
116859024Sobrien	  continue;
116959024Sobrien	}
117059024Sobrien
117159024Sobrien      /* This is a final link.  */
117259024Sobrien      h = NULL;
117359024Sobrien      sym = NULL;
117459024Sobrien      sec = NULL;
117559024Sobrien      if (r_symndx < symtab_hdr->sh_info)
117659024Sobrien	{
117759024Sobrien	  sym = local_syms + r_symndx;
117859024Sobrien	  sec = local_sections[r_symndx];
117959024Sobrien	  relocation = (sec->output_section->vma
118059024Sobrien			+ sec->output_offset
118159024Sobrien			+ sym->st_value);
118259024Sobrien	}
118359024Sobrien      else
118459024Sobrien	{
118559024Sobrien	  h = sym_hashes[r_symndx - symtab_hdr->sh_info];
118659024Sobrien	  while (h->root.type == bfd_link_hash_indirect
118759024Sobrien		 || h->root.type == bfd_link_hash_warning)
118859024Sobrien	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
118959024Sobrien	  if (h->root.type == bfd_link_hash_defined
119059024Sobrien	      || h->root.type == bfd_link_hash_defweak)
119159024Sobrien	    {
119259024Sobrien	      sec = h->root.u.def.section;
119359024Sobrien	      if ((r_type == R_SPARC_WPLT30
119460484Sobrien		   && h->plt.offset != (bfd_vma) -1)
119559024Sobrien		  || ((r_type == R_SPARC_GOT10
119659024Sobrien		       || r_type == R_SPARC_GOT13
119759024Sobrien		       || r_type == R_SPARC_GOT22)
119859024Sobrien		      && elf_hash_table (info)->dynamic_sections_created
119959024Sobrien		      && (! info->shared
120059024Sobrien			  || (! info->symbolic && h->dynindx != -1)
120159024Sobrien			  || (h->elf_link_hash_flags
120259024Sobrien			      & ELF_LINK_HASH_DEF_REGULAR) == 0))
120359024Sobrien		  || (info->shared
120459024Sobrien		      && ((! info->symbolic && h->dynindx != -1)
120559024Sobrien			  || (h->elf_link_hash_flags
120659024Sobrien			      & ELF_LINK_HASH_DEF_REGULAR) == 0)
120759024Sobrien		      && (r_type == R_SPARC_8
120859024Sobrien			  || r_type == R_SPARC_16
120959024Sobrien			  || r_type == R_SPARC_32
121059024Sobrien			  || r_type == R_SPARC_DISP8
121159024Sobrien			  || r_type == R_SPARC_DISP16
121259024Sobrien			  || r_type == R_SPARC_DISP32
121359024Sobrien			  || r_type == R_SPARC_WDISP30
121459024Sobrien			  || r_type == R_SPARC_WDISP22
121559024Sobrien			  || r_type == R_SPARC_WDISP19
121659024Sobrien			  || r_type == R_SPARC_WDISP16
121759024Sobrien			  || r_type == R_SPARC_HI22
121859024Sobrien			  || r_type == R_SPARC_22
121959024Sobrien			  || r_type == R_SPARC_13
122059024Sobrien			  || r_type == R_SPARC_LO10
122159024Sobrien			  || r_type == R_SPARC_UA32
122259024Sobrien			  || ((r_type == R_SPARC_PC10
122359024Sobrien			       || r_type == R_SPARC_PC22)
122459024Sobrien			      && strcmp (h->root.root.string,
122559024Sobrien					 "_GLOBAL_OFFSET_TABLE_") != 0))))
122659024Sobrien		{
122759024Sobrien		  /* In these cases, we don't need the relocation
122859024Sobrien                     value.  We check specially because in some
122959024Sobrien                     obscure cases sec->output_section will be NULL.  */
123059024Sobrien		  relocation = 0;
123159024Sobrien		}
123259024Sobrien	      else
123359024Sobrien		relocation = (h->root.u.def.value
123459024Sobrien			      + sec->output_section->vma
123559024Sobrien			      + sec->output_offset);
123659024Sobrien	    }
123759024Sobrien	  else if (h->root.type == bfd_link_hash_undefweak)
123859024Sobrien	    relocation = 0;
123968765Sobrien	  else if (info->shared && !info->symbolic
124068765Sobrien		   && !info->no_undefined
124168765Sobrien		   && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
124259024Sobrien	    relocation = 0;
124359024Sobrien	  else
124459024Sobrien	    {
124559024Sobrien	      if (! ((*info->callbacks->undefined_symbol)
124659024Sobrien		     (info, h->root.root.string, input_bfd,
124760484Sobrien		      input_section, rel->r_offset,
124868765Sobrien		      (!info->shared || info->no_undefined
124968765Sobrien		       || ELF_ST_VISIBILITY (h->other)))))
125059024Sobrien		return false;
125159024Sobrien	      relocation = 0;
125259024Sobrien	    }
125359024Sobrien	}
125459024Sobrien
125559024Sobrien      switch (r_type)
125659024Sobrien	{
125759024Sobrien	case R_SPARC_GOT10:
125859024Sobrien	case R_SPARC_GOT13:
125959024Sobrien	case R_SPARC_GOT22:
126059024Sobrien	  /* Relocation is to the entry for this symbol in the global
126159024Sobrien             offset table.  */
126259024Sobrien	  if (sgot == NULL)
126359024Sobrien	    {
126459024Sobrien	      sgot = bfd_get_section_by_name (dynobj, ".got");
126559024Sobrien	      BFD_ASSERT (sgot != NULL);
126659024Sobrien	    }
126759024Sobrien
126859024Sobrien	  if (h != NULL)
126959024Sobrien	    {
127059024Sobrien	      bfd_vma off;
127159024Sobrien
127260484Sobrien	      off = h->got.offset;
127359024Sobrien	      BFD_ASSERT (off != (bfd_vma) -1);
127459024Sobrien
127559024Sobrien	      if (! elf_hash_table (info)->dynamic_sections_created
127659024Sobrien		  || (info->shared
127759024Sobrien		      && (info->symbolic || h->dynindx == -1)
127859024Sobrien		      && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)))
127959024Sobrien		{
128059024Sobrien		  /* This is actually a static link, or it is a
128159024Sobrien                     -Bsymbolic link and the symbol is defined
128259024Sobrien                     locally, or the symbol was forced to be local
128359024Sobrien                     because of a version file.  We must initialize
128459024Sobrien                     this entry in the global offset table.  Since the
128559024Sobrien                     offset must always be a multiple of 4, we use the
128659024Sobrien                     least significant bit to record whether we have
128759024Sobrien                     initialized it already.
128859024Sobrien
128959024Sobrien		     When doing a dynamic link, we create a .rela.got
129059024Sobrien		     relocation entry to initialize the value.  This
129159024Sobrien		     is done in the finish_dynamic_symbol routine.  */
129259024Sobrien		  if ((off & 1) != 0)
129359024Sobrien		    off &= ~1;
129459024Sobrien		  else
129559024Sobrien		    {
129659024Sobrien		      bfd_put_32 (output_bfd, relocation,
129759024Sobrien				  sgot->contents + off);
129860484Sobrien		      h->got.offset |= 1;
129959024Sobrien		    }
130059024Sobrien		}
130159024Sobrien
130259024Sobrien	      relocation = sgot->output_offset + off - got_base;
130359024Sobrien	    }
130459024Sobrien	  else
130559024Sobrien	    {
130659024Sobrien	      bfd_vma off;
130759024Sobrien
130859024Sobrien	      BFD_ASSERT (local_got_offsets != NULL
130959024Sobrien			  && local_got_offsets[r_symndx] != (bfd_vma) -1);
131059024Sobrien
131159024Sobrien	      off = local_got_offsets[r_symndx];
131259024Sobrien
131359024Sobrien	      /* The offset must always be a multiple of 4.  We use
131459024Sobrien		 the least significant bit to record whether we have
131559024Sobrien		 already processed this entry.  */
131659024Sobrien	      if ((off & 1) != 0)
131759024Sobrien		off &= ~1;
131859024Sobrien	      else
131959024Sobrien		{
132059024Sobrien		  bfd_put_32 (output_bfd, relocation, sgot->contents + off);
132159024Sobrien
132259024Sobrien		  if (info->shared)
132359024Sobrien		    {
132459024Sobrien		      asection *srelgot;
132559024Sobrien		      Elf_Internal_Rela outrel;
132659024Sobrien
132759024Sobrien		      /* We need to generate a R_SPARC_RELATIVE reloc
132859024Sobrien			 for the dynamic linker.  */
132959024Sobrien		      srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
133059024Sobrien		      BFD_ASSERT (srelgot != NULL);
133159024Sobrien
133259024Sobrien		      outrel.r_offset = (sgot->output_section->vma
133359024Sobrien					 + sgot->output_offset
133459024Sobrien					 + off);
133559024Sobrien		      outrel.r_info = ELF32_R_INFO (0, R_SPARC_RELATIVE);
133659024Sobrien		      outrel.r_addend = 0;
133759024Sobrien		      bfd_elf32_swap_reloca_out (output_bfd, &outrel,
133859024Sobrien						 (((Elf32_External_Rela *)
133959024Sobrien						   srelgot->contents)
134059024Sobrien						  + srelgot->reloc_count));
134159024Sobrien		      ++srelgot->reloc_count;
134259024Sobrien		    }
134359024Sobrien
134459024Sobrien		  local_got_offsets[r_symndx] |= 1;
134559024Sobrien		}
134659024Sobrien
134759024Sobrien	      relocation = sgot->output_offset + off - got_base;
134859024Sobrien	    }
134959024Sobrien
135059024Sobrien	  break;
135159024Sobrien
135259024Sobrien	case R_SPARC_WPLT30:
135359024Sobrien	  /* Relocation is to the entry for this symbol in the
135459024Sobrien             procedure linkage table.  */
135559024Sobrien
135660484Sobrien	  /* The Solaris native assembler will generate a WPLT30 reloc
135760484Sobrien	     for a local symbol if you assemble a call from one
135860484Sobrien	     section to another when using -K pic.  We treat it as
135960484Sobrien	     WDISP30.  */
136060484Sobrien	  if (h == NULL)
136160484Sobrien	    break;
136260484Sobrien
136360484Sobrien	  if (h->plt.offset == (bfd_vma) -1)
136459024Sobrien	    {
136559024Sobrien	      /* We didn't make a PLT entry for this symbol.  This
136659024Sobrien                 happens when statically linking PIC code, or when
136759024Sobrien                 using -Bsymbolic.  */
136859024Sobrien	      break;
136959024Sobrien	    }
137059024Sobrien
137159024Sobrien	  if (splt == NULL)
137259024Sobrien	    {
137359024Sobrien	      splt = bfd_get_section_by_name (dynobj, ".plt");
137459024Sobrien	      BFD_ASSERT (splt != NULL);
137559024Sobrien	    }
137659024Sobrien
137759024Sobrien	  relocation = (splt->output_section->vma
137859024Sobrien			+ splt->output_offset
137960484Sobrien			+ h->plt.offset);
138059024Sobrien	  break;
138159024Sobrien
138259024Sobrien	case R_SPARC_PC10:
138359024Sobrien	case R_SPARC_PC22:
138459024Sobrien	  if (h != NULL
138559024Sobrien	      && strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
138659024Sobrien	    break;
138759024Sobrien	  /* Fall through.  */
138859024Sobrien	case R_SPARC_DISP8:
138959024Sobrien	case R_SPARC_DISP16:
139059024Sobrien	case R_SPARC_DISP32:
139159024Sobrien	case R_SPARC_WDISP30:
139259024Sobrien	case R_SPARC_WDISP22:
139359024Sobrien	case R_SPARC_WDISP19:
139459024Sobrien	case R_SPARC_WDISP16:
139559024Sobrien	  if (h == NULL
139659024Sobrien	      || (info->symbolic
139759024Sobrien		  && (h->elf_link_hash_flags
139859024Sobrien		      & ELF_LINK_HASH_DEF_REGULAR) != 0))
139959024Sobrien	    break;
140059024Sobrien	  /* Fall through.  */
140159024Sobrien	case R_SPARC_8:
140259024Sobrien	case R_SPARC_16:
140359024Sobrien	case R_SPARC_32:
140459024Sobrien	case R_SPARC_HI22:
140559024Sobrien	case R_SPARC_22:
140659024Sobrien	case R_SPARC_13:
140759024Sobrien	case R_SPARC_LO10:
140859024Sobrien	case R_SPARC_UA32:
140959024Sobrien	  if (info->shared)
141059024Sobrien	    {
141159024Sobrien	      Elf_Internal_Rela outrel;
141259024Sobrien	      boolean skip;
141359024Sobrien
141459024Sobrien	      /* When generating a shared object, these relocations
141559024Sobrien                 are copied into the output file to be resolved at run
141659024Sobrien                 time.  */
141759024Sobrien
141859024Sobrien	      if (sreloc == NULL)
141959024Sobrien		{
142059024Sobrien		  const char *name;
142159024Sobrien
142259024Sobrien		  name = (bfd_elf_string_from_elf_section
142359024Sobrien			  (input_bfd,
142459024Sobrien			   elf_elfheader (input_bfd)->e_shstrndx,
142559024Sobrien			   elf_section_data (input_section)->rel_hdr.sh_name));
142659024Sobrien		  if (name == NULL)
142759024Sobrien		    return false;
142859024Sobrien
142959024Sobrien		  BFD_ASSERT (strncmp (name, ".rela", 5) == 0
143059024Sobrien			      && strcmp (bfd_get_section_name (input_bfd,
143159024Sobrien							       input_section),
143259024Sobrien					 name + 5) == 0);
143359024Sobrien
143459024Sobrien		  sreloc = bfd_get_section_by_name (dynobj, name);
143559024Sobrien		  BFD_ASSERT (sreloc != NULL);
143659024Sobrien		}
143759024Sobrien
143859024Sobrien	      skip = false;
143959024Sobrien
144059024Sobrien	      if (elf_section_data (input_section)->stab_info == NULL)
144159024Sobrien		outrel.r_offset = rel->r_offset;
144259024Sobrien	      else
144359024Sobrien		{
144459024Sobrien		  bfd_vma off;
144559024Sobrien
144659024Sobrien		  off = (_bfd_stab_section_offset
144759024Sobrien			 (output_bfd, &elf_hash_table (info)->stab_info,
144859024Sobrien			  input_section,
144959024Sobrien			  &elf_section_data (input_section)->stab_info,
145059024Sobrien			  rel->r_offset));
145159024Sobrien		  if (off == (bfd_vma) -1)
145259024Sobrien		    skip = true;
145359024Sobrien		  outrel.r_offset = off;
145459024Sobrien		}
145559024Sobrien
145659024Sobrien	      outrel.r_offset += (input_section->output_section->vma
145759024Sobrien				  + input_section->output_offset);
145859024Sobrien
145959024Sobrien	      if (skip)
146059024Sobrien		memset (&outrel, 0, sizeof outrel);
146159024Sobrien	      /* h->dynindx may be -1 if the symbol was marked to
146259024Sobrien                 become local.  */
146359024Sobrien	      else if (h != NULL
146459024Sobrien		       && ((! info->symbolic && h->dynindx != -1)
146559024Sobrien			   || (h->elf_link_hash_flags
146659024Sobrien			       & ELF_LINK_HASH_DEF_REGULAR) == 0))
146759024Sobrien		{
146859024Sobrien		  BFD_ASSERT (h->dynindx != -1);
146959024Sobrien		  outrel.r_info = ELF32_R_INFO (h->dynindx, r_type);
147059024Sobrien		  outrel.r_addend = rel->r_addend;
147159024Sobrien		}
147259024Sobrien	      else
147359024Sobrien		{
147459024Sobrien		  if (r_type == R_SPARC_32)
147559024Sobrien		    {
147659024Sobrien		      outrel.r_info = ELF32_R_INFO (0, R_SPARC_RELATIVE);
147759024Sobrien		      outrel.r_addend = relocation + rel->r_addend;
147859024Sobrien		    }
147959024Sobrien		  else
148059024Sobrien		    {
148159024Sobrien		      long indx;
148259024Sobrien
148359024Sobrien		      if (h == NULL)
148459024Sobrien			sec = local_sections[r_symndx];
148559024Sobrien		      else
148659024Sobrien			{
148759024Sobrien			  BFD_ASSERT (h->root.type == bfd_link_hash_defined
148859024Sobrien				      || (h->root.type
148959024Sobrien					  == bfd_link_hash_defweak));
149059024Sobrien			  sec = h->root.u.def.section;
149159024Sobrien			}
149259024Sobrien		      if (sec != NULL && bfd_is_abs_section (sec))
149359024Sobrien			indx = 0;
149459024Sobrien		      else if (sec == NULL || sec->owner == NULL)
149559024Sobrien			{
149659024Sobrien			  bfd_set_error (bfd_error_bad_value);
149759024Sobrien			  return false;
149859024Sobrien			}
149959024Sobrien		      else
150059024Sobrien			{
150159024Sobrien			  asection *osec;
150259024Sobrien
150359024Sobrien			  osec = sec->output_section;
150459024Sobrien			  indx = elf_section_data (osec)->dynindx;
150559024Sobrien
150659024Sobrien			  /* FIXME: we really should be able to link non-pic
150759024Sobrien			     shared libraries.  */
150859024Sobrien			  if (indx == 0)
150959024Sobrien			    {
151059024Sobrien			      BFD_FAIL ();
151159024Sobrien			      (*_bfd_error_handler)
151260484Sobrien				(_("%s: probably compiled without -fPIC?"),
151359024Sobrien				 bfd_get_filename (input_bfd));
151459024Sobrien			      bfd_set_error (bfd_error_bad_value);
151559024Sobrien			      return false;
151659024Sobrien			    }
151759024Sobrien			}
151859024Sobrien
151959024Sobrien		      outrel.r_info = ELF32_R_INFO (indx, r_type);
152059024Sobrien		      outrel.r_addend = relocation + rel->r_addend;
152159024Sobrien		    }
152259024Sobrien		}
152359024Sobrien
152459024Sobrien	      bfd_elf32_swap_reloca_out (output_bfd, &outrel,
152559024Sobrien					 (((Elf32_External_Rela *)
152659024Sobrien					   sreloc->contents)
152759024Sobrien					  + sreloc->reloc_count));
152859024Sobrien	      ++sreloc->reloc_count;
152959024Sobrien
153059024Sobrien	      /* This reloc will be computed at runtime, so there's no
153159024Sobrien                 need to do anything now, unless this is a RELATIVE
153259024Sobrien                 reloc in an unallocated section.  */
153359024Sobrien	      if (skip
153459024Sobrien		  || (input_section->flags & SEC_ALLOC) != 0
153559024Sobrien		  || ELF32_R_TYPE (outrel.r_info) != R_SPARC_RELATIVE)
153659024Sobrien		continue;
153759024Sobrien	    }
153859024Sobrien	  break;
153959024Sobrien
154059024Sobrien	default:
154159024Sobrien	  break;
154259024Sobrien	}
154359024Sobrien
154477298Sobrien      r = bfd_reloc_continue;
154560484Sobrien      if (r_type == R_SPARC_WDISP16)
154659024Sobrien	{
154759024Sobrien	  bfd_vma x;
154859024Sobrien
154959024Sobrien	  relocation += rel->r_addend;
155059024Sobrien	  relocation -= (input_section->output_section->vma
155159024Sobrien			 + input_section->output_offset);
155259024Sobrien	  relocation -= rel->r_offset;
155359024Sobrien
155459024Sobrien	  x = bfd_get_32 (input_bfd, contents + rel->r_offset);
155559024Sobrien	  x |= ((((relocation >> 2) & 0xc000) << 6)
155659024Sobrien		| ((relocation >> 2) & 0x3fff));
155759024Sobrien	  bfd_put_32 (input_bfd, x, contents + rel->r_offset);
155859024Sobrien
155959024Sobrien	  if ((bfd_signed_vma) relocation < - 0x40000
156059024Sobrien	      || (bfd_signed_vma) relocation > 0x3ffff)
156159024Sobrien	    r = bfd_reloc_overflow;
156259024Sobrien	  else
156359024Sobrien	    r = bfd_reloc_ok;
156459024Sobrien	}
156560484Sobrien      else if (r_type == R_SPARC_REV32)
156660484Sobrien	{
156760484Sobrien	  bfd_vma x;
156859024Sobrien
156960484Sobrien	  relocation = relocation + rel->r_addend;
157060484Sobrien
157160484Sobrien	  x = bfd_get_32 (input_bfd, contents + rel->r_offset);
157260484Sobrien	  x = x + relocation;
157360484Sobrien	  bfd_putl32 (/*input_bfd,*/ x, contents + rel->r_offset);
157460484Sobrien	  r = bfd_reloc_ok;
157560484Sobrien	}
157677298Sobrien      else if ((r_type == R_SPARC_WDISP30 || r_type == R_SPARC_WPLT30)
157777298Sobrien	       && SEC_DO_RELAX (input_section)
157877298Sobrien	       && rel->r_offset + 4 < input_section->_raw_size)
157977298Sobrien	{
158077298Sobrien#define G0		0
158177298Sobrien#define O7		15
158277298Sobrien#define XCC		(2 << 20)
158377298Sobrien#define COND(x)		(((x)&0xf)<<25)
158477298Sobrien#define CONDA		COND(0x8)
158577298Sobrien#define INSN_BPA	(F2(0,1) | CONDA | BPRED | XCC)
158677298Sobrien#define INSN_BA		(F2(0,2) | CONDA)
158777298Sobrien#define INSN_OR		F3(2, 0x2, 0)
158877298Sobrien#define INSN_NOP	F2(0,4)
158977298Sobrien
159077298Sobrien	  bfd_vma x, y;
159177298Sobrien
159277298Sobrien	  /* If the instruction is a call with either:
159377298Sobrien	     restore
159477298Sobrien	     arithmetic instruction with rd == %o7
159577298Sobrien	     where rs1 != %o7 and rs2 if it is register != %o7
159677298Sobrien	     then we can optimize if the call destination is near
159777298Sobrien	     by changing the call into a branch always.  */
159877298Sobrien	  x = bfd_get_32 (input_bfd, contents + rel->r_offset);
159977298Sobrien	  y = bfd_get_32 (input_bfd, contents + rel->r_offset + 4);
160077298Sobrien	  if ((x & OP(~0)) == OP(1) && (y & OP(~0)) == OP(2))
160177298Sobrien	    {
160277298Sobrien	      if (((y & OP3(~0)) == OP3(0x3d) /* restore */
160377298Sobrien		   || ((y & OP3(0x28)) == 0 /* arithmetic */
160477298Sobrien		       && (y & RD(~0)) == RD(O7)))
160577298Sobrien		  && (y & RS1(~0)) != RS1(O7)
160677298Sobrien		  && ((y & F3I(~0))
160777298Sobrien		      || (y & RS2(~0)) != RS2(O7)))
160877298Sobrien		{
160977298Sobrien		  bfd_vma reloc;
161077298Sobrien
161177298Sobrien		  reloc = relocation + rel->r_addend - rel->r_offset;
161277298Sobrien		  reloc -= (input_section->output_section->vma
161377298Sobrien			   + input_section->output_offset);
161477298Sobrien
161577298Sobrien		  /* Ensure the reloc fits into simm22.  */
161677298Sobrien		  if ((reloc & 3) == 0
161777298Sobrien		      && ((reloc & ~(bfd_vma)0x7fffff) == 0
161877298Sobrien			  || ((reloc | 0x7fffff) == ~(bfd_vma)0)))
161977298Sobrien		    {
162077298Sobrien		      reloc >>= 2;
162177298Sobrien
162277298Sobrien		      /* Check whether it fits into simm19 on v9.  */
162377298Sobrien		      if (((reloc & 0x3c0000) == 0
162477298Sobrien			   || (reloc & 0x3c0000) == 0x3c0000)
162577298Sobrien			  && (elf_elfheader (output_bfd)->e_flags & EF_SPARC_32PLUS))
162677298Sobrien			x = INSN_BPA | (reloc & 0x7ffff); /* ba,pt %xcc */
162777298Sobrien		      else
162877298Sobrien			x = INSN_BA | (reloc & 0x3fffff); /* ba */
162977298Sobrien		      bfd_put_32 (input_bfd, x, contents + rel->r_offset);
163077298Sobrien		      r = bfd_reloc_ok;
163177298Sobrien		      if (rel->r_offset >= 4
163277298Sobrien			  && (y & (0xffffffff ^ RS1(~0)))
163377298Sobrien			      == (INSN_OR | RD(O7) | RS2(G0)))
163477298Sobrien			{
163577298Sobrien			  bfd_vma z;
163677298Sobrien			  unsigned int reg;
163777298Sobrien
163877298Sobrien			  z = bfd_get_32 (input_bfd,
163977298Sobrien					  contents + rel->r_offset - 4);
164077298Sobrien			  if ((z & (0xffffffff ^ RD(~0)))
164177298Sobrien			      != (INSN_OR | RS1(O7) | RS2(G0)))
164277298Sobrien			    break;
164377298Sobrien
164477298Sobrien			  /* The sequence was
164577298Sobrien			     or %o7, %g0, %rN
164677298Sobrien			     call foo
164777298Sobrien			     or %rN, %g0, %o7
164877298Sobrien
164977298Sobrien			     If call foo was replaced with ba, replace
165077298Sobrien			     or %rN, %g0, %o7 with nop.  */
165177298Sobrien
165277298Sobrien			  reg = (y & RS1(~0)) >> 14;
165377298Sobrien			  if (reg != ((z & RD(~0)) >> 25)
165477298Sobrien			      || reg == G0 || reg == O7)
165577298Sobrien			    break;
165677298Sobrien
165777298Sobrien			  bfd_put_32 (input_bfd, INSN_NOP,
165877298Sobrien				      contents + rel->r_offset + 4);
165977298Sobrien			}
166077298Sobrien
166177298Sobrien		    }
166277298Sobrien		}
166377298Sobrien	    }
166477298Sobrien	}
166577298Sobrien
166677298Sobrien      if (r == bfd_reloc_continue)
166760484Sobrien	r = _bfd_final_link_relocate (howto, input_bfd, input_section,
166860484Sobrien				      contents, rel->r_offset,
166960484Sobrien				      relocation, rel->r_addend);
167060484Sobrien
167159024Sobrien      if (r != bfd_reloc_ok)
167259024Sobrien	{
167359024Sobrien	  switch (r)
167459024Sobrien	    {
167559024Sobrien	    default:
167659024Sobrien	    case bfd_reloc_outofrange:
167759024Sobrien	      abort ();
167859024Sobrien	    case bfd_reloc_overflow:
167959024Sobrien	      {
168059024Sobrien		const char *name;
168159024Sobrien
168259024Sobrien		if (h != NULL)
168359024Sobrien		  name = h->root.root.string;
168459024Sobrien		else
168559024Sobrien		  {
168659024Sobrien		    name = bfd_elf_string_from_elf_section (input_bfd,
168759024Sobrien							    symtab_hdr->sh_link,
168859024Sobrien							    sym->st_name);
168959024Sobrien		    if (name == NULL)
169059024Sobrien		      return false;
169159024Sobrien		    if (*name == '\0')
169259024Sobrien		      name = bfd_section_name (input_bfd, sec);
169359024Sobrien		  }
169459024Sobrien		if (! ((*info->callbacks->reloc_overflow)
169559024Sobrien		       (info, name, howto->name, (bfd_vma) 0,
169659024Sobrien			input_bfd, input_section, rel->r_offset)))
169759024Sobrien		  return false;
169859024Sobrien	      }
169959024Sobrien	      break;
170059024Sobrien	    }
170159024Sobrien	}
170259024Sobrien    }
170359024Sobrien
170459024Sobrien  return true;
170559024Sobrien}
170659024Sobrien
170759024Sobrien/* Finish up dynamic symbol handling.  We set the contents of various
170859024Sobrien   dynamic sections here.  */
170959024Sobrien
171059024Sobrienstatic boolean
171159024Sobrienelf32_sparc_finish_dynamic_symbol (output_bfd, info, h, sym)
171259024Sobrien     bfd *output_bfd;
171359024Sobrien     struct bfd_link_info *info;
171459024Sobrien     struct elf_link_hash_entry *h;
171559024Sobrien     Elf_Internal_Sym *sym;
171659024Sobrien{
171759024Sobrien  bfd *dynobj;
171859024Sobrien
171959024Sobrien  dynobj = elf_hash_table (info)->dynobj;
172059024Sobrien
172160484Sobrien  if (h->plt.offset != (bfd_vma) -1)
172259024Sobrien    {
172359024Sobrien      asection *splt;
172459024Sobrien      asection *srela;
172559024Sobrien      Elf_Internal_Rela rela;
172659024Sobrien
172759024Sobrien      /* This symbol has an entry in the procedure linkage table.  Set
172859024Sobrien         it up.  */
172959024Sobrien
173059024Sobrien      BFD_ASSERT (h->dynindx != -1);
173159024Sobrien
173259024Sobrien      splt = bfd_get_section_by_name (dynobj, ".plt");
173359024Sobrien      srela = bfd_get_section_by_name (dynobj, ".rela.plt");
173459024Sobrien      BFD_ASSERT (splt != NULL && srela != NULL);
173559024Sobrien
173659024Sobrien      /* Fill in the entry in the procedure linkage table.  */
173759024Sobrien      bfd_put_32 (output_bfd,
173860484Sobrien		  PLT_ENTRY_WORD0 + h->plt.offset,
173960484Sobrien		  splt->contents + h->plt.offset);
174059024Sobrien      bfd_put_32 (output_bfd,
174159024Sobrien		  (PLT_ENTRY_WORD1
174260484Sobrien		   + (((- (h->plt.offset + 4)) >> 2) & 0x3fffff)),
174360484Sobrien		  splt->contents + h->plt.offset + 4);
174459024Sobrien      bfd_put_32 (output_bfd, PLT_ENTRY_WORD2,
174560484Sobrien		  splt->contents + h->plt.offset + 8);
174659024Sobrien
174759024Sobrien      /* Fill in the entry in the .rela.plt section.  */
174859024Sobrien      rela.r_offset = (splt->output_section->vma
174959024Sobrien		       + splt->output_offset
175060484Sobrien		       + h->plt.offset);
175159024Sobrien      rela.r_info = ELF32_R_INFO (h->dynindx, R_SPARC_JMP_SLOT);
175259024Sobrien      rela.r_addend = 0;
175359024Sobrien      bfd_elf32_swap_reloca_out (output_bfd, &rela,
175459024Sobrien				 ((Elf32_External_Rela *) srela->contents
175560484Sobrien				  + h->plt.offset / PLT_ENTRY_SIZE - 4));
175659024Sobrien
175759024Sobrien      if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
175859024Sobrien	{
175959024Sobrien	  /* Mark the symbol as undefined, rather than as defined in
176059024Sobrien	     the .plt section.  Leave the value alone.  */
176159024Sobrien	  sym->st_shndx = SHN_UNDEF;
176259024Sobrien	}
176359024Sobrien    }
176459024Sobrien
176560484Sobrien  if (h->got.offset != (bfd_vma) -1)
176659024Sobrien    {
176759024Sobrien      asection *sgot;
176859024Sobrien      asection *srela;
176959024Sobrien      Elf_Internal_Rela rela;
177059024Sobrien
177159024Sobrien      /* This symbol has an entry in the global offset table.  Set it
177259024Sobrien         up.  */
177359024Sobrien
177459024Sobrien      sgot = bfd_get_section_by_name (dynobj, ".got");
177559024Sobrien      srela = bfd_get_section_by_name (dynobj, ".rela.got");
177659024Sobrien      BFD_ASSERT (sgot != NULL && srela != NULL);
177759024Sobrien
177859024Sobrien      rela.r_offset = (sgot->output_section->vma
177959024Sobrien		       + sgot->output_offset
178060484Sobrien		       + (h->got.offset &~ 1));
178159024Sobrien
178259024Sobrien      /* If this is a -Bsymbolic link, and the symbol is defined
178359024Sobrien	 locally, we just want to emit a RELATIVE reloc.  Likewise if
178459024Sobrien	 the symbol was forced to be local because of a version file.
178559024Sobrien	 The entry in the global offset table will already have been
178659024Sobrien	 initialized in the relocate_section function.  */
178759024Sobrien      if (info->shared
178859024Sobrien	  && (info->symbolic || h->dynindx == -1)
178959024Sobrien	  && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))
179059024Sobrien	rela.r_info = ELF32_R_INFO (0, R_SPARC_RELATIVE);
179159024Sobrien      else
179259024Sobrien	{
179360484Sobrien	  bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + h->got.offset);
179459024Sobrien	  rela.r_info = ELF32_R_INFO (h->dynindx, R_SPARC_GLOB_DAT);
179559024Sobrien	}
179659024Sobrien
179759024Sobrien      rela.r_addend = 0;
179859024Sobrien      bfd_elf32_swap_reloca_out (output_bfd, &rela,
179959024Sobrien				 ((Elf32_External_Rela *) srela->contents
180059024Sobrien				  + srela->reloc_count));
180159024Sobrien      ++srela->reloc_count;
180259024Sobrien    }
180359024Sobrien
180459024Sobrien  if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_COPY) != 0)
180559024Sobrien    {
180659024Sobrien      asection *s;
180759024Sobrien      Elf_Internal_Rela rela;
180859024Sobrien
180959024Sobrien      /* This symbols needs a copy reloc.  Set it up.  */
181059024Sobrien
181159024Sobrien      BFD_ASSERT (h->dynindx != -1);
181259024Sobrien
181359024Sobrien      s = bfd_get_section_by_name (h->root.u.def.section->owner,
181459024Sobrien				   ".rela.bss");
181559024Sobrien      BFD_ASSERT (s != NULL);
181659024Sobrien
181759024Sobrien      rela.r_offset = (h->root.u.def.value
181859024Sobrien		       + h->root.u.def.section->output_section->vma
181959024Sobrien		       + h->root.u.def.section->output_offset);
182059024Sobrien      rela.r_info = ELF32_R_INFO (h->dynindx, R_SPARC_COPY);
182159024Sobrien      rela.r_addend = 0;
182259024Sobrien      bfd_elf32_swap_reloca_out (output_bfd, &rela,
182359024Sobrien				 ((Elf32_External_Rela *) s->contents
182459024Sobrien				  + s->reloc_count));
182559024Sobrien      ++s->reloc_count;
182659024Sobrien    }
182759024Sobrien
182859024Sobrien  /* Mark some specially defined symbols as absolute.  */
182959024Sobrien  if (strcmp (h->root.root.string, "_DYNAMIC") == 0
183059024Sobrien      || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0
183159024Sobrien      || strcmp (h->root.root.string, "_PROCEDURE_LINKAGE_TABLE_") == 0)
183259024Sobrien    sym->st_shndx = SHN_ABS;
183359024Sobrien
183459024Sobrien  return true;
183559024Sobrien}
183659024Sobrien
183759024Sobrien/* Finish up the dynamic sections.  */
183859024Sobrien
183959024Sobrienstatic boolean
184059024Sobrienelf32_sparc_finish_dynamic_sections (output_bfd, info)
184159024Sobrien     bfd *output_bfd;
184259024Sobrien     struct bfd_link_info *info;
184359024Sobrien{
184459024Sobrien  bfd *dynobj;
184559024Sobrien  asection *sdyn;
184659024Sobrien  asection *sgot;
184759024Sobrien
184859024Sobrien  dynobj = elf_hash_table (info)->dynobj;
184959024Sobrien
185059024Sobrien  sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
185159024Sobrien
185259024Sobrien  if (elf_hash_table (info)->dynamic_sections_created)
185359024Sobrien    {
185459024Sobrien      asection *splt;
185559024Sobrien      Elf32_External_Dyn *dyncon, *dynconend;
185659024Sobrien
185759024Sobrien      splt = bfd_get_section_by_name (dynobj, ".plt");
185859024Sobrien      BFD_ASSERT (splt != NULL && sdyn != NULL);
185959024Sobrien
186059024Sobrien      dyncon = (Elf32_External_Dyn *) sdyn->contents;
186159024Sobrien      dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->_raw_size);
186259024Sobrien      for (; dyncon < dynconend; dyncon++)
186359024Sobrien	{
186459024Sobrien	  Elf_Internal_Dyn dyn;
186559024Sobrien	  const char *name;
186659024Sobrien	  boolean size;
186759024Sobrien
186859024Sobrien	  bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn);
186959024Sobrien
187059024Sobrien	  switch (dyn.d_tag)
187159024Sobrien	    {
187259024Sobrien	    case DT_PLTGOT:   name = ".plt"; size = false; break;
187359024Sobrien	    case DT_PLTRELSZ: name = ".rela.plt"; size = true; break;
187459024Sobrien	    case DT_JMPREL:   name = ".rela.plt"; size = false; break;
187559024Sobrien	    default:	  name = NULL; size = false; break;
187659024Sobrien	    }
187759024Sobrien
187859024Sobrien	  if (name != NULL)
187959024Sobrien	    {
188059024Sobrien	      asection *s;
188159024Sobrien
188259024Sobrien	      s = bfd_get_section_by_name (output_bfd, name);
188359024Sobrien	      if (s == NULL)
188459024Sobrien		dyn.d_un.d_val = 0;
188559024Sobrien	      else
188659024Sobrien		{
188759024Sobrien		  if (! size)
188859024Sobrien		    dyn.d_un.d_ptr = s->vma;
188959024Sobrien		  else
189059024Sobrien		    {
189159024Sobrien		      if (s->_cooked_size != 0)
189259024Sobrien			dyn.d_un.d_val = s->_cooked_size;
189359024Sobrien		      else
189459024Sobrien			dyn.d_un.d_val = s->_raw_size;
189559024Sobrien		    }
189659024Sobrien		}
189759024Sobrien	      bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
189859024Sobrien	    }
189959024Sobrien	}
190059024Sobrien
190159024Sobrien      /* Clear the first four entries in the procedure linkage table,
190259024Sobrien	 and put a nop in the last four bytes.  */
190359024Sobrien      if (splt->_raw_size > 0)
190459024Sobrien	{
190559024Sobrien	  memset (splt->contents, 0, 4 * PLT_ENTRY_SIZE);
190659024Sobrien	  bfd_put_32 (output_bfd, SPARC_NOP,
190759024Sobrien		      splt->contents + splt->_raw_size - 4);
190859024Sobrien	}
190959024Sobrien
191059024Sobrien      elf_section_data (splt->output_section)->this_hdr.sh_entsize =
191159024Sobrien	PLT_ENTRY_SIZE;
191259024Sobrien    }
191359024Sobrien
191459024Sobrien  /* Set the first entry in the global offset table to the address of
191559024Sobrien     the dynamic section.  */
191659024Sobrien  sgot = bfd_get_section_by_name (dynobj, ".got");
191759024Sobrien  BFD_ASSERT (sgot != NULL);
191859024Sobrien  if (sgot->_raw_size > 0)
191959024Sobrien    {
192059024Sobrien      if (sdyn == NULL)
192159024Sobrien	bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents);
192259024Sobrien      else
192359024Sobrien	bfd_put_32 (output_bfd,
192459024Sobrien		    sdyn->output_section->vma + sdyn->output_offset,
192559024Sobrien		    sgot->contents);
192659024Sobrien    }
192759024Sobrien
192859024Sobrien  elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4;
192959024Sobrien
193059024Sobrien  return true;
193159024Sobrien}
193259024Sobrien
193359024Sobrien/* Functions for dealing with the e_flags field.
193459024Sobrien
193559024Sobrien   We don't define set_private_flags or copy_private_bfd_data because
193659024Sobrien   the only currently defined values are based on the bfd mach number,
193759024Sobrien   so we use the latter instead and defer setting e_flags until the
193859024Sobrien   file is written out.  */
193959024Sobrien
194059024Sobrien/* Merge backend specific data from an object file to the output
194159024Sobrien   object file when linking.  */
194259024Sobrien
194359024Sobrienstatic boolean
194459024Sobrienelf32_sparc_merge_private_bfd_data (ibfd, obfd)
194559024Sobrien     bfd *ibfd;
194659024Sobrien     bfd *obfd;
194759024Sobrien{
194859024Sobrien  boolean error;
194960484Sobrien  /* FIXME: This should not be static.  */
195060484Sobrien  static unsigned long previous_ibfd_e_flags = (unsigned long) -1;
195159024Sobrien
195259024Sobrien  if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
195359024Sobrien      || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
195459024Sobrien    return true;
195559024Sobrien
195659024Sobrien  error = false;
195759024Sobrien
195859024Sobrien  if (bfd_get_mach (ibfd) >= bfd_mach_sparc_v9)
195959024Sobrien    {
196059024Sobrien      error = true;
196159024Sobrien      (*_bfd_error_handler)
196260484Sobrien	(_("%s: compiled for a 64 bit system and target is 32 bit"),
196359024Sobrien	 bfd_get_filename (ibfd));
196459024Sobrien    }
196560484Sobrien  else if ((ibfd->flags & DYNAMIC) == 0)
196660484Sobrien    {
196760484Sobrien      if (bfd_get_mach (obfd) < bfd_get_mach (ibfd))
196860484Sobrien	bfd_set_arch_mach (obfd, bfd_arch_sparc, bfd_get_mach (ibfd));
196960484Sobrien    }
197059024Sobrien
197160484Sobrien  if (((elf_elfheader (ibfd)->e_flags & EF_SPARC_LEDATA)
197260484Sobrien       != previous_ibfd_e_flags)
197360484Sobrien      && previous_ibfd_e_flags != (unsigned long) -1)
197460484Sobrien    {
197560484Sobrien      (*_bfd_error_handler)
197660484Sobrien	(_("%s: linking little endian files with big endian files"),
197760484Sobrien	 bfd_get_filename (ibfd));
197860484Sobrien      error = true;
197960484Sobrien    }
198060484Sobrien  previous_ibfd_e_flags = elf_elfheader (ibfd)->e_flags & EF_SPARC_LEDATA;
198160484Sobrien
198259024Sobrien  if (error)
198359024Sobrien    {
198459024Sobrien      bfd_set_error (bfd_error_bad_value);
198559024Sobrien      return false;
198659024Sobrien    }
198759024Sobrien
198859024Sobrien  return true;
198959024Sobrien}
199059024Sobrien
199159024Sobrien/* Set the right machine number.  */
199259024Sobrien
199359024Sobrienstatic boolean
199459024Sobrienelf32_sparc_object_p (abfd)
199559024Sobrien     bfd *abfd;
199659024Sobrien{
199759024Sobrien  if (elf_elfheader (abfd)->e_machine == EM_SPARC32PLUS)
199859024Sobrien    {
199977298Sobrien      if (elf_elfheader (abfd)->e_flags & EF_SPARC_SUN_US3)
200059024Sobrien	return bfd_default_set_arch_mach (abfd, bfd_arch_sparc,
200177298Sobrien					  bfd_mach_sparc_v8plusb);
200277298Sobrien      else if (elf_elfheader (abfd)->e_flags & EF_SPARC_SUN_US1)
200377298Sobrien	return bfd_default_set_arch_mach (abfd, bfd_arch_sparc,
200459024Sobrien					  bfd_mach_sparc_v8plusa);
200559024Sobrien      else if (elf_elfheader (abfd)->e_flags & EF_SPARC_32PLUS)
200659024Sobrien	return bfd_default_set_arch_mach (abfd, bfd_arch_sparc,
200759024Sobrien					  bfd_mach_sparc_v8plus);
200859024Sobrien      else
200959024Sobrien	return false;
201059024Sobrien    }
201160484Sobrien  else if (elf_elfheader (abfd)->e_flags & EF_SPARC_LEDATA)
201260484Sobrien    return bfd_default_set_arch_mach (abfd, bfd_arch_sparc,
201360484Sobrien                                      bfd_mach_sparc_sparclite_le);
201459024Sobrien  else
201559024Sobrien    return bfd_default_set_arch_mach (abfd, bfd_arch_sparc, bfd_mach_sparc);
201659024Sobrien}
201759024Sobrien
201859024Sobrien/* The final processing done just before writing out the object file.
201959024Sobrien   We need to set the e_machine field appropriately.  */
202059024Sobrien
202159024Sobrienstatic void
202259024Sobrienelf32_sparc_final_write_processing (abfd, linker)
202359024Sobrien     bfd *abfd;
202460484Sobrien     boolean linker ATTRIBUTE_UNUSED;
202559024Sobrien{
202659024Sobrien  switch (bfd_get_mach (abfd))
202759024Sobrien    {
202859024Sobrien    case bfd_mach_sparc :
202959024Sobrien      break; /* nothing to do */
203059024Sobrien    case bfd_mach_sparc_v8plus :
203159024Sobrien      elf_elfheader (abfd)->e_machine = EM_SPARC32PLUS;
203259024Sobrien      elf_elfheader (abfd)->e_flags &=~ EF_SPARC_32PLUS_MASK;
203359024Sobrien      elf_elfheader (abfd)->e_flags |= EF_SPARC_32PLUS;
203459024Sobrien      break;
203559024Sobrien    case bfd_mach_sparc_v8plusa :
203659024Sobrien      elf_elfheader (abfd)->e_machine = EM_SPARC32PLUS;
203759024Sobrien      elf_elfheader (abfd)->e_flags &=~ EF_SPARC_32PLUS_MASK;
203859024Sobrien      elf_elfheader (abfd)->e_flags |= EF_SPARC_32PLUS | EF_SPARC_SUN_US1;
203959024Sobrien      break;
204077298Sobrien    case bfd_mach_sparc_v8plusb :
204177298Sobrien      elf_elfheader (abfd)->e_machine = EM_SPARC32PLUS;
204277298Sobrien      elf_elfheader (abfd)->e_flags &=~ EF_SPARC_32PLUS_MASK;
204377298Sobrien      elf_elfheader (abfd)->e_flags |= EF_SPARC_32PLUS | EF_SPARC_SUN_US1
204477298Sobrien				       | EF_SPARC_SUN_US3;
204577298Sobrien      break;
204660484Sobrien    case bfd_mach_sparc_sparclite_le :
204760484Sobrien      elf_elfheader (abfd)->e_machine = EM_SPARC;
204860484Sobrien      elf_elfheader (abfd)->e_flags |= EF_SPARC_LEDATA;
204960484Sobrien      break;
205059024Sobrien    default :
205159024Sobrien      abort ();
205260484Sobrien      break;
205359024Sobrien    }
205459024Sobrien}
205559024Sobrien
205659024Sobrien#define TARGET_BIG_SYM	bfd_elf32_sparc_vec
205759024Sobrien#define TARGET_BIG_NAME	"elf32-sparc"
205859024Sobrien#define ELF_ARCH	bfd_arch_sparc
205959024Sobrien#define ELF_MACHINE_CODE EM_SPARC
206059024Sobrien#define ELF_MACHINE_ALT1 EM_SPARC32PLUS
206159024Sobrien#define ELF_MAXPAGESIZE 0x10000
206259024Sobrien
206359024Sobrien#define bfd_elf32_bfd_reloc_type_lookup	elf32_sparc_reloc_type_lookup
206477298Sobrien#define bfd_elf32_bfd_relax_section	elf32_sparc_relax_section
206559024Sobrien#define elf_info_to_howto		elf32_sparc_info_to_howto
206659024Sobrien#define elf_backend_create_dynamic_sections \
206759024Sobrien					_bfd_elf_create_dynamic_sections
206859024Sobrien#define elf_backend_check_relocs	elf32_sparc_check_relocs
206959024Sobrien#define elf_backend_adjust_dynamic_symbol \
207059024Sobrien					elf32_sparc_adjust_dynamic_symbol
207159024Sobrien#define elf_backend_size_dynamic_sections \
207259024Sobrien					elf32_sparc_size_dynamic_sections
207359024Sobrien#define elf_backend_relocate_section	elf32_sparc_relocate_section
207459024Sobrien#define elf_backend_finish_dynamic_symbol \
207559024Sobrien					elf32_sparc_finish_dynamic_symbol
207659024Sobrien#define elf_backend_finish_dynamic_sections \
207759024Sobrien					elf32_sparc_finish_dynamic_sections
207859024Sobrien#define bfd_elf32_bfd_merge_private_bfd_data \
207959024Sobrien					elf32_sparc_merge_private_bfd_data
208059024Sobrien#define elf_backend_object_p		elf32_sparc_object_p
208159024Sobrien#define elf_backend_final_write_processing \
208259024Sobrien					elf32_sparc_final_write_processing
208360484Sobrien#define elf_backend_gc_mark_hook        elf32_sparc_gc_mark_hook
208460484Sobrien#define elf_backend_gc_sweep_hook       elf32_sparc_gc_sweep_hook
208560484Sobrien
208660484Sobrien#define elf_backend_can_gc_sections 1
208759024Sobrien#define elf_backend_want_got_plt 0
208859024Sobrien#define elf_backend_plt_readonly 0
208959024Sobrien#define elf_backend_want_plt_sym 1
209060484Sobrien#define elf_backend_got_header_size 4
209160484Sobrien#define elf_backend_plt_header_size (4*PLT_ENTRY_SIZE)
209259024Sobrien
209359024Sobrien#include "elf32-target.h"
2094