elf64-ppc.c revision 89857
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)); 4289857Sobrienstatic bfd_reloc_status_type ppc64_elf_addr16_ha_reloc 4389857Sobrien PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); 4489857Sobrienstatic boolean ppc64_elf_set_private_flags 4589857Sobrien PARAMS ((bfd *, flagword)); 4689857Sobrienstatic boolean ppc64_elf_merge_private_bfd_data 4789857Sobrien PARAMS ((bfd *, bfd *)); 4889857Sobrienstatic boolean ppc64_elf_section_from_shdr 4989857Sobrien PARAMS ((bfd *, Elf64_Internal_Shdr *, char *)); 5089857Sobrienstatic struct bfd_hash_entry *link_hash_newfunc 5189857Sobrien PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *)); 5289857Sobrienstatic struct bfd_link_hash_table *ppc64_elf_link_hash_table_create 5389857Sobrien PARAMS ((bfd *)); 5489857Sobrienstatic boolean create_got_section 5589857Sobrien PARAMS ((bfd *, struct bfd_link_info *)); 5689857Sobrienstatic boolean ppc64_elf_create_dynamic_sections 5789857Sobrien PARAMS ((bfd *, struct bfd_link_info *)); 5889857Sobrienstatic void ppc64_elf_copy_indirect_symbol 5989857Sobrien PARAMS ((struct elf_link_hash_entry *, struct elf_link_hash_entry *)); 6089857Sobrienstatic boolean ppc64_elf_check_relocs 6189857Sobrien PARAMS ((bfd *, struct bfd_link_info *, asection *, 6289857Sobrien const Elf_Internal_Rela *)); 6389857Sobrienstatic asection * ppc64_elf_gc_mark_hook 6489857Sobrien PARAMS ((bfd *abfd, struct bfd_link_info *info, Elf_Internal_Rela *rel, 6589857Sobrien struct elf_link_hash_entry *h, Elf_Internal_Sym *sym)); 6689857Sobrienstatic boolean ppc64_elf_gc_sweep_hook 6789857Sobrien PARAMS ((bfd *abfd, struct bfd_link_info *info, asection *sec, 6889857Sobrien const Elf_Internal_Rela *relocs)); 6989857Sobrienstatic boolean func_desc_adjust 7089857Sobrien PARAMS ((struct elf_link_hash_entry *, PTR)); 7189857Sobrienstatic boolean ppc64_elf_func_desc_adjust 7289857Sobrien PARAMS ((bfd *, struct bfd_link_info *)); 7389857Sobrienstatic boolean ppc64_elf_adjust_dynamic_symbol 7489857Sobrien PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *)); 7589857Sobrienstatic void ppc64_elf_hide_symbol 7689857Sobrien PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *, boolean)); 7789857Sobrienstatic boolean allocate_dynrelocs 7889857Sobrien PARAMS ((struct elf_link_hash_entry *, PTR)); 7989857Sobrienstatic boolean readonly_dynrelocs 8089857Sobrien PARAMS ((struct elf_link_hash_entry *, PTR)); 8189857Sobrienstatic enum elf_reloc_type_class ppc64_elf_reloc_type_class 8289857Sobrien PARAMS ((const Elf_Internal_Rela *)); 8389857Sobrienstatic boolean ppc64_elf_size_dynamic_sections 8489857Sobrien PARAMS ((bfd *, struct bfd_link_info *)); 8589857Sobrienstatic bfd_byte *build_plt_stub 8689857Sobrien PARAMS ((bfd *, bfd_byte *, int, int)); 8789857Sobrienstatic boolean build_one_stub 8889857Sobrien PARAMS ((struct elf_link_hash_entry *, PTR)); 8989857Sobrienstatic boolean ppc64_elf_fake_sections 9089857Sobrien PARAMS ((bfd *, Elf64_Internal_Shdr *, asection *)); 9189857Sobrienstatic boolean ppc64_elf_relocate_section 9289857Sobrien PARAMS ((bfd *, struct bfd_link_info *info, bfd *, asection *, bfd_byte *, 9389857Sobrien Elf_Internal_Rela *relocs, Elf_Internal_Sym *local_syms, 9489857Sobrien asection **)); 9589857Sobrienstatic boolean ppc64_elf_finish_dynamic_symbol 9689857Sobrien PARAMS ((bfd *, struct bfd_link_info *, struct elf_link_hash_entry *, 9789857Sobrien Elf_Internal_Sym *)); 9889857Sobrienstatic boolean ppc64_elf_finish_dynamic_sections 9989857Sobrien PARAMS ((bfd *, struct bfd_link_info *)); 10089857Sobrien 10189857Sobrien 10289857Sobrien/* Mask to set RA in memory instructions. */ 10389857Sobrien#define RA_REGISTER_MASK 0x001f0000 10489857Sobrien 10589857Sobrien/* Value to shift register by to insert RA. */ 10689857Sobrien#define RA_REGISTER_SHIFT 16 10789857Sobrien 10889857Sobrien/* The name of the dynamic interpreter. This is put in the .interp 10989857Sobrien section. */ 11089857Sobrien#define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1" 11189857Sobrien 11289857Sobrien/* The size in bytes of an entry in the procedure linkage table. */ 11389857Sobrien#define PLT_ENTRY_SIZE 24 11489857Sobrien 11589857Sobrien/* The initial size of the plt reserved for the dynamic linker. */ 11689857Sobrien#define PLT_INITIAL_ENTRY_SIZE PLT_ENTRY_SIZE 11789857Sobrien 11889857Sobrien/* TOC base pointers offset from start of TOC. */ 11989857Sobrien#define TOC_BASE_OFF (0x8000) 12089857Sobrien 12189857Sobrien/* .plt call stub instructions. */ 12289857Sobrien#define ADDIS_R12_R2 0x3d820000 /* addis %r12,%r2,xxx@ha */ 12389857Sobrien#define STD_R2_40R1 0xf8410028 /* std %r2,40(%r1) */ 12489857Sobrien#define LD_R11_0R12 0xe96c0000 /* ld %r11,xxx+0@l(%r12) */ 12589857Sobrien#define LD_R2_0R12 0xe84c0000 /* ld %r2,xxx+8@l(%r12) */ 12689857Sobrien#define MTCTR_R11 0x7d6903a6 /* mtctr %r11 */ 12789857Sobrien /* ld %r11,xxx+16@l(%r12) */ 12889857Sobrien#define BCTR 0x4e800420 /* bctr */ 12989857Sobrien 13089857Sobrien/* The normal stub is this size. */ 13189857Sobrien#define PLT_CALL_STUB_SIZE (7*4) 13289857Sobrien 13389857Sobrien/* But sometimes the .plt entry crosses a 64k boundary, and we need 13489857Sobrien to adjust the high word with this insn. */ 13589857Sobrien#define ADDIS_R12_R12_1 0x3d8c0001 /* addis %r12,%r12,1 */ 13689857Sobrien 13789857Sobrien/* The .glink fixup call stub is the same as the .plt call stub, but 13889857Sobrien the first instruction restores r2, and the std is omitted. */ 13989857Sobrien#define LD_R2_40R1 0xe8410028 /* ld %r2,40(%r1) */ 14089857Sobrien 14189857Sobrien/* Always allow this much space. */ 14289857Sobrien#define GLINK_CALL_STUB_SIZE (8*4) 14389857Sobrien 14489857Sobrien/* Pad with this. */ 14589857Sobrien#define NOP 0x60000000 14689857Sobrien 14789857Sobrien/* .glink entries for the first 32k functions are two instructions. */ 14889857Sobrien#define LI_R0_0 0x38000000 /* li %r0,0 */ 14989857Sobrien#define B_DOT 0x48000000 /* b . */ 15089857Sobrien 15189857Sobrien/* After that, we need two instructions to load the index, followed by 15289857Sobrien a branch. */ 15389857Sobrien#define LIS_R0_0 0x3c000000 /* lis %r0,0 */ 15489857Sobrien#define ORI_R0_R0_0 0x60000000 /* ori %r0,%r0,0 */ 15589857Sobrien 15689857Sobrien/* Since .opd is an array of descriptors and each entry will end up 15789857Sobrien with identical R_PPC64_RELATIVE relocs, there is really no need to 15889857Sobrien propagate .opd relocs; The dynamic linker should be taught to 15989857Sobrien relocate .opd without reloc entries. FIXME: the dynamic linker 16089857Sobrien will need to know where and how large .opd is via a couple of new 16189857Sobrien DT_PPC64_* tags, or perhaps just with one reloc that specifies the 16289857Sobrien start of .opd via its offset and the size via its addend. Also, 16389857Sobrien .opd should be trimmed of unused values. */ 16489857Sobrien#ifndef NO_OPD_RELOCS 16589857Sobrien#define NO_OPD_RELOCS 0 16689857Sobrien#endif 16789857Sobrien 16889857Sobrien/* Relocation HOWTO's. */ 16989857Sobrienstatic reloc_howto_type *ppc64_elf_howto_table[(int) R_PPC_max]; 17089857Sobrien 17189857Sobrienstatic reloc_howto_type ppc64_elf_howto_raw[] = { 17289857Sobrien /* This reloc does nothing. */ 17389857Sobrien HOWTO (R_PPC64_NONE, /* type */ 17489857Sobrien 0, /* rightshift */ 17589857Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 17689857Sobrien 32, /* bitsize */ 17789857Sobrien false, /* pc_relative */ 17889857Sobrien 0, /* bitpos */ 17989857Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 18089857Sobrien bfd_elf_generic_reloc, /* special_function */ 18189857Sobrien "R_PPC64_NONE", /* name */ 18289857Sobrien false, /* partial_inplace */ 18389857Sobrien 0, /* src_mask */ 18489857Sobrien 0, /* dst_mask */ 18589857Sobrien false), /* pcrel_offset */ 18689857Sobrien 18789857Sobrien /* A standard 32 bit relocation. */ 18889857Sobrien HOWTO (R_PPC64_ADDR32, /* type */ 18989857Sobrien 0, /* rightshift */ 19089857Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 19189857Sobrien 32, /* bitsize */ 19289857Sobrien false, /* pc_relative */ 19389857Sobrien 0, /* bitpos */ 19489857Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 19589857Sobrien bfd_elf_generic_reloc, /* special_function */ 19689857Sobrien "R_PPC64_ADDR32", /* name */ 19789857Sobrien false, /* partial_inplace */ 19889857Sobrien 0, /* src_mask */ 19989857Sobrien 0xffffffff, /* dst_mask */ 20089857Sobrien false), /* pcrel_offset */ 20189857Sobrien 20289857Sobrien /* An absolute 26 bit branch; the lower two bits must be zero. 20389857Sobrien FIXME: we don't check that, we just clear them. */ 20489857Sobrien HOWTO (R_PPC64_ADDR24, /* type */ 20589857Sobrien 0, /* rightshift */ 20689857Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 20789857Sobrien 26, /* bitsize */ 20889857Sobrien false, /* pc_relative */ 20989857Sobrien 0, /* bitpos */ 21089857Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 21189857Sobrien bfd_elf_generic_reloc, /* special_function */ 21289857Sobrien "R_PPC64_ADDR24", /* name */ 21389857Sobrien false, /* partial_inplace */ 21489857Sobrien 0, /* src_mask */ 21589857Sobrien 0x3fffffc, /* dst_mask */ 21689857Sobrien false), /* pcrel_offset */ 21789857Sobrien 21889857Sobrien /* A standard 16 bit relocation. */ 21989857Sobrien HOWTO (R_PPC64_ADDR16, /* type */ 22089857Sobrien 0, /* rightshift */ 22189857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 22289857Sobrien 16, /* bitsize */ 22389857Sobrien false, /* pc_relative */ 22489857Sobrien 0, /* bitpos */ 22589857Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 22689857Sobrien bfd_elf_generic_reloc, /* special_function */ 22789857Sobrien "R_PPC64_ADDR16", /* name */ 22889857Sobrien false, /* partial_inplace */ 22989857Sobrien 0, /* src_mask */ 23089857Sobrien 0xffff, /* dst_mask */ 23189857Sobrien false), /* pcrel_offset */ 23289857Sobrien 23389857Sobrien /* A 16 bit relocation without overflow. */ 23489857Sobrien HOWTO (R_PPC64_ADDR16_LO, /* type */ 23589857Sobrien 0, /* rightshift */ 23689857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 23789857Sobrien 16, /* bitsize */ 23889857Sobrien false, /* pc_relative */ 23989857Sobrien 0, /* bitpos */ 24089857Sobrien complain_overflow_dont,/* complain_on_overflow */ 24189857Sobrien bfd_elf_generic_reloc, /* special_function */ 24289857Sobrien "R_PPC64_ADDR16_LO", /* name */ 24389857Sobrien false, /* partial_inplace */ 24489857Sobrien 0, /* src_mask */ 24589857Sobrien 0xffff, /* dst_mask */ 24689857Sobrien false), /* pcrel_offset */ 24789857Sobrien 24889857Sobrien /* Bits 16-31 of an address. */ 24989857Sobrien HOWTO (R_PPC64_ADDR16_HI, /* type */ 25089857Sobrien 16, /* rightshift */ 25189857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 25289857Sobrien 16, /* bitsize */ 25389857Sobrien false, /* pc_relative */ 25489857Sobrien 0, /* bitpos */ 25589857Sobrien complain_overflow_dont, /* complain_on_overflow */ 25689857Sobrien bfd_elf_generic_reloc, /* special_function */ 25789857Sobrien "R_PPC64_ADDR16_HI", /* name */ 25889857Sobrien false, /* partial_inplace */ 25989857Sobrien 0, /* src_mask */ 26089857Sobrien 0xffff, /* dst_mask */ 26189857Sobrien false), /* pcrel_offset */ 26289857Sobrien 26389857Sobrien /* Bits 16-31 of an address, plus 1 if the contents of the low 16 26489857Sobrien bits, treated as a signed number, is negative. */ 26589857Sobrien HOWTO (R_PPC64_ADDR16_HA, /* type */ 26689857Sobrien 16, /* rightshift */ 26789857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 26889857Sobrien 16, /* bitsize */ 26989857Sobrien false, /* pc_relative */ 27089857Sobrien 0, /* bitpos */ 27189857Sobrien complain_overflow_dont, /* complain_on_overflow */ 27289857Sobrien ppc64_elf_addr16_ha_reloc, /* special_function */ 27389857Sobrien "R_PPC64_ADDR16_HA", /* name */ 27489857Sobrien false, /* partial_inplace */ 27589857Sobrien 0, /* src_mask */ 27689857Sobrien 0xffff, /* dst_mask */ 27789857Sobrien false), /* pcrel_offset */ 27889857Sobrien 27989857Sobrien /* An absolute 16 bit branch; the lower two bits must be zero. 28089857Sobrien FIXME: we don't check that, we just clear them. */ 28189857Sobrien HOWTO (R_PPC64_ADDR14, /* type */ 28289857Sobrien 0, /* rightshift */ 28389857Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 28489857Sobrien 16, /* bitsize */ 28589857Sobrien false, /* pc_relative */ 28689857Sobrien 0, /* bitpos */ 28789857Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 28889857Sobrien bfd_elf_generic_reloc, /* special_function */ 28989857Sobrien "R_PPC64_ADDR14", /* name */ 29089857Sobrien false, /* partial_inplace */ 29189857Sobrien 0, /* src_mask */ 29289857Sobrien 0xfffc, /* dst_mask */ 29389857Sobrien false), /* pcrel_offset */ 29489857Sobrien 29589857Sobrien /* An absolute 16 bit branch, for which bit 10 should be set to 29689857Sobrien indicate that the branch is expected to be taken. The lower two 29789857Sobrien bits must be zero. */ 29889857Sobrien HOWTO (R_PPC64_ADDR14_BRTAKEN, /* type */ 29989857Sobrien 0, /* rightshift */ 30089857Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 30189857Sobrien 16, /* bitsize */ 30289857Sobrien false, /* pc_relative */ 30389857Sobrien 0, /* bitpos */ 30489857Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 30589857Sobrien bfd_elf_generic_reloc, /* special_function */ 30689857Sobrien "R_PPC64_ADDR14_BRTAKEN",/* name */ 30789857Sobrien false, /* partial_inplace */ 30889857Sobrien 0, /* src_mask */ 30989857Sobrien 0xfffc, /* dst_mask */ 31089857Sobrien false), /* pcrel_offset */ 31189857Sobrien 31289857Sobrien /* An absolute 16 bit branch, for which bit 10 should be set to 31389857Sobrien indicate that the branch is not expected to be taken. The lower 31489857Sobrien two bits must be zero. */ 31589857Sobrien HOWTO (R_PPC64_ADDR14_BRNTAKEN, /* type */ 31689857Sobrien 0, /* rightshift */ 31789857Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 31889857Sobrien 16, /* bitsize */ 31989857Sobrien false, /* pc_relative */ 32089857Sobrien 0, /* bitpos */ 32189857Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 32289857Sobrien bfd_elf_generic_reloc, /* special_function */ 32389857Sobrien "R_PPC64_ADDR14_BRNTAKEN",/* name */ 32489857Sobrien false, /* partial_inplace */ 32589857Sobrien 0, /* src_mask */ 32689857Sobrien 0xfffc, /* dst_mask */ 32789857Sobrien false), /* pcrel_offset */ 32889857Sobrien 32989857Sobrien /* A relative 26 bit branch; the lower two bits must be zero. */ 33089857Sobrien HOWTO (R_PPC64_REL24, /* type */ 33189857Sobrien 0, /* rightshift */ 33289857Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 33389857Sobrien 26, /* bitsize */ 33489857Sobrien true, /* pc_relative */ 33589857Sobrien 0, /* bitpos */ 33689857Sobrien complain_overflow_signed, /* complain_on_overflow */ 33789857Sobrien bfd_elf_generic_reloc, /* special_function */ 33889857Sobrien "R_PPC64_REL24", /* name */ 33989857Sobrien false, /* partial_inplace */ 34089857Sobrien 0, /* src_mask */ 34189857Sobrien 0x3fffffc, /* dst_mask */ 34289857Sobrien true), /* pcrel_offset */ 34389857Sobrien 34489857Sobrien /* A relative 16 bit branch; the lower two bits must be zero. */ 34589857Sobrien HOWTO (R_PPC64_REL14, /* type */ 34689857Sobrien 0, /* rightshift */ 34789857Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 34889857Sobrien 16, /* bitsize */ 34989857Sobrien true, /* pc_relative */ 35089857Sobrien 0, /* bitpos */ 35189857Sobrien complain_overflow_signed, /* complain_on_overflow */ 35289857Sobrien bfd_elf_generic_reloc, /* special_function */ 35389857Sobrien "R_PPC64_REL14", /* name */ 35489857Sobrien false, /* partial_inplace */ 35589857Sobrien 0, /* src_mask */ 35689857Sobrien 0xfffc, /* dst_mask */ 35789857Sobrien true), /* pcrel_offset */ 35889857Sobrien 35989857Sobrien /* A relative 16 bit branch. Bit 10 should be set to indicate that 36089857Sobrien the branch is expected to be taken. The lower two bits must be 36189857Sobrien zero. */ 36289857Sobrien HOWTO (R_PPC64_REL14_BRTAKEN, /* type */ 36389857Sobrien 0, /* rightshift */ 36489857Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 36589857Sobrien 16, /* bitsize */ 36689857Sobrien true, /* pc_relative */ 36789857Sobrien 0, /* bitpos */ 36889857Sobrien complain_overflow_signed, /* complain_on_overflow */ 36989857Sobrien bfd_elf_generic_reloc, /* special_function */ 37089857Sobrien "R_PPC64_REL14_BRTAKEN", /* name */ 37189857Sobrien false, /* partial_inplace */ 37289857Sobrien 0, /* src_mask */ 37389857Sobrien 0xfffc, /* dst_mask */ 37489857Sobrien true), /* pcrel_offset */ 37589857Sobrien 37689857Sobrien /* A relative 16 bit branch. Bit 10 should be set to indicate that 37789857Sobrien the branch is not expected to be taken. The lower two bits must 37889857Sobrien be zero. */ 37989857Sobrien HOWTO (R_PPC64_REL14_BRNTAKEN, /* type */ 38089857Sobrien 0, /* rightshift */ 38189857Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 38289857Sobrien 16, /* bitsize */ 38389857Sobrien true, /* pc_relative */ 38489857Sobrien 0, /* bitpos */ 38589857Sobrien complain_overflow_signed, /* complain_on_overflow */ 38689857Sobrien bfd_elf_generic_reloc, /* special_function */ 38789857Sobrien "R_PPC64_REL14_BRNTAKEN",/* name */ 38889857Sobrien false, /* partial_inplace */ 38989857Sobrien 0, /* src_mask */ 39089857Sobrien 0xfffc, /* dst_mask */ 39189857Sobrien true), /* pcrel_offset */ 39289857Sobrien 39389857Sobrien /* Like R_PPC64_ADDR16, but referring to the GOT table entry for the 39489857Sobrien symbol. */ 39589857Sobrien HOWTO (R_PPC64_GOT16, /* type */ 39689857Sobrien 0, /* rightshift */ 39789857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 39889857Sobrien 16, /* bitsize */ 39989857Sobrien false, /* pc_relative */ 40089857Sobrien 0, /* bitpos */ 40189857Sobrien complain_overflow_signed, /* complain_on_overflow */ 40289857Sobrien bfd_elf_generic_reloc, /* special_function */ 40389857Sobrien "R_PPC64_GOT16", /* name */ 40489857Sobrien false, /* partial_inplace */ 40589857Sobrien 0, /* src_mask */ 40689857Sobrien 0xffff, /* dst_mask */ 40789857Sobrien false), /* pcrel_offset */ 40889857Sobrien 40989857Sobrien /* Like R_PPC64_ADDR16_LO, but referring to the GOT table entry for 41089857Sobrien the symbol. */ 41189857Sobrien HOWTO (R_PPC64_GOT16_LO, /* type */ 41289857Sobrien 0, /* rightshift */ 41389857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 41489857Sobrien 16, /* bitsize */ 41589857Sobrien false, /* pc_relative */ 41689857Sobrien 0, /* bitpos */ 41789857Sobrien complain_overflow_dont, /* complain_on_overflow */ 41889857Sobrien bfd_elf_generic_reloc, /* special_function */ 41989857Sobrien "R_PPC64_GOT16_LO", /* name */ 42089857Sobrien false, /* partial_inplace */ 42189857Sobrien 0, /* src_mask */ 42289857Sobrien 0xffff, /* dst_mask */ 42389857Sobrien false), /* pcrel_offset */ 42489857Sobrien 42589857Sobrien /* Like R_PPC64_ADDR16_HI, but referring to the GOT table entry for 42689857Sobrien the symbol. */ 42789857Sobrien HOWTO (R_PPC64_GOT16_HI, /* type */ 42889857Sobrien 16, /* rightshift */ 42989857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 43089857Sobrien 16, /* bitsize */ 43189857Sobrien false, /* pc_relative */ 43289857Sobrien 0, /* bitpos */ 43389857Sobrien complain_overflow_dont,/* complain_on_overflow */ 43489857Sobrien bfd_elf_generic_reloc, /* special_function */ 43589857Sobrien "R_PPC64_GOT16_HI", /* name */ 43689857Sobrien false, /* partial_inplace */ 43789857Sobrien 0, /* src_mask */ 43889857Sobrien 0xffff, /* dst_mask */ 43989857Sobrien false), /* pcrel_offset */ 44089857Sobrien 44189857Sobrien /* Like R_PPC64_ADDR16_HA, but referring to the GOT table entry for 44289857Sobrien the symbol. */ 44389857Sobrien HOWTO (R_PPC64_GOT16_HA, /* type */ 44489857Sobrien 16, /* rightshift */ 44589857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 44689857Sobrien 16, /* bitsize */ 44789857Sobrien false, /* pc_relative */ 44889857Sobrien 0, /* bitpos */ 44989857Sobrien complain_overflow_dont,/* complain_on_overflow */ 45089857Sobrien ppc64_elf_addr16_ha_reloc, /* special_function */ 45189857Sobrien "R_PPC64_GOT16_HA", /* name */ 45289857Sobrien false, /* partial_inplace */ 45389857Sobrien 0, /* src_mask */ 45489857Sobrien 0xffff, /* dst_mask */ 45589857Sobrien false), /* pcrel_offset */ 45689857Sobrien 45789857Sobrien /* This is used only by the dynamic linker. The symbol should exist 45889857Sobrien both in the object being run and in some shared library. The 45989857Sobrien dynamic linker copies the data addressed by the symbol from the 46089857Sobrien shared library into the object, because the object being 46189857Sobrien run has to have the data at some particular address. */ 46289857Sobrien HOWTO (R_PPC64_COPY, /* type */ 46389857Sobrien 0, /* rightshift */ 46489857Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 46589857Sobrien 32, /* bitsize */ 46689857Sobrien false, /* pc_relative */ 46789857Sobrien 0, /* bitpos */ 46889857Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 46989857Sobrien bfd_elf_generic_reloc, /* special_function */ 47089857Sobrien "R_PPC64_COPY", /* name */ 47189857Sobrien false, /* partial_inplace */ 47289857Sobrien 0, /* src_mask */ 47389857Sobrien 0, /* dst_mask */ 47489857Sobrien false), /* pcrel_offset */ 47589857Sobrien 47689857Sobrien /* Like R_PPC64_ADDR64, but used when setting global offset table 47789857Sobrien entries. */ 47889857Sobrien HOWTO (R_PPC64_GLOB_DAT, /* type */ 47989857Sobrien 0, /* rightshift */ 48089857Sobrien 4, /* size (0=byte, 1=short, 2=long, 4=64 bits) */ 48189857Sobrien 64, /* bitsize */ 48289857Sobrien false, /* pc_relative */ 48389857Sobrien 0, /* bitpos */ 48489857Sobrien complain_overflow_dont, /* complain_on_overflow */ 48589857Sobrien bfd_elf_generic_reloc, /* special_function */ 48689857Sobrien "R_PPC64_GLOB_DAT", /* name */ 48789857Sobrien false, /* partial_inplace */ 48889857Sobrien 0, /* src_mask */ 48989857Sobrien 0xffffffffffffffff, /* dst_mask */ 49089857Sobrien false), /* pcrel_offset */ 49189857Sobrien 49289857Sobrien /* Created by the link editor. Marks a procedure linkage table 49389857Sobrien entry for a symbol. */ 49489857Sobrien HOWTO (R_PPC64_JMP_SLOT, /* type */ 49589857Sobrien 0, /* rightshift */ 49689857Sobrien 0, /* size (0 = byte, 1 = short, 2 = long) */ 49789857Sobrien 0, /* bitsize */ 49889857Sobrien false, /* pc_relative */ 49989857Sobrien 0, /* bitpos */ 50089857Sobrien complain_overflow_dont, /* complain_on_overflow */ 50189857Sobrien bfd_elf_generic_reloc, /* special_function */ 50289857Sobrien "R_PPC64_JMP_SLOT", /* name */ 50389857Sobrien false, /* partial_inplace */ 50489857Sobrien 0, /* src_mask */ 50589857Sobrien 0, /* dst_mask */ 50689857Sobrien false), /* pcrel_offset */ 50789857Sobrien 50889857Sobrien /* Used only by the dynamic linker. When the object is run, this 50989857Sobrien doubleword64 is set to the load address of the object, plus the 51089857Sobrien addend. */ 51189857Sobrien HOWTO (R_PPC64_RELATIVE, /* type */ 51289857Sobrien 0, /* rightshift */ 51389857Sobrien 4, /* size (0=byte, 1=short, 2=long, 4=64 bits) */ 51489857Sobrien 64, /* bitsize */ 51589857Sobrien false, /* pc_relative */ 51689857Sobrien 0, /* bitpos */ 51789857Sobrien complain_overflow_dont, /* complain_on_overflow */ 51889857Sobrien bfd_elf_generic_reloc, /* special_function */ 51989857Sobrien "R_PPC64_RELATIVE", /* name */ 52089857Sobrien false, /* partial_inplace */ 52189857Sobrien 0, /* src_mask */ 52289857Sobrien 0xffffffffffffffff, /* dst_mask */ 52389857Sobrien false), /* pcrel_offset */ 52489857Sobrien 52589857Sobrien /* Like R_PPC64_ADDR32, but may be unaligned. */ 52689857Sobrien HOWTO (R_PPC64_UADDR32, /* type */ 52789857Sobrien 0, /* rightshift */ 52889857Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 52989857Sobrien 32, /* bitsize */ 53089857Sobrien false, /* pc_relative */ 53189857Sobrien 0, /* bitpos */ 53289857Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 53389857Sobrien bfd_elf_generic_reloc, /* special_function */ 53489857Sobrien "R_PPC64_UADDR32", /* name */ 53589857Sobrien false, /* partial_inplace */ 53689857Sobrien 0, /* src_mask */ 53789857Sobrien 0xffffffff, /* dst_mask */ 53889857Sobrien false), /* pcrel_offset */ 53989857Sobrien 54089857Sobrien /* Like R_PPC64_ADDR16, but may be unaligned. */ 54189857Sobrien HOWTO (R_PPC64_UADDR16, /* type */ 54289857Sobrien 0, /* rightshift */ 54389857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 54489857Sobrien 16, /* bitsize */ 54589857Sobrien false, /* pc_relative */ 54689857Sobrien 0, /* bitpos */ 54789857Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 54889857Sobrien bfd_elf_generic_reloc, /* special_function */ 54989857Sobrien "R_PPC64_UADDR16", /* name */ 55089857Sobrien false, /* partial_inplace */ 55189857Sobrien 0, /* src_mask */ 55289857Sobrien 0xffff, /* dst_mask */ 55389857Sobrien false), /* pcrel_offset */ 55489857Sobrien 55589857Sobrien /* 32-bit PC relative. */ 55689857Sobrien HOWTO (R_PPC64_REL32, /* type */ 55789857Sobrien 0, /* rightshift */ 55889857Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 55989857Sobrien 32, /* bitsize */ 56089857Sobrien true, /* pc_relative */ 56189857Sobrien 0, /* bitpos */ 56289857Sobrien /* FIXME: Verify. Was complain_overflow_bitfield. */ 56389857Sobrien complain_overflow_signed, /* complain_on_overflow */ 56489857Sobrien bfd_elf_generic_reloc, /* special_function */ 56589857Sobrien "R_PPC64_REL32", /* name */ 56689857Sobrien false, /* partial_inplace */ 56789857Sobrien 0, /* src_mask */ 56889857Sobrien 0xffffffff, /* dst_mask */ 56989857Sobrien true), /* pcrel_offset */ 57089857Sobrien 57189857Sobrien /* 32-bit relocation to the symbol's procedure linkage table. */ 57289857Sobrien HOWTO (R_PPC64_PLT32, /* type */ 57389857Sobrien 0, /* rightshift */ 57489857Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 57589857Sobrien 32, /* bitsize */ 57689857Sobrien false, /* pc_relative */ 57789857Sobrien 0, /* bitpos */ 57889857Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 57989857Sobrien bfd_elf_generic_reloc, /* special_function */ 58089857Sobrien "R_PPC64_PLT32", /* name */ 58189857Sobrien false, /* partial_inplace */ 58289857Sobrien 0, /* src_mask */ 58389857Sobrien 0, /* dst_mask */ 58489857Sobrien false), /* pcrel_offset */ 58589857Sobrien 58689857Sobrien /* 32-bit PC relative relocation to the symbol's procedure linkage table. 58789857Sobrien FIXME: R_PPC64_PLTREL32 not supported. */ 58889857Sobrien HOWTO (R_PPC64_PLTREL32, /* type */ 58989857Sobrien 0, /* rightshift */ 59089857Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 59189857Sobrien 32, /* bitsize */ 59289857Sobrien true, /* pc_relative */ 59389857Sobrien 0, /* bitpos */ 59489857Sobrien complain_overflow_signed, /* complain_on_overflow */ 59589857Sobrien bfd_elf_generic_reloc, /* special_function */ 59689857Sobrien "R_PPC64_PLTREL32", /* name */ 59789857Sobrien false, /* partial_inplace */ 59889857Sobrien 0, /* src_mask */ 59989857Sobrien 0, /* dst_mask */ 60089857Sobrien true), /* pcrel_offset */ 60189857Sobrien 60289857Sobrien /* Like R_PPC64_ADDR16_LO, but referring to the PLT table entry for 60389857Sobrien the symbol. */ 60489857Sobrien HOWTO (R_PPC64_PLT16_LO, /* type */ 60589857Sobrien 0, /* rightshift */ 60689857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 60789857Sobrien 16, /* bitsize */ 60889857Sobrien false, /* pc_relative */ 60989857Sobrien 0, /* bitpos */ 61089857Sobrien complain_overflow_dont, /* complain_on_overflow */ 61189857Sobrien bfd_elf_generic_reloc, /* special_function */ 61289857Sobrien "R_PPC64_PLT16_LO", /* name */ 61389857Sobrien false, /* partial_inplace */ 61489857Sobrien 0, /* src_mask */ 61589857Sobrien 0xffff, /* dst_mask */ 61689857Sobrien false), /* pcrel_offset */ 61789857Sobrien 61889857Sobrien /* Like R_PPC64_ADDR16_HI, but referring to the PLT table entry for 61989857Sobrien the symbol. */ 62089857Sobrien HOWTO (R_PPC64_PLT16_HI, /* type */ 62189857Sobrien 16, /* rightshift */ 62289857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 62389857Sobrien 16, /* bitsize */ 62489857Sobrien false, /* pc_relative */ 62589857Sobrien 0, /* bitpos */ 62689857Sobrien complain_overflow_dont, /* complain_on_overflow */ 62789857Sobrien bfd_elf_generic_reloc, /* special_function */ 62889857Sobrien "R_PPC64_PLT16_HI", /* name */ 62989857Sobrien false, /* partial_inplace */ 63089857Sobrien 0, /* src_mask */ 63189857Sobrien 0xffff, /* dst_mask */ 63289857Sobrien false), /* pcrel_offset */ 63389857Sobrien 63489857Sobrien /* Like R_PPC64_ADDR16_HA, but referring to the PLT table entry for 63589857Sobrien the symbol. */ 63689857Sobrien HOWTO (R_PPC64_PLT16_HA, /* type */ 63789857Sobrien 16, /* rightshift */ 63889857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 63989857Sobrien 16, /* bitsize */ 64089857Sobrien false, /* pc_relative */ 64189857Sobrien 0, /* bitpos */ 64289857Sobrien complain_overflow_dont, /* complain_on_overflow */ 64389857Sobrien ppc64_elf_addr16_ha_reloc, /* special_function */ 64489857Sobrien "R_PPC64_PLT16_HA", /* name */ 64589857Sobrien false, /* partial_inplace */ 64689857Sobrien 0, /* src_mask */ 64789857Sobrien 0xffff, /* dst_mask */ 64889857Sobrien false), /* pcrel_offset */ 64989857Sobrien 65089857Sobrien /* 32-bit section relative relocation. */ 65189857Sobrien /* FIXME: Verify R_PPC64_SECTOFF. Seems strange with size=2 and 65289857Sobrien dst_mask=0. */ 65389857Sobrien HOWTO (R_PPC64_SECTOFF, /* type */ 65489857Sobrien 0, /* rightshift */ 65589857Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 65689857Sobrien 32, /* bitsize */ 65789857Sobrien true, /* pc_relative */ 65889857Sobrien 0, /* bitpos */ 65989857Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 66089857Sobrien bfd_elf_generic_reloc, /* special_function */ 66189857Sobrien "R_PPC64_SECTOFF", /* name */ 66289857Sobrien false, /* partial_inplace */ 66389857Sobrien 0, /* src_mask */ 66489857Sobrien 0, /* dst_mask */ 66589857Sobrien true), /* pcrel_offset */ 66689857Sobrien 66789857Sobrien /* 16-bit lower half section relative relocation. */ 66889857Sobrien HOWTO (R_PPC64_SECTOFF_LO, /* type */ 66989857Sobrien 0, /* rightshift */ 67089857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 67189857Sobrien 16, /* bitsize */ 67289857Sobrien false, /* pc_relative */ 67389857Sobrien 0, /* bitpos */ 67489857Sobrien complain_overflow_dont, /* complain_on_overflow */ 67589857Sobrien bfd_elf_generic_reloc, /* special_function */ 67689857Sobrien "R_PPC64_SECTOFF_LO", /* name */ 67789857Sobrien false, /* partial_inplace */ 67889857Sobrien 0, /* src_mask */ 67989857Sobrien 0xffff, /* dst_mask */ 68089857Sobrien false), /* pcrel_offset */ 68189857Sobrien 68289857Sobrien /* 16-bit upper half section relative relocation. */ 68389857Sobrien HOWTO (R_PPC64_SECTOFF_HI, /* type */ 68489857Sobrien 16, /* rightshift */ 68589857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 68689857Sobrien 16, /* bitsize */ 68789857Sobrien false, /* pc_relative */ 68889857Sobrien 0, /* bitpos */ 68989857Sobrien complain_overflow_dont, /* complain_on_overflow */ 69089857Sobrien bfd_elf_generic_reloc, /* special_function */ 69189857Sobrien "R_PPC64_SECTOFF_HI", /* name */ 69289857Sobrien false, /* partial_inplace */ 69389857Sobrien 0, /* src_mask */ 69489857Sobrien 0xffff, /* dst_mask */ 69589857Sobrien false), /* pcrel_offset */ 69689857Sobrien 69789857Sobrien /* 16-bit upper half adjusted section relative relocation. */ 69889857Sobrien HOWTO (R_PPC64_SECTOFF_HA, /* type */ 69989857Sobrien 16, /* rightshift */ 70089857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 70189857Sobrien 16, /* bitsize */ 70289857Sobrien false, /* pc_relative */ 70389857Sobrien 0, /* bitpos */ 70489857Sobrien complain_overflow_dont, /* complain_on_overflow */ 70589857Sobrien ppc64_elf_addr16_ha_reloc, /* special_function */ 70689857Sobrien "R_PPC64_SECTOFF_HA", /* name */ 70789857Sobrien false, /* partial_inplace */ 70889857Sobrien 0, /* src_mask */ 70989857Sobrien 0xffff, /* dst_mask */ 71089857Sobrien false), /* pcrel_offset */ 71189857Sobrien 71289857Sobrien /* Like R_PPC64_REL24 without touching the two least significant 71389857Sobrien bits. */ 71489857Sobrien /* FIXME: Verify R_PPC64_ADDR30. */ 71589857Sobrien HOWTO (R_PPC64_ADDR30, /* type */ 71689857Sobrien 2, /* rightshift */ 71789857Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 71889857Sobrien 30, /* bitsize */ 71989857Sobrien true, /* pc_relative */ 72089857Sobrien 0, /* bitpos */ 72189857Sobrien complain_overflow_dont, /* complain_on_overflow */ 72289857Sobrien bfd_elf_generic_reloc, /* special_function */ 72389857Sobrien "R_PPC64_ADDR30", /* name */ 72489857Sobrien false, /* partial_inplace */ 72589857Sobrien 0, /* src_mask */ 72689857Sobrien 0xfffffffc, /* dst_mask */ 72789857Sobrien true), /* pcrel_offset */ 72889857Sobrien 72989857Sobrien /* Relocs in the 64-bit PowerPC ELF ABI, not in the 32-bit ABI. */ 73089857Sobrien 73189857Sobrien /* A standard 64-bit relocation. */ 73289857Sobrien HOWTO (R_PPC64_ADDR64, /* type */ 73389857Sobrien 0, /* rightshift */ 73489857Sobrien 4, /* size (0=byte, 1=short, 2=long, 4=64 bits) */ 73589857Sobrien 64, /* bitsize */ 73689857Sobrien false, /* pc_relative */ 73789857Sobrien 0, /* bitpos */ 73889857Sobrien complain_overflow_dont, /* complain_on_overflow */ 73989857Sobrien bfd_elf_generic_reloc, /* special_function */ 74089857Sobrien "R_PPC64_ADDR64", /* name */ 74189857Sobrien false, /* partial_inplace */ 74289857Sobrien 0, /* src_mask */ 74389857Sobrien 0xffffffffffffffff, /* dst_mask */ 74489857Sobrien false), /* pcrel_offset */ 74589857Sobrien 74689857Sobrien /* The bits 32-47 of an address. */ 74789857Sobrien HOWTO (R_PPC64_ADDR16_HIGHER, /* type */ 74889857Sobrien 32, /* rightshift */ 74989857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 75089857Sobrien 16, /* bitsize */ 75189857Sobrien false, /* pc_relative */ 75289857Sobrien 0, /* bitpos */ 75389857Sobrien complain_overflow_dont, /* complain_on_overflow */ 75489857Sobrien bfd_elf_generic_reloc, /* special_function */ 75589857Sobrien "R_PPC64_ADDR16_HIGHER", /* name */ 75689857Sobrien false, /* partial_inplace */ 75789857Sobrien 0, /* src_mask */ 75889857Sobrien 0xffff, /* dst_mask */ 75989857Sobrien false), /* pcrel_offset */ 76089857Sobrien 76189857Sobrien /* The bits 32-47 of an address, plus 1 if the contents of the low 76289857Sobrien 16 bits, treated as a signed number, is negative. */ 76389857Sobrien HOWTO (R_PPC64_ADDR16_HIGHERA, /* type */ 76489857Sobrien 32, /* rightshift */ 76589857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 76689857Sobrien 16, /* bitsize */ 76789857Sobrien false, /* pc_relative */ 76889857Sobrien 0, /* bitpos */ 76989857Sobrien complain_overflow_dont, /* complain_on_overflow */ 77089857Sobrien ppc64_elf_addr16_ha_reloc, /* special_function */ 77189857Sobrien "R_PPC64_ADDR16_HIGHERA", /* name */ 77289857Sobrien false, /* partial_inplace */ 77389857Sobrien 0, /* src_mask */ 77489857Sobrien 0xffff, /* dst_mask */ 77589857Sobrien false), /* pcrel_offset */ 77689857Sobrien 77789857Sobrien /* The bits 48-63 of an address. */ 77889857Sobrien HOWTO (R_PPC64_ADDR16_HIGHEST,/* type */ 77989857Sobrien 48, /* rightshift */ 78089857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 78189857Sobrien 16, /* bitsize */ 78289857Sobrien false, /* pc_relative */ 78389857Sobrien 0, /* bitpos */ 78489857Sobrien complain_overflow_dont, /* complain_on_overflow */ 78589857Sobrien bfd_elf_generic_reloc, /* special_function */ 78689857Sobrien "R_PPC64_ADDR16_HIGHEST", /* name */ 78789857Sobrien false, /* partial_inplace */ 78889857Sobrien 0, /* src_mask */ 78989857Sobrien 0xffff, /* dst_mask */ 79089857Sobrien false), /* pcrel_offset */ 79189857Sobrien 79289857Sobrien /* The bits 48-63 of an address, plus 1 if the contents of the low 79389857Sobrien 16 bits, treated as a signed number, is negative. */ 79489857Sobrien HOWTO (R_PPC64_ADDR16_HIGHESTA,/* type */ 79589857Sobrien 48, /* rightshift */ 79689857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 79789857Sobrien 16, /* bitsize */ 79889857Sobrien false, /* pc_relative */ 79989857Sobrien 0, /* bitpos */ 80089857Sobrien complain_overflow_dont, /* complain_on_overflow */ 80189857Sobrien ppc64_elf_addr16_ha_reloc, /* special_function */ 80289857Sobrien "R_PPC64_ADDR16_HIGHESTA", /* name */ 80389857Sobrien false, /* partial_inplace */ 80489857Sobrien 0, /* src_mask */ 80589857Sobrien 0xffff, /* dst_mask */ 80689857Sobrien false), /* pcrel_offset */ 80789857Sobrien 80889857Sobrien /* Like ADDR64, but may be unaligned. */ 80989857Sobrien HOWTO (R_PPC64_UADDR64, /* type */ 81089857Sobrien 0, /* rightshift */ 81189857Sobrien 4, /* size (0=byte, 1=short, 2=long, 4=64 bits) */ 81289857Sobrien 64, /* bitsize */ 81389857Sobrien false, /* pc_relative */ 81489857Sobrien 0, /* bitpos */ 81589857Sobrien complain_overflow_dont, /* complain_on_overflow */ 81689857Sobrien bfd_elf_generic_reloc, /* special_function */ 81789857Sobrien "R_PPC64_UADDR64", /* name */ 81889857Sobrien false, /* partial_inplace */ 81989857Sobrien 0, /* src_mask */ 82089857Sobrien 0xffffffffffffffff, /* dst_mask */ 82189857Sobrien false), /* pcrel_offset */ 82289857Sobrien 82389857Sobrien /* 64-bit relative relocation. */ 82489857Sobrien HOWTO (R_PPC64_REL64, /* type */ 82589857Sobrien 0, /* rightshift */ 82689857Sobrien 4, /* size (0=byte, 1=short, 2=long, 4=64 bits) */ 82789857Sobrien 64, /* bitsize */ 82889857Sobrien true, /* pc_relative */ 82989857Sobrien 0, /* bitpos */ 83089857Sobrien complain_overflow_dont, /* complain_on_overflow */ 83189857Sobrien bfd_elf_generic_reloc, /* special_function */ 83289857Sobrien "R_PPC64_REL64", /* name */ 83389857Sobrien false, /* partial_inplace */ 83489857Sobrien 0, /* src_mask */ 83589857Sobrien 0xffffffffffffffff, /* dst_mask */ 83689857Sobrien true), /* pcrel_offset */ 83789857Sobrien 83889857Sobrien /* 64-bit relocation to the symbol's procedure linkage table. */ 83989857Sobrien HOWTO (R_PPC64_PLT64, /* type */ 84089857Sobrien 0, /* rightshift */ 84189857Sobrien 4, /* size (0=byte, 1=short, 2=long, 4=64 bits) */ 84289857Sobrien 64, /* bitsize */ 84389857Sobrien false, /* pc_relative */ 84489857Sobrien 0, /* bitpos */ 84589857Sobrien complain_overflow_dont, /* complain_on_overflow */ 84689857Sobrien bfd_elf_generic_reloc, /* special_function */ 84789857Sobrien "R_PPC64_PLT64", /* name */ 84889857Sobrien false, /* partial_inplace */ 84989857Sobrien 0, /* src_mask */ 85089857Sobrien 0, /* dst_mask */ 85189857Sobrien false), /* pcrel_offset */ 85289857Sobrien 85389857Sobrien /* 64-bit PC relative relocation to the symbol's procedure linkage 85489857Sobrien table. */ 85589857Sobrien /* FIXME: R_PPC64_PLTREL64 not supported. */ 85689857Sobrien HOWTO (R_PPC64_PLTREL64, /* type */ 85789857Sobrien 0, /* rightshift */ 85889857Sobrien 4, /* size (0=byte, 1=short, 2=long, 4=64 bits) */ 85989857Sobrien 64, /* bitsize */ 86089857Sobrien true, /* pc_relative */ 86189857Sobrien 0, /* bitpos */ 86289857Sobrien complain_overflow_dont, /* complain_on_overflow */ 86389857Sobrien bfd_elf_generic_reloc, /* special_function */ 86489857Sobrien "R_PPC64_PLTREL64", /* name */ 86589857Sobrien false, /* partial_inplace */ 86689857Sobrien 0, /* src_mask */ 86789857Sobrien 0, /* dst_mask */ 86889857Sobrien true), /* pcrel_offset */ 86989857Sobrien 87089857Sobrien /* 16 bit TOC-relative relocation. */ 87189857Sobrien 87289857Sobrien /* R_PPC64_TOC16 47 half16* S + A - .TOC. */ 87389857Sobrien HOWTO (R_PPC64_TOC16, /* type */ 87489857Sobrien 0, /* rightshift */ 87589857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 87689857Sobrien 16, /* bitsize */ 87789857Sobrien false, /* pc_relative */ 87889857Sobrien 0, /* bitpos */ 87989857Sobrien complain_overflow_signed, /* complain_on_overflow */ 88089857Sobrien bfd_elf_generic_reloc, /* special_function */ 88189857Sobrien "R_PPC64_TOC16", /* name */ 88289857Sobrien false, /* partial_inplace */ 88389857Sobrien 0, /* src_mask */ 88489857Sobrien 0xffff, /* dst_mask */ 88589857Sobrien false), /* pcrel_offset */ 88689857Sobrien 88789857Sobrien /* 16 bit TOC-relative relocation without overflow. */ 88889857Sobrien 88989857Sobrien /* R_PPC64_TOC16_LO 48 half16 #lo (S + A - .TOC.) */ 89089857Sobrien HOWTO (R_PPC64_TOC16_LO, /* type */ 89189857Sobrien 0, /* rightshift */ 89289857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 89389857Sobrien 16, /* bitsize */ 89489857Sobrien false, /* pc_relative */ 89589857Sobrien 0, /* bitpos */ 89689857Sobrien complain_overflow_dont, /* complain_on_overflow */ 89789857Sobrien bfd_elf_generic_reloc, /* special_function */ 89889857Sobrien "R_PPC64_TOC16_LO", /* name */ 89989857Sobrien false, /* partial_inplace */ 90089857Sobrien 0, /* src_mask */ 90189857Sobrien 0xffff, /* dst_mask */ 90289857Sobrien false), /* pcrel_offset */ 90389857Sobrien 90489857Sobrien /* 16 bit TOC-relative relocation, high 16 bits. */ 90589857Sobrien 90689857Sobrien /* R_PPC64_TOC16_HI 49 half16 #hi (S + A - .TOC.) */ 90789857Sobrien HOWTO (R_PPC64_TOC16_HI, /* type */ 90889857Sobrien 16, /* rightshift */ 90989857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 91089857Sobrien 16, /* bitsize */ 91189857Sobrien false, /* pc_relative */ 91289857Sobrien 0, /* bitpos */ 91389857Sobrien complain_overflow_dont, /* complain_on_overflow */ 91489857Sobrien bfd_elf_generic_reloc, /* special_function */ 91589857Sobrien "R_PPC64_TOC16_HI", /* name */ 91689857Sobrien false, /* partial_inplace */ 91789857Sobrien 0, /* src_mask */ 91889857Sobrien 0xffff, /* dst_mask */ 91989857Sobrien false), /* pcrel_offset */ 92089857Sobrien 92189857Sobrien /* 16 bit TOC-relative relocation, high 16 bits, plus 1 if the 92289857Sobrien contents of the low 16 bits, treated as a signed number, is 92389857Sobrien negative. */ 92489857Sobrien 92589857Sobrien /* R_PPC64_TOC16_HA 50 half16 #ha (S + A - .TOC.) */ 92689857Sobrien HOWTO (R_PPC64_TOC16_HA, /* type */ 92789857Sobrien 16, /* rightshift */ 92889857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 92989857Sobrien 16, /* bitsize */ 93089857Sobrien false, /* pc_relative */ 93189857Sobrien 0, /* bitpos */ 93289857Sobrien complain_overflow_dont, /* complain_on_overflow */ 93389857Sobrien ppc64_elf_addr16_ha_reloc, /* special_function */ 93489857Sobrien "R_PPC64_TOC16_HA", /* name */ 93589857Sobrien false, /* partial_inplace */ 93689857Sobrien 0, /* src_mask */ 93789857Sobrien 0xffff, /* dst_mask */ 93889857Sobrien false), /* pcrel_offset */ 93989857Sobrien 94089857Sobrien /* 64-bit relocation; insert value of TOC base (.TOC.). */ 94189857Sobrien 94289857Sobrien /* R_PPC64_TOC 51 doubleword64 .TOC. */ 94389857Sobrien HOWTO (R_PPC64_TOC, /* type */ 94489857Sobrien 0, /* rightshift */ 94589857Sobrien 4, /* size (0=byte, 1=short, 2=long, 4=64 bits) */ 94689857Sobrien 64, /* bitsize */ 94789857Sobrien false, /* pc_relative */ 94889857Sobrien 0, /* bitpos */ 94989857Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 95089857Sobrien bfd_elf_generic_reloc, /* special_function */ 95189857Sobrien "R_PPC64_TOC", /* name */ 95289857Sobrien false, /* partial_inplace */ 95389857Sobrien 0, /* src_mask */ 95489857Sobrien 0xffffffffffffffff, /* dst_mask */ 95589857Sobrien false), /* pcrel_offset */ 95689857Sobrien 95789857Sobrien /* Like R_PPC64_GOT16, but also informs the link editor that the 95889857Sobrien value to relocate may (!) refer to a PLT entry which the link 95989857Sobrien editor (a) may replace with the symbol value. If the link editor 96089857Sobrien is unable to fully resolve the symbol, it may (b) create a PLT 96189857Sobrien entry and store the address to the new PLT entry in the GOT. 96289857Sobrien This permits lazy resolution of function symbols at run time. 96389857Sobrien The link editor may also skip all of this and just (c) emit a 96489857Sobrien R_PPC64_GLOB_DAT to tie the symbol to the GOT entry. */ 96589857Sobrien /* FIXME: R_PPC64_PLTGOT16 not implemented. */ 96689857Sobrien HOWTO (R_PPC64_PLTGOT16, /* type */ 96789857Sobrien 0, /* rightshift */ 96889857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 96989857Sobrien 16, /* bitsize */ 97089857Sobrien false, /* pc_relative */ 97189857Sobrien 0, /* bitpos */ 97289857Sobrien complain_overflow_signed, /* complain_on_overflow */ 97389857Sobrien bfd_elf_generic_reloc, /* special_function */ 97489857Sobrien "R_PPC64_PLTGOT16", /* name */ 97589857Sobrien false, /* partial_inplace */ 97689857Sobrien 0, /* src_mask */ 97789857Sobrien 0xffff, /* dst_mask */ 97889857Sobrien false), /* pcrel_offset */ 97989857Sobrien 98089857Sobrien /* Like R_PPC64_PLTGOT16, but without overflow. */ 98189857Sobrien /* FIXME: R_PPC64_PLTGOT16_LO not implemented. */ 98289857Sobrien HOWTO (R_PPC64_PLTGOT16_LO, /* type */ 98389857Sobrien 0, /* rightshift */ 98489857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 98589857Sobrien 16, /* bitsize */ 98689857Sobrien false, /* pc_relative */ 98789857Sobrien 0, /* bitpos */ 98889857Sobrien complain_overflow_dont, /* complain_on_overflow */ 98989857Sobrien bfd_elf_generic_reloc, /* special_function */ 99089857Sobrien "R_PPC64_PLTGOT16_LO", /* name */ 99189857Sobrien false, /* partial_inplace */ 99289857Sobrien 0, /* src_mask */ 99389857Sobrien 0xffff, /* dst_mask */ 99489857Sobrien false), /* pcrel_offset */ 99589857Sobrien 99689857Sobrien /* Like R_PPC64_PLT_GOT16, but using bits 16-31 of the address. */ 99789857Sobrien /* FIXME: R_PPC64_PLTGOT16_HI not implemented. */ 99889857Sobrien HOWTO (R_PPC64_PLTGOT16_HI, /* type */ 99989857Sobrien 16, /* rightshift */ 100089857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 100189857Sobrien 16, /* bitsize */ 100289857Sobrien false, /* pc_relative */ 100389857Sobrien 0, /* bitpos */ 100489857Sobrien complain_overflow_dont, /* complain_on_overflow */ 100589857Sobrien bfd_elf_generic_reloc, /* special_function */ 100689857Sobrien "R_PPC64_PLTGOT16_HI", /* name */ 100789857Sobrien false, /* partial_inplace */ 100889857Sobrien 0, /* src_mask */ 100989857Sobrien 0xffff, /* dst_mask */ 101089857Sobrien false), /* pcrel_offset */ 101189857Sobrien 101289857Sobrien /* Like R_PPC64_PLT_GOT16, but using bits 16-31 of the address, plus 101389857Sobrien 1 if the contents of the low 16 bits, treated as a signed number, 101489857Sobrien is negative. */ 101589857Sobrien /* FIXME: R_PPC64_PLTGOT16_HA not implemented. */ 101689857Sobrien HOWTO (R_PPC64_PLTGOT16_HA, /* type */ 101789857Sobrien 16, /* rightshift */ 101889857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 101989857Sobrien 16, /* bitsize */ 102089857Sobrien false, /* pc_relative */ 102189857Sobrien 0, /* bitpos */ 102289857Sobrien complain_overflow_dont,/* complain_on_overflow */ 102389857Sobrien ppc64_elf_addr16_ha_reloc, /* special_function */ 102489857Sobrien "R_PPC64_PLTGOT16_HA", /* name */ 102589857Sobrien false, /* partial_inplace */ 102689857Sobrien 0, /* src_mask */ 102789857Sobrien 0xffff, /* dst_mask */ 102889857Sobrien false), /* pcrel_offset */ 102989857Sobrien 103089857Sobrien /* Like R_PPC64_ADDR16, but for instructions with a DS field. */ 103189857Sobrien HOWTO (R_PPC64_ADDR16_DS, /* type */ 103289857Sobrien 0, /* rightshift */ 103389857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 103489857Sobrien 16, /* bitsize */ 103589857Sobrien false, /* pc_relative */ 103689857Sobrien 0, /* bitpos */ 103789857Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 103889857Sobrien bfd_elf_generic_reloc, /* special_function */ 103989857Sobrien "R_PPC64_ADDR16_DS", /* name */ 104089857Sobrien false, /* partial_inplace */ 104189857Sobrien 0, /* src_mask */ 104289857Sobrien 0xfffc, /* dst_mask */ 104389857Sobrien false), /* pcrel_offset */ 104489857Sobrien 104589857Sobrien /* Like R_PPC64_ADDR16_LO, but for instructions with a DS field. */ 104689857Sobrien HOWTO (R_PPC64_ADDR16_LO_DS, /* type */ 104789857Sobrien 0, /* rightshift */ 104889857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 104989857Sobrien 16, /* bitsize */ 105089857Sobrien false, /* pc_relative */ 105189857Sobrien 0, /* bitpos */ 105289857Sobrien complain_overflow_dont,/* complain_on_overflow */ 105389857Sobrien bfd_elf_generic_reloc, /* special_function */ 105489857Sobrien "R_PPC64_ADDR16_LO_DS",/* name */ 105589857Sobrien false, /* partial_inplace */ 105689857Sobrien 0, /* src_mask */ 105789857Sobrien 0xfffc, /* dst_mask */ 105889857Sobrien false), /* pcrel_offset */ 105989857Sobrien 106089857Sobrien /* Like R_PPC64_GOT16, but for instructions with a DS field. */ 106189857Sobrien HOWTO (R_PPC64_GOT16_DS, /* type */ 106289857Sobrien 0, /* rightshift */ 106389857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 106489857Sobrien 16, /* bitsize */ 106589857Sobrien false, /* pc_relative */ 106689857Sobrien 0, /* bitpos */ 106789857Sobrien complain_overflow_signed, /* complain_on_overflow */ 106889857Sobrien bfd_elf_generic_reloc, /* special_function */ 106989857Sobrien "R_PPC64_GOT16_DS", /* name */ 107089857Sobrien false, /* partial_inplace */ 107189857Sobrien 0, /* src_mask */ 107289857Sobrien 0xfffc, /* dst_mask */ 107389857Sobrien false), /* pcrel_offset */ 107489857Sobrien 107589857Sobrien /* Like R_PPC64_GOT16_LO, but for instructions with a DS field. */ 107689857Sobrien HOWTO (R_PPC64_GOT16_LO_DS, /* type */ 107789857Sobrien 0, /* rightshift */ 107889857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 107989857Sobrien 16, /* bitsize */ 108089857Sobrien false, /* pc_relative */ 108189857Sobrien 0, /* bitpos */ 108289857Sobrien complain_overflow_dont, /* complain_on_overflow */ 108389857Sobrien bfd_elf_generic_reloc, /* special_function */ 108489857Sobrien "R_PPC64_GOT16_LO_DS", /* name */ 108589857Sobrien false, /* partial_inplace */ 108689857Sobrien 0, /* src_mask */ 108789857Sobrien 0xfffc, /* dst_mask */ 108889857Sobrien false), /* pcrel_offset */ 108989857Sobrien 109089857Sobrien /* Like R_PPC64_PLT16_LO, but for instructions with a DS field. */ 109189857Sobrien HOWTO (R_PPC64_PLT16_LO_DS, /* type */ 109289857Sobrien 0, /* rightshift */ 109389857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 109489857Sobrien 16, /* bitsize */ 109589857Sobrien false, /* pc_relative */ 109689857Sobrien 0, /* bitpos */ 109789857Sobrien complain_overflow_dont, /* complain_on_overflow */ 109889857Sobrien bfd_elf_generic_reloc, /* special_function */ 109989857Sobrien "R_PPC64_PLT16_LO_DS", /* name */ 110089857Sobrien false, /* partial_inplace */ 110189857Sobrien 0, /* src_mask */ 110289857Sobrien 0xfffc, /* dst_mask */ 110389857Sobrien false), /* pcrel_offset */ 110489857Sobrien 110589857Sobrien /* Like R_PPC64_SECTOFF, but for instructions with a DS field. */ 110689857Sobrien /* FIXME: Verify R_PPC64_SECTOFF. Seems strange with size=2 and 110789857Sobrien dst_mask=0. */ 110889857Sobrien HOWTO (R_PPC64_SECTOFF_DS, /* type */ 110989857Sobrien 0, /* rightshift */ 111089857Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 111189857Sobrien 32, /* bitsize */ 111289857Sobrien true, /* pc_relative */ 111389857Sobrien 0, /* bitpos */ 111489857Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 111589857Sobrien bfd_elf_generic_reloc, /* special_function */ 111689857Sobrien "R_PPC64_SECTOFF_DS", /* name */ 111789857Sobrien false, /* partial_inplace */ 111889857Sobrien 0, /* src_mask */ 111989857Sobrien 0, /* dst_mask */ 112089857Sobrien true), /* pcrel_offset */ 112189857Sobrien 112289857Sobrien /* Like R_PPC64_SECTOFF_LO, but for instructions with a DS field. */ 112389857Sobrien HOWTO (R_PPC64_SECTOFF_LO_DS, /* type */ 112489857Sobrien 0, /* rightshift */ 112589857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 112689857Sobrien 16, /* bitsize */ 112789857Sobrien false, /* pc_relative */ 112889857Sobrien 0, /* bitpos */ 112989857Sobrien complain_overflow_dont, /* complain_on_overflow */ 113089857Sobrien bfd_elf_generic_reloc, /* special_function */ 113189857Sobrien "R_PPC64_SECTOFF_LO_DS",/* name */ 113289857Sobrien false, /* partial_inplace */ 113389857Sobrien 0, /* src_mask */ 113489857Sobrien 0xfffc, /* dst_mask */ 113589857Sobrien false), /* pcrel_offset */ 113689857Sobrien 113789857Sobrien /* Like R_PPC64_TOC16, but for instructions with a DS field. */ 113889857Sobrien HOWTO (R_PPC64_TOC16_DS, /* type */ 113989857Sobrien 0, /* rightshift */ 114089857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 114189857Sobrien 16, /* bitsize */ 114289857Sobrien false, /* pc_relative */ 114389857Sobrien 0, /* bitpos */ 114489857Sobrien complain_overflow_signed, /* complain_on_overflow */ 114589857Sobrien bfd_elf_generic_reloc, /* special_function */ 114689857Sobrien "R_PPC64_TOC16_DS", /* name */ 114789857Sobrien false, /* partial_inplace */ 114889857Sobrien 0, /* src_mask */ 114989857Sobrien 0xfffc, /* dst_mask */ 115089857Sobrien false), /* pcrel_offset */ 115189857Sobrien 115289857Sobrien /* Like R_PPC64_TOC16_LO, but for instructions with a DS field. */ 115389857Sobrien HOWTO (R_PPC64_TOC16_LO_DS, /* type */ 115489857Sobrien 0, /* rightshift */ 115589857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 115689857Sobrien 16, /* bitsize */ 115789857Sobrien false, /* pc_relative */ 115889857Sobrien 0, /* bitpos */ 115989857Sobrien complain_overflow_dont, /* complain_on_overflow */ 116089857Sobrien bfd_elf_generic_reloc, /* special_function */ 116189857Sobrien "R_PPC64_TOC16_LO_DS", /* name */ 116289857Sobrien false, /* partial_inplace */ 116389857Sobrien 0, /* src_mask */ 116489857Sobrien 0xfffc, /* dst_mask */ 116589857Sobrien false), /* pcrel_offset */ 116689857Sobrien 116789857Sobrien /* Like R_PPC64_PLTGOT16, but for instructions with a DS field. */ 116889857Sobrien /* FIXME: R_PPC64_PLTGOT16_DS not implemented. */ 116989857Sobrien HOWTO (R_PPC64_PLTGOT16_DS, /* type */ 117089857Sobrien 0, /* rightshift */ 117189857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 117289857Sobrien 16, /* bitsize */ 117389857Sobrien false, /* pc_relative */ 117489857Sobrien 0, /* bitpos */ 117589857Sobrien complain_overflow_signed, /* complain_on_overflow */ 117689857Sobrien bfd_elf_generic_reloc, /* special_function */ 117789857Sobrien "R_PPC64_PLTGOT16_DS", /* name */ 117889857Sobrien false, /* partial_inplace */ 117989857Sobrien 0, /* src_mask */ 118089857Sobrien 0xfffc, /* dst_mask */ 118189857Sobrien false), /* pcrel_offset */ 118289857Sobrien 118389857Sobrien /* Like R_PPC64_PLTGOT16_LO, but for instructions with a DS field. */ 118489857Sobrien /* FIXME: R_PPC64_PLTGOT16_LO not implemented. */ 118589857Sobrien HOWTO (R_PPC64_PLTGOT16_LO_DS,/* type */ 118689857Sobrien 0, /* rightshift */ 118789857Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 118889857Sobrien 16, /* bitsize */ 118989857Sobrien false, /* pc_relative */ 119089857Sobrien 0, /* bitpos */ 119189857Sobrien complain_overflow_dont, /* complain_on_overflow */ 119289857Sobrien bfd_elf_generic_reloc, /* special_function */ 119389857Sobrien "R_PPC64_PLTGOT16_LO_DS",/* name */ 119489857Sobrien false, /* partial_inplace */ 119589857Sobrien 0, /* src_mask */ 119689857Sobrien 0xfffc, /* dst_mask */ 119789857Sobrien false), /* pcrel_offset */ 119889857Sobrien 119989857Sobrien /* GNU extension to record C++ vtable hierarchy. */ 120089857Sobrien HOWTO (R_PPC64_GNU_VTINHERIT, /* type */ 120189857Sobrien 0, /* rightshift */ 120289857Sobrien 0, /* size (0 = byte, 1 = short, 2 = long) */ 120389857Sobrien 0, /* bitsize */ 120489857Sobrien false, /* pc_relative */ 120589857Sobrien 0, /* bitpos */ 120689857Sobrien complain_overflow_dont, /* complain_on_overflow */ 120789857Sobrien NULL, /* special_function */ 120889857Sobrien "R_PPC64_GNU_VTINHERIT", /* name */ 120989857Sobrien false, /* partial_inplace */ 121089857Sobrien 0, /* src_mask */ 121189857Sobrien 0, /* dst_mask */ 121289857Sobrien false), /* pcrel_offset */ 121389857Sobrien 121489857Sobrien /* GNU extension to record C++ vtable member usage. */ 121589857Sobrien HOWTO (R_PPC64_GNU_VTENTRY, /* type */ 121689857Sobrien 0, /* rightshift */ 121789857Sobrien 0, /* size (0 = byte, 1 = short, 2 = long) */ 121889857Sobrien 0, /* bitsize */ 121989857Sobrien false, /* pc_relative */ 122089857Sobrien 0, /* bitpos */ 122189857Sobrien complain_overflow_dont, /* complain_on_overflow */ 122289857Sobrien NULL, /* special_function */ 122389857Sobrien "R_PPC64_GNU_VTENTRY", /* name */ 122489857Sobrien false, /* partial_inplace */ 122589857Sobrien 0, /* src_mask */ 122689857Sobrien 0, /* dst_mask */ 122789857Sobrien false), /* pcrel_offset */ 122889857Sobrien}; 122989857Sobrien 123089857Sobrien 123189857Sobrien/* Initialize the ppc64_elf_howto_table, so that linear accesses can 123289857Sobrien be done. */ 123389857Sobrien 123489857Sobrienstatic void 123589857Sobrienppc_howto_init () 123689857Sobrien{ 123789857Sobrien unsigned int i, type; 123889857Sobrien 123989857Sobrien for (i = 0; 124089857Sobrien i < sizeof (ppc64_elf_howto_raw) / sizeof (ppc64_elf_howto_raw[0]); 124189857Sobrien i++) 124289857Sobrien { 124389857Sobrien type = ppc64_elf_howto_raw[i].type; 124489857Sobrien BFD_ASSERT (type < (sizeof (ppc64_elf_howto_table) 124589857Sobrien / sizeof (ppc64_elf_howto_table[0]))); 124689857Sobrien ppc64_elf_howto_table[type] = &ppc64_elf_howto_raw[i]; 124789857Sobrien } 124889857Sobrien} 124989857Sobrien 125089857Sobrienstatic reloc_howto_type * 125189857Sobrienppc64_elf_reloc_type_lookup (abfd, code) 125289857Sobrien bfd *abfd ATTRIBUTE_UNUSED; 125389857Sobrien bfd_reloc_code_real_type code; 125489857Sobrien{ 125589857Sobrien enum elf_ppc_reloc_type ppc_reloc = R_PPC_NONE; 125689857Sobrien 125789857Sobrien if (!ppc64_elf_howto_table[R_PPC64_ADDR32]) 125889857Sobrien /* Initialize howto table if needed. */ 125989857Sobrien ppc_howto_init (); 126089857Sobrien 126189857Sobrien switch ((int) code) 126289857Sobrien { 126389857Sobrien default: 126489857Sobrien return (reloc_howto_type *) NULL; 126589857Sobrien 126689857Sobrien case BFD_RELOC_NONE: ppc_reloc = R_PPC64_NONE; 126789857Sobrien break; 126889857Sobrien case BFD_RELOC_32: ppc_reloc = R_PPC64_ADDR32; 126989857Sobrien break; 127089857Sobrien case BFD_RELOC_PPC_BA26: ppc_reloc = R_PPC64_ADDR24; 127189857Sobrien break; 127289857Sobrien case BFD_RELOC_16: ppc_reloc = R_PPC64_ADDR16; 127389857Sobrien break; 127489857Sobrien case BFD_RELOC_LO16: ppc_reloc = R_PPC64_ADDR16_LO; 127589857Sobrien break; 127689857Sobrien case BFD_RELOC_HI16: ppc_reloc = R_PPC64_ADDR16_HI; 127789857Sobrien break; 127889857Sobrien case BFD_RELOC_HI16_S: ppc_reloc = R_PPC64_ADDR16_HA; 127989857Sobrien break; 128089857Sobrien case BFD_RELOC_PPC_BA16: ppc_reloc = R_PPC64_ADDR14; 128189857Sobrien break; 128289857Sobrien case BFD_RELOC_PPC_BA16_BRTAKEN: ppc_reloc = R_PPC64_ADDR14_BRTAKEN; 128389857Sobrien break; 128489857Sobrien case BFD_RELOC_PPC_BA16_BRNTAKEN: ppc_reloc = R_PPC64_ADDR14_BRNTAKEN; 128589857Sobrien break; 128689857Sobrien case BFD_RELOC_PPC_B26: ppc_reloc = R_PPC64_REL24; 128789857Sobrien break; 128889857Sobrien case BFD_RELOC_PPC_B16: ppc_reloc = R_PPC64_REL14; 128989857Sobrien break; 129089857Sobrien case BFD_RELOC_PPC_B16_BRTAKEN: ppc_reloc = R_PPC64_REL14_BRTAKEN; 129189857Sobrien break; 129289857Sobrien case BFD_RELOC_PPC_B16_BRNTAKEN: ppc_reloc = R_PPC64_REL14_BRNTAKEN; 129389857Sobrien break; 129489857Sobrien case BFD_RELOC_16_GOTOFF: ppc_reloc = R_PPC64_GOT16; 129589857Sobrien break; 129689857Sobrien case BFD_RELOC_LO16_GOTOFF: ppc_reloc = R_PPC64_GOT16_LO; 129789857Sobrien break; 129889857Sobrien case BFD_RELOC_HI16_GOTOFF: ppc_reloc = R_PPC64_GOT16_HI; 129989857Sobrien break; 130089857Sobrien case BFD_RELOC_HI16_S_GOTOFF: ppc_reloc = R_PPC64_GOT16_HA; 130189857Sobrien break; 130289857Sobrien case BFD_RELOC_PPC_COPY: ppc_reloc = R_PPC64_COPY; 130389857Sobrien break; 130489857Sobrien case BFD_RELOC_PPC_GLOB_DAT: ppc_reloc = R_PPC64_GLOB_DAT; 130589857Sobrien break; 130689857Sobrien case BFD_RELOC_32_PCREL: ppc_reloc = R_PPC64_REL32; 130789857Sobrien break; 130889857Sobrien case BFD_RELOC_32_PLTOFF: ppc_reloc = R_PPC64_PLT32; 130989857Sobrien break; 131089857Sobrien case BFD_RELOC_32_PLT_PCREL: ppc_reloc = R_PPC64_PLTREL32; 131189857Sobrien break; 131289857Sobrien case BFD_RELOC_LO16_PLTOFF: ppc_reloc = R_PPC64_PLT16_LO; 131389857Sobrien break; 131489857Sobrien case BFD_RELOC_HI16_PLTOFF: ppc_reloc = R_PPC64_PLT16_HI; 131589857Sobrien break; 131689857Sobrien case BFD_RELOC_HI16_S_PLTOFF: ppc_reloc = R_PPC64_PLT16_HA; 131789857Sobrien break; 131889857Sobrien case BFD_RELOC_32_BASEREL: ppc_reloc = R_PPC64_SECTOFF; 131989857Sobrien break; 132089857Sobrien case BFD_RELOC_LO16_BASEREL: ppc_reloc = R_PPC64_SECTOFF_LO; 132189857Sobrien break; 132289857Sobrien case BFD_RELOC_HI16_BASEREL: ppc_reloc = R_PPC64_SECTOFF_HI; 132389857Sobrien break; 132489857Sobrien case BFD_RELOC_HI16_S_BASEREL: ppc_reloc = R_PPC64_SECTOFF_HA; 132589857Sobrien break; 132689857Sobrien case BFD_RELOC_CTOR: ppc_reloc = R_PPC64_ADDR64; 132789857Sobrien break; 132889857Sobrien case BFD_RELOC_64: ppc_reloc = R_PPC64_ADDR64; 132989857Sobrien break; 133089857Sobrien case BFD_RELOC_PPC64_HIGHER: ppc_reloc = R_PPC64_ADDR16_HIGHER; 133189857Sobrien break; 133289857Sobrien case BFD_RELOC_PPC64_HIGHER_S: ppc_reloc = R_PPC64_ADDR16_HIGHERA; 133389857Sobrien break; 133489857Sobrien case BFD_RELOC_PPC64_HIGHEST: ppc_reloc = R_PPC64_ADDR16_HIGHEST; 133589857Sobrien break; 133689857Sobrien case BFD_RELOC_PPC64_HIGHEST_S: ppc_reloc = R_PPC64_ADDR16_HIGHESTA; 133789857Sobrien break; 133889857Sobrien case BFD_RELOC_64_PCREL: ppc_reloc = R_PPC64_REL64; 133989857Sobrien break; 134089857Sobrien case BFD_RELOC_64_PLTOFF: ppc_reloc = R_PPC64_PLT64; 134189857Sobrien break; 134289857Sobrien case BFD_RELOC_64_PLT_PCREL: ppc_reloc = R_PPC64_PLTREL64; 134389857Sobrien break; 134489857Sobrien case BFD_RELOC_PPC_TOC16: ppc_reloc = R_PPC64_TOC16; 134589857Sobrien break; 134689857Sobrien case BFD_RELOC_PPC64_TOC16_LO: ppc_reloc = R_PPC64_TOC16_LO; 134789857Sobrien break; 134889857Sobrien case BFD_RELOC_PPC64_TOC16_HI: ppc_reloc = R_PPC64_TOC16_HI; 134989857Sobrien break; 135089857Sobrien case BFD_RELOC_PPC64_TOC16_HA: ppc_reloc = R_PPC64_TOC16_HA; 135189857Sobrien break; 135289857Sobrien case BFD_RELOC_PPC64_TOC: ppc_reloc = R_PPC64_TOC; 135389857Sobrien break; 135489857Sobrien case BFD_RELOC_PPC64_PLTGOT16: ppc_reloc = R_PPC64_PLTGOT16; 135589857Sobrien break; 135689857Sobrien case BFD_RELOC_PPC64_PLTGOT16_LO: ppc_reloc = R_PPC64_PLTGOT16_LO; 135789857Sobrien break; 135889857Sobrien case BFD_RELOC_PPC64_PLTGOT16_HI: ppc_reloc = R_PPC64_PLTGOT16_HI; 135989857Sobrien break; 136089857Sobrien case BFD_RELOC_PPC64_PLTGOT16_HA: ppc_reloc = R_PPC64_PLTGOT16_HA; 136189857Sobrien break; 136289857Sobrien case BFD_RELOC_PPC64_ADDR16_DS: ppc_reloc = R_PPC64_ADDR16_DS; 136389857Sobrien break; 136489857Sobrien case BFD_RELOC_PPC64_ADDR16_LO_DS: ppc_reloc = R_PPC64_ADDR16_LO_DS; 136589857Sobrien break; 136689857Sobrien case BFD_RELOC_PPC64_GOT16_DS: ppc_reloc = R_PPC64_GOT16_DS; 136789857Sobrien break; 136889857Sobrien case BFD_RELOC_PPC64_GOT16_LO_DS: ppc_reloc = R_PPC64_GOT16_LO_DS; 136989857Sobrien break; 137089857Sobrien case BFD_RELOC_PPC64_PLT16_LO_DS: ppc_reloc = R_PPC64_PLT16_LO_DS; 137189857Sobrien break; 137289857Sobrien case BFD_RELOC_PPC64_SECTOFF_DS: ppc_reloc = R_PPC64_SECTOFF_DS; 137389857Sobrien break; 137489857Sobrien case BFD_RELOC_PPC64_SECTOFF_LO_DS: ppc_reloc = R_PPC64_SECTOFF_LO_DS; 137589857Sobrien break; 137689857Sobrien case BFD_RELOC_PPC64_TOC16_DS: ppc_reloc = R_PPC64_TOC16_DS; 137789857Sobrien break; 137889857Sobrien case BFD_RELOC_PPC64_TOC16_LO_DS: ppc_reloc = R_PPC64_TOC16_LO_DS; 137989857Sobrien break; 138089857Sobrien case BFD_RELOC_PPC64_PLTGOT16_DS: ppc_reloc = R_PPC64_PLTGOT16_DS; 138189857Sobrien break; 138289857Sobrien case BFD_RELOC_PPC64_PLTGOT16_LO_DS: ppc_reloc = R_PPC64_PLTGOT16_LO_DS; 138389857Sobrien break; 138489857Sobrien case BFD_RELOC_VTABLE_INHERIT: ppc_reloc = R_PPC64_GNU_VTINHERIT; 138589857Sobrien break; 138689857Sobrien case BFD_RELOC_VTABLE_ENTRY: ppc_reloc = R_PPC64_GNU_VTENTRY; 138789857Sobrien break; 138889857Sobrien } 138989857Sobrien 139089857Sobrien return ppc64_elf_howto_table[(int) ppc_reloc]; 139189857Sobrien}; 139289857Sobrien 139389857Sobrien/* Set the howto pointer for a PowerPC ELF reloc. */ 139489857Sobrien 139589857Sobrienstatic void 139689857Sobrienppc64_elf_info_to_howto (abfd, cache_ptr, dst) 139789857Sobrien bfd *abfd ATTRIBUTE_UNUSED; 139889857Sobrien arelent *cache_ptr; 139989857Sobrien Elf64_Internal_Rela *dst; 140089857Sobrien{ 140189857Sobrien unsigned int type; 140289857Sobrien 140389857Sobrien if (!ppc64_elf_howto_table[R_PPC64_ADDR32]) 140489857Sobrien /* Initialize howto table if needed. */ 140589857Sobrien ppc_howto_init (); 140689857Sobrien 140789857Sobrien type = ELF64_R_TYPE (dst->r_info); 140889857Sobrien BFD_ASSERT (type < (sizeof (ppc64_elf_howto_table) 140989857Sobrien / sizeof (ppc64_elf_howto_table[0]))); 141089857Sobrien cache_ptr->howto = ppc64_elf_howto_table[type]; 141189857Sobrien} 141289857Sobrien 141389857Sobrien/* Handle the R_PPC_ADDR16_HA and similar relocs. */ 141489857Sobrien 141589857Sobrienstatic bfd_reloc_status_type 141689857Sobrienppc64_elf_addr16_ha_reloc (abfd, reloc_entry, symbol, data, input_section, 141789857Sobrien output_bfd, error_message) 141889857Sobrien bfd *abfd ATTRIBUTE_UNUSED; 141989857Sobrien arelent *reloc_entry; 142089857Sobrien asymbol *symbol; 142189857Sobrien PTR data ATTRIBUTE_UNUSED; 142289857Sobrien asection *input_section; 142389857Sobrien bfd *output_bfd; 142489857Sobrien char **error_message ATTRIBUTE_UNUSED; 142589857Sobrien{ 142689857Sobrien bfd_vma relocation; 142789857Sobrien 142889857Sobrien if (output_bfd != NULL) 142989857Sobrien { 143089857Sobrien reloc_entry->address += input_section->output_offset; 143189857Sobrien return bfd_reloc_ok; 143289857Sobrien } 143389857Sobrien 143489857Sobrien if (reloc_entry->address > input_section->_cooked_size) 143589857Sobrien return bfd_reloc_outofrange; 143689857Sobrien 143789857Sobrien if (bfd_is_com_section (symbol->section)) 143889857Sobrien relocation = 0; 143989857Sobrien else 144089857Sobrien relocation = symbol->value; 144189857Sobrien 144289857Sobrien relocation += symbol->section->output_section->vma; 144389857Sobrien relocation += symbol->section->output_offset; 144489857Sobrien relocation += reloc_entry->addend; 144589857Sobrien 144689857Sobrien reloc_entry->addend += (relocation & 0x8000) << 1; 144789857Sobrien 144889857Sobrien return bfd_reloc_continue; 144989857Sobrien} 145089857Sobrien 145189857Sobrien/* Function to set whether a module needs the -mrelocatable bit set. */ 145289857Sobrien 145389857Sobrienstatic boolean 145489857Sobrienppc64_elf_set_private_flags (abfd, flags) 145589857Sobrien bfd *abfd; 145689857Sobrien flagword flags; 145789857Sobrien{ 145889857Sobrien BFD_ASSERT (!elf_flags_init (abfd) 145989857Sobrien || elf_elfheader (abfd)->e_flags == flags); 146089857Sobrien 146189857Sobrien elf_elfheader (abfd)->e_flags = flags; 146289857Sobrien elf_flags_init (abfd) = true; 146389857Sobrien return true; 146489857Sobrien} 146589857Sobrien 146689857Sobrien/* Merge backend specific data from an object file to the output 146789857Sobrien object file when linking. */ 146889857Sobrienstatic boolean 146989857Sobrienppc64_elf_merge_private_bfd_data (ibfd, obfd) 147089857Sobrien bfd *ibfd; 147189857Sobrien bfd *obfd; 147289857Sobrien{ 147389857Sobrien flagword old_flags; 147489857Sobrien flagword new_flags; 147589857Sobrien boolean error; 147689857Sobrien 147789857Sobrien /* Check if we have the same endianess. */ 147889857Sobrien if (ibfd->xvec->byteorder != obfd->xvec->byteorder 147989857Sobrien && obfd->xvec->byteorder != BFD_ENDIAN_UNKNOWN) 148089857Sobrien { 148189857Sobrien const char *msg; 148289857Sobrien 148389857Sobrien if (bfd_big_endian (ibfd)) 148489857Sobrien msg = _("%s: compiled for a big endian system and target is little endian"); 148589857Sobrien else 148689857Sobrien msg = _("%s: compiled for a little endian system and target is big endian"); 148789857Sobrien 148889857Sobrien (*_bfd_error_handler) (msg, bfd_archive_filename (ibfd)); 148989857Sobrien 149089857Sobrien bfd_set_error (bfd_error_wrong_format); 149189857Sobrien return false; 149289857Sobrien } 149389857Sobrien 149489857Sobrien if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour 149589857Sobrien || bfd_get_flavour (obfd) != bfd_target_elf_flavour) 149689857Sobrien return true; 149789857Sobrien 149889857Sobrien new_flags = elf_elfheader (ibfd)->e_flags; 149989857Sobrien old_flags = elf_elfheader (obfd)->e_flags; 150089857Sobrien if (!elf_flags_init (obfd)) 150189857Sobrien { 150289857Sobrien /* First call, no flags set. */ 150389857Sobrien elf_flags_init (obfd) = true; 150489857Sobrien elf_elfheader (obfd)->e_flags = new_flags; 150589857Sobrien } 150689857Sobrien 150789857Sobrien else if (new_flags == old_flags) 150889857Sobrien /* Compatible flags are ok. */ 150989857Sobrien ; 151089857Sobrien 151189857Sobrien else 151289857Sobrien { 151389857Sobrien /* Incompatible flags. Warn about -mrelocatable mismatch. 151489857Sobrien Allow -mrelocatable-lib to be linked with either. */ 151589857Sobrien error = false; 151689857Sobrien if ((new_flags & EF_PPC_RELOCATABLE) != 0 151789857Sobrien && (old_flags & (EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB)) == 0) 151889857Sobrien { 151989857Sobrien error = true; 152089857Sobrien (*_bfd_error_handler) 152189857Sobrien (_("%s: compiled with -mrelocatable and linked with modules compiled normally"), 152289857Sobrien bfd_archive_filename (ibfd)); 152389857Sobrien } 152489857Sobrien else if ((new_flags & (EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB)) == 0 152589857Sobrien && (old_flags & EF_PPC_RELOCATABLE) != 0) 152689857Sobrien { 152789857Sobrien error = true; 152889857Sobrien (*_bfd_error_handler) 152989857Sobrien (_("%s: compiled normally and linked with modules compiled with -mrelocatable"), 153089857Sobrien bfd_archive_filename (ibfd)); 153189857Sobrien } 153289857Sobrien 153389857Sobrien /* The output is -mrelocatable-lib iff both the input files are. */ 153489857Sobrien if (! (new_flags & EF_PPC_RELOCATABLE_LIB)) 153589857Sobrien elf_elfheader (obfd)->e_flags &= ~EF_PPC_RELOCATABLE_LIB; 153689857Sobrien 153789857Sobrien /* The output is -mrelocatable iff it can't be -mrelocatable-lib, 153889857Sobrien but each input file is either -mrelocatable or -mrelocatable-lib. */ 153989857Sobrien if (! (elf_elfheader (obfd)->e_flags & EF_PPC_RELOCATABLE_LIB) 154089857Sobrien && (new_flags & (EF_PPC_RELOCATABLE_LIB | EF_PPC_RELOCATABLE)) 154189857Sobrien && (old_flags & (EF_PPC_RELOCATABLE_LIB | EF_PPC_RELOCATABLE))) 154289857Sobrien elf_elfheader (obfd)->e_flags |= EF_PPC_RELOCATABLE; 154389857Sobrien 154489857Sobrien /* Do not warn about eabi vs. V.4 mismatch, just or in the bit 154589857Sobrien if any module uses it. */ 154689857Sobrien elf_elfheader (obfd)->e_flags |= (new_flags & EF_PPC_EMB); 154789857Sobrien 154889857Sobrien new_flags &= ~(EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB | EF_PPC_EMB); 154989857Sobrien old_flags &= ~(EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB | EF_PPC_EMB); 155089857Sobrien 155189857Sobrien /* Warn about any other mismatches. */ 155289857Sobrien if (new_flags != old_flags) 155389857Sobrien { 155489857Sobrien error = true; 155589857Sobrien (*_bfd_error_handler) 155689857Sobrien (_("%s: uses different e_flags (0x%lx) fields than previous modules (0x%lx)"), 155789857Sobrien bfd_archive_filename (ibfd), (long) new_flags, (long) old_flags); 155889857Sobrien } 155989857Sobrien 156089857Sobrien if (error) 156189857Sobrien { 156289857Sobrien bfd_set_error (bfd_error_bad_value); 156389857Sobrien return false; 156489857Sobrien } 156589857Sobrien } 156689857Sobrien 156789857Sobrien return true; 156889857Sobrien} 156989857Sobrien 157089857Sobrien/* Handle a PowerPC specific section when reading an object file. This 157189857Sobrien is called when elfcode.h finds a section with an unknown type. */ 157289857Sobrien 157389857Sobrienstatic boolean 157489857Sobrienppc64_elf_section_from_shdr (abfd, hdr, name) 157589857Sobrien bfd *abfd; 157689857Sobrien Elf64_Internal_Shdr *hdr; 157789857Sobrien char *name; 157889857Sobrien{ 157989857Sobrien asection *newsect; 158089857Sobrien flagword flags; 158189857Sobrien 158289857Sobrien if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name)) 158389857Sobrien return false; 158489857Sobrien 158589857Sobrien newsect = hdr->bfd_section; 158689857Sobrien flags = bfd_get_section_flags (abfd, newsect); 158789857Sobrien if (hdr->sh_flags & SHF_EXCLUDE) 158889857Sobrien flags |= SEC_EXCLUDE; 158989857Sobrien 159089857Sobrien if (hdr->sh_type == SHT_ORDERED) 159189857Sobrien flags |= SEC_SORT_ENTRIES; 159289857Sobrien 159389857Sobrien bfd_set_section_flags (abfd, newsect, flags); 159489857Sobrien return true; 159589857Sobrien} 159689857Sobrien 159789857Sobrien/* The following functions are specific to the ELF linker, while 159889857Sobrien functions above are used generally. Those named ppc64_elf_* are 159989857Sobrien called by the main ELF linker code. They appear in this file more 160089857Sobrien or less in the order in which they are called. eg. 160189857Sobrien ppc64_elf_check_relocs is called early in the link process, 160289857Sobrien ppc64_elf_finish_dynamic_sections is one of the last functions 160389857Sobrien called. 160489857Sobrien 160589857Sobrien PowerPC64-ELF uses a similar scheme to PowerPC64-XCOFF in that 160689857Sobrien functions have both a function code symbol and a function descriptor 160789857Sobrien symbol. A call to foo in a relocatable object file looks like: 160889857Sobrien 160989857Sobrien . .text 161089857Sobrien . x: 161189857Sobrien . bl .foo 161289857Sobrien . nop 161389857Sobrien 161489857Sobrien The function definition in another object file might be: 161589857Sobrien 161689857Sobrien . .section .opd 161789857Sobrien . foo: .quad .foo 161889857Sobrien . .quad .TOC.@tocbase 161989857Sobrien . .quad 0 162089857Sobrien . 162189857Sobrien . .text 162289857Sobrien . .foo: blr 162389857Sobrien 162489857Sobrien When the linker resolves the call during a static link, the branch 162589857Sobrien unsurprisingly just goes to .foo and the .opd information is unused. 162689857Sobrien If the function definition is in a shared library, things are a little 162789857Sobrien different: The call goes via a plt call stub, the opd information gets 162889857Sobrien copied to the plt, and the linker patches the nop. 162989857Sobrien 163089857Sobrien . x: 163189857Sobrien . bl .foo_stub 163289857Sobrien . ld 2,40(1) 163389857Sobrien . 163489857Sobrien . 163589857Sobrien . .foo_stub: 163689857Sobrien . addis 12,2,Lfoo@toc@ha # in practice, the call stub 163789857Sobrien . addi 12,12,Lfoo@toc@l # is slightly optimised, but 163889857Sobrien . std 2,40(1) # this is the general idea 163989857Sobrien . ld 11,0(12) 164089857Sobrien . ld 2,8(12) 164189857Sobrien . mtctr 11 164289857Sobrien . ld 11,16(12) 164389857Sobrien . bctr 164489857Sobrien . 164589857Sobrien . .section .plt 164689857Sobrien . Lfoo: reloc (R_PPC64_JMP_SLOT, foo) 164789857Sobrien 164889857Sobrien The "reloc ()" notation is supposed to indicate that the linker emits 164989857Sobrien an R_PPC64_JMP_SLOT reloc against foo. The dynamic linker does the opd 165089857Sobrien copying. 165189857Sobrien 165289857Sobrien What are the difficulties here? Well, firstly, the relocations 165389857Sobrien examined by the linker in check_relocs are against the function code 165489857Sobrien sym .foo, while the dynamic relocation in the plt is emitted against 165589857Sobrien the function descriptor symbol, foo. Somewhere along the line, we need 165689857Sobrien to carefully copy dynamic link information from one symbol to the other. 165789857Sobrien Secondly, the generic part of the elf linker will make .foo a dynamic 165889857Sobrien symbol as is normal for most other backends. We need foo dynamic 165989857Sobrien instead, at least for an application final link. However, when 166089857Sobrien creating a shared library containing foo, we need to have both symbols 166189857Sobrien dynamic so that references to .foo are satisfied during the early 166289857Sobrien stages of linking. Otherwise the linker might decide to pull in a 166389857Sobrien definition from some other object, eg. a static library. */ 166489857Sobrien 166589857Sobrien/* The linker needs to keep track of the number of relocs that it 166689857Sobrien decides to copy as dynamic relocs in check_relocs for each symbol. 166789857Sobrien This is so that it can later discard them if they are found to be 166889857Sobrien unnecessary. We store the information in a field extending the 166989857Sobrien regular ELF linker hash table. */ 167089857Sobrien 167189857Sobrienstruct ppc_dyn_relocs 167289857Sobrien{ 167389857Sobrien struct ppc_dyn_relocs *next; 167489857Sobrien 167589857Sobrien /* The input section of the reloc. */ 167689857Sobrien asection *sec; 167789857Sobrien 167889857Sobrien /* Total number of relocs copied for the input section. */ 167989857Sobrien bfd_size_type count; 168089857Sobrien 168189857Sobrien /* Number of pc-relative relocs copied for the input section. */ 168289857Sobrien bfd_size_type pc_count; 168389857Sobrien}; 168489857Sobrien 168589857Sobrien/* Of those relocs that might be copied as dynamic relocs, this macro 168689857Sobrien selects between relative and absolute types. */ 168789857Sobrien 168889857Sobrien#define IS_ABSOLUTE_RELOC(RTYPE) \ 168989857Sobrien ((RTYPE) != R_PPC64_REL14 \ 169089857Sobrien && (RTYPE) != R_PPC64_REL14_BRNTAKEN \ 169189857Sobrien && (RTYPE) != R_PPC64_REL14_BRTAKEN \ 169289857Sobrien && (RTYPE) != R_PPC64_REL24 \ 169389857Sobrien && (RTYPE) != R_PPC64_REL32 \ 169489857Sobrien && (RTYPE) != R_PPC64_REL64) 169589857Sobrien 169689857Sobrien/* ppc64 ELF linker hash entry. */ 169789857Sobrien 169889857Sobrienstruct ppc_link_hash_entry 169989857Sobrien{ 170089857Sobrien struct elf_link_hash_entry elf; 170189857Sobrien 170289857Sobrien /* Track dynamic relocs copied for this symbol. */ 170389857Sobrien struct ppc_dyn_relocs *dyn_relocs; 170489857Sobrien 170589857Sobrien /* Flag function code and descriptor symbols. */ 170689857Sobrien unsigned int is_func:1; 170789857Sobrien unsigned int is_func_descriptor:1; 170889857Sobrien}; 170989857Sobrien 171089857Sobrien/* ppc64 ELF linker hash table. */ 171189857Sobrien 171289857Sobrienstruct ppc_link_hash_table 171389857Sobrien{ 171489857Sobrien struct elf_link_hash_table elf; 171589857Sobrien 171689857Sobrien /* Short-cuts to get to dynamic linker sections. */ 171789857Sobrien asection *sgot; 171889857Sobrien asection *srelgot; 171989857Sobrien asection *splt; 172089857Sobrien asection *srelplt; 172189857Sobrien asection *sdynbss; 172289857Sobrien asection *srelbss; 172389857Sobrien asection *sstub; 172489857Sobrien asection *sglink; 172589857Sobrien 172689857Sobrien /* Set on error. */ 172789857Sobrien int plt_overflow; 172889857Sobrien 172989857Sobrien /* Small local sym to section mapping cache. */ 173089857Sobrien struct sym_sec_cache sym_sec; 173189857Sobrien}; 173289857Sobrien 173389857Sobrien/* Get the ppc64 ELF linker hash table from a link_info structure. */ 173489857Sobrien 173589857Sobrien#define ppc_hash_table(p) \ 173689857Sobrien ((struct ppc_link_hash_table *) ((p)->hash)) 173789857Sobrien 173889857Sobrien/* Create an entry in a ppc64 ELF linker hash table. */ 173989857Sobrien 174089857Sobrienstatic struct bfd_hash_entry * 174189857Sobrienlink_hash_newfunc (entry, table, string) 174289857Sobrien struct bfd_hash_entry *entry; 174389857Sobrien struct bfd_hash_table *table; 174489857Sobrien const char *string; 174589857Sobrien{ 174689857Sobrien /* Allocate the structure if it has not already been allocated by a 174789857Sobrien subclass. */ 174889857Sobrien if (entry == NULL) 174989857Sobrien { 175089857Sobrien entry = bfd_hash_allocate (table, sizeof (struct ppc_link_hash_entry)); 175189857Sobrien if (entry == NULL) 175289857Sobrien return entry; 175389857Sobrien } 175489857Sobrien 175589857Sobrien /* Call the allocation method of the superclass. */ 175689857Sobrien entry = _bfd_elf_link_hash_newfunc (entry, table, string); 175789857Sobrien if (entry != NULL) 175889857Sobrien { 175989857Sobrien struct ppc_link_hash_entry *eh = (struct ppc_link_hash_entry *) entry; 176089857Sobrien 176189857Sobrien eh->dyn_relocs = NULL; 176289857Sobrien eh->is_func = 0; 176389857Sobrien eh->is_func_descriptor = 0; 176489857Sobrien } 176589857Sobrien 176689857Sobrien return entry; 176789857Sobrien} 176889857Sobrien 176989857Sobrien/* Create a ppc64 ELF linker hash table. */ 177089857Sobrien 177189857Sobrienstatic struct bfd_link_hash_table * 177289857Sobrienppc64_elf_link_hash_table_create (abfd) 177389857Sobrien bfd *abfd; 177489857Sobrien{ 177589857Sobrien struct ppc_link_hash_table *htab; 177689857Sobrien bfd_size_type amt = sizeof (struct ppc_link_hash_table); 177789857Sobrien 177889857Sobrien htab = (struct ppc_link_hash_table *) bfd_alloc (abfd, amt); 177989857Sobrien if (htab == NULL) 178089857Sobrien return NULL; 178189857Sobrien 178289857Sobrien if (! _bfd_elf_link_hash_table_init (&htab->elf, abfd, link_hash_newfunc)) 178389857Sobrien { 178489857Sobrien bfd_release (abfd, htab); 178589857Sobrien return NULL; 178689857Sobrien } 178789857Sobrien 178889857Sobrien htab->sgot = NULL; 178989857Sobrien htab->srelgot = NULL; 179089857Sobrien htab->splt = NULL; 179189857Sobrien htab->srelplt = NULL; 179289857Sobrien htab->sdynbss = NULL; 179389857Sobrien htab->srelbss = NULL; 179489857Sobrien htab->sstub = NULL; 179589857Sobrien htab->sglink = NULL; 179689857Sobrien htab->plt_overflow = 0; 179789857Sobrien htab->sym_sec.abfd = NULL; 179889857Sobrien 179989857Sobrien return &htab->elf.root; 180089857Sobrien} 180189857Sobrien 180289857Sobrien/* Create .got and .rela.got sections in DYNOBJ, and set up 180389857Sobrien shortcuts to them in our hash table. */ 180489857Sobrien 180589857Sobrienstatic boolean 180689857Sobriencreate_got_section (dynobj, info) 180789857Sobrien bfd *dynobj; 180889857Sobrien struct bfd_link_info *info; 180989857Sobrien{ 181089857Sobrien struct ppc_link_hash_table *htab; 181189857Sobrien 181289857Sobrien if (! _bfd_elf_create_got_section (dynobj, info)) 181389857Sobrien return false; 181489857Sobrien 181589857Sobrien htab = ppc_hash_table (info); 181689857Sobrien htab->sgot = bfd_get_section_by_name (dynobj, ".got"); 181789857Sobrien if (!htab->sgot) 181889857Sobrien abort (); 181989857Sobrien 182089857Sobrien htab->srelgot = bfd_make_section (dynobj, ".rela.got"); 182189857Sobrien if (!htab->srelgot 182289857Sobrien || ! bfd_set_section_flags (dynobj, htab->srelgot, 182389857Sobrien (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS 182489857Sobrien | SEC_IN_MEMORY | SEC_LINKER_CREATED 182589857Sobrien | SEC_READONLY)) 182689857Sobrien || ! bfd_set_section_alignment (dynobj, htab->srelgot, 3)) 182789857Sobrien return false; 182889857Sobrien return true; 182989857Sobrien} 183089857Sobrien 183189857Sobrien/* Create the .stub and .glink sections as well as the ordinary 183289857Sobrien dynamic sections. */ 183389857Sobrien 183489857Sobrienstatic boolean 183589857Sobrienppc64_elf_create_dynamic_sections (dynobj, info) 183689857Sobrien bfd *dynobj; 183789857Sobrien struct bfd_link_info *info; 183889857Sobrien{ 183989857Sobrien struct ppc_link_hash_table *htab; 184089857Sobrien flagword flags; 184189857Sobrien 184289857Sobrien htab = ppc_hash_table (info); 184389857Sobrien if (!htab->sgot && !create_got_section (dynobj, info)) 184489857Sobrien return false; 184589857Sobrien 184689857Sobrien if (!_bfd_elf_create_dynamic_sections (dynobj, info)) 184789857Sobrien return false; 184889857Sobrien 184989857Sobrien htab->splt = bfd_get_section_by_name (dynobj, ".plt"); 185089857Sobrien htab->srelplt = bfd_get_section_by_name (dynobj, ".rela.plt"); 185189857Sobrien htab->sdynbss = bfd_get_section_by_name (dynobj, ".dynbss"); 185289857Sobrien if (!info->shared) 185389857Sobrien htab->srelbss = bfd_get_section_by_name (dynobj, ".rela.bss"); 185489857Sobrien 185589857Sobrien if (!htab->splt || !htab->srelplt || !htab->sdynbss 185689857Sobrien || (!info->shared && !htab->srelbss)) 185789857Sobrien abort (); 185889857Sobrien 185989857Sobrien /* Create .stub and .glink for global linkage functions. */ 186089857Sobrien flags = (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_READONLY 186189857Sobrien | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED); 186289857Sobrien htab->sstub = bfd_make_section (dynobj, ".stub"); 186389857Sobrien if (htab->sstub == NULL 186489857Sobrien || ! bfd_set_section_flags (dynobj, htab->sstub, flags) 186589857Sobrien || ! bfd_set_section_alignment (dynobj, htab->sstub, 2)) 186689857Sobrien return false; 186789857Sobrien htab->sglink = bfd_make_section (dynobj, ".glink"); 186889857Sobrien if (htab->sglink == NULL 186989857Sobrien || ! bfd_set_section_flags (dynobj, htab->sglink, flags) 187089857Sobrien || ! bfd_set_section_alignment (dynobj, htab->sglink, 3)) 187189857Sobrien return false; 187289857Sobrien 187389857Sobrien return true; 187489857Sobrien} 187589857Sobrien 187689857Sobrien/* Copy the extra info we tack onto an elf_link_hash_entry. */ 187789857Sobrien 187889857Sobrienstatic void 187989857Sobrienppc64_elf_copy_indirect_symbol (dir, ind) 188089857Sobrien struct elf_link_hash_entry *dir, *ind; 188189857Sobrien{ 188289857Sobrien struct ppc_link_hash_entry *edir, *eind; 188389857Sobrien 188489857Sobrien edir = (struct ppc_link_hash_entry *) dir; 188589857Sobrien eind = (struct ppc_link_hash_entry *) ind; 188689857Sobrien 188789857Sobrien if (eind->dyn_relocs != NULL) 188889857Sobrien { 188989857Sobrien if (edir->dyn_relocs != NULL) 189089857Sobrien { 189189857Sobrien struct ppc_dyn_relocs **pp; 189289857Sobrien struct ppc_dyn_relocs *p; 189389857Sobrien 189489857Sobrien if (ind->root.type == bfd_link_hash_indirect) 189589857Sobrien abort (); 189689857Sobrien 189789857Sobrien /* Add reloc counts against the weak sym to the strong sym 189889857Sobrien list. Merge any entries against the same section. */ 189989857Sobrien for (pp = &eind->dyn_relocs; (p = *pp) != NULL; ) 190089857Sobrien { 190189857Sobrien struct ppc_dyn_relocs *q; 190289857Sobrien 190389857Sobrien for (q = edir->dyn_relocs; q != NULL; q = q->next) 190489857Sobrien if (q->sec == p->sec) 190589857Sobrien { 190689857Sobrien q->pc_count += p->pc_count; 190789857Sobrien q->count += p->count; 190889857Sobrien *pp = p->next; 190989857Sobrien break; 191089857Sobrien } 191189857Sobrien if (q == NULL) 191289857Sobrien pp = &p->next; 191389857Sobrien } 191489857Sobrien *pp = edir->dyn_relocs; 191589857Sobrien } 191689857Sobrien 191789857Sobrien edir->dyn_relocs = eind->dyn_relocs; 191889857Sobrien eind->dyn_relocs = NULL; 191989857Sobrien } 192089857Sobrien 192189857Sobrien edir->is_func |= eind->is_func; 192289857Sobrien edir->is_func_descriptor |= eind->is_func_descriptor; 192389857Sobrien 192489857Sobrien _bfd_elf_link_hash_copy_indirect (dir, ind); 192589857Sobrien} 192689857Sobrien 192789857Sobrien/* Look through the relocs for a section during the first phase, and 192889857Sobrien calculate needed space in the global offset table, procedure 192989857Sobrien linkage table, and dynamic reloc sections. */ 193089857Sobrien 193189857Sobrienstatic boolean 193289857Sobrienppc64_elf_check_relocs (abfd, info, sec, relocs) 193389857Sobrien bfd *abfd; 193489857Sobrien struct bfd_link_info *info; 193589857Sobrien asection *sec; 193689857Sobrien const Elf_Internal_Rela *relocs; 193789857Sobrien{ 193889857Sobrien struct ppc_link_hash_table *htab; 193989857Sobrien Elf_Internal_Shdr *symtab_hdr; 194089857Sobrien struct elf_link_hash_entry **sym_hashes, **sym_hashes_end; 194189857Sobrien const Elf_Internal_Rela *rel; 194289857Sobrien const Elf_Internal_Rela *rel_end; 194389857Sobrien asection *sreloc; 194489857Sobrien boolean is_opd; 194589857Sobrien 194689857Sobrien if (info->relocateable) 194789857Sobrien return true; 194889857Sobrien 194989857Sobrien htab = ppc_hash_table (info); 195089857Sobrien symtab_hdr = &elf_tdata (abfd)->symtab_hdr; 195189857Sobrien 195289857Sobrien sym_hashes = elf_sym_hashes (abfd); 195389857Sobrien sym_hashes_end = (sym_hashes 195489857Sobrien + symtab_hdr->sh_size / sizeof (Elf64_External_Sym)); 195589857Sobrien if (!elf_bad_symtab (abfd)) 195689857Sobrien sym_hashes_end -= symtab_hdr->sh_info; 195789857Sobrien 195889857Sobrien sreloc = NULL; 195989857Sobrien is_opd = strcmp (bfd_get_section_name (abfd, sec), ".opd") == 0; 196089857Sobrien 196189857Sobrien rel_end = relocs + sec->reloc_count; 196289857Sobrien for (rel = relocs; rel < rel_end; rel++) 196389857Sobrien { 196489857Sobrien unsigned long r_symndx; 196589857Sobrien struct elf_link_hash_entry *h; 196689857Sobrien enum elf_ppc_reloc_type r_type; 196789857Sobrien 196889857Sobrien r_symndx = ELF64_R_SYM (rel->r_info); 196989857Sobrien if (r_symndx < symtab_hdr->sh_info) 197089857Sobrien h = NULL; 197189857Sobrien else 197289857Sobrien h = sym_hashes[r_symndx - symtab_hdr->sh_info]; 197389857Sobrien 197489857Sobrien r_type = (enum elf_ppc_reloc_type) ELF64_R_TYPE (rel->r_info); 197589857Sobrien switch (r_type) 197689857Sobrien { 197789857Sobrien /* GOT16 relocations */ 197889857Sobrien case R_PPC64_GOT16: 197989857Sobrien case R_PPC64_GOT16_DS: 198089857Sobrien case R_PPC64_GOT16_HA: 198189857Sobrien case R_PPC64_GOT16_HI: 198289857Sobrien case R_PPC64_GOT16_LO: 198389857Sobrien case R_PPC64_GOT16_LO_DS: 198489857Sobrien 198589857Sobrien /* This symbol requires a global offset table entry. */ 198689857Sobrien if (htab->sgot == NULL) 198789857Sobrien { 198889857Sobrien if (htab->elf.dynobj == NULL) 198989857Sobrien htab->elf.dynobj = abfd; 199089857Sobrien if (!create_got_section (htab->elf.dynobj, info)) 199189857Sobrien return false; 199289857Sobrien } 199389857Sobrien 199489857Sobrien if (h != NULL) 199589857Sobrien { 199689857Sobrien h->got.refcount += 1; 199789857Sobrien } 199889857Sobrien else 199989857Sobrien { 200089857Sobrien bfd_signed_vma *local_got_refcounts; 200189857Sobrien 200289857Sobrien /* This is a global offset table entry for a local symbol. */ 200389857Sobrien local_got_refcounts = elf_local_got_refcounts (abfd); 200489857Sobrien if (local_got_refcounts == NULL) 200589857Sobrien { 200689857Sobrien bfd_size_type size; 200789857Sobrien 200889857Sobrien size = symtab_hdr->sh_info; 200989857Sobrien size *= sizeof (bfd_signed_vma); 201089857Sobrien local_got_refcounts = ((bfd_signed_vma *) 201189857Sobrien bfd_zalloc (abfd, size)); 201289857Sobrien if (local_got_refcounts == NULL) 201389857Sobrien return false; 201489857Sobrien elf_local_got_refcounts (abfd) = local_got_refcounts; 201589857Sobrien } 201689857Sobrien local_got_refcounts[r_symndx] += 1; 201789857Sobrien } 201889857Sobrien break; 201989857Sobrien 202089857Sobrien case R_PPC64_PLT16_HA: 202189857Sobrien case R_PPC64_PLT16_HI: 202289857Sobrien case R_PPC64_PLT16_LO: 202389857Sobrien case R_PPC64_PLT32: 202489857Sobrien case R_PPC64_PLT64: 202589857Sobrien /* This symbol requires a procedure linkage table entry. We 202689857Sobrien actually build the entry in adjust_dynamic_symbol, 202789857Sobrien because this might be a case of linking PIC code without 202889857Sobrien linking in any dynamic objects, in which case we don't 202989857Sobrien need to generate a procedure linkage table after all. */ 203089857Sobrien if (h == NULL) 203189857Sobrien { 203289857Sobrien /* It does not make sense to have a procedure linkage 203389857Sobrien table entry for a local symbol. */ 203489857Sobrien bfd_set_error (bfd_error_bad_value); 203589857Sobrien return false; 203689857Sobrien } 203789857Sobrien 203889857Sobrien h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; 203989857Sobrien h->plt.refcount += 1; 204089857Sobrien ((struct ppc_link_hash_entry *) h)->is_func = 1; 204189857Sobrien break; 204289857Sobrien 204389857Sobrien /* The following relocations don't need to propagate the 204489857Sobrien relocation if linking a shared object since they are 204589857Sobrien section relative. */ 204689857Sobrien case R_PPC64_SECTOFF: 204789857Sobrien case R_PPC64_SECTOFF_LO: 204889857Sobrien case R_PPC64_SECTOFF_HI: 204989857Sobrien case R_PPC64_SECTOFF_HA: 205089857Sobrien case R_PPC64_SECTOFF_DS: 205189857Sobrien case R_PPC64_SECTOFF_LO_DS: 205289857Sobrien case R_PPC64_TOC16: 205389857Sobrien case R_PPC64_TOC16_LO: 205489857Sobrien case R_PPC64_TOC16_HI: 205589857Sobrien case R_PPC64_TOC16_HA: 205689857Sobrien case R_PPC64_TOC16_DS: 205789857Sobrien case R_PPC64_TOC16_LO_DS: 205889857Sobrien break; 205989857Sobrien 206089857Sobrien /* This relocation describes the C++ object vtable hierarchy. 206189857Sobrien Reconstruct it for later use during GC. */ 206289857Sobrien case R_PPC64_GNU_VTINHERIT: 206389857Sobrien if (!_bfd_elf64_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) 206489857Sobrien return false; 206589857Sobrien break; 206689857Sobrien 206789857Sobrien /* This relocation describes which C++ vtable entries are actually 206889857Sobrien used. Record for later use during GC. */ 206989857Sobrien case R_PPC64_GNU_VTENTRY: 207089857Sobrien if (!_bfd_elf64_gc_record_vtentry (abfd, sec, h, rel->r_addend)) 207189857Sobrien return false; 207289857Sobrien break; 207389857Sobrien 207489857Sobrien case R_PPC64_REL24: 207589857Sobrien if (h != NULL 207689857Sobrien && h->root.root.string[0] == '.' 207789857Sobrien && h->root.root.string[1] != 0) 207889857Sobrien { 207989857Sobrien /* We may need a .plt entry if the function this reloc 208089857Sobrien refers to is in a shared lib. */ 208189857Sobrien h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; 208289857Sobrien h->plt.refcount += 1; 208389857Sobrien ((struct ppc_link_hash_entry *) h)->is_func = 1; 208489857Sobrien } 208589857Sobrien break; 208689857Sobrien 208789857Sobrien case R_PPC64_ADDR64: 208889857Sobrien if (is_opd 208989857Sobrien && h != NULL 209089857Sobrien && h->root.root.string[0] == '.' 209189857Sobrien && h->root.root.string[1] != 0) 209289857Sobrien { 209389857Sobrien struct elf_link_hash_entry *fdh; 209489857Sobrien 209589857Sobrien fdh = elf_link_hash_lookup (&htab->elf, h->root.root.string + 1, 209689857Sobrien false, false, false); 209789857Sobrien if (fdh != NULL) 209889857Sobrien { 209989857Sobrien /* Ensure the function descriptor symbol string is 210089857Sobrien part of the code symbol string. We aren't 210189857Sobrien changing the name here, just allowing some tricks 210289857Sobrien in ppc64_elf_hide_symbol. */ 210389857Sobrien fdh->root.root.string = h->root.root.string + 1; 210489857Sobrien ((struct ppc_link_hash_entry *) fdh)->is_func_descriptor = 1; 210589857Sobrien ((struct ppc_link_hash_entry *) h)->is_func = 1; 210689857Sobrien } 210789857Sobrien } 210889857Sobrien /* Fall through. */ 210989857Sobrien 211089857Sobrien case R_PPC64_REL64: 211189857Sobrien case R_PPC64_REL32: 211289857Sobrien case R_PPC64_REL14: 211389857Sobrien case R_PPC64_REL14_BRTAKEN: 211489857Sobrien case R_PPC64_REL14_BRNTAKEN: 211589857Sobrien case R_PPC64_ADDR14: 211689857Sobrien case R_PPC64_ADDR14_BRNTAKEN: 211789857Sobrien case R_PPC64_ADDR14_BRTAKEN: 211889857Sobrien case R_PPC64_ADDR16: 211989857Sobrien case R_PPC64_ADDR16_DS: 212089857Sobrien case R_PPC64_ADDR16_HA: 212189857Sobrien case R_PPC64_ADDR16_HI: 212289857Sobrien case R_PPC64_ADDR16_HIGHER: 212389857Sobrien case R_PPC64_ADDR16_HIGHERA: 212489857Sobrien case R_PPC64_ADDR16_HIGHEST: 212589857Sobrien case R_PPC64_ADDR16_HIGHESTA: 212689857Sobrien case R_PPC64_ADDR16_LO: 212789857Sobrien case R_PPC64_ADDR16_LO_DS: 212889857Sobrien case R_PPC64_ADDR24: 212989857Sobrien case R_PPC64_ADDR30: 213089857Sobrien case R_PPC64_ADDR32: 213189857Sobrien case R_PPC64_UADDR16: 213289857Sobrien case R_PPC64_UADDR32: 213389857Sobrien case R_PPC64_UADDR64: 213489857Sobrien case R_PPC64_TOC: 213589857Sobrien /* Don't propagate .opd relocs. */ 213689857Sobrien if (NO_OPD_RELOCS && is_opd) 213789857Sobrien break; 213889857Sobrien 213989857Sobrien /* If we are creating a shared library, and this is a reloc 214089857Sobrien against a global symbol, or a non PC relative reloc 214189857Sobrien against a local symbol, then we need to copy the reloc 214289857Sobrien into the shared library. However, if we are linking with 214389857Sobrien -Bsymbolic, we do not need to copy a reloc against a 214489857Sobrien global symbol which is defined in an object we are 214589857Sobrien including in the link (i.e., DEF_REGULAR is set). At 214689857Sobrien this point we have not seen all the input files, so it is 214789857Sobrien possible that DEF_REGULAR is not set now but will be set 214889857Sobrien later (it is never cleared). In case of a weak definition, 214989857Sobrien DEF_REGULAR may be cleared later by a strong definition in 215089857Sobrien a shared library. We account for that possibility below by 215189857Sobrien storing information in the relocs_copied field of the hash 215289857Sobrien table entry. A similar situation occurs when creating 215389857Sobrien shared libraries and symbol visibility changes render the 215489857Sobrien symbol local. 215589857Sobrien 215689857Sobrien If on the other hand, we are creating an executable, we 215789857Sobrien may need to keep relocations for symbols satisfied by a 215889857Sobrien dynamic library if we manage to avoid copy relocs for the 215989857Sobrien symbol. */ 216089857Sobrien if ((info->shared 216189857Sobrien && (sec->flags & SEC_ALLOC) != 0 216289857Sobrien && (IS_ABSOLUTE_RELOC (r_type) 216389857Sobrien || (h != NULL 216489857Sobrien && (! info->symbolic 216589857Sobrien || h->root.type == bfd_link_hash_defweak 216689857Sobrien || (h->elf_link_hash_flags 216789857Sobrien & ELF_LINK_HASH_DEF_REGULAR) == 0)))) 216889857Sobrien || (!info->shared 216989857Sobrien && (sec->flags & SEC_ALLOC) != 0 217089857Sobrien && h != NULL 217189857Sobrien && (h->root.type == bfd_link_hash_defweak 217289857Sobrien || (h->elf_link_hash_flags 217389857Sobrien & ELF_LINK_HASH_DEF_REGULAR) == 0))) 217489857Sobrien { 217589857Sobrien struct ppc_dyn_relocs *p; 217689857Sobrien struct ppc_dyn_relocs **head; 217789857Sobrien 217889857Sobrien /* We must copy these reloc types into the output file. 217989857Sobrien Create a reloc section in dynobj and make room for 218089857Sobrien this reloc. */ 218189857Sobrien if (sreloc == NULL) 218289857Sobrien { 218389857Sobrien const char *name; 218489857Sobrien bfd *dynobj; 218589857Sobrien 218689857Sobrien name = (bfd_elf_string_from_elf_section 218789857Sobrien (abfd, 218889857Sobrien elf_elfheader (abfd)->e_shstrndx, 218989857Sobrien elf_section_data (sec)->rel_hdr.sh_name)); 219089857Sobrien if (name == NULL) 219189857Sobrien return false; 219289857Sobrien 219389857Sobrien if (strncmp (name, ".rela", 5) != 0 219489857Sobrien || strcmp (bfd_get_section_name (abfd, sec), 219589857Sobrien name + 5) != 0) 219689857Sobrien { 219789857Sobrien (*_bfd_error_handler) 219889857Sobrien (_("%s: bad relocation section name `%s\'"), 219989857Sobrien bfd_archive_filename (abfd), name); 220089857Sobrien bfd_set_error (bfd_error_bad_value); 220189857Sobrien } 220289857Sobrien 220389857Sobrien if (htab->elf.dynobj == NULL) 220489857Sobrien htab->elf.dynobj = abfd; 220589857Sobrien 220689857Sobrien dynobj = htab->elf.dynobj; 220789857Sobrien sreloc = bfd_get_section_by_name (dynobj, name); 220889857Sobrien if (sreloc == NULL) 220989857Sobrien { 221089857Sobrien flagword flags; 221189857Sobrien 221289857Sobrien sreloc = bfd_make_section (dynobj, name); 221389857Sobrien flags = (SEC_HAS_CONTENTS | SEC_READONLY 221489857Sobrien | SEC_IN_MEMORY | SEC_LINKER_CREATED); 221589857Sobrien if ((sec->flags & SEC_ALLOC) != 0) 221689857Sobrien flags |= SEC_ALLOC | SEC_LOAD; 221789857Sobrien if (sreloc == NULL 221889857Sobrien || ! bfd_set_section_flags (dynobj, sreloc, flags) 221989857Sobrien || ! bfd_set_section_alignment (dynobj, sreloc, 3)) 222089857Sobrien return false; 222189857Sobrien } 222289857Sobrien elf_section_data (sec)->sreloc = sreloc; 222389857Sobrien } 222489857Sobrien 222589857Sobrien /* If this is a global symbol, we count the number of 222689857Sobrien relocations we need for this symbol. */ 222789857Sobrien if (h != NULL) 222889857Sobrien { 222989857Sobrien head = &((struct ppc_link_hash_entry *) h)->dyn_relocs; 223089857Sobrien } 223189857Sobrien else 223289857Sobrien { 223389857Sobrien /* Track dynamic relocs needed for local syms too. 223489857Sobrien We really need local syms available to do this 223589857Sobrien easily. Oh well. */ 223689857Sobrien 223789857Sobrien asection *s; 223889857Sobrien s = bfd_section_from_r_symndx (abfd, &htab->sym_sec, 223989857Sobrien sec, r_symndx); 224089857Sobrien if (s == NULL) 224189857Sobrien return false; 224289857Sobrien 224389857Sobrien head = ((struct ppc_dyn_relocs **) 224489857Sobrien &elf_section_data (s)->local_dynrel); 224589857Sobrien } 224689857Sobrien 224789857Sobrien p = *head; 224889857Sobrien if (p == NULL || p->sec != sec) 224989857Sobrien { 225089857Sobrien p = ((struct ppc_dyn_relocs *) 225189857Sobrien bfd_alloc (htab->elf.dynobj, 225289857Sobrien (bfd_size_type) sizeof *p)); 225389857Sobrien if (p == NULL) 225489857Sobrien return false; 225589857Sobrien p->next = *head; 225689857Sobrien *head = p; 225789857Sobrien p->sec = sec; 225889857Sobrien p->count = 0; 225989857Sobrien p->pc_count = 0; 226089857Sobrien } 226189857Sobrien 226289857Sobrien p->count += 1; 226389857Sobrien if (!IS_ABSOLUTE_RELOC (r_type)) 226489857Sobrien p->pc_count += 1; 226589857Sobrien } 226689857Sobrien break; 226789857Sobrien 226889857Sobrien default: 226989857Sobrien } 227089857Sobrien } 227189857Sobrien 227289857Sobrien return true; 227389857Sobrien} 227489857Sobrien 227589857Sobrien/* Return the section that should be marked against GC for a given 227689857Sobrien relocation. */ 227789857Sobrien 227889857Sobrienstatic asection * 227989857Sobrienppc64_elf_gc_mark_hook (abfd, info, rel, h, sym) 228089857Sobrien bfd *abfd; 228189857Sobrien struct bfd_link_info *info ATTRIBUTE_UNUSED; 228289857Sobrien Elf_Internal_Rela *rel; 228389857Sobrien struct elf_link_hash_entry *h; 228489857Sobrien Elf_Internal_Sym *sym; 228589857Sobrien{ 228689857Sobrien if (h != NULL) 228789857Sobrien { 228889857Sobrien enum elf_ppc_reloc_type r_type; 228989857Sobrien 229089857Sobrien r_type = (enum elf_ppc_reloc_type) ELF64_R_TYPE (rel->r_info); 229189857Sobrien switch (r_type) 229289857Sobrien { 229389857Sobrien case R_PPC64_GNU_VTINHERIT: 229489857Sobrien case R_PPC64_GNU_VTENTRY: 229589857Sobrien break; 229689857Sobrien 229789857Sobrien default: 229889857Sobrien switch (h->root.type) 229989857Sobrien { 230089857Sobrien case bfd_link_hash_defined: 230189857Sobrien case bfd_link_hash_defweak: 230289857Sobrien return h->root.u.def.section; 230389857Sobrien 230489857Sobrien case bfd_link_hash_common: 230589857Sobrien return h->root.u.c.p->section; 230689857Sobrien 230789857Sobrien default: 230889857Sobrien break; 230989857Sobrien } 231089857Sobrien } 231189857Sobrien } 231289857Sobrien else 231389857Sobrien { 231489857Sobrien return bfd_section_from_elf_index (abfd, sym->st_shndx); 231589857Sobrien } 231689857Sobrien 231789857Sobrien return NULL; 231889857Sobrien} 231989857Sobrien 232089857Sobrien/* Update the .got, .plt. and dynamic reloc reference counts for the 232189857Sobrien section being removed. */ 232289857Sobrien 232389857Sobrienstatic boolean 232489857Sobrienppc64_elf_gc_sweep_hook (abfd, info, sec, relocs) 232589857Sobrien bfd *abfd; 232689857Sobrien struct bfd_link_info *info ATTRIBUTE_UNUSED; 232789857Sobrien asection *sec; 232889857Sobrien const Elf_Internal_Rela *relocs; 232989857Sobrien{ 233089857Sobrien Elf_Internal_Shdr *symtab_hdr; 233189857Sobrien struct elf_link_hash_entry **sym_hashes; 233289857Sobrien bfd_signed_vma *local_got_refcounts; 233389857Sobrien const Elf_Internal_Rela *rel, *relend; 233489857Sobrien 233589857Sobrien elf_section_data (sec)->local_dynrel = NULL; 233689857Sobrien 233789857Sobrien symtab_hdr = &elf_tdata (abfd)->symtab_hdr; 233889857Sobrien sym_hashes = elf_sym_hashes (abfd); 233989857Sobrien local_got_refcounts = elf_local_got_refcounts (abfd); 234089857Sobrien 234189857Sobrien relend = relocs + sec->reloc_count; 234289857Sobrien for (rel = relocs; rel < relend; rel++) 234389857Sobrien { 234489857Sobrien unsigned long r_symndx; 234589857Sobrien enum elf_ppc_reloc_type r_type; 234689857Sobrien struct elf_link_hash_entry *h; 234789857Sobrien 234889857Sobrien r_symndx = ELF64_R_SYM (rel->r_info); 234989857Sobrien r_type = (enum elf_ppc_reloc_type) ELF64_R_TYPE (rel->r_info); 235089857Sobrien switch (r_type) 235189857Sobrien { 235289857Sobrien case R_PPC64_GOT16: 235389857Sobrien case R_PPC64_GOT16_DS: 235489857Sobrien case R_PPC64_GOT16_HA: 235589857Sobrien case R_PPC64_GOT16_HI: 235689857Sobrien case R_PPC64_GOT16_LO: 235789857Sobrien case R_PPC64_GOT16_LO_DS: 235889857Sobrien if (r_symndx >= symtab_hdr->sh_info) 235989857Sobrien { 236089857Sobrien h = sym_hashes[r_symndx - symtab_hdr->sh_info]; 236189857Sobrien if (h->got.refcount > 0) 236289857Sobrien h->got.refcount--; 236389857Sobrien } 236489857Sobrien else 236589857Sobrien { 236689857Sobrien if (local_got_refcounts[r_symndx] > 0) 236789857Sobrien local_got_refcounts[r_symndx]--; 236889857Sobrien } 236989857Sobrien break; 237089857Sobrien 237189857Sobrien case R_PPC64_PLT16_HA: 237289857Sobrien case R_PPC64_PLT16_HI: 237389857Sobrien case R_PPC64_PLT16_LO: 237489857Sobrien case R_PPC64_PLT32: 237589857Sobrien case R_PPC64_PLT64: 237689857Sobrien if (r_symndx >= symtab_hdr->sh_info) 237789857Sobrien { 237889857Sobrien h = sym_hashes[r_symndx - symtab_hdr->sh_info]; 237989857Sobrien if (h->plt.refcount > 0) 238089857Sobrien h->plt.refcount--; 238189857Sobrien } 238289857Sobrien break; 238389857Sobrien 238489857Sobrien case R_PPC64_REL24: 238589857Sobrien if (r_symndx >= symtab_hdr->sh_info) 238689857Sobrien { 238789857Sobrien h = sym_hashes[r_symndx - symtab_hdr->sh_info]; 238889857Sobrien if (h->plt.refcount > 0) 238989857Sobrien h->plt.refcount--; 239089857Sobrien } 239189857Sobrien break; 239289857Sobrien 239389857Sobrien case R_PPC64_REL14: 239489857Sobrien case R_PPC64_REL14_BRNTAKEN: 239589857Sobrien case R_PPC64_REL14_BRTAKEN: 239689857Sobrien case R_PPC64_REL32: 239789857Sobrien case R_PPC64_REL64: 239889857Sobrien if (r_symndx >= symtab_hdr->sh_info) 239989857Sobrien { 240089857Sobrien struct ppc_link_hash_entry *eh; 240189857Sobrien struct ppc_dyn_relocs **pp; 240289857Sobrien struct ppc_dyn_relocs *p; 240389857Sobrien 240489857Sobrien h = sym_hashes[r_symndx - symtab_hdr->sh_info]; 240589857Sobrien eh = (struct ppc_link_hash_entry *) h; 240689857Sobrien 240789857Sobrien for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next) 240889857Sobrien if (p->sec == sec) 240989857Sobrien { 241089857Sobrien p->pc_count -= 1; 241189857Sobrien p->count -= 1; 241289857Sobrien if (p->count == 0) 241389857Sobrien *pp = p->next; 241489857Sobrien break; 241589857Sobrien } 241689857Sobrien } 241789857Sobrien break; 241889857Sobrien 241989857Sobrien case R_PPC64_ADDR14: 242089857Sobrien case R_PPC64_ADDR14_BRNTAKEN: 242189857Sobrien case R_PPC64_ADDR14_BRTAKEN: 242289857Sobrien case R_PPC64_ADDR16: 242389857Sobrien case R_PPC64_ADDR16_DS: 242489857Sobrien case R_PPC64_ADDR16_HA: 242589857Sobrien case R_PPC64_ADDR16_HI: 242689857Sobrien case R_PPC64_ADDR16_HIGHER: 242789857Sobrien case R_PPC64_ADDR16_HIGHERA: 242889857Sobrien case R_PPC64_ADDR16_HIGHEST: 242989857Sobrien case R_PPC64_ADDR16_HIGHESTA: 243089857Sobrien case R_PPC64_ADDR16_LO: 243189857Sobrien case R_PPC64_ADDR16_LO_DS: 243289857Sobrien case R_PPC64_ADDR24: 243389857Sobrien case R_PPC64_ADDR30: 243489857Sobrien case R_PPC64_ADDR32: 243589857Sobrien case R_PPC64_ADDR64: 243689857Sobrien case R_PPC64_UADDR16: 243789857Sobrien case R_PPC64_UADDR32: 243889857Sobrien case R_PPC64_UADDR64: 243989857Sobrien case R_PPC64_TOC: 244089857Sobrien if (r_symndx >= symtab_hdr->sh_info) 244189857Sobrien { 244289857Sobrien struct ppc_link_hash_entry *eh; 244389857Sobrien struct ppc_dyn_relocs **pp; 244489857Sobrien struct ppc_dyn_relocs *p; 244589857Sobrien 244689857Sobrien h = sym_hashes[r_symndx - symtab_hdr->sh_info]; 244789857Sobrien eh = (struct ppc_link_hash_entry *) h; 244889857Sobrien 244989857Sobrien for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next) 245089857Sobrien if (p->sec == sec) 245189857Sobrien { 245289857Sobrien p->count -= 1; 245389857Sobrien if (p->count == 0) 245489857Sobrien *pp = p->next; 245589857Sobrien break; 245689857Sobrien } 245789857Sobrien } 245889857Sobrien break; 245989857Sobrien 246089857Sobrien default: 246189857Sobrien break; 246289857Sobrien } 246389857Sobrien } 246489857Sobrien return true; 246589857Sobrien} 246689857Sobrien 246789857Sobrien/* Called via elf_link_hash_traverse to transfer dynamic linking 246889857Sobrien information on function code symbol entries to their corresponding 246989857Sobrien function descriptor symbol entries. */ 247089857Sobrienstatic boolean 247189857Sobrienfunc_desc_adjust (h, inf) 247289857Sobrien struct elf_link_hash_entry *h; 247389857Sobrien PTR inf; 247489857Sobrien{ 247589857Sobrien struct bfd_link_info *info; 247689857Sobrien struct ppc_link_hash_table *htab; 247789857Sobrien 247889857Sobrien if (h->root.type == bfd_link_hash_indirect 247989857Sobrien || h->root.type == bfd_link_hash_warning) 248089857Sobrien return true; 248189857Sobrien 248289857Sobrien info = (struct bfd_link_info *) inf; 248389857Sobrien htab = ppc_hash_table (info); 248489857Sobrien 248589857Sobrien /* If this is a function code symbol, transfer dynamic linking 248689857Sobrien information to the function descriptor symbol. */ 248789857Sobrien if (!((struct ppc_link_hash_entry *) h)->is_func) 248889857Sobrien return true; 248989857Sobrien 249089857Sobrien if (h->plt.refcount > 0 249189857Sobrien && h->root.root.string[0] == '.' 249289857Sobrien && h->root.root.string[1] != '\0') 249389857Sobrien { 249489857Sobrien struct elf_link_hash_entry *fdh; 249589857Sobrien boolean force_local; 249689857Sobrien 249789857Sobrien /* Find the corresponding function descriptor symbol. Create it 249889857Sobrien as undefined if necessary. */ 249989857Sobrien 250089857Sobrien fdh = elf_link_hash_lookup (&htab->elf, h->root.root.string + 1, 250189857Sobrien false, false, true); 250289857Sobrien 250389857Sobrien if (fdh == NULL && info->shared) 250489857Sobrien { 250589857Sobrien bfd *abfd; 250689857Sobrien asymbol *newsym; 250789857Sobrien 250889857Sobrien /* Create it as undefined. */ 250989857Sobrien if (h->root.type == bfd_link_hash_undefined 251089857Sobrien || h->root.type == bfd_link_hash_undefweak) 251189857Sobrien abfd = h->root.u.undef.abfd; 251289857Sobrien else if (h->root.type == bfd_link_hash_defined 251389857Sobrien || h->root.type == bfd_link_hash_defweak) 251489857Sobrien abfd = h->root.u.def.section->owner; 251589857Sobrien else 251689857Sobrien abort (); 251789857Sobrien newsym = bfd_make_empty_symbol (abfd); 251889857Sobrien newsym->name = h->root.root.string + 1; 251989857Sobrien newsym->section = bfd_und_section_ptr; 252089857Sobrien newsym->value = 0; 252189857Sobrien newsym->flags = BSF_OBJECT; 252289857Sobrien if (h->root.type == bfd_link_hash_undefweak) 252389857Sobrien newsym->flags |= BSF_WEAK; 252489857Sobrien 252589857Sobrien if ( !(_bfd_generic_link_add_one_symbol 252689857Sobrien (info, abfd, newsym->name, newsym->flags, 252789857Sobrien newsym->section, newsym->value, NULL, false, false, 252889857Sobrien (struct bfd_link_hash_entry **) &fdh))) 252989857Sobrien { 253089857Sobrien return false; 253189857Sobrien } 253289857Sobrien } 253389857Sobrien 253489857Sobrien if (fdh != NULL 253589857Sobrien && (fdh->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0 253689857Sobrien && (info->shared 253789857Sobrien || (fdh->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0 253889857Sobrien || (fdh->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) != 0)) 253989857Sobrien { 254089857Sobrien if (fdh->dynindx == -1) 254189857Sobrien if (! bfd_elf64_link_record_dynamic_symbol (info, fdh)) 254289857Sobrien return false; 254389857Sobrien fdh->plt.refcount = h->plt.refcount; 254489857Sobrien fdh->elf_link_hash_flags |= (h->elf_link_hash_flags 254589857Sobrien & (ELF_LINK_HASH_REF_REGULAR 254689857Sobrien | ELF_LINK_HASH_REF_DYNAMIC 254789857Sobrien | ELF_LINK_HASH_REF_REGULAR_NONWEAK 254889857Sobrien | ELF_LINK_NON_GOT_REF)); 254989857Sobrien fdh->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; 255089857Sobrien ((struct ppc_link_hash_entry *) fdh)->is_func_descriptor = 1; 255189857Sobrien fdh->root.root.string = h->root.root.string + 1; 255289857Sobrien } 255389857Sobrien 255489857Sobrien /* Now that the info is on the function descriptor, clear the 255589857Sobrien function code sym info. Any function code syms for which we 255689857Sobrien don't have a definition in a regular file, we force local. 255789857Sobrien This prevents a shared library from exporting syms that have 255889857Sobrien been imported from another library. Function code syms that 255989857Sobrien are really in the library we must leave global to prevent the 256089857Sobrien linker dragging a definition in from a static library. */ 256189857Sobrien force_local = (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0; 256289857Sobrien _bfd_elf_link_hash_hide_symbol (info, h, force_local); 256389857Sobrien } 256489857Sobrien 256589857Sobrien return true; 256689857Sobrien} 256789857Sobrien 256889857Sobrien/* Called near the start of bfd_elf_size_dynamic_sections. We use 256989857Sobrien this hook to transfer dynamic linking information gathered so far 257089857Sobrien on function code symbol entries, to their corresponding function 257189857Sobrien descriptor symbol entries. */ 257289857Sobrienstatic boolean 257389857Sobrienppc64_elf_func_desc_adjust (obfd, info) 257489857Sobrien bfd *obfd ATTRIBUTE_UNUSED; 257589857Sobrien struct bfd_link_info *info; 257689857Sobrien{ 257789857Sobrien struct ppc_link_hash_table *htab; 257889857Sobrien 257989857Sobrien htab = ppc_hash_table (info); 258089857Sobrien elf_link_hash_traverse (&htab->elf, func_desc_adjust, (PTR) info); 258189857Sobrien return true; 258289857Sobrien} 258389857Sobrien 258489857Sobrien/* Adjust a symbol defined by a dynamic object and referenced by a 258589857Sobrien regular object. The current definition is in some section of the 258689857Sobrien dynamic object, but we're not including those sections. We have to 258789857Sobrien change the definition to something the rest of the link can 258889857Sobrien understand. */ 258989857Sobrien 259089857Sobrienstatic boolean 259189857Sobrienppc64_elf_adjust_dynamic_symbol (info, h) 259289857Sobrien struct bfd_link_info *info; 259389857Sobrien struct elf_link_hash_entry *h; 259489857Sobrien{ 259589857Sobrien struct ppc_link_hash_table *htab; 259689857Sobrien struct ppc_link_hash_entry * eh; 259789857Sobrien struct ppc_dyn_relocs *p; 259889857Sobrien asection *s; 259989857Sobrien unsigned int power_of_two; 260089857Sobrien 260189857Sobrien htab = ppc_hash_table (info); 260289857Sobrien 260389857Sobrien /* Deal with function syms. */ 260489857Sobrien if (h->type == STT_FUNC 260589857Sobrien || (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0) 260689857Sobrien { 260789857Sobrien /* Clear procedure linkage table information for any symbol that 260889857Sobrien won't need a .plt entry. */ 260989857Sobrien if (!((struct ppc_link_hash_entry *) h)->is_func_descriptor 261089857Sobrien || h->plt.refcount <= 0 261189857Sobrien || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0 261289857Sobrien || (! info->shared 261389857Sobrien && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) == 0 261489857Sobrien && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) == 0)) 261589857Sobrien { 261689857Sobrien h->plt.offset = (bfd_vma) -1; 261789857Sobrien h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; 261889857Sobrien } 261989857Sobrien return true; 262089857Sobrien } 262189857Sobrien else 262289857Sobrien h->plt.offset = (bfd_vma) -1; 262389857Sobrien 262489857Sobrien /* If this is a weak symbol, and there is a real definition, the 262589857Sobrien processor independent code will have arranged for us to see the 262689857Sobrien real definition first, and we can just use the same value. */ 262789857Sobrien if (h->weakdef != NULL) 262889857Sobrien { 262989857Sobrien BFD_ASSERT (h->weakdef->root.type == bfd_link_hash_defined 263089857Sobrien || h->weakdef->root.type == bfd_link_hash_defweak); 263189857Sobrien h->root.u.def.section = h->weakdef->root.u.def.section; 263289857Sobrien h->root.u.def.value = h->weakdef->root.u.def.value; 263389857Sobrien return true; 263489857Sobrien } 263589857Sobrien 263689857Sobrien /* This is a reference to a symbol defined by a dynamic object which 263789857Sobrien is not a function. */ 263889857Sobrien 263989857Sobrien /* If we are creating a shared library, we must presume that the 264089857Sobrien only references to the symbol are via the global offset table. 264189857Sobrien For such cases we need not do anything here; the relocations will 264289857Sobrien be handled correctly by relocate_section. */ 264389857Sobrien if (info->shared) 264489857Sobrien return true; 264589857Sobrien 264689857Sobrien /* If there are no references to this symbol that do not use the 264789857Sobrien GOT, we don't need to generate a copy reloc. */ 264889857Sobrien if ((h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0) 264989857Sobrien return true; 265089857Sobrien 265189857Sobrien eh = (struct ppc_link_hash_entry *) h; 265289857Sobrien for (p = eh->dyn_relocs; p != NULL; p = p->next) 265389857Sobrien { 265489857Sobrien s = p->sec->output_section; 265589857Sobrien if (s != NULL && (s->flags & SEC_READONLY) != 0) 265689857Sobrien break; 265789857Sobrien } 265889857Sobrien 265989857Sobrien /* If we didn't find any dynamic relocs in read-only sections, then 266089857Sobrien we'll be keeping the dynamic relocs and avoiding the copy reloc. */ 266189857Sobrien if (p == NULL) 266289857Sobrien { 266389857Sobrien h->elf_link_hash_flags &= ~ELF_LINK_NON_GOT_REF; 266489857Sobrien return true; 266589857Sobrien } 266689857Sobrien 266789857Sobrien /* We must allocate the symbol in our .dynbss section, which will 266889857Sobrien become part of the .bss section of the executable. There will be 266989857Sobrien an entry for this symbol in the .dynsym section. The dynamic 267089857Sobrien object will contain position independent code, so all references 267189857Sobrien from the dynamic object to this symbol will go through the global 267289857Sobrien offset table. The dynamic linker will use the .dynsym entry to 267389857Sobrien determine the address it must put in the global offset table, so 267489857Sobrien both the dynamic object and the regular object will refer to the 267589857Sobrien same memory location for the variable. */ 267689857Sobrien 267789857Sobrien /* We must generate a R_PPC_COPY reloc to tell the dynamic linker to 267889857Sobrien copy the initial value out of the dynamic object and into the 267989857Sobrien runtime process image. We need to remember the offset into the 268089857Sobrien .rela.bss section we are going to use. */ 268189857Sobrien if ((h->root.u.def.section->flags & SEC_ALLOC) != 0) 268289857Sobrien { 268389857Sobrien htab->srelbss->_raw_size += sizeof (Elf64_External_Rela); 268489857Sobrien h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_COPY; 268589857Sobrien } 268689857Sobrien 268789857Sobrien /* We need to figure out the alignment required for this symbol. I 268889857Sobrien have no idea how ELF linkers handle this. */ 268989857Sobrien power_of_two = bfd_log2 (h->size); 269089857Sobrien if (power_of_two > 4) 269189857Sobrien power_of_two = 4; 269289857Sobrien 269389857Sobrien /* Apply the required alignment. */ 269489857Sobrien s = htab->sdynbss; 269589857Sobrien s->_raw_size = BFD_ALIGN (s->_raw_size, (bfd_size_type) (1 << power_of_two)); 269689857Sobrien if (power_of_two > bfd_get_section_alignment (htab->elf.dynobj, s)) 269789857Sobrien { 269889857Sobrien if (! bfd_set_section_alignment (htab->elf.dynobj, s, power_of_two)) 269989857Sobrien return false; 270089857Sobrien } 270189857Sobrien 270289857Sobrien /* Define the symbol as being at this point in the section. */ 270389857Sobrien h->root.u.def.section = s; 270489857Sobrien h->root.u.def.value = s->_raw_size; 270589857Sobrien 270689857Sobrien /* Increment the section size to make room for the symbol. */ 270789857Sobrien s->_raw_size += h->size; 270889857Sobrien 270989857Sobrien return true; 271089857Sobrien} 271189857Sobrien 271289857Sobrien/* If given a function descriptor symbol, hide both the function code 271389857Sobrien sym and the descriptor. */ 271489857Sobrienstatic void 271589857Sobrienppc64_elf_hide_symbol (info, h, force_local) 271689857Sobrien struct bfd_link_info *info; 271789857Sobrien struct elf_link_hash_entry *h; 271889857Sobrien boolean force_local; 271989857Sobrien{ 272089857Sobrien _bfd_elf_link_hash_hide_symbol (info, h, force_local); 272189857Sobrien 272289857Sobrien if (((struct ppc_link_hash_entry *) h)->is_func_descriptor) 272389857Sobrien { 272489857Sobrien const char *name; 272589857Sobrien struct elf_link_hash_entry *fh; 272689857Sobrien struct ppc_link_hash_table *htab; 272789857Sobrien 272889857Sobrien name = h->root.root.string - 1; 272989857Sobrien htab = ppc_hash_table (info); 273089857Sobrien fh = elf_link_hash_lookup (&htab->elf, name, false, false, false); 273189857Sobrien if (fh != NULL) 273289857Sobrien _bfd_elf_link_hash_hide_symbol (info, fh, force_local); 273389857Sobrien } 273489857Sobrien} 273589857Sobrien 273689857Sobrien/* This is the condition under which ppc64_elf_finish_dynamic_symbol 273789857Sobrien will be called from elflink.h. If elflink.h doesn't call our 273889857Sobrien finish_dynamic_symbol routine, we'll need to do something about 273989857Sobrien initializing any .plt and .got entries in ppc64_elf_relocate_section. */ 274089857Sobrien#define WILL_CALL_FINISH_DYNAMIC_SYMBOL(DYN, INFO, H) \ 274189857Sobrien ((DYN) \ 274289857Sobrien && ((INFO)->shared \ 274389857Sobrien || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) \ 274489857Sobrien && ((H)->dynindx != -1 \ 274589857Sobrien || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0)) 274689857Sobrien 274789857Sobrien/* Allocate space in .plt, .got and associated reloc sections for 274889857Sobrien dynamic relocs. */ 274989857Sobrien 275089857Sobrienstatic boolean 275189857Sobrienallocate_dynrelocs (h, inf) 275289857Sobrien struct elf_link_hash_entry *h; 275389857Sobrien PTR inf; 275489857Sobrien{ 275589857Sobrien struct bfd_link_info *info; 275689857Sobrien struct ppc_link_hash_table *htab; 275789857Sobrien asection *s; 275889857Sobrien struct ppc_link_hash_entry *eh; 275989857Sobrien struct ppc_dyn_relocs *p; 276089857Sobrien 276189857Sobrien if (h->root.type == bfd_link_hash_indirect 276289857Sobrien || h->root.type == bfd_link_hash_warning) 276389857Sobrien return true; 276489857Sobrien 276589857Sobrien info = (struct bfd_link_info *) inf; 276689857Sobrien htab = ppc_hash_table (info); 276789857Sobrien 276889857Sobrien if (htab->elf.dynamic_sections_created 276989857Sobrien && h->plt.refcount > 0 277089857Sobrien && h->dynindx != -1) 277189857Sobrien { 277289857Sobrien BFD_ASSERT (((struct ppc_link_hash_entry *) h)->is_func_descriptor); 277389857Sobrien 277489857Sobrien if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info, h)) 277589857Sobrien { 277689857Sobrien /* If this is the first .plt entry, make room for the special 277789857Sobrien first entry. */ 277889857Sobrien s = htab->splt; 277989857Sobrien if (s->_raw_size == 0) 278089857Sobrien s->_raw_size += PLT_INITIAL_ENTRY_SIZE; 278189857Sobrien 278289857Sobrien h->plt.offset = s->_raw_size; 278389857Sobrien 278489857Sobrien /* Make room for this entry. */ 278589857Sobrien s->_raw_size += PLT_ENTRY_SIZE; 278689857Sobrien 278789857Sobrien /* Make room for the .stub and .glink code. */ 278889857Sobrien s = htab->sstub; 278989857Sobrien s->_raw_size += PLT_CALL_STUB_SIZE; 279089857Sobrien 279189857Sobrien s = htab->sglink; 279289857Sobrien if (s->_raw_size == 0) 279389857Sobrien s->_raw_size += GLINK_CALL_STUB_SIZE; 279489857Sobrien /* We need bigger stubs past index 32767. */ 279589857Sobrien if (s->_raw_size >= GLINK_CALL_STUB_SIZE + 32768*2*4) 279689857Sobrien s->_raw_size += 4; 279789857Sobrien s->_raw_size += 2*4; 279889857Sobrien 279989857Sobrien /* We also need to make an entry in the .rela.plt section. */ 280089857Sobrien s = htab->srelplt; 280189857Sobrien s->_raw_size += sizeof (Elf64_External_Rela); 280289857Sobrien } 280389857Sobrien else 280489857Sobrien { 280589857Sobrien h->plt.offset = (bfd_vma) -1; 280689857Sobrien h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; 280789857Sobrien } 280889857Sobrien } 280989857Sobrien else 281089857Sobrien { 281189857Sobrien h->plt.offset = (bfd_vma) -1; 281289857Sobrien h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; 281389857Sobrien } 281489857Sobrien 281589857Sobrien if (h->got.refcount > 0) 281689857Sobrien { 281789857Sobrien boolean dyn; 281889857Sobrien 281989857Sobrien /* Make sure this symbol is output as a dynamic symbol. 282089857Sobrien Undefined weak syms won't yet be marked as dynamic. */ 282189857Sobrien if (h->dynindx == -1 282289857Sobrien && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) 282389857Sobrien { 282489857Sobrien if (! bfd_elf64_link_record_dynamic_symbol (info, h)) 282589857Sobrien return false; 282689857Sobrien } 282789857Sobrien 282889857Sobrien s = htab->sgot; 282989857Sobrien h->got.offset = s->_raw_size; 283089857Sobrien s->_raw_size += 8; 283189857Sobrien dyn = htab->elf.dynamic_sections_created; 283289857Sobrien if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h)) 283389857Sobrien htab->srelgot->_raw_size += sizeof (Elf64_External_Rela); 283489857Sobrien } 283589857Sobrien else 283689857Sobrien h->got.offset = (bfd_vma) -1; 283789857Sobrien 283889857Sobrien eh = (struct ppc_link_hash_entry *) h; 283989857Sobrien if (eh->dyn_relocs == NULL) 284089857Sobrien return true; 284189857Sobrien 284289857Sobrien /* In the shared -Bsymbolic case, discard space allocated for 284389857Sobrien dynamic pc-relative relocs against symbols which turn out to be 284489857Sobrien defined in regular objects. For the normal shared case, discard 284589857Sobrien space for relocs that have become local due to symbol visibility 284689857Sobrien changes. */ 284789857Sobrien 284889857Sobrien if (info->shared) 284989857Sobrien { 285089857Sobrien if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0 285189857Sobrien && ((h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0 285289857Sobrien || info->symbolic)) 285389857Sobrien { 285489857Sobrien struct ppc_dyn_relocs **pp; 285589857Sobrien 285689857Sobrien for (pp = &eh->dyn_relocs; (p = *pp) != NULL; ) 285789857Sobrien { 285889857Sobrien p->count -= p->pc_count; 285989857Sobrien p->pc_count = 0; 286089857Sobrien if (p->count == 0) 286189857Sobrien *pp = p->next; 286289857Sobrien else 286389857Sobrien pp = &p->next; 286489857Sobrien } 286589857Sobrien } 286689857Sobrien } 286789857Sobrien else 286889857Sobrien { 286989857Sobrien /* For the non-shared case, discard space for relocs against 287089857Sobrien symbols which turn out to need copy relocs or are not 287189857Sobrien dynamic. */ 287289857Sobrien 287389857Sobrien if ((h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0 287489857Sobrien && (((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0 287589857Sobrien && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) 287689857Sobrien || (htab->elf.dynamic_sections_created 287789857Sobrien && (h->root.type == bfd_link_hash_undefweak 287889857Sobrien || h->root.type == bfd_link_hash_undefined)))) 287989857Sobrien { 288089857Sobrien /* Make sure this symbol is output as a dynamic symbol. 288189857Sobrien Undefined weak syms won't yet be marked as dynamic. */ 288289857Sobrien if (h->dynindx == -1 288389857Sobrien && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) 288489857Sobrien { 288589857Sobrien if (! bfd_elf64_link_record_dynamic_symbol (info, h)) 288689857Sobrien return false; 288789857Sobrien } 288889857Sobrien 288989857Sobrien /* If that succeeded, we know we'll be keeping all the 289089857Sobrien relocs. */ 289189857Sobrien if (h->dynindx != -1) 289289857Sobrien goto keep; 289389857Sobrien } 289489857Sobrien 289589857Sobrien eh->dyn_relocs = NULL; 289689857Sobrien 289789857Sobrien keep: ; 289889857Sobrien } 289989857Sobrien 290089857Sobrien /* Finally, allocate space. */ 290189857Sobrien for (p = eh->dyn_relocs; p != NULL; p = p->next) 290289857Sobrien { 290389857Sobrien asection *sreloc = elf_section_data (p->sec)->sreloc; 290489857Sobrien sreloc->_raw_size += p->count * sizeof (Elf64_External_Rela); 290589857Sobrien } 290689857Sobrien 290789857Sobrien return true; 290889857Sobrien} 290989857Sobrien 291089857Sobrien/* Find any dynamic relocs that apply to read-only sections. */ 291189857Sobrien 291289857Sobrienstatic boolean 291389857Sobrienreadonly_dynrelocs (h, inf) 291489857Sobrien struct elf_link_hash_entry *h; 291589857Sobrien PTR inf; 291689857Sobrien{ 291789857Sobrien struct ppc_link_hash_entry *eh; 291889857Sobrien struct ppc_dyn_relocs *p; 291989857Sobrien 292089857Sobrien eh = (struct ppc_link_hash_entry *) h; 292189857Sobrien for (p = eh->dyn_relocs; p != NULL; p = p->next) 292289857Sobrien { 292389857Sobrien asection *s = p->sec->output_section; 292489857Sobrien 292589857Sobrien if (s != NULL && (s->flags & SEC_READONLY) != 0) 292689857Sobrien { 292789857Sobrien struct bfd_link_info *info = (struct bfd_link_info *) inf; 292889857Sobrien 292989857Sobrien info->flags |= DF_TEXTREL; 293089857Sobrien 293189857Sobrien /* Not an error, just cut short the traversal. */ 293289857Sobrien return false; 293389857Sobrien } 293489857Sobrien } 293589857Sobrien return true; 293689857Sobrien} 293789857Sobrien 293889857Sobrien/* Set the sizes of the dynamic sections. */ 293989857Sobrien 294089857Sobrienstatic boolean 294189857Sobrienppc64_elf_size_dynamic_sections (output_bfd, info) 294289857Sobrien bfd *output_bfd ATTRIBUTE_UNUSED; 294389857Sobrien struct bfd_link_info *info; 294489857Sobrien{ 294589857Sobrien struct ppc_link_hash_table *htab; 294689857Sobrien bfd *dynobj; 294789857Sobrien asection *s; 294889857Sobrien boolean relocs; 294989857Sobrien bfd *ibfd; 295089857Sobrien 295189857Sobrien htab = ppc_hash_table (info); 295289857Sobrien dynobj = htab->elf.dynobj; 295389857Sobrien if (dynobj == NULL) 295489857Sobrien abort (); 295589857Sobrien 295689857Sobrien if (htab->elf.dynamic_sections_created) 295789857Sobrien { 295889857Sobrien /* Set the contents of the .interp section to the interpreter. */ 295989857Sobrien if (! info->shared) 296089857Sobrien { 296189857Sobrien s = bfd_get_section_by_name (dynobj, ".interp"); 296289857Sobrien if (s == NULL) 296389857Sobrien abort (); 296489857Sobrien s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER; 296589857Sobrien s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER; 296689857Sobrien } 296789857Sobrien } 296889857Sobrien 296989857Sobrien /* Set up .got offsets for local syms, and space for local dynamic 297089857Sobrien relocs. */ 297189857Sobrien for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) 297289857Sobrien { 297389857Sobrien bfd_signed_vma *local_got; 297489857Sobrien bfd_signed_vma *end_local_got; 297589857Sobrien bfd_size_type locsymcount; 297689857Sobrien Elf_Internal_Shdr *symtab_hdr; 297789857Sobrien asection *srel; 297889857Sobrien 297989857Sobrien if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour) 298089857Sobrien continue; 298189857Sobrien 298289857Sobrien for (s = ibfd->sections; s != NULL; s = s->next) 298389857Sobrien { 298489857Sobrien struct ppc_dyn_relocs *p; 298589857Sobrien 298689857Sobrien for (p = *((struct ppc_dyn_relocs **) 298789857Sobrien &elf_section_data (s)->local_dynrel); 298889857Sobrien p != NULL; 298989857Sobrien p = p->next) 299089857Sobrien { 299189857Sobrien if (!bfd_is_abs_section (p->sec) 299289857Sobrien && bfd_is_abs_section (p->sec->output_section)) 299389857Sobrien { 299489857Sobrien /* Input section has been discarded, either because 299589857Sobrien it is a copy of a linkonce section or due to 299689857Sobrien linker script /DISCARD/, so we'll be discarding 299789857Sobrien the relocs too. */ 299889857Sobrien } 299989857Sobrien else 300089857Sobrien { 300189857Sobrien srel = elf_section_data (p->sec)->sreloc; 300289857Sobrien srel->_raw_size += p->count * sizeof (Elf64_External_Rela); 300389857Sobrien } 300489857Sobrien } 300589857Sobrien } 300689857Sobrien 300789857Sobrien local_got = elf_local_got_refcounts (ibfd); 300889857Sobrien if (!local_got) 300989857Sobrien continue; 301089857Sobrien 301189857Sobrien symtab_hdr = &elf_tdata (ibfd)->symtab_hdr; 301289857Sobrien locsymcount = symtab_hdr->sh_info; 301389857Sobrien end_local_got = local_got + locsymcount; 301489857Sobrien s = htab->sgot; 301589857Sobrien srel = htab->srelgot; 301689857Sobrien for (; local_got < end_local_got; ++local_got) 301789857Sobrien { 301889857Sobrien if (*local_got > 0) 301989857Sobrien { 302089857Sobrien *local_got = s->_raw_size; 302189857Sobrien s->_raw_size += 8; 302289857Sobrien if (info->shared) 302389857Sobrien srel->_raw_size += sizeof (Elf64_External_Rela); 302489857Sobrien } 302589857Sobrien else 302689857Sobrien *local_got = (bfd_vma) -1; 302789857Sobrien } 302889857Sobrien } 302989857Sobrien 303089857Sobrien /* Allocate global sym .plt and .got entries, and space for global 303189857Sobrien sym dynamic relocs. */ 303289857Sobrien elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, (PTR) info); 303389857Sobrien 303489857Sobrien /* We now have determined the sizes of the various dynamic sections. 303589857Sobrien Allocate memory for them. */ 303689857Sobrien relocs = false; 303789857Sobrien for (s = dynobj->sections; s != NULL; s = s->next) 303889857Sobrien { 303989857Sobrien bfd_vma size; 304089857Sobrien 304189857Sobrien if ((s->flags & SEC_LINKER_CREATED) == 0) 304289857Sobrien continue; 304389857Sobrien 304489857Sobrien if (s == htab->splt 304589857Sobrien || s == htab->sgot 304689857Sobrien || s == htab->sstub 304789857Sobrien || s == htab->sglink) 304889857Sobrien { 304989857Sobrien /* Strip this section if we don't need it; see the 305089857Sobrien comment below. */ 305189857Sobrien } 305289857Sobrien else if (strncmp (bfd_get_section_name (dynobj, s), ".rela", 5) == 0) 305389857Sobrien { 305489857Sobrien if (s->_raw_size == 0) 305589857Sobrien { 305689857Sobrien /* If we don't need this section, strip it from the 305789857Sobrien output file. This is mostly to handle .rela.bss and 305889857Sobrien .rela.plt. We must create both sections in 305989857Sobrien create_dynamic_sections, because they must be created 306089857Sobrien before the linker maps input sections to output 306189857Sobrien sections. The linker does that before 306289857Sobrien adjust_dynamic_symbol is called, and it is that 306389857Sobrien function which decides whether anything needs to go 306489857Sobrien into these sections. */ 306589857Sobrien } 306689857Sobrien else 306789857Sobrien { 306889857Sobrien if (s != htab->srelplt) 306989857Sobrien relocs = true; 307089857Sobrien 307189857Sobrien /* We use the reloc_count field as a counter if we need 307289857Sobrien to copy relocs into the output file. */ 307389857Sobrien s->reloc_count = 0; 307489857Sobrien } 307589857Sobrien } 307689857Sobrien else 307789857Sobrien { 307889857Sobrien /* It's not one of our sections, so don't allocate space. */ 307989857Sobrien continue; 308089857Sobrien } 308189857Sobrien 308289857Sobrien if (s->_raw_size == 0) 308389857Sobrien { 308489857Sobrien _bfd_strip_section_from_output (info, s); 308589857Sobrien continue; 308689857Sobrien } 308789857Sobrien 308889857Sobrien /* Allocate memory for the section contents. We use bfd_zalloc 308989857Sobrien here in case unused entries are not reclaimed before the 309089857Sobrien section's contents are written out. This should not happen, 309189857Sobrien but this way if it does, we get a R_PPC64_NONE reloc instead 309289857Sobrien of garbage. */ 309389857Sobrien size = s->_raw_size; 309489857Sobrien if (s == htab->sstub) 309589857Sobrien { 309689857Sobrien /* .stub may grow. Allocate enough for the maximum growth. */ 309789857Sobrien size += (size + 65536 + 65535) / 65536 * 4; 309889857Sobrien } 309989857Sobrien s->contents = (bfd_byte *) bfd_zalloc (dynobj, size); 310089857Sobrien if (s->contents == NULL) 310189857Sobrien return false; 310289857Sobrien } 310389857Sobrien 310489857Sobrien if (htab->elf.dynamic_sections_created) 310589857Sobrien { 310689857Sobrien /* Add some entries to the .dynamic section. We fill in the 310789857Sobrien values later, in ppc64_elf_finish_dynamic_sections, but we 310889857Sobrien must add the entries now so that we get the correct size for 310989857Sobrien the .dynamic section. The DT_DEBUG entry is filled in by the 311089857Sobrien dynamic linker and used by the debugger. */ 311189857Sobrien#define add_dynamic_entry(TAG, VAL) \ 311289857Sobrien bfd_elf64_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL)) 311389857Sobrien 311489857Sobrien if (!info->shared) 311589857Sobrien { 311689857Sobrien if (!add_dynamic_entry (DT_DEBUG, 0)) 311789857Sobrien return false; 311889857Sobrien } 311989857Sobrien 312089857Sobrien if (htab->splt->_raw_size != 0) 312189857Sobrien { 312289857Sobrien if (!add_dynamic_entry (DT_PLTGOT, 0) 312389857Sobrien || !add_dynamic_entry (DT_PLTRELSZ, 0) 312489857Sobrien || !add_dynamic_entry (DT_PLTREL, DT_RELA) 312589857Sobrien || !add_dynamic_entry (DT_JMPREL, 0) 312689857Sobrien || !add_dynamic_entry (DT_PPC64_GLINK, 0)) 312789857Sobrien return false; 312889857Sobrien } 312989857Sobrien 313089857Sobrien if (relocs) 313189857Sobrien { 313289857Sobrien if (!add_dynamic_entry (DT_RELA, 0) 313389857Sobrien || !add_dynamic_entry (DT_RELASZ, 0) 313489857Sobrien || !add_dynamic_entry (DT_RELAENT, sizeof (Elf64_External_Rela))) 313589857Sobrien return false; 313689857Sobrien 313789857Sobrien /* If any dynamic relocs apply to a read-only section, 313889857Sobrien then we need a DT_TEXTREL entry. */ 313989857Sobrien elf_link_hash_traverse (&htab->elf, readonly_dynrelocs, (PTR) info); 314089857Sobrien 314189857Sobrien if ((info->flags & DF_TEXTREL) != 0) 314289857Sobrien { 314389857Sobrien if (!add_dynamic_entry (DT_TEXTREL, 0)) 314489857Sobrien return false; 314589857Sobrien } 314689857Sobrien } 314789857Sobrien } 314889857Sobrien#undef add_dynamic_entry 314989857Sobrien 315089857Sobrien return true; 315189857Sobrien} 315289857Sobrien 315389857Sobrien/* Called after we have seen all the input files/sections, but before 315489857Sobrien final symbol resolution and section placement has been determined. 315589857Sobrien 315689857Sobrien We use this hook to provide a value for TOCstart, which we store in 315789857Sobrien the output bfd elf_gp. */ 315889857Sobrien 315989857Sobrienboolean 316089857Sobrienppc64_elf_set_toc (obfd, info) 316189857Sobrien bfd *obfd; 316289857Sobrien struct bfd_link_info *info; 316389857Sobrien{ 316489857Sobrien if (!info->relocateable) 316589857Sobrien { 316689857Sobrien asection *s; 316789857Sobrien bfd_vma TOCstart; 316889857Sobrien 316989857Sobrien /* The TOC consists of sections .got, .toc, .tocbss, .plt in that 317089857Sobrien order. The TOC starts where the first of these sections starts. */ 317189857Sobrien s = bfd_get_section_by_name (obfd, ".got"); 317289857Sobrien if (s == NULL) 317389857Sobrien s = bfd_get_section_by_name (obfd, ".toc"); 317489857Sobrien if (s == NULL) 317589857Sobrien s = bfd_get_section_by_name (obfd, ".tocbss"); 317689857Sobrien if (s == NULL) 317789857Sobrien s = bfd_get_section_by_name (obfd, ".plt"); 317889857Sobrien if (s == NULL) 317989857Sobrien { 318089857Sobrien /* This may happen for 318189857Sobrien o references to TOC base (SYM@toc / TOC[tc0]) without a 318289857Sobrien .toc directive 318389857Sobrien o bad linker script 318489857Sobrien o --gc-sections and empty TOC sections 318589857Sobrien 318689857Sobrien FIXME: Warn user? */ 318789857Sobrien 318889857Sobrien /* Look for a likely section. We probably won't even be 318989857Sobrien using TOCstart. */ 319089857Sobrien for (s = obfd->sections; s != NULL; s = s->next) 319189857Sobrien if ((s->flags & (SEC_ALLOC | SEC_SMALL_DATA | SEC_READONLY)) 319289857Sobrien == (SEC_ALLOC | SEC_SMALL_DATA)) 319389857Sobrien break; 319489857Sobrien if (s == NULL) 319589857Sobrien for (s = obfd->sections; s != NULL; s = s->next) 319689857Sobrien if ((s->flags & (SEC_ALLOC | SEC_SMALL_DATA)) 319789857Sobrien == (SEC_ALLOC | SEC_SMALL_DATA)) 319889857Sobrien break; 319989857Sobrien if (s == NULL) 320089857Sobrien for (s = obfd->sections; s != NULL; s = s->next) 320189857Sobrien if ((s->flags & (SEC_ALLOC | SEC_READONLY)) == SEC_ALLOC) 320289857Sobrien break; 320389857Sobrien if (s == NULL) 320489857Sobrien for (s = obfd->sections; s != NULL; s = s->next) 320589857Sobrien if ((s->flags & SEC_ALLOC) == SEC_ALLOC) 320689857Sobrien break; 320789857Sobrien } 320889857Sobrien 320989857Sobrien TOCstart = 0; 321089857Sobrien if (s != NULL) 321189857Sobrien TOCstart = s->output_section->vma + s->output_offset; 321289857Sobrien 321389857Sobrien elf_gp (obfd) = TOCstart; 321489857Sobrien } 321589857Sobrien return true; 321689857Sobrien} 321789857Sobrien 321889857Sobrien/* PowerPC64 .plt entries are 24 bytes long, which doesn't divide 321989857Sobrien evenly into 64k. Sometimes with a large enough .plt, we'll need to 322089857Sobrien use offsets differing in the high 16 bits when accessing a .plt 322189857Sobrien entry from a .plt call stub. This function adjusts the size of 322289857Sobrien .stub to accommodate the extra stub instruction needed in such 322389857Sobrien cases. */ 322489857Sobrien 322589857Sobrienboolean 322689857Sobrienppc64_elf_size_stubs (obfd, info, changed) 322789857Sobrien bfd *obfd; 322889857Sobrien struct bfd_link_info *info; 322989857Sobrien int *changed; 323089857Sobrien{ 323189857Sobrien struct ppc_link_hash_table *htab = ppc_hash_table (info); 323289857Sobrien bfd_vma plt_offset, next_64k; 323389857Sobrien long base, num, extra; 323489857Sobrien 323589857Sobrien /* .plt and .stub should be both present, or both absent. */ 323689857Sobrien if ((htab->splt == NULL || htab->splt->_raw_size == 0) 323789857Sobrien != (htab->sstub == NULL || htab->sstub->_raw_size == 0)) 323889857Sobrien abort (); 323989857Sobrien 324089857Sobrien /* If no .plt, then nothing to do. */ 324189857Sobrien if (htab->splt == NULL || htab->splt->_raw_size == 0) 324289857Sobrien return true; 324389857Sobrien 324489857Sobrien plt_offset = (htab->splt->output_section->vma 324589857Sobrien + htab->splt->output_offset 324689857Sobrien - elf_gp (obfd)); 324789857Sobrien next_64k = (plt_offset + 65535) & -65536; 324889857Sobrien 324989857Sobrien /* If the .plt doesn't have any entries crossing a 64k boundary, 325089857Sobrien then there is no need for bigger stubs. */ 325189857Sobrien if (next_64k <= plt_offset + htab->splt->_raw_size) 325289857Sobrien return true; 325389857Sobrien 325489857Sobrien /* OK, so we have at least one transition. Since .plt entries are 325589857Sobrien 24 bytes long, we'll strike it lucky every 3*64k, with the 64k 325689857Sobrien boundary between .plt entries. */ 325789857Sobrien base = next_64k / 65536; 325889857Sobrien num = (plt_offset + htab->splt->_raw_size - next_64k) / 65536; 325989857Sobrien extra = (base % 3 + num + 1) * 2 / 3; 326089857Sobrien 326189857Sobrien /* Allow one extra instruction for each EXTRA. The change in .stub 326289857Sobrien may change the location of .toc and .plt. .toc and .plt ought to 326389857Sobrien move as a group, but someone might be playing with eg. .plt 326489857Sobrien alignment, so don't allow .stub size to decrease. */ 326589857Sobrien if (htab->sstub->_cooked_size < htab->sstub->_raw_size + extra * 4) 326689857Sobrien { 326789857Sobrien htab->sstub->_cooked_size = htab->sstub->_raw_size + extra * 4; 326889857Sobrien *changed = true; 326989857Sobrien } 327089857Sobrien return true; 327189857Sobrien} 327289857Sobrien 327389857Sobrien/* Build a .plt call stub. */ 327489857Sobrien 327589857Sobrienstatic bfd_byte * 327689857Sobrienbuild_plt_stub (obfd, p, offset, glink) 327789857Sobrien bfd *obfd; 327889857Sobrien bfd_byte *p; 327989857Sobrien int offset; 328089857Sobrien int glink; 328189857Sobrien{ 328289857Sobrien#define PPC_LO(v) ((v) & 0xffff) 328389857Sobrien#define PPC_HI(v) (((v) >> 16) & 0xffff) 328489857Sobrien#define PPC_HA(v) PPC_HI ((v) + 0x8000) 328589857Sobrien 328689857Sobrien if (glink) 328789857Sobrien bfd_put_32 (obfd, LD_R2_40R1, p), p += 4; 328889857Sobrien bfd_put_32 (obfd, ADDIS_R12_R2 | PPC_HA (offset), p), p += 4; 328989857Sobrien if (!glink) 329089857Sobrien bfd_put_32 (obfd, STD_R2_40R1, p), p += 4; 329189857Sobrien bfd_put_32 (obfd, LD_R11_0R12 | PPC_LO (offset), p), p += 4; 329289857Sobrien if (PPC_HA (offset + 8) != PPC_HA (offset)) 329389857Sobrien bfd_put_32 (obfd, ADDIS_R12_R12_1, p), p += 4; 329489857Sobrien offset += 8; 329589857Sobrien bfd_put_32 (obfd, LD_R2_0R12 | PPC_LO (offset), p), p += 4; 329689857Sobrien if (PPC_HA (offset + 8) != PPC_HA (offset)) 329789857Sobrien bfd_put_32 (obfd, ADDIS_R12_R12_1, p), p += 4; 329889857Sobrien offset += 8; 329989857Sobrien bfd_put_32 (obfd, MTCTR_R11, p), p += 4; 330089857Sobrien bfd_put_32 (obfd, LD_R11_0R12 | PPC_LO (offset), p), p += 4; 330189857Sobrien bfd_put_32 (obfd, BCTR, p), p += 4; 330289857Sobrien return p; 330389857Sobrien} 330489857Sobrien 330589857Sobrien/* Build the stubs for one function call. */ 330689857Sobrien 330789857Sobrienstatic boolean 330889857Sobrienbuild_one_stub (h, inf) 330989857Sobrien struct elf_link_hash_entry *h; 331089857Sobrien PTR inf; 331189857Sobrien{ 331289857Sobrien struct bfd_link_info *info; 331389857Sobrien struct ppc_link_hash_table *htab; 331489857Sobrien 331589857Sobrien if (h->root.type == bfd_link_hash_indirect 331689857Sobrien || h->root.type == bfd_link_hash_warning) 331789857Sobrien return true; 331889857Sobrien 331989857Sobrien info = (struct bfd_link_info *) inf; 332089857Sobrien htab = ppc_hash_table (info); 332189857Sobrien 332289857Sobrien if (htab->elf.dynamic_sections_created 332389857Sobrien && h->plt.offset != (bfd_vma) -1 332489857Sobrien && ((struct ppc_link_hash_entry *) h)->is_func_descriptor) 332589857Sobrien { 332689857Sobrien struct elf_link_hash_entry *fh; 332789857Sobrien asection *s; 332889857Sobrien bfd_vma plt_r2; 332989857Sobrien bfd_byte *p; 333089857Sobrien unsigned int indx; 333189857Sobrien 333289857Sobrien fh = elf_link_hash_lookup (&htab->elf, h->root.root.string - 1, 333389857Sobrien false, false, true); 333489857Sobrien 333589857Sobrien if (fh == NULL) 333689857Sobrien abort (); 333789857Sobrien 333889857Sobrien BFD_ASSERT (((struct ppc_link_hash_entry *) fh)->is_func); 333989857Sobrien 334089857Sobrien /* Build the .plt call stub. */ 334189857Sobrien plt_r2 = (htab->splt->output_section->vma 334289857Sobrien + htab->splt->output_offset 334389857Sobrien + h->plt.offset 334489857Sobrien - elf_gp (htab->splt->output_section->owner) 334589857Sobrien - TOC_BASE_OFF); 334689857Sobrien 334789857Sobrien if (plt_r2 + 0x80000000 > 0xffffffff 334889857Sobrien || (plt_r2 & 3) != 0) 334989857Sobrien { 335089857Sobrien (*_bfd_error_handler) 335189857Sobrien (_("linkage table error against `%s'"), 335289857Sobrien h->root.root.string); 335389857Sobrien bfd_set_error (bfd_error_bad_value); 335489857Sobrien htab->plt_overflow = true; 335589857Sobrien return false; 335689857Sobrien } 335789857Sobrien 335889857Sobrien s = htab->sstub; 335989857Sobrien /* Steal plt.offset to store the stub offset. */ 336089857Sobrien fh->plt.offset = s->_cooked_size; 336189857Sobrien p = s->contents + s->_cooked_size; 336289857Sobrien p = build_plt_stub (s->owner, p, (int) plt_r2, 0); 336389857Sobrien s->_cooked_size = p - s->contents; 336489857Sobrien 336589857Sobrien /* Build the .glink lazy link call stub. */ 336689857Sobrien s = htab->sglink; 336789857Sobrien p = s->contents + s->_cooked_size; 336889857Sobrien indx = s->reloc_count; 336989857Sobrien if (indx < 0x8000) 337089857Sobrien { 337189857Sobrien bfd_put_32 (s->owner, LI_R0_0 | indx, p); 337289857Sobrien p += 4; 337389857Sobrien } 337489857Sobrien else 337589857Sobrien { 337689857Sobrien bfd_put_32 (s->owner, LIS_R0_0 | PPC_HI (indx), p); 337789857Sobrien p += 4; 337889857Sobrien bfd_put_32 (s->owner, ORI_R0_R0_0 | PPC_LO (indx), p); 337989857Sobrien p += 4; 338089857Sobrien } 338189857Sobrien bfd_put_32 (s->owner, B_DOT | ((s->contents - p) & 0x3fffffc), p); 338289857Sobrien p += 4; 338389857Sobrien s->_cooked_size = p - s->contents; 338489857Sobrien s->reloc_count += 1; 338589857Sobrien } 338689857Sobrien return true; 338789857Sobrien} 338889857Sobrien 338989857Sobrienboolean 339089857Sobrienppc64_elf_build_stubs (obfd, info) 339189857Sobrien bfd *obfd; 339289857Sobrien struct bfd_link_info *info; 339389857Sobrien{ 339489857Sobrien struct ppc_link_hash_table *htab = ppc_hash_table (info); 339589857Sobrien bfd_vma old_stub_size; 339689857Sobrien bfd_vma plt_r2; 339789857Sobrien bfd_byte *p; 339889857Sobrien 339989857Sobrien /* If no .plt stubs, then nothing to do. */ 340089857Sobrien if (htab->sstub == NULL || htab->sstub->_raw_size == 0) 340189857Sobrien return true; 340289857Sobrien 340389857Sobrien old_stub_size = htab->sstub->_cooked_size; 340489857Sobrien htab->sstub->_cooked_size = 0; 340589857Sobrien 340689857Sobrien /* Build the .glink plt call stub. */ 340789857Sobrien plt_r2 = (htab->splt->output_section->vma 340889857Sobrien + htab->splt->output_offset 340989857Sobrien - elf_gp (obfd) 341089857Sobrien - TOC_BASE_OFF); 341189857Sobrien p = htab->sglink->contents; 341289857Sobrien p = build_plt_stub (htab->sglink->owner, p, (int) plt_r2, 1); 341389857Sobrien while (p - htab->sglink->contents < GLINK_CALL_STUB_SIZE) 341489857Sobrien { 341589857Sobrien bfd_put_32 (htab->sglink->owner, NOP, p); 341689857Sobrien p += 4; 341789857Sobrien } 341889857Sobrien htab->sglink->_cooked_size = p - htab->sglink->contents; 341989857Sobrien 342089857Sobrien /* Use reloc_count to count entries. */ 342189857Sobrien htab->sglink->reloc_count = 0; 342289857Sobrien 342389857Sobrien elf_link_hash_traverse (&htab->elf, build_one_stub, (PTR) info); 342489857Sobrien htab->sglink->reloc_count = 0; 342589857Sobrien 342689857Sobrien if (htab->plt_overflow) 342789857Sobrien return false; 342889857Sobrien 342989857Sobrien if (old_stub_size != htab->sstub->_cooked_size 343089857Sobrien || htab->sglink->_raw_size != htab->sglink->_cooked_size) 343189857Sobrien { 343289857Sobrien (*_bfd_error_handler) 343389857Sobrien (_("stub section size doesn't match calculated size")); 343489857Sobrien bfd_set_error (bfd_error_bad_value); 343589857Sobrien return false; 343689857Sobrien } 343789857Sobrien return true; 343889857Sobrien} 343989857Sobrien 344089857Sobrien/* Set up any other section flags and such that may be necessary. */ 344189857Sobrien 344289857Sobrienstatic boolean 344389857Sobrienppc64_elf_fake_sections (abfd, shdr, asect) 344489857Sobrien bfd *abfd ATTRIBUTE_UNUSED; 344589857Sobrien Elf64_Internal_Shdr *shdr; 344689857Sobrien asection *asect; 344789857Sobrien{ 344889857Sobrien if ((asect->flags & SEC_EXCLUDE) != 0) 344989857Sobrien shdr->sh_flags |= SHF_EXCLUDE; 345089857Sobrien 345189857Sobrien if ((asect->flags & SEC_SORT_ENTRIES) != 0) 345289857Sobrien shdr->sh_type = SHT_ORDERED; 345389857Sobrien 345489857Sobrien return true; 345589857Sobrien} 345689857Sobrien 345789857Sobrien/* The RELOCATE_SECTION function is called by the ELF backend linker 345889857Sobrien to handle the relocations for a section. 345989857Sobrien 346089857Sobrien The relocs are always passed as Rela structures; if the section 346189857Sobrien actually uses Rel structures, the r_addend field will always be 346289857Sobrien zero. 346389857Sobrien 346489857Sobrien This function is responsible for adjust the section contents as 346589857Sobrien necessary, and (if using Rela relocs and generating a 346689857Sobrien relocateable output file) adjusting the reloc addend as 346789857Sobrien necessary. 346889857Sobrien 346989857Sobrien This function does not have to worry about setting the reloc 347089857Sobrien address or the reloc symbol index. 347189857Sobrien 347289857Sobrien LOCAL_SYMS is a pointer to the swapped in local symbols. 347389857Sobrien 347489857Sobrien LOCAL_SECTIONS is an array giving the section in the input file 347589857Sobrien corresponding to the st_shndx field of each local symbol. 347689857Sobrien 347789857Sobrien The global hash table entry for the global symbols can be found 347889857Sobrien via elf_sym_hashes (input_bfd). 347989857Sobrien 348089857Sobrien When generating relocateable output, this function must handle 348189857Sobrien STB_LOCAL/STT_SECTION symbols specially. The output symbol is 348289857Sobrien going to be the section symbol corresponding to the output 348389857Sobrien section, which means that the addend must be adjusted 348489857Sobrien accordingly. */ 348589857Sobrien 348689857Sobrienstatic boolean 348789857Sobrienppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, 348889857Sobrien contents, relocs, local_syms, local_sections) 348989857Sobrien bfd *output_bfd; 349089857Sobrien struct bfd_link_info *info; 349189857Sobrien bfd *input_bfd; 349289857Sobrien asection *input_section; 349389857Sobrien bfd_byte *contents; 349489857Sobrien Elf_Internal_Rela *relocs; 349589857Sobrien Elf_Internal_Sym *local_syms; 349689857Sobrien asection **local_sections; 349789857Sobrien{ 349889857Sobrien struct ppc_link_hash_table *htab; 349989857Sobrien Elf_Internal_Shdr *symtab_hdr; 350089857Sobrien struct elf_link_hash_entry **sym_hashes; 350189857Sobrien Elf_Internal_Rela *rel; 350289857Sobrien Elf_Internal_Rela *relend; 350389857Sobrien bfd_vma *local_got_offsets; 350489857Sobrien bfd_vma TOCstart; 350589857Sobrien boolean ret = true; 350689857Sobrien boolean is_opd; 350789857Sobrien 350889857Sobrien /* Initialize howto table if needed. */ 350989857Sobrien if (!ppc64_elf_howto_table[R_PPC64_ADDR32]) 351089857Sobrien ppc_howto_init (); 351189857Sobrien 351289857Sobrien htab = ppc_hash_table (info); 351389857Sobrien local_got_offsets = elf_local_got_offsets (input_bfd); 351489857Sobrien TOCstart = elf_gp (output_bfd); 351589857Sobrien symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; 351689857Sobrien sym_hashes = elf_sym_hashes (input_bfd); 351789857Sobrien is_opd = strcmp (bfd_get_section_name (abfd, input_section), ".opd") == 0; 351889857Sobrien 351989857Sobrien rel = relocs; 352089857Sobrien relend = relocs + input_section->reloc_count; 352189857Sobrien for (; rel < relend; rel++) 352289857Sobrien { 352389857Sobrien enum elf_ppc_reloc_type r_type; 352489857Sobrien bfd_vma offset; 352589857Sobrien bfd_vma addend; 352689857Sobrien bfd_reloc_status_type r; 352789857Sobrien Elf_Internal_Sym *sym; 352889857Sobrien asection *sec; 352989857Sobrien struct elf_link_hash_entry *h; 353089857Sobrien const char *sym_name; 353189857Sobrien unsigned long r_symndx; 353289857Sobrien bfd_vma relocation; 353389857Sobrien boolean unresolved_reloc; 353489857Sobrien boolean has_nop; 353589857Sobrien long insn; 353689857Sobrien 353789857Sobrien r_type = (enum elf_ppc_reloc_type) ELF64_R_TYPE (rel->r_info); 353889857Sobrien r_symndx = ELF64_R_SYM (rel->r_info); 353989857Sobrien 354089857Sobrien if (info->relocateable) 354189857Sobrien { 354289857Sobrien /* This is a relocatable link. We don't have to change 354389857Sobrien anything, unless the reloc is against a section symbol, 354489857Sobrien in which case we have to adjust according to where the 354589857Sobrien section symbol winds up in the output section. */ 354689857Sobrien if (r_symndx < symtab_hdr->sh_info) 354789857Sobrien { 354889857Sobrien sym = local_syms + r_symndx; 354989857Sobrien if ((unsigned) ELF_ST_TYPE (sym->st_info) == STT_SECTION) 355089857Sobrien { 355189857Sobrien sec = local_sections[r_symndx]; 355289857Sobrien rel->r_addend += sec->output_offset + sym->st_value; 355389857Sobrien } 355489857Sobrien } 355589857Sobrien continue; 355689857Sobrien } 355789857Sobrien 355889857Sobrien /* This is a final link. */ 355989857Sobrien 356089857Sobrien offset = rel->r_offset; 356189857Sobrien addend = rel->r_addend; 356289857Sobrien r = bfd_reloc_other; 356389857Sobrien sym = (Elf_Internal_Sym *) 0; 356489857Sobrien sec = (asection *) 0; 356589857Sobrien h = (struct elf_link_hash_entry *) 0; 356689857Sobrien sym_name = (const char *) 0; 356789857Sobrien unresolved_reloc = false; 356889857Sobrien 356989857Sobrien if (r_type == R_PPC64_TOC) 357089857Sobrien { 357189857Sobrien /* Relocation value is TOC base. Symbol is ignored. */ 357289857Sobrien relocation = TOCstart + TOC_BASE_OFF; 357389857Sobrien } 357489857Sobrien else if (r_symndx < symtab_hdr->sh_info) 357589857Sobrien { 357689857Sobrien /* It's a local symbol. */ 357789857Sobrien sym = local_syms + r_symndx; 357889857Sobrien sec = local_sections[r_symndx]; 357989857Sobrien sym_name = "<local symbol>"; 358089857Sobrien 358189857Sobrien relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel); 358289857Sobrien addend = rel->r_addend; 358389857Sobrien } 358489857Sobrien else 358589857Sobrien { 358689857Sobrien /* It's a global symbol. */ 358789857Sobrien h = sym_hashes[r_symndx - symtab_hdr->sh_info]; 358889857Sobrien while (h->root.type == bfd_link_hash_indirect 358989857Sobrien || h->root.type == bfd_link_hash_warning) 359089857Sobrien h = (struct elf_link_hash_entry *) h->root.u.i.link; 359189857Sobrien sym_name = h->root.root.string; 359289857Sobrien relocation = 0; 359389857Sobrien if (h->root.type == bfd_link_hash_defined 359489857Sobrien || h->root.type == bfd_link_hash_defweak) 359589857Sobrien { 359689857Sobrien sec = h->root.u.def.section; 359789857Sobrien if (sec->output_section == NULL) 359889857Sobrien /* Set a flag that will be cleared later if we find a 359989857Sobrien relocation value for this symbol. output_section 360089857Sobrien is typically NULL for symbols satisfied by a shared 360189857Sobrien library. */ 360289857Sobrien unresolved_reloc = true; 360389857Sobrien else 360489857Sobrien relocation = (h->root.u.def.value 360589857Sobrien + sec->output_section->vma 360689857Sobrien + sec->output_offset); 360789857Sobrien } 360889857Sobrien else if (h->root.type == bfd_link_hash_undefweak) 360989857Sobrien ; 361089857Sobrien else if (info->shared 361189857Sobrien && (!info->symbolic || info->allow_shlib_undefined) 361289857Sobrien && !info->no_undefined 361389857Sobrien && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT) 361489857Sobrien ; 361589857Sobrien else 361689857Sobrien { 361789857Sobrien if (! ((*info->callbacks->undefined_symbol) 361889857Sobrien (info, h->root.root.string, input_bfd, input_section, 361989857Sobrien offset, (!info->shared 362089857Sobrien || info->no_undefined 362189857Sobrien || ELF_ST_VISIBILITY (h->other))))) 362289857Sobrien return false; 362389857Sobrien } 362489857Sobrien } 362589857Sobrien 362689857Sobrien /* First handle relocations that tweak non-addend part of insn. */ 362789857Sobrien insn = 0; 362889857Sobrien switch (r_type) 362989857Sobrien { 363089857Sobrien default: 363189857Sobrien break; 363289857Sobrien 363389857Sobrien /* Branch taken prediction relocations. */ 363489857Sobrien case R_PPC64_ADDR14_BRTAKEN: 363589857Sobrien case R_PPC64_REL14_BRTAKEN: 363689857Sobrien insn = 0x01 << 21; /* Set 't' bit, lowest bit of BO field. */ 363789857Sobrien /* Fall thru. */ 363889857Sobrien 363989857Sobrien /* Branch not taken prediction relocations. */ 364089857Sobrien case R_PPC64_ADDR14_BRNTAKEN: 364189857Sobrien case R_PPC64_REL14_BRNTAKEN: 364289857Sobrien insn |= bfd_get_32 (output_bfd, contents + offset) & ~(0x01 << 21); 364389857Sobrien /* Set 'a' bit. This is 0b00010 in BO field for branch on CR(BI) 364489857Sobrien insns (BO == 001at or 011at), and 0b01000 for branch on CTR 364589857Sobrien insns (BO == 1a00t or 1a01t). */ 364689857Sobrien if ((insn & (0x14 << 21)) == (0x04 << 21)) 364789857Sobrien insn |= 0x02 << 21; 364889857Sobrien else if ((insn & (0x14 << 21)) == (0x10 << 21)) 364989857Sobrien insn |= 0x08 << 21; 365089857Sobrien else 365189857Sobrien break; 365289857Sobrien 365389857Sobrien bfd_put_32 (output_bfd, (bfd_vma) insn, contents + offset); 365489857Sobrien break; 365589857Sobrien 365689857Sobrien case R_PPC64_REL24: 365789857Sobrien case R_PPC64_ADDR24: 365889857Sobrien /* An ADDR24 or REL24 branching to a linkage function may be 365989857Sobrien followed by a nop that we have to replace with a ld in 366089857Sobrien order to restore the TOC base pointer. Only calls to 366189857Sobrien shared objects need to alter the TOC base. These are 366289857Sobrien recognized by their need for a PLT entry. */ 366389857Sobrien has_nop = 0; 366489857Sobrien if (h != NULL 366589857Sobrien && h->plt.offset != (bfd_vma) -1 366689857Sobrien && htab->sstub != NULL) 366789857Sobrien { 366889857Sobrien /* plt.offset here is the offset into the stub section. */ 366989857Sobrien relocation = (htab->sstub->output_section->vma 367089857Sobrien + htab->sstub->output_offset 367189857Sobrien + h->plt.offset); 367289857Sobrien unresolved_reloc = false; 367389857Sobrien 367489857Sobrien /* Make sure that there really is an instruction after 367589857Sobrien the branch that we can decode. */ 367689857Sobrien if (offset + 8 <= input_section->_cooked_size) 367789857Sobrien { 367889857Sobrien bfd_byte *pnext; 367989857Sobrien 368089857Sobrien pnext = contents + offset + 4; 368189857Sobrien insn = bfd_get_32 (input_bfd, pnext); 368289857Sobrien 368389857Sobrien if (insn == 0x60000000 /* nop (ori r0,r0,0) */ 368489857Sobrien || insn == 0x4def7b82 /* cror 15,15,15 */ 368589857Sobrien || insn == 0x4ffffb82) /* cror 31,31,31 */ 368689857Sobrien { 368789857Sobrien bfd_put_32 (input_bfd, 368889857Sobrien (bfd_vma) 0xe8410028, /* ld r2,40(r1) */ 368989857Sobrien pnext); 369089857Sobrien has_nop = 1; 369189857Sobrien } 369289857Sobrien } 369389857Sobrien } 369489857Sobrien 369589857Sobrien if (h != NULL 369689857Sobrien && h->root.type == bfd_link_hash_undefweak 369789857Sobrien && r_type == R_PPC64_REL24 369889857Sobrien && addend == 0 369989857Sobrien && relocation == 0) 370089857Sobrien { 370189857Sobrien /* Tweak calls to undefined weak functions to behave as 370289857Sobrien if the "called" function immediately returns. We can 370389857Sobrien thus call to a weak function without first checking 370489857Sobrien whether the function is defined. */ 370589857Sobrien relocation = 4; 370689857Sobrien if (has_nop) 370789857Sobrien relocation = 8; 370889857Sobrien } 370989857Sobrien break; 371089857Sobrien } 371189857Sobrien 371289857Sobrien /* Set `addend'. */ 371389857Sobrien switch (r_type) 371489857Sobrien { 371589857Sobrien default: 371689857Sobrien (*_bfd_error_handler) 371789857Sobrien (_("%s: unknown relocation type %d for symbol %s"), 371889857Sobrien bfd_archive_filename (input_bfd), (int) r_type, sym_name); 371989857Sobrien 372089857Sobrien bfd_set_error (bfd_error_bad_value); 372189857Sobrien ret = false; 372289857Sobrien continue; 372389857Sobrien 372489857Sobrien case R_PPC64_NONE: 372589857Sobrien case R_PPC_GNU_VTINHERIT: 372689857Sobrien case R_PPC_GNU_VTENTRY: 372789857Sobrien continue; 372889857Sobrien 372989857Sobrien /* GOT16 relocations. Like an ADDR16 using the symbol's 373089857Sobrien address in the GOT as relocation value instead of the 373189857Sobrien symbols value itself. Also, create a GOT entry for the 373289857Sobrien symbol and put the symbol value there. */ 373389857Sobrien case R_PPC64_GOT16: 373489857Sobrien case R_PPC64_GOT16_LO: 373589857Sobrien case R_PPC64_GOT16_HI: 373689857Sobrien case R_PPC64_GOT16_HA: 373789857Sobrien case R_PPC64_GOT16_DS: 373889857Sobrien case R_PPC64_GOT16_LO_DS: 373989857Sobrien { 374089857Sobrien /* Relocation is to the entry for this symbol in the global 374189857Sobrien offset table. */ 374289857Sobrien bfd_vma off; 374389857Sobrien 374489857Sobrien if (htab->sgot == NULL) 374589857Sobrien abort (); 374689857Sobrien 374789857Sobrien if (h != NULL) 374889857Sobrien { 374989857Sobrien boolean dyn; 375089857Sobrien 375189857Sobrien off = h->got.offset; 375289857Sobrien dyn = htab->elf.dynamic_sections_created; 375389857Sobrien if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h) 375489857Sobrien || (info->shared 375589857Sobrien && (info->symbolic 375689857Sobrien || h->dynindx == -1 375789857Sobrien || (h->elf_link_hash_flags 375889857Sobrien & ELF_LINK_FORCED_LOCAL)) 375989857Sobrien && (h->elf_link_hash_flags 376089857Sobrien & ELF_LINK_HASH_DEF_REGULAR))) 376189857Sobrien { 376289857Sobrien /* This is actually a static link, or it is a 376389857Sobrien -Bsymbolic link and the symbol is defined 376489857Sobrien locally, or the symbol was forced to be local 376589857Sobrien because of a version file. We must initialize 376689857Sobrien this entry in the global offset table. Since the 376789857Sobrien offset must always be a multiple of 8, we use the 376889857Sobrien least significant bit to record whether we have 376989857Sobrien initialized it already. 377089857Sobrien 377189857Sobrien When doing a dynamic link, we create a .rel.got 377289857Sobrien relocation entry to initialize the value. This 377389857Sobrien is done in the finish_dynamic_symbol routine. */ 377489857Sobrien if ((off & 1) != 0) 377589857Sobrien off &= ~1; 377689857Sobrien else 377789857Sobrien { 377889857Sobrien bfd_put_64 (output_bfd, relocation, 377989857Sobrien htab->sgot->contents + off); 378089857Sobrien h->got.offset |= 1; 378189857Sobrien } 378289857Sobrien } 378389857Sobrien else 378489857Sobrien unresolved_reloc = false; 378589857Sobrien } 378689857Sobrien else 378789857Sobrien { 378889857Sobrien if (local_got_offsets == NULL) 378989857Sobrien abort (); 379089857Sobrien 379189857Sobrien off = local_got_offsets[r_symndx]; 379289857Sobrien 379389857Sobrien /* The offset must always be a multiple of 8. We use 379489857Sobrien the least significant bit to record whether we have 379589857Sobrien already processed this entry. */ 379689857Sobrien if ((off & 1) != 0) 379789857Sobrien off &= ~1; 379889857Sobrien else 379989857Sobrien { 380089857Sobrien bfd_put_64 (output_bfd, relocation, 380189857Sobrien htab->sgot->contents + off); 380289857Sobrien 380389857Sobrien if (info->shared) 380489857Sobrien { 380589857Sobrien Elf_Internal_Rela outrel; 380689857Sobrien Elf64_External_Rela *loc; 380789857Sobrien 380889857Sobrien /* We need to generate a R_PPC64_RELATIVE reloc 380989857Sobrien for the dynamic linker. */ 381089857Sobrien outrel.r_offset = (htab->sgot->output_section->vma 381189857Sobrien + htab->sgot->output_offset 381289857Sobrien + off); 381389857Sobrien outrel.r_info = ELF64_R_INFO (0, R_PPC64_RELATIVE); 381489857Sobrien outrel.r_addend = relocation; 381589857Sobrien loc = (Elf64_External_Rela *) htab->srelgot->contents; 381689857Sobrien loc += htab->srelgot->reloc_count++; 381789857Sobrien bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc); 381889857Sobrien } 381989857Sobrien 382089857Sobrien local_got_offsets[r_symndx] |= 1; 382189857Sobrien } 382289857Sobrien } 382389857Sobrien 382489857Sobrien if (off >= (bfd_vma) -2) 382589857Sobrien abort (); 382689857Sobrien 382789857Sobrien relocation = htab->sgot->output_offset + off; 382889857Sobrien 382989857Sobrien /* TOC base (r2) is TOC start plus 0x8000. */ 383089857Sobrien addend -= TOC_BASE_OFF; 383189857Sobrien } 383289857Sobrien break; 383389857Sobrien 383489857Sobrien case R_PPC64_PLT16_HA: 383589857Sobrien case R_PPC64_PLT16_HI: 383689857Sobrien case R_PPC64_PLT16_LO: 383789857Sobrien case R_PPC64_PLT32: 383889857Sobrien case R_PPC64_PLT64: 383989857Sobrien /* Relocation is to the entry for this symbol in the 384089857Sobrien procedure linkage table. */ 384189857Sobrien 384289857Sobrien /* Resolve a PLT reloc against a local symbol directly, 384389857Sobrien without using the procedure linkage table. */ 384489857Sobrien if (h == NULL) 384589857Sobrien break; 384689857Sobrien 384789857Sobrien if (h->plt.offset == (bfd_vma) -1 384889857Sobrien || htab->splt == NULL) 384989857Sobrien { 385089857Sobrien /* We didn't make a PLT entry for this symbol. This 385189857Sobrien happens when statically linking PIC code, or when 385289857Sobrien using -Bsymbolic. */ 385389857Sobrien break; 385489857Sobrien } 385589857Sobrien 385689857Sobrien relocation = (htab->splt->output_section->vma 385789857Sobrien + htab->splt->output_offset 385889857Sobrien + h->plt.offset); 385989857Sobrien unresolved_reloc = false; 386089857Sobrien break; 386189857Sobrien 386289857Sobrien /* TOC16 relocs. We want the offset relative to the TOC base, 386389857Sobrien which is the address of the start of the TOC plus 0x8000. 386489857Sobrien The TOC consists of sections .got, .toc, .tocbss, and .plt, 386589857Sobrien in this order. */ 386689857Sobrien case R_PPC64_TOC16: 386789857Sobrien case R_PPC64_TOC16_LO: 386889857Sobrien case R_PPC64_TOC16_HI: 386989857Sobrien case R_PPC64_TOC16_DS: 387089857Sobrien case R_PPC64_TOC16_LO_DS: 387189857Sobrien case R_PPC64_TOC16_HA: 387289857Sobrien addend -= TOCstart + TOC_BASE_OFF; 387389857Sobrien break; 387489857Sobrien 387589857Sobrien /* Relocate against the beginning of the section. */ 387689857Sobrien case R_PPC64_SECTOFF: 387789857Sobrien case R_PPC64_SECTOFF_LO: 387889857Sobrien case R_PPC64_SECTOFF_HI: 387989857Sobrien case R_PPC64_SECTOFF_DS: 388089857Sobrien case R_PPC64_SECTOFF_LO_DS: 388189857Sobrien case R_PPC64_SECTOFF_HA: 388289857Sobrien if (sec != (asection *) 0) 388389857Sobrien addend -= sec->output_section->vma; 388489857Sobrien break; 388589857Sobrien 388689857Sobrien case R_PPC64_REL24: 388789857Sobrien break; 388889857Sobrien 388989857Sobrien /* Relocations that may need to be propagated if this is a 389089857Sobrien dynamic object. */ 389189857Sobrien case R_PPC64_REL14: 389289857Sobrien case R_PPC64_REL14_BRNTAKEN: 389389857Sobrien case R_PPC64_REL14_BRTAKEN: 389489857Sobrien case R_PPC64_REL32: 389589857Sobrien case R_PPC64_REL64: 389689857Sobrien case R_PPC64_ADDR14: 389789857Sobrien case R_PPC64_ADDR14_BRNTAKEN: 389889857Sobrien case R_PPC64_ADDR14_BRTAKEN: 389989857Sobrien case R_PPC64_ADDR16: 390089857Sobrien case R_PPC64_ADDR16_DS: 390189857Sobrien case R_PPC64_ADDR16_HA: 390289857Sobrien case R_PPC64_ADDR16_HI: 390389857Sobrien case R_PPC64_ADDR16_HIGHER: 390489857Sobrien case R_PPC64_ADDR16_HIGHERA: 390589857Sobrien case R_PPC64_ADDR16_HIGHEST: 390689857Sobrien case R_PPC64_ADDR16_HIGHESTA: 390789857Sobrien case R_PPC64_ADDR16_LO: 390889857Sobrien case R_PPC64_ADDR16_LO_DS: 390989857Sobrien case R_PPC64_ADDR24: 391089857Sobrien case R_PPC64_ADDR30: 391189857Sobrien case R_PPC64_ADDR32: 391289857Sobrien case R_PPC64_ADDR64: 391389857Sobrien case R_PPC64_UADDR16: 391489857Sobrien case R_PPC64_UADDR32: 391589857Sobrien case R_PPC64_UADDR64: 391689857Sobrien /* r_symndx will be zero only for relocs against symbols 391789857Sobrien from removed linkonce sections, or sections discarded by 391889857Sobrien a linker script. */ 391989857Sobrien if (r_symndx == 0) 392089857Sobrien break; 392189857Sobrien /* Fall thru. */ 392289857Sobrien 392389857Sobrien case R_PPC64_TOC: 392489857Sobrien if ((input_section->flags & SEC_ALLOC) == 0) 392589857Sobrien break; 392689857Sobrien 392789857Sobrien if (NO_OPD_RELOCS && is_opd) 392889857Sobrien break; 392989857Sobrien 393089857Sobrien if ((info->shared 393189857Sobrien && (IS_ABSOLUTE_RELOC (r_type) 393289857Sobrien || (h != NULL 393389857Sobrien && h->dynindx != -1 393489857Sobrien && (! info->symbolic 393589857Sobrien || (h->elf_link_hash_flags 393689857Sobrien & ELF_LINK_HASH_DEF_REGULAR) == 0)))) 393789857Sobrien || (!info->shared 393889857Sobrien && h != NULL 393989857Sobrien && h->dynindx != -1 394089857Sobrien && (h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0 394189857Sobrien && (((h->elf_link_hash_flags 394289857Sobrien & ELF_LINK_HASH_DEF_DYNAMIC) != 0 394389857Sobrien && (h->elf_link_hash_flags 394489857Sobrien & ELF_LINK_HASH_DEF_REGULAR) == 0) 394589857Sobrien || h->root.type == bfd_link_hash_undefweak 394689857Sobrien || h->root.type == bfd_link_hash_undefined))) 394789857Sobrien { 394889857Sobrien Elf_Internal_Rela outrel; 394989857Sobrien boolean skip, relocate; 395089857Sobrien asection *sreloc; 395189857Sobrien Elf64_External_Rela *loc; 395289857Sobrien 395389857Sobrien /* When generating a dynamic object, these relocations 395489857Sobrien are copied into the output file to be resolved at run 395589857Sobrien time. */ 395689857Sobrien 395789857Sobrien skip = false; 395889857Sobrien 395989857Sobrien outrel.r_offset = 396089857Sobrien _bfd_elf_section_offset (output_bfd, info, input_section, 396189857Sobrien rel->r_offset); 396289857Sobrien if (outrel.r_offset == (bfd_vma) -1) 396389857Sobrien skip = true; 396489857Sobrien 396589857Sobrien outrel.r_offset += (input_section->output_section->vma 396689857Sobrien + input_section->output_offset); 396789857Sobrien outrel.r_addend = addend; 396889857Sobrien 396989857Sobrien if (skip) 397089857Sobrien { 397189857Sobrien relocate = false; 397289857Sobrien memset (&outrel, 0, sizeof outrel); 397389857Sobrien } 397489857Sobrien else if (h != NULL 397589857Sobrien && h->dynindx != -1 397689857Sobrien && !is_opd 397789857Sobrien && (!IS_ABSOLUTE_RELOC (r_type) 397889857Sobrien || !info->shared 397989857Sobrien || !info->symbolic 398089857Sobrien || (h->elf_link_hash_flags 398189857Sobrien & ELF_LINK_HASH_DEF_REGULAR) == 0)) 398289857Sobrien { 398389857Sobrien relocate = false; 398489857Sobrien outrel.r_info = ELF64_R_INFO (h->dynindx, r_type); 398589857Sobrien } 398689857Sobrien else 398789857Sobrien { 398889857Sobrien /* This symbol is local, or marked to become local, 398989857Sobrien or this is an opd section reloc which must point 399089857Sobrien at a local function. */ 399189857Sobrien outrel.r_addend += relocation; 399289857Sobrien relocate = true; 399389857Sobrien if (r_type == R_PPC64_ADDR64 || r_type == R_PPC64_TOC) 399489857Sobrien { 399589857Sobrien outrel.r_info = ELF64_R_INFO (0, R_PPC64_RELATIVE); 399689857Sobrien } 399789857Sobrien else 399889857Sobrien { 399989857Sobrien long indx = 0; 400089857Sobrien 400189857Sobrien if (bfd_is_abs_section (sec)) 400289857Sobrien ; 400389857Sobrien else if (sec == NULL || sec->owner == NULL) 400489857Sobrien { 400589857Sobrien bfd_set_error (bfd_error_bad_value); 400689857Sobrien return false; 400789857Sobrien } 400889857Sobrien else 400989857Sobrien { 401089857Sobrien asection *osec; 401189857Sobrien 401289857Sobrien osec = sec->output_section; 401389857Sobrien indx = elf_section_data (osec)->dynindx; 401489857Sobrien 401589857Sobrien /* We are turning this relocation into one 401689857Sobrien against a section symbol, so subtract out 401789857Sobrien the output section's address but not the 401889857Sobrien offset of the input section in the output 401989857Sobrien section. */ 402089857Sobrien outrel.r_addend -= osec->vma; 402189857Sobrien } 402289857Sobrien 402389857Sobrien outrel.r_info = ELF64_R_INFO (indx, r_type); 402489857Sobrien } 402589857Sobrien } 402689857Sobrien 402789857Sobrien sreloc = elf_section_data (input_section)->sreloc; 402889857Sobrien if (sreloc == NULL) 402989857Sobrien abort (); 403089857Sobrien 403189857Sobrien loc = (Elf64_External_Rela *) sreloc->contents; 403289857Sobrien loc += sreloc->reloc_count++; 403389857Sobrien bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc); 403489857Sobrien 403589857Sobrien /* If this reloc is against an external symbol, it will 403689857Sobrien be computed at runtime, so there's no need to do 403789857Sobrien anything now. */ 403889857Sobrien if (! relocate) 403989857Sobrien continue; 404089857Sobrien } 404189857Sobrien break; 404289857Sobrien 404389857Sobrien case R_PPC64_COPY: 404489857Sobrien case R_PPC64_GLOB_DAT: 404589857Sobrien case R_PPC64_JMP_SLOT: 404689857Sobrien case R_PPC64_RELATIVE: 404789857Sobrien /* We shouldn't ever see these dynamic relocs in relocatable 404889857Sobrien files. */ 404989857Sobrien /* Fall thru */ 405089857Sobrien 405189857Sobrien case R_PPC64_PLTGOT16: 405289857Sobrien case R_PPC64_PLTGOT16_DS: 405389857Sobrien case R_PPC64_PLTGOT16_HA: 405489857Sobrien case R_PPC64_PLTGOT16_HI: 405589857Sobrien case R_PPC64_PLTGOT16_LO: 405689857Sobrien case R_PPC64_PLTGOT16_LO_DS: 405789857Sobrien case R_PPC64_PLTREL32: 405889857Sobrien case R_PPC64_PLTREL64: 405989857Sobrien /* These ones haven't been implemented yet. */ 406089857Sobrien 406189857Sobrien (*_bfd_error_handler) 406289857Sobrien (_("%s: Relocation %s is not supported for symbol %s."), 406389857Sobrien bfd_archive_filename (input_bfd), 406489857Sobrien ppc64_elf_howto_table[(int) r_type]->name, sym_name); 406589857Sobrien 406689857Sobrien bfd_set_error (bfd_error_invalid_operation); 406789857Sobrien ret = false; 406889857Sobrien continue; 406989857Sobrien } 407089857Sobrien 407189857Sobrien /* Do any further special processing. */ 407289857Sobrien switch (r_type) 407389857Sobrien { 407489857Sobrien default: 407589857Sobrien break; 407689857Sobrien 407789857Sobrien case R_PPC64_ADDR16_HA: 407889857Sobrien case R_PPC64_ADDR16_HIGHERA: 407989857Sobrien case R_PPC64_ADDR16_HIGHESTA: 408089857Sobrien case R_PPC64_PLT16_HA: 408189857Sobrien case R_PPC64_TOC16_HA: 408289857Sobrien case R_PPC64_SECTOFF_HA: 408389857Sobrien /* It's just possible that this symbol is a weak symbol 408489857Sobrien that's not actually defined anywhere. In that case, 408589857Sobrien 'sec' would be NULL, and we should leave the symbol 408689857Sobrien alone (it will be set to zero elsewhere in the link). */ 408789857Sobrien if (sec != NULL) 408889857Sobrien /* Add 0x10000 if sign bit in 0:15 is set. */ 408989857Sobrien addend += ((relocation + addend) & 0x8000) << 1; 409089857Sobrien break; 409189857Sobrien 409289857Sobrien case R_PPC64_ADDR16_DS: 409389857Sobrien case R_PPC64_ADDR16_LO_DS: 409489857Sobrien case R_PPC64_GOT16_DS: 409589857Sobrien case R_PPC64_GOT16_LO_DS: 409689857Sobrien case R_PPC64_PLT16_LO_DS: 409789857Sobrien case R_PPC64_SECTOFF_DS: 409889857Sobrien case R_PPC64_SECTOFF_LO_DS: 409989857Sobrien case R_PPC64_TOC16_DS: 410089857Sobrien case R_PPC64_TOC16_LO_DS: 410189857Sobrien case R_PPC64_PLTGOT16_DS: 410289857Sobrien case R_PPC64_PLTGOT16_LO_DS: 410389857Sobrien if (((relocation + addend) & 3) != 0) 410489857Sobrien { 410589857Sobrien (*_bfd_error_handler) 410689857Sobrien (_("%s: error: relocation %s not a multiple of 4"), 410789857Sobrien bfd_archive_filename (input_bfd), 410889857Sobrien ppc64_elf_howto_table[(int) r_type]->name); 410989857Sobrien bfd_set_error (bfd_error_bad_value); 411089857Sobrien ret = false; 411189857Sobrien continue; 411289857Sobrien } 411389857Sobrien break; 411489857Sobrien } 411589857Sobrien 411689857Sobrien /* FIXME: Why do we allow debugging sections to escape this error? 411789857Sobrien More importantly, why do we not emit dynamic relocs above in 411889857Sobrien debugging sections (which are ! SEC_ALLOC)? If we had 411989857Sobrien emitted the dynamic reloc, we could remove the fudge here. */ 412089857Sobrien if (unresolved_reloc 412189857Sobrien && !(info->shared 412289857Sobrien && (input_section->flags & SEC_DEBUGGING) != 0 412389857Sobrien && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0)) 412489857Sobrien (*_bfd_error_handler) 412589857Sobrien (_("%s(%s+0x%lx): unresolvable relocation against symbol `%s'"), 412689857Sobrien bfd_archive_filename (input_bfd), 412789857Sobrien bfd_get_section_name (input_bfd, input_section), 412889857Sobrien (long) rel->r_offset, 412989857Sobrien h->root.root.string); 413089857Sobrien 413189857Sobrien r = _bfd_final_link_relocate (ppc64_elf_howto_table[(int) r_type], 413289857Sobrien input_bfd, 413389857Sobrien input_section, 413489857Sobrien contents, 413589857Sobrien offset, 413689857Sobrien relocation, 413789857Sobrien addend); 413889857Sobrien 413989857Sobrien if (r == bfd_reloc_ok) 414089857Sobrien ; 414189857Sobrien else if (r == bfd_reloc_overflow) 414289857Sobrien { 414389857Sobrien const char *name; 414489857Sobrien 414589857Sobrien if (h != NULL) 414689857Sobrien { 414789857Sobrien if (h->root.type == bfd_link_hash_undefweak 414889857Sobrien && ppc64_elf_howto_table[(int) r_type]->pc_relative) 414989857Sobrien { 415089857Sobrien /* Assume this is a call protected by other code that 415189857Sobrien detects the symbol is undefined. If this is the case, 415289857Sobrien we can safely ignore the overflow. If not, the 415389857Sobrien program is hosed anyway, and a little warning isn't 415489857Sobrien going to help. */ 415589857Sobrien 415689857Sobrien continue; 415789857Sobrien } 415889857Sobrien 415989857Sobrien name = h->root.root.string; 416089857Sobrien } 416189857Sobrien else 416289857Sobrien { 416389857Sobrien name = bfd_elf_string_from_elf_section (input_bfd, 416489857Sobrien symtab_hdr->sh_link, 416589857Sobrien sym->st_name); 416689857Sobrien if (name == NULL) 416789857Sobrien continue; 416889857Sobrien if (*name == '\0') 416989857Sobrien name = bfd_section_name (input_bfd, sec); 417089857Sobrien } 417189857Sobrien 417289857Sobrien if (! ((*info->callbacks->reloc_overflow) 417389857Sobrien (info, name, ppc64_elf_howto_table[(int) r_type]->name, 417489857Sobrien (bfd_vma) 0, input_bfd, input_section, offset))) 417589857Sobrien return false; 417689857Sobrien } 417789857Sobrien else 417889857Sobrien ret = false; 417989857Sobrien } 418089857Sobrien 418189857Sobrien return ret; 418289857Sobrien} 418389857Sobrien 418489857Sobrien/* Finish up dynamic symbol handling. We set the contents of various 418589857Sobrien dynamic sections here. */ 418689857Sobrien 418789857Sobrienstatic boolean 418889857Sobrienppc64_elf_finish_dynamic_symbol (output_bfd, info, h, sym) 418989857Sobrien bfd *output_bfd; 419089857Sobrien struct bfd_link_info *info; 419189857Sobrien struct elf_link_hash_entry *h; 419289857Sobrien Elf_Internal_Sym *sym; 419389857Sobrien{ 419489857Sobrien struct ppc_link_hash_table *htab; 419589857Sobrien bfd *dynobj; 419689857Sobrien 419789857Sobrien htab = ppc_hash_table (info); 419889857Sobrien dynobj = htab->elf.dynobj; 419989857Sobrien 420089857Sobrien if (h->plt.offset != (bfd_vma) -1 420189857Sobrien && ((struct ppc_link_hash_entry *) h)->is_func_descriptor) 420289857Sobrien { 420389857Sobrien Elf_Internal_Rela rela; 420489857Sobrien Elf64_External_Rela *loc; 420589857Sobrien 420689857Sobrien /* This symbol has an entry in the procedure linkage table. Set 420789857Sobrien it up. */ 420889857Sobrien 420989857Sobrien if (htab->splt == NULL 421089857Sobrien || htab->srelplt == NULL 421189857Sobrien || htab->sglink == NULL) 421289857Sobrien abort (); 421389857Sobrien 421489857Sobrien /* Create a JMP_SLOT reloc to inform the dynamic linker to 421589857Sobrien fill in the PLT entry. */ 421689857Sobrien 421789857Sobrien rela.r_offset = (htab->splt->output_section->vma 421889857Sobrien + htab->splt->output_offset 421989857Sobrien + h->plt.offset); 422089857Sobrien rela.r_info = ELF64_R_INFO (h->dynindx, R_PPC64_JMP_SLOT); 422189857Sobrien rela.r_addend = 0; 422289857Sobrien 422389857Sobrien loc = (Elf64_External_Rela *) htab->srelplt->contents; 422489857Sobrien loc += (h->plt.offset - PLT_INITIAL_ENTRY_SIZE) / PLT_ENTRY_SIZE; 422589857Sobrien bfd_elf64_swap_reloca_out (output_bfd, &rela, loc); 422689857Sobrien } 422789857Sobrien 422889857Sobrien if (h->got.offset != (bfd_vma) -1) 422989857Sobrien { 423089857Sobrien Elf_Internal_Rela rela; 423189857Sobrien Elf64_External_Rela *loc; 423289857Sobrien 423389857Sobrien /* This symbol has an entry in the global offset table. Set it 423489857Sobrien up. */ 423589857Sobrien 423689857Sobrien if (htab->sgot == NULL || htab->srelgot == NULL) 423789857Sobrien abort (); 423889857Sobrien 423989857Sobrien rela.r_offset = (htab->sgot->output_section->vma 424089857Sobrien + htab->sgot->output_offset 424189857Sobrien + (h->got.offset &~ (bfd_vma) 1)); 424289857Sobrien 424389857Sobrien /* If this is a static link, or it is a -Bsymbolic link and the 424489857Sobrien symbol is defined locally or was forced to be local because 424589857Sobrien of a version file, we just want to emit a RELATIVE reloc. 424689857Sobrien The entry in the global offset table will already have been 424789857Sobrien initialized in the relocate_section function. */ 424889857Sobrien if (info->shared 424989857Sobrien && (info->symbolic 425089857Sobrien || h->dynindx == -1 425189857Sobrien || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL)) 425289857Sobrien && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)) 425389857Sobrien { 425489857Sobrien BFD_ASSERT((h->got.offset & 1) != 0); 425589857Sobrien rela.r_info = ELF64_R_INFO (0, R_PPC64_RELATIVE); 425689857Sobrien rela.r_addend = (h->root.u.def.value 425789857Sobrien + h->root.u.def.section->output_section->vma 425889857Sobrien + h->root.u.def.section->output_offset); 425989857Sobrien } 426089857Sobrien else 426189857Sobrien { 426289857Sobrien BFD_ASSERT ((h->got.offset & 1) == 0); 426389857Sobrien bfd_put_64 (output_bfd, (bfd_vma) 0, 426489857Sobrien htab->sgot->contents + h->got.offset); 426589857Sobrien rela.r_info = ELF64_R_INFO (h->dynindx, R_PPC64_GLOB_DAT); 426689857Sobrien rela.r_addend = 0; 426789857Sobrien } 426889857Sobrien 426989857Sobrien loc = (Elf64_External_Rela *) htab->srelgot->contents; 427089857Sobrien loc += htab->srelgot->reloc_count++; 427189857Sobrien bfd_elf64_swap_reloca_out (output_bfd, &rela, loc); 427289857Sobrien } 427389857Sobrien 427489857Sobrien if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_COPY) != 0) 427589857Sobrien { 427689857Sobrien Elf_Internal_Rela rela; 427789857Sobrien Elf64_External_Rela *loc; 427889857Sobrien 427989857Sobrien /* This symbol needs a copy reloc. Set it up. */ 428089857Sobrien 428189857Sobrien if (h->dynindx == -1 428289857Sobrien || (h->root.type != bfd_link_hash_defined 428389857Sobrien && h->root.type != bfd_link_hash_defweak) 428489857Sobrien || htab->srelbss == NULL) 428589857Sobrien abort (); 428689857Sobrien 428789857Sobrien rela.r_offset = (h->root.u.def.value 428889857Sobrien + h->root.u.def.section->output_section->vma 428989857Sobrien + h->root.u.def.section->output_offset); 429089857Sobrien rela.r_info = ELF64_R_INFO (h->dynindx, R_PPC64_COPY); 429189857Sobrien rela.r_addend = 0; 429289857Sobrien loc = (Elf64_External_Rela *) htab->srelbss->contents; 429389857Sobrien loc += htab->srelbss->reloc_count++; 429489857Sobrien bfd_elf64_swap_reloca_out (output_bfd, &rela, loc); 429589857Sobrien } 429689857Sobrien 429789857Sobrien /* Mark some specially defined symbols as absolute. */ 429889857Sobrien if (strcmp (h->root.root.string, "_DYNAMIC") == 0) 429989857Sobrien sym->st_shndx = SHN_ABS; 430089857Sobrien 430189857Sobrien return true; 430289857Sobrien} 430389857Sobrien 430489857Sobrien/* Used to decide how to sort relocs in an optimal manner for the 430589857Sobrien dynamic linker, before writing them out. */ 430689857Sobrien 430789857Sobrienstatic enum elf_reloc_type_class 430889857Sobrienppc64_elf_reloc_type_class (rela) 430989857Sobrien const Elf_Internal_Rela *rela; 431089857Sobrien{ 431189857Sobrien enum elf_ppc_reloc_type r_type; 431289857Sobrien 431389857Sobrien r_type = (enum elf_ppc_reloc_type) ELF64_R_TYPE (rela->r_info); 431489857Sobrien switch (r_type) 431589857Sobrien { 431689857Sobrien case R_PPC64_RELATIVE: 431789857Sobrien return reloc_class_relative; 431889857Sobrien case R_PPC64_JMP_SLOT: 431989857Sobrien return reloc_class_plt; 432089857Sobrien case R_PPC64_COPY: 432189857Sobrien return reloc_class_copy; 432289857Sobrien default: 432389857Sobrien return reloc_class_normal; 432489857Sobrien } 432589857Sobrien} 432689857Sobrien 432789857Sobrien/* Finish up the dynamic sections. */ 432889857Sobrien 432989857Sobrienstatic boolean 433089857Sobrienppc64_elf_finish_dynamic_sections (output_bfd, info) 433189857Sobrien bfd *output_bfd; 433289857Sobrien struct bfd_link_info *info; 433389857Sobrien{ 433489857Sobrien struct ppc_link_hash_table *htab; 433589857Sobrien bfd *dynobj; 433689857Sobrien asection *sdyn; 433789857Sobrien 433889857Sobrien htab = ppc_hash_table (info); 433989857Sobrien dynobj = htab->elf.dynobj; 434089857Sobrien sdyn = bfd_get_section_by_name (dynobj, ".dynamic"); 434189857Sobrien 434289857Sobrien if (htab->elf.dynamic_sections_created) 434389857Sobrien { 434489857Sobrien Elf64_External_Dyn *dyncon, *dynconend; 434589857Sobrien 434689857Sobrien if (sdyn == NULL || htab->sgot == NULL) 434789857Sobrien abort (); 434889857Sobrien 434989857Sobrien dyncon = (Elf64_External_Dyn *) sdyn->contents; 435089857Sobrien dynconend = (Elf64_External_Dyn *) (sdyn->contents + sdyn->_raw_size); 435189857Sobrien for (; dyncon < dynconend; dyncon++) 435289857Sobrien { 435389857Sobrien Elf_Internal_Dyn dyn; 435489857Sobrien 435589857Sobrien bfd_elf64_swap_dyn_in (dynobj, dyncon, &dyn); 435689857Sobrien 435789857Sobrien switch (dyn.d_tag) 435889857Sobrien { 435989857Sobrien default: 436089857Sobrien continue; 436189857Sobrien 436289857Sobrien case DT_PPC64_GLINK: 436389857Sobrien dyn.d_un.d_ptr = (htab->sglink->output_section->vma 436489857Sobrien + htab->sglink->output_offset); 436589857Sobrien break; 436689857Sobrien 436789857Sobrien case DT_PLTGOT: 436889857Sobrien dyn.d_un.d_ptr = (htab->splt->output_section->vma 436989857Sobrien + htab->splt->output_offset); 437089857Sobrien break; 437189857Sobrien 437289857Sobrien case DT_JMPREL: 437389857Sobrien dyn.d_un.d_ptr = (htab->srelplt->output_section->vma 437489857Sobrien + htab->srelplt->output_offset); 437589857Sobrien break; 437689857Sobrien 437789857Sobrien case DT_PLTRELSZ: 437889857Sobrien dyn.d_un.d_val = htab->srelplt->_raw_size; 437989857Sobrien break; 438089857Sobrien 438189857Sobrien case DT_RELASZ: 438289857Sobrien /* Don't count procedure linkage table relocs in the 438389857Sobrien overall reloc count. */ 438489857Sobrien if (htab->srelplt != NULL) 438589857Sobrien dyn.d_un.d_val -= htab->srelplt->_raw_size; 438689857Sobrien break; 438789857Sobrien } 438889857Sobrien 438989857Sobrien bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon); 439089857Sobrien } 439189857Sobrien } 439289857Sobrien 439389857Sobrien if (htab->sgot != NULL && htab->sgot->_raw_size != 0) 439489857Sobrien { 439589857Sobrien /* Fill in the first entry in the global offset table. 439689857Sobrien We use it to hold the link-time TOCbase. */ 439789857Sobrien bfd_put_64 (output_bfd, 439889857Sobrien elf_gp (output_bfd) + TOC_BASE_OFF, 439989857Sobrien htab->sgot->contents); 440089857Sobrien 440189857Sobrien /* Set .got entry size. */ 440289857Sobrien elf_section_data (htab->sgot->output_section)->this_hdr.sh_entsize = 8; 440389857Sobrien } 440489857Sobrien 440589857Sobrien if (htab->splt != NULL && htab->splt->_raw_size != 0) 440689857Sobrien { 440789857Sobrien /* Set .plt entry size. */ 440889857Sobrien elf_section_data (htab->splt->output_section)->this_hdr.sh_entsize 440989857Sobrien = PLT_ENTRY_SIZE; 441089857Sobrien } 441189857Sobrien 441289857Sobrien return true; 441389857Sobrien} 441489857Sobrien 441589857Sobrien#define TARGET_LITTLE_SYM bfd_elf64_powerpcle_vec 441689857Sobrien#define TARGET_LITTLE_NAME "elf64-powerpcle" 441789857Sobrien#define TARGET_BIG_SYM bfd_elf64_powerpc_vec 441889857Sobrien#define TARGET_BIG_NAME "elf64-powerpc" 441989857Sobrien#define ELF_ARCH bfd_arch_powerpc 442089857Sobrien#define ELF_MACHINE_CODE EM_PPC64 442189857Sobrien#define ELF_MAXPAGESIZE 0x10000 442289857Sobrien#define elf_info_to_howto ppc64_elf_info_to_howto 442389857Sobrien 442489857Sobrien#ifdef EM_CYGNUS_POWERPC 442589857Sobrien#define ELF_MACHINE_ALT1 EM_CYGNUS_POWERPC 442689857Sobrien#endif 442789857Sobrien 442889857Sobrien#ifdef EM_PPC_OLD 442989857Sobrien#define ELF_MACHINE_ALT2 EM_PPC_OLD 443089857Sobrien#endif 443189857Sobrien 443289857Sobrien#define elf_backend_want_got_sym 0 443389857Sobrien#define elf_backend_want_plt_sym 0 443489857Sobrien#define elf_backend_plt_alignment 3 443589857Sobrien#define elf_backend_plt_not_loaded 1 443689857Sobrien#define elf_backend_got_symbol_offset 0 443789857Sobrien#define elf_backend_got_header_size 8 443889857Sobrien#define elf_backend_plt_header_size PLT_INITIAL_ENTRY_SIZE 443989857Sobrien#define elf_backend_can_gc_sections 1 444089857Sobrien#define elf_backend_can_refcount 1 444189857Sobrien 444289857Sobrien#define bfd_elf64_bfd_reloc_type_lookup ppc64_elf_reloc_type_lookup 444389857Sobrien#define bfd_elf64_bfd_set_private_flags ppc64_elf_set_private_flags 444489857Sobrien#define bfd_elf64_bfd_merge_private_bfd_data ppc64_elf_merge_private_bfd_data 444589857Sobrien#define bfd_elf64_bfd_link_hash_table_create ppc64_elf_link_hash_table_create 444689857Sobrien 444789857Sobrien#define elf_backend_section_from_shdr ppc64_elf_section_from_shdr 444889857Sobrien#define elf_backend_create_dynamic_sections ppc64_elf_create_dynamic_sections 444989857Sobrien#define elf_backend_copy_indirect_symbol ppc64_elf_copy_indirect_symbol 445089857Sobrien#define elf_backend_check_relocs ppc64_elf_check_relocs 445189857Sobrien#define elf_backend_gc_mark_hook ppc64_elf_gc_mark_hook 445289857Sobrien#define elf_backend_gc_sweep_hook ppc64_elf_gc_sweep_hook 445389857Sobrien#define elf_backend_adjust_dynamic_symbol ppc64_elf_adjust_dynamic_symbol 445489857Sobrien#define elf_backend_hide_symbol ppc64_elf_hide_symbol 445589857Sobrien#define elf_backend_always_size_sections ppc64_elf_func_desc_adjust 445689857Sobrien#define elf_backend_size_dynamic_sections ppc64_elf_size_dynamic_sections 445789857Sobrien#define elf_backend_fake_sections ppc64_elf_fake_sections 445889857Sobrien#define elf_backend_relocate_section ppc64_elf_relocate_section 445989857Sobrien#define elf_backend_finish_dynamic_symbol ppc64_elf_finish_dynamic_symbol 446089857Sobrien#define elf_backend_reloc_type_class ppc64_elf_reloc_type_class 446189857Sobrien#define elf_backend_finish_dynamic_sections ppc64_elf_finish_dynamic_sections 446289857Sobrien 446389857Sobrien#include "elf64-target.h" 4464