elf64-ppc.c revision 107492
189857Sobrien/* PowerPC64-specific support for 64-bit ELF. 289857Sobrien Copyright 1999, 2000, 2001, 2002 Free Software Foundation, Inc. 389857Sobrien Written by Linus Nordberg, Swox AB <info@swox.com>, 489857Sobrien based on elf32-ppc.c by Ian Lance Taylor. 589857Sobrien 689857SobrienThis file is part of BFD, the Binary File Descriptor library. 789857Sobrien 889857SobrienThis program is free software; you can redistribute it and/or modify 989857Sobrienit under the terms of the GNU General Public License as published by 1089857Sobrienthe Free Software Foundation; either version 2 of the License, or 1189857Sobrien(at your option) any later version. 1289857Sobrien 1389857SobrienThis program is distributed in the hope that it will be useful, 1489857Sobrienbut WITHOUT ANY WARRANTY; without even the implied warranty of 1589857SobrienMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1689857SobrienGNU General Public License for more details. 1789857Sobrien 1889857SobrienYou should have received a copy of the GNU General Public License 1989857Sobrienalong with this program; if not, write to the Free Software 2089857SobrienFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 2189857Sobrien 2289857Sobrien/* This file is based on the 64-bit PowerPC ELF ABI. It is also based 2389857Sobrien on the file elf32-ppc.c. */ 2489857Sobrien 2589857Sobrien#include "bfd.h" 2689857Sobrien#include "sysdep.h" 2789857Sobrien#include "bfdlink.h" 2889857Sobrien#include "libbfd.h" 2989857Sobrien#include "elf-bfd.h" 3089857Sobrien#include "elf/ppc.h" 3189857Sobrien#include "elf64-ppc.h" 3289857Sobrien 3389857Sobrien#define USE_RELA /* we want RELA relocations, not REL. */ 3489857Sobrien 3589857Sobrien 3689857Sobrienstatic void ppc_howto_init 3789857Sobrien PARAMS ((void)); 3889857Sobrienstatic reloc_howto_type *ppc64_elf_reloc_type_lookup 3989857Sobrien PARAMS ((bfd *abfd, bfd_reloc_code_real_type code)); 4089857Sobrienstatic void ppc64_elf_info_to_howto 4189857Sobrien PARAMS ((bfd *abfd, arelent *cache_ptr, Elf64_Internal_Rela *dst)); 4299461Sobrienstatic bfd_reloc_status_type ppc64_elf_ha_reloc 4389857Sobrien PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); 4499461Sobrienstatic bfd_reloc_status_type ppc64_elf_brtaken_reloc 4599461Sobrien PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); 4699461Sobrienstatic bfd_reloc_status_type ppc64_elf_sectoff_reloc 4799461Sobrien PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); 4899461Sobrienstatic bfd_reloc_status_type ppc64_elf_sectoff_ha_reloc 4999461Sobrien PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); 5099461Sobrienstatic bfd_reloc_status_type ppc64_elf_toc_reloc 5199461Sobrien PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); 5299461Sobrienstatic bfd_reloc_status_type ppc64_elf_toc_ha_reloc 5399461Sobrien PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); 5499461Sobrienstatic bfd_reloc_status_type ppc64_elf_toc64_reloc 5599461Sobrien PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); 5699461Sobrienstatic bfd_reloc_status_type ppc64_elf_unhandled_reloc 5799461Sobrien PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); 58104834Sobrienstatic boolean ppc64_elf_object_p 59104834Sobrien PARAMS ((bfd *)); 6089857Sobrienstatic boolean ppc64_elf_merge_private_bfd_data 6189857Sobrien PARAMS ((bfd *, bfd *)); 6289857Sobrien 6389857Sobrien 6489857Sobrien/* The name of the dynamic interpreter. This is put in the .interp 6589857Sobrien section. */ 6689857Sobrien#define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1" 6789857Sobrien 6889857Sobrien/* The size in bytes of an entry in the procedure linkage table. */ 6989857Sobrien#define PLT_ENTRY_SIZE 24 7089857Sobrien 7189857Sobrien/* The initial size of the plt reserved for the dynamic linker. */ 7289857Sobrien#define PLT_INITIAL_ENTRY_SIZE PLT_ENTRY_SIZE 7389857Sobrien 7489857Sobrien/* TOC base pointers offset from start of TOC. */ 7589857Sobrien#define TOC_BASE_OFF (0x8000) 7689857Sobrien 7789857Sobrien/* .plt call stub instructions. */ 7889857Sobrien#define ADDIS_R12_R2 0x3d820000 /* addis %r12,%r2,xxx@ha */ 7989857Sobrien#define STD_R2_40R1 0xf8410028 /* std %r2,40(%r1) */ 8089857Sobrien#define LD_R11_0R12 0xe96c0000 /* ld %r11,xxx+0@l(%r12) */ 8189857Sobrien#define LD_R2_0R12 0xe84c0000 /* ld %r2,xxx+8@l(%r12) */ 8289857Sobrien#define MTCTR_R11 0x7d6903a6 /* mtctr %r11 */ 8389857Sobrien /* ld %r11,xxx+16@l(%r12) */ 8489857Sobrien#define BCTR 0x4e800420 /* bctr */ 8589857Sobrien 8689857Sobrien/* The normal stub is this size. */ 8789857Sobrien#define PLT_CALL_STUB_SIZE (7*4) 8889857Sobrien 8989857Sobrien/* But sometimes the .plt entry crosses a 64k boundary, and we need 9089857Sobrien to adjust the high word with this insn. */ 9189857Sobrien#define ADDIS_R12_R12_1 0x3d8c0001 /* addis %r12,%r12,1 */ 9289857Sobrien 9389857Sobrien/* The .glink fixup call stub is the same as the .plt call stub, but 9489857Sobrien the first instruction restores r2, and the std is omitted. */ 9589857Sobrien#define LD_R2_40R1 0xe8410028 /* ld %r2,40(%r1) */ 9689857Sobrien 9789857Sobrien/* Always allow this much space. */ 9889857Sobrien#define GLINK_CALL_STUB_SIZE (8*4) 9989857Sobrien 10089857Sobrien/* Pad with this. */ 10189857Sobrien#define NOP 0x60000000 10289857Sobrien 10399461Sobrien/* Some other nops. */ 10499461Sobrien#define CROR_151515 0x4def7b82 10599461Sobrien#define CROR_313131 0x4ffffb82 10699461Sobrien 107104834Sobrien/* .glink entries for the first 32k functions are two instructions. */ 10889857Sobrien#define LI_R0_0 0x38000000 /* li %r0,0 */ 10989857Sobrien#define B_DOT 0x48000000 /* b . */ 11089857Sobrien 11189857Sobrien/* After that, we need two instructions to load the index, followed by 11289857Sobrien a branch. */ 11389857Sobrien#define LIS_R0_0 0x3c000000 /* lis %r0,0 */ 11489857Sobrien#define ORI_R0_R0_0 0x60000000 /* ori %r0,%r0,0 */ 11589857Sobrien 11692828Sobrien/* Instructions to save and restore floating point regs. */ 11792828Sobrien#define STFD_FR0_0R1 0xd8010000 /* stfd %fr0,0(%r1) */ 11892828Sobrien#define LFD_FR0_0R1 0xc8010000 /* lfd %fr0,0(%r1) */ 11992828Sobrien#define BLR 0x4e800020 /* blr */ 12092828Sobrien 12189857Sobrien/* Since .opd is an array of descriptors and each entry will end up 12289857Sobrien with identical R_PPC64_RELATIVE relocs, there is really no need to 12389857Sobrien propagate .opd relocs; The dynamic linker should be taught to 124104834Sobrien relocate .opd without reloc entries. */ 12589857Sobrien#ifndef NO_OPD_RELOCS 12689857Sobrien#define NO_OPD_RELOCS 0 12789857Sobrien#endif 12889857Sobrien 129104834Sobrien#define ONES(n) (((bfd_vma) 1 << ((n) - 1) << 1) - 1) 130104834Sobrien 13189857Sobrien/* Relocation HOWTO's. */ 13289857Sobrienstatic reloc_howto_type *ppc64_elf_howto_table[(int) R_PPC_max]; 13389857Sobrien 13489857Sobrienstatic reloc_howto_type ppc64_elf_howto_raw[] = { 13589857Sobrien /* This reloc does nothing. */ 13689857Sobrien HOWTO (R_PPC64_NONE, /* type */ 13789857Sobrien 0, /* rightshift */ 138104834Sobrien 0, /* size (0 = byte, 1 = short, 2 = long) */ 139104834Sobrien 8, /* bitsize */ 14089857Sobrien false, /* pc_relative */ 14189857Sobrien 0, /* bitpos */ 142104834Sobrien complain_overflow_dont, /* complain_on_overflow */ 14389857Sobrien bfd_elf_generic_reloc, /* special_function */ 14489857Sobrien "R_PPC64_NONE", /* name */ 14589857Sobrien false, /* partial_inplace */ 14689857Sobrien 0, /* src_mask */ 14789857Sobrien 0, /* dst_mask */ 14889857Sobrien false), /* pcrel_offset */ 14989857Sobrien 15089857Sobrien /* A standard 32 bit relocation. */ 15189857Sobrien HOWTO (R_PPC64_ADDR32, /* type */ 15289857Sobrien 0, /* rightshift */ 15389857Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 15489857Sobrien 32, /* bitsize */ 15589857Sobrien false, /* pc_relative */ 15689857Sobrien 0, /* bitpos */ 15789857Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 15889857Sobrien bfd_elf_generic_reloc, /* special_function */ 15989857Sobrien "R_PPC64_ADDR32", /* name */ 16089857Sobrien false, /* partial_inplace */ 16189857Sobrien 0, /* src_mask */ 16289857Sobrien 0xffffffff, /* dst_mask */ 16389857Sobrien false), /* pcrel_offset */ 16489857Sobrien 16589857Sobrien /* An absolute 26 bit branch; the lower two bits must be zero. 16689857Sobrien FIXME: we don't check that, we just clear them. */ 16789857Sobrien HOWTO (R_PPC64_ADDR24, /* type */ 16889857Sobrien 0, /* rightshift */ 16989857Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 17089857Sobrien 26, /* bitsize */ 17189857Sobrien false, /* pc_relative */ 17289857Sobrien 0, /* bitpos */ 17389857Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 17489857Sobrien bfd_elf_generic_reloc, /* special_function */ 17589857Sobrien "R_PPC64_ADDR24", /* name */ 17689857Sobrien false, /* partial_inplace */ 17789857Sobrien 0, /* src_mask */ 178104834Sobrien 0x03fffffc, /* dst_mask */ 17989857Sobrien false), /* pcrel_offset */ 18089857Sobrien 18189857Sobrien /* A standard 16 bit relocation. */ 18289857Sobrien HOWTO (R_PPC64_ADDR16, /* type */ 18389857Sobrien 0, /* rightshift */ 18489857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 18589857Sobrien 16, /* bitsize */ 18689857Sobrien false, /* pc_relative */ 18789857Sobrien 0, /* bitpos */ 18889857Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 18989857Sobrien bfd_elf_generic_reloc, /* special_function */ 19089857Sobrien "R_PPC64_ADDR16", /* name */ 19189857Sobrien false, /* partial_inplace */ 19289857Sobrien 0, /* src_mask */ 19389857Sobrien 0xffff, /* dst_mask */ 19489857Sobrien false), /* pcrel_offset */ 19589857Sobrien 19689857Sobrien /* A 16 bit relocation without overflow. */ 19789857Sobrien HOWTO (R_PPC64_ADDR16_LO, /* type */ 19889857Sobrien 0, /* rightshift */ 19989857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 20089857Sobrien 16, /* bitsize */ 20189857Sobrien false, /* pc_relative */ 20289857Sobrien 0, /* bitpos */ 20389857Sobrien complain_overflow_dont,/* complain_on_overflow */ 20489857Sobrien bfd_elf_generic_reloc, /* special_function */ 20589857Sobrien "R_PPC64_ADDR16_LO", /* name */ 20689857Sobrien false, /* partial_inplace */ 20789857Sobrien 0, /* src_mask */ 20889857Sobrien 0xffff, /* dst_mask */ 20989857Sobrien false), /* pcrel_offset */ 21089857Sobrien 21189857Sobrien /* Bits 16-31 of an address. */ 21289857Sobrien HOWTO (R_PPC64_ADDR16_HI, /* type */ 21389857Sobrien 16, /* rightshift */ 21489857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 21589857Sobrien 16, /* bitsize */ 21689857Sobrien false, /* pc_relative */ 21789857Sobrien 0, /* bitpos */ 21889857Sobrien complain_overflow_dont, /* complain_on_overflow */ 21989857Sobrien bfd_elf_generic_reloc, /* special_function */ 22089857Sobrien "R_PPC64_ADDR16_HI", /* name */ 22189857Sobrien false, /* partial_inplace */ 22289857Sobrien 0, /* src_mask */ 22389857Sobrien 0xffff, /* dst_mask */ 22489857Sobrien false), /* pcrel_offset */ 22589857Sobrien 22689857Sobrien /* Bits 16-31 of an address, plus 1 if the contents of the low 16 22789857Sobrien bits, treated as a signed number, is negative. */ 22889857Sobrien HOWTO (R_PPC64_ADDR16_HA, /* type */ 22989857Sobrien 16, /* rightshift */ 23089857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 23189857Sobrien 16, /* bitsize */ 23289857Sobrien false, /* pc_relative */ 23389857Sobrien 0, /* bitpos */ 23489857Sobrien complain_overflow_dont, /* complain_on_overflow */ 23599461Sobrien ppc64_elf_ha_reloc, /* special_function */ 23689857Sobrien "R_PPC64_ADDR16_HA", /* name */ 23789857Sobrien false, /* partial_inplace */ 23889857Sobrien 0, /* src_mask */ 23989857Sobrien 0xffff, /* dst_mask */ 24089857Sobrien false), /* pcrel_offset */ 24189857Sobrien 24289857Sobrien /* An absolute 16 bit branch; the lower two bits must be zero. 24389857Sobrien FIXME: we don't check that, we just clear them. */ 24489857Sobrien HOWTO (R_PPC64_ADDR14, /* type */ 24589857Sobrien 0, /* rightshift */ 24689857Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 24789857Sobrien 16, /* bitsize */ 24889857Sobrien false, /* pc_relative */ 24989857Sobrien 0, /* bitpos */ 25089857Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 25189857Sobrien bfd_elf_generic_reloc, /* special_function */ 25289857Sobrien "R_PPC64_ADDR14", /* name */ 25389857Sobrien false, /* partial_inplace */ 25489857Sobrien 0, /* src_mask */ 255104834Sobrien 0x0000fffc, /* dst_mask */ 25689857Sobrien false), /* pcrel_offset */ 25789857Sobrien 25889857Sobrien /* An absolute 16 bit branch, for which bit 10 should be set to 25989857Sobrien indicate that the branch is expected to be taken. The lower two 26089857Sobrien bits must be zero. */ 26189857Sobrien HOWTO (R_PPC64_ADDR14_BRTAKEN, /* type */ 26289857Sobrien 0, /* rightshift */ 26389857Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 26489857Sobrien 16, /* bitsize */ 26589857Sobrien false, /* pc_relative */ 26689857Sobrien 0, /* bitpos */ 26789857Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 26899461Sobrien ppc64_elf_brtaken_reloc, /* special_function */ 26989857Sobrien "R_PPC64_ADDR14_BRTAKEN",/* name */ 27089857Sobrien false, /* partial_inplace */ 27189857Sobrien 0, /* src_mask */ 272104834Sobrien 0x0000fffc, /* dst_mask */ 27389857Sobrien false), /* pcrel_offset */ 27489857Sobrien 27589857Sobrien /* An absolute 16 bit branch, for which bit 10 should be set to 27689857Sobrien indicate that the branch is not expected to be taken. The lower 27789857Sobrien two bits must be zero. */ 27889857Sobrien HOWTO (R_PPC64_ADDR14_BRNTAKEN, /* type */ 27989857Sobrien 0, /* rightshift */ 28089857Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 28189857Sobrien 16, /* bitsize */ 28289857Sobrien false, /* pc_relative */ 28389857Sobrien 0, /* bitpos */ 28489857Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 28599461Sobrien ppc64_elf_brtaken_reloc, /* special_function */ 28689857Sobrien "R_PPC64_ADDR14_BRNTAKEN",/* name */ 28789857Sobrien false, /* partial_inplace */ 28889857Sobrien 0, /* src_mask */ 289104834Sobrien 0x0000fffc, /* dst_mask */ 29089857Sobrien false), /* pcrel_offset */ 29189857Sobrien 29289857Sobrien /* A relative 26 bit branch; the lower two bits must be zero. */ 29389857Sobrien HOWTO (R_PPC64_REL24, /* type */ 29489857Sobrien 0, /* rightshift */ 29589857Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 29689857Sobrien 26, /* bitsize */ 29789857Sobrien true, /* pc_relative */ 29889857Sobrien 0, /* bitpos */ 29989857Sobrien complain_overflow_signed, /* complain_on_overflow */ 30089857Sobrien bfd_elf_generic_reloc, /* special_function */ 30189857Sobrien "R_PPC64_REL24", /* name */ 30289857Sobrien false, /* partial_inplace */ 30389857Sobrien 0, /* src_mask */ 304104834Sobrien 0x03fffffc, /* dst_mask */ 30589857Sobrien true), /* pcrel_offset */ 30689857Sobrien 30789857Sobrien /* A relative 16 bit branch; the lower two bits must be zero. */ 30889857Sobrien HOWTO (R_PPC64_REL14, /* type */ 30989857Sobrien 0, /* rightshift */ 31089857Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 31189857Sobrien 16, /* bitsize */ 31289857Sobrien true, /* pc_relative */ 31389857Sobrien 0, /* bitpos */ 31489857Sobrien complain_overflow_signed, /* complain_on_overflow */ 31589857Sobrien bfd_elf_generic_reloc, /* special_function */ 31689857Sobrien "R_PPC64_REL14", /* name */ 31789857Sobrien false, /* partial_inplace */ 31889857Sobrien 0, /* src_mask */ 319104834Sobrien 0x0000fffc, /* dst_mask */ 32089857Sobrien true), /* pcrel_offset */ 32189857Sobrien 32289857Sobrien /* A relative 16 bit branch. Bit 10 should be set to indicate that 32389857Sobrien the branch is expected to be taken. The lower two bits must be 32489857Sobrien zero. */ 32589857Sobrien HOWTO (R_PPC64_REL14_BRTAKEN, /* type */ 32689857Sobrien 0, /* rightshift */ 32789857Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 32889857Sobrien 16, /* bitsize */ 32989857Sobrien true, /* pc_relative */ 33089857Sobrien 0, /* bitpos */ 33189857Sobrien complain_overflow_signed, /* complain_on_overflow */ 33299461Sobrien ppc64_elf_brtaken_reloc, /* special_function */ 33389857Sobrien "R_PPC64_REL14_BRTAKEN", /* name */ 33489857Sobrien false, /* partial_inplace */ 33589857Sobrien 0, /* src_mask */ 336104834Sobrien 0x0000fffc, /* dst_mask */ 33789857Sobrien true), /* pcrel_offset */ 33889857Sobrien 33989857Sobrien /* A relative 16 bit branch. Bit 10 should be set to indicate that 34089857Sobrien the branch is not expected to be taken. The lower two bits must 34189857Sobrien be zero. */ 34289857Sobrien HOWTO (R_PPC64_REL14_BRNTAKEN, /* type */ 34389857Sobrien 0, /* rightshift */ 34489857Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 34589857Sobrien 16, /* bitsize */ 34689857Sobrien true, /* pc_relative */ 34789857Sobrien 0, /* bitpos */ 34889857Sobrien complain_overflow_signed, /* complain_on_overflow */ 34999461Sobrien ppc64_elf_brtaken_reloc, /* special_function */ 35089857Sobrien "R_PPC64_REL14_BRNTAKEN",/* name */ 35189857Sobrien false, /* partial_inplace */ 35289857Sobrien 0, /* src_mask */ 353104834Sobrien 0x0000fffc, /* dst_mask */ 35489857Sobrien true), /* pcrel_offset */ 35589857Sobrien 35689857Sobrien /* Like R_PPC64_ADDR16, but referring to the GOT table entry for the 35789857Sobrien symbol. */ 35889857Sobrien HOWTO (R_PPC64_GOT16, /* type */ 35989857Sobrien 0, /* rightshift */ 36089857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 36189857Sobrien 16, /* bitsize */ 36289857Sobrien false, /* pc_relative */ 36389857Sobrien 0, /* bitpos */ 36489857Sobrien complain_overflow_signed, /* complain_on_overflow */ 36599461Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 36689857Sobrien "R_PPC64_GOT16", /* name */ 36789857Sobrien false, /* partial_inplace */ 36889857Sobrien 0, /* src_mask */ 36989857Sobrien 0xffff, /* dst_mask */ 37089857Sobrien false), /* pcrel_offset */ 37189857Sobrien 37289857Sobrien /* Like R_PPC64_ADDR16_LO, but referring to the GOT table entry for 37389857Sobrien the symbol. */ 37489857Sobrien HOWTO (R_PPC64_GOT16_LO, /* type */ 37589857Sobrien 0, /* rightshift */ 37689857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 37789857Sobrien 16, /* bitsize */ 37889857Sobrien false, /* pc_relative */ 37989857Sobrien 0, /* bitpos */ 38089857Sobrien complain_overflow_dont, /* complain_on_overflow */ 38199461Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 38289857Sobrien "R_PPC64_GOT16_LO", /* name */ 38389857Sobrien false, /* partial_inplace */ 38489857Sobrien 0, /* src_mask */ 38589857Sobrien 0xffff, /* dst_mask */ 38689857Sobrien false), /* pcrel_offset */ 38789857Sobrien 38889857Sobrien /* Like R_PPC64_ADDR16_HI, but referring to the GOT table entry for 38989857Sobrien the symbol. */ 39089857Sobrien HOWTO (R_PPC64_GOT16_HI, /* type */ 39189857Sobrien 16, /* rightshift */ 39289857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 39389857Sobrien 16, /* bitsize */ 39489857Sobrien false, /* pc_relative */ 39589857Sobrien 0, /* bitpos */ 39689857Sobrien complain_overflow_dont,/* complain_on_overflow */ 39799461Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 39889857Sobrien "R_PPC64_GOT16_HI", /* name */ 39989857Sobrien false, /* partial_inplace */ 40089857Sobrien 0, /* src_mask */ 40189857Sobrien 0xffff, /* dst_mask */ 40289857Sobrien false), /* pcrel_offset */ 40389857Sobrien 40489857Sobrien /* Like R_PPC64_ADDR16_HA, but referring to the GOT table entry for 40589857Sobrien the symbol. */ 40689857Sobrien HOWTO (R_PPC64_GOT16_HA, /* type */ 40789857Sobrien 16, /* rightshift */ 40889857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 40989857Sobrien 16, /* bitsize */ 41089857Sobrien false, /* pc_relative */ 41189857Sobrien 0, /* bitpos */ 41289857Sobrien complain_overflow_dont,/* complain_on_overflow */ 41399461Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 41489857Sobrien "R_PPC64_GOT16_HA", /* name */ 41589857Sobrien false, /* partial_inplace */ 41689857Sobrien 0, /* src_mask */ 41789857Sobrien 0xffff, /* dst_mask */ 41889857Sobrien false), /* pcrel_offset */ 41989857Sobrien 42089857Sobrien /* This is used only by the dynamic linker. The symbol should exist 42189857Sobrien both in the object being run and in some shared library. The 42289857Sobrien dynamic linker copies the data addressed by the symbol from the 42389857Sobrien shared library into the object, because the object being 42489857Sobrien run has to have the data at some particular address. */ 42589857Sobrien HOWTO (R_PPC64_COPY, /* type */ 42689857Sobrien 0, /* rightshift */ 427104834Sobrien 0, /* this one is variable size */ 428104834Sobrien 0, /* bitsize */ 42989857Sobrien false, /* pc_relative */ 43089857Sobrien 0, /* bitpos */ 431104834Sobrien complain_overflow_dont, /* complain_on_overflow */ 432104834Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 43389857Sobrien "R_PPC64_COPY", /* name */ 43489857Sobrien false, /* partial_inplace */ 43589857Sobrien 0, /* src_mask */ 43689857Sobrien 0, /* dst_mask */ 43789857Sobrien false), /* pcrel_offset */ 43889857Sobrien 43989857Sobrien /* Like R_PPC64_ADDR64, but used when setting global offset table 44089857Sobrien entries. */ 44189857Sobrien HOWTO (R_PPC64_GLOB_DAT, /* type */ 44289857Sobrien 0, /* rightshift */ 44389857Sobrien 4, /* size (0=byte, 1=short, 2=long, 4=64 bits) */ 44489857Sobrien 64, /* bitsize */ 44589857Sobrien false, /* pc_relative */ 44689857Sobrien 0, /* bitpos */ 44789857Sobrien complain_overflow_dont, /* complain_on_overflow */ 44899461Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 44989857Sobrien "R_PPC64_GLOB_DAT", /* name */ 45089857Sobrien false, /* partial_inplace */ 45189857Sobrien 0, /* src_mask */ 452104834Sobrien ONES (64), /* dst_mask */ 45389857Sobrien false), /* pcrel_offset */ 45489857Sobrien 45589857Sobrien /* Created by the link editor. Marks a procedure linkage table 45689857Sobrien entry for a symbol. */ 45789857Sobrien HOWTO (R_PPC64_JMP_SLOT, /* type */ 45889857Sobrien 0, /* rightshift */ 45989857Sobrien 0, /* size (0 = byte, 1 = short, 2 = long) */ 46089857Sobrien 0, /* bitsize */ 46189857Sobrien false, /* pc_relative */ 46289857Sobrien 0, /* bitpos */ 46389857Sobrien complain_overflow_dont, /* complain_on_overflow */ 46499461Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 46589857Sobrien "R_PPC64_JMP_SLOT", /* name */ 46689857Sobrien false, /* partial_inplace */ 46789857Sobrien 0, /* src_mask */ 46889857Sobrien 0, /* dst_mask */ 46989857Sobrien false), /* pcrel_offset */ 47089857Sobrien 47189857Sobrien /* Used only by the dynamic linker. When the object is run, this 47289857Sobrien doubleword64 is set to the load address of the object, plus the 47389857Sobrien addend. */ 47489857Sobrien HOWTO (R_PPC64_RELATIVE, /* type */ 47589857Sobrien 0, /* rightshift */ 47689857Sobrien 4, /* size (0=byte, 1=short, 2=long, 4=64 bits) */ 47789857Sobrien 64, /* bitsize */ 47889857Sobrien false, /* pc_relative */ 47989857Sobrien 0, /* bitpos */ 48089857Sobrien complain_overflow_dont, /* complain_on_overflow */ 48189857Sobrien bfd_elf_generic_reloc, /* special_function */ 48289857Sobrien "R_PPC64_RELATIVE", /* name */ 48389857Sobrien false, /* partial_inplace */ 48489857Sobrien 0, /* src_mask */ 485104834Sobrien ONES (64), /* dst_mask */ 48689857Sobrien false), /* pcrel_offset */ 48789857Sobrien 48889857Sobrien /* Like R_PPC64_ADDR32, but may be unaligned. */ 48989857Sobrien HOWTO (R_PPC64_UADDR32, /* type */ 49089857Sobrien 0, /* rightshift */ 49189857Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 49289857Sobrien 32, /* bitsize */ 49389857Sobrien false, /* pc_relative */ 49489857Sobrien 0, /* bitpos */ 49589857Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 49689857Sobrien bfd_elf_generic_reloc, /* special_function */ 49789857Sobrien "R_PPC64_UADDR32", /* name */ 49889857Sobrien false, /* partial_inplace */ 49989857Sobrien 0, /* src_mask */ 50089857Sobrien 0xffffffff, /* dst_mask */ 50189857Sobrien false), /* pcrel_offset */ 50289857Sobrien 50389857Sobrien /* Like R_PPC64_ADDR16, but may be unaligned. */ 50489857Sobrien HOWTO (R_PPC64_UADDR16, /* type */ 50589857Sobrien 0, /* rightshift */ 50689857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 50789857Sobrien 16, /* bitsize */ 50889857Sobrien false, /* pc_relative */ 50989857Sobrien 0, /* bitpos */ 51089857Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 51189857Sobrien bfd_elf_generic_reloc, /* special_function */ 51289857Sobrien "R_PPC64_UADDR16", /* name */ 51389857Sobrien false, /* partial_inplace */ 51489857Sobrien 0, /* src_mask */ 51589857Sobrien 0xffff, /* dst_mask */ 51689857Sobrien false), /* pcrel_offset */ 51789857Sobrien 51889857Sobrien /* 32-bit PC relative. */ 51989857Sobrien HOWTO (R_PPC64_REL32, /* type */ 52089857Sobrien 0, /* rightshift */ 52189857Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 52289857Sobrien 32, /* bitsize */ 52389857Sobrien true, /* pc_relative */ 52489857Sobrien 0, /* bitpos */ 525104834Sobrien /* FIXME: Verify. Was complain_overflow_bitfield. */ 52689857Sobrien complain_overflow_signed, /* complain_on_overflow */ 52789857Sobrien bfd_elf_generic_reloc, /* special_function */ 52889857Sobrien "R_PPC64_REL32", /* name */ 52989857Sobrien false, /* partial_inplace */ 53089857Sobrien 0, /* src_mask */ 53189857Sobrien 0xffffffff, /* dst_mask */ 53289857Sobrien true), /* pcrel_offset */ 53389857Sobrien 53489857Sobrien /* 32-bit relocation to the symbol's procedure linkage table. */ 53589857Sobrien HOWTO (R_PPC64_PLT32, /* type */ 53689857Sobrien 0, /* rightshift */ 53789857Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 53889857Sobrien 32, /* bitsize */ 53989857Sobrien false, /* pc_relative */ 54089857Sobrien 0, /* bitpos */ 54189857Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 54299461Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 54389857Sobrien "R_PPC64_PLT32", /* name */ 54489857Sobrien false, /* partial_inplace */ 54589857Sobrien 0, /* src_mask */ 546104834Sobrien 0xffffffff, /* dst_mask */ 54789857Sobrien false), /* pcrel_offset */ 54889857Sobrien 54989857Sobrien /* 32-bit PC relative relocation to the symbol's procedure linkage table. 55089857Sobrien FIXME: R_PPC64_PLTREL32 not supported. */ 55189857Sobrien HOWTO (R_PPC64_PLTREL32, /* type */ 55289857Sobrien 0, /* rightshift */ 55389857Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 55489857Sobrien 32, /* bitsize */ 55589857Sobrien true, /* pc_relative */ 55689857Sobrien 0, /* bitpos */ 55789857Sobrien complain_overflow_signed, /* complain_on_overflow */ 55889857Sobrien bfd_elf_generic_reloc, /* special_function */ 55989857Sobrien "R_PPC64_PLTREL32", /* name */ 56089857Sobrien false, /* partial_inplace */ 56189857Sobrien 0, /* src_mask */ 562104834Sobrien 0xffffffff, /* dst_mask */ 56389857Sobrien true), /* pcrel_offset */ 56489857Sobrien 56589857Sobrien /* Like R_PPC64_ADDR16_LO, but referring to the PLT table entry for 56689857Sobrien the symbol. */ 56789857Sobrien HOWTO (R_PPC64_PLT16_LO, /* type */ 56889857Sobrien 0, /* rightshift */ 56989857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 57089857Sobrien 16, /* bitsize */ 57189857Sobrien false, /* pc_relative */ 57289857Sobrien 0, /* bitpos */ 57389857Sobrien complain_overflow_dont, /* complain_on_overflow */ 57499461Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 57589857Sobrien "R_PPC64_PLT16_LO", /* name */ 57689857Sobrien false, /* partial_inplace */ 57789857Sobrien 0, /* src_mask */ 57889857Sobrien 0xffff, /* dst_mask */ 57989857Sobrien false), /* pcrel_offset */ 58089857Sobrien 58189857Sobrien /* Like R_PPC64_ADDR16_HI, but referring to the PLT table entry for 58289857Sobrien the symbol. */ 58389857Sobrien HOWTO (R_PPC64_PLT16_HI, /* type */ 58489857Sobrien 16, /* rightshift */ 58589857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 58689857Sobrien 16, /* bitsize */ 58789857Sobrien false, /* pc_relative */ 58889857Sobrien 0, /* bitpos */ 58989857Sobrien complain_overflow_dont, /* complain_on_overflow */ 59099461Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 59189857Sobrien "R_PPC64_PLT16_HI", /* name */ 59289857Sobrien false, /* partial_inplace */ 59389857Sobrien 0, /* src_mask */ 59489857Sobrien 0xffff, /* dst_mask */ 59589857Sobrien false), /* pcrel_offset */ 59689857Sobrien 59789857Sobrien /* Like R_PPC64_ADDR16_HA, but referring to the PLT table entry for 59889857Sobrien the symbol. */ 59989857Sobrien HOWTO (R_PPC64_PLT16_HA, /* type */ 60089857Sobrien 16, /* rightshift */ 60189857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 60289857Sobrien 16, /* bitsize */ 60389857Sobrien false, /* pc_relative */ 60489857Sobrien 0, /* bitpos */ 60589857Sobrien complain_overflow_dont, /* complain_on_overflow */ 60699461Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 60789857Sobrien "R_PPC64_PLT16_HA", /* name */ 60889857Sobrien false, /* partial_inplace */ 60989857Sobrien 0, /* src_mask */ 61089857Sobrien 0xffff, /* dst_mask */ 61189857Sobrien false), /* pcrel_offset */ 61289857Sobrien 61399461Sobrien /* 16-bit section relative relocation. */ 61489857Sobrien HOWTO (R_PPC64_SECTOFF, /* type */ 61589857Sobrien 0, /* rightshift */ 61699461Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 61799461Sobrien 16, /* bitsize */ 61899461Sobrien false, /* pc_relative */ 61989857Sobrien 0, /* bitpos */ 62089857Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 62199461Sobrien ppc64_elf_sectoff_reloc, /* special_function */ 62289857Sobrien "R_PPC64_SECTOFF", /* name */ 62389857Sobrien false, /* partial_inplace */ 62489857Sobrien 0, /* src_mask */ 62599461Sobrien 0xffff, /* dst_mask */ 62699461Sobrien false), /* pcrel_offset */ 62789857Sobrien 62899461Sobrien /* Like R_PPC64_SECTOFF, but no overflow warning. */ 62989857Sobrien HOWTO (R_PPC64_SECTOFF_LO, /* type */ 63089857Sobrien 0, /* rightshift */ 63189857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 63289857Sobrien 16, /* bitsize */ 63389857Sobrien false, /* pc_relative */ 63489857Sobrien 0, /* bitpos */ 63589857Sobrien complain_overflow_dont, /* complain_on_overflow */ 63699461Sobrien ppc64_elf_sectoff_reloc, /* special_function */ 63789857Sobrien "R_PPC64_SECTOFF_LO", /* name */ 63889857Sobrien false, /* partial_inplace */ 63989857Sobrien 0, /* src_mask */ 64089857Sobrien 0xffff, /* dst_mask */ 64189857Sobrien false), /* pcrel_offset */ 64289857Sobrien 64389857Sobrien /* 16-bit upper half section relative relocation. */ 64489857Sobrien HOWTO (R_PPC64_SECTOFF_HI, /* type */ 64589857Sobrien 16, /* rightshift */ 64689857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 64789857Sobrien 16, /* bitsize */ 64889857Sobrien false, /* pc_relative */ 64989857Sobrien 0, /* bitpos */ 65089857Sobrien complain_overflow_dont, /* complain_on_overflow */ 65199461Sobrien ppc64_elf_sectoff_reloc, /* special_function */ 65289857Sobrien "R_PPC64_SECTOFF_HI", /* name */ 65389857Sobrien false, /* partial_inplace */ 65489857Sobrien 0, /* src_mask */ 65589857Sobrien 0xffff, /* dst_mask */ 65689857Sobrien false), /* pcrel_offset */ 65789857Sobrien 65889857Sobrien /* 16-bit upper half adjusted section relative relocation. */ 65989857Sobrien HOWTO (R_PPC64_SECTOFF_HA, /* type */ 66089857Sobrien 16, /* rightshift */ 66189857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 66289857Sobrien 16, /* bitsize */ 66389857Sobrien false, /* pc_relative */ 66489857Sobrien 0, /* bitpos */ 66589857Sobrien complain_overflow_dont, /* complain_on_overflow */ 66699461Sobrien ppc64_elf_sectoff_ha_reloc, /* special_function */ 66789857Sobrien "R_PPC64_SECTOFF_HA", /* name */ 66889857Sobrien false, /* partial_inplace */ 66989857Sobrien 0, /* src_mask */ 67089857Sobrien 0xffff, /* dst_mask */ 67189857Sobrien false), /* pcrel_offset */ 67289857Sobrien 67389857Sobrien /* Like R_PPC64_REL24 without touching the two least significant 67499461Sobrien bits. Should have been named R_PPC64_REL30! */ 67589857Sobrien HOWTO (R_PPC64_ADDR30, /* type */ 67689857Sobrien 2, /* rightshift */ 67789857Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 67889857Sobrien 30, /* bitsize */ 67989857Sobrien true, /* pc_relative */ 68089857Sobrien 0, /* bitpos */ 68189857Sobrien complain_overflow_dont, /* complain_on_overflow */ 68289857Sobrien bfd_elf_generic_reloc, /* special_function */ 68389857Sobrien "R_PPC64_ADDR30", /* name */ 68489857Sobrien false, /* partial_inplace */ 68589857Sobrien 0, /* src_mask */ 68689857Sobrien 0xfffffffc, /* dst_mask */ 68789857Sobrien true), /* pcrel_offset */ 68889857Sobrien 68989857Sobrien /* Relocs in the 64-bit PowerPC ELF ABI, not in the 32-bit ABI. */ 69089857Sobrien 69189857Sobrien /* A standard 64-bit relocation. */ 69289857Sobrien HOWTO (R_PPC64_ADDR64, /* type */ 69389857Sobrien 0, /* rightshift */ 69489857Sobrien 4, /* size (0=byte, 1=short, 2=long, 4=64 bits) */ 69589857Sobrien 64, /* bitsize */ 69689857Sobrien false, /* pc_relative */ 69789857Sobrien 0, /* bitpos */ 69889857Sobrien complain_overflow_dont, /* complain_on_overflow */ 69989857Sobrien bfd_elf_generic_reloc, /* special_function */ 70089857Sobrien "R_PPC64_ADDR64", /* name */ 70189857Sobrien false, /* partial_inplace */ 70289857Sobrien 0, /* src_mask */ 703104834Sobrien ONES (64), /* dst_mask */ 70489857Sobrien false), /* pcrel_offset */ 70589857Sobrien 70689857Sobrien /* The bits 32-47 of an address. */ 70789857Sobrien HOWTO (R_PPC64_ADDR16_HIGHER, /* type */ 70889857Sobrien 32, /* rightshift */ 70989857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 71089857Sobrien 16, /* bitsize */ 71189857Sobrien false, /* pc_relative */ 71289857Sobrien 0, /* bitpos */ 71389857Sobrien complain_overflow_dont, /* complain_on_overflow */ 71489857Sobrien bfd_elf_generic_reloc, /* special_function */ 71589857Sobrien "R_PPC64_ADDR16_HIGHER", /* name */ 71689857Sobrien false, /* partial_inplace */ 71789857Sobrien 0, /* src_mask */ 71889857Sobrien 0xffff, /* dst_mask */ 71989857Sobrien false), /* pcrel_offset */ 72089857Sobrien 72189857Sobrien /* The bits 32-47 of an address, plus 1 if the contents of the low 72289857Sobrien 16 bits, treated as a signed number, is negative. */ 72389857Sobrien HOWTO (R_PPC64_ADDR16_HIGHERA, /* type */ 72489857Sobrien 32, /* rightshift */ 72589857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 72689857Sobrien 16, /* bitsize */ 72789857Sobrien false, /* pc_relative */ 72889857Sobrien 0, /* bitpos */ 72989857Sobrien complain_overflow_dont, /* complain_on_overflow */ 73099461Sobrien ppc64_elf_ha_reloc, /* special_function */ 73189857Sobrien "R_PPC64_ADDR16_HIGHERA", /* name */ 73289857Sobrien false, /* partial_inplace */ 73389857Sobrien 0, /* src_mask */ 73489857Sobrien 0xffff, /* dst_mask */ 73589857Sobrien false), /* pcrel_offset */ 73689857Sobrien 73789857Sobrien /* The bits 48-63 of an address. */ 73889857Sobrien HOWTO (R_PPC64_ADDR16_HIGHEST,/* type */ 73989857Sobrien 48, /* rightshift */ 74089857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 74189857Sobrien 16, /* bitsize */ 74289857Sobrien false, /* pc_relative */ 74389857Sobrien 0, /* bitpos */ 74489857Sobrien complain_overflow_dont, /* complain_on_overflow */ 74589857Sobrien bfd_elf_generic_reloc, /* special_function */ 74689857Sobrien "R_PPC64_ADDR16_HIGHEST", /* name */ 74789857Sobrien false, /* partial_inplace */ 74889857Sobrien 0, /* src_mask */ 74989857Sobrien 0xffff, /* dst_mask */ 75089857Sobrien false), /* pcrel_offset */ 75189857Sobrien 75289857Sobrien /* The bits 48-63 of an address, plus 1 if the contents of the low 75389857Sobrien 16 bits, treated as a signed number, is negative. */ 75489857Sobrien HOWTO (R_PPC64_ADDR16_HIGHESTA,/* type */ 75589857Sobrien 48, /* rightshift */ 75689857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 75789857Sobrien 16, /* bitsize */ 75889857Sobrien false, /* pc_relative */ 75989857Sobrien 0, /* bitpos */ 76089857Sobrien complain_overflow_dont, /* complain_on_overflow */ 76199461Sobrien ppc64_elf_ha_reloc, /* special_function */ 76289857Sobrien "R_PPC64_ADDR16_HIGHESTA", /* name */ 76389857Sobrien false, /* partial_inplace */ 76489857Sobrien 0, /* src_mask */ 76589857Sobrien 0xffff, /* dst_mask */ 76689857Sobrien false), /* pcrel_offset */ 76789857Sobrien 76889857Sobrien /* Like ADDR64, but may be unaligned. */ 76989857Sobrien HOWTO (R_PPC64_UADDR64, /* type */ 77089857Sobrien 0, /* rightshift */ 77189857Sobrien 4, /* size (0=byte, 1=short, 2=long, 4=64 bits) */ 77289857Sobrien 64, /* bitsize */ 77389857Sobrien false, /* pc_relative */ 77489857Sobrien 0, /* bitpos */ 77589857Sobrien complain_overflow_dont, /* complain_on_overflow */ 77689857Sobrien bfd_elf_generic_reloc, /* special_function */ 77789857Sobrien "R_PPC64_UADDR64", /* name */ 77889857Sobrien false, /* partial_inplace */ 77989857Sobrien 0, /* src_mask */ 780104834Sobrien ONES (64), /* dst_mask */ 78189857Sobrien false), /* pcrel_offset */ 78289857Sobrien 78389857Sobrien /* 64-bit relative relocation. */ 78489857Sobrien HOWTO (R_PPC64_REL64, /* type */ 78589857Sobrien 0, /* rightshift */ 78689857Sobrien 4, /* size (0=byte, 1=short, 2=long, 4=64 bits) */ 78789857Sobrien 64, /* bitsize */ 78889857Sobrien true, /* pc_relative */ 78989857Sobrien 0, /* bitpos */ 79089857Sobrien complain_overflow_dont, /* complain_on_overflow */ 79189857Sobrien bfd_elf_generic_reloc, /* special_function */ 79289857Sobrien "R_PPC64_REL64", /* name */ 79389857Sobrien false, /* partial_inplace */ 79489857Sobrien 0, /* src_mask */ 795104834Sobrien ONES (64), /* dst_mask */ 79689857Sobrien true), /* pcrel_offset */ 79789857Sobrien 798104834Sobrien /* 64-bit relocation to the symbol's procedure linkage table. */ 79989857Sobrien HOWTO (R_PPC64_PLT64, /* type */ 80089857Sobrien 0, /* rightshift */ 80189857Sobrien 4, /* size (0=byte, 1=short, 2=long, 4=64 bits) */ 80289857Sobrien 64, /* bitsize */ 80389857Sobrien false, /* pc_relative */ 80489857Sobrien 0, /* bitpos */ 80589857Sobrien complain_overflow_dont, /* complain_on_overflow */ 80699461Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 80789857Sobrien "R_PPC64_PLT64", /* name */ 80889857Sobrien false, /* partial_inplace */ 80989857Sobrien 0, /* src_mask */ 810104834Sobrien ONES (64), /* dst_mask */ 81189857Sobrien false), /* pcrel_offset */ 81289857Sobrien 81389857Sobrien /* 64-bit PC relative relocation to the symbol's procedure linkage 81489857Sobrien table. */ 81589857Sobrien /* FIXME: R_PPC64_PLTREL64 not supported. */ 81689857Sobrien HOWTO (R_PPC64_PLTREL64, /* type */ 81789857Sobrien 0, /* rightshift */ 81889857Sobrien 4, /* size (0=byte, 1=short, 2=long, 4=64 bits) */ 81989857Sobrien 64, /* bitsize */ 82089857Sobrien true, /* pc_relative */ 82189857Sobrien 0, /* bitpos */ 82289857Sobrien complain_overflow_dont, /* complain_on_overflow */ 82399461Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 82489857Sobrien "R_PPC64_PLTREL64", /* name */ 82589857Sobrien false, /* partial_inplace */ 82689857Sobrien 0, /* src_mask */ 827104834Sobrien ONES (64), /* dst_mask */ 82889857Sobrien true), /* pcrel_offset */ 82989857Sobrien 83089857Sobrien /* 16 bit TOC-relative relocation. */ 83189857Sobrien 83289857Sobrien /* R_PPC64_TOC16 47 half16* S + A - .TOC. */ 83389857Sobrien HOWTO (R_PPC64_TOC16, /* type */ 83489857Sobrien 0, /* rightshift */ 83589857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 83689857Sobrien 16, /* bitsize */ 83789857Sobrien false, /* pc_relative */ 83889857Sobrien 0, /* bitpos */ 83989857Sobrien complain_overflow_signed, /* complain_on_overflow */ 84099461Sobrien ppc64_elf_toc_reloc, /* special_function */ 84189857Sobrien "R_PPC64_TOC16", /* name */ 84289857Sobrien false, /* partial_inplace */ 84389857Sobrien 0, /* src_mask */ 84489857Sobrien 0xffff, /* dst_mask */ 84589857Sobrien false), /* pcrel_offset */ 84689857Sobrien 84789857Sobrien /* 16 bit TOC-relative relocation without overflow. */ 84889857Sobrien 84989857Sobrien /* R_PPC64_TOC16_LO 48 half16 #lo (S + A - .TOC.) */ 85089857Sobrien HOWTO (R_PPC64_TOC16_LO, /* type */ 85189857Sobrien 0, /* rightshift */ 85289857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 85389857Sobrien 16, /* bitsize */ 85489857Sobrien false, /* pc_relative */ 85589857Sobrien 0, /* bitpos */ 85689857Sobrien complain_overflow_dont, /* complain_on_overflow */ 85799461Sobrien ppc64_elf_toc_reloc, /* special_function */ 85889857Sobrien "R_PPC64_TOC16_LO", /* name */ 85989857Sobrien false, /* partial_inplace */ 86089857Sobrien 0, /* src_mask */ 86189857Sobrien 0xffff, /* dst_mask */ 86289857Sobrien false), /* pcrel_offset */ 86389857Sobrien 86489857Sobrien /* 16 bit TOC-relative relocation, high 16 bits. */ 86589857Sobrien 86689857Sobrien /* R_PPC64_TOC16_HI 49 half16 #hi (S + A - .TOC.) */ 86789857Sobrien HOWTO (R_PPC64_TOC16_HI, /* type */ 86889857Sobrien 16, /* rightshift */ 86989857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 87089857Sobrien 16, /* bitsize */ 87189857Sobrien false, /* pc_relative */ 87289857Sobrien 0, /* bitpos */ 87389857Sobrien complain_overflow_dont, /* complain_on_overflow */ 87499461Sobrien ppc64_elf_toc_reloc, /* special_function */ 87589857Sobrien "R_PPC64_TOC16_HI", /* name */ 87689857Sobrien false, /* partial_inplace */ 87789857Sobrien 0, /* src_mask */ 87889857Sobrien 0xffff, /* dst_mask */ 87989857Sobrien false), /* pcrel_offset */ 88089857Sobrien 88189857Sobrien /* 16 bit TOC-relative relocation, high 16 bits, plus 1 if the 88289857Sobrien contents of the low 16 bits, treated as a signed number, is 88389857Sobrien negative. */ 88489857Sobrien 88589857Sobrien /* R_PPC64_TOC16_HA 50 half16 #ha (S + A - .TOC.) */ 88689857Sobrien HOWTO (R_PPC64_TOC16_HA, /* type */ 88789857Sobrien 16, /* rightshift */ 88889857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 88989857Sobrien 16, /* bitsize */ 89089857Sobrien false, /* pc_relative */ 89189857Sobrien 0, /* bitpos */ 89289857Sobrien complain_overflow_dont, /* complain_on_overflow */ 89399461Sobrien ppc64_elf_toc_ha_reloc, /* special_function */ 89489857Sobrien "R_PPC64_TOC16_HA", /* name */ 89589857Sobrien false, /* partial_inplace */ 89689857Sobrien 0, /* src_mask */ 89789857Sobrien 0xffff, /* dst_mask */ 89889857Sobrien false), /* pcrel_offset */ 89989857Sobrien 90089857Sobrien /* 64-bit relocation; insert value of TOC base (.TOC.). */ 90189857Sobrien 90289857Sobrien /* R_PPC64_TOC 51 doubleword64 .TOC. */ 90389857Sobrien HOWTO (R_PPC64_TOC, /* type */ 90489857Sobrien 0, /* rightshift */ 90589857Sobrien 4, /* size (0=byte, 1=short, 2=long, 4=64 bits) */ 90689857Sobrien 64, /* bitsize */ 90789857Sobrien false, /* pc_relative */ 90889857Sobrien 0, /* bitpos */ 90989857Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 91099461Sobrien ppc64_elf_toc64_reloc, /* special_function */ 91189857Sobrien "R_PPC64_TOC", /* name */ 91289857Sobrien false, /* partial_inplace */ 91389857Sobrien 0, /* src_mask */ 914104834Sobrien ONES (64), /* dst_mask */ 91589857Sobrien false), /* pcrel_offset */ 91689857Sobrien 91789857Sobrien /* Like R_PPC64_GOT16, but also informs the link editor that the 91889857Sobrien value to relocate may (!) refer to a PLT entry which the link 91989857Sobrien editor (a) may replace with the symbol value. If the link editor 92089857Sobrien is unable to fully resolve the symbol, it may (b) create a PLT 92189857Sobrien entry and store the address to the new PLT entry in the GOT. 92289857Sobrien This permits lazy resolution of function symbols at run time. 92389857Sobrien The link editor may also skip all of this and just (c) emit a 92489857Sobrien R_PPC64_GLOB_DAT to tie the symbol to the GOT entry. */ 92589857Sobrien /* FIXME: R_PPC64_PLTGOT16 not implemented. */ 92689857Sobrien HOWTO (R_PPC64_PLTGOT16, /* type */ 92789857Sobrien 0, /* rightshift */ 92889857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 92989857Sobrien 16, /* bitsize */ 93089857Sobrien false, /* pc_relative */ 93189857Sobrien 0, /* bitpos */ 93289857Sobrien complain_overflow_signed, /* complain_on_overflow */ 93399461Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 93489857Sobrien "R_PPC64_PLTGOT16", /* name */ 93589857Sobrien false, /* partial_inplace */ 93689857Sobrien 0, /* src_mask */ 93789857Sobrien 0xffff, /* dst_mask */ 93889857Sobrien false), /* pcrel_offset */ 93989857Sobrien 94089857Sobrien /* Like R_PPC64_PLTGOT16, but without overflow. */ 94189857Sobrien /* FIXME: R_PPC64_PLTGOT16_LO not implemented. */ 94289857Sobrien HOWTO (R_PPC64_PLTGOT16_LO, /* type */ 94389857Sobrien 0, /* rightshift */ 94489857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 94589857Sobrien 16, /* bitsize */ 94689857Sobrien false, /* pc_relative */ 94789857Sobrien 0, /* bitpos */ 94889857Sobrien complain_overflow_dont, /* complain_on_overflow */ 94999461Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 95089857Sobrien "R_PPC64_PLTGOT16_LO", /* name */ 95189857Sobrien false, /* partial_inplace */ 95289857Sobrien 0, /* src_mask */ 95389857Sobrien 0xffff, /* dst_mask */ 95489857Sobrien false), /* pcrel_offset */ 95589857Sobrien 95689857Sobrien /* Like R_PPC64_PLT_GOT16, but using bits 16-31 of the address. */ 95789857Sobrien /* FIXME: R_PPC64_PLTGOT16_HI not implemented. */ 95889857Sobrien HOWTO (R_PPC64_PLTGOT16_HI, /* type */ 95989857Sobrien 16, /* rightshift */ 96089857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 96189857Sobrien 16, /* bitsize */ 96289857Sobrien false, /* pc_relative */ 96389857Sobrien 0, /* bitpos */ 96489857Sobrien complain_overflow_dont, /* complain_on_overflow */ 96599461Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 96689857Sobrien "R_PPC64_PLTGOT16_HI", /* name */ 96789857Sobrien false, /* partial_inplace */ 96889857Sobrien 0, /* src_mask */ 96989857Sobrien 0xffff, /* dst_mask */ 97089857Sobrien false), /* pcrel_offset */ 97189857Sobrien 97289857Sobrien /* Like R_PPC64_PLT_GOT16, but using bits 16-31 of the address, plus 97389857Sobrien 1 if the contents of the low 16 bits, treated as a signed number, 97489857Sobrien is negative. */ 97589857Sobrien /* FIXME: R_PPC64_PLTGOT16_HA not implemented. */ 97689857Sobrien HOWTO (R_PPC64_PLTGOT16_HA, /* type */ 97789857Sobrien 16, /* rightshift */ 97889857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 97989857Sobrien 16, /* bitsize */ 98089857Sobrien false, /* pc_relative */ 98189857Sobrien 0, /* bitpos */ 98289857Sobrien complain_overflow_dont,/* complain_on_overflow */ 98399461Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 98489857Sobrien "R_PPC64_PLTGOT16_HA", /* name */ 98589857Sobrien false, /* partial_inplace */ 98689857Sobrien 0, /* src_mask */ 98789857Sobrien 0xffff, /* dst_mask */ 98889857Sobrien false), /* pcrel_offset */ 98989857Sobrien 99089857Sobrien /* Like R_PPC64_ADDR16, but for instructions with a DS field. */ 99189857Sobrien HOWTO (R_PPC64_ADDR16_DS, /* type */ 99289857Sobrien 0, /* rightshift */ 99389857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 99489857Sobrien 16, /* bitsize */ 99589857Sobrien false, /* pc_relative */ 99689857Sobrien 0, /* bitpos */ 99789857Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 99889857Sobrien bfd_elf_generic_reloc, /* special_function */ 99989857Sobrien "R_PPC64_ADDR16_DS", /* name */ 100089857Sobrien false, /* partial_inplace */ 100189857Sobrien 0, /* src_mask */ 100289857Sobrien 0xfffc, /* dst_mask */ 100389857Sobrien false), /* pcrel_offset */ 100489857Sobrien 100589857Sobrien /* Like R_PPC64_ADDR16_LO, but for instructions with a DS field. */ 100689857Sobrien HOWTO (R_PPC64_ADDR16_LO_DS, /* type */ 100789857Sobrien 0, /* rightshift */ 100889857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 100989857Sobrien 16, /* bitsize */ 101089857Sobrien false, /* pc_relative */ 101189857Sobrien 0, /* bitpos */ 101289857Sobrien complain_overflow_dont,/* complain_on_overflow */ 101389857Sobrien bfd_elf_generic_reloc, /* special_function */ 101489857Sobrien "R_PPC64_ADDR16_LO_DS",/* name */ 101589857Sobrien false, /* partial_inplace */ 101689857Sobrien 0, /* src_mask */ 101789857Sobrien 0xfffc, /* dst_mask */ 101889857Sobrien false), /* pcrel_offset */ 101989857Sobrien 102089857Sobrien /* Like R_PPC64_GOT16, but for instructions with a DS field. */ 102189857Sobrien HOWTO (R_PPC64_GOT16_DS, /* type */ 102289857Sobrien 0, /* rightshift */ 102389857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 102489857Sobrien 16, /* bitsize */ 102589857Sobrien false, /* pc_relative */ 102689857Sobrien 0, /* bitpos */ 102789857Sobrien complain_overflow_signed, /* complain_on_overflow */ 102899461Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 102989857Sobrien "R_PPC64_GOT16_DS", /* name */ 103089857Sobrien false, /* partial_inplace */ 103189857Sobrien 0, /* src_mask */ 103289857Sobrien 0xfffc, /* dst_mask */ 103389857Sobrien false), /* pcrel_offset */ 103489857Sobrien 103589857Sobrien /* Like R_PPC64_GOT16_LO, but for instructions with a DS field. */ 103689857Sobrien HOWTO (R_PPC64_GOT16_LO_DS, /* type */ 103789857Sobrien 0, /* rightshift */ 103889857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 103989857Sobrien 16, /* bitsize */ 104089857Sobrien false, /* pc_relative */ 104189857Sobrien 0, /* bitpos */ 104289857Sobrien complain_overflow_dont, /* complain_on_overflow */ 104399461Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 104489857Sobrien "R_PPC64_GOT16_LO_DS", /* name */ 104589857Sobrien false, /* partial_inplace */ 104689857Sobrien 0, /* src_mask */ 104789857Sobrien 0xfffc, /* dst_mask */ 104889857Sobrien false), /* pcrel_offset */ 104989857Sobrien 105089857Sobrien /* Like R_PPC64_PLT16_LO, but for instructions with a DS field. */ 105189857Sobrien HOWTO (R_PPC64_PLT16_LO_DS, /* type */ 105289857Sobrien 0, /* rightshift */ 105389857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 105489857Sobrien 16, /* bitsize */ 105589857Sobrien false, /* pc_relative */ 105689857Sobrien 0, /* bitpos */ 105789857Sobrien complain_overflow_dont, /* complain_on_overflow */ 105899461Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 105989857Sobrien "R_PPC64_PLT16_LO_DS", /* name */ 106089857Sobrien false, /* partial_inplace */ 106189857Sobrien 0, /* src_mask */ 106289857Sobrien 0xfffc, /* dst_mask */ 106389857Sobrien false), /* pcrel_offset */ 106489857Sobrien 106589857Sobrien /* Like R_PPC64_SECTOFF, but for instructions with a DS field. */ 106689857Sobrien HOWTO (R_PPC64_SECTOFF_DS, /* type */ 106789857Sobrien 0, /* rightshift */ 106899461Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 106999461Sobrien 16, /* bitsize */ 107099461Sobrien false, /* pc_relative */ 107189857Sobrien 0, /* bitpos */ 107289857Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 107399461Sobrien ppc64_elf_sectoff_reloc, /* special_function */ 107489857Sobrien "R_PPC64_SECTOFF_DS", /* name */ 107589857Sobrien false, /* partial_inplace */ 107689857Sobrien 0, /* src_mask */ 107799461Sobrien 0xfffc, /* dst_mask */ 107899461Sobrien false), /* pcrel_offset */ 107989857Sobrien 108089857Sobrien /* Like R_PPC64_SECTOFF_LO, but for instructions with a DS field. */ 108189857Sobrien HOWTO (R_PPC64_SECTOFF_LO_DS, /* type */ 108289857Sobrien 0, /* rightshift */ 108389857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 108489857Sobrien 16, /* bitsize */ 108589857Sobrien false, /* pc_relative */ 108689857Sobrien 0, /* bitpos */ 108789857Sobrien complain_overflow_dont, /* complain_on_overflow */ 108899461Sobrien ppc64_elf_sectoff_reloc, /* special_function */ 108989857Sobrien "R_PPC64_SECTOFF_LO_DS",/* name */ 109089857Sobrien false, /* partial_inplace */ 109189857Sobrien 0, /* src_mask */ 109289857Sobrien 0xfffc, /* dst_mask */ 109389857Sobrien false), /* pcrel_offset */ 109489857Sobrien 109589857Sobrien /* Like R_PPC64_TOC16, but for instructions with a DS field. */ 109689857Sobrien HOWTO (R_PPC64_TOC16_DS, /* type */ 109789857Sobrien 0, /* rightshift */ 109889857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 109989857Sobrien 16, /* bitsize */ 110089857Sobrien false, /* pc_relative */ 110189857Sobrien 0, /* bitpos */ 110289857Sobrien complain_overflow_signed, /* complain_on_overflow */ 110399461Sobrien ppc64_elf_toc_reloc, /* special_function */ 110489857Sobrien "R_PPC64_TOC16_DS", /* name */ 110589857Sobrien false, /* partial_inplace */ 110689857Sobrien 0, /* src_mask */ 110789857Sobrien 0xfffc, /* dst_mask */ 110889857Sobrien false), /* pcrel_offset */ 110989857Sobrien 111089857Sobrien /* Like R_PPC64_TOC16_LO, but for instructions with a DS field. */ 111189857Sobrien HOWTO (R_PPC64_TOC16_LO_DS, /* type */ 111289857Sobrien 0, /* rightshift */ 111389857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 111489857Sobrien 16, /* bitsize */ 111589857Sobrien false, /* pc_relative */ 111689857Sobrien 0, /* bitpos */ 111789857Sobrien complain_overflow_dont, /* complain_on_overflow */ 111899461Sobrien ppc64_elf_toc_reloc, /* special_function */ 111989857Sobrien "R_PPC64_TOC16_LO_DS", /* name */ 112089857Sobrien false, /* partial_inplace */ 112189857Sobrien 0, /* src_mask */ 112289857Sobrien 0xfffc, /* dst_mask */ 112389857Sobrien false), /* pcrel_offset */ 112489857Sobrien 112589857Sobrien /* Like R_PPC64_PLTGOT16, but for instructions with a DS field. */ 112689857Sobrien /* FIXME: R_PPC64_PLTGOT16_DS not implemented. */ 112789857Sobrien HOWTO (R_PPC64_PLTGOT16_DS, /* type */ 112889857Sobrien 0, /* rightshift */ 112989857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 113089857Sobrien 16, /* bitsize */ 113189857Sobrien false, /* pc_relative */ 113289857Sobrien 0, /* bitpos */ 113389857Sobrien complain_overflow_signed, /* complain_on_overflow */ 113499461Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 113589857Sobrien "R_PPC64_PLTGOT16_DS", /* name */ 113689857Sobrien false, /* partial_inplace */ 113789857Sobrien 0, /* src_mask */ 113889857Sobrien 0xfffc, /* dst_mask */ 113989857Sobrien false), /* pcrel_offset */ 114089857Sobrien 114189857Sobrien /* Like R_PPC64_PLTGOT16_LO, but for instructions with a DS field. */ 114289857Sobrien /* FIXME: R_PPC64_PLTGOT16_LO not implemented. */ 114389857Sobrien HOWTO (R_PPC64_PLTGOT16_LO_DS,/* type */ 114489857Sobrien 0, /* rightshift */ 114589857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 114689857Sobrien 16, /* bitsize */ 114789857Sobrien false, /* pc_relative */ 114889857Sobrien 0, /* bitpos */ 114989857Sobrien complain_overflow_dont, /* complain_on_overflow */ 115099461Sobrien ppc64_elf_unhandled_reloc, /* special_function */ 115189857Sobrien "R_PPC64_PLTGOT16_LO_DS",/* name */ 115289857Sobrien false, /* partial_inplace */ 115389857Sobrien 0, /* src_mask */ 115489857Sobrien 0xfffc, /* dst_mask */ 115589857Sobrien false), /* pcrel_offset */ 115689857Sobrien 115789857Sobrien /* GNU extension to record C++ vtable hierarchy. */ 115889857Sobrien HOWTO (R_PPC64_GNU_VTINHERIT, /* type */ 115989857Sobrien 0, /* rightshift */ 116089857Sobrien 0, /* size (0 = byte, 1 = short, 2 = long) */ 116189857Sobrien 0, /* bitsize */ 116289857Sobrien false, /* pc_relative */ 116389857Sobrien 0, /* bitpos */ 116489857Sobrien complain_overflow_dont, /* complain_on_overflow */ 116589857Sobrien NULL, /* special_function */ 116689857Sobrien "R_PPC64_GNU_VTINHERIT", /* name */ 116789857Sobrien false, /* partial_inplace */ 116889857Sobrien 0, /* src_mask */ 116989857Sobrien 0, /* dst_mask */ 117089857Sobrien false), /* pcrel_offset */ 117189857Sobrien 117289857Sobrien /* GNU extension to record C++ vtable member usage. */ 117389857Sobrien HOWTO (R_PPC64_GNU_VTENTRY, /* type */ 117489857Sobrien 0, /* rightshift */ 117589857Sobrien 0, /* size (0 = byte, 1 = short, 2 = long) */ 117689857Sobrien 0, /* bitsize */ 117789857Sobrien false, /* pc_relative */ 117889857Sobrien 0, /* bitpos */ 117989857Sobrien complain_overflow_dont, /* complain_on_overflow */ 118089857Sobrien NULL, /* special_function */ 118189857Sobrien "R_PPC64_GNU_VTENTRY", /* name */ 118289857Sobrien false, /* partial_inplace */ 118389857Sobrien 0, /* src_mask */ 118489857Sobrien 0, /* dst_mask */ 118589857Sobrien false), /* pcrel_offset */ 118689857Sobrien}; 118789857Sobrien 118889857Sobrien 118989857Sobrien/* Initialize the ppc64_elf_howto_table, so that linear accesses can 119089857Sobrien be done. */ 119189857Sobrien 119289857Sobrienstatic void 119389857Sobrienppc_howto_init () 119489857Sobrien{ 119589857Sobrien unsigned int i, type; 119689857Sobrien 119789857Sobrien for (i = 0; 119889857Sobrien i < sizeof (ppc64_elf_howto_raw) / sizeof (ppc64_elf_howto_raw[0]); 119989857Sobrien i++) 120089857Sobrien { 120189857Sobrien type = ppc64_elf_howto_raw[i].type; 120289857Sobrien BFD_ASSERT (type < (sizeof (ppc64_elf_howto_table) 120389857Sobrien / sizeof (ppc64_elf_howto_table[0]))); 120489857Sobrien ppc64_elf_howto_table[type] = &ppc64_elf_howto_raw[i]; 120589857Sobrien } 120689857Sobrien} 120789857Sobrien 120889857Sobrienstatic reloc_howto_type * 120989857Sobrienppc64_elf_reloc_type_lookup (abfd, code) 121089857Sobrien bfd *abfd ATTRIBUTE_UNUSED; 121189857Sobrien bfd_reloc_code_real_type code; 121289857Sobrien{ 121389857Sobrien enum elf_ppc_reloc_type ppc_reloc = R_PPC_NONE; 121489857Sobrien 121589857Sobrien if (!ppc64_elf_howto_table[R_PPC64_ADDR32]) 121689857Sobrien /* Initialize howto table if needed. */ 121789857Sobrien ppc_howto_init (); 121889857Sobrien 121989857Sobrien switch ((int) code) 122089857Sobrien { 122189857Sobrien default: 122289857Sobrien return (reloc_howto_type *) NULL; 122389857Sobrien 122489857Sobrien case BFD_RELOC_NONE: ppc_reloc = R_PPC64_NONE; 122589857Sobrien break; 122689857Sobrien case BFD_RELOC_32: ppc_reloc = R_PPC64_ADDR32; 122789857Sobrien break; 122889857Sobrien case BFD_RELOC_PPC_BA26: ppc_reloc = R_PPC64_ADDR24; 122989857Sobrien break; 123089857Sobrien case BFD_RELOC_16: ppc_reloc = R_PPC64_ADDR16; 123189857Sobrien break; 123289857Sobrien case BFD_RELOC_LO16: ppc_reloc = R_PPC64_ADDR16_LO; 123389857Sobrien break; 123489857Sobrien case BFD_RELOC_HI16: ppc_reloc = R_PPC64_ADDR16_HI; 123589857Sobrien break; 123689857Sobrien case BFD_RELOC_HI16_S: ppc_reloc = R_PPC64_ADDR16_HA; 123789857Sobrien break; 123889857Sobrien case BFD_RELOC_PPC_BA16: ppc_reloc = R_PPC64_ADDR14; 123989857Sobrien break; 124089857Sobrien case BFD_RELOC_PPC_BA16_BRTAKEN: ppc_reloc = R_PPC64_ADDR14_BRTAKEN; 124189857Sobrien break; 124289857Sobrien case BFD_RELOC_PPC_BA16_BRNTAKEN: ppc_reloc = R_PPC64_ADDR14_BRNTAKEN; 124389857Sobrien break; 124489857Sobrien case BFD_RELOC_PPC_B26: ppc_reloc = R_PPC64_REL24; 124589857Sobrien break; 124689857Sobrien case BFD_RELOC_PPC_B16: ppc_reloc = R_PPC64_REL14; 124789857Sobrien break; 124889857Sobrien case BFD_RELOC_PPC_B16_BRTAKEN: ppc_reloc = R_PPC64_REL14_BRTAKEN; 124989857Sobrien break; 125089857Sobrien case BFD_RELOC_PPC_B16_BRNTAKEN: ppc_reloc = R_PPC64_REL14_BRNTAKEN; 125189857Sobrien break; 125289857Sobrien case BFD_RELOC_16_GOTOFF: ppc_reloc = R_PPC64_GOT16; 125389857Sobrien break; 125489857Sobrien case BFD_RELOC_LO16_GOTOFF: ppc_reloc = R_PPC64_GOT16_LO; 125589857Sobrien break; 125689857Sobrien case BFD_RELOC_HI16_GOTOFF: ppc_reloc = R_PPC64_GOT16_HI; 125789857Sobrien break; 125889857Sobrien case BFD_RELOC_HI16_S_GOTOFF: ppc_reloc = R_PPC64_GOT16_HA; 125989857Sobrien break; 126089857Sobrien case BFD_RELOC_PPC_COPY: ppc_reloc = R_PPC64_COPY; 126189857Sobrien break; 126289857Sobrien case BFD_RELOC_PPC_GLOB_DAT: ppc_reloc = R_PPC64_GLOB_DAT; 126389857Sobrien break; 126489857Sobrien case BFD_RELOC_32_PCREL: ppc_reloc = R_PPC64_REL32; 126589857Sobrien break; 126689857Sobrien case BFD_RELOC_32_PLTOFF: ppc_reloc = R_PPC64_PLT32; 126789857Sobrien break; 126889857Sobrien case BFD_RELOC_32_PLT_PCREL: ppc_reloc = R_PPC64_PLTREL32; 126989857Sobrien break; 127089857Sobrien case BFD_RELOC_LO16_PLTOFF: ppc_reloc = R_PPC64_PLT16_LO; 127189857Sobrien break; 127289857Sobrien case BFD_RELOC_HI16_PLTOFF: ppc_reloc = R_PPC64_PLT16_HI; 127389857Sobrien break; 127489857Sobrien case BFD_RELOC_HI16_S_PLTOFF: ppc_reloc = R_PPC64_PLT16_HA; 127589857Sobrien break; 127699461Sobrien case BFD_RELOC_16_BASEREL: ppc_reloc = R_PPC64_SECTOFF; 127789857Sobrien break; 127889857Sobrien case BFD_RELOC_LO16_BASEREL: ppc_reloc = R_PPC64_SECTOFF_LO; 127989857Sobrien break; 128089857Sobrien case BFD_RELOC_HI16_BASEREL: ppc_reloc = R_PPC64_SECTOFF_HI; 128189857Sobrien break; 128289857Sobrien case BFD_RELOC_HI16_S_BASEREL: ppc_reloc = R_PPC64_SECTOFF_HA; 128389857Sobrien break; 128489857Sobrien case BFD_RELOC_CTOR: ppc_reloc = R_PPC64_ADDR64; 128589857Sobrien break; 128689857Sobrien case BFD_RELOC_64: ppc_reloc = R_PPC64_ADDR64; 128789857Sobrien break; 128889857Sobrien case BFD_RELOC_PPC64_HIGHER: ppc_reloc = R_PPC64_ADDR16_HIGHER; 128989857Sobrien break; 129089857Sobrien case BFD_RELOC_PPC64_HIGHER_S: ppc_reloc = R_PPC64_ADDR16_HIGHERA; 129189857Sobrien break; 129289857Sobrien case BFD_RELOC_PPC64_HIGHEST: ppc_reloc = R_PPC64_ADDR16_HIGHEST; 129389857Sobrien break; 129489857Sobrien case BFD_RELOC_PPC64_HIGHEST_S: ppc_reloc = R_PPC64_ADDR16_HIGHESTA; 129589857Sobrien break; 129689857Sobrien case BFD_RELOC_64_PCREL: ppc_reloc = R_PPC64_REL64; 129789857Sobrien break; 129889857Sobrien case BFD_RELOC_64_PLTOFF: ppc_reloc = R_PPC64_PLT64; 129989857Sobrien break; 130089857Sobrien case BFD_RELOC_64_PLT_PCREL: ppc_reloc = R_PPC64_PLTREL64; 130189857Sobrien break; 130289857Sobrien case BFD_RELOC_PPC_TOC16: ppc_reloc = R_PPC64_TOC16; 130389857Sobrien break; 130489857Sobrien case BFD_RELOC_PPC64_TOC16_LO: ppc_reloc = R_PPC64_TOC16_LO; 130589857Sobrien break; 130689857Sobrien case BFD_RELOC_PPC64_TOC16_HI: ppc_reloc = R_PPC64_TOC16_HI; 130789857Sobrien break; 130889857Sobrien case BFD_RELOC_PPC64_TOC16_HA: ppc_reloc = R_PPC64_TOC16_HA; 130989857Sobrien break; 131089857Sobrien case BFD_RELOC_PPC64_TOC: ppc_reloc = R_PPC64_TOC; 131189857Sobrien break; 131289857Sobrien case BFD_RELOC_PPC64_PLTGOT16: ppc_reloc = R_PPC64_PLTGOT16; 131389857Sobrien break; 131489857Sobrien case BFD_RELOC_PPC64_PLTGOT16_LO: ppc_reloc = R_PPC64_PLTGOT16_LO; 131589857Sobrien break; 131689857Sobrien case BFD_RELOC_PPC64_PLTGOT16_HI: ppc_reloc = R_PPC64_PLTGOT16_HI; 131789857Sobrien break; 131889857Sobrien case BFD_RELOC_PPC64_PLTGOT16_HA: ppc_reloc = R_PPC64_PLTGOT16_HA; 131989857Sobrien break; 132089857Sobrien case BFD_RELOC_PPC64_ADDR16_DS: ppc_reloc = R_PPC64_ADDR16_DS; 132189857Sobrien break; 132289857Sobrien case BFD_RELOC_PPC64_ADDR16_LO_DS: ppc_reloc = R_PPC64_ADDR16_LO_DS; 132389857Sobrien break; 132489857Sobrien case BFD_RELOC_PPC64_GOT16_DS: ppc_reloc = R_PPC64_GOT16_DS; 132589857Sobrien break; 132689857Sobrien case BFD_RELOC_PPC64_GOT16_LO_DS: ppc_reloc = R_PPC64_GOT16_LO_DS; 132789857Sobrien break; 132889857Sobrien case BFD_RELOC_PPC64_PLT16_LO_DS: ppc_reloc = R_PPC64_PLT16_LO_DS; 132989857Sobrien break; 133089857Sobrien case BFD_RELOC_PPC64_SECTOFF_DS: ppc_reloc = R_PPC64_SECTOFF_DS; 133189857Sobrien break; 133289857Sobrien case BFD_RELOC_PPC64_SECTOFF_LO_DS: ppc_reloc = R_PPC64_SECTOFF_LO_DS; 133389857Sobrien break; 133489857Sobrien case BFD_RELOC_PPC64_TOC16_DS: ppc_reloc = R_PPC64_TOC16_DS; 133589857Sobrien break; 133689857Sobrien case BFD_RELOC_PPC64_TOC16_LO_DS: ppc_reloc = R_PPC64_TOC16_LO_DS; 133789857Sobrien break; 133889857Sobrien case BFD_RELOC_PPC64_PLTGOT16_DS: ppc_reloc = R_PPC64_PLTGOT16_DS; 133989857Sobrien break; 134089857Sobrien case BFD_RELOC_PPC64_PLTGOT16_LO_DS: ppc_reloc = R_PPC64_PLTGOT16_LO_DS; 134189857Sobrien break; 134289857Sobrien case BFD_RELOC_VTABLE_INHERIT: ppc_reloc = R_PPC64_GNU_VTINHERIT; 134389857Sobrien break; 134489857Sobrien case BFD_RELOC_VTABLE_ENTRY: ppc_reloc = R_PPC64_GNU_VTENTRY; 134589857Sobrien break; 134689857Sobrien } 134789857Sobrien 134889857Sobrien return ppc64_elf_howto_table[(int) ppc_reloc]; 134989857Sobrien}; 135089857Sobrien 135189857Sobrien/* Set the howto pointer for a PowerPC ELF reloc. */ 135289857Sobrien 135389857Sobrienstatic void 135489857Sobrienppc64_elf_info_to_howto (abfd, cache_ptr, dst) 135589857Sobrien bfd *abfd ATTRIBUTE_UNUSED; 135689857Sobrien arelent *cache_ptr; 135789857Sobrien Elf64_Internal_Rela *dst; 135889857Sobrien{ 135989857Sobrien unsigned int type; 136089857Sobrien 1361104834Sobrien /* Initialize howto table if needed. */ 136289857Sobrien if (!ppc64_elf_howto_table[R_PPC64_ADDR32]) 136389857Sobrien ppc_howto_init (); 136489857Sobrien 136589857Sobrien type = ELF64_R_TYPE (dst->r_info); 136689857Sobrien BFD_ASSERT (type < (sizeof (ppc64_elf_howto_table) 136789857Sobrien / sizeof (ppc64_elf_howto_table[0]))); 136889857Sobrien cache_ptr->howto = ppc64_elf_howto_table[type]; 136989857Sobrien} 137089857Sobrien 137189857Sobrien/* Handle the R_PPC_ADDR16_HA and similar relocs. */ 137289857Sobrien 137389857Sobrienstatic bfd_reloc_status_type 137499461Sobrienppc64_elf_ha_reloc (abfd, reloc_entry, symbol, data, 137599461Sobrien input_section, output_bfd, error_message) 137699461Sobrien bfd *abfd; 137789857Sobrien arelent *reloc_entry; 137889857Sobrien asymbol *symbol; 137999461Sobrien PTR data; 138089857Sobrien asection *input_section; 138189857Sobrien bfd *output_bfd; 138299461Sobrien char **error_message; 138389857Sobrien{ 138499461Sobrien /* If this is a relocatable link (output_bfd test tells us), just 138599461Sobrien call the generic function. Any adjustment will be done at final 138699461Sobrien link time. */ 138799461Sobrien if (output_bfd != NULL) 1388104834Sobrien return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, 138999461Sobrien input_section, output_bfd, error_message); 139089857Sobrien 139199461Sobrien /* Adjust the addend for sign extension of the low 16 bits. 139299461Sobrien We won't actually be using the low 16 bits, so trashing them 139399461Sobrien doesn't matter. */ 139499461Sobrien reloc_entry->addend += 0x8000; 139599461Sobrien return bfd_reloc_continue; 139699461Sobrien} 139799461Sobrien 139899461Sobrienstatic bfd_reloc_status_type 139999461Sobrienppc64_elf_brtaken_reloc (abfd, reloc_entry, symbol, data, 140099461Sobrien input_section, output_bfd, error_message) 140199461Sobrien bfd *abfd; 140299461Sobrien arelent *reloc_entry; 140399461Sobrien asymbol *symbol; 140499461Sobrien PTR data; 140599461Sobrien asection *input_section; 140699461Sobrien bfd *output_bfd; 140799461Sobrien char **error_message; 140899461Sobrien{ 140999461Sobrien long insn; 141099461Sobrien enum elf_ppc_reloc_type r_type; 141199461Sobrien bfd_size_type octets; 141299461Sobrien /* Disabled until we sort out how ld should choose 'y' vs 'at'. */ 141399461Sobrien boolean is_power4 = false; 141499461Sobrien 141599461Sobrien /* If this is a relocatable link (output_bfd test tells us), just 141699461Sobrien call the generic function. Any adjustment will be done at final 141799461Sobrien link time. */ 141889857Sobrien if (output_bfd != NULL) 1419104834Sobrien return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, 142099461Sobrien input_section, output_bfd, error_message); 142199461Sobrien 142299461Sobrien octets = reloc_entry->address * bfd_octets_per_byte (abfd); 142399461Sobrien insn = bfd_get_32 (abfd, (bfd_byte *) data + octets); 142499461Sobrien insn &= ~(0x01 << 21); 142599461Sobrien r_type = (enum elf_ppc_reloc_type) reloc_entry->howto->type; 142699461Sobrien if (r_type == R_PPC64_ADDR14_BRTAKEN 142799461Sobrien || r_type == R_PPC64_REL14_BRTAKEN) 1428104834Sobrien insn |= 0x01 << 21; /* 'y' or 't' bit, lowest bit of BO field. */ 142999461Sobrien 143099461Sobrien if (is_power4) 143189857Sobrien { 143299461Sobrien /* Set 'a' bit. This is 0b00010 in BO field for branch 143399461Sobrien on CR(BI) insns (BO == 001at or 011at), and 0b01000 143499461Sobrien for branch on CTR insns (BO == 1a00t or 1a01t). */ 143599461Sobrien if ((insn & (0x14 << 21)) == (0x04 << 21)) 143699461Sobrien insn |= 0x02 << 21; 143799461Sobrien else if ((insn & (0x14 << 21)) == (0x10 << 21)) 143899461Sobrien insn |= 0x08 << 21; 143999461Sobrien else 144099461Sobrien return bfd_reloc_continue; 144189857Sobrien } 144299461Sobrien else 144399461Sobrien { 144499461Sobrien bfd_vma target = 0; 144599461Sobrien bfd_vma from; 144689857Sobrien 144799461Sobrien if (!bfd_is_com_section (symbol->section)) 144899461Sobrien target = symbol->value; 144999461Sobrien target += symbol->section->output_section->vma; 145099461Sobrien target += symbol->section->output_offset; 145199461Sobrien target += reloc_entry->addend; 145289857Sobrien 145399461Sobrien from = (reloc_entry->address 145499461Sobrien + input_section->output_offset 145599461Sobrien + input_section->output_section->vma); 145689857Sobrien 145799461Sobrien /* Invert 'y' bit if not the default. */ 145899461Sobrien if ((bfd_signed_vma) (target - from) < 0) 145999461Sobrien insn ^= 0x01 << 21; 146099461Sobrien } 146199461Sobrien bfd_put_32 (abfd, (bfd_vma) insn, (bfd_byte *) data + octets); 146299461Sobrien return bfd_reloc_continue; 146399461Sobrien} 146489857Sobrien 146599461Sobrienstatic bfd_reloc_status_type 146699461Sobrienppc64_elf_sectoff_reloc (abfd, reloc_entry, symbol, data, 146799461Sobrien input_section, output_bfd, error_message) 146899461Sobrien bfd *abfd; 146999461Sobrien arelent *reloc_entry; 147099461Sobrien asymbol *symbol; 147199461Sobrien PTR data; 147299461Sobrien asection *input_section; 147399461Sobrien bfd *output_bfd; 147499461Sobrien char **error_message; 147599461Sobrien{ 147699461Sobrien /* If this is a relocatable link (output_bfd test tells us), just 147799461Sobrien call the generic function. Any adjustment will be done at final 147899461Sobrien link time. */ 147999461Sobrien if (output_bfd != NULL) 1480104834Sobrien return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, 148199461Sobrien input_section, output_bfd, error_message); 148289857Sobrien 148399461Sobrien /* Subtract the symbol section base address. */ 148499461Sobrien reloc_entry->addend -= symbol->section->output_section->vma; 148589857Sobrien return bfd_reloc_continue; 148689857Sobrien} 148789857Sobrien 148899461Sobrienstatic bfd_reloc_status_type 148999461Sobrienppc64_elf_sectoff_ha_reloc (abfd, reloc_entry, symbol, data, 149099461Sobrien input_section, output_bfd, error_message) 149199461Sobrien bfd *abfd; 149299461Sobrien arelent *reloc_entry; 149399461Sobrien asymbol *symbol; 149499461Sobrien PTR data; 149599461Sobrien asection *input_section; 149699461Sobrien bfd *output_bfd; 149799461Sobrien char **error_message; 149899461Sobrien{ 149999461Sobrien /* If this is a relocatable link (output_bfd test tells us), just 150099461Sobrien call the generic function. Any adjustment will be done at final 150199461Sobrien link time. */ 150299461Sobrien if (output_bfd != NULL) 1503104834Sobrien return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, 150499461Sobrien input_section, output_bfd, error_message); 150599461Sobrien 150699461Sobrien /* Subtract the symbol section base address. */ 150799461Sobrien reloc_entry->addend -= symbol->section->output_section->vma; 150899461Sobrien 150999461Sobrien /* Adjust the addend for sign extension of the low 16 bits. */ 151099461Sobrien reloc_entry->addend += 0x8000; 151199461Sobrien return bfd_reloc_continue; 151299461Sobrien} 151399461Sobrien 151499461Sobrienstatic bfd_reloc_status_type 151599461Sobrienppc64_elf_toc_reloc (abfd, reloc_entry, symbol, data, 151699461Sobrien input_section, output_bfd, error_message) 151799461Sobrien bfd *abfd; 151899461Sobrien arelent *reloc_entry; 151999461Sobrien asymbol *symbol; 152099461Sobrien PTR data; 152199461Sobrien asection *input_section; 152299461Sobrien bfd *output_bfd; 152399461Sobrien char **error_message; 152499461Sobrien{ 152599461Sobrien bfd_vma TOCstart; 152699461Sobrien 152799461Sobrien /* If this is a relocatable link (output_bfd test tells us), just 152899461Sobrien call the generic function. Any adjustment will be done at final 152999461Sobrien link time. */ 153099461Sobrien if (output_bfd != NULL) 1531104834Sobrien return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, 153299461Sobrien input_section, output_bfd, error_message); 153399461Sobrien 153499461Sobrien TOCstart = _bfd_get_gp_value (input_section->output_section->owner); 153599461Sobrien if (TOCstart == 0) 153699461Sobrien TOCstart = ppc64_elf_toc (input_section->output_section->owner); 153799461Sobrien 153899461Sobrien /* Subtract the TOC base address. */ 153999461Sobrien reloc_entry->addend -= TOCstart + TOC_BASE_OFF; 154099461Sobrien return bfd_reloc_continue; 154199461Sobrien} 154299461Sobrien 154399461Sobrienstatic bfd_reloc_status_type 154499461Sobrienppc64_elf_toc_ha_reloc (abfd, reloc_entry, symbol, data, 154599461Sobrien input_section, output_bfd, error_message) 154699461Sobrien bfd *abfd; 154799461Sobrien arelent *reloc_entry; 154899461Sobrien asymbol *symbol; 154999461Sobrien PTR data; 155099461Sobrien asection *input_section; 155199461Sobrien bfd *output_bfd; 155299461Sobrien char **error_message; 155399461Sobrien{ 155499461Sobrien bfd_vma TOCstart; 155599461Sobrien 155699461Sobrien /* If this is a relocatable link (output_bfd test tells us), just 155799461Sobrien call the generic function. Any adjustment will be done at final 155899461Sobrien link time. */ 155999461Sobrien if (output_bfd != NULL) 1560104834Sobrien return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, 156199461Sobrien input_section, output_bfd, error_message); 156299461Sobrien 156399461Sobrien TOCstart = _bfd_get_gp_value (input_section->output_section->owner); 156499461Sobrien if (TOCstart == 0) 156599461Sobrien TOCstart = ppc64_elf_toc (input_section->output_section->owner); 156699461Sobrien 156799461Sobrien /* Subtract the TOC base address. */ 156899461Sobrien reloc_entry->addend -= TOCstart + TOC_BASE_OFF; 156999461Sobrien 157099461Sobrien /* Adjust the addend for sign extension of the low 16 bits. */ 157199461Sobrien reloc_entry->addend += 0x8000; 157299461Sobrien return bfd_reloc_continue; 157399461Sobrien} 157499461Sobrien 157599461Sobrienstatic bfd_reloc_status_type 157699461Sobrienppc64_elf_toc64_reloc (abfd, reloc_entry, symbol, data, 157799461Sobrien input_section, output_bfd, error_message) 157899461Sobrien bfd *abfd; 157999461Sobrien arelent *reloc_entry; 158099461Sobrien asymbol *symbol; 158199461Sobrien PTR data; 158299461Sobrien asection *input_section; 158399461Sobrien bfd *output_bfd; 158499461Sobrien char **error_message; 158599461Sobrien{ 158699461Sobrien bfd_vma TOCstart; 158799461Sobrien bfd_size_type octets; 158899461Sobrien 158999461Sobrien /* If this is a relocatable link (output_bfd test tells us), just 159099461Sobrien call the generic function. Any adjustment will be done at final 159199461Sobrien link time. */ 159299461Sobrien if (output_bfd != NULL) 1593104834Sobrien return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, 159499461Sobrien input_section, output_bfd, error_message); 159599461Sobrien 159699461Sobrien TOCstart = _bfd_get_gp_value (input_section->output_section->owner); 159799461Sobrien if (TOCstart == 0) 159899461Sobrien TOCstart = ppc64_elf_toc (input_section->output_section->owner); 159999461Sobrien 160099461Sobrien octets = reloc_entry->address * bfd_octets_per_byte (abfd); 160199461Sobrien bfd_put_64 (abfd, TOCstart + TOC_BASE_OFF, (bfd_byte *) data + octets); 160299461Sobrien return bfd_reloc_ok; 160399461Sobrien} 160499461Sobrien 160599461Sobrienstatic bfd_reloc_status_type 160699461Sobrienppc64_elf_unhandled_reloc (abfd, reloc_entry, symbol, data, 160799461Sobrien input_section, output_bfd, error_message) 160899461Sobrien bfd *abfd; 160999461Sobrien arelent *reloc_entry; 161099461Sobrien asymbol *symbol; 161199461Sobrien PTR data; 161299461Sobrien asection *input_section; 161399461Sobrien bfd *output_bfd; 161499461Sobrien char **error_message; 161599461Sobrien{ 161699461Sobrien /* If this is a relocatable link (output_bfd test tells us), just 161799461Sobrien call the generic function. Any adjustment will be done at final 161899461Sobrien link time. */ 161999461Sobrien if (output_bfd != NULL) 1620104834Sobrien return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, 162199461Sobrien input_section, output_bfd, error_message); 162299461Sobrien 162399461Sobrien if (error_message != NULL) 162499461Sobrien { 162599461Sobrien static char buf[60]; 162699461Sobrien sprintf (buf, "generic linker can't handle %s", 162799461Sobrien reloc_entry->howto->name); 162899461Sobrien *error_message = buf; 162999461Sobrien } 163099461Sobrien return bfd_reloc_dangerous; 163199461Sobrien} 163299461Sobrien 1633104834Sobrien/* Fix bad default arch selected for a 64 bit input bfd when the 1634104834Sobrien default is 32 bit. */ 163589857Sobrien 163689857Sobrienstatic boolean 1637104834Sobrienppc64_elf_object_p (abfd) 163889857Sobrien bfd *abfd; 163989857Sobrien{ 1640104834Sobrien if (abfd->arch_info->the_default && abfd->arch_info->bits_per_word == 32) 1641104834Sobrien { 1642104834Sobrien Elf_Internal_Ehdr *i_ehdr = elf_elfheader (abfd); 164389857Sobrien 1644104834Sobrien if (i_ehdr->e_ident[EI_CLASS] == ELFCLASS64) 1645104834Sobrien { 1646104834Sobrien /* Relies on arch after 32 bit default being 64 bit default. */ 1647104834Sobrien abfd->arch_info = abfd->arch_info->next; 1648104834Sobrien BFD_ASSERT (abfd->arch_info->bits_per_word == 64); 1649104834Sobrien } 1650104834Sobrien } 165189857Sobrien return true; 165289857Sobrien} 165389857Sobrien 165489857Sobrien/* Merge backend specific data from an object file to the output 165589857Sobrien object file when linking. */ 1656104834Sobrien 165789857Sobrienstatic boolean 165889857Sobrienppc64_elf_merge_private_bfd_data (ibfd, obfd) 165989857Sobrien bfd *ibfd; 166089857Sobrien bfd *obfd; 166189857Sobrien{ 166289857Sobrien /* Check if we have the same endianess. */ 166389857Sobrien if (ibfd->xvec->byteorder != obfd->xvec->byteorder 1664107492Sobrien && ibfd->xvec->byteorder != BFD_ENDIAN_UNKNOWN 166589857Sobrien && obfd->xvec->byteorder != BFD_ENDIAN_UNKNOWN) 166689857Sobrien { 166789857Sobrien const char *msg; 166889857Sobrien 166989857Sobrien if (bfd_big_endian (ibfd)) 167089857Sobrien msg = _("%s: compiled for a big endian system and target is little endian"); 167189857Sobrien else 167289857Sobrien msg = _("%s: compiled for a little endian system and target is big endian"); 167389857Sobrien 167489857Sobrien (*_bfd_error_handler) (msg, bfd_archive_filename (ibfd)); 167589857Sobrien 167689857Sobrien bfd_set_error (bfd_error_wrong_format); 167789857Sobrien return false; 167889857Sobrien } 167989857Sobrien 168089857Sobrien return true; 168189857Sobrien} 168289857Sobrien 168389857Sobrien/* The following functions are specific to the ELF linker, while 168489857Sobrien functions above are used generally. Those named ppc64_elf_* are 168589857Sobrien called by the main ELF linker code. They appear in this file more 168689857Sobrien or less in the order in which they are called. eg. 168789857Sobrien ppc64_elf_check_relocs is called early in the link process, 168889857Sobrien ppc64_elf_finish_dynamic_sections is one of the last functions 168989857Sobrien called. 169089857Sobrien 169189857Sobrien PowerPC64-ELF uses a similar scheme to PowerPC64-XCOFF in that 169289857Sobrien functions have both a function code symbol and a function descriptor 169389857Sobrien symbol. A call to foo in a relocatable object file looks like: 169489857Sobrien 169589857Sobrien . .text 169689857Sobrien . x: 169789857Sobrien . bl .foo 169889857Sobrien . nop 169989857Sobrien 170089857Sobrien The function definition in another object file might be: 170189857Sobrien 170289857Sobrien . .section .opd 170389857Sobrien . foo: .quad .foo 170489857Sobrien . .quad .TOC.@tocbase 170589857Sobrien . .quad 0 170689857Sobrien . 170789857Sobrien . .text 170889857Sobrien . .foo: blr 170989857Sobrien 171089857Sobrien When the linker resolves the call during a static link, the branch 171189857Sobrien unsurprisingly just goes to .foo and the .opd information is unused. 171289857Sobrien If the function definition is in a shared library, things are a little 171389857Sobrien different: The call goes via a plt call stub, the opd information gets 171489857Sobrien copied to the plt, and the linker patches the nop. 171589857Sobrien 171689857Sobrien . x: 171789857Sobrien . bl .foo_stub 171889857Sobrien . ld 2,40(1) 171989857Sobrien . 172089857Sobrien . 172189857Sobrien . .foo_stub: 172289857Sobrien . addis 12,2,Lfoo@toc@ha # in practice, the call stub 172389857Sobrien . addi 12,12,Lfoo@toc@l # is slightly optimised, but 172489857Sobrien . std 2,40(1) # this is the general idea 172589857Sobrien . ld 11,0(12) 172689857Sobrien . ld 2,8(12) 172789857Sobrien . mtctr 11 172889857Sobrien . ld 11,16(12) 172989857Sobrien . bctr 173089857Sobrien . 173189857Sobrien . .section .plt 173289857Sobrien . Lfoo: reloc (R_PPC64_JMP_SLOT, foo) 173389857Sobrien 173489857Sobrien The "reloc ()" notation is supposed to indicate that the linker emits 173589857Sobrien an R_PPC64_JMP_SLOT reloc against foo. The dynamic linker does the opd 173689857Sobrien copying. 173789857Sobrien 173889857Sobrien What are the difficulties here? Well, firstly, the relocations 173989857Sobrien examined by the linker in check_relocs are against the function code 174089857Sobrien sym .foo, while the dynamic relocation in the plt is emitted against 174189857Sobrien the function descriptor symbol, foo. Somewhere along the line, we need 174289857Sobrien to carefully copy dynamic link information from one symbol to the other. 174389857Sobrien Secondly, the generic part of the elf linker will make .foo a dynamic 174489857Sobrien symbol as is normal for most other backends. We need foo dynamic 174589857Sobrien instead, at least for an application final link. However, when 174689857Sobrien creating a shared library containing foo, we need to have both symbols 174789857Sobrien dynamic so that references to .foo are satisfied during the early 174889857Sobrien stages of linking. Otherwise the linker might decide to pull in a 174989857Sobrien definition from some other object, eg. a static library. */ 175089857Sobrien 175189857Sobrien/* The linker needs to keep track of the number of relocs that it 175289857Sobrien decides to copy as dynamic relocs in check_relocs for each symbol. 175389857Sobrien This is so that it can later discard them if they are found to be 175489857Sobrien unnecessary. We store the information in a field extending the 175589857Sobrien regular ELF linker hash table. */ 175689857Sobrien 175789857Sobrienstruct ppc_dyn_relocs 175889857Sobrien{ 175989857Sobrien struct ppc_dyn_relocs *next; 176089857Sobrien 176189857Sobrien /* The input section of the reloc. */ 176289857Sobrien asection *sec; 176389857Sobrien 176489857Sobrien /* Total number of relocs copied for the input section. */ 176589857Sobrien bfd_size_type count; 176689857Sobrien 176789857Sobrien /* Number of pc-relative relocs copied for the input section. */ 176889857Sobrien bfd_size_type pc_count; 176989857Sobrien}; 177089857Sobrien 177189857Sobrien/* Of those relocs that might be copied as dynamic relocs, this macro 177289857Sobrien selects between relative and absolute types. */ 177389857Sobrien 177489857Sobrien#define IS_ABSOLUTE_RELOC(RTYPE) \ 1775104834Sobrien ((RTYPE) != R_PPC64_REL32 \ 1776104834Sobrien && (RTYPE) != R_PPC64_REL64 \ 1777104834Sobrien && (RTYPE) != R_PPC64_ADDR30) 177889857Sobrien 1779104834Sobrien/* Section name for stubs is the associated section name plus this 1780104834Sobrien string. */ 1781104834Sobrien#define STUB_SUFFIX ".stub" 178289857Sobrien 1783104834Sobrien/* Linker stubs. 1784104834Sobrien ppc_stub_long_branch: 1785104834Sobrien Used when a 14 bit branch (or even a 24 bit branch) can't reach its 1786104834Sobrien destination, but a 24 bit branch in a stub section will reach. 1787104834Sobrien . b dest 1788104834Sobrien 1789104834Sobrien ppc_stub_plt_branch: 1790104834Sobrien Similar to the above, but a 24 bit branch in the stub section won't 1791104834Sobrien reach its destination. 1792107492Sobrien . addis %r12,%r2,xxx@toc@ha 1793107492Sobrien . ld %r11,xxx@toc@l(%r12) 1794104834Sobrien . mtctr %r11 1795104834Sobrien . bctr 1796104834Sobrien 1797104834Sobrien ppc_stub_plt_call: 1798104834Sobrien Used to call a function in a shared library. 1799107492Sobrien . addis %r12,%r2,xxx@toc@ha 1800104834Sobrien . std %r2,40(%r1) 1801107492Sobrien . ld %r11,xxx+0@toc@l(%r12) 1802107492Sobrien . ld %r2,xxx+8@toc@l(%r12) 1803104834Sobrien . mtctr %r11 1804107492Sobrien . ld %r11,xxx+16@toc@l(%r12) 1805104834Sobrien . bctr 1806104834Sobrien*/ 1807104834Sobrien 1808104834Sobrienenum ppc_stub_type { 1809104834Sobrien ppc_stub_none, 1810104834Sobrien ppc_stub_long_branch, 1811104834Sobrien ppc_stub_plt_branch, 1812104834Sobrien ppc_stub_plt_call 1813104834Sobrien}; 1814104834Sobrien 1815104834Sobrienstruct ppc_stub_hash_entry { 1816104834Sobrien 1817104834Sobrien /* Base hash table entry structure. */ 1818104834Sobrien struct bfd_hash_entry root; 1819104834Sobrien 1820104834Sobrien /* The stub section. */ 1821104834Sobrien asection *stub_sec; 1822104834Sobrien 1823104834Sobrien /* Offset within stub_sec of the beginning of this stub. */ 1824104834Sobrien bfd_vma stub_offset; 1825104834Sobrien 1826104834Sobrien /* Given the symbol's value and its section we can determine its final 1827104834Sobrien value when building the stubs (so the stub knows where to jump. */ 1828104834Sobrien bfd_vma target_value; 1829104834Sobrien asection *target_section; 1830104834Sobrien 1831104834Sobrien enum ppc_stub_type stub_type; 1832104834Sobrien 1833104834Sobrien /* The symbol table entry, if any, that this was derived from. */ 1834104834Sobrien struct ppc_link_hash_entry *h; 1835104834Sobrien 1836104834Sobrien /* Where this stub is being called from, or, in the case of combined 1837104834Sobrien stub sections, the first input section in the group. */ 1838104834Sobrien asection *id_sec; 1839104834Sobrien}; 1840104834Sobrien 1841104834Sobrienstruct ppc_branch_hash_entry { 1842104834Sobrien 1843104834Sobrien /* Base hash table entry structure. */ 1844104834Sobrien struct bfd_hash_entry root; 1845104834Sobrien 1846104834Sobrien /* Offset within .branch_lt. */ 1847104834Sobrien unsigned int offset; 1848104834Sobrien 1849104834Sobrien /* Generation marker. */ 1850104834Sobrien unsigned int iter; 1851104834Sobrien}; 1852104834Sobrien 185389857Sobrienstruct ppc_link_hash_entry 185489857Sobrien{ 185589857Sobrien struct elf_link_hash_entry elf; 185689857Sobrien 1857104834Sobrien /* A pointer to the most recently used stub hash entry against this 1858104834Sobrien symbol. */ 1859104834Sobrien struct ppc_stub_hash_entry *stub_cache; 1860104834Sobrien 186189857Sobrien /* Track dynamic relocs copied for this symbol. */ 186289857Sobrien struct ppc_dyn_relocs *dyn_relocs; 186389857Sobrien 1864104834Sobrien /* Link between function code and descriptor symbols. */ 1865104834Sobrien struct elf_link_hash_entry *oh; 1866104834Sobrien 186789857Sobrien /* Flag function code and descriptor symbols. */ 186889857Sobrien unsigned int is_func:1; 186989857Sobrien unsigned int is_func_descriptor:1; 1870104834Sobrien unsigned int is_entry:1; 187189857Sobrien}; 187289857Sobrien 187389857Sobrien/* ppc64 ELF linker hash table. */ 187489857Sobrien 187589857Sobrienstruct ppc_link_hash_table 187689857Sobrien{ 187789857Sobrien struct elf_link_hash_table elf; 187889857Sobrien 1879104834Sobrien /* The stub hash table. */ 1880104834Sobrien struct bfd_hash_table stub_hash_table; 1881104834Sobrien 1882104834Sobrien /* Another hash table for plt_branch stubs. */ 1883104834Sobrien struct bfd_hash_table branch_hash_table; 1884104834Sobrien 1885104834Sobrien /* Linker stub bfd. */ 1886104834Sobrien bfd *stub_bfd; 1887104834Sobrien 1888104834Sobrien /* Linker call-backs. */ 1889104834Sobrien asection * (*add_stub_section) PARAMS ((const char *, asection *)); 1890104834Sobrien void (*layout_sections_again) PARAMS ((void)); 1891104834Sobrien 1892104834Sobrien /* Array to keep track of which stub sections have been created, and 1893104834Sobrien information on stub grouping. */ 1894104834Sobrien struct map_stub { 1895104834Sobrien /* This is the section to which stubs in the group will be attached. */ 1896104834Sobrien asection *link_sec; 1897104834Sobrien /* The stub section. */ 1898104834Sobrien asection *stub_sec; 1899104834Sobrien } *stub_group; 1900104834Sobrien 1901104834Sobrien /* Assorted information used by ppc64_elf_size_stubs. */ 1902104834Sobrien int top_index; 1903104834Sobrien asection **input_list; 1904104834Sobrien 190589857Sobrien /* Short-cuts to get to dynamic linker sections. */ 190689857Sobrien asection *sgot; 190789857Sobrien asection *srelgot; 190889857Sobrien asection *splt; 190989857Sobrien asection *srelplt; 191089857Sobrien asection *sdynbss; 191189857Sobrien asection *srelbss; 191289857Sobrien asection *sglink; 191392828Sobrien asection *sfpr; 1914104834Sobrien asection *sbrlt; 1915104834Sobrien asection *srelbrlt; 191689857Sobrien 191789857Sobrien /* Set on error. */ 1918104834Sobrien unsigned int stub_error; 191989857Sobrien 1920104834Sobrien /* Flag set when small branches are detected. Used to 1921104834Sobrien select suitable defaults for the stub group size. */ 1922104834Sobrien unsigned int has_14bit_branch; 1923104834Sobrien 192499461Sobrien /* Set if we detect a reference undefined weak symbol. */ 192599461Sobrien unsigned int have_undefweak; 192699461Sobrien 1927104834Sobrien /* Incremented every time we size stubs. */ 1928104834Sobrien unsigned int stub_iteration; 1929104834Sobrien 193089857Sobrien /* Small local sym to section mapping cache. */ 193189857Sobrien struct sym_sec_cache sym_sec; 193289857Sobrien}; 193389857Sobrien 1934104834Sobrienstatic struct bfd_hash_entry *stub_hash_newfunc 1935104834Sobrien PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *)); 1936104834Sobrienstatic struct bfd_hash_entry *branch_hash_newfunc 1937104834Sobrien PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *)); 1938104834Sobrienstatic struct bfd_hash_entry *link_hash_newfunc 1939104834Sobrien PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *)); 1940104834Sobrienstatic struct bfd_link_hash_table *ppc64_elf_link_hash_table_create 1941104834Sobrien PARAMS ((bfd *)); 1942104834Sobrienstatic void ppc64_elf_link_hash_table_free 1943104834Sobrien PARAMS ((struct bfd_link_hash_table *)); 1944104834Sobrienstatic char *ppc_stub_name 1945104834Sobrien PARAMS ((const asection *, const asection *, 1946104834Sobrien const struct ppc_link_hash_entry *, const Elf_Internal_Rela *)); 1947104834Sobrienstatic struct ppc_stub_hash_entry *ppc_get_stub_entry 1948104834Sobrien PARAMS ((const asection *, const asection *, struct elf_link_hash_entry *, 1949104834Sobrien const Elf_Internal_Rela *, struct ppc_link_hash_table *)); 1950104834Sobrienstatic struct ppc_stub_hash_entry *ppc_add_stub 1951104834Sobrien PARAMS ((const char *, asection *, struct ppc_link_hash_table *)); 1952104834Sobrienstatic boolean create_linkage_sections 1953104834Sobrien PARAMS ((bfd *, struct bfd_link_info *)); 1954104834Sobrienstatic boolean create_got_section 1955104834Sobrien PARAMS ((bfd *, struct bfd_link_info *)); 1956104834Sobrienstatic boolean ppc64_elf_create_dynamic_sections 1957104834Sobrien PARAMS ((bfd *, struct bfd_link_info *)); 1958104834Sobrienstatic void ppc64_elf_copy_indirect_symbol 1959104834Sobrien PARAMS ((struct elf_backend_data *, struct elf_link_hash_entry *, 1960104834Sobrien struct elf_link_hash_entry *)); 1961104834Sobrienstatic boolean ppc64_elf_check_relocs 1962104834Sobrien PARAMS ((bfd *, struct bfd_link_info *, asection *, 1963104834Sobrien const Elf_Internal_Rela *)); 1964104834Sobrienstatic asection * ppc64_elf_gc_mark_hook 1965104834Sobrien PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *, 1966104834Sobrien struct elf_link_hash_entry *, Elf_Internal_Sym *)); 1967104834Sobrienstatic boolean ppc64_elf_gc_sweep_hook 1968104834Sobrien PARAMS ((bfd *, struct bfd_link_info *, asection *, 1969104834Sobrien const Elf_Internal_Rela *)); 1970104834Sobrienstatic boolean func_desc_adjust 1971104834Sobrien PARAMS ((struct elf_link_hash_entry *, PTR)); 1972104834Sobrienstatic boolean ppc64_elf_func_desc_adjust 1973104834Sobrien PARAMS ((bfd *, struct bfd_link_info *)); 1974104834Sobrienstatic boolean ppc64_elf_adjust_dynamic_symbol 1975104834Sobrien PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *)); 1976104834Sobrienstatic void ppc64_elf_hide_symbol 1977104834Sobrien PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *, boolean)); 1978104834Sobrienstatic boolean edit_opd 1979104834Sobrien PARAMS ((bfd *, struct bfd_link_info *)); 1980104834Sobrienstatic boolean allocate_dynrelocs 1981104834Sobrien PARAMS ((struct elf_link_hash_entry *, PTR)); 1982104834Sobrienstatic boolean readonly_dynrelocs 1983104834Sobrien PARAMS ((struct elf_link_hash_entry *, PTR)); 1984104834Sobrienstatic enum elf_reloc_type_class ppc64_elf_reloc_type_class 1985104834Sobrien PARAMS ((const Elf_Internal_Rela *)); 1986104834Sobrienstatic boolean ppc64_elf_size_dynamic_sections 1987104834Sobrien PARAMS ((bfd *, struct bfd_link_info *)); 1988104834Sobrienstatic INLINE enum ppc_stub_type ppc_type_of_stub 1989104834Sobrien PARAMS ((asection *, const Elf_Internal_Rela *, 1990104834Sobrien struct ppc_link_hash_entry **, bfd_vma)); 1991104834Sobrienstatic bfd_byte *build_plt_stub 1992104834Sobrien PARAMS ((bfd *, bfd_byte *, int, int)); 1993104834Sobrienstatic boolean ppc_build_one_stub 1994104834Sobrien PARAMS ((struct bfd_hash_entry *, PTR)); 1995104834Sobrienstatic boolean ppc_size_one_stub 1996104834Sobrien PARAMS ((struct bfd_hash_entry *, PTR)); 1997104834Sobrienstatic void group_sections 1998104834Sobrien PARAMS ((struct ppc_link_hash_table *, bfd_size_type, boolean)); 1999104834Sobrienstatic boolean ppc64_elf_relocate_section 2000104834Sobrien PARAMS ((bfd *, struct bfd_link_info *info, bfd *, asection *, bfd_byte *, 2001104834Sobrien Elf_Internal_Rela *relocs, Elf_Internal_Sym *local_syms, 2002104834Sobrien asection **)); 2003104834Sobrienstatic boolean ppc64_elf_finish_dynamic_symbol 2004104834Sobrien PARAMS ((bfd *, struct bfd_link_info *, struct elf_link_hash_entry *, 2005104834Sobrien Elf_Internal_Sym *)); 2006104834Sobrienstatic boolean ppc64_elf_finish_dynamic_sections 2007104834Sobrien PARAMS ((bfd *, struct bfd_link_info *)); 2008104834Sobrien 200989857Sobrien/* Get the ppc64 ELF linker hash table from a link_info structure. */ 201089857Sobrien 201189857Sobrien#define ppc_hash_table(p) \ 201289857Sobrien ((struct ppc_link_hash_table *) ((p)->hash)) 201389857Sobrien 2014104834Sobrien#define ppc_stub_hash_lookup(table, string, create, copy) \ 2015104834Sobrien ((struct ppc_stub_hash_entry *) \ 2016104834Sobrien bfd_hash_lookup ((table), (string), (create), (copy))) 2017104834Sobrien 2018104834Sobrien#define ppc_branch_hash_lookup(table, string, create, copy) \ 2019104834Sobrien ((struct ppc_branch_hash_entry *) \ 2020104834Sobrien bfd_hash_lookup ((table), (string), (create), (copy))) 2021104834Sobrien 2022104834Sobrien/* Create an entry in the stub hash table. */ 2023104834Sobrien 2024104834Sobrienstatic struct bfd_hash_entry * 2025104834Sobrienstub_hash_newfunc (entry, table, string) 2026104834Sobrien struct bfd_hash_entry *entry; 2027104834Sobrien struct bfd_hash_table *table; 2028104834Sobrien const char *string; 2029104834Sobrien{ 2030104834Sobrien /* Allocate the structure if it has not already been allocated by a 2031104834Sobrien subclass. */ 2032104834Sobrien if (entry == NULL) 2033104834Sobrien { 2034104834Sobrien entry = bfd_hash_allocate (table, sizeof (struct ppc_stub_hash_entry)); 2035104834Sobrien if (entry == NULL) 2036104834Sobrien return entry; 2037104834Sobrien } 2038104834Sobrien 2039104834Sobrien /* Call the allocation method of the superclass. */ 2040104834Sobrien entry = bfd_hash_newfunc (entry, table, string); 2041104834Sobrien if (entry != NULL) 2042104834Sobrien { 2043104834Sobrien struct ppc_stub_hash_entry *eh; 2044104834Sobrien 2045104834Sobrien /* Initialize the local fields. */ 2046104834Sobrien eh = (struct ppc_stub_hash_entry *) entry; 2047104834Sobrien eh->stub_sec = NULL; 2048104834Sobrien eh->stub_offset = 0; 2049104834Sobrien eh->target_value = 0; 2050104834Sobrien eh->target_section = NULL; 2051104834Sobrien eh->stub_type = ppc_stub_none; 2052104834Sobrien eh->h = NULL; 2053104834Sobrien eh->id_sec = NULL; 2054104834Sobrien } 2055104834Sobrien 2056104834Sobrien return entry; 2057104834Sobrien} 2058104834Sobrien 2059104834Sobrien/* Create an entry in the branch hash table. */ 2060104834Sobrien 2061104834Sobrienstatic struct bfd_hash_entry * 2062104834Sobrienbranch_hash_newfunc (entry, table, string) 2063104834Sobrien struct bfd_hash_entry *entry; 2064104834Sobrien struct bfd_hash_table *table; 2065104834Sobrien const char *string; 2066104834Sobrien{ 2067104834Sobrien /* Allocate the structure if it has not already been allocated by a 2068104834Sobrien subclass. */ 2069104834Sobrien if (entry == NULL) 2070104834Sobrien { 2071104834Sobrien entry = bfd_hash_allocate (table, sizeof (struct ppc_branch_hash_entry)); 2072104834Sobrien if (entry == NULL) 2073104834Sobrien return entry; 2074104834Sobrien } 2075104834Sobrien 2076104834Sobrien /* Call the allocation method of the superclass. */ 2077104834Sobrien entry = bfd_hash_newfunc (entry, table, string); 2078104834Sobrien if (entry != NULL) 2079104834Sobrien { 2080104834Sobrien struct ppc_branch_hash_entry *eh; 2081104834Sobrien 2082104834Sobrien /* Initialize the local fields. */ 2083104834Sobrien eh = (struct ppc_branch_hash_entry *) entry; 2084104834Sobrien eh->offset = 0; 2085104834Sobrien eh->iter = 0; 2086104834Sobrien } 2087104834Sobrien 2088104834Sobrien return entry; 2089104834Sobrien} 2090104834Sobrien 209189857Sobrien/* Create an entry in a ppc64 ELF linker hash table. */ 209289857Sobrien 209389857Sobrienstatic struct bfd_hash_entry * 209489857Sobrienlink_hash_newfunc (entry, table, string) 209589857Sobrien struct bfd_hash_entry *entry; 209689857Sobrien struct bfd_hash_table *table; 209789857Sobrien const char *string; 209889857Sobrien{ 209989857Sobrien /* Allocate the structure if it has not already been allocated by a 210089857Sobrien subclass. */ 210189857Sobrien if (entry == NULL) 210289857Sobrien { 210389857Sobrien entry = bfd_hash_allocate (table, sizeof (struct ppc_link_hash_entry)); 210489857Sobrien if (entry == NULL) 210589857Sobrien return entry; 210689857Sobrien } 210789857Sobrien 210889857Sobrien /* Call the allocation method of the superclass. */ 210989857Sobrien entry = _bfd_elf_link_hash_newfunc (entry, table, string); 211089857Sobrien if (entry != NULL) 211189857Sobrien { 211289857Sobrien struct ppc_link_hash_entry *eh = (struct ppc_link_hash_entry *) entry; 211389857Sobrien 2114104834Sobrien eh->stub_cache = NULL; 211589857Sobrien eh->dyn_relocs = NULL; 2116104834Sobrien eh->oh = NULL; 211789857Sobrien eh->is_func = 0; 211889857Sobrien eh->is_func_descriptor = 0; 2119104834Sobrien eh->is_entry = 0; 212089857Sobrien } 212189857Sobrien 212289857Sobrien return entry; 212389857Sobrien} 212489857Sobrien 212589857Sobrien/* Create a ppc64 ELF linker hash table. */ 212689857Sobrien 212789857Sobrienstatic struct bfd_link_hash_table * 212889857Sobrienppc64_elf_link_hash_table_create (abfd) 212989857Sobrien bfd *abfd; 213089857Sobrien{ 213189857Sobrien struct ppc_link_hash_table *htab; 213289857Sobrien bfd_size_type amt = sizeof (struct ppc_link_hash_table); 213389857Sobrien 2134104834Sobrien htab = (struct ppc_link_hash_table *) bfd_malloc (amt); 213589857Sobrien if (htab == NULL) 213689857Sobrien return NULL; 213789857Sobrien 213889857Sobrien if (! _bfd_elf_link_hash_table_init (&htab->elf, abfd, link_hash_newfunc)) 213989857Sobrien { 2140104834Sobrien free (htab); 214189857Sobrien return NULL; 214289857Sobrien } 214389857Sobrien 2144104834Sobrien /* Init the stub hash table too. */ 2145104834Sobrien if (!bfd_hash_table_init (&htab->stub_hash_table, stub_hash_newfunc)) 2146104834Sobrien return NULL; 2147104834Sobrien 2148104834Sobrien /* And the branch hash table. */ 2149104834Sobrien if (!bfd_hash_table_init (&htab->branch_hash_table, branch_hash_newfunc)) 2150104834Sobrien return NULL; 2151104834Sobrien 2152104834Sobrien htab->stub_bfd = NULL; 2153104834Sobrien htab->add_stub_section = NULL; 2154104834Sobrien htab->layout_sections_again = NULL; 2155104834Sobrien htab->stub_group = NULL; 215689857Sobrien htab->sgot = NULL; 215789857Sobrien htab->srelgot = NULL; 215889857Sobrien htab->splt = NULL; 215989857Sobrien htab->srelplt = NULL; 216089857Sobrien htab->sdynbss = NULL; 216189857Sobrien htab->srelbss = NULL; 216289857Sobrien htab->sglink = NULL; 216392828Sobrien htab->sfpr = NULL; 2164104834Sobrien htab->sbrlt = NULL; 2165104834Sobrien htab->srelbrlt = NULL; 2166104834Sobrien htab->stub_error = 0; 2167104834Sobrien htab->has_14bit_branch = 0; 216899461Sobrien htab->have_undefweak = 0; 2169104834Sobrien htab->stub_iteration = 0; 217089857Sobrien htab->sym_sec.abfd = NULL; 217189857Sobrien 217289857Sobrien return &htab->elf.root; 217389857Sobrien} 217489857Sobrien 2175104834Sobrien/* Free the derived linker hash table. */ 2176104834Sobrien 2177104834Sobrienstatic void 2178104834Sobrienppc64_elf_link_hash_table_free (hash) 2179104834Sobrien struct bfd_link_hash_table *hash; 2180104834Sobrien{ 2181104834Sobrien struct ppc_link_hash_table *ret = (struct ppc_link_hash_table *) hash; 2182104834Sobrien 2183104834Sobrien bfd_hash_table_free (&ret->stub_hash_table); 2184104834Sobrien bfd_hash_table_free (&ret->branch_hash_table); 2185104834Sobrien _bfd_generic_link_hash_table_free (hash); 2186104834Sobrien} 2187104834Sobrien 2188104834Sobrien/* Build a name for an entry in the stub hash table. */ 2189104834Sobrien 2190104834Sobrienstatic char * 2191104834Sobrienppc_stub_name (input_section, sym_sec, h, rel) 2192104834Sobrien const asection *input_section; 2193104834Sobrien const asection *sym_sec; 2194104834Sobrien const struct ppc_link_hash_entry *h; 2195104834Sobrien const Elf_Internal_Rela *rel; 2196104834Sobrien{ 2197104834Sobrien char *stub_name; 2198104834Sobrien bfd_size_type len; 2199104834Sobrien 2200104834Sobrien /* rel->r_addend is actually 64 bit, but who uses more than +/- 2^31 2201104834Sobrien offsets from a sym as a branch target? In fact, we could 2202104834Sobrien probably assume the addend is always zero. */ 2203104834Sobrien BFD_ASSERT (((int) rel->r_addend & 0xffffffff) == rel->r_addend); 2204104834Sobrien 2205104834Sobrien if (h) 2206104834Sobrien { 2207104834Sobrien len = 8 + 1 + strlen (h->elf.root.root.string) + 1 + 8 + 1; 2208104834Sobrien stub_name = bfd_malloc (len); 2209104834Sobrien if (stub_name != NULL) 2210104834Sobrien { 2211104834Sobrien sprintf (stub_name, "%08x_%s+%x", 2212104834Sobrien input_section->id & 0xffffffff, 2213104834Sobrien h->elf.root.root.string, 2214104834Sobrien (int) rel->r_addend & 0xffffffff); 2215104834Sobrien } 2216104834Sobrien } 2217104834Sobrien else 2218104834Sobrien { 2219104834Sobrien len = 8 + 1 + 8 + 1 + 8 + 1 + 16 + 1; 2220104834Sobrien stub_name = bfd_malloc (len); 2221104834Sobrien if (stub_name != NULL) 2222104834Sobrien { 2223104834Sobrien sprintf (stub_name, "%08x_%x:%x+%x", 2224104834Sobrien input_section->id & 0xffffffff, 2225104834Sobrien sym_sec->id & 0xffffffff, 2226104834Sobrien (int) ELF64_R_SYM (rel->r_info) & 0xffffffff, 2227104834Sobrien (int) rel->r_addend & 0xffffffff); 2228104834Sobrien } 2229104834Sobrien } 2230104834Sobrien return stub_name; 2231104834Sobrien} 2232104834Sobrien 2233104834Sobrien/* Look up an entry in the stub hash. Stub entries are cached because 2234104834Sobrien creating the stub name takes a bit of time. */ 2235104834Sobrien 2236104834Sobrienstatic struct ppc_stub_hash_entry * 2237104834Sobrienppc_get_stub_entry (input_section, sym_sec, hash, rel, htab) 2238104834Sobrien const asection *input_section; 2239104834Sobrien const asection *sym_sec; 2240104834Sobrien struct elf_link_hash_entry *hash; 2241104834Sobrien const Elf_Internal_Rela *rel; 2242104834Sobrien struct ppc_link_hash_table *htab; 2243104834Sobrien{ 2244104834Sobrien struct ppc_stub_hash_entry *stub_entry; 2245104834Sobrien struct ppc_link_hash_entry *h = (struct ppc_link_hash_entry *) hash; 2246104834Sobrien const asection *id_sec; 2247104834Sobrien 2248104834Sobrien /* If this input section is part of a group of sections sharing one 2249104834Sobrien stub section, then use the id of the first section in the group. 2250104834Sobrien Stub names need to include a section id, as there may well be 2251104834Sobrien more than one stub used to reach say, printf, and we need to 2252104834Sobrien distinguish between them. */ 2253104834Sobrien id_sec = htab->stub_group[input_section->id].link_sec; 2254104834Sobrien 2255104834Sobrien if (h != NULL && h->stub_cache != NULL 2256104834Sobrien && h->stub_cache->h == h 2257104834Sobrien && h->stub_cache->id_sec == id_sec) 2258104834Sobrien { 2259104834Sobrien stub_entry = h->stub_cache; 2260104834Sobrien } 2261104834Sobrien else 2262104834Sobrien { 2263104834Sobrien char *stub_name; 2264104834Sobrien 2265104834Sobrien stub_name = ppc_stub_name (id_sec, sym_sec, h, rel); 2266104834Sobrien if (stub_name == NULL) 2267104834Sobrien return NULL; 2268104834Sobrien 2269104834Sobrien stub_entry = ppc_stub_hash_lookup (&htab->stub_hash_table, 2270104834Sobrien stub_name, false, false); 2271104834Sobrien if (h != NULL) 2272104834Sobrien h->stub_cache = stub_entry; 2273104834Sobrien 2274104834Sobrien free (stub_name); 2275104834Sobrien } 2276104834Sobrien 2277104834Sobrien return stub_entry; 2278104834Sobrien} 2279104834Sobrien 2280104834Sobrien/* Add a new stub entry to the stub hash. Not all fields of the new 2281104834Sobrien stub entry are initialised. */ 2282104834Sobrien 2283104834Sobrienstatic struct ppc_stub_hash_entry * 2284104834Sobrienppc_add_stub (stub_name, section, htab) 2285104834Sobrien const char *stub_name; 2286104834Sobrien asection *section; 2287104834Sobrien struct ppc_link_hash_table *htab; 2288104834Sobrien{ 2289104834Sobrien asection *link_sec; 2290104834Sobrien asection *stub_sec; 2291104834Sobrien struct ppc_stub_hash_entry *stub_entry; 2292104834Sobrien 2293104834Sobrien link_sec = htab->stub_group[section->id].link_sec; 2294104834Sobrien stub_sec = htab->stub_group[section->id].stub_sec; 2295104834Sobrien if (stub_sec == NULL) 2296104834Sobrien { 2297104834Sobrien stub_sec = htab->stub_group[link_sec->id].stub_sec; 2298104834Sobrien if (stub_sec == NULL) 2299104834Sobrien { 2300104834Sobrien size_t namelen; 2301104834Sobrien bfd_size_type len; 2302104834Sobrien char *s_name; 2303104834Sobrien 2304104834Sobrien namelen = strlen (link_sec->name); 2305104834Sobrien len = namelen + sizeof (STUB_SUFFIX); 2306104834Sobrien s_name = bfd_alloc (htab->stub_bfd, len); 2307104834Sobrien if (s_name == NULL) 2308104834Sobrien return NULL; 2309104834Sobrien 2310104834Sobrien memcpy (s_name, link_sec->name, namelen); 2311104834Sobrien memcpy (s_name + namelen, STUB_SUFFIX, sizeof (STUB_SUFFIX)); 2312104834Sobrien stub_sec = (*htab->add_stub_section) (s_name, link_sec); 2313104834Sobrien if (stub_sec == NULL) 2314104834Sobrien return NULL; 2315104834Sobrien htab->stub_group[link_sec->id].stub_sec = stub_sec; 2316104834Sobrien } 2317104834Sobrien htab->stub_group[section->id].stub_sec = stub_sec; 2318104834Sobrien } 2319104834Sobrien 2320104834Sobrien /* Enter this entry into the linker stub hash table. */ 2321104834Sobrien stub_entry = ppc_stub_hash_lookup (&htab->stub_hash_table, stub_name, 2322104834Sobrien true, false); 2323104834Sobrien if (stub_entry == NULL) 2324104834Sobrien { 2325104834Sobrien (*_bfd_error_handler) (_("%s: cannot create stub entry %s"), 2326104834Sobrien bfd_archive_filename (section->owner), 2327104834Sobrien stub_name); 2328104834Sobrien return NULL; 2329104834Sobrien } 2330104834Sobrien 2331104834Sobrien stub_entry->stub_sec = stub_sec; 2332104834Sobrien stub_entry->stub_offset = 0; 2333104834Sobrien stub_entry->id_sec = link_sec; 2334104834Sobrien return stub_entry; 2335104834Sobrien} 2336104834Sobrien 233792828Sobrien/* Create sections for linker generated code. */ 233892828Sobrien 233992828Sobrienstatic boolean 234092828Sobriencreate_linkage_sections (dynobj, info) 234192828Sobrien bfd *dynobj; 234292828Sobrien struct bfd_link_info *info; 234392828Sobrien{ 234492828Sobrien struct ppc_link_hash_table *htab; 234592828Sobrien flagword flags; 234692828Sobrien 234792828Sobrien htab = ppc_hash_table (info); 234892828Sobrien 234992828Sobrien /* Create .sfpr for code to save and restore fp regs. */ 235092828Sobrien flags = (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_READONLY 235192828Sobrien | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED); 2352104834Sobrien htab->sfpr = bfd_make_section_anyway (dynobj, ".sfpr"); 235392828Sobrien if (htab->sfpr == NULL 235492828Sobrien || ! bfd_set_section_flags (dynobj, htab->sfpr, flags) 235592828Sobrien || ! bfd_set_section_alignment (dynobj, htab->sfpr, 2)) 235692828Sobrien return false; 235792828Sobrien 2358104834Sobrien /* Create .glink for lazy dynamic linking support. */ 2359104834Sobrien htab->sglink = bfd_make_section_anyway (dynobj, ".glink"); 236092828Sobrien if (htab->sglink == NULL 236192828Sobrien || ! bfd_set_section_flags (dynobj, htab->sglink, flags) 236292828Sobrien || ! bfd_set_section_alignment (dynobj, htab->sglink, 2)) 236392828Sobrien return false; 236492828Sobrien 2365104834Sobrien /* Create .branch_lt for plt_branch stubs. */ 2366104834Sobrien flags = (SEC_ALLOC | SEC_LOAD 2367104834Sobrien | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED); 2368104834Sobrien htab->sbrlt = bfd_make_section_anyway (dynobj, ".branch_lt"); 2369104834Sobrien if (htab->sbrlt == NULL 2370104834Sobrien || ! bfd_set_section_flags (dynobj, htab->sbrlt, flags) 2371104834Sobrien || ! bfd_set_section_alignment (dynobj, htab->sbrlt, 3)) 2372104834Sobrien return false; 2373104834Sobrien 2374104834Sobrien if (info->shared) 2375104834Sobrien { 2376104834Sobrien flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY 2377104834Sobrien | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED); 2378104834Sobrien htab->srelbrlt = bfd_make_section_anyway (dynobj, ".rela.branch_lt"); 2379104834Sobrien if (!htab->srelbrlt 2380104834Sobrien || ! bfd_set_section_flags (dynobj, htab->srelbrlt, flags) 2381104834Sobrien || ! bfd_set_section_alignment (dynobj, htab->srelbrlt, 3)) 2382104834Sobrien return false; 2383104834Sobrien } 238492828Sobrien return true; 238592828Sobrien} 238692828Sobrien 238789857Sobrien/* Create .got and .rela.got sections in DYNOBJ, and set up 238889857Sobrien shortcuts to them in our hash table. */ 238989857Sobrien 239089857Sobrienstatic boolean 239189857Sobriencreate_got_section (dynobj, info) 239289857Sobrien bfd *dynobj; 239389857Sobrien struct bfd_link_info *info; 239489857Sobrien{ 239589857Sobrien struct ppc_link_hash_table *htab; 239689857Sobrien 239789857Sobrien if (! _bfd_elf_create_got_section (dynobj, info)) 239889857Sobrien return false; 239989857Sobrien 240089857Sobrien htab = ppc_hash_table (info); 240189857Sobrien htab->sgot = bfd_get_section_by_name (dynobj, ".got"); 240289857Sobrien if (!htab->sgot) 240389857Sobrien abort (); 240489857Sobrien 240589857Sobrien htab->srelgot = bfd_make_section (dynobj, ".rela.got"); 240689857Sobrien if (!htab->srelgot 240789857Sobrien || ! bfd_set_section_flags (dynobj, htab->srelgot, 240889857Sobrien (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS 240989857Sobrien | SEC_IN_MEMORY | SEC_LINKER_CREATED 241089857Sobrien | SEC_READONLY)) 241189857Sobrien || ! bfd_set_section_alignment (dynobj, htab->srelgot, 3)) 241289857Sobrien return false; 241389857Sobrien return true; 241489857Sobrien} 241589857Sobrien 241692828Sobrien/* Create the dynamic sections, and set up shortcuts. */ 241789857Sobrien 241889857Sobrienstatic boolean 241989857Sobrienppc64_elf_create_dynamic_sections (dynobj, info) 242089857Sobrien bfd *dynobj; 242189857Sobrien struct bfd_link_info *info; 242289857Sobrien{ 242389857Sobrien struct ppc_link_hash_table *htab; 242489857Sobrien 242589857Sobrien htab = ppc_hash_table (info); 242689857Sobrien if (!htab->sgot && !create_got_section (dynobj, info)) 242789857Sobrien return false; 242889857Sobrien 242989857Sobrien if (!_bfd_elf_create_dynamic_sections (dynobj, info)) 243089857Sobrien return false; 243189857Sobrien 243289857Sobrien htab->splt = bfd_get_section_by_name (dynobj, ".plt"); 243389857Sobrien htab->srelplt = bfd_get_section_by_name (dynobj, ".rela.plt"); 243489857Sobrien htab->sdynbss = bfd_get_section_by_name (dynobj, ".dynbss"); 243589857Sobrien if (!info->shared) 243689857Sobrien htab->srelbss = bfd_get_section_by_name (dynobj, ".rela.bss"); 243789857Sobrien 243889857Sobrien if (!htab->splt || !htab->srelplt || !htab->sdynbss 243989857Sobrien || (!info->shared && !htab->srelbss)) 244089857Sobrien abort (); 244189857Sobrien 244289857Sobrien return true; 244389857Sobrien} 244489857Sobrien 244589857Sobrien/* Copy the extra info we tack onto an elf_link_hash_entry. */ 244689857Sobrien 244789857Sobrienstatic void 2448104834Sobrienppc64_elf_copy_indirect_symbol (bed, dir, ind) 2449104834Sobrien struct elf_backend_data *bed; 245089857Sobrien struct elf_link_hash_entry *dir, *ind; 245189857Sobrien{ 245289857Sobrien struct ppc_link_hash_entry *edir, *eind; 245389857Sobrien 245489857Sobrien edir = (struct ppc_link_hash_entry *) dir; 245589857Sobrien eind = (struct ppc_link_hash_entry *) ind; 245689857Sobrien 245789857Sobrien if (eind->dyn_relocs != NULL) 245889857Sobrien { 245989857Sobrien if (edir->dyn_relocs != NULL) 246089857Sobrien { 246189857Sobrien struct ppc_dyn_relocs **pp; 246289857Sobrien struct ppc_dyn_relocs *p; 246389857Sobrien 246489857Sobrien if (ind->root.type == bfd_link_hash_indirect) 246589857Sobrien abort (); 246689857Sobrien 246789857Sobrien /* Add reloc counts against the weak sym to the strong sym 246889857Sobrien list. Merge any entries against the same section. */ 246989857Sobrien for (pp = &eind->dyn_relocs; (p = *pp) != NULL; ) 247089857Sobrien { 247189857Sobrien struct ppc_dyn_relocs *q; 247289857Sobrien 247389857Sobrien for (q = edir->dyn_relocs; q != NULL; q = q->next) 247489857Sobrien if (q->sec == p->sec) 247589857Sobrien { 247689857Sobrien q->pc_count += p->pc_count; 247789857Sobrien q->count += p->count; 247889857Sobrien *pp = p->next; 247989857Sobrien break; 248089857Sobrien } 248189857Sobrien if (q == NULL) 248289857Sobrien pp = &p->next; 248389857Sobrien } 248489857Sobrien *pp = edir->dyn_relocs; 248589857Sobrien } 248689857Sobrien 248789857Sobrien edir->dyn_relocs = eind->dyn_relocs; 248889857Sobrien eind->dyn_relocs = NULL; 248989857Sobrien } 249089857Sobrien 249189857Sobrien edir->is_func |= eind->is_func; 249289857Sobrien edir->is_func_descriptor |= eind->is_func_descriptor; 2493104834Sobrien edir->is_entry |= eind->is_entry; 249489857Sobrien 2495104834Sobrien _bfd_elf_link_hash_copy_indirect (bed, dir, ind); 249689857Sobrien} 249789857Sobrien 2498104834Sobrien/* Set a flag, used by ppc64_elf_gc_mark_hook, on the entry symbol and 2499104834Sobrien symbols undefined on the command-line. */ 2500104834Sobrien 2501104834Sobrienboolean 2502104834Sobrienppc64_elf_mark_entry_syms (info) 2503104834Sobrien struct bfd_link_info *info; 2504104834Sobrien{ 2505104834Sobrien struct ppc_link_hash_table *htab; 2506104834Sobrien struct bfd_sym_chain *sym; 2507104834Sobrien 2508104834Sobrien htab = ppc_hash_table (info); 2509104834Sobrien for (sym = info->gc_sym_list; sym; sym = sym->next) 2510104834Sobrien { 2511104834Sobrien struct elf_link_hash_entry *h; 2512104834Sobrien 2513104834Sobrien h = elf_link_hash_lookup (&htab->elf, sym->name, false, false, false); 2514104834Sobrien if (h != NULL) 2515104834Sobrien ((struct ppc_link_hash_entry *) h)->is_entry = 1; 2516104834Sobrien } 2517104834Sobrien return true; 2518104834Sobrien} 2519104834Sobrien 252089857Sobrien/* Look through the relocs for a section during the first phase, and 252189857Sobrien calculate needed space in the global offset table, procedure 252289857Sobrien linkage table, and dynamic reloc sections. */ 252389857Sobrien 252489857Sobrienstatic boolean 252589857Sobrienppc64_elf_check_relocs (abfd, info, sec, relocs) 252689857Sobrien bfd *abfd; 252789857Sobrien struct bfd_link_info *info; 252889857Sobrien asection *sec; 252989857Sobrien const Elf_Internal_Rela *relocs; 253089857Sobrien{ 253189857Sobrien struct ppc_link_hash_table *htab; 253289857Sobrien Elf_Internal_Shdr *symtab_hdr; 253389857Sobrien struct elf_link_hash_entry **sym_hashes, **sym_hashes_end; 253489857Sobrien const Elf_Internal_Rela *rel; 253589857Sobrien const Elf_Internal_Rela *rel_end; 253689857Sobrien asection *sreloc; 2537104834Sobrien asection **opd_sym_map; 253889857Sobrien 253989857Sobrien if (info->relocateable) 254089857Sobrien return true; 254189857Sobrien 254289857Sobrien htab = ppc_hash_table (info); 254389857Sobrien symtab_hdr = &elf_tdata (abfd)->symtab_hdr; 254489857Sobrien 254589857Sobrien sym_hashes = elf_sym_hashes (abfd); 254689857Sobrien sym_hashes_end = (sym_hashes 2547104834Sobrien + symtab_hdr->sh_size / sizeof (Elf64_External_Sym) 2548104834Sobrien - symtab_hdr->sh_info); 254989857Sobrien 255089857Sobrien sreloc = NULL; 2551104834Sobrien opd_sym_map = NULL; 2552104834Sobrien if (strcmp (bfd_get_section_name (abfd, sec), ".opd") == 0) 2553104834Sobrien { 2554104834Sobrien /* Garbage collection needs some extra help with .opd sections. 2555104834Sobrien We don't want to necessarily keep everything referenced by 2556104834Sobrien relocs in .opd, as that would keep all functions. Instead, 2557104834Sobrien if we reference an .opd symbol (a function descriptor), we 2558104834Sobrien want to keep the function code symbol's section. This is 2559104834Sobrien easy for global symbols, but for local syms we need to keep 2560104834Sobrien information about the associated function section. Later, if 2561104834Sobrien edit_opd deletes entries, we'll use this array to adjust 2562104834Sobrien local syms in .opd. */ 2563104834Sobrien union opd_info { 2564104834Sobrien asection *func_section; 2565104834Sobrien long entry_adjust; 2566104834Sobrien }; 2567104834Sobrien bfd_size_type amt; 256889857Sobrien 2569104834Sobrien amt = sec->_raw_size * sizeof (union opd_info) / 24; 2570104834Sobrien opd_sym_map = (asection **) bfd_zalloc (abfd, amt); 2571104834Sobrien if (opd_sym_map == NULL) 2572104834Sobrien return false; 2573104834Sobrien elf_section_data (sec)->tdata = opd_sym_map; 2574104834Sobrien } 2575104834Sobrien 257692828Sobrien if (htab->elf.dynobj == NULL) 257792828Sobrien htab->elf.dynobj = abfd; 257892828Sobrien if (htab->sfpr == NULL 257992828Sobrien && !create_linkage_sections (htab->elf.dynobj, info)) 258092828Sobrien return false; 258192828Sobrien 258289857Sobrien rel_end = relocs + sec->reloc_count; 258389857Sobrien for (rel = relocs; rel < rel_end; rel++) 258489857Sobrien { 258589857Sobrien unsigned long r_symndx; 258689857Sobrien struct elf_link_hash_entry *h; 258789857Sobrien enum elf_ppc_reloc_type r_type; 258889857Sobrien 258989857Sobrien r_symndx = ELF64_R_SYM (rel->r_info); 259089857Sobrien if (r_symndx < symtab_hdr->sh_info) 259189857Sobrien h = NULL; 259289857Sobrien else 259389857Sobrien h = sym_hashes[r_symndx - symtab_hdr->sh_info]; 259489857Sobrien 259589857Sobrien r_type = (enum elf_ppc_reloc_type) ELF64_R_TYPE (rel->r_info); 259689857Sobrien switch (r_type) 259789857Sobrien { 259889857Sobrien /* GOT16 relocations */ 259989857Sobrien case R_PPC64_GOT16: 260089857Sobrien case R_PPC64_GOT16_DS: 260189857Sobrien case R_PPC64_GOT16_HA: 260289857Sobrien case R_PPC64_GOT16_HI: 260389857Sobrien case R_PPC64_GOT16_LO: 260489857Sobrien case R_PPC64_GOT16_LO_DS: 260589857Sobrien 260689857Sobrien /* This symbol requires a global offset table entry. */ 260792828Sobrien if (htab->sgot == NULL 260892828Sobrien && !create_got_section (htab->elf.dynobj, info)) 260992828Sobrien return false; 261089857Sobrien 261189857Sobrien if (h != NULL) 261289857Sobrien { 261389857Sobrien h->got.refcount += 1; 261489857Sobrien } 261589857Sobrien else 261689857Sobrien { 261789857Sobrien bfd_signed_vma *local_got_refcounts; 261889857Sobrien 261989857Sobrien /* This is a global offset table entry for a local symbol. */ 262089857Sobrien local_got_refcounts = elf_local_got_refcounts (abfd); 262189857Sobrien if (local_got_refcounts == NULL) 262289857Sobrien { 262389857Sobrien bfd_size_type size; 262489857Sobrien 262589857Sobrien size = symtab_hdr->sh_info; 262689857Sobrien size *= sizeof (bfd_signed_vma); 262789857Sobrien local_got_refcounts = ((bfd_signed_vma *) 262889857Sobrien bfd_zalloc (abfd, size)); 262989857Sobrien if (local_got_refcounts == NULL) 263089857Sobrien return false; 263189857Sobrien elf_local_got_refcounts (abfd) = local_got_refcounts; 263289857Sobrien } 263389857Sobrien local_got_refcounts[r_symndx] += 1; 263489857Sobrien } 263589857Sobrien break; 263689857Sobrien 263789857Sobrien case R_PPC64_PLT16_HA: 263889857Sobrien case R_PPC64_PLT16_HI: 263989857Sobrien case R_PPC64_PLT16_LO: 264089857Sobrien case R_PPC64_PLT32: 264189857Sobrien case R_PPC64_PLT64: 264289857Sobrien /* This symbol requires a procedure linkage table entry. We 2643104834Sobrien actually build the entry in adjust_dynamic_symbol, 2644104834Sobrien because this might be a case of linking PIC code without 2645104834Sobrien linking in any dynamic objects, in which case we don't 2646104834Sobrien need to generate a procedure linkage table after all. */ 264789857Sobrien if (h == NULL) 264889857Sobrien { 264989857Sobrien /* It does not make sense to have a procedure linkage 2650104834Sobrien table entry for a local symbol. */ 265189857Sobrien bfd_set_error (bfd_error_bad_value); 265289857Sobrien return false; 265389857Sobrien } 265489857Sobrien 265589857Sobrien h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; 265689857Sobrien h->plt.refcount += 1; 265789857Sobrien ((struct ppc_link_hash_entry *) h)->is_func = 1; 265889857Sobrien break; 265989857Sobrien 266089857Sobrien /* The following relocations don't need to propagate the 266189857Sobrien relocation if linking a shared object since they are 266289857Sobrien section relative. */ 266389857Sobrien case R_PPC64_SECTOFF: 266489857Sobrien case R_PPC64_SECTOFF_LO: 266589857Sobrien case R_PPC64_SECTOFF_HI: 266689857Sobrien case R_PPC64_SECTOFF_HA: 266789857Sobrien case R_PPC64_SECTOFF_DS: 266889857Sobrien case R_PPC64_SECTOFF_LO_DS: 266989857Sobrien case R_PPC64_TOC16: 267089857Sobrien case R_PPC64_TOC16_LO: 267189857Sobrien case R_PPC64_TOC16_HI: 267289857Sobrien case R_PPC64_TOC16_HA: 267389857Sobrien case R_PPC64_TOC16_DS: 267489857Sobrien case R_PPC64_TOC16_LO_DS: 267589857Sobrien break; 267689857Sobrien 267789857Sobrien /* This relocation describes the C++ object vtable hierarchy. 267889857Sobrien Reconstruct it for later use during GC. */ 267989857Sobrien case R_PPC64_GNU_VTINHERIT: 268089857Sobrien if (!_bfd_elf64_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) 268189857Sobrien return false; 268289857Sobrien break; 268389857Sobrien 268489857Sobrien /* This relocation describes which C++ vtable entries are actually 268589857Sobrien used. Record for later use during GC. */ 268689857Sobrien case R_PPC64_GNU_VTENTRY: 268789857Sobrien if (!_bfd_elf64_gc_record_vtentry (abfd, sec, h, rel->r_addend)) 268889857Sobrien return false; 268989857Sobrien break; 269089857Sobrien 2691104834Sobrien case R_PPC64_REL14: 2692104834Sobrien case R_PPC64_REL14_BRTAKEN: 2693104834Sobrien case R_PPC64_REL14_BRNTAKEN: 2694104834Sobrien htab->has_14bit_branch = 1; 2695104834Sobrien /* Fall through. */ 2696104834Sobrien 269789857Sobrien case R_PPC64_REL24: 269889857Sobrien if (h != NULL 269989857Sobrien && h->root.root.string[0] == '.' 270089857Sobrien && h->root.root.string[1] != 0) 270189857Sobrien { 270289857Sobrien /* We may need a .plt entry if the function this reloc 270389857Sobrien refers to is in a shared lib. */ 270489857Sobrien h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; 270589857Sobrien h->plt.refcount += 1; 270689857Sobrien ((struct ppc_link_hash_entry *) h)->is_func = 1; 270789857Sobrien } 270889857Sobrien break; 270989857Sobrien 271089857Sobrien case R_PPC64_ADDR64: 2711104834Sobrien if (opd_sym_map != NULL 271289857Sobrien && h != NULL 271389857Sobrien && h->root.root.string[0] == '.' 271489857Sobrien && h->root.root.string[1] != 0) 271589857Sobrien { 271689857Sobrien struct elf_link_hash_entry *fdh; 271789857Sobrien 271889857Sobrien fdh = elf_link_hash_lookup (&htab->elf, h->root.root.string + 1, 271989857Sobrien false, false, false); 272089857Sobrien if (fdh != NULL) 272189857Sobrien { 272289857Sobrien ((struct ppc_link_hash_entry *) fdh)->is_func_descriptor = 1; 2723104834Sobrien ((struct ppc_link_hash_entry *) fdh)->oh = h; 272489857Sobrien ((struct ppc_link_hash_entry *) h)->is_func = 1; 2725104834Sobrien ((struct ppc_link_hash_entry *) h)->oh = fdh; 272689857Sobrien } 272789857Sobrien } 2728104834Sobrien if (opd_sym_map != NULL 2729104834Sobrien && h == NULL 2730104834Sobrien && rel + 1 < rel_end 2731104834Sobrien && ((enum elf_ppc_reloc_type) ELF64_R_TYPE ((rel + 1)->r_info) 2732104834Sobrien == R_PPC64_TOC)) 2733104834Sobrien { 2734104834Sobrien asection *s; 2735104834Sobrien 2736104834Sobrien s = bfd_section_from_r_symndx (abfd, &htab->sym_sec, sec, 2737104834Sobrien r_symndx); 2738104834Sobrien if (s == NULL) 2739104834Sobrien return false; 2740104834Sobrien else if (s != sec) 2741104834Sobrien opd_sym_map[rel->r_offset / 24] = s; 2742104834Sobrien } 274389857Sobrien /* Fall through. */ 274489857Sobrien 274589857Sobrien case R_PPC64_REL64: 274689857Sobrien case R_PPC64_REL32: 274789857Sobrien case R_PPC64_ADDR14: 274889857Sobrien case R_PPC64_ADDR14_BRNTAKEN: 274989857Sobrien case R_PPC64_ADDR14_BRTAKEN: 275089857Sobrien case R_PPC64_ADDR16: 275189857Sobrien case R_PPC64_ADDR16_DS: 275289857Sobrien case R_PPC64_ADDR16_HA: 275389857Sobrien case R_PPC64_ADDR16_HI: 275489857Sobrien case R_PPC64_ADDR16_HIGHER: 275589857Sobrien case R_PPC64_ADDR16_HIGHERA: 275689857Sobrien case R_PPC64_ADDR16_HIGHEST: 275789857Sobrien case R_PPC64_ADDR16_HIGHESTA: 275889857Sobrien case R_PPC64_ADDR16_LO: 275989857Sobrien case R_PPC64_ADDR16_LO_DS: 276089857Sobrien case R_PPC64_ADDR24: 276189857Sobrien case R_PPC64_ADDR30: 276289857Sobrien case R_PPC64_ADDR32: 276389857Sobrien case R_PPC64_UADDR16: 276489857Sobrien case R_PPC64_UADDR32: 276589857Sobrien case R_PPC64_UADDR64: 276689857Sobrien case R_PPC64_TOC: 276789857Sobrien /* Don't propagate .opd relocs. */ 2768104834Sobrien if (NO_OPD_RELOCS && opd_sym_map != NULL) 276989857Sobrien break; 277089857Sobrien 277189857Sobrien /* If we are creating a shared library, and this is a reloc 277289857Sobrien against a global symbol, or a non PC relative reloc 277389857Sobrien against a local symbol, then we need to copy the reloc 277489857Sobrien into the shared library. However, if we are linking with 277589857Sobrien -Bsymbolic, we do not need to copy a reloc against a 277689857Sobrien global symbol which is defined in an object we are 277789857Sobrien including in the link (i.e., DEF_REGULAR is set). At 277889857Sobrien this point we have not seen all the input files, so it is 277989857Sobrien possible that DEF_REGULAR is not set now but will be set 278089857Sobrien later (it is never cleared). In case of a weak definition, 278189857Sobrien DEF_REGULAR may be cleared later by a strong definition in 278289857Sobrien a shared library. We account for that possibility below by 278389857Sobrien storing information in the relocs_copied field of the hash 278489857Sobrien table entry. A similar situation occurs when creating 278589857Sobrien shared libraries and symbol visibility changes render the 278689857Sobrien symbol local. 278789857Sobrien 278889857Sobrien If on the other hand, we are creating an executable, we 278989857Sobrien may need to keep relocations for symbols satisfied by a 279089857Sobrien dynamic library if we manage to avoid copy relocs for the 279189857Sobrien symbol. */ 279289857Sobrien if ((info->shared 279389857Sobrien && (sec->flags & SEC_ALLOC) != 0 279489857Sobrien && (IS_ABSOLUTE_RELOC (r_type) 279589857Sobrien || (h != NULL 279689857Sobrien && (! info->symbolic 279789857Sobrien || h->root.type == bfd_link_hash_defweak 279889857Sobrien || (h->elf_link_hash_flags 279989857Sobrien & ELF_LINK_HASH_DEF_REGULAR) == 0)))) 280089857Sobrien || (!info->shared 280189857Sobrien && (sec->flags & SEC_ALLOC) != 0 280289857Sobrien && h != NULL 280389857Sobrien && (h->root.type == bfd_link_hash_defweak 280489857Sobrien || (h->elf_link_hash_flags 280589857Sobrien & ELF_LINK_HASH_DEF_REGULAR) == 0))) 280689857Sobrien { 280789857Sobrien struct ppc_dyn_relocs *p; 280889857Sobrien struct ppc_dyn_relocs **head; 280989857Sobrien 281089857Sobrien /* We must copy these reloc types into the output file. 281189857Sobrien Create a reloc section in dynobj and make room for 281289857Sobrien this reloc. */ 281389857Sobrien if (sreloc == NULL) 281489857Sobrien { 281589857Sobrien const char *name; 281689857Sobrien bfd *dynobj; 281789857Sobrien 281889857Sobrien name = (bfd_elf_string_from_elf_section 281989857Sobrien (abfd, 282089857Sobrien elf_elfheader (abfd)->e_shstrndx, 282189857Sobrien elf_section_data (sec)->rel_hdr.sh_name)); 282289857Sobrien if (name == NULL) 282389857Sobrien return false; 282489857Sobrien 282589857Sobrien if (strncmp (name, ".rela", 5) != 0 282689857Sobrien || strcmp (bfd_get_section_name (abfd, sec), 282789857Sobrien name + 5) != 0) 282889857Sobrien { 282989857Sobrien (*_bfd_error_handler) 283089857Sobrien (_("%s: bad relocation section name `%s\'"), 283189857Sobrien bfd_archive_filename (abfd), name); 283289857Sobrien bfd_set_error (bfd_error_bad_value); 283389857Sobrien } 283489857Sobrien 283589857Sobrien dynobj = htab->elf.dynobj; 283689857Sobrien sreloc = bfd_get_section_by_name (dynobj, name); 283789857Sobrien if (sreloc == NULL) 283889857Sobrien { 283989857Sobrien flagword flags; 284089857Sobrien 284189857Sobrien sreloc = bfd_make_section (dynobj, name); 284289857Sobrien flags = (SEC_HAS_CONTENTS | SEC_READONLY 284389857Sobrien | SEC_IN_MEMORY | SEC_LINKER_CREATED); 284489857Sobrien if ((sec->flags & SEC_ALLOC) != 0) 284589857Sobrien flags |= SEC_ALLOC | SEC_LOAD; 284689857Sobrien if (sreloc == NULL 284789857Sobrien || ! bfd_set_section_flags (dynobj, sreloc, flags) 284889857Sobrien || ! bfd_set_section_alignment (dynobj, sreloc, 3)) 284989857Sobrien return false; 285089857Sobrien } 285189857Sobrien elf_section_data (sec)->sreloc = sreloc; 285289857Sobrien } 285389857Sobrien 285489857Sobrien /* If this is a global symbol, we count the number of 285589857Sobrien relocations we need for this symbol. */ 285689857Sobrien if (h != NULL) 285789857Sobrien { 285889857Sobrien head = &((struct ppc_link_hash_entry *) h)->dyn_relocs; 285989857Sobrien } 286089857Sobrien else 286189857Sobrien { 286289857Sobrien /* Track dynamic relocs needed for local syms too. 286389857Sobrien We really need local syms available to do this 286489857Sobrien easily. Oh well. */ 286589857Sobrien 286689857Sobrien asection *s; 286789857Sobrien s = bfd_section_from_r_symndx (abfd, &htab->sym_sec, 286889857Sobrien sec, r_symndx); 286989857Sobrien if (s == NULL) 287089857Sobrien return false; 287189857Sobrien 287289857Sobrien head = ((struct ppc_dyn_relocs **) 287389857Sobrien &elf_section_data (s)->local_dynrel); 287489857Sobrien } 287589857Sobrien 287689857Sobrien p = *head; 287789857Sobrien if (p == NULL || p->sec != sec) 287889857Sobrien { 287989857Sobrien p = ((struct ppc_dyn_relocs *) 288089857Sobrien bfd_alloc (htab->elf.dynobj, 288189857Sobrien (bfd_size_type) sizeof *p)); 288289857Sobrien if (p == NULL) 288389857Sobrien return false; 288489857Sobrien p->next = *head; 288589857Sobrien *head = p; 288689857Sobrien p->sec = sec; 288789857Sobrien p->count = 0; 288889857Sobrien p->pc_count = 0; 288989857Sobrien } 289089857Sobrien 289189857Sobrien p->count += 1; 289289857Sobrien if (!IS_ABSOLUTE_RELOC (r_type)) 289389857Sobrien p->pc_count += 1; 289489857Sobrien } 289589857Sobrien break; 289689857Sobrien 289789857Sobrien default: 289892828Sobrien break; 289989857Sobrien } 290089857Sobrien } 290189857Sobrien 290289857Sobrien return true; 290389857Sobrien} 290489857Sobrien 290589857Sobrien/* Return the section that should be marked against GC for a given 290689857Sobrien relocation. */ 290789857Sobrien 290889857Sobrienstatic asection * 2909104834Sobrienppc64_elf_gc_mark_hook (sec, info, rel, h, sym) 2910104834Sobrien asection *sec; 291189857Sobrien struct bfd_link_info *info ATTRIBUTE_UNUSED; 291289857Sobrien Elf_Internal_Rela *rel; 291389857Sobrien struct elf_link_hash_entry *h; 291489857Sobrien Elf_Internal_Sym *sym; 291589857Sobrien{ 2916104834Sobrien asection *rsec = NULL; 2917104834Sobrien 291889857Sobrien if (h != NULL) 291989857Sobrien { 292089857Sobrien enum elf_ppc_reloc_type r_type; 2921104834Sobrien struct ppc_link_hash_entry *fdh; 292289857Sobrien 292389857Sobrien r_type = (enum elf_ppc_reloc_type) ELF64_R_TYPE (rel->r_info); 292489857Sobrien switch (r_type) 292589857Sobrien { 292689857Sobrien case R_PPC64_GNU_VTINHERIT: 292789857Sobrien case R_PPC64_GNU_VTENTRY: 292889857Sobrien break; 292989857Sobrien 293089857Sobrien default: 293189857Sobrien switch (h->root.type) 293289857Sobrien { 293389857Sobrien case bfd_link_hash_defined: 293489857Sobrien case bfd_link_hash_defweak: 2935104834Sobrien fdh = (struct ppc_link_hash_entry *) h; 293689857Sobrien 2937104834Sobrien /* Function descriptor syms cause the associated 2938104834Sobrien function code sym section to be marked. */ 2939104834Sobrien if (fdh->is_func_descriptor) 2940104834Sobrien rsec = fdh->oh->root.u.def.section; 2941104834Sobrien 2942104834Sobrien /* Function entry syms return NULL if they are in .opd 2943104834Sobrien and are not ._start (or others undefined on the ld 2944104834Sobrien command line). Thus we avoid marking all function 2945104834Sobrien sections, as all functions are referenced in .opd. */ 2946104834Sobrien else if ((fdh->oh != NULL 2947104834Sobrien && ((struct ppc_link_hash_entry *) fdh->oh)->is_entry) 2948104834Sobrien || elf_section_data (sec)->tdata == NULL) 2949104834Sobrien rsec = h->root.u.def.section; 2950104834Sobrien break; 2951104834Sobrien 295289857Sobrien case bfd_link_hash_common: 2953104834Sobrien rsec = h->root.u.c.p->section; 2954104834Sobrien break; 295589857Sobrien 295689857Sobrien default: 295789857Sobrien break; 295889857Sobrien } 295989857Sobrien } 296089857Sobrien } 296189857Sobrien else 296289857Sobrien { 2963104834Sobrien asection **opd_sym_section; 2964104834Sobrien 2965104834Sobrien rsec = bfd_section_from_elf_index (sec->owner, sym->st_shndx); 2966104834Sobrien opd_sym_section = (asection **) elf_section_data (rsec)->tdata; 2967104834Sobrien if (opd_sym_section != NULL) 2968104834Sobrien rsec = opd_sym_section[sym->st_value / 24]; 2969104834Sobrien else if (elf_section_data (sec)->tdata != NULL) 2970104834Sobrien rsec = NULL; 297189857Sobrien } 297289857Sobrien 2973104834Sobrien return rsec; 297489857Sobrien} 297589857Sobrien 297689857Sobrien/* Update the .got, .plt. and dynamic reloc reference counts for the 297789857Sobrien section being removed. */ 297889857Sobrien 297989857Sobrienstatic boolean 298089857Sobrienppc64_elf_gc_sweep_hook (abfd, info, sec, relocs) 298189857Sobrien bfd *abfd; 298289857Sobrien struct bfd_link_info *info ATTRIBUTE_UNUSED; 298389857Sobrien asection *sec; 298489857Sobrien const Elf_Internal_Rela *relocs; 298589857Sobrien{ 298689857Sobrien Elf_Internal_Shdr *symtab_hdr; 298789857Sobrien struct elf_link_hash_entry **sym_hashes; 298889857Sobrien bfd_signed_vma *local_got_refcounts; 298989857Sobrien const Elf_Internal_Rela *rel, *relend; 299089857Sobrien 299189857Sobrien elf_section_data (sec)->local_dynrel = NULL; 299289857Sobrien 299389857Sobrien symtab_hdr = &elf_tdata (abfd)->symtab_hdr; 299489857Sobrien sym_hashes = elf_sym_hashes (abfd); 299589857Sobrien local_got_refcounts = elf_local_got_refcounts (abfd); 299689857Sobrien 299789857Sobrien relend = relocs + sec->reloc_count; 299889857Sobrien for (rel = relocs; rel < relend; rel++) 299989857Sobrien { 300089857Sobrien unsigned long r_symndx; 300189857Sobrien enum elf_ppc_reloc_type r_type; 300289857Sobrien struct elf_link_hash_entry *h; 300389857Sobrien 300489857Sobrien r_symndx = ELF64_R_SYM (rel->r_info); 300589857Sobrien r_type = (enum elf_ppc_reloc_type) ELF64_R_TYPE (rel->r_info); 300689857Sobrien switch (r_type) 300789857Sobrien { 300889857Sobrien case R_PPC64_GOT16: 300989857Sobrien case R_PPC64_GOT16_DS: 301089857Sobrien case R_PPC64_GOT16_HA: 301189857Sobrien case R_PPC64_GOT16_HI: 301289857Sobrien case R_PPC64_GOT16_LO: 301389857Sobrien case R_PPC64_GOT16_LO_DS: 301489857Sobrien if (r_symndx >= symtab_hdr->sh_info) 301589857Sobrien { 301689857Sobrien h = sym_hashes[r_symndx - symtab_hdr->sh_info]; 301789857Sobrien if (h->got.refcount > 0) 301889857Sobrien h->got.refcount--; 301989857Sobrien } 302089857Sobrien else 302189857Sobrien { 302289857Sobrien if (local_got_refcounts[r_symndx] > 0) 302389857Sobrien local_got_refcounts[r_symndx]--; 302489857Sobrien } 302589857Sobrien break; 302689857Sobrien 302789857Sobrien case R_PPC64_PLT16_HA: 302889857Sobrien case R_PPC64_PLT16_HI: 302989857Sobrien case R_PPC64_PLT16_LO: 303089857Sobrien case R_PPC64_PLT32: 303189857Sobrien case R_PPC64_PLT64: 303289857Sobrien if (r_symndx >= symtab_hdr->sh_info) 303389857Sobrien { 303489857Sobrien h = sym_hashes[r_symndx - symtab_hdr->sh_info]; 303589857Sobrien if (h->plt.refcount > 0) 303689857Sobrien h->plt.refcount--; 303789857Sobrien } 303889857Sobrien break; 303989857Sobrien 3040104834Sobrien case R_PPC64_REL14: 3041104834Sobrien case R_PPC64_REL14_BRNTAKEN: 3042104834Sobrien case R_PPC64_REL14_BRTAKEN: 304389857Sobrien case R_PPC64_REL24: 304489857Sobrien if (r_symndx >= symtab_hdr->sh_info) 304589857Sobrien { 304689857Sobrien h = sym_hashes[r_symndx - symtab_hdr->sh_info]; 304789857Sobrien if (h->plt.refcount > 0) 304889857Sobrien h->plt.refcount--; 304989857Sobrien } 305089857Sobrien break; 305189857Sobrien 305289857Sobrien case R_PPC64_REL32: 305389857Sobrien case R_PPC64_REL64: 305489857Sobrien if (r_symndx >= symtab_hdr->sh_info) 305589857Sobrien { 305689857Sobrien struct ppc_link_hash_entry *eh; 305789857Sobrien struct ppc_dyn_relocs **pp; 305889857Sobrien struct ppc_dyn_relocs *p; 305989857Sobrien 306089857Sobrien h = sym_hashes[r_symndx - symtab_hdr->sh_info]; 306189857Sobrien eh = (struct ppc_link_hash_entry *) h; 306289857Sobrien 306389857Sobrien for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next) 306489857Sobrien if (p->sec == sec) 306589857Sobrien { 306689857Sobrien p->pc_count -= 1; 306789857Sobrien p->count -= 1; 306889857Sobrien if (p->count == 0) 306989857Sobrien *pp = p->next; 307089857Sobrien break; 307189857Sobrien } 307289857Sobrien } 307389857Sobrien break; 307489857Sobrien 307589857Sobrien case R_PPC64_ADDR14: 307689857Sobrien case R_PPC64_ADDR14_BRNTAKEN: 307789857Sobrien case R_PPC64_ADDR14_BRTAKEN: 307889857Sobrien case R_PPC64_ADDR16: 307989857Sobrien case R_PPC64_ADDR16_DS: 308089857Sobrien case R_PPC64_ADDR16_HA: 308189857Sobrien case R_PPC64_ADDR16_HI: 308289857Sobrien case R_PPC64_ADDR16_HIGHER: 308389857Sobrien case R_PPC64_ADDR16_HIGHERA: 308489857Sobrien case R_PPC64_ADDR16_HIGHEST: 308589857Sobrien case R_PPC64_ADDR16_HIGHESTA: 308689857Sobrien case R_PPC64_ADDR16_LO: 308789857Sobrien case R_PPC64_ADDR16_LO_DS: 308889857Sobrien case R_PPC64_ADDR24: 308989857Sobrien case R_PPC64_ADDR30: 309089857Sobrien case R_PPC64_ADDR32: 309189857Sobrien case R_PPC64_ADDR64: 309289857Sobrien case R_PPC64_UADDR16: 309389857Sobrien case R_PPC64_UADDR32: 309489857Sobrien case R_PPC64_UADDR64: 309589857Sobrien case R_PPC64_TOC: 309689857Sobrien if (r_symndx >= symtab_hdr->sh_info) 309789857Sobrien { 309889857Sobrien struct ppc_link_hash_entry *eh; 309989857Sobrien struct ppc_dyn_relocs **pp; 310089857Sobrien struct ppc_dyn_relocs *p; 310189857Sobrien 310289857Sobrien h = sym_hashes[r_symndx - symtab_hdr->sh_info]; 310389857Sobrien eh = (struct ppc_link_hash_entry *) h; 310489857Sobrien 310589857Sobrien for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next) 310689857Sobrien if (p->sec == sec) 310789857Sobrien { 310889857Sobrien p->count -= 1; 310989857Sobrien if (p->count == 0) 311089857Sobrien *pp = p->next; 311189857Sobrien break; 311289857Sobrien } 311389857Sobrien } 311489857Sobrien break; 311589857Sobrien 311689857Sobrien default: 311789857Sobrien break; 311889857Sobrien } 311989857Sobrien } 312089857Sobrien return true; 312189857Sobrien} 312289857Sobrien 312389857Sobrien/* Called via elf_link_hash_traverse to transfer dynamic linking 312489857Sobrien information on function code symbol entries to their corresponding 312589857Sobrien function descriptor symbol entries. */ 312689857Sobrienstatic boolean 312789857Sobrienfunc_desc_adjust (h, inf) 312889857Sobrien struct elf_link_hash_entry *h; 312989857Sobrien PTR inf; 313089857Sobrien{ 313189857Sobrien struct bfd_link_info *info; 313289857Sobrien struct ppc_link_hash_table *htab; 313389857Sobrien 313494536Sobrien if (h->root.type == bfd_link_hash_indirect) 313589857Sobrien return true; 313689857Sobrien 313794536Sobrien if (h->root.type == bfd_link_hash_warning) 313894536Sobrien h = (struct elf_link_hash_entry *) h->root.u.i.link; 313994536Sobrien 314089857Sobrien info = (struct bfd_link_info *) inf; 314189857Sobrien htab = ppc_hash_table (info); 314289857Sobrien 314389857Sobrien /* If this is a function code symbol, transfer dynamic linking 314489857Sobrien information to the function descriptor symbol. */ 314589857Sobrien if (!((struct ppc_link_hash_entry *) h)->is_func) 314689857Sobrien return true; 314789857Sobrien 314899461Sobrien if (h->root.type == bfd_link_hash_undefweak 314999461Sobrien && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR)) 315099461Sobrien htab->have_undefweak = true; 315199461Sobrien 315289857Sobrien if (h->plt.refcount > 0 315389857Sobrien && h->root.root.string[0] == '.' 315489857Sobrien && h->root.root.string[1] != '\0') 315589857Sobrien { 3156104834Sobrien struct elf_link_hash_entry *fdh = ((struct ppc_link_hash_entry *) h)->oh; 315789857Sobrien boolean force_local; 315889857Sobrien 315989857Sobrien /* Find the corresponding function descriptor symbol. Create it 316089857Sobrien as undefined if necessary. */ 316189857Sobrien 3162104834Sobrien if (fdh == NULL) 3163104834Sobrien fdh = elf_link_hash_lookup (&htab->elf, h->root.root.string + 1, 3164104834Sobrien false, false, true); 316589857Sobrien 316691041Sobrien if (fdh == NULL 316791041Sobrien && info->shared 316891041Sobrien && (h->root.type == bfd_link_hash_undefined 316991041Sobrien || h->root.type == bfd_link_hash_undefweak)) 317089857Sobrien { 317189857Sobrien bfd *abfd; 317289857Sobrien asymbol *newsym; 3173107492Sobrien struct bfd_link_hash_entry *bh; 317489857Sobrien 317591041Sobrien abfd = h->root.u.undef.abfd; 317689857Sobrien newsym = bfd_make_empty_symbol (abfd); 317789857Sobrien newsym->name = h->root.root.string + 1; 317889857Sobrien newsym->section = bfd_und_section_ptr; 317989857Sobrien newsym->value = 0; 318089857Sobrien newsym->flags = BSF_OBJECT; 318189857Sobrien if (h->root.type == bfd_link_hash_undefweak) 318289857Sobrien newsym->flags |= BSF_WEAK; 318389857Sobrien 3184107492Sobrien bh = &fdh->root; 318589857Sobrien if ( !(_bfd_generic_link_add_one_symbol 318689857Sobrien (info, abfd, newsym->name, newsym->flags, 3187107492Sobrien newsym->section, newsym->value, NULL, false, false, &bh))) 318889857Sobrien { 318989857Sobrien return false; 319089857Sobrien } 3191107492Sobrien fdh = (struct elf_link_hash_entry *) bh; 319291041Sobrien fdh->elf_link_hash_flags &= ~ELF_LINK_NON_ELF; 319389857Sobrien } 319489857Sobrien 319589857Sobrien if (fdh != NULL 319689857Sobrien && (fdh->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0 319789857Sobrien && (info->shared 319889857Sobrien || (fdh->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0 319989857Sobrien || (fdh->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) != 0)) 320089857Sobrien { 320189857Sobrien if (fdh->dynindx == -1) 320289857Sobrien if (! bfd_elf64_link_record_dynamic_symbol (info, fdh)) 320389857Sobrien return false; 320489857Sobrien fdh->elf_link_hash_flags |= (h->elf_link_hash_flags 320589857Sobrien & (ELF_LINK_HASH_REF_REGULAR 320689857Sobrien | ELF_LINK_HASH_REF_DYNAMIC 320789857Sobrien | ELF_LINK_HASH_REF_REGULAR_NONWEAK 320889857Sobrien | ELF_LINK_NON_GOT_REF)); 320991041Sobrien if (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT) 321091041Sobrien { 321191041Sobrien fdh->plt.refcount = h->plt.refcount; 321291041Sobrien fdh->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; 321391041Sobrien } 321489857Sobrien ((struct ppc_link_hash_entry *) fdh)->is_func_descriptor = 1; 3215104834Sobrien ((struct ppc_link_hash_entry *) fdh)->oh = h; 3216104834Sobrien ((struct ppc_link_hash_entry *) h)->oh = fdh; 321789857Sobrien } 321889857Sobrien 321989857Sobrien /* Now that the info is on the function descriptor, clear the 322089857Sobrien function code sym info. Any function code syms for which we 322189857Sobrien don't have a definition in a regular file, we force local. 322289857Sobrien This prevents a shared library from exporting syms that have 322389857Sobrien been imported from another library. Function code syms that 322489857Sobrien are really in the library we must leave global to prevent the 322591041Sobrien linker dragging in a definition from a static library. */ 3226104834Sobrien force_local = (info->shared 3227104834Sobrien && ((h->elf_link_hash_flags 3228104834Sobrien & ELF_LINK_HASH_DEF_REGULAR) == 0 3229104834Sobrien || fdh == NULL 3230104834Sobrien || (fdh->elf_link_hash_flags 3231104834Sobrien & ELF_LINK_HASH_DEF_REGULAR) == 0 3232104834Sobrien || (fdh->elf_link_hash_flags 3233104834Sobrien & ELF_LINK_FORCED_LOCAL) != 0)); 323489857Sobrien _bfd_elf_link_hash_hide_symbol (info, h, force_local); 323589857Sobrien } 323689857Sobrien 323789857Sobrien return true; 323889857Sobrien} 323989857Sobrien 324092828Sobrien#define MIN_SAVE_FPR 14 324192828Sobrien#define MAX_SAVE_FPR 31 324292828Sobrien 324389857Sobrien/* Called near the start of bfd_elf_size_dynamic_sections. We use 324492828Sobrien this hook to a) provide some gcc support functions, and b) transfer 324592828Sobrien dynamic linking information gathered so far on function code symbol 324692828Sobrien entries, to their corresponding function descriptor symbol entries. */ 324789857Sobrienstatic boolean 324889857Sobrienppc64_elf_func_desc_adjust (obfd, info) 324989857Sobrien bfd *obfd ATTRIBUTE_UNUSED; 325089857Sobrien struct bfd_link_info *info; 325189857Sobrien{ 325289857Sobrien struct ppc_link_hash_table *htab; 325392828Sobrien unsigned int lowest_savef = MAX_SAVE_FPR + 2; 325492828Sobrien unsigned int lowest_restf = MAX_SAVE_FPR + 2; 325592828Sobrien unsigned int i; 325692828Sobrien struct elf_link_hash_entry *h; 325799461Sobrien bfd_byte *p; 325892828Sobrien char sym[10]; 325989857Sobrien 326089857Sobrien htab = ppc_hash_table (info); 326192828Sobrien 326292828Sobrien if (htab->sfpr == NULL) 326392828Sobrien /* We don't have any relocs. */ 326492828Sobrien return true; 326592828Sobrien 326692828Sobrien /* First provide any missing ._savef* and ._restf* functions. */ 326792828Sobrien memcpy (sym, "._savef14", 10); 326892828Sobrien for (i = MIN_SAVE_FPR; i <= MAX_SAVE_FPR; i++) 326992828Sobrien { 327092828Sobrien sym[7] = i / 10 + '0'; 327192828Sobrien sym[8] = i % 10 + '0'; 327292828Sobrien h = elf_link_hash_lookup (&htab->elf, sym, false, false, true); 327392828Sobrien if (h != NULL 327492828Sobrien && h->root.type == bfd_link_hash_undefined) 327592828Sobrien { 327692828Sobrien if (lowest_savef > i) 327792828Sobrien lowest_savef = i; 327892828Sobrien h->root.type = bfd_link_hash_defined; 327992828Sobrien h->root.u.def.section = htab->sfpr; 328092828Sobrien h->root.u.def.value = (i - lowest_savef) * 4; 328192828Sobrien h->type = STT_FUNC; 328292828Sobrien h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR; 328392828Sobrien _bfd_elf_link_hash_hide_symbol (info, h, info->shared); 328492828Sobrien } 328592828Sobrien } 328692828Sobrien 328792828Sobrien memcpy (sym, "._restf14", 10); 328892828Sobrien for (i = MIN_SAVE_FPR; i <= MAX_SAVE_FPR; i++) 328992828Sobrien { 329092828Sobrien sym[7] = i / 10 + '0'; 329192828Sobrien sym[8] = i % 10 + '0'; 329292828Sobrien h = elf_link_hash_lookup (&htab->elf, sym, false, false, true); 329392828Sobrien if (h != NULL 329492828Sobrien && h->root.type == bfd_link_hash_undefined) 329592828Sobrien { 329692828Sobrien if (lowest_restf > i) 329792828Sobrien lowest_restf = i; 329892828Sobrien h->root.type = bfd_link_hash_defined; 329992828Sobrien h->root.u.def.section = htab->sfpr; 330092828Sobrien h->root.u.def.value = ((MAX_SAVE_FPR + 2 - lowest_savef) * 4 330192828Sobrien + (i - lowest_restf) * 4); 330292828Sobrien h->type = STT_FUNC; 330392828Sobrien h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR; 330492828Sobrien _bfd_elf_link_hash_hide_symbol (info, h, info->shared); 330592828Sobrien } 330692828Sobrien } 330792828Sobrien 330899461Sobrien elf_link_hash_traverse (&htab->elf, func_desc_adjust, (PTR) info); 330999461Sobrien 331092828Sobrien htab->sfpr->_raw_size = ((MAX_SAVE_FPR + 2 - lowest_savef) * 4 331192828Sobrien + (MAX_SAVE_FPR + 2 - lowest_restf) * 4); 331292828Sobrien 331392828Sobrien if (htab->sfpr->_raw_size == 0) 331492828Sobrien { 331599461Sobrien if (!htab->have_undefweak) 331699461Sobrien { 331799461Sobrien _bfd_strip_section_from_output (info, htab->sfpr); 331899461Sobrien return true; 331999461Sobrien } 332099461Sobrien 332199461Sobrien htab->sfpr->_raw_size = 4; 332292828Sobrien } 332399461Sobrien 332499461Sobrien p = (bfd_byte *) bfd_alloc (htab->elf.dynobj, htab->sfpr->_raw_size); 332599461Sobrien if (p == NULL) 332699461Sobrien return false; 332799461Sobrien htab->sfpr->contents = p; 332899461Sobrien 332999461Sobrien for (i = lowest_savef; i <= MAX_SAVE_FPR; i++) 333092828Sobrien { 333199461Sobrien unsigned int fpr = i << 21; 333299461Sobrien unsigned int stackoff = (1 << 16) - (MAX_SAVE_FPR + 1 - i) * 8; 333399461Sobrien bfd_put_32 (htab->elf.dynobj, STFD_FR0_0R1 + fpr + stackoff, p); 333499461Sobrien p += 4; 333599461Sobrien } 333699461Sobrien if (lowest_savef <= MAX_SAVE_FPR) 333799461Sobrien { 333892828Sobrien bfd_put_32 (htab->elf.dynobj, BLR, p); 333992828Sobrien p += 4; 334099461Sobrien } 334192828Sobrien 334299461Sobrien for (i = lowest_restf; i <= MAX_SAVE_FPR; i++) 334399461Sobrien { 334499461Sobrien unsigned int fpr = i << 21; 334599461Sobrien unsigned int stackoff = (1 << 16) - (MAX_SAVE_FPR + 1 - i) * 8; 334699461Sobrien bfd_put_32 (htab->elf.dynobj, LFD_FR0_0R1 + fpr + stackoff, p); 334792828Sobrien p += 4; 334892828Sobrien } 334999461Sobrien if (lowest_restf <= MAX_SAVE_FPR 335099461Sobrien || htab->sfpr->_raw_size == 4) 335199461Sobrien { 335299461Sobrien bfd_put_32 (htab->elf.dynobj, BLR, p); 335399461Sobrien } 335492828Sobrien 335589857Sobrien return true; 335689857Sobrien} 335789857Sobrien 335889857Sobrien/* Adjust a symbol defined by a dynamic object and referenced by a 335989857Sobrien regular object. The current definition is in some section of the 336089857Sobrien dynamic object, but we're not including those sections. We have to 336189857Sobrien change the definition to something the rest of the link can 336289857Sobrien understand. */ 336389857Sobrien 336489857Sobrienstatic boolean 336589857Sobrienppc64_elf_adjust_dynamic_symbol (info, h) 336689857Sobrien struct bfd_link_info *info; 336789857Sobrien struct elf_link_hash_entry *h; 336889857Sobrien{ 336989857Sobrien struct ppc_link_hash_table *htab; 337089857Sobrien struct ppc_link_hash_entry * eh; 337189857Sobrien struct ppc_dyn_relocs *p; 337289857Sobrien asection *s; 337389857Sobrien unsigned int power_of_two; 337489857Sobrien 337589857Sobrien htab = ppc_hash_table (info); 337689857Sobrien 337789857Sobrien /* Deal with function syms. */ 337889857Sobrien if (h->type == STT_FUNC 337989857Sobrien || (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0) 338089857Sobrien { 338189857Sobrien /* Clear procedure linkage table information for any symbol that 338289857Sobrien won't need a .plt entry. */ 338389857Sobrien if (!((struct ppc_link_hash_entry *) h)->is_func_descriptor 338489857Sobrien || h->plt.refcount <= 0 338589857Sobrien || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0 338689857Sobrien || (! info->shared 338789857Sobrien && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) == 0 338889857Sobrien && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) == 0)) 338989857Sobrien { 339089857Sobrien h->plt.offset = (bfd_vma) -1; 339189857Sobrien h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; 339289857Sobrien } 339389857Sobrien return true; 339489857Sobrien } 339589857Sobrien else 339689857Sobrien h->plt.offset = (bfd_vma) -1; 339789857Sobrien 339889857Sobrien /* If this is a weak symbol, and there is a real definition, the 339989857Sobrien processor independent code will have arranged for us to see the 340089857Sobrien real definition first, and we can just use the same value. */ 340189857Sobrien if (h->weakdef != NULL) 340289857Sobrien { 340389857Sobrien BFD_ASSERT (h->weakdef->root.type == bfd_link_hash_defined 340489857Sobrien || h->weakdef->root.type == bfd_link_hash_defweak); 340589857Sobrien h->root.u.def.section = h->weakdef->root.u.def.section; 340689857Sobrien h->root.u.def.value = h->weakdef->root.u.def.value; 340789857Sobrien return true; 340889857Sobrien } 340989857Sobrien 341089857Sobrien /* This is a reference to a symbol defined by a dynamic object which 341189857Sobrien is not a function. */ 341289857Sobrien 341389857Sobrien /* If we are creating a shared library, we must presume that the 341489857Sobrien only references to the symbol are via the global offset table. 341589857Sobrien For such cases we need not do anything here; the relocations will 341689857Sobrien be handled correctly by relocate_section. */ 341789857Sobrien if (info->shared) 341889857Sobrien return true; 341989857Sobrien 342089857Sobrien /* If there are no references to this symbol that do not use the 342189857Sobrien GOT, we don't need to generate a copy reloc. */ 342289857Sobrien if ((h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0) 342389857Sobrien return true; 342489857Sobrien 342589857Sobrien eh = (struct ppc_link_hash_entry *) h; 342689857Sobrien for (p = eh->dyn_relocs; p != NULL; p = p->next) 342789857Sobrien { 342889857Sobrien s = p->sec->output_section; 342989857Sobrien if (s != NULL && (s->flags & SEC_READONLY) != 0) 343089857Sobrien break; 343189857Sobrien } 343289857Sobrien 343389857Sobrien /* If we didn't find any dynamic relocs in read-only sections, then 343489857Sobrien we'll be keeping the dynamic relocs and avoiding the copy reloc. */ 343589857Sobrien if (p == NULL) 343689857Sobrien { 343789857Sobrien h->elf_link_hash_flags &= ~ELF_LINK_NON_GOT_REF; 343889857Sobrien return true; 343989857Sobrien } 344089857Sobrien 344189857Sobrien /* We must allocate the symbol in our .dynbss section, which will 344289857Sobrien become part of the .bss section of the executable. There will be 344389857Sobrien an entry for this symbol in the .dynsym section. The dynamic 344489857Sobrien object will contain position independent code, so all references 344589857Sobrien from the dynamic object to this symbol will go through the global 344689857Sobrien offset table. The dynamic linker will use the .dynsym entry to 344789857Sobrien determine the address it must put in the global offset table, so 344889857Sobrien both the dynamic object and the regular object will refer to the 344989857Sobrien same memory location for the variable. */ 345089857Sobrien 345189857Sobrien /* We must generate a R_PPC_COPY reloc to tell the dynamic linker to 345289857Sobrien copy the initial value out of the dynamic object and into the 345389857Sobrien runtime process image. We need to remember the offset into the 345489857Sobrien .rela.bss section we are going to use. */ 345589857Sobrien if ((h->root.u.def.section->flags & SEC_ALLOC) != 0) 345689857Sobrien { 345789857Sobrien htab->srelbss->_raw_size += sizeof (Elf64_External_Rela); 345889857Sobrien h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_COPY; 345989857Sobrien } 346089857Sobrien 346189857Sobrien /* We need to figure out the alignment required for this symbol. I 346289857Sobrien have no idea how ELF linkers handle this. */ 346389857Sobrien power_of_two = bfd_log2 (h->size); 346489857Sobrien if (power_of_two > 4) 346589857Sobrien power_of_two = 4; 346689857Sobrien 346789857Sobrien /* Apply the required alignment. */ 346889857Sobrien s = htab->sdynbss; 346989857Sobrien s->_raw_size = BFD_ALIGN (s->_raw_size, (bfd_size_type) (1 << power_of_two)); 347089857Sobrien if (power_of_two > bfd_get_section_alignment (htab->elf.dynobj, s)) 347189857Sobrien { 347289857Sobrien if (! bfd_set_section_alignment (htab->elf.dynobj, s, power_of_two)) 347389857Sobrien return false; 347489857Sobrien } 347589857Sobrien 347689857Sobrien /* Define the symbol as being at this point in the section. */ 347789857Sobrien h->root.u.def.section = s; 347889857Sobrien h->root.u.def.value = s->_raw_size; 347989857Sobrien 348089857Sobrien /* Increment the section size to make room for the symbol. */ 348189857Sobrien s->_raw_size += h->size; 348289857Sobrien 348389857Sobrien return true; 348489857Sobrien} 348589857Sobrien 348689857Sobrien/* If given a function descriptor symbol, hide both the function code 348789857Sobrien sym and the descriptor. */ 348889857Sobrienstatic void 348989857Sobrienppc64_elf_hide_symbol (info, h, force_local) 349089857Sobrien struct bfd_link_info *info; 349189857Sobrien struct elf_link_hash_entry *h; 349289857Sobrien boolean force_local; 349389857Sobrien{ 349489857Sobrien _bfd_elf_link_hash_hide_symbol (info, h, force_local); 349589857Sobrien 349689857Sobrien if (((struct ppc_link_hash_entry *) h)->is_func_descriptor) 349789857Sobrien { 3498104834Sobrien struct elf_link_hash_entry *fh = ((struct ppc_link_hash_entry *) h)->oh; 349989857Sobrien 3500104834Sobrien if (fh == NULL) 3501104834Sobrien { 3502104834Sobrien const char *p, *q; 3503104834Sobrien struct ppc_link_hash_table *htab; 3504104834Sobrien char save; 3505104834Sobrien 3506104834Sobrien /* We aren't supposed to use alloca in BFD because on 3507104834Sobrien systems which do not have alloca the version in libiberty 3508104834Sobrien calls xmalloc, which might cause the program to crash 3509104834Sobrien when it runs out of memory. This function doesn't have a 3510104834Sobrien return status, so there's no way to gracefully return an 3511104834Sobrien error. So cheat. We know that string[-1] can be safely 3512104834Sobrien dereferenced; It's either a string in an ELF string 3513104834Sobrien table, or allocated in an objalloc structure. */ 3514104834Sobrien 3515104834Sobrien p = h->root.root.string - 1; 3516104834Sobrien save = *p; 3517104834Sobrien *(char *) p = '.'; 3518104834Sobrien htab = ppc_hash_table (info); 3519104834Sobrien fh = elf_link_hash_lookup (&htab->elf, p, false, false, false); 3520104834Sobrien *(char *) p = save; 3521104834Sobrien 3522104834Sobrien /* Unfortunately, if it so happens that the string we were 3523104834Sobrien looking for was allocated immediately before this string, 3524104834Sobrien then we overwrote the string terminator. That's the only 3525104834Sobrien reason the lookup should fail. */ 3526104834Sobrien if (fh == NULL) 3527104834Sobrien { 3528104834Sobrien q = h->root.root.string + strlen (h->root.root.string); 3529104834Sobrien while (q >= h->root.root.string && *q == *p) 3530104834Sobrien --q, --p; 3531104834Sobrien if (q < h->root.root.string && *p == '.') 3532104834Sobrien fh = elf_link_hash_lookup (&htab->elf, p, false, false, false); 3533104834Sobrien } 3534104834Sobrien if (fh != NULL) 3535104834Sobrien { 3536104834Sobrien ((struct ppc_link_hash_entry *) h)->oh = fh; 3537104834Sobrien ((struct ppc_link_hash_entry *) fh)->oh = h; 3538104834Sobrien } 3539104834Sobrien } 354089857Sobrien if (fh != NULL) 354189857Sobrien _bfd_elf_link_hash_hide_symbol (info, fh, force_local); 354289857Sobrien } 354389857Sobrien} 354489857Sobrien 3545104834Sobrienstatic boolean 3546104834Sobrienedit_opd (obfd, info) 3547104834Sobrien bfd *obfd; 3548104834Sobrien struct bfd_link_info *info; 3549104834Sobrien{ 3550104834Sobrien bfd *ibfd; 3551104834Sobrien unsigned int bfd_indx; 3552104834Sobrien 3553104834Sobrien for (bfd_indx = 0, ibfd = info->input_bfds; 3554104834Sobrien ibfd != NULL; 3555104834Sobrien ibfd = ibfd->link_next, bfd_indx++) 3556104834Sobrien { 3557104834Sobrien asection *sec; 3558104834Sobrien Elf_Internal_Rela *relstart, *rel, *relend; 3559104834Sobrien Elf_Internal_Shdr *symtab_hdr; 3560104834Sobrien Elf_Internal_Sym *local_syms; 3561104834Sobrien struct elf_link_hash_entry **sym_hashes; 3562104834Sobrien bfd_vma offset; 3563104834Sobrien long *adjust; 3564104834Sobrien boolean need_edit; 3565104834Sobrien 3566104834Sobrien sec = bfd_get_section_by_name (ibfd, ".opd"); 3567104834Sobrien if (sec == NULL) 3568104834Sobrien continue; 3569104834Sobrien 3570104834Sobrien adjust = (long *) elf_section_data (sec)->tdata; 3571104834Sobrien BFD_ASSERT (adjust != NULL); 3572104834Sobrien memset (adjust, 0, (size_t) sec->_raw_size * sizeof (long) / 24); 3573104834Sobrien 3574104834Sobrien if (sec->output_section == bfd_abs_section_ptr) 3575104834Sobrien continue; 3576104834Sobrien 3577104834Sobrien /* Look through the section relocs. */ 3578104834Sobrien if ((sec->flags & SEC_RELOC) == 0 || sec->reloc_count == 0) 3579104834Sobrien continue; 3580104834Sobrien 3581104834Sobrien local_syms = NULL; 3582104834Sobrien symtab_hdr = &elf_tdata (ibfd)->symtab_hdr; 3583104834Sobrien sym_hashes = elf_sym_hashes (ibfd); 3584104834Sobrien 3585104834Sobrien /* Read the relocations. */ 3586104834Sobrien relstart = _bfd_elf64_link_read_relocs (obfd, sec, (PTR) NULL, 3587104834Sobrien (Elf_Internal_Rela *) NULL, 3588104834Sobrien info->keep_memory); 3589104834Sobrien if (relstart == NULL) 3590104834Sobrien return false; 3591104834Sobrien 3592104834Sobrien /* First run through the relocs to check they are sane, and to 3593104834Sobrien determine whether we need to edit this opd section. */ 3594104834Sobrien need_edit = false; 3595104834Sobrien offset = 0; 3596104834Sobrien relend = relstart + sec->reloc_count; 3597104834Sobrien for (rel = relstart; rel < relend; rel++) 3598104834Sobrien { 3599104834Sobrien enum elf_ppc_reloc_type r_type; 3600104834Sobrien unsigned long r_symndx; 3601104834Sobrien asection *sym_sec; 3602104834Sobrien struct elf_link_hash_entry *h; 3603104834Sobrien Elf_Internal_Sym *sym; 3604104834Sobrien 3605104834Sobrien /* .opd contains a regular array of 24 byte entries. We're 3606104834Sobrien only interested in the reloc pointing to a function entry 3607104834Sobrien point. */ 3608104834Sobrien r_type = (enum elf_ppc_reloc_type) ELF64_R_TYPE (rel->r_info); 3609104834Sobrien if (r_type == R_PPC64_TOC) 3610104834Sobrien continue; 3611104834Sobrien 3612104834Sobrien if (r_type != R_PPC64_ADDR64) 3613104834Sobrien { 3614104834Sobrien (*_bfd_error_handler) 3615104834Sobrien (_("%s: unexpected reloc type %u in .opd section"), 3616104834Sobrien bfd_archive_filename (ibfd), r_type); 3617104834Sobrien need_edit = false; 3618104834Sobrien break; 3619104834Sobrien } 3620104834Sobrien 3621104834Sobrien if (rel + 1 >= relend) 3622104834Sobrien continue; 3623104834Sobrien r_type = (enum elf_ppc_reloc_type) ELF64_R_TYPE ((rel + 1)->r_info); 3624104834Sobrien if (r_type != R_PPC64_TOC) 3625104834Sobrien continue; 3626104834Sobrien 3627104834Sobrien if (rel->r_offset != offset) 3628104834Sobrien { 3629104834Sobrien /* If someone messes with .opd alignment then after a 3630104834Sobrien "ld -r" we might have padding in the middle of .opd. 3631104834Sobrien Also, there's nothing to prevent someone putting 3632104834Sobrien something silly in .opd with the assembler. No .opd 3633104834Sobrien optimization for them! */ 3634104834Sobrien (*_bfd_error_handler) 3635104834Sobrien (_("%s: .opd is not a regular array of opd entries"), 3636104834Sobrien bfd_archive_filename (ibfd)); 3637104834Sobrien need_edit = false; 3638104834Sobrien break; 3639104834Sobrien } 3640104834Sobrien 3641104834Sobrien r_symndx = ELF64_R_SYM (rel->r_info); 3642104834Sobrien sym_sec = NULL; 3643104834Sobrien h = NULL; 3644104834Sobrien sym = NULL; 3645104834Sobrien if (r_symndx >= symtab_hdr->sh_info) 3646104834Sobrien { 3647104834Sobrien h = sym_hashes[r_symndx - symtab_hdr->sh_info]; 3648104834Sobrien while (h->root.type == bfd_link_hash_indirect 3649104834Sobrien || h->root.type == bfd_link_hash_warning) 3650104834Sobrien h = (struct elf_link_hash_entry *) h->root.u.i.link; 3651104834Sobrien if (h->root.type == bfd_link_hash_defined 3652104834Sobrien || h->root.type == bfd_link_hash_defweak) 3653104834Sobrien sym_sec = h->root.u.def.section; 3654104834Sobrien } 3655104834Sobrien else 3656104834Sobrien { 3657104834Sobrien if (local_syms == NULL) 3658104834Sobrien { 3659104834Sobrien local_syms = (Elf_Internal_Sym *) symtab_hdr->contents; 3660104834Sobrien if (local_syms == NULL) 3661104834Sobrien local_syms = bfd_elf_get_elf_syms (ibfd, symtab_hdr, 3662104834Sobrien symtab_hdr->sh_info, 0, 3663104834Sobrien NULL, NULL, NULL); 3664104834Sobrien if (local_syms == NULL) 3665104834Sobrien goto error_free_rel; 3666104834Sobrien } 3667104834Sobrien sym = local_syms + r_symndx; 3668104834Sobrien if ((sym->st_shndx != SHN_UNDEF 3669104834Sobrien && sym->st_shndx < SHN_LORESERVE) 3670104834Sobrien || sym->st_shndx > SHN_HIRESERVE) 3671104834Sobrien sym_sec = bfd_section_from_elf_index (ibfd, sym->st_shndx); 3672104834Sobrien } 3673104834Sobrien 3674104834Sobrien if (sym_sec == NULL || sym_sec->owner == NULL) 3675104834Sobrien { 3676104834Sobrien (*_bfd_error_handler) 3677104834Sobrien (_("%s: undefined sym `%s' in .opd section"), 3678104834Sobrien bfd_archive_filename (ibfd), 3679104834Sobrien h != NULL ? h->root.root.string : "<local symbol>"); 3680104834Sobrien need_edit = false; 3681104834Sobrien break; 3682104834Sobrien } 3683104834Sobrien 3684104834Sobrien /* opd entries are always for functions defined in the 3685104834Sobrien current input bfd. If the symbol isn't defined in the 3686104834Sobrien input bfd, then we won't be using the function in this 3687104834Sobrien bfd; It must be defined in a linkonce section in another 3688104834Sobrien bfd, or is weak. It's also possible that we are 3689104834Sobrien discarding the function due to a linker script /DISCARD/, 3690104834Sobrien which we test for via the output_section. */ 3691104834Sobrien if (sym_sec->owner != ibfd 3692104834Sobrien || sym_sec->output_section == bfd_abs_section_ptr) 3693104834Sobrien need_edit = true; 3694104834Sobrien 3695104834Sobrien offset += 24; 3696104834Sobrien } 3697104834Sobrien 3698104834Sobrien if (need_edit) 3699104834Sobrien { 3700104834Sobrien Elf_Internal_Rela *write_rel; 3701104834Sobrien bfd_byte *rptr, *wptr; 3702104834Sobrien boolean skip; 3703104834Sobrien 3704104834Sobrien /* This seems a waste of time as input .opd sections are all 3705104834Sobrien zeros as generated by gcc, but I suppose there's no reason 3706104834Sobrien this will always be so. We might start putting something in 3707104834Sobrien the third word of .opd entries. */ 3708104834Sobrien if ((sec->flags & SEC_IN_MEMORY) == 0) 3709104834Sobrien { 3710104834Sobrien bfd_byte *loc = bfd_alloc (ibfd, sec->_raw_size); 3711104834Sobrien if (loc == NULL 3712104834Sobrien || !bfd_get_section_contents (ibfd, sec, loc, (bfd_vma) 0, 3713104834Sobrien sec->_raw_size)) 3714104834Sobrien { 3715104834Sobrien if (local_syms != NULL 3716104834Sobrien && symtab_hdr->contents != (unsigned char *) local_syms) 3717104834Sobrien free (local_syms); 3718104834Sobrien error_free_rel: 3719104834Sobrien if (elf_section_data (sec)->relocs != relstart) 3720104834Sobrien free (relstart); 3721104834Sobrien return false; 3722104834Sobrien } 3723104834Sobrien sec->contents = loc; 3724104834Sobrien sec->flags |= (SEC_IN_MEMORY | SEC_HAS_CONTENTS); 3725104834Sobrien } 3726104834Sobrien 3727104834Sobrien elf_section_data (sec)->relocs = relstart; 3728104834Sobrien 3729104834Sobrien wptr = sec->contents; 3730104834Sobrien rptr = sec->contents; 3731104834Sobrien write_rel = relstart; 3732104834Sobrien skip = false; 3733104834Sobrien offset = 0; 3734104834Sobrien for (rel = relstart; rel < relend; rel++) 3735104834Sobrien { 3736104834Sobrien if (rel->r_offset == offset) 3737104834Sobrien { 3738104834Sobrien unsigned long r_symndx; 3739104834Sobrien asection *sym_sec; 3740104834Sobrien struct elf_link_hash_entry *h; 3741104834Sobrien Elf_Internal_Sym *sym; 3742104834Sobrien 3743104834Sobrien r_symndx = ELF64_R_SYM (rel->r_info); 3744104834Sobrien sym_sec = NULL; 3745104834Sobrien h = NULL; 3746104834Sobrien sym = NULL; 3747104834Sobrien if (r_symndx >= symtab_hdr->sh_info) 3748104834Sobrien { 3749104834Sobrien h = sym_hashes[r_symndx - symtab_hdr->sh_info]; 3750104834Sobrien while (h->root.type == bfd_link_hash_indirect 3751104834Sobrien || h->root.type == bfd_link_hash_warning) 3752104834Sobrien h = (struct elf_link_hash_entry *) h->root.u.i.link; 3753104834Sobrien if (h->root.type == bfd_link_hash_defined 3754104834Sobrien || h->root.type == bfd_link_hash_defweak) 3755104834Sobrien sym_sec = h->root.u.def.section; 3756104834Sobrien } 3757104834Sobrien else 3758104834Sobrien { 3759104834Sobrien sym = local_syms + r_symndx; 3760104834Sobrien if ((sym->st_shndx != SHN_UNDEF 3761104834Sobrien && sym->st_shndx < SHN_LORESERVE) 3762104834Sobrien || sym->st_shndx > SHN_HIRESERVE) 3763104834Sobrien sym_sec = bfd_section_from_elf_index (ibfd, 3764104834Sobrien sym->st_shndx); 3765104834Sobrien } 3766104834Sobrien 3767104834Sobrien skip = (sym_sec->owner != ibfd 3768104834Sobrien || sym_sec->output_section == bfd_abs_section_ptr); 3769104834Sobrien if (skip) 3770104834Sobrien { 3771104834Sobrien if (h != NULL && sym_sec->owner == ibfd) 3772104834Sobrien { 3773104834Sobrien /* Arrange for the function descriptor sym 3774104834Sobrien to be dropped. */ 3775104834Sobrien struct elf_link_hash_entry *fdh; 3776104834Sobrien struct ppc_link_hash_entry *fh; 3777104834Sobrien 3778104834Sobrien fh = (struct ppc_link_hash_entry *) h; 3779104834Sobrien BFD_ASSERT (fh->is_func); 3780104834Sobrien fdh = fh->oh; 3781104834Sobrien fdh->root.u.def.value = 0; 3782104834Sobrien fdh->root.u.def.section = sym_sec; 3783104834Sobrien } 3784104834Sobrien } 3785104834Sobrien else 3786104834Sobrien { 3787104834Sobrien /* We'll be keeping this opd entry. */ 3788104834Sobrien 3789104834Sobrien if (h != NULL) 3790104834Sobrien { 3791104834Sobrien /* Redefine the function descriptor symbol 3792104834Sobrien to this location in the opd section. 3793104834Sobrien We've checked above that opd relocs are 3794104834Sobrien ordered. */ 3795104834Sobrien struct elf_link_hash_entry *fdh; 3796104834Sobrien struct ppc_link_hash_entry *fh; 3797104834Sobrien 3798104834Sobrien fh = (struct ppc_link_hash_entry *) h; 3799104834Sobrien BFD_ASSERT (fh->is_func); 3800104834Sobrien fdh = fh->oh; 3801104834Sobrien fdh->root.u.def.value = wptr - sec->contents; 3802104834Sobrien } 3803104834Sobrien else 3804104834Sobrien { 3805104834Sobrien /* Local syms are a bit tricky. We could 3806104834Sobrien tweak them as they can be cached, but 3807104834Sobrien we'd need to look through the local syms 3808104834Sobrien for the function descriptor sym which we 3809104834Sobrien don't have at the moment. So keep an 3810104834Sobrien array of adjustments. */ 3811107492Sobrien adjust[rel->r_offset / 24] = wptr - rptr; 3812104834Sobrien } 3813104834Sobrien 3814104834Sobrien if (wptr != rptr) 3815104834Sobrien memcpy (wptr, rptr, 24); 3816104834Sobrien wptr += 24; 3817104834Sobrien } 3818104834Sobrien rptr += 24; 3819104834Sobrien offset += 24; 3820104834Sobrien } 3821104834Sobrien 3822104834Sobrien /* We need to adjust any reloc offsets to point to the 3823104834Sobrien new opd entries. While we're at it, we may as well 3824104834Sobrien remove redundant relocs. */ 3825104834Sobrien if (!skip) 3826104834Sobrien { 3827104834Sobrien rel->r_offset += wptr - rptr; 3828104834Sobrien if (write_rel != rel) 3829104834Sobrien memcpy (write_rel, rel, sizeof (*rel)); 3830104834Sobrien ++write_rel; 3831104834Sobrien } 3832104834Sobrien } 3833104834Sobrien 3834104834Sobrien sec->_cooked_size = wptr - sec->contents; 3835104834Sobrien sec->reloc_count = write_rel - relstart; 3836104834Sobrien } 3837104834Sobrien else if (elf_section_data (sec)->relocs != relstart) 3838104834Sobrien free (relstart); 3839104834Sobrien 3840104834Sobrien if (local_syms != NULL 3841104834Sobrien && symtab_hdr->contents != (unsigned char *) local_syms) 3842104834Sobrien { 3843104834Sobrien if (!info->keep_memory) 3844104834Sobrien free (local_syms); 3845104834Sobrien else 3846104834Sobrien symtab_hdr->contents = (unsigned char *) local_syms; 3847104834Sobrien } 3848104834Sobrien } 3849104834Sobrien 3850104834Sobrien return true; 3851104834Sobrien} 3852104834Sobrien 385389857Sobrien/* This is the condition under which ppc64_elf_finish_dynamic_symbol 385489857Sobrien will be called from elflink.h. If elflink.h doesn't call our 385589857Sobrien finish_dynamic_symbol routine, we'll need to do something about 385689857Sobrien initializing any .plt and .got entries in ppc64_elf_relocate_section. */ 385789857Sobrien#define WILL_CALL_FINISH_DYNAMIC_SYMBOL(DYN, INFO, H) \ 385889857Sobrien ((DYN) \ 385989857Sobrien && ((INFO)->shared \ 386089857Sobrien || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) \ 386189857Sobrien && ((H)->dynindx != -1 \ 386289857Sobrien || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0)) 386389857Sobrien 386489857Sobrien/* Allocate space in .plt, .got and associated reloc sections for 386589857Sobrien dynamic relocs. */ 386689857Sobrien 386789857Sobrienstatic boolean 386889857Sobrienallocate_dynrelocs (h, inf) 386989857Sobrien struct elf_link_hash_entry *h; 387089857Sobrien PTR inf; 387189857Sobrien{ 387289857Sobrien struct bfd_link_info *info; 387389857Sobrien struct ppc_link_hash_table *htab; 387489857Sobrien asection *s; 387589857Sobrien struct ppc_link_hash_entry *eh; 387689857Sobrien struct ppc_dyn_relocs *p; 387789857Sobrien 387894536Sobrien if (h->root.type == bfd_link_hash_indirect) 387989857Sobrien return true; 388089857Sobrien 388194536Sobrien if (h->root.type == bfd_link_hash_warning) 388294536Sobrien h = (struct elf_link_hash_entry *) h->root.u.i.link; 388394536Sobrien 388489857Sobrien info = (struct bfd_link_info *) inf; 388589857Sobrien htab = ppc_hash_table (info); 388689857Sobrien 388789857Sobrien if (htab->elf.dynamic_sections_created 388889857Sobrien && h->plt.refcount > 0 388989857Sobrien && h->dynindx != -1) 389089857Sobrien { 389189857Sobrien BFD_ASSERT (((struct ppc_link_hash_entry *) h)->is_func_descriptor); 389289857Sobrien 389389857Sobrien if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info, h)) 389489857Sobrien { 389589857Sobrien /* If this is the first .plt entry, make room for the special 389689857Sobrien first entry. */ 389789857Sobrien s = htab->splt; 389889857Sobrien if (s->_raw_size == 0) 389989857Sobrien s->_raw_size += PLT_INITIAL_ENTRY_SIZE; 390089857Sobrien 390189857Sobrien h->plt.offset = s->_raw_size; 390289857Sobrien 390389857Sobrien /* Make room for this entry. */ 390489857Sobrien s->_raw_size += PLT_ENTRY_SIZE; 390589857Sobrien 3906104834Sobrien /* Make room for the .glink code. */ 390789857Sobrien s = htab->sglink; 390889857Sobrien if (s->_raw_size == 0) 390989857Sobrien s->_raw_size += GLINK_CALL_STUB_SIZE; 391089857Sobrien /* We need bigger stubs past index 32767. */ 391189857Sobrien if (s->_raw_size >= GLINK_CALL_STUB_SIZE + 32768*2*4) 391289857Sobrien s->_raw_size += 4; 391389857Sobrien s->_raw_size += 2*4; 391489857Sobrien 391589857Sobrien /* We also need to make an entry in the .rela.plt section. */ 391689857Sobrien s = htab->srelplt; 391789857Sobrien s->_raw_size += sizeof (Elf64_External_Rela); 391889857Sobrien } 391989857Sobrien else 392089857Sobrien { 392189857Sobrien h->plt.offset = (bfd_vma) -1; 392289857Sobrien h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; 392389857Sobrien } 392489857Sobrien } 392589857Sobrien else 392689857Sobrien { 392789857Sobrien h->plt.offset = (bfd_vma) -1; 392889857Sobrien h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; 392989857Sobrien } 393089857Sobrien 393189857Sobrien if (h->got.refcount > 0) 393289857Sobrien { 393389857Sobrien boolean dyn; 393489857Sobrien 393589857Sobrien /* Make sure this symbol is output as a dynamic symbol. 393689857Sobrien Undefined weak syms won't yet be marked as dynamic. */ 393789857Sobrien if (h->dynindx == -1 393889857Sobrien && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) 393989857Sobrien { 394089857Sobrien if (! bfd_elf64_link_record_dynamic_symbol (info, h)) 394189857Sobrien return false; 394289857Sobrien } 394389857Sobrien 394489857Sobrien s = htab->sgot; 394589857Sobrien h->got.offset = s->_raw_size; 394689857Sobrien s->_raw_size += 8; 394789857Sobrien dyn = htab->elf.dynamic_sections_created; 394889857Sobrien if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h)) 394989857Sobrien htab->srelgot->_raw_size += sizeof (Elf64_External_Rela); 395089857Sobrien } 395189857Sobrien else 395289857Sobrien h->got.offset = (bfd_vma) -1; 395389857Sobrien 395489857Sobrien eh = (struct ppc_link_hash_entry *) h; 395589857Sobrien if (eh->dyn_relocs == NULL) 395689857Sobrien return true; 395789857Sobrien 395889857Sobrien /* In the shared -Bsymbolic case, discard space allocated for 395989857Sobrien dynamic pc-relative relocs against symbols which turn out to be 396089857Sobrien defined in regular objects. For the normal shared case, discard 396189857Sobrien space for relocs that have become local due to symbol visibility 396289857Sobrien changes. */ 396389857Sobrien 396489857Sobrien if (info->shared) 396589857Sobrien { 396689857Sobrien if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0 396789857Sobrien && ((h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0 396889857Sobrien || info->symbolic)) 396989857Sobrien { 397089857Sobrien struct ppc_dyn_relocs **pp; 397189857Sobrien 397289857Sobrien for (pp = &eh->dyn_relocs; (p = *pp) != NULL; ) 397389857Sobrien { 397489857Sobrien p->count -= p->pc_count; 397589857Sobrien p->pc_count = 0; 397689857Sobrien if (p->count == 0) 397789857Sobrien *pp = p->next; 397889857Sobrien else 397989857Sobrien pp = &p->next; 398089857Sobrien } 398189857Sobrien } 398289857Sobrien } 398389857Sobrien else 398489857Sobrien { 398589857Sobrien /* For the non-shared case, discard space for relocs against 398689857Sobrien symbols which turn out to need copy relocs or are not 398789857Sobrien dynamic. */ 398889857Sobrien 398989857Sobrien if ((h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0 399089857Sobrien && (((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0 399189857Sobrien && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) 399289857Sobrien || (htab->elf.dynamic_sections_created 399389857Sobrien && (h->root.type == bfd_link_hash_undefweak 399489857Sobrien || h->root.type == bfd_link_hash_undefined)))) 399589857Sobrien { 399689857Sobrien /* Make sure this symbol is output as a dynamic symbol. 399789857Sobrien Undefined weak syms won't yet be marked as dynamic. */ 399889857Sobrien if (h->dynindx == -1 399989857Sobrien && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) 400089857Sobrien { 400189857Sobrien if (! bfd_elf64_link_record_dynamic_symbol (info, h)) 400289857Sobrien return false; 400389857Sobrien } 400489857Sobrien 400589857Sobrien /* If that succeeded, we know we'll be keeping all the 400689857Sobrien relocs. */ 400789857Sobrien if (h->dynindx != -1) 400889857Sobrien goto keep; 400989857Sobrien } 401089857Sobrien 401189857Sobrien eh->dyn_relocs = NULL; 401289857Sobrien 401389857Sobrien keep: ; 401489857Sobrien } 401589857Sobrien 401689857Sobrien /* Finally, allocate space. */ 401789857Sobrien for (p = eh->dyn_relocs; p != NULL; p = p->next) 401889857Sobrien { 401989857Sobrien asection *sreloc = elf_section_data (p->sec)->sreloc; 402089857Sobrien sreloc->_raw_size += p->count * sizeof (Elf64_External_Rela); 402189857Sobrien } 402289857Sobrien 402389857Sobrien return true; 402489857Sobrien} 402589857Sobrien 402689857Sobrien/* Find any dynamic relocs that apply to read-only sections. */ 402789857Sobrien 402889857Sobrienstatic boolean 402989857Sobrienreadonly_dynrelocs (h, inf) 403089857Sobrien struct elf_link_hash_entry *h; 403189857Sobrien PTR inf; 403289857Sobrien{ 403389857Sobrien struct ppc_link_hash_entry *eh; 403489857Sobrien struct ppc_dyn_relocs *p; 403589857Sobrien 403694536Sobrien if (h->root.type == bfd_link_hash_warning) 403794536Sobrien h = (struct elf_link_hash_entry *) h->root.u.i.link; 403894536Sobrien 403989857Sobrien eh = (struct ppc_link_hash_entry *) h; 404089857Sobrien for (p = eh->dyn_relocs; p != NULL; p = p->next) 404189857Sobrien { 404289857Sobrien asection *s = p->sec->output_section; 404389857Sobrien 404489857Sobrien if (s != NULL && (s->flags & SEC_READONLY) != 0) 404589857Sobrien { 404689857Sobrien struct bfd_link_info *info = (struct bfd_link_info *) inf; 404789857Sobrien 404889857Sobrien info->flags |= DF_TEXTREL; 404989857Sobrien 405089857Sobrien /* Not an error, just cut short the traversal. */ 405189857Sobrien return false; 405289857Sobrien } 405389857Sobrien } 405489857Sobrien return true; 405589857Sobrien} 405689857Sobrien 405789857Sobrien/* Set the sizes of the dynamic sections. */ 405889857Sobrien 405989857Sobrienstatic boolean 406089857Sobrienppc64_elf_size_dynamic_sections (output_bfd, info) 406189857Sobrien bfd *output_bfd ATTRIBUTE_UNUSED; 406289857Sobrien struct bfd_link_info *info; 406389857Sobrien{ 406489857Sobrien struct ppc_link_hash_table *htab; 406589857Sobrien bfd *dynobj; 406689857Sobrien asection *s; 406789857Sobrien boolean relocs; 406889857Sobrien bfd *ibfd; 406989857Sobrien 407089857Sobrien htab = ppc_hash_table (info); 407189857Sobrien dynobj = htab->elf.dynobj; 407289857Sobrien if (dynobj == NULL) 407389857Sobrien abort (); 407489857Sobrien 407589857Sobrien if (htab->elf.dynamic_sections_created) 407689857Sobrien { 407789857Sobrien /* Set the contents of the .interp section to the interpreter. */ 407889857Sobrien if (! info->shared) 407989857Sobrien { 408089857Sobrien s = bfd_get_section_by_name (dynobj, ".interp"); 408189857Sobrien if (s == NULL) 408289857Sobrien abort (); 408389857Sobrien s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER; 408489857Sobrien s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER; 408589857Sobrien } 408689857Sobrien } 408789857Sobrien 408889857Sobrien /* Set up .got offsets for local syms, and space for local dynamic 408989857Sobrien relocs. */ 409089857Sobrien for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) 409189857Sobrien { 409289857Sobrien bfd_signed_vma *local_got; 409389857Sobrien bfd_signed_vma *end_local_got; 409489857Sobrien bfd_size_type locsymcount; 409589857Sobrien Elf_Internal_Shdr *symtab_hdr; 409689857Sobrien asection *srel; 409789857Sobrien 409889857Sobrien if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour) 409989857Sobrien continue; 410089857Sobrien 410189857Sobrien for (s = ibfd->sections; s != NULL; s = s->next) 410289857Sobrien { 410389857Sobrien struct ppc_dyn_relocs *p; 410489857Sobrien 410589857Sobrien for (p = *((struct ppc_dyn_relocs **) 410689857Sobrien &elf_section_data (s)->local_dynrel); 410789857Sobrien p != NULL; 410889857Sobrien p = p->next) 410989857Sobrien { 411089857Sobrien if (!bfd_is_abs_section (p->sec) 411189857Sobrien && bfd_is_abs_section (p->sec->output_section)) 411289857Sobrien { 411389857Sobrien /* Input section has been discarded, either because 411489857Sobrien it is a copy of a linkonce section or due to 411589857Sobrien linker script /DISCARD/, so we'll be discarding 411689857Sobrien the relocs too. */ 411789857Sobrien } 411891041Sobrien else if (p->count != 0) 411989857Sobrien { 412089857Sobrien srel = elf_section_data (p->sec)->sreloc; 412189857Sobrien srel->_raw_size += p->count * sizeof (Elf64_External_Rela); 412291041Sobrien if ((p->sec->output_section->flags & SEC_READONLY) != 0) 412391041Sobrien info->flags |= DF_TEXTREL; 412489857Sobrien } 412589857Sobrien } 412689857Sobrien } 412789857Sobrien 412889857Sobrien local_got = elf_local_got_refcounts (ibfd); 412989857Sobrien if (!local_got) 413089857Sobrien continue; 413189857Sobrien 413289857Sobrien symtab_hdr = &elf_tdata (ibfd)->symtab_hdr; 413389857Sobrien locsymcount = symtab_hdr->sh_info; 413489857Sobrien end_local_got = local_got + locsymcount; 413589857Sobrien s = htab->sgot; 413689857Sobrien srel = htab->srelgot; 413789857Sobrien for (; local_got < end_local_got; ++local_got) 413889857Sobrien { 413989857Sobrien if (*local_got > 0) 414089857Sobrien { 414189857Sobrien *local_got = s->_raw_size; 414289857Sobrien s->_raw_size += 8; 414389857Sobrien if (info->shared) 414489857Sobrien srel->_raw_size += sizeof (Elf64_External_Rela); 414589857Sobrien } 414689857Sobrien else 414789857Sobrien *local_got = (bfd_vma) -1; 414889857Sobrien } 414989857Sobrien } 415089857Sobrien 4151104834Sobrien if (!edit_opd (output_bfd, info)) 4152104834Sobrien return false; 4153104834Sobrien 415489857Sobrien /* Allocate global sym .plt and .got entries, and space for global 415589857Sobrien sym dynamic relocs. */ 415689857Sobrien elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, (PTR) info); 415789857Sobrien 415889857Sobrien /* We now have determined the sizes of the various dynamic sections. 415989857Sobrien Allocate memory for them. */ 416089857Sobrien relocs = false; 416189857Sobrien for (s = dynobj->sections; s != NULL; s = s->next) 416289857Sobrien { 416389857Sobrien if ((s->flags & SEC_LINKER_CREATED) == 0) 416489857Sobrien continue; 416589857Sobrien 4166104834Sobrien if (s == htab->sbrlt || s == htab->srelbrlt) 4167104834Sobrien /* These haven't been allocated yet; don't strip. */ 4168104834Sobrien continue; 4169104834Sobrien else if (s == htab->splt 4170104834Sobrien || s == htab->sgot 4171104834Sobrien || s == htab->sglink) 417289857Sobrien { 417389857Sobrien /* Strip this section if we don't need it; see the 417489857Sobrien comment below. */ 417589857Sobrien } 417689857Sobrien else if (strncmp (bfd_get_section_name (dynobj, s), ".rela", 5) == 0) 417789857Sobrien { 417889857Sobrien if (s->_raw_size == 0) 417989857Sobrien { 418089857Sobrien /* If we don't need this section, strip it from the 418189857Sobrien output file. This is mostly to handle .rela.bss and 418289857Sobrien .rela.plt. We must create both sections in 418389857Sobrien create_dynamic_sections, because they must be created 418489857Sobrien before the linker maps input sections to output 418589857Sobrien sections. The linker does that before 418689857Sobrien adjust_dynamic_symbol is called, and it is that 418789857Sobrien function which decides whether anything needs to go 418889857Sobrien into these sections. */ 418989857Sobrien } 419089857Sobrien else 419189857Sobrien { 419289857Sobrien if (s != htab->srelplt) 419389857Sobrien relocs = true; 419489857Sobrien 419589857Sobrien /* We use the reloc_count field as a counter if we need 419689857Sobrien to copy relocs into the output file. */ 419789857Sobrien s->reloc_count = 0; 419889857Sobrien } 419989857Sobrien } 420089857Sobrien else 420189857Sobrien { 420289857Sobrien /* It's not one of our sections, so don't allocate space. */ 420389857Sobrien continue; 420489857Sobrien } 420589857Sobrien 420689857Sobrien if (s->_raw_size == 0) 420789857Sobrien { 420889857Sobrien _bfd_strip_section_from_output (info, s); 420989857Sobrien continue; 421089857Sobrien } 421189857Sobrien 4212104834Sobrien /* .plt is in the bss section. We don't initialise it. */ 4213104834Sobrien if ((s->flags & SEC_LOAD) == 0) 4214104834Sobrien continue; 4215104834Sobrien 421689857Sobrien /* Allocate memory for the section contents. We use bfd_zalloc 421789857Sobrien here in case unused entries are not reclaimed before the 421889857Sobrien section's contents are written out. This should not happen, 421989857Sobrien but this way if it does, we get a R_PPC64_NONE reloc instead 422089857Sobrien of garbage. */ 4221104834Sobrien s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size); 422289857Sobrien if (s->contents == NULL) 422389857Sobrien return false; 422489857Sobrien } 422589857Sobrien 422689857Sobrien if (htab->elf.dynamic_sections_created) 422789857Sobrien { 422889857Sobrien /* Add some entries to the .dynamic section. We fill in the 422989857Sobrien values later, in ppc64_elf_finish_dynamic_sections, but we 423089857Sobrien must add the entries now so that we get the correct size for 423189857Sobrien the .dynamic section. The DT_DEBUG entry is filled in by the 423289857Sobrien dynamic linker and used by the debugger. */ 423389857Sobrien#define add_dynamic_entry(TAG, VAL) \ 423489857Sobrien bfd_elf64_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL)) 423589857Sobrien 423689857Sobrien if (!info->shared) 423789857Sobrien { 423889857Sobrien if (!add_dynamic_entry (DT_DEBUG, 0)) 423989857Sobrien return false; 424089857Sobrien } 424189857Sobrien 4242104834Sobrien if (htab->splt != NULL && htab->splt->_raw_size != 0) 424389857Sobrien { 424489857Sobrien if (!add_dynamic_entry (DT_PLTGOT, 0) 424589857Sobrien || !add_dynamic_entry (DT_PLTRELSZ, 0) 424689857Sobrien || !add_dynamic_entry (DT_PLTREL, DT_RELA) 424789857Sobrien || !add_dynamic_entry (DT_JMPREL, 0) 424889857Sobrien || !add_dynamic_entry (DT_PPC64_GLINK, 0)) 424989857Sobrien return false; 425089857Sobrien } 425189857Sobrien 425291041Sobrien if (NO_OPD_RELOCS) 425391041Sobrien { 425491041Sobrien if (!add_dynamic_entry (DT_PPC64_OPD, 0) 425591041Sobrien || !add_dynamic_entry (DT_PPC64_OPDSZ, 0)) 425691041Sobrien return false; 425791041Sobrien } 425891041Sobrien 425989857Sobrien if (relocs) 426089857Sobrien { 426189857Sobrien if (!add_dynamic_entry (DT_RELA, 0) 426289857Sobrien || !add_dynamic_entry (DT_RELASZ, 0) 426389857Sobrien || !add_dynamic_entry (DT_RELAENT, sizeof (Elf64_External_Rela))) 426489857Sobrien return false; 426589857Sobrien 426689857Sobrien /* If any dynamic relocs apply to a read-only section, 426789857Sobrien then we need a DT_TEXTREL entry. */ 426891041Sobrien if ((info->flags & DF_TEXTREL) == 0) 426991041Sobrien elf_link_hash_traverse (&htab->elf, readonly_dynrelocs, 427091041Sobrien (PTR) info); 427189857Sobrien 427289857Sobrien if ((info->flags & DF_TEXTREL) != 0) 427389857Sobrien { 427489857Sobrien if (!add_dynamic_entry (DT_TEXTREL, 0)) 427589857Sobrien return false; 427689857Sobrien } 427789857Sobrien } 427889857Sobrien } 427989857Sobrien#undef add_dynamic_entry 428089857Sobrien 428189857Sobrien return true; 428289857Sobrien} 428389857Sobrien 4284104834Sobrien/* Determine the type of stub needed, if any, for a call. */ 428589857Sobrien 4286104834Sobrienstatic INLINE enum ppc_stub_type 4287104834Sobrienppc_type_of_stub (input_sec, rel, hash, destination) 4288104834Sobrien asection *input_sec; 4289104834Sobrien const Elf_Internal_Rela *rel; 4290104834Sobrien struct ppc_link_hash_entry **hash; 4291104834Sobrien bfd_vma destination; 429289857Sobrien{ 4293104834Sobrien struct ppc_link_hash_entry *h = *hash; 4294104834Sobrien bfd_vma location; 4295104834Sobrien bfd_vma branch_offset; 4296104834Sobrien bfd_vma max_branch_offset; 4297104834Sobrien unsigned int r_type; 429899461Sobrien 4299104834Sobrien if (h != NULL) 430089857Sobrien { 4301104834Sobrien if (h->oh != NULL 4302104834Sobrien && h->oh->plt.offset != (bfd_vma) -1 4303104834Sobrien && h->oh->dynindx != -1) 4304104834Sobrien { 4305104834Sobrien *hash = (struct ppc_link_hash_entry *) h->oh; 4306104834Sobrien return ppc_stub_plt_call; 4307104834Sobrien } 430889857Sobrien 4309104834Sobrien if (h->elf.root.type == bfd_link_hash_undefweak 4310104834Sobrien || h->elf.root.type == bfd_link_hash_undefined) 4311104834Sobrien return ppc_stub_none; 431299461Sobrien } 431389857Sobrien 4314104834Sobrien /* Determine where the call point is. */ 4315104834Sobrien location = (input_sec->output_offset 4316104834Sobrien + input_sec->output_section->vma 4317104834Sobrien + rel->r_offset); 431889857Sobrien 4319104834Sobrien branch_offset = destination - location; 4320104834Sobrien r_type = ELF64_R_TYPE (rel->r_info); 432189857Sobrien 4322104834Sobrien /* Determine if a long branch stub is needed. */ 4323104834Sobrien max_branch_offset = 1 << 25; 4324104834Sobrien if (r_type != (unsigned int) R_PPC64_REL24) 4325104834Sobrien max_branch_offset = 1 << 15; 432689857Sobrien 4327104834Sobrien if (branch_offset + max_branch_offset >= 2 * max_branch_offset) 4328104834Sobrien /* We need a stub. Figure out whether a long_branch or plt_branch 4329104834Sobrien is needed later. */ 4330104834Sobrien return ppc_stub_long_branch; 433189857Sobrien 4332104834Sobrien return ppc_stub_none; 433389857Sobrien} 433489857Sobrien 433589857Sobrien/* Build a .plt call stub. */ 433689857Sobrien 433789857Sobrienstatic bfd_byte * 433889857Sobrienbuild_plt_stub (obfd, p, offset, glink) 433989857Sobrien bfd *obfd; 434089857Sobrien bfd_byte *p; 434189857Sobrien int offset; 434289857Sobrien int glink; 434389857Sobrien{ 434489857Sobrien#define PPC_LO(v) ((v) & 0xffff) 434589857Sobrien#define PPC_HI(v) (((v) >> 16) & 0xffff) 434689857Sobrien#define PPC_HA(v) PPC_HI ((v) + 0x8000) 434789857Sobrien 434889857Sobrien if (glink) 434989857Sobrien bfd_put_32 (obfd, LD_R2_40R1, p), p += 4; 435089857Sobrien bfd_put_32 (obfd, ADDIS_R12_R2 | PPC_HA (offset), p), p += 4; 435189857Sobrien if (!glink) 435289857Sobrien bfd_put_32 (obfd, STD_R2_40R1, p), p += 4; 435389857Sobrien bfd_put_32 (obfd, LD_R11_0R12 | PPC_LO (offset), p), p += 4; 435489857Sobrien if (PPC_HA (offset + 8) != PPC_HA (offset)) 435589857Sobrien bfd_put_32 (obfd, ADDIS_R12_R12_1, p), p += 4; 435689857Sobrien offset += 8; 435789857Sobrien bfd_put_32 (obfd, LD_R2_0R12 | PPC_LO (offset), p), p += 4; 435889857Sobrien if (PPC_HA (offset + 8) != PPC_HA (offset)) 435989857Sobrien bfd_put_32 (obfd, ADDIS_R12_R12_1, p), p += 4; 436089857Sobrien offset += 8; 436189857Sobrien bfd_put_32 (obfd, MTCTR_R11, p), p += 4; 436289857Sobrien bfd_put_32 (obfd, LD_R11_0R12 | PPC_LO (offset), p), p += 4; 436389857Sobrien bfd_put_32 (obfd, BCTR, p), p += 4; 436489857Sobrien return p; 436589857Sobrien} 436689857Sobrien 436789857Sobrienstatic boolean 4368104834Sobrienppc_build_one_stub (gen_entry, in_arg) 4369104834Sobrien struct bfd_hash_entry *gen_entry; 4370104834Sobrien PTR in_arg; 437189857Sobrien{ 4372104834Sobrien struct ppc_stub_hash_entry *stub_entry; 4373104834Sobrien struct ppc_branch_hash_entry *br_entry; 437489857Sobrien struct bfd_link_info *info; 437589857Sobrien struct ppc_link_hash_table *htab; 4376104834Sobrien asection *stub_sec; 4377104834Sobrien bfd *stub_bfd; 4378104834Sobrien bfd_byte *loc; 4379104834Sobrien bfd_byte *p; 4380104834Sobrien unsigned int indx; 4381104834Sobrien bfd_vma off; 4382104834Sobrien int size; 438389857Sobrien 4384104834Sobrien /* Massage our args to the form they really have. */ 4385104834Sobrien stub_entry = (struct ppc_stub_hash_entry *) gen_entry; 4386104834Sobrien info = (struct bfd_link_info *) in_arg; 438789857Sobrien 438889857Sobrien htab = ppc_hash_table (info); 4389104834Sobrien stub_sec = stub_entry->stub_sec; 439089857Sobrien 4391104834Sobrien /* Make a note of the offset within the stubs for this entry. */ 4392104834Sobrien stub_entry->stub_offset = stub_sec->_cooked_size; 4393104834Sobrien loc = stub_sec->contents + stub_entry->stub_offset; 4394104834Sobrien 4395104834Sobrien stub_bfd = stub_sec->owner; 4396104834Sobrien 4397104834Sobrien switch (stub_entry->stub_type) 439889857Sobrien { 4399104834Sobrien case ppc_stub_long_branch: 4400104834Sobrien /* Branches are relative. This is where we are going to. */ 4401104834Sobrien off = (stub_entry->target_value 4402104834Sobrien + stub_entry->target_section->output_offset 4403104834Sobrien + stub_entry->target_section->output_section->vma); 440489857Sobrien 4405104834Sobrien /* And this is where we are coming from. */ 4406104834Sobrien off -= (stub_entry->stub_offset 4407104834Sobrien + stub_sec->output_offset 4408104834Sobrien + stub_sec->output_section->vma); 440989857Sobrien 4410104834Sobrien BFD_ASSERT (off + (1 << 25) < (bfd_vma) (1 << 26)); 441189857Sobrien 4412104834Sobrien bfd_put_32 (stub_bfd, (bfd_vma) B_DOT | (off & 0x3fffffc), loc); 4413104834Sobrien size = 4; 4414104834Sobrien break; 441589857Sobrien 4416104834Sobrien case ppc_stub_plt_branch: 4417104834Sobrien br_entry = ppc_branch_hash_lookup (&htab->branch_hash_table, 4418104834Sobrien stub_entry->root.string + 9, 4419104834Sobrien false, false); 4420104834Sobrien if (br_entry == NULL) 4421104834Sobrien { 4422104834Sobrien (*_bfd_error_handler) (_("can't find branch stub `%s'"), 4423104834Sobrien stub_entry->root.string + 9); 4424104834Sobrien htab->stub_error = true; 4425104834Sobrien return false; 4426104834Sobrien } 442789857Sobrien 4428104834Sobrien off = (stub_entry->target_value 4429104834Sobrien + stub_entry->target_section->output_offset 4430104834Sobrien + stub_entry->target_section->output_section->vma); 4431104834Sobrien 4432104834Sobrien bfd_put_64 (htab->sbrlt->owner, off, 4433104834Sobrien htab->sbrlt->contents + br_entry->offset); 4434104834Sobrien 4435104834Sobrien if (info->shared) 443689857Sobrien { 4437104834Sobrien /* Create a reloc for the branch lookup table entry. */ 4438104834Sobrien Elf_Internal_Rela rela; 4439104834Sobrien Elf64_External_Rela *r; 4440104834Sobrien 4441104834Sobrien rela.r_offset = (br_entry->offset 4442104834Sobrien + htab->sbrlt->output_offset 4443104834Sobrien + htab->sbrlt->output_section->vma); 4444104834Sobrien rela.r_info = ELF64_R_INFO (0, R_PPC64_RELATIVE); 4445104834Sobrien rela.r_addend = off; 4446104834Sobrien 4447104834Sobrien r = (Elf64_External_Rela *) htab->srelbrlt->contents; 4448104834Sobrien r += htab->srelbrlt->reloc_count++; 4449104834Sobrien bfd_elf64_swap_reloca_out (htab->srelbrlt->owner, &rela, r); 4450104834Sobrien } 4451104834Sobrien 4452104834Sobrien off = (br_entry->offset 4453104834Sobrien + htab->sbrlt->output_offset 4454104834Sobrien + htab->sbrlt->output_section->vma 4455104834Sobrien - elf_gp (htab->sbrlt->output_section->owner) 4456104834Sobrien - TOC_BASE_OFF); 4457104834Sobrien 4458104834Sobrien if (off + 0x80000000 > 0xffffffff || (off & 7) != 0) 4459104834Sobrien { 446089857Sobrien (*_bfd_error_handler) 446189857Sobrien (_("linkage table error against `%s'"), 4462104834Sobrien stub_entry->root.string); 446389857Sobrien bfd_set_error (bfd_error_bad_value); 4464104834Sobrien htab->stub_error = true; 446589857Sobrien return false; 446689857Sobrien } 446789857Sobrien 4468104834Sobrien indx = off; 4469104834Sobrien bfd_put_32 (stub_bfd, (bfd_vma) ADDIS_R12_R2 | PPC_HA (indx), loc); 4470104834Sobrien bfd_put_32 (stub_bfd, (bfd_vma) LD_R11_0R12 | PPC_LO (indx), loc + 4); 4471104834Sobrien bfd_put_32 (stub_bfd, (bfd_vma) MTCTR_R11, loc + 8); 4472104834Sobrien bfd_put_32 (stub_bfd, (bfd_vma) BCTR, loc + 12); 4473104834Sobrien size = 16; 4474104834Sobrien break; 447589857Sobrien 4476104834Sobrien case ppc_stub_plt_call: 4477104834Sobrien /* Do the best we can for shared libraries built without 4478104834Sobrien exporting ".foo" for each "foo". This can happen when symbol 4479104834Sobrien versioning scripts strip all bar a subset of symbols. */ 4480104834Sobrien if (stub_entry->h->oh->root.type != bfd_link_hash_defined 4481104834Sobrien && stub_entry->h->oh->root.type != bfd_link_hash_defweak) 448289857Sobrien { 4483104834Sobrien /* Point the symbol at the stub. There may be multiple stubs, 4484104834Sobrien we don't really care; The main thing is to make this sym 4485104834Sobrien defined somewhere. */ 4486104834Sobrien stub_entry->h->oh->root.type = bfd_link_hash_defined; 4487104834Sobrien stub_entry->h->oh->root.u.def.section = stub_entry->stub_sec; 4488104834Sobrien stub_entry->h->oh->root.u.def.value = stub_entry->stub_offset; 448989857Sobrien } 4490104834Sobrien 4491104834Sobrien /* Now build the stub. */ 4492104834Sobrien off = stub_entry->h->elf.plt.offset; 4493104834Sobrien if (off >= (bfd_vma) -2) 4494104834Sobrien abort (); 4495104834Sobrien 4496104834Sobrien off &= ~ (bfd_vma) 1; 4497104834Sobrien off += (htab->splt->output_offset 4498104834Sobrien + htab->splt->output_section->vma 4499104834Sobrien - elf_gp (htab->splt->output_section->owner) 4500104834Sobrien - TOC_BASE_OFF); 4501104834Sobrien 4502104834Sobrien if (off + 0x80000000 > 0xffffffff || (off & 7) != 0) 450389857Sobrien { 4504104834Sobrien (*_bfd_error_handler) 4505104834Sobrien (_("linkage table error against `%s'"), 4506104834Sobrien stub_entry->h->elf.root.root.string); 4507104834Sobrien bfd_set_error (bfd_error_bad_value); 4508104834Sobrien htab->stub_error = true; 4509104834Sobrien return false; 451089857Sobrien } 4511104834Sobrien 4512104834Sobrien p = build_plt_stub (stub_bfd, loc, (int) off, 0); 4513104834Sobrien size = p - loc; 4514104834Sobrien break; 4515104834Sobrien 4516104834Sobrien default: 4517104834Sobrien BFD_FAIL (); 4518104834Sobrien return false; 451989857Sobrien } 4520104834Sobrien 4521104834Sobrien stub_sec->_cooked_size += size; 452289857Sobrien return true; 452389857Sobrien} 452489857Sobrien 4525104834Sobrien/* As above, but don't actually build the stub. Just bump offset so 4526104834Sobrien we know stub section sizes, and select plt_branch stubs where 4527104834Sobrien long_branch stubs won't do. */ 4528104834Sobrien 4529104834Sobrienstatic boolean 4530104834Sobrienppc_size_one_stub (gen_entry, in_arg) 4531104834Sobrien struct bfd_hash_entry *gen_entry; 4532104834Sobrien PTR in_arg; 4533104834Sobrien{ 4534104834Sobrien struct ppc_stub_hash_entry *stub_entry; 4535104834Sobrien struct ppc_link_hash_table *htab; 4536104834Sobrien bfd_vma off; 4537104834Sobrien int size; 4538104834Sobrien 4539104834Sobrien /* Massage our args to the form they really have. */ 4540104834Sobrien stub_entry = (struct ppc_stub_hash_entry *) gen_entry; 4541104834Sobrien htab = (struct ppc_link_hash_table *) in_arg; 4542104834Sobrien 4543104834Sobrien if (stub_entry->stub_type == ppc_stub_plt_call) 4544104834Sobrien { 4545104834Sobrien off = stub_entry->h->elf.plt.offset & ~(bfd_vma) 1; 4546104834Sobrien off += (htab->splt->output_offset 4547104834Sobrien + htab->splt->output_section->vma 4548104834Sobrien - elf_gp (htab->splt->output_section->owner) 4549104834Sobrien - TOC_BASE_OFF); 4550104834Sobrien 4551104834Sobrien size = 28; 4552104834Sobrien if (PPC_HA ((int) off + 16) != PPC_HA ((int) off)) 4553104834Sobrien size += 4; 4554104834Sobrien } 4555104834Sobrien else 4556104834Sobrien { 4557104834Sobrien /* ppc_stub_long_branch or ppc_stub_plt_branch. */ 4558104834Sobrien stub_entry->stub_type = ppc_stub_long_branch; 4559104834Sobrien size = 4; 4560104834Sobrien 4561104834Sobrien off = (stub_entry->target_value 4562104834Sobrien + stub_entry->target_section->output_offset 4563104834Sobrien + stub_entry->target_section->output_section->vma); 4564104834Sobrien off -= (stub_entry->stub_sec->_raw_size 4565104834Sobrien + stub_entry->stub_sec->output_offset 4566104834Sobrien + stub_entry->stub_sec->output_section->vma); 4567104834Sobrien 4568104834Sobrien if (off + (1 << 25) >= (bfd_vma) (1 << 26)) 4569104834Sobrien { 4570104834Sobrien struct ppc_branch_hash_entry *br_entry; 4571104834Sobrien 4572104834Sobrien br_entry = ppc_branch_hash_lookup (&htab->branch_hash_table, 4573104834Sobrien stub_entry->root.string + 9, 4574104834Sobrien true, false); 4575104834Sobrien if (br_entry == NULL) 4576104834Sobrien { 4577104834Sobrien (*_bfd_error_handler) (_("can't build branch stub `%s'"), 4578104834Sobrien stub_entry->root.string + 9); 4579104834Sobrien htab->stub_error = true; 4580104834Sobrien return false; 4581104834Sobrien } 4582104834Sobrien 4583104834Sobrien if (br_entry->iter != htab->stub_iteration) 4584104834Sobrien { 4585104834Sobrien br_entry->iter = htab->stub_iteration; 4586104834Sobrien br_entry->offset = htab->sbrlt->_raw_size; 4587104834Sobrien htab->sbrlt->_raw_size += 8; 4588104834Sobrien } 4589104834Sobrien stub_entry->stub_type = ppc_stub_plt_branch; 4590104834Sobrien size = 16; 4591104834Sobrien } 4592104834Sobrien } 4593104834Sobrien 4594104834Sobrien stub_entry->stub_sec->_raw_size += size; 4595104834Sobrien return true; 4596104834Sobrien} 4597104834Sobrien 4598104834Sobrien/* Set up various things so that we can make a list of input sections 4599104834Sobrien for each output section included in the link. Returns -1 on error, 4600104834Sobrien 0 when no stubs will be needed, and 1 on success. */ 4601104834Sobrien 4602104834Sobrienint 4603104834Sobrienppc64_elf_setup_section_lists (output_bfd, info) 4604104834Sobrien bfd *output_bfd; 460589857Sobrien struct bfd_link_info *info; 460689857Sobrien{ 4607104834Sobrien bfd *input_bfd; 4608104834Sobrien int top_id, top_index; 4609104834Sobrien asection *section; 4610104834Sobrien asection **input_list, **list; 4611104834Sobrien bfd_size_type amt; 461289857Sobrien struct ppc_link_hash_table *htab = ppc_hash_table (info); 461389857Sobrien 4614104834Sobrien if (htab->elf.root.creator->flavour != bfd_target_elf_flavour 4615104834Sobrien || htab->sbrlt == NULL) 4616104834Sobrien return 0; 461789857Sobrien 4618104834Sobrien /* Find the top input section id. */ 4619104834Sobrien for (input_bfd = info->input_bfds, top_id = 0; 4620104834Sobrien input_bfd != NULL; 4621104834Sobrien input_bfd = input_bfd->link_next) 4622104834Sobrien { 4623104834Sobrien for (section = input_bfd->sections; 4624104834Sobrien section != NULL; 4625104834Sobrien section = section->next) 4626104834Sobrien { 4627104834Sobrien if (top_id < section->id) 4628104834Sobrien top_id = section->id; 4629104834Sobrien } 4630104834Sobrien } 463189857Sobrien 4632104834Sobrien amt = sizeof (struct map_stub) * (top_id + 1); 4633104834Sobrien htab->stub_group = (struct map_stub *) bfd_zmalloc (amt); 4634104834Sobrien if (htab->stub_group == NULL) 4635104834Sobrien return -1; 4636104834Sobrien 4637104834Sobrien /* We can't use output_bfd->section_count here to find the top output 4638104834Sobrien section index as some sections may have been removed, and 4639104834Sobrien _bfd_strip_section_from_output doesn't renumber the indices. */ 4640104834Sobrien for (section = output_bfd->sections, top_index = 0; 4641104834Sobrien section != NULL; 4642104834Sobrien section = section->next) 464389857Sobrien { 4644104834Sobrien if (top_index < section->index) 4645104834Sobrien top_index = section->index; 464689857Sobrien } 464789857Sobrien 4648104834Sobrien htab->top_index = top_index; 4649104834Sobrien amt = sizeof (asection *) * (top_index + 1); 4650104834Sobrien input_list = (asection **) bfd_malloc (amt); 4651104834Sobrien htab->input_list = input_list; 4652104834Sobrien if (input_list == NULL) 4653104834Sobrien return -1; 465489857Sobrien 4655104834Sobrien /* For sections we aren't interested in, mark their entries with a 4656104834Sobrien value we can check later. */ 4657104834Sobrien list = input_list + top_index; 4658104834Sobrien do 4659104834Sobrien *list = bfd_abs_section_ptr; 4660104834Sobrien while (list-- != input_list); 466189857Sobrien 4662104834Sobrien for (section = output_bfd->sections; 4663104834Sobrien section != NULL; 4664104834Sobrien section = section->next) 4665104834Sobrien { 4666104834Sobrien if ((section->flags & SEC_CODE) != 0) 4667104834Sobrien input_list[section->index] = NULL; 4668104834Sobrien } 466989857Sobrien 4670104834Sobrien return 1; 4671104834Sobrien} 4672104834Sobrien 4673104834Sobrien/* The linker repeatedly calls this function for each input section, 4674104834Sobrien in the order that input sections are linked into output sections. 4675104834Sobrien Build lists of input sections to determine groupings between which 4676104834Sobrien we may insert linker stubs. */ 4677104834Sobrien 4678104834Sobrienvoid 4679104834Sobrienppc64_elf_next_input_section (info, isec) 4680104834Sobrien struct bfd_link_info *info; 4681104834Sobrien asection *isec; 4682104834Sobrien{ 4683104834Sobrien struct ppc_link_hash_table *htab = ppc_hash_table (info); 4684104834Sobrien 4685104834Sobrien if (isec->output_section->index <= htab->top_index) 468689857Sobrien { 4687104834Sobrien asection **list = htab->input_list + isec->output_section->index; 4688104834Sobrien if (*list != bfd_abs_section_ptr) 4689104834Sobrien { 4690104834Sobrien /* Steal the link_sec pointer for our list. */ 4691104834Sobrien#define PREV_SEC(sec) (htab->stub_group[(sec)->id].link_sec) 4692104834Sobrien /* This happens to make the list in reverse order, 4693104834Sobrien which is what we want. */ 4694104834Sobrien PREV_SEC (isec) = *list; 4695104834Sobrien *list = isec; 4696104834Sobrien } 469789857Sobrien } 469889857Sobrien} 469989857Sobrien 4700104834Sobrien/* See whether we can group stub sections together. Grouping stub 4701104834Sobrien sections may result in fewer stubs. More importantly, we need to 4702104834Sobrien put all .init* and .fini* stubs at the beginning of the .init or 4703104834Sobrien .fini output sections respectively, because glibc splits the 4704104834Sobrien _init and _fini functions into multiple parts. Putting a stub in 4705104834Sobrien the middle of a function is not a good idea. */ 470689857Sobrien 4707104834Sobrienstatic void 4708104834Sobriengroup_sections (htab, stub_group_size, stubs_always_before_branch) 4709104834Sobrien struct ppc_link_hash_table *htab; 4710104834Sobrien bfd_size_type stub_group_size; 4711104834Sobrien boolean stubs_always_before_branch; 471289857Sobrien{ 4713104834Sobrien asection **list = htab->input_list + htab->top_index; 4714104834Sobrien do 4715104834Sobrien { 4716104834Sobrien asection *tail = *list; 4717104834Sobrien if (tail == bfd_abs_section_ptr) 4718104834Sobrien continue; 4719104834Sobrien while (tail != NULL) 4720104834Sobrien { 4721104834Sobrien asection *curr; 4722104834Sobrien asection *prev; 4723104834Sobrien bfd_size_type total; 472489857Sobrien 4725104834Sobrien curr = tail; 4726104834Sobrien if (tail->_cooked_size) 4727104834Sobrien total = tail->_cooked_size; 4728104834Sobrien else 4729104834Sobrien total = tail->_raw_size; 4730104834Sobrien while ((prev = PREV_SEC (curr)) != NULL 4731104834Sobrien && ((total += curr->output_offset - prev->output_offset) 4732104834Sobrien < stub_group_size)) 4733104834Sobrien curr = prev; 473489857Sobrien 4735104834Sobrien /* OK, the size from the start of CURR to the end is less 4736104834Sobrien than stub_group_size and thus can be handled by one stub 4737104834Sobrien section. (or the tail section is itself larger than 4738104834Sobrien stub_group_size, in which case we may be toast.) We 4739104834Sobrien should really be keeping track of the total size of stubs 4740104834Sobrien added here, as stubs contribute to the final output 4741104834Sobrien section size. That's a little tricky, and this way will 4742104834Sobrien only break if stubs added make the total size more than 4743104834Sobrien 2^25, ie. for the default stub_group_size, if stubs total 4744104834Sobrien more than 2834432 bytes, or over 100000 plt call stubs. */ 4745104834Sobrien do 4746104834Sobrien { 4747104834Sobrien prev = PREV_SEC (tail); 4748104834Sobrien /* Set up this stub group. */ 4749104834Sobrien htab->stub_group[tail->id].link_sec = curr; 4750104834Sobrien } 4751104834Sobrien while (tail != curr && (tail = prev) != NULL); 4752104834Sobrien 4753104834Sobrien /* But wait, there's more! Input sections up to stub_group_size 4754104834Sobrien bytes before the stub section can be handled by it too. */ 4755104834Sobrien if (!stubs_always_before_branch) 4756104834Sobrien { 4757104834Sobrien total = 0; 4758104834Sobrien while (prev != NULL 4759104834Sobrien && ((total += tail->output_offset - prev->output_offset) 4760104834Sobrien < stub_group_size)) 4761104834Sobrien { 4762104834Sobrien tail = prev; 4763104834Sobrien prev = PREV_SEC (tail); 4764104834Sobrien htab->stub_group[tail->id].link_sec = curr; 4765104834Sobrien } 4766104834Sobrien } 4767104834Sobrien tail = prev; 4768104834Sobrien } 4769104834Sobrien } 4770104834Sobrien while (list-- != htab->input_list); 4771104834Sobrien free (htab->input_list); 4772104834Sobrien#undef PREV_SEC 4773104834Sobrien} 4774104834Sobrien 4775104834Sobrien/* Determine and set the size of the stub section for a final link. 4776104834Sobrien 4777104834Sobrien The basic idea here is to examine all the relocations looking for 4778104834Sobrien PC-relative calls to a target that is unreachable with a "bl" 4779104834Sobrien instruction. */ 4780104834Sobrien 4781104834Sobrienboolean 4782104834Sobrienppc64_elf_size_stubs (output_bfd, stub_bfd, info, group_size, 4783104834Sobrien add_stub_section, layout_sections_again) 4784104834Sobrien bfd *output_bfd; 4785104834Sobrien bfd *stub_bfd; 4786104834Sobrien struct bfd_link_info *info; 4787104834Sobrien bfd_signed_vma group_size; 4788104834Sobrien asection * (*add_stub_section) PARAMS ((const char *, asection *)); 4789104834Sobrien void (*layout_sections_again) PARAMS ((void)); 4790104834Sobrien{ 4791104834Sobrien bfd_size_type stub_group_size; 4792104834Sobrien boolean stubs_always_before_branch; 4793104834Sobrien struct ppc_link_hash_table *htab = ppc_hash_table (info); 4794104834Sobrien 4795104834Sobrien /* Stash our params away. */ 4796104834Sobrien htab->stub_bfd = stub_bfd; 4797104834Sobrien htab->add_stub_section = add_stub_section; 4798104834Sobrien htab->layout_sections_again = layout_sections_again; 4799104834Sobrien stubs_always_before_branch = group_size < 0; 4800104834Sobrien if (group_size < 0) 4801104834Sobrien stub_group_size = -group_size; 4802104834Sobrien else 4803104834Sobrien stub_group_size = group_size; 4804104834Sobrien if (stub_group_size == 1) 4805104834Sobrien { 4806104834Sobrien /* Default values. */ 4807104834Sobrien stub_group_size = 30720000; 4808104834Sobrien if (htab->has_14bit_branch) 4809104834Sobrien stub_group_size = 30000; 4810104834Sobrien } 4811104834Sobrien 4812104834Sobrien group_sections (htab, stub_group_size, stubs_always_before_branch); 4813104834Sobrien 4814104834Sobrien while (1) 4815104834Sobrien { 4816104834Sobrien bfd *input_bfd; 4817104834Sobrien unsigned int bfd_indx; 4818104834Sobrien asection *stub_sec; 4819104834Sobrien boolean stub_changed; 4820104834Sobrien 4821104834Sobrien htab->stub_iteration += 1; 4822104834Sobrien stub_changed = false; 4823104834Sobrien 4824104834Sobrien for (input_bfd = info->input_bfds, bfd_indx = 0; 4825104834Sobrien input_bfd != NULL; 4826104834Sobrien input_bfd = input_bfd->link_next, bfd_indx++) 4827104834Sobrien { 4828104834Sobrien Elf_Internal_Shdr *symtab_hdr; 4829104834Sobrien asection *section; 4830104834Sobrien Elf_Internal_Sym *local_syms = NULL; 4831104834Sobrien 4832104834Sobrien /* We'll need the symbol table in a second. */ 4833104834Sobrien symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; 4834104834Sobrien if (symtab_hdr->sh_info == 0) 4835104834Sobrien continue; 4836104834Sobrien 4837104834Sobrien /* Walk over each section attached to the input bfd. */ 4838104834Sobrien for (section = input_bfd->sections; 4839104834Sobrien section != NULL; 4840104834Sobrien section = section->next) 4841104834Sobrien { 4842104834Sobrien Elf_Internal_Rela *internal_relocs, *irelaend, *irela; 4843104834Sobrien 4844104834Sobrien /* If there aren't any relocs, then there's nothing more 4845104834Sobrien to do. */ 4846104834Sobrien if ((section->flags & SEC_RELOC) == 0 4847104834Sobrien || section->reloc_count == 0) 4848104834Sobrien continue; 4849104834Sobrien 4850104834Sobrien /* If this section is a link-once section that will be 4851104834Sobrien discarded, then don't create any stubs. */ 4852104834Sobrien if (section->output_section == NULL 4853104834Sobrien || section->output_section->owner != output_bfd) 4854104834Sobrien continue; 4855104834Sobrien 4856104834Sobrien /* Get the relocs. */ 4857104834Sobrien internal_relocs 4858104834Sobrien = _bfd_elf64_link_read_relocs (input_bfd, section, NULL, 4859104834Sobrien (Elf_Internal_Rela *) NULL, 4860104834Sobrien info->keep_memory); 4861104834Sobrien if (internal_relocs == NULL) 4862104834Sobrien goto error_ret_free_local; 4863104834Sobrien 4864104834Sobrien /* Now examine each relocation. */ 4865104834Sobrien irela = internal_relocs; 4866104834Sobrien irelaend = irela + section->reloc_count; 4867104834Sobrien for (; irela < irelaend; irela++) 4868104834Sobrien { 4869104834Sobrien unsigned int r_type, r_indx; 4870104834Sobrien enum ppc_stub_type stub_type; 4871104834Sobrien struct ppc_stub_hash_entry *stub_entry; 4872104834Sobrien asection *sym_sec; 4873104834Sobrien bfd_vma sym_value; 4874104834Sobrien bfd_vma destination; 4875104834Sobrien struct ppc_link_hash_entry *hash; 4876104834Sobrien char *stub_name; 4877104834Sobrien const asection *id_sec; 4878104834Sobrien 4879104834Sobrien r_type = ELF64_R_TYPE (irela->r_info); 4880104834Sobrien r_indx = ELF64_R_SYM (irela->r_info); 4881104834Sobrien 4882104834Sobrien if (r_type >= (unsigned int) R_PPC_max) 4883104834Sobrien { 4884104834Sobrien bfd_set_error (bfd_error_bad_value); 4885104834Sobrien goto error_ret_free_internal; 4886104834Sobrien } 4887104834Sobrien 4888104834Sobrien /* Only look for stubs on branch instructions. */ 4889104834Sobrien if (r_type != (unsigned int) R_PPC64_REL24 4890104834Sobrien && r_type != (unsigned int) R_PPC64_REL14 4891104834Sobrien && r_type != (unsigned int) R_PPC64_REL14_BRTAKEN 4892104834Sobrien && r_type != (unsigned int) R_PPC64_REL14_BRNTAKEN) 4893104834Sobrien continue; 4894104834Sobrien 4895104834Sobrien /* Now determine the call target, its name, value, 4896104834Sobrien section. */ 4897104834Sobrien sym_sec = NULL; 4898104834Sobrien sym_value = 0; 4899104834Sobrien destination = 0; 4900104834Sobrien hash = NULL; 4901104834Sobrien if (r_indx < symtab_hdr->sh_info) 4902104834Sobrien { 4903104834Sobrien /* It's a local symbol. */ 4904104834Sobrien Elf_Internal_Sym *sym; 4905104834Sobrien Elf_Internal_Shdr *hdr; 4906104834Sobrien 4907104834Sobrien if (local_syms == NULL) 4908104834Sobrien { 4909104834Sobrien local_syms 4910104834Sobrien = (Elf_Internal_Sym *) symtab_hdr->contents; 4911104834Sobrien if (local_syms == NULL) 4912104834Sobrien local_syms 4913104834Sobrien = bfd_elf_get_elf_syms (input_bfd, symtab_hdr, 4914104834Sobrien symtab_hdr->sh_info, 0, 4915104834Sobrien NULL, NULL, NULL); 4916104834Sobrien if (local_syms == NULL) 4917104834Sobrien goto error_ret_free_internal; 4918104834Sobrien } 4919104834Sobrien sym = local_syms + r_indx; 4920104834Sobrien hdr = elf_elfsections (input_bfd)[sym->st_shndx]; 4921104834Sobrien sym_sec = hdr->bfd_section; 4922104834Sobrien if (ELF_ST_TYPE (sym->st_info) != STT_SECTION) 4923104834Sobrien sym_value = sym->st_value; 4924104834Sobrien destination = (sym_value + irela->r_addend 4925104834Sobrien + sym_sec->output_offset 4926104834Sobrien + sym_sec->output_section->vma); 4927104834Sobrien } 4928104834Sobrien else 4929104834Sobrien { 4930104834Sobrien /* It's an external symbol. */ 4931104834Sobrien int e_indx; 4932104834Sobrien 4933104834Sobrien e_indx = r_indx - symtab_hdr->sh_info; 4934104834Sobrien hash = ((struct ppc_link_hash_entry *) 4935104834Sobrien elf_sym_hashes (input_bfd)[e_indx]); 4936104834Sobrien 4937104834Sobrien while (hash->elf.root.type == bfd_link_hash_indirect 4938104834Sobrien || hash->elf.root.type == bfd_link_hash_warning) 4939104834Sobrien hash = ((struct ppc_link_hash_entry *) 4940104834Sobrien hash->elf.root.u.i.link); 4941104834Sobrien 4942104834Sobrien if (hash->elf.root.type == bfd_link_hash_defined 4943104834Sobrien || hash->elf.root.type == bfd_link_hash_defweak) 4944104834Sobrien { 4945104834Sobrien sym_sec = hash->elf.root.u.def.section; 4946104834Sobrien sym_value = hash->elf.root.u.def.value; 4947104834Sobrien if (sym_sec->output_section != NULL) 4948104834Sobrien destination = (sym_value + irela->r_addend 4949104834Sobrien + sym_sec->output_offset 4950104834Sobrien + sym_sec->output_section->vma); 4951104834Sobrien } 4952104834Sobrien else if (hash->elf.root.type == bfd_link_hash_undefweak) 4953104834Sobrien ; 4954104834Sobrien else if (hash->elf.root.type == bfd_link_hash_undefined) 4955104834Sobrien ; 4956104834Sobrien else 4957104834Sobrien { 4958104834Sobrien bfd_set_error (bfd_error_bad_value); 4959104834Sobrien goto error_ret_free_internal; 4960104834Sobrien } 4961104834Sobrien } 4962104834Sobrien 4963104834Sobrien /* Determine what (if any) linker stub is needed. */ 4964104834Sobrien stub_type = ppc_type_of_stub (section, irela, &hash, 4965104834Sobrien destination); 4966104834Sobrien if (stub_type == ppc_stub_none) 4967104834Sobrien continue; 4968104834Sobrien 4969104834Sobrien /* Support for grouping stub sections. */ 4970104834Sobrien id_sec = htab->stub_group[section->id].link_sec; 4971104834Sobrien 4972104834Sobrien /* Get the name of this stub. */ 4973104834Sobrien stub_name = ppc_stub_name (id_sec, sym_sec, hash, irela); 4974104834Sobrien if (!stub_name) 4975104834Sobrien goto error_ret_free_internal; 4976104834Sobrien 4977104834Sobrien stub_entry = ppc_stub_hash_lookup (&htab->stub_hash_table, 4978104834Sobrien stub_name, false, false); 4979104834Sobrien if (stub_entry != NULL) 4980104834Sobrien { 4981104834Sobrien /* The proper stub has already been created. */ 4982104834Sobrien free (stub_name); 4983104834Sobrien continue; 4984104834Sobrien } 4985104834Sobrien 4986104834Sobrien stub_entry = ppc_add_stub (stub_name, section, htab); 4987104834Sobrien if (stub_entry == NULL) 4988104834Sobrien { 4989104834Sobrien free (stub_name); 4990104834Sobrien error_ret_free_internal: 4991104834Sobrien if (elf_section_data (section)->relocs == NULL) 4992104834Sobrien free (internal_relocs); 4993104834Sobrien error_ret_free_local: 4994104834Sobrien if (local_syms != NULL 4995104834Sobrien && (symtab_hdr->contents 4996104834Sobrien != (unsigned char *) local_syms)) 4997104834Sobrien free (local_syms); 4998104834Sobrien return false; 4999104834Sobrien } 5000104834Sobrien 5001104834Sobrien stub_entry->target_value = sym_value; 5002104834Sobrien stub_entry->target_section = sym_sec; 5003104834Sobrien stub_entry->stub_type = stub_type; 5004104834Sobrien stub_entry->h = hash; 5005104834Sobrien stub_changed = true; 5006104834Sobrien } 5007104834Sobrien 5008104834Sobrien /* We're done with the internal relocs, free them. */ 5009104834Sobrien if (elf_section_data (section)->relocs != internal_relocs) 5010104834Sobrien free (internal_relocs); 5011104834Sobrien } 5012104834Sobrien 5013104834Sobrien if (local_syms != NULL 5014104834Sobrien && symtab_hdr->contents != (unsigned char *) local_syms) 5015104834Sobrien { 5016104834Sobrien if (!info->keep_memory) 5017104834Sobrien free (local_syms); 5018104834Sobrien else 5019104834Sobrien symtab_hdr->contents = (unsigned char *) local_syms; 5020104834Sobrien } 5021104834Sobrien } 5022104834Sobrien 5023104834Sobrien if (!stub_changed) 5024104834Sobrien break; 5025104834Sobrien 5026104834Sobrien /* OK, we've added some stubs. Find out the new size of the 5027104834Sobrien stub sections. */ 5028104834Sobrien for (stub_sec = htab->stub_bfd->sections; 5029104834Sobrien stub_sec != NULL; 5030104834Sobrien stub_sec = stub_sec->next) 5031104834Sobrien { 5032104834Sobrien stub_sec->_raw_size = 0; 5033104834Sobrien stub_sec->_cooked_size = 0; 5034104834Sobrien } 5035104834Sobrien htab->sbrlt->_raw_size = 0; 5036104834Sobrien htab->sbrlt->_cooked_size = 0; 5037104834Sobrien 5038104834Sobrien bfd_hash_traverse (&htab->stub_hash_table, ppc_size_one_stub, htab); 5039104834Sobrien 5040104834Sobrien /* Ask the linker to do its stuff. */ 5041104834Sobrien (*htab->layout_sections_again) (); 5042104834Sobrien } 5043104834Sobrien 5044104834Sobrien /* It would be nice to strip .branch_lt from the output if the 5045104834Sobrien section is empty, but it's too late. If we strip sections here, 5046104834Sobrien the dynamic symbol table is corrupted since the section symbol 5047104834Sobrien for the stripped section isn't written. */ 5048104834Sobrien 504989857Sobrien return true; 505089857Sobrien} 505189857Sobrien 5052104834Sobrien/* Called after we have determined section placement. If sections 5053104834Sobrien move, we'll be called again. Provide a value for TOCstart. */ 5054104834Sobrien 5055104834Sobrienbfd_vma 5056104834Sobrienppc64_elf_toc (obfd) 5057104834Sobrien bfd *obfd; 5058104834Sobrien{ 5059104834Sobrien asection *s; 5060104834Sobrien bfd_vma TOCstart; 5061104834Sobrien 5062104834Sobrien /* The TOC consists of sections .got, .toc, .tocbss, .plt in that 5063104834Sobrien order. The TOC starts where the first of these sections starts. */ 5064104834Sobrien s = bfd_get_section_by_name (obfd, ".got"); 5065104834Sobrien if (s == NULL) 5066104834Sobrien s = bfd_get_section_by_name (obfd, ".toc"); 5067104834Sobrien if (s == NULL) 5068104834Sobrien s = bfd_get_section_by_name (obfd, ".tocbss"); 5069104834Sobrien if (s == NULL) 5070104834Sobrien s = bfd_get_section_by_name (obfd, ".plt"); 5071104834Sobrien if (s == NULL) 5072104834Sobrien { 5073104834Sobrien /* This may happen for 5074104834Sobrien o references to TOC base (SYM@toc / TOC[tc0]) without a 5075104834Sobrien .toc directive 5076104834Sobrien o bad linker script 5077104834Sobrien o --gc-sections and empty TOC sections 5078104834Sobrien 5079104834Sobrien FIXME: Warn user? */ 5080104834Sobrien 5081104834Sobrien /* Look for a likely section. We probably won't even be 5082104834Sobrien using TOCstart. */ 5083104834Sobrien for (s = obfd->sections; s != NULL; s = s->next) 5084104834Sobrien if ((s->flags & (SEC_ALLOC | SEC_SMALL_DATA | SEC_READONLY)) 5085104834Sobrien == (SEC_ALLOC | SEC_SMALL_DATA)) 5086104834Sobrien break; 5087104834Sobrien if (s == NULL) 5088104834Sobrien for (s = obfd->sections; s != NULL; s = s->next) 5089104834Sobrien if ((s->flags & (SEC_ALLOC | SEC_SMALL_DATA)) 5090104834Sobrien == (SEC_ALLOC | SEC_SMALL_DATA)) 5091104834Sobrien break; 5092104834Sobrien if (s == NULL) 5093104834Sobrien for (s = obfd->sections; s != NULL; s = s->next) 5094104834Sobrien if ((s->flags & (SEC_ALLOC | SEC_READONLY)) == SEC_ALLOC) 5095104834Sobrien break; 5096104834Sobrien if (s == NULL) 5097104834Sobrien for (s = obfd->sections; s != NULL; s = s->next) 5098104834Sobrien if ((s->flags & SEC_ALLOC) == SEC_ALLOC) 5099104834Sobrien break; 5100104834Sobrien } 5101104834Sobrien 5102104834Sobrien TOCstart = 0; 5103104834Sobrien if (s != NULL) 5104104834Sobrien TOCstart = s->output_section->vma + s->output_offset; 5105104834Sobrien 5106104834Sobrien return TOCstart; 5107104834Sobrien} 5108104834Sobrien 5109104834Sobrien/* Build all the stubs associated with the current output file. 5110104834Sobrien The stubs are kept in a hash table attached to the main linker 5111104834Sobrien hash table. This function is called via gldelf64ppc_finish. */ 5112104834Sobrien 5113104834Sobrienboolean 5114104834Sobrienppc64_elf_build_stubs (info) 5115104834Sobrien struct bfd_link_info *info; 5116104834Sobrien{ 5117104834Sobrien struct ppc_link_hash_table *htab = ppc_hash_table (info); 5118104834Sobrien asection *stub_sec; 5119104834Sobrien bfd_vma plt_r2; 5120104834Sobrien bfd_byte *p; 5121104834Sobrien 5122104834Sobrien for (stub_sec = htab->stub_bfd->sections; 5123104834Sobrien stub_sec != NULL; 5124104834Sobrien stub_sec = stub_sec->next) 5125104834Sobrien { 5126104834Sobrien bfd_size_type size; 5127104834Sobrien 5128104834Sobrien /* Allocate memory to hold the linker stubs. */ 5129104834Sobrien size = stub_sec->_raw_size; 5130104834Sobrien if (size != 0) 5131104834Sobrien { 5132104834Sobrien stub_sec->contents = (bfd_byte *) bfd_zalloc (htab->stub_bfd, size); 5133104834Sobrien if (stub_sec->contents == NULL) 5134104834Sobrien return false; 5135104834Sobrien } 5136104834Sobrien stub_sec->_cooked_size = 0; 5137104834Sobrien } 5138104834Sobrien 5139104834Sobrien if (htab->splt != NULL) 5140104834Sobrien { 5141104834Sobrien unsigned int indx; 5142104834Sobrien 5143104834Sobrien /* Build the .glink plt call stub. */ 5144104834Sobrien plt_r2 = (htab->splt->output_offset 5145104834Sobrien + htab->splt->output_section->vma 5146104834Sobrien - elf_gp (htab->splt->output_section->owner) 5147104834Sobrien - TOC_BASE_OFF); 5148104834Sobrien p = htab->sglink->contents; 5149104834Sobrien p = build_plt_stub (htab->sglink->owner, p, (int) plt_r2, 1); 5150104834Sobrien while (p < htab->sglink->contents + GLINK_CALL_STUB_SIZE) 5151104834Sobrien { 5152104834Sobrien bfd_put_32 (htab->sglink->owner, NOP, p); 5153104834Sobrien p += 4; 5154104834Sobrien } 5155104834Sobrien 5156104834Sobrien /* Build the .glink lazy link call stubs. */ 5157104834Sobrien indx = 0; 5158104834Sobrien while (p < htab->sglink->contents + htab->sglink->_raw_size) 5159104834Sobrien { 5160104834Sobrien if (indx < 0x8000) 5161104834Sobrien { 5162104834Sobrien bfd_put_32 (htab->sglink->owner, LI_R0_0 | indx, p); 5163104834Sobrien p += 4; 5164104834Sobrien } 5165104834Sobrien else 5166104834Sobrien { 5167104834Sobrien bfd_put_32 (htab->sglink->owner, LIS_R0_0 | PPC_HI (indx), p); 5168104834Sobrien p += 4; 5169104834Sobrien bfd_put_32 (htab->sglink->owner, ORI_R0_R0_0 | PPC_LO (indx), p); 5170104834Sobrien p += 4; 5171104834Sobrien } 5172104834Sobrien bfd_put_32 (htab->sglink->owner, 5173104834Sobrien B_DOT | ((htab->sglink->contents - p) & 0x3fffffc), p); 5174104834Sobrien indx++; 5175104834Sobrien p += 4; 5176104834Sobrien } 5177104834Sobrien htab->sglink->_cooked_size = p - htab->sglink->contents; 5178104834Sobrien } 5179104834Sobrien 5180104834Sobrien if (htab->sbrlt->_raw_size != 0) 5181104834Sobrien { 5182104834Sobrien htab->sbrlt->contents = (bfd_byte *) bfd_zalloc (htab->sbrlt->owner, 5183104834Sobrien htab->sbrlt->_raw_size); 5184104834Sobrien if (htab->sbrlt->contents == NULL) 5185104834Sobrien return false; 5186104834Sobrien } 5187104834Sobrien 5188104834Sobrien /* Build the stubs as directed by the stub hash table. */ 5189104834Sobrien bfd_hash_traverse (&htab->stub_hash_table, ppc_build_one_stub, info); 5190104834Sobrien 5191104834Sobrien for (stub_sec = htab->stub_bfd->sections; 5192104834Sobrien stub_sec != NULL; 5193104834Sobrien stub_sec = stub_sec->next) 5194104834Sobrien { 5195104834Sobrien if (stub_sec->_raw_size != stub_sec->_cooked_size) 5196104834Sobrien break; 5197104834Sobrien } 5198104834Sobrien 5199104834Sobrien if (stub_sec != NULL 5200104834Sobrien || htab->sglink->_raw_size != htab->sglink->_cooked_size) 5201104834Sobrien { 5202104834Sobrien htab->stub_error = true; 5203104834Sobrien (*_bfd_error_handler) (_("stubs don't match calculated size")); 5204104834Sobrien } 5205104834Sobrien 5206104834Sobrien return !htab->stub_error; 5207104834Sobrien} 5208104834Sobrien 520989857Sobrien/* The RELOCATE_SECTION function is called by the ELF backend linker 521089857Sobrien to handle the relocations for a section. 521189857Sobrien 521289857Sobrien The relocs are always passed as Rela structures; if the section 521389857Sobrien actually uses Rel structures, the r_addend field will always be 521489857Sobrien zero. 521589857Sobrien 521689857Sobrien This function is responsible for adjust the section contents as 521789857Sobrien necessary, and (if using Rela relocs and generating a 521889857Sobrien relocateable output file) adjusting the reloc addend as 521989857Sobrien necessary. 522089857Sobrien 522189857Sobrien This function does not have to worry about setting the reloc 522289857Sobrien address or the reloc symbol index. 522389857Sobrien 522489857Sobrien LOCAL_SYMS is a pointer to the swapped in local symbols. 522589857Sobrien 522689857Sobrien LOCAL_SECTIONS is an array giving the section in the input file 522789857Sobrien corresponding to the st_shndx field of each local symbol. 522889857Sobrien 522989857Sobrien The global hash table entry for the global symbols can be found 523089857Sobrien via elf_sym_hashes (input_bfd). 523189857Sobrien 523289857Sobrien When generating relocateable output, this function must handle 523389857Sobrien STB_LOCAL/STT_SECTION symbols specially. The output symbol is 523489857Sobrien going to be the section symbol corresponding to the output 523589857Sobrien section, which means that the addend must be adjusted 523689857Sobrien accordingly. */ 523789857Sobrien 523889857Sobrienstatic boolean 523989857Sobrienppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, 524089857Sobrien contents, relocs, local_syms, local_sections) 524189857Sobrien bfd *output_bfd; 524289857Sobrien struct bfd_link_info *info; 524389857Sobrien bfd *input_bfd; 524489857Sobrien asection *input_section; 524589857Sobrien bfd_byte *contents; 524689857Sobrien Elf_Internal_Rela *relocs; 524789857Sobrien Elf_Internal_Sym *local_syms; 524889857Sobrien asection **local_sections; 524989857Sobrien{ 525089857Sobrien struct ppc_link_hash_table *htab; 525189857Sobrien Elf_Internal_Shdr *symtab_hdr; 525289857Sobrien struct elf_link_hash_entry **sym_hashes; 525389857Sobrien Elf_Internal_Rela *rel; 525489857Sobrien Elf_Internal_Rela *relend; 525589857Sobrien bfd_vma *local_got_offsets; 525689857Sobrien bfd_vma TOCstart; 525789857Sobrien boolean ret = true; 525889857Sobrien boolean is_opd; 525992828Sobrien /* Disabled until we sort out how ld should choose 'y' vs 'at'. */ 526092828Sobrien boolean is_power4 = false; 526189857Sobrien 526299461Sobrien if (info->relocateable) 526399461Sobrien return true; 526499461Sobrien 526589857Sobrien /* Initialize howto table if needed. */ 526689857Sobrien if (!ppc64_elf_howto_table[R_PPC64_ADDR32]) 526789857Sobrien ppc_howto_init (); 526889857Sobrien 526989857Sobrien htab = ppc_hash_table (info); 527089857Sobrien local_got_offsets = elf_local_got_offsets (input_bfd); 527189857Sobrien TOCstart = elf_gp (output_bfd); 527289857Sobrien symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; 527389857Sobrien sym_hashes = elf_sym_hashes (input_bfd); 5274104834Sobrien is_opd = elf_section_data (input_section)->tdata != NULL; 527589857Sobrien 527689857Sobrien rel = relocs; 527789857Sobrien relend = relocs + input_section->reloc_count; 527889857Sobrien for (; rel < relend; rel++) 527989857Sobrien { 528089857Sobrien enum elf_ppc_reloc_type r_type; 528189857Sobrien bfd_vma offset; 528289857Sobrien bfd_vma addend; 528389857Sobrien bfd_reloc_status_type r; 528489857Sobrien Elf_Internal_Sym *sym; 528589857Sobrien asection *sec; 528689857Sobrien struct elf_link_hash_entry *h; 5287104834Sobrien struct elf_link_hash_entry *fdh; 528889857Sobrien const char *sym_name; 528989857Sobrien unsigned long r_symndx; 529089857Sobrien bfd_vma relocation; 529189857Sobrien boolean unresolved_reloc; 5292104834Sobrien boolean warned; 529389857Sobrien long insn; 5294104834Sobrien struct ppc_stub_hash_entry *stub_entry; 5295104834Sobrien bfd_vma max_br_offset; 529699461Sobrien bfd_vma from; 529789857Sobrien 529889857Sobrien r_type = (enum elf_ppc_reloc_type) ELF64_R_TYPE (rel->r_info); 529989857Sobrien r_symndx = ELF64_R_SYM (rel->r_info); 530089857Sobrien offset = rel->r_offset; 530189857Sobrien addend = rel->r_addend; 530289857Sobrien r = bfd_reloc_other; 530389857Sobrien sym = (Elf_Internal_Sym *) 0; 530489857Sobrien sec = (asection *) 0; 530589857Sobrien h = (struct elf_link_hash_entry *) 0; 530689857Sobrien sym_name = (const char *) 0; 530789857Sobrien unresolved_reloc = false; 5308104834Sobrien warned = false; 530989857Sobrien 531089857Sobrien if (r_type == R_PPC64_TOC) 531189857Sobrien { 531289857Sobrien /* Relocation value is TOC base. Symbol is ignored. */ 531389857Sobrien relocation = TOCstart + TOC_BASE_OFF; 531489857Sobrien } 531589857Sobrien else if (r_symndx < symtab_hdr->sh_info) 531689857Sobrien { 531789857Sobrien /* It's a local symbol. */ 531889857Sobrien sym = local_syms + r_symndx; 531989857Sobrien sec = local_sections[r_symndx]; 532089857Sobrien sym_name = "<local symbol>"; 532189857Sobrien 532289857Sobrien relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel); 532399461Sobrien /* rel may have changed, update our copy of addend. */ 532489857Sobrien addend = rel->r_addend; 5325104834Sobrien 5326104834Sobrien if (elf_section_data (sec) != NULL) 5327104834Sobrien { 5328104834Sobrien long *opd_sym_adjust; 5329104834Sobrien 5330104834Sobrien opd_sym_adjust = (long *) elf_section_data (sec)->tdata; 5331104834Sobrien if (opd_sym_adjust != NULL && sym->st_value % 24 == 0) 5332104834Sobrien relocation += opd_sym_adjust[sym->st_value / 24]; 5333104834Sobrien } 533489857Sobrien } 533589857Sobrien else 533689857Sobrien { 533789857Sobrien /* It's a global symbol. */ 533889857Sobrien h = sym_hashes[r_symndx - symtab_hdr->sh_info]; 533989857Sobrien while (h->root.type == bfd_link_hash_indirect 534089857Sobrien || h->root.type == bfd_link_hash_warning) 534189857Sobrien h = (struct elf_link_hash_entry *) h->root.u.i.link; 534289857Sobrien sym_name = h->root.root.string; 534389857Sobrien relocation = 0; 534489857Sobrien if (h->root.type == bfd_link_hash_defined 534589857Sobrien || h->root.type == bfd_link_hash_defweak) 534689857Sobrien { 534789857Sobrien sec = h->root.u.def.section; 534889857Sobrien if (sec->output_section == NULL) 534989857Sobrien /* Set a flag that will be cleared later if we find a 535089857Sobrien relocation value for this symbol. output_section 535189857Sobrien is typically NULL for symbols satisfied by a shared 535289857Sobrien library. */ 535389857Sobrien unresolved_reloc = true; 535489857Sobrien else 535589857Sobrien relocation = (h->root.u.def.value 535689857Sobrien + sec->output_section->vma 535789857Sobrien + sec->output_offset); 535889857Sobrien } 535989857Sobrien else if (h->root.type == bfd_link_hash_undefweak) 536089857Sobrien ; 536189857Sobrien else if (info->shared 536289857Sobrien && (!info->symbolic || info->allow_shlib_undefined) 536389857Sobrien && !info->no_undefined 536489857Sobrien && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT) 536589857Sobrien ; 536689857Sobrien else 536789857Sobrien { 536889857Sobrien if (! ((*info->callbacks->undefined_symbol) 536989857Sobrien (info, h->root.root.string, input_bfd, input_section, 537089857Sobrien offset, (!info->shared 537189857Sobrien || info->no_undefined 537289857Sobrien || ELF_ST_VISIBILITY (h->other))))) 537389857Sobrien return false; 5374104834Sobrien warned = true; 537589857Sobrien } 537689857Sobrien } 537789857Sobrien 537889857Sobrien /* First handle relocations that tweak non-addend part of insn. */ 537989857Sobrien insn = 0; 538089857Sobrien switch (r_type) 538189857Sobrien { 538289857Sobrien default: 538389857Sobrien break; 538489857Sobrien 538589857Sobrien /* Branch taken prediction relocations. */ 538689857Sobrien case R_PPC64_ADDR14_BRTAKEN: 538789857Sobrien case R_PPC64_REL14_BRTAKEN: 5388104834Sobrien insn = 0x01 << 21; /* 'y' or 't' bit, lowest bit of BO field. */ 5389104834Sobrien /* Fall thru. */ 539089857Sobrien 539189857Sobrien /* Branch not taken prediction relocations. */ 539289857Sobrien case R_PPC64_ADDR14_BRNTAKEN: 539389857Sobrien case R_PPC64_REL14_BRNTAKEN: 539489857Sobrien insn |= bfd_get_32 (output_bfd, contents + offset) & ~(0x01 << 21); 539592828Sobrien if (is_power4) 539692828Sobrien { 539792828Sobrien /* Set 'a' bit. This is 0b00010 in BO field for branch 539892828Sobrien on CR(BI) insns (BO == 001at or 011at), and 0b01000 539992828Sobrien for branch on CTR insns (BO == 1a00t or 1a01t). */ 540092828Sobrien if ((insn & (0x14 << 21)) == (0x04 << 21)) 540192828Sobrien insn |= 0x02 << 21; 540292828Sobrien else if ((insn & (0x14 << 21)) == (0x10 << 21)) 540392828Sobrien insn |= 0x08 << 21; 540492828Sobrien else 540592828Sobrien break; 540692828Sobrien } 540789857Sobrien else 540892828Sobrien { 540999461Sobrien from = (offset 541099461Sobrien + input_section->output_offset 541199461Sobrien + input_section->output_section->vma); 541299461Sobrien 541392828Sobrien /* Invert 'y' bit if not the default. */ 541499461Sobrien if ((bfd_signed_vma) (relocation + addend - from) < 0) 541592828Sobrien insn ^= 0x01 << 21; 541692828Sobrien } 541789857Sobrien 541889857Sobrien bfd_put_32 (output_bfd, (bfd_vma) insn, contents + offset); 541989857Sobrien break; 542089857Sobrien 542189857Sobrien case R_PPC64_REL24: 542299461Sobrien /* A REL24 branching to a linkage function is followed by a 542399461Sobrien nop. We replace the nop with a ld in order to restore 542499461Sobrien the TOC base pointer. Only calls to shared objects need 542599461Sobrien to alter the TOC base. These are recognized by their 542699461Sobrien need for a PLT entry. */ 542789857Sobrien if (h != NULL 5428104834Sobrien && (fdh = ((struct ppc_link_hash_entry *) h)->oh) != NULL 5429104834Sobrien && fdh->plt.offset != (bfd_vma) -1 5430104834Sobrien && (stub_entry = ppc_get_stub_entry (input_section, sec, fdh, 5431104834Sobrien rel, htab)) != NULL) 543289857Sobrien { 543399461Sobrien boolean can_plt_call = 0; 543489857Sobrien 543589857Sobrien if (offset + 8 <= input_section->_cooked_size) 543689857Sobrien { 543799461Sobrien insn = bfd_get_32 (input_bfd, contents + offset + 4); 543899461Sobrien if (insn == NOP 543999461Sobrien || insn == CROR_151515 || insn == CROR_313131) 544089857Sobrien { 544199461Sobrien bfd_put_32 (input_bfd, (bfd_vma) LD_R2_40R1, 544299461Sobrien contents + offset + 4); 544399461Sobrien can_plt_call = 1; 544489857Sobrien } 544589857Sobrien } 544699461Sobrien 544799461Sobrien if (!can_plt_call) 544899461Sobrien { 544999461Sobrien /* If this is a plain branch rather than a branch 545099461Sobrien and link, don't require a nop. */ 545199461Sobrien insn = bfd_get_32 (input_bfd, contents + offset); 545299461Sobrien if ((insn & 1) == 0) 545399461Sobrien can_plt_call = 1; 545499461Sobrien } 545599461Sobrien 545699461Sobrien if (can_plt_call) 545799461Sobrien { 5458104834Sobrien relocation = (stub_entry->stub_offset 5459104834Sobrien + stub_entry->stub_sec->output_offset 5460104834Sobrien + stub_entry->stub_sec->output_section->vma); 546199461Sobrien addend = 0; 546299461Sobrien unresolved_reloc = false; 546399461Sobrien } 546489857Sobrien } 546589857Sobrien 546689857Sobrien if (h != NULL 546789857Sobrien && h->root.type == bfd_link_hash_undefweak 546899461Sobrien && relocation == 0 546999461Sobrien && addend == 0) 547089857Sobrien { 547199461Sobrien /* Tweak calls to undefined weak functions to point at a 547299461Sobrien blr. We can thus call a weak function without first 547399461Sobrien checking whether the function is defined. We have a 547499461Sobrien blr at the end of .sfpr. */ 547599461Sobrien BFD_ASSERT (htab->sfpr->_raw_size != 0); 547699461Sobrien relocation = (htab->sfpr->_raw_size - 4 547799461Sobrien + htab->sfpr->output_offset 547899461Sobrien + htab->sfpr->output_section->vma); 547999461Sobrien from = (offset 548099461Sobrien + input_section->output_offset 548199461Sobrien + input_section->output_section->vma); 548299461Sobrien 548399461Sobrien /* But let's not be silly about it. If the blr isn't in 548499461Sobrien reach, just go to the next instruction. */ 548599461Sobrien if (relocation - from + (1 << 25) >= (1 << 26) 548699461Sobrien || htab->sfpr->_raw_size == 0) 548799461Sobrien relocation = from + 4; 548889857Sobrien } 548989857Sobrien break; 549089857Sobrien } 549189857Sobrien 549289857Sobrien /* Set `addend'. */ 549389857Sobrien switch (r_type) 549489857Sobrien { 549589857Sobrien default: 549689857Sobrien (*_bfd_error_handler) 549789857Sobrien (_("%s: unknown relocation type %d for symbol %s"), 549889857Sobrien bfd_archive_filename (input_bfd), (int) r_type, sym_name); 549989857Sobrien 550089857Sobrien bfd_set_error (bfd_error_bad_value); 550189857Sobrien ret = false; 550289857Sobrien continue; 550389857Sobrien 550489857Sobrien case R_PPC64_NONE: 550589857Sobrien case R_PPC_GNU_VTINHERIT: 550689857Sobrien case R_PPC_GNU_VTENTRY: 550789857Sobrien continue; 550889857Sobrien 550989857Sobrien /* GOT16 relocations. Like an ADDR16 using the symbol's 551089857Sobrien address in the GOT as relocation value instead of the 551189857Sobrien symbols value itself. Also, create a GOT entry for the 551289857Sobrien symbol and put the symbol value there. */ 551389857Sobrien case R_PPC64_GOT16: 551489857Sobrien case R_PPC64_GOT16_LO: 551589857Sobrien case R_PPC64_GOT16_HI: 551689857Sobrien case R_PPC64_GOT16_HA: 551789857Sobrien case R_PPC64_GOT16_DS: 551889857Sobrien case R_PPC64_GOT16_LO_DS: 551989857Sobrien { 552089857Sobrien /* Relocation is to the entry for this symbol in the global 552189857Sobrien offset table. */ 552289857Sobrien bfd_vma off; 552389857Sobrien 552489857Sobrien if (htab->sgot == NULL) 552589857Sobrien abort (); 552689857Sobrien 552789857Sobrien if (h != NULL) 552889857Sobrien { 552989857Sobrien boolean dyn; 553089857Sobrien 553189857Sobrien off = h->got.offset; 553289857Sobrien dyn = htab->elf.dynamic_sections_created; 553389857Sobrien if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h) 553489857Sobrien || (info->shared 553589857Sobrien && (info->symbolic 553689857Sobrien || h->dynindx == -1 553789857Sobrien || (h->elf_link_hash_flags 553889857Sobrien & ELF_LINK_FORCED_LOCAL)) 553989857Sobrien && (h->elf_link_hash_flags 554089857Sobrien & ELF_LINK_HASH_DEF_REGULAR))) 554189857Sobrien { 554289857Sobrien /* This is actually a static link, or it is a 554389857Sobrien -Bsymbolic link and the symbol is defined 554489857Sobrien locally, or the symbol was forced to be local 554589857Sobrien because of a version file. We must initialize 554689857Sobrien this entry in the global offset table. Since the 554789857Sobrien offset must always be a multiple of 8, we use the 554889857Sobrien least significant bit to record whether we have 554989857Sobrien initialized it already. 555089857Sobrien 555189857Sobrien When doing a dynamic link, we create a .rel.got 555289857Sobrien relocation entry to initialize the value. This 555389857Sobrien is done in the finish_dynamic_symbol routine. */ 555489857Sobrien if ((off & 1) != 0) 555589857Sobrien off &= ~1; 555689857Sobrien else 555789857Sobrien { 555889857Sobrien bfd_put_64 (output_bfd, relocation, 555989857Sobrien htab->sgot->contents + off); 556089857Sobrien h->got.offset |= 1; 556189857Sobrien } 556289857Sobrien } 556389857Sobrien else 556489857Sobrien unresolved_reloc = false; 556589857Sobrien } 556689857Sobrien else 556789857Sobrien { 556889857Sobrien if (local_got_offsets == NULL) 556989857Sobrien abort (); 557089857Sobrien 557189857Sobrien off = local_got_offsets[r_symndx]; 557289857Sobrien 557389857Sobrien /* The offset must always be a multiple of 8. We use 557489857Sobrien the least significant bit to record whether we have 557589857Sobrien already processed this entry. */ 557689857Sobrien if ((off & 1) != 0) 557789857Sobrien off &= ~1; 557889857Sobrien else 557989857Sobrien { 558089857Sobrien bfd_put_64 (output_bfd, relocation, 558189857Sobrien htab->sgot->contents + off); 558289857Sobrien 558389857Sobrien if (info->shared) 558489857Sobrien { 558589857Sobrien Elf_Internal_Rela outrel; 558689857Sobrien Elf64_External_Rela *loc; 558789857Sobrien 558889857Sobrien /* We need to generate a R_PPC64_RELATIVE reloc 558989857Sobrien for the dynamic linker. */ 559089857Sobrien outrel.r_offset = (htab->sgot->output_section->vma 559189857Sobrien + htab->sgot->output_offset 559289857Sobrien + off); 559389857Sobrien outrel.r_info = ELF64_R_INFO (0, R_PPC64_RELATIVE); 559489857Sobrien outrel.r_addend = relocation; 559589857Sobrien loc = (Elf64_External_Rela *) htab->srelgot->contents; 559689857Sobrien loc += htab->srelgot->reloc_count++; 559789857Sobrien bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc); 559889857Sobrien } 559989857Sobrien 560089857Sobrien local_got_offsets[r_symndx] |= 1; 560189857Sobrien } 560289857Sobrien } 560389857Sobrien 560489857Sobrien if (off >= (bfd_vma) -2) 560589857Sobrien abort (); 560689857Sobrien 560789857Sobrien relocation = htab->sgot->output_offset + off; 560889857Sobrien 560989857Sobrien /* TOC base (r2) is TOC start plus 0x8000. */ 561089857Sobrien addend -= TOC_BASE_OFF; 561189857Sobrien } 561289857Sobrien break; 561389857Sobrien 561489857Sobrien case R_PPC64_PLT16_HA: 561589857Sobrien case R_PPC64_PLT16_HI: 561689857Sobrien case R_PPC64_PLT16_LO: 561789857Sobrien case R_PPC64_PLT32: 561889857Sobrien case R_PPC64_PLT64: 561989857Sobrien /* Relocation is to the entry for this symbol in the 562089857Sobrien procedure linkage table. */ 562189857Sobrien 562289857Sobrien /* Resolve a PLT reloc against a local symbol directly, 562389857Sobrien without using the procedure linkage table. */ 562489857Sobrien if (h == NULL) 562589857Sobrien break; 562689857Sobrien 562789857Sobrien if (h->plt.offset == (bfd_vma) -1 562889857Sobrien || htab->splt == NULL) 562989857Sobrien { 563089857Sobrien /* We didn't make a PLT entry for this symbol. This 563189857Sobrien happens when statically linking PIC code, or when 563289857Sobrien using -Bsymbolic. */ 563389857Sobrien break; 563489857Sobrien } 563589857Sobrien 563689857Sobrien relocation = (htab->splt->output_section->vma 563789857Sobrien + htab->splt->output_offset 563889857Sobrien + h->plt.offset); 563989857Sobrien unresolved_reloc = false; 564089857Sobrien break; 564189857Sobrien 564289857Sobrien /* TOC16 relocs. We want the offset relative to the TOC base, 564389857Sobrien which is the address of the start of the TOC plus 0x8000. 564489857Sobrien The TOC consists of sections .got, .toc, .tocbss, and .plt, 564589857Sobrien in this order. */ 564689857Sobrien case R_PPC64_TOC16: 564789857Sobrien case R_PPC64_TOC16_LO: 564889857Sobrien case R_PPC64_TOC16_HI: 564989857Sobrien case R_PPC64_TOC16_DS: 565089857Sobrien case R_PPC64_TOC16_LO_DS: 565189857Sobrien case R_PPC64_TOC16_HA: 565289857Sobrien addend -= TOCstart + TOC_BASE_OFF; 565389857Sobrien break; 565489857Sobrien 565589857Sobrien /* Relocate against the beginning of the section. */ 565689857Sobrien case R_PPC64_SECTOFF: 565789857Sobrien case R_PPC64_SECTOFF_LO: 565889857Sobrien case R_PPC64_SECTOFF_HI: 565989857Sobrien case R_PPC64_SECTOFF_DS: 566089857Sobrien case R_PPC64_SECTOFF_LO_DS: 566189857Sobrien case R_PPC64_SECTOFF_HA: 566289857Sobrien if (sec != (asection *) 0) 566389857Sobrien addend -= sec->output_section->vma; 566489857Sobrien break; 566589857Sobrien 5666104834Sobrien case R_PPC64_REL14: 5667104834Sobrien case R_PPC64_REL14_BRNTAKEN: 5668104834Sobrien case R_PPC64_REL14_BRTAKEN: 566989857Sobrien case R_PPC64_REL24: 567089857Sobrien break; 567189857Sobrien 567289857Sobrien /* Relocations that may need to be propagated if this is a 567389857Sobrien dynamic object. */ 567489857Sobrien case R_PPC64_REL32: 567589857Sobrien case R_PPC64_REL64: 567689857Sobrien case R_PPC64_ADDR14: 567789857Sobrien case R_PPC64_ADDR14_BRNTAKEN: 567889857Sobrien case R_PPC64_ADDR14_BRTAKEN: 567989857Sobrien case R_PPC64_ADDR16: 568089857Sobrien case R_PPC64_ADDR16_DS: 568189857Sobrien case R_PPC64_ADDR16_HA: 568289857Sobrien case R_PPC64_ADDR16_HI: 568389857Sobrien case R_PPC64_ADDR16_HIGHER: 568489857Sobrien case R_PPC64_ADDR16_HIGHERA: 568589857Sobrien case R_PPC64_ADDR16_HIGHEST: 568689857Sobrien case R_PPC64_ADDR16_HIGHESTA: 568789857Sobrien case R_PPC64_ADDR16_LO: 568889857Sobrien case R_PPC64_ADDR16_LO_DS: 568989857Sobrien case R_PPC64_ADDR24: 569089857Sobrien case R_PPC64_ADDR30: 569189857Sobrien case R_PPC64_ADDR32: 569289857Sobrien case R_PPC64_ADDR64: 569389857Sobrien case R_PPC64_UADDR16: 569489857Sobrien case R_PPC64_UADDR32: 569589857Sobrien case R_PPC64_UADDR64: 569689857Sobrien /* r_symndx will be zero only for relocs against symbols 569789857Sobrien from removed linkonce sections, or sections discarded by 569889857Sobrien a linker script. */ 569989857Sobrien if (r_symndx == 0) 570089857Sobrien break; 570189857Sobrien /* Fall thru. */ 570289857Sobrien 570389857Sobrien case R_PPC64_TOC: 570489857Sobrien if ((input_section->flags & SEC_ALLOC) == 0) 570589857Sobrien break; 570689857Sobrien 570789857Sobrien if (NO_OPD_RELOCS && is_opd) 570889857Sobrien break; 570989857Sobrien 571089857Sobrien if ((info->shared 571189857Sobrien && (IS_ABSOLUTE_RELOC (r_type) 571289857Sobrien || (h != NULL 571389857Sobrien && h->dynindx != -1 571489857Sobrien && (! info->symbolic 571589857Sobrien || (h->elf_link_hash_flags 571689857Sobrien & ELF_LINK_HASH_DEF_REGULAR) == 0)))) 571789857Sobrien || (!info->shared 571889857Sobrien && h != NULL 571989857Sobrien && h->dynindx != -1 572089857Sobrien && (h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0 572189857Sobrien && (((h->elf_link_hash_flags 572289857Sobrien & ELF_LINK_HASH_DEF_DYNAMIC) != 0 572389857Sobrien && (h->elf_link_hash_flags 572489857Sobrien & ELF_LINK_HASH_DEF_REGULAR) == 0) 572589857Sobrien || h->root.type == bfd_link_hash_undefweak 572689857Sobrien || h->root.type == bfd_link_hash_undefined))) 572789857Sobrien { 572889857Sobrien Elf_Internal_Rela outrel; 572989857Sobrien boolean skip, relocate; 573089857Sobrien asection *sreloc; 573189857Sobrien Elf64_External_Rela *loc; 573289857Sobrien 573389857Sobrien /* When generating a dynamic object, these relocations 573489857Sobrien are copied into the output file to be resolved at run 573589857Sobrien time. */ 573689857Sobrien 573789857Sobrien skip = false; 573891041Sobrien relocate = false; 573989857Sobrien 574089857Sobrien outrel.r_offset = 574189857Sobrien _bfd_elf_section_offset (output_bfd, info, input_section, 574289857Sobrien rel->r_offset); 574389857Sobrien if (outrel.r_offset == (bfd_vma) -1) 574489857Sobrien skip = true; 574591041Sobrien else if (outrel.r_offset == (bfd_vma) -2) 574691041Sobrien skip = true, relocate = true; 574789857Sobrien outrel.r_offset += (input_section->output_section->vma 574889857Sobrien + input_section->output_offset); 574989857Sobrien outrel.r_addend = addend; 575089857Sobrien 575189857Sobrien if (skip) 575291041Sobrien memset (&outrel, 0, sizeof outrel); 575389857Sobrien else if (h != NULL 575489857Sobrien && h->dynindx != -1 575589857Sobrien && !is_opd 575689857Sobrien && (!IS_ABSOLUTE_RELOC (r_type) 575789857Sobrien || !info->shared 575889857Sobrien || !info->symbolic 575989857Sobrien || (h->elf_link_hash_flags 576089857Sobrien & ELF_LINK_HASH_DEF_REGULAR) == 0)) 576191041Sobrien outrel.r_info = ELF64_R_INFO (h->dynindx, r_type); 576289857Sobrien else 576389857Sobrien { 576489857Sobrien /* This symbol is local, or marked to become local, 576589857Sobrien or this is an opd section reloc which must point 576689857Sobrien at a local function. */ 576789857Sobrien outrel.r_addend += relocation; 576889857Sobrien relocate = true; 576989857Sobrien if (r_type == R_PPC64_ADDR64 || r_type == R_PPC64_TOC) 577089857Sobrien { 5771104834Sobrien if (is_opd && h != NULL) 5772104834Sobrien { 5773104834Sobrien /* Lie about opd entries. This case occurs 5774104834Sobrien when building shared libraries and we 5775104834Sobrien reference a function in another shared 5776104834Sobrien lib. The same thing happens for a weak 5777104834Sobrien definition in an application that's 5778104834Sobrien overridden by a strong definition in a 5779104834Sobrien shared lib. (I believe this is a generic 5780104834Sobrien bug in binutils handling of weak syms.) 5781104834Sobrien In these cases we won't use the opd 5782104834Sobrien entry in this lib. */ 5783104834Sobrien unresolved_reloc = false; 5784104834Sobrien } 578589857Sobrien outrel.r_info = ELF64_R_INFO (0, R_PPC64_RELATIVE); 578689857Sobrien } 578789857Sobrien else 578889857Sobrien { 578989857Sobrien long indx = 0; 579089857Sobrien 579189857Sobrien if (bfd_is_abs_section (sec)) 579289857Sobrien ; 579389857Sobrien else if (sec == NULL || sec->owner == NULL) 579489857Sobrien { 579589857Sobrien bfd_set_error (bfd_error_bad_value); 579689857Sobrien return false; 579789857Sobrien } 579889857Sobrien else 579989857Sobrien { 580089857Sobrien asection *osec; 580189857Sobrien 580289857Sobrien osec = sec->output_section; 580389857Sobrien indx = elf_section_data (osec)->dynindx; 580489857Sobrien 580589857Sobrien /* We are turning this relocation into one 580689857Sobrien against a section symbol, so subtract out 580789857Sobrien the output section's address but not the 580889857Sobrien offset of the input section in the output 580989857Sobrien section. */ 581089857Sobrien outrel.r_addend -= osec->vma; 581189857Sobrien } 581289857Sobrien 581389857Sobrien outrel.r_info = ELF64_R_INFO (indx, r_type); 581489857Sobrien } 581589857Sobrien } 581689857Sobrien 581789857Sobrien sreloc = elf_section_data (input_section)->sreloc; 581889857Sobrien if (sreloc == NULL) 581989857Sobrien abort (); 582089857Sobrien 582189857Sobrien loc = (Elf64_External_Rela *) sreloc->contents; 582289857Sobrien loc += sreloc->reloc_count++; 582389857Sobrien bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc); 582489857Sobrien 582589857Sobrien /* If this reloc is against an external symbol, it will 582689857Sobrien be computed at runtime, so there's no need to do 582789857Sobrien anything now. */ 582889857Sobrien if (! relocate) 582989857Sobrien continue; 583089857Sobrien } 583189857Sobrien break; 583289857Sobrien 583389857Sobrien case R_PPC64_COPY: 583489857Sobrien case R_PPC64_GLOB_DAT: 583589857Sobrien case R_PPC64_JMP_SLOT: 583689857Sobrien case R_PPC64_RELATIVE: 583789857Sobrien /* We shouldn't ever see these dynamic relocs in relocatable 583889857Sobrien files. */ 583989857Sobrien /* Fall thru */ 584089857Sobrien 584189857Sobrien case R_PPC64_PLTGOT16: 584289857Sobrien case R_PPC64_PLTGOT16_DS: 584389857Sobrien case R_PPC64_PLTGOT16_HA: 584489857Sobrien case R_PPC64_PLTGOT16_HI: 584589857Sobrien case R_PPC64_PLTGOT16_LO: 584689857Sobrien case R_PPC64_PLTGOT16_LO_DS: 584789857Sobrien case R_PPC64_PLTREL32: 584889857Sobrien case R_PPC64_PLTREL64: 584989857Sobrien /* These ones haven't been implemented yet. */ 585089857Sobrien 585189857Sobrien (*_bfd_error_handler) 585289857Sobrien (_("%s: Relocation %s is not supported for symbol %s."), 585389857Sobrien bfd_archive_filename (input_bfd), 585489857Sobrien ppc64_elf_howto_table[(int) r_type]->name, sym_name); 585589857Sobrien 585689857Sobrien bfd_set_error (bfd_error_invalid_operation); 585789857Sobrien ret = false; 585889857Sobrien continue; 585989857Sobrien } 586089857Sobrien 586189857Sobrien /* Do any further special processing. */ 586289857Sobrien switch (r_type) 586389857Sobrien { 586489857Sobrien default: 586589857Sobrien break; 586689857Sobrien 586789857Sobrien case R_PPC64_ADDR16_HA: 586889857Sobrien case R_PPC64_ADDR16_HIGHERA: 586989857Sobrien case R_PPC64_ADDR16_HIGHESTA: 587089857Sobrien case R_PPC64_PLT16_HA: 587189857Sobrien case R_PPC64_TOC16_HA: 587289857Sobrien case R_PPC64_SECTOFF_HA: 587389857Sobrien /* It's just possible that this symbol is a weak symbol 587489857Sobrien that's not actually defined anywhere. In that case, 587589857Sobrien 'sec' would be NULL, and we should leave the symbol 587689857Sobrien alone (it will be set to zero elsewhere in the link). */ 587789857Sobrien if (sec != NULL) 587889857Sobrien /* Add 0x10000 if sign bit in 0:15 is set. */ 587989857Sobrien addend += ((relocation + addend) & 0x8000) << 1; 588089857Sobrien break; 588189857Sobrien 588289857Sobrien case R_PPC64_ADDR16_DS: 588389857Sobrien case R_PPC64_ADDR16_LO_DS: 588489857Sobrien case R_PPC64_GOT16_DS: 588589857Sobrien case R_PPC64_GOT16_LO_DS: 588689857Sobrien case R_PPC64_PLT16_LO_DS: 588789857Sobrien case R_PPC64_SECTOFF_DS: 588889857Sobrien case R_PPC64_SECTOFF_LO_DS: 588989857Sobrien case R_PPC64_TOC16_DS: 589089857Sobrien case R_PPC64_TOC16_LO_DS: 589189857Sobrien case R_PPC64_PLTGOT16_DS: 589289857Sobrien case R_PPC64_PLTGOT16_LO_DS: 589389857Sobrien if (((relocation + addend) & 3) != 0) 589489857Sobrien { 589589857Sobrien (*_bfd_error_handler) 589689857Sobrien (_("%s: error: relocation %s not a multiple of 4"), 589789857Sobrien bfd_archive_filename (input_bfd), 589889857Sobrien ppc64_elf_howto_table[(int) r_type]->name); 589989857Sobrien bfd_set_error (bfd_error_bad_value); 590089857Sobrien ret = false; 590189857Sobrien continue; 590289857Sobrien } 590389857Sobrien break; 5904104834Sobrien 5905104834Sobrien case R_PPC64_REL14: 5906104834Sobrien case R_PPC64_REL14_BRNTAKEN: 5907104834Sobrien case R_PPC64_REL14_BRTAKEN: 5908104834Sobrien max_br_offset = 1 << 15; 5909104834Sobrien goto branch_check; 5910104834Sobrien 5911104834Sobrien case R_PPC64_REL24: 5912104834Sobrien max_br_offset = 1 << 25; 5913104834Sobrien 5914104834Sobrien branch_check: 5915104834Sobrien /* If the branch is out of reach, then redirect the 5916104834Sobrien call to the local stub for this function. */ 5917104834Sobrien from = (offset 5918104834Sobrien + input_section->output_offset 5919104834Sobrien + input_section->output_section->vma); 5920104834Sobrien if (relocation + addend - from + max_br_offset >= 2 * max_br_offset 5921104834Sobrien && (stub_entry = ppc_get_stub_entry (input_section, sec, h, 5922104834Sobrien rel, htab)) != NULL) 5923104834Sobrien { 5924104834Sobrien /* Munge up the value and addend so that we call the stub 5925104834Sobrien rather than the procedure directly. */ 5926104834Sobrien relocation = (stub_entry->stub_offset 5927104834Sobrien + stub_entry->stub_sec->output_offset 5928104834Sobrien + stub_entry->stub_sec->output_section->vma); 5929104834Sobrien addend = 0; 5930104834Sobrien } 5931104834Sobrien break; 593289857Sobrien } 593389857Sobrien 5934104834Sobrien /* Dynamic relocs are not propagated for SEC_DEBUGGING sections 5935104834Sobrien because such sections are not SEC_ALLOC and thus ld.so will 5936104834Sobrien not process them. */ 593789857Sobrien if (unresolved_reloc 5938104834Sobrien && !((input_section->flags & SEC_DEBUGGING) != 0 593989857Sobrien && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0)) 5940104834Sobrien { 5941104834Sobrien (*_bfd_error_handler) 5942104834Sobrien (_("%s(%s+0x%lx): unresolvable relocation against symbol `%s'"), 5943104834Sobrien bfd_archive_filename (input_bfd), 5944104834Sobrien bfd_get_section_name (input_bfd, input_section), 5945104834Sobrien (long) rel->r_offset, 5946104834Sobrien h->root.root.string); 5947104834Sobrien ret = false; 5948104834Sobrien } 594989857Sobrien 595089857Sobrien r = _bfd_final_link_relocate (ppc64_elf_howto_table[(int) r_type], 595189857Sobrien input_bfd, 595289857Sobrien input_section, 595389857Sobrien contents, 595489857Sobrien offset, 595589857Sobrien relocation, 595689857Sobrien addend); 595789857Sobrien 5958104834Sobrien if (r != bfd_reloc_ok) 595989857Sobrien { 596089857Sobrien const char *name; 596189857Sobrien 596289857Sobrien if (h != NULL) 596389857Sobrien { 596489857Sobrien if (h->root.type == bfd_link_hash_undefweak 596589857Sobrien && ppc64_elf_howto_table[(int) r_type]->pc_relative) 596689857Sobrien { 596789857Sobrien /* Assume this is a call protected by other code that 596889857Sobrien detects the symbol is undefined. If this is the case, 596989857Sobrien we can safely ignore the overflow. If not, the 597089857Sobrien program is hosed anyway, and a little warning isn't 597189857Sobrien going to help. */ 597289857Sobrien 597389857Sobrien continue; 597489857Sobrien } 597589857Sobrien 597689857Sobrien name = h->root.root.string; 597789857Sobrien } 597889857Sobrien else 597989857Sobrien { 598089857Sobrien name = bfd_elf_string_from_elf_section (input_bfd, 598189857Sobrien symtab_hdr->sh_link, 598289857Sobrien sym->st_name); 598389857Sobrien if (name == NULL) 598489857Sobrien continue; 598589857Sobrien if (*name == '\0') 598689857Sobrien name = bfd_section_name (input_bfd, sec); 598789857Sobrien } 598889857Sobrien 5989104834Sobrien if (r == bfd_reloc_overflow) 5990104834Sobrien { 5991104834Sobrien if (warned) 5992104834Sobrien continue; 5993104834Sobrien if (!((*info->callbacks->reloc_overflow) 5994104834Sobrien (info, name, ppc64_elf_howto_table[(int) r_type]->name, 5995104834Sobrien rel->r_addend, input_bfd, input_section, offset))) 5996104834Sobrien return false; 5997104834Sobrien } 5998104834Sobrien else 5999104834Sobrien { 6000104834Sobrien (*_bfd_error_handler) 6001104834Sobrien (_("%s(%s+0x%lx): reloc against `%s': error %d"), 6002104834Sobrien bfd_archive_filename (input_bfd), 6003104834Sobrien bfd_get_section_name (input_bfd, input_section), 6004104834Sobrien (long) rel->r_offset, name, (int) r); 6005104834Sobrien ret = false; 6006104834Sobrien } 600789857Sobrien } 600889857Sobrien } 600989857Sobrien 601089857Sobrien return ret; 601189857Sobrien} 601289857Sobrien 601389857Sobrien/* Finish up dynamic symbol handling. We set the contents of various 601489857Sobrien dynamic sections here. */ 601589857Sobrien 601689857Sobrienstatic boolean 601789857Sobrienppc64_elf_finish_dynamic_symbol (output_bfd, info, h, sym) 601889857Sobrien bfd *output_bfd; 601989857Sobrien struct bfd_link_info *info; 602089857Sobrien struct elf_link_hash_entry *h; 602189857Sobrien Elf_Internal_Sym *sym; 602289857Sobrien{ 602389857Sobrien struct ppc_link_hash_table *htab; 602489857Sobrien bfd *dynobj; 602589857Sobrien 602689857Sobrien htab = ppc_hash_table (info); 602789857Sobrien dynobj = htab->elf.dynobj; 602889857Sobrien 602989857Sobrien if (h->plt.offset != (bfd_vma) -1 603089857Sobrien && ((struct ppc_link_hash_entry *) h)->is_func_descriptor) 603189857Sobrien { 603289857Sobrien Elf_Internal_Rela rela; 603389857Sobrien Elf64_External_Rela *loc; 603489857Sobrien 603589857Sobrien /* This symbol has an entry in the procedure linkage table. Set 6036104834Sobrien it up. */ 603789857Sobrien 603889857Sobrien if (htab->splt == NULL 603989857Sobrien || htab->srelplt == NULL 604089857Sobrien || htab->sglink == NULL) 604189857Sobrien abort (); 604289857Sobrien 604389857Sobrien /* Create a JMP_SLOT reloc to inform the dynamic linker to 604489857Sobrien fill in the PLT entry. */ 604589857Sobrien 604689857Sobrien rela.r_offset = (htab->splt->output_section->vma 604789857Sobrien + htab->splt->output_offset 604889857Sobrien + h->plt.offset); 604989857Sobrien rela.r_info = ELF64_R_INFO (h->dynindx, R_PPC64_JMP_SLOT); 605089857Sobrien rela.r_addend = 0; 605189857Sobrien 605289857Sobrien loc = (Elf64_External_Rela *) htab->srelplt->contents; 605389857Sobrien loc += (h->plt.offset - PLT_INITIAL_ENTRY_SIZE) / PLT_ENTRY_SIZE; 605489857Sobrien bfd_elf64_swap_reloca_out (output_bfd, &rela, loc); 605589857Sobrien } 605689857Sobrien 605789857Sobrien if (h->got.offset != (bfd_vma) -1) 605889857Sobrien { 605989857Sobrien Elf_Internal_Rela rela; 606089857Sobrien Elf64_External_Rela *loc; 606189857Sobrien 606289857Sobrien /* This symbol has an entry in the global offset table. Set it 6063104834Sobrien up. */ 606489857Sobrien 606589857Sobrien if (htab->sgot == NULL || htab->srelgot == NULL) 606689857Sobrien abort (); 606789857Sobrien 606889857Sobrien rela.r_offset = (htab->sgot->output_section->vma 606989857Sobrien + htab->sgot->output_offset 607089857Sobrien + (h->got.offset &~ (bfd_vma) 1)); 607189857Sobrien 607289857Sobrien /* If this is a static link, or it is a -Bsymbolic link and the 607389857Sobrien symbol is defined locally or was forced to be local because 607489857Sobrien of a version file, we just want to emit a RELATIVE reloc. 607589857Sobrien The entry in the global offset table will already have been 607689857Sobrien initialized in the relocate_section function. */ 607789857Sobrien if (info->shared 607889857Sobrien && (info->symbolic 607989857Sobrien || h->dynindx == -1 608089857Sobrien || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL)) 608189857Sobrien && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)) 608289857Sobrien { 608389857Sobrien BFD_ASSERT((h->got.offset & 1) != 0); 608489857Sobrien rela.r_info = ELF64_R_INFO (0, R_PPC64_RELATIVE); 608589857Sobrien rela.r_addend = (h->root.u.def.value 608689857Sobrien + h->root.u.def.section->output_section->vma 608789857Sobrien + h->root.u.def.section->output_offset); 608889857Sobrien } 608989857Sobrien else 609089857Sobrien { 609189857Sobrien BFD_ASSERT ((h->got.offset & 1) == 0); 609289857Sobrien bfd_put_64 (output_bfd, (bfd_vma) 0, 609389857Sobrien htab->sgot->contents + h->got.offset); 609489857Sobrien rela.r_info = ELF64_R_INFO (h->dynindx, R_PPC64_GLOB_DAT); 609589857Sobrien rela.r_addend = 0; 609689857Sobrien } 609789857Sobrien 609889857Sobrien loc = (Elf64_External_Rela *) htab->srelgot->contents; 609989857Sobrien loc += htab->srelgot->reloc_count++; 610089857Sobrien bfd_elf64_swap_reloca_out (output_bfd, &rela, loc); 610189857Sobrien } 610289857Sobrien 610389857Sobrien if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_COPY) != 0) 610489857Sobrien { 610589857Sobrien Elf_Internal_Rela rela; 610689857Sobrien Elf64_External_Rela *loc; 610789857Sobrien 610889857Sobrien /* This symbol needs a copy reloc. Set it up. */ 610989857Sobrien 611089857Sobrien if (h->dynindx == -1 611189857Sobrien || (h->root.type != bfd_link_hash_defined 611289857Sobrien && h->root.type != bfd_link_hash_defweak) 611389857Sobrien || htab->srelbss == NULL) 611489857Sobrien abort (); 611589857Sobrien 611689857Sobrien rela.r_offset = (h->root.u.def.value 611789857Sobrien + h->root.u.def.section->output_section->vma 611889857Sobrien + h->root.u.def.section->output_offset); 611989857Sobrien rela.r_info = ELF64_R_INFO (h->dynindx, R_PPC64_COPY); 612089857Sobrien rela.r_addend = 0; 612189857Sobrien loc = (Elf64_External_Rela *) htab->srelbss->contents; 612289857Sobrien loc += htab->srelbss->reloc_count++; 612389857Sobrien bfd_elf64_swap_reloca_out (output_bfd, &rela, loc); 612489857Sobrien } 612589857Sobrien 612689857Sobrien /* Mark some specially defined symbols as absolute. */ 612789857Sobrien if (strcmp (h->root.root.string, "_DYNAMIC") == 0) 612889857Sobrien sym->st_shndx = SHN_ABS; 612989857Sobrien 613089857Sobrien return true; 613189857Sobrien} 613289857Sobrien 613389857Sobrien/* Used to decide how to sort relocs in an optimal manner for the 613489857Sobrien dynamic linker, before writing them out. */ 613589857Sobrien 613689857Sobrienstatic enum elf_reloc_type_class 613789857Sobrienppc64_elf_reloc_type_class (rela) 613889857Sobrien const Elf_Internal_Rela *rela; 613989857Sobrien{ 614089857Sobrien enum elf_ppc_reloc_type r_type; 614189857Sobrien 614289857Sobrien r_type = (enum elf_ppc_reloc_type) ELF64_R_TYPE (rela->r_info); 614389857Sobrien switch (r_type) 614489857Sobrien { 614589857Sobrien case R_PPC64_RELATIVE: 614689857Sobrien return reloc_class_relative; 614789857Sobrien case R_PPC64_JMP_SLOT: 614889857Sobrien return reloc_class_plt; 614989857Sobrien case R_PPC64_COPY: 615089857Sobrien return reloc_class_copy; 615189857Sobrien default: 615289857Sobrien return reloc_class_normal; 615389857Sobrien } 615489857Sobrien} 615589857Sobrien 615689857Sobrien/* Finish up the dynamic sections. */ 615789857Sobrien 615889857Sobrienstatic boolean 615989857Sobrienppc64_elf_finish_dynamic_sections (output_bfd, info) 616089857Sobrien bfd *output_bfd; 616189857Sobrien struct bfd_link_info *info; 616289857Sobrien{ 616389857Sobrien struct ppc_link_hash_table *htab; 616489857Sobrien bfd *dynobj; 616589857Sobrien asection *sdyn; 616689857Sobrien 616789857Sobrien htab = ppc_hash_table (info); 616889857Sobrien dynobj = htab->elf.dynobj; 616989857Sobrien sdyn = bfd_get_section_by_name (dynobj, ".dynamic"); 617089857Sobrien 617189857Sobrien if (htab->elf.dynamic_sections_created) 617289857Sobrien { 617389857Sobrien Elf64_External_Dyn *dyncon, *dynconend; 617489857Sobrien 617589857Sobrien if (sdyn == NULL || htab->sgot == NULL) 617689857Sobrien abort (); 617789857Sobrien 617889857Sobrien dyncon = (Elf64_External_Dyn *) sdyn->contents; 617989857Sobrien dynconend = (Elf64_External_Dyn *) (sdyn->contents + sdyn->_raw_size); 618089857Sobrien for (; dyncon < dynconend; dyncon++) 618189857Sobrien { 618289857Sobrien Elf_Internal_Dyn dyn; 618391041Sobrien asection *s; 618489857Sobrien 618589857Sobrien bfd_elf64_swap_dyn_in (dynobj, dyncon, &dyn); 618689857Sobrien 618789857Sobrien switch (dyn.d_tag) 618889857Sobrien { 618989857Sobrien default: 619089857Sobrien continue; 619189857Sobrien 619289857Sobrien case DT_PPC64_GLINK: 619389857Sobrien dyn.d_un.d_ptr = (htab->sglink->output_section->vma 619489857Sobrien + htab->sglink->output_offset); 619589857Sobrien break; 619689857Sobrien 619791041Sobrien case DT_PPC64_OPD: 619891041Sobrien s = bfd_get_section_by_name (output_bfd, ".opd"); 619991041Sobrien if (s != NULL) 620091041Sobrien dyn.d_un.d_ptr = s->vma; 620191041Sobrien break; 620291041Sobrien 620391041Sobrien case DT_PPC64_OPDSZ: 620491041Sobrien s = bfd_get_section_by_name (output_bfd, ".opd"); 620591041Sobrien if (s != NULL) 620691041Sobrien dyn.d_un.d_val = s->_raw_size; 620791041Sobrien break; 620891041Sobrien 620989857Sobrien case DT_PLTGOT: 621089857Sobrien dyn.d_un.d_ptr = (htab->splt->output_section->vma 621189857Sobrien + htab->splt->output_offset); 621289857Sobrien break; 621389857Sobrien 621489857Sobrien case DT_JMPREL: 621589857Sobrien dyn.d_un.d_ptr = (htab->srelplt->output_section->vma 621689857Sobrien + htab->srelplt->output_offset); 621789857Sobrien break; 621889857Sobrien 621989857Sobrien case DT_PLTRELSZ: 622089857Sobrien dyn.d_un.d_val = htab->srelplt->_raw_size; 622189857Sobrien break; 622289857Sobrien 622389857Sobrien case DT_RELASZ: 622489857Sobrien /* Don't count procedure linkage table relocs in the 622589857Sobrien overall reloc count. */ 622689857Sobrien if (htab->srelplt != NULL) 622789857Sobrien dyn.d_un.d_val -= htab->srelplt->_raw_size; 622889857Sobrien break; 622989857Sobrien } 623089857Sobrien 623189857Sobrien bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon); 623289857Sobrien } 623389857Sobrien } 623489857Sobrien 623589857Sobrien if (htab->sgot != NULL && htab->sgot->_raw_size != 0) 623689857Sobrien { 623789857Sobrien /* Fill in the first entry in the global offset table. 623889857Sobrien We use it to hold the link-time TOCbase. */ 623989857Sobrien bfd_put_64 (output_bfd, 624089857Sobrien elf_gp (output_bfd) + TOC_BASE_OFF, 624189857Sobrien htab->sgot->contents); 624289857Sobrien 624389857Sobrien /* Set .got entry size. */ 624489857Sobrien elf_section_data (htab->sgot->output_section)->this_hdr.sh_entsize = 8; 624589857Sobrien } 624689857Sobrien 624789857Sobrien if (htab->splt != NULL && htab->splt->_raw_size != 0) 624889857Sobrien { 624989857Sobrien /* Set .plt entry size. */ 625089857Sobrien elf_section_data (htab->splt->output_section)->this_hdr.sh_entsize 625189857Sobrien = PLT_ENTRY_SIZE; 625289857Sobrien } 625389857Sobrien 625489857Sobrien return true; 625589857Sobrien} 625689857Sobrien 625789857Sobrien#define TARGET_LITTLE_SYM bfd_elf64_powerpcle_vec 625889857Sobrien#define TARGET_LITTLE_NAME "elf64-powerpcle" 625989857Sobrien#define TARGET_BIG_SYM bfd_elf64_powerpc_vec 626089857Sobrien#define TARGET_BIG_NAME "elf64-powerpc" 626189857Sobrien#define ELF_ARCH bfd_arch_powerpc 626289857Sobrien#define ELF_MACHINE_CODE EM_PPC64 626389857Sobrien#define ELF_MAXPAGESIZE 0x10000 626489857Sobrien#define elf_info_to_howto ppc64_elf_info_to_howto 626589857Sobrien 626689857Sobrien#ifdef EM_CYGNUS_POWERPC 626789857Sobrien#define ELF_MACHINE_ALT1 EM_CYGNUS_POWERPC 626889857Sobrien#endif 626989857Sobrien 627089857Sobrien#ifdef EM_PPC_OLD 627189857Sobrien#define ELF_MACHINE_ALT2 EM_PPC_OLD 627289857Sobrien#endif 627389857Sobrien 627489857Sobrien#define elf_backend_want_got_sym 0 627589857Sobrien#define elf_backend_want_plt_sym 0 627689857Sobrien#define elf_backend_plt_alignment 3 627789857Sobrien#define elf_backend_plt_not_loaded 1 627889857Sobrien#define elf_backend_got_symbol_offset 0 627989857Sobrien#define elf_backend_got_header_size 8 628089857Sobrien#define elf_backend_plt_header_size PLT_INITIAL_ENTRY_SIZE 628189857Sobrien#define elf_backend_can_gc_sections 1 628289857Sobrien#define elf_backend_can_refcount 1 628399461Sobrien#define elf_backend_rela_normal 1 628489857Sobrien 628589857Sobrien#define bfd_elf64_bfd_reloc_type_lookup ppc64_elf_reloc_type_lookup 628689857Sobrien#define bfd_elf64_bfd_merge_private_bfd_data ppc64_elf_merge_private_bfd_data 628789857Sobrien#define bfd_elf64_bfd_link_hash_table_create ppc64_elf_link_hash_table_create 6288104834Sobrien#define bfd_elf64_bfd_link_hash_table_free ppc64_elf_link_hash_table_free 628989857Sobrien 6290104834Sobrien#define elf_backend_object_p ppc64_elf_object_p 629189857Sobrien#define elf_backend_create_dynamic_sections ppc64_elf_create_dynamic_sections 629289857Sobrien#define elf_backend_copy_indirect_symbol ppc64_elf_copy_indirect_symbol 629389857Sobrien#define elf_backend_check_relocs ppc64_elf_check_relocs 629489857Sobrien#define elf_backend_gc_mark_hook ppc64_elf_gc_mark_hook 629589857Sobrien#define elf_backend_gc_sweep_hook ppc64_elf_gc_sweep_hook 629689857Sobrien#define elf_backend_adjust_dynamic_symbol ppc64_elf_adjust_dynamic_symbol 629789857Sobrien#define elf_backend_hide_symbol ppc64_elf_hide_symbol 629889857Sobrien#define elf_backend_always_size_sections ppc64_elf_func_desc_adjust 629989857Sobrien#define elf_backend_size_dynamic_sections ppc64_elf_size_dynamic_sections 630089857Sobrien#define elf_backend_relocate_section ppc64_elf_relocate_section 630189857Sobrien#define elf_backend_finish_dynamic_symbol ppc64_elf_finish_dynamic_symbol 630289857Sobrien#define elf_backend_reloc_type_class ppc64_elf_reloc_type_class 630389857Sobrien#define elf_backend_finish_dynamic_sections ppc64_elf_finish_dynamic_sections 630489857Sobrien 630589857Sobrien#include "elf64-target.h" 6306