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