199461Sobrien/* IBM S/390-specific support for 32-bit ELF
2218822Sdim   Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
3218822Sdim   Free Software Foundation, Inc.
499461Sobrien   Contributed by Carl B. Pedersen and Martin Schwidefsky.
599461Sobrien
699461Sobrien   This file is part of BFD, the Binary File Descriptor library.
799461Sobrien
899461Sobrien   This program is free software; you can redistribute it and/or modify
999461Sobrien   it under the terms of the GNU General Public License as published by
1099461Sobrien   the Free Software Foundation; either version 2 of the License, or
1199461Sobrien   (at your option) any later version.
1299461Sobrien
1399461Sobrien   This program is distributed in the hope that it will be useful,
1499461Sobrien   but WITHOUT ANY WARRANTY; without even the implied warranty of
1599461Sobrien   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1699461Sobrien   GNU General Public License for more details.
1799461Sobrien
1899461Sobrien   You should have received a copy of the GNU General Public License
1999461Sobrien   along with this program; if not, write to the Free Software
20218822Sdim   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
21218822Sdim   02110-1301, USA.  */
2299461Sobrien
23218822Sdim#include "sysdep.h"
2499461Sobrien#include "bfd.h"
2599461Sobrien#include "bfdlink.h"
2699461Sobrien#include "libbfd.h"
2799461Sobrien#include "elf-bfd.h"
2899461Sobrien
2999461Sobrienstatic reloc_howto_type *elf_s390_reloc_type_lookup
3099461Sobrien  PARAMS ((bfd *, bfd_reloc_code_real_type));
3199461Sobrienstatic void elf_s390_info_to_howto
3299461Sobrien  PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
33130561Sobrienstatic bfd_boolean elf_s390_is_local_label_name
3499461Sobrien  PARAMS ((bfd *, const char *));
3599461Sobrienstatic struct bfd_hash_entry *link_hash_newfunc
3699461Sobrien  PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
3799461Sobrienstatic struct bfd_link_hash_table *elf_s390_link_hash_table_create
3899461Sobrien  PARAMS ((bfd *));
39130561Sobrienstatic bfd_boolean create_got_section
4099461Sobrien  PARAMS((bfd *, struct bfd_link_info *));
41130561Sobrienstatic bfd_boolean elf_s390_create_dynamic_sections
4299461Sobrien  PARAMS((bfd *, struct bfd_link_info *));
4399461Sobrienstatic void elf_s390_copy_indirect_symbol
44218822Sdim  PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *,
45107492Sobrien	   struct elf_link_hash_entry *));
46130561Sobrienstatic bfd_boolean elf_s390_check_relocs
4799461Sobrien  PARAMS ((bfd *, struct bfd_link_info *, asection *,
4899461Sobrien	   const Elf_Internal_Rela *));
49130561Sobrienstruct elf_s390_link_hash_entry;
50130561Sobrienstatic void elf_s390_adjust_gotplt
51130561Sobrien  PARAMS ((struct elf_s390_link_hash_entry *));
52130561Sobrienstatic bfd_boolean elf_s390_adjust_dynamic_symbol
5399461Sobrien  PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
54130561Sobrienstatic bfd_boolean allocate_dynrelocs
5599461Sobrien  PARAMS ((struct elf_link_hash_entry *, PTR));
56130561Sobrienstatic bfd_boolean readonly_dynrelocs
5799461Sobrien  PARAMS ((struct elf_link_hash_entry *, PTR));
58130561Sobrienstatic bfd_boolean elf_s390_size_dynamic_sections
5999461Sobrien  PARAMS ((bfd *, struct bfd_link_info *));
60130561Sobrienstatic bfd_boolean elf_s390_relocate_section
6199461Sobrien  PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
6299461Sobrien	   Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
63130561Sobrienstatic bfd_boolean elf_s390_finish_dynamic_symbol
6499461Sobrien  PARAMS ((bfd *, struct bfd_link_info *, struct elf_link_hash_entry *,
6599461Sobrien	   Elf_Internal_Sym *));
6699461Sobrienstatic enum elf_reloc_type_class elf_s390_reloc_type_class
6799461Sobrien  PARAMS ((const Elf_Internal_Rela *));
68130561Sobrienstatic bfd_boolean elf_s390_finish_dynamic_sections
6999461Sobrien  PARAMS ((bfd *, struct bfd_link_info *));
70130561Sobrienstatic bfd_boolean elf_s390_object_p
71130561Sobrien  PARAMS ((bfd *));
72130561Sobrienstatic bfd_boolean elf_s390_grok_prstatus
73130561Sobrien  PARAMS ((bfd *, Elf_Internal_Note *));
74130561Sobrienstatic int elf_s390_tls_transition
75130561Sobrien  PARAMS ((struct bfd_link_info *, int, int));
76130561Sobrienstatic bfd_reloc_status_type s390_tls_reloc
77130561Sobrien  PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
78130561Sobrienstatic bfd_vma dtpoff_base
79130561Sobrien  PARAMS ((struct bfd_link_info *));
80130561Sobrienstatic bfd_vma tpoff
81130561Sobrien  PARAMS ((struct bfd_link_info *, bfd_vma));
82130561Sobrienstatic void invalid_tls_insn
83130561Sobrien  PARAMS ((bfd *, asection *, Elf_Internal_Rela *));
84130561Sobrienstatic bfd_reloc_status_type s390_elf_ldisp_reloc
85130561Sobrien  PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
8699461Sobrien
8799461Sobrien#include "elf/s390.h"
8899461Sobrien
8999461Sobrien/* The relocation "howto" table.  */
9099461Sobrien
9199461Sobrienstatic reloc_howto_type elf_howto_table[] =
9299461Sobrien{
9399461Sobrien  HOWTO (R_390_NONE,		/* type */
9499461Sobrien	 0,			/* rightshift */
9599461Sobrien	 0,			/* size (0 = byte, 1 = short, 2 = long) */
9699461Sobrien	 0,			/* bitsize */
97130561Sobrien	 FALSE,			/* pc_relative */
9899461Sobrien	 0,			/* bitpos */
9999461Sobrien	 complain_overflow_dont, /* complain_on_overflow */
10099461Sobrien	 bfd_elf_generic_reloc, /* special_function */
10199461Sobrien	 "R_390_NONE",		/* name */
102130561Sobrien	 FALSE,			/* partial_inplace */
10399461Sobrien	 0,			/* src_mask */
10499461Sobrien	 0,			/* dst_mask */
105130561Sobrien	 FALSE),		/* pcrel_offset */
10699461Sobrien
107130561Sobrien  HOWTO(R_390_8,         0, 0,  8, FALSE, 0, complain_overflow_bitfield,
108130561Sobrien	bfd_elf_generic_reloc, "R_390_8",        FALSE, 0,0x000000ff, FALSE),
109130561Sobrien  HOWTO(R_390_12,        0, 1, 12, FALSE, 0, complain_overflow_dont,
110130561Sobrien	bfd_elf_generic_reloc, "R_390_12",       FALSE, 0,0x00000fff, FALSE),
111130561Sobrien  HOWTO(R_390_16,        0, 1, 16, FALSE, 0, complain_overflow_bitfield,
112130561Sobrien	bfd_elf_generic_reloc, "R_390_16",       FALSE, 0,0x0000ffff, FALSE),
113130561Sobrien  HOWTO(R_390_32,        0, 2, 32, FALSE, 0, complain_overflow_bitfield,
114130561Sobrien	bfd_elf_generic_reloc, "R_390_32",       FALSE, 0,0xffffffff, FALSE),
115130561Sobrien  HOWTO(R_390_PC32,	 0, 2, 32,  TRUE, 0, complain_overflow_bitfield,
116130561Sobrien	bfd_elf_generic_reloc, "R_390_PC32",     FALSE, 0,0xffffffff, TRUE),
117130561Sobrien  HOWTO(R_390_GOT12,	 0, 1, 12, FALSE, 0, complain_overflow_bitfield,
118130561Sobrien	bfd_elf_generic_reloc, "R_390_GOT12",    FALSE, 0,0x00000fff, FALSE),
119130561Sobrien  HOWTO(R_390_GOT32,	 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
120130561Sobrien	bfd_elf_generic_reloc, "R_390_GOT32",    FALSE, 0,0xffffffff, FALSE),
121130561Sobrien  HOWTO(R_390_PLT32,	 0, 2, 32,  TRUE, 0, complain_overflow_bitfield,
122130561Sobrien	bfd_elf_generic_reloc, "R_390_PLT32",    FALSE, 0,0xffffffff, TRUE),
123130561Sobrien  HOWTO(R_390_COPY,      0, 2, 32, FALSE, 0, complain_overflow_bitfield,
124130561Sobrien	bfd_elf_generic_reloc, "R_390_COPY",     FALSE, 0,0xffffffff, FALSE),
125130561Sobrien  HOWTO(R_390_GLOB_DAT,  0, 2, 32, FALSE, 0, complain_overflow_bitfield,
126130561Sobrien	bfd_elf_generic_reloc, "R_390_GLOB_DAT", FALSE, 0,0xffffffff, FALSE),
127130561Sobrien  HOWTO(R_390_JMP_SLOT,  0, 2, 32, FALSE, 0, complain_overflow_bitfield,
128130561Sobrien	bfd_elf_generic_reloc, "R_390_JMP_SLOT", FALSE, 0,0xffffffff, FALSE),
129130561Sobrien  HOWTO(R_390_RELATIVE,  0, 2, 32,  TRUE, 0, complain_overflow_bitfield,
130130561Sobrien	bfd_elf_generic_reloc, "R_390_RELATIVE", FALSE, 0,0xffffffff, FALSE),
131130561Sobrien  HOWTO(R_390_GOTOFF32,  0, 2, 32, FALSE, 0, complain_overflow_bitfield,
132130561Sobrien	bfd_elf_generic_reloc, "R_390_GOTOFF32", FALSE, 0,0xffffffff, FALSE),
133130561Sobrien  HOWTO(R_390_GOTPC,     0, 2, 32,  TRUE, 0, complain_overflow_bitfield,
134130561Sobrien	bfd_elf_generic_reloc, "R_390_GOTPC",    FALSE, 0,0xffffffff, TRUE),
135130561Sobrien  HOWTO(R_390_GOT16,     0, 1, 16, FALSE, 0, complain_overflow_bitfield,
136130561Sobrien	bfd_elf_generic_reloc, "R_390_GOT16",    FALSE, 0,0x0000ffff, FALSE),
137130561Sobrien  HOWTO(R_390_PC16,      0, 1, 16,  TRUE, 0, complain_overflow_bitfield,
138130561Sobrien	bfd_elf_generic_reloc, "R_390_PC16",     FALSE, 0,0x0000ffff, TRUE),
139130561Sobrien  HOWTO(R_390_PC16DBL,   1, 1, 16,  TRUE, 0, complain_overflow_bitfield,
140130561Sobrien	bfd_elf_generic_reloc, "R_390_PC16DBL",  FALSE, 0,0x0000ffff, TRUE),
141130561Sobrien  HOWTO(R_390_PLT16DBL,  1, 1, 16,  TRUE, 0, complain_overflow_bitfield,
142130561Sobrien	bfd_elf_generic_reloc, "R_390_PLT16DBL", FALSE, 0,0x0000ffff, TRUE),
143130561Sobrien  HOWTO(R_390_PC32DBL,	 1, 2, 32,  TRUE, 0, complain_overflow_bitfield,
144130561Sobrien	bfd_elf_generic_reloc, "R_390_PC32DBL",  FALSE, 0,0xffffffff, TRUE),
145130561Sobrien  HOWTO(R_390_PLT32DBL,	 1, 2, 32,  TRUE, 0, complain_overflow_bitfield,
146130561Sobrien	bfd_elf_generic_reloc, "R_390_PLT32DBL", FALSE, 0,0xffffffff, TRUE),
147130561Sobrien  HOWTO(R_390_GOTPCDBL,  1, 2, 32,  TRUE, 0, complain_overflow_bitfield,
148130561Sobrien	bfd_elf_generic_reloc, "R_390_GOTPCDBL", FALSE, 0,0xffffffff, TRUE),
149130561Sobrien  EMPTY_HOWTO (R_390_64),	/* Empty entry for R_390_64.  */
150130561Sobrien  EMPTY_HOWTO (R_390_PC64),	/* Empty entry for R_390_PC64.  */
151130561Sobrien  EMPTY_HOWTO (R_390_GOT64),	/* Empty entry for R_390_GOT64.  */
152130561Sobrien  EMPTY_HOWTO (R_390_PLT64),	/* Empty entry for R_390_PLT64.  */
153130561Sobrien  HOWTO(R_390_GOTENT,	 1, 2, 32,  TRUE, 0, complain_overflow_bitfield,
154130561Sobrien	bfd_elf_generic_reloc, "R_390_GOTENT",   FALSE, 0,0xffffffff, TRUE),
155130561Sobrien  HOWTO(R_390_GOTOFF16,  0, 1, 16, FALSE, 0, complain_overflow_bitfield,
156130561Sobrien	bfd_elf_generic_reloc, "R_390_GOTOFF16", FALSE, 0,0x0000ffff, FALSE),
157130561Sobrien  EMPTY_HOWTO (R_390_GOTOFF64),	/* Empty entry for R_390_GOTOFF64.  */
158130561Sobrien  HOWTO(R_390_GOTPLT12,  0, 1, 12, FALSE, 0, complain_overflow_dont,
159130561Sobrien	bfd_elf_generic_reloc, "R_390_GOTPLT12", FALSE, 0,0x00000fff, FALSE),
160130561Sobrien  HOWTO(R_390_GOTPLT16,  0, 1, 16, FALSE, 0, complain_overflow_bitfield,
161130561Sobrien	bfd_elf_generic_reloc, "R_390_GOTPLT16", FALSE, 0,0x0000ffff, FALSE),
162130561Sobrien  HOWTO(R_390_GOTPLT32,  0, 2, 32, FALSE, 0, complain_overflow_bitfield,
163130561Sobrien	bfd_elf_generic_reloc, "R_390_GOTPLT32", FALSE, 0,0xffffffff, FALSE),
164130561Sobrien  EMPTY_HOWTO (R_390_GOTPLT64),	/* Empty entry for R_390_GOTPLT64.  */
165130561Sobrien  HOWTO(R_390_GOTPLTENT, 1, 2, 32,  TRUE, 0, complain_overflow_bitfield,
166130561Sobrien	bfd_elf_generic_reloc, "R_390_GOTPLTENT",FALSE, 0,0xffffffff, TRUE),
167130561Sobrien  HOWTO(R_390_PLTOFF16,  0, 1, 16, FALSE, 0, complain_overflow_bitfield,
168130561Sobrien	bfd_elf_generic_reloc, "R_390_PLTOFF16", FALSE, 0,0x0000ffff, FALSE),
169130561Sobrien  HOWTO(R_390_PLTOFF32,  0, 2, 32, FALSE, 0, complain_overflow_bitfield,
170130561Sobrien	bfd_elf_generic_reloc, "R_390_PLTOFF32", FALSE, 0,0xffffffff, FALSE),
171130561Sobrien  EMPTY_HOWTO (R_390_PLTOFF64),	/* Empty entry for R_390_PLTOFF64.  */
172130561Sobrien  HOWTO(R_390_TLS_LOAD, 0, 0, 0, FALSE, 0, complain_overflow_dont,
173130561Sobrien	s390_tls_reloc, "R_390_TLS_LOAD", FALSE, 0, 0, FALSE),
174130561Sobrien  HOWTO(R_390_TLS_GDCALL, 0, 0, 0, FALSE, 0, complain_overflow_dont,
175130561Sobrien	s390_tls_reloc, "R_390_TLS_GDCALL", FALSE, 0, 0, FALSE),
176130561Sobrien  HOWTO(R_390_TLS_LDCALL, 0, 0, 0, FALSE, 0, complain_overflow_dont,
177130561Sobrien	s390_tls_reloc, "R_390_TLS_LDCALL", FALSE, 0, 0, FALSE),
178130561Sobrien  HOWTO(R_390_TLS_GD32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
179130561Sobrien	bfd_elf_generic_reloc, "R_390_TLS_GD32", FALSE, 0, 0xffffffff, FALSE),
180130561Sobrien  EMPTY_HOWTO (R_390_TLS_GD64),	/* Empty entry for R_390_TLS_GD64.  */
181130561Sobrien  HOWTO(R_390_TLS_GOTIE12, 0, 1, 12, FALSE, 0, complain_overflow_dont,
182130561Sobrien	bfd_elf_generic_reloc, "R_390_TLS_GOTIE12", FALSE, 0, 0x00000fff, FALSE),
183130561Sobrien  HOWTO(R_390_TLS_GOTIE32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
184130561Sobrien	bfd_elf_generic_reloc, "R_390_TLS_GOTIE32", FALSE, 0, 0xffffffff, FALSE),
185130561Sobrien  EMPTY_HOWTO (R_390_TLS_GOTIE64),	/* Empty entry for R_390_TLS_GOTIE64.  */
186130561Sobrien  HOWTO(R_390_TLS_LDM32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
187130561Sobrien	bfd_elf_generic_reloc, "R_390_TLS_LDM32", FALSE, 0, 0xffffffff, FALSE),
188130561Sobrien  EMPTY_HOWTO (R_390_TLS_LDM64),	/* Empty entry for R_390_TLS_LDM64.  */
189130561Sobrien  HOWTO(R_390_TLS_IE32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
190130561Sobrien	bfd_elf_generic_reloc, "R_390_TLS_IE32", FALSE, 0, 0xffffffff, FALSE),
191130561Sobrien  EMPTY_HOWTO (R_390_TLS_IE64),	/* Empty entry for R_390_TLS_IE64.  */
192130561Sobrien  HOWTO(R_390_TLS_IEENT, 1, 2, 32, TRUE, 0, complain_overflow_bitfield,
193130561Sobrien	bfd_elf_generic_reloc, "R_390_TLS_IEENT", FALSE, 0, 0xffffffff, TRUE),
194130561Sobrien  HOWTO(R_390_TLS_LE32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
195130561Sobrien	bfd_elf_generic_reloc, "R_390_TLS_LE32", FALSE, 0, 0xffffffff, FALSE),
196130561Sobrien  EMPTY_HOWTO (R_390_TLS_LE64),	/* Empty entry for R_390_TLS_LE64.  */
197130561Sobrien  HOWTO(R_390_TLS_LDO32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
198130561Sobrien	bfd_elf_generic_reloc, "R_390_TLS_LDO32", FALSE, 0, 0xffffffff, FALSE),
199130561Sobrien  EMPTY_HOWTO (R_390_TLS_LDO64),	/* Empty entry for R_390_TLS_LDO64.  */
200130561Sobrien  HOWTO(R_390_TLS_DTPMOD, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
201130561Sobrien	bfd_elf_generic_reloc, "R_390_TLS_DTPMOD", FALSE, 0, 0xffffffff, FALSE),
202130561Sobrien  HOWTO(R_390_TLS_DTPOFF, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
203130561Sobrien	bfd_elf_generic_reloc, "R_390_TLS_DTPOFF", FALSE, 0, 0xffffffff, FALSE),
204130561Sobrien  HOWTO(R_390_TLS_TPOFF, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
205130561Sobrien	bfd_elf_generic_reloc, "R_390_TLS_TPOFF", FALSE, 0, 0xffffffff, FALSE),
206130561Sobrien  HOWTO(R_390_20,        0, 2, 20, FALSE, 8, complain_overflow_dont,
207130561Sobrien	s390_elf_ldisp_reloc, "R_390_20",      FALSE, 0,0x0fffff00, FALSE),
208130561Sobrien  HOWTO(R_390_GOT20,	 0, 2, 20, FALSE, 8, complain_overflow_dont,
209130561Sobrien	s390_elf_ldisp_reloc, "R_390_GOT20",   FALSE, 0,0x0fffff00, FALSE),
210130561Sobrien  HOWTO(R_390_GOTPLT20,  0, 2, 20, FALSE, 8, complain_overflow_dont,
211130561Sobrien	s390_elf_ldisp_reloc, "R_390_GOTPLT20", FALSE, 0,0x0fffff00, FALSE),
212130561Sobrien  HOWTO(R_390_TLS_GOTIE20, 0, 2, 20, FALSE, 8, complain_overflow_dont,
213130561Sobrien	s390_elf_ldisp_reloc, "R_390_TLS_GOTIE20", FALSE, 0,0x0fffff00, FALSE),
21499461Sobrien};
21599461Sobrien
21699461Sobrien/* GNU extension to record C++ vtable hierarchy.  */
21799461Sobrienstatic reloc_howto_type elf32_s390_vtinherit_howto =
218130561Sobrien  HOWTO (R_390_GNU_VTINHERIT, 0,2,0,FALSE,0,complain_overflow_dont, NULL, "R_390_GNU_VTINHERIT", FALSE,0, 0, FALSE);
21999461Sobrienstatic reloc_howto_type elf32_s390_vtentry_howto =
220130561Sobrien  HOWTO (R_390_GNU_VTENTRY, 0,2,0,FALSE,0,complain_overflow_dont, _bfd_elf_rel_vtable_reloc_fn,"R_390_GNU_VTENTRY", FALSE,0,0, FALSE);
22199461Sobrien
22299461Sobrienstatic reloc_howto_type *
22399461Sobrienelf_s390_reloc_type_lookup (abfd, code)
22499461Sobrien     bfd *abfd ATTRIBUTE_UNUSED;
22599461Sobrien     bfd_reloc_code_real_type code;
22699461Sobrien{
22799461Sobrien  switch (code)
22899461Sobrien    {
22999461Sobrien    case BFD_RELOC_NONE:
23099461Sobrien      return &elf_howto_table[(int) R_390_NONE];
23199461Sobrien    case BFD_RELOC_8:
23299461Sobrien      return &elf_howto_table[(int) R_390_8];
23399461Sobrien    case BFD_RELOC_390_12:
23499461Sobrien      return &elf_howto_table[(int) R_390_12];
23599461Sobrien    case BFD_RELOC_16:
23699461Sobrien      return &elf_howto_table[(int) R_390_16];
23799461Sobrien    case BFD_RELOC_32:
23899461Sobrien      return &elf_howto_table[(int) R_390_32];
23999461Sobrien    case BFD_RELOC_CTOR:
24099461Sobrien      return &elf_howto_table[(int) R_390_32];
24199461Sobrien    case BFD_RELOC_32_PCREL:
24299461Sobrien      return &elf_howto_table[(int) R_390_PC32];
24399461Sobrien    case BFD_RELOC_390_GOT12:
24499461Sobrien      return &elf_howto_table[(int) R_390_GOT12];
24599461Sobrien    case BFD_RELOC_32_GOT_PCREL:
24699461Sobrien      return &elf_howto_table[(int) R_390_GOT32];
24799461Sobrien    case BFD_RELOC_390_PLT32:
24899461Sobrien      return &elf_howto_table[(int) R_390_PLT32];
24999461Sobrien    case BFD_RELOC_390_COPY:
25099461Sobrien      return &elf_howto_table[(int) R_390_COPY];
25199461Sobrien    case BFD_RELOC_390_GLOB_DAT:
25299461Sobrien      return &elf_howto_table[(int) R_390_GLOB_DAT];
25399461Sobrien    case BFD_RELOC_390_JMP_SLOT:
25499461Sobrien      return &elf_howto_table[(int) R_390_JMP_SLOT];
25599461Sobrien    case BFD_RELOC_390_RELATIVE:
25699461Sobrien      return &elf_howto_table[(int) R_390_RELATIVE];
25799461Sobrien    case BFD_RELOC_32_GOTOFF:
258130561Sobrien      return &elf_howto_table[(int) R_390_GOTOFF32];
25999461Sobrien    case BFD_RELOC_390_GOTPC:
26099461Sobrien      return &elf_howto_table[(int) R_390_GOTPC];
26199461Sobrien    case BFD_RELOC_390_GOT16:
26299461Sobrien      return &elf_howto_table[(int) R_390_GOT16];
26399461Sobrien    case BFD_RELOC_16_PCREL:
26499461Sobrien      return &elf_howto_table[(int) R_390_PC16];
26599461Sobrien    case BFD_RELOC_390_PC16DBL:
26699461Sobrien      return &elf_howto_table[(int) R_390_PC16DBL];
26799461Sobrien    case BFD_RELOC_390_PLT16DBL:
26899461Sobrien      return &elf_howto_table[(int) R_390_PLT16DBL];
26999461Sobrien    case BFD_RELOC_390_PC32DBL:
27099461Sobrien      return &elf_howto_table[(int) R_390_PC32DBL];
27199461Sobrien    case BFD_RELOC_390_PLT32DBL:
27299461Sobrien      return &elf_howto_table[(int) R_390_PLT32DBL];
27399461Sobrien    case BFD_RELOC_390_GOTPCDBL:
27499461Sobrien      return &elf_howto_table[(int) R_390_GOTPCDBL];
27599461Sobrien    case BFD_RELOC_390_GOTENT:
27699461Sobrien      return &elf_howto_table[(int) R_390_GOTENT];
277130561Sobrien    case BFD_RELOC_16_GOTOFF:
278130561Sobrien      return &elf_howto_table[(int) R_390_GOTOFF16];
279130561Sobrien    case BFD_RELOC_390_GOTPLT12:
280130561Sobrien      return &elf_howto_table[(int) R_390_GOTPLT12];
281130561Sobrien    case BFD_RELOC_390_GOTPLT16:
282130561Sobrien      return &elf_howto_table[(int) R_390_GOTPLT16];
283130561Sobrien    case BFD_RELOC_390_GOTPLT32:
284130561Sobrien      return &elf_howto_table[(int) R_390_GOTPLT32];
285130561Sobrien    case BFD_RELOC_390_GOTPLTENT:
286130561Sobrien      return &elf_howto_table[(int) R_390_GOTPLTENT];
287130561Sobrien    case BFD_RELOC_390_PLTOFF16:
288130561Sobrien      return &elf_howto_table[(int) R_390_PLTOFF16];
289130561Sobrien    case BFD_RELOC_390_PLTOFF32:
290130561Sobrien      return &elf_howto_table[(int) R_390_PLTOFF32];
291130561Sobrien    case BFD_RELOC_390_TLS_LOAD:
292130561Sobrien      return &elf_howto_table[(int) R_390_TLS_LOAD];
293130561Sobrien    case BFD_RELOC_390_TLS_GDCALL:
294130561Sobrien      return &elf_howto_table[(int) R_390_TLS_GDCALL];
295130561Sobrien    case BFD_RELOC_390_TLS_LDCALL:
296130561Sobrien      return &elf_howto_table[(int) R_390_TLS_LDCALL];
297130561Sobrien    case BFD_RELOC_390_TLS_GD32:
298130561Sobrien      return &elf_howto_table[(int) R_390_TLS_GD32];
299130561Sobrien    case BFD_RELOC_390_TLS_GOTIE12:
300130561Sobrien      return &elf_howto_table[(int) R_390_TLS_GOTIE12];
301130561Sobrien    case BFD_RELOC_390_TLS_GOTIE32:
302130561Sobrien      return &elf_howto_table[(int) R_390_TLS_GOTIE32];
303130561Sobrien    case BFD_RELOC_390_TLS_LDM32:
304130561Sobrien      return &elf_howto_table[(int) R_390_TLS_LDM32];
305130561Sobrien    case BFD_RELOC_390_TLS_IE32:
306130561Sobrien      return &elf_howto_table[(int) R_390_TLS_IE32];
307130561Sobrien    case BFD_RELOC_390_TLS_IEENT:
308130561Sobrien      return &elf_howto_table[(int) R_390_TLS_IEENT];
309130561Sobrien    case BFD_RELOC_390_TLS_LE32:
310130561Sobrien      return &elf_howto_table[(int) R_390_TLS_LE32];
311130561Sobrien    case BFD_RELOC_390_TLS_LDO32:
312130561Sobrien      return &elf_howto_table[(int) R_390_TLS_LDO32];
313130561Sobrien    case BFD_RELOC_390_TLS_DTPMOD:
314130561Sobrien      return &elf_howto_table[(int) R_390_TLS_DTPMOD];
315130561Sobrien    case BFD_RELOC_390_TLS_DTPOFF:
316130561Sobrien      return &elf_howto_table[(int) R_390_TLS_DTPOFF];
317130561Sobrien    case BFD_RELOC_390_TLS_TPOFF:
318130561Sobrien      return &elf_howto_table[(int) R_390_TLS_TPOFF];
319130561Sobrien    case BFD_RELOC_390_20:
320130561Sobrien      return &elf_howto_table[(int) R_390_20];
321130561Sobrien    case BFD_RELOC_390_GOT20:
322130561Sobrien      return &elf_howto_table[(int) R_390_GOT20];
323130561Sobrien    case BFD_RELOC_390_GOTPLT20:
324130561Sobrien      return &elf_howto_table[(int) R_390_GOTPLT20];
325130561Sobrien    case BFD_RELOC_390_TLS_GOTIE20:
326130561Sobrien      return &elf_howto_table[(int) R_390_TLS_GOTIE20];
32799461Sobrien    case BFD_RELOC_VTABLE_INHERIT:
32899461Sobrien      return &elf32_s390_vtinherit_howto;
32999461Sobrien    case BFD_RELOC_VTABLE_ENTRY:
33099461Sobrien      return &elf32_s390_vtentry_howto;
33199461Sobrien    default:
33299461Sobrien      break;
33399461Sobrien    }
33499461Sobrien  return 0;
33599461Sobrien}
33699461Sobrien
337218822Sdimstatic reloc_howto_type *
338218822Sdimelf_s390_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
339218822Sdim			    const char *r_name)
340218822Sdim{
341218822Sdim  unsigned int i;
342218822Sdim
343218822Sdim  for (i = 0; i < sizeof (elf_howto_table) / sizeof (elf_howto_table[0]); i++)
344218822Sdim    if (elf_howto_table[i].name != NULL
345218822Sdim	&& strcasecmp (elf_howto_table[i].name, r_name) == 0)
346218822Sdim      return &elf_howto_table[i];
347218822Sdim
348218822Sdim  if (strcasecmp (elf32_s390_vtinherit_howto.name, r_name) == 0)
349218822Sdim    return &elf32_s390_vtinherit_howto;
350218822Sdim  if (strcasecmp (elf32_s390_vtentry_howto.name, r_name) == 0)
351218822Sdim    return &elf32_s390_vtentry_howto;
352218822Sdim
353218822Sdim  return NULL;
354218822Sdim}
355218822Sdim
35699461Sobrien/* We need to use ELF32_R_TYPE so we have our own copy of this function,
35799461Sobrien   and elf32-s390.c has its own copy.  */
35899461Sobrien
35999461Sobrienstatic void
36099461Sobrienelf_s390_info_to_howto (abfd, cache_ptr, dst)
36199461Sobrien     bfd *abfd ATTRIBUTE_UNUSED;
36299461Sobrien     arelent *cache_ptr;
36399461Sobrien     Elf_Internal_Rela *dst;
36499461Sobrien{
365218822Sdim  unsigned int r_type = ELF32_R_TYPE(dst->r_info);
366218822Sdim  switch (r_type)
36799461Sobrien    {
36899461Sobrien    case R_390_GNU_VTINHERIT:
36999461Sobrien      cache_ptr->howto = &elf32_s390_vtinherit_howto;
37099461Sobrien      break;
37199461Sobrien
37299461Sobrien    case R_390_GNU_VTENTRY:
37399461Sobrien      cache_ptr->howto = &elf32_s390_vtentry_howto;
37499461Sobrien      break;
37599461Sobrien
37699461Sobrien    default:
377218822Sdim      if (r_type >= sizeof (elf_howto_table) / sizeof (elf_howto_table[0]))
378218822Sdim	{
379218822Sdim	  (*_bfd_error_handler) (_("%B: invalid relocation type %d"),
380218822Sdim				 abfd, (int) r_type);
381218822Sdim	  r_type = R_390_NONE;
382218822Sdim	}
383218822Sdim      cache_ptr->howto = &elf_howto_table[r_type];
38499461Sobrien    }
38599461Sobrien}
38699461Sobrien
387130561Sobrien/* A relocation function which doesn't do anything.  */
388130561Sobrienstatic bfd_reloc_status_type
389130561Sobriens390_tls_reloc (abfd, reloc_entry, symbol, data, input_section,
390130561Sobrien		output_bfd, error_message)
391130561Sobrien     bfd *abfd ATTRIBUTE_UNUSED;
392130561Sobrien     arelent *reloc_entry;
393130561Sobrien     asymbol *symbol ATTRIBUTE_UNUSED;
394130561Sobrien     PTR data ATTRIBUTE_UNUSED;
395130561Sobrien     asection *input_section;
396130561Sobrien     bfd *output_bfd;
397130561Sobrien     char **error_message ATTRIBUTE_UNUSED;
398130561Sobrien{
399130561Sobrien  if (output_bfd)
400130561Sobrien    reloc_entry->address += input_section->output_offset;
401130561Sobrien  return bfd_reloc_ok;
402130561Sobrien}
403130561Sobrien
404130561Sobrien/* Handle the large displacement relocs.  */
405130561Sobrienstatic bfd_reloc_status_type
406130561Sobriens390_elf_ldisp_reloc (abfd, reloc_entry, symbol, data, input_section,
407130561Sobrien                      output_bfd, error_message)
408130561Sobrien     bfd *abfd ATTRIBUTE_UNUSED;
409130561Sobrien     arelent *reloc_entry;
410130561Sobrien     asymbol *symbol;
411130561Sobrien     PTR data ATTRIBUTE_UNUSED;
412130561Sobrien     asection *input_section;
413130561Sobrien     bfd *output_bfd;
414130561Sobrien     char **error_message ATTRIBUTE_UNUSED;
415130561Sobrien{
416130561Sobrien  reloc_howto_type *howto = reloc_entry->howto;
417130561Sobrien  bfd_vma relocation;
418130561Sobrien  bfd_vma insn;
419130561Sobrien
420130561Sobrien  if (output_bfd != (bfd *) NULL
421130561Sobrien      && (symbol->flags & BSF_SECTION_SYM) == 0
422130561Sobrien      && (! howto->partial_inplace
423130561Sobrien	  || reloc_entry->addend == 0))
424130561Sobrien    {
425130561Sobrien      reloc_entry->address += input_section->output_offset;
426130561Sobrien      return bfd_reloc_ok;
427130561Sobrien    }
428130561Sobrien
429130561Sobrien  if (output_bfd != NULL)
430130561Sobrien    return bfd_reloc_continue;
431130561Sobrien
432218822Sdim  if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
433130561Sobrien    return bfd_reloc_outofrange;
434130561Sobrien
435130561Sobrien  relocation = (symbol->value
436130561Sobrien		+ symbol->section->output_section->vma
437130561Sobrien		+ symbol->section->output_offset);
438130561Sobrien  relocation += reloc_entry->addend;
439130561Sobrien  if (howto->pc_relative)
440130561Sobrien    {
441130561Sobrien      relocation -= (input_section->output_section->vma
442130561Sobrien		     + input_section->output_offset);
443130561Sobrien      relocation -= reloc_entry->address;
444130561Sobrien    }
445130561Sobrien
446130561Sobrien  insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
447130561Sobrien  insn |= (relocation & 0xfff) << 16 | (relocation & 0xff000) >> 4;
448130561Sobrien  bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc_entry->address);
449130561Sobrien
450130561Sobrien  if ((bfd_signed_vma) relocation < - 0x80000
451130561Sobrien      || (bfd_signed_vma) relocation > 0x7ffff)
452130561Sobrien    return bfd_reloc_overflow;
453130561Sobrien  else
454130561Sobrien    return bfd_reloc_ok;
455130561Sobrien}
456130561Sobrien
457130561Sobrienstatic bfd_boolean
45899461Sobrienelf_s390_is_local_label_name (abfd, name)
45999461Sobrien     bfd *abfd;
46099461Sobrien     const char *name;
46199461Sobrien{
46299461Sobrien  if (name[0] == '.' && (name[1] == 'X' || name[1] == 'L'))
463130561Sobrien    return TRUE;
46499461Sobrien
46599461Sobrien  return _bfd_elf_is_local_label_name (abfd, name);
46699461Sobrien}
46799461Sobrien
46899461Sobrien/* Functions for the 390 ELF linker.  */
46999461Sobrien
47099461Sobrien/* The name of the dynamic interpreter.  This is put in the .interp
47199461Sobrien   section.  */
47299461Sobrien
47399461Sobrien#define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1"
47499461Sobrien
475130561Sobrien/* If ELIMINATE_COPY_RELOCS is non-zero, the linker will try to avoid
476130561Sobrien   copying dynamic variables from a shared lib into an app's dynbss
477130561Sobrien   section, and instead use a dynamic relocation to point into the
478130561Sobrien   shared lib.  */
479130561Sobrien#define ELIMINATE_COPY_RELOCS 1
480130561Sobrien
48199461Sobrien/* The size in bytes of the first entry in the procedure linkage table.  */
48299461Sobrien#define PLT_FIRST_ENTRY_SIZE 32
48399461Sobrien/* The size in bytes of an entry in the procedure linkage table.  */
48499461Sobrien#define PLT_ENTRY_SIZE 32
48599461Sobrien
48699461Sobrien#define GOT_ENTRY_SIZE 4
48799461Sobrien
48899461Sobrien/* The first three entries in a procedure linkage table are reserved,
48999461Sobrien   and the initial contents are unimportant (we zero them out).
49099461Sobrien   Subsequent entries look like this.  See the SVR4 ABI 386
49199461Sobrien   supplement to see how this works.  */
49299461Sobrien
49399461Sobrien/* For the s390, simple addr offset can only be 0 - 4096.
49499461Sobrien   To use the full 2 GB address space, several instructions
49599461Sobrien   are needed to load an address in a register and execute
49699461Sobrien   a branch( or just saving the address)
49799461Sobrien
49899461Sobrien   Furthermore, only r 0 and 1 are free to use!!!  */
49999461Sobrien
50099461Sobrien/* The first 3 words in the GOT are then reserved.
50199461Sobrien   Word 0 is the address of the dynamic table.
50299461Sobrien   Word 1 is a pointer to a structure describing the object
50399461Sobrien   Word 2 is used to point to the loader entry address.
50499461Sobrien
505130561Sobrien   The code for position independent PLT entries looks like this:
50699461Sobrien
50799461Sobrien   r12 holds addr of the current GOT at entry to the PLT
50899461Sobrien
50999461Sobrien   The GOT holds the address in the PLT to be executed.
51099461Sobrien   The loader then gets:
51199461Sobrien   24(15) =  Pointer to the structure describing the object.
51299461Sobrien   28(15) =  Offset in symbol table
51399461Sobrien
51499461Sobrien   The loader  must  then find the module where the function is
51599461Sobrien   and insert the address in the GOT.
51699461Sobrien
51799461Sobrien  Note: 390 can only address +- 64 K relative.
51899461Sobrien        We check if offset > 65536, then make a relative branch -64xxx
51999461Sobrien        back to a previous defined branch
52099461Sobrien
52199461SobrienPLT1: BASR 1,0         # 2 bytes
52299461Sobrien      L    1,22(1)     # 4 bytes  Load offset in GOT in r 1
52399461Sobrien      L    1,(1,12)    # 4 bytes  Load address from GOT in r1
52499461Sobrien      BCR  15,1        # 2 bytes  Jump to address
52599461SobrienRET1: BASR 1,0         # 2 bytes  Return from GOT 1st time
52699461Sobrien      L    1,14(1)     # 4 bytes  Load offset in symol table in r1
52799461Sobrien      BRC  15,-x       # 4 bytes  Jump to start of PLT
52899461Sobrien      .word 0          # 2 bytes filler
52999461Sobrien      .long ?          # 4 bytes  offset in GOT
53099461Sobrien      .long ?          # 4 bytes  offset into symbol table
53199461Sobrien
53299461Sobrien  This was the general case. There are two additional, optimizes PLT
53399461Sobrien  definitions. One for GOT offsets < 4096 and one for GOT offsets < 32768.
53499461Sobrien  First the one for GOT offsets < 4096:
53599461Sobrien
53699461SobrienPLT1: L    1,<offset>(12) # 4 bytes  Load address from GOT in R1
53799461Sobrien      BCR  15,1           # 2 bytes  Jump to address
53899461Sobrien      .word 0,0,0         # 6 bytes  filler
53999461SobrienRET1: BASR 1,0            # 2 bytes  Return from GOT 1st time
54099461Sobrien      L    1,14(1)        # 4 bytes  Load offset in symbol table in r1
54199461Sobrien      BRC  15,-x          # 4 bytes  Jump to start of PLT
54299461Sobrien      .word 0,0,0         # 6 bytes  filler
54399461Sobrien      .long ?             # 4 bytes  offset into symbol table
54499461Sobrien
54599461Sobrien  Second the one for GOT offsets < 32768:
54699461Sobrien
54799461SobrienPLT1: LHI  1,<offset>     # 4 bytes  Load offset in GOT to r1
54899461Sobrien      L    1,(1,12)       # 4 bytes  Load address from GOT to r1
54999461Sobrien      BCR  15,1           # 2 bytes  Jump to address
55099461Sobrien      .word 0             # 2 bytes  filler
55199461SobrienRET1: BASR 1,0            # 2 bytes  Return from GOT 1st time
55299461Sobrien      L    1,14(1)        # 4 bytes  Load offset in symbol table in r1
55399461Sobrien      BRC  15,-x          # 4 bytes  Jump to start of PLT
55499461Sobrien      .word 0,0,0         # 6 bytes  filler
55599461Sobrien      .long ?             # 4 bytes  offset into symbol table
55699461Sobrien
55799461SobrienTotal = 32 bytes per PLT entry
55899461Sobrien
55999461Sobrien   The code for static build PLT entries looks like this:
56099461Sobrien
56199461SobrienPLT1: BASR 1,0         # 2 bytes
56299461Sobrien      L    1,22(1)     # 4 bytes  Load address of GOT entry
56399461Sobrien      L    1,0(0,1)    # 4 bytes  Load address from GOT in r1
56499461Sobrien      BCR  15,1        # 2 bytes  Jump to address
56599461SobrienRET1: BASR 1,0         # 2 bytes  Return from GOT 1st time
56699461Sobrien      L    1,14(1)     # 4 bytes  Load offset in symbol table in r1
56799461Sobrien      BRC  15,-x       # 4 bytes  Jump to start of PLT
56899461Sobrien      .word 0          # 2 bytes  filler
56999461Sobrien      .long ?          # 4 bytes  address of GOT entry
57099461Sobrien      .long ?          # 4 bytes  offset into symbol table  */
57199461Sobrien
57299461Sobrien#define PLT_PIC_ENTRY_WORD0 0x0d105810
57399461Sobrien#define PLT_PIC_ENTRY_WORD1 0x10165811
57499461Sobrien#define PLT_PIC_ENTRY_WORD2 0xc00007f1
57599461Sobrien#define PLT_PIC_ENTRY_WORD3 0x0d105810
57699461Sobrien#define PLT_PIC_ENTRY_WORD4 0x100ea7f4
57799461Sobrien
57899461Sobrien#define PLT_PIC12_ENTRY_WORD0 0x5810c000
57999461Sobrien#define PLT_PIC12_ENTRY_WORD1 0x07f10000
58099461Sobrien#define PLT_PIC12_ENTRY_WORD2 0x00000000
58199461Sobrien#define PLT_PIC12_ENTRY_WORD3 0x0d105810
58299461Sobrien#define PLT_PIC12_ENTRY_WORD4 0x100ea7f4
58399461Sobrien
58499461Sobrien#define PLT_PIC16_ENTRY_WORD0 0xa7180000
58599461Sobrien#define PLT_PIC16_ENTRY_WORD1 0x5811c000
58699461Sobrien#define PLT_PIC16_ENTRY_WORD2 0x07f10000
58799461Sobrien#define PLT_PIC16_ENTRY_WORD3 0x0d105810
58899461Sobrien#define PLT_PIC16_ENTRY_WORD4 0x100ea7f4
58999461Sobrien
59099461Sobrien#define PLT_ENTRY_WORD0     0x0d105810
59199461Sobrien#define PLT_ENTRY_WORD1     0x10165810
59299461Sobrien#define PLT_ENTRY_WORD2     0x100007f1
59399461Sobrien#define PLT_ENTRY_WORD3     0x0d105810
59499461Sobrien#define PLT_ENTRY_WORD4     0x100ea7f4
59599461Sobrien
59699461Sobrien/* The first PLT entry pushes the offset into the symbol table
59799461Sobrien   from R1 onto the stack at 8(15) and the loader object info
59899461Sobrien   at 12(15), loads the loader address in R1 and jumps to it.  */
59999461Sobrien
60099461Sobrien/* The first entry in the PLT for PIC code:
60199461Sobrien
60299461SobrienPLT0:
60399461Sobrien   ST   1,28(15)  # R1 has offset into symbol table
60499461Sobrien   L    1,4(12)   # Get loader ino(object struct address)
60599461Sobrien   ST   1,24(15)  # Store address
60699461Sobrien   L    1,8(12)   # Entry address of loader in R1
60799461Sobrien   BR   1         # Jump to loader
60899461Sobrien
60999461Sobrien   The first entry in the PLT for static code:
61099461Sobrien
61199461SobrienPLT0:
61299461Sobrien   ST   1,28(15)      # R1 has offset into symbol table
61399461Sobrien   BASR 1,0
61499461Sobrien   L    1,18(0,1)     # Get address of GOT
61599461Sobrien   MVC  24(4,15),4(1) # Move loader ino to stack
61699461Sobrien   L    1,8(1)        # Get address of loader
61799461Sobrien   BR   1             # Jump to loader
61899461Sobrien   .word 0            # filler
61999461Sobrien   .long got          # address of GOT  */
62099461Sobrien
62199461Sobrien#define PLT_PIC_FIRST_ENTRY_WORD0 0x5010f01c
62299461Sobrien#define PLT_PIC_FIRST_ENTRY_WORD1 0x5810c004
62399461Sobrien#define PLT_PIC_FIRST_ENTRY_WORD2 0x5010f018
62499461Sobrien#define PLT_PIC_FIRST_ENTRY_WORD3 0x5810c008
62599461Sobrien#define PLT_PIC_FIRST_ENTRY_WORD4 0x07f10000
62699461Sobrien
62799461Sobrien#define PLT_FIRST_ENTRY_WORD0     0x5010f01c
62899461Sobrien#define PLT_FIRST_ENTRY_WORD1     0x0d105810
62999461Sobrien#define PLT_FIRST_ENTRY_WORD2     0x1012D203
63099461Sobrien#define PLT_FIRST_ENTRY_WORD3     0xf0181004
63199461Sobrien#define PLT_FIRST_ENTRY_WORD4     0x58101008
63299461Sobrien#define PLT_FIRST_ENTRY_WORD5     0x07f10000
63399461Sobrien
63499461Sobrien/* The s390 linker needs to keep track of the number of relocs that it
63599461Sobrien   decides to copy as dynamic relocs in check_relocs for each symbol.
63699461Sobrien   This is so that it can later discard them if they are found to be
63799461Sobrien   unnecessary.  We store the information in a field extending the
63899461Sobrien   regular ELF linker hash table.  */
63999461Sobrien
64099461Sobrienstruct elf_s390_dyn_relocs
64199461Sobrien{
64299461Sobrien  struct elf_s390_dyn_relocs *next;
64399461Sobrien
64499461Sobrien  /* The input section of the reloc.  */
64599461Sobrien  asection *sec;
64699461Sobrien
64799461Sobrien  /* Total number of relocs copied for the input section.  */
64899461Sobrien  bfd_size_type count;
64999461Sobrien
65099461Sobrien  /* Number of pc-relative relocs copied for the input section.  */
65199461Sobrien  bfd_size_type pc_count;
65299461Sobrien};
65399461Sobrien
65499461Sobrien/* s390 ELF linker hash entry.  */
65599461Sobrien
65699461Sobrienstruct elf_s390_link_hash_entry
65799461Sobrien{
65899461Sobrien  struct elf_link_hash_entry elf;
65999461Sobrien
66099461Sobrien  /* Track dynamic relocs copied for this symbol.  */
66199461Sobrien  struct elf_s390_dyn_relocs *dyn_relocs;
662130561Sobrien
663130561Sobrien  /* Number of GOTPLT references for a function.  */
664130561Sobrien  bfd_signed_vma gotplt_refcount;
665130561Sobrien
666130561Sobrien#define GOT_UNKNOWN	0
667130561Sobrien#define GOT_NORMAL	1
668130561Sobrien#define GOT_TLS_GD	2
669130561Sobrien#define GOT_TLS_IE	3
670130561Sobrien#define GOT_TLS_IE_NLT	4
671130561Sobrien  unsigned char tls_type;
67299461Sobrien};
67399461Sobrien
674130561Sobrien#define elf_s390_hash_entry(ent) \
675130561Sobrien  ((struct elf_s390_link_hash_entry *)(ent))
676130561Sobrien
677130561Sobrienstruct elf_s390_obj_tdata
678130561Sobrien{
679130561Sobrien  struct elf_obj_tdata root;
680130561Sobrien
681130561Sobrien  /* tls_type for each local got entry.  */
682130561Sobrien  char *local_got_tls_type;
683130561Sobrien};
684130561Sobrien
685130561Sobrien#define elf_s390_tdata(abfd) \
686130561Sobrien  ((struct elf_s390_obj_tdata *) (abfd)->tdata.any)
687130561Sobrien
688130561Sobrien#define elf_s390_local_got_tls_type(abfd) \
689130561Sobrien  (elf_s390_tdata (abfd)->local_got_tls_type)
690130561Sobrien
691130561Sobrienstatic bfd_boolean
692218822Sdimelf_s390_mkobject (bfd *abfd)
693130561Sobrien{
694130561Sobrien  if (abfd->tdata.any == NULL)
695218822Sdim    {
696218822Sdim      bfd_size_type amt = sizeof (struct elf_s390_obj_tdata);
697218822Sdim      abfd->tdata.any = bfd_zalloc (abfd, amt);
698218822Sdim      if (abfd->tdata.any == NULL)
699218822Sdim	return FALSE;
700218822Sdim    }
701218822Sdim  return bfd_elf_mkobject (abfd);
702130561Sobrien}
703130561Sobrien
704130561Sobrienstatic bfd_boolean
705130561Sobrienelf_s390_object_p (abfd)
706130561Sobrien     bfd *abfd;
707130561Sobrien{
708130561Sobrien  /* Set the right machine number for an s390 elf32 file.  */
709130561Sobrien  return bfd_default_set_arch_mach (abfd, bfd_arch_s390, bfd_mach_s390_31);
710130561Sobrien}
711130561Sobrien
71299461Sobrien/* s390 ELF linker hash table.  */
71399461Sobrien
71499461Sobrienstruct elf_s390_link_hash_table
71599461Sobrien{
71699461Sobrien  struct elf_link_hash_table elf;
71799461Sobrien
71899461Sobrien  /* Short-cuts to get to dynamic linker sections.  */
71999461Sobrien  asection *sgot;
72099461Sobrien  asection *sgotplt;
72199461Sobrien  asection *srelgot;
72299461Sobrien  asection *splt;
72399461Sobrien  asection *srelplt;
72499461Sobrien  asection *sdynbss;
72599461Sobrien  asection *srelbss;
72699461Sobrien
727130561Sobrien  union {
728130561Sobrien    bfd_signed_vma refcount;
729130561Sobrien    bfd_vma offset;
730130561Sobrien  } tls_ldm_got;
731130561Sobrien
73299461Sobrien  /* Small local sym to section mapping cache.  */
73399461Sobrien  struct sym_sec_cache sym_sec;
73499461Sobrien};
73599461Sobrien
73699461Sobrien/* Get the s390 ELF linker hash table from a link_info structure.  */
73799461Sobrien
73899461Sobrien#define elf_s390_hash_table(p) \
73999461Sobrien  ((struct elf_s390_link_hash_table *) ((p)->hash))
74099461Sobrien
74199461Sobrien/* Create an entry in an s390 ELF linker hash table.  */
74299461Sobrien
74399461Sobrienstatic struct bfd_hash_entry *
74499461Sobrienlink_hash_newfunc (entry, table, string)
74599461Sobrien     struct bfd_hash_entry *entry;
74699461Sobrien     struct bfd_hash_table *table;
74799461Sobrien     const char *string;
74899461Sobrien{
74999461Sobrien  /* Allocate the structure if it has not already been allocated by a
75099461Sobrien     subclass.  */
75199461Sobrien  if (entry == NULL)
75299461Sobrien    {
75399461Sobrien      entry = bfd_hash_allocate (table,
75499461Sobrien				 sizeof (struct elf_s390_link_hash_entry));
75599461Sobrien      if (entry == NULL)
75699461Sobrien	return entry;
75799461Sobrien    }
75899461Sobrien
75999461Sobrien  /* Call the allocation method of the superclass.  */
76099461Sobrien  entry = _bfd_elf_link_hash_newfunc (entry, table, string);
76199461Sobrien  if (entry != NULL)
76299461Sobrien    {
76399461Sobrien      struct elf_s390_link_hash_entry *eh;
76499461Sobrien
76599461Sobrien      eh = (struct elf_s390_link_hash_entry *) entry;
76699461Sobrien      eh->dyn_relocs = NULL;
767130561Sobrien      eh->gotplt_refcount = 0;
768130561Sobrien      eh->tls_type = GOT_UNKNOWN;
76999461Sobrien    }
77099461Sobrien
77199461Sobrien  return entry;
77299461Sobrien}
77399461Sobrien
77499461Sobrien/* Create an s390 ELF linker hash table.  */
77599461Sobrien
77699461Sobrienstatic struct bfd_link_hash_table *
77799461Sobrienelf_s390_link_hash_table_create (abfd)
77899461Sobrien     bfd *abfd;
77999461Sobrien{
78099461Sobrien  struct elf_s390_link_hash_table *ret;
78199461Sobrien  bfd_size_type amt = sizeof (struct elf_s390_link_hash_table);
78299461Sobrien
783107492Sobrien  ret = (struct elf_s390_link_hash_table *) bfd_malloc (amt);
78499461Sobrien  if (ret == NULL)
78599461Sobrien    return NULL;
78699461Sobrien
787218822Sdim  if (!_bfd_elf_link_hash_table_init (&ret->elf, abfd, link_hash_newfunc,
788218822Sdim				      sizeof (struct elf_s390_link_hash_entry)))
78999461Sobrien    {
790107492Sobrien      free (ret);
79199461Sobrien      return NULL;
79299461Sobrien    }
79399461Sobrien
79499461Sobrien  ret->sgot = NULL;
79599461Sobrien  ret->sgotplt = NULL;
79699461Sobrien  ret->srelgot = NULL;
79799461Sobrien  ret->splt = NULL;
79899461Sobrien  ret->srelplt = NULL;
79999461Sobrien  ret->sdynbss = NULL;
80099461Sobrien  ret->srelbss = NULL;
801130561Sobrien  ret->tls_ldm_got.refcount = 0;
80299461Sobrien  ret->sym_sec.abfd = NULL;
80399461Sobrien
80499461Sobrien  return &ret->elf.root;
80599461Sobrien}
80699461Sobrien
80799461Sobrien/* Create .got, .gotplt, and .rela.got sections in DYNOBJ, and set up
80899461Sobrien   shortcuts to them in our hash table.  */
80999461Sobrien
810130561Sobrienstatic bfd_boolean
81199461Sobriencreate_got_section (dynobj, info)
81299461Sobrien     bfd *dynobj;
81399461Sobrien     struct bfd_link_info *info;
81499461Sobrien{
81599461Sobrien  struct elf_s390_link_hash_table *htab;
81699461Sobrien
81799461Sobrien  if (! _bfd_elf_create_got_section (dynobj, info))
818130561Sobrien    return FALSE;
81999461Sobrien
82099461Sobrien  htab = elf_s390_hash_table (info);
82199461Sobrien  htab->sgot = bfd_get_section_by_name (dynobj, ".got");
82299461Sobrien  htab->sgotplt = bfd_get_section_by_name (dynobj, ".got.plt");
82399461Sobrien  if (!htab->sgot || !htab->sgotplt)
82499461Sobrien    abort ();
82599461Sobrien
826218822Sdim  htab->srelgot = bfd_make_section_with_flags (dynobj, ".rela.got",
827218822Sdim					       (SEC_ALLOC | SEC_LOAD
828218822Sdim						| SEC_HAS_CONTENTS
829218822Sdim						| SEC_IN_MEMORY
830218822Sdim						| SEC_LINKER_CREATED
831218822Sdim						| SEC_READONLY));
83299461Sobrien  if (htab->srelgot == NULL
83399461Sobrien      || ! bfd_set_section_alignment (dynobj, htab->srelgot, 2))
834130561Sobrien    return FALSE;
835130561Sobrien  return TRUE;
83699461Sobrien}
83799461Sobrien
83899461Sobrien/* Create .plt, .rela.plt, .got, .got.plt, .rela.got, .dynbss, and
83999461Sobrien   .rela.bss sections in DYNOBJ, and set up shortcuts to them in our
84099461Sobrien   hash table.  */
84199461Sobrien
842130561Sobrienstatic bfd_boolean
84399461Sobrienelf_s390_create_dynamic_sections (dynobj, info)
84499461Sobrien     bfd *dynobj;
84599461Sobrien     struct bfd_link_info *info;
84699461Sobrien{
84799461Sobrien  struct elf_s390_link_hash_table *htab;
84899461Sobrien
84999461Sobrien  htab = elf_s390_hash_table (info);
85099461Sobrien  if (!htab->sgot && !create_got_section (dynobj, info))
851130561Sobrien    return FALSE;
85299461Sobrien
85399461Sobrien  if (!_bfd_elf_create_dynamic_sections (dynobj, info))
854130561Sobrien    return FALSE;
85599461Sobrien
85699461Sobrien  htab->splt = bfd_get_section_by_name (dynobj, ".plt");
85799461Sobrien  htab->srelplt = bfd_get_section_by_name (dynobj, ".rela.plt");
85899461Sobrien  htab->sdynbss = bfd_get_section_by_name (dynobj, ".dynbss");
85999461Sobrien  if (!info->shared)
86099461Sobrien    htab->srelbss = bfd_get_section_by_name (dynobj, ".rela.bss");
86199461Sobrien
86299461Sobrien  if (!htab->splt || !htab->srelplt || !htab->sdynbss
86399461Sobrien      || (!info->shared && !htab->srelbss))
86499461Sobrien    abort ();
86599461Sobrien
866130561Sobrien  return TRUE;
86799461Sobrien}
86899461Sobrien
86999461Sobrien/* Copy the extra info we tack onto an elf_link_hash_entry.  */
87099461Sobrien
87199461Sobrienstatic void
872218822Sdimelf_s390_copy_indirect_symbol (info, dir, ind)
873218822Sdim     struct bfd_link_info *info;
87499461Sobrien     struct elf_link_hash_entry *dir, *ind;
87599461Sobrien{
87699461Sobrien  struct elf_s390_link_hash_entry *edir, *eind;
87799461Sobrien
87899461Sobrien  edir = (struct elf_s390_link_hash_entry *) dir;
87999461Sobrien  eind = (struct elf_s390_link_hash_entry *) ind;
88099461Sobrien
88199461Sobrien  if (eind->dyn_relocs != NULL)
88299461Sobrien    {
88399461Sobrien      if (edir->dyn_relocs != NULL)
88499461Sobrien	{
88599461Sobrien	  struct elf_s390_dyn_relocs **pp;
88699461Sobrien	  struct elf_s390_dyn_relocs *p;
88799461Sobrien
888218822Sdim	  /* Add reloc counts against the indirect sym to the direct sym
88999461Sobrien	     list.  Merge any entries against the same section.  */
89099461Sobrien	  for (pp = &eind->dyn_relocs; (p = *pp) != NULL; )
89199461Sobrien	    {
89299461Sobrien	      struct elf_s390_dyn_relocs *q;
89399461Sobrien
89499461Sobrien	      for (q = edir->dyn_relocs; q != NULL; q = q->next)
89599461Sobrien		if (q->sec == p->sec)
89699461Sobrien		  {
89799461Sobrien		    q->pc_count += p->pc_count;
89899461Sobrien		    q->count += p->count;
89999461Sobrien		    *pp = p->next;
90099461Sobrien		    break;
90199461Sobrien		  }
90299461Sobrien	      if (q == NULL)
90399461Sobrien		pp = &p->next;
90499461Sobrien	    }
90599461Sobrien	  *pp = edir->dyn_relocs;
90699461Sobrien	}
90799461Sobrien
90899461Sobrien      edir->dyn_relocs = eind->dyn_relocs;
90999461Sobrien      eind->dyn_relocs = NULL;
91099461Sobrien    }
91199461Sobrien
912130561Sobrien  if (ind->root.type == bfd_link_hash_indirect
913130561Sobrien      && dir->got.refcount <= 0)
914130561Sobrien    {
915130561Sobrien      edir->tls_type = eind->tls_type;
916130561Sobrien      eind->tls_type = GOT_UNKNOWN;
917130561Sobrien    }
918130561Sobrien
919130561Sobrien  if (ELIMINATE_COPY_RELOCS
920130561Sobrien      && ind->root.type != bfd_link_hash_indirect
921218822Sdim      && dir->dynamic_adjusted)
922218822Sdim    {
923218822Sdim      /* If called to transfer flags for a weakdef during processing
924218822Sdim	 of elf_adjust_dynamic_symbol, don't copy non_got_ref.
925218822Sdim	 We clear it ourselves for ELIMINATE_COPY_RELOCS.  */
926218822Sdim      dir->ref_dynamic |= ind->ref_dynamic;
927218822Sdim      dir->ref_regular |= ind->ref_regular;
928218822Sdim      dir->ref_regular_nonweak |= ind->ref_regular_nonweak;
929218822Sdim      dir->needs_plt |= ind->needs_plt;
930218822Sdim    }
931130561Sobrien  else
932218822Sdim    _bfd_elf_link_hash_copy_indirect (info, dir, ind);
93399461Sobrien}
93499461Sobrien
935130561Sobrienstatic int
936130561Sobrienelf_s390_tls_transition (info, r_type, is_local)
937130561Sobrien     struct bfd_link_info *info;
938130561Sobrien     int r_type;
939130561Sobrien     int is_local;
940130561Sobrien{
941130561Sobrien  if (info->shared)
942130561Sobrien    return r_type;
943130561Sobrien
944130561Sobrien  switch (r_type)
945130561Sobrien    {
946130561Sobrien    case R_390_TLS_GD32:
947130561Sobrien    case R_390_TLS_IE32:
948130561Sobrien      if (is_local)
949130561Sobrien	return R_390_TLS_LE32;
950130561Sobrien      return R_390_TLS_IE32;
951130561Sobrien    case R_390_TLS_GOTIE32:
952130561Sobrien      if (is_local)
953130561Sobrien	return R_390_TLS_LE32;
954130561Sobrien      return R_390_TLS_GOTIE32;
955130561Sobrien    case R_390_TLS_LDM32:
956130561Sobrien      return R_390_TLS_LE32;
957130561Sobrien    }
958130561Sobrien
959130561Sobrien  return r_type;
960130561Sobrien}
961130561Sobrien
96299461Sobrien/* Look through the relocs for a section during the first phase, and
96399461Sobrien   allocate space in the global offset table or procedure linkage
96499461Sobrien   table.  */
96599461Sobrien
966130561Sobrienstatic bfd_boolean
96799461Sobrienelf_s390_check_relocs (abfd, info, sec, relocs)
96899461Sobrien     bfd *abfd;
96999461Sobrien     struct bfd_link_info *info;
97099461Sobrien     asection *sec;
97199461Sobrien     const Elf_Internal_Rela *relocs;
97299461Sobrien{
97399461Sobrien  struct elf_s390_link_hash_table *htab;
97499461Sobrien  Elf_Internal_Shdr *symtab_hdr;
97599461Sobrien  struct elf_link_hash_entry **sym_hashes;
97699461Sobrien  const Elf_Internal_Rela *rel;
97799461Sobrien  const Elf_Internal_Rela *rel_end;
97899461Sobrien  asection *sreloc;
979130561Sobrien  bfd_signed_vma *local_got_refcounts;
980130561Sobrien  int tls_type, old_tls_type;
98199461Sobrien
982130561Sobrien  if (info->relocatable)
983130561Sobrien    return TRUE;
98499461Sobrien
98599461Sobrien  htab = elf_s390_hash_table (info);
98699461Sobrien  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
98799461Sobrien  sym_hashes = elf_sym_hashes (abfd);
988130561Sobrien  local_got_refcounts = elf_local_got_refcounts (abfd);
98999461Sobrien
99099461Sobrien  sreloc = NULL;
99199461Sobrien
99299461Sobrien  rel_end = relocs + sec->reloc_count;
99399461Sobrien  for (rel = relocs; rel < rel_end; rel++)
99499461Sobrien    {
995130561Sobrien      unsigned int r_type;
99699461Sobrien      unsigned long r_symndx;
99799461Sobrien      struct elf_link_hash_entry *h;
99899461Sobrien
99999461Sobrien      r_symndx = ELF32_R_SYM (rel->r_info);
100099461Sobrien
100199461Sobrien      if (r_symndx >= NUM_SHDR_ENTRIES (symtab_hdr))
100299461Sobrien	{
1003218822Sdim	  (*_bfd_error_handler) (_("%B: bad symbol index: %d"),
1004218822Sdim				 abfd, r_symndx);
1005130561Sobrien	  return FALSE;
100699461Sobrien	}
100799461Sobrien
100899461Sobrien      if (r_symndx < symtab_hdr->sh_info)
100999461Sobrien	h = NULL;
101099461Sobrien      else
1011218822Sdim	{
1012218822Sdim	  h = sym_hashes[r_symndx - symtab_hdr->sh_info];
1013218822Sdim	  while (h->root.type == bfd_link_hash_indirect
1014218822Sdim		 || h->root.type == bfd_link_hash_warning)
1015218822Sdim	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
1016218822Sdim	}
101799461Sobrien
1018130561Sobrien      /* Create got section and local_got_refcounts array if they
1019130561Sobrien	 are needed.  */
1020130561Sobrien      r_type = elf_s390_tls_transition (info,
1021130561Sobrien					ELF32_R_TYPE (rel->r_info),
1022130561Sobrien					h == NULL);
1023130561Sobrien      switch (r_type)
102499461Sobrien	{
102599461Sobrien	case R_390_GOT12:
1026130561Sobrien	case R_390_GOT16:
1027130561Sobrien	case R_390_GOT20:
102899461Sobrien	case R_390_GOT32:
102999461Sobrien	case R_390_GOTENT:
1030130561Sobrien	case R_390_GOTPLT12:
1031130561Sobrien	case R_390_GOTPLT16:
1032130561Sobrien	case R_390_GOTPLT20:
1033130561Sobrien	case R_390_GOTPLT32:
1034130561Sobrien	case R_390_GOTPLTENT:
1035130561Sobrien	case R_390_TLS_GD32:
1036130561Sobrien	case R_390_TLS_GOTIE12:
1037130561Sobrien	case R_390_TLS_GOTIE20:
1038130561Sobrien	case R_390_TLS_GOTIE32:
1039130561Sobrien	case R_390_TLS_IEENT:
1040130561Sobrien	case R_390_TLS_IE32:
1041130561Sobrien	case R_390_TLS_LDM32:
1042130561Sobrien	  if (h == NULL
1043130561Sobrien	      && local_got_refcounts == NULL)
104499461Sobrien	    {
1045130561Sobrien	      bfd_size_type size;
104699461Sobrien
1047130561Sobrien	      size = symtab_hdr->sh_info;
1048130561Sobrien	      size *= (sizeof (bfd_signed_vma) + sizeof(char));
1049130561Sobrien	      local_got_refcounts = ((bfd_signed_vma *)
1050130561Sobrien				     bfd_zalloc (abfd, size));
105199461Sobrien	      if (local_got_refcounts == NULL)
1052130561Sobrien		return FALSE;
1053130561Sobrien	      elf_local_got_refcounts (abfd) = local_got_refcounts;
1054130561Sobrien	      elf_s390_local_got_tls_type (abfd)
1055130561Sobrien		= (char *) (local_got_refcounts + symtab_hdr->sh_info);
105699461Sobrien	    }
1057130561Sobrien	  /* Fall through.  */
1058130561Sobrien	case R_390_GOTOFF16:
1059130561Sobrien	case R_390_GOTOFF32:
106099461Sobrien	case R_390_GOTPC:
106199461Sobrien	case R_390_GOTPCDBL:
106299461Sobrien	  if (htab->sgot == NULL)
106399461Sobrien	    {
106499461Sobrien	      if (htab->elf.dynobj == NULL)
106599461Sobrien		htab->elf.dynobj = abfd;
106699461Sobrien	      if (!create_got_section (htab->elf.dynobj, info))
1067130561Sobrien		return FALSE;
106899461Sobrien	    }
1069130561Sobrien	}
1070130561Sobrien
1071130561Sobrien      switch (r_type)
1072130561Sobrien	{
1073130561Sobrien	case R_390_GOTOFF16:
1074130561Sobrien	case R_390_GOTOFF32:
1075130561Sobrien	case R_390_GOTPC:
1076130561Sobrien	case R_390_GOTPCDBL:
1077130561Sobrien	  /* Got is created, nothing to be done.  */
107899461Sobrien	  break;
107999461Sobrien
1080130561Sobrien	case R_390_PLT16DBL:
1081130561Sobrien	case R_390_PLT32DBL:
108299461Sobrien	case R_390_PLT32:
1083130561Sobrien	case R_390_PLTOFF16:
1084130561Sobrien	case R_390_PLTOFF32:
108599461Sobrien	  /* This symbol requires a procedure linkage table entry.  We
1086130561Sobrien	     actually build the entry in adjust_dynamic_symbol,
1087130561Sobrien	     because this might be a case of linking PIC code which is
1088130561Sobrien	     never referenced by a dynamic object, in which case we
1089130561Sobrien	     don't need to generate a procedure linkage table entry
1090130561Sobrien	     after all.  */
109199461Sobrien
109299461Sobrien	  /* If this is a local symbol, we resolve it directly without
1093130561Sobrien	     creating a procedure linkage table entry.  */
1094130561Sobrien	  if (h != NULL)
1095130561Sobrien	    {
1096218822Sdim	      h->needs_plt = 1;
1097130561Sobrien	      h->plt.refcount += 1;
1098130561Sobrien	    }
1099130561Sobrien	  break;
110099461Sobrien
1101130561Sobrien	case R_390_GOTPLT12:
1102130561Sobrien	case R_390_GOTPLT16:
1103130561Sobrien	case R_390_GOTPLT20:
1104130561Sobrien	case R_390_GOTPLT32:
1105130561Sobrien	case R_390_GOTPLTENT:
1106130561Sobrien	  /* This symbol requires either a procedure linkage table entry
1107130561Sobrien	     or an entry in the local got. We actually build the entry
1108130561Sobrien	     in adjust_dynamic_symbol because whether this is really a
1109130561Sobrien	     global reference can change and with it the fact if we have
1110130561Sobrien	     to create a plt entry or a local got entry. To be able to
1111130561Sobrien	     make a once global symbol a local one we have to keep track
1112130561Sobrien	     of the number of gotplt references that exist for this
1113130561Sobrien	     symbol.  */
1114130561Sobrien	  if (h != NULL)
1115130561Sobrien	    {
1116130561Sobrien	      ((struct elf_s390_link_hash_entry *) h)->gotplt_refcount++;
1117218822Sdim	      h->needs_plt = 1;
1118130561Sobrien	      h->plt.refcount += 1;
1119130561Sobrien	    }
1120130561Sobrien	  else
1121130561Sobrien	    local_got_refcounts[r_symndx] += 1;
112299461Sobrien	  break;
112399461Sobrien
1124130561Sobrien	case R_390_TLS_LDM32:
1125130561Sobrien	  htab->tls_ldm_got.refcount += 1;
1126130561Sobrien	  break;
1127130561Sobrien
1128130561Sobrien	case R_390_TLS_IE32:
1129130561Sobrien	case R_390_TLS_GOTIE12:
1130130561Sobrien	case R_390_TLS_GOTIE20:
1131130561Sobrien	case R_390_TLS_GOTIE32:
1132130561Sobrien	case R_390_TLS_IEENT:
1133130561Sobrien	  if (info->shared)
1134130561Sobrien	    info->flags |= DF_STATIC_TLS;
1135130561Sobrien	  /* Fall through.  */
1136130561Sobrien
1137130561Sobrien	case R_390_GOT12:
1138130561Sobrien	case R_390_GOT16:
1139130561Sobrien	case R_390_GOT20:
1140130561Sobrien	case R_390_GOT32:
1141130561Sobrien	case R_390_GOTENT:
1142130561Sobrien	case R_390_TLS_GD32:
1143130561Sobrien	  /* This symbol requires a global offset table entry.  */
1144130561Sobrien	  switch (r_type)
1145130561Sobrien	    {
1146130561Sobrien	    default:
1147130561Sobrien	    case R_390_GOT12:
1148130561Sobrien	    case R_390_GOT16:
1149130561Sobrien	    case R_390_GOT20:
1150130561Sobrien	    case R_390_GOT32:
1151130561Sobrien	    case R_390_GOTENT:
1152130561Sobrien	      tls_type = GOT_NORMAL;
1153130561Sobrien	      break;
1154130561Sobrien	    case R_390_TLS_GD32:
1155130561Sobrien	      tls_type = GOT_TLS_GD;
1156130561Sobrien	      break;
1157130561Sobrien	    case R_390_TLS_IE32:
1158130561Sobrien	    case R_390_TLS_GOTIE32:
1159130561Sobrien	      tls_type = GOT_TLS_IE;
1160130561Sobrien	      break;
1161130561Sobrien	    case R_390_TLS_GOTIE12:
1162130561Sobrien	    case R_390_TLS_GOTIE20:
1163130561Sobrien	    case R_390_TLS_IEENT:
1164130561Sobrien	      tls_type = GOT_TLS_IE_NLT;
1165130561Sobrien	      break;
1166130561Sobrien	    }
1167130561Sobrien
1168130561Sobrien	  if (h != NULL)
1169130561Sobrien	    {
1170130561Sobrien	      h->got.refcount += 1;
1171130561Sobrien	      old_tls_type = elf_s390_hash_entry(h)->tls_type;
1172130561Sobrien	    }
1173130561Sobrien	  else
1174130561Sobrien	    {
1175130561Sobrien	      local_got_refcounts[r_symndx] += 1;
1176130561Sobrien	      old_tls_type = elf_s390_local_got_tls_type (abfd) [r_symndx];
1177130561Sobrien	    }
1178130561Sobrien	  /* If a TLS symbol is accessed using IE at least once,
1179130561Sobrien	     there is no point to use dynamic model for it.  */
1180130561Sobrien	  if (old_tls_type != tls_type && old_tls_type != GOT_UNKNOWN)
1181130561Sobrien	    {
1182130561Sobrien	      if (old_tls_type == GOT_NORMAL || tls_type == GOT_NORMAL)
1183130561Sobrien		{
1184130561Sobrien		  (*_bfd_error_handler)
1185218822Sdim		    (_("%B: `%s' accessed both as normal and thread local symbol"),
1186218822Sdim		     abfd, h->root.root.string);
1187130561Sobrien		  return FALSE;
1188130561Sobrien		}
1189130561Sobrien	      if (old_tls_type > tls_type)
1190130561Sobrien		tls_type = old_tls_type;
1191130561Sobrien	    }
1192130561Sobrien
1193130561Sobrien	  if (old_tls_type != tls_type)
1194130561Sobrien	    {
1195130561Sobrien	      if (h != NULL)
1196130561Sobrien		elf_s390_hash_entry (h)->tls_type = tls_type;
1197130561Sobrien	      else
1198130561Sobrien		elf_s390_local_got_tls_type (abfd) [r_symndx] = tls_type;
1199130561Sobrien	    }
1200130561Sobrien
1201130561Sobrien	  if (r_type != R_390_TLS_IE32)
1202130561Sobrien	    break;
1203130561Sobrien	  /* Fall through.  */
1204130561Sobrien
1205130561Sobrien	case R_390_TLS_LE32:
1206130561Sobrien	  if (!info->shared)
1207130561Sobrien	    break;
1208130561Sobrien	  info->flags |= DF_STATIC_TLS;
1209130561Sobrien	  /* Fall through.  */
1210130561Sobrien
1211130561Sobrien	case R_390_8:
1212130561Sobrien	case R_390_16:
121399461Sobrien	case R_390_32:
1214130561Sobrien	case R_390_PC16:
1215130561Sobrien	case R_390_PC16DBL:
121699461Sobrien	case R_390_PC32DBL:
121799461Sobrien	case R_390_PC32:
121899461Sobrien	  if (h != NULL && !info->shared)
121999461Sobrien	    {
122099461Sobrien	      /* If this reloc is in a read-only section, we might
122199461Sobrien		 need a copy reloc.  We can't check reliably at this
122299461Sobrien		 stage whether the section is read-only, as input
122399461Sobrien		 sections have not yet been mapped to output sections.
122499461Sobrien		 Tentatively set the flag for now, and correct in
122599461Sobrien		 adjust_dynamic_symbol.  */
1226218822Sdim	      h->non_got_ref = 1;
122799461Sobrien
122899461Sobrien	      /* We may need a .plt entry if the function this reloc
122999461Sobrien		 refers to is in a shared lib.  */
123099461Sobrien	      h->plt.refcount += 1;
123199461Sobrien	    }
123299461Sobrien
123399461Sobrien	  /* If we are creating a shared library, and this is a reloc
123499461Sobrien	     against a global symbol, or a non PC relative reloc
123599461Sobrien	     against a local symbol, then we need to copy the reloc
123699461Sobrien	     into the shared library.  However, if we are linking with
123799461Sobrien	     -Bsymbolic, we do not need to copy a reloc against a
123899461Sobrien	     global symbol which is defined in an object we are
123999461Sobrien	     including in the link (i.e., DEF_REGULAR is set).  At
124099461Sobrien	     this point we have not seen all the input files, so it is
124199461Sobrien	     possible that DEF_REGULAR is not set now but will be set
124299461Sobrien	     later (it is never cleared).  In case of a weak definition,
124399461Sobrien	     DEF_REGULAR may be cleared later by a strong definition in
124499461Sobrien	     a shared library. We account for that possibility below by
124599461Sobrien	     storing information in the relocs_copied field of the hash
124699461Sobrien	     table entry.  A similar situation occurs when creating
124799461Sobrien	     shared libraries and symbol visibility changes render the
124899461Sobrien	     symbol local.
124999461Sobrien
125099461Sobrien	     If on the other hand, we are creating an executable, we
125199461Sobrien	     may need to keep relocations for symbols satisfied by a
125299461Sobrien	     dynamic library if we manage to avoid copy relocs for the
125399461Sobrien	     symbol.  */
125499461Sobrien	  if ((info->shared
125599461Sobrien	       && (sec->flags & SEC_ALLOC) != 0
125699461Sobrien	       && ((ELF32_R_TYPE (rel->r_info) != R_390_PC16
125799461Sobrien		    && ELF32_R_TYPE (rel->r_info) != R_390_PC16DBL
125899461Sobrien		    && ELF32_R_TYPE (rel->r_info) != R_390_PC32DBL
125999461Sobrien		    && ELF32_R_TYPE (rel->r_info) != R_390_PC32)
126099461Sobrien		   || (h != NULL
126199461Sobrien		       && (! info->symbolic
126299461Sobrien			   || h->root.type == bfd_link_hash_defweak
1263218822Sdim			   || !h->def_regular))))
1264130561Sobrien	      || (ELIMINATE_COPY_RELOCS
1265130561Sobrien		  && !info->shared
126699461Sobrien		  && (sec->flags & SEC_ALLOC) != 0
126799461Sobrien		  && h != NULL
126899461Sobrien		  && (h->root.type == bfd_link_hash_defweak
1269218822Sdim		      || !h->def_regular)))
127099461Sobrien	    {
127199461Sobrien	      struct elf_s390_dyn_relocs *p;
127299461Sobrien	      struct elf_s390_dyn_relocs **head;
127399461Sobrien
127499461Sobrien	      /* We must copy these reloc types into the output file.
127599461Sobrien		 Create a reloc section in dynobj and make room for
127699461Sobrien		 this reloc.  */
127799461Sobrien	      if (sreloc == NULL)
127899461Sobrien		{
127999461Sobrien		  const char *name;
128099461Sobrien		  bfd *dynobj;
128199461Sobrien
128299461Sobrien		  name = (bfd_elf_string_from_elf_section
128399461Sobrien			  (abfd,
128499461Sobrien			   elf_elfheader (abfd)->e_shstrndx,
128599461Sobrien			   elf_section_data (sec)->rel_hdr.sh_name));
128699461Sobrien		  if (name == NULL)
1287130561Sobrien		    return FALSE;
128899461Sobrien
1289218822Sdim		  if (! CONST_STRNEQ (name, ".rela")
129099461Sobrien		      || strcmp (bfd_get_section_name (abfd, sec),
129199461Sobrien				 name + 5) != 0)
129299461Sobrien		    {
129399461Sobrien		      (*_bfd_error_handler)
1294218822Sdim			(_("%B: bad relocation section name `%s\'"),
1295218822Sdim			 abfd, name);
129699461Sobrien		    }
129799461Sobrien
129899461Sobrien		  if (htab->elf.dynobj == NULL)
129999461Sobrien		    htab->elf.dynobj = abfd;
130099461Sobrien
130199461Sobrien		  dynobj = htab->elf.dynobj;
130299461Sobrien		  sreloc = bfd_get_section_by_name (dynobj, name);
130399461Sobrien		  if (sreloc == NULL)
130499461Sobrien		    {
130599461Sobrien		      flagword flags;
130699461Sobrien
130799461Sobrien		      flags = (SEC_HAS_CONTENTS | SEC_READONLY
130899461Sobrien			       | SEC_IN_MEMORY | SEC_LINKER_CREATED);
130999461Sobrien		      if ((sec->flags & SEC_ALLOC) != 0)
131099461Sobrien			flags |= SEC_ALLOC | SEC_LOAD;
1311218822Sdim		      sreloc = bfd_make_section_with_flags (dynobj,
1312218822Sdim							    name,
1313218822Sdim							    flags);
131499461Sobrien		      if (sreloc == NULL
131599461Sobrien			  || ! bfd_set_section_alignment (dynobj, sreloc, 2))
1316130561Sobrien			return FALSE;
131799461Sobrien		    }
131899461Sobrien		  elf_section_data (sec)->sreloc = sreloc;
131999461Sobrien		}
132099461Sobrien
132199461Sobrien	      /* If this is a global symbol, we count the number of
132299461Sobrien		 relocations we need for this symbol.  */
132399461Sobrien	      if (h != NULL)
132499461Sobrien		{
132599461Sobrien		  head = &((struct elf_s390_link_hash_entry *) h)->dyn_relocs;
132699461Sobrien		}
132799461Sobrien	      else
132899461Sobrien		{
132999461Sobrien		  /* Track dynamic relocs needed for local syms too.
133099461Sobrien		     We really need local syms available to do this
133199461Sobrien		     easily.  Oh well.  */
1332130561Sobrien		  asection *s;
1333218822Sdim		  void *vpp;
133499461Sobrien
133599461Sobrien		  s = bfd_section_from_r_symndx (abfd, &htab->sym_sec,
133699461Sobrien						 sec, r_symndx);
133799461Sobrien		  if (s == NULL)
1338130561Sobrien		    return FALSE;
133999461Sobrien
1340218822Sdim		  vpp = &elf_section_data (s)->local_dynrel;
1341218822Sdim		  head = (struct elf_s390_dyn_relocs **) vpp;
134299461Sobrien		}
134399461Sobrien
134499461Sobrien	      p = *head;
134599461Sobrien	      if (p == NULL || p->sec != sec)
134699461Sobrien		{
134799461Sobrien		  bfd_size_type amt = sizeof *p;
1348130561Sobrien
134999461Sobrien		  p = ((struct elf_s390_dyn_relocs *)
135099461Sobrien		       bfd_alloc (htab->elf.dynobj, amt));
135199461Sobrien		  if (p == NULL)
1352130561Sobrien		    return FALSE;
135399461Sobrien		  p->next = *head;
135499461Sobrien		  *head = p;
135599461Sobrien		  p->sec = sec;
135699461Sobrien		  p->count = 0;
135799461Sobrien		  p->pc_count = 0;
135899461Sobrien		}
135999461Sobrien
136099461Sobrien	      p->count += 1;
136199461Sobrien	      if (ELF32_R_TYPE (rel->r_info) == R_390_PC16
136299461Sobrien		  || ELF32_R_TYPE (rel->r_info) == R_390_PC16DBL
136399461Sobrien		  || ELF32_R_TYPE (rel->r_info) == R_390_PC32DBL
136499461Sobrien		  || ELF32_R_TYPE (rel->r_info) == R_390_PC32)
136599461Sobrien		p->pc_count += 1;
136699461Sobrien	    }
136799461Sobrien	  break;
136899461Sobrien
136999461Sobrien	  /* This relocation describes the C++ object vtable hierarchy.
137099461Sobrien	     Reconstruct it for later use during GC.  */
1371130561Sobrien	case R_390_GNU_VTINHERIT:
1372130561Sobrien	  if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
1373130561Sobrien	    return FALSE;
1374130561Sobrien	  break;
137599461Sobrien
137699461Sobrien	  /* This relocation describes which C++ vtable entries are actually
137799461Sobrien	     used.  Record for later use during GC.  */
1378130561Sobrien	case R_390_GNU_VTENTRY:
1379130561Sobrien	  if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
1380130561Sobrien	    return FALSE;
1381130561Sobrien	  break;
138299461Sobrien
138399461Sobrien	default:
138499461Sobrien	  break;
138599461Sobrien	}
138699461Sobrien    }
138799461Sobrien
1388130561Sobrien  return TRUE;
138999461Sobrien}
139099461Sobrien
139199461Sobrien/* Return the section that should be marked against GC for a given
139299461Sobrien   relocation.  */
139399461Sobrien
139499461Sobrienstatic asection *
1395218822Sdimelf_s390_gc_mark_hook (asection *sec,
1396218822Sdim		       struct bfd_link_info *info,
1397218822Sdim		       Elf_Internal_Rela *rel,
1398218822Sdim		       struct elf_link_hash_entry *h,
1399218822Sdim		       Elf_Internal_Sym *sym)
140099461Sobrien{
140199461Sobrien  if (h != NULL)
1402218822Sdim    switch (ELF32_R_TYPE (rel->r_info))
1403218822Sdim      {
1404218822Sdim      case R_390_GNU_VTINHERIT:
1405218822Sdim      case R_390_GNU_VTENTRY:
1406218822Sdim	return NULL;
1407218822Sdim      }
1408218822Sdim  return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
140999461Sobrien
141099461Sobrien}
141199461Sobrien
141299461Sobrien/* Update the got entry reference counts for the section being removed.  */
141399461Sobrien
1414130561Sobrienstatic bfd_boolean
1415218822Sdimelf_s390_gc_sweep_hook (bfd *abfd,
1416218822Sdim			struct bfd_link_info *info,
1417218822Sdim			asection *sec,
1418218822Sdim			const Elf_Internal_Rela *relocs)
141999461Sobrien{
142099461Sobrien  Elf_Internal_Shdr *symtab_hdr;
142199461Sobrien  struct elf_link_hash_entry **sym_hashes;
142299461Sobrien  bfd_signed_vma *local_got_refcounts;
142399461Sobrien  const Elf_Internal_Rela *rel, *relend;
142499461Sobrien
142599461Sobrien  elf_section_data (sec)->local_dynrel = NULL;
142699461Sobrien
142799461Sobrien  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
142899461Sobrien  sym_hashes = elf_sym_hashes (abfd);
142999461Sobrien  local_got_refcounts = elf_local_got_refcounts (abfd);
143099461Sobrien
143199461Sobrien  relend = relocs + sec->reloc_count;
143299461Sobrien  for (rel = relocs; rel < relend; rel++)
1433130561Sobrien    {
1434130561Sobrien      unsigned long r_symndx;
1435130561Sobrien      unsigned int r_type;
1436130561Sobrien      struct elf_link_hash_entry *h = NULL;
143799461Sobrien
1438130561Sobrien      r_symndx = ELF32_R_SYM (rel->r_info);
1439130561Sobrien      if (r_symndx >= symtab_hdr->sh_info)
1440130561Sobrien	{
1441130561Sobrien	  struct elf_s390_link_hash_entry *eh;
1442130561Sobrien	  struct elf_s390_dyn_relocs **pp;
1443130561Sobrien	  struct elf_s390_dyn_relocs *p;
144499461Sobrien
1445130561Sobrien	  h = sym_hashes[r_symndx - symtab_hdr->sh_info];
1446218822Sdim	  while (h->root.type == bfd_link_hash_indirect
1447218822Sdim		 || h->root.type == bfd_link_hash_warning)
1448218822Sdim	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
1449130561Sobrien	  eh = (struct elf_s390_link_hash_entry *) h;
145099461Sobrien
1451130561Sobrien	  for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next)
1452130561Sobrien	    if (p->sec == sec)
1453130561Sobrien	      {
1454130561Sobrien		/* Everything must go for SEC.  */
1455130561Sobrien		*pp = p->next;
1456130561Sobrien		break;
1457130561Sobrien	      }
1458130561Sobrien	}
145999461Sobrien
1460130561Sobrien      r_type = ELF32_R_TYPE (rel->r_info);
1461130561Sobrien      r_type = elf_s390_tls_transition (info, r_type, h != NULL);
1462130561Sobrien      switch (r_type)
1463130561Sobrien	{
1464130561Sobrien	case R_390_TLS_LDM32:
1465130561Sobrien	  if (elf_s390_hash_table (info)->tls_ldm_got.refcount > 0)
1466130561Sobrien	    elf_s390_hash_table (info)->tls_ldm_got.refcount -= 1;
1467130561Sobrien	  break;
146899461Sobrien
1469130561Sobrien	case R_390_TLS_GD32:
1470130561Sobrien	case R_390_TLS_IE32:
1471130561Sobrien	case R_390_TLS_GOTIE12:
1472130561Sobrien	case R_390_TLS_GOTIE20:
1473130561Sobrien	case R_390_TLS_GOTIE32:
1474130561Sobrien	case R_390_TLS_IEENT:
1475130561Sobrien	case R_390_GOT12:
1476130561Sobrien	case R_390_GOT16:
1477130561Sobrien	case R_390_GOT20:
1478130561Sobrien	case R_390_GOT32:
1479130561Sobrien	case R_390_GOTOFF16:
1480130561Sobrien	case R_390_GOTOFF32:
1481130561Sobrien	case R_390_GOTPC:
1482130561Sobrien	case R_390_GOTPCDBL:
1483130561Sobrien	case R_390_GOTENT:
1484130561Sobrien	  if (h != NULL)
1485130561Sobrien	    {
1486130561Sobrien	      if (h->got.refcount > 0)
1487130561Sobrien		h->got.refcount -= 1;
1488130561Sobrien	    }
1489130561Sobrien	  else if (local_got_refcounts != NULL)
1490130561Sobrien	    {
1491130561Sobrien	      if (local_got_refcounts[r_symndx] > 0)
1492130561Sobrien		local_got_refcounts[r_symndx] -= 1;
1493130561Sobrien	    }
1494130561Sobrien	  break;
1495130561Sobrien
1496130561Sobrien	case R_390_8:
1497130561Sobrien	case R_390_12:
1498130561Sobrien	case R_390_16:
1499130561Sobrien	case R_390_20:
1500130561Sobrien	case R_390_32:
1501130561Sobrien	case R_390_PC16:
1502130561Sobrien	case R_390_PC16DBL:
1503130561Sobrien	case R_390_PC32DBL:
1504130561Sobrien	case R_390_PC32:
1505130561Sobrien	  if (info->shared)
1506130561Sobrien	    break;
1507130561Sobrien	  /* Fall through.  */
1508130561Sobrien
1509130561Sobrien	case R_390_PLT16DBL:
1510130561Sobrien	case R_390_PLT32DBL:
1511130561Sobrien	case R_390_PLT32:
1512130561Sobrien	case R_390_PLTOFF16:
1513130561Sobrien	case R_390_PLTOFF32:
1514130561Sobrien	  if (h != NULL)
1515130561Sobrien	    {
1516130561Sobrien	      if (h->plt.refcount > 0)
1517130561Sobrien		h->plt.refcount -= 1;
1518130561Sobrien	    }
1519130561Sobrien	  break;
1520130561Sobrien
1521130561Sobrien	case R_390_GOTPLT12:
1522130561Sobrien	case R_390_GOTPLT16:
1523130561Sobrien	case R_390_GOTPLT20:
1524130561Sobrien	case R_390_GOTPLT32:
1525130561Sobrien	case R_390_GOTPLTENT:
1526130561Sobrien	  if (h != NULL)
1527130561Sobrien	    {
1528130561Sobrien	      if (h->plt.refcount > 0)
152999461Sobrien		{
1530130561Sobrien		  ((struct elf_s390_link_hash_entry *) h)->gotplt_refcount--;
1531130561Sobrien		  h->plt.refcount -= 1;
153299461Sobrien		}
1533130561Sobrien	    }
1534130561Sobrien	  else if (local_got_refcounts != NULL)
1535130561Sobrien	    {
1536130561Sobrien	      if (local_got_refcounts[r_symndx] > 0)
1537130561Sobrien		local_got_refcounts[r_symndx] -= 1;
1538130561Sobrien	    }
1539130561Sobrien	  break;
154099461Sobrien
1541130561Sobrien	default:
1542130561Sobrien	  break;
1543130561Sobrien	}
1544130561Sobrien    }
154599461Sobrien
1546130561Sobrien  return TRUE;
1547130561Sobrien}
154899461Sobrien
1549130561Sobrien/* Make sure we emit a GOT entry if the symbol was supposed to have a PLT
1550130561Sobrien   entry but we found we will not create any.  Called when we find we will
1551130561Sobrien   not have any PLT for this symbol, by for example
1552130561Sobrien   elf_s390_adjust_dynamic_symbol when we're doing a proper dynamic link,
1553130561Sobrien   or elf_s390_size_dynamic_sections if no dynamic sections will be
1554130561Sobrien   created (we're only linking static objects).  */
1555130561Sobrien
1556130561Sobrienstatic void
1557130561Sobrienelf_s390_adjust_gotplt (h)
1558130561Sobrien     struct elf_s390_link_hash_entry *h;
1559130561Sobrien{
1560130561Sobrien  if (h->elf.root.type == bfd_link_hash_warning)
1561130561Sobrien    h = (struct elf_s390_link_hash_entry *) h->elf.root.u.i.link;
1562130561Sobrien
1563130561Sobrien  if (h->gotplt_refcount <= 0)
1564130561Sobrien    return;
1565130561Sobrien
1566130561Sobrien  /* We simply add the number of gotplt references to the number
1567130561Sobrien   * of got references for this symbol.  */
1568130561Sobrien  h->elf.got.refcount += h->gotplt_refcount;
1569130561Sobrien  h->gotplt_refcount = -1;
157099461Sobrien}
157199461Sobrien
157299461Sobrien/* Adjust a symbol defined by a dynamic object and referenced by a
157399461Sobrien   regular object.  The current definition is in some section of the
157499461Sobrien   dynamic object, but we're not including those sections.  We have to
157599461Sobrien   change the definition to something the rest of the link can
157699461Sobrien   understand.  */
157799461Sobrien
1578130561Sobrienstatic bfd_boolean
157999461Sobrienelf_s390_adjust_dynamic_symbol (info, h)
158099461Sobrien     struct bfd_link_info *info;
158199461Sobrien     struct elf_link_hash_entry *h;
158299461Sobrien{
158399461Sobrien  struct elf_s390_link_hash_table *htab;
158499461Sobrien  asection *s;
158599461Sobrien
158699461Sobrien  /* If this is a function, put it in the procedure linkage table.  We
158799461Sobrien     will fill in the contents of the procedure linkage table later
1588107492Sobrien     (although we could actually do it here).  */
158999461Sobrien  if (h->type == STT_FUNC
1590218822Sdim      || h->needs_plt)
159199461Sobrien    {
159299461Sobrien      if (h->plt.refcount <= 0
159399461Sobrien	  || (! info->shared
1594218822Sdim	      && !h->def_dynamic
1595218822Sdim	      && !h->ref_dynamic
159699461Sobrien	      && h->root.type != bfd_link_hash_undefweak
159799461Sobrien	      && h->root.type != bfd_link_hash_undefined))
159899461Sobrien	{
159999461Sobrien	  /* This case can occur if we saw a PLT32 reloc in an input
1600130561Sobrien	     file, but the symbol was never referred to by a dynamic
1601130561Sobrien	     object, or if all references were garbage collected.  In
160299461Sobrien	     such a case, we don't actually need to build a procedure
160399461Sobrien	     linkage table, and we can just do a PC32 reloc instead.  */
160499461Sobrien	  h->plt.offset = (bfd_vma) -1;
1605218822Sdim	  h->needs_plt = 0;
1606130561Sobrien	  elf_s390_adjust_gotplt((struct elf_s390_link_hash_entry *) h);
160799461Sobrien	}
160899461Sobrien
1609130561Sobrien      return TRUE;
161099461Sobrien    }
161199461Sobrien  else
161299461Sobrien    /* It's possible that we incorrectly decided a .plt reloc was
161399461Sobrien       needed for an R_390_PC32 reloc to a non-function sym in
161499461Sobrien       check_relocs.  We can't decide accurately between function and
161599461Sobrien       non-function syms in check-relocs;  Objects loaded later in
161699461Sobrien       the link may change h->type.  So fix it now.  */
161799461Sobrien    h->plt.offset = (bfd_vma) -1;
161899461Sobrien
161999461Sobrien  /* If this is a weak symbol, and there is a real definition, the
162099461Sobrien     processor independent code will have arranged for us to see the
162199461Sobrien     real definition first, and we can just use the same value.  */
1622218822Sdim  if (h->u.weakdef != NULL)
162399461Sobrien    {
1624218822Sdim      BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined
1625218822Sdim		  || h->u.weakdef->root.type == bfd_link_hash_defweak);
1626218822Sdim      h->root.u.def.section = h->u.weakdef->root.u.def.section;
1627218822Sdim      h->root.u.def.value = h->u.weakdef->root.u.def.value;
1628130561Sobrien      if (ELIMINATE_COPY_RELOCS || info->nocopyreloc)
1629218822Sdim	h->non_got_ref = h->u.weakdef->non_got_ref;
1630130561Sobrien      return TRUE;
163199461Sobrien    }
163299461Sobrien
163399461Sobrien  /* This is a reference to a symbol defined by a dynamic object which
163499461Sobrien     is not a function.  */
163599461Sobrien
163699461Sobrien  /* If we are creating a shared library, we must presume that the
163799461Sobrien     only references to the symbol are via the global offset table.
163899461Sobrien     For such cases we need not do anything here; the relocations will
163999461Sobrien     be handled correctly by relocate_section.  */
164099461Sobrien  if (info->shared)
1641130561Sobrien    return TRUE;
164299461Sobrien
164399461Sobrien  /* If there are no references to this symbol that do not use the
164499461Sobrien     GOT, we don't need to generate a copy reloc.  */
1645218822Sdim  if (!h->non_got_ref)
1646130561Sobrien    return TRUE;
164799461Sobrien
164899461Sobrien  /* If -z nocopyreloc was given, we won't generate them either.  */
164999461Sobrien  if (info->nocopyreloc)
165099461Sobrien    {
1651218822Sdim      h->non_got_ref = 0;
1652130561Sobrien      return TRUE;
165399461Sobrien    }
165499461Sobrien
1655130561Sobrien  if (ELIMINATE_COPY_RELOCS)
165699461Sobrien    {
1657130561Sobrien      struct elf_s390_link_hash_entry * eh;
1658130561Sobrien      struct elf_s390_dyn_relocs *p;
165999461Sobrien
1660130561Sobrien      eh = (struct elf_s390_link_hash_entry *) h;
1661130561Sobrien      for (p = eh->dyn_relocs; p != NULL; p = p->next)
1662130561Sobrien	{
1663130561Sobrien	  s = p->sec->output_section;
1664130561Sobrien	  if (s != NULL && (s->flags & SEC_READONLY) != 0)
1665130561Sobrien	    break;
1666130561Sobrien	}
1667130561Sobrien
1668130561Sobrien      /* If we didn't find any dynamic relocs in read-only sections, then
1669130561Sobrien	 we'll be keeping the dynamic relocs and avoiding the copy reloc.  */
1670130561Sobrien      if (p == NULL)
1671130561Sobrien	{
1672218822Sdim	  h->non_got_ref = 0;
1673130561Sobrien	  return TRUE;
1674130561Sobrien	}
167599461Sobrien    }
167699461Sobrien
1677218822Sdim  if (h->size == 0)
1678218822Sdim    {
1679218822Sdim      (*_bfd_error_handler) (_("dynamic variable `%s' is zero size"),
1680218822Sdim			     h->root.root.string);
1681218822Sdim      return TRUE;
1682218822Sdim    }
1683218822Sdim
168499461Sobrien  /* We must allocate the symbol in our .dynbss section, which will
168599461Sobrien     become part of the .bss section of the executable.  There will be
168699461Sobrien     an entry for this symbol in the .dynsym section.  The dynamic
168799461Sobrien     object will contain position independent code, so all references
168899461Sobrien     from the dynamic object to this symbol will go through the global
168999461Sobrien     offset table.  The dynamic linker will use the .dynsym entry to
169099461Sobrien     determine the address it must put in the global offset table, so
169199461Sobrien     both the dynamic object and the regular object will refer to the
169299461Sobrien     same memory location for the variable.  */
169399461Sobrien
169499461Sobrien  htab = elf_s390_hash_table (info);
169599461Sobrien
169699461Sobrien  /* We must generate a R_390_COPY reloc to tell the dynamic linker to
169799461Sobrien     copy the initial value out of the dynamic object and into the
169899461Sobrien     runtime process image.  */
169999461Sobrien  if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
170099461Sobrien    {
1701218822Sdim      htab->srelbss->size += sizeof (Elf32_External_Rela);
1702218822Sdim      h->needs_copy = 1;
170399461Sobrien    }
170499461Sobrien
170599461Sobrien  s = htab->sdynbss;
170699461Sobrien
1707218822Sdim  return _bfd_elf_adjust_dynamic_copy (h, s);
170899461Sobrien}
170999461Sobrien
171099461Sobrien/* Allocate space in .plt, .got and associated reloc sections for
171199461Sobrien   dynamic relocs.  */
171299461Sobrien
1713130561Sobrienstatic bfd_boolean
171499461Sobrienallocate_dynrelocs (h, inf)
171599461Sobrien     struct elf_link_hash_entry *h;
171699461Sobrien     PTR inf;
171799461Sobrien{
171899461Sobrien  struct bfd_link_info *info;
171999461Sobrien  struct elf_s390_link_hash_table *htab;
172099461Sobrien  struct elf_s390_link_hash_entry *eh;
172199461Sobrien  struct elf_s390_dyn_relocs *p;
172299461Sobrien
172399461Sobrien  if (h->root.type == bfd_link_hash_indirect)
1724130561Sobrien    return TRUE;
172599461Sobrien
172699461Sobrien  if (h->root.type == bfd_link_hash_warning)
1727130561Sobrien    /* When warning symbols are created, they **replace** the "real"
1728130561Sobrien       entry in the hash table, thus we never get to see the real
1729130561Sobrien       symbol in a hash traversal.  So look at it now.  */
173099461Sobrien    h = (struct elf_link_hash_entry *) h->root.u.i.link;
173199461Sobrien
173299461Sobrien  info = (struct bfd_link_info *) inf;
173399461Sobrien  htab = elf_s390_hash_table (info);
173499461Sobrien
173599461Sobrien  if (htab->elf.dynamic_sections_created
1736130561Sobrien      && h->plt.refcount > 0
1737130561Sobrien      && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
1738130561Sobrien	  || h->root.type != bfd_link_hash_undefweak))
173999461Sobrien    {
174099461Sobrien      /* Make sure this symbol is output as a dynamic symbol.
174199461Sobrien	 Undefined weak syms won't yet be marked as dynamic.  */
174299461Sobrien      if (h->dynindx == -1
1743218822Sdim	  && !h->forced_local)
174499461Sobrien	{
1745130561Sobrien	  if (! bfd_elf_link_record_dynamic_symbol (info, h))
1746130561Sobrien	    return FALSE;
174799461Sobrien	}
174899461Sobrien
1749130561Sobrien      if (info->shared
1750130561Sobrien	  || WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, 0, h))
175199461Sobrien	{
175299461Sobrien	  asection *s = htab->splt;
175399461Sobrien
175499461Sobrien	  /* If this is the first .plt entry, make room for the special
175599461Sobrien	     first entry.  */
1756218822Sdim	  if (s->size == 0)
1757218822Sdim	    s->size += PLT_FIRST_ENTRY_SIZE;
175899461Sobrien
1759218822Sdim	  h->plt.offset = s->size;
176099461Sobrien
176199461Sobrien	  /* If this symbol is not defined in a regular file, and we are
176299461Sobrien	     not generating a shared library, then set the symbol to this
176399461Sobrien	     location in the .plt.  This is required to make function
176499461Sobrien	     pointers compare as equal between the normal executable and
176599461Sobrien	     the shared library.  */
176699461Sobrien	  if (! info->shared
1767218822Sdim	      && !h->def_regular)
176899461Sobrien	    {
176999461Sobrien	      h->root.u.def.section = s;
177099461Sobrien	      h->root.u.def.value = h->plt.offset;
177199461Sobrien	    }
177299461Sobrien
177399461Sobrien	  /* Make room for this entry.  */
1774218822Sdim	  s->size += PLT_ENTRY_SIZE;
177599461Sobrien
177699461Sobrien	  /* We also need to make an entry in the .got.plt section, which
177799461Sobrien	     will be placed in the .got section by the linker script.  */
1778218822Sdim	  htab->sgotplt->size += GOT_ENTRY_SIZE;
177999461Sobrien
178099461Sobrien	  /* We also need to make an entry in the .rela.plt section.  */
1781218822Sdim	  htab->srelplt->size += sizeof (Elf32_External_Rela);
178299461Sobrien	}
178399461Sobrien      else
178499461Sobrien	{
178599461Sobrien 	  h->plt.offset = (bfd_vma) -1;
1786218822Sdim	  h->needs_plt = 0;
1787130561Sobrien	  elf_s390_adjust_gotplt((struct elf_s390_link_hash_entry *) h);
178899461Sobrien	}
178999461Sobrien    }
179099461Sobrien  else
179199461Sobrien    {
179299461Sobrien      h->plt.offset = (bfd_vma) -1;
1793218822Sdim      h->needs_plt = 0;
1794130561Sobrien      elf_s390_adjust_gotplt((struct elf_s390_link_hash_entry *) h);
179599461Sobrien    }
179699461Sobrien
1797130561Sobrien  /* If R_390_TLS_{IE32,GOTIE32,GOTIE12,IEENT} symbol is now local to
1798130561Sobrien     the binary, we can optimize a bit. IE32 and GOTIE32 get converted
1799130561Sobrien     to R_390_TLS_LE32 requiring no TLS entry. For GOTIE12 and IEENT
1800130561Sobrien     we can save the dynamic TLS relocation.  */
1801130561Sobrien  if (h->got.refcount > 0
1802130561Sobrien      && !info->shared
1803130561Sobrien      && h->dynindx == -1
1804130561Sobrien      && elf_s390_hash_entry(h)->tls_type >= GOT_TLS_IE)
180599461Sobrien    {
1806130561Sobrien      if (elf_s390_hash_entry(h)->tls_type == GOT_TLS_IE_NLT)
1807130561Sobrien	/* For the GOTIE access without a literal pool entry the offset has
1808130561Sobrien	   to be stored somewhere. The immediate value in the instruction
1809130561Sobrien	   is not bit enough so the value is stored in the got.  */
1810130561Sobrien	{
1811218822Sdim	  h->got.offset = htab->sgot->size;
1812218822Sdim	  htab->sgot->size += GOT_ENTRY_SIZE;
1813130561Sobrien	}
1814130561Sobrien      else
1815130561Sobrien	h->got.offset = (bfd_vma) -1;
1816130561Sobrien    }
1817130561Sobrien  else if (h->got.refcount > 0)
1818130561Sobrien   {
181999461Sobrien      asection *s;
1820130561Sobrien      bfd_boolean dyn;
1821130561Sobrien      int tls_type = elf_s390_hash_entry(h)->tls_type;
182299461Sobrien
182399461Sobrien      /* Make sure this symbol is output as a dynamic symbol.
182499461Sobrien	 Undefined weak syms won't yet be marked as dynamic.  */
182599461Sobrien      if (h->dynindx == -1
1826218822Sdim	  && !h->forced_local)
182799461Sobrien	{
1828130561Sobrien	  if (! bfd_elf_link_record_dynamic_symbol (info, h))
1829130561Sobrien	    return FALSE;
183099461Sobrien	}
183199461Sobrien
183299461Sobrien      s = htab->sgot;
1833218822Sdim      h->got.offset = s->size;
1834218822Sdim      s->size += GOT_ENTRY_SIZE;
1835130561Sobrien      /* R_390_TLS_GD32 needs 2 consecutive GOT slots.  */
1836130561Sobrien      if (tls_type == GOT_TLS_GD)
1837218822Sdim	s->size += GOT_ENTRY_SIZE;
183899461Sobrien      dyn = htab->elf.dynamic_sections_created;
1839130561Sobrien      /* R_390_TLS_IE32 needs one dynamic relocation,
1840130561Sobrien	 R_390_TLS_GD32 needs one if local symbol and two if global.  */
1841130561Sobrien      if ((tls_type == GOT_TLS_GD && h->dynindx == -1)
1842130561Sobrien	  || tls_type >= GOT_TLS_IE)
1843218822Sdim	htab->srelgot->size += sizeof (Elf32_External_Rela);
1844130561Sobrien      else if (tls_type == GOT_TLS_GD)
1845218822Sdim	htab->srelgot->size += 2 * sizeof (Elf32_External_Rela);
1846130561Sobrien      else if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
1847130561Sobrien		|| h->root.type != bfd_link_hash_undefweak)
1848130561Sobrien	       && (info->shared
1849130561Sobrien		   || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h)))
1850218822Sdim	htab->srelgot->size += sizeof (Elf32_External_Rela);
185199461Sobrien    }
185299461Sobrien  else
185399461Sobrien    h->got.offset = (bfd_vma) -1;
185499461Sobrien
185599461Sobrien  eh = (struct elf_s390_link_hash_entry *) h;
185699461Sobrien  if (eh->dyn_relocs == NULL)
1857130561Sobrien    return TRUE;
185899461Sobrien
185999461Sobrien  /* In the shared -Bsymbolic case, discard space allocated for
186099461Sobrien     dynamic pc-relative relocs against symbols which turn out to be
186199461Sobrien     defined in regular objects.  For the normal shared case, discard
186299461Sobrien     space for pc-relative relocs that have become local due to symbol
186399461Sobrien     visibility changes.  */
186499461Sobrien
186599461Sobrien  if (info->shared)
186699461Sobrien    {
1867130561Sobrien      if (SYMBOL_REFERENCES_LOCAL (info, h))
186899461Sobrien	{
186999461Sobrien	  struct elf_s390_dyn_relocs **pp;
187099461Sobrien
187199461Sobrien	  for (pp = &eh->dyn_relocs; (p = *pp) != NULL; )
187299461Sobrien	    {
187399461Sobrien	      p->count -= p->pc_count;
187499461Sobrien	      p->pc_count = 0;
187599461Sobrien	      if (p->count == 0)
187699461Sobrien		*pp = p->next;
187799461Sobrien	      else
187899461Sobrien		pp = &p->next;
187999461Sobrien	    }
188099461Sobrien	}
1881130561Sobrien
1882130561Sobrien      /* Also discard relocs on undefined weak syms with non-default
1883130561Sobrien	 visibility.  */
1884218822Sdim      if (eh->dyn_relocs != NULL
1885130561Sobrien	  && h->root.type == bfd_link_hash_undefweak)
1886218822Sdim	{
1887218822Sdim	  if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
1888218822Sdim	    eh->dyn_relocs = NULL;
1889218822Sdim
1890218822Sdim	  /* Make sure undefined weak symbols are output as a dynamic
1891218822Sdim	     symbol in PIEs.  */
1892218822Sdim	  else if (h->dynindx == -1
1893218822Sdim		   && !h->forced_local)
1894218822Sdim	    {
1895218822Sdim	      if (! bfd_elf_link_record_dynamic_symbol (info, h))
1896218822Sdim		return FALSE;
1897218822Sdim	    }
1898218822Sdim	}
189999461Sobrien    }
1900130561Sobrien  else if (ELIMINATE_COPY_RELOCS)
190199461Sobrien    {
190299461Sobrien      /* For the non-shared case, discard space for relocs against
190399461Sobrien	 symbols which turn out to need copy relocs or are not
190499461Sobrien	 dynamic.  */
190599461Sobrien
1906218822Sdim      if (!h->non_got_ref
1907218822Sdim	  && ((h->def_dynamic
1908218822Sdim	       && !h->def_regular)
190999461Sobrien	      || (htab->elf.dynamic_sections_created
191099461Sobrien		  && (h->root.type == bfd_link_hash_undefweak
191199461Sobrien		      || h->root.type == bfd_link_hash_undefined))))
191299461Sobrien	{
191399461Sobrien	  /* Make sure this symbol is output as a dynamic symbol.
191499461Sobrien	     Undefined weak syms won't yet be marked as dynamic.  */
191599461Sobrien	  if (h->dynindx == -1
1916218822Sdim	      && !h->forced_local)
191799461Sobrien	    {
1918130561Sobrien	      if (! bfd_elf_link_record_dynamic_symbol (info, h))
1919130561Sobrien		return FALSE;
192099461Sobrien	    }
192199461Sobrien
192299461Sobrien	  /* If that succeeded, we know we'll be keeping all the
192399461Sobrien	     relocs.  */
192499461Sobrien	  if (h->dynindx != -1)
192599461Sobrien	    goto keep;
192699461Sobrien	}
192799461Sobrien
192899461Sobrien      eh->dyn_relocs = NULL;
192999461Sobrien
193099461Sobrien    keep: ;
193199461Sobrien    }
193299461Sobrien
193399461Sobrien  /* Finally, allocate space.  */
193499461Sobrien  for (p = eh->dyn_relocs; p != NULL; p = p->next)
193599461Sobrien    {
193699461Sobrien      asection *sreloc = elf_section_data (p->sec)->sreloc;
1937130561Sobrien
1938218822Sdim      sreloc->size += p->count * sizeof (Elf32_External_Rela);
193999461Sobrien    }
194099461Sobrien
1941130561Sobrien  return TRUE;
194299461Sobrien}
194399461Sobrien
194499461Sobrien/* Find any dynamic relocs that apply to read-only sections.  */
194599461Sobrien
1946130561Sobrienstatic bfd_boolean
194799461Sobrienreadonly_dynrelocs (h, inf)
194899461Sobrien     struct elf_link_hash_entry *h;
194999461Sobrien     PTR inf;
195099461Sobrien{
195199461Sobrien  struct elf_s390_link_hash_entry *eh;
195299461Sobrien  struct elf_s390_dyn_relocs *p;
195399461Sobrien
195499461Sobrien  if (h->root.type == bfd_link_hash_warning)
195599461Sobrien    h = (struct elf_link_hash_entry *) h->root.u.i.link;
195699461Sobrien
195799461Sobrien  eh = (struct elf_s390_link_hash_entry *) h;
195899461Sobrien  for (p = eh->dyn_relocs; p != NULL; p = p->next)
195999461Sobrien    {
196099461Sobrien      asection *s = p->sec->output_section;
196199461Sobrien
196299461Sobrien      if (s != NULL && (s->flags & SEC_READONLY) != 0)
196399461Sobrien	{
196499461Sobrien	  struct bfd_link_info *info = (struct bfd_link_info *) inf;
196599461Sobrien
196699461Sobrien	  info->flags |= DF_TEXTREL;
196799461Sobrien
196899461Sobrien	  /* Not an error, just cut short the traversal.  */
1969130561Sobrien	  return FALSE;
197099461Sobrien	}
197199461Sobrien    }
1972130561Sobrien  return TRUE;
197399461Sobrien}
197499461Sobrien
197599461Sobrien/* Set the sizes of the dynamic sections.  */
197699461Sobrien
1977130561Sobrienstatic bfd_boolean
197899461Sobrienelf_s390_size_dynamic_sections (output_bfd, info)
197999461Sobrien     bfd *output_bfd ATTRIBUTE_UNUSED;
198099461Sobrien     struct bfd_link_info *info;
198199461Sobrien{
198299461Sobrien  struct elf_s390_link_hash_table *htab;
198399461Sobrien  bfd *dynobj;
198499461Sobrien  asection *s;
1985130561Sobrien  bfd_boolean relocs;
198699461Sobrien  bfd *ibfd;
198799461Sobrien
198899461Sobrien  htab = elf_s390_hash_table (info);
198999461Sobrien  dynobj = htab->elf.dynobj;
199099461Sobrien  if (dynobj == NULL)
199199461Sobrien    abort ();
199299461Sobrien
199399461Sobrien  if (htab->elf.dynamic_sections_created)
199499461Sobrien    {
199599461Sobrien      /* Set the contents of the .interp section to the interpreter.  */
1996130561Sobrien      if (info->executable)
199799461Sobrien	{
199899461Sobrien	  s = bfd_get_section_by_name (dynobj, ".interp");
199999461Sobrien	  if (s == NULL)
200099461Sobrien	    abort ();
2001218822Sdim	  s->size = sizeof ELF_DYNAMIC_INTERPRETER;
200299461Sobrien	  s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
200399461Sobrien	}
200499461Sobrien    }
200599461Sobrien
200699461Sobrien  /* Set up .got offsets for local syms, and space for local dynamic
200799461Sobrien     relocs.  */
200899461Sobrien  for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
200999461Sobrien    {
201099461Sobrien      bfd_signed_vma *local_got;
201199461Sobrien      bfd_signed_vma *end_local_got;
2012130561Sobrien      char *local_tls_type;
201399461Sobrien      bfd_size_type locsymcount;
201499461Sobrien      Elf_Internal_Shdr *symtab_hdr;
201599461Sobrien      asection *srela;
201699461Sobrien
201799461Sobrien      if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
201899461Sobrien	continue;
201999461Sobrien
202099461Sobrien      for (s = ibfd->sections; s != NULL; s = s->next)
202199461Sobrien	{
202299461Sobrien	  struct elf_s390_dyn_relocs *p;
202399461Sobrien
2024218822Sdim	  for (p = elf_section_data (s)->local_dynrel; p != NULL; p = p->next)
202599461Sobrien	    {
202699461Sobrien	      if (!bfd_is_abs_section (p->sec)
202799461Sobrien		  && bfd_is_abs_section (p->sec->output_section))
202899461Sobrien		{
202999461Sobrien		  /* Input section has been discarded, either because
203099461Sobrien		     it is a copy of a linkonce section or due to
203199461Sobrien		     linker script /DISCARD/, so we'll be discarding
203299461Sobrien		     the relocs too.  */
203399461Sobrien		}
203499461Sobrien	      else if (p->count != 0)
203599461Sobrien		{
203699461Sobrien		  srela = elf_section_data (p->sec)->sreloc;
2037218822Sdim		  srela->size += p->count * sizeof (Elf32_External_Rela);
203899461Sobrien		  if ((p->sec->output_section->flags & SEC_READONLY) != 0)
203999461Sobrien		    info->flags |= DF_TEXTREL;
204099461Sobrien		}
204199461Sobrien	    }
204299461Sobrien	}
204399461Sobrien
204499461Sobrien      local_got = elf_local_got_refcounts (ibfd);
204599461Sobrien      if (!local_got)
204699461Sobrien	continue;
204799461Sobrien
204899461Sobrien      symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
204999461Sobrien      locsymcount = symtab_hdr->sh_info;
205099461Sobrien      end_local_got = local_got + locsymcount;
2051130561Sobrien      local_tls_type = elf_s390_local_got_tls_type (ibfd);
205299461Sobrien      s = htab->sgot;
205399461Sobrien      srela = htab->srelgot;
2054130561Sobrien      for (; local_got < end_local_got; ++local_got, ++local_tls_type)
205599461Sobrien	{
205699461Sobrien	  if (*local_got > 0)
205799461Sobrien	    {
2058218822Sdim	      *local_got = s->size;
2059218822Sdim	      s->size += GOT_ENTRY_SIZE;
2060130561Sobrien	      if (*local_tls_type == GOT_TLS_GD)
2061218822Sdim		s->size += GOT_ENTRY_SIZE;
206299461Sobrien	      if (info->shared)
2063218822Sdim		srela->size += sizeof (Elf32_External_Rela);
206499461Sobrien	    }
206599461Sobrien	  else
206699461Sobrien	    *local_got = (bfd_vma) -1;
206799461Sobrien	}
206899461Sobrien    }
206999461Sobrien
2070130561Sobrien  if (htab->tls_ldm_got.refcount > 0)
2071130561Sobrien    {
2072130561Sobrien      /* Allocate 2 got entries and 1 dynamic reloc for R_390_TLS_LDM32
2073130561Sobrien	 relocs.  */
2074218822Sdim      htab->tls_ldm_got.offset = htab->sgot->size;
2075218822Sdim      htab->sgot->size += 2 * GOT_ENTRY_SIZE;
2076218822Sdim      htab->srelgot->size += sizeof (Elf32_External_Rela);
2077130561Sobrien    }
2078130561Sobrien  else
2079130561Sobrien    htab->tls_ldm_got.offset = -1;
2080130561Sobrien
208199461Sobrien  /* Allocate global sym .plt and .got entries, and space for global
208299461Sobrien     sym dynamic relocs.  */
208399461Sobrien  elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, (PTR) info);
208499461Sobrien
208599461Sobrien  /* We now have determined the sizes of the various dynamic sections.
208699461Sobrien     Allocate memory for them.  */
2087130561Sobrien  relocs = FALSE;
208899461Sobrien  for (s = dynobj->sections; s != NULL; s = s->next)
208999461Sobrien    {
209099461Sobrien      if ((s->flags & SEC_LINKER_CREATED) == 0)
209199461Sobrien	continue;
209299461Sobrien
209399461Sobrien      if (s == htab->splt
209499461Sobrien	  || s == htab->sgot
2095218822Sdim	  || s == htab->sgotplt
2096218822Sdim	  || s == htab->sdynbss)
209799461Sobrien	{
209899461Sobrien	  /* Strip this section if we don't need it; see the
209999461Sobrien	     comment below.  */
210099461Sobrien	}
2101218822Sdim      else if (CONST_STRNEQ (bfd_get_section_name (dynobj, s), ".rela"))
210299461Sobrien	{
2103218822Sdim	  if (s->size != 0)
2104130561Sobrien	    relocs = TRUE;
210599461Sobrien
210699461Sobrien	  /* We use the reloc_count field as a counter if we need
210799461Sobrien	     to copy relocs into the output file.  */
210899461Sobrien	  s->reloc_count = 0;
210999461Sobrien	}
211099461Sobrien      else
211199461Sobrien	{
211299461Sobrien	  /* It's not one of our sections, so don't allocate space.  */
211399461Sobrien	  continue;
211499461Sobrien	}
211599461Sobrien
2116218822Sdim      if (s->size == 0)
211799461Sobrien	{
211899461Sobrien	  /* If we don't need this section, strip it from the
211999461Sobrien	     output file.  This is to handle .rela.bss and
212099461Sobrien	     .rela.plt.  We must create it in
212199461Sobrien	     create_dynamic_sections, because it must be created
212299461Sobrien	     before the linker maps input sections to output
212399461Sobrien	     sections.  The linker does that before
212499461Sobrien	     adjust_dynamic_symbol is called, and it is that
212599461Sobrien	     function which decides whether anything needs to go
212699461Sobrien	     into these sections.  */
212799461Sobrien
2128218822Sdim	  s->flags |= SEC_EXCLUDE;
212999461Sobrien	  continue;
213099461Sobrien	}
213199461Sobrien
2132218822Sdim      if ((s->flags & SEC_HAS_CONTENTS) == 0)
2133218822Sdim	continue;
2134218822Sdim
213599461Sobrien      /* Allocate memory for the section contents.  We use bfd_zalloc
213699461Sobrien	 here in case unused entries are not reclaimed before the
213799461Sobrien	 section's contents are written out.  This should not happen,
213899461Sobrien	 but this way if it does, we get a R_390_NONE reloc instead
213999461Sobrien	 of garbage.  */
2140218822Sdim      s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size);
214199461Sobrien      if (s->contents == NULL)
2142130561Sobrien	return FALSE;
214399461Sobrien    }
214499461Sobrien
214599461Sobrien  if (htab->elf.dynamic_sections_created)
214699461Sobrien    {
214799461Sobrien      /* Add some entries to the .dynamic section.  We fill in the
214899461Sobrien	 values later, in elf_s390_finish_dynamic_sections, but we
214999461Sobrien	 must add the entries now so that we get the correct size for
215099461Sobrien	 the .dynamic section.  The DT_DEBUG entry is filled in by the
215199461Sobrien	 dynamic linker and used by the debugger.  */
215299461Sobrien#define add_dynamic_entry(TAG, VAL) \
2153130561Sobrien  _bfd_elf_add_dynamic_entry (info, TAG, VAL)
215499461Sobrien
2155130561Sobrien      if (info->executable)
215699461Sobrien	{
215799461Sobrien	  if (!add_dynamic_entry (DT_DEBUG, 0))
2158130561Sobrien	    return FALSE;
215999461Sobrien	}
216099461Sobrien
2161218822Sdim      if (htab->splt->size != 0)
216299461Sobrien	{
216399461Sobrien	  if (!add_dynamic_entry (DT_PLTGOT, 0)
216499461Sobrien	      || !add_dynamic_entry (DT_PLTRELSZ, 0)
216599461Sobrien	      || !add_dynamic_entry (DT_PLTREL, DT_RELA)
216699461Sobrien	      || !add_dynamic_entry (DT_JMPREL, 0))
2167130561Sobrien	    return FALSE;
216899461Sobrien	}
216999461Sobrien
217099461Sobrien      if (relocs)
2171130561Sobrien	{
2172130561Sobrien	  if (!add_dynamic_entry (DT_RELA, 0)
2173130561Sobrien	      || !add_dynamic_entry (DT_RELASZ, 0)
2174130561Sobrien	      || !add_dynamic_entry (DT_RELAENT, sizeof (Elf32_External_Rela)))
2175130561Sobrien	    return FALSE;
217699461Sobrien
217799461Sobrien	  /* If any dynamic relocs apply to a read-only section,
217899461Sobrien	     then we need a DT_TEXTREL entry.  */
217999461Sobrien	  if ((info->flags & DF_TEXTREL) == 0)
218099461Sobrien	    elf_link_hash_traverse (&htab->elf, readonly_dynrelocs,
218199461Sobrien				    (PTR) info);
218299461Sobrien
218399461Sobrien	  if ((info->flags & DF_TEXTREL) != 0)
218499461Sobrien	    {
218599461Sobrien	      if (!add_dynamic_entry (DT_TEXTREL, 0))
2186130561Sobrien		return FALSE;
218799461Sobrien	    }
218899461Sobrien	}
218999461Sobrien    }
219099461Sobrien#undef add_dynamic_entry
219199461Sobrien
2192130561Sobrien  return TRUE;
219399461Sobrien}
219499461Sobrien
2195130561Sobrien/* Return the base VMA address which should be subtracted from real addresses
2196130561Sobrien   when resolving @dtpoff relocation.
2197130561Sobrien   This is PT_TLS segment p_vaddr.  */
2198130561Sobrien
2199130561Sobrienstatic bfd_vma
2200130561Sobriendtpoff_base (info)
2201130561Sobrien     struct bfd_link_info *info;
2202130561Sobrien{
2203130561Sobrien  /* If tls_sec is NULL, we should have signalled an error already.  */
2204130561Sobrien  if (elf_hash_table (info)->tls_sec == NULL)
2205130561Sobrien    return 0;
2206130561Sobrien  return elf_hash_table (info)->tls_sec->vma;
2207130561Sobrien}
2208130561Sobrien
2209130561Sobrien/* Return the relocation value for @tpoff relocation
2210130561Sobrien   if STT_TLS virtual address is ADDRESS.  */
2211130561Sobrien
2212130561Sobrienstatic bfd_vma
2213130561Sobrientpoff (info, address)
2214130561Sobrien     struct bfd_link_info *info;
2215130561Sobrien     bfd_vma address;
2216130561Sobrien{
2217130561Sobrien  struct elf_link_hash_table *htab = elf_hash_table (info);
2218130561Sobrien
2219130561Sobrien  /* If tls_sec is NULL, we should have signalled an error already.  */
2220130561Sobrien  if (htab->tls_sec == NULL)
2221130561Sobrien    return 0;
2222130561Sobrien  return htab->tls_size + htab->tls_sec->vma - address;
2223130561Sobrien}
2224130561Sobrien
2225130561Sobrien/* Complain if TLS instruction relocation is against an invalid
2226130561Sobrien   instruction.  */
2227130561Sobrien
2228130561Sobrienstatic void
2229130561Sobrieninvalid_tls_insn (input_bfd, input_section, rel)
2230130561Sobrien     bfd *input_bfd;
2231130561Sobrien     asection *input_section;
2232130561Sobrien     Elf_Internal_Rela *rel;
2233130561Sobrien{
2234130561Sobrien  reloc_howto_type *howto;
2235130561Sobrien
2236130561Sobrien  howto = elf_howto_table + ELF32_R_TYPE (rel->r_info);
2237130561Sobrien  (*_bfd_error_handler)
2238218822Sdim    (_("%B(%A+0x%lx): invalid instruction for TLS relocation %s"),
2239218822Sdim     input_bfd,
2240218822Sdim     input_section,
2241130561Sobrien     (long) rel->r_offset,
2242130561Sobrien     howto->name);
2243218822Sdim  bfd_set_error (bfd_error_bad_value);
2244130561Sobrien}
2245130561Sobrien
224699461Sobrien/* Relocate a 390 ELF section.  */
224799461Sobrien
2248130561Sobrienstatic bfd_boolean
224999461Sobrienelf_s390_relocate_section (output_bfd, info, input_bfd, input_section,
225099461Sobrien			      contents, relocs, local_syms, local_sections)
225199461Sobrien     bfd *output_bfd;
225299461Sobrien     struct bfd_link_info *info;
225399461Sobrien     bfd *input_bfd;
225499461Sobrien     asection *input_section;
225599461Sobrien     bfd_byte *contents;
225699461Sobrien     Elf_Internal_Rela *relocs;
225799461Sobrien     Elf_Internal_Sym *local_syms;
225899461Sobrien     asection **local_sections;
225999461Sobrien{
226099461Sobrien  struct elf_s390_link_hash_table *htab;
226199461Sobrien  Elf_Internal_Shdr *symtab_hdr;
226299461Sobrien  struct elf_link_hash_entry **sym_hashes;
226399461Sobrien  bfd_vma *local_got_offsets;
226499461Sobrien  Elf_Internal_Rela *rel;
226599461Sobrien  Elf_Internal_Rela *relend;
226699461Sobrien
226799461Sobrien  htab = elf_s390_hash_table (info);
226899461Sobrien  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
226999461Sobrien  sym_hashes = elf_sym_hashes (input_bfd);
227099461Sobrien  local_got_offsets = elf_local_got_offsets (input_bfd);
227199461Sobrien
227299461Sobrien  rel = relocs;
227399461Sobrien  relend = relocs + input_section->reloc_count;
227499461Sobrien  for (; rel < relend; rel++)
227599461Sobrien    {
2276130561Sobrien      unsigned int r_type;
227799461Sobrien      reloc_howto_type *howto;
227899461Sobrien      unsigned long r_symndx;
227999461Sobrien      struct elf_link_hash_entry *h;
228099461Sobrien      Elf_Internal_Sym *sym;
228199461Sobrien      asection *sec;
228299461Sobrien      bfd_vma off;
228399461Sobrien      bfd_vma relocation;
2284130561Sobrien      bfd_boolean unresolved_reloc;
228599461Sobrien      bfd_reloc_status_type r;
2286130561Sobrien      int tls_type;
228799461Sobrien
228899461Sobrien      r_type = ELF32_R_TYPE (rel->r_info);
228999461Sobrien      if (r_type == (int) R_390_GNU_VTINHERIT
2290130561Sobrien	  || r_type == (int) R_390_GNU_VTENTRY)
2291130561Sobrien	continue;
2292130561Sobrien      if (r_type >= (int) R_390_max)
229399461Sobrien	{
229499461Sobrien	  bfd_set_error (bfd_error_bad_value);
2295130561Sobrien	  return FALSE;
229699461Sobrien	}
229799461Sobrien
229899461Sobrien      howto = elf_howto_table + r_type;
229999461Sobrien      r_symndx = ELF32_R_SYM (rel->r_info);
2300130561Sobrien
230199461Sobrien      h = NULL;
230299461Sobrien      sym = NULL;
230399461Sobrien      sec = NULL;
2304130561Sobrien      unresolved_reloc = FALSE;
230599461Sobrien      if (r_symndx < symtab_hdr->sh_info)
230699461Sobrien	{
230799461Sobrien	  sym = local_syms + r_symndx;
230899461Sobrien	  sec = local_sections[r_symndx];
2309130561Sobrien	  relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
231099461Sobrien	}
231199461Sobrien      else
231299461Sobrien	{
2313130561Sobrien	  bfd_boolean warned ATTRIBUTE_UNUSED;
231499461Sobrien
2315130561Sobrien	  RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
2316130561Sobrien				   r_symndx, symtab_hdr, sym_hashes,
2317130561Sobrien				   h, sec, relocation,
2318130561Sobrien				   unresolved_reloc, warned);
231999461Sobrien	}
232099461Sobrien
2321218822Sdim      if (sec != NULL && elf_discarded_section (sec))
2322218822Sdim	{
2323218822Sdim	  /* For relocs against symbols from removed linkonce sections,
2324218822Sdim	     or sections discarded by a linker script, we just want the
2325218822Sdim	     section contents zeroed.  Avoid any special processing.  */
2326218822Sdim	  _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
2327218822Sdim	  rel->r_info = 0;
2328218822Sdim	  rel->r_addend = 0;
2329218822Sdim	  continue;
2330218822Sdim	}
2331218822Sdim
2332218822Sdim      if (info->relocatable)
2333218822Sdim	continue;
2334218822Sdim
233599461Sobrien      switch (r_type)
233699461Sobrien	{
2337130561Sobrien	case R_390_GOTPLT12:
2338130561Sobrien	case R_390_GOTPLT16:
2339130561Sobrien	case R_390_GOTPLT20:
2340130561Sobrien	case R_390_GOTPLT32:
2341130561Sobrien	case R_390_GOTPLTENT:
2342130561Sobrien	  /* There are three cases for a GOTPLT relocation. 1) The
2343130561Sobrien	     relocation is against the jump slot entry of a plt that
2344130561Sobrien	     will get emitted to the output file. 2) The relocation
2345130561Sobrien	     is against the jump slot of a plt entry that has been
2346130561Sobrien	     removed. elf_s390_adjust_gotplt has created a GOT entry
2347130561Sobrien	     as replacement. 3) The relocation is against a local symbol.
2348130561Sobrien	     Cases 2) and 3) are the same as the GOT relocation code
2349130561Sobrien	     so we just have to test for case 1 and fall through for
2350130561Sobrien	     the other two.  */
2351130561Sobrien	  if (h != NULL && h->plt.offset != (bfd_vma) -1)
2352130561Sobrien	    {
2353130561Sobrien	      bfd_vma plt_index;
2354130561Sobrien
2355130561Sobrien	      /* Calc. index no.
2356130561Sobrien		 Current offset - size first entry / entry size.  */
2357130561Sobrien	      plt_index = (h->plt.offset - PLT_FIRST_ENTRY_SIZE) /
2358130561Sobrien		PLT_ENTRY_SIZE;
2359130561Sobrien
2360130561Sobrien	      /* Offset in GOT is PLT index plus GOT headers(3) times 4,
2361130561Sobrien		 addr & GOT addr.  */
2362130561Sobrien	      relocation = (plt_index + 3) * GOT_ENTRY_SIZE;
2363130561Sobrien	      unresolved_reloc = FALSE;
2364130561Sobrien
2365130561Sobrien	      if (r_type == R_390_GOTPLTENT)
2366130561Sobrien		relocation += htab->sgot->output_section->vma;
2367130561Sobrien	      break;
2368130561Sobrien	    }
2369130561Sobrien	  /* Fall through.  */
2370130561Sobrien
2371130561Sobrien	case R_390_GOT12:
2372130561Sobrien	case R_390_GOT16:
2373130561Sobrien	case R_390_GOT20:
2374130561Sobrien	case R_390_GOT32:
237599461Sobrien	case R_390_GOTENT:
2376130561Sobrien	  /* Relocation is to the entry for this symbol in the global
2377130561Sobrien	     offset table.  */
237899461Sobrien	  if (htab->sgot == NULL)
237999461Sobrien	    abort ();
238099461Sobrien
2381130561Sobrien	  if (h != NULL)
2382130561Sobrien	    {
2383130561Sobrien	      bfd_boolean dyn;
238499461Sobrien
2385130561Sobrien	      off = h->got.offset;
238699461Sobrien	      dyn = htab->elf.dynamic_sections_created;
2387130561Sobrien	      if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h)
2388130561Sobrien		  || (info->shared
2389130561Sobrien		      && (info->symbolic
239099461Sobrien			  || h->dynindx == -1
2391218822Sdim			  || h->forced_local)
2392218822Sdim		      && h->def_regular)
2393130561Sobrien		  || (ELF_ST_VISIBILITY (h->other)
2394130561Sobrien		      && h->root.type == bfd_link_hash_undefweak))
2395130561Sobrien		{
2396130561Sobrien		  /* This is actually a static link, or it is a
2397130561Sobrien		     -Bsymbolic link and the symbol is defined
2398130561Sobrien		     locally, or the symbol was forced to be local
2399130561Sobrien		     because of a version file.  We must initialize
2400130561Sobrien		     this entry in the global offset table.  Since the
2401130561Sobrien		     offset must always be a multiple of 2, we use the
2402130561Sobrien		     least significant bit to record whether we have
2403130561Sobrien		     initialized it already.
240499461Sobrien
2405130561Sobrien		     When doing a dynamic link, we create a .rel.got
2406130561Sobrien		     relocation entry to initialize the value.  This
2407130561Sobrien		     is done in the finish_dynamic_symbol routine.  */
2408130561Sobrien		  if ((off & 1) != 0)
2409130561Sobrien		    off &= ~1;
2410130561Sobrien		  else
2411130561Sobrien		    {
241299461Sobrien		      bfd_put_32 (output_bfd, relocation,
241399461Sobrien				  htab->sgot->contents + off);
2414130561Sobrien		      h->got.offset |= 1;
2415130561Sobrien		    }
2416130561Sobrien		}
241799461Sobrien	      else
2418130561Sobrien		unresolved_reloc = FALSE;
2419130561Sobrien	    }
2420130561Sobrien	  else
2421130561Sobrien	    {
242299461Sobrien	      if (local_got_offsets == NULL)
242399461Sobrien		abort ();
242499461Sobrien
2425130561Sobrien	      off = local_got_offsets[r_symndx];
242699461Sobrien
2427130561Sobrien	      /* The offset must always be a multiple of 4.  We use
2428130561Sobrien		 the least significant bit to record whether we have
2429130561Sobrien		 already generated the necessary reloc.  */
2430130561Sobrien	      if ((off & 1) != 0)
2431130561Sobrien		off &= ~1;
2432130561Sobrien	      else
2433130561Sobrien		{
2434130561Sobrien		  bfd_put_32 (output_bfd, relocation,
243599461Sobrien			      htab->sgot->contents + off);
243699461Sobrien
2437130561Sobrien		  if (info->shared)
2438130561Sobrien		    {
2439130561Sobrien		      asection *srelgot;
2440130561Sobrien		      Elf_Internal_Rela outrel;
2441130561Sobrien		      bfd_byte *loc;
244299461Sobrien
2443130561Sobrien		      srelgot = htab->srelgot;
244499461Sobrien		      if (srelgot == NULL)
244599461Sobrien			abort ();
244699461Sobrien
2447130561Sobrien		      outrel.r_offset = (htab->sgot->output_section->vma
2448130561Sobrien					 + htab->sgot->output_offset
2449130561Sobrien					 + off);
2450130561Sobrien		      outrel.r_info = ELF32_R_INFO (0, R_390_RELATIVE);
245199461Sobrien		      outrel.r_addend = relocation;
2452130561Sobrien		      loc = srelgot->contents;
2453130561Sobrien		      loc += srelgot->reloc_count++ * sizeof (Elf32_External_Rela);
2454130561Sobrien		      bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
2455130561Sobrien		    }
245699461Sobrien
2457130561Sobrien		  local_got_offsets[r_symndx] |= 1;
2458130561Sobrien		}
2459130561Sobrien	    }
246099461Sobrien
246199461Sobrien	  if (off >= (bfd_vma) -2)
246299461Sobrien	    abort ();
246399461Sobrien
246499461Sobrien	  relocation = htab->sgot->output_offset + off;
246599461Sobrien
2466130561Sobrien	  /* For @GOTENT the relocation is against the offset between
2467130561Sobrien	     the instruction and the symbols entry in the GOT and not
2468130561Sobrien	     between the start of the GOT and the symbols entry. We
2469130561Sobrien	     add the vma of the GOT to get the correct value.  */
2470130561Sobrien	  if (   r_type == R_390_GOTENT
2471130561Sobrien	      || r_type == R_390_GOTPLTENT)
247299461Sobrien	    relocation += htab->sgot->output_section->vma;
247399461Sobrien
2474130561Sobrien	  break;
247599461Sobrien
2476130561Sobrien	case R_390_GOTOFF16:
2477130561Sobrien	case R_390_GOTOFF32:
2478130561Sobrien	  /* Relocation is relative to the start of the global offset
2479130561Sobrien	     table.  */
248099461Sobrien
2481130561Sobrien	  /* Note that sgot->output_offset is not involved in this
2482130561Sobrien	     calculation.  We always want the start of .got.  If we
2483130561Sobrien	     defined _GLOBAL_OFFSET_TABLE in a different way, as is
2484130561Sobrien	     permitted by the ABI, we might have to change this
2485130561Sobrien	     calculation.  */
2486130561Sobrien	  relocation -= htab->sgot->output_section->vma;
2487130561Sobrien	  break;
248899461Sobrien
2489130561Sobrien	case R_390_GOTPC:
249099461Sobrien	case R_390_GOTPCDBL:
2491130561Sobrien	  /* Use global offset table as symbol value.  */
2492130561Sobrien	  relocation = htab->sgot->output_section->vma;
2493130561Sobrien	  unresolved_reloc = FALSE;
2494130561Sobrien	  break;
249599461Sobrien
2496130561Sobrien	case R_390_PLT16DBL:
2497130561Sobrien	case R_390_PLT32DBL:
2498130561Sobrien	case R_390_PLT32:
2499130561Sobrien	  /* Relocation is to the entry for this symbol in the
2500130561Sobrien	     procedure linkage table.  */
250199461Sobrien
2502130561Sobrien	  /* Resolve a PLT32 reloc against a local symbol directly,
2503130561Sobrien	     without using the procedure linkage table.  */
2504130561Sobrien	  if (h == NULL)
2505130561Sobrien	    break;
250699461Sobrien
2507130561Sobrien	  if (h->plt.offset == (bfd_vma) -1
250899461Sobrien	      || htab->splt == NULL)
2509130561Sobrien	    {
2510130561Sobrien	      /* We didn't make a PLT entry for this symbol.  This
2511130561Sobrien		 happens when statically linking PIC code, or when
2512130561Sobrien		 using -Bsymbolic.  */
2513130561Sobrien	      break;
2514130561Sobrien	    }
251599461Sobrien
2516130561Sobrien	  relocation = (htab->splt->output_section->vma
2517130561Sobrien			+ htab->splt->output_offset
2518130561Sobrien			+ h->plt.offset);
2519130561Sobrien	  unresolved_reloc = FALSE;
2520130561Sobrien	  break;
252199461Sobrien
2522130561Sobrien	case R_390_PLTOFF16:
2523130561Sobrien	case R_390_PLTOFF32:
2524130561Sobrien	  /* Relocation is to the entry for this symbol in the
2525130561Sobrien	     procedure linkage table relative to the start of the GOT.  */
2526130561Sobrien
2527130561Sobrien	  /* For local symbols or if we didn't make a PLT entry for
2528130561Sobrien	     this symbol resolve the symbol directly.  */
2529130561Sobrien	  if (   h == NULL
2530130561Sobrien	      || h->plt.offset == (bfd_vma) -1
2531130561Sobrien	      || htab->splt == NULL)
2532130561Sobrien	    {
2533130561Sobrien	      relocation -= htab->sgot->output_section->vma;
2534130561Sobrien	      break;
2535130561Sobrien	    }
2536130561Sobrien
2537130561Sobrien	  relocation = (htab->splt->output_section->vma
2538130561Sobrien			+ htab->splt->output_offset
2539130561Sobrien			+ h->plt.offset
2540130561Sobrien			- htab->sgot->output_section->vma);
2541130561Sobrien	  unresolved_reloc = FALSE;
2542130561Sobrien	  break;
2543130561Sobrien
2544130561Sobrien	case R_390_8:
2545130561Sobrien	case R_390_16:
2546130561Sobrien	case R_390_32:
2547130561Sobrien	case R_390_PC16:
2548130561Sobrien	case R_390_PC16DBL:
2549130561Sobrien	case R_390_PC32DBL:
2550130561Sobrien	case R_390_PC32:
2551218822Sdim	  if ((input_section->flags & SEC_ALLOC) == 0)
255299461Sobrien	    break;
255399461Sobrien
2554130561Sobrien	  if ((info->shared
2555130561Sobrien	       && (h == NULL
2556130561Sobrien		   || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
2557130561Sobrien		   || h->root.type != bfd_link_hash_undefweak)
255899461Sobrien	       && ((r_type != R_390_PC16
255999461Sobrien		    && r_type != R_390_PC16DBL
256099461Sobrien		    && r_type != R_390_PC32DBL
256199461Sobrien		    && r_type != R_390_PC32)
256299461Sobrien		   || (h != NULL
2563130561Sobrien		       && !SYMBOL_REFERENCES_LOCAL (info, h))))
2564130561Sobrien	      || (ELIMINATE_COPY_RELOCS
2565130561Sobrien		  && !info->shared
256699461Sobrien		  && h != NULL
256799461Sobrien		  && h->dynindx != -1
2568218822Sdim		  && !h->non_got_ref
2569218822Sdim		  && ((h->def_dynamic
2570218822Sdim		       && !h->def_regular)
257199461Sobrien		      || h->root.type == bfd_link_hash_undefweak
257299461Sobrien		      || h->root.type == bfd_link_hash_undefined)))
2573130561Sobrien	    {
2574130561Sobrien	      Elf_Internal_Rela outrel;
2575130561Sobrien	      bfd_boolean skip, relocate;
257699461Sobrien	      asection *sreloc;
2577130561Sobrien	      bfd_byte *loc;
257899461Sobrien
257999461Sobrien	      /* When generating a shared object, these relocations
258099461Sobrien		 are copied into the output file to be resolved at run
258199461Sobrien		 time.  */
258299461Sobrien
2583130561Sobrien	      skip = FALSE;
2584130561Sobrien	      relocate = FALSE;
258599461Sobrien
258699461Sobrien	      outrel.r_offset =
258799461Sobrien		_bfd_elf_section_offset (output_bfd, info, input_section,
258899461Sobrien					 rel->r_offset);
258999461Sobrien	      if (outrel.r_offset == (bfd_vma) -1)
2590130561Sobrien		skip = TRUE;
259199461Sobrien	      else if (outrel.r_offset == (bfd_vma) -2)
2592130561Sobrien		skip = TRUE, relocate = TRUE;
2593130561Sobrien	      outrel.r_offset += (input_section->output_section->vma
2594130561Sobrien				  + input_section->output_offset);
259599461Sobrien
2596130561Sobrien	      if (skip)
259799461Sobrien		memset (&outrel, 0, sizeof outrel);
2598130561Sobrien	      else if (h != NULL
259999461Sobrien		       && h->dynindx != -1
260099461Sobrien		       && (r_type == R_390_PC16
260199461Sobrien			   || r_type == R_390_PC16DBL
260299461Sobrien			   || r_type == R_390_PC32DBL
260399461Sobrien			   || r_type == R_390_PC32
260499461Sobrien			   || !info->shared
260599461Sobrien			   || !info->symbolic
2606218822Sdim			   || !h->def_regular))
2607130561Sobrien		{
2608130561Sobrien		  outrel.r_info = ELF32_R_INFO (h->dynindx, r_type);
260999461Sobrien		  outrel.r_addend = rel->r_addend;
2610130561Sobrien		}
2611130561Sobrien	      else
2612130561Sobrien		{
261399461Sobrien		  /* This symbol is local, or marked to become local.  */
261499461Sobrien		  outrel.r_addend = relocation + rel->r_addend;
2615130561Sobrien		  if (r_type == R_390_32)
2616130561Sobrien		    {
2617130561Sobrien		      relocate = TRUE;
2618130561Sobrien		      outrel.r_info = ELF32_R_INFO (0, R_390_RELATIVE);
2619130561Sobrien		    }
2620130561Sobrien		  else
2621130561Sobrien		    {
2622130561Sobrien		      long sindx;
262399461Sobrien
2624130561Sobrien		      if (bfd_is_abs_section (sec))
2625130561Sobrien			sindx = 0;
2626130561Sobrien		      else if (sec == NULL || sec->owner == NULL)
2627130561Sobrien			{
2628130561Sobrien			  bfd_set_error(bfd_error_bad_value);
2629130561Sobrien			  return FALSE;
2630130561Sobrien			}
2631130561Sobrien		      else
2632130561Sobrien			{
2633130561Sobrien			  asection *osec;
2634130561Sobrien
2635130561Sobrien			  osec = sec->output_section;
2636130561Sobrien			  sindx = elf_section_data (osec)->dynindx;
2637218822Sdim			  if (sindx == 0)
2638218822Sdim			    {
2639218822Sdim			      osec = htab->elf.text_index_section;
2640218822Sdim			      sindx = elf_section_data (osec)->dynindx;
2641218822Sdim			    }
2642218822Sdim			  BFD_ASSERT (sindx != 0);
2643130561Sobrien
2644130561Sobrien			  /* We are turning this relocation into one
2645130561Sobrien			     against a section symbol, so subtract out
2646130561Sobrien			     the output section's address but not the
2647130561Sobrien			     offset of the input section in the output
2648130561Sobrien			     section.  */
2649130561Sobrien			  outrel.r_addend -= osec->vma;
2650130561Sobrien			}
2651130561Sobrien		      outrel.r_info = ELF32_R_INFO (sindx, r_type);
2652130561Sobrien		    }
2653130561Sobrien		}
2654130561Sobrien
265599461Sobrien	      sreloc = elf_section_data (input_section)->sreloc;
265699461Sobrien	      if (sreloc == NULL)
265799461Sobrien		abort ();
265899461Sobrien
2659130561Sobrien	      loc = sreloc->contents;
2660130561Sobrien	      loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rela);
266199461Sobrien	      bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
266299461Sobrien
2663130561Sobrien	      /* If this reloc is against an external symbol, we do
2664130561Sobrien		 not want to fiddle with the addend.  Otherwise, we
2665130561Sobrien		 need to include the symbol value so that it becomes
2666130561Sobrien		 an addend for the dynamic reloc.  */
2667130561Sobrien	      if (! relocate)
2668130561Sobrien		continue;
2669130561Sobrien	    }
267099461Sobrien	  break;
267199461Sobrien
2672130561Sobrien	  /* Relocations for tls literal pool entries.  */
2673130561Sobrien	case R_390_TLS_IE32:
2674130561Sobrien	  if (info->shared)
2675130561Sobrien	    {
2676130561Sobrien	      Elf_Internal_Rela outrel;
2677130561Sobrien	      asection *sreloc;
2678130561Sobrien	      bfd_byte *loc;
2679130561Sobrien
2680130561Sobrien	      outrel.r_offset = rel->r_offset
2681130561Sobrien				+ input_section->output_section->vma
2682130561Sobrien				+ input_section->output_offset;
2683130561Sobrien	      outrel.r_info = ELF32_R_INFO (0, R_390_RELATIVE);
2684130561Sobrien	      sreloc = elf_section_data (input_section)->sreloc;
2685130561Sobrien	      if (sreloc == NULL)
2686130561Sobrien		abort ();
2687130561Sobrien	      loc = sreloc->contents;
2688130561Sobrien	      loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rela);
2689130561Sobrien	      bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc);
2690130561Sobrien	    }
2691130561Sobrien	  /* Fall through.  */
2692130561Sobrien
2693130561Sobrien	case R_390_TLS_GD32:
2694130561Sobrien	case R_390_TLS_GOTIE32:
2695130561Sobrien	  r_type = elf_s390_tls_transition (info, r_type, h == NULL);
2696130561Sobrien	  tls_type = GOT_UNKNOWN;
2697130561Sobrien	  if (h == NULL && local_got_offsets)
2698130561Sobrien	    tls_type = elf_s390_local_got_tls_type (input_bfd) [r_symndx];
2699130561Sobrien	  else if (h != NULL)
2700130561Sobrien	    {
2701130561Sobrien	      tls_type = elf_s390_hash_entry(h)->tls_type;
2702130561Sobrien	      if (!info->shared && h->dynindx == -1 && tls_type >= GOT_TLS_IE)
2703130561Sobrien		r_type = R_390_TLS_LE32;
2704130561Sobrien	    }
2705130561Sobrien	  if (r_type == R_390_TLS_GD32 && tls_type >= GOT_TLS_IE)
2706130561Sobrien	    r_type = R_390_TLS_IE32;
2707130561Sobrien
2708130561Sobrien	  if (r_type == R_390_TLS_LE32)
2709130561Sobrien	    {
2710130561Sobrien	      /* This relocation gets optimized away by the local exec
2711130561Sobrien		 access optimization.  */
2712130561Sobrien	      BFD_ASSERT (! unresolved_reloc);
2713130561Sobrien	      bfd_put_32 (output_bfd, -tpoff (info, relocation),
2714130561Sobrien			  contents + rel->r_offset);
2715130561Sobrien	      continue;
2716130561Sobrien	    }
2717130561Sobrien
2718130561Sobrien	  if (htab->sgot == NULL)
2719130561Sobrien	    abort ();
2720130561Sobrien
2721130561Sobrien	  if (h != NULL)
2722130561Sobrien	    off = h->got.offset;
2723130561Sobrien	  else
2724130561Sobrien	    {
2725130561Sobrien	      if (local_got_offsets == NULL)
2726130561Sobrien		abort ();
2727130561Sobrien
2728130561Sobrien	      off = local_got_offsets[r_symndx];
2729130561Sobrien	    }
2730130561Sobrien
2731130561Sobrien	emit_tls_relocs:
2732130561Sobrien
2733130561Sobrien	  if ((off & 1) != 0)
2734130561Sobrien	    off &= ~1;
2735130561Sobrien	  else
2736130561Sobrien	    {
2737130561Sobrien	      Elf_Internal_Rela outrel;
2738130561Sobrien	      bfd_byte *loc;
2739130561Sobrien	      int dr_type, indx;
2740130561Sobrien
2741130561Sobrien	      if (htab->srelgot == NULL)
2742130561Sobrien		abort ();
2743130561Sobrien
2744130561Sobrien	      outrel.r_offset = (htab->sgot->output_section->vma
2745130561Sobrien				 + htab->sgot->output_offset + off);
2746130561Sobrien
2747130561Sobrien	      indx = h && h->dynindx != -1 ? h->dynindx : 0;
2748130561Sobrien	      if (r_type == R_390_TLS_GD32)
2749130561Sobrien		dr_type = R_390_TLS_DTPMOD;
2750130561Sobrien	      else
2751130561Sobrien		dr_type = R_390_TLS_TPOFF;
2752130561Sobrien	      if (dr_type == R_390_TLS_TPOFF && indx == 0)
2753130561Sobrien		outrel.r_addend = relocation - dtpoff_base (info);
2754130561Sobrien	      else
2755130561Sobrien		outrel.r_addend = 0;
2756130561Sobrien	      outrel.r_info = ELF32_R_INFO (indx, dr_type);
2757130561Sobrien	      loc = htab->srelgot->contents;
2758130561Sobrien	      loc += htab->srelgot->reloc_count++
2759130561Sobrien		* sizeof (Elf32_External_Rela);
2760130561Sobrien	      bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
2761130561Sobrien
2762130561Sobrien	      if (r_type == R_390_TLS_GD32)
2763130561Sobrien		{
2764130561Sobrien		  if (indx == 0)
2765130561Sobrien		    {
2766130561Sobrien		      BFD_ASSERT (! unresolved_reloc);
2767130561Sobrien		      bfd_put_32 (output_bfd,
2768130561Sobrien				  relocation - dtpoff_base (info),
2769130561Sobrien				  htab->sgot->contents + off + GOT_ENTRY_SIZE);
2770130561Sobrien		    }
2771130561Sobrien		  else
2772130561Sobrien		    {
2773130561Sobrien		      outrel.r_info = ELF32_R_INFO (indx, R_390_TLS_DTPOFF);
2774130561Sobrien		      outrel.r_offset += GOT_ENTRY_SIZE;
2775130561Sobrien		      outrel.r_addend = 0;
2776130561Sobrien		      htab->srelgot->reloc_count++;
2777130561Sobrien		      loc += sizeof (Elf32_External_Rela);
2778130561Sobrien		      bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
2779130561Sobrien		    }
2780130561Sobrien		}
2781130561Sobrien
2782130561Sobrien	      if (h != NULL)
2783130561Sobrien		h->got.offset |= 1;
2784130561Sobrien	      else
2785130561Sobrien		local_got_offsets[r_symndx] |= 1;
2786130561Sobrien	    }
2787130561Sobrien
2788130561Sobrien	  if (off >= (bfd_vma) -2)
2789130561Sobrien	    abort ();
2790130561Sobrien	  if (r_type == ELF32_R_TYPE (rel->r_info))
2791130561Sobrien	    {
2792130561Sobrien	      relocation = htab->sgot->output_offset + off;
2793130561Sobrien	      if (r_type == R_390_TLS_IE32 || r_type == R_390_TLS_IEENT)
2794130561Sobrien		relocation += htab->sgot->output_section->vma;
2795130561Sobrien	      unresolved_reloc = FALSE;
2796130561Sobrien	    }
2797130561Sobrien	  else
2798130561Sobrien	    {
2799130561Sobrien	      bfd_put_32 (output_bfd, htab->sgot->output_offset + off,
2800130561Sobrien			  contents + rel->r_offset);
2801130561Sobrien	      continue;
2802130561Sobrien	    }
2803130561Sobrien	  break;
2804130561Sobrien
2805130561Sobrien	case R_390_TLS_GOTIE12:
2806130561Sobrien	case R_390_TLS_GOTIE20:
2807130561Sobrien	case R_390_TLS_IEENT:
2808130561Sobrien	  if (h == NULL)
2809130561Sobrien	    {
2810130561Sobrien	      if (local_got_offsets == NULL)
2811130561Sobrien		abort();
2812130561Sobrien	      off = local_got_offsets[r_symndx];
2813130561Sobrien	      if (info->shared)
2814130561Sobrien		goto emit_tls_relocs;
2815130561Sobrien	    }
2816130561Sobrien	  else
2817130561Sobrien	    {
2818130561Sobrien	      off = h->got.offset;
2819130561Sobrien	      tls_type = elf_s390_hash_entry(h)->tls_type;
2820130561Sobrien	      if (info->shared || h->dynindx != -1 || tls_type < GOT_TLS_IE)
2821130561Sobrien		goto emit_tls_relocs;
2822130561Sobrien	    }
2823130561Sobrien
2824130561Sobrien	  if (htab->sgot == NULL)
2825130561Sobrien	    abort ();
2826130561Sobrien
2827130561Sobrien	  BFD_ASSERT (! unresolved_reloc);
2828130561Sobrien	  bfd_put_32 (output_bfd, -tpoff (info, relocation),
2829130561Sobrien		      htab->sgot->contents + off);
2830130561Sobrien	  relocation = htab->sgot->output_offset + off;
2831130561Sobrien	  if (r_type == R_390_TLS_IEENT)
2832130561Sobrien	    relocation += htab->sgot->output_section->vma;
2833130561Sobrien	  unresolved_reloc = FALSE;
2834130561Sobrien	  break;
2835130561Sobrien
2836130561Sobrien	case R_390_TLS_LDM32:
2837130561Sobrien	  if (! info->shared)
2838130561Sobrien	    /* The literal pool entry this relocation refers to gets ignored
2839130561Sobrien	       by the optimized code of the local exec model. Do nothing
2840130561Sobrien	       and the value will turn out zero.  */
2841130561Sobrien	    continue;
2842130561Sobrien
2843130561Sobrien	  if (htab->sgot == NULL)
2844130561Sobrien	    abort ();
2845130561Sobrien
2846130561Sobrien	  off = htab->tls_ldm_got.offset;
2847130561Sobrien	  if (off & 1)
2848130561Sobrien	    off &= ~1;
2849130561Sobrien	  else
2850130561Sobrien	    {
2851130561Sobrien	      Elf_Internal_Rela outrel;
2852130561Sobrien	      bfd_byte *loc;
2853130561Sobrien
2854130561Sobrien	      if (htab->srelgot == NULL)
2855130561Sobrien		abort ();
2856130561Sobrien
2857130561Sobrien	      outrel.r_offset = (htab->sgot->output_section->vma
2858130561Sobrien				 + htab->sgot->output_offset + off);
2859130561Sobrien
2860130561Sobrien	      bfd_put_32 (output_bfd, 0,
2861130561Sobrien			  htab->sgot->contents + off + GOT_ENTRY_SIZE);
2862130561Sobrien	      outrel.r_info = ELF32_R_INFO (0, R_390_TLS_DTPMOD);
2863130561Sobrien	      outrel.r_addend = 0;
2864130561Sobrien	      loc = htab->srelgot->contents;
2865130561Sobrien	      loc += htab->srelgot->reloc_count++
2866130561Sobrien		* sizeof (Elf32_External_Rela);
2867130561Sobrien	      bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
2868130561Sobrien	      htab->tls_ldm_got.offset |= 1;
2869130561Sobrien	    }
2870130561Sobrien	  relocation = htab->sgot->output_offset + off;
2871130561Sobrien	  unresolved_reloc = FALSE;
2872130561Sobrien	  break;
2873130561Sobrien
2874130561Sobrien	case R_390_TLS_LE32:
2875130561Sobrien	  if (info->shared)
2876130561Sobrien	    {
2877130561Sobrien	      /* Linking a shared library with non-fpic code requires
2878130561Sobrien		 a R_390_TLS_TPOFF relocation.  */
2879130561Sobrien	      Elf_Internal_Rela outrel;
2880130561Sobrien	      asection *sreloc;
2881130561Sobrien	      bfd_byte *loc;
2882130561Sobrien	      int indx;
2883130561Sobrien
2884130561Sobrien	      outrel.r_offset = rel->r_offset
2885130561Sobrien				+ input_section->output_section->vma
2886130561Sobrien				+ input_section->output_offset;
2887130561Sobrien	      if (h != NULL && h->dynindx != -1)
2888130561Sobrien		indx = h->dynindx;
2889130561Sobrien	      else
2890130561Sobrien		indx = 0;
2891130561Sobrien	      outrel.r_info = ELF32_R_INFO (indx, R_390_TLS_TPOFF);
2892130561Sobrien	      if (indx == 0)
2893130561Sobrien		outrel.r_addend = relocation - dtpoff_base (info);
2894130561Sobrien	      else
2895130561Sobrien		outrel.r_addend = 0;
2896130561Sobrien	      sreloc = elf_section_data (input_section)->sreloc;
2897130561Sobrien	      if (sreloc == NULL)
2898130561Sobrien		abort ();
2899130561Sobrien	      loc = sreloc->contents;
2900130561Sobrien	      loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rela);
2901130561Sobrien	      bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
2902130561Sobrien	    }
2903130561Sobrien	  else
2904130561Sobrien	    {
2905130561Sobrien	      BFD_ASSERT (! unresolved_reloc);
2906130561Sobrien	      bfd_put_32 (output_bfd, -tpoff (info, relocation),
2907130561Sobrien			  contents + rel->r_offset);
2908130561Sobrien	    }
2909130561Sobrien	  continue;
2910130561Sobrien
2911130561Sobrien	case R_390_TLS_LDO32:
2912218822Sdim	  if (info->shared)
2913130561Sobrien	    relocation -= dtpoff_base (info);
2914130561Sobrien	  else
2915130561Sobrien	    /* When converting LDO to LE, we must negate.  */
2916130561Sobrien	    relocation = -tpoff (info, relocation);
2917130561Sobrien	  break;
2918130561Sobrien
2919130561Sobrien	  /* Relocations for tls instructions.  */
2920130561Sobrien	case R_390_TLS_LOAD:
2921130561Sobrien	case R_390_TLS_GDCALL:
2922130561Sobrien	case R_390_TLS_LDCALL:
2923130561Sobrien	  tls_type = GOT_UNKNOWN;
2924130561Sobrien	  if (h == NULL && local_got_offsets)
2925130561Sobrien	    tls_type = elf_s390_local_got_tls_type (input_bfd) [r_symndx];
2926130561Sobrien	  else if (h != NULL)
2927130561Sobrien	    tls_type = elf_s390_hash_entry(h)->tls_type;
2928130561Sobrien
2929130561Sobrien	  if (tls_type == GOT_TLS_GD)
2930130561Sobrien	    continue;
2931130561Sobrien
2932130561Sobrien	  if (r_type == R_390_TLS_LOAD)
2933130561Sobrien	    {
2934130561Sobrien	      if (!info->shared && (h == NULL || h->dynindx == -1))
2935130561Sobrien		{
2936130561Sobrien		  /* IE->LE transition. Four valid cases:
2937130561Sobrien		     l %rx,0(0,%ry)    -> lr %rx,%ry + bcr 0,0
2938130561Sobrien		     l %rx,0(%ry,0)    -> lr %rx,%ry + bcr 0,0
2939130561Sobrien		     l %rx,0(%ry,%r12) -> lr %rx,%ry + bcr 0,0
2940130561Sobrien		     l %rx,0(%r12,%ry) -> lr %rx,%ry + bcr 0,0 */
2941130561Sobrien		  unsigned int insn, ry;
2942130561Sobrien
2943130561Sobrien		  insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
2944130561Sobrien		  ry = 0;
2945130561Sobrien		  if ((insn & 0xff00f000) == 0x58000000)
2946130561Sobrien		    /* l %rx,0(%ry,0) -> lr %rx,%ry + bcr 0,0  */
2947130561Sobrien		    ry = (insn & 0x000f0000);
2948130561Sobrien		  else if ((insn & 0xff0f0000) == 0x58000000)
2949130561Sobrien		    /* l %rx,0(0,%ry) -> lr %rx,%ry + bcr 0,0  */
2950130561Sobrien		    ry = (insn & 0x0000f000) << 4;
2951130561Sobrien		  else if ((insn & 0xff00f000) == 0x5800c000)
2952130561Sobrien		    /* l %rx,0(%ry,%r12) -> lr %rx,%ry + bcr 0,0  */
2953130561Sobrien		    ry = (insn & 0x000f0000);
2954130561Sobrien		  else if ((insn & 0xff0f0000) == 0x580c0000)
2955130561Sobrien		    /* l %rx,0(%r12,%ry) -> lr %rx,%ry + bcr 0,0  */
2956130561Sobrien		    ry = (insn & 0x0000f000) << 4;
2957130561Sobrien		  else
2958130561Sobrien		    invalid_tls_insn (input_bfd, input_section, rel);
2959130561Sobrien		  insn = 0x18000700 | (insn & 0x00f00000) | ry;
2960130561Sobrien		  bfd_put_32 (output_bfd, insn, contents + rel->r_offset);
2961130561Sobrien		}
2962130561Sobrien	    }
2963130561Sobrien	  else if (r_type == R_390_TLS_GDCALL)
2964130561Sobrien	    {
2965130561Sobrien	      unsigned int insn;
2966130561Sobrien
2967130561Sobrien	      insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
2968218822Sdim	      if ((insn & 0xff000fff) != 0x4d000000 &&
2969218822Sdim		  (insn & 0xffff0000) != 0xc0e50000)
2970130561Sobrien		invalid_tls_insn (input_bfd, input_section, rel);
2971130561Sobrien	      if (!info->shared && (h == NULL || h->dynindx == -1))
2972218822Sdim		{
2973218822Sdim		  if ((insn & 0xff000000) == 0x4d000000)
2974218822Sdim		    {
2975218822Sdim		      /* GD->LE transition.
2976218822Sdim			 bas %r14,0(%rx,%r13) -> bc 0,0  */
2977218822Sdim		      insn = 0x47000000;
2978218822Sdim		    }
2979218822Sdim		  else
2980218822Sdim		    {
2981218822Sdim		      /* GD->LE transition.
2982218822Sdim			 brasl %r14,_tls_get_addr@plt -> brcl 0,.  */
2983218822Sdim		      insn = 0xc0040000;
2984218822Sdim		      bfd_put_16 (output_bfd, 0x0000,
2985218822Sdim				  contents + rel->r_offset + 4);
2986218822Sdim		    }
2987218822Sdim		}
2988130561Sobrien	      else
2989218822Sdim		{
2990218822Sdim		  if ((insn & 0xff000000) == 0x4d000000)
2991218822Sdim		    {
2992218822Sdim		      /* GD->IE transition.
2993218822Sdim			 bas %r14,0(%rx,%r13) -> l %r2,0(%r2,%r12)  */
2994218822Sdim		      insn = 0x5822c000;
2995218822Sdim		    }
2996218822Sdim		  else
2997218822Sdim		    {
2998218822Sdim		      /* GD->IE transition.
2999218822Sdim			 brasl %r14,__tls_get_addr@plt ->
3000218822Sdim			 	l %r2,0(%r2,%r12) ; bcr 0,0 */
3001218822Sdim		      insn = 0x5822c000;
3002218822Sdim		      bfd_put_16 (output_bfd, 0x0700,
3003218822Sdim				  contents + rel->r_offset + 4);
3004218822Sdim		    }
3005218822Sdim		}
3006130561Sobrien	      bfd_put_32 (output_bfd, insn, contents + rel->r_offset);
3007130561Sobrien	    }
3008130561Sobrien	  else if (r_type == R_390_TLS_LDCALL)
3009130561Sobrien	    {
3010130561Sobrien	      if (!info->shared)
3011130561Sobrien		{
3012130561Sobrien		  unsigned int insn;
3013130561Sobrien
3014130561Sobrien		  insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
3015218822Sdim		  if ((insn & 0xff000fff) != 0x4d000000 &&
3016218822Sdim		      (insn & 0xffff0000) != 0xc0e50000)
3017130561Sobrien		    invalid_tls_insn (input_bfd, input_section, rel);
3018218822Sdim		  if ((insn & 0xff000000) == 0x4d000000)
3019218822Sdim		    {
3020218822Sdim		      /* LD->LE transition.
3021218822Sdim			 bas %r14,0(%rx,%r13) -> bc 0,0  */
3022218822Sdim		      insn = 0x47000000;
3023218822Sdim		    }
3024218822Sdim		  else
3025218822Sdim		    {
3026218822Sdim		      /* LD->LE transition.
3027218822Sdim			 brasl %r14,__tls_get_addr@plt -> brcl 0,. */
3028218822Sdim		      insn = 0xc0040000;
3029218822Sdim		      bfd_put_16 (output_bfd, 0x0000,
3030218822Sdim				  contents + rel->r_offset + 4);
3031218822Sdim		    }
3032130561Sobrien		  bfd_put_32 (output_bfd, insn, contents + rel->r_offset);
3033130561Sobrien		}
3034130561Sobrien	    }
3035130561Sobrien	  continue;
3036130561Sobrien
303799461Sobrien	default:
303899461Sobrien	  break;
303999461Sobrien	}
304099461Sobrien
3041107492Sobrien      /* Dynamic relocs are not propagated for SEC_DEBUGGING sections
3042107492Sobrien	 because such sections are not SEC_ALLOC and thus ld.so will
3043107492Sobrien	 not process them.  */
304499461Sobrien      if (unresolved_reloc
3045107492Sobrien	  && !((input_section->flags & SEC_DEBUGGING) != 0
3046218822Sdim	       && h->def_dynamic))
304799461Sobrien	(*_bfd_error_handler)
3048218822Sdim	  (_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"),
3049218822Sdim	   input_bfd,
3050218822Sdim	   input_section,
305199461Sobrien	   (long) rel->r_offset,
3052218822Sdim	   howto->name,
305399461Sobrien	   h->root.root.string);
305499461Sobrien
3055130561Sobrien      if (r_type == R_390_20
3056130561Sobrien	  || r_type == R_390_GOT20
3057130561Sobrien	  || r_type == R_390_GOTPLT20
3058130561Sobrien	  || r_type == R_390_TLS_GOTIE20)
3059130561Sobrien	{
3060130561Sobrien	  relocation += rel->r_addend;
3061130561Sobrien	  relocation = (relocation&0xfff) << 8 | (relocation&0xff000) >> 12;
3062130561Sobrien	  r = _bfd_final_link_relocate (howto, input_bfd, input_section,
3063130561Sobrien					contents, rel->r_offset,
3064130561Sobrien					relocation, 0);
3065130561Sobrien	}
3066130561Sobrien      else
3067130561Sobrien	r = _bfd_final_link_relocate (howto, input_bfd, input_section,
3068130561Sobrien				      contents, rel->r_offset,
3069130561Sobrien				      relocation, rel->r_addend);
307099461Sobrien
307199461Sobrien      if (r != bfd_reloc_ok)
307299461Sobrien	{
307399461Sobrien	  const char *name;
307499461Sobrien
307599461Sobrien	  if (h != NULL)
307699461Sobrien	    name = h->root.root.string;
307799461Sobrien	  else
307899461Sobrien	    {
307999461Sobrien	      name = bfd_elf_string_from_elf_section (input_bfd,
308099461Sobrien						      symtab_hdr->sh_link,
308199461Sobrien						      sym->st_name);
308299461Sobrien	      if (name == NULL)
3083130561Sobrien		return FALSE;
308499461Sobrien	      if (*name == '\0')
308599461Sobrien		name = bfd_section_name (input_bfd, sec);
308699461Sobrien	    }
308799461Sobrien
308899461Sobrien	  if (r == bfd_reloc_overflow)
308999461Sobrien	    {
309099461Sobrien
309199461Sobrien	      if (! ((*info->callbacks->reloc_overflow)
3092218822Sdim		     (info, (h ? &h->root : NULL), name, howto->name,
3093218822Sdim		      (bfd_vma) 0, input_bfd, input_section,
3094218822Sdim		      rel->r_offset)))
3095130561Sobrien		return FALSE;
309699461Sobrien	    }
309799461Sobrien	  else
309899461Sobrien	    {
309999461Sobrien	      (*_bfd_error_handler)
3100218822Sdim		(_("%B(%A+0x%lx): reloc against `%s': error %d"),
3101218822Sdim		 input_bfd, input_section,
310299461Sobrien		 (long) rel->r_offset, name, (int) r);
3103130561Sobrien	      return FALSE;
310499461Sobrien	    }
310599461Sobrien	}
310699461Sobrien    }
310799461Sobrien
3108130561Sobrien  return TRUE;
310999461Sobrien}
311099461Sobrien
311199461Sobrien/* Finish up dynamic symbol handling.  We set the contents of various
311299461Sobrien   dynamic sections here.  */
311399461Sobrien
3114130561Sobrienstatic bfd_boolean
311599461Sobrienelf_s390_finish_dynamic_symbol (output_bfd, info, h, sym)
311699461Sobrien     bfd *output_bfd;
311799461Sobrien     struct bfd_link_info *info;
311899461Sobrien     struct elf_link_hash_entry *h;
311999461Sobrien     Elf_Internal_Sym *sym;
312099461Sobrien{
312199461Sobrien  struct elf_s390_link_hash_table *htab;
312299461Sobrien
312399461Sobrien  htab = elf_s390_hash_table (info);
312499461Sobrien
312599461Sobrien  if (h->plt.offset != (bfd_vma) -1)
312699461Sobrien    {
312799461Sobrien      bfd_vma plt_index;
312899461Sobrien      bfd_vma got_offset;
312999461Sobrien      Elf_Internal_Rela rela;
3130130561Sobrien      bfd_byte *loc;
313199461Sobrien      bfd_vma relative_offset;
313299461Sobrien
313399461Sobrien      /* This symbol has an entry in the procedure linkage table.  Set
3134130561Sobrien	 it up.  */
313599461Sobrien      if (h->dynindx == -1
313699461Sobrien	  || htab->splt == NULL
313799461Sobrien	  || htab->sgotplt == NULL
313899461Sobrien	  || htab->srelplt == NULL)
313999461Sobrien	abort ();
314099461Sobrien
314199461Sobrien      /* Calc. index no.
3142130561Sobrien	 Current offset - size first entry / entry size.  */
314399461Sobrien      plt_index = (h->plt.offset - PLT_FIRST_ENTRY_SIZE) / PLT_ENTRY_SIZE;
314499461Sobrien
314599461Sobrien      /* Offset in GOT is PLT index plus GOT headers(3) times 4,
3146130561Sobrien	 addr & GOT addr.  */
314799461Sobrien      got_offset = (plt_index + 3) * GOT_ENTRY_SIZE;
314899461Sobrien
314999461Sobrien      /* S390 uses halfwords for relative branch calc!  */
315099461Sobrien      relative_offset = - ((PLT_FIRST_ENTRY_SIZE +
3151130561Sobrien			    (PLT_ENTRY_SIZE * plt_index) + 18) / 2);
315299461Sobrien      /* If offset is > 32768, branch to a previous branch
3153130561Sobrien	 390 can only handle +-64 K jumps.  */
315499461Sobrien      if ( -32768 > (int) relative_offset )
3155130561Sobrien	relative_offset
3156130561Sobrien	  = -(unsigned) (((65536 / PLT_ENTRY_SIZE - 1) * PLT_ENTRY_SIZE) / 2);
315799461Sobrien
315899461Sobrien      /* Fill in the entry in the procedure linkage table.  */
315999461Sobrien      if (!info->shared)
316099461Sobrien	{
3161130561Sobrien	  bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD0,
316299461Sobrien		      htab->splt->contents + h->plt.offset);
316399461Sobrien	  bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD1,
316499461Sobrien		      htab->splt->contents + h->plt.offset + 4);
316599461Sobrien	  bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD2,
316699461Sobrien		      htab->splt->contents + h->plt.offset + 8);
316799461Sobrien	  bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD3,
316899461Sobrien		      htab->splt->contents + h->plt.offset + 12);
316999461Sobrien	  bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD4,
317099461Sobrien		      htab->splt->contents + h->plt.offset + 16);
317199461Sobrien	  bfd_put_32 (output_bfd, (bfd_vma) 0+(relative_offset << 16),
317299461Sobrien		      htab->splt->contents + h->plt.offset + 20);
317399461Sobrien	  bfd_put_32 (output_bfd,
317499461Sobrien		      (htab->sgotplt->output_section->vma
317599461Sobrien		       + htab->sgotplt->output_offset
317699461Sobrien		       + got_offset),
317799461Sobrien		      htab->splt->contents + h->plt.offset + 24);
317899461Sobrien	}
317999461Sobrien      else if (got_offset < 4096)
318099461Sobrien	{
318199461Sobrien	  bfd_put_32 (output_bfd, (bfd_vma) PLT_PIC12_ENTRY_WORD0 + got_offset,
318299461Sobrien		      htab->splt->contents + h->plt.offset);
318399461Sobrien	  bfd_put_32 (output_bfd, (bfd_vma) PLT_PIC12_ENTRY_WORD1,
318499461Sobrien		      htab->splt->contents + h->plt.offset + 4);
318599461Sobrien	  bfd_put_32 (output_bfd, (bfd_vma) PLT_PIC12_ENTRY_WORD2,
318699461Sobrien		      htab->splt->contents + h->plt.offset + 8);
318799461Sobrien	  bfd_put_32 (output_bfd, (bfd_vma) PLT_PIC12_ENTRY_WORD3,
318899461Sobrien		      htab->splt->contents + h->plt.offset + 12);
318999461Sobrien	  bfd_put_32 (output_bfd, (bfd_vma) PLT_PIC12_ENTRY_WORD4,
319099461Sobrien		      htab->splt->contents + h->plt.offset + 16);
319199461Sobrien	  bfd_put_32 (output_bfd, (bfd_vma) 0+(relative_offset << 16),
319299461Sobrien		      htab->splt->contents + h->plt.offset + 20);
319399461Sobrien	  bfd_put_32 (output_bfd, (bfd_vma) 0,
319499461Sobrien		      htab->splt->contents + h->plt.offset + 24);
319599461Sobrien	}
319699461Sobrien      else if (got_offset < 32768)
319799461Sobrien	{
319899461Sobrien	  bfd_put_32 (output_bfd, (bfd_vma) PLT_PIC16_ENTRY_WORD0 + got_offset,
319999461Sobrien		      htab->splt->contents + h->plt.offset);
320099461Sobrien	  bfd_put_32 (output_bfd, (bfd_vma) PLT_PIC16_ENTRY_WORD1,
320199461Sobrien		      htab->splt->contents + h->plt.offset + 4);
320299461Sobrien	  bfd_put_32 (output_bfd, (bfd_vma) PLT_PIC16_ENTRY_WORD2,
320399461Sobrien		      htab->splt->contents + h->plt.offset + 8);
320499461Sobrien	  bfd_put_32 (output_bfd, (bfd_vma) PLT_PIC16_ENTRY_WORD3,
320599461Sobrien		      htab->splt->contents + h->plt.offset + 12);
320699461Sobrien	  bfd_put_32 (output_bfd, (bfd_vma) PLT_PIC16_ENTRY_WORD4,
320799461Sobrien		      htab->splt->contents + h->plt.offset + 16);
320899461Sobrien	  bfd_put_32 (output_bfd, (bfd_vma) 0+(relative_offset << 16),
320999461Sobrien		      htab->splt->contents + h->plt.offset + 20);
321099461Sobrien	  bfd_put_32 (output_bfd, (bfd_vma) 0,
321199461Sobrien		      htab->splt->contents + h->plt.offset + 24);
321299461Sobrien	}
321399461Sobrien      else
321499461Sobrien	{
321599461Sobrien	  bfd_put_32 (output_bfd, (bfd_vma) PLT_PIC_ENTRY_WORD0,
321699461Sobrien		      htab->splt->contents + h->plt.offset);
321799461Sobrien	  bfd_put_32 (output_bfd, (bfd_vma) PLT_PIC_ENTRY_WORD1,
321899461Sobrien		      htab->splt->contents + h->plt.offset + 4);
321999461Sobrien	  bfd_put_32 (output_bfd, (bfd_vma) PLT_PIC_ENTRY_WORD2,
322099461Sobrien		      htab->splt->contents + h->plt.offset + 8);
322199461Sobrien	  bfd_put_32 (output_bfd, (bfd_vma) PLT_PIC_ENTRY_WORD3,
322299461Sobrien		      htab->splt->contents + h->plt.offset + 12);
322399461Sobrien	  bfd_put_32 (output_bfd, (bfd_vma) PLT_PIC_ENTRY_WORD4,
322499461Sobrien		      htab->splt->contents + h->plt.offset + 16);
322599461Sobrien	  bfd_put_32 (output_bfd, (bfd_vma) 0+(relative_offset << 16),
322699461Sobrien		      htab->splt->contents + h->plt.offset + 20);
322799461Sobrien	  bfd_put_32 (output_bfd, got_offset,
322899461Sobrien		      htab->splt->contents + h->plt.offset + 24);
322999461Sobrien	}
323099461Sobrien      /* Insert offset into  reloc. table here.  */
323199461Sobrien      bfd_put_32 (output_bfd, plt_index * sizeof (Elf32_External_Rela),
3232130561Sobrien		  htab->splt->contents + h->plt.offset + 28);
323399461Sobrien
323499461Sobrien      /* Fill in the entry in the global offset table.
3235130561Sobrien	 Points to instruction after GOT offset.  */
323699461Sobrien      bfd_put_32 (output_bfd,
323799461Sobrien		  (htab->splt->output_section->vma
323899461Sobrien		   + htab->splt->output_offset
323999461Sobrien		   + h->plt.offset
324099461Sobrien		   + 12),
324199461Sobrien		  htab->sgotplt->contents + got_offset);
324299461Sobrien
324399461Sobrien      /* Fill in the entry in the .rela.plt section.  */
324499461Sobrien      rela.r_offset = (htab->sgotplt->output_section->vma
324599461Sobrien		       + htab->sgotplt->output_offset
324699461Sobrien		       + got_offset);
324799461Sobrien      rela.r_info = ELF32_R_INFO (h->dynindx, R_390_JMP_SLOT);
324899461Sobrien      rela.r_addend = 0;
3249130561Sobrien      loc = htab->srelplt->contents + plt_index * sizeof (Elf32_External_Rela);
325099461Sobrien      bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
325199461Sobrien
3252218822Sdim      if (!h->def_regular)
325399461Sobrien	{
325499461Sobrien	  /* Mark the symbol as undefined, rather than as defined in
325599461Sobrien	     the .plt section.  Leave the value alone.  This is a clue
325699461Sobrien	     for the dynamic linker, to make function pointer
325799461Sobrien	     comparisons work between an application and shared
325899461Sobrien	     library.  */
325999461Sobrien	  sym->st_shndx = SHN_UNDEF;
326099461Sobrien	}
326199461Sobrien    }
326299461Sobrien
3263130561Sobrien  if (h->got.offset != (bfd_vma) -1
3264130561Sobrien      && elf_s390_hash_entry(h)->tls_type != GOT_TLS_GD
3265130561Sobrien      && elf_s390_hash_entry(h)->tls_type != GOT_TLS_IE
3266130561Sobrien      && elf_s390_hash_entry(h)->tls_type != GOT_TLS_IE_NLT)
326799461Sobrien    {
326899461Sobrien      Elf_Internal_Rela rela;
3269130561Sobrien      bfd_byte *loc;
327099461Sobrien
327199461Sobrien      /* This symbol has an entry in the global offset table.  Set it
3272130561Sobrien	 up.  */
327399461Sobrien
327499461Sobrien      if (htab->sgot == NULL || htab->srelgot == NULL)
327599461Sobrien	abort ();
327699461Sobrien
327799461Sobrien      rela.r_offset = (htab->sgot->output_section->vma
327899461Sobrien		       + htab->sgot->output_offset
327999461Sobrien		       + (h->got.offset &~ (bfd_vma) 1));
328099461Sobrien
328199461Sobrien      /* If this is a static link, or it is a -Bsymbolic link and the
328299461Sobrien	 symbol is defined locally or was forced to be local because
328399461Sobrien	 of a version file, we just want to emit a RELATIVE reloc.
328499461Sobrien	 The entry in the global offset table will already have been
328599461Sobrien	 initialized in the relocate_section function.  */
328699461Sobrien      if (info->shared
328799461Sobrien	  && (info->symbolic
328899461Sobrien	      || h->dynindx == -1
3289218822Sdim	      || h->forced_local)
3290218822Sdim	  && h->def_regular)
329199461Sobrien	{
329299461Sobrien	  BFD_ASSERT((h->got.offset & 1) != 0);
329399461Sobrien	  rela.r_info = ELF32_R_INFO (0, R_390_RELATIVE);
329499461Sobrien	  rela.r_addend = (h->root.u.def.value
3295130561Sobrien			   + h->root.u.def.section->output_section->vma
3296130561Sobrien			   + h->root.u.def.section->output_offset);
3297130561Sobrien	}
329899461Sobrien      else
329999461Sobrien	{
330099461Sobrien	  BFD_ASSERT((h->got.offset & 1) == 0);
330199461Sobrien	  bfd_put_32 (output_bfd, (bfd_vma) 0, htab->sgot->contents + h->got.offset);
330299461Sobrien	  rela.r_info = ELF32_R_INFO (h->dynindx, R_390_GLOB_DAT);
3303130561Sobrien	  rela.r_addend = 0;
3304130561Sobrien	}
330599461Sobrien
3306130561Sobrien      loc = htab->srelgot->contents;
3307130561Sobrien      loc += htab->srelgot->reloc_count++ * sizeof (Elf32_External_Rela);
330899461Sobrien      bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
330999461Sobrien    }
331099461Sobrien
3311218822Sdim  if (h->needs_copy)
331299461Sobrien    {
331399461Sobrien      Elf_Internal_Rela rela;
3314130561Sobrien      bfd_byte *loc;
331599461Sobrien
331699461Sobrien      /* This symbols needs a copy reloc.  Set it up.  */
331799461Sobrien
331899461Sobrien      if (h->dynindx == -1
331999461Sobrien	  || (h->root.type != bfd_link_hash_defined
332099461Sobrien	      && h->root.type != bfd_link_hash_defweak)
332199461Sobrien	  || htab->srelbss == NULL)
332299461Sobrien	abort ();
332399461Sobrien
332499461Sobrien      rela.r_offset = (h->root.u.def.value
332599461Sobrien		       + h->root.u.def.section->output_section->vma
332699461Sobrien		       + h->root.u.def.section->output_offset);
332799461Sobrien      rela.r_info = ELF32_R_INFO (h->dynindx, R_390_COPY);
332899461Sobrien      rela.r_addend = 0;
3329130561Sobrien      loc = htab->srelbss->contents;
3330130561Sobrien      loc += htab->srelbss->reloc_count++ * sizeof (Elf32_External_Rela);
333199461Sobrien      bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
333299461Sobrien    }
333399461Sobrien
333499461Sobrien  /* Mark some specially defined symbols as absolute.  */
333599461Sobrien  if (strcmp (h->root.root.string, "_DYNAMIC") == 0
3336218822Sdim      || h == htab->elf.hgot
3337218822Sdim      || h == htab->elf.hplt)
333899461Sobrien    sym->st_shndx = SHN_ABS;
333999461Sobrien
3340130561Sobrien  return TRUE;
334199461Sobrien}
334299461Sobrien
334399461Sobrien/* Used to decide how to sort relocs in an optimal manner for the
334499461Sobrien   dynamic linker, before writing them out.  */
334599461Sobrien
334699461Sobrienstatic enum elf_reloc_type_class
334799461Sobrienelf_s390_reloc_type_class (rela)
334899461Sobrien     const Elf_Internal_Rela *rela;
334999461Sobrien{
335099461Sobrien  switch ((int) ELF32_R_TYPE (rela->r_info))
335199461Sobrien    {
335299461Sobrien    case R_390_RELATIVE:
335399461Sobrien      return reloc_class_relative;
335499461Sobrien    case R_390_JMP_SLOT:
335599461Sobrien      return reloc_class_plt;
335699461Sobrien    case R_390_COPY:
335799461Sobrien      return reloc_class_copy;
335899461Sobrien    default:
335999461Sobrien      return reloc_class_normal;
336099461Sobrien    }
336199461Sobrien}
336299461Sobrien
336399461Sobrien/* Finish up the dynamic sections.  */
336499461Sobrien
3365130561Sobrienstatic bfd_boolean
336699461Sobrienelf_s390_finish_dynamic_sections (output_bfd, info)
336799461Sobrien     bfd *output_bfd;
336899461Sobrien     struct bfd_link_info *info;
336999461Sobrien{
337099461Sobrien  struct elf_s390_link_hash_table *htab;
337199461Sobrien  bfd *dynobj;
337299461Sobrien  asection *sdyn;
337399461Sobrien
337499461Sobrien  htab = elf_s390_hash_table (info);
337599461Sobrien  dynobj = htab->elf.dynobj;
337699461Sobrien  sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
337799461Sobrien
337899461Sobrien  if (htab->elf.dynamic_sections_created)
337999461Sobrien    {
338099461Sobrien      Elf32_External_Dyn *dyncon, *dynconend;
338199461Sobrien
338299461Sobrien      if (sdyn == NULL || htab->sgot == NULL)
338399461Sobrien	abort ();
338499461Sobrien
338599461Sobrien      dyncon = (Elf32_External_Dyn *) sdyn->contents;
3386218822Sdim      dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->size);
338799461Sobrien      for (; dyncon < dynconend; dyncon++)
338899461Sobrien	{
338999461Sobrien	  Elf_Internal_Dyn dyn;
339099461Sobrien	  asection *s;
339199461Sobrien
339299461Sobrien	  bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn);
339399461Sobrien
339499461Sobrien	  switch (dyn.d_tag)
339599461Sobrien	    {
339699461Sobrien	    default:
339799461Sobrien	      continue;
339899461Sobrien
339999461Sobrien	    case DT_PLTGOT:
340099461Sobrien	      dyn.d_un.d_ptr = htab->sgot->output_section->vma;
340199461Sobrien	      break;
340299461Sobrien
340399461Sobrien	    case DT_JMPREL:
340499461Sobrien	      dyn.d_un.d_ptr = htab->srelplt->output_section->vma;
340599461Sobrien	      break;
340699461Sobrien
340799461Sobrien	    case DT_PLTRELSZ:
340899461Sobrien	      s = htab->srelplt->output_section;
3409218822Sdim	      dyn.d_un.d_val = s->size;
341099461Sobrien	      break;
341199461Sobrien	    }
341299461Sobrien
341399461Sobrien	  bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
341499461Sobrien	}
341599461Sobrien
341699461Sobrien      /* Fill in the special first entry in the procedure linkage table.  */
3417218822Sdim      if (htab->splt && htab->splt->size > 0)
341899461Sobrien	{
3419130561Sobrien	  memset (htab->splt->contents, 0, PLT_FIRST_ENTRY_SIZE);
3420130561Sobrien	  if (info->shared)
342199461Sobrien	    {
342299461Sobrien	      bfd_put_32 (output_bfd, (bfd_vma) PLT_PIC_FIRST_ENTRY_WORD0,
3423130561Sobrien			  htab->splt->contents );
342499461Sobrien	      bfd_put_32 (output_bfd, (bfd_vma) PLT_PIC_FIRST_ENTRY_WORD1,
3425130561Sobrien			  htab->splt->contents +4 );
342699461Sobrien	      bfd_put_32 (output_bfd, (bfd_vma) PLT_PIC_FIRST_ENTRY_WORD2,
3427130561Sobrien			  htab->splt->contents +8 );
342899461Sobrien	      bfd_put_32 (output_bfd, (bfd_vma) PLT_PIC_FIRST_ENTRY_WORD3,
3429130561Sobrien			  htab->splt->contents +12 );
343099461Sobrien	      bfd_put_32 (output_bfd, (bfd_vma) PLT_PIC_FIRST_ENTRY_WORD4,
3431130561Sobrien			  htab->splt->contents +16 );
3432130561Sobrien	   }
3433130561Sobrien	  else
3434130561Sobrien	   {
3435130561Sobrien	      bfd_put_32 (output_bfd, (bfd_vma)PLT_FIRST_ENTRY_WORD0,
3436130561Sobrien			  htab->splt->contents );
3437130561Sobrien	      bfd_put_32 (output_bfd, (bfd_vma) PLT_FIRST_ENTRY_WORD1,
3438130561Sobrien			  htab->splt->contents +4 );
3439130561Sobrien	      bfd_put_32 (output_bfd, (bfd_vma) PLT_FIRST_ENTRY_WORD2,
3440130561Sobrien			  htab->splt->contents +8 );
3441130561Sobrien	      bfd_put_32 (output_bfd, (bfd_vma) PLT_FIRST_ENTRY_WORD3,
3442130561Sobrien			  htab->splt->contents +12 );
3443130561Sobrien	      bfd_put_32 (output_bfd, (bfd_vma) PLT_FIRST_ENTRY_WORD4,
3444130561Sobrien			  htab->splt->contents +16 );
3445130561Sobrien	      bfd_put_32 (output_bfd, (bfd_vma) PLT_FIRST_ENTRY_WORD5,
3446130561Sobrien			  htab->splt->contents +20 );
3447130561Sobrien	      bfd_put_32 (output_bfd,
3448130561Sobrien			  htab->sgotplt->output_section->vma
344999461Sobrien			  + htab->sgotplt->output_offset,
3450130561Sobrien			  htab->splt->contents + 24);
3451130561Sobrien	   }
345299461Sobrien	  elf_section_data (htab->splt->output_section)
345399461Sobrien	    ->this_hdr.sh_entsize = 4;
345499461Sobrien	}
345599461Sobrien
345699461Sobrien    }
345799461Sobrien
345899461Sobrien  if (htab->sgotplt)
345999461Sobrien    {
346099461Sobrien      /* Fill in the first three entries in the global offset table.  */
3461218822Sdim      if (htab->sgotplt->size > 0)
346299461Sobrien	{
346399461Sobrien	  bfd_put_32 (output_bfd,
346499461Sobrien		      (sdyn == NULL ? (bfd_vma) 0
346599461Sobrien		       : sdyn->output_section->vma + sdyn->output_offset),
346699461Sobrien		      htab->sgotplt->contents);
346799461Sobrien	  /* One entry for shared object struct ptr.  */
346899461Sobrien	  bfd_put_32 (output_bfd, (bfd_vma) 0, htab->sgotplt->contents + 4);
346999461Sobrien	  /* One entry for _dl_runtime_resolve.  */
347099461Sobrien	  bfd_put_32 (output_bfd, (bfd_vma) 0, htab->sgotplt->contents + 8);
347199461Sobrien	}
347299461Sobrien
347399461Sobrien      elf_section_data (htab->sgotplt->output_section)
347499461Sobrien	->this_hdr.sh_entsize = 4;
347599461Sobrien    }
3476130561Sobrien  return TRUE;
347799461Sobrien}
347899461Sobrien
3479130561Sobrienstatic bfd_boolean
348099461Sobrienelf_s390_grok_prstatus (abfd, note)
348199461Sobrien     bfd * abfd;
348299461Sobrien     Elf_Internal_Note * note;
348399461Sobrien{
348499461Sobrien  int offset;
3485218822Sdim  unsigned int size;
348699461Sobrien
348799461Sobrien  switch (note->descsz)
348899461Sobrien    {
348999461Sobrien      default:
3490130561Sobrien	return FALSE;
349199461Sobrien
349299461Sobrien      case 224:		/* S/390 Linux.  */
349399461Sobrien	/* pr_cursig */
349499461Sobrien	elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12);
349599461Sobrien
349699461Sobrien	/* pr_pid */
349799461Sobrien	elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, note->descdata + 24);
349899461Sobrien
349999461Sobrien	/* pr_reg */
350099461Sobrien	offset = 72;
3501218822Sdim	size = 144;
350299461Sobrien	break;
350399461Sobrien    }
350499461Sobrien
350599461Sobrien  /* Make a ".reg/999" section.  */
350699461Sobrien  return _bfd_elfcore_make_pseudosection (abfd, ".reg",
3507218822Sdim					  size, note->descpos + offset);
350899461Sobrien}
350999461Sobrien
3510218822Sdim/* Return address for Ith PLT stub in section PLT, for relocation REL
3511218822Sdim   or (bfd_vma) -1 if it should not be included.  */
3512218822Sdim
3513218822Sdimstatic bfd_vma
3514218822Sdimelf_s390_plt_sym_val (bfd_vma i, const asection *plt,
3515218822Sdim		      const arelent *rel ATTRIBUTE_UNUSED)
3516218822Sdim{
3517218822Sdim  return plt->vma + PLT_FIRST_ENTRY_SIZE + i * PLT_ENTRY_SIZE;
3518218822Sdim}
3519218822Sdim
3520218822Sdim
352199461Sobrien#define TARGET_BIG_SYM	bfd_elf32_s390_vec
352299461Sobrien#define TARGET_BIG_NAME	"elf32-s390"
352399461Sobrien#define ELF_ARCH	bfd_arch_s390
352499461Sobrien#define ELF_MACHINE_CODE EM_S390
352599461Sobrien#define ELF_MACHINE_ALT1 EM_S390_OLD
352699461Sobrien#define ELF_MAXPAGESIZE 0x1000
352799461Sobrien
352899461Sobrien#define elf_backend_can_gc_sections	1
352999461Sobrien#define elf_backend_can_refcount	1
353099461Sobrien#define elf_backend_want_got_plt	1
353199461Sobrien#define elf_backend_plt_readonly	1
353299461Sobrien#define elf_backend_want_plt_sym	0
353399461Sobrien#define elf_backend_got_header_size	12
353499461Sobrien#define elf_backend_rela_normal		1
353599461Sobrien
3536130561Sobrien#define elf_info_to_howto		      elf_s390_info_to_howto
353799461Sobrien
353899461Sobrien#define bfd_elf32_bfd_is_local_label_name     elf_s390_is_local_label_name
353999461Sobrien#define bfd_elf32_bfd_link_hash_table_create  elf_s390_link_hash_table_create
354099461Sobrien#define bfd_elf32_bfd_reloc_type_lookup	      elf_s390_reloc_type_lookup
3541218822Sdim#define bfd_elf32_bfd_reloc_name_lookup elf_s390_reloc_name_lookup
354299461Sobrien
354399461Sobrien#define elf_backend_adjust_dynamic_symbol     elf_s390_adjust_dynamic_symbol
3544130561Sobrien#define elf_backend_check_relocs	      elf_s390_check_relocs
354599461Sobrien#define elf_backend_copy_indirect_symbol      elf_s390_copy_indirect_symbol
354699461Sobrien#define elf_backend_create_dynamic_sections   elf_s390_create_dynamic_sections
354799461Sobrien#define elf_backend_finish_dynamic_sections   elf_s390_finish_dynamic_sections
354899461Sobrien#define elf_backend_finish_dynamic_symbol     elf_s390_finish_dynamic_symbol
3549130561Sobrien#define elf_backend_gc_mark_hook	      elf_s390_gc_mark_hook
3550130561Sobrien#define elf_backend_gc_sweep_hook	      elf_s390_gc_sweep_hook
355199461Sobrien#define elf_backend_reloc_type_class	      elf_s390_reloc_type_class
3552130561Sobrien#define elf_backend_relocate_section	      elf_s390_relocate_section
355399461Sobrien#define elf_backend_size_dynamic_sections     elf_s390_size_dynamic_sections
3554218822Sdim#define elf_backend_init_index_section	      _bfd_elf_init_1_index_section
355599461Sobrien#define elf_backend_reloc_type_class	      elf_s390_reloc_type_class
355699461Sobrien#define elf_backend_grok_prstatus	      elf_s390_grok_prstatus
3557218822Sdim#define elf_backend_plt_sym_val		      elf_s390_plt_sym_val
355899461Sobrien
3559130561Sobrien#define bfd_elf32_mkobject		elf_s390_mkobject
3560130561Sobrien#define elf_backend_object_p		elf_s390_object_p
356199461Sobrien
356299461Sobrien#include "elf32-target.h"
3563