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