elf32-sparc.c revision 77298
159024Sobrien/* SPARC-specific support for 32-bit ELF 260484Sobrien Copyright (C) 1993, 94, 95, 96, 97, 98, 99, 2000 360484Sobrien Free Software Foundation, Inc. 459024Sobrien 559024SobrienThis file is part of BFD, the Binary File Descriptor library. 659024Sobrien 759024SobrienThis program is free software; you can redistribute it and/or modify 859024Sobrienit under the terms of the GNU General Public License as published by 959024Sobrienthe Free Software Foundation; either version 2 of the License, or 1059024Sobrien(at your option) any later version. 1159024Sobrien 1259024SobrienThis program is distributed in the hope that it will be useful, 1359024Sobrienbut WITHOUT ANY WARRANTY; without even the implied warranty of 1459024SobrienMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1559024SobrienGNU General Public License for more details. 1659024Sobrien 1759024SobrienYou should have received a copy of the GNU General Public License 1859024Sobrienalong with this program; if not, write to the Free Software 1959024SobrienFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 2059024Sobrien 2159024Sobrien#include "bfd.h" 2259024Sobrien#include "sysdep.h" 2359024Sobrien#include "bfdlink.h" 2459024Sobrien#include "libbfd.h" 2559024Sobrien#include "elf-bfd.h" 2659024Sobrien#include "elf/sparc.h" 2777298Sobrien#include "opcode/sparc.h" 2859024Sobrien 2959024Sobrienstatic reloc_howto_type *elf32_sparc_reloc_type_lookup 3059024Sobrien PARAMS ((bfd *, bfd_reloc_code_real_type)); 3159024Sobrienstatic void elf32_sparc_info_to_howto 3259024Sobrien PARAMS ((bfd *, arelent *, Elf_Internal_Rela *)); 3359024Sobrienstatic boolean elf32_sparc_check_relocs 3459024Sobrien PARAMS ((bfd *, struct bfd_link_info *, asection *, 3559024Sobrien const Elf_Internal_Rela *)); 3659024Sobrienstatic boolean elf32_sparc_adjust_dynamic_symbol 3759024Sobrien PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *)); 3859024Sobrienstatic boolean elf32_sparc_size_dynamic_sections 3959024Sobrien PARAMS ((bfd *, struct bfd_link_info *)); 4077298Sobrienstatic boolean elf32_sparc_relax_section 4177298Sobrien PARAMS ((bfd *, asection *, struct bfd_link_info *, boolean *)); 4259024Sobrienstatic boolean elf32_sparc_relocate_section 4359024Sobrien PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, 4459024Sobrien Elf_Internal_Rela *, Elf_Internal_Sym *, asection **)); 4559024Sobrienstatic boolean elf32_sparc_finish_dynamic_symbol 4659024Sobrien PARAMS ((bfd *, struct bfd_link_info *, struct elf_link_hash_entry *, 4759024Sobrien Elf_Internal_Sym *)); 4859024Sobrienstatic boolean elf32_sparc_finish_dynamic_sections 4959024Sobrien PARAMS ((bfd *, struct bfd_link_info *)); 5059024Sobrienstatic boolean elf32_sparc_merge_private_bfd_data PARAMS ((bfd *, bfd *)); 5159024Sobrienstatic boolean elf32_sparc_object_p 5259024Sobrien PARAMS ((bfd *)); 5359024Sobrienstatic void elf32_sparc_final_write_processing 5459024Sobrien PARAMS ((bfd *, boolean)); 5559024Sobrien 5659024Sobrien/* The relocation "howto" table. */ 5759024Sobrien 5859024Sobrienstatic bfd_reloc_status_type sparc_elf_notsupported_reloc 5959024Sobrien PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); 6059024Sobrienstatic bfd_reloc_status_type sparc_elf_wdisp16_reloc 6159024Sobrien PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); 6259024Sobrien 6359024Sobrienreloc_howto_type _bfd_sparc_elf_howto_table[] = 6459024Sobrien{ 6559024Sobrien HOWTO(R_SPARC_NONE, 0,0, 0,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_NONE", false,0,0x00000000,true), 6659024Sobrien HOWTO(R_SPARC_8, 0,0, 8,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_8", false,0,0x000000ff,true), 6759024Sobrien HOWTO(R_SPARC_16, 0,1,16,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_16", false,0,0x0000ffff,true), 6859024Sobrien HOWTO(R_SPARC_32, 0,2,32,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_32", false,0,0xffffffff,true), 6959024Sobrien HOWTO(R_SPARC_DISP8, 0,0, 8,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_DISP8", false,0,0x000000ff,true), 7059024Sobrien HOWTO(R_SPARC_DISP16, 0,1,16,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_DISP16", false,0,0x0000ffff,true), 7159024Sobrien HOWTO(R_SPARC_DISP32, 0,2,32,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_DISP32", false,0,0x00ffffff,true), 7259024Sobrien HOWTO(R_SPARC_WDISP30, 2,2,30,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_WDISP30", false,0,0x3fffffff,true), 7359024Sobrien HOWTO(R_SPARC_WDISP22, 2,2,22,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_WDISP22", false,0,0x003fffff,true), 7459024Sobrien HOWTO(R_SPARC_HI22, 10,2,22,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_HI22", false,0,0x003fffff,true), 7559024Sobrien HOWTO(R_SPARC_22, 0,2,22,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_22", false,0,0x003fffff,true), 7659024Sobrien HOWTO(R_SPARC_13, 0,2,13,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_13", false,0,0x00001fff,true), 7759024Sobrien HOWTO(R_SPARC_LO10, 0,2,10,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_LO10", false,0,0x000003ff,true), 7859024Sobrien HOWTO(R_SPARC_GOT10, 0,2,10,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_GOT10", false,0,0x000003ff,true), 7959024Sobrien HOWTO(R_SPARC_GOT13, 0,2,13,false,0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_GOT13", false,0,0x00001fff,true), 8059024Sobrien HOWTO(R_SPARC_GOT22, 10,2,22,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_GOT22", false,0,0x003fffff,true), 8159024Sobrien HOWTO(R_SPARC_PC10, 0,2,10,true, 0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_PC10", false,0,0x000003ff,true), 8259024Sobrien HOWTO(R_SPARC_PC22, 10,2,22,true, 0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_PC22", false,0,0x003fffff,true), 8359024Sobrien HOWTO(R_SPARC_WPLT30, 2,2,30,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_WPLT30", false,0,0x3fffffff,true), 8459024Sobrien HOWTO(R_SPARC_COPY, 0,0,00,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_COPY", false,0,0x00000000,true), 8559024Sobrien 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), 8659024Sobrien 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), 8759024Sobrien HOWTO(R_SPARC_RELATIVE, 0,0,00,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_RELATIVE",false,0,0x00000000,true), 8859024Sobrien HOWTO(R_SPARC_UA32, 0,0,00,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_UA32", false,0,0x00000000,true), 8959024Sobrien HOWTO(R_SPARC_PLT32, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_PLT32", false,0,0x00000000,true), 9059024Sobrien HOWTO(R_SPARC_HIPLT22, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_HIPLT22", false,0,0x00000000,true), 9159024Sobrien HOWTO(R_SPARC_LOPLT10, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_LOPLT10", false,0,0x00000000,true), 9259024Sobrien HOWTO(R_SPARC_PCPLT32, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_PCPLT32", false,0,0x00000000,true), 9359024Sobrien HOWTO(R_SPARC_PCPLT22, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_PCPLT22", false,0,0x00000000,true), 9459024Sobrien HOWTO(R_SPARC_PCPLT10, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_PCPLT10", false,0,0x00000000,true), 9559024Sobrien HOWTO(R_SPARC_10, 0,2,10,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_10", false,0,0x000003ff,true), 9659024Sobrien HOWTO(R_SPARC_11, 0,2,11,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_11", false,0,0x000007ff,true), 9759024Sobrien /* These are for sparc64 in a 64 bit environment. 9859024Sobrien Values need to be here because the table is indexed by reloc number. */ 9959024Sobrien HOWTO(R_SPARC_64, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_64", false,0,0x00000000,true), 10059024Sobrien HOWTO(R_SPARC_OLO10, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_OLO10", false,0,0x00000000,true), 10159024Sobrien HOWTO(R_SPARC_HH22, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_HH22", false,0,0x00000000,true), 10259024Sobrien HOWTO(R_SPARC_HM10, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_HM10", false,0,0x00000000,true), 10359024Sobrien HOWTO(R_SPARC_LM22, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_LM22", false,0,0x00000000,true), 10459024Sobrien HOWTO(R_SPARC_PC_HH22, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_PC_HH22", false,0,0x00000000,true), 10559024Sobrien HOWTO(R_SPARC_PC_HM10, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_PC_HM10", false,0,0x00000000,true), 10659024Sobrien HOWTO(R_SPARC_PC_LM22, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_PC_LM22", false,0,0x00000000,true), 10759024Sobrien /* End sparc64 in 64 bit environment values. 10859024Sobrien The following are for sparc64 in a 32 bit environment. */ 10959024Sobrien HOWTO(R_SPARC_WDISP16, 2,2,16,true, 0,complain_overflow_signed, sparc_elf_wdisp16_reloc,"R_SPARC_WDISP16", false,0,0x00000000,true), 11059024Sobrien HOWTO(R_SPARC_WDISP19, 2,2,19,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_WDISP19", false,0,0x0007ffff,true), 11159024Sobrien 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), 11259024Sobrien HOWTO(R_SPARC_7, 0,2, 7,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_7", false,0,0x0000007f,true), 11359024Sobrien HOWTO(R_SPARC_5, 0,2, 5,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_5", false,0,0x0000001f,true), 11460484Sobrien HOWTO(R_SPARC_6, 0,2, 6,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_6", false,0,0x0000003f,true), 11560484Sobrien HOWTO(R_SPARC_NONE, 0,0, 0,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_NONE", false,0,0x00000000,true), 11660484Sobrien HOWTO(R_SPARC_NONE, 0,0, 0,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_NONE", false,0,0x00000000,true), 11760484Sobrien HOWTO(R_SPARC_NONE, 0,0, 0,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_NONE", false,0,0x00000000,true), 11860484Sobrien HOWTO(R_SPARC_NONE, 0,0, 0,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_NONE", false,0,0x00000000,true), 11960484Sobrien HOWTO(R_SPARC_NONE, 0,0, 0,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_NONE", false,0,0x00000000,true), 12060484Sobrien HOWTO(R_SPARC_NONE, 0,0, 0,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_NONE", false,0,0x00000000,true), 12160484Sobrien HOWTO(R_SPARC_NONE, 0,0, 0,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_NONE", false,0,0x00000000,true), 12260484Sobrien HOWTO(R_SPARC_NONE, 0,0, 0,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_NONE", false,0,0x00000000,true), 12360484Sobrien HOWTO(R_SPARC_NONE, 0,0, 0,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_NONE", false,0,0x00000000,true), 12460484Sobrien HOWTO(R_SPARC_NONE, 0,0, 0,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_NONE", false,0,0x00000000,true), 12560484Sobrien HOWTO(R_SPARC_REV32, 0,2,32,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_REV32", false,0,0xffffffff,true), 12659024Sobrien}; 12760484Sobrienstatic reloc_howto_type elf32_sparc_vtinherit_howto = 12860484Sobrien HOWTO (R_SPARC_GNU_VTINHERIT, 0,2,0,false,0,complain_overflow_dont, NULL, "R_SPARC_GNU_VTINHERIT", false,0, 0, false); 12960484Sobrienstatic reloc_howto_type elf32_sparc_vtentry_howto = 13060484Sobrien 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); 13159024Sobrien 13259024Sobrienstruct elf_reloc_map { 13360484Sobrien bfd_reloc_code_real_type bfd_reloc_val; 13459024Sobrien unsigned char elf_reloc_val; 13559024Sobrien}; 13659024Sobrien 13759024Sobrienstatic CONST struct elf_reloc_map sparc_reloc_map[] = 13859024Sobrien{ 13959024Sobrien { BFD_RELOC_NONE, R_SPARC_NONE, }, 14059024Sobrien { BFD_RELOC_16, R_SPARC_16, }, 14159024Sobrien { BFD_RELOC_8, R_SPARC_8 }, 14259024Sobrien { BFD_RELOC_8_PCREL, R_SPARC_DISP8 }, 14359024Sobrien { BFD_RELOC_CTOR, R_SPARC_32 }, 14459024Sobrien { BFD_RELOC_32, R_SPARC_32 }, 14559024Sobrien { BFD_RELOC_32_PCREL, R_SPARC_DISP32 }, 14659024Sobrien { BFD_RELOC_HI22, R_SPARC_HI22 }, 14759024Sobrien { BFD_RELOC_LO10, R_SPARC_LO10, }, 14859024Sobrien { BFD_RELOC_32_PCREL_S2, R_SPARC_WDISP30 }, 14959024Sobrien { BFD_RELOC_SPARC22, R_SPARC_22 }, 15059024Sobrien { BFD_RELOC_SPARC13, R_SPARC_13 }, 15159024Sobrien { BFD_RELOC_SPARC_GOT10, R_SPARC_GOT10 }, 15259024Sobrien { BFD_RELOC_SPARC_GOT13, R_SPARC_GOT13 }, 15359024Sobrien { BFD_RELOC_SPARC_GOT22, R_SPARC_GOT22 }, 15459024Sobrien { BFD_RELOC_SPARC_PC10, R_SPARC_PC10 }, 15559024Sobrien { BFD_RELOC_SPARC_PC22, R_SPARC_PC22 }, 15659024Sobrien { BFD_RELOC_SPARC_WPLT30, R_SPARC_WPLT30 }, 15759024Sobrien { BFD_RELOC_SPARC_COPY, R_SPARC_COPY }, 15859024Sobrien { BFD_RELOC_SPARC_GLOB_DAT, R_SPARC_GLOB_DAT }, 15959024Sobrien { BFD_RELOC_SPARC_JMP_SLOT, R_SPARC_JMP_SLOT }, 16059024Sobrien { BFD_RELOC_SPARC_RELATIVE, R_SPARC_RELATIVE }, 16159024Sobrien { BFD_RELOC_SPARC_WDISP22, R_SPARC_WDISP22 }, 16259024Sobrien /* ??? Doesn't dwarf use this? */ 16359024Sobrien/*{ BFD_RELOC_SPARC_UA32, R_SPARC_UA32 }, not used?? */ 16459024Sobrien {BFD_RELOC_SPARC_10, R_SPARC_10}, 16559024Sobrien {BFD_RELOC_SPARC_11, R_SPARC_11}, 16659024Sobrien {BFD_RELOC_SPARC_64, R_SPARC_64}, 16759024Sobrien {BFD_RELOC_SPARC_OLO10, R_SPARC_OLO10}, 16859024Sobrien {BFD_RELOC_SPARC_HH22, R_SPARC_HH22}, 16959024Sobrien {BFD_RELOC_SPARC_HM10, R_SPARC_HM10}, 17059024Sobrien {BFD_RELOC_SPARC_LM22, R_SPARC_LM22}, 17159024Sobrien {BFD_RELOC_SPARC_PC_HH22, R_SPARC_PC_HH22}, 17259024Sobrien {BFD_RELOC_SPARC_PC_HM10, R_SPARC_PC_HM10}, 17359024Sobrien {BFD_RELOC_SPARC_PC_LM22, R_SPARC_PC_LM22}, 17459024Sobrien {BFD_RELOC_SPARC_WDISP16, R_SPARC_WDISP16}, 17559024Sobrien {BFD_RELOC_SPARC_WDISP19, R_SPARC_WDISP19}, 17659024Sobrien {BFD_RELOC_SPARC_7, R_SPARC_7}, 17759024Sobrien {BFD_RELOC_SPARC_5, R_SPARC_5}, 17860484Sobrien {BFD_RELOC_SPARC_6, R_SPARC_6}, 17960484Sobrien {BFD_RELOC_SPARC_REV32, R_SPARC_REV32 }, 18060484Sobrien {BFD_RELOC_VTABLE_INHERIT, R_SPARC_GNU_VTINHERIT}, 18160484Sobrien {BFD_RELOC_VTABLE_ENTRY, R_SPARC_GNU_VTENTRY}, 18259024Sobrien}; 18359024Sobrien 18459024Sobrienstatic reloc_howto_type * 18559024Sobrienelf32_sparc_reloc_type_lookup (abfd, code) 18660484Sobrien bfd *abfd ATTRIBUTE_UNUSED; 18759024Sobrien bfd_reloc_code_real_type code; 18859024Sobrien{ 18959024Sobrien unsigned int i; 19077298Sobrien 19160484Sobrien switch (code) 19259024Sobrien { 19360484Sobrien case BFD_RELOC_VTABLE_INHERIT: 19460484Sobrien return &elf32_sparc_vtinherit_howto; 19560484Sobrien 19660484Sobrien case BFD_RELOC_VTABLE_ENTRY: 19760484Sobrien return &elf32_sparc_vtentry_howto; 19860484Sobrien 19960484Sobrien default: 20060484Sobrien for (i = 0; i < sizeof (sparc_reloc_map) / sizeof (struct elf_reloc_map); i++) 20160484Sobrien { 20260484Sobrien if (sparc_reloc_map[i].bfd_reloc_val == code) 20360484Sobrien return &_bfd_sparc_elf_howto_table[(int) sparc_reloc_map[i].elf_reloc_val]; 20460484Sobrien } 20559024Sobrien } 20660484Sobrien bfd_set_error (bfd_error_bad_value); 20760484Sobrien return NULL; 20859024Sobrien} 20959024Sobrien 21059024Sobrien/* We need to use ELF32_R_TYPE so we have our own copy of this function, 21159024Sobrien and elf64-sparc.c has its own copy. */ 21259024Sobrien 21359024Sobrienstatic void 21459024Sobrienelf32_sparc_info_to_howto (abfd, cache_ptr, dst) 21560484Sobrien bfd *abfd ATTRIBUTE_UNUSED; 21659024Sobrien arelent *cache_ptr; 21759024Sobrien Elf_Internal_Rela *dst; 21859024Sobrien{ 21960484Sobrien switch (ELF32_R_TYPE(dst->r_info)) 22060484Sobrien { 22160484Sobrien case R_SPARC_GNU_VTINHERIT: 22260484Sobrien cache_ptr->howto = &elf32_sparc_vtinherit_howto; 22360484Sobrien break; 22460484Sobrien 22560484Sobrien case R_SPARC_GNU_VTENTRY: 22660484Sobrien cache_ptr->howto = &elf32_sparc_vtentry_howto; 22760484Sobrien break; 22860484Sobrien 22960484Sobrien default: 23060484Sobrien BFD_ASSERT (ELF32_R_TYPE(dst->r_info) < (unsigned int) R_SPARC_max_std); 23160484Sobrien cache_ptr->howto = &_bfd_sparc_elf_howto_table[ELF32_R_TYPE(dst->r_info)]; 23260484Sobrien } 23359024Sobrien} 23459024Sobrien 23559024Sobrien/* For unsupported relocs. */ 23659024Sobrien 23759024Sobrienstatic bfd_reloc_status_type 23859024Sobriensparc_elf_notsupported_reloc (abfd, 23959024Sobrien reloc_entry, 24059024Sobrien symbol, 24159024Sobrien data, 24259024Sobrien input_section, 24359024Sobrien output_bfd, 24459024Sobrien error_message) 24560484Sobrien bfd *abfd ATTRIBUTE_UNUSED; 24660484Sobrien arelent *reloc_entry ATTRIBUTE_UNUSED; 24760484Sobrien asymbol *symbol ATTRIBUTE_UNUSED; 24860484Sobrien PTR data ATTRIBUTE_UNUSED; 24960484Sobrien asection *input_section ATTRIBUTE_UNUSED; 25060484Sobrien bfd *output_bfd ATTRIBUTE_UNUSED; 25160484Sobrien char **error_message ATTRIBUTE_UNUSED; 25259024Sobrien{ 25359024Sobrien return bfd_reloc_notsupported; 25459024Sobrien} 25559024Sobrien 25659024Sobrien/* Handle the WDISP16 reloc. */ 25759024Sobrien 25859024Sobrienstatic bfd_reloc_status_type 25959024Sobriensparc_elf_wdisp16_reloc (abfd, 26059024Sobrien reloc_entry, 26159024Sobrien symbol, 26259024Sobrien data, 26359024Sobrien input_section, 26459024Sobrien output_bfd, 26559024Sobrien error_message) 26659024Sobrien bfd *abfd; 26759024Sobrien arelent *reloc_entry; 26859024Sobrien asymbol *symbol; 26959024Sobrien PTR data; 27059024Sobrien asection *input_section; 27159024Sobrien bfd *output_bfd; 27260484Sobrien char **error_message ATTRIBUTE_UNUSED; 27359024Sobrien{ 27459024Sobrien bfd_vma relocation; 27559024Sobrien bfd_vma x; 27659024Sobrien 27759024Sobrien if (output_bfd != (bfd *) NULL 27859024Sobrien && (symbol->flags & BSF_SECTION_SYM) == 0 27959024Sobrien && (! reloc_entry->howto->partial_inplace 28059024Sobrien || reloc_entry->addend == 0)) 28159024Sobrien { 28259024Sobrien reloc_entry->address += input_section->output_offset; 28359024Sobrien return bfd_reloc_ok; 28459024Sobrien } 28559024Sobrien 28659024Sobrien if (output_bfd != NULL) 28759024Sobrien return bfd_reloc_continue; 28859024Sobrien 28959024Sobrien if (reloc_entry->address > input_section->_cooked_size) 29059024Sobrien return bfd_reloc_outofrange; 29159024Sobrien 29259024Sobrien relocation = (symbol->value 29359024Sobrien + symbol->section->output_section->vma 29459024Sobrien + symbol->section->output_offset); 29559024Sobrien relocation += reloc_entry->addend; 29659024Sobrien relocation -= (input_section->output_section->vma 29759024Sobrien + input_section->output_offset); 29859024Sobrien relocation -= reloc_entry->address; 29959024Sobrien 30059024Sobrien x = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address); 30159024Sobrien x |= ((((relocation >> 2) & 0xc000) << 6) 30259024Sobrien | ((relocation >> 2) & 0x3fff)); 30359024Sobrien bfd_put_32 (abfd, x, (bfd_byte *) data + reloc_entry->address); 30459024Sobrien 30559024Sobrien if ((bfd_signed_vma) relocation < - 0x40000 30659024Sobrien || (bfd_signed_vma) relocation > 0x3ffff) 30759024Sobrien return bfd_reloc_overflow; 30859024Sobrien else 30959024Sobrien return bfd_reloc_ok; 31059024Sobrien} 31159024Sobrien 31259024Sobrien/* Functions for the SPARC ELF linker. */ 31359024Sobrien 31459024Sobrien/* The name of the dynamic interpreter. This is put in the .interp 31559024Sobrien section. */ 31659024Sobrien 31759024Sobrien#define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1" 31859024Sobrien 31959024Sobrien/* The nop opcode we use. */ 32059024Sobrien 32159024Sobrien#define SPARC_NOP 0x01000000 32259024Sobrien 32359024Sobrien/* The size in bytes of an entry in the procedure linkage table. */ 32459024Sobrien 32559024Sobrien#define PLT_ENTRY_SIZE 12 32659024Sobrien 32759024Sobrien/* The first four entries in a procedure linkage table are reserved, 32859024Sobrien and the initial contents are unimportant (we zero them out). 32959024Sobrien Subsequent entries look like this. See the SVR4 ABI SPARC 33059024Sobrien supplement to see how this works. */ 33159024Sobrien 33259024Sobrien/* sethi %hi(.-.plt0),%g1. We fill in the address later. */ 33359024Sobrien#define PLT_ENTRY_WORD0 0x03000000 33459024Sobrien/* b,a .plt0. We fill in the offset later. */ 33559024Sobrien#define PLT_ENTRY_WORD1 0x30800000 33659024Sobrien/* nop. */ 33759024Sobrien#define PLT_ENTRY_WORD2 SPARC_NOP 33859024Sobrien 33959024Sobrien/* Look through the relocs for a section during the first phase, and 34059024Sobrien allocate space in the global offset table or procedure linkage 34159024Sobrien table. */ 34259024Sobrien 34359024Sobrienstatic boolean 34459024Sobrienelf32_sparc_check_relocs (abfd, info, sec, relocs) 34559024Sobrien bfd *abfd; 34659024Sobrien struct bfd_link_info *info; 34759024Sobrien asection *sec; 34859024Sobrien const Elf_Internal_Rela *relocs; 34959024Sobrien{ 35059024Sobrien bfd *dynobj; 35159024Sobrien Elf_Internal_Shdr *symtab_hdr; 35259024Sobrien struct elf_link_hash_entry **sym_hashes; 35359024Sobrien bfd_vma *local_got_offsets; 35459024Sobrien const Elf_Internal_Rela *rel; 35559024Sobrien const Elf_Internal_Rela *rel_end; 35659024Sobrien asection *sgot; 35759024Sobrien asection *srelgot; 35859024Sobrien asection *sreloc; 35959024Sobrien 36059024Sobrien if (info->relocateable) 36159024Sobrien return true; 36259024Sobrien 36359024Sobrien dynobj = elf_hash_table (info)->dynobj; 36459024Sobrien symtab_hdr = &elf_tdata (abfd)->symtab_hdr; 36559024Sobrien sym_hashes = elf_sym_hashes (abfd); 36659024Sobrien local_got_offsets = elf_local_got_offsets (abfd); 36759024Sobrien 36859024Sobrien sgot = NULL; 36959024Sobrien srelgot = NULL; 37059024Sobrien sreloc = NULL; 37159024Sobrien 37259024Sobrien rel_end = relocs + sec->reloc_count; 37359024Sobrien for (rel = relocs; rel < rel_end; rel++) 37459024Sobrien { 37559024Sobrien unsigned long r_symndx; 37659024Sobrien struct elf_link_hash_entry *h; 37759024Sobrien 37859024Sobrien r_symndx = ELF32_R_SYM (rel->r_info); 37959024Sobrien if (r_symndx < symtab_hdr->sh_info) 38059024Sobrien h = NULL; 38159024Sobrien else 38259024Sobrien h = sym_hashes[r_symndx - symtab_hdr->sh_info]; 38359024Sobrien 38459024Sobrien switch (ELF32_R_TYPE (rel->r_info)) 38559024Sobrien { 38659024Sobrien case R_SPARC_GOT10: 38759024Sobrien case R_SPARC_GOT13: 38859024Sobrien case R_SPARC_GOT22: 38959024Sobrien /* This symbol requires a global offset table entry. */ 39059024Sobrien 39159024Sobrien if (dynobj == NULL) 39259024Sobrien { 39359024Sobrien /* Create the .got section. */ 39459024Sobrien elf_hash_table (info)->dynobj = dynobj = abfd; 39559024Sobrien if (! _bfd_elf_create_got_section (dynobj, info)) 39659024Sobrien return false; 39759024Sobrien } 39859024Sobrien 39959024Sobrien if (sgot == NULL) 40059024Sobrien { 40159024Sobrien sgot = bfd_get_section_by_name (dynobj, ".got"); 40259024Sobrien BFD_ASSERT (sgot != NULL); 40359024Sobrien } 40459024Sobrien 40559024Sobrien if (srelgot == NULL 40659024Sobrien && (h != NULL || info->shared)) 40759024Sobrien { 40859024Sobrien srelgot = bfd_get_section_by_name (dynobj, ".rela.got"); 40959024Sobrien if (srelgot == NULL) 41059024Sobrien { 41159024Sobrien srelgot = bfd_make_section (dynobj, ".rela.got"); 41259024Sobrien if (srelgot == NULL 41359024Sobrien || ! bfd_set_section_flags (dynobj, srelgot, 41459024Sobrien (SEC_ALLOC 41559024Sobrien | SEC_LOAD 41659024Sobrien | SEC_HAS_CONTENTS 41759024Sobrien | SEC_IN_MEMORY 41859024Sobrien | SEC_LINKER_CREATED 41959024Sobrien | SEC_READONLY)) 42059024Sobrien || ! bfd_set_section_alignment (dynobj, srelgot, 2)) 42159024Sobrien return false; 42259024Sobrien } 42359024Sobrien } 42459024Sobrien 42559024Sobrien if (h != NULL) 42659024Sobrien { 42760484Sobrien if (h->got.offset != (bfd_vma) -1) 42859024Sobrien { 42959024Sobrien /* We have already allocated space in the .got. */ 43059024Sobrien break; 43159024Sobrien } 43260484Sobrien h->got.offset = sgot->_raw_size; 43359024Sobrien 43459024Sobrien /* Make sure this symbol is output as a dynamic symbol. */ 43559024Sobrien if (h->dynindx == -1) 43659024Sobrien { 43759024Sobrien if (! bfd_elf32_link_record_dynamic_symbol (info, h)) 43859024Sobrien return false; 43959024Sobrien } 44059024Sobrien 44159024Sobrien srelgot->_raw_size += sizeof (Elf32_External_Rela); 44259024Sobrien } 44359024Sobrien else 44459024Sobrien { 44559024Sobrien /* This is a global offset table entry for a local 44659024Sobrien symbol. */ 44759024Sobrien if (local_got_offsets == NULL) 44859024Sobrien { 44959024Sobrien size_t size; 45059024Sobrien register unsigned int i; 45159024Sobrien 45259024Sobrien size = symtab_hdr->sh_info * sizeof (bfd_vma); 45359024Sobrien local_got_offsets = (bfd_vma *) bfd_alloc (abfd, size); 45459024Sobrien if (local_got_offsets == NULL) 45559024Sobrien return false; 45659024Sobrien elf_local_got_offsets (abfd) = local_got_offsets; 45759024Sobrien for (i = 0; i < symtab_hdr->sh_info; i++) 45859024Sobrien local_got_offsets[i] = (bfd_vma) -1; 45959024Sobrien } 46059024Sobrien if (local_got_offsets[r_symndx] != (bfd_vma) -1) 46159024Sobrien { 46259024Sobrien /* We have already allocated space in the .got. */ 46359024Sobrien break; 46459024Sobrien } 46559024Sobrien local_got_offsets[r_symndx] = sgot->_raw_size; 46659024Sobrien 46759024Sobrien if (info->shared) 46859024Sobrien { 46959024Sobrien /* If we are generating a shared object, we need to 47059024Sobrien output a R_SPARC_RELATIVE reloc so that the 47159024Sobrien dynamic linker can adjust this GOT entry. */ 47259024Sobrien srelgot->_raw_size += sizeof (Elf32_External_Rela); 47359024Sobrien } 47459024Sobrien } 47559024Sobrien 47659024Sobrien sgot->_raw_size += 4; 47759024Sobrien 47859024Sobrien /* If the .got section is more than 0x1000 bytes, we add 47959024Sobrien 0x1000 to the value of _GLOBAL_OFFSET_TABLE_, so that 13 48059024Sobrien bit relocations have a greater chance of working. */ 48159024Sobrien if (sgot->_raw_size >= 0x1000 48259024Sobrien && elf_hash_table (info)->hgot->root.u.def.value == 0) 48359024Sobrien elf_hash_table (info)->hgot->root.u.def.value = 0x1000; 48459024Sobrien 48559024Sobrien break; 48659024Sobrien 48759024Sobrien case R_SPARC_WPLT30: 48859024Sobrien /* This symbol requires a procedure linkage table entry. We 48959024Sobrien actually build the entry in adjust_dynamic_symbol, 49059024Sobrien because this might be a case of linking PIC code without 49159024Sobrien linking in any dynamic objects, in which case we don't 49259024Sobrien need to generate a procedure linkage table after all. */ 49359024Sobrien 49459024Sobrien if (h == NULL) 49559024Sobrien { 49660484Sobrien /* The Solaris native assembler will generate a WPLT30 49760484Sobrien reloc for a local symbol if you assemble a call from 49860484Sobrien one section to another when using -K pic. We treat 49960484Sobrien it as WDISP30. */ 50060484Sobrien break; 50159024Sobrien } 50259024Sobrien 50359024Sobrien /* Make sure this symbol is output as a dynamic symbol. */ 50459024Sobrien if (h->dynindx == -1) 50559024Sobrien { 50659024Sobrien if (! bfd_elf32_link_record_dynamic_symbol (info, h)) 50759024Sobrien return false; 50859024Sobrien } 50959024Sobrien 51059024Sobrien h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; 51159024Sobrien 51259024Sobrien break; 51359024Sobrien 51459024Sobrien case R_SPARC_PC10: 51559024Sobrien case R_SPARC_PC22: 51660484Sobrien if (h != NULL) 51760484Sobrien h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF; 51860484Sobrien 51959024Sobrien if (h != NULL 52059024Sobrien && strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0) 52159024Sobrien break; 52259024Sobrien /* Fall through. */ 52359024Sobrien case R_SPARC_DISP8: 52459024Sobrien case R_SPARC_DISP16: 52559024Sobrien case R_SPARC_DISP32: 52659024Sobrien case R_SPARC_WDISP30: 52759024Sobrien case R_SPARC_WDISP22: 52859024Sobrien case R_SPARC_WDISP19: 52959024Sobrien case R_SPARC_WDISP16: 53060484Sobrien if (h != NULL) 53160484Sobrien h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF; 53260484Sobrien 53359024Sobrien /* If we are linking with -Bsymbolic, we do not need to copy 53459024Sobrien a PC relative reloc against a global symbol which is 53559024Sobrien defined in an object we are including in the link (i.e., 53659024Sobrien DEF_REGULAR is set). FIXME: At this point we have not 53759024Sobrien seen all the input files, so it is possible that 53859024Sobrien DEF_REGULAR is not set now but will be set later (it is 53959024Sobrien never cleared). This needs to be handled as in 54059024Sobrien elf32-i386.c. */ 54159024Sobrien if (h == NULL 54259024Sobrien || (info->symbolic 54359024Sobrien && (h->elf_link_hash_flags 54459024Sobrien & ELF_LINK_HASH_DEF_REGULAR) != 0)) 54559024Sobrien break; 54659024Sobrien /* Fall through. */ 54759024Sobrien case R_SPARC_8: 54859024Sobrien case R_SPARC_16: 54959024Sobrien case R_SPARC_32: 55059024Sobrien case R_SPARC_HI22: 55159024Sobrien case R_SPARC_22: 55259024Sobrien case R_SPARC_13: 55359024Sobrien case R_SPARC_LO10: 55459024Sobrien case R_SPARC_UA32: 55560484Sobrien if (h != NULL) 55660484Sobrien h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF; 55760484Sobrien 55859024Sobrien if (info->shared) 55959024Sobrien { 56059024Sobrien /* When creating a shared object, we must copy these 56159024Sobrien relocs into the output file. We create a reloc 56259024Sobrien section in dynobj and make room for the reloc. */ 56359024Sobrien if (sreloc == NULL) 56459024Sobrien { 56559024Sobrien const char *name; 56659024Sobrien 56759024Sobrien name = (bfd_elf_string_from_elf_section 56859024Sobrien (abfd, 56959024Sobrien elf_elfheader (abfd)->e_shstrndx, 57059024Sobrien elf_section_data (sec)->rel_hdr.sh_name)); 57159024Sobrien if (name == NULL) 57259024Sobrien return false; 57359024Sobrien 57459024Sobrien BFD_ASSERT (strncmp (name, ".rela", 5) == 0 57559024Sobrien && strcmp (bfd_get_section_name (abfd, sec), 57659024Sobrien name + 5) == 0); 57759024Sobrien 57859024Sobrien sreloc = bfd_get_section_by_name (dynobj, name); 57959024Sobrien if (sreloc == NULL) 58059024Sobrien { 58159024Sobrien flagword flags; 58259024Sobrien 58359024Sobrien sreloc = bfd_make_section (dynobj, name); 58459024Sobrien flags = (SEC_HAS_CONTENTS | SEC_READONLY 58559024Sobrien | SEC_IN_MEMORY | SEC_LINKER_CREATED); 58659024Sobrien if ((sec->flags & SEC_ALLOC) != 0) 58759024Sobrien flags |= SEC_ALLOC | SEC_LOAD; 58859024Sobrien if (sreloc == NULL 58959024Sobrien || ! bfd_set_section_flags (dynobj, sreloc, flags) 59059024Sobrien || ! bfd_set_section_alignment (dynobj, sreloc, 2)) 59159024Sobrien return false; 59259024Sobrien } 59359024Sobrien } 59459024Sobrien 59559024Sobrien sreloc->_raw_size += sizeof (Elf32_External_Rela); 59659024Sobrien } 59759024Sobrien 59859024Sobrien break; 59959024Sobrien 60060484Sobrien case R_SPARC_GNU_VTINHERIT: 60160484Sobrien if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) 60260484Sobrien return false; 60360484Sobrien break; 60460484Sobrien 60560484Sobrien case R_SPARC_GNU_VTENTRY: 60660484Sobrien if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend)) 60760484Sobrien return false; 60860484Sobrien break; 60960484Sobrien 61059024Sobrien default: 61159024Sobrien break; 61259024Sobrien } 61359024Sobrien } 61459024Sobrien 61559024Sobrien return true; 61659024Sobrien} 61759024Sobrien 61860484Sobrienstatic asection * 61960484Sobrienelf32_sparc_gc_mark_hook (abfd, info, rel, h, sym) 62060484Sobrien bfd *abfd; 62160484Sobrien struct bfd_link_info *info ATTRIBUTE_UNUSED; 62260484Sobrien Elf_Internal_Rela *rel; 62360484Sobrien struct elf_link_hash_entry *h; 62460484Sobrien Elf_Internal_Sym *sym; 62560484Sobrien{ 62660484Sobrien 62760484Sobrien if (h != NULL) 62860484Sobrien { 62960484Sobrien switch (ELF32_R_TYPE (rel->r_info)) 63060484Sobrien { 63160484Sobrien case R_SPARC_GNU_VTINHERIT: 63260484Sobrien case R_SPARC_GNU_VTENTRY: 63360484Sobrien break; 63460484Sobrien 63560484Sobrien default: 63660484Sobrien switch (h->root.type) 63760484Sobrien { 63860484Sobrien case bfd_link_hash_defined: 63960484Sobrien case bfd_link_hash_defweak: 64060484Sobrien return h->root.u.def.section; 64160484Sobrien 64260484Sobrien case bfd_link_hash_common: 64360484Sobrien return h->root.u.c.p->section; 64460484Sobrien 64560484Sobrien default: 64660484Sobrien break; 64760484Sobrien } 64860484Sobrien } 64960484Sobrien } 65060484Sobrien else 65160484Sobrien { 65260484Sobrien if (!(elf_bad_symtab (abfd) 65360484Sobrien && ELF_ST_BIND (sym->st_info) != STB_LOCAL) 65460484Sobrien && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE) 65560484Sobrien && sym->st_shndx != SHN_COMMON)) 65660484Sobrien { 65760484Sobrien return bfd_section_from_elf_index (abfd, sym->st_shndx); 65860484Sobrien } 65960484Sobrien } 66060484Sobrien 66160484Sobrien return NULL; 66260484Sobrien} 66360484Sobrien 66460484Sobrien/* Update the got entry reference counts for the section being removed. */ 66560484Sobrienstatic boolean 66660484Sobrienelf32_sparc_gc_sweep_hook (abfd, info, sec, relocs) 66760484Sobrien bfd *abfd; 66860484Sobrien struct bfd_link_info *info ATTRIBUTE_UNUSED; 66960484Sobrien asection *sec; 67060484Sobrien const Elf_Internal_Rela *relocs; 67160484Sobrien{ 67260484Sobrien 67360484Sobrien Elf_Internal_Shdr *symtab_hdr; 67460484Sobrien struct elf_link_hash_entry **sym_hashes; 67560484Sobrien bfd_signed_vma *local_got_refcounts; 67660484Sobrien const Elf_Internal_Rela *rel, *relend; 67760484Sobrien unsigned long r_symndx; 67860484Sobrien struct elf_link_hash_entry *h; 67960484Sobrien 68060484Sobrien symtab_hdr = &elf_tdata (abfd)->symtab_hdr; 68160484Sobrien sym_hashes = elf_sym_hashes (abfd); 68260484Sobrien local_got_refcounts = elf_local_got_refcounts (abfd); 68360484Sobrien 68460484Sobrien relend = relocs + sec->reloc_count; 68560484Sobrien for (rel = relocs; rel < relend; rel++) 68660484Sobrien switch (ELF32_R_TYPE (rel->r_info)) 68760484Sobrien { 68860484Sobrien case R_SPARC_GOT10: 68960484Sobrien case R_SPARC_GOT13: 69060484Sobrien case R_SPARC_GOT22: 69160484Sobrien r_symndx = ELF32_R_SYM (rel->r_info); 69260484Sobrien if (r_symndx >= symtab_hdr->sh_info) 69360484Sobrien { 69460484Sobrien h = sym_hashes[r_symndx - symtab_hdr->sh_info]; 69560484Sobrien if (h->got.refcount > 0) 69660484Sobrien h->got.refcount--; 69760484Sobrien } 69860484Sobrien else 69960484Sobrien { 70060484Sobrien if (local_got_refcounts[r_symndx] > 0) 70160484Sobrien local_got_refcounts[r_symndx]--; 70260484Sobrien } 70360484Sobrien break; 70460484Sobrien 70560484Sobrien case R_SPARC_PLT32: 70660484Sobrien case R_SPARC_HIPLT22: 70760484Sobrien case R_SPARC_LOPLT10: 70860484Sobrien case R_SPARC_PCPLT32: 70960484Sobrien case R_SPARC_PCPLT10: 71060484Sobrien r_symndx = ELF32_R_SYM (rel->r_info); 71160484Sobrien if (r_symndx >= symtab_hdr->sh_info) 71260484Sobrien { 71360484Sobrien h = sym_hashes[r_symndx - symtab_hdr->sh_info]; 71460484Sobrien if (h->plt.refcount > 0) 71560484Sobrien h->plt.refcount--; 71660484Sobrien } 71760484Sobrien break; 71860484Sobrien 71960484Sobrien default: 72060484Sobrien break; 72160484Sobrien } 72260484Sobrien 72360484Sobrien return true; 72460484Sobrien} 72560484Sobrien 72659024Sobrien/* Adjust a symbol defined by a dynamic object and referenced by a 72759024Sobrien regular object. The current definition is in some section of the 72859024Sobrien dynamic object, but we're not including those sections. We have to 72959024Sobrien change the definition to something the rest of the link can 73059024Sobrien understand. */ 73159024Sobrien 73259024Sobrienstatic boolean 73359024Sobrienelf32_sparc_adjust_dynamic_symbol (info, h) 73459024Sobrien struct bfd_link_info *info; 73559024Sobrien struct elf_link_hash_entry *h; 73659024Sobrien{ 73759024Sobrien bfd *dynobj; 73859024Sobrien asection *s; 73959024Sobrien unsigned int power_of_two; 74059024Sobrien 74159024Sobrien dynobj = elf_hash_table (info)->dynobj; 74259024Sobrien 74359024Sobrien /* Make sure we know what is going on here. */ 74459024Sobrien BFD_ASSERT (dynobj != NULL 74559024Sobrien && ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) 74659024Sobrien || h->weakdef != NULL 74759024Sobrien || ((h->elf_link_hash_flags 74859024Sobrien & ELF_LINK_HASH_DEF_DYNAMIC) != 0 74959024Sobrien && (h->elf_link_hash_flags 75059024Sobrien & ELF_LINK_HASH_REF_REGULAR) != 0 75159024Sobrien && (h->elf_link_hash_flags 75259024Sobrien & ELF_LINK_HASH_DEF_REGULAR) == 0))); 75359024Sobrien 75459024Sobrien /* If this is a function, put it in the procedure linkage table. We 75559024Sobrien will fill in the contents of the procedure linkage table later 75659024Sobrien (although we could actually do it here). The STT_NOTYPE 75759024Sobrien condition is a hack specifically for the Oracle libraries 75859024Sobrien delivered for Solaris; for some inexplicable reason, they define 75959024Sobrien some of their functions as STT_NOTYPE when they really should be 76059024Sobrien STT_FUNC. */ 76159024Sobrien if (h->type == STT_FUNC 76259024Sobrien || (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0 76359024Sobrien || (h->type == STT_NOTYPE 76459024Sobrien && (h->root.type == bfd_link_hash_defined 76559024Sobrien || h->root.type == bfd_link_hash_defweak) 76659024Sobrien && (h->root.u.def.section->flags & SEC_CODE) != 0)) 76759024Sobrien { 76859024Sobrien if (! elf_hash_table (info)->dynamic_sections_created 76959024Sobrien || ((!info->shared || info->symbolic || h->dynindx == -1) 77059024Sobrien && (h->elf_link_hash_flags 77159024Sobrien & ELF_LINK_HASH_DEF_REGULAR) != 0)) 77259024Sobrien { 77359024Sobrien /* This case can occur if we saw a WPLT30 reloc in an input 77459024Sobrien file, but none of the input files were dynamic objects. 77559024Sobrien Or, when linking the main application or a -Bsymbolic 77659024Sobrien shared library against PIC code. Or when a global symbol 77759024Sobrien has been made private, e.g. via versioning. 77859024Sobrien 77959024Sobrien In these cases we know what value the symbol will resolve 78059024Sobrien to, so we don't actually need to build a procedure linkage 78159024Sobrien table, and we can just do a WDISP30 reloc instead. */ 78259024Sobrien 78359024Sobrien h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; 78459024Sobrien return true; 78559024Sobrien } 78659024Sobrien 78759024Sobrien s = bfd_get_section_by_name (dynobj, ".plt"); 78859024Sobrien BFD_ASSERT (s != NULL); 78959024Sobrien 79059024Sobrien /* The first four entries in .plt are reserved. */ 79159024Sobrien if (s->_raw_size == 0) 79259024Sobrien s->_raw_size = 4 * PLT_ENTRY_SIZE; 79359024Sobrien 79459024Sobrien /* The procedure linkage table has a maximum size. */ 79559024Sobrien if (s->_raw_size >= 0x400000) 79659024Sobrien { 79759024Sobrien bfd_set_error (bfd_error_bad_value); 79859024Sobrien return false; 79959024Sobrien } 80059024Sobrien 80159024Sobrien /* If this symbol is not defined in a regular file, and we are 80259024Sobrien not generating a shared library, then set the symbol to this 80359024Sobrien location in the .plt. This is required to make function 80459024Sobrien pointers compare as equal between the normal executable and 80559024Sobrien the shared library. */ 80659024Sobrien if (! info->shared 80759024Sobrien && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) 80859024Sobrien { 80959024Sobrien h->root.u.def.section = s; 81059024Sobrien h->root.u.def.value = s->_raw_size; 81159024Sobrien } 81259024Sobrien 81360484Sobrien h->plt.offset = s->_raw_size; 81459024Sobrien 81559024Sobrien /* Make room for this entry. */ 81659024Sobrien s->_raw_size += PLT_ENTRY_SIZE; 81759024Sobrien 81859024Sobrien /* We also need to make an entry in the .rela.plt section. */ 81959024Sobrien 82059024Sobrien s = bfd_get_section_by_name (dynobj, ".rela.plt"); 82159024Sobrien BFD_ASSERT (s != NULL); 82259024Sobrien s->_raw_size += sizeof (Elf32_External_Rela); 82359024Sobrien 82459024Sobrien return true; 82559024Sobrien } 82659024Sobrien 82759024Sobrien /* If this is a weak symbol, and there is a real definition, the 82859024Sobrien processor independent code will have arranged for us to see the 82959024Sobrien real definition first, and we can just use the same value. */ 83059024Sobrien if (h->weakdef != NULL) 83159024Sobrien { 83259024Sobrien BFD_ASSERT (h->weakdef->root.type == bfd_link_hash_defined 83359024Sobrien || h->weakdef->root.type == bfd_link_hash_defweak); 83459024Sobrien h->root.u.def.section = h->weakdef->root.u.def.section; 83559024Sobrien h->root.u.def.value = h->weakdef->root.u.def.value; 83659024Sobrien return true; 83759024Sobrien } 83859024Sobrien 83959024Sobrien /* This is a reference to a symbol defined by a dynamic object which 84059024Sobrien is not a function. */ 84159024Sobrien 84259024Sobrien /* If we are creating a shared library, we must presume that the 84359024Sobrien only references to the symbol are via the global offset table. 84459024Sobrien For such cases we need not do anything here; the relocations will 84559024Sobrien be handled correctly by relocate_section. */ 84659024Sobrien if (info->shared) 84759024Sobrien return true; 84859024Sobrien 84960484Sobrien /* If there are no references to this symbol that do not use the 85060484Sobrien GOT, we don't need to generate a copy reloc. */ 85160484Sobrien if ((h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0) 85260484Sobrien return true; 85360484Sobrien 85459024Sobrien /* We must allocate the symbol in our .dynbss section, which will 85559024Sobrien become part of the .bss section of the executable. There will be 85659024Sobrien an entry for this symbol in the .dynsym section. The dynamic 85759024Sobrien object will contain position independent code, so all references 85859024Sobrien from the dynamic object to this symbol will go through the global 85959024Sobrien offset table. The dynamic linker will use the .dynsym entry to 86059024Sobrien determine the address it must put in the global offset table, so 86159024Sobrien both the dynamic object and the regular object will refer to the 86259024Sobrien same memory location for the variable. */ 86359024Sobrien 86459024Sobrien s = bfd_get_section_by_name (dynobj, ".dynbss"); 86559024Sobrien BFD_ASSERT (s != NULL); 86659024Sobrien 86759024Sobrien /* We must generate a R_SPARC_COPY reloc to tell the dynamic linker 86859024Sobrien to copy the initial value out of the dynamic object and into the 86959024Sobrien runtime process image. We need to remember the offset into the 87059024Sobrien .rel.bss section we are going to use. */ 87159024Sobrien if ((h->root.u.def.section->flags & SEC_ALLOC) != 0) 87259024Sobrien { 87359024Sobrien asection *srel; 87459024Sobrien 87559024Sobrien srel = bfd_get_section_by_name (dynobj, ".rela.bss"); 87659024Sobrien BFD_ASSERT (srel != NULL); 87759024Sobrien srel->_raw_size += sizeof (Elf32_External_Rela); 87859024Sobrien h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_COPY; 87959024Sobrien } 88059024Sobrien 88159024Sobrien /* We need to figure out the alignment required for this symbol. I 88259024Sobrien have no idea how ELF linkers handle this. */ 88359024Sobrien power_of_two = bfd_log2 (h->size); 88459024Sobrien if (power_of_two > 3) 88559024Sobrien power_of_two = 3; 88659024Sobrien 88759024Sobrien /* Apply the required alignment. */ 88859024Sobrien s->_raw_size = BFD_ALIGN (s->_raw_size, 88959024Sobrien (bfd_size_type) (1 << power_of_two)); 89059024Sobrien if (power_of_two > bfd_get_section_alignment (dynobj, s)) 89159024Sobrien { 89259024Sobrien if (! bfd_set_section_alignment (dynobj, s, power_of_two)) 89359024Sobrien return false; 89459024Sobrien } 89559024Sobrien 89659024Sobrien /* Define the symbol as being at this point in the section. */ 89759024Sobrien h->root.u.def.section = s; 89859024Sobrien h->root.u.def.value = s->_raw_size; 89959024Sobrien 90059024Sobrien /* Increment the section size to make room for the symbol. */ 90159024Sobrien s->_raw_size += h->size; 90259024Sobrien 90359024Sobrien return true; 90459024Sobrien} 90559024Sobrien 90659024Sobrien/* Set the sizes of the dynamic sections. */ 90759024Sobrien 90859024Sobrienstatic boolean 90959024Sobrienelf32_sparc_size_dynamic_sections (output_bfd, info) 91059024Sobrien bfd *output_bfd; 91159024Sobrien struct bfd_link_info *info; 91259024Sobrien{ 91359024Sobrien bfd *dynobj; 91459024Sobrien asection *s; 91559024Sobrien boolean reltext; 91659024Sobrien boolean relplt; 91759024Sobrien 91859024Sobrien dynobj = elf_hash_table (info)->dynobj; 91959024Sobrien BFD_ASSERT (dynobj != NULL); 92059024Sobrien 92159024Sobrien if (elf_hash_table (info)->dynamic_sections_created) 92259024Sobrien { 92359024Sobrien /* Set the contents of the .interp section to the interpreter. */ 92459024Sobrien if (! info->shared) 92559024Sobrien { 92659024Sobrien s = bfd_get_section_by_name (dynobj, ".interp"); 92759024Sobrien BFD_ASSERT (s != NULL); 92859024Sobrien s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER; 92959024Sobrien s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER; 93059024Sobrien } 93159024Sobrien 93259024Sobrien /* Make space for the trailing nop in .plt. */ 93359024Sobrien s = bfd_get_section_by_name (dynobj, ".plt"); 93459024Sobrien BFD_ASSERT (s != NULL); 93559024Sobrien if (s->_raw_size > 0) 93659024Sobrien s->_raw_size += 4; 93759024Sobrien } 93859024Sobrien else 93959024Sobrien { 94059024Sobrien /* We may have created entries in the .rela.got section. 94159024Sobrien However, if we are not creating the dynamic sections, we will 94259024Sobrien not actually use these entries. Reset the size of .rela.got, 94359024Sobrien which will cause it to get stripped from the output file 94459024Sobrien below. */ 94559024Sobrien s = bfd_get_section_by_name (dynobj, ".rela.got"); 94659024Sobrien if (s != NULL) 94759024Sobrien s->_raw_size = 0; 94859024Sobrien } 94959024Sobrien 95059024Sobrien /* The check_relocs and adjust_dynamic_symbol entry points have 95159024Sobrien determined the sizes of the various dynamic sections. Allocate 95259024Sobrien memory for them. */ 95359024Sobrien reltext = false; 95459024Sobrien relplt = false; 95559024Sobrien for (s = dynobj->sections; s != NULL; s = s->next) 95659024Sobrien { 95759024Sobrien const char *name; 95859024Sobrien boolean strip; 95959024Sobrien 96059024Sobrien if ((s->flags & SEC_LINKER_CREATED) == 0) 96159024Sobrien continue; 96259024Sobrien 96359024Sobrien /* It's OK to base decisions on the section name, because none 96459024Sobrien of the dynobj section names depend upon the input files. */ 96559024Sobrien name = bfd_get_section_name (dynobj, s); 96659024Sobrien 96759024Sobrien strip = false; 96859024Sobrien 96959024Sobrien if (strncmp (name, ".rela", 5) == 0) 97059024Sobrien { 97159024Sobrien if (s->_raw_size == 0) 97259024Sobrien { 97359024Sobrien /* If we don't need this section, strip it from the 97459024Sobrien output file. This is to handle .rela.bss and 97559024Sobrien .rel.plt. We must create it in 97659024Sobrien create_dynamic_sections, because it must be created 97759024Sobrien before the linker maps input sections to output 97859024Sobrien sections. The linker does that before 97959024Sobrien adjust_dynamic_symbol is called, and it is that 98059024Sobrien function which decides whether anything needs to go 98159024Sobrien into these sections. */ 98259024Sobrien strip = true; 98359024Sobrien } 98459024Sobrien else 98559024Sobrien { 98659024Sobrien const char *outname; 98759024Sobrien asection *target; 98859024Sobrien 98959024Sobrien /* If this relocation section applies to a read only 99059024Sobrien section, then we probably need a DT_TEXTREL entry. */ 99159024Sobrien outname = bfd_get_section_name (output_bfd, 99259024Sobrien s->output_section); 99359024Sobrien target = bfd_get_section_by_name (output_bfd, outname + 5); 99459024Sobrien if (target != NULL 99559024Sobrien && (target->flags & SEC_READONLY) != 0 99659024Sobrien && (target->flags & SEC_ALLOC) != 0) 99759024Sobrien reltext = true; 99859024Sobrien 99959024Sobrien if (strcmp (name, ".rela.plt") == 0) 100059024Sobrien relplt = true; 100159024Sobrien 100259024Sobrien /* We use the reloc_count field as a counter if we need 100359024Sobrien to copy relocs into the output file. */ 100459024Sobrien s->reloc_count = 0; 100559024Sobrien } 100659024Sobrien } 100759024Sobrien else if (strcmp (name, ".plt") != 0 100859024Sobrien && strcmp (name, ".got") != 0) 100959024Sobrien { 101059024Sobrien /* It's not one of our sections, so don't allocate space. */ 101159024Sobrien continue; 101259024Sobrien } 101359024Sobrien 101459024Sobrien if (strip) 101559024Sobrien { 101660484Sobrien _bfd_strip_section_from_output (info, s); 101759024Sobrien continue; 101859024Sobrien } 101959024Sobrien 102059024Sobrien /* Allocate memory for the section contents. */ 102177298Sobrien /* FIXME: This should be a call to bfd_alloc not bfd_zalloc. 102277298Sobrien Unused entries should be reclaimed before the section's contents 102377298Sobrien are written out, but at the moment this does not happen. Thus in 102477298Sobrien order to prevent writing out garbage, we initialise the section's 102577298Sobrien contents to zero. */ 102677298Sobrien s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size); 102759024Sobrien if (s->contents == NULL && s->_raw_size != 0) 102859024Sobrien return false; 102959024Sobrien } 103059024Sobrien 103159024Sobrien if (elf_hash_table (info)->dynamic_sections_created) 103259024Sobrien { 103359024Sobrien /* Add some entries to the .dynamic section. We fill in the 103459024Sobrien values later, in elf32_sparc_finish_dynamic_sections, but we 103559024Sobrien must add the entries now so that we get the correct size for 103659024Sobrien the .dynamic section. The DT_DEBUG entry is filled in by the 103759024Sobrien dynamic linker and used by the debugger. */ 103859024Sobrien if (! info->shared) 103959024Sobrien { 104059024Sobrien if (! bfd_elf32_add_dynamic_entry (info, DT_DEBUG, 0)) 104159024Sobrien return false; 104259024Sobrien } 104359024Sobrien 104459024Sobrien if (relplt) 104559024Sobrien { 104659024Sobrien if (! bfd_elf32_add_dynamic_entry (info, DT_PLTGOT, 0) 104759024Sobrien || ! bfd_elf32_add_dynamic_entry (info, DT_PLTRELSZ, 0) 104859024Sobrien || ! bfd_elf32_add_dynamic_entry (info, DT_PLTREL, DT_RELA) 104959024Sobrien || ! bfd_elf32_add_dynamic_entry (info, DT_JMPREL, 0)) 105059024Sobrien return false; 105159024Sobrien } 105259024Sobrien 105359024Sobrien if (! bfd_elf32_add_dynamic_entry (info, DT_RELA, 0) 105459024Sobrien || ! bfd_elf32_add_dynamic_entry (info, DT_RELASZ, 0) 105559024Sobrien || ! bfd_elf32_add_dynamic_entry (info, DT_RELAENT, 105659024Sobrien sizeof (Elf32_External_Rela))) 105759024Sobrien return false; 105859024Sobrien 105959024Sobrien if (reltext) 106059024Sobrien { 106159024Sobrien if (! bfd_elf32_add_dynamic_entry (info, DT_TEXTREL, 0)) 106259024Sobrien return false; 106377298Sobrien info->flags |= DF_TEXTREL; 106459024Sobrien } 106559024Sobrien } 106659024Sobrien 106759024Sobrien return true; 106859024Sobrien} 106959024Sobrien 107077298Sobrien#define SET_SEC_DO_RELAX(section) do { elf_section_data(section)->tdata = (void *)1; } while (0) 107177298Sobrien#define SEC_DO_RELAX(section) (elf_section_data(section)->tdata == (void *)1) 107277298Sobrien 107377298Sobrienstatic boolean 107477298Sobrienelf32_sparc_relax_section (abfd, section, link_info, again) 107577298Sobrien bfd *abfd ATTRIBUTE_UNUSED; 107677298Sobrien asection *section ATTRIBUTE_UNUSED; 107777298Sobrien struct bfd_link_info *link_info ATTRIBUTE_UNUSED; 107877298Sobrien boolean *again; 107977298Sobrien{ 108077298Sobrien *again = false; 108177298Sobrien SET_SEC_DO_RELAX (section); 108277298Sobrien return true; 108377298Sobrien} 108477298Sobrien 108559024Sobrien/* Relocate a SPARC ELF section. */ 108659024Sobrien 108759024Sobrienstatic boolean 108859024Sobrienelf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, 108959024Sobrien contents, relocs, local_syms, local_sections) 109059024Sobrien bfd *output_bfd; 109159024Sobrien struct bfd_link_info *info; 109259024Sobrien bfd *input_bfd; 109359024Sobrien asection *input_section; 109459024Sobrien bfd_byte *contents; 109559024Sobrien Elf_Internal_Rela *relocs; 109659024Sobrien Elf_Internal_Sym *local_syms; 109759024Sobrien asection **local_sections; 109859024Sobrien{ 109959024Sobrien bfd *dynobj; 110059024Sobrien Elf_Internal_Shdr *symtab_hdr; 110159024Sobrien struct elf_link_hash_entry **sym_hashes; 110259024Sobrien bfd_vma *local_got_offsets; 110359024Sobrien bfd_vma got_base; 110459024Sobrien asection *sgot; 110559024Sobrien asection *splt; 110659024Sobrien asection *sreloc; 110759024Sobrien Elf_Internal_Rela *rel; 110859024Sobrien Elf_Internal_Rela *relend; 110959024Sobrien 111059024Sobrien dynobj = elf_hash_table (info)->dynobj; 111159024Sobrien symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; 111259024Sobrien sym_hashes = elf_sym_hashes (input_bfd); 111359024Sobrien local_got_offsets = elf_local_got_offsets (input_bfd); 111459024Sobrien 111559024Sobrien if (elf_hash_table (info)->hgot == NULL) 111659024Sobrien got_base = 0; 111759024Sobrien else 111859024Sobrien got_base = elf_hash_table (info)->hgot->root.u.def.value; 111959024Sobrien 112059024Sobrien sgot = NULL; 112159024Sobrien splt = NULL; 112259024Sobrien sreloc = NULL; 112359024Sobrien 112459024Sobrien rel = relocs; 112559024Sobrien relend = relocs + input_section->reloc_count; 112659024Sobrien for (; rel < relend; rel++) 112759024Sobrien { 112859024Sobrien int r_type; 112959024Sobrien reloc_howto_type *howto; 113059024Sobrien unsigned long r_symndx; 113159024Sobrien struct elf_link_hash_entry *h; 113259024Sobrien Elf_Internal_Sym *sym; 113359024Sobrien asection *sec; 113459024Sobrien bfd_vma relocation; 113559024Sobrien bfd_reloc_status_type r; 113659024Sobrien 113759024Sobrien r_type = ELF32_R_TYPE (rel->r_info); 113860484Sobrien 113977298Sobrien if (r_type == R_SPARC_GNU_VTINHERIT 114060484Sobrien || r_type == R_SPARC_GNU_VTENTRY) 114160484Sobrien continue; 114260484Sobrien 114360484Sobrien if (r_type < 0 || r_type >= (int) R_SPARC_max_std) 114459024Sobrien { 114559024Sobrien bfd_set_error (bfd_error_bad_value); 114659024Sobrien return false; 114759024Sobrien } 114859024Sobrien howto = _bfd_sparc_elf_howto_table + r_type; 114959024Sobrien 115059024Sobrien r_symndx = ELF32_R_SYM (rel->r_info); 115159024Sobrien 115259024Sobrien if (info->relocateable) 115359024Sobrien { 115459024Sobrien /* This is a relocateable link. We don't have to change 115559024Sobrien anything, unless the reloc is against a section symbol, 115659024Sobrien in which case we have to adjust according to where the 115759024Sobrien section symbol winds up in the output section. */ 115859024Sobrien if (r_symndx < symtab_hdr->sh_info) 115959024Sobrien { 116059024Sobrien sym = local_syms + r_symndx; 116159024Sobrien if (ELF_ST_TYPE (sym->st_info) == STT_SECTION) 116259024Sobrien { 116359024Sobrien sec = local_sections[r_symndx]; 116459024Sobrien rel->r_addend += sec->output_offset + sym->st_value; 116559024Sobrien } 116659024Sobrien } 116759024Sobrien 116859024Sobrien continue; 116959024Sobrien } 117059024Sobrien 117159024Sobrien /* This is a final link. */ 117259024Sobrien h = NULL; 117359024Sobrien sym = NULL; 117459024Sobrien sec = NULL; 117559024Sobrien if (r_symndx < symtab_hdr->sh_info) 117659024Sobrien { 117759024Sobrien sym = local_syms + r_symndx; 117859024Sobrien sec = local_sections[r_symndx]; 117959024Sobrien relocation = (sec->output_section->vma 118059024Sobrien + sec->output_offset 118159024Sobrien + sym->st_value); 118259024Sobrien } 118359024Sobrien else 118459024Sobrien { 118559024Sobrien h = sym_hashes[r_symndx - symtab_hdr->sh_info]; 118659024Sobrien while (h->root.type == bfd_link_hash_indirect 118759024Sobrien || h->root.type == bfd_link_hash_warning) 118859024Sobrien h = (struct elf_link_hash_entry *) h->root.u.i.link; 118959024Sobrien if (h->root.type == bfd_link_hash_defined 119059024Sobrien || h->root.type == bfd_link_hash_defweak) 119159024Sobrien { 119259024Sobrien sec = h->root.u.def.section; 119359024Sobrien if ((r_type == R_SPARC_WPLT30 119460484Sobrien && h->plt.offset != (bfd_vma) -1) 119559024Sobrien || ((r_type == R_SPARC_GOT10 119659024Sobrien || r_type == R_SPARC_GOT13 119759024Sobrien || r_type == R_SPARC_GOT22) 119859024Sobrien && elf_hash_table (info)->dynamic_sections_created 119959024Sobrien && (! info->shared 120059024Sobrien || (! info->symbolic && h->dynindx != -1) 120159024Sobrien || (h->elf_link_hash_flags 120259024Sobrien & ELF_LINK_HASH_DEF_REGULAR) == 0)) 120359024Sobrien || (info->shared 120459024Sobrien && ((! info->symbolic && h->dynindx != -1) 120559024Sobrien || (h->elf_link_hash_flags 120659024Sobrien & ELF_LINK_HASH_DEF_REGULAR) == 0) 120759024Sobrien && (r_type == R_SPARC_8 120859024Sobrien || r_type == R_SPARC_16 120959024Sobrien || r_type == R_SPARC_32 121059024Sobrien || r_type == R_SPARC_DISP8 121159024Sobrien || r_type == R_SPARC_DISP16 121259024Sobrien || r_type == R_SPARC_DISP32 121359024Sobrien || r_type == R_SPARC_WDISP30 121459024Sobrien || r_type == R_SPARC_WDISP22 121559024Sobrien || r_type == R_SPARC_WDISP19 121659024Sobrien || r_type == R_SPARC_WDISP16 121759024Sobrien || r_type == R_SPARC_HI22 121859024Sobrien || r_type == R_SPARC_22 121959024Sobrien || r_type == R_SPARC_13 122059024Sobrien || r_type == R_SPARC_LO10 122159024Sobrien || r_type == R_SPARC_UA32 122259024Sobrien || ((r_type == R_SPARC_PC10 122359024Sobrien || r_type == R_SPARC_PC22) 122459024Sobrien && strcmp (h->root.root.string, 122559024Sobrien "_GLOBAL_OFFSET_TABLE_") != 0)))) 122659024Sobrien { 122759024Sobrien /* In these cases, we don't need the relocation 122859024Sobrien value. We check specially because in some 122959024Sobrien obscure cases sec->output_section will be NULL. */ 123059024Sobrien relocation = 0; 123159024Sobrien } 123259024Sobrien else 123359024Sobrien relocation = (h->root.u.def.value 123459024Sobrien + sec->output_section->vma 123559024Sobrien + sec->output_offset); 123659024Sobrien } 123759024Sobrien else if (h->root.type == bfd_link_hash_undefweak) 123859024Sobrien relocation = 0; 123968765Sobrien else if (info->shared && !info->symbolic 124068765Sobrien && !info->no_undefined 124168765Sobrien && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT) 124259024Sobrien relocation = 0; 124359024Sobrien else 124459024Sobrien { 124559024Sobrien if (! ((*info->callbacks->undefined_symbol) 124659024Sobrien (info, h->root.root.string, input_bfd, 124760484Sobrien input_section, rel->r_offset, 124868765Sobrien (!info->shared || info->no_undefined 124968765Sobrien || ELF_ST_VISIBILITY (h->other))))) 125059024Sobrien return false; 125159024Sobrien relocation = 0; 125259024Sobrien } 125359024Sobrien } 125459024Sobrien 125559024Sobrien switch (r_type) 125659024Sobrien { 125759024Sobrien case R_SPARC_GOT10: 125859024Sobrien case R_SPARC_GOT13: 125959024Sobrien case R_SPARC_GOT22: 126059024Sobrien /* Relocation is to the entry for this symbol in the global 126159024Sobrien offset table. */ 126259024Sobrien if (sgot == NULL) 126359024Sobrien { 126459024Sobrien sgot = bfd_get_section_by_name (dynobj, ".got"); 126559024Sobrien BFD_ASSERT (sgot != NULL); 126659024Sobrien } 126759024Sobrien 126859024Sobrien if (h != NULL) 126959024Sobrien { 127059024Sobrien bfd_vma off; 127159024Sobrien 127260484Sobrien off = h->got.offset; 127359024Sobrien BFD_ASSERT (off != (bfd_vma) -1); 127459024Sobrien 127559024Sobrien if (! elf_hash_table (info)->dynamic_sections_created 127659024Sobrien || (info->shared 127759024Sobrien && (info->symbolic || h->dynindx == -1) 127859024Sobrien && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))) 127959024Sobrien { 128059024Sobrien /* This is actually a static link, or it is a 128159024Sobrien -Bsymbolic link and the symbol is defined 128259024Sobrien locally, or the symbol was forced to be local 128359024Sobrien because of a version file. We must initialize 128459024Sobrien this entry in the global offset table. Since the 128559024Sobrien offset must always be a multiple of 4, we use the 128659024Sobrien least significant bit to record whether we have 128759024Sobrien initialized it already. 128859024Sobrien 128959024Sobrien When doing a dynamic link, we create a .rela.got 129059024Sobrien relocation entry to initialize the value. This 129159024Sobrien is done in the finish_dynamic_symbol routine. */ 129259024Sobrien if ((off & 1) != 0) 129359024Sobrien off &= ~1; 129459024Sobrien else 129559024Sobrien { 129659024Sobrien bfd_put_32 (output_bfd, relocation, 129759024Sobrien sgot->contents + off); 129860484Sobrien h->got.offset |= 1; 129959024Sobrien } 130059024Sobrien } 130159024Sobrien 130259024Sobrien relocation = sgot->output_offset + off - got_base; 130359024Sobrien } 130459024Sobrien else 130559024Sobrien { 130659024Sobrien bfd_vma off; 130759024Sobrien 130859024Sobrien BFD_ASSERT (local_got_offsets != NULL 130959024Sobrien && local_got_offsets[r_symndx] != (bfd_vma) -1); 131059024Sobrien 131159024Sobrien off = local_got_offsets[r_symndx]; 131259024Sobrien 131359024Sobrien /* The offset must always be a multiple of 4. We use 131459024Sobrien the least significant bit to record whether we have 131559024Sobrien already processed this entry. */ 131659024Sobrien if ((off & 1) != 0) 131759024Sobrien off &= ~1; 131859024Sobrien else 131959024Sobrien { 132059024Sobrien bfd_put_32 (output_bfd, relocation, sgot->contents + off); 132159024Sobrien 132259024Sobrien if (info->shared) 132359024Sobrien { 132459024Sobrien asection *srelgot; 132559024Sobrien Elf_Internal_Rela outrel; 132659024Sobrien 132759024Sobrien /* We need to generate a R_SPARC_RELATIVE reloc 132859024Sobrien for the dynamic linker. */ 132959024Sobrien srelgot = bfd_get_section_by_name (dynobj, ".rela.got"); 133059024Sobrien BFD_ASSERT (srelgot != NULL); 133159024Sobrien 133259024Sobrien outrel.r_offset = (sgot->output_section->vma 133359024Sobrien + sgot->output_offset 133459024Sobrien + off); 133559024Sobrien outrel.r_info = ELF32_R_INFO (0, R_SPARC_RELATIVE); 133659024Sobrien outrel.r_addend = 0; 133759024Sobrien bfd_elf32_swap_reloca_out (output_bfd, &outrel, 133859024Sobrien (((Elf32_External_Rela *) 133959024Sobrien srelgot->contents) 134059024Sobrien + srelgot->reloc_count)); 134159024Sobrien ++srelgot->reloc_count; 134259024Sobrien } 134359024Sobrien 134459024Sobrien local_got_offsets[r_symndx] |= 1; 134559024Sobrien } 134659024Sobrien 134759024Sobrien relocation = sgot->output_offset + off - got_base; 134859024Sobrien } 134959024Sobrien 135059024Sobrien break; 135159024Sobrien 135259024Sobrien case R_SPARC_WPLT30: 135359024Sobrien /* Relocation is to the entry for this symbol in the 135459024Sobrien procedure linkage table. */ 135559024Sobrien 135660484Sobrien /* The Solaris native assembler will generate a WPLT30 reloc 135760484Sobrien for a local symbol if you assemble a call from one 135860484Sobrien section to another when using -K pic. We treat it as 135960484Sobrien WDISP30. */ 136060484Sobrien if (h == NULL) 136160484Sobrien break; 136260484Sobrien 136360484Sobrien if (h->plt.offset == (bfd_vma) -1) 136459024Sobrien { 136559024Sobrien /* We didn't make a PLT entry for this symbol. This 136659024Sobrien happens when statically linking PIC code, or when 136759024Sobrien using -Bsymbolic. */ 136859024Sobrien break; 136959024Sobrien } 137059024Sobrien 137159024Sobrien if (splt == NULL) 137259024Sobrien { 137359024Sobrien splt = bfd_get_section_by_name (dynobj, ".plt"); 137459024Sobrien BFD_ASSERT (splt != NULL); 137559024Sobrien } 137659024Sobrien 137759024Sobrien relocation = (splt->output_section->vma 137859024Sobrien + splt->output_offset 137960484Sobrien + h->plt.offset); 138059024Sobrien break; 138159024Sobrien 138259024Sobrien case R_SPARC_PC10: 138359024Sobrien case R_SPARC_PC22: 138459024Sobrien if (h != NULL 138559024Sobrien && strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0) 138659024Sobrien break; 138759024Sobrien /* Fall through. */ 138859024Sobrien case R_SPARC_DISP8: 138959024Sobrien case R_SPARC_DISP16: 139059024Sobrien case R_SPARC_DISP32: 139159024Sobrien case R_SPARC_WDISP30: 139259024Sobrien case R_SPARC_WDISP22: 139359024Sobrien case R_SPARC_WDISP19: 139459024Sobrien case R_SPARC_WDISP16: 139559024Sobrien if (h == NULL 139659024Sobrien || (info->symbolic 139759024Sobrien && (h->elf_link_hash_flags 139859024Sobrien & ELF_LINK_HASH_DEF_REGULAR) != 0)) 139959024Sobrien break; 140059024Sobrien /* Fall through. */ 140159024Sobrien case R_SPARC_8: 140259024Sobrien case R_SPARC_16: 140359024Sobrien case R_SPARC_32: 140459024Sobrien case R_SPARC_HI22: 140559024Sobrien case R_SPARC_22: 140659024Sobrien case R_SPARC_13: 140759024Sobrien case R_SPARC_LO10: 140859024Sobrien case R_SPARC_UA32: 140959024Sobrien if (info->shared) 141059024Sobrien { 141159024Sobrien Elf_Internal_Rela outrel; 141259024Sobrien boolean skip; 141359024Sobrien 141459024Sobrien /* When generating a shared object, these relocations 141559024Sobrien are copied into the output file to be resolved at run 141659024Sobrien time. */ 141759024Sobrien 141859024Sobrien if (sreloc == NULL) 141959024Sobrien { 142059024Sobrien const char *name; 142159024Sobrien 142259024Sobrien name = (bfd_elf_string_from_elf_section 142359024Sobrien (input_bfd, 142459024Sobrien elf_elfheader (input_bfd)->e_shstrndx, 142559024Sobrien elf_section_data (input_section)->rel_hdr.sh_name)); 142659024Sobrien if (name == NULL) 142759024Sobrien return false; 142859024Sobrien 142959024Sobrien BFD_ASSERT (strncmp (name, ".rela", 5) == 0 143059024Sobrien && strcmp (bfd_get_section_name (input_bfd, 143159024Sobrien input_section), 143259024Sobrien name + 5) == 0); 143359024Sobrien 143459024Sobrien sreloc = bfd_get_section_by_name (dynobj, name); 143559024Sobrien BFD_ASSERT (sreloc != NULL); 143659024Sobrien } 143759024Sobrien 143859024Sobrien skip = false; 143959024Sobrien 144059024Sobrien if (elf_section_data (input_section)->stab_info == NULL) 144159024Sobrien outrel.r_offset = rel->r_offset; 144259024Sobrien else 144359024Sobrien { 144459024Sobrien bfd_vma off; 144559024Sobrien 144659024Sobrien off = (_bfd_stab_section_offset 144759024Sobrien (output_bfd, &elf_hash_table (info)->stab_info, 144859024Sobrien input_section, 144959024Sobrien &elf_section_data (input_section)->stab_info, 145059024Sobrien rel->r_offset)); 145159024Sobrien if (off == (bfd_vma) -1) 145259024Sobrien skip = true; 145359024Sobrien outrel.r_offset = off; 145459024Sobrien } 145559024Sobrien 145659024Sobrien outrel.r_offset += (input_section->output_section->vma 145759024Sobrien + input_section->output_offset); 145859024Sobrien 145959024Sobrien if (skip) 146059024Sobrien memset (&outrel, 0, sizeof outrel); 146159024Sobrien /* h->dynindx may be -1 if the symbol was marked to 146259024Sobrien become local. */ 146359024Sobrien else if (h != NULL 146459024Sobrien && ((! info->symbolic && h->dynindx != -1) 146559024Sobrien || (h->elf_link_hash_flags 146659024Sobrien & ELF_LINK_HASH_DEF_REGULAR) == 0)) 146759024Sobrien { 146859024Sobrien BFD_ASSERT (h->dynindx != -1); 146959024Sobrien outrel.r_info = ELF32_R_INFO (h->dynindx, r_type); 147059024Sobrien outrel.r_addend = rel->r_addend; 147159024Sobrien } 147259024Sobrien else 147359024Sobrien { 147459024Sobrien if (r_type == R_SPARC_32) 147559024Sobrien { 147659024Sobrien outrel.r_info = ELF32_R_INFO (0, R_SPARC_RELATIVE); 147759024Sobrien outrel.r_addend = relocation + rel->r_addend; 147859024Sobrien } 147959024Sobrien else 148059024Sobrien { 148159024Sobrien long indx; 148259024Sobrien 148359024Sobrien if (h == NULL) 148459024Sobrien sec = local_sections[r_symndx]; 148559024Sobrien else 148659024Sobrien { 148759024Sobrien BFD_ASSERT (h->root.type == bfd_link_hash_defined 148859024Sobrien || (h->root.type 148959024Sobrien == bfd_link_hash_defweak)); 149059024Sobrien sec = h->root.u.def.section; 149159024Sobrien } 149259024Sobrien if (sec != NULL && bfd_is_abs_section (sec)) 149359024Sobrien indx = 0; 149459024Sobrien else if (sec == NULL || sec->owner == NULL) 149559024Sobrien { 149659024Sobrien bfd_set_error (bfd_error_bad_value); 149759024Sobrien return false; 149859024Sobrien } 149959024Sobrien else 150059024Sobrien { 150159024Sobrien asection *osec; 150259024Sobrien 150359024Sobrien osec = sec->output_section; 150459024Sobrien indx = elf_section_data (osec)->dynindx; 150559024Sobrien 150659024Sobrien /* FIXME: we really should be able to link non-pic 150759024Sobrien shared libraries. */ 150859024Sobrien if (indx == 0) 150959024Sobrien { 151059024Sobrien BFD_FAIL (); 151159024Sobrien (*_bfd_error_handler) 151260484Sobrien (_("%s: probably compiled without -fPIC?"), 151359024Sobrien bfd_get_filename (input_bfd)); 151459024Sobrien bfd_set_error (bfd_error_bad_value); 151559024Sobrien return false; 151659024Sobrien } 151759024Sobrien } 151859024Sobrien 151959024Sobrien outrel.r_info = ELF32_R_INFO (indx, r_type); 152059024Sobrien outrel.r_addend = relocation + rel->r_addend; 152159024Sobrien } 152259024Sobrien } 152359024Sobrien 152459024Sobrien bfd_elf32_swap_reloca_out (output_bfd, &outrel, 152559024Sobrien (((Elf32_External_Rela *) 152659024Sobrien sreloc->contents) 152759024Sobrien + sreloc->reloc_count)); 152859024Sobrien ++sreloc->reloc_count; 152959024Sobrien 153059024Sobrien /* This reloc will be computed at runtime, so there's no 153159024Sobrien need to do anything now, unless this is a RELATIVE 153259024Sobrien reloc in an unallocated section. */ 153359024Sobrien if (skip 153459024Sobrien || (input_section->flags & SEC_ALLOC) != 0 153559024Sobrien || ELF32_R_TYPE (outrel.r_info) != R_SPARC_RELATIVE) 153659024Sobrien continue; 153759024Sobrien } 153859024Sobrien break; 153959024Sobrien 154059024Sobrien default: 154159024Sobrien break; 154259024Sobrien } 154359024Sobrien 154477298Sobrien r = bfd_reloc_continue; 154560484Sobrien if (r_type == R_SPARC_WDISP16) 154659024Sobrien { 154759024Sobrien bfd_vma x; 154859024Sobrien 154959024Sobrien relocation += rel->r_addend; 155059024Sobrien relocation -= (input_section->output_section->vma 155159024Sobrien + input_section->output_offset); 155259024Sobrien relocation -= rel->r_offset; 155359024Sobrien 155459024Sobrien x = bfd_get_32 (input_bfd, contents + rel->r_offset); 155559024Sobrien x |= ((((relocation >> 2) & 0xc000) << 6) 155659024Sobrien | ((relocation >> 2) & 0x3fff)); 155759024Sobrien bfd_put_32 (input_bfd, x, contents + rel->r_offset); 155859024Sobrien 155959024Sobrien if ((bfd_signed_vma) relocation < - 0x40000 156059024Sobrien || (bfd_signed_vma) relocation > 0x3ffff) 156159024Sobrien r = bfd_reloc_overflow; 156259024Sobrien else 156359024Sobrien r = bfd_reloc_ok; 156459024Sobrien } 156560484Sobrien else if (r_type == R_SPARC_REV32) 156660484Sobrien { 156760484Sobrien bfd_vma x; 156859024Sobrien 156960484Sobrien relocation = relocation + rel->r_addend; 157060484Sobrien 157160484Sobrien x = bfd_get_32 (input_bfd, contents + rel->r_offset); 157260484Sobrien x = x + relocation; 157360484Sobrien bfd_putl32 (/*input_bfd,*/ x, contents + rel->r_offset); 157460484Sobrien r = bfd_reloc_ok; 157560484Sobrien } 157677298Sobrien else if ((r_type == R_SPARC_WDISP30 || r_type == R_SPARC_WPLT30) 157777298Sobrien && SEC_DO_RELAX (input_section) 157877298Sobrien && rel->r_offset + 4 < input_section->_raw_size) 157977298Sobrien { 158077298Sobrien#define G0 0 158177298Sobrien#define O7 15 158277298Sobrien#define XCC (2 << 20) 158377298Sobrien#define COND(x) (((x)&0xf)<<25) 158477298Sobrien#define CONDA COND(0x8) 158577298Sobrien#define INSN_BPA (F2(0,1) | CONDA | BPRED | XCC) 158677298Sobrien#define INSN_BA (F2(0,2) | CONDA) 158777298Sobrien#define INSN_OR F3(2, 0x2, 0) 158877298Sobrien#define INSN_NOP F2(0,4) 158977298Sobrien 159077298Sobrien bfd_vma x, y; 159177298Sobrien 159277298Sobrien /* If the instruction is a call with either: 159377298Sobrien restore 159477298Sobrien arithmetic instruction with rd == %o7 159577298Sobrien where rs1 != %o7 and rs2 if it is register != %o7 159677298Sobrien then we can optimize if the call destination is near 159777298Sobrien by changing the call into a branch always. */ 159877298Sobrien x = bfd_get_32 (input_bfd, contents + rel->r_offset); 159977298Sobrien y = bfd_get_32 (input_bfd, contents + rel->r_offset + 4); 160077298Sobrien if ((x & OP(~0)) == OP(1) && (y & OP(~0)) == OP(2)) 160177298Sobrien { 160277298Sobrien if (((y & OP3(~0)) == OP3(0x3d) /* restore */ 160377298Sobrien || ((y & OP3(0x28)) == 0 /* arithmetic */ 160477298Sobrien && (y & RD(~0)) == RD(O7))) 160577298Sobrien && (y & RS1(~0)) != RS1(O7) 160677298Sobrien && ((y & F3I(~0)) 160777298Sobrien || (y & RS2(~0)) != RS2(O7))) 160877298Sobrien { 160977298Sobrien bfd_vma reloc; 161077298Sobrien 161177298Sobrien reloc = relocation + rel->r_addend - rel->r_offset; 161277298Sobrien reloc -= (input_section->output_section->vma 161377298Sobrien + input_section->output_offset); 161477298Sobrien 161577298Sobrien /* Ensure the reloc fits into simm22. */ 161677298Sobrien if ((reloc & 3) == 0 161777298Sobrien && ((reloc & ~(bfd_vma)0x7fffff) == 0 161877298Sobrien || ((reloc | 0x7fffff) == ~(bfd_vma)0))) 161977298Sobrien { 162077298Sobrien reloc >>= 2; 162177298Sobrien 162277298Sobrien /* Check whether it fits into simm19 on v9. */ 162377298Sobrien if (((reloc & 0x3c0000) == 0 162477298Sobrien || (reloc & 0x3c0000) == 0x3c0000) 162577298Sobrien && (elf_elfheader (output_bfd)->e_flags & EF_SPARC_32PLUS)) 162677298Sobrien x = INSN_BPA | (reloc & 0x7ffff); /* ba,pt %xcc */ 162777298Sobrien else 162877298Sobrien x = INSN_BA | (reloc & 0x3fffff); /* ba */ 162977298Sobrien bfd_put_32 (input_bfd, x, contents + rel->r_offset); 163077298Sobrien r = bfd_reloc_ok; 163177298Sobrien if (rel->r_offset >= 4 163277298Sobrien && (y & (0xffffffff ^ RS1(~0))) 163377298Sobrien == (INSN_OR | RD(O7) | RS2(G0))) 163477298Sobrien { 163577298Sobrien bfd_vma z; 163677298Sobrien unsigned int reg; 163777298Sobrien 163877298Sobrien z = bfd_get_32 (input_bfd, 163977298Sobrien contents + rel->r_offset - 4); 164077298Sobrien if ((z & (0xffffffff ^ RD(~0))) 164177298Sobrien != (INSN_OR | RS1(O7) | RS2(G0))) 164277298Sobrien break; 164377298Sobrien 164477298Sobrien /* The sequence was 164577298Sobrien or %o7, %g0, %rN 164677298Sobrien call foo 164777298Sobrien or %rN, %g0, %o7 164877298Sobrien 164977298Sobrien If call foo was replaced with ba, replace 165077298Sobrien or %rN, %g0, %o7 with nop. */ 165177298Sobrien 165277298Sobrien reg = (y & RS1(~0)) >> 14; 165377298Sobrien if (reg != ((z & RD(~0)) >> 25) 165477298Sobrien || reg == G0 || reg == O7) 165577298Sobrien break; 165677298Sobrien 165777298Sobrien bfd_put_32 (input_bfd, INSN_NOP, 165877298Sobrien contents + rel->r_offset + 4); 165977298Sobrien } 166077298Sobrien 166177298Sobrien } 166277298Sobrien } 166377298Sobrien } 166477298Sobrien } 166577298Sobrien 166677298Sobrien if (r == bfd_reloc_continue) 166760484Sobrien r = _bfd_final_link_relocate (howto, input_bfd, input_section, 166860484Sobrien contents, rel->r_offset, 166960484Sobrien relocation, rel->r_addend); 167060484Sobrien 167159024Sobrien if (r != bfd_reloc_ok) 167259024Sobrien { 167359024Sobrien switch (r) 167459024Sobrien { 167559024Sobrien default: 167659024Sobrien case bfd_reloc_outofrange: 167759024Sobrien abort (); 167859024Sobrien case bfd_reloc_overflow: 167959024Sobrien { 168059024Sobrien const char *name; 168159024Sobrien 168259024Sobrien if (h != NULL) 168359024Sobrien name = h->root.root.string; 168459024Sobrien else 168559024Sobrien { 168659024Sobrien name = bfd_elf_string_from_elf_section (input_bfd, 168759024Sobrien symtab_hdr->sh_link, 168859024Sobrien sym->st_name); 168959024Sobrien if (name == NULL) 169059024Sobrien return false; 169159024Sobrien if (*name == '\0') 169259024Sobrien name = bfd_section_name (input_bfd, sec); 169359024Sobrien } 169459024Sobrien if (! ((*info->callbacks->reloc_overflow) 169559024Sobrien (info, name, howto->name, (bfd_vma) 0, 169659024Sobrien input_bfd, input_section, rel->r_offset))) 169759024Sobrien return false; 169859024Sobrien } 169959024Sobrien break; 170059024Sobrien } 170159024Sobrien } 170259024Sobrien } 170359024Sobrien 170459024Sobrien return true; 170559024Sobrien} 170659024Sobrien 170759024Sobrien/* Finish up dynamic symbol handling. We set the contents of various 170859024Sobrien dynamic sections here. */ 170959024Sobrien 171059024Sobrienstatic boolean 171159024Sobrienelf32_sparc_finish_dynamic_symbol (output_bfd, info, h, sym) 171259024Sobrien bfd *output_bfd; 171359024Sobrien struct bfd_link_info *info; 171459024Sobrien struct elf_link_hash_entry *h; 171559024Sobrien Elf_Internal_Sym *sym; 171659024Sobrien{ 171759024Sobrien bfd *dynobj; 171859024Sobrien 171959024Sobrien dynobj = elf_hash_table (info)->dynobj; 172059024Sobrien 172160484Sobrien if (h->plt.offset != (bfd_vma) -1) 172259024Sobrien { 172359024Sobrien asection *splt; 172459024Sobrien asection *srela; 172559024Sobrien Elf_Internal_Rela rela; 172659024Sobrien 172759024Sobrien /* This symbol has an entry in the procedure linkage table. Set 172859024Sobrien it up. */ 172959024Sobrien 173059024Sobrien BFD_ASSERT (h->dynindx != -1); 173159024Sobrien 173259024Sobrien splt = bfd_get_section_by_name (dynobj, ".plt"); 173359024Sobrien srela = bfd_get_section_by_name (dynobj, ".rela.plt"); 173459024Sobrien BFD_ASSERT (splt != NULL && srela != NULL); 173559024Sobrien 173659024Sobrien /* Fill in the entry in the procedure linkage table. */ 173759024Sobrien bfd_put_32 (output_bfd, 173860484Sobrien PLT_ENTRY_WORD0 + h->plt.offset, 173960484Sobrien splt->contents + h->plt.offset); 174059024Sobrien bfd_put_32 (output_bfd, 174159024Sobrien (PLT_ENTRY_WORD1 174260484Sobrien + (((- (h->plt.offset + 4)) >> 2) & 0x3fffff)), 174360484Sobrien splt->contents + h->plt.offset + 4); 174459024Sobrien bfd_put_32 (output_bfd, PLT_ENTRY_WORD2, 174560484Sobrien splt->contents + h->plt.offset + 8); 174659024Sobrien 174759024Sobrien /* Fill in the entry in the .rela.plt section. */ 174859024Sobrien rela.r_offset = (splt->output_section->vma 174959024Sobrien + splt->output_offset 175060484Sobrien + h->plt.offset); 175159024Sobrien rela.r_info = ELF32_R_INFO (h->dynindx, R_SPARC_JMP_SLOT); 175259024Sobrien rela.r_addend = 0; 175359024Sobrien bfd_elf32_swap_reloca_out (output_bfd, &rela, 175459024Sobrien ((Elf32_External_Rela *) srela->contents 175560484Sobrien + h->plt.offset / PLT_ENTRY_SIZE - 4)); 175659024Sobrien 175759024Sobrien if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) 175859024Sobrien { 175959024Sobrien /* Mark the symbol as undefined, rather than as defined in 176059024Sobrien the .plt section. Leave the value alone. */ 176159024Sobrien sym->st_shndx = SHN_UNDEF; 176259024Sobrien } 176359024Sobrien } 176459024Sobrien 176560484Sobrien if (h->got.offset != (bfd_vma) -1) 176659024Sobrien { 176759024Sobrien asection *sgot; 176859024Sobrien asection *srela; 176959024Sobrien Elf_Internal_Rela rela; 177059024Sobrien 177159024Sobrien /* This symbol has an entry in the global offset table. Set it 177259024Sobrien up. */ 177359024Sobrien 177459024Sobrien sgot = bfd_get_section_by_name (dynobj, ".got"); 177559024Sobrien srela = bfd_get_section_by_name (dynobj, ".rela.got"); 177659024Sobrien BFD_ASSERT (sgot != NULL && srela != NULL); 177759024Sobrien 177859024Sobrien rela.r_offset = (sgot->output_section->vma 177959024Sobrien + sgot->output_offset 178060484Sobrien + (h->got.offset &~ 1)); 178159024Sobrien 178259024Sobrien /* If this is a -Bsymbolic link, and the symbol is defined 178359024Sobrien locally, we just want to emit a RELATIVE reloc. Likewise if 178459024Sobrien the symbol was forced to be local because of a version file. 178559024Sobrien The entry in the global offset table will already have been 178659024Sobrien initialized in the relocate_section function. */ 178759024Sobrien if (info->shared 178859024Sobrien && (info->symbolic || h->dynindx == -1) 178959024Sobrien && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)) 179059024Sobrien rela.r_info = ELF32_R_INFO (0, R_SPARC_RELATIVE); 179159024Sobrien else 179259024Sobrien { 179360484Sobrien bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + h->got.offset); 179459024Sobrien rela.r_info = ELF32_R_INFO (h->dynindx, R_SPARC_GLOB_DAT); 179559024Sobrien } 179659024Sobrien 179759024Sobrien rela.r_addend = 0; 179859024Sobrien bfd_elf32_swap_reloca_out (output_bfd, &rela, 179959024Sobrien ((Elf32_External_Rela *) srela->contents 180059024Sobrien + srela->reloc_count)); 180159024Sobrien ++srela->reloc_count; 180259024Sobrien } 180359024Sobrien 180459024Sobrien if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_COPY) != 0) 180559024Sobrien { 180659024Sobrien asection *s; 180759024Sobrien Elf_Internal_Rela rela; 180859024Sobrien 180959024Sobrien /* This symbols needs a copy reloc. Set it up. */ 181059024Sobrien 181159024Sobrien BFD_ASSERT (h->dynindx != -1); 181259024Sobrien 181359024Sobrien s = bfd_get_section_by_name (h->root.u.def.section->owner, 181459024Sobrien ".rela.bss"); 181559024Sobrien BFD_ASSERT (s != NULL); 181659024Sobrien 181759024Sobrien rela.r_offset = (h->root.u.def.value 181859024Sobrien + h->root.u.def.section->output_section->vma 181959024Sobrien + h->root.u.def.section->output_offset); 182059024Sobrien rela.r_info = ELF32_R_INFO (h->dynindx, R_SPARC_COPY); 182159024Sobrien rela.r_addend = 0; 182259024Sobrien bfd_elf32_swap_reloca_out (output_bfd, &rela, 182359024Sobrien ((Elf32_External_Rela *) s->contents 182459024Sobrien + s->reloc_count)); 182559024Sobrien ++s->reloc_count; 182659024Sobrien } 182759024Sobrien 182859024Sobrien /* Mark some specially defined symbols as absolute. */ 182959024Sobrien if (strcmp (h->root.root.string, "_DYNAMIC") == 0 183059024Sobrien || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0 183159024Sobrien || strcmp (h->root.root.string, "_PROCEDURE_LINKAGE_TABLE_") == 0) 183259024Sobrien sym->st_shndx = SHN_ABS; 183359024Sobrien 183459024Sobrien return true; 183559024Sobrien} 183659024Sobrien 183759024Sobrien/* Finish up the dynamic sections. */ 183859024Sobrien 183959024Sobrienstatic boolean 184059024Sobrienelf32_sparc_finish_dynamic_sections (output_bfd, info) 184159024Sobrien bfd *output_bfd; 184259024Sobrien struct bfd_link_info *info; 184359024Sobrien{ 184459024Sobrien bfd *dynobj; 184559024Sobrien asection *sdyn; 184659024Sobrien asection *sgot; 184759024Sobrien 184859024Sobrien dynobj = elf_hash_table (info)->dynobj; 184959024Sobrien 185059024Sobrien sdyn = bfd_get_section_by_name (dynobj, ".dynamic"); 185159024Sobrien 185259024Sobrien if (elf_hash_table (info)->dynamic_sections_created) 185359024Sobrien { 185459024Sobrien asection *splt; 185559024Sobrien Elf32_External_Dyn *dyncon, *dynconend; 185659024Sobrien 185759024Sobrien splt = bfd_get_section_by_name (dynobj, ".plt"); 185859024Sobrien BFD_ASSERT (splt != NULL && sdyn != NULL); 185959024Sobrien 186059024Sobrien dyncon = (Elf32_External_Dyn *) sdyn->contents; 186159024Sobrien dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->_raw_size); 186259024Sobrien for (; dyncon < dynconend; dyncon++) 186359024Sobrien { 186459024Sobrien Elf_Internal_Dyn dyn; 186559024Sobrien const char *name; 186659024Sobrien boolean size; 186759024Sobrien 186859024Sobrien bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn); 186959024Sobrien 187059024Sobrien switch (dyn.d_tag) 187159024Sobrien { 187259024Sobrien case DT_PLTGOT: name = ".plt"; size = false; break; 187359024Sobrien case DT_PLTRELSZ: name = ".rela.plt"; size = true; break; 187459024Sobrien case DT_JMPREL: name = ".rela.plt"; size = false; break; 187559024Sobrien default: name = NULL; size = false; break; 187659024Sobrien } 187759024Sobrien 187859024Sobrien if (name != NULL) 187959024Sobrien { 188059024Sobrien asection *s; 188159024Sobrien 188259024Sobrien s = bfd_get_section_by_name (output_bfd, name); 188359024Sobrien if (s == NULL) 188459024Sobrien dyn.d_un.d_val = 0; 188559024Sobrien else 188659024Sobrien { 188759024Sobrien if (! size) 188859024Sobrien dyn.d_un.d_ptr = s->vma; 188959024Sobrien else 189059024Sobrien { 189159024Sobrien if (s->_cooked_size != 0) 189259024Sobrien dyn.d_un.d_val = s->_cooked_size; 189359024Sobrien else 189459024Sobrien dyn.d_un.d_val = s->_raw_size; 189559024Sobrien } 189659024Sobrien } 189759024Sobrien bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); 189859024Sobrien } 189959024Sobrien } 190059024Sobrien 190159024Sobrien /* Clear the first four entries in the procedure linkage table, 190259024Sobrien and put a nop in the last four bytes. */ 190359024Sobrien if (splt->_raw_size > 0) 190459024Sobrien { 190559024Sobrien memset (splt->contents, 0, 4 * PLT_ENTRY_SIZE); 190659024Sobrien bfd_put_32 (output_bfd, SPARC_NOP, 190759024Sobrien splt->contents + splt->_raw_size - 4); 190859024Sobrien } 190959024Sobrien 191059024Sobrien elf_section_data (splt->output_section)->this_hdr.sh_entsize = 191159024Sobrien PLT_ENTRY_SIZE; 191259024Sobrien } 191359024Sobrien 191459024Sobrien /* Set the first entry in the global offset table to the address of 191559024Sobrien the dynamic section. */ 191659024Sobrien sgot = bfd_get_section_by_name (dynobj, ".got"); 191759024Sobrien BFD_ASSERT (sgot != NULL); 191859024Sobrien if (sgot->_raw_size > 0) 191959024Sobrien { 192059024Sobrien if (sdyn == NULL) 192159024Sobrien bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents); 192259024Sobrien else 192359024Sobrien bfd_put_32 (output_bfd, 192459024Sobrien sdyn->output_section->vma + sdyn->output_offset, 192559024Sobrien sgot->contents); 192659024Sobrien } 192759024Sobrien 192859024Sobrien elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4; 192959024Sobrien 193059024Sobrien return true; 193159024Sobrien} 193259024Sobrien 193359024Sobrien/* Functions for dealing with the e_flags field. 193459024Sobrien 193559024Sobrien We don't define set_private_flags or copy_private_bfd_data because 193659024Sobrien the only currently defined values are based on the bfd mach number, 193759024Sobrien so we use the latter instead and defer setting e_flags until the 193859024Sobrien file is written out. */ 193959024Sobrien 194059024Sobrien/* Merge backend specific data from an object file to the output 194159024Sobrien object file when linking. */ 194259024Sobrien 194359024Sobrienstatic boolean 194459024Sobrienelf32_sparc_merge_private_bfd_data (ibfd, obfd) 194559024Sobrien bfd *ibfd; 194659024Sobrien bfd *obfd; 194759024Sobrien{ 194859024Sobrien boolean error; 194960484Sobrien /* FIXME: This should not be static. */ 195060484Sobrien static unsigned long previous_ibfd_e_flags = (unsigned long) -1; 195159024Sobrien 195259024Sobrien if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour 195359024Sobrien || bfd_get_flavour (obfd) != bfd_target_elf_flavour) 195459024Sobrien return true; 195559024Sobrien 195659024Sobrien error = false; 195759024Sobrien 195859024Sobrien if (bfd_get_mach (ibfd) >= bfd_mach_sparc_v9) 195959024Sobrien { 196059024Sobrien error = true; 196159024Sobrien (*_bfd_error_handler) 196260484Sobrien (_("%s: compiled for a 64 bit system and target is 32 bit"), 196359024Sobrien bfd_get_filename (ibfd)); 196459024Sobrien } 196560484Sobrien else if ((ibfd->flags & DYNAMIC) == 0) 196660484Sobrien { 196760484Sobrien if (bfd_get_mach (obfd) < bfd_get_mach (ibfd)) 196860484Sobrien bfd_set_arch_mach (obfd, bfd_arch_sparc, bfd_get_mach (ibfd)); 196960484Sobrien } 197059024Sobrien 197160484Sobrien if (((elf_elfheader (ibfd)->e_flags & EF_SPARC_LEDATA) 197260484Sobrien != previous_ibfd_e_flags) 197360484Sobrien && previous_ibfd_e_flags != (unsigned long) -1) 197460484Sobrien { 197560484Sobrien (*_bfd_error_handler) 197660484Sobrien (_("%s: linking little endian files with big endian files"), 197760484Sobrien bfd_get_filename (ibfd)); 197860484Sobrien error = true; 197960484Sobrien } 198060484Sobrien previous_ibfd_e_flags = elf_elfheader (ibfd)->e_flags & EF_SPARC_LEDATA; 198160484Sobrien 198259024Sobrien if (error) 198359024Sobrien { 198459024Sobrien bfd_set_error (bfd_error_bad_value); 198559024Sobrien return false; 198659024Sobrien } 198759024Sobrien 198859024Sobrien return true; 198959024Sobrien} 199059024Sobrien 199159024Sobrien/* Set the right machine number. */ 199259024Sobrien 199359024Sobrienstatic boolean 199459024Sobrienelf32_sparc_object_p (abfd) 199559024Sobrien bfd *abfd; 199659024Sobrien{ 199759024Sobrien if (elf_elfheader (abfd)->e_machine == EM_SPARC32PLUS) 199859024Sobrien { 199977298Sobrien if (elf_elfheader (abfd)->e_flags & EF_SPARC_SUN_US3) 200059024Sobrien return bfd_default_set_arch_mach (abfd, bfd_arch_sparc, 200177298Sobrien bfd_mach_sparc_v8plusb); 200277298Sobrien else if (elf_elfheader (abfd)->e_flags & EF_SPARC_SUN_US1) 200377298Sobrien return bfd_default_set_arch_mach (abfd, bfd_arch_sparc, 200459024Sobrien bfd_mach_sparc_v8plusa); 200559024Sobrien else if (elf_elfheader (abfd)->e_flags & EF_SPARC_32PLUS) 200659024Sobrien return bfd_default_set_arch_mach (abfd, bfd_arch_sparc, 200759024Sobrien bfd_mach_sparc_v8plus); 200859024Sobrien else 200959024Sobrien return false; 201059024Sobrien } 201160484Sobrien else if (elf_elfheader (abfd)->e_flags & EF_SPARC_LEDATA) 201260484Sobrien return bfd_default_set_arch_mach (abfd, bfd_arch_sparc, 201360484Sobrien bfd_mach_sparc_sparclite_le); 201459024Sobrien else 201559024Sobrien return bfd_default_set_arch_mach (abfd, bfd_arch_sparc, bfd_mach_sparc); 201659024Sobrien} 201759024Sobrien 201859024Sobrien/* The final processing done just before writing out the object file. 201959024Sobrien We need to set the e_machine field appropriately. */ 202059024Sobrien 202159024Sobrienstatic void 202259024Sobrienelf32_sparc_final_write_processing (abfd, linker) 202359024Sobrien bfd *abfd; 202460484Sobrien boolean linker ATTRIBUTE_UNUSED; 202559024Sobrien{ 202659024Sobrien switch (bfd_get_mach (abfd)) 202759024Sobrien { 202859024Sobrien case bfd_mach_sparc : 202959024Sobrien break; /* nothing to do */ 203059024Sobrien case bfd_mach_sparc_v8plus : 203159024Sobrien elf_elfheader (abfd)->e_machine = EM_SPARC32PLUS; 203259024Sobrien elf_elfheader (abfd)->e_flags &=~ EF_SPARC_32PLUS_MASK; 203359024Sobrien elf_elfheader (abfd)->e_flags |= EF_SPARC_32PLUS; 203459024Sobrien break; 203559024Sobrien case bfd_mach_sparc_v8plusa : 203659024Sobrien elf_elfheader (abfd)->e_machine = EM_SPARC32PLUS; 203759024Sobrien elf_elfheader (abfd)->e_flags &=~ EF_SPARC_32PLUS_MASK; 203859024Sobrien elf_elfheader (abfd)->e_flags |= EF_SPARC_32PLUS | EF_SPARC_SUN_US1; 203959024Sobrien break; 204077298Sobrien case bfd_mach_sparc_v8plusb : 204177298Sobrien elf_elfheader (abfd)->e_machine = EM_SPARC32PLUS; 204277298Sobrien elf_elfheader (abfd)->e_flags &=~ EF_SPARC_32PLUS_MASK; 204377298Sobrien elf_elfheader (abfd)->e_flags |= EF_SPARC_32PLUS | EF_SPARC_SUN_US1 204477298Sobrien | EF_SPARC_SUN_US3; 204577298Sobrien break; 204660484Sobrien case bfd_mach_sparc_sparclite_le : 204760484Sobrien elf_elfheader (abfd)->e_machine = EM_SPARC; 204860484Sobrien elf_elfheader (abfd)->e_flags |= EF_SPARC_LEDATA; 204960484Sobrien break; 205059024Sobrien default : 205159024Sobrien abort (); 205260484Sobrien break; 205359024Sobrien } 205459024Sobrien} 205559024Sobrien 205659024Sobrien#define TARGET_BIG_SYM bfd_elf32_sparc_vec 205759024Sobrien#define TARGET_BIG_NAME "elf32-sparc" 205859024Sobrien#define ELF_ARCH bfd_arch_sparc 205959024Sobrien#define ELF_MACHINE_CODE EM_SPARC 206059024Sobrien#define ELF_MACHINE_ALT1 EM_SPARC32PLUS 206159024Sobrien#define ELF_MAXPAGESIZE 0x10000 206259024Sobrien 206359024Sobrien#define bfd_elf32_bfd_reloc_type_lookup elf32_sparc_reloc_type_lookup 206477298Sobrien#define bfd_elf32_bfd_relax_section elf32_sparc_relax_section 206559024Sobrien#define elf_info_to_howto elf32_sparc_info_to_howto 206659024Sobrien#define elf_backend_create_dynamic_sections \ 206759024Sobrien _bfd_elf_create_dynamic_sections 206859024Sobrien#define elf_backend_check_relocs elf32_sparc_check_relocs 206959024Sobrien#define elf_backend_adjust_dynamic_symbol \ 207059024Sobrien elf32_sparc_adjust_dynamic_symbol 207159024Sobrien#define elf_backend_size_dynamic_sections \ 207259024Sobrien elf32_sparc_size_dynamic_sections 207359024Sobrien#define elf_backend_relocate_section elf32_sparc_relocate_section 207459024Sobrien#define elf_backend_finish_dynamic_symbol \ 207559024Sobrien elf32_sparc_finish_dynamic_symbol 207659024Sobrien#define elf_backend_finish_dynamic_sections \ 207759024Sobrien elf32_sparc_finish_dynamic_sections 207859024Sobrien#define bfd_elf32_bfd_merge_private_bfd_data \ 207959024Sobrien elf32_sparc_merge_private_bfd_data 208059024Sobrien#define elf_backend_object_p elf32_sparc_object_p 208159024Sobrien#define elf_backend_final_write_processing \ 208259024Sobrien elf32_sparc_final_write_processing 208360484Sobrien#define elf_backend_gc_mark_hook elf32_sparc_gc_mark_hook 208460484Sobrien#define elf_backend_gc_sweep_hook elf32_sparc_gc_sweep_hook 208560484Sobrien 208660484Sobrien#define elf_backend_can_gc_sections 1 208759024Sobrien#define elf_backend_want_got_plt 0 208859024Sobrien#define elf_backend_plt_readonly 0 208959024Sobrien#define elf_backend_want_plt_sym 1 209060484Sobrien#define elf_backend_got_header_size 4 209160484Sobrien#define elf_backend_plt_header_size (4*PLT_ENTRY_SIZE) 209259024Sobrien 209359024Sobrien#include "elf32-target.h" 2094