189857Sobrien/* PowerPC64-specific support for 64-bit ELF.
2218822Sdim   Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
3130561Sobrien   Free Software Foundation, Inc.
489857Sobrien   Written by Linus Nordberg, Swox AB <info@swox.com>,
589857Sobrien   based on elf32-ppc.c by Ian Lance Taylor.
6130561Sobrien   Largely rewritten by Alan Modra <amodra@bigpond.net.au>
789857Sobrien
8130561Sobrien   This file is part of BFD, the Binary File Descriptor library.
989857Sobrien
10130561Sobrien   This program is free software; you can redistribute it and/or modify
11130561Sobrien   it under the terms of the GNU General Public License as published by
12130561Sobrien   the Free Software Foundation; either version 2 of the License, or
13130561Sobrien   (at your option) any later version.
1489857Sobrien
15130561Sobrien   This program is distributed in the hope that it will be useful,
16130561Sobrien   but WITHOUT ANY WARRANTY; without even the implied warranty of
17130561Sobrien   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18130561Sobrien   GNU General Public License for more details.
1989857Sobrien
20130561Sobrien   You should have received a copy of the GNU General Public License along
21130561Sobrien   with this program; if not, write to the Free Software Foundation, Inc.,
22218822Sdim   51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
2389857Sobrien
24130561Sobrien/* The 64-bit PowerPC ELF ABI may be found at
25130561Sobrien   http://www.linuxbase.org/spec/ELF/ppc64/PPC-elf64abi.txt, and
26130561Sobrien   http://www.linuxbase.org/spec/ELF/ppc64/spec/book1.html  */
2789857Sobrien
28218822Sdim#include "sysdep.h"
29218822Sdim#include <stdarg.h>
3089857Sobrien#include "bfd.h"
3189857Sobrien#include "bfdlink.h"
3289857Sobrien#include "libbfd.h"
3389857Sobrien#include "elf-bfd.h"
34130561Sobrien#include "elf/ppc64.h"
3589857Sobrien#include "elf64-ppc.h"
3689857Sobrien
3799461Sobrienstatic bfd_reloc_status_type ppc64_elf_ha_reloc
38130561Sobrien  (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
39218822Sdimstatic bfd_reloc_status_type ppc64_elf_branch_reloc
40218822Sdim  (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
4199461Sobrienstatic bfd_reloc_status_type ppc64_elf_brtaken_reloc
42130561Sobrien  (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
4399461Sobrienstatic bfd_reloc_status_type ppc64_elf_sectoff_reloc
44130561Sobrien  (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
4599461Sobrienstatic bfd_reloc_status_type ppc64_elf_sectoff_ha_reloc
46130561Sobrien  (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
4799461Sobrienstatic bfd_reloc_status_type ppc64_elf_toc_reloc
48130561Sobrien  (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
4999461Sobrienstatic bfd_reloc_status_type ppc64_elf_toc_ha_reloc
50130561Sobrien  (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
5199461Sobrienstatic bfd_reloc_status_type ppc64_elf_toc64_reloc
52130561Sobrien  (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
5399461Sobrienstatic bfd_reloc_status_type ppc64_elf_unhandled_reloc
54130561Sobrien  (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
55218822Sdimstatic bfd_vma opd_entry_value
56218822Sdim  (asection *, bfd_vma, asection **, bfd_vma *);
5789857Sobrien
58130561Sobrien#define TARGET_LITTLE_SYM	bfd_elf64_powerpcle_vec
59130561Sobrien#define TARGET_LITTLE_NAME	"elf64-powerpcle"
60130561Sobrien#define TARGET_BIG_SYM		bfd_elf64_powerpc_vec
61130561Sobrien#define TARGET_BIG_NAME		"elf64-powerpc"
62130561Sobrien#define ELF_ARCH		bfd_arch_powerpc
63130561Sobrien#define ELF_MACHINE_CODE	EM_PPC64
64130561Sobrien#define ELF_MAXPAGESIZE		0x10000
65218822Sdim#define ELF_COMMONPAGESIZE	0x1000
66130561Sobrien#define elf_info_to_howto	ppc64_elf_info_to_howto
67130561Sobrien
68130561Sobrien#define elf_backend_want_got_sym 0
69130561Sobrien#define elf_backend_want_plt_sym 0
70130561Sobrien#define elf_backend_plt_alignment 3
71130561Sobrien#define elf_backend_plt_not_loaded 1
72130561Sobrien#define elf_backend_got_header_size 8
73130561Sobrien#define elf_backend_can_gc_sections 1
74130561Sobrien#define elf_backend_can_refcount 1
75130561Sobrien#define elf_backend_rela_normal 1
76218822Sdim#define elf_backend_default_execstack 0
77130561Sobrien
78130561Sobrien#define bfd_elf64_mkobject		      ppc64_elf_mkobject
79130561Sobrien#define bfd_elf64_bfd_reloc_type_lookup	      ppc64_elf_reloc_type_lookup
80218822Sdim#define bfd_elf64_bfd_reloc_name_lookup ppc64_elf_reloc_name_lookup
81130561Sobrien#define bfd_elf64_bfd_merge_private_bfd_data  ppc64_elf_merge_private_bfd_data
82130561Sobrien#define bfd_elf64_new_section_hook	      ppc64_elf_new_section_hook
83130561Sobrien#define bfd_elf64_bfd_link_hash_table_create  ppc64_elf_link_hash_table_create
84130561Sobrien#define bfd_elf64_bfd_link_hash_table_free    ppc64_elf_link_hash_table_free
85218822Sdim#define bfd_elf64_get_synthetic_symtab	      ppc64_elf_get_synthetic_symtab
86130561Sobrien
87130561Sobrien#define elf_backend_object_p		      ppc64_elf_object_p
88130561Sobrien#define elf_backend_grok_prstatus	      ppc64_elf_grok_prstatus
89130561Sobrien#define elf_backend_grok_psinfo		      ppc64_elf_grok_psinfo
90218822Sdim#define elf_backend_write_core_note	      ppc64_elf_write_core_note
91130561Sobrien#define elf_backend_create_dynamic_sections   ppc64_elf_create_dynamic_sections
92130561Sobrien#define elf_backend_copy_indirect_symbol      ppc64_elf_copy_indirect_symbol
93130561Sobrien#define elf_backend_add_symbol_hook	      ppc64_elf_add_symbol_hook
94218822Sdim#define elf_backend_check_directives	      ppc64_elf_check_directives
95218822Sdim#define elf_backend_as_needed_cleanup	      ppc64_elf_as_needed_cleanup
96218822Sdim#define elf_backend_archive_symbol_lookup     ppc64_elf_archive_symbol_lookup
97130561Sobrien#define elf_backend_check_relocs	      ppc64_elf_check_relocs
98218822Sdim#define elf_backend_gc_mark_dynamic_ref       ppc64_elf_gc_mark_dynamic_ref
99130561Sobrien#define elf_backend_gc_mark_hook	      ppc64_elf_gc_mark_hook
100130561Sobrien#define elf_backend_gc_sweep_hook	      ppc64_elf_gc_sweep_hook
101130561Sobrien#define elf_backend_adjust_dynamic_symbol     ppc64_elf_adjust_dynamic_symbol
102130561Sobrien#define elf_backend_hide_symbol		      ppc64_elf_hide_symbol
103130561Sobrien#define elf_backend_always_size_sections      ppc64_elf_func_desc_adjust
104130561Sobrien#define elf_backend_size_dynamic_sections     ppc64_elf_size_dynamic_sections
105218822Sdim#define elf_backend_init_index_section	      _bfd_elf_init_2_index_sections
106218822Sdim#define elf_backend_action_discarded	      ppc64_elf_action_discarded
107130561Sobrien#define elf_backend_relocate_section	      ppc64_elf_relocate_section
108130561Sobrien#define elf_backend_finish_dynamic_symbol     ppc64_elf_finish_dynamic_symbol
109130561Sobrien#define elf_backend_reloc_type_class	      ppc64_elf_reloc_type_class
110130561Sobrien#define elf_backend_finish_dynamic_sections   ppc64_elf_finish_dynamic_sections
111130561Sobrien#define elf_backend_link_output_symbol_hook   ppc64_elf_output_symbol_hook
112130561Sobrien#define elf_backend_special_sections	      ppc64_elf_special_sections
113130561Sobrien
11489857Sobrien/* The name of the dynamic interpreter.  This is put in the .interp
11589857Sobrien   section.  */
11689857Sobrien#define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1"
11789857Sobrien
11889857Sobrien/* The size in bytes of an entry in the procedure linkage table.  */
11989857Sobrien#define PLT_ENTRY_SIZE 24
12089857Sobrien
12189857Sobrien/* The initial size of the plt reserved for the dynamic linker.  */
12289857Sobrien#define PLT_INITIAL_ENTRY_SIZE PLT_ENTRY_SIZE
12389857Sobrien
12489857Sobrien/* TOC base pointers offset from start of TOC.  */
125130561Sobrien#define TOC_BASE_OFF	0x8000
12689857Sobrien
127130561Sobrien/* Offset of tp and dtp pointers from start of TLS block.  */
128130561Sobrien#define TP_OFFSET	0x7000
129130561Sobrien#define DTP_OFFSET	0x8000
130130561Sobrien
131130561Sobrien/* .plt call stub instructions.  The normal stub is like this, but
132130561Sobrien   sometimes the .plt entry crosses a 64k boundary and we need to
133130561Sobrien   insert an addis to adjust r12.  */
134130561Sobrien#define PLT_CALL_STUB_SIZE (7*4)
13589857Sobrien#define ADDIS_R12_R2	0x3d820000	/* addis %r12,%r2,xxx@ha     */
13689857Sobrien#define STD_R2_40R1	0xf8410028	/* std	 %r2,40(%r1)	     */
13789857Sobrien#define LD_R11_0R12	0xe96c0000	/* ld	 %r11,xxx+0@l(%r12)  */
13889857Sobrien#define LD_R2_0R12	0xe84c0000	/* ld	 %r2,xxx+8@l(%r12)   */
13989857Sobrien#define MTCTR_R11	0x7d6903a6	/* mtctr %r11		     */
14089857Sobrien					/* ld	 %r11,xxx+16@l(%r12) */
14189857Sobrien#define BCTR		0x4e800420	/* bctr			     */
14289857Sobrien
14389857Sobrien
144218822Sdim#define ADDIS_R12_R12	0x3d8c0000	/* addis %r12,%r12,off@ha  */
145130561Sobrien#define ADDIS_R2_R2	0x3c420000	/* addis %r2,%r2,off@ha  */
146130561Sobrien#define ADDI_R2_R2	0x38420000	/* addi  %r2,%r2,off@l   */
14789857Sobrien
148130561Sobrien#define LD_R2_40R1	0xe8410028	/* ld    %r2,40(%r1)     */
14989857Sobrien
150218822Sdim/* glink call stub instructions.  We enter with the index in R0.  */
151130561Sobrien#define GLINK_CALL_STUB_SIZE (16*4)
152218822Sdim					/* 0:				*/
153218822Sdim					/*  .quad plt0-1f		*/
154218822Sdim					/* __glink:			*/
155218822Sdim#define MFLR_R12	0x7d8802a6	/*  mflr %12			*/
156218822Sdim#define BCL_20_31	0x429f0005	/*  bcl 20,31,1f		*/
157218822Sdim					/* 1:				*/
158218822Sdim#define MFLR_R11	0x7d6802a6	/*  mflr %11			*/
159218822Sdim#define LD_R2_M16R11	0xe84bfff0	/*  ld %2,(0b-1b)(%11)		*/
160218822Sdim#define MTLR_R12	0x7d8803a6	/*  mtlr %12			*/
161218822Sdim#define ADD_R12_R2_R11	0x7d825a14	/*  add %12,%2,%11		*/
162218822Sdim					/*  ld %11,0(%12)		*/
163218822Sdim					/*  ld %2,8(%12)		*/
164218822Sdim					/*  mtctr %11			*/
165218822Sdim					/*  ld %11,16(%12)		*/
166218822Sdim					/*  bctr			*/
16789857Sobrien
16889857Sobrien/* Pad with this.  */
16989857Sobrien#define NOP		0x60000000
17089857Sobrien
17199461Sobrien/* Some other nops.  */
17299461Sobrien#define CROR_151515	0x4def7b82
17399461Sobrien#define CROR_313131	0x4ffffb82
17499461Sobrien
175104834Sobrien/* .glink entries for the first 32k functions are two instructions.  */
17689857Sobrien#define LI_R0_0		0x38000000	/* li    %r0,0		*/
17789857Sobrien#define B_DOT		0x48000000	/* b     .		*/
17889857Sobrien
17989857Sobrien/* After that, we need two instructions to load the index, followed by
18089857Sobrien   a branch.  */
18189857Sobrien#define LIS_R0_0	0x3c000000	/* lis   %r0,0		*/
18289857Sobrien#define ORI_R0_R0_0	0x60000000	/* ori	 %r0,%r0,0	*/
18389857Sobrien
184218822Sdim/* Instructions used by the save and restore reg functions.  */
185218822Sdim#define STD_R0_0R1	0xf8010000	/* std   %r0,0(%r1)	*/
186218822Sdim#define STD_R0_0R12	0xf80c0000	/* std   %r0,0(%r12)	*/
187218822Sdim#define LD_R0_0R1	0xe8010000	/* ld    %r0,0(%r1)	*/
188218822Sdim#define LD_R0_0R12	0xe80c0000	/* ld    %r0,0(%r12)	*/
18992828Sobrien#define STFD_FR0_0R1	0xd8010000	/* stfd  %fr0,0(%r1)	*/
19092828Sobrien#define LFD_FR0_0R1	0xc8010000	/* lfd   %fr0,0(%r1)	*/
191218822Sdim#define LI_R12_0	0x39800000	/* li    %r12,0		*/
192218822Sdim#define STVX_VR0_R12_R0	0x7c0c01ce	/* stvx  %v0,%r12,%r0	*/
193218822Sdim#define LVX_VR0_R12_R0	0x7c0c00ce	/* lvx   %v0,%r12,%r0	*/
194218822Sdim#define MTLR_R0		0x7c0803a6	/* mtlr  %r0		*/
19592828Sobrien#define BLR		0x4e800020	/* blr			*/
19692828Sobrien
19789857Sobrien/* Since .opd is an array of descriptors and each entry will end up
19889857Sobrien   with identical R_PPC64_RELATIVE relocs, there is really no need to
19989857Sobrien   propagate .opd relocs;  The dynamic linker should be taught to
200104834Sobrien   relocate .opd without reloc entries.  */
20189857Sobrien#ifndef NO_OPD_RELOCS
20289857Sobrien#define NO_OPD_RELOCS 0
20389857Sobrien#endif
20489857Sobrien
205104834Sobrien#define ONES(n) (((bfd_vma) 1 << ((n) - 1) << 1) - 1)
206130561Sobrien
20789857Sobrien/* Relocation HOWTO's.  */
208130561Sobrienstatic reloc_howto_type *ppc64_elf_howto_table[(int) R_PPC64_max];
20989857Sobrien
21089857Sobrienstatic reloc_howto_type ppc64_elf_howto_raw[] = {
21189857Sobrien  /* This reloc does nothing.  */
21289857Sobrien  HOWTO (R_PPC64_NONE,		/* type */
21389857Sobrien	 0,			/* rightshift */
214130561Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
215130561Sobrien	 32,			/* bitsize */
216130561Sobrien	 FALSE,			/* pc_relative */
21789857Sobrien	 0,			/* bitpos */
218104834Sobrien	 complain_overflow_dont, /* complain_on_overflow */
21989857Sobrien	 bfd_elf_generic_reloc,	/* special_function */
22089857Sobrien	 "R_PPC64_NONE",	/* name */
221130561Sobrien	 FALSE,			/* partial_inplace */
22289857Sobrien	 0,			/* src_mask */
22389857Sobrien	 0,			/* dst_mask */
224130561Sobrien	 FALSE),		/* pcrel_offset */
22589857Sobrien
22689857Sobrien  /* A standard 32 bit relocation.  */
22789857Sobrien  HOWTO (R_PPC64_ADDR32,	/* type */
22889857Sobrien	 0,			/* rightshift */
22989857Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
23089857Sobrien	 32,			/* bitsize */
231130561Sobrien	 FALSE,			/* pc_relative */
23289857Sobrien	 0,			/* bitpos */
23389857Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
23489857Sobrien	 bfd_elf_generic_reloc,	/* special_function */
23589857Sobrien	 "R_PPC64_ADDR32",	/* name */
236130561Sobrien	 FALSE,			/* partial_inplace */
23789857Sobrien	 0,			/* src_mask */
23889857Sobrien	 0xffffffff,		/* dst_mask */
239130561Sobrien	 FALSE),		/* pcrel_offset */
24089857Sobrien
24189857Sobrien  /* An absolute 26 bit branch; the lower two bits must be zero.
24289857Sobrien     FIXME: we don't check that, we just clear them.  */
24389857Sobrien  HOWTO (R_PPC64_ADDR24,	/* type */
24489857Sobrien	 0,			/* rightshift */
24589857Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
24689857Sobrien	 26,			/* bitsize */
247130561Sobrien	 FALSE,			/* pc_relative */
24889857Sobrien	 0,			/* bitpos */
24989857Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
25089857Sobrien	 bfd_elf_generic_reloc,	/* special_function */
25189857Sobrien	 "R_PPC64_ADDR24",	/* name */
252130561Sobrien	 FALSE,			/* partial_inplace */
25389857Sobrien	 0,			/* src_mask */
254104834Sobrien	 0x03fffffc,		/* dst_mask */
255130561Sobrien	 FALSE),		/* pcrel_offset */
25689857Sobrien
25789857Sobrien  /* A standard 16 bit relocation.  */
25889857Sobrien  HOWTO (R_PPC64_ADDR16,	/* type */
25989857Sobrien	 0,			/* rightshift */
26089857Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
26189857Sobrien	 16,			/* bitsize */
262130561Sobrien	 FALSE,			/* pc_relative */
26389857Sobrien	 0,			/* bitpos */
26489857Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
26589857Sobrien	 bfd_elf_generic_reloc,	/* special_function */
26689857Sobrien	 "R_PPC64_ADDR16",	/* name */
267130561Sobrien	 FALSE,			/* partial_inplace */
26889857Sobrien	 0,			/* src_mask */
26989857Sobrien	 0xffff,		/* dst_mask */
270130561Sobrien	 FALSE),		/* pcrel_offset */
27189857Sobrien
27289857Sobrien  /* A 16 bit relocation without overflow.  */
27389857Sobrien  HOWTO (R_PPC64_ADDR16_LO,	/* type */
27489857Sobrien	 0,			/* rightshift */
27589857Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
27689857Sobrien	 16,			/* bitsize */
277130561Sobrien	 FALSE,			/* pc_relative */
27889857Sobrien	 0,			/* bitpos */
27989857Sobrien	 complain_overflow_dont,/* complain_on_overflow */
28089857Sobrien	 bfd_elf_generic_reloc,	/* special_function */
28189857Sobrien	 "R_PPC64_ADDR16_LO",	/* name */
282130561Sobrien	 FALSE,			/* partial_inplace */
28389857Sobrien	 0,			/* src_mask */
28489857Sobrien	 0xffff,		/* dst_mask */
285130561Sobrien	 FALSE),		/* pcrel_offset */
28689857Sobrien
28789857Sobrien  /* Bits 16-31 of an address.  */
28889857Sobrien  HOWTO (R_PPC64_ADDR16_HI,	/* type */
28989857Sobrien	 16,			/* rightshift */
29089857Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
29189857Sobrien	 16,			/* bitsize */
292130561Sobrien	 FALSE,			/* pc_relative */
29389857Sobrien	 0,			/* bitpos */
29489857Sobrien	 complain_overflow_dont, /* complain_on_overflow */
29589857Sobrien	 bfd_elf_generic_reloc,	/* special_function */
29689857Sobrien	 "R_PPC64_ADDR16_HI",	/* name */
297130561Sobrien	 FALSE,			/* partial_inplace */
29889857Sobrien	 0,			/* src_mask */
29989857Sobrien	 0xffff,		/* dst_mask */
300130561Sobrien	 FALSE),		/* pcrel_offset */
30189857Sobrien
30289857Sobrien  /* Bits 16-31 of an address, plus 1 if the contents of the low 16
30389857Sobrien     bits, treated as a signed number, is negative.  */
30489857Sobrien  HOWTO (R_PPC64_ADDR16_HA,	/* type */
30589857Sobrien	 16,			/* rightshift */
30689857Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
30789857Sobrien	 16,			/* bitsize */
308130561Sobrien	 FALSE,			/* pc_relative */
30989857Sobrien	 0,			/* bitpos */
31089857Sobrien	 complain_overflow_dont, /* complain_on_overflow */
31199461Sobrien	 ppc64_elf_ha_reloc,	/* special_function */
31289857Sobrien	 "R_PPC64_ADDR16_HA",	/* name */
313130561Sobrien	 FALSE,			/* partial_inplace */
31489857Sobrien	 0,			/* src_mask */
31589857Sobrien	 0xffff,		/* dst_mask */
316130561Sobrien	 FALSE),		/* pcrel_offset */
31789857Sobrien
31889857Sobrien  /* An absolute 16 bit branch; the lower two bits must be zero.
31989857Sobrien     FIXME: we don't check that, we just clear them.  */
32089857Sobrien  HOWTO (R_PPC64_ADDR14,	/* type */
32189857Sobrien	 0,			/* rightshift */
32289857Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
32389857Sobrien	 16,			/* bitsize */
324130561Sobrien	 FALSE,			/* pc_relative */
32589857Sobrien	 0,			/* bitpos */
32689857Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
327218822Sdim	 ppc64_elf_branch_reloc, /* special_function */
32889857Sobrien	 "R_PPC64_ADDR14",	/* name */
329130561Sobrien	 FALSE,			/* partial_inplace */
33089857Sobrien	 0,			/* src_mask */
331104834Sobrien	 0x0000fffc,		/* dst_mask */
332130561Sobrien	 FALSE),		/* pcrel_offset */
33389857Sobrien
33489857Sobrien  /* An absolute 16 bit branch, for which bit 10 should be set to
33589857Sobrien     indicate that the branch is expected to be taken.  The lower two
33689857Sobrien     bits must be zero.  */
33789857Sobrien  HOWTO (R_PPC64_ADDR14_BRTAKEN, /* type */
33889857Sobrien	 0,			/* rightshift */
33989857Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
34089857Sobrien	 16,			/* bitsize */
341130561Sobrien	 FALSE,			/* pc_relative */
34289857Sobrien	 0,			/* bitpos */
34389857Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
34499461Sobrien	 ppc64_elf_brtaken_reloc, /* special_function */
34589857Sobrien	 "R_PPC64_ADDR14_BRTAKEN",/* name */
346130561Sobrien	 FALSE,			/* partial_inplace */
34789857Sobrien	 0,			/* src_mask */
348104834Sobrien	 0x0000fffc,		/* dst_mask */
349130561Sobrien	 FALSE),		/* pcrel_offset */
35089857Sobrien
35189857Sobrien  /* An absolute 16 bit branch, for which bit 10 should be set to
35289857Sobrien     indicate that the branch is not expected to be taken.  The lower
35389857Sobrien     two bits must be zero.  */
35489857Sobrien  HOWTO (R_PPC64_ADDR14_BRNTAKEN, /* type */
35589857Sobrien	 0,			/* rightshift */
35689857Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
35789857Sobrien	 16,			/* bitsize */
358130561Sobrien	 FALSE,			/* pc_relative */
35989857Sobrien	 0,			/* bitpos */
36089857Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
36199461Sobrien	 ppc64_elf_brtaken_reloc, /* special_function */
36289857Sobrien	 "R_PPC64_ADDR14_BRNTAKEN",/* name */
363130561Sobrien	 FALSE,			/* partial_inplace */
36489857Sobrien	 0,			/* src_mask */
365104834Sobrien	 0x0000fffc,		/* dst_mask */
366130561Sobrien	 FALSE),		/* pcrel_offset */
36789857Sobrien
36889857Sobrien  /* A relative 26 bit branch; the lower two bits must be zero.  */
36989857Sobrien  HOWTO (R_PPC64_REL24,		/* type */
37089857Sobrien	 0,			/* rightshift */
37189857Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
37289857Sobrien	 26,			/* bitsize */
373130561Sobrien	 TRUE,			/* pc_relative */
37489857Sobrien	 0,			/* bitpos */
37589857Sobrien	 complain_overflow_signed, /* complain_on_overflow */
376218822Sdim	 ppc64_elf_branch_reloc, /* special_function */
37789857Sobrien	 "R_PPC64_REL24",	/* name */
378130561Sobrien	 FALSE,			/* partial_inplace */
37989857Sobrien	 0,			/* src_mask */
380104834Sobrien	 0x03fffffc,		/* dst_mask */
381130561Sobrien	 TRUE),			/* pcrel_offset */
38289857Sobrien
38389857Sobrien  /* A relative 16 bit branch; the lower two bits must be zero.  */
38489857Sobrien  HOWTO (R_PPC64_REL14,		/* type */
38589857Sobrien	 0,			/* rightshift */
38689857Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
38789857Sobrien	 16,			/* bitsize */
388130561Sobrien	 TRUE,			/* pc_relative */
38989857Sobrien	 0,			/* bitpos */
39089857Sobrien	 complain_overflow_signed, /* complain_on_overflow */
391218822Sdim	 ppc64_elf_branch_reloc, /* special_function */
39289857Sobrien	 "R_PPC64_REL14",	/* name */
393130561Sobrien	 FALSE,			/* partial_inplace */
39489857Sobrien	 0,			/* src_mask */
395104834Sobrien	 0x0000fffc,		/* dst_mask */
396130561Sobrien	 TRUE),			/* pcrel_offset */
39789857Sobrien
39889857Sobrien  /* A relative 16 bit branch.  Bit 10 should be set to indicate that
39989857Sobrien     the branch is expected to be taken.  The lower two bits must be
40089857Sobrien     zero.  */
40189857Sobrien  HOWTO (R_PPC64_REL14_BRTAKEN,	/* type */
40289857Sobrien	 0,			/* rightshift */
40389857Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
40489857Sobrien	 16,			/* bitsize */
405130561Sobrien	 TRUE,			/* pc_relative */
40689857Sobrien	 0,			/* bitpos */
40789857Sobrien	 complain_overflow_signed, /* complain_on_overflow */
40899461Sobrien	 ppc64_elf_brtaken_reloc, /* special_function */
40989857Sobrien	 "R_PPC64_REL14_BRTAKEN", /* name */
410130561Sobrien	 FALSE,			/* partial_inplace */
41189857Sobrien	 0,			/* src_mask */
412104834Sobrien	 0x0000fffc,		/* dst_mask */
413130561Sobrien	 TRUE),			/* pcrel_offset */
41489857Sobrien
41589857Sobrien  /* A relative 16 bit branch.  Bit 10 should be set to indicate that
41689857Sobrien     the branch is not expected to be taken.  The lower two bits must
41789857Sobrien     be zero.  */
41889857Sobrien  HOWTO (R_PPC64_REL14_BRNTAKEN, /* type */
41989857Sobrien	 0,			/* rightshift */
42089857Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
42189857Sobrien	 16,			/* bitsize */
422130561Sobrien	 TRUE,			/* pc_relative */
42389857Sobrien	 0,			/* bitpos */
42489857Sobrien	 complain_overflow_signed, /* complain_on_overflow */
42599461Sobrien	 ppc64_elf_brtaken_reloc, /* special_function */
42689857Sobrien	 "R_PPC64_REL14_BRNTAKEN",/* name */
427130561Sobrien	 FALSE,			/* partial_inplace */
42889857Sobrien	 0,			/* src_mask */
429104834Sobrien	 0x0000fffc,		/* dst_mask */
430130561Sobrien	 TRUE),			/* pcrel_offset */
43189857Sobrien
43289857Sobrien  /* Like R_PPC64_ADDR16, but referring to the GOT table entry for the
43389857Sobrien     symbol.  */
43489857Sobrien  HOWTO (R_PPC64_GOT16,		/* type */
43589857Sobrien	 0,			/* rightshift */
43689857Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
43789857Sobrien	 16,			/* bitsize */
438130561Sobrien	 FALSE,			/* pc_relative */
43989857Sobrien	 0,			/* bitpos */
44089857Sobrien	 complain_overflow_signed, /* complain_on_overflow */
44199461Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
44289857Sobrien	 "R_PPC64_GOT16",	/* name */
443130561Sobrien	 FALSE,			/* partial_inplace */
44489857Sobrien	 0,			/* src_mask */
44589857Sobrien	 0xffff,		/* dst_mask */
446130561Sobrien	 FALSE),		/* pcrel_offset */
44789857Sobrien
44889857Sobrien  /* Like R_PPC64_ADDR16_LO, but referring to the GOT table entry for
44989857Sobrien     the symbol.  */
45089857Sobrien  HOWTO (R_PPC64_GOT16_LO,	/* type */
45189857Sobrien	 0,			/* rightshift */
45289857Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
45389857Sobrien	 16,			/* bitsize */
454130561Sobrien	 FALSE,			/* pc_relative */
45589857Sobrien	 0,			/* bitpos */
45689857Sobrien	 complain_overflow_dont, /* complain_on_overflow */
45799461Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
45889857Sobrien	 "R_PPC64_GOT16_LO",	/* name */
459130561Sobrien	 FALSE,			/* partial_inplace */
46089857Sobrien	 0,			/* src_mask */
46189857Sobrien	 0xffff,		/* dst_mask */
462130561Sobrien	 FALSE),		/* pcrel_offset */
46389857Sobrien
46489857Sobrien  /* Like R_PPC64_ADDR16_HI, but referring to the GOT table entry for
46589857Sobrien     the symbol.  */
46689857Sobrien  HOWTO (R_PPC64_GOT16_HI,	/* type */
46789857Sobrien	 16,			/* rightshift */
46889857Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
46989857Sobrien	 16,			/* bitsize */
470130561Sobrien	 FALSE,			/* pc_relative */
47189857Sobrien	 0,			/* bitpos */
47289857Sobrien	 complain_overflow_dont,/* complain_on_overflow */
47399461Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
47489857Sobrien	 "R_PPC64_GOT16_HI",	/* name */
475130561Sobrien	 FALSE,			/* partial_inplace */
47689857Sobrien	 0,			/* src_mask */
47789857Sobrien	 0xffff,		/* dst_mask */
478130561Sobrien	 FALSE),		/* pcrel_offset */
47989857Sobrien
48089857Sobrien  /* Like R_PPC64_ADDR16_HA, but referring to the GOT table entry for
48189857Sobrien     the symbol.  */
48289857Sobrien  HOWTO (R_PPC64_GOT16_HA,	/* type */
48389857Sobrien	 16,			/* rightshift */
48489857Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
48589857Sobrien	 16,			/* bitsize */
486130561Sobrien	 FALSE,			/* pc_relative */
48789857Sobrien	 0,			/* bitpos */
48889857Sobrien	 complain_overflow_dont,/* complain_on_overflow */
48999461Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
49089857Sobrien	 "R_PPC64_GOT16_HA",	/* name */
491130561Sobrien	 FALSE,			/* partial_inplace */
49289857Sobrien	 0,			/* src_mask */
49389857Sobrien	 0xffff,		/* dst_mask */
494130561Sobrien	 FALSE),		/* pcrel_offset */
49589857Sobrien
49689857Sobrien  /* This is used only by the dynamic linker.  The symbol should exist
49789857Sobrien     both in the object being run and in some shared library.  The
49889857Sobrien     dynamic linker copies the data addressed by the symbol from the
49989857Sobrien     shared library into the object, because the object being
50089857Sobrien     run has to have the data at some particular address.  */
50189857Sobrien  HOWTO (R_PPC64_COPY,		/* type */
50289857Sobrien	 0,			/* rightshift */
503104834Sobrien	 0,			/* this one is variable size */
504104834Sobrien	 0,			/* bitsize */
505130561Sobrien	 FALSE,			/* pc_relative */
50689857Sobrien	 0,			/* bitpos */
507104834Sobrien	 complain_overflow_dont, /* complain_on_overflow */
508104834Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
50989857Sobrien	 "R_PPC64_COPY",	/* name */
510130561Sobrien	 FALSE,			/* partial_inplace */
51189857Sobrien	 0,			/* src_mask */
51289857Sobrien	 0,			/* dst_mask */
513130561Sobrien	 FALSE),		/* pcrel_offset */
51489857Sobrien
51589857Sobrien  /* Like R_PPC64_ADDR64, but used when setting global offset table
51689857Sobrien     entries.  */
51789857Sobrien  HOWTO (R_PPC64_GLOB_DAT,	/* type */
51889857Sobrien	 0,			/* rightshift */
51989857Sobrien	 4,			/* size (0=byte, 1=short, 2=long, 4=64 bits) */
52089857Sobrien	 64,			/* bitsize */
521130561Sobrien	 FALSE,			/* pc_relative */
52289857Sobrien	 0,			/* bitpos */
52389857Sobrien	 complain_overflow_dont, /* complain_on_overflow */
52499461Sobrien	 ppc64_elf_unhandled_reloc,  /* special_function */
52589857Sobrien	 "R_PPC64_GLOB_DAT",	/* name */
526130561Sobrien	 FALSE,			/* partial_inplace */
52789857Sobrien	 0,			/* src_mask */
528104834Sobrien	 ONES (64),		/* dst_mask */
529130561Sobrien	 FALSE),		/* pcrel_offset */
53089857Sobrien
53189857Sobrien  /* Created by the link editor.  Marks a procedure linkage table
53289857Sobrien     entry for a symbol.  */
53389857Sobrien  HOWTO (R_PPC64_JMP_SLOT,	/* type */
53489857Sobrien	 0,			/* rightshift */
53589857Sobrien	 0,			/* size (0 = byte, 1 = short, 2 = long) */
53689857Sobrien	 0,			/* bitsize */
537130561Sobrien	 FALSE,			/* pc_relative */
53889857Sobrien	 0,			/* bitpos */
53989857Sobrien	 complain_overflow_dont, /* complain_on_overflow */
54099461Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
54189857Sobrien	 "R_PPC64_JMP_SLOT",	/* name */
542130561Sobrien	 FALSE,			/* partial_inplace */
54389857Sobrien	 0,			/* src_mask */
54489857Sobrien	 0,			/* dst_mask */
545130561Sobrien	 FALSE),		/* pcrel_offset */
54689857Sobrien
54789857Sobrien  /* Used only by the dynamic linker.  When the object is run, this
54889857Sobrien     doubleword64 is set to the load address of the object, plus the
54989857Sobrien     addend.  */
55089857Sobrien  HOWTO (R_PPC64_RELATIVE,	/* type */
55189857Sobrien	 0,			/* rightshift */
55289857Sobrien	 4,			/* size (0=byte, 1=short, 2=long, 4=64 bits) */
55389857Sobrien	 64,			/* bitsize */
554130561Sobrien	 FALSE,			/* pc_relative */
55589857Sobrien	 0,			/* bitpos */
55689857Sobrien	 complain_overflow_dont, /* complain_on_overflow */
55789857Sobrien	 bfd_elf_generic_reloc,	/* special_function */
55889857Sobrien	 "R_PPC64_RELATIVE",	/* name */
559130561Sobrien	 FALSE,			/* partial_inplace */
56089857Sobrien	 0,			/* src_mask */
561104834Sobrien	 ONES (64),		/* dst_mask */
562130561Sobrien	 FALSE),		/* pcrel_offset */
56389857Sobrien
56489857Sobrien  /* Like R_PPC64_ADDR32, but may be unaligned.  */
56589857Sobrien  HOWTO (R_PPC64_UADDR32,	/* type */
56689857Sobrien	 0,			/* rightshift */
56789857Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
56889857Sobrien	 32,			/* bitsize */
569130561Sobrien	 FALSE,			/* pc_relative */
57089857Sobrien	 0,			/* bitpos */
57189857Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
57289857Sobrien	 bfd_elf_generic_reloc,	/* special_function */
57389857Sobrien	 "R_PPC64_UADDR32",	/* name */
574130561Sobrien	 FALSE,			/* partial_inplace */
57589857Sobrien	 0,			/* src_mask */
57689857Sobrien	 0xffffffff,		/* dst_mask */
577130561Sobrien	 FALSE),		/* pcrel_offset */
57889857Sobrien
57989857Sobrien  /* Like R_PPC64_ADDR16, but may be unaligned.  */
58089857Sobrien  HOWTO (R_PPC64_UADDR16,	/* type */
58189857Sobrien	 0,			/* rightshift */
58289857Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
58389857Sobrien	 16,			/* bitsize */
584130561Sobrien	 FALSE,			/* pc_relative */
58589857Sobrien	 0,			/* bitpos */
58689857Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
58789857Sobrien	 bfd_elf_generic_reloc,	/* special_function */
58889857Sobrien	 "R_PPC64_UADDR16",	/* name */
589130561Sobrien	 FALSE,			/* partial_inplace */
59089857Sobrien	 0,			/* src_mask */
59189857Sobrien	 0xffff,		/* dst_mask */
592130561Sobrien	 FALSE),		/* pcrel_offset */
59389857Sobrien
59489857Sobrien  /* 32-bit PC relative.  */
59589857Sobrien  HOWTO (R_PPC64_REL32,		/* type */
59689857Sobrien	 0,			/* rightshift */
59789857Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
59889857Sobrien	 32,			/* bitsize */
599130561Sobrien	 TRUE,			/* pc_relative */
60089857Sobrien	 0,			/* bitpos */
601104834Sobrien	 /* FIXME: Verify.  Was complain_overflow_bitfield.  */
60289857Sobrien	 complain_overflow_signed, /* complain_on_overflow */
60389857Sobrien	 bfd_elf_generic_reloc,	/* special_function */
60489857Sobrien	 "R_PPC64_REL32",	/* name */
605130561Sobrien	 FALSE,			/* partial_inplace */
60689857Sobrien	 0,			/* src_mask */
60789857Sobrien	 0xffffffff,		/* dst_mask */
608130561Sobrien	 TRUE),			/* pcrel_offset */
60989857Sobrien
61089857Sobrien  /* 32-bit relocation to the symbol's procedure linkage table.  */
61189857Sobrien  HOWTO (R_PPC64_PLT32,		/* type */
61289857Sobrien	 0,			/* rightshift */
61389857Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
61489857Sobrien	 32,			/* bitsize */
615130561Sobrien	 FALSE,			/* pc_relative */
61689857Sobrien	 0,			/* bitpos */
61789857Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
61899461Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
61989857Sobrien	 "R_PPC64_PLT32",	/* name */
620130561Sobrien	 FALSE,			/* partial_inplace */
62189857Sobrien	 0,			/* src_mask */
622104834Sobrien	 0xffffffff,		/* dst_mask */
623130561Sobrien	 FALSE),		/* pcrel_offset */
62489857Sobrien
62589857Sobrien  /* 32-bit PC relative relocation to the symbol's procedure linkage table.
62689857Sobrien     FIXME: R_PPC64_PLTREL32 not supported.  */
62789857Sobrien  HOWTO (R_PPC64_PLTREL32,	/* type */
62889857Sobrien	 0,			/* rightshift */
62989857Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
63089857Sobrien	 32,			/* bitsize */
631130561Sobrien	 TRUE,			/* pc_relative */
63289857Sobrien	 0,			/* bitpos */
63389857Sobrien	 complain_overflow_signed, /* complain_on_overflow */
63489857Sobrien	 bfd_elf_generic_reloc,	/* special_function */
63589857Sobrien	 "R_PPC64_PLTREL32",	/* name */
636130561Sobrien	 FALSE,			/* partial_inplace */
63789857Sobrien	 0,			/* src_mask */
638104834Sobrien	 0xffffffff,		/* dst_mask */
639130561Sobrien	 TRUE),			/* pcrel_offset */
64089857Sobrien
64189857Sobrien  /* Like R_PPC64_ADDR16_LO, but referring to the PLT table entry for
64289857Sobrien     the symbol.  */
64389857Sobrien  HOWTO (R_PPC64_PLT16_LO,	/* type */
64489857Sobrien	 0,			/* rightshift */
64589857Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
64689857Sobrien	 16,			/* bitsize */
647130561Sobrien	 FALSE,			/* pc_relative */
64889857Sobrien	 0,			/* bitpos */
64989857Sobrien	 complain_overflow_dont, /* complain_on_overflow */
65099461Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
65189857Sobrien	 "R_PPC64_PLT16_LO",	/* name */
652130561Sobrien	 FALSE,			/* partial_inplace */
65389857Sobrien	 0,			/* src_mask */
65489857Sobrien	 0xffff,		/* dst_mask */
655130561Sobrien	 FALSE),		/* pcrel_offset */
65689857Sobrien
65789857Sobrien  /* Like R_PPC64_ADDR16_HI, but referring to the PLT table entry for
65889857Sobrien     the symbol.  */
65989857Sobrien  HOWTO (R_PPC64_PLT16_HI,	/* type */
66089857Sobrien	 16,			/* rightshift */
66189857Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
66289857Sobrien	 16,			/* bitsize */
663130561Sobrien	 FALSE,			/* pc_relative */
66489857Sobrien	 0,			/* bitpos */
66589857Sobrien	 complain_overflow_dont, /* complain_on_overflow */
66699461Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
66789857Sobrien	 "R_PPC64_PLT16_HI",	/* name */
668130561Sobrien	 FALSE,			/* partial_inplace */
66989857Sobrien	 0,			/* src_mask */
67089857Sobrien	 0xffff,		/* dst_mask */
671130561Sobrien	 FALSE),		/* pcrel_offset */
67289857Sobrien
67389857Sobrien  /* Like R_PPC64_ADDR16_HA, but referring to the PLT table entry for
67489857Sobrien     the symbol.  */
67589857Sobrien  HOWTO (R_PPC64_PLT16_HA,	/* type */
67689857Sobrien	 16,			/* rightshift */
67789857Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
67889857Sobrien	 16,			/* bitsize */
679130561Sobrien	 FALSE,			/* pc_relative */
68089857Sobrien	 0,			/* bitpos */
68189857Sobrien	 complain_overflow_dont, /* complain_on_overflow */
68299461Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
68389857Sobrien	 "R_PPC64_PLT16_HA",	/* name */
684130561Sobrien	 FALSE,			/* partial_inplace */
68589857Sobrien	 0,			/* src_mask */
68689857Sobrien	 0xffff,		/* dst_mask */
687130561Sobrien	 FALSE),		/* pcrel_offset */
68889857Sobrien
68999461Sobrien  /* 16-bit section relative relocation.  */
69089857Sobrien  HOWTO (R_PPC64_SECTOFF,	/* type */
69189857Sobrien	 0,			/* rightshift */
69299461Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
69399461Sobrien	 16,			/* bitsize */
694130561Sobrien	 FALSE,			/* pc_relative */
69589857Sobrien	 0,			/* bitpos */
69689857Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
69799461Sobrien	 ppc64_elf_sectoff_reloc, /* special_function */
69889857Sobrien	 "R_PPC64_SECTOFF",	/* name */
699130561Sobrien	 FALSE,			/* partial_inplace */
70089857Sobrien	 0,			/* src_mask */
70199461Sobrien	 0xffff,		/* dst_mask */
702130561Sobrien	 FALSE),		/* pcrel_offset */
70389857Sobrien
70499461Sobrien  /* Like R_PPC64_SECTOFF, but no overflow warning.  */
70589857Sobrien  HOWTO (R_PPC64_SECTOFF_LO,	/* type */
70689857Sobrien	 0,			/* rightshift */
70789857Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
70889857Sobrien	 16,			/* bitsize */
709130561Sobrien	 FALSE,			/* pc_relative */
71089857Sobrien	 0,			/* bitpos */
71189857Sobrien	 complain_overflow_dont, /* complain_on_overflow */
71299461Sobrien	 ppc64_elf_sectoff_reloc, /* special_function */
71389857Sobrien	 "R_PPC64_SECTOFF_LO",	/* name */
714130561Sobrien	 FALSE,			/* partial_inplace */
71589857Sobrien	 0,			/* src_mask */
71689857Sobrien	 0xffff,		/* dst_mask */
717130561Sobrien	 FALSE),		/* pcrel_offset */
71889857Sobrien
71989857Sobrien  /* 16-bit upper half section relative relocation.  */
72089857Sobrien  HOWTO (R_PPC64_SECTOFF_HI,	/* type */
72189857Sobrien	 16,			/* rightshift */
72289857Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
72389857Sobrien	 16,			/* bitsize */
724130561Sobrien	 FALSE,			/* pc_relative */
72589857Sobrien	 0,			/* bitpos */
72689857Sobrien	 complain_overflow_dont, /* complain_on_overflow */
72799461Sobrien	 ppc64_elf_sectoff_reloc, /* special_function */
72889857Sobrien	 "R_PPC64_SECTOFF_HI",	/* name */
729130561Sobrien	 FALSE,			/* partial_inplace */
73089857Sobrien	 0,			/* src_mask */
73189857Sobrien	 0xffff,		/* dst_mask */
732130561Sobrien	 FALSE),		/* pcrel_offset */
73389857Sobrien
73489857Sobrien  /* 16-bit upper half adjusted section relative relocation.  */
73589857Sobrien  HOWTO (R_PPC64_SECTOFF_HA,	/* type */
73689857Sobrien	 16,			/* rightshift */
73789857Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
73889857Sobrien	 16,			/* bitsize */
739130561Sobrien	 FALSE,			/* pc_relative */
74089857Sobrien	 0,			/* bitpos */
74189857Sobrien	 complain_overflow_dont, /* complain_on_overflow */
74299461Sobrien	 ppc64_elf_sectoff_ha_reloc, /* special_function */
74389857Sobrien	 "R_PPC64_SECTOFF_HA",	/* name */
744130561Sobrien	 FALSE,			/* partial_inplace */
74589857Sobrien	 0,			/* src_mask */
74689857Sobrien	 0xffff,		/* dst_mask */
747130561Sobrien	 FALSE),		/* pcrel_offset */
74889857Sobrien
749130561Sobrien  /* Like R_PPC64_REL24 without touching the two least significant bits.  */
750130561Sobrien  HOWTO (R_PPC64_REL30,		/* type */
75189857Sobrien	 2,			/* rightshift */
75289857Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
75389857Sobrien	 30,			/* bitsize */
754130561Sobrien	 TRUE,			/* pc_relative */
75589857Sobrien	 0,			/* bitpos */
75689857Sobrien	 complain_overflow_dont, /* complain_on_overflow */
75789857Sobrien	 bfd_elf_generic_reloc, /* special_function */
758130561Sobrien	 "R_PPC64_REL30",	/* name */
759130561Sobrien	 FALSE,			/* partial_inplace */
76089857Sobrien	 0,			/* src_mask */
76189857Sobrien	 0xfffffffc,		/* dst_mask */
762130561Sobrien	 TRUE),			/* pcrel_offset */
76389857Sobrien
76489857Sobrien  /* Relocs in the 64-bit PowerPC ELF ABI, not in the 32-bit ABI.  */
76589857Sobrien
76689857Sobrien  /* A standard 64-bit relocation.  */
76789857Sobrien  HOWTO (R_PPC64_ADDR64,	/* type */
76889857Sobrien	 0,			/* rightshift */
76989857Sobrien	 4,			/* size (0=byte, 1=short, 2=long, 4=64 bits) */
77089857Sobrien	 64,			/* bitsize */
771130561Sobrien	 FALSE,			/* pc_relative */
77289857Sobrien	 0,			/* bitpos */
77389857Sobrien	 complain_overflow_dont, /* complain_on_overflow */
77489857Sobrien	 bfd_elf_generic_reloc,	/* special_function */
77589857Sobrien	 "R_PPC64_ADDR64",	/* name */
776130561Sobrien	 FALSE,			/* partial_inplace */
77789857Sobrien	 0,			/* src_mask */
778104834Sobrien	 ONES (64),		/* dst_mask */
779130561Sobrien	 FALSE),		/* pcrel_offset */
78089857Sobrien
78189857Sobrien  /* The bits 32-47 of an address.  */
78289857Sobrien  HOWTO (R_PPC64_ADDR16_HIGHER,	/* type */
78389857Sobrien	 32,			/* rightshift */
78489857Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
78589857Sobrien	 16,			/* bitsize */
786130561Sobrien	 FALSE,			/* pc_relative */
78789857Sobrien	 0,			/* bitpos */
78889857Sobrien	 complain_overflow_dont, /* complain_on_overflow */
78989857Sobrien	 bfd_elf_generic_reloc,	/* special_function */
79089857Sobrien	 "R_PPC64_ADDR16_HIGHER", /* name */
791130561Sobrien	 FALSE,			/* partial_inplace */
79289857Sobrien	 0,			/* src_mask */
79389857Sobrien	 0xffff,		/* dst_mask */
794130561Sobrien	 FALSE),		/* pcrel_offset */
79589857Sobrien
79689857Sobrien  /* The bits 32-47 of an address, plus 1 if the contents of the low
79789857Sobrien     16 bits, treated as a signed number, is negative.  */
79889857Sobrien  HOWTO (R_PPC64_ADDR16_HIGHERA, /* type */
79989857Sobrien	 32,			/* rightshift */
80089857Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
80189857Sobrien	 16,			/* bitsize */
802130561Sobrien	 FALSE,			/* pc_relative */
80389857Sobrien	 0,			/* bitpos */
80489857Sobrien	 complain_overflow_dont, /* complain_on_overflow */
80599461Sobrien	 ppc64_elf_ha_reloc,	/* special_function */
80689857Sobrien	 "R_PPC64_ADDR16_HIGHERA", /* name */
807130561Sobrien	 FALSE,			/* partial_inplace */
80889857Sobrien	 0,			/* src_mask */
80989857Sobrien	 0xffff,		/* dst_mask */
810130561Sobrien	 FALSE),		/* pcrel_offset */
81189857Sobrien
81289857Sobrien  /* The bits 48-63 of an address.  */
81389857Sobrien  HOWTO (R_PPC64_ADDR16_HIGHEST,/* type */
81489857Sobrien	 48,			/* rightshift */
81589857Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
81689857Sobrien	 16,			/* bitsize */
817130561Sobrien	 FALSE,			/* pc_relative */
81889857Sobrien	 0,			/* bitpos */
81989857Sobrien	 complain_overflow_dont, /* complain_on_overflow */
82089857Sobrien	 bfd_elf_generic_reloc,	/* special_function */
82189857Sobrien	 "R_PPC64_ADDR16_HIGHEST", /* name */
822130561Sobrien	 FALSE,			/* partial_inplace */
82389857Sobrien	 0,			/* src_mask */
82489857Sobrien	 0xffff,		/* dst_mask */
825130561Sobrien	 FALSE),		/* pcrel_offset */
82689857Sobrien
82789857Sobrien  /* The bits 48-63 of an address, plus 1 if the contents of the low
82889857Sobrien     16 bits, treated as a signed number, is negative.  */
82989857Sobrien  HOWTO (R_PPC64_ADDR16_HIGHESTA,/* type */
83089857Sobrien	 48,			/* rightshift */
83189857Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
83289857Sobrien	 16,			/* bitsize */
833130561Sobrien	 FALSE,			/* pc_relative */
83489857Sobrien	 0,			/* bitpos */
83589857Sobrien	 complain_overflow_dont, /* complain_on_overflow */
83699461Sobrien	 ppc64_elf_ha_reloc,	/* special_function */
83789857Sobrien	 "R_PPC64_ADDR16_HIGHESTA", /* name */
838130561Sobrien	 FALSE,			/* partial_inplace */
83989857Sobrien	 0,			/* src_mask */
84089857Sobrien	 0xffff,		/* dst_mask */
841130561Sobrien	 FALSE),		/* pcrel_offset */
84289857Sobrien
84389857Sobrien  /* Like ADDR64, but may be unaligned.  */
84489857Sobrien  HOWTO (R_PPC64_UADDR64,	/* type */
84589857Sobrien	 0,			/* rightshift */
84689857Sobrien	 4,			/* size (0=byte, 1=short, 2=long, 4=64 bits) */
84789857Sobrien	 64,			/* bitsize */
848130561Sobrien	 FALSE,			/* pc_relative */
84989857Sobrien	 0,			/* bitpos */
85089857Sobrien	 complain_overflow_dont, /* complain_on_overflow */
85189857Sobrien	 bfd_elf_generic_reloc,	/* special_function */
85289857Sobrien	 "R_PPC64_UADDR64",	/* name */
853130561Sobrien	 FALSE,			/* partial_inplace */
85489857Sobrien	 0,			/* src_mask */
855104834Sobrien	 ONES (64),		/* dst_mask */
856130561Sobrien	 FALSE),		/* pcrel_offset */
85789857Sobrien
85889857Sobrien  /* 64-bit relative relocation.  */
85989857Sobrien  HOWTO (R_PPC64_REL64,		/* type */
86089857Sobrien	 0,			/* rightshift */
86189857Sobrien	 4,			/* size (0=byte, 1=short, 2=long, 4=64 bits) */
86289857Sobrien	 64,			/* bitsize */
863130561Sobrien	 TRUE,			/* pc_relative */
86489857Sobrien	 0,			/* bitpos */
86589857Sobrien	 complain_overflow_dont, /* complain_on_overflow */
86689857Sobrien	 bfd_elf_generic_reloc,	/* special_function */
86789857Sobrien	 "R_PPC64_REL64",	/* name */
868130561Sobrien	 FALSE,			/* partial_inplace */
86989857Sobrien	 0,			/* src_mask */
870104834Sobrien	 ONES (64),		/* dst_mask */
871130561Sobrien	 TRUE),			/* pcrel_offset */
87289857Sobrien
873104834Sobrien  /* 64-bit relocation to the symbol's procedure linkage table.  */
87489857Sobrien  HOWTO (R_PPC64_PLT64,		/* type */
87589857Sobrien	 0,			/* rightshift */
87689857Sobrien	 4,			/* size (0=byte, 1=short, 2=long, 4=64 bits) */
87789857Sobrien	 64,			/* bitsize */
878130561Sobrien	 FALSE,			/* pc_relative */
87989857Sobrien	 0,			/* bitpos */
88089857Sobrien	 complain_overflow_dont, /* complain_on_overflow */
88199461Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
88289857Sobrien	 "R_PPC64_PLT64",	/* name */
883130561Sobrien	 FALSE,			/* partial_inplace */
88489857Sobrien	 0,			/* src_mask */
885104834Sobrien	 ONES (64),		/* dst_mask */
886130561Sobrien	 FALSE),		/* pcrel_offset */
88789857Sobrien
88889857Sobrien  /* 64-bit PC relative relocation to the symbol's procedure linkage
88989857Sobrien     table.  */
89089857Sobrien  /* FIXME: R_PPC64_PLTREL64 not supported.  */
89189857Sobrien  HOWTO (R_PPC64_PLTREL64,	/* type */
89289857Sobrien	 0,			/* rightshift */
89389857Sobrien	 4,			/* size (0=byte, 1=short, 2=long, 4=64 bits) */
89489857Sobrien	 64,			/* bitsize */
895130561Sobrien	 TRUE,			/* pc_relative */
89689857Sobrien	 0,			/* bitpos */
89789857Sobrien	 complain_overflow_dont, /* complain_on_overflow */
89899461Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
89989857Sobrien	 "R_PPC64_PLTREL64",	/* name */
900130561Sobrien	 FALSE,			/* partial_inplace */
90189857Sobrien	 0,			/* src_mask */
902104834Sobrien	 ONES (64),		/* dst_mask */
903130561Sobrien	 TRUE),			/* pcrel_offset */
90489857Sobrien
90589857Sobrien  /* 16 bit TOC-relative relocation.  */
90689857Sobrien
90789857Sobrien  /* R_PPC64_TOC16	  47	   half16*	S + A - .TOC.  */
90889857Sobrien  HOWTO (R_PPC64_TOC16,		/* type */
90989857Sobrien	 0,			/* rightshift */
91089857Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
91189857Sobrien	 16,			/* bitsize */
912130561Sobrien	 FALSE,			/* pc_relative */
91389857Sobrien	 0,			/* bitpos */
91489857Sobrien	 complain_overflow_signed, /* complain_on_overflow */
91599461Sobrien	 ppc64_elf_toc_reloc,	/* special_function */
91689857Sobrien	 "R_PPC64_TOC16",	/* name */
917130561Sobrien	 FALSE,			/* partial_inplace */
91889857Sobrien	 0,			/* src_mask */
91989857Sobrien	 0xffff,		/* dst_mask */
920130561Sobrien	 FALSE),		/* pcrel_offset */
92189857Sobrien
92289857Sobrien  /* 16 bit TOC-relative relocation without overflow.  */
92389857Sobrien
92489857Sobrien  /* R_PPC64_TOC16_LO	  48	   half16	 #lo (S + A - .TOC.)  */
92589857Sobrien  HOWTO (R_PPC64_TOC16_LO,	/* type */
92689857Sobrien	 0,			/* rightshift */
92789857Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
92889857Sobrien	 16,			/* bitsize */
929130561Sobrien	 FALSE,			/* pc_relative */
93089857Sobrien	 0,			/* bitpos */
93189857Sobrien	 complain_overflow_dont, /* complain_on_overflow */
93299461Sobrien	 ppc64_elf_toc_reloc,	/* special_function */
93389857Sobrien	 "R_PPC64_TOC16_LO",	/* name */
934130561Sobrien	 FALSE,			/* partial_inplace */
93589857Sobrien	 0,			/* src_mask */
93689857Sobrien	 0xffff,		/* dst_mask */
937130561Sobrien	 FALSE),		/* pcrel_offset */
93889857Sobrien
93989857Sobrien  /* 16 bit TOC-relative relocation, high 16 bits.  */
94089857Sobrien
94189857Sobrien  /* R_PPC64_TOC16_HI	  49	   half16	 #hi (S + A - .TOC.)  */
94289857Sobrien  HOWTO (R_PPC64_TOC16_HI,	/* type */
94389857Sobrien	 16,			/* rightshift */
94489857Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
94589857Sobrien	 16,			/* bitsize */
946130561Sobrien	 FALSE,			/* pc_relative */
94789857Sobrien	 0,			/* bitpos */
94889857Sobrien	 complain_overflow_dont, /* complain_on_overflow */
94999461Sobrien	 ppc64_elf_toc_reloc,	/* special_function */
95089857Sobrien	 "R_PPC64_TOC16_HI",	/* name */
951130561Sobrien	 FALSE,			/* partial_inplace */
95289857Sobrien	 0,			/* src_mask */
95389857Sobrien	 0xffff,		/* dst_mask */
954130561Sobrien	 FALSE),		/* pcrel_offset */
95589857Sobrien
95689857Sobrien  /* 16 bit TOC-relative relocation, high 16 bits, plus 1 if the
95789857Sobrien     contents of the low 16 bits, treated as a signed number, is
95889857Sobrien     negative.  */
95989857Sobrien
96089857Sobrien  /* R_PPC64_TOC16_HA	  50	   half16	 #ha (S + A - .TOC.)  */
96189857Sobrien  HOWTO (R_PPC64_TOC16_HA,	/* type */
96289857Sobrien	 16,			/* rightshift */
96389857Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
96489857Sobrien	 16,			/* bitsize */
965130561Sobrien	 FALSE,			/* pc_relative */
96689857Sobrien	 0,			/* bitpos */
96789857Sobrien	 complain_overflow_dont, /* complain_on_overflow */
96899461Sobrien	 ppc64_elf_toc_ha_reloc, /* special_function */
96989857Sobrien	 "R_PPC64_TOC16_HA",	/* name */
970130561Sobrien	 FALSE,			/* partial_inplace */
97189857Sobrien	 0,			/* src_mask */
97289857Sobrien	 0xffff,		/* dst_mask */
973130561Sobrien	 FALSE),		/* pcrel_offset */
97489857Sobrien
97589857Sobrien  /* 64-bit relocation; insert value of TOC base (.TOC.).  */
97689857Sobrien
97789857Sobrien  /* R_PPC64_TOC		  51	   doubleword64	 .TOC.  */
97889857Sobrien  HOWTO (R_PPC64_TOC,		/* type */
97989857Sobrien	 0,			/* rightshift */
98089857Sobrien	 4,			/* size (0=byte, 1=short, 2=long, 4=64 bits) */
98189857Sobrien	 64,			/* bitsize */
982130561Sobrien	 FALSE,			/* pc_relative */
98389857Sobrien	 0,			/* bitpos */
98489857Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
98599461Sobrien	 ppc64_elf_toc64_reloc,	/* special_function */
98689857Sobrien	 "R_PPC64_TOC",		/* name */
987130561Sobrien	 FALSE,			/* partial_inplace */
98889857Sobrien	 0,			/* src_mask */
989104834Sobrien	 ONES (64),		/* dst_mask */
990130561Sobrien	 FALSE),		/* pcrel_offset */
99189857Sobrien
99289857Sobrien  /* Like R_PPC64_GOT16, but also informs the link editor that the
99389857Sobrien     value to relocate may (!) refer to a PLT entry which the link
99489857Sobrien     editor (a) may replace with the symbol value.  If the link editor
99589857Sobrien     is unable to fully resolve the symbol, it may (b) create a PLT
99689857Sobrien     entry and store the address to the new PLT entry in the GOT.
99789857Sobrien     This permits lazy resolution of function symbols at run time.
99889857Sobrien     The link editor may also skip all of this and just (c) emit a
99989857Sobrien     R_PPC64_GLOB_DAT to tie the symbol to the GOT entry.  */
100089857Sobrien  /* FIXME: R_PPC64_PLTGOT16 not implemented.  */
100189857Sobrien    HOWTO (R_PPC64_PLTGOT16,	/* type */
100289857Sobrien	 0,			/* rightshift */
100389857Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
100489857Sobrien	 16,			/* bitsize */
1005130561Sobrien	 FALSE,			/* pc_relative */
100689857Sobrien	 0,			/* bitpos */
100789857Sobrien	 complain_overflow_signed, /* complain_on_overflow */
100899461Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
100989857Sobrien	 "R_PPC64_PLTGOT16",	/* name */
1010130561Sobrien	 FALSE,			/* partial_inplace */
101189857Sobrien	 0,			/* src_mask */
101289857Sobrien	 0xffff,		/* dst_mask */
1013130561Sobrien	 FALSE),		/* pcrel_offset */
101489857Sobrien
101589857Sobrien  /* Like R_PPC64_PLTGOT16, but without overflow.  */
101689857Sobrien  /* FIXME: R_PPC64_PLTGOT16_LO not implemented.  */
101789857Sobrien  HOWTO (R_PPC64_PLTGOT16_LO,	/* type */
101889857Sobrien	 0,			/* rightshift */
101989857Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
102089857Sobrien	 16,			/* bitsize */
1021130561Sobrien	 FALSE,			/* pc_relative */
102289857Sobrien	 0,			/* bitpos */
102389857Sobrien	 complain_overflow_dont, /* complain_on_overflow */
102499461Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
102589857Sobrien	 "R_PPC64_PLTGOT16_LO",	/* name */
1026130561Sobrien	 FALSE,			/* partial_inplace */
102789857Sobrien	 0,			/* src_mask */
102889857Sobrien	 0xffff,		/* dst_mask */
1029130561Sobrien	 FALSE),		/* pcrel_offset */
103089857Sobrien
103189857Sobrien  /* Like R_PPC64_PLT_GOT16, but using bits 16-31 of the address.  */
103289857Sobrien  /* FIXME: R_PPC64_PLTGOT16_HI not implemented.  */
103389857Sobrien  HOWTO (R_PPC64_PLTGOT16_HI,	/* type */
103489857Sobrien	 16,			/* rightshift */
103589857Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
103689857Sobrien	 16,			/* bitsize */
1037130561Sobrien	 FALSE,			/* pc_relative */
103889857Sobrien	 0,			/* bitpos */
103989857Sobrien	 complain_overflow_dont, /* complain_on_overflow */
104099461Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
104189857Sobrien	 "R_PPC64_PLTGOT16_HI",	/* name */
1042130561Sobrien	 FALSE,			/* partial_inplace */
104389857Sobrien	 0,			/* src_mask */
104489857Sobrien	 0xffff,		/* dst_mask */
1045130561Sobrien	 FALSE),		/* pcrel_offset */
104689857Sobrien
104789857Sobrien  /* Like R_PPC64_PLT_GOT16, but using bits 16-31 of the address, plus
104889857Sobrien     1 if the contents of the low 16 bits, treated as a signed number,
104989857Sobrien     is negative.  */
105089857Sobrien  /* FIXME: R_PPC64_PLTGOT16_HA not implemented.  */
105189857Sobrien  HOWTO (R_PPC64_PLTGOT16_HA,	/* type */
105289857Sobrien	 16,			/* rightshift */
105389857Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
105489857Sobrien	 16,			/* bitsize */
1055130561Sobrien	 FALSE,			/* pc_relative */
105689857Sobrien	 0,			/* bitpos */
105789857Sobrien	 complain_overflow_dont,/* complain_on_overflow */
105899461Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
105989857Sobrien	 "R_PPC64_PLTGOT16_HA",	/* name */
1060130561Sobrien	 FALSE,			/* partial_inplace */
106189857Sobrien	 0,			/* src_mask */
106289857Sobrien	 0xffff,		/* dst_mask */
1063130561Sobrien	 FALSE),		/* pcrel_offset */
106489857Sobrien
106589857Sobrien  /* Like R_PPC64_ADDR16, but for instructions with a DS field.  */
106689857Sobrien  HOWTO (R_PPC64_ADDR16_DS,	/* type */
106789857Sobrien	 0,			/* rightshift */
106889857Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
106989857Sobrien	 16,			/* bitsize */
1070130561Sobrien	 FALSE,			/* pc_relative */
107189857Sobrien	 0,			/* bitpos */
107289857Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
107389857Sobrien	 bfd_elf_generic_reloc,	/* special_function */
107489857Sobrien	 "R_PPC64_ADDR16_DS",	/* name */
1075130561Sobrien	 FALSE,			/* partial_inplace */
107689857Sobrien	 0,			/* src_mask */
107789857Sobrien	 0xfffc,		/* dst_mask */
1078130561Sobrien	 FALSE),		/* pcrel_offset */
107989857Sobrien
108089857Sobrien  /* Like R_PPC64_ADDR16_LO, but for instructions with a DS field.  */
108189857Sobrien  HOWTO (R_PPC64_ADDR16_LO_DS,	/* type */
108289857Sobrien	 0,			/* rightshift */
108389857Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
108489857Sobrien	 16,			/* bitsize */
1085130561Sobrien	 FALSE,			/* pc_relative */
108689857Sobrien	 0,			/* bitpos */
108789857Sobrien	 complain_overflow_dont,/* complain_on_overflow */
108889857Sobrien	 bfd_elf_generic_reloc,	/* special_function */
108989857Sobrien	 "R_PPC64_ADDR16_LO_DS",/* name */
1090130561Sobrien	 FALSE,			/* partial_inplace */
109189857Sobrien	 0,			/* src_mask */
109289857Sobrien	 0xfffc,		/* dst_mask */
1093130561Sobrien	 FALSE),		/* pcrel_offset */
109489857Sobrien
109589857Sobrien  /* Like R_PPC64_GOT16, but for instructions with a DS field.  */
109689857Sobrien  HOWTO (R_PPC64_GOT16_DS,	/* type */
109789857Sobrien	 0,			/* rightshift */
109889857Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
109989857Sobrien	 16,			/* bitsize */
1100130561Sobrien	 FALSE,			/* pc_relative */
110189857Sobrien	 0,			/* bitpos */
110289857Sobrien	 complain_overflow_signed, /* complain_on_overflow */
110399461Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
110489857Sobrien	 "R_PPC64_GOT16_DS",	/* name */
1105130561Sobrien	 FALSE,			/* partial_inplace */
110689857Sobrien	 0,			/* src_mask */
110789857Sobrien	 0xfffc,		/* dst_mask */
1108130561Sobrien	 FALSE),		/* pcrel_offset */
110989857Sobrien
111089857Sobrien  /* Like R_PPC64_GOT16_LO, but for instructions with a DS field.  */
111189857Sobrien  HOWTO (R_PPC64_GOT16_LO_DS,	/* type */
111289857Sobrien	 0,			/* rightshift */
111389857Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
111489857Sobrien	 16,			/* bitsize */
1115130561Sobrien	 FALSE,			/* pc_relative */
111689857Sobrien	 0,			/* bitpos */
111789857Sobrien	 complain_overflow_dont, /* complain_on_overflow */
111899461Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
111989857Sobrien	 "R_PPC64_GOT16_LO_DS",	/* name */
1120130561Sobrien	 FALSE,			/* partial_inplace */
112189857Sobrien	 0,			/* src_mask */
112289857Sobrien	 0xfffc,		/* dst_mask */
1123130561Sobrien	 FALSE),		/* pcrel_offset */
112489857Sobrien
112589857Sobrien  /* Like R_PPC64_PLT16_LO, but for instructions with a DS field.  */
112689857Sobrien  HOWTO (R_PPC64_PLT16_LO_DS,	/* type */
112789857Sobrien	 0,			/* rightshift */
112889857Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
112989857Sobrien	 16,			/* bitsize */
1130130561Sobrien	 FALSE,			/* pc_relative */
113189857Sobrien	 0,			/* bitpos */
113289857Sobrien	 complain_overflow_dont, /* complain_on_overflow */
113399461Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
113489857Sobrien	 "R_PPC64_PLT16_LO_DS",	/* name */
1135130561Sobrien	 FALSE,			/* partial_inplace */
113689857Sobrien	 0,			/* src_mask */
113789857Sobrien	 0xfffc,		/* dst_mask */
1138130561Sobrien	 FALSE),		/* pcrel_offset */
113989857Sobrien
114089857Sobrien  /* Like R_PPC64_SECTOFF, but for instructions with a DS field.  */
114189857Sobrien  HOWTO (R_PPC64_SECTOFF_DS,	/* type */
114289857Sobrien	 0,			/* rightshift */
114399461Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
114499461Sobrien	 16,			/* bitsize */
1145130561Sobrien	 FALSE,			/* pc_relative */
114689857Sobrien	 0,			/* bitpos */
114789857Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
114899461Sobrien	 ppc64_elf_sectoff_reloc, /* special_function */
114989857Sobrien	 "R_PPC64_SECTOFF_DS",	/* name */
1150130561Sobrien	 FALSE,			/* partial_inplace */
115189857Sobrien	 0,			/* src_mask */
115299461Sobrien	 0xfffc,		/* dst_mask */
1153130561Sobrien	 FALSE),		/* pcrel_offset */
115489857Sobrien
115589857Sobrien  /* Like R_PPC64_SECTOFF_LO, but for instructions with a DS field.  */
115689857Sobrien  HOWTO (R_PPC64_SECTOFF_LO_DS, /* type */
115789857Sobrien	 0,			/* rightshift */
115889857Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
115989857Sobrien	 16,			/* bitsize */
1160130561Sobrien	 FALSE,			/* pc_relative */
116189857Sobrien	 0,			/* bitpos */
116289857Sobrien	 complain_overflow_dont, /* complain_on_overflow */
116399461Sobrien	 ppc64_elf_sectoff_reloc, /* special_function */
116489857Sobrien	 "R_PPC64_SECTOFF_LO_DS",/* name */
1165130561Sobrien	 FALSE,			/* partial_inplace */
116689857Sobrien	 0,			/* src_mask */
116789857Sobrien	 0xfffc,		/* dst_mask */
1168130561Sobrien	 FALSE),		/* pcrel_offset */
116989857Sobrien
117089857Sobrien  /* Like R_PPC64_TOC16, but for instructions with a DS field.  */
117189857Sobrien  HOWTO (R_PPC64_TOC16_DS,	/* type */
117289857Sobrien	 0,			/* rightshift */
117389857Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
117489857Sobrien	 16,			/* bitsize */
1175130561Sobrien	 FALSE,			/* pc_relative */
117689857Sobrien	 0,			/* bitpos */
117789857Sobrien	 complain_overflow_signed, /* complain_on_overflow */
117899461Sobrien	 ppc64_elf_toc_reloc,	/* special_function */
117989857Sobrien	 "R_PPC64_TOC16_DS",	/* name */
1180130561Sobrien	 FALSE,			/* partial_inplace */
118189857Sobrien	 0,			/* src_mask */
118289857Sobrien	 0xfffc,		/* dst_mask */
1183130561Sobrien	 FALSE),		/* pcrel_offset */
118489857Sobrien
118589857Sobrien  /* Like R_PPC64_TOC16_LO, but for instructions with a DS field.  */
118689857Sobrien  HOWTO (R_PPC64_TOC16_LO_DS,	/* type */
118789857Sobrien	 0,			/* rightshift */
118889857Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
118989857Sobrien	 16,			/* bitsize */
1190130561Sobrien	 FALSE,			/* pc_relative */
119189857Sobrien	 0,			/* bitpos */
119289857Sobrien	 complain_overflow_dont, /* complain_on_overflow */
119399461Sobrien	 ppc64_elf_toc_reloc,	/* special_function */
119489857Sobrien	 "R_PPC64_TOC16_LO_DS",	/* name */
1195130561Sobrien	 FALSE,			/* partial_inplace */
119689857Sobrien	 0,			/* src_mask */
119789857Sobrien	 0xfffc,		/* dst_mask */
1198130561Sobrien	 FALSE),		/* pcrel_offset */
119989857Sobrien
120089857Sobrien  /* Like R_PPC64_PLTGOT16, but for instructions with a DS field.  */
120189857Sobrien  /* FIXME: R_PPC64_PLTGOT16_DS not implemented.  */
1202218822Sdim  HOWTO (R_PPC64_PLTGOT16_DS,	/* type */
120389857Sobrien	 0,			/* rightshift */
120489857Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
120589857Sobrien	 16,			/* bitsize */
1206130561Sobrien	 FALSE,			/* pc_relative */
120789857Sobrien	 0,			/* bitpos */
120889857Sobrien	 complain_overflow_signed, /* complain_on_overflow */
120999461Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
121089857Sobrien	 "R_PPC64_PLTGOT16_DS",	/* name */
1211130561Sobrien	 FALSE,			/* partial_inplace */
121289857Sobrien	 0,			/* src_mask */
121389857Sobrien	 0xfffc,		/* dst_mask */
1214130561Sobrien	 FALSE),		/* pcrel_offset */
121589857Sobrien
121689857Sobrien  /* Like R_PPC64_PLTGOT16_LO, but for instructions with a DS field.  */
121789857Sobrien  /* FIXME: R_PPC64_PLTGOT16_LO not implemented.  */
121889857Sobrien  HOWTO (R_PPC64_PLTGOT16_LO_DS,/* type */
121989857Sobrien	 0,			/* rightshift */
122089857Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
122189857Sobrien	 16,			/* bitsize */
1222130561Sobrien	 FALSE,			/* pc_relative */
122389857Sobrien	 0,			/* bitpos */
122489857Sobrien	 complain_overflow_dont, /* complain_on_overflow */
122599461Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
122689857Sobrien	 "R_PPC64_PLTGOT16_LO_DS",/* name */
1227130561Sobrien	 FALSE,			/* partial_inplace */
122889857Sobrien	 0,			/* src_mask */
122989857Sobrien	 0xfffc,		/* dst_mask */
1230130561Sobrien	 FALSE),		/* pcrel_offset */
123189857Sobrien
1232130561Sobrien  /* Marker reloc for TLS.  */
1233130561Sobrien  HOWTO (R_PPC64_TLS,
1234130561Sobrien	 0,			/* rightshift */
1235130561Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
1236130561Sobrien	 32,			/* bitsize */
1237130561Sobrien	 FALSE,			/* pc_relative */
1238130561Sobrien	 0,			/* bitpos */
1239130561Sobrien	 complain_overflow_dont, /* complain_on_overflow */
1240130561Sobrien	 bfd_elf_generic_reloc,	/* special_function */
1241130561Sobrien	 "R_PPC64_TLS",		/* name */
1242130561Sobrien	 FALSE,			/* partial_inplace */
1243130561Sobrien	 0,			/* src_mask */
1244130561Sobrien	 0,			/* dst_mask */
1245130561Sobrien	 FALSE),		/* pcrel_offset */
1246130561Sobrien
1247130561Sobrien  /* Computes the load module index of the load module that contains the
1248130561Sobrien     definition of its TLS sym.  */
1249130561Sobrien  HOWTO (R_PPC64_DTPMOD64,
1250130561Sobrien	 0,			/* rightshift */
1251130561Sobrien	 4,			/* size (0 = byte, 1 = short, 2 = long) */
1252130561Sobrien	 64,			/* bitsize */
1253130561Sobrien	 FALSE,			/* pc_relative */
1254130561Sobrien	 0,			/* bitpos */
1255130561Sobrien	 complain_overflow_dont, /* complain_on_overflow */
1256130561Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
1257130561Sobrien	 "R_PPC64_DTPMOD64",	/* name */
1258130561Sobrien	 FALSE,			/* partial_inplace */
1259130561Sobrien	 0,			/* src_mask */
1260130561Sobrien	 ONES (64),		/* dst_mask */
1261130561Sobrien	 FALSE),		/* pcrel_offset */
1262130561Sobrien
1263130561Sobrien  /* Computes a dtv-relative displacement, the difference between the value
1264130561Sobrien     of sym+add and the base address of the thread-local storage block that
1265130561Sobrien     contains the definition of sym, minus 0x8000.  */
1266130561Sobrien  HOWTO (R_PPC64_DTPREL64,
1267130561Sobrien	 0,			/* rightshift */
1268130561Sobrien	 4,			/* size (0 = byte, 1 = short, 2 = long) */
1269130561Sobrien	 64,			/* bitsize */
1270130561Sobrien	 FALSE,			/* pc_relative */
1271130561Sobrien	 0,			/* bitpos */
1272130561Sobrien	 complain_overflow_dont, /* complain_on_overflow */
1273130561Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
1274130561Sobrien	 "R_PPC64_DTPREL64",	/* name */
1275130561Sobrien	 FALSE,			/* partial_inplace */
1276130561Sobrien	 0,			/* src_mask */
1277130561Sobrien	 ONES (64),		/* dst_mask */
1278130561Sobrien	 FALSE),		/* pcrel_offset */
1279130561Sobrien
1280130561Sobrien  /* A 16 bit dtprel reloc.  */
1281130561Sobrien  HOWTO (R_PPC64_DTPREL16,
1282130561Sobrien	 0,			/* rightshift */
1283130561Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
1284130561Sobrien	 16,			/* bitsize */
1285130561Sobrien	 FALSE,			/* pc_relative */
1286130561Sobrien	 0,			/* bitpos */
1287130561Sobrien	 complain_overflow_signed, /* complain_on_overflow */
1288130561Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
1289130561Sobrien	 "R_PPC64_DTPREL16",	/* name */
1290130561Sobrien	 FALSE,			/* partial_inplace */
1291130561Sobrien	 0,			/* src_mask */
1292130561Sobrien	 0xffff,		/* dst_mask */
1293130561Sobrien	 FALSE),		/* pcrel_offset */
1294130561Sobrien
1295130561Sobrien  /* Like DTPREL16, but no overflow.  */
1296130561Sobrien  HOWTO (R_PPC64_DTPREL16_LO,
1297130561Sobrien	 0,			/* rightshift */
1298130561Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
1299130561Sobrien	 16,			/* bitsize */
1300130561Sobrien	 FALSE,			/* pc_relative */
1301130561Sobrien	 0,			/* bitpos */
1302130561Sobrien	 complain_overflow_dont, /* complain_on_overflow */
1303130561Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
1304130561Sobrien	 "R_PPC64_DTPREL16_LO",	/* name */
1305130561Sobrien	 FALSE,			/* partial_inplace */
1306130561Sobrien	 0,			/* src_mask */
1307130561Sobrien	 0xffff,		/* dst_mask */
1308130561Sobrien	 FALSE),		/* pcrel_offset */
1309130561Sobrien
1310130561Sobrien  /* Like DTPREL16_LO, but next higher group of 16 bits.  */
1311130561Sobrien  HOWTO (R_PPC64_DTPREL16_HI,
1312130561Sobrien	 16,			/* rightshift */
1313130561Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
1314130561Sobrien	 16,			/* bitsize */
1315130561Sobrien	 FALSE,			/* pc_relative */
1316130561Sobrien	 0,			/* bitpos */
1317130561Sobrien	 complain_overflow_dont, /* complain_on_overflow */
1318130561Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
1319130561Sobrien	 "R_PPC64_DTPREL16_HI",	/* name */
1320130561Sobrien	 FALSE,			/* partial_inplace */
1321130561Sobrien	 0,			/* src_mask */
1322130561Sobrien	 0xffff,		/* dst_mask */
1323130561Sobrien	 FALSE),		/* pcrel_offset */
1324130561Sobrien
1325130561Sobrien  /* Like DTPREL16_HI, but adjust for low 16 bits.  */
1326130561Sobrien  HOWTO (R_PPC64_DTPREL16_HA,
1327130561Sobrien	 16,			/* rightshift */
1328130561Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
1329130561Sobrien	 16,			/* bitsize */
1330130561Sobrien	 FALSE,			/* pc_relative */
1331130561Sobrien	 0,			/* bitpos */
1332130561Sobrien	 complain_overflow_dont, /* complain_on_overflow */
1333130561Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
1334130561Sobrien	 "R_PPC64_DTPREL16_HA",	/* name */
1335130561Sobrien	 FALSE,			/* partial_inplace */
1336130561Sobrien	 0,			/* src_mask */
1337130561Sobrien	 0xffff,		/* dst_mask */
1338130561Sobrien	 FALSE),		/* pcrel_offset */
1339130561Sobrien
1340130561Sobrien  /* Like DTPREL16_HI, but next higher group of 16 bits.  */
1341130561Sobrien  HOWTO (R_PPC64_DTPREL16_HIGHER,
1342130561Sobrien	 32,			/* rightshift */
1343130561Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
1344130561Sobrien	 16,			/* bitsize */
1345130561Sobrien	 FALSE,			/* pc_relative */
1346130561Sobrien	 0,			/* bitpos */
1347130561Sobrien	 complain_overflow_dont, /* complain_on_overflow */
1348130561Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
1349130561Sobrien	 "R_PPC64_DTPREL16_HIGHER", /* name */
1350130561Sobrien	 FALSE,			/* partial_inplace */
1351130561Sobrien	 0,			/* src_mask */
1352130561Sobrien	 0xffff,		/* dst_mask */
1353130561Sobrien	 FALSE),		/* pcrel_offset */
1354130561Sobrien
1355130561Sobrien  /* Like DTPREL16_HIGHER, but adjust for low 16 bits.  */
1356130561Sobrien  HOWTO (R_PPC64_DTPREL16_HIGHERA,
1357130561Sobrien	 32,			/* rightshift */
1358130561Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
1359130561Sobrien	 16,			/* bitsize */
1360130561Sobrien	 FALSE,			/* pc_relative */
1361130561Sobrien	 0,			/* bitpos */
1362130561Sobrien	 complain_overflow_dont, /* complain_on_overflow */
1363130561Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
1364130561Sobrien	 "R_PPC64_DTPREL16_HIGHERA", /* name */
1365130561Sobrien	 FALSE,			/* partial_inplace */
1366130561Sobrien	 0,			/* src_mask */
1367130561Sobrien	 0xffff,		/* dst_mask */
1368130561Sobrien	 FALSE),		/* pcrel_offset */
1369130561Sobrien
1370130561Sobrien  /* Like DTPREL16_HIGHER, but next higher group of 16 bits.  */
1371130561Sobrien  HOWTO (R_PPC64_DTPREL16_HIGHEST,
1372130561Sobrien	 48,			/* rightshift */
1373130561Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
1374130561Sobrien	 16,			/* bitsize */
1375130561Sobrien	 FALSE,			/* pc_relative */
1376130561Sobrien	 0,			/* bitpos */
1377130561Sobrien	 complain_overflow_dont, /* complain_on_overflow */
1378130561Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
1379130561Sobrien	 "R_PPC64_DTPREL16_HIGHEST", /* name */
1380130561Sobrien	 FALSE,			/* partial_inplace */
1381130561Sobrien	 0,			/* src_mask */
1382130561Sobrien	 0xffff,		/* dst_mask */
1383130561Sobrien	 FALSE),		/* pcrel_offset */
1384130561Sobrien
1385130561Sobrien  /* Like DTPREL16_HIGHEST, but adjust for low 16 bits.  */
1386130561Sobrien  HOWTO (R_PPC64_DTPREL16_HIGHESTA,
1387130561Sobrien	 48,			/* rightshift */
1388130561Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
1389130561Sobrien	 16,			/* bitsize */
1390130561Sobrien	 FALSE,			/* pc_relative */
1391130561Sobrien	 0,			/* bitpos */
1392130561Sobrien	 complain_overflow_dont, /* complain_on_overflow */
1393130561Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
1394130561Sobrien	 "R_PPC64_DTPREL16_HIGHESTA", /* name */
1395130561Sobrien	 FALSE,			/* partial_inplace */
1396130561Sobrien	 0,			/* src_mask */
1397130561Sobrien	 0xffff,		/* dst_mask */
1398130561Sobrien	 FALSE),		/* pcrel_offset */
1399130561Sobrien
1400130561Sobrien  /* Like DTPREL16, but for insns with a DS field.  */
1401130561Sobrien  HOWTO (R_PPC64_DTPREL16_DS,
1402130561Sobrien	 0,			/* rightshift */
1403130561Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
1404130561Sobrien	 16,			/* bitsize */
1405130561Sobrien	 FALSE,			/* pc_relative */
1406130561Sobrien	 0,			/* bitpos */
1407130561Sobrien	 complain_overflow_signed, /* complain_on_overflow */
1408130561Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
1409130561Sobrien	 "R_PPC64_DTPREL16_DS",	/* name */
1410130561Sobrien	 FALSE,			/* partial_inplace */
1411130561Sobrien	 0,			/* src_mask */
1412130561Sobrien	 0xfffc,		/* dst_mask */
1413130561Sobrien	 FALSE),		/* pcrel_offset */
1414130561Sobrien
1415130561Sobrien  /* Like DTPREL16_DS, but no overflow.  */
1416130561Sobrien  HOWTO (R_PPC64_DTPREL16_LO_DS,
1417130561Sobrien	 0,			/* rightshift */
1418130561Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
1419130561Sobrien	 16,			/* bitsize */
1420130561Sobrien	 FALSE,			/* pc_relative */
1421130561Sobrien	 0,			/* bitpos */
1422130561Sobrien	 complain_overflow_dont, /* complain_on_overflow */
1423130561Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
1424130561Sobrien	 "R_PPC64_DTPREL16_LO_DS", /* name */
1425130561Sobrien	 FALSE,			/* partial_inplace */
1426130561Sobrien	 0,			/* src_mask */
1427130561Sobrien	 0xfffc,		/* dst_mask */
1428130561Sobrien	 FALSE),		/* pcrel_offset */
1429130561Sobrien
1430130561Sobrien  /* Computes a tp-relative displacement, the difference between the value of
1431130561Sobrien     sym+add and the value of the thread pointer (r13).  */
1432130561Sobrien  HOWTO (R_PPC64_TPREL64,
1433130561Sobrien	 0,			/* rightshift */
1434130561Sobrien	 4,			/* size (0 = byte, 1 = short, 2 = long) */
1435130561Sobrien	 64,			/* bitsize */
1436130561Sobrien	 FALSE,			/* pc_relative */
1437130561Sobrien	 0,			/* bitpos */
1438130561Sobrien	 complain_overflow_dont, /* complain_on_overflow */
1439130561Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
1440130561Sobrien	 "R_PPC64_TPREL64",	/* name */
1441130561Sobrien	 FALSE,			/* partial_inplace */
1442130561Sobrien	 0,			/* src_mask */
1443130561Sobrien	 ONES (64),		/* dst_mask */
1444130561Sobrien	 FALSE),		/* pcrel_offset */
1445130561Sobrien
1446130561Sobrien  /* A 16 bit tprel reloc.  */
1447130561Sobrien  HOWTO (R_PPC64_TPREL16,
1448130561Sobrien	 0,			/* rightshift */
1449130561Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
1450130561Sobrien	 16,			/* bitsize */
1451130561Sobrien	 FALSE,			/* pc_relative */
1452130561Sobrien	 0,			/* bitpos */
1453130561Sobrien	 complain_overflow_signed, /* complain_on_overflow */
1454130561Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
1455130561Sobrien	 "R_PPC64_TPREL16",	/* name */
1456130561Sobrien	 FALSE,			/* partial_inplace */
1457130561Sobrien	 0,			/* src_mask */
1458130561Sobrien	 0xffff,		/* dst_mask */
1459130561Sobrien	 FALSE),		/* pcrel_offset */
1460130561Sobrien
1461130561Sobrien  /* Like TPREL16, but no overflow.  */
1462130561Sobrien  HOWTO (R_PPC64_TPREL16_LO,
1463130561Sobrien	 0,			/* rightshift */
1464130561Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
1465130561Sobrien	 16,			/* bitsize */
1466130561Sobrien	 FALSE,			/* pc_relative */
1467130561Sobrien	 0,			/* bitpos */
1468130561Sobrien	 complain_overflow_dont, /* complain_on_overflow */
1469130561Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
1470130561Sobrien	 "R_PPC64_TPREL16_LO",	/* name */
1471130561Sobrien	 FALSE,			/* partial_inplace */
1472130561Sobrien	 0,			/* src_mask */
1473130561Sobrien	 0xffff,		/* dst_mask */
1474130561Sobrien	 FALSE),		/* pcrel_offset */
1475130561Sobrien
1476130561Sobrien  /* Like TPREL16_LO, but next higher group of 16 bits.  */
1477130561Sobrien  HOWTO (R_PPC64_TPREL16_HI,
1478130561Sobrien	 16,			/* rightshift */
1479130561Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
1480130561Sobrien	 16,			/* bitsize */
1481130561Sobrien	 FALSE,			/* pc_relative */
1482130561Sobrien	 0,			/* bitpos */
1483130561Sobrien	 complain_overflow_dont, /* complain_on_overflow */
1484130561Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
1485130561Sobrien	 "R_PPC64_TPREL16_HI",	/* name */
1486130561Sobrien	 FALSE,			/* partial_inplace */
1487130561Sobrien	 0,			/* src_mask */
1488130561Sobrien	 0xffff,		/* dst_mask */
1489130561Sobrien	 FALSE),		/* pcrel_offset */
1490130561Sobrien
1491130561Sobrien  /* Like TPREL16_HI, but adjust for low 16 bits.  */
1492130561Sobrien  HOWTO (R_PPC64_TPREL16_HA,
1493130561Sobrien	 16,			/* rightshift */
1494130561Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
1495130561Sobrien	 16,			/* bitsize */
1496130561Sobrien	 FALSE,			/* pc_relative */
1497130561Sobrien	 0,			/* bitpos */
1498130561Sobrien	 complain_overflow_dont, /* complain_on_overflow */
1499130561Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
1500130561Sobrien	 "R_PPC64_TPREL16_HA",	/* name */
1501130561Sobrien	 FALSE,			/* partial_inplace */
1502130561Sobrien	 0,			/* src_mask */
1503130561Sobrien	 0xffff,		/* dst_mask */
1504130561Sobrien	 FALSE),		/* pcrel_offset */
1505130561Sobrien
1506130561Sobrien  /* Like TPREL16_HI, but next higher group of 16 bits.  */
1507130561Sobrien  HOWTO (R_PPC64_TPREL16_HIGHER,
1508130561Sobrien	 32,			/* rightshift */
1509130561Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
1510130561Sobrien	 16,			/* bitsize */
1511130561Sobrien	 FALSE,			/* pc_relative */
1512130561Sobrien	 0,			/* bitpos */
1513130561Sobrien	 complain_overflow_dont, /* complain_on_overflow */
1514130561Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
1515130561Sobrien	 "R_PPC64_TPREL16_HIGHER",	/* name */
1516130561Sobrien	 FALSE,			/* partial_inplace */
1517130561Sobrien	 0,			/* src_mask */
1518130561Sobrien	 0xffff,		/* dst_mask */
1519130561Sobrien	 FALSE),		/* pcrel_offset */
1520130561Sobrien
1521130561Sobrien  /* Like TPREL16_HIGHER, but adjust for low 16 bits.  */
1522130561Sobrien  HOWTO (R_PPC64_TPREL16_HIGHERA,
1523130561Sobrien	 32,			/* rightshift */
1524130561Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
1525130561Sobrien	 16,			/* bitsize */
1526130561Sobrien	 FALSE,			/* pc_relative */
1527130561Sobrien	 0,			/* bitpos */
1528130561Sobrien	 complain_overflow_dont, /* complain_on_overflow */
1529130561Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
1530130561Sobrien	 "R_PPC64_TPREL16_HIGHERA", /* name */
1531130561Sobrien	 FALSE,			/* partial_inplace */
1532130561Sobrien	 0,			/* src_mask */
1533130561Sobrien	 0xffff,		/* dst_mask */
1534130561Sobrien	 FALSE),		/* pcrel_offset */
1535130561Sobrien
1536130561Sobrien  /* Like TPREL16_HIGHER, but next higher group of 16 bits.  */
1537130561Sobrien  HOWTO (R_PPC64_TPREL16_HIGHEST,
1538130561Sobrien	 48,			/* rightshift */
1539130561Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
1540130561Sobrien	 16,			/* bitsize */
1541130561Sobrien	 FALSE,			/* pc_relative */
1542130561Sobrien	 0,			/* bitpos */
1543130561Sobrien	 complain_overflow_dont, /* complain_on_overflow */
1544130561Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
1545130561Sobrien	 "R_PPC64_TPREL16_HIGHEST", /* name */
1546130561Sobrien	 FALSE,			/* partial_inplace */
1547130561Sobrien	 0,			/* src_mask */
1548130561Sobrien	 0xffff,		/* dst_mask */
1549130561Sobrien	 FALSE),		/* pcrel_offset */
1550130561Sobrien
1551130561Sobrien  /* Like TPREL16_HIGHEST, but adjust for low 16 bits.  */
1552130561Sobrien  HOWTO (R_PPC64_TPREL16_HIGHESTA,
1553130561Sobrien	 48,			/* rightshift */
1554130561Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
1555130561Sobrien	 16,			/* bitsize */
1556130561Sobrien	 FALSE,			/* pc_relative */
1557130561Sobrien	 0,			/* bitpos */
1558130561Sobrien	 complain_overflow_dont, /* complain_on_overflow */
1559130561Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
1560130561Sobrien	 "R_PPC64_TPREL16_HIGHESTA", /* name */
1561130561Sobrien	 FALSE,			/* partial_inplace */
1562130561Sobrien	 0,			/* src_mask */
1563130561Sobrien	 0xffff,		/* dst_mask */
1564130561Sobrien	 FALSE),		/* pcrel_offset */
1565130561Sobrien
1566130561Sobrien  /* Like TPREL16, but for insns with a DS field.  */
1567130561Sobrien  HOWTO (R_PPC64_TPREL16_DS,
1568130561Sobrien	 0,			/* rightshift */
1569130561Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
1570130561Sobrien	 16,			/* bitsize */
1571130561Sobrien	 FALSE,			/* pc_relative */
1572130561Sobrien	 0,			/* bitpos */
1573130561Sobrien	 complain_overflow_signed, /* complain_on_overflow */
1574130561Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
1575130561Sobrien	 "R_PPC64_TPREL16_DS",	/* name */
1576130561Sobrien	 FALSE,			/* partial_inplace */
1577130561Sobrien	 0,			/* src_mask */
1578130561Sobrien	 0xfffc,		/* dst_mask */
1579130561Sobrien	 FALSE),		/* pcrel_offset */
1580130561Sobrien
1581130561Sobrien  /* Like TPREL16_DS, but no overflow.  */
1582130561Sobrien  HOWTO (R_PPC64_TPREL16_LO_DS,
1583130561Sobrien	 0,			/* rightshift */
1584130561Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
1585130561Sobrien	 16,			/* bitsize */
1586130561Sobrien	 FALSE,			/* pc_relative */
1587130561Sobrien	 0,			/* bitpos */
1588130561Sobrien	 complain_overflow_dont, /* complain_on_overflow */
1589130561Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
1590130561Sobrien	 "R_PPC64_TPREL16_LO_DS", /* name */
1591130561Sobrien	 FALSE,			/* partial_inplace */
1592130561Sobrien	 0,			/* src_mask */
1593130561Sobrien	 0xfffc,		/* dst_mask */
1594130561Sobrien	 FALSE),		/* pcrel_offset */
1595130561Sobrien
1596130561Sobrien  /* Allocates two contiguous entries in the GOT to hold a tls_index structure,
1597130561Sobrien     with values (sym+add)@dtpmod and (sym+add)@dtprel, and computes the offset
1598130561Sobrien     to the first entry relative to the TOC base (r2).  */
1599130561Sobrien  HOWTO (R_PPC64_GOT_TLSGD16,
1600130561Sobrien	 0,			/* rightshift */
1601130561Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
1602130561Sobrien	 16,			/* bitsize */
1603130561Sobrien	 FALSE,			/* pc_relative */
1604130561Sobrien	 0,			/* bitpos */
1605130561Sobrien	 complain_overflow_signed, /* complain_on_overflow */
1606130561Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
1607130561Sobrien	 "R_PPC64_GOT_TLSGD16",	/* name */
1608130561Sobrien	 FALSE,			/* partial_inplace */
1609130561Sobrien	 0,			/* src_mask */
1610130561Sobrien	 0xffff,		/* dst_mask */
1611130561Sobrien	 FALSE),		/* pcrel_offset */
1612130561Sobrien
1613130561Sobrien  /* Like GOT_TLSGD16, but no overflow.  */
1614130561Sobrien  HOWTO (R_PPC64_GOT_TLSGD16_LO,
1615130561Sobrien	 0,			/* rightshift */
1616130561Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
1617130561Sobrien	 16,			/* bitsize */
1618130561Sobrien	 FALSE,			/* pc_relative */
1619130561Sobrien	 0,			/* bitpos */
1620130561Sobrien	 complain_overflow_dont, /* complain_on_overflow */
1621130561Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
1622130561Sobrien	 "R_PPC64_GOT_TLSGD16_LO", /* name */
1623130561Sobrien	 FALSE,			/* partial_inplace */
1624130561Sobrien	 0,			/* src_mask */
1625130561Sobrien	 0xffff,		/* dst_mask */
1626130561Sobrien	 FALSE),		/* pcrel_offset */
1627130561Sobrien
1628130561Sobrien  /* Like GOT_TLSGD16_LO, but next higher group of 16 bits.  */
1629130561Sobrien  HOWTO (R_PPC64_GOT_TLSGD16_HI,
1630130561Sobrien	 16,			/* rightshift */
1631130561Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
1632130561Sobrien	 16,			/* bitsize */
1633130561Sobrien	 FALSE,			/* pc_relative */
1634130561Sobrien	 0,			/* bitpos */
1635130561Sobrien	 complain_overflow_dont, /* complain_on_overflow */
1636130561Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
1637130561Sobrien	 "R_PPC64_GOT_TLSGD16_HI", /* name */
1638130561Sobrien	 FALSE,			/* partial_inplace */
1639130561Sobrien	 0,			/* src_mask */
1640130561Sobrien	 0xffff,		/* dst_mask */
1641130561Sobrien	 FALSE),		/* pcrel_offset */
1642130561Sobrien
1643130561Sobrien  /* Like GOT_TLSGD16_HI, but adjust for low 16 bits.  */
1644130561Sobrien  HOWTO (R_PPC64_GOT_TLSGD16_HA,
1645130561Sobrien	 16,			/* rightshift */
1646130561Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
1647130561Sobrien	 16,			/* bitsize */
1648130561Sobrien	 FALSE,			/* pc_relative */
1649130561Sobrien	 0,			/* bitpos */
1650130561Sobrien	 complain_overflow_dont, /* complain_on_overflow */
1651130561Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
1652130561Sobrien	 "R_PPC64_GOT_TLSGD16_HA", /* name */
1653130561Sobrien	 FALSE,			/* partial_inplace */
1654130561Sobrien	 0,			/* src_mask */
1655130561Sobrien	 0xffff,		/* dst_mask */
1656130561Sobrien	 FALSE),		/* pcrel_offset */
1657130561Sobrien
1658130561Sobrien  /* Allocates two contiguous entries in the GOT to hold a tls_index structure,
1659130561Sobrien     with values (sym+add)@dtpmod and zero, and computes the offset to the
1660130561Sobrien     first entry relative to the TOC base (r2).  */
1661130561Sobrien  HOWTO (R_PPC64_GOT_TLSLD16,
1662130561Sobrien	 0,			/* rightshift */
1663130561Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
1664130561Sobrien	 16,			/* bitsize */
1665130561Sobrien	 FALSE,			/* pc_relative */
1666130561Sobrien	 0,			/* bitpos */
1667130561Sobrien	 complain_overflow_signed, /* complain_on_overflow */
1668130561Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
1669130561Sobrien	 "R_PPC64_GOT_TLSLD16",	/* name */
1670130561Sobrien	 FALSE,			/* partial_inplace */
1671130561Sobrien	 0,			/* src_mask */
1672130561Sobrien	 0xffff,		/* dst_mask */
1673130561Sobrien	 FALSE),		/* pcrel_offset */
1674130561Sobrien
1675130561Sobrien  /* Like GOT_TLSLD16, but no overflow.  */
1676130561Sobrien  HOWTO (R_PPC64_GOT_TLSLD16_LO,
1677130561Sobrien	 0,			/* rightshift */
1678130561Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
1679130561Sobrien	 16,			/* bitsize */
1680130561Sobrien	 FALSE,			/* pc_relative */
1681130561Sobrien	 0,			/* bitpos */
1682130561Sobrien	 complain_overflow_dont, /* complain_on_overflow */
1683130561Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
1684130561Sobrien	 "R_PPC64_GOT_TLSLD16_LO", /* name */
1685130561Sobrien	 FALSE,			/* partial_inplace */
1686130561Sobrien	 0,			/* src_mask */
1687130561Sobrien	 0xffff,		/* dst_mask */
1688130561Sobrien	 FALSE),		/* pcrel_offset */
1689130561Sobrien
1690130561Sobrien  /* Like GOT_TLSLD16_LO, but next higher group of 16 bits.  */
1691130561Sobrien  HOWTO (R_PPC64_GOT_TLSLD16_HI,
1692130561Sobrien	 16,			/* rightshift */
1693130561Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
1694130561Sobrien	 16,			/* bitsize */
1695130561Sobrien	 FALSE,			/* pc_relative */
1696130561Sobrien	 0,			/* bitpos */
1697130561Sobrien	 complain_overflow_dont, /* complain_on_overflow */
1698130561Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
1699130561Sobrien	 "R_PPC64_GOT_TLSLD16_HI", /* name */
1700130561Sobrien	 FALSE,			/* partial_inplace */
1701130561Sobrien	 0,			/* src_mask */
1702130561Sobrien	 0xffff,		/* dst_mask */
1703130561Sobrien	 FALSE),		/* pcrel_offset */
1704130561Sobrien
1705130561Sobrien  /* Like GOT_TLSLD16_HI, but adjust for low 16 bits.  */
1706130561Sobrien  HOWTO (R_PPC64_GOT_TLSLD16_HA,
1707130561Sobrien	 16,			/* rightshift */
1708130561Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
1709130561Sobrien	 16,			/* bitsize */
1710130561Sobrien	 FALSE,			/* pc_relative */
1711130561Sobrien	 0,			/* bitpos */
1712130561Sobrien	 complain_overflow_dont, /* complain_on_overflow */
1713130561Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
1714130561Sobrien	 "R_PPC64_GOT_TLSLD16_HA", /* name */
1715130561Sobrien	 FALSE,			/* partial_inplace */
1716130561Sobrien	 0,			/* src_mask */
1717130561Sobrien	 0xffff,		/* dst_mask */
1718130561Sobrien	 FALSE),		/* pcrel_offset */
1719130561Sobrien
1720130561Sobrien  /* Allocates an entry in the GOT with value (sym+add)@dtprel, and computes
1721130561Sobrien     the offset to the entry relative to the TOC base (r2).  */
1722130561Sobrien  HOWTO (R_PPC64_GOT_DTPREL16_DS,
1723130561Sobrien	 0,			/* rightshift */
1724130561Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
1725130561Sobrien	 16,			/* bitsize */
1726130561Sobrien	 FALSE,			/* pc_relative */
1727130561Sobrien	 0,			/* bitpos */
1728130561Sobrien	 complain_overflow_signed, /* complain_on_overflow */
1729130561Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
1730130561Sobrien	 "R_PPC64_GOT_DTPREL16_DS", /* name */
1731130561Sobrien	 FALSE,			/* partial_inplace */
1732130561Sobrien	 0,			/* src_mask */
1733130561Sobrien	 0xfffc,		/* dst_mask */
1734130561Sobrien	 FALSE),		/* pcrel_offset */
1735130561Sobrien
1736130561Sobrien  /* Like GOT_DTPREL16_DS, but no overflow.  */
1737130561Sobrien  HOWTO (R_PPC64_GOT_DTPREL16_LO_DS,
1738130561Sobrien	 0,			/* rightshift */
1739130561Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
1740130561Sobrien	 16,			/* bitsize */
1741130561Sobrien	 FALSE,			/* pc_relative */
1742130561Sobrien	 0,			/* bitpos */
1743130561Sobrien	 complain_overflow_dont, /* complain_on_overflow */
1744130561Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
1745130561Sobrien	 "R_PPC64_GOT_DTPREL16_LO_DS", /* name */
1746130561Sobrien	 FALSE,			/* partial_inplace */
1747130561Sobrien	 0,			/* src_mask */
1748130561Sobrien	 0xfffc,		/* dst_mask */
1749130561Sobrien	 FALSE),		/* pcrel_offset */
1750130561Sobrien
1751130561Sobrien  /* Like GOT_DTPREL16_LO_DS, but next higher group of 16 bits.  */
1752130561Sobrien  HOWTO (R_PPC64_GOT_DTPREL16_HI,
1753130561Sobrien	 16,			/* rightshift */
1754130561Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
1755130561Sobrien	 16,			/* bitsize */
1756130561Sobrien	 FALSE,			/* pc_relative */
1757130561Sobrien	 0,			/* bitpos */
1758130561Sobrien	 complain_overflow_dont, /* complain_on_overflow */
1759130561Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
1760130561Sobrien	 "R_PPC64_GOT_DTPREL16_HI", /* name */
1761130561Sobrien	 FALSE,			/* partial_inplace */
1762130561Sobrien	 0,			/* src_mask */
1763130561Sobrien	 0xffff,		/* dst_mask */
1764130561Sobrien	 FALSE),		/* pcrel_offset */
1765130561Sobrien
1766130561Sobrien  /* Like GOT_DTPREL16_HI, but adjust for low 16 bits.  */
1767130561Sobrien  HOWTO (R_PPC64_GOT_DTPREL16_HA,
1768130561Sobrien	 16,			/* rightshift */
1769130561Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
1770130561Sobrien	 16,			/* bitsize */
1771130561Sobrien	 FALSE,			/* pc_relative */
1772130561Sobrien	 0,			/* bitpos */
1773130561Sobrien	 complain_overflow_dont, /* complain_on_overflow */
1774130561Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
1775130561Sobrien	 "R_PPC64_GOT_DTPREL16_HA", /* name */
1776130561Sobrien	 FALSE,			/* partial_inplace */
1777130561Sobrien	 0,			/* src_mask */
1778130561Sobrien	 0xffff,		/* dst_mask */
1779130561Sobrien	 FALSE),		/* pcrel_offset */
1780130561Sobrien
1781130561Sobrien  /* Allocates an entry in the GOT with value (sym+add)@tprel, and computes the
1782130561Sobrien     offset to the entry relative to the TOC base (r2).  */
1783130561Sobrien  HOWTO (R_PPC64_GOT_TPREL16_DS,
1784130561Sobrien	 0,			/* rightshift */
1785130561Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
1786130561Sobrien	 16,			/* bitsize */
1787130561Sobrien	 FALSE,			/* pc_relative */
1788130561Sobrien	 0,			/* bitpos */
1789130561Sobrien	 complain_overflow_signed, /* complain_on_overflow */
1790130561Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
1791130561Sobrien	 "R_PPC64_GOT_TPREL16_DS", /* name */
1792130561Sobrien	 FALSE,			/* partial_inplace */
1793130561Sobrien	 0,			/* src_mask */
1794130561Sobrien	 0xfffc,		/* dst_mask */
1795130561Sobrien	 FALSE),		/* pcrel_offset */
1796130561Sobrien
1797130561Sobrien  /* Like GOT_TPREL16_DS, but no overflow.  */
1798130561Sobrien  HOWTO (R_PPC64_GOT_TPREL16_LO_DS,
1799130561Sobrien	 0,			/* rightshift */
1800130561Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
1801130561Sobrien	 16,			/* bitsize */
1802130561Sobrien	 FALSE,			/* pc_relative */
1803130561Sobrien	 0,			/* bitpos */
1804130561Sobrien	 complain_overflow_dont, /* complain_on_overflow */
1805130561Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
1806130561Sobrien	 "R_PPC64_GOT_TPREL16_LO_DS", /* name */
1807130561Sobrien	 FALSE,			/* partial_inplace */
1808130561Sobrien	 0,			/* src_mask */
1809130561Sobrien	 0xfffc,		/* dst_mask */
1810130561Sobrien	 FALSE),		/* pcrel_offset */
1811130561Sobrien
1812130561Sobrien  /* Like GOT_TPREL16_LO_DS, but next higher group of 16 bits.  */
1813130561Sobrien  HOWTO (R_PPC64_GOT_TPREL16_HI,
1814130561Sobrien	 16,			/* rightshift */
1815130561Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
1816130561Sobrien	 16,			/* bitsize */
1817130561Sobrien	 FALSE,			/* pc_relative */
1818130561Sobrien	 0,			/* bitpos */
1819130561Sobrien	 complain_overflow_dont, /* complain_on_overflow */
1820130561Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
1821130561Sobrien	 "R_PPC64_GOT_TPREL16_HI", /* name */
1822130561Sobrien	 FALSE,			/* partial_inplace */
1823130561Sobrien	 0,			/* src_mask */
1824130561Sobrien	 0xffff,		/* dst_mask */
1825130561Sobrien	 FALSE),		/* pcrel_offset */
1826130561Sobrien
1827130561Sobrien  /* Like GOT_TPREL16_HI, but adjust for low 16 bits.  */
1828130561Sobrien  HOWTO (R_PPC64_GOT_TPREL16_HA,
1829130561Sobrien	 16,			/* rightshift */
1830130561Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
1831130561Sobrien	 16,			/* bitsize */
1832130561Sobrien	 FALSE,			/* pc_relative */
1833130561Sobrien	 0,			/* bitpos */
1834130561Sobrien	 complain_overflow_dont, /* complain_on_overflow */
1835130561Sobrien	 ppc64_elf_unhandled_reloc, /* special_function */
1836130561Sobrien	 "R_PPC64_GOT_TPREL16_HA", /* name */
1837130561Sobrien	 FALSE,			/* partial_inplace */
1838130561Sobrien	 0,			/* src_mask */
1839130561Sobrien	 0xffff,		/* dst_mask */
1840130561Sobrien	 FALSE),		/* pcrel_offset */
1841130561Sobrien
184289857Sobrien  /* GNU extension to record C++ vtable hierarchy.  */
184389857Sobrien  HOWTO (R_PPC64_GNU_VTINHERIT,	/* type */
184489857Sobrien	 0,			/* rightshift */
184589857Sobrien	 0,			/* size (0 = byte, 1 = short, 2 = long) */
184689857Sobrien	 0,			/* bitsize */
1847130561Sobrien	 FALSE,			/* pc_relative */
184889857Sobrien	 0,			/* bitpos */
184989857Sobrien	 complain_overflow_dont, /* complain_on_overflow */
185089857Sobrien	 NULL,			/* special_function */
185189857Sobrien	 "R_PPC64_GNU_VTINHERIT", /* name */
1852130561Sobrien	 FALSE,			/* partial_inplace */
185389857Sobrien	 0,			/* src_mask */
185489857Sobrien	 0,			/* dst_mask */
1855130561Sobrien	 FALSE),		/* pcrel_offset */
185689857Sobrien
185789857Sobrien  /* GNU extension to record C++ vtable member usage.  */
185889857Sobrien  HOWTO (R_PPC64_GNU_VTENTRY,	/* type */
185989857Sobrien	 0,			/* rightshift */
186089857Sobrien	 0,			/* size (0 = byte, 1 = short, 2 = long) */
186189857Sobrien	 0,			/* bitsize */
1862130561Sobrien	 FALSE,			/* pc_relative */
186389857Sobrien	 0,			/* bitpos */
186489857Sobrien	 complain_overflow_dont, /* complain_on_overflow */
186589857Sobrien	 NULL,			/* special_function */
186689857Sobrien	 "R_PPC64_GNU_VTENTRY",	/* name */
1867130561Sobrien	 FALSE,			/* partial_inplace */
186889857Sobrien	 0,			/* src_mask */
186989857Sobrien	 0,			/* dst_mask */
1870130561Sobrien	 FALSE),		/* pcrel_offset */
187189857Sobrien};
187289857Sobrien
187389857Sobrien
187489857Sobrien/* Initialize the ppc64_elf_howto_table, so that linear accesses can
187589857Sobrien   be done.  */
187689857Sobrien
187789857Sobrienstatic void
1878130561Sobrienppc_howto_init (void)
187989857Sobrien{
188089857Sobrien  unsigned int i, type;
188189857Sobrien
188289857Sobrien  for (i = 0;
188389857Sobrien       i < sizeof (ppc64_elf_howto_raw) / sizeof (ppc64_elf_howto_raw[0]);
188489857Sobrien       i++)
188589857Sobrien    {
188689857Sobrien      type = ppc64_elf_howto_raw[i].type;
188789857Sobrien      BFD_ASSERT (type < (sizeof (ppc64_elf_howto_table)
188889857Sobrien			  / sizeof (ppc64_elf_howto_table[0])));
188989857Sobrien      ppc64_elf_howto_table[type] = &ppc64_elf_howto_raw[i];
189089857Sobrien    }
189189857Sobrien}
189289857Sobrien
189389857Sobrienstatic reloc_howto_type *
1894130561Sobrienppc64_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
1895130561Sobrien			     bfd_reloc_code_real_type code)
189689857Sobrien{
1897130561Sobrien  enum elf_ppc64_reloc_type r = R_PPC64_NONE;
189889857Sobrien
189989857Sobrien  if (!ppc64_elf_howto_table[R_PPC64_ADDR32])
190089857Sobrien    /* Initialize howto table if needed.  */
190189857Sobrien    ppc_howto_init ();
190289857Sobrien
1903130561Sobrien  switch (code)
190489857Sobrien    {
190589857Sobrien    default:
1906130561Sobrien      return NULL;
190789857Sobrien
1908130561Sobrien    case BFD_RELOC_NONE:			r = R_PPC64_NONE;
190989857Sobrien      break;
1910130561Sobrien    case BFD_RELOC_32:				r = R_PPC64_ADDR32;
191189857Sobrien      break;
1912130561Sobrien    case BFD_RELOC_PPC_BA26:			r = R_PPC64_ADDR24;
191389857Sobrien      break;
1914130561Sobrien    case BFD_RELOC_16:				r = R_PPC64_ADDR16;
191589857Sobrien      break;
1916130561Sobrien    case BFD_RELOC_LO16:			r = R_PPC64_ADDR16_LO;
191789857Sobrien      break;
1918130561Sobrien    case BFD_RELOC_HI16:			r = R_PPC64_ADDR16_HI;
191989857Sobrien      break;
1920130561Sobrien    case BFD_RELOC_HI16_S:			r = R_PPC64_ADDR16_HA;
192189857Sobrien      break;
1922130561Sobrien    case BFD_RELOC_PPC_BA16:			r = R_PPC64_ADDR14;
192389857Sobrien      break;
1924130561Sobrien    case BFD_RELOC_PPC_BA16_BRTAKEN:		r = R_PPC64_ADDR14_BRTAKEN;
192589857Sobrien      break;
1926130561Sobrien    case BFD_RELOC_PPC_BA16_BRNTAKEN:		r = R_PPC64_ADDR14_BRNTAKEN;
192789857Sobrien      break;
1928130561Sobrien    case BFD_RELOC_PPC_B26:			r = R_PPC64_REL24;
192989857Sobrien      break;
1930130561Sobrien    case BFD_RELOC_PPC_B16:			r = R_PPC64_REL14;
193189857Sobrien      break;
1932130561Sobrien    case BFD_RELOC_PPC_B16_BRTAKEN:		r = R_PPC64_REL14_BRTAKEN;
193389857Sobrien      break;
1934130561Sobrien    case BFD_RELOC_PPC_B16_BRNTAKEN:		r = R_PPC64_REL14_BRNTAKEN;
193589857Sobrien      break;
1936130561Sobrien    case BFD_RELOC_16_GOTOFF:			r = R_PPC64_GOT16;
193789857Sobrien      break;
1938130561Sobrien    case BFD_RELOC_LO16_GOTOFF:			r = R_PPC64_GOT16_LO;
193989857Sobrien      break;
1940130561Sobrien    case BFD_RELOC_HI16_GOTOFF:			r = R_PPC64_GOT16_HI;
194189857Sobrien      break;
1942130561Sobrien    case BFD_RELOC_HI16_S_GOTOFF:		r = R_PPC64_GOT16_HA;
194389857Sobrien      break;
1944130561Sobrien    case BFD_RELOC_PPC_COPY:			r = R_PPC64_COPY;
194589857Sobrien      break;
1946130561Sobrien    case BFD_RELOC_PPC_GLOB_DAT:		r = R_PPC64_GLOB_DAT;
194789857Sobrien      break;
1948130561Sobrien    case BFD_RELOC_32_PCREL:			r = R_PPC64_REL32;
194989857Sobrien      break;
1950130561Sobrien    case BFD_RELOC_32_PLTOFF:			r = R_PPC64_PLT32;
195189857Sobrien      break;
1952130561Sobrien    case BFD_RELOC_32_PLT_PCREL:		r = R_PPC64_PLTREL32;
195389857Sobrien      break;
1954130561Sobrien    case BFD_RELOC_LO16_PLTOFF:			r = R_PPC64_PLT16_LO;
195589857Sobrien      break;
1956130561Sobrien    case BFD_RELOC_HI16_PLTOFF:			r = R_PPC64_PLT16_HI;
195789857Sobrien      break;
1958130561Sobrien    case BFD_RELOC_HI16_S_PLTOFF:		r = R_PPC64_PLT16_HA;
195989857Sobrien      break;
1960130561Sobrien    case BFD_RELOC_16_BASEREL:			r = R_PPC64_SECTOFF;
196189857Sobrien      break;
1962130561Sobrien    case BFD_RELOC_LO16_BASEREL:		r = R_PPC64_SECTOFF_LO;
196389857Sobrien      break;
1964130561Sobrien    case BFD_RELOC_HI16_BASEREL:		r = R_PPC64_SECTOFF_HI;
196589857Sobrien      break;
1966130561Sobrien    case BFD_RELOC_HI16_S_BASEREL:		r = R_PPC64_SECTOFF_HA;
196789857Sobrien      break;
1968130561Sobrien    case BFD_RELOC_CTOR:			r = R_PPC64_ADDR64;
196989857Sobrien      break;
1970130561Sobrien    case BFD_RELOC_64:				r = R_PPC64_ADDR64;
197189857Sobrien      break;
1972130561Sobrien    case BFD_RELOC_PPC64_HIGHER:		r = R_PPC64_ADDR16_HIGHER;
197389857Sobrien      break;
1974130561Sobrien    case BFD_RELOC_PPC64_HIGHER_S:		r = R_PPC64_ADDR16_HIGHERA;
197589857Sobrien      break;
1976130561Sobrien    case BFD_RELOC_PPC64_HIGHEST:		r = R_PPC64_ADDR16_HIGHEST;
197789857Sobrien      break;
1978130561Sobrien    case BFD_RELOC_PPC64_HIGHEST_S:		r = R_PPC64_ADDR16_HIGHESTA;
197989857Sobrien      break;
1980130561Sobrien    case BFD_RELOC_64_PCREL:			r = R_PPC64_REL64;
198189857Sobrien      break;
1982130561Sobrien    case BFD_RELOC_64_PLTOFF:			r = R_PPC64_PLT64;
198389857Sobrien      break;
1984130561Sobrien    case BFD_RELOC_64_PLT_PCREL:		r = R_PPC64_PLTREL64;
198589857Sobrien      break;
1986130561Sobrien    case BFD_RELOC_PPC_TOC16:			r = R_PPC64_TOC16;
198789857Sobrien      break;
1988130561Sobrien    case BFD_RELOC_PPC64_TOC16_LO:		r = R_PPC64_TOC16_LO;
198989857Sobrien      break;
1990130561Sobrien    case BFD_RELOC_PPC64_TOC16_HI:		r = R_PPC64_TOC16_HI;
199189857Sobrien      break;
1992130561Sobrien    case BFD_RELOC_PPC64_TOC16_HA:		r = R_PPC64_TOC16_HA;
199389857Sobrien      break;
1994130561Sobrien    case BFD_RELOC_PPC64_TOC:			r = R_PPC64_TOC;
199589857Sobrien      break;
1996130561Sobrien    case BFD_RELOC_PPC64_PLTGOT16:		r = R_PPC64_PLTGOT16;
199789857Sobrien      break;
1998130561Sobrien    case BFD_RELOC_PPC64_PLTGOT16_LO:		r = R_PPC64_PLTGOT16_LO;
199989857Sobrien      break;
2000130561Sobrien    case BFD_RELOC_PPC64_PLTGOT16_HI:		r = R_PPC64_PLTGOT16_HI;
200189857Sobrien      break;
2002130561Sobrien    case BFD_RELOC_PPC64_PLTGOT16_HA:		r = R_PPC64_PLTGOT16_HA;
200389857Sobrien      break;
2004130561Sobrien    case BFD_RELOC_PPC64_ADDR16_DS:		r = R_PPC64_ADDR16_DS;
200589857Sobrien      break;
2006130561Sobrien    case BFD_RELOC_PPC64_ADDR16_LO_DS:		r = R_PPC64_ADDR16_LO_DS;
200789857Sobrien      break;
2008130561Sobrien    case BFD_RELOC_PPC64_GOT16_DS:		r = R_PPC64_GOT16_DS;
200989857Sobrien      break;
2010130561Sobrien    case BFD_RELOC_PPC64_GOT16_LO_DS:		r = R_PPC64_GOT16_LO_DS;
201189857Sobrien      break;
2012130561Sobrien    case BFD_RELOC_PPC64_PLT16_LO_DS:		r = R_PPC64_PLT16_LO_DS;
201389857Sobrien      break;
2014130561Sobrien    case BFD_RELOC_PPC64_SECTOFF_DS:		r = R_PPC64_SECTOFF_DS;
201589857Sobrien      break;
2016130561Sobrien    case BFD_RELOC_PPC64_SECTOFF_LO_DS:		r = R_PPC64_SECTOFF_LO_DS;
201789857Sobrien      break;
2018130561Sobrien    case BFD_RELOC_PPC64_TOC16_DS:		r = R_PPC64_TOC16_DS;
201989857Sobrien      break;
2020130561Sobrien    case BFD_RELOC_PPC64_TOC16_LO_DS:		r = R_PPC64_TOC16_LO_DS;
202189857Sobrien      break;
2022130561Sobrien    case BFD_RELOC_PPC64_PLTGOT16_DS:		r = R_PPC64_PLTGOT16_DS;
202389857Sobrien      break;
2024130561Sobrien    case BFD_RELOC_PPC64_PLTGOT16_LO_DS:	r = R_PPC64_PLTGOT16_LO_DS;
202589857Sobrien      break;
2026130561Sobrien    case BFD_RELOC_PPC_TLS:			r = R_PPC64_TLS;
202789857Sobrien      break;
2028130561Sobrien    case BFD_RELOC_PPC_DTPMOD:			r = R_PPC64_DTPMOD64;
202989857Sobrien      break;
2030130561Sobrien    case BFD_RELOC_PPC_TPREL16:			r = R_PPC64_TPREL16;
2031130561Sobrien      break;
2032130561Sobrien    case BFD_RELOC_PPC_TPREL16_LO:		r = R_PPC64_TPREL16_LO;
2033130561Sobrien      break;
2034130561Sobrien    case BFD_RELOC_PPC_TPREL16_HI:		r = R_PPC64_TPREL16_HI;
2035130561Sobrien      break;
2036130561Sobrien    case BFD_RELOC_PPC_TPREL16_HA:		r = R_PPC64_TPREL16_HA;
2037130561Sobrien      break;
2038130561Sobrien    case BFD_RELOC_PPC_TPREL:			r = R_PPC64_TPREL64;
2039130561Sobrien      break;
2040130561Sobrien    case BFD_RELOC_PPC_DTPREL16:		r = R_PPC64_DTPREL16;
2041130561Sobrien      break;
2042130561Sobrien    case BFD_RELOC_PPC_DTPREL16_LO:		r = R_PPC64_DTPREL16_LO;
2043130561Sobrien      break;
2044130561Sobrien    case BFD_RELOC_PPC_DTPREL16_HI:		r = R_PPC64_DTPREL16_HI;
2045130561Sobrien      break;
2046130561Sobrien    case BFD_RELOC_PPC_DTPREL16_HA:		r = R_PPC64_DTPREL16_HA;
2047130561Sobrien      break;
2048130561Sobrien    case BFD_RELOC_PPC_DTPREL:			r = R_PPC64_DTPREL64;
2049130561Sobrien      break;
2050130561Sobrien    case BFD_RELOC_PPC_GOT_TLSGD16:		r = R_PPC64_GOT_TLSGD16;
2051130561Sobrien      break;
2052130561Sobrien    case BFD_RELOC_PPC_GOT_TLSGD16_LO:		r = R_PPC64_GOT_TLSGD16_LO;
2053130561Sobrien      break;
2054130561Sobrien    case BFD_RELOC_PPC_GOT_TLSGD16_HI:		r = R_PPC64_GOT_TLSGD16_HI;
2055130561Sobrien      break;
2056130561Sobrien    case BFD_RELOC_PPC_GOT_TLSGD16_HA:		r = R_PPC64_GOT_TLSGD16_HA;
2057130561Sobrien      break;
2058130561Sobrien    case BFD_RELOC_PPC_GOT_TLSLD16:		r = R_PPC64_GOT_TLSLD16;
2059130561Sobrien      break;
2060130561Sobrien    case BFD_RELOC_PPC_GOT_TLSLD16_LO:		r = R_PPC64_GOT_TLSLD16_LO;
2061130561Sobrien      break;
2062130561Sobrien    case BFD_RELOC_PPC_GOT_TLSLD16_HI:		r = R_PPC64_GOT_TLSLD16_HI;
2063130561Sobrien      break;
2064130561Sobrien    case BFD_RELOC_PPC_GOT_TLSLD16_HA:		r = R_PPC64_GOT_TLSLD16_HA;
2065130561Sobrien      break;
2066130561Sobrien    case BFD_RELOC_PPC_GOT_TPREL16:		r = R_PPC64_GOT_TPREL16_DS;
2067130561Sobrien      break;
2068130561Sobrien    case BFD_RELOC_PPC_GOT_TPREL16_LO:		r = R_PPC64_GOT_TPREL16_LO_DS;
2069130561Sobrien      break;
2070130561Sobrien    case BFD_RELOC_PPC_GOT_TPREL16_HI:		r = R_PPC64_GOT_TPREL16_HI;
2071130561Sobrien      break;
2072130561Sobrien    case BFD_RELOC_PPC_GOT_TPREL16_HA:		r = R_PPC64_GOT_TPREL16_HA;
2073130561Sobrien      break;
2074130561Sobrien    case BFD_RELOC_PPC_GOT_DTPREL16:		r = R_PPC64_GOT_DTPREL16_DS;
2075130561Sobrien      break;
2076130561Sobrien    case BFD_RELOC_PPC_GOT_DTPREL16_LO:		r = R_PPC64_GOT_DTPREL16_LO_DS;
2077130561Sobrien      break;
2078130561Sobrien    case BFD_RELOC_PPC_GOT_DTPREL16_HI:		r = R_PPC64_GOT_DTPREL16_HI;
2079130561Sobrien      break;
2080130561Sobrien    case BFD_RELOC_PPC_GOT_DTPREL16_HA:		r = R_PPC64_GOT_DTPREL16_HA;
2081130561Sobrien      break;
2082130561Sobrien    case BFD_RELOC_PPC64_TPREL16_DS:		r = R_PPC64_TPREL16_DS;
2083130561Sobrien      break;
2084130561Sobrien    case BFD_RELOC_PPC64_TPREL16_LO_DS:		r = R_PPC64_TPREL16_LO_DS;
2085130561Sobrien      break;
2086130561Sobrien    case BFD_RELOC_PPC64_TPREL16_HIGHER:	r = R_PPC64_TPREL16_HIGHER;
2087130561Sobrien      break;
2088130561Sobrien    case BFD_RELOC_PPC64_TPREL16_HIGHERA:	r = R_PPC64_TPREL16_HIGHERA;
2089130561Sobrien      break;
2090130561Sobrien    case BFD_RELOC_PPC64_TPREL16_HIGHEST:	r = R_PPC64_TPREL16_HIGHEST;
2091130561Sobrien      break;
2092130561Sobrien    case BFD_RELOC_PPC64_TPREL16_HIGHESTA:	r = R_PPC64_TPREL16_HIGHESTA;
2093130561Sobrien      break;
2094130561Sobrien    case BFD_RELOC_PPC64_DTPREL16_DS:		r = R_PPC64_DTPREL16_DS;
2095130561Sobrien      break;
2096130561Sobrien    case BFD_RELOC_PPC64_DTPREL16_LO_DS:	r = R_PPC64_DTPREL16_LO_DS;
2097130561Sobrien      break;
2098130561Sobrien    case BFD_RELOC_PPC64_DTPREL16_HIGHER:	r = R_PPC64_DTPREL16_HIGHER;
2099130561Sobrien      break;
2100130561Sobrien    case BFD_RELOC_PPC64_DTPREL16_HIGHERA:	r = R_PPC64_DTPREL16_HIGHERA;
2101130561Sobrien      break;
2102130561Sobrien    case BFD_RELOC_PPC64_DTPREL16_HIGHEST:	r = R_PPC64_DTPREL16_HIGHEST;
2103130561Sobrien      break;
2104130561Sobrien    case BFD_RELOC_PPC64_DTPREL16_HIGHESTA:	r = R_PPC64_DTPREL16_HIGHESTA;
2105130561Sobrien      break;
2106130561Sobrien    case BFD_RELOC_VTABLE_INHERIT:		r = R_PPC64_GNU_VTINHERIT;
2107130561Sobrien      break;
2108130561Sobrien    case BFD_RELOC_VTABLE_ENTRY:		r = R_PPC64_GNU_VTENTRY;
2109130561Sobrien      break;
211089857Sobrien    }
211189857Sobrien
2112130561Sobrien  return ppc64_elf_howto_table[r];
211389857Sobrien};
211489857Sobrien
2115218822Sdimstatic reloc_howto_type *
2116218822Sdimppc64_elf_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
2117218822Sdim			     const char *r_name)
2118218822Sdim{
2119218822Sdim  unsigned int i;
2120218822Sdim
2121218822Sdim  for (i = 0;
2122218822Sdim       i < sizeof (ppc64_elf_howto_raw) / sizeof (ppc64_elf_howto_raw[0]);
2123218822Sdim       i++)
2124218822Sdim    if (ppc64_elf_howto_raw[i].name != NULL
2125218822Sdim	&& strcasecmp (ppc64_elf_howto_raw[i].name, r_name) == 0)
2126218822Sdim      return &ppc64_elf_howto_raw[i];
2127218822Sdim
2128218822Sdim  return NULL;
2129218822Sdim}
2130218822Sdim
213189857Sobrien/* Set the howto pointer for a PowerPC ELF reloc.  */
213289857Sobrien
213389857Sobrienstatic void
2134130561Sobrienppc64_elf_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr,
2135130561Sobrien			 Elf_Internal_Rela *dst)
213689857Sobrien{
213789857Sobrien  unsigned int type;
213889857Sobrien
2139104834Sobrien  /* Initialize howto table if needed.  */
214089857Sobrien  if (!ppc64_elf_howto_table[R_PPC64_ADDR32])
214189857Sobrien    ppc_howto_init ();
214289857Sobrien
214389857Sobrien  type = ELF64_R_TYPE (dst->r_info);
2144218822Sdim  if (type >= (sizeof (ppc64_elf_howto_table)
2145218822Sdim	       / sizeof (ppc64_elf_howto_table[0])))
2146218822Sdim    {
2147218822Sdim      (*_bfd_error_handler) (_("%B: invalid relocation type %d"),
2148218822Sdim			     abfd, (int) type);
2149218822Sdim      type = R_PPC64_NONE;
2150218822Sdim    }
215189857Sobrien  cache_ptr->howto = ppc64_elf_howto_table[type];
215289857Sobrien}
215389857Sobrien
2154130561Sobrien/* Handle the R_PPC64_ADDR16_HA and similar relocs.  */
215589857Sobrien
215689857Sobrienstatic bfd_reloc_status_type
2157130561Sobrienppc64_elf_ha_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
2158130561Sobrien		    void *data, asection *input_section,
2159130561Sobrien		    bfd *output_bfd, char **error_message)
216089857Sobrien{
216199461Sobrien  /* If this is a relocatable link (output_bfd test tells us), just
216299461Sobrien     call the generic function.  Any adjustment will be done at final
216399461Sobrien     link time.  */
216499461Sobrien  if (output_bfd != NULL)
2165104834Sobrien    return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
216699461Sobrien				  input_section, output_bfd, error_message);
216789857Sobrien
216899461Sobrien  /* Adjust the addend for sign extension of the low 16 bits.
216999461Sobrien     We won't actually be using the low 16 bits, so trashing them
217099461Sobrien     doesn't matter.  */
217199461Sobrien  reloc_entry->addend += 0x8000;
217299461Sobrien  return bfd_reloc_continue;
217399461Sobrien}
217499461Sobrien
217599461Sobrienstatic bfd_reloc_status_type
2176218822Sdimppc64_elf_branch_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
2177218822Sdim			void *data, asection *input_section,
2178218822Sdim			bfd *output_bfd, char **error_message)
2179218822Sdim{
2180218822Sdim  if (output_bfd != NULL)
2181218822Sdim    return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
2182218822Sdim				  input_section, output_bfd, error_message);
2183218822Sdim
2184218822Sdim  if (strcmp (symbol->section->name, ".opd") == 0
2185218822Sdim      && (symbol->section->owner->flags & DYNAMIC) == 0)
2186218822Sdim    {
2187218822Sdim      bfd_vma dest = opd_entry_value (symbol->section,
2188218822Sdim				      symbol->value + reloc_entry->addend,
2189218822Sdim				      NULL, NULL);
2190218822Sdim      if (dest != (bfd_vma) -1)
2191218822Sdim	reloc_entry->addend = dest - (symbol->value
2192218822Sdim				      + symbol->section->output_section->vma
2193218822Sdim				      + symbol->section->output_offset);
2194218822Sdim    }
2195218822Sdim  return bfd_reloc_continue;
2196218822Sdim}
2197218822Sdim
2198218822Sdimstatic bfd_reloc_status_type
2199130561Sobrienppc64_elf_brtaken_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
2200130561Sobrien			 void *data, asection *input_section,
2201130561Sobrien			 bfd *output_bfd, char **error_message)
220299461Sobrien{
220399461Sobrien  long insn;
2204130561Sobrien  enum elf_ppc64_reloc_type r_type;
220599461Sobrien  bfd_size_type octets;
220699461Sobrien  /* Disabled until we sort out how ld should choose 'y' vs 'at'.  */
2207130561Sobrien  bfd_boolean is_power4 = FALSE;
220899461Sobrien
220999461Sobrien  /* If this is a relocatable link (output_bfd test tells us), just
221099461Sobrien     call the generic function.  Any adjustment will be done at final
221199461Sobrien     link time.  */
221289857Sobrien  if (output_bfd != NULL)
2213104834Sobrien    return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
221499461Sobrien				  input_section, output_bfd, error_message);
221599461Sobrien
221699461Sobrien  octets = reloc_entry->address * bfd_octets_per_byte (abfd);
221799461Sobrien  insn = bfd_get_32 (abfd, (bfd_byte *) data + octets);
221899461Sobrien  insn &= ~(0x01 << 21);
2219130561Sobrien  r_type = reloc_entry->howto->type;
222099461Sobrien  if (r_type == R_PPC64_ADDR14_BRTAKEN
222199461Sobrien      || r_type == R_PPC64_REL14_BRTAKEN)
2222104834Sobrien    insn |= 0x01 << 21; /* 'y' or 't' bit, lowest bit of BO field.  */
222399461Sobrien
222499461Sobrien  if (is_power4)
222589857Sobrien    {
222699461Sobrien      /* Set 'a' bit.  This is 0b00010 in BO field for branch
222799461Sobrien	 on CR(BI) insns (BO == 001at or 011at), and 0b01000
222899461Sobrien	 for branch on CTR insns (BO == 1a00t or 1a01t).  */
222999461Sobrien      if ((insn & (0x14 << 21)) == (0x04 << 21))
223099461Sobrien	insn |= 0x02 << 21;
223199461Sobrien      else if ((insn & (0x14 << 21)) == (0x10 << 21))
223299461Sobrien	insn |= 0x08 << 21;
223399461Sobrien      else
2234218822Sdim	goto out;
223589857Sobrien    }
223699461Sobrien  else
223799461Sobrien    {
223899461Sobrien      bfd_vma target = 0;
223999461Sobrien      bfd_vma from;
224089857Sobrien
224199461Sobrien      if (!bfd_is_com_section (symbol->section))
224299461Sobrien	target = symbol->value;
224399461Sobrien      target += symbol->section->output_section->vma;
224499461Sobrien      target += symbol->section->output_offset;
224599461Sobrien      target += reloc_entry->addend;
224689857Sobrien
224799461Sobrien      from = (reloc_entry->address
224899461Sobrien	      + input_section->output_offset
224999461Sobrien	      + input_section->output_section->vma);
225089857Sobrien
225199461Sobrien      /* Invert 'y' bit if not the default.  */
225299461Sobrien      if ((bfd_signed_vma) (target - from) < 0)
225399461Sobrien	insn ^= 0x01 << 21;
225499461Sobrien    }
2255130561Sobrien  bfd_put_32 (abfd, insn, (bfd_byte *) data + octets);
2256218822Sdim out:
2257218822Sdim  return ppc64_elf_branch_reloc (abfd, reloc_entry, symbol, data,
2258218822Sdim				 input_section, output_bfd, error_message);
225999461Sobrien}
226089857Sobrien
226199461Sobrienstatic bfd_reloc_status_type
2262130561Sobrienppc64_elf_sectoff_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
2263130561Sobrien			 void *data, asection *input_section,
2264130561Sobrien			 bfd *output_bfd, char **error_message)
226599461Sobrien{
226699461Sobrien  /* If this is a relocatable link (output_bfd test tells us), just
226799461Sobrien     call the generic function.  Any adjustment will be done at final
226899461Sobrien     link time.  */
226999461Sobrien  if (output_bfd != NULL)
2270104834Sobrien    return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
227199461Sobrien				  input_section, output_bfd, error_message);
227289857Sobrien
227399461Sobrien  /* Subtract the symbol section base address.  */
227499461Sobrien  reloc_entry->addend -= symbol->section->output_section->vma;
227589857Sobrien  return bfd_reloc_continue;
227689857Sobrien}
227789857Sobrien
227899461Sobrienstatic bfd_reloc_status_type
2279130561Sobrienppc64_elf_sectoff_ha_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
2280130561Sobrien			    void *data, asection *input_section,
2281130561Sobrien			    bfd *output_bfd, char **error_message)
228299461Sobrien{
228399461Sobrien  /* If this is a relocatable link (output_bfd test tells us), just
228499461Sobrien     call the generic function.  Any adjustment will be done at final
228599461Sobrien     link time.  */
228699461Sobrien  if (output_bfd != NULL)
2287104834Sobrien    return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
228899461Sobrien				  input_section, output_bfd, error_message);
228999461Sobrien
229099461Sobrien  /* Subtract the symbol section base address.  */
229199461Sobrien  reloc_entry->addend -= symbol->section->output_section->vma;
229299461Sobrien
229399461Sobrien  /* Adjust the addend for sign extension of the low 16 bits.  */
229499461Sobrien  reloc_entry->addend += 0x8000;
229599461Sobrien  return bfd_reloc_continue;
229699461Sobrien}
229799461Sobrien
229899461Sobrienstatic bfd_reloc_status_type
2299130561Sobrienppc64_elf_toc_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
2300130561Sobrien		     void *data, asection *input_section,
2301130561Sobrien		     bfd *output_bfd, char **error_message)
230299461Sobrien{
230399461Sobrien  bfd_vma TOCstart;
230499461Sobrien
230599461Sobrien  /* If this is a relocatable link (output_bfd test tells us), just
230699461Sobrien     call the generic function.  Any adjustment will be done at final
230799461Sobrien     link time.  */
230899461Sobrien  if (output_bfd != NULL)
2309104834Sobrien    return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
231099461Sobrien				  input_section, output_bfd, error_message);
231199461Sobrien
231299461Sobrien  TOCstart = _bfd_get_gp_value (input_section->output_section->owner);
231399461Sobrien  if (TOCstart == 0)
231499461Sobrien    TOCstart = ppc64_elf_toc (input_section->output_section->owner);
231599461Sobrien
231699461Sobrien  /* Subtract the TOC base address.  */
231799461Sobrien  reloc_entry->addend -= TOCstart + TOC_BASE_OFF;
231899461Sobrien  return bfd_reloc_continue;
231999461Sobrien}
232099461Sobrien
232199461Sobrienstatic bfd_reloc_status_type
2322130561Sobrienppc64_elf_toc_ha_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
2323130561Sobrien			void *data, asection *input_section,
2324130561Sobrien			bfd *output_bfd, char **error_message)
232599461Sobrien{
232699461Sobrien  bfd_vma TOCstart;
232799461Sobrien
232899461Sobrien  /* If this is a relocatable link (output_bfd test tells us), just
232999461Sobrien     call the generic function.  Any adjustment will be done at final
233099461Sobrien     link time.  */
233199461Sobrien  if (output_bfd != NULL)
2332104834Sobrien    return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
233399461Sobrien				  input_section, output_bfd, error_message);
233499461Sobrien
233599461Sobrien  TOCstart = _bfd_get_gp_value (input_section->output_section->owner);
233699461Sobrien  if (TOCstart == 0)
233799461Sobrien    TOCstart = ppc64_elf_toc (input_section->output_section->owner);
233899461Sobrien
233999461Sobrien  /* Subtract the TOC base address.  */
234099461Sobrien  reloc_entry->addend -= TOCstart + TOC_BASE_OFF;
234199461Sobrien
234299461Sobrien  /* Adjust the addend for sign extension of the low 16 bits.  */
234399461Sobrien  reloc_entry->addend += 0x8000;
234499461Sobrien  return bfd_reloc_continue;
234599461Sobrien}
234699461Sobrien
234799461Sobrienstatic bfd_reloc_status_type
2348130561Sobrienppc64_elf_toc64_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
2349130561Sobrien		       void *data, asection *input_section,
2350130561Sobrien		       bfd *output_bfd, char **error_message)
235199461Sobrien{
235299461Sobrien  bfd_vma TOCstart;
235399461Sobrien  bfd_size_type octets;
235499461Sobrien
235599461Sobrien  /* If this is a relocatable link (output_bfd test tells us), just
235699461Sobrien     call the generic function.  Any adjustment will be done at final
235799461Sobrien     link time.  */
235899461Sobrien  if (output_bfd != NULL)
2359104834Sobrien    return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
236099461Sobrien				  input_section, output_bfd, error_message);
236199461Sobrien
236299461Sobrien  TOCstart = _bfd_get_gp_value (input_section->output_section->owner);
236399461Sobrien  if (TOCstart == 0)
236499461Sobrien    TOCstart = ppc64_elf_toc (input_section->output_section->owner);
236599461Sobrien
236699461Sobrien  octets = reloc_entry->address * bfd_octets_per_byte (abfd);
236799461Sobrien  bfd_put_64 (abfd, TOCstart + TOC_BASE_OFF, (bfd_byte *) data + octets);
236899461Sobrien  return bfd_reloc_ok;
236999461Sobrien}
237099461Sobrien
237199461Sobrienstatic bfd_reloc_status_type
2372130561Sobrienppc64_elf_unhandled_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
2373130561Sobrien			   void *data, asection *input_section,
2374130561Sobrien			   bfd *output_bfd, char **error_message)
237599461Sobrien{
237699461Sobrien  /* If this is a relocatable link (output_bfd test tells us), just
237799461Sobrien     call the generic function.  Any adjustment will be done at final
237899461Sobrien     link time.  */
237999461Sobrien  if (output_bfd != NULL)
2380104834Sobrien    return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
238199461Sobrien				  input_section, output_bfd, error_message);
238299461Sobrien
238399461Sobrien  if (error_message != NULL)
238499461Sobrien    {
238599461Sobrien      static char buf[60];
238699461Sobrien      sprintf (buf, "generic linker can't handle %s",
238799461Sobrien	       reloc_entry->howto->name);
238899461Sobrien      *error_message = buf;
238999461Sobrien    }
239099461Sobrien  return bfd_reloc_dangerous;
239199461Sobrien}
239299461Sobrien
2393130561Sobrienstruct ppc64_elf_obj_tdata
2394130561Sobrien{
2395130561Sobrien  struct elf_obj_tdata elf;
2396130561Sobrien
2397130561Sobrien  /* Shortcuts to dynamic linker sections.  */
2398130561Sobrien  asection *got;
2399130561Sobrien  asection *relgot;
2400130561Sobrien
2401218822Sdim  /* Used during garbage collection.  We attach global symbols defined
2402218822Sdim     on removed .opd entries to this section so that the sym is removed.  */
2403218822Sdim  asection *deleted_section;
2404218822Sdim
2405130561Sobrien  /* TLS local dynamic got entry handling.  Suppose for multiple GOT
2406130561Sobrien     sections means we potentially need one of these for each input bfd.  */
2407130561Sobrien  union {
2408130561Sobrien    bfd_signed_vma refcount;
2409130561Sobrien    bfd_vma offset;
2410130561Sobrien  } tlsld_got;
2411218822Sdim
2412218822Sdim  /* A copy of relocs before they are modified for --emit-relocs.  */
2413218822Sdim  Elf_Internal_Rela *opd_relocs;
2414130561Sobrien};
2415130561Sobrien
2416130561Sobrien#define ppc64_elf_tdata(bfd) \
2417130561Sobrien  ((struct ppc64_elf_obj_tdata *) (bfd)->tdata.any)
2418130561Sobrien
2419130561Sobrien#define ppc64_tlsld_got(bfd) \
2420130561Sobrien  (&ppc64_elf_tdata (bfd)->tlsld_got)
2421130561Sobrien
2422130561Sobrien/* Override the generic function because we store some extras.  */
2423130561Sobrien
2424130561Sobrienstatic bfd_boolean
2425130561Sobrienppc64_elf_mkobject (bfd *abfd)
2426130561Sobrien{
2427130561Sobrien  if (abfd->tdata.any == NULL)
2428218822Sdim    {
2429218822Sdim      bfd_size_type amt = sizeof (struct ppc64_elf_obj_tdata);
2430218822Sdim      abfd->tdata.any = bfd_zalloc (abfd, amt);
2431218822Sdim      if (abfd->tdata.any == NULL)
2432218822Sdim	return FALSE;
2433218822Sdim    }
2434218822Sdim  return bfd_elf_mkobject (abfd);
2435130561Sobrien}
2436130561Sobrien
2437218822Sdim/* Return 1 if target is one of ours.  */
2438218822Sdim
2439218822Sdimstatic bfd_boolean
2440218822Sdimis_ppc64_elf_target (const struct bfd_target *targ)
2441218822Sdim{
2442218822Sdim  extern const bfd_target bfd_elf64_powerpc_vec;
2443218822Sdim  extern const bfd_target bfd_elf64_powerpcle_vec;
2444218822Sdim
2445218822Sdim  return targ == &bfd_elf64_powerpc_vec || targ == &bfd_elf64_powerpcle_vec;
2446218822Sdim}
2447218822Sdim
2448104834Sobrien/* Fix bad default arch selected for a 64 bit input bfd when the
2449104834Sobrien   default is 32 bit.  */
245089857Sobrien
2451130561Sobrienstatic bfd_boolean
2452130561Sobrienppc64_elf_object_p (bfd *abfd)
245389857Sobrien{
2454104834Sobrien  if (abfd->arch_info->the_default && abfd->arch_info->bits_per_word == 32)
2455104834Sobrien    {
2456104834Sobrien      Elf_Internal_Ehdr *i_ehdr = elf_elfheader (abfd);
245789857Sobrien
2458104834Sobrien      if (i_ehdr->e_ident[EI_CLASS] == ELFCLASS64)
2459104834Sobrien	{
2460104834Sobrien	  /* Relies on arch after 32 bit default being 64 bit default.  */
2461104834Sobrien	  abfd->arch_info = abfd->arch_info->next;
2462104834Sobrien	  BFD_ASSERT (abfd->arch_info->bits_per_word == 64);
2463104834Sobrien	}
2464104834Sobrien    }
2465130561Sobrien  return TRUE;
246689857Sobrien}
246789857Sobrien
2468130561Sobrien/* Support for core dump NOTE sections.  */
2469130561Sobrien
2470130561Sobrienstatic bfd_boolean
2471130561Sobrienppc64_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
2472130561Sobrien{
2473218822Sdim  size_t offset, size;
2474130561Sobrien
2475130561Sobrien  if (note->descsz != 504)
2476130561Sobrien    return FALSE;
2477130561Sobrien
2478130561Sobrien  /* pr_cursig */
2479130561Sobrien  elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12);
2480130561Sobrien
2481130561Sobrien  /* pr_pid */
2482130561Sobrien  elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, note->descdata + 32);
2483130561Sobrien
2484130561Sobrien  /* pr_reg */
2485130561Sobrien  offset = 112;
2486218822Sdim  size = 384;
2487130561Sobrien
2488130561Sobrien  /* Make a ".reg/999" section.  */
2489130561Sobrien  return _bfd_elfcore_make_pseudosection (abfd, ".reg",
2490218822Sdim					  size, note->descpos + offset);
2491130561Sobrien}
2492130561Sobrien
2493130561Sobrienstatic bfd_boolean
2494130561Sobrienppc64_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
2495130561Sobrien{
2496130561Sobrien  if (note->descsz != 136)
2497130561Sobrien    return FALSE;
2498130561Sobrien
2499130561Sobrien  elf_tdata (abfd)->core_program
2500130561Sobrien    = _bfd_elfcore_strndup (abfd, note->descdata + 40, 16);
2501130561Sobrien  elf_tdata (abfd)->core_command
2502130561Sobrien    = _bfd_elfcore_strndup (abfd, note->descdata + 56, 80);
2503130561Sobrien
2504130561Sobrien  return TRUE;
2505130561Sobrien}
2506130561Sobrien
2507218822Sdimstatic char *
2508218822Sdimppc64_elf_write_core_note (bfd *abfd, char *buf, int *bufsiz, int note_type,
2509218822Sdim			   ...)
2510218822Sdim{
2511218822Sdim  switch (note_type)
2512218822Sdim    {
2513218822Sdim    default:
2514218822Sdim      return NULL;
2515218822Sdim
2516218822Sdim    case NT_PRPSINFO:
2517218822Sdim      {
2518218822Sdim	char data[136];
2519218822Sdim	va_list ap;
2520218822Sdim
2521218822Sdim	va_start (ap, note_type);
2522218822Sdim	memset (data, 0, 40);
2523218822Sdim	strncpy (data + 40, va_arg (ap, const char *), 16);
2524218822Sdim	strncpy (data + 56, va_arg (ap, const char *), 80);
2525218822Sdim	va_end (ap);
2526218822Sdim	return elfcore_write_note (abfd, buf, bufsiz,
2527218822Sdim				   "CORE", note_type, data, sizeof (data));
2528218822Sdim      }
2529218822Sdim
2530218822Sdim    case NT_PRSTATUS:
2531218822Sdim      {
2532218822Sdim	char data[504];
2533218822Sdim	va_list ap;
2534218822Sdim	long pid;
2535218822Sdim	int cursig;
2536218822Sdim	const void *greg;
2537218822Sdim
2538218822Sdim	va_start (ap, note_type);
2539218822Sdim	memset (data, 0, 112);
2540218822Sdim	pid = va_arg (ap, long);
2541218822Sdim	bfd_put_32 (abfd, pid, data + 32);
2542218822Sdim	cursig = va_arg (ap, int);
2543218822Sdim	bfd_put_16 (abfd, cursig, data + 12);
2544218822Sdim	greg = va_arg (ap, const void *);
2545218822Sdim	memcpy (data + 112, greg, 384);
2546218822Sdim	memset (data + 496, 0, 8);
2547218822Sdim	va_end (ap);
2548218822Sdim	return elfcore_write_note (abfd, buf, bufsiz,
2549218822Sdim				   "CORE", note_type, data, sizeof (data));
2550218822Sdim      }
2551218822Sdim    }
2552218822Sdim}
2553218822Sdim
255489857Sobrien/* Merge backend specific data from an object file to the output
255589857Sobrien   object file when linking.  */
2556104834Sobrien
2557130561Sobrienstatic bfd_boolean
2558130561Sobrienppc64_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
255989857Sobrien{
256089857Sobrien  /* Check if we have the same endianess.  */
256189857Sobrien  if (ibfd->xvec->byteorder != obfd->xvec->byteorder
2562107492Sobrien      && ibfd->xvec->byteorder != BFD_ENDIAN_UNKNOWN
256389857Sobrien      && obfd->xvec->byteorder != BFD_ENDIAN_UNKNOWN)
256489857Sobrien    {
256589857Sobrien      const char *msg;
256689857Sobrien
256789857Sobrien      if (bfd_big_endian (ibfd))
2568218822Sdim	msg = _("%B: compiled for a big endian system "
2569130561Sobrien		"and target is little endian");
257089857Sobrien      else
2571218822Sdim	msg = _("%B: compiled for a little endian system "
2572130561Sobrien		"and target is big endian");
257389857Sobrien
2574218822Sdim      (*_bfd_error_handler) (msg, ibfd);
257589857Sobrien
257689857Sobrien      bfd_set_error (bfd_error_wrong_format);
2577130561Sobrien      return FALSE;
257889857Sobrien    }
257989857Sobrien
2580130561Sobrien  return TRUE;
258189857Sobrien}
2582130561Sobrien
2583130561Sobrien/* Add extra PPC sections.  */
2584130561Sobrien
2585218822Sdimstatic const struct bfd_elf_special_section ppc64_elf_special_sections[]=
2586130561Sobrien{
2587218822Sdim  { STRING_COMMA_LEN (".plt"),    0, SHT_NOBITS,   0 },
2588218822Sdim  { STRING_COMMA_LEN (".sbss"),  -2, SHT_NOBITS,   SHF_ALLOC + SHF_WRITE },
2589218822Sdim  { STRING_COMMA_LEN (".sdata"), -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
2590218822Sdim  { STRING_COMMA_LEN (".toc"),    0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
2591218822Sdim  { STRING_COMMA_LEN (".toc1"),   0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
2592218822Sdim  { STRING_COMMA_LEN (".tocbss"), 0, SHT_NOBITS,   SHF_ALLOC + SHF_WRITE },
2593218822Sdim  { NULL,                     0,  0, 0,            0 }
2594130561Sobrien};
2595130561Sobrien
2596218822Sdimenum _ppc64_sec_type {
2597218822Sdim  sec_normal = 0,
2598218822Sdim  sec_opd = 1,
2599218822Sdim  sec_toc = 2
2600218822Sdim};
2601218822Sdim
2602130561Sobrienstruct _ppc64_elf_section_data
2603130561Sobrien{
2604130561Sobrien  struct bfd_elf_section_data elf;
2605130561Sobrien
2606130561Sobrien  /* An array with one entry for each opd function descriptor.  */
2607130561Sobrien  union
2608130561Sobrien  {
2609130561Sobrien    /* Points to the function code section for local opd entries.  */
2610218822Sdim    asection **opd_func_sec;
2611130561Sobrien    /* After editing .opd, adjust references to opd local syms.  */
2612218822Sdim    long *opd_adjust;
2613130561Sobrien
2614218822Sdim    /* An array for toc sections, indexed by offset/8.
2615218822Sdim       Specifies the relocation symbol index used at a given toc offset.  */
2616218822Sdim    unsigned *t_symndx;
2617218822Sdim  } u;
2618218822Sdim
2619218822Sdim  enum _ppc64_sec_type sec_type:2;
2620218822Sdim
2621218822Sdim  /* Flag set when small branches are detected.  Used to
2622218822Sdim     select suitable defaults for the stub group size.  */
2623218822Sdim  unsigned int has_14bit_branch:1;
2624130561Sobrien};
2625130561Sobrien
2626130561Sobrien#define ppc64_elf_section_data(sec) \
2627130561Sobrien  ((struct _ppc64_elf_section_data *) elf_section_data (sec))
2628130561Sobrien
2629130561Sobrienstatic bfd_boolean
2630130561Sobrienppc64_elf_new_section_hook (bfd *abfd, asection *sec)
2631130561Sobrien{
2632218822Sdim  if (!sec->used_by_bfd)
2633218822Sdim    {
2634218822Sdim      struct _ppc64_elf_section_data *sdata;
2635218822Sdim      bfd_size_type amt = sizeof (*sdata);
2636130561Sobrien
2637218822Sdim      sdata = bfd_zalloc (abfd, amt);
2638218822Sdim      if (sdata == NULL)
2639218822Sdim	return FALSE;
2640218822Sdim      sec->used_by_bfd = sdata;
2641218822Sdim    }
2642130561Sobrien
2643130561Sobrien  return _bfd_elf_new_section_hook (abfd, sec);
2644130561Sobrien}
2645218822Sdim
2646218822Sdimstatic void *
2647218822Sdimget_opd_info (asection * sec)
2648218822Sdim{
2649218822Sdim  if (sec != NULL
2650218822Sdim      && ppc64_elf_section_data (sec) != NULL
2651218822Sdim      && ppc64_elf_section_data (sec)->sec_type == sec_opd)
2652218822Sdim    return ppc64_elf_section_data (sec)->u.opd_adjust;
2653218822Sdim  return NULL;
2654218822Sdim}
265589857Sobrien
2656218822Sdim/* Parameters for the qsort hook.  */
2657218822Sdimstatic asection *synthetic_opd;
2658218822Sdimstatic bfd_boolean synthetic_relocatable;
2659218822Sdim
2660218822Sdim/* qsort comparison function for ppc64_elf_get_synthetic_symtab.  */
2661218822Sdim
2662218822Sdimstatic int
2663218822Sdimcompare_symbols (const void *ap, const void *bp)
2664218822Sdim{
2665218822Sdim  const asymbol *a = * (const asymbol **) ap;
2666218822Sdim  const asymbol *b = * (const asymbol **) bp;
2667218822Sdim
2668218822Sdim  /* Section symbols first.  */
2669218822Sdim  if ((a->flags & BSF_SECTION_SYM) && !(b->flags & BSF_SECTION_SYM))
2670218822Sdim    return -1;
2671218822Sdim  if (!(a->flags & BSF_SECTION_SYM) && (b->flags & BSF_SECTION_SYM))
2672218822Sdim    return 1;
2673218822Sdim
2674218822Sdim  /* then .opd symbols.  */
2675218822Sdim  if (a->section == synthetic_opd && b->section != synthetic_opd)
2676218822Sdim    return -1;
2677218822Sdim  if (a->section != synthetic_opd && b->section == synthetic_opd)
2678218822Sdim    return 1;
2679218822Sdim
2680218822Sdim  /* then other code symbols.  */
2681218822Sdim  if ((a->section->flags & (SEC_CODE | SEC_ALLOC | SEC_THREAD_LOCAL))
2682218822Sdim      == (SEC_CODE | SEC_ALLOC)
2683218822Sdim      && (b->section->flags & (SEC_CODE | SEC_ALLOC | SEC_THREAD_LOCAL))
2684218822Sdim	 != (SEC_CODE | SEC_ALLOC))
2685218822Sdim    return -1;
2686218822Sdim
2687218822Sdim  if ((a->section->flags & (SEC_CODE | SEC_ALLOC | SEC_THREAD_LOCAL))
2688218822Sdim      != (SEC_CODE | SEC_ALLOC)
2689218822Sdim      && (b->section->flags & (SEC_CODE | SEC_ALLOC | SEC_THREAD_LOCAL))
2690218822Sdim	 == (SEC_CODE | SEC_ALLOC))
2691218822Sdim    return 1;
2692218822Sdim
2693218822Sdim  if (synthetic_relocatable)
2694218822Sdim    {
2695218822Sdim      if (a->section->id < b->section->id)
2696218822Sdim	return -1;
2697218822Sdim
2698218822Sdim      if (a->section->id > b->section->id)
2699218822Sdim	return 1;
2700218822Sdim    }
2701218822Sdim
2702218822Sdim  if (a->value + a->section->vma < b->value + b->section->vma)
2703218822Sdim    return -1;
2704218822Sdim
2705218822Sdim  if (a->value + a->section->vma > b->value + b->section->vma)
2706218822Sdim    return 1;
2707218822Sdim
2708218822Sdim  /* For syms with the same value, prefer strong dynamic global function
2709218822Sdim     syms over other syms.  */
2710218822Sdim  if ((a->flags & BSF_GLOBAL) != 0 && (b->flags & BSF_GLOBAL) == 0)
2711218822Sdim    return -1;
2712218822Sdim
2713218822Sdim  if ((a->flags & BSF_GLOBAL) == 0 && (b->flags & BSF_GLOBAL) != 0)
2714218822Sdim    return 1;
2715218822Sdim
2716218822Sdim  if ((a->flags & BSF_FUNCTION) != 0 && (b->flags & BSF_FUNCTION) == 0)
2717218822Sdim    return -1;
2718218822Sdim
2719218822Sdim  if ((a->flags & BSF_FUNCTION) == 0 && (b->flags & BSF_FUNCTION) != 0)
2720218822Sdim    return 1;
2721218822Sdim
2722218822Sdim  if ((a->flags & BSF_WEAK) == 0 && (b->flags & BSF_WEAK) != 0)
2723218822Sdim    return -1;
2724218822Sdim
2725218822Sdim  if ((a->flags & BSF_WEAK) != 0 && (b->flags & BSF_WEAK) == 0)
2726218822Sdim    return 1;
2727218822Sdim
2728218822Sdim  if ((a->flags & BSF_DYNAMIC) != 0 && (b->flags & BSF_DYNAMIC) == 0)
2729218822Sdim    return -1;
2730218822Sdim
2731218822Sdim  if ((a->flags & BSF_DYNAMIC) == 0 && (b->flags & BSF_DYNAMIC) != 0)
2732218822Sdim    return 1;
2733218822Sdim
2734218822Sdim  return 0;
2735218822Sdim}
2736218822Sdim
2737218822Sdim/* Search SYMS for a symbol of the given VALUE.  */
2738218822Sdim
2739218822Sdimstatic asymbol *
2740218822Sdimsym_exists_at (asymbol **syms, long lo, long hi, int id, bfd_vma value)
2741218822Sdim{
2742218822Sdim  long mid;
2743218822Sdim
2744218822Sdim  if (id == -1)
2745218822Sdim    {
2746218822Sdim      while (lo < hi)
2747218822Sdim	{
2748218822Sdim	  mid = (lo + hi) >> 1;
2749218822Sdim	  if (syms[mid]->value + syms[mid]->section->vma < value)
2750218822Sdim	    lo = mid + 1;
2751218822Sdim	  else if (syms[mid]->value + syms[mid]->section->vma > value)
2752218822Sdim	    hi = mid;
2753218822Sdim	  else
2754218822Sdim	    return syms[mid];
2755218822Sdim	}
2756218822Sdim    }
2757218822Sdim  else
2758218822Sdim    {
2759218822Sdim      while (lo < hi)
2760218822Sdim	{
2761218822Sdim	  mid = (lo + hi) >> 1;
2762218822Sdim	  if (syms[mid]->section->id < id)
2763218822Sdim	    lo = mid + 1;
2764218822Sdim	  else if (syms[mid]->section->id > id)
2765218822Sdim	    hi = mid;
2766218822Sdim	  else if (syms[mid]->value < value)
2767218822Sdim	    lo = mid + 1;
2768218822Sdim	  else if (syms[mid]->value > value)
2769218822Sdim	    hi = mid;
2770218822Sdim	  else
2771218822Sdim	    return syms[mid];
2772218822Sdim	}
2773218822Sdim    }
2774218822Sdim  return NULL;
2775218822Sdim}
2776218822Sdim
2777218822Sdim/* Create synthetic symbols, effectively restoring "dot-symbol" function
2778218822Sdim   entry syms.  */
2779218822Sdim
2780218822Sdimstatic long
2781218822Sdimppc64_elf_get_synthetic_symtab (bfd *abfd,
2782218822Sdim				long static_count, asymbol **static_syms,
2783218822Sdim				long dyn_count, asymbol **dyn_syms,
2784218822Sdim				asymbol **ret)
2785218822Sdim{
2786218822Sdim  asymbol *s;
2787218822Sdim  long i;
2788218822Sdim  long count;
2789218822Sdim  char *names;
2790218822Sdim  long symcount, codesecsym, codesecsymend, secsymend, opdsymend;
2791218822Sdim  asection *opd;
2792218822Sdim  bfd_boolean relocatable = (abfd->flags & (EXEC_P | DYNAMIC)) == 0;
2793218822Sdim  asymbol **syms;
2794218822Sdim
2795218822Sdim  *ret = NULL;
2796218822Sdim
2797218822Sdim  opd = bfd_get_section_by_name (abfd, ".opd");
2798218822Sdim  if (opd == NULL)
2799218822Sdim    return 0;
2800218822Sdim
2801218822Sdim  symcount = static_count;
2802218822Sdim  if (!relocatable)
2803218822Sdim    symcount += dyn_count;
2804218822Sdim  if (symcount == 0)
2805218822Sdim    return 0;
2806218822Sdim
2807218822Sdim  syms = bfd_malloc ((symcount + 1) * sizeof (*syms));
2808218822Sdim  if (syms == NULL)
2809218822Sdim    return -1;
2810218822Sdim
2811218822Sdim  if (!relocatable && static_count != 0 && dyn_count != 0)
2812218822Sdim    {
2813218822Sdim      /* Use both symbol tables.  */
2814218822Sdim      memcpy (syms, static_syms, static_count * sizeof (*syms));
2815218822Sdim      memcpy (syms + static_count, dyn_syms, (dyn_count + 1) * sizeof (*syms));
2816218822Sdim    }
2817218822Sdim  else if (!relocatable && static_count == 0)
2818218822Sdim    memcpy (syms, dyn_syms, (symcount + 1) * sizeof (*syms));
2819218822Sdim  else
2820218822Sdim    memcpy (syms, static_syms, (symcount + 1) * sizeof (*syms));
2821218822Sdim
2822218822Sdim  synthetic_opd = opd;
2823218822Sdim  synthetic_relocatable = relocatable;
2824218822Sdim  qsort (syms, symcount, sizeof (*syms), compare_symbols);
2825218822Sdim
2826218822Sdim  if (!relocatable && symcount > 1)
2827218822Sdim    {
2828218822Sdim      long j;
2829218822Sdim      /* Trim duplicate syms, since we may have merged the normal and
2830218822Sdim	 dynamic symbols.  Actually, we only care about syms that have
2831218822Sdim	 different values, so trim any with the same value.  */
2832218822Sdim      for (i = 1, j = 1; i < symcount; ++i)
2833218822Sdim	if (syms[i - 1]->value + syms[i - 1]->section->vma
2834218822Sdim	    != syms[i]->value + syms[i]->section->vma)
2835218822Sdim	  syms[j++] = syms[i];
2836218822Sdim      symcount = j;
2837218822Sdim    }
2838218822Sdim
2839218822Sdim  i = 0;
2840218822Sdim  if (syms[i]->section == opd)
2841218822Sdim    ++i;
2842218822Sdim  codesecsym = i;
2843218822Sdim
2844218822Sdim  for (; i < symcount; ++i)
2845218822Sdim    if (((syms[i]->section->flags & (SEC_CODE | SEC_ALLOC | SEC_THREAD_LOCAL))
2846218822Sdim	 != (SEC_CODE | SEC_ALLOC))
2847218822Sdim	|| (syms[i]->flags & BSF_SECTION_SYM) == 0)
2848218822Sdim      break;
2849218822Sdim  codesecsymend = i;
2850218822Sdim
2851218822Sdim  for (; i < symcount; ++i)
2852218822Sdim    if ((syms[i]->flags & BSF_SECTION_SYM) == 0)
2853218822Sdim      break;
2854218822Sdim  secsymend = i;
2855218822Sdim
2856218822Sdim  for (; i < symcount; ++i)
2857218822Sdim    if (syms[i]->section != opd)
2858218822Sdim      break;
2859218822Sdim  opdsymend = i;
2860218822Sdim
2861218822Sdim  for (; i < symcount; ++i)
2862218822Sdim    if ((syms[i]->section->flags & (SEC_CODE | SEC_ALLOC | SEC_THREAD_LOCAL))
2863218822Sdim	!= (SEC_CODE | SEC_ALLOC))
2864218822Sdim      break;
2865218822Sdim  symcount = i;
2866218822Sdim
2867218822Sdim  count = 0;
2868218822Sdim  if (opdsymend == secsymend)
2869218822Sdim    goto done;
2870218822Sdim
2871218822Sdim  if (relocatable)
2872218822Sdim    {
2873218822Sdim      bfd_boolean (*slurp_relocs) (bfd *, asection *, asymbol **, bfd_boolean);
2874218822Sdim      arelent *r;
2875218822Sdim      size_t size;
2876218822Sdim      long relcount;
2877218822Sdim
2878218822Sdim      slurp_relocs = get_elf_backend_data (abfd)->s->slurp_reloc_table;
2879218822Sdim      relcount = (opd->flags & SEC_RELOC) ? opd->reloc_count : 0;
2880218822Sdim      if (relcount == 0)
2881218822Sdim	goto done;
2882218822Sdim
2883218822Sdim      if (!(*slurp_relocs) (abfd, opd, static_syms, FALSE))
2884218822Sdim	{
2885218822Sdim	  count = -1;
2886218822Sdim	  goto done;
2887218822Sdim	}
2888218822Sdim
2889218822Sdim      size = 0;
2890218822Sdim      for (i = secsymend, r = opd->relocation; i < opdsymend; ++i)
2891218822Sdim	{
2892218822Sdim	  asymbol *sym;
2893218822Sdim
2894218822Sdim	  while (r < opd->relocation + relcount
2895218822Sdim		 && r->address < syms[i]->value + opd->vma)
2896218822Sdim	    ++r;
2897218822Sdim
2898218822Sdim	  if (r == opd->relocation + relcount)
2899218822Sdim	    break;
2900218822Sdim
2901218822Sdim	  if (r->address != syms[i]->value + opd->vma)
2902218822Sdim	    continue;
2903218822Sdim
2904218822Sdim	  if (r->howto->type != R_PPC64_ADDR64)
2905218822Sdim	    continue;
2906218822Sdim
2907218822Sdim	  sym = *r->sym_ptr_ptr;
2908218822Sdim	  if (!sym_exists_at (syms, opdsymend, symcount,
2909218822Sdim			      sym->section->id, sym->value + r->addend))
2910218822Sdim	    {
2911218822Sdim	      ++count;
2912218822Sdim	      size += sizeof (asymbol);
2913218822Sdim	      size += strlen (syms[i]->name) + 2;
2914218822Sdim	    }
2915218822Sdim	}
2916218822Sdim
2917218822Sdim      s = *ret = bfd_malloc (size);
2918218822Sdim      if (s == NULL)
2919218822Sdim	{
2920218822Sdim	  count = -1;
2921218822Sdim	  goto done;
2922218822Sdim	}
2923218822Sdim
2924218822Sdim      names = (char *) (s + count);
2925218822Sdim
2926218822Sdim      for (i = secsymend, r = opd->relocation; i < opdsymend; ++i)
2927218822Sdim	{
2928218822Sdim	  asymbol *sym;
2929218822Sdim
2930218822Sdim	  while (r < opd->relocation + relcount
2931218822Sdim		 && r->address < syms[i]->value + opd->vma)
2932218822Sdim	    ++r;
2933218822Sdim
2934218822Sdim	  if (r == opd->relocation + relcount)
2935218822Sdim	    break;
2936218822Sdim
2937218822Sdim	  if (r->address != syms[i]->value + opd->vma)
2938218822Sdim	    continue;
2939218822Sdim
2940218822Sdim	  if (r->howto->type != R_PPC64_ADDR64)
2941218822Sdim	    continue;
2942218822Sdim
2943218822Sdim	  sym = *r->sym_ptr_ptr;
2944218822Sdim	  if (!sym_exists_at (syms, opdsymend, symcount,
2945218822Sdim			      sym->section->id, sym->value + r->addend))
2946218822Sdim	    {
2947218822Sdim	      size_t len;
2948218822Sdim
2949218822Sdim	      *s = *syms[i];
2950218822Sdim	      s->section = sym->section;
2951218822Sdim	      s->value = sym->value + r->addend;
2952218822Sdim	      s->name = names;
2953218822Sdim	      *names++ = '.';
2954218822Sdim	      len = strlen (syms[i]->name);
2955218822Sdim	      memcpy (names, syms[i]->name, len + 1);
2956218822Sdim	      names += len + 1;
2957218822Sdim	      s++;
2958218822Sdim	    }
2959218822Sdim	}
2960218822Sdim    }
2961218822Sdim  else
2962218822Sdim    {
2963218822Sdim      bfd_byte *contents;
2964218822Sdim      size_t size;
2965218822Sdim
2966218822Sdim      if (!bfd_malloc_and_get_section (abfd, opd, &contents))
2967218822Sdim	{
2968218822Sdim	  if (contents)
2969218822Sdim	    {
2970218822Sdim	    free_contents_and_exit:
2971218822Sdim	      free (contents);
2972218822Sdim	    }
2973218822Sdim	  count = -1;
2974218822Sdim	  goto done;
2975218822Sdim	}
2976218822Sdim
2977218822Sdim      size = 0;
2978218822Sdim      for (i = secsymend; i < opdsymend; ++i)
2979218822Sdim	{
2980218822Sdim	  bfd_vma ent;
2981218822Sdim
2982218822Sdim	  ent = bfd_get_64 (abfd, contents + syms[i]->value);
2983218822Sdim	  if (!sym_exists_at (syms, opdsymend, symcount, -1, ent))
2984218822Sdim	    {
2985218822Sdim	      ++count;
2986218822Sdim	      size += sizeof (asymbol);
2987218822Sdim	      size += strlen (syms[i]->name) + 2;
2988218822Sdim	    }
2989218822Sdim	}
2990218822Sdim
2991218822Sdim      s = *ret = bfd_malloc (size);
2992218822Sdim      if (s == NULL)
2993218822Sdim	goto free_contents_and_exit;
2994218822Sdim
2995218822Sdim      names = (char *) (s + count);
2996218822Sdim
2997218822Sdim      for (i = secsymend; i < opdsymend; ++i)
2998218822Sdim	{
2999218822Sdim	  bfd_vma ent;
3000218822Sdim
3001218822Sdim	  ent = bfd_get_64 (abfd, contents + syms[i]->value);
3002218822Sdim	  if (!sym_exists_at (syms, opdsymend, symcount, -1, ent))
3003218822Sdim	    {
3004218822Sdim	      long lo, hi;
3005218822Sdim	      size_t len;
3006218822Sdim	      asection *sec = abfd->sections;
3007218822Sdim
3008218822Sdim	      *s = *syms[i];
3009218822Sdim	      lo = codesecsym;
3010218822Sdim	      hi = codesecsymend;
3011218822Sdim	      while (lo < hi)
3012218822Sdim		{
3013218822Sdim		  long mid = (lo + hi) >> 1;
3014218822Sdim		  if (syms[mid]->section->vma < ent)
3015218822Sdim		    lo = mid + 1;
3016218822Sdim		  else if (syms[mid]->section->vma > ent)
3017218822Sdim		    hi = mid;
3018218822Sdim		  else
3019218822Sdim		    {
3020218822Sdim		      sec = syms[mid]->section;
3021218822Sdim		      break;
3022218822Sdim		    }
3023218822Sdim		}
3024218822Sdim
3025218822Sdim	      if (lo >= hi && lo > codesecsym)
3026218822Sdim		sec = syms[lo - 1]->section;
3027218822Sdim
3028218822Sdim	      for (; sec != NULL; sec = sec->next)
3029218822Sdim		{
3030218822Sdim		  if (sec->vma > ent)
3031218822Sdim		    break;
3032218822Sdim		  if ((sec->flags & SEC_ALLOC) == 0
3033218822Sdim		      || (sec->flags & SEC_LOAD) == 0)
3034218822Sdim		    break;
3035218822Sdim		  if ((sec->flags & SEC_CODE) != 0)
3036218822Sdim		    s->section = sec;
3037218822Sdim		}
3038218822Sdim	      s->value = ent - s->section->vma;
3039218822Sdim	      s->name = names;
3040218822Sdim	      *names++ = '.';
3041218822Sdim	      len = strlen (syms[i]->name);
3042218822Sdim	      memcpy (names, syms[i]->name, len + 1);
3043218822Sdim	      names += len + 1;
3044218822Sdim	      s++;
3045218822Sdim	    }
3046218822Sdim	}
3047218822Sdim      free (contents);
3048218822Sdim    }
3049218822Sdim
3050218822Sdim done:
3051218822Sdim  free (syms);
3052218822Sdim  return count;
3053218822Sdim}
3054218822Sdim
305589857Sobrien/* The following functions are specific to the ELF linker, while
305689857Sobrien   functions above are used generally.  Those named ppc64_elf_* are
305789857Sobrien   called by the main ELF linker code.  They appear in this file more
305889857Sobrien   or less in the order in which they are called.  eg.
305989857Sobrien   ppc64_elf_check_relocs is called early in the link process,
306089857Sobrien   ppc64_elf_finish_dynamic_sections is one of the last functions
306189857Sobrien   called.
306289857Sobrien
306389857Sobrien   PowerPC64-ELF uses a similar scheme to PowerPC64-XCOFF in that
306489857Sobrien   functions have both a function code symbol and a function descriptor
306589857Sobrien   symbol.  A call to foo in a relocatable object file looks like:
306689857Sobrien
306789857Sobrien   .		.text
306889857Sobrien   .	x:
306989857Sobrien   .		bl	.foo
307089857Sobrien   .		nop
307189857Sobrien
307289857Sobrien   The function definition in another object file might be:
307389857Sobrien
307489857Sobrien   .		.section .opd
307589857Sobrien   .	foo:	.quad	.foo
307689857Sobrien   .		.quad	.TOC.@tocbase
307789857Sobrien   .		.quad	0
307889857Sobrien   .
307989857Sobrien   .		.text
308089857Sobrien   .	.foo:	blr
308189857Sobrien
308289857Sobrien   When the linker resolves the call during a static link, the branch
308389857Sobrien   unsurprisingly just goes to .foo and the .opd information is unused.
308489857Sobrien   If the function definition is in a shared library, things are a little
308589857Sobrien   different:  The call goes via a plt call stub, the opd information gets
308689857Sobrien   copied to the plt, and the linker patches the nop.
308789857Sobrien
308889857Sobrien   .	x:
308989857Sobrien   .		bl	.foo_stub
309089857Sobrien   .		ld	2,40(1)
309189857Sobrien   .
309289857Sobrien   .
309389857Sobrien   .	.foo_stub:
309489857Sobrien   .		addis	12,2,Lfoo@toc@ha	# in practice, the call stub
3095130561Sobrien   .		addi	12,12,Lfoo@toc@l	# is slightly optimized, but
309689857Sobrien   .		std	2,40(1)			# this is the general idea
309789857Sobrien   .		ld	11,0(12)
309889857Sobrien   .		ld	2,8(12)
309989857Sobrien   .		mtctr	11
310089857Sobrien   .		ld	11,16(12)
310189857Sobrien   .		bctr
310289857Sobrien   .
310389857Sobrien   .		.section .plt
310489857Sobrien   .	Lfoo:	reloc (R_PPC64_JMP_SLOT, foo)
310589857Sobrien
310689857Sobrien   The "reloc ()" notation is supposed to indicate that the linker emits
310789857Sobrien   an R_PPC64_JMP_SLOT reloc against foo.  The dynamic linker does the opd
310889857Sobrien   copying.
310989857Sobrien
311089857Sobrien   What are the difficulties here?  Well, firstly, the relocations
311189857Sobrien   examined by the linker in check_relocs are against the function code
311289857Sobrien   sym .foo, while the dynamic relocation in the plt is emitted against
311389857Sobrien   the function descriptor symbol, foo.  Somewhere along the line, we need
311489857Sobrien   to carefully copy dynamic link information from one symbol to the other.
311589857Sobrien   Secondly, the generic part of the elf linker will make .foo a dynamic
311689857Sobrien   symbol as is normal for most other backends.  We need foo dynamic
311789857Sobrien   instead, at least for an application final link.  However, when
311889857Sobrien   creating a shared library containing foo, we need to have both symbols
311989857Sobrien   dynamic so that references to .foo are satisfied during the early
312089857Sobrien   stages of linking.  Otherwise the linker might decide to pull in a
3121218822Sdim   definition from some other object, eg. a static library.
312289857Sobrien
3123218822Sdim   Update: As of August 2004, we support a new convention.  Function
3124218822Sdim   calls may use the function descriptor symbol, ie. "bl foo".  This
3125218822Sdim   behaves exactly as "bl .foo".  */
3126218822Sdim
312789857Sobrien/* The linker needs to keep track of the number of relocs that it
312889857Sobrien   decides to copy as dynamic relocs in check_relocs for each symbol.
312989857Sobrien   This is so that it can later discard them if they are found to be
313089857Sobrien   unnecessary.  We store the information in a field extending the
313189857Sobrien   regular ELF linker hash table.  */
313289857Sobrien
313389857Sobrienstruct ppc_dyn_relocs
313489857Sobrien{
313589857Sobrien  struct ppc_dyn_relocs *next;
313689857Sobrien
313789857Sobrien  /* The input section of the reloc.  */
313889857Sobrien  asection *sec;
313989857Sobrien
314089857Sobrien  /* Total number of relocs copied for the input section.  */
314189857Sobrien  bfd_size_type count;
314289857Sobrien
314389857Sobrien  /* Number of pc-relative relocs copied for the input section.  */
314489857Sobrien  bfd_size_type pc_count;
314589857Sobrien};
314689857Sobrien
3147130561Sobrien/* Track GOT entries needed for a given symbol.  We might need more
3148130561Sobrien   than one got entry per symbol.  */
3149130561Sobrienstruct got_entry
3150130561Sobrien{
3151130561Sobrien  struct got_entry *next;
3152130561Sobrien
3153130561Sobrien  /* The symbol addend that we'll be placing in the GOT.  */
3154130561Sobrien  bfd_vma addend;
3155130561Sobrien
3156130561Sobrien  /* Unlike other ELF targets, we use separate GOT entries for the same
3157130561Sobrien     symbol referenced from different input files.  This is to support
3158130561Sobrien     automatic multiple TOC/GOT sections, where the TOC base can vary
3159130561Sobrien     from one input file to another.
3160130561Sobrien
3161130561Sobrien     Point to the BFD owning this GOT entry.  */
3162130561Sobrien  bfd *owner;
3163130561Sobrien
3164130561Sobrien  /* Zero for non-tls entries, or TLS_TLS and one of TLS_GD, TLS_LD,
3165130561Sobrien     TLS_TPREL or TLS_DTPREL for tls entries.  */
3166130561Sobrien  char tls_type;
3167130561Sobrien
3168130561Sobrien  /* Reference count until size_dynamic_sections, GOT offset thereafter.  */
3169130561Sobrien  union
3170130561Sobrien    {
3171130561Sobrien      bfd_signed_vma refcount;
3172130561Sobrien      bfd_vma offset;
3173130561Sobrien    } got;
3174130561Sobrien};
3175130561Sobrien
3176130561Sobrien/* The same for PLT.  */
3177130561Sobrienstruct plt_entry
3178130561Sobrien{
3179130561Sobrien  struct plt_entry *next;
3180130561Sobrien
3181130561Sobrien  bfd_vma addend;
3182130561Sobrien
3183130561Sobrien  union
3184130561Sobrien    {
3185130561Sobrien      bfd_signed_vma refcount;
3186130561Sobrien      bfd_vma offset;
3187130561Sobrien    } plt;
3188130561Sobrien};
3189130561Sobrien
319089857Sobrien/* Of those relocs that might be copied as dynamic relocs, this macro
3191130561Sobrien   selects those that must be copied when linking a shared library,
3192130561Sobrien   even when the symbol is local.  */
319389857Sobrien
3194130561Sobrien#define MUST_BE_DYN_RELOC(RTYPE)		\
3195104834Sobrien  ((RTYPE) != R_PPC64_REL32			\
3196104834Sobrien   && (RTYPE) != R_PPC64_REL64			\
3197130561Sobrien   && (RTYPE) != R_PPC64_REL30)
319889857Sobrien
3199130561Sobrien/* If ELIMINATE_COPY_RELOCS is non-zero, the linker will try to avoid
3200130561Sobrien   copying dynamic variables from a shared lib into an app's dynbss
3201130561Sobrien   section, and instead use a dynamic relocation to point into the
3202130561Sobrien   shared lib.  With code that gcc generates, it's vital that this be
3203130561Sobrien   enabled;  In the PowerPC64 ABI, the address of a function is actually
3204130561Sobrien   the address of a function descriptor, which resides in the .opd
3205130561Sobrien   section.  gcc uses the descriptor directly rather than going via the
3206130561Sobrien   GOT as some other ABI's do, which means that initialized function
3207130561Sobrien   pointers must reference the descriptor.  Thus, a function pointer
3208130561Sobrien   initialized to the address of a function in a shared library will
3209130561Sobrien   either require a copy reloc, or a dynamic reloc.  Using a copy reloc
3210130561Sobrien   redefines the function descriptor symbol to point to the copy.  This
3211130561Sobrien   presents a problem as a plt entry for that function is also
3212130561Sobrien   initialized from the function descriptor symbol and the copy reloc
3213130561Sobrien   may not be initialized first.  */
3214130561Sobrien#define ELIMINATE_COPY_RELOCS 1
3215130561Sobrien
3216104834Sobrien/* Section name for stubs is the associated section name plus this
3217104834Sobrien   string.  */
3218104834Sobrien#define STUB_SUFFIX ".stub"
321989857Sobrien
3220104834Sobrien/* Linker stubs.
3221104834Sobrien   ppc_stub_long_branch:
3222104834Sobrien   Used when a 14 bit branch (or even a 24 bit branch) can't reach its
3223104834Sobrien   destination, but a 24 bit branch in a stub section will reach.
3224104834Sobrien   .	b	dest
3225104834Sobrien
3226104834Sobrien   ppc_stub_plt_branch:
3227104834Sobrien   Similar to the above, but a 24 bit branch in the stub section won't
3228104834Sobrien   reach its destination.
3229107492Sobrien   .	addis	%r12,%r2,xxx@toc@ha
3230107492Sobrien   .	ld	%r11,xxx@toc@l(%r12)
3231104834Sobrien   .	mtctr	%r11
3232104834Sobrien   .	bctr
3233104834Sobrien
3234104834Sobrien   ppc_stub_plt_call:
3235218822Sdim   Used to call a function in a shared library.  If it so happens that
3236218822Sdim   the plt entry referenced crosses a 64k boundary, then an extra
3237218822Sdim   "addis %r12,%r12,1" will be inserted before the load at xxx+8 or
3238218822Sdim   xxx+16 as appropriate.
3239107492Sobrien   .	addis	%r12,%r2,xxx@toc@ha
3240104834Sobrien   .	std	%r2,40(%r1)
3241107492Sobrien   .	ld	%r11,xxx+0@toc@l(%r12)
3242107492Sobrien   .	ld	%r2,xxx+8@toc@l(%r12)
3243104834Sobrien   .	mtctr	%r11
3244107492Sobrien   .	ld	%r11,xxx+16@toc@l(%r12)
3245104834Sobrien   .	bctr
3246130561Sobrien
3247130561Sobrien   ppc_stub_long_branch and ppc_stub_plt_branch may also have additional
3248130561Sobrien   code to adjust the value and save r2 to support multiple toc sections.
3249130561Sobrien   A ppc_stub_long_branch with an r2 offset looks like:
3250130561Sobrien   .	std	%r2,40(%r1)
3251130561Sobrien   .	addis	%r2,%r2,off@ha
3252130561Sobrien   .	addi	%r2,%r2,off@l
3253130561Sobrien   .	b	dest
3254130561Sobrien
3255130561Sobrien   A ppc_stub_plt_branch with an r2 offset looks like:
3256130561Sobrien   .	std	%r2,40(%r1)
3257130561Sobrien   .	addis	%r12,%r2,xxx@toc@ha
3258130561Sobrien   .	ld	%r11,xxx@toc@l(%r12)
3259130561Sobrien   .	addis	%r2,%r2,off@ha
3260130561Sobrien   .	addi	%r2,%r2,off@l
3261130561Sobrien   .	mtctr	%r11
3262130561Sobrien   .	bctr
3263104834Sobrien*/
3264104834Sobrien
3265104834Sobrienenum ppc_stub_type {
3266104834Sobrien  ppc_stub_none,
3267104834Sobrien  ppc_stub_long_branch,
3268130561Sobrien  ppc_stub_long_branch_r2off,
3269104834Sobrien  ppc_stub_plt_branch,
3270130561Sobrien  ppc_stub_plt_branch_r2off,
3271104834Sobrien  ppc_stub_plt_call
3272104834Sobrien};
3273104834Sobrien
3274104834Sobrienstruct ppc_stub_hash_entry {
3275104834Sobrien
3276104834Sobrien  /* Base hash table entry structure.  */
3277104834Sobrien  struct bfd_hash_entry root;
3278104834Sobrien
3279130561Sobrien  enum ppc_stub_type stub_type;
3280130561Sobrien
3281104834Sobrien  /* The stub section.  */
3282104834Sobrien  asection *stub_sec;
3283104834Sobrien
3284104834Sobrien  /* Offset within stub_sec of the beginning of this stub.  */
3285104834Sobrien  bfd_vma stub_offset;
3286104834Sobrien
3287104834Sobrien  /* Given the symbol's value and its section we can determine its final
3288104834Sobrien     value when building the stubs (so the stub knows where to jump.  */
3289104834Sobrien  bfd_vma target_value;
3290104834Sobrien  asection *target_section;
3291104834Sobrien
3292104834Sobrien  /* The symbol table entry, if any, that this was derived from.  */
3293104834Sobrien  struct ppc_link_hash_entry *h;
3294104834Sobrien
3295130561Sobrien  /* And the reloc addend that this was derived from.  */
3296130561Sobrien  bfd_vma addend;
3297130561Sobrien
3298104834Sobrien  /* Where this stub is being called from, or, in the case of combined
3299104834Sobrien     stub sections, the first input section in the group.  */
3300104834Sobrien  asection *id_sec;
3301104834Sobrien};
3302104834Sobrien
3303104834Sobrienstruct ppc_branch_hash_entry {
3304104834Sobrien
3305104834Sobrien  /* Base hash table entry structure.  */
3306104834Sobrien  struct bfd_hash_entry root;
3307104834Sobrien
3308218822Sdim  /* Offset within branch lookup table.  */
3309104834Sobrien  unsigned int offset;
3310104834Sobrien
3311104834Sobrien  /* Generation marker.  */
3312104834Sobrien  unsigned int iter;
3313104834Sobrien};
3314104834Sobrien
331589857Sobrienstruct ppc_link_hash_entry
331689857Sobrien{
331789857Sobrien  struct elf_link_hash_entry elf;
331889857Sobrien
3319218822Sdim  union {
3320218822Sdim    /* A pointer to the most recently used stub hash entry against this
3321218822Sdim       symbol.  */
3322218822Sdim    struct ppc_stub_hash_entry *stub_cache;
3323104834Sobrien
3324218822Sdim    /* A pointer to the next symbol starting with a '.'  */
3325218822Sdim    struct ppc_link_hash_entry *next_dot_sym;
3326218822Sdim  } u;
3327218822Sdim
332889857Sobrien  /* Track dynamic relocs copied for this symbol.  */
332989857Sobrien  struct ppc_dyn_relocs *dyn_relocs;
333089857Sobrien
3331104834Sobrien  /* Link between function code and descriptor symbols.  */
3332218822Sdim  struct ppc_link_hash_entry *oh;
3333104834Sobrien
333489857Sobrien  /* Flag function code and descriptor symbols.  */
333589857Sobrien  unsigned int is_func:1;
333689857Sobrien  unsigned int is_func_descriptor:1;
3337218822Sdim  unsigned int fake:1;
3338130561Sobrien
3339218822Sdim  /* Whether global opd/toc sym has been adjusted or not.
3340218822Sdim     After ppc64_elf_edit_opd/ppc64_elf_edit_toc has run, this flag
3341218822Sdim     should be set for all globals defined in any opd/toc section.  */
3342130561Sobrien  unsigned int adjust_done:1;
3343130561Sobrien
3344218822Sdim  /* Set if we twiddled this symbol to weak at some stage.  */
3345218822Sdim  unsigned int was_undefined:1;
3346218822Sdim
3347130561Sobrien  /* Contexts in which symbol is used in the GOT (or TOC).
3348130561Sobrien     TLS_GD .. TLS_EXPLICIT bits are or'd into the mask as the
3349130561Sobrien     corresponding relocs are encountered during check_relocs.
3350130561Sobrien     tls_optimize clears TLS_GD .. TLS_TPREL when optimizing to
3351130561Sobrien     indicate the corresponding GOT entry type is not needed.
3352130561Sobrien     tls_optimize may also set TLS_TPRELGD when a GD reloc turns into
3353130561Sobrien     a TPREL one.  We use a separate flag rather than setting TPREL
3354130561Sobrien     just for convenience in distinguishing the two cases.  */
3355130561Sobrien#define TLS_GD		 1	/* GD reloc. */
3356130561Sobrien#define TLS_LD		 2	/* LD reloc. */
3357130561Sobrien#define TLS_TPREL	 4	/* TPREL reloc, => IE. */
3358130561Sobrien#define TLS_DTPREL	 8	/* DTPREL reloc, => LD. */
3359130561Sobrien#define TLS_TLS		16	/* Any TLS reloc.  */
3360130561Sobrien#define TLS_EXPLICIT	32	/* Marks TOC section TLS relocs. */
3361130561Sobrien#define TLS_TPRELGD	64	/* TPREL reloc resulting from GD->IE. */
3362130561Sobrien  char tls_mask;
336389857Sobrien};
336489857Sobrien
336589857Sobrien/* ppc64 ELF linker hash table.  */
336689857Sobrien
336789857Sobrienstruct ppc_link_hash_table
336889857Sobrien{
336989857Sobrien  struct elf_link_hash_table elf;
337089857Sobrien
3371104834Sobrien  /* The stub hash table.  */
3372104834Sobrien  struct bfd_hash_table stub_hash_table;
3373104834Sobrien
3374104834Sobrien  /* Another hash table for plt_branch stubs.  */
3375104834Sobrien  struct bfd_hash_table branch_hash_table;
3376104834Sobrien
3377104834Sobrien  /* Linker stub bfd.  */
3378104834Sobrien  bfd *stub_bfd;
3379104834Sobrien
3380104834Sobrien  /* Linker call-backs.  */
3381130561Sobrien  asection * (*add_stub_section) (const char *, asection *);
3382130561Sobrien  void (*layout_sections_again) (void);
3383104834Sobrien
3384104834Sobrien  /* Array to keep track of which stub sections have been created, and
3385104834Sobrien     information on stub grouping.  */
3386104834Sobrien  struct map_stub {
3387104834Sobrien    /* This is the section to which stubs in the group will be attached.  */
3388104834Sobrien    asection *link_sec;
3389104834Sobrien    /* The stub section.  */
3390104834Sobrien    asection *stub_sec;
3391130561Sobrien    /* Along with elf_gp, specifies the TOC pointer used in this group.  */
3392130561Sobrien    bfd_vma toc_off;
3393104834Sobrien  } *stub_group;
3394104834Sobrien
3395130561Sobrien  /* Temp used when calculating TOC pointers.  */
3396130561Sobrien  bfd_vma toc_curr;
3397130561Sobrien
3398130561Sobrien  /* Highest input section id.  */
3399130561Sobrien  int top_id;
3400130561Sobrien
3401130561Sobrien  /* Highest output section index.  */
3402104834Sobrien  int top_index;
3403130561Sobrien
3404218822Sdim  /* Used when adding symbols.  */
3405218822Sdim  struct ppc_link_hash_entry *dot_syms;
3406218822Sdim
3407130561Sobrien  /* List of input sections for each output section.  */
3408104834Sobrien  asection **input_list;
3409104834Sobrien
341089857Sobrien  /* Short-cuts to get to dynamic linker sections.  */
3411130561Sobrien  asection *got;
3412130561Sobrien  asection *plt;
3413130561Sobrien  asection *relplt;
3414130561Sobrien  asection *dynbss;
3415130561Sobrien  asection *relbss;
3416130561Sobrien  asection *glink;
341792828Sobrien  asection *sfpr;
3418130561Sobrien  asection *brlt;
3419130561Sobrien  asection *relbrlt;
342089857Sobrien
3421218822Sdim  /* Shortcut to .__tls_get_addr and __tls_get_addr.  */
3422218822Sdim  struct ppc_link_hash_entry *tls_get_addr;
3423218822Sdim  struct ppc_link_hash_entry *tls_get_addr_fd;
3424130561Sobrien
3425130561Sobrien  /* Statistics.  */
3426130561Sobrien  unsigned long stub_count[ppc_stub_plt_call];
3427130561Sobrien
3428218822Sdim  /* Number of stubs against global syms.  */
3429218822Sdim  unsigned long stub_globals;
3430218822Sdim
3431130561Sobrien  /* Set if we should emit symbols for stubs.  */
3432218822Sdim  unsigned int emit_stub_syms:1;
3433130561Sobrien
3434218822Sdim  /* Support for multiple toc sections.  */
3435218822Sdim  unsigned int no_multi_toc:1;
3436218822Sdim  unsigned int multi_toc_needed:1;
3437218822Sdim
343889857Sobrien  /* Set on error.  */
3439218822Sdim  unsigned int stub_error:1;
344089857Sobrien
3441218822Sdim  /* Temp used by ppc64_elf_check_directives.  */
3442218822Sdim  unsigned int twiddled_syms:1;
3443104834Sobrien
3444104834Sobrien  /* Incremented every time we size stubs.  */
3445104834Sobrien  unsigned int stub_iteration;
3446104834Sobrien
344789857Sobrien  /* Small local sym to section mapping cache.  */
344889857Sobrien  struct sym_sec_cache sym_sec;
344989857Sobrien};
345089857Sobrien
3451218822Sdim/* Rename some of the generic section flags to better document how they
3452218822Sdim   are used here.  */
3453218822Sdim#define has_toc_reloc has_gp_reloc
3454218822Sdim#define makes_toc_func_call need_finalize_relax
3455218822Sdim#define call_check_in_progress reloc_done
3456218822Sdim
345789857Sobrien/* Get the ppc64 ELF linker hash table from a link_info structure.  */
345889857Sobrien
345989857Sobrien#define ppc_hash_table(p) \
346089857Sobrien  ((struct ppc_link_hash_table *) ((p)->hash))
346189857Sobrien
3462104834Sobrien#define ppc_stub_hash_lookup(table, string, create, copy) \
3463104834Sobrien  ((struct ppc_stub_hash_entry *) \
3464104834Sobrien   bfd_hash_lookup ((table), (string), (create), (copy)))
3465104834Sobrien
3466104834Sobrien#define ppc_branch_hash_lookup(table, string, create, copy) \
3467104834Sobrien  ((struct ppc_branch_hash_entry *) \
3468104834Sobrien   bfd_hash_lookup ((table), (string), (create), (copy)))
3469104834Sobrien
3470104834Sobrien/* Create an entry in the stub hash table.  */
3471104834Sobrien
3472104834Sobrienstatic struct bfd_hash_entry *
3473130561Sobrienstub_hash_newfunc (struct bfd_hash_entry *entry,
3474130561Sobrien		   struct bfd_hash_table *table,
3475130561Sobrien		   const char *string)
3476104834Sobrien{
3477104834Sobrien  /* Allocate the structure if it has not already been allocated by a
3478104834Sobrien     subclass.  */
3479104834Sobrien  if (entry == NULL)
3480104834Sobrien    {
3481104834Sobrien      entry = bfd_hash_allocate (table, sizeof (struct ppc_stub_hash_entry));
3482104834Sobrien      if (entry == NULL)
3483104834Sobrien	return entry;
3484104834Sobrien    }
3485104834Sobrien
3486104834Sobrien  /* Call the allocation method of the superclass.  */
3487104834Sobrien  entry = bfd_hash_newfunc (entry, table, string);
3488104834Sobrien  if (entry != NULL)
3489104834Sobrien    {
3490104834Sobrien      struct ppc_stub_hash_entry *eh;
3491104834Sobrien
3492104834Sobrien      /* Initialize the local fields.  */
3493104834Sobrien      eh = (struct ppc_stub_hash_entry *) entry;
3494130561Sobrien      eh->stub_type = ppc_stub_none;
3495104834Sobrien      eh->stub_sec = NULL;
3496104834Sobrien      eh->stub_offset = 0;
3497104834Sobrien      eh->target_value = 0;
3498104834Sobrien      eh->target_section = NULL;
3499104834Sobrien      eh->h = NULL;
3500104834Sobrien      eh->id_sec = NULL;
3501104834Sobrien    }
3502104834Sobrien
3503104834Sobrien  return entry;
3504104834Sobrien}
3505104834Sobrien
3506104834Sobrien/* Create an entry in the branch hash table.  */
3507104834Sobrien
3508104834Sobrienstatic struct bfd_hash_entry *
3509130561Sobrienbranch_hash_newfunc (struct bfd_hash_entry *entry,
3510130561Sobrien		     struct bfd_hash_table *table,
3511130561Sobrien		     const char *string)
3512104834Sobrien{
3513104834Sobrien  /* Allocate the structure if it has not already been allocated by a
3514104834Sobrien     subclass.  */
3515104834Sobrien  if (entry == NULL)
3516104834Sobrien    {
3517104834Sobrien      entry = bfd_hash_allocate (table, sizeof (struct ppc_branch_hash_entry));
3518104834Sobrien      if (entry == NULL)
3519104834Sobrien	return entry;
3520104834Sobrien    }
3521104834Sobrien
3522104834Sobrien  /* Call the allocation method of the superclass.  */
3523104834Sobrien  entry = bfd_hash_newfunc (entry, table, string);
3524104834Sobrien  if (entry != NULL)
3525104834Sobrien    {
3526104834Sobrien      struct ppc_branch_hash_entry *eh;
3527104834Sobrien
3528104834Sobrien      /* Initialize the local fields.  */
3529104834Sobrien      eh = (struct ppc_branch_hash_entry *) entry;
3530104834Sobrien      eh->offset = 0;
3531104834Sobrien      eh->iter = 0;
3532104834Sobrien    }
3533104834Sobrien
3534104834Sobrien  return entry;
3535104834Sobrien}
3536104834Sobrien
353789857Sobrien/* Create an entry in a ppc64 ELF linker hash table.  */
353889857Sobrien
353989857Sobrienstatic struct bfd_hash_entry *
3540130561Sobrienlink_hash_newfunc (struct bfd_hash_entry *entry,
3541130561Sobrien		   struct bfd_hash_table *table,
3542130561Sobrien		   const char *string)
354389857Sobrien{
354489857Sobrien  /* Allocate the structure if it has not already been allocated by a
354589857Sobrien     subclass.  */
354689857Sobrien  if (entry == NULL)
354789857Sobrien    {
354889857Sobrien      entry = bfd_hash_allocate (table, sizeof (struct ppc_link_hash_entry));
354989857Sobrien      if (entry == NULL)
355089857Sobrien	return entry;
355189857Sobrien    }
355289857Sobrien
355389857Sobrien  /* Call the allocation method of the superclass.  */
355489857Sobrien  entry = _bfd_elf_link_hash_newfunc (entry, table, string);
355589857Sobrien  if (entry != NULL)
355689857Sobrien    {
355789857Sobrien      struct ppc_link_hash_entry *eh = (struct ppc_link_hash_entry *) entry;
355889857Sobrien
3559218822Sdim      memset (&eh->u.stub_cache, 0,
3560218822Sdim	      (sizeof (struct ppc_link_hash_entry)
3561218822Sdim	       - offsetof (struct ppc_link_hash_entry, u.stub_cache)));
3562218822Sdim
3563218822Sdim      /* When making function calls, old ABI code references function entry
3564218822Sdim	 points (dot symbols), while new ABI code references the function
3565218822Sdim	 descriptor symbol.  We need to make any combination of reference and
3566218822Sdim	 definition work together, without breaking archive linking.
3567218822Sdim
3568218822Sdim	 For a defined function "foo" and an undefined call to "bar":
3569218822Sdim	 An old object defines "foo" and ".foo", references ".bar" (possibly
3570218822Sdim	 "bar" too).
3571218822Sdim	 A new object defines "foo" and references "bar".
3572218822Sdim
3573218822Sdim	 A new object thus has no problem with its undefined symbols being
3574218822Sdim	 satisfied by definitions in an old object.  On the other hand, the
3575218822Sdim	 old object won't have ".bar" satisfied by a new object.
3576218822Sdim
3577218822Sdim	 Keep a list of newly added dot-symbols.  */
3578218822Sdim
3579218822Sdim      if (string[0] == '.')
3580218822Sdim	{
3581218822Sdim	  struct ppc_link_hash_table *htab;
3582218822Sdim
3583218822Sdim	  htab = (struct ppc_link_hash_table *) table;
3584218822Sdim	  eh->u.next_dot_sym = htab->dot_syms;
3585218822Sdim	  htab->dot_syms = eh;
3586218822Sdim	}
358789857Sobrien    }
358889857Sobrien
358989857Sobrien  return entry;
359089857Sobrien}
359189857Sobrien
359289857Sobrien/* Create a ppc64 ELF linker hash table.  */
359389857Sobrien
359489857Sobrienstatic struct bfd_link_hash_table *
3595130561Sobrienppc64_elf_link_hash_table_create (bfd *abfd)
359689857Sobrien{
359789857Sobrien  struct ppc_link_hash_table *htab;
359889857Sobrien  bfd_size_type amt = sizeof (struct ppc_link_hash_table);
359989857Sobrien
3600130561Sobrien  htab = bfd_zmalloc (amt);
360189857Sobrien  if (htab == NULL)
360289857Sobrien    return NULL;
360389857Sobrien
3604218822Sdim  if (!_bfd_elf_link_hash_table_init (&htab->elf, abfd, link_hash_newfunc,
3605218822Sdim				      sizeof (struct ppc_link_hash_entry)))
360689857Sobrien    {
3607104834Sobrien      free (htab);
360889857Sobrien      return NULL;
360989857Sobrien    }
361089857Sobrien
3611104834Sobrien  /* Init the stub hash table too.  */
3612218822Sdim  if (!bfd_hash_table_init (&htab->stub_hash_table, stub_hash_newfunc,
3613218822Sdim			    sizeof (struct ppc_stub_hash_entry)))
3614104834Sobrien    return NULL;
3615104834Sobrien
3616104834Sobrien  /* And the branch hash table.  */
3617218822Sdim  if (!bfd_hash_table_init (&htab->branch_hash_table, branch_hash_newfunc,
3618218822Sdim			    sizeof (struct ppc_branch_hash_entry)))
3619104834Sobrien    return NULL;
3620104834Sobrien
3621130561Sobrien  /* Initializing two fields of the union is just cosmetic.  We really
3622130561Sobrien     only care about glist, but when compiled on a 32-bit host the
3623130561Sobrien     bfd_vma fields are larger.  Setting the bfd_vma to zero makes
3624130561Sobrien     debugger inspection of these fields look nicer.  */
3625218822Sdim  htab->elf.init_got_refcount.refcount = 0;
3626218822Sdim  htab->elf.init_got_refcount.glist = NULL;
3627218822Sdim  htab->elf.init_plt_refcount.refcount = 0;
3628218822Sdim  htab->elf.init_plt_refcount.glist = NULL;
3629218822Sdim  htab->elf.init_got_offset.offset = 0;
3630218822Sdim  htab->elf.init_got_offset.glist = NULL;
3631218822Sdim  htab->elf.init_plt_offset.offset = 0;
3632218822Sdim  htab->elf.init_plt_offset.glist = NULL;
363389857Sobrien
363489857Sobrien  return &htab->elf.root;
363589857Sobrien}
363689857Sobrien
3637104834Sobrien/* Free the derived linker hash table.  */
3638104834Sobrien
3639104834Sobrienstatic void
3640130561Sobrienppc64_elf_link_hash_table_free (struct bfd_link_hash_table *hash)
3641104834Sobrien{
3642104834Sobrien  struct ppc_link_hash_table *ret = (struct ppc_link_hash_table *) hash;
3643104834Sobrien
3644104834Sobrien  bfd_hash_table_free (&ret->stub_hash_table);
3645104834Sobrien  bfd_hash_table_free (&ret->branch_hash_table);
3646104834Sobrien  _bfd_generic_link_hash_table_free (hash);
3647104834Sobrien}
3648104834Sobrien
3649130561Sobrien/* Satisfy the ELF linker by filling in some fields in our fake bfd.  */
3650130561Sobrien
3651130561Sobrienvoid
3652130561Sobrienppc64_elf_init_stub_bfd (bfd *abfd, struct bfd_link_info *info)
3653130561Sobrien{
3654130561Sobrien  struct ppc_link_hash_table *htab;
3655130561Sobrien
3656130561Sobrien  elf_elfheader (abfd)->e_ident[EI_CLASS] = ELFCLASS64;
3657130561Sobrien
3658130561Sobrien/* Always hook our dynamic sections into the first bfd, which is the
3659130561Sobrien   linker created stub bfd.  This ensures that the GOT header is at
3660130561Sobrien   the start of the output TOC section.  */
3661130561Sobrien  htab = ppc_hash_table (info);
3662130561Sobrien  htab->stub_bfd = abfd;
3663130561Sobrien  htab->elf.dynobj = abfd;
3664130561Sobrien}
3665130561Sobrien
3666104834Sobrien/* Build a name for an entry in the stub hash table.  */
3667104834Sobrien
3668104834Sobrienstatic char *
3669130561Sobrienppc_stub_name (const asection *input_section,
3670130561Sobrien	       const asection *sym_sec,
3671130561Sobrien	       const struct ppc_link_hash_entry *h,
3672130561Sobrien	       const Elf_Internal_Rela *rel)
3673104834Sobrien{
3674104834Sobrien  char *stub_name;
3675104834Sobrien  bfd_size_type len;
3676104834Sobrien
3677104834Sobrien  /* rel->r_addend is actually 64 bit, but who uses more than +/- 2^31
3678104834Sobrien     offsets from a sym as a branch target?  In fact, we could
3679104834Sobrien     probably assume the addend is always zero.  */
3680104834Sobrien  BFD_ASSERT (((int) rel->r_addend & 0xffffffff) == rel->r_addend);
3681104834Sobrien
3682104834Sobrien  if (h)
3683104834Sobrien    {
3684104834Sobrien      len = 8 + 1 + strlen (h->elf.root.root.string) + 1 + 8 + 1;
3685104834Sobrien      stub_name = bfd_malloc (len);
3686218822Sdim      if (stub_name == NULL)
3687218822Sdim	return stub_name;
3688218822Sdim
3689218822Sdim      sprintf (stub_name, "%08x.%s+%x",
3690218822Sdim	       input_section->id & 0xffffffff,
3691218822Sdim	       h->elf.root.root.string,
3692218822Sdim	       (int) rel->r_addend & 0xffffffff);
3693104834Sobrien    }
3694104834Sobrien  else
3695104834Sobrien    {
3696130561Sobrien      len = 8 + 1 + 8 + 1 + 8 + 1 + 8 + 1;
3697104834Sobrien      stub_name = bfd_malloc (len);
3698218822Sdim      if (stub_name == NULL)
3699218822Sdim	return stub_name;
3700218822Sdim
3701218822Sdim      sprintf (stub_name, "%08x.%x:%x+%x",
3702218822Sdim	       input_section->id & 0xffffffff,
3703218822Sdim	       sym_sec->id & 0xffffffff,
3704218822Sdim	       (int) ELF64_R_SYM (rel->r_info) & 0xffffffff,
3705218822Sdim	       (int) rel->r_addend & 0xffffffff);
3706104834Sobrien    }
3707218822Sdim  if (stub_name[len - 2] == '+' && stub_name[len - 1] == '0')
3708218822Sdim    stub_name[len - 2] = 0;
3709104834Sobrien  return stub_name;
3710104834Sobrien}
3711104834Sobrien
3712104834Sobrien/* Look up an entry in the stub hash.  Stub entries are cached because
3713104834Sobrien   creating the stub name takes a bit of time.  */
3714104834Sobrien
3715104834Sobrienstatic struct ppc_stub_hash_entry *
3716130561Sobrienppc_get_stub_entry (const asection *input_section,
3717130561Sobrien		    const asection *sym_sec,
3718218822Sdim		    struct ppc_link_hash_entry *h,
3719130561Sobrien		    const Elf_Internal_Rela *rel,
3720130561Sobrien		    struct ppc_link_hash_table *htab)
3721104834Sobrien{
3722104834Sobrien  struct ppc_stub_hash_entry *stub_entry;
3723104834Sobrien  const asection *id_sec;
3724104834Sobrien
3725104834Sobrien  /* If this input section is part of a group of sections sharing one
3726104834Sobrien     stub section, then use the id of the first section in the group.
3727104834Sobrien     Stub names need to include a section id, as there may well be
3728104834Sobrien     more than one stub used to reach say, printf, and we need to
3729104834Sobrien     distinguish between them.  */
3730104834Sobrien  id_sec = htab->stub_group[input_section->id].link_sec;
3731104834Sobrien
3732218822Sdim  if (h != NULL && h->u.stub_cache != NULL
3733218822Sdim      && h->u.stub_cache->h == h
3734218822Sdim      && h->u.stub_cache->id_sec == id_sec)
3735104834Sobrien    {
3736218822Sdim      stub_entry = h->u.stub_cache;
3737104834Sobrien    }
3738104834Sobrien  else
3739104834Sobrien    {
3740104834Sobrien      char *stub_name;
3741104834Sobrien
3742104834Sobrien      stub_name = ppc_stub_name (id_sec, sym_sec, h, rel);
3743104834Sobrien      if (stub_name == NULL)
3744104834Sobrien	return NULL;
3745104834Sobrien
3746104834Sobrien      stub_entry = ppc_stub_hash_lookup (&htab->stub_hash_table,
3747130561Sobrien					 stub_name, FALSE, FALSE);
3748104834Sobrien      if (h != NULL)
3749218822Sdim	h->u.stub_cache = stub_entry;
3750104834Sobrien
3751104834Sobrien      free (stub_name);
3752104834Sobrien    }
3753104834Sobrien
3754104834Sobrien  return stub_entry;
3755104834Sobrien}
3756104834Sobrien
3757104834Sobrien/* Add a new stub entry to the stub hash.  Not all fields of the new
3758104834Sobrien   stub entry are initialised.  */
3759104834Sobrien
3760104834Sobrienstatic struct ppc_stub_hash_entry *
3761130561Sobrienppc_add_stub (const char *stub_name,
3762130561Sobrien	      asection *section,
3763130561Sobrien	      struct ppc_link_hash_table *htab)
3764104834Sobrien{
3765104834Sobrien  asection *link_sec;
3766104834Sobrien  asection *stub_sec;
3767104834Sobrien  struct ppc_stub_hash_entry *stub_entry;
3768104834Sobrien
3769104834Sobrien  link_sec = htab->stub_group[section->id].link_sec;
3770104834Sobrien  stub_sec = htab->stub_group[section->id].stub_sec;
3771104834Sobrien  if (stub_sec == NULL)
3772104834Sobrien    {
3773104834Sobrien      stub_sec = htab->stub_group[link_sec->id].stub_sec;
3774104834Sobrien      if (stub_sec == NULL)
3775104834Sobrien	{
3776104834Sobrien	  size_t namelen;
3777104834Sobrien	  bfd_size_type len;
3778104834Sobrien	  char *s_name;
3779104834Sobrien
3780104834Sobrien	  namelen = strlen (link_sec->name);
3781104834Sobrien	  len = namelen + sizeof (STUB_SUFFIX);
3782104834Sobrien	  s_name = bfd_alloc (htab->stub_bfd, len);
3783104834Sobrien	  if (s_name == NULL)
3784104834Sobrien	    return NULL;
3785104834Sobrien
3786104834Sobrien	  memcpy (s_name, link_sec->name, namelen);
3787104834Sobrien	  memcpy (s_name + namelen, STUB_SUFFIX, sizeof (STUB_SUFFIX));
3788104834Sobrien	  stub_sec = (*htab->add_stub_section) (s_name, link_sec);
3789104834Sobrien	  if (stub_sec == NULL)
3790104834Sobrien	    return NULL;
3791104834Sobrien	  htab->stub_group[link_sec->id].stub_sec = stub_sec;
3792104834Sobrien	}
3793104834Sobrien      htab->stub_group[section->id].stub_sec = stub_sec;
3794104834Sobrien    }
3795104834Sobrien
3796104834Sobrien  /* Enter this entry into the linker stub hash table.  */
3797104834Sobrien  stub_entry = ppc_stub_hash_lookup (&htab->stub_hash_table, stub_name,
3798130561Sobrien				     TRUE, FALSE);
3799104834Sobrien  if (stub_entry == NULL)
3800104834Sobrien    {
3801218822Sdim      (*_bfd_error_handler) (_("%B: cannot create stub entry %s"),
3802218822Sdim			     section->owner, stub_name);
3803104834Sobrien      return NULL;
3804104834Sobrien    }
3805104834Sobrien
3806104834Sobrien  stub_entry->stub_sec = stub_sec;
3807104834Sobrien  stub_entry->stub_offset = 0;
3808104834Sobrien  stub_entry->id_sec = link_sec;
3809104834Sobrien  return stub_entry;
3810104834Sobrien}
3811104834Sobrien
381292828Sobrien/* Create sections for linker generated code.  */
381392828Sobrien
3814130561Sobrienstatic bfd_boolean
3815130561Sobriencreate_linkage_sections (bfd *dynobj, struct bfd_link_info *info)
381692828Sobrien{
381792828Sobrien  struct ppc_link_hash_table *htab;
381892828Sobrien  flagword flags;
381992828Sobrien
382092828Sobrien  htab = ppc_hash_table (info);
382192828Sobrien
382292828Sobrien  /* Create .sfpr for code to save and restore fp regs.  */
382392828Sobrien  flags = (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_READONLY
382492828Sobrien	   | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED);
3825218822Sdim  htab->sfpr = bfd_make_section_anyway_with_flags (dynobj, ".sfpr",
3826218822Sdim						   flags);
382792828Sobrien  if (htab->sfpr == NULL
382892828Sobrien      || ! bfd_set_section_alignment (dynobj, htab->sfpr, 2))
3829130561Sobrien    return FALSE;
383092828Sobrien
3831104834Sobrien  /* Create .glink for lazy dynamic linking support.  */
3832218822Sdim  htab->glink = bfd_make_section_anyway_with_flags (dynobj, ".glink",
3833218822Sdim						    flags);
3834130561Sobrien  if (htab->glink == NULL
3835218822Sdim      || ! bfd_set_section_alignment (dynobj, htab->glink, 3))
3836130561Sobrien    return FALSE;
383792828Sobrien
3838218822Sdim  /* Create branch lookup table for plt_branch stubs.  */
3839104834Sobrien  flags = (SEC_ALLOC | SEC_LOAD
3840104834Sobrien	   | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED);
3841218822Sdim  htab->brlt = bfd_make_section_anyway_with_flags (dynobj, ".branch_lt",
3842218822Sdim						   flags);
3843130561Sobrien  if (htab->brlt == NULL
3844130561Sobrien      || ! bfd_set_section_alignment (dynobj, htab->brlt, 3))
3845130561Sobrien    return FALSE;
3846104834Sobrien
3847218822Sdim  if (!info->shared)
3848218822Sdim    return TRUE;
3849218822Sdim
3850218822Sdim  flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY
3851218822Sdim	   | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED);
3852218822Sdim  htab->relbrlt = bfd_make_section_anyway_with_flags (dynobj,
3853218822Sdim						      ".rela.branch_lt",
3854218822Sdim						      flags);
3855218822Sdim  if (!htab->relbrlt
3856218822Sdim      || ! bfd_set_section_alignment (dynobj, htab->relbrlt, 3))
3857218822Sdim    return FALSE;
3858218822Sdim
3859130561Sobrien  return TRUE;
386092828Sobrien}
386192828Sobrien
3862130561Sobrien/* Create .got and .rela.got sections in ABFD, and .got in dynobj if
3863130561Sobrien   not already done.  */
386489857Sobrien
3865130561Sobrienstatic bfd_boolean
3866130561Sobriencreate_got_section (bfd *abfd, struct bfd_link_info *info)
386789857Sobrien{
3868130561Sobrien  asection *got, *relgot;
3869130561Sobrien  flagword flags;
3870130561Sobrien  struct ppc_link_hash_table *htab = ppc_hash_table (info);
387189857Sobrien
3872130561Sobrien  if (!htab->got)
3873130561Sobrien    {
3874130561Sobrien      if (! _bfd_elf_create_got_section (htab->elf.dynobj, info))
3875130561Sobrien	return FALSE;
387689857Sobrien
3877130561Sobrien      htab->got = bfd_get_section_by_name (htab->elf.dynobj, ".got");
3878130561Sobrien      if (!htab->got)
3879130561Sobrien	abort ();
3880130561Sobrien    }
388189857Sobrien
3882130561Sobrien  flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
3883130561Sobrien	   | SEC_LINKER_CREATED);
3884130561Sobrien
3885218822Sdim  got = bfd_make_section_anyway_with_flags (abfd, ".got", flags);
3886130561Sobrien  if (!got
3887130561Sobrien      || !bfd_set_section_alignment (abfd, got, 3))
3888130561Sobrien    return FALSE;
3889130561Sobrien
3890218822Sdim  relgot = bfd_make_section_anyway_with_flags (abfd, ".rela.got",
3891218822Sdim					       flags | SEC_READONLY);
3892130561Sobrien  if (!relgot
3893130561Sobrien      || ! bfd_set_section_alignment (abfd, relgot, 3))
3894130561Sobrien    return FALSE;
3895130561Sobrien
3896130561Sobrien  ppc64_elf_tdata (abfd)->got = got;
3897130561Sobrien  ppc64_elf_tdata (abfd)->relgot = relgot;
3898130561Sobrien  return TRUE;
389989857Sobrien}
390089857Sobrien
390192828Sobrien/* Create the dynamic sections, and set up shortcuts.  */
390289857Sobrien
3903130561Sobrienstatic bfd_boolean
3904130561Sobrienppc64_elf_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info)
390589857Sobrien{
390689857Sobrien  struct ppc_link_hash_table *htab;
390789857Sobrien
390889857Sobrien  if (!_bfd_elf_create_dynamic_sections (dynobj, info))
3909130561Sobrien    return FALSE;
391089857Sobrien
3911130561Sobrien  htab = ppc_hash_table (info);
3912130561Sobrien  if (!htab->got)
3913130561Sobrien    htab->got = bfd_get_section_by_name (dynobj, ".got");
3914130561Sobrien  htab->plt = bfd_get_section_by_name (dynobj, ".plt");
3915130561Sobrien  htab->relplt = bfd_get_section_by_name (dynobj, ".rela.plt");
3916130561Sobrien  htab->dynbss = bfd_get_section_by_name (dynobj, ".dynbss");
391789857Sobrien  if (!info->shared)
3918130561Sobrien    htab->relbss = bfd_get_section_by_name (dynobj, ".rela.bss");
391989857Sobrien
3920130561Sobrien  if (!htab->got || !htab->plt || !htab->relplt || !htab->dynbss
3921130561Sobrien      || (!info->shared && !htab->relbss))
392289857Sobrien    abort ();
392389857Sobrien
3924130561Sobrien  return TRUE;
392589857Sobrien}
392689857Sobrien
3927218822Sdim/* Merge PLT info on FROM with that on TO.  */
3928218822Sdim
3929218822Sdimstatic void
3930218822Sdimmove_plt_plist (struct ppc_link_hash_entry *from,
3931218822Sdim		struct ppc_link_hash_entry *to)
3932218822Sdim{
3933218822Sdim  if (from->elf.plt.plist != NULL)
3934218822Sdim    {
3935218822Sdim      if (to->elf.plt.plist != NULL)
3936218822Sdim	{
3937218822Sdim	  struct plt_entry **entp;
3938218822Sdim	  struct plt_entry *ent;
3939218822Sdim
3940218822Sdim	  for (entp = &from->elf.plt.plist; (ent = *entp) != NULL; )
3941218822Sdim	    {
3942218822Sdim	      struct plt_entry *dent;
3943218822Sdim
3944218822Sdim	      for (dent = to->elf.plt.plist; dent != NULL; dent = dent->next)
3945218822Sdim		if (dent->addend == ent->addend)
3946218822Sdim		  {
3947218822Sdim		    dent->plt.refcount += ent->plt.refcount;
3948218822Sdim		    *entp = ent->next;
3949218822Sdim		    break;
3950218822Sdim		  }
3951218822Sdim	      if (dent == NULL)
3952218822Sdim		entp = &ent->next;
3953218822Sdim	    }
3954218822Sdim	  *entp = to->elf.plt.plist;
3955218822Sdim	}
3956218822Sdim
3957218822Sdim      to->elf.plt.plist = from->elf.plt.plist;
3958218822Sdim      from->elf.plt.plist = NULL;
3959218822Sdim    }
3960218822Sdim}
3961218822Sdim
396289857Sobrien/* Copy the extra info we tack onto an elf_link_hash_entry.  */
396389857Sobrien
396489857Sobrienstatic void
3965218822Sdimppc64_elf_copy_indirect_symbol (struct bfd_link_info *info,
3966218822Sdim				struct elf_link_hash_entry *dir,
3967218822Sdim				struct elf_link_hash_entry *ind)
396889857Sobrien{
396989857Sobrien  struct ppc_link_hash_entry *edir, *eind;
397089857Sobrien
397189857Sobrien  edir = (struct ppc_link_hash_entry *) dir;
397289857Sobrien  eind = (struct ppc_link_hash_entry *) ind;
397389857Sobrien
3974130561Sobrien  /* Copy over any dynamic relocs we may have on the indirect sym.  */
397589857Sobrien  if (eind->dyn_relocs != NULL)
397689857Sobrien    {
397789857Sobrien      if (edir->dyn_relocs != NULL)
397889857Sobrien	{
397989857Sobrien	  struct ppc_dyn_relocs **pp;
398089857Sobrien	  struct ppc_dyn_relocs *p;
398189857Sobrien
3982218822Sdim	  /* Add reloc counts against the indirect sym to the direct sym
398389857Sobrien	     list.  Merge any entries against the same section.  */
398489857Sobrien	  for (pp = &eind->dyn_relocs; (p = *pp) != NULL; )
398589857Sobrien	    {
398689857Sobrien	      struct ppc_dyn_relocs *q;
398789857Sobrien
398889857Sobrien	      for (q = edir->dyn_relocs; q != NULL; q = q->next)
398989857Sobrien		if (q->sec == p->sec)
399089857Sobrien		  {
399189857Sobrien		    q->pc_count += p->pc_count;
399289857Sobrien		    q->count += p->count;
399389857Sobrien		    *pp = p->next;
399489857Sobrien		    break;
399589857Sobrien		  }
399689857Sobrien	      if (q == NULL)
399789857Sobrien		pp = &p->next;
399889857Sobrien	    }
399989857Sobrien	  *pp = edir->dyn_relocs;
400089857Sobrien	}
400189857Sobrien
400289857Sobrien      edir->dyn_relocs = eind->dyn_relocs;
400389857Sobrien      eind->dyn_relocs = NULL;
400489857Sobrien    }
400589857Sobrien
400689857Sobrien  edir->is_func |= eind->is_func;
400789857Sobrien  edir->is_func_descriptor |= eind->is_func_descriptor;
4008130561Sobrien  edir->tls_mask |= eind->tls_mask;
400989857Sobrien
4010130561Sobrien  /* If called to transfer flags for a weakdef during processing
4011218822Sdim     of elf_adjust_dynamic_symbol, don't copy NON_GOT_REF.
4012130561Sobrien     We clear it ourselves for ELIMINATE_COPY_RELOCS.  */
4013218822Sdim  if (!(ELIMINATE_COPY_RELOCS
4014218822Sdim	&& eind->elf.root.type != bfd_link_hash_indirect
4015218822Sdim	&& edir->elf.dynamic_adjusted))
4016218822Sdim    edir->elf.non_got_ref |= eind->elf.non_got_ref;
4017130561Sobrien
4018218822Sdim  edir->elf.ref_dynamic |= eind->elf.ref_dynamic;
4019218822Sdim  edir->elf.ref_regular |= eind->elf.ref_regular;
4020218822Sdim  edir->elf.ref_regular_nonweak |= eind->elf.ref_regular_nonweak;
4021218822Sdim  edir->elf.needs_plt |= eind->elf.needs_plt;
4022130561Sobrien
4023130561Sobrien  /* If we were called to copy over info for a weak sym, that's all.  */
4024130561Sobrien  if (eind->elf.root.type != bfd_link_hash_indirect)
4025130561Sobrien    return;
4026130561Sobrien
4027130561Sobrien  /* Copy over got entries that we may have already seen to the
4028130561Sobrien     symbol which just became indirect.  */
4029130561Sobrien  if (eind->elf.got.glist != NULL)
4030130561Sobrien    {
4031130561Sobrien      if (edir->elf.got.glist != NULL)
4032130561Sobrien	{
4033130561Sobrien	  struct got_entry **entp;
4034130561Sobrien	  struct got_entry *ent;
4035130561Sobrien
4036130561Sobrien	  for (entp = &eind->elf.got.glist; (ent = *entp) != NULL; )
4037130561Sobrien	    {
4038130561Sobrien	      struct got_entry *dent;
4039130561Sobrien
4040130561Sobrien	      for (dent = edir->elf.got.glist; dent != NULL; dent = dent->next)
4041130561Sobrien		if (dent->addend == ent->addend
4042130561Sobrien		    && dent->owner == ent->owner
4043130561Sobrien		    && dent->tls_type == ent->tls_type)
4044130561Sobrien		  {
4045130561Sobrien		    dent->got.refcount += ent->got.refcount;
4046130561Sobrien		    *entp = ent->next;
4047130561Sobrien		    break;
4048130561Sobrien		  }
4049130561Sobrien	      if (dent == NULL)
4050130561Sobrien		entp = &ent->next;
4051130561Sobrien	    }
4052130561Sobrien	  *entp = edir->elf.got.glist;
4053130561Sobrien	}
4054130561Sobrien
4055130561Sobrien      edir->elf.got.glist = eind->elf.got.glist;
4056130561Sobrien      eind->elf.got.glist = NULL;
4057130561Sobrien    }
4058130561Sobrien
4059130561Sobrien  /* And plt entries.  */
4060218822Sdim  move_plt_plist (eind, edir);
4061130561Sobrien
4062218822Sdim  if (eind->elf.dynindx != -1)
4063130561Sobrien    {
4064218822Sdim      if (edir->elf.dynindx != -1)
4065218822Sdim	_bfd_elf_strtab_delref (elf_hash_table (info)->dynstr,
4066218822Sdim				edir->elf.dynstr_index);
4067130561Sobrien      edir->elf.dynindx = eind->elf.dynindx;
4068130561Sobrien      edir->elf.dynstr_index = eind->elf.dynstr_index;
4069130561Sobrien      eind->elf.dynindx = -1;
4070130561Sobrien      eind->elf.dynstr_index = 0;
4071130561Sobrien    }
407289857Sobrien}
407389857Sobrien
4074218822Sdim/* Find the function descriptor hash entry from the given function code
4075218822Sdim   hash entry FH.  Link the entries via their OH fields.  */
4076104834Sobrien
4077218822Sdimstatic struct ppc_link_hash_entry *
4078218822Sdimget_fdh (struct ppc_link_hash_entry *fh, struct ppc_link_hash_table *htab)
4079104834Sobrien{
4080218822Sdim  struct ppc_link_hash_entry *fdh = fh->oh;
4081104834Sobrien
4082218822Sdim  if (fdh == NULL)
4083104834Sobrien    {
4084218822Sdim      const char *fd_name = fh->elf.root.root.string + 1;
4085104834Sobrien
4086218822Sdim      fdh = (struct ppc_link_hash_entry *)
4087218822Sdim	elf_link_hash_lookup (&htab->elf, fd_name, FALSE, FALSE, FALSE);
4088218822Sdim      if (fdh != NULL)
4089218822Sdim	{
4090218822Sdim	  fdh->is_func_descriptor = 1;
4091218822Sdim	  fdh->oh = fh;
4092218822Sdim	  fh->is_func = 1;
4093218822Sdim	  fh->oh = fdh;
4094218822Sdim	}
4095104834Sobrien    }
4096218822Sdim
4097218822Sdim  return fdh;
4098104834Sobrien}
4099104834Sobrien
4100218822Sdim/* Make a fake function descriptor sym for the code sym FH.  */
4101130561Sobrien
4102218822Sdimstatic struct ppc_link_hash_entry *
4103218822Sdimmake_fdh (struct bfd_link_info *info,
4104218822Sdim	  struct ppc_link_hash_entry *fh)
4105218822Sdim{
4106218822Sdim  bfd *abfd;
4107218822Sdim  asymbol *newsym;
4108218822Sdim  struct bfd_link_hash_entry *bh;
4109218822Sdim  struct ppc_link_hash_entry *fdh;
4110218822Sdim
4111218822Sdim  abfd = fh->elf.root.u.undef.abfd;
4112218822Sdim  newsym = bfd_make_empty_symbol (abfd);
4113218822Sdim  newsym->name = fh->elf.root.root.string + 1;
4114218822Sdim  newsym->section = bfd_und_section_ptr;
4115218822Sdim  newsym->value = 0;
4116218822Sdim  newsym->flags = BSF_WEAK;
4117218822Sdim
4118218822Sdim  bh = NULL;
4119218822Sdim  if (!_bfd_generic_link_add_one_symbol (info, abfd, newsym->name,
4120218822Sdim					 newsym->flags, newsym->section,
4121218822Sdim					 newsym->value, NULL, FALSE, FALSE,
4122218822Sdim					 &bh))
4123218822Sdim    return NULL;
4124218822Sdim
4125218822Sdim  fdh = (struct ppc_link_hash_entry *) bh;
4126218822Sdim  fdh->elf.non_elf = 0;
4127218822Sdim  fdh->fake = 1;
4128218822Sdim  fdh->is_func_descriptor = 1;
4129218822Sdim  fdh->oh = fh;
4130218822Sdim  fh->is_func = 1;
4131218822Sdim  fh->oh = fdh;
4132218822Sdim  return fdh;
4133218822Sdim}
4134218822Sdim
4135218822Sdim/* Fix function descriptor symbols defined in .opd sections to be
4136218822Sdim   function type.  */
4137218822Sdim
4138130561Sobrienstatic bfd_boolean
4139130561Sobrienppc64_elf_add_symbol_hook (bfd *ibfd ATTRIBUTE_UNUSED,
4140130561Sobrien			   struct bfd_link_info *info ATTRIBUTE_UNUSED,
4141130561Sobrien			   Elf_Internal_Sym *isym,
4142130561Sobrien			   const char **name ATTRIBUTE_UNUSED,
4143130561Sobrien			   flagword *flags ATTRIBUTE_UNUSED,
4144130561Sobrien			   asection **sec,
4145130561Sobrien			   bfd_vma *value ATTRIBUTE_UNUSED)
4146130561Sobrien{
4147218822Sdim  if (*sec != NULL
4148218822Sdim      && strcmp (bfd_get_section_name (ibfd, *sec), ".opd") == 0)
4149130561Sobrien    isym->st_info = ELF_ST_INFO (ELF_ST_BIND (isym->st_info), STT_FUNC);
4150218822Sdim
4151130561Sobrien  return TRUE;
4152130561Sobrien}
4153130561Sobrien
4154218822Sdim/* This function makes an old ABI object reference to ".bar" cause the
4155218822Sdim   inclusion of a new ABI object archive that defines "bar".
4156218822Sdim   NAME is a symbol defined in an archive.  Return a symbol in the hash
4157218822Sdim   table that might be satisfied by the archive symbols.  */
4158218822Sdim
4159218822Sdimstatic struct elf_link_hash_entry *
4160218822Sdimppc64_elf_archive_symbol_lookup (bfd *abfd,
4161218822Sdim				 struct bfd_link_info *info,
4162218822Sdim				 const char *name)
4163218822Sdim{
4164218822Sdim  struct elf_link_hash_entry *h;
4165218822Sdim  char *dot_name;
4166218822Sdim  size_t len;
4167218822Sdim
4168218822Sdim  h = _bfd_elf_archive_symbol_lookup (abfd, info, name);
4169218822Sdim  if (h != NULL
4170218822Sdim      /* Don't return this sym if it is a fake function descriptor
4171218822Sdim	 created by add_symbol_adjust.  */
4172218822Sdim      && !(h->root.type == bfd_link_hash_undefweak
4173218822Sdim	   && ((struct ppc_link_hash_entry *) h)->fake))
4174218822Sdim    return h;
4175218822Sdim
4176218822Sdim  if (name[0] == '.')
4177218822Sdim    return h;
4178218822Sdim
4179218822Sdim  len = strlen (name);
4180218822Sdim  dot_name = bfd_alloc (abfd, len + 2);
4181218822Sdim  if (dot_name == NULL)
4182218822Sdim    return (struct elf_link_hash_entry *) 0 - 1;
4183218822Sdim  dot_name[0] = '.';
4184218822Sdim  memcpy (dot_name + 1, name, len + 1);
4185218822Sdim  h = _bfd_elf_archive_symbol_lookup (abfd, info, dot_name);
4186218822Sdim  bfd_release (abfd, dot_name);
4187218822Sdim  return h;
4188218822Sdim}
4189218822Sdim
4190218822Sdim/* This function satisfies all old ABI object references to ".bar" if a
4191218822Sdim   new ABI object defines "bar".  Well, at least, undefined dot symbols
4192218822Sdim   are made weak.  This stops later archive searches from including an
4193218822Sdim   object if we already have a function descriptor definition.  It also
4194218822Sdim   prevents the linker complaining about undefined symbols.
4195218822Sdim   We also check and correct mismatched symbol visibility here.  The
4196218822Sdim   most restrictive visibility of the function descriptor and the
4197218822Sdim   function entry symbol is used.  */
4198218822Sdim
4199130561Sobrienstatic bfd_boolean
4200218822Sdimadd_symbol_adjust (struct ppc_link_hash_entry *eh, struct bfd_link_info *info)
4201218822Sdim{
4202218822Sdim  struct ppc_link_hash_table *htab;
4203218822Sdim  struct ppc_link_hash_entry *fdh;
4204218822Sdim
4205218822Sdim  if (eh->elf.root.type == bfd_link_hash_indirect)
4206218822Sdim    return TRUE;
4207218822Sdim
4208218822Sdim  if (eh->elf.root.type == bfd_link_hash_warning)
4209218822Sdim    eh = (struct ppc_link_hash_entry *) eh->elf.root.u.i.link;
4210218822Sdim
4211218822Sdim  if (eh->elf.root.root.string[0] != '.')
4212218822Sdim    abort ();
4213218822Sdim
4214218822Sdim  htab = ppc_hash_table (info);
4215218822Sdim  fdh = get_fdh (eh, htab);
4216218822Sdim  if (fdh == NULL
4217218822Sdim      && !info->relocatable
4218218822Sdim      && (eh->elf.root.type == bfd_link_hash_undefined
4219218822Sdim	  || eh->elf.root.type == bfd_link_hash_undefweak)
4220218822Sdim      && eh->elf.ref_regular)
4221218822Sdim    {
4222218822Sdim      /* Make an undefweak function descriptor sym, which is enough to
4223218822Sdim	 pull in an --as-needed shared lib, but won't cause link
4224218822Sdim	 errors.  Archives are handled elsewhere.  */
4225218822Sdim      fdh = make_fdh (info, eh);
4226218822Sdim      if (fdh == NULL)
4227218822Sdim	return FALSE;
4228218822Sdim      else
4229218822Sdim	fdh->elf.ref_regular = 1;
4230218822Sdim    }
4231218822Sdim  else if (fdh != NULL)
4232218822Sdim    {
4233218822Sdim      unsigned entry_vis = ELF_ST_VISIBILITY (eh->elf.other) - 1;
4234218822Sdim      unsigned descr_vis = ELF_ST_VISIBILITY (fdh->elf.other) - 1;
4235218822Sdim      if (entry_vis < descr_vis)
4236218822Sdim	fdh->elf.other += entry_vis - descr_vis;
4237218822Sdim      else if (entry_vis > descr_vis)
4238218822Sdim	eh->elf.other += descr_vis - entry_vis;
4239218822Sdim
4240218822Sdim      if ((fdh->elf.root.type == bfd_link_hash_defined
4241218822Sdim	   || fdh->elf.root.type == bfd_link_hash_defweak)
4242218822Sdim	  && eh->elf.root.type == bfd_link_hash_undefined)
4243218822Sdim	{
4244218822Sdim	  eh->elf.root.type = bfd_link_hash_undefweak;
4245218822Sdim	  eh->was_undefined = 1;
4246218822Sdim	  htab->twiddled_syms = 1;
4247218822Sdim	}
4248218822Sdim    }
4249218822Sdim
4250218822Sdim  return TRUE;
4251218822Sdim}
4252218822Sdim
4253218822Sdim/* Process list of dot-symbols we made in link_hash_newfunc.  */
4254218822Sdim
4255218822Sdimstatic bfd_boolean
4256218822Sdimppc64_elf_check_directives (bfd *ibfd, struct bfd_link_info *info)
4257218822Sdim{
4258218822Sdim  struct ppc_link_hash_table *htab;
4259218822Sdim  struct ppc_link_hash_entry **p, *eh;
4260218822Sdim
4261218822Sdim  htab = ppc_hash_table (info);
4262218822Sdim  if (!is_ppc64_elf_target (htab->elf.root.creator))
4263218822Sdim    return TRUE;
4264218822Sdim
4265218822Sdim  if (is_ppc64_elf_target (ibfd->xvec))
4266218822Sdim    {
4267218822Sdim      p = &htab->dot_syms;
4268218822Sdim      while ((eh = *p) != NULL)
4269218822Sdim	{
4270218822Sdim	  *p = NULL;
4271218822Sdim	  if (!add_symbol_adjust (eh, info))
4272218822Sdim	    return FALSE;
4273218822Sdim	  p = &eh->u.next_dot_sym;
4274218822Sdim	}
4275218822Sdim    }
4276218822Sdim
4277218822Sdim  /* Clear the list for non-ppc64 input files.  */
4278218822Sdim  p = &htab->dot_syms;
4279218822Sdim  while ((eh = *p) != NULL)
4280218822Sdim    {
4281218822Sdim      *p = NULL;
4282218822Sdim      p = &eh->u.next_dot_sym;
4283218822Sdim    }
4284218822Sdim
4285218822Sdim  /* We need to fix the undefs list for any syms we have twiddled to
4286218822Sdim     undef_weak.  */
4287218822Sdim  if (htab->twiddled_syms)
4288218822Sdim    {
4289218822Sdim      bfd_link_repair_undef_list (&htab->elf.root);
4290218822Sdim      htab->twiddled_syms = 0;
4291218822Sdim    }
4292218822Sdim  return TRUE;
4293218822Sdim}
4294218822Sdim
4295218822Sdim/* Undo hash table changes when an --as-needed input file is determined
4296218822Sdim   not to be needed.  */
4297218822Sdim
4298218822Sdimstatic bfd_boolean
4299218822Sdimppc64_elf_as_needed_cleanup (bfd *ibfd ATTRIBUTE_UNUSED,
4300218822Sdim			     struct bfd_link_info *info)
4301218822Sdim{
4302218822Sdim  ppc_hash_table (info)->dot_syms = NULL;
4303218822Sdim  return TRUE;
4304218822Sdim}
4305218822Sdim
4306218822Sdimstatic bfd_boolean
4307130561Sobrienupdate_local_sym_info (bfd *abfd, Elf_Internal_Shdr *symtab_hdr,
4308130561Sobrien		       unsigned long r_symndx, bfd_vma r_addend, int tls_type)
4309130561Sobrien{
4310130561Sobrien  struct got_entry **local_got_ents = elf_local_got_ents (abfd);
4311130561Sobrien  char *local_got_tls_masks;
4312130561Sobrien
4313130561Sobrien  if (local_got_ents == NULL)
4314130561Sobrien    {
4315130561Sobrien      bfd_size_type size = symtab_hdr->sh_info;
4316130561Sobrien
4317130561Sobrien      size *= sizeof (*local_got_ents) + sizeof (*local_got_tls_masks);
4318130561Sobrien      local_got_ents = bfd_zalloc (abfd, size);
4319130561Sobrien      if (local_got_ents == NULL)
4320130561Sobrien	return FALSE;
4321130561Sobrien      elf_local_got_ents (abfd) = local_got_ents;
4322130561Sobrien    }
4323130561Sobrien
4324130561Sobrien  if ((tls_type & TLS_EXPLICIT) == 0)
4325130561Sobrien    {
4326130561Sobrien      struct got_entry *ent;
4327130561Sobrien
4328130561Sobrien      for (ent = local_got_ents[r_symndx]; ent != NULL; ent = ent->next)
4329130561Sobrien	if (ent->addend == r_addend
4330130561Sobrien	    && ent->owner == abfd
4331130561Sobrien	    && ent->tls_type == tls_type)
4332130561Sobrien	  break;
4333130561Sobrien      if (ent == NULL)
4334130561Sobrien	{
4335130561Sobrien	  bfd_size_type amt = sizeof (*ent);
4336130561Sobrien	  ent = bfd_alloc (abfd, amt);
4337130561Sobrien	  if (ent == NULL)
4338130561Sobrien	    return FALSE;
4339130561Sobrien	  ent->next = local_got_ents[r_symndx];
4340130561Sobrien	  ent->addend = r_addend;
4341130561Sobrien	  ent->owner = abfd;
4342130561Sobrien	  ent->tls_type = tls_type;
4343130561Sobrien	  ent->got.refcount = 0;
4344130561Sobrien	  local_got_ents[r_symndx] = ent;
4345130561Sobrien	}
4346130561Sobrien      ent->got.refcount += 1;
4347130561Sobrien    }
4348130561Sobrien
4349130561Sobrien  local_got_tls_masks = (char *) (local_got_ents + symtab_hdr->sh_info);
4350130561Sobrien  local_got_tls_masks[r_symndx] |= tls_type;
4351130561Sobrien  return TRUE;
4352130561Sobrien}
4353130561Sobrien
4354130561Sobrienstatic bfd_boolean
4355130561Sobrienupdate_plt_info (bfd *abfd, struct ppc_link_hash_entry *eh, bfd_vma addend)
4356130561Sobrien{
4357130561Sobrien  struct plt_entry *ent;
4358130561Sobrien
4359130561Sobrien  for (ent = eh->elf.plt.plist; ent != NULL; ent = ent->next)
4360130561Sobrien    if (ent->addend == addend)
4361130561Sobrien      break;
4362130561Sobrien  if (ent == NULL)
4363130561Sobrien    {
4364130561Sobrien      bfd_size_type amt = sizeof (*ent);
4365130561Sobrien      ent = bfd_alloc (abfd, amt);
4366130561Sobrien      if (ent == NULL)
4367130561Sobrien	return FALSE;
4368130561Sobrien      ent->next = eh->elf.plt.plist;
4369130561Sobrien      ent->addend = addend;
4370130561Sobrien      ent->plt.refcount = 0;
4371130561Sobrien      eh->elf.plt.plist = ent;
4372130561Sobrien    }
4373130561Sobrien  ent->plt.refcount += 1;
4374218822Sdim  eh->elf.needs_plt = 1;
4375218822Sdim  if (eh->elf.root.root.string[0] == '.'
4376218822Sdim      && eh->elf.root.root.string[1] != '\0')
4377218822Sdim    eh->is_func = 1;
4378130561Sobrien  return TRUE;
4379130561Sobrien}
4380130561Sobrien
438189857Sobrien/* Look through the relocs for a section during the first phase, and
438289857Sobrien   calculate needed space in the global offset table, procedure
438389857Sobrien   linkage table, and dynamic reloc sections.  */
438489857Sobrien
4385130561Sobrienstatic bfd_boolean
4386130561Sobrienppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
4387130561Sobrien			asection *sec, const Elf_Internal_Rela *relocs)
438889857Sobrien{
438989857Sobrien  struct ppc_link_hash_table *htab;
439089857Sobrien  Elf_Internal_Shdr *symtab_hdr;
439189857Sobrien  struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
439289857Sobrien  const Elf_Internal_Rela *rel;
439389857Sobrien  const Elf_Internal_Rela *rel_end;
439489857Sobrien  asection *sreloc;
4395104834Sobrien  asection **opd_sym_map;
439689857Sobrien
4397130561Sobrien  if (info->relocatable)
4398130561Sobrien    return TRUE;
439989857Sobrien
4400130561Sobrien  /* Don't do anything special with non-loaded, non-alloced sections.
4401130561Sobrien     In particular, any relocs in such sections should not affect GOT
4402130561Sobrien     and PLT reference counting (ie. we don't allow them to create GOT
4403130561Sobrien     or PLT entries), there's no possibility or desire to optimize TLS
4404130561Sobrien     relocs, and there's not much point in propagating relocs to shared
4405130561Sobrien     libs that the dynamic linker won't relocate.  */
4406130561Sobrien  if ((sec->flags & SEC_ALLOC) == 0)
4407130561Sobrien    return TRUE;
4408130561Sobrien
440989857Sobrien  htab = ppc_hash_table (info);
441089857Sobrien  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
441189857Sobrien
441289857Sobrien  sym_hashes = elf_sym_hashes (abfd);
441389857Sobrien  sym_hashes_end = (sym_hashes
4414104834Sobrien		    + symtab_hdr->sh_size / sizeof (Elf64_External_Sym)
4415104834Sobrien		    - symtab_hdr->sh_info);
441689857Sobrien
441789857Sobrien  sreloc = NULL;
4418104834Sobrien  opd_sym_map = NULL;
4419104834Sobrien  if (strcmp (bfd_get_section_name (abfd, sec), ".opd") == 0)
4420104834Sobrien    {
4421104834Sobrien      /* Garbage collection needs some extra help with .opd sections.
4422104834Sobrien	 We don't want to necessarily keep everything referenced by
4423104834Sobrien	 relocs in .opd, as that would keep all functions.  Instead,
4424104834Sobrien	 if we reference an .opd symbol (a function descriptor), we
4425104834Sobrien	 want to keep the function code symbol's section.  This is
4426104834Sobrien	 easy for global symbols, but for local syms we need to keep
4427104834Sobrien	 information about the associated function section.  Later, if
4428104834Sobrien	 edit_opd deletes entries, we'll use this array to adjust
4429104834Sobrien	 local syms in .opd.  */
4430104834Sobrien      union opd_info {
4431104834Sobrien	asection *func_section;
4432104834Sobrien	long entry_adjust;
4433104834Sobrien      };
4434104834Sobrien      bfd_size_type amt;
443589857Sobrien
4436218822Sdim      amt = sec->size * sizeof (union opd_info) / 8;
4437130561Sobrien      opd_sym_map = bfd_zalloc (abfd, amt);
4438104834Sobrien      if (opd_sym_map == NULL)
4439130561Sobrien	return FALSE;
4440218822Sdim      ppc64_elf_section_data (sec)->u.opd_func_sec = opd_sym_map;
4441218822Sdim      BFD_ASSERT (ppc64_elf_section_data (sec)->sec_type == sec_normal);
4442218822Sdim      ppc64_elf_section_data (sec)->sec_type = sec_opd;
4443104834Sobrien    }
4444104834Sobrien
444592828Sobrien  if (htab->sfpr == NULL
444692828Sobrien      && !create_linkage_sections (htab->elf.dynobj, info))
4447130561Sobrien    return FALSE;
444892828Sobrien
444989857Sobrien  rel_end = relocs + sec->reloc_count;
445089857Sobrien  for (rel = relocs; rel < rel_end; rel++)
445189857Sobrien    {
445289857Sobrien      unsigned long r_symndx;
445389857Sobrien      struct elf_link_hash_entry *h;
4454130561Sobrien      enum elf_ppc64_reloc_type r_type;
4455130561Sobrien      int tls_type = 0;
4456218822Sdim      struct _ppc64_elf_section_data *ppc64_sec;
445789857Sobrien
445889857Sobrien      r_symndx = ELF64_R_SYM (rel->r_info);
445989857Sobrien      if (r_symndx < symtab_hdr->sh_info)
446089857Sobrien	h = NULL;
446189857Sobrien      else
4462218822Sdim	{
4463218822Sdim	  h = sym_hashes[r_symndx - symtab_hdr->sh_info];
4464218822Sdim	  while (h->root.type == bfd_link_hash_indirect
4465218822Sdim		 || h->root.type == bfd_link_hash_warning)
4466218822Sdim	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
4467218822Sdim	}
446889857Sobrien
4469130561Sobrien      r_type = ELF64_R_TYPE (rel->r_info);
447089857Sobrien      switch (r_type)
447189857Sobrien	{
4472130561Sobrien	case R_PPC64_GOT_TLSLD16:
4473130561Sobrien	case R_PPC64_GOT_TLSLD16_LO:
4474130561Sobrien	case R_PPC64_GOT_TLSLD16_HI:
4475130561Sobrien	case R_PPC64_GOT_TLSLD16_HA:
4476130561Sobrien	  ppc64_tlsld_got (abfd)->refcount += 1;
4477130561Sobrien	  tls_type = TLS_TLS | TLS_LD;
4478130561Sobrien	  goto dogottls;
4479130561Sobrien
4480130561Sobrien	case R_PPC64_GOT_TLSGD16:
4481130561Sobrien	case R_PPC64_GOT_TLSGD16_LO:
4482130561Sobrien	case R_PPC64_GOT_TLSGD16_HI:
4483130561Sobrien	case R_PPC64_GOT_TLSGD16_HA:
4484130561Sobrien	  tls_type = TLS_TLS | TLS_GD;
4485130561Sobrien	  goto dogottls;
4486130561Sobrien
4487130561Sobrien	case R_PPC64_GOT_TPREL16_DS:
4488130561Sobrien	case R_PPC64_GOT_TPREL16_LO_DS:
4489130561Sobrien	case R_PPC64_GOT_TPREL16_HI:
4490130561Sobrien	case R_PPC64_GOT_TPREL16_HA:
4491130561Sobrien	  if (info->shared)
4492130561Sobrien	    info->flags |= DF_STATIC_TLS;
4493130561Sobrien	  tls_type = TLS_TLS | TLS_TPREL;
4494130561Sobrien	  goto dogottls;
4495130561Sobrien
4496130561Sobrien	case R_PPC64_GOT_DTPREL16_DS:
4497130561Sobrien	case R_PPC64_GOT_DTPREL16_LO_DS:
4498130561Sobrien	case R_PPC64_GOT_DTPREL16_HI:
4499130561Sobrien	case R_PPC64_GOT_DTPREL16_HA:
4500130561Sobrien	  tls_type = TLS_TLS | TLS_DTPREL;
4501130561Sobrien	dogottls:
4502130561Sobrien	  sec->has_tls_reloc = 1;
4503130561Sobrien	  /* Fall thru */
4504130561Sobrien
450589857Sobrien	case R_PPC64_GOT16:
450689857Sobrien	case R_PPC64_GOT16_DS:
450789857Sobrien	case R_PPC64_GOT16_HA:
450889857Sobrien	case R_PPC64_GOT16_HI:
450989857Sobrien	case R_PPC64_GOT16_LO:
451089857Sobrien	case R_PPC64_GOT16_LO_DS:
451189857Sobrien	  /* This symbol requires a global offset table entry.  */
4512218822Sdim	  sec->has_toc_reloc = 1;
4513130561Sobrien	  if (ppc64_elf_tdata (abfd)->got == NULL
4514130561Sobrien	      && !create_got_section (abfd, info))
4515130561Sobrien	    return FALSE;
451689857Sobrien
451789857Sobrien	  if (h != NULL)
451889857Sobrien	    {
4519130561Sobrien	      struct ppc_link_hash_entry *eh;
4520130561Sobrien	      struct got_entry *ent;
452189857Sobrien
4522130561Sobrien	      eh = (struct ppc_link_hash_entry *) h;
4523130561Sobrien	      for (ent = eh->elf.got.glist; ent != NULL; ent = ent->next)
4524130561Sobrien		if (ent->addend == rel->r_addend
4525130561Sobrien		    && ent->owner == abfd
4526130561Sobrien		    && ent->tls_type == tls_type)
4527130561Sobrien		  break;
4528130561Sobrien	      if (ent == NULL)
452989857Sobrien		{
4530130561Sobrien		  bfd_size_type amt = sizeof (*ent);
4531130561Sobrien		  ent = bfd_alloc (abfd, amt);
4532130561Sobrien		  if (ent == NULL)
4533130561Sobrien		    return FALSE;
4534130561Sobrien		  ent->next = eh->elf.got.glist;
4535130561Sobrien		  ent->addend = rel->r_addend;
4536130561Sobrien		  ent->owner = abfd;
4537130561Sobrien		  ent->tls_type = tls_type;
4538130561Sobrien		  ent->got.refcount = 0;
4539130561Sobrien		  eh->elf.got.glist = ent;
454089857Sobrien		}
4541130561Sobrien	      ent->got.refcount += 1;
4542130561Sobrien	      eh->tls_mask |= tls_type;
454389857Sobrien	    }
4544130561Sobrien	  else
4545130561Sobrien	    /* This is a global offset table entry for a local symbol.  */
4546130561Sobrien	    if (!update_local_sym_info (abfd, symtab_hdr, r_symndx,
4547130561Sobrien					rel->r_addend, tls_type))
4548130561Sobrien	      return FALSE;
454989857Sobrien	  break;
455089857Sobrien
455189857Sobrien	case R_PPC64_PLT16_HA:
455289857Sobrien	case R_PPC64_PLT16_HI:
455389857Sobrien	case R_PPC64_PLT16_LO:
455489857Sobrien	case R_PPC64_PLT32:
455589857Sobrien	case R_PPC64_PLT64:
455689857Sobrien	  /* This symbol requires a procedure linkage table entry.  We
4557104834Sobrien	     actually build the entry in adjust_dynamic_symbol,
4558104834Sobrien	     because this might be a case of linking PIC code without
4559104834Sobrien	     linking in any dynamic objects, in which case we don't
4560104834Sobrien	     need to generate a procedure linkage table after all.  */
456189857Sobrien	  if (h == NULL)
456289857Sobrien	    {
456389857Sobrien	      /* It does not make sense to have a procedure linkage
4564104834Sobrien		 table entry for a local symbol.  */
456589857Sobrien	      bfd_set_error (bfd_error_bad_value);
4566130561Sobrien	      return FALSE;
456789857Sobrien	    }
4568130561Sobrien	  else
4569130561Sobrien	    if (!update_plt_info (abfd, (struct ppc_link_hash_entry *) h,
4570130561Sobrien				  rel->r_addend))
4571130561Sobrien	      return FALSE;
457289857Sobrien	  break;
457389857Sobrien
457489857Sobrien	  /* The following relocations don't need to propagate the
457589857Sobrien	     relocation if linking a shared object since they are
457689857Sobrien	     section relative.  */
457789857Sobrien	case R_PPC64_SECTOFF:
457889857Sobrien	case R_PPC64_SECTOFF_LO:
457989857Sobrien	case R_PPC64_SECTOFF_HI:
458089857Sobrien	case R_PPC64_SECTOFF_HA:
458189857Sobrien	case R_PPC64_SECTOFF_DS:
458289857Sobrien	case R_PPC64_SECTOFF_LO_DS:
4583130561Sobrien	case R_PPC64_DTPREL16:
4584130561Sobrien	case R_PPC64_DTPREL16_LO:
4585130561Sobrien	case R_PPC64_DTPREL16_HI:
4586130561Sobrien	case R_PPC64_DTPREL16_HA:
4587130561Sobrien	case R_PPC64_DTPREL16_DS:
4588130561Sobrien	case R_PPC64_DTPREL16_LO_DS:
4589130561Sobrien	case R_PPC64_DTPREL16_HIGHER:
4590130561Sobrien	case R_PPC64_DTPREL16_HIGHERA:
4591130561Sobrien	case R_PPC64_DTPREL16_HIGHEST:
4592130561Sobrien	case R_PPC64_DTPREL16_HIGHESTA:
4593130561Sobrien	  break;
4594130561Sobrien
4595130561Sobrien	  /* Nor do these.  */
459689857Sobrien	case R_PPC64_TOC16:
459789857Sobrien	case R_PPC64_TOC16_LO:
459889857Sobrien	case R_PPC64_TOC16_HI:
459989857Sobrien	case R_PPC64_TOC16_HA:
460089857Sobrien	case R_PPC64_TOC16_DS:
460189857Sobrien	case R_PPC64_TOC16_LO_DS:
4602218822Sdim	  sec->has_toc_reloc = 1;
460389857Sobrien	  break;
460489857Sobrien
460589857Sobrien	  /* This relocation describes the C++ object vtable hierarchy.
460689857Sobrien	     Reconstruct it for later use during GC.  */
460789857Sobrien	case R_PPC64_GNU_VTINHERIT:
4608130561Sobrien	  if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
4609130561Sobrien	    return FALSE;
461089857Sobrien	  break;
461189857Sobrien
461289857Sobrien	  /* This relocation describes which C++ vtable entries are actually
461389857Sobrien	     used.  Record for later use during GC.  */
461489857Sobrien	case R_PPC64_GNU_VTENTRY:
4615130561Sobrien	  if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
4616130561Sobrien	    return FALSE;
461789857Sobrien	  break;
461889857Sobrien
4619104834Sobrien	case R_PPC64_REL14:
4620104834Sobrien	case R_PPC64_REL14_BRTAKEN:
4621104834Sobrien	case R_PPC64_REL14_BRNTAKEN:
4622218822Sdim	  {
4623218822Sdim	    asection *dest = NULL;
4624218822Sdim
4625218822Sdim	    /* Heuristic: If jumping outside our section, chances are
4626218822Sdim	       we are going to need a stub.  */
4627218822Sdim	    if (h != NULL)
4628218822Sdim	      {
4629218822Sdim		/* If the sym is weak it may be overridden later, so
4630218822Sdim		   don't assume we know where a weak sym lives.  */
4631218822Sdim		if (h->root.type == bfd_link_hash_defined)
4632218822Sdim		  dest = h->root.u.def.section;
4633218822Sdim	      }
4634218822Sdim	    else
4635218822Sdim	      dest = bfd_section_from_r_symndx (abfd, &htab->sym_sec,
4636218822Sdim						sec, r_symndx);
4637218822Sdim	    if (dest != sec)
4638218822Sdim	      ppc64_elf_section_data (sec)->has_14bit_branch = 1;
4639218822Sdim	  }
4640104834Sobrien	  /* Fall through.  */
4641104834Sobrien
464289857Sobrien	case R_PPC64_REL24:
4643218822Sdim	  if (h != NULL)
464489857Sobrien	    {
464589857Sobrien	      /* We may need a .plt entry if the function this reloc
464689857Sobrien		 refers to is in a shared lib.  */
4647130561Sobrien	      if (!update_plt_info (abfd, (struct ppc_link_hash_entry *) h,
4648130561Sobrien				    rel->r_addend))
4649130561Sobrien		return FALSE;
4650218822Sdim	      if (h == &htab->tls_get_addr->elf
4651218822Sdim		  || h == &htab->tls_get_addr_fd->elf)
4652130561Sobrien		sec->has_tls_reloc = 1;
4653218822Sdim	      else if (htab->tls_get_addr == NULL
4654218822Sdim		       && CONST_STRNEQ (h->root.root.string, ".__tls_get_addr")
4655130561Sobrien		       && (h->root.root.string[15] == 0
4656130561Sobrien			   || h->root.root.string[15] == '@'))
4657130561Sobrien		{
4658218822Sdim		  htab->tls_get_addr = (struct ppc_link_hash_entry *) h;
4659130561Sobrien		  sec->has_tls_reloc = 1;
4660130561Sobrien		}
4661218822Sdim	      else if (htab->tls_get_addr_fd == NULL
4662218822Sdim		       && CONST_STRNEQ (h->root.root.string, "__tls_get_addr")
4663218822Sdim		       && (h->root.root.string[14] == 0
4664218822Sdim			   || h->root.root.string[14] == '@'))
4665218822Sdim		{
4666218822Sdim		  htab->tls_get_addr_fd = (struct ppc_link_hash_entry *) h;
4667218822Sdim		  sec->has_tls_reloc = 1;
4668218822Sdim		}
466989857Sobrien	    }
467089857Sobrien	  break;
467189857Sobrien
4672130561Sobrien	case R_PPC64_TPREL64:
4673130561Sobrien	  tls_type = TLS_EXPLICIT | TLS_TLS | TLS_TPREL;
4674130561Sobrien	  if (info->shared)
4675130561Sobrien	    info->flags |= DF_STATIC_TLS;
4676130561Sobrien	  goto dotlstoc;
4677130561Sobrien
4678130561Sobrien	case R_PPC64_DTPMOD64:
4679130561Sobrien	  if (rel + 1 < rel_end
4680130561Sobrien	      && rel[1].r_info == ELF64_R_INFO (r_symndx, R_PPC64_DTPREL64)
4681130561Sobrien	      && rel[1].r_offset == rel->r_offset + 8)
4682130561Sobrien	    tls_type = TLS_EXPLICIT | TLS_TLS | TLS_GD;
4683130561Sobrien	  else
4684130561Sobrien	    tls_type = TLS_EXPLICIT | TLS_TLS | TLS_LD;
4685130561Sobrien	  goto dotlstoc;
4686130561Sobrien
4687130561Sobrien	case R_PPC64_DTPREL64:
4688130561Sobrien	  tls_type = TLS_EXPLICIT | TLS_TLS | TLS_DTPREL;
4689130561Sobrien	  if (rel != relocs
4690130561Sobrien	      && rel[-1].r_info == ELF64_R_INFO (r_symndx, R_PPC64_DTPMOD64)
4691130561Sobrien	      && rel[-1].r_offset == rel->r_offset - 8)
4692130561Sobrien	    /* This is the second reloc of a dtpmod, dtprel pair.
4693130561Sobrien	       Don't mark with TLS_DTPREL.  */
4694130561Sobrien	    goto dodyn;
4695130561Sobrien
4696130561Sobrien	dotlstoc:
4697130561Sobrien	  sec->has_tls_reloc = 1;
4698130561Sobrien	  if (h != NULL)
4699130561Sobrien	    {
4700130561Sobrien	      struct ppc_link_hash_entry *eh;
4701130561Sobrien	      eh = (struct ppc_link_hash_entry *) h;
4702130561Sobrien	      eh->tls_mask |= tls_type;
4703130561Sobrien	    }
4704130561Sobrien	  else
4705130561Sobrien	    if (!update_local_sym_info (abfd, symtab_hdr, r_symndx,
4706130561Sobrien					rel->r_addend, tls_type))
4707130561Sobrien	      return FALSE;
4708130561Sobrien
4709218822Sdim	  ppc64_sec = ppc64_elf_section_data (sec);
4710218822Sdim	  if (ppc64_sec->sec_type != sec_toc)
4711130561Sobrien	    {
4712130561Sobrien	      /* One extra to simplify get_tls_mask.  */
4713218822Sdim	      bfd_size_type amt = sec->size * sizeof (unsigned) / 8 + 1;
4714218822Sdim	      ppc64_sec->u.t_symndx = bfd_zalloc (abfd, amt);
4715218822Sdim	      if (ppc64_sec->u.t_symndx == NULL)
4716130561Sobrien		return FALSE;
4717218822Sdim	      BFD_ASSERT (ppc64_sec->sec_type == sec_normal);
4718218822Sdim	      ppc64_sec->sec_type = sec_toc;
4719130561Sobrien	    }
4720130561Sobrien	  BFD_ASSERT (rel->r_offset % 8 == 0);
4721218822Sdim	  ppc64_sec->u.t_symndx[rel->r_offset / 8] = r_symndx;
4722130561Sobrien
4723130561Sobrien	  /* Mark the second slot of a GD or LD entry.
4724130561Sobrien	     -1 to indicate GD and -2 to indicate LD.  */
4725130561Sobrien	  if (tls_type == (TLS_EXPLICIT | TLS_TLS | TLS_GD))
4726218822Sdim	    ppc64_sec->u.t_symndx[rel->r_offset / 8 + 1] = -1;
4727130561Sobrien	  else if (tls_type == (TLS_EXPLICIT | TLS_TLS | TLS_LD))
4728218822Sdim	    ppc64_sec->u.t_symndx[rel->r_offset / 8 + 1] = -2;
4729130561Sobrien	  goto dodyn;
4730130561Sobrien
4731130561Sobrien	case R_PPC64_TPREL16:
4732130561Sobrien	case R_PPC64_TPREL16_LO:
4733130561Sobrien	case R_PPC64_TPREL16_HI:
4734130561Sobrien	case R_PPC64_TPREL16_HA:
4735130561Sobrien	case R_PPC64_TPREL16_DS:
4736130561Sobrien	case R_PPC64_TPREL16_LO_DS:
4737130561Sobrien	case R_PPC64_TPREL16_HIGHER:
4738130561Sobrien	case R_PPC64_TPREL16_HIGHERA:
4739130561Sobrien	case R_PPC64_TPREL16_HIGHEST:
4740130561Sobrien	case R_PPC64_TPREL16_HIGHESTA:
4741130561Sobrien	  if (info->shared)
4742130561Sobrien	    {
4743130561Sobrien	      info->flags |= DF_STATIC_TLS;
4744130561Sobrien	      goto dodyn;
4745130561Sobrien	    }
4746130561Sobrien	  break;
4747130561Sobrien
474889857Sobrien	case R_PPC64_ADDR64:
4749104834Sobrien	  if (opd_sym_map != NULL
4750104834Sobrien	      && rel + 1 < rel_end
4751130561Sobrien	      && ELF64_R_TYPE ((rel + 1)->r_info) == R_PPC64_TOC)
4752104834Sobrien	    {
4753218822Sdim	      if (h != NULL)
4754218822Sdim		{
4755218822Sdim		  if (h->root.root.string[0] == '.'
4756218822Sdim		      && h->root.root.string[1] != 0
4757218822Sdim		      && get_fdh ((struct ppc_link_hash_entry *) h, htab))
4758218822Sdim		    ;
4759218822Sdim		  else
4760218822Sdim		    ((struct ppc_link_hash_entry *) h)->is_func = 1;
4761218822Sdim		}
4762218822Sdim	      else
4763218822Sdim		{
4764218822Sdim		  asection *s;
4765104834Sobrien
4766218822Sdim		  s = bfd_section_from_r_symndx (abfd, &htab->sym_sec, sec,
4767218822Sdim						 r_symndx);
4768218822Sdim		  if (s == NULL)
4769218822Sdim		    return FALSE;
4770218822Sdim		  else if (s != sec)
4771218822Sdim		    opd_sym_map[rel->r_offset / 8] = s;
4772218822Sdim		}
4773104834Sobrien	    }
477489857Sobrien	  /* Fall through.  */
477589857Sobrien
4776130561Sobrien	case R_PPC64_REL30:
4777130561Sobrien	case R_PPC64_REL32:
477889857Sobrien	case R_PPC64_REL64:
477989857Sobrien	case R_PPC64_ADDR14:
478089857Sobrien	case R_PPC64_ADDR14_BRNTAKEN:
478189857Sobrien	case R_PPC64_ADDR14_BRTAKEN:
478289857Sobrien	case R_PPC64_ADDR16:
478389857Sobrien	case R_PPC64_ADDR16_DS:
478489857Sobrien	case R_PPC64_ADDR16_HA:
478589857Sobrien	case R_PPC64_ADDR16_HI:
478689857Sobrien	case R_PPC64_ADDR16_HIGHER:
478789857Sobrien	case R_PPC64_ADDR16_HIGHERA:
478889857Sobrien	case R_PPC64_ADDR16_HIGHEST:
478989857Sobrien	case R_PPC64_ADDR16_HIGHESTA:
479089857Sobrien	case R_PPC64_ADDR16_LO:
479189857Sobrien	case R_PPC64_ADDR16_LO_DS:
479289857Sobrien	case R_PPC64_ADDR24:
479389857Sobrien	case R_PPC64_ADDR32:
479489857Sobrien	case R_PPC64_UADDR16:
479589857Sobrien	case R_PPC64_UADDR32:
479689857Sobrien	case R_PPC64_UADDR64:
479789857Sobrien	case R_PPC64_TOC:
4798130561Sobrien	  if (h != NULL && !info->shared)
4799130561Sobrien	    /* We may need a copy reloc.  */
4800218822Sdim	    h->non_got_ref = 1;
4801130561Sobrien
480289857Sobrien	  /* Don't propagate .opd relocs.  */
4803104834Sobrien	  if (NO_OPD_RELOCS && opd_sym_map != NULL)
480489857Sobrien	    break;
480589857Sobrien
480689857Sobrien	  /* If we are creating a shared library, and this is a reloc
480789857Sobrien	     against a global symbol, or a non PC relative reloc
480889857Sobrien	     against a local symbol, then we need to copy the reloc
480989857Sobrien	     into the shared library.  However, if we are linking with
481089857Sobrien	     -Bsymbolic, we do not need to copy a reloc against a
481189857Sobrien	     global symbol which is defined in an object we are
481289857Sobrien	     including in the link (i.e., DEF_REGULAR is set).  At
481389857Sobrien	     this point we have not seen all the input files, so it is
481489857Sobrien	     possible that DEF_REGULAR is not set now but will be set
481589857Sobrien	     later (it is never cleared).  In case of a weak definition,
481689857Sobrien	     DEF_REGULAR may be cleared later by a strong definition in
481789857Sobrien	     a shared library.  We account for that possibility below by
4818130561Sobrien	     storing information in the dyn_relocs field of the hash
481989857Sobrien	     table entry.  A similar situation occurs when creating
482089857Sobrien	     shared libraries and symbol visibility changes render the
482189857Sobrien	     symbol local.
482289857Sobrien
482389857Sobrien	     If on the other hand, we are creating an executable, we
482489857Sobrien	     may need to keep relocations for symbols satisfied by a
482589857Sobrien	     dynamic library if we manage to avoid copy relocs for the
482689857Sobrien	     symbol.  */
4827130561Sobrien	dodyn:
482889857Sobrien	  if ((info->shared
4829130561Sobrien	       && (MUST_BE_DYN_RELOC (r_type)
483089857Sobrien		   || (h != NULL
483189857Sobrien		       && (! info->symbolic
483289857Sobrien			   || h->root.type == bfd_link_hash_defweak
4833218822Sdim			   || !h->def_regular))))
4834130561Sobrien	      || (ELIMINATE_COPY_RELOCS
4835130561Sobrien		  && !info->shared
483689857Sobrien		  && h != NULL
483789857Sobrien		  && (h->root.type == bfd_link_hash_defweak
4838218822Sdim		      || !h->def_regular)))
483989857Sobrien	    {
484089857Sobrien	      struct ppc_dyn_relocs *p;
484189857Sobrien	      struct ppc_dyn_relocs **head;
484289857Sobrien
484389857Sobrien	      /* We must copy these reloc types into the output file.
484489857Sobrien		 Create a reloc section in dynobj and make room for
484589857Sobrien		 this reloc.  */
484689857Sobrien	      if (sreloc == NULL)
484789857Sobrien		{
484889857Sobrien		  const char *name;
484989857Sobrien		  bfd *dynobj;
485089857Sobrien
485189857Sobrien		  name = (bfd_elf_string_from_elf_section
485289857Sobrien			  (abfd,
485389857Sobrien			   elf_elfheader (abfd)->e_shstrndx,
485489857Sobrien			   elf_section_data (sec)->rel_hdr.sh_name));
485589857Sobrien		  if (name == NULL)
4856130561Sobrien		    return FALSE;
485789857Sobrien
4858218822Sdim		  if (! CONST_STRNEQ (name, ".rela")
485989857Sobrien		      || strcmp (bfd_get_section_name (abfd, sec),
486089857Sobrien				 name + 5) != 0)
486189857Sobrien		    {
486289857Sobrien		      (*_bfd_error_handler)
4863218822Sdim			(_("%B: bad relocation section name `%s\'"),
4864218822Sdim			 abfd, name);
486589857Sobrien		      bfd_set_error (bfd_error_bad_value);
486689857Sobrien		    }
486789857Sobrien
486889857Sobrien		  dynobj = htab->elf.dynobj;
486989857Sobrien		  sreloc = bfd_get_section_by_name (dynobj, name);
487089857Sobrien		  if (sreloc == NULL)
487189857Sobrien		    {
487289857Sobrien		      flagword flags;
487389857Sobrien
487489857Sobrien		      flags = (SEC_HAS_CONTENTS | SEC_READONLY
4875218822Sdim			       | SEC_IN_MEMORY | SEC_LINKER_CREATED
4876218822Sdim			       | SEC_ALLOC | SEC_LOAD);
4877218822Sdim		      sreloc = bfd_make_section_with_flags (dynobj,
4878218822Sdim							    name,
4879218822Sdim							    flags);
488089857Sobrien		      if (sreloc == NULL
488189857Sobrien			  || ! bfd_set_section_alignment (dynobj, sreloc, 3))
4882130561Sobrien			return FALSE;
488389857Sobrien		    }
488489857Sobrien		  elf_section_data (sec)->sreloc = sreloc;
488589857Sobrien		}
488689857Sobrien
488789857Sobrien	      /* If this is a global symbol, we count the number of
488889857Sobrien		 relocations we need for this symbol.  */
488989857Sobrien	      if (h != NULL)
489089857Sobrien		{
489189857Sobrien		  head = &((struct ppc_link_hash_entry *) h)->dyn_relocs;
489289857Sobrien		}
489389857Sobrien	      else
489489857Sobrien		{
489589857Sobrien		  /* Track dynamic relocs needed for local syms too.
489689857Sobrien		     We really need local syms available to do this
489789857Sobrien		     easily.  Oh well.  */
489889857Sobrien
489989857Sobrien		  asection *s;
4900218822Sdim		  void *vpp;
4901218822Sdim
490289857Sobrien		  s = bfd_section_from_r_symndx (abfd, &htab->sym_sec,
490389857Sobrien						 sec, r_symndx);
490489857Sobrien		  if (s == NULL)
4905130561Sobrien		    return FALSE;
490689857Sobrien
4907218822Sdim		  vpp = &elf_section_data (s)->local_dynrel;
4908218822Sdim		  head = (struct ppc_dyn_relocs **) vpp;
490989857Sobrien		}
491089857Sobrien
491189857Sobrien	      p = *head;
491289857Sobrien	      if (p == NULL || p->sec != sec)
491389857Sobrien		{
4914130561Sobrien		  p = bfd_alloc (htab->elf.dynobj, sizeof *p);
491589857Sobrien		  if (p == NULL)
4916130561Sobrien		    return FALSE;
491789857Sobrien		  p->next = *head;
491889857Sobrien		  *head = p;
491989857Sobrien		  p->sec = sec;
492089857Sobrien		  p->count = 0;
492189857Sobrien		  p->pc_count = 0;
492289857Sobrien		}
492389857Sobrien
492489857Sobrien	      p->count += 1;
4925130561Sobrien	      if (!MUST_BE_DYN_RELOC (r_type))
492689857Sobrien		p->pc_count += 1;
492789857Sobrien	    }
492889857Sobrien	  break;
492989857Sobrien
493089857Sobrien	default:
493192828Sobrien	  break;
493289857Sobrien	}
493389857Sobrien    }
493489857Sobrien
4935130561Sobrien  return TRUE;
493689857Sobrien}
493789857Sobrien
4938218822Sdim/* OFFSET in OPD_SEC specifies a function descriptor.  Return the address
4939218822Sdim   of the code entry point, and its section.  */
4940218822Sdim
4941218822Sdimstatic bfd_vma
4942218822Sdimopd_entry_value (asection *opd_sec,
4943218822Sdim		 bfd_vma offset,
4944218822Sdim		 asection **code_sec,
4945218822Sdim		 bfd_vma *code_off)
4946218822Sdim{
4947218822Sdim  bfd *opd_bfd = opd_sec->owner;
4948218822Sdim  Elf_Internal_Rela *relocs;
4949218822Sdim  Elf_Internal_Rela *lo, *hi, *look;
4950218822Sdim  bfd_vma val;
4951218822Sdim
4952218822Sdim  /* No relocs implies we are linking a --just-symbols object.  */
4953218822Sdim  if (opd_sec->reloc_count == 0)
4954218822Sdim    {
4955218822Sdim      bfd_vma val;
4956218822Sdim
4957218822Sdim      if (!bfd_get_section_contents (opd_bfd, opd_sec, &val, offset, 8))
4958218822Sdim	return (bfd_vma) -1;
4959218822Sdim
4960218822Sdim      if (code_sec != NULL)
4961218822Sdim	{
4962218822Sdim	  asection *sec, *likely = NULL;
4963218822Sdim	  for (sec = opd_bfd->sections; sec != NULL; sec = sec->next)
4964218822Sdim	    if (sec->vma <= val
4965218822Sdim		&& (sec->flags & SEC_LOAD) != 0
4966218822Sdim		&& (sec->flags & SEC_ALLOC) != 0)
4967218822Sdim	      likely = sec;
4968218822Sdim	  if (likely != NULL)
4969218822Sdim	    {
4970218822Sdim	      *code_sec = likely;
4971218822Sdim	      if (code_off != NULL)
4972218822Sdim		*code_off = val - likely->vma;
4973218822Sdim	    }
4974218822Sdim	}
4975218822Sdim      return val;
4976218822Sdim    }
4977218822Sdim
4978218822Sdim  relocs = ppc64_elf_tdata (opd_bfd)->opd_relocs;
4979218822Sdim  if (relocs == NULL)
4980218822Sdim    relocs = _bfd_elf_link_read_relocs (opd_bfd, opd_sec, NULL, NULL, TRUE);
4981218822Sdim
4982218822Sdim  /* Go find the opd reloc at the sym address.  */
4983218822Sdim  lo = relocs;
4984218822Sdim  BFD_ASSERT (lo != NULL);
4985218822Sdim  hi = lo + opd_sec->reloc_count - 1; /* ignore last reloc */
4986218822Sdim  val = (bfd_vma) -1;
4987218822Sdim  while (lo < hi)
4988218822Sdim    {
4989218822Sdim      look = lo + (hi - lo) / 2;
4990218822Sdim      if (look->r_offset < offset)
4991218822Sdim	lo = look + 1;
4992218822Sdim      else if (look->r_offset > offset)
4993218822Sdim	hi = look;
4994218822Sdim      else
4995218822Sdim	{
4996218822Sdim	  Elf_Internal_Shdr *symtab_hdr = &elf_tdata (opd_bfd)->symtab_hdr;
4997218822Sdim	  if (ELF64_R_TYPE (look->r_info) == R_PPC64_ADDR64
4998218822Sdim	      && ELF64_R_TYPE ((look + 1)->r_info) == R_PPC64_TOC)
4999218822Sdim	    {
5000218822Sdim	      unsigned long symndx = ELF64_R_SYM (look->r_info);
5001218822Sdim	      asection *sec;
5002218822Sdim
5003218822Sdim	      if (symndx < symtab_hdr->sh_info)
5004218822Sdim		{
5005218822Sdim		  Elf_Internal_Sym *sym;
5006218822Sdim
5007218822Sdim		  sym = (Elf_Internal_Sym *) symtab_hdr->contents;
5008218822Sdim		  if (sym == NULL)
5009218822Sdim		    {
5010218822Sdim		      sym = bfd_elf_get_elf_syms (opd_bfd, symtab_hdr,
5011218822Sdim						  symtab_hdr->sh_info,
5012218822Sdim						  0, NULL, NULL, NULL);
5013218822Sdim		      if (sym == NULL)
5014218822Sdim			break;
5015218822Sdim		      symtab_hdr->contents = (bfd_byte *) sym;
5016218822Sdim		    }
5017218822Sdim
5018218822Sdim		  sym += symndx;
5019218822Sdim		  val = sym->st_value;
5020218822Sdim		  sec = NULL;
5021218822Sdim		  if ((sym->st_shndx != SHN_UNDEF
5022218822Sdim		       && sym->st_shndx < SHN_LORESERVE)
5023218822Sdim		      || sym->st_shndx > SHN_HIRESERVE)
5024218822Sdim		    sec = bfd_section_from_elf_index (opd_bfd, sym->st_shndx);
5025218822Sdim		  BFD_ASSERT ((sec->flags & SEC_MERGE) == 0);
5026218822Sdim		}
5027218822Sdim	      else
5028218822Sdim		{
5029218822Sdim		  struct elf_link_hash_entry **sym_hashes;
5030218822Sdim		  struct elf_link_hash_entry *rh;
5031218822Sdim
5032218822Sdim		  sym_hashes = elf_sym_hashes (opd_bfd);
5033218822Sdim		  rh = sym_hashes[symndx - symtab_hdr->sh_info];
5034218822Sdim		  while (rh->root.type == bfd_link_hash_indirect
5035218822Sdim			 || rh->root.type == bfd_link_hash_warning)
5036218822Sdim		    rh = ((struct elf_link_hash_entry *) rh->root.u.i.link);
5037218822Sdim		  BFD_ASSERT (rh->root.type == bfd_link_hash_defined
5038218822Sdim			      || rh->root.type == bfd_link_hash_defweak);
5039218822Sdim		  val = rh->root.u.def.value;
5040218822Sdim		  sec = rh->root.u.def.section;
5041218822Sdim		}
5042218822Sdim	      val += look->r_addend;
5043218822Sdim	      if (code_off != NULL)
5044218822Sdim		*code_off = val;
5045218822Sdim	      if (code_sec != NULL)
5046218822Sdim		*code_sec = sec;
5047218822Sdim	      if (sec != NULL && sec->output_section != NULL)
5048218822Sdim		val += sec->output_section->vma + sec->output_offset;
5049218822Sdim	    }
5050218822Sdim	  break;
5051218822Sdim	}
5052218822Sdim    }
5053218822Sdim
5054218822Sdim  return val;
5055218822Sdim}
5056218822Sdim
5057218822Sdim/* Mark sections containing dynamically referenced symbols.  When
5058218822Sdim   building shared libraries, we must assume that any visible symbol is
5059218822Sdim   referenced.  */
5060218822Sdim
5061218822Sdimstatic bfd_boolean
5062218822Sdimppc64_elf_gc_mark_dynamic_ref (struct elf_link_hash_entry *h, void *inf)
5063218822Sdim{
5064218822Sdim  struct bfd_link_info *info = (struct bfd_link_info *) inf;
5065218822Sdim  struct ppc_link_hash_entry *eh = (struct ppc_link_hash_entry *) h;
5066218822Sdim
5067218822Sdim  if (eh->elf.root.type == bfd_link_hash_warning)
5068218822Sdim    eh = (struct ppc_link_hash_entry *) eh->elf.root.u.i.link;
5069218822Sdim
5070218822Sdim  /* Dynamic linking info is on the func descriptor sym.  */
5071218822Sdim  if (eh->oh != NULL
5072218822Sdim      && eh->oh->is_func_descriptor
5073218822Sdim      && (eh->oh->elf.root.type == bfd_link_hash_defined
5074218822Sdim	  || eh->oh->elf.root.type == bfd_link_hash_defweak))
5075218822Sdim    eh = eh->oh;
5076218822Sdim
5077218822Sdim  if ((eh->elf.root.type == bfd_link_hash_defined
5078218822Sdim       || eh->elf.root.type == bfd_link_hash_defweak)
5079218822Sdim      && (eh->elf.ref_dynamic
5080218822Sdim	  || (!info->executable
5081218822Sdim	      && eh->elf.def_regular
5082218822Sdim	      && ELF_ST_VISIBILITY (eh->elf.other) != STV_INTERNAL
5083218822Sdim	      && ELF_ST_VISIBILITY (eh->elf.other) != STV_HIDDEN)))
5084218822Sdim    {
5085218822Sdim      asection *code_sec;
5086218822Sdim
5087218822Sdim      eh->elf.root.u.def.section->flags |= SEC_KEEP;
5088218822Sdim
5089218822Sdim      /* Function descriptor syms cause the associated
5090218822Sdim	 function code sym section to be marked.  */
5091218822Sdim      if (eh->is_func_descriptor
5092218822Sdim	  && (eh->oh->elf.root.type == bfd_link_hash_defined
5093218822Sdim	      || eh->oh->elf.root.type == bfd_link_hash_defweak))
5094218822Sdim	eh->oh->elf.root.u.def.section->flags |= SEC_KEEP;
5095218822Sdim      else if (get_opd_info (eh->elf.root.u.def.section) != NULL
5096218822Sdim	       && opd_entry_value (eh->elf.root.u.def.section,
5097218822Sdim				   eh->elf.root.u.def.value,
5098218822Sdim				   &code_sec, NULL) != (bfd_vma) -1)
5099218822Sdim	code_sec->flags |= SEC_KEEP;
5100218822Sdim    }
5101218822Sdim
5102218822Sdim  return TRUE;
5103218822Sdim}
5104218822Sdim
510589857Sobrien/* Return the section that should be marked against GC for a given
510689857Sobrien   relocation.  */
510789857Sobrien
510889857Sobrienstatic asection *
5109130561Sobrienppc64_elf_gc_mark_hook (asection *sec,
5110218822Sdim			struct bfd_link_info *info,
5111130561Sobrien			Elf_Internal_Rela *rel,
5112130561Sobrien			struct elf_link_hash_entry *h,
5113130561Sobrien			Elf_Internal_Sym *sym)
511489857Sobrien{
5115218822Sdim  asection *rsec;
5116104834Sobrien
5117218822Sdim  /* First mark all our entry sym sections.  */
5118218822Sdim  if (info->gc_sym_list != NULL)
5119218822Sdim    {
5120218822Sdim      struct ppc_link_hash_table *htab = ppc_hash_table (info);
5121218822Sdim      struct bfd_sym_chain *sym = info->gc_sym_list;
5122218822Sdim
5123218822Sdim      info->gc_sym_list = NULL;
5124218822Sdim      for (; sym != NULL; sym = sym->next)
5125218822Sdim	{
5126218822Sdim	  struct ppc_link_hash_entry *eh;
5127218822Sdim
5128218822Sdim	  eh = (struct ppc_link_hash_entry *)
5129218822Sdim	    elf_link_hash_lookup (&htab->elf, sym->name, FALSE, FALSE, FALSE);
5130218822Sdim	  if (eh == NULL)
5131218822Sdim	    continue;
5132218822Sdim	  if (eh->elf.root.type != bfd_link_hash_defined
5133218822Sdim	      && eh->elf.root.type != bfd_link_hash_defweak)
5134218822Sdim	    continue;
5135218822Sdim
5136218822Sdim	  if (eh->is_func_descriptor
5137218822Sdim	      && (eh->oh->elf.root.type == bfd_link_hash_defined
5138218822Sdim		  || eh->oh->elf.root.type == bfd_link_hash_defweak))
5139218822Sdim	    rsec = eh->oh->elf.root.u.def.section;
5140218822Sdim	  else if (get_opd_info (eh->elf.root.u.def.section) != NULL
5141218822Sdim		   && opd_entry_value (eh->elf.root.u.def.section,
5142218822Sdim				       eh->elf.root.u.def.value,
5143218822Sdim				       &rsec, NULL) != (bfd_vma) -1)
5144218822Sdim	    ;
5145218822Sdim	  else
5146218822Sdim	    continue;
5147218822Sdim
5148218822Sdim	  if (!rsec->gc_mark)
5149218822Sdim	    _bfd_elf_gc_mark (info, rsec, ppc64_elf_gc_mark_hook);
5150218822Sdim
5151218822Sdim	  rsec = eh->elf.root.u.def.section;
5152218822Sdim	  if (!rsec->gc_mark)
5153218822Sdim	    _bfd_elf_gc_mark (info, rsec, ppc64_elf_gc_mark_hook);
5154218822Sdim	}
5155218822Sdim    }
5156218822Sdim
5157218822Sdim  /* Syms return NULL if we're marking .opd, so we avoid marking all
5158218822Sdim     function sections, as all functions are referenced in .opd.  */
5159218822Sdim  rsec = NULL;
5160218822Sdim  if (get_opd_info (sec) != NULL)
5161218822Sdim    return rsec;
5162218822Sdim
516389857Sobrien  if (h != NULL)
516489857Sobrien    {
5165130561Sobrien      enum elf_ppc64_reloc_type r_type;
5166218822Sdim      struct ppc_link_hash_entry *eh;
516789857Sobrien
5168130561Sobrien      r_type = ELF64_R_TYPE (rel->r_info);
516989857Sobrien      switch (r_type)
517089857Sobrien	{
517189857Sobrien	case R_PPC64_GNU_VTINHERIT:
517289857Sobrien	case R_PPC64_GNU_VTENTRY:
517389857Sobrien	  break;
517489857Sobrien
517589857Sobrien	default:
517689857Sobrien	  switch (h->root.type)
517789857Sobrien	    {
517889857Sobrien	    case bfd_link_hash_defined:
517989857Sobrien	    case bfd_link_hash_defweak:
5180218822Sdim	      eh = (struct ppc_link_hash_entry *) h;
5181218822Sdim	      if (eh->oh != NULL
5182218822Sdim		  && eh->oh->is_func_descriptor
5183218822Sdim		  && (eh->oh->elf.root.type == bfd_link_hash_defined
5184218822Sdim		      || eh->oh->elf.root.type == bfd_link_hash_defweak))
5185218822Sdim		eh = eh->oh;
518689857Sobrien
5187104834Sobrien	      /* Function descriptor syms cause the associated
5188104834Sobrien		 function code sym section to be marked.  */
5189218822Sdim	      if (eh->is_func_descriptor
5190218822Sdim		  && (eh->oh->elf.root.type == bfd_link_hash_defined
5191218822Sdim		      || eh->oh->elf.root.type == bfd_link_hash_defweak))
5192218822Sdim		{
5193218822Sdim		  /* They also mark their opd section.  */
5194218822Sdim		  if (!eh->elf.root.u.def.section->gc_mark)
5195218822Sdim		    _bfd_elf_gc_mark (info, eh->elf.root.u.def.section,
5196218822Sdim				      ppc64_elf_gc_mark_hook);
5197104834Sobrien
5198218822Sdim		  rsec = eh->oh->elf.root.u.def.section;
5199218822Sdim		}
5200218822Sdim	      else if (get_opd_info (eh->elf.root.u.def.section) != NULL
5201218822Sdim		       && opd_entry_value (eh->elf.root.u.def.section,
5202218822Sdim					   eh->elf.root.u.def.value,
5203218822Sdim					   &rsec, NULL) != (bfd_vma) -1)
5204218822Sdim		{
5205218822Sdim		  if (!eh->elf.root.u.def.section->gc_mark)
5206218822Sdim		    _bfd_elf_gc_mark (info, eh->elf.root.u.def.section,
5207218822Sdim				      ppc64_elf_gc_mark_hook);
5208218822Sdim		}
5209218822Sdim	      else
5210104834Sobrien		rsec = h->root.u.def.section;
5211104834Sobrien	      break;
5212104834Sobrien
521389857Sobrien	    case bfd_link_hash_common:
5214104834Sobrien	      rsec = h->root.u.c.p->section;
5215104834Sobrien	      break;
521689857Sobrien
521789857Sobrien	    default:
521889857Sobrien	      break;
521989857Sobrien	    }
522089857Sobrien	}
522189857Sobrien    }
522289857Sobrien  else
522389857Sobrien    {
5224104834Sobrien      asection **opd_sym_section;
5225104834Sobrien
5226104834Sobrien      rsec = bfd_section_from_elf_index (sec->owner, sym->st_shndx);
5227218822Sdim      opd_sym_section = get_opd_info (rsec);
5228104834Sobrien      if (opd_sym_section != NULL)
5229218822Sdim	{
5230218822Sdim	  if (!rsec->gc_mark)
5231218822Sdim	    _bfd_elf_gc_mark (info, rsec, ppc64_elf_gc_mark_hook);
5232218822Sdim
5233218822Sdim	  rsec = opd_sym_section[(sym->st_value + rel->r_addend) / 8];
5234218822Sdim	}
523589857Sobrien    }
523689857Sobrien
5237104834Sobrien  return rsec;
523889857Sobrien}
523989857Sobrien
524089857Sobrien/* Update the .got, .plt. and dynamic reloc reference counts for the
524189857Sobrien   section being removed.  */
524289857Sobrien
5243130561Sobrienstatic bfd_boolean
5244130561Sobrienppc64_elf_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
5245130561Sobrien			 asection *sec, const Elf_Internal_Rela *relocs)
524689857Sobrien{
5247130561Sobrien  struct ppc_link_hash_table *htab;
524889857Sobrien  Elf_Internal_Shdr *symtab_hdr;
524989857Sobrien  struct elf_link_hash_entry **sym_hashes;
5250130561Sobrien  struct got_entry **local_got_ents;
525189857Sobrien  const Elf_Internal_Rela *rel, *relend;
525289857Sobrien
5253130561Sobrien  if ((sec->flags & SEC_ALLOC) == 0)
5254130561Sobrien    return TRUE;
5255130561Sobrien
525689857Sobrien  elf_section_data (sec)->local_dynrel = NULL;
525789857Sobrien
5258130561Sobrien  htab = ppc_hash_table (info);
525989857Sobrien  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
526089857Sobrien  sym_hashes = elf_sym_hashes (abfd);
5261130561Sobrien  local_got_ents = elf_local_got_ents (abfd);
526289857Sobrien
526389857Sobrien  relend = relocs + sec->reloc_count;
526489857Sobrien  for (rel = relocs; rel < relend; rel++)
526589857Sobrien    {
526689857Sobrien      unsigned long r_symndx;
5267130561Sobrien      enum elf_ppc64_reloc_type r_type;
5268130561Sobrien      struct elf_link_hash_entry *h = NULL;
5269130561Sobrien      char tls_type = 0;
527089857Sobrien
527189857Sobrien      r_symndx = ELF64_R_SYM (rel->r_info);
5272130561Sobrien      r_type = ELF64_R_TYPE (rel->r_info);
5273130561Sobrien      if (r_symndx >= symtab_hdr->sh_info)
5274130561Sobrien	{
5275130561Sobrien	  struct ppc_link_hash_entry *eh;
5276130561Sobrien	  struct ppc_dyn_relocs **pp;
5277130561Sobrien	  struct ppc_dyn_relocs *p;
5278130561Sobrien
5279130561Sobrien	  h = sym_hashes[r_symndx - symtab_hdr->sh_info];
5280218822Sdim	  while (h->root.type == bfd_link_hash_indirect
5281218822Sdim		 || h->root.type == bfd_link_hash_warning)
5282218822Sdim	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
5283130561Sobrien	  eh = (struct ppc_link_hash_entry *) h;
5284130561Sobrien
5285130561Sobrien	  for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next)
5286130561Sobrien	    if (p->sec == sec)
5287130561Sobrien	      {
5288130561Sobrien		/* Everything must go for SEC.  */
5289130561Sobrien		*pp = p->next;
5290130561Sobrien		break;
5291130561Sobrien	      }
5292130561Sobrien	}
5293130561Sobrien
529489857Sobrien      switch (r_type)
529589857Sobrien	{
5296130561Sobrien	case R_PPC64_GOT_TLSLD16:
5297130561Sobrien	case R_PPC64_GOT_TLSLD16_LO:
5298130561Sobrien	case R_PPC64_GOT_TLSLD16_HI:
5299130561Sobrien	case R_PPC64_GOT_TLSLD16_HA:
5300130561Sobrien	  ppc64_tlsld_got (abfd)->refcount -= 1;
5301130561Sobrien	  tls_type = TLS_TLS | TLS_LD;
5302130561Sobrien	  goto dogot;
5303130561Sobrien
5304130561Sobrien	case R_PPC64_GOT_TLSGD16:
5305130561Sobrien	case R_PPC64_GOT_TLSGD16_LO:
5306130561Sobrien	case R_PPC64_GOT_TLSGD16_HI:
5307130561Sobrien	case R_PPC64_GOT_TLSGD16_HA:
5308130561Sobrien	  tls_type = TLS_TLS | TLS_GD;
5309130561Sobrien	  goto dogot;
5310130561Sobrien
5311130561Sobrien	case R_PPC64_GOT_TPREL16_DS:
5312130561Sobrien	case R_PPC64_GOT_TPREL16_LO_DS:
5313130561Sobrien	case R_PPC64_GOT_TPREL16_HI:
5314130561Sobrien	case R_PPC64_GOT_TPREL16_HA:
5315130561Sobrien	  tls_type = TLS_TLS | TLS_TPREL;
5316130561Sobrien	  goto dogot;
5317130561Sobrien
5318130561Sobrien	case R_PPC64_GOT_DTPREL16_DS:
5319130561Sobrien	case R_PPC64_GOT_DTPREL16_LO_DS:
5320130561Sobrien	case R_PPC64_GOT_DTPREL16_HI:
5321130561Sobrien	case R_PPC64_GOT_DTPREL16_HA:
5322130561Sobrien	  tls_type = TLS_TLS | TLS_DTPREL;
5323130561Sobrien	  goto dogot;
5324130561Sobrien
532589857Sobrien	case R_PPC64_GOT16:
532689857Sobrien	case R_PPC64_GOT16_DS:
532789857Sobrien	case R_PPC64_GOT16_HA:
532889857Sobrien	case R_PPC64_GOT16_HI:
532989857Sobrien	case R_PPC64_GOT16_LO:
533089857Sobrien	case R_PPC64_GOT16_LO_DS:
5331130561Sobrien	dogot:
5332130561Sobrien	  {
5333130561Sobrien	    struct got_entry *ent;
5334130561Sobrien
5335130561Sobrien	    if (h != NULL)
5336130561Sobrien	      ent = h->got.glist;
5337130561Sobrien	    else
5338130561Sobrien	      ent = local_got_ents[r_symndx];
5339130561Sobrien
5340130561Sobrien	    for (; ent != NULL; ent = ent->next)
5341130561Sobrien	      if (ent->addend == rel->r_addend
5342130561Sobrien		  && ent->owner == abfd
5343130561Sobrien		  && ent->tls_type == tls_type)
5344130561Sobrien		break;
5345130561Sobrien	    if (ent == NULL)
5346130561Sobrien	      abort ();
5347130561Sobrien	    if (ent->got.refcount > 0)
5348130561Sobrien	      ent->got.refcount -= 1;
5349130561Sobrien	  }
535089857Sobrien	  break;
535189857Sobrien
535289857Sobrien	case R_PPC64_PLT16_HA:
535389857Sobrien	case R_PPC64_PLT16_HI:
535489857Sobrien	case R_PPC64_PLT16_LO:
535589857Sobrien	case R_PPC64_PLT32:
535689857Sobrien	case R_PPC64_PLT64:
5357104834Sobrien	case R_PPC64_REL14:
5358104834Sobrien	case R_PPC64_REL14_BRNTAKEN:
5359104834Sobrien	case R_PPC64_REL14_BRTAKEN:
536089857Sobrien	case R_PPC64_REL24:
5361130561Sobrien	  if (h != NULL)
536289857Sobrien	    {
5363130561Sobrien	      struct plt_entry *ent;
536489857Sobrien
5365130561Sobrien	      for (ent = h->plt.plist; ent != NULL; ent = ent->next)
5366130561Sobrien		if (ent->addend == rel->r_addend)
5367130561Sobrien		  break;
5368218822Sdim	      if (ent != NULL && ent->plt.refcount > 0)
5369130561Sobrien		ent->plt.refcount -= 1;
537089857Sobrien	    }
537189857Sobrien	  break;
537289857Sobrien
537389857Sobrien	default:
537489857Sobrien	  break;
537589857Sobrien	}
537689857Sobrien    }
5377130561Sobrien  return TRUE;
537889857Sobrien}
537989857Sobrien
5380218822Sdim/* The maximum size of .sfpr.  */
5381218822Sdim#define SFPR_MAX (218*4)
5382218822Sdim
5383218822Sdimstruct sfpr_def_parms
5384218822Sdim{
5385218822Sdim  const char name[12];
5386218822Sdim  unsigned char lo, hi;
5387218822Sdim  bfd_byte * (*write_ent) (bfd *, bfd_byte *, int);
5388218822Sdim  bfd_byte * (*write_tail) (bfd *, bfd_byte *, int);
5389218822Sdim};
5390218822Sdim
5391218822Sdim/* Auto-generate _save*, _rest* functions in .sfpr.  */
5392218822Sdim
5393218822Sdimstatic unsigned int
5394218822Sdimsfpr_define (struct bfd_link_info *info, const struct sfpr_def_parms *parm)
5395218822Sdim{
5396218822Sdim  struct ppc_link_hash_table *htab = ppc_hash_table (info);
5397218822Sdim  unsigned int i;
5398218822Sdim  size_t len = strlen (parm->name);
5399218822Sdim  bfd_boolean writing = FALSE;
5400218822Sdim  char sym[16];
5401218822Sdim
5402218822Sdim  memcpy (sym, parm->name, len);
5403218822Sdim  sym[len + 2] = 0;
5404218822Sdim
5405218822Sdim  for (i = parm->lo; i <= parm->hi; i++)
5406218822Sdim    {
5407218822Sdim      struct elf_link_hash_entry *h;
5408218822Sdim
5409218822Sdim      sym[len + 0] = i / 10 + '0';
5410218822Sdim      sym[len + 1] = i % 10 + '0';
5411218822Sdim      h = elf_link_hash_lookup (&htab->elf, sym, FALSE, FALSE, TRUE);
5412218822Sdim      if (h != NULL
5413218822Sdim	  && !h->def_regular)
5414218822Sdim	{
5415218822Sdim	  h->root.type = bfd_link_hash_defined;
5416218822Sdim	  h->root.u.def.section = htab->sfpr;
5417218822Sdim	  h->root.u.def.value = htab->sfpr->size;
5418218822Sdim	  h->type = STT_FUNC;
5419218822Sdim	  h->def_regular = 1;
5420218822Sdim	  _bfd_elf_link_hash_hide_symbol (info, h, TRUE);
5421218822Sdim	  writing = TRUE;
5422218822Sdim	  if (htab->sfpr->contents == NULL)
5423218822Sdim	    {
5424218822Sdim	      htab->sfpr->contents = bfd_alloc (htab->elf.dynobj, SFPR_MAX);
5425218822Sdim	      if (htab->sfpr->contents == NULL)
5426218822Sdim		return FALSE;
5427218822Sdim	    }
5428218822Sdim	}
5429218822Sdim      if (writing)
5430218822Sdim	{
5431218822Sdim	  bfd_byte *p = htab->sfpr->contents + htab->sfpr->size;
5432218822Sdim	  if (i != parm->hi)
5433218822Sdim	    p = (*parm->write_ent) (htab->elf.dynobj, p, i);
5434218822Sdim	  else
5435218822Sdim	    p = (*parm->write_tail) (htab->elf.dynobj, p, i);
5436218822Sdim	  htab->sfpr->size = p - htab->sfpr->contents;
5437218822Sdim	}
5438218822Sdim    }
5439218822Sdim
5440218822Sdim  return TRUE;
5441218822Sdim}
5442218822Sdim
5443218822Sdimstatic bfd_byte *
5444218822Sdimsavegpr0 (bfd *abfd, bfd_byte *p, int r)
5445218822Sdim{
5446218822Sdim  bfd_put_32 (abfd, STD_R0_0R1 + (r << 21) + (1 << 16) - (32 - r) * 8, p);
5447218822Sdim  return p + 4;
5448218822Sdim}
5449218822Sdim
5450218822Sdimstatic bfd_byte *
5451218822Sdimsavegpr0_tail (bfd *abfd, bfd_byte *p, int r)
5452218822Sdim{
5453218822Sdim  p = savegpr0 (abfd, p, r);
5454218822Sdim  bfd_put_32 (abfd, STD_R0_0R1 + 16, p);
5455218822Sdim  p = p + 4;
5456218822Sdim  bfd_put_32 (abfd, BLR, p);
5457218822Sdim  return p + 4;
5458218822Sdim}
5459218822Sdim
5460218822Sdimstatic bfd_byte *
5461218822Sdimrestgpr0 (bfd *abfd, bfd_byte *p, int r)
5462218822Sdim{
5463218822Sdim  bfd_put_32 (abfd, LD_R0_0R1 + (r << 21) + (1 << 16) - (32 - r) * 8, p);
5464218822Sdim  return p + 4;
5465218822Sdim}
5466218822Sdim
5467218822Sdimstatic bfd_byte *
5468218822Sdimrestgpr0_tail (bfd *abfd, bfd_byte *p, int r)
5469218822Sdim{
5470218822Sdim  bfd_put_32 (abfd, LD_R0_0R1 + 16, p);
5471218822Sdim  p = p + 4;
5472218822Sdim  p = restgpr0 (abfd, p, r);
5473218822Sdim  bfd_put_32 (abfd, MTLR_R0, p);
5474218822Sdim  p = p + 4;
5475218822Sdim  if (r == 29)
5476218822Sdim    {
5477218822Sdim      p = restgpr0 (abfd, p, 30);
5478218822Sdim      p = restgpr0 (abfd, p, 31);
5479218822Sdim    }
5480218822Sdim  bfd_put_32 (abfd, BLR, p);
5481218822Sdim  return p + 4;
5482218822Sdim}
5483218822Sdim
5484218822Sdimstatic bfd_byte *
5485218822Sdimsavegpr1 (bfd *abfd, bfd_byte *p, int r)
5486218822Sdim{
5487218822Sdim  bfd_put_32 (abfd, STD_R0_0R12 + (r << 21) + (1 << 16) - (32 - r) * 8, p);
5488218822Sdim  return p + 4;
5489218822Sdim}
5490218822Sdim
5491218822Sdimstatic bfd_byte *
5492218822Sdimsavegpr1_tail (bfd *abfd, bfd_byte *p, int r)
5493218822Sdim{
5494218822Sdim  p = savegpr1 (abfd, p, r);
5495218822Sdim  bfd_put_32 (abfd, BLR, p);
5496218822Sdim  return p + 4;
5497218822Sdim}
5498218822Sdim
5499218822Sdimstatic bfd_byte *
5500218822Sdimrestgpr1 (bfd *abfd, bfd_byte *p, int r)
5501218822Sdim{
5502218822Sdim  bfd_put_32 (abfd, LD_R0_0R12 + (r << 21) + (1 << 16) - (32 - r) * 8, p);
5503218822Sdim  return p + 4;
5504218822Sdim}
5505218822Sdim
5506218822Sdimstatic bfd_byte *
5507218822Sdimrestgpr1_tail (bfd *abfd, bfd_byte *p, int r)
5508218822Sdim{
5509218822Sdim  p = restgpr1 (abfd, p, r);
5510218822Sdim  bfd_put_32 (abfd, BLR, p);
5511218822Sdim  return p + 4;
5512218822Sdim}
5513218822Sdim
5514218822Sdimstatic bfd_byte *
5515218822Sdimsavefpr (bfd *abfd, bfd_byte *p, int r)
5516218822Sdim{
5517218822Sdim  bfd_put_32 (abfd, STFD_FR0_0R1 + (r << 21) + (1 << 16) - (32 - r) * 8, p);
5518218822Sdim  return p + 4;
5519218822Sdim}
5520218822Sdim
5521218822Sdimstatic bfd_byte *
5522218822Sdimsavefpr0_tail (bfd *abfd, bfd_byte *p, int r)
5523218822Sdim{
5524218822Sdim  p = savefpr (abfd, p, r);
5525218822Sdim  bfd_put_32 (abfd, STD_R0_0R1 + 16, p);
5526218822Sdim  p = p + 4;
5527218822Sdim  bfd_put_32 (abfd, BLR, p);
5528218822Sdim  return p + 4;
5529218822Sdim}
5530218822Sdim
5531218822Sdimstatic bfd_byte *
5532218822Sdimrestfpr (bfd *abfd, bfd_byte *p, int r)
5533218822Sdim{
5534218822Sdim  bfd_put_32 (abfd, LFD_FR0_0R1 + (r << 21) + (1 << 16) - (32 - r) * 8, p);
5535218822Sdim  return p + 4;
5536218822Sdim}
5537218822Sdim
5538218822Sdimstatic bfd_byte *
5539218822Sdimrestfpr0_tail (bfd *abfd, bfd_byte *p, int r)
5540218822Sdim{
5541218822Sdim  bfd_put_32 (abfd, LD_R0_0R1 + 16, p);
5542218822Sdim  p = p + 4;
5543218822Sdim  p = restfpr (abfd, p, r);
5544218822Sdim  bfd_put_32 (abfd, MTLR_R0, p);
5545218822Sdim  p = p + 4;
5546218822Sdim  if (r == 29)
5547218822Sdim    {
5548218822Sdim      p = restfpr (abfd, p, 30);
5549218822Sdim      p = restfpr (abfd, p, 31);
5550218822Sdim    }
5551218822Sdim  bfd_put_32 (abfd, BLR, p);
5552218822Sdim  return p + 4;
5553218822Sdim}
5554218822Sdim
5555218822Sdimstatic bfd_byte *
5556218822Sdimsavefpr1_tail (bfd *abfd, bfd_byte *p, int r)
5557218822Sdim{
5558218822Sdim  p = savefpr (abfd, p, r);
5559218822Sdim  bfd_put_32 (abfd, BLR, p);
5560218822Sdim  return p + 4;
5561218822Sdim}
5562218822Sdim
5563218822Sdimstatic bfd_byte *
5564218822Sdimrestfpr1_tail (bfd *abfd, bfd_byte *p, int r)
5565218822Sdim{
5566218822Sdim  p = restfpr (abfd, p, r);
5567218822Sdim  bfd_put_32 (abfd, BLR, p);
5568218822Sdim  return p + 4;
5569218822Sdim}
5570218822Sdim
5571218822Sdimstatic bfd_byte *
5572218822Sdimsavevr (bfd *abfd, bfd_byte *p, int r)
5573218822Sdim{
5574218822Sdim  bfd_put_32 (abfd, LI_R12_0 + (1 << 16) - (32 - r) * 16, p);
5575218822Sdim  p = p + 4;
5576218822Sdim  bfd_put_32 (abfd, STVX_VR0_R12_R0 + (r << 21), p);
5577218822Sdim  return p + 4;
5578218822Sdim}
5579218822Sdim
5580218822Sdimstatic bfd_byte *
5581218822Sdimsavevr_tail (bfd *abfd, bfd_byte *p, int r)
5582218822Sdim{
5583218822Sdim  p = savevr (abfd, p, r);
5584218822Sdim  bfd_put_32 (abfd, BLR, p);
5585218822Sdim  return p + 4;
5586218822Sdim}
5587218822Sdim
5588218822Sdimstatic bfd_byte *
5589218822Sdimrestvr (bfd *abfd, bfd_byte *p, int r)
5590218822Sdim{
5591218822Sdim  bfd_put_32 (abfd, LI_R12_0 + (1 << 16) - (32 - r) * 16, p);
5592218822Sdim  p = p + 4;
5593218822Sdim  bfd_put_32 (abfd, LVX_VR0_R12_R0 + (r << 21), p);
5594218822Sdim  return p + 4;
5595218822Sdim}
5596218822Sdim
5597218822Sdimstatic bfd_byte *
5598218822Sdimrestvr_tail (bfd *abfd, bfd_byte *p, int r)
5599218822Sdim{
5600218822Sdim  p = restvr (abfd, p, r);
5601218822Sdim  bfd_put_32 (abfd, BLR, p);
5602218822Sdim  return p + 4;
5603218822Sdim}
5604218822Sdim
560589857Sobrien/* Called via elf_link_hash_traverse to transfer dynamic linking
560689857Sobrien   information on function code symbol entries to their corresponding
560789857Sobrien   function descriptor symbol entries.  */
5608218822Sdim
5609130561Sobrienstatic bfd_boolean
5610130561Sobrienfunc_desc_adjust (struct elf_link_hash_entry *h, void *inf)
561189857Sobrien{
561289857Sobrien  struct bfd_link_info *info;
561389857Sobrien  struct ppc_link_hash_table *htab;
5614130561Sobrien  struct plt_entry *ent;
5615130561Sobrien  struct ppc_link_hash_entry *fh;
5616130561Sobrien  struct ppc_link_hash_entry *fdh;
5617130561Sobrien  bfd_boolean force_local;
561889857Sobrien
5619130561Sobrien  fh = (struct ppc_link_hash_entry *) h;
5620130561Sobrien  if (fh->elf.root.type == bfd_link_hash_indirect)
5621130561Sobrien    return TRUE;
562289857Sobrien
5623130561Sobrien  if (fh->elf.root.type == bfd_link_hash_warning)
5624130561Sobrien    fh = (struct ppc_link_hash_entry *) fh->elf.root.u.i.link;
562594536Sobrien
5626130561Sobrien  info = inf;
562789857Sobrien  htab = ppc_hash_table (info);
562889857Sobrien
5629218822Sdim  /* Resolve undefined references to dot-symbols as the value
5630218822Sdim     in the function descriptor, if we have one in a regular object.
5631218822Sdim     This is to satisfy cases like ".quad .foo".  Calls to functions
5632218822Sdim     in dynamic objects are handled elsewhere.  */
5633218822Sdim  if (fh->elf.root.type == bfd_link_hash_undefweak
5634218822Sdim      && fh->was_undefined
5635218822Sdim      && (fh->oh->elf.root.type == bfd_link_hash_defined
5636218822Sdim	  || fh->oh->elf.root.type == bfd_link_hash_defweak)
5637218822Sdim      && get_opd_info (fh->oh->elf.root.u.def.section) != NULL
5638218822Sdim      && opd_entry_value (fh->oh->elf.root.u.def.section,
5639218822Sdim			  fh->oh->elf.root.u.def.value,
5640218822Sdim			  &fh->elf.root.u.def.section,
5641218822Sdim			  &fh->elf.root.u.def.value) != (bfd_vma) -1)
5642218822Sdim    {
5643218822Sdim      fh->elf.root.type = fh->oh->elf.root.type;
5644218822Sdim      fh->elf.forced_local = 1;
5645218822Sdim    }
5646218822Sdim
564789857Sobrien  /* If this is a function code symbol, transfer dynamic linking
564889857Sobrien     information to the function descriptor symbol.  */
5649130561Sobrien  if (!fh->is_func)
5650130561Sobrien    return TRUE;
565189857Sobrien
5652130561Sobrien  for (ent = fh->elf.plt.plist; ent != NULL; ent = ent->next)
5653130561Sobrien    if (ent->plt.refcount > 0)
5654130561Sobrien      break;
5655130561Sobrien  if (ent == NULL
5656130561Sobrien      || fh->elf.root.root.string[0] != '.'
5657130561Sobrien      || fh->elf.root.root.string[1] == '\0')
5658130561Sobrien    return TRUE;
565989857Sobrien
5660130561Sobrien  /* Find the corresponding function descriptor symbol.  Create it
5661130561Sobrien     as undefined if necessary.  */
566289857Sobrien
5663130561Sobrien  fdh = get_fdh (fh, htab);
5664130561Sobrien  if (fdh != NULL)
5665130561Sobrien    while (fdh->elf.root.type == bfd_link_hash_indirect
5666130561Sobrien	   || fdh->elf.root.type == bfd_link_hash_warning)
5667130561Sobrien      fdh = (struct ppc_link_hash_entry *) fdh->elf.root.u.i.link;
566889857Sobrien
5669130561Sobrien  if (fdh == NULL
5670130561Sobrien      && info->shared
5671130561Sobrien      && (fh->elf.root.type == bfd_link_hash_undefined
5672130561Sobrien	  || fh->elf.root.type == bfd_link_hash_undefweak))
5673130561Sobrien    {
5674218822Sdim      fdh = make_fdh (info, fh);
5675218822Sdim      if (fdh == NULL)
5676218822Sdim	return FALSE;
5677218822Sdim    }
567889857Sobrien
5679218822Sdim  /* Fake function descriptors are made undefweak.  If the function
5680218822Sdim     code symbol is strong undefined, make the fake sym the same.
5681218822Sdim     If the function code symbol is defined, then force the fake
5682218822Sdim     descriptor local;  We can't support overriding of symbols in a
5683218822Sdim     shared library on a fake descriptor.  */
568489857Sobrien
5685218822Sdim  if (fdh != NULL
5686218822Sdim      && fdh->fake
5687218822Sdim      && fdh->elf.root.type == bfd_link_hash_undefweak)
5688218822Sdim    {
5689218822Sdim      if (fh->elf.root.type == bfd_link_hash_undefined)
5690130561Sobrien	{
5691218822Sdim	  fdh->elf.root.type = bfd_link_hash_undefined;
5692218822Sdim	  bfd_link_add_undef (&htab->elf.root, &fdh->elf.root);
569389857Sobrien	}
5694218822Sdim      else if (fh->elf.root.type == bfd_link_hash_defined
5695218822Sdim	       || fh->elf.root.type == bfd_link_hash_defweak)
5696218822Sdim	{
5697218822Sdim	  _bfd_elf_link_hash_hide_symbol (info, &fdh->elf, TRUE);
5698218822Sdim	}
5699130561Sobrien    }
570089857Sobrien
5701130561Sobrien  if (fdh != NULL
5702218822Sdim      && !fdh->elf.forced_local
5703130561Sobrien      && (info->shared
5704218822Sdim	  || fdh->elf.def_dynamic
5705218822Sdim	  || fdh->elf.ref_dynamic
5706130561Sobrien	  || (fdh->elf.root.type == bfd_link_hash_undefweak
5707130561Sobrien	      && ELF_ST_VISIBILITY (fdh->elf.other) == STV_DEFAULT)))
5708130561Sobrien    {
5709130561Sobrien      if (fdh->elf.dynindx == -1)
5710130561Sobrien	if (! bfd_elf_link_record_dynamic_symbol (info, &fdh->elf))
5711130561Sobrien	  return FALSE;
5712218822Sdim      fdh->elf.ref_regular |= fh->elf.ref_regular;
5713218822Sdim      fdh->elf.ref_dynamic |= fh->elf.ref_dynamic;
5714218822Sdim      fdh->elf.ref_regular_nonweak |= fh->elf.ref_regular_nonweak;
5715218822Sdim      fdh->elf.non_got_ref |= fh->elf.non_got_ref;
5716130561Sobrien      if (ELF_ST_VISIBILITY (fh->elf.other) == STV_DEFAULT)
571789857Sobrien	{
5718218822Sdim	  move_plt_plist (fh, fdh);
5719218822Sdim	  fdh->elf.needs_plt = 1;
572089857Sobrien	}
5721130561Sobrien      fdh->is_func_descriptor = 1;
5722218822Sdim      fdh->oh = fh;
5723218822Sdim      fh->oh = fdh;
572489857Sobrien    }
572589857Sobrien
5726130561Sobrien  /* Now that the info is on the function descriptor, clear the
5727130561Sobrien     function code sym info.  Any function code syms for which we
5728130561Sobrien     don't have a definition in a regular file, we force local.
5729130561Sobrien     This prevents a shared library from exporting syms that have
5730130561Sobrien     been imported from another library.  Function code syms that
5731130561Sobrien     are really in the library we must leave global to prevent the
5732130561Sobrien     linker dragging in a definition from a static library.  */
5733218822Sdim  force_local = (!fh->elf.def_regular
5734218822Sdim		 || fdh == NULL
5735218822Sdim		 || !fdh->elf.def_regular
5736218822Sdim		 || fdh->elf.forced_local);
5737130561Sobrien  _bfd_elf_link_hash_hide_symbol (info, &fh->elf, force_local);
5738130561Sobrien
5739130561Sobrien  return TRUE;
574089857Sobrien}
574189857Sobrien
574289857Sobrien/* Called near the start of bfd_elf_size_dynamic_sections.  We use
574392828Sobrien   this hook to a) provide some gcc support functions, and b) transfer
574492828Sobrien   dynamic linking information gathered so far on function code symbol
574592828Sobrien   entries, to their corresponding function descriptor symbol entries.  */
5746218822Sdim
5747130561Sobrienstatic bfd_boolean
5748130561Sobrienppc64_elf_func_desc_adjust (bfd *obfd ATTRIBUTE_UNUSED,
5749130561Sobrien			    struct bfd_link_info *info)
575089857Sobrien{
575189857Sobrien  struct ppc_link_hash_table *htab;
575292828Sobrien  unsigned int i;
5753218822Sdim  const struct sfpr_def_parms funcs[] =
5754218822Sdim    {
5755218822Sdim      { "_savegpr0_", 14, 31, savegpr0, savegpr0_tail },
5756218822Sdim      { "_restgpr0_", 14, 29, restgpr0, restgpr0_tail },
5757218822Sdim      { "_restgpr0_", 30, 31, restgpr0, restgpr0_tail },
5758218822Sdim      { "_savegpr1_", 14, 31, savegpr1, savegpr1_tail },
5759218822Sdim      { "_restgpr1_", 14, 31, restgpr1, restgpr1_tail },
5760218822Sdim      { "_savefpr_", 14, 31, savefpr, savefpr0_tail },
5761218822Sdim      { "_restfpr_", 14, 29, restfpr, restfpr0_tail },
5762218822Sdim      { "_restfpr_", 30, 31, restfpr, restfpr0_tail },
5763218822Sdim      { "._savef", 14, 31, savefpr, savefpr1_tail },
5764218822Sdim      { "._restf", 14, 31, restfpr, restfpr1_tail },
5765218822Sdim      { "_savevr_", 20, 31, savevr, savevr_tail },
5766218822Sdim      { "_restvr_", 20, 31, restvr, restvr_tail }
5767218822Sdim    };
576889857Sobrien
576989857Sobrien  htab = ppc_hash_table (info);
577092828Sobrien  if (htab->sfpr == NULL)
577192828Sobrien    /* We don't have any relocs.  */
5772130561Sobrien    return TRUE;
577392828Sobrien
5774218822Sdim  /* Provide any missing _save* and _rest* functions.  */
5775218822Sdim  htab->sfpr->size = 0;
5776218822Sdim  for (i = 0; i < sizeof (funcs) / sizeof (funcs[0]); i++)
5777218822Sdim    if (!sfpr_define (info, &funcs[i]))
5778218822Sdim      return FALSE;
577992828Sobrien
5780130561Sobrien  elf_link_hash_traverse (&htab->elf, func_desc_adjust, info);
578199461Sobrien
5782218822Sdim  if (htab->sfpr->size == 0)
5783218822Sdim    htab->sfpr->flags |= SEC_EXCLUDE;
578492828Sobrien
5785130561Sobrien  return TRUE;
578689857Sobrien}
578789857Sobrien
578889857Sobrien/* Adjust a symbol defined by a dynamic object and referenced by a
578989857Sobrien   regular object.  The current definition is in some section of the
579089857Sobrien   dynamic object, but we're not including those sections.  We have to
579189857Sobrien   change the definition to something the rest of the link can
579289857Sobrien   understand.  */
579389857Sobrien
5794130561Sobrienstatic bfd_boolean
5795130561Sobrienppc64_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
5796130561Sobrien				 struct elf_link_hash_entry *h)
579789857Sobrien{
579889857Sobrien  struct ppc_link_hash_table *htab;
579989857Sobrien  asection *s;
580089857Sobrien
580189857Sobrien  htab = ppc_hash_table (info);
580289857Sobrien
580389857Sobrien  /* Deal with function syms.  */
580489857Sobrien  if (h->type == STT_FUNC
5805218822Sdim      || h->needs_plt)
580689857Sobrien    {
580789857Sobrien      /* Clear procedure linkage table information for any symbol that
580889857Sobrien	 won't need a .plt entry.  */
5809130561Sobrien      struct plt_entry *ent;
5810130561Sobrien      for (ent = h->plt.plist; ent != NULL; ent = ent->next)
5811130561Sobrien	if (ent->plt.refcount > 0)
5812130561Sobrien	  break;
5813218822Sdim      if (ent == NULL
5814130561Sobrien	  || SYMBOL_CALLS_LOCAL (info, h)
5815130561Sobrien	  || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
5816130561Sobrien	      && h->root.type == bfd_link_hash_undefweak))
581789857Sobrien	{
5818130561Sobrien	  h->plt.plist = NULL;
5819218822Sdim	  h->needs_plt = 0;
582089857Sobrien	}
582189857Sobrien    }
582289857Sobrien  else
5823130561Sobrien    h->plt.plist = NULL;
582489857Sobrien
582589857Sobrien  /* If this is a weak symbol, and there is a real definition, the
582689857Sobrien     processor independent code will have arranged for us to see the
582789857Sobrien     real definition first, and we can just use the same value.  */
5828218822Sdim  if (h->u.weakdef != NULL)
582989857Sobrien    {
5830218822Sdim      BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined
5831218822Sdim		  || h->u.weakdef->root.type == bfd_link_hash_defweak);
5832218822Sdim      h->root.u.def.section = h->u.weakdef->root.u.def.section;
5833218822Sdim      h->root.u.def.value = h->u.weakdef->root.u.def.value;
5834130561Sobrien      if (ELIMINATE_COPY_RELOCS)
5835218822Sdim	h->non_got_ref = h->u.weakdef->non_got_ref;
5836130561Sobrien      return TRUE;
583789857Sobrien    }
583889857Sobrien
583989857Sobrien  /* If we are creating a shared library, we must presume that the
584089857Sobrien     only references to the symbol are via the global offset table.
584189857Sobrien     For such cases we need not do anything here; the relocations will
584289857Sobrien     be handled correctly by relocate_section.  */
584389857Sobrien  if (info->shared)
5844130561Sobrien    return TRUE;
584589857Sobrien
584689857Sobrien  /* If there are no references to this symbol that do not use the
584789857Sobrien     GOT, we don't need to generate a copy reloc.  */
5848218822Sdim  if (!h->non_got_ref)
5849130561Sobrien    return TRUE;
585089857Sobrien
5851218822Sdim  /* Don't generate a copy reloc for symbols defined in the executable.  */
5852218822Sdim  if (!h->def_dynamic || !h->ref_regular || h->def_regular)
5853218822Sdim    return TRUE;
5854218822Sdim
5855130561Sobrien  if (ELIMINATE_COPY_RELOCS)
585689857Sobrien    {
5857130561Sobrien      struct ppc_link_hash_entry * eh;
5858130561Sobrien      struct ppc_dyn_relocs *p;
5859130561Sobrien
5860130561Sobrien      eh = (struct ppc_link_hash_entry *) h;
5861130561Sobrien      for (p = eh->dyn_relocs; p != NULL; p = p->next)
5862130561Sobrien	{
5863130561Sobrien	  s = p->sec->output_section;
5864130561Sobrien	  if (s != NULL && (s->flags & SEC_READONLY) != 0)
5865130561Sobrien	    break;
5866130561Sobrien	}
5867130561Sobrien
5868130561Sobrien      /* If we didn't find any dynamic relocs in read-only sections, then
5869130561Sobrien	 we'll be keeping the dynamic relocs and avoiding the copy reloc.  */
5870130561Sobrien      if (p == NULL)
5871130561Sobrien	{
5872218822Sdim	  h->non_got_ref = 0;
5873130561Sobrien	  return TRUE;
5874130561Sobrien	}
587589857Sobrien    }
587689857Sobrien
5877130561Sobrien  if (h->plt.plist != NULL)
587889857Sobrien    {
5879130561Sobrien      /* We should never get here, but unfortunately there are versions
5880130561Sobrien	 of gcc out there that improperly (for this ABI) put initialized
5881130561Sobrien	 function pointers, vtable refs and suchlike in read-only
5882130561Sobrien	 sections.  Allow them to proceed, but warn that this might
5883130561Sobrien	 break at runtime.  */
5884130561Sobrien      (*_bfd_error_handler)
5885130561Sobrien	(_("copy reloc against `%s' requires lazy plt linking; "
5886130561Sobrien	   "avoid setting LD_BIND_NOW=1 or upgrade gcc"),
5887130561Sobrien	 h->root.root.string);
588889857Sobrien    }
588989857Sobrien
5890130561Sobrien  /* This is a reference to a symbol defined by a dynamic object which
5891130561Sobrien     is not a function.  */
5892130561Sobrien
5893218822Sdim  if (h->size == 0)
5894218822Sdim    {
5895218822Sdim      (*_bfd_error_handler) (_("dynamic variable `%s' is zero size"),
5896218822Sdim			     h->root.root.string);
5897218822Sdim      return TRUE;
5898218822Sdim    }
5899218822Sdim
590089857Sobrien  /* We must allocate the symbol in our .dynbss section, which will
590189857Sobrien     become part of the .bss section of the executable.  There will be
590289857Sobrien     an entry for this symbol in the .dynsym section.  The dynamic
590389857Sobrien     object will contain position independent code, so all references
590489857Sobrien     from the dynamic object to this symbol will go through the global
590589857Sobrien     offset table.  The dynamic linker will use the .dynsym entry to
590689857Sobrien     determine the address it must put in the global offset table, so
590789857Sobrien     both the dynamic object and the regular object will refer to the
590889857Sobrien     same memory location for the variable.  */
590989857Sobrien
5910130561Sobrien  /* We must generate a R_PPC64_COPY reloc to tell the dynamic linker
5911130561Sobrien     to copy the initial value out of the dynamic object and into the
591289857Sobrien     runtime process image.  We need to remember the offset into the
591389857Sobrien     .rela.bss section we are going to use.  */
591489857Sobrien  if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
591589857Sobrien    {
5916218822Sdim      htab->relbss->size += sizeof (Elf64_External_Rela);
5917218822Sdim      h->needs_copy = 1;
591889857Sobrien    }
591989857Sobrien
5920130561Sobrien  s = htab->dynbss;
592189857Sobrien
5922218822Sdim  return _bfd_elf_adjust_dynamic_copy (h, s);
592389857Sobrien}
592489857Sobrien
592589857Sobrien/* If given a function descriptor symbol, hide both the function code
592689857Sobrien   sym and the descriptor.  */
592789857Sobrienstatic void
5928130561Sobrienppc64_elf_hide_symbol (struct bfd_link_info *info,
5929130561Sobrien		       struct elf_link_hash_entry *h,
5930130561Sobrien		       bfd_boolean force_local)
593189857Sobrien{
5932218822Sdim  struct ppc_link_hash_entry *eh;
593389857Sobrien  _bfd_elf_link_hash_hide_symbol (info, h, force_local);
593489857Sobrien
5935218822Sdim  eh = (struct ppc_link_hash_entry *) h;
5936218822Sdim  if (eh->is_func_descriptor)
593789857Sobrien    {
5938218822Sdim      struct ppc_link_hash_entry *fh = eh->oh;
593989857Sobrien
5940104834Sobrien      if (fh == NULL)
5941104834Sobrien	{
5942104834Sobrien	  const char *p, *q;
5943104834Sobrien	  struct ppc_link_hash_table *htab;
5944104834Sobrien	  char save;
5945104834Sobrien
5946104834Sobrien	  /* We aren't supposed to use alloca in BFD because on
5947104834Sobrien	     systems which do not have alloca the version in libiberty
5948104834Sobrien	     calls xmalloc, which might cause the program to crash
5949104834Sobrien	     when it runs out of memory.  This function doesn't have a
5950104834Sobrien	     return status, so there's no way to gracefully return an
5951104834Sobrien	     error.  So cheat.  We know that string[-1] can be safely
5952218822Sdim	     accessed;  It's either a string in an ELF string table,
5953218822Sdim	     or allocated in an objalloc structure.  */
5954104834Sobrien
5955218822Sdim	  p = eh->elf.root.root.string - 1;
5956104834Sobrien	  save = *p;
5957104834Sobrien	  *(char *) p = '.';
5958104834Sobrien	  htab = ppc_hash_table (info);
5959218822Sdim	  fh = (struct ppc_link_hash_entry *)
5960218822Sdim	    elf_link_hash_lookup (&htab->elf, p, FALSE, FALSE, FALSE);
5961104834Sobrien	  *(char *) p = save;
5962104834Sobrien
5963104834Sobrien	  /* Unfortunately, if it so happens that the string we were
5964104834Sobrien	     looking for was allocated immediately before this string,
5965104834Sobrien	     then we overwrote the string terminator.  That's the only
5966104834Sobrien	     reason the lookup should fail.  */
5967104834Sobrien	  if (fh == NULL)
5968104834Sobrien	    {
5969218822Sdim	      q = eh->elf.root.root.string + strlen (eh->elf.root.root.string);
5970218822Sdim	      while (q >= eh->elf.root.root.string && *q == *p)
5971104834Sobrien		--q, --p;
5972218822Sdim	      if (q < eh->elf.root.root.string && *p == '.')
5973218822Sdim		fh = (struct ppc_link_hash_entry *)
5974218822Sdim		  elf_link_hash_lookup (&htab->elf, p, FALSE, FALSE, FALSE);
5975104834Sobrien	    }
5976104834Sobrien	  if (fh != NULL)
5977104834Sobrien	    {
5978218822Sdim	      eh->oh = fh;
5979218822Sdim	      fh->oh = eh;
5980104834Sobrien	    }
5981104834Sobrien	}
598289857Sobrien      if (fh != NULL)
5983218822Sdim	_bfd_elf_link_hash_hide_symbol (info, &fh->elf, force_local);
598489857Sobrien    }
598589857Sobrien}
598689857Sobrien
5987130561Sobrienstatic bfd_boolean
5988218822Sdimget_sym_h (struct elf_link_hash_entry **hp,
5989218822Sdim	   Elf_Internal_Sym **symp,
5990218822Sdim	   asection **symsecp,
5991218822Sdim	   char **tls_maskp,
5992218822Sdim	   Elf_Internal_Sym **locsymsp,
5993218822Sdim	   unsigned long r_symndx,
5994218822Sdim	   bfd *ibfd)
5995104834Sobrien{
5996130561Sobrien  Elf_Internal_Shdr *symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
5997130561Sobrien
5998130561Sobrien  if (r_symndx >= symtab_hdr->sh_info)
5999130561Sobrien    {
6000130561Sobrien      struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (ibfd);
6001130561Sobrien      struct elf_link_hash_entry *h;
6002130561Sobrien
6003130561Sobrien      h = sym_hashes[r_symndx - symtab_hdr->sh_info];
6004130561Sobrien      while (h->root.type == bfd_link_hash_indirect
6005130561Sobrien	     || h->root.type == bfd_link_hash_warning)
6006130561Sobrien	h = (struct elf_link_hash_entry *) h->root.u.i.link;
6007130561Sobrien
6008130561Sobrien      if (hp != NULL)
6009130561Sobrien	*hp = h;
6010130561Sobrien
6011130561Sobrien      if (symp != NULL)
6012130561Sobrien	*symp = NULL;
6013130561Sobrien
6014130561Sobrien      if (symsecp != NULL)
6015130561Sobrien	{
6016130561Sobrien	  asection *symsec = NULL;
6017130561Sobrien	  if (h->root.type == bfd_link_hash_defined
6018130561Sobrien	      || h->root.type == bfd_link_hash_defweak)
6019130561Sobrien	    symsec = h->root.u.def.section;
6020130561Sobrien	  *symsecp = symsec;
6021130561Sobrien	}
6022130561Sobrien
6023130561Sobrien      if (tls_maskp != NULL)
6024130561Sobrien	{
6025130561Sobrien	  struct ppc_link_hash_entry *eh;
6026130561Sobrien
6027130561Sobrien	  eh = (struct ppc_link_hash_entry *) h;
6028130561Sobrien	  *tls_maskp = &eh->tls_mask;
6029130561Sobrien	}
6030130561Sobrien    }
6031130561Sobrien  else
6032130561Sobrien    {
6033130561Sobrien      Elf_Internal_Sym *sym;
6034130561Sobrien      Elf_Internal_Sym *locsyms = *locsymsp;
6035130561Sobrien
6036130561Sobrien      if (locsyms == NULL)
6037130561Sobrien	{
6038130561Sobrien	  locsyms = (Elf_Internal_Sym *) symtab_hdr->contents;
6039130561Sobrien	  if (locsyms == NULL)
6040130561Sobrien	    locsyms = bfd_elf_get_elf_syms (ibfd, symtab_hdr,
6041130561Sobrien					    symtab_hdr->sh_info,
6042130561Sobrien					    0, NULL, NULL, NULL);
6043130561Sobrien	  if (locsyms == NULL)
6044130561Sobrien	    return FALSE;
6045130561Sobrien	  *locsymsp = locsyms;
6046130561Sobrien	}
6047130561Sobrien      sym = locsyms + r_symndx;
6048130561Sobrien
6049130561Sobrien      if (hp != NULL)
6050130561Sobrien	*hp = NULL;
6051130561Sobrien
6052130561Sobrien      if (symp != NULL)
6053130561Sobrien	*symp = sym;
6054130561Sobrien
6055130561Sobrien      if (symsecp != NULL)
6056130561Sobrien	{
6057130561Sobrien	  asection *symsec = NULL;
6058130561Sobrien	  if ((sym->st_shndx != SHN_UNDEF
6059130561Sobrien	       && sym->st_shndx < SHN_LORESERVE)
6060130561Sobrien	      || sym->st_shndx > SHN_HIRESERVE)
6061130561Sobrien	    symsec = bfd_section_from_elf_index (ibfd, sym->st_shndx);
6062130561Sobrien	  *symsecp = symsec;
6063130561Sobrien	}
6064130561Sobrien
6065130561Sobrien      if (tls_maskp != NULL)
6066130561Sobrien	{
6067130561Sobrien	  struct got_entry **lgot_ents;
6068130561Sobrien	  char *tls_mask;
6069130561Sobrien
6070130561Sobrien	  tls_mask = NULL;
6071130561Sobrien	  lgot_ents = elf_local_got_ents (ibfd);
6072130561Sobrien	  if (lgot_ents != NULL)
6073130561Sobrien	    {
6074130561Sobrien	      char *lgot_masks = (char *) (lgot_ents + symtab_hdr->sh_info);
6075130561Sobrien	      tls_mask = &lgot_masks[r_symndx];
6076130561Sobrien	    }
6077130561Sobrien	  *tls_maskp = tls_mask;
6078130561Sobrien	}
6079130561Sobrien    }
6080130561Sobrien  return TRUE;
6081130561Sobrien}
6082130561Sobrien
6083130561Sobrien/* Returns TLS_MASKP for the given REL symbol.  Function return is 0 on
6084130561Sobrien   error, 2 on a toc GD type suitable for optimization, 3 on a toc LD
6085130561Sobrien   type suitable for optimization, and 1 otherwise.  */
6086130561Sobrien
6087130561Sobrienstatic int
6088130561Sobrienget_tls_mask (char **tls_maskp, unsigned long *toc_symndx,
6089130561Sobrien	      Elf_Internal_Sym **locsymsp,
6090130561Sobrien	      const Elf_Internal_Rela *rel, bfd *ibfd)
6091130561Sobrien{
6092130561Sobrien  unsigned long r_symndx;
6093130561Sobrien  int next_r;
6094130561Sobrien  struct elf_link_hash_entry *h;
6095130561Sobrien  Elf_Internal_Sym *sym;
6096130561Sobrien  asection *sec;
6097130561Sobrien  bfd_vma off;
6098130561Sobrien
6099130561Sobrien  r_symndx = ELF64_R_SYM (rel->r_info);
6100130561Sobrien  if (!get_sym_h (&h, &sym, &sec, tls_maskp, locsymsp, r_symndx, ibfd))
6101130561Sobrien    return 0;
6102130561Sobrien
6103130561Sobrien  if ((*tls_maskp != NULL && **tls_maskp != 0)
6104130561Sobrien      || sec == NULL
6105218822Sdim      || ppc64_elf_section_data (sec)->sec_type != sec_toc)
6106130561Sobrien    return 1;
6107130561Sobrien
6108130561Sobrien  /* Look inside a TOC section too.  */
6109130561Sobrien  if (h != NULL)
6110130561Sobrien    {
6111130561Sobrien      BFD_ASSERT (h->root.type == bfd_link_hash_defined);
6112130561Sobrien      off = h->root.u.def.value;
6113130561Sobrien    }
6114130561Sobrien  else
6115130561Sobrien    off = sym->st_value;
6116130561Sobrien  off += rel->r_addend;
6117130561Sobrien  BFD_ASSERT (off % 8 == 0);
6118218822Sdim  r_symndx = ppc64_elf_section_data (sec)->u.t_symndx[off / 8];
6119218822Sdim  next_r = ppc64_elf_section_data (sec)->u.t_symndx[off / 8 + 1];
6120130561Sobrien  if (!get_sym_h (&h, &sym, &sec, tls_maskp, locsymsp, r_symndx, ibfd))
6121130561Sobrien    return 0;
6122130561Sobrien  if (toc_symndx != NULL)
6123130561Sobrien    *toc_symndx = r_symndx;
6124130561Sobrien  if ((h == NULL
6125130561Sobrien       || ((h->root.type == bfd_link_hash_defined
6126130561Sobrien	    || h->root.type == bfd_link_hash_defweak)
6127218822Sdim	   && !h->def_dynamic))
6128130561Sobrien      && (next_r == -1 || next_r == -2))
6129130561Sobrien    return 1 - next_r;
6130130561Sobrien  return 1;
6131130561Sobrien}
6132130561Sobrien
6133130561Sobrien/* Adjust all global syms defined in opd sections.  In gcc generated
6134218822Sdim   code for the old ABI, these will already have been done.  */
6135130561Sobrien
6136130561Sobrienstatic bfd_boolean
6137130561Sobrienadjust_opd_syms (struct elf_link_hash_entry *h, void *inf ATTRIBUTE_UNUSED)
6138130561Sobrien{
6139130561Sobrien  struct ppc_link_hash_entry *eh;
6140130561Sobrien  asection *sym_sec;
6141130561Sobrien  long *opd_adjust;
6142130561Sobrien
6143130561Sobrien  if (h->root.type == bfd_link_hash_indirect)
6144130561Sobrien    return TRUE;
6145130561Sobrien
6146130561Sobrien  if (h->root.type == bfd_link_hash_warning)
6147130561Sobrien    h = (struct elf_link_hash_entry *) h->root.u.i.link;
6148130561Sobrien
6149130561Sobrien  if (h->root.type != bfd_link_hash_defined
6150130561Sobrien      && h->root.type != bfd_link_hash_defweak)
6151130561Sobrien    return TRUE;
6152130561Sobrien
6153130561Sobrien  eh = (struct ppc_link_hash_entry *) h;
6154130561Sobrien  if (eh->adjust_done)
6155130561Sobrien    return TRUE;
6156130561Sobrien
6157130561Sobrien  sym_sec = eh->elf.root.u.def.section;
6158218822Sdim  opd_adjust = get_opd_info (sym_sec);
6159218822Sdim  if (opd_adjust != NULL)
6160130561Sobrien    {
6161218822Sdim      long adjust = opd_adjust[eh->elf.root.u.def.value / 8];
6162218822Sdim      if (adjust == -1)
6163218822Sdim	{
6164218822Sdim	  /* This entry has been deleted.  */
6165218822Sdim	  asection *dsec = ppc64_elf_tdata (sym_sec->owner)->deleted_section;
6166218822Sdim	  if (dsec == NULL)
6167218822Sdim	    {
6168218822Sdim	      for (dsec = sym_sec->owner->sections; dsec; dsec = dsec->next)
6169218822Sdim		if (elf_discarded_section (dsec))
6170218822Sdim		  {
6171218822Sdim		    ppc64_elf_tdata (sym_sec->owner)->deleted_section = dsec;
6172218822Sdim		    break;
6173218822Sdim		  }
6174218822Sdim	    }
6175218822Sdim	  eh->elf.root.u.def.value = 0;
6176218822Sdim	  eh->elf.root.u.def.section = dsec;
6177218822Sdim	}
6178218822Sdim      else
6179218822Sdim	eh->elf.root.u.def.value += adjust;
6180130561Sobrien      eh->adjust_done = 1;
6181130561Sobrien    }
6182130561Sobrien  return TRUE;
6183130561Sobrien}
6184130561Sobrien
6185218822Sdim/* Handles decrementing dynamic reloc counts for the reloc specified by
6186218822Sdim   R_INFO in section SEC.  If LOCAL_SYMS is NULL, then H and SYM_SEC
6187218822Sdim   have already been determined.  */
6188218822Sdim
6189218822Sdimstatic bfd_boolean
6190218822Sdimdec_dynrel_count (bfd_vma r_info,
6191218822Sdim		  asection *sec,
6192218822Sdim		  struct bfd_link_info *info,
6193218822Sdim		  Elf_Internal_Sym **local_syms,
6194218822Sdim		  struct elf_link_hash_entry *h,
6195218822Sdim		  asection *sym_sec)
6196218822Sdim{
6197218822Sdim  enum elf_ppc64_reloc_type r_type;
6198218822Sdim  struct ppc_dyn_relocs *p;
6199218822Sdim  struct ppc_dyn_relocs **pp;
6200218822Sdim
6201218822Sdim  /* Can this reloc be dynamic?  This switch, and later tests here
6202218822Sdim     should be kept in sync with the code in check_relocs.  */
6203218822Sdim  r_type = ELF64_R_TYPE (r_info);
6204218822Sdim  switch (r_type)
6205218822Sdim    {
6206218822Sdim    default:
6207218822Sdim      return TRUE;
6208218822Sdim
6209218822Sdim    case R_PPC64_TPREL16:
6210218822Sdim    case R_PPC64_TPREL16_LO:
6211218822Sdim    case R_PPC64_TPREL16_HI:
6212218822Sdim    case R_PPC64_TPREL16_HA:
6213218822Sdim    case R_PPC64_TPREL16_DS:
6214218822Sdim    case R_PPC64_TPREL16_LO_DS:
6215218822Sdim    case R_PPC64_TPREL16_HIGHER:
6216218822Sdim    case R_PPC64_TPREL16_HIGHERA:
6217218822Sdim    case R_PPC64_TPREL16_HIGHEST:
6218218822Sdim    case R_PPC64_TPREL16_HIGHESTA:
6219218822Sdim      if (!info->shared)
6220218822Sdim	return TRUE;
6221218822Sdim
6222218822Sdim    case R_PPC64_TPREL64:
6223218822Sdim    case R_PPC64_DTPMOD64:
6224218822Sdim    case R_PPC64_DTPREL64:
6225218822Sdim    case R_PPC64_ADDR64:
6226218822Sdim    case R_PPC64_REL30:
6227218822Sdim    case R_PPC64_REL32:
6228218822Sdim    case R_PPC64_REL64:
6229218822Sdim    case R_PPC64_ADDR14:
6230218822Sdim    case R_PPC64_ADDR14_BRNTAKEN:
6231218822Sdim    case R_PPC64_ADDR14_BRTAKEN:
6232218822Sdim    case R_PPC64_ADDR16:
6233218822Sdim    case R_PPC64_ADDR16_DS:
6234218822Sdim    case R_PPC64_ADDR16_HA:
6235218822Sdim    case R_PPC64_ADDR16_HI:
6236218822Sdim    case R_PPC64_ADDR16_HIGHER:
6237218822Sdim    case R_PPC64_ADDR16_HIGHERA:
6238218822Sdim    case R_PPC64_ADDR16_HIGHEST:
6239218822Sdim    case R_PPC64_ADDR16_HIGHESTA:
6240218822Sdim    case R_PPC64_ADDR16_LO:
6241218822Sdim    case R_PPC64_ADDR16_LO_DS:
6242218822Sdim    case R_PPC64_ADDR24:
6243218822Sdim    case R_PPC64_ADDR32:
6244218822Sdim    case R_PPC64_UADDR16:
6245218822Sdim    case R_PPC64_UADDR32:
6246218822Sdim    case R_PPC64_UADDR64:
6247218822Sdim    case R_PPC64_TOC:
6248218822Sdim      break;
6249218822Sdim    }
6250218822Sdim
6251218822Sdim  if (local_syms != NULL)
6252218822Sdim    {
6253218822Sdim      unsigned long r_symndx;
6254218822Sdim      Elf_Internal_Sym *sym;
6255218822Sdim      bfd *ibfd = sec->owner;
6256218822Sdim
6257218822Sdim      r_symndx = ELF64_R_SYM (r_info);
6258218822Sdim      if (!get_sym_h (&h, &sym, &sym_sec, NULL, local_syms, r_symndx, ibfd))
6259218822Sdim	return FALSE;
6260218822Sdim    }
6261218822Sdim
6262218822Sdim  if ((info->shared
6263218822Sdim       && (MUST_BE_DYN_RELOC (r_type)
6264218822Sdim	   || (h != NULL
6265218822Sdim	       && (!info->symbolic
6266218822Sdim		   || h->root.type == bfd_link_hash_defweak
6267218822Sdim		   || !h->def_regular))))
6268218822Sdim      || (ELIMINATE_COPY_RELOCS
6269218822Sdim	  && !info->shared
6270218822Sdim	  && h != NULL
6271218822Sdim	  && (h->root.type == bfd_link_hash_defweak
6272218822Sdim	      || !h->def_regular)))
6273218822Sdim    ;
6274218822Sdim  else
6275218822Sdim    return TRUE;
6276218822Sdim
6277218822Sdim  if (h != NULL)
6278218822Sdim    pp = &((struct ppc_link_hash_entry *) h)->dyn_relocs;
6279218822Sdim  else
6280218822Sdim    {
6281218822Sdim      if (sym_sec != NULL)
6282218822Sdim	{
6283218822Sdim	  void *vpp = &elf_section_data (sym_sec)->local_dynrel;
6284218822Sdim	  pp = (struct ppc_dyn_relocs **) vpp;
6285218822Sdim	}
6286218822Sdim      else
6287218822Sdim	{
6288218822Sdim	  void *vpp = &elf_section_data (sec)->local_dynrel;
6289218822Sdim	  pp = (struct ppc_dyn_relocs **) vpp;
6290218822Sdim	}
6291218822Sdim
6292218822Sdim      /* elf_gc_sweep may have already removed all dyn relocs associated
6293218822Sdim	 with local syms for a given section.  Don't report a dynreloc
6294218822Sdim	 miscount.  */
6295218822Sdim      if (*pp == NULL)
6296218822Sdim	return TRUE;
6297218822Sdim    }
6298218822Sdim
6299218822Sdim  while ((p = *pp) != NULL)
6300218822Sdim    {
6301218822Sdim      if (p->sec == sec)
6302218822Sdim	{
6303218822Sdim	  if (!MUST_BE_DYN_RELOC (r_type))
6304218822Sdim	    p->pc_count -= 1;
6305218822Sdim	  p->count -= 1;
6306218822Sdim	  if (p->count == 0)
6307218822Sdim	    *pp = p->next;
6308218822Sdim	  return TRUE;
6309218822Sdim	}
6310218822Sdim      pp = &p->next;
6311218822Sdim    }
6312218822Sdim
6313218822Sdim  (*_bfd_error_handler) (_("dynreloc miscount for %B, section %A"),
6314218822Sdim			   sec->owner, sec);
6315218822Sdim  bfd_set_error (bfd_error_bad_value);
6316218822Sdim  return FALSE;
6317218822Sdim}
6318218822Sdim
6319130561Sobrien/* Remove unused Official Procedure Descriptor entries.  Currently we
6320130561Sobrien   only remove those associated with functions in discarded link-once
6321130561Sobrien   sections, or weakly defined functions that have been overridden.  It
6322130561Sobrien   would be possible to remove many more entries for statically linked
6323130561Sobrien   applications.  */
6324130561Sobrien
6325130561Sobrienbfd_boolean
6326218822Sdimppc64_elf_edit_opd (bfd *obfd, struct bfd_link_info *info,
6327218822Sdim		    bfd_boolean no_opd_opt,
6328218822Sdim		    bfd_boolean non_overlapping)
6329130561Sobrien{
6330104834Sobrien  bfd *ibfd;
6331130561Sobrien  bfd_boolean some_edited = FALSE;
6332218822Sdim  asection *need_pad = NULL;
6333104834Sobrien
6334130561Sobrien  for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
6335104834Sobrien    {
6336104834Sobrien      asection *sec;
6337104834Sobrien      Elf_Internal_Rela *relstart, *rel, *relend;
6338104834Sobrien      Elf_Internal_Shdr *symtab_hdr;
6339104834Sobrien      Elf_Internal_Sym *local_syms;
6340104834Sobrien      struct elf_link_hash_entry **sym_hashes;
6341104834Sobrien      bfd_vma offset;
6342130561Sobrien      bfd_size_type amt;
6343218822Sdim      long *opd_adjust;
6344218822Sdim      bfd_boolean need_edit, add_aux_fields;
6345218822Sdim      bfd_size_type cnt_16b = 0;
6346104834Sobrien
6347104834Sobrien      sec = bfd_get_section_by_name (ibfd, ".opd");
6348218822Sdim      if (sec == NULL || sec->size == 0)
6349104834Sobrien	continue;
6350104834Sobrien
6351218822Sdim      amt = sec->size * sizeof (long) / 8;
6352218822Sdim      opd_adjust = get_opd_info (sec);
6353218822Sdim      if (opd_adjust == NULL)
6354130561Sobrien	{
6355218822Sdim	  /* check_relocs hasn't been called.  Must be a ld -r link
6356218822Sdim	     or --just-symbols object.   */
6357218822Sdim	  opd_adjust = bfd_alloc (obfd, amt);
6358218822Sdim	  if (opd_adjust == NULL)
6359218822Sdim	    return FALSE;
6360218822Sdim	  ppc64_elf_section_data (sec)->u.opd_adjust = opd_adjust;
6361218822Sdim	  BFD_ASSERT (ppc64_elf_section_data (sec)->sec_type == sec_normal);
6362218822Sdim	  ppc64_elf_section_data (sec)->sec_type = sec_opd;
6363130561Sobrien	}
6364218822Sdim      memset (opd_adjust, 0, amt);
6365104834Sobrien
6366218822Sdim      if (no_opd_opt)
6367218822Sdim	continue;
6368218822Sdim
6369218822Sdim      if (sec->sec_info_type == ELF_INFO_TYPE_JUST_SYMS)
6370218822Sdim	continue;
6371218822Sdim
6372104834Sobrien      if (sec->output_section == bfd_abs_section_ptr)
6373104834Sobrien	continue;
6374104834Sobrien
6375104834Sobrien      /* Look through the section relocs.  */
6376104834Sobrien      if ((sec->flags & SEC_RELOC) == 0 || sec->reloc_count == 0)
6377104834Sobrien	continue;
6378104834Sobrien
6379104834Sobrien      local_syms = NULL;
6380104834Sobrien      symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
6381104834Sobrien      sym_hashes = elf_sym_hashes (ibfd);
6382104834Sobrien
6383104834Sobrien      /* Read the relocations.  */
6384130561Sobrien      relstart = _bfd_elf_link_read_relocs (ibfd, sec, NULL, NULL,
6385130561Sobrien					    info->keep_memory);
6386104834Sobrien      if (relstart == NULL)
6387130561Sobrien	return FALSE;
6388104834Sobrien
6389104834Sobrien      /* First run through the relocs to check they are sane, and to
6390104834Sobrien	 determine whether we need to edit this opd section.  */
6391130561Sobrien      need_edit = FALSE;
6392218822Sdim      need_pad = sec;
6393104834Sobrien      offset = 0;
6394104834Sobrien      relend = relstart + sec->reloc_count;
6395130561Sobrien      for (rel = relstart; rel < relend; )
6396104834Sobrien	{
6397130561Sobrien	  enum elf_ppc64_reloc_type r_type;
6398104834Sobrien	  unsigned long r_symndx;
6399104834Sobrien	  asection *sym_sec;
6400104834Sobrien	  struct elf_link_hash_entry *h;
6401104834Sobrien	  Elf_Internal_Sym *sym;
6402104834Sobrien
6403218822Sdim	  /* .opd contains a regular array of 16 or 24 byte entries.  We're
6404104834Sobrien	     only interested in the reloc pointing to a function entry
6405104834Sobrien	     point.  */
6406130561Sobrien	  if (rel->r_offset != offset
6407130561Sobrien	      || rel + 1 >= relend
6408130561Sobrien	      || (rel + 1)->r_offset != offset + 8)
6409104834Sobrien	    {
6410104834Sobrien	      /* If someone messes with .opd alignment then after a
6411104834Sobrien		 "ld -r" we might have padding in the middle of .opd.
6412104834Sobrien		 Also, there's nothing to prevent someone putting
6413104834Sobrien		 something silly in .opd with the assembler.  No .opd
6414130561Sobrien		 optimization for them!  */
6415218822Sdim	    broken_opd:
6416104834Sobrien	      (*_bfd_error_handler)
6417218822Sdim		(_("%B: .opd is not a regular array of opd entries"), ibfd);
6418130561Sobrien	      need_edit = FALSE;
6419104834Sobrien	      break;
6420104834Sobrien	    }
6421104834Sobrien
6422130561Sobrien	  if ((r_type = ELF64_R_TYPE (rel->r_info)) != R_PPC64_ADDR64
6423130561Sobrien	      || (r_type = ELF64_R_TYPE ((rel + 1)->r_info)) != R_PPC64_TOC)
6424104834Sobrien	    {
6425130561Sobrien	      (*_bfd_error_handler)
6426218822Sdim		(_("%B: unexpected reloc type %u in .opd section"),
6427218822Sdim		 ibfd, r_type);
6428130561Sobrien	      need_edit = FALSE;
6429130561Sobrien	      break;
6430104834Sobrien	    }
6431104834Sobrien
6432130561Sobrien	  r_symndx = ELF64_R_SYM (rel->r_info);
6433130561Sobrien	  if (!get_sym_h (&h, &sym, &sym_sec, NULL, &local_syms,
6434130561Sobrien			  r_symndx, ibfd))
6435130561Sobrien	    goto error_ret;
6436130561Sobrien
6437104834Sobrien	  if (sym_sec == NULL || sym_sec->owner == NULL)
6438104834Sobrien	    {
6439130561Sobrien	      const char *sym_name;
6440130561Sobrien	      if (h != NULL)
6441130561Sobrien		sym_name = h->root.root.string;
6442130561Sobrien	      else
6443218822Sdim		sym_name = bfd_elf_sym_name (ibfd, symtab_hdr, sym,
6444218822Sdim					     sym_sec);
6445130561Sobrien
6446104834Sobrien	      (*_bfd_error_handler)
6447218822Sdim		(_("%B: undefined sym `%s' in .opd section"),
6448218822Sdim		 ibfd, sym_name);
6449130561Sobrien	      need_edit = FALSE;
6450104834Sobrien	      break;
6451104834Sobrien	    }
6452104834Sobrien
6453104834Sobrien	  /* opd entries are always for functions defined in the
6454104834Sobrien	     current input bfd.  If the symbol isn't defined in the
6455104834Sobrien	     input bfd, then we won't be using the function in this
6456104834Sobrien	     bfd;  It must be defined in a linkonce section in another
6457104834Sobrien	     bfd, or is weak.  It's also possible that we are
6458104834Sobrien	     discarding the function due to a linker script /DISCARD/,
6459104834Sobrien	     which we test for via the output_section.  */
6460104834Sobrien	  if (sym_sec->owner != ibfd
6461104834Sobrien	      || sym_sec->output_section == bfd_abs_section_ptr)
6462130561Sobrien	    need_edit = TRUE;
6463104834Sobrien
6464130561Sobrien	  rel += 2;
6465218822Sdim	  if (rel == relend
6466218822Sdim	      || (rel + 1 == relend && rel->r_offset == offset + 16))
6467218822Sdim	    {
6468218822Sdim	      if (sec->size == offset + 24)
6469218822Sdim		{
6470218822Sdim		  need_pad = NULL;
6471218822Sdim		  break;
6472218822Sdim		}
6473218822Sdim	      if (rel == relend && sec->size == offset + 16)
6474218822Sdim		{
6475218822Sdim		  cnt_16b++;
6476218822Sdim		  break;
6477218822Sdim		}
6478218822Sdim	      goto broken_opd;
6479218822Sdim	    }
6480218822Sdim
6481218822Sdim	  if (rel->r_offset == offset + 24)
6482218822Sdim	    offset += 24;
6483218822Sdim	  else if (rel->r_offset != offset + 16)
6484218822Sdim	    goto broken_opd;
6485218822Sdim	  else if (rel + 1 < relend
6486218822Sdim		   && ELF64_R_TYPE (rel[0].r_info) == R_PPC64_ADDR64
6487218822Sdim		   && ELF64_R_TYPE (rel[1].r_info) == R_PPC64_TOC)
6488218822Sdim	    {
6489218822Sdim	      offset += 16;
6490218822Sdim	      cnt_16b++;
6491218822Sdim	    }
6492218822Sdim	  else if (rel + 2 < relend
6493218822Sdim		   && ELF64_R_TYPE (rel[1].r_info) == R_PPC64_ADDR64
6494218822Sdim		   && ELF64_R_TYPE (rel[2].r_info) == R_PPC64_TOC)
6495218822Sdim	    {
6496218822Sdim	      offset += 24;
6497218822Sdim	      rel += 1;
6498218822Sdim	    }
6499218822Sdim	  else
6500218822Sdim	    goto broken_opd;
6501104834Sobrien	}
6502104834Sobrien
6503218822Sdim      add_aux_fields = non_overlapping && cnt_16b > 0;
6504218822Sdim
6505218822Sdim      if (need_edit || add_aux_fields)
6506104834Sobrien	{
6507104834Sobrien	  Elf_Internal_Rela *write_rel;
6508104834Sobrien	  bfd_byte *rptr, *wptr;
6509218822Sdim	  bfd_byte *new_contents = NULL;
6510130561Sobrien	  bfd_boolean skip;
6511218822Sdim	  long opd_ent_size;
6512104834Sobrien
6513104834Sobrien	  /* This seems a waste of time as input .opd sections are all
6514104834Sobrien	     zeros as generated by gcc, but I suppose there's no reason
6515104834Sobrien	     this will always be so.  We might start putting something in
6516104834Sobrien	     the third word of .opd entries.  */
6517104834Sobrien	  if ((sec->flags & SEC_IN_MEMORY) == 0)
6518104834Sobrien	    {
6519218822Sdim	      bfd_byte *loc;
6520218822Sdim	      if (!bfd_malloc_and_get_section (ibfd, sec, &loc))
6521104834Sobrien		{
6522218822Sdim		  if (loc != NULL)
6523218822Sdim		    free (loc);
6524130561Sobrien		error_ret:
6525104834Sobrien		  if (local_syms != NULL
6526104834Sobrien		      && symtab_hdr->contents != (unsigned char *) local_syms)
6527104834Sobrien		    free (local_syms);
6528104834Sobrien		  if (elf_section_data (sec)->relocs != relstart)
6529104834Sobrien		    free (relstart);
6530130561Sobrien		  return FALSE;
6531104834Sobrien		}
6532104834Sobrien	      sec->contents = loc;
6533104834Sobrien	      sec->flags |= (SEC_IN_MEMORY | SEC_HAS_CONTENTS);
6534104834Sobrien	    }
6535104834Sobrien
6536104834Sobrien	  elf_section_data (sec)->relocs = relstart;
6537104834Sobrien
6538218822Sdim	  new_contents = sec->contents;
6539218822Sdim	  if (add_aux_fields)
6540218822Sdim	    {
6541218822Sdim	      new_contents = bfd_malloc (sec->size + cnt_16b * 8);
6542218822Sdim	      if (new_contents == NULL)
6543218822Sdim		return FALSE;
6544218822Sdim	      need_pad = FALSE;
6545218822Sdim	    }
6546218822Sdim	  wptr = new_contents;
6547104834Sobrien	  rptr = sec->contents;
6548218822Sdim
6549104834Sobrien	  write_rel = relstart;
6550130561Sobrien	  skip = FALSE;
6551104834Sobrien	  offset = 0;
6552218822Sdim	  opd_ent_size = 0;
6553104834Sobrien	  for (rel = relstart; rel < relend; rel++)
6554104834Sobrien	    {
6555130561Sobrien	      unsigned long r_symndx;
6556130561Sobrien	      asection *sym_sec;
6557130561Sobrien	      struct elf_link_hash_entry *h;
6558130561Sobrien	      Elf_Internal_Sym *sym;
6559130561Sobrien
6560130561Sobrien	      r_symndx = ELF64_R_SYM (rel->r_info);
6561130561Sobrien	      if (!get_sym_h (&h, &sym, &sym_sec, NULL, &local_syms,
6562130561Sobrien			      r_symndx, ibfd))
6563130561Sobrien		goto error_ret;
6564130561Sobrien
6565104834Sobrien	      if (rel->r_offset == offset)
6566104834Sobrien		{
6567130561Sobrien		  struct ppc_link_hash_entry *fdh = NULL;
6568104834Sobrien
6569218822Sdim		  /* See if the .opd entry is full 24 byte or
6570218822Sdim		     16 byte (with fd_aux entry overlapped with next
6571218822Sdim		     fd_func).  */
6572218822Sdim		  opd_ent_size = 24;
6573218822Sdim		  if ((rel + 2 == relend && sec->size == offset + 16)
6574218822Sdim		      || (rel + 3 < relend
6575218822Sdim			  && rel[2].r_offset == offset + 16
6576218822Sdim			  && rel[3].r_offset == offset + 24
6577218822Sdim			  && ELF64_R_TYPE (rel[2].r_info) == R_PPC64_ADDR64
6578218822Sdim			  && ELF64_R_TYPE (rel[3].r_info) == R_PPC64_TOC))
6579218822Sdim		    opd_ent_size = 16;
6580218822Sdim
6581218822Sdim		  if (h != NULL
6582218822Sdim		      && h->root.root.string[0] == '.')
6583218822Sdim		    {
6584218822Sdim		      fdh = get_fdh ((struct ppc_link_hash_entry *) h,
6585218822Sdim				     ppc_hash_table (info));
6586218822Sdim		      if (fdh != NULL
6587218822Sdim			  && fdh->elf.root.type != bfd_link_hash_defined
6588218822Sdim			  && fdh->elf.root.type != bfd_link_hash_defweak)
6589218822Sdim			fdh = NULL;
6590218822Sdim		    }
6591218822Sdim
6592104834Sobrien		  skip = (sym_sec->owner != ibfd
6593104834Sobrien			  || sym_sec->output_section == bfd_abs_section_ptr);
6594104834Sobrien		  if (skip)
6595104834Sobrien		    {
6596218822Sdim		      if (fdh != NULL && sym_sec->owner == ibfd)
6597104834Sobrien			{
6598104834Sobrien			  /* Arrange for the function descriptor sym
6599104834Sobrien			     to be dropped.  */
6600130561Sobrien			  fdh->elf.root.u.def.value = 0;
6601130561Sobrien			  fdh->elf.root.u.def.section = sym_sec;
6602104834Sobrien			}
6603218822Sdim		      opd_adjust[rel->r_offset / 8] = -1;
6604104834Sobrien		    }
6605104834Sobrien		  else
6606104834Sobrien		    {
6607104834Sobrien		      /* We'll be keeping this opd entry.  */
6608104834Sobrien
6609218822Sdim		      if (fdh != NULL)
6610104834Sobrien			{
6611130561Sobrien			  /* Redefine the function descriptor symbol to
6612130561Sobrien			     this location in the opd section.  It is
6613130561Sobrien			     necessary to update the value here rather
6614130561Sobrien			     than using an array of adjustments as we do
6615130561Sobrien			     for local symbols, because various places
6616130561Sobrien			     in the generic ELF code use the value
6617130561Sobrien			     stored in u.def.value.  */
6618218822Sdim			  fdh->elf.root.u.def.value = wptr - new_contents;
6619130561Sobrien			  fdh->adjust_done = 1;
6620104834Sobrien			}
6621104834Sobrien
6622130561Sobrien		      /* Local syms are a bit tricky.  We could
6623130561Sobrien			 tweak them as they can be cached, but
6624130561Sobrien			 we'd need to look through the local syms
6625130561Sobrien			 for the function descriptor sym which we
6626130561Sobrien			 don't have at the moment.  So keep an
6627130561Sobrien			 array of adjustments.  */
6628218822Sdim		      opd_adjust[rel->r_offset / 8]
6629218822Sdim			= (wptr - new_contents) - (rptr - sec->contents);
6630130561Sobrien
6631104834Sobrien		      if (wptr != rptr)
6632218822Sdim			memcpy (wptr, rptr, opd_ent_size);
6633218822Sdim		      wptr += opd_ent_size;
6634218822Sdim		      if (add_aux_fields && opd_ent_size == 16)
6635218822Sdim			{
6636218822Sdim			  memset (wptr, '\0', 8);
6637218822Sdim			  wptr += 8;
6638218822Sdim			}
6639104834Sobrien		    }
6640218822Sdim		  rptr += opd_ent_size;
6641218822Sdim		  offset += opd_ent_size;
6642104834Sobrien		}
6643104834Sobrien
6644130561Sobrien	      if (skip)
6645104834Sobrien		{
6646218822Sdim		  if (!NO_OPD_RELOCS
6647218822Sdim		      && !info->relocatable
6648218822Sdim		      && !dec_dynrel_count (rel->r_info, sec, info,
6649218822Sdim					    NULL, h, sym_sec))
6650218822Sdim		    goto error_ret;
6651130561Sobrien		}
6652130561Sobrien	      else
6653130561Sobrien		{
6654130561Sobrien		  /* We need to adjust any reloc offsets to point to the
6655130561Sobrien		     new opd entries.  While we're at it, we may as well
6656130561Sobrien		     remove redundant relocs.  */
6657218822Sdim		  rel->r_offset += opd_adjust[(offset - opd_ent_size) / 8];
6658104834Sobrien		  if (write_rel != rel)
6659104834Sobrien		    memcpy (write_rel, rel, sizeof (*rel));
6660104834Sobrien		  ++write_rel;
6661104834Sobrien		}
6662104834Sobrien	    }
6663104834Sobrien
6664218822Sdim	  sec->size = wptr - new_contents;
6665104834Sobrien	  sec->reloc_count = write_rel - relstart;
6666218822Sdim	  if (add_aux_fields)
6667218822Sdim	    {
6668218822Sdim	      free (sec->contents);
6669218822Sdim	      sec->contents = new_contents;
6670218822Sdim	    }
6671218822Sdim
6672218822Sdim	  /* Fudge the header size too, as this is used later in
6673130561Sobrien	     elf_bfd_final_link if we are emitting relocs.  */
6674130561Sobrien	  elf_section_data (sec)->rel_hdr.sh_size
6675130561Sobrien	    = sec->reloc_count * elf_section_data (sec)->rel_hdr.sh_entsize;
6676130561Sobrien	  BFD_ASSERT (elf_section_data (sec)->rel_hdr2 == NULL);
6677130561Sobrien	  some_edited = TRUE;
6678104834Sobrien	}
6679104834Sobrien      else if (elf_section_data (sec)->relocs != relstart)
6680104834Sobrien	free (relstart);
6681104834Sobrien
6682104834Sobrien      if (local_syms != NULL
6683104834Sobrien	  && symtab_hdr->contents != (unsigned char *) local_syms)
6684104834Sobrien	{
6685104834Sobrien	  if (!info->keep_memory)
6686104834Sobrien	    free (local_syms);
6687104834Sobrien	  else
6688104834Sobrien	    symtab_hdr->contents = (unsigned char *) local_syms;
6689104834Sobrien	}
6690104834Sobrien    }
6691104834Sobrien
6692130561Sobrien  if (some_edited)
6693130561Sobrien    elf_link_hash_traverse (elf_hash_table (info), adjust_opd_syms, NULL);
6694130561Sobrien
6695218822Sdim  /* If we are doing a final link and the last .opd entry is just 16 byte
6696218822Sdim     long, add a 8 byte padding after it.  */
6697218822Sdim  if (need_pad != NULL && !info->relocatable)
6698218822Sdim    {
6699218822Sdim      bfd_byte *p;
6700218822Sdim
6701218822Sdim      if ((need_pad->flags & SEC_IN_MEMORY) == 0)
6702218822Sdim	{
6703218822Sdim	  BFD_ASSERT (need_pad->size > 0);
6704218822Sdim
6705218822Sdim	  p = bfd_malloc (need_pad->size + 8);
6706218822Sdim	  if (p == NULL)
6707218822Sdim	    return FALSE;
6708218822Sdim
6709218822Sdim	  if (! bfd_get_section_contents (need_pad->owner, need_pad,
6710218822Sdim					  p, 0, need_pad->size))
6711218822Sdim	    return FALSE;
6712218822Sdim
6713218822Sdim	  need_pad->contents = p;
6714218822Sdim	  need_pad->flags |= (SEC_IN_MEMORY | SEC_HAS_CONTENTS);
6715218822Sdim	}
6716218822Sdim      else
6717218822Sdim	{
6718218822Sdim	  p = bfd_realloc (need_pad->contents, need_pad->size + 8);
6719218822Sdim	  if (p == NULL)
6720218822Sdim	    return FALSE;
6721218822Sdim
6722218822Sdim	  need_pad->contents = p;
6723218822Sdim	}
6724218822Sdim
6725218822Sdim      memset (need_pad->contents + need_pad->size, 0, 8);
6726218822Sdim      need_pad->size += 8;
6727218822Sdim    }
6728218822Sdim
6729130561Sobrien  return TRUE;
6730104834Sobrien}
673189857Sobrien
6732130561Sobrien/* Set htab->tls_get_addr and call the generic ELF tls_setup function.  */
6733130561Sobrien
6734130561Sobrienasection *
6735130561Sobrienppc64_elf_tls_setup (bfd *obfd, struct bfd_link_info *info)
6736130561Sobrien{
6737130561Sobrien  struct ppc_link_hash_table *htab;
6738130561Sobrien
6739130561Sobrien  htab = ppc_hash_table (info);
6740130561Sobrien  if (htab->tls_get_addr != NULL)
6741130561Sobrien    {
6742218822Sdim      struct ppc_link_hash_entry *h = htab->tls_get_addr;
6743130561Sobrien
6744218822Sdim      while (h->elf.root.type == bfd_link_hash_indirect
6745218822Sdim	     || h->elf.root.type == bfd_link_hash_warning)
6746218822Sdim	h = (struct ppc_link_hash_entry *) h->elf.root.u.i.link;
6747130561Sobrien
6748130561Sobrien      htab->tls_get_addr = h;
6749218822Sdim
6750218822Sdim      if (htab->tls_get_addr_fd == NULL
6751218822Sdim	  && h->oh != NULL
6752218822Sdim	  && h->oh->is_func_descriptor
6753218822Sdim	  && (h->oh->elf.root.type == bfd_link_hash_defined
6754218822Sdim	      || h->oh->elf.root.type == bfd_link_hash_defweak))
6755218822Sdim	htab->tls_get_addr_fd = h->oh;
6756130561Sobrien    }
6757130561Sobrien
6758218822Sdim  if (htab->tls_get_addr_fd != NULL)
6759218822Sdim    {
6760218822Sdim      struct ppc_link_hash_entry *h = htab->tls_get_addr_fd;
6761218822Sdim
6762218822Sdim      while (h->elf.root.type == bfd_link_hash_indirect
6763218822Sdim	     || h->elf.root.type == bfd_link_hash_warning)
6764218822Sdim	h = (struct ppc_link_hash_entry *) h->elf.root.u.i.link;
6765218822Sdim
6766218822Sdim      htab->tls_get_addr_fd = h;
6767218822Sdim    }
6768218822Sdim
6769130561Sobrien  return _bfd_elf_tls_setup (obfd, info);
6770130561Sobrien}
6771130561Sobrien
6772130561Sobrien/* Run through all the TLS relocs looking for optimization
6773130561Sobrien   opportunities.  The linker has been hacked (see ppc64elf.em) to do
6774130561Sobrien   a preliminary section layout so that we know the TLS segment
6775130561Sobrien   offsets.  We can't optimize earlier because some optimizations need
6776130561Sobrien   to know the tp offset, and we need to optimize before allocating
6777130561Sobrien   dynamic relocations.  */
6778130561Sobrien
6779130561Sobrienbfd_boolean
6780130561Sobrienppc64_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
6781130561Sobrien{
6782130561Sobrien  bfd *ibfd;
6783130561Sobrien  asection *sec;
6784130561Sobrien  struct ppc_link_hash_table *htab;
6785130561Sobrien
6786130561Sobrien  if (info->relocatable || info->shared)
6787130561Sobrien    return TRUE;
6788130561Sobrien
6789130561Sobrien  htab = ppc_hash_table (info);
6790130561Sobrien  for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
6791130561Sobrien    {
6792130561Sobrien      Elf_Internal_Sym *locsyms = NULL;
6793218822Sdim      asection *toc = bfd_get_section_by_name (ibfd, ".toc");
6794218822Sdim      unsigned char *toc_ref = NULL;
6795130561Sobrien
6796218822Sdim      /* Look at all the sections for this file, with TOC last.  */
6797218822Sdim      for (sec = (ibfd->sections == toc && toc && toc->next ? toc->next
6798218822Sdim		  : ibfd->sections);
6799218822Sdim	   sec != NULL;
6800218822Sdim	   sec = (sec == toc ? NULL
6801218822Sdim		  : sec->next == NULL ? toc
6802218822Sdim		  : sec->next == toc && toc->next ? toc->next
6803218822Sdim		  : sec->next))
6804130561Sobrien	if (sec->has_tls_reloc && !bfd_is_abs_section (sec->output_section))
6805130561Sobrien	  {
6806130561Sobrien	    Elf_Internal_Rela *relstart, *rel, *relend;
6807130561Sobrien	    int expecting_tls_get_addr;
6808218822Sdim	    long toc_ref_index = 0;
6809130561Sobrien
6810130561Sobrien	    /* Read the relocations.  */
6811130561Sobrien	    relstart = _bfd_elf_link_read_relocs (ibfd, sec, NULL, NULL,
6812130561Sobrien						  info->keep_memory);
6813130561Sobrien	    if (relstart == NULL)
6814130561Sobrien	      return FALSE;
6815130561Sobrien
6816130561Sobrien	    expecting_tls_get_addr = 0;
6817130561Sobrien	    relend = relstart + sec->reloc_count;
6818130561Sobrien	    for (rel = relstart; rel < relend; rel++)
6819130561Sobrien	      {
6820130561Sobrien		enum elf_ppc64_reloc_type r_type;
6821130561Sobrien		unsigned long r_symndx;
6822130561Sobrien		struct elf_link_hash_entry *h;
6823130561Sobrien		Elf_Internal_Sym *sym;
6824130561Sobrien		asection *sym_sec;
6825130561Sobrien		char *tls_mask;
6826130561Sobrien		char tls_set, tls_clear, tls_type = 0;
6827130561Sobrien		bfd_vma value;
6828130561Sobrien		bfd_boolean ok_tprel, is_local;
6829130561Sobrien
6830130561Sobrien		r_symndx = ELF64_R_SYM (rel->r_info);
6831130561Sobrien		if (!get_sym_h (&h, &sym, &sym_sec, &tls_mask, &locsyms,
6832130561Sobrien				r_symndx, ibfd))
6833130561Sobrien		  {
6834130561Sobrien		  err_free_rel:
6835130561Sobrien		    if (elf_section_data (sec)->relocs != relstart)
6836130561Sobrien		      free (relstart);
6837218822Sdim		    if (toc_ref != NULL)
6838218822Sdim		      free (toc_ref);
6839130561Sobrien		    if (locsyms != NULL
6840130561Sobrien			&& (elf_tdata (ibfd)->symtab_hdr.contents
6841130561Sobrien			    != (unsigned char *) locsyms))
6842130561Sobrien		      free (locsyms);
6843130561Sobrien		    return FALSE;
6844130561Sobrien		  }
6845130561Sobrien
6846130561Sobrien		if (h != NULL)
6847130561Sobrien		  {
6848130561Sobrien		    if (h->root.type != bfd_link_hash_defined
6849130561Sobrien			&& h->root.type != bfd_link_hash_defweak)
6850130561Sobrien		      continue;
6851130561Sobrien		    value = h->root.u.def.value;
6852130561Sobrien		  }
6853130561Sobrien		else
6854218822Sdim		  /* Symbols referenced by TLS relocs must be of type
6855218822Sdim		     STT_TLS.  So no need for .opd local sym adjust.  */
6856218822Sdim		  value = sym->st_value;
6857130561Sobrien
6858130561Sobrien		ok_tprel = FALSE;
6859130561Sobrien		is_local = FALSE;
6860130561Sobrien		if (h == NULL
6861218822Sdim		    || !h->def_dynamic)
6862130561Sobrien		  {
6863130561Sobrien		    is_local = TRUE;
6864130561Sobrien		    value += sym_sec->output_offset;
6865130561Sobrien		    value += sym_sec->output_section->vma;
6866130561Sobrien		    value -= htab->elf.tls_sec->vma;
6867130561Sobrien		    ok_tprel = (value + TP_OFFSET + ((bfd_vma) 1 << 31)
6868130561Sobrien				< (bfd_vma) 1 << 32);
6869130561Sobrien		  }
6870130561Sobrien
6871130561Sobrien		r_type = ELF64_R_TYPE (rel->r_info);
6872130561Sobrien		switch (r_type)
6873130561Sobrien		  {
6874130561Sobrien		  case R_PPC64_GOT_TLSLD16:
6875130561Sobrien		  case R_PPC64_GOT_TLSLD16_LO:
6876130561Sobrien		  case R_PPC64_GOT_TLSLD16_HI:
6877130561Sobrien		  case R_PPC64_GOT_TLSLD16_HA:
6878130561Sobrien		    /* These relocs should never be against a symbol
6879130561Sobrien		       defined in a shared lib.  Leave them alone if
6880130561Sobrien		       that turns out to be the case.  */
6881130561Sobrien		    ppc64_tlsld_got (ibfd)->refcount -= 1;
6882130561Sobrien		    if (!is_local)
6883130561Sobrien		      continue;
6884130561Sobrien
6885130561Sobrien		    /* LD -> LE */
6886130561Sobrien		    tls_set = 0;
6887130561Sobrien		    tls_clear = TLS_LD;
6888130561Sobrien		    tls_type = TLS_TLS | TLS_LD;
6889130561Sobrien		    expecting_tls_get_addr = 1;
6890130561Sobrien		    break;
6891130561Sobrien
6892130561Sobrien		  case R_PPC64_GOT_TLSGD16:
6893130561Sobrien		  case R_PPC64_GOT_TLSGD16_LO:
6894130561Sobrien		  case R_PPC64_GOT_TLSGD16_HI:
6895130561Sobrien		  case R_PPC64_GOT_TLSGD16_HA:
6896130561Sobrien		    if (ok_tprel)
6897130561Sobrien		      /* GD -> LE */
6898130561Sobrien		      tls_set = 0;
6899130561Sobrien		    else
6900130561Sobrien		      /* GD -> IE */
6901130561Sobrien		      tls_set = TLS_TLS | TLS_TPRELGD;
6902130561Sobrien		    tls_clear = TLS_GD;
6903130561Sobrien		    tls_type = TLS_TLS | TLS_GD;
6904130561Sobrien		    expecting_tls_get_addr = 1;
6905130561Sobrien		    break;
6906130561Sobrien
6907130561Sobrien		  case R_PPC64_GOT_TPREL16_DS:
6908130561Sobrien		  case R_PPC64_GOT_TPREL16_LO_DS:
6909130561Sobrien		  case R_PPC64_GOT_TPREL16_HI:
6910130561Sobrien		  case R_PPC64_GOT_TPREL16_HA:
6911130561Sobrien		    expecting_tls_get_addr = 0;
6912130561Sobrien		    if (ok_tprel)
6913130561Sobrien		      {
6914130561Sobrien			/* IE -> LE */
6915130561Sobrien			tls_set = 0;
6916130561Sobrien			tls_clear = TLS_TPREL;
6917130561Sobrien			tls_type = TLS_TLS | TLS_TPREL;
6918130561Sobrien			break;
6919130561Sobrien		      }
6920130561Sobrien		    else
6921130561Sobrien		      continue;
6922130561Sobrien
6923130561Sobrien		  case R_PPC64_REL14:
6924130561Sobrien		  case R_PPC64_REL14_BRTAKEN:
6925130561Sobrien		  case R_PPC64_REL14_BRNTAKEN:
6926130561Sobrien		  case R_PPC64_REL24:
6927130561Sobrien		    if (h != NULL
6928218822Sdim			&& (h == &htab->tls_get_addr->elf
6929218822Sdim			    || h == &htab->tls_get_addr_fd->elf))
6930130561Sobrien		      {
6931130561Sobrien			if (!expecting_tls_get_addr
6932130561Sobrien			    && rel != relstart
6933130561Sobrien			    && ((ELF64_R_TYPE (rel[-1].r_info)
6934130561Sobrien				 == R_PPC64_TOC16)
6935130561Sobrien				|| (ELF64_R_TYPE (rel[-1].r_info)
6936130561Sobrien				    == R_PPC64_TOC16_LO)))
6937130561Sobrien			  {
6938130561Sobrien			    /* Check for toc tls entries.  */
6939130561Sobrien			    char *toc_tls;
6940130561Sobrien			    int retval;
6941130561Sobrien
6942130561Sobrien			    retval = get_tls_mask (&toc_tls, NULL, &locsyms,
6943130561Sobrien						   rel - 1, ibfd);
6944130561Sobrien			    if (retval == 0)
6945130561Sobrien			      goto err_free_rel;
6946218822Sdim			    if (retval > 1 && toc_tls != NULL)
6947218822Sdim			      {
6948218822Sdim				expecting_tls_get_addr = 1;
6949218822Sdim				if (toc_ref != NULL)
6950218822Sdim				  toc_ref[toc_ref_index] = 1;
6951218822Sdim			      }
6952130561Sobrien			  }
6953130561Sobrien
6954130561Sobrien			if (expecting_tls_get_addr)
6955130561Sobrien			  {
6956130561Sobrien			    struct plt_entry *ent;
6957130561Sobrien			    for (ent = h->plt.plist; ent; ent = ent->next)
6958130561Sobrien			      if (ent->addend == 0)
6959130561Sobrien				{
6960130561Sobrien				  if (ent->plt.refcount > 0)
6961130561Sobrien				    ent->plt.refcount -= 1;
6962130561Sobrien				  break;
6963130561Sobrien				}
6964130561Sobrien			  }
6965130561Sobrien		      }
6966130561Sobrien		    expecting_tls_get_addr = 0;
6967130561Sobrien		    continue;
6968130561Sobrien
6969218822Sdim		  case R_PPC64_TOC16:
6970218822Sdim		  case R_PPC64_TOC16_LO:
6971218822Sdim		  case R_PPC64_TLS:
6972218822Sdim		    expecting_tls_get_addr = 0;
6973218822Sdim		    if (sym_sec == toc && toc != NULL)
6974218822Sdim		      {
6975218822Sdim			/* Mark this toc entry as referenced by a TLS
6976218822Sdim			   code sequence.  We can do that now in the
6977218822Sdim			   case of R_PPC64_TLS, and after checking for
6978218822Sdim			   tls_get_addr for the TOC16 relocs.  */
6979218822Sdim			if (toc_ref == NULL)
6980218822Sdim			  {
6981218822Sdim			    toc_ref = bfd_zmalloc (toc->size / 8);
6982218822Sdim			    if (toc_ref == NULL)
6983218822Sdim			      goto err_free_rel;
6984218822Sdim			  }
6985218822Sdim			if (h != NULL)
6986218822Sdim			  value = h->root.u.def.value;
6987218822Sdim			else
6988218822Sdim			  value = sym->st_value;
6989218822Sdim			value += rel->r_addend;
6990218822Sdim			BFD_ASSERT (value < toc->size && value % 8 == 0);
6991218822Sdim			toc_ref_index = value / 8;
6992218822Sdim			if (r_type == R_PPC64_TLS)
6993218822Sdim			  toc_ref[toc_ref_index] = 1;
6994218822Sdim		      }
6995218822Sdim		    continue;
6996218822Sdim
6997130561Sobrien		  case R_PPC64_TPREL64:
6998130561Sobrien		    expecting_tls_get_addr = 0;
6999218822Sdim		    if (sec != toc
7000218822Sdim			|| toc_ref == NULL
7001218822Sdim			|| !toc_ref[rel->r_offset / 8])
7002218822Sdim		      continue;
7003130561Sobrien		    if (ok_tprel)
7004130561Sobrien		      {
7005130561Sobrien			/* IE -> LE */
7006130561Sobrien			tls_set = TLS_EXPLICIT;
7007130561Sobrien			tls_clear = TLS_TPREL;
7008130561Sobrien			break;
7009130561Sobrien		      }
7010130561Sobrien		    else
7011130561Sobrien		      continue;
7012130561Sobrien
7013130561Sobrien		  case R_PPC64_DTPMOD64:
7014130561Sobrien		    expecting_tls_get_addr = 0;
7015218822Sdim		    if (sec != toc
7016218822Sdim			|| toc_ref == NULL
7017218822Sdim			|| !toc_ref[rel->r_offset / 8])
7018218822Sdim		      continue;
7019130561Sobrien		    if (rel + 1 < relend
7020130561Sobrien			&& (rel[1].r_info
7021130561Sobrien			    == ELF64_R_INFO (r_symndx, R_PPC64_DTPREL64))
7022130561Sobrien			&& rel[1].r_offset == rel->r_offset + 8)
7023130561Sobrien		      {
7024130561Sobrien			if (ok_tprel)
7025130561Sobrien			  /* GD -> LE */
7026130561Sobrien			  tls_set = TLS_EXPLICIT | TLS_GD;
7027130561Sobrien			else
7028130561Sobrien			  /* GD -> IE */
7029130561Sobrien			  tls_set = TLS_EXPLICIT | TLS_GD | TLS_TPRELGD;
7030130561Sobrien			tls_clear = TLS_GD;
7031130561Sobrien		      }
7032130561Sobrien		    else
7033130561Sobrien		      {
7034130561Sobrien			if (!is_local)
7035130561Sobrien			  continue;
7036130561Sobrien
7037130561Sobrien			/* LD -> LE */
7038130561Sobrien			tls_set = TLS_EXPLICIT;
7039130561Sobrien			tls_clear = TLS_LD;
7040130561Sobrien		      }
7041130561Sobrien		    break;
7042130561Sobrien
7043130561Sobrien		  default:
7044130561Sobrien		    expecting_tls_get_addr = 0;
7045130561Sobrien		    continue;
7046130561Sobrien		  }
7047130561Sobrien
7048130561Sobrien		if ((tls_set & TLS_EXPLICIT) == 0)
7049130561Sobrien		  {
7050130561Sobrien		    struct got_entry *ent;
7051130561Sobrien
7052130561Sobrien		    /* Adjust got entry for this reloc.  */
7053130561Sobrien		    if (h != NULL)
7054130561Sobrien		      ent = h->got.glist;
7055130561Sobrien		    else
7056130561Sobrien		      ent = elf_local_got_ents (ibfd)[r_symndx];
7057130561Sobrien
7058130561Sobrien		    for (; ent != NULL; ent = ent->next)
7059130561Sobrien		      if (ent->addend == rel->r_addend
7060130561Sobrien			  && ent->owner == ibfd
7061130561Sobrien			  && ent->tls_type == tls_type)
7062130561Sobrien			break;
7063130561Sobrien		    if (ent == NULL)
7064130561Sobrien		      abort ();
7065130561Sobrien
7066130561Sobrien		    if (tls_set == 0)
7067130561Sobrien		      {
7068130561Sobrien			/* We managed to get rid of a got entry.  */
7069130561Sobrien			if (ent->got.refcount > 0)
7070130561Sobrien			  ent->got.refcount -= 1;
7071130561Sobrien		      }
7072130561Sobrien		  }
7073218822Sdim		else
7074130561Sobrien		  {
7075218822Sdim		    /* If we got rid of a DTPMOD/DTPREL reloc pair then
7076218822Sdim		       we'll lose one or two dyn relocs.  */
7077218822Sdim		    if (!dec_dynrel_count (rel->r_info, sec, info,
7078218822Sdim					   NULL, h, sym_sec))
7079218822Sdim		      return FALSE;
7080130561Sobrien
7081218822Sdim		    if (tls_set == (TLS_EXPLICIT | TLS_GD))
7082218822Sdim		      {
7083218822Sdim			if (!dec_dynrel_count ((rel + 1)->r_info, sec, info,
7084218822Sdim					       NULL, h, sym_sec))
7085218822Sdim			  return FALSE;
7086218822Sdim		      }
7087130561Sobrien		  }
7088130561Sobrien
7089130561Sobrien		*tls_mask |= tls_set;
7090130561Sobrien		*tls_mask &= ~tls_clear;
7091130561Sobrien	      }
7092130561Sobrien
7093130561Sobrien	    if (elf_section_data (sec)->relocs != relstart)
7094130561Sobrien	      free (relstart);
7095130561Sobrien	  }
7096130561Sobrien
7097218822Sdim      if (toc_ref != NULL)
7098218822Sdim	free (toc_ref);
7099218822Sdim
7100130561Sobrien      if (locsyms != NULL
7101130561Sobrien	  && (elf_tdata (ibfd)->symtab_hdr.contents
7102130561Sobrien	      != (unsigned char *) locsyms))
7103130561Sobrien	{
7104130561Sobrien	  if (!info->keep_memory)
7105130561Sobrien	    free (locsyms);
7106130561Sobrien	  else
7107130561Sobrien	    elf_tdata (ibfd)->symtab_hdr.contents = (unsigned char *) locsyms;
7108130561Sobrien	}
7109130561Sobrien    }
7110130561Sobrien  return TRUE;
7111130561Sobrien}
7112130561Sobrien
7113218822Sdim/* Called via elf_link_hash_traverse from ppc64_elf_edit_toc to adjust
7114218822Sdim   the values of any global symbols in a toc section that has been
7115218822Sdim   edited.  Globals in toc sections should be a rarity, so this function
7116218822Sdim   sets a flag if any are found in toc sections other than the one just
7117218822Sdim   edited, so that futher hash table traversals can be avoided.  */
7118218822Sdim
7119218822Sdimstruct adjust_toc_info
7120218822Sdim{
7121218822Sdim  asection *toc;
7122218822Sdim  unsigned long *skip;
7123218822Sdim  bfd_boolean global_toc_syms;
7124218822Sdim};
7125218822Sdim
7126218822Sdimstatic bfd_boolean
7127218822Sdimadjust_toc_syms (struct elf_link_hash_entry *h, void *inf)
7128218822Sdim{
7129218822Sdim  struct ppc_link_hash_entry *eh;
7130218822Sdim  struct adjust_toc_info *toc_inf = (struct adjust_toc_info *) inf;
7131218822Sdim
7132218822Sdim  if (h->root.type == bfd_link_hash_indirect)
7133218822Sdim    return TRUE;
7134218822Sdim
7135218822Sdim  if (h->root.type == bfd_link_hash_warning)
7136218822Sdim    h = (struct elf_link_hash_entry *) h->root.u.i.link;
7137218822Sdim
7138218822Sdim  if (h->root.type != bfd_link_hash_defined
7139218822Sdim      && h->root.type != bfd_link_hash_defweak)
7140218822Sdim    return TRUE;
7141218822Sdim
7142218822Sdim  eh = (struct ppc_link_hash_entry *) h;
7143218822Sdim  if (eh->adjust_done)
7144218822Sdim    return TRUE;
7145218822Sdim
7146218822Sdim  if (eh->elf.root.u.def.section == toc_inf->toc)
7147218822Sdim    {
7148218822Sdim      unsigned long skip = toc_inf->skip[eh->elf.root.u.def.value >> 3];
7149218822Sdim      if (skip != (unsigned long) -1)
7150218822Sdim	eh->elf.root.u.def.value -= skip;
7151218822Sdim      else
7152218822Sdim	{
7153218822Sdim	  (*_bfd_error_handler)
7154218822Sdim	    (_("%s defined in removed toc entry"), eh->elf.root.root.string);
7155218822Sdim	  eh->elf.root.u.def.section = &bfd_abs_section;
7156218822Sdim	  eh->elf.root.u.def.value = 0;
7157218822Sdim	}
7158218822Sdim      eh->adjust_done = 1;
7159218822Sdim    }
7160218822Sdim  else if (strcmp (eh->elf.root.u.def.section->name, ".toc") == 0)
7161218822Sdim    toc_inf->global_toc_syms = TRUE;
7162218822Sdim
7163218822Sdim  return TRUE;
7164218822Sdim}
7165218822Sdim
7166218822Sdim/* Examine all relocs referencing .toc sections in order to remove
7167218822Sdim   unused .toc entries.  */
7168218822Sdim
7169218822Sdimbfd_boolean
7170218822Sdimppc64_elf_edit_toc (bfd *obfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
7171218822Sdim{
7172218822Sdim  bfd *ibfd;
7173218822Sdim  struct adjust_toc_info toc_inf;
7174218822Sdim
7175218822Sdim  toc_inf.global_toc_syms = TRUE;
7176218822Sdim  for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
7177218822Sdim    {
7178218822Sdim      asection *toc, *sec;
7179218822Sdim      Elf_Internal_Shdr *symtab_hdr;
7180218822Sdim      Elf_Internal_Sym *local_syms;
7181218822Sdim      struct elf_link_hash_entry **sym_hashes;
7182218822Sdim      Elf_Internal_Rela *relstart, *rel;
7183218822Sdim      unsigned long *skip, *drop;
7184218822Sdim      unsigned char *used;
7185218822Sdim      unsigned char *keep, last, some_unused;
7186218822Sdim
7187218822Sdim      toc = bfd_get_section_by_name (ibfd, ".toc");
7188218822Sdim      if (toc == NULL
7189218822Sdim	  || toc->size == 0
7190218822Sdim	  || toc->sec_info_type == ELF_INFO_TYPE_JUST_SYMS
7191218822Sdim	  || elf_discarded_section (toc))
7192218822Sdim	continue;
7193218822Sdim
7194218822Sdim      local_syms = NULL;
7195218822Sdim      symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
7196218822Sdim      sym_hashes = elf_sym_hashes (ibfd);
7197218822Sdim
7198218822Sdim      /* Look at sections dropped from the final link.  */
7199218822Sdim      skip = NULL;
7200218822Sdim      relstart = NULL;
7201218822Sdim      for (sec = ibfd->sections; sec != NULL; sec = sec->next)
7202218822Sdim	{
7203218822Sdim	  if (sec->reloc_count == 0
7204218822Sdim	      || !elf_discarded_section (sec)
7205218822Sdim	      || get_opd_info (sec)
7206218822Sdim	      || (sec->flags & SEC_ALLOC) == 0
7207218822Sdim	      || (sec->flags & SEC_DEBUGGING) != 0)
7208218822Sdim	    continue;
7209218822Sdim
7210218822Sdim	  relstart = _bfd_elf_link_read_relocs (ibfd, sec, NULL, NULL, FALSE);
7211218822Sdim	  if (relstart == NULL)
7212218822Sdim	    goto error_ret;
7213218822Sdim
7214218822Sdim	  /* Run through the relocs to see which toc entries might be
7215218822Sdim	     unused.  */
7216218822Sdim	  for (rel = relstart; rel < relstart + sec->reloc_count; ++rel)
7217218822Sdim	    {
7218218822Sdim	      enum elf_ppc64_reloc_type r_type;
7219218822Sdim	      unsigned long r_symndx;
7220218822Sdim	      asection *sym_sec;
7221218822Sdim	      struct elf_link_hash_entry *h;
7222218822Sdim	      Elf_Internal_Sym *sym;
7223218822Sdim	      bfd_vma val;
7224218822Sdim
7225218822Sdim	      r_type = ELF64_R_TYPE (rel->r_info);
7226218822Sdim	      switch (r_type)
7227218822Sdim		{
7228218822Sdim		default:
7229218822Sdim		  continue;
7230218822Sdim
7231218822Sdim		case R_PPC64_TOC16:
7232218822Sdim		case R_PPC64_TOC16_LO:
7233218822Sdim		case R_PPC64_TOC16_HI:
7234218822Sdim		case R_PPC64_TOC16_HA:
7235218822Sdim		case R_PPC64_TOC16_DS:
7236218822Sdim		case R_PPC64_TOC16_LO_DS:
7237218822Sdim		  break;
7238218822Sdim		}
7239218822Sdim
7240218822Sdim	      r_symndx = ELF64_R_SYM (rel->r_info);
7241218822Sdim	      if (!get_sym_h (&h, &sym, &sym_sec, NULL, &local_syms,
7242218822Sdim			      r_symndx, ibfd))
7243218822Sdim		goto error_ret;
7244218822Sdim
7245218822Sdim	      if (sym_sec != toc)
7246218822Sdim		continue;
7247218822Sdim
7248218822Sdim	      if (h != NULL)
7249218822Sdim		val = h->root.u.def.value;
7250218822Sdim	      else
7251218822Sdim		val = sym->st_value;
7252218822Sdim	      val += rel->r_addend;
7253218822Sdim
7254218822Sdim	      if (val >= toc->size)
7255218822Sdim		continue;
7256218822Sdim
7257218822Sdim	      /* Anything in the toc ought to be aligned to 8 bytes.
7258218822Sdim		 If not, don't mark as unused.  */
7259218822Sdim	      if (val & 7)
7260218822Sdim		continue;
7261218822Sdim
7262218822Sdim	      if (skip == NULL)
7263218822Sdim		{
7264218822Sdim		  skip = bfd_zmalloc (sizeof (*skip) * (toc->size + 7) / 8);
7265218822Sdim		  if (skip == NULL)
7266218822Sdim		    goto error_ret;
7267218822Sdim		}
7268218822Sdim
7269218822Sdim	      skip[val >> 3] = 1;
7270218822Sdim	    }
7271218822Sdim
7272218822Sdim	  if (elf_section_data (sec)->relocs != relstart)
7273218822Sdim	    free (relstart);
7274218822Sdim	}
7275218822Sdim
7276218822Sdim      if (skip == NULL)
7277218822Sdim	continue;
7278218822Sdim
7279218822Sdim      used = bfd_zmalloc (sizeof (*used) * (toc->size + 7) / 8);
7280218822Sdim      if (used == NULL)
7281218822Sdim	{
7282218822Sdim	error_ret:
7283218822Sdim	  if (local_syms != NULL
7284218822Sdim	      && symtab_hdr->contents != (unsigned char *) local_syms)
7285218822Sdim	    free (local_syms);
7286218822Sdim	  if (sec != NULL
7287218822Sdim	      && relstart != NULL
7288218822Sdim	      && elf_section_data (sec)->relocs != relstart)
7289218822Sdim	    free (relstart);
7290218822Sdim	  if (skip != NULL)
7291218822Sdim	    free (skip);
7292218822Sdim	  return FALSE;
7293218822Sdim	}
7294218822Sdim
7295218822Sdim      /* Now check all kept sections that might reference the toc.
7296218822Sdim	 Check the toc itself last.  */
7297218822Sdim      for (sec = (ibfd->sections == toc && toc->next ? toc->next
7298218822Sdim		  : ibfd->sections);
7299218822Sdim	   sec != NULL;
7300218822Sdim	   sec = (sec == toc ? NULL
7301218822Sdim		  : sec->next == NULL ? toc
7302218822Sdim		  : sec->next == toc && toc->next ? toc->next
7303218822Sdim		  : sec->next))
7304218822Sdim	{
7305218822Sdim	  int repeat;
7306218822Sdim
7307218822Sdim	  if (sec->reloc_count == 0
7308218822Sdim	      || elf_discarded_section (sec)
7309218822Sdim	      || get_opd_info (sec)
7310218822Sdim	      || (sec->flags & SEC_ALLOC) == 0
7311218822Sdim	      || (sec->flags & SEC_DEBUGGING) != 0)
7312218822Sdim	    continue;
7313218822Sdim
7314218822Sdim	  relstart = _bfd_elf_link_read_relocs (ibfd, sec, NULL, NULL, TRUE);
7315218822Sdim	  if (relstart == NULL)
7316218822Sdim	    goto error_ret;
7317218822Sdim
7318218822Sdim	  /* Mark toc entries referenced as used.  */
7319218822Sdim	  repeat = 0;
7320218822Sdim	  do
7321218822Sdim	    for (rel = relstart; rel < relstart + sec->reloc_count; ++rel)
7322218822Sdim	      {
7323218822Sdim		enum elf_ppc64_reloc_type r_type;
7324218822Sdim		unsigned long r_symndx;
7325218822Sdim		asection *sym_sec;
7326218822Sdim		struct elf_link_hash_entry *h;
7327218822Sdim		Elf_Internal_Sym *sym;
7328218822Sdim		bfd_vma val;
7329218822Sdim
7330218822Sdim		r_type = ELF64_R_TYPE (rel->r_info);
7331218822Sdim		switch (r_type)
7332218822Sdim		  {
7333218822Sdim		  case R_PPC64_TOC16:
7334218822Sdim		  case R_PPC64_TOC16_LO:
7335218822Sdim		  case R_PPC64_TOC16_HI:
7336218822Sdim		  case R_PPC64_TOC16_HA:
7337218822Sdim		  case R_PPC64_TOC16_DS:
7338218822Sdim		  case R_PPC64_TOC16_LO_DS:
7339218822Sdim		    /* In case we're taking addresses of toc entries.  */
7340218822Sdim		  case R_PPC64_ADDR64:
7341218822Sdim		    break;
7342218822Sdim
7343218822Sdim		  default:
7344218822Sdim		    continue;
7345218822Sdim		  }
7346218822Sdim
7347218822Sdim		r_symndx = ELF64_R_SYM (rel->r_info);
7348218822Sdim		if (!get_sym_h (&h, &sym, &sym_sec, NULL, &local_syms,
7349218822Sdim				r_symndx, ibfd))
7350218822Sdim		  {
7351218822Sdim		    free (used);
7352218822Sdim		    goto error_ret;
7353218822Sdim		  }
7354218822Sdim
7355218822Sdim		if (sym_sec != toc)
7356218822Sdim		  continue;
7357218822Sdim
7358218822Sdim		if (h != NULL)
7359218822Sdim		  val = h->root.u.def.value;
7360218822Sdim		else
7361218822Sdim		  val = sym->st_value;
7362218822Sdim		val += rel->r_addend;
7363218822Sdim
7364218822Sdim		if (val >= toc->size)
7365218822Sdim		  continue;
7366218822Sdim
7367218822Sdim		/* For the toc section, we only mark as used if
7368218822Sdim		   this entry itself isn't unused.  */
7369218822Sdim		if (sec == toc
7370218822Sdim		    && !used[val >> 3]
7371218822Sdim		    && (used[rel->r_offset >> 3]
7372218822Sdim			|| !skip[rel->r_offset >> 3]))
7373218822Sdim		  /* Do all the relocs again, to catch reference
7374218822Sdim		     chains.  */
7375218822Sdim		  repeat = 1;
7376218822Sdim
7377218822Sdim		used[val >> 3] = 1;
7378218822Sdim	      }
7379218822Sdim	  while (repeat);
7380218822Sdim	}
7381218822Sdim
7382218822Sdim      /* Merge the used and skip arrays.  Assume that TOC
7383218822Sdim	 doublewords not appearing as either used or unused belong
7384218822Sdim	 to to an entry more than one doubleword in size.  */
7385218822Sdim      for (drop = skip, keep = used, last = 0, some_unused = 0;
7386218822Sdim	   drop < skip + (toc->size + 7) / 8;
7387218822Sdim	   ++drop, ++keep)
7388218822Sdim	{
7389218822Sdim	  if (*keep)
7390218822Sdim	    {
7391218822Sdim	      *drop = 0;
7392218822Sdim	      last = 0;
7393218822Sdim	    }
7394218822Sdim	  else if (*drop)
7395218822Sdim	    {
7396218822Sdim	      some_unused = 1;
7397218822Sdim	      last = 1;
7398218822Sdim	    }
7399218822Sdim	  else
7400218822Sdim	    *drop = last;
7401218822Sdim	}
7402218822Sdim
7403218822Sdim      free (used);
7404218822Sdim
7405218822Sdim      if (some_unused)
7406218822Sdim	{
7407218822Sdim	  bfd_byte *contents, *src;
7408218822Sdim	  unsigned long off;
7409218822Sdim
7410218822Sdim	  /* Shuffle the toc contents, and at the same time convert the
7411218822Sdim	     skip array from booleans into offsets.  */
7412218822Sdim	  if (!bfd_malloc_and_get_section (ibfd, toc, &contents))
7413218822Sdim	    goto error_ret;
7414218822Sdim
7415218822Sdim	  elf_section_data (toc)->this_hdr.contents = contents;
7416218822Sdim
7417218822Sdim	  for (src = contents, off = 0, drop = skip;
7418218822Sdim	       src < contents + toc->size;
7419218822Sdim	       src += 8, ++drop)
7420218822Sdim	    {
7421218822Sdim	      if (*drop)
7422218822Sdim		{
7423218822Sdim		  *drop = (unsigned long) -1;
7424218822Sdim		  off += 8;
7425218822Sdim		}
7426218822Sdim	      else if (off != 0)
7427218822Sdim		{
7428218822Sdim		  *drop = off;
7429218822Sdim		  memcpy (src - off, src, 8);
7430218822Sdim		}
7431218822Sdim	    }
7432218822Sdim	  toc->rawsize = toc->size;
7433218822Sdim	  toc->size = src - contents - off;
7434218822Sdim
7435218822Sdim	  if (toc->reloc_count != 0)
7436218822Sdim	    {
7437218822Sdim	      Elf_Internal_Rela *wrel;
7438218822Sdim	      bfd_size_type sz;
7439218822Sdim
7440218822Sdim	      /* Read toc relocs.  */
7441218822Sdim	      relstart = _bfd_elf_link_read_relocs (ibfd, toc, NULL, NULL,
7442218822Sdim						    TRUE);
7443218822Sdim	      if (relstart == NULL)
7444218822Sdim		goto error_ret;
7445218822Sdim
7446218822Sdim	      /* Remove unused toc relocs, and adjust those we keep.  */
7447218822Sdim	      wrel = relstart;
7448218822Sdim	      for (rel = relstart; rel < relstart + toc->reloc_count; ++rel)
7449218822Sdim		if (skip[rel->r_offset >> 3] != (unsigned long) -1)
7450218822Sdim		  {
7451218822Sdim		    wrel->r_offset = rel->r_offset - skip[rel->r_offset >> 3];
7452218822Sdim		    wrel->r_info = rel->r_info;
7453218822Sdim		    wrel->r_addend = rel->r_addend;
7454218822Sdim		    ++wrel;
7455218822Sdim		  }
7456218822Sdim		else if (!dec_dynrel_count (rel->r_info, toc, info,
7457218822Sdim					    &local_syms, NULL, NULL))
7458218822Sdim		  goto error_ret;
7459218822Sdim
7460218822Sdim	      toc->reloc_count = wrel - relstart;
7461218822Sdim	      sz = elf_section_data (toc)->rel_hdr.sh_entsize;
7462218822Sdim	      elf_section_data (toc)->rel_hdr.sh_size = toc->reloc_count * sz;
7463218822Sdim	      BFD_ASSERT (elf_section_data (toc)->rel_hdr2 == NULL);
7464218822Sdim	    }
7465218822Sdim
7466218822Sdim	  /* Adjust addends for relocs against the toc section sym.  */
7467218822Sdim	  for (sec = ibfd->sections; sec != NULL; sec = sec->next)
7468218822Sdim	    {
7469218822Sdim	      if (sec->reloc_count == 0
7470218822Sdim		  || elf_discarded_section (sec))
7471218822Sdim		continue;
7472218822Sdim
7473218822Sdim	      relstart = _bfd_elf_link_read_relocs (ibfd, sec, NULL, NULL,
7474218822Sdim						    TRUE);
7475218822Sdim	      if (relstart == NULL)
7476218822Sdim		goto error_ret;
7477218822Sdim
7478218822Sdim	      for (rel = relstart; rel < relstart + sec->reloc_count; ++rel)
7479218822Sdim		{
7480218822Sdim		  enum elf_ppc64_reloc_type r_type;
7481218822Sdim		  unsigned long r_symndx;
7482218822Sdim		  asection *sym_sec;
7483218822Sdim		  struct elf_link_hash_entry *h;
7484218822Sdim		  Elf_Internal_Sym *sym;
7485218822Sdim
7486218822Sdim		  r_type = ELF64_R_TYPE (rel->r_info);
7487218822Sdim		  switch (r_type)
7488218822Sdim		    {
7489218822Sdim		    default:
7490218822Sdim		      continue;
7491218822Sdim
7492218822Sdim		    case R_PPC64_TOC16:
7493218822Sdim		    case R_PPC64_TOC16_LO:
7494218822Sdim		    case R_PPC64_TOC16_HI:
7495218822Sdim		    case R_PPC64_TOC16_HA:
7496218822Sdim		    case R_PPC64_TOC16_DS:
7497218822Sdim		    case R_PPC64_TOC16_LO_DS:
7498218822Sdim		    case R_PPC64_ADDR64:
7499218822Sdim		      break;
7500218822Sdim		    }
7501218822Sdim
7502218822Sdim		  r_symndx = ELF64_R_SYM (rel->r_info);
7503218822Sdim		  if (!get_sym_h (&h, &sym, &sym_sec, NULL, &local_syms,
7504218822Sdim				  r_symndx, ibfd))
7505218822Sdim		    goto error_ret;
7506218822Sdim
7507218822Sdim		  if (sym_sec != toc || h != NULL || sym->st_value != 0)
7508218822Sdim		    continue;
7509218822Sdim
7510218822Sdim		  rel->r_addend -= skip[rel->r_addend >> 3];
7511218822Sdim		}
7512218822Sdim	    }
7513218822Sdim
7514218822Sdim	  /* We shouldn't have local or global symbols defined in the TOC,
7515218822Sdim	     but handle them anyway.  */
7516218822Sdim	  if (local_syms != NULL)
7517218822Sdim	    {
7518218822Sdim	      Elf_Internal_Sym *sym;
7519218822Sdim
7520218822Sdim	      for (sym = local_syms;
7521218822Sdim		   sym < local_syms + symtab_hdr->sh_info;
7522218822Sdim		   ++sym)
7523218822Sdim		if (sym->st_shndx != SHN_UNDEF
7524218822Sdim		    && (sym->st_shndx < SHN_LORESERVE
7525218822Sdim			|| sym->st_shndx > SHN_HIRESERVE)
7526218822Sdim		    && sym->st_value != 0
7527218822Sdim		    && bfd_section_from_elf_index (ibfd, sym->st_shndx) == toc)
7528218822Sdim		  {
7529218822Sdim		    if (skip[sym->st_value >> 3] != (unsigned long) -1)
7530218822Sdim		      sym->st_value -= skip[sym->st_value >> 3];
7531218822Sdim		    else
7532218822Sdim		      {
7533218822Sdim			(*_bfd_error_handler)
7534218822Sdim			  (_("%s defined in removed toc entry"),
7535218822Sdim			   bfd_elf_sym_name (ibfd, symtab_hdr, sym,
7536218822Sdim					     NULL));
7537218822Sdim			sym->st_value = 0;
7538218822Sdim			sym->st_shndx = SHN_ABS;
7539218822Sdim		      }
7540218822Sdim		    symtab_hdr->contents = (unsigned char *) local_syms;
7541218822Sdim		  }
7542218822Sdim	    }
7543218822Sdim
7544218822Sdim	  /* Finally, adjust any global syms defined in the toc.  */
7545218822Sdim	  if (toc_inf.global_toc_syms)
7546218822Sdim	    {
7547218822Sdim	      toc_inf.toc = toc;
7548218822Sdim	      toc_inf.skip = skip;
7549218822Sdim	      toc_inf.global_toc_syms = FALSE;
7550218822Sdim	      elf_link_hash_traverse (elf_hash_table (info), adjust_toc_syms,
7551218822Sdim				      &toc_inf);
7552218822Sdim	    }
7553218822Sdim	}
7554218822Sdim
7555218822Sdim      if (local_syms != NULL
7556218822Sdim	  && symtab_hdr->contents != (unsigned char *) local_syms)
7557218822Sdim	{
7558218822Sdim	  if (!info->keep_memory)
7559218822Sdim	    free (local_syms);
7560218822Sdim	  else
7561218822Sdim	    symtab_hdr->contents = (unsigned char *) local_syms;
7562218822Sdim	}
7563218822Sdim      free (skip);
7564218822Sdim    }
7565218822Sdim
7566218822Sdim  return TRUE;
7567218822Sdim}
7568218822Sdim
756989857Sobrien/* Allocate space in .plt, .got and associated reloc sections for
757089857Sobrien   dynamic relocs.  */
757189857Sobrien
7572130561Sobrienstatic bfd_boolean
7573130561Sobrienallocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
757489857Sobrien{
757589857Sobrien  struct bfd_link_info *info;
757689857Sobrien  struct ppc_link_hash_table *htab;
757789857Sobrien  asection *s;
757889857Sobrien  struct ppc_link_hash_entry *eh;
757989857Sobrien  struct ppc_dyn_relocs *p;
7580130561Sobrien  struct got_entry *gent;
758189857Sobrien
758294536Sobrien  if (h->root.type == bfd_link_hash_indirect)
7583130561Sobrien    return TRUE;
758489857Sobrien
758594536Sobrien  if (h->root.type == bfd_link_hash_warning)
758694536Sobrien    h = (struct elf_link_hash_entry *) h->root.u.i.link;
758794536Sobrien
758889857Sobrien  info = (struct bfd_link_info *) inf;
758989857Sobrien  htab = ppc_hash_table (info);
759089857Sobrien
759189857Sobrien  if (htab->elf.dynamic_sections_created
7592130561Sobrien      && h->dynindx != -1
7593130561Sobrien      && WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info->shared, h))
759489857Sobrien    {
7595130561Sobrien      struct plt_entry *pent;
7596130561Sobrien      bfd_boolean doneone = FALSE;
7597130561Sobrien      for (pent = h->plt.plist; pent != NULL; pent = pent->next)
7598130561Sobrien	if (pent->plt.refcount > 0)
7599130561Sobrien	  {
7600130561Sobrien	    /* If this is the first .plt entry, make room for the special
7601130561Sobrien	       first entry.  */
7602130561Sobrien	    s = htab->plt;
7603218822Sdim	    if (s->size == 0)
7604218822Sdim	      s->size += PLT_INITIAL_ENTRY_SIZE;
760589857Sobrien
7606218822Sdim	    pent->plt.offset = s->size;
760789857Sobrien
7608130561Sobrien	    /* Make room for this entry.  */
7609218822Sdim	    s->size += PLT_ENTRY_SIZE;
761089857Sobrien
7611130561Sobrien	    /* Make room for the .glink code.  */
7612130561Sobrien	    s = htab->glink;
7613218822Sdim	    if (s->size == 0)
7614218822Sdim	      s->size += GLINK_CALL_STUB_SIZE;
7615130561Sobrien	    /* We need bigger stubs past index 32767.  */
7616218822Sdim	    if (s->size >= GLINK_CALL_STUB_SIZE + 32768*2*4)
7617218822Sdim	      s->size += 4;
7618218822Sdim	    s->size += 2*4;
761989857Sobrien
7620130561Sobrien	    /* We also need to make an entry in the .rela.plt section.  */
7621130561Sobrien	    s = htab->relplt;
7622218822Sdim	    s->size += sizeof (Elf64_External_Rela);
7623130561Sobrien	    doneone = TRUE;
7624130561Sobrien	  }
7625130561Sobrien	else
7626130561Sobrien	  pent->plt.offset = (bfd_vma) -1;
7627130561Sobrien      if (!doneone)
762889857Sobrien	{
7629130561Sobrien	  h->plt.plist = NULL;
7630218822Sdim	  h->needs_plt = 0;
763189857Sobrien	}
763289857Sobrien    }
763389857Sobrien  else
763489857Sobrien    {
7635130561Sobrien      h->plt.plist = NULL;
7636218822Sdim      h->needs_plt = 0;
763789857Sobrien    }
763889857Sobrien
7639130561Sobrien  eh = (struct ppc_link_hash_entry *) h;
7640130561Sobrien  /* Run through the TLS GD got entries first if we're changing them
7641130561Sobrien     to TPREL.  */
7642130561Sobrien  if ((eh->tls_mask & TLS_TPRELGD) != 0)
7643130561Sobrien    for (gent = h->got.glist; gent != NULL; gent = gent->next)
7644130561Sobrien      if (gent->got.refcount > 0
7645130561Sobrien	  && (gent->tls_type & TLS_GD) != 0)
7646130561Sobrien	{
7647130561Sobrien	  /* This was a GD entry that has been converted to TPREL.  If
7648130561Sobrien	     there happens to be a TPREL entry we can use that one.  */
7649130561Sobrien	  struct got_entry *ent;
7650130561Sobrien	  for (ent = h->got.glist; ent != NULL; ent = ent->next)
7651130561Sobrien	    if (ent->got.refcount > 0
7652130561Sobrien		&& (ent->tls_type & TLS_TPREL) != 0
7653130561Sobrien		&& ent->addend == gent->addend
7654130561Sobrien		&& ent->owner == gent->owner)
7655130561Sobrien	      {
7656130561Sobrien		gent->got.refcount = 0;
7657130561Sobrien		break;
7658130561Sobrien	      }
765989857Sobrien
7660130561Sobrien	  /* If not, then we'll be using our own TPREL entry.  */
7661130561Sobrien	  if (gent->got.refcount != 0)
7662130561Sobrien	    gent->tls_type = TLS_TLS | TLS_TPREL;
766389857Sobrien	}
766489857Sobrien
7665130561Sobrien  for (gent = h->got.glist; gent != NULL; gent = gent->next)
7666130561Sobrien    if (gent->got.refcount > 0)
7667130561Sobrien      {
7668130561Sobrien	bfd_boolean dyn;
766989857Sobrien
7670130561Sobrien	/* Make sure this symbol is output as a dynamic symbol.
7671130561Sobrien	   Undefined weak syms won't yet be marked as dynamic,
7672130561Sobrien	   nor will all TLS symbols.  */
7673130561Sobrien	if (h->dynindx == -1
7674218822Sdim	    && !h->forced_local)
7675130561Sobrien	  {
7676130561Sobrien	    if (! bfd_elf_link_record_dynamic_symbol (info, h))
7677130561Sobrien	      return FALSE;
7678130561Sobrien	  }
7679130561Sobrien
7680130561Sobrien	if ((gent->tls_type & TLS_LD) != 0
7681218822Sdim	    && !h->def_dynamic)
7682130561Sobrien	  {
7683130561Sobrien	    gent->got.offset = ppc64_tlsld_got (gent->owner)->offset;
7684130561Sobrien	    continue;
7685130561Sobrien	  }
7686130561Sobrien
7687130561Sobrien	s = ppc64_elf_tdata (gent->owner)->got;
7688218822Sdim	gent->got.offset = s->size;
7689218822Sdim	s->size
7690130561Sobrien	  += (gent->tls_type & eh->tls_mask & (TLS_GD | TLS_LD)) ? 16 : 8;
7691130561Sobrien	dyn = htab->elf.dynamic_sections_created;
7692130561Sobrien	if ((info->shared
7693130561Sobrien	     || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h))
7694130561Sobrien	    && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
7695130561Sobrien		|| h->root.type != bfd_link_hash_undefweak))
7696218822Sdim	  ppc64_elf_tdata (gent->owner)->relgot->size
7697130561Sobrien	    += (gent->tls_type & eh->tls_mask & TLS_GD
7698130561Sobrien		? 2 * sizeof (Elf64_External_Rela)
7699130561Sobrien		: sizeof (Elf64_External_Rela));
7700130561Sobrien      }
7701130561Sobrien    else
7702130561Sobrien      gent->got.offset = (bfd_vma) -1;
7703130561Sobrien
770489857Sobrien  if (eh->dyn_relocs == NULL)
7705130561Sobrien    return TRUE;
770689857Sobrien
770789857Sobrien  /* In the shared -Bsymbolic case, discard space allocated for
770889857Sobrien     dynamic pc-relative relocs against symbols which turn out to be
770989857Sobrien     defined in regular objects.  For the normal shared case, discard
771089857Sobrien     space for relocs that have become local due to symbol visibility
771189857Sobrien     changes.  */
771289857Sobrien
771389857Sobrien  if (info->shared)
771489857Sobrien    {
7715130561Sobrien      /* Relocs that use pc_count are those that appear on a call insn,
7716130561Sobrien	 or certain REL relocs (see MUST_BE_DYN_RELOC) that can be
7717130561Sobrien	 generated via assembly.  We want calls to protected symbols to
7718130561Sobrien	 resolve directly to the function rather than going via the plt.
7719130561Sobrien	 If people want function pointer comparisons to work as expected
7720130561Sobrien	 then they should avoid writing weird assembly.  */
7721130561Sobrien      if (SYMBOL_CALLS_LOCAL (info, h))
772289857Sobrien	{
772389857Sobrien	  struct ppc_dyn_relocs **pp;
772489857Sobrien
772589857Sobrien	  for (pp = &eh->dyn_relocs; (p = *pp) != NULL; )
772689857Sobrien	    {
772789857Sobrien	      p->count -= p->pc_count;
772889857Sobrien	      p->pc_count = 0;
772989857Sobrien	      if (p->count == 0)
773089857Sobrien		*pp = p->next;
773189857Sobrien	      else
773289857Sobrien		pp = &p->next;
773389857Sobrien	    }
773489857Sobrien	}
7735130561Sobrien
7736130561Sobrien      /* Also discard relocs on undefined weak syms with non-default
7737130561Sobrien	 visibility.  */
7738218822Sdim      if (eh->dyn_relocs != NULL
7739130561Sobrien	  && h->root.type == bfd_link_hash_undefweak)
7740218822Sdim	{
7741218822Sdim	  if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
7742218822Sdim	    eh->dyn_relocs = NULL;
7743218822Sdim
7744218822Sdim	  /* Make sure this symbol is output as a dynamic symbol.
7745218822Sdim	     Undefined weak syms won't yet be marked as dynamic.  */
7746218822Sdim	  else if (h->dynindx == -1
7747218822Sdim		   && !h->forced_local)
7748218822Sdim	    {
7749218822Sdim	      if (! bfd_elf_link_record_dynamic_symbol (info, h))
7750218822Sdim		return FALSE;
7751218822Sdim	    }
7752218822Sdim	}
775389857Sobrien    }
7754130561Sobrien  else if (ELIMINATE_COPY_RELOCS)
775589857Sobrien    {
775689857Sobrien      /* For the non-shared case, discard space for relocs against
775789857Sobrien	 symbols which turn out to need copy relocs or are not
775889857Sobrien	 dynamic.  */
775989857Sobrien
7760218822Sdim      if (!h->non_got_ref
7761218822Sdim	  && h->def_dynamic
7762218822Sdim	  && !h->def_regular)
776389857Sobrien	{
776489857Sobrien	  /* Make sure this symbol is output as a dynamic symbol.
776589857Sobrien	     Undefined weak syms won't yet be marked as dynamic.  */
776689857Sobrien	  if (h->dynindx == -1
7767218822Sdim	      && !h->forced_local)
776889857Sobrien	    {
7769130561Sobrien	      if (! bfd_elf_link_record_dynamic_symbol (info, h))
7770130561Sobrien		return FALSE;
777189857Sobrien	    }
777289857Sobrien
777389857Sobrien	  /* If that succeeded, we know we'll be keeping all the
777489857Sobrien	     relocs.  */
777589857Sobrien	  if (h->dynindx != -1)
777689857Sobrien	    goto keep;
777789857Sobrien	}
777889857Sobrien
777989857Sobrien      eh->dyn_relocs = NULL;
778089857Sobrien
778189857Sobrien    keep: ;
778289857Sobrien    }
778389857Sobrien
778489857Sobrien  /* Finally, allocate space.  */
778589857Sobrien  for (p = eh->dyn_relocs; p != NULL; p = p->next)
778689857Sobrien    {
778789857Sobrien      asection *sreloc = elf_section_data (p->sec)->sreloc;
7788218822Sdim      sreloc->size += p->count * sizeof (Elf64_External_Rela);
778989857Sobrien    }
779089857Sobrien
7791130561Sobrien  return TRUE;
779289857Sobrien}
779389857Sobrien
779489857Sobrien/* Find any dynamic relocs that apply to read-only sections.  */
779589857Sobrien
7796130561Sobrienstatic bfd_boolean
7797130561Sobrienreadonly_dynrelocs (struct elf_link_hash_entry *h, void *inf)
779889857Sobrien{
779989857Sobrien  struct ppc_link_hash_entry *eh;
780089857Sobrien  struct ppc_dyn_relocs *p;
780189857Sobrien
780294536Sobrien  if (h->root.type == bfd_link_hash_warning)
780394536Sobrien    h = (struct elf_link_hash_entry *) h->root.u.i.link;
780494536Sobrien
780589857Sobrien  eh = (struct ppc_link_hash_entry *) h;
780689857Sobrien  for (p = eh->dyn_relocs; p != NULL; p = p->next)
780789857Sobrien    {
780889857Sobrien      asection *s = p->sec->output_section;
780989857Sobrien
781089857Sobrien      if (s != NULL && (s->flags & SEC_READONLY) != 0)
781189857Sobrien	{
7812130561Sobrien	  struct bfd_link_info *info = inf;
781389857Sobrien
781489857Sobrien	  info->flags |= DF_TEXTREL;
781589857Sobrien
781689857Sobrien	  /* Not an error, just cut short the traversal.  */
7817130561Sobrien	  return FALSE;
781889857Sobrien	}
781989857Sobrien    }
7820130561Sobrien  return TRUE;
782189857Sobrien}
782289857Sobrien
782389857Sobrien/* Set the sizes of the dynamic sections.  */
782489857Sobrien
7825130561Sobrienstatic bfd_boolean
7826130561Sobrienppc64_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
7827130561Sobrien				 struct bfd_link_info *info)
782889857Sobrien{
782989857Sobrien  struct ppc_link_hash_table *htab;
783089857Sobrien  bfd *dynobj;
783189857Sobrien  asection *s;
7832130561Sobrien  bfd_boolean relocs;
783389857Sobrien  bfd *ibfd;
783489857Sobrien
783589857Sobrien  htab = ppc_hash_table (info);
783689857Sobrien  dynobj = htab->elf.dynobj;
783789857Sobrien  if (dynobj == NULL)
783889857Sobrien    abort ();
783989857Sobrien
784089857Sobrien  if (htab->elf.dynamic_sections_created)
784189857Sobrien    {
784289857Sobrien      /* Set the contents of the .interp section to the interpreter.  */
7843130561Sobrien      if (info->executable)
784489857Sobrien	{
784589857Sobrien	  s = bfd_get_section_by_name (dynobj, ".interp");
784689857Sobrien	  if (s == NULL)
784789857Sobrien	    abort ();
7848218822Sdim	  s->size = sizeof ELF_DYNAMIC_INTERPRETER;
784989857Sobrien	  s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
785089857Sobrien	}
785189857Sobrien    }
785289857Sobrien
785389857Sobrien  /* Set up .got offsets for local syms, and space for local dynamic
785489857Sobrien     relocs.  */
785589857Sobrien  for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
785689857Sobrien    {
7857130561Sobrien      struct got_entry **lgot_ents;
7858130561Sobrien      struct got_entry **end_lgot_ents;
7859130561Sobrien      char *lgot_masks;
786089857Sobrien      bfd_size_type locsymcount;
786189857Sobrien      Elf_Internal_Shdr *symtab_hdr;
786289857Sobrien      asection *srel;
786389857Sobrien
7864218822Sdim      if (!is_ppc64_elf_target (ibfd->xvec))
786589857Sobrien	continue;
786689857Sobrien
7867130561Sobrien      if (ppc64_tlsld_got (ibfd)->refcount > 0)
7868130561Sobrien	{
7869130561Sobrien	  s = ppc64_elf_tdata (ibfd)->got;
7870218822Sdim	  ppc64_tlsld_got (ibfd)->offset = s->size;
7871218822Sdim	  s->size += 16;
7872130561Sobrien	  if (info->shared)
7873130561Sobrien	    {
7874130561Sobrien	      srel = ppc64_elf_tdata (ibfd)->relgot;
7875218822Sdim	      srel->size += sizeof (Elf64_External_Rela);
7876130561Sobrien	    }
7877130561Sobrien	}
7878130561Sobrien      else
7879130561Sobrien	ppc64_tlsld_got (ibfd)->offset = (bfd_vma) -1;
7880130561Sobrien
788189857Sobrien      for (s = ibfd->sections; s != NULL; s = s->next)
788289857Sobrien	{
788389857Sobrien	  struct ppc_dyn_relocs *p;
788489857Sobrien
7885218822Sdim	  for (p = elf_section_data (s)->local_dynrel; p != NULL; p = p->next)
788689857Sobrien	    {
788789857Sobrien	      if (!bfd_is_abs_section (p->sec)
788889857Sobrien		  && bfd_is_abs_section (p->sec->output_section))
788989857Sobrien		{
789089857Sobrien		  /* Input section has been discarded, either because
789189857Sobrien		     it is a copy of a linkonce section or due to
789289857Sobrien		     linker script /DISCARD/, so we'll be discarding
789389857Sobrien		     the relocs too.  */
789489857Sobrien		}
789591041Sobrien	      else if (p->count != 0)
789689857Sobrien		{
789789857Sobrien		  srel = elf_section_data (p->sec)->sreloc;
7898218822Sdim		  srel->size += p->count * sizeof (Elf64_External_Rela);
789991041Sobrien		  if ((p->sec->output_section->flags & SEC_READONLY) != 0)
790091041Sobrien		    info->flags |= DF_TEXTREL;
790189857Sobrien		}
790289857Sobrien	    }
790389857Sobrien	}
790489857Sobrien
7905130561Sobrien      lgot_ents = elf_local_got_ents (ibfd);
7906130561Sobrien      if (!lgot_ents)
790789857Sobrien	continue;
790889857Sobrien
790989857Sobrien      symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
791089857Sobrien      locsymcount = symtab_hdr->sh_info;
7911130561Sobrien      end_lgot_ents = lgot_ents + locsymcount;
7912130561Sobrien      lgot_masks = (char *) end_lgot_ents;
7913130561Sobrien      s = ppc64_elf_tdata (ibfd)->got;
7914130561Sobrien      srel = ppc64_elf_tdata (ibfd)->relgot;
7915130561Sobrien      for (; lgot_ents < end_lgot_ents; ++lgot_ents, ++lgot_masks)
791689857Sobrien	{
7917130561Sobrien	  struct got_entry *ent;
7918130561Sobrien
7919130561Sobrien	  for (ent = *lgot_ents; ent != NULL; ent = ent->next)
7920130561Sobrien	    if (ent->got.refcount > 0)
7921130561Sobrien	      {
7922130561Sobrien		if ((ent->tls_type & *lgot_masks & TLS_LD) != 0)
7923130561Sobrien		  {
7924130561Sobrien		    if (ppc64_tlsld_got (ibfd)->offset == (bfd_vma) -1)
7925130561Sobrien		      {
7926218822Sdim			ppc64_tlsld_got (ibfd)->offset = s->size;
7927218822Sdim			s->size += 16;
7928130561Sobrien			if (info->shared)
7929218822Sdim			  srel->size += sizeof (Elf64_External_Rela);
7930130561Sobrien		      }
7931130561Sobrien		    ent->got.offset = ppc64_tlsld_got (ibfd)->offset;
7932130561Sobrien		  }
7933130561Sobrien		else
7934130561Sobrien		  {
7935218822Sdim		    ent->got.offset = s->size;
7936130561Sobrien		    if ((ent->tls_type & *lgot_masks & TLS_GD) != 0)
7937130561Sobrien		      {
7938218822Sdim			s->size += 16;
7939130561Sobrien			if (info->shared)
7940218822Sdim			  srel->size += 2 * sizeof (Elf64_External_Rela);
7941130561Sobrien		      }
7942130561Sobrien		    else
7943130561Sobrien		      {
7944218822Sdim			s->size += 8;
7945130561Sobrien			if (info->shared)
7946218822Sdim			  srel->size += sizeof (Elf64_External_Rela);
7947130561Sobrien		      }
7948130561Sobrien		  }
7949130561Sobrien	      }
7950130561Sobrien	    else
7951130561Sobrien	      ent->got.offset = (bfd_vma) -1;
795289857Sobrien	}
795389857Sobrien    }
795489857Sobrien
795589857Sobrien  /* Allocate global sym .plt and .got entries, and space for global
795689857Sobrien     sym dynamic relocs.  */
7957130561Sobrien  elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, info);
795889857Sobrien
795989857Sobrien  /* We now have determined the sizes of the various dynamic sections.
796089857Sobrien     Allocate memory for them.  */
7961130561Sobrien  relocs = FALSE;
796289857Sobrien  for (s = dynobj->sections; s != NULL; s = s->next)
796389857Sobrien    {
796489857Sobrien      if ((s->flags & SEC_LINKER_CREATED) == 0)
796589857Sobrien	continue;
796689857Sobrien
7967130561Sobrien      if (s == htab->brlt || s == htab->relbrlt)
7968104834Sobrien	/* These haven't been allocated yet;  don't strip.  */
7969104834Sobrien	continue;
7970130561Sobrien      else if (s == htab->got
7971130561Sobrien	       || s == htab->plt
7972218822Sdim	       || s == htab->glink
7973218822Sdim	       || s == htab->dynbss)
797489857Sobrien	{
797589857Sobrien	  /* Strip this section if we don't need it; see the
797689857Sobrien	     comment below.  */
797789857Sobrien	}
7978218822Sdim      else if (CONST_STRNEQ (bfd_get_section_name (dynobj, s), ".rela"))
797989857Sobrien	{
7980218822Sdim	  if (s->size != 0)
798189857Sobrien	    {
7982130561Sobrien	      if (s != htab->relplt)
7983130561Sobrien		relocs = TRUE;
798489857Sobrien
798589857Sobrien	      /* We use the reloc_count field as a counter if we need
798689857Sobrien		 to copy relocs into the output file.  */
798789857Sobrien	      s->reloc_count = 0;
798889857Sobrien	    }
798989857Sobrien	}
799089857Sobrien      else
799189857Sobrien	{
799289857Sobrien	  /* It's not one of our sections, so don't allocate space.  */
799389857Sobrien	  continue;
799489857Sobrien	}
799589857Sobrien
7996218822Sdim      if (s->size == 0)
799789857Sobrien	{
7998218822Sdim	  /* If we don't need this section, strip it from the
7999218822Sdim	     output file.  This is mostly to handle .rela.bss and
8000218822Sdim	     .rela.plt.  We must create both sections in
8001218822Sdim	     create_dynamic_sections, because they must be created
8002218822Sdim	     before the linker maps input sections to output
8003218822Sdim	     sections.  The linker does that before
8004218822Sdim	     adjust_dynamic_symbol is called, and it is that
8005218822Sdim	     function which decides whether anything needs to go
8006218822Sdim	     into these sections.  */
8007218822Sdim	  s->flags |= SEC_EXCLUDE;
800889857Sobrien	  continue;
800989857Sobrien	}
801089857Sobrien
8011218822Sdim      if ((s->flags & SEC_HAS_CONTENTS) == 0)
8012104834Sobrien	continue;
8013104834Sobrien
801489857Sobrien      /* Allocate memory for the section contents.  We use bfd_zalloc
801589857Sobrien	 here in case unused entries are not reclaimed before the
801689857Sobrien	 section's contents are written out.  This should not happen,
8017130561Sobrien	 but this way if it does we get a R_PPC64_NONE reloc in .rela
8018130561Sobrien	 sections instead of garbage.
8019130561Sobrien	 We also rely on the section contents being zero when writing
8020130561Sobrien	 the GOT.  */
8021218822Sdim      s->contents = bfd_zalloc (dynobj, s->size);
802289857Sobrien      if (s->contents == NULL)
8023130561Sobrien	return FALSE;
802489857Sobrien    }
802589857Sobrien
8026130561Sobrien  for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
8027130561Sobrien    {
8028218822Sdim      if (!is_ppc64_elf_target (ibfd->xvec))
8029209867Snwhitehorn	continue;
8030209867Snwhitehorn
8031130561Sobrien      s = ppc64_elf_tdata (ibfd)->got;
8032130561Sobrien      if (s != NULL && s != htab->got)
8033130561Sobrien	{
8034218822Sdim	  if (s->size == 0)
8035218822Sdim	    s->flags |= SEC_EXCLUDE;
8036130561Sobrien	  else
8037130561Sobrien	    {
8038218822Sdim	      s->contents = bfd_zalloc (ibfd, s->size);
8039130561Sobrien	      if (s->contents == NULL)
8040130561Sobrien		return FALSE;
8041130561Sobrien	    }
8042130561Sobrien	}
8043130561Sobrien      s = ppc64_elf_tdata (ibfd)->relgot;
8044130561Sobrien      if (s != NULL)
8045130561Sobrien	{
8046218822Sdim	  if (s->size == 0)
8047218822Sdim	    s->flags |= SEC_EXCLUDE;
8048130561Sobrien	  else
8049130561Sobrien	    {
8050218822Sdim	      s->contents = bfd_zalloc (ibfd, s->size);
8051130561Sobrien	      if (s->contents == NULL)
8052130561Sobrien		return FALSE;
8053130561Sobrien	      relocs = TRUE;
8054130561Sobrien	      s->reloc_count = 0;
8055130561Sobrien	    }
8056130561Sobrien	}
8057130561Sobrien    }
8058130561Sobrien
805989857Sobrien  if (htab->elf.dynamic_sections_created)
806089857Sobrien    {
806189857Sobrien      /* Add some entries to the .dynamic section.  We fill in the
806289857Sobrien	 values later, in ppc64_elf_finish_dynamic_sections, but we
806389857Sobrien	 must add the entries now so that we get the correct size for
806489857Sobrien	 the .dynamic section.  The DT_DEBUG entry is filled in by the
806589857Sobrien	 dynamic linker and used by the debugger.  */
806689857Sobrien#define add_dynamic_entry(TAG, VAL) \
8067130561Sobrien  _bfd_elf_add_dynamic_entry (info, TAG, VAL)
806889857Sobrien
8069130561Sobrien      if (info->executable)
807089857Sobrien	{
807189857Sobrien	  if (!add_dynamic_entry (DT_DEBUG, 0))
8072130561Sobrien	    return FALSE;
807389857Sobrien	}
807489857Sobrien
8075218822Sdim      if (htab->plt != NULL && htab->plt->size != 0)
807689857Sobrien	{
807789857Sobrien	  if (!add_dynamic_entry (DT_PLTGOT, 0)
807889857Sobrien	      || !add_dynamic_entry (DT_PLTRELSZ, 0)
807989857Sobrien	      || !add_dynamic_entry (DT_PLTREL, DT_RELA)
808089857Sobrien	      || !add_dynamic_entry (DT_JMPREL, 0)
808189857Sobrien	      || !add_dynamic_entry (DT_PPC64_GLINK, 0))
8082130561Sobrien	    return FALSE;
808389857Sobrien	}
808489857Sobrien
808591041Sobrien      if (NO_OPD_RELOCS)
808691041Sobrien	{
808791041Sobrien	  if (!add_dynamic_entry (DT_PPC64_OPD, 0)
808891041Sobrien	      || !add_dynamic_entry (DT_PPC64_OPDSZ, 0))
8089130561Sobrien	    return FALSE;
809091041Sobrien	}
809191041Sobrien
809289857Sobrien      if (relocs)
809389857Sobrien	{
809489857Sobrien	  if (!add_dynamic_entry (DT_RELA, 0)
809589857Sobrien	      || !add_dynamic_entry (DT_RELASZ, 0)
809689857Sobrien	      || !add_dynamic_entry (DT_RELAENT, sizeof (Elf64_External_Rela)))
8097130561Sobrien	    return FALSE;
809889857Sobrien
809989857Sobrien	  /* If any dynamic relocs apply to a read-only section,
810089857Sobrien	     then we need a DT_TEXTREL entry.  */
810191041Sobrien	  if ((info->flags & DF_TEXTREL) == 0)
8102130561Sobrien	    elf_link_hash_traverse (&htab->elf, readonly_dynrelocs, info);
810389857Sobrien
810489857Sobrien	  if ((info->flags & DF_TEXTREL) != 0)
810589857Sobrien	    {
810689857Sobrien	      if (!add_dynamic_entry (DT_TEXTREL, 0))
8107130561Sobrien		return FALSE;
810889857Sobrien	    }
810989857Sobrien	}
811089857Sobrien    }
811189857Sobrien#undef add_dynamic_entry
811289857Sobrien
8113130561Sobrien  return TRUE;
811489857Sobrien}
811589857Sobrien
8116104834Sobrien/* Determine the type of stub needed, if any, for a call.  */
811789857Sobrien
8118130561Sobrienstatic inline enum ppc_stub_type
8119130561Sobrienppc_type_of_stub (asection *input_sec,
8120130561Sobrien		  const Elf_Internal_Rela *rel,
8121130561Sobrien		  struct ppc_link_hash_entry **hash,
8122130561Sobrien		  bfd_vma destination)
812389857Sobrien{
8124104834Sobrien  struct ppc_link_hash_entry *h = *hash;
8125104834Sobrien  bfd_vma location;
8126104834Sobrien  bfd_vma branch_offset;
8127104834Sobrien  bfd_vma max_branch_offset;
8128130561Sobrien  enum elf_ppc64_reloc_type r_type;
812999461Sobrien
8130104834Sobrien  if (h != NULL)
813189857Sobrien    {
8132218822Sdim      struct ppc_link_hash_entry *fdh = h;
8133218822Sdim      if (fdh->oh != NULL
8134218822Sdim	  && fdh->oh->is_func_descriptor)
8135218822Sdim	fdh = fdh->oh;
8136218822Sdim
8137218822Sdim      if (fdh->elf.dynindx != -1)
8138104834Sobrien	{
8139130561Sobrien	  struct plt_entry *ent;
8140218822Sdim
8141218822Sdim	  for (ent = fdh->elf.plt.plist; ent != NULL; ent = ent->next)
8142130561Sobrien	    if (ent->addend == rel->r_addend
8143130561Sobrien		&& ent->plt.offset != (bfd_vma) -1)
8144130561Sobrien	      {
8145218822Sdim		*hash = fdh;
8146130561Sobrien		return ppc_stub_plt_call;
8147130561Sobrien	      }
8148104834Sobrien	}
814989857Sobrien
8150218822Sdim      /* Here, we know we don't have a plt entry.  If we don't have a
8151218822Sdim	 either a defined function descriptor or a defined entry symbol
8152218822Sdim	 in a regular object file, then it is pointless trying to make
8153218822Sdim	 any other type of stub.  */
8154218822Sdim      if (!((fdh->elf.root.type == bfd_link_hash_defined
8155218822Sdim	    || fdh->elf.root.type == bfd_link_hash_defweak)
8156218822Sdim	    && fdh->elf.root.u.def.section->output_section != NULL)
8157218822Sdim	  && !((h->elf.root.type == bfd_link_hash_defined
8158218822Sdim		|| h->elf.root.type == bfd_link_hash_defweak)
8159218822Sdim	       && h->elf.root.u.def.section->output_section != NULL))
8160104834Sobrien	return ppc_stub_none;
816199461Sobrien    }
816289857Sobrien
8163104834Sobrien  /* Determine where the call point is.  */
8164104834Sobrien  location = (input_sec->output_offset
8165104834Sobrien	      + input_sec->output_section->vma
8166104834Sobrien	      + rel->r_offset);
816789857Sobrien
8168104834Sobrien  branch_offset = destination - location;
8169104834Sobrien  r_type = ELF64_R_TYPE (rel->r_info);
817089857Sobrien
8171104834Sobrien  /* Determine if a long branch stub is needed.  */
8172104834Sobrien  max_branch_offset = 1 << 25;
8173130561Sobrien  if (r_type != R_PPC64_REL24)
8174104834Sobrien    max_branch_offset = 1 << 15;
817589857Sobrien
8176104834Sobrien  if (branch_offset + max_branch_offset >= 2 * max_branch_offset)
8177104834Sobrien    /* We need a stub.  Figure out whether a long_branch or plt_branch
8178104834Sobrien       is needed later.  */
8179104834Sobrien    return ppc_stub_long_branch;
818089857Sobrien
8181104834Sobrien  return ppc_stub_none;
818289857Sobrien}
818389857Sobrien
818489857Sobrien/* Build a .plt call stub.  */
818589857Sobrien
8186130561Sobrienstatic inline bfd_byte *
8187130561Sobrienbuild_plt_stub (bfd *obfd, bfd_byte *p, int offset)
818889857Sobrien{
818989857Sobrien#define PPC_LO(v) ((v) & 0xffff)
819089857Sobrien#define PPC_HI(v) (((v) >> 16) & 0xffff)
819189857Sobrien#define PPC_HA(v) PPC_HI ((v) + 0x8000)
819289857Sobrien
819389857Sobrien  bfd_put_32 (obfd, ADDIS_R12_R2 | PPC_HA (offset), p),	p += 4;
8194130561Sobrien  bfd_put_32 (obfd, STD_R2_40R1, p),			p += 4;
819589857Sobrien  bfd_put_32 (obfd, LD_R11_0R12 | PPC_LO (offset), p),	p += 4;
819689857Sobrien  if (PPC_HA (offset + 8) != PPC_HA (offset))
8197130561Sobrien    bfd_put_32 (obfd, ADDIS_R12_R12 | 1, p),		p += 4;
819889857Sobrien  offset += 8;
819989857Sobrien  bfd_put_32 (obfd, LD_R2_0R12 | PPC_LO (offset), p),	p += 4;
820089857Sobrien  if (PPC_HA (offset + 8) != PPC_HA (offset))
8201130561Sobrien    bfd_put_32 (obfd, ADDIS_R12_R12 | 1, p),		p += 4;
820289857Sobrien  offset += 8;
820389857Sobrien  bfd_put_32 (obfd, MTCTR_R11, p),			p += 4;
820489857Sobrien  bfd_put_32 (obfd, LD_R11_0R12 | PPC_LO (offset), p),	p += 4;
820589857Sobrien  bfd_put_32 (obfd, BCTR, p),				p += 4;
820689857Sobrien  return p;
820789857Sobrien}
820889857Sobrien
8209130561Sobrienstatic bfd_boolean
8210130561Sobrienppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
821189857Sobrien{
8212104834Sobrien  struct ppc_stub_hash_entry *stub_entry;
8213104834Sobrien  struct ppc_branch_hash_entry *br_entry;
821489857Sobrien  struct bfd_link_info *info;
821589857Sobrien  struct ppc_link_hash_table *htab;
8216104834Sobrien  bfd_byte *loc;
8217104834Sobrien  bfd_byte *p;
8218104834Sobrien  unsigned int indx;
8219130561Sobrien  struct plt_entry *ent;
8220218822Sdim  bfd_vma dest, off;
8221104834Sobrien  int size;
822289857Sobrien
8223104834Sobrien  /* Massage our args to the form they really have.  */
8224104834Sobrien  stub_entry = (struct ppc_stub_hash_entry *) gen_entry;
8225130561Sobrien  info = in_arg;
822689857Sobrien
822789857Sobrien  htab = ppc_hash_table (info);
822889857Sobrien
8229104834Sobrien  /* Make a note of the offset within the stubs for this entry.  */
8230218822Sdim  stub_entry->stub_offset = stub_entry->stub_sec->size;
8231130561Sobrien  loc = stub_entry->stub_sec->contents + stub_entry->stub_offset;
8232104834Sobrien
8233130561Sobrien  htab->stub_count[stub_entry->stub_type - 1] += 1;
8234104834Sobrien  switch (stub_entry->stub_type)
823589857Sobrien    {
8236104834Sobrien    case ppc_stub_long_branch:
8237130561Sobrien    case ppc_stub_long_branch_r2off:
8238104834Sobrien      /* Branches are relative.  This is where we are going to.  */
8239218822Sdim      off = dest = (stub_entry->target_value
8240218822Sdim		    + stub_entry->target_section->output_offset
8241218822Sdim		    + stub_entry->target_section->output_section->vma);
824289857Sobrien
8243104834Sobrien      /* And this is where we are coming from.  */
8244104834Sobrien      off -= (stub_entry->stub_offset
8245130561Sobrien	      + stub_entry->stub_sec->output_offset
8246130561Sobrien	      + stub_entry->stub_sec->output_section->vma);
824789857Sobrien
8248130561Sobrien      if (stub_entry->stub_type != ppc_stub_long_branch_r2off)
8249130561Sobrien	size = 4;
8250130561Sobrien      else
8251130561Sobrien	{
8252130561Sobrien	  bfd_vma r2off;
8253130561Sobrien
8254130561Sobrien	  r2off = (htab->stub_group[stub_entry->target_section->id].toc_off
8255130561Sobrien		   - htab->stub_group[stub_entry->id_sec->id].toc_off);
8256130561Sobrien	  bfd_put_32 (htab->stub_bfd, STD_R2_40R1, loc);
8257130561Sobrien	  loc += 4;
8258130561Sobrien	  bfd_put_32 (htab->stub_bfd, ADDIS_R2_R2 | PPC_HA (r2off), loc);
8259130561Sobrien	  loc += 4;
8260130561Sobrien	  bfd_put_32 (htab->stub_bfd, ADDI_R2_R2 | PPC_LO (r2off), loc);
8261130561Sobrien	  loc += 4;
8262130561Sobrien	  off -= 12;
8263130561Sobrien	  size = 16;
8264130561Sobrien	}
8265130561Sobrien      bfd_put_32 (htab->stub_bfd, B_DOT | (off & 0x3fffffc), loc);
8266130561Sobrien
8267218822Sdim      if (off + (1 << 25) >= (bfd_vma) (1 << 26))
8268218822Sdim	{
8269218822Sdim	  (*_bfd_error_handler) (_("long branch stub `%s' offset overflow"),
8270218822Sdim				 stub_entry->root.string);
8271218822Sdim	  htab->stub_error = TRUE;
8272218822Sdim	  return FALSE;
8273218822Sdim	}
8274218822Sdim
8275218822Sdim      if (info->emitrelocations)
8276218822Sdim	{
8277218822Sdim	  Elf_Internal_Rela *relocs, *r;
8278218822Sdim	  struct bfd_elf_section_data *elfsec_data;
8279218822Sdim
8280218822Sdim	  elfsec_data = elf_section_data (stub_entry->stub_sec);
8281218822Sdim	  relocs = elfsec_data->relocs;
8282218822Sdim	  if (relocs == NULL)
8283218822Sdim	    {
8284218822Sdim	      bfd_size_type relsize;
8285218822Sdim	      relsize = stub_entry->stub_sec->reloc_count * sizeof (*relocs);
8286218822Sdim	      relocs = bfd_alloc (htab->stub_bfd, relsize);
8287218822Sdim	      if (relocs == NULL)
8288218822Sdim		return FALSE;
8289218822Sdim	      elfsec_data->relocs = relocs;
8290218822Sdim	      elfsec_data->rel_hdr.sh_size = relsize;
8291218822Sdim	      elfsec_data->rel_hdr.sh_entsize = 24;
8292218822Sdim	      stub_entry->stub_sec->reloc_count = 0;
8293218822Sdim	    }
8294218822Sdim	  r = relocs + stub_entry->stub_sec->reloc_count;
8295218822Sdim	  stub_entry->stub_sec->reloc_count += 1;
8296218822Sdim	  r->r_offset = loc - stub_entry->stub_sec->contents;
8297218822Sdim	  r->r_info = ELF64_R_INFO (0, R_PPC64_REL24);
8298218822Sdim	  r->r_addend = dest;
8299218822Sdim	  if (stub_entry->h != NULL)
8300218822Sdim	    {
8301218822Sdim	      struct elf_link_hash_entry **hashes;
8302218822Sdim	      unsigned long symndx;
8303218822Sdim	      struct ppc_link_hash_entry *h;
8304218822Sdim
8305218822Sdim	      hashes = elf_sym_hashes (htab->stub_bfd);
8306218822Sdim	      if (hashes == NULL)
8307218822Sdim		{
8308218822Sdim		  bfd_size_type hsize;
8309218822Sdim
8310218822Sdim		  hsize = (htab->stub_globals + 1) * sizeof (*hashes);
8311218822Sdim		  hashes = bfd_zalloc (htab->stub_bfd, hsize);
8312218822Sdim		  if (hashes == NULL)
8313218822Sdim		    return FALSE;
8314218822Sdim		  elf_sym_hashes (htab->stub_bfd) = hashes;
8315218822Sdim		  htab->stub_globals = 1;
8316218822Sdim		}
8317218822Sdim	      symndx = htab->stub_globals++;
8318218822Sdim	      h = stub_entry->h;
8319218822Sdim	      hashes[symndx] = &h->elf;
8320218822Sdim	      r->r_info = ELF64_R_INFO (symndx, R_PPC64_REL24);
8321218822Sdim	      if (h->oh != NULL && h->oh->is_func)
8322218822Sdim		h = h->oh;
8323218822Sdim	      if (h->elf.root.u.def.section != stub_entry->target_section)
8324218822Sdim		/* H is an opd symbol.  The addend must be zero.  */
8325218822Sdim		r->r_addend = 0;
8326218822Sdim	      else
8327218822Sdim		{
8328218822Sdim		  off = (h->elf.root.u.def.value
8329218822Sdim			 + h->elf.root.u.def.section->output_offset
8330218822Sdim			 + h->elf.root.u.def.section->output_section->vma);
8331218822Sdim		  r->r_addend -= off;
8332218822Sdim		}
8333218822Sdim	    }
8334218822Sdim	}
8335104834Sobrien      break;
833689857Sobrien
8337104834Sobrien    case ppc_stub_plt_branch:
8338130561Sobrien    case ppc_stub_plt_branch_r2off:
8339104834Sobrien      br_entry = ppc_branch_hash_lookup (&htab->branch_hash_table,
8340104834Sobrien					 stub_entry->root.string + 9,
8341130561Sobrien					 FALSE, FALSE);
8342104834Sobrien      if (br_entry == NULL)
8343104834Sobrien	{
8344104834Sobrien	  (*_bfd_error_handler) (_("can't find branch stub `%s'"),
8345218822Sdim				 stub_entry->root.string);
8346130561Sobrien	  htab->stub_error = TRUE;
8347130561Sobrien	  return FALSE;
8348104834Sobrien	}
834989857Sobrien
8350104834Sobrien      off = (stub_entry->target_value
8351104834Sobrien	     + stub_entry->target_section->output_offset
8352104834Sobrien	     + stub_entry->target_section->output_section->vma);
8353104834Sobrien
8354130561Sobrien      bfd_put_64 (htab->brlt->owner, off,
8355130561Sobrien		  htab->brlt->contents + br_entry->offset);
8356104834Sobrien
8357218822Sdim      if (htab->relbrlt != NULL)
835889857Sobrien	{
8359104834Sobrien	  /* Create a reloc for the branch lookup table entry.  */
8360104834Sobrien	  Elf_Internal_Rela rela;
8361130561Sobrien	  bfd_byte *rl;
8362104834Sobrien
8363104834Sobrien	  rela.r_offset = (br_entry->offset
8364130561Sobrien			   + htab->brlt->output_offset
8365130561Sobrien			   + htab->brlt->output_section->vma);
8366104834Sobrien	  rela.r_info = ELF64_R_INFO (0, R_PPC64_RELATIVE);
8367104834Sobrien	  rela.r_addend = off;
8368104834Sobrien
8369130561Sobrien	  rl = htab->relbrlt->contents;
8370130561Sobrien	  rl += htab->relbrlt->reloc_count++ * sizeof (Elf64_External_Rela);
8371130561Sobrien	  bfd_elf64_swap_reloca_out (htab->relbrlt->owner, &rela, rl);
8372104834Sobrien	}
8373218822Sdim      else if (info->emitrelocations)
8374218822Sdim	{
8375218822Sdim	  Elf_Internal_Rela *relocs, *r;
8376218822Sdim	  struct bfd_elf_section_data *elfsec_data;
8377104834Sobrien
8378218822Sdim	  elfsec_data = elf_section_data (htab->brlt);
8379218822Sdim	  relocs = elfsec_data->relocs;
8380218822Sdim	  if (relocs == NULL)
8381218822Sdim	    {
8382218822Sdim	      bfd_size_type relsize;
8383218822Sdim	      relsize = htab->brlt->reloc_count * sizeof (*relocs);
8384218822Sdim	      relocs = bfd_alloc (htab->brlt->owner, relsize);
8385218822Sdim	      if (relocs == NULL)
8386218822Sdim		return FALSE;
8387218822Sdim	      elfsec_data->relocs = relocs;
8388218822Sdim	      elfsec_data->rel_hdr.sh_size = relsize;
8389218822Sdim	      elfsec_data->rel_hdr.sh_entsize = 24;
8390218822Sdim	      htab->brlt->reloc_count = 0;
8391218822Sdim	    }
8392218822Sdim	  r = relocs + htab->brlt->reloc_count;
8393218822Sdim	  htab->brlt->reloc_count += 1;
8394218822Sdim	  r->r_offset = (br_entry->offset
8395218822Sdim			 + htab->brlt->output_offset
8396218822Sdim			 + htab->brlt->output_section->vma);
8397218822Sdim	  r->r_info = ELF64_R_INFO (0, R_PPC64_RELATIVE);
8398218822Sdim	  r->r_addend = off;
8399218822Sdim	}
8400218822Sdim
8401104834Sobrien      off = (br_entry->offset
8402130561Sobrien	     + htab->brlt->output_offset
8403130561Sobrien	     + htab->brlt->output_section->vma
8404130561Sobrien	     - elf_gp (htab->brlt->output_section->owner)
8405130561Sobrien	     - htab->stub_group[stub_entry->id_sec->id].toc_off);
8406104834Sobrien
8407130561Sobrien      if (off + 0x80008000 > 0xffffffff || (off & 7) != 0)
8408104834Sobrien	{
840989857Sobrien	  (*_bfd_error_handler)
841089857Sobrien	    (_("linkage table error against `%s'"),
8411104834Sobrien	     stub_entry->root.string);
841289857Sobrien	  bfd_set_error (bfd_error_bad_value);
8413130561Sobrien	  htab->stub_error = TRUE;
8414130561Sobrien	  return FALSE;
841589857Sobrien	}
841689857Sobrien
8417104834Sobrien      indx = off;
8418130561Sobrien      if (stub_entry->stub_type != ppc_stub_plt_branch_r2off)
8419130561Sobrien	{
8420130561Sobrien	  bfd_put_32 (htab->stub_bfd, ADDIS_R12_R2 | PPC_HA (indx), loc);
8421130561Sobrien	  loc += 4;
8422130561Sobrien	  bfd_put_32 (htab->stub_bfd, LD_R11_0R12 | PPC_LO (indx), loc);
8423130561Sobrien	  size = 16;
8424130561Sobrien	}
8425130561Sobrien      else
8426130561Sobrien	{
8427130561Sobrien	  bfd_vma r2off;
8428130561Sobrien
8429130561Sobrien	  r2off = (htab->stub_group[stub_entry->target_section->id].toc_off
8430130561Sobrien		   - htab->stub_group[stub_entry->id_sec->id].toc_off);
8431130561Sobrien	  bfd_put_32 (htab->stub_bfd, STD_R2_40R1, loc);
8432130561Sobrien	  loc += 4;
8433130561Sobrien	  bfd_put_32 (htab->stub_bfd, ADDIS_R12_R2 | PPC_HA (indx), loc);
8434130561Sobrien	  loc += 4;
8435130561Sobrien	  bfd_put_32 (htab->stub_bfd, LD_R11_0R12 | PPC_LO (indx), loc);
8436130561Sobrien	  loc += 4;
8437130561Sobrien	  bfd_put_32 (htab->stub_bfd, ADDIS_R2_R2 | PPC_HA (r2off), loc);
8438130561Sobrien	  loc += 4;
8439130561Sobrien	  bfd_put_32 (htab->stub_bfd, ADDI_R2_R2 | PPC_LO (r2off), loc);
8440130561Sobrien	  size = 28;
8441130561Sobrien	}
8442130561Sobrien      loc += 4;
8443130561Sobrien      bfd_put_32 (htab->stub_bfd, MTCTR_R11, loc);
8444130561Sobrien      loc += 4;
8445130561Sobrien      bfd_put_32 (htab->stub_bfd, BCTR, loc);
8446104834Sobrien      break;
844789857Sobrien
8448104834Sobrien    case ppc_stub_plt_call:
8449104834Sobrien      /* Do the best we can for shared libraries built without
8450104834Sobrien	 exporting ".foo" for each "foo".  This can happen when symbol
8451104834Sobrien	 versioning scripts strip all bar a subset of symbols.  */
8452218822Sdim      if (stub_entry->h->oh != NULL
8453218822Sdim	  && stub_entry->h->oh->elf.root.type != bfd_link_hash_defined
8454218822Sdim	  && stub_entry->h->oh->elf.root.type != bfd_link_hash_defweak)
845589857Sobrien	{
8456104834Sobrien	  /* Point the symbol at the stub.  There may be multiple stubs,
8457104834Sobrien	     we don't really care;  The main thing is to make this sym
8458130561Sobrien	     defined somewhere.  Maybe defining the symbol in the stub
8459130561Sobrien	     section is a silly idea.  If we didn't do this, htab->top_id
8460130561Sobrien	     could disappear.  */
8461218822Sdim	  stub_entry->h->oh->elf.root.type = bfd_link_hash_defined;
8462218822Sdim	  stub_entry->h->oh->elf.root.u.def.section = stub_entry->stub_sec;
8463218822Sdim	  stub_entry->h->oh->elf.root.u.def.value = stub_entry->stub_offset;
846489857Sobrien	}
8465104834Sobrien
8466104834Sobrien      /* Now build the stub.  */
8467130561Sobrien      off = (bfd_vma) -1;
8468130561Sobrien      for (ent = stub_entry->h->elf.plt.plist; ent != NULL; ent = ent->next)
8469130561Sobrien	if (ent->addend == stub_entry->addend)
8470130561Sobrien	  {
8471130561Sobrien	    off = ent->plt.offset;
8472130561Sobrien	    break;
8473130561Sobrien	  }
8474104834Sobrien      if (off >= (bfd_vma) -2)
8475104834Sobrien	abort ();
8476104834Sobrien
8477104834Sobrien      off &= ~ (bfd_vma) 1;
8478130561Sobrien      off += (htab->plt->output_offset
8479130561Sobrien	      + htab->plt->output_section->vma
8480130561Sobrien	      - elf_gp (htab->plt->output_section->owner)
8481130561Sobrien	      - htab->stub_group[stub_entry->id_sec->id].toc_off);
8482104834Sobrien
8483130561Sobrien      if (off + 0x80008000 > 0xffffffff || (off & 7) != 0)
848489857Sobrien	{
8485104834Sobrien	  (*_bfd_error_handler)
8486104834Sobrien	    (_("linkage table error against `%s'"),
8487104834Sobrien	     stub_entry->h->elf.root.root.string);
8488104834Sobrien	  bfd_set_error (bfd_error_bad_value);
8489130561Sobrien	  htab->stub_error = TRUE;
8490130561Sobrien	  return FALSE;
849189857Sobrien	}
8492104834Sobrien
8493130561Sobrien      p = build_plt_stub (htab->stub_bfd, loc, off);
8494104834Sobrien      size = p - loc;
8495104834Sobrien      break;
8496104834Sobrien
8497104834Sobrien    default:
8498104834Sobrien      BFD_FAIL ();
8499130561Sobrien      return FALSE;
850089857Sobrien    }
8501104834Sobrien
8502218822Sdim  stub_entry->stub_sec->size += size;
8503130561Sobrien
8504218822Sdim  if (htab->emit_stub_syms)
8505130561Sobrien    {
8506130561Sobrien      struct elf_link_hash_entry *h;
8507218822Sdim      size_t len1, len2;
8508218822Sdim      char *name;
8509218822Sdim      const char *const stub_str[] = { "long_branch",
8510218822Sdim				       "long_branch_r2off",
8511218822Sdim				       "plt_branch",
8512218822Sdim				       "plt_branch_r2off",
8513218822Sdim				       "plt_call" };
8514218822Sdim
8515218822Sdim      len1 = strlen (stub_str[stub_entry->stub_type - 1]);
8516218822Sdim      len2 = strlen (stub_entry->root.string);
8517218822Sdim      name = bfd_malloc (len1 + len2 + 2);
8518218822Sdim      if (name == NULL)
8519218822Sdim	return FALSE;
8520218822Sdim      memcpy (name, stub_entry->root.string, 9);
8521218822Sdim      memcpy (name + 9, stub_str[stub_entry->stub_type - 1], len1);
8522218822Sdim      memcpy (name + len1 + 9, stub_entry->root.string + 8, len2 - 8 + 1);
8523218822Sdim      h = elf_link_hash_lookup (&htab->elf, name, TRUE, FALSE, FALSE);
8524130561Sobrien      if (h == NULL)
8525130561Sobrien	return FALSE;
8526130561Sobrien      if (h->root.type == bfd_link_hash_new)
8527130561Sobrien	{
8528130561Sobrien	  h->root.type = bfd_link_hash_defined;
8529130561Sobrien	  h->root.u.def.section = stub_entry->stub_sec;
8530130561Sobrien	  h->root.u.def.value = stub_entry->stub_offset;
8531218822Sdim	  h->ref_regular = 1;
8532218822Sdim	  h->def_regular = 1;
8533218822Sdim	  h->ref_regular_nonweak = 1;
8534218822Sdim	  h->forced_local = 1;
8535218822Sdim	  h->non_elf = 0;
8536130561Sobrien	}
8537130561Sobrien    }
8538130561Sobrien
8539130561Sobrien  return TRUE;
854089857Sobrien}
854189857Sobrien
8542104834Sobrien/* As above, but don't actually build the stub.  Just bump offset so
8543104834Sobrien   we know stub section sizes, and select plt_branch stubs where
8544104834Sobrien   long_branch stubs won't do.  */
8545104834Sobrien
8546130561Sobrienstatic bfd_boolean
8547130561Sobrienppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
8548104834Sobrien{
8549104834Sobrien  struct ppc_stub_hash_entry *stub_entry;
8550130561Sobrien  struct bfd_link_info *info;
8551104834Sobrien  struct ppc_link_hash_table *htab;
8552104834Sobrien  bfd_vma off;
8553104834Sobrien  int size;
8554104834Sobrien
8555104834Sobrien  /* Massage our args to the form they really have.  */
8556104834Sobrien  stub_entry = (struct ppc_stub_hash_entry *) gen_entry;
8557130561Sobrien  info = in_arg;
8558104834Sobrien
8559130561Sobrien  htab = ppc_hash_table (info);
8560130561Sobrien
8561104834Sobrien  if (stub_entry->stub_type == ppc_stub_plt_call)
8562104834Sobrien    {
8563130561Sobrien      struct plt_entry *ent;
8564130561Sobrien      off = (bfd_vma) -1;
8565130561Sobrien      for (ent = stub_entry->h->elf.plt.plist; ent != NULL; ent = ent->next)
8566130561Sobrien	if (ent->addend == stub_entry->addend)
8567130561Sobrien	  {
8568130561Sobrien	    off = ent->plt.offset & ~(bfd_vma) 1;
8569130561Sobrien	    break;
8570130561Sobrien	  }
8571130561Sobrien      if (off >= (bfd_vma) -2)
8572130561Sobrien	abort ();
8573130561Sobrien      off += (htab->plt->output_offset
8574130561Sobrien	      + htab->plt->output_section->vma
8575130561Sobrien	      - elf_gp (htab->plt->output_section->owner)
8576130561Sobrien	      - htab->stub_group[stub_entry->id_sec->id].toc_off);
8577104834Sobrien
8578130561Sobrien      size = PLT_CALL_STUB_SIZE;
8579130561Sobrien      if (PPC_HA (off + 16) != PPC_HA (off))
8580104834Sobrien	size += 4;
8581104834Sobrien    }
8582104834Sobrien  else
8583104834Sobrien    {
8584130561Sobrien      /* ppc_stub_long_branch or ppc_stub_plt_branch, or their r2off
8585130561Sobrien	 variants.  */
8586104834Sobrien      off = (stub_entry->target_value
8587104834Sobrien	     + stub_entry->target_section->output_offset
8588104834Sobrien	     + stub_entry->target_section->output_section->vma);
8589218822Sdim      off -= (stub_entry->stub_sec->size
8590104834Sobrien	      + stub_entry->stub_sec->output_offset
8591104834Sobrien	      + stub_entry->stub_sec->output_section->vma);
8592104834Sobrien
8593130561Sobrien      /* Reset the stub type from the plt variant in case we now
8594130561Sobrien	 can reach with a shorter stub.  */
8595130561Sobrien      if (stub_entry->stub_type >= ppc_stub_plt_branch)
8596130561Sobrien	stub_entry->stub_type += ppc_stub_long_branch - ppc_stub_plt_branch;
8597130561Sobrien
8598130561Sobrien      size = 4;
8599130561Sobrien      if (stub_entry->stub_type == ppc_stub_long_branch_r2off)
8600130561Sobrien	{
8601130561Sobrien	  off -= 12;
8602130561Sobrien	  size = 16;
8603130561Sobrien	}
8604130561Sobrien
8605130561Sobrien      /* If the branch offset if too big, use a ppc_stub_plt_branch.  */
8606104834Sobrien      if (off + (1 << 25) >= (bfd_vma) (1 << 26))
8607104834Sobrien	{
8608104834Sobrien	  struct ppc_branch_hash_entry *br_entry;
8609104834Sobrien
8610104834Sobrien	  br_entry = ppc_branch_hash_lookup (&htab->branch_hash_table,
8611104834Sobrien					     stub_entry->root.string + 9,
8612130561Sobrien					     TRUE, FALSE);
8613104834Sobrien	  if (br_entry == NULL)
8614104834Sobrien	    {
8615104834Sobrien	      (*_bfd_error_handler) (_("can't build branch stub `%s'"),
8616218822Sdim				     stub_entry->root.string);
8617130561Sobrien	      htab->stub_error = TRUE;
8618130561Sobrien	      return FALSE;
8619104834Sobrien	    }
8620104834Sobrien
8621104834Sobrien	  if (br_entry->iter != htab->stub_iteration)
8622104834Sobrien	    {
8623104834Sobrien	      br_entry->iter = htab->stub_iteration;
8624218822Sdim	      br_entry->offset = htab->brlt->size;
8625218822Sdim	      htab->brlt->size += 8;
8626130561Sobrien
8627218822Sdim	      if (htab->relbrlt != NULL)
8628218822Sdim		htab->relbrlt->size += sizeof (Elf64_External_Rela);
8629218822Sdim	      else if (info->emitrelocations)
8630218822Sdim		{
8631218822Sdim		  htab->brlt->reloc_count += 1;
8632218822Sdim		  htab->brlt->flags |= SEC_RELOC;
8633218822Sdim		}
8634104834Sobrien	    }
8635130561Sobrien
8636130561Sobrien	  stub_entry->stub_type += ppc_stub_plt_branch - ppc_stub_long_branch;
8637104834Sobrien	  size = 16;
8638130561Sobrien	  if (stub_entry->stub_type != ppc_stub_plt_branch)
8639130561Sobrien	    size = 28;
8640104834Sobrien	}
8641218822Sdim      else if (info->emitrelocations)
8642218822Sdim	{
8643218822Sdim	  stub_entry->stub_sec->reloc_count += 1;
8644218822Sdim	  stub_entry->stub_sec->flags |= SEC_RELOC;
8645218822Sdim	}
8646104834Sobrien    }
8647104834Sobrien
8648218822Sdim  stub_entry->stub_sec->size += size;
8649130561Sobrien  return TRUE;
8650104834Sobrien}
8651104834Sobrien
8652104834Sobrien/* Set up various things so that we can make a list of input sections
8653104834Sobrien   for each output section included in the link.  Returns -1 on error,
8654104834Sobrien   0 when no stubs will be needed, and 1 on success.  */
8655104834Sobrien
8656104834Sobrienint
8657218822Sdimppc64_elf_setup_section_lists (bfd *output_bfd,
8658218822Sdim			       struct bfd_link_info *info,
8659218822Sdim			       int no_multi_toc)
866089857Sobrien{
8661104834Sobrien  bfd *input_bfd;
8662130561Sobrien  int top_id, top_index, id;
8663104834Sobrien  asection *section;
8664130561Sobrien  asection **input_list;
8665104834Sobrien  bfd_size_type amt;
866689857Sobrien  struct ppc_link_hash_table *htab = ppc_hash_table (info);
866789857Sobrien
8668218822Sdim  htab->no_multi_toc = no_multi_toc;
8669218822Sdim
8670130561Sobrien  if (htab->brlt == NULL)
8671104834Sobrien    return 0;
867289857Sobrien
8673104834Sobrien  /* Find the top input section id.  */
8674130561Sobrien  for (input_bfd = info->input_bfds, top_id = 3;
8675104834Sobrien       input_bfd != NULL;
8676104834Sobrien       input_bfd = input_bfd->link_next)
8677104834Sobrien    {
8678104834Sobrien      for (section = input_bfd->sections;
8679104834Sobrien	   section != NULL;
8680104834Sobrien	   section = section->next)
8681104834Sobrien	{
8682104834Sobrien	  if (top_id < section->id)
8683104834Sobrien	    top_id = section->id;
8684104834Sobrien	}
8685104834Sobrien    }
868689857Sobrien
8687130561Sobrien  htab->top_id = top_id;
8688104834Sobrien  amt = sizeof (struct map_stub) * (top_id + 1);
8689130561Sobrien  htab->stub_group = bfd_zmalloc (amt);
8690104834Sobrien  if (htab->stub_group == NULL)
8691104834Sobrien    return -1;
8692104834Sobrien
8693130561Sobrien  /* Set toc_off for com, und, abs and ind sections.  */
8694130561Sobrien  for (id = 0; id < 3; id++)
8695130561Sobrien    htab->stub_group[id].toc_off = TOC_BASE_OFF;
8696130561Sobrien
8697130561Sobrien  elf_gp (output_bfd) = htab->toc_curr = ppc64_elf_toc (output_bfd);
8698130561Sobrien
8699104834Sobrien  /* We can't use output_bfd->section_count here to find the top output
8700104834Sobrien     section index as some sections may have been removed, and
8701218822Sdim     strip_excluded_output_sections doesn't renumber the indices.  */
8702104834Sobrien  for (section = output_bfd->sections, top_index = 0;
8703104834Sobrien       section != NULL;
8704104834Sobrien       section = section->next)
870589857Sobrien    {
8706104834Sobrien      if (top_index < section->index)
8707104834Sobrien	top_index = section->index;
870889857Sobrien    }
870989857Sobrien
8710104834Sobrien  htab->top_index = top_index;
8711104834Sobrien  amt = sizeof (asection *) * (top_index + 1);
8712130561Sobrien  input_list = bfd_zmalloc (amt);
8713104834Sobrien  htab->input_list = input_list;
8714104834Sobrien  if (input_list == NULL)
8715104834Sobrien    return -1;
871689857Sobrien
8717130561Sobrien  return 1;
8718130561Sobrien}
871989857Sobrien
8720130561Sobrien/* The linker repeatedly calls this function for each TOC input section
8721130561Sobrien   and linker generated GOT section.  Group input bfds such that the toc
8722130561Sobrien   within a group is less than 64k in size.  Will break with cute linker
8723130561Sobrien   scripts that play games with dot in the output toc section.  */
8724130561Sobrien
8725130561Sobrienvoid
8726130561Sobrienppc64_elf_next_toc_section (struct bfd_link_info *info, asection *isec)
8727130561Sobrien{
8728130561Sobrien  struct ppc_link_hash_table *htab = ppc_hash_table (info);
8729130561Sobrien
8730130561Sobrien  if (!htab->no_multi_toc)
8731104834Sobrien    {
8732130561Sobrien      bfd_vma addr = isec->output_offset + isec->output_section->vma;
8733130561Sobrien      bfd_vma off = addr - htab->toc_curr;
8734218822Sdim
8735218822Sdim      if (off + isec->size > 0x10000)
8736218822Sdim	htab->toc_curr = addr;
8737218822Sdim
8738130561Sobrien      elf_gp (isec->owner) = (htab->toc_curr
8739130561Sobrien			      - elf_gp (isec->output_section->owner)
8740130561Sobrien			      + TOC_BASE_OFF);
8741104834Sobrien    }
8742130561Sobrien}
874389857Sobrien
8744130561Sobrien/* Called after the last call to the above function.  */
8745130561Sobrien
8746130561Sobrienvoid
8747218822Sdimppc64_elf_reinit_toc (bfd *output_bfd, struct bfd_link_info *info)
8748130561Sobrien{
8749130561Sobrien  struct ppc_link_hash_table *htab = ppc_hash_table (info);
8750130561Sobrien
8751218822Sdim  htab->multi_toc_needed = htab->toc_curr != elf_gp (output_bfd);
8752218822Sdim
8753130561Sobrien  /* toc_curr tracks the TOC offset used for code sections below in
8754130561Sobrien     ppc64_elf_next_input_section.  Start off at 0x8000.  */
8755130561Sobrien  htab->toc_curr = TOC_BASE_OFF;
8756104834Sobrien}
8757104834Sobrien
8758130561Sobrien/* No toc references were found in ISEC.  If the code in ISEC makes no
8759130561Sobrien   calls, then there's no need to use toc adjusting stubs when branching
8760130561Sobrien   into ISEC.  Actually, indirect calls from ISEC are OK as they will
8761218822Sdim   load r2.  Returns -1 on error, 0 for no stub needed, 1 for stub
8762218822Sdim   needed, and 2 if a cyclical call-graph was found but no other reason
8763218822Sdim   for a stub was detected.  If called from the top level, a return of
8764218822Sdim   2 means the same as a return of 0.  */
8765130561Sobrien
8766130561Sobrienstatic int
8767130561Sobrientoc_adjusting_stub_needed (struct bfd_link_info *info, asection *isec)
8768130561Sobrien{
8769218822Sdim  Elf_Internal_Rela *relstart, *rel;
8770218822Sdim  Elf_Internal_Sym *local_syms;
8771130561Sobrien  int ret;
8772218822Sdim  struct ppc_link_hash_table *htab;
8773130561Sobrien
8774130561Sobrien  /* We know none of our code bearing sections will need toc stubs.  */
8775130561Sobrien  if ((isec->flags & SEC_LINKER_CREATED) != 0)
8776130561Sobrien    return 0;
8777130561Sobrien
8778218822Sdim  if (isec->size == 0)
8779130561Sobrien    return 0;
8780130561Sobrien
8781218822Sdim  if (isec->output_section == NULL)
8782218822Sdim    return 0;
8783218822Sdim
8784130561Sobrien  /* Hack for linux kernel.  .fixup contains branches, but only back to
8785130561Sobrien     the function that hit an exception.  */
8786218822Sdim  if (strcmp (isec->name, ".fixup") == 0)
8787218822Sdim    return 0;
8788130561Sobrien
8789218822Sdim  if (isec->reloc_count == 0)
8790218822Sdim    return 0;
8791218822Sdim
8792218822Sdim  relstart = _bfd_elf_link_read_relocs (isec->owner, isec, NULL, NULL,
8793218822Sdim					info->keep_memory);
8794218822Sdim  if (relstart == NULL)
8795218822Sdim    return -1;
8796218822Sdim
8797218822Sdim  /* Look for branches to outside of this section.  */
8798218822Sdim  local_syms = NULL;
8799218822Sdim  ret = 0;
8800218822Sdim  htab = ppc_hash_table (info);
8801218822Sdim  for (rel = relstart; rel < relstart + isec->reloc_count; ++rel)
8802130561Sobrien    {
8803218822Sdim      enum elf_ppc64_reloc_type r_type;
8804218822Sdim      unsigned long r_symndx;
8805218822Sdim      struct elf_link_hash_entry *h;
8806218822Sdim      Elf_Internal_Sym *sym;
8807218822Sdim      asection *sym_sec;
8808218822Sdim      long *opd_adjust;
8809218822Sdim      bfd_vma sym_value;
8810218822Sdim      bfd_vma dest;
8811218822Sdim
8812218822Sdim      r_type = ELF64_R_TYPE (rel->r_info);
8813218822Sdim      if (r_type != R_PPC64_REL24
8814218822Sdim	  && r_type != R_PPC64_REL14
8815218822Sdim	  && r_type != R_PPC64_REL14_BRTAKEN
8816218822Sdim	  && r_type != R_PPC64_REL14_BRNTAKEN)
8817218822Sdim	continue;
8818218822Sdim
8819218822Sdim      r_symndx = ELF64_R_SYM (rel->r_info);
8820218822Sdim      if (!get_sym_h (&h, &sym, &sym_sec, NULL, &local_syms, r_symndx,
8821218822Sdim		      isec->owner))
8822130561Sobrien	{
8823218822Sdim	  ret = -1;
8824218822Sdim	  break;
8825130561Sobrien	}
8826130561Sobrien
8827218822Sdim      /* Calls to dynamic lib functions go through a plt call stub
8828218822Sdim	 that uses r2.  Branches to undefined symbols might be a call
8829218822Sdim	 using old-style dot symbols that can be satisfied by a plt
8830218822Sdim	 call into a new-style dynamic library.  */
8831218822Sdim      if (sym_sec == NULL)
8832130561Sobrien	{
8833218822Sdim	  struct ppc_link_hash_entry *eh = (struct ppc_link_hash_entry *) h;
8834218822Sdim	  if (eh != NULL
8835218822Sdim	      && eh->oh != NULL
8836218822Sdim	      && eh->oh->elf.plt.plist != NULL)
8837218822Sdim	    {
8838218822Sdim	      ret = 1;
8839218822Sdim	      break;
8840218822Sdim	    }
8841218822Sdim
8842218822Sdim	  /* Ignore other undefined symbols.  */
8843218822Sdim	  continue;
8844218822Sdim	}
8845218822Sdim
8846218822Sdim      /* Assume branches to other sections not included in the link need
8847218822Sdim	 stubs too, to cover -R and absolute syms.  */
8848218822Sdim      if (sym_sec->output_section == NULL)
8849218822Sdim	{
8850130561Sobrien	  ret = 1;
8851130561Sobrien	  break;
8852130561Sobrien	}
8853218822Sdim
8854218822Sdim      if (h == NULL)
8855218822Sdim	sym_value = sym->st_value;
8856218822Sdim      else
8857218822Sdim	{
8858218822Sdim	  if (h->root.type != bfd_link_hash_defined
8859218822Sdim	      && h->root.type != bfd_link_hash_defweak)
8860218822Sdim	    abort ();
8861218822Sdim	  sym_value = h->root.u.def.value;
8862218822Sdim	}
8863218822Sdim      sym_value += rel->r_addend;
8864218822Sdim
8865218822Sdim      /* If this branch reloc uses an opd sym, find the code section.  */
8866218822Sdim      opd_adjust = get_opd_info (sym_sec);
8867218822Sdim      if (opd_adjust != NULL)
8868218822Sdim	{
8869218822Sdim	  if (h == NULL)
8870218822Sdim	    {
8871218822Sdim	      long adjust;
8872218822Sdim
8873218822Sdim	      adjust = opd_adjust[sym->st_value / 8];
8874218822Sdim	      if (adjust == -1)
8875218822Sdim		/* Assume deleted functions won't ever be called.  */
8876218822Sdim		continue;
8877218822Sdim	      sym_value += adjust;
8878218822Sdim	    }
8879218822Sdim
8880218822Sdim	  dest = opd_entry_value (sym_sec, sym_value, &sym_sec, NULL);
8881218822Sdim	  if (dest == (bfd_vma) -1)
8882218822Sdim	    continue;
8883218822Sdim	}
8884218822Sdim      else
8885218822Sdim	dest = (sym_value
8886218822Sdim		+ sym_sec->output_offset
8887218822Sdim		+ sym_sec->output_section->vma);
8888218822Sdim
8889218822Sdim      /* Ignore branch to self.  */
8890218822Sdim      if (sym_sec == isec)
8891218822Sdim	continue;
8892218822Sdim
8893218822Sdim      /* If the called function uses the toc, we need a stub.  */
8894218822Sdim      if (sym_sec->has_toc_reloc
8895218822Sdim	  || sym_sec->makes_toc_func_call)
8896218822Sdim	{
8897218822Sdim	  ret = 1;
8898218822Sdim	  break;
8899218822Sdim	}
8900218822Sdim
8901218822Sdim      /* Assume any branch that needs a long branch stub might in fact
8902218822Sdim	 need a plt_branch stub.  A plt_branch stub uses r2.  */
8903218822Sdim      else if (dest - (isec->output_offset
8904218822Sdim		       + isec->output_section->vma
8905218822Sdim		       + rel->r_offset) + (1 << 25) >= (2 << 25))
8906218822Sdim	{
8907218822Sdim	  ret = 1;
8908218822Sdim	  break;
8909218822Sdim	}
8910218822Sdim
8911218822Sdim      /* If calling back to a section in the process of being tested, we
8912218822Sdim	 can't say for sure that no toc adjusting stubs are needed, so
8913218822Sdim	 don't return zero.  */
8914218822Sdim      else if (sym_sec->call_check_in_progress)
8915218822Sdim	ret = 2;
8916218822Sdim
8917218822Sdim      /* Branches to another section that itself doesn't have any TOC
8918218822Sdim	 references are OK.  Recursively call ourselves to check.  */
8919218822Sdim      else if (sym_sec->id <= htab->top_id
8920218822Sdim	       && htab->stub_group[sym_sec->id].toc_off == 0)
8921218822Sdim	{
8922218822Sdim	  int recur;
8923218822Sdim
8924218822Sdim	  /* Mark current section as indeterminate, so that other
8925218822Sdim	     sections that call back to current won't be marked as
8926218822Sdim	     known.  */
8927218822Sdim	  isec->call_check_in_progress = 1;
8928218822Sdim	  recur = toc_adjusting_stub_needed (info, sym_sec);
8929218822Sdim	  isec->call_check_in_progress = 0;
8930218822Sdim
8931218822Sdim	  if (recur < 0)
8932218822Sdim	    {
8933218822Sdim	      /* An error.  Exit.  */
8934218822Sdim	      ret = -1;
8935218822Sdim	      break;
8936218822Sdim	    }
8937218822Sdim	  else if (recur <= 1)
8938218822Sdim	    {
8939218822Sdim	      /* Known result.  Mark as checked and set section flag.  */
8940218822Sdim	      htab->stub_group[sym_sec->id].toc_off = 1;
8941218822Sdim	      if (recur != 0)
8942218822Sdim		{
8943218822Sdim		  sym_sec->makes_toc_func_call = 1;
8944218822Sdim		  ret = 1;
8945218822Sdim		  break;
8946218822Sdim		}
8947218822Sdim	    }
8948218822Sdim	  else
8949218822Sdim	    {
8950218822Sdim	      /* Unknown result.  Continue checking.  */
8951218822Sdim	      ret = 2;
8952218822Sdim	    }
8953218822Sdim	}
8954130561Sobrien    }
8955130561Sobrien
8956218822Sdim  if (local_syms != NULL
8957218822Sdim      && (elf_tdata (isec->owner)->symtab_hdr.contents
8958218822Sdim	  != (unsigned char *) local_syms))
8959218822Sdim    free (local_syms);
8960218822Sdim  if (elf_section_data (isec)->relocs != relstart)
8961218822Sdim    free (relstart);
8962218822Sdim
8963130561Sobrien  return ret;
8964130561Sobrien}
8965130561Sobrien
8966104834Sobrien/* The linker repeatedly calls this function for each input section,
8967104834Sobrien   in the order that input sections are linked into output sections.
8968104834Sobrien   Build lists of input sections to determine groupings between which
8969104834Sobrien   we may insert linker stubs.  */
8970104834Sobrien
8971130561Sobrienbfd_boolean
8972130561Sobrienppc64_elf_next_input_section (struct bfd_link_info *info, asection *isec)
8973104834Sobrien{
8974104834Sobrien  struct ppc_link_hash_table *htab = ppc_hash_table (info);
8975104834Sobrien
8976130561Sobrien  if ((isec->output_section->flags & SEC_CODE) != 0
8977130561Sobrien      && isec->output_section->index <= htab->top_index)
897889857Sobrien    {
8979104834Sobrien      asection **list = htab->input_list + isec->output_section->index;
8980130561Sobrien      /* Steal the link_sec pointer for our list.  */
8981104834Sobrien#define PREV_SEC(sec) (htab->stub_group[(sec)->id].link_sec)
8982130561Sobrien      /* This happens to make the list in reverse order,
8983130561Sobrien	 which is what we want.  */
8984130561Sobrien      PREV_SEC (isec) = *list;
8985130561Sobrien      *list = isec;
898689857Sobrien    }
8987130561Sobrien
8988218822Sdim  if (htab->multi_toc_needed)
8989130561Sobrien    {
8990218822Sdim      /* If a code section has a function that uses the TOC then we need
8991218822Sdim	 to use the right TOC (obviously).  Also, make sure that .opd gets
8992218822Sdim	 the correct TOC value for R_PPC64_TOC relocs that don't have or
8993218822Sdim	 can't find their function symbol (shouldn't ever happen now).  */
8994218822Sdim      if (isec->has_toc_reloc || (isec->flags & SEC_CODE) == 0)
8995218822Sdim	{
8996218822Sdim	  if (elf_gp (isec->owner) != 0)
8997218822Sdim	    htab->toc_curr = elf_gp (isec->owner);
8998218822Sdim	}
8999218822Sdim      else if (htab->stub_group[isec->id].toc_off == 0)
9000218822Sdim	{
9001218822Sdim	  int ret = toc_adjusting_stub_needed (info, isec);
9002218822Sdim	  if (ret < 0)
9003218822Sdim	    return FALSE;
9004218822Sdim	  else
9005218822Sdim	    isec->makes_toc_func_call = ret & 1;
9006218822Sdim	}
9007130561Sobrien    }
9008130561Sobrien
9009130561Sobrien  /* Functions that don't use the TOC can belong in any TOC group.
9010130561Sobrien     Use the last TOC base.  This happens to make _init and _fini
9011130561Sobrien     pasting work.  */
9012130561Sobrien  htab->stub_group[isec->id].toc_off = htab->toc_curr;
9013130561Sobrien  return TRUE;
901489857Sobrien}
901589857Sobrien
9016104834Sobrien/* See whether we can group stub sections together.  Grouping stub
9017104834Sobrien   sections may result in fewer stubs.  More importantly, we need to
9018104834Sobrien   put all .init* and .fini* stubs at the beginning of the .init or
9019104834Sobrien   .fini output sections respectively, because glibc splits the
9020104834Sobrien   _init and _fini functions into multiple parts.  Putting a stub in
9021104834Sobrien   the middle of a function is not a good idea.  */
902289857Sobrien
9023104834Sobrienstatic void
9024130561Sobriengroup_sections (struct ppc_link_hash_table *htab,
9025130561Sobrien		bfd_size_type stub_group_size,
9026130561Sobrien		bfd_boolean stubs_always_before_branch)
902789857Sobrien{
9028218822Sdim  asection **list;
9029218822Sdim  bfd_size_type stub14_group_size;
9030218822Sdim  bfd_boolean suppress_size_errors;
9031218822Sdim
9032218822Sdim  suppress_size_errors = FALSE;
9033218822Sdim  stub14_group_size = stub_group_size;
9034218822Sdim  if (stub_group_size == 1)
9035218822Sdim    {
9036218822Sdim      /* Default values.  */
9037218822Sdim      if (stubs_always_before_branch)
9038218822Sdim	{
9039218822Sdim	  stub_group_size = 0x1e00000;
9040218822Sdim	  stub14_group_size = 0x7800;
9041218822Sdim	}
9042218822Sdim      else
9043218822Sdim	{
9044218822Sdim	  stub_group_size = 0x1c00000;
9045218822Sdim	  stub14_group_size = 0x7000;
9046218822Sdim	}
9047218822Sdim      suppress_size_errors = TRUE;
9048218822Sdim    }
9049218822Sdim
9050218822Sdim  list = htab->input_list + htab->top_index;
9051104834Sobrien  do
9052104834Sobrien    {
9053104834Sobrien      asection *tail = *list;
9054104834Sobrien      while (tail != NULL)
9055104834Sobrien	{
9056104834Sobrien	  asection *curr;
9057104834Sobrien	  asection *prev;
9058104834Sobrien	  bfd_size_type total;
9059130561Sobrien	  bfd_boolean big_sec;
9060130561Sobrien	  bfd_vma curr_toc;
906189857Sobrien
9062104834Sobrien	  curr = tail;
9063218822Sdim	  total = tail->size;
9064218822Sdim	  big_sec = total > (ppc64_elf_section_data (tail)->has_14bit_branch
9065218822Sdim			     ? stub14_group_size : stub_group_size);
9066218822Sdim	  if (big_sec && !suppress_size_errors)
9067218822Sdim	    (*_bfd_error_handler) (_("%B section %A exceeds stub group size"),
9068218822Sdim				     tail->owner, tail);
9069130561Sobrien	  curr_toc = htab->stub_group[tail->id].toc_off;
9070130561Sobrien
9071104834Sobrien	  while ((prev = PREV_SEC (curr)) != NULL
9072104834Sobrien		 && ((total += curr->output_offset - prev->output_offset)
9073218822Sdim		     < (ppc64_elf_section_data (prev)->has_14bit_branch
9074218822Sdim			? stub14_group_size : stub_group_size))
9075130561Sobrien		 && htab->stub_group[prev->id].toc_off == curr_toc)
9076104834Sobrien	    curr = prev;
907789857Sobrien
9078104834Sobrien	  /* OK, the size from the start of CURR to the end is less
9079104834Sobrien	     than stub_group_size and thus can be handled by one stub
9080104834Sobrien	     section.  (or the tail section is itself larger than
9081104834Sobrien	     stub_group_size, in which case we may be toast.)  We
9082104834Sobrien	     should really be keeping track of the total size of stubs
9083104834Sobrien	     added here, as stubs contribute to the final output
9084104834Sobrien	     section size.  That's a little tricky, and this way will
9085104834Sobrien	     only break if stubs added make the total size more than
9086104834Sobrien	     2^25, ie. for the default stub_group_size, if stubs total
9087130561Sobrien	     more than 2097152 bytes, or nearly 75000 plt call stubs.  */
9088104834Sobrien	  do
9089104834Sobrien	    {
9090104834Sobrien	      prev = PREV_SEC (tail);
9091104834Sobrien	      /* Set up this stub group.  */
9092104834Sobrien	      htab->stub_group[tail->id].link_sec = curr;
9093104834Sobrien	    }
9094104834Sobrien	  while (tail != curr && (tail = prev) != NULL);
9095104834Sobrien
9096104834Sobrien	  /* But wait, there's more!  Input sections up to stub_group_size
9097130561Sobrien	     bytes before the stub section can be handled by it too.
9098130561Sobrien	     Don't do this if we have a really large section after the
9099130561Sobrien	     stubs, as adding more stubs increases the chance that
9100130561Sobrien	     branches may not reach into the stub section.  */
9101130561Sobrien	  if (!stubs_always_before_branch && !big_sec)
9102104834Sobrien	    {
9103104834Sobrien	      total = 0;
9104104834Sobrien	      while (prev != NULL
9105104834Sobrien		     && ((total += tail->output_offset - prev->output_offset)
9106218822Sdim			 < (ppc64_elf_section_data (prev)->has_14bit_branch
9107218822Sdim			    ? stub14_group_size : stub_group_size))
9108130561Sobrien		     && htab->stub_group[prev->id].toc_off == curr_toc)
9109104834Sobrien		{
9110104834Sobrien		  tail = prev;
9111104834Sobrien		  prev = PREV_SEC (tail);
9112104834Sobrien		  htab->stub_group[tail->id].link_sec = curr;
9113104834Sobrien		}
9114104834Sobrien	    }
9115104834Sobrien	  tail = prev;
9116104834Sobrien	}
9117104834Sobrien    }
9118104834Sobrien  while (list-- != htab->input_list);
9119104834Sobrien  free (htab->input_list);
9120104834Sobrien#undef PREV_SEC
9121104834Sobrien}
9122104834Sobrien
9123104834Sobrien/* Determine and set the size of the stub section for a final link.
9124104834Sobrien
9125104834Sobrien   The basic idea here is to examine all the relocations looking for
9126104834Sobrien   PC-relative calls to a target that is unreachable with a "bl"
9127104834Sobrien   instruction.  */
9128104834Sobrien
9129130561Sobrienbfd_boolean
9130130561Sobrienppc64_elf_size_stubs (bfd *output_bfd,
9131130561Sobrien		      struct bfd_link_info *info,
9132130561Sobrien		      bfd_signed_vma group_size,
9133130561Sobrien		      asection *(*add_stub_section) (const char *, asection *),
9134130561Sobrien		      void (*layout_sections_again) (void))
9135104834Sobrien{
9136104834Sobrien  bfd_size_type stub_group_size;
9137130561Sobrien  bfd_boolean stubs_always_before_branch;
9138104834Sobrien  struct ppc_link_hash_table *htab = ppc_hash_table (info);
9139104834Sobrien
9140104834Sobrien  /* Stash our params away.  */
9141104834Sobrien  htab->add_stub_section = add_stub_section;
9142104834Sobrien  htab->layout_sections_again = layout_sections_again;
9143104834Sobrien  stubs_always_before_branch = group_size < 0;
9144104834Sobrien  if (group_size < 0)
9145104834Sobrien    stub_group_size = -group_size;
9146104834Sobrien  else
9147104834Sobrien    stub_group_size = group_size;
9148104834Sobrien
9149104834Sobrien  group_sections (htab, stub_group_size, stubs_always_before_branch);
9150104834Sobrien
9151104834Sobrien  while (1)
9152104834Sobrien    {
9153104834Sobrien      bfd *input_bfd;
9154104834Sobrien      unsigned int bfd_indx;
9155104834Sobrien      asection *stub_sec;
9156104834Sobrien
9157104834Sobrien      htab->stub_iteration += 1;
9158104834Sobrien
9159104834Sobrien      for (input_bfd = info->input_bfds, bfd_indx = 0;
9160104834Sobrien	   input_bfd != NULL;
9161104834Sobrien	   input_bfd = input_bfd->link_next, bfd_indx++)
9162104834Sobrien	{
9163104834Sobrien	  Elf_Internal_Shdr *symtab_hdr;
9164104834Sobrien	  asection *section;
9165104834Sobrien	  Elf_Internal_Sym *local_syms = NULL;
9166104834Sobrien
9167218822Sdim	  if (!is_ppc64_elf_target (input_bfd->xvec))
9168218822Sdim	    continue;
9169218822Sdim
9170104834Sobrien	  /* We'll need the symbol table in a second.  */
9171104834Sobrien	  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
9172104834Sobrien	  if (symtab_hdr->sh_info == 0)
9173104834Sobrien	    continue;
9174104834Sobrien
9175104834Sobrien	  /* Walk over each section attached to the input bfd.  */
9176104834Sobrien	  for (section = input_bfd->sections;
9177104834Sobrien	       section != NULL;
9178104834Sobrien	       section = section->next)
9179104834Sobrien	    {
9180104834Sobrien	      Elf_Internal_Rela *internal_relocs, *irelaend, *irela;
9181104834Sobrien
9182104834Sobrien	      /* If there aren't any relocs, then there's nothing more
9183104834Sobrien		 to do.  */
9184104834Sobrien	      if ((section->flags & SEC_RELOC) == 0
9185218822Sdim		  || (section->flags & SEC_ALLOC) == 0
9186218822Sdim		  || (section->flags & SEC_LOAD) == 0
9187218822Sdim		  || (section->flags & SEC_CODE) == 0
9188104834Sobrien		  || section->reloc_count == 0)
9189104834Sobrien		continue;
9190104834Sobrien
9191104834Sobrien	      /* If this section is a link-once section that will be
9192104834Sobrien		 discarded, then don't create any stubs.  */
9193104834Sobrien	      if (section->output_section == NULL
9194104834Sobrien		  || section->output_section->owner != output_bfd)
9195104834Sobrien		continue;
9196104834Sobrien
9197104834Sobrien	      /* Get the relocs.  */
9198104834Sobrien	      internal_relocs
9199130561Sobrien		= _bfd_elf_link_read_relocs (input_bfd, section, NULL, NULL,
9200130561Sobrien					     info->keep_memory);
9201104834Sobrien	      if (internal_relocs == NULL)
9202104834Sobrien		goto error_ret_free_local;
9203104834Sobrien
9204104834Sobrien	      /* Now examine each relocation.  */
9205104834Sobrien	      irela = internal_relocs;
9206104834Sobrien	      irelaend = irela + section->reloc_count;
9207104834Sobrien	      for (; irela < irelaend; irela++)
9208104834Sobrien		{
9209130561Sobrien		  enum elf_ppc64_reloc_type r_type;
9210130561Sobrien		  unsigned int r_indx;
9211104834Sobrien		  enum ppc_stub_type stub_type;
9212104834Sobrien		  struct ppc_stub_hash_entry *stub_entry;
9213218822Sdim		  asection *sym_sec, *code_sec;
9214104834Sobrien		  bfd_vma sym_value;
9215104834Sobrien		  bfd_vma destination;
9216218822Sdim		  bfd_boolean ok_dest;
9217104834Sobrien		  struct ppc_link_hash_entry *hash;
9218218822Sdim		  struct ppc_link_hash_entry *fdh;
9219130561Sobrien		  struct elf_link_hash_entry *h;
9220130561Sobrien		  Elf_Internal_Sym *sym;
9221104834Sobrien		  char *stub_name;
9222104834Sobrien		  const asection *id_sec;
9223218822Sdim		  long *opd_adjust;
9224104834Sobrien
9225104834Sobrien		  r_type = ELF64_R_TYPE (irela->r_info);
9226104834Sobrien		  r_indx = ELF64_R_SYM (irela->r_info);
9227104834Sobrien
9228130561Sobrien		  if (r_type >= R_PPC64_max)
9229104834Sobrien		    {
9230104834Sobrien		      bfd_set_error (bfd_error_bad_value);
9231104834Sobrien		      goto error_ret_free_internal;
9232104834Sobrien		    }
9233104834Sobrien
9234104834Sobrien		  /* Only look for stubs on branch instructions.  */
9235130561Sobrien		  if (r_type != R_PPC64_REL24
9236130561Sobrien		      && r_type != R_PPC64_REL14
9237130561Sobrien		      && r_type != R_PPC64_REL14_BRTAKEN
9238130561Sobrien		      && r_type != R_PPC64_REL14_BRNTAKEN)
9239104834Sobrien		    continue;
9240104834Sobrien
9241104834Sobrien		  /* Now determine the call target, its name, value,
9242104834Sobrien		     section.  */
9243130561Sobrien		  if (!get_sym_h (&h, &sym, &sym_sec, NULL, &local_syms,
9244130561Sobrien				  r_indx, input_bfd))
9245130561Sobrien		    goto error_ret_free_internal;
9246130561Sobrien		  hash = (struct ppc_link_hash_entry *) h;
9247130561Sobrien
9248218822Sdim		  ok_dest = FALSE;
9249218822Sdim		  fdh = NULL;
9250218822Sdim		  sym_value = 0;
9251130561Sobrien		  if (hash == NULL)
9252104834Sobrien		    {
9253130561Sobrien		      sym_value = sym->st_value;
9254218822Sdim		      ok_dest = TRUE;
9255218822Sdim		    }
9256218822Sdim		  else if (hash->elf.root.type == bfd_link_hash_defined
9257218822Sdim			   || hash->elf.root.type == bfd_link_hash_defweak)
9258218822Sdim		    {
9259218822Sdim		      sym_value = hash->elf.root.u.def.value;
9260218822Sdim		      if (sym_sec->output_section != NULL)
9261218822Sdim			ok_dest = TRUE;
9262218822Sdim		    }
9263218822Sdim		  else if (hash->elf.root.type == bfd_link_hash_undefweak
9264218822Sdim			   || hash->elf.root.type == bfd_link_hash_undefined)
9265218822Sdim		    {
9266218822Sdim		      /* Recognise an old ABI func code entry sym, and
9267218822Sdim			 use the func descriptor sym instead if it is
9268218822Sdim			 defined.  */
9269218822Sdim		      if (hash->elf.root.root.string[0] == '.'
9270218822Sdim			  && (fdh = get_fdh (hash, htab)) != NULL)
9271218822Sdim			{
9272218822Sdim			  if (fdh->elf.root.type == bfd_link_hash_defined
9273218822Sdim			      || fdh->elf.root.type == bfd_link_hash_defweak)
9274218822Sdim			    {
9275218822Sdim			      sym_sec = fdh->elf.root.u.def.section;
9276218822Sdim			      sym_value = fdh->elf.root.u.def.value;
9277218822Sdim			      if (sym_sec->output_section != NULL)
9278218822Sdim				ok_dest = TRUE;
9279218822Sdim			    }
9280218822Sdim			  else
9281218822Sdim			    fdh = NULL;
9282218822Sdim			}
9283218822Sdim		    }
9284218822Sdim		  else
9285218822Sdim		    {
9286218822Sdim		      bfd_set_error (bfd_error_bad_value);
9287218822Sdim		      goto error_ret_free_internal;
9288218822Sdim		    }
9289218822Sdim
9290218822Sdim		  destination = 0;
9291218822Sdim		  if (ok_dest)
9292218822Sdim		    {
9293218822Sdim		      sym_value += irela->r_addend;
9294218822Sdim		      destination = (sym_value
9295104834Sobrien				     + sym_sec->output_offset
9296104834Sobrien				     + sym_sec->output_section->vma);
9297104834Sobrien		    }
9298218822Sdim
9299218822Sdim		  code_sec = sym_sec;
9300218822Sdim		  opd_adjust = get_opd_info (sym_sec);
9301218822Sdim		  if (opd_adjust != NULL)
9302104834Sobrien		    {
9303218822Sdim		      bfd_vma dest;
9304218822Sdim
9305218822Sdim		      if (hash == NULL)
9306104834Sobrien			{
9307218822Sdim			  long adjust = opd_adjust[sym_value / 8];
9308218822Sdim			  if (adjust == -1)
9309218822Sdim			    continue;
9310218822Sdim			  sym_value += adjust;
9311104834Sobrien			}
9312218822Sdim		      dest = opd_entry_value (sym_sec, sym_value,
9313218822Sdim					      &code_sec, &sym_value);
9314218822Sdim		      if (dest != (bfd_vma) -1)
9315104834Sobrien			{
9316218822Sdim			  destination = dest;
9317218822Sdim			  if (fdh != NULL)
9318218822Sdim			    {
9319218822Sdim			      /* Fixup old ABI sym to point at code
9320218822Sdim				 entry.  */
9321218822Sdim			      hash->elf.root.type = bfd_link_hash_defweak;
9322218822Sdim			      hash->elf.root.u.def.section = code_sec;
9323218822Sdim			      hash->elf.root.u.def.value = sym_value;
9324218822Sdim			    }
9325104834Sobrien			}
9326104834Sobrien		    }
9327104834Sobrien
9328104834Sobrien		  /* Determine what (if any) linker stub is needed.  */
9329104834Sobrien		  stub_type = ppc_type_of_stub (section, irela, &hash,
9330104834Sobrien						destination);
9331130561Sobrien
9332130561Sobrien		  if (stub_type != ppc_stub_plt_call)
9333130561Sobrien		    {
9334130561Sobrien		      /* Check whether we need a TOC adjusting stub.
9335130561Sobrien			 Since the linker pastes together pieces from
9336130561Sobrien			 different object files when creating the
9337130561Sobrien			 _init and _fini functions, it may be that a
9338130561Sobrien			 call to what looks like a local sym is in
9339130561Sobrien			 fact a call needing a TOC adjustment.  */
9340218822Sdim		      if (code_sec != NULL
9341218822Sdim			  && code_sec->output_section != NULL
9342218822Sdim			  && (htab->stub_group[code_sec->id].toc_off
9343130561Sobrien			      != htab->stub_group[section->id].toc_off)
9344218822Sdim			  && (code_sec->has_toc_reloc
9345218822Sdim			      || code_sec->makes_toc_func_call))
9346130561Sobrien			stub_type = ppc_stub_long_branch_r2off;
9347130561Sobrien		    }
9348130561Sobrien
9349104834Sobrien		  if (stub_type == ppc_stub_none)
9350104834Sobrien		    continue;
9351104834Sobrien
9352130561Sobrien		  /* __tls_get_addr calls might be eliminated.  */
9353130561Sobrien		  if (stub_type != ppc_stub_plt_call
9354130561Sobrien		      && hash != NULL
9355218822Sdim		      && (hash == htab->tls_get_addr
9356218822Sdim			  || hash == htab->tls_get_addr_fd)
9357130561Sobrien		      && section->has_tls_reloc
9358130561Sobrien		      && irela != internal_relocs)
9359130561Sobrien		    {
9360130561Sobrien		      /* Get tls info.  */
9361130561Sobrien		      char *tls_mask;
9362130561Sobrien
9363130561Sobrien		      if (!get_tls_mask (&tls_mask, NULL, &local_syms,
9364130561Sobrien					 irela - 1, input_bfd))
9365130561Sobrien			goto error_ret_free_internal;
9366130561Sobrien		      if (*tls_mask != 0)
9367130561Sobrien			continue;
9368130561Sobrien		    }
9369130561Sobrien
9370104834Sobrien		  /* Support for grouping stub sections.  */
9371104834Sobrien		  id_sec = htab->stub_group[section->id].link_sec;
9372104834Sobrien
9373104834Sobrien		  /* Get the name of this stub.  */
9374104834Sobrien		  stub_name = ppc_stub_name (id_sec, sym_sec, hash, irela);
9375104834Sobrien		  if (!stub_name)
9376104834Sobrien		    goto error_ret_free_internal;
9377104834Sobrien
9378104834Sobrien		  stub_entry = ppc_stub_hash_lookup (&htab->stub_hash_table,
9379130561Sobrien						     stub_name, FALSE, FALSE);
9380104834Sobrien		  if (stub_entry != NULL)
9381104834Sobrien		    {
9382104834Sobrien		      /* The proper stub has already been created.  */
9383104834Sobrien		      free (stub_name);
9384104834Sobrien		      continue;
9385104834Sobrien		    }
9386104834Sobrien
9387104834Sobrien		  stub_entry = ppc_add_stub (stub_name, section, htab);
9388104834Sobrien		  if (stub_entry == NULL)
9389104834Sobrien		    {
9390104834Sobrien		      free (stub_name);
9391104834Sobrien		    error_ret_free_internal:
9392104834Sobrien		      if (elf_section_data (section)->relocs == NULL)
9393104834Sobrien			free (internal_relocs);
9394104834Sobrien		    error_ret_free_local:
9395104834Sobrien		      if (local_syms != NULL
9396104834Sobrien			  && (symtab_hdr->contents
9397104834Sobrien			      != (unsigned char *) local_syms))
9398104834Sobrien			free (local_syms);
9399130561Sobrien		      return FALSE;
9400104834Sobrien		    }
9401104834Sobrien
9402130561Sobrien		  stub_entry->stub_type = stub_type;
9403104834Sobrien		  stub_entry->target_value = sym_value;
9404218822Sdim		  stub_entry->target_section = code_sec;
9405104834Sobrien		  stub_entry->h = hash;
9406130561Sobrien		  stub_entry->addend = irela->r_addend;
9407218822Sdim
9408218822Sdim		  if (stub_entry->h != NULL)
9409218822Sdim		    htab->stub_globals += 1;
9410104834Sobrien		}
9411104834Sobrien
9412104834Sobrien	      /* We're done with the internal relocs, free them.  */
9413104834Sobrien	      if (elf_section_data (section)->relocs != internal_relocs)
9414104834Sobrien		free (internal_relocs);
9415104834Sobrien	    }
9416104834Sobrien
9417104834Sobrien	  if (local_syms != NULL
9418104834Sobrien	      && symtab_hdr->contents != (unsigned char *) local_syms)
9419104834Sobrien	    {
9420104834Sobrien	      if (!info->keep_memory)
9421104834Sobrien		free (local_syms);
9422104834Sobrien	      else
9423104834Sobrien		symtab_hdr->contents = (unsigned char *) local_syms;
9424104834Sobrien	    }
9425104834Sobrien	}
9426104834Sobrien
9427218822Sdim      /* We may have added some stubs.  Find out the new size of the
9428104834Sobrien	 stub sections.  */
9429104834Sobrien      for (stub_sec = htab->stub_bfd->sections;
9430104834Sobrien	   stub_sec != NULL;
9431104834Sobrien	   stub_sec = stub_sec->next)
9432130561Sobrien	if ((stub_sec->flags & SEC_LINKER_CREATED) == 0)
9433130561Sobrien	  {
9434218822Sdim	    stub_sec->rawsize = stub_sec->size;
9435218822Sdim	    stub_sec->size = 0;
9436218822Sdim	    stub_sec->reloc_count = 0;
9437218822Sdim	    stub_sec->flags &= ~SEC_RELOC;
9438130561Sobrien	  }
9439104834Sobrien
9440218822Sdim      htab->brlt->size = 0;
9441218822Sdim      htab->brlt->reloc_count = 0;
9442218822Sdim      htab->brlt->flags &= ~SEC_RELOC;
9443218822Sdim      if (htab->relbrlt != NULL)
9444218822Sdim	htab->relbrlt->size = 0;
9445218822Sdim
9446130561Sobrien      bfd_hash_traverse (&htab->stub_hash_table, ppc_size_one_stub, info);
9447104834Sobrien
9448218822Sdim      for (stub_sec = htab->stub_bfd->sections;
9449218822Sdim	   stub_sec != NULL;
9450218822Sdim	   stub_sec = stub_sec->next)
9451218822Sdim	if ((stub_sec->flags & SEC_LINKER_CREATED) == 0
9452218822Sdim	    && stub_sec->rawsize != stub_sec->size)
9453218822Sdim	  break;
9454218822Sdim
9455218822Sdim      /* Exit from this loop when no stubs have been added, and no stubs
9456218822Sdim	 have changed size.  */
9457218822Sdim      if (stub_sec == NULL)
9458218822Sdim	break;
9459218822Sdim
9460104834Sobrien      /* Ask the linker to do its stuff.  */
9461104834Sobrien      (*htab->layout_sections_again) ();
9462104834Sobrien    }
9463104834Sobrien
9464218822Sdim  /* It would be nice to strip htab->brlt from the output if the
9465104834Sobrien     section is empty, but it's too late.  If we strip sections here,
9466104834Sobrien     the dynamic symbol table is corrupted since the section symbol
9467104834Sobrien     for the stripped section isn't written.  */
9468104834Sobrien
9469130561Sobrien  return TRUE;
947089857Sobrien}
947189857Sobrien
9472104834Sobrien/* Called after we have determined section placement.  If sections
9473104834Sobrien   move, we'll be called again.  Provide a value for TOCstart.  */
9474104834Sobrien
9475104834Sobrienbfd_vma
9476130561Sobrienppc64_elf_toc (bfd *obfd)
9477104834Sobrien{
9478104834Sobrien  asection *s;
9479104834Sobrien  bfd_vma TOCstart;
9480104834Sobrien
9481104834Sobrien  /* The TOC consists of sections .got, .toc, .tocbss, .plt in that
9482104834Sobrien     order.  The TOC starts where the first of these sections starts.  */
9483104834Sobrien  s = bfd_get_section_by_name (obfd, ".got");
9484104834Sobrien  if (s == NULL)
9485104834Sobrien    s = bfd_get_section_by_name (obfd, ".toc");
9486104834Sobrien  if (s == NULL)
9487104834Sobrien    s = bfd_get_section_by_name (obfd, ".tocbss");
9488104834Sobrien  if (s == NULL)
9489104834Sobrien    s = bfd_get_section_by_name (obfd, ".plt");
9490104834Sobrien  if (s == NULL)
9491104834Sobrien    {
9492104834Sobrien      /* This may happen for
9493104834Sobrien	 o  references to TOC base (SYM@toc / TOC[tc0]) without a
9494104834Sobrien	 .toc directive
9495104834Sobrien	 o  bad linker script
9496104834Sobrien	 o --gc-sections and empty TOC sections
9497104834Sobrien
9498104834Sobrien	 FIXME: Warn user?  */
9499104834Sobrien
9500104834Sobrien      /* Look for a likely section.  We probably won't even be
9501104834Sobrien	 using TOCstart.  */
9502104834Sobrien      for (s = obfd->sections; s != NULL; s = s->next)
9503104834Sobrien	if ((s->flags & (SEC_ALLOC | SEC_SMALL_DATA | SEC_READONLY))
9504104834Sobrien	    == (SEC_ALLOC | SEC_SMALL_DATA))
9505104834Sobrien	  break;
9506104834Sobrien      if (s == NULL)
9507104834Sobrien	for (s = obfd->sections; s != NULL; s = s->next)
9508104834Sobrien	  if ((s->flags & (SEC_ALLOC | SEC_SMALL_DATA))
9509104834Sobrien	      == (SEC_ALLOC | SEC_SMALL_DATA))
9510104834Sobrien	    break;
9511104834Sobrien      if (s == NULL)
9512104834Sobrien	for (s = obfd->sections; s != NULL; s = s->next)
9513104834Sobrien	  if ((s->flags & (SEC_ALLOC | SEC_READONLY)) == SEC_ALLOC)
9514104834Sobrien	    break;
9515104834Sobrien      if (s == NULL)
9516104834Sobrien	for (s = obfd->sections; s != NULL; s = s->next)
9517104834Sobrien	  if ((s->flags & SEC_ALLOC) == SEC_ALLOC)
9518104834Sobrien	    break;
9519104834Sobrien    }
9520104834Sobrien
9521104834Sobrien  TOCstart = 0;
9522104834Sobrien  if (s != NULL)
9523104834Sobrien    TOCstart = s->output_section->vma + s->output_offset;
9524104834Sobrien
9525104834Sobrien  return TOCstart;
9526104834Sobrien}
9527104834Sobrien
9528104834Sobrien/* Build all the stubs associated with the current output file.
9529104834Sobrien   The stubs are kept in a hash table attached to the main linker
9530104834Sobrien   hash table.  This function is called via gldelf64ppc_finish.  */
9531104834Sobrien
9532130561Sobrienbfd_boolean
9533130561Sobrienppc64_elf_build_stubs (bfd_boolean emit_stub_syms,
9534130561Sobrien		       struct bfd_link_info *info,
9535130561Sobrien		       char **stats)
9536104834Sobrien{
9537104834Sobrien  struct ppc_link_hash_table *htab = ppc_hash_table (info);
9538104834Sobrien  asection *stub_sec;
9539104834Sobrien  bfd_byte *p;
9540130561Sobrien  int stub_sec_count = 0;
9541104834Sobrien
9542130561Sobrien  htab->emit_stub_syms = emit_stub_syms;
9543218822Sdim
9544218822Sdim  /* Allocate memory to hold the linker stubs.  */
9545104834Sobrien  for (stub_sec = htab->stub_bfd->sections;
9546104834Sobrien       stub_sec != NULL;
9547104834Sobrien       stub_sec = stub_sec->next)
9548218822Sdim    if ((stub_sec->flags & SEC_LINKER_CREATED) == 0
9549218822Sdim	&& stub_sec->size != 0)
9550130561Sobrien      {
9551218822Sdim	stub_sec->contents = bfd_zalloc (htab->stub_bfd, stub_sec->size);
9552218822Sdim	if (stub_sec->contents == NULL)
9553218822Sdim	  return FALSE;
9554218822Sdim	/* We want to check that built size is the same as calculated
9555218822Sdim	   size.  rawsize is a convenient location to use.  */
9556218822Sdim	stub_sec->rawsize = stub_sec->size;
9557218822Sdim	stub_sec->size = 0;
9558130561Sobrien      }
9559104834Sobrien
9560218822Sdim  if (htab->glink != NULL && htab->glink->size != 0)
9561104834Sobrien    {
9562104834Sobrien      unsigned int indx;
9563130561Sobrien      bfd_vma plt0;
9564104834Sobrien
9565104834Sobrien      /* Build the .glink plt call stub.  */
9566130561Sobrien      if (htab->emit_stub_syms)
9567130561Sobrien	{
9568130561Sobrien	  struct elf_link_hash_entry *h;
9569130561Sobrien	  h = elf_link_hash_lookup (&htab->elf, "__glink", TRUE, FALSE, FALSE);
9570130561Sobrien	  if (h == NULL)
9571130561Sobrien	    return FALSE;
9572130561Sobrien	  if (h->root.type == bfd_link_hash_new)
9573130561Sobrien	    {
9574130561Sobrien	      h->root.type = bfd_link_hash_defined;
9575130561Sobrien	      h->root.u.def.section = htab->glink;
9576218822Sdim	      h->root.u.def.value = 8;
9577218822Sdim	      h->ref_regular = 1;
9578218822Sdim	      h->def_regular = 1;
9579218822Sdim	      h->ref_regular_nonweak = 1;
9580218822Sdim	      h->forced_local = 1;
9581218822Sdim	      h->non_elf = 0;
9582130561Sobrien	    }
9583130561Sobrien	}
9584130561Sobrien      p = htab->glink->contents;
9585218822Sdim      plt0 = (htab->plt->output_section->vma
9586218822Sdim	      + htab->plt->output_offset
9587218822Sdim	      - (htab->glink->output_section->vma
9588218822Sdim		 + htab->glink->output_offset
9589218822Sdim		 + 16));
9590218822Sdim      bfd_put_64 (htab->glink->owner, plt0, p);
9591218822Sdim      p += 8;
9592218822Sdim      bfd_put_32 (htab->glink->owner, MFLR_R12, p);
9593130561Sobrien      p += 4;
9594218822Sdim      bfd_put_32 (htab->glink->owner, BCL_20_31, p);
9595130561Sobrien      p += 4;
9596218822Sdim      bfd_put_32 (htab->glink->owner, MFLR_R11, p);
9597130561Sobrien      p += 4;
9598218822Sdim      bfd_put_32 (htab->glink->owner, LD_R2_M16R11, p);
9599130561Sobrien      p += 4;
9600218822Sdim      bfd_put_32 (htab->glink->owner, MTLR_R12, p);
9601130561Sobrien      p += 4;
9602218822Sdim      bfd_put_32 (htab->glink->owner, ADD_R12_R2_R11, p);
9603130561Sobrien      p += 4;
9604218822Sdim      bfd_put_32 (htab->glink->owner, LD_R11_0R12, p);
9605130561Sobrien      p += 4;
9606130561Sobrien      bfd_put_32 (htab->glink->owner, LD_R2_0R12 | 8, p);
9607130561Sobrien      p += 4;
9608130561Sobrien      bfd_put_32 (htab->glink->owner, MTCTR_R11, p);
9609130561Sobrien      p += 4;
9610130561Sobrien      bfd_put_32 (htab->glink->owner, LD_R11_0R12 | 16, p);
9611130561Sobrien      p += 4;
9612130561Sobrien      bfd_put_32 (htab->glink->owner, BCTR, p);
9613130561Sobrien      p += 4;
9614218822Sdim      while (p - htab->glink->contents < GLINK_CALL_STUB_SIZE)
9615218822Sdim	{
9616218822Sdim	  bfd_put_32 (htab->glink->owner, NOP, p);
9617218822Sdim	  p += 4;
9618218822Sdim	}
9619130561Sobrien
9620104834Sobrien      /* Build the .glink lazy link call stubs.  */
9621104834Sobrien      indx = 0;
9622218822Sdim      while (p < htab->glink->contents + htab->glink->size)
9623104834Sobrien	{
9624104834Sobrien	  if (indx < 0x8000)
9625104834Sobrien	    {
9626130561Sobrien	      bfd_put_32 (htab->glink->owner, LI_R0_0 | indx, p);
9627104834Sobrien	      p += 4;
9628104834Sobrien	    }
9629104834Sobrien	  else
9630104834Sobrien	    {
9631130561Sobrien	      bfd_put_32 (htab->glink->owner, LIS_R0_0 | PPC_HI (indx), p);
9632104834Sobrien	      p += 4;
9633130561Sobrien	      bfd_put_32 (htab->glink->owner, ORI_R0_R0_0 | PPC_LO (indx), p);
9634104834Sobrien	      p += 4;
9635104834Sobrien	    }
9636130561Sobrien	  bfd_put_32 (htab->glink->owner,
9637218822Sdim		      B_DOT | ((htab->glink->contents - p + 8) & 0x3fffffc), p);
9638104834Sobrien	  indx++;
9639104834Sobrien	  p += 4;
9640104834Sobrien	}
9641218822Sdim      htab->glink->rawsize = p - htab->glink->contents;
9642104834Sobrien    }
9643104834Sobrien
9644218822Sdim  if (htab->brlt->size != 0)
9645104834Sobrien    {
9646130561Sobrien      htab->brlt->contents = bfd_zalloc (htab->brlt->owner,
9647218822Sdim					 htab->brlt->size);
9648130561Sobrien      if (htab->brlt->contents == NULL)
9649130561Sobrien	return FALSE;
9650104834Sobrien    }
9651218822Sdim  if (htab->relbrlt != NULL && htab->relbrlt->size != 0)
9652130561Sobrien    {
9653130561Sobrien      htab->relbrlt->contents = bfd_zalloc (htab->relbrlt->owner,
9654218822Sdim					    htab->relbrlt->size);
9655130561Sobrien      if (htab->relbrlt->contents == NULL)
9656130561Sobrien	return FALSE;
9657130561Sobrien    }
9658104834Sobrien
9659104834Sobrien  /* Build the stubs as directed by the stub hash table.  */
9660104834Sobrien  bfd_hash_traverse (&htab->stub_hash_table, ppc_build_one_stub, info);
9661104834Sobrien
9662218822Sdim  if (htab->relbrlt != NULL)
9663218822Sdim    htab->relbrlt->reloc_count = 0;
9664218822Sdim
9665104834Sobrien  for (stub_sec = htab->stub_bfd->sections;
9666104834Sobrien       stub_sec != NULL;
9667104834Sobrien       stub_sec = stub_sec->next)
9668130561Sobrien    if ((stub_sec->flags & SEC_LINKER_CREATED) == 0)
9669130561Sobrien      {
9670130561Sobrien	stub_sec_count += 1;
9671218822Sdim	if (stub_sec->rawsize != stub_sec->size)
9672130561Sobrien	  break;
9673130561Sobrien      }
9674104834Sobrien
9675104834Sobrien  if (stub_sec != NULL
9676218822Sdim      || htab->glink->rawsize != htab->glink->size)
9677104834Sobrien    {
9678130561Sobrien      htab->stub_error = TRUE;
9679104834Sobrien      (*_bfd_error_handler) (_("stubs don't match calculated size"));
9680104834Sobrien    }
9681104834Sobrien
9682130561Sobrien  if (htab->stub_error)
9683130561Sobrien    return FALSE;
9684130561Sobrien
9685130561Sobrien  if (stats != NULL)
9686130561Sobrien    {
9687130561Sobrien      *stats = bfd_malloc (500);
9688130561Sobrien      if (*stats == NULL)
9689130561Sobrien	return FALSE;
9690130561Sobrien
9691218822Sdim      sprintf (*stats, _("linker stubs in %u group%s\n"
9692130561Sobrien			 "  branch       %lu\n"
9693130561Sobrien			 "  toc adjust   %lu\n"
9694130561Sobrien			 "  long branch  %lu\n"
9695130561Sobrien			 "  long toc adj %lu\n"
9696130561Sobrien			 "  plt call     %lu"),
9697130561Sobrien	       stub_sec_count,
9698218822Sdim	       stub_sec_count == 1 ? "" : "s",
9699130561Sobrien	       htab->stub_count[ppc_stub_long_branch - 1],
9700130561Sobrien	       htab->stub_count[ppc_stub_long_branch_r2off - 1],
9701130561Sobrien	       htab->stub_count[ppc_stub_plt_branch - 1],
9702130561Sobrien	       htab->stub_count[ppc_stub_plt_branch_r2off - 1],
9703130561Sobrien	       htab->stub_count[ppc_stub_plt_call - 1]);
9704130561Sobrien    }
9705130561Sobrien  return TRUE;
9706104834Sobrien}
9707104834Sobrien
9708218822Sdim/* This function undoes the changes made by add_symbol_adjust.  */
9709218822Sdim
9710218822Sdimstatic bfd_boolean
9711218822Sdimundo_symbol_twiddle (struct elf_link_hash_entry *h, void *inf ATTRIBUTE_UNUSED)
9712218822Sdim{
9713218822Sdim  struct ppc_link_hash_entry *eh;
9714218822Sdim
9715218822Sdim  if (h->root.type == bfd_link_hash_indirect)
9716218822Sdim    return TRUE;
9717218822Sdim
9718218822Sdim  if (h->root.type == bfd_link_hash_warning)
9719218822Sdim    h = (struct elf_link_hash_entry *) h->root.u.i.link;
9720218822Sdim
9721218822Sdim  eh = (struct ppc_link_hash_entry *) h;
9722218822Sdim  if (eh->elf.root.type != bfd_link_hash_undefweak || !eh->was_undefined)
9723218822Sdim    return TRUE;
9724218822Sdim
9725218822Sdim  eh->elf.root.type = bfd_link_hash_undefined;
9726218822Sdim  return TRUE;
9727218822Sdim}
9728218822Sdim
9729218822Sdimvoid
9730218822Sdimppc64_elf_restore_symbols (struct bfd_link_info *info)
9731218822Sdim{
9732218822Sdim  struct ppc_link_hash_table *htab = ppc_hash_table (info);
9733218822Sdim  elf_link_hash_traverse (&htab->elf, undo_symbol_twiddle, info);
9734218822Sdim}
9735218822Sdim
9736218822Sdim/* What to do when ld finds relocations against symbols defined in
9737218822Sdim   discarded sections.  */
9738218822Sdim
9739218822Sdimstatic unsigned int
9740218822Sdimppc64_elf_action_discarded (asection *sec)
9741218822Sdim{
9742218822Sdim  if (strcmp (".opd", sec->name) == 0)
9743218822Sdim    return 0;
9744218822Sdim
9745218822Sdim  if (strcmp (".toc", sec->name) == 0)
9746218822Sdim    return 0;
9747218822Sdim
9748218822Sdim  if (strcmp (".toc1", sec->name) == 0)
9749218822Sdim    return 0;
9750218822Sdim
9751218822Sdim  if (sec->flags & SEC_RELOC)
9752218822Sdim    return 0;
9753218822Sdim
9754218822Sdim  return _bfd_elf_default_action_discarded (sec);
9755218822Sdim}
9756218822Sdim
975789857Sobrien/* The RELOCATE_SECTION function is called by the ELF backend linker
975889857Sobrien   to handle the relocations for a section.
975989857Sobrien
976089857Sobrien   The relocs are always passed as Rela structures; if the section
976189857Sobrien   actually uses Rel structures, the r_addend field will always be
976289857Sobrien   zero.
976389857Sobrien
976489857Sobrien   This function is responsible for adjust the section contents as
976589857Sobrien   necessary, and (if using Rela relocs and generating a
9766130561Sobrien   relocatable output file) adjusting the reloc addend as
976789857Sobrien   necessary.
976889857Sobrien
976989857Sobrien   This function does not have to worry about setting the reloc
977089857Sobrien   address or the reloc symbol index.
977189857Sobrien
977289857Sobrien   LOCAL_SYMS is a pointer to the swapped in local symbols.
977389857Sobrien
977489857Sobrien   LOCAL_SECTIONS is an array giving the section in the input file
977589857Sobrien   corresponding to the st_shndx field of each local symbol.
977689857Sobrien
977789857Sobrien   The global hash table entry for the global symbols can be found
977889857Sobrien   via elf_sym_hashes (input_bfd).
977989857Sobrien
9780130561Sobrien   When generating relocatable output, this function must handle
978189857Sobrien   STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
978289857Sobrien   going to be the section symbol corresponding to the output
978389857Sobrien   section, which means that the addend must be adjusted
978489857Sobrien   accordingly.  */
978589857Sobrien
9786130561Sobrienstatic bfd_boolean
9787130561Sobrienppc64_elf_relocate_section (bfd *output_bfd,
9788130561Sobrien			    struct bfd_link_info *info,
9789130561Sobrien			    bfd *input_bfd,
9790130561Sobrien			    asection *input_section,
9791130561Sobrien			    bfd_byte *contents,
9792130561Sobrien			    Elf_Internal_Rela *relocs,
9793130561Sobrien			    Elf_Internal_Sym *local_syms,
9794130561Sobrien			    asection **local_sections)
979589857Sobrien{
979689857Sobrien  struct ppc_link_hash_table *htab;
979789857Sobrien  Elf_Internal_Shdr *symtab_hdr;
979889857Sobrien  struct elf_link_hash_entry **sym_hashes;
979989857Sobrien  Elf_Internal_Rela *rel;
980089857Sobrien  Elf_Internal_Rela *relend;
9801130561Sobrien  Elf_Internal_Rela outrel;
9802130561Sobrien  bfd_byte *loc;
9803130561Sobrien  struct got_entry **local_got_ents;
980489857Sobrien  bfd_vma TOCstart;
9805130561Sobrien  bfd_boolean ret = TRUE;
9806130561Sobrien  bfd_boolean is_opd;
980792828Sobrien  /* Disabled until we sort out how ld should choose 'y' vs 'at'.  */
9808130561Sobrien  bfd_boolean is_power4 = FALSE;
9809218822Sdim  bfd_vma d_offset = (bfd_big_endian (output_bfd) ? 2 : 0);
981089857Sobrien
981189857Sobrien  /* Initialize howto table if needed.  */
981289857Sobrien  if (!ppc64_elf_howto_table[R_PPC64_ADDR32])
981389857Sobrien    ppc_howto_init ();
981489857Sobrien
981589857Sobrien  htab = ppc_hash_table (info);
9816218822Sdim
9817218822Sdim  /* Don't relocate stub sections.  */
9818218822Sdim  if (input_section->owner == htab->stub_bfd)
9819218822Sdim    return TRUE;
9820218822Sdim
9821130561Sobrien  local_got_ents = elf_local_got_ents (input_bfd);
982289857Sobrien  TOCstart = elf_gp (output_bfd);
982389857Sobrien  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
982489857Sobrien  sym_hashes = elf_sym_hashes (input_bfd);
9825218822Sdim  is_opd = ppc64_elf_section_data (input_section)->sec_type == sec_opd;
982689857Sobrien
982789857Sobrien  rel = relocs;
982889857Sobrien  relend = relocs + input_section->reloc_count;
982989857Sobrien  for (; rel < relend; rel++)
983089857Sobrien    {
9831130561Sobrien      enum elf_ppc64_reloc_type r_type;
9832218822Sdim      bfd_vma addend, orig_addend;
983389857Sobrien      bfd_reloc_status_type r;
983489857Sobrien      Elf_Internal_Sym *sym;
983589857Sobrien      asection *sec;
9836218822Sdim      struct elf_link_hash_entry *h_elf;
9837218822Sdim      struct ppc_link_hash_entry *h;
9838218822Sdim      struct ppc_link_hash_entry *fdh;
983989857Sobrien      const char *sym_name;
9840130561Sobrien      unsigned long r_symndx, toc_symndx;
9841130561Sobrien      char tls_mask, tls_gd, tls_type;
9842130561Sobrien      char sym_type;
984389857Sobrien      bfd_vma relocation;
9844130561Sobrien      bfd_boolean unresolved_reloc;
9845130561Sobrien      bfd_boolean warned;
9846130561Sobrien      unsigned long insn, mask;
9847104834Sobrien      struct ppc_stub_hash_entry *stub_entry;
9848104834Sobrien      bfd_vma max_br_offset;
984999461Sobrien      bfd_vma from;
985089857Sobrien
9851130561Sobrien      r_type = ELF64_R_TYPE (rel->r_info);
985289857Sobrien      r_symndx = ELF64_R_SYM (rel->r_info);
985389857Sobrien
9854130561Sobrien      /* For old style R_PPC64_TOC relocs with a zero symbol, use the
9855130561Sobrien	 symbol of the previous ADDR64 reloc.  The symbol gives us the
9856130561Sobrien	 proper TOC base to use.  */
9857130561Sobrien      if (rel->r_info == ELF64_R_INFO (0, R_PPC64_TOC)
9858130561Sobrien	  && rel != relocs
9859130561Sobrien	  && ELF64_R_TYPE (rel[-1].r_info) == R_PPC64_ADDR64
9860130561Sobrien	  && is_opd)
9861130561Sobrien	r_symndx = ELF64_R_SYM (rel[-1].r_info);
9862130561Sobrien
9863130561Sobrien      sym = NULL;
9864130561Sobrien      sec = NULL;
9865218822Sdim      h_elf = NULL;
9866130561Sobrien      sym_name = NULL;
9867130561Sobrien      unresolved_reloc = FALSE;
9868130561Sobrien      warned = FALSE;
9869218822Sdim      orig_addend = rel->r_addend;
9870130561Sobrien
9871130561Sobrien      if (r_symndx < symtab_hdr->sh_info)
987289857Sobrien	{
987389857Sobrien	  /* It's a local symbol.  */
9874218822Sdim	  long *opd_adjust;
9875218822Sdim
987689857Sobrien	  sym = local_syms + r_symndx;
987789857Sobrien	  sec = local_sections[r_symndx];
9878218822Sdim	  sym_name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym, sec);
9879130561Sobrien	  sym_type = ELF64_ST_TYPE (sym->st_info);
9880130561Sobrien	  relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
9881218822Sdim	  opd_adjust = get_opd_info (sec);
9882218822Sdim	  if (opd_adjust != NULL)
9883104834Sobrien	    {
9884218822Sdim	      long adjust = opd_adjust[(sym->st_value + rel->r_addend) / 8];
9885218822Sdim	      if (adjust == -1)
9886218822Sdim		relocation = 0;
9887218822Sdim	      else
9888218822Sdim		{
9889218822Sdim		  /* If this is a relocation against the opd section sym
9890218822Sdim		     and we have edited .opd, adjust the reloc addend so
9891218822Sdim		     that ld -r and ld --emit-relocs output is correct.
9892218822Sdim		     If it is a reloc against some other .opd symbol,
9893218822Sdim		     then the symbol value will be adjusted later.  */
9894218822Sdim		  if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
9895218822Sdim		    rel->r_addend += adjust;
9896218822Sdim		  else
9897218822Sdim		    relocation += adjust;
9898218822Sdim		}
9899104834Sobrien	    }
990089857Sobrien	}
990189857Sobrien      else
990289857Sobrien	{
9903130561Sobrien	  RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
9904130561Sobrien				   r_symndx, symtab_hdr, sym_hashes,
9905218822Sdim				   h_elf, sec, relocation,
9906130561Sobrien				   unresolved_reloc, warned);
9907218822Sdim	  sym_name = h_elf->root.root.string;
9908218822Sdim	  sym_type = h_elf->type;
9909130561Sobrien	}
9910218822Sdim      h = (struct ppc_link_hash_entry *) h_elf;
9911130561Sobrien
9912218822Sdim      if (sec != NULL && elf_discarded_section (sec))
9913218822Sdim	{
9914218822Sdim	  /* For relocs against symbols from removed linkonce sections,
9915218822Sdim	     or sections discarded by a linker script, we just want the
9916218822Sdim	     section contents zeroed.  Avoid any special processing.  */
9917218822Sdim	  _bfd_clear_contents (ppc64_elf_howto_table[r_type], input_bfd,
9918218822Sdim			       contents + rel->r_offset);
9919218822Sdim	  rel->r_info = 0;
9920218822Sdim	  rel->r_addend = 0;
9921218822Sdim	  continue;
9922218822Sdim	}
9923218822Sdim
9924218822Sdim      if (info->relocatable)
9925218822Sdim	continue;
9926218822Sdim
9927130561Sobrien      /* TLS optimizations.  Replace instruction sequences and relocs
9928130561Sobrien	 based on information we collected in tls_optimize.  We edit
9929130561Sobrien	 RELOCS so that --emit-relocs will output something sensible
9930130561Sobrien	 for the final instruction stream.  */
9931130561Sobrien      tls_mask = 0;
9932130561Sobrien      tls_gd = 0;
9933130561Sobrien      toc_symndx = 0;
9934130561Sobrien      if (IS_PPC64_TLS_RELOC (r_type))
9935130561Sobrien	{
9936130561Sobrien	  if (h != NULL)
9937218822Sdim	    tls_mask = h->tls_mask;
9938130561Sobrien	  else if (local_got_ents != NULL)
9939130561Sobrien	    {
9940130561Sobrien	      char *lgot_masks;
9941130561Sobrien	      lgot_masks = (char *) (local_got_ents + symtab_hdr->sh_info);
9942130561Sobrien	      tls_mask = lgot_masks[r_symndx];
9943130561Sobrien	    }
9944130561Sobrien	  if (tls_mask == 0 && r_type == R_PPC64_TLS)
9945130561Sobrien	    {
9946130561Sobrien	      /* Check for toc tls entries.  */
9947130561Sobrien	      char *toc_tls;
9948130561Sobrien
9949130561Sobrien	      if (!get_tls_mask (&toc_tls, &toc_symndx, &local_syms,
9950130561Sobrien				 rel, input_bfd))
9951130561Sobrien		return FALSE;
9952130561Sobrien
9953130561Sobrien	      if (toc_tls)
9954130561Sobrien		tls_mask = *toc_tls;
9955130561Sobrien	    }
9956130561Sobrien	}
9957130561Sobrien
9958130561Sobrien      /* Check that tls relocs are used with tls syms, and non-tls
9959130561Sobrien	 relocs are used with non-tls syms.  */
9960130561Sobrien      if (r_symndx != 0
9961130561Sobrien	  && r_type != R_PPC64_NONE
9962130561Sobrien	  && (h == NULL
9963218822Sdim	      || h->elf.root.type == bfd_link_hash_defined
9964218822Sdim	      || h->elf.root.type == bfd_link_hash_defweak)
9965130561Sobrien	  && IS_PPC64_TLS_RELOC (r_type) != (sym_type == STT_TLS))
9966130561Sobrien	{
9967130561Sobrien	  if (r_type == R_PPC64_TLS && tls_mask != 0)
9968130561Sobrien	    /* R_PPC64_TLS is OK against a symbol in the TOC.  */
9969130561Sobrien	    ;
9970130561Sobrien	  else
9971130561Sobrien	    (*_bfd_error_handler)
9972130561Sobrien	      (sym_type == STT_TLS
9973218822Sdim	       ? _("%B(%A+0x%lx): %s used with TLS symbol %s")
9974218822Sdim	       : _("%B(%A+0x%lx): %s used with non-TLS symbol %s"),
9975218822Sdim	       input_bfd,
9976218822Sdim	       input_section,
9977130561Sobrien	       (long) rel->r_offset,
9978130561Sobrien	       ppc64_elf_howto_table[r_type]->name,
9979130561Sobrien	       sym_name);
9980130561Sobrien	}
9981130561Sobrien
9982130561Sobrien      /* Ensure reloc mapping code below stays sane.  */
9983130561Sobrien      if (R_PPC64_TOC16_LO_DS != R_PPC64_TOC16_DS + 1
9984130561Sobrien	  || R_PPC64_TOC16_LO != R_PPC64_TOC16 + 1
9985130561Sobrien	  || (R_PPC64_GOT_TLSLD16 & 3)    != (R_PPC64_GOT_TLSGD16 & 3)
9986130561Sobrien	  || (R_PPC64_GOT_TLSLD16_LO & 3) != (R_PPC64_GOT_TLSGD16_LO & 3)
9987130561Sobrien	  || (R_PPC64_GOT_TLSLD16_HI & 3) != (R_PPC64_GOT_TLSGD16_HI & 3)
9988130561Sobrien	  || (R_PPC64_GOT_TLSLD16_HA & 3) != (R_PPC64_GOT_TLSGD16_HA & 3)
9989130561Sobrien	  || (R_PPC64_GOT_TLSLD16 & 3)    != (R_PPC64_GOT_TPREL16_DS & 3)
9990130561Sobrien	  || (R_PPC64_GOT_TLSLD16_LO & 3) != (R_PPC64_GOT_TPREL16_LO_DS & 3)
9991130561Sobrien	  || (R_PPC64_GOT_TLSLD16_HI & 3) != (R_PPC64_GOT_TPREL16_HI & 3)
9992130561Sobrien	  || (R_PPC64_GOT_TLSLD16_HA & 3) != (R_PPC64_GOT_TPREL16_HA & 3))
9993130561Sobrien	abort ();
9994130561Sobrien
9995130561Sobrien      switch (r_type)
9996130561Sobrien	{
9997130561Sobrien	default:
9998130561Sobrien	  break;
9999130561Sobrien
10000130561Sobrien	case R_PPC64_TOC16:
10001130561Sobrien	case R_PPC64_TOC16_LO:
10002130561Sobrien	case R_PPC64_TOC16_DS:
10003130561Sobrien	case R_PPC64_TOC16_LO_DS:
10004130561Sobrien	  {
10005130561Sobrien	    /* Check for toc tls entries.  */
10006130561Sobrien	    char *toc_tls;
10007130561Sobrien	    int retval;
10008130561Sobrien
10009130561Sobrien	    retval = get_tls_mask (&toc_tls, &toc_symndx, &local_syms,
10010130561Sobrien				   rel, input_bfd);
10011130561Sobrien	    if (retval == 0)
10012130561Sobrien	      return FALSE;
10013130561Sobrien
10014130561Sobrien	    if (toc_tls)
10015130561Sobrien	      {
10016130561Sobrien		tls_mask = *toc_tls;
10017130561Sobrien		if (r_type == R_PPC64_TOC16_DS
10018130561Sobrien		    || r_type == R_PPC64_TOC16_LO_DS)
10019130561Sobrien		  {
10020130561Sobrien		    if (tls_mask != 0
10021130561Sobrien			&& (tls_mask & (TLS_DTPREL | TLS_TPREL)) == 0)
10022130561Sobrien		      goto toctprel;
10023130561Sobrien		  }
10024130561Sobrien		else
10025130561Sobrien		  {
10026130561Sobrien		    /* If we found a GD reloc pair, then we might be
10027130561Sobrien		       doing a GD->IE transition.  */
10028130561Sobrien		    if (retval == 2)
10029130561Sobrien		      {
10030130561Sobrien			tls_gd = TLS_TPRELGD;
10031130561Sobrien			if (tls_mask != 0 && (tls_mask & TLS_GD) == 0)
10032130561Sobrien			  goto tls_get_addr_check;
10033130561Sobrien		      }
10034130561Sobrien		    else if (retval == 3)
10035130561Sobrien		      {
10036130561Sobrien			if (tls_mask != 0 && (tls_mask & TLS_LD) == 0)
10037130561Sobrien			  goto tls_get_addr_check;
10038130561Sobrien		      }
10039130561Sobrien		  }
10040130561Sobrien	      }
10041130561Sobrien	  }
10042130561Sobrien	  break;
10043130561Sobrien
10044130561Sobrien	case R_PPC64_GOT_TPREL16_DS:
10045130561Sobrien	case R_PPC64_GOT_TPREL16_LO_DS:
10046130561Sobrien	  if (tls_mask != 0
10047130561Sobrien	      && (tls_mask & TLS_TPREL) == 0)
1004889857Sobrien	    {
10049130561Sobrien	    toctprel:
10050218822Sdim	      insn = bfd_get_32 (output_bfd, contents + rel->r_offset - d_offset);
10051130561Sobrien	      insn &= 31 << 21;
10052130561Sobrien	      insn |= 0x3c0d0000;	/* addis 0,13,0 */
10053218822Sdim	      bfd_put_32 (output_bfd, insn, contents + rel->r_offset - d_offset);
10054130561Sobrien	      r_type = R_PPC64_TPREL16_HA;
10055130561Sobrien	      if (toc_symndx != 0)
10056130561Sobrien		{
10057130561Sobrien		  rel->r_info = ELF64_R_INFO (toc_symndx, r_type);
10058130561Sobrien		  /* We changed the symbol.  Start over in order to
10059130561Sobrien		     get h, sym, sec etc. right.  */
10060130561Sobrien		  rel--;
10061130561Sobrien		  continue;
10062130561Sobrien		}
1006389857Sobrien	      else
10064130561Sobrien		rel->r_info = ELF64_R_INFO (r_symndx, r_type);
1006589857Sobrien	    }
10066130561Sobrien	  break;
10067130561Sobrien
10068130561Sobrien	case R_PPC64_TLS:
10069130561Sobrien	  if (tls_mask != 0
10070130561Sobrien	      && (tls_mask & TLS_TPREL) == 0)
10071130561Sobrien	    {
10072130561Sobrien	      bfd_vma rtra;
10073130561Sobrien	      insn = bfd_get_32 (output_bfd, contents + rel->r_offset);
10074130561Sobrien	      if ((insn & ((0x3f << 26) | (31 << 11)))
10075130561Sobrien		  == ((31 << 26) | (13 << 11)))
10076130561Sobrien		rtra = insn & ((1 << 26) - (1 << 16));
10077130561Sobrien	      else if ((insn & ((0x3f << 26) | (31 << 16)))
10078130561Sobrien		       == ((31 << 26) | (13 << 16)))
10079130561Sobrien		rtra = (insn & (31 << 21)) | ((insn & (31 << 11)) << 5);
10080130561Sobrien	      else
10081130561Sobrien		abort ();
10082130561Sobrien	      if ((insn & ((1 << 11) - (1 << 1))) == 266 << 1)
10083130561Sobrien		/* add -> addi.  */
10084130561Sobrien		insn = 14 << 26;
10085130561Sobrien	      else if ((insn & (31 << 1)) == 23 << 1
10086130561Sobrien		       && ((insn & (31 << 6)) < 14 << 6
10087130561Sobrien			   || ((insn & (31 << 6)) >= 16 << 6
10088130561Sobrien			       && (insn & (31 << 6)) < 24 << 6)))
10089130561Sobrien		/* load and store indexed -> dform.  */
10090130561Sobrien		insn = (32 | ((insn >> 6) & 31)) << 26;
10091130561Sobrien	      else if ((insn & (31 << 1)) == 21 << 1
10092130561Sobrien		       && (insn & (0x1a << 6)) == 0)
10093130561Sobrien		/* ldx, ldux, stdx, stdux -> ld, ldu, std, stdu.  */
10094130561Sobrien		insn = (((58 | ((insn >> 6) & 4)) << 26)
10095130561Sobrien			| ((insn >> 6) & 1));
10096130561Sobrien	      else if ((insn & (31 << 1)) == 21 << 1
10097130561Sobrien		       && (insn & ((1 << 11) - (1 << 1))) == 341 << 1)
10098130561Sobrien		/* lwax -> lwa.  */
10099130561Sobrien		insn = (58 << 26) | 2;
10100130561Sobrien	      else
10101130561Sobrien		abort ();
10102130561Sobrien	      insn |= rtra;
10103130561Sobrien	      bfd_put_32 (output_bfd, insn, contents + rel->r_offset);
10104130561Sobrien	      /* Was PPC64_TLS which sits on insn boundary, now
10105218822Sdim		 PPC64_TPREL16_LO which is at low-order half-word.  */
10106218822Sdim	      rel->r_offset += d_offset;
10107130561Sobrien	      r_type = R_PPC64_TPREL16_LO;
10108130561Sobrien	      if (toc_symndx != 0)
10109130561Sobrien		{
10110130561Sobrien		  rel->r_info = ELF64_R_INFO (toc_symndx, r_type);
10111130561Sobrien		  /* We changed the symbol.  Start over in order to
10112130561Sobrien		     get h, sym, sec etc. right.  */
10113130561Sobrien		  rel--;
10114130561Sobrien		  continue;
10115130561Sobrien		}
10116130561Sobrien	      else
10117130561Sobrien		rel->r_info = ELF64_R_INFO (r_symndx, r_type);
10118130561Sobrien	    }
10119130561Sobrien	  break;
10120130561Sobrien
10121130561Sobrien	case R_PPC64_GOT_TLSGD16_HI:
10122130561Sobrien	case R_PPC64_GOT_TLSGD16_HA:
10123130561Sobrien	  tls_gd = TLS_TPRELGD;
10124130561Sobrien	  if (tls_mask != 0 && (tls_mask & TLS_GD) == 0)
10125130561Sobrien	    goto tls_gdld_hi;
10126130561Sobrien	  break;
10127130561Sobrien
10128130561Sobrien	case R_PPC64_GOT_TLSLD16_HI:
10129130561Sobrien	case R_PPC64_GOT_TLSLD16_HA:
10130130561Sobrien	  if (tls_mask != 0 && (tls_mask & TLS_LD) == 0)
10131130561Sobrien	    {
10132130561Sobrien	    tls_gdld_hi:
10133130561Sobrien	      if ((tls_mask & tls_gd) != 0)
10134130561Sobrien		r_type = (((r_type - (R_PPC64_GOT_TLSGD16 & 3)) & 3)
10135130561Sobrien			  + R_PPC64_GOT_TPREL16_DS);
10136130561Sobrien	      else
10137130561Sobrien		{
10138130561Sobrien		  bfd_put_32 (output_bfd, NOP, contents + rel->r_offset);
10139218822Sdim		  rel->r_offset -= d_offset;
10140130561Sobrien		  r_type = R_PPC64_NONE;
10141130561Sobrien		}
10142130561Sobrien	      rel->r_info = ELF64_R_INFO (r_symndx, r_type);
10143130561Sobrien	    }
10144130561Sobrien	  break;
10145130561Sobrien
10146130561Sobrien	case R_PPC64_GOT_TLSGD16:
10147130561Sobrien	case R_PPC64_GOT_TLSGD16_LO:
10148130561Sobrien	  tls_gd = TLS_TPRELGD;
10149130561Sobrien	  if (tls_mask != 0 && (tls_mask & TLS_GD) == 0)
10150130561Sobrien	    goto tls_get_addr_check;
10151130561Sobrien	  break;
10152130561Sobrien
10153130561Sobrien	case R_PPC64_GOT_TLSLD16:
10154130561Sobrien	case R_PPC64_GOT_TLSLD16_LO:
10155130561Sobrien	  if (tls_mask != 0 && (tls_mask & TLS_LD) == 0)
10156130561Sobrien	    {
10157130561Sobrien	    tls_get_addr_check:
10158130561Sobrien	      if (rel + 1 < relend)
10159130561Sobrien		{
10160130561Sobrien		  enum elf_ppc64_reloc_type r_type2;
10161130561Sobrien		  unsigned long r_symndx2;
10162130561Sobrien		  struct elf_link_hash_entry *h2;
10163130561Sobrien		  bfd_vma insn1, insn2, insn3;
10164130561Sobrien		  bfd_vma offset;
10165130561Sobrien
10166130561Sobrien		  /* The next instruction should be a call to
10167130561Sobrien		     __tls_get_addr.  Peek at the reloc to be sure.  */
10168130561Sobrien		  r_type2 = ELF64_R_TYPE (rel[1].r_info);
10169130561Sobrien		  r_symndx2 = ELF64_R_SYM (rel[1].r_info);
10170130561Sobrien		  if (r_symndx2 < symtab_hdr->sh_info
10171130561Sobrien		      || (r_type2 != R_PPC64_REL14
10172130561Sobrien			  && r_type2 != R_PPC64_REL14_BRTAKEN
10173130561Sobrien			  && r_type2 != R_PPC64_REL14_BRNTAKEN
10174130561Sobrien			  && r_type2 != R_PPC64_REL24))
10175130561Sobrien		    break;
10176130561Sobrien
10177130561Sobrien		  h2 = sym_hashes[r_symndx2 - symtab_hdr->sh_info];
10178130561Sobrien		  while (h2->root.type == bfd_link_hash_indirect
10179130561Sobrien			 || h2->root.type == bfd_link_hash_warning)
10180130561Sobrien		    h2 = (struct elf_link_hash_entry *) h2->root.u.i.link;
10181218822Sdim		  if (h2 == NULL || (h2 != &htab->tls_get_addr->elf
10182218822Sdim				     && h2 != &htab->tls_get_addr_fd->elf))
10183130561Sobrien		    break;
10184130561Sobrien
10185130561Sobrien		  /* OK, it checks out.  Replace the call.  */
10186130561Sobrien		  offset = rel[1].r_offset;
10187130561Sobrien		  insn1 = bfd_get_32 (output_bfd,
10188218822Sdim				      contents + rel->r_offset - d_offset);
10189130561Sobrien		  insn3 = bfd_get_32 (output_bfd,
10190130561Sobrien				      contents + offset + 4);
10191130561Sobrien		  if ((tls_mask & tls_gd) != 0)
10192130561Sobrien		    {
10193130561Sobrien		      /* IE */
10194130561Sobrien		      insn1 &= (1 << 26) - (1 << 2);
10195130561Sobrien		      insn1 |= 58 << 26;	/* ld */
10196130561Sobrien		      insn2 = 0x7c636a14;	/* add 3,3,13 */
10197130561Sobrien		      rel[1].r_info = ELF64_R_INFO (r_symndx2, R_PPC64_NONE);
10198130561Sobrien		      if ((tls_mask & TLS_EXPLICIT) == 0)
10199130561Sobrien			r_type = (((r_type - (R_PPC64_GOT_TLSGD16 & 3)) & 3)
10200130561Sobrien				  + R_PPC64_GOT_TPREL16_DS);
10201130561Sobrien		      else
10202130561Sobrien			r_type += R_PPC64_TOC16_DS - R_PPC64_TOC16;
10203130561Sobrien		      rel->r_info = ELF64_R_INFO (r_symndx, r_type);
10204130561Sobrien		    }
10205130561Sobrien		  else
10206130561Sobrien		    {
10207130561Sobrien		      /* LE */
10208130561Sobrien		      insn1 = 0x3c6d0000;	/* addis 3,13,0 */
10209130561Sobrien		      insn2 = 0x38630000;	/* addi 3,3,0 */
10210130561Sobrien		      if (tls_gd == 0)
10211130561Sobrien			{
10212130561Sobrien			  /* Was an LD reloc.  */
10213130561Sobrien			  r_symndx = 0;
10214130561Sobrien			  rel->r_addend = htab->elf.tls_sec->vma + DTP_OFFSET;
10215130561Sobrien			  rel[1].r_addend = htab->elf.tls_sec->vma + DTP_OFFSET;
10216130561Sobrien			}
10217130561Sobrien		      else if (toc_symndx != 0)
10218130561Sobrien			r_symndx = toc_symndx;
10219130561Sobrien		      r_type = R_PPC64_TPREL16_HA;
10220130561Sobrien		      rel->r_info = ELF64_R_INFO (r_symndx, r_type);
10221130561Sobrien		      rel[1].r_info = ELF64_R_INFO (r_symndx,
10222130561Sobrien						    R_PPC64_TPREL16_LO);
10223218822Sdim		      rel[1].r_offset += d_offset;
10224130561Sobrien		    }
10225130561Sobrien		  if (insn3 == NOP
10226130561Sobrien		      || insn3 == CROR_151515 || insn3 == CROR_313131)
10227130561Sobrien		    {
10228130561Sobrien		      insn3 = insn2;
10229130561Sobrien		      insn2 = NOP;
10230130561Sobrien		      rel[1].r_offset += 4;
10231130561Sobrien		    }
10232218822Sdim		  bfd_put_32 (output_bfd, insn1, contents + rel->r_offset - d_offset);
10233130561Sobrien		  bfd_put_32 (output_bfd, insn2, contents + offset);
10234130561Sobrien		  bfd_put_32 (output_bfd, insn3, contents + offset + 4);
10235130561Sobrien		  if (tls_gd == 0 || toc_symndx != 0)
10236130561Sobrien		    {
10237130561Sobrien		      /* We changed the symbol.  Start over in order
10238130561Sobrien			 to get h, sym, sec etc. right.  */
10239130561Sobrien		      rel--;
10240130561Sobrien		      continue;
10241130561Sobrien		    }
10242130561Sobrien		}
10243130561Sobrien	    }
10244130561Sobrien	  break;
10245130561Sobrien
10246130561Sobrien	case R_PPC64_DTPMOD64:
10247130561Sobrien	  if (rel + 1 < relend
10248130561Sobrien	      && rel[1].r_info == ELF64_R_INFO (r_symndx, R_PPC64_DTPREL64)
10249130561Sobrien	      && rel[1].r_offset == rel->r_offset + 8)
10250130561Sobrien	    {
10251130561Sobrien	      if ((tls_mask & TLS_GD) == 0)
10252130561Sobrien		{
10253130561Sobrien		  rel[1].r_info = ELF64_R_INFO (r_symndx, R_PPC64_NONE);
10254130561Sobrien		  if ((tls_mask & TLS_TPRELGD) != 0)
10255130561Sobrien		    r_type = R_PPC64_TPREL64;
10256130561Sobrien		  else
10257130561Sobrien		    {
10258130561Sobrien		      bfd_put_64 (output_bfd, 1, contents + rel->r_offset);
10259130561Sobrien		      r_type = R_PPC64_NONE;
10260130561Sobrien		    }
10261130561Sobrien		  rel->r_info = ELF64_R_INFO (r_symndx, r_type);
10262130561Sobrien		}
10263130561Sobrien	    }
1026489857Sobrien	  else
1026589857Sobrien	    {
10266130561Sobrien	      if ((tls_mask & TLS_LD) == 0)
10267130561Sobrien		{
10268130561Sobrien		  bfd_put_64 (output_bfd, 1, contents + rel->r_offset);
10269130561Sobrien		  r_type = R_PPC64_NONE;
10270130561Sobrien		  rel->r_info = ELF64_R_INFO (r_symndx, r_type);
10271130561Sobrien		}
1027289857Sobrien	    }
10273130561Sobrien	  break;
10274130561Sobrien
10275130561Sobrien	case R_PPC64_TPREL64:
10276130561Sobrien	  if ((tls_mask & TLS_TPREL) == 0)
10277130561Sobrien	    {
10278130561Sobrien	      r_type = R_PPC64_NONE;
10279130561Sobrien	      rel->r_info = ELF64_R_INFO (r_symndx, r_type);
10280130561Sobrien	    }
10281130561Sobrien	  break;
1028289857Sobrien	}
1028389857Sobrien
10284130561Sobrien      /* Handle other relocations that tweak non-addend part of insn.  */
1028589857Sobrien      insn = 0;
10286218822Sdim      max_br_offset = 1 << 25;
10287218822Sdim      addend = rel->r_addend;
1028889857Sobrien      switch (r_type)
1028989857Sobrien	{
1029089857Sobrien	default:
1029189857Sobrien	  break;
1029289857Sobrien
1029389857Sobrien	  /* Branch taken prediction relocations.  */
1029489857Sobrien	case R_PPC64_ADDR14_BRTAKEN:
1029589857Sobrien	case R_PPC64_REL14_BRTAKEN:
10296104834Sobrien	  insn = 0x01 << 21; /* 'y' or 't' bit, lowest bit of BO field.  */
10297104834Sobrien	  /* Fall thru.  */
1029889857Sobrien
1029989857Sobrien	  /* Branch not taken prediction relocations.  */
1030089857Sobrien	case R_PPC64_ADDR14_BRNTAKEN:
1030189857Sobrien	case R_PPC64_REL14_BRNTAKEN:
10302130561Sobrien	  insn |= bfd_get_32 (output_bfd,
10303130561Sobrien			      contents + rel->r_offset) & ~(0x01 << 21);
10304218822Sdim	  /* Fall thru.  */
1030599461Sobrien
10306218822Sdim	case R_PPC64_REL14:
10307218822Sdim	  max_br_offset = 1 << 15;
10308218822Sdim	  /* Fall thru.  */
1030989857Sobrien
1031089857Sobrien	case R_PPC64_REL24:
10311130561Sobrien	  /* Calls to functions with a different TOC, such as calls to
10312130561Sobrien	     shared objects, need to alter the TOC pointer.  This is
10313130561Sobrien	     done using a linkage stub.  A REL24 branching to these
10314130561Sobrien	     linkage stubs needs to be followed by a nop, as the nop
10315130561Sobrien	     will be replaced with an instruction to restore the TOC
10316130561Sobrien	     base pointer.  */
10317218822Sdim	  stub_entry = NULL;
10318218822Sdim	  fdh = h;
10319130561Sobrien	  if (((h != NULL
10320218822Sdim		&& (((fdh = h->oh) != NULL
10321218822Sdim		     && fdh->elf.plt.plist != NULL)
10322218822Sdim		    || (fdh = h)->elf.plt.plist != NULL))
10323218822Sdim	       || (sec != NULL
10324130561Sobrien		   && sec->output_section != NULL
10325218822Sdim		   && sec->id <= htab->top_id
10326130561Sobrien		   && (htab->stub_group[sec->id].toc_off
10327130561Sobrien		       != htab->stub_group[input_section->id].toc_off)))
10328104834Sobrien	      && (stub_entry = ppc_get_stub_entry (input_section, sec, fdh,
10329130561Sobrien						   rel, htab)) != NULL
10330130561Sobrien	      && (stub_entry->stub_type == ppc_stub_plt_call
10331130561Sobrien		  || stub_entry->stub_type == ppc_stub_plt_branch_r2off
10332130561Sobrien		  || stub_entry->stub_type == ppc_stub_long_branch_r2off))
1033389857Sobrien	    {
10334218822Sdim	      bfd_boolean can_plt_call = FALSE;
1033589857Sobrien
10336218822Sdim	      if (rel->r_offset + 8 <= input_section->size)
1033789857Sobrien		{
10338218822Sdim		  unsigned long nop;
10339218822Sdim		  nop = bfd_get_32 (input_bfd, contents + rel->r_offset + 4);
10340218822Sdim		  if (nop == NOP
10341218822Sdim		      || nop == CROR_151515 || nop == CROR_313131)
1034289857Sobrien		    {
10343130561Sobrien		      bfd_put_32 (input_bfd, LD_R2_40R1,
10344130561Sobrien				  contents + rel->r_offset + 4);
10345218822Sdim		      can_plt_call = TRUE;
1034689857Sobrien		    }
1034789857Sobrien		}
1034899461Sobrien
1034999461Sobrien	      if (!can_plt_call)
1035099461Sobrien		{
10351130561Sobrien		  if (stub_entry->stub_type == ppc_stub_plt_call)
10352130561Sobrien		    {
10353130561Sobrien		      /* If this is a plain branch rather than a branch
10354218822Sdim			 and link, don't require a nop.  However, don't
10355218822Sdim			 allow tail calls in a shared library as they
10356218822Sdim			 will result in r2 being corrupted.  */
10357218822Sdim		      unsigned long br;
10358218822Sdim		      br = bfd_get_32 (input_bfd, contents + rel->r_offset);
10359218822Sdim		      if (info->executable && (br & 1) == 0)
10360218822Sdim			can_plt_call = TRUE;
10361218822Sdim		      else
10362218822Sdim			stub_entry = NULL;
10363130561Sobrien		    }
10364130561Sobrien		  else if (h != NULL
10365218822Sdim			   && strcmp (h->elf.root.root.string,
10366130561Sobrien				      ".__libc_start_main") == 0)
10367130561Sobrien		    {
10368130561Sobrien		      /* Allow crt1 branch to go via a toc adjusting stub.  */
10369218822Sdim		      can_plt_call = TRUE;
10370130561Sobrien		    }
10371130561Sobrien		  else
10372130561Sobrien		    {
10373130561Sobrien		      if (strcmp (input_section->output_section->name,
10374130561Sobrien				  ".init") == 0
10375130561Sobrien			  || strcmp (input_section->output_section->name,
10376130561Sobrien				     ".fini") == 0)
10377130561Sobrien			(*_bfd_error_handler)
10378218822Sdim			  (_("%B(%A+0x%lx): automatic multiple TOCs "
10379130561Sobrien			     "not supported using your crt files; "
10380130561Sobrien			     "recompile with -mminimal-toc or upgrade gcc"),
10381218822Sdim			   input_bfd,
10382218822Sdim			   input_section,
10383130561Sobrien			   (long) rel->r_offset);
10384130561Sobrien		      else
10385130561Sobrien			(*_bfd_error_handler)
10386218822Sdim			  (_("%B(%A+0x%lx): sibling call optimization to `%s' "
10387130561Sobrien			     "does not allow automatic multiple TOCs; "
10388130561Sobrien			     "recompile with -mminimal-toc or "
10389130561Sobrien			     "-fno-optimize-sibling-calls, "
10390130561Sobrien			     "or make `%s' extern"),
10391218822Sdim			   input_bfd,
10392218822Sdim			   input_section,
10393130561Sobrien			   (long) rel->r_offset,
10394130561Sobrien			   sym_name,
10395130561Sobrien			   sym_name);
10396130561Sobrien		      bfd_set_error (bfd_error_bad_value);
10397130561Sobrien		      ret = FALSE;
10398130561Sobrien		    }
1039999461Sobrien		}
1040099461Sobrien
10401218822Sdim	      if (can_plt_call
10402218822Sdim		  && stub_entry->stub_type == ppc_stub_plt_call)
10403218822Sdim		unresolved_reloc = FALSE;
10404218822Sdim	    }
10405218822Sdim
10406218822Sdim	  if (stub_entry == NULL
10407218822Sdim	      && get_opd_info (sec) != NULL)
10408218822Sdim	    {
10409218822Sdim	      /* The branch destination is the value of the opd entry. */
10410218822Sdim	      bfd_vma off = (relocation + addend
10411218822Sdim			     - sec->output_section->vma
10412218822Sdim			     - sec->output_offset);
10413218822Sdim	      bfd_vma dest = opd_entry_value (sec, off, NULL, NULL);
10414218822Sdim	      if (dest != (bfd_vma) -1)
1041599461Sobrien		{
10416218822Sdim		  relocation = dest;
10417218822Sdim		  addend = 0;
1041899461Sobrien		}
1041989857Sobrien	    }
1042089857Sobrien
10421218822Sdim	  /* If the branch is out of reach we ought to have a long
10422218822Sdim	     branch stub.  */
10423218822Sdim	  from = (rel->r_offset
10424218822Sdim		  + input_section->output_offset
10425218822Sdim		  + input_section->output_section->vma);
10426218822Sdim
10427218822Sdim	  if (stub_entry == NULL
10428218822Sdim	      && (relocation + addend - from + max_br_offset
10429218822Sdim		  >= 2 * max_br_offset)
10430218822Sdim	      && r_type != R_PPC64_ADDR14_BRTAKEN
10431218822Sdim	      && r_type != R_PPC64_ADDR14_BRNTAKEN)
10432218822Sdim	    stub_entry = ppc_get_stub_entry (input_section, sec, h, rel,
10433218822Sdim					     htab);
10434218822Sdim
10435218822Sdim	  if (stub_entry != NULL)
1043689857Sobrien	    {
10437218822Sdim	      /* Munge up the value and addend so that we call the stub
10438218822Sdim		 rather than the procedure directly.  */
10439218822Sdim	      relocation = (stub_entry->stub_offset
10440218822Sdim			    + stub_entry->stub_sec->output_offset
10441218822Sdim			    + stub_entry->stub_sec->output_section->vma);
10442218822Sdim	      addend = 0;
10443218822Sdim	    }
1044499461Sobrien
10445218822Sdim	  if (insn != 0)
10446218822Sdim	    {
10447218822Sdim	      if (is_power4)
10448218822Sdim		{
10449218822Sdim		  /* Set 'a' bit.  This is 0b00010 in BO field for branch
10450218822Sdim		     on CR(BI) insns (BO == 001at or 011at), and 0b01000
10451218822Sdim		     for branch on CTR insns (BO == 1a00t or 1a01t).  */
10452218822Sdim		  if ((insn & (0x14 << 21)) == (0x04 << 21))
10453218822Sdim		    insn |= 0x02 << 21;
10454218822Sdim		  else if ((insn & (0x14 << 21)) == (0x10 << 21))
10455218822Sdim		    insn |= 0x08 << 21;
10456218822Sdim		  else
10457218822Sdim		    break;
10458218822Sdim		}
10459218822Sdim	      else
10460218822Sdim		{
10461218822Sdim		  /* Invert 'y' bit if not the default.  */
10462218822Sdim		  if ((bfd_signed_vma) (relocation + addend - from) < 0)
10463218822Sdim		    insn ^= 0x01 << 21;
10464218822Sdim		}
10465218822Sdim
10466218822Sdim	      bfd_put_32 (output_bfd, insn, contents + rel->r_offset);
1046789857Sobrien	    }
10468218822Sdim
10469218822Sdim	  /* NOP out calls to undefined weak functions.
10470218822Sdim	     We can thus call a weak function without first
10471218822Sdim	     checking whether the function is defined.  */
10472218822Sdim	  else if (h != NULL
10473218822Sdim		   && h->elf.root.type == bfd_link_hash_undefweak
10474218822Sdim		   && r_type == R_PPC64_REL24
10475218822Sdim		   && relocation == 0
10476218822Sdim		   && addend == 0)
10477218822Sdim	    {
10478218822Sdim	      bfd_put_32 (output_bfd, NOP, contents + rel->r_offset);
10479218822Sdim	      continue;
10480218822Sdim	    }
1048189857Sobrien	  break;
1048289857Sobrien	}
1048389857Sobrien
1048489857Sobrien      /* Set `addend'.  */
10485130561Sobrien      tls_type = 0;
1048689857Sobrien      switch (r_type)
1048789857Sobrien	{
1048889857Sobrien	default:
1048989857Sobrien	  (*_bfd_error_handler)
10490218822Sdim	    (_("%B: unknown relocation type %d for symbol %s"),
10491218822Sdim	     input_bfd, (int) r_type, sym_name);
1049289857Sobrien
1049389857Sobrien	  bfd_set_error (bfd_error_bad_value);
10494130561Sobrien	  ret = FALSE;
1049589857Sobrien	  continue;
1049689857Sobrien
1049789857Sobrien	case R_PPC64_NONE:
10498130561Sobrien	case R_PPC64_TLS:
10499130561Sobrien	case R_PPC64_GNU_VTINHERIT:
10500130561Sobrien	case R_PPC64_GNU_VTENTRY:
1050189857Sobrien	  continue;
1050289857Sobrien
1050389857Sobrien	  /* GOT16 relocations.  Like an ADDR16 using the symbol's
1050489857Sobrien	     address in the GOT as relocation value instead of the
10505130561Sobrien	     symbol's value itself.  Also, create a GOT entry for the
1050689857Sobrien	     symbol and put the symbol value there.  */
10507130561Sobrien	case R_PPC64_GOT_TLSGD16:
10508130561Sobrien	case R_PPC64_GOT_TLSGD16_LO:
10509130561Sobrien	case R_PPC64_GOT_TLSGD16_HI:
10510130561Sobrien	case R_PPC64_GOT_TLSGD16_HA:
10511130561Sobrien	  tls_type = TLS_TLS | TLS_GD;
10512130561Sobrien	  goto dogot;
10513130561Sobrien
10514130561Sobrien	case R_PPC64_GOT_TLSLD16:
10515130561Sobrien	case R_PPC64_GOT_TLSLD16_LO:
10516130561Sobrien	case R_PPC64_GOT_TLSLD16_HI:
10517130561Sobrien	case R_PPC64_GOT_TLSLD16_HA:
10518130561Sobrien	  tls_type = TLS_TLS | TLS_LD;
10519130561Sobrien	  goto dogot;
10520130561Sobrien
10521130561Sobrien	case R_PPC64_GOT_TPREL16_DS:
10522130561Sobrien	case R_PPC64_GOT_TPREL16_LO_DS:
10523130561Sobrien	case R_PPC64_GOT_TPREL16_HI:
10524130561Sobrien	case R_PPC64_GOT_TPREL16_HA:
10525130561Sobrien	  tls_type = TLS_TLS | TLS_TPREL;
10526130561Sobrien	  goto dogot;
10527130561Sobrien
10528130561Sobrien	case R_PPC64_GOT_DTPREL16_DS:
10529130561Sobrien	case R_PPC64_GOT_DTPREL16_LO_DS:
10530130561Sobrien	case R_PPC64_GOT_DTPREL16_HI:
10531130561Sobrien	case R_PPC64_GOT_DTPREL16_HA:
10532130561Sobrien	  tls_type = TLS_TLS | TLS_DTPREL;
10533130561Sobrien	  goto dogot;
10534130561Sobrien
1053589857Sobrien	case R_PPC64_GOT16:
1053689857Sobrien	case R_PPC64_GOT16_LO:
1053789857Sobrien	case R_PPC64_GOT16_HI:
1053889857Sobrien	case R_PPC64_GOT16_HA:
1053989857Sobrien	case R_PPC64_GOT16_DS:
1054089857Sobrien	case R_PPC64_GOT16_LO_DS:
10541130561Sobrien	dogot:
1054289857Sobrien	  {
1054389857Sobrien	    /* Relocation is to the entry for this symbol in the global
1054489857Sobrien	       offset table.  */
10545130561Sobrien	    asection *got;
10546130561Sobrien	    bfd_vma *offp;
1054789857Sobrien	    bfd_vma off;
10548130561Sobrien	    unsigned long indx = 0;
1054989857Sobrien
10550130561Sobrien	    if (tls_type == (TLS_TLS | TLS_LD)
10551130561Sobrien		&& (h == NULL
10552218822Sdim		    || !h->elf.def_dynamic))
10553130561Sobrien	      offp = &ppc64_tlsld_got (input_bfd)->offset;
10554130561Sobrien	    else
1055589857Sobrien	      {
10556130561Sobrien		struct got_entry *ent;
1055789857Sobrien
10558130561Sobrien		if (h != NULL)
1055989857Sobrien		  {
10560130561Sobrien		    bfd_boolean dyn = htab->elf.dynamic_sections_created;
10561218822Sdim		    if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared,
10562218822Sdim							  &h->elf)
10563130561Sobrien			|| (info->shared
10564218822Sdim			    && SYMBOL_REFERENCES_LOCAL (info, &h->elf)))
10565130561Sobrien		      /* This is actually a static link, or it is a
10566130561Sobrien			 -Bsymbolic link and the symbol is defined
10567130561Sobrien			 locally, or the symbol was forced to be local
10568130561Sobrien			 because of a version file.  */
10569130561Sobrien		      ;
1057089857Sobrien		    else
1057189857Sobrien		      {
10572218822Sdim			indx = h->elf.dynindx;
10573130561Sobrien			unresolved_reloc = FALSE;
1057489857Sobrien		      }
10575218822Sdim		    ent = h->elf.got.glist;
1057689857Sobrien		  }
1057789857Sobrien		else
10578130561Sobrien		  {
10579130561Sobrien		    if (local_got_ents == NULL)
10580130561Sobrien		      abort ();
10581130561Sobrien		    ent = local_got_ents[r_symndx];
10582130561Sobrien		  }
10583130561Sobrien
10584130561Sobrien		for (; ent != NULL; ent = ent->next)
10585218822Sdim		  if (ent->addend == orig_addend
10586130561Sobrien		      && ent->owner == input_bfd
10587130561Sobrien		      && ent->tls_type == tls_type)
10588130561Sobrien		    break;
10589130561Sobrien		if (ent == NULL)
10590130561Sobrien		  abort ();
10591130561Sobrien		offp = &ent->got.offset;
1059289857Sobrien	      }
10593130561Sobrien
10594130561Sobrien	    got = ppc64_elf_tdata (input_bfd)->got;
10595130561Sobrien	    if (got == NULL)
10596130561Sobrien	      abort ();
10597130561Sobrien
10598130561Sobrien	    /* The offset must always be a multiple of 8.  We use the
10599130561Sobrien	       least significant bit to record whether we have already
10600130561Sobrien	       processed this entry.  */
10601130561Sobrien	    off = *offp;
10602130561Sobrien	    if ((off & 1) != 0)
10603130561Sobrien	      off &= ~1;
1060489857Sobrien	    else
1060589857Sobrien	      {
10606130561Sobrien		/* Generate relocs for the dynamic linker, except in
10607130561Sobrien		   the case of TLSLD where we'll use one entry per
10608130561Sobrien		   module.  */
10609130561Sobrien		asection *relgot = ppc64_elf_tdata (input_bfd)->relgot;
1061089857Sobrien
10611130561Sobrien		*offp = off | 1;
10612130561Sobrien		if ((info->shared || indx != 0)
10613130561Sobrien		    && (h == NULL
10614218822Sdim			|| ELF_ST_VISIBILITY (h->elf.other) == STV_DEFAULT
10615218822Sdim			|| h->elf.root.type != bfd_link_hash_undefweak))
10616130561Sobrien		  {
10617130561Sobrien		    outrel.r_offset = (got->output_section->vma
10618130561Sobrien				       + got->output_offset
10619130561Sobrien				       + off);
10620218822Sdim		    outrel.r_addend = addend;
10621130561Sobrien		    if (tls_type & (TLS_LD | TLS_GD))
10622130561Sobrien		      {
10623130561Sobrien			outrel.r_addend = 0;
10624130561Sobrien			outrel.r_info = ELF64_R_INFO (indx, R_PPC64_DTPMOD64);
10625130561Sobrien			if (tls_type == (TLS_TLS | TLS_GD))
10626130561Sobrien			  {
10627130561Sobrien			    loc = relgot->contents;
10628130561Sobrien			    loc += (relgot->reloc_count++
10629130561Sobrien				    * sizeof (Elf64_External_Rela));
10630130561Sobrien			    bfd_elf64_swap_reloca_out (output_bfd,
10631130561Sobrien						       &outrel, loc);
10632130561Sobrien			    outrel.r_offset += 8;
10633218822Sdim			    outrel.r_addend = addend;
10634130561Sobrien			    outrel.r_info
10635130561Sobrien			      = ELF64_R_INFO (indx, R_PPC64_DTPREL64);
10636130561Sobrien			  }
10637130561Sobrien		      }
10638130561Sobrien		    else if (tls_type == (TLS_TLS | TLS_DTPREL))
10639130561Sobrien		      outrel.r_info = ELF64_R_INFO (indx, R_PPC64_DTPREL64);
10640130561Sobrien		    else if (tls_type == (TLS_TLS | TLS_TPREL))
10641130561Sobrien		      outrel.r_info = ELF64_R_INFO (indx, R_PPC64_TPREL64);
10642130561Sobrien		    else if (indx == 0)
10643130561Sobrien		      {
10644130561Sobrien			outrel.r_info = ELF64_R_INFO (indx, R_PPC64_RELATIVE);
1064589857Sobrien
10646130561Sobrien			/* Write the .got section contents for the sake
10647130561Sobrien			   of prelink.  */
10648130561Sobrien			loc = got->contents + off;
10649130561Sobrien			bfd_put_64 (output_bfd, outrel.r_addend + relocation,
10650130561Sobrien				    loc);
10651130561Sobrien		      }
10652130561Sobrien		    else
10653130561Sobrien		      outrel.r_info = ELF64_R_INFO (indx, R_PPC64_GLOB_DAT);
10654130561Sobrien
10655130561Sobrien		    if (indx == 0 && tls_type != (TLS_TLS | TLS_LD))
10656130561Sobrien		      {
10657130561Sobrien			outrel.r_addend += relocation;
10658130561Sobrien			if (tls_type & (TLS_GD | TLS_DTPREL | TLS_TPREL))
10659130561Sobrien			  outrel.r_addend -= htab->elf.tls_sec->vma;
10660130561Sobrien		      }
10661130561Sobrien		    loc = relgot->contents;
10662130561Sobrien		    loc += (relgot->reloc_count++
10663130561Sobrien			    * sizeof (Elf64_External_Rela));
10664130561Sobrien		    bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
10665130561Sobrien		  }
10666130561Sobrien
10667130561Sobrien		/* Init the .got section contents here if we're not
10668130561Sobrien		   emitting a reloc.  */
1066989857Sobrien		else
1067089857Sobrien		  {
10671218822Sdim		    relocation += addend;
10672130561Sobrien		    if (tls_type == (TLS_TLS | TLS_LD))
10673130561Sobrien		      relocation = 1;
10674130561Sobrien		    else if (tls_type != 0)
1067589857Sobrien		      {
10676130561Sobrien			relocation -= htab->elf.tls_sec->vma + DTP_OFFSET;
10677130561Sobrien			if (tls_type == (TLS_TLS | TLS_TPREL))
10678130561Sobrien			  relocation += DTP_OFFSET - TP_OFFSET;
1067989857Sobrien
10680130561Sobrien			if (tls_type == (TLS_TLS | TLS_GD))
10681130561Sobrien			  {
10682130561Sobrien			    bfd_put_64 (output_bfd, relocation,
10683130561Sobrien					got->contents + off + 8);
10684130561Sobrien			    relocation = 1;
10685130561Sobrien			  }
1068689857Sobrien		      }
1068789857Sobrien
10688130561Sobrien		    bfd_put_64 (output_bfd, relocation,
10689130561Sobrien				got->contents + off);
1069089857Sobrien		  }
1069189857Sobrien	      }
1069289857Sobrien
1069389857Sobrien	    if (off >= (bfd_vma) -2)
1069489857Sobrien	      abort ();
1069589857Sobrien
10696130561Sobrien	    relocation = got->output_offset + off;
1069789857Sobrien
1069889857Sobrien	    /* TOC base (r2) is TOC start plus 0x8000.  */
10699130561Sobrien	    addend = -TOC_BASE_OFF;
1070089857Sobrien	  }
1070189857Sobrien	  break;
1070289857Sobrien
1070389857Sobrien	case R_PPC64_PLT16_HA:
1070489857Sobrien	case R_PPC64_PLT16_HI:
1070589857Sobrien	case R_PPC64_PLT16_LO:
1070689857Sobrien	case R_PPC64_PLT32:
1070789857Sobrien	case R_PPC64_PLT64:
1070889857Sobrien	  /* Relocation is to the entry for this symbol in the
1070989857Sobrien	     procedure linkage table.  */
1071089857Sobrien
1071189857Sobrien	  /* Resolve a PLT reloc against a local symbol directly,
1071289857Sobrien	     without using the procedure linkage table.  */
1071389857Sobrien	  if (h == NULL)
1071489857Sobrien	    break;
1071589857Sobrien
10716130561Sobrien	  /* It's possible that we didn't make a PLT entry for this
10717130561Sobrien	     symbol.  This happens when statically linking PIC code,
10718130561Sobrien	     or when using -Bsymbolic.  Go find a match if there is a
10719130561Sobrien	     PLT entry.  */
10720130561Sobrien	  if (htab->plt != NULL)
1072189857Sobrien	    {
10722130561Sobrien	      struct plt_entry *ent;
10723218822Sdim	      for (ent = h->elf.plt.plist; ent != NULL; ent = ent->next)
10724218822Sdim		if (ent->addend == orig_addend
10725130561Sobrien		    && ent->plt.offset != (bfd_vma) -1)
10726130561Sobrien		  {
10727130561Sobrien		    relocation = (htab->plt->output_section->vma
10728130561Sobrien				  + htab->plt->output_offset
10729130561Sobrien				  + ent->plt.offset);
10730130561Sobrien		    unresolved_reloc = FALSE;
10731130561Sobrien		  }
1073289857Sobrien	    }
1073389857Sobrien	  break;
1073489857Sobrien
10735130561Sobrien	case R_PPC64_TOC:
10736130561Sobrien	  /* Relocation value is TOC base.  */
10737130561Sobrien	  relocation = TOCstart;
10738130561Sobrien	  if (r_symndx == 0)
10739130561Sobrien	    relocation += htab->stub_group[input_section->id].toc_off;
10740130561Sobrien	  else if (unresolved_reloc)
10741130561Sobrien	    ;
10742130561Sobrien	  else if (sec != NULL && sec->id <= htab->top_id)
10743130561Sobrien	    relocation += htab->stub_group[sec->id].toc_off;
10744130561Sobrien	  else
10745130561Sobrien	    unresolved_reloc = TRUE;
10746218822Sdim	  goto dodyn;
10747130561Sobrien
1074889857Sobrien	  /* TOC16 relocs.  We want the offset relative to the TOC base,
1074989857Sobrien	     which is the address of the start of the TOC plus 0x8000.
1075089857Sobrien	     The TOC consists of sections .got, .toc, .tocbss, and .plt,
1075189857Sobrien	     in this order.  */
1075289857Sobrien	case R_PPC64_TOC16:
1075389857Sobrien	case R_PPC64_TOC16_LO:
1075489857Sobrien	case R_PPC64_TOC16_HI:
1075589857Sobrien	case R_PPC64_TOC16_DS:
1075689857Sobrien	case R_PPC64_TOC16_LO_DS:
1075789857Sobrien	case R_PPC64_TOC16_HA:
10758130561Sobrien	  addend -= TOCstart + htab->stub_group[input_section->id].toc_off;
1075989857Sobrien	  break;
1076089857Sobrien
1076189857Sobrien	  /* Relocate against the beginning of the section.  */
1076289857Sobrien	case R_PPC64_SECTOFF:
1076389857Sobrien	case R_PPC64_SECTOFF_LO:
1076489857Sobrien	case R_PPC64_SECTOFF_HI:
1076589857Sobrien	case R_PPC64_SECTOFF_DS:
1076689857Sobrien	case R_PPC64_SECTOFF_LO_DS:
1076789857Sobrien	case R_PPC64_SECTOFF_HA:
10768130561Sobrien	  if (sec != NULL)
1076989857Sobrien	    addend -= sec->output_section->vma;
1077089857Sobrien	  break;
1077189857Sobrien
10772104834Sobrien	case R_PPC64_REL14:
10773104834Sobrien	case R_PPC64_REL14_BRNTAKEN:
10774104834Sobrien	case R_PPC64_REL14_BRTAKEN:
1077589857Sobrien	case R_PPC64_REL24:
1077689857Sobrien	  break;
1077789857Sobrien
10778130561Sobrien	case R_PPC64_TPREL16:
10779130561Sobrien	case R_PPC64_TPREL16_LO:
10780130561Sobrien	case R_PPC64_TPREL16_HI:
10781130561Sobrien	case R_PPC64_TPREL16_HA:
10782130561Sobrien	case R_PPC64_TPREL16_DS:
10783130561Sobrien	case R_PPC64_TPREL16_LO_DS:
10784130561Sobrien	case R_PPC64_TPREL16_HIGHER:
10785130561Sobrien	case R_PPC64_TPREL16_HIGHERA:
10786130561Sobrien	case R_PPC64_TPREL16_HIGHEST:
10787130561Sobrien	case R_PPC64_TPREL16_HIGHESTA:
10788130561Sobrien	  addend -= htab->elf.tls_sec->vma + TP_OFFSET;
10789130561Sobrien	  if (info->shared)
10790130561Sobrien	    /* The TPREL16 relocs shouldn't really be used in shared
10791130561Sobrien	       libs as they will result in DT_TEXTREL being set, but
10792130561Sobrien	       support them anyway.  */
10793130561Sobrien	    goto dodyn;
10794130561Sobrien	  break;
10795130561Sobrien
10796130561Sobrien	case R_PPC64_DTPREL16:
10797130561Sobrien	case R_PPC64_DTPREL16_LO:
10798130561Sobrien	case R_PPC64_DTPREL16_HI:
10799130561Sobrien	case R_PPC64_DTPREL16_HA:
10800130561Sobrien	case R_PPC64_DTPREL16_DS:
10801130561Sobrien	case R_PPC64_DTPREL16_LO_DS:
10802130561Sobrien	case R_PPC64_DTPREL16_HIGHER:
10803130561Sobrien	case R_PPC64_DTPREL16_HIGHERA:
10804130561Sobrien	case R_PPC64_DTPREL16_HIGHEST:
10805130561Sobrien	case R_PPC64_DTPREL16_HIGHESTA:
10806130561Sobrien	  addend -= htab->elf.tls_sec->vma + DTP_OFFSET;
10807130561Sobrien	  break;
10808130561Sobrien
10809130561Sobrien	case R_PPC64_DTPMOD64:
10810130561Sobrien	  relocation = 1;
10811130561Sobrien	  addend = 0;
10812130561Sobrien	  goto dodyn;
10813130561Sobrien
10814130561Sobrien	case R_PPC64_TPREL64:
10815130561Sobrien	  addend -= htab->elf.tls_sec->vma + TP_OFFSET;
10816130561Sobrien	  goto dodyn;
10817130561Sobrien
10818130561Sobrien	case R_PPC64_DTPREL64:
10819130561Sobrien	  addend -= htab->elf.tls_sec->vma + DTP_OFFSET;
10820130561Sobrien	  /* Fall thru */
10821130561Sobrien
1082289857Sobrien	  /* Relocations that may need to be propagated if this is a
1082389857Sobrien	     dynamic object.  */
10824130561Sobrien	case R_PPC64_REL30:
1082589857Sobrien	case R_PPC64_REL32:
1082689857Sobrien	case R_PPC64_REL64:
1082789857Sobrien	case R_PPC64_ADDR14:
1082889857Sobrien	case R_PPC64_ADDR14_BRNTAKEN:
1082989857Sobrien	case R_PPC64_ADDR14_BRTAKEN:
1083089857Sobrien	case R_PPC64_ADDR16:
1083189857Sobrien	case R_PPC64_ADDR16_DS:
1083289857Sobrien	case R_PPC64_ADDR16_HA:
1083389857Sobrien	case R_PPC64_ADDR16_HI:
1083489857Sobrien	case R_PPC64_ADDR16_HIGHER:
1083589857Sobrien	case R_PPC64_ADDR16_HIGHERA:
1083689857Sobrien	case R_PPC64_ADDR16_HIGHEST:
1083789857Sobrien	case R_PPC64_ADDR16_HIGHESTA:
1083889857Sobrien	case R_PPC64_ADDR16_LO:
1083989857Sobrien	case R_PPC64_ADDR16_LO_DS:
1084089857Sobrien	case R_PPC64_ADDR24:
1084189857Sobrien	case R_PPC64_ADDR32:
1084289857Sobrien	case R_PPC64_ADDR64:
1084389857Sobrien	case R_PPC64_UADDR16:
1084489857Sobrien	case R_PPC64_UADDR32:
1084589857Sobrien	case R_PPC64_UADDR64:
10846130561Sobrien	dodyn:
1084789857Sobrien	  if ((input_section->flags & SEC_ALLOC) == 0)
1084889857Sobrien	    break;
1084989857Sobrien
1085089857Sobrien	  if (NO_OPD_RELOCS && is_opd)
1085189857Sobrien	    break;
1085289857Sobrien
1085389857Sobrien	  if ((info->shared
10854130561Sobrien	       && (h == NULL
10855218822Sdim		   || ELF_ST_VISIBILITY (h->elf.other) == STV_DEFAULT
10856218822Sdim		   || h->elf.root.type != bfd_link_hash_undefweak)
10857130561Sobrien	       && (MUST_BE_DYN_RELOC (r_type)
10858218822Sdim		   || !SYMBOL_CALLS_LOCAL (info, &h->elf)))
10859130561Sobrien	      || (ELIMINATE_COPY_RELOCS
10860130561Sobrien		  && !info->shared
1086189857Sobrien		  && h != NULL
10862218822Sdim		  && h->elf.dynindx != -1
10863218822Sdim		  && !h->elf.non_got_ref
10864218822Sdim		  && h->elf.def_dynamic
10865218822Sdim		  && !h->elf.def_regular))
1086689857Sobrien	    {
1086789857Sobrien	      Elf_Internal_Rela outrel;
10868130561Sobrien	      bfd_boolean skip, relocate;
1086989857Sobrien	      asection *sreloc;
10870130561Sobrien	      bfd_byte *loc;
10871130561Sobrien	      bfd_vma out_off;
1087289857Sobrien
1087389857Sobrien	      /* When generating a dynamic object, these relocations
1087489857Sobrien		 are copied into the output file to be resolved at run
1087589857Sobrien		 time.  */
1087689857Sobrien
10877130561Sobrien	      skip = FALSE;
10878130561Sobrien	      relocate = FALSE;
1087989857Sobrien
10880130561Sobrien	      out_off = _bfd_elf_section_offset (output_bfd, info,
10881130561Sobrien						 input_section, rel->r_offset);
10882130561Sobrien	      if (out_off == (bfd_vma) -1)
10883130561Sobrien		skip = TRUE;
10884130561Sobrien	      else if (out_off == (bfd_vma) -2)
10885130561Sobrien		skip = TRUE, relocate = TRUE;
10886130561Sobrien	      out_off += (input_section->output_section->vma
10887130561Sobrien			  + input_section->output_offset);
10888130561Sobrien	      outrel.r_offset = out_off;
10889130561Sobrien	      outrel.r_addend = rel->r_addend;
1089089857Sobrien
10891130561Sobrien	      /* Optimize unaligned reloc use.  */
10892130561Sobrien	      if ((r_type == R_PPC64_ADDR64 && (out_off & 7) != 0)
10893130561Sobrien		  || (r_type == R_PPC64_UADDR64 && (out_off & 7) == 0))
10894130561Sobrien		r_type ^= R_PPC64_ADDR64 ^ R_PPC64_UADDR64;
10895130561Sobrien	      else if ((r_type == R_PPC64_ADDR32 && (out_off & 3) != 0)
10896130561Sobrien		       || (r_type == R_PPC64_UADDR32 && (out_off & 3) == 0))
10897130561Sobrien		r_type ^= R_PPC64_ADDR32 ^ R_PPC64_UADDR32;
10898130561Sobrien	      else if ((r_type == R_PPC64_ADDR16 && (out_off & 1) != 0)
10899130561Sobrien		       || (r_type == R_PPC64_UADDR16 && (out_off & 1) == 0))
10900130561Sobrien		r_type ^= R_PPC64_ADDR16 ^ R_PPC64_UADDR16;
10901130561Sobrien
1090289857Sobrien	      if (skip)
1090391041Sobrien		memset (&outrel, 0, sizeof outrel);
10904218822Sdim	      else if (!SYMBOL_REFERENCES_LOCAL (info, &h->elf)
1090589857Sobrien		       && !is_opd
10906130561Sobrien		       && r_type != R_PPC64_TOC)
10907218822Sdim		outrel.r_info = ELF64_R_INFO (h->elf.dynindx, r_type);
1090889857Sobrien	      else
1090989857Sobrien		{
1091089857Sobrien		  /* This symbol is local, or marked to become local,
1091189857Sobrien		     or this is an opd section reloc which must point
1091289857Sobrien		     at a local function.  */
1091389857Sobrien		  outrel.r_addend += relocation;
1091489857Sobrien		  if (r_type == R_PPC64_ADDR64 || r_type == R_PPC64_TOC)
1091589857Sobrien		    {
10916104834Sobrien		      if (is_opd && h != NULL)
10917104834Sobrien			{
10918104834Sobrien			  /* Lie about opd entries.  This case occurs
10919104834Sobrien			     when building shared libraries and we
10920104834Sobrien			     reference a function in another shared
10921104834Sobrien			     lib.  The same thing happens for a weak
10922104834Sobrien			     definition in an application that's
10923104834Sobrien			     overridden by a strong definition in a
10924104834Sobrien			     shared lib.  (I believe this is a generic
10925104834Sobrien			     bug in binutils handling of weak syms.)
10926104834Sobrien			     In these cases we won't use the opd
10927104834Sobrien			     entry in this lib.  */
10928130561Sobrien			  unresolved_reloc = FALSE;
10929104834Sobrien			}
1093089857Sobrien		      outrel.r_info = ELF64_R_INFO (0, R_PPC64_RELATIVE);
10931130561Sobrien
10932130561Sobrien		      /* We need to relocate .opd contents for ld.so.
10933130561Sobrien			 Prelink also wants simple and consistent rules
10934130561Sobrien			 for relocs.  This make all RELATIVE relocs have
10935130561Sobrien			 *r_offset equal to r_addend.  */
10936130561Sobrien		      relocate = TRUE;
1093789857Sobrien		    }
1093889857Sobrien		  else
1093989857Sobrien		    {
1094089857Sobrien		      long indx = 0;
1094189857Sobrien
1094289857Sobrien		      if (bfd_is_abs_section (sec))
1094389857Sobrien			;
1094489857Sobrien		      else if (sec == NULL || sec->owner == NULL)
1094589857Sobrien			{
1094689857Sobrien			  bfd_set_error (bfd_error_bad_value);
10947130561Sobrien			  return FALSE;
1094889857Sobrien			}
1094989857Sobrien		      else
1095089857Sobrien			{
1095189857Sobrien			  asection *osec;
1095289857Sobrien
1095389857Sobrien			  osec = sec->output_section;
1095489857Sobrien			  indx = elf_section_data (osec)->dynindx;
1095589857Sobrien
10956218822Sdim			  if (indx == 0)
10957218822Sdim			    {
10958218822Sdim			      if ((osec->flags & SEC_READONLY) == 0
10959218822Sdim				  && htab->elf.data_index_section != NULL)
10960218822Sdim				osec = htab->elf.data_index_section;
10961218822Sdim			      else
10962218822Sdim				osec = htab->elf.text_index_section;
10963218822Sdim			      indx = elf_section_data (osec)->dynindx;
10964218822Sdim			    }
10965218822Sdim			  BFD_ASSERT (indx != 0);
10966218822Sdim
1096789857Sobrien			  /* We are turning this relocation into one
1096889857Sobrien			     against a section symbol, so subtract out
1096989857Sobrien			     the output section's address but not the
1097089857Sobrien			     offset of the input section in the output
1097189857Sobrien			     section.  */
1097289857Sobrien			  outrel.r_addend -= osec->vma;
1097389857Sobrien			}
1097489857Sobrien
1097589857Sobrien		      outrel.r_info = ELF64_R_INFO (indx, r_type);
1097689857Sobrien		    }
1097789857Sobrien		}
1097889857Sobrien
1097989857Sobrien	      sreloc = elf_section_data (input_section)->sreloc;
1098089857Sobrien	      if (sreloc == NULL)
1098189857Sobrien		abort ();
1098289857Sobrien
10983218822Sdim	      if (sreloc->reloc_count * sizeof (Elf64_External_Rela)
10984218822Sdim		  >= sreloc->size)
10985218822Sdim		abort ();
10986130561Sobrien	      loc = sreloc->contents;
10987130561Sobrien	      loc += sreloc->reloc_count++ * sizeof (Elf64_External_Rela);
1098889857Sobrien	      bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
1098989857Sobrien
1099089857Sobrien	      /* If this reloc is against an external symbol, it will
1099189857Sobrien		 be computed at runtime, so there's no need to do
10992130561Sobrien		 anything now.  However, for the sake of prelink ensure
10993130561Sobrien		 that the section contents are a known value.  */
1099489857Sobrien	      if (! relocate)
10995130561Sobrien		{
10996130561Sobrien		  unresolved_reloc = FALSE;
10997130561Sobrien		  /* The value chosen here is quite arbitrary as ld.so
10998130561Sobrien		     ignores section contents except for the special
10999130561Sobrien		     case of .opd where the contents might be accessed
11000130561Sobrien		     before relocation.  Choose zero, as that won't
11001130561Sobrien		     cause reloc overflow.  */
11002130561Sobrien		  relocation = 0;
11003130561Sobrien		  addend = 0;
11004130561Sobrien		  /* Use *r_offset == r_addend for R_PPC64_ADDR64 relocs
11005130561Sobrien		     to improve backward compatibility with older
11006130561Sobrien		     versions of ld.  */
11007130561Sobrien		  if (r_type == R_PPC64_ADDR64)
11008130561Sobrien		    addend = outrel.r_addend;
11009130561Sobrien		  /* Adjust pc_relative relocs to have zero in *r_offset.  */
11010130561Sobrien		  else if (ppc64_elf_howto_table[r_type]->pc_relative)
11011130561Sobrien		    addend = (input_section->output_section->vma
11012130561Sobrien			      + input_section->output_offset
11013130561Sobrien			      + rel->r_offset);
11014130561Sobrien		}
1101589857Sobrien	    }
1101689857Sobrien	  break;
1101789857Sobrien
1101889857Sobrien	case R_PPC64_COPY:
1101989857Sobrien	case R_PPC64_GLOB_DAT:
1102089857Sobrien	case R_PPC64_JMP_SLOT:
1102189857Sobrien	case R_PPC64_RELATIVE:
1102289857Sobrien	  /* We shouldn't ever see these dynamic relocs in relocatable
1102389857Sobrien	     files.  */
11024130561Sobrien	  /* Fall through.  */
1102589857Sobrien
1102689857Sobrien	case R_PPC64_PLTGOT16:
1102789857Sobrien	case R_PPC64_PLTGOT16_DS:
1102889857Sobrien	case R_PPC64_PLTGOT16_HA:
1102989857Sobrien	case R_PPC64_PLTGOT16_HI:
1103089857Sobrien	case R_PPC64_PLTGOT16_LO:
1103189857Sobrien	case R_PPC64_PLTGOT16_LO_DS:
1103289857Sobrien	case R_PPC64_PLTREL32:
1103389857Sobrien	case R_PPC64_PLTREL64:
1103489857Sobrien	  /* These ones haven't been implemented yet.  */
1103589857Sobrien
1103689857Sobrien	  (*_bfd_error_handler)
11037218822Sdim	    (_("%B: relocation %s is not supported for symbol %s."),
11038218822Sdim	     input_bfd,
11039130561Sobrien	     ppc64_elf_howto_table[r_type]->name, sym_name);
1104089857Sobrien
1104189857Sobrien	  bfd_set_error (bfd_error_invalid_operation);
11042130561Sobrien	  ret = FALSE;
1104389857Sobrien	  continue;
1104489857Sobrien	}
1104589857Sobrien
1104689857Sobrien      /* Do any further special processing.  */
1104789857Sobrien      switch (r_type)
1104889857Sobrien	{
1104989857Sobrien	default:
1105089857Sobrien	  break;
1105189857Sobrien
1105289857Sobrien	case R_PPC64_ADDR16_HA:
1105389857Sobrien	case R_PPC64_ADDR16_HIGHERA:
1105489857Sobrien	case R_PPC64_ADDR16_HIGHESTA:
1105589857Sobrien	case R_PPC64_TOC16_HA:
1105689857Sobrien	case R_PPC64_SECTOFF_HA:
11057130561Sobrien	case R_PPC64_TPREL16_HA:
11058130561Sobrien	case R_PPC64_DTPREL16_HA:
11059130561Sobrien	case R_PPC64_TPREL16_HIGHER:
11060130561Sobrien	case R_PPC64_TPREL16_HIGHERA:
11061130561Sobrien	case R_PPC64_TPREL16_HIGHEST:
11062130561Sobrien	case R_PPC64_TPREL16_HIGHESTA:
11063130561Sobrien	case R_PPC64_DTPREL16_HIGHER:
11064130561Sobrien	case R_PPC64_DTPREL16_HIGHERA:
11065130561Sobrien	case R_PPC64_DTPREL16_HIGHEST:
11066130561Sobrien	case R_PPC64_DTPREL16_HIGHESTA:
1106789857Sobrien	  /* It's just possible that this symbol is a weak symbol
1106889857Sobrien	     that's not actually defined anywhere. In that case,
1106989857Sobrien	     'sec' would be NULL, and we should leave the symbol
1107089857Sobrien	     alone (it will be set to zero elsewhere in the link).  */
11071218822Sdim	  if (sec == NULL)
11072218822Sdim	    break;
11073218822Sdim	  /* Fall thru */
11074218822Sdim
11075218822Sdim	case R_PPC64_GOT16_HA:
11076218822Sdim	case R_PPC64_PLTGOT16_HA:
11077218822Sdim	case R_PPC64_PLT16_HA:
11078218822Sdim	case R_PPC64_GOT_TLSGD16_HA:
11079218822Sdim	case R_PPC64_GOT_TLSLD16_HA:
11080218822Sdim	case R_PPC64_GOT_TPREL16_HA:
11081218822Sdim	case R_PPC64_GOT_DTPREL16_HA:
11082218822Sdim	  /* Add 0x10000 if sign bit in 0:15 is set.
11083218822Sdim	     Bits 0:15 are not used.  */
11084218822Sdim	  addend += 0x8000;
1108589857Sobrien	  break;
1108689857Sobrien
1108789857Sobrien	case R_PPC64_ADDR16_DS:
1108889857Sobrien	case R_PPC64_ADDR16_LO_DS:
1108989857Sobrien	case R_PPC64_GOT16_DS:
1109089857Sobrien	case R_PPC64_GOT16_LO_DS:
1109189857Sobrien	case R_PPC64_PLT16_LO_DS:
1109289857Sobrien	case R_PPC64_SECTOFF_DS:
1109389857Sobrien	case R_PPC64_SECTOFF_LO_DS:
1109489857Sobrien	case R_PPC64_TOC16_DS:
1109589857Sobrien	case R_PPC64_TOC16_LO_DS:
1109689857Sobrien	case R_PPC64_PLTGOT16_DS:
1109789857Sobrien	case R_PPC64_PLTGOT16_LO_DS:
11098130561Sobrien	case R_PPC64_GOT_TPREL16_DS:
11099130561Sobrien	case R_PPC64_GOT_TPREL16_LO_DS:
11100130561Sobrien	case R_PPC64_GOT_DTPREL16_DS:
11101130561Sobrien	case R_PPC64_GOT_DTPREL16_LO_DS:
11102130561Sobrien	case R_PPC64_TPREL16_DS:
11103130561Sobrien	case R_PPC64_TPREL16_LO_DS:
11104130561Sobrien	case R_PPC64_DTPREL16_DS:
11105130561Sobrien	case R_PPC64_DTPREL16_LO_DS:
11106130561Sobrien	  insn = bfd_get_32 (input_bfd, contents + (rel->r_offset & ~3));
11107130561Sobrien	  mask = 3;
11108130561Sobrien	  /* If this reloc is against an lq insn, then the value must be
11109130561Sobrien	     a multiple of 16.  This is somewhat of a hack, but the
11110130561Sobrien	     "correct" way to do this by defining _DQ forms of all the
11111130561Sobrien	     _DS relocs bloats all reloc switches in this file.  It
11112130561Sobrien	     doesn't seem to make much sense to use any of these relocs
11113130561Sobrien	     in data, so testing the insn should be safe.  */
11114130561Sobrien	  if ((insn & (0x3f << 26)) == (56u << 26))
11115130561Sobrien	    mask = 15;
11116130561Sobrien	  if (((relocation + addend) & mask) != 0)
1111789857Sobrien	    {
1111889857Sobrien	      (*_bfd_error_handler)
11119218822Sdim		(_("%B: error: relocation %s not a multiple of %d"),
11120218822Sdim		 input_bfd,
11121130561Sobrien		 ppc64_elf_howto_table[r_type]->name,
11122130561Sobrien		 mask + 1);
1112389857Sobrien	      bfd_set_error (bfd_error_bad_value);
11124130561Sobrien	      ret = FALSE;
1112589857Sobrien	      continue;
1112689857Sobrien	    }
1112789857Sobrien	  break;
1112889857Sobrien	}
1112989857Sobrien
11130104834Sobrien      /* Dynamic relocs are not propagated for SEC_DEBUGGING sections
11131104834Sobrien	 because such sections are not SEC_ALLOC and thus ld.so will
11132104834Sobrien	 not process them.  */
1113389857Sobrien      if (unresolved_reloc
11134104834Sobrien	  && !((input_section->flags & SEC_DEBUGGING) != 0
11135218822Sdim	       && h->elf.def_dynamic))
11136104834Sobrien	{
11137104834Sobrien	  (*_bfd_error_handler)
11138218822Sdim	    (_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"),
11139218822Sdim	     input_bfd,
11140218822Sdim	     input_section,
11141104834Sobrien	     (long) rel->r_offset,
11142130561Sobrien	     ppc64_elf_howto_table[(int) r_type]->name,
11143218822Sdim	     h->elf.root.root.string);
11144130561Sobrien	  ret = FALSE;
11145104834Sobrien	}
1114689857Sobrien
1114789857Sobrien      r = _bfd_final_link_relocate (ppc64_elf_howto_table[(int) r_type],
1114889857Sobrien				    input_bfd,
1114989857Sobrien				    input_section,
1115089857Sobrien				    contents,
11151130561Sobrien				    rel->r_offset,
1115289857Sobrien				    relocation,
1115389857Sobrien				    addend);
1115489857Sobrien
11155104834Sobrien      if (r != bfd_reloc_ok)
1115689857Sobrien	{
11157130561Sobrien	  if (sym_name == NULL)
11158130561Sobrien	    sym_name = "(null)";
11159130561Sobrien	  if (r == bfd_reloc_overflow)
1116089857Sobrien	    {
11161130561Sobrien	      if (warned)
11162130561Sobrien		continue;
11163130561Sobrien	      if (h != NULL
11164218822Sdim		  && h->elf.root.type == bfd_link_hash_undefweak
11165130561Sobrien		  && ppc64_elf_howto_table[r_type]->pc_relative)
1116689857Sobrien		{
1116789857Sobrien		  /* Assume this is a call protected by other code that
1116889857Sobrien		     detects the symbol is undefined.  If this is the case,
1116989857Sobrien		     we can safely ignore the overflow.  If not, the
1117089857Sobrien		     program is hosed anyway, and a little warning isn't
1117189857Sobrien		     going to help.  */
1117289857Sobrien
1117389857Sobrien		  continue;
1117489857Sobrien		}
1117589857Sobrien
11176104834Sobrien	      if (!((*info->callbacks->reloc_overflow)
11177218822Sdim		    (info, (h ? &h->elf.root : NULL), sym_name,
11178218822Sdim		     ppc64_elf_howto_table[r_type]->name,
11179218822Sdim		     orig_addend, input_bfd, input_section, rel->r_offset)))
11180130561Sobrien		return FALSE;
11181104834Sobrien	    }
11182104834Sobrien	  else
11183104834Sobrien	    {
11184104834Sobrien	      (*_bfd_error_handler)
11185218822Sdim		(_("%B(%A+0x%lx): %s reloc against `%s': error %d"),
11186218822Sdim		 input_bfd,
11187218822Sdim		 input_section,
11188130561Sobrien		 (long) rel->r_offset,
11189130561Sobrien		 ppc64_elf_howto_table[r_type]->name,
11190130561Sobrien		 sym_name,
11191130561Sobrien		 (int) r);
11192130561Sobrien	      ret = FALSE;
11193104834Sobrien	    }
1119489857Sobrien	}
1119589857Sobrien    }
1119689857Sobrien
11197218822Sdim  /* If we're emitting relocations, then shortly after this function
11198218822Sdim     returns, reloc offsets and addends for this section will be
11199218822Sdim     adjusted.  Worse, reloc symbol indices will be for the output
11200218822Sdim     file rather than the input.  Save a copy of the relocs for
11201218822Sdim     opd_entry_value.  */
11202218822Sdim  if (is_opd && (info->emitrelocations || info->relocatable))
11203218822Sdim    {
11204218822Sdim      bfd_size_type amt;
11205218822Sdim      amt = input_section->reloc_count * sizeof (Elf_Internal_Rela);
11206218822Sdim      rel = bfd_alloc (input_bfd, amt);
11207218822Sdim      BFD_ASSERT (ppc64_elf_tdata (input_bfd)->opd_relocs == NULL);
11208218822Sdim      ppc64_elf_tdata (input_bfd)->opd_relocs = rel;
11209218822Sdim      if (rel == NULL)
11210218822Sdim	return FALSE;
11211218822Sdim      memcpy (rel, relocs, amt);
11212218822Sdim    }
1121389857Sobrien  return ret;
1121489857Sobrien}
1121589857Sobrien
11216130561Sobrien/* Adjust the value of any local symbols in opd sections.  */
11217130561Sobrien
11218130561Sobrienstatic bfd_boolean
11219130561Sobrienppc64_elf_output_symbol_hook (struct bfd_link_info *info,
11220130561Sobrien			      const char *name ATTRIBUTE_UNUSED,
11221130561Sobrien			      Elf_Internal_Sym *elfsym,
11222130561Sobrien			      asection *input_sec,
11223130561Sobrien			      struct elf_link_hash_entry *h)
11224130561Sobrien{
11225218822Sdim  long *opd_adjust, adjust;
11226130561Sobrien  bfd_vma value;
11227130561Sobrien
11228218822Sdim  if (h != NULL)
11229130561Sobrien    return TRUE;
11230130561Sobrien
11231218822Sdim  opd_adjust = get_opd_info (input_sec);
11232218822Sdim  if (opd_adjust == NULL)
11233218822Sdim    return TRUE;
11234218822Sdim
11235130561Sobrien  value = elfsym->st_value - input_sec->output_offset;
11236130561Sobrien  if (!info->relocatable)
11237130561Sobrien    value -= input_sec->output_section->vma;
11238130561Sobrien
11239218822Sdim  adjust = opd_adjust[value / 8];
11240218822Sdim  if (adjust == -1)
11241218822Sdim    elfsym->st_value = 0;
11242218822Sdim  else
11243218822Sdim    elfsym->st_value += adjust;
11244130561Sobrien  return TRUE;
11245130561Sobrien}
11246130561Sobrien
1124789857Sobrien/* Finish up dynamic symbol handling.  We set the contents of various
1124889857Sobrien   dynamic sections here.  */
1124989857Sobrien
11250130561Sobrienstatic bfd_boolean
11251130561Sobrienppc64_elf_finish_dynamic_symbol (bfd *output_bfd,
11252130561Sobrien				 struct bfd_link_info *info,
11253130561Sobrien				 struct elf_link_hash_entry *h,
11254130561Sobrien				 Elf_Internal_Sym *sym)
1125589857Sobrien{
1125689857Sobrien  struct ppc_link_hash_table *htab;
11257218822Sdim  struct plt_entry *ent;
11258218822Sdim  Elf_Internal_Rela rela;
11259218822Sdim  bfd_byte *loc;
1126089857Sobrien
1126189857Sobrien  htab = ppc_hash_table (info);
1126289857Sobrien
11263218822Sdim  for (ent = h->plt.plist; ent != NULL; ent = ent->next)
11264218822Sdim    if (ent->plt.offset != (bfd_vma) -1)
11265218822Sdim      {
11266218822Sdim	/* This symbol has an entry in the procedure linkage
11267218822Sdim	   table.  Set it up.  */
1126889857Sobrien
11269218822Sdim	if (htab->plt == NULL
11270218822Sdim	    || htab->relplt == NULL
11271218822Sdim	    || htab->glink == NULL)
11272218822Sdim	  abort ();
1127389857Sobrien
11274218822Sdim	/* Create a JMP_SLOT reloc to inform the dynamic linker to
11275218822Sdim	   fill in the PLT entry.  */
11276218822Sdim	rela.r_offset = (htab->plt->output_section->vma
11277218822Sdim			 + htab->plt->output_offset
11278218822Sdim			 + ent->plt.offset);
11279218822Sdim	rela.r_info = ELF64_R_INFO (h->dynindx, R_PPC64_JMP_SLOT);
11280218822Sdim	rela.r_addend = ent->addend;
1128189857Sobrien
11282218822Sdim	loc = htab->relplt->contents;
11283218822Sdim	loc += ((ent->plt.offset - PLT_INITIAL_ENTRY_SIZE) / PLT_ENTRY_SIZE
11284218822Sdim		* sizeof (Elf64_External_Rela));
11285218822Sdim	bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
11286218822Sdim      }
1128789857Sobrien
11288218822Sdim  if (h->needs_copy)
1128989857Sobrien    {
1129089857Sobrien      Elf_Internal_Rela rela;
11291130561Sobrien      bfd_byte *loc;
1129289857Sobrien
1129389857Sobrien      /* This symbol needs a copy reloc.  Set it up.  */
1129489857Sobrien
1129589857Sobrien      if (h->dynindx == -1
1129689857Sobrien	  || (h->root.type != bfd_link_hash_defined
1129789857Sobrien	      && h->root.type != bfd_link_hash_defweak)
11298130561Sobrien	  || htab->relbss == NULL)
1129989857Sobrien	abort ();
1130089857Sobrien
1130189857Sobrien      rela.r_offset = (h->root.u.def.value
1130289857Sobrien		       + h->root.u.def.section->output_section->vma
1130389857Sobrien		       + h->root.u.def.section->output_offset);
1130489857Sobrien      rela.r_info = ELF64_R_INFO (h->dynindx, R_PPC64_COPY);
1130589857Sobrien      rela.r_addend = 0;
11306130561Sobrien      loc = htab->relbss->contents;
11307130561Sobrien      loc += htab->relbss->reloc_count++ * sizeof (Elf64_External_Rela);
1130889857Sobrien      bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
1130989857Sobrien    }
1131089857Sobrien
1131189857Sobrien  /* Mark some specially defined symbols as absolute.  */
1131289857Sobrien  if (strcmp (h->root.root.string, "_DYNAMIC") == 0)
1131389857Sobrien    sym->st_shndx = SHN_ABS;
1131489857Sobrien
11315130561Sobrien  return TRUE;
1131689857Sobrien}
1131789857Sobrien
1131889857Sobrien/* Used to decide how to sort relocs in an optimal manner for the
1131989857Sobrien   dynamic linker, before writing them out.  */
1132089857Sobrien
1132189857Sobrienstatic enum elf_reloc_type_class
11322130561Sobrienppc64_elf_reloc_type_class (const Elf_Internal_Rela *rela)
1132389857Sobrien{
11324130561Sobrien  enum elf_ppc64_reloc_type r_type;
1132589857Sobrien
11326130561Sobrien  r_type = ELF64_R_TYPE (rela->r_info);
1132789857Sobrien  switch (r_type)
1132889857Sobrien    {
1132989857Sobrien    case R_PPC64_RELATIVE:
1133089857Sobrien      return reloc_class_relative;
1133189857Sobrien    case R_PPC64_JMP_SLOT:
1133289857Sobrien      return reloc_class_plt;
1133389857Sobrien    case R_PPC64_COPY:
1133489857Sobrien      return reloc_class_copy;
1133589857Sobrien    default:
1133689857Sobrien      return reloc_class_normal;
1133789857Sobrien    }
1133889857Sobrien}
1133989857Sobrien
1134089857Sobrien/* Finish up the dynamic sections.  */
1134189857Sobrien
11342130561Sobrienstatic bfd_boolean
11343130561Sobrienppc64_elf_finish_dynamic_sections (bfd *output_bfd,
11344130561Sobrien				   struct bfd_link_info *info)
1134589857Sobrien{
1134689857Sobrien  struct ppc_link_hash_table *htab;
1134789857Sobrien  bfd *dynobj;
1134889857Sobrien  asection *sdyn;
1134989857Sobrien
1135089857Sobrien  htab = ppc_hash_table (info);
1135189857Sobrien  dynobj = htab->elf.dynobj;
1135289857Sobrien  sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
1135389857Sobrien
1135489857Sobrien  if (htab->elf.dynamic_sections_created)
1135589857Sobrien    {
1135689857Sobrien      Elf64_External_Dyn *dyncon, *dynconend;
1135789857Sobrien
11358130561Sobrien      if (sdyn == NULL || htab->got == NULL)
1135989857Sobrien	abort ();
1136089857Sobrien
1136189857Sobrien      dyncon = (Elf64_External_Dyn *) sdyn->contents;
11362218822Sdim      dynconend = (Elf64_External_Dyn *) (sdyn->contents + sdyn->size);
1136389857Sobrien      for (; dyncon < dynconend; dyncon++)
1136489857Sobrien	{
1136589857Sobrien	  Elf_Internal_Dyn dyn;
1136691041Sobrien	  asection *s;
1136789857Sobrien
1136889857Sobrien	  bfd_elf64_swap_dyn_in (dynobj, dyncon, &dyn);
1136989857Sobrien
1137089857Sobrien	  switch (dyn.d_tag)
1137189857Sobrien	    {
1137289857Sobrien	    default:
1137389857Sobrien	      continue;
1137489857Sobrien
1137589857Sobrien	    case DT_PPC64_GLINK:
11376130561Sobrien	      s = htab->glink;
11377130561Sobrien	      dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
11378130561Sobrien	      /* We stupidly defined DT_PPC64_GLINK to be the start
11379130561Sobrien		 of glink rather than the first entry point, which is
11380130561Sobrien		 what ld.so needs, and now have a bigger stub to
11381130561Sobrien		 support automatic multiple TOCs.  */
11382130561Sobrien	      dyn.d_un.d_ptr += GLINK_CALL_STUB_SIZE - 32;
1138389857Sobrien	      break;
1138489857Sobrien
1138591041Sobrien	    case DT_PPC64_OPD:
1138691041Sobrien	      s = bfd_get_section_by_name (output_bfd, ".opd");
11387130561Sobrien	      if (s == NULL)
11388130561Sobrien		continue;
11389130561Sobrien	      dyn.d_un.d_ptr = s->vma;
1139091041Sobrien	      break;
1139191041Sobrien
1139291041Sobrien	    case DT_PPC64_OPDSZ:
1139391041Sobrien	      s = bfd_get_section_by_name (output_bfd, ".opd");
11394130561Sobrien	      if (s == NULL)
11395130561Sobrien		continue;
11396218822Sdim	      dyn.d_un.d_val = s->size;
1139791041Sobrien	      break;
1139891041Sobrien
1139989857Sobrien	    case DT_PLTGOT:
11400130561Sobrien	      s = htab->plt;
11401130561Sobrien	      dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
1140289857Sobrien	      break;
1140389857Sobrien
1140489857Sobrien	    case DT_JMPREL:
11405130561Sobrien	      s = htab->relplt;
11406130561Sobrien	      dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
1140789857Sobrien	      break;
1140889857Sobrien
1140989857Sobrien	    case DT_PLTRELSZ:
11410218822Sdim	      dyn.d_un.d_val = htab->relplt->size;
1141189857Sobrien	      break;
1141289857Sobrien
1141389857Sobrien	    case DT_RELASZ:
1141489857Sobrien	      /* Don't count procedure linkage table relocs in the
1141589857Sobrien		 overall reloc count.  */
11416130561Sobrien	      s = htab->relplt;
11417130561Sobrien	      if (s == NULL)
11418130561Sobrien		continue;
11419218822Sdim	      dyn.d_un.d_val -= s->size;
1142089857Sobrien	      break;
11421130561Sobrien
11422130561Sobrien	    case DT_RELA:
11423130561Sobrien	      /* We may not be using the standard ELF linker script.
11424130561Sobrien		 If .rela.plt is the first .rela section, we adjust
11425130561Sobrien		 DT_RELA to not include it.  */
11426130561Sobrien	      s = htab->relplt;
11427130561Sobrien	      if (s == NULL)
11428130561Sobrien		continue;
11429130561Sobrien	      if (dyn.d_un.d_ptr != s->output_section->vma + s->output_offset)
11430130561Sobrien		continue;
11431218822Sdim	      dyn.d_un.d_ptr += s->size;
11432130561Sobrien	      break;
1143389857Sobrien	    }
1143489857Sobrien
1143589857Sobrien	  bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon);
1143689857Sobrien	}
1143789857Sobrien    }
1143889857Sobrien
11439218822Sdim  if (htab->got != NULL && htab->got->size != 0)
1144089857Sobrien    {
1144189857Sobrien      /* Fill in the first entry in the global offset table.
1144289857Sobrien	 We use it to hold the link-time TOCbase.  */
1144389857Sobrien      bfd_put_64 (output_bfd,
1144489857Sobrien		  elf_gp (output_bfd) + TOC_BASE_OFF,
11445130561Sobrien		  htab->got->contents);
1144689857Sobrien
1144789857Sobrien      /* Set .got entry size.  */
11448130561Sobrien      elf_section_data (htab->got->output_section)->this_hdr.sh_entsize = 8;
1144989857Sobrien    }
1145089857Sobrien
11451218822Sdim  if (htab->plt != NULL && htab->plt->size != 0)
1145289857Sobrien    {
1145389857Sobrien      /* Set .plt entry size.  */
11454130561Sobrien      elf_section_data (htab->plt->output_section)->this_hdr.sh_entsize
1145589857Sobrien	= PLT_ENTRY_SIZE;
1145689857Sobrien    }
1145789857Sobrien
11458218822Sdim  /* brlt is SEC_LINKER_CREATED, so we need to write out relocs for
11459218822Sdim     brlt ourselves if emitrelocations.  */
11460218822Sdim  if (htab->brlt != NULL
11461218822Sdim      && htab->brlt->reloc_count != 0
11462218822Sdim      && !_bfd_elf_link_output_relocs (output_bfd,
11463218822Sdim				       htab->brlt,
11464218822Sdim				       &elf_section_data (htab->brlt)->rel_hdr,
11465218822Sdim				       elf_section_data (htab->brlt)->relocs,
11466218822Sdim				       NULL))
11467218822Sdim    return FALSE;
11468218822Sdim
11469130561Sobrien  /* We need to handle writing out multiple GOT sections ourselves,
11470218822Sdim     since we didn't add them to DYNOBJ.  We know dynobj is the first
11471218822Sdim     bfd.  */
11472130561Sobrien  while ((dynobj = dynobj->link_next) != NULL)
11473130561Sobrien    {
11474130561Sobrien      asection *s;
11475209867Snwhitehorn
11476218822Sdim      if (!is_ppc64_elf_target (dynobj->xvec))
11477209867Snwhitehorn	continue;
11478209867Snwhitehorn
11479130561Sobrien      s = ppc64_elf_tdata (dynobj)->got;
11480130561Sobrien      if (s != NULL
11481218822Sdim	  && s->size != 0
11482130561Sobrien	  && s->output_section != bfd_abs_section_ptr
11483130561Sobrien	  && !bfd_set_section_contents (output_bfd, s->output_section,
11484130561Sobrien					s->contents, s->output_offset,
11485218822Sdim					s->size))
11486130561Sobrien	return FALSE;
11487130561Sobrien      s = ppc64_elf_tdata (dynobj)->relgot;
11488130561Sobrien      if (s != NULL
11489218822Sdim	  && s->size != 0
11490130561Sobrien	  && s->output_section != bfd_abs_section_ptr
11491130561Sobrien	  && !bfd_set_section_contents (output_bfd, s->output_section,
11492130561Sobrien					s->contents, s->output_offset,
11493218822Sdim					s->size))
11494130561Sobrien	return FALSE;
11495130561Sobrien    }
11496130561Sobrien
11497130561Sobrien  return TRUE;
1149889857Sobrien}
1149989857Sobrien
1150089857Sobrien#include "elf64-target.h"
11501