1214082Sdim/* SPARC-specific support for ELF
2214634Sdim   Copyright 2005, 2006, 2007 Free Software Foundation, Inc.
3214082Sdim
4214082Sdim   This file is part of BFD, the Binary File Descriptor library.
5214082Sdim
6214082Sdim   This program is free software; you can redistribute it and/or modify
7214082Sdim   it under the terms of the GNU General Public License as published by
8214082Sdim   the Free Software Foundation; either version 2 of the License, or
9214082Sdim   (at your option) any later version.
10214082Sdim
11214082Sdim   This program is distributed in the hope that it will be useful,
12214082Sdim   but WITHOUT ANY WARRANTY; without even the implied warranty of
13214082Sdim   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14214082Sdim   GNU General Public License for more details.
15214082Sdim
16214082Sdim   You should have received a copy of the GNU General Public License
17214082Sdim   along with this program; if not, write to the Free Software
18214082Sdim   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
19214082Sdim
20214082Sdim/* This file handles functionality common to the different SPARC ABI's.  */
21214082Sdim
22214634Sdim#include "sysdep.h"
23214082Sdim#include "bfd.h"
24214082Sdim#include "bfdlink.h"
25214082Sdim#include "libbfd.h"
26214082Sdim#include "libiberty.h"
27214082Sdim#include "elf-bfd.h"
28214082Sdim#include "elf/sparc.h"
29214082Sdim#include "opcode/sparc.h"
30214082Sdim#include "elfxx-sparc.h"
31214082Sdim#include "elf-vxworks.h"
32214082Sdim
33214082Sdim/* In case we're on a 32-bit machine, construct a 64-bit "-1" value.  */
34214082Sdim#define MINUS_ONE (~ (bfd_vma) 0)
35214082Sdim
36214082Sdim#define ABI_64_P(abfd) \
37214082Sdim  (get_elf_backend_data (abfd)->s->elfclass == ELFCLASS64)
38214082Sdim
39214082Sdim/* The relocation "howto" table.  */
40214082Sdim
41214082Sdim/* Utility for performing the standard initial work of an instruction
42214082Sdim   relocation.
43214082Sdim   *PRELOCATION will contain the relocated item.
44214082Sdim   *PINSN will contain the instruction from the input stream.
45214082Sdim   If the result is `bfd_reloc_other' the caller can continue with
46214082Sdim   performing the relocation.  Otherwise it must stop and return the
47214082Sdim   value to its caller.  */
48214082Sdim
49214082Sdimstatic bfd_reloc_status_type
50214082Sdiminit_insn_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
51214082Sdim		 PTR data, asection *input_section, bfd *output_bfd,
52214082Sdim		 bfd_vma *prelocation, bfd_vma *pinsn)
53214082Sdim{
54214082Sdim  bfd_vma relocation;
55214082Sdim  reloc_howto_type *howto = reloc_entry->howto;
56214082Sdim
57214082Sdim  if (output_bfd != (bfd *) NULL
58214082Sdim      && (symbol->flags & BSF_SECTION_SYM) == 0
59214082Sdim      && (! howto->partial_inplace
60214082Sdim	  || reloc_entry->addend == 0))
61214082Sdim    {
62214082Sdim      reloc_entry->address += input_section->output_offset;
63214082Sdim      return bfd_reloc_ok;
64214082Sdim    }
65214082Sdim
66214082Sdim  /* This works because partial_inplace is FALSE.  */
67214082Sdim  if (output_bfd != NULL)
68214082Sdim    return bfd_reloc_continue;
69214082Sdim
70214082Sdim  if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
71214082Sdim    return bfd_reloc_outofrange;
72214082Sdim
73214082Sdim  relocation = (symbol->value
74214082Sdim		+ symbol->section->output_section->vma
75214082Sdim		+ symbol->section->output_offset);
76214082Sdim  relocation += reloc_entry->addend;
77214082Sdim  if (howto->pc_relative)
78214082Sdim    {
79214082Sdim      relocation -= (input_section->output_section->vma
80214082Sdim		     + input_section->output_offset);
81214082Sdim      relocation -= reloc_entry->address;
82214082Sdim    }
83214082Sdim
84214082Sdim  *prelocation = relocation;
85214082Sdim  *pinsn = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
86214082Sdim  return bfd_reloc_other;
87214082Sdim}
88214082Sdim
89214082Sdim/* For unsupported relocs.  */
90214082Sdim
91214082Sdimstatic bfd_reloc_status_type
92214082Sdimsparc_elf_notsup_reloc (bfd *abfd ATTRIBUTE_UNUSED,
93214082Sdim			arelent *reloc_entry ATTRIBUTE_UNUSED,
94214082Sdim			asymbol *symbol ATTRIBUTE_UNUSED,
95214082Sdim			PTR data ATTRIBUTE_UNUSED,
96214082Sdim			asection *input_section ATTRIBUTE_UNUSED,
97214082Sdim			bfd *output_bfd ATTRIBUTE_UNUSED,
98214082Sdim			char **error_message ATTRIBUTE_UNUSED)
99214082Sdim{
100214082Sdim  return bfd_reloc_notsupported;
101214082Sdim}
102214082Sdim
103214082Sdim/* Handle the WDISP16 reloc.  */
104214082Sdim
105214082Sdimstatic bfd_reloc_status_type
106214082Sdimsparc_elf_wdisp16_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
107214082Sdim			 PTR data, asection *input_section, bfd *output_bfd,
108214082Sdim			 char **error_message ATTRIBUTE_UNUSED)
109214082Sdim{
110214082Sdim  bfd_vma relocation;
111214082Sdim  bfd_vma insn;
112214082Sdim  bfd_reloc_status_type status;
113214082Sdim
114214082Sdim  status = init_insn_reloc (abfd, reloc_entry, symbol, data,
115214082Sdim			    input_section, output_bfd, &relocation, &insn);
116214082Sdim  if (status != bfd_reloc_other)
117214082Sdim    return status;
118214082Sdim
119214082Sdim  insn &= ~ (bfd_vma) 0x303fff;
120214082Sdim  insn |= (((relocation >> 2) & 0xc000) << 6) | ((relocation >> 2) & 0x3fff);
121214082Sdim  bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc_entry->address);
122214082Sdim
123214082Sdim  if ((bfd_signed_vma) relocation < - 0x40000
124214082Sdim      || (bfd_signed_vma) relocation > 0x3ffff)
125214082Sdim    return bfd_reloc_overflow;
126214082Sdim  else
127214082Sdim    return bfd_reloc_ok;
128214082Sdim}
129214082Sdim
130214082Sdim/* Handle the HIX22 reloc.  */
131214082Sdim
132214082Sdimstatic bfd_reloc_status_type
133214082Sdimsparc_elf_hix22_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
134214082Sdim		       PTR data, asection *input_section, bfd *output_bfd,
135214082Sdim		       char **error_message ATTRIBUTE_UNUSED)
136214082Sdim{
137214082Sdim  bfd_vma relocation;
138214082Sdim  bfd_vma insn;
139214082Sdim  bfd_reloc_status_type status;
140214082Sdim
141214082Sdim  status = init_insn_reloc (abfd, reloc_entry, symbol, data,
142214082Sdim			    input_section, output_bfd, &relocation, &insn);
143214082Sdim  if (status != bfd_reloc_other)
144214082Sdim    return status;
145214082Sdim
146214082Sdim  relocation ^= MINUS_ONE;
147214082Sdim  insn = (insn &~ (bfd_vma) 0x3fffff) | ((relocation >> 10) & 0x3fffff);
148214082Sdim  bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc_entry->address);
149214082Sdim
150214082Sdim  if ((relocation & ~ (bfd_vma) 0xffffffff) != 0)
151214082Sdim    return bfd_reloc_overflow;
152214082Sdim  else
153214082Sdim    return bfd_reloc_ok;
154214082Sdim}
155214082Sdim
156214082Sdim/* Handle the LOX10 reloc.  */
157214082Sdim
158214082Sdimstatic bfd_reloc_status_type
159214082Sdimsparc_elf_lox10_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
160214082Sdim		       PTR data, asection *input_section, bfd *output_bfd,
161214082Sdim		       char **error_message ATTRIBUTE_UNUSED)
162214082Sdim{
163214082Sdim  bfd_vma relocation;
164214082Sdim  bfd_vma insn;
165214082Sdim  bfd_reloc_status_type status;
166214082Sdim
167214082Sdim  status = init_insn_reloc (abfd, reloc_entry, symbol, data,
168214082Sdim			    input_section, output_bfd, &relocation, &insn);
169214082Sdim  if (status != bfd_reloc_other)
170214082Sdim    return status;
171214082Sdim
172214082Sdim  insn = (insn &~ (bfd_vma) 0x1fff) | 0x1c00 | (relocation & 0x3ff);
173214082Sdim  bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc_entry->address);
174214082Sdim
175214082Sdim  return bfd_reloc_ok;
176214082Sdim}
177214082Sdim
178214082Sdimstatic reloc_howto_type _bfd_sparc_elf_howto_table[] =
179214082Sdim{
180214082Sdim  HOWTO(R_SPARC_NONE,      0,0, 0,FALSE,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_NONE",    FALSE,0,0x00000000,TRUE),
181214082Sdim  HOWTO(R_SPARC_8,         0,0, 8,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_8",       FALSE,0,0x000000ff,TRUE),
182214082Sdim  HOWTO(R_SPARC_16,        0,1,16,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_16",      FALSE,0,0x0000ffff,TRUE),
183214082Sdim  HOWTO(R_SPARC_32,        0,2,32,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_32",      FALSE,0,0xffffffff,TRUE),
184214082Sdim  HOWTO(R_SPARC_DISP8,     0,0, 8,TRUE, 0,complain_overflow_signed,  bfd_elf_generic_reloc,  "R_SPARC_DISP8",   FALSE,0,0x000000ff,TRUE),
185214082Sdim  HOWTO(R_SPARC_DISP16,    0,1,16,TRUE, 0,complain_overflow_signed,  bfd_elf_generic_reloc,  "R_SPARC_DISP16",  FALSE,0,0x0000ffff,TRUE),
186214082Sdim  HOWTO(R_SPARC_DISP32,    0,2,32,TRUE, 0,complain_overflow_signed,  bfd_elf_generic_reloc,  "R_SPARC_DISP32",  FALSE,0,0xffffffff,TRUE),
187214082Sdim  HOWTO(R_SPARC_WDISP30,   2,2,30,TRUE, 0,complain_overflow_signed,  bfd_elf_generic_reloc,  "R_SPARC_WDISP30", FALSE,0,0x3fffffff,TRUE),
188214082Sdim  HOWTO(R_SPARC_WDISP22,   2,2,22,TRUE, 0,complain_overflow_signed,  bfd_elf_generic_reloc,  "R_SPARC_WDISP22", FALSE,0,0x003fffff,TRUE),
189214082Sdim  HOWTO(R_SPARC_HI22,     10,2,22,FALSE,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_HI22",    FALSE,0,0x003fffff,TRUE),
190214082Sdim  HOWTO(R_SPARC_22,        0,2,22,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_22",      FALSE,0,0x003fffff,TRUE),
191214082Sdim  HOWTO(R_SPARC_13,        0,2,13,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_13",      FALSE,0,0x00001fff,TRUE),
192214082Sdim  HOWTO(R_SPARC_LO10,      0,2,10,FALSE,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_LO10",    FALSE,0,0x000003ff,TRUE),
193214082Sdim  HOWTO(R_SPARC_GOT10,     0,2,10,FALSE,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_GOT10",   FALSE,0,0x000003ff,TRUE),
194214082Sdim  HOWTO(R_SPARC_GOT13,     0,2,13,FALSE,0,complain_overflow_signed,  bfd_elf_generic_reloc,  "R_SPARC_GOT13",   FALSE,0,0x00001fff,TRUE),
195214082Sdim  HOWTO(R_SPARC_GOT22,    10,2,22,FALSE,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_GOT22",   FALSE,0,0x003fffff,TRUE),
196214082Sdim  HOWTO(R_SPARC_PC10,      0,2,10,TRUE, 0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_PC10",    FALSE,0,0x000003ff,TRUE),
197214082Sdim  HOWTO(R_SPARC_PC22,     10,2,22,TRUE, 0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_PC22",    FALSE,0,0x003fffff,TRUE),
198214082Sdim  HOWTO(R_SPARC_WPLT30,    2,2,30,TRUE, 0,complain_overflow_signed,  bfd_elf_generic_reloc,  "R_SPARC_WPLT30",  FALSE,0,0x3fffffff,TRUE),
199214082Sdim  HOWTO(R_SPARC_COPY,      0,0,00,FALSE,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_COPY",    FALSE,0,0x00000000,TRUE),
200214082Sdim  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),
201214082Sdim  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),
202214082Sdim  HOWTO(R_SPARC_RELATIVE,  0,0,00,FALSE,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_RELATIVE",FALSE,0,0x00000000,TRUE),
203214082Sdim  HOWTO(R_SPARC_UA32,      0,2,32,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_UA32",    FALSE,0,0xffffffff,TRUE),
204214082Sdim  HOWTO(R_SPARC_PLT32,     0,2,32,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_PLT32",   FALSE,0,0xffffffff,TRUE),
205214082Sdim  HOWTO(R_SPARC_HIPLT22,   0,0,00,FALSE,0,complain_overflow_dont,    sparc_elf_notsup_reloc, "R_SPARC_HIPLT22",  FALSE,0,0x00000000,TRUE),
206214082Sdim  HOWTO(R_SPARC_LOPLT10,   0,0,00,FALSE,0,complain_overflow_dont,    sparc_elf_notsup_reloc, "R_SPARC_LOPLT10",  FALSE,0,0x00000000,TRUE),
207214082Sdim  HOWTO(R_SPARC_PCPLT32,   0,0,00,FALSE,0,complain_overflow_dont,    sparc_elf_notsup_reloc, "R_SPARC_PCPLT32",  FALSE,0,0x00000000,TRUE),
208214082Sdim  HOWTO(R_SPARC_PCPLT22,   0,0,00,FALSE,0,complain_overflow_dont,    sparc_elf_notsup_reloc, "R_SPARC_PCPLT22",  FALSE,0,0x00000000,TRUE),
209214082Sdim  HOWTO(R_SPARC_PCPLT10,   0,0,00,FALSE,0,complain_overflow_dont,    sparc_elf_notsup_reloc, "R_SPARC_PCPLT10",  FALSE,0,0x00000000,TRUE),
210214082Sdim  HOWTO(R_SPARC_10,        0,2,10,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_10",      FALSE,0,0x000003ff,TRUE),
211214082Sdim  HOWTO(R_SPARC_11,        0,2,11,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_11",      FALSE,0,0x000007ff,TRUE),
212214082Sdim  HOWTO(R_SPARC_64,        0,4,64,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_64",      FALSE,0,MINUS_ONE, TRUE),
213214082Sdim  HOWTO(R_SPARC_OLO10,     0,2,13,FALSE,0,complain_overflow_signed,  sparc_elf_notsup_reloc, "R_SPARC_OLO10",   FALSE,0,0x00001fff,TRUE),
214214082Sdim  HOWTO(R_SPARC_HH22,     42,2,22,FALSE,0,complain_overflow_unsigned,bfd_elf_generic_reloc,  "R_SPARC_HH22",    FALSE,0,0x003fffff,TRUE),
215214082Sdim  HOWTO(R_SPARC_HM10,     32,2,10,FALSE,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_HM10",    FALSE,0,0x000003ff,TRUE),
216214082Sdim  HOWTO(R_SPARC_LM22,     10,2,22,FALSE,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_LM22",    FALSE,0,0x003fffff,TRUE),
217214082Sdim  HOWTO(R_SPARC_PC_HH22,  42,2,22,TRUE, 0,complain_overflow_unsigned,bfd_elf_generic_reloc,  "R_SPARC_PC_HH22",    FALSE,0,0x003fffff,TRUE),
218214082Sdim  HOWTO(R_SPARC_PC_HM10,  32,2,10,TRUE, 0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_PC_HM10",    FALSE,0,0x000003ff,TRUE),
219214082Sdim  HOWTO(R_SPARC_PC_LM22,  10,2,22,TRUE, 0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_PC_LM22",    FALSE,0,0x003fffff,TRUE),
220214082Sdim  HOWTO(R_SPARC_WDISP16,   2,2,16,TRUE, 0,complain_overflow_signed,  sparc_elf_wdisp16_reloc,"R_SPARC_WDISP16", FALSE,0,0x00000000,TRUE),
221214082Sdim  HOWTO(R_SPARC_WDISP19,   2,2,19,TRUE, 0,complain_overflow_signed,  bfd_elf_generic_reloc,  "R_SPARC_WDISP19", FALSE,0,0x0007ffff,TRUE),
222214082Sdim  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),
223214082Sdim  HOWTO(R_SPARC_7,         0,2, 7,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_7",       FALSE,0,0x0000007f,TRUE),
224214082Sdim  HOWTO(R_SPARC_5,         0,2, 5,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_5",       FALSE,0,0x0000001f,TRUE),
225214082Sdim  HOWTO(R_SPARC_6,         0,2, 6,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_6",       FALSE,0,0x0000003f,TRUE),
226214082Sdim  HOWTO(R_SPARC_DISP64,    0,4,64,TRUE, 0,complain_overflow_signed,  bfd_elf_generic_reloc,  "R_SPARC_DISP64",  FALSE,0,MINUS_ONE, TRUE),
227214082Sdim  HOWTO(R_SPARC_PLT64,     0,4,64,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_PLT64",   FALSE,0,MINUS_ONE, TRUE),
228214082Sdim  HOWTO(R_SPARC_HIX22,     0,4, 0,FALSE,0,complain_overflow_bitfield,sparc_elf_hix22_reloc,  "R_SPARC_HIX22",   FALSE,0,MINUS_ONE, FALSE),
229214082Sdim  HOWTO(R_SPARC_LOX10,     0,4, 0,FALSE,0,complain_overflow_dont,    sparc_elf_lox10_reloc,  "R_SPARC_LOX10",   FALSE,0,MINUS_ONE, FALSE),
230214082Sdim  HOWTO(R_SPARC_H44,      22,2,22,FALSE,0,complain_overflow_unsigned,bfd_elf_generic_reloc,  "R_SPARC_H44",     FALSE,0,0x003fffff,FALSE),
231214082Sdim  HOWTO(R_SPARC_M44,      12,2,10,FALSE,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_M44",     FALSE,0,0x000003ff,FALSE),
232214082Sdim  HOWTO(R_SPARC_L44,       0,2,13,FALSE,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_L44",     FALSE,0,0x00000fff,FALSE),
233214082Sdim  HOWTO(R_SPARC_REGISTER,  0,4, 0,FALSE,0,complain_overflow_bitfield,sparc_elf_notsup_reloc, "R_SPARC_REGISTER",FALSE,0,MINUS_ONE, FALSE),
234214082Sdim  HOWTO(R_SPARC_UA64,        0,4,64,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_UA64",      FALSE,0,MINUS_ONE, TRUE),
235214082Sdim  HOWTO(R_SPARC_UA16,        0,1,16,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc,  "R_SPARC_UA16",      FALSE,0,0x0000ffff,TRUE),
236214082Sdim  HOWTO(R_SPARC_TLS_GD_HI22,10,2,22,FALSE,0,complain_overflow_dont,  bfd_elf_generic_reloc,  "R_SPARC_TLS_GD_HI22",FALSE,0,0x003fffff,TRUE),
237214082Sdim  HOWTO(R_SPARC_TLS_GD_LO10,0,2,10,FALSE,0,complain_overflow_dont,   bfd_elf_generic_reloc,  "R_SPARC_TLS_GD_LO10",FALSE,0,0x000003ff,TRUE),
238214082Sdim  HOWTO(R_SPARC_TLS_GD_ADD,0,0, 0,FALSE,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_TLS_GD_ADD",FALSE,0,0x00000000,TRUE),
239214082Sdim  HOWTO(R_SPARC_TLS_GD_CALL,2,2,30,TRUE,0,complain_overflow_signed,  bfd_elf_generic_reloc,  "R_SPARC_TLS_GD_CALL",FALSE,0,0x3fffffff,TRUE),
240214082Sdim  HOWTO(R_SPARC_TLS_LDM_HI22,10,2,22,FALSE,0,complain_overflow_dont, bfd_elf_generic_reloc,  "R_SPARC_TLS_LDM_HI22",FALSE,0,0x003fffff,TRUE),
241214082Sdim  HOWTO(R_SPARC_TLS_LDM_LO10,0,2,10,FALSE,0,complain_overflow_dont,  bfd_elf_generic_reloc,  "R_SPARC_TLS_LDM_LO10",FALSE,0,0x000003ff,TRUE),
242214082Sdim  HOWTO(R_SPARC_TLS_LDM_ADD,0,0, 0,FALSE,0,complain_overflow_dont,   bfd_elf_generic_reloc,  "R_SPARC_TLS_LDM_ADD",FALSE,0,0x00000000,TRUE),
243214082Sdim  HOWTO(R_SPARC_TLS_LDM_CALL,2,2,30,TRUE,0,complain_overflow_signed, bfd_elf_generic_reloc,  "R_SPARC_TLS_LDM_CALL",FALSE,0,0x3fffffff,TRUE),
244214082Sdim  HOWTO(R_SPARC_TLS_LDO_HIX22,0,2,0,FALSE,0,complain_overflow_bitfield,sparc_elf_hix22_reloc,"R_SPARC_TLS_LDO_HIX22",FALSE,0,0x003fffff, FALSE),
245214082Sdim  HOWTO(R_SPARC_TLS_LDO_LOX10,0,2,0,FALSE,0,complain_overflow_dont,  sparc_elf_lox10_reloc,  "R_SPARC_TLS_LDO_LOX10",FALSE,0,0x000003ff, FALSE),
246214082Sdim  HOWTO(R_SPARC_TLS_LDO_ADD,0,0, 0,FALSE,0,complain_overflow_dont,   bfd_elf_generic_reloc,  "R_SPARC_TLS_LDO_ADD",FALSE,0,0x00000000,TRUE),
247214082Sdim  HOWTO(R_SPARC_TLS_IE_HI22,10,2,22,FALSE,0,complain_overflow_dont,  bfd_elf_generic_reloc,  "R_SPARC_TLS_IE_HI22",FALSE,0,0x003fffff,TRUE),
248214082Sdim  HOWTO(R_SPARC_TLS_IE_LO10,0,2,10,FALSE,0,complain_overflow_dont,   bfd_elf_generic_reloc,  "R_SPARC_TLS_IE_LO10",FALSE,0,0x000003ff,TRUE),
249214082Sdim  HOWTO(R_SPARC_TLS_IE_LD,0,0, 0,FALSE,0,complain_overflow_dont,     bfd_elf_generic_reloc,  "R_SPARC_TLS_IE_LD",FALSE,0,0x00000000,TRUE),
250214082Sdim  HOWTO(R_SPARC_TLS_IE_LDX,0,0, 0,FALSE,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_TLS_IE_LDX",FALSE,0,0x00000000,TRUE),
251214082Sdim  HOWTO(R_SPARC_TLS_IE_ADD,0,0, 0,FALSE,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_TLS_IE_ADD",FALSE,0,0x00000000,TRUE),
252214082Sdim  HOWTO(R_SPARC_TLS_LE_HIX22,0,2,0,FALSE,0,complain_overflow_bitfield,sparc_elf_hix22_reloc, "R_SPARC_TLS_LE_HIX22",FALSE,0,0x003fffff, FALSE),
253214082Sdim  HOWTO(R_SPARC_TLS_LE_LOX10,0,2,0,FALSE,0,complain_overflow_dont,   sparc_elf_lox10_reloc,  "R_SPARC_TLS_LE_LOX10",FALSE,0,0x000003ff, FALSE),
254214082Sdim  HOWTO(R_SPARC_TLS_DTPMOD32,0,0, 0,FALSE,0,complain_overflow_dont,  bfd_elf_generic_reloc,  "R_SPARC_TLS_DTPMOD32",FALSE,0,0x00000000,TRUE),
255214082Sdim  HOWTO(R_SPARC_TLS_DTPMOD64,0,0, 0,FALSE,0,complain_overflow_dont,  bfd_elf_generic_reloc,  "R_SPARC_TLS_DTPMOD64",FALSE,0,0x00000000,TRUE),
256214082Sdim  HOWTO(R_SPARC_TLS_DTPOFF32,0,2,32,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc,"R_SPARC_TLS_DTPOFF32",FALSE,0,0xffffffff,TRUE),
257214082Sdim  HOWTO(R_SPARC_TLS_DTPOFF64,0,4,64,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc,"R_SPARC_TLS_DTPOFF64",FALSE,0,MINUS_ONE,TRUE),
258214082Sdim  HOWTO(R_SPARC_TLS_TPOFF32,0,0, 0,FALSE,0,complain_overflow_dont,   bfd_elf_generic_reloc,  "R_SPARC_TLS_TPOFF32",FALSE,0,0x00000000,TRUE),
259214082Sdim  HOWTO(R_SPARC_TLS_TPOFF64,0,0, 0,FALSE,0,complain_overflow_dont,   bfd_elf_generic_reloc,  "R_SPARC_TLS_TPOFF64",FALSE,0,0x00000000,TRUE)
260214082Sdim};
261214082Sdimstatic reloc_howto_type sparc_vtinherit_howto =
262214082Sdim  HOWTO (R_SPARC_GNU_VTINHERIT, 0,2,0,FALSE,0,complain_overflow_dont, NULL, "R_SPARC_GNU_VTINHERIT", FALSE,0, 0, FALSE);
263214082Sdimstatic reloc_howto_type sparc_vtentry_howto =
264214082Sdim  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);
265214082Sdimstatic reloc_howto_type sparc_rev32_howto =
266214082Sdim  HOWTO(R_SPARC_REV32, 0,2,32,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_REV32", FALSE,0,0xffffffff,TRUE);
267214082Sdim
268214082Sdimstruct elf_reloc_map {
269214082Sdim  bfd_reloc_code_real_type bfd_reloc_val;
270214082Sdim  unsigned char elf_reloc_val;
271214082Sdim};
272214082Sdim
273214082Sdimstatic const struct elf_reloc_map sparc_reloc_map[] =
274214082Sdim{
275214082Sdim  { BFD_RELOC_NONE, R_SPARC_NONE, },
276214082Sdim  { BFD_RELOC_16, R_SPARC_16, },
277214082Sdim  { BFD_RELOC_16_PCREL, R_SPARC_DISP16 },
278214082Sdim  { BFD_RELOC_8, R_SPARC_8 },
279214082Sdim  { BFD_RELOC_8_PCREL, R_SPARC_DISP8 },
280214082Sdim  { BFD_RELOC_CTOR, R_SPARC_64 },
281214082Sdim  { BFD_RELOC_32, R_SPARC_32 },
282214082Sdim  { BFD_RELOC_32_PCREL, R_SPARC_DISP32 },
283214082Sdim  { BFD_RELOC_HI22, R_SPARC_HI22 },
284214082Sdim  { BFD_RELOC_LO10, R_SPARC_LO10, },
285214082Sdim  { BFD_RELOC_32_PCREL_S2, R_SPARC_WDISP30 },
286214082Sdim  { BFD_RELOC_64_PCREL, R_SPARC_DISP64 },
287214082Sdim  { BFD_RELOC_SPARC22, R_SPARC_22 },
288214082Sdim  { BFD_RELOC_SPARC13, R_SPARC_13 },
289214082Sdim  { BFD_RELOC_SPARC_GOT10, R_SPARC_GOT10 },
290214082Sdim  { BFD_RELOC_SPARC_GOT13, R_SPARC_GOT13 },
291214082Sdim  { BFD_RELOC_SPARC_GOT22, R_SPARC_GOT22 },
292214082Sdim  { BFD_RELOC_SPARC_PC10, R_SPARC_PC10 },
293214082Sdim  { BFD_RELOC_SPARC_PC22, R_SPARC_PC22 },
294214082Sdim  { BFD_RELOC_SPARC_WPLT30, R_SPARC_WPLT30 },
295214082Sdim  { BFD_RELOC_SPARC_COPY, R_SPARC_COPY },
296214082Sdim  { BFD_RELOC_SPARC_GLOB_DAT, R_SPARC_GLOB_DAT },
297214082Sdim  { BFD_RELOC_SPARC_JMP_SLOT, R_SPARC_JMP_SLOT },
298214082Sdim  { BFD_RELOC_SPARC_RELATIVE, R_SPARC_RELATIVE },
299214082Sdim  { BFD_RELOC_SPARC_WDISP22, R_SPARC_WDISP22 },
300214082Sdim  { BFD_RELOC_SPARC_UA16, R_SPARC_UA16 },
301214082Sdim  { BFD_RELOC_SPARC_UA32, R_SPARC_UA32 },
302214082Sdim  { BFD_RELOC_SPARC_UA64, R_SPARC_UA64 },
303214082Sdim  { BFD_RELOC_SPARC_10, R_SPARC_10 },
304214082Sdim  { BFD_RELOC_SPARC_11, R_SPARC_11 },
305214082Sdim  { BFD_RELOC_SPARC_64, R_SPARC_64 },
306214082Sdim  { BFD_RELOC_SPARC_OLO10, R_SPARC_OLO10 },
307214082Sdim  { BFD_RELOC_SPARC_HH22, R_SPARC_HH22 },
308214082Sdim  { BFD_RELOC_SPARC_HM10, R_SPARC_HM10 },
309214082Sdim  { BFD_RELOC_SPARC_LM22, R_SPARC_LM22 },
310214082Sdim  { BFD_RELOC_SPARC_PC_HH22, R_SPARC_PC_HH22 },
311214082Sdim  { BFD_RELOC_SPARC_PC_HM10, R_SPARC_PC_HM10 },
312214082Sdim  { BFD_RELOC_SPARC_PC_LM22, R_SPARC_PC_LM22 },
313214082Sdim  { BFD_RELOC_SPARC_WDISP16, R_SPARC_WDISP16 },
314214082Sdim  { BFD_RELOC_SPARC_WDISP19, R_SPARC_WDISP19 },
315214082Sdim  { BFD_RELOC_SPARC_7, R_SPARC_7 },
316214082Sdim  { BFD_RELOC_SPARC_5, R_SPARC_5 },
317214082Sdim  { BFD_RELOC_SPARC_6, R_SPARC_6 },
318214082Sdim  { BFD_RELOC_SPARC_DISP64, R_SPARC_DISP64 },
319214082Sdim  { BFD_RELOC_SPARC_TLS_GD_HI22, R_SPARC_TLS_GD_HI22 },
320214082Sdim  { BFD_RELOC_SPARC_TLS_GD_LO10, R_SPARC_TLS_GD_LO10 },
321214082Sdim  { BFD_RELOC_SPARC_TLS_GD_ADD, R_SPARC_TLS_GD_ADD },
322214082Sdim  { BFD_RELOC_SPARC_TLS_GD_CALL, R_SPARC_TLS_GD_CALL },
323214082Sdim  { BFD_RELOC_SPARC_TLS_LDM_HI22, R_SPARC_TLS_LDM_HI22 },
324214082Sdim  { BFD_RELOC_SPARC_TLS_LDM_LO10, R_SPARC_TLS_LDM_LO10 },
325214082Sdim  { BFD_RELOC_SPARC_TLS_LDM_ADD, R_SPARC_TLS_LDM_ADD },
326214082Sdim  { BFD_RELOC_SPARC_TLS_LDM_CALL, R_SPARC_TLS_LDM_CALL },
327214082Sdim  { BFD_RELOC_SPARC_TLS_LDO_HIX22, R_SPARC_TLS_LDO_HIX22 },
328214082Sdim  { BFD_RELOC_SPARC_TLS_LDO_LOX10, R_SPARC_TLS_LDO_LOX10 },
329214082Sdim  { BFD_RELOC_SPARC_TLS_LDO_ADD, R_SPARC_TLS_LDO_ADD },
330214082Sdim  { BFD_RELOC_SPARC_TLS_IE_HI22, R_SPARC_TLS_IE_HI22 },
331214082Sdim  { BFD_RELOC_SPARC_TLS_IE_LO10, R_SPARC_TLS_IE_LO10 },
332214082Sdim  { BFD_RELOC_SPARC_TLS_IE_LD, R_SPARC_TLS_IE_LD },
333214082Sdim  { BFD_RELOC_SPARC_TLS_IE_LDX, R_SPARC_TLS_IE_LDX },
334214082Sdim  { BFD_RELOC_SPARC_TLS_IE_ADD, R_SPARC_TLS_IE_ADD },
335214082Sdim  { BFD_RELOC_SPARC_TLS_LE_HIX22, R_SPARC_TLS_LE_HIX22 },
336214082Sdim  { BFD_RELOC_SPARC_TLS_LE_LOX10, R_SPARC_TLS_LE_LOX10 },
337214082Sdim  { BFD_RELOC_SPARC_TLS_DTPMOD32, R_SPARC_TLS_DTPMOD32 },
338214082Sdim  { BFD_RELOC_SPARC_TLS_DTPMOD64, R_SPARC_TLS_DTPMOD64 },
339214082Sdim  { BFD_RELOC_SPARC_TLS_DTPOFF32, R_SPARC_TLS_DTPOFF32 },
340214082Sdim  { BFD_RELOC_SPARC_TLS_DTPOFF64, R_SPARC_TLS_DTPOFF64 },
341214082Sdim  { BFD_RELOC_SPARC_TLS_TPOFF32, R_SPARC_TLS_TPOFF32 },
342214082Sdim  { BFD_RELOC_SPARC_TLS_TPOFF64, R_SPARC_TLS_TPOFF64 },
343214082Sdim  { BFD_RELOC_SPARC_PLT32, R_SPARC_PLT32 },
344214082Sdim  { BFD_RELOC_SPARC_PLT64, R_SPARC_PLT64 },
345214082Sdim  { BFD_RELOC_SPARC_HIX22, R_SPARC_HIX22 },
346214082Sdim  { BFD_RELOC_SPARC_LOX10, R_SPARC_LOX10 },
347214082Sdim  { BFD_RELOC_SPARC_H44, R_SPARC_H44 },
348214082Sdim  { BFD_RELOC_SPARC_M44, R_SPARC_M44 },
349214082Sdim  { BFD_RELOC_SPARC_L44, R_SPARC_L44 },
350214082Sdim  { BFD_RELOC_SPARC_REGISTER, R_SPARC_REGISTER },
351214082Sdim  { BFD_RELOC_VTABLE_INHERIT, R_SPARC_GNU_VTINHERIT },
352214082Sdim  { BFD_RELOC_VTABLE_ENTRY, R_SPARC_GNU_VTENTRY },
353214082Sdim  { BFD_RELOC_SPARC_REV32, R_SPARC_REV32 },
354214082Sdim};
355214082Sdim
356214082Sdimreloc_howto_type *
357214082Sdim_bfd_sparc_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
358214082Sdim				  bfd_reloc_code_real_type code)
359214082Sdim{
360214082Sdim  unsigned int i;
361214082Sdim
362214082Sdim  switch (code)
363214082Sdim    {
364214082Sdim    case BFD_RELOC_VTABLE_INHERIT:
365214082Sdim      return &sparc_vtinherit_howto;
366214082Sdim
367214082Sdim    case BFD_RELOC_VTABLE_ENTRY:
368214082Sdim      return &sparc_vtentry_howto;
369214082Sdim
370214082Sdim    case BFD_RELOC_SPARC_REV32:
371214082Sdim      return &sparc_rev32_howto;
372214082Sdim
373214082Sdim    default:
374214082Sdim      for (i = 0;
375214082Sdim	   i < sizeof (sparc_reloc_map) / sizeof (struct elf_reloc_map);
376214082Sdim	   i++)
377214082Sdim	{
378214082Sdim	  if (sparc_reloc_map[i].bfd_reloc_val == code)
379214082Sdim	    return (_bfd_sparc_elf_howto_table
380214082Sdim		    + (int) sparc_reloc_map[i].elf_reloc_val);
381214082Sdim	}
382214082Sdim    }
383214082Sdim    bfd_set_error (bfd_error_bad_value);
384214082Sdim    return NULL;
385214082Sdim}
386214082Sdim
387214082Sdimreloc_howto_type *
388214634Sdim_bfd_sparc_elf_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
389214634Sdim				  const char *r_name)
390214634Sdim{
391214634Sdim  unsigned int i;
392214634Sdim
393214634Sdim  for (i = 0;
394214634Sdim       i < (sizeof (_bfd_sparc_elf_howto_table)
395214634Sdim	    / sizeof (_bfd_sparc_elf_howto_table[0]));
396214634Sdim       i++)
397214634Sdim    if (_bfd_sparc_elf_howto_table[i].name != NULL
398214634Sdim	&& strcasecmp (_bfd_sparc_elf_howto_table[i].name, r_name) == 0)
399214634Sdim      return &_bfd_sparc_elf_howto_table[i];
400214634Sdim
401214634Sdim  if (strcasecmp (sparc_vtinherit_howto.name, r_name) == 0)
402214634Sdim    return &sparc_vtinherit_howto;
403214634Sdim  if (strcasecmp (sparc_vtentry_howto.name, r_name) == 0)
404214634Sdim    return &sparc_vtentry_howto;
405214634Sdim  if (strcasecmp (sparc_rev32_howto.name, r_name) == 0)
406214634Sdim    return &sparc_rev32_howto;
407214634Sdim
408214634Sdim  return NULL;
409214634Sdim}
410214634Sdim
411214634Sdimreloc_howto_type *
412214082Sdim_bfd_sparc_elf_info_to_howto_ptr (unsigned int r_type)
413214082Sdim{
414214082Sdim  switch (r_type)
415214082Sdim    {
416214082Sdim    case R_SPARC_GNU_VTINHERIT:
417214082Sdim      return &sparc_vtinherit_howto;
418214082Sdim
419214082Sdim    case R_SPARC_GNU_VTENTRY:
420214082Sdim      return &sparc_vtentry_howto;
421214082Sdim
422214082Sdim    case R_SPARC_REV32:
423214082Sdim      return &sparc_rev32_howto;
424214082Sdim
425214082Sdim    default:
426214082Sdim      if (r_type >= (unsigned int) R_SPARC_max_std)
427214082Sdim	{
428214082Sdim	  (*_bfd_error_handler) (_("invalid relocation type %d"),
429214082Sdim				 (int) r_type);
430214082Sdim	  r_type = R_SPARC_NONE;
431214082Sdim	}
432214082Sdim      return &_bfd_sparc_elf_howto_table[r_type];
433214082Sdim    }
434214082Sdim}
435214082Sdim
436214082Sdim/* Both 32-bit and 64-bit sparc encode this in an identical manner,
437214082Sdim   so just take advantage of that.  */
438214082Sdim#define SPARC_ELF_R_TYPE(r_info)	\
439214082Sdim	((r_info) & 0xff)
440214082Sdim
441214082Sdimvoid
442214082Sdim_bfd_sparc_elf_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr,
443214082Sdim			      Elf_Internal_Rela *dst)
444214082Sdim{
445214082Sdim  unsigned int r_type = SPARC_ELF_R_TYPE (dst->r_info);
446214082Sdim
447214082Sdim  cache_ptr->howto = _bfd_sparc_elf_info_to_howto_ptr (r_type);
448214082Sdim}
449214082Sdim
450214082Sdim
451214082Sdim/* The nop opcode we use.  */
452214082Sdim#define SPARC_NOP 0x01000000
453214082Sdim
454214082Sdim#define SPARC_INSN_BYTES	4
455214082Sdim
456214082Sdim/* The SPARC linker needs to keep track of the number of relocs that it
457214082Sdim   decides to copy as dynamic relocs in check_relocs for each symbol.
458214082Sdim   This is so that it can later discard them if they are found to be
459214082Sdim   unnecessary.  We store the information in a field extending the
460214082Sdim   regular ELF linker hash table.  */
461214082Sdim
462214082Sdimstruct _bfd_sparc_elf_dyn_relocs
463214082Sdim{
464214082Sdim  struct _bfd_sparc_elf_dyn_relocs *next;
465214082Sdim
466214082Sdim  /* The input section of the reloc.  */
467214082Sdim  asection *sec;
468214082Sdim
469214082Sdim  /* Total number of relocs copied for the input section.  */
470214082Sdim  bfd_size_type count;
471214082Sdim
472214082Sdim  /* Number of pc-relative relocs copied for the input section.  */
473214082Sdim  bfd_size_type pc_count;
474214082Sdim};
475214082Sdim
476214082Sdim/* SPARC ELF linker hash entry.  */
477214082Sdim
478214082Sdimstruct _bfd_sparc_elf_link_hash_entry
479214082Sdim{
480214082Sdim  struct elf_link_hash_entry elf;
481214082Sdim
482214082Sdim  /* Track dynamic relocs copied for this symbol.  */
483214082Sdim  struct _bfd_sparc_elf_dyn_relocs *dyn_relocs;
484214082Sdim
485214082Sdim#define GOT_UNKNOWN     0
486214082Sdim#define GOT_NORMAL      1
487214082Sdim#define GOT_TLS_GD      2
488214082Sdim#define GOT_TLS_IE      3
489214082Sdim  unsigned char tls_type;
490214082Sdim};
491214082Sdim
492214082Sdim#define _bfd_sparc_elf_hash_entry(ent) ((struct _bfd_sparc_elf_link_hash_entry *)(ent))
493214082Sdim
494214082Sdimstruct _bfd_sparc_elf_obj_tdata
495214082Sdim{
496214082Sdim  struct elf_obj_tdata root;
497214082Sdim
498214082Sdim  /* tls_type for each local got entry.  */
499214082Sdim  char *local_got_tls_type;
500214082Sdim
501214082Sdim  /* TRUE if TLS GD relocs has been seen for this object.  */
502214082Sdim  bfd_boolean has_tlsgd;
503214082Sdim};
504214082Sdim
505214082Sdim#define _bfd_sparc_elf_tdata(abfd) \
506214082Sdim  ((struct _bfd_sparc_elf_obj_tdata *) (abfd)->tdata.any)
507214082Sdim
508214082Sdim#define _bfd_sparc_elf_local_got_tls_type(abfd) \
509214082Sdim  (_bfd_sparc_elf_tdata (abfd)->local_got_tls_type)
510214082Sdim
511214082Sdimbfd_boolean
512214082Sdim_bfd_sparc_elf_mkobject (bfd *abfd)
513214082Sdim{
514214082Sdim  if (abfd->tdata.any == NULL)
515214634Sdim    {
516214634Sdim      bfd_size_type amt = sizeof (struct _bfd_sparc_elf_obj_tdata);
517214634Sdim      abfd->tdata.any = bfd_zalloc (abfd, amt);
518214634Sdim      if (abfd->tdata.any == NULL)
519214634Sdim	return FALSE;
520214634Sdim    }
521214634Sdim  return bfd_elf_mkobject (abfd);
522214082Sdim}
523214082Sdim
524214082Sdimstatic void
525214082Sdimsparc_put_word_32 (bfd *bfd, bfd_vma val, void *ptr)
526214082Sdim{
527214082Sdim  bfd_put_32 (bfd, val, ptr);
528214082Sdim}
529214082Sdim
530214082Sdimstatic void
531214082Sdimsparc_put_word_64 (bfd *bfd, bfd_vma val, void *ptr)
532214082Sdim{
533214082Sdim  bfd_put_64 (bfd, val, ptr);
534214082Sdim}
535214082Sdim
536214082Sdimstatic void
537214634Sdimsparc_elf_append_rela (bfd *abfd, asection *s, Elf_Internal_Rela *rel)
538214082Sdim{
539214634Sdim  const struct elf_backend_data *bed;
540214634Sdim  bfd_byte *loc;
541214082Sdim
542214634Sdim  bed = get_elf_backend_data (abfd);
543214634Sdim  loc = s->contents + (s->reloc_count++ * bed->s->sizeof_rela);
544214634Sdim  bed->s->swap_reloca_out (abfd, rel, loc);
545214082Sdim}
546214082Sdim
547214082Sdimstatic bfd_vma
548214082Sdimsparc_elf_r_info_64 (Elf_Internal_Rela *in_rel ATTRIBUTE_UNUSED,
549214082Sdim		     bfd_vma index ATTRIBUTE_UNUSED,
550214082Sdim		     bfd_vma type ATTRIBUTE_UNUSED)
551214082Sdim{
552214082Sdim  return ELF64_R_INFO (index,
553214082Sdim		       (in_rel ?
554214082Sdim			ELF64_R_TYPE_INFO (ELF64_R_TYPE_DATA (in_rel->r_info),
555214082Sdim					   type) : type));
556214082Sdim}
557214082Sdim
558214082Sdimstatic bfd_vma
559214082Sdimsparc_elf_r_info_32 (Elf_Internal_Rela *in_rel ATTRIBUTE_UNUSED,
560214082Sdim		     bfd_vma index, bfd_vma type)
561214082Sdim{
562214082Sdim  return ELF32_R_INFO (index, type);
563214082Sdim}
564214082Sdim
565214082Sdimstatic bfd_vma
566214082Sdimsparc_elf_r_symndx_64 (bfd_vma r_info)
567214082Sdim{
568214082Sdim  bfd_vma r_symndx = ELF32_R_SYM (r_info);
569214082Sdim  return (r_symndx >> 24);
570214082Sdim}
571214082Sdim
572214082Sdimstatic bfd_vma
573214082Sdimsparc_elf_r_symndx_32 (bfd_vma r_info)
574214082Sdim{
575214082Sdim  return ELF32_R_SYM (r_info);
576214082Sdim}
577214082Sdim
578214082Sdim/* PLT/GOT stuff */
579214082Sdim
580214082Sdim#define PLT32_ENTRY_SIZE 12
581214082Sdim#define PLT32_HEADER_SIZE	(4 * PLT32_ENTRY_SIZE)
582214082Sdim
583214082Sdim/* The first four entries in a 32-bit procedure linkage table are reserved,
584214082Sdim   and the initial contents are unimportant (we zero them out).
585214082Sdim   Subsequent entries look like this.  See the SVR4 ABI SPARC
586214082Sdim   supplement to see how this works.  */
587214082Sdim
588214082Sdim/* sethi %hi(.-.plt0),%g1.  We fill in the address later.  */
589214082Sdim#define PLT32_ENTRY_WORD0 0x03000000
590214082Sdim/* b,a .plt0.  We fill in the offset later.  */
591214082Sdim#define PLT32_ENTRY_WORD1 0x30800000
592214082Sdim/* nop.  */
593214082Sdim#define PLT32_ENTRY_WORD2 SPARC_NOP
594214082Sdim
595214082Sdimstatic int
596214082Sdimsparc32_plt_entry_build (bfd *output_bfd, asection *splt, bfd_vma offset,
597214082Sdim			 bfd_vma max ATTRIBUTE_UNUSED,
598214082Sdim			 bfd_vma *r_offset)
599214082Sdim{
600214082Sdim      bfd_put_32 (output_bfd,
601214082Sdim		  PLT32_ENTRY_WORD0 + offset,
602214082Sdim		  splt->contents + offset);
603214082Sdim      bfd_put_32 (output_bfd,
604214082Sdim		  (PLT32_ENTRY_WORD1
605214082Sdim		   + (((- (offset + 4)) >> 2) & 0x3fffff)),
606214082Sdim		  splt->contents + offset + 4);
607214082Sdim      bfd_put_32 (output_bfd, (bfd_vma) PLT32_ENTRY_WORD2,
608214082Sdim		  splt->contents + offset + 8);
609214082Sdim
610214082Sdim      *r_offset = offset;
611214082Sdim
612214082Sdim      return offset / PLT32_ENTRY_SIZE - 4;
613214082Sdim}
614214082Sdim
615214082Sdim/* Both the headers and the entries are icache aligned.  */
616214082Sdim#define PLT64_ENTRY_SIZE	32
617214082Sdim#define PLT64_HEADER_SIZE	(4 * PLT64_ENTRY_SIZE)
618214082Sdim#define PLT64_LARGE_THRESHOLD	32768
619214082Sdim
620214082Sdimstatic int
621214082Sdimsparc64_plt_entry_build (bfd *output_bfd, asection *splt, bfd_vma offset,
622214082Sdim			 bfd_vma max, bfd_vma *r_offset)
623214082Sdim{
624214082Sdim  unsigned char *entry = splt->contents + offset;
625214082Sdim  const unsigned int nop = SPARC_NOP;
626214082Sdim  int index;
627214082Sdim
628214082Sdim  if (offset < (PLT64_LARGE_THRESHOLD * PLT64_ENTRY_SIZE))
629214082Sdim    {
630214082Sdim      unsigned int sethi, ba;
631214082Sdim
632214082Sdim      *r_offset = offset;
633214082Sdim
634214082Sdim      index = (offset / PLT64_ENTRY_SIZE);
635214082Sdim
636214082Sdim      sethi = 0x03000000 | (index * PLT64_ENTRY_SIZE);
637214082Sdim      ba = 0x30680000
638214082Sdim	| (((splt->contents + PLT64_ENTRY_SIZE) - (entry + 4)) / 4 & 0x7ffff);
639214082Sdim
640214082Sdim      bfd_put_32 (output_bfd, (bfd_vma) sethi, entry);
641214082Sdim      bfd_put_32 (output_bfd, (bfd_vma) ba,    entry + 4);
642214082Sdim      bfd_put_32 (output_bfd, (bfd_vma) nop,   entry + 8);
643214082Sdim      bfd_put_32 (output_bfd, (bfd_vma) nop,   entry + 12);
644214082Sdim      bfd_put_32 (output_bfd, (bfd_vma) nop,   entry + 16);
645214082Sdim      bfd_put_32 (output_bfd, (bfd_vma) nop,   entry + 20);
646214082Sdim      bfd_put_32 (output_bfd, (bfd_vma) nop,   entry + 24);
647214082Sdim      bfd_put_32 (output_bfd, (bfd_vma) nop,   entry + 28);
648214082Sdim    }
649214082Sdim  else
650214082Sdim    {
651214082Sdim      unsigned char *ptr;
652214082Sdim      unsigned int ldx;
653214082Sdim      int block, last_block, ofs, last_ofs, chunks_this_block;
654214082Sdim      const int insn_chunk_size = (6 * 4);
655214082Sdim      const int ptr_chunk_size = (1 * 8);
656214082Sdim      const int entries_per_block = 160;
657214082Sdim      const int block_size = entries_per_block * (insn_chunk_size
658214082Sdim						  + ptr_chunk_size);
659214082Sdim
660214082Sdim      /* Entries 32768 and higher are grouped into blocks of 160.
661214082Sdim	 The blocks are further subdivided into 160 sequences of
662214082Sdim	 6 instructions and 160 pointers.  If a block does not require
663214082Sdim	 the full 160 entries, let's say it requires N, then there
664214082Sdim	 will be N sequences of 6 instructions and N pointers.  */
665214082Sdim
666214082Sdim      offset -= (PLT64_LARGE_THRESHOLD * PLT64_ENTRY_SIZE);
667214082Sdim      max -= (PLT64_LARGE_THRESHOLD * PLT64_ENTRY_SIZE);
668214082Sdim
669214082Sdim      block = offset / block_size;
670214082Sdim      last_block = max / block_size;
671214082Sdim      if (block != last_block)
672214082Sdim	{
673214082Sdim	  chunks_this_block = 160;
674214082Sdim	}
675214082Sdim      else
676214082Sdim	{
677214082Sdim	  last_ofs = max % block_size;
678214082Sdim	  chunks_this_block = last_ofs / (insn_chunk_size + ptr_chunk_size);
679214082Sdim	}
680214082Sdim
681214082Sdim      ofs = offset % block_size;
682214082Sdim
683214082Sdim      index = (PLT64_LARGE_THRESHOLD +
684214082Sdim	       (block * 160) +
685214082Sdim	       (ofs / insn_chunk_size));
686214082Sdim
687214082Sdim      ptr = splt->contents
688214082Sdim	+ (PLT64_LARGE_THRESHOLD * PLT64_ENTRY_SIZE)
689214082Sdim	+ (block * block_size)
690214082Sdim	+ (chunks_this_block * insn_chunk_size)
691214082Sdim	+ (ofs / insn_chunk_size) * ptr_chunk_size;
692214082Sdim
693214082Sdim      *r_offset = (bfd_vma) (ptr - splt->contents);
694214082Sdim
695214082Sdim      ldx = 0xc25be000 | ((ptr - (entry+4)) & 0x1fff);
696214082Sdim
697214082Sdim      /* mov %o7,%g5
698214082Sdim	 call .+8
699214082Sdim	 nop
700214082Sdim	 ldx [%o7+P],%g1
701214082Sdim	 jmpl %o7+%g1,%g1
702214082Sdim	 mov %g5,%o7  */
703214082Sdim      bfd_put_32 (output_bfd, (bfd_vma) 0x8a10000f, entry);
704214082Sdim      bfd_put_32 (output_bfd, (bfd_vma) 0x40000002, entry + 4);
705214082Sdim      bfd_put_32 (output_bfd, (bfd_vma) SPARC_NOP,  entry + 8);
706214082Sdim      bfd_put_32 (output_bfd, (bfd_vma) ldx,        entry + 12);
707214082Sdim      bfd_put_32 (output_bfd, (bfd_vma) 0x83c3c001, entry + 16);
708214082Sdim      bfd_put_32 (output_bfd, (bfd_vma) 0x9e100005, entry + 20);
709214082Sdim
710214082Sdim      bfd_put_64 (output_bfd, (bfd_vma) (splt->contents - (entry + 4)), ptr);
711214082Sdim    }
712214082Sdim
713214082Sdim  return index - 4;
714214082Sdim}
715214082Sdim
716214082Sdim/* The format of the first PLT entry in a VxWorks executable.  */
717214082Sdimstatic const bfd_vma sparc_vxworks_exec_plt0_entry[] =
718214082Sdim  {
719214082Sdim    0x05000000,	/* sethi  %hi(_GLOBAL_OFFSET_TABLE_+8), %g2 */
720214082Sdim    0x8410a000,	/* or     %g2, %lo(_GLOBAL_OFFSET_TABLE_+8), %g2 */
721214082Sdim    0xc4008000,	/* ld     [ %g2 ], %g2 */
722214082Sdim    0x81c08000,	/* jmp    %g2 */
723214082Sdim    0x01000000	/* nop */
724214082Sdim  };
725214082Sdim
726214082Sdim/* The format of subsequent PLT entries.  */
727214082Sdimstatic const bfd_vma sparc_vxworks_exec_plt_entry[] =
728214082Sdim  {
729214082Sdim    0x03000000,	/* sethi  %hi(_GLOBAL_OFFSET_TABLE_+f@got), %g1 */
730214082Sdim    0x82106000,	/* or     %g1, %lo(_GLOBAL_OFFSET_TABLE_+f@got), %g1 */
731214082Sdim    0xc2004000,	/* ld     [ %g1 ], %g1 */
732214082Sdim    0x81c04000,	/* jmp    %g1 */
733214082Sdim    0x01000000,	/* nop */
734214082Sdim    0x03000000,	/* sethi  %hi(f@pltindex), %g1 */
735214082Sdim    0x10800000,	/* b      _PLT_resolve */
736214082Sdim    0x82106000	/* or     %g1, %lo(f@pltindex), %g1 */
737214082Sdim  };
738214082Sdim
739214082Sdim/* The format of the first PLT entry in a VxWorks shared object.  */
740214082Sdimstatic const bfd_vma sparc_vxworks_shared_plt0_entry[] =
741214082Sdim  {
742214082Sdim    0xc405e008,	/* ld     [ %l7 + 8 ], %g2 */
743214082Sdim    0x81c08000,	/* jmp    %g2 */
744214082Sdim    0x01000000	/* nop */
745214082Sdim  };
746214082Sdim
747214082Sdim/* The format of subsequent PLT entries.  */
748214082Sdimstatic const bfd_vma sparc_vxworks_shared_plt_entry[] =
749214082Sdim  {
750214082Sdim    0x03000000,	/* sethi  %hi(f@got), %g1 */
751214082Sdim    0x82106000,	/* or     %g1, %lo(f@got), %g1 */
752214082Sdim    0xc205c001,	/* ld     [ %l7 + %g1 ], %g1 */
753214082Sdim    0x81c04000,	/* jmp    %g1 */
754214082Sdim    0x01000000,	/* nop */
755214082Sdim    0x03000000,	/* sethi  %hi(f@pltindex), %g1 */
756214082Sdim    0x10800000,	/* b      _PLT_resolve */
757214082Sdim    0x82106000	/* or     %g1, %lo(f@pltindex), %g1 */
758214082Sdim  };
759214082Sdim
760214082Sdim#define SPARC_ELF_PUT_WORD(htab, bfd, val, ptr)	\
761214082Sdim	htab->put_word(bfd, val, ptr)
762214082Sdim
763214082Sdim#define SPARC_ELF_R_INFO(htab, in_rel, index, type)	\
764214082Sdim	htab->r_info(in_rel, index, type)
765214082Sdim
766214082Sdim#define SPARC_ELF_R_SYMNDX(htab, r_info)	\
767214082Sdim	htab->r_symndx(r_info)
768214082Sdim
769214082Sdim#define SPARC_ELF_WORD_BYTES(htab)	\
770214082Sdim	htab->bytes_per_word
771214082Sdim
772214082Sdim#define SPARC_ELF_RELA_BYTES(htab)	\
773214082Sdim	htab->bytes_per_rela
774214082Sdim
775214082Sdim#define SPARC_ELF_DTPOFF_RELOC(htab)	\
776214082Sdim	htab->dtpoff_reloc
777214082Sdim
778214082Sdim#define SPARC_ELF_DTPMOD_RELOC(htab)	\
779214082Sdim	htab->dtpmod_reloc
780214082Sdim
781214082Sdim#define SPARC_ELF_TPOFF_RELOC(htab)	\
782214082Sdim	htab->tpoff_reloc
783214082Sdim
784214082Sdim#define SPARC_ELF_BUILD_PLT_ENTRY(htab, obfd, splt, off, max, r_off) \
785214082Sdim	htab->build_plt_entry (obfd, splt, off, max, r_off)
786214082Sdim
787214082Sdim/* Create an entry in an SPARC ELF linker hash table.  */
788214082Sdim
789214082Sdimstatic struct bfd_hash_entry *
790214082Sdimlink_hash_newfunc (struct bfd_hash_entry *entry,
791214082Sdim		   struct bfd_hash_table *table, const char *string)
792214082Sdim{
793214082Sdim  /* Allocate the structure if it has not already been allocated by a
794214082Sdim     subclass.  */
795214082Sdim  if (entry == NULL)
796214082Sdim    {
797214082Sdim      entry = bfd_hash_allocate (table,
798214082Sdim				 sizeof (struct _bfd_sparc_elf_link_hash_entry));
799214082Sdim      if (entry == NULL)
800214082Sdim	return entry;
801214082Sdim    }
802214082Sdim
803214082Sdim  /* Call the allocation method of the superclass.  */
804214082Sdim  entry = _bfd_elf_link_hash_newfunc (entry, table, string);
805214082Sdim  if (entry != NULL)
806214082Sdim    {
807214082Sdim      struct _bfd_sparc_elf_link_hash_entry *eh;
808214082Sdim
809214082Sdim      eh = (struct _bfd_sparc_elf_link_hash_entry *) entry;
810214082Sdim      eh->dyn_relocs = NULL;
811214082Sdim      eh->tls_type = GOT_UNKNOWN;
812214082Sdim    }
813214082Sdim
814214082Sdim  return entry;
815214082Sdim}
816214082Sdim
817214082Sdim/* The name of the dynamic interpreter.  This is put in the .interp
818214082Sdim   section.  */
819214082Sdim
820214082Sdim#define ELF32_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1"
821214082Sdim#define ELF64_DYNAMIC_INTERPRETER "/usr/lib/sparcv9/ld.so.1"
822214082Sdim
823214082Sdim/* Create a SPARC ELF linker hash table.  */
824214082Sdim
825214082Sdimstruct bfd_link_hash_table *
826214082Sdim_bfd_sparc_elf_link_hash_table_create (bfd *abfd)
827214082Sdim{
828214082Sdim  struct _bfd_sparc_elf_link_hash_table *ret;
829214082Sdim  bfd_size_type amt = sizeof (struct _bfd_sparc_elf_link_hash_table);
830214082Sdim
831214082Sdim  ret = (struct _bfd_sparc_elf_link_hash_table *) bfd_zmalloc (amt);
832214082Sdim  if (ret == NULL)
833214082Sdim    return NULL;
834214082Sdim
835214082Sdim  if (ABI_64_P (abfd))
836214082Sdim    {
837214082Sdim      ret->put_word = sparc_put_word_64;
838214082Sdim      ret->r_info = sparc_elf_r_info_64;
839214082Sdim      ret->r_symndx = sparc_elf_r_symndx_64;
840214082Sdim      ret->dtpoff_reloc = R_SPARC_TLS_DTPOFF64;
841214082Sdim      ret->dtpmod_reloc = R_SPARC_TLS_DTPMOD64;
842214082Sdim      ret->tpoff_reloc = R_SPARC_TLS_TPOFF64;
843214082Sdim      ret->word_align_power = 3;
844214082Sdim      ret->align_power_max = 4;
845214082Sdim      ret->bytes_per_word = 8;
846214082Sdim      ret->bytes_per_rela = sizeof (Elf64_External_Rela);
847214082Sdim      ret->dynamic_interpreter = ELF64_DYNAMIC_INTERPRETER;
848214082Sdim      ret->dynamic_interpreter_size = sizeof ELF64_DYNAMIC_INTERPRETER;
849214082Sdim    }
850214082Sdim  else
851214082Sdim    {
852214082Sdim      ret->put_word = sparc_put_word_32;
853214082Sdim      ret->r_info = sparc_elf_r_info_32;
854214082Sdim      ret->r_symndx = sparc_elf_r_symndx_32;
855214082Sdim      ret->dtpoff_reloc = R_SPARC_TLS_DTPOFF32;
856214082Sdim      ret->dtpmod_reloc = R_SPARC_TLS_DTPMOD32;
857214082Sdim      ret->tpoff_reloc = R_SPARC_TLS_TPOFF32;
858214082Sdim      ret->word_align_power = 2;
859214082Sdim      ret->align_power_max = 3;
860214082Sdim      ret->bytes_per_word = 4;
861214082Sdim      ret->bytes_per_rela = sizeof (Elf32_External_Rela);
862214082Sdim      ret->dynamic_interpreter = ELF32_DYNAMIC_INTERPRETER;
863214082Sdim      ret->dynamic_interpreter_size = sizeof ELF32_DYNAMIC_INTERPRETER;
864214082Sdim    }
865214082Sdim
866214082Sdim  if (!_bfd_elf_link_hash_table_init (&ret->elf, abfd, link_hash_newfunc,
867214082Sdim				      sizeof (struct _bfd_sparc_elf_link_hash_entry)))
868214082Sdim    {
869214082Sdim      free (ret);
870214082Sdim      return NULL;
871214082Sdim    }
872214082Sdim
873214082Sdim  return &ret->elf.root;
874214082Sdim}
875214082Sdim
876214082Sdim/* Create .got and .rela.got sections in DYNOBJ, and set up
877214082Sdim   shortcuts to them in our hash table.  */
878214082Sdim
879214082Sdimstatic bfd_boolean
880214082Sdimcreate_got_section (bfd *dynobj, struct bfd_link_info *info)
881214082Sdim{
882214082Sdim  struct _bfd_sparc_elf_link_hash_table *htab;
883214082Sdim
884214082Sdim  if (! _bfd_elf_create_got_section (dynobj, info))
885214082Sdim    return FALSE;
886214082Sdim
887214082Sdim  htab = _bfd_sparc_elf_hash_table (info);
888214082Sdim  htab->sgot = bfd_get_section_by_name (dynobj, ".got");
889214082Sdim  BFD_ASSERT (htab->sgot != NULL);
890214082Sdim
891214082Sdim  htab->srelgot = bfd_make_section_with_flags (dynobj, ".rela.got",
892214082Sdim					       SEC_ALLOC
893214082Sdim					       | SEC_LOAD
894214082Sdim					       | SEC_HAS_CONTENTS
895214082Sdim					       | SEC_IN_MEMORY
896214082Sdim					       | SEC_LINKER_CREATED
897214082Sdim					       | SEC_READONLY);
898214082Sdim  if (htab->srelgot == NULL
899214082Sdim      || ! bfd_set_section_alignment (dynobj, htab->srelgot,
900214082Sdim				      htab->word_align_power))
901214082Sdim    return FALSE;
902214082Sdim
903214082Sdim  if (htab->is_vxworks)
904214082Sdim    {
905214082Sdim      htab->sgotplt = bfd_get_section_by_name (dynobj, ".got.plt");
906214082Sdim      if (!htab->sgotplt)
907214082Sdim	return FALSE;
908214082Sdim    }
909214082Sdim
910214082Sdim  return TRUE;
911214082Sdim}
912214082Sdim
913214082Sdim/* Create .plt, .rela.plt, .got, .rela.got, .dynbss, and
914214082Sdim   .rela.bss sections in DYNOBJ, and set up shortcuts to them in our
915214082Sdim   hash table.  */
916214082Sdim
917214082Sdimbfd_boolean
918214082Sdim_bfd_sparc_elf_create_dynamic_sections (bfd *dynobj,
919214082Sdim					struct bfd_link_info *info)
920214082Sdim{
921214082Sdim  struct _bfd_sparc_elf_link_hash_table *htab;
922214082Sdim
923214082Sdim  htab = _bfd_sparc_elf_hash_table (info);
924214082Sdim  if (!htab->sgot && !create_got_section (dynobj, info))
925214082Sdim    return FALSE;
926214082Sdim
927214082Sdim  if (!_bfd_elf_create_dynamic_sections (dynobj, info))
928214082Sdim    return FALSE;
929214082Sdim
930214082Sdim  htab->splt = bfd_get_section_by_name (dynobj, ".plt");
931214082Sdim  htab->srelplt = bfd_get_section_by_name (dynobj, ".rela.plt");
932214082Sdim  htab->sdynbss = bfd_get_section_by_name (dynobj, ".dynbss");
933214082Sdim  if (!info->shared)
934214082Sdim    htab->srelbss = bfd_get_section_by_name (dynobj, ".rela.bss");
935214082Sdim
936214082Sdim  if (htab->is_vxworks)
937214082Sdim    {
938214082Sdim      if (!elf_vxworks_create_dynamic_sections (dynobj, info, &htab->srelplt2))
939214082Sdim	return FALSE;
940214082Sdim      if (info->shared)
941214082Sdim	{
942214082Sdim	  htab->plt_header_size
943214082Sdim	    = 4 * ARRAY_SIZE (sparc_vxworks_shared_plt0_entry);
944214082Sdim	  htab->plt_entry_size
945214082Sdim	    = 4 * ARRAY_SIZE (sparc_vxworks_shared_plt_entry);
946214082Sdim	}
947214082Sdim      else
948214082Sdim	{
949214082Sdim	  htab->plt_header_size
950214082Sdim	    = 4 * ARRAY_SIZE (sparc_vxworks_exec_plt0_entry);
951214082Sdim	  htab->plt_entry_size
952214082Sdim	    = 4 * ARRAY_SIZE (sparc_vxworks_exec_plt_entry);
953214082Sdim	}
954214082Sdim    }
955214082Sdim  else
956214082Sdim    {
957214082Sdim      if (ABI_64_P (dynobj))
958214082Sdim	{
959214082Sdim	  htab->build_plt_entry = sparc64_plt_entry_build;
960214082Sdim	  htab->plt_header_size = PLT64_HEADER_SIZE;
961214082Sdim	  htab->plt_entry_size = PLT64_ENTRY_SIZE;
962214082Sdim	}
963214082Sdim      else
964214082Sdim	{
965214082Sdim	  htab->build_plt_entry = sparc32_plt_entry_build;
966214082Sdim	  htab->plt_header_size = PLT32_HEADER_SIZE;
967214082Sdim	  htab->plt_entry_size = PLT32_ENTRY_SIZE;
968214082Sdim	}
969214082Sdim    }
970214082Sdim
971214082Sdim  if (!htab->splt || !htab->srelplt || !htab->sdynbss
972214082Sdim      || (!info->shared && !htab->srelbss))
973214082Sdim    abort ();
974214082Sdim
975214082Sdim  return TRUE;
976214082Sdim}
977214082Sdim
978214082Sdim/* Copy the extra info we tack onto an elf_link_hash_entry.  */
979214082Sdim
980214082Sdimvoid
981214082Sdim_bfd_sparc_elf_copy_indirect_symbol (struct bfd_link_info *info,
982214082Sdim				     struct elf_link_hash_entry *dir,
983214082Sdim				     struct elf_link_hash_entry *ind)
984214082Sdim{
985214082Sdim  struct _bfd_sparc_elf_link_hash_entry *edir, *eind;
986214082Sdim
987214082Sdim  edir = (struct _bfd_sparc_elf_link_hash_entry *) dir;
988214082Sdim  eind = (struct _bfd_sparc_elf_link_hash_entry *) ind;
989214082Sdim
990214082Sdim  if (eind->dyn_relocs != NULL)
991214082Sdim    {
992214082Sdim      if (edir->dyn_relocs != NULL)
993214082Sdim	{
994214082Sdim	  struct _bfd_sparc_elf_dyn_relocs **pp;
995214082Sdim	  struct _bfd_sparc_elf_dyn_relocs *p;
996214082Sdim
997214082Sdim	  /* Add reloc counts against the indirect sym to the direct sym
998214082Sdim	     list.  Merge any entries against the same section.  */
999214082Sdim	  for (pp = &eind->dyn_relocs; (p = *pp) != NULL; )
1000214082Sdim	    {
1001214082Sdim	      struct _bfd_sparc_elf_dyn_relocs *q;
1002214082Sdim
1003214082Sdim	      for (q = edir->dyn_relocs; q != NULL; q = q->next)
1004214082Sdim		if (q->sec == p->sec)
1005214082Sdim		  {
1006214082Sdim		    q->pc_count += p->pc_count;
1007214082Sdim		    q->count += p->count;
1008214082Sdim		    *pp = p->next;
1009214082Sdim		    break;
1010214082Sdim		  }
1011214082Sdim	      if (q == NULL)
1012214082Sdim		pp = &p->next;
1013214082Sdim	    }
1014214082Sdim	  *pp = edir->dyn_relocs;
1015214082Sdim	}
1016214082Sdim
1017214082Sdim      edir->dyn_relocs = eind->dyn_relocs;
1018214082Sdim      eind->dyn_relocs = NULL;
1019214082Sdim    }
1020214082Sdim
1021214082Sdim  if (ind->root.type == bfd_link_hash_indirect
1022214082Sdim      && dir->got.refcount <= 0)
1023214082Sdim    {
1024214082Sdim      edir->tls_type = eind->tls_type;
1025214082Sdim      eind->tls_type = GOT_UNKNOWN;
1026214082Sdim    }
1027214082Sdim  _bfd_elf_link_hash_copy_indirect (info, dir, ind);
1028214082Sdim}
1029214082Sdim
1030214082Sdimstatic int
1031214082Sdimsparc_elf_tls_transition (struct bfd_link_info *info, bfd *abfd,
1032214082Sdim			  int r_type, int is_local)
1033214082Sdim{
1034214082Sdim  if (! ABI_64_P (abfd)
1035214082Sdim      && r_type == R_SPARC_TLS_GD_HI22
1036214082Sdim      && ! _bfd_sparc_elf_tdata (abfd)->has_tlsgd)
1037214082Sdim    r_type = R_SPARC_REV32;
1038214082Sdim
1039214082Sdim  if (info->shared)
1040214082Sdim    return r_type;
1041214082Sdim
1042214082Sdim  switch (r_type)
1043214082Sdim    {
1044214082Sdim    case R_SPARC_TLS_GD_HI22:
1045214082Sdim      if (is_local)
1046214082Sdim	return R_SPARC_TLS_LE_HIX22;
1047214082Sdim      return R_SPARC_TLS_IE_HI22;
1048214082Sdim    case R_SPARC_TLS_GD_LO10:
1049214082Sdim      if (is_local)
1050214082Sdim	return R_SPARC_TLS_LE_LOX10;
1051214082Sdim      return R_SPARC_TLS_IE_LO10;
1052214082Sdim    case R_SPARC_TLS_IE_HI22:
1053214082Sdim      if (is_local)
1054214082Sdim	return R_SPARC_TLS_LE_HIX22;
1055214082Sdim      return r_type;
1056214082Sdim    case R_SPARC_TLS_IE_LO10:
1057214082Sdim      if (is_local)
1058214082Sdim	return R_SPARC_TLS_LE_LOX10;
1059214082Sdim      return r_type;
1060214082Sdim    case R_SPARC_TLS_LDM_HI22:
1061214082Sdim      return R_SPARC_TLS_LE_HIX22;
1062214082Sdim    case R_SPARC_TLS_LDM_LO10:
1063214082Sdim      return R_SPARC_TLS_LE_LOX10;
1064214082Sdim    }
1065214082Sdim
1066214082Sdim  return r_type;
1067214082Sdim}
1068214082Sdim
1069214082Sdim/* Look through the relocs for a section during the first phase, and
1070214082Sdim   allocate space in the global offset table or procedure linkage
1071214082Sdim   table.  */
1072214082Sdim
1073214082Sdimbfd_boolean
1074214082Sdim_bfd_sparc_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
1075214082Sdim			     asection *sec, const Elf_Internal_Rela *relocs)
1076214082Sdim{
1077214082Sdim  struct _bfd_sparc_elf_link_hash_table *htab;
1078214082Sdim  Elf_Internal_Shdr *symtab_hdr;
1079214082Sdim  struct elf_link_hash_entry **sym_hashes;
1080214082Sdim  bfd_vma *local_got_offsets;
1081214082Sdim  const Elf_Internal_Rela *rel;
1082214082Sdim  const Elf_Internal_Rela *rel_end;
1083214082Sdim  asection *sreloc;
1084214082Sdim  int num_relocs;
1085214082Sdim  bfd_boolean checked_tlsgd = FALSE;
1086214082Sdim
1087214082Sdim  if (info->relocatable)
1088214082Sdim    return TRUE;
1089214082Sdim
1090214082Sdim  htab = _bfd_sparc_elf_hash_table (info);
1091214082Sdim  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
1092214082Sdim  sym_hashes = elf_sym_hashes (abfd);
1093214082Sdim  local_got_offsets = elf_local_got_offsets (abfd);
1094214082Sdim
1095214082Sdim  sreloc = NULL;
1096214082Sdim
1097214082Sdim  if (ABI_64_P (abfd))
1098214082Sdim    num_relocs = NUM_SHDR_ENTRIES (& elf_section_data (sec)->rel_hdr);
1099214082Sdim  else
1100214082Sdim    num_relocs = sec->reloc_count;
1101214082Sdim  rel_end = relocs + num_relocs;
1102214082Sdim  for (rel = relocs; rel < rel_end; rel++)
1103214082Sdim    {
1104214082Sdim      unsigned int r_type;
1105214082Sdim      unsigned long r_symndx;
1106214082Sdim      struct elf_link_hash_entry *h;
1107214082Sdim
1108214082Sdim      r_symndx = SPARC_ELF_R_SYMNDX (htab, rel->r_info);
1109214082Sdim      r_type = SPARC_ELF_R_TYPE (rel->r_info);
1110214082Sdim
1111214082Sdim      if (r_symndx >= NUM_SHDR_ENTRIES (symtab_hdr))
1112214082Sdim	{
1113214082Sdim	  (*_bfd_error_handler) (_("%B: bad symbol index: %d"),
1114214082Sdim				 abfd, r_symndx);
1115214082Sdim	  return FALSE;
1116214082Sdim	}
1117214082Sdim
1118214082Sdim      if (r_symndx < symtab_hdr->sh_info)
1119214082Sdim	h = NULL;
1120214082Sdim      else
1121214082Sdim	{
1122214082Sdim	  h = sym_hashes[r_symndx - symtab_hdr->sh_info];
1123214082Sdim	  while (h->root.type == bfd_link_hash_indirect
1124214082Sdim		 || h->root.type == bfd_link_hash_warning)
1125214082Sdim	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
1126214082Sdim	}
1127214082Sdim
1128214082Sdim      /* Compatibility with old R_SPARC_REV32 reloc conflicting
1129214082Sdim	 with R_SPARC_TLS_GD_HI22.  */
1130214082Sdim      if (! ABI_64_P (abfd) && ! checked_tlsgd)
1131214082Sdim	switch (r_type)
1132214082Sdim	  {
1133214082Sdim	  case R_SPARC_TLS_GD_HI22:
1134214082Sdim	    {
1135214082Sdim	      const Elf_Internal_Rela *relt;
1136214082Sdim
1137214082Sdim	      for (relt = rel + 1; relt < rel_end; relt++)
1138214082Sdim		if (ELF32_R_TYPE (relt->r_info) == R_SPARC_TLS_GD_LO10
1139214082Sdim		    || ELF32_R_TYPE (relt->r_info) == R_SPARC_TLS_GD_ADD
1140214082Sdim		    || ELF32_R_TYPE (relt->r_info) == R_SPARC_TLS_GD_CALL)
1141214082Sdim		  break;
1142214082Sdim	      checked_tlsgd = TRUE;
1143214082Sdim	      _bfd_sparc_elf_tdata (abfd)->has_tlsgd = relt < rel_end;
1144214082Sdim	    }
1145214082Sdim	    break;
1146214082Sdim	  case R_SPARC_TLS_GD_LO10:
1147214082Sdim	  case R_SPARC_TLS_GD_ADD:
1148214082Sdim	  case R_SPARC_TLS_GD_CALL:
1149214082Sdim	    checked_tlsgd = TRUE;
1150214082Sdim	    _bfd_sparc_elf_tdata (abfd)->has_tlsgd = TRUE;
1151214082Sdim	    break;
1152214082Sdim	  }
1153214082Sdim
1154214082Sdim      r_type = sparc_elf_tls_transition (info, abfd, r_type, h == NULL);
1155214082Sdim      switch (r_type)
1156214082Sdim	{
1157214082Sdim	case R_SPARC_TLS_LDM_HI22:
1158214082Sdim	case R_SPARC_TLS_LDM_LO10:
1159214082Sdim	  htab->tls_ldm_got.refcount += 1;
1160214082Sdim	  break;
1161214082Sdim
1162214082Sdim	case R_SPARC_TLS_LE_HIX22:
1163214082Sdim	case R_SPARC_TLS_LE_LOX10:
1164214082Sdim	  if (info->shared)
1165214082Sdim	    goto r_sparc_plt32;
1166214082Sdim	  break;
1167214082Sdim
1168214082Sdim	case R_SPARC_TLS_IE_HI22:
1169214082Sdim	case R_SPARC_TLS_IE_LO10:
1170214082Sdim	  if (info->shared)
1171214082Sdim	    info->flags |= DF_STATIC_TLS;
1172214082Sdim	  /* Fall through */
1173214082Sdim
1174214082Sdim	case R_SPARC_GOT10:
1175214082Sdim	case R_SPARC_GOT13:
1176214082Sdim	case R_SPARC_GOT22:
1177214082Sdim	case R_SPARC_TLS_GD_HI22:
1178214082Sdim	case R_SPARC_TLS_GD_LO10:
1179214082Sdim	  /* This symbol requires a global offset table entry.  */
1180214082Sdim	  {
1181214082Sdim	    int tls_type, old_tls_type;
1182214082Sdim
1183214082Sdim	    switch (r_type)
1184214082Sdim	      {
1185214082Sdim	      default:
1186214082Sdim	      case R_SPARC_GOT10:
1187214082Sdim	      case R_SPARC_GOT13:
1188214082Sdim	      case R_SPARC_GOT22:
1189214082Sdim		tls_type = GOT_NORMAL;
1190214082Sdim		break;
1191214082Sdim	      case R_SPARC_TLS_GD_HI22:
1192214082Sdim	      case R_SPARC_TLS_GD_LO10:
1193214082Sdim		tls_type = GOT_TLS_GD;
1194214082Sdim		break;
1195214082Sdim	      case R_SPARC_TLS_IE_HI22:
1196214082Sdim	      case R_SPARC_TLS_IE_LO10:
1197214082Sdim		tls_type = GOT_TLS_IE;
1198214082Sdim		break;
1199214082Sdim	      }
1200214082Sdim
1201214082Sdim	    if (h != NULL)
1202214082Sdim	      {
1203214082Sdim		h->got.refcount += 1;
1204214082Sdim		old_tls_type = _bfd_sparc_elf_hash_entry(h)->tls_type;
1205214082Sdim	      }
1206214082Sdim	    else
1207214082Sdim	      {
1208214082Sdim		bfd_signed_vma *local_got_refcounts;
1209214082Sdim
1210214082Sdim		/* This is a global offset table entry for a local symbol.  */
1211214082Sdim		local_got_refcounts = elf_local_got_refcounts (abfd);
1212214082Sdim		if (local_got_refcounts == NULL)
1213214082Sdim		  {
1214214082Sdim		    bfd_size_type size;
1215214082Sdim
1216214082Sdim		    size = symtab_hdr->sh_info;
1217214082Sdim		    size *= (sizeof (bfd_signed_vma) + sizeof(char));
1218214082Sdim		    local_got_refcounts = ((bfd_signed_vma *)
1219214082Sdim					   bfd_zalloc (abfd, size));
1220214082Sdim		    if (local_got_refcounts == NULL)
1221214082Sdim		      return FALSE;
1222214082Sdim		    elf_local_got_refcounts (abfd) = local_got_refcounts;
1223214082Sdim		    _bfd_sparc_elf_local_got_tls_type (abfd)
1224214082Sdim		      = (char *) (local_got_refcounts + symtab_hdr->sh_info);
1225214082Sdim		  }
1226214082Sdim		local_got_refcounts[r_symndx] += 1;
1227214082Sdim		old_tls_type = _bfd_sparc_elf_local_got_tls_type (abfd) [r_symndx];
1228214082Sdim	      }
1229214082Sdim
1230214082Sdim	    /* If a TLS symbol is accessed using IE at least once,
1231214082Sdim	       there is no point to use dynamic model for it.  */
1232214082Sdim	    if (old_tls_type != tls_type && old_tls_type != GOT_UNKNOWN
1233214082Sdim		&& (old_tls_type != GOT_TLS_GD
1234214082Sdim		    || tls_type != GOT_TLS_IE))
1235214082Sdim	      {
1236214082Sdim		if (old_tls_type == GOT_TLS_IE && tls_type == GOT_TLS_GD)
1237214082Sdim		  tls_type = old_tls_type;
1238214082Sdim		else
1239214082Sdim		  {
1240214082Sdim		    (*_bfd_error_handler)
1241214082Sdim		      (_("%B: `%s' accessed both as normal and thread local symbol"),
1242214082Sdim		       abfd, h ? h->root.root.string : "<local>");
1243214082Sdim		    return FALSE;
1244214082Sdim		  }
1245214082Sdim	      }
1246214082Sdim
1247214082Sdim	    if (old_tls_type != tls_type)
1248214082Sdim	      {
1249214082Sdim		if (h != NULL)
1250214082Sdim		  _bfd_sparc_elf_hash_entry (h)->tls_type = tls_type;
1251214082Sdim		else
1252214082Sdim		  _bfd_sparc_elf_local_got_tls_type (abfd) [r_symndx] = tls_type;
1253214082Sdim	      }
1254214082Sdim	  }
1255214082Sdim
1256214082Sdim	  if (htab->sgot == NULL)
1257214082Sdim	    {
1258214082Sdim	      if (htab->elf.dynobj == NULL)
1259214082Sdim		htab->elf.dynobj = abfd;
1260214082Sdim	      if (!create_got_section (htab->elf.dynobj, info))
1261214082Sdim		return FALSE;
1262214082Sdim	    }
1263214082Sdim	  break;
1264214082Sdim
1265214082Sdim	case R_SPARC_TLS_GD_CALL:
1266214082Sdim	case R_SPARC_TLS_LDM_CALL:
1267214082Sdim	  if (info->shared)
1268214082Sdim	    {
1269214082Sdim	      /* These are basically R_SPARC_TLS_WPLT30 relocs against
1270214082Sdim		 __tls_get_addr.  */
1271214082Sdim	      struct bfd_link_hash_entry *bh = NULL;
1272214082Sdim	      if (! _bfd_generic_link_add_one_symbol (info, abfd,
1273214082Sdim						      "__tls_get_addr", 0,
1274214082Sdim						      bfd_und_section_ptr, 0,
1275214082Sdim						      NULL, FALSE, FALSE,
1276214082Sdim						      &bh))
1277214082Sdim		return FALSE;
1278214082Sdim	      h = (struct elf_link_hash_entry *) bh;
1279214082Sdim	    }
1280214082Sdim	  else
1281214082Sdim	    break;
1282214082Sdim	  /* Fall through */
1283214082Sdim
1284214082Sdim	case R_SPARC_PLT32:
1285214082Sdim	case R_SPARC_WPLT30:
1286214082Sdim	case R_SPARC_HIPLT22:
1287214082Sdim	case R_SPARC_LOPLT10:
1288214082Sdim	case R_SPARC_PCPLT32:
1289214082Sdim	case R_SPARC_PCPLT22:
1290214082Sdim	case R_SPARC_PCPLT10:
1291214082Sdim	case R_SPARC_PLT64:
1292214082Sdim	  /* This symbol requires a procedure linkage table entry.  We
1293214082Sdim	     actually build the entry in adjust_dynamic_symbol,
1294214082Sdim	     because this might be a case of linking PIC code without
1295214082Sdim	     linking in any dynamic objects, in which case we don't
1296214082Sdim	     need to generate a procedure linkage table after all.  */
1297214082Sdim
1298214082Sdim	  if (h == NULL)
1299214082Sdim	    {
1300214082Sdim	      if (! ABI_64_P (abfd))
1301214082Sdim		{
1302214082Sdim		  /* The Solaris native assembler will generate a WPLT30
1303214082Sdim		     reloc for a local symbol if you assemble a call from
1304214082Sdim		     one section to another when using -K pic.  We treat
1305214082Sdim		     it as WDISP30.  */
1306214082Sdim		  if (ELF32_R_TYPE (rel->r_info) == R_SPARC_PLT32)
1307214082Sdim		    goto r_sparc_plt32;
1308214082Sdim		  break;
1309214082Sdim		}
1310214082Sdim
1311214082Sdim	      /* It does not make sense to have a procedure linkage
1312214082Sdim                 table entry for a local symbol.  */
1313214082Sdim	      bfd_set_error (bfd_error_bad_value);
1314214082Sdim	      return FALSE;
1315214082Sdim	    }
1316214082Sdim
1317214082Sdim	  h->needs_plt = 1;
1318214082Sdim
1319214082Sdim	  {
1320214082Sdim	    int this_r_type;
1321214082Sdim
1322214082Sdim	    this_r_type = SPARC_ELF_R_TYPE (rel->r_info);
1323214082Sdim	    if (this_r_type == R_SPARC_PLT32
1324214082Sdim		|| this_r_type == R_SPARC_PLT64)
1325214082Sdim	      goto r_sparc_plt32;
1326214082Sdim	  }
1327214082Sdim	  h->plt.refcount += 1;
1328214082Sdim	  break;
1329214082Sdim
1330214082Sdim	case R_SPARC_PC10:
1331214082Sdim	case R_SPARC_PC22:
1332214082Sdim	case R_SPARC_PC_HH22:
1333214082Sdim	case R_SPARC_PC_HM10:
1334214082Sdim	case R_SPARC_PC_LM22:
1335214082Sdim	  if (h != NULL)
1336214082Sdim	    h->non_got_ref = 1;
1337214082Sdim
1338214082Sdim	  if (h != NULL
1339214082Sdim	      && strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
1340214082Sdim	    break;
1341214082Sdim	  /* Fall through.  */
1342214082Sdim
1343214082Sdim	case R_SPARC_DISP8:
1344214082Sdim	case R_SPARC_DISP16:
1345214082Sdim	case R_SPARC_DISP32:
1346214082Sdim	case R_SPARC_DISP64:
1347214082Sdim	case R_SPARC_WDISP30:
1348214082Sdim	case R_SPARC_WDISP22:
1349214082Sdim	case R_SPARC_WDISP19:
1350214082Sdim	case R_SPARC_WDISP16:
1351214082Sdim	case R_SPARC_8:
1352214082Sdim	case R_SPARC_16:
1353214082Sdim	case R_SPARC_32:
1354214082Sdim	case R_SPARC_HI22:
1355214082Sdim	case R_SPARC_22:
1356214082Sdim	case R_SPARC_13:
1357214082Sdim	case R_SPARC_LO10:
1358214082Sdim	case R_SPARC_UA16:
1359214082Sdim	case R_SPARC_UA32:
1360214082Sdim	case R_SPARC_10:
1361214082Sdim	case R_SPARC_11:
1362214082Sdim	case R_SPARC_64:
1363214082Sdim	case R_SPARC_OLO10:
1364214082Sdim	case R_SPARC_HH22:
1365214082Sdim	case R_SPARC_HM10:
1366214082Sdim	case R_SPARC_LM22:
1367214082Sdim	case R_SPARC_7:
1368214082Sdim	case R_SPARC_5:
1369214082Sdim	case R_SPARC_6:
1370214082Sdim	case R_SPARC_HIX22:
1371214082Sdim	case R_SPARC_LOX10:
1372214082Sdim	case R_SPARC_H44:
1373214082Sdim	case R_SPARC_M44:
1374214082Sdim	case R_SPARC_L44:
1375214082Sdim	case R_SPARC_UA64:
1376214082Sdim	  if (h != NULL)
1377214082Sdim	    h->non_got_ref = 1;
1378214082Sdim
1379214082Sdim	r_sparc_plt32:
1380214082Sdim	  if (h != NULL && !info->shared)
1381214082Sdim	    {
1382214082Sdim	      /* We may need a .plt entry if the function this reloc
1383214082Sdim		 refers to is in a shared lib.  */
1384214082Sdim	      h->plt.refcount += 1;
1385214082Sdim	    }
1386214082Sdim
1387214082Sdim	  /* If we are creating a shared library, and this is a reloc
1388214082Sdim	     against a global symbol, or a non PC relative reloc
1389214082Sdim	     against a local symbol, then we need to copy the reloc
1390214082Sdim	     into the shared library.  However, if we are linking with
1391214082Sdim	     -Bsymbolic, we do not need to copy a reloc against a
1392214082Sdim	     global symbol which is defined in an object we are
1393214082Sdim	     including in the link (i.e., DEF_REGULAR is set).  At
1394214082Sdim	     this point we have not seen all the input files, so it is
1395214082Sdim	     possible that DEF_REGULAR is not set now but will be set
1396214082Sdim	     later (it is never cleared).  In case of a weak definition,
1397214082Sdim	     DEF_REGULAR may be cleared later by a strong definition in
1398214082Sdim	     a shared library.  We account for that possibility below by
1399214082Sdim	     storing information in the relocs_copied field of the hash
1400214082Sdim	     table entry.  A similar situation occurs when creating
1401214082Sdim	     shared libraries and symbol visibility changes render the
1402214082Sdim	     symbol local.
1403214082Sdim
1404214082Sdim	     If on the other hand, we are creating an executable, we
1405214082Sdim	     may need to keep relocations for symbols satisfied by a
1406214082Sdim	     dynamic library if we manage to avoid copy relocs for the
1407214082Sdim	     symbol.  */
1408214082Sdim	  if ((info->shared
1409214082Sdim	       && (sec->flags & SEC_ALLOC) != 0
1410214082Sdim	       && (! _bfd_sparc_elf_howto_table[r_type].pc_relative
1411214082Sdim		   || (h != NULL
1412214082Sdim		       && (! info->symbolic
1413214082Sdim			   || h->root.type == bfd_link_hash_defweak
1414214082Sdim			   || !h->def_regular))))
1415214082Sdim	      || (!info->shared
1416214082Sdim		  && (sec->flags & SEC_ALLOC) != 0
1417214082Sdim		  && h != NULL
1418214082Sdim		  && (h->root.type == bfd_link_hash_defweak
1419214082Sdim		      || !h->def_regular)))
1420214082Sdim	    {
1421214082Sdim	      struct _bfd_sparc_elf_dyn_relocs *p;
1422214082Sdim	      struct _bfd_sparc_elf_dyn_relocs **head;
1423214082Sdim
1424214082Sdim	      /* When creating a shared object, we must copy these
1425214082Sdim		 relocs into the output file.  We create a reloc
1426214082Sdim		 section in dynobj and make room for the reloc.  */
1427214082Sdim	      if (sreloc == NULL)
1428214082Sdim		{
1429214082Sdim		  const char *name;
1430214082Sdim		  bfd *dynobj;
1431214082Sdim
1432214082Sdim		  name = (bfd_elf_string_from_elf_section
1433214082Sdim			  (abfd,
1434214082Sdim			   elf_elfheader (abfd)->e_shstrndx,
1435214082Sdim			   elf_section_data (sec)->rel_hdr.sh_name));
1436214082Sdim		  if (name == NULL)
1437214082Sdim		    return FALSE;
1438214082Sdim
1439214634Sdim		  BFD_ASSERT (CONST_STRNEQ (name, ".rela")
1440214082Sdim			      && strcmp (bfd_get_section_name (abfd, sec),
1441214082Sdim					 name + 5) == 0);
1442214082Sdim
1443214082Sdim		  if (htab->elf.dynobj == NULL)
1444214082Sdim		    htab->elf.dynobj = abfd;
1445214082Sdim		  dynobj = htab->elf.dynobj;
1446214082Sdim
1447214082Sdim		  sreloc = bfd_get_section_by_name (dynobj, name);
1448214082Sdim		  if (sreloc == NULL)
1449214082Sdim		    {
1450214082Sdim		      flagword flags;
1451214082Sdim
1452214082Sdim		      flags = (SEC_HAS_CONTENTS | SEC_READONLY
1453214082Sdim			       | SEC_IN_MEMORY | SEC_LINKER_CREATED);
1454214082Sdim		      if ((sec->flags & SEC_ALLOC) != 0)
1455214082Sdim			flags |= SEC_ALLOC | SEC_LOAD;
1456214082Sdim		      sreloc = bfd_make_section_with_flags (dynobj,
1457214082Sdim							    name,
1458214082Sdim							    flags);
1459214082Sdim		      if (sreloc == NULL
1460214082Sdim			  || ! bfd_set_section_alignment (dynobj, sreloc,
1461214082Sdim							  htab->word_align_power))
1462214082Sdim			return FALSE;
1463214082Sdim		    }
1464214082Sdim		  elf_section_data (sec)->sreloc = sreloc;
1465214082Sdim		}
1466214082Sdim
1467214082Sdim	      /* If this is a global symbol, we count the number of
1468214082Sdim		 relocations we need for this symbol.  */
1469214082Sdim	      if (h != NULL)
1470214082Sdim		head = &((struct _bfd_sparc_elf_link_hash_entry *) h)->dyn_relocs;
1471214082Sdim	      else
1472214082Sdim		{
1473214082Sdim		  /* Track dynamic relocs needed for local syms too.
1474214082Sdim		     We really need local syms available to do this
1475214082Sdim		     easily.  Oh well.  */
1476214082Sdim
1477214082Sdim		  asection *s;
1478214082Sdim		  void *vpp;
1479214082Sdim
1480214082Sdim		  s = bfd_section_from_r_symndx (abfd, &htab->sym_sec,
1481214082Sdim						 sec, r_symndx);
1482214082Sdim		  if (s == NULL)
1483214082Sdim		    return FALSE;
1484214082Sdim
1485214082Sdim		  vpp = &elf_section_data (s)->local_dynrel;
1486214082Sdim		  head = (struct _bfd_sparc_elf_dyn_relocs **) vpp;
1487214082Sdim		}
1488214082Sdim
1489214082Sdim	      p = *head;
1490214082Sdim	      if (p == NULL || p->sec != sec)
1491214082Sdim		{
1492214082Sdim		  bfd_size_type amt = sizeof *p;
1493214082Sdim		  p = ((struct _bfd_sparc_elf_dyn_relocs *)
1494214082Sdim		       bfd_alloc (htab->elf.dynobj, amt));
1495214082Sdim		  if (p == NULL)
1496214082Sdim		    return FALSE;
1497214082Sdim		  p->next = *head;
1498214082Sdim		  *head = p;
1499214082Sdim		  p->sec = sec;
1500214082Sdim		  p->count = 0;
1501214082Sdim		  p->pc_count = 0;
1502214082Sdim		}
1503214082Sdim
1504214082Sdim	      p->count += 1;
1505214082Sdim	      if (_bfd_sparc_elf_howto_table[r_type].pc_relative)
1506214082Sdim		p->pc_count += 1;
1507214082Sdim	    }
1508214082Sdim
1509214082Sdim	  break;
1510214082Sdim
1511214082Sdim	case R_SPARC_GNU_VTINHERIT:
1512214082Sdim	  if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
1513214082Sdim	    return FALSE;
1514214082Sdim	  break;
1515214082Sdim
1516214082Sdim	case R_SPARC_GNU_VTENTRY:
1517214082Sdim	  if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
1518214082Sdim	    return FALSE;
1519214082Sdim	  break;
1520214082Sdim
1521214082Sdim	case R_SPARC_REGISTER:
1522214082Sdim	  /* Nothing to do.  */
1523214082Sdim	  break;
1524214082Sdim
1525214082Sdim	default:
1526214082Sdim	  break;
1527214082Sdim	}
1528214082Sdim    }
1529214082Sdim
1530214082Sdim  return TRUE;
1531214082Sdim}
1532214082Sdim
1533214082Sdimasection *
1534214082Sdim_bfd_sparc_elf_gc_mark_hook (asection *sec,
1535214082Sdim			     struct bfd_link_info *info,
1536214082Sdim			     Elf_Internal_Rela *rel,
1537214082Sdim			     struct elf_link_hash_entry *h,
1538214082Sdim			     Elf_Internal_Sym *sym)
1539214082Sdim{
1540214082Sdim  if (h != NULL)
1541214634Sdim    switch (SPARC_ELF_R_TYPE (rel->r_info))
1542214082Sdim      {
1543214082Sdim      case R_SPARC_GNU_VTINHERIT:
1544214082Sdim      case R_SPARC_GNU_VTENTRY:
1545214634Sdim	return NULL;
1546214082Sdim      }
1547214082Sdim
1548214634Sdim  return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
1549214082Sdim}
1550214082Sdim
1551214082Sdim/* Update the got entry reference counts for the section being removed.  */
1552214082Sdimbfd_boolean
1553214082Sdim_bfd_sparc_elf_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
1554214082Sdim			      asection *sec, const Elf_Internal_Rela *relocs)
1555214082Sdim{
1556214082Sdim  struct _bfd_sparc_elf_link_hash_table *htab;
1557214082Sdim  Elf_Internal_Shdr *symtab_hdr;
1558214082Sdim  struct elf_link_hash_entry **sym_hashes;
1559214082Sdim  bfd_signed_vma *local_got_refcounts;
1560214082Sdim  const Elf_Internal_Rela *rel, *relend;
1561214082Sdim
1562214082Sdim  elf_section_data (sec)->local_dynrel = NULL;
1563214082Sdim
1564214082Sdim  htab = _bfd_sparc_elf_hash_table (info);
1565214082Sdim  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
1566214082Sdim  sym_hashes = elf_sym_hashes (abfd);
1567214082Sdim  local_got_refcounts = elf_local_got_refcounts (abfd);
1568214082Sdim
1569214082Sdim  relend = relocs + sec->reloc_count;
1570214082Sdim  for (rel = relocs; rel < relend; rel++)
1571214082Sdim    {
1572214082Sdim      unsigned long r_symndx;
1573214082Sdim      unsigned int r_type;
1574214082Sdim      struct elf_link_hash_entry *h = NULL;
1575214082Sdim
1576214082Sdim      r_symndx = SPARC_ELF_R_SYMNDX (htab, rel->r_info);
1577214082Sdim      if (r_symndx >= symtab_hdr->sh_info)
1578214082Sdim	{
1579214082Sdim	  struct _bfd_sparc_elf_link_hash_entry *eh;
1580214082Sdim	  struct _bfd_sparc_elf_dyn_relocs **pp;
1581214082Sdim	  struct _bfd_sparc_elf_dyn_relocs *p;
1582214082Sdim
1583214082Sdim	  h = sym_hashes[r_symndx - symtab_hdr->sh_info];
1584214082Sdim	  while (h->root.type == bfd_link_hash_indirect
1585214082Sdim		 || h->root.type == bfd_link_hash_warning)
1586214082Sdim	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
1587214082Sdim	  eh = (struct _bfd_sparc_elf_link_hash_entry *) h;
1588214082Sdim	  for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next)
1589214082Sdim	    if (p->sec == sec)
1590214082Sdim	      {
1591214082Sdim		/* Everything must go for SEC.  */
1592214082Sdim		*pp = p->next;
1593214082Sdim		break;
1594214082Sdim	      }
1595214082Sdim	}
1596214082Sdim
1597214082Sdim      r_type = SPARC_ELF_R_TYPE (rel->r_info);
1598214082Sdim      r_type = sparc_elf_tls_transition (info, abfd, r_type, h != NULL);
1599214082Sdim      switch (r_type)
1600214082Sdim	{
1601214082Sdim	case R_SPARC_TLS_LDM_HI22:
1602214082Sdim	case R_SPARC_TLS_LDM_LO10:
1603214082Sdim	  if (_bfd_sparc_elf_hash_table (info)->tls_ldm_got.refcount > 0)
1604214082Sdim	    _bfd_sparc_elf_hash_table (info)->tls_ldm_got.refcount -= 1;
1605214082Sdim	  break;
1606214082Sdim
1607214082Sdim	case R_SPARC_TLS_GD_HI22:
1608214082Sdim	case R_SPARC_TLS_GD_LO10:
1609214082Sdim	case R_SPARC_TLS_IE_HI22:
1610214082Sdim	case R_SPARC_TLS_IE_LO10:
1611214082Sdim	case R_SPARC_GOT10:
1612214082Sdim	case R_SPARC_GOT13:
1613214082Sdim	case R_SPARC_GOT22:
1614214082Sdim	  if (h != NULL)
1615214082Sdim	    {
1616214082Sdim	      if (h->got.refcount > 0)
1617214082Sdim		h->got.refcount--;
1618214082Sdim	    }
1619214082Sdim	  else
1620214082Sdim	    {
1621214082Sdim	      if (local_got_refcounts[r_symndx] > 0)
1622214082Sdim		local_got_refcounts[r_symndx]--;
1623214082Sdim	    }
1624214082Sdim	  break;
1625214082Sdim
1626214082Sdim	case R_SPARC_PC10:
1627214082Sdim	case R_SPARC_PC22:
1628214082Sdim	case R_SPARC_PC_HH22:
1629214082Sdim	case R_SPARC_PC_HM10:
1630214082Sdim	case R_SPARC_PC_LM22:
1631214082Sdim	  if (h != NULL
1632214082Sdim	      && strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
1633214082Sdim	    break;
1634214082Sdim	  /* Fall through.  */
1635214082Sdim
1636214082Sdim	case R_SPARC_DISP8:
1637214082Sdim	case R_SPARC_DISP16:
1638214082Sdim	case R_SPARC_DISP32:
1639214082Sdim	case R_SPARC_DISP64:
1640214082Sdim	case R_SPARC_WDISP30:
1641214082Sdim	case R_SPARC_WDISP22:
1642214082Sdim	case R_SPARC_WDISP19:
1643214082Sdim	case R_SPARC_WDISP16:
1644214082Sdim	case R_SPARC_8:
1645214082Sdim	case R_SPARC_16:
1646214082Sdim	case R_SPARC_32:
1647214082Sdim	case R_SPARC_HI22:
1648214082Sdim	case R_SPARC_22:
1649214082Sdim	case R_SPARC_13:
1650214082Sdim	case R_SPARC_LO10:
1651214082Sdim	case R_SPARC_UA16:
1652214082Sdim	case R_SPARC_UA32:
1653214082Sdim	case R_SPARC_PLT32:
1654214082Sdim	case R_SPARC_10:
1655214082Sdim	case R_SPARC_11:
1656214082Sdim	case R_SPARC_64:
1657214082Sdim	case R_SPARC_OLO10:
1658214082Sdim	case R_SPARC_HH22:
1659214082Sdim	case R_SPARC_HM10:
1660214082Sdim	case R_SPARC_LM22:
1661214082Sdim	case R_SPARC_7:
1662214082Sdim	case R_SPARC_5:
1663214082Sdim	case R_SPARC_6:
1664214082Sdim	case R_SPARC_HIX22:
1665214082Sdim	case R_SPARC_LOX10:
1666214082Sdim	case R_SPARC_H44:
1667214082Sdim	case R_SPARC_M44:
1668214082Sdim	case R_SPARC_L44:
1669214082Sdim	case R_SPARC_UA64:
1670214082Sdim	  if (info->shared)
1671214082Sdim	    break;
1672214082Sdim	  /* Fall through.  */
1673214082Sdim
1674214082Sdim	case R_SPARC_WPLT30:
1675214082Sdim	  if (h != NULL)
1676214082Sdim	    {
1677214082Sdim	      if (h->plt.refcount > 0)
1678214082Sdim		h->plt.refcount--;
1679214082Sdim	    }
1680214082Sdim	  break;
1681214082Sdim
1682214082Sdim	default:
1683214082Sdim	  break;
1684214082Sdim	}
1685214082Sdim    }
1686214082Sdim
1687214082Sdim  return TRUE;
1688214082Sdim}
1689214082Sdim
1690214082Sdim/* Adjust a symbol defined by a dynamic object and referenced by a
1691214082Sdim   regular object.  The current definition is in some section of the
1692214082Sdim   dynamic object, but we're not including those sections.  We have to
1693214082Sdim   change the definition to something the rest of the link can
1694214082Sdim   understand.  */
1695214082Sdim
1696214082Sdimbfd_boolean
1697214082Sdim_bfd_sparc_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
1698214082Sdim				     struct elf_link_hash_entry *h)
1699214082Sdim{
1700214082Sdim  struct _bfd_sparc_elf_link_hash_table *htab;
1701214082Sdim  struct _bfd_sparc_elf_link_hash_entry * eh;
1702214082Sdim  struct _bfd_sparc_elf_dyn_relocs *p;
1703214082Sdim  asection *s;
1704214082Sdim
1705214082Sdim  htab = _bfd_sparc_elf_hash_table (info);
1706214082Sdim
1707214082Sdim  /* Make sure we know what is going on here.  */
1708214082Sdim  BFD_ASSERT (htab->elf.dynobj != NULL
1709214082Sdim	      && (h->needs_plt
1710214082Sdim		  || h->u.weakdef != NULL
1711214082Sdim		  || (h->def_dynamic
1712214082Sdim		      && h->ref_regular
1713214082Sdim		      && !h->def_regular)));
1714214082Sdim
1715214082Sdim  /* If this is a function, put it in the procedure linkage table.  We
1716214082Sdim     will fill in the contents of the procedure linkage table later
1717214082Sdim     (although we could actually do it here).  The STT_NOTYPE
1718214082Sdim     condition is a hack specifically for the Oracle libraries
1719214082Sdim     delivered for Solaris; for some inexplicable reason, they define
1720214082Sdim     some of their functions as STT_NOTYPE when they really should be
1721214082Sdim     STT_FUNC.  */
1722214082Sdim  if (h->type == STT_FUNC
1723214082Sdim      || h->needs_plt
1724214082Sdim      || (h->type == STT_NOTYPE
1725214082Sdim	  && (h->root.type == bfd_link_hash_defined
1726214082Sdim	      || h->root.type == bfd_link_hash_defweak)
1727214082Sdim	  && (h->root.u.def.section->flags & SEC_CODE) != 0))
1728214082Sdim    {
1729214082Sdim      if (h->plt.refcount <= 0
1730214082Sdim	  || (! info->shared
1731214082Sdim	      && !h->def_dynamic
1732214082Sdim	      && !h->ref_dynamic
1733214082Sdim	      && h->root.type != bfd_link_hash_undefweak
1734214082Sdim	      && h->root.type != bfd_link_hash_undefined))
1735214082Sdim	{
1736214082Sdim	  /* This case can occur if we saw a WPLT30 reloc in an input
1737214082Sdim	     file, but the symbol was never referred to by a dynamic
1738214082Sdim	     object, or if all references were garbage collected.  In
1739214082Sdim	     such a case, we don't actually need to build a procedure
1740214082Sdim	     linkage table, and we can just do a WDISP30 reloc instead.  */
1741214082Sdim	  h->plt.offset = (bfd_vma) -1;
1742214082Sdim	  h->needs_plt = 0;
1743214082Sdim	}
1744214082Sdim
1745214082Sdim      return TRUE;
1746214082Sdim    }
1747214082Sdim  else
1748214082Sdim    h->plt.offset = (bfd_vma) -1;
1749214082Sdim
1750214082Sdim  /* If this is a weak symbol, and there is a real definition, the
1751214082Sdim     processor independent code will have arranged for us to see the
1752214082Sdim     real definition first, and we can just use the same value.  */
1753214082Sdim  if (h->u.weakdef != NULL)
1754214082Sdim    {
1755214082Sdim      BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined
1756214082Sdim		  || h->u.weakdef->root.type == bfd_link_hash_defweak);
1757214082Sdim      h->root.u.def.section = h->u.weakdef->root.u.def.section;
1758214082Sdim      h->root.u.def.value = h->u.weakdef->root.u.def.value;
1759214082Sdim      return TRUE;
1760214082Sdim    }
1761214082Sdim
1762214082Sdim  /* This is a reference to a symbol defined by a dynamic object which
1763214082Sdim     is not a function.  */
1764214082Sdim
1765214082Sdim  /* If we are creating a shared library, we must presume that the
1766214082Sdim     only references to the symbol are via the global offset table.
1767214082Sdim     For such cases we need not do anything here; the relocations will
1768214082Sdim     be handled correctly by relocate_section.  */
1769214082Sdim  if (info->shared)
1770214082Sdim    return TRUE;
1771214082Sdim
1772214082Sdim  /* If there are no references to this symbol that do not use the
1773214082Sdim     GOT, we don't need to generate a copy reloc.  */
1774214082Sdim  if (!h->non_got_ref)
1775214082Sdim    return TRUE;
1776214082Sdim
1777214082Sdim  eh = (struct _bfd_sparc_elf_link_hash_entry *) h;
1778214082Sdim  for (p = eh->dyn_relocs; p != NULL; p = p->next)
1779214082Sdim    {
1780214082Sdim      s = p->sec->output_section;
1781214082Sdim      if (s != NULL && (s->flags & SEC_READONLY) != 0)
1782214082Sdim	break;
1783214082Sdim    }
1784214082Sdim
1785214082Sdim  /* If we didn't find any dynamic relocs in read-only sections, then
1786214082Sdim     we'll be keeping the dynamic relocs and avoiding the copy reloc.  */
1787214082Sdim  if (p == NULL)
1788214082Sdim    {
1789214082Sdim      h->non_got_ref = 0;
1790214082Sdim      return TRUE;
1791214082Sdim    }
1792214082Sdim
1793214082Sdim  if (h->size == 0)
1794214082Sdim    {
1795214082Sdim      (*_bfd_error_handler) (_("dynamic variable `%s' is zero size"),
1796214082Sdim			     h->root.root.string);
1797214082Sdim      return TRUE;
1798214082Sdim    }
1799214082Sdim
1800214082Sdim  /* We must allocate the symbol in our .dynbss section, which will
1801214082Sdim     become part of the .bss section of the executable.  There will be
1802214082Sdim     an entry for this symbol in the .dynsym section.  The dynamic
1803214082Sdim     object will contain position independent code, so all references
1804214082Sdim     from the dynamic object to this symbol will go through the global
1805214082Sdim     offset table.  The dynamic linker will use the .dynsym entry to
1806214082Sdim     determine the address it must put in the global offset table, so
1807214082Sdim     both the dynamic object and the regular object will refer to the
1808214082Sdim     same memory location for the variable.  */
1809214082Sdim
1810214082Sdim  /* We must generate a R_SPARC_COPY reloc to tell the dynamic linker
1811214082Sdim     to copy the initial value out of the dynamic object and into the
1812214082Sdim     runtime process image.  We need to remember the offset into the
1813214082Sdim     .rel.bss section we are going to use.  */
1814214082Sdim  if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
1815214082Sdim    {
1816214082Sdim      htab->srelbss->size += SPARC_ELF_RELA_BYTES (htab);
1817214082Sdim      h->needs_copy = 1;
1818214082Sdim    }
1819214082Sdim
1820214082Sdim  s = htab->sdynbss;
1821214082Sdim
1822214634Sdim  return _bfd_elf_adjust_dynamic_copy (h, s);
1823214082Sdim}
1824214082Sdim
1825214082Sdim/* Allocate space in .plt, .got and associated reloc sections for
1826214082Sdim   dynamic relocs.  */
1827214082Sdim
1828214082Sdimstatic bfd_boolean
1829214082Sdimallocate_dynrelocs (struct elf_link_hash_entry *h, PTR inf)
1830214082Sdim{
1831214082Sdim  struct bfd_link_info *info;
1832214082Sdim  struct _bfd_sparc_elf_link_hash_table *htab;
1833214082Sdim  struct _bfd_sparc_elf_link_hash_entry *eh;
1834214082Sdim  struct _bfd_sparc_elf_dyn_relocs *p;
1835214082Sdim
1836214082Sdim  if (h->root.type == bfd_link_hash_indirect)
1837214082Sdim    return TRUE;
1838214082Sdim
1839214082Sdim  if (h->root.type == bfd_link_hash_warning)
1840214082Sdim    /* When warning symbols are created, they **replace** the "real"
1841214082Sdim       entry in the hash table, thus we never get to see the real
1842214082Sdim       symbol in a hash traversal.  So look at it now.  */
1843214082Sdim    h = (struct elf_link_hash_entry *) h->root.u.i.link;
1844214082Sdim
1845214082Sdim  info = (struct bfd_link_info *) inf;
1846214082Sdim  htab = _bfd_sparc_elf_hash_table (info);
1847214082Sdim
1848214082Sdim  if (htab->elf.dynamic_sections_created
1849214082Sdim      && h->plt.refcount > 0)
1850214082Sdim    {
1851214082Sdim      /* Make sure this symbol is output as a dynamic symbol.
1852214082Sdim	 Undefined weak syms won't yet be marked as dynamic.  */
1853214082Sdim      if (h->dynindx == -1
1854214082Sdim	  && !h->forced_local)
1855214082Sdim	{
1856214082Sdim	  if (! bfd_elf_link_record_dynamic_symbol (info, h))
1857214082Sdim	    return FALSE;
1858214082Sdim	}
1859214082Sdim
1860214082Sdim      if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info->shared, h))
1861214082Sdim	{
1862214082Sdim	  asection *s = htab->splt;
1863214082Sdim
1864214082Sdim	  /* Allocate room for the header.  */
1865214082Sdim	  if (s->size == 0)
1866214082Sdim	    {
1867214082Sdim	      s->size = htab->plt_header_size;
1868214082Sdim
1869214082Sdim	      /* Allocate space for the .rela.plt.unloaded relocations.  */
1870214082Sdim	      if (htab->is_vxworks && !info->shared)
1871214082Sdim		htab->srelplt2->size = sizeof (Elf32_External_Rela) * 2;
1872214082Sdim	    }
1873214082Sdim
1874214082Sdim	  /* The procedure linkage table size is bounded by the magnitude
1875214082Sdim	     of the offset we can describe in the entry.  */
1876214082Sdim	  if (s->size >= (SPARC_ELF_WORD_BYTES(htab) == 8 ?
1877214082Sdim			  (((bfd_vma)1 << 31) << 1) : 0x400000))
1878214082Sdim	    {
1879214082Sdim	      bfd_set_error (bfd_error_bad_value);
1880214082Sdim	      return FALSE;
1881214082Sdim	    }
1882214082Sdim
1883214082Sdim	  if (SPARC_ELF_WORD_BYTES(htab) == 8
1884214082Sdim	      && s->size >= PLT64_LARGE_THRESHOLD * PLT64_ENTRY_SIZE)
1885214082Sdim	    {
1886214082Sdim	      bfd_vma off = s->size - PLT64_LARGE_THRESHOLD * PLT64_ENTRY_SIZE;
1887214082Sdim
1888214082Sdim
1889214082Sdim	      off = (off % (160 * PLT64_ENTRY_SIZE)) / PLT64_ENTRY_SIZE;
1890214082Sdim
1891214082Sdim	      h->plt.offset = (s->size - (off * 8));
1892214082Sdim	    }
1893214082Sdim	  else
1894214082Sdim	    h->plt.offset = s->size;
1895214082Sdim
1896214082Sdim	  /* If this symbol is not defined in a regular file, and we are
1897214082Sdim	     not generating a shared library, then set the symbol to this
1898214082Sdim	     location in the .plt.  This is required to make function
1899214082Sdim	     pointers compare as equal between the normal executable and
1900214082Sdim	     the shared library.  */
1901214082Sdim	  if (! info->shared
1902214082Sdim	      && !h->def_regular)
1903214082Sdim	    {
1904214082Sdim	      h->root.u.def.section = s;
1905214082Sdim	      h->root.u.def.value = h->plt.offset;
1906214082Sdim	    }
1907214082Sdim
1908214082Sdim	  /* Make room for this entry.  */
1909214082Sdim	  s->size += htab->plt_entry_size;
1910214082Sdim
1911214082Sdim	  /* We also need to make an entry in the .rela.plt section.  */
1912214082Sdim	  htab->srelplt->size += SPARC_ELF_RELA_BYTES (htab);
1913214082Sdim
1914214082Sdim	  if (htab->is_vxworks)
1915214082Sdim	    {
1916214082Sdim	      /* Allocate space for the .got.plt entry.  */
1917214082Sdim	      htab->sgotplt->size += 4;
1918214082Sdim
1919214082Sdim	      /* ...and for the .rela.plt.unloaded relocations.  */
1920214082Sdim	      if (!info->shared)
1921214082Sdim		htab->srelplt2->size += sizeof (Elf32_External_Rela) * 3;
1922214082Sdim	    }
1923214082Sdim	}
1924214082Sdim      else
1925214082Sdim	{
1926214082Sdim	  h->plt.offset = (bfd_vma) -1;
1927214082Sdim	  h->needs_plt = 0;
1928214082Sdim	}
1929214082Sdim    }
1930214082Sdim  else
1931214082Sdim    {
1932214082Sdim      h->plt.offset = (bfd_vma) -1;
1933214082Sdim      h->needs_plt = 0;
1934214082Sdim    }
1935214082Sdim
1936214082Sdim  /* If R_SPARC_TLS_IE_{HI22,LO10} symbol is now local to the binary,
1937214082Sdim     make it a R_SPARC_TLS_LE_{HI22,LO10} requiring no TLS entry.  */
1938214082Sdim  if (h->got.refcount > 0
1939214082Sdim      && !info->shared
1940214082Sdim      && h->dynindx == -1
1941214082Sdim      && _bfd_sparc_elf_hash_entry(h)->tls_type == GOT_TLS_IE)
1942214082Sdim    h->got.offset = (bfd_vma) -1;
1943214082Sdim  else if (h->got.refcount > 0)
1944214082Sdim    {
1945214082Sdim      asection *s;
1946214082Sdim      bfd_boolean dyn;
1947214082Sdim      int tls_type = _bfd_sparc_elf_hash_entry(h)->tls_type;
1948214082Sdim
1949214082Sdim      /* Make sure this symbol is output as a dynamic symbol.
1950214082Sdim	 Undefined weak syms won't yet be marked as dynamic.  */
1951214082Sdim      if (h->dynindx == -1
1952214082Sdim	  && !h->forced_local)
1953214082Sdim	{
1954214082Sdim	  if (! bfd_elf_link_record_dynamic_symbol (info, h))
1955214082Sdim	    return FALSE;
1956214082Sdim	}
1957214082Sdim
1958214082Sdim      s = htab->sgot;
1959214082Sdim      h->got.offset = s->size;
1960214082Sdim      s->size += SPARC_ELF_WORD_BYTES (htab);
1961214082Sdim      /* R_SPARC_TLS_GD_HI{22,LO10} needs 2 consecutive GOT slots.  */
1962214082Sdim      if (tls_type == GOT_TLS_GD)
1963214082Sdim	s->size += SPARC_ELF_WORD_BYTES (htab);
1964214082Sdim      dyn = htab->elf.dynamic_sections_created;
1965214082Sdim      /* R_SPARC_TLS_IE_{HI22,LO10} needs one dynamic relocation,
1966214082Sdim	 R_SPARC_TLS_GD_{HI22,LO10} needs one if local symbol and two if
1967214082Sdim	 global.  */
1968214082Sdim      if ((tls_type == GOT_TLS_GD && h->dynindx == -1)
1969214082Sdim	  || tls_type == GOT_TLS_IE)
1970214082Sdim	htab->srelgot->size += SPARC_ELF_RELA_BYTES (htab);
1971214082Sdim      else if (tls_type == GOT_TLS_GD)
1972214082Sdim	htab->srelgot->size += 2 * SPARC_ELF_RELA_BYTES (htab);
1973214082Sdim      else if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h))
1974214082Sdim	htab->srelgot->size += SPARC_ELF_RELA_BYTES (htab);
1975214082Sdim    }
1976214082Sdim  else
1977214082Sdim    h->got.offset = (bfd_vma) -1;
1978214082Sdim
1979214082Sdim  eh = (struct _bfd_sparc_elf_link_hash_entry *) h;
1980214082Sdim  if (eh->dyn_relocs == NULL)
1981214082Sdim    return TRUE;
1982214082Sdim
1983214082Sdim  /* In the shared -Bsymbolic case, discard space allocated for
1984214082Sdim     dynamic pc-relative relocs against symbols which turn out to be
1985214082Sdim     defined in regular objects.  For the normal shared case, discard
1986214082Sdim     space for pc-relative relocs that have become local due to symbol
1987214082Sdim     visibility changes.  */
1988214082Sdim
1989214082Sdim  if (info->shared)
1990214082Sdim    {
1991214082Sdim      if (h->def_regular
1992214082Sdim	  && (h->forced_local
1993214082Sdim	      || info->symbolic))
1994214082Sdim	{
1995214082Sdim	  struct _bfd_sparc_elf_dyn_relocs **pp;
1996214082Sdim
1997214082Sdim	  for (pp = &eh->dyn_relocs; (p = *pp) != NULL; )
1998214082Sdim	    {
1999214082Sdim	      p->count -= p->pc_count;
2000214082Sdim	      p->pc_count = 0;
2001214082Sdim	      if (p->count == 0)
2002214082Sdim		*pp = p->next;
2003214082Sdim	      else
2004214082Sdim		pp = &p->next;
2005214082Sdim	    }
2006214082Sdim	}
2007214082Sdim
2008214082Sdim      /* Also discard relocs on undefined weak syms with non-default
2009214082Sdim	 visibility.  */
2010214082Sdim      if (eh->dyn_relocs != NULL
2011214082Sdim	  && h->root.type == bfd_link_hash_undefweak)
2012214082Sdim	{
2013214082Sdim	  if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
2014214082Sdim	    eh->dyn_relocs = NULL;
2015214082Sdim
2016214082Sdim	  /* Make sure undefined weak symbols are output as a dynamic
2017214082Sdim	     symbol in PIEs.  */
2018214082Sdim	  else if (h->dynindx == -1
2019214082Sdim		   && !h->forced_local)
2020214082Sdim	    {
2021214082Sdim	      if (! bfd_elf_link_record_dynamic_symbol (info, h))
2022214082Sdim		return FALSE;
2023214082Sdim	    }
2024214082Sdim	}
2025214082Sdim    }
2026214082Sdim  else
2027214082Sdim    {
2028214082Sdim      /* For the non-shared case, discard space for relocs against
2029214082Sdim	 symbols which turn out to need copy relocs or are not
2030214082Sdim	 dynamic.  */
2031214082Sdim
2032214082Sdim      if (!h->non_got_ref
2033214082Sdim	  && ((h->def_dynamic
2034214082Sdim	       && !h->def_regular)
2035214082Sdim	      || (htab->elf.dynamic_sections_created
2036214082Sdim		  && (h->root.type == bfd_link_hash_undefweak
2037214082Sdim		      || h->root.type == bfd_link_hash_undefined))))
2038214082Sdim	{
2039214082Sdim	  /* Make sure this symbol is output as a dynamic symbol.
2040214082Sdim	     Undefined weak syms won't yet be marked as dynamic.  */
2041214082Sdim	  if (h->dynindx == -1
2042214082Sdim	      && !h->forced_local)
2043214082Sdim	    {
2044214082Sdim	      if (! bfd_elf_link_record_dynamic_symbol (info, h))
2045214082Sdim		return FALSE;
2046214082Sdim	    }
2047214082Sdim
2048214082Sdim	  /* If that succeeded, we know we'll be keeping all the
2049214082Sdim	     relocs.  */
2050214082Sdim	  if (h->dynindx != -1)
2051214082Sdim	    goto keep;
2052214082Sdim	}
2053214082Sdim
2054214082Sdim      eh->dyn_relocs = NULL;
2055214082Sdim
2056214082Sdim    keep: ;
2057214082Sdim    }
2058214082Sdim
2059214082Sdim  /* Finally, allocate space.  */
2060214082Sdim  for (p = eh->dyn_relocs; p != NULL; p = p->next)
2061214082Sdim    {
2062214082Sdim      asection *sreloc = elf_section_data (p->sec)->sreloc;
2063214082Sdim      sreloc->size += p->count * SPARC_ELF_RELA_BYTES (htab);
2064214082Sdim    }
2065214082Sdim
2066214082Sdim  return TRUE;
2067214082Sdim}
2068214082Sdim
2069214082Sdim/* Find any dynamic relocs that apply to read-only sections.  */
2070214082Sdim
2071214082Sdimstatic bfd_boolean
2072214082Sdimreadonly_dynrelocs (struct elf_link_hash_entry *h, PTR inf)
2073214082Sdim{
2074214082Sdim  struct _bfd_sparc_elf_link_hash_entry *eh;
2075214082Sdim  struct _bfd_sparc_elf_dyn_relocs *p;
2076214082Sdim
2077214082Sdim  if (h->root.type == bfd_link_hash_warning)
2078214082Sdim    h = (struct elf_link_hash_entry *) h->root.u.i.link;
2079214082Sdim
2080214082Sdim  eh = (struct _bfd_sparc_elf_link_hash_entry *) h;
2081214082Sdim  for (p = eh->dyn_relocs; p != NULL; p = p->next)
2082214082Sdim    {
2083214082Sdim      asection *s = p->sec->output_section;
2084214082Sdim
2085214082Sdim      if (s != NULL && (s->flags & SEC_READONLY) != 0)
2086214082Sdim	{
2087214082Sdim	  struct bfd_link_info *info = (struct bfd_link_info *) inf;
2088214082Sdim
2089214082Sdim	  info->flags |= DF_TEXTREL;
2090214082Sdim
2091214082Sdim	  /* Not an error, just cut short the traversal.  */
2092214082Sdim	  return FALSE;
2093214082Sdim	}
2094214082Sdim    }
2095214082Sdim  return TRUE;
2096214082Sdim}
2097214082Sdim
2098214082Sdim/* Return true if the dynamic symbol for a given section should be
2099214082Sdim   omitted when creating a shared library.  */
2100214082Sdim
2101214082Sdimbfd_boolean
2102214082Sdim_bfd_sparc_elf_omit_section_dynsym (bfd *output_bfd,
2103214082Sdim				    struct bfd_link_info *info,
2104214082Sdim				    asection *p)
2105214082Sdim{
2106214082Sdim  /* We keep the .got section symbol so that explicit relocations
2107214082Sdim     against the _GLOBAL_OFFSET_TABLE_ symbol emitted in PIC mode
2108214082Sdim     can be turned into relocations against the .got symbol.  */
2109214082Sdim  if (strcmp (p->name, ".got") == 0)
2110214082Sdim    return FALSE;
2111214082Sdim
2112214082Sdim  return _bfd_elf_link_omit_section_dynsym (output_bfd, info, p);
2113214082Sdim}
2114214082Sdim
2115214082Sdim/* Set the sizes of the dynamic sections.  */
2116214082Sdim
2117214082Sdimbfd_boolean
2118214082Sdim_bfd_sparc_elf_size_dynamic_sections (bfd *output_bfd,
2119214082Sdim				      struct bfd_link_info *info)
2120214082Sdim{
2121214082Sdim  struct _bfd_sparc_elf_link_hash_table *htab;
2122214082Sdim  bfd *dynobj;
2123214082Sdim  asection *s;
2124214082Sdim  bfd *ibfd;
2125214082Sdim
2126214082Sdim  htab = _bfd_sparc_elf_hash_table (info);
2127214082Sdim  dynobj = htab->elf.dynobj;
2128214082Sdim  BFD_ASSERT (dynobj != NULL);
2129214082Sdim
2130214082Sdim  if (elf_hash_table (info)->dynamic_sections_created)
2131214082Sdim    {
2132214082Sdim      /* Set the contents of the .interp section to the interpreter.  */
2133214082Sdim      if (info->executable)
2134214082Sdim	{
2135214082Sdim	  s = bfd_get_section_by_name (dynobj, ".interp");
2136214082Sdim	  BFD_ASSERT (s != NULL);
2137214082Sdim	  s->size = htab->dynamic_interpreter_size;
2138214082Sdim	  s->contents = (unsigned char *) htab->dynamic_interpreter;
2139214082Sdim	}
2140214082Sdim    }
2141214082Sdim
2142214082Sdim  /* Set up .got offsets for local syms, and space for local dynamic
2143214082Sdim     relocs.  */
2144214082Sdim  for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
2145214082Sdim    {
2146214082Sdim      bfd_signed_vma *local_got;
2147214082Sdim      bfd_signed_vma *end_local_got;
2148214082Sdim      char *local_tls_type;
2149214082Sdim      bfd_size_type locsymcount;
2150214082Sdim      Elf_Internal_Shdr *symtab_hdr;
2151214082Sdim      asection *srel;
2152214082Sdim
2153214082Sdim      if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
2154214082Sdim	continue;
2155214082Sdim
2156214082Sdim      for (s = ibfd->sections; s != NULL; s = s->next)
2157214082Sdim	{
2158214082Sdim	  struct _bfd_sparc_elf_dyn_relocs *p;
2159214082Sdim
2160214082Sdim	  for (p = elf_section_data (s)->local_dynrel; p != NULL; p = p->next)
2161214082Sdim	    {
2162214082Sdim	      if (!bfd_is_abs_section (p->sec)
2163214082Sdim		  && bfd_is_abs_section (p->sec->output_section))
2164214082Sdim		{
2165214082Sdim		  /* Input section has been discarded, either because
2166214082Sdim		     it is a copy of a linkonce section or due to
2167214082Sdim		     linker script /DISCARD/, so we'll be discarding
2168214082Sdim		     the relocs too.  */
2169214082Sdim		}
2170214082Sdim	      else if (p->count != 0)
2171214082Sdim		{
2172214082Sdim		  srel = elf_section_data (p->sec)->sreloc;
2173214082Sdim		  srel->size += p->count * SPARC_ELF_RELA_BYTES (htab);
2174214082Sdim		  if ((p->sec->output_section->flags & SEC_READONLY) != 0)
2175214082Sdim		    info->flags |= DF_TEXTREL;
2176214082Sdim		}
2177214082Sdim	    }
2178214082Sdim	}
2179214082Sdim
2180214082Sdim      local_got = elf_local_got_refcounts (ibfd);
2181214082Sdim      if (!local_got)
2182214082Sdim	continue;
2183214082Sdim
2184214082Sdim      symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
2185214082Sdim      locsymcount = symtab_hdr->sh_info;
2186214082Sdim      end_local_got = local_got + locsymcount;
2187214082Sdim      local_tls_type = _bfd_sparc_elf_local_got_tls_type (ibfd);
2188214082Sdim      s = htab->sgot;
2189214082Sdim      srel = htab->srelgot;
2190214082Sdim      for (; local_got < end_local_got; ++local_got, ++local_tls_type)
2191214082Sdim	{
2192214082Sdim	  if (*local_got > 0)
2193214082Sdim	    {
2194214082Sdim	      *local_got = s->size;
2195214082Sdim	      s->size += SPARC_ELF_WORD_BYTES (htab);
2196214082Sdim	      if (*local_tls_type == GOT_TLS_GD)
2197214082Sdim		s->size += SPARC_ELF_WORD_BYTES (htab);
2198214082Sdim	      if (info->shared
2199214082Sdim		  || *local_tls_type == GOT_TLS_GD
2200214082Sdim		  || *local_tls_type == GOT_TLS_IE)
2201214082Sdim		srel->size += SPARC_ELF_RELA_BYTES (htab);
2202214082Sdim	    }
2203214082Sdim	  else
2204214082Sdim	    *local_got = (bfd_vma) -1;
2205214082Sdim	}
2206214082Sdim    }
2207214082Sdim
2208214082Sdim  if (htab->tls_ldm_got.refcount > 0)
2209214082Sdim    {
2210214082Sdim      /* Allocate 2 got entries and 1 dynamic reloc for
2211214082Sdim	 R_SPARC_TLS_LDM_{HI22,LO10} relocs.  */
2212214082Sdim      htab->tls_ldm_got.offset = htab->sgot->size;
2213214082Sdim      htab->sgot->size += (2 * SPARC_ELF_WORD_BYTES (htab));
2214214082Sdim      htab->srelgot->size += SPARC_ELF_RELA_BYTES (htab);
2215214082Sdim    }
2216214082Sdim  else
2217214082Sdim    htab->tls_ldm_got.offset = -1;
2218214082Sdim
2219214082Sdim  /* Allocate global sym .plt and .got entries, and space for global
2220214082Sdim     sym dynamic relocs.  */
2221214082Sdim  elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, (PTR) info);
2222214082Sdim
2223214082Sdim  if (! ABI_64_P (output_bfd)
2224214082Sdim      && !htab->is_vxworks
2225214082Sdim      && elf_hash_table (info)->dynamic_sections_created)
2226214082Sdim    {
2227214082Sdim      /* Make space for the trailing nop in .plt.  */
2228214082Sdim      if (htab->splt->size > 0)
2229214082Sdim	htab->splt->size += 1 * SPARC_INSN_BYTES;
2230214082Sdim
2231214082Sdim      /* If the .got section is more than 0x1000 bytes, we add
2232214082Sdim	 0x1000 to the value of _GLOBAL_OFFSET_TABLE_, so that 13
2233214082Sdim	 bit relocations have a greater chance of working.
2234214082Sdim
2235214082Sdim	 FIXME: Make this optimization work for 64-bit too.  */
2236214082Sdim      if (htab->sgot->size >= 0x1000
2237214082Sdim	  && elf_hash_table (info)->hgot->root.u.def.value == 0)
2238214082Sdim	elf_hash_table (info)->hgot->root.u.def.value = 0x1000;
2239214082Sdim    }
2240214082Sdim
2241214082Sdim  /* The check_relocs and adjust_dynamic_symbol entry points have
2242214082Sdim     determined the sizes of the various dynamic sections.  Allocate
2243214082Sdim     memory for them.  */
2244214082Sdim  for (s = dynobj->sections; s != NULL; s = s->next)
2245214082Sdim    {
2246214082Sdim      if ((s->flags & SEC_LINKER_CREATED) == 0)
2247214082Sdim	continue;
2248214082Sdim
2249214082Sdim      if (s == htab->splt
2250214082Sdim	  || s == htab->sgot
2251214082Sdim	  || s == htab->sdynbss
2252214082Sdim	  || s == htab->sgotplt)
2253214082Sdim	{
2254214082Sdim	  /* Strip this section if we don't need it; see the
2255214082Sdim	     comment below.  */
2256214082Sdim	}
2257214634Sdim      else if (CONST_STRNEQ (s->name, ".rela"))
2258214082Sdim	{
2259214082Sdim	  if (s->size != 0)
2260214082Sdim	    {
2261214082Sdim	      /* We use the reloc_count field as a counter if we need
2262214082Sdim		 to copy relocs into the output file.  */
2263214082Sdim	      s->reloc_count = 0;
2264214082Sdim	    }
2265214082Sdim	}
2266214082Sdim      else
2267214082Sdim	{
2268214082Sdim	  /* It's not one of our sections.  */
2269214082Sdim	  continue;
2270214082Sdim	}
2271214082Sdim
2272214082Sdim      if (s->size == 0)
2273214082Sdim	{
2274214082Sdim	  /* If we don't need this section, strip it from the
2275214082Sdim	     output file.  This is mostly to handle .rela.bss and
2276214082Sdim	     .rela.plt.  We must create both sections in
2277214082Sdim	     create_dynamic_sections, because they must be created
2278214082Sdim	     before the linker maps input sections to output
2279214082Sdim	     sections.  The linker does that before
2280214082Sdim	     adjust_dynamic_symbol is called, and it is that
2281214082Sdim	     function which decides whether anything needs to go
2282214082Sdim	     into these sections.  */
2283214082Sdim	  s->flags |= SEC_EXCLUDE;
2284214082Sdim	  continue;
2285214082Sdim	}
2286214082Sdim
2287214082Sdim      if ((s->flags & SEC_HAS_CONTENTS) == 0)
2288214082Sdim	continue;
2289214082Sdim
2290214082Sdim      /* Allocate memory for the section contents.  Zero the memory
2291214082Sdim	 for the benefit of .rela.plt, which has 4 unused entries
2292214082Sdim	 at the beginning, and we don't want garbage.  */
2293214082Sdim      s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size);
2294214082Sdim      if (s->contents == NULL)
2295214082Sdim	return FALSE;
2296214082Sdim    }
2297214082Sdim
2298214082Sdim  if (elf_hash_table (info)->dynamic_sections_created)
2299214082Sdim    {
2300214082Sdim      /* Add some entries to the .dynamic section.  We fill in the
2301214082Sdim	 values later, in _bfd_sparc_elf_finish_dynamic_sections, but we
2302214082Sdim	 must add the entries now so that we get the correct size for
2303214082Sdim	 the .dynamic section.  The DT_DEBUG entry is filled in by the
2304214082Sdim	 dynamic linker and used by the debugger.  */
2305214082Sdim#define add_dynamic_entry(TAG, VAL) \
2306214082Sdim  _bfd_elf_add_dynamic_entry (info, TAG, VAL)
2307214082Sdim
2308214082Sdim      if (info->executable)
2309214082Sdim	{
2310214082Sdim	  if (!add_dynamic_entry (DT_DEBUG, 0))
2311214082Sdim	    return FALSE;
2312214082Sdim	}
2313214082Sdim
2314214082Sdim      if (htab->srelplt->size != 0)
2315214082Sdim	{
2316214082Sdim	  if (!add_dynamic_entry (DT_PLTGOT, 0)
2317214082Sdim	      || !add_dynamic_entry (DT_PLTRELSZ, 0)
2318214082Sdim	      || !add_dynamic_entry (DT_PLTREL, DT_RELA)
2319214082Sdim	      || !add_dynamic_entry (DT_JMPREL, 0))
2320214082Sdim	    return FALSE;
2321214082Sdim	}
2322214082Sdim
2323214082Sdim      if (!add_dynamic_entry (DT_RELA, 0)
2324214082Sdim	  || !add_dynamic_entry (DT_RELASZ, 0)
2325214082Sdim	  || !add_dynamic_entry (DT_RELAENT,
2326214082Sdim				 SPARC_ELF_RELA_BYTES (htab)))
2327214082Sdim	return FALSE;
2328214082Sdim
2329214082Sdim      /* If any dynamic relocs apply to a read-only section,
2330214082Sdim	 then we need a DT_TEXTREL entry.  */
2331214082Sdim      if ((info->flags & DF_TEXTREL) == 0)
2332214082Sdim	elf_link_hash_traverse (&htab->elf, readonly_dynrelocs,
2333214082Sdim				(PTR) info);
2334214082Sdim
2335214082Sdim      if (info->flags & DF_TEXTREL)
2336214082Sdim	{
2337214082Sdim	  if (!add_dynamic_entry (DT_TEXTREL, 0))
2338214082Sdim	    return FALSE;
2339214082Sdim	}
2340214082Sdim
2341214082Sdim      if (ABI_64_P (output_bfd))
2342214082Sdim	{
2343214082Sdim	  int reg;
2344214082Sdim	  struct _bfd_sparc_elf_app_reg * app_regs;
2345214082Sdim	  struct elf_strtab_hash *dynstr;
2346214082Sdim	  struct elf_link_hash_table *eht = elf_hash_table (info);
2347214082Sdim
2348214082Sdim	  /* Add dynamic STT_REGISTER symbols and corresponding DT_SPARC_REGISTER
2349214082Sdim	     entries if needed.  */
2350214082Sdim	  app_regs = _bfd_sparc_elf_hash_table (info)->app_regs;
2351214082Sdim	  dynstr = eht->dynstr;
2352214082Sdim
2353214082Sdim	  for (reg = 0; reg < 4; reg++)
2354214082Sdim	    if (app_regs [reg].name != NULL)
2355214082Sdim	      {
2356214082Sdim		struct elf_link_local_dynamic_entry *entry, *e;
2357214082Sdim
2358214082Sdim		if (!add_dynamic_entry (DT_SPARC_REGISTER, 0))
2359214082Sdim		  return FALSE;
2360214082Sdim
2361214082Sdim		entry = (struct elf_link_local_dynamic_entry *)
2362214082Sdim		  bfd_hash_allocate (&info->hash->table, sizeof (*entry));
2363214082Sdim		if (entry == NULL)
2364214082Sdim		  return FALSE;
2365214082Sdim
2366214082Sdim		/* We cheat here a little bit: the symbol will not be local, so we
2367214082Sdim		   put it at the end of the dynlocal linked list.  We will fix it
2368214082Sdim		   later on, as we have to fix other fields anyway.  */
2369214082Sdim		entry->isym.st_value = reg < 2 ? reg + 2 : reg + 4;
2370214082Sdim		entry->isym.st_size = 0;
2371214082Sdim		if (*app_regs [reg].name != '\0')
2372214082Sdim		  entry->isym.st_name
2373214082Sdim		    = _bfd_elf_strtab_add (dynstr, app_regs[reg].name, FALSE);
2374214082Sdim		else
2375214082Sdim		  entry->isym.st_name = 0;
2376214082Sdim		entry->isym.st_other = 0;
2377214082Sdim		entry->isym.st_info = ELF_ST_INFO (app_regs [reg].bind,
2378214082Sdim						   STT_REGISTER);
2379214082Sdim		entry->isym.st_shndx = app_regs [reg].shndx;
2380214082Sdim		entry->next = NULL;
2381214082Sdim		entry->input_bfd = output_bfd;
2382214082Sdim		entry->input_indx = -1;
2383214082Sdim
2384214082Sdim		if (eht->dynlocal == NULL)
2385214082Sdim		  eht->dynlocal = entry;
2386214082Sdim		else
2387214082Sdim		  {
2388214082Sdim		    for (e = eht->dynlocal; e->next; e = e->next)
2389214082Sdim		      ;
2390214082Sdim		    e->next = entry;
2391214082Sdim		  }
2392214082Sdim		eht->dynsymcount++;
2393214082Sdim	      }
2394214082Sdim	}
2395214082Sdim    }
2396214082Sdim#undef add_dynamic_entry
2397214082Sdim
2398214082Sdim  return TRUE;
2399214082Sdim}
2400214082Sdim
2401214082Sdimbfd_boolean
2402214082Sdim_bfd_sparc_elf_new_section_hook (bfd *abfd, asection *sec)
2403214082Sdim{
2404214634Sdim  if (!sec->used_by_bfd)
2405214634Sdim    {
2406214634Sdim      struct _bfd_sparc_elf_section_data *sdata;
2407214634Sdim      bfd_size_type amt = sizeof (*sdata);
2408214082Sdim
2409214634Sdim      sdata = bfd_zalloc (abfd, amt);
2410214634Sdim      if (sdata == NULL)
2411214634Sdim	return FALSE;
2412214634Sdim      sec->used_by_bfd = sdata;
2413214634Sdim    }
2414214082Sdim
2415214082Sdim  return _bfd_elf_new_section_hook (abfd, sec);
2416214082Sdim}
2417214082Sdim
2418214082Sdimbfd_boolean
2419214082Sdim_bfd_sparc_elf_relax_section (bfd *abfd ATTRIBUTE_UNUSED,
2420214082Sdim			      struct bfd_section *section,
2421214082Sdim			      struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
2422214082Sdim			      bfd_boolean *again)
2423214082Sdim{
2424214082Sdim  *again = FALSE;
2425214082Sdim  sec_do_relax (section) = 1;
2426214082Sdim  return TRUE;
2427214082Sdim}
2428214082Sdim
2429214082Sdim/* Return the base VMA address which should be subtracted from real addresses
2430214082Sdim   when resolving @dtpoff relocation.
2431214082Sdim   This is PT_TLS segment p_vaddr.  */
2432214082Sdim
2433214082Sdimstatic bfd_vma
2434214082Sdimdtpoff_base (struct bfd_link_info *info)
2435214082Sdim{
2436214082Sdim  /* If tls_sec is NULL, we should have signalled an error already.  */
2437214082Sdim  if (elf_hash_table (info)->tls_sec == NULL)
2438214082Sdim    return 0;
2439214082Sdim  return elf_hash_table (info)->tls_sec->vma;
2440214082Sdim}
2441214082Sdim
2442214082Sdim/* Return the relocation value for @tpoff relocation
2443214082Sdim   if STT_TLS virtual address is ADDRESS.  */
2444214082Sdim
2445214082Sdimstatic bfd_vma
2446214082Sdimtpoff (struct bfd_link_info *info, bfd_vma address)
2447214082Sdim{
2448214082Sdim  struct elf_link_hash_table *htab = elf_hash_table (info);
2449214082Sdim
2450214082Sdim  /* If tls_sec is NULL, we should have signalled an error already.  */
2451214082Sdim  if (htab->tls_sec == NULL)
2452214082Sdim    return 0;
2453214082Sdim  return address - htab->tls_size - htab->tls_sec->vma;
2454214082Sdim}
2455214082Sdim
2456214082Sdim/* Relocate a SPARC ELF section.  */
2457214082Sdim
2458214082Sdimbfd_boolean
2459214634Sdim_bfd_sparc_elf_relocate_section (bfd *output_bfd,
2460214634Sdim				 struct bfd_link_info *info,
2461214634Sdim				 bfd *input_bfd,
2462214634Sdim				 asection *input_section,
2463214634Sdim				 bfd_byte *contents,
2464214634Sdim				 Elf_Internal_Rela *relocs,
2465214634Sdim				 Elf_Internal_Sym *local_syms,
2466214634Sdim				 asection **local_sections)
2467214082Sdim{
2468214082Sdim  struct _bfd_sparc_elf_link_hash_table *htab;
2469214082Sdim  Elf_Internal_Shdr *symtab_hdr;
2470214082Sdim  struct elf_link_hash_entry **sym_hashes;
2471214082Sdim  bfd_vma *local_got_offsets;
2472214082Sdim  bfd_vma got_base;
2473214082Sdim  asection *sreloc;
2474214082Sdim  Elf_Internal_Rela *rel;
2475214082Sdim  Elf_Internal_Rela *relend;
2476214082Sdim  int num_relocs;
2477219530Smarius  const struct elf_backend_data *bed;
2478214082Sdim
2479214082Sdim  htab = _bfd_sparc_elf_hash_table (info);
2480214082Sdim  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
2481214082Sdim  sym_hashes = elf_sym_hashes (input_bfd);
2482214082Sdim  local_got_offsets = elf_local_got_offsets (input_bfd);
2483219530Smarius  bed = get_elf_backend_data (output_bfd);
2484214082Sdim
2485214082Sdim  if (elf_hash_table (info)->hgot == NULL)
2486214082Sdim    got_base = 0;
2487214082Sdim  else
2488214082Sdim    got_base = elf_hash_table (info)->hgot->root.u.def.value;
2489214082Sdim
2490214082Sdim  sreloc = elf_section_data (input_section)->sreloc;
2491214082Sdim
2492214082Sdim  rel = relocs;
2493214082Sdim  if (ABI_64_P (output_bfd))
2494214082Sdim    num_relocs = NUM_SHDR_ENTRIES (& elf_section_data (input_section)->rel_hdr);
2495214082Sdim  else
2496214082Sdim    num_relocs = input_section->reloc_count;
2497214082Sdim  relend = relocs + num_relocs;
2498214082Sdim  for (; rel < relend; rel++)
2499214082Sdim    {
2500214082Sdim      int r_type, tls_type;
2501214082Sdim      reloc_howto_type *howto;
2502214082Sdim      unsigned long r_symndx;
2503214082Sdim      struct elf_link_hash_entry *h;
2504214082Sdim      Elf_Internal_Sym *sym;
2505214082Sdim      asection *sec;
2506214082Sdim      bfd_vma relocation, off;
2507214082Sdim      bfd_reloc_status_type r;
2508214082Sdim      bfd_boolean is_plt = FALSE;
2509214082Sdim      bfd_boolean unresolved_reloc;
2510214082Sdim
2511214082Sdim      r_type = SPARC_ELF_R_TYPE (rel->r_info);
2512214082Sdim      if (r_type == R_SPARC_GNU_VTINHERIT
2513214082Sdim	  || r_type == R_SPARC_GNU_VTENTRY)
2514214082Sdim	continue;
2515214082Sdim
2516214082Sdim      if (r_type < 0 || r_type >= (int) R_SPARC_max_std)
2517214082Sdim	{
2518214082Sdim	  bfd_set_error (bfd_error_bad_value);
2519214082Sdim	  return FALSE;
2520214082Sdim	}
2521214082Sdim      howto = _bfd_sparc_elf_howto_table + r_type;
2522214082Sdim
2523214082Sdim      r_symndx = SPARC_ELF_R_SYMNDX (htab, rel->r_info);
2524214082Sdim      h = NULL;
2525214082Sdim      sym = NULL;
2526214082Sdim      sec = NULL;
2527214082Sdim      unresolved_reloc = FALSE;
2528214082Sdim      if (r_symndx < symtab_hdr->sh_info)
2529214082Sdim	{
2530214082Sdim	  sym = local_syms + r_symndx;
2531214082Sdim	  sec = local_sections[r_symndx];
2532214082Sdim	  relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
2533214082Sdim	}
2534214082Sdim      else
2535214082Sdim	{
2536214082Sdim	  bfd_boolean warned;
2537214082Sdim
2538214082Sdim	  RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
2539214082Sdim				   r_symndx, symtab_hdr, sym_hashes,
2540214082Sdim				   h, sec, relocation,
2541214082Sdim				   unresolved_reloc, warned);
2542214082Sdim	  if (warned)
2543214082Sdim	    {
2544214082Sdim	      /* To avoid generating warning messages about truncated
2545214082Sdim		 relocations, set the relocation's address to be the same as
2546214082Sdim		 the start of this section.  */
2547214082Sdim	      if (input_section->output_section != NULL)
2548214082Sdim		relocation = input_section->output_section->vma;
2549214082Sdim	      else
2550214082Sdim		relocation = 0;
2551214082Sdim	    }
2552214082Sdim	}
2553214082Sdim
2554214634Sdim      if (sec != NULL && elf_discarded_section (sec))
2555214634Sdim	{
2556214634Sdim	  /* For relocs against symbols from removed linkonce
2557214634Sdim	     sections, or sections discarded by a linker script, we
2558214634Sdim	     just want the section contents zeroed.  Avoid any
2559214634Sdim	     special processing.  */
2560214634Sdim	  _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
2561214634Sdim	  rel->r_info = 0;
2562214634Sdim	  rel->r_addend = 0;
2563214634Sdim	  continue;
2564214634Sdim	}
2565214634Sdim
2566214634Sdim      if (info->relocatable)
2567214634Sdim	continue;
2568214634Sdim
2569214082Sdim      switch (r_type)
2570214082Sdim	{
2571214082Sdim	case R_SPARC_GOT10:
2572214082Sdim	case R_SPARC_GOT13:
2573214082Sdim	case R_SPARC_GOT22:
2574214082Sdim	  /* Relocation is to the entry for this symbol in the global
2575214082Sdim	     offset table.  */
2576214082Sdim	  if (htab->sgot == NULL)
2577214082Sdim	    abort ();
2578214082Sdim
2579214082Sdim	  if (h != NULL)
2580214082Sdim	    {
2581214082Sdim	      bfd_boolean dyn;
2582214082Sdim
2583214082Sdim	      off = h->got.offset;
2584214082Sdim	      BFD_ASSERT (off != (bfd_vma) -1);
2585214082Sdim	      dyn = elf_hash_table (info)->dynamic_sections_created;
2586214082Sdim
2587214082Sdim	      if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h)
2588214082Sdim		  || (info->shared
2589214082Sdim		      && (info->symbolic
2590214082Sdim			  || h->dynindx == -1
2591214082Sdim			  || h->forced_local)
2592214082Sdim		      && h->def_regular))
2593214082Sdim		{
2594214082Sdim		  /* This is actually a static link, or it is a
2595214082Sdim		     -Bsymbolic link and the symbol is defined
2596214082Sdim		     locally, or the symbol was forced to be local
2597214082Sdim		     because of a version file.  We must initialize
2598214082Sdim		     this entry in the global offset table.  Since the
2599214082Sdim		     offset must always be a multiple of 8 for 64-bit
2600214082Sdim		     and 4 for 32-bit, we use the least significant bit
2601214082Sdim		     to record whether we have initialized it already.
2602214082Sdim
2603214082Sdim		     When doing a dynamic link, we create a .rela.got
2604214082Sdim		     relocation entry to initialize the value.  This
2605214082Sdim		     is done in the finish_dynamic_symbol routine.  */
2606214082Sdim		  if ((off & 1) != 0)
2607214082Sdim		    off &= ~1;
2608214082Sdim		  else
2609214082Sdim		    {
2610214082Sdim		      SPARC_ELF_PUT_WORD (htab, output_bfd, relocation,
2611214082Sdim					  htab->sgot->contents + off);
2612214082Sdim		      h->got.offset |= 1;
2613214082Sdim		    }
2614214082Sdim		}
2615214082Sdim	      else
2616214082Sdim		unresolved_reloc = FALSE;
2617214082Sdim	    }
2618214082Sdim	  else
2619214082Sdim	    {
2620214082Sdim	      BFD_ASSERT (local_got_offsets != NULL
2621214082Sdim			  && local_got_offsets[r_symndx] != (bfd_vma) -1);
2622214082Sdim
2623214082Sdim	      off = local_got_offsets[r_symndx];
2624214082Sdim
2625214082Sdim	      /* The offset must always be a multiple of 8 on 64-bit and
2626214082Sdim		 4 on 32-bit.  We use the least significant bit to record
2627214082Sdim		 whether we have already processed this entry.  */
2628214082Sdim	      if ((off & 1) != 0)
2629214082Sdim		off &= ~1;
2630214082Sdim	      else
2631214082Sdim		{
2632214082Sdim
2633214082Sdim		  if (info->shared)
2634214082Sdim		    {
2635214082Sdim		      asection *s;
2636214082Sdim		      Elf_Internal_Rela outrel;
2637214082Sdim
2638214082Sdim		      /* We need to generate a R_SPARC_RELATIVE reloc
2639214082Sdim			 for the dynamic linker.  */
2640214082Sdim		      s = htab->srelgot;
2641214082Sdim		      BFD_ASSERT (s != NULL);
2642214082Sdim
2643214082Sdim		      outrel.r_offset = (htab->sgot->output_section->vma
2644214082Sdim					 + htab->sgot->output_offset
2645214082Sdim					 + off);
2646214082Sdim		      outrel.r_info = SPARC_ELF_R_INFO (htab, NULL,
2647214082Sdim							0, R_SPARC_RELATIVE);
2648214082Sdim		      outrel.r_addend = relocation;
2649214082Sdim		      relocation = 0;
2650214634Sdim		      sparc_elf_append_rela (output_bfd, s, &outrel);
2651214082Sdim		    }
2652214082Sdim
2653214082Sdim		  SPARC_ELF_PUT_WORD (htab, output_bfd, relocation,
2654214082Sdim				      htab->sgot->contents + off);
2655214082Sdim		  local_got_offsets[r_symndx] |= 1;
2656214082Sdim		}
2657214082Sdim	    }
2658214082Sdim	  relocation = htab->sgot->output_offset + off - got_base;
2659214082Sdim	  break;
2660214082Sdim
2661214082Sdim	case R_SPARC_PLT32:
2662214082Sdim	case R_SPARC_PLT64:
2663214082Sdim	  if (h == NULL || h->plt.offset == (bfd_vma) -1)
2664214082Sdim	    {
2665214082Sdim	      r_type = (r_type == R_SPARC_PLT32) ? R_SPARC_32 : R_SPARC_64;
2666214082Sdim	      goto r_sparc_plt32;
2667214082Sdim	    }
2668214082Sdim	  /* Fall through.  */
2669214082Sdim
2670214082Sdim	case R_SPARC_WPLT30:
2671214082Sdim	case R_SPARC_HIPLT22:
2672214082Sdim	case R_SPARC_LOPLT10:
2673214082Sdim	case R_SPARC_PCPLT32:
2674214082Sdim	case R_SPARC_PCPLT22:
2675214082Sdim	case R_SPARC_PCPLT10:
2676214082Sdim	r_sparc_wplt30:
2677214082Sdim	  /* Relocation is to the entry for this symbol in the
2678214082Sdim	     procedure linkage table.  */
2679214082Sdim
2680214082Sdim	  if (! ABI_64_P (output_bfd))
2681214082Sdim	    {
2682214082Sdim	      /* The Solaris native assembler will generate a WPLT30 reloc
2683214082Sdim		 for a local symbol if you assemble a call from one
2684214082Sdim		 section to another when using -K pic.  We treat it as
2685214082Sdim		 WDISP30.  */
2686214082Sdim	      if (h == NULL)
2687214082Sdim		break;
2688214082Sdim	    }
2689214082Sdim	  else
2690214082Sdim	    {
2691214082Sdim	      BFD_ASSERT (h != NULL);
2692214082Sdim	    }
2693214082Sdim
2694214082Sdim	  if (h->plt.offset == (bfd_vma) -1 || htab->splt == NULL)
2695214082Sdim	    {
2696214082Sdim	      /* We didn't make a PLT entry for this symbol.  This
2697214082Sdim		 happens when statically linking PIC code, or when
2698214082Sdim		 using -Bsymbolic.  */
2699214082Sdim	      break;
2700214082Sdim	    }
2701214082Sdim
2702214082Sdim	  relocation = (htab->splt->output_section->vma
2703214082Sdim			+ htab->splt->output_offset
2704214082Sdim			+ h->plt.offset);
2705214082Sdim	  unresolved_reloc = FALSE;
2706214082Sdim	  if (r_type == R_SPARC_PLT32 || r_type == R_SPARC_PLT64)
2707214082Sdim	    {
2708214082Sdim	      r_type = r_type == R_SPARC_PLT32 ? R_SPARC_32 : R_SPARC_64;
2709214082Sdim	      is_plt = TRUE;
2710214082Sdim	      goto r_sparc_plt32;
2711214082Sdim	    }
2712214082Sdim	  break;
2713214082Sdim
2714214082Sdim	case R_SPARC_PC10:
2715214082Sdim	case R_SPARC_PC22:
2716214082Sdim	case R_SPARC_PC_HH22:
2717214082Sdim	case R_SPARC_PC_HM10:
2718214082Sdim	case R_SPARC_PC_LM22:
2719214082Sdim	  if (h != NULL
2720214082Sdim	      && strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
2721214082Sdim	    break;
2722214082Sdim	  /* Fall through.  */
2723214082Sdim	case R_SPARC_DISP8:
2724214082Sdim	case R_SPARC_DISP16:
2725214082Sdim	case R_SPARC_DISP32:
2726214082Sdim	case R_SPARC_DISP64:
2727214082Sdim	case R_SPARC_WDISP30:
2728214082Sdim	case R_SPARC_WDISP22:
2729214082Sdim	case R_SPARC_WDISP19:
2730214082Sdim	case R_SPARC_WDISP16:
2731214082Sdim	case R_SPARC_8:
2732214082Sdim	case R_SPARC_16:
2733214082Sdim	case R_SPARC_32:
2734214082Sdim	case R_SPARC_HI22:
2735214082Sdim	case R_SPARC_22:
2736214082Sdim	case R_SPARC_13:
2737214082Sdim	case R_SPARC_LO10:
2738214082Sdim	case R_SPARC_UA16:
2739214082Sdim	case R_SPARC_UA32:
2740214082Sdim	case R_SPARC_10:
2741214082Sdim	case R_SPARC_11:
2742214082Sdim	case R_SPARC_64:
2743214082Sdim	case R_SPARC_OLO10:
2744214082Sdim	case R_SPARC_HH22:
2745214082Sdim	case R_SPARC_HM10:
2746214082Sdim	case R_SPARC_LM22:
2747214082Sdim	case R_SPARC_7:
2748214082Sdim	case R_SPARC_5:
2749214082Sdim	case R_SPARC_6:
2750214082Sdim	case R_SPARC_HIX22:
2751214082Sdim	case R_SPARC_LOX10:
2752214082Sdim	case R_SPARC_H44:
2753214082Sdim	case R_SPARC_M44:
2754214082Sdim	case R_SPARC_L44:
2755214082Sdim	case R_SPARC_UA64:
2756214082Sdim	r_sparc_plt32:
2757214634Sdim	  if ((input_section->flags & SEC_ALLOC) == 0)
2758214082Sdim	    break;
2759214082Sdim
2760214082Sdim	  if ((info->shared
2761214082Sdim	       && (h == NULL
2762214082Sdim		   || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
2763214082Sdim		   || h->root.type != bfd_link_hash_undefweak)
2764214082Sdim	       && (! howto->pc_relative
2765214082Sdim		   || (h != NULL
2766214082Sdim		       && h->dynindx != -1
2767214082Sdim		       && (! info->symbolic
2768214082Sdim			   || !h->def_regular))))
2769214082Sdim	      || (!info->shared
2770214082Sdim		  && h != NULL
2771214082Sdim		  && h->dynindx != -1
2772214082Sdim		  && !h->non_got_ref
2773214082Sdim		  && ((h->def_dynamic
2774214082Sdim		       && !h->def_regular)
2775214082Sdim		      || h->root.type == bfd_link_hash_undefweak
2776214082Sdim		      || h->root.type == bfd_link_hash_undefined)))
2777214082Sdim	    {
2778214082Sdim	      Elf_Internal_Rela outrel;
2779214082Sdim	      bfd_boolean skip, relocate = FALSE;
2780214082Sdim
2781214082Sdim	      /* When generating a shared object, these relocations
2782214082Sdim		 are copied into the output file to be resolved at run
2783214082Sdim		 time.  */
2784214082Sdim
2785214082Sdim	      BFD_ASSERT (sreloc != NULL);
2786214082Sdim
2787214082Sdim	      skip = FALSE;
2788214082Sdim
2789214082Sdim	      outrel.r_offset =
2790214082Sdim		_bfd_elf_section_offset (output_bfd, info, input_section,
2791214082Sdim					 rel->r_offset);
2792214082Sdim	      if (outrel.r_offset == (bfd_vma) -1)
2793214082Sdim		skip = TRUE;
2794214082Sdim	      else if (outrel.r_offset == (bfd_vma) -2)
2795214082Sdim		skip = TRUE, relocate = TRUE;
2796214082Sdim	      outrel.r_offset += (input_section->output_section->vma
2797214082Sdim				  + input_section->output_offset);
2798214082Sdim
2799214082Sdim	      /* Optimize unaligned reloc usage now that we know where
2800214082Sdim		 it finally resides.  */
2801214082Sdim	      switch (r_type)
2802214082Sdim		{
2803214082Sdim		case R_SPARC_16:
2804214082Sdim		  if (outrel.r_offset & 1)
2805214082Sdim		    r_type = R_SPARC_UA16;
2806214082Sdim		  break;
2807214082Sdim		case R_SPARC_UA16:
2808214082Sdim		  if (!(outrel.r_offset & 1))
2809214082Sdim		    r_type = R_SPARC_16;
2810214082Sdim		  break;
2811214082Sdim		case R_SPARC_32:
2812214082Sdim		  if (outrel.r_offset & 3)
2813214082Sdim		    r_type = R_SPARC_UA32;
2814214082Sdim		  break;
2815214082Sdim		case R_SPARC_UA32:
2816214082Sdim		  if (!(outrel.r_offset & 3))
2817214082Sdim		    r_type = R_SPARC_32;
2818214082Sdim		  break;
2819214082Sdim		case R_SPARC_64:
2820214082Sdim		  if (outrel.r_offset & 7)
2821214082Sdim		    r_type = R_SPARC_UA64;
2822214082Sdim		  break;
2823214082Sdim		case R_SPARC_UA64:
2824214082Sdim		  if (!(outrel.r_offset & 7))
2825214082Sdim		    r_type = R_SPARC_64;
2826214082Sdim		  break;
2827214082Sdim	  	case R_SPARC_DISP8:
2828214082Sdim		case R_SPARC_DISP16:
2829214082Sdim	  	case R_SPARC_DISP32:
2830214082Sdim	  	case R_SPARC_DISP64:
2831214082Sdim		  /* If the symbol is not dynamic, we should not keep
2832214082Sdim		     a dynamic relocation.  But an .rela.* slot has been
2833214082Sdim		     allocated for it, output R_SPARC_NONE.
2834214082Sdim		     FIXME: Add code tracking needed dynamic relocs as
2835214082Sdim		     e.g. i386 has.  */
2836214082Sdim		  if (h->dynindx == -1)
2837214082Sdim		    skip = TRUE, relocate = TRUE;
2838214082Sdim		  break;
2839214082Sdim		}
2840214082Sdim
2841214082Sdim	      if (skip)
2842214082Sdim		memset (&outrel, 0, sizeof outrel);
2843214082Sdim	      /* h->dynindx may be -1 if the symbol was marked to
2844214082Sdim		 become local.  */
2845214082Sdim	      else if (h != NULL && ! is_plt
2846214082Sdim		       && ((! info->symbolic && h->dynindx != -1)
2847214082Sdim			   || !h->def_regular))
2848214082Sdim		{
2849214082Sdim		  BFD_ASSERT (h->dynindx != -1);
2850214082Sdim		  outrel.r_info = SPARC_ELF_R_INFO (htab, rel, h->dynindx, r_type);
2851214082Sdim		  outrel.r_addend = rel->r_addend;
2852214082Sdim		}
2853214082Sdim	      else
2854214082Sdim		{
2855214082Sdim		  if (r_type == R_SPARC_32 || r_type == R_SPARC_64)
2856214082Sdim		    {
2857214082Sdim		      outrel.r_info = SPARC_ELF_R_INFO (htab, NULL,
2858214082Sdim							0, R_SPARC_RELATIVE);
2859214082Sdim		      outrel.r_addend = relocation + rel->r_addend;
2860214082Sdim		    }
2861214082Sdim		  else
2862214082Sdim		    {
2863214082Sdim		      long indx;
2864214082Sdim
2865214634Sdim		      outrel.r_addend = relocation + rel->r_addend;
2866214634Sdim
2867214082Sdim		      if (is_plt)
2868214082Sdim			sec = htab->splt;
2869214082Sdim
2870214082Sdim		      if (bfd_is_abs_section (sec))
2871214082Sdim			indx = 0;
2872214082Sdim		      else if (sec == NULL || sec->owner == NULL)
2873214082Sdim			{
2874214082Sdim			  bfd_set_error (bfd_error_bad_value);
2875214082Sdim			  return FALSE;
2876214082Sdim			}
2877214082Sdim		      else
2878214082Sdim			{
2879214082Sdim			  asection *osec;
2880214082Sdim
2881214082Sdim			  osec = sec->output_section;
2882214082Sdim			  indx = elf_section_data (osec)->dynindx;
2883214082Sdim
2884214634Sdim			  if (indx == 0)
2885214634Sdim			    {
2886214634Sdim			      osec = htab->elf.text_index_section;
2887214634Sdim			      indx = elf_section_data (osec)->dynindx;
2888214634Sdim			    }
2889214634Sdim
2890214082Sdim			  /* FIXME: we really should be able to link non-pic
2891214082Sdim			     shared libraries.  */
2892214082Sdim			  if (indx == 0)
2893214082Sdim			    {
2894214082Sdim			      BFD_FAIL ();
2895214082Sdim			      (*_bfd_error_handler)
2896214082Sdim				(_("%B: probably compiled without -fPIC?"),
2897214082Sdim				 input_bfd);
2898214082Sdim			      bfd_set_error (bfd_error_bad_value);
2899214082Sdim			      return FALSE;
2900214082Sdim			    }
2901219530Smarius
2902219530Smarius			  /* We are turning this relocation into one
2903219530Smarius			     against a section symbol, so subtract out
2904219530Smarius			     the output section's address but not the
2905219530Smarius			     offset of the input section in the output
2906219530Smarius			     section on OSes where ld.so doesn't expect
2907219530Smarius			     buggy relocs.  */
2908219530Smarius			  if (bed->elf_osabi == ELFOSABI_FREEBSD)
2909219530Smarius			    outrel.r_addend -= osec->vma;
2910214082Sdim			}
2911214082Sdim
2912214634Sdim		      outrel.r_info = SPARC_ELF_R_INFO (htab, rel, indx,
2913214634Sdim							r_type);
2914214082Sdim		    }
2915214082Sdim		}
2916214082Sdim
2917214634Sdim	      sparc_elf_append_rela (output_bfd, sreloc, &outrel);
2918214082Sdim
2919214082Sdim	      /* This reloc will be computed at runtime, so there's no
2920214082Sdim		 need to do anything now.  */
2921214082Sdim	      if (! relocate)
2922214082Sdim		continue;
2923214082Sdim	    }
2924214082Sdim	  break;
2925214082Sdim
2926214082Sdim	case R_SPARC_TLS_GD_HI22:
2927214082Sdim	  if (! ABI_64_P (input_bfd)
2928214082Sdim	      && ! _bfd_sparc_elf_tdata (input_bfd)->has_tlsgd)
2929214082Sdim	    {
2930214082Sdim	      /* R_SPARC_REV32 used the same reloc number as
2931214082Sdim		 R_SPARC_TLS_GD_HI22.  */
2932214082Sdim	      r_type = R_SPARC_REV32;
2933214082Sdim	      break;
2934214082Sdim	    }
2935214082Sdim	  /* Fall through */
2936214082Sdim
2937214082Sdim	case R_SPARC_TLS_GD_LO10:
2938214082Sdim	case R_SPARC_TLS_IE_HI22:
2939214082Sdim	case R_SPARC_TLS_IE_LO10:
2940214082Sdim	  r_type = sparc_elf_tls_transition (info, input_bfd, r_type, h == NULL);
2941214082Sdim	  tls_type = GOT_UNKNOWN;
2942214082Sdim	  if (h == NULL && local_got_offsets)
2943214082Sdim	    tls_type = _bfd_sparc_elf_local_got_tls_type (input_bfd) [r_symndx];
2944214082Sdim	  else if (h != NULL)
2945214082Sdim	    {
2946214082Sdim	      tls_type = _bfd_sparc_elf_hash_entry(h)->tls_type;
2947214082Sdim	      if (!info->shared && h->dynindx == -1 && tls_type == GOT_TLS_IE)
2948214082Sdim		switch (SPARC_ELF_R_TYPE (rel->r_info))
2949214082Sdim		  {
2950214082Sdim		  case R_SPARC_TLS_GD_HI22:
2951214082Sdim		  case R_SPARC_TLS_IE_HI22:
2952214082Sdim		    r_type = R_SPARC_TLS_LE_HIX22;
2953214082Sdim		    break;
2954214082Sdim		  default:
2955214082Sdim		    r_type = R_SPARC_TLS_LE_LOX10;
2956214082Sdim		    break;
2957214082Sdim		  }
2958214082Sdim	    }
2959214082Sdim	  if (tls_type == GOT_TLS_IE)
2960214082Sdim	    switch (r_type)
2961214082Sdim	      {
2962214082Sdim	      case R_SPARC_TLS_GD_HI22:
2963214082Sdim		r_type = R_SPARC_TLS_IE_HI22;
2964214082Sdim		break;
2965214082Sdim	      case R_SPARC_TLS_GD_LO10:
2966214082Sdim		r_type = R_SPARC_TLS_IE_LO10;
2967214082Sdim		break;
2968214082Sdim	      }
2969214082Sdim
2970214082Sdim	  if (r_type == R_SPARC_TLS_LE_HIX22)
2971214082Sdim	    {
2972214082Sdim	      relocation = tpoff (info, relocation);
2973214082Sdim	      break;
2974214082Sdim	    }
2975214082Sdim	  if (r_type == R_SPARC_TLS_LE_LOX10)
2976214082Sdim	    {
2977214082Sdim	      /* Change add into xor.  */
2978214082Sdim	      relocation = tpoff (info, relocation);
2979214082Sdim	      bfd_put_32 (output_bfd, (bfd_get_32 (input_bfd,
2980214082Sdim						   contents + rel->r_offset)
2981214082Sdim				       | 0x80182000), contents + rel->r_offset);
2982214082Sdim	      break;
2983214082Sdim	    }
2984214082Sdim
2985214082Sdim	  if (h != NULL)
2986214082Sdim	    {
2987214082Sdim	      off = h->got.offset;
2988214082Sdim	      h->got.offset |= 1;
2989214082Sdim	    }
2990214082Sdim	  else
2991214082Sdim	    {
2992214082Sdim	      BFD_ASSERT (local_got_offsets != NULL);
2993214082Sdim	      off = local_got_offsets[r_symndx];
2994214082Sdim	      local_got_offsets[r_symndx] |= 1;
2995214082Sdim	    }
2996214082Sdim
2997214082Sdim	r_sparc_tlsldm:
2998214082Sdim	  if (htab->sgot == NULL)
2999214082Sdim	    abort ();
3000214082Sdim
3001214082Sdim	  if ((off & 1) != 0)
3002214082Sdim	    off &= ~1;
3003214082Sdim	  else
3004214082Sdim	    {
3005214082Sdim	      Elf_Internal_Rela outrel;
3006214082Sdim	      int dr_type, indx;
3007214082Sdim
3008214082Sdim	      if (htab->srelgot == NULL)
3009214082Sdim		abort ();
3010214082Sdim
3011214082Sdim	      SPARC_ELF_PUT_WORD (htab, output_bfd, 0, htab->sgot->contents + off);
3012214082Sdim	      outrel.r_offset = (htab->sgot->output_section->vma
3013214082Sdim				 + htab->sgot->output_offset + off);
3014214082Sdim	      indx = h && h->dynindx != -1 ? h->dynindx : 0;
3015214082Sdim	      if (r_type == R_SPARC_TLS_IE_HI22
3016214082Sdim		  || r_type == R_SPARC_TLS_IE_LO10)
3017214082Sdim		dr_type = SPARC_ELF_TPOFF_RELOC (htab);
3018214082Sdim	      else
3019214082Sdim		dr_type = SPARC_ELF_DTPMOD_RELOC (htab);
3020214082Sdim	      if (dr_type == SPARC_ELF_TPOFF_RELOC (htab) && indx == 0)
3021214082Sdim		outrel.r_addend = relocation - dtpoff_base (info);
3022214082Sdim	      else
3023214082Sdim		outrel.r_addend = 0;
3024214082Sdim	      outrel.r_info = SPARC_ELF_R_INFO (htab, NULL, indx, dr_type);
3025214634Sdim	      sparc_elf_append_rela (output_bfd, htab->srelgot, &outrel);
3026214082Sdim
3027214082Sdim	      if (r_type == R_SPARC_TLS_GD_HI22
3028214082Sdim		  || r_type == R_SPARC_TLS_GD_LO10)
3029214082Sdim		{
3030214082Sdim		  if (indx == 0)
3031214082Sdim		    {
3032214082Sdim	    	      BFD_ASSERT (! unresolved_reloc);
3033214082Sdim		      SPARC_ELF_PUT_WORD (htab, output_bfd,
3034214082Sdim					  relocation - dtpoff_base (info),
3035214082Sdim					  (htab->sgot->contents + off
3036214082Sdim					   + SPARC_ELF_WORD_BYTES (htab)));
3037214082Sdim		    }
3038214082Sdim		  else
3039214082Sdim		    {
3040214082Sdim		      SPARC_ELF_PUT_WORD (htab, output_bfd, 0,
3041214082Sdim					  (htab->sgot->contents + off
3042214082Sdim					   + SPARC_ELF_WORD_BYTES (htab)));
3043214082Sdim		      outrel.r_info = SPARC_ELF_R_INFO (htab, NULL, indx,
3044214082Sdim							SPARC_ELF_DTPOFF_RELOC (htab));
3045214082Sdim		      outrel.r_offset += SPARC_ELF_WORD_BYTES (htab);
3046214634Sdim		      sparc_elf_append_rela (output_bfd, htab->srelgot,
3047214634Sdim					     &outrel);
3048214082Sdim		    }
3049214082Sdim		}
3050214082Sdim	      else if (dr_type == SPARC_ELF_DTPMOD_RELOC (htab))
3051214082Sdim		{
3052214082Sdim		  SPARC_ELF_PUT_WORD (htab, output_bfd, 0,
3053214082Sdim				      (htab->sgot->contents + off
3054214082Sdim				       + SPARC_ELF_WORD_BYTES (htab)));
3055214082Sdim		}
3056214082Sdim	    }
3057214082Sdim
3058214082Sdim	  if (off >= (bfd_vma) -2)
3059214082Sdim	    abort ();
3060214082Sdim
3061214082Sdim	  relocation = htab->sgot->output_offset + off - got_base;
3062214082Sdim	  unresolved_reloc = FALSE;
3063214082Sdim	  howto = _bfd_sparc_elf_howto_table + r_type;
3064214082Sdim	  break;
3065214082Sdim
3066214082Sdim	case R_SPARC_TLS_LDM_HI22:
3067214082Sdim	case R_SPARC_TLS_LDM_LO10:
3068214082Sdim	  if (! info->shared)
3069214082Sdim	    {
3070214082Sdim	      bfd_put_32 (output_bfd, SPARC_NOP, contents + rel->r_offset);
3071214082Sdim	      continue;
3072214082Sdim	    }
3073214082Sdim	  off = htab->tls_ldm_got.offset;
3074214082Sdim	  htab->tls_ldm_got.offset |= 1;
3075214082Sdim	  goto r_sparc_tlsldm;
3076214082Sdim
3077214082Sdim	case R_SPARC_TLS_LDO_HIX22:
3078214082Sdim	case R_SPARC_TLS_LDO_LOX10:
3079214082Sdim	  if (info->shared)
3080214082Sdim	    {
3081214082Sdim	      relocation -= dtpoff_base (info);
3082214082Sdim	      break;
3083214082Sdim	    }
3084214082Sdim
3085214082Sdim	  r_type = (r_type == R_SPARC_TLS_LDO_HIX22
3086214082Sdim		    ? R_SPARC_TLS_LE_HIX22 : R_SPARC_TLS_LE_LOX10);
3087214082Sdim	  /* Fall through.  */
3088214082Sdim
3089214082Sdim	case R_SPARC_TLS_LE_HIX22:
3090214082Sdim	case R_SPARC_TLS_LE_LOX10:
3091214082Sdim	  if (info->shared)
3092214082Sdim	    {
3093214082Sdim	      Elf_Internal_Rela outrel;
3094214082Sdim	      bfd_boolean skip, relocate = FALSE;
3095214082Sdim
3096214082Sdim	      BFD_ASSERT (sreloc != NULL);
3097214082Sdim	      skip = FALSE;
3098214082Sdim	      outrel.r_offset =
3099214082Sdim		_bfd_elf_section_offset (output_bfd, info, input_section,
3100214082Sdim					 rel->r_offset);
3101214082Sdim	      if (outrel.r_offset == (bfd_vma) -1)
3102214082Sdim		skip = TRUE;
3103214082Sdim	      else if (outrel.r_offset == (bfd_vma) -2)
3104214082Sdim		skip = TRUE, relocate = TRUE;
3105214082Sdim	      outrel.r_offset += (input_section->output_section->vma
3106214082Sdim				  + input_section->output_offset);
3107214082Sdim	      if (skip)
3108214082Sdim		memset (&outrel, 0, sizeof outrel);
3109214082Sdim	      else
3110214082Sdim		{
3111214082Sdim		  outrel.r_info = SPARC_ELF_R_INFO (htab, NULL, 0, r_type);
3112214082Sdim		  outrel.r_addend = relocation - dtpoff_base (info)
3113214082Sdim				    + rel->r_addend;
3114214082Sdim		}
3115214082Sdim
3116214634Sdim	      sparc_elf_append_rela (output_bfd, sreloc, &outrel);
3117214082Sdim	      continue;
3118214082Sdim	    }
3119214082Sdim	  relocation = tpoff (info, relocation);
3120214082Sdim	  break;
3121214082Sdim
3122214082Sdim	case R_SPARC_TLS_LDM_CALL:
3123214082Sdim	  if (! info->shared)
3124214082Sdim	    {
3125214082Sdim	      /* mov %g0, %o0 */
3126214082Sdim	      bfd_put_32 (output_bfd, 0x90100000, contents + rel->r_offset);
3127214082Sdim	      continue;
3128214082Sdim	    }
3129214082Sdim	  /* Fall through */
3130214082Sdim
3131214082Sdim	case R_SPARC_TLS_GD_CALL:
3132214082Sdim	  tls_type = GOT_UNKNOWN;
3133214082Sdim	  if (h == NULL && local_got_offsets)
3134214082Sdim	    tls_type = _bfd_sparc_elf_local_got_tls_type (input_bfd) [r_symndx];
3135214082Sdim	  else if (h != NULL)
3136214082Sdim	    tls_type = _bfd_sparc_elf_hash_entry(h)->tls_type;
3137214082Sdim	  if (! info->shared
3138214082Sdim	      || (r_type == R_SPARC_TLS_GD_CALL && tls_type == GOT_TLS_IE))
3139214082Sdim	    {
3140214082Sdim	      bfd_vma insn;
3141214082Sdim
3142214082Sdim	      if (!info->shared && (h == NULL || h->dynindx == -1))
3143214082Sdim		{
3144214082Sdim		  /* GD -> LE */
3145214082Sdim		  bfd_put_32 (output_bfd, SPARC_NOP, contents + rel->r_offset);
3146214082Sdim		  continue;
3147214082Sdim		}
3148214082Sdim
3149214082Sdim	      /* GD -> IE */
3150214082Sdim	      if (rel + 1 < relend
3151214082Sdim		  && SPARC_ELF_R_TYPE (rel[1].r_info) == R_SPARC_TLS_GD_ADD
3152214082Sdim		  && rel[1].r_offset == rel->r_offset + 4
3153214082Sdim		  && SPARC_ELF_R_SYMNDX (htab, rel[1].r_info) == r_symndx
3154214082Sdim		  && (((insn = bfd_get_32 (input_bfd,
3155214082Sdim					   contents + rel[1].r_offset))
3156214082Sdim		       >> 25) & 0x1f) == 8)
3157214082Sdim		{
3158214082Sdim		  /* We have
3159214082Sdim		     call __tls_get_addr, %tgd_call(foo)
3160214082Sdim		      add %reg1, %reg2, %o0, %tgd_add(foo)
3161214082Sdim		     and change it into IE:
3162214082Sdim		     {ld,ldx} [%reg1 + %reg2], %o0, %tie_ldx(foo)
3163214082Sdim		     add %g7, %o0, %o0, %tie_add(foo).
3164214082Sdim		     add is 0x80000000 | (rd << 25) | (rs1 << 14) | rs2,
3165214082Sdim		     ld is 0xc0000000 | (rd << 25) | (rs1 << 14) | rs2,
3166214082Sdim		     ldx is 0xc0580000 | (rd << 25) | (rs1 << 14) | rs2.  */
3167214082Sdim		  bfd_put_32 (output_bfd, insn | (ABI_64_P (output_bfd) ? 0xc0580000 : 0xc0000000),
3168214082Sdim			      contents + rel->r_offset);
3169214082Sdim		  bfd_put_32 (output_bfd, 0x9001c008,
3170214082Sdim			      contents + rel->r_offset + 4);
3171214082Sdim		  rel++;
3172214082Sdim		  continue;
3173214082Sdim		}
3174214082Sdim
3175214082Sdim	      bfd_put_32 (output_bfd, 0x9001c008, contents + rel->r_offset);
3176214082Sdim	      continue;
3177214082Sdim	    }
3178214082Sdim
3179214082Sdim	  h = (struct elf_link_hash_entry *)
3180214082Sdim	      bfd_link_hash_lookup (info->hash, "__tls_get_addr", FALSE,
3181214082Sdim				    FALSE, TRUE);
3182214082Sdim	  BFD_ASSERT (h != NULL);
3183214082Sdim	  r_type = R_SPARC_WPLT30;
3184214082Sdim	  howto = _bfd_sparc_elf_howto_table + r_type;
3185214082Sdim	  goto r_sparc_wplt30;
3186214082Sdim
3187214082Sdim	case R_SPARC_TLS_GD_ADD:
3188214082Sdim	  tls_type = GOT_UNKNOWN;
3189214082Sdim	  if (h == NULL && local_got_offsets)
3190214082Sdim	    tls_type = _bfd_sparc_elf_local_got_tls_type (input_bfd) [r_symndx];
3191214082Sdim	  else if (h != NULL)
3192214082Sdim	    tls_type = _bfd_sparc_elf_hash_entry(h)->tls_type;
3193214082Sdim	  if (! info->shared || tls_type == GOT_TLS_IE)
3194214082Sdim	    {
3195214082Sdim	      /* add %reg1, %reg2, %reg3, %tgd_add(foo)
3196214082Sdim		 changed into IE:
3197214082Sdim		 {ld,ldx} [%reg1 + %reg2], %reg3, %tie_ldx(foo)
3198214082Sdim		 or LE:
3199214082Sdim		 add %g7, %reg2, %reg3.  */
3200214082Sdim	      bfd_vma insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
3201214082Sdim	      if ((h != NULL && h->dynindx != -1) || info->shared)
3202214082Sdim		relocation = insn | (ABI_64_P (output_bfd) ? 0xc0580000 : 0xc0000000);
3203214082Sdim	      else
3204214082Sdim		relocation = (insn & ~0x7c000) | 0x1c000;
3205214082Sdim	      bfd_put_32 (output_bfd, relocation, contents + rel->r_offset);
3206214082Sdim	    }
3207214082Sdim	  continue;
3208214082Sdim
3209214082Sdim	case R_SPARC_TLS_LDM_ADD:
3210214082Sdim	  if (! info->shared)
3211214082Sdim	    bfd_put_32 (output_bfd, SPARC_NOP, contents + rel->r_offset);
3212214082Sdim	  continue;
3213214082Sdim
3214214082Sdim	case R_SPARC_TLS_LDO_ADD:
3215214082Sdim	  if (! info->shared)
3216214082Sdim	    {
3217214082Sdim	      /* Change rs1 into %g7.  */
3218214082Sdim	      bfd_vma insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
3219214082Sdim	      insn = (insn & ~0x7c000) | 0x1c000;
3220214082Sdim	      bfd_put_32 (output_bfd, insn, contents + rel->r_offset);
3221214082Sdim	    }
3222214082Sdim	  continue;
3223214082Sdim
3224214082Sdim	case R_SPARC_TLS_IE_LD:
3225214082Sdim	case R_SPARC_TLS_IE_LDX:
3226214082Sdim	  if (! info->shared && (h == NULL || h->dynindx == -1))
3227214082Sdim	    {
3228214082Sdim	      bfd_vma insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
3229214082Sdim	      int rs2 = insn & 0x1f;
3230214082Sdim	      int rd = (insn >> 25) & 0x1f;
3231214082Sdim
3232214082Sdim	      if (rs2 == rd)
3233214082Sdim		relocation = SPARC_NOP;
3234214082Sdim	      else
3235214082Sdim		relocation = 0x80100000 | (insn & 0x3e00001f);
3236214082Sdim	      bfd_put_32 (output_bfd, relocation, contents + rel->r_offset);
3237214082Sdim	    }
3238214082Sdim	  continue;
3239214082Sdim
3240214082Sdim	case R_SPARC_TLS_IE_ADD:
3241214082Sdim	  /* Totally useless relocation.  */
3242214082Sdim	  continue;
3243214082Sdim
3244214082Sdim	case R_SPARC_TLS_DTPOFF32:
3245214082Sdim	case R_SPARC_TLS_DTPOFF64:
3246214082Sdim	  relocation -= dtpoff_base (info);
3247214082Sdim	  break;
3248214082Sdim
3249214082Sdim	default:
3250214082Sdim	  break;
3251214082Sdim	}
3252214082Sdim
3253214082Sdim      /* Dynamic relocs are not propagated for SEC_DEBUGGING sections
3254214082Sdim	 because such sections are not SEC_ALLOC and thus ld.so will
3255214082Sdim	 not process them.  */
3256214082Sdim      if (unresolved_reloc
3257214082Sdim	  && !((input_section->flags & SEC_DEBUGGING) != 0
3258214082Sdim	       && h->def_dynamic))
3259214082Sdim	(*_bfd_error_handler)
3260214082Sdim	  (_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"),
3261214082Sdim	   input_bfd,
3262214082Sdim	   input_section,
3263214082Sdim	   (long) rel->r_offset,
3264214082Sdim	   howto->name,
3265214082Sdim	   h->root.root.string);
3266214082Sdim
3267214082Sdim      r = bfd_reloc_continue;
3268214082Sdim      if (r_type == R_SPARC_OLO10)
3269214082Sdim	{
3270214082Sdim	    bfd_vma x;
3271214082Sdim
3272214082Sdim	    if (! ABI_64_P (output_bfd))
3273214082Sdim	      abort ();
3274214082Sdim
3275214082Sdim	    relocation += rel->r_addend;
3276214082Sdim	    relocation = (relocation & 0x3ff) + ELF64_R_TYPE_DATA (rel->r_info);
3277214082Sdim
3278214082Sdim	    x = bfd_get_32 (input_bfd, contents + rel->r_offset);
3279214082Sdim	    x = (x & ~(bfd_vma) 0x1fff) | (relocation & 0x1fff);
3280214082Sdim	    bfd_put_32 (input_bfd, x, contents + rel->r_offset);
3281214082Sdim
3282214082Sdim	    r = bfd_check_overflow (howto->complain_on_overflow,
3283214082Sdim				    howto->bitsize, howto->rightshift,
3284214082Sdim				    bfd_arch_bits_per_address (input_bfd),
3285214082Sdim				    relocation);
3286214082Sdim	}
3287214082Sdim      else if (r_type == R_SPARC_WDISP16)
3288214082Sdim	{
3289214082Sdim	  bfd_vma x;
3290214082Sdim
3291214082Sdim	  relocation += rel->r_addend;
3292214082Sdim	  relocation -= (input_section->output_section->vma
3293214082Sdim			 + input_section->output_offset);
3294214082Sdim	  relocation -= rel->r_offset;
3295214082Sdim
3296214082Sdim	  x = bfd_get_32 (input_bfd, contents + rel->r_offset);
3297214082Sdim	  x |= ((((relocation >> 2) & 0xc000) << 6)
3298214082Sdim		| ((relocation >> 2) & 0x3fff));
3299214082Sdim	  bfd_put_32 (input_bfd, x, contents + rel->r_offset);
3300214082Sdim
3301214082Sdim	  r = bfd_check_overflow (howto->complain_on_overflow,
3302214082Sdim				  howto->bitsize, howto->rightshift,
3303214082Sdim				  bfd_arch_bits_per_address (input_bfd),
3304214082Sdim				  relocation);
3305214082Sdim	}
3306214082Sdim      else if (r_type == R_SPARC_REV32)
3307214082Sdim	{
3308214082Sdim	  bfd_vma x;
3309214082Sdim
3310214082Sdim	  relocation = relocation + rel->r_addend;
3311214082Sdim
3312214082Sdim	  x = bfd_get_32 (input_bfd, contents + rel->r_offset);
3313214082Sdim	  x = x + relocation;
3314214082Sdim	  bfd_putl32 (/*input_bfd,*/ x, contents + rel->r_offset);
3315214082Sdim	  r = bfd_reloc_ok;
3316214082Sdim	}
3317214082Sdim      else if (r_type == R_SPARC_TLS_LDO_HIX22
3318214082Sdim	       || r_type == R_SPARC_TLS_LE_HIX22)
3319214082Sdim	{
3320214082Sdim	  bfd_vma x;
3321214082Sdim
3322214082Sdim	  relocation += rel->r_addend;
3323214082Sdim	  if (r_type == R_SPARC_TLS_LE_HIX22)
3324214082Sdim	    relocation ^= MINUS_ONE;
3325214082Sdim
3326214082Sdim	  x = bfd_get_32 (input_bfd, contents + rel->r_offset);
3327214082Sdim	  x = (x & ~(bfd_vma) 0x3fffff) | ((relocation >> 10) & 0x3fffff);
3328214082Sdim	  bfd_put_32 (input_bfd, x, contents + rel->r_offset);
3329214082Sdim	  r = bfd_reloc_ok;
3330214082Sdim	}
3331214082Sdim      else if (r_type == R_SPARC_TLS_LDO_LOX10
3332214082Sdim	       || r_type == R_SPARC_TLS_LE_LOX10)
3333214082Sdim	{
3334214082Sdim	  bfd_vma x;
3335214082Sdim
3336214082Sdim	  relocation += rel->r_addend;
3337214082Sdim	  relocation &= 0x3ff;
3338214082Sdim	  if (r_type == R_SPARC_TLS_LE_LOX10)
3339214082Sdim	    relocation |= 0x1c00;
3340214082Sdim
3341214082Sdim	  x = bfd_get_32 (input_bfd, contents + rel->r_offset);
3342214082Sdim	  x = (x & ~(bfd_vma) 0x1fff) | relocation;
3343214082Sdim	  bfd_put_32 (input_bfd, x, contents + rel->r_offset);
3344214082Sdim
3345214082Sdim	  r = bfd_reloc_ok;
3346214082Sdim	}
3347214082Sdim      else if (r_type == R_SPARC_HIX22)
3348214082Sdim	{
3349214082Sdim	  bfd_vma x;
3350214082Sdim
3351214082Sdim	  relocation += rel->r_addend;
3352214082Sdim	  relocation = relocation ^ MINUS_ONE;
3353214082Sdim
3354214082Sdim	  x = bfd_get_32 (input_bfd, contents + rel->r_offset);
3355214082Sdim	  x = (x & ~(bfd_vma) 0x3fffff) | ((relocation >> 10) & 0x3fffff);
3356214082Sdim	  bfd_put_32 (input_bfd, x, contents + rel->r_offset);
3357214082Sdim
3358214082Sdim	  r = bfd_check_overflow (howto->complain_on_overflow,
3359214082Sdim				  howto->bitsize, howto->rightshift,
3360214082Sdim				  bfd_arch_bits_per_address (input_bfd),
3361214082Sdim				  relocation);
3362214082Sdim	}
3363214082Sdim      else if (r_type == R_SPARC_LOX10)
3364214082Sdim	{
3365214082Sdim	  bfd_vma x;
3366214082Sdim
3367214082Sdim	  relocation += rel->r_addend;
3368214082Sdim	  relocation = (relocation & 0x3ff) | 0x1c00;
3369214082Sdim
3370214082Sdim	  x = bfd_get_32 (input_bfd, contents + rel->r_offset);
3371214082Sdim	  x = (x & ~(bfd_vma) 0x1fff) | relocation;
3372214082Sdim	  bfd_put_32 (input_bfd, x, contents + rel->r_offset);
3373214082Sdim
3374214082Sdim	  r = bfd_reloc_ok;
3375214082Sdim	}
3376214082Sdim      else if ((r_type == R_SPARC_WDISP30 || r_type == R_SPARC_WPLT30)
3377214082Sdim	       && sec_do_relax (input_section)
3378214082Sdim	       && rel->r_offset + 4 < input_section->size)
3379214082Sdim	{
3380214082Sdim#define G0		0
3381214082Sdim#define O7		15
3382214082Sdim#define XCC		(2 << 20)
3383214082Sdim#define COND(x)		(((x)&0xf)<<25)
3384214082Sdim#define CONDA		COND(0x8)
3385214082Sdim#define INSN_BPA	(F2(0,1) | CONDA | BPRED | XCC)
3386214082Sdim#define INSN_BA		(F2(0,2) | CONDA)
3387214082Sdim#define INSN_OR		F3(2, 0x2, 0)
3388214082Sdim#define INSN_NOP	F2(0,4)
3389214082Sdim
3390214082Sdim	  bfd_vma x, y;
3391214082Sdim
3392214082Sdim	  /* If the instruction is a call with either:
3393214082Sdim	     restore
3394214082Sdim	     arithmetic instruction with rd == %o7
3395214082Sdim	     where rs1 != %o7 and rs2 if it is register != %o7
3396214082Sdim	     then we can optimize if the call destination is near
3397214082Sdim	     by changing the call into a branch always.  */
3398214082Sdim	  x = bfd_get_32 (input_bfd, contents + rel->r_offset);
3399214082Sdim	  y = bfd_get_32 (input_bfd, contents + rel->r_offset + 4);
3400214082Sdim	  if ((x & OP(~0)) == OP(1) && (y & OP(~0)) == OP(2))
3401214082Sdim	    {
3402214082Sdim	      if (((y & OP3(~0)) == OP3(0x3d) /* restore */
3403214082Sdim		   || ((y & OP3(0x28)) == 0 /* arithmetic */
3404214082Sdim		       && (y & RD(~0)) == RD(O7)))
3405214082Sdim		  && (y & RS1(~0)) != RS1(O7)
3406214082Sdim		  && ((y & F3I(~0))
3407214082Sdim		      || (y & RS2(~0)) != RS2(O7)))
3408214082Sdim		{
3409214082Sdim		  bfd_vma reloc;
3410214082Sdim
3411214082Sdim		  reloc = relocation + rel->r_addend - rel->r_offset;
3412214082Sdim		  reloc -= (input_section->output_section->vma
3413214082Sdim			    + input_section->output_offset);
3414214082Sdim
3415214082Sdim		  /* Ensure the branch fits into simm22.  */
3416214082Sdim		  if ((reloc & 3) == 0
3417214082Sdim		      && ((reloc & ~(bfd_vma)0x7fffff) == 0
3418214082Sdim			  || ((reloc | 0x7fffff) == ~(bfd_vma)0)))
3419214082Sdim		    {
3420214082Sdim		      reloc >>= 2;
3421214082Sdim
3422214082Sdim		      /* Check whether it fits into simm19.  */
3423214082Sdim		      if (((reloc & 0x3c0000) == 0
3424214082Sdim			   || (reloc & 0x3c0000) == 0x3c0000)
3425214082Sdim			  && (ABI_64_P (output_bfd)
3426214082Sdim			      || elf_elfheader (output_bfd)->e_flags & EF_SPARC_32PLUS))
3427214082Sdim			x = INSN_BPA | (reloc & 0x7ffff); /* ba,pt %xcc */
3428214082Sdim		      else
3429214082Sdim			x = INSN_BA | (reloc & 0x3fffff); /* ba */
3430214082Sdim		      bfd_put_32 (input_bfd, x, contents + rel->r_offset);
3431214082Sdim		      r = bfd_reloc_ok;
3432214082Sdim		      if (rel->r_offset >= 4
3433214082Sdim			  && (y & (0xffffffff ^ RS1(~0)))
3434214082Sdim			     == (INSN_OR | RD(O7) | RS2(G0)))
3435214082Sdim			{
3436214082Sdim			  bfd_vma z;
3437214082Sdim			  unsigned int reg;
3438214082Sdim
3439214082Sdim			  z = bfd_get_32 (input_bfd,
3440214082Sdim					  contents + rel->r_offset - 4);
3441214082Sdim			  if ((z & (0xffffffff ^ RD(~0)))
3442214082Sdim			      != (INSN_OR | RS1(O7) | RS2(G0)))
3443214082Sdim			    break;
3444214082Sdim
3445214082Sdim			  /* The sequence was
3446214082Sdim			     or %o7, %g0, %rN
3447214082Sdim			     call foo
3448214082Sdim			     or %rN, %g0, %o7
3449214082Sdim
3450214082Sdim			     If call foo was replaced with ba, replace
3451214082Sdim			     or %rN, %g0, %o7 with nop.  */
3452214082Sdim
3453214082Sdim			  reg = (y & RS1(~0)) >> 14;
3454214082Sdim			  if (reg != ((z & RD(~0)) >> 25)
3455214082Sdim			      || reg == G0 || reg == O7)
3456214082Sdim			    break;
3457214082Sdim
3458214082Sdim			  bfd_put_32 (input_bfd, (bfd_vma) INSN_NOP,
3459214082Sdim				      contents + rel->r_offset + 4);
3460214082Sdim			}
3461214082Sdim
3462214082Sdim		    }
3463214082Sdim		}
3464214082Sdim	    }
3465214082Sdim	}
3466214082Sdim
3467214082Sdim      if (r == bfd_reloc_continue)
3468214082Sdim	r = _bfd_final_link_relocate (howto, input_bfd, input_section,
3469214082Sdim				      contents, rel->r_offset,
3470214082Sdim				      relocation, rel->r_addend);
3471214082Sdim
3472214082Sdim      if (r != bfd_reloc_ok)
3473214082Sdim	{
3474214082Sdim	  switch (r)
3475214082Sdim	    {
3476214082Sdim	    default:
3477214082Sdim	    case bfd_reloc_outofrange:
3478214082Sdim	      abort ();
3479214082Sdim	    case bfd_reloc_overflow:
3480214082Sdim	      {
3481214082Sdim		const char *name;
3482214082Sdim
3483214082Sdim		/* The Solaris native linker silently disregards overflows.
3484214082Sdim		   We don't, but this breaks stabs debugging info, whose
3485214082Sdim		   relocations are only 32-bits wide.  Ignore overflows in
3486214082Sdim		   this case and also for discarded entries.  */
3487214082Sdim		if ((r_type == R_SPARC_32 || r_type == R_SPARC_DISP32)
3488214082Sdim		    && (((input_section->flags & SEC_DEBUGGING) != 0
3489214082Sdim			 && strcmp (bfd_section_name (input_bfd,
3490214082Sdim						      input_section),
3491214082Sdim				    ".stab") == 0)
3492214082Sdim			|| _bfd_elf_section_offset (output_bfd, info,
3493214082Sdim						    input_section,
3494214082Sdim						    rel->r_offset)
3495214082Sdim			     == (bfd_vma)-1))
3496214082Sdim		  break;
3497214082Sdim
3498214082Sdim		if (h != NULL)
3499214082Sdim		  {
3500214082Sdim		    /* Assume this is a call protected by other code that
3501214082Sdim		       detect the symbol is undefined.  If this is the case,
3502214082Sdim		       we can safely ignore the overflow.  If not, the
3503214082Sdim		       program is hosed anyway, and a little warning isn't
3504214082Sdim		       going to help.  */
3505214082Sdim		    if (h->root.type == bfd_link_hash_undefweak
3506214082Sdim			&& howto->pc_relative)
3507214082Sdim		      break;
3508214082Sdim
3509214082Sdim	            name = NULL;
3510214082Sdim		  }
3511214082Sdim		else
3512214082Sdim		  {
3513214082Sdim		    name = bfd_elf_string_from_elf_section (input_bfd,
3514214082Sdim							    symtab_hdr->sh_link,
3515214082Sdim							    sym->st_name);
3516214082Sdim		    if (name == NULL)
3517214082Sdim		      return FALSE;
3518214082Sdim		    if (*name == '\0')
3519214082Sdim		      name = bfd_section_name (input_bfd, sec);
3520214082Sdim		  }
3521214082Sdim		if (! ((*info->callbacks->reloc_overflow)
3522214082Sdim		       (info, (h ? &h->root : NULL), name, howto->name,
3523214082Sdim			(bfd_vma) 0, input_bfd, input_section,
3524214082Sdim			rel->r_offset)))
3525214082Sdim		  return FALSE;
3526214082Sdim	      }
3527214082Sdim	      break;
3528214082Sdim	    }
3529214082Sdim	}
3530214082Sdim    }
3531214082Sdim
3532214082Sdim  return TRUE;
3533214082Sdim}
3534214082Sdim
3535214082Sdim/* Build a VxWorks PLT entry.  PLT_INDEX is the index of the PLT entry
3536214082Sdim   and PLT_OFFSET is the byte offset from the start of .plt.  GOT_OFFSET
3537214082Sdim   is the offset of the associated .got.plt entry from
3538214082Sdim   _GLOBAL_OFFSET_TABLE_.  */
3539214082Sdim
3540214082Sdimstatic void
3541214082Sdimsparc_vxworks_build_plt_entry (bfd *output_bfd, struct bfd_link_info *info,
3542214082Sdim			       bfd_vma plt_offset, bfd_vma plt_index,
3543214082Sdim			       bfd_vma got_offset)
3544214082Sdim{
3545214082Sdim  bfd_vma got_base;
3546214082Sdim  const bfd_vma *plt_entry;
3547214082Sdim  struct _bfd_sparc_elf_link_hash_table *htab;
3548214082Sdim  bfd_byte *loc;
3549214082Sdim  Elf_Internal_Rela rela;
3550214082Sdim
3551214082Sdim  htab = _bfd_sparc_elf_hash_table (info);
3552214082Sdim  if (info->shared)
3553214082Sdim    {
3554214082Sdim      plt_entry = sparc_vxworks_shared_plt_entry;
3555214082Sdim      got_base = 0;
3556214082Sdim    }
3557214082Sdim  else
3558214082Sdim    {
3559214082Sdim      plt_entry = sparc_vxworks_exec_plt_entry;
3560214082Sdim      got_base = (htab->elf.hgot->root.u.def.value
3561214082Sdim		  + htab->elf.hgot->root.u.def.section->output_offset
3562214082Sdim		  + htab->elf.hgot->root.u.def.section->output_section->vma);
3563214082Sdim    }
3564214082Sdim
3565214082Sdim  /* Fill in the entry in the procedure linkage table.  */
3566214082Sdim  bfd_put_32 (output_bfd, plt_entry[0] + ((got_base + got_offset) >> 10),
3567214082Sdim	      htab->splt->contents + plt_offset);
3568214082Sdim  bfd_put_32 (output_bfd, plt_entry[1] + ((got_base + got_offset) & 0x3ff),
3569214082Sdim	      htab->splt->contents + plt_offset + 4);
3570214082Sdim  bfd_put_32 (output_bfd, plt_entry[2],
3571214082Sdim	      htab->splt->contents + plt_offset + 8);
3572214082Sdim  bfd_put_32 (output_bfd, plt_entry[3],
3573214082Sdim	      htab->splt->contents + plt_offset + 12);
3574214082Sdim  bfd_put_32 (output_bfd, plt_entry[4],
3575214082Sdim	      htab->splt->contents + plt_offset + 16);
3576214082Sdim  bfd_put_32 (output_bfd, plt_entry[5] + (plt_index >> 10),
3577214082Sdim	      htab->splt->contents + plt_offset + 20);
3578214082Sdim  /* PC-relative displacement for a branch to the start of
3579214082Sdim     the PLT section.  */
3580214082Sdim  bfd_put_32 (output_bfd, plt_entry[6] + (((-plt_offset - 24) >> 2)
3581214082Sdim					  & 0x003fffff),
3582214082Sdim	      htab->splt->contents + plt_offset + 24);
3583214082Sdim  bfd_put_32 (output_bfd, plt_entry[7] + (plt_index & 0x3ff),
3584214082Sdim	      htab->splt->contents + plt_offset + 28);
3585214082Sdim
3586214082Sdim  /* Fill in the .got.plt entry, pointing initially at the
3587214082Sdim     second half of the PLT entry.  */
3588214082Sdim  BFD_ASSERT (htab->sgotplt != NULL);
3589214082Sdim  bfd_put_32 (output_bfd,
3590214082Sdim	      htab->splt->output_section->vma
3591214082Sdim	      + htab->splt->output_offset
3592214082Sdim	      + plt_offset + 20,
3593214082Sdim	      htab->sgotplt->contents + got_offset);
3594214082Sdim
3595214082Sdim  /* Add relocations to .rela.plt.unloaded.  */
3596214082Sdim  if (!info->shared)
3597214082Sdim    {
3598214082Sdim      loc = (htab->srelplt2->contents
3599214082Sdim	     + (2 + 3 * plt_index) * sizeof (Elf32_External_Rela));
3600214082Sdim
3601214082Sdim      /* Relocate the initial sethi.  */
3602214082Sdim      rela.r_offset = (htab->splt->output_section->vma
3603214082Sdim		       + htab->splt->output_offset
3604214082Sdim		       + plt_offset);
3605214082Sdim      rela.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_SPARC_HI22);
3606214082Sdim      rela.r_addend = got_offset;
3607214082Sdim      bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
3608214082Sdim      loc += sizeof (Elf32_External_Rela);
3609214082Sdim
3610214082Sdim      /* Likewise the following or.  */
3611214082Sdim      rela.r_offset += 4;
3612214082Sdim      rela.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_SPARC_LO10);
3613214082Sdim      bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
3614214082Sdim      loc += sizeof (Elf32_External_Rela);
3615214082Sdim
3616214082Sdim      /* Relocate the .got.plt entry.  */
3617214082Sdim      rela.r_offset = (htab->sgotplt->output_section->vma
3618214082Sdim		       + htab->sgotplt->output_offset
3619214082Sdim		       + got_offset);
3620214082Sdim      rela.r_info = ELF32_R_INFO (htab->elf.hplt->indx, R_SPARC_32);
3621214082Sdim      rela.r_addend = plt_offset + 20;
3622214082Sdim      bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
3623214082Sdim    }
3624214082Sdim}
3625214082Sdim
3626214082Sdim/* Finish up dynamic symbol handling.  We set the contents of various
3627214082Sdim   dynamic sections here.  */
3628214082Sdim
3629214082Sdimbfd_boolean
3630214082Sdim_bfd_sparc_elf_finish_dynamic_symbol (bfd *output_bfd,
3631214082Sdim				      struct bfd_link_info *info,
3632214082Sdim				      struct elf_link_hash_entry *h,
3633214082Sdim				      Elf_Internal_Sym *sym)
3634214082Sdim{
3635214082Sdim  bfd *dynobj;
3636214082Sdim  struct _bfd_sparc_elf_link_hash_table *htab;
3637214634Sdim  const struct elf_backend_data *bed;
3638214082Sdim
3639214082Sdim  htab = _bfd_sparc_elf_hash_table (info);
3640214082Sdim  dynobj = htab->elf.dynobj;
3641214634Sdim  bed = get_elf_backend_data (output_bfd);
3642214082Sdim
3643214082Sdim  if (h->plt.offset != (bfd_vma) -1)
3644214082Sdim    {
3645214082Sdim      asection *splt;
3646214082Sdim      asection *srela;
3647214082Sdim      Elf_Internal_Rela rela;
3648214082Sdim      bfd_byte *loc;
3649214082Sdim      bfd_vma r_offset, got_offset;
3650214082Sdim      int rela_index;
3651214082Sdim
3652214082Sdim      /* This symbol has an entry in the PLT.  Set it up.  */
3653214082Sdim
3654214082Sdim      BFD_ASSERT (h->dynindx != -1);
3655214082Sdim
3656214082Sdim      splt = htab->splt;
3657214082Sdim      srela = htab->srelplt;
3658214082Sdim      BFD_ASSERT (splt != NULL && srela != NULL);
3659214082Sdim
3660214082Sdim      /* Fill in the entry in the .rela.plt section.  */
3661214082Sdim      if (htab->is_vxworks)
3662214082Sdim	{
3663214082Sdim	  /* Work out the index of this PLT entry.  */
3664214082Sdim	  rela_index = ((h->plt.offset - htab->plt_header_size)
3665214082Sdim			/ htab->plt_entry_size);
3666214082Sdim
3667214082Sdim	  /* Calculate the offset of the associated .got.plt entry.
3668214082Sdim	     The first three entries are reserved.  */
3669214082Sdim	  got_offset = (rela_index + 3) * 4;
3670214082Sdim
3671214082Sdim	  sparc_vxworks_build_plt_entry (output_bfd, info, h->plt.offset,
3672214082Sdim					 rela_index, got_offset);
3673214082Sdim
3674214082Sdim
3675214082Sdim	  /* On VxWorks, the relocation points to the .got.plt entry,
3676214082Sdim	     not the .plt entry.  */
3677214082Sdim	  rela.r_offset = (htab->sgotplt->output_section->vma
3678214082Sdim			   + htab->sgotplt->output_offset
3679214082Sdim			   + got_offset);
3680214082Sdim	  rela.r_addend = 0;
3681214082Sdim	}
3682214082Sdim      else
3683214082Sdim	{
3684214082Sdim	  /* Fill in the entry in the procedure linkage table.  */
3685214082Sdim	  rela_index = SPARC_ELF_BUILD_PLT_ENTRY (htab, output_bfd, splt,
3686214082Sdim						  h->plt.offset, splt->size,
3687214082Sdim						  &r_offset);
3688214082Sdim
3689214082Sdim	  rela.r_offset = r_offset
3690214082Sdim	    + (splt->output_section->vma + splt->output_offset);
3691214082Sdim	  if (! ABI_64_P (output_bfd)
3692214082Sdim	      || h->plt.offset < (PLT64_LARGE_THRESHOLD * PLT64_ENTRY_SIZE))
3693214082Sdim	    {
3694214082Sdim	      rela.r_addend = 0;
3695214082Sdim	    }
3696214082Sdim	  else
3697214082Sdim	    {
3698214082Sdim	      rela.r_addend = (-(h->plt.offset + 4)
3699214082Sdim			       - splt->output_section->vma
3700214082Sdim			       - splt->output_offset);
3701214082Sdim	    }
3702214082Sdim	}
3703214082Sdim      rela.r_info = SPARC_ELF_R_INFO (htab, NULL, h->dynindx, R_SPARC_JMP_SLOT);
3704214082Sdim
3705214082Sdim      /* Adjust for the first 4 reserved elements in the .plt section
3706214082Sdim	 when setting the offset in the .rela.plt section.
3707214082Sdim	 Sun forgot to read their own ABI and copied elf32-sparc behaviour,
3708214082Sdim	 thus .plt[4] has corresponding .rela.plt[0] and so on.  */
3709214082Sdim
3710214082Sdim      loc = srela->contents;
3711214634Sdim      loc += rela_index * bed->s->sizeof_rela;
3712214634Sdim      bed->s->swap_reloca_out (output_bfd, &rela, loc);
3713214082Sdim
3714214082Sdim      if (!h->def_regular)
3715214082Sdim	{
3716214082Sdim	  /* Mark the symbol as undefined, rather than as defined in
3717214082Sdim	     the .plt section.  Leave the value alone.  */
3718214082Sdim	  sym->st_shndx = SHN_UNDEF;
3719214082Sdim	  /* If the symbol is weak, we do need to clear the value.
3720214082Sdim	     Otherwise, the PLT entry would provide a definition for
3721214082Sdim	     the symbol even if the symbol wasn't defined anywhere,
3722214082Sdim	     and so the symbol would never be NULL.  */
3723214082Sdim	  if (!h->ref_regular_nonweak)
3724214082Sdim	    sym->st_value = 0;
3725214082Sdim	}
3726214082Sdim    }
3727214082Sdim
3728214082Sdim  if (h->got.offset != (bfd_vma) -1
3729214082Sdim      && _bfd_sparc_elf_hash_entry(h)->tls_type != GOT_TLS_GD
3730214082Sdim      && _bfd_sparc_elf_hash_entry(h)->tls_type != GOT_TLS_IE)
3731214082Sdim    {
3732214082Sdim      asection *sgot;
3733214082Sdim      asection *srela;
3734214082Sdim      Elf_Internal_Rela rela;
3735214082Sdim
3736214082Sdim      /* This symbol has an entry in the GOT.  Set it up.  */
3737214082Sdim
3738214082Sdim      sgot = htab->sgot;
3739214082Sdim      srela = htab->srelgot;
3740214082Sdim      BFD_ASSERT (sgot != NULL && srela != NULL);
3741214082Sdim
3742214082Sdim      rela.r_offset = (sgot->output_section->vma
3743214082Sdim		       + sgot->output_offset
3744214082Sdim		       + (h->got.offset &~ (bfd_vma) 1));
3745214082Sdim
3746214082Sdim      /* If this is a -Bsymbolic link, and the symbol is defined
3747214082Sdim	 locally, we just want to emit a RELATIVE reloc.  Likewise if
3748214082Sdim	 the symbol was forced to be local because of a version file.
3749214082Sdim	 The entry in the global offset table will already have been
3750214082Sdim	 initialized in the relocate_section function.  */
3751214082Sdim      if (info->shared
3752214082Sdim	  && (info->symbolic || h->dynindx == -1)
3753214082Sdim	  && h->def_regular)
3754214082Sdim	{
3755214082Sdim	  asection *sec = h->root.u.def.section;
3756214082Sdim	  rela.r_info = SPARC_ELF_R_INFO (htab, NULL, 0, R_SPARC_RELATIVE);
3757214082Sdim	  rela.r_addend = (h->root.u.def.value
3758214082Sdim			   + sec->output_section->vma
3759214082Sdim			   + sec->output_offset);
3760214082Sdim	}
3761214082Sdim      else
3762214082Sdim	{
3763214082Sdim	  rela.r_info = SPARC_ELF_R_INFO (htab, NULL, h->dynindx, R_SPARC_GLOB_DAT);
3764214082Sdim	  rela.r_addend = 0;
3765214082Sdim	}
3766214082Sdim
3767214082Sdim      SPARC_ELF_PUT_WORD (htab, output_bfd, 0,
3768214082Sdim			  sgot->contents + (h->got.offset & ~(bfd_vma) 1));
3769214634Sdim      sparc_elf_append_rela (output_bfd, srela, &rela);
3770214082Sdim    }
3771214082Sdim
3772214082Sdim  if (h->needs_copy)
3773214082Sdim    {
3774214082Sdim      asection *s;
3775214082Sdim      Elf_Internal_Rela rela;
3776214082Sdim
3777214082Sdim      /* This symbols needs a copy reloc.  Set it up.  */
3778214082Sdim      BFD_ASSERT (h->dynindx != -1);
3779214082Sdim
3780214082Sdim      s = bfd_get_section_by_name (h->root.u.def.section->owner,
3781214082Sdim				   ".rela.bss");
3782214082Sdim      BFD_ASSERT (s != NULL);
3783214082Sdim
3784214082Sdim      rela.r_offset = (h->root.u.def.value
3785214082Sdim		       + h->root.u.def.section->output_section->vma
3786214082Sdim		       + h->root.u.def.section->output_offset);
3787214082Sdim      rela.r_info = SPARC_ELF_R_INFO (htab, NULL, h->dynindx, R_SPARC_COPY);
3788214082Sdim      rela.r_addend = 0;
3789214634Sdim      sparc_elf_append_rela (output_bfd, s, &rela);
3790214082Sdim    }
3791214082Sdim
3792214082Sdim  /* Mark some specially defined symbols as absolute.  On VxWorks,
3793214082Sdim     _GLOBAL_OFFSET_TABLE_ is not absolute: it is relative to the
3794214082Sdim     ".got" section.  Likewise _PROCEDURE_LINKAGE_TABLE_ and ".plt".  */
3795214082Sdim  if (strcmp (h->root.root.string, "_DYNAMIC") == 0
3796214082Sdim      || (!htab->is_vxworks
3797214082Sdim	  && (h == htab->elf.hgot || h == htab->elf.hplt)))
3798214082Sdim    sym->st_shndx = SHN_ABS;
3799214082Sdim
3800214082Sdim  return TRUE;
3801214082Sdim}
3802214082Sdim
3803214082Sdim/* Finish up the dynamic sections.  */
3804214082Sdim
3805214082Sdimstatic bfd_boolean
3806214634Sdimsparc_finish_dyn (bfd *output_bfd, struct bfd_link_info *info,
3807214634Sdim		  bfd *dynobj, asection *sdyn,
3808214634Sdim		  asection *splt ATTRIBUTE_UNUSED)
3809214082Sdim{
3810214634Sdim  struct _bfd_sparc_elf_link_hash_table *htab;
3811214634Sdim  const struct elf_backend_data *bed;
3812214634Sdim  bfd_byte *dyncon, *dynconend;
3813214634Sdim  size_t dynsize;
3814214082Sdim  int stt_regidx = -1;
3815214634Sdim  bfd_boolean abi_64_p;
3816214082Sdim
3817214082Sdim  htab = _bfd_sparc_elf_hash_table (info);
3818214634Sdim  bed = get_elf_backend_data (output_bfd);
3819214634Sdim  dynsize = bed->s->sizeof_dyn;
3820214634Sdim  dynconend = sdyn->contents + sdyn->size;
3821214634Sdim  abi_64_p = ABI_64_P (output_bfd);
3822214634Sdim  for (dyncon = sdyn->contents; dyncon < dynconend; dyncon += dynsize)
3823214082Sdim    {
3824214082Sdim      Elf_Internal_Dyn dyn;
3825214082Sdim      const char *name;
3826214082Sdim      bfd_boolean size;
3827214082Sdim
3828214634Sdim      bed->s->swap_dyn_in (dynobj, dyncon, &dyn);
3829214082Sdim
3830214082Sdim      if (htab->is_vxworks && dyn.d_tag == DT_RELASZ)
3831214082Sdim	{
3832214082Sdim	  /* On VxWorks, DT_RELASZ should not include the relocations
3833214082Sdim	     in .rela.plt.  */
3834214082Sdim	  if (htab->srelplt)
3835214082Sdim	    {
3836214082Sdim	      dyn.d_un.d_val -= htab->srelplt->size;
3837214634Sdim	      bed->s->swap_dyn_out (output_bfd, &dyn, dyncon);
3838214082Sdim	    }
3839214082Sdim	}
3840214082Sdim      else if (htab->is_vxworks && dyn.d_tag == DT_PLTGOT)
3841214082Sdim	{
3842214082Sdim	  /* On VxWorks, DT_PLTGOT should point to the start of the GOT,
3843214082Sdim	     not to the start of the PLT.  */
3844214082Sdim	  if (htab->sgotplt)
3845214082Sdim	    {
3846214082Sdim	      dyn.d_un.d_val = (htab->sgotplt->output_section->vma
3847214082Sdim				+ htab->sgotplt->output_offset);
3848214634Sdim	      bed->s->swap_dyn_out (output_bfd, &dyn, dyncon);
3849214082Sdim	    }
3850214082Sdim	}
3851214634Sdim      else if (abi_64_p && dyn.d_tag == DT_SPARC_REGISTER)
3852214634Sdim	{
3853214634Sdim	  if (stt_regidx == -1)
3854214634Sdim	    {
3855214634Sdim	      stt_regidx =
3856214634Sdim		_bfd_elf_link_lookup_local_dynindx (info, output_bfd, -1);
3857214634Sdim	      if (stt_regidx == -1)
3858214634Sdim		return FALSE;
3859214634Sdim	    }
3860214634Sdim	  dyn.d_un.d_val = stt_regidx++;
3861214634Sdim	  bed->s->swap_dyn_out (output_bfd, &dyn, dyncon);
3862214634Sdim	}
3863214082Sdim      else
3864214082Sdim	{
3865214082Sdim	  switch (dyn.d_tag)
3866214082Sdim	    {
3867214082Sdim	    case DT_PLTGOT:   name = ".plt"; size = FALSE; break;
3868214082Sdim	    case DT_PLTRELSZ: name = ".rela.plt"; size = TRUE; break;
3869214082Sdim	    case DT_JMPREL:   name = ".rela.plt"; size = FALSE; break;
3870214634Sdim	    default:	      name = NULL; size = FALSE; break;
3871214082Sdim	    }
3872214082Sdim
3873214082Sdim	  if (name != NULL)
3874214082Sdim	    {
3875214082Sdim	      asection *s;
3876214082Sdim
3877214082Sdim	      s = bfd_get_section_by_name (output_bfd, name);
3878214082Sdim	      if (s == NULL)
3879214082Sdim		dyn.d_un.d_val = 0;
3880214082Sdim	      else
3881214082Sdim		{
3882214082Sdim		  if (! size)
3883214082Sdim		    dyn.d_un.d_ptr = s->vma;
3884214082Sdim		  else
3885214082Sdim		    dyn.d_un.d_val = s->size;
3886214082Sdim		}
3887214634Sdim	      bed->s->swap_dyn_out (output_bfd, &dyn, dyncon);
3888214082Sdim	    }
3889214082Sdim	}
3890214082Sdim    }
3891214082Sdim  return TRUE;
3892214082Sdim}
3893214082Sdim
3894214082Sdim/* Install the first PLT entry in a VxWorks executable and make sure that
3895214082Sdim   .rela.plt.unloaded relocations have the correct symbol indexes.  */
3896214082Sdim
3897214082Sdimstatic void
3898214082Sdimsparc_vxworks_finish_exec_plt (bfd *output_bfd, struct bfd_link_info *info)
3899214082Sdim{
3900214082Sdim  struct _bfd_sparc_elf_link_hash_table *htab;
3901214082Sdim  Elf_Internal_Rela rela;
3902214082Sdim  bfd_vma got_base;
3903214082Sdim  bfd_byte *loc;
3904214082Sdim
3905214082Sdim  htab = _bfd_sparc_elf_hash_table (info);
3906214082Sdim
3907214082Sdim  /* Calculate the absolute value of _GLOBAL_OFFSET_TABLE_.  */
3908214082Sdim  got_base = (htab->elf.hgot->root.u.def.section->output_section->vma
3909214082Sdim	      + htab->elf.hgot->root.u.def.section->output_offset
3910214082Sdim	      + htab->elf.hgot->root.u.def.value);
3911214082Sdim
3912214082Sdim  /* Install the initial PLT entry.  */
3913214082Sdim  bfd_put_32 (output_bfd,
3914214082Sdim	      sparc_vxworks_exec_plt0_entry[0] + ((got_base + 8) >> 10),
3915214082Sdim	      htab->splt->contents);
3916214082Sdim  bfd_put_32 (output_bfd,
3917214082Sdim	      sparc_vxworks_exec_plt0_entry[1] + ((got_base + 8) & 0x3ff),
3918214082Sdim	      htab->splt->contents + 4);
3919214082Sdim  bfd_put_32 (output_bfd,
3920214082Sdim	      sparc_vxworks_exec_plt0_entry[2],
3921214082Sdim	      htab->splt->contents + 8);
3922214082Sdim  bfd_put_32 (output_bfd,
3923214082Sdim	      sparc_vxworks_exec_plt0_entry[3],
3924214082Sdim	      htab->splt->contents + 12);
3925214082Sdim  bfd_put_32 (output_bfd,
3926214082Sdim	      sparc_vxworks_exec_plt0_entry[4],
3927214082Sdim	      htab->splt->contents + 16);
3928214082Sdim
3929214082Sdim  loc = htab->srelplt2->contents;
3930214082Sdim
3931214082Sdim  /* Add an unloaded relocation for the initial entry's "sethi".  */
3932214082Sdim  rela.r_offset = (htab->splt->output_section->vma
3933214082Sdim		   + htab->splt->output_offset);
3934214082Sdim  rela.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_SPARC_HI22);
3935214082Sdim  rela.r_addend = 8;
3936214082Sdim  bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
3937214082Sdim  loc += sizeof (Elf32_External_Rela);
3938214082Sdim
3939214082Sdim  /* Likewise the following "or".  */
3940214082Sdim  rela.r_offset += 4;
3941214082Sdim  rela.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_SPARC_LO10);
3942214082Sdim  bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
3943214082Sdim  loc += sizeof (Elf32_External_Rela);
3944214082Sdim
3945214082Sdim  /* Fix up the remaining .rela.plt.unloaded relocations.  They may have
3946214082Sdim     the wrong symbol index for _G_O_T_ or _P_L_T_ depending on the order
3947214082Sdim     in which symbols were output.  */
3948214082Sdim  while (loc < htab->srelplt2->contents + htab->srelplt2->size)
3949214082Sdim    {
3950214082Sdim      Elf_Internal_Rela rel;
3951214082Sdim
3952214082Sdim      /* The entry's initial "sethi" (against _G_O_T_).  */
3953214082Sdim      bfd_elf32_swap_reloc_in (output_bfd, loc, &rel);
3954214082Sdim      rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_SPARC_HI22);
3955214082Sdim      bfd_elf32_swap_reloc_out (output_bfd, &rel, loc);
3956214082Sdim      loc += sizeof (Elf32_External_Rela);
3957214082Sdim
3958214082Sdim      /* The following "or" (also against _G_O_T_).  */
3959214082Sdim      bfd_elf32_swap_reloc_in (output_bfd, loc, &rel);
3960214082Sdim      rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_SPARC_LO10);
3961214082Sdim      bfd_elf32_swap_reloc_out (output_bfd, &rel, loc);
3962214082Sdim      loc += sizeof (Elf32_External_Rela);
3963214082Sdim
3964214082Sdim      /* The .got.plt entry (against _P_L_T_).  */
3965214082Sdim      bfd_elf32_swap_reloc_in (output_bfd, loc, &rel);
3966214082Sdim      rel.r_info = ELF32_R_INFO (htab->elf.hplt->indx, R_SPARC_32);
3967214082Sdim      bfd_elf32_swap_reloc_out (output_bfd, &rel, loc);
3968214082Sdim      loc += sizeof (Elf32_External_Rela);
3969214082Sdim    }
3970214082Sdim}
3971214082Sdim
3972214082Sdim/* Install the first PLT entry in a VxWorks shared object.  */
3973214082Sdim
3974214082Sdimstatic void
3975214082Sdimsparc_vxworks_finish_shared_plt (bfd *output_bfd, struct bfd_link_info *info)
3976214082Sdim{
3977214082Sdim  struct _bfd_sparc_elf_link_hash_table *htab;
3978214082Sdim  unsigned int i;
3979214082Sdim
3980214082Sdim  htab = _bfd_sparc_elf_hash_table (info);
3981214082Sdim  for (i = 0; i < ARRAY_SIZE (sparc_vxworks_shared_plt0_entry); i++)
3982214082Sdim    bfd_put_32 (output_bfd, sparc_vxworks_shared_plt0_entry[i],
3983214082Sdim		htab->splt->contents + i * 4);
3984214082Sdim}
3985214082Sdim
3986214082Sdimbfd_boolean
3987214082Sdim_bfd_sparc_elf_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
3988214082Sdim{
3989214082Sdim  bfd *dynobj;
3990214082Sdim  asection *sdyn;
3991214082Sdim  struct _bfd_sparc_elf_link_hash_table *htab;
3992214082Sdim
3993214082Sdim  htab = _bfd_sparc_elf_hash_table (info);
3994214082Sdim  dynobj = htab->elf.dynobj;
3995214082Sdim
3996214082Sdim  sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
3997214082Sdim
3998214082Sdim  if (elf_hash_table (info)->dynamic_sections_created)
3999214082Sdim    {
4000214082Sdim      asection *splt;
4001214082Sdim
4002214082Sdim      splt = bfd_get_section_by_name (dynobj, ".plt");
4003214082Sdim      BFD_ASSERT (splt != NULL && sdyn != NULL);
4004214082Sdim
4005214634Sdim      if (!sparc_finish_dyn (output_bfd, info, dynobj, sdyn, splt))
4006214634Sdim	return FALSE;
4007214082Sdim
4008214082Sdim      /* Initialize the contents of the .plt section.  */
4009214082Sdim      if (splt->size > 0)
4010214082Sdim	{
4011214082Sdim	  if (htab->is_vxworks)
4012214082Sdim	    {
4013214082Sdim	      if (info->shared)
4014214082Sdim		sparc_vxworks_finish_shared_plt (output_bfd, info);
4015214082Sdim	      else
4016214082Sdim		sparc_vxworks_finish_exec_plt (output_bfd, info);
4017214082Sdim	    }
4018214082Sdim	  else
4019214082Sdim	    {
4020214082Sdim	      memset (splt->contents, 0, htab->plt_header_size);
4021214082Sdim	      if (!ABI_64_P (output_bfd))
4022214082Sdim		bfd_put_32 (output_bfd, (bfd_vma) SPARC_NOP,
4023214082Sdim			    splt->contents + splt->size - 4);
4024214082Sdim	    }
4025214082Sdim	}
4026214082Sdim
4027214082Sdim      elf_section_data (splt->output_section)->this_hdr.sh_entsize
4028214634Sdim	= (htab->is_vxworks || !ABI_64_P (output_bfd))
4029214634Sdim	  ? 0 : htab->plt_entry_size;
4030214082Sdim    }
4031214082Sdim
4032214082Sdim  /* Set the first entry in the global offset table to the address of
4033214082Sdim     the dynamic section.  */
4034214082Sdim  if (htab->sgot && htab->sgot->size > 0)
4035214082Sdim    {
4036214082Sdim      bfd_vma val = (sdyn ?
4037214082Sdim		     sdyn->output_section->vma + sdyn->output_offset :
4038214082Sdim		     0);
4039214082Sdim
4040214082Sdim      SPARC_ELF_PUT_WORD (htab, output_bfd, val, htab->sgot->contents);
4041214082Sdim    }
4042214082Sdim
4043214082Sdim  if (htab->sgot)
4044214082Sdim    elf_section_data (htab->sgot->output_section)->this_hdr.sh_entsize =
4045214082Sdim      SPARC_ELF_WORD_BYTES (htab);
4046214082Sdim
4047214082Sdim  return TRUE;
4048214082Sdim}
4049214082Sdim
4050214082Sdim
4051214082Sdim/* Set the right machine number for a SPARC ELF file.  */
4052214082Sdim
4053214082Sdimbfd_boolean
4054214082Sdim_bfd_sparc_elf_object_p (bfd *abfd)
4055214082Sdim{
4056214082Sdim  if (ABI_64_P (abfd))
4057214082Sdim    {
4058214082Sdim      unsigned long mach = bfd_mach_sparc_v9;
4059214082Sdim
4060214082Sdim      if (elf_elfheader (abfd)->e_flags & EF_SPARC_SUN_US3)
4061214082Sdim	mach = bfd_mach_sparc_v9b;
4062214082Sdim      else if (elf_elfheader (abfd)->e_flags & EF_SPARC_SUN_US1)
4063214082Sdim	mach = bfd_mach_sparc_v9a;
4064214082Sdim      return bfd_default_set_arch_mach (abfd, bfd_arch_sparc, mach);
4065214082Sdim    }
4066214082Sdim  else
4067214082Sdim    {
4068214082Sdim      if (elf_elfheader (abfd)->e_machine == EM_SPARC32PLUS)
4069214082Sdim	{
4070214082Sdim	  if (elf_elfheader (abfd)->e_flags & EF_SPARC_SUN_US3)
4071214082Sdim	    return bfd_default_set_arch_mach (abfd, bfd_arch_sparc,
4072214082Sdim					      bfd_mach_sparc_v8plusb);
4073214082Sdim	  else if (elf_elfheader (abfd)->e_flags & EF_SPARC_SUN_US1)
4074214082Sdim	    return bfd_default_set_arch_mach (abfd, bfd_arch_sparc,
4075214082Sdim					      bfd_mach_sparc_v8plusa);
4076214082Sdim	  else if (elf_elfheader (abfd)->e_flags & EF_SPARC_32PLUS)
4077214082Sdim	    return bfd_default_set_arch_mach (abfd, bfd_arch_sparc,
4078214082Sdim					      bfd_mach_sparc_v8plus);
4079214082Sdim	  else
4080214082Sdim	    return FALSE;
4081214082Sdim	}
4082214082Sdim      else if (elf_elfheader (abfd)->e_flags & EF_SPARC_LEDATA)
4083214082Sdim	return bfd_default_set_arch_mach (abfd, bfd_arch_sparc,
4084214082Sdim					  bfd_mach_sparc_sparclite_le);
4085214082Sdim      else
4086214082Sdim	return bfd_default_set_arch_mach (abfd, bfd_arch_sparc, bfd_mach_sparc);
4087214082Sdim    }
4088214082Sdim}
4089214082Sdim
4090214082Sdim/* Return address for Ith PLT stub in section PLT, for relocation REL
4091214082Sdim   or (bfd_vma) -1 if it should not be included.  */
4092214082Sdim
4093214082Sdimbfd_vma
4094214082Sdim_bfd_sparc_elf_plt_sym_val (bfd_vma i, const asection *plt, const arelent *rel)
4095214082Sdim{
4096214082Sdim  if (ABI_64_P (plt->owner))
4097214082Sdim    {
4098214082Sdim      bfd_vma j;
4099214082Sdim
4100214082Sdim      i += PLT64_HEADER_SIZE / PLT64_ENTRY_SIZE;
4101214082Sdim      if (i < PLT64_LARGE_THRESHOLD)
4102214082Sdim	return plt->vma + i * PLT64_ENTRY_SIZE;
4103214082Sdim
4104214082Sdim      j = (i - PLT64_LARGE_THRESHOLD) % 160;
4105214082Sdim      i -= j;
4106214082Sdim      return plt->vma + i * PLT64_ENTRY_SIZE + j * 4 * 6;
4107214082Sdim    }
4108214082Sdim  else
4109214082Sdim    return rel->address;
4110214082Sdim}
4111