elf32-ppc.c revision 89857
160484Sobrien/* PowerPC-specific support for 32-bit ELF
278828Sobrien   Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
378828Sobrien   Free Software Foundation, Inc.
460484Sobrien   Written by Ian Lance Taylor, Cygnus Support.
560484Sobrien
660484SobrienThis file is part of BFD, the Binary File Descriptor library.
760484Sobrien
860484SobrienThis program is free software; you can redistribute it and/or modify
960484Sobrienit under the terms of the GNU General Public License as published by
1060484Sobrienthe Free Software Foundation; either version 2 of the License, or
1160484Sobrien(at your option) any later version.
1260484Sobrien
1360484SobrienThis program is distributed in the hope that it will be useful,
1460484Sobrienbut WITHOUT ANY WARRANTY; without even the implied warranty of
1560484SobrienMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1660484SobrienGNU General Public License for more details.
1760484Sobrien
1860484SobrienYou should have received a copy of the GNU General Public License
1960484Sobrienalong with this program; if not, write to the Free Software
2060484SobrienFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
2160484Sobrien
2260484Sobrien/* This file is based on a preliminary PowerPC ELF ABI.  The
2360484Sobrien   information may not match the final PowerPC ELF ABI.  It includes
2460484Sobrien   suggestions from the in-progress Embedded PowerPC ABI, and that
2560484Sobrien   information may also not match.  */
2660484Sobrien
2760484Sobrien#include "bfd.h"
2860484Sobrien#include "sysdep.h"
2960484Sobrien#include "bfdlink.h"
3060484Sobrien#include "libbfd.h"
3160484Sobrien#include "elf-bfd.h"
3260484Sobrien#include "elf/ppc.h"
3360484Sobrien
3460484Sobrien#define USE_RELA		/* we want RELA relocations, not REL */
3560484Sobrien
3660484Sobrienstatic reloc_howto_type *ppc_elf_reloc_type_lookup
3760484Sobrien  PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
3860484Sobrienstatic void ppc_elf_info_to_howto
3960484Sobrien  PARAMS ((bfd *abfd, arelent *cache_ptr, Elf32_Internal_Rela *dst));
4060484Sobrienstatic void ppc_elf_howto_init PARAMS ((void));
4189857Sobrienstatic int ppc_elf_sort_rela PARAMS ((const PTR, const PTR));
4289857Sobrienstatic boolean ppc_elf_relax_section
4389857Sobrien  PARAMS ((bfd *, asection *, struct bfd_link_info *, boolean *));
4460484Sobrienstatic bfd_reloc_status_type ppc_elf_addr16_ha_reloc
4560484Sobrien  PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
4660484Sobrienstatic boolean ppc_elf_set_private_flags PARAMS ((bfd *, flagword));
4760484Sobrienstatic boolean ppc_elf_merge_private_bfd_data PARAMS ((bfd *, bfd *));
4860484Sobrien
4960484Sobrienstatic int ppc_elf_additional_program_headers PARAMS ((bfd *));
5060484Sobrienstatic boolean ppc_elf_modify_segment_map PARAMS ((bfd *));
5160484Sobrien
5260484Sobrienstatic boolean ppc_elf_create_dynamic_sections
5360484Sobrien  PARAMS ((bfd *, struct bfd_link_info *));
5460484Sobrien
5560484Sobrienstatic boolean ppc_elf_section_from_shdr PARAMS ((bfd *,
5660484Sobrien						  Elf32_Internal_Shdr *,
5760484Sobrien						  char *));
5860484Sobrienstatic boolean ppc_elf_fake_sections
5960484Sobrien  PARAMS ((bfd *, Elf32_Internal_Shdr *, asection *));
6060484Sobrien
6160484Sobrienstatic elf_linker_section_t *ppc_elf_create_linker_section
6260484Sobrien  PARAMS ((bfd *abfd,
6360484Sobrien	   struct bfd_link_info *info,
6460484Sobrien	   enum elf_linker_section_enum));
6560484Sobrien
6660484Sobrienstatic boolean ppc_elf_check_relocs PARAMS ((bfd *,
6760484Sobrien					     struct bfd_link_info *,
6860484Sobrien					     asection *,
6960484Sobrien					     const Elf_Internal_Rela *));
7060484Sobrien
7160484Sobrienstatic asection * ppc_elf_gc_mark_hook PARAMS ((bfd *abfd,
7260484Sobrien						struct bfd_link_info *info,
7360484Sobrien						Elf_Internal_Rela *rel,
7460484Sobrien						struct elf_link_hash_entry *h,
7560484Sobrien						Elf_Internal_Sym *sym));
7660484Sobrien
7760484Sobrienstatic boolean ppc_elf_gc_sweep_hook PARAMS ((bfd *abfd,
7860484Sobrien					      struct bfd_link_info *info,
7960484Sobrien					      asection *sec,
8060484Sobrien					      const Elf_Internal_Rela *relocs));
8160484Sobrien
8260484Sobrienstatic boolean ppc_elf_adjust_dynamic_symbol PARAMS ((struct bfd_link_info *,
8360484Sobrien						      struct elf_link_hash_entry *));
8460484Sobrien
8560484Sobrienstatic boolean ppc_elf_size_dynamic_sections PARAMS ((bfd *, struct bfd_link_info *));
8660484Sobrien
8760484Sobrienstatic boolean ppc_elf_relocate_section PARAMS ((bfd *,
8860484Sobrien						 struct bfd_link_info *info,
8960484Sobrien						 bfd *,
9060484Sobrien						 asection *,
9160484Sobrien						 bfd_byte *,
9260484Sobrien						 Elf_Internal_Rela *relocs,
9360484Sobrien						 Elf_Internal_Sym *local_syms,
9460484Sobrien						 asection **));
9560484Sobrien
9660484Sobrienstatic boolean ppc_elf_add_symbol_hook  PARAMS ((bfd *,
9760484Sobrien						 struct bfd_link_info *,
9860484Sobrien						 const Elf_Internal_Sym *,
9960484Sobrien						 const char **,
10060484Sobrien						 flagword *,
10160484Sobrien						 asection **,
10260484Sobrien						 bfd_vma *));
10360484Sobrien
10460484Sobrienstatic boolean ppc_elf_finish_dynamic_symbol PARAMS ((bfd *,
10560484Sobrien						      struct bfd_link_info *,
10660484Sobrien						      struct elf_link_hash_entry *,
10760484Sobrien						      Elf_Internal_Sym *));
10860484Sobrien
10960484Sobrienstatic boolean ppc_elf_finish_dynamic_sections PARAMS ((bfd *, struct bfd_link_info *));
11089857Sobrienstatic enum elf_reloc_type_class ppc_elf_reloc_type_class
11189857Sobrien  PARAMS ((const Elf_Internal_Rela *));
11289857Sobrienstatic boolean ppc_elf_grok_prstatus
11389857Sobrien  PARAMS ((bfd *abfd, Elf_Internal_Note *note));
11489857Sobrienstatic boolean ppc_elf_grok_psinfo
11589857Sobrien  PARAMS ((bfd *abfd, Elf_Internal_Note *note));
11660484Sobrien
11760484Sobrien#define BRANCH_PREDICT_BIT 0x200000		/* branch prediction bit for branch taken relocs */
11860484Sobrien#define RA_REGISTER_MASK 0x001f0000		/* mask to set RA in memory instructions */
11960484Sobrien#define RA_REGISTER_SHIFT 16			/* value to shift register by to insert RA */
12060484Sobrien
12160484Sobrien/* The name of the dynamic interpreter.  This is put in the .interp
12260484Sobrien   section.  */
12360484Sobrien
12460484Sobrien#define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1"
12560484Sobrien
12660484Sobrien/* The size in bytes of an entry in the procedure linkage table.  */
12760484Sobrien#define PLT_ENTRY_SIZE 12
12860484Sobrien/* The initial size of the plt reserved for the dynamic linker.  */
12960484Sobrien#define PLT_INITIAL_ENTRY_SIZE 72
13060484Sobrien/* The size of the gap between entries in the PLT.  */
13160484Sobrien#define PLT_SLOT_SIZE 8
13260484Sobrien/* The number of single-slot PLT entries (the rest use two slots).  */
13360484Sobrien#define PLT_NUM_SINGLE_ENTRIES 8192
13460484Sobrien
13577298Sobrien/* Will references to this symbol always reference the symbol
13677298Sobrien   in this object?  */
13777298Sobrien#define SYMBOL_REFERENCES_LOCAL(INFO, H)				\
13877298Sobrien  ((! INFO->shared							\
13977298Sobrien    || INFO->symbolic							\
14077298Sobrien    || H->dynindx == -1							\
14177298Sobrien    || ELF_ST_VISIBILITY (H->other) == STV_INTERNAL			\
14277298Sobrien    || ELF_ST_VISIBILITY (H->other) == STV_HIDDEN)			\
14377298Sobrien   && (H->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0)
14477298Sobrien
14577298Sobrien/* Will _calls_ to this symbol always call the version in this object?  */
14677298Sobrien#define SYMBOL_CALLS_LOCAL(INFO, H)				\
14777298Sobrien  ((! INFO->shared							\
14877298Sobrien    || INFO->symbolic							\
14977298Sobrien    || H->dynindx == -1							\
15077298Sobrien    || ELF_ST_VISIBILITY (H->other) != STV_DEFAULT)			\
15177298Sobrien   && (H->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0)
15260484Sobrien
15377298Sobrienstatic reloc_howto_type *ppc_elf_howto_table[(int) R_PPC_max];
15460484Sobrien
15577298Sobrienstatic reloc_howto_type ppc_elf_howto_raw[] = {
15660484Sobrien  /* This reloc does nothing.  */
15760484Sobrien  HOWTO (R_PPC_NONE,		/* type */
15860484Sobrien	 0,			/* rightshift */
15960484Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
16060484Sobrien	 32,			/* bitsize */
16160484Sobrien	 false,			/* pc_relative */
16260484Sobrien	 0,			/* bitpos */
16360484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
16460484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
16560484Sobrien	 "R_PPC_NONE",		/* name */
16660484Sobrien	 false,			/* partial_inplace */
16760484Sobrien	 0,			/* src_mask */
16860484Sobrien	 0,			/* dst_mask */
16960484Sobrien	 false),		/* pcrel_offset */
17060484Sobrien
17160484Sobrien  /* A standard 32 bit relocation.  */
17260484Sobrien  HOWTO (R_PPC_ADDR32,		/* type */
17360484Sobrien	 0,			/* rightshift */
17460484Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
17560484Sobrien	 32,			/* bitsize */
17660484Sobrien	 false,			/* pc_relative */
17760484Sobrien	 0,			/* bitpos */
17860484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
17960484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
18060484Sobrien	 "R_PPC_ADDR32",	/* name */
18160484Sobrien	 false,			/* partial_inplace */
18260484Sobrien	 0,			/* src_mask */
18360484Sobrien	 0xffffffff,		/* dst_mask */
18460484Sobrien	 false),		/* pcrel_offset */
18560484Sobrien
18660484Sobrien  /* An absolute 26 bit branch; the lower two bits must be zero.
18760484Sobrien     FIXME: we don't check that, we just clear them.  */
18860484Sobrien  HOWTO (R_PPC_ADDR24,		/* type */
18960484Sobrien	 0,			/* rightshift */
19060484Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
19160484Sobrien	 26,			/* bitsize */
19260484Sobrien	 false,			/* pc_relative */
19360484Sobrien	 0,			/* bitpos */
19460484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
19560484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
19660484Sobrien	 "R_PPC_ADDR24",	/* name */
19760484Sobrien	 false,			/* partial_inplace */
19860484Sobrien	 0,			/* src_mask */
19960484Sobrien	 0x3fffffc,		/* dst_mask */
20060484Sobrien	 false),		/* pcrel_offset */
20160484Sobrien
20260484Sobrien  /* A standard 16 bit relocation.  */
20360484Sobrien  HOWTO (R_PPC_ADDR16,		/* type */
20460484Sobrien	 0,			/* rightshift */
20560484Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
20660484Sobrien	 16,			/* bitsize */
20760484Sobrien	 false,			/* pc_relative */
20860484Sobrien	 0,			/* bitpos */
20960484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
21060484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
21160484Sobrien	 "R_PPC_ADDR16",	/* name */
21260484Sobrien	 false,			/* partial_inplace */
21360484Sobrien	 0,			/* src_mask */
21460484Sobrien	 0xffff,		/* dst_mask */
21560484Sobrien	 false),		/* pcrel_offset */
21660484Sobrien
21760484Sobrien  /* A 16 bit relocation without overflow.  */
21860484Sobrien  HOWTO (R_PPC_ADDR16_LO,	/* type */
21960484Sobrien	 0,			/* rightshift */
22060484Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
22160484Sobrien	 16,			/* bitsize */
22260484Sobrien	 false,			/* pc_relative */
22360484Sobrien	 0,			/* bitpos */
22460484Sobrien	 complain_overflow_dont,/* complain_on_overflow */
22560484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
22660484Sobrien	 "R_PPC_ADDR16_LO",	/* name */
22760484Sobrien	 false,			/* partial_inplace */
22860484Sobrien	 0,			/* src_mask */
22960484Sobrien	 0xffff,		/* dst_mask */
23060484Sobrien	 false),		/* pcrel_offset */
23160484Sobrien
23260484Sobrien  /* The high order 16 bits of an address.  */
23360484Sobrien  HOWTO (R_PPC_ADDR16_HI,	/* type */
23460484Sobrien	 16,			/* rightshift */
23560484Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
23660484Sobrien	 16,			/* bitsize */
23760484Sobrien	 false,			/* pc_relative */
23860484Sobrien	 0,			/* bitpos */
23960484Sobrien	 complain_overflow_dont, /* complain_on_overflow */
24060484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
24160484Sobrien	 "R_PPC_ADDR16_HI",	/* name */
24260484Sobrien	 false,			/* partial_inplace */
24360484Sobrien	 0,			/* src_mask */
24460484Sobrien	 0xffff,		/* dst_mask */
24560484Sobrien	 false),		/* pcrel_offset */
24660484Sobrien
24760484Sobrien  /* The high order 16 bits of an address, plus 1 if the contents of
24877298Sobrien     the low 16 bits, treated as a signed number, is negative.  */
24960484Sobrien  HOWTO (R_PPC_ADDR16_HA,	/* type */
25060484Sobrien	 16,			/* rightshift */
25160484Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
25260484Sobrien	 16,			/* bitsize */
25360484Sobrien	 false,			/* pc_relative */
25460484Sobrien	 0,			/* bitpos */
25560484Sobrien	 complain_overflow_dont, /* complain_on_overflow */
25660484Sobrien	 ppc_elf_addr16_ha_reloc, /* special_function */
25760484Sobrien	 "R_PPC_ADDR16_HA",	/* name */
25860484Sobrien	 false,			/* partial_inplace */
25960484Sobrien	 0,			/* src_mask */
26060484Sobrien	 0xffff,		/* dst_mask */
26160484Sobrien	 false),		/* pcrel_offset */
26260484Sobrien
26360484Sobrien  /* An absolute 16 bit branch; the lower two bits must be zero.
26460484Sobrien     FIXME: we don't check that, we just clear them.  */
26560484Sobrien  HOWTO (R_PPC_ADDR14,		/* type */
26660484Sobrien	 0,			/* rightshift */
26760484Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
26860484Sobrien	 16,			/* bitsize */
26960484Sobrien	 false,			/* pc_relative */
27060484Sobrien	 0,			/* bitpos */
27160484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
27260484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
27360484Sobrien	 "R_PPC_ADDR14",	/* name */
27460484Sobrien	 false,			/* partial_inplace */
27560484Sobrien	 0,			/* src_mask */
27660484Sobrien	 0xfffc,		/* dst_mask */
27760484Sobrien	 false),		/* pcrel_offset */
27860484Sobrien
27960484Sobrien  /* An absolute 16 bit branch, for which bit 10 should be set to
28060484Sobrien     indicate that the branch is expected to be taken.	The lower two
28177298Sobrien     bits must be zero.  */
28260484Sobrien  HOWTO (R_PPC_ADDR14_BRTAKEN,	/* type */
28360484Sobrien	 0,			/* rightshift */
28460484Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
28560484Sobrien	 16,			/* bitsize */
28660484Sobrien	 false,			/* pc_relative */
28760484Sobrien	 0,			/* bitpos */
28860484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
28960484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
29060484Sobrien	 "R_PPC_ADDR14_BRTAKEN",/* name */
29160484Sobrien	 false,			/* partial_inplace */
29260484Sobrien	 0,			/* src_mask */
29360484Sobrien	 0xfffc,		/* dst_mask */
29460484Sobrien	 false),		/* pcrel_offset */
29560484Sobrien
29660484Sobrien  /* An absolute 16 bit branch, for which bit 10 should be set to
29760484Sobrien     indicate that the branch is not expected to be taken.  The lower
29860484Sobrien     two bits must be zero.  */
29960484Sobrien  HOWTO (R_PPC_ADDR14_BRNTAKEN, /* type */
30060484Sobrien	 0,			/* rightshift */
30160484Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
30260484Sobrien	 16,			/* bitsize */
30360484Sobrien	 false,			/* pc_relative */
30460484Sobrien	 0,			/* bitpos */
30560484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
30660484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
30760484Sobrien	 "R_PPC_ADDR14_BRNTAKEN",/* name */
30860484Sobrien	 false,			/* partial_inplace */
30960484Sobrien	 0,			/* src_mask */
31060484Sobrien	 0xfffc,		/* dst_mask */
31160484Sobrien	 false),		/* pcrel_offset */
31260484Sobrien
31377298Sobrien  /* A relative 26 bit branch; the lower two bits must be zero.  */
31460484Sobrien  HOWTO (R_PPC_REL24,		/* type */
31560484Sobrien	 0,			/* rightshift */
31660484Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
31760484Sobrien	 26,			/* bitsize */
31860484Sobrien	 true,			/* pc_relative */
31960484Sobrien	 0,			/* bitpos */
32060484Sobrien	 complain_overflow_signed, /* complain_on_overflow */
32160484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
32260484Sobrien	 "R_PPC_REL24",		/* name */
32360484Sobrien	 false,			/* partial_inplace */
32460484Sobrien	 0,			/* src_mask */
32560484Sobrien	 0x3fffffc,		/* dst_mask */
32660484Sobrien	 true),			/* pcrel_offset */
32760484Sobrien
32877298Sobrien  /* A relative 16 bit branch; the lower two bits must be zero.  */
32960484Sobrien  HOWTO (R_PPC_REL14,		/* type */
33060484Sobrien	 0,			/* rightshift */
33160484Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
33260484Sobrien	 16,			/* bitsize */
33360484Sobrien	 true,			/* pc_relative */
33460484Sobrien	 0,			/* bitpos */
33560484Sobrien	 complain_overflow_signed, /* complain_on_overflow */
33660484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
33760484Sobrien	 "R_PPC_REL14",		/* name */
33860484Sobrien	 false,			/* partial_inplace */
33960484Sobrien	 0,			/* src_mask */
34060484Sobrien	 0xfffc,		/* dst_mask */
34160484Sobrien	 true),			/* pcrel_offset */
34260484Sobrien
34377298Sobrien  /* A relative 16 bit branch.  Bit 10 should be set to indicate that
34460484Sobrien     the branch is expected to be taken.  The lower two bits must be
34560484Sobrien     zero.  */
34660484Sobrien  HOWTO (R_PPC_REL14_BRTAKEN,	/* type */
34760484Sobrien	 0,			/* rightshift */
34860484Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
34960484Sobrien	 16,			/* bitsize */
35060484Sobrien	 true,			/* pc_relative */
35160484Sobrien	 0,			/* bitpos */
35260484Sobrien	 complain_overflow_signed, /* complain_on_overflow */
35360484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
35460484Sobrien	 "R_PPC_REL14_BRTAKEN",	/* name */
35560484Sobrien	 false,			/* partial_inplace */
35660484Sobrien	 0,			/* src_mask */
35760484Sobrien	 0xfffc,		/* dst_mask */
35860484Sobrien	 true),			/* pcrel_offset */
35960484Sobrien
36077298Sobrien  /* A relative 16 bit branch.  Bit 10 should be set to indicate that
36160484Sobrien     the branch is not expected to be taken.  The lower two bits must
36260484Sobrien     be zero.  */
36360484Sobrien  HOWTO (R_PPC_REL14_BRNTAKEN,	/* type */
36460484Sobrien	 0,			/* rightshift */
36560484Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
36660484Sobrien	 16,			/* bitsize */
36760484Sobrien	 true,			/* pc_relative */
36860484Sobrien	 0,			/* bitpos */
36960484Sobrien	 complain_overflow_signed, /* complain_on_overflow */
37060484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
37160484Sobrien	 "R_PPC_REL14_BRNTAKEN",/* name */
37260484Sobrien	 false,			/* partial_inplace */
37360484Sobrien	 0,			/* src_mask */
37460484Sobrien	 0xfffc,		/* dst_mask */
37560484Sobrien	 true),			/* pcrel_offset */
37660484Sobrien
37760484Sobrien  /* Like R_PPC_ADDR16, but referring to the GOT table entry for the
37860484Sobrien     symbol.  */
37960484Sobrien  HOWTO (R_PPC_GOT16,		/* type */
38060484Sobrien	 0,			/* rightshift */
38160484Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
38260484Sobrien	 16,			/* bitsize */
38360484Sobrien	 false,			/* pc_relative */
38460484Sobrien	 0,			/* bitpos */
38560484Sobrien	 complain_overflow_signed, /* complain_on_overflow */
38660484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
38760484Sobrien	 "R_PPC_GOT16",		/* name */
38860484Sobrien	 false,			/* partial_inplace */
38960484Sobrien	 0,			/* src_mask */
39060484Sobrien	 0xffff,		/* dst_mask */
39160484Sobrien	 false),		/* pcrel_offset */
39260484Sobrien
39360484Sobrien  /* Like R_PPC_ADDR16_LO, but referring to the GOT table entry for
39460484Sobrien     the symbol.  */
39560484Sobrien  HOWTO (R_PPC_GOT16_LO,	/* type */
39660484Sobrien	 0,			/* rightshift */
39760484Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
39860484Sobrien	 16,			/* bitsize */
39960484Sobrien	 false,			/* pc_relative */
40060484Sobrien	 0,			/* bitpos */
40160484Sobrien	 complain_overflow_dont, /* complain_on_overflow */
40260484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
40360484Sobrien	 "R_PPC_GOT16_LO",	/* name */
40460484Sobrien	 false,			/* partial_inplace */
40560484Sobrien	 0,			/* src_mask */
40660484Sobrien	 0xffff,		/* dst_mask */
40760484Sobrien	 false),		/* pcrel_offset */
40860484Sobrien
40960484Sobrien  /* Like R_PPC_ADDR16_HI, but referring to the GOT table entry for
41060484Sobrien     the symbol.  */
41160484Sobrien  HOWTO (R_PPC_GOT16_HI,	/* type */
41260484Sobrien	 16,			/* rightshift */
41360484Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
41460484Sobrien	 16,			/* bitsize */
41560484Sobrien	 false,			/* pc_relative */
41660484Sobrien	 0,			/* bitpos */
41760484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
41860484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
41960484Sobrien	 "R_PPC_GOT16_HI",	/* name */
42060484Sobrien	 false,			/* partial_inplace */
42160484Sobrien	 0,			/* src_mask */
42260484Sobrien	 0xffff,		/* dst_mask */
42360484Sobrien	 false),		 /* pcrel_offset */
42460484Sobrien
42560484Sobrien  /* Like R_PPC_ADDR16_HA, but referring to the GOT table entry for
42660484Sobrien     the symbol.  */
42760484Sobrien  HOWTO (R_PPC_GOT16_HA,	/* type */
42860484Sobrien	 16,			/* rightshift */
42960484Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
43060484Sobrien	 16,			/* bitsize */
43160484Sobrien	 false,			/* pc_relative */
43260484Sobrien	 0,			/* bitpos */
43360484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
43460484Sobrien	 ppc_elf_addr16_ha_reloc, /* special_function */
43560484Sobrien	 "R_PPC_GOT16_HA",	/* name */
43660484Sobrien	 false,			/* partial_inplace */
43760484Sobrien	 0,			/* src_mask */
43860484Sobrien	 0xffff,		/* dst_mask */
43960484Sobrien	 false),		/* pcrel_offset */
44060484Sobrien
44160484Sobrien  /* Like R_PPC_REL24, but referring to the procedure linkage table
44260484Sobrien     entry for the symbol.  */
44360484Sobrien  HOWTO (R_PPC_PLTREL24,	/* type */
44460484Sobrien	 0,			/* rightshift */
44560484Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
44660484Sobrien	 26,			/* bitsize */
44760484Sobrien	 true,			/* pc_relative */
44860484Sobrien	 0,			/* bitpos */
44960484Sobrien	 complain_overflow_signed,  /* complain_on_overflow */
45060484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
45160484Sobrien	 "R_PPC_PLTREL24",	/* name */
45260484Sobrien	 false,			/* partial_inplace */
45360484Sobrien	 0,			/* src_mask */
45460484Sobrien	 0x3fffffc,		/* dst_mask */
45560484Sobrien	 true),			/* pcrel_offset */
45660484Sobrien
45760484Sobrien  /* This is used only by the dynamic linker.  The symbol should exist
45860484Sobrien     both in the object being run and in some shared library.  The
45960484Sobrien     dynamic linker copies the data addressed by the symbol from the
46060484Sobrien     shared library into the object, because the object being
46160484Sobrien     run has to have the data at some particular address.  */
46260484Sobrien  HOWTO (R_PPC_COPY,		/* type */
46360484Sobrien	 0,			/* rightshift */
46460484Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
46560484Sobrien	 32,			/* bitsize */
46660484Sobrien	 false,			/* pc_relative */
46760484Sobrien	 0,			/* bitpos */
46860484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
46960484Sobrien	 bfd_elf_generic_reloc,	 /* special_function */
47060484Sobrien	 "R_PPC_COPY",		/* name */
47160484Sobrien	 false,			/* partial_inplace */
47260484Sobrien	 0,			/* src_mask */
47360484Sobrien	 0,			/* dst_mask */
47460484Sobrien	 false),		/* pcrel_offset */
47560484Sobrien
47660484Sobrien  /* Like R_PPC_ADDR32, but used when setting global offset table
47760484Sobrien     entries.  */
47860484Sobrien  HOWTO (R_PPC_GLOB_DAT,	/* type */
47960484Sobrien	 0,			/* rightshift */
48060484Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
48160484Sobrien	 32,			/* bitsize */
48260484Sobrien	 false,			/* pc_relative */
48360484Sobrien	 0,			/* bitpos */
48460484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
48560484Sobrien	 bfd_elf_generic_reloc,	 /* special_function */
48660484Sobrien	 "R_PPC_GLOB_DAT",	/* name */
48760484Sobrien	 false,			/* partial_inplace */
48860484Sobrien	 0,			/* src_mask */
48960484Sobrien	 0xffffffff,		/* dst_mask */
49060484Sobrien	 false),		/* pcrel_offset */
49160484Sobrien
49260484Sobrien  /* Marks a procedure linkage table entry for a symbol.  */
49360484Sobrien  HOWTO (R_PPC_JMP_SLOT,	/* type */
49460484Sobrien	 0,			/* rightshift */
49560484Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
49660484Sobrien	 32,			/* bitsize */
49760484Sobrien	 false,			/* pc_relative */
49860484Sobrien	 0,			/* bitpos */
49960484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
50060484Sobrien	 bfd_elf_generic_reloc,	 /* special_function */
50160484Sobrien	 "R_PPC_JMP_SLOT",	/* name */
50260484Sobrien	 false,			/* partial_inplace */
50360484Sobrien	 0,			/* src_mask */
50460484Sobrien	 0,			/* dst_mask */
50560484Sobrien	 false),		/* pcrel_offset */
50660484Sobrien
50760484Sobrien  /* Used only by the dynamic linker.  When the object is run, this
50860484Sobrien     longword is set to the load address of the object, plus the
50960484Sobrien     addend.  */
51060484Sobrien  HOWTO (R_PPC_RELATIVE,	/* type */
51160484Sobrien	 0,			/* rightshift */
51260484Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
51360484Sobrien	 32,			/* bitsize */
51460484Sobrien	 false,			/* pc_relative */
51560484Sobrien	 0,			/* bitpos */
51660484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
51760484Sobrien	 bfd_elf_generic_reloc,	 /* special_function */
51860484Sobrien	 "R_PPC_RELATIVE",	/* name */
51960484Sobrien	 false,			/* partial_inplace */
52060484Sobrien	 0,			/* src_mask */
52160484Sobrien	 0xffffffff,		/* dst_mask */
52260484Sobrien	 false),		/* pcrel_offset */
52360484Sobrien
52460484Sobrien  /* Like R_PPC_REL24, but uses the value of the symbol within the
52560484Sobrien     object rather than the final value.  Normally used for
52660484Sobrien     _GLOBAL_OFFSET_TABLE_.  */
52760484Sobrien  HOWTO (R_PPC_LOCAL24PC,	/* type */
52860484Sobrien	 0,			/* rightshift */
52960484Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
53060484Sobrien	 26,			/* bitsize */
53160484Sobrien	 true,			/* pc_relative */
53260484Sobrien	 0,			/* bitpos */
53360484Sobrien	 complain_overflow_signed, /* complain_on_overflow */
53460484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
53560484Sobrien	 "R_PPC_LOCAL24PC",	/* name */
53660484Sobrien	 false,			/* partial_inplace */
53760484Sobrien	 0,			/* src_mask */
53860484Sobrien	 0x3fffffc,		/* dst_mask */
53960484Sobrien	 true),			/* pcrel_offset */
54060484Sobrien
54160484Sobrien  /* Like R_PPC_ADDR32, but may be unaligned.  */
54260484Sobrien  HOWTO (R_PPC_UADDR32,		/* type */
54360484Sobrien	 0,			/* rightshift */
54460484Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
54560484Sobrien	 32,			/* bitsize */
54660484Sobrien	 false,			/* pc_relative */
54760484Sobrien	 0,			/* bitpos */
54860484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
54960484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
55060484Sobrien	 "R_PPC_UADDR32",	/* name */
55160484Sobrien	 false,			/* partial_inplace */
55260484Sobrien	 0,			/* src_mask */
55360484Sobrien	 0xffffffff,		/* dst_mask */
55460484Sobrien	 false),		/* pcrel_offset */
55560484Sobrien
55660484Sobrien  /* Like R_PPC_ADDR16, but may be unaligned.  */
55760484Sobrien  HOWTO (R_PPC_UADDR16,		/* type */
55860484Sobrien	 0,			/* rightshift */
55960484Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
56060484Sobrien	 16,			/* bitsize */
56160484Sobrien	 false,			/* pc_relative */
56260484Sobrien	 0,			/* bitpos */
56360484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
56460484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
56560484Sobrien	 "R_PPC_UADDR16",	/* name */
56660484Sobrien	 false,			/* partial_inplace */
56760484Sobrien	 0,			/* src_mask */
56860484Sobrien	 0xffff,		/* dst_mask */
56960484Sobrien	 false),		/* pcrel_offset */
57060484Sobrien
57160484Sobrien  /* 32-bit PC relative */
57260484Sobrien  HOWTO (R_PPC_REL32,		/* type */
57360484Sobrien	 0,			/* rightshift */
57460484Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
57560484Sobrien	 32,			/* bitsize */
57660484Sobrien	 true,			/* pc_relative */
57760484Sobrien	 0,			/* bitpos */
57860484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
57960484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
58060484Sobrien	 "R_PPC_REL32",		/* name */
58160484Sobrien	 false,			/* partial_inplace */
58260484Sobrien	 0,			/* src_mask */
58360484Sobrien	 0xffffffff,		/* dst_mask */
58460484Sobrien	 true),			/* pcrel_offset */
58560484Sobrien
58660484Sobrien  /* 32-bit relocation to the symbol's procedure linkage table.
58777298Sobrien     FIXME: not supported.  */
58860484Sobrien  HOWTO (R_PPC_PLT32,		/* type */
58960484Sobrien	 0,			/* rightshift */
59060484Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
59160484Sobrien	 32,			/* bitsize */
59260484Sobrien	 false,			/* pc_relative */
59360484Sobrien	 0,			/* bitpos */
59460484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
59560484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
59660484Sobrien	 "R_PPC_PLT32",		/* name */
59760484Sobrien	 false,			/* partial_inplace */
59860484Sobrien	 0,			/* src_mask */
59960484Sobrien	 0,			/* dst_mask */
60060484Sobrien	 false),		/* pcrel_offset */
60160484Sobrien
60260484Sobrien  /* 32-bit PC relative relocation to the symbol's procedure linkage table.
60377298Sobrien     FIXME: not supported.  */
60460484Sobrien  HOWTO (R_PPC_PLTREL32,	/* type */
60560484Sobrien	 0,			/* rightshift */
60660484Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
60760484Sobrien	 32,			/* bitsize */
60860484Sobrien	 true,			/* pc_relative */
60960484Sobrien	 0,			/* bitpos */
61060484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
61160484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
61260484Sobrien	 "R_PPC_PLTREL32",	/* name */
61360484Sobrien	 false,			/* partial_inplace */
61460484Sobrien	 0,			/* src_mask */
61560484Sobrien	 0,			/* dst_mask */
61660484Sobrien	 true),			/* pcrel_offset */
61760484Sobrien
61860484Sobrien  /* Like R_PPC_ADDR16_LO, but referring to the PLT table entry for
61960484Sobrien     the symbol.  */
62060484Sobrien  HOWTO (R_PPC_PLT16_LO,	/* type */
62160484Sobrien	 0,			/* rightshift */
62260484Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
62360484Sobrien	 16,			/* bitsize */
62460484Sobrien	 false,			/* pc_relative */
62560484Sobrien	 0,			/* bitpos */
62660484Sobrien	 complain_overflow_dont, /* complain_on_overflow */
62760484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
62860484Sobrien	 "R_PPC_PLT16_LO",	/* name */
62960484Sobrien	 false,			/* partial_inplace */
63060484Sobrien	 0,			/* src_mask */
63160484Sobrien	 0xffff,		/* dst_mask */
63260484Sobrien	 false),		/* pcrel_offset */
63360484Sobrien
63460484Sobrien  /* Like R_PPC_ADDR16_HI, but referring to the PLT table entry for
63560484Sobrien     the symbol.  */
63660484Sobrien  HOWTO (R_PPC_PLT16_HI,	/* type */
63760484Sobrien	 16,			/* rightshift */
63860484Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
63960484Sobrien	 16,			/* bitsize */
64060484Sobrien	 false,			/* pc_relative */
64160484Sobrien	 0,			/* bitpos */
64260484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
64360484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
64460484Sobrien	 "R_PPC_PLT16_HI",	/* name */
64560484Sobrien	 false,			/* partial_inplace */
64660484Sobrien	 0,			/* src_mask */
64760484Sobrien	 0xffff,		/* dst_mask */
64860484Sobrien	 false),		 /* pcrel_offset */
64960484Sobrien
65060484Sobrien  /* Like R_PPC_ADDR16_HA, but referring to the PLT table entry for
65160484Sobrien     the symbol.  */
65260484Sobrien  HOWTO (R_PPC_PLT16_HA,	/* type */
65360484Sobrien	 16,			/* rightshift */
65460484Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
65560484Sobrien	 16,			/* bitsize */
65660484Sobrien	 false,			/* pc_relative */
65760484Sobrien	 0,			/* bitpos */
65860484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
65960484Sobrien	 ppc_elf_addr16_ha_reloc, /* special_function */
66060484Sobrien	 "R_PPC_PLT16_HA",	/* name */
66160484Sobrien	 false,			/* partial_inplace */
66260484Sobrien	 0,			/* src_mask */
66360484Sobrien	 0xffff,		/* dst_mask */
66460484Sobrien	 false),		/* pcrel_offset */
66560484Sobrien
66660484Sobrien  /* A sign-extended 16 bit value relative to _SDA_BASE_, for use with
66760484Sobrien     small data items.  */
66860484Sobrien  HOWTO (R_PPC_SDAREL16,	/* type */
66960484Sobrien	 0,			/* rightshift */
67060484Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
67160484Sobrien	 16,			/* bitsize */
67260484Sobrien	 false,			/* pc_relative */
67360484Sobrien	 0,			/* bitpos */
67460484Sobrien	 complain_overflow_signed, /* complain_on_overflow */
67560484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
67660484Sobrien	 "R_PPC_SDAREL16",	/* name */
67760484Sobrien	 false,			/* partial_inplace */
67860484Sobrien	 0,			/* src_mask */
67960484Sobrien	 0xffff,		/* dst_mask */
68060484Sobrien	 false),		/* pcrel_offset */
68160484Sobrien
68277298Sobrien  /* 32-bit section relative relocation.  */
68360484Sobrien  HOWTO (R_PPC_SECTOFF,		/* type */
68460484Sobrien	 0,			/* rightshift */
68560484Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
68660484Sobrien	 32,			/* bitsize */
68760484Sobrien	 true,			/* pc_relative */
68860484Sobrien	 0,			/* bitpos */
68960484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
69060484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
69160484Sobrien	 "R_PPC_SECTOFF",	/* name */
69260484Sobrien	 false,			/* partial_inplace */
69360484Sobrien	 0,			/* src_mask */
69460484Sobrien	 0,			/* dst_mask */
69560484Sobrien	 true),			/* pcrel_offset */
69660484Sobrien
69777298Sobrien  /* 16-bit lower half section relative relocation.  */
69860484Sobrien  HOWTO (R_PPC_SECTOFF_LO,	  /* type */
69960484Sobrien	 0,			/* rightshift */
70060484Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
70160484Sobrien	 16,			/* bitsize */
70260484Sobrien	 false,			/* pc_relative */
70360484Sobrien	 0,			/* bitpos */
70460484Sobrien	 complain_overflow_dont, /* complain_on_overflow */
70560484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
70660484Sobrien	 "R_PPC_SECTOFF_LO",	/* name */
70760484Sobrien	 false,			/* partial_inplace */
70860484Sobrien	 0,			/* src_mask */
70960484Sobrien	 0xffff,		/* dst_mask */
71060484Sobrien	 false),		/* pcrel_offset */
71160484Sobrien
71277298Sobrien  /* 16-bit upper half section relative relocation.  */
71360484Sobrien  HOWTO (R_PPC_SECTOFF_HI,	/* type */
71460484Sobrien	 16,			/* rightshift */
71560484Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
71660484Sobrien	 16,			/* bitsize */
71760484Sobrien	 false,			/* pc_relative */
71860484Sobrien	 0,			/* bitpos */
71960484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
72060484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
72160484Sobrien	 "R_PPC_SECTOFF_HI",	/* name */
72260484Sobrien	 false,			/* partial_inplace */
72360484Sobrien	 0,			/* src_mask */
72460484Sobrien	 0xffff,		/* dst_mask */
72560484Sobrien	 false),		 /* pcrel_offset */
72660484Sobrien
72777298Sobrien  /* 16-bit upper half adjusted section relative relocation.  */
72860484Sobrien  HOWTO (R_PPC_SECTOFF_HA,	/* type */
72960484Sobrien	 16,			/* rightshift */
73060484Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
73160484Sobrien	 16,			/* bitsize */
73260484Sobrien	 false,			/* pc_relative */
73360484Sobrien	 0,			/* bitpos */
73460484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
73560484Sobrien	 ppc_elf_addr16_ha_reloc, /* special_function */
73660484Sobrien	 "R_PPC_SECTOFF_HA",	/* name */
73760484Sobrien	 false,			/* partial_inplace */
73860484Sobrien	 0,			/* src_mask */
73960484Sobrien	 0xffff,		/* dst_mask */
74060484Sobrien	 false),		/* pcrel_offset */
74160484Sobrien
74260484Sobrien  /* The remaining relocs are from the Embedded ELF ABI, and are not
74360484Sobrien     in the SVR4 ELF ABI.  */
74460484Sobrien
74560484Sobrien  /* 32 bit value resulting from the addend minus the symbol */
74660484Sobrien  HOWTO (R_PPC_EMB_NADDR32,	/* type */
74760484Sobrien	 0,			/* rightshift */
74860484Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
74960484Sobrien	 32,			/* bitsize */
75060484Sobrien	 false,			/* pc_relative */
75160484Sobrien	 0,			/* bitpos */
75260484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
75360484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
75460484Sobrien	 "R_PPC_EMB_NADDR32",	/* name */
75560484Sobrien	 false,			/* partial_inplace */
75660484Sobrien	 0,			/* src_mask */
75760484Sobrien	 0xffffffff,		/* dst_mask */
75860484Sobrien	 false),		/* pcrel_offset */
75960484Sobrien
76060484Sobrien  /* 16 bit value resulting from the addend minus the symbol */
76160484Sobrien  HOWTO (R_PPC_EMB_NADDR16,	/* type */
76260484Sobrien	 0,			/* rightshift */
76360484Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
76460484Sobrien	 16,			/* bitsize */
76560484Sobrien	 false,			/* pc_relative */
76660484Sobrien	 0,			/* bitpos */
76760484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
76860484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
76960484Sobrien	 "R_PPC_EMB_NADDR16",	/* name */
77060484Sobrien	 false,			/* partial_inplace */
77160484Sobrien	 0,			/* src_mask */
77260484Sobrien	 0xffff,		/* dst_mask */
77360484Sobrien	 false),		/* pcrel_offset */
77460484Sobrien
77560484Sobrien  /* 16 bit value resulting from the addend minus the symbol */
77660484Sobrien  HOWTO (R_PPC_EMB_NADDR16_LO,	/* type */
77760484Sobrien	 0,			/* rightshift */
77860484Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
77960484Sobrien	 16,			/* bitsize */
78060484Sobrien	 false,			/* pc_relative */
78160484Sobrien	 0,			/* bitpos */
78260484Sobrien	 complain_overflow_dont,/* complain_on_overflow */
78360484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
78460484Sobrien	 "R_PPC_EMB_ADDR16_LO",	/* name */
78560484Sobrien	 false,			/* partial_inplace */
78660484Sobrien	 0,			/* src_mask */
78760484Sobrien	 0xffff,		/* dst_mask */
78860484Sobrien	 false),		/* pcrel_offset */
78960484Sobrien
79060484Sobrien  /* The high order 16 bits of the addend minus the symbol */
79160484Sobrien  HOWTO (R_PPC_EMB_NADDR16_HI,	/* type */
79260484Sobrien	 16,			/* rightshift */
79360484Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
79460484Sobrien	 16,			/* bitsize */
79560484Sobrien	 false,			/* pc_relative */
79660484Sobrien	 0,			/* bitpos */
79760484Sobrien	 complain_overflow_dont, /* complain_on_overflow */
79860484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
79960484Sobrien	 "R_PPC_EMB_NADDR16_HI", /* name */
80060484Sobrien	 false,			/* partial_inplace */
80160484Sobrien	 0,			/* src_mask */
80260484Sobrien	 0xffff,		/* dst_mask */
80360484Sobrien	 false),		/* pcrel_offset */
80460484Sobrien
80560484Sobrien  /* The high order 16 bits of the result of the addend minus the address,
80660484Sobrien     plus 1 if the contents of the low 16 bits, treated as a signed number,
80760484Sobrien     is negative.  */
80860484Sobrien  HOWTO (R_PPC_EMB_NADDR16_HA,	/* type */
80960484Sobrien	 16,			/* rightshift */
81060484Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
81160484Sobrien	 16,			/* bitsize */
81260484Sobrien	 false,			/* pc_relative */
81360484Sobrien	 0,			/* bitpos */
81460484Sobrien	 complain_overflow_dont, /* complain_on_overflow */
81560484Sobrien	 ppc_elf_addr16_ha_reloc, /* special_function */
81660484Sobrien	 "R_PPC_EMB_NADDR16_HA", /* name */
81760484Sobrien	 false,			/* partial_inplace */
81860484Sobrien	 0,			/* src_mask */
81960484Sobrien	 0xffff,		/* dst_mask */
82060484Sobrien	 false),		/* pcrel_offset */
82160484Sobrien
82260484Sobrien  /* 16 bit value resulting from allocating a 4 byte word to hold an
82360484Sobrien     address in the .sdata section, and returning the offset from
82460484Sobrien     _SDA_BASE_ for that relocation */
82560484Sobrien  HOWTO (R_PPC_EMB_SDAI16,	/* type */
82660484Sobrien	 0,			/* rightshift */
82760484Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
82860484Sobrien	 16,			/* bitsize */
82960484Sobrien	 false,			/* pc_relative */
83060484Sobrien	 0,			/* bitpos */
83160484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
83260484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
83360484Sobrien	 "R_PPC_EMB_SDAI16",	/* name */
83460484Sobrien	 false,			/* partial_inplace */
83560484Sobrien	 0,			/* src_mask */
83660484Sobrien	 0xffff,		/* dst_mask */
83760484Sobrien	 false),		/* pcrel_offset */
83860484Sobrien
83960484Sobrien  /* 16 bit value resulting from allocating a 4 byte word to hold an
84060484Sobrien     address in the .sdata2 section, and returning the offset from
84160484Sobrien     _SDA2_BASE_ for that relocation */
84260484Sobrien  HOWTO (R_PPC_EMB_SDA2I16,	/* type */
84360484Sobrien	 0,			/* rightshift */
84460484Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
84560484Sobrien	 16,			/* bitsize */
84660484Sobrien	 false,			/* pc_relative */
84760484Sobrien	 0,			/* bitpos */
84860484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
84960484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
85060484Sobrien	 "R_PPC_EMB_SDA2I16",	/* name */
85160484Sobrien	 false,			/* partial_inplace */
85260484Sobrien	 0,			/* src_mask */
85360484Sobrien	 0xffff,		/* dst_mask */
85460484Sobrien	 false),		/* pcrel_offset */
85560484Sobrien
85660484Sobrien  /* A sign-extended 16 bit value relative to _SDA2_BASE_, for use with
85760484Sobrien     small data items.	 */
85860484Sobrien  HOWTO (R_PPC_EMB_SDA2REL,	/* type */
85960484Sobrien	 0,			/* rightshift */
86060484Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
86160484Sobrien	 16,			/* bitsize */
86260484Sobrien	 false,			/* pc_relative */
86360484Sobrien	 0,			/* bitpos */
86460484Sobrien	 complain_overflow_signed, /* complain_on_overflow */
86560484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
86660484Sobrien	 "R_PPC_EMB_SDA2REL",	/* name */
86760484Sobrien	 false,			/* partial_inplace */
86860484Sobrien	 0,			/* src_mask */
86960484Sobrien	 0xffff,		/* dst_mask */
87060484Sobrien	 false),		/* pcrel_offset */
87160484Sobrien
87260484Sobrien  /* Relocate against either _SDA_BASE_ or _SDA2_BASE_, filling in the 16 bit
87360484Sobrien     signed offset from the appropriate base, and filling in the register
87460484Sobrien     field with the appropriate register (0, 2, or 13).  */
87560484Sobrien  HOWTO (R_PPC_EMB_SDA21,	/* type */
87660484Sobrien	 0,			/* rightshift */
87760484Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
87860484Sobrien	 16,			/* bitsize */
87960484Sobrien	 false,			/* pc_relative */
88060484Sobrien	 0,			/* bitpos */
88160484Sobrien	 complain_overflow_signed, /* complain_on_overflow */
88260484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
88360484Sobrien	 "R_PPC_EMB_SDA21",	/* name */
88460484Sobrien	 false,			/* partial_inplace */
88560484Sobrien	 0,			/* src_mask */
88660484Sobrien	 0xffff,		/* dst_mask */
88760484Sobrien	 false),		/* pcrel_offset */
88860484Sobrien
88960484Sobrien  /* Relocation not handled: R_PPC_EMB_MRKREF */
89060484Sobrien  /* Relocation not handled: R_PPC_EMB_RELSEC16 */
89160484Sobrien  /* Relocation not handled: R_PPC_EMB_RELST_LO */
89260484Sobrien  /* Relocation not handled: R_PPC_EMB_RELST_HI */
89360484Sobrien  /* Relocation not handled: R_PPC_EMB_RELST_HA */
89460484Sobrien  /* Relocation not handled: R_PPC_EMB_BIT_FLD */
89560484Sobrien
89660484Sobrien  /* PC relative relocation against either _SDA_BASE_ or _SDA2_BASE_, filling
89760484Sobrien     in the 16 bit signed offset from the appropriate base, and filling in the
89860484Sobrien     register field with the appropriate register (0, 2, or 13).  */
89960484Sobrien  HOWTO (R_PPC_EMB_RELSDA,	/* type */
90060484Sobrien	 0,			/* rightshift */
90160484Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
90260484Sobrien	 16,			/* bitsize */
90360484Sobrien	 true,			/* pc_relative */
90460484Sobrien	 0,			/* bitpos */
90560484Sobrien	 complain_overflow_signed, /* complain_on_overflow */
90660484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
90760484Sobrien	 "R_PPC_EMB_RELSDA",	/* name */
90860484Sobrien	 false,			/* partial_inplace */
90960484Sobrien	 0,			/* src_mask */
91060484Sobrien	 0xffff,		/* dst_mask */
91160484Sobrien	 false),		/* pcrel_offset */
91260484Sobrien
91360484Sobrien  /* GNU extension to record C++ vtable hierarchy */
91460484Sobrien  HOWTO (R_PPC_GNU_VTINHERIT,	/* type */
91560484Sobrien	 0,			/* rightshift */
91660484Sobrien	 0,			/* size (0 = byte, 1 = short, 2 = long) */
91760484Sobrien	 0,			/* bitsize */
91860484Sobrien	 false,			/* pc_relative */
91960484Sobrien	 0,			/* bitpos */
92060484Sobrien	 complain_overflow_dont, /* complain_on_overflow */
92160484Sobrien	 NULL,			/* special_function */
92260484Sobrien	 "R_PPC_GNU_VTINHERIT",	/* name */
92360484Sobrien	 false,			/* partial_inplace */
92460484Sobrien	 0,			/* src_mask */
92560484Sobrien	 0,			/* dst_mask */
92660484Sobrien	 false),		/* pcrel_offset */
92760484Sobrien
92860484Sobrien  /* GNU extension to record C++ vtable member usage */
92960484Sobrien  HOWTO (R_PPC_GNU_VTENTRY,	/* type */
93060484Sobrien	 0,			/* rightshift */
93160484Sobrien	 0,			/* size (0 = byte, 1 = short, 2 = long) */
93260484Sobrien	 0,			/* bitsize */
93360484Sobrien	 false,			/* pc_relative */
93460484Sobrien	 0,			/* bitpos */
93560484Sobrien	 complain_overflow_dont, /* complain_on_overflow */
93660484Sobrien	 NULL,			/* special_function */
93760484Sobrien	 "R_PPC_GNU_VTENTRY",	/* name */
93860484Sobrien	 false,			/* partial_inplace */
93960484Sobrien	 0,			/* src_mask */
94060484Sobrien	 0,			/* dst_mask */
94160484Sobrien	 false),		/* pcrel_offset */
94260484Sobrien
94360484Sobrien  /* Phony reloc to handle AIX style TOC entries */
94460484Sobrien  HOWTO (R_PPC_TOC16,		/* type */
94560484Sobrien	 0,			/* rightshift */
94660484Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
94760484Sobrien	 16,			/* bitsize */
94860484Sobrien	 false,			/* pc_relative */
94960484Sobrien	 0,			/* bitpos */
95060484Sobrien	 complain_overflow_signed, /* complain_on_overflow */
95160484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
95260484Sobrien	 "R_PPC_TOC16",		/* name */
95360484Sobrien	 false,			/* partial_inplace */
95460484Sobrien	 0,			/* src_mask */
95560484Sobrien	 0xffff,		/* dst_mask */
95660484Sobrien	 false),		/* pcrel_offset */
95760484Sobrien};
95860484Sobrien
95960484Sobrien/* Initialize the ppc_elf_howto_table, so that linear accesses can be done.  */
96060484Sobrien
96160484Sobrienstatic void
96260484Sobrienppc_elf_howto_init ()
96360484Sobrien{
96460484Sobrien  unsigned int i, type;
96560484Sobrien
96660484Sobrien  for (i = 0; i < sizeof (ppc_elf_howto_raw) / sizeof (ppc_elf_howto_raw[0]); i++)
96760484Sobrien    {
96860484Sobrien      type = ppc_elf_howto_raw[i].type;
96977298Sobrien      BFD_ASSERT (type < sizeof (ppc_elf_howto_table) / sizeof (ppc_elf_howto_table[0]));
97060484Sobrien      ppc_elf_howto_table[type] = &ppc_elf_howto_raw[i];
97160484Sobrien    }
97260484Sobrien}
97360484Sobrien
97460484Sobrien/* This function handles relaxing for the PPC with option --mpc860c0[=<n>].
97560484Sobrien
97660484Sobrien   The MPC860, revision C0 or earlier contains a bug in the die.
97760484Sobrien   If all of the following conditions are true, the next instruction
97860484Sobrien   to be executed *may* be treated as a no-op.
97960484Sobrien   1/ A forward branch is executed.
98060484Sobrien   2/ The branch is predicted as not taken.
98160484Sobrien   3/ The branch is taken.
98260484Sobrien   4/ The branch is located in the last 5 words of a page.
98360484Sobrien      (The EOP limit is 5 by default but may be specified as any value from 1-10.)
98477298Sobrien
98560484Sobrien   Our software solution is to detect these problematic branches in a
98660484Sobrien   linker pass and modify them as follows:
98760484Sobrien   1/ Unconditional branches - Since these are always predicted taken,
98860484Sobrien      there is no problem and no action is required.
98960484Sobrien   2/ Conditional backward branches - No problem, no action required.
99060484Sobrien   3/ Conditional forward branches - Ensure that the "inverse prediction
99160484Sobrien      bit" is set (ensure it is predicted taken).
99260484Sobrien   4/ Conditional register branches - Ensure that the "y bit" is set
99360484Sobrien      (ensure it is predicted taken).
99460484Sobrien*/
99560484Sobrien
99660484Sobrien/* Sort sections by address.  */
99760484Sobrien
99860484Sobrienstatic int
99960484Sobrienppc_elf_sort_rela (arg1, arg2)
100089857Sobrien     const PTR arg1;
100189857Sobrien     const PTR arg2;
100260484Sobrien{
100360484Sobrien  const Elf_Internal_Rela **rela1 = (const Elf_Internal_Rela**) arg1;
100460484Sobrien  const Elf_Internal_Rela **rela2 = (const Elf_Internal_Rela**) arg2;
100560484Sobrien
100677298Sobrien  /* Sort by offset.  */
100760484Sobrien  return ((*rela1)->r_offset - (*rela2)->r_offset);
100860484Sobrien}
100960484Sobrien
101060484Sobrienstatic boolean
101160484Sobrienppc_elf_relax_section (abfd, isec, link_info, again)
101277298Sobrien     bfd *abfd;
101377298Sobrien     asection *isec;
101477298Sobrien     struct bfd_link_info *link_info;
101577298Sobrien     boolean *again;
101660484Sobrien{
101760484Sobrien#define PAGESIZE 0x1000
101860484Sobrien
101960484Sobrien  bfd_byte *contents = NULL;
102060484Sobrien  bfd_byte *free_contents = NULL;
102160484Sobrien  Elf_Internal_Rela *internal_relocs = NULL;
102260484Sobrien  Elf_Internal_Rela *free_relocs = NULL;
102360484Sobrien  Elf_Internal_Rela **rela_comb = NULL;
102460484Sobrien  int comb_curr, comb_count;
102560484Sobrien
102677298Sobrien  /* We never have to do this more than once per input section.  */
102760484Sobrien  *again = false;
102860484Sobrien
102960484Sobrien  /* If needed, initialize this section's cooked size.  */
103060484Sobrien  if (isec->_cooked_size == 0)
103160484Sobrien      isec->_cooked_size = isec->_raw_size;
103260484Sobrien
103360484Sobrien  /* We're only interested in text sections which overlap the
103477298Sobrien     troublesome area at the end of a page.  */
103560484Sobrien  if (link_info->mpc860c0 && (isec->flags & SEC_CODE) && isec->_cooked_size)
103660484Sobrien    {
103760484Sobrien      bfd_vma dot, end_page, end_section;
103860484Sobrien      boolean section_modified;
103960484Sobrien
104077298Sobrien      /* Get the section contents.  */
104160484Sobrien      /* Get cached copy if it exists.  */
104260484Sobrien      if (elf_section_data (isec)->this_hdr.contents != NULL)
104360484Sobrien	  contents = elf_section_data (isec)->this_hdr.contents;
104460484Sobrien      else
104560484Sobrien	{
104660484Sobrien	  /* Go get them off disk.  */
104760484Sobrien	  contents = (bfd_byte *) bfd_malloc (isec->_raw_size);
104860484Sobrien	  if (contents == NULL)
104977298Sobrien	    goto error_return;
105060484Sobrien	  free_contents = contents;
105160484Sobrien
105260484Sobrien	  if (! bfd_get_section_contents (abfd, isec, contents,
105360484Sobrien					  (file_ptr) 0, isec->_raw_size))
105477298Sobrien	    goto error_return;
105560484Sobrien	}
105660484Sobrien
105760484Sobrien      comb_curr = 0;
105860484Sobrien      comb_count = 0;
105960484Sobrien      if (isec->reloc_count)
106077298Sobrien	{
106160484Sobrien          unsigned n;
106289857Sobrien	  bfd_size_type amt;
106360484Sobrien
106460484Sobrien          /* Get a copy of the native relocations.  */
106560484Sobrien          internal_relocs = _bfd_elf32_link_read_relocs (
106677298Sobrien    	    abfd, isec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
106760484Sobrien    	    link_info->keep_memory);
106860484Sobrien          if (internal_relocs == NULL)
106960484Sobrien    	      goto error_return;
107060484Sobrien          if (! link_info->keep_memory)
107160484Sobrien    	      free_relocs = internal_relocs;
107277298Sobrien
107377298Sobrien          /* Setup a faster access method for the reloc info we need.  */
107489857Sobrien	  amt = isec->reloc_count;
107589857Sobrien	  amt *= sizeof (Elf_Internal_Rela*);
107689857Sobrien          rela_comb = (Elf_Internal_Rela**) bfd_malloc (amt);
107760484Sobrien          if (rela_comb == NULL)
107860484Sobrien              goto error_return;
107977298Sobrien          for (n = 0; n < isec->reloc_count; ++n)
108060484Sobrien            {
108160484Sobrien              long r_type;
108277298Sobrien
108360484Sobrien              r_type = ELF32_R_TYPE (internal_relocs[n].r_info);
108477298Sobrien              if (r_type < 0 || r_type >= (int) R_PPC_max)
108560484Sobrien                  goto error_return;
108677298Sobrien
108760484Sobrien              /* Prologue constants are sometimes present in the ".text"
108860484Sobrien              sections and they can be identified by their associated relocation.
108960484Sobrien              We don't want to process those words and some others which
109060484Sobrien              can also be identified by their relocations.  However, not all
109160484Sobrien              conditional branches will have a relocation so we will
109260484Sobrien              only ignore words that 1) have a reloc, and 2) the reloc
109360484Sobrien              is not applicable to a conditional branch.
109477298Sobrien              The array rela_comb is built here for use in the EOP scan loop.  */
109560484Sobrien              switch (r_type)
109660484Sobrien                {
109760484Sobrien                case R_PPC_ADDR14_BRNTAKEN:     /* absolute, predicted not taken */
109877298Sobrien                case R_PPC_REL14:               /* relative cond. br.  */
109960484Sobrien                case R_PPC_REL14_BRNTAKEN:      /* rel. cond. br., predicted not taken */
110077298Sobrien                  /* We should check the instruction.  */
110160484Sobrien                  break;
110260484Sobrien                default:
110377298Sobrien                  /* The word is not a conditional branch - ignore it.  */
110460484Sobrien                  rela_comb[comb_count++] = &internal_relocs[n];
110560484Sobrien                  break;
110660484Sobrien                }
110760484Sobrien            }
110860484Sobrien          if (comb_count > 1)
110977298Sobrien	    qsort (rela_comb, (size_t) comb_count, sizeof (int), ppc_elf_sort_rela);
111077298Sobrien	}
111160484Sobrien
111277298Sobrien      /* Enumerate each EOP region that overlaps this section.  */
111360484Sobrien      end_section = isec->vma + isec->_cooked_size;
111460484Sobrien      dot = end_page = (isec->vma | (PAGESIZE - 1)) + 1;
111560484Sobrien      dot -= link_info->mpc860c0;
111660484Sobrien      section_modified = false;
111760484Sobrien      if (dot < isec->vma)      /* Increment the start position if this section */
111877298Sobrien          dot = isec->vma;      /* begins in the middle of its first EOP region.  */
111960484Sobrien      for (;
112060484Sobrien           dot < end_section;
112160484Sobrien           dot += PAGESIZE, end_page += PAGESIZE)
112260484Sobrien        {
112360484Sobrien
112477298Sobrien          /* Check each word in this EOP region.  */
112560484Sobrien          for (; dot < end_page; dot += 4)
112660484Sobrien            {
112760484Sobrien              bfd_vma isec_offset;
112860484Sobrien              unsigned long insn;
112960484Sobrien              boolean skip, modified;
113060484Sobrien
113160484Sobrien              /* Don't process this word if there is a relocation for it and
113277298Sobrien              the relocation indicates the word is not a conditional branch.  */
113360484Sobrien              skip = false;
113460484Sobrien              isec_offset = dot - isec->vma;
113560484Sobrien              for (; comb_curr<comb_count; ++comb_curr)
113660484Sobrien                {
113760484Sobrien                  bfd_vma r_offset;
113860484Sobrien
113960484Sobrien                  r_offset = rela_comb[comb_curr]->r_offset;
114060484Sobrien                  if (r_offset >= isec_offset)
114160484Sobrien                    {
114260484Sobrien                      if (r_offset == isec_offset) skip = true;
114360484Sobrien                      break;
114460484Sobrien                    }
114560484Sobrien                }
114660484Sobrien              if (skip) continue;
114760484Sobrien
114877298Sobrien              /* Check the current word for a problematic conditional branch.  */
114960484Sobrien#define BO0(insn) ((insn) & 0x02000000)
115060484Sobrien#define BO2(insn) ((insn) & 0x00800000)
115160484Sobrien#define BO4(insn) ((insn) & 0x00200000)
115260484Sobrien              insn = (unsigned long) bfd_get_32 (abfd, contents + isec_offset);
115360484Sobrien              modified = false;
115460484Sobrien              if ((insn & 0xFc000000) == 0x40000000)
115560484Sobrien                {
115660484Sobrien                  /* Instruction is BCx */
115760484Sobrien                  if ((!BO0(insn) || !BO2(insn)) && !BO4(insn))
115860484Sobrien                    {
115960484Sobrien                      bfd_vma target;
116060484Sobrien                      /* This branch is predicted as "normal".
116177298Sobrien                      If this is a forward branch, it is problematic.  */
116260484Sobrien
116360484Sobrien                      target = insn & 0x0000Fffc;               /*extract*/
116460484Sobrien                      target = (target ^ 0x8000) - 0x8000;      /*sign extend*/
116560484Sobrien                      if ((insn & 0x00000002) == 0)
116660484Sobrien                          target += dot;                        /*convert to abs*/
116760484Sobrien                      if (target > dot)
116860484Sobrien                        {
116960484Sobrien                          insn |= 0x00200000;   /* set the prediction bit */
117060484Sobrien                          modified = true;
117160484Sobrien                        }
117260484Sobrien                    }
117360484Sobrien                }
117460484Sobrien              else if ((insn & 0xFc00Fffe) == 0x4c000420)
117560484Sobrien                {
117660484Sobrien                  /* Instruction is BCCTRx */
117760484Sobrien                  if ((!BO0(insn) || !BO2(insn)) && !BO4(insn))
117860484Sobrien		    {
117960484Sobrien		      /* This branch is predicted as not-taken.
118060484Sobrien		      If this is a forward branch, it is problematic.
118160484Sobrien                      Since we can't tell statically if it will branch forward,
118277298Sobrien                      always set the prediction bit.  */
118360484Sobrien                      insn |= 0x00200000;   /* set the prediction bit */
118460484Sobrien                      modified = true;
118560484Sobrien		    }
118660484Sobrien                }
118760484Sobrien              else if ((insn & 0xFc00Fffe) == 0x4c000020)
118860484Sobrien                {
118960484Sobrien                  /* Instruction is BCLRx */
119060484Sobrien                  if ((!BO0(insn) || !BO2(insn)) && !BO4(insn))
119160484Sobrien		    {
119260484Sobrien		      /* This branch is predicted as not-taken.
119360484Sobrien		      If this is a forward branch, it is problematic.
119460484Sobrien                      Since we can't tell statically if it will branch forward,
119577298Sobrien                      always set the prediction bit.  */
119660484Sobrien                      insn |= 0x00200000;   /* set the prediction bit */
119760484Sobrien                      modified = true;
119860484Sobrien		    }
119960484Sobrien                }
120060484Sobrien#undef BO0
120160484Sobrien#undef BO2
120260484Sobrien#undef BO4
120360484Sobrien              if (modified)
120460484Sobrien	        {
120589857Sobrien                  bfd_put_32 (abfd, (bfd_vma) insn, contents + isec_offset);
120660484Sobrien		  section_modified = true;
120760484Sobrien	        }
120860484Sobrien            }
120960484Sobrien        }
121060484Sobrien      if (section_modified)
121160484Sobrien	{
121260484Sobrien	  elf_section_data (isec)->this_hdr.contents = contents;
121360484Sobrien	  free_contents = NULL;
121460484Sobrien	}
121560484Sobrien    }
121660484Sobrien
121760484Sobrien  if (rela_comb != NULL)
121860484Sobrien    {
121960484Sobrien      free (rela_comb);
122060484Sobrien      rela_comb = NULL;
122160484Sobrien    }
122260484Sobrien
122360484Sobrien  if (free_relocs != NULL)
122460484Sobrien    {
122560484Sobrien      free (free_relocs);
122660484Sobrien      free_relocs = NULL;
122760484Sobrien    }
122860484Sobrien
122960484Sobrien  if (free_contents != NULL)
123060484Sobrien    {
123160484Sobrien      if (! link_info->keep_memory)
123260484Sobrien	free (free_contents);
123360484Sobrien      else
123460484Sobrien	{
123560484Sobrien	  /* Cache the section contents for elf_link_input_bfd.  */
123660484Sobrien	  elf_section_data (isec)->this_hdr.contents = contents;
123760484Sobrien	}
123860484Sobrien      free_contents = NULL;
123960484Sobrien    }
124060484Sobrien
124160484Sobrien  return true;
124260484Sobrien
124360484Sobrienerror_return:
124460484Sobrien  if (rela_comb != NULL)
124560484Sobrien    free (rela_comb);
124660484Sobrien  if (free_relocs != NULL)
124760484Sobrien    free (free_relocs);
124860484Sobrien  if (free_contents != NULL)
124960484Sobrien    free (free_contents);
125060484Sobrien  return false;
125160484Sobrien}
125260484Sobrien
125360484Sobrienstatic reloc_howto_type *
125460484Sobrienppc_elf_reloc_type_lookup (abfd, code)
125560484Sobrien     bfd *abfd ATTRIBUTE_UNUSED;
125660484Sobrien     bfd_reloc_code_real_type code;
125760484Sobrien{
125860484Sobrien  enum elf_ppc_reloc_type ppc_reloc = R_PPC_NONE;
125960484Sobrien
126060484Sobrien  if (!ppc_elf_howto_table[R_PPC_ADDR32])
126177298Sobrien    /* Initialize howto table if needed.  */
126260484Sobrien    ppc_elf_howto_init ();
126360484Sobrien
126477298Sobrien  switch ((int) code)
126560484Sobrien    {
126660484Sobrien    default:
126777298Sobrien      return (reloc_howto_type *) NULL;
126860484Sobrien
126960484Sobrien    case BFD_RELOC_NONE:		ppc_reloc = R_PPC_NONE;			break;
127060484Sobrien    case BFD_RELOC_32:			ppc_reloc = R_PPC_ADDR32;		break;
127160484Sobrien    case BFD_RELOC_PPC_BA26:		ppc_reloc = R_PPC_ADDR24;		break;
127260484Sobrien    case BFD_RELOC_16:			ppc_reloc = R_PPC_ADDR16;		break;
127360484Sobrien    case BFD_RELOC_LO16:		ppc_reloc = R_PPC_ADDR16_LO;		break;
127460484Sobrien    case BFD_RELOC_HI16:		ppc_reloc = R_PPC_ADDR16_HI;		break;
127560484Sobrien    case BFD_RELOC_HI16_S:		ppc_reloc = R_PPC_ADDR16_HA;		break;
127660484Sobrien    case BFD_RELOC_PPC_BA16:		ppc_reloc = R_PPC_ADDR14;		break;
127760484Sobrien    case BFD_RELOC_PPC_BA16_BRTAKEN:	ppc_reloc = R_PPC_ADDR14_BRTAKEN;	break;
127860484Sobrien    case BFD_RELOC_PPC_BA16_BRNTAKEN:	ppc_reloc = R_PPC_ADDR14_BRNTAKEN;	break;
127960484Sobrien    case BFD_RELOC_PPC_B26:		ppc_reloc = R_PPC_REL24;		break;
128060484Sobrien    case BFD_RELOC_PPC_B16:		ppc_reloc = R_PPC_REL14;		break;
128160484Sobrien    case BFD_RELOC_PPC_B16_BRTAKEN:	ppc_reloc = R_PPC_REL14_BRTAKEN;	break;
128260484Sobrien    case BFD_RELOC_PPC_B16_BRNTAKEN:	ppc_reloc = R_PPC_REL14_BRNTAKEN;	break;
128360484Sobrien    case BFD_RELOC_16_GOTOFF:		ppc_reloc = R_PPC_GOT16;		break;
128460484Sobrien    case BFD_RELOC_LO16_GOTOFF:		ppc_reloc = R_PPC_GOT16_LO;		break;
128560484Sobrien    case BFD_RELOC_HI16_GOTOFF:		ppc_reloc = R_PPC_GOT16_HI;		break;
128660484Sobrien    case BFD_RELOC_HI16_S_GOTOFF:	ppc_reloc = R_PPC_GOT16_HA;		break;
128760484Sobrien    case BFD_RELOC_24_PLT_PCREL:	ppc_reloc = R_PPC_PLTREL24;		break;
128860484Sobrien    case BFD_RELOC_PPC_COPY:		ppc_reloc = R_PPC_COPY;			break;
128960484Sobrien    case BFD_RELOC_PPC_GLOB_DAT:	ppc_reloc = R_PPC_GLOB_DAT;		break;
129060484Sobrien    case BFD_RELOC_PPC_LOCAL24PC:	ppc_reloc = R_PPC_LOCAL24PC;		break;
129160484Sobrien    case BFD_RELOC_32_PCREL:		ppc_reloc = R_PPC_REL32;		break;
129260484Sobrien    case BFD_RELOC_32_PLTOFF:		ppc_reloc = R_PPC_PLT32;		break;
129360484Sobrien    case BFD_RELOC_32_PLT_PCREL:	ppc_reloc = R_PPC_PLTREL32;		break;
129460484Sobrien    case BFD_RELOC_LO16_PLTOFF:		ppc_reloc = R_PPC_PLT16_LO;		break;
129560484Sobrien    case BFD_RELOC_HI16_PLTOFF:		ppc_reloc = R_PPC_PLT16_HI;		break;
129660484Sobrien    case BFD_RELOC_HI16_S_PLTOFF:	ppc_reloc = R_PPC_PLT16_HA;		break;
129760484Sobrien    case BFD_RELOC_GPREL16:		ppc_reloc = R_PPC_SDAREL16;		break;
129860484Sobrien    case BFD_RELOC_32_BASEREL:		ppc_reloc = R_PPC_SECTOFF;		break;
129960484Sobrien    case BFD_RELOC_LO16_BASEREL:	ppc_reloc = R_PPC_SECTOFF_LO;		break;
130060484Sobrien    case BFD_RELOC_HI16_BASEREL:	ppc_reloc = R_PPC_SECTOFF_HI;		break;
130160484Sobrien    case BFD_RELOC_HI16_S_BASEREL:	ppc_reloc = R_PPC_SECTOFF_HA;		break;
130260484Sobrien    case BFD_RELOC_CTOR:		ppc_reloc = R_PPC_ADDR32;		break;
130360484Sobrien    case BFD_RELOC_PPC_TOC16:		ppc_reloc = R_PPC_TOC16;		break;
130460484Sobrien    case BFD_RELOC_PPC_EMB_NADDR32:	ppc_reloc = R_PPC_EMB_NADDR32;		break;
130560484Sobrien    case BFD_RELOC_PPC_EMB_NADDR16:	ppc_reloc = R_PPC_EMB_NADDR16;		break;
130660484Sobrien    case BFD_RELOC_PPC_EMB_NADDR16_LO:	ppc_reloc = R_PPC_EMB_NADDR16_LO;	break;
130760484Sobrien    case BFD_RELOC_PPC_EMB_NADDR16_HI:	ppc_reloc = R_PPC_EMB_NADDR16_HI;	break;
130860484Sobrien    case BFD_RELOC_PPC_EMB_NADDR16_HA:	ppc_reloc = R_PPC_EMB_NADDR16_HA;	break;
130960484Sobrien    case BFD_RELOC_PPC_EMB_SDAI16:	ppc_reloc = R_PPC_EMB_SDAI16;		break;
131060484Sobrien    case BFD_RELOC_PPC_EMB_SDA2I16:	ppc_reloc = R_PPC_EMB_SDA2I16;		break;
131160484Sobrien    case BFD_RELOC_PPC_EMB_SDA2REL:	ppc_reloc = R_PPC_EMB_SDA2REL;		break;
131260484Sobrien    case BFD_RELOC_PPC_EMB_SDA21:	ppc_reloc = R_PPC_EMB_SDA21;		break;
131360484Sobrien    case BFD_RELOC_PPC_EMB_MRKREF:	ppc_reloc = R_PPC_EMB_MRKREF;		break;
131460484Sobrien    case BFD_RELOC_PPC_EMB_RELSEC16:	ppc_reloc = R_PPC_EMB_RELSEC16;		break;
131560484Sobrien    case BFD_RELOC_PPC_EMB_RELST_LO:	ppc_reloc = R_PPC_EMB_RELST_LO;		break;
131660484Sobrien    case BFD_RELOC_PPC_EMB_RELST_HI:	ppc_reloc = R_PPC_EMB_RELST_HI;		break;
131760484Sobrien    case BFD_RELOC_PPC_EMB_RELST_HA:	ppc_reloc = R_PPC_EMB_RELST_HA;		break;
131860484Sobrien    case BFD_RELOC_PPC_EMB_BIT_FLD:	ppc_reloc = R_PPC_EMB_BIT_FLD;		break;
131960484Sobrien    case BFD_RELOC_PPC_EMB_RELSDA:	ppc_reloc = R_PPC_EMB_RELSDA;		break;
132060484Sobrien    case BFD_RELOC_VTABLE_INHERIT:	ppc_reloc = R_PPC_GNU_VTINHERIT;	break;
132160484Sobrien    case BFD_RELOC_VTABLE_ENTRY:	ppc_reloc = R_PPC_GNU_VTENTRY;		break;
132260484Sobrien    }
132360484Sobrien
132477298Sobrien  return ppc_elf_howto_table[(int) ppc_reloc];
132560484Sobrien};
132660484Sobrien
132760484Sobrien/* Set the howto pointer for a PowerPC ELF reloc.  */
132860484Sobrien
132960484Sobrienstatic void
133060484Sobrienppc_elf_info_to_howto (abfd, cache_ptr, dst)
133160484Sobrien     bfd *abfd ATTRIBUTE_UNUSED;
133260484Sobrien     arelent *cache_ptr;
133360484Sobrien     Elf32_Internal_Rela *dst;
133460484Sobrien{
133577298Sobrien  if (!ppc_elf_howto_table[R_PPC_ADDR32])
133677298Sobrien    /* Initialize howto table if needed.  */
133760484Sobrien    ppc_elf_howto_init ();
133860484Sobrien
133960484Sobrien  BFD_ASSERT (ELF32_R_TYPE (dst->r_info) < (unsigned int) R_PPC_max);
134060484Sobrien  cache_ptr->howto = ppc_elf_howto_table[ELF32_R_TYPE (dst->r_info)];
134160484Sobrien}
134260484Sobrien
134360484Sobrien/* Handle the R_PPC_ADDR16_HA reloc.  */
134460484Sobrien
134560484Sobrienstatic bfd_reloc_status_type
134660484Sobrienppc_elf_addr16_ha_reloc (abfd, reloc_entry, symbol, data, input_section,
134760484Sobrien			 output_bfd, error_message)
134860484Sobrien     bfd *abfd ATTRIBUTE_UNUSED;
134960484Sobrien     arelent *reloc_entry;
135060484Sobrien     asymbol *symbol;
135160484Sobrien     PTR data ATTRIBUTE_UNUSED;
135260484Sobrien     asection *input_section;
135360484Sobrien     bfd *output_bfd;
135460484Sobrien     char **error_message ATTRIBUTE_UNUSED;
135560484Sobrien{
135660484Sobrien  bfd_vma relocation;
135760484Sobrien
135860484Sobrien  if (output_bfd != NULL)
135960484Sobrien    {
136060484Sobrien      reloc_entry->address += input_section->output_offset;
136160484Sobrien      return bfd_reloc_ok;
136260484Sobrien    }
136360484Sobrien
136460484Sobrien  if (reloc_entry->address > input_section->_cooked_size)
136560484Sobrien    return bfd_reloc_outofrange;
136660484Sobrien
136760484Sobrien  if (bfd_is_com_section (symbol->section))
136860484Sobrien    relocation = 0;
136960484Sobrien  else
137060484Sobrien    relocation = symbol->value;
137160484Sobrien
137260484Sobrien  relocation += symbol->section->output_section->vma;
137360484Sobrien  relocation += symbol->section->output_offset;
137460484Sobrien  relocation += reloc_entry->addend;
137560484Sobrien
137660484Sobrien  reloc_entry->addend += (relocation & 0x8000) << 1;
137760484Sobrien
137860484Sobrien  return bfd_reloc_continue;
137960484Sobrien}
138060484Sobrien
138177298Sobrien/* Function to set whether a module needs the -mrelocatable bit set.  */
138260484Sobrien
138360484Sobrienstatic boolean
138460484Sobrienppc_elf_set_private_flags (abfd, flags)
138560484Sobrien     bfd *abfd;
138660484Sobrien     flagword flags;
138760484Sobrien{
138860484Sobrien  BFD_ASSERT (!elf_flags_init (abfd)
138960484Sobrien	      || elf_elfheader (abfd)->e_flags == flags);
139060484Sobrien
139160484Sobrien  elf_elfheader (abfd)->e_flags = flags;
139260484Sobrien  elf_flags_init (abfd) = true;
139360484Sobrien  return true;
139460484Sobrien}
139560484Sobrien
139660484Sobrien/* Merge backend specific data from an object file to the output
139760484Sobrien   object file when linking */
139860484Sobrienstatic boolean
139960484Sobrienppc_elf_merge_private_bfd_data (ibfd, obfd)
140060484Sobrien     bfd *ibfd;
140160484Sobrien     bfd *obfd;
140260484Sobrien{
140360484Sobrien  flagword old_flags;
140460484Sobrien  flagword new_flags;
140560484Sobrien  boolean error;
140660484Sobrien
140760484Sobrien  /* Check if we have the same endianess */
140877298Sobrien  if (_bfd_generic_verify_endian_match (ibfd, obfd) == false)
140977298Sobrien    return false;
141060484Sobrien
141160484Sobrien  if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
141260484Sobrien      || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
141360484Sobrien    return true;
141460484Sobrien
141560484Sobrien  new_flags = elf_elfheader (ibfd)->e_flags;
141660484Sobrien  old_flags = elf_elfheader (obfd)->e_flags;
141760484Sobrien  if (!elf_flags_init (obfd))	/* First call, no flags set */
141860484Sobrien    {
141960484Sobrien      elf_flags_init (obfd) = true;
142060484Sobrien      elf_elfheader (obfd)->e_flags = new_flags;
142160484Sobrien    }
142260484Sobrien
142360484Sobrien  else if (new_flags == old_flags)	/* Compatible flags are ok */
142460484Sobrien    ;
142560484Sobrien
142660484Sobrien  else					/* Incompatible flags */
142760484Sobrien    {
142860484Sobrien      /* Warn about -mrelocatable mismatch.  Allow -mrelocatable-lib to be linked
142960484Sobrien         with either.  */
143060484Sobrien      error = false;
143160484Sobrien      if ((new_flags & EF_PPC_RELOCATABLE) != 0
143260484Sobrien	  && (old_flags & (EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB)) == 0)
143360484Sobrien	{
143460484Sobrien	  error = true;
143560484Sobrien	  (*_bfd_error_handler)
143660484Sobrien	    (_("%s: compiled with -mrelocatable and linked with modules compiled normally"),
143789857Sobrien	     bfd_archive_filename (ibfd));
143860484Sobrien	}
143960484Sobrien      else if ((new_flags & (EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB)) == 0
144060484Sobrien	       && (old_flags & EF_PPC_RELOCATABLE) != 0)
144160484Sobrien	{
144260484Sobrien	  error = true;
144360484Sobrien	  (*_bfd_error_handler)
144460484Sobrien	    (_("%s: compiled normally and linked with modules compiled with -mrelocatable"),
144589857Sobrien	     bfd_archive_filename (ibfd));
144660484Sobrien	}
144760484Sobrien
144860484Sobrien      /* The output is -mrelocatable-lib iff both the input files are.  */
144960484Sobrien      if (! (new_flags & EF_PPC_RELOCATABLE_LIB))
145060484Sobrien	elf_elfheader (obfd)->e_flags &= ~EF_PPC_RELOCATABLE_LIB;
145160484Sobrien
145260484Sobrien      /* The output is -mrelocatable iff it can't be -mrelocatable-lib,
145360484Sobrien         but each input file is either -mrelocatable or -mrelocatable-lib.  */
145460484Sobrien      if (! (elf_elfheader (obfd)->e_flags & EF_PPC_RELOCATABLE_LIB)
145560484Sobrien	  && (new_flags & (EF_PPC_RELOCATABLE_LIB | EF_PPC_RELOCATABLE))
145660484Sobrien	  && (old_flags & (EF_PPC_RELOCATABLE_LIB | EF_PPC_RELOCATABLE)))
145760484Sobrien	elf_elfheader (obfd)->e_flags |= EF_PPC_RELOCATABLE;
145860484Sobrien
145960484Sobrien      /* Do not warn about eabi vs. V.4 mismatch, just or in the bit if any module uses it */
146060484Sobrien      elf_elfheader (obfd)->e_flags |= (new_flags & EF_PPC_EMB);
146160484Sobrien
146260484Sobrien      new_flags &= ~ (EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB | EF_PPC_EMB);
146360484Sobrien      old_flags &= ~ (EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB | EF_PPC_EMB);
146460484Sobrien
146560484Sobrien      /* Warn about any other mismatches */
146660484Sobrien      if (new_flags != old_flags)
146760484Sobrien	{
146860484Sobrien	  error = true;
146960484Sobrien	  (*_bfd_error_handler)
147060484Sobrien	    (_("%s: uses different e_flags (0x%lx) fields than previous modules (0x%lx)"),
147189857Sobrien	     bfd_archive_filename (ibfd), (long) new_flags, (long) old_flags);
147260484Sobrien	}
147360484Sobrien
147460484Sobrien      if (error)
147560484Sobrien	{
147660484Sobrien	  bfd_set_error (bfd_error_bad_value);
147760484Sobrien	  return false;
147860484Sobrien	}
147960484Sobrien    }
148060484Sobrien
148160484Sobrien  return true;
148260484Sobrien}
148360484Sobrien
148460484Sobrien/* Handle a PowerPC specific section when reading an object file.  This
148560484Sobrien   is called when elfcode.h finds a section with an unknown type.  */
148660484Sobrien
148760484Sobrienstatic boolean
148860484Sobrienppc_elf_section_from_shdr (abfd, hdr, name)
148960484Sobrien     bfd *abfd;
149060484Sobrien     Elf32_Internal_Shdr *hdr;
149160484Sobrien     char *name;
149260484Sobrien{
149360484Sobrien  asection *newsect;
149460484Sobrien  flagword flags;
149560484Sobrien
149660484Sobrien  if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name))
149760484Sobrien    return false;
149860484Sobrien
149960484Sobrien  newsect = hdr->bfd_section;
150060484Sobrien  flags = bfd_get_section_flags (abfd, newsect);
150160484Sobrien  if (hdr->sh_flags & SHF_EXCLUDE)
150260484Sobrien    flags |= SEC_EXCLUDE;
150360484Sobrien
150460484Sobrien  if (hdr->sh_type == SHT_ORDERED)
150560484Sobrien    flags |= SEC_SORT_ENTRIES;
150660484Sobrien
150760484Sobrien  bfd_set_section_flags (abfd, newsect, flags);
150860484Sobrien  return true;
150960484Sobrien}
151060484Sobrien
151160484Sobrien/* Set up any other section flags and such that may be necessary.  */
151260484Sobrien
151360484Sobrienstatic boolean
151460484Sobrienppc_elf_fake_sections (abfd, shdr, asect)
151560484Sobrien     bfd *abfd ATTRIBUTE_UNUSED;
151660484Sobrien     Elf32_Internal_Shdr *shdr;
151760484Sobrien     asection *asect;
151860484Sobrien{
151960484Sobrien  if ((asect->flags & SEC_EXCLUDE) != 0)
152060484Sobrien    shdr->sh_flags |= SHF_EXCLUDE;
152160484Sobrien
152260484Sobrien  if ((asect->flags & SEC_SORT_ENTRIES) != 0)
152360484Sobrien    shdr->sh_type = SHT_ORDERED;
152460484Sobrien
152560484Sobrien  return true;
152660484Sobrien}
152760484Sobrien
152860484Sobrien/* Create a special linker section */
152960484Sobrienstatic elf_linker_section_t *
153060484Sobrienppc_elf_create_linker_section (abfd, info, which)
153160484Sobrien     bfd *abfd;
153260484Sobrien     struct bfd_link_info *info;
153360484Sobrien     enum elf_linker_section_enum which;
153460484Sobrien{
153560484Sobrien  bfd *dynobj = elf_hash_table (info)->dynobj;
153660484Sobrien  elf_linker_section_t *lsect;
153760484Sobrien
153860484Sobrien  /* Record the first bfd section that needs the special section */
153960484Sobrien  if (!dynobj)
154060484Sobrien    dynobj = elf_hash_table (info)->dynobj = abfd;
154160484Sobrien
154260484Sobrien  /* If this is the first time, create the section */
154360484Sobrien  lsect = elf_linker_section (dynobj, which);
154460484Sobrien  if (!lsect)
154560484Sobrien    {
154660484Sobrien      elf_linker_section_t defaults;
154760484Sobrien      static elf_linker_section_t zero_section;
154860484Sobrien
154960484Sobrien      defaults = zero_section;
155060484Sobrien      defaults.which = which;
155160484Sobrien      defaults.hole_written_p = false;
155260484Sobrien      defaults.alignment = 2;
155360484Sobrien
155460484Sobrien      /* Both of these sections are (technically) created by the user
155560484Sobrien	 putting data in them, so they shouldn't be marked
155660484Sobrien	 SEC_LINKER_CREATED.
155760484Sobrien
155860484Sobrien	 The linker creates them so it has somewhere to attach their
155960484Sobrien	 respective symbols. In fact, if they were empty it would
156060484Sobrien	 be OK to leave the symbol set to 0 (or any random number), because
156160484Sobrien	 the appropriate register should never be used.  */
156260484Sobrien      defaults.flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
156360484Sobrien			| SEC_IN_MEMORY);
156460484Sobrien
156560484Sobrien      switch (which)
156660484Sobrien	{
156760484Sobrien	default:
156860484Sobrien	  (*_bfd_error_handler) (_("%s: Unknown special linker type %d"),
156960484Sobrien				 bfd_get_filename (abfd),
157077298Sobrien				 (int) which);
157160484Sobrien
157260484Sobrien	  bfd_set_error (bfd_error_bad_value);
157377298Sobrien	  return (elf_linker_section_t *) 0;
157460484Sobrien
157560484Sobrien	case LINKER_SECTION_SDATA:	/* .sdata/.sbss section */
157660484Sobrien	  defaults.name		  = ".sdata";
157760484Sobrien	  defaults.rel_name	  = ".rela.sdata";
157860484Sobrien	  defaults.bss_name	  = ".sbss";
157960484Sobrien	  defaults.sym_name	  = "_SDA_BASE_";
158060484Sobrien	  defaults.sym_offset	  = 32768;
158160484Sobrien	  break;
158260484Sobrien
158360484Sobrien	case LINKER_SECTION_SDATA2:	/* .sdata2/.sbss2 section */
158460484Sobrien	  defaults.name		  = ".sdata2";
158560484Sobrien	  defaults.rel_name	  = ".rela.sdata2";
158660484Sobrien	  defaults.bss_name	  = ".sbss2";
158760484Sobrien	  defaults.sym_name	  = "_SDA2_BASE_";
158860484Sobrien	  defaults.sym_offset	  = 32768;
158960484Sobrien	  defaults.flags	 |= SEC_READONLY;
159060484Sobrien	  break;
159160484Sobrien	}
159260484Sobrien
159360484Sobrien      lsect = _bfd_elf_create_linker_section (abfd, info, which, &defaults);
159460484Sobrien    }
159560484Sobrien
159660484Sobrien  return lsect;
159760484Sobrien}
159860484Sobrien
159977298Sobrien/* If we have a non-zero sized .sbss2 or .PPC.EMB.sbss0 sections, we
160077298Sobrien   need to bump up the number of section headers.  */
160160484Sobrien
160260484Sobrienstatic int
160360484Sobrienppc_elf_additional_program_headers (abfd)
160460484Sobrien     bfd *abfd;
160560484Sobrien{
160660484Sobrien  asection *s;
160760484Sobrien  int ret;
160860484Sobrien
160960484Sobrien  ret = 0;
161060484Sobrien
161160484Sobrien  s = bfd_get_section_by_name (abfd, ".interp");
161260484Sobrien  if (s != NULL)
161360484Sobrien    ++ret;
161460484Sobrien
161560484Sobrien  s = bfd_get_section_by_name (abfd, ".sbss2");
161660484Sobrien  if (s != NULL && (s->flags & SEC_LOAD) != 0 && s->_raw_size > 0)
161760484Sobrien    ++ret;
161860484Sobrien
161960484Sobrien  s = bfd_get_section_by_name (abfd, ".PPC.EMB.sbss0");
162060484Sobrien  if (s != NULL && (s->flags & SEC_LOAD) != 0 && s->_raw_size > 0)
162160484Sobrien    ++ret;
162260484Sobrien
162360484Sobrien  return ret;
162460484Sobrien}
162560484Sobrien
162677298Sobrien/* Modify the segment map if needed.  */
162760484Sobrien
162860484Sobrienstatic boolean
162960484Sobrienppc_elf_modify_segment_map (abfd)
163060484Sobrien     bfd *abfd ATTRIBUTE_UNUSED;
163160484Sobrien{
163260484Sobrien  return true;
163360484Sobrien}
163460484Sobrien
163560484Sobrien/* We have to create .dynsbss and .rela.sbss here so that they get mapped
163660484Sobrien   to output sections (just like _bfd_elf_create_dynamic_sections has
163760484Sobrien   to create .dynbss and .rela.bss).  */
163860484Sobrien
163960484Sobrienstatic boolean
164060484Sobrienppc_elf_create_dynamic_sections (abfd, info)
164160484Sobrien     bfd *abfd;
164260484Sobrien     struct bfd_link_info *info;
164360484Sobrien{
164460484Sobrien  register asection *s;
164560484Sobrien  flagword flags;
164660484Sobrien
164777298Sobrien  if (!_bfd_elf_create_dynamic_sections (abfd, info))
164860484Sobrien    return false;
164960484Sobrien
165060484Sobrien  flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
165160484Sobrien	   | SEC_LINKER_CREATED);
165260484Sobrien
165360484Sobrien  s = bfd_make_section (abfd, ".dynsbss");
165460484Sobrien  if (s == NULL
165560484Sobrien      || ! bfd_set_section_flags (abfd, s, SEC_ALLOC))
165660484Sobrien    return false;
165760484Sobrien
165860484Sobrien  if (! info->shared)
165960484Sobrien    {
166060484Sobrien      s = bfd_make_section (abfd, ".rela.sbss");
166160484Sobrien      if (s == NULL
166260484Sobrien	  || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
166360484Sobrien	  || ! bfd_set_section_alignment (abfd, s, 2))
166460484Sobrien	return false;
166560484Sobrien    }
166660484Sobrien  return true;
166760484Sobrien}
166860484Sobrien
166960484Sobrien/* Adjust a symbol defined by a dynamic object and referenced by a
167060484Sobrien   regular object.  The current definition is in some section of the
167160484Sobrien   dynamic object, but we're not including those sections.  We have to
167260484Sobrien   change the definition to something the rest of the link can
167360484Sobrien   understand.  */
167460484Sobrien
167560484Sobrienstatic boolean
167660484Sobrienppc_elf_adjust_dynamic_symbol (info, h)
167760484Sobrien     struct bfd_link_info *info;
167860484Sobrien     struct elf_link_hash_entry *h;
167960484Sobrien{
168060484Sobrien  bfd *dynobj = elf_hash_table (info)->dynobj;
168160484Sobrien  asection *s;
168260484Sobrien  unsigned int power_of_two;
168360484Sobrien  bfd_vma plt_offset;
168460484Sobrien
168560484Sobrien#ifdef DEBUG
168660484Sobrien  fprintf (stderr, "ppc_elf_adjust_dynamic_symbol called for %s\n", h->root.root.string);
168760484Sobrien#endif
168860484Sobrien
168960484Sobrien  /* Make sure we know what is going on here.  */
169060484Sobrien  BFD_ASSERT (dynobj != NULL
169160484Sobrien	      && ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT)
169260484Sobrien		  || h->weakdef != NULL
169360484Sobrien		  || ((h->elf_link_hash_flags
169460484Sobrien		       & ELF_LINK_HASH_DEF_DYNAMIC) != 0
169560484Sobrien		      && (h->elf_link_hash_flags
169660484Sobrien			  & ELF_LINK_HASH_REF_REGULAR) != 0
169760484Sobrien		      && (h->elf_link_hash_flags
169860484Sobrien			  & ELF_LINK_HASH_DEF_REGULAR) == 0)));
169960484Sobrien
170060484Sobrien  /* If this is a function, put it in the procedure linkage table.  We
170160484Sobrien     will fill in the contents of the procedure linkage table later,
170260484Sobrien     when we know the address of the .got section.  */
170360484Sobrien  if (h->type == STT_FUNC
170460484Sobrien      || (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0)
170560484Sobrien    {
170660484Sobrien      if (! elf_hash_table (info)->dynamic_sections_created
170777298Sobrien 	  || SYMBOL_CALLS_LOCAL (info, h)
170860484Sobrien	  || (info->shared && h->plt.refcount <= 0))
170960484Sobrien	{
171060484Sobrien	  /* A PLT entry is not required/allowed when:
171160484Sobrien
171260484Sobrien	     1. We are not using ld.so; because then the PLT entry
171360484Sobrien	     can't be set up, so we can't use one.
171460484Sobrien
171577298Sobrien	     2. We know for certain that a call to this symbol
171677298Sobrien	     will go to this object.
171760484Sobrien
171860484Sobrien	     3. GC has rendered the entry unused.
171960484Sobrien	     Note, however, that in an executable all references to the
172060484Sobrien	     symbol go to the PLT, so we can't turn it off in that case.
172160484Sobrien	     ??? The correct thing to do here is to reference count
172260484Sobrien	     all uses of the symbol, not just those to the GOT or PLT.  */
172360484Sobrien	  h->plt.offset = (bfd_vma) -1;
172460484Sobrien	  h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
172560484Sobrien	  return true;
172660484Sobrien	}
172760484Sobrien
172860484Sobrien      /* Make sure this symbol is output as a dynamic symbol.  */
172960484Sobrien      if (h->dynindx == -1)
173060484Sobrien	{
173160484Sobrien	  if (! bfd_elf32_link_record_dynamic_symbol (info, h))
173260484Sobrien	    return false;
173360484Sobrien	}
173460484Sobrien      BFD_ASSERT (h->dynindx != -1);
173560484Sobrien
173660484Sobrien      s = bfd_get_section_by_name (dynobj, ".plt");
173760484Sobrien      BFD_ASSERT (s != NULL);
173860484Sobrien
173960484Sobrien      /* If this is the first .plt entry, make room for the special
174060484Sobrien	 first entry.  */
174160484Sobrien      if (s->_raw_size == 0)
174260484Sobrien	s->_raw_size += PLT_INITIAL_ENTRY_SIZE;
174360484Sobrien
174460484Sobrien      /* The PowerPC PLT is actually composed of two parts, the first part
174560484Sobrien	 is 2 words (for a load and a jump), and then there is a remaining
174660484Sobrien	 word available at the end.  */
174760484Sobrien      plt_offset = (PLT_INITIAL_ENTRY_SIZE
174860484Sobrien		    + (PLT_SLOT_SIZE
174960484Sobrien		       * ((s->_raw_size - PLT_INITIAL_ENTRY_SIZE)
175060484Sobrien			  / PLT_ENTRY_SIZE)));
175160484Sobrien
175260484Sobrien      /* If this symbol is not defined in a regular file, and we are
175360484Sobrien	 not generating a shared library, then set the symbol to this
175460484Sobrien	 location in the .plt.  This is required to make function
175560484Sobrien	 pointers compare as equal between the normal executable and
175660484Sobrien	 the shared library.  */
175760484Sobrien      if (! info->shared
175860484Sobrien	  && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
175960484Sobrien	{
176060484Sobrien	  h->root.u.def.section = s;
176160484Sobrien	  h->root.u.def.value = plt_offset;
176260484Sobrien	}
176360484Sobrien
176460484Sobrien      h->plt.offset = plt_offset;
176560484Sobrien
176660484Sobrien      /* Make room for this entry.  After the 8192nd entry, room
176760484Sobrien         for two entries is allocated.  */
176860484Sobrien      if ((s->_raw_size - PLT_INITIAL_ENTRY_SIZE) / PLT_ENTRY_SIZE
176960484Sobrien	  >= PLT_NUM_SINGLE_ENTRIES)
177060484Sobrien	s->_raw_size += 2 * PLT_ENTRY_SIZE;
177160484Sobrien      else
177260484Sobrien	s->_raw_size += PLT_ENTRY_SIZE;
177360484Sobrien
177460484Sobrien      /* We also need to make an entry in the .rela.plt section.  */
177560484Sobrien      s = bfd_get_section_by_name (dynobj, ".rela.plt");
177660484Sobrien      BFD_ASSERT (s != NULL);
177760484Sobrien      s->_raw_size += sizeof (Elf32_External_Rela);
177860484Sobrien
177960484Sobrien      return true;
178060484Sobrien    }
178189857Sobrien  else
178289857Sobrien    h->plt.offset = (bfd_vma) -1;
178360484Sobrien
178460484Sobrien  /* If this is a weak symbol, and there is a real definition, the
178560484Sobrien     processor independent code will have arranged for us to see the
178660484Sobrien     real definition first, and we can just use the same value.  */
178760484Sobrien  if (h->weakdef != NULL)
178860484Sobrien    {
178960484Sobrien      BFD_ASSERT (h->weakdef->root.type == bfd_link_hash_defined
179060484Sobrien		  || h->weakdef->root.type == bfd_link_hash_defweak);
179160484Sobrien      h->root.u.def.section = h->weakdef->root.u.def.section;
179260484Sobrien      h->root.u.def.value = h->weakdef->root.u.def.value;
179360484Sobrien      return true;
179460484Sobrien    }
179560484Sobrien
179660484Sobrien  /* This is a reference to a symbol defined by a dynamic object which
179760484Sobrien     is not a function.  */
179860484Sobrien
179960484Sobrien  /* If we are creating a shared library, we must presume that the
180060484Sobrien     only references to the symbol are via the global offset table.
180160484Sobrien     For such cases we need not do anything here; the relocations will
180260484Sobrien     be handled correctly by relocate_section.  */
180360484Sobrien  if (info->shared)
180460484Sobrien    return true;
180560484Sobrien
180660484Sobrien  /* We must allocate the symbol in our .dynbss section, which will
180760484Sobrien     become part of the .bss section of the executable.  There will be
180860484Sobrien     an entry for this symbol in the .dynsym section.  The dynamic
180960484Sobrien     object will contain position independent code, so all references
181060484Sobrien     from the dynamic object to this symbol will go through the global
181160484Sobrien     offset table.  The dynamic linker will use the .dynsym entry to
181260484Sobrien     determine the address it must put in the global offset table, so
181360484Sobrien     both the dynamic object and the regular object will refer to the
181460484Sobrien     same memory location for the variable.
181560484Sobrien
181660484Sobrien     Of course, if the symbol is sufficiently small, we must instead
181760484Sobrien     allocate it in .sbss.  FIXME: It would be better to do this if and
181860484Sobrien     only if there were actually SDAREL relocs for that symbol.  */
181960484Sobrien
182060484Sobrien  if (h->size <= elf_gp_size (dynobj))
182160484Sobrien    s = bfd_get_section_by_name (dynobj, ".dynsbss");
182260484Sobrien  else
182360484Sobrien    s = bfd_get_section_by_name (dynobj, ".dynbss");
182460484Sobrien  BFD_ASSERT (s != NULL);
182560484Sobrien
182660484Sobrien  /* We must generate a R_PPC_COPY reloc to tell the dynamic linker to
182760484Sobrien     copy the initial value out of the dynamic object and into the
182860484Sobrien     runtime process image.  We need to remember the offset into the
182960484Sobrien     .rela.bss section we are going to use.  */
183060484Sobrien  if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
183160484Sobrien    {
183260484Sobrien      asection *srel;
183360484Sobrien
183460484Sobrien      if (h->size <= elf_gp_size (dynobj))
183560484Sobrien	srel = bfd_get_section_by_name (dynobj, ".rela.sbss");
183660484Sobrien      else
183760484Sobrien	srel = bfd_get_section_by_name (dynobj, ".rela.bss");
183860484Sobrien      BFD_ASSERT (srel != NULL);
183960484Sobrien      srel->_raw_size += sizeof (Elf32_External_Rela);
184060484Sobrien      h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_COPY;
184160484Sobrien    }
184260484Sobrien
184360484Sobrien  /* We need to figure out the alignment required for this symbol.  I
184460484Sobrien     have no idea how ELF linkers handle this.  */
184560484Sobrien  power_of_two = bfd_log2 (h->size);
184660484Sobrien  if (power_of_two > 4)
184760484Sobrien    power_of_two = 4;
184860484Sobrien
184960484Sobrien  /* Apply the required alignment.  */
185060484Sobrien  s->_raw_size = BFD_ALIGN (s->_raw_size,
185160484Sobrien			    (bfd_size_type) (1 << power_of_two));
185260484Sobrien  if (power_of_two > bfd_get_section_alignment (dynobj, s))
185360484Sobrien    {
185460484Sobrien      if (! bfd_set_section_alignment (dynobj, s, power_of_two))
185560484Sobrien	return false;
185660484Sobrien    }
185760484Sobrien
185860484Sobrien  /* Define the symbol as being at this point in the section.  */
185960484Sobrien  h->root.u.def.section = s;
186060484Sobrien  h->root.u.def.value = s->_raw_size;
186160484Sobrien
186260484Sobrien  /* Increment the section size to make room for the symbol.  */
186360484Sobrien  s->_raw_size += h->size;
186460484Sobrien
186560484Sobrien  return true;
186660484Sobrien}
186760484Sobrien
186860484Sobrien/* Set the sizes of the dynamic sections.  */
186960484Sobrien
187060484Sobrienstatic boolean
187160484Sobrienppc_elf_size_dynamic_sections (output_bfd, info)
187289857Sobrien     bfd *output_bfd ATTRIBUTE_UNUSED;
187360484Sobrien     struct bfd_link_info *info;
187460484Sobrien{
187560484Sobrien  bfd *dynobj;
187660484Sobrien  asection *s;
187760484Sobrien  boolean plt;
187860484Sobrien  boolean relocs;
187960484Sobrien
188060484Sobrien#ifdef DEBUG
188160484Sobrien  fprintf (stderr, "ppc_elf_size_dynamic_sections called\n");
188260484Sobrien#endif
188360484Sobrien
188460484Sobrien  dynobj = elf_hash_table (info)->dynobj;
188560484Sobrien  BFD_ASSERT (dynobj != NULL);
188660484Sobrien
188760484Sobrien  if (elf_hash_table (info)->dynamic_sections_created)
188860484Sobrien    {
188960484Sobrien      /* Set the contents of the .interp section to the interpreter.  */
189060484Sobrien      if (! info->shared)
189160484Sobrien	{
189260484Sobrien	  s = bfd_get_section_by_name (dynobj, ".interp");
189360484Sobrien	  BFD_ASSERT (s != NULL);
189460484Sobrien	  s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER;
189560484Sobrien	  s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
189660484Sobrien	}
189760484Sobrien    }
189860484Sobrien  else
189960484Sobrien    {
190060484Sobrien      /* We may have created entries in the .rela.got, .rela.sdata, and
190160484Sobrien	 .rela.sdata2 sections.  However, if we are not creating the
190260484Sobrien	 dynamic sections, we will not actually use these entries.  Reset
190360484Sobrien	 the size of .rela.got, et al, which will cause it to get
190460484Sobrien	 stripped from the output file below.  */
190560484Sobrien      static char *rela_sections[] = { ".rela.got", ".rela.sdata",
190660484Sobrien				       ".rela.sdata2", ".rela.sbss",
190777298Sobrien				       (char *) 0 };
190860484Sobrien      char **p;
190960484Sobrien
191077298Sobrien      for (p = rela_sections; *p != (char *) 0; p++)
191160484Sobrien	{
191260484Sobrien	  s = bfd_get_section_by_name (dynobj, *p);
191360484Sobrien	  if (s != NULL)
191460484Sobrien	    s->_raw_size = 0;
191560484Sobrien	}
191660484Sobrien    }
191760484Sobrien
191860484Sobrien  /* The check_relocs and adjust_dynamic_symbol entry points have
191960484Sobrien     determined the sizes of the various dynamic sections.  Allocate
192060484Sobrien     memory for them.  */
192160484Sobrien  plt = false;
192260484Sobrien  relocs = false;
192360484Sobrien  for (s = dynobj->sections; s != NULL; s = s->next)
192460484Sobrien    {
192560484Sobrien      const char *name;
192660484Sobrien      boolean strip;
192760484Sobrien
192860484Sobrien      if ((s->flags & SEC_LINKER_CREATED) == 0)
192960484Sobrien	continue;
193060484Sobrien
193160484Sobrien      /* It's OK to base decisions on the section name, because none
193260484Sobrien	 of the dynobj section names depend upon the input files.  */
193360484Sobrien      name = bfd_get_section_name (dynobj, s);
193460484Sobrien
193560484Sobrien      strip = false;
193660484Sobrien
193760484Sobrien      if (strcmp (name, ".plt") == 0)
193860484Sobrien	{
193960484Sobrien	  if (s->_raw_size == 0)
194060484Sobrien	    {
194160484Sobrien	      /* Strip this section if we don't need it; see the
194260484Sobrien                 comment below.  */
194360484Sobrien	      strip = true;
194460484Sobrien	    }
194560484Sobrien	  else
194660484Sobrien	    {
194760484Sobrien	      /* Remember whether there is a PLT.  */
194860484Sobrien	      plt = true;
194960484Sobrien	    }
195060484Sobrien	}
195160484Sobrien      else if (strncmp (name, ".rela", 5) == 0)
195260484Sobrien	{
195360484Sobrien	  if (s->_raw_size == 0)
195460484Sobrien	    {
195560484Sobrien	      /* If we don't need this section, strip it from the
195660484Sobrien		 output file.  This is mostly to handle .rela.bss and
195760484Sobrien		 .rela.plt.  We must create both sections in
195860484Sobrien		 create_dynamic_sections, because they must be created
195960484Sobrien		 before the linker maps input sections to output
196060484Sobrien		 sections.  The linker does that before
196160484Sobrien		 adjust_dynamic_symbol is called, and it is that
196260484Sobrien		 function which decides whether anything needs to go
196360484Sobrien		 into these sections.  */
196460484Sobrien	      strip = true;
196560484Sobrien	    }
196660484Sobrien	  else
196760484Sobrien	    {
196877298Sobrien	      /* Remember whether there are any relocation sections.  */
196960484Sobrien	      relocs = true;
197060484Sobrien
197160484Sobrien	      /* We use the reloc_count field as a counter if we need
197260484Sobrien		 to copy relocs into the output file.  */
197360484Sobrien	      s->reloc_count = 0;
197460484Sobrien	    }
197560484Sobrien	}
197660484Sobrien      else if (strcmp (name, ".got") != 0
197760484Sobrien	       && strcmp (name, ".sdata") != 0
197860484Sobrien	       && strcmp (name, ".sdata2") != 0)
197960484Sobrien	{
198060484Sobrien	  /* It's not one of our sections, so don't allocate space.  */
198160484Sobrien	  continue;
198260484Sobrien	}
198360484Sobrien
198460484Sobrien      if (strip)
198560484Sobrien	{
198660484Sobrien	  _bfd_strip_section_from_output (info, s);
198760484Sobrien	  continue;
198860484Sobrien	}
198960484Sobrien
199060484Sobrien      /* Allocate memory for the section contents.  */
199160484Sobrien      s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size);
199260484Sobrien      if (s->contents == NULL && s->_raw_size != 0)
199360484Sobrien	return false;
199460484Sobrien    }
199560484Sobrien
199660484Sobrien  if (elf_hash_table (info)->dynamic_sections_created)
199760484Sobrien    {
199860484Sobrien      /* Add some entries to the .dynamic section.  We fill in the
199960484Sobrien	 values later, in ppc_elf_finish_dynamic_sections, but we
200060484Sobrien	 must add the entries now so that we get the correct size for
200160484Sobrien	 the .dynamic section.  The DT_DEBUG entry is filled in by the
200260484Sobrien	 dynamic linker and used by the debugger.  */
200389857Sobrien#define add_dynamic_entry(TAG, VAL) \
200489857Sobrien  bfd_elf32_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL))
200589857Sobrien
200689857Sobrien      if (!info->shared)
200760484Sobrien	{
200889857Sobrien	  if (!add_dynamic_entry (DT_DEBUG, 0))
200960484Sobrien	    return false;
201060484Sobrien	}
201160484Sobrien
201260484Sobrien      if (plt)
201360484Sobrien	{
201489857Sobrien	  if (!add_dynamic_entry (DT_PLTGOT, 0)
201589857Sobrien	      || !add_dynamic_entry (DT_PLTRELSZ, 0)
201689857Sobrien	      || !add_dynamic_entry (DT_PLTREL, DT_RELA)
201789857Sobrien	      || !add_dynamic_entry (DT_JMPREL, 0))
201860484Sobrien	    return false;
201960484Sobrien	}
202060484Sobrien
202160484Sobrien      if (relocs)
202260484Sobrien	{
202389857Sobrien	  if (!add_dynamic_entry (DT_RELA, 0)
202489857Sobrien	      || !add_dynamic_entry (DT_RELASZ, 0)
202589857Sobrien	      || !add_dynamic_entry (DT_RELAENT, sizeof (Elf32_External_Rela)))
202660484Sobrien	    return false;
202760484Sobrien	}
202860484Sobrien
202989857Sobrien      if ((info->flags & DF_TEXTREL) != 0)
203060484Sobrien	{
203189857Sobrien	  if (!add_dynamic_entry (DT_TEXTREL, 0))
203260484Sobrien	    return false;
203377298Sobrien	  info->flags |= DF_TEXTREL;
203460484Sobrien	}
203560484Sobrien    }
203689857Sobrien#undef add_dynamic_entry
203760484Sobrien
203860484Sobrien  return true;
203960484Sobrien}
204060484Sobrien
204160484Sobrien/* Look through the relocs for a section during the first phase, and
204260484Sobrien   allocate space in the global offset table or procedure linkage
204360484Sobrien   table.  */
204460484Sobrien
204560484Sobrienstatic boolean
204660484Sobrienppc_elf_check_relocs (abfd, info, sec, relocs)
204760484Sobrien     bfd *abfd;
204860484Sobrien     struct bfd_link_info *info;
204960484Sobrien     asection *sec;
205060484Sobrien     const Elf_Internal_Rela *relocs;
205160484Sobrien{
205260484Sobrien  bfd *dynobj;
205360484Sobrien  Elf_Internal_Shdr *symtab_hdr;
205460484Sobrien  struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
205560484Sobrien  const Elf_Internal_Rela *rel;
205660484Sobrien  const Elf_Internal_Rela *rel_end;
205760484Sobrien  bfd_signed_vma *local_got_refcounts;
205860484Sobrien  elf_linker_section_t *sdata;
205960484Sobrien  elf_linker_section_t *sdata2;
206060484Sobrien  asection *sreloc;
206160484Sobrien  asection *sgot = NULL;
206260484Sobrien  asection *srelgot = NULL;
206360484Sobrien
206460484Sobrien  if (info->relocateable)
206560484Sobrien    return true;
206660484Sobrien
206760484Sobrien#ifdef DEBUG
206860484Sobrien  fprintf (stderr, "ppc_elf_check_relocs called for section %s in %s\n",
206960484Sobrien	   bfd_get_section_name (abfd, sec),
207089857Sobrien	   bfd_archive_filename (abfd));
207160484Sobrien#endif
207260484Sobrien
207360484Sobrien  /* Create the linker generated sections all the time so that the
207460484Sobrien     special symbols are created.  */
207560484Sobrien
207660484Sobrien  if ((sdata = elf_linker_section (abfd, LINKER_SECTION_SDATA)) == NULL)
207760484Sobrien    {
207860484Sobrien      sdata = ppc_elf_create_linker_section (abfd, info, LINKER_SECTION_SDATA);
207960484Sobrien      if (!sdata)
208060484Sobrien	return false;
208160484Sobrien    }
208260484Sobrien
208360484Sobrien  if ((sdata2 = elf_linker_section (abfd, LINKER_SECTION_SDATA2)) == NULL)
208460484Sobrien    {
208560484Sobrien      sdata2 = ppc_elf_create_linker_section (abfd, info, LINKER_SECTION_SDATA2);
208660484Sobrien      if (!sdata2)
208760484Sobrien	return false;
208860484Sobrien    }
208960484Sobrien
209060484Sobrien  dynobj = elf_hash_table (info)->dynobj;
209160484Sobrien  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
209260484Sobrien  local_got_refcounts = elf_local_got_refcounts (abfd);
209360484Sobrien
209460484Sobrien  sym_hashes = elf_sym_hashes (abfd);
209577298Sobrien  sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof (Elf32_External_Sym);
209660484Sobrien  if (!elf_bad_symtab (abfd))
209760484Sobrien    sym_hashes_end -= symtab_hdr->sh_info;
209860484Sobrien
209960484Sobrien  sreloc = NULL;
210060484Sobrien
210160484Sobrien  rel_end = relocs + sec->reloc_count;
210260484Sobrien  for (rel = relocs; rel < rel_end; rel++)
210360484Sobrien    {
210460484Sobrien      unsigned long r_symndx;
210560484Sobrien      struct elf_link_hash_entry *h;
210660484Sobrien
210760484Sobrien      r_symndx = ELF32_R_SYM (rel->r_info);
210860484Sobrien      if (r_symndx < symtab_hdr->sh_info)
210960484Sobrien	h = NULL;
211060484Sobrien      else
211160484Sobrien	h = sym_hashes[r_symndx - symtab_hdr->sh_info];
211260484Sobrien
211360484Sobrien      /* If a relocation refers to _GLOBAL_OFFSET_TABLE_, create the .got.
211460484Sobrien	 This shows up in particular in an R_PPC_ADDR32 in the eabi
211560484Sobrien	 startup code.  */
211660484Sobrien      if (h && strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
211760484Sobrien	{
211860484Sobrien	  if (sgot == NULL)
211960484Sobrien	    {
212060484Sobrien	      if (dynobj == NULL)
212160484Sobrien		elf_hash_table (info)->dynobj = dynobj = abfd;
212260484Sobrien	      if (! _bfd_elf_create_got_section (dynobj, info))
212360484Sobrien		return false;
212460484Sobrien	      sgot = bfd_get_section_by_name (dynobj, ".got");
212560484Sobrien	      BFD_ASSERT (sgot != NULL);
212660484Sobrien	    }
212760484Sobrien	}
212860484Sobrien
212960484Sobrien      switch (ELF32_R_TYPE (rel->r_info))
213060484Sobrien	{
213160484Sobrien	/* GOT16 relocations */
213260484Sobrien	case R_PPC_GOT16:
213360484Sobrien	case R_PPC_GOT16_LO:
213460484Sobrien	case R_PPC_GOT16_HI:
213560484Sobrien	case R_PPC_GOT16_HA:
213660484Sobrien	  /* This symbol requires a global offset table entry.  */
213760484Sobrien
213860484Sobrien	  if (sgot == NULL)
213960484Sobrien	    {
214060484Sobrien	      if (dynobj == NULL)
214160484Sobrien		elf_hash_table (info)->dynobj = dynobj = abfd;
214260484Sobrien	      if (! _bfd_elf_create_got_section (dynobj, info))
214360484Sobrien		return false;
214460484Sobrien	      sgot = bfd_get_section_by_name (dynobj, ".got");
214560484Sobrien	      BFD_ASSERT (sgot != NULL);
214660484Sobrien	    }
214760484Sobrien
214860484Sobrien	  if (srelgot == NULL
214960484Sobrien	      && (h != NULL || info->shared))
215060484Sobrien	    {
215160484Sobrien	      srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
215260484Sobrien	      if (srelgot == NULL)
215360484Sobrien		{
215460484Sobrien		  srelgot = bfd_make_section (dynobj, ".rela.got");
215560484Sobrien		  if (srelgot == NULL
215660484Sobrien		      || ! bfd_set_section_flags (dynobj, srelgot,
215760484Sobrien						  (SEC_ALLOC
215860484Sobrien						   | SEC_LOAD
215960484Sobrien						   | SEC_HAS_CONTENTS
216060484Sobrien						   | SEC_IN_MEMORY
216160484Sobrien						   | SEC_LINKER_CREATED
216260484Sobrien						   | SEC_READONLY))
216360484Sobrien		      || ! bfd_set_section_alignment (dynobj, srelgot, 2))
216460484Sobrien		    return false;
216560484Sobrien		}
216660484Sobrien	    }
216760484Sobrien
216860484Sobrien	  if (h != NULL)
216960484Sobrien	    {
217089857Sobrien	      if (h->got.refcount == 0)
217160484Sobrien		{
217260484Sobrien		  /* Make sure this symbol is output as a dynamic symbol.  */
217360484Sobrien		  if (h->dynindx == -1)
217460484Sobrien		    if (!bfd_elf32_link_record_dynamic_symbol (info, h))
217560484Sobrien		      return false;
217660484Sobrien
217760484Sobrien		  /* Allocate space in the .got.  */
217860484Sobrien		  sgot->_raw_size += 4;
217960484Sobrien		  /* Allocate relocation space.  */
218060484Sobrien		  srelgot->_raw_size += sizeof (Elf32_External_Rela);
218160484Sobrien		}
218289857Sobrien	      h->got.refcount++;
218360484Sobrien	    }
218460484Sobrien	  else
218560484Sobrien	    {
218660484Sobrien	      /* This is a global offset table entry for a local symbol.  */
218760484Sobrien	      if (local_got_refcounts == NULL)
218860484Sobrien		{
218989857Sobrien		  bfd_size_type size;
219060484Sobrien
219189857Sobrien		  size = symtab_hdr->sh_info;
219289857Sobrien		  size *= sizeof (bfd_signed_vma);
219389857Sobrien		  local_got_refcounts
219489857Sobrien		    = (bfd_signed_vma *) bfd_zalloc (abfd, size);
219560484Sobrien		  if (local_got_refcounts == NULL)
219660484Sobrien		    return false;
219760484Sobrien		  elf_local_got_refcounts (abfd) = local_got_refcounts;
219860484Sobrien		}
219989857Sobrien	      if (local_got_refcounts[r_symndx] == 0)
220060484Sobrien		{
220160484Sobrien		  sgot->_raw_size += 4;
220260484Sobrien
220360484Sobrien		  /* If we are generating a shared object, we need to
220460484Sobrien                     output a R_PPC_RELATIVE reloc so that the
220560484Sobrien                     dynamic linker can adjust this GOT entry.  */
220660484Sobrien		  if (info->shared)
220760484Sobrien		    srelgot->_raw_size += sizeof (Elf32_External_Rela);
220860484Sobrien		}
220989857Sobrien	      local_got_refcounts[r_symndx]++;
221060484Sobrien	    }
221160484Sobrien	  break;
221260484Sobrien
221360484Sobrien	/* Indirect .sdata relocation */
221460484Sobrien	case R_PPC_EMB_SDAI16:
221560484Sobrien	  if (info->shared)
221660484Sobrien	    {
221760484Sobrien	      ((*_bfd_error_handler)
221860484Sobrien	       (_("%s: relocation %s cannot be used when making a shared object"),
221989857Sobrien		bfd_archive_filename (abfd), "R_PPC_EMB_SDAI16"));
222077298Sobrien	      return false;
222160484Sobrien	    }
222260484Sobrien
222360484Sobrien	  if (srelgot == NULL && (h != NULL || info->shared))
222460484Sobrien	    {
222560484Sobrien	      srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
222660484Sobrien	      if (srelgot == NULL)
222760484Sobrien		{
222860484Sobrien		  srelgot = bfd_make_section (dynobj, ".rela.got");
222960484Sobrien		  if (srelgot == NULL
223060484Sobrien		      || ! bfd_set_section_flags (dynobj, srelgot,
223160484Sobrien						  (SEC_ALLOC
223260484Sobrien						   | SEC_LOAD
223360484Sobrien						   | SEC_HAS_CONTENTS
223460484Sobrien						   | SEC_IN_MEMORY
223560484Sobrien						   | SEC_LINKER_CREATED
223660484Sobrien						   | SEC_READONLY))
223760484Sobrien		      || ! bfd_set_section_alignment (dynobj, srelgot, 2))
223860484Sobrien		    return false;
223960484Sobrien		}
224060484Sobrien	    }
224160484Sobrien
224260484Sobrien	  if (!bfd_elf32_create_pointer_linker_section (abfd, info, sdata, h, rel))
224360484Sobrien	    return false;
224460484Sobrien
224560484Sobrien	  break;
224660484Sobrien
224760484Sobrien	/* Indirect .sdata2 relocation */
224860484Sobrien	case R_PPC_EMB_SDA2I16:
224960484Sobrien	  if (info->shared)
225060484Sobrien	    {
225160484Sobrien	      ((*_bfd_error_handler)
225260484Sobrien	       (_("%s: relocation %s cannot be used when making a shared object"),
225389857Sobrien		bfd_archive_filename (abfd), "R_PPC_EMB_SDA2I16"));
225460484Sobrien	      return false;
225560484Sobrien	    }
225660484Sobrien
225760484Sobrien	  if (srelgot == NULL && (h != NULL || info->shared))
225860484Sobrien	    {
225960484Sobrien	      srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
226060484Sobrien	      if (srelgot == NULL)
226160484Sobrien		{
226260484Sobrien		  srelgot = bfd_make_section (dynobj, ".rela.got");
226360484Sobrien		  if (srelgot == NULL
226460484Sobrien		      || ! bfd_set_section_flags (dynobj, srelgot,
226560484Sobrien						  (SEC_ALLOC
226660484Sobrien						   | SEC_LOAD
226760484Sobrien						   | SEC_HAS_CONTENTS
226860484Sobrien						   | SEC_IN_MEMORY
226960484Sobrien						   | SEC_LINKER_CREATED
227060484Sobrien						   | SEC_READONLY))
227160484Sobrien		      || ! bfd_set_section_alignment (dynobj, srelgot, 2))
227260484Sobrien		    return false;
227360484Sobrien		}
227460484Sobrien	    }
227560484Sobrien
227660484Sobrien	  if (!bfd_elf32_create_pointer_linker_section (abfd, info, sdata2, h, rel))
227760484Sobrien	    return false;
227860484Sobrien
227960484Sobrien	  break;
228060484Sobrien
228160484Sobrien	case R_PPC_SDAREL16:
228260484Sobrien	case R_PPC_EMB_SDA2REL:
228360484Sobrien	case R_PPC_EMB_SDA21:
228460484Sobrien	  if (info->shared)
228560484Sobrien	    {
228660484Sobrien	      ((*_bfd_error_handler)
228760484Sobrien	       (_("%s: relocation %s cannot be used when making a shared object"),
228889857Sobrien		bfd_archive_filename (abfd),
228977298Sobrien		ppc_elf_howto_table[(int) ELF32_R_TYPE (rel->r_info)]->name));
229060484Sobrien	      return false;
229160484Sobrien	    }
229260484Sobrien	  break;
229360484Sobrien
229460484Sobrien	case R_PPC_PLT32:
229560484Sobrien	case R_PPC_PLTREL24:
229660484Sobrien	case R_PPC_PLT16_LO:
229760484Sobrien	case R_PPC_PLT16_HI:
229860484Sobrien	case R_PPC_PLT16_HA:
229960484Sobrien#ifdef DEBUG
230060484Sobrien	  fprintf (stderr, "Reloc requires a PLT entry\n");
230160484Sobrien#endif
230260484Sobrien	  /* This symbol requires a procedure linkage table entry.  We
230360484Sobrien             actually build the entry in adjust_dynamic_symbol,
230460484Sobrien             because this might be a case of linking PIC code without
230560484Sobrien             linking in any dynamic objects, in which case we don't
230660484Sobrien             need to generate a procedure linkage table after all.  */
230760484Sobrien
230860484Sobrien	  if (h == NULL)
230960484Sobrien	    {
231060484Sobrien	      /* It does not make sense to have a procedure linkage
231160484Sobrien                 table entry for a local symbol.  */
231260484Sobrien	      bfd_set_error (bfd_error_bad_value);
231360484Sobrien	      return false;
231460484Sobrien	    }
231560484Sobrien
231660484Sobrien	  /* Make sure this symbol is output as a dynamic symbol.  */
231760484Sobrien	  if (h->dynindx == -1)
231860484Sobrien	    {
231960484Sobrien	      if (! bfd_elf32_link_record_dynamic_symbol (info, h))
232060484Sobrien		return false;
232160484Sobrien	    }
232289857Sobrien	  h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
232389857Sobrien	  h->plt.refcount++;
232460484Sobrien	  break;
232560484Sobrien
232660484Sobrien	  /* The following relocations don't need to propagate the
232760484Sobrien	     relocation if linking a shared object since they are
232860484Sobrien	     section relative.  */
232960484Sobrien	case R_PPC_SECTOFF:
233060484Sobrien	case R_PPC_SECTOFF_LO:
233160484Sobrien	case R_PPC_SECTOFF_HI:
233260484Sobrien	case R_PPC_SECTOFF_HA:
233360484Sobrien	  break;
233460484Sobrien
233560484Sobrien	  /* This refers only to functions defined in the shared library */
233660484Sobrien	case R_PPC_LOCAL24PC:
233760484Sobrien	  break;
233860484Sobrien
233960484Sobrien	  /* This relocation describes the C++ object vtable hierarchy.
234060484Sobrien	     Reconstruct it for later use during GC.  */
234160484Sobrien	case R_PPC_GNU_VTINHERIT:
234260484Sobrien	  if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
234360484Sobrien	    return false;
234460484Sobrien	  break;
234560484Sobrien
234660484Sobrien	  /* This relocation describes which C++ vtable entries are actually
234760484Sobrien	     used.  Record for later use during GC.  */
234860484Sobrien	case R_PPC_GNU_VTENTRY:
234960484Sobrien	  if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
235060484Sobrien	    return false;
235160484Sobrien	  break;
235260484Sobrien
235360484Sobrien	  /* When creating a shared object, we must copy these
235460484Sobrien	     relocs into the output file.  We create a reloc
235560484Sobrien	     section in dynobj and make room for the reloc.  */
235660484Sobrien	case R_PPC_REL24:
235760484Sobrien	case R_PPC_REL14:
235860484Sobrien	case R_PPC_REL14_BRTAKEN:
235960484Sobrien	case R_PPC_REL14_BRNTAKEN:
236060484Sobrien	case R_PPC_REL32:
236160484Sobrien	  if (h == NULL
236277298Sobrien	      || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0
236377298Sobrien	      || SYMBOL_REFERENCES_LOCAL (info, h))
236460484Sobrien	    break;
236560484Sobrien	  /* fall through */
236660484Sobrien
236760484Sobrien	default:
236860484Sobrien	  if (info->shared)
236960484Sobrien	    {
237060484Sobrien#ifdef DEBUG
237160484Sobrien	      fprintf (stderr, "ppc_elf_check_relocs need to create relocation for %s\n",
237260484Sobrien		       (h && h->root.root.string) ? h->root.root.string : "<unknown>");
237360484Sobrien#endif
237460484Sobrien	      if (sreloc == NULL)
237560484Sobrien		{
237660484Sobrien		  const char *name;
237760484Sobrien
237860484Sobrien		  name = (bfd_elf_string_from_elf_section
237960484Sobrien			  (abfd,
238060484Sobrien			   elf_elfheader (abfd)->e_shstrndx,
238160484Sobrien			   elf_section_data (sec)->rel_hdr.sh_name));
238260484Sobrien		  if (name == NULL)
238360484Sobrien		    return false;
238460484Sobrien
238560484Sobrien		  BFD_ASSERT (strncmp (name, ".rela", 5) == 0
238660484Sobrien			      && strcmp (bfd_get_section_name (abfd, sec),
238760484Sobrien					 name + 5) == 0);
238860484Sobrien
238960484Sobrien		  sreloc = bfd_get_section_by_name (dynobj, name);
239060484Sobrien		  if (sreloc == NULL)
239160484Sobrien		    {
239260484Sobrien		      flagword flags;
239360484Sobrien
239460484Sobrien		      sreloc = bfd_make_section (dynobj, name);
239560484Sobrien		      flags = (SEC_HAS_CONTENTS | SEC_READONLY
239660484Sobrien			       | SEC_IN_MEMORY | SEC_LINKER_CREATED);
239760484Sobrien		      if ((sec->flags & SEC_ALLOC) != 0)
239860484Sobrien			flags |= SEC_ALLOC | SEC_LOAD;
239960484Sobrien		      if (sreloc == NULL
240060484Sobrien			  || ! bfd_set_section_flags (dynobj, sreloc, flags)
240160484Sobrien			  || ! bfd_set_section_alignment (dynobj, sreloc, 2))
240260484Sobrien			return false;
240360484Sobrien		    }
240489857Sobrien		  if (sec->flags & SEC_READONLY)
240589857Sobrien		    info->flags |= DF_TEXTREL;
240660484Sobrien		}
240760484Sobrien
240860484Sobrien	      sreloc->_raw_size += sizeof (Elf32_External_Rela);
240960484Sobrien
241060484Sobrien	      /* FIXME: We should here do what the m68k and i386
241160484Sobrien		 backends do: if the reloc is pc-relative, record it
241260484Sobrien		 in case it turns out that the reloc is unnecessary
241360484Sobrien		 because the symbol is forced local by versioning or
241460484Sobrien		 we are linking with -Bdynamic.  Fortunately this
241560484Sobrien		 case is not frequent.  */
241660484Sobrien	    }
241760484Sobrien
241860484Sobrien	  break;
241960484Sobrien	}
242060484Sobrien    }
242160484Sobrien
242260484Sobrien  return true;
242360484Sobrien}
242460484Sobrien
242560484Sobrien/* Return the section that should be marked against GC for a given
242660484Sobrien   relocation.  */
242760484Sobrien
242860484Sobrienstatic asection *
242960484Sobrienppc_elf_gc_mark_hook (abfd, info, rel, h, sym)
243060484Sobrien     bfd *abfd;
243160484Sobrien     struct bfd_link_info *info ATTRIBUTE_UNUSED;
243260484Sobrien     Elf_Internal_Rela *rel;
243360484Sobrien     struct elf_link_hash_entry *h;
243460484Sobrien     Elf_Internal_Sym *sym;
243560484Sobrien{
243660484Sobrien  if (h != NULL)
243760484Sobrien    {
243860484Sobrien      switch (ELF32_R_TYPE (rel->r_info))
243960484Sobrien	{
244060484Sobrien	case R_PPC_GNU_VTINHERIT:
244160484Sobrien	case R_PPC_GNU_VTENTRY:
244260484Sobrien	  break;
244360484Sobrien
244460484Sobrien	default:
244560484Sobrien	  switch (h->root.type)
244660484Sobrien	    {
244760484Sobrien	    case bfd_link_hash_defined:
244860484Sobrien	    case bfd_link_hash_defweak:
244960484Sobrien	      return h->root.u.def.section;
245060484Sobrien
245160484Sobrien	    case bfd_link_hash_common:
245260484Sobrien	      return h->root.u.c.p->section;
245360484Sobrien
245460484Sobrien	    default:
245560484Sobrien	      break;
245660484Sobrien	    }
245760484Sobrien	}
245860484Sobrien    }
245960484Sobrien  else
246060484Sobrien    {
246189857Sobrien      return bfd_section_from_elf_index (abfd, sym->st_shndx);
246260484Sobrien    }
246360484Sobrien
246460484Sobrien  return NULL;
246560484Sobrien}
246660484Sobrien
246760484Sobrien/* Update the got entry reference counts for the section being removed.  */
246860484Sobrien
246960484Sobrienstatic boolean
247060484Sobrienppc_elf_gc_sweep_hook (abfd, info, sec, relocs)
247160484Sobrien     bfd *abfd;
247260484Sobrien     struct bfd_link_info *info ATTRIBUTE_UNUSED;
247360484Sobrien     asection *sec;
247460484Sobrien     const Elf_Internal_Rela *relocs;
247560484Sobrien{
247660484Sobrien  Elf_Internal_Shdr *symtab_hdr;
247760484Sobrien  struct elf_link_hash_entry **sym_hashes;
247860484Sobrien  bfd_signed_vma *local_got_refcounts;
247960484Sobrien  const Elf_Internal_Rela *rel, *relend;
248060484Sobrien  unsigned long r_symndx;
248160484Sobrien  struct elf_link_hash_entry *h;
248260484Sobrien
248360484Sobrien  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
248460484Sobrien  sym_hashes = elf_sym_hashes (abfd);
248560484Sobrien  local_got_refcounts = elf_local_got_refcounts (abfd);
248660484Sobrien
248760484Sobrien  relend = relocs + sec->reloc_count;
248860484Sobrien  for (rel = relocs; rel < relend; rel++)
248960484Sobrien    switch (ELF32_R_TYPE (rel->r_info))
249060484Sobrien      {
249160484Sobrien      case R_PPC_GOT16:
249260484Sobrien      case R_PPC_GOT16_LO:
249360484Sobrien      case R_PPC_GOT16_HI:
249460484Sobrien      case R_PPC_GOT16_HA:
249560484Sobrien	r_symndx = ELF32_R_SYM (rel->r_info);
249660484Sobrien	if (r_symndx >= symtab_hdr->sh_info)
249760484Sobrien	  {
249860484Sobrien	    h = sym_hashes[r_symndx - symtab_hdr->sh_info];
249960484Sobrien	    if (h->got.refcount > 0)
250060484Sobrien	      h->got.refcount--;
250160484Sobrien	  }
250277298Sobrien	else if (local_got_refcounts != NULL)
250360484Sobrien	  {
250460484Sobrien	    if (local_got_refcounts[r_symndx] > 0)
250560484Sobrien	      local_got_refcounts[r_symndx]--;
250660484Sobrien	  }
250760484Sobrien        break;
250860484Sobrien
250960484Sobrien      case R_PPC_PLT32:
251060484Sobrien      case R_PPC_PLTREL24:
251160484Sobrien      case R_PPC_PLT16_LO:
251260484Sobrien      case R_PPC_PLT16_HI:
251360484Sobrien      case R_PPC_PLT16_HA:
251460484Sobrien	r_symndx = ELF32_R_SYM (rel->r_info);
251560484Sobrien	if (r_symndx >= symtab_hdr->sh_info)
251660484Sobrien	  {
251760484Sobrien	    h = sym_hashes[r_symndx - symtab_hdr->sh_info];
251860484Sobrien	    if (h->plt.refcount > 0)
251960484Sobrien	      h->plt.refcount--;
252060484Sobrien	  }
252160484Sobrien	break;
252260484Sobrien
252360484Sobrien      default:
252460484Sobrien	break;
252560484Sobrien      }
252660484Sobrien
252760484Sobrien  return true;
252860484Sobrien}
252960484Sobrien
253060484Sobrien/* Hook called by the linker routine which adds symbols from an object
253160484Sobrien   file.  We use it to put .comm items in .sbss, and not .bss.  */
253260484Sobrien
253360484Sobrienstatic boolean
253460484Sobrienppc_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
253560484Sobrien     bfd *abfd;
253660484Sobrien     struct bfd_link_info *info;
253760484Sobrien     const Elf_Internal_Sym *sym;
253860484Sobrien     const char **namep ATTRIBUTE_UNUSED;
253960484Sobrien     flagword *flagsp ATTRIBUTE_UNUSED;
254060484Sobrien     asection **secp;
254160484Sobrien     bfd_vma *valp;
254260484Sobrien{
254360484Sobrien  if (sym->st_shndx == SHN_COMMON
254460484Sobrien      && !info->relocateable
254589857Sobrien      && sym->st_size <= elf_gp_size (abfd))
254660484Sobrien    {
254760484Sobrien      /* Common symbols less than or equal to -G nn bytes are automatically
254860484Sobrien	 put into .sdata.  */
254960484Sobrien      elf_linker_section_t *sdata
255060484Sobrien	= ppc_elf_create_linker_section (abfd, info, LINKER_SECTION_SDATA);
255160484Sobrien
255260484Sobrien      if (!sdata->bss_section)
255360484Sobrien	{
255489857Sobrien	  bfd_size_type amt;
255589857Sobrien
255660484Sobrien	  /* We don't go through bfd_make_section, because we don't
255760484Sobrien             want to attach this common section to DYNOBJ.  The linker
255860484Sobrien             will move the symbols to the appropriate output section
255960484Sobrien             when it defines common symbols.  */
256089857Sobrien	  amt = sizeof (asection);
256189857Sobrien	  sdata->bss_section = (asection *) bfd_zalloc (abfd, amt);
256260484Sobrien	  if (sdata->bss_section == NULL)
256360484Sobrien	    return false;
256460484Sobrien	  sdata->bss_section->name = sdata->bss_name;
256560484Sobrien	  sdata->bss_section->flags = SEC_IS_COMMON;
256660484Sobrien	  sdata->bss_section->output_section = sdata->bss_section;
256789857Sobrien	  amt = sizeof (asymbol);
256889857Sobrien	  sdata->bss_section->symbol = (asymbol *) bfd_zalloc (abfd, amt);
256989857Sobrien	  amt = sizeof (asymbol *);
257060484Sobrien	  sdata->bss_section->symbol_ptr_ptr =
257189857Sobrien	    (asymbol **) bfd_zalloc (abfd, amt);
257260484Sobrien	  if (sdata->bss_section->symbol == NULL
257360484Sobrien	      || sdata->bss_section->symbol_ptr_ptr == NULL)
257460484Sobrien	    return false;
257560484Sobrien	  sdata->bss_section->symbol->name = sdata->bss_name;
257660484Sobrien	  sdata->bss_section->symbol->flags = BSF_SECTION_SYM;
257760484Sobrien	  sdata->bss_section->symbol->section = sdata->bss_section;
257860484Sobrien	  *sdata->bss_section->symbol_ptr_ptr = sdata->bss_section->symbol;
257960484Sobrien	}
258060484Sobrien
258160484Sobrien      *secp = sdata->bss_section;
258260484Sobrien      *valp = sym->st_size;
258360484Sobrien    }
258460484Sobrien
258560484Sobrien  return true;
258660484Sobrien}
258760484Sobrien
258860484Sobrien/* Finish up dynamic symbol handling.  We set the contents of various
258960484Sobrien   dynamic sections here.  */
259060484Sobrien
259160484Sobrienstatic boolean
259260484Sobrienppc_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
259360484Sobrien     bfd *output_bfd;
259460484Sobrien     struct bfd_link_info *info;
259560484Sobrien     struct elf_link_hash_entry *h;
259660484Sobrien     Elf_Internal_Sym *sym;
259760484Sobrien{
259860484Sobrien  bfd *dynobj;
259960484Sobrien
260060484Sobrien#ifdef DEBUG
260160484Sobrien  fprintf (stderr, "ppc_elf_finish_dynamic_symbol called for %s",
260260484Sobrien	   h->root.root.string);
260360484Sobrien#endif
260460484Sobrien
260560484Sobrien  dynobj = elf_hash_table (info)->dynobj;
260660484Sobrien  BFD_ASSERT (dynobj != NULL);
260760484Sobrien
260860484Sobrien  if (h->plt.offset != (bfd_vma) -1)
260960484Sobrien    {
261060484Sobrien      asection *splt;
261160484Sobrien      asection *srela;
261260484Sobrien      Elf_Internal_Rela rela;
261360484Sobrien      bfd_vma reloc_index;
261460484Sobrien
261560484Sobrien#ifdef DEBUG
261660484Sobrien      fprintf (stderr, ", plt_offset = %d", h->plt.offset);
261760484Sobrien#endif
261860484Sobrien
261960484Sobrien      /* This symbol has an entry in the procedure linkage table.  Set
262060484Sobrien         it up.  */
262160484Sobrien
262260484Sobrien      BFD_ASSERT (h->dynindx != -1);
262360484Sobrien
262460484Sobrien      splt = bfd_get_section_by_name (dynobj, ".plt");
262560484Sobrien      srela = bfd_get_section_by_name (dynobj, ".rela.plt");
262660484Sobrien      BFD_ASSERT (splt != NULL && srela != NULL);
262760484Sobrien
262860484Sobrien      /* We don't need to fill in the .plt.  The ppc dynamic linker
262960484Sobrien	 will fill it in.  */
263060484Sobrien
263160484Sobrien      /* Fill in the entry in the .rela.plt section.  */
263260484Sobrien      rela.r_offset = (splt->output_section->vma
263360484Sobrien		       + splt->output_offset
263460484Sobrien		       + h->plt.offset);
263560484Sobrien      rela.r_info = ELF32_R_INFO (h->dynindx, R_PPC_JMP_SLOT);
263660484Sobrien      rela.r_addend = 0;
263760484Sobrien
263860484Sobrien      reloc_index = (h->plt.offset - PLT_INITIAL_ENTRY_SIZE) / PLT_SLOT_SIZE;
263960484Sobrien      if (reloc_index > PLT_NUM_SINGLE_ENTRIES)
264060484Sobrien	reloc_index -= (reloc_index - PLT_NUM_SINGLE_ENTRIES) / 2;
264160484Sobrien      bfd_elf32_swap_reloca_out (output_bfd, &rela,
264260484Sobrien				 ((Elf32_External_Rela *) srela->contents
264360484Sobrien				  + reloc_index));
264460484Sobrien
264560484Sobrien      if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
264660484Sobrien	{
264760484Sobrien	  /* Mark the symbol as undefined, rather than as defined in
264860484Sobrien	     the .plt section.  Leave the value alone.  */
264960484Sobrien	  sym->st_shndx = SHN_UNDEF;
265068765Sobrien	  /* If the symbol is weak, we do need to clear the value.
265168765Sobrien	     Otherwise, the PLT entry would provide a definition for
265268765Sobrien	     the symbol even if the symbol wasn't defined anywhere,
265368765Sobrien	     and so the symbol would never be NULL.  */
265477298Sobrien	  if ((h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR_NONWEAK)
265568765Sobrien	      == 0)
265668765Sobrien	    sym->st_value = 0;
265760484Sobrien	}
265860484Sobrien    }
265960484Sobrien
266060484Sobrien  if (h->got.offset != (bfd_vma) -1)
266160484Sobrien    {
266260484Sobrien      asection *sgot;
266360484Sobrien      asection *srela;
266460484Sobrien      Elf_Internal_Rela rela;
266560484Sobrien
266660484Sobrien      /* This symbol has an entry in the global offset table.  Set it
266760484Sobrien         up.  */
266860484Sobrien
266960484Sobrien      sgot = bfd_get_section_by_name (dynobj, ".got");
267060484Sobrien      srela = bfd_get_section_by_name (dynobj, ".rela.got");
267160484Sobrien      BFD_ASSERT (sgot != NULL && srela != NULL);
267260484Sobrien
267360484Sobrien      rela.r_offset = (sgot->output_section->vma
267460484Sobrien		       + sgot->output_offset
267589857Sobrien		       + (h->got.offset &~ (bfd_vma) 1));
267660484Sobrien
267760484Sobrien      /* If this is a -Bsymbolic link, and the symbol is defined
267860484Sobrien	 locally, we just want to emit a RELATIVE reloc.  The entry in
267960484Sobrien	 the global offset table will already have been initialized in
268060484Sobrien	 the relocate_section function.  */
268160484Sobrien      if (info->shared
268277298Sobrien	  && SYMBOL_REFERENCES_LOCAL (info, h))
268360484Sobrien	{
268460484Sobrien	  rela.r_info = ELF32_R_INFO (0, R_PPC_RELATIVE);
268560484Sobrien	  rela.r_addend = (h->root.u.def.value
268660484Sobrien			   + h->root.u.def.section->output_section->vma
268760484Sobrien			   + h->root.u.def.section->output_offset);
268860484Sobrien	}
268960484Sobrien      else
269060484Sobrien	{
269177298Sobrien	  BFD_ASSERT ((h->got.offset & 1) == 0);
269260484Sobrien	  bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + h->got.offset);
269360484Sobrien	  rela.r_info = ELF32_R_INFO (h->dynindx, R_PPC_GLOB_DAT);
269460484Sobrien	  rela.r_addend = 0;
269560484Sobrien	}
269660484Sobrien
269760484Sobrien      bfd_elf32_swap_reloca_out (output_bfd, &rela,
269860484Sobrien				 ((Elf32_External_Rela *) srela->contents
269960484Sobrien				  + srela->reloc_count));
270060484Sobrien      ++srela->reloc_count;
270160484Sobrien    }
270260484Sobrien
270360484Sobrien  if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_COPY) != 0)
270460484Sobrien    {
270560484Sobrien      asection *s;
270660484Sobrien      Elf_Internal_Rela rela;
270760484Sobrien
270860484Sobrien      /* This symbols needs a copy reloc.  Set it up.  */
270960484Sobrien
271060484Sobrien#ifdef DEBUG
271160484Sobrien      fprintf (stderr, ", copy");
271260484Sobrien#endif
271360484Sobrien
271460484Sobrien      BFD_ASSERT (h->dynindx != -1);
271560484Sobrien
271660484Sobrien      if (h->size <= elf_gp_size (dynobj))
271760484Sobrien	s = bfd_get_section_by_name (h->root.u.def.section->owner,
271860484Sobrien				     ".rela.sbss");
271960484Sobrien      else
272060484Sobrien	s = bfd_get_section_by_name (h->root.u.def.section->owner,
272160484Sobrien				     ".rela.bss");
272260484Sobrien      BFD_ASSERT (s != NULL);
272360484Sobrien
272460484Sobrien      rela.r_offset = (h->root.u.def.value
272560484Sobrien		       + h->root.u.def.section->output_section->vma
272660484Sobrien		       + h->root.u.def.section->output_offset);
272760484Sobrien      rela.r_info = ELF32_R_INFO (h->dynindx, R_PPC_COPY);
272860484Sobrien      rela.r_addend = 0;
272960484Sobrien      bfd_elf32_swap_reloca_out (output_bfd, &rela,
273060484Sobrien				 ((Elf32_External_Rela *) s->contents
273160484Sobrien				  + s->reloc_count));
273260484Sobrien      ++s->reloc_count;
273360484Sobrien    }
273460484Sobrien
273560484Sobrien#ifdef DEBUG
273660484Sobrien  fprintf (stderr, "\n");
273760484Sobrien#endif
273860484Sobrien
273960484Sobrien  /* Mark some specially defined symbols as absolute.  */
274060484Sobrien  if (strcmp (h->root.root.string, "_DYNAMIC") == 0
274160484Sobrien      || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0
274260484Sobrien      || strcmp (h->root.root.string, "_PROCEDURE_LINKAGE_TABLE_") == 0)
274360484Sobrien    sym->st_shndx = SHN_ABS;
274460484Sobrien
274560484Sobrien  return true;
274660484Sobrien}
274760484Sobrien
274860484Sobrien/* Finish up the dynamic sections.  */
274960484Sobrien
275060484Sobrienstatic boolean
275160484Sobrienppc_elf_finish_dynamic_sections (output_bfd, info)
275260484Sobrien     bfd *output_bfd;
275360484Sobrien     struct bfd_link_info *info;
275460484Sobrien{
275560484Sobrien  asection *sdyn;
275660484Sobrien  bfd *dynobj = elf_hash_table (info)->dynobj;
275760484Sobrien  asection *sgot = bfd_get_section_by_name (dynobj, ".got");
275860484Sobrien
275960484Sobrien#ifdef DEBUG
276060484Sobrien  fprintf (stderr, "ppc_elf_finish_dynamic_sections called\n");
276160484Sobrien#endif
276260484Sobrien
276360484Sobrien  sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
276460484Sobrien
276560484Sobrien  if (elf_hash_table (info)->dynamic_sections_created)
276660484Sobrien    {
276760484Sobrien      asection *splt;
276860484Sobrien      Elf32_External_Dyn *dyncon, *dynconend;
276960484Sobrien
277060484Sobrien      splt = bfd_get_section_by_name (dynobj, ".plt");
277160484Sobrien      BFD_ASSERT (splt != NULL && sdyn != NULL);
277260484Sobrien
277360484Sobrien      dyncon = (Elf32_External_Dyn *) sdyn->contents;
277460484Sobrien      dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->_raw_size);
277560484Sobrien      for (; dyncon < dynconend; dyncon++)
277660484Sobrien	{
277760484Sobrien	  Elf_Internal_Dyn dyn;
277860484Sobrien	  const char *name;
277960484Sobrien	  boolean size;
278060484Sobrien
278160484Sobrien	  bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn);
278260484Sobrien
278360484Sobrien	  switch (dyn.d_tag)
278460484Sobrien	    {
278560484Sobrien	    case DT_PLTGOT:   name = ".plt";	  size = false; break;
278660484Sobrien	    case DT_PLTRELSZ: name = ".rela.plt"; size = true;  break;
278760484Sobrien	    case DT_JMPREL:   name = ".rela.plt"; size = false; break;
278860484Sobrien	    default:	      name = NULL;	  size = false; break;
278960484Sobrien	    }
279060484Sobrien
279160484Sobrien	  if (name != NULL)
279260484Sobrien	    {
279360484Sobrien	      asection *s;
279460484Sobrien
279560484Sobrien	      s = bfd_get_section_by_name (output_bfd, name);
279660484Sobrien	      if (s == NULL)
279760484Sobrien		dyn.d_un.d_val = 0;
279860484Sobrien	      else
279960484Sobrien		{
280060484Sobrien		  if (! size)
280160484Sobrien		    dyn.d_un.d_ptr = s->vma;
280260484Sobrien		  else
280360484Sobrien		    {
280460484Sobrien		      if (s->_cooked_size != 0)
280560484Sobrien			dyn.d_un.d_val = s->_cooked_size;
280660484Sobrien		      else
280760484Sobrien			dyn.d_un.d_val = s->_raw_size;
280860484Sobrien		    }
280960484Sobrien		}
281060484Sobrien	      bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
281160484Sobrien	    }
281260484Sobrien	}
281360484Sobrien    }
281460484Sobrien
281560484Sobrien  /* Add a blrl instruction at _GLOBAL_OFFSET_TABLE_-4 so that a function can
281660484Sobrien     easily find the address of the _GLOBAL_OFFSET_TABLE_.  */
281760484Sobrien  if (sgot)
281860484Sobrien    {
281960484Sobrien      unsigned char *contents = sgot->contents;
282089857Sobrien      bfd_put_32 (output_bfd, (bfd_vma) 0x4e800021 /* blrl */, contents);
282160484Sobrien
282260484Sobrien      if (sdyn == NULL)
282360484Sobrien	bfd_put_32 (output_bfd, (bfd_vma) 0, contents+4);
282460484Sobrien      else
282560484Sobrien	bfd_put_32 (output_bfd,
282660484Sobrien		    sdyn->output_section->vma + sdyn->output_offset,
282760484Sobrien		    contents+4);
282860484Sobrien
282960484Sobrien      elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4;
283060484Sobrien    }
283160484Sobrien
283260484Sobrien  return true;
283360484Sobrien}
283460484Sobrien
283560484Sobrien/* The RELOCATE_SECTION function is called by the ELF backend linker
283660484Sobrien   to handle the relocations for a section.
283760484Sobrien
283860484Sobrien   The relocs are always passed as Rela structures; if the section
283960484Sobrien   actually uses Rel structures, the r_addend field will always be
284060484Sobrien   zero.
284160484Sobrien
284260484Sobrien   This function is responsible for adjust the section contents as
284360484Sobrien   necessary, and (if using Rela relocs and generating a
284460484Sobrien   relocateable output file) adjusting the reloc addend as
284560484Sobrien   necessary.
284660484Sobrien
284760484Sobrien   This function does not have to worry about setting the reloc
284860484Sobrien   address or the reloc symbol index.
284960484Sobrien
285060484Sobrien   LOCAL_SYMS is a pointer to the swapped in local symbols.
285160484Sobrien
285260484Sobrien   LOCAL_SECTIONS is an array giving the section in the input file
285360484Sobrien   corresponding to the st_shndx field of each local symbol.
285460484Sobrien
285560484Sobrien   The global hash table entry for the global symbols can be found
285660484Sobrien   via elf_sym_hashes (input_bfd).
285760484Sobrien
285860484Sobrien   When generating relocateable output, this function must handle
285960484Sobrien   STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
286060484Sobrien   going to be the section symbol corresponding to the output
286160484Sobrien   section, which means that the addend must be adjusted
286260484Sobrien   accordingly.  */
286360484Sobrien
286460484Sobrienstatic boolean
286560484Sobrienppc_elf_relocate_section (output_bfd, info, input_bfd, input_section,
286660484Sobrien			  contents, relocs, local_syms, local_sections)
286760484Sobrien     bfd *output_bfd;
286860484Sobrien     struct bfd_link_info *info;
286960484Sobrien     bfd *input_bfd;
287060484Sobrien     asection *input_section;
287160484Sobrien     bfd_byte *contents;
287260484Sobrien     Elf_Internal_Rela *relocs;
287360484Sobrien     Elf_Internal_Sym *local_syms;
287460484Sobrien     asection **local_sections;
287560484Sobrien{
287660484Sobrien  Elf_Internal_Shdr *symtab_hdr		  = &elf_tdata (input_bfd)->symtab_hdr;
287760484Sobrien  struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (input_bfd);
287860484Sobrien  bfd *dynobj				  = elf_hash_table (info)->dynobj;
287960484Sobrien  elf_linker_section_t *sdata		  = (dynobj) ? elf_linker_section (dynobj, LINKER_SECTION_SDATA)  : NULL;
288060484Sobrien  elf_linker_section_t *sdata2		  = (dynobj) ? elf_linker_section (dynobj, LINKER_SECTION_SDATA2) : NULL;
288160484Sobrien  Elf_Internal_Rela *rel		  = relocs;
288260484Sobrien  Elf_Internal_Rela *relend		  = relocs + input_section->reloc_count;
288360484Sobrien  asection *sreloc			  = NULL;
288460484Sobrien  asection *splt;
288560484Sobrien  asection *sgot;
288660484Sobrien  bfd_vma *local_got_offsets;
288760484Sobrien  boolean ret				  = true;
288860484Sobrien  long insn;
288960484Sobrien
289060484Sobrien#ifdef DEBUG
289160484Sobrien  fprintf (stderr, "ppc_elf_relocate_section called for %s section %s, %ld relocations%s\n",
289289857Sobrien	   bfd_archive_filename (input_bfd),
289360484Sobrien	   bfd_section_name(input_bfd, input_section),
289477298Sobrien	   (long) input_section->reloc_count,
289560484Sobrien	   (info->relocateable) ? " (relocatable)" : "");
289660484Sobrien#endif
289760484Sobrien
289877298Sobrien  if (!ppc_elf_howto_table[R_PPC_ADDR32])
289977298Sobrien    /* Initialize howto table if needed.  */
290060484Sobrien    ppc_elf_howto_init ();
290160484Sobrien
290260484Sobrien  local_got_offsets = elf_local_got_offsets (input_bfd);
290360484Sobrien
290460484Sobrien  splt = sgot = NULL;
290560484Sobrien  if (dynobj != NULL)
290660484Sobrien    {
290760484Sobrien      splt = bfd_get_section_by_name (dynobj, ".plt");
290860484Sobrien      sgot = bfd_get_section_by_name (dynobj, ".got");
290960484Sobrien    }
291060484Sobrien
291160484Sobrien  for (; rel < relend; rel++)
291260484Sobrien    {
291360484Sobrien      enum elf_ppc_reloc_type r_type	= (enum elf_ppc_reloc_type)ELF32_R_TYPE (rel->r_info);
291460484Sobrien      bfd_vma offset			= rel->r_offset;
291560484Sobrien      bfd_vma addend			= rel->r_addend;
291660484Sobrien      bfd_reloc_status_type r		= bfd_reloc_other;
291777298Sobrien      Elf_Internal_Sym *sym		= (Elf_Internal_Sym *) 0;
291877298Sobrien      asection *sec			= (asection *) 0;
291977298Sobrien      struct elf_link_hash_entry *h	= (struct elf_link_hash_entry *) 0;
292077298Sobrien      const char *sym_name		= (const char *) 0;
292160484Sobrien      reloc_howto_type *howto;
292260484Sobrien      unsigned long r_symndx;
292360484Sobrien      bfd_vma relocation;
292477298Sobrien      int will_become_local;
292560484Sobrien
292660484Sobrien      /* Unknown relocation handling */
292777298Sobrien      if ((unsigned) r_type >= (unsigned) R_PPC_max
292877298Sobrien	  || !ppc_elf_howto_table[(int) r_type])
292960484Sobrien	{
293060484Sobrien	  (*_bfd_error_handler) (_("%s: unknown relocation type %d"),
293189857Sobrien				 bfd_archive_filename (input_bfd),
293277298Sobrien				 (int) r_type);
293360484Sobrien
293460484Sobrien	  bfd_set_error (bfd_error_bad_value);
293560484Sobrien	  ret = false;
293660484Sobrien	  continue;
293760484Sobrien	}
293860484Sobrien
293977298Sobrien      howto = ppc_elf_howto_table[(int) r_type];
294060484Sobrien      r_symndx = ELF32_R_SYM (rel->r_info);
294160484Sobrien
294260484Sobrien      if (info->relocateable)
294360484Sobrien	{
294460484Sobrien	  /* This is a relocateable link.  We don't have to change
294560484Sobrien	     anything, unless the reloc is against a section symbol,
294660484Sobrien	     in which case we have to adjust according to where the
294760484Sobrien	     section symbol winds up in the output section.  */
294860484Sobrien	  if (r_symndx < symtab_hdr->sh_info)
294960484Sobrien	    {
295060484Sobrien	      sym = local_syms + r_symndx;
295177298Sobrien	      if ((unsigned) ELF_ST_TYPE (sym->st_info) == STT_SECTION)
295260484Sobrien		{
295360484Sobrien		  sec = local_sections[r_symndx];
295460484Sobrien		  addend = rel->r_addend += sec->output_offset + sym->st_value;
295560484Sobrien		}
295660484Sobrien	    }
295760484Sobrien
295860484Sobrien#ifdef DEBUG
295960484Sobrien	  fprintf (stderr, "\ttype = %s (%d), symbol index = %ld, offset = %ld, addend = %ld\n",
296060484Sobrien		   howto->name,
296177298Sobrien		   (int) r_type,
296260484Sobrien		   r_symndx,
296377298Sobrien		   (long) offset,
296477298Sobrien		   (long) addend);
296560484Sobrien#endif
296660484Sobrien	  continue;
296760484Sobrien	}
296860484Sobrien
296960484Sobrien      /* This is a final link.  */
297060484Sobrien      if (r_symndx < symtab_hdr->sh_info)
297160484Sobrien	{
297260484Sobrien	  sym = local_syms + r_symndx;
297360484Sobrien	  sec = local_sections[r_symndx];
297460484Sobrien	  sym_name = "<local symbol>";
297560484Sobrien
297689857Sobrien	  relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel);
297789857Sobrien	  addend = rel->r_addend;
297877298Sobrien	  /* Relocs to local symbols are always resolved.  */
297977298Sobrien	  will_become_local = 1;
298060484Sobrien	}
298160484Sobrien      else
298260484Sobrien	{
298360484Sobrien	  h = sym_hashes[r_symndx - symtab_hdr->sh_info];
298460484Sobrien	  while (h->root.type == bfd_link_hash_indirect
298560484Sobrien		 || h->root.type == bfd_link_hash_warning)
298660484Sobrien	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
298760484Sobrien	  sym_name = h->root.root.string;
298877298Sobrien
298977298Sobrien	  /* Can this relocation be resolved immediately?  */
299077298Sobrien	  will_become_local = SYMBOL_REFERENCES_LOCAL (info, h);
299177298Sobrien
299260484Sobrien	  if (h->root.type == bfd_link_hash_defined
299360484Sobrien	      || h->root.type == bfd_link_hash_defweak)
299460484Sobrien	    {
299560484Sobrien	      sec = h->root.u.def.section;
299677298Sobrien	      if (((r_type == R_PPC_PLT32
299777298Sobrien		    || r_type == R_PPC_PLTREL24)
299877298Sobrien		   && splt != NULL
299960484Sobrien		   && h->plt.offset != (bfd_vma) -1)
300060484Sobrien		  || (r_type == R_PPC_LOCAL24PC
300160484Sobrien		      && sec->output_section == NULL)
300260484Sobrien		  || ((r_type == R_PPC_GOT16
300360484Sobrien		       || r_type == R_PPC_GOT16_LO
300460484Sobrien		       || r_type == R_PPC_GOT16_HI
300560484Sobrien		       || r_type == R_PPC_GOT16_HA)
300660484Sobrien		      && elf_hash_table (info)->dynamic_sections_created
300777298Sobrien		      && (! info->shared || ! will_become_local))
300860484Sobrien		  || (info->shared
300977298Sobrien 		      && ! will_become_local
301060484Sobrien		      && ((input_section->flags & SEC_ALLOC) != 0
301160484Sobrien			  /* Testing SEC_DEBUGGING here may be wrong.
301260484Sobrien                             It's here to avoid a crash when
301360484Sobrien                             generating a shared library with DWARF
301460484Sobrien                             debugging information.  */
301577298Sobrien			  || ((input_section->flags & SEC_DEBUGGING) != 0
301677298Sobrien			      && (h->elf_link_hash_flags
301777298Sobrien				  & ELF_LINK_HASH_DEF_DYNAMIC) != 0))
301860484Sobrien		      && (r_type == R_PPC_ADDR32
301960484Sobrien			  || r_type == R_PPC_ADDR24
302060484Sobrien			  || r_type == R_PPC_ADDR16
302160484Sobrien			  || r_type == R_PPC_ADDR16_LO
302260484Sobrien			  || r_type == R_PPC_ADDR16_HI
302360484Sobrien			  || r_type == R_PPC_ADDR16_HA
302460484Sobrien			  || r_type == R_PPC_ADDR14
302560484Sobrien			  || r_type == R_PPC_ADDR14_BRTAKEN
302660484Sobrien			  || r_type == R_PPC_ADDR14_BRNTAKEN
302760484Sobrien			  || r_type == R_PPC_COPY
302860484Sobrien			  || r_type == R_PPC_GLOB_DAT
302960484Sobrien			  || r_type == R_PPC_JMP_SLOT
303060484Sobrien			  || r_type == R_PPC_UADDR32
303160484Sobrien			  || r_type == R_PPC_UADDR16
303260484Sobrien			  || r_type == R_PPC_SDAREL16
303360484Sobrien			  || r_type == R_PPC_EMB_NADDR32
303460484Sobrien			  || r_type == R_PPC_EMB_NADDR16
303560484Sobrien			  || r_type == R_PPC_EMB_NADDR16_LO
303660484Sobrien			  || r_type == R_PPC_EMB_NADDR16_HI
303760484Sobrien			  || r_type == R_PPC_EMB_NADDR16_HA
303860484Sobrien			  || r_type == R_PPC_EMB_SDAI16
303960484Sobrien			  || r_type == R_PPC_EMB_SDA2I16
304060484Sobrien			  || r_type == R_PPC_EMB_SDA2REL
304160484Sobrien			  || r_type == R_PPC_EMB_SDA21
304260484Sobrien			  || r_type == R_PPC_EMB_MRKREF
304360484Sobrien			  || r_type == R_PPC_EMB_BIT_FLD
304460484Sobrien			  || r_type == R_PPC_EMB_RELSDA
304560484Sobrien			  || ((r_type == R_PPC_REL24
304660484Sobrien			       || r_type == R_PPC_REL32
304760484Sobrien			       || r_type == R_PPC_REL14
304860484Sobrien			       || r_type == R_PPC_REL14_BRTAKEN
304960484Sobrien			       || r_type == R_PPC_REL14_BRNTAKEN
305060484Sobrien			       || r_type == R_PPC_RELATIVE)
305160484Sobrien			      && strcmp (h->root.root.string,
305260484Sobrien					 "_GLOBAL_OFFSET_TABLE_") != 0))))
305360484Sobrien		{
305460484Sobrien		  /* In these cases, we don't need the relocation
305560484Sobrien                     value.  We check specially because in some
305660484Sobrien                     obscure cases sec->output_section will be NULL.  */
305760484Sobrien		  relocation = 0;
305860484Sobrien		}
305960484Sobrien	      else if (sec->output_section == NULL)
306077298Sobrien		{
306160484Sobrien                  (*_bfd_error_handler)
306260484Sobrien                    (_("%s: warning: unresolvable relocation against symbol `%s' from %s section"),
306389857Sobrien                     bfd_archive_filename (input_bfd), h->root.root.string,
306460484Sobrien                     bfd_get_section_name (input_bfd, input_section));
306560484Sobrien		  relocation = 0;
306677298Sobrien		}
306760484Sobrien	      else
306860484Sobrien		relocation = (h->root.u.def.value
306960484Sobrien			      + sec->output_section->vma
307060484Sobrien			      + sec->output_offset);
307160484Sobrien	    }
307260484Sobrien	  else if (h->root.type == bfd_link_hash_undefweak)
307360484Sobrien	    relocation = 0;
307489857Sobrien	  else if (info->shared
307589857Sobrien		   && (!info->symbolic || info->allow_shlib_undefined)
307689857Sobrien		   && !info->no_undefined
307768765Sobrien		   && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
307860484Sobrien	    relocation = 0;
307960484Sobrien	  else
308060484Sobrien	    {
308177298Sobrien	      if (! (*info->callbacks->undefined_symbol) (info,
308260484Sobrien							 h->root.root.string,
308360484Sobrien							 input_bfd,
308460484Sobrien							 input_section,
308560484Sobrien							 rel->r_offset,
308660484Sobrien							 (!info->shared
308768765Sobrien							  || info->no_undefined
308868765Sobrien							  || ELF_ST_VISIBILITY (h->other))))
308960484Sobrien		return false;
309060484Sobrien	      relocation = 0;
309160484Sobrien	    }
309260484Sobrien	}
309360484Sobrien
309477298Sobrien      switch ((int) r_type)
309560484Sobrien	{
309660484Sobrien	default:
309760484Sobrien	  (*_bfd_error_handler) (_("%s: unknown relocation type %d for symbol %s"),
309889857Sobrien				 bfd_archive_filename (input_bfd),
309977298Sobrien				 (int) r_type, sym_name);
310060484Sobrien
310160484Sobrien	  bfd_set_error (bfd_error_bad_value);
310260484Sobrien	  ret = false;
310360484Sobrien	  continue;
310460484Sobrien
310589857Sobrien	case (int) R_PPC_NONE:
310689857Sobrien	  continue;
310789857Sobrien
310860484Sobrien	/* Relocations that need no special processing.  */
310977298Sobrien	case (int) R_PPC_LOCAL24PC:
311060484Sobrien	  /* It makes no sense to point a local relocation
311160484Sobrien	     at a symbol not in this object.  */
311260484Sobrien	  if (h != NULL
311360484Sobrien	      && (h->root.type == bfd_link_hash_defined
311460484Sobrien		  || h->root.type == bfd_link_hash_defweak)
311560484Sobrien	      && sec->output_section == NULL)
311660484Sobrien	    {
311760484Sobrien	      if (! (*info->callbacks->undefined_symbol) (info,
311860484Sobrien							  h->root.root.string,
311960484Sobrien							  input_bfd,
312060484Sobrien							  input_section,
312160484Sobrien							  rel->r_offset,
312260484Sobrien							  true))
312360484Sobrien		return false;
312460484Sobrien	      continue;
312560484Sobrien	    }
312660484Sobrien	  break;
312760484Sobrien
312860484Sobrien	/* Relocations that may need to be propagated if this is a shared
312960484Sobrien           object.  */
313077298Sobrien	case (int) R_PPC_REL24:
313177298Sobrien	case (int) R_PPC_REL32:
313277298Sobrien	case (int) R_PPC_REL14:
313360484Sobrien	  /* If these relocations are not to a named symbol, they can be
313460484Sobrien	     handled right here, no need to bother the dynamic linker.  */
313560484Sobrien	  if (h == NULL
313677298Sobrien	      || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0
313777298Sobrien	      || SYMBOL_REFERENCES_LOCAL (info, h))
313860484Sobrien	    break;
313960484Sobrien	/* fall through */
314060484Sobrien
314160484Sobrien	/* Relocations that always need to be propagated if this is a shared
314260484Sobrien           object.  */
314377298Sobrien	case (int) R_PPC_ADDR32:
314477298Sobrien	case (int) R_PPC_ADDR24:
314577298Sobrien	case (int) R_PPC_ADDR16:
314677298Sobrien	case (int) R_PPC_ADDR16_LO:
314777298Sobrien	case (int) R_PPC_ADDR16_HI:
314877298Sobrien	case (int) R_PPC_ADDR16_HA:
314977298Sobrien	case (int) R_PPC_ADDR14:
315077298Sobrien	case (int) R_PPC_UADDR32:
315177298Sobrien	case (int) R_PPC_UADDR16:
315289857Sobrien	  if (info->shared && r_symndx != 0)
315360484Sobrien	    {
315460484Sobrien	      Elf_Internal_Rela outrel;
315560484Sobrien	      boolean skip;
315660484Sobrien
315760484Sobrien#ifdef DEBUG
315860484Sobrien	      fprintf (stderr, "ppc_elf_relocate_section need to create relocation for %s\n",
315960484Sobrien		       (h && h->root.root.string) ? h->root.root.string : "<unknown>");
316060484Sobrien#endif
316160484Sobrien
316260484Sobrien	      /* When generating a shared object, these relocations
316360484Sobrien                 are copied into the output file to be resolved at run
316460484Sobrien                 time.  */
316560484Sobrien
316660484Sobrien	      if (sreloc == NULL)
316760484Sobrien		{
316860484Sobrien		  const char *name;
316960484Sobrien
317060484Sobrien		  name = (bfd_elf_string_from_elf_section
317160484Sobrien			  (input_bfd,
317260484Sobrien			   elf_elfheader (input_bfd)->e_shstrndx,
317360484Sobrien			   elf_section_data (input_section)->rel_hdr.sh_name));
317460484Sobrien		  if (name == NULL)
317560484Sobrien		    return false;
317660484Sobrien
317760484Sobrien		  BFD_ASSERT (strncmp (name, ".rela", 5) == 0
317860484Sobrien			      && strcmp (bfd_get_section_name (input_bfd,
317960484Sobrien							       input_section),
318060484Sobrien					 name + 5) == 0);
318160484Sobrien
318260484Sobrien		  sreloc = bfd_get_section_by_name (dynobj, name);
318360484Sobrien		  BFD_ASSERT (sreloc != NULL);
318460484Sobrien		}
318560484Sobrien
318660484Sobrien	      skip = false;
318760484Sobrien
318889857Sobrien	      outrel.r_offset =
318989857Sobrien		_bfd_elf_section_offset (output_bfd, info, input_section,
319089857Sobrien					 rel->r_offset);
319189857Sobrien	      if (outrel.r_offset == (bfd_vma) -1)
319289857Sobrien		skip = true;
319360484Sobrien	      outrel.r_offset += (input_section->output_section->vma
319460484Sobrien				  + input_section->output_offset);
319560484Sobrien
319660484Sobrien	      if (skip)
319760484Sobrien		memset (&outrel, 0, sizeof outrel);
319860484Sobrien	      /* h->dynindx may be -1 if this symbol was marked to
319960484Sobrien                 become local.  */
320077298Sobrien	      else if (! will_become_local)
320160484Sobrien		{
320260484Sobrien		  outrel.r_info = ELF32_R_INFO (h->dynindx, r_type);
320360484Sobrien		  outrel.r_addend = rel->r_addend;
320460484Sobrien		}
320560484Sobrien	      else
320660484Sobrien		{
320760484Sobrien		  if (r_type == R_PPC_ADDR32)
320860484Sobrien		    {
320960484Sobrien		      outrel.r_info = ELF32_R_INFO (0, R_PPC_RELATIVE);
321060484Sobrien		      outrel.r_addend = relocation + rel->r_addend;
321160484Sobrien		    }
321260484Sobrien		  else
321360484Sobrien		    {
321460484Sobrien		      long indx;
321560484Sobrien
321660484Sobrien		      if (h == NULL)
321760484Sobrien			sec = local_sections[r_symndx];
321860484Sobrien		      else
321960484Sobrien			{
322060484Sobrien			  BFD_ASSERT (h->root.type == bfd_link_hash_defined
322160484Sobrien				      || (h->root.type
322260484Sobrien					  == bfd_link_hash_defweak));
322360484Sobrien			  sec = h->root.u.def.section;
322460484Sobrien			}
322560484Sobrien		      if (sec != NULL && bfd_is_abs_section (sec))
322660484Sobrien			indx = 0;
322760484Sobrien		      else if (sec == NULL || sec->owner == NULL)
322860484Sobrien			{
322960484Sobrien			  bfd_set_error (bfd_error_bad_value);
323060484Sobrien			  return false;
323160484Sobrien			}
323260484Sobrien		      else
323360484Sobrien			{
323460484Sobrien			  asection *osec;
323560484Sobrien
323660484Sobrien			  osec = sec->output_section;
323760484Sobrien			  indx = elf_section_data (osec)->dynindx;
323877298Sobrien			  BFD_ASSERT (indx > 0);
323960484Sobrien#ifdef DEBUG
324060484Sobrien			  if (indx <= 0)
324160484Sobrien			    {
324277298Sobrien			      printf ("indx=%d section=%s flags=%08x name=%s\n",
324360484Sobrien				     indx, osec->name, osec->flags,
324460484Sobrien				     h->root.root.string);
324560484Sobrien			    }
324660484Sobrien#endif
324760484Sobrien			}
324860484Sobrien
324960484Sobrien		      outrel.r_info = ELF32_R_INFO (indx, r_type);
325060484Sobrien		      outrel.r_addend = relocation + rel->r_addend;
325160484Sobrien		    }
325260484Sobrien		}
325360484Sobrien
325460484Sobrien	      bfd_elf32_swap_reloca_out (output_bfd, &outrel,
325560484Sobrien					 (((Elf32_External_Rela *)
325660484Sobrien					   sreloc->contents)
325760484Sobrien					  + sreloc->reloc_count));
325860484Sobrien	      ++sreloc->reloc_count;
325960484Sobrien
326060484Sobrien	      /* This reloc will be computed at runtime, so there's no
326160484Sobrien                 need to do anything now, unless this is a RELATIVE
326260484Sobrien                 reloc in an unallocated section.  */
326360484Sobrien	      if (skip
326460484Sobrien		  || (input_section->flags & SEC_ALLOC) != 0
326560484Sobrien		  || ELF32_R_TYPE (outrel.r_info) != R_PPC_RELATIVE)
326660484Sobrien		continue;
326760484Sobrien	    }
326860484Sobrien
326960484Sobrien	  /* Arithmetic adjust relocations that aren't going into a
327060484Sobrien	     shared object.  */
327160484Sobrien	  if (r_type == R_PPC_ADDR16_HA
327260484Sobrien	      /* It's just possible that this symbol is a weak symbol
327360484Sobrien		 that's not actually defined anywhere. In that case,
327460484Sobrien		 'sec' would be NULL, and we should leave the symbol
327560484Sobrien		 alone (it will be set to zero elsewhere in the link).  */
327660484Sobrien	      && sec != NULL)
327760484Sobrien	    {
327860484Sobrien	      addend += ((relocation + addend) & 0x8000) << 1;
327960484Sobrien	    }
328060484Sobrien	  break;
328160484Sobrien
328260484Sobrien	/* branch taken prediction relocations */
328377298Sobrien	case (int) R_PPC_ADDR14_BRTAKEN:
328477298Sobrien	case (int) R_PPC_REL14_BRTAKEN:
328560484Sobrien	  insn = bfd_get_32 (output_bfd, contents + offset);
328660484Sobrien	  if ((relocation - offset) & 0x8000)
328760484Sobrien	    insn &= ~BRANCH_PREDICT_BIT;
328860484Sobrien	  else
328960484Sobrien	    insn |= BRANCH_PREDICT_BIT;
329089857Sobrien	  bfd_put_32 (output_bfd, (bfd_vma) insn, contents + offset);
329160484Sobrien	  break;
329260484Sobrien
329360484Sobrien	/* branch not taken predicition relocations */
329477298Sobrien	case (int) R_PPC_ADDR14_BRNTAKEN:
329577298Sobrien	case (int) R_PPC_REL14_BRNTAKEN:
329660484Sobrien	  insn = bfd_get_32 (output_bfd, contents + offset);
329760484Sobrien	  if ((relocation - offset) & 0x8000)
329860484Sobrien	    insn |= BRANCH_PREDICT_BIT;
329960484Sobrien	  else
330060484Sobrien	    insn &= ~BRANCH_PREDICT_BIT;
330189857Sobrien	  bfd_put_32 (output_bfd, (bfd_vma) insn, contents + offset);
330260484Sobrien	  break;
330360484Sobrien
330460484Sobrien	/* GOT16 relocations */
330577298Sobrien	case (int) R_PPC_GOT16:
330677298Sobrien	case (int) R_PPC_GOT16_LO:
330777298Sobrien	case (int) R_PPC_GOT16_HI:
330877298Sobrien	case (int) R_PPC_GOT16_HA:
330960484Sobrien	  /* Relocation is to the entry for this symbol in the global
331060484Sobrien             offset table.  */
331160484Sobrien	  BFD_ASSERT (sgot != NULL);
331260484Sobrien
331360484Sobrien	  if (h != NULL)
331460484Sobrien	    {
331560484Sobrien	      bfd_vma off;
331660484Sobrien
331760484Sobrien	      off = h->got.offset;
331860484Sobrien	      BFD_ASSERT (off != (bfd_vma) -1);
331960484Sobrien
332060484Sobrien	      if (! elf_hash_table (info)->dynamic_sections_created
332160484Sobrien		  || (info->shared
332277298Sobrien		      && SYMBOL_REFERENCES_LOCAL (info, h)))
332360484Sobrien		{
332460484Sobrien		  /* This is actually a static link, or it is a
332560484Sobrien                     -Bsymbolic link and the symbol is defined
332660484Sobrien                     locally.  We must initialize this entry in the
332760484Sobrien                     global offset table.  Since the offset must
332860484Sobrien                     always be a multiple of 4, we use the least
332960484Sobrien                     significant bit to record whether we have
333060484Sobrien                     initialized it already.
333160484Sobrien
333260484Sobrien		     When doing a dynamic link, we create a .rela.got
333360484Sobrien		     relocation entry to initialize the value.  This
333460484Sobrien		     is done in the finish_dynamic_symbol routine.  */
333560484Sobrien		  if ((off & 1) != 0)
333660484Sobrien		    off &= ~1;
333760484Sobrien		  else
333860484Sobrien		    {
333960484Sobrien		      bfd_put_32 (output_bfd, relocation,
334060484Sobrien				  sgot->contents + off);
334160484Sobrien		      h->got.offset |= 1;
334260484Sobrien		    }
334360484Sobrien		}
334460484Sobrien
334560484Sobrien	      relocation = sgot->output_offset + off - 4;
334660484Sobrien	    }
334760484Sobrien	  else
334860484Sobrien	    {
334960484Sobrien	      bfd_vma off;
335060484Sobrien
335160484Sobrien	      BFD_ASSERT (local_got_offsets != NULL
335260484Sobrien			  && local_got_offsets[r_symndx] != (bfd_vma) -1);
335360484Sobrien
335460484Sobrien	      off = local_got_offsets[r_symndx];
335560484Sobrien
335660484Sobrien	      /* The offset must always be a multiple of 4.  We use
335760484Sobrien		 the least significant bit to record whether we have
335860484Sobrien		 already processed this entry.  */
335960484Sobrien	      if ((off & 1) != 0)
336060484Sobrien		off &= ~1;
336160484Sobrien	      else
336260484Sobrien		{
336360484Sobrien		  bfd_put_32 (output_bfd, relocation, sgot->contents + off);
336460484Sobrien
336560484Sobrien		  if (info->shared)
336660484Sobrien		    {
336760484Sobrien		      asection *srelgot;
336860484Sobrien		      Elf_Internal_Rela outrel;
336960484Sobrien
337060484Sobrien		      /* We need to generate a R_PPC_RELATIVE reloc
337160484Sobrien			 for the dynamic linker.  */
337260484Sobrien		      srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
337360484Sobrien		      BFD_ASSERT (srelgot != NULL);
337460484Sobrien
337560484Sobrien		      outrel.r_offset = (sgot->output_section->vma
337660484Sobrien					 + sgot->output_offset
337760484Sobrien					 + off);
337860484Sobrien		      outrel.r_info = ELF32_R_INFO (0, R_PPC_RELATIVE);
337960484Sobrien		      outrel.r_addend = relocation;
338060484Sobrien		      bfd_elf32_swap_reloca_out (output_bfd, &outrel,
338160484Sobrien						 (((Elf32_External_Rela *)
338260484Sobrien						   srelgot->contents)
338360484Sobrien						  + srelgot->reloc_count));
338460484Sobrien		      ++srelgot->reloc_count;
338560484Sobrien		    }
338660484Sobrien
338760484Sobrien		  local_got_offsets[r_symndx] |= 1;
338860484Sobrien		}
338960484Sobrien
339060484Sobrien	      relocation = sgot->output_offset + off - 4;
339160484Sobrien	    }
339260484Sobrien	  break;
339360484Sobrien
339460484Sobrien	/* Indirect .sdata relocation */
339577298Sobrien	case (int) R_PPC_EMB_SDAI16:
339660484Sobrien	  BFD_ASSERT (sdata != NULL);
339760484Sobrien	  relocation = bfd_elf32_finish_pointer_linker_section (output_bfd, input_bfd, info,
339860484Sobrien								sdata, h, relocation, rel,
339960484Sobrien								R_PPC_RELATIVE);
340060484Sobrien	  break;
340160484Sobrien
340260484Sobrien	/* Indirect .sdata2 relocation */
340377298Sobrien	case (int) R_PPC_EMB_SDA2I16:
340460484Sobrien	  BFD_ASSERT (sdata2 != NULL);
340560484Sobrien	  relocation = bfd_elf32_finish_pointer_linker_section (output_bfd, input_bfd, info,
340660484Sobrien								sdata2, h, relocation, rel,
340760484Sobrien								R_PPC_RELATIVE);
340860484Sobrien	  break;
340960484Sobrien
341060484Sobrien	/* Handle the TOC16 reloc.  We want to use the offset within the .got
341160484Sobrien	   section, not the actual VMA.  This is appropriate when generating
341260484Sobrien	   an embedded ELF object, for which the .got section acts like the
341360484Sobrien	   AIX .toc section.  */
341477298Sobrien	case (int) R_PPC_TOC16:			/* phony GOT16 relocations */
341577298Sobrien	  BFD_ASSERT (sec != (asection *) 0);
341660484Sobrien	  BFD_ASSERT (bfd_is_und_section (sec)
341760484Sobrien		      || strcmp (bfd_get_section_name (abfd, sec), ".got") == 0
341860484Sobrien		      || strcmp (bfd_get_section_name (abfd, sec), ".cgot") == 0)
341960484Sobrien
342060484Sobrien	  addend -= sec->output_section->vma + sec->output_offset + 0x8000;
342160484Sobrien	  break;
342260484Sobrien
342377298Sobrien	case (int) R_PPC_PLTREL24:
342460484Sobrien	  /* Relocation is to the entry for this symbol in the
342560484Sobrien             procedure linkage table.  */
342660484Sobrien	  BFD_ASSERT (h != NULL);
342760484Sobrien
342860484Sobrien	  if (h->plt.offset == (bfd_vma) -1
342960484Sobrien	      || splt == NULL)
343060484Sobrien	    {
343160484Sobrien	      /* We didn't make a PLT entry for this symbol.  This
343260484Sobrien                 happens when statically linking PIC code, or when
343360484Sobrien                 using -Bsymbolic.  */
343460484Sobrien	      break;
343560484Sobrien	    }
343660484Sobrien
343760484Sobrien	  relocation = (splt->output_section->vma
343860484Sobrien			+ splt->output_offset
343960484Sobrien			+ h->plt.offset);
344077298Sobrien	  break;
344160484Sobrien
344260484Sobrien	/* relocate against _SDA_BASE_ */
344377298Sobrien	case (int) R_PPC_SDAREL16:
344460484Sobrien	  {
344560484Sobrien	    const char *name;
344660484Sobrien
344777298Sobrien	    BFD_ASSERT (sec != (asection *) 0);
344860484Sobrien	    name = bfd_get_section_name (abfd, sec->output_section);
344960484Sobrien	    if (strcmp (name, ".sdata") != 0
345060484Sobrien		&& strcmp (name, ".sbss") != 0)
345160484Sobrien	      {
345260484Sobrien		(*_bfd_error_handler) (_("%s: The target (%s) of a %s relocation is in the wrong output section (%s)"),
345389857Sobrien				       bfd_archive_filename (input_bfd),
345460484Sobrien				       sym_name,
345577298Sobrien				       ppc_elf_howto_table[(int) r_type]->name,
345660484Sobrien				       name);
345760484Sobrien	      }
345860484Sobrien	    addend -= (sdata->sym_hash->root.u.def.value
345960484Sobrien		       + sdata->sym_hash->root.u.def.section->output_section->vma
346060484Sobrien		       + sdata->sym_hash->root.u.def.section->output_offset);
346160484Sobrien	  }
346260484Sobrien	  break;
346360484Sobrien
346460484Sobrien	/* relocate against _SDA2_BASE_ */
346577298Sobrien	case (int) R_PPC_EMB_SDA2REL:
346660484Sobrien	  {
346760484Sobrien	    const char *name;
346860484Sobrien
346977298Sobrien	    BFD_ASSERT (sec != (asection *) 0);
347060484Sobrien	    name = bfd_get_section_name (abfd, sec->output_section);
347160484Sobrien	    if (strcmp (name, ".sdata2") != 0 && strcmp (name, ".sbss2") != 0)
347260484Sobrien	      {
347360484Sobrien		(*_bfd_error_handler) (_("%s: The target (%s) of a %s relocation is in the wrong output section (%s)"),
347489857Sobrien				       bfd_archive_filename (input_bfd),
347560484Sobrien				       sym_name,
347677298Sobrien				       ppc_elf_howto_table[(int) r_type]->name,
347760484Sobrien				       name);
347877298Sobrien
347960484Sobrien		bfd_set_error (bfd_error_bad_value);
348060484Sobrien		ret = false;
348160484Sobrien		continue;
348260484Sobrien	      }
348360484Sobrien	    addend -= (sdata2->sym_hash->root.u.def.value
348460484Sobrien		       + sdata2->sym_hash->root.u.def.section->output_section->vma
348560484Sobrien		       + sdata2->sym_hash->root.u.def.section->output_offset);
348660484Sobrien	  }
348760484Sobrien	  break;
348860484Sobrien
348960484Sobrien	/* relocate against either _SDA_BASE_, _SDA2_BASE_, or 0 */
349077298Sobrien	case (int) R_PPC_EMB_SDA21:
349177298Sobrien	case (int) R_PPC_EMB_RELSDA:
349260484Sobrien	  {
349360484Sobrien	    const char *name;
349460484Sobrien	    int reg;
349560484Sobrien
349677298Sobrien	    BFD_ASSERT (sec != (asection *) 0);
349760484Sobrien	    name = bfd_get_section_name (abfd, sec->output_section);
349860484Sobrien	    if (strcmp (name, ".sdata") == 0 || strcmp (name, ".sbss") == 0)
349960484Sobrien	      {
350060484Sobrien		reg = 13;
350160484Sobrien		addend -= (sdata->sym_hash->root.u.def.value
350260484Sobrien			   + sdata->sym_hash->root.u.def.section->output_section->vma
350360484Sobrien			   + sdata->sym_hash->root.u.def.section->output_offset);
350460484Sobrien	      }
350560484Sobrien
350677298Sobrien	    else if (strcmp (name, ".sdata2") == 0
350777298Sobrien		     || strcmp (name, ".sbss2") == 0)
350860484Sobrien	      {
350960484Sobrien		reg = 2;
351060484Sobrien		addend -= (sdata2->sym_hash->root.u.def.value
351160484Sobrien			   + sdata2->sym_hash->root.u.def.section->output_section->vma
351260484Sobrien			   + sdata2->sym_hash->root.u.def.section->output_offset);
351360484Sobrien	      }
351460484Sobrien
351577298Sobrien	    else if (strcmp (name, ".PPC.EMB.sdata0") == 0
351677298Sobrien		     || strcmp (name, ".PPC.EMB.sbss0") == 0)
351760484Sobrien	      {
351860484Sobrien		reg = 0;
351960484Sobrien	      }
352060484Sobrien
352160484Sobrien	    else
352260484Sobrien	      {
352360484Sobrien		(*_bfd_error_handler) (_("%s: The target (%s) of a %s relocation is in the wrong output section (%s)"),
352489857Sobrien				       bfd_archive_filename (input_bfd),
352560484Sobrien				       sym_name,
352677298Sobrien				       ppc_elf_howto_table[(int) r_type]->name,
352760484Sobrien				       name);
352860484Sobrien
352960484Sobrien		bfd_set_error (bfd_error_bad_value);
353060484Sobrien		ret = false;
353160484Sobrien		continue;
353260484Sobrien	      }
353360484Sobrien
353460484Sobrien	    if (r_type == R_PPC_EMB_SDA21)
353560484Sobrien	      {			/* fill in register field */
353660484Sobrien		insn = bfd_get_32 (output_bfd, contents + offset);
353760484Sobrien		insn = (insn & ~RA_REGISTER_MASK) | (reg << RA_REGISTER_SHIFT);
353889857Sobrien		bfd_put_32 (output_bfd, (bfd_vma) insn, contents + offset);
353960484Sobrien	      }
354060484Sobrien	  }
354160484Sobrien	  break;
354260484Sobrien
354360484Sobrien	/* Relocate against the beginning of the section */
354477298Sobrien	case (int) R_PPC_SECTOFF:
354577298Sobrien	case (int) R_PPC_SECTOFF_LO:
354677298Sobrien	case (int) R_PPC_SECTOFF_HI:
354777298Sobrien	  BFD_ASSERT (sec != (asection *) 0);
354860484Sobrien	  addend -= sec->output_section->vma;
354960484Sobrien	  break;
355060484Sobrien
355177298Sobrien	case (int) R_PPC_SECTOFF_HA:
355277298Sobrien	  BFD_ASSERT (sec != (asection *) 0);
355360484Sobrien	  addend -= sec->output_section->vma;
355460484Sobrien	  addend += ((relocation + addend) & 0x8000) << 1;
355560484Sobrien	  break;
355660484Sobrien
355760484Sobrien	/* Negative relocations */
355877298Sobrien	case (int) R_PPC_EMB_NADDR32:
355977298Sobrien	case (int) R_PPC_EMB_NADDR16:
356077298Sobrien	case (int) R_PPC_EMB_NADDR16_LO:
356177298Sobrien	case (int) R_PPC_EMB_NADDR16_HI:
356277298Sobrien	  addend -= 2 * relocation;
356360484Sobrien	  break;
356460484Sobrien
356577298Sobrien	case (int) R_PPC_EMB_NADDR16_HA:
356677298Sobrien	  addend -= 2 * relocation;
356760484Sobrien	  addend += ((relocation + addend) & 0x8000) << 1;
356860484Sobrien	  break;
356960484Sobrien
357060484Sobrien	/* NOP relocation that prevents garbage collecting linkers from omitting a
357160484Sobrien	   reference.  */
357277298Sobrien	case (int) R_PPC_EMB_MRKREF:
357360484Sobrien	  continue;
357460484Sobrien
357577298Sobrien	case (int) R_PPC_COPY:
357677298Sobrien	case (int) R_PPC_GLOB_DAT:
357777298Sobrien	case (int) R_PPC_JMP_SLOT:
357877298Sobrien	case (int) R_PPC_RELATIVE:
357977298Sobrien	case (int) R_PPC_PLT32:
358077298Sobrien	case (int) R_PPC_PLTREL32:
358177298Sobrien	case (int) R_PPC_PLT16_LO:
358277298Sobrien	case (int) R_PPC_PLT16_HI:
358377298Sobrien	case (int) R_PPC_PLT16_HA:
358477298Sobrien	case (int) R_PPC_EMB_RELSEC16:
358577298Sobrien	case (int) R_PPC_EMB_RELST_LO:
358677298Sobrien	case (int) R_PPC_EMB_RELST_HI:
358777298Sobrien	case (int) R_PPC_EMB_RELST_HA:
358877298Sobrien	case (int) R_PPC_EMB_BIT_FLD:
358960484Sobrien	  (*_bfd_error_handler) (_("%s: Relocation %s is not yet supported for symbol %s."),
359089857Sobrien				 bfd_archive_filename (input_bfd),
359177298Sobrien				 ppc_elf_howto_table[(int) r_type]->name,
359260484Sobrien				 sym_name);
359360484Sobrien
359460484Sobrien	  bfd_set_error (bfd_error_invalid_operation);
359560484Sobrien	  ret = false;
359660484Sobrien	  continue;
359760484Sobrien
359877298Sobrien	case (int) R_PPC_GNU_VTINHERIT:
359977298Sobrien	case (int) R_PPC_GNU_VTENTRY:
360060484Sobrien	  /* These are no-ops in the end.  */
360160484Sobrien	  continue;
360260484Sobrien	}
360360484Sobrien
360460484Sobrien#ifdef DEBUG
360560484Sobrien      fprintf (stderr, "\ttype = %s (%d), name = %s, symbol index = %ld, offset = %ld, addend = %ld\n",
360660484Sobrien	       howto->name,
360777298Sobrien	       (int) r_type,
360860484Sobrien	       sym_name,
360960484Sobrien	       r_symndx,
361077298Sobrien	       (long) offset,
361177298Sobrien	       (long) addend);
361260484Sobrien#endif
361360484Sobrien
361460484Sobrien      r = _bfd_final_link_relocate (howto,
361560484Sobrien				    input_bfd,
361660484Sobrien				    input_section,
361760484Sobrien				    contents,
361860484Sobrien				    offset,
361960484Sobrien				    relocation,
362060484Sobrien				    addend);
362160484Sobrien
362260484Sobrien      if (r == bfd_reloc_ok)
362360484Sobrien	;
362460484Sobrien      else if (r == bfd_reloc_overflow)
362560484Sobrien	{
362660484Sobrien	  const char *name;
362760484Sobrien
362860484Sobrien	  if (h != NULL)
362960484Sobrien	    {
363060484Sobrien	      if (h->root.type == bfd_link_hash_undefweak
363160484Sobrien		  && howto->pc_relative)
363260484Sobrien		{
363360484Sobrien		  /* Assume this is a call protected by other code that
363460484Sobrien		     detect the symbol is undefined.  If this is the case,
363560484Sobrien		     we can safely ignore the overflow.  If not, the
363660484Sobrien		     program is hosed anyway, and a little warning isn't
363760484Sobrien		     going to help.  */
363860484Sobrien
363960484Sobrien		  continue;
364060484Sobrien		}
364160484Sobrien
364260484Sobrien	      name = h->root.root.string;
364360484Sobrien	    }
364460484Sobrien	  else
364560484Sobrien	    {
364660484Sobrien	      name = bfd_elf_string_from_elf_section (input_bfd,
364760484Sobrien						      symtab_hdr->sh_link,
364860484Sobrien						      sym->st_name);
364960484Sobrien	      if (name == NULL)
365060484Sobrien		continue;
365160484Sobrien	      if (*name == '\0')
365260484Sobrien		name = bfd_section_name (input_bfd, sec);
365360484Sobrien	    }
365460484Sobrien
365577298Sobrien	  if (! (*info->callbacks->reloc_overflow) (info,
365660484Sobrien						   name,
365760484Sobrien						   howto->name,
365860484Sobrien						   (bfd_vma) 0,
365960484Sobrien						   input_bfd,
366060484Sobrien						   input_section,
366160484Sobrien						   offset))
366260484Sobrien	    return false;
366360484Sobrien	}
366460484Sobrien      else
366560484Sobrien	ret = false;
366660484Sobrien    }
366760484Sobrien
366860484Sobrien#ifdef DEBUG
366960484Sobrien  fprintf (stderr, "\n");
367060484Sobrien#endif
367160484Sobrien
367260484Sobrien  return ret;
367360484Sobrien}
367489857Sobrien
367589857Sobrienstatic enum elf_reloc_type_class
367689857Sobrienppc_elf_reloc_type_class (rela)
367789857Sobrien     const Elf_Internal_Rela *rela;
367889857Sobrien{
367989857Sobrien  switch ((int) ELF32_R_TYPE (rela->r_info))
368089857Sobrien    {
368189857Sobrien    case R_PPC_RELATIVE:
368289857Sobrien      return reloc_class_relative;
368389857Sobrien    case R_PPC_REL24:
368489857Sobrien    case R_PPC_ADDR24:
368589857Sobrien    case R_PPC_JMP_SLOT:
368689857Sobrien      return reloc_class_plt;
368789857Sobrien    case R_PPC_COPY:
368889857Sobrien      return reloc_class_copy;
368989857Sobrien    default:
369089857Sobrien      return reloc_class_normal;
369189857Sobrien    }
369289857Sobrien}
369360484Sobrien
369489857Sobrien/* Support for core dump NOTE sections */
369589857Sobrienstatic boolean
369689857Sobrienppc_elf_grok_prstatus (abfd, note)
369789857Sobrien     bfd *abfd;
369889857Sobrien     Elf_Internal_Note *note;
369989857Sobrien{
370089857Sobrien  int offset;
370189857Sobrien  unsigned int raw_size;
370289857Sobrien
370389857Sobrien  switch (note->descsz)
370489857Sobrien    {
370589857Sobrien      default:
370689857Sobrien	return false;
370789857Sobrien
370889857Sobrien      case 268:		/* Linux/PPC */
370989857Sobrien	/* pr_cursig */
371089857Sobrien	elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12);
371189857Sobrien
371289857Sobrien	/* pr_pid */
371389857Sobrien	elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, note->descdata + 24);
371489857Sobrien
371589857Sobrien	/* pr_reg */
371689857Sobrien	offset = 72;
371789857Sobrien	raw_size = 192;
371889857Sobrien
371989857Sobrien	break;
372089857Sobrien    }
372189857Sobrien
372289857Sobrien  /* Make a ".reg/999" section.  */
372389857Sobrien  return _bfd_elfcore_make_pseudosection (abfd, ".reg",
372489857Sobrien					  raw_size, note->descpos + offset);
372589857Sobrien}
372689857Sobrien
372789857Sobrienstatic boolean
372889857Sobrienppc_elf_grok_psinfo (abfd, note)
372989857Sobrien     bfd *abfd;
373089857Sobrien     Elf_Internal_Note *note;
373189857Sobrien{
373289857Sobrien  switch (note->descsz)
373389857Sobrien    {
373489857Sobrien      default:
373589857Sobrien	return false;
373689857Sobrien
373789857Sobrien      case 128:		/* Linux/PPC elf_prpsinfo */
373889857Sobrien	elf_tdata (abfd)->core_program
373989857Sobrien	 = _bfd_elfcore_strndup (abfd, note->descdata + 32, 16);
374089857Sobrien	elf_tdata (abfd)->core_command
374189857Sobrien	 = _bfd_elfcore_strndup (abfd, note->descdata + 48, 80);
374289857Sobrien    }
374389857Sobrien
374489857Sobrien  /* Note that for some reason, a spurious space is tacked
374589857Sobrien     onto the end of the args in some (at least one anyway)
374689857Sobrien     implementations, so strip it off if it exists.  */
374789857Sobrien
374889857Sobrien  {
374989857Sobrien    char *command = elf_tdata (abfd)->core_command;
375089857Sobrien    int n = strlen (command);
375189857Sobrien
375289857Sobrien    if (0 < n && command[n - 1] == ' ')
375389857Sobrien      command[n - 1] = '\0';
375489857Sobrien  }
375589857Sobrien
375689857Sobrien  return true;
375789857Sobrien}
375889857Sobrien
375960484Sobrien#define TARGET_LITTLE_SYM	bfd_elf32_powerpcle_vec
376060484Sobrien#define TARGET_LITTLE_NAME	"elf32-powerpcle"
376160484Sobrien#define TARGET_BIG_SYM		bfd_elf32_powerpc_vec
376260484Sobrien#define TARGET_BIG_NAME		"elf32-powerpc"
376360484Sobrien#define ELF_ARCH		bfd_arch_powerpc
376460484Sobrien#define ELF_MACHINE_CODE	EM_PPC
376560484Sobrien#define ELF_MAXPAGESIZE		0x10000
376660484Sobrien#define elf_info_to_howto	ppc_elf_info_to_howto
376760484Sobrien
376860484Sobrien#ifdef  EM_CYGNUS_POWERPC
376960484Sobrien#define ELF_MACHINE_ALT1	EM_CYGNUS_POWERPC
377060484Sobrien#endif
377160484Sobrien
377260484Sobrien#ifdef EM_PPC_OLD
377360484Sobrien#define ELF_MACHINE_ALT2	EM_PPC_OLD
377460484Sobrien#endif
377560484Sobrien
377660484Sobrien#define elf_backend_plt_not_loaded	1
377760484Sobrien#define elf_backend_got_symbol_offset	4
377860484Sobrien#define elf_backend_can_gc_sections	1
377989857Sobrien#define elf_backend_can_refcount	1
378060484Sobrien#define elf_backend_got_header_size	12
378160484Sobrien#define elf_backend_plt_header_size	PLT_INITIAL_ENTRY_SIZE
378260484Sobrien
378360484Sobrien#define bfd_elf32_bfd_merge_private_bfd_data	ppc_elf_merge_private_bfd_data
378460484Sobrien#define bfd_elf32_bfd_relax_section             ppc_elf_relax_section
378560484Sobrien#define bfd_elf32_bfd_reloc_type_lookup		ppc_elf_reloc_type_lookup
378660484Sobrien#define bfd_elf32_bfd_set_private_flags		ppc_elf_set_private_flags
378760484Sobrien#define bfd_elf32_bfd_final_link		_bfd_elf32_gc_common_final_link
378860484Sobrien
378960484Sobrien#define elf_backend_gc_mark_hook		ppc_elf_gc_mark_hook
379060484Sobrien#define elf_backend_gc_sweep_hook		ppc_elf_gc_sweep_hook
379160484Sobrien#define elf_backend_section_from_shdr		ppc_elf_section_from_shdr
379260484Sobrien#define elf_backend_relocate_section		ppc_elf_relocate_section
379360484Sobrien#define elf_backend_create_dynamic_sections	ppc_elf_create_dynamic_sections
379460484Sobrien#define elf_backend_check_relocs		ppc_elf_check_relocs
379560484Sobrien#define elf_backend_adjust_dynamic_symbol	ppc_elf_adjust_dynamic_symbol
379660484Sobrien#define elf_backend_add_symbol_hook		ppc_elf_add_symbol_hook
379760484Sobrien#define elf_backend_size_dynamic_sections	ppc_elf_size_dynamic_sections
379860484Sobrien#define elf_backend_finish_dynamic_symbol	ppc_elf_finish_dynamic_symbol
379960484Sobrien#define elf_backend_finish_dynamic_sections	ppc_elf_finish_dynamic_sections
380060484Sobrien#define elf_backend_fake_sections		ppc_elf_fake_sections
380160484Sobrien#define elf_backend_additional_program_headers	ppc_elf_additional_program_headers
380260484Sobrien#define elf_backend_modify_segment_map		ppc_elf_modify_segment_map
380389857Sobrien#define elf_backend_grok_prstatus		ppc_elf_grok_prstatus
380489857Sobrien#define elf_backend_grok_psinfo			ppc_elf_grok_psinfo
380589857Sobrien#define elf_backend_reloc_type_class		ppc_elf_reloc_type_class
380660484Sobrien
380760484Sobrien#include "elf32-target.h"
3808