elf64-ppc.c revision 209867
189857Sobrien/* PowerPC64-specific support for 64-bit ELF. 2130561Sobrien Copyright 1999, 2000, 2001, 2002, 2003, 2004 3130561Sobrien Free Software Foundation, Inc. 489857Sobrien Written by Linus Nordberg, Swox AB <info@swox.com>, 589857Sobrien based on elf32-ppc.c by Ian Lance Taylor. 6130561Sobrien Largely rewritten by Alan Modra <amodra@bigpond.net.au> 789857Sobrien 8130561Sobrien This file is part of BFD, the Binary File Descriptor library. 989857Sobrien 10130561Sobrien This program is free software; you can redistribute it and/or modify 11130561Sobrien it under the terms of the GNU General Public License as published by 12130561Sobrien the Free Software Foundation; either version 2 of the License, or 13130561Sobrien (at your option) any later version. 1489857Sobrien 15130561Sobrien This program is distributed in the hope that it will be useful, 16130561Sobrien but WITHOUT ANY WARRANTY; without even the implied warranty of 17130561Sobrien MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18130561Sobrien GNU General Public License for more details. 1989857Sobrien 20130561Sobrien You should have received a copy of the GNU General Public License along 21130561Sobrien with this program; if not, write to the Free Software Foundation, Inc., 22130561Sobrien 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 2389857Sobrien 24130561Sobrien/* The 64-bit PowerPC ELF ABI may be found at 25130561Sobrien http://www.linuxbase.org/spec/ELF/ppc64/PPC-elf64abi.txt, and 26130561Sobrien http://www.linuxbase.org/spec/ELF/ppc64/spec/book1.html */ 2789857Sobrien 2889857Sobrien#include "bfd.h" 2989857Sobrien#include "sysdep.h" 3089857Sobrien#include "bfdlink.h" 3189857Sobrien#include "libbfd.h" 3289857Sobrien#include "elf-bfd.h" 33130561Sobrien#include "elf/ppc64.h" 3489857Sobrien#include "elf64-ppc.h" 3589857Sobrien 3699461Sobrienstatic bfd_reloc_status_type ppc64_elf_ha_reloc 37130561Sobrien (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); 3899461Sobrienstatic bfd_reloc_status_type ppc64_elf_brtaken_reloc 39130561Sobrien (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); 4099461Sobrienstatic bfd_reloc_status_type ppc64_elf_sectoff_reloc 41130561Sobrien (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); 4299461Sobrienstatic bfd_reloc_status_type ppc64_elf_sectoff_ha_reloc 43130561Sobrien (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); 4499461Sobrienstatic bfd_reloc_status_type ppc64_elf_toc_reloc 45130561Sobrien (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); 4699461Sobrienstatic bfd_reloc_status_type ppc64_elf_toc_ha_reloc 47130561Sobrien (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); 4899461Sobrienstatic bfd_reloc_status_type ppc64_elf_toc64_reloc 49130561Sobrien (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); 5099461Sobrienstatic bfd_reloc_status_type ppc64_elf_unhandled_reloc 51130561Sobrien (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); 5289857Sobrien 5389857Sobrien 54130561Sobrien#define TARGET_LITTLE_SYM bfd_elf64_powerpcle_vec 55130561Sobrien#define TARGET_LITTLE_NAME "elf64-powerpcle" 56130561Sobrien#define TARGET_BIG_SYM bfd_elf64_powerpc_vec 57130561Sobrien#define TARGET_BIG_NAME "elf64-powerpc" 58130561Sobrien#define ELF_ARCH bfd_arch_powerpc 59130561Sobrien#define ELF_MACHINE_CODE EM_PPC64 60130561Sobrien#define ELF_MAXPAGESIZE 0x10000 61130561Sobrien#define elf_info_to_howto ppc64_elf_info_to_howto 62130561Sobrien 63130561Sobrien#define elf_backend_want_got_sym 0 64130561Sobrien#define elf_backend_want_plt_sym 0 65130561Sobrien#define elf_backend_plt_alignment 3 66130561Sobrien#define elf_backend_plt_not_loaded 1 67130561Sobrien#define elf_backend_got_symbol_offset 0 68130561Sobrien#define elf_backend_got_header_size 8 69130561Sobrien#define elf_backend_can_gc_sections 1 70130561Sobrien#define elf_backend_can_refcount 1 71130561Sobrien#define elf_backend_rela_normal 1 72130561Sobrien 73130561Sobrien#define bfd_elf64_mkobject ppc64_elf_mkobject 74130561Sobrien#define bfd_elf64_bfd_reloc_type_lookup ppc64_elf_reloc_type_lookup 75130561Sobrien#define bfd_elf64_bfd_merge_private_bfd_data ppc64_elf_merge_private_bfd_data 76130561Sobrien#define bfd_elf64_new_section_hook ppc64_elf_new_section_hook 77130561Sobrien#define bfd_elf64_bfd_link_hash_table_create ppc64_elf_link_hash_table_create 78130561Sobrien#define bfd_elf64_bfd_link_hash_table_free ppc64_elf_link_hash_table_free 79130561Sobrien 80130561Sobrien#define elf_backend_object_p ppc64_elf_object_p 81130561Sobrien#define elf_backend_grok_prstatus ppc64_elf_grok_prstatus 82130561Sobrien#define elf_backend_grok_psinfo ppc64_elf_grok_psinfo 83130561Sobrien#define elf_backend_create_dynamic_sections ppc64_elf_create_dynamic_sections 84130561Sobrien#define elf_backend_copy_indirect_symbol ppc64_elf_copy_indirect_symbol 85130561Sobrien#define elf_backend_add_symbol_hook ppc64_elf_add_symbol_hook 86130561Sobrien#define elf_backend_check_relocs ppc64_elf_check_relocs 87130561Sobrien#define elf_backend_gc_mark_hook ppc64_elf_gc_mark_hook 88130561Sobrien#define elf_backend_gc_sweep_hook ppc64_elf_gc_sweep_hook 89130561Sobrien#define elf_backend_adjust_dynamic_symbol ppc64_elf_adjust_dynamic_symbol 90130561Sobrien#define elf_backend_hide_symbol ppc64_elf_hide_symbol 91130561Sobrien#define elf_backend_always_size_sections ppc64_elf_func_desc_adjust 92130561Sobrien#define elf_backend_size_dynamic_sections ppc64_elf_size_dynamic_sections 93130561Sobrien#define elf_backend_relocate_section ppc64_elf_relocate_section 94130561Sobrien#define elf_backend_finish_dynamic_symbol ppc64_elf_finish_dynamic_symbol 95130561Sobrien#define elf_backend_reloc_type_class ppc64_elf_reloc_type_class 96130561Sobrien#define elf_backend_finish_dynamic_sections ppc64_elf_finish_dynamic_sections 97130561Sobrien#define elf_backend_link_output_symbol_hook ppc64_elf_output_symbol_hook 98130561Sobrien#define elf_backend_special_sections ppc64_elf_special_sections 99130561Sobrien 10089857Sobrien/* The name of the dynamic interpreter. This is put in the .interp 10189857Sobrien section. */ 10289857Sobrien#define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1" 10389857Sobrien 10489857Sobrien/* The size in bytes of an entry in the procedure linkage table. */ 10589857Sobrien#define PLT_ENTRY_SIZE 24 10689857Sobrien 10789857Sobrien/* The initial size of the plt reserved for the dynamic linker. */ 10889857Sobrien#define PLT_INITIAL_ENTRY_SIZE PLT_ENTRY_SIZE 10989857Sobrien 11089857Sobrien/* TOC base pointers offset from start of TOC. */ 111130561Sobrien#define TOC_BASE_OFF 0x8000 11289857Sobrien 113130561Sobrien/* Offset of tp and dtp pointers from start of TLS block. */ 114130561Sobrien#define TP_OFFSET 0x7000 115130561Sobrien#define DTP_OFFSET 0x8000 116130561Sobrien 117130561Sobrien/* .plt call stub instructions. The normal stub is like this, but 118130561Sobrien sometimes the .plt entry crosses a 64k boundary and we need to 119130561Sobrien insert an addis to adjust r12. */ 120130561Sobrien#define PLT_CALL_STUB_SIZE (7*4) 12189857Sobrien#define ADDIS_R12_R2 0x3d820000 /* addis %r12,%r2,xxx@ha */ 12289857Sobrien#define STD_R2_40R1 0xf8410028 /* std %r2,40(%r1) */ 12389857Sobrien#define LD_R11_0R12 0xe96c0000 /* ld %r11,xxx+0@l(%r12) */ 12489857Sobrien#define LD_R2_0R12 0xe84c0000 /* ld %r2,xxx+8@l(%r12) */ 12589857Sobrien#define MTCTR_R11 0x7d6903a6 /* mtctr %r11 */ 12689857Sobrien /* ld %r11,xxx+16@l(%r12) */ 12789857Sobrien#define BCTR 0x4e800420 /* bctr */ 12889857Sobrien 12989857Sobrien 130130561Sobrien#define ADDIS_R2_R2 0x3c420000 /* addis %r2,%r2,off@ha */ 131130561Sobrien#define ADDI_R2_R2 0x38420000 /* addi %r2,%r2,off@l */ 13289857Sobrien 133130561Sobrien#define LD_R2_40R1 0xe8410028 /* ld %r2,40(%r1) */ 13489857Sobrien 135130561Sobrien/* glink call stub instructions. We enter with the index in R0, and the 136130561Sobrien address of glink entry in CTR. From that, we can calculate PLT0. */ 137130561Sobrien#define GLINK_CALL_STUB_SIZE (16*4) 138130561Sobrien#define MFCTR_R12 0x7d8902a6 /* mfctr %r12 */ 139130561Sobrien#define SLDI_R11_R0_3 0x780b1f24 /* sldi %r11,%r0,3 */ 140130561Sobrien#define ADDIC_R2_R0_32K 0x34408000 /* addic. %r2,%r0,-32768 */ 141130561Sobrien#define SUB_R12_R12_R11 0x7d8b6050 /* sub %r12,%r12,%r11 */ 142130561Sobrien#define SRADI_R2_R2_63 0x7c42fe76 /* sradi %r2,%r2,63 */ 143130561Sobrien#define SLDI_R11_R0_2 0x780b1764 /* sldi %r11,%r0,2 */ 144130561Sobrien#define AND_R2_R2_R11 0x7c425838 /* and %r2,%r2,%r11 */ 145130561Sobrien /* sub %r12,%r12,%r11 */ 146130561Sobrien#define ADD_R12_R12_R2 0x7d8c1214 /* add %r12,%r12,%r2 */ 147130561Sobrien#define ADDIS_R12_R12 0x3d8c0000 /* addis %r12,%r12,xxx@ha */ 148130561Sobrien /* ld %r11,xxx@l(%r12) */ 149130561Sobrien#define ADDI_R12_R12 0x398c0000 /* addi %r12,%r12,xxx@l */ 150130561Sobrien /* ld %r2,8(%r12) */ 151130561Sobrien /* mtctr %r11 */ 152130561Sobrien /* ld %r11,16(%r12) */ 153130561Sobrien /* bctr */ 15489857Sobrien 15589857Sobrien/* Pad with this. */ 15689857Sobrien#define NOP 0x60000000 15789857Sobrien 15899461Sobrien/* Some other nops. */ 15999461Sobrien#define CROR_151515 0x4def7b82 16099461Sobrien#define CROR_313131 0x4ffffb82 16199461Sobrien 162104834Sobrien/* .glink entries for the first 32k functions are two instructions. */ 16389857Sobrien#define LI_R0_0 0x38000000 /* li %r0,0 */ 16489857Sobrien#define B_DOT 0x48000000 /* b . */ 16589857Sobrien 16689857Sobrien/* After that, we need two instructions to load the index, followed by 16789857Sobrien a branch. */ 16889857Sobrien#define LIS_R0_0 0x3c000000 /* lis %r0,0 */ 16989857Sobrien#define ORI_R0_R0_0 0x60000000 /* ori %r0,%r0,0 */ 17089857Sobrien 17192828Sobrien/* Instructions to save and restore floating point regs. */ 17292828Sobrien#define STFD_FR0_0R1 0xd8010000 /* stfd %fr0,0(%r1) */ 17392828Sobrien#define LFD_FR0_0R1 0xc8010000 /* lfd %fr0,0(%r1) */ 17492828Sobrien#define BLR 0x4e800020 /* blr */ 17592828Sobrien 17689857Sobrien/* Since .opd is an array of descriptors and each entry will end up 17789857Sobrien with identical R_PPC64_RELATIVE relocs, there is really no need to 17889857Sobrien propagate .opd relocs; The dynamic linker should be taught to 179104834Sobrien relocate .opd without reloc entries. */ 18089857Sobrien#ifndef NO_OPD_RELOCS 18189857Sobrien#define NO_OPD_RELOCS 0 18289857Sobrien#endif 18389857Sobrien 184104834Sobrien#define ONES(n) (((bfd_vma) 1 << ((n) - 1) << 1) - 1) 185130561Sobrien 18689857Sobrien/* Relocation HOWTO's. */ 187130561Sobrienstatic reloc_howto_type *ppc64_elf_howto_table[(int) R_PPC64_max]; 18889857Sobrien 18989857Sobrienstatic reloc_howto_type ppc64_elf_howto_raw[] = { 19089857Sobrien /* This reloc does nothing. */ 19189857Sobrien HOWTO (R_PPC64_NONE, /* type */ 19289857Sobrien 0, /* rightshift */ 193130561Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 194130561Sobrien 32, /* bitsize */ 195130561Sobrien FALSE, /* pc_relative */ 19689857Sobrien 0, /* bitpos */ 197104834Sobrien complain_overflow_dont, /* complain_on_overflow */ 19889857Sobrien bfd_elf_generic_reloc, /* special_function */ 19989857Sobrien "R_PPC64_NONE", /* name */ 200130561Sobrien FALSE, /* partial_inplace */ 20189857Sobrien 0, /* src_mask */ 20289857Sobrien 0, /* dst_mask */ 203130561Sobrien FALSE), /* pcrel_offset */ 20489857Sobrien 20589857Sobrien /* A standard 32 bit relocation. */ 20689857Sobrien HOWTO (R_PPC64_ADDR32, /* type */ 20789857Sobrien 0, /* rightshift */ 20889857Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 20989857Sobrien 32, /* bitsize */ 210130561Sobrien FALSE, /* pc_relative */ 21189857Sobrien 0, /* bitpos */ 21289857Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 21389857Sobrien bfd_elf_generic_reloc, /* special_function */ 21489857Sobrien "R_PPC64_ADDR32", /* name */ 215130561Sobrien FALSE, /* partial_inplace */ 21689857Sobrien 0, /* src_mask */ 21789857Sobrien 0xffffffff, /* dst_mask */ 218130561Sobrien FALSE), /* pcrel_offset */ 21989857Sobrien 22089857Sobrien /* An absolute 26 bit branch; the lower two bits must be zero. 22189857Sobrien FIXME: we don't check that, we just clear them. */ 22289857Sobrien HOWTO (R_PPC64_ADDR24, /* type */ 22389857Sobrien 0, /* rightshift */ 22489857Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 22589857Sobrien 26, /* bitsize */ 226130561Sobrien FALSE, /* pc_relative */ 22789857Sobrien 0, /* bitpos */ 22889857Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 22989857Sobrien bfd_elf_generic_reloc, /* special_function */ 23089857Sobrien "R_PPC64_ADDR24", /* name */ 231130561Sobrien FALSE, /* partial_inplace */ 23289857Sobrien 0, /* src_mask */ 233104834Sobrien 0x03fffffc, /* dst_mask */ 234130561Sobrien FALSE), /* pcrel_offset */ 23589857Sobrien 23689857Sobrien /* A standard 16 bit relocation. */ 23789857Sobrien HOWTO (R_PPC64_ADDR16, /* type */ 23889857Sobrien 0, /* rightshift */ 23989857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 24089857Sobrien 16, /* bitsize */ 241130561Sobrien FALSE, /* pc_relative */ 24289857Sobrien 0, /* bitpos */ 24389857Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 24489857Sobrien bfd_elf_generic_reloc, /* special_function */ 24589857Sobrien "R_PPC64_ADDR16", /* name */ 246130561Sobrien FALSE, /* partial_inplace */ 24789857Sobrien 0, /* src_mask */ 24889857Sobrien 0xffff, /* dst_mask */ 249130561Sobrien FALSE), /* pcrel_offset */ 25089857Sobrien 25189857Sobrien /* A 16 bit relocation without overflow. */ 25289857Sobrien HOWTO (R_PPC64_ADDR16_LO, /* type */ 25389857Sobrien 0, /* rightshift */ 25489857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 25589857Sobrien 16, /* bitsize */ 256130561Sobrien FALSE, /* pc_relative */ 25789857Sobrien 0, /* bitpos */ 25889857Sobrien complain_overflow_dont,/* complain_on_overflow */ 25989857Sobrien bfd_elf_generic_reloc, /* special_function */ 26089857Sobrien "R_PPC64_ADDR16_LO", /* name */ 261130561Sobrien FALSE, /* partial_inplace */ 26289857Sobrien 0, /* src_mask */ 26389857Sobrien 0xffff, /* dst_mask */ 264130561Sobrien FALSE), /* pcrel_offset */ 26589857Sobrien 26689857Sobrien /* Bits 16-31 of an address. */ 26789857Sobrien HOWTO (R_PPC64_ADDR16_HI, /* type */ 26889857Sobrien 16, /* rightshift */ 26989857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 27089857Sobrien 16, /* bitsize */ 271130561Sobrien FALSE, /* pc_relative */ 27289857Sobrien 0, /* bitpos */ 27389857Sobrien complain_overflow_dont, /* complain_on_overflow */ 27489857Sobrien bfd_elf_generic_reloc, /* special_function */ 27589857Sobrien "R_PPC64_ADDR16_HI", /* name */ 276130561Sobrien FALSE, /* partial_inplace */ 27789857Sobrien 0, /* src_mask */ 27889857Sobrien 0xffff, /* dst_mask */ 279130561Sobrien FALSE), /* pcrel_offset */ 28089857Sobrien 28189857Sobrien /* Bits 16-31 of an address, plus 1 if the contents of the low 16 28289857Sobrien bits, treated as a signed number, is negative. */ 28389857Sobrien HOWTO (R_PPC64_ADDR16_HA, /* type */ 28489857Sobrien 16, /* rightshift */ 28589857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 28689857Sobrien 16, /* bitsize */ 287130561Sobrien FALSE, /* pc_relative */ 28889857Sobrien 0, /* bitpos */ 28989857Sobrien complain_overflow_dont, /* complain_on_overflow */ 29099461Sobrien ppc64_elf_ha_reloc, /* special_function */ 29189857Sobrien "R_PPC64_ADDR16_HA", /* name */ 292130561Sobrien FALSE, /* partial_inplace */ 29389857Sobrien 0, /* src_mask */ 29489857Sobrien 0xffff, /* dst_mask */ 295130561Sobrien FALSE), /* pcrel_offset */ 29689857Sobrien 29789857Sobrien /* An absolute 16 bit branch; the lower two bits must be zero. 29889857Sobrien FIXME: we don't check that, we just clear them. */ 29989857Sobrien HOWTO (R_PPC64_ADDR14, /* type */ 30089857Sobrien 0, /* rightshift */ 30189857Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 30289857Sobrien 16, /* bitsize */ 303130561Sobrien FALSE, /* pc_relative */ 30489857Sobrien 0, /* bitpos */ 30589857Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 30689857Sobrien bfd_elf_generic_reloc, /* special_function */ 30789857Sobrien "R_PPC64_ADDR14", /* name */ 308130561Sobrien FALSE, /* partial_inplace */ 30989857Sobrien 0, /* src_mask */ 310104834Sobrien 0x0000fffc, /* dst_mask */ 311130561Sobrien FALSE), /* pcrel_offset */ 31289857Sobrien 31389857Sobrien /* An absolute 16 bit branch, for which bit 10 should be set to 31489857Sobrien indicate that the branch is expected to be taken. The lower two 31589857Sobrien bits must be zero. */ 31689857Sobrien HOWTO (R_PPC64_ADDR14_BRTAKEN, /* type */ 31789857Sobrien 0, /* rightshift */ 31889857Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 31989857Sobrien 16, /* bitsize */ 320130561Sobrien FALSE, /* pc_relative */ 32189857Sobrien 0, /* bitpos */ 32289857Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 32399461Sobrien ppc64_elf_brtaken_reloc, /* special_function */ 32489857Sobrien "R_PPC64_ADDR14_BRTAKEN",/* name */ 325130561Sobrien FALSE, /* partial_inplace */ 32689857Sobrien 0, /* src_mask */ 327104834Sobrien 0x0000fffc, /* dst_mask */ 328130561Sobrien FALSE), /* pcrel_offset */ 32989857Sobrien 33089857Sobrien /* An absolute 16 bit branch, for which bit 10 should be set to 33189857Sobrien indicate that the branch is not expected to be taken. The lower 33289857Sobrien two bits must be zero. */ 33389857Sobrien HOWTO (R_PPC64_ADDR14_BRNTAKEN, /* type */ 33489857Sobrien 0, /* rightshift */ 33589857Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 33689857Sobrien 16, /* bitsize */ 337130561Sobrien FALSE, /* pc_relative */ 33889857Sobrien 0, /* bitpos */ 33989857Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 34099461Sobrien ppc64_elf_brtaken_reloc, /* special_function */ 34189857Sobrien "R_PPC64_ADDR14_BRNTAKEN",/* name */ 342130561Sobrien FALSE, /* partial_inplace */ 34389857Sobrien 0, /* src_mask */ 344104834Sobrien 0x0000fffc, /* dst_mask */ 345130561Sobrien FALSE), /* pcrel_offset */ 34689857Sobrien 34789857Sobrien /* A relative 26 bit branch; the lower two bits must be zero. */ 34889857Sobrien HOWTO (R_PPC64_REL24, /* type */ 34989857Sobrien 0, /* rightshift */ 35089857Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 35189857Sobrien 26, /* bitsize */ 352130561Sobrien TRUE, /* pc_relative */ 35389857Sobrien 0, /* bitpos */ 35489857Sobrien complain_overflow_signed, /* complain_on_overflow */ 35589857Sobrien bfd_elf_generic_reloc, /* special_function */ 35689857Sobrien "R_PPC64_REL24", /* name */ 357130561Sobrien FALSE, /* partial_inplace */ 35889857Sobrien 0, /* src_mask */ 359104834Sobrien 0x03fffffc, /* dst_mask */ 360130561Sobrien TRUE), /* pcrel_offset */ 36189857Sobrien 36289857Sobrien /* A relative 16 bit branch; the lower two bits must be zero. */ 36389857Sobrien HOWTO (R_PPC64_REL14, /* type */ 36489857Sobrien 0, /* rightshift */ 36589857Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 36689857Sobrien 16, /* bitsize */ 367130561Sobrien TRUE, /* pc_relative */ 36889857Sobrien 0, /* bitpos */ 36989857Sobrien complain_overflow_signed, /* complain_on_overflow */ 37089857Sobrien bfd_elf_generic_reloc, /* special_function */ 37189857Sobrien "R_PPC64_REL14", /* name */ 372130561Sobrien FALSE, /* partial_inplace */ 37389857Sobrien 0, /* src_mask */ 374104834Sobrien 0x0000fffc, /* dst_mask */ 375130561Sobrien TRUE), /* pcrel_offset */ 37689857Sobrien 37789857Sobrien /* A relative 16 bit branch. Bit 10 should be set to indicate that 37889857Sobrien the branch is expected to be taken. The lower two bits must be 37989857Sobrien zero. */ 38089857Sobrien HOWTO (R_PPC64_REL14_BRTAKEN, /* type */ 38189857Sobrien 0, /* rightshift */ 38289857Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 38389857Sobrien 16, /* bitsize */ 384130561Sobrien TRUE, /* pc_relative */ 38589857Sobrien 0, /* bitpos */ 38689857Sobrien complain_overflow_signed, /* complain_on_overflow */ 38799461Sobrien ppc64_elf_brtaken_reloc, /* special_function */ 38889857Sobrien "R_PPC64_REL14_BRTAKEN", /* name */ 389130561Sobrien FALSE, /* partial_inplace */ 39089857Sobrien 0, /* src_mask */ 391104834Sobrien 0x0000fffc, /* dst_mask */ 392130561Sobrien TRUE), /* pcrel_offset */ 39389857Sobrien 39489857Sobrien /* A relative 16 bit branch. Bit 10 should be set to indicate that 39589857Sobrien the branch is not expected to be taken. The lower two bits must 39689857Sobrien be zero. */ 39789857Sobrien HOWTO (R_PPC64_REL14_BRNTAKEN, /* type */ 39889857Sobrien 0, /* rightshift */ 39989857Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 40089857Sobrien 16, /* bitsize */ 401130561Sobrien TRUE, /* pc_relative */ 40289857Sobrien 0, /* bitpos */ 40389857Sobrien complain_overflow_signed, /* complain_on_overflow */ 40499461Sobrien ppc64_elf_brtaken_reloc, /* special_function */ 40589857Sobrien "R_PPC64_REL14_BRNTAKEN",/* name */ 406130561Sobrien FALSE, /* partial_inplace */ 40789857Sobrien 0, /* src_mask */ 408104834Sobrien 0x0000fffc, /* dst_mask */ 409130561Sobrien TRUE), /* pcrel_offset */ 41089857Sobrien 41189857Sobrien /* Like R_PPC64_ADDR16, but referring to the GOT table entry for the 41289857Sobrien symbol. */ 41389857Sobrien HOWTO (R_PPC64_GOT16, /* type */ 41489857Sobrien 0, /* rightshift */ 41589857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 41689857Sobrien 16, /* bitsize */ 417130561Sobrien FALSE, /* pc_relative */ 41889857Sobrien 0, /* bitpos */ 41989857Sobrien complain_overflow_signed, /* complain_on_overflow */ 42099461Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 42189857Sobrien "R_PPC64_GOT16", /* name */ 422130561Sobrien FALSE, /* partial_inplace */ 42389857Sobrien 0, /* src_mask */ 42489857Sobrien 0xffff, /* dst_mask */ 425130561Sobrien FALSE), /* pcrel_offset */ 42689857Sobrien 42789857Sobrien /* Like R_PPC64_ADDR16_LO, but referring to the GOT table entry for 42889857Sobrien the symbol. */ 42989857Sobrien HOWTO (R_PPC64_GOT16_LO, /* type */ 43089857Sobrien 0, /* rightshift */ 43189857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 43289857Sobrien 16, /* bitsize */ 433130561Sobrien FALSE, /* pc_relative */ 43489857Sobrien 0, /* bitpos */ 43589857Sobrien complain_overflow_dont, /* complain_on_overflow */ 43699461Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 43789857Sobrien "R_PPC64_GOT16_LO", /* name */ 438130561Sobrien FALSE, /* partial_inplace */ 43989857Sobrien 0, /* src_mask */ 44089857Sobrien 0xffff, /* dst_mask */ 441130561Sobrien FALSE), /* pcrel_offset */ 44289857Sobrien 44389857Sobrien /* Like R_PPC64_ADDR16_HI, but referring to the GOT table entry for 44489857Sobrien the symbol. */ 44589857Sobrien HOWTO (R_PPC64_GOT16_HI, /* type */ 44689857Sobrien 16, /* rightshift */ 44789857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 44889857Sobrien 16, /* bitsize */ 449130561Sobrien FALSE, /* pc_relative */ 45089857Sobrien 0, /* bitpos */ 45189857Sobrien complain_overflow_dont,/* complain_on_overflow */ 45299461Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 45389857Sobrien "R_PPC64_GOT16_HI", /* name */ 454130561Sobrien FALSE, /* partial_inplace */ 45589857Sobrien 0, /* src_mask */ 45689857Sobrien 0xffff, /* dst_mask */ 457130561Sobrien FALSE), /* pcrel_offset */ 45889857Sobrien 45989857Sobrien /* Like R_PPC64_ADDR16_HA, but referring to the GOT table entry for 46089857Sobrien the symbol. */ 46189857Sobrien HOWTO (R_PPC64_GOT16_HA, /* type */ 46289857Sobrien 16, /* rightshift */ 46389857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 46489857Sobrien 16, /* bitsize */ 465130561Sobrien FALSE, /* pc_relative */ 46689857Sobrien 0, /* bitpos */ 46789857Sobrien complain_overflow_dont,/* complain_on_overflow */ 46899461Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 46989857Sobrien "R_PPC64_GOT16_HA", /* name */ 470130561Sobrien FALSE, /* partial_inplace */ 47189857Sobrien 0, /* src_mask */ 47289857Sobrien 0xffff, /* dst_mask */ 473130561Sobrien FALSE), /* pcrel_offset */ 47489857Sobrien 47589857Sobrien /* This is used only by the dynamic linker. The symbol should exist 47689857Sobrien both in the object being run and in some shared library. The 47789857Sobrien dynamic linker copies the data addressed by the symbol from the 47889857Sobrien shared library into the object, because the object being 47989857Sobrien run has to have the data at some particular address. */ 48089857Sobrien HOWTO (R_PPC64_COPY, /* type */ 48189857Sobrien 0, /* rightshift */ 482104834Sobrien 0, /* this one is variable size */ 483104834Sobrien 0, /* bitsize */ 484130561Sobrien FALSE, /* pc_relative */ 48589857Sobrien 0, /* bitpos */ 486104834Sobrien complain_overflow_dont, /* complain_on_overflow */ 487104834Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 48889857Sobrien "R_PPC64_COPY", /* name */ 489130561Sobrien FALSE, /* partial_inplace */ 49089857Sobrien 0, /* src_mask */ 49189857Sobrien 0, /* dst_mask */ 492130561Sobrien FALSE), /* pcrel_offset */ 49389857Sobrien 49489857Sobrien /* Like R_PPC64_ADDR64, but used when setting global offset table 49589857Sobrien entries. */ 49689857Sobrien HOWTO (R_PPC64_GLOB_DAT, /* type */ 49789857Sobrien 0, /* rightshift */ 49889857Sobrien 4, /* size (0=byte, 1=short, 2=long, 4=64 bits) */ 49989857Sobrien 64, /* bitsize */ 500130561Sobrien FALSE, /* pc_relative */ 50189857Sobrien 0, /* bitpos */ 50289857Sobrien complain_overflow_dont, /* complain_on_overflow */ 50399461Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 50489857Sobrien "R_PPC64_GLOB_DAT", /* name */ 505130561Sobrien FALSE, /* partial_inplace */ 50689857Sobrien 0, /* src_mask */ 507104834Sobrien ONES (64), /* dst_mask */ 508130561Sobrien FALSE), /* pcrel_offset */ 50989857Sobrien 51089857Sobrien /* Created by the link editor. Marks a procedure linkage table 51189857Sobrien entry for a symbol. */ 51289857Sobrien HOWTO (R_PPC64_JMP_SLOT, /* type */ 51389857Sobrien 0, /* rightshift */ 51489857Sobrien 0, /* size (0 = byte, 1 = short, 2 = long) */ 51589857Sobrien 0, /* bitsize */ 516130561Sobrien FALSE, /* pc_relative */ 51789857Sobrien 0, /* bitpos */ 51889857Sobrien complain_overflow_dont, /* complain_on_overflow */ 51999461Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 52089857Sobrien "R_PPC64_JMP_SLOT", /* name */ 521130561Sobrien FALSE, /* partial_inplace */ 52289857Sobrien 0, /* src_mask */ 52389857Sobrien 0, /* dst_mask */ 524130561Sobrien FALSE), /* pcrel_offset */ 52589857Sobrien 52689857Sobrien /* Used only by the dynamic linker. When the object is run, this 52789857Sobrien doubleword64 is set to the load address of the object, plus the 52889857Sobrien addend. */ 52989857Sobrien HOWTO (R_PPC64_RELATIVE, /* type */ 53089857Sobrien 0, /* rightshift */ 53189857Sobrien 4, /* size (0=byte, 1=short, 2=long, 4=64 bits) */ 53289857Sobrien 64, /* bitsize */ 533130561Sobrien FALSE, /* pc_relative */ 53489857Sobrien 0, /* bitpos */ 53589857Sobrien complain_overflow_dont, /* complain_on_overflow */ 53689857Sobrien bfd_elf_generic_reloc, /* special_function */ 53789857Sobrien "R_PPC64_RELATIVE", /* name */ 538130561Sobrien FALSE, /* partial_inplace */ 53989857Sobrien 0, /* src_mask */ 540104834Sobrien ONES (64), /* dst_mask */ 541130561Sobrien FALSE), /* pcrel_offset */ 54289857Sobrien 54389857Sobrien /* Like R_PPC64_ADDR32, but may be unaligned. */ 54489857Sobrien HOWTO (R_PPC64_UADDR32, /* type */ 54589857Sobrien 0, /* rightshift */ 54689857Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 54789857Sobrien 32, /* bitsize */ 548130561Sobrien FALSE, /* pc_relative */ 54989857Sobrien 0, /* bitpos */ 55089857Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 55189857Sobrien bfd_elf_generic_reloc, /* special_function */ 55289857Sobrien "R_PPC64_UADDR32", /* name */ 553130561Sobrien FALSE, /* partial_inplace */ 55489857Sobrien 0, /* src_mask */ 55589857Sobrien 0xffffffff, /* dst_mask */ 556130561Sobrien FALSE), /* pcrel_offset */ 55789857Sobrien 55889857Sobrien /* Like R_PPC64_ADDR16, but may be unaligned. */ 55989857Sobrien HOWTO (R_PPC64_UADDR16, /* type */ 56089857Sobrien 0, /* rightshift */ 56189857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 56289857Sobrien 16, /* bitsize */ 563130561Sobrien FALSE, /* pc_relative */ 56489857Sobrien 0, /* bitpos */ 56589857Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 56689857Sobrien bfd_elf_generic_reloc, /* special_function */ 56789857Sobrien "R_PPC64_UADDR16", /* name */ 568130561Sobrien FALSE, /* partial_inplace */ 56989857Sobrien 0, /* src_mask */ 57089857Sobrien 0xffff, /* dst_mask */ 571130561Sobrien FALSE), /* pcrel_offset */ 57289857Sobrien 57389857Sobrien /* 32-bit PC relative. */ 57489857Sobrien HOWTO (R_PPC64_REL32, /* type */ 57589857Sobrien 0, /* rightshift */ 57689857Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 57789857Sobrien 32, /* bitsize */ 578130561Sobrien TRUE, /* pc_relative */ 57989857Sobrien 0, /* bitpos */ 580104834Sobrien /* FIXME: Verify. Was complain_overflow_bitfield. */ 58189857Sobrien complain_overflow_signed, /* complain_on_overflow */ 58289857Sobrien bfd_elf_generic_reloc, /* special_function */ 58389857Sobrien "R_PPC64_REL32", /* name */ 584130561Sobrien FALSE, /* partial_inplace */ 58589857Sobrien 0, /* src_mask */ 58689857Sobrien 0xffffffff, /* dst_mask */ 587130561Sobrien TRUE), /* pcrel_offset */ 58889857Sobrien 58989857Sobrien /* 32-bit relocation to the symbol's procedure linkage table. */ 59089857Sobrien HOWTO (R_PPC64_PLT32, /* type */ 59189857Sobrien 0, /* rightshift */ 59289857Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 59389857Sobrien 32, /* bitsize */ 594130561Sobrien FALSE, /* pc_relative */ 59589857Sobrien 0, /* bitpos */ 59689857Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 59799461Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 59889857Sobrien "R_PPC64_PLT32", /* name */ 599130561Sobrien FALSE, /* partial_inplace */ 60089857Sobrien 0, /* src_mask */ 601104834Sobrien 0xffffffff, /* dst_mask */ 602130561Sobrien FALSE), /* pcrel_offset */ 60389857Sobrien 60489857Sobrien /* 32-bit PC relative relocation to the symbol's procedure linkage table. 60589857Sobrien FIXME: R_PPC64_PLTREL32 not supported. */ 60689857Sobrien HOWTO (R_PPC64_PLTREL32, /* type */ 60789857Sobrien 0, /* rightshift */ 60889857Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 60989857Sobrien 32, /* bitsize */ 610130561Sobrien TRUE, /* pc_relative */ 61189857Sobrien 0, /* bitpos */ 61289857Sobrien complain_overflow_signed, /* complain_on_overflow */ 61389857Sobrien bfd_elf_generic_reloc, /* special_function */ 61489857Sobrien "R_PPC64_PLTREL32", /* name */ 615130561Sobrien FALSE, /* partial_inplace */ 61689857Sobrien 0, /* src_mask */ 617104834Sobrien 0xffffffff, /* dst_mask */ 618130561Sobrien TRUE), /* pcrel_offset */ 61989857Sobrien 62089857Sobrien /* Like R_PPC64_ADDR16_LO, but referring to the PLT table entry for 62189857Sobrien the symbol. */ 62289857Sobrien HOWTO (R_PPC64_PLT16_LO, /* type */ 62389857Sobrien 0, /* rightshift */ 62489857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 62589857Sobrien 16, /* bitsize */ 626130561Sobrien FALSE, /* pc_relative */ 62789857Sobrien 0, /* bitpos */ 62889857Sobrien complain_overflow_dont, /* complain_on_overflow */ 62999461Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 63089857Sobrien "R_PPC64_PLT16_LO", /* name */ 631130561Sobrien FALSE, /* partial_inplace */ 63289857Sobrien 0, /* src_mask */ 63389857Sobrien 0xffff, /* dst_mask */ 634130561Sobrien FALSE), /* pcrel_offset */ 63589857Sobrien 63689857Sobrien /* Like R_PPC64_ADDR16_HI, but referring to the PLT table entry for 63789857Sobrien the symbol. */ 63889857Sobrien HOWTO (R_PPC64_PLT16_HI, /* type */ 63989857Sobrien 16, /* rightshift */ 64089857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 64189857Sobrien 16, /* bitsize */ 642130561Sobrien FALSE, /* pc_relative */ 64389857Sobrien 0, /* bitpos */ 64489857Sobrien complain_overflow_dont, /* complain_on_overflow */ 64599461Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 64689857Sobrien "R_PPC64_PLT16_HI", /* name */ 647130561Sobrien FALSE, /* partial_inplace */ 64889857Sobrien 0, /* src_mask */ 64989857Sobrien 0xffff, /* dst_mask */ 650130561Sobrien FALSE), /* pcrel_offset */ 65189857Sobrien 65289857Sobrien /* Like R_PPC64_ADDR16_HA, but referring to the PLT table entry for 65389857Sobrien the symbol. */ 65489857Sobrien HOWTO (R_PPC64_PLT16_HA, /* type */ 65589857Sobrien 16, /* rightshift */ 65689857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 65789857Sobrien 16, /* bitsize */ 658130561Sobrien FALSE, /* pc_relative */ 65989857Sobrien 0, /* bitpos */ 66089857Sobrien complain_overflow_dont, /* complain_on_overflow */ 66199461Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 66289857Sobrien "R_PPC64_PLT16_HA", /* name */ 663130561Sobrien FALSE, /* partial_inplace */ 66489857Sobrien 0, /* src_mask */ 66589857Sobrien 0xffff, /* dst_mask */ 666130561Sobrien FALSE), /* pcrel_offset */ 66789857Sobrien 66899461Sobrien /* 16-bit section relative relocation. */ 66989857Sobrien HOWTO (R_PPC64_SECTOFF, /* type */ 67089857Sobrien 0, /* rightshift */ 67199461Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 67299461Sobrien 16, /* bitsize */ 673130561Sobrien FALSE, /* pc_relative */ 67489857Sobrien 0, /* bitpos */ 67589857Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 67699461Sobrien ppc64_elf_sectoff_reloc, /* special_function */ 67789857Sobrien "R_PPC64_SECTOFF", /* name */ 678130561Sobrien FALSE, /* partial_inplace */ 67989857Sobrien 0, /* src_mask */ 68099461Sobrien 0xffff, /* dst_mask */ 681130561Sobrien FALSE), /* pcrel_offset */ 68289857Sobrien 68399461Sobrien /* Like R_PPC64_SECTOFF, but no overflow warning. */ 68489857Sobrien HOWTO (R_PPC64_SECTOFF_LO, /* type */ 68589857Sobrien 0, /* rightshift */ 68689857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 68789857Sobrien 16, /* bitsize */ 688130561Sobrien FALSE, /* pc_relative */ 68989857Sobrien 0, /* bitpos */ 69089857Sobrien complain_overflow_dont, /* complain_on_overflow */ 69199461Sobrien ppc64_elf_sectoff_reloc, /* special_function */ 69289857Sobrien "R_PPC64_SECTOFF_LO", /* name */ 693130561Sobrien FALSE, /* partial_inplace */ 69489857Sobrien 0, /* src_mask */ 69589857Sobrien 0xffff, /* dst_mask */ 696130561Sobrien FALSE), /* pcrel_offset */ 69789857Sobrien 69889857Sobrien /* 16-bit upper half section relative relocation. */ 69989857Sobrien HOWTO (R_PPC64_SECTOFF_HI, /* type */ 70089857Sobrien 16, /* rightshift */ 70189857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 70289857Sobrien 16, /* bitsize */ 703130561Sobrien FALSE, /* pc_relative */ 70489857Sobrien 0, /* bitpos */ 70589857Sobrien complain_overflow_dont, /* complain_on_overflow */ 70699461Sobrien ppc64_elf_sectoff_reloc, /* special_function */ 70789857Sobrien "R_PPC64_SECTOFF_HI", /* name */ 708130561Sobrien FALSE, /* partial_inplace */ 70989857Sobrien 0, /* src_mask */ 71089857Sobrien 0xffff, /* dst_mask */ 711130561Sobrien FALSE), /* pcrel_offset */ 71289857Sobrien 71389857Sobrien /* 16-bit upper half adjusted section relative relocation. */ 71489857Sobrien HOWTO (R_PPC64_SECTOFF_HA, /* type */ 71589857Sobrien 16, /* rightshift */ 71689857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 71789857Sobrien 16, /* bitsize */ 718130561Sobrien FALSE, /* pc_relative */ 71989857Sobrien 0, /* bitpos */ 72089857Sobrien complain_overflow_dont, /* complain_on_overflow */ 72199461Sobrien ppc64_elf_sectoff_ha_reloc, /* special_function */ 72289857Sobrien "R_PPC64_SECTOFF_HA", /* name */ 723130561Sobrien FALSE, /* partial_inplace */ 72489857Sobrien 0, /* src_mask */ 72589857Sobrien 0xffff, /* dst_mask */ 726130561Sobrien FALSE), /* pcrel_offset */ 72789857Sobrien 728130561Sobrien /* Like R_PPC64_REL24 without touching the two least significant bits. */ 729130561Sobrien HOWTO (R_PPC64_REL30, /* type */ 73089857Sobrien 2, /* rightshift */ 73189857Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 73289857Sobrien 30, /* bitsize */ 733130561Sobrien TRUE, /* pc_relative */ 73489857Sobrien 0, /* bitpos */ 73589857Sobrien complain_overflow_dont, /* complain_on_overflow */ 73689857Sobrien bfd_elf_generic_reloc, /* special_function */ 737130561Sobrien "R_PPC64_REL30", /* name */ 738130561Sobrien FALSE, /* partial_inplace */ 73989857Sobrien 0, /* src_mask */ 74089857Sobrien 0xfffffffc, /* dst_mask */ 741130561Sobrien TRUE), /* pcrel_offset */ 74289857Sobrien 74389857Sobrien /* Relocs in the 64-bit PowerPC ELF ABI, not in the 32-bit ABI. */ 74489857Sobrien 74589857Sobrien /* A standard 64-bit relocation. */ 74689857Sobrien HOWTO (R_PPC64_ADDR64, /* type */ 74789857Sobrien 0, /* rightshift */ 74889857Sobrien 4, /* size (0=byte, 1=short, 2=long, 4=64 bits) */ 74989857Sobrien 64, /* bitsize */ 750130561Sobrien FALSE, /* pc_relative */ 75189857Sobrien 0, /* bitpos */ 75289857Sobrien complain_overflow_dont, /* complain_on_overflow */ 75389857Sobrien bfd_elf_generic_reloc, /* special_function */ 75489857Sobrien "R_PPC64_ADDR64", /* name */ 755130561Sobrien FALSE, /* partial_inplace */ 75689857Sobrien 0, /* src_mask */ 757104834Sobrien ONES (64), /* dst_mask */ 758130561Sobrien FALSE), /* pcrel_offset */ 75989857Sobrien 76089857Sobrien /* The bits 32-47 of an address. */ 76189857Sobrien HOWTO (R_PPC64_ADDR16_HIGHER, /* type */ 76289857Sobrien 32, /* rightshift */ 76389857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 76489857Sobrien 16, /* bitsize */ 765130561Sobrien FALSE, /* pc_relative */ 76689857Sobrien 0, /* bitpos */ 76789857Sobrien complain_overflow_dont, /* complain_on_overflow */ 76889857Sobrien bfd_elf_generic_reloc, /* special_function */ 76989857Sobrien "R_PPC64_ADDR16_HIGHER", /* name */ 770130561Sobrien FALSE, /* partial_inplace */ 77189857Sobrien 0, /* src_mask */ 77289857Sobrien 0xffff, /* dst_mask */ 773130561Sobrien FALSE), /* pcrel_offset */ 77489857Sobrien 77589857Sobrien /* The bits 32-47 of an address, plus 1 if the contents of the low 77689857Sobrien 16 bits, treated as a signed number, is negative. */ 77789857Sobrien HOWTO (R_PPC64_ADDR16_HIGHERA, /* type */ 77889857Sobrien 32, /* rightshift */ 77989857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 78089857Sobrien 16, /* bitsize */ 781130561Sobrien FALSE, /* pc_relative */ 78289857Sobrien 0, /* bitpos */ 78389857Sobrien complain_overflow_dont, /* complain_on_overflow */ 78499461Sobrien ppc64_elf_ha_reloc, /* special_function */ 78589857Sobrien "R_PPC64_ADDR16_HIGHERA", /* name */ 786130561Sobrien FALSE, /* partial_inplace */ 78789857Sobrien 0, /* src_mask */ 78889857Sobrien 0xffff, /* dst_mask */ 789130561Sobrien FALSE), /* pcrel_offset */ 79089857Sobrien 79189857Sobrien /* The bits 48-63 of an address. */ 79289857Sobrien HOWTO (R_PPC64_ADDR16_HIGHEST,/* type */ 79389857Sobrien 48, /* rightshift */ 79489857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 79589857Sobrien 16, /* bitsize */ 796130561Sobrien FALSE, /* pc_relative */ 79789857Sobrien 0, /* bitpos */ 79889857Sobrien complain_overflow_dont, /* complain_on_overflow */ 79989857Sobrien bfd_elf_generic_reloc, /* special_function */ 80089857Sobrien "R_PPC64_ADDR16_HIGHEST", /* name */ 801130561Sobrien FALSE, /* partial_inplace */ 80289857Sobrien 0, /* src_mask */ 80389857Sobrien 0xffff, /* dst_mask */ 804130561Sobrien FALSE), /* pcrel_offset */ 80589857Sobrien 80689857Sobrien /* The bits 48-63 of an address, plus 1 if the contents of the low 80789857Sobrien 16 bits, treated as a signed number, is negative. */ 80889857Sobrien HOWTO (R_PPC64_ADDR16_HIGHESTA,/* type */ 80989857Sobrien 48, /* rightshift */ 81089857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 81189857Sobrien 16, /* bitsize */ 812130561Sobrien FALSE, /* pc_relative */ 81389857Sobrien 0, /* bitpos */ 81489857Sobrien complain_overflow_dont, /* complain_on_overflow */ 81599461Sobrien ppc64_elf_ha_reloc, /* special_function */ 81689857Sobrien "R_PPC64_ADDR16_HIGHESTA", /* name */ 817130561Sobrien FALSE, /* partial_inplace */ 81889857Sobrien 0, /* src_mask */ 81989857Sobrien 0xffff, /* dst_mask */ 820130561Sobrien FALSE), /* pcrel_offset */ 82189857Sobrien 82289857Sobrien /* Like ADDR64, but may be unaligned. */ 82389857Sobrien HOWTO (R_PPC64_UADDR64, /* type */ 82489857Sobrien 0, /* rightshift */ 82589857Sobrien 4, /* size (0=byte, 1=short, 2=long, 4=64 bits) */ 82689857Sobrien 64, /* bitsize */ 827130561Sobrien FALSE, /* pc_relative */ 82889857Sobrien 0, /* bitpos */ 82989857Sobrien complain_overflow_dont, /* complain_on_overflow */ 83089857Sobrien bfd_elf_generic_reloc, /* special_function */ 83189857Sobrien "R_PPC64_UADDR64", /* name */ 832130561Sobrien FALSE, /* partial_inplace */ 83389857Sobrien 0, /* src_mask */ 834104834Sobrien ONES (64), /* dst_mask */ 835130561Sobrien FALSE), /* pcrel_offset */ 83689857Sobrien 83789857Sobrien /* 64-bit relative relocation. */ 83889857Sobrien HOWTO (R_PPC64_REL64, /* type */ 83989857Sobrien 0, /* rightshift */ 84089857Sobrien 4, /* size (0=byte, 1=short, 2=long, 4=64 bits) */ 84189857Sobrien 64, /* bitsize */ 842130561Sobrien TRUE, /* pc_relative */ 84389857Sobrien 0, /* bitpos */ 84489857Sobrien complain_overflow_dont, /* complain_on_overflow */ 84589857Sobrien bfd_elf_generic_reloc, /* special_function */ 84689857Sobrien "R_PPC64_REL64", /* name */ 847130561Sobrien FALSE, /* partial_inplace */ 84889857Sobrien 0, /* src_mask */ 849104834Sobrien ONES (64), /* dst_mask */ 850130561Sobrien TRUE), /* pcrel_offset */ 85189857Sobrien 852104834Sobrien /* 64-bit relocation to the symbol's procedure linkage table. */ 85389857Sobrien HOWTO (R_PPC64_PLT64, /* type */ 85489857Sobrien 0, /* rightshift */ 85589857Sobrien 4, /* size (0=byte, 1=short, 2=long, 4=64 bits) */ 85689857Sobrien 64, /* bitsize */ 857130561Sobrien FALSE, /* pc_relative */ 85889857Sobrien 0, /* bitpos */ 85989857Sobrien complain_overflow_dont, /* complain_on_overflow */ 86099461Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 86189857Sobrien "R_PPC64_PLT64", /* name */ 862130561Sobrien FALSE, /* partial_inplace */ 86389857Sobrien 0, /* src_mask */ 864104834Sobrien ONES (64), /* dst_mask */ 865130561Sobrien FALSE), /* pcrel_offset */ 86689857Sobrien 86789857Sobrien /* 64-bit PC relative relocation to the symbol's procedure linkage 86889857Sobrien table. */ 86989857Sobrien /* FIXME: R_PPC64_PLTREL64 not supported. */ 87089857Sobrien HOWTO (R_PPC64_PLTREL64, /* type */ 87189857Sobrien 0, /* rightshift */ 87289857Sobrien 4, /* size (0=byte, 1=short, 2=long, 4=64 bits) */ 87389857Sobrien 64, /* bitsize */ 874130561Sobrien TRUE, /* pc_relative */ 87589857Sobrien 0, /* bitpos */ 87689857Sobrien complain_overflow_dont, /* complain_on_overflow */ 87799461Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 87889857Sobrien "R_PPC64_PLTREL64", /* name */ 879130561Sobrien FALSE, /* partial_inplace */ 88089857Sobrien 0, /* src_mask */ 881104834Sobrien ONES (64), /* dst_mask */ 882130561Sobrien TRUE), /* pcrel_offset */ 88389857Sobrien 88489857Sobrien /* 16 bit TOC-relative relocation. */ 88589857Sobrien 88689857Sobrien /* R_PPC64_TOC16 47 half16* S + A - .TOC. */ 88789857Sobrien HOWTO (R_PPC64_TOC16, /* type */ 88889857Sobrien 0, /* rightshift */ 88989857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 89089857Sobrien 16, /* bitsize */ 891130561Sobrien FALSE, /* pc_relative */ 89289857Sobrien 0, /* bitpos */ 89389857Sobrien complain_overflow_signed, /* complain_on_overflow */ 89499461Sobrien ppc64_elf_toc_reloc, /* special_function */ 89589857Sobrien "R_PPC64_TOC16", /* name */ 896130561Sobrien FALSE, /* partial_inplace */ 89789857Sobrien 0, /* src_mask */ 89889857Sobrien 0xffff, /* dst_mask */ 899130561Sobrien FALSE), /* pcrel_offset */ 90089857Sobrien 90189857Sobrien /* 16 bit TOC-relative relocation without overflow. */ 90289857Sobrien 90389857Sobrien /* R_PPC64_TOC16_LO 48 half16 #lo (S + A - .TOC.) */ 90489857Sobrien HOWTO (R_PPC64_TOC16_LO, /* type */ 90589857Sobrien 0, /* rightshift */ 90689857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 90789857Sobrien 16, /* bitsize */ 908130561Sobrien FALSE, /* pc_relative */ 90989857Sobrien 0, /* bitpos */ 91089857Sobrien complain_overflow_dont, /* complain_on_overflow */ 91199461Sobrien ppc64_elf_toc_reloc, /* special_function */ 91289857Sobrien "R_PPC64_TOC16_LO", /* name */ 913130561Sobrien FALSE, /* partial_inplace */ 91489857Sobrien 0, /* src_mask */ 91589857Sobrien 0xffff, /* dst_mask */ 916130561Sobrien FALSE), /* pcrel_offset */ 91789857Sobrien 91889857Sobrien /* 16 bit TOC-relative relocation, high 16 bits. */ 91989857Sobrien 92089857Sobrien /* R_PPC64_TOC16_HI 49 half16 #hi (S + A - .TOC.) */ 92189857Sobrien HOWTO (R_PPC64_TOC16_HI, /* type */ 92289857Sobrien 16, /* rightshift */ 92389857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 92489857Sobrien 16, /* bitsize */ 925130561Sobrien FALSE, /* pc_relative */ 92689857Sobrien 0, /* bitpos */ 92789857Sobrien complain_overflow_dont, /* complain_on_overflow */ 92899461Sobrien ppc64_elf_toc_reloc, /* special_function */ 92989857Sobrien "R_PPC64_TOC16_HI", /* name */ 930130561Sobrien FALSE, /* partial_inplace */ 93189857Sobrien 0, /* src_mask */ 93289857Sobrien 0xffff, /* dst_mask */ 933130561Sobrien FALSE), /* pcrel_offset */ 93489857Sobrien 93589857Sobrien /* 16 bit TOC-relative relocation, high 16 bits, plus 1 if the 93689857Sobrien contents of the low 16 bits, treated as a signed number, is 93789857Sobrien negative. */ 93889857Sobrien 93989857Sobrien /* R_PPC64_TOC16_HA 50 half16 #ha (S + A - .TOC.) */ 94089857Sobrien HOWTO (R_PPC64_TOC16_HA, /* type */ 94189857Sobrien 16, /* rightshift */ 94289857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 94389857Sobrien 16, /* bitsize */ 944130561Sobrien FALSE, /* pc_relative */ 94589857Sobrien 0, /* bitpos */ 94689857Sobrien complain_overflow_dont, /* complain_on_overflow */ 94799461Sobrien ppc64_elf_toc_ha_reloc, /* special_function */ 94889857Sobrien "R_PPC64_TOC16_HA", /* name */ 949130561Sobrien FALSE, /* partial_inplace */ 95089857Sobrien 0, /* src_mask */ 95189857Sobrien 0xffff, /* dst_mask */ 952130561Sobrien FALSE), /* pcrel_offset */ 95389857Sobrien 95489857Sobrien /* 64-bit relocation; insert value of TOC base (.TOC.). */ 95589857Sobrien 95689857Sobrien /* R_PPC64_TOC 51 doubleword64 .TOC. */ 95789857Sobrien HOWTO (R_PPC64_TOC, /* type */ 95889857Sobrien 0, /* rightshift */ 95989857Sobrien 4, /* size (0=byte, 1=short, 2=long, 4=64 bits) */ 96089857Sobrien 64, /* bitsize */ 961130561Sobrien FALSE, /* pc_relative */ 96289857Sobrien 0, /* bitpos */ 96389857Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 96499461Sobrien ppc64_elf_toc64_reloc, /* special_function */ 96589857Sobrien "R_PPC64_TOC", /* name */ 966130561Sobrien FALSE, /* partial_inplace */ 96789857Sobrien 0, /* src_mask */ 968104834Sobrien ONES (64), /* dst_mask */ 969130561Sobrien FALSE), /* pcrel_offset */ 97089857Sobrien 97189857Sobrien /* Like R_PPC64_GOT16, but also informs the link editor that the 97289857Sobrien value to relocate may (!) refer to a PLT entry which the link 97389857Sobrien editor (a) may replace with the symbol value. If the link editor 97489857Sobrien is unable to fully resolve the symbol, it may (b) create a PLT 97589857Sobrien entry and store the address to the new PLT entry in the GOT. 97689857Sobrien This permits lazy resolution of function symbols at run time. 97789857Sobrien The link editor may also skip all of this and just (c) emit a 97889857Sobrien R_PPC64_GLOB_DAT to tie the symbol to the GOT entry. */ 97989857Sobrien /* FIXME: R_PPC64_PLTGOT16 not implemented. */ 98089857Sobrien HOWTO (R_PPC64_PLTGOT16, /* type */ 98189857Sobrien 0, /* rightshift */ 98289857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 98389857Sobrien 16, /* bitsize */ 984130561Sobrien FALSE, /* pc_relative */ 98589857Sobrien 0, /* bitpos */ 98689857Sobrien complain_overflow_signed, /* complain_on_overflow */ 98799461Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 98889857Sobrien "R_PPC64_PLTGOT16", /* name */ 989130561Sobrien FALSE, /* partial_inplace */ 99089857Sobrien 0, /* src_mask */ 99189857Sobrien 0xffff, /* dst_mask */ 992130561Sobrien FALSE), /* pcrel_offset */ 99389857Sobrien 99489857Sobrien /* Like R_PPC64_PLTGOT16, but without overflow. */ 99589857Sobrien /* FIXME: R_PPC64_PLTGOT16_LO not implemented. */ 99689857Sobrien HOWTO (R_PPC64_PLTGOT16_LO, /* type */ 99789857Sobrien 0, /* rightshift */ 99889857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 99989857Sobrien 16, /* bitsize */ 1000130561Sobrien FALSE, /* pc_relative */ 100189857Sobrien 0, /* bitpos */ 100289857Sobrien complain_overflow_dont, /* complain_on_overflow */ 100399461Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 100489857Sobrien "R_PPC64_PLTGOT16_LO", /* name */ 1005130561Sobrien FALSE, /* partial_inplace */ 100689857Sobrien 0, /* src_mask */ 100789857Sobrien 0xffff, /* dst_mask */ 1008130561Sobrien FALSE), /* pcrel_offset */ 100989857Sobrien 101089857Sobrien /* Like R_PPC64_PLT_GOT16, but using bits 16-31 of the address. */ 101189857Sobrien /* FIXME: R_PPC64_PLTGOT16_HI not implemented. */ 101289857Sobrien HOWTO (R_PPC64_PLTGOT16_HI, /* type */ 101389857Sobrien 16, /* rightshift */ 101489857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 101589857Sobrien 16, /* bitsize */ 1016130561Sobrien FALSE, /* pc_relative */ 101789857Sobrien 0, /* bitpos */ 101889857Sobrien complain_overflow_dont, /* complain_on_overflow */ 101999461Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 102089857Sobrien "R_PPC64_PLTGOT16_HI", /* name */ 1021130561Sobrien FALSE, /* partial_inplace */ 102289857Sobrien 0, /* src_mask */ 102389857Sobrien 0xffff, /* dst_mask */ 1024130561Sobrien FALSE), /* pcrel_offset */ 102589857Sobrien 102689857Sobrien /* Like R_PPC64_PLT_GOT16, but using bits 16-31 of the address, plus 102789857Sobrien 1 if the contents of the low 16 bits, treated as a signed number, 102889857Sobrien is negative. */ 102989857Sobrien /* FIXME: R_PPC64_PLTGOT16_HA not implemented. */ 103089857Sobrien HOWTO (R_PPC64_PLTGOT16_HA, /* type */ 103189857Sobrien 16, /* rightshift */ 103289857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 103389857Sobrien 16, /* bitsize */ 1034130561Sobrien FALSE, /* pc_relative */ 103589857Sobrien 0, /* bitpos */ 103689857Sobrien complain_overflow_dont,/* complain_on_overflow */ 103799461Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 103889857Sobrien "R_PPC64_PLTGOT16_HA", /* name */ 1039130561Sobrien FALSE, /* partial_inplace */ 104089857Sobrien 0, /* src_mask */ 104189857Sobrien 0xffff, /* dst_mask */ 1042130561Sobrien FALSE), /* pcrel_offset */ 104389857Sobrien 104489857Sobrien /* Like R_PPC64_ADDR16, but for instructions with a DS field. */ 104589857Sobrien HOWTO (R_PPC64_ADDR16_DS, /* type */ 104689857Sobrien 0, /* rightshift */ 104789857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 104889857Sobrien 16, /* bitsize */ 1049130561Sobrien FALSE, /* pc_relative */ 105089857Sobrien 0, /* bitpos */ 105189857Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 105289857Sobrien bfd_elf_generic_reloc, /* special_function */ 105389857Sobrien "R_PPC64_ADDR16_DS", /* name */ 1054130561Sobrien FALSE, /* partial_inplace */ 105589857Sobrien 0, /* src_mask */ 105689857Sobrien 0xfffc, /* dst_mask */ 1057130561Sobrien FALSE), /* pcrel_offset */ 105889857Sobrien 105989857Sobrien /* Like R_PPC64_ADDR16_LO, but for instructions with a DS field. */ 106089857Sobrien HOWTO (R_PPC64_ADDR16_LO_DS, /* type */ 106189857Sobrien 0, /* rightshift */ 106289857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 106389857Sobrien 16, /* bitsize */ 1064130561Sobrien FALSE, /* pc_relative */ 106589857Sobrien 0, /* bitpos */ 106689857Sobrien complain_overflow_dont,/* complain_on_overflow */ 106789857Sobrien bfd_elf_generic_reloc, /* special_function */ 106889857Sobrien "R_PPC64_ADDR16_LO_DS",/* name */ 1069130561Sobrien FALSE, /* partial_inplace */ 107089857Sobrien 0, /* src_mask */ 107189857Sobrien 0xfffc, /* dst_mask */ 1072130561Sobrien FALSE), /* pcrel_offset */ 107389857Sobrien 107489857Sobrien /* Like R_PPC64_GOT16, but for instructions with a DS field. */ 107589857Sobrien HOWTO (R_PPC64_GOT16_DS, /* type */ 107689857Sobrien 0, /* rightshift */ 107789857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 107889857Sobrien 16, /* bitsize */ 1079130561Sobrien FALSE, /* pc_relative */ 108089857Sobrien 0, /* bitpos */ 108189857Sobrien complain_overflow_signed, /* complain_on_overflow */ 108299461Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 108389857Sobrien "R_PPC64_GOT16_DS", /* name */ 1084130561Sobrien FALSE, /* partial_inplace */ 108589857Sobrien 0, /* src_mask */ 108689857Sobrien 0xfffc, /* dst_mask */ 1087130561Sobrien FALSE), /* pcrel_offset */ 108889857Sobrien 108989857Sobrien /* Like R_PPC64_GOT16_LO, but for instructions with a DS field. */ 109089857Sobrien HOWTO (R_PPC64_GOT16_LO_DS, /* type */ 109189857Sobrien 0, /* rightshift */ 109289857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 109389857Sobrien 16, /* bitsize */ 1094130561Sobrien FALSE, /* pc_relative */ 109589857Sobrien 0, /* bitpos */ 109689857Sobrien complain_overflow_dont, /* complain_on_overflow */ 109799461Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 109889857Sobrien "R_PPC64_GOT16_LO_DS", /* name */ 1099130561Sobrien FALSE, /* partial_inplace */ 110089857Sobrien 0, /* src_mask */ 110189857Sobrien 0xfffc, /* dst_mask */ 1102130561Sobrien FALSE), /* pcrel_offset */ 110389857Sobrien 110489857Sobrien /* Like R_PPC64_PLT16_LO, but for instructions with a DS field. */ 110589857Sobrien HOWTO (R_PPC64_PLT16_LO_DS, /* type */ 110689857Sobrien 0, /* rightshift */ 110789857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 110889857Sobrien 16, /* bitsize */ 1109130561Sobrien FALSE, /* pc_relative */ 111089857Sobrien 0, /* bitpos */ 111189857Sobrien complain_overflow_dont, /* complain_on_overflow */ 111299461Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 111389857Sobrien "R_PPC64_PLT16_LO_DS", /* name */ 1114130561Sobrien FALSE, /* partial_inplace */ 111589857Sobrien 0, /* src_mask */ 111689857Sobrien 0xfffc, /* dst_mask */ 1117130561Sobrien FALSE), /* pcrel_offset */ 111889857Sobrien 111989857Sobrien /* Like R_PPC64_SECTOFF, but for instructions with a DS field. */ 112089857Sobrien HOWTO (R_PPC64_SECTOFF_DS, /* type */ 112189857Sobrien 0, /* rightshift */ 112299461Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 112399461Sobrien 16, /* bitsize */ 1124130561Sobrien FALSE, /* pc_relative */ 112589857Sobrien 0, /* bitpos */ 112689857Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 112799461Sobrien ppc64_elf_sectoff_reloc, /* special_function */ 112889857Sobrien "R_PPC64_SECTOFF_DS", /* name */ 1129130561Sobrien FALSE, /* partial_inplace */ 113089857Sobrien 0, /* src_mask */ 113199461Sobrien 0xfffc, /* dst_mask */ 1132130561Sobrien FALSE), /* pcrel_offset */ 113389857Sobrien 113489857Sobrien /* Like R_PPC64_SECTOFF_LO, but for instructions with a DS field. */ 113589857Sobrien HOWTO (R_PPC64_SECTOFF_LO_DS, /* type */ 113689857Sobrien 0, /* rightshift */ 113789857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 113889857Sobrien 16, /* bitsize */ 1139130561Sobrien FALSE, /* pc_relative */ 114089857Sobrien 0, /* bitpos */ 114189857Sobrien complain_overflow_dont, /* complain_on_overflow */ 114299461Sobrien ppc64_elf_sectoff_reloc, /* special_function */ 114389857Sobrien "R_PPC64_SECTOFF_LO_DS",/* name */ 1144130561Sobrien FALSE, /* partial_inplace */ 114589857Sobrien 0, /* src_mask */ 114689857Sobrien 0xfffc, /* dst_mask */ 1147130561Sobrien FALSE), /* pcrel_offset */ 114889857Sobrien 114989857Sobrien /* Like R_PPC64_TOC16, but for instructions with a DS field. */ 115089857Sobrien HOWTO (R_PPC64_TOC16_DS, /* type */ 115189857Sobrien 0, /* rightshift */ 115289857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 115389857Sobrien 16, /* bitsize */ 1154130561Sobrien FALSE, /* pc_relative */ 115589857Sobrien 0, /* bitpos */ 115689857Sobrien complain_overflow_signed, /* complain_on_overflow */ 115799461Sobrien ppc64_elf_toc_reloc, /* special_function */ 115889857Sobrien "R_PPC64_TOC16_DS", /* name */ 1159130561Sobrien FALSE, /* partial_inplace */ 116089857Sobrien 0, /* src_mask */ 116189857Sobrien 0xfffc, /* dst_mask */ 1162130561Sobrien FALSE), /* pcrel_offset */ 116389857Sobrien 116489857Sobrien /* Like R_PPC64_TOC16_LO, but for instructions with a DS field. */ 116589857Sobrien HOWTO (R_PPC64_TOC16_LO_DS, /* type */ 116689857Sobrien 0, /* rightshift */ 116789857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 116889857Sobrien 16, /* bitsize */ 1169130561Sobrien FALSE, /* pc_relative */ 117089857Sobrien 0, /* bitpos */ 117189857Sobrien complain_overflow_dont, /* complain_on_overflow */ 117299461Sobrien ppc64_elf_toc_reloc, /* special_function */ 117389857Sobrien "R_PPC64_TOC16_LO_DS", /* name */ 1174130561Sobrien FALSE, /* partial_inplace */ 117589857Sobrien 0, /* src_mask */ 117689857Sobrien 0xfffc, /* dst_mask */ 1177130561Sobrien FALSE), /* pcrel_offset */ 117889857Sobrien 117989857Sobrien /* Like R_PPC64_PLTGOT16, but for instructions with a DS field. */ 118089857Sobrien /* FIXME: R_PPC64_PLTGOT16_DS not implemented. */ 118189857Sobrien HOWTO (R_PPC64_PLTGOT16_DS, /* type */ 118289857Sobrien 0, /* rightshift */ 118389857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 118489857Sobrien 16, /* bitsize */ 1185130561Sobrien FALSE, /* pc_relative */ 118689857Sobrien 0, /* bitpos */ 118789857Sobrien complain_overflow_signed, /* complain_on_overflow */ 118899461Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 118989857Sobrien "R_PPC64_PLTGOT16_DS", /* name */ 1190130561Sobrien FALSE, /* partial_inplace */ 119189857Sobrien 0, /* src_mask */ 119289857Sobrien 0xfffc, /* dst_mask */ 1193130561Sobrien FALSE), /* pcrel_offset */ 119489857Sobrien 119589857Sobrien /* Like R_PPC64_PLTGOT16_LO, but for instructions with a DS field. */ 119689857Sobrien /* FIXME: R_PPC64_PLTGOT16_LO not implemented. */ 119789857Sobrien HOWTO (R_PPC64_PLTGOT16_LO_DS,/* type */ 119889857Sobrien 0, /* rightshift */ 119989857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 120089857Sobrien 16, /* bitsize */ 1201130561Sobrien FALSE, /* pc_relative */ 120289857Sobrien 0, /* bitpos */ 120389857Sobrien complain_overflow_dont, /* complain_on_overflow */ 120499461Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 120589857Sobrien "R_PPC64_PLTGOT16_LO_DS",/* name */ 1206130561Sobrien FALSE, /* partial_inplace */ 120789857Sobrien 0, /* src_mask */ 120889857Sobrien 0xfffc, /* dst_mask */ 1209130561Sobrien FALSE), /* pcrel_offset */ 121089857Sobrien 1211130561Sobrien /* Marker reloc for TLS. */ 1212130561Sobrien HOWTO (R_PPC64_TLS, 1213130561Sobrien 0, /* rightshift */ 1214130561Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 1215130561Sobrien 32, /* bitsize */ 1216130561Sobrien FALSE, /* pc_relative */ 1217130561Sobrien 0, /* bitpos */ 1218130561Sobrien complain_overflow_dont, /* complain_on_overflow */ 1219130561Sobrien bfd_elf_generic_reloc, /* special_function */ 1220130561Sobrien "R_PPC64_TLS", /* name */ 1221130561Sobrien FALSE, /* partial_inplace */ 1222130561Sobrien 0, /* src_mask */ 1223130561Sobrien 0, /* dst_mask */ 1224130561Sobrien FALSE), /* pcrel_offset */ 1225130561Sobrien 1226130561Sobrien /* Computes the load module index of the load module that contains the 1227130561Sobrien definition of its TLS sym. */ 1228130561Sobrien HOWTO (R_PPC64_DTPMOD64, 1229130561Sobrien 0, /* rightshift */ 1230130561Sobrien 4, /* size (0 = byte, 1 = short, 2 = long) */ 1231130561Sobrien 64, /* bitsize */ 1232130561Sobrien FALSE, /* pc_relative */ 1233130561Sobrien 0, /* bitpos */ 1234130561Sobrien complain_overflow_dont, /* complain_on_overflow */ 1235130561Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 1236130561Sobrien "R_PPC64_DTPMOD64", /* name */ 1237130561Sobrien FALSE, /* partial_inplace */ 1238130561Sobrien 0, /* src_mask */ 1239130561Sobrien ONES (64), /* dst_mask */ 1240130561Sobrien FALSE), /* pcrel_offset */ 1241130561Sobrien 1242130561Sobrien /* Computes a dtv-relative displacement, the difference between the value 1243130561Sobrien of sym+add and the base address of the thread-local storage block that 1244130561Sobrien contains the definition of sym, minus 0x8000. */ 1245130561Sobrien HOWTO (R_PPC64_DTPREL64, 1246130561Sobrien 0, /* rightshift */ 1247130561Sobrien 4, /* size (0 = byte, 1 = short, 2 = long) */ 1248130561Sobrien 64, /* bitsize */ 1249130561Sobrien FALSE, /* pc_relative */ 1250130561Sobrien 0, /* bitpos */ 1251130561Sobrien complain_overflow_dont, /* complain_on_overflow */ 1252130561Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 1253130561Sobrien "R_PPC64_DTPREL64", /* name */ 1254130561Sobrien FALSE, /* partial_inplace */ 1255130561Sobrien 0, /* src_mask */ 1256130561Sobrien ONES (64), /* dst_mask */ 1257130561Sobrien FALSE), /* pcrel_offset */ 1258130561Sobrien 1259130561Sobrien /* A 16 bit dtprel reloc. */ 1260130561Sobrien HOWTO (R_PPC64_DTPREL16, 1261130561Sobrien 0, /* rightshift */ 1262130561Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 1263130561Sobrien 16, /* bitsize */ 1264130561Sobrien FALSE, /* pc_relative */ 1265130561Sobrien 0, /* bitpos */ 1266130561Sobrien complain_overflow_signed, /* complain_on_overflow */ 1267130561Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 1268130561Sobrien "R_PPC64_DTPREL16", /* name */ 1269130561Sobrien FALSE, /* partial_inplace */ 1270130561Sobrien 0, /* src_mask */ 1271130561Sobrien 0xffff, /* dst_mask */ 1272130561Sobrien FALSE), /* pcrel_offset */ 1273130561Sobrien 1274130561Sobrien /* Like DTPREL16, but no overflow. */ 1275130561Sobrien HOWTO (R_PPC64_DTPREL16_LO, 1276130561Sobrien 0, /* rightshift */ 1277130561Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 1278130561Sobrien 16, /* bitsize */ 1279130561Sobrien FALSE, /* pc_relative */ 1280130561Sobrien 0, /* bitpos */ 1281130561Sobrien complain_overflow_dont, /* complain_on_overflow */ 1282130561Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 1283130561Sobrien "R_PPC64_DTPREL16_LO", /* name */ 1284130561Sobrien FALSE, /* partial_inplace */ 1285130561Sobrien 0, /* src_mask */ 1286130561Sobrien 0xffff, /* dst_mask */ 1287130561Sobrien FALSE), /* pcrel_offset */ 1288130561Sobrien 1289130561Sobrien /* Like DTPREL16_LO, but next higher group of 16 bits. */ 1290130561Sobrien HOWTO (R_PPC64_DTPREL16_HI, 1291130561Sobrien 16, /* rightshift */ 1292130561Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 1293130561Sobrien 16, /* bitsize */ 1294130561Sobrien FALSE, /* pc_relative */ 1295130561Sobrien 0, /* bitpos */ 1296130561Sobrien complain_overflow_dont, /* complain_on_overflow */ 1297130561Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 1298130561Sobrien "R_PPC64_DTPREL16_HI", /* name */ 1299130561Sobrien FALSE, /* partial_inplace */ 1300130561Sobrien 0, /* src_mask */ 1301130561Sobrien 0xffff, /* dst_mask */ 1302130561Sobrien FALSE), /* pcrel_offset */ 1303130561Sobrien 1304130561Sobrien /* Like DTPREL16_HI, but adjust for low 16 bits. */ 1305130561Sobrien HOWTO (R_PPC64_DTPREL16_HA, 1306130561Sobrien 16, /* rightshift */ 1307130561Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 1308130561Sobrien 16, /* bitsize */ 1309130561Sobrien FALSE, /* pc_relative */ 1310130561Sobrien 0, /* bitpos */ 1311130561Sobrien complain_overflow_dont, /* complain_on_overflow */ 1312130561Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 1313130561Sobrien "R_PPC64_DTPREL16_HA", /* name */ 1314130561Sobrien FALSE, /* partial_inplace */ 1315130561Sobrien 0, /* src_mask */ 1316130561Sobrien 0xffff, /* dst_mask */ 1317130561Sobrien FALSE), /* pcrel_offset */ 1318130561Sobrien 1319130561Sobrien /* Like DTPREL16_HI, but next higher group of 16 bits. */ 1320130561Sobrien HOWTO (R_PPC64_DTPREL16_HIGHER, 1321130561Sobrien 32, /* rightshift */ 1322130561Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 1323130561Sobrien 16, /* bitsize */ 1324130561Sobrien FALSE, /* pc_relative */ 1325130561Sobrien 0, /* bitpos */ 1326130561Sobrien complain_overflow_dont, /* complain_on_overflow */ 1327130561Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 1328130561Sobrien "R_PPC64_DTPREL16_HIGHER", /* name */ 1329130561Sobrien FALSE, /* partial_inplace */ 1330130561Sobrien 0, /* src_mask */ 1331130561Sobrien 0xffff, /* dst_mask */ 1332130561Sobrien FALSE), /* pcrel_offset */ 1333130561Sobrien 1334130561Sobrien /* Like DTPREL16_HIGHER, but adjust for low 16 bits. */ 1335130561Sobrien HOWTO (R_PPC64_DTPREL16_HIGHERA, 1336130561Sobrien 32, /* rightshift */ 1337130561Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 1338130561Sobrien 16, /* bitsize */ 1339130561Sobrien FALSE, /* pc_relative */ 1340130561Sobrien 0, /* bitpos */ 1341130561Sobrien complain_overflow_dont, /* complain_on_overflow */ 1342130561Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 1343130561Sobrien "R_PPC64_DTPREL16_HIGHERA", /* name */ 1344130561Sobrien FALSE, /* partial_inplace */ 1345130561Sobrien 0, /* src_mask */ 1346130561Sobrien 0xffff, /* dst_mask */ 1347130561Sobrien FALSE), /* pcrel_offset */ 1348130561Sobrien 1349130561Sobrien /* Like DTPREL16_HIGHER, but next higher group of 16 bits. */ 1350130561Sobrien HOWTO (R_PPC64_DTPREL16_HIGHEST, 1351130561Sobrien 48, /* rightshift */ 1352130561Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 1353130561Sobrien 16, /* bitsize */ 1354130561Sobrien FALSE, /* pc_relative */ 1355130561Sobrien 0, /* bitpos */ 1356130561Sobrien complain_overflow_dont, /* complain_on_overflow */ 1357130561Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 1358130561Sobrien "R_PPC64_DTPREL16_HIGHEST", /* name */ 1359130561Sobrien FALSE, /* partial_inplace */ 1360130561Sobrien 0, /* src_mask */ 1361130561Sobrien 0xffff, /* dst_mask */ 1362130561Sobrien FALSE), /* pcrel_offset */ 1363130561Sobrien 1364130561Sobrien /* Like DTPREL16_HIGHEST, but adjust for low 16 bits. */ 1365130561Sobrien HOWTO (R_PPC64_DTPREL16_HIGHESTA, 1366130561Sobrien 48, /* rightshift */ 1367130561Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 1368130561Sobrien 16, /* bitsize */ 1369130561Sobrien FALSE, /* pc_relative */ 1370130561Sobrien 0, /* bitpos */ 1371130561Sobrien complain_overflow_dont, /* complain_on_overflow */ 1372130561Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 1373130561Sobrien "R_PPC64_DTPREL16_HIGHESTA", /* name */ 1374130561Sobrien FALSE, /* partial_inplace */ 1375130561Sobrien 0, /* src_mask */ 1376130561Sobrien 0xffff, /* dst_mask */ 1377130561Sobrien FALSE), /* pcrel_offset */ 1378130561Sobrien 1379130561Sobrien /* Like DTPREL16, but for insns with a DS field. */ 1380130561Sobrien HOWTO (R_PPC64_DTPREL16_DS, 1381130561Sobrien 0, /* rightshift */ 1382130561Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 1383130561Sobrien 16, /* bitsize */ 1384130561Sobrien FALSE, /* pc_relative */ 1385130561Sobrien 0, /* bitpos */ 1386130561Sobrien complain_overflow_signed, /* complain_on_overflow */ 1387130561Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 1388130561Sobrien "R_PPC64_DTPREL16_DS", /* name */ 1389130561Sobrien FALSE, /* partial_inplace */ 1390130561Sobrien 0, /* src_mask */ 1391130561Sobrien 0xfffc, /* dst_mask */ 1392130561Sobrien FALSE), /* pcrel_offset */ 1393130561Sobrien 1394130561Sobrien /* Like DTPREL16_DS, but no overflow. */ 1395130561Sobrien HOWTO (R_PPC64_DTPREL16_LO_DS, 1396130561Sobrien 0, /* rightshift */ 1397130561Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 1398130561Sobrien 16, /* bitsize */ 1399130561Sobrien FALSE, /* pc_relative */ 1400130561Sobrien 0, /* bitpos */ 1401130561Sobrien complain_overflow_dont, /* complain_on_overflow */ 1402130561Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 1403130561Sobrien "R_PPC64_DTPREL16_LO_DS", /* name */ 1404130561Sobrien FALSE, /* partial_inplace */ 1405130561Sobrien 0, /* src_mask */ 1406130561Sobrien 0xfffc, /* dst_mask */ 1407130561Sobrien FALSE), /* pcrel_offset */ 1408130561Sobrien 1409130561Sobrien /* Computes a tp-relative displacement, the difference between the value of 1410130561Sobrien sym+add and the value of the thread pointer (r13). */ 1411130561Sobrien HOWTO (R_PPC64_TPREL64, 1412130561Sobrien 0, /* rightshift */ 1413130561Sobrien 4, /* size (0 = byte, 1 = short, 2 = long) */ 1414130561Sobrien 64, /* bitsize */ 1415130561Sobrien FALSE, /* pc_relative */ 1416130561Sobrien 0, /* bitpos */ 1417130561Sobrien complain_overflow_dont, /* complain_on_overflow */ 1418130561Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 1419130561Sobrien "R_PPC64_TPREL64", /* name */ 1420130561Sobrien FALSE, /* partial_inplace */ 1421130561Sobrien 0, /* src_mask */ 1422130561Sobrien ONES (64), /* dst_mask */ 1423130561Sobrien FALSE), /* pcrel_offset */ 1424130561Sobrien 1425130561Sobrien /* A 16 bit tprel reloc. */ 1426130561Sobrien HOWTO (R_PPC64_TPREL16, 1427130561Sobrien 0, /* rightshift */ 1428130561Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 1429130561Sobrien 16, /* bitsize */ 1430130561Sobrien FALSE, /* pc_relative */ 1431130561Sobrien 0, /* bitpos */ 1432130561Sobrien complain_overflow_signed, /* complain_on_overflow */ 1433130561Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 1434130561Sobrien "R_PPC64_TPREL16", /* name */ 1435130561Sobrien FALSE, /* partial_inplace */ 1436130561Sobrien 0, /* src_mask */ 1437130561Sobrien 0xffff, /* dst_mask */ 1438130561Sobrien FALSE), /* pcrel_offset */ 1439130561Sobrien 1440130561Sobrien /* Like TPREL16, but no overflow. */ 1441130561Sobrien HOWTO (R_PPC64_TPREL16_LO, 1442130561Sobrien 0, /* rightshift */ 1443130561Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 1444130561Sobrien 16, /* bitsize */ 1445130561Sobrien FALSE, /* pc_relative */ 1446130561Sobrien 0, /* bitpos */ 1447130561Sobrien complain_overflow_dont, /* complain_on_overflow */ 1448130561Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 1449130561Sobrien "R_PPC64_TPREL16_LO", /* name */ 1450130561Sobrien FALSE, /* partial_inplace */ 1451130561Sobrien 0, /* src_mask */ 1452130561Sobrien 0xffff, /* dst_mask */ 1453130561Sobrien FALSE), /* pcrel_offset */ 1454130561Sobrien 1455130561Sobrien /* Like TPREL16_LO, but next higher group of 16 bits. */ 1456130561Sobrien HOWTO (R_PPC64_TPREL16_HI, 1457130561Sobrien 16, /* rightshift */ 1458130561Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 1459130561Sobrien 16, /* bitsize */ 1460130561Sobrien FALSE, /* pc_relative */ 1461130561Sobrien 0, /* bitpos */ 1462130561Sobrien complain_overflow_dont, /* complain_on_overflow */ 1463130561Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 1464130561Sobrien "R_PPC64_TPREL16_HI", /* name */ 1465130561Sobrien FALSE, /* partial_inplace */ 1466130561Sobrien 0, /* src_mask */ 1467130561Sobrien 0xffff, /* dst_mask */ 1468130561Sobrien FALSE), /* pcrel_offset */ 1469130561Sobrien 1470130561Sobrien /* Like TPREL16_HI, but adjust for low 16 bits. */ 1471130561Sobrien HOWTO (R_PPC64_TPREL16_HA, 1472130561Sobrien 16, /* rightshift */ 1473130561Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 1474130561Sobrien 16, /* bitsize */ 1475130561Sobrien FALSE, /* pc_relative */ 1476130561Sobrien 0, /* bitpos */ 1477130561Sobrien complain_overflow_dont, /* complain_on_overflow */ 1478130561Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 1479130561Sobrien "R_PPC64_TPREL16_HA", /* name */ 1480130561Sobrien FALSE, /* partial_inplace */ 1481130561Sobrien 0, /* src_mask */ 1482130561Sobrien 0xffff, /* dst_mask */ 1483130561Sobrien FALSE), /* pcrel_offset */ 1484130561Sobrien 1485130561Sobrien /* Like TPREL16_HI, but next higher group of 16 bits. */ 1486130561Sobrien HOWTO (R_PPC64_TPREL16_HIGHER, 1487130561Sobrien 32, /* rightshift */ 1488130561Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 1489130561Sobrien 16, /* bitsize */ 1490130561Sobrien FALSE, /* pc_relative */ 1491130561Sobrien 0, /* bitpos */ 1492130561Sobrien complain_overflow_dont, /* complain_on_overflow */ 1493130561Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 1494130561Sobrien "R_PPC64_TPREL16_HIGHER", /* name */ 1495130561Sobrien FALSE, /* partial_inplace */ 1496130561Sobrien 0, /* src_mask */ 1497130561Sobrien 0xffff, /* dst_mask */ 1498130561Sobrien FALSE), /* pcrel_offset */ 1499130561Sobrien 1500130561Sobrien /* Like TPREL16_HIGHER, but adjust for low 16 bits. */ 1501130561Sobrien HOWTO (R_PPC64_TPREL16_HIGHERA, 1502130561Sobrien 32, /* rightshift */ 1503130561Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 1504130561Sobrien 16, /* bitsize */ 1505130561Sobrien FALSE, /* pc_relative */ 1506130561Sobrien 0, /* bitpos */ 1507130561Sobrien complain_overflow_dont, /* complain_on_overflow */ 1508130561Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 1509130561Sobrien "R_PPC64_TPREL16_HIGHERA", /* name */ 1510130561Sobrien FALSE, /* partial_inplace */ 1511130561Sobrien 0, /* src_mask */ 1512130561Sobrien 0xffff, /* dst_mask */ 1513130561Sobrien FALSE), /* pcrel_offset */ 1514130561Sobrien 1515130561Sobrien /* Like TPREL16_HIGHER, but next higher group of 16 bits. */ 1516130561Sobrien HOWTO (R_PPC64_TPREL16_HIGHEST, 1517130561Sobrien 48, /* rightshift */ 1518130561Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 1519130561Sobrien 16, /* bitsize */ 1520130561Sobrien FALSE, /* pc_relative */ 1521130561Sobrien 0, /* bitpos */ 1522130561Sobrien complain_overflow_dont, /* complain_on_overflow */ 1523130561Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 1524130561Sobrien "R_PPC64_TPREL16_HIGHEST", /* name */ 1525130561Sobrien FALSE, /* partial_inplace */ 1526130561Sobrien 0, /* src_mask */ 1527130561Sobrien 0xffff, /* dst_mask */ 1528130561Sobrien FALSE), /* pcrel_offset */ 1529130561Sobrien 1530130561Sobrien /* Like TPREL16_HIGHEST, but adjust for low 16 bits. */ 1531130561Sobrien HOWTO (R_PPC64_TPREL16_HIGHESTA, 1532130561Sobrien 48, /* rightshift */ 1533130561Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 1534130561Sobrien 16, /* bitsize */ 1535130561Sobrien FALSE, /* pc_relative */ 1536130561Sobrien 0, /* bitpos */ 1537130561Sobrien complain_overflow_dont, /* complain_on_overflow */ 1538130561Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 1539130561Sobrien "R_PPC64_TPREL16_HIGHESTA", /* name */ 1540130561Sobrien FALSE, /* partial_inplace */ 1541130561Sobrien 0, /* src_mask */ 1542130561Sobrien 0xffff, /* dst_mask */ 1543130561Sobrien FALSE), /* pcrel_offset */ 1544130561Sobrien 1545130561Sobrien /* Like TPREL16, but for insns with a DS field. */ 1546130561Sobrien HOWTO (R_PPC64_TPREL16_DS, 1547130561Sobrien 0, /* rightshift */ 1548130561Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 1549130561Sobrien 16, /* bitsize */ 1550130561Sobrien FALSE, /* pc_relative */ 1551130561Sobrien 0, /* bitpos */ 1552130561Sobrien complain_overflow_signed, /* complain_on_overflow */ 1553130561Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 1554130561Sobrien "R_PPC64_TPREL16_DS", /* name */ 1555130561Sobrien FALSE, /* partial_inplace */ 1556130561Sobrien 0, /* src_mask */ 1557130561Sobrien 0xfffc, /* dst_mask */ 1558130561Sobrien FALSE), /* pcrel_offset */ 1559130561Sobrien 1560130561Sobrien /* Like TPREL16_DS, but no overflow. */ 1561130561Sobrien HOWTO (R_PPC64_TPREL16_LO_DS, 1562130561Sobrien 0, /* rightshift */ 1563130561Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 1564130561Sobrien 16, /* bitsize */ 1565130561Sobrien FALSE, /* pc_relative */ 1566130561Sobrien 0, /* bitpos */ 1567130561Sobrien complain_overflow_dont, /* complain_on_overflow */ 1568130561Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 1569130561Sobrien "R_PPC64_TPREL16_LO_DS", /* name */ 1570130561Sobrien FALSE, /* partial_inplace */ 1571130561Sobrien 0, /* src_mask */ 1572130561Sobrien 0xfffc, /* dst_mask */ 1573130561Sobrien FALSE), /* pcrel_offset */ 1574130561Sobrien 1575130561Sobrien /* Allocates two contiguous entries in the GOT to hold a tls_index structure, 1576130561Sobrien with values (sym+add)@dtpmod and (sym+add)@dtprel, and computes the offset 1577130561Sobrien to the first entry relative to the TOC base (r2). */ 1578130561Sobrien HOWTO (R_PPC64_GOT_TLSGD16, 1579130561Sobrien 0, /* rightshift */ 1580130561Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 1581130561Sobrien 16, /* bitsize */ 1582130561Sobrien FALSE, /* pc_relative */ 1583130561Sobrien 0, /* bitpos */ 1584130561Sobrien complain_overflow_signed, /* complain_on_overflow */ 1585130561Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 1586130561Sobrien "R_PPC64_GOT_TLSGD16", /* name */ 1587130561Sobrien FALSE, /* partial_inplace */ 1588130561Sobrien 0, /* src_mask */ 1589130561Sobrien 0xffff, /* dst_mask */ 1590130561Sobrien FALSE), /* pcrel_offset */ 1591130561Sobrien 1592130561Sobrien /* Like GOT_TLSGD16, but no overflow. */ 1593130561Sobrien HOWTO (R_PPC64_GOT_TLSGD16_LO, 1594130561Sobrien 0, /* rightshift */ 1595130561Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 1596130561Sobrien 16, /* bitsize */ 1597130561Sobrien FALSE, /* pc_relative */ 1598130561Sobrien 0, /* bitpos */ 1599130561Sobrien complain_overflow_dont, /* complain_on_overflow */ 1600130561Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 1601130561Sobrien "R_PPC64_GOT_TLSGD16_LO", /* name */ 1602130561Sobrien FALSE, /* partial_inplace */ 1603130561Sobrien 0, /* src_mask */ 1604130561Sobrien 0xffff, /* dst_mask */ 1605130561Sobrien FALSE), /* pcrel_offset */ 1606130561Sobrien 1607130561Sobrien /* Like GOT_TLSGD16_LO, but next higher group of 16 bits. */ 1608130561Sobrien HOWTO (R_PPC64_GOT_TLSGD16_HI, 1609130561Sobrien 16, /* rightshift */ 1610130561Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 1611130561Sobrien 16, /* bitsize */ 1612130561Sobrien FALSE, /* pc_relative */ 1613130561Sobrien 0, /* bitpos */ 1614130561Sobrien complain_overflow_dont, /* complain_on_overflow */ 1615130561Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 1616130561Sobrien "R_PPC64_GOT_TLSGD16_HI", /* name */ 1617130561Sobrien FALSE, /* partial_inplace */ 1618130561Sobrien 0, /* src_mask */ 1619130561Sobrien 0xffff, /* dst_mask */ 1620130561Sobrien FALSE), /* pcrel_offset */ 1621130561Sobrien 1622130561Sobrien /* Like GOT_TLSGD16_HI, but adjust for low 16 bits. */ 1623130561Sobrien HOWTO (R_PPC64_GOT_TLSGD16_HA, 1624130561Sobrien 16, /* rightshift */ 1625130561Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 1626130561Sobrien 16, /* bitsize */ 1627130561Sobrien FALSE, /* pc_relative */ 1628130561Sobrien 0, /* bitpos */ 1629130561Sobrien complain_overflow_dont, /* complain_on_overflow */ 1630130561Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 1631130561Sobrien "R_PPC64_GOT_TLSGD16_HA", /* name */ 1632130561Sobrien FALSE, /* partial_inplace */ 1633130561Sobrien 0, /* src_mask */ 1634130561Sobrien 0xffff, /* dst_mask */ 1635130561Sobrien FALSE), /* pcrel_offset */ 1636130561Sobrien 1637130561Sobrien /* Allocates two contiguous entries in the GOT to hold a tls_index structure, 1638130561Sobrien with values (sym+add)@dtpmod and zero, and computes the offset to the 1639130561Sobrien first entry relative to the TOC base (r2). */ 1640130561Sobrien HOWTO (R_PPC64_GOT_TLSLD16, 1641130561Sobrien 0, /* rightshift */ 1642130561Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 1643130561Sobrien 16, /* bitsize */ 1644130561Sobrien FALSE, /* pc_relative */ 1645130561Sobrien 0, /* bitpos */ 1646130561Sobrien complain_overflow_signed, /* complain_on_overflow */ 1647130561Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 1648130561Sobrien "R_PPC64_GOT_TLSLD16", /* name */ 1649130561Sobrien FALSE, /* partial_inplace */ 1650130561Sobrien 0, /* src_mask */ 1651130561Sobrien 0xffff, /* dst_mask */ 1652130561Sobrien FALSE), /* pcrel_offset */ 1653130561Sobrien 1654130561Sobrien /* Like GOT_TLSLD16, but no overflow. */ 1655130561Sobrien HOWTO (R_PPC64_GOT_TLSLD16_LO, 1656130561Sobrien 0, /* rightshift */ 1657130561Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 1658130561Sobrien 16, /* bitsize */ 1659130561Sobrien FALSE, /* pc_relative */ 1660130561Sobrien 0, /* bitpos */ 1661130561Sobrien complain_overflow_dont, /* complain_on_overflow */ 1662130561Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 1663130561Sobrien "R_PPC64_GOT_TLSLD16_LO", /* name */ 1664130561Sobrien FALSE, /* partial_inplace */ 1665130561Sobrien 0, /* src_mask */ 1666130561Sobrien 0xffff, /* dst_mask */ 1667130561Sobrien FALSE), /* pcrel_offset */ 1668130561Sobrien 1669130561Sobrien /* Like GOT_TLSLD16_LO, but next higher group of 16 bits. */ 1670130561Sobrien HOWTO (R_PPC64_GOT_TLSLD16_HI, 1671130561Sobrien 16, /* rightshift */ 1672130561Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 1673130561Sobrien 16, /* bitsize */ 1674130561Sobrien FALSE, /* pc_relative */ 1675130561Sobrien 0, /* bitpos */ 1676130561Sobrien complain_overflow_dont, /* complain_on_overflow */ 1677130561Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 1678130561Sobrien "R_PPC64_GOT_TLSLD16_HI", /* name */ 1679130561Sobrien FALSE, /* partial_inplace */ 1680130561Sobrien 0, /* src_mask */ 1681130561Sobrien 0xffff, /* dst_mask */ 1682130561Sobrien FALSE), /* pcrel_offset */ 1683130561Sobrien 1684130561Sobrien /* Like GOT_TLSLD16_HI, but adjust for low 16 bits. */ 1685130561Sobrien HOWTO (R_PPC64_GOT_TLSLD16_HA, 1686130561Sobrien 16, /* rightshift */ 1687130561Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 1688130561Sobrien 16, /* bitsize */ 1689130561Sobrien FALSE, /* pc_relative */ 1690130561Sobrien 0, /* bitpos */ 1691130561Sobrien complain_overflow_dont, /* complain_on_overflow */ 1692130561Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 1693130561Sobrien "R_PPC64_GOT_TLSLD16_HA", /* name */ 1694130561Sobrien FALSE, /* partial_inplace */ 1695130561Sobrien 0, /* src_mask */ 1696130561Sobrien 0xffff, /* dst_mask */ 1697130561Sobrien FALSE), /* pcrel_offset */ 1698130561Sobrien 1699130561Sobrien /* Allocates an entry in the GOT with value (sym+add)@dtprel, and computes 1700130561Sobrien the offset to the entry relative to the TOC base (r2). */ 1701130561Sobrien HOWTO (R_PPC64_GOT_DTPREL16_DS, 1702130561Sobrien 0, /* rightshift */ 1703130561Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 1704130561Sobrien 16, /* bitsize */ 1705130561Sobrien FALSE, /* pc_relative */ 1706130561Sobrien 0, /* bitpos */ 1707130561Sobrien complain_overflow_signed, /* complain_on_overflow */ 1708130561Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 1709130561Sobrien "R_PPC64_GOT_DTPREL16_DS", /* name */ 1710130561Sobrien FALSE, /* partial_inplace */ 1711130561Sobrien 0, /* src_mask */ 1712130561Sobrien 0xfffc, /* dst_mask */ 1713130561Sobrien FALSE), /* pcrel_offset */ 1714130561Sobrien 1715130561Sobrien /* Like GOT_DTPREL16_DS, but no overflow. */ 1716130561Sobrien HOWTO (R_PPC64_GOT_DTPREL16_LO_DS, 1717130561Sobrien 0, /* rightshift */ 1718130561Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 1719130561Sobrien 16, /* bitsize */ 1720130561Sobrien FALSE, /* pc_relative */ 1721130561Sobrien 0, /* bitpos */ 1722130561Sobrien complain_overflow_dont, /* complain_on_overflow */ 1723130561Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 1724130561Sobrien "R_PPC64_GOT_DTPREL16_LO_DS", /* name */ 1725130561Sobrien FALSE, /* partial_inplace */ 1726130561Sobrien 0, /* src_mask */ 1727130561Sobrien 0xfffc, /* dst_mask */ 1728130561Sobrien FALSE), /* pcrel_offset */ 1729130561Sobrien 1730130561Sobrien /* Like GOT_DTPREL16_LO_DS, but next higher group of 16 bits. */ 1731130561Sobrien HOWTO (R_PPC64_GOT_DTPREL16_HI, 1732130561Sobrien 16, /* rightshift */ 1733130561Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 1734130561Sobrien 16, /* bitsize */ 1735130561Sobrien FALSE, /* pc_relative */ 1736130561Sobrien 0, /* bitpos */ 1737130561Sobrien complain_overflow_dont, /* complain_on_overflow */ 1738130561Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 1739130561Sobrien "R_PPC64_GOT_DTPREL16_HI", /* name */ 1740130561Sobrien FALSE, /* partial_inplace */ 1741130561Sobrien 0, /* src_mask */ 1742130561Sobrien 0xffff, /* dst_mask */ 1743130561Sobrien FALSE), /* pcrel_offset */ 1744130561Sobrien 1745130561Sobrien /* Like GOT_DTPREL16_HI, but adjust for low 16 bits. */ 1746130561Sobrien HOWTO (R_PPC64_GOT_DTPREL16_HA, 1747130561Sobrien 16, /* rightshift */ 1748130561Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 1749130561Sobrien 16, /* bitsize */ 1750130561Sobrien FALSE, /* pc_relative */ 1751130561Sobrien 0, /* bitpos */ 1752130561Sobrien complain_overflow_dont, /* complain_on_overflow */ 1753130561Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 1754130561Sobrien "R_PPC64_GOT_DTPREL16_HA", /* name */ 1755130561Sobrien FALSE, /* partial_inplace */ 1756130561Sobrien 0, /* src_mask */ 1757130561Sobrien 0xffff, /* dst_mask */ 1758130561Sobrien FALSE), /* pcrel_offset */ 1759130561Sobrien 1760130561Sobrien /* Allocates an entry in the GOT with value (sym+add)@tprel, and computes the 1761130561Sobrien offset to the entry relative to the TOC base (r2). */ 1762130561Sobrien HOWTO (R_PPC64_GOT_TPREL16_DS, 1763130561Sobrien 0, /* rightshift */ 1764130561Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 1765130561Sobrien 16, /* bitsize */ 1766130561Sobrien FALSE, /* pc_relative */ 1767130561Sobrien 0, /* bitpos */ 1768130561Sobrien complain_overflow_signed, /* complain_on_overflow */ 1769130561Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 1770130561Sobrien "R_PPC64_GOT_TPREL16_DS", /* name */ 1771130561Sobrien FALSE, /* partial_inplace */ 1772130561Sobrien 0, /* src_mask */ 1773130561Sobrien 0xfffc, /* dst_mask */ 1774130561Sobrien FALSE), /* pcrel_offset */ 1775130561Sobrien 1776130561Sobrien /* Like GOT_TPREL16_DS, but no overflow. */ 1777130561Sobrien HOWTO (R_PPC64_GOT_TPREL16_LO_DS, 1778130561Sobrien 0, /* rightshift */ 1779130561Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 1780130561Sobrien 16, /* bitsize */ 1781130561Sobrien FALSE, /* pc_relative */ 1782130561Sobrien 0, /* bitpos */ 1783130561Sobrien complain_overflow_dont, /* complain_on_overflow */ 1784130561Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 1785130561Sobrien "R_PPC64_GOT_TPREL16_LO_DS", /* name */ 1786130561Sobrien FALSE, /* partial_inplace */ 1787130561Sobrien 0, /* src_mask */ 1788130561Sobrien 0xfffc, /* dst_mask */ 1789130561Sobrien FALSE), /* pcrel_offset */ 1790130561Sobrien 1791130561Sobrien /* Like GOT_TPREL16_LO_DS, but next higher group of 16 bits. */ 1792130561Sobrien HOWTO (R_PPC64_GOT_TPREL16_HI, 1793130561Sobrien 16, /* rightshift */ 1794130561Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 1795130561Sobrien 16, /* bitsize */ 1796130561Sobrien FALSE, /* pc_relative */ 1797130561Sobrien 0, /* bitpos */ 1798130561Sobrien complain_overflow_dont, /* complain_on_overflow */ 1799130561Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 1800130561Sobrien "R_PPC64_GOT_TPREL16_HI", /* name */ 1801130561Sobrien FALSE, /* partial_inplace */ 1802130561Sobrien 0, /* src_mask */ 1803130561Sobrien 0xffff, /* dst_mask */ 1804130561Sobrien FALSE), /* pcrel_offset */ 1805130561Sobrien 1806130561Sobrien /* Like GOT_TPREL16_HI, but adjust for low 16 bits. */ 1807130561Sobrien HOWTO (R_PPC64_GOT_TPREL16_HA, 1808130561Sobrien 16, /* rightshift */ 1809130561Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 1810130561Sobrien 16, /* bitsize */ 1811130561Sobrien FALSE, /* pc_relative */ 1812130561Sobrien 0, /* bitpos */ 1813130561Sobrien complain_overflow_dont, /* complain_on_overflow */ 1814130561Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 1815130561Sobrien "R_PPC64_GOT_TPREL16_HA", /* name */ 1816130561Sobrien FALSE, /* partial_inplace */ 1817130561Sobrien 0, /* src_mask */ 1818130561Sobrien 0xffff, /* dst_mask */ 1819130561Sobrien FALSE), /* pcrel_offset */ 1820130561Sobrien 182189857Sobrien /* GNU extension to record C++ vtable hierarchy. */ 182289857Sobrien HOWTO (R_PPC64_GNU_VTINHERIT, /* type */ 182389857Sobrien 0, /* rightshift */ 182489857Sobrien 0, /* size (0 = byte, 1 = short, 2 = long) */ 182589857Sobrien 0, /* bitsize */ 1826130561Sobrien FALSE, /* pc_relative */ 182789857Sobrien 0, /* bitpos */ 182889857Sobrien complain_overflow_dont, /* complain_on_overflow */ 182989857Sobrien NULL, /* special_function */ 183089857Sobrien "R_PPC64_GNU_VTINHERIT", /* name */ 1831130561Sobrien FALSE, /* partial_inplace */ 183289857Sobrien 0, /* src_mask */ 183389857Sobrien 0, /* dst_mask */ 1834130561Sobrien FALSE), /* pcrel_offset */ 183589857Sobrien 183689857Sobrien /* GNU extension to record C++ vtable member usage. */ 183789857Sobrien HOWTO (R_PPC64_GNU_VTENTRY, /* type */ 183889857Sobrien 0, /* rightshift */ 183989857Sobrien 0, /* size (0 = byte, 1 = short, 2 = long) */ 184089857Sobrien 0, /* bitsize */ 1841130561Sobrien FALSE, /* pc_relative */ 184289857Sobrien 0, /* bitpos */ 184389857Sobrien complain_overflow_dont, /* complain_on_overflow */ 184489857Sobrien NULL, /* special_function */ 184589857Sobrien "R_PPC64_GNU_VTENTRY", /* name */ 1846130561Sobrien FALSE, /* partial_inplace */ 184789857Sobrien 0, /* src_mask */ 184889857Sobrien 0, /* dst_mask */ 1849130561Sobrien FALSE), /* pcrel_offset */ 185089857Sobrien}; 185189857Sobrien 185289857Sobrien 185389857Sobrien/* Initialize the ppc64_elf_howto_table, so that linear accesses can 185489857Sobrien be done. */ 185589857Sobrien 185689857Sobrienstatic void 1857130561Sobrienppc_howto_init (void) 185889857Sobrien{ 185989857Sobrien unsigned int i, type; 186089857Sobrien 186189857Sobrien for (i = 0; 186289857Sobrien i < sizeof (ppc64_elf_howto_raw) / sizeof (ppc64_elf_howto_raw[0]); 186389857Sobrien i++) 186489857Sobrien { 186589857Sobrien type = ppc64_elf_howto_raw[i].type; 186689857Sobrien BFD_ASSERT (type < (sizeof (ppc64_elf_howto_table) 186789857Sobrien / sizeof (ppc64_elf_howto_table[0]))); 186889857Sobrien ppc64_elf_howto_table[type] = &ppc64_elf_howto_raw[i]; 186989857Sobrien } 187089857Sobrien} 187189857Sobrien 187289857Sobrienstatic reloc_howto_type * 1873130561Sobrienppc64_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, 1874130561Sobrien bfd_reloc_code_real_type code) 187589857Sobrien{ 1876130561Sobrien enum elf_ppc64_reloc_type r = R_PPC64_NONE; 187789857Sobrien 187889857Sobrien if (!ppc64_elf_howto_table[R_PPC64_ADDR32]) 187989857Sobrien /* Initialize howto table if needed. */ 188089857Sobrien ppc_howto_init (); 188189857Sobrien 1882130561Sobrien switch (code) 188389857Sobrien { 188489857Sobrien default: 1885130561Sobrien return NULL; 188689857Sobrien 1887130561Sobrien case BFD_RELOC_NONE: r = R_PPC64_NONE; 188889857Sobrien break; 1889130561Sobrien case BFD_RELOC_32: r = R_PPC64_ADDR32; 189089857Sobrien break; 1891130561Sobrien case BFD_RELOC_PPC_BA26: r = R_PPC64_ADDR24; 189289857Sobrien break; 1893130561Sobrien case BFD_RELOC_16: r = R_PPC64_ADDR16; 189489857Sobrien break; 1895130561Sobrien case BFD_RELOC_LO16: r = R_PPC64_ADDR16_LO; 189689857Sobrien break; 1897130561Sobrien case BFD_RELOC_HI16: r = R_PPC64_ADDR16_HI; 189889857Sobrien break; 1899130561Sobrien case BFD_RELOC_HI16_S: r = R_PPC64_ADDR16_HA; 190089857Sobrien break; 1901130561Sobrien case BFD_RELOC_PPC_BA16: r = R_PPC64_ADDR14; 190289857Sobrien break; 1903130561Sobrien case BFD_RELOC_PPC_BA16_BRTAKEN: r = R_PPC64_ADDR14_BRTAKEN; 190489857Sobrien break; 1905130561Sobrien case BFD_RELOC_PPC_BA16_BRNTAKEN: r = R_PPC64_ADDR14_BRNTAKEN; 190689857Sobrien break; 1907130561Sobrien case BFD_RELOC_PPC_B26: r = R_PPC64_REL24; 190889857Sobrien break; 1909130561Sobrien case BFD_RELOC_PPC_B16: r = R_PPC64_REL14; 191089857Sobrien break; 1911130561Sobrien case BFD_RELOC_PPC_B16_BRTAKEN: r = R_PPC64_REL14_BRTAKEN; 191289857Sobrien break; 1913130561Sobrien case BFD_RELOC_PPC_B16_BRNTAKEN: r = R_PPC64_REL14_BRNTAKEN; 191489857Sobrien break; 1915130561Sobrien case BFD_RELOC_16_GOTOFF: r = R_PPC64_GOT16; 191689857Sobrien break; 1917130561Sobrien case BFD_RELOC_LO16_GOTOFF: r = R_PPC64_GOT16_LO; 191889857Sobrien break; 1919130561Sobrien case BFD_RELOC_HI16_GOTOFF: r = R_PPC64_GOT16_HI; 192089857Sobrien break; 1921130561Sobrien case BFD_RELOC_HI16_S_GOTOFF: r = R_PPC64_GOT16_HA; 192289857Sobrien break; 1923130561Sobrien case BFD_RELOC_PPC_COPY: r = R_PPC64_COPY; 192489857Sobrien break; 1925130561Sobrien case BFD_RELOC_PPC_GLOB_DAT: r = R_PPC64_GLOB_DAT; 192689857Sobrien break; 1927130561Sobrien case BFD_RELOC_32_PCREL: r = R_PPC64_REL32; 192889857Sobrien break; 1929130561Sobrien case BFD_RELOC_32_PLTOFF: r = R_PPC64_PLT32; 193089857Sobrien break; 1931130561Sobrien case BFD_RELOC_32_PLT_PCREL: r = R_PPC64_PLTREL32; 193289857Sobrien break; 1933130561Sobrien case BFD_RELOC_LO16_PLTOFF: r = R_PPC64_PLT16_LO; 193489857Sobrien break; 1935130561Sobrien case BFD_RELOC_HI16_PLTOFF: r = R_PPC64_PLT16_HI; 193689857Sobrien break; 1937130561Sobrien case BFD_RELOC_HI16_S_PLTOFF: r = R_PPC64_PLT16_HA; 193889857Sobrien break; 1939130561Sobrien case BFD_RELOC_16_BASEREL: r = R_PPC64_SECTOFF; 194089857Sobrien break; 1941130561Sobrien case BFD_RELOC_LO16_BASEREL: r = R_PPC64_SECTOFF_LO; 194289857Sobrien break; 1943130561Sobrien case BFD_RELOC_HI16_BASEREL: r = R_PPC64_SECTOFF_HI; 194489857Sobrien break; 1945130561Sobrien case BFD_RELOC_HI16_S_BASEREL: r = R_PPC64_SECTOFF_HA; 194689857Sobrien break; 1947130561Sobrien case BFD_RELOC_CTOR: r = R_PPC64_ADDR64; 194889857Sobrien break; 1949130561Sobrien case BFD_RELOC_64: r = R_PPC64_ADDR64; 195089857Sobrien break; 1951130561Sobrien case BFD_RELOC_PPC64_HIGHER: r = R_PPC64_ADDR16_HIGHER; 195289857Sobrien break; 1953130561Sobrien case BFD_RELOC_PPC64_HIGHER_S: r = R_PPC64_ADDR16_HIGHERA; 195489857Sobrien break; 1955130561Sobrien case BFD_RELOC_PPC64_HIGHEST: r = R_PPC64_ADDR16_HIGHEST; 195689857Sobrien break; 1957130561Sobrien case BFD_RELOC_PPC64_HIGHEST_S: r = R_PPC64_ADDR16_HIGHESTA; 195889857Sobrien break; 1959130561Sobrien case BFD_RELOC_64_PCREL: r = R_PPC64_REL64; 196089857Sobrien break; 1961130561Sobrien case BFD_RELOC_64_PLTOFF: r = R_PPC64_PLT64; 196289857Sobrien break; 1963130561Sobrien case BFD_RELOC_64_PLT_PCREL: r = R_PPC64_PLTREL64; 196489857Sobrien break; 1965130561Sobrien case BFD_RELOC_PPC_TOC16: r = R_PPC64_TOC16; 196689857Sobrien break; 1967130561Sobrien case BFD_RELOC_PPC64_TOC16_LO: r = R_PPC64_TOC16_LO; 196889857Sobrien break; 1969130561Sobrien case BFD_RELOC_PPC64_TOC16_HI: r = R_PPC64_TOC16_HI; 197089857Sobrien break; 1971130561Sobrien case BFD_RELOC_PPC64_TOC16_HA: r = R_PPC64_TOC16_HA; 197289857Sobrien break; 1973130561Sobrien case BFD_RELOC_PPC64_TOC: r = R_PPC64_TOC; 197489857Sobrien break; 1975130561Sobrien case BFD_RELOC_PPC64_PLTGOT16: r = R_PPC64_PLTGOT16; 197689857Sobrien break; 1977130561Sobrien case BFD_RELOC_PPC64_PLTGOT16_LO: r = R_PPC64_PLTGOT16_LO; 197889857Sobrien break; 1979130561Sobrien case BFD_RELOC_PPC64_PLTGOT16_HI: r = R_PPC64_PLTGOT16_HI; 198089857Sobrien break; 1981130561Sobrien case BFD_RELOC_PPC64_PLTGOT16_HA: r = R_PPC64_PLTGOT16_HA; 198289857Sobrien break; 1983130561Sobrien case BFD_RELOC_PPC64_ADDR16_DS: r = R_PPC64_ADDR16_DS; 198489857Sobrien break; 1985130561Sobrien case BFD_RELOC_PPC64_ADDR16_LO_DS: r = R_PPC64_ADDR16_LO_DS; 198689857Sobrien break; 1987130561Sobrien case BFD_RELOC_PPC64_GOT16_DS: r = R_PPC64_GOT16_DS; 198889857Sobrien break; 1989130561Sobrien case BFD_RELOC_PPC64_GOT16_LO_DS: r = R_PPC64_GOT16_LO_DS; 199089857Sobrien break; 1991130561Sobrien case BFD_RELOC_PPC64_PLT16_LO_DS: r = R_PPC64_PLT16_LO_DS; 199289857Sobrien break; 1993130561Sobrien case BFD_RELOC_PPC64_SECTOFF_DS: r = R_PPC64_SECTOFF_DS; 199489857Sobrien break; 1995130561Sobrien case BFD_RELOC_PPC64_SECTOFF_LO_DS: r = R_PPC64_SECTOFF_LO_DS; 199689857Sobrien break; 1997130561Sobrien case BFD_RELOC_PPC64_TOC16_DS: r = R_PPC64_TOC16_DS; 199889857Sobrien break; 1999130561Sobrien case BFD_RELOC_PPC64_TOC16_LO_DS: r = R_PPC64_TOC16_LO_DS; 200089857Sobrien break; 2001130561Sobrien case BFD_RELOC_PPC64_PLTGOT16_DS: r = R_PPC64_PLTGOT16_DS; 200289857Sobrien break; 2003130561Sobrien case BFD_RELOC_PPC64_PLTGOT16_LO_DS: r = R_PPC64_PLTGOT16_LO_DS; 200489857Sobrien break; 2005130561Sobrien case BFD_RELOC_PPC_TLS: r = R_PPC64_TLS; 200689857Sobrien break; 2007130561Sobrien case BFD_RELOC_PPC_DTPMOD: r = R_PPC64_DTPMOD64; 200889857Sobrien break; 2009130561Sobrien case BFD_RELOC_PPC_TPREL16: r = R_PPC64_TPREL16; 2010130561Sobrien break; 2011130561Sobrien case BFD_RELOC_PPC_TPREL16_LO: r = R_PPC64_TPREL16_LO; 2012130561Sobrien break; 2013130561Sobrien case BFD_RELOC_PPC_TPREL16_HI: r = R_PPC64_TPREL16_HI; 2014130561Sobrien break; 2015130561Sobrien case BFD_RELOC_PPC_TPREL16_HA: r = R_PPC64_TPREL16_HA; 2016130561Sobrien break; 2017130561Sobrien case BFD_RELOC_PPC_TPREL: r = R_PPC64_TPREL64; 2018130561Sobrien break; 2019130561Sobrien case BFD_RELOC_PPC_DTPREL16: r = R_PPC64_DTPREL16; 2020130561Sobrien break; 2021130561Sobrien case BFD_RELOC_PPC_DTPREL16_LO: r = R_PPC64_DTPREL16_LO; 2022130561Sobrien break; 2023130561Sobrien case BFD_RELOC_PPC_DTPREL16_HI: r = R_PPC64_DTPREL16_HI; 2024130561Sobrien break; 2025130561Sobrien case BFD_RELOC_PPC_DTPREL16_HA: r = R_PPC64_DTPREL16_HA; 2026130561Sobrien break; 2027130561Sobrien case BFD_RELOC_PPC_DTPREL: r = R_PPC64_DTPREL64; 2028130561Sobrien break; 2029130561Sobrien case BFD_RELOC_PPC_GOT_TLSGD16: r = R_PPC64_GOT_TLSGD16; 2030130561Sobrien break; 2031130561Sobrien case BFD_RELOC_PPC_GOT_TLSGD16_LO: r = R_PPC64_GOT_TLSGD16_LO; 2032130561Sobrien break; 2033130561Sobrien case BFD_RELOC_PPC_GOT_TLSGD16_HI: r = R_PPC64_GOT_TLSGD16_HI; 2034130561Sobrien break; 2035130561Sobrien case BFD_RELOC_PPC_GOT_TLSGD16_HA: r = R_PPC64_GOT_TLSGD16_HA; 2036130561Sobrien break; 2037130561Sobrien case BFD_RELOC_PPC_GOT_TLSLD16: r = R_PPC64_GOT_TLSLD16; 2038130561Sobrien break; 2039130561Sobrien case BFD_RELOC_PPC_GOT_TLSLD16_LO: r = R_PPC64_GOT_TLSLD16_LO; 2040130561Sobrien break; 2041130561Sobrien case BFD_RELOC_PPC_GOT_TLSLD16_HI: r = R_PPC64_GOT_TLSLD16_HI; 2042130561Sobrien break; 2043130561Sobrien case BFD_RELOC_PPC_GOT_TLSLD16_HA: r = R_PPC64_GOT_TLSLD16_HA; 2044130561Sobrien break; 2045130561Sobrien case BFD_RELOC_PPC_GOT_TPREL16: r = R_PPC64_GOT_TPREL16_DS; 2046130561Sobrien break; 2047130561Sobrien case BFD_RELOC_PPC_GOT_TPREL16_LO: r = R_PPC64_GOT_TPREL16_LO_DS; 2048130561Sobrien break; 2049130561Sobrien case BFD_RELOC_PPC_GOT_TPREL16_HI: r = R_PPC64_GOT_TPREL16_HI; 2050130561Sobrien break; 2051130561Sobrien case BFD_RELOC_PPC_GOT_TPREL16_HA: r = R_PPC64_GOT_TPREL16_HA; 2052130561Sobrien break; 2053130561Sobrien case BFD_RELOC_PPC_GOT_DTPREL16: r = R_PPC64_GOT_DTPREL16_DS; 2054130561Sobrien break; 2055130561Sobrien case BFD_RELOC_PPC_GOT_DTPREL16_LO: r = R_PPC64_GOT_DTPREL16_LO_DS; 2056130561Sobrien break; 2057130561Sobrien case BFD_RELOC_PPC_GOT_DTPREL16_HI: r = R_PPC64_GOT_DTPREL16_HI; 2058130561Sobrien break; 2059130561Sobrien case BFD_RELOC_PPC_GOT_DTPREL16_HA: r = R_PPC64_GOT_DTPREL16_HA; 2060130561Sobrien break; 2061130561Sobrien case BFD_RELOC_PPC64_TPREL16_DS: r = R_PPC64_TPREL16_DS; 2062130561Sobrien break; 2063130561Sobrien case BFD_RELOC_PPC64_TPREL16_LO_DS: r = R_PPC64_TPREL16_LO_DS; 2064130561Sobrien break; 2065130561Sobrien case BFD_RELOC_PPC64_TPREL16_HIGHER: r = R_PPC64_TPREL16_HIGHER; 2066130561Sobrien break; 2067130561Sobrien case BFD_RELOC_PPC64_TPREL16_HIGHERA: r = R_PPC64_TPREL16_HIGHERA; 2068130561Sobrien break; 2069130561Sobrien case BFD_RELOC_PPC64_TPREL16_HIGHEST: r = R_PPC64_TPREL16_HIGHEST; 2070130561Sobrien break; 2071130561Sobrien case BFD_RELOC_PPC64_TPREL16_HIGHESTA: r = R_PPC64_TPREL16_HIGHESTA; 2072130561Sobrien break; 2073130561Sobrien case BFD_RELOC_PPC64_DTPREL16_DS: r = R_PPC64_DTPREL16_DS; 2074130561Sobrien break; 2075130561Sobrien case BFD_RELOC_PPC64_DTPREL16_LO_DS: r = R_PPC64_DTPREL16_LO_DS; 2076130561Sobrien break; 2077130561Sobrien case BFD_RELOC_PPC64_DTPREL16_HIGHER: r = R_PPC64_DTPREL16_HIGHER; 2078130561Sobrien break; 2079130561Sobrien case BFD_RELOC_PPC64_DTPREL16_HIGHERA: r = R_PPC64_DTPREL16_HIGHERA; 2080130561Sobrien break; 2081130561Sobrien case BFD_RELOC_PPC64_DTPREL16_HIGHEST: r = R_PPC64_DTPREL16_HIGHEST; 2082130561Sobrien break; 2083130561Sobrien case BFD_RELOC_PPC64_DTPREL16_HIGHESTA: r = R_PPC64_DTPREL16_HIGHESTA; 2084130561Sobrien break; 2085130561Sobrien case BFD_RELOC_VTABLE_INHERIT: r = R_PPC64_GNU_VTINHERIT; 2086130561Sobrien break; 2087130561Sobrien case BFD_RELOC_VTABLE_ENTRY: r = R_PPC64_GNU_VTENTRY; 2088130561Sobrien break; 208989857Sobrien } 209089857Sobrien 2091130561Sobrien return ppc64_elf_howto_table[r]; 209289857Sobrien}; 209389857Sobrien 209489857Sobrien/* Set the howto pointer for a PowerPC ELF reloc. */ 209589857Sobrien 209689857Sobrienstatic void 2097130561Sobrienppc64_elf_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr, 2098130561Sobrien Elf_Internal_Rela *dst) 209989857Sobrien{ 210089857Sobrien unsigned int type; 210189857Sobrien 2102104834Sobrien /* Initialize howto table if needed. */ 210389857Sobrien if (!ppc64_elf_howto_table[R_PPC64_ADDR32]) 210489857Sobrien ppc_howto_init (); 210589857Sobrien 210689857Sobrien type = ELF64_R_TYPE (dst->r_info); 210789857Sobrien BFD_ASSERT (type < (sizeof (ppc64_elf_howto_table) 210889857Sobrien / sizeof (ppc64_elf_howto_table[0]))); 210989857Sobrien cache_ptr->howto = ppc64_elf_howto_table[type]; 211089857Sobrien} 211189857Sobrien 2112130561Sobrien/* Handle the R_PPC64_ADDR16_HA and similar relocs. */ 211389857Sobrien 211489857Sobrienstatic bfd_reloc_status_type 2115130561Sobrienppc64_elf_ha_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, 2116130561Sobrien void *data, asection *input_section, 2117130561Sobrien bfd *output_bfd, char **error_message) 211889857Sobrien{ 211999461Sobrien /* If this is a relocatable link (output_bfd test tells us), just 212099461Sobrien call the generic function. Any adjustment will be done at final 212199461Sobrien link time. */ 212299461Sobrien if (output_bfd != NULL) 2123104834Sobrien return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, 212499461Sobrien input_section, output_bfd, error_message); 212589857Sobrien 212699461Sobrien /* Adjust the addend for sign extension of the low 16 bits. 212799461Sobrien We won't actually be using the low 16 bits, so trashing them 212899461Sobrien doesn't matter. */ 212999461Sobrien reloc_entry->addend += 0x8000; 213099461Sobrien return bfd_reloc_continue; 213199461Sobrien} 213299461Sobrien 213399461Sobrienstatic bfd_reloc_status_type 2134130561Sobrienppc64_elf_brtaken_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, 2135130561Sobrien void *data, asection *input_section, 2136130561Sobrien bfd *output_bfd, char **error_message) 213799461Sobrien{ 213899461Sobrien long insn; 2139130561Sobrien enum elf_ppc64_reloc_type r_type; 214099461Sobrien bfd_size_type octets; 214199461Sobrien /* Disabled until we sort out how ld should choose 'y' vs 'at'. */ 2142130561Sobrien bfd_boolean is_power4 = FALSE; 214399461Sobrien 214499461Sobrien /* If this is a relocatable link (output_bfd test tells us), just 214599461Sobrien call the generic function. Any adjustment will be done at final 214699461Sobrien link time. */ 214789857Sobrien if (output_bfd != NULL) 2148104834Sobrien return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, 214999461Sobrien input_section, output_bfd, error_message); 215099461Sobrien 215199461Sobrien octets = reloc_entry->address * bfd_octets_per_byte (abfd); 215299461Sobrien insn = bfd_get_32 (abfd, (bfd_byte *) data + octets); 215399461Sobrien insn &= ~(0x01 << 21); 2154130561Sobrien r_type = reloc_entry->howto->type; 215599461Sobrien if (r_type == R_PPC64_ADDR14_BRTAKEN 215699461Sobrien || r_type == R_PPC64_REL14_BRTAKEN) 2157104834Sobrien insn |= 0x01 << 21; /* 'y' or 't' bit, lowest bit of BO field. */ 215899461Sobrien 215999461Sobrien if (is_power4) 216089857Sobrien { 216199461Sobrien /* Set 'a' bit. This is 0b00010 in BO field for branch 216299461Sobrien on CR(BI) insns (BO == 001at or 011at), and 0b01000 216399461Sobrien for branch on CTR insns (BO == 1a00t or 1a01t). */ 216499461Sobrien if ((insn & (0x14 << 21)) == (0x04 << 21)) 216599461Sobrien insn |= 0x02 << 21; 216699461Sobrien else if ((insn & (0x14 << 21)) == (0x10 << 21)) 216799461Sobrien insn |= 0x08 << 21; 216899461Sobrien else 216999461Sobrien return bfd_reloc_continue; 217089857Sobrien } 217199461Sobrien else 217299461Sobrien { 217399461Sobrien bfd_vma target = 0; 217499461Sobrien bfd_vma from; 217589857Sobrien 217699461Sobrien if (!bfd_is_com_section (symbol->section)) 217799461Sobrien target = symbol->value; 217899461Sobrien target += symbol->section->output_section->vma; 217999461Sobrien target += symbol->section->output_offset; 218099461Sobrien target += reloc_entry->addend; 218189857Sobrien 218299461Sobrien from = (reloc_entry->address 218399461Sobrien + input_section->output_offset 218499461Sobrien + input_section->output_section->vma); 218589857Sobrien 218699461Sobrien /* Invert 'y' bit if not the default. */ 218799461Sobrien if ((bfd_signed_vma) (target - from) < 0) 218899461Sobrien insn ^= 0x01 << 21; 218999461Sobrien } 2190130561Sobrien bfd_put_32 (abfd, insn, (bfd_byte *) data + octets); 219199461Sobrien return bfd_reloc_continue; 219299461Sobrien} 219389857Sobrien 219499461Sobrienstatic bfd_reloc_status_type 2195130561Sobrienppc64_elf_sectoff_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, 2196130561Sobrien void *data, asection *input_section, 2197130561Sobrien bfd *output_bfd, char **error_message) 219899461Sobrien{ 219999461Sobrien /* If this is a relocatable link (output_bfd test tells us), just 220099461Sobrien call the generic function. Any adjustment will be done at final 220199461Sobrien link time. */ 220299461Sobrien if (output_bfd != NULL) 2203104834Sobrien return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, 220499461Sobrien input_section, output_bfd, error_message); 220589857Sobrien 220699461Sobrien /* Subtract the symbol section base address. */ 220799461Sobrien reloc_entry->addend -= symbol->section->output_section->vma; 220889857Sobrien return bfd_reloc_continue; 220989857Sobrien} 221089857Sobrien 221199461Sobrienstatic bfd_reloc_status_type 2212130561Sobrienppc64_elf_sectoff_ha_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, 2213130561Sobrien void *data, asection *input_section, 2214130561Sobrien bfd *output_bfd, char **error_message) 221599461Sobrien{ 221699461Sobrien /* If this is a relocatable link (output_bfd test tells us), just 221799461Sobrien call the generic function. Any adjustment will be done at final 221899461Sobrien link time. */ 221999461Sobrien if (output_bfd != NULL) 2220104834Sobrien return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, 222199461Sobrien input_section, output_bfd, error_message); 222299461Sobrien 222399461Sobrien /* Subtract the symbol section base address. */ 222499461Sobrien reloc_entry->addend -= symbol->section->output_section->vma; 222599461Sobrien 222699461Sobrien /* Adjust the addend for sign extension of the low 16 bits. */ 222799461Sobrien reloc_entry->addend += 0x8000; 222899461Sobrien return bfd_reloc_continue; 222999461Sobrien} 223099461Sobrien 223199461Sobrienstatic bfd_reloc_status_type 2232130561Sobrienppc64_elf_toc_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, 2233130561Sobrien void *data, asection *input_section, 2234130561Sobrien bfd *output_bfd, char **error_message) 223599461Sobrien{ 223699461Sobrien bfd_vma TOCstart; 223799461Sobrien 223899461Sobrien /* If this is a relocatable link (output_bfd test tells us), just 223999461Sobrien call the generic function. Any adjustment will be done at final 224099461Sobrien link time. */ 224199461Sobrien if (output_bfd != NULL) 2242104834Sobrien return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, 224399461Sobrien input_section, output_bfd, error_message); 224499461Sobrien 224599461Sobrien TOCstart = _bfd_get_gp_value (input_section->output_section->owner); 224699461Sobrien if (TOCstart == 0) 224799461Sobrien TOCstart = ppc64_elf_toc (input_section->output_section->owner); 224899461Sobrien 224999461Sobrien /* Subtract the TOC base address. */ 225099461Sobrien reloc_entry->addend -= TOCstart + TOC_BASE_OFF; 225199461Sobrien return bfd_reloc_continue; 225299461Sobrien} 225399461Sobrien 225499461Sobrienstatic bfd_reloc_status_type 2255130561Sobrienppc64_elf_toc_ha_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, 2256130561Sobrien void *data, asection *input_section, 2257130561Sobrien bfd *output_bfd, char **error_message) 225899461Sobrien{ 225999461Sobrien bfd_vma TOCstart; 226099461Sobrien 226199461Sobrien /* If this is a relocatable link (output_bfd test tells us), just 226299461Sobrien call the generic function. Any adjustment will be done at final 226399461Sobrien link time. */ 226499461Sobrien if (output_bfd != NULL) 2265104834Sobrien return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, 226699461Sobrien input_section, output_bfd, error_message); 226799461Sobrien 226899461Sobrien TOCstart = _bfd_get_gp_value (input_section->output_section->owner); 226999461Sobrien if (TOCstart == 0) 227099461Sobrien TOCstart = ppc64_elf_toc (input_section->output_section->owner); 227199461Sobrien 227299461Sobrien /* Subtract the TOC base address. */ 227399461Sobrien reloc_entry->addend -= TOCstart + TOC_BASE_OFF; 227499461Sobrien 227599461Sobrien /* Adjust the addend for sign extension of the low 16 bits. */ 227699461Sobrien reloc_entry->addend += 0x8000; 227799461Sobrien return bfd_reloc_continue; 227899461Sobrien} 227999461Sobrien 228099461Sobrienstatic bfd_reloc_status_type 2281130561Sobrienppc64_elf_toc64_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, 2282130561Sobrien void *data, asection *input_section, 2283130561Sobrien bfd *output_bfd, char **error_message) 228499461Sobrien{ 228599461Sobrien bfd_vma TOCstart; 228699461Sobrien bfd_size_type octets; 228799461Sobrien 228899461Sobrien /* If this is a relocatable link (output_bfd test tells us), just 228999461Sobrien call the generic function. Any adjustment will be done at final 229099461Sobrien link time. */ 229199461Sobrien if (output_bfd != NULL) 2292104834Sobrien return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, 229399461Sobrien input_section, output_bfd, error_message); 229499461Sobrien 229599461Sobrien TOCstart = _bfd_get_gp_value (input_section->output_section->owner); 229699461Sobrien if (TOCstart == 0) 229799461Sobrien TOCstart = ppc64_elf_toc (input_section->output_section->owner); 229899461Sobrien 229999461Sobrien octets = reloc_entry->address * bfd_octets_per_byte (abfd); 230099461Sobrien bfd_put_64 (abfd, TOCstart + TOC_BASE_OFF, (bfd_byte *) data + octets); 230199461Sobrien return bfd_reloc_ok; 230299461Sobrien} 230399461Sobrien 230499461Sobrienstatic bfd_reloc_status_type 2305130561Sobrienppc64_elf_unhandled_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, 2306130561Sobrien void *data, asection *input_section, 2307130561Sobrien bfd *output_bfd, char **error_message) 230899461Sobrien{ 230999461Sobrien /* If this is a relocatable link (output_bfd test tells us), just 231099461Sobrien call the generic function. Any adjustment will be done at final 231199461Sobrien link time. */ 231299461Sobrien if (output_bfd != NULL) 2313104834Sobrien return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, 231499461Sobrien input_section, output_bfd, error_message); 231599461Sobrien 231699461Sobrien if (error_message != NULL) 231799461Sobrien { 231899461Sobrien static char buf[60]; 231999461Sobrien sprintf (buf, "generic linker can't handle %s", 232099461Sobrien reloc_entry->howto->name); 232199461Sobrien *error_message = buf; 232299461Sobrien } 232399461Sobrien return bfd_reloc_dangerous; 232499461Sobrien} 232599461Sobrien 2326130561Sobrienstruct ppc64_elf_obj_tdata 2327130561Sobrien{ 2328130561Sobrien struct elf_obj_tdata elf; 2329130561Sobrien 2330130561Sobrien /* Shortcuts to dynamic linker sections. */ 2331130561Sobrien asection *got; 2332130561Sobrien asection *relgot; 2333130561Sobrien 2334130561Sobrien /* TLS local dynamic got entry handling. Suppose for multiple GOT 2335130561Sobrien sections means we potentially need one of these for each input bfd. */ 2336130561Sobrien union { 2337130561Sobrien bfd_signed_vma refcount; 2338130561Sobrien bfd_vma offset; 2339130561Sobrien } tlsld_got; 2340130561Sobrien}; 2341130561Sobrien 2342130561Sobrien#define ppc64_elf_tdata(bfd) \ 2343130561Sobrien ((struct ppc64_elf_obj_tdata *) (bfd)->tdata.any) 2344130561Sobrien 2345130561Sobrien#define ppc64_tlsld_got(bfd) \ 2346130561Sobrien (&ppc64_elf_tdata (bfd)->tlsld_got) 2347130561Sobrien 2348130561Sobrien/* Override the generic function because we store some extras. */ 2349130561Sobrien 2350130561Sobrienstatic bfd_boolean 2351130561Sobrienppc64_elf_mkobject (bfd *abfd) 2352130561Sobrien{ 2353130561Sobrien bfd_size_type amt = sizeof (struct ppc64_elf_obj_tdata); 2354130561Sobrien abfd->tdata.any = bfd_zalloc (abfd, amt); 2355130561Sobrien if (abfd->tdata.any == NULL) 2356130561Sobrien return FALSE; 2357130561Sobrien return TRUE; 2358130561Sobrien} 2359130561Sobrien 2360104834Sobrien/* Fix bad default arch selected for a 64 bit input bfd when the 2361104834Sobrien default is 32 bit. */ 236289857Sobrien 2363130561Sobrienstatic bfd_boolean 2364130561Sobrienppc64_elf_object_p (bfd *abfd) 236589857Sobrien{ 2366104834Sobrien if (abfd->arch_info->the_default && abfd->arch_info->bits_per_word == 32) 2367104834Sobrien { 2368104834Sobrien Elf_Internal_Ehdr *i_ehdr = elf_elfheader (abfd); 236989857Sobrien 2370104834Sobrien if (i_ehdr->e_ident[EI_CLASS] == ELFCLASS64) 2371104834Sobrien { 2372104834Sobrien /* Relies on arch after 32 bit default being 64 bit default. */ 2373104834Sobrien abfd->arch_info = abfd->arch_info->next; 2374104834Sobrien BFD_ASSERT (abfd->arch_info->bits_per_word == 64); 2375104834Sobrien } 2376104834Sobrien } 2377130561Sobrien return TRUE; 237889857Sobrien} 237989857Sobrien 2380130561Sobrien/* Support for core dump NOTE sections. */ 2381130561Sobrien 2382130561Sobrienstatic bfd_boolean 2383130561Sobrienppc64_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) 2384130561Sobrien{ 2385130561Sobrien size_t offset, raw_size; 2386130561Sobrien 2387130561Sobrien if (note->descsz != 504) 2388130561Sobrien return FALSE; 2389130561Sobrien 2390130561Sobrien /* pr_cursig */ 2391130561Sobrien elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12); 2392130561Sobrien 2393130561Sobrien /* pr_pid */ 2394130561Sobrien elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, note->descdata + 32); 2395130561Sobrien 2396130561Sobrien /* pr_reg */ 2397130561Sobrien offset = 112; 2398130561Sobrien raw_size = 384; 2399130561Sobrien 2400130561Sobrien /* Make a ".reg/999" section. */ 2401130561Sobrien return _bfd_elfcore_make_pseudosection (abfd, ".reg", 2402130561Sobrien raw_size, note->descpos + offset); 2403130561Sobrien} 2404130561Sobrien 2405130561Sobrienstatic bfd_boolean 2406130561Sobrienppc64_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) 2407130561Sobrien{ 2408130561Sobrien if (note->descsz != 136) 2409130561Sobrien return FALSE; 2410130561Sobrien 2411130561Sobrien elf_tdata (abfd)->core_program 2412130561Sobrien = _bfd_elfcore_strndup (abfd, note->descdata + 40, 16); 2413130561Sobrien elf_tdata (abfd)->core_command 2414130561Sobrien = _bfd_elfcore_strndup (abfd, note->descdata + 56, 80); 2415130561Sobrien 2416130561Sobrien return TRUE; 2417130561Sobrien} 2418130561Sobrien 241989857Sobrien/* Merge backend specific data from an object file to the output 242089857Sobrien object file when linking. */ 2421104834Sobrien 2422130561Sobrienstatic bfd_boolean 2423130561Sobrienppc64_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd) 242489857Sobrien{ 242589857Sobrien /* Check if we have the same endianess. */ 242689857Sobrien if (ibfd->xvec->byteorder != obfd->xvec->byteorder 2427107492Sobrien && ibfd->xvec->byteorder != BFD_ENDIAN_UNKNOWN 242889857Sobrien && obfd->xvec->byteorder != BFD_ENDIAN_UNKNOWN) 242989857Sobrien { 243089857Sobrien const char *msg; 243189857Sobrien 243289857Sobrien if (bfd_big_endian (ibfd)) 2433130561Sobrien msg = _("%s: compiled for a big endian system " 2434130561Sobrien "and target is little endian"); 243589857Sobrien else 2436130561Sobrien msg = _("%s: compiled for a little endian system " 2437130561Sobrien "and target is big endian"); 243889857Sobrien 243989857Sobrien (*_bfd_error_handler) (msg, bfd_archive_filename (ibfd)); 244089857Sobrien 244189857Sobrien bfd_set_error (bfd_error_wrong_format); 2442130561Sobrien return FALSE; 244389857Sobrien } 244489857Sobrien 2445130561Sobrien return TRUE; 244689857Sobrien} 2447130561Sobrien 2448130561Sobrien/* Add extra PPC sections. */ 2449130561Sobrien 2450130561Sobrienstatic struct bfd_elf_special_section const ppc64_elf_special_sections[]= 2451130561Sobrien{ 2452130561Sobrien { ".sdata", 6, -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE }, 2453130561Sobrien { ".sbss", 5, -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE }, 2454130561Sobrien { ".plt", 4, 0, SHT_NOBITS, 0 }, 2455130561Sobrien { ".toc", 4, 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE }, 2456130561Sobrien { ".toc1", 5, 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE }, 2457130561Sobrien { ".tocbss", 7, 0, SHT_NOBITS, SHF_ALLOC + SHF_WRITE }, 2458130561Sobrien { NULL, 0, 0, 0, 0 } 2459130561Sobrien}; 2460130561Sobrien 2461130561Sobrienstruct _ppc64_elf_section_data 2462130561Sobrien{ 2463130561Sobrien struct bfd_elf_section_data elf; 2464130561Sobrien 2465130561Sobrien /* An array with one entry for each opd function descriptor. */ 2466130561Sobrien union 2467130561Sobrien { 2468130561Sobrien /* Points to the function code section for local opd entries. */ 2469130561Sobrien asection **func_sec; 2470130561Sobrien /* After editing .opd, adjust references to opd local syms. */ 2471130561Sobrien long *adjust; 2472130561Sobrien } opd; 2473130561Sobrien 2474130561Sobrien /* An array for toc sections, indexed by offset/8. 2475130561Sobrien Specifies the relocation symbol index used at a given toc offset. */ 2476130561Sobrien unsigned *t_symndx; 2477130561Sobrien}; 2478130561Sobrien 2479130561Sobrien#define ppc64_elf_section_data(sec) \ 2480130561Sobrien ((struct _ppc64_elf_section_data *) elf_section_data (sec)) 2481130561Sobrien 2482130561Sobrienstatic bfd_boolean 2483130561Sobrienppc64_elf_new_section_hook (bfd *abfd, asection *sec) 2484130561Sobrien{ 2485130561Sobrien struct _ppc64_elf_section_data *sdata; 2486130561Sobrien bfd_size_type amt = sizeof (*sdata); 2487130561Sobrien 2488130561Sobrien sdata = bfd_zalloc (abfd, amt); 2489130561Sobrien if (sdata == NULL) 2490130561Sobrien return FALSE; 2491130561Sobrien sec->used_by_bfd = sdata; 2492130561Sobrien 2493130561Sobrien return _bfd_elf_new_section_hook (abfd, sec); 2494130561Sobrien} 249589857Sobrien 249689857Sobrien/* The following functions are specific to the ELF linker, while 249789857Sobrien functions above are used generally. Those named ppc64_elf_* are 249889857Sobrien called by the main ELF linker code. They appear in this file more 249989857Sobrien or less in the order in which they are called. eg. 250089857Sobrien ppc64_elf_check_relocs is called early in the link process, 250189857Sobrien ppc64_elf_finish_dynamic_sections is one of the last functions 250289857Sobrien called. 250389857Sobrien 250489857Sobrien PowerPC64-ELF uses a similar scheme to PowerPC64-XCOFF in that 250589857Sobrien functions have both a function code symbol and a function descriptor 250689857Sobrien symbol. A call to foo in a relocatable object file looks like: 250789857Sobrien 250889857Sobrien . .text 250989857Sobrien . x: 251089857Sobrien . bl .foo 251189857Sobrien . nop 251289857Sobrien 251389857Sobrien The function definition in another object file might be: 251489857Sobrien 251589857Sobrien . .section .opd 251689857Sobrien . foo: .quad .foo 251789857Sobrien . .quad .TOC.@tocbase 251889857Sobrien . .quad 0 251989857Sobrien . 252089857Sobrien . .text 252189857Sobrien . .foo: blr 252289857Sobrien 252389857Sobrien When the linker resolves the call during a static link, the branch 252489857Sobrien unsurprisingly just goes to .foo and the .opd information is unused. 252589857Sobrien If the function definition is in a shared library, things are a little 252689857Sobrien different: The call goes via a plt call stub, the opd information gets 252789857Sobrien copied to the plt, and the linker patches the nop. 252889857Sobrien 252989857Sobrien . x: 253089857Sobrien . bl .foo_stub 253189857Sobrien . ld 2,40(1) 253289857Sobrien . 253389857Sobrien . 253489857Sobrien . .foo_stub: 253589857Sobrien . addis 12,2,Lfoo@toc@ha # in practice, the call stub 2536130561Sobrien . addi 12,12,Lfoo@toc@l # is slightly optimized, but 253789857Sobrien . std 2,40(1) # this is the general idea 253889857Sobrien . ld 11,0(12) 253989857Sobrien . ld 2,8(12) 254089857Sobrien . mtctr 11 254189857Sobrien . ld 11,16(12) 254289857Sobrien . bctr 254389857Sobrien . 254489857Sobrien . .section .plt 254589857Sobrien . Lfoo: reloc (R_PPC64_JMP_SLOT, foo) 254689857Sobrien 254789857Sobrien The "reloc ()" notation is supposed to indicate that the linker emits 254889857Sobrien an R_PPC64_JMP_SLOT reloc against foo. The dynamic linker does the opd 254989857Sobrien copying. 255089857Sobrien 255189857Sobrien What are the difficulties here? Well, firstly, the relocations 255289857Sobrien examined by the linker in check_relocs are against the function code 255389857Sobrien sym .foo, while the dynamic relocation in the plt is emitted against 255489857Sobrien the function descriptor symbol, foo. Somewhere along the line, we need 255589857Sobrien to carefully copy dynamic link information from one symbol to the other. 255689857Sobrien Secondly, the generic part of the elf linker will make .foo a dynamic 255789857Sobrien symbol as is normal for most other backends. We need foo dynamic 255889857Sobrien instead, at least for an application final link. However, when 255989857Sobrien creating a shared library containing foo, we need to have both symbols 256089857Sobrien dynamic so that references to .foo are satisfied during the early 256189857Sobrien stages of linking. Otherwise the linker might decide to pull in a 256289857Sobrien definition from some other object, eg. a static library. */ 256389857Sobrien 256489857Sobrien/* The linker needs to keep track of the number of relocs that it 256589857Sobrien decides to copy as dynamic relocs in check_relocs for each symbol. 256689857Sobrien This is so that it can later discard them if they are found to be 256789857Sobrien unnecessary. We store the information in a field extending the 256889857Sobrien regular ELF linker hash table. */ 256989857Sobrien 257089857Sobrienstruct ppc_dyn_relocs 257189857Sobrien{ 257289857Sobrien struct ppc_dyn_relocs *next; 257389857Sobrien 257489857Sobrien /* The input section of the reloc. */ 257589857Sobrien asection *sec; 257689857Sobrien 257789857Sobrien /* Total number of relocs copied for the input section. */ 257889857Sobrien bfd_size_type count; 257989857Sobrien 258089857Sobrien /* Number of pc-relative relocs copied for the input section. */ 258189857Sobrien bfd_size_type pc_count; 258289857Sobrien}; 258389857Sobrien 2584130561Sobrien/* Track GOT entries needed for a given symbol. We might need more 2585130561Sobrien than one got entry per symbol. */ 2586130561Sobrienstruct got_entry 2587130561Sobrien{ 2588130561Sobrien struct got_entry *next; 2589130561Sobrien 2590130561Sobrien /* The symbol addend that we'll be placing in the GOT. */ 2591130561Sobrien bfd_vma addend; 2592130561Sobrien 2593130561Sobrien /* Unlike other ELF targets, we use separate GOT entries for the same 2594130561Sobrien symbol referenced from different input files. This is to support 2595130561Sobrien automatic multiple TOC/GOT sections, where the TOC base can vary 2596130561Sobrien from one input file to another. 2597130561Sobrien 2598130561Sobrien Point to the BFD owning this GOT entry. */ 2599130561Sobrien bfd *owner; 2600130561Sobrien 2601130561Sobrien /* Zero for non-tls entries, or TLS_TLS and one of TLS_GD, TLS_LD, 2602130561Sobrien TLS_TPREL or TLS_DTPREL for tls entries. */ 2603130561Sobrien char tls_type; 2604130561Sobrien 2605130561Sobrien /* Reference count until size_dynamic_sections, GOT offset thereafter. */ 2606130561Sobrien union 2607130561Sobrien { 2608130561Sobrien bfd_signed_vma refcount; 2609130561Sobrien bfd_vma offset; 2610130561Sobrien } got; 2611130561Sobrien}; 2612130561Sobrien 2613130561Sobrien/* The same for PLT. */ 2614130561Sobrienstruct plt_entry 2615130561Sobrien{ 2616130561Sobrien struct plt_entry *next; 2617130561Sobrien 2618130561Sobrien bfd_vma addend; 2619130561Sobrien 2620130561Sobrien union 2621130561Sobrien { 2622130561Sobrien bfd_signed_vma refcount; 2623130561Sobrien bfd_vma offset; 2624130561Sobrien } plt; 2625130561Sobrien}; 2626130561Sobrien 262789857Sobrien/* Of those relocs that might be copied as dynamic relocs, this macro 2628130561Sobrien selects those that must be copied when linking a shared library, 2629130561Sobrien even when the symbol is local. */ 263089857Sobrien 2631130561Sobrien#define MUST_BE_DYN_RELOC(RTYPE) \ 2632104834Sobrien ((RTYPE) != R_PPC64_REL32 \ 2633104834Sobrien && (RTYPE) != R_PPC64_REL64 \ 2634130561Sobrien && (RTYPE) != R_PPC64_REL30) 263589857Sobrien 2636130561Sobrien/* If ELIMINATE_COPY_RELOCS is non-zero, the linker will try to avoid 2637130561Sobrien copying dynamic variables from a shared lib into an app's dynbss 2638130561Sobrien section, and instead use a dynamic relocation to point into the 2639130561Sobrien shared lib. With code that gcc generates, it's vital that this be 2640130561Sobrien enabled; In the PowerPC64 ABI, the address of a function is actually 2641130561Sobrien the address of a function descriptor, which resides in the .opd 2642130561Sobrien section. gcc uses the descriptor directly rather than going via the 2643130561Sobrien GOT as some other ABI's do, which means that initialized function 2644130561Sobrien pointers must reference the descriptor. Thus, a function pointer 2645130561Sobrien initialized to the address of a function in a shared library will 2646130561Sobrien either require a copy reloc, or a dynamic reloc. Using a copy reloc 2647130561Sobrien redefines the function descriptor symbol to point to the copy. This 2648130561Sobrien presents a problem as a plt entry for that function is also 2649130561Sobrien initialized from the function descriptor symbol and the copy reloc 2650130561Sobrien may not be initialized first. */ 2651130561Sobrien#define ELIMINATE_COPY_RELOCS 1 2652130561Sobrien 2653104834Sobrien/* Section name for stubs is the associated section name plus this 2654104834Sobrien string. */ 2655104834Sobrien#define STUB_SUFFIX ".stub" 265689857Sobrien 2657104834Sobrien/* Linker stubs. 2658104834Sobrien ppc_stub_long_branch: 2659104834Sobrien Used when a 14 bit branch (or even a 24 bit branch) can't reach its 2660104834Sobrien destination, but a 24 bit branch in a stub section will reach. 2661104834Sobrien . b dest 2662104834Sobrien 2663104834Sobrien ppc_stub_plt_branch: 2664104834Sobrien Similar to the above, but a 24 bit branch in the stub section won't 2665104834Sobrien reach its destination. 2666107492Sobrien . addis %r12,%r2,xxx@toc@ha 2667107492Sobrien . ld %r11,xxx@toc@l(%r12) 2668104834Sobrien . mtctr %r11 2669104834Sobrien . bctr 2670104834Sobrien 2671104834Sobrien ppc_stub_plt_call: 2672104834Sobrien Used to call a function in a shared library. 2673107492Sobrien . addis %r12,%r2,xxx@toc@ha 2674104834Sobrien . std %r2,40(%r1) 2675107492Sobrien . ld %r11,xxx+0@toc@l(%r12) 2676107492Sobrien . ld %r2,xxx+8@toc@l(%r12) 2677104834Sobrien . mtctr %r11 2678107492Sobrien . ld %r11,xxx+16@toc@l(%r12) 2679104834Sobrien . bctr 2680130561Sobrien 2681130561Sobrien ppc_stub_long_branch and ppc_stub_plt_branch may also have additional 2682130561Sobrien code to adjust the value and save r2 to support multiple toc sections. 2683130561Sobrien A ppc_stub_long_branch with an r2 offset looks like: 2684130561Sobrien . std %r2,40(%r1) 2685130561Sobrien . addis %r2,%r2,off@ha 2686130561Sobrien . addi %r2,%r2,off@l 2687130561Sobrien . b dest 2688130561Sobrien 2689130561Sobrien A ppc_stub_plt_branch with an r2 offset looks like: 2690130561Sobrien . std %r2,40(%r1) 2691130561Sobrien . addis %r12,%r2,xxx@toc@ha 2692130561Sobrien . ld %r11,xxx@toc@l(%r12) 2693130561Sobrien . addis %r2,%r2,off@ha 2694130561Sobrien . addi %r2,%r2,off@l 2695130561Sobrien . mtctr %r11 2696130561Sobrien . bctr 2697104834Sobrien*/ 2698104834Sobrien 2699104834Sobrienenum ppc_stub_type { 2700104834Sobrien ppc_stub_none, 2701104834Sobrien ppc_stub_long_branch, 2702130561Sobrien ppc_stub_long_branch_r2off, 2703104834Sobrien ppc_stub_plt_branch, 2704130561Sobrien ppc_stub_plt_branch_r2off, 2705104834Sobrien ppc_stub_plt_call 2706104834Sobrien}; 2707104834Sobrien 2708104834Sobrienstruct ppc_stub_hash_entry { 2709104834Sobrien 2710104834Sobrien /* Base hash table entry structure. */ 2711104834Sobrien struct bfd_hash_entry root; 2712104834Sobrien 2713130561Sobrien enum ppc_stub_type stub_type; 2714130561Sobrien 2715104834Sobrien /* The stub section. */ 2716104834Sobrien asection *stub_sec; 2717104834Sobrien 2718104834Sobrien /* Offset within stub_sec of the beginning of this stub. */ 2719104834Sobrien bfd_vma stub_offset; 2720104834Sobrien 2721104834Sobrien /* Given the symbol's value and its section we can determine its final 2722104834Sobrien value when building the stubs (so the stub knows where to jump. */ 2723104834Sobrien bfd_vma target_value; 2724104834Sobrien asection *target_section; 2725104834Sobrien 2726104834Sobrien /* The symbol table entry, if any, that this was derived from. */ 2727104834Sobrien struct ppc_link_hash_entry *h; 2728104834Sobrien 2729130561Sobrien /* And the reloc addend that this was derived from. */ 2730130561Sobrien bfd_vma addend; 2731130561Sobrien 2732104834Sobrien /* Where this stub is being called from, or, in the case of combined 2733104834Sobrien stub sections, the first input section in the group. */ 2734104834Sobrien asection *id_sec; 2735104834Sobrien}; 2736104834Sobrien 2737104834Sobrienstruct ppc_branch_hash_entry { 2738104834Sobrien 2739104834Sobrien /* Base hash table entry structure. */ 2740104834Sobrien struct bfd_hash_entry root; 2741104834Sobrien 2742104834Sobrien /* Offset within .branch_lt. */ 2743104834Sobrien unsigned int offset; 2744104834Sobrien 2745104834Sobrien /* Generation marker. */ 2746104834Sobrien unsigned int iter; 2747104834Sobrien}; 2748104834Sobrien 274989857Sobrienstruct ppc_link_hash_entry 275089857Sobrien{ 275189857Sobrien struct elf_link_hash_entry elf; 275289857Sobrien 2753104834Sobrien /* A pointer to the most recently used stub hash entry against this 2754104834Sobrien symbol. */ 2755104834Sobrien struct ppc_stub_hash_entry *stub_cache; 2756104834Sobrien 275789857Sobrien /* Track dynamic relocs copied for this symbol. */ 275889857Sobrien struct ppc_dyn_relocs *dyn_relocs; 275989857Sobrien 2760104834Sobrien /* Link between function code and descriptor symbols. */ 2761104834Sobrien struct elf_link_hash_entry *oh; 2762104834Sobrien 276389857Sobrien /* Flag function code and descriptor symbols. */ 276489857Sobrien unsigned int is_func:1; 276589857Sobrien unsigned int is_func_descriptor:1; 2766104834Sobrien unsigned int is_entry:1; 2767130561Sobrien 2768130561Sobrien /* Whether global opd sym has been adjusted or not. */ 2769130561Sobrien unsigned int adjust_done:1; 2770130561Sobrien 2771130561Sobrien /* Contexts in which symbol is used in the GOT (or TOC). 2772130561Sobrien TLS_GD .. TLS_EXPLICIT bits are or'd into the mask as the 2773130561Sobrien corresponding relocs are encountered during check_relocs. 2774130561Sobrien tls_optimize clears TLS_GD .. TLS_TPREL when optimizing to 2775130561Sobrien indicate the corresponding GOT entry type is not needed. 2776130561Sobrien tls_optimize may also set TLS_TPRELGD when a GD reloc turns into 2777130561Sobrien a TPREL one. We use a separate flag rather than setting TPREL 2778130561Sobrien just for convenience in distinguishing the two cases. */ 2779130561Sobrien#define TLS_GD 1 /* GD reloc. */ 2780130561Sobrien#define TLS_LD 2 /* LD reloc. */ 2781130561Sobrien#define TLS_TPREL 4 /* TPREL reloc, => IE. */ 2782130561Sobrien#define TLS_DTPREL 8 /* DTPREL reloc, => LD. */ 2783130561Sobrien#define TLS_TLS 16 /* Any TLS reloc. */ 2784130561Sobrien#define TLS_EXPLICIT 32 /* Marks TOC section TLS relocs. */ 2785130561Sobrien#define TLS_TPRELGD 64 /* TPREL reloc resulting from GD->IE. */ 2786130561Sobrien char tls_mask; 278789857Sobrien}; 278889857Sobrien 278989857Sobrien/* ppc64 ELF linker hash table. */ 279089857Sobrien 279189857Sobrienstruct ppc_link_hash_table 279289857Sobrien{ 279389857Sobrien struct elf_link_hash_table elf; 279489857Sobrien 2795104834Sobrien /* The stub hash table. */ 2796104834Sobrien struct bfd_hash_table stub_hash_table; 2797104834Sobrien 2798104834Sobrien /* Another hash table for plt_branch stubs. */ 2799104834Sobrien struct bfd_hash_table branch_hash_table; 2800104834Sobrien 2801104834Sobrien /* Linker stub bfd. */ 2802104834Sobrien bfd *stub_bfd; 2803104834Sobrien 2804104834Sobrien /* Linker call-backs. */ 2805130561Sobrien asection * (*add_stub_section) (const char *, asection *); 2806130561Sobrien void (*layout_sections_again) (void); 2807104834Sobrien 2808104834Sobrien /* Array to keep track of which stub sections have been created, and 2809104834Sobrien information on stub grouping. */ 2810104834Sobrien struct map_stub { 2811104834Sobrien /* This is the section to which stubs in the group will be attached. */ 2812104834Sobrien asection *link_sec; 2813104834Sobrien /* The stub section. */ 2814104834Sobrien asection *stub_sec; 2815130561Sobrien /* Along with elf_gp, specifies the TOC pointer used in this group. */ 2816130561Sobrien bfd_vma toc_off; 2817104834Sobrien } *stub_group; 2818104834Sobrien 2819130561Sobrien /* Support for multiple toc sections. */ 2820130561Sobrien unsigned int no_multi_toc; 2821130561Sobrien unsigned int multi_toc_needed; 2822130561Sobrien 2823130561Sobrien /* Temp used when calculating TOC pointers. */ 2824130561Sobrien bfd_vma toc_curr; 2825130561Sobrien 2826130561Sobrien /* Highest input section id. */ 2827130561Sobrien int top_id; 2828130561Sobrien 2829130561Sobrien /* Highest output section index. */ 2830104834Sobrien int top_index; 2831130561Sobrien 2832130561Sobrien /* List of input sections for each output section. */ 2833104834Sobrien asection **input_list; 2834104834Sobrien 283589857Sobrien /* Short-cuts to get to dynamic linker sections. */ 2836130561Sobrien asection *got; 2837130561Sobrien asection *plt; 2838130561Sobrien asection *relplt; 2839130561Sobrien asection *dynbss; 2840130561Sobrien asection *relbss; 2841130561Sobrien asection *glink; 284292828Sobrien asection *sfpr; 2843130561Sobrien asection *brlt; 2844130561Sobrien asection *relbrlt; 284589857Sobrien 2846130561Sobrien /* Shortcut to .__tls_get_addr. */ 2847130561Sobrien struct elf_link_hash_entry *tls_get_addr; 2848130561Sobrien 2849130561Sobrien /* Statistics. */ 2850130561Sobrien unsigned long stub_count[ppc_stub_plt_call]; 2851130561Sobrien 2852130561Sobrien /* Set if we should emit symbols for stubs. */ 2853130561Sobrien unsigned int emit_stub_syms; 2854130561Sobrien 285589857Sobrien /* Set on error. */ 2856104834Sobrien unsigned int stub_error; 285789857Sobrien 2858104834Sobrien /* Flag set when small branches are detected. Used to 2859104834Sobrien select suitable defaults for the stub group size. */ 2860104834Sobrien unsigned int has_14bit_branch; 2861104834Sobrien 286299461Sobrien /* Set if we detect a reference undefined weak symbol. */ 286399461Sobrien unsigned int have_undefweak; 286499461Sobrien 2865104834Sobrien /* Incremented every time we size stubs. */ 2866104834Sobrien unsigned int stub_iteration; 2867104834Sobrien 286889857Sobrien /* Small local sym to section mapping cache. */ 286989857Sobrien struct sym_sec_cache sym_sec; 287089857Sobrien}; 287189857Sobrien 287289857Sobrien/* Get the ppc64 ELF linker hash table from a link_info structure. */ 287389857Sobrien 287489857Sobrien#define ppc_hash_table(p) \ 287589857Sobrien ((struct ppc_link_hash_table *) ((p)->hash)) 287689857Sobrien 2877104834Sobrien#define ppc_stub_hash_lookup(table, string, create, copy) \ 2878104834Sobrien ((struct ppc_stub_hash_entry *) \ 2879104834Sobrien bfd_hash_lookup ((table), (string), (create), (copy))) 2880104834Sobrien 2881104834Sobrien#define ppc_branch_hash_lookup(table, string, create, copy) \ 2882104834Sobrien ((struct ppc_branch_hash_entry *) \ 2883104834Sobrien bfd_hash_lookup ((table), (string), (create), (copy))) 2884104834Sobrien 2885104834Sobrien/* Create an entry in the stub hash table. */ 2886104834Sobrien 2887104834Sobrienstatic struct bfd_hash_entry * 2888130561Sobrienstub_hash_newfunc (struct bfd_hash_entry *entry, 2889130561Sobrien struct bfd_hash_table *table, 2890130561Sobrien const char *string) 2891104834Sobrien{ 2892104834Sobrien /* Allocate the structure if it has not already been allocated by a 2893104834Sobrien subclass. */ 2894104834Sobrien if (entry == NULL) 2895104834Sobrien { 2896104834Sobrien entry = bfd_hash_allocate (table, sizeof (struct ppc_stub_hash_entry)); 2897104834Sobrien if (entry == NULL) 2898104834Sobrien return entry; 2899104834Sobrien } 2900104834Sobrien 2901104834Sobrien /* Call the allocation method of the superclass. */ 2902104834Sobrien entry = bfd_hash_newfunc (entry, table, string); 2903104834Sobrien if (entry != NULL) 2904104834Sobrien { 2905104834Sobrien struct ppc_stub_hash_entry *eh; 2906104834Sobrien 2907104834Sobrien /* Initialize the local fields. */ 2908104834Sobrien eh = (struct ppc_stub_hash_entry *) entry; 2909130561Sobrien eh->stub_type = ppc_stub_none; 2910104834Sobrien eh->stub_sec = NULL; 2911104834Sobrien eh->stub_offset = 0; 2912104834Sobrien eh->target_value = 0; 2913104834Sobrien eh->target_section = NULL; 2914104834Sobrien eh->h = NULL; 2915104834Sobrien eh->id_sec = NULL; 2916104834Sobrien } 2917104834Sobrien 2918104834Sobrien return entry; 2919104834Sobrien} 2920104834Sobrien 2921104834Sobrien/* Create an entry in the branch hash table. */ 2922104834Sobrien 2923104834Sobrienstatic struct bfd_hash_entry * 2924130561Sobrienbranch_hash_newfunc (struct bfd_hash_entry *entry, 2925130561Sobrien struct bfd_hash_table *table, 2926130561Sobrien const char *string) 2927104834Sobrien{ 2928104834Sobrien /* Allocate the structure if it has not already been allocated by a 2929104834Sobrien subclass. */ 2930104834Sobrien if (entry == NULL) 2931104834Sobrien { 2932104834Sobrien entry = bfd_hash_allocate (table, sizeof (struct ppc_branch_hash_entry)); 2933104834Sobrien if (entry == NULL) 2934104834Sobrien return entry; 2935104834Sobrien } 2936104834Sobrien 2937104834Sobrien /* Call the allocation method of the superclass. */ 2938104834Sobrien entry = bfd_hash_newfunc (entry, table, string); 2939104834Sobrien if (entry != NULL) 2940104834Sobrien { 2941104834Sobrien struct ppc_branch_hash_entry *eh; 2942104834Sobrien 2943104834Sobrien /* Initialize the local fields. */ 2944104834Sobrien eh = (struct ppc_branch_hash_entry *) entry; 2945104834Sobrien eh->offset = 0; 2946104834Sobrien eh->iter = 0; 2947104834Sobrien } 2948104834Sobrien 2949104834Sobrien return entry; 2950104834Sobrien} 2951104834Sobrien 295289857Sobrien/* Create an entry in a ppc64 ELF linker hash table. */ 295389857Sobrien 295489857Sobrienstatic struct bfd_hash_entry * 2955130561Sobrienlink_hash_newfunc (struct bfd_hash_entry *entry, 2956130561Sobrien struct bfd_hash_table *table, 2957130561Sobrien const char *string) 295889857Sobrien{ 295989857Sobrien /* Allocate the structure if it has not already been allocated by a 296089857Sobrien subclass. */ 296189857Sobrien if (entry == NULL) 296289857Sobrien { 296389857Sobrien entry = bfd_hash_allocate (table, sizeof (struct ppc_link_hash_entry)); 296489857Sobrien if (entry == NULL) 296589857Sobrien return entry; 296689857Sobrien } 296789857Sobrien 296889857Sobrien /* Call the allocation method of the superclass. */ 296989857Sobrien entry = _bfd_elf_link_hash_newfunc (entry, table, string); 297089857Sobrien if (entry != NULL) 297189857Sobrien { 297289857Sobrien struct ppc_link_hash_entry *eh = (struct ppc_link_hash_entry *) entry; 297389857Sobrien 2974104834Sobrien eh->stub_cache = NULL; 297589857Sobrien eh->dyn_relocs = NULL; 2976104834Sobrien eh->oh = NULL; 297789857Sobrien eh->is_func = 0; 297889857Sobrien eh->is_func_descriptor = 0; 2979104834Sobrien eh->is_entry = 0; 2980130561Sobrien eh->adjust_done = 0; 2981130561Sobrien eh->tls_mask = 0; 298289857Sobrien } 298389857Sobrien 298489857Sobrien return entry; 298589857Sobrien} 298689857Sobrien 298789857Sobrien/* Create a ppc64 ELF linker hash table. */ 298889857Sobrien 298989857Sobrienstatic struct bfd_link_hash_table * 2990130561Sobrienppc64_elf_link_hash_table_create (bfd *abfd) 299189857Sobrien{ 299289857Sobrien struct ppc_link_hash_table *htab; 299389857Sobrien bfd_size_type amt = sizeof (struct ppc_link_hash_table); 299489857Sobrien 2995130561Sobrien htab = bfd_zmalloc (amt); 299689857Sobrien if (htab == NULL) 299789857Sobrien return NULL; 299889857Sobrien 299989857Sobrien if (! _bfd_elf_link_hash_table_init (&htab->elf, abfd, link_hash_newfunc)) 300089857Sobrien { 3001104834Sobrien free (htab); 300289857Sobrien return NULL; 300389857Sobrien } 300489857Sobrien 3005104834Sobrien /* Init the stub hash table too. */ 3006104834Sobrien if (!bfd_hash_table_init (&htab->stub_hash_table, stub_hash_newfunc)) 3007104834Sobrien return NULL; 3008104834Sobrien 3009104834Sobrien /* And the branch hash table. */ 3010104834Sobrien if (!bfd_hash_table_init (&htab->branch_hash_table, branch_hash_newfunc)) 3011104834Sobrien return NULL; 3012104834Sobrien 3013130561Sobrien /* Initializing two fields of the union is just cosmetic. We really 3014130561Sobrien only care about glist, but when compiled on a 32-bit host the 3015130561Sobrien bfd_vma fields are larger. Setting the bfd_vma to zero makes 3016130561Sobrien debugger inspection of these fields look nicer. */ 3017130561Sobrien htab->elf.init_refcount.refcount = 0; 3018130561Sobrien htab->elf.init_refcount.glist = NULL; 3019130561Sobrien htab->elf.init_offset.offset = 0; 3020130561Sobrien htab->elf.init_offset.glist = NULL; 302189857Sobrien 302289857Sobrien return &htab->elf.root; 302389857Sobrien} 302489857Sobrien 3025104834Sobrien/* Free the derived linker hash table. */ 3026104834Sobrien 3027104834Sobrienstatic void 3028130561Sobrienppc64_elf_link_hash_table_free (struct bfd_link_hash_table *hash) 3029104834Sobrien{ 3030104834Sobrien struct ppc_link_hash_table *ret = (struct ppc_link_hash_table *) hash; 3031104834Sobrien 3032104834Sobrien bfd_hash_table_free (&ret->stub_hash_table); 3033104834Sobrien bfd_hash_table_free (&ret->branch_hash_table); 3034104834Sobrien _bfd_generic_link_hash_table_free (hash); 3035104834Sobrien} 3036104834Sobrien 3037130561Sobrien/* Satisfy the ELF linker by filling in some fields in our fake bfd. */ 3038130561Sobrien 3039130561Sobrienvoid 3040130561Sobrienppc64_elf_init_stub_bfd (bfd *abfd, struct bfd_link_info *info) 3041130561Sobrien{ 3042130561Sobrien struct ppc_link_hash_table *htab; 3043130561Sobrien 3044130561Sobrien elf_elfheader (abfd)->e_ident[EI_CLASS] = ELFCLASS64; 3045130561Sobrien 3046130561Sobrien/* Always hook our dynamic sections into the first bfd, which is the 3047130561Sobrien linker created stub bfd. This ensures that the GOT header is at 3048130561Sobrien the start of the output TOC section. */ 3049130561Sobrien htab = ppc_hash_table (info); 3050130561Sobrien htab->stub_bfd = abfd; 3051130561Sobrien htab->elf.dynobj = abfd; 3052130561Sobrien} 3053130561Sobrien 3054104834Sobrien/* Build a name for an entry in the stub hash table. */ 3055104834Sobrien 3056104834Sobrienstatic char * 3057130561Sobrienppc_stub_name (const asection *input_section, 3058130561Sobrien const asection *sym_sec, 3059130561Sobrien const struct ppc_link_hash_entry *h, 3060130561Sobrien const Elf_Internal_Rela *rel) 3061104834Sobrien{ 3062104834Sobrien char *stub_name; 3063104834Sobrien bfd_size_type len; 3064104834Sobrien 3065104834Sobrien /* rel->r_addend is actually 64 bit, but who uses more than +/- 2^31 3066104834Sobrien offsets from a sym as a branch target? In fact, we could 3067104834Sobrien probably assume the addend is always zero. */ 3068104834Sobrien BFD_ASSERT (((int) rel->r_addend & 0xffffffff) == rel->r_addend); 3069104834Sobrien 3070104834Sobrien if (h) 3071104834Sobrien { 3072104834Sobrien len = 8 + 1 + strlen (h->elf.root.root.string) + 1 + 8 + 1; 3073104834Sobrien stub_name = bfd_malloc (len); 3074104834Sobrien if (stub_name != NULL) 3075104834Sobrien { 3076130561Sobrien sprintf (stub_name, "%08x.%s+%x", 3077104834Sobrien input_section->id & 0xffffffff, 3078104834Sobrien h->elf.root.root.string, 3079104834Sobrien (int) rel->r_addend & 0xffffffff); 3080104834Sobrien } 3081104834Sobrien } 3082104834Sobrien else 3083104834Sobrien { 3084130561Sobrien len = 8 + 1 + 8 + 1 + 8 + 1 + 8 + 1; 3085104834Sobrien stub_name = bfd_malloc (len); 3086104834Sobrien if (stub_name != NULL) 3087104834Sobrien { 3088130561Sobrien sprintf (stub_name, "%08x.%x:%x+%x", 3089104834Sobrien input_section->id & 0xffffffff, 3090104834Sobrien sym_sec->id & 0xffffffff, 3091104834Sobrien (int) ELF64_R_SYM (rel->r_info) & 0xffffffff, 3092104834Sobrien (int) rel->r_addend & 0xffffffff); 3093104834Sobrien } 3094104834Sobrien } 3095104834Sobrien return stub_name; 3096104834Sobrien} 3097104834Sobrien 3098104834Sobrien/* Look up an entry in the stub hash. Stub entries are cached because 3099104834Sobrien creating the stub name takes a bit of time. */ 3100104834Sobrien 3101104834Sobrienstatic struct ppc_stub_hash_entry * 3102130561Sobrienppc_get_stub_entry (const asection *input_section, 3103130561Sobrien const asection *sym_sec, 3104130561Sobrien struct elf_link_hash_entry *hash, 3105130561Sobrien const Elf_Internal_Rela *rel, 3106130561Sobrien struct ppc_link_hash_table *htab) 3107104834Sobrien{ 3108104834Sobrien struct ppc_stub_hash_entry *stub_entry; 3109104834Sobrien struct ppc_link_hash_entry *h = (struct ppc_link_hash_entry *) hash; 3110104834Sobrien const asection *id_sec; 3111104834Sobrien 3112104834Sobrien /* If this input section is part of a group of sections sharing one 3113104834Sobrien stub section, then use the id of the first section in the group. 3114104834Sobrien Stub names need to include a section id, as there may well be 3115104834Sobrien more than one stub used to reach say, printf, and we need to 3116104834Sobrien distinguish between them. */ 3117104834Sobrien id_sec = htab->stub_group[input_section->id].link_sec; 3118104834Sobrien 3119104834Sobrien if (h != NULL && h->stub_cache != NULL 3120104834Sobrien && h->stub_cache->h == h 3121104834Sobrien && h->stub_cache->id_sec == id_sec) 3122104834Sobrien { 3123104834Sobrien stub_entry = h->stub_cache; 3124104834Sobrien } 3125104834Sobrien else 3126104834Sobrien { 3127104834Sobrien char *stub_name; 3128104834Sobrien 3129104834Sobrien stub_name = ppc_stub_name (id_sec, sym_sec, h, rel); 3130104834Sobrien if (stub_name == NULL) 3131104834Sobrien return NULL; 3132104834Sobrien 3133104834Sobrien stub_entry = ppc_stub_hash_lookup (&htab->stub_hash_table, 3134130561Sobrien stub_name, FALSE, FALSE); 3135104834Sobrien if (h != NULL) 3136104834Sobrien h->stub_cache = stub_entry; 3137104834Sobrien 3138104834Sobrien free (stub_name); 3139104834Sobrien } 3140104834Sobrien 3141104834Sobrien return stub_entry; 3142104834Sobrien} 3143104834Sobrien 3144104834Sobrien/* Add a new stub entry to the stub hash. Not all fields of the new 3145104834Sobrien stub entry are initialised. */ 3146104834Sobrien 3147104834Sobrienstatic struct ppc_stub_hash_entry * 3148130561Sobrienppc_add_stub (const char *stub_name, 3149130561Sobrien asection *section, 3150130561Sobrien struct ppc_link_hash_table *htab) 3151104834Sobrien{ 3152104834Sobrien asection *link_sec; 3153104834Sobrien asection *stub_sec; 3154104834Sobrien struct ppc_stub_hash_entry *stub_entry; 3155104834Sobrien 3156104834Sobrien link_sec = htab->stub_group[section->id].link_sec; 3157104834Sobrien stub_sec = htab->stub_group[section->id].stub_sec; 3158104834Sobrien if (stub_sec == NULL) 3159104834Sobrien { 3160104834Sobrien stub_sec = htab->stub_group[link_sec->id].stub_sec; 3161104834Sobrien if (stub_sec == NULL) 3162104834Sobrien { 3163104834Sobrien size_t namelen; 3164104834Sobrien bfd_size_type len; 3165104834Sobrien char *s_name; 3166104834Sobrien 3167104834Sobrien namelen = strlen (link_sec->name); 3168104834Sobrien len = namelen + sizeof (STUB_SUFFIX); 3169104834Sobrien s_name = bfd_alloc (htab->stub_bfd, len); 3170104834Sobrien if (s_name == NULL) 3171104834Sobrien return NULL; 3172104834Sobrien 3173104834Sobrien memcpy (s_name, link_sec->name, namelen); 3174104834Sobrien memcpy (s_name + namelen, STUB_SUFFIX, sizeof (STUB_SUFFIX)); 3175104834Sobrien stub_sec = (*htab->add_stub_section) (s_name, link_sec); 3176104834Sobrien if (stub_sec == NULL) 3177104834Sobrien return NULL; 3178104834Sobrien htab->stub_group[link_sec->id].stub_sec = stub_sec; 3179104834Sobrien } 3180104834Sobrien htab->stub_group[section->id].stub_sec = stub_sec; 3181104834Sobrien } 3182104834Sobrien 3183104834Sobrien /* Enter this entry into the linker stub hash table. */ 3184104834Sobrien stub_entry = ppc_stub_hash_lookup (&htab->stub_hash_table, stub_name, 3185130561Sobrien TRUE, FALSE); 3186104834Sobrien if (stub_entry == NULL) 3187104834Sobrien { 3188104834Sobrien (*_bfd_error_handler) (_("%s: cannot create stub entry %s"), 3189104834Sobrien bfd_archive_filename (section->owner), 3190104834Sobrien stub_name); 3191104834Sobrien return NULL; 3192104834Sobrien } 3193104834Sobrien 3194104834Sobrien stub_entry->stub_sec = stub_sec; 3195104834Sobrien stub_entry->stub_offset = 0; 3196104834Sobrien stub_entry->id_sec = link_sec; 3197104834Sobrien return stub_entry; 3198104834Sobrien} 3199104834Sobrien 320092828Sobrien/* Create sections for linker generated code. */ 320192828Sobrien 3202130561Sobrienstatic bfd_boolean 3203130561Sobriencreate_linkage_sections (bfd *dynobj, struct bfd_link_info *info) 320492828Sobrien{ 320592828Sobrien struct ppc_link_hash_table *htab; 320692828Sobrien flagword flags; 320792828Sobrien 320892828Sobrien htab = ppc_hash_table (info); 320992828Sobrien 321092828Sobrien /* Create .sfpr for code to save and restore fp regs. */ 321192828Sobrien flags = (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_READONLY 321292828Sobrien | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED); 3213104834Sobrien htab->sfpr = bfd_make_section_anyway (dynobj, ".sfpr"); 321492828Sobrien if (htab->sfpr == NULL 321592828Sobrien || ! bfd_set_section_flags (dynobj, htab->sfpr, flags) 321692828Sobrien || ! bfd_set_section_alignment (dynobj, htab->sfpr, 2)) 3217130561Sobrien return FALSE; 321892828Sobrien 3219104834Sobrien /* Create .glink for lazy dynamic linking support. */ 3220130561Sobrien htab->glink = bfd_make_section_anyway (dynobj, ".glink"); 3221130561Sobrien if (htab->glink == NULL 3222130561Sobrien || ! bfd_set_section_flags (dynobj, htab->glink, flags) 3223130561Sobrien || ! bfd_set_section_alignment (dynobj, htab->glink, 2)) 3224130561Sobrien return FALSE; 322592828Sobrien 3226104834Sobrien /* Create .branch_lt for plt_branch stubs. */ 3227104834Sobrien flags = (SEC_ALLOC | SEC_LOAD 3228104834Sobrien | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED); 3229130561Sobrien htab->brlt = bfd_make_section_anyway (dynobj, ".branch_lt"); 3230130561Sobrien if (htab->brlt == NULL 3231130561Sobrien || ! bfd_set_section_flags (dynobj, htab->brlt, flags) 3232130561Sobrien || ! bfd_set_section_alignment (dynobj, htab->brlt, 3)) 3233130561Sobrien return FALSE; 3234104834Sobrien 3235104834Sobrien if (info->shared) 3236104834Sobrien { 3237104834Sobrien flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY 3238104834Sobrien | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED); 3239130561Sobrien htab->relbrlt = bfd_make_section_anyway (dynobj, ".rela.branch_lt"); 3240130561Sobrien if (!htab->relbrlt 3241130561Sobrien || ! bfd_set_section_flags (dynobj, htab->relbrlt, flags) 3242130561Sobrien || ! bfd_set_section_alignment (dynobj, htab->relbrlt, 3)) 3243130561Sobrien return FALSE; 3244104834Sobrien } 3245130561Sobrien return TRUE; 324692828Sobrien} 324792828Sobrien 3248130561Sobrien/* Create .got and .rela.got sections in ABFD, and .got in dynobj if 3249130561Sobrien not already done. */ 325089857Sobrien 3251130561Sobrienstatic bfd_boolean 3252130561Sobriencreate_got_section (bfd *abfd, struct bfd_link_info *info) 325389857Sobrien{ 3254130561Sobrien asection *got, *relgot; 3255130561Sobrien flagword flags; 3256130561Sobrien struct ppc_link_hash_table *htab = ppc_hash_table (info); 325789857Sobrien 3258130561Sobrien if (!htab->got) 3259130561Sobrien { 3260130561Sobrien if (! _bfd_elf_create_got_section (htab->elf.dynobj, info)) 3261130561Sobrien return FALSE; 326289857Sobrien 3263130561Sobrien htab->got = bfd_get_section_by_name (htab->elf.dynobj, ".got"); 3264130561Sobrien if (!htab->got) 3265130561Sobrien abort (); 3266130561Sobrien } 326789857Sobrien 3268130561Sobrien flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY 3269130561Sobrien | SEC_LINKER_CREATED); 3270130561Sobrien 3271209867Snwhitehorn got = bfd_make_section_anyway (abfd, ".got"); 3272130561Sobrien if (!got 3273130561Sobrien || !bfd_set_section_flags (abfd, got, flags) 3274130561Sobrien || !bfd_set_section_alignment (abfd, got, 3)) 3275130561Sobrien return FALSE; 3276130561Sobrien 3277209867Snwhitehorn relgot = bfd_make_section_anyway (abfd, ".rela.got"); 3278130561Sobrien if (!relgot 3279130561Sobrien || ! bfd_set_section_flags (abfd, relgot, flags | SEC_READONLY) 3280130561Sobrien || ! bfd_set_section_alignment (abfd, relgot, 3)) 3281130561Sobrien return FALSE; 3282130561Sobrien 3283130561Sobrien ppc64_elf_tdata (abfd)->got = got; 3284130561Sobrien ppc64_elf_tdata (abfd)->relgot = relgot; 3285130561Sobrien return TRUE; 328689857Sobrien} 328789857Sobrien 328892828Sobrien/* Create the dynamic sections, and set up shortcuts. */ 328989857Sobrien 3290130561Sobrienstatic bfd_boolean 3291130561Sobrienppc64_elf_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info) 329289857Sobrien{ 329389857Sobrien struct ppc_link_hash_table *htab; 329489857Sobrien 329589857Sobrien if (!_bfd_elf_create_dynamic_sections (dynobj, info)) 3296130561Sobrien return FALSE; 329789857Sobrien 3298130561Sobrien htab = ppc_hash_table (info); 3299130561Sobrien if (!htab->got) 3300130561Sobrien htab->got = bfd_get_section_by_name (dynobj, ".got"); 3301130561Sobrien htab->plt = bfd_get_section_by_name (dynobj, ".plt"); 3302130561Sobrien htab->relplt = bfd_get_section_by_name (dynobj, ".rela.plt"); 3303130561Sobrien htab->dynbss = bfd_get_section_by_name (dynobj, ".dynbss"); 330489857Sobrien if (!info->shared) 3305130561Sobrien htab->relbss = bfd_get_section_by_name (dynobj, ".rela.bss"); 330689857Sobrien 3307130561Sobrien if (!htab->got || !htab->plt || !htab->relplt || !htab->dynbss 3308130561Sobrien || (!info->shared && !htab->relbss)) 330989857Sobrien abort (); 331089857Sobrien 3311130561Sobrien return TRUE; 331289857Sobrien} 331389857Sobrien 331489857Sobrien/* Copy the extra info we tack onto an elf_link_hash_entry. */ 331589857Sobrien 331689857Sobrienstatic void 3317130561Sobrienppc64_elf_copy_indirect_symbol 3318130561Sobrien (const struct elf_backend_data *bed ATTRIBUTE_UNUSED, 3319130561Sobrien struct elf_link_hash_entry *dir, 3320130561Sobrien struct elf_link_hash_entry *ind) 332189857Sobrien{ 332289857Sobrien struct ppc_link_hash_entry *edir, *eind; 3323130561Sobrien flagword mask; 332489857Sobrien 332589857Sobrien edir = (struct ppc_link_hash_entry *) dir; 332689857Sobrien eind = (struct ppc_link_hash_entry *) ind; 332789857Sobrien 3328130561Sobrien /* Copy over any dynamic relocs we may have on the indirect sym. */ 332989857Sobrien if (eind->dyn_relocs != NULL) 333089857Sobrien { 333189857Sobrien if (edir->dyn_relocs != NULL) 333289857Sobrien { 333389857Sobrien struct ppc_dyn_relocs **pp; 333489857Sobrien struct ppc_dyn_relocs *p; 333589857Sobrien 3336130561Sobrien if (eind->elf.root.type == bfd_link_hash_indirect) 333789857Sobrien abort (); 333889857Sobrien 333989857Sobrien /* Add reloc counts against the weak sym to the strong sym 334089857Sobrien list. Merge any entries against the same section. */ 334189857Sobrien for (pp = &eind->dyn_relocs; (p = *pp) != NULL; ) 334289857Sobrien { 334389857Sobrien struct ppc_dyn_relocs *q; 334489857Sobrien 334589857Sobrien for (q = edir->dyn_relocs; q != NULL; q = q->next) 334689857Sobrien if (q->sec == p->sec) 334789857Sobrien { 334889857Sobrien q->pc_count += p->pc_count; 334989857Sobrien q->count += p->count; 335089857Sobrien *pp = p->next; 335189857Sobrien break; 335289857Sobrien } 335389857Sobrien if (q == NULL) 335489857Sobrien pp = &p->next; 335589857Sobrien } 335689857Sobrien *pp = edir->dyn_relocs; 335789857Sobrien } 335889857Sobrien 335989857Sobrien edir->dyn_relocs = eind->dyn_relocs; 336089857Sobrien eind->dyn_relocs = NULL; 336189857Sobrien } 336289857Sobrien 336389857Sobrien edir->is_func |= eind->is_func; 336489857Sobrien edir->is_func_descriptor |= eind->is_func_descriptor; 3365104834Sobrien edir->is_entry |= eind->is_entry; 3366130561Sobrien edir->tls_mask |= eind->tls_mask; 336789857Sobrien 3368130561Sobrien mask = (ELF_LINK_HASH_REF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR 3369130561Sobrien | ELF_LINK_HASH_REF_REGULAR_NONWEAK | ELF_LINK_NON_GOT_REF 3370130561Sobrien | ELF_LINK_HASH_NEEDS_PLT); 3371130561Sobrien /* If called to transfer flags for a weakdef during processing 3372130561Sobrien of elf_adjust_dynamic_symbol, don't copy ELF_LINK_NON_GOT_REF. 3373130561Sobrien We clear it ourselves for ELIMINATE_COPY_RELOCS. */ 3374130561Sobrien if (ELIMINATE_COPY_RELOCS 3375130561Sobrien && eind->elf.root.type != bfd_link_hash_indirect 3376130561Sobrien && (edir->elf.elf_link_hash_flags & ELF_LINK_HASH_DYNAMIC_ADJUSTED) != 0) 3377130561Sobrien mask &= ~ELF_LINK_NON_GOT_REF; 3378130561Sobrien 3379130561Sobrien edir->elf.elf_link_hash_flags |= eind->elf.elf_link_hash_flags & mask; 3380130561Sobrien 3381130561Sobrien /* If we were called to copy over info for a weak sym, that's all. */ 3382130561Sobrien if (eind->elf.root.type != bfd_link_hash_indirect) 3383130561Sobrien return; 3384130561Sobrien 3385130561Sobrien /* Copy over got entries that we may have already seen to the 3386130561Sobrien symbol which just became indirect. */ 3387130561Sobrien if (eind->elf.got.glist != NULL) 3388130561Sobrien { 3389130561Sobrien if (edir->elf.got.glist != NULL) 3390130561Sobrien { 3391130561Sobrien struct got_entry **entp; 3392130561Sobrien struct got_entry *ent; 3393130561Sobrien 3394130561Sobrien for (entp = &eind->elf.got.glist; (ent = *entp) != NULL; ) 3395130561Sobrien { 3396130561Sobrien struct got_entry *dent; 3397130561Sobrien 3398130561Sobrien for (dent = edir->elf.got.glist; dent != NULL; dent = dent->next) 3399130561Sobrien if (dent->addend == ent->addend 3400130561Sobrien && dent->owner == ent->owner 3401130561Sobrien && dent->tls_type == ent->tls_type) 3402130561Sobrien { 3403130561Sobrien dent->got.refcount += ent->got.refcount; 3404130561Sobrien *entp = ent->next; 3405130561Sobrien break; 3406130561Sobrien } 3407130561Sobrien if (dent == NULL) 3408130561Sobrien entp = &ent->next; 3409130561Sobrien } 3410130561Sobrien *entp = edir->elf.got.glist; 3411130561Sobrien } 3412130561Sobrien 3413130561Sobrien edir->elf.got.glist = eind->elf.got.glist; 3414130561Sobrien eind->elf.got.glist = NULL; 3415130561Sobrien } 3416130561Sobrien 3417130561Sobrien /* And plt entries. */ 3418130561Sobrien if (eind->elf.plt.plist != NULL) 3419130561Sobrien { 3420130561Sobrien if (edir->elf.plt.plist != NULL) 3421130561Sobrien { 3422130561Sobrien struct plt_entry **entp; 3423130561Sobrien struct plt_entry *ent; 3424130561Sobrien 3425130561Sobrien for (entp = &eind->elf.plt.plist; (ent = *entp) != NULL; ) 3426130561Sobrien { 3427130561Sobrien struct plt_entry *dent; 3428130561Sobrien 3429130561Sobrien for (dent = edir->elf.plt.plist; dent != NULL; dent = dent->next) 3430130561Sobrien if (dent->addend == ent->addend) 3431130561Sobrien { 3432130561Sobrien dent->plt.refcount += ent->plt.refcount; 3433130561Sobrien *entp = ent->next; 3434130561Sobrien break; 3435130561Sobrien } 3436130561Sobrien if (dent == NULL) 3437130561Sobrien entp = &ent->next; 3438130561Sobrien } 3439130561Sobrien *entp = edir->elf.plt.plist; 3440130561Sobrien } 3441130561Sobrien 3442130561Sobrien edir->elf.plt.plist = eind->elf.plt.plist; 3443130561Sobrien eind->elf.plt.plist = NULL; 3444130561Sobrien } 3445130561Sobrien 3446130561Sobrien if (edir->elf.dynindx == -1) 3447130561Sobrien { 3448130561Sobrien edir->elf.dynindx = eind->elf.dynindx; 3449130561Sobrien edir->elf.dynstr_index = eind->elf.dynstr_index; 3450130561Sobrien eind->elf.dynindx = -1; 3451130561Sobrien eind->elf.dynstr_index = 0; 3452130561Sobrien } 3453130561Sobrien else 3454130561Sobrien BFD_ASSERT (eind->elf.dynindx == -1); 345589857Sobrien} 345689857Sobrien 3457104834Sobrien/* Set a flag, used by ppc64_elf_gc_mark_hook, on the entry symbol and 3458104834Sobrien symbols undefined on the command-line. */ 3459104834Sobrien 3460130561Sobrienbfd_boolean 3461130561Sobrienppc64_elf_mark_entry_syms (struct bfd_link_info *info) 3462104834Sobrien{ 3463104834Sobrien struct ppc_link_hash_table *htab; 3464104834Sobrien struct bfd_sym_chain *sym; 3465104834Sobrien 3466104834Sobrien htab = ppc_hash_table (info); 3467104834Sobrien for (sym = info->gc_sym_list; sym; sym = sym->next) 3468104834Sobrien { 3469104834Sobrien struct elf_link_hash_entry *h; 3470104834Sobrien 3471130561Sobrien h = elf_link_hash_lookup (&htab->elf, sym->name, FALSE, FALSE, FALSE); 3472104834Sobrien if (h != NULL) 3473104834Sobrien ((struct ppc_link_hash_entry *) h)->is_entry = 1; 3474104834Sobrien } 3475130561Sobrien return TRUE; 3476104834Sobrien} 3477104834Sobrien 3478130561Sobrien/* Hack symbols defined in .opd sections to be function type. */ 3479130561Sobrien 3480130561Sobrienstatic bfd_boolean 3481130561Sobrienppc64_elf_add_symbol_hook (bfd *ibfd ATTRIBUTE_UNUSED, 3482130561Sobrien struct bfd_link_info *info ATTRIBUTE_UNUSED, 3483130561Sobrien Elf_Internal_Sym *isym, 3484130561Sobrien const char **name ATTRIBUTE_UNUSED, 3485130561Sobrien flagword *flags ATTRIBUTE_UNUSED, 3486130561Sobrien asection **sec, 3487130561Sobrien bfd_vma *value ATTRIBUTE_UNUSED) 3488130561Sobrien{ 3489130561Sobrien if (strcmp (bfd_get_section_name (ibfd, *sec), ".opd") == 0) 3490130561Sobrien isym->st_info = ELF_ST_INFO (ELF_ST_BIND (isym->st_info), STT_FUNC); 3491130561Sobrien return TRUE; 3492130561Sobrien} 3493130561Sobrien 3494130561Sobrienstatic bfd_boolean 3495130561Sobrienupdate_local_sym_info (bfd *abfd, Elf_Internal_Shdr *symtab_hdr, 3496130561Sobrien unsigned long r_symndx, bfd_vma r_addend, int tls_type) 3497130561Sobrien{ 3498130561Sobrien struct got_entry **local_got_ents = elf_local_got_ents (abfd); 3499130561Sobrien char *local_got_tls_masks; 3500130561Sobrien 3501130561Sobrien if (local_got_ents == NULL) 3502130561Sobrien { 3503130561Sobrien bfd_size_type size = symtab_hdr->sh_info; 3504130561Sobrien 3505130561Sobrien size *= sizeof (*local_got_ents) + sizeof (*local_got_tls_masks); 3506130561Sobrien local_got_ents = bfd_zalloc (abfd, size); 3507130561Sobrien if (local_got_ents == NULL) 3508130561Sobrien return FALSE; 3509130561Sobrien elf_local_got_ents (abfd) = local_got_ents; 3510130561Sobrien } 3511130561Sobrien 3512130561Sobrien if ((tls_type & TLS_EXPLICIT) == 0) 3513130561Sobrien { 3514130561Sobrien struct got_entry *ent; 3515130561Sobrien 3516130561Sobrien for (ent = local_got_ents[r_symndx]; ent != NULL; ent = ent->next) 3517130561Sobrien if (ent->addend == r_addend 3518130561Sobrien && ent->owner == abfd 3519130561Sobrien && ent->tls_type == tls_type) 3520130561Sobrien break; 3521130561Sobrien if (ent == NULL) 3522130561Sobrien { 3523130561Sobrien bfd_size_type amt = sizeof (*ent); 3524130561Sobrien ent = bfd_alloc (abfd, amt); 3525130561Sobrien if (ent == NULL) 3526130561Sobrien return FALSE; 3527130561Sobrien ent->next = local_got_ents[r_symndx]; 3528130561Sobrien ent->addend = r_addend; 3529130561Sobrien ent->owner = abfd; 3530130561Sobrien ent->tls_type = tls_type; 3531130561Sobrien ent->got.refcount = 0; 3532130561Sobrien local_got_ents[r_symndx] = ent; 3533130561Sobrien } 3534130561Sobrien ent->got.refcount += 1; 3535130561Sobrien } 3536130561Sobrien 3537130561Sobrien local_got_tls_masks = (char *) (local_got_ents + symtab_hdr->sh_info); 3538130561Sobrien local_got_tls_masks[r_symndx] |= tls_type; 3539130561Sobrien return TRUE; 3540130561Sobrien} 3541130561Sobrien 3542130561Sobrienstatic bfd_boolean 3543130561Sobrienupdate_plt_info (bfd *abfd, struct ppc_link_hash_entry *eh, bfd_vma addend) 3544130561Sobrien{ 3545130561Sobrien struct plt_entry *ent; 3546130561Sobrien 3547130561Sobrien for (ent = eh->elf.plt.plist; ent != NULL; ent = ent->next) 3548130561Sobrien if (ent->addend == addend) 3549130561Sobrien break; 3550130561Sobrien if (ent == NULL) 3551130561Sobrien { 3552130561Sobrien bfd_size_type amt = sizeof (*ent); 3553130561Sobrien ent = bfd_alloc (abfd, amt); 3554130561Sobrien if (ent == NULL) 3555130561Sobrien return FALSE; 3556130561Sobrien ent->next = eh->elf.plt.plist; 3557130561Sobrien ent->addend = addend; 3558130561Sobrien ent->plt.refcount = 0; 3559130561Sobrien eh->elf.plt.plist = ent; 3560130561Sobrien } 3561130561Sobrien ent->plt.refcount += 1; 3562130561Sobrien eh->elf.elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; 3563130561Sobrien eh->is_func = 1; 3564130561Sobrien return TRUE; 3565130561Sobrien} 3566130561Sobrien 3567130561Sobrien/* Find the function descriptor hash entry from the given function code 3568130561Sobrien hash entry FH. Link the entries via their OH fields. */ 3569130561Sobrienstatic struct ppc_link_hash_entry * 3570130561Sobrienget_fdh (struct ppc_link_hash_entry *fh, struct ppc_link_hash_table *htab) 3571130561Sobrien{ 3572130561Sobrien struct ppc_link_hash_entry *fdh = (struct ppc_link_hash_entry *) fh->oh; 3573130561Sobrien 3574130561Sobrien if (fdh == NULL) 3575130561Sobrien { 3576130561Sobrien const char *fd_name = fh->elf.root.root.string + 1; 3577130561Sobrien 3578130561Sobrien fdh = (struct ppc_link_hash_entry *) 3579130561Sobrien elf_link_hash_lookup (&htab->elf, fd_name, FALSE, FALSE, FALSE); 3580130561Sobrien if (fdh != NULL) 3581130561Sobrien { 3582130561Sobrien fdh->is_func_descriptor = 1; 3583130561Sobrien fdh->oh = &fh->elf; 3584130561Sobrien fh->is_func = 1; 3585130561Sobrien fh->oh = &fdh->elf; 3586130561Sobrien } 3587130561Sobrien } 3588130561Sobrien 3589130561Sobrien return fdh; 3590130561Sobrien} 3591130561Sobrien 359289857Sobrien/* Look through the relocs for a section during the first phase, and 359389857Sobrien calculate needed space in the global offset table, procedure 359489857Sobrien linkage table, and dynamic reloc sections. */ 359589857Sobrien 3596130561Sobrienstatic bfd_boolean 3597130561Sobrienppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, 3598130561Sobrien asection *sec, const Elf_Internal_Rela *relocs) 359989857Sobrien{ 360089857Sobrien struct ppc_link_hash_table *htab; 360189857Sobrien Elf_Internal_Shdr *symtab_hdr; 360289857Sobrien struct elf_link_hash_entry **sym_hashes, **sym_hashes_end; 360389857Sobrien const Elf_Internal_Rela *rel; 360489857Sobrien const Elf_Internal_Rela *rel_end; 360589857Sobrien asection *sreloc; 3606104834Sobrien asection **opd_sym_map; 360789857Sobrien 3608130561Sobrien if (info->relocatable) 3609130561Sobrien return TRUE; 361089857Sobrien 3611130561Sobrien /* Don't do anything special with non-loaded, non-alloced sections. 3612130561Sobrien In particular, any relocs in such sections should not affect GOT 3613130561Sobrien and PLT reference counting (ie. we don't allow them to create GOT 3614130561Sobrien or PLT entries), there's no possibility or desire to optimize TLS 3615130561Sobrien relocs, and there's not much point in propagating relocs to shared 3616130561Sobrien libs that the dynamic linker won't relocate. */ 3617130561Sobrien if ((sec->flags & SEC_ALLOC) == 0) 3618130561Sobrien return TRUE; 3619130561Sobrien 362089857Sobrien htab = ppc_hash_table (info); 362189857Sobrien symtab_hdr = &elf_tdata (abfd)->symtab_hdr; 362289857Sobrien 362389857Sobrien sym_hashes = elf_sym_hashes (abfd); 362489857Sobrien sym_hashes_end = (sym_hashes 3625104834Sobrien + symtab_hdr->sh_size / sizeof (Elf64_External_Sym) 3626104834Sobrien - symtab_hdr->sh_info); 362789857Sobrien 362889857Sobrien sreloc = NULL; 3629104834Sobrien opd_sym_map = NULL; 3630104834Sobrien if (strcmp (bfd_get_section_name (abfd, sec), ".opd") == 0) 3631104834Sobrien { 3632104834Sobrien /* Garbage collection needs some extra help with .opd sections. 3633104834Sobrien We don't want to necessarily keep everything referenced by 3634104834Sobrien relocs in .opd, as that would keep all functions. Instead, 3635104834Sobrien if we reference an .opd symbol (a function descriptor), we 3636104834Sobrien want to keep the function code symbol's section. This is 3637104834Sobrien easy for global symbols, but for local syms we need to keep 3638104834Sobrien information about the associated function section. Later, if 3639104834Sobrien edit_opd deletes entries, we'll use this array to adjust 3640104834Sobrien local syms in .opd. */ 3641104834Sobrien union opd_info { 3642104834Sobrien asection *func_section; 3643104834Sobrien long entry_adjust; 3644104834Sobrien }; 3645104834Sobrien bfd_size_type amt; 364689857Sobrien 3647104834Sobrien amt = sec->_raw_size * sizeof (union opd_info) / 24; 3648130561Sobrien opd_sym_map = bfd_zalloc (abfd, amt); 3649104834Sobrien if (opd_sym_map == NULL) 3650130561Sobrien return FALSE; 3651130561Sobrien ppc64_elf_section_data (sec)->opd.func_sec = opd_sym_map; 3652104834Sobrien } 3653104834Sobrien 365492828Sobrien if (htab->sfpr == NULL 365592828Sobrien && !create_linkage_sections (htab->elf.dynobj, info)) 3656130561Sobrien return FALSE; 365792828Sobrien 365889857Sobrien rel_end = relocs + sec->reloc_count; 365989857Sobrien for (rel = relocs; rel < rel_end; rel++) 366089857Sobrien { 366189857Sobrien unsigned long r_symndx; 366289857Sobrien struct elf_link_hash_entry *h; 3663130561Sobrien enum elf_ppc64_reloc_type r_type; 3664130561Sobrien int tls_type = 0; 366589857Sobrien 366689857Sobrien r_symndx = ELF64_R_SYM (rel->r_info); 366789857Sobrien if (r_symndx < symtab_hdr->sh_info) 366889857Sobrien h = NULL; 366989857Sobrien else 367089857Sobrien h = sym_hashes[r_symndx - symtab_hdr->sh_info]; 367189857Sobrien 3672130561Sobrien r_type = ELF64_R_TYPE (rel->r_info); 367389857Sobrien switch (r_type) 367489857Sobrien { 3675130561Sobrien case R_PPC64_GOT_TLSLD16: 3676130561Sobrien case R_PPC64_GOT_TLSLD16_LO: 3677130561Sobrien case R_PPC64_GOT_TLSLD16_HI: 3678130561Sobrien case R_PPC64_GOT_TLSLD16_HA: 3679130561Sobrien ppc64_tlsld_got (abfd)->refcount += 1; 3680130561Sobrien tls_type = TLS_TLS | TLS_LD; 3681130561Sobrien goto dogottls; 3682130561Sobrien 3683130561Sobrien case R_PPC64_GOT_TLSGD16: 3684130561Sobrien case R_PPC64_GOT_TLSGD16_LO: 3685130561Sobrien case R_PPC64_GOT_TLSGD16_HI: 3686130561Sobrien case R_PPC64_GOT_TLSGD16_HA: 3687130561Sobrien tls_type = TLS_TLS | TLS_GD; 3688130561Sobrien goto dogottls; 3689130561Sobrien 3690130561Sobrien case R_PPC64_GOT_TPREL16_DS: 3691130561Sobrien case R_PPC64_GOT_TPREL16_LO_DS: 3692130561Sobrien case R_PPC64_GOT_TPREL16_HI: 3693130561Sobrien case R_PPC64_GOT_TPREL16_HA: 3694130561Sobrien if (info->shared) 3695130561Sobrien info->flags |= DF_STATIC_TLS; 3696130561Sobrien tls_type = TLS_TLS | TLS_TPREL; 3697130561Sobrien goto dogottls; 3698130561Sobrien 3699130561Sobrien case R_PPC64_GOT_DTPREL16_DS: 3700130561Sobrien case R_PPC64_GOT_DTPREL16_LO_DS: 3701130561Sobrien case R_PPC64_GOT_DTPREL16_HI: 3702130561Sobrien case R_PPC64_GOT_DTPREL16_HA: 3703130561Sobrien tls_type = TLS_TLS | TLS_DTPREL; 3704130561Sobrien dogottls: 3705130561Sobrien sec->has_tls_reloc = 1; 3706130561Sobrien /* Fall thru */ 3707130561Sobrien 370889857Sobrien case R_PPC64_GOT16: 370989857Sobrien case R_PPC64_GOT16_DS: 371089857Sobrien case R_PPC64_GOT16_HA: 371189857Sobrien case R_PPC64_GOT16_HI: 371289857Sobrien case R_PPC64_GOT16_LO: 371389857Sobrien case R_PPC64_GOT16_LO_DS: 371489857Sobrien /* This symbol requires a global offset table entry. */ 3715130561Sobrien sec->has_gp_reloc = 1; 3716130561Sobrien if (ppc64_elf_tdata (abfd)->got == NULL 3717130561Sobrien && !create_got_section (abfd, info)) 3718130561Sobrien return FALSE; 371989857Sobrien 372089857Sobrien if (h != NULL) 372189857Sobrien { 3722130561Sobrien struct ppc_link_hash_entry *eh; 3723130561Sobrien struct got_entry *ent; 372489857Sobrien 3725130561Sobrien eh = (struct ppc_link_hash_entry *) h; 3726130561Sobrien for (ent = eh->elf.got.glist; ent != NULL; ent = ent->next) 3727130561Sobrien if (ent->addend == rel->r_addend 3728130561Sobrien && ent->owner == abfd 3729130561Sobrien && ent->tls_type == tls_type) 3730130561Sobrien break; 3731130561Sobrien if (ent == NULL) 373289857Sobrien { 3733130561Sobrien bfd_size_type amt = sizeof (*ent); 3734130561Sobrien ent = bfd_alloc (abfd, amt); 3735130561Sobrien if (ent == NULL) 3736130561Sobrien return FALSE; 3737130561Sobrien ent->next = eh->elf.got.glist; 3738130561Sobrien ent->addend = rel->r_addend; 3739130561Sobrien ent->owner = abfd; 3740130561Sobrien ent->tls_type = tls_type; 3741130561Sobrien ent->got.refcount = 0; 3742130561Sobrien eh->elf.got.glist = ent; 374389857Sobrien } 3744130561Sobrien ent->got.refcount += 1; 3745130561Sobrien eh->tls_mask |= tls_type; 374689857Sobrien } 3747130561Sobrien else 3748130561Sobrien /* This is a global offset table entry for a local symbol. */ 3749130561Sobrien if (!update_local_sym_info (abfd, symtab_hdr, r_symndx, 3750130561Sobrien rel->r_addend, tls_type)) 3751130561Sobrien return FALSE; 375289857Sobrien break; 375389857Sobrien 375489857Sobrien case R_PPC64_PLT16_HA: 375589857Sobrien case R_PPC64_PLT16_HI: 375689857Sobrien case R_PPC64_PLT16_LO: 375789857Sobrien case R_PPC64_PLT32: 375889857Sobrien case R_PPC64_PLT64: 375989857Sobrien /* This symbol requires a procedure linkage table entry. We 3760104834Sobrien actually build the entry in adjust_dynamic_symbol, 3761104834Sobrien because this might be a case of linking PIC code without 3762104834Sobrien linking in any dynamic objects, in which case we don't 3763104834Sobrien need to generate a procedure linkage table after all. */ 376489857Sobrien if (h == NULL) 376589857Sobrien { 376689857Sobrien /* It does not make sense to have a procedure linkage 3767104834Sobrien table entry for a local symbol. */ 376889857Sobrien bfd_set_error (bfd_error_bad_value); 3769130561Sobrien return FALSE; 377089857Sobrien } 3771130561Sobrien else 3772130561Sobrien if (!update_plt_info (abfd, (struct ppc_link_hash_entry *) h, 3773130561Sobrien rel->r_addend)) 3774130561Sobrien return FALSE; 377589857Sobrien break; 377689857Sobrien 377789857Sobrien /* The following relocations don't need to propagate the 377889857Sobrien relocation if linking a shared object since they are 377989857Sobrien section relative. */ 378089857Sobrien case R_PPC64_SECTOFF: 378189857Sobrien case R_PPC64_SECTOFF_LO: 378289857Sobrien case R_PPC64_SECTOFF_HI: 378389857Sobrien case R_PPC64_SECTOFF_HA: 378489857Sobrien case R_PPC64_SECTOFF_DS: 378589857Sobrien case R_PPC64_SECTOFF_LO_DS: 3786130561Sobrien case R_PPC64_DTPREL16: 3787130561Sobrien case R_PPC64_DTPREL16_LO: 3788130561Sobrien case R_PPC64_DTPREL16_HI: 3789130561Sobrien case R_PPC64_DTPREL16_HA: 3790130561Sobrien case R_PPC64_DTPREL16_DS: 3791130561Sobrien case R_PPC64_DTPREL16_LO_DS: 3792130561Sobrien case R_PPC64_DTPREL16_HIGHER: 3793130561Sobrien case R_PPC64_DTPREL16_HIGHERA: 3794130561Sobrien case R_PPC64_DTPREL16_HIGHEST: 3795130561Sobrien case R_PPC64_DTPREL16_HIGHESTA: 3796130561Sobrien break; 3797130561Sobrien 3798130561Sobrien /* Nor do these. */ 379989857Sobrien case R_PPC64_TOC16: 380089857Sobrien case R_PPC64_TOC16_LO: 380189857Sobrien case R_PPC64_TOC16_HI: 380289857Sobrien case R_PPC64_TOC16_HA: 380389857Sobrien case R_PPC64_TOC16_DS: 380489857Sobrien case R_PPC64_TOC16_LO_DS: 3805130561Sobrien sec->has_gp_reloc = 1; 380689857Sobrien break; 380789857Sobrien 380889857Sobrien /* This relocation describes the C++ object vtable hierarchy. 380989857Sobrien Reconstruct it for later use during GC. */ 381089857Sobrien case R_PPC64_GNU_VTINHERIT: 3811130561Sobrien if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) 3812130561Sobrien return FALSE; 381389857Sobrien break; 381489857Sobrien 381589857Sobrien /* This relocation describes which C++ vtable entries are actually 381689857Sobrien used. Record for later use during GC. */ 381789857Sobrien case R_PPC64_GNU_VTENTRY: 3818130561Sobrien if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend)) 3819130561Sobrien return FALSE; 382089857Sobrien break; 382189857Sobrien 3822104834Sobrien case R_PPC64_REL14: 3823104834Sobrien case R_PPC64_REL14_BRTAKEN: 3824104834Sobrien case R_PPC64_REL14_BRNTAKEN: 3825104834Sobrien htab->has_14bit_branch = 1; 3826104834Sobrien /* Fall through. */ 3827104834Sobrien 382889857Sobrien case R_PPC64_REL24: 382989857Sobrien if (h != NULL 383089857Sobrien && h->root.root.string[0] == '.' 383189857Sobrien && h->root.root.string[1] != 0) 383289857Sobrien { 383389857Sobrien /* We may need a .plt entry if the function this reloc 383489857Sobrien refers to is in a shared lib. */ 3835130561Sobrien if (!update_plt_info (abfd, (struct ppc_link_hash_entry *) h, 3836130561Sobrien rel->r_addend)) 3837130561Sobrien return FALSE; 3838130561Sobrien if (h == htab->tls_get_addr) 3839130561Sobrien sec->has_tls_reloc = 1; 3840130561Sobrien else if ((strncmp (h->root.root.string, ".__tls_get_addr", 15) 3841130561Sobrien == 0) 3842130561Sobrien && (h->root.root.string[15] == 0 3843130561Sobrien || h->root.root.string[15] == '@')) 3844130561Sobrien { 3845130561Sobrien htab->tls_get_addr = h; 3846130561Sobrien sec->has_tls_reloc = 1; 3847130561Sobrien } 384889857Sobrien } 384989857Sobrien break; 385089857Sobrien 3851130561Sobrien case R_PPC64_TPREL64: 3852130561Sobrien tls_type = TLS_EXPLICIT | TLS_TLS | TLS_TPREL; 3853130561Sobrien if (info->shared) 3854130561Sobrien info->flags |= DF_STATIC_TLS; 3855130561Sobrien goto dotlstoc; 3856130561Sobrien 3857130561Sobrien case R_PPC64_DTPMOD64: 3858130561Sobrien if (rel + 1 < rel_end 3859130561Sobrien && rel[1].r_info == ELF64_R_INFO (r_symndx, R_PPC64_DTPREL64) 3860130561Sobrien && rel[1].r_offset == rel->r_offset + 8) 3861130561Sobrien tls_type = TLS_EXPLICIT | TLS_TLS | TLS_GD; 3862130561Sobrien else 3863130561Sobrien tls_type = TLS_EXPLICIT | TLS_TLS | TLS_LD; 3864130561Sobrien goto dotlstoc; 3865130561Sobrien 3866130561Sobrien case R_PPC64_DTPREL64: 3867130561Sobrien tls_type = TLS_EXPLICIT | TLS_TLS | TLS_DTPREL; 3868130561Sobrien if (rel != relocs 3869130561Sobrien && rel[-1].r_info == ELF64_R_INFO (r_symndx, R_PPC64_DTPMOD64) 3870130561Sobrien && rel[-1].r_offset == rel->r_offset - 8) 3871130561Sobrien /* This is the second reloc of a dtpmod, dtprel pair. 3872130561Sobrien Don't mark with TLS_DTPREL. */ 3873130561Sobrien goto dodyn; 3874130561Sobrien 3875130561Sobrien dotlstoc: 3876130561Sobrien sec->has_tls_reloc = 1; 3877130561Sobrien if (h != NULL) 3878130561Sobrien { 3879130561Sobrien struct ppc_link_hash_entry *eh; 3880130561Sobrien eh = (struct ppc_link_hash_entry *) h; 3881130561Sobrien eh->tls_mask |= tls_type; 3882130561Sobrien } 3883130561Sobrien else 3884130561Sobrien if (!update_local_sym_info (abfd, symtab_hdr, r_symndx, 3885130561Sobrien rel->r_addend, tls_type)) 3886130561Sobrien return FALSE; 3887130561Sobrien 3888130561Sobrien if (ppc64_elf_section_data (sec)->t_symndx == NULL) 3889130561Sobrien { 3890130561Sobrien /* One extra to simplify get_tls_mask. */ 3891130561Sobrien bfd_size_type amt = sec->_raw_size * sizeof (unsigned) / 8 + 1; 3892130561Sobrien ppc64_elf_section_data (sec)->t_symndx = bfd_zalloc (abfd, amt); 3893130561Sobrien if (ppc64_elf_section_data (sec)->t_symndx == NULL) 3894130561Sobrien return FALSE; 3895130561Sobrien } 3896130561Sobrien BFD_ASSERT (rel->r_offset % 8 == 0); 3897130561Sobrien ppc64_elf_section_data (sec)->t_symndx[rel->r_offset / 8] = r_symndx; 3898130561Sobrien 3899130561Sobrien /* Mark the second slot of a GD or LD entry. 3900130561Sobrien -1 to indicate GD and -2 to indicate LD. */ 3901130561Sobrien if (tls_type == (TLS_EXPLICIT | TLS_TLS | TLS_GD)) 3902130561Sobrien ppc64_elf_section_data (sec)->t_symndx[rel->r_offset / 8 + 1] = -1; 3903130561Sobrien else if (tls_type == (TLS_EXPLICIT | TLS_TLS | TLS_LD)) 3904130561Sobrien ppc64_elf_section_data (sec)->t_symndx[rel->r_offset / 8 + 1] = -2; 3905130561Sobrien goto dodyn; 3906130561Sobrien 3907130561Sobrien case R_PPC64_TPREL16: 3908130561Sobrien case R_PPC64_TPREL16_LO: 3909130561Sobrien case R_PPC64_TPREL16_HI: 3910130561Sobrien case R_PPC64_TPREL16_HA: 3911130561Sobrien case R_PPC64_TPREL16_DS: 3912130561Sobrien case R_PPC64_TPREL16_LO_DS: 3913130561Sobrien case R_PPC64_TPREL16_HIGHER: 3914130561Sobrien case R_PPC64_TPREL16_HIGHERA: 3915130561Sobrien case R_PPC64_TPREL16_HIGHEST: 3916130561Sobrien case R_PPC64_TPREL16_HIGHESTA: 3917130561Sobrien if (info->shared) 3918130561Sobrien { 3919130561Sobrien info->flags |= DF_STATIC_TLS; 3920130561Sobrien goto dodyn; 3921130561Sobrien } 3922130561Sobrien break; 3923130561Sobrien 392489857Sobrien case R_PPC64_ADDR64: 3925104834Sobrien if (opd_sym_map != NULL 392689857Sobrien && h != NULL 392789857Sobrien && h->root.root.string[0] == '.' 392889857Sobrien && h->root.root.string[1] != 0) 3929130561Sobrien get_fdh ((struct ppc_link_hash_entry *) h, htab); 393089857Sobrien 3931104834Sobrien if (opd_sym_map != NULL 3932104834Sobrien && h == NULL 3933104834Sobrien && rel + 1 < rel_end 3934130561Sobrien && ELF64_R_TYPE ((rel + 1)->r_info) == R_PPC64_TOC) 3935104834Sobrien { 3936104834Sobrien asection *s; 3937104834Sobrien 3938104834Sobrien s = bfd_section_from_r_symndx (abfd, &htab->sym_sec, sec, 3939104834Sobrien r_symndx); 3940104834Sobrien if (s == NULL) 3941130561Sobrien return FALSE; 3942104834Sobrien else if (s != sec) 3943104834Sobrien opd_sym_map[rel->r_offset / 24] = s; 3944104834Sobrien } 394589857Sobrien /* Fall through. */ 394689857Sobrien 3947130561Sobrien case R_PPC64_REL30: 3948130561Sobrien case R_PPC64_REL32: 394989857Sobrien case R_PPC64_REL64: 395089857Sobrien case R_PPC64_ADDR14: 395189857Sobrien case R_PPC64_ADDR14_BRNTAKEN: 395289857Sobrien case R_PPC64_ADDR14_BRTAKEN: 395389857Sobrien case R_PPC64_ADDR16: 395489857Sobrien case R_PPC64_ADDR16_DS: 395589857Sobrien case R_PPC64_ADDR16_HA: 395689857Sobrien case R_PPC64_ADDR16_HI: 395789857Sobrien case R_PPC64_ADDR16_HIGHER: 395889857Sobrien case R_PPC64_ADDR16_HIGHERA: 395989857Sobrien case R_PPC64_ADDR16_HIGHEST: 396089857Sobrien case R_PPC64_ADDR16_HIGHESTA: 396189857Sobrien case R_PPC64_ADDR16_LO: 396289857Sobrien case R_PPC64_ADDR16_LO_DS: 396389857Sobrien case R_PPC64_ADDR24: 396489857Sobrien case R_PPC64_ADDR32: 396589857Sobrien case R_PPC64_UADDR16: 396689857Sobrien case R_PPC64_UADDR32: 396789857Sobrien case R_PPC64_UADDR64: 396889857Sobrien case R_PPC64_TOC: 3969130561Sobrien if (h != NULL && !info->shared) 3970130561Sobrien /* We may need a copy reloc. */ 3971130561Sobrien h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF; 3972130561Sobrien 397389857Sobrien /* Don't propagate .opd relocs. */ 3974104834Sobrien if (NO_OPD_RELOCS && opd_sym_map != NULL) 397589857Sobrien break; 397689857Sobrien 397789857Sobrien /* If we are creating a shared library, and this is a reloc 397889857Sobrien against a global symbol, or a non PC relative reloc 397989857Sobrien against a local symbol, then we need to copy the reloc 398089857Sobrien into the shared library. However, if we are linking with 398189857Sobrien -Bsymbolic, we do not need to copy a reloc against a 398289857Sobrien global symbol which is defined in an object we are 398389857Sobrien including in the link (i.e., DEF_REGULAR is set). At 398489857Sobrien this point we have not seen all the input files, so it is 398589857Sobrien possible that DEF_REGULAR is not set now but will be set 398689857Sobrien later (it is never cleared). In case of a weak definition, 398789857Sobrien DEF_REGULAR may be cleared later by a strong definition in 398889857Sobrien a shared library. We account for that possibility below by 3989130561Sobrien storing information in the dyn_relocs field of the hash 399089857Sobrien table entry. A similar situation occurs when creating 399189857Sobrien shared libraries and symbol visibility changes render the 399289857Sobrien symbol local. 399389857Sobrien 399489857Sobrien If on the other hand, we are creating an executable, we 399589857Sobrien may need to keep relocations for symbols satisfied by a 399689857Sobrien dynamic library if we manage to avoid copy relocs for the 399789857Sobrien symbol. */ 3998130561Sobrien dodyn: 399989857Sobrien if ((info->shared 4000130561Sobrien && (MUST_BE_DYN_RELOC (r_type) 400189857Sobrien || (h != NULL 400289857Sobrien && (! info->symbolic 400389857Sobrien || h->root.type == bfd_link_hash_defweak 400489857Sobrien || (h->elf_link_hash_flags 400589857Sobrien & ELF_LINK_HASH_DEF_REGULAR) == 0)))) 4006130561Sobrien || (ELIMINATE_COPY_RELOCS 4007130561Sobrien && !info->shared 400889857Sobrien && h != NULL 400989857Sobrien && (h->root.type == bfd_link_hash_defweak 401089857Sobrien || (h->elf_link_hash_flags 401189857Sobrien & ELF_LINK_HASH_DEF_REGULAR) == 0))) 401289857Sobrien { 401389857Sobrien struct ppc_dyn_relocs *p; 401489857Sobrien struct ppc_dyn_relocs **head; 401589857Sobrien 401689857Sobrien /* We must copy these reloc types into the output file. 401789857Sobrien Create a reloc section in dynobj and make room for 401889857Sobrien this reloc. */ 401989857Sobrien if (sreloc == NULL) 402089857Sobrien { 402189857Sobrien const char *name; 402289857Sobrien bfd *dynobj; 402389857Sobrien 402489857Sobrien name = (bfd_elf_string_from_elf_section 402589857Sobrien (abfd, 402689857Sobrien elf_elfheader (abfd)->e_shstrndx, 402789857Sobrien elf_section_data (sec)->rel_hdr.sh_name)); 402889857Sobrien if (name == NULL) 4029130561Sobrien return FALSE; 403089857Sobrien 403189857Sobrien if (strncmp (name, ".rela", 5) != 0 403289857Sobrien || strcmp (bfd_get_section_name (abfd, sec), 403389857Sobrien name + 5) != 0) 403489857Sobrien { 403589857Sobrien (*_bfd_error_handler) 403689857Sobrien (_("%s: bad relocation section name `%s\'"), 403789857Sobrien bfd_archive_filename (abfd), name); 403889857Sobrien bfd_set_error (bfd_error_bad_value); 403989857Sobrien } 404089857Sobrien 404189857Sobrien dynobj = htab->elf.dynobj; 404289857Sobrien sreloc = bfd_get_section_by_name (dynobj, name); 404389857Sobrien if (sreloc == NULL) 404489857Sobrien { 404589857Sobrien flagword flags; 404689857Sobrien 404789857Sobrien sreloc = bfd_make_section (dynobj, name); 404889857Sobrien flags = (SEC_HAS_CONTENTS | SEC_READONLY 404989857Sobrien | SEC_IN_MEMORY | SEC_LINKER_CREATED); 405089857Sobrien if ((sec->flags & SEC_ALLOC) != 0) 405189857Sobrien flags |= SEC_ALLOC | SEC_LOAD; 405289857Sobrien if (sreloc == NULL 405389857Sobrien || ! bfd_set_section_flags (dynobj, sreloc, flags) 405489857Sobrien || ! bfd_set_section_alignment (dynobj, sreloc, 3)) 4055130561Sobrien return FALSE; 405689857Sobrien } 405789857Sobrien elf_section_data (sec)->sreloc = sreloc; 405889857Sobrien } 405989857Sobrien 406089857Sobrien /* If this is a global symbol, we count the number of 406189857Sobrien relocations we need for this symbol. */ 406289857Sobrien if (h != NULL) 406389857Sobrien { 406489857Sobrien head = &((struct ppc_link_hash_entry *) h)->dyn_relocs; 406589857Sobrien } 406689857Sobrien else 406789857Sobrien { 406889857Sobrien /* Track dynamic relocs needed for local syms too. 406989857Sobrien We really need local syms available to do this 407089857Sobrien easily. Oh well. */ 407189857Sobrien 407289857Sobrien asection *s; 407389857Sobrien s = bfd_section_from_r_symndx (abfd, &htab->sym_sec, 407489857Sobrien sec, r_symndx); 407589857Sobrien if (s == NULL) 4076130561Sobrien return FALSE; 407789857Sobrien 407889857Sobrien head = ((struct ppc_dyn_relocs **) 407989857Sobrien &elf_section_data (s)->local_dynrel); 408089857Sobrien } 408189857Sobrien 408289857Sobrien p = *head; 408389857Sobrien if (p == NULL || p->sec != sec) 408489857Sobrien { 4085130561Sobrien p = bfd_alloc (htab->elf.dynobj, sizeof *p); 408689857Sobrien if (p == NULL) 4087130561Sobrien return FALSE; 408889857Sobrien p->next = *head; 408989857Sobrien *head = p; 409089857Sobrien p->sec = sec; 409189857Sobrien p->count = 0; 409289857Sobrien p->pc_count = 0; 409389857Sobrien } 409489857Sobrien 409589857Sobrien p->count += 1; 4096130561Sobrien if (!MUST_BE_DYN_RELOC (r_type)) 409789857Sobrien p->pc_count += 1; 409889857Sobrien } 409989857Sobrien break; 410089857Sobrien 410189857Sobrien default: 410292828Sobrien break; 410389857Sobrien } 410489857Sobrien } 410589857Sobrien 4106130561Sobrien return TRUE; 410789857Sobrien} 410889857Sobrien 410989857Sobrien/* Return the section that should be marked against GC for a given 411089857Sobrien relocation. */ 411189857Sobrien 411289857Sobrienstatic asection * 4113130561Sobrienppc64_elf_gc_mark_hook (asection *sec, 4114130561Sobrien struct bfd_link_info *info ATTRIBUTE_UNUSED, 4115130561Sobrien Elf_Internal_Rela *rel, 4116130561Sobrien struct elf_link_hash_entry *h, 4117130561Sobrien Elf_Internal_Sym *sym) 411889857Sobrien{ 4119104834Sobrien asection *rsec = NULL; 4120104834Sobrien 412189857Sobrien if (h != NULL) 412289857Sobrien { 4123130561Sobrien enum elf_ppc64_reloc_type r_type; 4124104834Sobrien struct ppc_link_hash_entry *fdh; 412589857Sobrien 4126130561Sobrien r_type = ELF64_R_TYPE (rel->r_info); 412789857Sobrien switch (r_type) 412889857Sobrien { 412989857Sobrien case R_PPC64_GNU_VTINHERIT: 413089857Sobrien case R_PPC64_GNU_VTENTRY: 413189857Sobrien break; 413289857Sobrien 413389857Sobrien default: 413489857Sobrien switch (h->root.type) 413589857Sobrien { 413689857Sobrien case bfd_link_hash_defined: 413789857Sobrien case bfd_link_hash_defweak: 4138104834Sobrien fdh = (struct ppc_link_hash_entry *) h; 413989857Sobrien 4140104834Sobrien /* Function descriptor syms cause the associated 4141104834Sobrien function code sym section to be marked. */ 4142104834Sobrien if (fdh->is_func_descriptor) 4143104834Sobrien rsec = fdh->oh->root.u.def.section; 4144104834Sobrien 4145104834Sobrien /* Function entry syms return NULL if they are in .opd 4146104834Sobrien and are not ._start (or others undefined on the ld 4147104834Sobrien command line). Thus we avoid marking all function 4148130561Sobrien sections, as all functions are referenced in .opd. */ 4149104834Sobrien else if ((fdh->oh != NULL 4150104834Sobrien && ((struct ppc_link_hash_entry *) fdh->oh)->is_entry) 4151130561Sobrien || ppc64_elf_section_data (sec)->opd.func_sec == NULL) 4152104834Sobrien rsec = h->root.u.def.section; 4153104834Sobrien break; 4154104834Sobrien 415589857Sobrien case bfd_link_hash_common: 4156104834Sobrien rsec = h->root.u.c.p->section; 4157104834Sobrien break; 415889857Sobrien 415989857Sobrien default: 416089857Sobrien break; 416189857Sobrien } 416289857Sobrien } 416389857Sobrien } 416489857Sobrien else 416589857Sobrien { 4166104834Sobrien asection **opd_sym_section; 4167104834Sobrien 4168104834Sobrien rsec = bfd_section_from_elf_index (sec->owner, sym->st_shndx); 4169130561Sobrien opd_sym_section = ppc64_elf_section_data (rsec)->opd.func_sec; 4170104834Sobrien if (opd_sym_section != NULL) 4171104834Sobrien rsec = opd_sym_section[sym->st_value / 24]; 4172130561Sobrien else if (ppc64_elf_section_data (sec)->opd.func_sec != NULL) 4173104834Sobrien rsec = NULL; 417489857Sobrien } 417589857Sobrien 4176104834Sobrien return rsec; 417789857Sobrien} 417889857Sobrien 417989857Sobrien/* Update the .got, .plt. and dynamic reloc reference counts for the 418089857Sobrien section being removed. */ 418189857Sobrien 4182130561Sobrienstatic bfd_boolean 4183130561Sobrienppc64_elf_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info, 4184130561Sobrien asection *sec, const Elf_Internal_Rela *relocs) 418589857Sobrien{ 4186130561Sobrien struct ppc_link_hash_table *htab; 418789857Sobrien Elf_Internal_Shdr *symtab_hdr; 418889857Sobrien struct elf_link_hash_entry **sym_hashes; 4189130561Sobrien struct got_entry **local_got_ents; 419089857Sobrien const Elf_Internal_Rela *rel, *relend; 419189857Sobrien 4192130561Sobrien if ((sec->flags & SEC_ALLOC) == 0) 4193130561Sobrien return TRUE; 4194130561Sobrien 419589857Sobrien elf_section_data (sec)->local_dynrel = NULL; 419689857Sobrien 4197130561Sobrien htab = ppc_hash_table (info); 419889857Sobrien symtab_hdr = &elf_tdata (abfd)->symtab_hdr; 419989857Sobrien sym_hashes = elf_sym_hashes (abfd); 4200130561Sobrien local_got_ents = elf_local_got_ents (abfd); 420189857Sobrien 420289857Sobrien relend = relocs + sec->reloc_count; 420389857Sobrien for (rel = relocs; rel < relend; rel++) 420489857Sobrien { 420589857Sobrien unsigned long r_symndx; 4206130561Sobrien enum elf_ppc64_reloc_type r_type; 4207130561Sobrien struct elf_link_hash_entry *h = NULL; 4208130561Sobrien char tls_type = 0; 420989857Sobrien 421089857Sobrien r_symndx = ELF64_R_SYM (rel->r_info); 4211130561Sobrien r_type = ELF64_R_TYPE (rel->r_info); 4212130561Sobrien if (r_symndx >= symtab_hdr->sh_info) 4213130561Sobrien { 4214130561Sobrien struct ppc_link_hash_entry *eh; 4215130561Sobrien struct ppc_dyn_relocs **pp; 4216130561Sobrien struct ppc_dyn_relocs *p; 4217130561Sobrien 4218130561Sobrien h = sym_hashes[r_symndx - symtab_hdr->sh_info]; 4219130561Sobrien eh = (struct ppc_link_hash_entry *) h; 4220130561Sobrien 4221130561Sobrien for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next) 4222130561Sobrien if (p->sec == sec) 4223130561Sobrien { 4224130561Sobrien /* Everything must go for SEC. */ 4225130561Sobrien *pp = p->next; 4226130561Sobrien break; 4227130561Sobrien } 4228130561Sobrien } 4229130561Sobrien 423089857Sobrien switch (r_type) 423189857Sobrien { 4232130561Sobrien case R_PPC64_GOT_TLSLD16: 4233130561Sobrien case R_PPC64_GOT_TLSLD16_LO: 4234130561Sobrien case R_PPC64_GOT_TLSLD16_HI: 4235130561Sobrien case R_PPC64_GOT_TLSLD16_HA: 4236130561Sobrien ppc64_tlsld_got (abfd)->refcount -= 1; 4237130561Sobrien tls_type = TLS_TLS | TLS_LD; 4238130561Sobrien goto dogot; 4239130561Sobrien 4240130561Sobrien case R_PPC64_GOT_TLSGD16: 4241130561Sobrien case R_PPC64_GOT_TLSGD16_LO: 4242130561Sobrien case R_PPC64_GOT_TLSGD16_HI: 4243130561Sobrien case R_PPC64_GOT_TLSGD16_HA: 4244130561Sobrien tls_type = TLS_TLS | TLS_GD; 4245130561Sobrien goto dogot; 4246130561Sobrien 4247130561Sobrien case R_PPC64_GOT_TPREL16_DS: 4248130561Sobrien case R_PPC64_GOT_TPREL16_LO_DS: 4249130561Sobrien case R_PPC64_GOT_TPREL16_HI: 4250130561Sobrien case R_PPC64_GOT_TPREL16_HA: 4251130561Sobrien tls_type = TLS_TLS | TLS_TPREL; 4252130561Sobrien goto dogot; 4253130561Sobrien 4254130561Sobrien case R_PPC64_GOT_DTPREL16_DS: 4255130561Sobrien case R_PPC64_GOT_DTPREL16_LO_DS: 4256130561Sobrien case R_PPC64_GOT_DTPREL16_HI: 4257130561Sobrien case R_PPC64_GOT_DTPREL16_HA: 4258130561Sobrien tls_type = TLS_TLS | TLS_DTPREL; 4259130561Sobrien goto dogot; 4260130561Sobrien 426189857Sobrien case R_PPC64_GOT16: 426289857Sobrien case R_PPC64_GOT16_DS: 426389857Sobrien case R_PPC64_GOT16_HA: 426489857Sobrien case R_PPC64_GOT16_HI: 426589857Sobrien case R_PPC64_GOT16_LO: 426689857Sobrien case R_PPC64_GOT16_LO_DS: 4267130561Sobrien dogot: 4268130561Sobrien { 4269130561Sobrien struct got_entry *ent; 4270130561Sobrien 4271130561Sobrien if (h != NULL) 4272130561Sobrien ent = h->got.glist; 4273130561Sobrien else 4274130561Sobrien ent = local_got_ents[r_symndx]; 4275130561Sobrien 4276130561Sobrien for (; ent != NULL; ent = ent->next) 4277130561Sobrien if (ent->addend == rel->r_addend 4278130561Sobrien && ent->owner == abfd 4279130561Sobrien && ent->tls_type == tls_type) 4280130561Sobrien break; 4281130561Sobrien if (ent == NULL) 4282130561Sobrien abort (); 4283130561Sobrien if (ent->got.refcount > 0) 4284130561Sobrien ent->got.refcount -= 1; 4285130561Sobrien } 428689857Sobrien break; 428789857Sobrien 428889857Sobrien case R_PPC64_PLT16_HA: 428989857Sobrien case R_PPC64_PLT16_HI: 429089857Sobrien case R_PPC64_PLT16_LO: 429189857Sobrien case R_PPC64_PLT32: 429289857Sobrien case R_PPC64_PLT64: 4293104834Sobrien case R_PPC64_REL14: 4294104834Sobrien case R_PPC64_REL14_BRNTAKEN: 4295104834Sobrien case R_PPC64_REL14_BRTAKEN: 429689857Sobrien case R_PPC64_REL24: 4297130561Sobrien if (h != NULL) 429889857Sobrien { 4299130561Sobrien struct plt_entry *ent; 430089857Sobrien 4301130561Sobrien for (ent = h->plt.plist; ent != NULL; ent = ent->next) 4302130561Sobrien if (ent->addend == rel->r_addend) 4303130561Sobrien break; 4304130561Sobrien if (ent == NULL) 4305130561Sobrien abort (); 4306130561Sobrien if (ent->plt.refcount > 0) 4307130561Sobrien ent->plt.refcount -= 1; 430889857Sobrien } 430989857Sobrien break; 431089857Sobrien 431189857Sobrien default: 431289857Sobrien break; 431389857Sobrien } 431489857Sobrien } 4315130561Sobrien return TRUE; 431689857Sobrien} 431789857Sobrien 431889857Sobrien/* Called via elf_link_hash_traverse to transfer dynamic linking 431989857Sobrien information on function code symbol entries to their corresponding 432089857Sobrien function descriptor symbol entries. */ 4321130561Sobrienstatic bfd_boolean 4322130561Sobrienfunc_desc_adjust (struct elf_link_hash_entry *h, void *inf) 432389857Sobrien{ 432489857Sobrien struct bfd_link_info *info; 432589857Sobrien struct ppc_link_hash_table *htab; 4326130561Sobrien struct plt_entry *ent; 4327130561Sobrien struct ppc_link_hash_entry *fh; 4328130561Sobrien struct ppc_link_hash_entry *fdh; 4329130561Sobrien bfd_boolean force_local; 433089857Sobrien 4331130561Sobrien fh = (struct ppc_link_hash_entry *) h; 4332130561Sobrien if (fh->elf.root.type == bfd_link_hash_indirect) 4333130561Sobrien return TRUE; 433489857Sobrien 4335130561Sobrien if (fh->elf.root.type == bfd_link_hash_warning) 4336130561Sobrien fh = (struct ppc_link_hash_entry *) fh->elf.root.u.i.link; 433794536Sobrien 4338130561Sobrien info = inf; 433989857Sobrien htab = ppc_hash_table (info); 434089857Sobrien 434189857Sobrien /* If this is a function code symbol, transfer dynamic linking 434289857Sobrien information to the function descriptor symbol. */ 4343130561Sobrien if (!fh->is_func) 4344130561Sobrien return TRUE; 434589857Sobrien 4346130561Sobrien if (fh->elf.root.type == bfd_link_hash_undefweak 4347130561Sobrien && (fh->elf.elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR)) 4348130561Sobrien htab->have_undefweak = TRUE; 434999461Sobrien 4350130561Sobrien for (ent = fh->elf.plt.plist; ent != NULL; ent = ent->next) 4351130561Sobrien if (ent->plt.refcount > 0) 4352130561Sobrien break; 4353130561Sobrien if (ent == NULL 4354130561Sobrien || fh->elf.root.root.string[0] != '.' 4355130561Sobrien || fh->elf.root.root.string[1] == '\0') 4356130561Sobrien return TRUE; 435789857Sobrien 4358130561Sobrien /* Find the corresponding function descriptor symbol. Create it 4359130561Sobrien as undefined if necessary. */ 436089857Sobrien 4361130561Sobrien fdh = get_fdh (fh, htab); 4362130561Sobrien if (fdh != NULL) 4363130561Sobrien while (fdh->elf.root.type == bfd_link_hash_indirect 4364130561Sobrien || fdh->elf.root.type == bfd_link_hash_warning) 4365130561Sobrien fdh = (struct ppc_link_hash_entry *) fdh->elf.root.u.i.link; 436689857Sobrien 4367130561Sobrien if (fdh == NULL 4368130561Sobrien && info->shared 4369130561Sobrien && (fh->elf.root.type == bfd_link_hash_undefined 4370130561Sobrien || fh->elf.root.type == bfd_link_hash_undefweak)) 4371130561Sobrien { 4372130561Sobrien bfd *abfd; 4373130561Sobrien asymbol *newsym; 4374130561Sobrien struct bfd_link_hash_entry *bh; 437589857Sobrien 4376130561Sobrien abfd = fh->elf.root.u.undef.abfd; 4377130561Sobrien newsym = bfd_make_empty_symbol (abfd); 4378130561Sobrien newsym->name = fh->elf.root.root.string + 1; 4379130561Sobrien newsym->section = bfd_und_section_ptr; 4380130561Sobrien newsym->value = 0; 4381130561Sobrien newsym->flags = BSF_OBJECT; 4382130561Sobrien if (fh->elf.root.type == bfd_link_hash_undefweak) 4383130561Sobrien newsym->flags |= BSF_WEAK; 438489857Sobrien 4385130561Sobrien bh = &fdh->elf.root; 4386130561Sobrien if ( !(_bfd_generic_link_add_one_symbol 4387130561Sobrien (info, abfd, newsym->name, newsym->flags, 4388130561Sobrien newsym->section, newsym->value, NULL, FALSE, FALSE, &bh))) 4389130561Sobrien { 4390130561Sobrien return FALSE; 439189857Sobrien } 4392130561Sobrien fdh = (struct ppc_link_hash_entry *) bh; 4393130561Sobrien fdh->elf.elf_link_hash_flags &= ~ELF_LINK_NON_ELF; 4394130561Sobrien fdh->elf.size = 24; 4395130561Sobrien fdh->elf.type = STT_OBJECT; 4396130561Sobrien } 439789857Sobrien 4398130561Sobrien if (fdh != NULL 4399130561Sobrien && (fdh->elf.elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0 4400130561Sobrien && (info->shared 4401130561Sobrien || (fdh->elf.elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0 4402130561Sobrien || (fdh->elf.elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) != 0 4403130561Sobrien || (fdh->elf.root.type == bfd_link_hash_undefweak 4404130561Sobrien && ELF_ST_VISIBILITY (fdh->elf.other) == STV_DEFAULT))) 4405130561Sobrien { 4406130561Sobrien if (fdh->elf.dynindx == -1) 4407130561Sobrien if (! bfd_elf_link_record_dynamic_symbol (info, &fdh->elf)) 4408130561Sobrien return FALSE; 4409130561Sobrien fdh->elf.elf_link_hash_flags 4410130561Sobrien |= (fh->elf.elf_link_hash_flags & (ELF_LINK_HASH_REF_REGULAR 4411130561Sobrien | ELF_LINK_HASH_REF_DYNAMIC 4412130561Sobrien | ELF_LINK_HASH_REF_REGULAR_NONWEAK 4413130561Sobrien | ELF_LINK_NON_GOT_REF)); 4414130561Sobrien if (ELF_ST_VISIBILITY (fh->elf.other) == STV_DEFAULT) 441589857Sobrien { 4416130561Sobrien fdh->elf.plt.plist = fh->elf.plt.plist; 4417130561Sobrien fdh->elf.elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; 441889857Sobrien } 4419130561Sobrien fdh->is_func_descriptor = 1; 4420130561Sobrien fdh->oh = &fh->elf; 4421130561Sobrien fh->oh = &fdh->elf; 442289857Sobrien } 442389857Sobrien 4424130561Sobrien /* Now that the info is on the function descriptor, clear the 4425130561Sobrien function code sym info. Any function code syms for which we 4426130561Sobrien don't have a definition in a regular file, we force local. 4427130561Sobrien This prevents a shared library from exporting syms that have 4428130561Sobrien been imported from another library. Function code syms that 4429130561Sobrien are really in the library we must leave global to prevent the 4430130561Sobrien linker dragging in a definition from a static library. */ 4431130561Sobrien force_local 4432130561Sobrien = (info->shared 4433130561Sobrien && ((fh->elf.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0 4434130561Sobrien || fdh == NULL 4435130561Sobrien || (fdh->elf.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0 4436130561Sobrien || (fdh->elf.elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0)); 4437130561Sobrien _bfd_elf_link_hash_hide_symbol (info, &fh->elf, force_local); 4438130561Sobrien 4439130561Sobrien return TRUE; 444089857Sobrien} 444189857Sobrien 444292828Sobrien#define MIN_SAVE_FPR 14 444392828Sobrien#define MAX_SAVE_FPR 31 444492828Sobrien 444589857Sobrien/* Called near the start of bfd_elf_size_dynamic_sections. We use 444692828Sobrien this hook to a) provide some gcc support functions, and b) transfer 444792828Sobrien dynamic linking information gathered so far on function code symbol 444892828Sobrien entries, to their corresponding function descriptor symbol entries. */ 4449130561Sobrienstatic bfd_boolean 4450130561Sobrienppc64_elf_func_desc_adjust (bfd *obfd ATTRIBUTE_UNUSED, 4451130561Sobrien struct bfd_link_info *info) 445289857Sobrien{ 445389857Sobrien struct ppc_link_hash_table *htab; 445492828Sobrien unsigned int lowest_savef = MAX_SAVE_FPR + 2; 445592828Sobrien unsigned int lowest_restf = MAX_SAVE_FPR + 2; 445692828Sobrien unsigned int i; 445792828Sobrien struct elf_link_hash_entry *h; 445899461Sobrien bfd_byte *p; 445992828Sobrien char sym[10]; 446089857Sobrien 446189857Sobrien htab = ppc_hash_table (info); 446292828Sobrien 446392828Sobrien if (htab->sfpr == NULL) 446492828Sobrien /* We don't have any relocs. */ 4465130561Sobrien return TRUE; 446692828Sobrien 446792828Sobrien /* First provide any missing ._savef* and ._restf* functions. */ 446892828Sobrien memcpy (sym, "._savef14", 10); 446992828Sobrien for (i = MIN_SAVE_FPR; i <= MAX_SAVE_FPR; i++) 447092828Sobrien { 447192828Sobrien sym[7] = i / 10 + '0'; 447292828Sobrien sym[8] = i % 10 + '0'; 4473130561Sobrien h = elf_link_hash_lookup (&htab->elf, sym, FALSE, FALSE, TRUE); 447492828Sobrien if (h != NULL 4475130561Sobrien && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) 447692828Sobrien { 447792828Sobrien if (lowest_savef > i) 447892828Sobrien lowest_savef = i; 447992828Sobrien h->root.type = bfd_link_hash_defined; 448092828Sobrien h->root.u.def.section = htab->sfpr; 448192828Sobrien h->root.u.def.value = (i - lowest_savef) * 4; 448292828Sobrien h->type = STT_FUNC; 448392828Sobrien h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR; 4484130561Sobrien _bfd_elf_link_hash_hide_symbol (info, h, TRUE); 448592828Sobrien } 448692828Sobrien } 448792828Sobrien 448892828Sobrien memcpy (sym, "._restf14", 10); 448992828Sobrien for (i = MIN_SAVE_FPR; i <= MAX_SAVE_FPR; i++) 449092828Sobrien { 449192828Sobrien sym[7] = i / 10 + '0'; 449292828Sobrien sym[8] = i % 10 + '0'; 4493130561Sobrien h = elf_link_hash_lookup (&htab->elf, sym, FALSE, FALSE, TRUE); 449492828Sobrien if (h != NULL 4495130561Sobrien && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) 449692828Sobrien { 449792828Sobrien if (lowest_restf > i) 449892828Sobrien lowest_restf = i; 449992828Sobrien h->root.type = bfd_link_hash_defined; 450092828Sobrien h->root.u.def.section = htab->sfpr; 450192828Sobrien h->root.u.def.value = ((MAX_SAVE_FPR + 2 - lowest_savef) * 4 450292828Sobrien + (i - lowest_restf) * 4); 450392828Sobrien h->type = STT_FUNC; 450492828Sobrien h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR; 4505130561Sobrien _bfd_elf_link_hash_hide_symbol (info, h, TRUE); 450692828Sobrien } 450792828Sobrien } 450892828Sobrien 4509130561Sobrien elf_link_hash_traverse (&htab->elf, func_desc_adjust, info); 451099461Sobrien 451192828Sobrien htab->sfpr->_raw_size = ((MAX_SAVE_FPR + 2 - lowest_savef) * 4 451292828Sobrien + (MAX_SAVE_FPR + 2 - lowest_restf) * 4); 451392828Sobrien 451492828Sobrien if (htab->sfpr->_raw_size == 0) 451592828Sobrien { 451699461Sobrien if (!htab->have_undefweak) 451799461Sobrien { 451899461Sobrien _bfd_strip_section_from_output (info, htab->sfpr); 4519130561Sobrien return TRUE; 452099461Sobrien } 452199461Sobrien 452299461Sobrien htab->sfpr->_raw_size = 4; 452392828Sobrien } 452499461Sobrien 4525130561Sobrien p = bfd_alloc (htab->elf.dynobj, htab->sfpr->_raw_size); 452699461Sobrien if (p == NULL) 4527130561Sobrien return FALSE; 452899461Sobrien htab->sfpr->contents = p; 452999461Sobrien 453099461Sobrien for (i = lowest_savef; i <= MAX_SAVE_FPR; i++) 453192828Sobrien { 453299461Sobrien unsigned int fpr = i << 21; 453399461Sobrien unsigned int stackoff = (1 << 16) - (MAX_SAVE_FPR + 1 - i) * 8; 453499461Sobrien bfd_put_32 (htab->elf.dynobj, STFD_FR0_0R1 + fpr + stackoff, p); 453599461Sobrien p += 4; 453699461Sobrien } 453799461Sobrien if (lowest_savef <= MAX_SAVE_FPR) 453899461Sobrien { 453992828Sobrien bfd_put_32 (htab->elf.dynobj, BLR, p); 454092828Sobrien p += 4; 454199461Sobrien } 454292828Sobrien 454399461Sobrien for (i = lowest_restf; i <= MAX_SAVE_FPR; i++) 454499461Sobrien { 454599461Sobrien unsigned int fpr = i << 21; 454699461Sobrien unsigned int stackoff = (1 << 16) - (MAX_SAVE_FPR + 1 - i) * 8; 454799461Sobrien bfd_put_32 (htab->elf.dynobj, LFD_FR0_0R1 + fpr + stackoff, p); 454892828Sobrien p += 4; 454992828Sobrien } 455099461Sobrien if (lowest_restf <= MAX_SAVE_FPR 455199461Sobrien || htab->sfpr->_raw_size == 4) 455299461Sobrien { 455399461Sobrien bfd_put_32 (htab->elf.dynobj, BLR, p); 455499461Sobrien } 455592828Sobrien 4556130561Sobrien return TRUE; 455789857Sobrien} 455889857Sobrien 455989857Sobrien/* Adjust a symbol defined by a dynamic object and referenced by a 456089857Sobrien regular object. The current definition is in some section of the 456189857Sobrien dynamic object, but we're not including those sections. We have to 456289857Sobrien change the definition to something the rest of the link can 456389857Sobrien understand. */ 456489857Sobrien 4565130561Sobrienstatic bfd_boolean 4566130561Sobrienppc64_elf_adjust_dynamic_symbol (struct bfd_link_info *info, 4567130561Sobrien struct elf_link_hash_entry *h) 456889857Sobrien{ 456989857Sobrien struct ppc_link_hash_table *htab; 457089857Sobrien asection *s; 457189857Sobrien unsigned int power_of_two; 457289857Sobrien 457389857Sobrien htab = ppc_hash_table (info); 457489857Sobrien 457589857Sobrien /* Deal with function syms. */ 457689857Sobrien if (h->type == STT_FUNC 457789857Sobrien || (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0) 457889857Sobrien { 457989857Sobrien /* Clear procedure linkage table information for any symbol that 458089857Sobrien won't need a .plt entry. */ 4581130561Sobrien struct plt_entry *ent; 4582130561Sobrien for (ent = h->plt.plist; ent != NULL; ent = ent->next) 4583130561Sobrien if (ent->plt.refcount > 0) 4584130561Sobrien break; 458589857Sobrien if (!((struct ppc_link_hash_entry *) h)->is_func_descriptor 4586130561Sobrien || ent == NULL 4587130561Sobrien || SYMBOL_CALLS_LOCAL (info, h) 4588130561Sobrien || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT 4589130561Sobrien && h->root.type == bfd_link_hash_undefweak)) 459089857Sobrien { 4591130561Sobrien h->plt.plist = NULL; 459289857Sobrien h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; 459389857Sobrien } 459489857Sobrien } 459589857Sobrien else 4596130561Sobrien h->plt.plist = NULL; 459789857Sobrien 459889857Sobrien /* If this is a weak symbol, and there is a real definition, the 459989857Sobrien processor independent code will have arranged for us to see the 460089857Sobrien real definition first, and we can just use the same value. */ 460189857Sobrien if (h->weakdef != NULL) 460289857Sobrien { 460389857Sobrien BFD_ASSERT (h->weakdef->root.type == bfd_link_hash_defined 460489857Sobrien || h->weakdef->root.type == bfd_link_hash_defweak); 460589857Sobrien h->root.u.def.section = h->weakdef->root.u.def.section; 460689857Sobrien h->root.u.def.value = h->weakdef->root.u.def.value; 4607130561Sobrien if (ELIMINATE_COPY_RELOCS) 4608130561Sobrien h->elf_link_hash_flags 4609130561Sobrien = ((h->elf_link_hash_flags & ~ELF_LINK_NON_GOT_REF) 4610130561Sobrien | (h->weakdef->elf_link_hash_flags & ELF_LINK_NON_GOT_REF)); 4611130561Sobrien return TRUE; 461289857Sobrien } 461389857Sobrien 461489857Sobrien /* If we are creating a shared library, we must presume that the 461589857Sobrien only references to the symbol are via the global offset table. 461689857Sobrien For such cases we need not do anything here; the relocations will 461789857Sobrien be handled correctly by relocate_section. */ 461889857Sobrien if (info->shared) 4619130561Sobrien return TRUE; 462089857Sobrien 462189857Sobrien /* If there are no references to this symbol that do not use the 462289857Sobrien GOT, we don't need to generate a copy reloc. */ 462389857Sobrien if ((h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0) 4624130561Sobrien return TRUE; 462589857Sobrien 4626130561Sobrien if (ELIMINATE_COPY_RELOCS) 462789857Sobrien { 4628130561Sobrien struct ppc_link_hash_entry * eh; 4629130561Sobrien struct ppc_dyn_relocs *p; 4630130561Sobrien 4631130561Sobrien eh = (struct ppc_link_hash_entry *) h; 4632130561Sobrien for (p = eh->dyn_relocs; p != NULL; p = p->next) 4633130561Sobrien { 4634130561Sobrien s = p->sec->output_section; 4635130561Sobrien if (s != NULL && (s->flags & SEC_READONLY) != 0) 4636130561Sobrien break; 4637130561Sobrien } 4638130561Sobrien 4639130561Sobrien /* If we didn't find any dynamic relocs in read-only sections, then 4640130561Sobrien we'll be keeping the dynamic relocs and avoiding the copy reloc. */ 4641130561Sobrien if (p == NULL) 4642130561Sobrien { 4643130561Sobrien h->elf_link_hash_flags &= ~ELF_LINK_NON_GOT_REF; 4644130561Sobrien return TRUE; 4645130561Sobrien } 464689857Sobrien } 464789857Sobrien 4648130561Sobrien if (h->plt.plist != NULL) 464989857Sobrien { 4650130561Sobrien /* We should never get here, but unfortunately there are versions 4651130561Sobrien of gcc out there that improperly (for this ABI) put initialized 4652130561Sobrien function pointers, vtable refs and suchlike in read-only 4653130561Sobrien sections. Allow them to proceed, but warn that this might 4654130561Sobrien break at runtime. */ 4655130561Sobrien (*_bfd_error_handler) 4656130561Sobrien (_("copy reloc against `%s' requires lazy plt linking; " 4657130561Sobrien "avoid setting LD_BIND_NOW=1 or upgrade gcc"), 4658130561Sobrien h->root.root.string); 465989857Sobrien } 466089857Sobrien 4661130561Sobrien /* This is a reference to a symbol defined by a dynamic object which 4662130561Sobrien is not a function. */ 4663130561Sobrien 466489857Sobrien /* We must allocate the symbol in our .dynbss section, which will 466589857Sobrien become part of the .bss section of the executable. There will be 466689857Sobrien an entry for this symbol in the .dynsym section. The dynamic 466789857Sobrien object will contain position independent code, so all references 466889857Sobrien from the dynamic object to this symbol will go through the global 466989857Sobrien offset table. The dynamic linker will use the .dynsym entry to 467089857Sobrien determine the address it must put in the global offset table, so 467189857Sobrien both the dynamic object and the regular object will refer to the 467289857Sobrien same memory location for the variable. */ 467389857Sobrien 4674130561Sobrien /* We must generate a R_PPC64_COPY reloc to tell the dynamic linker 4675130561Sobrien to copy the initial value out of the dynamic object and into the 467689857Sobrien runtime process image. We need to remember the offset into the 467789857Sobrien .rela.bss section we are going to use. */ 467889857Sobrien if ((h->root.u.def.section->flags & SEC_ALLOC) != 0) 467989857Sobrien { 4680130561Sobrien htab->relbss->_raw_size += sizeof (Elf64_External_Rela); 468189857Sobrien h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_COPY; 468289857Sobrien } 468389857Sobrien 468489857Sobrien /* We need to figure out the alignment required for this symbol. I 468589857Sobrien have no idea how ELF linkers handle this. */ 468689857Sobrien power_of_two = bfd_log2 (h->size); 468789857Sobrien if (power_of_two > 4) 468889857Sobrien power_of_two = 4; 468989857Sobrien 469089857Sobrien /* Apply the required alignment. */ 4691130561Sobrien s = htab->dynbss; 469289857Sobrien s->_raw_size = BFD_ALIGN (s->_raw_size, (bfd_size_type) (1 << power_of_two)); 469389857Sobrien if (power_of_two > bfd_get_section_alignment (htab->elf.dynobj, s)) 469489857Sobrien { 469589857Sobrien if (! bfd_set_section_alignment (htab->elf.dynobj, s, power_of_two)) 4696130561Sobrien return FALSE; 469789857Sobrien } 469889857Sobrien 469989857Sobrien /* Define the symbol as being at this point in the section. */ 470089857Sobrien h->root.u.def.section = s; 470189857Sobrien h->root.u.def.value = s->_raw_size; 470289857Sobrien 470389857Sobrien /* Increment the section size to make room for the symbol. */ 470489857Sobrien s->_raw_size += h->size; 470589857Sobrien 4706130561Sobrien return TRUE; 470789857Sobrien} 470889857Sobrien 470989857Sobrien/* If given a function descriptor symbol, hide both the function code 471089857Sobrien sym and the descriptor. */ 471189857Sobrienstatic void 4712130561Sobrienppc64_elf_hide_symbol (struct bfd_link_info *info, 4713130561Sobrien struct elf_link_hash_entry *h, 4714130561Sobrien bfd_boolean force_local) 471589857Sobrien{ 471689857Sobrien _bfd_elf_link_hash_hide_symbol (info, h, force_local); 471789857Sobrien 471889857Sobrien if (((struct ppc_link_hash_entry *) h)->is_func_descriptor) 471989857Sobrien { 4720104834Sobrien struct elf_link_hash_entry *fh = ((struct ppc_link_hash_entry *) h)->oh; 472189857Sobrien 4722104834Sobrien if (fh == NULL) 4723104834Sobrien { 4724104834Sobrien const char *p, *q; 4725104834Sobrien struct ppc_link_hash_table *htab; 4726104834Sobrien char save; 4727104834Sobrien 4728104834Sobrien /* We aren't supposed to use alloca in BFD because on 4729104834Sobrien systems which do not have alloca the version in libiberty 4730104834Sobrien calls xmalloc, which might cause the program to crash 4731104834Sobrien when it runs out of memory. This function doesn't have a 4732104834Sobrien return status, so there's no way to gracefully return an 4733104834Sobrien error. So cheat. We know that string[-1] can be safely 4734104834Sobrien dereferenced; It's either a string in an ELF string 4735104834Sobrien table, or allocated in an objalloc structure. */ 4736104834Sobrien 4737104834Sobrien p = h->root.root.string - 1; 4738104834Sobrien save = *p; 4739104834Sobrien *(char *) p = '.'; 4740104834Sobrien htab = ppc_hash_table (info); 4741130561Sobrien fh = elf_link_hash_lookup (&htab->elf, p, FALSE, FALSE, FALSE); 4742104834Sobrien *(char *) p = save; 4743104834Sobrien 4744104834Sobrien /* Unfortunately, if it so happens that the string we were 4745104834Sobrien looking for was allocated immediately before this string, 4746104834Sobrien then we overwrote the string terminator. That's the only 4747104834Sobrien reason the lookup should fail. */ 4748104834Sobrien if (fh == NULL) 4749104834Sobrien { 4750104834Sobrien q = h->root.root.string + strlen (h->root.root.string); 4751104834Sobrien while (q >= h->root.root.string && *q == *p) 4752104834Sobrien --q, --p; 4753104834Sobrien if (q < h->root.root.string && *p == '.') 4754130561Sobrien fh = elf_link_hash_lookup (&htab->elf, p, FALSE, FALSE, FALSE); 4755104834Sobrien } 4756104834Sobrien if (fh != NULL) 4757104834Sobrien { 4758104834Sobrien ((struct ppc_link_hash_entry *) h)->oh = fh; 4759104834Sobrien ((struct ppc_link_hash_entry *) fh)->oh = h; 4760104834Sobrien } 4761104834Sobrien } 476289857Sobrien if (fh != NULL) 476389857Sobrien _bfd_elf_link_hash_hide_symbol (info, fh, force_local); 476489857Sobrien } 476589857Sobrien} 476689857Sobrien 4767130561Sobrienstatic bfd_boolean 4768130561Sobrienget_sym_h (struct elf_link_hash_entry **hp, Elf_Internal_Sym **symp, 4769130561Sobrien asection **symsecp, char **tls_maskp, Elf_Internal_Sym **locsymsp, 4770130561Sobrien unsigned long r_symndx, bfd *ibfd) 4771104834Sobrien{ 4772130561Sobrien Elf_Internal_Shdr *symtab_hdr = &elf_tdata (ibfd)->symtab_hdr; 4773130561Sobrien 4774130561Sobrien if (r_symndx >= symtab_hdr->sh_info) 4775130561Sobrien { 4776130561Sobrien struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (ibfd); 4777130561Sobrien struct elf_link_hash_entry *h; 4778130561Sobrien 4779130561Sobrien h = sym_hashes[r_symndx - symtab_hdr->sh_info]; 4780130561Sobrien while (h->root.type == bfd_link_hash_indirect 4781130561Sobrien || h->root.type == bfd_link_hash_warning) 4782130561Sobrien h = (struct elf_link_hash_entry *) h->root.u.i.link; 4783130561Sobrien 4784130561Sobrien if (hp != NULL) 4785130561Sobrien *hp = h; 4786130561Sobrien 4787130561Sobrien if (symp != NULL) 4788130561Sobrien *symp = NULL; 4789130561Sobrien 4790130561Sobrien if (symsecp != NULL) 4791130561Sobrien { 4792130561Sobrien asection *symsec = NULL; 4793130561Sobrien if (h->root.type == bfd_link_hash_defined 4794130561Sobrien || h->root.type == bfd_link_hash_defweak) 4795130561Sobrien symsec = h->root.u.def.section; 4796130561Sobrien *symsecp = symsec; 4797130561Sobrien } 4798130561Sobrien 4799130561Sobrien if (tls_maskp != NULL) 4800130561Sobrien { 4801130561Sobrien struct ppc_link_hash_entry *eh; 4802130561Sobrien 4803130561Sobrien eh = (struct ppc_link_hash_entry *) h; 4804130561Sobrien *tls_maskp = &eh->tls_mask; 4805130561Sobrien } 4806130561Sobrien } 4807130561Sobrien else 4808130561Sobrien { 4809130561Sobrien Elf_Internal_Sym *sym; 4810130561Sobrien Elf_Internal_Sym *locsyms = *locsymsp; 4811130561Sobrien 4812130561Sobrien if (locsyms == NULL) 4813130561Sobrien { 4814130561Sobrien locsyms = (Elf_Internal_Sym *) symtab_hdr->contents; 4815130561Sobrien if (locsyms == NULL) 4816130561Sobrien locsyms = bfd_elf_get_elf_syms (ibfd, symtab_hdr, 4817130561Sobrien symtab_hdr->sh_info, 4818130561Sobrien 0, NULL, NULL, NULL); 4819130561Sobrien if (locsyms == NULL) 4820130561Sobrien return FALSE; 4821130561Sobrien *locsymsp = locsyms; 4822130561Sobrien } 4823130561Sobrien sym = locsyms + r_symndx; 4824130561Sobrien 4825130561Sobrien if (hp != NULL) 4826130561Sobrien *hp = NULL; 4827130561Sobrien 4828130561Sobrien if (symp != NULL) 4829130561Sobrien *symp = sym; 4830130561Sobrien 4831130561Sobrien if (symsecp != NULL) 4832130561Sobrien { 4833130561Sobrien asection *symsec = NULL; 4834130561Sobrien if ((sym->st_shndx != SHN_UNDEF 4835130561Sobrien && sym->st_shndx < SHN_LORESERVE) 4836130561Sobrien || sym->st_shndx > SHN_HIRESERVE) 4837130561Sobrien symsec = bfd_section_from_elf_index (ibfd, sym->st_shndx); 4838130561Sobrien *symsecp = symsec; 4839130561Sobrien } 4840130561Sobrien 4841130561Sobrien if (tls_maskp != NULL) 4842130561Sobrien { 4843130561Sobrien struct got_entry **lgot_ents; 4844130561Sobrien char *tls_mask; 4845130561Sobrien 4846130561Sobrien tls_mask = NULL; 4847130561Sobrien lgot_ents = elf_local_got_ents (ibfd); 4848130561Sobrien if (lgot_ents != NULL) 4849130561Sobrien { 4850130561Sobrien char *lgot_masks = (char *) (lgot_ents + symtab_hdr->sh_info); 4851130561Sobrien tls_mask = &lgot_masks[r_symndx]; 4852130561Sobrien } 4853130561Sobrien *tls_maskp = tls_mask; 4854130561Sobrien } 4855130561Sobrien } 4856130561Sobrien return TRUE; 4857130561Sobrien} 4858130561Sobrien 4859130561Sobrien/* Returns TLS_MASKP for the given REL symbol. Function return is 0 on 4860130561Sobrien error, 2 on a toc GD type suitable for optimization, 3 on a toc LD 4861130561Sobrien type suitable for optimization, and 1 otherwise. */ 4862130561Sobrien 4863130561Sobrienstatic int 4864130561Sobrienget_tls_mask (char **tls_maskp, unsigned long *toc_symndx, 4865130561Sobrien Elf_Internal_Sym **locsymsp, 4866130561Sobrien const Elf_Internal_Rela *rel, bfd *ibfd) 4867130561Sobrien{ 4868130561Sobrien unsigned long r_symndx; 4869130561Sobrien int next_r; 4870130561Sobrien struct elf_link_hash_entry *h; 4871130561Sobrien Elf_Internal_Sym *sym; 4872130561Sobrien asection *sec; 4873130561Sobrien bfd_vma off; 4874130561Sobrien 4875130561Sobrien r_symndx = ELF64_R_SYM (rel->r_info); 4876130561Sobrien if (!get_sym_h (&h, &sym, &sec, tls_maskp, locsymsp, r_symndx, ibfd)) 4877130561Sobrien return 0; 4878130561Sobrien 4879130561Sobrien if ((*tls_maskp != NULL && **tls_maskp != 0) 4880130561Sobrien || sec == NULL 4881130561Sobrien || ppc64_elf_section_data (sec)->t_symndx == NULL) 4882130561Sobrien return 1; 4883130561Sobrien 4884130561Sobrien /* Look inside a TOC section too. */ 4885130561Sobrien if (h != NULL) 4886130561Sobrien { 4887130561Sobrien BFD_ASSERT (h->root.type == bfd_link_hash_defined); 4888130561Sobrien off = h->root.u.def.value; 4889130561Sobrien } 4890130561Sobrien else 4891130561Sobrien off = sym->st_value; 4892130561Sobrien off += rel->r_addend; 4893130561Sobrien BFD_ASSERT (off % 8 == 0); 4894130561Sobrien r_symndx = ppc64_elf_section_data (sec)->t_symndx[off / 8]; 4895130561Sobrien next_r = ppc64_elf_section_data (sec)->t_symndx[off / 8 + 1]; 4896130561Sobrien if (!get_sym_h (&h, &sym, &sec, tls_maskp, locsymsp, r_symndx, ibfd)) 4897130561Sobrien return 0; 4898130561Sobrien if (toc_symndx != NULL) 4899130561Sobrien *toc_symndx = r_symndx; 4900130561Sobrien if ((h == NULL 4901130561Sobrien || ((h->root.type == bfd_link_hash_defined 4902130561Sobrien || h->root.type == bfd_link_hash_defweak) 4903130561Sobrien && !(h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC))) 4904130561Sobrien && (next_r == -1 || next_r == -2)) 4905130561Sobrien return 1 - next_r; 4906130561Sobrien return 1; 4907130561Sobrien} 4908130561Sobrien 4909130561Sobrien/* Adjust all global syms defined in opd sections. In gcc generated 4910130561Sobrien code these will already have been done, but I suppose we have to 4911130561Sobrien cater for all sorts of hand written assembly. */ 4912130561Sobrien 4913130561Sobrienstatic bfd_boolean 4914130561Sobrienadjust_opd_syms (struct elf_link_hash_entry *h, void *inf ATTRIBUTE_UNUSED) 4915130561Sobrien{ 4916130561Sobrien struct ppc_link_hash_entry *eh; 4917130561Sobrien asection *sym_sec; 4918130561Sobrien long *opd_adjust; 4919130561Sobrien 4920130561Sobrien if (h->root.type == bfd_link_hash_indirect) 4921130561Sobrien return TRUE; 4922130561Sobrien 4923130561Sobrien if (h->root.type == bfd_link_hash_warning) 4924130561Sobrien h = (struct elf_link_hash_entry *) h->root.u.i.link; 4925130561Sobrien 4926130561Sobrien if (h->root.type != bfd_link_hash_defined 4927130561Sobrien && h->root.type != bfd_link_hash_defweak) 4928130561Sobrien return TRUE; 4929130561Sobrien 4930130561Sobrien eh = (struct ppc_link_hash_entry *) h; 4931130561Sobrien if (eh->adjust_done) 4932130561Sobrien return TRUE; 4933130561Sobrien 4934130561Sobrien sym_sec = eh->elf.root.u.def.section; 4935130561Sobrien if (sym_sec != NULL 4936130561Sobrien && elf_section_data (sym_sec) != NULL 4937130561Sobrien && (opd_adjust = ppc64_elf_section_data (sym_sec)->opd.adjust) != NULL) 4938130561Sobrien { 4939130561Sobrien eh->elf.root.u.def.value += opd_adjust[eh->elf.root.u.def.value / 24]; 4940130561Sobrien eh->adjust_done = 1; 4941130561Sobrien } 4942130561Sobrien return TRUE; 4943130561Sobrien} 4944130561Sobrien 4945130561Sobrien/* Remove unused Official Procedure Descriptor entries. Currently we 4946130561Sobrien only remove those associated with functions in discarded link-once 4947130561Sobrien sections, or weakly defined functions that have been overridden. It 4948130561Sobrien would be possible to remove many more entries for statically linked 4949130561Sobrien applications. */ 4950130561Sobrien 4951130561Sobrienbfd_boolean 4952130561Sobrienppc64_elf_edit_opd (bfd *obfd, struct bfd_link_info *info) 4953130561Sobrien{ 4954104834Sobrien bfd *ibfd; 4955130561Sobrien bfd_boolean some_edited = FALSE; 4956104834Sobrien 4957130561Sobrien for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) 4958104834Sobrien { 4959104834Sobrien asection *sec; 4960104834Sobrien Elf_Internal_Rela *relstart, *rel, *relend; 4961104834Sobrien Elf_Internal_Shdr *symtab_hdr; 4962104834Sobrien Elf_Internal_Sym *local_syms; 4963104834Sobrien struct elf_link_hash_entry **sym_hashes; 4964104834Sobrien bfd_vma offset; 4965130561Sobrien bfd_size_type amt; 4966104834Sobrien long *adjust; 4967130561Sobrien bfd_boolean need_edit; 4968104834Sobrien 4969104834Sobrien sec = bfd_get_section_by_name (ibfd, ".opd"); 4970104834Sobrien if (sec == NULL) 4971104834Sobrien continue; 4972104834Sobrien 4973130561Sobrien amt = sec->_raw_size * sizeof (long) / 24; 4974130561Sobrien adjust = ppc64_elf_section_data (sec)->opd.adjust; 4975130561Sobrien if (adjust == NULL) 4976130561Sobrien { 4977130561Sobrien /* Must be a ld -r link. ie. check_relocs hasn't been 4978130561Sobrien called. */ 4979130561Sobrien adjust = bfd_zalloc (obfd, amt); 4980130561Sobrien ppc64_elf_section_data (sec)->opd.adjust = adjust; 4981130561Sobrien } 4982130561Sobrien memset (adjust, 0, amt); 4983104834Sobrien 4984104834Sobrien if (sec->output_section == bfd_abs_section_ptr) 4985104834Sobrien continue; 4986104834Sobrien 4987104834Sobrien /* Look through the section relocs. */ 4988104834Sobrien if ((sec->flags & SEC_RELOC) == 0 || sec->reloc_count == 0) 4989104834Sobrien continue; 4990104834Sobrien 4991104834Sobrien local_syms = NULL; 4992104834Sobrien symtab_hdr = &elf_tdata (ibfd)->symtab_hdr; 4993104834Sobrien sym_hashes = elf_sym_hashes (ibfd); 4994104834Sobrien 4995104834Sobrien /* Read the relocations. */ 4996130561Sobrien relstart = _bfd_elf_link_read_relocs (ibfd, sec, NULL, NULL, 4997130561Sobrien info->keep_memory); 4998104834Sobrien if (relstart == NULL) 4999130561Sobrien return FALSE; 5000104834Sobrien 5001104834Sobrien /* First run through the relocs to check they are sane, and to 5002104834Sobrien determine whether we need to edit this opd section. */ 5003130561Sobrien need_edit = FALSE; 5004104834Sobrien offset = 0; 5005104834Sobrien relend = relstart + sec->reloc_count; 5006130561Sobrien for (rel = relstart; rel < relend; ) 5007104834Sobrien { 5008130561Sobrien enum elf_ppc64_reloc_type r_type; 5009104834Sobrien unsigned long r_symndx; 5010104834Sobrien asection *sym_sec; 5011104834Sobrien struct elf_link_hash_entry *h; 5012104834Sobrien Elf_Internal_Sym *sym; 5013104834Sobrien 5014104834Sobrien /* .opd contains a regular array of 24 byte entries. We're 5015104834Sobrien only interested in the reloc pointing to a function entry 5016104834Sobrien point. */ 5017130561Sobrien if (rel->r_offset != offset 5018130561Sobrien || rel + 1 >= relend 5019130561Sobrien || (rel + 1)->r_offset != offset + 8) 5020104834Sobrien { 5021104834Sobrien /* If someone messes with .opd alignment then after a 5022104834Sobrien "ld -r" we might have padding in the middle of .opd. 5023104834Sobrien Also, there's nothing to prevent someone putting 5024104834Sobrien something silly in .opd with the assembler. No .opd 5025130561Sobrien optimization for them! */ 5026104834Sobrien (*_bfd_error_handler) 5027104834Sobrien (_("%s: .opd is not a regular array of opd entries"), 5028104834Sobrien bfd_archive_filename (ibfd)); 5029130561Sobrien need_edit = FALSE; 5030104834Sobrien break; 5031104834Sobrien } 5032104834Sobrien 5033130561Sobrien if ((r_type = ELF64_R_TYPE (rel->r_info)) != R_PPC64_ADDR64 5034130561Sobrien || (r_type = ELF64_R_TYPE ((rel + 1)->r_info)) != R_PPC64_TOC) 5035104834Sobrien { 5036130561Sobrien (*_bfd_error_handler) 5037130561Sobrien (_("%s: unexpected reloc type %u in .opd section"), 5038130561Sobrien bfd_archive_filename (ibfd), r_type); 5039130561Sobrien need_edit = FALSE; 5040130561Sobrien break; 5041104834Sobrien } 5042104834Sobrien 5043130561Sobrien r_symndx = ELF64_R_SYM (rel->r_info); 5044130561Sobrien if (!get_sym_h (&h, &sym, &sym_sec, NULL, &local_syms, 5045130561Sobrien r_symndx, ibfd)) 5046130561Sobrien goto error_ret; 5047130561Sobrien 5048104834Sobrien if (sym_sec == NULL || sym_sec->owner == NULL) 5049104834Sobrien { 5050130561Sobrien const char *sym_name; 5051130561Sobrien if (h != NULL) 5052130561Sobrien sym_name = h->root.root.string; 5053130561Sobrien else 5054130561Sobrien sym_name = bfd_elf_local_sym_name (ibfd, sym); 5055130561Sobrien 5056104834Sobrien (*_bfd_error_handler) 5057104834Sobrien (_("%s: undefined sym `%s' in .opd section"), 5058104834Sobrien bfd_archive_filename (ibfd), 5059130561Sobrien sym_name); 5060130561Sobrien need_edit = FALSE; 5061104834Sobrien break; 5062104834Sobrien } 5063104834Sobrien 5064104834Sobrien /* opd entries are always for functions defined in the 5065104834Sobrien current input bfd. If the symbol isn't defined in the 5066104834Sobrien input bfd, then we won't be using the function in this 5067104834Sobrien bfd; It must be defined in a linkonce section in another 5068104834Sobrien bfd, or is weak. It's also possible that we are 5069104834Sobrien discarding the function due to a linker script /DISCARD/, 5070104834Sobrien which we test for via the output_section. */ 5071104834Sobrien if (sym_sec->owner != ibfd 5072104834Sobrien || sym_sec->output_section == bfd_abs_section_ptr) 5073130561Sobrien need_edit = TRUE; 5074104834Sobrien 5075104834Sobrien offset += 24; 5076130561Sobrien rel += 2; 5077130561Sobrien /* Allow for the possibility of a reloc on the third word. */ 5078130561Sobrien if (rel < relend 5079130561Sobrien && rel->r_offset == offset - 8) 5080130561Sobrien rel += 1; 5081104834Sobrien } 5082104834Sobrien 5083104834Sobrien if (need_edit) 5084104834Sobrien { 5085104834Sobrien Elf_Internal_Rela *write_rel; 5086104834Sobrien bfd_byte *rptr, *wptr; 5087130561Sobrien bfd_boolean skip; 5088104834Sobrien 5089104834Sobrien /* This seems a waste of time as input .opd sections are all 5090104834Sobrien zeros as generated by gcc, but I suppose there's no reason 5091104834Sobrien this will always be so. We might start putting something in 5092104834Sobrien the third word of .opd entries. */ 5093104834Sobrien if ((sec->flags & SEC_IN_MEMORY) == 0) 5094104834Sobrien { 5095104834Sobrien bfd_byte *loc = bfd_alloc (ibfd, sec->_raw_size); 5096104834Sobrien if (loc == NULL 5097130561Sobrien || !bfd_get_section_contents (ibfd, sec, loc, 0, 5098104834Sobrien sec->_raw_size)) 5099104834Sobrien { 5100130561Sobrien error_ret: 5101104834Sobrien if (local_syms != NULL 5102104834Sobrien && symtab_hdr->contents != (unsigned char *) local_syms) 5103104834Sobrien free (local_syms); 5104104834Sobrien if (elf_section_data (sec)->relocs != relstart) 5105104834Sobrien free (relstart); 5106130561Sobrien return FALSE; 5107104834Sobrien } 5108104834Sobrien sec->contents = loc; 5109104834Sobrien sec->flags |= (SEC_IN_MEMORY | SEC_HAS_CONTENTS); 5110104834Sobrien } 5111104834Sobrien 5112104834Sobrien elf_section_data (sec)->relocs = relstart; 5113104834Sobrien 5114104834Sobrien wptr = sec->contents; 5115104834Sobrien rptr = sec->contents; 5116104834Sobrien write_rel = relstart; 5117130561Sobrien skip = FALSE; 5118104834Sobrien offset = 0; 5119104834Sobrien for (rel = relstart; rel < relend; rel++) 5120104834Sobrien { 5121130561Sobrien unsigned long r_symndx; 5122130561Sobrien asection *sym_sec; 5123130561Sobrien struct elf_link_hash_entry *h; 5124130561Sobrien Elf_Internal_Sym *sym; 5125130561Sobrien 5126130561Sobrien r_symndx = ELF64_R_SYM (rel->r_info); 5127130561Sobrien if (!get_sym_h (&h, &sym, &sym_sec, NULL, &local_syms, 5128130561Sobrien r_symndx, ibfd)) 5129130561Sobrien goto error_ret; 5130130561Sobrien 5131104834Sobrien if (rel->r_offset == offset) 5132104834Sobrien { 5133130561Sobrien struct ppc_link_hash_entry *fdh = NULL; 5134130561Sobrien if (h != NULL) 5135130561Sobrien fdh = get_fdh ((struct ppc_link_hash_entry *) h, 5136130561Sobrien ppc_hash_table (info)); 5137104834Sobrien 5138104834Sobrien skip = (sym_sec->owner != ibfd 5139104834Sobrien || sym_sec->output_section == bfd_abs_section_ptr); 5140104834Sobrien if (skip) 5141104834Sobrien { 5142104834Sobrien if (h != NULL && sym_sec->owner == ibfd) 5143104834Sobrien { 5144104834Sobrien /* Arrange for the function descriptor sym 5145104834Sobrien to be dropped. */ 5146130561Sobrien fdh->elf.root.u.def.value = 0; 5147130561Sobrien fdh->elf.root.u.def.section = sym_sec; 5148104834Sobrien } 5149104834Sobrien } 5150104834Sobrien else 5151104834Sobrien { 5152104834Sobrien /* We'll be keeping this opd entry. */ 5153104834Sobrien 5154104834Sobrien if (h != NULL) 5155104834Sobrien { 5156130561Sobrien /* Redefine the function descriptor symbol to 5157130561Sobrien this location in the opd section. It is 5158130561Sobrien necessary to update the value here rather 5159130561Sobrien than using an array of adjustments as we do 5160130561Sobrien for local symbols, because various places 5161130561Sobrien in the generic ELF code use the value 5162130561Sobrien stored in u.def.value. */ 5163130561Sobrien fdh->elf.root.u.def.value = wptr - sec->contents; 5164130561Sobrien fdh->adjust_done = 1; 5165104834Sobrien } 5166104834Sobrien 5167130561Sobrien /* Local syms are a bit tricky. We could 5168130561Sobrien tweak them as they can be cached, but 5169130561Sobrien we'd need to look through the local syms 5170130561Sobrien for the function descriptor sym which we 5171130561Sobrien don't have at the moment. So keep an 5172130561Sobrien array of adjustments. */ 5173130561Sobrien adjust[rel->r_offset / 24] = wptr - rptr; 5174130561Sobrien 5175104834Sobrien if (wptr != rptr) 5176104834Sobrien memcpy (wptr, rptr, 24); 5177104834Sobrien wptr += 24; 5178104834Sobrien } 5179104834Sobrien rptr += 24; 5180104834Sobrien offset += 24; 5181104834Sobrien } 5182104834Sobrien 5183130561Sobrien if (skip) 5184104834Sobrien { 5185130561Sobrien BFD_ASSERT (MUST_BE_DYN_RELOC (ELF64_R_TYPE (rel->r_info))); 5186130561Sobrien if (info->shared) 5187130561Sobrien { 5188130561Sobrien /* We won't be needing dynamic relocs here. */ 5189130561Sobrien struct ppc_dyn_relocs **pp; 5190130561Sobrien struct ppc_dyn_relocs *p; 5191130561Sobrien 5192130561Sobrien if (h != NULL) 5193130561Sobrien pp = &((struct ppc_link_hash_entry *) h)->dyn_relocs; 5194130561Sobrien else if (sym_sec != NULL) 5195130561Sobrien pp = ((struct ppc_dyn_relocs **) 5196130561Sobrien &elf_section_data (sym_sec)->local_dynrel); 5197130561Sobrien else 5198130561Sobrien pp = ((struct ppc_dyn_relocs **) 5199130561Sobrien &elf_section_data (sec)->local_dynrel); 5200130561Sobrien while ((p = *pp) != NULL) 5201130561Sobrien { 5202130561Sobrien if (p->sec == sec) 5203130561Sobrien { 5204130561Sobrien p->count -= 1; 5205130561Sobrien if (p->count == 0) 5206130561Sobrien *pp = p->next; 5207130561Sobrien break; 5208130561Sobrien } 5209130561Sobrien pp = &p->next; 5210130561Sobrien } 5211130561Sobrien } 5212130561Sobrien } 5213130561Sobrien else 5214130561Sobrien { 5215130561Sobrien /* We need to adjust any reloc offsets to point to the 5216130561Sobrien new opd entries. While we're at it, we may as well 5217130561Sobrien remove redundant relocs. */ 5218104834Sobrien rel->r_offset += wptr - rptr; 5219104834Sobrien if (write_rel != rel) 5220104834Sobrien memcpy (write_rel, rel, sizeof (*rel)); 5221104834Sobrien ++write_rel; 5222104834Sobrien } 5223104834Sobrien } 5224104834Sobrien 5225104834Sobrien sec->_cooked_size = wptr - sec->contents; 5226104834Sobrien sec->reloc_count = write_rel - relstart; 5227130561Sobrien /* Fudge the size too, as this is used later in 5228130561Sobrien elf_bfd_final_link if we are emitting relocs. */ 5229130561Sobrien elf_section_data (sec)->rel_hdr.sh_size 5230130561Sobrien = sec->reloc_count * elf_section_data (sec)->rel_hdr.sh_entsize; 5231130561Sobrien BFD_ASSERT (elf_section_data (sec)->rel_hdr2 == NULL); 5232130561Sobrien some_edited = TRUE; 5233104834Sobrien } 5234104834Sobrien else if (elf_section_data (sec)->relocs != relstart) 5235104834Sobrien free (relstart); 5236104834Sobrien 5237104834Sobrien if (local_syms != NULL 5238104834Sobrien && symtab_hdr->contents != (unsigned char *) local_syms) 5239104834Sobrien { 5240104834Sobrien if (!info->keep_memory) 5241104834Sobrien free (local_syms); 5242104834Sobrien else 5243104834Sobrien symtab_hdr->contents = (unsigned char *) local_syms; 5244104834Sobrien } 5245104834Sobrien } 5246104834Sobrien 5247130561Sobrien if (some_edited) 5248130561Sobrien elf_link_hash_traverse (elf_hash_table (info), adjust_opd_syms, NULL); 5249130561Sobrien 5250130561Sobrien return TRUE; 5251104834Sobrien} 525289857Sobrien 5253130561Sobrien/* Set htab->tls_get_addr and call the generic ELF tls_setup function. */ 5254130561Sobrien 5255130561Sobrienasection * 5256130561Sobrienppc64_elf_tls_setup (bfd *obfd, struct bfd_link_info *info) 5257130561Sobrien{ 5258130561Sobrien struct ppc_link_hash_table *htab; 5259130561Sobrien 5260130561Sobrien htab = ppc_hash_table (info); 5261130561Sobrien if (htab->tls_get_addr != NULL) 5262130561Sobrien { 5263130561Sobrien struct elf_link_hash_entry *h = htab->tls_get_addr; 5264130561Sobrien 5265130561Sobrien while (h->root.type == bfd_link_hash_indirect 5266130561Sobrien || h->root.type == bfd_link_hash_warning) 5267130561Sobrien h = (struct elf_link_hash_entry *) h->root.u.i.link; 5268130561Sobrien 5269130561Sobrien htab->tls_get_addr = h; 5270130561Sobrien } 5271130561Sobrien 5272130561Sobrien return _bfd_elf_tls_setup (obfd, info); 5273130561Sobrien} 5274130561Sobrien 5275130561Sobrien/* Run through all the TLS relocs looking for optimization 5276130561Sobrien opportunities. The linker has been hacked (see ppc64elf.em) to do 5277130561Sobrien a preliminary section layout so that we know the TLS segment 5278130561Sobrien offsets. We can't optimize earlier because some optimizations need 5279130561Sobrien to know the tp offset, and we need to optimize before allocating 5280130561Sobrien dynamic relocations. */ 5281130561Sobrien 5282130561Sobrienbfd_boolean 5283130561Sobrienppc64_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, struct bfd_link_info *info) 5284130561Sobrien{ 5285130561Sobrien bfd *ibfd; 5286130561Sobrien asection *sec; 5287130561Sobrien struct ppc_link_hash_table *htab; 5288130561Sobrien 5289130561Sobrien if (info->relocatable || info->shared) 5290130561Sobrien return TRUE; 5291130561Sobrien 5292130561Sobrien htab = ppc_hash_table (info); 5293130561Sobrien for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) 5294130561Sobrien { 5295130561Sobrien Elf_Internal_Sym *locsyms = NULL; 5296130561Sobrien 5297130561Sobrien for (sec = ibfd->sections; sec != NULL; sec = sec->next) 5298130561Sobrien if (sec->has_tls_reloc && !bfd_is_abs_section (sec->output_section)) 5299130561Sobrien { 5300130561Sobrien Elf_Internal_Rela *relstart, *rel, *relend; 5301130561Sobrien int expecting_tls_get_addr; 5302130561Sobrien 5303130561Sobrien /* Read the relocations. */ 5304130561Sobrien relstart = _bfd_elf_link_read_relocs (ibfd, sec, NULL, NULL, 5305130561Sobrien info->keep_memory); 5306130561Sobrien if (relstart == NULL) 5307130561Sobrien return FALSE; 5308130561Sobrien 5309130561Sobrien expecting_tls_get_addr = 0; 5310130561Sobrien relend = relstart + sec->reloc_count; 5311130561Sobrien for (rel = relstart; rel < relend; rel++) 5312130561Sobrien { 5313130561Sobrien enum elf_ppc64_reloc_type r_type; 5314130561Sobrien unsigned long r_symndx; 5315130561Sobrien struct elf_link_hash_entry *h; 5316130561Sobrien Elf_Internal_Sym *sym; 5317130561Sobrien asection *sym_sec; 5318130561Sobrien char *tls_mask; 5319130561Sobrien char tls_set, tls_clear, tls_type = 0; 5320130561Sobrien bfd_vma value; 5321130561Sobrien bfd_boolean ok_tprel, is_local; 5322130561Sobrien 5323130561Sobrien r_symndx = ELF64_R_SYM (rel->r_info); 5324130561Sobrien if (!get_sym_h (&h, &sym, &sym_sec, &tls_mask, &locsyms, 5325130561Sobrien r_symndx, ibfd)) 5326130561Sobrien { 5327130561Sobrien err_free_rel: 5328130561Sobrien if (elf_section_data (sec)->relocs != relstart) 5329130561Sobrien free (relstart); 5330130561Sobrien if (locsyms != NULL 5331130561Sobrien && (elf_tdata (ibfd)->symtab_hdr.contents 5332130561Sobrien != (unsigned char *) locsyms)) 5333130561Sobrien free (locsyms); 5334130561Sobrien return FALSE; 5335130561Sobrien } 5336130561Sobrien 5337130561Sobrien if (h != NULL) 5338130561Sobrien { 5339130561Sobrien if (h->root.type != bfd_link_hash_defined 5340130561Sobrien && h->root.type != bfd_link_hash_defweak) 5341130561Sobrien continue; 5342130561Sobrien value = h->root.u.def.value; 5343130561Sobrien } 5344130561Sobrien else 5345130561Sobrien { 5346130561Sobrien value = sym->st_value; 5347130561Sobrien 5348130561Sobrien if (elf_section_data (sym_sec) != NULL) 5349130561Sobrien { 5350130561Sobrien long *adjust; 5351130561Sobrien adjust = ppc64_elf_section_data (sym_sec)->opd.adjust; 5352130561Sobrien if (adjust != NULL) 5353130561Sobrien value += adjust[value / 24]; 5354130561Sobrien } 5355130561Sobrien } 5356130561Sobrien 5357130561Sobrien ok_tprel = FALSE; 5358130561Sobrien is_local = FALSE; 5359130561Sobrien if (h == NULL 5360130561Sobrien || !(h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC)) 5361130561Sobrien { 5362130561Sobrien is_local = TRUE; 5363130561Sobrien value += sym_sec->output_offset; 5364130561Sobrien value += sym_sec->output_section->vma; 5365130561Sobrien value -= htab->elf.tls_sec->vma; 5366130561Sobrien ok_tprel = (value + TP_OFFSET + ((bfd_vma) 1 << 31) 5367130561Sobrien < (bfd_vma) 1 << 32); 5368130561Sobrien } 5369130561Sobrien 5370130561Sobrien r_type = ELF64_R_TYPE (rel->r_info); 5371130561Sobrien switch (r_type) 5372130561Sobrien { 5373130561Sobrien case R_PPC64_GOT_TLSLD16: 5374130561Sobrien case R_PPC64_GOT_TLSLD16_LO: 5375130561Sobrien case R_PPC64_GOT_TLSLD16_HI: 5376130561Sobrien case R_PPC64_GOT_TLSLD16_HA: 5377130561Sobrien /* These relocs should never be against a symbol 5378130561Sobrien defined in a shared lib. Leave them alone if 5379130561Sobrien that turns out to be the case. */ 5380130561Sobrien ppc64_tlsld_got (ibfd)->refcount -= 1; 5381130561Sobrien if (!is_local) 5382130561Sobrien continue; 5383130561Sobrien 5384130561Sobrien /* LD -> LE */ 5385130561Sobrien tls_set = 0; 5386130561Sobrien tls_clear = TLS_LD; 5387130561Sobrien tls_type = TLS_TLS | TLS_LD; 5388130561Sobrien expecting_tls_get_addr = 1; 5389130561Sobrien break; 5390130561Sobrien 5391130561Sobrien case R_PPC64_GOT_TLSGD16: 5392130561Sobrien case R_PPC64_GOT_TLSGD16_LO: 5393130561Sobrien case R_PPC64_GOT_TLSGD16_HI: 5394130561Sobrien case R_PPC64_GOT_TLSGD16_HA: 5395130561Sobrien if (ok_tprel) 5396130561Sobrien /* GD -> LE */ 5397130561Sobrien tls_set = 0; 5398130561Sobrien else 5399130561Sobrien /* GD -> IE */ 5400130561Sobrien tls_set = TLS_TLS | TLS_TPRELGD; 5401130561Sobrien tls_clear = TLS_GD; 5402130561Sobrien tls_type = TLS_TLS | TLS_GD; 5403130561Sobrien expecting_tls_get_addr = 1; 5404130561Sobrien break; 5405130561Sobrien 5406130561Sobrien case R_PPC64_GOT_TPREL16_DS: 5407130561Sobrien case R_PPC64_GOT_TPREL16_LO_DS: 5408130561Sobrien case R_PPC64_GOT_TPREL16_HI: 5409130561Sobrien case R_PPC64_GOT_TPREL16_HA: 5410130561Sobrien expecting_tls_get_addr = 0; 5411130561Sobrien if (ok_tprel) 5412130561Sobrien { 5413130561Sobrien /* IE -> LE */ 5414130561Sobrien tls_set = 0; 5415130561Sobrien tls_clear = TLS_TPREL; 5416130561Sobrien tls_type = TLS_TLS | TLS_TPREL; 5417130561Sobrien break; 5418130561Sobrien } 5419130561Sobrien else 5420130561Sobrien continue; 5421130561Sobrien 5422130561Sobrien case R_PPC64_REL14: 5423130561Sobrien case R_PPC64_REL14_BRTAKEN: 5424130561Sobrien case R_PPC64_REL14_BRNTAKEN: 5425130561Sobrien case R_PPC64_REL24: 5426130561Sobrien if (h != NULL 5427130561Sobrien && h == htab->tls_get_addr) 5428130561Sobrien { 5429130561Sobrien if (!expecting_tls_get_addr 5430130561Sobrien && rel != relstart 5431130561Sobrien && ((ELF64_R_TYPE (rel[-1].r_info) 5432130561Sobrien == R_PPC64_TOC16) 5433130561Sobrien || (ELF64_R_TYPE (rel[-1].r_info) 5434130561Sobrien == R_PPC64_TOC16_LO))) 5435130561Sobrien { 5436130561Sobrien /* Check for toc tls entries. */ 5437130561Sobrien char *toc_tls; 5438130561Sobrien int retval; 5439130561Sobrien 5440130561Sobrien retval = get_tls_mask (&toc_tls, NULL, &locsyms, 5441130561Sobrien rel - 1, ibfd); 5442130561Sobrien if (retval == 0) 5443130561Sobrien goto err_free_rel; 5444130561Sobrien if (toc_tls != NULL) 5445130561Sobrien expecting_tls_get_addr = retval > 1; 5446130561Sobrien } 5447130561Sobrien 5448130561Sobrien if (expecting_tls_get_addr) 5449130561Sobrien { 5450130561Sobrien struct plt_entry *ent; 5451130561Sobrien for (ent = h->plt.plist; ent; ent = ent->next) 5452130561Sobrien if (ent->addend == 0) 5453130561Sobrien { 5454130561Sobrien if (ent->plt.refcount > 0) 5455130561Sobrien ent->plt.refcount -= 1; 5456130561Sobrien break; 5457130561Sobrien } 5458130561Sobrien } 5459130561Sobrien } 5460130561Sobrien expecting_tls_get_addr = 0; 5461130561Sobrien continue; 5462130561Sobrien 5463130561Sobrien case R_PPC64_TPREL64: 5464130561Sobrien expecting_tls_get_addr = 0; 5465130561Sobrien if (ok_tprel) 5466130561Sobrien { 5467130561Sobrien /* IE -> LE */ 5468130561Sobrien tls_set = TLS_EXPLICIT; 5469130561Sobrien tls_clear = TLS_TPREL; 5470130561Sobrien break; 5471130561Sobrien } 5472130561Sobrien else 5473130561Sobrien continue; 5474130561Sobrien 5475130561Sobrien case R_PPC64_DTPMOD64: 5476130561Sobrien expecting_tls_get_addr = 0; 5477130561Sobrien if (rel + 1 < relend 5478130561Sobrien && (rel[1].r_info 5479130561Sobrien == ELF64_R_INFO (r_symndx, R_PPC64_DTPREL64)) 5480130561Sobrien && rel[1].r_offset == rel->r_offset + 8) 5481130561Sobrien { 5482130561Sobrien if (ok_tprel) 5483130561Sobrien /* GD -> LE */ 5484130561Sobrien tls_set = TLS_EXPLICIT | TLS_GD; 5485130561Sobrien else 5486130561Sobrien /* GD -> IE */ 5487130561Sobrien tls_set = TLS_EXPLICIT | TLS_GD | TLS_TPRELGD; 5488130561Sobrien tls_clear = TLS_GD; 5489130561Sobrien } 5490130561Sobrien else 5491130561Sobrien { 5492130561Sobrien if (!is_local) 5493130561Sobrien continue; 5494130561Sobrien 5495130561Sobrien /* LD -> LE */ 5496130561Sobrien tls_set = TLS_EXPLICIT; 5497130561Sobrien tls_clear = TLS_LD; 5498130561Sobrien } 5499130561Sobrien break; 5500130561Sobrien 5501130561Sobrien default: 5502130561Sobrien expecting_tls_get_addr = 0; 5503130561Sobrien continue; 5504130561Sobrien } 5505130561Sobrien 5506130561Sobrien if ((tls_set & TLS_EXPLICIT) == 0) 5507130561Sobrien { 5508130561Sobrien struct got_entry *ent; 5509130561Sobrien 5510130561Sobrien /* Adjust got entry for this reloc. */ 5511130561Sobrien if (h != NULL) 5512130561Sobrien ent = h->got.glist; 5513130561Sobrien else 5514130561Sobrien ent = elf_local_got_ents (ibfd)[r_symndx]; 5515130561Sobrien 5516130561Sobrien for (; ent != NULL; ent = ent->next) 5517130561Sobrien if (ent->addend == rel->r_addend 5518130561Sobrien && ent->owner == ibfd 5519130561Sobrien && ent->tls_type == tls_type) 5520130561Sobrien break; 5521130561Sobrien if (ent == NULL) 5522130561Sobrien abort (); 5523130561Sobrien 5524130561Sobrien if (tls_set == 0) 5525130561Sobrien { 5526130561Sobrien /* We managed to get rid of a got entry. */ 5527130561Sobrien if (ent->got.refcount > 0) 5528130561Sobrien ent->got.refcount -= 1; 5529130561Sobrien } 5530130561Sobrien } 5531130561Sobrien else if (h != NULL) 5532130561Sobrien { 5533130561Sobrien struct ppc_link_hash_entry * eh; 5534130561Sobrien struct ppc_dyn_relocs **pp; 5535130561Sobrien struct ppc_dyn_relocs *p; 5536130561Sobrien 5537130561Sobrien /* Adjust dynamic relocs. */ 5538130561Sobrien eh = (struct ppc_link_hash_entry *) h; 5539130561Sobrien for (pp = &eh->dyn_relocs; 5540130561Sobrien (p = *pp) != NULL; 5541130561Sobrien pp = &p->next) 5542130561Sobrien if (p->sec == sec) 5543130561Sobrien { 5544130561Sobrien /* If we got rid of a DTPMOD/DTPREL reloc 5545130561Sobrien pair then we'll lose one or two dyn 5546130561Sobrien relocs. */ 5547130561Sobrien if (tls_set == (TLS_EXPLICIT | TLS_GD)) 5548130561Sobrien p->count -= 1; 5549130561Sobrien p->count -= 1; 5550130561Sobrien if (p->count == 0) 5551130561Sobrien *pp = p->next; 5552130561Sobrien break; 5553130561Sobrien } 5554130561Sobrien } 5555130561Sobrien 5556130561Sobrien *tls_mask |= tls_set; 5557130561Sobrien *tls_mask &= ~tls_clear; 5558130561Sobrien } 5559130561Sobrien 5560130561Sobrien if (elf_section_data (sec)->relocs != relstart) 5561130561Sobrien free (relstart); 5562130561Sobrien } 5563130561Sobrien 5564130561Sobrien if (locsyms != NULL 5565130561Sobrien && (elf_tdata (ibfd)->symtab_hdr.contents 5566130561Sobrien != (unsigned char *) locsyms)) 5567130561Sobrien { 5568130561Sobrien if (!info->keep_memory) 5569130561Sobrien free (locsyms); 5570130561Sobrien else 5571130561Sobrien elf_tdata (ibfd)->symtab_hdr.contents = (unsigned char *) locsyms; 5572130561Sobrien } 5573130561Sobrien } 5574130561Sobrien return TRUE; 5575130561Sobrien} 5576130561Sobrien 557789857Sobrien/* Allocate space in .plt, .got and associated reloc sections for 557889857Sobrien dynamic relocs. */ 557989857Sobrien 5580130561Sobrienstatic bfd_boolean 5581130561Sobrienallocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) 558289857Sobrien{ 558389857Sobrien struct bfd_link_info *info; 558489857Sobrien struct ppc_link_hash_table *htab; 558589857Sobrien asection *s; 558689857Sobrien struct ppc_link_hash_entry *eh; 558789857Sobrien struct ppc_dyn_relocs *p; 5588130561Sobrien struct got_entry *gent; 558989857Sobrien 559094536Sobrien if (h->root.type == bfd_link_hash_indirect) 5591130561Sobrien return TRUE; 559289857Sobrien 559394536Sobrien if (h->root.type == bfd_link_hash_warning) 559494536Sobrien h = (struct elf_link_hash_entry *) h->root.u.i.link; 559594536Sobrien 559689857Sobrien info = (struct bfd_link_info *) inf; 559789857Sobrien htab = ppc_hash_table (info); 559889857Sobrien 559989857Sobrien if (htab->elf.dynamic_sections_created 5600130561Sobrien && h->dynindx != -1 5601130561Sobrien && WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info->shared, h)) 560289857Sobrien { 5603130561Sobrien struct plt_entry *pent; 5604130561Sobrien bfd_boolean doneone = FALSE; 5605130561Sobrien for (pent = h->plt.plist; pent != NULL; pent = pent->next) 5606130561Sobrien if (pent->plt.refcount > 0) 5607130561Sobrien { 5608130561Sobrien BFD_ASSERT (((struct ppc_link_hash_entry *) h)->is_func_descriptor); 560989857Sobrien 5610130561Sobrien /* If this is the first .plt entry, make room for the special 5611130561Sobrien first entry. */ 5612130561Sobrien s = htab->plt; 5613130561Sobrien if (s->_raw_size == 0) 5614130561Sobrien s->_raw_size += PLT_INITIAL_ENTRY_SIZE; 561589857Sobrien 5616130561Sobrien pent->plt.offset = s->_raw_size; 561789857Sobrien 5618130561Sobrien /* Make room for this entry. */ 5619130561Sobrien s->_raw_size += PLT_ENTRY_SIZE; 562089857Sobrien 5621130561Sobrien /* Make room for the .glink code. */ 5622130561Sobrien s = htab->glink; 5623130561Sobrien if (s->_raw_size == 0) 5624130561Sobrien s->_raw_size += GLINK_CALL_STUB_SIZE; 5625130561Sobrien /* We need bigger stubs past index 32767. */ 5626130561Sobrien if (s->_raw_size >= GLINK_CALL_STUB_SIZE + 32768*2*4) 5627130561Sobrien s->_raw_size += 4; 5628130561Sobrien s->_raw_size += 2*4; 562989857Sobrien 5630130561Sobrien /* We also need to make an entry in the .rela.plt section. */ 5631130561Sobrien s = htab->relplt; 5632130561Sobrien s->_raw_size += sizeof (Elf64_External_Rela); 5633130561Sobrien doneone = TRUE; 5634130561Sobrien } 5635130561Sobrien else 5636130561Sobrien pent->plt.offset = (bfd_vma) -1; 5637130561Sobrien if (!doneone) 563889857Sobrien { 5639130561Sobrien h->plt.plist = NULL; 564089857Sobrien h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; 564189857Sobrien } 564289857Sobrien } 564389857Sobrien else 564489857Sobrien { 5645130561Sobrien h->plt.plist = NULL; 564689857Sobrien h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; 564789857Sobrien } 564889857Sobrien 5649130561Sobrien eh = (struct ppc_link_hash_entry *) h; 5650130561Sobrien /* Run through the TLS GD got entries first if we're changing them 5651130561Sobrien to TPREL. */ 5652130561Sobrien if ((eh->tls_mask & TLS_TPRELGD) != 0) 5653130561Sobrien for (gent = h->got.glist; gent != NULL; gent = gent->next) 5654130561Sobrien if (gent->got.refcount > 0 5655130561Sobrien && (gent->tls_type & TLS_GD) != 0) 5656130561Sobrien { 5657130561Sobrien /* This was a GD entry that has been converted to TPREL. If 5658130561Sobrien there happens to be a TPREL entry we can use that one. */ 5659130561Sobrien struct got_entry *ent; 5660130561Sobrien for (ent = h->got.glist; ent != NULL; ent = ent->next) 5661130561Sobrien if (ent->got.refcount > 0 5662130561Sobrien && (ent->tls_type & TLS_TPREL) != 0 5663130561Sobrien && ent->addend == gent->addend 5664130561Sobrien && ent->owner == gent->owner) 5665130561Sobrien { 5666130561Sobrien gent->got.refcount = 0; 5667130561Sobrien break; 5668130561Sobrien } 566989857Sobrien 5670130561Sobrien /* If not, then we'll be using our own TPREL entry. */ 5671130561Sobrien if (gent->got.refcount != 0) 5672130561Sobrien gent->tls_type = TLS_TLS | TLS_TPREL; 567389857Sobrien } 567489857Sobrien 5675130561Sobrien for (gent = h->got.glist; gent != NULL; gent = gent->next) 5676130561Sobrien if (gent->got.refcount > 0) 5677130561Sobrien { 5678130561Sobrien bfd_boolean dyn; 567989857Sobrien 5680130561Sobrien /* Make sure this symbol is output as a dynamic symbol. 5681130561Sobrien Undefined weak syms won't yet be marked as dynamic, 5682130561Sobrien nor will all TLS symbols. */ 5683130561Sobrien if (h->dynindx == -1 5684130561Sobrien && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) 5685130561Sobrien { 5686130561Sobrien if (! bfd_elf_link_record_dynamic_symbol (info, h)) 5687130561Sobrien return FALSE; 5688130561Sobrien } 5689130561Sobrien 5690130561Sobrien if ((gent->tls_type & TLS_LD) != 0 5691130561Sobrien && !(h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC)) 5692130561Sobrien { 5693130561Sobrien gent->got.offset = ppc64_tlsld_got (gent->owner)->offset; 5694130561Sobrien continue; 5695130561Sobrien } 5696130561Sobrien 5697130561Sobrien s = ppc64_elf_tdata (gent->owner)->got; 5698130561Sobrien gent->got.offset = s->_raw_size; 5699130561Sobrien s->_raw_size 5700130561Sobrien += (gent->tls_type & eh->tls_mask & (TLS_GD | TLS_LD)) ? 16 : 8; 5701130561Sobrien dyn = htab->elf.dynamic_sections_created; 5702130561Sobrien if ((info->shared 5703130561Sobrien || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h)) 5704130561Sobrien && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT 5705130561Sobrien || h->root.type != bfd_link_hash_undefweak)) 5706130561Sobrien ppc64_elf_tdata (gent->owner)->relgot->_raw_size 5707130561Sobrien += (gent->tls_type & eh->tls_mask & TLS_GD 5708130561Sobrien ? 2 * sizeof (Elf64_External_Rela) 5709130561Sobrien : sizeof (Elf64_External_Rela)); 5710130561Sobrien } 5711130561Sobrien else 5712130561Sobrien gent->got.offset = (bfd_vma) -1; 5713130561Sobrien 571489857Sobrien if (eh->dyn_relocs == NULL) 5715130561Sobrien return TRUE; 571689857Sobrien 571789857Sobrien /* In the shared -Bsymbolic case, discard space allocated for 571889857Sobrien dynamic pc-relative relocs against symbols which turn out to be 571989857Sobrien defined in regular objects. For the normal shared case, discard 572089857Sobrien space for relocs that have become local due to symbol visibility 572189857Sobrien changes. */ 572289857Sobrien 572389857Sobrien if (info->shared) 572489857Sobrien { 5725130561Sobrien /* Relocs that use pc_count are those that appear on a call insn, 5726130561Sobrien or certain REL relocs (see MUST_BE_DYN_RELOC) that can be 5727130561Sobrien generated via assembly. We want calls to protected symbols to 5728130561Sobrien resolve directly to the function rather than going via the plt. 5729130561Sobrien If people want function pointer comparisons to work as expected 5730130561Sobrien then they should avoid writing weird assembly. */ 5731130561Sobrien if (SYMBOL_CALLS_LOCAL (info, h)) 573289857Sobrien { 573389857Sobrien struct ppc_dyn_relocs **pp; 573489857Sobrien 573589857Sobrien for (pp = &eh->dyn_relocs; (p = *pp) != NULL; ) 573689857Sobrien { 573789857Sobrien p->count -= p->pc_count; 573889857Sobrien p->pc_count = 0; 573989857Sobrien if (p->count == 0) 574089857Sobrien *pp = p->next; 574189857Sobrien else 574289857Sobrien pp = &p->next; 574389857Sobrien } 574489857Sobrien } 5745130561Sobrien 5746130561Sobrien /* Also discard relocs on undefined weak syms with non-default 5747130561Sobrien visibility. */ 5748130561Sobrien if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT 5749130561Sobrien && h->root.type == bfd_link_hash_undefweak) 5750130561Sobrien eh->dyn_relocs = NULL; 575189857Sobrien } 5752130561Sobrien else if (ELIMINATE_COPY_RELOCS) 575389857Sobrien { 575489857Sobrien /* For the non-shared case, discard space for relocs against 575589857Sobrien symbols which turn out to need copy relocs or are not 575689857Sobrien dynamic. */ 575789857Sobrien 575889857Sobrien if ((h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0 5759130561Sobrien && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0 5760130561Sobrien && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) 576189857Sobrien { 576289857Sobrien /* Make sure this symbol is output as a dynamic symbol. 576389857Sobrien Undefined weak syms won't yet be marked as dynamic. */ 576489857Sobrien if (h->dynindx == -1 576589857Sobrien && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) 576689857Sobrien { 5767130561Sobrien if (! bfd_elf_link_record_dynamic_symbol (info, h)) 5768130561Sobrien return FALSE; 576989857Sobrien } 577089857Sobrien 577189857Sobrien /* If that succeeded, we know we'll be keeping all the 577289857Sobrien relocs. */ 577389857Sobrien if (h->dynindx != -1) 577489857Sobrien goto keep; 577589857Sobrien } 577689857Sobrien 577789857Sobrien eh->dyn_relocs = NULL; 577889857Sobrien 577989857Sobrien keep: ; 578089857Sobrien } 578189857Sobrien 578289857Sobrien /* Finally, allocate space. */ 578389857Sobrien for (p = eh->dyn_relocs; p != NULL; p = p->next) 578489857Sobrien { 578589857Sobrien asection *sreloc = elf_section_data (p->sec)->sreloc; 578689857Sobrien sreloc->_raw_size += p->count * sizeof (Elf64_External_Rela); 578789857Sobrien } 578889857Sobrien 5789130561Sobrien return TRUE; 579089857Sobrien} 579189857Sobrien 579289857Sobrien/* Find any dynamic relocs that apply to read-only sections. */ 579389857Sobrien 5794130561Sobrienstatic bfd_boolean 5795130561Sobrienreadonly_dynrelocs (struct elf_link_hash_entry *h, void *inf) 579689857Sobrien{ 579789857Sobrien struct ppc_link_hash_entry *eh; 579889857Sobrien struct ppc_dyn_relocs *p; 579989857Sobrien 580094536Sobrien if (h->root.type == bfd_link_hash_warning) 580194536Sobrien h = (struct elf_link_hash_entry *) h->root.u.i.link; 580294536Sobrien 580389857Sobrien eh = (struct ppc_link_hash_entry *) h; 580489857Sobrien for (p = eh->dyn_relocs; p != NULL; p = p->next) 580589857Sobrien { 580689857Sobrien asection *s = p->sec->output_section; 580789857Sobrien 580889857Sobrien if (s != NULL && (s->flags & SEC_READONLY) != 0) 580989857Sobrien { 5810130561Sobrien struct bfd_link_info *info = inf; 581189857Sobrien 581289857Sobrien info->flags |= DF_TEXTREL; 581389857Sobrien 581489857Sobrien /* Not an error, just cut short the traversal. */ 5815130561Sobrien return FALSE; 581689857Sobrien } 581789857Sobrien } 5818130561Sobrien return TRUE; 581989857Sobrien} 582089857Sobrien 582189857Sobrien/* Set the sizes of the dynamic sections. */ 582289857Sobrien 5823130561Sobrienstatic bfd_boolean 5824130561Sobrienppc64_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, 5825130561Sobrien struct bfd_link_info *info) 582689857Sobrien{ 582789857Sobrien struct ppc_link_hash_table *htab; 582889857Sobrien bfd *dynobj; 582989857Sobrien asection *s; 5830130561Sobrien bfd_boolean relocs; 583189857Sobrien bfd *ibfd; 583289857Sobrien 583389857Sobrien htab = ppc_hash_table (info); 583489857Sobrien dynobj = htab->elf.dynobj; 583589857Sobrien if (dynobj == NULL) 583689857Sobrien abort (); 583789857Sobrien 583889857Sobrien if (htab->elf.dynamic_sections_created) 583989857Sobrien { 584089857Sobrien /* Set the contents of the .interp section to the interpreter. */ 5841130561Sobrien if (info->executable) 584289857Sobrien { 584389857Sobrien s = bfd_get_section_by_name (dynobj, ".interp"); 584489857Sobrien if (s == NULL) 584589857Sobrien abort (); 584689857Sobrien s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER; 584789857Sobrien s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER; 584889857Sobrien } 584989857Sobrien } 585089857Sobrien 585189857Sobrien /* Set up .got offsets for local syms, and space for local dynamic 585289857Sobrien relocs. */ 585389857Sobrien for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) 585489857Sobrien { 5855130561Sobrien struct got_entry **lgot_ents; 5856130561Sobrien struct got_entry **end_lgot_ents; 5857130561Sobrien char *lgot_masks; 585889857Sobrien bfd_size_type locsymcount; 585989857Sobrien Elf_Internal_Shdr *symtab_hdr; 586089857Sobrien asection *srel; 586189857Sobrien 586289857Sobrien if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour) 586389857Sobrien continue; 586489857Sobrien 5865130561Sobrien if (ppc64_tlsld_got (ibfd)->refcount > 0) 5866130561Sobrien { 5867130561Sobrien s = ppc64_elf_tdata (ibfd)->got; 5868130561Sobrien ppc64_tlsld_got (ibfd)->offset = s->_raw_size; 5869130561Sobrien s->_raw_size += 16; 5870130561Sobrien if (info->shared) 5871130561Sobrien { 5872130561Sobrien srel = ppc64_elf_tdata (ibfd)->relgot; 5873130561Sobrien srel->_raw_size += sizeof (Elf64_External_Rela); 5874130561Sobrien } 5875130561Sobrien } 5876130561Sobrien else 5877130561Sobrien ppc64_tlsld_got (ibfd)->offset = (bfd_vma) -1; 5878130561Sobrien 587989857Sobrien for (s = ibfd->sections; s != NULL; s = s->next) 588089857Sobrien { 588189857Sobrien struct ppc_dyn_relocs *p; 588289857Sobrien 588389857Sobrien for (p = *((struct ppc_dyn_relocs **) 588489857Sobrien &elf_section_data (s)->local_dynrel); 588589857Sobrien p != NULL; 588689857Sobrien p = p->next) 588789857Sobrien { 588889857Sobrien if (!bfd_is_abs_section (p->sec) 588989857Sobrien && bfd_is_abs_section (p->sec->output_section)) 589089857Sobrien { 589189857Sobrien /* Input section has been discarded, either because 589289857Sobrien it is a copy of a linkonce section or due to 589389857Sobrien linker script /DISCARD/, so we'll be discarding 589489857Sobrien the relocs too. */ 589589857Sobrien } 589691041Sobrien else if (p->count != 0) 589789857Sobrien { 589889857Sobrien srel = elf_section_data (p->sec)->sreloc; 589989857Sobrien srel->_raw_size += p->count * sizeof (Elf64_External_Rela); 590091041Sobrien if ((p->sec->output_section->flags & SEC_READONLY) != 0) 590191041Sobrien info->flags |= DF_TEXTREL; 590289857Sobrien } 590389857Sobrien } 590489857Sobrien } 590589857Sobrien 5906130561Sobrien lgot_ents = elf_local_got_ents (ibfd); 5907130561Sobrien if (!lgot_ents) 590889857Sobrien continue; 590989857Sobrien 591089857Sobrien symtab_hdr = &elf_tdata (ibfd)->symtab_hdr; 591189857Sobrien locsymcount = symtab_hdr->sh_info; 5912130561Sobrien end_lgot_ents = lgot_ents + locsymcount; 5913130561Sobrien lgot_masks = (char *) end_lgot_ents; 5914130561Sobrien s = ppc64_elf_tdata (ibfd)->got; 5915130561Sobrien srel = ppc64_elf_tdata (ibfd)->relgot; 5916130561Sobrien for (; lgot_ents < end_lgot_ents; ++lgot_ents, ++lgot_masks) 591789857Sobrien { 5918130561Sobrien struct got_entry *ent; 5919130561Sobrien 5920130561Sobrien for (ent = *lgot_ents; ent != NULL; ent = ent->next) 5921130561Sobrien if (ent->got.refcount > 0) 5922130561Sobrien { 5923130561Sobrien if ((ent->tls_type & *lgot_masks & TLS_LD) != 0) 5924130561Sobrien { 5925130561Sobrien if (ppc64_tlsld_got (ibfd)->offset == (bfd_vma) -1) 5926130561Sobrien { 5927130561Sobrien ppc64_tlsld_got (ibfd)->offset = s->_raw_size; 5928130561Sobrien s->_raw_size += 16; 5929130561Sobrien if (info->shared) 5930130561Sobrien srel->_raw_size += sizeof (Elf64_External_Rela); 5931130561Sobrien } 5932130561Sobrien ent->got.offset = ppc64_tlsld_got (ibfd)->offset; 5933130561Sobrien } 5934130561Sobrien else 5935130561Sobrien { 5936130561Sobrien ent->got.offset = s->_raw_size; 5937130561Sobrien if ((ent->tls_type & *lgot_masks & TLS_GD) != 0) 5938130561Sobrien { 5939130561Sobrien s->_raw_size += 16; 5940130561Sobrien if (info->shared) 5941130561Sobrien srel->_raw_size += 2 * sizeof (Elf64_External_Rela); 5942130561Sobrien } 5943130561Sobrien else 5944130561Sobrien { 5945130561Sobrien s->_raw_size += 8; 5946130561Sobrien if (info->shared) 5947130561Sobrien srel->_raw_size += sizeof (Elf64_External_Rela); 5948130561Sobrien } 5949130561Sobrien } 5950130561Sobrien } 5951130561Sobrien else 5952130561Sobrien ent->got.offset = (bfd_vma) -1; 595389857Sobrien } 595489857Sobrien } 595589857Sobrien 595689857Sobrien /* Allocate global sym .plt and .got entries, and space for global 595789857Sobrien sym dynamic relocs. */ 5958130561Sobrien elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, info); 595989857Sobrien 596089857Sobrien /* We now have determined the sizes of the various dynamic sections. 596189857Sobrien Allocate memory for them. */ 5962130561Sobrien relocs = FALSE; 596389857Sobrien for (s = dynobj->sections; s != NULL; s = s->next) 596489857Sobrien { 596589857Sobrien if ((s->flags & SEC_LINKER_CREATED) == 0) 596689857Sobrien continue; 596789857Sobrien 5968130561Sobrien /* Reset _cooked_size since prelim layout will set it wrongly, 5969130561Sobrien and a non-zero _cooked_size sticks. */ 5970130561Sobrien s->_cooked_size = 0; 5971130561Sobrien 5972130561Sobrien if (s == htab->brlt || s == htab->relbrlt) 5973104834Sobrien /* These haven't been allocated yet; don't strip. */ 5974104834Sobrien continue; 5975130561Sobrien else if (s == htab->got 5976130561Sobrien || s == htab->plt 5977130561Sobrien || s == htab->glink) 597889857Sobrien { 597989857Sobrien /* Strip this section if we don't need it; see the 598089857Sobrien comment below. */ 598189857Sobrien } 598289857Sobrien else if (strncmp (bfd_get_section_name (dynobj, s), ".rela", 5) == 0) 598389857Sobrien { 598489857Sobrien if (s->_raw_size == 0) 598589857Sobrien { 598689857Sobrien /* If we don't need this section, strip it from the 598789857Sobrien output file. This is mostly to handle .rela.bss and 598889857Sobrien .rela.plt. We must create both sections in 598989857Sobrien create_dynamic_sections, because they must be created 599089857Sobrien before the linker maps input sections to output 599189857Sobrien sections. The linker does that before 599289857Sobrien adjust_dynamic_symbol is called, and it is that 599389857Sobrien function which decides whether anything needs to go 599489857Sobrien into these sections. */ 599589857Sobrien } 599689857Sobrien else 599789857Sobrien { 5998130561Sobrien if (s != htab->relplt) 5999130561Sobrien relocs = TRUE; 600089857Sobrien 600189857Sobrien /* We use the reloc_count field as a counter if we need 600289857Sobrien to copy relocs into the output file. */ 600389857Sobrien s->reloc_count = 0; 600489857Sobrien } 600589857Sobrien } 600689857Sobrien else 600789857Sobrien { 600889857Sobrien /* It's not one of our sections, so don't allocate space. */ 600989857Sobrien continue; 601089857Sobrien } 601189857Sobrien 601289857Sobrien if (s->_raw_size == 0) 601389857Sobrien { 601489857Sobrien _bfd_strip_section_from_output (info, s); 601589857Sobrien continue; 601689857Sobrien } 601789857Sobrien 6018104834Sobrien /* .plt is in the bss section. We don't initialise it. */ 6019130561Sobrien if (s == htab->plt) 6020104834Sobrien continue; 6021104834Sobrien 602289857Sobrien /* Allocate memory for the section contents. We use bfd_zalloc 602389857Sobrien here in case unused entries are not reclaimed before the 602489857Sobrien section's contents are written out. This should not happen, 6025130561Sobrien but this way if it does we get a R_PPC64_NONE reloc in .rela 6026130561Sobrien sections instead of garbage. 6027130561Sobrien We also rely on the section contents being zero when writing 6028130561Sobrien the GOT. */ 6029130561Sobrien s->contents = bfd_zalloc (dynobj, s->_raw_size); 603089857Sobrien if (s->contents == NULL) 6031130561Sobrien return FALSE; 603289857Sobrien } 603389857Sobrien 6034130561Sobrien for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) 6035130561Sobrien { 6036209867Snwhitehorn /* Skip this BFD if it is not ELF */ 6037209867Snwhitehorn if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour) 6038209867Snwhitehorn continue; 6039209867Snwhitehorn 6040130561Sobrien s = ppc64_elf_tdata (ibfd)->got; 6041130561Sobrien if (s != NULL && s != htab->got) 6042130561Sobrien { 6043130561Sobrien s->_cooked_size = 0; 6044130561Sobrien if (s->_raw_size == 0) 6045130561Sobrien _bfd_strip_section_from_output (info, s); 6046130561Sobrien else 6047130561Sobrien { 6048130561Sobrien s->contents = bfd_zalloc (ibfd, s->_raw_size); 6049130561Sobrien if (s->contents == NULL) 6050130561Sobrien return FALSE; 6051130561Sobrien } 6052130561Sobrien } 6053130561Sobrien s = ppc64_elf_tdata (ibfd)->relgot; 6054130561Sobrien if (s != NULL) 6055130561Sobrien { 6056130561Sobrien s->_cooked_size = 0; 6057130561Sobrien if (s->_raw_size == 0) 6058130561Sobrien _bfd_strip_section_from_output (info, s); 6059130561Sobrien else 6060130561Sobrien { 6061130561Sobrien s->contents = bfd_zalloc (ibfd, s->_raw_size); 6062130561Sobrien if (s->contents == NULL) 6063130561Sobrien return FALSE; 6064130561Sobrien relocs = TRUE; 6065130561Sobrien s->reloc_count = 0; 6066130561Sobrien } 6067130561Sobrien } 6068130561Sobrien } 6069130561Sobrien 607089857Sobrien if (htab->elf.dynamic_sections_created) 607189857Sobrien { 607289857Sobrien /* Add some entries to the .dynamic section. We fill in the 607389857Sobrien values later, in ppc64_elf_finish_dynamic_sections, but we 607489857Sobrien must add the entries now so that we get the correct size for 607589857Sobrien the .dynamic section. The DT_DEBUG entry is filled in by the 607689857Sobrien dynamic linker and used by the debugger. */ 607789857Sobrien#define add_dynamic_entry(TAG, VAL) \ 6078130561Sobrien _bfd_elf_add_dynamic_entry (info, TAG, VAL) 607989857Sobrien 6080130561Sobrien if (info->executable) 608189857Sobrien { 608289857Sobrien if (!add_dynamic_entry (DT_DEBUG, 0)) 6083130561Sobrien return FALSE; 608489857Sobrien } 608589857Sobrien 6086130561Sobrien if (htab->plt != NULL && htab->plt->_raw_size != 0) 608789857Sobrien { 608889857Sobrien if (!add_dynamic_entry (DT_PLTGOT, 0) 608989857Sobrien || !add_dynamic_entry (DT_PLTRELSZ, 0) 609089857Sobrien || !add_dynamic_entry (DT_PLTREL, DT_RELA) 609189857Sobrien || !add_dynamic_entry (DT_JMPREL, 0) 609289857Sobrien || !add_dynamic_entry (DT_PPC64_GLINK, 0)) 6093130561Sobrien return FALSE; 609489857Sobrien } 609589857Sobrien 609691041Sobrien if (NO_OPD_RELOCS) 609791041Sobrien { 609891041Sobrien if (!add_dynamic_entry (DT_PPC64_OPD, 0) 609991041Sobrien || !add_dynamic_entry (DT_PPC64_OPDSZ, 0)) 6100130561Sobrien return FALSE; 610191041Sobrien } 610291041Sobrien 610389857Sobrien if (relocs) 610489857Sobrien { 610589857Sobrien if (!add_dynamic_entry (DT_RELA, 0) 610689857Sobrien || !add_dynamic_entry (DT_RELASZ, 0) 610789857Sobrien || !add_dynamic_entry (DT_RELAENT, sizeof (Elf64_External_Rela))) 6108130561Sobrien return FALSE; 610989857Sobrien 611089857Sobrien /* If any dynamic relocs apply to a read-only section, 611189857Sobrien then we need a DT_TEXTREL entry. */ 611291041Sobrien if ((info->flags & DF_TEXTREL) == 0) 6113130561Sobrien elf_link_hash_traverse (&htab->elf, readonly_dynrelocs, info); 611489857Sobrien 611589857Sobrien if ((info->flags & DF_TEXTREL) != 0) 611689857Sobrien { 611789857Sobrien if (!add_dynamic_entry (DT_TEXTREL, 0)) 6118130561Sobrien return FALSE; 611989857Sobrien } 612089857Sobrien } 612189857Sobrien } 612289857Sobrien#undef add_dynamic_entry 612389857Sobrien 6124130561Sobrien return TRUE; 612589857Sobrien} 612689857Sobrien 6127104834Sobrien/* Determine the type of stub needed, if any, for a call. */ 612889857Sobrien 6129130561Sobrienstatic inline enum ppc_stub_type 6130130561Sobrienppc_type_of_stub (asection *input_sec, 6131130561Sobrien const Elf_Internal_Rela *rel, 6132130561Sobrien struct ppc_link_hash_entry **hash, 6133130561Sobrien bfd_vma destination) 613489857Sobrien{ 6135104834Sobrien struct ppc_link_hash_entry *h = *hash; 6136104834Sobrien bfd_vma location; 6137104834Sobrien bfd_vma branch_offset; 6138104834Sobrien bfd_vma max_branch_offset; 6139130561Sobrien enum elf_ppc64_reloc_type r_type; 614099461Sobrien 6141104834Sobrien if (h != NULL) 614289857Sobrien { 6143104834Sobrien if (h->oh != NULL 6144104834Sobrien && h->oh->dynindx != -1) 6145104834Sobrien { 6146130561Sobrien struct plt_entry *ent; 6147130561Sobrien for (ent = h->oh->plt.plist; ent != NULL; ent = ent->next) 6148130561Sobrien if (ent->addend == rel->r_addend 6149130561Sobrien && ent->plt.offset != (bfd_vma) -1) 6150130561Sobrien { 6151130561Sobrien *hash = (struct ppc_link_hash_entry *) h->oh; 6152130561Sobrien return ppc_stub_plt_call; 6153130561Sobrien } 6154104834Sobrien } 615589857Sobrien 6156130561Sobrien if (!(h->elf.root.type == bfd_link_hash_defined 6157130561Sobrien || h->elf.root.type == bfd_link_hash_defweak) 6158130561Sobrien || h->elf.root.u.def.section->output_section == NULL) 6159104834Sobrien return ppc_stub_none; 616099461Sobrien } 616189857Sobrien 6162104834Sobrien /* Determine where the call point is. */ 6163104834Sobrien location = (input_sec->output_offset 6164104834Sobrien + input_sec->output_section->vma 6165104834Sobrien + rel->r_offset); 616689857Sobrien 6167104834Sobrien branch_offset = destination - location; 6168104834Sobrien r_type = ELF64_R_TYPE (rel->r_info); 616989857Sobrien 6170104834Sobrien /* Determine if a long branch stub is needed. */ 6171104834Sobrien max_branch_offset = 1 << 25; 6172130561Sobrien if (r_type != R_PPC64_REL24) 6173104834Sobrien max_branch_offset = 1 << 15; 617489857Sobrien 6175104834Sobrien if (branch_offset + max_branch_offset >= 2 * max_branch_offset) 6176104834Sobrien /* We need a stub. Figure out whether a long_branch or plt_branch 6177104834Sobrien is needed later. */ 6178104834Sobrien return ppc_stub_long_branch; 617989857Sobrien 6180104834Sobrien return ppc_stub_none; 618189857Sobrien} 618289857Sobrien 618389857Sobrien/* Build a .plt call stub. */ 618489857Sobrien 6185130561Sobrienstatic inline bfd_byte * 6186130561Sobrienbuild_plt_stub (bfd *obfd, bfd_byte *p, int offset) 618789857Sobrien{ 618889857Sobrien#define PPC_LO(v) ((v) & 0xffff) 618989857Sobrien#define PPC_HI(v) (((v) >> 16) & 0xffff) 619089857Sobrien#define PPC_HA(v) PPC_HI ((v) + 0x8000) 619189857Sobrien 619289857Sobrien bfd_put_32 (obfd, ADDIS_R12_R2 | PPC_HA (offset), p), p += 4; 6193130561Sobrien bfd_put_32 (obfd, STD_R2_40R1, p), p += 4; 619489857Sobrien bfd_put_32 (obfd, LD_R11_0R12 | PPC_LO (offset), p), p += 4; 619589857Sobrien if (PPC_HA (offset + 8) != PPC_HA (offset)) 6196130561Sobrien bfd_put_32 (obfd, ADDIS_R12_R12 | 1, p), p += 4; 619789857Sobrien offset += 8; 619889857Sobrien bfd_put_32 (obfd, LD_R2_0R12 | PPC_LO (offset), p), p += 4; 619989857Sobrien if (PPC_HA (offset + 8) != PPC_HA (offset)) 6200130561Sobrien bfd_put_32 (obfd, ADDIS_R12_R12 | 1, p), p += 4; 620189857Sobrien offset += 8; 620289857Sobrien bfd_put_32 (obfd, MTCTR_R11, p), p += 4; 620389857Sobrien bfd_put_32 (obfd, LD_R11_0R12 | PPC_LO (offset), p), p += 4; 620489857Sobrien bfd_put_32 (obfd, BCTR, p), p += 4; 620589857Sobrien return p; 620689857Sobrien} 620789857Sobrien 6208130561Sobrienstatic bfd_boolean 6209130561Sobrienppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) 621089857Sobrien{ 6211104834Sobrien struct ppc_stub_hash_entry *stub_entry; 6212104834Sobrien struct ppc_branch_hash_entry *br_entry; 621389857Sobrien struct bfd_link_info *info; 621489857Sobrien struct ppc_link_hash_table *htab; 6215104834Sobrien bfd_byte *loc; 6216104834Sobrien bfd_byte *p; 6217104834Sobrien unsigned int indx; 6218130561Sobrien struct plt_entry *ent; 6219104834Sobrien bfd_vma off; 6220104834Sobrien int size; 622189857Sobrien 6222104834Sobrien /* Massage our args to the form they really have. */ 6223104834Sobrien stub_entry = (struct ppc_stub_hash_entry *) gen_entry; 6224130561Sobrien info = in_arg; 622589857Sobrien 622689857Sobrien htab = ppc_hash_table (info); 622789857Sobrien 6228104834Sobrien /* Make a note of the offset within the stubs for this entry. */ 6229130561Sobrien stub_entry->stub_offset = stub_entry->stub_sec->_cooked_size; 6230130561Sobrien loc = stub_entry->stub_sec->contents + stub_entry->stub_offset; 6231104834Sobrien 6232130561Sobrien htab->stub_count[stub_entry->stub_type - 1] += 1; 6233104834Sobrien switch (stub_entry->stub_type) 623489857Sobrien { 6235104834Sobrien case ppc_stub_long_branch: 6236130561Sobrien case ppc_stub_long_branch_r2off: 6237104834Sobrien /* Branches are relative. This is where we are going to. */ 6238104834Sobrien off = (stub_entry->target_value 6239104834Sobrien + stub_entry->target_section->output_offset 6240104834Sobrien + stub_entry->target_section->output_section->vma); 624189857Sobrien 6242104834Sobrien /* And this is where we are coming from. */ 6243104834Sobrien off -= (stub_entry->stub_offset 6244130561Sobrien + stub_entry->stub_sec->output_offset 6245130561Sobrien + stub_entry->stub_sec->output_section->vma); 624689857Sobrien 6247130561Sobrien if (stub_entry->stub_type != ppc_stub_long_branch_r2off) 6248130561Sobrien size = 4; 6249130561Sobrien else 6250130561Sobrien { 6251130561Sobrien bfd_vma r2off; 6252130561Sobrien 6253130561Sobrien r2off = (htab->stub_group[stub_entry->target_section->id].toc_off 6254130561Sobrien - htab->stub_group[stub_entry->id_sec->id].toc_off); 6255130561Sobrien bfd_put_32 (htab->stub_bfd, STD_R2_40R1, loc); 6256130561Sobrien loc += 4; 6257130561Sobrien bfd_put_32 (htab->stub_bfd, ADDIS_R2_R2 | PPC_HA (r2off), loc); 6258130561Sobrien loc += 4; 6259130561Sobrien bfd_put_32 (htab->stub_bfd, ADDI_R2_R2 | PPC_LO (r2off), loc); 6260130561Sobrien loc += 4; 6261130561Sobrien off -= 12; 6262130561Sobrien size = 16; 6263130561Sobrien } 6264130561Sobrien bfd_put_32 (htab->stub_bfd, B_DOT | (off & 0x3fffffc), loc); 6265130561Sobrien 6266104834Sobrien BFD_ASSERT (off + (1 << 25) < (bfd_vma) (1 << 26)); 6267104834Sobrien break; 626889857Sobrien 6269104834Sobrien case ppc_stub_plt_branch: 6270130561Sobrien case ppc_stub_plt_branch_r2off: 6271104834Sobrien br_entry = ppc_branch_hash_lookup (&htab->branch_hash_table, 6272104834Sobrien stub_entry->root.string + 9, 6273130561Sobrien FALSE, FALSE); 6274104834Sobrien if (br_entry == NULL) 6275104834Sobrien { 6276104834Sobrien (*_bfd_error_handler) (_("can't find branch stub `%s'"), 6277104834Sobrien stub_entry->root.string + 9); 6278130561Sobrien htab->stub_error = TRUE; 6279130561Sobrien return FALSE; 6280104834Sobrien } 628189857Sobrien 6282104834Sobrien off = (stub_entry->target_value 6283104834Sobrien + stub_entry->target_section->output_offset 6284104834Sobrien + stub_entry->target_section->output_section->vma); 6285104834Sobrien 6286130561Sobrien bfd_put_64 (htab->brlt->owner, off, 6287130561Sobrien htab->brlt->contents + br_entry->offset); 6288104834Sobrien 6289104834Sobrien if (info->shared) 629089857Sobrien { 6291104834Sobrien /* Create a reloc for the branch lookup table entry. */ 6292104834Sobrien Elf_Internal_Rela rela; 6293130561Sobrien bfd_byte *rl; 6294104834Sobrien 6295104834Sobrien rela.r_offset = (br_entry->offset 6296130561Sobrien + htab->brlt->output_offset 6297130561Sobrien + htab->brlt->output_section->vma); 6298104834Sobrien rela.r_info = ELF64_R_INFO (0, R_PPC64_RELATIVE); 6299104834Sobrien rela.r_addend = off; 6300104834Sobrien 6301130561Sobrien rl = htab->relbrlt->contents; 6302130561Sobrien rl += htab->relbrlt->reloc_count++ * sizeof (Elf64_External_Rela); 6303130561Sobrien bfd_elf64_swap_reloca_out (htab->relbrlt->owner, &rela, rl); 6304104834Sobrien } 6305104834Sobrien 6306104834Sobrien off = (br_entry->offset 6307130561Sobrien + htab->brlt->output_offset 6308130561Sobrien + htab->brlt->output_section->vma 6309130561Sobrien - elf_gp (htab->brlt->output_section->owner) 6310130561Sobrien - htab->stub_group[stub_entry->id_sec->id].toc_off); 6311104834Sobrien 6312130561Sobrien if (off + 0x80008000 > 0xffffffff || (off & 7) != 0) 6313104834Sobrien { 631489857Sobrien (*_bfd_error_handler) 631589857Sobrien (_("linkage table error against `%s'"), 6316104834Sobrien stub_entry->root.string); 631789857Sobrien bfd_set_error (bfd_error_bad_value); 6318130561Sobrien htab->stub_error = TRUE; 6319130561Sobrien return FALSE; 632089857Sobrien } 632189857Sobrien 6322104834Sobrien indx = off; 6323130561Sobrien if (stub_entry->stub_type != ppc_stub_plt_branch_r2off) 6324130561Sobrien { 6325130561Sobrien bfd_put_32 (htab->stub_bfd, ADDIS_R12_R2 | PPC_HA (indx), loc); 6326130561Sobrien loc += 4; 6327130561Sobrien bfd_put_32 (htab->stub_bfd, LD_R11_0R12 | PPC_LO (indx), loc); 6328130561Sobrien size = 16; 6329130561Sobrien } 6330130561Sobrien else 6331130561Sobrien { 6332130561Sobrien bfd_vma r2off; 6333130561Sobrien 6334130561Sobrien r2off = (htab->stub_group[stub_entry->target_section->id].toc_off 6335130561Sobrien - htab->stub_group[stub_entry->id_sec->id].toc_off); 6336130561Sobrien bfd_put_32 (htab->stub_bfd, STD_R2_40R1, loc); 6337130561Sobrien loc += 4; 6338130561Sobrien bfd_put_32 (htab->stub_bfd, ADDIS_R12_R2 | PPC_HA (indx), loc); 6339130561Sobrien loc += 4; 6340130561Sobrien bfd_put_32 (htab->stub_bfd, LD_R11_0R12 | PPC_LO (indx), loc); 6341130561Sobrien loc += 4; 6342130561Sobrien bfd_put_32 (htab->stub_bfd, ADDIS_R2_R2 | PPC_HA (r2off), loc); 6343130561Sobrien loc += 4; 6344130561Sobrien bfd_put_32 (htab->stub_bfd, ADDI_R2_R2 | PPC_LO (r2off), loc); 6345130561Sobrien size = 28; 6346130561Sobrien } 6347130561Sobrien loc += 4; 6348130561Sobrien bfd_put_32 (htab->stub_bfd, MTCTR_R11, loc); 6349130561Sobrien loc += 4; 6350130561Sobrien bfd_put_32 (htab->stub_bfd, BCTR, loc); 6351104834Sobrien break; 635289857Sobrien 6353104834Sobrien case ppc_stub_plt_call: 6354104834Sobrien /* Do the best we can for shared libraries built without 6355104834Sobrien exporting ".foo" for each "foo". This can happen when symbol 6356104834Sobrien versioning scripts strip all bar a subset of symbols. */ 6357104834Sobrien if (stub_entry->h->oh->root.type != bfd_link_hash_defined 6358104834Sobrien && stub_entry->h->oh->root.type != bfd_link_hash_defweak) 635989857Sobrien { 6360104834Sobrien /* Point the symbol at the stub. There may be multiple stubs, 6361104834Sobrien we don't really care; The main thing is to make this sym 6362130561Sobrien defined somewhere. Maybe defining the symbol in the stub 6363130561Sobrien section is a silly idea. If we didn't do this, htab->top_id 6364130561Sobrien could disappear. */ 6365104834Sobrien stub_entry->h->oh->root.type = bfd_link_hash_defined; 6366104834Sobrien stub_entry->h->oh->root.u.def.section = stub_entry->stub_sec; 6367104834Sobrien stub_entry->h->oh->root.u.def.value = stub_entry->stub_offset; 636889857Sobrien } 6369104834Sobrien 6370104834Sobrien /* Now build the stub. */ 6371130561Sobrien off = (bfd_vma) -1; 6372130561Sobrien for (ent = stub_entry->h->elf.plt.plist; ent != NULL; ent = ent->next) 6373130561Sobrien if (ent->addend == stub_entry->addend) 6374130561Sobrien { 6375130561Sobrien off = ent->plt.offset; 6376130561Sobrien break; 6377130561Sobrien } 6378104834Sobrien if (off >= (bfd_vma) -2) 6379104834Sobrien abort (); 6380104834Sobrien 6381104834Sobrien off &= ~ (bfd_vma) 1; 6382130561Sobrien off += (htab->plt->output_offset 6383130561Sobrien + htab->plt->output_section->vma 6384130561Sobrien - elf_gp (htab->plt->output_section->owner) 6385130561Sobrien - htab->stub_group[stub_entry->id_sec->id].toc_off); 6386104834Sobrien 6387130561Sobrien if (off + 0x80008000 > 0xffffffff || (off & 7) != 0) 638889857Sobrien { 6389104834Sobrien (*_bfd_error_handler) 6390104834Sobrien (_("linkage table error against `%s'"), 6391104834Sobrien stub_entry->h->elf.root.root.string); 6392104834Sobrien bfd_set_error (bfd_error_bad_value); 6393130561Sobrien htab->stub_error = TRUE; 6394130561Sobrien return FALSE; 639589857Sobrien } 6396104834Sobrien 6397130561Sobrien p = build_plt_stub (htab->stub_bfd, loc, off); 6398104834Sobrien size = p - loc; 6399104834Sobrien break; 6400104834Sobrien 6401104834Sobrien default: 6402104834Sobrien BFD_FAIL (); 6403130561Sobrien return FALSE; 640489857Sobrien } 6405104834Sobrien 6406130561Sobrien stub_entry->stub_sec->_cooked_size += size; 6407130561Sobrien 6408130561Sobrien if (htab->emit_stub_syms 6409130561Sobrien && !(stub_entry->stub_type == ppc_stub_plt_call 6410130561Sobrien && stub_entry->h->oh->root.type == bfd_link_hash_defined 6411130561Sobrien && stub_entry->h->oh->root.u.def.section == stub_entry->stub_sec 6412130561Sobrien && stub_entry->h->oh->root.u.def.value == stub_entry->stub_offset)) 6413130561Sobrien { 6414130561Sobrien struct elf_link_hash_entry *h; 6415130561Sobrien h = elf_link_hash_lookup (&htab->elf, stub_entry->root.string, 6416130561Sobrien TRUE, FALSE, FALSE); 6417130561Sobrien if (h == NULL) 6418130561Sobrien return FALSE; 6419130561Sobrien if (h->root.type == bfd_link_hash_new) 6420130561Sobrien { 6421130561Sobrien h->root.type = bfd_link_hash_defined; 6422130561Sobrien h->root.u.def.section = stub_entry->stub_sec; 6423130561Sobrien h->root.u.def.value = stub_entry->stub_offset; 6424130561Sobrien h->elf_link_hash_flags = (ELF_LINK_HASH_REF_REGULAR 6425130561Sobrien | ELF_LINK_HASH_DEF_REGULAR 6426130561Sobrien | ELF_LINK_HASH_REF_REGULAR_NONWEAK 6427130561Sobrien | ELF_LINK_FORCED_LOCAL); 6428130561Sobrien } 6429130561Sobrien } 6430130561Sobrien 6431130561Sobrien return TRUE; 643289857Sobrien} 643389857Sobrien 6434104834Sobrien/* As above, but don't actually build the stub. Just bump offset so 6435104834Sobrien we know stub section sizes, and select plt_branch stubs where 6436104834Sobrien long_branch stubs won't do. */ 6437104834Sobrien 6438130561Sobrienstatic bfd_boolean 6439130561Sobrienppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) 6440104834Sobrien{ 6441104834Sobrien struct ppc_stub_hash_entry *stub_entry; 6442130561Sobrien struct bfd_link_info *info; 6443104834Sobrien struct ppc_link_hash_table *htab; 6444104834Sobrien bfd_vma off; 6445104834Sobrien int size; 6446104834Sobrien 6447104834Sobrien /* Massage our args to the form they really have. */ 6448104834Sobrien stub_entry = (struct ppc_stub_hash_entry *) gen_entry; 6449130561Sobrien info = in_arg; 6450104834Sobrien 6451130561Sobrien htab = ppc_hash_table (info); 6452130561Sobrien 6453104834Sobrien if (stub_entry->stub_type == ppc_stub_plt_call) 6454104834Sobrien { 6455130561Sobrien struct plt_entry *ent; 6456130561Sobrien off = (bfd_vma) -1; 6457130561Sobrien for (ent = stub_entry->h->elf.plt.plist; ent != NULL; ent = ent->next) 6458130561Sobrien if (ent->addend == stub_entry->addend) 6459130561Sobrien { 6460130561Sobrien off = ent->plt.offset & ~(bfd_vma) 1; 6461130561Sobrien break; 6462130561Sobrien } 6463130561Sobrien if (off >= (bfd_vma) -2) 6464130561Sobrien abort (); 6465130561Sobrien off += (htab->plt->output_offset 6466130561Sobrien + htab->plt->output_section->vma 6467130561Sobrien - elf_gp (htab->plt->output_section->owner) 6468130561Sobrien - htab->stub_group[stub_entry->id_sec->id].toc_off); 6469104834Sobrien 6470130561Sobrien size = PLT_CALL_STUB_SIZE; 6471130561Sobrien if (PPC_HA (off + 16) != PPC_HA (off)) 6472104834Sobrien size += 4; 6473104834Sobrien } 6474104834Sobrien else 6475104834Sobrien { 6476130561Sobrien /* ppc_stub_long_branch or ppc_stub_plt_branch, or their r2off 6477130561Sobrien variants. */ 6478104834Sobrien off = (stub_entry->target_value 6479104834Sobrien + stub_entry->target_section->output_offset 6480104834Sobrien + stub_entry->target_section->output_section->vma); 6481104834Sobrien off -= (stub_entry->stub_sec->_raw_size 6482104834Sobrien + stub_entry->stub_sec->output_offset 6483104834Sobrien + stub_entry->stub_sec->output_section->vma); 6484104834Sobrien 6485130561Sobrien /* Reset the stub type from the plt variant in case we now 6486130561Sobrien can reach with a shorter stub. */ 6487130561Sobrien if (stub_entry->stub_type >= ppc_stub_plt_branch) 6488130561Sobrien stub_entry->stub_type += ppc_stub_long_branch - ppc_stub_plt_branch; 6489130561Sobrien 6490130561Sobrien size = 4; 6491130561Sobrien if (stub_entry->stub_type == ppc_stub_long_branch_r2off) 6492130561Sobrien { 6493130561Sobrien off -= 12; 6494130561Sobrien size = 16; 6495130561Sobrien } 6496130561Sobrien 6497130561Sobrien /* If the branch offset if too big, use a ppc_stub_plt_branch. */ 6498104834Sobrien if (off + (1 << 25) >= (bfd_vma) (1 << 26)) 6499104834Sobrien { 6500104834Sobrien struct ppc_branch_hash_entry *br_entry; 6501104834Sobrien 6502104834Sobrien br_entry = ppc_branch_hash_lookup (&htab->branch_hash_table, 6503104834Sobrien stub_entry->root.string + 9, 6504130561Sobrien TRUE, FALSE); 6505104834Sobrien if (br_entry == NULL) 6506104834Sobrien { 6507104834Sobrien (*_bfd_error_handler) (_("can't build branch stub `%s'"), 6508104834Sobrien stub_entry->root.string + 9); 6509130561Sobrien htab->stub_error = TRUE; 6510130561Sobrien return FALSE; 6511104834Sobrien } 6512104834Sobrien 6513104834Sobrien if (br_entry->iter != htab->stub_iteration) 6514104834Sobrien { 6515104834Sobrien br_entry->iter = htab->stub_iteration; 6516130561Sobrien br_entry->offset = htab->brlt->_raw_size; 6517130561Sobrien htab->brlt->_raw_size += 8; 6518130561Sobrien 6519130561Sobrien if (info->shared) 6520130561Sobrien htab->relbrlt->_raw_size += sizeof (Elf64_External_Rela); 6521104834Sobrien } 6522130561Sobrien 6523130561Sobrien stub_entry->stub_type += ppc_stub_plt_branch - ppc_stub_long_branch; 6524104834Sobrien size = 16; 6525130561Sobrien if (stub_entry->stub_type != ppc_stub_plt_branch) 6526130561Sobrien size = 28; 6527104834Sobrien } 6528104834Sobrien } 6529104834Sobrien 6530104834Sobrien stub_entry->stub_sec->_raw_size += size; 6531130561Sobrien return TRUE; 6532104834Sobrien} 6533104834Sobrien 6534104834Sobrien/* Set up various things so that we can make a list of input sections 6535104834Sobrien for each output section included in the link. Returns -1 on error, 6536104834Sobrien 0 when no stubs will be needed, and 1 on success. */ 6537104834Sobrien 6538104834Sobrienint 6539130561Sobrienppc64_elf_setup_section_lists (bfd *output_bfd, struct bfd_link_info *info) 654089857Sobrien{ 6541104834Sobrien bfd *input_bfd; 6542130561Sobrien int top_id, top_index, id; 6543104834Sobrien asection *section; 6544130561Sobrien asection **input_list; 6545104834Sobrien bfd_size_type amt; 654689857Sobrien struct ppc_link_hash_table *htab = ppc_hash_table (info); 654789857Sobrien 6548130561Sobrien if (htab->brlt == NULL) 6549104834Sobrien return 0; 655089857Sobrien 6551104834Sobrien /* Find the top input section id. */ 6552130561Sobrien for (input_bfd = info->input_bfds, top_id = 3; 6553104834Sobrien input_bfd != NULL; 6554104834Sobrien input_bfd = input_bfd->link_next) 6555104834Sobrien { 6556104834Sobrien for (section = input_bfd->sections; 6557104834Sobrien section != NULL; 6558104834Sobrien section = section->next) 6559104834Sobrien { 6560104834Sobrien if (top_id < section->id) 6561104834Sobrien top_id = section->id; 6562104834Sobrien } 6563104834Sobrien } 656489857Sobrien 6565130561Sobrien htab->top_id = top_id; 6566104834Sobrien amt = sizeof (struct map_stub) * (top_id + 1); 6567130561Sobrien htab->stub_group = bfd_zmalloc (amt); 6568104834Sobrien if (htab->stub_group == NULL) 6569104834Sobrien return -1; 6570104834Sobrien 6571130561Sobrien /* Set toc_off for com, und, abs and ind sections. */ 6572130561Sobrien for (id = 0; id < 3; id++) 6573130561Sobrien htab->stub_group[id].toc_off = TOC_BASE_OFF; 6574130561Sobrien 6575130561Sobrien elf_gp (output_bfd) = htab->toc_curr = ppc64_elf_toc (output_bfd); 6576130561Sobrien 6577104834Sobrien /* We can't use output_bfd->section_count here to find the top output 6578104834Sobrien section index as some sections may have been removed, and 6579104834Sobrien _bfd_strip_section_from_output doesn't renumber the indices. */ 6580104834Sobrien for (section = output_bfd->sections, top_index = 0; 6581104834Sobrien section != NULL; 6582104834Sobrien section = section->next) 658389857Sobrien { 6584104834Sobrien if (top_index < section->index) 6585104834Sobrien top_index = section->index; 658689857Sobrien } 658789857Sobrien 6588104834Sobrien htab->top_index = top_index; 6589104834Sobrien amt = sizeof (asection *) * (top_index + 1); 6590130561Sobrien input_list = bfd_zmalloc (amt); 6591104834Sobrien htab->input_list = input_list; 6592104834Sobrien if (input_list == NULL) 6593104834Sobrien return -1; 659489857Sobrien 6595130561Sobrien return 1; 6596130561Sobrien} 659789857Sobrien 6598130561Sobrien/* The linker repeatedly calls this function for each TOC input section 6599130561Sobrien and linker generated GOT section. Group input bfds such that the toc 6600130561Sobrien within a group is less than 64k in size. Will break with cute linker 6601130561Sobrien scripts that play games with dot in the output toc section. */ 6602130561Sobrien 6603130561Sobrienvoid 6604130561Sobrienppc64_elf_next_toc_section (struct bfd_link_info *info, asection *isec) 6605130561Sobrien{ 6606130561Sobrien struct ppc_link_hash_table *htab = ppc_hash_table (info); 6607130561Sobrien 6608130561Sobrien if (!htab->no_multi_toc) 6609104834Sobrien { 6610130561Sobrien bfd_vma addr = isec->output_offset + isec->output_section->vma; 6611130561Sobrien bfd_vma off = addr - htab->toc_curr; 6612130561Sobrien if (off + isec->_raw_size > 0x10000) 6613130561Sobrien { 6614130561Sobrien htab->toc_curr = addr; 6615130561Sobrien htab->multi_toc_needed = 1; 6616130561Sobrien } 6617130561Sobrien elf_gp (isec->owner) = (htab->toc_curr 6618130561Sobrien - elf_gp (isec->output_section->owner) 6619130561Sobrien + TOC_BASE_OFF); 6620104834Sobrien } 6621130561Sobrien} 662289857Sobrien 6623130561Sobrien/* Called after the last call to the above function. */ 6624130561Sobrien 6625130561Sobrienvoid 6626130561Sobrienppc64_elf_reinit_toc (bfd *output_bfd ATTRIBUTE_UNUSED, 6627130561Sobrien struct bfd_link_info *info) 6628130561Sobrien{ 6629130561Sobrien struct ppc_link_hash_table *htab = ppc_hash_table (info); 6630130561Sobrien 6631130561Sobrien /* toc_curr tracks the TOC offset used for code sections below in 6632130561Sobrien ppc64_elf_next_input_section. Start off at 0x8000. */ 6633130561Sobrien htab->toc_curr = TOC_BASE_OFF; 6634104834Sobrien} 6635104834Sobrien 6636130561Sobrien/* No toc references were found in ISEC. If the code in ISEC makes no 6637130561Sobrien calls, then there's no need to use toc adjusting stubs when branching 6638130561Sobrien into ISEC. Actually, indirect calls from ISEC are OK as they will 6639130561Sobrien load r2. */ 6640130561Sobrien 6641130561Sobrienstatic int 6642130561Sobrientoc_adjusting_stub_needed (struct bfd_link_info *info, asection *isec) 6643130561Sobrien{ 6644130561Sobrien bfd_byte *contents; 6645130561Sobrien bfd_size_type i; 6646130561Sobrien int ret; 6647130561Sobrien int branch_ok; 6648130561Sobrien 6649130561Sobrien /* We know none of our code bearing sections will need toc stubs. */ 6650130561Sobrien if ((isec->flags & SEC_LINKER_CREATED) != 0) 6651130561Sobrien return 0; 6652130561Sobrien 6653130561Sobrien if (isec->_raw_size == 0) 6654130561Sobrien return 0; 6655130561Sobrien 6656130561Sobrien /* Hack for linux kernel. .fixup contains branches, but only back to 6657130561Sobrien the function that hit an exception. */ 6658130561Sobrien branch_ok = strcmp (isec->name, ".fixup") == 0; 6659130561Sobrien 6660130561Sobrien contents = elf_section_data (isec)->this_hdr.contents; 6661130561Sobrien if (contents == NULL) 6662130561Sobrien { 6663130561Sobrien contents = bfd_malloc (isec->_raw_size); 6664130561Sobrien if (contents == NULL) 6665130561Sobrien return -1; 6666130561Sobrien if (! bfd_get_section_contents (isec->owner, isec, contents, 6667130561Sobrien 0, isec->_raw_size)) 6668130561Sobrien { 6669130561Sobrien free (contents); 6670130561Sobrien return -1; 6671130561Sobrien } 6672130561Sobrien if (info->keep_memory) 6673130561Sobrien elf_section_data (isec)->this_hdr.contents = contents; 6674130561Sobrien } 6675130561Sobrien 6676130561Sobrien /* Code scan, because we don't necessarily have relocs on calls to 6677130561Sobrien static functions. */ 6678130561Sobrien ret = 0; 6679130561Sobrien for (i = 0; i < isec->_raw_size; i += 4) 6680130561Sobrien { 6681130561Sobrien unsigned long insn = bfd_get_32 (isec->owner, contents + i); 6682130561Sobrien /* Is this a branch? */ 6683130561Sobrien if ((insn & (0x3f << 26)) == (18 << 26) 6684130561Sobrien /* If branch and link, it's a function call. */ 6685130561Sobrien && ((insn & 1) != 0 6686130561Sobrien /* Sibling calls use a plain branch. I don't know a way 6687130561Sobrien of deciding whether a branch is really a sibling call. */ 6688130561Sobrien || !branch_ok)) 6689130561Sobrien { 6690130561Sobrien ret = 1; 6691130561Sobrien break; 6692130561Sobrien } 6693130561Sobrien } 6694130561Sobrien 6695130561Sobrien if (elf_section_data (isec)->this_hdr.contents != contents) 6696130561Sobrien free (contents); 6697130561Sobrien return ret; 6698130561Sobrien} 6699130561Sobrien 6700104834Sobrien/* The linker repeatedly calls this function for each input section, 6701104834Sobrien in the order that input sections are linked into output sections. 6702104834Sobrien Build lists of input sections to determine groupings between which 6703104834Sobrien we may insert linker stubs. */ 6704104834Sobrien 6705130561Sobrienbfd_boolean 6706130561Sobrienppc64_elf_next_input_section (struct bfd_link_info *info, asection *isec) 6707104834Sobrien{ 6708104834Sobrien struct ppc_link_hash_table *htab = ppc_hash_table (info); 6709130561Sobrien int ret; 6710104834Sobrien 6711130561Sobrien if ((isec->output_section->flags & SEC_CODE) != 0 6712130561Sobrien && isec->output_section->index <= htab->top_index) 671389857Sobrien { 6714104834Sobrien asection **list = htab->input_list + isec->output_section->index; 6715130561Sobrien /* Steal the link_sec pointer for our list. */ 6716104834Sobrien#define PREV_SEC(sec) (htab->stub_group[(sec)->id].link_sec) 6717130561Sobrien /* This happens to make the list in reverse order, 6718130561Sobrien which is what we want. */ 6719130561Sobrien PREV_SEC (isec) = *list; 6720130561Sobrien *list = isec; 672189857Sobrien } 6722130561Sobrien 6723130561Sobrien /* If a code section has a function that uses the TOC then we need 6724130561Sobrien to use the right TOC (obviously). Also, make sure that .opd gets 6725130561Sobrien the correct TOC value for R_PPC64_TOC relocs that don't have or 6726130561Sobrien can't find their function symbol (shouldn't ever happen now). */ 6727130561Sobrien if (isec->has_gp_reloc || (isec->flags & SEC_CODE) == 0) 6728130561Sobrien { 6729130561Sobrien if (elf_gp (isec->owner) != 0) 6730130561Sobrien htab->toc_curr = elf_gp (isec->owner); 6731130561Sobrien } 6732130561Sobrien else if ((ret = toc_adjusting_stub_needed (info, isec)) < 0) 6733130561Sobrien return FALSE; 6734130561Sobrien else 6735130561Sobrien isec->has_gp_reloc = ret; 6736130561Sobrien 6737130561Sobrien /* Functions that don't use the TOC can belong in any TOC group. 6738130561Sobrien Use the last TOC base. This happens to make _init and _fini 6739130561Sobrien pasting work. */ 6740130561Sobrien htab->stub_group[isec->id].toc_off = htab->toc_curr; 6741130561Sobrien return TRUE; 674289857Sobrien} 674389857Sobrien 6744104834Sobrien/* See whether we can group stub sections together. Grouping stub 6745104834Sobrien sections may result in fewer stubs. More importantly, we need to 6746104834Sobrien put all .init* and .fini* stubs at the beginning of the .init or 6747104834Sobrien .fini output sections respectively, because glibc splits the 6748104834Sobrien _init and _fini functions into multiple parts. Putting a stub in 6749104834Sobrien the middle of a function is not a good idea. */ 675089857Sobrien 6751104834Sobrienstatic void 6752130561Sobriengroup_sections (struct ppc_link_hash_table *htab, 6753130561Sobrien bfd_size_type stub_group_size, 6754130561Sobrien bfd_boolean stubs_always_before_branch) 675589857Sobrien{ 6756104834Sobrien asection **list = htab->input_list + htab->top_index; 6757104834Sobrien do 6758104834Sobrien { 6759104834Sobrien asection *tail = *list; 6760104834Sobrien while (tail != NULL) 6761104834Sobrien { 6762104834Sobrien asection *curr; 6763104834Sobrien asection *prev; 6764104834Sobrien bfd_size_type total; 6765130561Sobrien bfd_boolean big_sec; 6766130561Sobrien bfd_vma curr_toc; 676789857Sobrien 6768104834Sobrien curr = tail; 6769104834Sobrien if (tail->_cooked_size) 6770104834Sobrien total = tail->_cooked_size; 6771104834Sobrien else 6772104834Sobrien total = tail->_raw_size; 6773130561Sobrien big_sec = total >= stub_group_size; 6774130561Sobrien curr_toc = htab->stub_group[tail->id].toc_off; 6775130561Sobrien 6776104834Sobrien while ((prev = PREV_SEC (curr)) != NULL 6777104834Sobrien && ((total += curr->output_offset - prev->output_offset) 6778130561Sobrien < stub_group_size) 6779130561Sobrien && htab->stub_group[prev->id].toc_off == curr_toc) 6780104834Sobrien curr = prev; 678189857Sobrien 6782104834Sobrien /* OK, the size from the start of CURR to the end is less 6783104834Sobrien than stub_group_size and thus can be handled by one stub 6784104834Sobrien section. (or the tail section is itself larger than 6785104834Sobrien stub_group_size, in which case we may be toast.) We 6786104834Sobrien should really be keeping track of the total size of stubs 6787104834Sobrien added here, as stubs contribute to the final output 6788104834Sobrien section size. That's a little tricky, and this way will 6789104834Sobrien only break if stubs added make the total size more than 6790104834Sobrien 2^25, ie. for the default stub_group_size, if stubs total 6791130561Sobrien more than 2097152 bytes, or nearly 75000 plt call stubs. */ 6792104834Sobrien do 6793104834Sobrien { 6794104834Sobrien prev = PREV_SEC (tail); 6795104834Sobrien /* Set up this stub group. */ 6796104834Sobrien htab->stub_group[tail->id].link_sec = curr; 6797104834Sobrien } 6798104834Sobrien while (tail != curr && (tail = prev) != NULL); 6799104834Sobrien 6800104834Sobrien /* But wait, there's more! Input sections up to stub_group_size 6801130561Sobrien bytes before the stub section can be handled by it too. 6802130561Sobrien Don't do this if we have a really large section after the 6803130561Sobrien stubs, as adding more stubs increases the chance that 6804130561Sobrien branches may not reach into the stub section. */ 6805130561Sobrien if (!stubs_always_before_branch && !big_sec) 6806104834Sobrien { 6807104834Sobrien total = 0; 6808104834Sobrien while (prev != NULL 6809104834Sobrien && ((total += tail->output_offset - prev->output_offset) 6810130561Sobrien < stub_group_size) 6811130561Sobrien && htab->stub_group[prev->id].toc_off == curr_toc) 6812104834Sobrien { 6813104834Sobrien tail = prev; 6814104834Sobrien prev = PREV_SEC (tail); 6815104834Sobrien htab->stub_group[tail->id].link_sec = curr; 6816104834Sobrien } 6817104834Sobrien } 6818104834Sobrien tail = prev; 6819104834Sobrien } 6820104834Sobrien } 6821104834Sobrien while (list-- != htab->input_list); 6822104834Sobrien free (htab->input_list); 6823104834Sobrien#undef PREV_SEC 6824104834Sobrien} 6825104834Sobrien 6826104834Sobrien/* Determine and set the size of the stub section for a final link. 6827104834Sobrien 6828104834Sobrien The basic idea here is to examine all the relocations looking for 6829104834Sobrien PC-relative calls to a target that is unreachable with a "bl" 6830104834Sobrien instruction. */ 6831104834Sobrien 6832130561Sobrienbfd_boolean 6833130561Sobrienppc64_elf_size_stubs (bfd *output_bfd, 6834130561Sobrien struct bfd_link_info *info, 6835130561Sobrien bfd_signed_vma group_size, 6836130561Sobrien asection *(*add_stub_section) (const char *, asection *), 6837130561Sobrien void (*layout_sections_again) (void)) 6838104834Sobrien{ 6839104834Sobrien bfd_size_type stub_group_size; 6840130561Sobrien bfd_boolean stubs_always_before_branch; 6841104834Sobrien struct ppc_link_hash_table *htab = ppc_hash_table (info); 6842104834Sobrien 6843104834Sobrien /* Stash our params away. */ 6844104834Sobrien htab->add_stub_section = add_stub_section; 6845104834Sobrien htab->layout_sections_again = layout_sections_again; 6846104834Sobrien stubs_always_before_branch = group_size < 0; 6847104834Sobrien if (group_size < 0) 6848104834Sobrien stub_group_size = -group_size; 6849104834Sobrien else 6850104834Sobrien stub_group_size = group_size; 6851104834Sobrien if (stub_group_size == 1) 6852104834Sobrien { 6853104834Sobrien /* Default values. */ 6854130561Sobrien if (stubs_always_before_branch) 6855130561Sobrien { 6856130561Sobrien stub_group_size = 0x1e00000; 6857130561Sobrien if (htab->has_14bit_branch) 6858130561Sobrien stub_group_size = 0x7800; 6859130561Sobrien } 6860130561Sobrien else 6861130561Sobrien { 6862130561Sobrien stub_group_size = 0x1c00000; 6863130561Sobrien if (htab->has_14bit_branch) 6864130561Sobrien stub_group_size = 0x7000; 6865130561Sobrien } 6866104834Sobrien } 6867104834Sobrien 6868104834Sobrien group_sections (htab, stub_group_size, stubs_always_before_branch); 6869104834Sobrien 6870104834Sobrien while (1) 6871104834Sobrien { 6872104834Sobrien bfd *input_bfd; 6873104834Sobrien unsigned int bfd_indx; 6874104834Sobrien asection *stub_sec; 6875130561Sobrien bfd_boolean stub_changed; 6876104834Sobrien 6877104834Sobrien htab->stub_iteration += 1; 6878130561Sobrien stub_changed = FALSE; 6879104834Sobrien 6880104834Sobrien for (input_bfd = info->input_bfds, bfd_indx = 0; 6881104834Sobrien input_bfd != NULL; 6882104834Sobrien input_bfd = input_bfd->link_next, bfd_indx++) 6883104834Sobrien { 6884104834Sobrien Elf_Internal_Shdr *symtab_hdr; 6885104834Sobrien asection *section; 6886104834Sobrien Elf_Internal_Sym *local_syms = NULL; 6887104834Sobrien 6888104834Sobrien /* We'll need the symbol table in a second. */ 6889104834Sobrien symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; 6890104834Sobrien if (symtab_hdr->sh_info == 0) 6891104834Sobrien continue; 6892104834Sobrien 6893104834Sobrien /* Walk over each section attached to the input bfd. */ 6894104834Sobrien for (section = input_bfd->sections; 6895104834Sobrien section != NULL; 6896104834Sobrien section = section->next) 6897104834Sobrien { 6898104834Sobrien Elf_Internal_Rela *internal_relocs, *irelaend, *irela; 6899104834Sobrien 6900104834Sobrien /* If there aren't any relocs, then there's nothing more 6901104834Sobrien to do. */ 6902104834Sobrien if ((section->flags & SEC_RELOC) == 0 6903104834Sobrien || section->reloc_count == 0) 6904104834Sobrien continue; 6905104834Sobrien 6906104834Sobrien /* If this section is a link-once section that will be 6907104834Sobrien discarded, then don't create any stubs. */ 6908104834Sobrien if (section->output_section == NULL 6909104834Sobrien || section->output_section->owner != output_bfd) 6910104834Sobrien continue; 6911104834Sobrien 6912104834Sobrien /* Get the relocs. */ 6913104834Sobrien internal_relocs 6914130561Sobrien = _bfd_elf_link_read_relocs (input_bfd, section, NULL, NULL, 6915130561Sobrien info->keep_memory); 6916104834Sobrien if (internal_relocs == NULL) 6917104834Sobrien goto error_ret_free_local; 6918104834Sobrien 6919104834Sobrien /* Now examine each relocation. */ 6920104834Sobrien irela = internal_relocs; 6921104834Sobrien irelaend = irela + section->reloc_count; 6922104834Sobrien for (; irela < irelaend; irela++) 6923104834Sobrien { 6924130561Sobrien enum elf_ppc64_reloc_type r_type; 6925130561Sobrien unsigned int r_indx; 6926104834Sobrien enum ppc_stub_type stub_type; 6927104834Sobrien struct ppc_stub_hash_entry *stub_entry; 6928104834Sobrien asection *sym_sec; 6929104834Sobrien bfd_vma sym_value; 6930104834Sobrien bfd_vma destination; 6931104834Sobrien struct ppc_link_hash_entry *hash; 6932130561Sobrien struct elf_link_hash_entry *h; 6933130561Sobrien Elf_Internal_Sym *sym; 6934104834Sobrien char *stub_name; 6935104834Sobrien const asection *id_sec; 6936104834Sobrien 6937104834Sobrien r_type = ELF64_R_TYPE (irela->r_info); 6938104834Sobrien r_indx = ELF64_R_SYM (irela->r_info); 6939104834Sobrien 6940130561Sobrien if (r_type >= R_PPC64_max) 6941104834Sobrien { 6942104834Sobrien bfd_set_error (bfd_error_bad_value); 6943104834Sobrien goto error_ret_free_internal; 6944104834Sobrien } 6945104834Sobrien 6946104834Sobrien /* Only look for stubs on branch instructions. */ 6947130561Sobrien if (r_type != R_PPC64_REL24 6948130561Sobrien && r_type != R_PPC64_REL14 6949130561Sobrien && r_type != R_PPC64_REL14_BRTAKEN 6950130561Sobrien && r_type != R_PPC64_REL14_BRNTAKEN) 6951104834Sobrien continue; 6952104834Sobrien 6953104834Sobrien /* Now determine the call target, its name, value, 6954104834Sobrien section. */ 6955104834Sobrien destination = 0; 6956130561Sobrien if (!get_sym_h (&h, &sym, &sym_sec, NULL, &local_syms, 6957130561Sobrien r_indx, input_bfd)) 6958130561Sobrien goto error_ret_free_internal; 6959130561Sobrien hash = (struct ppc_link_hash_entry *) h; 6960130561Sobrien 6961130561Sobrien if (hash == NULL) 6962104834Sobrien { 6963104834Sobrien /* It's a local symbol. */ 6964130561Sobrien sym_value = sym->st_value; 6965104834Sobrien destination = (sym_value + irela->r_addend 6966104834Sobrien + sym_sec->output_offset 6967104834Sobrien + sym_sec->output_section->vma); 6968104834Sobrien } 6969104834Sobrien else 6970104834Sobrien { 6971104834Sobrien /* It's an external symbol. */ 6972130561Sobrien sym_value = 0; 6973104834Sobrien if (hash->elf.root.type == bfd_link_hash_defined 6974104834Sobrien || hash->elf.root.type == bfd_link_hash_defweak) 6975104834Sobrien { 6976104834Sobrien sym_value = hash->elf.root.u.def.value; 6977104834Sobrien if (sym_sec->output_section != NULL) 6978104834Sobrien destination = (sym_value + irela->r_addend 6979104834Sobrien + sym_sec->output_offset 6980104834Sobrien + sym_sec->output_section->vma); 6981104834Sobrien } 6982104834Sobrien else if (hash->elf.root.type == bfd_link_hash_undefweak) 6983104834Sobrien ; 6984104834Sobrien else if (hash->elf.root.type == bfd_link_hash_undefined) 6985104834Sobrien ; 6986104834Sobrien else 6987104834Sobrien { 6988104834Sobrien bfd_set_error (bfd_error_bad_value); 6989104834Sobrien goto error_ret_free_internal; 6990104834Sobrien } 6991104834Sobrien } 6992104834Sobrien 6993104834Sobrien /* Determine what (if any) linker stub is needed. */ 6994104834Sobrien stub_type = ppc_type_of_stub (section, irela, &hash, 6995104834Sobrien destination); 6996130561Sobrien 6997130561Sobrien if (stub_type != ppc_stub_plt_call) 6998130561Sobrien { 6999130561Sobrien /* Check whether we need a TOC adjusting stub. 7000130561Sobrien Since the linker pastes together pieces from 7001130561Sobrien different object files when creating the 7002130561Sobrien _init and _fini functions, it may be that a 7003130561Sobrien call to what looks like a local sym is in 7004130561Sobrien fact a call needing a TOC adjustment. */ 7005130561Sobrien if (sym_sec != NULL 7006130561Sobrien && sym_sec->output_section != NULL 7007130561Sobrien && (htab->stub_group[sym_sec->id].toc_off 7008130561Sobrien != htab->stub_group[section->id].toc_off) 7009130561Sobrien && sym_sec->has_gp_reloc 7010130561Sobrien && section->has_gp_reloc) 7011130561Sobrien stub_type = ppc_stub_long_branch_r2off; 7012130561Sobrien } 7013130561Sobrien 7014104834Sobrien if (stub_type == ppc_stub_none) 7015104834Sobrien continue; 7016104834Sobrien 7017130561Sobrien /* __tls_get_addr calls might be eliminated. */ 7018130561Sobrien if (stub_type != ppc_stub_plt_call 7019130561Sobrien && hash != NULL 7020130561Sobrien && &hash->elf == htab->tls_get_addr 7021130561Sobrien && section->has_tls_reloc 7022130561Sobrien && irela != internal_relocs) 7023130561Sobrien { 7024130561Sobrien /* Get tls info. */ 7025130561Sobrien char *tls_mask; 7026130561Sobrien 7027130561Sobrien if (!get_tls_mask (&tls_mask, NULL, &local_syms, 7028130561Sobrien irela - 1, input_bfd)) 7029130561Sobrien goto error_ret_free_internal; 7030130561Sobrien if (*tls_mask != 0) 7031130561Sobrien continue; 7032130561Sobrien } 7033130561Sobrien 7034104834Sobrien /* Support for grouping stub sections. */ 7035104834Sobrien id_sec = htab->stub_group[section->id].link_sec; 7036104834Sobrien 7037104834Sobrien /* Get the name of this stub. */ 7038104834Sobrien stub_name = ppc_stub_name (id_sec, sym_sec, hash, irela); 7039104834Sobrien if (!stub_name) 7040104834Sobrien goto error_ret_free_internal; 7041104834Sobrien 7042104834Sobrien stub_entry = ppc_stub_hash_lookup (&htab->stub_hash_table, 7043130561Sobrien stub_name, FALSE, FALSE); 7044104834Sobrien if (stub_entry != NULL) 7045104834Sobrien { 7046104834Sobrien /* The proper stub has already been created. */ 7047104834Sobrien free (stub_name); 7048104834Sobrien continue; 7049104834Sobrien } 7050104834Sobrien 7051104834Sobrien stub_entry = ppc_add_stub (stub_name, section, htab); 7052104834Sobrien if (stub_entry == NULL) 7053104834Sobrien { 7054104834Sobrien free (stub_name); 7055104834Sobrien error_ret_free_internal: 7056104834Sobrien if (elf_section_data (section)->relocs == NULL) 7057104834Sobrien free (internal_relocs); 7058104834Sobrien error_ret_free_local: 7059104834Sobrien if (local_syms != NULL 7060104834Sobrien && (symtab_hdr->contents 7061104834Sobrien != (unsigned char *) local_syms)) 7062104834Sobrien free (local_syms); 7063130561Sobrien return FALSE; 7064104834Sobrien } 7065104834Sobrien 7066130561Sobrien stub_entry->stub_type = stub_type; 7067104834Sobrien stub_entry->target_value = sym_value; 7068104834Sobrien stub_entry->target_section = sym_sec; 7069104834Sobrien stub_entry->h = hash; 7070130561Sobrien stub_entry->addend = irela->r_addend; 7071130561Sobrien stub_changed = TRUE; 7072104834Sobrien } 7073104834Sobrien 7074104834Sobrien /* We're done with the internal relocs, free them. */ 7075104834Sobrien if (elf_section_data (section)->relocs != internal_relocs) 7076104834Sobrien free (internal_relocs); 7077104834Sobrien } 7078104834Sobrien 7079104834Sobrien if (local_syms != NULL 7080104834Sobrien && symtab_hdr->contents != (unsigned char *) local_syms) 7081104834Sobrien { 7082104834Sobrien if (!info->keep_memory) 7083104834Sobrien free (local_syms); 7084104834Sobrien else 7085104834Sobrien symtab_hdr->contents = (unsigned char *) local_syms; 7086104834Sobrien } 7087104834Sobrien } 7088104834Sobrien 7089104834Sobrien if (!stub_changed) 7090104834Sobrien break; 7091104834Sobrien 7092104834Sobrien /* OK, we've added some stubs. Find out the new size of the 7093104834Sobrien stub sections. */ 7094104834Sobrien for (stub_sec = htab->stub_bfd->sections; 7095104834Sobrien stub_sec != NULL; 7096104834Sobrien stub_sec = stub_sec->next) 7097130561Sobrien if ((stub_sec->flags & SEC_LINKER_CREATED) == 0) 7098130561Sobrien { 7099130561Sobrien stub_sec->_raw_size = 0; 7100130561Sobrien stub_sec->_cooked_size = 0; 7101130561Sobrien } 7102130561Sobrien htab->brlt->_raw_size = 0; 7103130561Sobrien htab->brlt->_cooked_size = 0; 7104130561Sobrien if (info->shared) 7105104834Sobrien { 7106130561Sobrien htab->relbrlt->_raw_size = 0; 7107130561Sobrien htab->relbrlt->_cooked_size = 0; 7108104834Sobrien } 7109104834Sobrien 7110130561Sobrien bfd_hash_traverse (&htab->stub_hash_table, ppc_size_one_stub, info); 7111104834Sobrien 7112104834Sobrien /* Ask the linker to do its stuff. */ 7113104834Sobrien (*htab->layout_sections_again) (); 7114104834Sobrien } 7115104834Sobrien 7116104834Sobrien /* It would be nice to strip .branch_lt from the output if the 7117104834Sobrien section is empty, but it's too late. If we strip sections here, 7118104834Sobrien the dynamic symbol table is corrupted since the section symbol 7119104834Sobrien for the stripped section isn't written. */ 7120104834Sobrien 7121130561Sobrien return TRUE; 712289857Sobrien} 712389857Sobrien 7124104834Sobrien/* Called after we have determined section placement. If sections 7125104834Sobrien move, we'll be called again. Provide a value for TOCstart. */ 7126104834Sobrien 7127104834Sobrienbfd_vma 7128130561Sobrienppc64_elf_toc (bfd *obfd) 7129104834Sobrien{ 7130104834Sobrien asection *s; 7131104834Sobrien bfd_vma TOCstart; 7132104834Sobrien 7133104834Sobrien /* The TOC consists of sections .got, .toc, .tocbss, .plt in that 7134104834Sobrien order. The TOC starts where the first of these sections starts. */ 7135104834Sobrien s = bfd_get_section_by_name (obfd, ".got"); 7136104834Sobrien if (s == NULL) 7137104834Sobrien s = bfd_get_section_by_name (obfd, ".toc"); 7138104834Sobrien if (s == NULL) 7139104834Sobrien s = bfd_get_section_by_name (obfd, ".tocbss"); 7140104834Sobrien if (s == NULL) 7141104834Sobrien s = bfd_get_section_by_name (obfd, ".plt"); 7142104834Sobrien if (s == NULL) 7143104834Sobrien { 7144104834Sobrien /* This may happen for 7145104834Sobrien o references to TOC base (SYM@toc / TOC[tc0]) without a 7146104834Sobrien .toc directive 7147104834Sobrien o bad linker script 7148104834Sobrien o --gc-sections and empty TOC sections 7149104834Sobrien 7150104834Sobrien FIXME: Warn user? */ 7151104834Sobrien 7152104834Sobrien /* Look for a likely section. We probably won't even be 7153104834Sobrien using TOCstart. */ 7154104834Sobrien for (s = obfd->sections; s != NULL; s = s->next) 7155104834Sobrien if ((s->flags & (SEC_ALLOC | SEC_SMALL_DATA | SEC_READONLY)) 7156104834Sobrien == (SEC_ALLOC | SEC_SMALL_DATA)) 7157104834Sobrien break; 7158104834Sobrien if (s == NULL) 7159104834Sobrien for (s = obfd->sections; s != NULL; s = s->next) 7160104834Sobrien if ((s->flags & (SEC_ALLOC | SEC_SMALL_DATA)) 7161104834Sobrien == (SEC_ALLOC | SEC_SMALL_DATA)) 7162104834Sobrien break; 7163104834Sobrien if (s == NULL) 7164104834Sobrien for (s = obfd->sections; s != NULL; s = s->next) 7165104834Sobrien if ((s->flags & (SEC_ALLOC | SEC_READONLY)) == SEC_ALLOC) 7166104834Sobrien break; 7167104834Sobrien if (s == NULL) 7168104834Sobrien for (s = obfd->sections; s != NULL; s = s->next) 7169104834Sobrien if ((s->flags & SEC_ALLOC) == SEC_ALLOC) 7170104834Sobrien break; 7171104834Sobrien } 7172104834Sobrien 7173104834Sobrien TOCstart = 0; 7174104834Sobrien if (s != NULL) 7175104834Sobrien TOCstart = s->output_section->vma + s->output_offset; 7176104834Sobrien 7177104834Sobrien return TOCstart; 7178104834Sobrien} 7179104834Sobrien 7180104834Sobrien/* Build all the stubs associated with the current output file. 7181104834Sobrien The stubs are kept in a hash table attached to the main linker 7182104834Sobrien hash table. This function is called via gldelf64ppc_finish. */ 7183104834Sobrien 7184130561Sobrienbfd_boolean 7185130561Sobrienppc64_elf_build_stubs (bfd_boolean emit_stub_syms, 7186130561Sobrien struct bfd_link_info *info, 7187130561Sobrien char **stats) 7188104834Sobrien{ 7189104834Sobrien struct ppc_link_hash_table *htab = ppc_hash_table (info); 7190104834Sobrien asection *stub_sec; 7191104834Sobrien bfd_byte *p; 7192130561Sobrien int stub_sec_count = 0; 7193104834Sobrien 7194130561Sobrien htab->emit_stub_syms = emit_stub_syms; 7195104834Sobrien for (stub_sec = htab->stub_bfd->sections; 7196104834Sobrien stub_sec != NULL; 7197104834Sobrien stub_sec = stub_sec->next) 7198130561Sobrien if ((stub_sec->flags & SEC_LINKER_CREATED) == 0) 7199130561Sobrien { 7200130561Sobrien bfd_size_type size; 7201104834Sobrien 7202130561Sobrien /* Allocate memory to hold the linker stubs. */ 7203130561Sobrien size = stub_sec->_raw_size; 7204130561Sobrien if (size != 0) 7205130561Sobrien { 7206130561Sobrien stub_sec->contents = bfd_zalloc (htab->stub_bfd, size); 7207130561Sobrien if (stub_sec->contents == NULL) 7208130561Sobrien return FALSE; 7209130561Sobrien } 7210130561Sobrien stub_sec->_cooked_size = 0; 7211130561Sobrien } 7212104834Sobrien 7213209867Snwhitehorn if (htab->glink != NULL && htab->glink->contents != NULL) 7214104834Sobrien { 7215104834Sobrien unsigned int indx; 7216130561Sobrien bfd_vma plt0; 7217104834Sobrien 7218104834Sobrien /* Build the .glink plt call stub. */ 7219130561Sobrien plt0 = (htab->plt->output_section->vma 7220130561Sobrien + htab->plt->output_offset 7221130561Sobrien - (htab->glink->output_section->vma 7222130561Sobrien + htab->glink->output_offset 7223130561Sobrien + GLINK_CALL_STUB_SIZE)); 7224130561Sobrien if (plt0 + 0x80008000 > 0xffffffff) 7225104834Sobrien { 7226130561Sobrien (*_bfd_error_handler) (_(".glink and .plt too far apart")); 7227130561Sobrien bfd_set_error (bfd_error_bad_value); 7228130561Sobrien return FALSE; 7229104834Sobrien } 7230104834Sobrien 7231130561Sobrien if (htab->emit_stub_syms) 7232130561Sobrien { 7233130561Sobrien struct elf_link_hash_entry *h; 7234130561Sobrien h = elf_link_hash_lookup (&htab->elf, "__glink", TRUE, FALSE, FALSE); 7235130561Sobrien if (h == NULL) 7236130561Sobrien return FALSE; 7237130561Sobrien if (h->root.type == bfd_link_hash_new) 7238130561Sobrien { 7239130561Sobrien h->root.type = bfd_link_hash_defined; 7240130561Sobrien h->root.u.def.section = htab->glink; 7241130561Sobrien h->root.u.def.value = 0; 7242130561Sobrien h->elf_link_hash_flags = (ELF_LINK_HASH_REF_REGULAR 7243130561Sobrien | ELF_LINK_HASH_DEF_REGULAR 7244130561Sobrien | ELF_LINK_HASH_REF_REGULAR_NONWEAK 7245130561Sobrien | ELF_LINK_FORCED_LOCAL); 7246130561Sobrien } 7247130561Sobrien } 7248130561Sobrien p = htab->glink->contents; 7249130561Sobrien bfd_put_32 (htab->glink->owner, MFCTR_R12, p); 7250130561Sobrien p += 4; 7251130561Sobrien bfd_put_32 (htab->glink->owner, SLDI_R11_R0_3, p); 7252130561Sobrien p += 4; 7253130561Sobrien bfd_put_32 (htab->glink->owner, ADDIC_R2_R0_32K, p); 7254130561Sobrien p += 4; 7255130561Sobrien bfd_put_32 (htab->glink->owner, SUB_R12_R12_R11, p); 7256130561Sobrien p += 4; 7257130561Sobrien bfd_put_32 (htab->glink->owner, SRADI_R2_R2_63, p); 7258130561Sobrien p += 4; 7259130561Sobrien bfd_put_32 (htab->glink->owner, SLDI_R11_R0_2, p); 7260130561Sobrien p += 4; 7261130561Sobrien bfd_put_32 (htab->glink->owner, AND_R2_R2_R11, p); 7262130561Sobrien p += 4; 7263130561Sobrien bfd_put_32 (htab->glink->owner, SUB_R12_R12_R11, p); 7264130561Sobrien p += 4; 7265130561Sobrien bfd_put_32 (htab->glink->owner, ADD_R12_R12_R2, p); 7266130561Sobrien p += 4; 7267130561Sobrien bfd_put_32 (htab->glink->owner, ADDIS_R12_R12 | PPC_HA (plt0), p); 7268130561Sobrien p += 4; 7269130561Sobrien bfd_put_32 (htab->glink->owner, LD_R11_0R12 | PPC_LO (plt0), p); 7270130561Sobrien p += 4; 7271130561Sobrien bfd_put_32 (htab->glink->owner, ADDI_R12_R12 | PPC_LO (plt0), p); 7272130561Sobrien p += 4; 7273130561Sobrien bfd_put_32 (htab->glink->owner, LD_R2_0R12 | 8, p); 7274130561Sobrien p += 4; 7275130561Sobrien bfd_put_32 (htab->glink->owner, MTCTR_R11, p); 7276130561Sobrien p += 4; 7277130561Sobrien bfd_put_32 (htab->glink->owner, LD_R11_0R12 | 16, p); 7278130561Sobrien p += 4; 7279130561Sobrien bfd_put_32 (htab->glink->owner, BCTR, p); 7280130561Sobrien p += 4; 7281130561Sobrien 7282104834Sobrien /* Build the .glink lazy link call stubs. */ 7283104834Sobrien indx = 0; 7284130561Sobrien while (p < htab->glink->contents + htab->glink->_raw_size) 7285104834Sobrien { 7286104834Sobrien if (indx < 0x8000) 7287104834Sobrien { 7288130561Sobrien bfd_put_32 (htab->glink->owner, LI_R0_0 | indx, p); 7289104834Sobrien p += 4; 7290104834Sobrien } 7291104834Sobrien else 7292104834Sobrien { 7293130561Sobrien bfd_put_32 (htab->glink->owner, LIS_R0_0 | PPC_HI (indx), p); 7294104834Sobrien p += 4; 7295130561Sobrien bfd_put_32 (htab->glink->owner, ORI_R0_R0_0 | PPC_LO (indx), p); 7296104834Sobrien p += 4; 7297104834Sobrien } 7298130561Sobrien bfd_put_32 (htab->glink->owner, 7299130561Sobrien B_DOT | ((htab->glink->contents - p) & 0x3fffffc), p); 7300104834Sobrien indx++; 7301104834Sobrien p += 4; 7302104834Sobrien } 7303130561Sobrien htab->glink->_cooked_size = p - htab->glink->contents; 7304104834Sobrien } 7305104834Sobrien 7306130561Sobrien if (htab->brlt->_raw_size != 0) 7307104834Sobrien { 7308130561Sobrien htab->brlt->contents = bfd_zalloc (htab->brlt->owner, 7309130561Sobrien htab->brlt->_raw_size); 7310130561Sobrien if (htab->brlt->contents == NULL) 7311130561Sobrien return FALSE; 7312104834Sobrien } 7313130561Sobrien if (info->shared && htab->relbrlt->_raw_size != 0) 7314130561Sobrien { 7315130561Sobrien htab->relbrlt->contents = bfd_zalloc (htab->relbrlt->owner, 7316130561Sobrien htab->relbrlt->_raw_size); 7317130561Sobrien if (htab->relbrlt->contents == NULL) 7318130561Sobrien return FALSE; 7319130561Sobrien } 7320104834Sobrien 7321104834Sobrien /* Build the stubs as directed by the stub hash table. */ 7322104834Sobrien bfd_hash_traverse (&htab->stub_hash_table, ppc_build_one_stub, info); 7323104834Sobrien 7324104834Sobrien for (stub_sec = htab->stub_bfd->sections; 7325104834Sobrien stub_sec != NULL; 7326104834Sobrien stub_sec = stub_sec->next) 7327130561Sobrien if ((stub_sec->flags & SEC_LINKER_CREATED) == 0) 7328130561Sobrien { 7329130561Sobrien stub_sec_count += 1; 7330130561Sobrien if (stub_sec->_raw_size != stub_sec->_cooked_size) 7331130561Sobrien break; 7332130561Sobrien } 7333104834Sobrien 7334104834Sobrien if (stub_sec != NULL 7335130561Sobrien || htab->glink->_raw_size != htab->glink->_cooked_size) 7336104834Sobrien { 7337130561Sobrien htab->stub_error = TRUE; 7338104834Sobrien (*_bfd_error_handler) (_("stubs don't match calculated size")); 7339104834Sobrien } 7340104834Sobrien 7341130561Sobrien if (htab->stub_error) 7342130561Sobrien return FALSE; 7343130561Sobrien 7344130561Sobrien if (stats != NULL) 7345130561Sobrien { 7346130561Sobrien *stats = bfd_malloc (500); 7347130561Sobrien if (*stats == NULL) 7348130561Sobrien return FALSE; 7349130561Sobrien 7350130561Sobrien sprintf (*stats, _("linker stubs in %u groups\n" 7351130561Sobrien " branch %lu\n" 7352130561Sobrien " toc adjust %lu\n" 7353130561Sobrien " long branch %lu\n" 7354130561Sobrien " long toc adj %lu\n" 7355130561Sobrien " plt call %lu"), 7356130561Sobrien stub_sec_count, 7357130561Sobrien htab->stub_count[ppc_stub_long_branch - 1], 7358130561Sobrien htab->stub_count[ppc_stub_long_branch_r2off - 1], 7359130561Sobrien htab->stub_count[ppc_stub_plt_branch - 1], 7360130561Sobrien htab->stub_count[ppc_stub_plt_branch_r2off - 1], 7361130561Sobrien htab->stub_count[ppc_stub_plt_call - 1]); 7362130561Sobrien } 7363130561Sobrien return TRUE; 7364104834Sobrien} 7365104834Sobrien 736689857Sobrien/* The RELOCATE_SECTION function is called by the ELF backend linker 736789857Sobrien to handle the relocations for a section. 736889857Sobrien 736989857Sobrien The relocs are always passed as Rela structures; if the section 737089857Sobrien actually uses Rel structures, the r_addend field will always be 737189857Sobrien zero. 737289857Sobrien 737389857Sobrien This function is responsible for adjust the section contents as 737489857Sobrien necessary, and (if using Rela relocs and generating a 7375130561Sobrien relocatable output file) adjusting the reloc addend as 737689857Sobrien necessary. 737789857Sobrien 737889857Sobrien This function does not have to worry about setting the reloc 737989857Sobrien address or the reloc symbol index. 738089857Sobrien 738189857Sobrien LOCAL_SYMS is a pointer to the swapped in local symbols. 738289857Sobrien 738389857Sobrien LOCAL_SECTIONS is an array giving the section in the input file 738489857Sobrien corresponding to the st_shndx field of each local symbol. 738589857Sobrien 738689857Sobrien The global hash table entry for the global symbols can be found 738789857Sobrien via elf_sym_hashes (input_bfd). 738889857Sobrien 7389130561Sobrien When generating relocatable output, this function must handle 739089857Sobrien STB_LOCAL/STT_SECTION symbols specially. The output symbol is 739189857Sobrien going to be the section symbol corresponding to the output 739289857Sobrien section, which means that the addend must be adjusted 739389857Sobrien accordingly. */ 739489857Sobrien 7395130561Sobrienstatic bfd_boolean 7396130561Sobrienppc64_elf_relocate_section (bfd *output_bfd, 7397130561Sobrien struct bfd_link_info *info, 7398130561Sobrien bfd *input_bfd, 7399130561Sobrien asection *input_section, 7400130561Sobrien bfd_byte *contents, 7401130561Sobrien Elf_Internal_Rela *relocs, 7402130561Sobrien Elf_Internal_Sym *local_syms, 7403130561Sobrien asection **local_sections) 740489857Sobrien{ 740589857Sobrien struct ppc_link_hash_table *htab; 740689857Sobrien Elf_Internal_Shdr *symtab_hdr; 740789857Sobrien struct elf_link_hash_entry **sym_hashes; 740889857Sobrien Elf_Internal_Rela *rel; 740989857Sobrien Elf_Internal_Rela *relend; 7410130561Sobrien Elf_Internal_Rela outrel; 7411130561Sobrien bfd_byte *loc; 7412130561Sobrien struct got_entry **local_got_ents; 741389857Sobrien bfd_vma TOCstart; 7414130561Sobrien bfd_boolean ret = TRUE; 7415130561Sobrien bfd_boolean is_opd; 741692828Sobrien /* Disabled until we sort out how ld should choose 'y' vs 'at'. */ 7417130561Sobrien bfd_boolean is_power4 = FALSE; 741889857Sobrien 7419130561Sobrien if (info->relocatable) 7420130561Sobrien return TRUE; 742199461Sobrien 742289857Sobrien /* Initialize howto table if needed. */ 742389857Sobrien if (!ppc64_elf_howto_table[R_PPC64_ADDR32]) 742489857Sobrien ppc_howto_init (); 742589857Sobrien 742689857Sobrien htab = ppc_hash_table (info); 7427130561Sobrien local_got_ents = elf_local_got_ents (input_bfd); 742889857Sobrien TOCstart = elf_gp (output_bfd); 742989857Sobrien symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; 743089857Sobrien sym_hashes = elf_sym_hashes (input_bfd); 7431130561Sobrien is_opd = ppc64_elf_section_data (input_section)->opd.adjust != NULL; 743289857Sobrien 743389857Sobrien rel = relocs; 743489857Sobrien relend = relocs + input_section->reloc_count; 743589857Sobrien for (; rel < relend; rel++) 743689857Sobrien { 7437130561Sobrien enum elf_ppc64_reloc_type r_type; 743889857Sobrien bfd_vma addend; 743989857Sobrien bfd_reloc_status_type r; 744089857Sobrien Elf_Internal_Sym *sym; 744189857Sobrien asection *sec; 744289857Sobrien struct elf_link_hash_entry *h; 7443104834Sobrien struct elf_link_hash_entry *fdh; 744489857Sobrien const char *sym_name; 7445130561Sobrien unsigned long r_symndx, toc_symndx; 7446130561Sobrien char tls_mask, tls_gd, tls_type; 7447130561Sobrien char sym_type; 744889857Sobrien bfd_vma relocation; 7449130561Sobrien bfd_boolean unresolved_reloc; 7450130561Sobrien bfd_boolean warned; 7451130561Sobrien unsigned long insn, mask; 7452104834Sobrien struct ppc_stub_hash_entry *stub_entry; 7453104834Sobrien bfd_vma max_br_offset; 745499461Sobrien bfd_vma from; 745589857Sobrien 7456130561Sobrien r_type = ELF64_R_TYPE (rel->r_info); 745789857Sobrien r_symndx = ELF64_R_SYM (rel->r_info); 745889857Sobrien 7459130561Sobrien /* For old style R_PPC64_TOC relocs with a zero symbol, use the 7460130561Sobrien symbol of the previous ADDR64 reloc. The symbol gives us the 7461130561Sobrien proper TOC base to use. */ 7462130561Sobrien if (rel->r_info == ELF64_R_INFO (0, R_PPC64_TOC) 7463130561Sobrien && rel != relocs 7464130561Sobrien && ELF64_R_TYPE (rel[-1].r_info) == R_PPC64_ADDR64 7465130561Sobrien && is_opd) 7466130561Sobrien r_symndx = ELF64_R_SYM (rel[-1].r_info); 7467130561Sobrien 7468130561Sobrien sym = NULL; 7469130561Sobrien sec = NULL; 7470130561Sobrien h = NULL; 7471130561Sobrien sym_name = NULL; 7472130561Sobrien unresolved_reloc = FALSE; 7473130561Sobrien warned = FALSE; 7474130561Sobrien 7475130561Sobrien if (r_symndx < symtab_hdr->sh_info) 747689857Sobrien { 747789857Sobrien /* It's a local symbol. */ 747889857Sobrien sym = local_syms + r_symndx; 747989857Sobrien sec = local_sections[r_symndx]; 7480130561Sobrien sym_name = bfd_elf_local_sym_name (input_bfd, sym); 7481130561Sobrien sym_type = ELF64_ST_TYPE (sym->st_info); 7482130561Sobrien relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel); 7483104834Sobrien if (elf_section_data (sec) != NULL) 7484104834Sobrien { 7485104834Sobrien long *opd_sym_adjust; 7486104834Sobrien 7487130561Sobrien opd_sym_adjust = ppc64_elf_section_data (sec)->opd.adjust; 7488130561Sobrien if (opd_sym_adjust != NULL) 7489104834Sobrien relocation += opd_sym_adjust[sym->st_value / 24]; 7490104834Sobrien } 749189857Sobrien } 749289857Sobrien else 749389857Sobrien { 7494130561Sobrien RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, 7495130561Sobrien r_symndx, symtab_hdr, sym_hashes, 7496130561Sobrien h, sec, relocation, 7497130561Sobrien unresolved_reloc, warned); 749889857Sobrien sym_name = h->root.root.string; 7499130561Sobrien sym_type = h->type; 7500130561Sobrien } 7501130561Sobrien 7502130561Sobrien /* TLS optimizations. Replace instruction sequences and relocs 7503130561Sobrien based on information we collected in tls_optimize. We edit 7504130561Sobrien RELOCS so that --emit-relocs will output something sensible 7505130561Sobrien for the final instruction stream. */ 7506130561Sobrien tls_mask = 0; 7507130561Sobrien tls_gd = 0; 7508130561Sobrien toc_symndx = 0; 7509130561Sobrien if (IS_PPC64_TLS_RELOC (r_type)) 7510130561Sobrien { 7511130561Sobrien if (h != NULL) 7512130561Sobrien tls_mask = ((struct ppc_link_hash_entry *) h)->tls_mask; 7513130561Sobrien else if (local_got_ents != NULL) 7514130561Sobrien { 7515130561Sobrien char *lgot_masks; 7516130561Sobrien lgot_masks = (char *) (local_got_ents + symtab_hdr->sh_info); 7517130561Sobrien tls_mask = lgot_masks[r_symndx]; 7518130561Sobrien } 7519130561Sobrien if (tls_mask == 0 && r_type == R_PPC64_TLS) 7520130561Sobrien { 7521130561Sobrien /* Check for toc tls entries. */ 7522130561Sobrien char *toc_tls; 7523130561Sobrien 7524130561Sobrien if (!get_tls_mask (&toc_tls, &toc_symndx, &local_syms, 7525130561Sobrien rel, input_bfd)) 7526130561Sobrien return FALSE; 7527130561Sobrien 7528130561Sobrien if (toc_tls) 7529130561Sobrien tls_mask = *toc_tls; 7530130561Sobrien } 7531130561Sobrien } 7532130561Sobrien 7533130561Sobrien /* Check that tls relocs are used with tls syms, and non-tls 7534130561Sobrien relocs are used with non-tls syms. */ 7535130561Sobrien if (r_symndx != 0 7536130561Sobrien && r_type != R_PPC64_NONE 7537130561Sobrien && (h == NULL 7538130561Sobrien || h->root.type == bfd_link_hash_defined 753989857Sobrien || h->root.type == bfd_link_hash_defweak) 7540130561Sobrien && IS_PPC64_TLS_RELOC (r_type) != (sym_type == STT_TLS)) 7541130561Sobrien { 7542130561Sobrien if (r_type == R_PPC64_TLS && tls_mask != 0) 7543130561Sobrien /* R_PPC64_TLS is OK against a symbol in the TOC. */ 7544130561Sobrien ; 7545130561Sobrien else 7546130561Sobrien (*_bfd_error_handler) 7547130561Sobrien (sym_type == STT_TLS 7548130561Sobrien ? _("%s(%s+0x%lx): %s used with TLS symbol %s") 7549130561Sobrien : _("%s(%s+0x%lx): %s used with non-TLS symbol %s"), 7550130561Sobrien bfd_archive_filename (input_bfd), 7551130561Sobrien input_section->name, 7552130561Sobrien (long) rel->r_offset, 7553130561Sobrien ppc64_elf_howto_table[r_type]->name, 7554130561Sobrien sym_name); 7555130561Sobrien } 7556130561Sobrien 7557130561Sobrien /* Ensure reloc mapping code below stays sane. */ 7558130561Sobrien if (R_PPC64_TOC16_LO_DS != R_PPC64_TOC16_DS + 1 7559130561Sobrien || R_PPC64_TOC16_LO != R_PPC64_TOC16 + 1 7560130561Sobrien || (R_PPC64_GOT_TLSLD16 & 3) != (R_PPC64_GOT_TLSGD16 & 3) 7561130561Sobrien || (R_PPC64_GOT_TLSLD16_LO & 3) != (R_PPC64_GOT_TLSGD16_LO & 3) 7562130561Sobrien || (R_PPC64_GOT_TLSLD16_HI & 3) != (R_PPC64_GOT_TLSGD16_HI & 3) 7563130561Sobrien || (R_PPC64_GOT_TLSLD16_HA & 3) != (R_PPC64_GOT_TLSGD16_HA & 3) 7564130561Sobrien || (R_PPC64_GOT_TLSLD16 & 3) != (R_PPC64_GOT_TPREL16_DS & 3) 7565130561Sobrien || (R_PPC64_GOT_TLSLD16_LO & 3) != (R_PPC64_GOT_TPREL16_LO_DS & 3) 7566130561Sobrien || (R_PPC64_GOT_TLSLD16_HI & 3) != (R_PPC64_GOT_TPREL16_HI & 3) 7567130561Sobrien || (R_PPC64_GOT_TLSLD16_HA & 3) != (R_PPC64_GOT_TPREL16_HA & 3)) 7568130561Sobrien abort (); 7569130561Sobrien 7570130561Sobrien switch (r_type) 7571130561Sobrien { 7572130561Sobrien default: 7573130561Sobrien break; 7574130561Sobrien 7575130561Sobrien case R_PPC64_TOC16: 7576130561Sobrien case R_PPC64_TOC16_LO: 7577130561Sobrien case R_PPC64_TOC16_DS: 7578130561Sobrien case R_PPC64_TOC16_LO_DS: 7579130561Sobrien { 7580130561Sobrien /* Check for toc tls entries. */ 7581130561Sobrien char *toc_tls; 7582130561Sobrien int retval; 7583130561Sobrien 7584130561Sobrien retval = get_tls_mask (&toc_tls, &toc_symndx, &local_syms, 7585130561Sobrien rel, input_bfd); 7586130561Sobrien if (retval == 0) 7587130561Sobrien return FALSE; 7588130561Sobrien 7589130561Sobrien if (toc_tls) 7590130561Sobrien { 7591130561Sobrien tls_mask = *toc_tls; 7592130561Sobrien if (r_type == R_PPC64_TOC16_DS 7593130561Sobrien || r_type == R_PPC64_TOC16_LO_DS) 7594130561Sobrien { 7595130561Sobrien if (tls_mask != 0 7596130561Sobrien && (tls_mask & (TLS_DTPREL | TLS_TPREL)) == 0) 7597130561Sobrien goto toctprel; 7598130561Sobrien } 7599130561Sobrien else 7600130561Sobrien { 7601130561Sobrien /* If we found a GD reloc pair, then we might be 7602130561Sobrien doing a GD->IE transition. */ 7603130561Sobrien if (retval == 2) 7604130561Sobrien { 7605130561Sobrien tls_gd = TLS_TPRELGD; 7606130561Sobrien if (tls_mask != 0 && (tls_mask & TLS_GD) == 0) 7607130561Sobrien goto tls_get_addr_check; 7608130561Sobrien } 7609130561Sobrien else if (retval == 3) 7610130561Sobrien { 7611130561Sobrien if (tls_mask != 0 && (tls_mask & TLS_LD) == 0) 7612130561Sobrien goto tls_get_addr_check; 7613130561Sobrien } 7614130561Sobrien } 7615130561Sobrien } 7616130561Sobrien } 7617130561Sobrien break; 7618130561Sobrien 7619130561Sobrien case R_PPC64_GOT_TPREL16_DS: 7620130561Sobrien case R_PPC64_GOT_TPREL16_LO_DS: 7621130561Sobrien if (tls_mask != 0 7622130561Sobrien && (tls_mask & TLS_TPREL) == 0) 762389857Sobrien { 7624130561Sobrien toctprel: 7625130561Sobrien insn = bfd_get_32 (output_bfd, contents + rel->r_offset - 2); 7626130561Sobrien insn &= 31 << 21; 7627130561Sobrien insn |= 0x3c0d0000; /* addis 0,13,0 */ 7628130561Sobrien bfd_put_32 (output_bfd, insn, contents + rel->r_offset - 2); 7629130561Sobrien r_type = R_PPC64_TPREL16_HA; 7630130561Sobrien if (toc_symndx != 0) 7631130561Sobrien { 7632130561Sobrien rel->r_info = ELF64_R_INFO (toc_symndx, r_type); 7633130561Sobrien /* We changed the symbol. Start over in order to 7634130561Sobrien get h, sym, sec etc. right. */ 7635130561Sobrien rel--; 7636130561Sobrien continue; 7637130561Sobrien } 763889857Sobrien else 7639130561Sobrien rel->r_info = ELF64_R_INFO (r_symndx, r_type); 764089857Sobrien } 7641130561Sobrien break; 7642130561Sobrien 7643130561Sobrien case R_PPC64_TLS: 7644130561Sobrien if (tls_mask != 0 7645130561Sobrien && (tls_mask & TLS_TPREL) == 0) 7646130561Sobrien { 7647130561Sobrien bfd_vma rtra; 7648130561Sobrien insn = bfd_get_32 (output_bfd, contents + rel->r_offset); 7649130561Sobrien if ((insn & ((0x3f << 26) | (31 << 11))) 7650130561Sobrien == ((31 << 26) | (13 << 11))) 7651130561Sobrien rtra = insn & ((1 << 26) - (1 << 16)); 7652130561Sobrien else if ((insn & ((0x3f << 26) | (31 << 16))) 7653130561Sobrien == ((31 << 26) | (13 << 16))) 7654130561Sobrien rtra = (insn & (31 << 21)) | ((insn & (31 << 11)) << 5); 7655130561Sobrien else 7656130561Sobrien abort (); 7657130561Sobrien if ((insn & ((1 << 11) - (1 << 1))) == 266 << 1) 7658130561Sobrien /* add -> addi. */ 7659130561Sobrien insn = 14 << 26; 7660130561Sobrien else if ((insn & (31 << 1)) == 23 << 1 7661130561Sobrien && ((insn & (31 << 6)) < 14 << 6 7662130561Sobrien || ((insn & (31 << 6)) >= 16 << 6 7663130561Sobrien && (insn & (31 << 6)) < 24 << 6))) 7664130561Sobrien /* load and store indexed -> dform. */ 7665130561Sobrien insn = (32 | ((insn >> 6) & 31)) << 26; 7666130561Sobrien else if ((insn & (31 << 1)) == 21 << 1 7667130561Sobrien && (insn & (0x1a << 6)) == 0) 7668130561Sobrien /* ldx, ldux, stdx, stdux -> ld, ldu, std, stdu. */ 7669130561Sobrien insn = (((58 | ((insn >> 6) & 4)) << 26) 7670130561Sobrien | ((insn >> 6) & 1)); 7671130561Sobrien else if ((insn & (31 << 1)) == 21 << 1 7672130561Sobrien && (insn & ((1 << 11) - (1 << 1))) == 341 << 1) 7673130561Sobrien /* lwax -> lwa. */ 7674130561Sobrien insn = (58 << 26) | 2; 7675130561Sobrien else 7676130561Sobrien abort (); 7677130561Sobrien insn |= rtra; 7678130561Sobrien bfd_put_32 (output_bfd, insn, contents + rel->r_offset); 7679130561Sobrien /* Was PPC64_TLS which sits on insn boundary, now 7680130561Sobrien PPC64_TPREL16_LO which is at insn+2. */ 7681130561Sobrien rel->r_offset += 2; 7682130561Sobrien r_type = R_PPC64_TPREL16_LO; 7683130561Sobrien if (toc_symndx != 0) 7684130561Sobrien { 7685130561Sobrien rel->r_info = ELF64_R_INFO (toc_symndx, r_type); 7686130561Sobrien /* We changed the symbol. Start over in order to 7687130561Sobrien get h, sym, sec etc. right. */ 7688130561Sobrien rel--; 7689130561Sobrien continue; 7690130561Sobrien } 7691130561Sobrien else 7692130561Sobrien rel->r_info = ELF64_R_INFO (r_symndx, r_type); 7693130561Sobrien } 7694130561Sobrien break; 7695130561Sobrien 7696130561Sobrien case R_PPC64_GOT_TLSGD16_HI: 7697130561Sobrien case R_PPC64_GOT_TLSGD16_HA: 7698130561Sobrien tls_gd = TLS_TPRELGD; 7699130561Sobrien if (tls_mask != 0 && (tls_mask & TLS_GD) == 0) 7700130561Sobrien goto tls_gdld_hi; 7701130561Sobrien break; 7702130561Sobrien 7703130561Sobrien case R_PPC64_GOT_TLSLD16_HI: 7704130561Sobrien case R_PPC64_GOT_TLSLD16_HA: 7705130561Sobrien if (tls_mask != 0 && (tls_mask & TLS_LD) == 0) 7706130561Sobrien { 7707130561Sobrien tls_gdld_hi: 7708130561Sobrien if ((tls_mask & tls_gd) != 0) 7709130561Sobrien r_type = (((r_type - (R_PPC64_GOT_TLSGD16 & 3)) & 3) 7710130561Sobrien + R_PPC64_GOT_TPREL16_DS); 7711130561Sobrien else 7712130561Sobrien { 7713130561Sobrien bfd_put_32 (output_bfd, NOP, contents + rel->r_offset); 7714130561Sobrien rel->r_offset -= 2; 7715130561Sobrien r_type = R_PPC64_NONE; 7716130561Sobrien } 7717130561Sobrien rel->r_info = ELF64_R_INFO (r_symndx, r_type); 7718130561Sobrien } 7719130561Sobrien break; 7720130561Sobrien 7721130561Sobrien case R_PPC64_GOT_TLSGD16: 7722130561Sobrien case R_PPC64_GOT_TLSGD16_LO: 7723130561Sobrien tls_gd = TLS_TPRELGD; 7724130561Sobrien if (tls_mask != 0 && (tls_mask & TLS_GD) == 0) 7725130561Sobrien goto tls_get_addr_check; 7726130561Sobrien break; 7727130561Sobrien 7728130561Sobrien case R_PPC64_GOT_TLSLD16: 7729130561Sobrien case R_PPC64_GOT_TLSLD16_LO: 7730130561Sobrien if (tls_mask != 0 && (tls_mask & TLS_LD) == 0) 7731130561Sobrien { 7732130561Sobrien tls_get_addr_check: 7733130561Sobrien if (rel + 1 < relend) 7734130561Sobrien { 7735130561Sobrien enum elf_ppc64_reloc_type r_type2; 7736130561Sobrien unsigned long r_symndx2; 7737130561Sobrien struct elf_link_hash_entry *h2; 7738130561Sobrien bfd_vma insn1, insn2, insn3; 7739130561Sobrien bfd_vma offset; 7740130561Sobrien 7741130561Sobrien /* The next instruction should be a call to 7742130561Sobrien __tls_get_addr. Peek at the reloc to be sure. */ 7743130561Sobrien r_type2 = ELF64_R_TYPE (rel[1].r_info); 7744130561Sobrien r_symndx2 = ELF64_R_SYM (rel[1].r_info); 7745130561Sobrien if (r_symndx2 < symtab_hdr->sh_info 7746130561Sobrien || (r_type2 != R_PPC64_REL14 7747130561Sobrien && r_type2 != R_PPC64_REL14_BRTAKEN 7748130561Sobrien && r_type2 != R_PPC64_REL14_BRNTAKEN 7749130561Sobrien && r_type2 != R_PPC64_REL24)) 7750130561Sobrien break; 7751130561Sobrien 7752130561Sobrien h2 = sym_hashes[r_symndx2 - symtab_hdr->sh_info]; 7753130561Sobrien while (h2->root.type == bfd_link_hash_indirect 7754130561Sobrien || h2->root.type == bfd_link_hash_warning) 7755130561Sobrien h2 = (struct elf_link_hash_entry *) h2->root.u.i.link; 7756130561Sobrien if (h2 == NULL || h2 != htab->tls_get_addr) 7757130561Sobrien break; 7758130561Sobrien 7759130561Sobrien /* OK, it checks out. Replace the call. */ 7760130561Sobrien offset = rel[1].r_offset; 7761130561Sobrien insn1 = bfd_get_32 (output_bfd, 7762130561Sobrien contents + rel->r_offset - 2); 7763130561Sobrien insn3 = bfd_get_32 (output_bfd, 7764130561Sobrien contents + offset + 4); 7765130561Sobrien if ((tls_mask & tls_gd) != 0) 7766130561Sobrien { 7767130561Sobrien /* IE */ 7768130561Sobrien insn1 &= (1 << 26) - (1 << 2); 7769130561Sobrien insn1 |= 58 << 26; /* ld */ 7770130561Sobrien insn2 = 0x7c636a14; /* add 3,3,13 */ 7771130561Sobrien rel[1].r_info = ELF64_R_INFO (r_symndx2, R_PPC64_NONE); 7772130561Sobrien if ((tls_mask & TLS_EXPLICIT) == 0) 7773130561Sobrien r_type = (((r_type - (R_PPC64_GOT_TLSGD16 & 3)) & 3) 7774130561Sobrien + R_PPC64_GOT_TPREL16_DS); 7775130561Sobrien else 7776130561Sobrien r_type += R_PPC64_TOC16_DS - R_PPC64_TOC16; 7777130561Sobrien rel->r_info = ELF64_R_INFO (r_symndx, r_type); 7778130561Sobrien } 7779130561Sobrien else 7780130561Sobrien { 7781130561Sobrien /* LE */ 7782130561Sobrien insn1 = 0x3c6d0000; /* addis 3,13,0 */ 7783130561Sobrien insn2 = 0x38630000; /* addi 3,3,0 */ 7784130561Sobrien if (tls_gd == 0) 7785130561Sobrien { 7786130561Sobrien /* Was an LD reloc. */ 7787130561Sobrien r_symndx = 0; 7788130561Sobrien rel->r_addend = htab->elf.tls_sec->vma + DTP_OFFSET; 7789130561Sobrien rel[1].r_addend = htab->elf.tls_sec->vma + DTP_OFFSET; 7790130561Sobrien } 7791130561Sobrien else if (toc_symndx != 0) 7792130561Sobrien r_symndx = toc_symndx; 7793130561Sobrien r_type = R_PPC64_TPREL16_HA; 7794130561Sobrien rel->r_info = ELF64_R_INFO (r_symndx, r_type); 7795130561Sobrien rel[1].r_info = ELF64_R_INFO (r_symndx, 7796130561Sobrien R_PPC64_TPREL16_LO); 7797130561Sobrien rel[1].r_offset += 2; 7798130561Sobrien } 7799130561Sobrien if (insn3 == NOP 7800130561Sobrien || insn3 == CROR_151515 || insn3 == CROR_313131) 7801130561Sobrien { 7802130561Sobrien insn3 = insn2; 7803130561Sobrien insn2 = NOP; 7804130561Sobrien rel[1].r_offset += 4; 7805130561Sobrien } 7806130561Sobrien bfd_put_32 (output_bfd, insn1, contents + rel->r_offset - 2); 7807130561Sobrien bfd_put_32 (output_bfd, insn2, contents + offset); 7808130561Sobrien bfd_put_32 (output_bfd, insn3, contents + offset + 4); 7809130561Sobrien if (tls_gd == 0 || toc_symndx != 0) 7810130561Sobrien { 7811130561Sobrien /* We changed the symbol. Start over in order 7812130561Sobrien to get h, sym, sec etc. right. */ 7813130561Sobrien rel--; 7814130561Sobrien continue; 7815130561Sobrien } 7816130561Sobrien } 7817130561Sobrien } 7818130561Sobrien break; 7819130561Sobrien 7820130561Sobrien case R_PPC64_DTPMOD64: 7821130561Sobrien if (rel + 1 < relend 7822130561Sobrien && rel[1].r_info == ELF64_R_INFO (r_symndx, R_PPC64_DTPREL64) 7823130561Sobrien && rel[1].r_offset == rel->r_offset + 8) 7824130561Sobrien { 7825130561Sobrien if ((tls_mask & TLS_GD) == 0) 7826130561Sobrien { 7827130561Sobrien rel[1].r_info = ELF64_R_INFO (r_symndx, R_PPC64_NONE); 7828130561Sobrien if ((tls_mask & TLS_TPRELGD) != 0) 7829130561Sobrien r_type = R_PPC64_TPREL64; 7830130561Sobrien else 7831130561Sobrien { 7832130561Sobrien bfd_put_64 (output_bfd, 1, contents + rel->r_offset); 7833130561Sobrien r_type = R_PPC64_NONE; 7834130561Sobrien } 7835130561Sobrien rel->r_info = ELF64_R_INFO (r_symndx, r_type); 7836130561Sobrien } 7837130561Sobrien } 783889857Sobrien else 783989857Sobrien { 7840130561Sobrien if ((tls_mask & TLS_LD) == 0) 7841130561Sobrien { 7842130561Sobrien bfd_put_64 (output_bfd, 1, contents + rel->r_offset); 7843130561Sobrien r_type = R_PPC64_NONE; 7844130561Sobrien rel->r_info = ELF64_R_INFO (r_symndx, r_type); 7845130561Sobrien } 784689857Sobrien } 7847130561Sobrien break; 7848130561Sobrien 7849130561Sobrien case R_PPC64_TPREL64: 7850130561Sobrien if ((tls_mask & TLS_TPREL) == 0) 7851130561Sobrien { 7852130561Sobrien r_type = R_PPC64_NONE; 7853130561Sobrien rel->r_info = ELF64_R_INFO (r_symndx, r_type); 7854130561Sobrien } 7855130561Sobrien break; 785689857Sobrien } 785789857Sobrien 7858130561Sobrien /* Handle other relocations that tweak non-addend part of insn. */ 785989857Sobrien insn = 0; 786089857Sobrien switch (r_type) 786189857Sobrien { 786289857Sobrien default: 786389857Sobrien break; 786489857Sobrien 786589857Sobrien /* Branch taken prediction relocations. */ 786689857Sobrien case R_PPC64_ADDR14_BRTAKEN: 786789857Sobrien case R_PPC64_REL14_BRTAKEN: 7868104834Sobrien insn = 0x01 << 21; /* 'y' or 't' bit, lowest bit of BO field. */ 7869104834Sobrien /* Fall thru. */ 787089857Sobrien 787189857Sobrien /* Branch not taken prediction relocations. */ 787289857Sobrien case R_PPC64_ADDR14_BRNTAKEN: 787389857Sobrien case R_PPC64_REL14_BRNTAKEN: 7874130561Sobrien insn |= bfd_get_32 (output_bfd, 7875130561Sobrien contents + rel->r_offset) & ~(0x01 << 21); 787692828Sobrien if (is_power4) 787792828Sobrien { 787892828Sobrien /* Set 'a' bit. This is 0b00010 in BO field for branch 787992828Sobrien on CR(BI) insns (BO == 001at or 011at), and 0b01000 788092828Sobrien for branch on CTR insns (BO == 1a00t or 1a01t). */ 788192828Sobrien if ((insn & (0x14 << 21)) == (0x04 << 21)) 788292828Sobrien insn |= 0x02 << 21; 788392828Sobrien else if ((insn & (0x14 << 21)) == (0x10 << 21)) 788492828Sobrien insn |= 0x08 << 21; 788592828Sobrien else 788692828Sobrien break; 788792828Sobrien } 788889857Sobrien else 788992828Sobrien { 7890130561Sobrien from = (rel->r_offset 789199461Sobrien + input_section->output_offset 789299461Sobrien + input_section->output_section->vma); 789399461Sobrien 789492828Sobrien /* Invert 'y' bit if not the default. */ 7895130561Sobrien if ((bfd_signed_vma) (relocation + rel->r_addend - from) < 0) 789692828Sobrien insn ^= 0x01 << 21; 789792828Sobrien } 789889857Sobrien 7899130561Sobrien bfd_put_32 (output_bfd, insn, contents + rel->r_offset); 790089857Sobrien break; 790189857Sobrien 790289857Sobrien case R_PPC64_REL24: 7903130561Sobrien /* Calls to functions with a different TOC, such as calls to 7904130561Sobrien shared objects, need to alter the TOC pointer. This is 7905130561Sobrien done using a linkage stub. A REL24 branching to these 7906130561Sobrien linkage stubs needs to be followed by a nop, as the nop 7907130561Sobrien will be replaced with an instruction to restore the TOC 7908130561Sobrien base pointer. */ 7909130561Sobrien if (((h != NULL 7910130561Sobrien && (fdh = ((struct ppc_link_hash_entry *) h)->oh) != NULL 7911130561Sobrien && fdh->plt.plist != NULL) 7912130561Sobrien || ((fdh = h, sec) != NULL 7913130561Sobrien && sec->output_section != NULL 7914130561Sobrien && (htab->stub_group[sec->id].toc_off 7915130561Sobrien != htab->stub_group[input_section->id].toc_off))) 7916104834Sobrien && (stub_entry = ppc_get_stub_entry (input_section, sec, fdh, 7917130561Sobrien rel, htab)) != NULL 7918130561Sobrien && (stub_entry->stub_type == ppc_stub_plt_call 7919130561Sobrien || stub_entry->stub_type == ppc_stub_plt_branch_r2off 7920130561Sobrien || stub_entry->stub_type == ppc_stub_long_branch_r2off)) 792189857Sobrien { 7922130561Sobrien bfd_boolean can_plt_call = 0; 792389857Sobrien 7924130561Sobrien if (rel->r_offset + 8 <= input_section->_cooked_size) 792589857Sobrien { 7926130561Sobrien insn = bfd_get_32 (input_bfd, contents + rel->r_offset + 4); 792799461Sobrien if (insn == NOP 792899461Sobrien || insn == CROR_151515 || insn == CROR_313131) 792989857Sobrien { 7930130561Sobrien bfd_put_32 (input_bfd, LD_R2_40R1, 7931130561Sobrien contents + rel->r_offset + 4); 793299461Sobrien can_plt_call = 1; 793389857Sobrien } 793489857Sobrien } 793599461Sobrien 793699461Sobrien if (!can_plt_call) 793799461Sobrien { 7938130561Sobrien if (stub_entry->stub_type == ppc_stub_plt_call) 7939130561Sobrien { 7940130561Sobrien /* If this is a plain branch rather than a branch 7941130561Sobrien and link, don't require a nop. */ 7942130561Sobrien insn = bfd_get_32 (input_bfd, contents + rel->r_offset); 7943130561Sobrien if ((insn & 1) == 0) 7944130561Sobrien can_plt_call = 1; 7945130561Sobrien } 7946130561Sobrien else if (h != NULL 7947130561Sobrien && strcmp (h->root.root.string, 7948130561Sobrien ".__libc_start_main") == 0) 7949130561Sobrien { 7950130561Sobrien /* Allow crt1 branch to go via a toc adjusting stub. */ 7951130561Sobrien can_plt_call = 1; 7952130561Sobrien } 7953130561Sobrien else 7954130561Sobrien { 7955130561Sobrien if (strcmp (input_section->output_section->name, 7956130561Sobrien ".init") == 0 7957130561Sobrien || strcmp (input_section->output_section->name, 7958130561Sobrien ".fini") == 0) 7959130561Sobrien (*_bfd_error_handler) 7960130561Sobrien (_("%s(%s+0x%lx): automatic multiple TOCs " 7961130561Sobrien "not supported using your crt files; " 7962130561Sobrien "recompile with -mminimal-toc or upgrade gcc"), 7963130561Sobrien bfd_archive_filename (input_bfd), 7964130561Sobrien input_section->name, 7965130561Sobrien (long) rel->r_offset); 7966130561Sobrien else 7967130561Sobrien (*_bfd_error_handler) 7968130561Sobrien (_("%s(%s+0x%lx): sibling call optimization to `%s' " 7969130561Sobrien "does not allow automatic multiple TOCs; " 7970130561Sobrien "recompile with -mminimal-toc or " 7971130561Sobrien "-fno-optimize-sibling-calls, " 7972130561Sobrien "or make `%s' extern"), 7973130561Sobrien bfd_archive_filename (input_bfd), 7974130561Sobrien input_section->name, 7975130561Sobrien (long) rel->r_offset, 7976130561Sobrien sym_name, 7977130561Sobrien sym_name); 7978130561Sobrien bfd_set_error (bfd_error_bad_value); 7979130561Sobrien ret = FALSE; 7980130561Sobrien } 798199461Sobrien } 798299461Sobrien 798399461Sobrien if (can_plt_call) 798499461Sobrien { 7985104834Sobrien relocation = (stub_entry->stub_offset 7986104834Sobrien + stub_entry->stub_sec->output_offset 7987104834Sobrien + stub_entry->stub_sec->output_section->vma); 7988130561Sobrien if (stub_entry->stub_type == ppc_stub_plt_call) 7989130561Sobrien unresolved_reloc = FALSE; 799099461Sobrien } 799189857Sobrien } 799289857Sobrien 799389857Sobrien if (h != NULL 799489857Sobrien && h->root.type == bfd_link_hash_undefweak 799599461Sobrien && relocation == 0 7996130561Sobrien && rel->r_addend == 0) 799789857Sobrien { 799899461Sobrien /* Tweak calls to undefined weak functions to point at a 799999461Sobrien blr. We can thus call a weak function without first 800099461Sobrien checking whether the function is defined. We have a 800199461Sobrien blr at the end of .sfpr. */ 800299461Sobrien BFD_ASSERT (htab->sfpr->_raw_size != 0); 800399461Sobrien relocation = (htab->sfpr->_raw_size - 4 800499461Sobrien + htab->sfpr->output_offset 800599461Sobrien + htab->sfpr->output_section->vma); 8006130561Sobrien from = (rel->r_offset 800799461Sobrien + input_section->output_offset 800899461Sobrien + input_section->output_section->vma); 800999461Sobrien 801099461Sobrien /* But let's not be silly about it. If the blr isn't in 801199461Sobrien reach, just go to the next instruction. */ 801299461Sobrien if (relocation - from + (1 << 25) >= (1 << 26) 801399461Sobrien || htab->sfpr->_raw_size == 0) 801499461Sobrien relocation = from + 4; 801589857Sobrien } 801689857Sobrien break; 801789857Sobrien } 801889857Sobrien 801989857Sobrien /* Set `addend'. */ 8020130561Sobrien tls_type = 0; 8021130561Sobrien addend = rel->r_addend; 802289857Sobrien switch (r_type) 802389857Sobrien { 802489857Sobrien default: 802589857Sobrien (*_bfd_error_handler) 802689857Sobrien (_("%s: unknown relocation type %d for symbol %s"), 802789857Sobrien bfd_archive_filename (input_bfd), (int) r_type, sym_name); 802889857Sobrien 802989857Sobrien bfd_set_error (bfd_error_bad_value); 8030130561Sobrien ret = FALSE; 803189857Sobrien continue; 803289857Sobrien 803389857Sobrien case R_PPC64_NONE: 8034130561Sobrien case R_PPC64_TLS: 8035130561Sobrien case R_PPC64_GNU_VTINHERIT: 8036130561Sobrien case R_PPC64_GNU_VTENTRY: 803789857Sobrien continue; 803889857Sobrien 803989857Sobrien /* GOT16 relocations. Like an ADDR16 using the symbol's 804089857Sobrien address in the GOT as relocation value instead of the 8041130561Sobrien symbol's value itself. Also, create a GOT entry for the 804289857Sobrien symbol and put the symbol value there. */ 8043130561Sobrien case R_PPC64_GOT_TLSGD16: 8044130561Sobrien case R_PPC64_GOT_TLSGD16_LO: 8045130561Sobrien case R_PPC64_GOT_TLSGD16_HI: 8046130561Sobrien case R_PPC64_GOT_TLSGD16_HA: 8047130561Sobrien tls_type = TLS_TLS | TLS_GD; 8048130561Sobrien goto dogot; 8049130561Sobrien 8050130561Sobrien case R_PPC64_GOT_TLSLD16: 8051130561Sobrien case R_PPC64_GOT_TLSLD16_LO: 8052130561Sobrien case R_PPC64_GOT_TLSLD16_HI: 8053130561Sobrien case R_PPC64_GOT_TLSLD16_HA: 8054130561Sobrien tls_type = TLS_TLS | TLS_LD; 8055130561Sobrien goto dogot; 8056130561Sobrien 8057130561Sobrien case R_PPC64_GOT_TPREL16_DS: 8058130561Sobrien case R_PPC64_GOT_TPREL16_LO_DS: 8059130561Sobrien case R_PPC64_GOT_TPREL16_HI: 8060130561Sobrien case R_PPC64_GOT_TPREL16_HA: 8061130561Sobrien tls_type = TLS_TLS | TLS_TPREL; 8062130561Sobrien goto dogot; 8063130561Sobrien 8064130561Sobrien case R_PPC64_GOT_DTPREL16_DS: 8065130561Sobrien case R_PPC64_GOT_DTPREL16_LO_DS: 8066130561Sobrien case R_PPC64_GOT_DTPREL16_HI: 8067130561Sobrien case R_PPC64_GOT_DTPREL16_HA: 8068130561Sobrien tls_type = TLS_TLS | TLS_DTPREL; 8069130561Sobrien goto dogot; 8070130561Sobrien 807189857Sobrien case R_PPC64_GOT16: 807289857Sobrien case R_PPC64_GOT16_LO: 807389857Sobrien case R_PPC64_GOT16_HI: 807489857Sobrien case R_PPC64_GOT16_HA: 807589857Sobrien case R_PPC64_GOT16_DS: 807689857Sobrien case R_PPC64_GOT16_LO_DS: 8077130561Sobrien dogot: 807889857Sobrien { 807989857Sobrien /* Relocation is to the entry for this symbol in the global 808089857Sobrien offset table. */ 8081130561Sobrien asection *got; 8082130561Sobrien bfd_vma *offp; 808389857Sobrien bfd_vma off; 8084130561Sobrien unsigned long indx = 0; 808589857Sobrien 8086130561Sobrien if (tls_type == (TLS_TLS | TLS_LD) 8087130561Sobrien && (h == NULL 8088130561Sobrien || !(h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC))) 8089130561Sobrien offp = &ppc64_tlsld_got (input_bfd)->offset; 8090130561Sobrien else 809189857Sobrien { 8092130561Sobrien struct got_entry *ent; 809389857Sobrien 8094130561Sobrien if (h != NULL) 809589857Sobrien { 8096130561Sobrien bfd_boolean dyn = htab->elf.dynamic_sections_created; 8097130561Sobrien if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h) 8098130561Sobrien || (info->shared 8099130561Sobrien && SYMBOL_REFERENCES_LOCAL (info, h))) 8100130561Sobrien /* This is actually a static link, or it is a 8101130561Sobrien -Bsymbolic link and the symbol is defined 8102130561Sobrien locally, or the symbol was forced to be local 8103130561Sobrien because of a version file. */ 8104130561Sobrien ; 810589857Sobrien else 810689857Sobrien { 8107130561Sobrien indx = h->dynindx; 8108130561Sobrien unresolved_reloc = FALSE; 810989857Sobrien } 8110130561Sobrien ent = h->got.glist; 811189857Sobrien } 811289857Sobrien else 8113130561Sobrien { 8114130561Sobrien if (local_got_ents == NULL) 8115130561Sobrien abort (); 8116130561Sobrien ent = local_got_ents[r_symndx]; 8117130561Sobrien } 8118130561Sobrien 8119130561Sobrien for (; ent != NULL; ent = ent->next) 8120130561Sobrien if (ent->addend == rel->r_addend 8121130561Sobrien && ent->owner == input_bfd 8122130561Sobrien && ent->tls_type == tls_type) 8123130561Sobrien break; 8124130561Sobrien if (ent == NULL) 8125130561Sobrien abort (); 8126130561Sobrien offp = &ent->got.offset; 812789857Sobrien } 8128130561Sobrien 8129130561Sobrien got = ppc64_elf_tdata (input_bfd)->got; 8130130561Sobrien if (got == NULL) 8131130561Sobrien abort (); 8132130561Sobrien 8133130561Sobrien /* The offset must always be a multiple of 8. We use the 8134130561Sobrien least significant bit to record whether we have already 8135130561Sobrien processed this entry. */ 8136130561Sobrien off = *offp; 8137130561Sobrien if ((off & 1) != 0) 8138130561Sobrien off &= ~1; 813989857Sobrien else 814089857Sobrien { 8141130561Sobrien /* Generate relocs for the dynamic linker, except in 8142130561Sobrien the case of TLSLD where we'll use one entry per 8143130561Sobrien module. */ 8144130561Sobrien asection *relgot = ppc64_elf_tdata (input_bfd)->relgot; 814589857Sobrien 8146130561Sobrien *offp = off | 1; 8147130561Sobrien if ((info->shared || indx != 0) 8148130561Sobrien && (h == NULL 8149130561Sobrien || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT 8150130561Sobrien || h->root.type != bfd_link_hash_undefweak)) 8151130561Sobrien { 8152130561Sobrien outrel.r_offset = (got->output_section->vma 8153130561Sobrien + got->output_offset 8154130561Sobrien + off); 8155130561Sobrien outrel.r_addend = rel->r_addend; 8156130561Sobrien if (tls_type & (TLS_LD | TLS_GD)) 8157130561Sobrien { 8158130561Sobrien outrel.r_addend = 0; 8159130561Sobrien outrel.r_info = ELF64_R_INFO (indx, R_PPC64_DTPMOD64); 8160130561Sobrien if (tls_type == (TLS_TLS | TLS_GD)) 8161130561Sobrien { 8162130561Sobrien loc = relgot->contents; 8163130561Sobrien loc += (relgot->reloc_count++ 8164130561Sobrien * sizeof (Elf64_External_Rela)); 8165130561Sobrien bfd_elf64_swap_reloca_out (output_bfd, 8166130561Sobrien &outrel, loc); 8167130561Sobrien outrel.r_offset += 8; 8168130561Sobrien outrel.r_addend = rel->r_addend; 8169130561Sobrien outrel.r_info 8170130561Sobrien = ELF64_R_INFO (indx, R_PPC64_DTPREL64); 8171130561Sobrien } 8172130561Sobrien } 8173130561Sobrien else if (tls_type == (TLS_TLS | TLS_DTPREL)) 8174130561Sobrien outrel.r_info = ELF64_R_INFO (indx, R_PPC64_DTPREL64); 8175130561Sobrien else if (tls_type == (TLS_TLS | TLS_TPREL)) 8176130561Sobrien outrel.r_info = ELF64_R_INFO (indx, R_PPC64_TPREL64); 8177130561Sobrien else if (indx == 0) 8178130561Sobrien { 8179130561Sobrien outrel.r_info = ELF64_R_INFO (indx, R_PPC64_RELATIVE); 818089857Sobrien 8181130561Sobrien /* Write the .got section contents for the sake 8182130561Sobrien of prelink. */ 8183130561Sobrien loc = got->contents + off; 8184130561Sobrien bfd_put_64 (output_bfd, outrel.r_addend + relocation, 8185130561Sobrien loc); 8186130561Sobrien } 8187130561Sobrien else 8188130561Sobrien outrel.r_info = ELF64_R_INFO (indx, R_PPC64_GLOB_DAT); 8189130561Sobrien 8190130561Sobrien if (indx == 0 && tls_type != (TLS_TLS | TLS_LD)) 8191130561Sobrien { 8192130561Sobrien outrel.r_addend += relocation; 8193130561Sobrien if (tls_type & (TLS_GD | TLS_DTPREL | TLS_TPREL)) 8194130561Sobrien outrel.r_addend -= htab->elf.tls_sec->vma; 8195130561Sobrien } 8196130561Sobrien loc = relgot->contents; 8197130561Sobrien loc += (relgot->reloc_count++ 8198130561Sobrien * sizeof (Elf64_External_Rela)); 8199130561Sobrien bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc); 8200130561Sobrien } 8201130561Sobrien 8202130561Sobrien /* Init the .got section contents here if we're not 8203130561Sobrien emitting a reloc. */ 820489857Sobrien else 820589857Sobrien { 8206130561Sobrien relocation += rel->r_addend; 8207130561Sobrien if (tls_type == (TLS_TLS | TLS_LD)) 8208130561Sobrien relocation = 1; 8209130561Sobrien else if (tls_type != 0) 821089857Sobrien { 8211130561Sobrien relocation -= htab->elf.tls_sec->vma + DTP_OFFSET; 8212130561Sobrien if (tls_type == (TLS_TLS | TLS_TPREL)) 8213130561Sobrien relocation += DTP_OFFSET - TP_OFFSET; 821489857Sobrien 8215130561Sobrien if (tls_type == (TLS_TLS | TLS_GD)) 8216130561Sobrien { 8217130561Sobrien bfd_put_64 (output_bfd, relocation, 8218130561Sobrien got->contents + off + 8); 8219130561Sobrien relocation = 1; 8220130561Sobrien } 822189857Sobrien } 822289857Sobrien 8223130561Sobrien bfd_put_64 (output_bfd, relocation, 8224130561Sobrien got->contents + off); 822589857Sobrien } 822689857Sobrien } 822789857Sobrien 822889857Sobrien if (off >= (bfd_vma) -2) 822989857Sobrien abort (); 823089857Sobrien 8231130561Sobrien relocation = got->output_offset + off; 823289857Sobrien 823389857Sobrien /* TOC base (r2) is TOC start plus 0x8000. */ 8234130561Sobrien addend = -TOC_BASE_OFF; 823589857Sobrien } 823689857Sobrien break; 823789857Sobrien 823889857Sobrien case R_PPC64_PLT16_HA: 823989857Sobrien case R_PPC64_PLT16_HI: 824089857Sobrien case R_PPC64_PLT16_LO: 824189857Sobrien case R_PPC64_PLT32: 824289857Sobrien case R_PPC64_PLT64: 824389857Sobrien /* Relocation is to the entry for this symbol in the 824489857Sobrien procedure linkage table. */ 824589857Sobrien 824689857Sobrien /* Resolve a PLT reloc against a local symbol directly, 824789857Sobrien without using the procedure linkage table. */ 824889857Sobrien if (h == NULL) 824989857Sobrien break; 825089857Sobrien 8251130561Sobrien /* It's possible that we didn't make a PLT entry for this 8252130561Sobrien symbol. This happens when statically linking PIC code, 8253130561Sobrien or when using -Bsymbolic. Go find a match if there is a 8254130561Sobrien PLT entry. */ 8255130561Sobrien if (htab->plt != NULL) 825689857Sobrien { 8257130561Sobrien struct plt_entry *ent; 8258130561Sobrien for (ent = h->plt.plist; ent != NULL; ent = ent->next) 8259130561Sobrien if (ent->addend == rel->r_addend 8260130561Sobrien && ent->plt.offset != (bfd_vma) -1) 8261130561Sobrien { 8262130561Sobrien relocation = (htab->plt->output_section->vma 8263130561Sobrien + htab->plt->output_offset 8264130561Sobrien + ent->plt.offset); 8265130561Sobrien unresolved_reloc = FALSE; 8266130561Sobrien } 826789857Sobrien } 826889857Sobrien break; 826989857Sobrien 8270130561Sobrien case R_PPC64_TOC: 8271130561Sobrien /* Relocation value is TOC base. */ 8272130561Sobrien relocation = TOCstart; 8273130561Sobrien if (r_symndx == 0) 8274130561Sobrien relocation += htab->stub_group[input_section->id].toc_off; 8275130561Sobrien else if (unresolved_reloc) 8276130561Sobrien ; 8277130561Sobrien else if (sec != NULL && sec->id <= htab->top_id) 8278130561Sobrien relocation += htab->stub_group[sec->id].toc_off; 8279130561Sobrien else 8280130561Sobrien unresolved_reloc = TRUE; 8281130561Sobrien goto dodyn2; 8282130561Sobrien 828389857Sobrien /* TOC16 relocs. We want the offset relative to the TOC base, 828489857Sobrien which is the address of the start of the TOC plus 0x8000. 828589857Sobrien The TOC consists of sections .got, .toc, .tocbss, and .plt, 828689857Sobrien in this order. */ 828789857Sobrien case R_PPC64_TOC16: 828889857Sobrien case R_PPC64_TOC16_LO: 828989857Sobrien case R_PPC64_TOC16_HI: 829089857Sobrien case R_PPC64_TOC16_DS: 829189857Sobrien case R_PPC64_TOC16_LO_DS: 829289857Sobrien case R_PPC64_TOC16_HA: 8293130561Sobrien addend -= TOCstart + htab->stub_group[input_section->id].toc_off; 829489857Sobrien break; 829589857Sobrien 829689857Sobrien /* Relocate against the beginning of the section. */ 829789857Sobrien case R_PPC64_SECTOFF: 829889857Sobrien case R_PPC64_SECTOFF_LO: 829989857Sobrien case R_PPC64_SECTOFF_HI: 830089857Sobrien case R_PPC64_SECTOFF_DS: 830189857Sobrien case R_PPC64_SECTOFF_LO_DS: 830289857Sobrien case R_PPC64_SECTOFF_HA: 8303130561Sobrien if (sec != NULL) 830489857Sobrien addend -= sec->output_section->vma; 830589857Sobrien break; 830689857Sobrien 8307104834Sobrien case R_PPC64_REL14: 8308104834Sobrien case R_PPC64_REL14_BRNTAKEN: 8309104834Sobrien case R_PPC64_REL14_BRTAKEN: 831089857Sobrien case R_PPC64_REL24: 831189857Sobrien break; 831289857Sobrien 8313130561Sobrien case R_PPC64_TPREL16: 8314130561Sobrien case R_PPC64_TPREL16_LO: 8315130561Sobrien case R_PPC64_TPREL16_HI: 8316130561Sobrien case R_PPC64_TPREL16_HA: 8317130561Sobrien case R_PPC64_TPREL16_DS: 8318130561Sobrien case R_PPC64_TPREL16_LO_DS: 8319130561Sobrien case R_PPC64_TPREL16_HIGHER: 8320130561Sobrien case R_PPC64_TPREL16_HIGHERA: 8321130561Sobrien case R_PPC64_TPREL16_HIGHEST: 8322130561Sobrien case R_PPC64_TPREL16_HIGHESTA: 8323130561Sobrien addend -= htab->elf.tls_sec->vma + TP_OFFSET; 8324130561Sobrien if (info->shared) 8325130561Sobrien /* The TPREL16 relocs shouldn't really be used in shared 8326130561Sobrien libs as they will result in DT_TEXTREL being set, but 8327130561Sobrien support them anyway. */ 8328130561Sobrien goto dodyn; 8329130561Sobrien break; 8330130561Sobrien 8331130561Sobrien case R_PPC64_DTPREL16: 8332130561Sobrien case R_PPC64_DTPREL16_LO: 8333130561Sobrien case R_PPC64_DTPREL16_HI: 8334130561Sobrien case R_PPC64_DTPREL16_HA: 8335130561Sobrien case R_PPC64_DTPREL16_DS: 8336130561Sobrien case R_PPC64_DTPREL16_LO_DS: 8337130561Sobrien case R_PPC64_DTPREL16_HIGHER: 8338130561Sobrien case R_PPC64_DTPREL16_HIGHERA: 8339130561Sobrien case R_PPC64_DTPREL16_HIGHEST: 8340130561Sobrien case R_PPC64_DTPREL16_HIGHESTA: 8341130561Sobrien addend -= htab->elf.tls_sec->vma + DTP_OFFSET; 8342130561Sobrien break; 8343130561Sobrien 8344130561Sobrien case R_PPC64_DTPMOD64: 8345130561Sobrien relocation = 1; 8346130561Sobrien addend = 0; 8347130561Sobrien goto dodyn; 8348130561Sobrien 8349130561Sobrien case R_PPC64_TPREL64: 8350130561Sobrien addend -= htab->elf.tls_sec->vma + TP_OFFSET; 8351130561Sobrien goto dodyn; 8352130561Sobrien 8353130561Sobrien case R_PPC64_DTPREL64: 8354130561Sobrien addend -= htab->elf.tls_sec->vma + DTP_OFFSET; 8355130561Sobrien /* Fall thru */ 8356130561Sobrien 835789857Sobrien /* Relocations that may need to be propagated if this is a 835889857Sobrien dynamic object. */ 8359130561Sobrien case R_PPC64_REL30: 836089857Sobrien case R_PPC64_REL32: 836189857Sobrien case R_PPC64_REL64: 836289857Sobrien case R_PPC64_ADDR14: 836389857Sobrien case R_PPC64_ADDR14_BRNTAKEN: 836489857Sobrien case R_PPC64_ADDR14_BRTAKEN: 836589857Sobrien case R_PPC64_ADDR16: 836689857Sobrien case R_PPC64_ADDR16_DS: 836789857Sobrien case R_PPC64_ADDR16_HA: 836889857Sobrien case R_PPC64_ADDR16_HI: 836989857Sobrien case R_PPC64_ADDR16_HIGHER: 837089857Sobrien case R_PPC64_ADDR16_HIGHERA: 837189857Sobrien case R_PPC64_ADDR16_HIGHEST: 837289857Sobrien case R_PPC64_ADDR16_HIGHESTA: 837389857Sobrien case R_PPC64_ADDR16_LO: 837489857Sobrien case R_PPC64_ADDR16_LO_DS: 837589857Sobrien case R_PPC64_ADDR24: 837689857Sobrien case R_PPC64_ADDR32: 837789857Sobrien case R_PPC64_ADDR64: 837889857Sobrien case R_PPC64_UADDR16: 837989857Sobrien case R_PPC64_UADDR32: 838089857Sobrien case R_PPC64_UADDR64: 838189857Sobrien /* r_symndx will be zero only for relocs against symbols 838289857Sobrien from removed linkonce sections, or sections discarded by 838389857Sobrien a linker script. */ 8384130561Sobrien dodyn: 838589857Sobrien if (r_symndx == 0) 838689857Sobrien break; 838789857Sobrien /* Fall thru. */ 838889857Sobrien 8389130561Sobrien dodyn2: 839089857Sobrien if ((input_section->flags & SEC_ALLOC) == 0) 839189857Sobrien break; 839289857Sobrien 839389857Sobrien if (NO_OPD_RELOCS && is_opd) 839489857Sobrien break; 839589857Sobrien 839689857Sobrien if ((info->shared 8397130561Sobrien && (h == NULL 8398130561Sobrien || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT 8399130561Sobrien || h->root.type != bfd_link_hash_undefweak) 8400130561Sobrien && (MUST_BE_DYN_RELOC (r_type) 8401130561Sobrien || !SYMBOL_CALLS_LOCAL (info, h))) 8402130561Sobrien || (ELIMINATE_COPY_RELOCS 8403130561Sobrien && !info->shared 840489857Sobrien && h != NULL 840589857Sobrien && h->dynindx != -1 840689857Sobrien && (h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0 8407130561Sobrien && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0 8408130561Sobrien && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)) 840989857Sobrien { 841089857Sobrien Elf_Internal_Rela outrel; 8411130561Sobrien bfd_boolean skip, relocate; 841289857Sobrien asection *sreloc; 8413130561Sobrien bfd_byte *loc; 8414130561Sobrien bfd_vma out_off; 841589857Sobrien 841689857Sobrien /* When generating a dynamic object, these relocations 841789857Sobrien are copied into the output file to be resolved at run 841889857Sobrien time. */ 841989857Sobrien 8420130561Sobrien skip = FALSE; 8421130561Sobrien relocate = FALSE; 842289857Sobrien 8423130561Sobrien out_off = _bfd_elf_section_offset (output_bfd, info, 8424130561Sobrien input_section, rel->r_offset); 8425130561Sobrien if (out_off == (bfd_vma) -1) 8426130561Sobrien skip = TRUE; 8427130561Sobrien else if (out_off == (bfd_vma) -2) 8428130561Sobrien skip = TRUE, relocate = TRUE; 8429130561Sobrien out_off += (input_section->output_section->vma 8430130561Sobrien + input_section->output_offset); 8431130561Sobrien outrel.r_offset = out_off; 8432130561Sobrien outrel.r_addend = rel->r_addend; 843389857Sobrien 8434130561Sobrien /* Optimize unaligned reloc use. */ 8435130561Sobrien if ((r_type == R_PPC64_ADDR64 && (out_off & 7) != 0) 8436130561Sobrien || (r_type == R_PPC64_UADDR64 && (out_off & 7) == 0)) 8437130561Sobrien r_type ^= R_PPC64_ADDR64 ^ R_PPC64_UADDR64; 8438130561Sobrien else if ((r_type == R_PPC64_ADDR32 && (out_off & 3) != 0) 8439130561Sobrien || (r_type == R_PPC64_UADDR32 && (out_off & 3) == 0)) 8440130561Sobrien r_type ^= R_PPC64_ADDR32 ^ R_PPC64_UADDR32; 8441130561Sobrien else if ((r_type == R_PPC64_ADDR16 && (out_off & 1) != 0) 8442130561Sobrien || (r_type == R_PPC64_UADDR16 && (out_off & 1) == 0)) 8443130561Sobrien r_type ^= R_PPC64_ADDR16 ^ R_PPC64_UADDR16; 8444130561Sobrien 844589857Sobrien if (skip) 844691041Sobrien memset (&outrel, 0, sizeof outrel); 8447130561Sobrien else if (!SYMBOL_REFERENCES_LOCAL (info, h) 844889857Sobrien && !is_opd 8449130561Sobrien && r_type != R_PPC64_TOC) 845091041Sobrien outrel.r_info = ELF64_R_INFO (h->dynindx, r_type); 845189857Sobrien else 845289857Sobrien { 845389857Sobrien /* This symbol is local, or marked to become local, 845489857Sobrien or this is an opd section reloc which must point 845589857Sobrien at a local function. */ 845689857Sobrien outrel.r_addend += relocation; 845789857Sobrien if (r_type == R_PPC64_ADDR64 || r_type == R_PPC64_TOC) 845889857Sobrien { 8459104834Sobrien if (is_opd && h != NULL) 8460104834Sobrien { 8461104834Sobrien /* Lie about opd entries. This case occurs 8462104834Sobrien when building shared libraries and we 8463104834Sobrien reference a function in another shared 8464104834Sobrien lib. The same thing happens for a weak 8465104834Sobrien definition in an application that's 8466104834Sobrien overridden by a strong definition in a 8467104834Sobrien shared lib. (I believe this is a generic 8468104834Sobrien bug in binutils handling of weak syms.) 8469104834Sobrien In these cases we won't use the opd 8470104834Sobrien entry in this lib. */ 8471130561Sobrien unresolved_reloc = FALSE; 8472104834Sobrien } 847389857Sobrien outrel.r_info = ELF64_R_INFO (0, R_PPC64_RELATIVE); 8474130561Sobrien 8475130561Sobrien /* We need to relocate .opd contents for ld.so. 8476130561Sobrien Prelink also wants simple and consistent rules 8477130561Sobrien for relocs. This make all RELATIVE relocs have 8478130561Sobrien *r_offset equal to r_addend. */ 8479130561Sobrien relocate = TRUE; 848089857Sobrien } 848189857Sobrien else 848289857Sobrien { 848389857Sobrien long indx = 0; 848489857Sobrien 848589857Sobrien if (bfd_is_abs_section (sec)) 848689857Sobrien ; 848789857Sobrien else if (sec == NULL || sec->owner == NULL) 848889857Sobrien { 848989857Sobrien bfd_set_error (bfd_error_bad_value); 8490130561Sobrien return FALSE; 849189857Sobrien } 849289857Sobrien else 849389857Sobrien { 849489857Sobrien asection *osec; 849589857Sobrien 849689857Sobrien osec = sec->output_section; 849789857Sobrien indx = elf_section_data (osec)->dynindx; 849889857Sobrien 849989857Sobrien /* We are turning this relocation into one 850089857Sobrien against a section symbol, so subtract out 850189857Sobrien the output section's address but not the 850289857Sobrien offset of the input section in the output 850389857Sobrien section. */ 850489857Sobrien outrel.r_addend -= osec->vma; 850589857Sobrien } 850689857Sobrien 850789857Sobrien outrel.r_info = ELF64_R_INFO (indx, r_type); 850889857Sobrien } 850989857Sobrien } 851089857Sobrien 851189857Sobrien sreloc = elf_section_data (input_section)->sreloc; 851289857Sobrien if (sreloc == NULL) 851389857Sobrien abort (); 851489857Sobrien 8515130561Sobrien loc = sreloc->contents; 8516130561Sobrien loc += sreloc->reloc_count++ * sizeof (Elf64_External_Rela); 851789857Sobrien bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc); 851889857Sobrien 851989857Sobrien /* If this reloc is against an external symbol, it will 852089857Sobrien be computed at runtime, so there's no need to do 8521130561Sobrien anything now. However, for the sake of prelink ensure 8522130561Sobrien that the section contents are a known value. */ 852389857Sobrien if (! relocate) 8524130561Sobrien { 8525130561Sobrien unresolved_reloc = FALSE; 8526130561Sobrien /* The value chosen here is quite arbitrary as ld.so 8527130561Sobrien ignores section contents except for the special 8528130561Sobrien case of .opd where the contents might be accessed 8529130561Sobrien before relocation. Choose zero, as that won't 8530130561Sobrien cause reloc overflow. */ 8531130561Sobrien relocation = 0; 8532130561Sobrien addend = 0; 8533130561Sobrien /* Use *r_offset == r_addend for R_PPC64_ADDR64 relocs 8534130561Sobrien to improve backward compatibility with older 8535130561Sobrien versions of ld. */ 8536130561Sobrien if (r_type == R_PPC64_ADDR64) 8537130561Sobrien addend = outrel.r_addend; 8538130561Sobrien /* Adjust pc_relative relocs to have zero in *r_offset. */ 8539130561Sobrien else if (ppc64_elf_howto_table[r_type]->pc_relative) 8540130561Sobrien addend = (input_section->output_section->vma 8541130561Sobrien + input_section->output_offset 8542130561Sobrien + rel->r_offset); 8543130561Sobrien } 854489857Sobrien } 854589857Sobrien break; 854689857Sobrien 854789857Sobrien case R_PPC64_COPY: 854889857Sobrien case R_PPC64_GLOB_DAT: 854989857Sobrien case R_PPC64_JMP_SLOT: 855089857Sobrien case R_PPC64_RELATIVE: 855189857Sobrien /* We shouldn't ever see these dynamic relocs in relocatable 855289857Sobrien files. */ 8553130561Sobrien /* Fall through. */ 855489857Sobrien 855589857Sobrien case R_PPC64_PLTGOT16: 855689857Sobrien case R_PPC64_PLTGOT16_DS: 855789857Sobrien case R_PPC64_PLTGOT16_HA: 855889857Sobrien case R_PPC64_PLTGOT16_HI: 855989857Sobrien case R_PPC64_PLTGOT16_LO: 856089857Sobrien case R_PPC64_PLTGOT16_LO_DS: 856189857Sobrien case R_PPC64_PLTREL32: 856289857Sobrien case R_PPC64_PLTREL64: 856389857Sobrien /* These ones haven't been implemented yet. */ 856489857Sobrien 856589857Sobrien (*_bfd_error_handler) 8566130561Sobrien (_("%s: relocation %s is not supported for symbol %s."), 856789857Sobrien bfd_archive_filename (input_bfd), 8568130561Sobrien ppc64_elf_howto_table[r_type]->name, sym_name); 856989857Sobrien 857089857Sobrien bfd_set_error (bfd_error_invalid_operation); 8571130561Sobrien ret = FALSE; 857289857Sobrien continue; 857389857Sobrien } 857489857Sobrien 857589857Sobrien /* Do any further special processing. */ 857689857Sobrien switch (r_type) 857789857Sobrien { 857889857Sobrien default: 857989857Sobrien break; 858089857Sobrien 858189857Sobrien case R_PPC64_ADDR16_HA: 858289857Sobrien case R_PPC64_ADDR16_HIGHERA: 858389857Sobrien case R_PPC64_ADDR16_HIGHESTA: 8584130561Sobrien case R_PPC64_GOT16_HA: 8585130561Sobrien case R_PPC64_PLTGOT16_HA: 858689857Sobrien case R_PPC64_PLT16_HA: 858789857Sobrien case R_PPC64_TOC16_HA: 858889857Sobrien case R_PPC64_SECTOFF_HA: 8589130561Sobrien case R_PPC64_TPREL16_HA: 8590130561Sobrien case R_PPC64_DTPREL16_HA: 8591130561Sobrien case R_PPC64_GOT_TLSGD16_HA: 8592130561Sobrien case R_PPC64_GOT_TLSLD16_HA: 8593130561Sobrien case R_PPC64_GOT_TPREL16_HA: 8594130561Sobrien case R_PPC64_GOT_DTPREL16_HA: 8595130561Sobrien case R_PPC64_TPREL16_HIGHER: 8596130561Sobrien case R_PPC64_TPREL16_HIGHERA: 8597130561Sobrien case R_PPC64_TPREL16_HIGHEST: 8598130561Sobrien case R_PPC64_TPREL16_HIGHESTA: 8599130561Sobrien case R_PPC64_DTPREL16_HIGHER: 8600130561Sobrien case R_PPC64_DTPREL16_HIGHERA: 8601130561Sobrien case R_PPC64_DTPREL16_HIGHEST: 8602130561Sobrien case R_PPC64_DTPREL16_HIGHESTA: 860389857Sobrien /* It's just possible that this symbol is a weak symbol 860489857Sobrien that's not actually defined anywhere. In that case, 860589857Sobrien 'sec' would be NULL, and we should leave the symbol 860689857Sobrien alone (it will be set to zero elsewhere in the link). */ 860789857Sobrien if (sec != NULL) 8608130561Sobrien /* Add 0x10000 if sign bit in 0:15 is set. 8609130561Sobrien Bits 0:15 are not used. */ 8610130561Sobrien addend += 0x8000; 861189857Sobrien break; 861289857Sobrien 861389857Sobrien case R_PPC64_ADDR16_DS: 861489857Sobrien case R_PPC64_ADDR16_LO_DS: 861589857Sobrien case R_PPC64_GOT16_DS: 861689857Sobrien case R_PPC64_GOT16_LO_DS: 861789857Sobrien case R_PPC64_PLT16_LO_DS: 861889857Sobrien case R_PPC64_SECTOFF_DS: 861989857Sobrien case R_PPC64_SECTOFF_LO_DS: 862089857Sobrien case R_PPC64_TOC16_DS: 862189857Sobrien case R_PPC64_TOC16_LO_DS: 862289857Sobrien case R_PPC64_PLTGOT16_DS: 862389857Sobrien case R_PPC64_PLTGOT16_LO_DS: 8624130561Sobrien case R_PPC64_GOT_TPREL16_DS: 8625130561Sobrien case R_PPC64_GOT_TPREL16_LO_DS: 8626130561Sobrien case R_PPC64_GOT_DTPREL16_DS: 8627130561Sobrien case R_PPC64_GOT_DTPREL16_LO_DS: 8628130561Sobrien case R_PPC64_TPREL16_DS: 8629130561Sobrien case R_PPC64_TPREL16_LO_DS: 8630130561Sobrien case R_PPC64_DTPREL16_DS: 8631130561Sobrien case R_PPC64_DTPREL16_LO_DS: 8632130561Sobrien insn = bfd_get_32 (input_bfd, contents + (rel->r_offset & ~3)); 8633130561Sobrien mask = 3; 8634130561Sobrien /* If this reloc is against an lq insn, then the value must be 8635130561Sobrien a multiple of 16. This is somewhat of a hack, but the 8636130561Sobrien "correct" way to do this by defining _DQ forms of all the 8637130561Sobrien _DS relocs bloats all reloc switches in this file. It 8638130561Sobrien doesn't seem to make much sense to use any of these relocs 8639130561Sobrien in data, so testing the insn should be safe. */ 8640130561Sobrien if ((insn & (0x3f << 26)) == (56u << 26)) 8641130561Sobrien mask = 15; 8642130561Sobrien if (((relocation + addend) & mask) != 0) 864389857Sobrien { 864489857Sobrien (*_bfd_error_handler) 8645130561Sobrien (_("%s: error: relocation %s not a multiple of %d"), 864689857Sobrien bfd_archive_filename (input_bfd), 8647130561Sobrien ppc64_elf_howto_table[r_type]->name, 8648130561Sobrien mask + 1); 864989857Sobrien bfd_set_error (bfd_error_bad_value); 8650130561Sobrien ret = FALSE; 865189857Sobrien continue; 865289857Sobrien } 865389857Sobrien break; 8654104834Sobrien 8655104834Sobrien case R_PPC64_REL14: 8656104834Sobrien case R_PPC64_REL14_BRNTAKEN: 8657104834Sobrien case R_PPC64_REL14_BRTAKEN: 8658104834Sobrien max_br_offset = 1 << 15; 8659104834Sobrien goto branch_check; 8660104834Sobrien 8661104834Sobrien case R_PPC64_REL24: 8662104834Sobrien max_br_offset = 1 << 25; 8663104834Sobrien 8664104834Sobrien branch_check: 8665130561Sobrien /* If the branch is out of reach or the TOC register needs 8666130561Sobrien adjusting, then redirect the call to the local stub for 8667130561Sobrien this function. */ 8668130561Sobrien from = (rel->r_offset 8669104834Sobrien + input_section->output_offset 8670104834Sobrien + input_section->output_section->vma); 8671130561Sobrien if ((relocation + addend - from + max_br_offset >= 2 * max_br_offset 8672130561Sobrien || (sec != NULL 8673130561Sobrien && sec->output_section != NULL 8674130561Sobrien && sec->id <= htab->top_id 8675130561Sobrien && (htab->stub_group[sec->id].toc_off 8676130561Sobrien != htab->stub_group[input_section->id].toc_off))) 8677104834Sobrien && (stub_entry = ppc_get_stub_entry (input_section, sec, h, 8678104834Sobrien rel, htab)) != NULL) 8679104834Sobrien { 8680104834Sobrien /* Munge up the value and addend so that we call the stub 8681104834Sobrien rather than the procedure directly. */ 8682104834Sobrien relocation = (stub_entry->stub_offset 8683104834Sobrien + stub_entry->stub_sec->output_offset 8684104834Sobrien + stub_entry->stub_sec->output_section->vma); 8685104834Sobrien addend = 0; 8686104834Sobrien } 8687104834Sobrien break; 868889857Sobrien } 868989857Sobrien 8690104834Sobrien /* Dynamic relocs are not propagated for SEC_DEBUGGING sections 8691104834Sobrien because such sections are not SEC_ALLOC and thus ld.so will 8692104834Sobrien not process them. */ 869389857Sobrien if (unresolved_reloc 8694104834Sobrien && !((input_section->flags & SEC_DEBUGGING) != 0 869589857Sobrien && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0)) 8696104834Sobrien { 8697104834Sobrien (*_bfd_error_handler) 8698130561Sobrien (_("%s(%s+0x%lx): unresolvable %s relocation against symbol `%s'"), 8699104834Sobrien bfd_archive_filename (input_bfd), 8700104834Sobrien bfd_get_section_name (input_bfd, input_section), 8701104834Sobrien (long) rel->r_offset, 8702130561Sobrien ppc64_elf_howto_table[(int) r_type]->name, 8703104834Sobrien h->root.root.string); 8704130561Sobrien ret = FALSE; 8705104834Sobrien } 870689857Sobrien 870789857Sobrien r = _bfd_final_link_relocate (ppc64_elf_howto_table[(int) r_type], 870889857Sobrien input_bfd, 870989857Sobrien input_section, 871089857Sobrien contents, 8711130561Sobrien rel->r_offset, 871289857Sobrien relocation, 871389857Sobrien addend); 871489857Sobrien 8715104834Sobrien if (r != bfd_reloc_ok) 871689857Sobrien { 8717130561Sobrien if (sym_name == NULL) 8718130561Sobrien sym_name = "(null)"; 8719130561Sobrien if (r == bfd_reloc_overflow) 872089857Sobrien { 8721130561Sobrien if (warned) 8722130561Sobrien continue; 8723130561Sobrien if (h != NULL 8724130561Sobrien && h->root.type == bfd_link_hash_undefweak 8725130561Sobrien && ppc64_elf_howto_table[r_type]->pc_relative) 872689857Sobrien { 872789857Sobrien /* Assume this is a call protected by other code that 872889857Sobrien detects the symbol is undefined. If this is the case, 872989857Sobrien we can safely ignore the overflow. If not, the 873089857Sobrien program is hosed anyway, and a little warning isn't 873189857Sobrien going to help. */ 873289857Sobrien 873389857Sobrien continue; 873489857Sobrien } 873589857Sobrien 8736104834Sobrien if (!((*info->callbacks->reloc_overflow) 8737130561Sobrien (info, sym_name, ppc64_elf_howto_table[r_type]->name, 8738130561Sobrien rel->r_addend, input_bfd, input_section, rel->r_offset))) 8739130561Sobrien return FALSE; 8740104834Sobrien } 8741104834Sobrien else 8742104834Sobrien { 8743104834Sobrien (*_bfd_error_handler) 8744130561Sobrien (_("%s(%s+0x%lx): %s reloc against `%s': error %d"), 8745104834Sobrien bfd_archive_filename (input_bfd), 8746104834Sobrien bfd_get_section_name (input_bfd, input_section), 8747130561Sobrien (long) rel->r_offset, 8748130561Sobrien ppc64_elf_howto_table[r_type]->name, 8749130561Sobrien sym_name, 8750130561Sobrien (int) r); 8751130561Sobrien ret = FALSE; 8752104834Sobrien } 875389857Sobrien } 875489857Sobrien } 875589857Sobrien 875689857Sobrien return ret; 875789857Sobrien} 875889857Sobrien 8759130561Sobrien/* Adjust the value of any local symbols in opd sections. */ 8760130561Sobrien 8761130561Sobrienstatic bfd_boolean 8762130561Sobrienppc64_elf_output_symbol_hook (struct bfd_link_info *info, 8763130561Sobrien const char *name ATTRIBUTE_UNUSED, 8764130561Sobrien Elf_Internal_Sym *elfsym, 8765130561Sobrien asection *input_sec, 8766130561Sobrien struct elf_link_hash_entry *h) 8767130561Sobrien{ 8768130561Sobrien long *adjust; 8769130561Sobrien bfd_vma value; 8770130561Sobrien 8771130561Sobrien if (h != NULL 8772130561Sobrien || input_sec == NULL 8773130561Sobrien || ppc64_elf_section_data (input_sec) == NULL 8774130561Sobrien || (adjust = ppc64_elf_section_data (input_sec)->opd.adjust) == NULL) 8775130561Sobrien return TRUE; 8776130561Sobrien 8777130561Sobrien value = elfsym->st_value - input_sec->output_offset; 8778130561Sobrien if (!info->relocatable) 8779130561Sobrien value -= input_sec->output_section->vma; 8780130561Sobrien 8781130561Sobrien elfsym->st_value += adjust[value / 24]; 8782130561Sobrien return TRUE; 8783130561Sobrien} 8784130561Sobrien 878589857Sobrien/* Finish up dynamic symbol handling. We set the contents of various 878689857Sobrien dynamic sections here. */ 878789857Sobrien 8788130561Sobrienstatic bfd_boolean 8789130561Sobrienppc64_elf_finish_dynamic_symbol (bfd *output_bfd, 8790130561Sobrien struct bfd_link_info *info, 8791130561Sobrien struct elf_link_hash_entry *h, 8792130561Sobrien Elf_Internal_Sym *sym) 879389857Sobrien{ 879489857Sobrien struct ppc_link_hash_table *htab; 879589857Sobrien bfd *dynobj; 879689857Sobrien 879789857Sobrien htab = ppc_hash_table (info); 879889857Sobrien dynobj = htab->elf.dynobj; 879989857Sobrien 8800130561Sobrien if (((struct ppc_link_hash_entry *) h)->is_func_descriptor) 880189857Sobrien { 8802130561Sobrien struct plt_entry *ent; 880389857Sobrien Elf_Internal_Rela rela; 8804130561Sobrien bfd_byte *loc; 880589857Sobrien 8806130561Sobrien for (ent = h->plt.plist; ent != NULL; ent = ent->next) 8807130561Sobrien if (ent->plt.offset != (bfd_vma) -1) 8808130561Sobrien { 8809130561Sobrien /* This symbol has an entry in the procedure linkage 8810130561Sobrien table. Set it up. */ 881189857Sobrien 8812130561Sobrien if (htab->plt == NULL 8813130561Sobrien || htab->relplt == NULL 8814130561Sobrien || htab->glink == NULL) 8815130561Sobrien abort (); 881689857Sobrien 8817130561Sobrien /* Create a JMP_SLOT reloc to inform the dynamic linker to 8818130561Sobrien fill in the PLT entry. */ 8819130561Sobrien rela.r_offset = (htab->plt->output_section->vma 8820130561Sobrien + htab->plt->output_offset 8821130561Sobrien + ent->plt.offset); 8822130561Sobrien rela.r_info = ELF64_R_INFO (h->dynindx, R_PPC64_JMP_SLOT); 8823130561Sobrien rela.r_addend = ent->addend; 882489857Sobrien 8825130561Sobrien loc = htab->relplt->contents; 8826130561Sobrien loc += ((ent->plt.offset - PLT_INITIAL_ENTRY_SIZE) / PLT_ENTRY_SIZE 8827130561Sobrien * sizeof (Elf64_External_Rela)); 8828130561Sobrien bfd_elf64_swap_reloca_out (output_bfd, &rela, loc); 8829130561Sobrien } 883089857Sobrien } 883189857Sobrien 883289857Sobrien if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_COPY) != 0) 883389857Sobrien { 883489857Sobrien Elf_Internal_Rela rela; 8835130561Sobrien bfd_byte *loc; 883689857Sobrien 883789857Sobrien /* This symbol needs a copy reloc. Set it up. */ 883889857Sobrien 883989857Sobrien if (h->dynindx == -1 884089857Sobrien || (h->root.type != bfd_link_hash_defined 884189857Sobrien && h->root.type != bfd_link_hash_defweak) 8842130561Sobrien || htab->relbss == NULL) 884389857Sobrien abort (); 884489857Sobrien 884589857Sobrien rela.r_offset = (h->root.u.def.value 884689857Sobrien + h->root.u.def.section->output_section->vma 884789857Sobrien + h->root.u.def.section->output_offset); 884889857Sobrien rela.r_info = ELF64_R_INFO (h->dynindx, R_PPC64_COPY); 884989857Sobrien rela.r_addend = 0; 8850130561Sobrien loc = htab->relbss->contents; 8851130561Sobrien loc += htab->relbss->reloc_count++ * sizeof (Elf64_External_Rela); 885289857Sobrien bfd_elf64_swap_reloca_out (output_bfd, &rela, loc); 885389857Sobrien } 885489857Sobrien 885589857Sobrien /* Mark some specially defined symbols as absolute. */ 885689857Sobrien if (strcmp (h->root.root.string, "_DYNAMIC") == 0) 885789857Sobrien sym->st_shndx = SHN_ABS; 885889857Sobrien 8859130561Sobrien return TRUE; 886089857Sobrien} 886189857Sobrien 886289857Sobrien/* Used to decide how to sort relocs in an optimal manner for the 886389857Sobrien dynamic linker, before writing them out. */ 886489857Sobrien 886589857Sobrienstatic enum elf_reloc_type_class 8866130561Sobrienppc64_elf_reloc_type_class (const Elf_Internal_Rela *rela) 886789857Sobrien{ 8868130561Sobrien enum elf_ppc64_reloc_type r_type; 886989857Sobrien 8870130561Sobrien r_type = ELF64_R_TYPE (rela->r_info); 887189857Sobrien switch (r_type) 887289857Sobrien { 887389857Sobrien case R_PPC64_RELATIVE: 887489857Sobrien return reloc_class_relative; 887589857Sobrien case R_PPC64_JMP_SLOT: 887689857Sobrien return reloc_class_plt; 887789857Sobrien case R_PPC64_COPY: 887889857Sobrien return reloc_class_copy; 887989857Sobrien default: 888089857Sobrien return reloc_class_normal; 888189857Sobrien } 888289857Sobrien} 888389857Sobrien 888489857Sobrien/* Finish up the dynamic sections. */ 888589857Sobrien 8886130561Sobrienstatic bfd_boolean 8887130561Sobrienppc64_elf_finish_dynamic_sections (bfd *output_bfd, 8888130561Sobrien struct bfd_link_info *info) 888989857Sobrien{ 889089857Sobrien struct ppc_link_hash_table *htab; 889189857Sobrien bfd *dynobj; 889289857Sobrien asection *sdyn; 889389857Sobrien 889489857Sobrien htab = ppc_hash_table (info); 889589857Sobrien dynobj = htab->elf.dynobj; 889689857Sobrien sdyn = bfd_get_section_by_name (dynobj, ".dynamic"); 889789857Sobrien 889889857Sobrien if (htab->elf.dynamic_sections_created) 889989857Sobrien { 890089857Sobrien Elf64_External_Dyn *dyncon, *dynconend; 890189857Sobrien 8902130561Sobrien if (sdyn == NULL || htab->got == NULL) 890389857Sobrien abort (); 890489857Sobrien 890589857Sobrien dyncon = (Elf64_External_Dyn *) sdyn->contents; 890689857Sobrien dynconend = (Elf64_External_Dyn *) (sdyn->contents + sdyn->_raw_size); 890789857Sobrien for (; dyncon < dynconend; dyncon++) 890889857Sobrien { 890989857Sobrien Elf_Internal_Dyn dyn; 891091041Sobrien asection *s; 891189857Sobrien 891289857Sobrien bfd_elf64_swap_dyn_in (dynobj, dyncon, &dyn); 891389857Sobrien 891489857Sobrien switch (dyn.d_tag) 891589857Sobrien { 891689857Sobrien default: 891789857Sobrien continue; 891889857Sobrien 891989857Sobrien case DT_PPC64_GLINK: 8920130561Sobrien s = htab->glink; 8921130561Sobrien dyn.d_un.d_ptr = s->output_section->vma + s->output_offset; 8922130561Sobrien /* We stupidly defined DT_PPC64_GLINK to be the start 8923130561Sobrien of glink rather than the first entry point, which is 8924130561Sobrien what ld.so needs, and now have a bigger stub to 8925130561Sobrien support automatic multiple TOCs. */ 8926130561Sobrien dyn.d_un.d_ptr += GLINK_CALL_STUB_SIZE - 32; 892789857Sobrien break; 892889857Sobrien 892991041Sobrien case DT_PPC64_OPD: 893091041Sobrien s = bfd_get_section_by_name (output_bfd, ".opd"); 8931130561Sobrien if (s == NULL) 8932130561Sobrien continue; 8933130561Sobrien dyn.d_un.d_ptr = s->vma; 893491041Sobrien break; 893591041Sobrien 893691041Sobrien case DT_PPC64_OPDSZ: 893791041Sobrien s = bfd_get_section_by_name (output_bfd, ".opd"); 8938130561Sobrien if (s == NULL) 8939130561Sobrien continue; 8940130561Sobrien dyn.d_un.d_val = s->_raw_size; 894191041Sobrien break; 894291041Sobrien 894389857Sobrien case DT_PLTGOT: 8944130561Sobrien s = htab->plt; 8945130561Sobrien dyn.d_un.d_ptr = s->output_section->vma + s->output_offset; 894689857Sobrien break; 894789857Sobrien 894889857Sobrien case DT_JMPREL: 8949130561Sobrien s = htab->relplt; 8950130561Sobrien dyn.d_un.d_ptr = s->output_section->vma + s->output_offset; 895189857Sobrien break; 895289857Sobrien 895389857Sobrien case DT_PLTRELSZ: 8954130561Sobrien dyn.d_un.d_val = htab->relplt->_raw_size; 895589857Sobrien break; 895689857Sobrien 895789857Sobrien case DT_RELASZ: 895889857Sobrien /* Don't count procedure linkage table relocs in the 895989857Sobrien overall reloc count. */ 8960130561Sobrien s = htab->relplt; 8961130561Sobrien if (s == NULL) 8962130561Sobrien continue; 8963130561Sobrien dyn.d_un.d_val -= s->_raw_size; 896489857Sobrien break; 8965130561Sobrien 8966130561Sobrien case DT_RELA: 8967130561Sobrien /* We may not be using the standard ELF linker script. 8968130561Sobrien If .rela.plt is the first .rela section, we adjust 8969130561Sobrien DT_RELA to not include it. */ 8970130561Sobrien s = htab->relplt; 8971130561Sobrien if (s == NULL) 8972130561Sobrien continue; 8973130561Sobrien if (dyn.d_un.d_ptr != s->output_section->vma + s->output_offset) 8974130561Sobrien continue; 8975130561Sobrien dyn.d_un.d_ptr += s->_raw_size; 8976130561Sobrien break; 897789857Sobrien } 897889857Sobrien 897989857Sobrien bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon); 898089857Sobrien } 898189857Sobrien } 898289857Sobrien 8983130561Sobrien if (htab->got != NULL && htab->got->_raw_size != 0) 898489857Sobrien { 898589857Sobrien /* Fill in the first entry in the global offset table. 898689857Sobrien We use it to hold the link-time TOCbase. */ 898789857Sobrien bfd_put_64 (output_bfd, 898889857Sobrien elf_gp (output_bfd) + TOC_BASE_OFF, 8989130561Sobrien htab->got->contents); 899089857Sobrien 899189857Sobrien /* Set .got entry size. */ 8992130561Sobrien elf_section_data (htab->got->output_section)->this_hdr.sh_entsize = 8; 899389857Sobrien } 899489857Sobrien 8995130561Sobrien if (htab->plt != NULL && htab->plt->_raw_size != 0) 899689857Sobrien { 899789857Sobrien /* Set .plt entry size. */ 8998130561Sobrien elf_section_data (htab->plt->output_section)->this_hdr.sh_entsize 899989857Sobrien = PLT_ENTRY_SIZE; 900089857Sobrien } 900189857Sobrien 9002130561Sobrien /* We need to handle writing out multiple GOT sections ourselves, 9003130561Sobrien since we didn't add them to DYNOBJ. */ 9004130561Sobrien while ((dynobj = dynobj->link_next) != NULL) 9005130561Sobrien { 9006130561Sobrien asection *s; 9007209867Snwhitehorn 9008209867Snwhitehorn if (bfd_get_flavour (dynobj) != bfd_target_elf_flavour) 9009209867Snwhitehorn continue; 9010209867Snwhitehorn 9011130561Sobrien s = ppc64_elf_tdata (dynobj)->got; 9012130561Sobrien if (s != NULL 9013130561Sobrien && s->_raw_size != 0 9014130561Sobrien && s->output_section != bfd_abs_section_ptr 9015130561Sobrien && !bfd_set_section_contents (output_bfd, s->output_section, 9016130561Sobrien s->contents, s->output_offset, 9017130561Sobrien s->_raw_size)) 9018130561Sobrien return FALSE; 9019130561Sobrien s = ppc64_elf_tdata (dynobj)->relgot; 9020130561Sobrien if (s != NULL 9021130561Sobrien && s->_raw_size != 0 9022130561Sobrien && s->output_section != bfd_abs_section_ptr 9023130561Sobrien && !bfd_set_section_contents (output_bfd, s->output_section, 9024130561Sobrien s->contents, s->output_offset, 9025130561Sobrien s->_raw_size)) 9026130561Sobrien return FALSE; 9027130561Sobrien } 9028130561Sobrien 9029130561Sobrien return TRUE; 903089857Sobrien} 903189857Sobrien 903289857Sobrien#include "elf64-target.h" 9033