199461Sobrien/* IBM S/390-specific support for 64-bit ELF 2218822Sdim Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 3218822Sdim Free Software Foundation, Inc. 499461Sobrien Contributed Martin Schwidefsky (schwidefsky@de.ibm.com). 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 int elf_s390_tls_transition 73130561Sobrien PARAMS ((struct bfd_link_info *, int, int)); 74130561Sobrienstatic bfd_reloc_status_type s390_tls_reloc 75130561Sobrien PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); 76130561Sobrienstatic bfd_vma dtpoff_base 77130561Sobrien PARAMS ((struct bfd_link_info *)); 78130561Sobrienstatic bfd_vma tpoff 79130561Sobrien PARAMS ((struct bfd_link_info *, bfd_vma)); 80130561Sobrienstatic void invalid_tls_insn 81130561Sobrien PARAMS ((bfd *, asection *, Elf_Internal_Rela *)); 82130561Sobrienstatic bfd_reloc_status_type s390_elf_ldisp_reloc 83130561Sobrien PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); 8499461Sobrien 8599461Sobrien#include "elf/s390.h" 8699461Sobrien 8799461Sobrien/* In case we're on a 32-bit machine, construct a 64-bit "-1" value 8899461Sobrien from smaller values. Start with zero, widen, *then* decrement. */ 8999461Sobrien#define MINUS_ONE (((bfd_vma)0) - 1) 9099461Sobrien 9199461Sobrien/* The relocation "howto" table. */ 9299461Sobrienstatic reloc_howto_type elf_howto_table[] = 9399461Sobrien{ 9499461Sobrien HOWTO (R_390_NONE, /* type */ 9599461Sobrien 0, /* rightshift */ 9699461Sobrien 0, /* size (0 = byte, 1 = short, 2 = long) */ 9799461Sobrien 0, /* bitsize */ 98130561Sobrien FALSE, /* pc_relative */ 9999461Sobrien 0, /* bitpos */ 10099461Sobrien complain_overflow_dont, /* complain_on_overflow */ 10199461Sobrien bfd_elf_generic_reloc, /* special_function */ 10299461Sobrien "R_390_NONE", /* name */ 103130561Sobrien FALSE, /* partial_inplace */ 10499461Sobrien 0, /* src_mask */ 10599461Sobrien 0, /* dst_mask */ 106130561Sobrien FALSE), /* pcrel_offset */ 10799461Sobrien 108130561Sobrien HOWTO(R_390_8, 0, 0, 8, FALSE, 0, complain_overflow_bitfield, 109130561Sobrien bfd_elf_generic_reloc, "R_390_8", FALSE, 0,0x000000ff, FALSE), 110130561Sobrien HOWTO(R_390_12, 0, 1, 12, FALSE, 0, complain_overflow_dont, 111130561Sobrien bfd_elf_generic_reloc, "R_390_12", FALSE, 0,0x00000fff, FALSE), 112130561Sobrien HOWTO(R_390_16, 0, 1, 16, FALSE, 0, complain_overflow_bitfield, 113130561Sobrien bfd_elf_generic_reloc, "R_390_16", FALSE, 0,0x0000ffff, FALSE), 114130561Sobrien HOWTO(R_390_32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, 115130561Sobrien bfd_elf_generic_reloc, "R_390_32", FALSE, 0,0xffffffff, FALSE), 116130561Sobrien HOWTO(R_390_PC32, 0, 2, 32, TRUE, 0, complain_overflow_bitfield, 117130561Sobrien bfd_elf_generic_reloc, "R_390_PC32", FALSE, 0,0xffffffff, TRUE), 118130561Sobrien HOWTO(R_390_GOT12, 0, 1, 12, FALSE, 0, complain_overflow_bitfield, 119130561Sobrien bfd_elf_generic_reloc, "R_390_GOT12", FALSE, 0,0x00000fff, FALSE), 120130561Sobrien HOWTO(R_390_GOT32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, 121130561Sobrien bfd_elf_generic_reloc, "R_390_GOT32", FALSE, 0,0xffffffff, FALSE), 122130561Sobrien HOWTO(R_390_PLT32, 0, 2, 32, TRUE, 0, complain_overflow_bitfield, 123130561Sobrien bfd_elf_generic_reloc, "R_390_PLT32", FALSE, 0,0xffffffff, TRUE), 124130561Sobrien HOWTO(R_390_COPY, 0, 4, 64, FALSE, 0, complain_overflow_bitfield, 125130561Sobrien bfd_elf_generic_reloc, "R_390_COPY", FALSE, 0,MINUS_ONE, FALSE), 126130561Sobrien HOWTO(R_390_GLOB_DAT, 0, 4, 64, FALSE, 0, complain_overflow_bitfield, 127130561Sobrien bfd_elf_generic_reloc, "R_390_GLOB_DAT", FALSE, 0,MINUS_ONE, FALSE), 128130561Sobrien HOWTO(R_390_JMP_SLOT, 0, 4, 64, FALSE, 0, complain_overflow_bitfield, 129130561Sobrien bfd_elf_generic_reloc, "R_390_JMP_SLOT", FALSE, 0,MINUS_ONE, FALSE), 130130561Sobrien HOWTO(R_390_RELATIVE, 0, 4, 64, TRUE, 0, complain_overflow_bitfield, 131130561Sobrien bfd_elf_generic_reloc, "R_390_RELATIVE", FALSE, 0,MINUS_ONE, FALSE), 132130561Sobrien HOWTO(R_390_GOTOFF32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, 133130561Sobrien bfd_elf_generic_reloc, "R_390_GOTOFF32", FALSE, 0,MINUS_ONE, FALSE), 134130561Sobrien HOWTO(R_390_GOTPC, 0, 4, 64, TRUE, 0, complain_overflow_bitfield, 135130561Sobrien bfd_elf_generic_reloc, "R_390_GOTPC", FALSE, 0,MINUS_ONE, TRUE), 136130561Sobrien HOWTO(R_390_GOT16, 0, 1, 16, FALSE, 0, complain_overflow_bitfield, 137130561Sobrien bfd_elf_generic_reloc, "R_390_GOT16", FALSE, 0,0x0000ffff, FALSE), 138130561Sobrien HOWTO(R_390_PC16, 0, 1, 16, TRUE, 0, complain_overflow_bitfield, 139130561Sobrien bfd_elf_generic_reloc, "R_390_PC16", FALSE, 0,0x0000ffff, TRUE), 140130561Sobrien HOWTO(R_390_PC16DBL, 1, 1, 16, TRUE, 0, complain_overflow_bitfield, 141130561Sobrien bfd_elf_generic_reloc, "R_390_PC16DBL", FALSE, 0,0x0000ffff, TRUE), 142130561Sobrien HOWTO(R_390_PLT16DBL, 1, 1, 16, TRUE, 0, complain_overflow_bitfield, 143130561Sobrien bfd_elf_generic_reloc, "R_390_PLT16DBL", FALSE, 0,0x0000ffff, TRUE), 144130561Sobrien HOWTO(R_390_PC32DBL, 1, 2, 32, TRUE, 0, complain_overflow_bitfield, 145130561Sobrien bfd_elf_generic_reloc, "R_390_PC32DBL", FALSE, 0,0xffffffff, TRUE), 146130561Sobrien HOWTO(R_390_PLT32DBL, 1, 2, 32, TRUE, 0, complain_overflow_bitfield, 147130561Sobrien bfd_elf_generic_reloc, "R_390_PLT32DBL", FALSE, 0,0xffffffff, TRUE), 148130561Sobrien HOWTO(R_390_GOTPCDBL, 1, 2, 32, TRUE, 0, complain_overflow_bitfield, 149130561Sobrien bfd_elf_generic_reloc, "R_390_GOTPCDBL", FALSE, 0,MINUS_ONE, TRUE), 150130561Sobrien HOWTO(R_390_64, 0, 4, 64, FALSE, 0, complain_overflow_bitfield, 151130561Sobrien bfd_elf_generic_reloc, "R_390_64", FALSE, 0,MINUS_ONE, FALSE), 152130561Sobrien HOWTO(R_390_PC64, 0, 4, 64, TRUE, 0, complain_overflow_bitfield, 153130561Sobrien bfd_elf_generic_reloc, "R_390_PC64", FALSE, 0,MINUS_ONE, TRUE), 154130561Sobrien HOWTO(R_390_GOT64, 0, 4, 64, FALSE, 0, complain_overflow_bitfield, 155130561Sobrien bfd_elf_generic_reloc, "R_390_GOT64", FALSE, 0,MINUS_ONE, FALSE), 156130561Sobrien HOWTO(R_390_PLT64, 0, 4, 64, TRUE, 0, complain_overflow_bitfield, 157130561Sobrien bfd_elf_generic_reloc, "R_390_PLT64", FALSE, 0,MINUS_ONE, TRUE), 158130561Sobrien HOWTO(R_390_GOTENT, 1, 2, 32, TRUE, 0, complain_overflow_bitfield, 159130561Sobrien bfd_elf_generic_reloc, "R_390_GOTENT", FALSE, 0,MINUS_ONE, TRUE), 160130561Sobrien HOWTO(R_390_GOTOFF16, 0, 1, 16, FALSE, 0, complain_overflow_bitfield, 161130561Sobrien bfd_elf_generic_reloc, "R_390_GOTOFF16", FALSE, 0,0x0000ffff, FALSE), 162130561Sobrien HOWTO(R_390_GOTOFF64, 0, 4, 64, FALSE, 0, complain_overflow_bitfield, 163130561Sobrien bfd_elf_generic_reloc, "R_390_GOTOFF64", FALSE, 0,MINUS_ONE, FALSE), 164130561Sobrien HOWTO(R_390_GOTPLT12, 0, 1, 12, FALSE, 0, complain_overflow_dont, 165130561Sobrien bfd_elf_generic_reloc, "R_390_GOTPLT12", FALSE, 0,0x00000fff, FALSE), 166130561Sobrien HOWTO(R_390_GOTPLT16, 0, 1, 16, FALSE, 0, complain_overflow_bitfield, 167130561Sobrien bfd_elf_generic_reloc, "R_390_GOTPLT16", FALSE, 0,0x0000ffff, FALSE), 168130561Sobrien HOWTO(R_390_GOTPLT32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, 169130561Sobrien bfd_elf_generic_reloc, "R_390_GOTPLT32", FALSE, 0,0xffffffff, FALSE), 170130561Sobrien HOWTO(R_390_GOTPLT64, 0, 4, 64, FALSE, 0, complain_overflow_bitfield, 171130561Sobrien bfd_elf_generic_reloc, "R_390_GOTPLT64", FALSE, 0,MINUS_ONE, FALSE), 172130561Sobrien HOWTO(R_390_GOTPLTENT, 1, 2, 32, TRUE, 0, complain_overflow_bitfield, 173130561Sobrien bfd_elf_generic_reloc, "R_390_GOTPLTENT",FALSE, 0,MINUS_ONE, TRUE), 174130561Sobrien HOWTO(R_390_PLTOFF16, 0, 1, 16, FALSE, 0, complain_overflow_bitfield, 175130561Sobrien bfd_elf_generic_reloc, "R_390_PLTOFF16", FALSE, 0,0x0000ffff, FALSE), 176130561Sobrien HOWTO(R_390_PLTOFF32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, 177130561Sobrien bfd_elf_generic_reloc, "R_390_PLTOFF32", FALSE, 0,0xffffffff, FALSE), 178130561Sobrien HOWTO(R_390_PLTOFF64, 0, 4, 64, FALSE, 0, complain_overflow_bitfield, 179130561Sobrien bfd_elf_generic_reloc, "R_390_PLTOFF64", FALSE, 0,MINUS_ONE, FALSE), 180130561Sobrien HOWTO(R_390_TLS_LOAD, 0, 0, 0, FALSE, 0, complain_overflow_dont, 181130561Sobrien s390_tls_reloc, "R_390_TLS_LOAD", FALSE, 0, 0, FALSE), 182130561Sobrien HOWTO(R_390_TLS_GDCALL, 0, 0, 0, FALSE, 0, complain_overflow_dont, 183130561Sobrien s390_tls_reloc, "R_390_TLS_GDCALL", FALSE, 0, 0, FALSE), 184130561Sobrien HOWTO(R_390_TLS_LDCALL, 0, 0, 0, FALSE, 0, complain_overflow_dont, 185130561Sobrien s390_tls_reloc, "R_390_TLS_LDCALL", FALSE, 0, 0, FALSE), 186130561Sobrien EMPTY_HOWTO (R_390_TLS_GD32), /* Empty entry for R_390_TLS_GD32. */ 187130561Sobrien HOWTO(R_390_TLS_GD64, 0, 4, 64, FALSE, 0, complain_overflow_bitfield, 188130561Sobrien bfd_elf_generic_reloc, "R_390_TLS_GD64", FALSE, 0, MINUS_ONE, FALSE), 189130561Sobrien HOWTO(R_390_TLS_GOTIE12, 0, 1, 12, FALSE, 0, complain_overflow_dont, 190130561Sobrien bfd_elf_generic_reloc, "R_390_TLS_GOTIE12", FALSE, 0, 0x00000fff, FALSE), 191130561Sobrien EMPTY_HOWTO (R_390_TLS_GOTIE32), /* Empty entry for R_390_TLS_GOTIE32. */ 192130561Sobrien HOWTO(R_390_TLS_GOTIE64, 0, 4, 64, FALSE, 0, complain_overflow_bitfield, 193130561Sobrien bfd_elf_generic_reloc, "R_390_TLS_GOTIE64", FALSE, 0, MINUS_ONE, FALSE), 194130561Sobrien EMPTY_HOWTO (R_390_TLS_LDM32), /* Empty entry for R_390_TLS_LDM32. */ 195130561Sobrien HOWTO(R_390_TLS_LDM64, 0, 4, 64, FALSE, 0, complain_overflow_bitfield, 196130561Sobrien bfd_elf_generic_reloc, "R_390_TLS_LDM64", FALSE, 0, MINUS_ONE, FALSE), 197130561Sobrien EMPTY_HOWTO (R_390_TLS_IE32), /* Empty entry for R_390_TLS_IE32. */ 198130561Sobrien HOWTO(R_390_TLS_IE64, 0, 4, 64, FALSE, 0, complain_overflow_bitfield, 199130561Sobrien bfd_elf_generic_reloc, "R_390_TLS_IE64", FALSE, 0, MINUS_ONE, FALSE), 200130561Sobrien HOWTO(R_390_TLS_IEENT, 1, 2, 32, TRUE, 0, complain_overflow_bitfield, 201130561Sobrien bfd_elf_generic_reloc, "R_390_TLS_IEENT", FALSE, 0, MINUS_ONE, TRUE), 202130561Sobrien EMPTY_HOWTO (R_390_TLS_LE32), /* Empty entry for R_390_TLS_LE32. */ 203130561Sobrien HOWTO(R_390_TLS_LE64, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, 204130561Sobrien bfd_elf_generic_reloc, "R_390_TLS_LE64", FALSE, 0, MINUS_ONE, FALSE), 205130561Sobrien EMPTY_HOWTO (R_390_TLS_LDO32), /* Empty entry for R_390_TLS_LDO32. */ 206130561Sobrien HOWTO(R_390_TLS_LDO64, 0, 4, 64, FALSE, 0, complain_overflow_bitfield, 207130561Sobrien bfd_elf_generic_reloc, "R_390_TLS_LDO64", FALSE, 0, MINUS_ONE, FALSE), 208130561Sobrien HOWTO(R_390_TLS_DTPMOD, 0, 4, 64, FALSE, 0, complain_overflow_bitfield, 209130561Sobrien bfd_elf_generic_reloc, "R_390_TLS_DTPMOD", FALSE, 0, MINUS_ONE, FALSE), 210130561Sobrien HOWTO(R_390_TLS_DTPOFF, 0, 4, 64, FALSE, 0, complain_overflow_bitfield, 211130561Sobrien bfd_elf_generic_reloc, "R_390_TLS_DTPOFF", FALSE, 0, MINUS_ONE, FALSE), 212130561Sobrien HOWTO(R_390_TLS_TPOFF, 0, 4, 64, FALSE, 0, complain_overflow_bitfield, 213130561Sobrien bfd_elf_generic_reloc, "R_390_TLS_TPOFF", FALSE, 0, MINUS_ONE, FALSE), 214130561Sobrien HOWTO(R_390_20, 0, 2, 20, FALSE, 8, complain_overflow_dont, 215130561Sobrien s390_elf_ldisp_reloc, "R_390_20", FALSE, 0,0x0fffff00, FALSE), 216130561Sobrien HOWTO(R_390_GOT20, 0, 2, 20, FALSE, 8, complain_overflow_dont, 217130561Sobrien s390_elf_ldisp_reloc, "R_390_GOT20", FALSE, 0,0x0fffff00, FALSE), 218130561Sobrien HOWTO(R_390_GOTPLT20, 0, 2, 20, FALSE, 8, complain_overflow_dont, 219130561Sobrien s390_elf_ldisp_reloc, "R_390_GOTPLT20", FALSE, 0,0x0fffff00, FALSE), 220130561Sobrien HOWTO(R_390_TLS_GOTIE20, 0, 2, 20, FALSE, 8, complain_overflow_dont, 221130561Sobrien s390_elf_ldisp_reloc, "R_390_TLS_GOTIE20", FALSE, 0,0x0fffff00, FALSE), 22299461Sobrien}; 22399461Sobrien 22499461Sobrien/* GNU extension to record C++ vtable hierarchy. */ 22599461Sobrienstatic reloc_howto_type elf64_s390_vtinherit_howto = 226130561Sobrien HOWTO (R_390_GNU_VTINHERIT, 0,4,0,FALSE,0,complain_overflow_dont, NULL, "R_390_GNU_VTINHERIT", FALSE,0, 0, FALSE); 22799461Sobrienstatic reloc_howto_type elf64_s390_vtentry_howto = 228130561Sobrien HOWTO (R_390_GNU_VTENTRY, 0,4,0,FALSE,0,complain_overflow_dont, _bfd_elf_rel_vtable_reloc_fn,"R_390_GNU_VTENTRY", FALSE,0,0, FALSE); 22999461Sobrien 23099461Sobrienstatic reloc_howto_type * 23199461Sobrienelf_s390_reloc_type_lookup (abfd, code) 23299461Sobrien bfd *abfd ATTRIBUTE_UNUSED; 23399461Sobrien bfd_reloc_code_real_type code; 23499461Sobrien{ 23599461Sobrien switch (code) 23699461Sobrien { 23799461Sobrien case BFD_RELOC_NONE: 23899461Sobrien return &elf_howto_table[(int) R_390_NONE]; 23999461Sobrien case BFD_RELOC_8: 24099461Sobrien return &elf_howto_table[(int) R_390_8]; 24199461Sobrien case BFD_RELOC_390_12: 24299461Sobrien return &elf_howto_table[(int) R_390_12]; 24399461Sobrien case BFD_RELOC_16: 24499461Sobrien return &elf_howto_table[(int) R_390_16]; 24599461Sobrien case BFD_RELOC_32: 24699461Sobrien return &elf_howto_table[(int) R_390_32]; 24799461Sobrien case BFD_RELOC_CTOR: 24899461Sobrien return &elf_howto_table[(int) R_390_32]; 24999461Sobrien case BFD_RELOC_32_PCREL: 25099461Sobrien return &elf_howto_table[(int) R_390_PC32]; 25199461Sobrien case BFD_RELOC_390_GOT12: 25299461Sobrien return &elf_howto_table[(int) R_390_GOT12]; 25399461Sobrien case BFD_RELOC_32_GOT_PCREL: 25499461Sobrien return &elf_howto_table[(int) R_390_GOT32]; 25599461Sobrien case BFD_RELOC_390_PLT32: 25699461Sobrien return &elf_howto_table[(int) R_390_PLT32]; 25799461Sobrien case BFD_RELOC_390_COPY: 25899461Sobrien return &elf_howto_table[(int) R_390_COPY]; 25999461Sobrien case BFD_RELOC_390_GLOB_DAT: 26099461Sobrien return &elf_howto_table[(int) R_390_GLOB_DAT]; 26199461Sobrien case BFD_RELOC_390_JMP_SLOT: 26299461Sobrien return &elf_howto_table[(int) R_390_JMP_SLOT]; 26399461Sobrien case BFD_RELOC_390_RELATIVE: 26499461Sobrien return &elf_howto_table[(int) R_390_RELATIVE]; 26599461Sobrien case BFD_RELOC_32_GOTOFF: 266130561Sobrien return &elf_howto_table[(int) R_390_GOTOFF32]; 26799461Sobrien case BFD_RELOC_390_GOTPC: 26899461Sobrien return &elf_howto_table[(int) R_390_GOTPC]; 26999461Sobrien case BFD_RELOC_390_GOT16: 27099461Sobrien return &elf_howto_table[(int) R_390_GOT16]; 27199461Sobrien case BFD_RELOC_16_PCREL: 27299461Sobrien return &elf_howto_table[(int) R_390_PC16]; 27399461Sobrien case BFD_RELOC_390_PC16DBL: 27499461Sobrien return &elf_howto_table[(int) R_390_PC16DBL]; 27599461Sobrien case BFD_RELOC_390_PLT16DBL: 27699461Sobrien return &elf_howto_table[(int) R_390_PLT16DBL]; 27799461Sobrien case BFD_RELOC_390_PC32DBL: 27899461Sobrien return &elf_howto_table[(int) R_390_PC32DBL]; 27999461Sobrien case BFD_RELOC_390_PLT32DBL: 28099461Sobrien return &elf_howto_table[(int) R_390_PLT32DBL]; 28199461Sobrien case BFD_RELOC_390_GOTPCDBL: 28299461Sobrien return &elf_howto_table[(int) R_390_GOTPCDBL]; 28399461Sobrien case BFD_RELOC_64: 28499461Sobrien return &elf_howto_table[(int) R_390_64]; 28599461Sobrien case BFD_RELOC_64_PCREL: 28699461Sobrien return &elf_howto_table[(int) R_390_PC64]; 28799461Sobrien case BFD_RELOC_390_GOT64: 28899461Sobrien return &elf_howto_table[(int) R_390_GOT64]; 28999461Sobrien case BFD_RELOC_390_PLT64: 29099461Sobrien return &elf_howto_table[(int) R_390_PLT64]; 29199461Sobrien case BFD_RELOC_390_GOTENT: 29299461Sobrien return &elf_howto_table[(int) R_390_GOTENT]; 293130561Sobrien case BFD_RELOC_16_GOTOFF: 294130561Sobrien return &elf_howto_table[(int) R_390_GOTOFF16]; 295130561Sobrien case BFD_RELOC_390_GOTOFF64: 296130561Sobrien return &elf_howto_table[(int) R_390_GOTOFF64]; 297130561Sobrien case BFD_RELOC_390_GOTPLT12: 298130561Sobrien return &elf_howto_table[(int) R_390_GOTPLT12]; 299130561Sobrien case BFD_RELOC_390_GOTPLT16: 300130561Sobrien return &elf_howto_table[(int) R_390_GOTPLT16]; 301130561Sobrien case BFD_RELOC_390_GOTPLT32: 302130561Sobrien return &elf_howto_table[(int) R_390_GOTPLT32]; 303130561Sobrien case BFD_RELOC_390_GOTPLT64: 304130561Sobrien return &elf_howto_table[(int) R_390_GOTPLT64]; 305130561Sobrien case BFD_RELOC_390_GOTPLTENT: 306130561Sobrien return &elf_howto_table[(int) R_390_GOTPLTENT]; 307130561Sobrien case BFD_RELOC_390_PLTOFF16: 308130561Sobrien return &elf_howto_table[(int) R_390_PLTOFF16]; 309130561Sobrien case BFD_RELOC_390_PLTOFF32: 310130561Sobrien return &elf_howto_table[(int) R_390_PLTOFF32]; 311130561Sobrien case BFD_RELOC_390_PLTOFF64: 312130561Sobrien return &elf_howto_table[(int) R_390_PLTOFF64]; 313130561Sobrien case BFD_RELOC_390_TLS_LOAD: 314130561Sobrien return &elf_howto_table[(int) R_390_TLS_LOAD]; 315130561Sobrien case BFD_RELOC_390_TLS_GDCALL: 316130561Sobrien return &elf_howto_table[(int) R_390_TLS_GDCALL]; 317130561Sobrien case BFD_RELOC_390_TLS_LDCALL: 318130561Sobrien return &elf_howto_table[(int) R_390_TLS_LDCALL]; 319130561Sobrien case BFD_RELOC_390_TLS_GD64: 320130561Sobrien return &elf_howto_table[(int) R_390_TLS_GD64]; 321130561Sobrien case BFD_RELOC_390_TLS_GOTIE12: 322130561Sobrien return &elf_howto_table[(int) R_390_TLS_GOTIE12]; 323130561Sobrien case BFD_RELOC_390_TLS_GOTIE64: 324130561Sobrien return &elf_howto_table[(int) R_390_TLS_GOTIE64]; 325130561Sobrien case BFD_RELOC_390_TLS_LDM64: 326130561Sobrien return &elf_howto_table[(int) R_390_TLS_LDM64]; 327130561Sobrien case BFD_RELOC_390_TLS_IE64: 328130561Sobrien return &elf_howto_table[(int) R_390_TLS_IE64]; 329130561Sobrien case BFD_RELOC_390_TLS_IEENT: 330130561Sobrien return &elf_howto_table[(int) R_390_TLS_IEENT]; 331130561Sobrien case BFD_RELOC_390_TLS_LE64: 332130561Sobrien return &elf_howto_table[(int) R_390_TLS_LE64]; 333130561Sobrien case BFD_RELOC_390_TLS_LDO64: 334130561Sobrien return &elf_howto_table[(int) R_390_TLS_LDO64]; 335130561Sobrien case BFD_RELOC_390_TLS_DTPMOD: 336130561Sobrien return &elf_howto_table[(int) R_390_TLS_DTPMOD]; 337130561Sobrien case BFD_RELOC_390_TLS_DTPOFF: 338130561Sobrien return &elf_howto_table[(int) R_390_TLS_DTPOFF]; 339130561Sobrien case BFD_RELOC_390_TLS_TPOFF: 340130561Sobrien return &elf_howto_table[(int) R_390_TLS_TPOFF]; 341130561Sobrien case BFD_RELOC_390_20: 342130561Sobrien return &elf_howto_table[(int) R_390_20]; 343130561Sobrien case BFD_RELOC_390_GOT20: 344130561Sobrien return &elf_howto_table[(int) R_390_GOT20]; 345130561Sobrien case BFD_RELOC_390_GOTPLT20: 346130561Sobrien return &elf_howto_table[(int) R_390_GOTPLT20]; 347130561Sobrien case BFD_RELOC_390_TLS_GOTIE20: 348130561Sobrien return &elf_howto_table[(int) R_390_TLS_GOTIE20]; 349130561Sobrien case BFD_RELOC_VTABLE_INHERIT: 350130561Sobrien return &elf64_s390_vtinherit_howto; 351130561Sobrien case BFD_RELOC_VTABLE_ENTRY: 352130561Sobrien return &elf64_s390_vtentry_howto; 35399461Sobrien default: 35499461Sobrien break; 35599461Sobrien } 35699461Sobrien return 0; 35799461Sobrien} 35899461Sobrien 359218822Sdimstatic reloc_howto_type * 360218822Sdimelf_s390_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, 361218822Sdim const char *r_name) 362218822Sdim{ 363218822Sdim unsigned int i; 364218822Sdim 365218822Sdim for (i = 0; 366218822Sdim i < sizeof (elf_howto_table) / sizeof (elf_howto_table[0]); 367218822Sdim i++) 368218822Sdim if (elf_howto_table[i].name != NULL 369218822Sdim && strcasecmp (elf_howto_table[i].name, r_name) == 0) 370218822Sdim return &elf_howto_table[i]; 371218822Sdim 372218822Sdim if (strcasecmp (elf64_s390_vtinherit_howto.name, r_name) == 0) 373218822Sdim return &elf64_s390_vtinherit_howto; 374218822Sdim if (strcasecmp (elf64_s390_vtentry_howto.name, r_name) == 0) 375218822Sdim return &elf64_s390_vtentry_howto; 376218822Sdim 377218822Sdim return NULL; 378218822Sdim} 379218822Sdim 38099461Sobrien/* We need to use ELF64_R_TYPE so we have our own copy of this function, 38199461Sobrien and elf64-s390.c has its own copy. */ 38299461Sobrien 38399461Sobrienstatic void 38499461Sobrienelf_s390_info_to_howto (abfd, cache_ptr, dst) 38599461Sobrien bfd *abfd ATTRIBUTE_UNUSED; 38699461Sobrien arelent *cache_ptr; 38799461Sobrien Elf_Internal_Rela *dst; 38899461Sobrien{ 389218822Sdim unsigned int r_type = ELF64_R_TYPE(dst->r_info); 390218822Sdim switch (r_type) 39199461Sobrien { 39299461Sobrien case R_390_GNU_VTINHERIT: 39399461Sobrien cache_ptr->howto = &elf64_s390_vtinherit_howto; 39499461Sobrien break; 39599461Sobrien 39699461Sobrien case R_390_GNU_VTENTRY: 39799461Sobrien cache_ptr->howto = &elf64_s390_vtentry_howto; 39899461Sobrien break; 39999461Sobrien 40099461Sobrien default: 401218822Sdim if (r_type >= sizeof (elf_howto_table) / sizeof (elf_howto_table[0])) 402218822Sdim { 403218822Sdim (*_bfd_error_handler) (_("%B: invalid relocation type %d"), 404218822Sdim abfd, (int) r_type); 405218822Sdim r_type = R_390_NONE; 406218822Sdim } 407218822Sdim cache_ptr->howto = &elf_howto_table[r_type]; 40899461Sobrien } 40999461Sobrien} 41099461Sobrien 411130561Sobrien/* A relocation function which doesn't do anything. */ 412130561Sobrienstatic bfd_reloc_status_type 413130561Sobriens390_tls_reloc (abfd, reloc_entry, symbol, data, input_section, 414130561Sobrien output_bfd, error_message) 415130561Sobrien bfd *abfd ATTRIBUTE_UNUSED; 416130561Sobrien arelent *reloc_entry; 417130561Sobrien asymbol *symbol ATTRIBUTE_UNUSED; 418130561Sobrien PTR data ATTRIBUTE_UNUSED; 419130561Sobrien asection *input_section; 420130561Sobrien bfd *output_bfd; 421130561Sobrien char **error_message ATTRIBUTE_UNUSED; 422130561Sobrien{ 423130561Sobrien if (output_bfd) 424130561Sobrien reloc_entry->address += input_section->output_offset; 425130561Sobrien return bfd_reloc_ok; 426130561Sobrien} 427130561Sobrien 428130561Sobrien/* Handle the large displacement relocs. */ 429130561Sobrienstatic bfd_reloc_status_type 430130561Sobriens390_elf_ldisp_reloc (abfd, reloc_entry, symbol, data, input_section, 431130561Sobrien output_bfd, error_message) 432130561Sobrien bfd *abfd; 433130561Sobrien arelent *reloc_entry; 434130561Sobrien asymbol *symbol; 435130561Sobrien PTR data; 436130561Sobrien asection *input_section; 437130561Sobrien bfd *output_bfd; 438130561Sobrien char **error_message ATTRIBUTE_UNUSED; 439130561Sobrien{ 440130561Sobrien reloc_howto_type *howto = reloc_entry->howto; 441130561Sobrien bfd_vma relocation; 442130561Sobrien bfd_vma insn; 443130561Sobrien 444130561Sobrien if (output_bfd != (bfd *) NULL 445130561Sobrien && (symbol->flags & BSF_SECTION_SYM) == 0 446130561Sobrien && (! howto->partial_inplace 447130561Sobrien || reloc_entry->addend == 0)) 448130561Sobrien { 449130561Sobrien reloc_entry->address += input_section->output_offset; 450130561Sobrien return bfd_reloc_ok; 451130561Sobrien } 452130561Sobrien if (output_bfd != NULL) 453130561Sobrien return bfd_reloc_continue; 454130561Sobrien 455218822Sdim if (reloc_entry->address > bfd_get_section_limit (abfd, input_section)) 456130561Sobrien return bfd_reloc_outofrange; 457130561Sobrien 458130561Sobrien relocation = (symbol->value 459130561Sobrien + symbol->section->output_section->vma 460130561Sobrien + symbol->section->output_offset); 461130561Sobrien relocation += reloc_entry->addend; 462130561Sobrien if (howto->pc_relative) 463130561Sobrien { 464130561Sobrien relocation -= (input_section->output_section->vma 465130561Sobrien + input_section->output_offset); 466130561Sobrien relocation -= reloc_entry->address; 467130561Sobrien } 468130561Sobrien 469130561Sobrien insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address); 470130561Sobrien insn |= (relocation & 0xfff) << 16 | (relocation & 0xff000) >> 4; 471130561Sobrien bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc_entry->address); 472130561Sobrien 473130561Sobrien if ((bfd_signed_vma) relocation < - 0x80000 474130561Sobrien || (bfd_signed_vma) relocation > 0x7ffff) 475130561Sobrien return bfd_reloc_overflow; 476130561Sobrien else 477130561Sobrien return bfd_reloc_ok; 478130561Sobrien} 479130561Sobrien 480130561Sobrienstatic bfd_boolean 48199461Sobrienelf_s390_is_local_label_name (abfd, name) 48299461Sobrien bfd *abfd; 48399461Sobrien const char *name; 48499461Sobrien{ 48599461Sobrien if (name[0] == '.' && (name[1] == 'X' || name[1] == 'L')) 486130561Sobrien return TRUE; 48799461Sobrien 48899461Sobrien return _bfd_elf_is_local_label_name (abfd, name); 48999461Sobrien} 49099461Sobrien 49199461Sobrien/* Functions for the 390 ELF linker. */ 49299461Sobrien 49399461Sobrien/* The name of the dynamic interpreter. This is put in the .interp 49499461Sobrien section. */ 49599461Sobrien 49699461Sobrien#define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1" 49799461Sobrien 498130561Sobrien/* If ELIMINATE_COPY_RELOCS is non-zero, the linker will try to avoid 499130561Sobrien copying dynamic variables from a shared lib into an app's dynbss 500130561Sobrien section, and instead use a dynamic relocation to point into the 501130561Sobrien shared lib. */ 502130561Sobrien#define ELIMINATE_COPY_RELOCS 1 503130561Sobrien 50499461Sobrien/* The size in bytes of the first entry in the procedure linkage table. */ 50599461Sobrien#define PLT_FIRST_ENTRY_SIZE 32 50699461Sobrien/* The size in bytes of an entry in the procedure linkage table. */ 50799461Sobrien#define PLT_ENTRY_SIZE 32 50899461Sobrien 50999461Sobrien#define GOT_ENTRY_SIZE 8 51099461Sobrien 51199461Sobrien/* The first three entries in a procedure linkage table are reserved, 51299461Sobrien and the initial contents are unimportant (we zero them out). 51399461Sobrien Subsequent entries look like this. See the SVR4 ABI 386 51499461Sobrien supplement to see how this works. */ 51599461Sobrien 51699461Sobrien/* For the s390, simple addr offset can only be 0 - 4096. 51799461Sobrien To use the full 16777216 TB address space, several instructions 51899461Sobrien are needed to load an address in a register and execute 51999461Sobrien a branch( or just saving the address) 52099461Sobrien 52199461Sobrien Furthermore, only r 0 and 1 are free to use!!! */ 52299461Sobrien 52399461Sobrien/* The first 3 words in the GOT are then reserved. 52499461Sobrien Word 0 is the address of the dynamic table. 52599461Sobrien Word 1 is a pointer to a structure describing the object 52699461Sobrien Word 2 is used to point to the loader entry address. 52799461Sobrien 52899461Sobrien The code for PLT entries looks like this: 52999461Sobrien 53099461Sobrien The GOT holds the address in the PLT to be executed. 53199461Sobrien The loader then gets: 53299461Sobrien 24(15) = Pointer to the structure describing the object. 53399461Sobrien 28(15) = Offset in symbol table 53499461Sobrien The loader must then find the module where the function is 53599461Sobrien and insert the address in the GOT. 53699461Sobrien 53799461Sobrien PLT1: LARL 1,<fn>@GOTENT # 6 bytes Load address of GOT entry in r1 53899461Sobrien LG 1,0(1) # 6 bytes Load address from GOT in r1 53999461Sobrien BCR 15,1 # 2 bytes Jump to address 54099461Sobrien RET1: BASR 1,0 # 2 bytes Return from GOT 1st time 54199461Sobrien LGF 1,12(1) # 6 bytes Load offset in symbl table in r1 54299461Sobrien BRCL 15,-x # 6 bytes Jump to start of PLT 54399461Sobrien .long ? # 4 bytes offset into symbol table 54499461Sobrien 54599461Sobrien Total = 32 bytes per PLT entry 54699461Sobrien Fixup at offset 2: relative address to GOT entry 54799461Sobrien Fixup at offset 22: relative branch to PLT0 54899461Sobrien Fixup at offset 28: 32 bit offset into symbol table 54999461Sobrien 55099461Sobrien A 32 bit offset into the symbol table is enough. It allows for symbol 55199461Sobrien tables up to a size of 2 gigabyte. A single dynamic object (the main 55299461Sobrien program, any shared library) is limited to 4GB in size and I want to see 55399461Sobrien the program that manages to have a symbol table of more than 2 GB with a 55499461Sobrien total size of at max 4 GB. */ 55599461Sobrien 55699461Sobrien#define PLT_ENTRY_WORD0 (bfd_vma) 0xc0100000 55799461Sobrien#define PLT_ENTRY_WORD1 (bfd_vma) 0x0000e310 55899461Sobrien#define PLT_ENTRY_WORD2 (bfd_vma) 0x10000004 55999461Sobrien#define PLT_ENTRY_WORD3 (bfd_vma) 0x07f10d10 56099461Sobrien#define PLT_ENTRY_WORD4 (bfd_vma) 0xe310100c 56199461Sobrien#define PLT_ENTRY_WORD5 (bfd_vma) 0x0014c0f4 56299461Sobrien#define PLT_ENTRY_WORD6 (bfd_vma) 0x00000000 56399461Sobrien#define PLT_ENTRY_WORD7 (bfd_vma) 0x00000000 56499461Sobrien 56599461Sobrien/* The first PLT entry pushes the offset into the symbol table 56699461Sobrien from R1 onto the stack at 8(15) and the loader object info 56799461Sobrien at 12(15), loads the loader address in R1 and jumps to it. */ 56899461Sobrien 56999461Sobrien/* The first entry in the PLT: 57099461Sobrien 57199461Sobrien PLT0: 57299461Sobrien STG 1,56(15) # r1 contains the offset into the symbol table 57399461Sobrien LARL 1,_GLOBAL_OFFSET_TABLE # load address of global offset table 57499461Sobrien MVC 48(8,15),8(1) # move loader ino (object struct address) to stack 57599461Sobrien LG 1,16(1) # get entry address of loader 57699461Sobrien BCR 15,1 # jump to loader 57799461Sobrien 57899461Sobrien Fixup at offset 8: relative address to start of GOT. */ 57999461Sobrien 58099461Sobrien#define PLT_FIRST_ENTRY_WORD0 (bfd_vma) 0xe310f038 58199461Sobrien#define PLT_FIRST_ENTRY_WORD1 (bfd_vma) 0x0024c010 58299461Sobrien#define PLT_FIRST_ENTRY_WORD2 (bfd_vma) 0x00000000 58399461Sobrien#define PLT_FIRST_ENTRY_WORD3 (bfd_vma) 0xd207f030 58499461Sobrien#define PLT_FIRST_ENTRY_WORD4 (bfd_vma) 0x1008e310 58599461Sobrien#define PLT_FIRST_ENTRY_WORD5 (bfd_vma) 0x10100004 58699461Sobrien#define PLT_FIRST_ENTRY_WORD6 (bfd_vma) 0x07f10700 58799461Sobrien#define PLT_FIRST_ENTRY_WORD7 (bfd_vma) 0x07000700 58899461Sobrien 58999461Sobrien/* The s390 linker needs to keep track of the number of relocs that it 59099461Sobrien decides to copy as dynamic relocs in check_relocs for each symbol. 59199461Sobrien This is so that it can later discard them if they are found to be 59299461Sobrien unnecessary. We store the information in a field extending the 59399461Sobrien regular ELF linker hash table. */ 59499461Sobrien 59599461Sobrienstruct elf_s390_dyn_relocs 59699461Sobrien{ 59799461Sobrien struct elf_s390_dyn_relocs *next; 59899461Sobrien 59999461Sobrien /* The input section of the reloc. */ 60099461Sobrien asection *sec; 60199461Sobrien 60299461Sobrien /* Total number of relocs copied for the input section. */ 60399461Sobrien bfd_size_type count; 60499461Sobrien 60599461Sobrien /* Number of pc-relative relocs copied for the input section. */ 60699461Sobrien bfd_size_type pc_count; 60799461Sobrien}; 60899461Sobrien 60999461Sobrien/* s390 ELF linker hash entry. */ 61099461Sobrien 61199461Sobrienstruct elf_s390_link_hash_entry 61299461Sobrien{ 61399461Sobrien struct elf_link_hash_entry elf; 61499461Sobrien 61599461Sobrien /* Track dynamic relocs copied for this symbol. */ 61699461Sobrien struct elf_s390_dyn_relocs *dyn_relocs; 617130561Sobrien 618130561Sobrien /* Number of GOTPLT references for a function. */ 619130561Sobrien bfd_signed_vma gotplt_refcount; 620130561Sobrien 621130561Sobrien#define GOT_UNKNOWN 0 622130561Sobrien#define GOT_NORMAL 1 623130561Sobrien#define GOT_TLS_GD 2 624130561Sobrien#define GOT_TLS_IE 3 625130561Sobrien#define GOT_TLS_IE_NLT 3 626130561Sobrien unsigned char tls_type; 62799461Sobrien}; 62899461Sobrien 629130561Sobrien#define elf_s390_hash_entry(ent) \ 630130561Sobrien ((struct elf_s390_link_hash_entry *)(ent)) 631130561Sobrien 632130561Sobrienstruct elf_s390_obj_tdata 633130561Sobrien{ 634130561Sobrien struct elf_obj_tdata root; 635130561Sobrien 636130561Sobrien /* tls_type for each local got entry. */ 637130561Sobrien char *local_got_tls_type; 638130561Sobrien}; 639130561Sobrien 640130561Sobrien#define elf_s390_tdata(abfd) \ 641130561Sobrien ((struct elf_s390_obj_tdata *) (abfd)->tdata.any) 642130561Sobrien 643130561Sobrien#define elf_s390_local_got_tls_type(abfd) \ 644130561Sobrien (elf_s390_tdata (abfd)->local_got_tls_type) 645130561Sobrien 646130561Sobrienstatic bfd_boolean 647218822Sdimelf_s390_mkobject (bfd *abfd) 648130561Sobrien{ 649130561Sobrien if (abfd->tdata.any == NULL) 650218822Sdim { 651218822Sdim bfd_size_type amt = sizeof (struct elf_s390_obj_tdata); 652218822Sdim abfd->tdata.any = bfd_zalloc (abfd, amt); 653218822Sdim if (abfd->tdata.any == NULL) 654218822Sdim return FALSE; 655218822Sdim } 656218822Sdim return bfd_elf_mkobject (abfd); 657130561Sobrien} 658130561Sobrien 659130561Sobrienstatic bfd_boolean 660130561Sobrienelf_s390_object_p (abfd) 661130561Sobrien bfd *abfd; 662130561Sobrien{ 663130561Sobrien /* Set the right machine number for an s390 elf32 file. */ 664130561Sobrien return bfd_default_set_arch_mach (abfd, bfd_arch_s390, bfd_mach_s390_64); 665130561Sobrien} 666130561Sobrien 66799461Sobrien/* s390 ELF linker hash table. */ 66899461Sobrien 66999461Sobrienstruct elf_s390_link_hash_table 67099461Sobrien{ 67199461Sobrien struct elf_link_hash_table elf; 67299461Sobrien 67399461Sobrien /* Short-cuts to get to dynamic linker sections. */ 67499461Sobrien asection *sgot; 67599461Sobrien asection *sgotplt; 67699461Sobrien asection *srelgot; 67799461Sobrien asection *splt; 67899461Sobrien asection *srelplt; 67999461Sobrien asection *sdynbss; 68099461Sobrien asection *srelbss; 68199461Sobrien 682130561Sobrien union { 683130561Sobrien bfd_signed_vma refcount; 684130561Sobrien bfd_vma offset; 685130561Sobrien } tls_ldm_got; 686130561Sobrien 68799461Sobrien /* Small local sym to section mapping cache. */ 68899461Sobrien struct sym_sec_cache sym_sec; 68999461Sobrien}; 69099461Sobrien 69199461Sobrien/* Get the s390 ELF linker hash table from a link_info structure. */ 69299461Sobrien 69399461Sobrien#define elf_s390_hash_table(p) \ 69499461Sobrien ((struct elf_s390_link_hash_table *) ((p)->hash)) 69599461Sobrien 69699461Sobrien/* Create an entry in an s390 ELF linker hash table. */ 69799461Sobrien 69899461Sobrienstatic struct bfd_hash_entry * 69999461Sobrienlink_hash_newfunc (entry, table, string) 70099461Sobrien struct bfd_hash_entry *entry; 70199461Sobrien struct bfd_hash_table *table; 70299461Sobrien const char *string; 70399461Sobrien{ 70499461Sobrien /* Allocate the structure if it has not already been allocated by a 70599461Sobrien subclass. */ 70699461Sobrien if (entry == NULL) 70799461Sobrien { 70899461Sobrien entry = bfd_hash_allocate (table, 70999461Sobrien sizeof (struct elf_s390_link_hash_entry)); 71099461Sobrien if (entry == NULL) 71199461Sobrien return entry; 71299461Sobrien } 71399461Sobrien 71499461Sobrien /* Call the allocation method of the superclass. */ 71599461Sobrien entry = _bfd_elf_link_hash_newfunc (entry, table, string); 71699461Sobrien if (entry != NULL) 71799461Sobrien { 71899461Sobrien struct elf_s390_link_hash_entry *eh; 71999461Sobrien 72099461Sobrien eh = (struct elf_s390_link_hash_entry *) entry; 72199461Sobrien eh->dyn_relocs = NULL; 722130561Sobrien eh->gotplt_refcount = 0; 723130561Sobrien eh->tls_type = GOT_UNKNOWN; 72499461Sobrien } 72599461Sobrien 72699461Sobrien return entry; 72799461Sobrien} 72899461Sobrien 72999461Sobrien/* Create an s390 ELF linker hash table. */ 73099461Sobrien 73199461Sobrienstatic struct bfd_link_hash_table * 73299461Sobrienelf_s390_link_hash_table_create (abfd) 73399461Sobrien bfd *abfd; 73499461Sobrien{ 73599461Sobrien struct elf_s390_link_hash_table *ret; 73699461Sobrien bfd_size_type amt = sizeof (struct elf_s390_link_hash_table); 73799461Sobrien 738107492Sobrien ret = (struct elf_s390_link_hash_table *) bfd_malloc (amt); 73999461Sobrien if (ret == NULL) 74099461Sobrien return NULL; 74199461Sobrien 742218822Sdim if (!_bfd_elf_link_hash_table_init (&ret->elf, abfd, link_hash_newfunc, 743218822Sdim sizeof (struct elf_s390_link_hash_entry))) 74499461Sobrien { 745107492Sobrien free (ret); 74699461Sobrien return NULL; 74799461Sobrien } 74899461Sobrien 74999461Sobrien ret->sgot = NULL; 75099461Sobrien ret->sgotplt = NULL; 75199461Sobrien ret->srelgot = NULL; 75299461Sobrien ret->splt = NULL; 75399461Sobrien ret->srelplt = NULL; 75499461Sobrien ret->sdynbss = NULL; 75599461Sobrien ret->srelbss = NULL; 756130561Sobrien ret->tls_ldm_got.refcount = 0; 75799461Sobrien ret->sym_sec.abfd = NULL; 75899461Sobrien 75999461Sobrien return &ret->elf.root; 76099461Sobrien} 76199461Sobrien 76299461Sobrien/* Create .got, .gotplt, and .rela.got sections in DYNOBJ, and set up 76399461Sobrien shortcuts to them in our hash table. */ 76499461Sobrien 765130561Sobrienstatic bfd_boolean 76699461Sobriencreate_got_section (dynobj, info) 76799461Sobrien bfd *dynobj; 76899461Sobrien struct bfd_link_info *info; 76999461Sobrien{ 77099461Sobrien struct elf_s390_link_hash_table *htab; 77199461Sobrien 77299461Sobrien if (! _bfd_elf_create_got_section (dynobj, info)) 773130561Sobrien return FALSE; 77499461Sobrien 77599461Sobrien htab = elf_s390_hash_table (info); 77699461Sobrien htab->sgot = bfd_get_section_by_name (dynobj, ".got"); 77799461Sobrien htab->sgotplt = bfd_get_section_by_name (dynobj, ".got.plt"); 77899461Sobrien if (!htab->sgot || !htab->sgotplt) 77999461Sobrien abort (); 78099461Sobrien 781218822Sdim htab->srelgot = bfd_make_section_with_flags (dynobj, ".rela.got", 782218822Sdim (SEC_ALLOC | SEC_LOAD 783218822Sdim | SEC_HAS_CONTENTS 784218822Sdim | SEC_IN_MEMORY 785218822Sdim | SEC_LINKER_CREATED 786218822Sdim | SEC_READONLY)); 78799461Sobrien if (htab->srelgot == NULL 788107492Sobrien || ! bfd_set_section_alignment (dynobj, htab->srelgot, 3)) 789130561Sobrien return FALSE; 790130561Sobrien return TRUE; 79199461Sobrien} 79299461Sobrien 79399461Sobrien/* Create .plt, .rela.plt, .got, .got.plt, .rela.got, .dynbss, and 79499461Sobrien .rela.bss sections in DYNOBJ, and set up shortcuts to them in our 79599461Sobrien hash table. */ 79699461Sobrien 797130561Sobrienstatic bfd_boolean 79899461Sobrienelf_s390_create_dynamic_sections (dynobj, info) 79999461Sobrien bfd *dynobj; 80099461Sobrien struct bfd_link_info *info; 80199461Sobrien{ 80299461Sobrien struct elf_s390_link_hash_table *htab; 80399461Sobrien 80499461Sobrien htab = elf_s390_hash_table (info); 80599461Sobrien if (!htab->sgot && !create_got_section (dynobj, info)) 806130561Sobrien return FALSE; 80799461Sobrien 80899461Sobrien if (!_bfd_elf_create_dynamic_sections (dynobj, info)) 809130561Sobrien return FALSE; 81099461Sobrien 81199461Sobrien htab->splt = bfd_get_section_by_name (dynobj, ".plt"); 81299461Sobrien htab->srelplt = bfd_get_section_by_name (dynobj, ".rela.plt"); 81399461Sobrien htab->sdynbss = bfd_get_section_by_name (dynobj, ".dynbss"); 81499461Sobrien if (!info->shared) 81599461Sobrien htab->srelbss = bfd_get_section_by_name (dynobj, ".rela.bss"); 81699461Sobrien 81799461Sobrien if (!htab->splt || !htab->srelplt || !htab->sdynbss 81899461Sobrien || (!info->shared && !htab->srelbss)) 81999461Sobrien abort (); 82099461Sobrien 821130561Sobrien return TRUE; 82299461Sobrien} 82399461Sobrien 82499461Sobrien/* Copy the extra info we tack onto an elf_link_hash_entry. */ 82599461Sobrien 82699461Sobrienstatic void 827218822Sdimelf_s390_copy_indirect_symbol (info, dir, ind) 828218822Sdim struct bfd_link_info *info; 82999461Sobrien struct elf_link_hash_entry *dir, *ind; 83099461Sobrien{ 83199461Sobrien struct elf_s390_link_hash_entry *edir, *eind; 83299461Sobrien 83399461Sobrien edir = (struct elf_s390_link_hash_entry *) dir; 83499461Sobrien eind = (struct elf_s390_link_hash_entry *) ind; 83599461Sobrien 83699461Sobrien if (eind->dyn_relocs != NULL) 83799461Sobrien { 83899461Sobrien if (edir->dyn_relocs != NULL) 83999461Sobrien { 84099461Sobrien struct elf_s390_dyn_relocs **pp; 84199461Sobrien struct elf_s390_dyn_relocs *p; 84299461Sobrien 843218822Sdim /* Add reloc counts against the indirect sym to the direct sym 84499461Sobrien list. Merge any entries against the same section. */ 84599461Sobrien for (pp = &eind->dyn_relocs; (p = *pp) != NULL; ) 84699461Sobrien { 84799461Sobrien struct elf_s390_dyn_relocs *q; 84899461Sobrien 84999461Sobrien for (q = edir->dyn_relocs; q != NULL; q = q->next) 85099461Sobrien if (q->sec == p->sec) 85199461Sobrien { 85299461Sobrien q->pc_count += p->pc_count; 85399461Sobrien q->count += p->count; 85499461Sobrien *pp = p->next; 85599461Sobrien break; 85699461Sobrien } 85799461Sobrien if (q == NULL) 85899461Sobrien pp = &p->next; 85999461Sobrien } 86099461Sobrien *pp = edir->dyn_relocs; 86199461Sobrien } 86299461Sobrien 86399461Sobrien edir->dyn_relocs = eind->dyn_relocs; 86499461Sobrien eind->dyn_relocs = NULL; 86599461Sobrien } 86699461Sobrien 867130561Sobrien if (ind->root.type == bfd_link_hash_indirect 868130561Sobrien && dir->got.refcount <= 0) 869130561Sobrien { 870130561Sobrien edir->tls_type = eind->tls_type; 871130561Sobrien eind->tls_type = GOT_UNKNOWN; 872130561Sobrien } 873130561Sobrien 874130561Sobrien if (ELIMINATE_COPY_RELOCS 875130561Sobrien && ind->root.type != bfd_link_hash_indirect 876218822Sdim && dir->dynamic_adjusted) 877218822Sdim { 878218822Sdim /* If called to transfer flags for a weakdef during processing 879218822Sdim of elf_adjust_dynamic_symbol, don't copy non_got_ref. 880218822Sdim We clear it ourselves for ELIMINATE_COPY_RELOCS. */ 881218822Sdim dir->ref_dynamic |= ind->ref_dynamic; 882218822Sdim dir->ref_regular |= ind->ref_regular; 883218822Sdim dir->ref_regular_nonweak |= ind->ref_regular_nonweak; 884218822Sdim dir->needs_plt |= ind->needs_plt; 885218822Sdim } 886130561Sobrien else 887218822Sdim _bfd_elf_link_hash_copy_indirect (info, dir, ind); 88899461Sobrien} 88999461Sobrien 890130561Sobrienstatic int 891130561Sobrienelf_s390_tls_transition (info, r_type, is_local) 892130561Sobrien struct bfd_link_info *info; 893130561Sobrien int r_type; 894130561Sobrien int is_local; 895130561Sobrien{ 896130561Sobrien if (info->shared) 897130561Sobrien return r_type; 898130561Sobrien 899130561Sobrien switch (r_type) 900130561Sobrien { 901130561Sobrien case R_390_TLS_GD64: 902130561Sobrien case R_390_TLS_IE64: 903130561Sobrien if (is_local) 904130561Sobrien return R_390_TLS_LE64; 905130561Sobrien return R_390_TLS_IE64; 906130561Sobrien case R_390_TLS_GOTIE64: 907130561Sobrien if (is_local) 908130561Sobrien return R_390_TLS_LE64; 909130561Sobrien return R_390_TLS_GOTIE64; 910130561Sobrien case R_390_TLS_LDM64: 911130561Sobrien return R_390_TLS_LE64; 912130561Sobrien } 913130561Sobrien 914130561Sobrien return r_type; 915130561Sobrien} 916130561Sobrien 91799461Sobrien/* Look through the relocs for a section during the first phase, and 91899461Sobrien allocate space in the global offset table or procedure linkage 91999461Sobrien table. */ 92099461Sobrien 921130561Sobrienstatic bfd_boolean 92299461Sobrienelf_s390_check_relocs (abfd, info, sec, relocs) 92399461Sobrien bfd *abfd; 92499461Sobrien struct bfd_link_info *info; 92599461Sobrien asection *sec; 92699461Sobrien const Elf_Internal_Rela *relocs; 92799461Sobrien{ 92899461Sobrien struct elf_s390_link_hash_table *htab; 92999461Sobrien Elf_Internal_Shdr *symtab_hdr; 93099461Sobrien struct elf_link_hash_entry **sym_hashes; 93199461Sobrien const Elf_Internal_Rela *rel; 93299461Sobrien const Elf_Internal_Rela *rel_end; 93399461Sobrien asection *sreloc; 934130561Sobrien bfd_signed_vma *local_got_refcounts; 935130561Sobrien int tls_type, old_tls_type; 93699461Sobrien 937130561Sobrien if (info->relocatable) 938130561Sobrien return TRUE; 93999461Sobrien 94099461Sobrien htab = elf_s390_hash_table (info); 94199461Sobrien symtab_hdr = &elf_tdata (abfd)->symtab_hdr; 94299461Sobrien sym_hashes = elf_sym_hashes (abfd); 943130561Sobrien local_got_refcounts = elf_local_got_refcounts (abfd); 94499461Sobrien 94599461Sobrien sreloc = NULL; 94699461Sobrien 94799461Sobrien rel_end = relocs + sec->reloc_count; 94899461Sobrien for (rel = relocs; rel < rel_end; rel++) 94999461Sobrien { 950130561Sobrien unsigned int r_type; 95199461Sobrien unsigned long r_symndx; 95299461Sobrien struct elf_link_hash_entry *h; 95399461Sobrien 95499461Sobrien r_symndx = ELF64_R_SYM (rel->r_info); 95599461Sobrien 95699461Sobrien if (r_symndx >= NUM_SHDR_ENTRIES (symtab_hdr)) 95799461Sobrien { 958218822Sdim (*_bfd_error_handler) (_("%B: bad symbol index: %d"), 959218822Sdim abfd, 96099461Sobrien r_symndx); 961130561Sobrien return FALSE; 96299461Sobrien } 96399461Sobrien 96499461Sobrien if (r_symndx < symtab_hdr->sh_info) 96599461Sobrien h = NULL; 96699461Sobrien else 967218822Sdim { 968218822Sdim h = sym_hashes[r_symndx - symtab_hdr->sh_info]; 969218822Sdim while (h->root.type == bfd_link_hash_indirect 970218822Sdim || h->root.type == bfd_link_hash_warning) 971218822Sdim h = (struct elf_link_hash_entry *) h->root.u.i.link; 972218822Sdim } 97399461Sobrien 974130561Sobrien /* Create got section and local_got_refcounts array if they 975130561Sobrien are needed. */ 976130561Sobrien r_type = elf_s390_tls_transition (info, 977130561Sobrien ELF64_R_TYPE (rel->r_info), 978130561Sobrien h == NULL); 979130561Sobrien switch (r_type) 98099461Sobrien { 98199461Sobrien case R_390_GOT12: 982130561Sobrien case R_390_GOT16: 983130561Sobrien case R_390_GOT20: 98499461Sobrien case R_390_GOT32: 98599461Sobrien case R_390_GOT64: 98699461Sobrien case R_390_GOTENT: 987130561Sobrien case R_390_GOTPLT12: 988130561Sobrien case R_390_GOTPLT16: 989130561Sobrien case R_390_GOTPLT20: 990130561Sobrien case R_390_GOTPLT32: 991130561Sobrien case R_390_GOTPLT64: 992130561Sobrien case R_390_GOTPLTENT: 993130561Sobrien case R_390_TLS_GD64: 994130561Sobrien case R_390_TLS_GOTIE12: 995130561Sobrien case R_390_TLS_GOTIE20: 996130561Sobrien case R_390_TLS_GOTIE64: 997130561Sobrien case R_390_TLS_IEENT: 998130561Sobrien case R_390_TLS_IE64: 999130561Sobrien case R_390_TLS_LDM64: 1000130561Sobrien if (h == NULL 1001130561Sobrien && local_got_refcounts == NULL) 100299461Sobrien { 1003130561Sobrien bfd_size_type size; 100499461Sobrien 1005130561Sobrien size = symtab_hdr->sh_info; 1006130561Sobrien size *= (sizeof (bfd_signed_vma) + sizeof(char)); 1007130561Sobrien local_got_refcounts = ((bfd_signed_vma *) 1008130561Sobrien bfd_zalloc (abfd, size)); 100999461Sobrien if (local_got_refcounts == NULL) 1010130561Sobrien return FALSE; 1011130561Sobrien elf_local_got_refcounts (abfd) = local_got_refcounts; 1012130561Sobrien elf_s390_local_got_tls_type (abfd) 1013130561Sobrien = (char *) (local_got_refcounts + symtab_hdr->sh_info); 101499461Sobrien } 1015130561Sobrien /* Fall through. */ 1016130561Sobrien case R_390_GOTOFF16: 1017130561Sobrien case R_390_GOTOFF32: 1018130561Sobrien case R_390_GOTOFF64: 101999461Sobrien case R_390_GOTPC: 102099461Sobrien case R_390_GOTPCDBL: 102199461Sobrien if (htab->sgot == NULL) 102299461Sobrien { 102399461Sobrien if (htab->elf.dynobj == NULL) 102499461Sobrien htab->elf.dynobj = abfd; 102599461Sobrien if (!create_got_section (htab->elf.dynobj, info)) 1026130561Sobrien return FALSE; 102799461Sobrien } 1028130561Sobrien } 1029130561Sobrien 1030130561Sobrien switch (r_type) 1031130561Sobrien { 1032130561Sobrien case R_390_GOTOFF16: 1033130561Sobrien case R_390_GOTOFF32: 1034130561Sobrien case R_390_GOTOFF64: 1035130561Sobrien case R_390_GOTPC: 1036130561Sobrien case R_390_GOTPCDBL: 1037130561Sobrien /* Got is created, nothing to be done. */ 103899461Sobrien break; 103999461Sobrien 1040130561Sobrien case R_390_PLT16DBL: 104199461Sobrien case R_390_PLT32: 104299461Sobrien case R_390_PLT32DBL: 104399461Sobrien case R_390_PLT64: 1044130561Sobrien case R_390_PLTOFF16: 1045130561Sobrien case R_390_PLTOFF32: 1046130561Sobrien case R_390_PLTOFF64: 104799461Sobrien /* This symbol requires a procedure linkage table entry. We 1048130561Sobrien actually build the entry in adjust_dynamic_symbol, 1049130561Sobrien because this might be a case of linking PIC code which is 1050130561Sobrien never referenced by a dynamic object, in which case we 1051130561Sobrien don't need to generate a procedure linkage table entry 1052130561Sobrien after all. */ 105399461Sobrien 105499461Sobrien /* If this is a local symbol, we resolve it directly without 1055130561Sobrien creating a procedure linkage table entry. */ 1056130561Sobrien if (h != NULL) 1057130561Sobrien { 1058218822Sdim h->needs_plt = 1; 1059130561Sobrien h->plt.refcount += 1; 1060130561Sobrien } 1061130561Sobrien break; 106299461Sobrien 1063130561Sobrien case R_390_GOTPLT12: 1064130561Sobrien case R_390_GOTPLT16: 1065130561Sobrien case R_390_GOTPLT20: 1066130561Sobrien case R_390_GOTPLT32: 1067130561Sobrien case R_390_GOTPLT64: 1068130561Sobrien case R_390_GOTPLTENT: 1069130561Sobrien /* This symbol requires either a procedure linkage table entry 1070130561Sobrien or an entry in the local got. We actually build the entry 1071130561Sobrien in adjust_dynamic_symbol because whether this is really a 1072130561Sobrien global reference can change and with it the fact if we have 1073130561Sobrien to create a plt entry or a local got entry. To be able to 1074130561Sobrien make a once global symbol a local one we have to keep track 1075130561Sobrien of the number of gotplt references that exist for this 1076130561Sobrien symbol. */ 1077130561Sobrien if (h != NULL) 1078130561Sobrien { 1079130561Sobrien ((struct elf_s390_link_hash_entry *) h)->gotplt_refcount++; 1080218822Sdim h->needs_plt = 1; 1081130561Sobrien h->plt.refcount += 1; 1082130561Sobrien } 1083130561Sobrien else 1084130561Sobrien local_got_refcounts[r_symndx] += 1; 108599461Sobrien break; 108699461Sobrien 1087130561Sobrien case R_390_TLS_LDM64: 1088130561Sobrien htab->tls_ldm_got.refcount += 1; 1089130561Sobrien break; 1090130561Sobrien 1091130561Sobrien case R_390_TLS_IE64: 1092130561Sobrien case R_390_TLS_GOTIE12: 1093130561Sobrien case R_390_TLS_GOTIE20: 1094130561Sobrien case R_390_TLS_GOTIE64: 1095130561Sobrien case R_390_TLS_IEENT: 1096130561Sobrien if (info->shared) 1097130561Sobrien info->flags |= DF_STATIC_TLS; 1098130561Sobrien /* Fall through */ 1099130561Sobrien 1100130561Sobrien case R_390_GOT12: 1101130561Sobrien case R_390_GOT16: 1102130561Sobrien case R_390_GOT20: 1103130561Sobrien case R_390_GOT32: 1104130561Sobrien case R_390_GOT64: 1105130561Sobrien case R_390_GOTENT: 1106130561Sobrien case R_390_TLS_GD64: 1107130561Sobrien /* This symbol requires a global offset table entry. */ 1108130561Sobrien switch (r_type) 1109130561Sobrien { 1110130561Sobrien default: 1111130561Sobrien case R_390_GOT12: 1112130561Sobrien case R_390_GOT16: 1113130561Sobrien case R_390_GOT20: 1114130561Sobrien case R_390_GOT32: 1115130561Sobrien case R_390_GOTENT: 1116130561Sobrien tls_type = GOT_NORMAL; 1117130561Sobrien break; 1118130561Sobrien case R_390_TLS_GD64: 1119130561Sobrien tls_type = GOT_TLS_GD; 1120130561Sobrien break; 1121130561Sobrien case R_390_TLS_IE64: 1122130561Sobrien case R_390_TLS_GOTIE64: 1123130561Sobrien tls_type = GOT_TLS_IE; 1124130561Sobrien break; 1125130561Sobrien case R_390_TLS_GOTIE12: 1126130561Sobrien case R_390_TLS_GOTIE20: 1127130561Sobrien case R_390_TLS_IEENT: 1128130561Sobrien tls_type = GOT_TLS_IE_NLT; 1129130561Sobrien break; 1130130561Sobrien } 1131130561Sobrien 1132130561Sobrien if (h != NULL) 1133130561Sobrien { 1134130561Sobrien h->got.refcount += 1; 1135130561Sobrien old_tls_type = elf_s390_hash_entry(h)->tls_type; 1136130561Sobrien } 1137130561Sobrien else 1138130561Sobrien { 1139130561Sobrien local_got_refcounts[r_symndx] += 1; 1140130561Sobrien old_tls_type = elf_s390_local_got_tls_type (abfd) [r_symndx]; 1141130561Sobrien } 1142130561Sobrien /* If a TLS symbol is accessed using IE at least once, 1143130561Sobrien there is no point to use dynamic model for it. */ 1144130561Sobrien if (old_tls_type != tls_type && old_tls_type != GOT_UNKNOWN) 1145130561Sobrien { 1146130561Sobrien if (old_tls_type == GOT_NORMAL || tls_type == GOT_NORMAL) 1147130561Sobrien { 1148130561Sobrien (*_bfd_error_handler) 1149218822Sdim (_("%B: `%s' accessed both as normal and thread local symbol"), 1150218822Sdim abfd, h->root.root.string); 1151130561Sobrien return FALSE; 1152130561Sobrien } 1153130561Sobrien if (old_tls_type > tls_type) 1154130561Sobrien tls_type = old_tls_type; 1155130561Sobrien } 1156130561Sobrien 1157130561Sobrien if (old_tls_type != tls_type) 1158130561Sobrien { 1159130561Sobrien if (h != NULL) 1160130561Sobrien elf_s390_hash_entry (h)->tls_type = tls_type; 1161130561Sobrien else 1162130561Sobrien elf_s390_local_got_tls_type (abfd) [r_symndx] = tls_type; 1163130561Sobrien } 1164130561Sobrien 1165130561Sobrien if (r_type != R_390_TLS_IE64) 1166130561Sobrien break; 1167130561Sobrien /* Fall through */ 1168130561Sobrien 1169130561Sobrien case R_390_TLS_LE64: 1170130561Sobrien if (!info->shared) 1171130561Sobrien break; 1172130561Sobrien info->flags |= DF_STATIC_TLS; 1173130561Sobrien /* Fall through */ 1174130561Sobrien 1175130561Sobrien case R_390_8: 1176130561Sobrien case R_390_16: 117799461Sobrien case R_390_32: 117899461Sobrien case R_390_64: 1179130561Sobrien case R_390_PC16: 1180130561Sobrien case R_390_PC16DBL: 118199461Sobrien case R_390_PC32: 118299461Sobrien case R_390_PC32DBL: 118399461Sobrien case R_390_PC64: 118499461Sobrien if (h != NULL && !info->shared) 118599461Sobrien { 118699461Sobrien /* If this reloc is in a read-only section, we might 118799461Sobrien need a copy reloc. We can't check reliably at this 118899461Sobrien stage whether the section is read-only, as input 118999461Sobrien sections have not yet been mapped to output sections. 119099461Sobrien Tentatively set the flag for now, and correct in 119199461Sobrien adjust_dynamic_symbol. */ 1192218822Sdim h->non_got_ref = 1; 119399461Sobrien 119499461Sobrien /* We may need a .plt entry if the function this reloc 119599461Sobrien refers to is in a shared lib. */ 119699461Sobrien h->plt.refcount += 1; 119799461Sobrien } 119899461Sobrien 119999461Sobrien /* If we are creating a shared library, and this is a reloc 120099461Sobrien against a global symbol, or a non PC relative reloc 120199461Sobrien against a local symbol, then we need to copy the reloc 120299461Sobrien into the shared library. However, if we are linking with 120399461Sobrien -Bsymbolic, we do not need to copy a reloc against a 120499461Sobrien global symbol which is defined in an object we are 120599461Sobrien including in the link (i.e., DEF_REGULAR is set). At 120699461Sobrien this point we have not seen all the input files, so it is 120799461Sobrien possible that DEF_REGULAR is not set now but will be set 120899461Sobrien later (it is never cleared). In case of a weak definition, 120999461Sobrien DEF_REGULAR may be cleared later by a strong definition in 121099461Sobrien a shared library. We account for that possibility below by 121199461Sobrien storing information in the relocs_copied field of the hash 121299461Sobrien table entry. A similar situation occurs when creating 121399461Sobrien shared libraries and symbol visibility changes render the 121499461Sobrien symbol local. 121599461Sobrien 121699461Sobrien If on the other hand, we are creating an executable, we 121799461Sobrien may need to keep relocations for symbols satisfied by a 121899461Sobrien dynamic library if we manage to avoid copy relocs for the 121999461Sobrien symbol. */ 122099461Sobrien if ((info->shared 122199461Sobrien && (sec->flags & SEC_ALLOC) != 0 122299461Sobrien && ((ELF64_R_TYPE (rel->r_info) != R_390_PC16 122399461Sobrien && ELF64_R_TYPE (rel->r_info) != R_390_PC16DBL 122499461Sobrien && ELF64_R_TYPE (rel->r_info) != R_390_PC32 122599461Sobrien && ELF64_R_TYPE (rel->r_info) != R_390_PC32DBL 122699461Sobrien && ELF64_R_TYPE (rel->r_info) != R_390_PC64) 122799461Sobrien || (h != NULL 122899461Sobrien && (! info->symbolic 122999461Sobrien || h->root.type == bfd_link_hash_defweak 1230218822Sdim || !h->def_regular)))) 1231130561Sobrien || (ELIMINATE_COPY_RELOCS 1232130561Sobrien && !info->shared 123399461Sobrien && (sec->flags & SEC_ALLOC) != 0 123499461Sobrien && h != NULL 123599461Sobrien && (h->root.type == bfd_link_hash_defweak 1236218822Sdim || !h->def_regular))) 123799461Sobrien { 123899461Sobrien struct elf_s390_dyn_relocs *p; 123999461Sobrien struct elf_s390_dyn_relocs **head; 124099461Sobrien 124199461Sobrien /* We must copy these reloc types into the output file. 124299461Sobrien Create a reloc section in dynobj and make room for 124399461Sobrien this reloc. */ 124499461Sobrien if (sreloc == NULL) 124599461Sobrien { 124699461Sobrien const char *name; 124799461Sobrien bfd *dynobj; 124899461Sobrien 124999461Sobrien name = (bfd_elf_string_from_elf_section 125099461Sobrien (abfd, 125199461Sobrien elf_elfheader (abfd)->e_shstrndx, 125299461Sobrien elf_section_data (sec)->rel_hdr.sh_name)); 125399461Sobrien if (name == NULL) 1254130561Sobrien return FALSE; 125599461Sobrien 1256218822Sdim if (! CONST_STRNEQ (name, ".rela") 125799461Sobrien || strcmp (bfd_get_section_name (abfd, sec), 125899461Sobrien name + 5) != 0) 125999461Sobrien { 126099461Sobrien (*_bfd_error_handler) 1261218822Sdim (_("%B: bad relocation section name `%s\'"), 1262218822Sdim abfd, name); 126399461Sobrien } 126499461Sobrien 126599461Sobrien if (htab->elf.dynobj == NULL) 126699461Sobrien htab->elf.dynobj = abfd; 126799461Sobrien 126899461Sobrien dynobj = htab->elf.dynobj; 126999461Sobrien sreloc = bfd_get_section_by_name (dynobj, name); 127099461Sobrien if (sreloc == NULL) 127199461Sobrien { 127299461Sobrien flagword flags; 127399461Sobrien 127499461Sobrien flags = (SEC_HAS_CONTENTS | SEC_READONLY 127599461Sobrien | SEC_IN_MEMORY | SEC_LINKER_CREATED); 127699461Sobrien if ((sec->flags & SEC_ALLOC) != 0) 127799461Sobrien flags |= SEC_ALLOC | SEC_LOAD; 1278218822Sdim sreloc = bfd_make_section_with_flags (dynobj, 1279218822Sdim name, 1280218822Sdim flags); 128199461Sobrien if (sreloc == NULL 1282107492Sobrien || ! bfd_set_section_alignment (dynobj, sreloc, 3)) 1283130561Sobrien return FALSE; 128499461Sobrien } 128599461Sobrien elf_section_data (sec)->sreloc = sreloc; 128699461Sobrien } 128799461Sobrien 128899461Sobrien /* If this is a global symbol, we count the number of 128999461Sobrien relocations we need for this symbol. */ 129099461Sobrien if (h != NULL) 129199461Sobrien { 129299461Sobrien head = &((struct elf_s390_link_hash_entry *) h)->dyn_relocs; 129399461Sobrien } 129499461Sobrien else 129599461Sobrien { 129699461Sobrien /* Track dynamic relocs needed for local syms too. 129799461Sobrien We really need local syms available to do this 129899461Sobrien easily. Oh well. */ 129999461Sobrien 130099461Sobrien asection *s; 1301218822Sdim void *vpp; 1302218822Sdim 130399461Sobrien s = bfd_section_from_r_symndx (abfd, &htab->sym_sec, 130499461Sobrien sec, r_symndx); 130599461Sobrien if (s == NULL) 1306130561Sobrien return FALSE; 130799461Sobrien 1308218822Sdim vpp = &elf_section_data (s)->local_dynrel; 1309218822Sdim head = (struct elf_s390_dyn_relocs **) vpp; 131099461Sobrien } 131199461Sobrien 131299461Sobrien p = *head; 131399461Sobrien if (p == NULL || p->sec != sec) 131499461Sobrien { 131599461Sobrien bfd_size_type amt = sizeof *p; 131699461Sobrien p = ((struct elf_s390_dyn_relocs *) 131799461Sobrien bfd_alloc (htab->elf.dynobj, amt)); 131899461Sobrien if (p == NULL) 1319130561Sobrien return FALSE; 132099461Sobrien p->next = *head; 132199461Sobrien *head = p; 132299461Sobrien p->sec = sec; 132399461Sobrien p->count = 0; 132499461Sobrien p->pc_count = 0; 132599461Sobrien } 132699461Sobrien 132799461Sobrien p->count += 1; 132899461Sobrien if (ELF64_R_TYPE (rel->r_info) == R_390_PC16 132999461Sobrien || ELF64_R_TYPE (rel->r_info) == R_390_PC16DBL 133099461Sobrien || ELF64_R_TYPE (rel->r_info) == R_390_PC32 133199461Sobrien || ELF64_R_TYPE (rel->r_info) == R_390_PC32DBL 133299461Sobrien || ELF64_R_TYPE (rel->r_info) == R_390_PC64) 133399461Sobrien p->pc_count += 1; 133499461Sobrien } 133599461Sobrien break; 133699461Sobrien 133799461Sobrien /* This relocation describes the C++ object vtable hierarchy. 133899461Sobrien Reconstruct it for later use during GC. */ 1339130561Sobrien case R_390_GNU_VTINHERIT: 1340130561Sobrien if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) 1341130561Sobrien return FALSE; 1342130561Sobrien break; 134399461Sobrien 134499461Sobrien /* This relocation describes which C++ vtable entries are actually 134599461Sobrien used. Record for later use during GC. */ 1346130561Sobrien case R_390_GNU_VTENTRY: 1347130561Sobrien if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend)) 1348130561Sobrien return FALSE; 1349130561Sobrien break; 135099461Sobrien 135199461Sobrien default: 135299461Sobrien break; 135399461Sobrien } 135499461Sobrien } 135599461Sobrien 1356130561Sobrien return TRUE; 135799461Sobrien} 135899461Sobrien 135999461Sobrien/* Return the section that should be marked against GC for a given 136099461Sobrien relocation. */ 136199461Sobrien 136299461Sobrienstatic asection * 1363218822Sdimelf_s390_gc_mark_hook (asection *sec, 1364218822Sdim struct bfd_link_info *info, 1365218822Sdim Elf_Internal_Rela *rel, 1366218822Sdim struct elf_link_hash_entry *h, 1367218822Sdim Elf_Internal_Sym *sym) 136899461Sobrien{ 136999461Sobrien if (h != NULL) 1370218822Sdim switch (ELF64_R_TYPE (rel->r_info)) 1371218822Sdim { 1372218822Sdim case R_390_GNU_VTINHERIT: 1373218822Sdim case R_390_GNU_VTENTRY: 1374218822Sdim return NULL; 1375218822Sdim } 137699461Sobrien 1377218822Sdim return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym); 137899461Sobrien} 137999461Sobrien 138099461Sobrien/* Update the got entry reference counts for the section being removed. */ 138199461Sobrien 1382130561Sobrienstatic bfd_boolean 1383218822Sdimelf_s390_gc_sweep_hook (bfd *abfd, 1384218822Sdim struct bfd_link_info *info, 1385218822Sdim asection *sec, 1386218822Sdim const Elf_Internal_Rela *relocs) 138799461Sobrien{ 138899461Sobrien Elf_Internal_Shdr *symtab_hdr; 138999461Sobrien struct elf_link_hash_entry **sym_hashes; 139099461Sobrien bfd_signed_vma *local_got_refcounts; 139199461Sobrien const Elf_Internal_Rela *rel, *relend; 139299461Sobrien 139399461Sobrien elf_section_data (sec)->local_dynrel = NULL; 139499461Sobrien 139599461Sobrien symtab_hdr = &elf_tdata (abfd)->symtab_hdr; 139699461Sobrien sym_hashes = elf_sym_hashes (abfd); 139799461Sobrien local_got_refcounts = elf_local_got_refcounts (abfd); 139899461Sobrien 139999461Sobrien relend = relocs + sec->reloc_count; 140099461Sobrien for (rel = relocs; rel < relend; rel++) 1401130561Sobrien { 1402130561Sobrien unsigned long r_symndx; 1403130561Sobrien unsigned int r_type; 1404130561Sobrien struct elf_link_hash_entry *h = NULL; 140599461Sobrien 1406130561Sobrien r_symndx = ELF64_R_SYM (rel->r_info); 1407130561Sobrien if (r_symndx >= symtab_hdr->sh_info) 1408130561Sobrien { 1409130561Sobrien struct elf_s390_link_hash_entry *eh; 1410130561Sobrien struct elf_s390_dyn_relocs **pp; 1411130561Sobrien struct elf_s390_dyn_relocs *p; 141299461Sobrien 1413130561Sobrien h = sym_hashes[r_symndx - symtab_hdr->sh_info]; 1414218822Sdim while (h->root.type == bfd_link_hash_indirect 1415218822Sdim || h->root.type == bfd_link_hash_warning) 1416218822Sdim h = (struct elf_link_hash_entry *) h->root.u.i.link; 1417130561Sobrien eh = (struct elf_s390_link_hash_entry *) h; 141899461Sobrien 1419130561Sobrien for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next) 1420130561Sobrien if (p->sec == sec) 1421130561Sobrien { 1422130561Sobrien /* Everything must go for SEC. */ 1423130561Sobrien *pp = p->next; 1424130561Sobrien break; 1425130561Sobrien } 1426130561Sobrien } 142799461Sobrien 1428130561Sobrien r_type = ELF64_R_TYPE (rel->r_info); 1429130561Sobrien r_type = elf_s390_tls_transition (info, r_type, h != NULL); 1430130561Sobrien switch (r_type) 1431130561Sobrien { 1432130561Sobrien case R_390_TLS_LDM64: 1433130561Sobrien if (elf_s390_hash_table (info)->tls_ldm_got.refcount > 0) 1434130561Sobrien elf_s390_hash_table (info)->tls_ldm_got.refcount -= 1; 1435130561Sobrien break; 143699461Sobrien 1437130561Sobrien case R_390_TLS_GD64: 1438130561Sobrien case R_390_TLS_IE64: 1439130561Sobrien case R_390_TLS_GOTIE12: 1440130561Sobrien case R_390_TLS_GOTIE20: 1441130561Sobrien case R_390_TLS_GOTIE64: 1442130561Sobrien case R_390_TLS_IEENT: 1443130561Sobrien case R_390_GOT12: 1444130561Sobrien case R_390_GOT16: 1445130561Sobrien case R_390_GOT20: 1446130561Sobrien case R_390_GOT32: 1447130561Sobrien case R_390_GOT64: 1448130561Sobrien case R_390_GOTOFF16: 1449130561Sobrien case R_390_GOTOFF32: 1450130561Sobrien case R_390_GOTOFF64: 1451130561Sobrien case R_390_GOTPC: 1452130561Sobrien case R_390_GOTPCDBL: 1453130561Sobrien case R_390_GOTENT: 1454130561Sobrien if (h != NULL) 1455130561Sobrien { 1456130561Sobrien if (h->got.refcount > 0) 1457130561Sobrien h->got.refcount -= 1; 1458130561Sobrien } 1459130561Sobrien else if (local_got_refcounts != NULL) 1460130561Sobrien { 1461130561Sobrien if (local_got_refcounts[r_symndx] > 0) 1462130561Sobrien local_got_refcounts[r_symndx] -= 1; 1463130561Sobrien } 1464130561Sobrien break; 1465130561Sobrien 1466130561Sobrien case R_390_8: 1467130561Sobrien case R_390_12: 1468130561Sobrien case R_390_16: 1469130561Sobrien case R_390_20: 1470130561Sobrien case R_390_32: 1471130561Sobrien case R_390_64: 1472130561Sobrien case R_390_PC16: 1473130561Sobrien case R_390_PC16DBL: 1474130561Sobrien case R_390_PC32: 1475130561Sobrien case R_390_PC32DBL: 1476130561Sobrien case R_390_PC64: 1477130561Sobrien if (info->shared) 1478130561Sobrien break; 1479130561Sobrien /* Fall through */ 1480130561Sobrien 1481130561Sobrien case R_390_PLT16DBL: 1482130561Sobrien case R_390_PLT32: 1483130561Sobrien case R_390_PLT32DBL: 1484130561Sobrien case R_390_PLT64: 1485130561Sobrien case R_390_PLTOFF16: 1486130561Sobrien case R_390_PLTOFF32: 1487130561Sobrien case R_390_PLTOFF64: 1488130561Sobrien if (h != NULL) 1489130561Sobrien { 1490130561Sobrien if (h->plt.refcount > 0) 1491130561Sobrien h->plt.refcount -= 1; 1492130561Sobrien } 1493130561Sobrien break; 1494130561Sobrien 1495130561Sobrien case R_390_GOTPLT12: 1496130561Sobrien case R_390_GOTPLT16: 1497130561Sobrien case R_390_GOTPLT20: 1498130561Sobrien case R_390_GOTPLT32: 1499130561Sobrien case R_390_GOTPLT64: 1500130561Sobrien case R_390_GOTPLTENT: 1501130561Sobrien if (h != NULL) 1502130561Sobrien { 1503130561Sobrien if (h->plt.refcount > 0) 150499461Sobrien { 1505130561Sobrien ((struct elf_s390_link_hash_entry *) h)->gotplt_refcount--; 1506130561Sobrien h->plt.refcount -= 1; 150799461Sobrien } 1508130561Sobrien } 1509130561Sobrien else if (local_got_refcounts != NULL) 1510130561Sobrien { 1511130561Sobrien if (local_got_refcounts[r_symndx] > 0) 1512130561Sobrien local_got_refcounts[r_symndx] -= 1; 1513130561Sobrien } 1514130561Sobrien break; 151599461Sobrien 1516130561Sobrien default: 1517130561Sobrien break; 1518130561Sobrien } 1519130561Sobrien } 152099461Sobrien 1521130561Sobrien return TRUE; 1522130561Sobrien} 152399461Sobrien 1524130561Sobrien/* Make sure we emit a GOT entry if the symbol was supposed to have a PLT 1525130561Sobrien entry but we found we will not create any. Called when we find we will 1526130561Sobrien not have any PLT for this symbol, by for example 1527130561Sobrien elf_s390_adjust_dynamic_symbol when we're doing a proper dynamic link, 1528130561Sobrien or elf_s390_size_dynamic_sections if no dynamic sections will be 1529130561Sobrien created (we're only linking static objects). */ 1530130561Sobrien 1531130561Sobrienstatic void 1532130561Sobrienelf_s390_adjust_gotplt (h) 1533130561Sobrien struct elf_s390_link_hash_entry *h; 1534130561Sobrien{ 1535130561Sobrien if (h->elf.root.type == bfd_link_hash_warning) 1536130561Sobrien h = (struct elf_s390_link_hash_entry *) h->elf.root.u.i.link; 1537130561Sobrien 1538130561Sobrien if (h->gotplt_refcount <= 0) 1539130561Sobrien return; 1540130561Sobrien 1541130561Sobrien /* We simply add the number of gotplt references to the number 1542130561Sobrien * of got references for this symbol. */ 1543130561Sobrien h->elf.got.refcount += h->gotplt_refcount; 1544130561Sobrien h->gotplt_refcount = -1; 154599461Sobrien} 154699461Sobrien 154799461Sobrien/* Adjust a symbol defined by a dynamic object and referenced by a 154899461Sobrien regular object. The current definition is in some section of the 154999461Sobrien dynamic object, but we're not including those sections. We have to 155099461Sobrien change the definition to something the rest of the link can 155199461Sobrien understand. */ 155299461Sobrien 1553130561Sobrienstatic bfd_boolean 155499461Sobrienelf_s390_adjust_dynamic_symbol (info, h) 155599461Sobrien struct bfd_link_info *info; 155699461Sobrien struct elf_link_hash_entry *h; 155799461Sobrien{ 155899461Sobrien struct elf_s390_link_hash_table *htab; 155999461Sobrien asection *s; 156099461Sobrien 156199461Sobrien /* If this is a function, put it in the procedure linkage table. We 156299461Sobrien will fill in the contents of the procedure linkage table later 1563107492Sobrien (although we could actually do it here). */ 156499461Sobrien if (h->type == STT_FUNC 1565218822Sdim || h->needs_plt) 156699461Sobrien { 156799461Sobrien if (h->plt.refcount <= 0 156899461Sobrien || (! info->shared 1569218822Sdim && !h->def_dynamic 1570218822Sdim && !h->ref_dynamic 157199461Sobrien && h->root.type != bfd_link_hash_undefweak 157299461Sobrien && h->root.type != bfd_link_hash_undefined)) 157399461Sobrien { 157499461Sobrien /* This case can occur if we saw a PLT32 reloc in an input 1575130561Sobrien file, but the symbol was never referred to by a dynamic 1576130561Sobrien object, or if all references were garbage collected. In 157799461Sobrien such a case, we don't actually need to build a procedure 157899461Sobrien linkage table, and we can just do a PC32 reloc instead. */ 157999461Sobrien h->plt.offset = (bfd_vma) -1; 1580218822Sdim h->needs_plt = 0; 1581130561Sobrien elf_s390_adjust_gotplt((struct elf_s390_link_hash_entry *) h); 158299461Sobrien } 158399461Sobrien 1584130561Sobrien return TRUE; 158599461Sobrien } 158699461Sobrien else 158799461Sobrien /* It's possible that we incorrectly decided a .plt reloc was 158899461Sobrien needed for an R_390_PC32 reloc to a non-function sym in 158999461Sobrien check_relocs. We can't decide accurately between function and 159099461Sobrien non-function syms in check-relocs; Objects loaded later in 159199461Sobrien the link may change h->type. So fix it now. */ 159299461Sobrien h->plt.offset = (bfd_vma) -1; 159399461Sobrien 159499461Sobrien /* If this is a weak symbol, and there is a real definition, the 159599461Sobrien processor independent code will have arranged for us to see the 159699461Sobrien real definition first, and we can just use the same value. */ 1597218822Sdim if (h->u.weakdef != NULL) 159899461Sobrien { 1599218822Sdim BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined 1600218822Sdim || h->u.weakdef->root.type == bfd_link_hash_defweak); 1601218822Sdim h->root.u.def.section = h->u.weakdef->root.u.def.section; 1602218822Sdim h->root.u.def.value = h->u.weakdef->root.u.def.value; 1603130561Sobrien if (ELIMINATE_COPY_RELOCS || info->nocopyreloc) 1604218822Sdim h->non_got_ref = h->u.weakdef->non_got_ref; 1605130561Sobrien return TRUE; 160699461Sobrien } 160799461Sobrien 160899461Sobrien /* This is a reference to a symbol defined by a dynamic object which 160999461Sobrien is not a function. */ 161099461Sobrien 161199461Sobrien /* If we are creating a shared library, we must presume that the 161299461Sobrien only references to the symbol are via the global offset table. 161399461Sobrien For such cases we need not do anything here; the relocations will 161499461Sobrien be handled correctly by relocate_section. */ 161599461Sobrien if (info->shared) 1616130561Sobrien return TRUE; 161799461Sobrien 161899461Sobrien /* If there are no references to this symbol that do not use the 161999461Sobrien GOT, we don't need to generate a copy reloc. */ 1620218822Sdim if (!h->non_got_ref) 1621130561Sobrien return TRUE; 162299461Sobrien 162399461Sobrien /* If -z nocopyreloc was given, we won't generate them either. */ 162499461Sobrien if (info->nocopyreloc) 162599461Sobrien { 1626218822Sdim h->non_got_ref = 0; 1627130561Sobrien return TRUE; 162899461Sobrien } 162999461Sobrien 1630130561Sobrien if (ELIMINATE_COPY_RELOCS) 163199461Sobrien { 1632130561Sobrien struct elf_s390_link_hash_entry * eh; 1633130561Sobrien struct elf_s390_dyn_relocs *p; 163499461Sobrien 1635130561Sobrien eh = (struct elf_s390_link_hash_entry *) h; 1636130561Sobrien for (p = eh->dyn_relocs; p != NULL; p = p->next) 1637130561Sobrien { 1638130561Sobrien s = p->sec->output_section; 1639130561Sobrien if (s != NULL && (s->flags & SEC_READONLY) != 0) 1640130561Sobrien break; 1641130561Sobrien } 1642130561Sobrien 1643130561Sobrien /* If we didn't find any dynamic relocs in read-only sections, then 1644130561Sobrien we'll be keeping the dynamic relocs and avoiding the copy reloc. */ 1645130561Sobrien if (p == NULL) 1646130561Sobrien { 1647218822Sdim h->non_got_ref = 0; 1648130561Sobrien return TRUE; 1649130561Sobrien } 165099461Sobrien } 165199461Sobrien 1652218822Sdim if (h->size == 0) 1653218822Sdim { 1654218822Sdim (*_bfd_error_handler) (_("dynamic variable `%s' is zero size"), 1655218822Sdim h->root.root.string); 1656218822Sdim return TRUE; 1657218822Sdim } 1658218822Sdim 165999461Sobrien /* We must allocate the symbol in our .dynbss section, which will 166099461Sobrien become part of the .bss section of the executable. There will be 166199461Sobrien an entry for this symbol in the .dynsym section. The dynamic 166299461Sobrien object will contain position independent code, so all references 166399461Sobrien from the dynamic object to this symbol will go through the global 166499461Sobrien offset table. The dynamic linker will use the .dynsym entry to 166599461Sobrien determine the address it must put in the global offset table, so 166699461Sobrien both the dynamic object and the regular object will refer to the 166799461Sobrien same memory location for the variable. */ 166899461Sobrien 166999461Sobrien htab = elf_s390_hash_table (info); 167099461Sobrien 167199461Sobrien /* We must generate a R_390_COPY reloc to tell the dynamic linker to 167299461Sobrien copy the initial value out of the dynamic object and into the 167399461Sobrien runtime process image. */ 167499461Sobrien if ((h->root.u.def.section->flags & SEC_ALLOC) != 0) 167599461Sobrien { 1676218822Sdim htab->srelbss->size += sizeof (Elf64_External_Rela); 1677218822Sdim h->needs_copy = 1; 167899461Sobrien } 167999461Sobrien 168099461Sobrien s = htab->sdynbss; 168199461Sobrien 1682218822Sdim return _bfd_elf_adjust_dynamic_copy (h, s); 168399461Sobrien} 168499461Sobrien 168599461Sobrien/* Allocate space in .plt, .got and associated reloc sections for 168699461Sobrien dynamic relocs. */ 168799461Sobrien 1688130561Sobrienstatic bfd_boolean 168999461Sobrienallocate_dynrelocs (h, inf) 169099461Sobrien struct elf_link_hash_entry *h; 169199461Sobrien PTR inf; 169299461Sobrien{ 169399461Sobrien struct bfd_link_info *info; 169499461Sobrien struct elf_s390_link_hash_table *htab; 169599461Sobrien struct elf_s390_link_hash_entry *eh; 169699461Sobrien struct elf_s390_dyn_relocs *p; 169799461Sobrien 169899461Sobrien if (h->root.type == bfd_link_hash_indirect) 1699130561Sobrien return TRUE; 170099461Sobrien 170199461Sobrien if (h->root.type == bfd_link_hash_warning) 1702130561Sobrien /* When warning symbols are created, they **replace** the "real" 1703130561Sobrien entry in the hash table, thus we never get to see the real 1704130561Sobrien symbol in a hash traversal. So look at it now. */ 170599461Sobrien h = (struct elf_link_hash_entry *) h->root.u.i.link; 170699461Sobrien 170799461Sobrien info = (struct bfd_link_info *) inf; 170899461Sobrien htab = elf_s390_hash_table (info); 170999461Sobrien 171099461Sobrien if (htab->elf.dynamic_sections_created 1711130561Sobrien && h->plt.refcount > 0 1712130561Sobrien && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT 1713130561Sobrien || h->root.type != bfd_link_hash_undefweak)) 171499461Sobrien { 171599461Sobrien /* Make sure this symbol is output as a dynamic symbol. 171699461Sobrien Undefined weak syms won't yet be marked as dynamic. */ 171799461Sobrien if (h->dynindx == -1 1718218822Sdim && !h->forced_local) 171999461Sobrien { 1720130561Sobrien if (! bfd_elf_link_record_dynamic_symbol (info, h)) 1721130561Sobrien return FALSE; 172299461Sobrien } 172399461Sobrien 1724130561Sobrien if (info->shared 1725130561Sobrien || WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, 0, h)) 172699461Sobrien { 172799461Sobrien asection *s = htab->splt; 172899461Sobrien 172999461Sobrien /* If this is the first .plt entry, make room for the special 173099461Sobrien first entry. */ 1731218822Sdim if (s->size == 0) 1732218822Sdim s->size += PLT_FIRST_ENTRY_SIZE; 173399461Sobrien 1734218822Sdim h->plt.offset = s->size; 173599461Sobrien 173699461Sobrien /* If this symbol is not defined in a regular file, and we are 173799461Sobrien not generating a shared library, then set the symbol to this 173899461Sobrien location in the .plt. This is required to make function 173999461Sobrien pointers compare as equal between the normal executable and 174099461Sobrien the shared library. */ 174199461Sobrien if (! info->shared 1742218822Sdim && !h->def_regular) 174399461Sobrien { 174499461Sobrien h->root.u.def.section = s; 174599461Sobrien h->root.u.def.value = h->plt.offset; 174699461Sobrien } 174799461Sobrien 174899461Sobrien /* Make room for this entry. */ 1749218822Sdim s->size += PLT_ENTRY_SIZE; 175099461Sobrien 175199461Sobrien /* We also need to make an entry in the .got.plt section, which 175299461Sobrien will be placed in the .got section by the linker script. */ 1753218822Sdim htab->sgotplt->size += GOT_ENTRY_SIZE; 175499461Sobrien 175599461Sobrien /* We also need to make an entry in the .rela.plt section. */ 1756218822Sdim htab->srelplt->size += sizeof (Elf64_External_Rela); 175799461Sobrien } 175899461Sobrien else 175999461Sobrien { 176099461Sobrien h->plt.offset = (bfd_vma) -1; 1761218822Sdim h->needs_plt = 0; 1762130561Sobrien elf_s390_adjust_gotplt((struct elf_s390_link_hash_entry *) h); 176399461Sobrien } 176499461Sobrien } 176599461Sobrien else 176699461Sobrien { 176799461Sobrien h->plt.offset = (bfd_vma) -1; 1768218822Sdim h->needs_plt = 0; 1769130561Sobrien elf_s390_adjust_gotplt((struct elf_s390_link_hash_entry *) h); 177099461Sobrien } 177199461Sobrien 1772130561Sobrien /* If R_390_TLS_{IE64,GOTIE64,GOTIE12,IEENT} symbol is now local to 1773130561Sobrien the binary, we can optimize a bit. IE64 and GOTIE64 get converted 1774130561Sobrien to R_390_TLS_LE64 requiring no TLS entry. For GOTIE12 and IEENT 1775130561Sobrien we can save the dynamic TLS relocation. */ 1776130561Sobrien if (h->got.refcount > 0 1777130561Sobrien && !info->shared 1778130561Sobrien && h->dynindx == -1 1779130561Sobrien && elf_s390_hash_entry(h)->tls_type >= GOT_TLS_IE) 178099461Sobrien { 1781130561Sobrien if (elf_s390_hash_entry(h)->tls_type == GOT_TLS_IE_NLT) 1782130561Sobrien /* For the GOTIE access without a literal pool entry the offset has 1783130561Sobrien to be stored somewhere. The immediate value in the instruction 1784130561Sobrien is not bit enough so the value is stored in the got. */ 1785130561Sobrien { 1786218822Sdim h->got.offset = htab->sgot->size; 1787218822Sdim htab->sgot->size += GOT_ENTRY_SIZE; 1788130561Sobrien } 1789130561Sobrien else 1790130561Sobrien h->got.offset = (bfd_vma) -1; 1791130561Sobrien } 1792130561Sobrien else if (h->got.refcount > 0) 1793130561Sobrien { 179499461Sobrien asection *s; 1795130561Sobrien bfd_boolean dyn; 1796130561Sobrien int tls_type = elf_s390_hash_entry(h)->tls_type; 179799461Sobrien 179899461Sobrien /* Make sure this symbol is output as a dynamic symbol. 179999461Sobrien Undefined weak syms won't yet be marked as dynamic. */ 180099461Sobrien if (h->dynindx == -1 1801218822Sdim && !h->forced_local) 180299461Sobrien { 1803130561Sobrien if (! bfd_elf_link_record_dynamic_symbol (info, h)) 1804130561Sobrien return FALSE; 180599461Sobrien } 180699461Sobrien 180799461Sobrien s = htab->sgot; 1808218822Sdim h->got.offset = s->size; 1809218822Sdim s->size += GOT_ENTRY_SIZE; 1810130561Sobrien /* R_390_TLS_GD64 needs 2 consecutive GOT slots. */ 1811130561Sobrien if (tls_type == GOT_TLS_GD) 1812218822Sdim s->size += GOT_ENTRY_SIZE; 181399461Sobrien dyn = htab->elf.dynamic_sections_created; 1814130561Sobrien /* R_390_TLS_IE64 needs one dynamic relocation, 1815130561Sobrien R_390_TLS_GD64 needs one if local symbol and two if global. */ 1816130561Sobrien if ((tls_type == GOT_TLS_GD && h->dynindx == -1) 1817130561Sobrien || tls_type >= GOT_TLS_IE) 1818218822Sdim htab->srelgot->size += sizeof (Elf64_External_Rela); 1819130561Sobrien else if (tls_type == GOT_TLS_GD) 1820218822Sdim htab->srelgot->size += 2 * sizeof (Elf64_External_Rela); 1821130561Sobrien else if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT 1822130561Sobrien || h->root.type != bfd_link_hash_undefweak) 1823130561Sobrien && (info->shared 1824130561Sobrien || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h))) 1825218822Sdim htab->srelgot->size += sizeof (Elf64_External_Rela); 182699461Sobrien } 182799461Sobrien else 182899461Sobrien h->got.offset = (bfd_vma) -1; 182999461Sobrien 183099461Sobrien eh = (struct elf_s390_link_hash_entry *) h; 183199461Sobrien if (eh->dyn_relocs == NULL) 1832130561Sobrien return TRUE; 183399461Sobrien 183499461Sobrien /* In the shared -Bsymbolic case, discard space allocated for 183599461Sobrien dynamic pc-relative relocs against symbols which turn out to be 183699461Sobrien defined in regular objects. For the normal shared case, discard 183799461Sobrien space for pc-relative relocs that have become local due to symbol 183899461Sobrien visibility changes. */ 183999461Sobrien 184099461Sobrien if (info->shared) 184199461Sobrien { 1842130561Sobrien if (SYMBOL_REFERENCES_LOCAL (info, h)) 184399461Sobrien { 184499461Sobrien struct elf_s390_dyn_relocs **pp; 184599461Sobrien 184699461Sobrien for (pp = &eh->dyn_relocs; (p = *pp) != NULL; ) 184799461Sobrien { 184899461Sobrien p->count -= p->pc_count; 184999461Sobrien p->pc_count = 0; 185099461Sobrien if (p->count == 0) 185199461Sobrien *pp = p->next; 185299461Sobrien else 185399461Sobrien pp = &p->next; 185499461Sobrien } 185599461Sobrien } 1856130561Sobrien 1857130561Sobrien /* Also discard relocs on undefined weak syms with non-default 1858130561Sobrien visibility. */ 1859218822Sdim if (eh->dyn_relocs != NULL 1860130561Sobrien && h->root.type == bfd_link_hash_undefweak) 1861218822Sdim { 1862218822Sdim if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT) 1863218822Sdim eh->dyn_relocs = NULL; 1864218822Sdim 1865218822Sdim /* Make sure undefined weak symbols are output as a dynamic 1866218822Sdim symbol in PIEs. */ 1867218822Sdim else if (h->dynindx == -1 1868218822Sdim && !h->forced_local) 1869218822Sdim { 1870218822Sdim if (! bfd_elf_link_record_dynamic_symbol (info, h)) 1871218822Sdim return FALSE; 1872218822Sdim } 1873218822Sdim } 187499461Sobrien } 1875130561Sobrien else if (ELIMINATE_COPY_RELOCS) 187699461Sobrien { 187799461Sobrien /* For the non-shared case, discard space for relocs against 187899461Sobrien symbols which turn out to need copy relocs or are not 187999461Sobrien dynamic. */ 188099461Sobrien 1881218822Sdim if (!h->non_got_ref 1882218822Sdim && ((h->def_dynamic 1883218822Sdim && !h->def_regular) 188499461Sobrien || (htab->elf.dynamic_sections_created 188599461Sobrien && (h->root.type == bfd_link_hash_undefweak 188699461Sobrien || h->root.type == bfd_link_hash_undefined)))) 188799461Sobrien { 188899461Sobrien /* Make sure this symbol is output as a dynamic symbol. 188999461Sobrien Undefined weak syms won't yet be marked as dynamic. */ 189099461Sobrien if (h->dynindx == -1 1891218822Sdim && !h->forced_local) 189299461Sobrien { 1893130561Sobrien if (! bfd_elf_link_record_dynamic_symbol (info, h)) 1894130561Sobrien return FALSE; 189599461Sobrien } 189699461Sobrien 189799461Sobrien /* If that succeeded, we know we'll be keeping all the 189899461Sobrien relocs. */ 189999461Sobrien if (h->dynindx != -1) 190099461Sobrien goto keep; 190199461Sobrien } 190299461Sobrien 190399461Sobrien eh->dyn_relocs = NULL; 190499461Sobrien 190599461Sobrien keep: ; 190699461Sobrien } 190799461Sobrien 190899461Sobrien /* Finally, allocate space. */ 190999461Sobrien for (p = eh->dyn_relocs; p != NULL; p = p->next) 191099461Sobrien { 191199461Sobrien asection *sreloc = elf_section_data (p->sec)->sreloc; 1912218822Sdim sreloc->size += p->count * sizeof (Elf64_External_Rela); 191399461Sobrien } 191499461Sobrien 1915130561Sobrien return TRUE; 191699461Sobrien} 191799461Sobrien 191899461Sobrien/* Find any dynamic relocs that apply to read-only sections. */ 191999461Sobrien 1920130561Sobrienstatic bfd_boolean 192199461Sobrienreadonly_dynrelocs (h, inf) 192299461Sobrien struct elf_link_hash_entry *h; 192399461Sobrien PTR inf; 192499461Sobrien{ 192599461Sobrien struct elf_s390_link_hash_entry *eh; 192699461Sobrien struct elf_s390_dyn_relocs *p; 192799461Sobrien 192899461Sobrien if (h->root.type == bfd_link_hash_warning) 192999461Sobrien h = (struct elf_link_hash_entry *) h->root.u.i.link; 193099461Sobrien 193199461Sobrien eh = (struct elf_s390_link_hash_entry *) h; 193299461Sobrien for (p = eh->dyn_relocs; p != NULL; p = p->next) 193399461Sobrien { 193499461Sobrien asection *s = p->sec->output_section; 193599461Sobrien 193699461Sobrien if (s != NULL && (s->flags & SEC_READONLY) != 0) 193799461Sobrien { 193899461Sobrien struct bfd_link_info *info = (struct bfd_link_info *) inf; 193999461Sobrien 194099461Sobrien info->flags |= DF_TEXTREL; 194199461Sobrien 194299461Sobrien /* Not an error, just cut short the traversal. */ 1943130561Sobrien return FALSE; 194499461Sobrien } 194599461Sobrien } 1946130561Sobrien return TRUE; 194799461Sobrien} 194899461Sobrien 194999461Sobrien/* Set the sizes of the dynamic sections. */ 195099461Sobrien 1951130561Sobrienstatic bfd_boolean 195299461Sobrienelf_s390_size_dynamic_sections (output_bfd, info) 195399461Sobrien bfd *output_bfd ATTRIBUTE_UNUSED; 195499461Sobrien struct bfd_link_info *info; 195599461Sobrien{ 195699461Sobrien struct elf_s390_link_hash_table *htab; 195799461Sobrien bfd *dynobj; 195899461Sobrien asection *s; 1959130561Sobrien bfd_boolean relocs; 196099461Sobrien bfd *ibfd; 196199461Sobrien 196299461Sobrien htab = elf_s390_hash_table (info); 196399461Sobrien dynobj = htab->elf.dynobj; 196499461Sobrien if (dynobj == NULL) 196599461Sobrien abort (); 196699461Sobrien 196799461Sobrien if (htab->elf.dynamic_sections_created) 196899461Sobrien { 196999461Sobrien /* Set the contents of the .interp section to the interpreter. */ 1970130561Sobrien if (info->executable) 197199461Sobrien { 197299461Sobrien s = bfd_get_section_by_name (dynobj, ".interp"); 197399461Sobrien if (s == NULL) 197499461Sobrien abort (); 1975218822Sdim s->size = sizeof ELF_DYNAMIC_INTERPRETER; 197699461Sobrien s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER; 197799461Sobrien } 197899461Sobrien } 197999461Sobrien 198099461Sobrien /* Set up .got offsets for local syms, and space for local dynamic 198199461Sobrien relocs. */ 198299461Sobrien for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) 198399461Sobrien { 198499461Sobrien bfd_signed_vma *local_got; 198599461Sobrien bfd_signed_vma *end_local_got; 1986130561Sobrien char *local_tls_type; 198799461Sobrien bfd_size_type locsymcount; 198899461Sobrien Elf_Internal_Shdr *symtab_hdr; 198999461Sobrien asection *srela; 199099461Sobrien 199199461Sobrien if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour) 199299461Sobrien continue; 199399461Sobrien 199499461Sobrien for (s = ibfd->sections; s != NULL; s = s->next) 199599461Sobrien { 199699461Sobrien struct elf_s390_dyn_relocs *p; 199799461Sobrien 1998218822Sdim for (p = elf_section_data (s)->local_dynrel; p != NULL; p = p->next) 199999461Sobrien { 200099461Sobrien if (!bfd_is_abs_section (p->sec) 200199461Sobrien && bfd_is_abs_section (p->sec->output_section)) 200299461Sobrien { 200399461Sobrien /* Input section has been discarded, either because 200499461Sobrien it is a copy of a linkonce section or due to 200599461Sobrien linker script /DISCARD/, so we'll be discarding 200699461Sobrien the relocs too. */ 200799461Sobrien } 200899461Sobrien else if (p->count != 0) 200999461Sobrien { 201099461Sobrien srela = elf_section_data (p->sec)->sreloc; 2011218822Sdim srela->size += p->count * sizeof (Elf64_External_Rela); 201299461Sobrien if ((p->sec->output_section->flags & SEC_READONLY) != 0) 201399461Sobrien info->flags |= DF_TEXTREL; 201499461Sobrien } 201599461Sobrien } 201699461Sobrien } 201799461Sobrien 201899461Sobrien local_got = elf_local_got_refcounts (ibfd); 201999461Sobrien if (!local_got) 202099461Sobrien continue; 202199461Sobrien 202299461Sobrien symtab_hdr = &elf_tdata (ibfd)->symtab_hdr; 202399461Sobrien locsymcount = symtab_hdr->sh_info; 202499461Sobrien end_local_got = local_got + locsymcount; 2025130561Sobrien local_tls_type = elf_s390_local_got_tls_type (ibfd); 202699461Sobrien s = htab->sgot; 202799461Sobrien srela = htab->srelgot; 2028130561Sobrien for (; local_got < end_local_got; ++local_got, ++local_tls_type) 202999461Sobrien { 203099461Sobrien if (*local_got > 0) 203199461Sobrien { 2032218822Sdim *local_got = s->size; 2033218822Sdim s->size += GOT_ENTRY_SIZE; 2034130561Sobrien if (*local_tls_type == GOT_TLS_GD) 2035218822Sdim s->size += GOT_ENTRY_SIZE; 203699461Sobrien if (info->shared) 2037218822Sdim srela->size += sizeof (Elf64_External_Rela); 203899461Sobrien } 203999461Sobrien else 204099461Sobrien *local_got = (bfd_vma) -1; 204199461Sobrien } 204299461Sobrien } 204399461Sobrien 2044130561Sobrien if (htab->tls_ldm_got.refcount > 0) 2045130561Sobrien { 2046130561Sobrien /* Allocate 2 got entries and 1 dynamic reloc for R_390_TLS_LDM64 2047130561Sobrien relocs. */ 2048218822Sdim htab->tls_ldm_got.offset = htab->sgot->size; 2049218822Sdim htab->sgot->size += 2 * GOT_ENTRY_SIZE; 2050218822Sdim htab->srelgot->size += sizeof (Elf64_External_Rela); 2051130561Sobrien } 2052130561Sobrien else 2053130561Sobrien htab->tls_ldm_got.offset = -1; 2054130561Sobrien 205599461Sobrien /* Allocate global sym .plt and .got entries, and space for global 205699461Sobrien sym dynamic relocs. */ 205799461Sobrien elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, (PTR) info); 205899461Sobrien 205999461Sobrien /* We now have determined the sizes of the various dynamic sections. 206099461Sobrien Allocate memory for them. */ 2061130561Sobrien relocs = FALSE; 206299461Sobrien for (s = dynobj->sections; s != NULL; s = s->next) 206399461Sobrien { 206499461Sobrien if ((s->flags & SEC_LINKER_CREATED) == 0) 206599461Sobrien continue; 206699461Sobrien 206799461Sobrien if (s == htab->splt 206899461Sobrien || s == htab->sgot 2069218822Sdim || s == htab->sgotplt 2070218822Sdim || s == htab->sdynbss) 207199461Sobrien { 207299461Sobrien /* Strip this section if we don't need it; see the 207399461Sobrien comment below. */ 207499461Sobrien } 2075218822Sdim else if (CONST_STRNEQ (bfd_get_section_name (dynobj, s), ".rela")) 207699461Sobrien { 2077218822Sdim if (s->size != 0 && s != htab->srelplt) 2078130561Sobrien relocs = TRUE; 207999461Sobrien 208099461Sobrien /* We use the reloc_count field as a counter if we need 208199461Sobrien to copy relocs into the output file. */ 208299461Sobrien s->reloc_count = 0; 208399461Sobrien } 208499461Sobrien else 208599461Sobrien { 208699461Sobrien /* It's not one of our sections, so don't allocate space. */ 208799461Sobrien continue; 208899461Sobrien } 208999461Sobrien 2090218822Sdim if (s->size == 0) 209199461Sobrien { 209299461Sobrien /* If we don't need this section, strip it from the 209399461Sobrien output file. This is to handle .rela.bss and 209499461Sobrien .rela.plt. We must create it in 209599461Sobrien create_dynamic_sections, because it must be created 209699461Sobrien before the linker maps input sections to output 209799461Sobrien sections. The linker does that before 209899461Sobrien adjust_dynamic_symbol is called, and it is that 209999461Sobrien function which decides whether anything needs to go 210099461Sobrien into these sections. */ 210199461Sobrien 2102218822Sdim s->flags |= SEC_EXCLUDE; 210399461Sobrien continue; 210499461Sobrien } 210599461Sobrien 2106218822Sdim if ((s->flags & SEC_HAS_CONTENTS) == 0) 2107218822Sdim continue; 2108218822Sdim 210999461Sobrien /* Allocate memory for the section contents. We use bfd_zalloc 211099461Sobrien here in case unused entries are not reclaimed before the 211199461Sobrien section's contents are written out. This should not happen, 211299461Sobrien but this way if it does, we get a R_390_NONE reloc instead 211399461Sobrien of garbage. */ 2114218822Sdim s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size); 211599461Sobrien if (s->contents == NULL) 2116130561Sobrien return FALSE; 211799461Sobrien } 211899461Sobrien 211999461Sobrien if (htab->elf.dynamic_sections_created) 212099461Sobrien { 212199461Sobrien /* Add some entries to the .dynamic section. We fill in the 212299461Sobrien values later, in elf_s390_finish_dynamic_sections, but we 212399461Sobrien must add the entries now so that we get the correct size for 212499461Sobrien the .dynamic section. The DT_DEBUG entry is filled in by the 212599461Sobrien dynamic linker and used by the debugger. */ 212699461Sobrien#define add_dynamic_entry(TAG, VAL) \ 2127130561Sobrien _bfd_elf_add_dynamic_entry (info, TAG, VAL) 212899461Sobrien 2129130561Sobrien if (info->executable) 213099461Sobrien { 213199461Sobrien if (!add_dynamic_entry (DT_DEBUG, 0)) 2132130561Sobrien return FALSE; 213399461Sobrien } 213499461Sobrien 2135218822Sdim if (htab->splt->size != 0) 213699461Sobrien { 213799461Sobrien if (!add_dynamic_entry (DT_PLTGOT, 0) 213899461Sobrien || !add_dynamic_entry (DT_PLTRELSZ, 0) 213999461Sobrien || !add_dynamic_entry (DT_PLTREL, DT_RELA) 214099461Sobrien || !add_dynamic_entry (DT_JMPREL, 0)) 2141130561Sobrien return FALSE; 214299461Sobrien } 214399461Sobrien 214499461Sobrien if (relocs) 2145130561Sobrien { 2146130561Sobrien if (!add_dynamic_entry (DT_RELA, 0) 2147130561Sobrien || !add_dynamic_entry (DT_RELASZ, 0) 2148130561Sobrien || !add_dynamic_entry (DT_RELAENT, sizeof (Elf64_External_Rela))) 2149130561Sobrien return FALSE; 215099461Sobrien 215199461Sobrien /* If any dynamic relocs apply to a read-only section, 215299461Sobrien then we need a DT_TEXTREL entry. */ 215399461Sobrien if ((info->flags & DF_TEXTREL) == 0) 215499461Sobrien elf_link_hash_traverse (&htab->elf, readonly_dynrelocs, 215599461Sobrien (PTR) info); 215699461Sobrien 215799461Sobrien if ((info->flags & DF_TEXTREL) != 0) 215899461Sobrien { 215999461Sobrien if (!add_dynamic_entry (DT_TEXTREL, 0)) 2160130561Sobrien return FALSE; 216199461Sobrien } 216299461Sobrien } 216399461Sobrien } 216499461Sobrien#undef add_dynamic_entry 216599461Sobrien 2166130561Sobrien return TRUE; 216799461Sobrien} 216899461Sobrien 2169130561Sobrien/* Return the base VMA address which should be subtracted from real addresses 2170130561Sobrien when resolving @dtpoff relocation. 2171130561Sobrien This is PT_TLS segment p_vaddr. */ 2172130561Sobrien 2173130561Sobrienstatic bfd_vma 2174130561Sobriendtpoff_base (info) 2175130561Sobrien struct bfd_link_info *info; 2176130561Sobrien{ 2177130561Sobrien /* If tls_sec is NULL, we should have signalled an error already. */ 2178130561Sobrien if (elf_hash_table (info)->tls_sec == NULL) 2179130561Sobrien return 0; 2180130561Sobrien return elf_hash_table (info)->tls_sec->vma; 2181130561Sobrien} 2182130561Sobrien 2183130561Sobrien/* Return the relocation value for @tpoff relocation 2184130561Sobrien if STT_TLS virtual address is ADDRESS. */ 2185130561Sobrien 2186130561Sobrienstatic bfd_vma 2187130561Sobrientpoff (info, address) 2188130561Sobrien struct bfd_link_info *info; 2189130561Sobrien bfd_vma address; 2190130561Sobrien{ 2191130561Sobrien struct elf_link_hash_table *htab = elf_hash_table (info); 2192130561Sobrien 2193130561Sobrien /* If tls_sec is NULL, we should have signalled an error already. */ 2194130561Sobrien if (htab->tls_sec == NULL) 2195130561Sobrien return 0; 2196130561Sobrien return htab->tls_size + htab->tls_sec->vma - address; 2197130561Sobrien} 2198130561Sobrien 2199130561Sobrien/* Complain if TLS instruction relocation is against an invalid 2200130561Sobrien instruction. */ 2201130561Sobrien 2202130561Sobrienstatic void 2203130561Sobrieninvalid_tls_insn (input_bfd, input_section, rel) 2204130561Sobrien bfd *input_bfd; 2205130561Sobrien asection *input_section; 2206130561Sobrien Elf_Internal_Rela *rel; 2207130561Sobrien{ 2208130561Sobrien reloc_howto_type *howto; 2209130561Sobrien 2210130561Sobrien howto = elf_howto_table + ELF64_R_TYPE (rel->r_info); 2211130561Sobrien (*_bfd_error_handler) 2212218822Sdim (_("%B(%A+0x%lx): invalid instruction for TLS relocation %s"), 2213218822Sdim input_bfd, 2214218822Sdim input_section, 2215130561Sobrien (long) rel->r_offset, 2216130561Sobrien howto->name); 2217218822Sdim bfd_set_error (bfd_error_bad_value); 2218130561Sobrien} 2219130561Sobrien 222099461Sobrien/* Relocate a 390 ELF section. */ 222199461Sobrien 2222130561Sobrienstatic bfd_boolean 222399461Sobrienelf_s390_relocate_section (output_bfd, info, input_bfd, input_section, 222499461Sobrien contents, relocs, local_syms, local_sections) 222599461Sobrien bfd *output_bfd; 222699461Sobrien struct bfd_link_info *info; 222799461Sobrien bfd *input_bfd; 222899461Sobrien asection *input_section; 222999461Sobrien bfd_byte *contents; 223099461Sobrien Elf_Internal_Rela *relocs; 223199461Sobrien Elf_Internal_Sym *local_syms; 223299461Sobrien asection **local_sections; 223399461Sobrien{ 223499461Sobrien struct elf_s390_link_hash_table *htab; 223599461Sobrien Elf_Internal_Shdr *symtab_hdr; 223699461Sobrien struct elf_link_hash_entry **sym_hashes; 223799461Sobrien bfd_vma *local_got_offsets; 223899461Sobrien Elf_Internal_Rela *rel; 223999461Sobrien Elf_Internal_Rela *relend; 224099461Sobrien 224199461Sobrien htab = elf_s390_hash_table (info); 224299461Sobrien symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; 224399461Sobrien sym_hashes = elf_sym_hashes (input_bfd); 224499461Sobrien local_got_offsets = elf_local_got_offsets (input_bfd); 224599461Sobrien 224699461Sobrien rel = relocs; 224799461Sobrien relend = relocs + input_section->reloc_count; 224899461Sobrien for (; rel < relend; rel++) 224999461Sobrien { 2250130561Sobrien unsigned int r_type; 225199461Sobrien reloc_howto_type *howto; 225299461Sobrien unsigned long r_symndx; 225399461Sobrien struct elf_link_hash_entry *h; 225499461Sobrien Elf_Internal_Sym *sym; 225599461Sobrien asection *sec; 225699461Sobrien bfd_vma off; 225799461Sobrien bfd_vma relocation; 2258130561Sobrien bfd_boolean unresolved_reloc; 225999461Sobrien bfd_reloc_status_type r; 2260130561Sobrien int tls_type; 226199461Sobrien 226299461Sobrien r_type = ELF64_R_TYPE (rel->r_info); 226399461Sobrien if (r_type == (int) R_390_GNU_VTINHERIT 2264130561Sobrien || r_type == (int) R_390_GNU_VTENTRY) 2265130561Sobrien continue; 2266130561Sobrien if (r_type >= (int) R_390_max) 226799461Sobrien { 226899461Sobrien bfd_set_error (bfd_error_bad_value); 2269130561Sobrien return FALSE; 227099461Sobrien } 227199461Sobrien 227299461Sobrien howto = elf_howto_table + r_type; 227399461Sobrien r_symndx = ELF64_R_SYM (rel->r_info); 2274130561Sobrien 227599461Sobrien h = NULL; 227699461Sobrien sym = NULL; 227799461Sobrien sec = NULL; 2278130561Sobrien unresolved_reloc = FALSE; 227999461Sobrien if (r_symndx < symtab_hdr->sh_info) 228099461Sobrien { 228199461Sobrien sym = local_syms + r_symndx; 228299461Sobrien sec = local_sections[r_symndx]; 2283130561Sobrien relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel); 228499461Sobrien } 228599461Sobrien else 228699461Sobrien { 2287130561Sobrien bfd_boolean warned ATTRIBUTE_UNUSED; 228899461Sobrien 2289130561Sobrien RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, 2290130561Sobrien r_symndx, symtab_hdr, sym_hashes, 2291130561Sobrien h, sec, relocation, 2292130561Sobrien unresolved_reloc, warned); 229399461Sobrien } 229499461Sobrien 2295218822Sdim if (sec != NULL && elf_discarded_section (sec)) 2296218822Sdim { 2297218822Sdim /* For relocs against symbols from removed linkonce sections, 2298218822Sdim or sections discarded by a linker script, we just want the 2299218822Sdim section contents zeroed. Avoid any special processing. */ 2300218822Sdim _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset); 2301218822Sdim rel->r_info = 0; 2302218822Sdim rel->r_addend = 0; 2303218822Sdim continue; 2304218822Sdim } 2305218822Sdim 2306218822Sdim if (info->relocatable) 2307218822Sdim continue; 2308218822Sdim 230999461Sobrien switch (r_type) 231099461Sobrien { 2311130561Sobrien case R_390_GOTPLT12: 2312130561Sobrien case R_390_GOTPLT16: 2313130561Sobrien case R_390_GOTPLT20: 2314130561Sobrien case R_390_GOTPLT32: 2315130561Sobrien case R_390_GOTPLT64: 2316130561Sobrien case R_390_GOTPLTENT: 2317130561Sobrien /* There are three cases for a GOTPLT relocation. 1) The 2318130561Sobrien relocation is against the jump slot entry of a plt that 2319130561Sobrien will get emitted to the output file. 2) The relocation 2320130561Sobrien is against the jump slot of a plt entry that has been 2321130561Sobrien removed. elf_s390_adjust_gotplt has created a GOT entry 2322130561Sobrien as replacement. 3) The relocation is against a local symbol. 2323130561Sobrien Cases 2) and 3) are the same as the GOT relocation code 2324130561Sobrien so we just have to test for case 1 and fall through for 2325130561Sobrien the other two. */ 2326130561Sobrien if (h != NULL && h->plt.offset != (bfd_vma) -1) 2327130561Sobrien { 2328130561Sobrien bfd_vma plt_index; 2329130561Sobrien 2330130561Sobrien /* Calc. index no. 2331130561Sobrien Current offset - size first entry / entry size. */ 2332130561Sobrien plt_index = (h->plt.offset - PLT_FIRST_ENTRY_SIZE) / 2333130561Sobrien PLT_ENTRY_SIZE; 2334130561Sobrien 2335130561Sobrien /* Offset in GOT is PLT index plus GOT headers(3) times 4, 2336130561Sobrien addr & GOT addr. */ 2337130561Sobrien relocation = (plt_index + 3) * GOT_ENTRY_SIZE; 2338130561Sobrien unresolved_reloc = FALSE; 2339130561Sobrien 2340130561Sobrien if (r_type == R_390_GOTPLTENT) 2341130561Sobrien relocation += htab->sgot->output_section->vma; 2342130561Sobrien break; 2343130561Sobrien } 2344130561Sobrien /* Fall through. */ 2345130561Sobrien 2346130561Sobrien case R_390_GOT12: 2347130561Sobrien case R_390_GOT16: 2348130561Sobrien case R_390_GOT20: 2349130561Sobrien case R_390_GOT32: 2350130561Sobrien case R_390_GOT64: 2351130561Sobrien case R_390_GOTENT: 2352130561Sobrien /* Relocation is to the entry for this symbol in the global 2353130561Sobrien offset table. */ 235499461Sobrien if (htab->sgot == NULL) 235599461Sobrien abort (); 235699461Sobrien 2357130561Sobrien if (h != NULL) 2358130561Sobrien { 2359130561Sobrien bfd_boolean dyn; 236099461Sobrien 2361130561Sobrien off = h->got.offset; 236299461Sobrien dyn = htab->elf.dynamic_sections_created; 2363130561Sobrien if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h) 2364130561Sobrien || (info->shared 2365130561Sobrien && (info->symbolic 236699461Sobrien || h->dynindx == -1 2367218822Sdim || h->forced_local) 2368218822Sdim && h->def_regular) 2369130561Sobrien || (ELF_ST_VISIBILITY (h->other) 2370130561Sobrien && h->root.type == bfd_link_hash_undefweak)) 2371130561Sobrien { 2372130561Sobrien /* This is actually a static link, or it is a 2373130561Sobrien -Bsymbolic link and the symbol is defined 2374130561Sobrien locally, or the symbol was forced to be local 2375130561Sobrien because of a version file. We must initialize 2376130561Sobrien this entry in the global offset table. Since the 2377130561Sobrien offset must always be a multiple of 2, we use the 2378130561Sobrien least significant bit to record whether we have 2379130561Sobrien initialized it already. 238099461Sobrien 2381130561Sobrien When doing a dynamic link, we create a .rel.got 2382130561Sobrien relocation entry to initialize the value. This 2383130561Sobrien is done in the finish_dynamic_symbol routine. */ 2384130561Sobrien if ((off & 1) != 0) 2385130561Sobrien off &= ~1; 2386130561Sobrien else 2387130561Sobrien { 238899461Sobrien bfd_put_64 (output_bfd, relocation, 238999461Sobrien htab->sgot->contents + off); 2390130561Sobrien h->got.offset |= 1; 2391130561Sobrien } 2392130561Sobrien } 239399461Sobrien else 2394130561Sobrien unresolved_reloc = FALSE; 2395130561Sobrien } 2396130561Sobrien else 2397130561Sobrien { 239899461Sobrien if (local_got_offsets == NULL) 239999461Sobrien abort (); 240099461Sobrien 2401130561Sobrien off = local_got_offsets[r_symndx]; 240299461Sobrien 2403130561Sobrien /* The offset must always be a multiple of 8. We use 2404130561Sobrien the least significant bit to record whether we have 2405130561Sobrien already generated the necessary reloc. */ 2406130561Sobrien if ((off & 1) != 0) 2407130561Sobrien off &= ~1; 2408130561Sobrien else 2409130561Sobrien { 2410130561Sobrien bfd_put_64 (output_bfd, relocation, 241199461Sobrien htab->sgot->contents + off); 241299461Sobrien 2413130561Sobrien if (info->shared) 2414130561Sobrien { 2415130561Sobrien asection *s; 2416130561Sobrien Elf_Internal_Rela outrel; 2417130561Sobrien bfd_byte *loc; 241899461Sobrien 2419130561Sobrien s = htab->srelgot; 2420130561Sobrien if (s == NULL) 242199461Sobrien abort (); 242299461Sobrien 2423130561Sobrien outrel.r_offset = (htab->sgot->output_section->vma 2424130561Sobrien + htab->sgot->output_offset 2425130561Sobrien + off); 2426130561Sobrien outrel.r_info = ELF64_R_INFO (0, R_390_RELATIVE); 242799461Sobrien outrel.r_addend = relocation; 2428130561Sobrien loc = s->contents; 2429130561Sobrien loc += s->reloc_count++ * sizeof (Elf64_External_Rela); 2430130561Sobrien bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc); 2431130561Sobrien } 243299461Sobrien 2433130561Sobrien local_got_offsets[r_symndx] |= 1; 2434130561Sobrien } 2435130561Sobrien } 243699461Sobrien 243799461Sobrien if (off >= (bfd_vma) -2) 243899461Sobrien abort (); 243999461Sobrien 244099461Sobrien relocation = htab->sgot->output_offset + off; 244199461Sobrien 2442130561Sobrien /* For @GOTENT the relocation is against the offset between 2443130561Sobrien the instruction and the symbols entry in the GOT and not 2444130561Sobrien between the start of the GOT and the symbols entry. We 2445130561Sobrien add the vma of the GOT to get the correct value. */ 2446130561Sobrien if ( r_type == R_390_GOTENT 2447130561Sobrien || r_type == R_390_GOTPLTENT) 244899461Sobrien relocation += htab->sgot->output_section->vma; 244999461Sobrien 2450130561Sobrien break; 245199461Sobrien 2452130561Sobrien case R_390_GOTOFF16: 2453130561Sobrien case R_390_GOTOFF32: 2454130561Sobrien case R_390_GOTOFF64: 2455130561Sobrien /* Relocation is relative to the start of the global offset 2456130561Sobrien table. */ 245799461Sobrien 2458130561Sobrien /* Note that sgot->output_offset is not involved in this 2459130561Sobrien calculation. We always want the start of .got. If we 2460130561Sobrien defined _GLOBAL_OFFSET_TABLE in a different way, as is 2461130561Sobrien permitted by the ABI, we might have to change this 2462130561Sobrien calculation. */ 2463130561Sobrien relocation -= htab->sgot->output_section->vma; 2464130561Sobrien break; 246599461Sobrien 2466130561Sobrien case R_390_GOTPC: 246799461Sobrien case R_390_GOTPCDBL: 2468130561Sobrien /* Use global offset table as symbol value. */ 2469130561Sobrien relocation = htab->sgot->output_section->vma; 2470130561Sobrien unresolved_reloc = FALSE; 2471130561Sobrien break; 247299461Sobrien 2473130561Sobrien case R_390_PLT16DBL: 2474130561Sobrien case R_390_PLT32: 2475130561Sobrien case R_390_PLT32DBL: 2476130561Sobrien case R_390_PLT64: 2477130561Sobrien /* Relocation is to the entry for this symbol in the 2478130561Sobrien procedure linkage table. */ 247999461Sobrien 2480130561Sobrien /* Resolve a PLT32 reloc against a local symbol directly, 2481130561Sobrien without using the procedure linkage table. */ 2482130561Sobrien if (h == NULL) 2483130561Sobrien break; 248499461Sobrien 2485130561Sobrien if (h->plt.offset == (bfd_vma) -1 248699461Sobrien || htab->splt == NULL) 2487130561Sobrien { 2488130561Sobrien /* We didn't make a PLT entry for this symbol. This 2489130561Sobrien happens when statically linking PIC code, or when 2490130561Sobrien using -Bsymbolic. */ 2491130561Sobrien break; 2492130561Sobrien } 249399461Sobrien 2494130561Sobrien relocation = (htab->splt->output_section->vma 2495130561Sobrien + htab->splt->output_offset 2496130561Sobrien + h->plt.offset); 2497130561Sobrien unresolved_reloc = FALSE; 2498130561Sobrien break; 249999461Sobrien 2500130561Sobrien case R_390_PLTOFF16: 2501130561Sobrien case R_390_PLTOFF32: 2502130561Sobrien case R_390_PLTOFF64: 2503130561Sobrien /* Relocation is to the entry for this symbol in the 2504130561Sobrien procedure linkage table relative to the start of the GOT. */ 2505130561Sobrien 2506130561Sobrien /* For local symbols or if we didn't make a PLT entry for 2507130561Sobrien this symbol resolve the symbol directly. */ 2508130561Sobrien if ( h == NULL 2509130561Sobrien || h->plt.offset == (bfd_vma) -1 2510130561Sobrien || htab->splt == NULL) 2511130561Sobrien { 2512130561Sobrien relocation -= htab->sgot->output_section->vma; 2513130561Sobrien break; 2514130561Sobrien } 2515130561Sobrien 2516130561Sobrien relocation = (htab->splt->output_section->vma 2517130561Sobrien + htab->splt->output_offset 2518130561Sobrien + h->plt.offset 2519130561Sobrien - htab->sgot->output_section->vma); 2520130561Sobrien unresolved_reloc = FALSE; 2521130561Sobrien break; 2522130561Sobrien 2523130561Sobrien case R_390_8: 2524130561Sobrien case R_390_16: 2525130561Sobrien case R_390_32: 2526130561Sobrien case R_390_64: 2527130561Sobrien case R_390_PC16: 2528130561Sobrien case R_390_PC16DBL: 2529130561Sobrien case R_390_PC32: 253099461Sobrien case R_390_PC32DBL: 2531130561Sobrien case R_390_PC64: 2532218822Sdim if ((input_section->flags & SEC_ALLOC) == 0) 253399461Sobrien break; 253499461Sobrien 2535130561Sobrien if ((info->shared 2536130561Sobrien && (h == NULL 2537130561Sobrien || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT 2538130561Sobrien || h->root.type != bfd_link_hash_undefweak) 253999461Sobrien && ((r_type != R_390_PC16 254099461Sobrien && r_type != R_390_PC16DBL 254199461Sobrien && r_type != R_390_PC32 254299461Sobrien && r_type != R_390_PC32DBL 254399461Sobrien && r_type != R_390_PC64) 254499461Sobrien || (h != NULL 2545130561Sobrien && !SYMBOL_REFERENCES_LOCAL (info, h)))) 2546130561Sobrien || (ELIMINATE_COPY_RELOCS 2547130561Sobrien && !info->shared 254899461Sobrien && h != NULL 254999461Sobrien && h->dynindx != -1 2550218822Sdim && !h->non_got_ref 2551218822Sdim && ((h->def_dynamic 2552218822Sdim && !h->def_regular) 255399461Sobrien || h->root.type == bfd_link_hash_undefweak 255499461Sobrien || h->root.type == bfd_link_hash_undefined))) 2555130561Sobrien { 2556130561Sobrien Elf_Internal_Rela outrel; 2557130561Sobrien bfd_boolean skip, relocate; 255899461Sobrien asection *sreloc; 2559130561Sobrien bfd_byte *loc; 256099461Sobrien 2561130561Sobrien /* When generating a shared object, these relocations 2562130561Sobrien are copied into the output file to be resolved at run 2563130561Sobrien time. */ 2564130561Sobrien skip = FALSE; 2565130561Sobrien relocate = FALSE; 256699461Sobrien 256799461Sobrien outrel.r_offset = 256899461Sobrien _bfd_elf_section_offset (output_bfd, info, input_section, 256999461Sobrien rel->r_offset); 257099461Sobrien if (outrel.r_offset == (bfd_vma) -1) 2571130561Sobrien skip = TRUE; 257299461Sobrien else if (outrel.r_offset == (bfd_vma) -2) 2573130561Sobrien skip = TRUE, relocate = TRUE; 257499461Sobrien 2575130561Sobrien outrel.r_offset += (input_section->output_section->vma 2576130561Sobrien + input_section->output_offset); 257799461Sobrien 2578130561Sobrien if (skip) 257999461Sobrien memset (&outrel, 0, sizeof outrel); 2580130561Sobrien else if (h != NULL 258199461Sobrien && h->dynindx != -1 258299461Sobrien && (r_type == R_390_PC16 258399461Sobrien || r_type == R_390_PC16DBL 258499461Sobrien || r_type == R_390_PC32 258599461Sobrien || r_type == R_390_PC32DBL 258699461Sobrien || r_type == R_390_PC64 258799461Sobrien || !info->shared 258899461Sobrien || !info->symbolic 2589218822Sdim || !h->def_regular)) 2590130561Sobrien { 2591130561Sobrien outrel.r_info = ELF64_R_INFO (h->dynindx, r_type); 259299461Sobrien outrel.r_addend = rel->r_addend; 2593130561Sobrien } 2594130561Sobrien else 2595130561Sobrien { 259699461Sobrien /* This symbol is local, or marked to become local. */ 259799461Sobrien outrel.r_addend = relocation + rel->r_addend; 2598130561Sobrien if (r_type == R_390_64) 2599130561Sobrien { 2600130561Sobrien relocate = TRUE; 2601130561Sobrien outrel.r_info = ELF64_R_INFO (0, R_390_RELATIVE); 2602130561Sobrien } 2603130561Sobrien else 2604130561Sobrien { 2605130561Sobrien long sindx; 2606130561Sobrien 2607130561Sobrien if (bfd_is_abs_section (sec)) 2608130561Sobrien sindx = 0; 2609130561Sobrien else if (sec == NULL || sec->owner == NULL) 2610130561Sobrien { 2611130561Sobrien bfd_set_error(bfd_error_bad_value); 2612130561Sobrien return FALSE; 2613130561Sobrien } 2614130561Sobrien else 2615130561Sobrien { 2616130561Sobrien asection *osec; 2617130561Sobrien 2618130561Sobrien osec = sec->output_section; 2619130561Sobrien sindx = elf_section_data (osec)->dynindx; 2620130561Sobrien 2621218822Sdim if (sindx == 0) 2622218822Sdim { 2623218822Sdim osec = htab->elf.text_index_section; 2624218822Sdim sindx = elf_section_data (osec)->dynindx; 2625218822Sdim } 2626218822Sdim BFD_ASSERT (sindx != 0); 2627218822Sdim 2628130561Sobrien /* We are turning this relocation into one 2629130561Sobrien against a section symbol, so subtract out 2630130561Sobrien the output section's address but not the 2631130561Sobrien offset of the input section in the output 2632130561Sobrien section. */ 2633130561Sobrien outrel.r_addend -= osec->vma; 2634130561Sobrien } 2635130561Sobrien outrel.r_info = ELF64_R_INFO (sindx, r_type); 2636130561Sobrien } 263799461Sobrien } 263899461Sobrien 263999461Sobrien sreloc = elf_section_data (input_section)->sreloc; 264099461Sobrien if (sreloc == NULL) 264199461Sobrien abort (); 264299461Sobrien 2643130561Sobrien loc = sreloc->contents; 2644130561Sobrien loc += sreloc->reloc_count++ * sizeof (Elf64_External_Rela); 2645130561Sobrien bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc); 264699461Sobrien 2647130561Sobrien /* If this reloc is against an external symbol, we do 2648130561Sobrien not want to fiddle with the addend. Otherwise, we 2649130561Sobrien need to include the symbol value so that it becomes 2650130561Sobrien an addend for the dynamic reloc. */ 2651130561Sobrien if (! relocate) 2652130561Sobrien continue; 2653130561Sobrien } 265499461Sobrien 2655130561Sobrien break; 265699461Sobrien 2657130561Sobrien /* Relocations for tls literal pool entries. */ 2658130561Sobrien case R_390_TLS_IE64: 2659130561Sobrien if (info->shared) 2660130561Sobrien { 2661130561Sobrien Elf_Internal_Rela outrel; 2662130561Sobrien asection *sreloc; 2663130561Sobrien bfd_byte *loc; 266499461Sobrien 2665130561Sobrien outrel.r_offset = rel->r_offset 2666130561Sobrien + input_section->output_section->vma 2667130561Sobrien + input_section->output_offset; 2668130561Sobrien outrel.r_info = ELF64_R_INFO (0, R_390_RELATIVE); 2669130561Sobrien sreloc = elf_section_data (input_section)->sreloc; 2670130561Sobrien if (sreloc == NULL) 2671130561Sobrien abort (); 2672130561Sobrien loc = sreloc->contents; 2673130561Sobrien loc += sreloc->reloc_count++ * sizeof (Elf64_External_Rela); 2674130561Sobrien bfd_elf64_swap_reloc_out (output_bfd, &outrel, loc); 2675130561Sobrien } 2676130561Sobrien /* Fall through. */ 2677130561Sobrien 2678130561Sobrien case R_390_TLS_GD64: 2679130561Sobrien case R_390_TLS_GOTIE64: 2680130561Sobrien r_type = elf_s390_tls_transition (info, r_type, h == NULL); 2681130561Sobrien tls_type = GOT_UNKNOWN; 2682130561Sobrien if (h == NULL && local_got_offsets) 2683130561Sobrien tls_type = elf_s390_local_got_tls_type (input_bfd) [r_symndx]; 2684130561Sobrien else if (h != NULL) 2685130561Sobrien { 2686130561Sobrien tls_type = elf_s390_hash_entry(h)->tls_type; 2687130561Sobrien if (!info->shared && h->dynindx == -1 && tls_type >= GOT_TLS_IE) 2688130561Sobrien r_type = R_390_TLS_LE64; 2689130561Sobrien } 2690130561Sobrien if (r_type == R_390_TLS_GD64 && tls_type >= GOT_TLS_IE) 2691130561Sobrien r_type = R_390_TLS_IE64; 2692130561Sobrien 2693130561Sobrien if (r_type == R_390_TLS_LE64) 2694130561Sobrien { 2695130561Sobrien /* This relocation gets optimized away by the local exec 2696130561Sobrien access optimization. */ 2697130561Sobrien BFD_ASSERT (! unresolved_reloc); 2698130561Sobrien bfd_put_64 (output_bfd, -tpoff (info, relocation), 2699130561Sobrien contents + rel->r_offset); 2700130561Sobrien continue; 2701130561Sobrien } 2702130561Sobrien 2703130561Sobrien if (htab->sgot == NULL) 2704130561Sobrien abort (); 2705130561Sobrien 2706130561Sobrien if (h != NULL) 2707130561Sobrien off = h->got.offset; 2708130561Sobrien else 2709130561Sobrien { 2710130561Sobrien if (local_got_offsets == NULL) 2711130561Sobrien abort (); 2712130561Sobrien 2713130561Sobrien off = local_got_offsets[r_symndx]; 2714130561Sobrien } 2715130561Sobrien 2716130561Sobrien emit_tls_relocs: 2717130561Sobrien 2718130561Sobrien if ((off & 1) != 0) 2719130561Sobrien off &= ~1; 2720130561Sobrien else 2721130561Sobrien { 2722130561Sobrien Elf_Internal_Rela outrel; 2723130561Sobrien bfd_byte *loc; 2724130561Sobrien int dr_type, indx; 2725130561Sobrien 2726130561Sobrien if (htab->srelgot == NULL) 2727130561Sobrien abort (); 2728130561Sobrien 2729130561Sobrien outrel.r_offset = (htab->sgot->output_section->vma 2730130561Sobrien + htab->sgot->output_offset + off); 2731130561Sobrien 2732130561Sobrien indx = h && h->dynindx != -1 ? h->dynindx : 0; 2733130561Sobrien if (r_type == R_390_TLS_GD64) 2734130561Sobrien dr_type = R_390_TLS_DTPMOD; 2735130561Sobrien else 2736130561Sobrien dr_type = R_390_TLS_TPOFF; 2737130561Sobrien if (dr_type == R_390_TLS_TPOFF && indx == 0) 2738130561Sobrien outrel.r_addend = relocation - dtpoff_base (info); 2739130561Sobrien else 2740130561Sobrien outrel.r_addend = 0; 2741130561Sobrien outrel.r_info = ELF64_R_INFO (indx, dr_type); 2742130561Sobrien loc = htab->srelgot->contents; 2743130561Sobrien loc += htab->srelgot->reloc_count++ 2744130561Sobrien * sizeof (Elf64_External_Rela); 2745130561Sobrien bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc); 2746130561Sobrien 2747130561Sobrien if (r_type == R_390_TLS_GD64) 2748130561Sobrien { 2749130561Sobrien if (indx == 0) 2750130561Sobrien { 2751130561Sobrien BFD_ASSERT (! unresolved_reloc); 2752130561Sobrien bfd_put_64 (output_bfd, 2753130561Sobrien relocation - dtpoff_base (info), 2754130561Sobrien htab->sgot->contents + off + GOT_ENTRY_SIZE); 2755130561Sobrien } 2756130561Sobrien else 2757130561Sobrien { 2758130561Sobrien outrel.r_info = ELF64_R_INFO (indx, R_390_TLS_DTPOFF); 2759130561Sobrien outrel.r_offset += GOT_ENTRY_SIZE; 2760130561Sobrien outrel.r_addend = 0; 2761130561Sobrien htab->srelgot->reloc_count++; 2762130561Sobrien loc += sizeof (Elf64_External_Rela); 2763130561Sobrien bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc); 2764130561Sobrien } 2765130561Sobrien } 2766130561Sobrien 2767130561Sobrien if (h != NULL) 2768130561Sobrien h->got.offset |= 1; 2769130561Sobrien else 2770130561Sobrien local_got_offsets[r_symndx] |= 1; 2771130561Sobrien } 2772130561Sobrien 2773130561Sobrien if (off >= (bfd_vma) -2) 2774130561Sobrien abort (); 2775130561Sobrien if (r_type == ELF64_R_TYPE (rel->r_info)) 2776130561Sobrien { 2777130561Sobrien relocation = htab->sgot->output_offset + off; 2778130561Sobrien if (r_type == R_390_TLS_IE64 || r_type == R_390_TLS_IEENT) 2779130561Sobrien relocation += htab->sgot->output_section->vma; 2780130561Sobrien unresolved_reloc = FALSE; 2781130561Sobrien } 2782130561Sobrien else 2783130561Sobrien { 2784130561Sobrien bfd_put_64 (output_bfd, htab->sgot->output_offset + off, 2785130561Sobrien contents + rel->r_offset); 2786130561Sobrien continue; 2787130561Sobrien } 2788130561Sobrien break; 2789130561Sobrien 2790130561Sobrien case R_390_TLS_GOTIE12: 2791130561Sobrien case R_390_TLS_GOTIE20: 2792130561Sobrien case R_390_TLS_IEENT: 2793130561Sobrien if (h == NULL) 2794130561Sobrien { 2795130561Sobrien if (local_got_offsets == NULL) 2796130561Sobrien abort(); 2797130561Sobrien off = local_got_offsets[r_symndx]; 2798130561Sobrien if (info->shared) 2799130561Sobrien goto emit_tls_relocs; 2800130561Sobrien } 2801130561Sobrien else 2802130561Sobrien { 2803130561Sobrien off = h->got.offset; 2804130561Sobrien tls_type = elf_s390_hash_entry(h)->tls_type; 2805130561Sobrien if (info->shared || h->dynindx != -1 || tls_type < GOT_TLS_IE) 2806130561Sobrien goto emit_tls_relocs; 2807130561Sobrien } 2808130561Sobrien 2809130561Sobrien if (htab->sgot == NULL) 2810130561Sobrien abort (); 2811130561Sobrien 2812130561Sobrien BFD_ASSERT (! unresolved_reloc); 2813130561Sobrien bfd_put_64 (output_bfd, -tpoff (info, relocation), 2814130561Sobrien htab->sgot->contents + off); 2815130561Sobrien relocation = htab->sgot->output_offset + off; 2816130561Sobrien if (r_type == R_390_TLS_IEENT) 2817130561Sobrien relocation += htab->sgot->output_section->vma; 2818130561Sobrien unresolved_reloc = FALSE; 2819130561Sobrien break; 2820130561Sobrien 2821130561Sobrien case R_390_TLS_LDM64: 2822130561Sobrien if (! info->shared) 2823130561Sobrien /* The literal pool entry this relocation refers to gets ignored 2824130561Sobrien by the optimized code of the local exec model. Do nothing 2825130561Sobrien and the value will turn out zero. */ 2826130561Sobrien continue; 2827130561Sobrien 2828130561Sobrien if (htab->sgot == NULL) 2829130561Sobrien abort (); 2830130561Sobrien 2831130561Sobrien off = htab->tls_ldm_got.offset; 2832130561Sobrien if (off & 1) 2833130561Sobrien off &= ~1; 2834130561Sobrien else 2835130561Sobrien { 2836130561Sobrien Elf_Internal_Rela outrel; 2837130561Sobrien bfd_byte *loc; 2838130561Sobrien 2839130561Sobrien if (htab->srelgot == NULL) 2840130561Sobrien abort (); 2841130561Sobrien 2842130561Sobrien outrel.r_offset = (htab->sgot->output_section->vma 2843130561Sobrien + htab->sgot->output_offset + off); 2844130561Sobrien 2845130561Sobrien bfd_put_64 (output_bfd, 0, 2846130561Sobrien htab->sgot->contents + off + GOT_ENTRY_SIZE); 2847130561Sobrien outrel.r_info = ELF64_R_INFO (0, R_390_TLS_DTPMOD); 2848130561Sobrien outrel.r_addend = 0; 2849130561Sobrien loc = htab->srelgot->contents; 2850130561Sobrien loc += htab->srelgot->reloc_count++ 2851130561Sobrien * sizeof (Elf64_External_Rela); 2852130561Sobrien bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc); 2853130561Sobrien htab->tls_ldm_got.offset |= 1; 2854130561Sobrien } 2855130561Sobrien relocation = htab->sgot->output_offset + off; 2856130561Sobrien unresolved_reloc = FALSE; 2857130561Sobrien break; 2858130561Sobrien 2859130561Sobrien case R_390_TLS_LE64: 2860130561Sobrien if (info->shared) 2861130561Sobrien { 2862130561Sobrien /* Linking a shared library with non-fpic code requires 2863130561Sobrien a R_390_TLS_TPOFF relocation. */ 2864130561Sobrien Elf_Internal_Rela outrel; 2865130561Sobrien asection *sreloc; 2866130561Sobrien bfd_byte *loc; 2867130561Sobrien int indx; 2868130561Sobrien 2869130561Sobrien outrel.r_offset = rel->r_offset 2870130561Sobrien + input_section->output_section->vma 2871130561Sobrien + input_section->output_offset; 2872130561Sobrien if (h != NULL && h->dynindx != -1) 2873130561Sobrien indx = h->dynindx; 2874130561Sobrien else 2875130561Sobrien indx = 0; 2876130561Sobrien outrel.r_info = ELF64_R_INFO (indx, R_390_TLS_TPOFF); 2877130561Sobrien if (indx == 0) 2878130561Sobrien outrel.r_addend = relocation - dtpoff_base (info); 2879130561Sobrien else 2880130561Sobrien outrel.r_addend = 0; 2881130561Sobrien sreloc = elf_section_data (input_section)->sreloc; 2882130561Sobrien if (sreloc == NULL) 2883130561Sobrien abort (); 2884130561Sobrien loc = sreloc->contents; 2885130561Sobrien loc += sreloc->reloc_count++ * sizeof (Elf64_External_Rela); 2886130561Sobrien bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc); 2887130561Sobrien } 2888130561Sobrien else 2889130561Sobrien { 2890130561Sobrien BFD_ASSERT (! unresolved_reloc); 2891130561Sobrien bfd_put_64 (output_bfd, -tpoff (info, relocation), 2892130561Sobrien contents + rel->r_offset); 2893130561Sobrien } 2894130561Sobrien continue; 2895130561Sobrien 2896130561Sobrien case R_390_TLS_LDO64: 2897218822Sdim if (info->shared) 2898130561Sobrien relocation -= dtpoff_base (info); 2899130561Sobrien else 2900130561Sobrien /* When converting LDO to LE, we must negate. */ 2901130561Sobrien relocation = -tpoff (info, relocation); 2902130561Sobrien break; 2903130561Sobrien 2904130561Sobrien /* Relocations for tls instructions. */ 2905130561Sobrien case R_390_TLS_LOAD: 2906130561Sobrien case R_390_TLS_GDCALL: 2907130561Sobrien case R_390_TLS_LDCALL: 2908130561Sobrien tls_type = GOT_UNKNOWN; 2909130561Sobrien if (h == NULL && local_got_offsets) 2910130561Sobrien tls_type = elf_s390_local_got_tls_type (input_bfd) [r_symndx]; 2911130561Sobrien else if (h != NULL) 2912130561Sobrien tls_type = elf_s390_hash_entry(h)->tls_type; 2913130561Sobrien 2914130561Sobrien if (tls_type == GOT_TLS_GD) 2915130561Sobrien continue; 2916130561Sobrien 2917130561Sobrien if (r_type == R_390_TLS_LOAD) 2918130561Sobrien { 2919130561Sobrien if (!info->shared && (h == NULL || h->dynindx == -1)) 2920130561Sobrien { 2921130561Sobrien /* IE->LE transition. Four valid cases: 2922130561Sobrien lg %rx,(0,%ry) -> sllg %rx,%ry,0 2923130561Sobrien lg %rx,(%ry,0) -> sllg %rx,%ry,0 2924130561Sobrien lg %rx,(%ry,%r12) -> sllg %rx,%ry,0 2925130561Sobrien lg %rx,(%r12,%ry) -> sllg %rx,%ry,0 */ 2926130561Sobrien unsigned int insn0, insn1, ry; 2927130561Sobrien 2928130561Sobrien insn0 = bfd_get_32 (input_bfd, contents + rel->r_offset); 2929130561Sobrien insn1 = bfd_get_16 (input_bfd, contents + rel->r_offset + 4); 2930130561Sobrien if (insn1 != 0x0004) 2931130561Sobrien invalid_tls_insn (input_bfd, input_section, rel); 2932130561Sobrien ry = 0; 2933130561Sobrien if ((insn0 & 0xff00f000) == 0xe3000000) 2934130561Sobrien /* lg %rx,0(%ry,0) -> sllg %rx,%ry,0 */ 2935130561Sobrien ry = (insn0 & 0x000f0000); 2936130561Sobrien else if ((insn0 & 0xff0f0000) == 0xe3000000) 2937130561Sobrien /* lg %rx,0(0,%ry) -> sllg %rx,%ry,0 */ 2938130561Sobrien ry = (insn0 & 0x0000f000) << 4; 2939130561Sobrien else if ((insn0 & 0xff00f000) == 0xe300c000) 2940130561Sobrien /* lg %rx,0(%ry,%r12) -> sllg %rx,%ry,0 */ 2941130561Sobrien ry = (insn0 & 0x000f0000); 2942130561Sobrien else if ((insn0 & 0xff0f0000) == 0xe30c0000) 2943130561Sobrien /* lg %rx,0(%r12,%ry) -> sllg %rx,%ry,0 */ 2944130561Sobrien ry = (insn0 & 0x0000f000) << 4; 2945130561Sobrien else 2946130561Sobrien invalid_tls_insn (input_bfd, input_section, rel); 2947130561Sobrien insn0 = 0xeb000000 | (insn0 & 0x00f00000) | ry; 2948130561Sobrien insn1 = 0x000d; 2949130561Sobrien bfd_put_32 (output_bfd, insn0, contents + rel->r_offset); 2950130561Sobrien bfd_put_16 (output_bfd, insn1, contents + rel->r_offset + 4); 2951130561Sobrien } 2952130561Sobrien } 2953130561Sobrien else if (r_type == R_390_TLS_GDCALL) 2954130561Sobrien { 2955130561Sobrien unsigned int insn0, insn1; 2956130561Sobrien 2957130561Sobrien insn0 = bfd_get_32 (input_bfd, contents + rel->r_offset); 2958130561Sobrien insn1 = bfd_get_16 (input_bfd, contents + rel->r_offset + 4); 2959130561Sobrien if ((insn0 & 0xffff0000) != 0xc0e50000) 2960130561Sobrien invalid_tls_insn (input_bfd, input_section, rel); 2961130561Sobrien if (!info->shared && (h == NULL || h->dynindx == -1)) 2962130561Sobrien { 2963130561Sobrien /* GD->LE transition. 2964130561Sobrien brasl %r14,__tls_get_addr@plt -> brcl 0,. */ 2965130561Sobrien insn0 = 0xc0040000; 2966130561Sobrien insn1 = 0x0000; 2967130561Sobrien } 2968130561Sobrien else 2969130561Sobrien { 2970130561Sobrien /* GD->IE transition. 2971130561Sobrien brasl %r14,__tls_get_addr@plt -> lg %r2,0(%r2,%r12) */ 2972130561Sobrien insn0 = 0xe322c000; 2973130561Sobrien insn1 = 0x0004; 2974130561Sobrien } 2975130561Sobrien bfd_put_32 (output_bfd, insn0, contents + rel->r_offset); 2976130561Sobrien bfd_put_16 (output_bfd, insn1, contents + rel->r_offset + 4); 2977130561Sobrien } 2978130561Sobrien else if (r_type == R_390_TLS_LDCALL) 2979130561Sobrien { 2980130561Sobrien if (!info->shared) 2981130561Sobrien { 2982130561Sobrien unsigned int insn0, insn1; 2983130561Sobrien 2984130561Sobrien insn0 = bfd_get_32 (input_bfd, contents + rel->r_offset); 2985130561Sobrien insn1 = bfd_get_16 (input_bfd, contents + rel->r_offset + 4); 2986130561Sobrien if ((insn0 & 0xffff0000) != 0xc0e50000) 2987130561Sobrien invalid_tls_insn (input_bfd, input_section, rel); 2988130561Sobrien /* LD->LE transition. 2989130561Sobrien brasl %r14,__tls_get_addr@plt -> brcl 0,. */ 2990130561Sobrien insn0 = 0xc0040000; 2991130561Sobrien insn1 = 0x0000; 2992130561Sobrien bfd_put_32 (output_bfd, insn0, contents + rel->r_offset); 2993130561Sobrien bfd_put_16 (output_bfd, insn1, contents + rel->r_offset + 4); 2994130561Sobrien } 2995130561Sobrien } 2996130561Sobrien continue; 2997130561Sobrien 2998130561Sobrien default: 2999130561Sobrien break; 3000130561Sobrien } 3001130561Sobrien 3002107492Sobrien /* Dynamic relocs are not propagated for SEC_DEBUGGING sections 3003107492Sobrien because such sections are not SEC_ALLOC and thus ld.so will 3004107492Sobrien not process them. */ 300599461Sobrien if (unresolved_reloc 3006107492Sobrien && !((input_section->flags & SEC_DEBUGGING) != 0 3007218822Sdim && h->def_dynamic)) 300899461Sobrien (*_bfd_error_handler) 3009218822Sdim (_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"), 3010218822Sdim input_bfd, 3011218822Sdim input_section, 301299461Sobrien (long) rel->r_offset, 3013218822Sdim howto->name, 301499461Sobrien h->root.root.string); 301599461Sobrien 3016130561Sobrien if (r_type == R_390_20 3017130561Sobrien || r_type == R_390_GOT20 3018130561Sobrien || r_type == R_390_GOTPLT20 3019130561Sobrien || r_type == R_390_TLS_GOTIE20) 3020130561Sobrien { 3021130561Sobrien relocation += rel->r_addend; 3022130561Sobrien relocation = (relocation&0xfff) << 8 | (relocation&0xff000) >> 12; 3023130561Sobrien r = _bfd_final_link_relocate (howto, input_bfd, input_section, 3024130561Sobrien contents, rel->r_offset, 3025130561Sobrien relocation, 0); 3026130561Sobrien } 3027130561Sobrien else 3028130561Sobrien r = _bfd_final_link_relocate (howto, input_bfd, input_section, 302999461Sobrien contents, rel->r_offset, 303099461Sobrien relocation, rel->r_addend); 303199461Sobrien 303299461Sobrien if (r != bfd_reloc_ok) 303399461Sobrien { 303499461Sobrien const char *name; 303599461Sobrien 303699461Sobrien if (h != NULL) 303799461Sobrien name = h->root.root.string; 303899461Sobrien else 303999461Sobrien { 304099461Sobrien name = bfd_elf_string_from_elf_section (input_bfd, 304199461Sobrien symtab_hdr->sh_link, 304299461Sobrien sym->st_name); 304399461Sobrien if (name == NULL) 3044130561Sobrien return FALSE; 304599461Sobrien if (*name == '\0') 304699461Sobrien name = bfd_section_name (input_bfd, sec); 304799461Sobrien } 304899461Sobrien 304999461Sobrien if (r == bfd_reloc_overflow) 305099461Sobrien { 305199461Sobrien 305299461Sobrien if (! ((*info->callbacks->reloc_overflow) 3053218822Sdim (info, (h ? &h->root : NULL), name, howto->name, 3054218822Sdim (bfd_vma) 0, input_bfd, input_section, 3055218822Sdim rel->r_offset))) 3056130561Sobrien return FALSE; 305799461Sobrien } 305899461Sobrien else 305999461Sobrien { 306099461Sobrien (*_bfd_error_handler) 3061218822Sdim (_("%B(%A+0x%lx): reloc against `%s': error %d"), 3062218822Sdim input_bfd, input_section, 306399461Sobrien (long) rel->r_offset, name, (int) r); 3064130561Sobrien return FALSE; 306599461Sobrien } 306699461Sobrien } 306799461Sobrien } 306899461Sobrien 3069130561Sobrien return TRUE; 307099461Sobrien} 307199461Sobrien 307299461Sobrien/* Finish up dynamic symbol handling. We set the contents of various 307399461Sobrien dynamic sections here. */ 307499461Sobrien 3075130561Sobrienstatic bfd_boolean 307699461Sobrienelf_s390_finish_dynamic_symbol (output_bfd, info, h, sym) 307799461Sobrien bfd *output_bfd; 307899461Sobrien struct bfd_link_info *info; 307999461Sobrien struct elf_link_hash_entry *h; 308099461Sobrien Elf_Internal_Sym *sym; 308199461Sobrien{ 308299461Sobrien struct elf_s390_link_hash_table *htab; 308399461Sobrien 308499461Sobrien htab = elf_s390_hash_table (info); 308599461Sobrien 308699461Sobrien if (h->plt.offset != (bfd_vma) -1) 308799461Sobrien { 308899461Sobrien bfd_vma plt_index; 308999461Sobrien bfd_vma got_offset; 309099461Sobrien Elf_Internal_Rela rela; 3091130561Sobrien bfd_byte *loc; 309299461Sobrien 309399461Sobrien /* This symbol has an entry in the procedure linkage table. Set 3094130561Sobrien it up. */ 309599461Sobrien 309699461Sobrien if (h->dynindx == -1 309799461Sobrien || htab->splt == NULL 309899461Sobrien || htab->sgotplt == NULL 309999461Sobrien || htab->srelplt == NULL) 310099461Sobrien abort (); 310199461Sobrien 310299461Sobrien /* Calc. index no. 3103130561Sobrien Current offset - size first entry / entry size. */ 310499461Sobrien plt_index = (h->plt.offset - PLT_FIRST_ENTRY_SIZE) / PLT_ENTRY_SIZE; 310599461Sobrien 310699461Sobrien /* Offset in GOT is PLT index plus GOT headers(3) times 8, 3107130561Sobrien addr & GOT addr. */ 310899461Sobrien got_offset = (plt_index + 3) * GOT_ENTRY_SIZE; 310999461Sobrien 311099461Sobrien /* Fill in the blueprint of a PLT. */ 311199461Sobrien bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD0, 311299461Sobrien htab->splt->contents + h->plt.offset); 311399461Sobrien bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD1, 311499461Sobrien htab->splt->contents + h->plt.offset + 4); 311599461Sobrien bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD2, 311699461Sobrien htab->splt->contents + h->plt.offset + 8); 311799461Sobrien bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD3, 311899461Sobrien htab->splt->contents + h->plt.offset + 12); 311999461Sobrien bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD4, 312099461Sobrien htab->splt->contents + h->plt.offset + 16); 312199461Sobrien bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD5, 312299461Sobrien htab->splt->contents + h->plt.offset + 20); 312399461Sobrien bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD6, 312499461Sobrien htab->splt->contents + h->plt.offset + 24); 312599461Sobrien bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD7, 312699461Sobrien htab->splt->contents + h->plt.offset + 28); 312799461Sobrien /* Fixup the relative address to the GOT entry */ 312899461Sobrien bfd_put_32 (output_bfd, 312999461Sobrien (htab->sgotplt->output_section->vma + 313099461Sobrien htab->sgotplt->output_offset + got_offset 313199461Sobrien - (htab->splt->output_section->vma + h->plt.offset))/2, 313299461Sobrien htab->splt->contents + h->plt.offset + 2); 313399461Sobrien /* Fixup the relative branch to PLT 0 */ 313499461Sobrien bfd_put_32 (output_bfd, - (PLT_FIRST_ENTRY_SIZE + 313599461Sobrien (PLT_ENTRY_SIZE * plt_index) + 22)/2, 313699461Sobrien htab->splt->contents + h->plt.offset + 24); 313799461Sobrien /* Fixup offset into symbol table */ 313899461Sobrien bfd_put_32 (output_bfd, plt_index * sizeof (Elf64_External_Rela), 313999461Sobrien htab->splt->contents + h->plt.offset + 28); 314099461Sobrien 314199461Sobrien /* Fill in the entry in the global offset table. 3142130561Sobrien Points to instruction after GOT offset. */ 314399461Sobrien bfd_put_64 (output_bfd, 314499461Sobrien (htab->splt->output_section->vma 314599461Sobrien + htab->splt->output_offset 314699461Sobrien + h->plt.offset 314799461Sobrien + 14), 314899461Sobrien htab->sgotplt->contents + got_offset); 314999461Sobrien 315099461Sobrien /* Fill in the entry in the .rela.plt section. */ 315199461Sobrien rela.r_offset = (htab->sgotplt->output_section->vma 315299461Sobrien + htab->sgotplt->output_offset 315399461Sobrien + got_offset); 315499461Sobrien rela.r_info = ELF64_R_INFO (h->dynindx, R_390_JMP_SLOT); 315599461Sobrien rela.r_addend = 0; 3156130561Sobrien loc = htab->srelplt->contents + plt_index * sizeof (Elf64_External_Rela); 315799461Sobrien bfd_elf64_swap_reloca_out (output_bfd, &rela, loc); 315899461Sobrien 3159218822Sdim if (!h->def_regular) 316099461Sobrien { 316199461Sobrien /* Mark the symbol as undefined, rather than as defined in 316299461Sobrien the .plt section. Leave the value alone. This is a clue 316399461Sobrien for the dynamic linker, to make function pointer 316499461Sobrien comparisons work between an application and shared 316599461Sobrien library. */ 316699461Sobrien sym->st_shndx = SHN_UNDEF; 316799461Sobrien } 316899461Sobrien } 316999461Sobrien 3170130561Sobrien if (h->got.offset != (bfd_vma) -1 3171130561Sobrien && elf_s390_hash_entry(h)->tls_type != GOT_TLS_GD 3172130561Sobrien && elf_s390_hash_entry(h)->tls_type != GOT_TLS_IE 3173130561Sobrien && elf_s390_hash_entry(h)->tls_type != GOT_TLS_IE_NLT) 317499461Sobrien { 317599461Sobrien Elf_Internal_Rela rela; 3176130561Sobrien bfd_byte *loc; 317799461Sobrien 317899461Sobrien /* This symbol has an entry in the global offset table. Set it 3179130561Sobrien up. */ 318099461Sobrien if (htab->sgot == NULL || htab->srelgot == NULL) 318199461Sobrien abort (); 318299461Sobrien 318399461Sobrien rela.r_offset = (htab->sgot->output_section->vma 318499461Sobrien + htab->sgot->output_offset 318599461Sobrien + (h->got.offset &~ (bfd_vma) 1)); 318699461Sobrien 318799461Sobrien /* If this is a static link, or it is a -Bsymbolic link and the 318899461Sobrien symbol is defined locally or was forced to be local because 318999461Sobrien of a version file, we just want to emit a RELATIVE reloc. 319099461Sobrien The entry in the global offset table will already have been 319199461Sobrien initialized in the relocate_section function. */ 319299461Sobrien if (info->shared 319399461Sobrien && (info->symbolic 319499461Sobrien || h->dynindx == -1 3195218822Sdim || h->forced_local) 3196218822Sdim && h->def_regular) 3197130561Sobrien { 319899461Sobrien BFD_ASSERT((h->got.offset & 1) != 0); 3199130561Sobrien rela.r_info = ELF64_R_INFO (0, R_390_RELATIVE); 3200130561Sobrien rela.r_addend = (h->root.u.def.value 3201130561Sobrien + h->root.u.def.section->output_section->vma 3202130561Sobrien + h->root.u.def.section->output_offset); 3203130561Sobrien } 320499461Sobrien else 320599461Sobrien { 320699461Sobrien BFD_ASSERT((h->got.offset & 1) == 0); 320799461Sobrien bfd_put_64 (output_bfd, (bfd_vma) 0, htab->sgot->contents + h->got.offset); 320899461Sobrien rela.r_info = ELF64_R_INFO (h->dynindx, R_390_GLOB_DAT); 3209130561Sobrien rela.r_addend = 0; 3210130561Sobrien } 321199461Sobrien 3212130561Sobrien loc = htab->srelgot->contents; 3213130561Sobrien loc += htab->srelgot->reloc_count++ * sizeof (Elf64_External_Rela); 321499461Sobrien bfd_elf64_swap_reloca_out (output_bfd, &rela, loc); 321599461Sobrien } 321699461Sobrien 3217218822Sdim if (h->needs_copy) 321899461Sobrien { 321999461Sobrien Elf_Internal_Rela rela; 3220130561Sobrien bfd_byte *loc; 322199461Sobrien 322299461Sobrien /* This symbols needs a copy reloc. Set it up. */ 322399461Sobrien 322499461Sobrien if (h->dynindx == -1 322599461Sobrien || (h->root.type != bfd_link_hash_defined 322699461Sobrien && h->root.type != bfd_link_hash_defweak) 322799461Sobrien || htab->srelbss == NULL) 322899461Sobrien abort (); 322999461Sobrien 323099461Sobrien rela.r_offset = (h->root.u.def.value 323199461Sobrien + h->root.u.def.section->output_section->vma 323299461Sobrien + h->root.u.def.section->output_offset); 323399461Sobrien rela.r_info = ELF64_R_INFO (h->dynindx, R_390_COPY); 323499461Sobrien rela.r_addend = 0; 3235130561Sobrien loc = htab->srelbss->contents; 3236130561Sobrien loc += htab->srelbss->reloc_count++ * sizeof (Elf64_External_Rela); 323799461Sobrien bfd_elf64_swap_reloca_out (output_bfd, &rela, loc); 323899461Sobrien } 323999461Sobrien 324099461Sobrien /* Mark some specially defined symbols as absolute. */ 324199461Sobrien if (strcmp (h->root.root.string, "_DYNAMIC") == 0 3242218822Sdim || h == htab->elf.hgot 3243218822Sdim || h == htab->elf.hplt) 324499461Sobrien sym->st_shndx = SHN_ABS; 324599461Sobrien 3246130561Sobrien return TRUE; 324799461Sobrien} 324899461Sobrien 324999461Sobrien/* Used to decide how to sort relocs in an optimal manner for the 325099461Sobrien dynamic linker, before writing them out. */ 325199461Sobrien 325299461Sobrienstatic enum elf_reloc_type_class 325399461Sobrienelf_s390_reloc_type_class (rela) 325499461Sobrien const Elf_Internal_Rela *rela; 325599461Sobrien{ 325699461Sobrien switch ((int) ELF64_R_TYPE (rela->r_info)) 325799461Sobrien { 325899461Sobrien case R_390_RELATIVE: 325999461Sobrien return reloc_class_relative; 326099461Sobrien case R_390_JMP_SLOT: 326199461Sobrien return reloc_class_plt; 326299461Sobrien case R_390_COPY: 326399461Sobrien return reloc_class_copy; 326499461Sobrien default: 326599461Sobrien return reloc_class_normal; 326699461Sobrien } 326799461Sobrien} 326899461Sobrien 326999461Sobrien/* Finish up the dynamic sections. */ 327099461Sobrien 3271130561Sobrienstatic bfd_boolean 327299461Sobrienelf_s390_finish_dynamic_sections (output_bfd, info) 327399461Sobrien bfd *output_bfd; 327499461Sobrien struct bfd_link_info *info; 327599461Sobrien{ 327699461Sobrien struct elf_s390_link_hash_table *htab; 327799461Sobrien bfd *dynobj; 327899461Sobrien asection *sdyn; 327999461Sobrien 328099461Sobrien htab = elf_s390_hash_table (info); 328199461Sobrien dynobj = htab->elf.dynobj; 328299461Sobrien sdyn = bfd_get_section_by_name (dynobj, ".dynamic"); 328399461Sobrien 328499461Sobrien if (htab->elf.dynamic_sections_created) 328599461Sobrien { 328699461Sobrien Elf64_External_Dyn *dyncon, *dynconend; 328799461Sobrien 328899461Sobrien if (sdyn == NULL || htab->sgot == NULL) 328999461Sobrien abort (); 329099461Sobrien 329199461Sobrien dyncon = (Elf64_External_Dyn *) sdyn->contents; 3292218822Sdim dynconend = (Elf64_External_Dyn *) (sdyn->contents + sdyn->size); 329399461Sobrien for (; dyncon < dynconend; dyncon++) 329499461Sobrien { 329599461Sobrien Elf_Internal_Dyn dyn; 329699461Sobrien asection *s; 329799461Sobrien 329899461Sobrien bfd_elf64_swap_dyn_in (dynobj, dyncon, &dyn); 329999461Sobrien 330099461Sobrien switch (dyn.d_tag) 330199461Sobrien { 330299461Sobrien default: 330399461Sobrien continue; 330499461Sobrien 330599461Sobrien case DT_PLTGOT: 330699461Sobrien dyn.d_un.d_ptr = htab->sgot->output_section->vma; 330799461Sobrien break; 330899461Sobrien 330999461Sobrien case DT_JMPREL: 331099461Sobrien dyn.d_un.d_ptr = htab->srelplt->output_section->vma; 331199461Sobrien break; 331299461Sobrien 331399461Sobrien case DT_PLTRELSZ: 331499461Sobrien s = htab->srelplt->output_section; 3315218822Sdim dyn.d_un.d_val = s->size; 331699461Sobrien break; 331799461Sobrien 331899461Sobrien case DT_RELASZ: 331999461Sobrien /* The procedure linkage table relocs (DT_JMPREL) should 332099461Sobrien not be included in the overall relocs (DT_RELA). 332199461Sobrien Therefore, we override the DT_RELASZ entry here to 332299461Sobrien make it not include the JMPREL relocs. Since the 332399461Sobrien linker script arranges for .rela.plt to follow all 332499461Sobrien other relocation sections, we don't have to worry 332599461Sobrien about changing the DT_RELA entry. */ 332699461Sobrien s = htab->srelplt->output_section; 3327218822Sdim dyn.d_un.d_val -= s->size; 332899461Sobrien break; 332999461Sobrien } 333099461Sobrien 333199461Sobrien bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon); 333299461Sobrien } 333399461Sobrien 333499461Sobrien /* Fill in the special first entry in the procedure linkage table. */ 3335218822Sdim if (htab->splt && htab->splt->size > 0) 333699461Sobrien { 333799461Sobrien /* fill in blueprint for plt 0 entry */ 333899461Sobrien bfd_put_32 (output_bfd, (bfd_vma) PLT_FIRST_ENTRY_WORD0, 333999461Sobrien htab->splt->contents ); 334099461Sobrien bfd_put_32 (output_bfd, (bfd_vma) PLT_FIRST_ENTRY_WORD1, 334199461Sobrien htab->splt->contents +4 ); 334299461Sobrien bfd_put_32 (output_bfd, (bfd_vma) PLT_FIRST_ENTRY_WORD3, 334399461Sobrien htab->splt->contents +12 ); 334499461Sobrien bfd_put_32 (output_bfd, (bfd_vma) PLT_FIRST_ENTRY_WORD4, 334599461Sobrien htab->splt->contents +16 ); 334699461Sobrien bfd_put_32 (output_bfd, (bfd_vma) PLT_FIRST_ENTRY_WORD5, 334799461Sobrien htab->splt->contents +20 ); 334899461Sobrien bfd_put_32 (output_bfd, (bfd_vma) PLT_FIRST_ENTRY_WORD6, 334999461Sobrien htab->splt->contents + 24); 335099461Sobrien bfd_put_32 (output_bfd, (bfd_vma) PLT_FIRST_ENTRY_WORD7, 335199461Sobrien htab->splt->contents + 28 ); 335299461Sobrien /* Fixup relative address to start of GOT */ 335399461Sobrien bfd_put_32 (output_bfd, 335499461Sobrien (htab->sgotplt->output_section->vma + 335599461Sobrien htab->sgotplt->output_offset 335699461Sobrien - htab->splt->output_section->vma - 6)/2, 335799461Sobrien htab->splt->contents + 8); 335899461Sobrien } 335999461Sobrien elf_section_data (htab->splt->output_section) 336099461Sobrien ->this_hdr.sh_entsize = PLT_ENTRY_SIZE; 336199461Sobrien } 336299461Sobrien 336399461Sobrien if (htab->sgotplt) 336499461Sobrien { 336599461Sobrien /* Fill in the first three entries in the global offset table. */ 3366218822Sdim if (htab->sgotplt->size > 0) 336799461Sobrien { 336899461Sobrien bfd_put_64 (output_bfd, 336999461Sobrien (sdyn == NULL ? (bfd_vma) 0 337099461Sobrien : sdyn->output_section->vma + sdyn->output_offset), 337199461Sobrien htab->sgotplt->contents); 337299461Sobrien /* One entry for shared object struct ptr. */ 337399461Sobrien bfd_put_64 (output_bfd, (bfd_vma) 0, htab->sgotplt->contents + 8); 337499461Sobrien /* One entry for _dl_runtime_resolve. */ 337599461Sobrien bfd_put_64 (output_bfd, (bfd_vma) 0, htab->sgotplt->contents + 12); 337699461Sobrien } 337799461Sobrien 337899461Sobrien elf_section_data (htab->sgot->output_section) 337999461Sobrien ->this_hdr.sh_entsize = 8; 338099461Sobrien } 3381130561Sobrien return TRUE; 338299461Sobrien} 338399461Sobrien 3384218822Sdim/* Return address for Ith PLT stub in section PLT, for relocation REL 3385218822Sdim or (bfd_vma) -1 if it should not be included. */ 3386218822Sdim 3387218822Sdimstatic bfd_vma 3388218822Sdimelf_s390_plt_sym_val (bfd_vma i, const asection *plt, 3389218822Sdim const arelent *rel ATTRIBUTE_UNUSED) 3390218822Sdim{ 3391218822Sdim return plt->vma + PLT_FIRST_ENTRY_SIZE + i * PLT_ENTRY_SIZE; 3392218822Sdim} 3393218822Sdim 3394218822Sdim 3395130561Sobrien/* Why was the hash table entry size definition changed from 3396130561Sobrien ARCH_SIZE/8 to 4? This breaks the 64 bit dynamic linker and 3397130561Sobrien this is the only reason for the s390_elf64_size_info structure. */ 339899461Sobrien 339999461Sobrienconst struct elf_size_info s390_elf64_size_info = 340099461Sobrien{ 340199461Sobrien sizeof (Elf64_External_Ehdr), 340299461Sobrien sizeof (Elf64_External_Phdr), 340399461Sobrien sizeof (Elf64_External_Shdr), 340499461Sobrien sizeof (Elf64_External_Rel), 340599461Sobrien sizeof (Elf64_External_Rela), 340699461Sobrien sizeof (Elf64_External_Sym), 340799461Sobrien sizeof (Elf64_External_Dyn), 340899461Sobrien sizeof (Elf_External_Note), 3409130561Sobrien 8, /* hash-table entry size. */ 3410130561Sobrien 1, /* internal relocations per external relocations. */ 3411130561Sobrien 64, /* arch_size. */ 3412130561Sobrien 3, /* log_file_align. */ 341399461Sobrien ELFCLASS64, EV_CURRENT, 341499461Sobrien bfd_elf64_write_out_phdrs, 341599461Sobrien bfd_elf64_write_shdrs_and_ehdr, 341699461Sobrien bfd_elf64_write_relocs, 3417107492Sobrien bfd_elf64_swap_symbol_in, 341899461Sobrien bfd_elf64_swap_symbol_out, 341999461Sobrien bfd_elf64_slurp_reloc_table, 342099461Sobrien bfd_elf64_slurp_symbol_table, 342199461Sobrien bfd_elf64_swap_dyn_in, 342299461Sobrien bfd_elf64_swap_dyn_out, 3423130561Sobrien bfd_elf64_swap_reloc_in, 3424130561Sobrien bfd_elf64_swap_reloc_out, 3425130561Sobrien bfd_elf64_swap_reloca_in, 3426130561Sobrien bfd_elf64_swap_reloca_out 342799461Sobrien}; 342899461Sobrien 342999461Sobrien#define TARGET_BIG_SYM bfd_elf64_s390_vec 343099461Sobrien#define TARGET_BIG_NAME "elf64-s390" 343199461Sobrien#define ELF_ARCH bfd_arch_s390 343299461Sobrien#define ELF_MACHINE_CODE EM_S390 343399461Sobrien#define ELF_MACHINE_ALT1 EM_S390_OLD 343499461Sobrien#define ELF_MAXPAGESIZE 0x1000 343599461Sobrien 343699461Sobrien#define elf_backend_size_info s390_elf64_size_info 343799461Sobrien 343899461Sobrien#define elf_backend_can_gc_sections 1 343999461Sobrien#define elf_backend_can_refcount 1 344099461Sobrien#define elf_backend_want_got_plt 1 344199461Sobrien#define elf_backend_plt_readonly 1 344299461Sobrien#define elf_backend_want_plt_sym 0 344399461Sobrien#define elf_backend_got_header_size 24 344499461Sobrien#define elf_backend_rela_normal 1 344599461Sobrien 344699461Sobrien#define elf_info_to_howto elf_s390_info_to_howto 344799461Sobrien 344899461Sobrien#define bfd_elf64_bfd_is_local_label_name elf_s390_is_local_label_name 344999461Sobrien#define bfd_elf64_bfd_link_hash_table_create elf_s390_link_hash_table_create 345099461Sobrien#define bfd_elf64_bfd_reloc_type_lookup elf_s390_reloc_type_lookup 3451218822Sdim#define bfd_elf64_bfd_reloc_name_lookup elf_s390_reloc_name_lookup 345299461Sobrien 345399461Sobrien#define elf_backend_adjust_dynamic_symbol elf_s390_adjust_dynamic_symbol 345499461Sobrien#define elf_backend_check_relocs elf_s390_check_relocs 345599461Sobrien#define elf_backend_copy_indirect_symbol elf_s390_copy_indirect_symbol 345699461Sobrien#define elf_backend_create_dynamic_sections elf_s390_create_dynamic_sections 345799461Sobrien#define elf_backend_finish_dynamic_sections elf_s390_finish_dynamic_sections 345899461Sobrien#define elf_backend_finish_dynamic_symbol elf_s390_finish_dynamic_symbol 345999461Sobrien#define elf_backend_gc_mark_hook elf_s390_gc_mark_hook 346099461Sobrien#define elf_backend_gc_sweep_hook elf_s390_gc_sweep_hook 346199461Sobrien#define elf_backend_reloc_type_class elf_s390_reloc_type_class 346299461Sobrien#define elf_backend_relocate_section elf_s390_relocate_section 346399461Sobrien#define elf_backend_size_dynamic_sections elf_s390_size_dynamic_sections 3464218822Sdim#define elf_backend_init_index_section _bfd_elf_init_1_index_section 346599461Sobrien#define elf_backend_reloc_type_class elf_s390_reloc_type_class 3466218822Sdim#define elf_backend_plt_sym_val elf_s390_plt_sym_val 346799461Sobrien 3468130561Sobrien#define bfd_elf64_mkobject elf_s390_mkobject 3469130561Sobrien#define elf_backend_object_p elf_s390_object_p 347099461Sobrien 347199461Sobrien#include "elf64-target.h" 3472