elf32-ppc.c revision 77298
160484Sobrien/* PowerPC-specific support for 32-bit ELF
260484Sobrien   Copyright 1994, 95, 96, 97, 98, 1999 Free Software Foundation, Inc.
360484Sobrien   Written by Ian Lance Taylor, Cygnus Support.
460484Sobrien
560484SobrienThis file is part of BFD, the Binary File Descriptor library.
660484Sobrien
760484SobrienThis program is free software; you can redistribute it and/or modify
860484Sobrienit under the terms of the GNU General Public License as published by
960484Sobrienthe Free Software Foundation; either version 2 of the License, or
1060484Sobrien(at your option) any later version.
1160484Sobrien
1260484SobrienThis program is distributed in the hope that it will be useful,
1360484Sobrienbut WITHOUT ANY WARRANTY; without even the implied warranty of
1460484SobrienMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1560484SobrienGNU General Public License for more details.
1660484Sobrien
1760484SobrienYou should have received a copy of the GNU General Public License
1860484Sobrienalong with this program; if not, write to the Free Software
1960484SobrienFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
2060484Sobrien
2160484Sobrien/* This file is based on a preliminary PowerPC ELF ABI.  The
2260484Sobrien   information may not match the final PowerPC ELF ABI.  It includes
2360484Sobrien   suggestions from the in-progress Embedded PowerPC ABI, and that
2460484Sobrien   information may also not match.  */
2560484Sobrien
2660484Sobrien#include "bfd.h"
2760484Sobrien#include "sysdep.h"
2860484Sobrien#include "bfdlink.h"
2960484Sobrien#include "libbfd.h"
3060484Sobrien#include "elf-bfd.h"
3160484Sobrien#include "elf/ppc.h"
3260484Sobrien
3360484Sobrien#define USE_RELA		/* we want RELA relocations, not REL */
3460484Sobrien
3560484Sobrienstatic reloc_howto_type *ppc_elf_reloc_type_lookup
3660484Sobrien  PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
3760484Sobrienstatic void ppc_elf_info_to_howto
3860484Sobrien  PARAMS ((bfd *abfd, arelent *cache_ptr, Elf32_Internal_Rela *dst));
3960484Sobrienstatic void ppc_elf_howto_init PARAMS ((void));
4060484Sobrienstatic bfd_reloc_status_type ppc_elf_addr16_ha_reloc
4160484Sobrien  PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
4260484Sobrienstatic boolean ppc_elf_set_private_flags PARAMS ((bfd *, flagword));
4360484Sobrienstatic boolean ppc_elf_copy_private_bfd_data PARAMS ((bfd *, bfd *));
4460484Sobrienstatic boolean ppc_elf_merge_private_bfd_data PARAMS ((bfd *, bfd *));
4560484Sobrien
4660484Sobrienstatic int ppc_elf_additional_program_headers PARAMS ((bfd *));
4760484Sobrienstatic boolean ppc_elf_modify_segment_map PARAMS ((bfd *));
4860484Sobrien
4960484Sobrienstatic boolean ppc_elf_create_dynamic_sections
5060484Sobrien  PARAMS ((bfd *, struct bfd_link_info *));
5160484Sobrien
5260484Sobrienstatic boolean ppc_elf_section_from_shdr PARAMS ((bfd *,
5360484Sobrien						  Elf32_Internal_Shdr *,
5460484Sobrien						  char *));
5560484Sobrienstatic boolean ppc_elf_fake_sections
5660484Sobrien  PARAMS ((bfd *, Elf32_Internal_Shdr *, asection *));
5760484Sobrien
5860484Sobrienstatic elf_linker_section_t *ppc_elf_create_linker_section
5960484Sobrien  PARAMS ((bfd *abfd,
6060484Sobrien	   struct bfd_link_info *info,
6160484Sobrien	   enum elf_linker_section_enum));
6260484Sobrien
6360484Sobrienstatic boolean ppc_elf_check_relocs PARAMS ((bfd *,
6460484Sobrien					     struct bfd_link_info *,
6560484Sobrien					     asection *,
6660484Sobrien					     const Elf_Internal_Rela *));
6760484Sobrien
6860484Sobrienstatic asection * ppc_elf_gc_mark_hook PARAMS ((bfd *abfd,
6960484Sobrien						struct bfd_link_info *info,
7060484Sobrien						Elf_Internal_Rela *rel,
7160484Sobrien						struct elf_link_hash_entry *h,
7260484Sobrien						Elf_Internal_Sym *sym));
7360484Sobrien
7460484Sobrienstatic boolean ppc_elf_gc_sweep_hook PARAMS ((bfd *abfd,
7560484Sobrien					      struct bfd_link_info *info,
7660484Sobrien					      asection *sec,
7760484Sobrien					      const Elf_Internal_Rela *relocs));
7860484Sobrien
7960484Sobrienstatic boolean ppc_elf_adjust_dynamic_symbol PARAMS ((struct bfd_link_info *,
8060484Sobrien						      struct elf_link_hash_entry *));
8160484Sobrien
8260484Sobrienstatic boolean ppc_elf_size_dynamic_sections PARAMS ((bfd *, struct bfd_link_info *));
8360484Sobrien
8460484Sobrienstatic boolean ppc_elf_relocate_section PARAMS ((bfd *,
8560484Sobrien						 struct bfd_link_info *info,
8660484Sobrien						 bfd *,
8760484Sobrien						 asection *,
8860484Sobrien						 bfd_byte *,
8960484Sobrien						 Elf_Internal_Rela *relocs,
9060484Sobrien						 Elf_Internal_Sym *local_syms,
9160484Sobrien						 asection **));
9260484Sobrien
9360484Sobrienstatic boolean ppc_elf_add_symbol_hook  PARAMS ((bfd *,
9460484Sobrien						 struct bfd_link_info *,
9560484Sobrien						 const Elf_Internal_Sym *,
9660484Sobrien						 const char **,
9760484Sobrien						 flagword *,
9860484Sobrien						 asection **,
9960484Sobrien						 bfd_vma *));
10060484Sobrien
10160484Sobrienstatic boolean ppc_elf_finish_dynamic_symbol PARAMS ((bfd *,
10260484Sobrien						      struct bfd_link_info *,
10360484Sobrien						      struct elf_link_hash_entry *,
10460484Sobrien						      Elf_Internal_Sym *));
10560484Sobrien
10660484Sobrienstatic boolean ppc_elf_finish_dynamic_sections PARAMS ((bfd *, struct bfd_link_info *));
10760484Sobrien
10860484Sobrien#define BRANCH_PREDICT_BIT 0x200000		/* branch prediction bit for branch taken relocs */
10960484Sobrien#define RA_REGISTER_MASK 0x001f0000		/* mask to set RA in memory instructions */
11060484Sobrien#define RA_REGISTER_SHIFT 16			/* value to shift register by to insert RA */
11160484Sobrien
11260484Sobrien/* The name of the dynamic interpreter.  This is put in the .interp
11360484Sobrien   section.  */
11460484Sobrien
11560484Sobrien#define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1"
11660484Sobrien
11760484Sobrien/* The size in bytes of an entry in the procedure linkage table.  */
11860484Sobrien#define PLT_ENTRY_SIZE 12
11960484Sobrien/* The initial size of the plt reserved for the dynamic linker.  */
12060484Sobrien#define PLT_INITIAL_ENTRY_SIZE 72
12160484Sobrien/* The size of the gap between entries in the PLT.  */
12260484Sobrien#define PLT_SLOT_SIZE 8
12360484Sobrien/* The number of single-slot PLT entries (the rest use two slots).  */
12460484Sobrien#define PLT_NUM_SINGLE_ENTRIES 8192
12560484Sobrien
12677298Sobrien/* Will references to this symbol always reference the symbol
12777298Sobrien   in this object?  */
12877298Sobrien#define SYMBOL_REFERENCES_LOCAL(INFO, H)				\
12977298Sobrien  ((! INFO->shared							\
13077298Sobrien    || INFO->symbolic							\
13177298Sobrien    || H->dynindx == -1							\
13277298Sobrien    || ELF_ST_VISIBILITY (H->other) == STV_INTERNAL			\
13377298Sobrien    || ELF_ST_VISIBILITY (H->other) == STV_HIDDEN)			\
13477298Sobrien   && (H->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0)
13577298Sobrien
13677298Sobrien/* Will _calls_ to this symbol always call the version in this object?  */
13777298Sobrien#define SYMBOL_CALLS_LOCAL(INFO, H)				\
13877298Sobrien  ((! INFO->shared							\
13977298Sobrien    || INFO->symbolic							\
14077298Sobrien    || H->dynindx == -1							\
14177298Sobrien    || ELF_ST_VISIBILITY (H->other) != STV_DEFAULT)			\
14277298Sobrien   && (H->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0)
14360484Sobrien
14477298Sobrienstatic reloc_howto_type *ppc_elf_howto_table[(int) R_PPC_max];
14560484Sobrien
14677298Sobrienstatic reloc_howto_type ppc_elf_howto_raw[] = {
14760484Sobrien  /* This reloc does nothing.  */
14860484Sobrien  HOWTO (R_PPC_NONE,		/* type */
14960484Sobrien	 0,			/* rightshift */
15060484Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
15160484Sobrien	 32,			/* bitsize */
15260484Sobrien	 false,			/* pc_relative */
15360484Sobrien	 0,			/* bitpos */
15460484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
15560484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
15660484Sobrien	 "R_PPC_NONE",		/* name */
15760484Sobrien	 false,			/* partial_inplace */
15860484Sobrien	 0,			/* src_mask */
15960484Sobrien	 0,			/* dst_mask */
16060484Sobrien	 false),		/* pcrel_offset */
16160484Sobrien
16260484Sobrien  /* A standard 32 bit relocation.  */
16360484Sobrien  HOWTO (R_PPC_ADDR32,		/* type */
16460484Sobrien	 0,			/* rightshift */
16560484Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
16660484Sobrien	 32,			/* bitsize */
16760484Sobrien	 false,			/* pc_relative */
16860484Sobrien	 0,			/* bitpos */
16960484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
17060484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
17160484Sobrien	 "R_PPC_ADDR32",	/* name */
17260484Sobrien	 false,			/* partial_inplace */
17360484Sobrien	 0,			/* src_mask */
17460484Sobrien	 0xffffffff,		/* dst_mask */
17560484Sobrien	 false),		/* pcrel_offset */
17660484Sobrien
17760484Sobrien  /* An absolute 26 bit branch; the lower two bits must be zero.
17860484Sobrien     FIXME: we don't check that, we just clear them.  */
17960484Sobrien  HOWTO (R_PPC_ADDR24,		/* type */
18060484Sobrien	 0,			/* rightshift */
18160484Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
18260484Sobrien	 26,			/* bitsize */
18360484Sobrien	 false,			/* pc_relative */
18460484Sobrien	 0,			/* bitpos */
18560484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
18660484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
18760484Sobrien	 "R_PPC_ADDR24",	/* name */
18860484Sobrien	 false,			/* partial_inplace */
18960484Sobrien	 0,			/* src_mask */
19060484Sobrien	 0x3fffffc,		/* dst_mask */
19160484Sobrien	 false),		/* pcrel_offset */
19260484Sobrien
19360484Sobrien  /* A standard 16 bit relocation.  */
19460484Sobrien  HOWTO (R_PPC_ADDR16,		/* type */
19560484Sobrien	 0,			/* rightshift */
19660484Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
19760484Sobrien	 16,			/* bitsize */
19860484Sobrien	 false,			/* pc_relative */
19960484Sobrien	 0,			/* bitpos */
20060484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
20160484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
20260484Sobrien	 "R_PPC_ADDR16",	/* name */
20360484Sobrien	 false,			/* partial_inplace */
20460484Sobrien	 0,			/* src_mask */
20560484Sobrien	 0xffff,		/* dst_mask */
20660484Sobrien	 false),		/* pcrel_offset */
20760484Sobrien
20860484Sobrien  /* A 16 bit relocation without overflow.  */
20960484Sobrien  HOWTO (R_PPC_ADDR16_LO,	/* type */
21060484Sobrien	 0,			/* rightshift */
21160484Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
21260484Sobrien	 16,			/* bitsize */
21360484Sobrien	 false,			/* pc_relative */
21460484Sobrien	 0,			/* bitpos */
21560484Sobrien	 complain_overflow_dont,/* complain_on_overflow */
21660484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
21760484Sobrien	 "R_PPC_ADDR16_LO",	/* name */
21860484Sobrien	 false,			/* partial_inplace */
21960484Sobrien	 0,			/* src_mask */
22060484Sobrien	 0xffff,		/* dst_mask */
22160484Sobrien	 false),		/* pcrel_offset */
22260484Sobrien
22360484Sobrien  /* The high order 16 bits of an address.  */
22460484Sobrien  HOWTO (R_PPC_ADDR16_HI,	/* type */
22560484Sobrien	 16,			/* rightshift */
22660484Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
22760484Sobrien	 16,			/* bitsize */
22860484Sobrien	 false,			/* pc_relative */
22960484Sobrien	 0,			/* bitpos */
23060484Sobrien	 complain_overflow_dont, /* complain_on_overflow */
23160484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
23260484Sobrien	 "R_PPC_ADDR16_HI",	/* name */
23360484Sobrien	 false,			/* partial_inplace */
23460484Sobrien	 0,			/* src_mask */
23560484Sobrien	 0xffff,		/* dst_mask */
23660484Sobrien	 false),		/* pcrel_offset */
23760484Sobrien
23860484Sobrien  /* The high order 16 bits of an address, plus 1 if the contents of
23977298Sobrien     the low 16 bits, treated as a signed number, is negative.  */
24060484Sobrien  HOWTO (R_PPC_ADDR16_HA,	/* type */
24160484Sobrien	 16,			/* rightshift */
24260484Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
24360484Sobrien	 16,			/* bitsize */
24460484Sobrien	 false,			/* pc_relative */
24560484Sobrien	 0,			/* bitpos */
24660484Sobrien	 complain_overflow_dont, /* complain_on_overflow */
24760484Sobrien	 ppc_elf_addr16_ha_reloc, /* special_function */
24860484Sobrien	 "R_PPC_ADDR16_HA",	/* name */
24960484Sobrien	 false,			/* partial_inplace */
25060484Sobrien	 0,			/* src_mask */
25160484Sobrien	 0xffff,		/* dst_mask */
25260484Sobrien	 false),		/* pcrel_offset */
25360484Sobrien
25460484Sobrien  /* An absolute 16 bit branch; the lower two bits must be zero.
25560484Sobrien     FIXME: we don't check that, we just clear them.  */
25660484Sobrien  HOWTO (R_PPC_ADDR14,		/* type */
25760484Sobrien	 0,			/* rightshift */
25860484Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
25960484Sobrien	 16,			/* bitsize */
26060484Sobrien	 false,			/* pc_relative */
26160484Sobrien	 0,			/* bitpos */
26260484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
26360484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
26460484Sobrien	 "R_PPC_ADDR14",	/* name */
26560484Sobrien	 false,			/* partial_inplace */
26660484Sobrien	 0,			/* src_mask */
26760484Sobrien	 0xfffc,		/* dst_mask */
26860484Sobrien	 false),		/* pcrel_offset */
26960484Sobrien
27060484Sobrien  /* An absolute 16 bit branch, for which bit 10 should be set to
27160484Sobrien     indicate that the branch is expected to be taken.	The lower two
27277298Sobrien     bits must be zero.  */
27360484Sobrien  HOWTO (R_PPC_ADDR14_BRTAKEN,	/* type */
27460484Sobrien	 0,			/* rightshift */
27560484Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
27660484Sobrien	 16,			/* bitsize */
27760484Sobrien	 false,			/* pc_relative */
27860484Sobrien	 0,			/* bitpos */
27960484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
28060484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
28160484Sobrien	 "R_PPC_ADDR14_BRTAKEN",/* name */
28260484Sobrien	 false,			/* partial_inplace */
28360484Sobrien	 0,			/* src_mask */
28460484Sobrien	 0xfffc,		/* dst_mask */
28560484Sobrien	 false),		/* pcrel_offset */
28660484Sobrien
28760484Sobrien  /* An absolute 16 bit branch, for which bit 10 should be set to
28860484Sobrien     indicate that the branch is not expected to be taken.  The lower
28960484Sobrien     two bits must be zero.  */
29060484Sobrien  HOWTO (R_PPC_ADDR14_BRNTAKEN, /* type */
29160484Sobrien	 0,			/* rightshift */
29260484Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
29360484Sobrien	 16,			/* bitsize */
29460484Sobrien	 false,			/* pc_relative */
29560484Sobrien	 0,			/* bitpos */
29660484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
29760484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
29860484Sobrien	 "R_PPC_ADDR14_BRNTAKEN",/* name */
29960484Sobrien	 false,			/* partial_inplace */
30060484Sobrien	 0,			/* src_mask */
30160484Sobrien	 0xfffc,		/* dst_mask */
30260484Sobrien	 false),		/* pcrel_offset */
30360484Sobrien
30477298Sobrien  /* A relative 26 bit branch; the lower two bits must be zero.  */
30560484Sobrien  HOWTO (R_PPC_REL24,		/* type */
30660484Sobrien	 0,			/* rightshift */
30760484Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
30860484Sobrien	 26,			/* bitsize */
30960484Sobrien	 true,			/* pc_relative */
31060484Sobrien	 0,			/* bitpos */
31160484Sobrien	 complain_overflow_signed, /* complain_on_overflow */
31260484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
31360484Sobrien	 "R_PPC_REL24",		/* name */
31460484Sobrien	 false,			/* partial_inplace */
31560484Sobrien	 0,			/* src_mask */
31660484Sobrien	 0x3fffffc,		/* dst_mask */
31760484Sobrien	 true),			/* pcrel_offset */
31860484Sobrien
31977298Sobrien  /* A relative 16 bit branch; the lower two bits must be zero.  */
32060484Sobrien  HOWTO (R_PPC_REL14,		/* type */
32160484Sobrien	 0,			/* rightshift */
32260484Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
32360484Sobrien	 16,			/* bitsize */
32460484Sobrien	 true,			/* pc_relative */
32560484Sobrien	 0,			/* bitpos */
32660484Sobrien	 complain_overflow_signed, /* complain_on_overflow */
32760484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
32860484Sobrien	 "R_PPC_REL14",		/* name */
32960484Sobrien	 false,			/* partial_inplace */
33060484Sobrien	 0,			/* src_mask */
33160484Sobrien	 0xfffc,		/* dst_mask */
33260484Sobrien	 true),			/* pcrel_offset */
33360484Sobrien
33477298Sobrien  /* A relative 16 bit branch.  Bit 10 should be set to indicate that
33560484Sobrien     the branch is expected to be taken.  The lower two bits must be
33660484Sobrien     zero.  */
33760484Sobrien  HOWTO (R_PPC_REL14_BRTAKEN,	/* type */
33860484Sobrien	 0,			/* rightshift */
33960484Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
34060484Sobrien	 16,			/* bitsize */
34160484Sobrien	 true,			/* pc_relative */
34260484Sobrien	 0,			/* bitpos */
34360484Sobrien	 complain_overflow_signed, /* complain_on_overflow */
34460484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
34560484Sobrien	 "R_PPC_REL14_BRTAKEN",	/* name */
34660484Sobrien	 false,			/* partial_inplace */
34760484Sobrien	 0,			/* src_mask */
34860484Sobrien	 0xfffc,		/* dst_mask */
34960484Sobrien	 true),			/* pcrel_offset */
35060484Sobrien
35177298Sobrien  /* A relative 16 bit branch.  Bit 10 should be set to indicate that
35260484Sobrien     the branch is not expected to be taken.  The lower two bits must
35360484Sobrien     be zero.  */
35460484Sobrien  HOWTO (R_PPC_REL14_BRNTAKEN,	/* type */
35560484Sobrien	 0,			/* rightshift */
35660484Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
35760484Sobrien	 16,			/* bitsize */
35860484Sobrien	 true,			/* pc_relative */
35960484Sobrien	 0,			/* bitpos */
36060484Sobrien	 complain_overflow_signed, /* complain_on_overflow */
36160484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
36260484Sobrien	 "R_PPC_REL14_BRNTAKEN",/* name */
36360484Sobrien	 false,			/* partial_inplace */
36460484Sobrien	 0,			/* src_mask */
36560484Sobrien	 0xfffc,		/* dst_mask */
36660484Sobrien	 true),			/* pcrel_offset */
36760484Sobrien
36860484Sobrien  /* Like R_PPC_ADDR16, but referring to the GOT table entry for the
36960484Sobrien     symbol.  */
37060484Sobrien  HOWTO (R_PPC_GOT16,		/* type */
37160484Sobrien	 0,			/* rightshift */
37260484Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
37360484Sobrien	 16,			/* bitsize */
37460484Sobrien	 false,			/* pc_relative */
37560484Sobrien	 0,			/* bitpos */
37660484Sobrien	 complain_overflow_signed, /* complain_on_overflow */
37760484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
37860484Sobrien	 "R_PPC_GOT16",		/* name */
37960484Sobrien	 false,			/* partial_inplace */
38060484Sobrien	 0,			/* src_mask */
38160484Sobrien	 0xffff,		/* dst_mask */
38260484Sobrien	 false),		/* pcrel_offset */
38360484Sobrien
38460484Sobrien  /* Like R_PPC_ADDR16_LO, but referring to the GOT table entry for
38560484Sobrien     the symbol.  */
38660484Sobrien  HOWTO (R_PPC_GOT16_LO,	/* type */
38760484Sobrien	 0,			/* rightshift */
38860484Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
38960484Sobrien	 16,			/* bitsize */
39060484Sobrien	 false,			/* pc_relative */
39160484Sobrien	 0,			/* bitpos */
39260484Sobrien	 complain_overflow_dont, /* complain_on_overflow */
39360484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
39460484Sobrien	 "R_PPC_GOT16_LO",	/* name */
39560484Sobrien	 false,			/* partial_inplace */
39660484Sobrien	 0,			/* src_mask */
39760484Sobrien	 0xffff,		/* dst_mask */
39860484Sobrien	 false),		/* pcrel_offset */
39960484Sobrien
40060484Sobrien  /* Like R_PPC_ADDR16_HI, but referring to the GOT table entry for
40160484Sobrien     the symbol.  */
40260484Sobrien  HOWTO (R_PPC_GOT16_HI,	/* type */
40360484Sobrien	 16,			/* rightshift */
40460484Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
40560484Sobrien	 16,			/* bitsize */
40660484Sobrien	 false,			/* pc_relative */
40760484Sobrien	 0,			/* bitpos */
40860484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
40960484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
41060484Sobrien	 "R_PPC_GOT16_HI",	/* name */
41160484Sobrien	 false,			/* partial_inplace */
41260484Sobrien	 0,			/* src_mask */
41360484Sobrien	 0xffff,		/* dst_mask */
41460484Sobrien	 false),		 /* pcrel_offset */
41560484Sobrien
41660484Sobrien  /* Like R_PPC_ADDR16_HA, but referring to the GOT table entry for
41760484Sobrien     the symbol.  */
41860484Sobrien  HOWTO (R_PPC_GOT16_HA,	/* type */
41960484Sobrien	 16,			/* rightshift */
42060484Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
42160484Sobrien	 16,			/* bitsize */
42260484Sobrien	 false,			/* pc_relative */
42360484Sobrien	 0,			/* bitpos */
42460484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
42560484Sobrien	 ppc_elf_addr16_ha_reloc, /* special_function */
42660484Sobrien	 "R_PPC_GOT16_HA",	/* name */
42760484Sobrien	 false,			/* partial_inplace */
42860484Sobrien	 0,			/* src_mask */
42960484Sobrien	 0xffff,		/* dst_mask */
43060484Sobrien	 false),		/* pcrel_offset */
43160484Sobrien
43260484Sobrien  /* Like R_PPC_REL24, but referring to the procedure linkage table
43360484Sobrien     entry for the symbol.  */
43460484Sobrien  HOWTO (R_PPC_PLTREL24,	/* type */
43560484Sobrien	 0,			/* rightshift */
43660484Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
43760484Sobrien	 26,			/* bitsize */
43860484Sobrien	 true,			/* pc_relative */
43960484Sobrien	 0,			/* bitpos */
44060484Sobrien	 complain_overflow_signed,  /* complain_on_overflow */
44160484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
44260484Sobrien	 "R_PPC_PLTREL24",	/* name */
44360484Sobrien	 false,			/* partial_inplace */
44460484Sobrien	 0,			/* src_mask */
44560484Sobrien	 0x3fffffc,		/* dst_mask */
44660484Sobrien	 true),			/* pcrel_offset */
44760484Sobrien
44860484Sobrien  /* This is used only by the dynamic linker.  The symbol should exist
44960484Sobrien     both in the object being run and in some shared library.  The
45060484Sobrien     dynamic linker copies the data addressed by the symbol from the
45160484Sobrien     shared library into the object, because the object being
45260484Sobrien     run has to have the data at some particular address.  */
45360484Sobrien  HOWTO (R_PPC_COPY,		/* type */
45460484Sobrien	 0,			/* rightshift */
45560484Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
45660484Sobrien	 32,			/* bitsize */
45760484Sobrien	 false,			/* pc_relative */
45860484Sobrien	 0,			/* bitpos */
45960484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
46060484Sobrien	 bfd_elf_generic_reloc,	 /* special_function */
46160484Sobrien	 "R_PPC_COPY",		/* name */
46260484Sobrien	 false,			/* partial_inplace */
46360484Sobrien	 0,			/* src_mask */
46460484Sobrien	 0,			/* dst_mask */
46560484Sobrien	 false),		/* pcrel_offset */
46660484Sobrien
46760484Sobrien  /* Like R_PPC_ADDR32, but used when setting global offset table
46860484Sobrien     entries.  */
46960484Sobrien  HOWTO (R_PPC_GLOB_DAT,	/* type */
47060484Sobrien	 0,			/* rightshift */
47160484Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
47260484Sobrien	 32,			/* bitsize */
47360484Sobrien	 false,			/* pc_relative */
47460484Sobrien	 0,			/* bitpos */
47560484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
47660484Sobrien	 bfd_elf_generic_reloc,	 /* special_function */
47760484Sobrien	 "R_PPC_GLOB_DAT",	/* name */
47860484Sobrien	 false,			/* partial_inplace */
47960484Sobrien	 0,			/* src_mask */
48060484Sobrien	 0xffffffff,		/* dst_mask */
48160484Sobrien	 false),		/* pcrel_offset */
48260484Sobrien
48360484Sobrien  /* Marks a procedure linkage table entry for a symbol.  */
48460484Sobrien  HOWTO (R_PPC_JMP_SLOT,	/* type */
48560484Sobrien	 0,			/* rightshift */
48660484Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
48760484Sobrien	 32,			/* bitsize */
48860484Sobrien	 false,			/* pc_relative */
48960484Sobrien	 0,			/* bitpos */
49060484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
49160484Sobrien	 bfd_elf_generic_reloc,	 /* special_function */
49260484Sobrien	 "R_PPC_JMP_SLOT",	/* name */
49360484Sobrien	 false,			/* partial_inplace */
49460484Sobrien	 0,			/* src_mask */
49560484Sobrien	 0,			/* dst_mask */
49660484Sobrien	 false),		/* pcrel_offset */
49760484Sobrien
49860484Sobrien  /* Used only by the dynamic linker.  When the object is run, this
49960484Sobrien     longword is set to the load address of the object, plus the
50060484Sobrien     addend.  */
50160484Sobrien  HOWTO (R_PPC_RELATIVE,	/* type */
50260484Sobrien	 0,			/* rightshift */
50360484Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
50460484Sobrien	 32,			/* bitsize */
50560484Sobrien	 false,			/* pc_relative */
50660484Sobrien	 0,			/* bitpos */
50760484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
50860484Sobrien	 bfd_elf_generic_reloc,	 /* special_function */
50960484Sobrien	 "R_PPC_RELATIVE",	/* name */
51060484Sobrien	 false,			/* partial_inplace */
51160484Sobrien	 0,			/* src_mask */
51260484Sobrien	 0xffffffff,		/* dst_mask */
51360484Sobrien	 false),		/* pcrel_offset */
51460484Sobrien
51560484Sobrien  /* Like R_PPC_REL24, but uses the value of the symbol within the
51660484Sobrien     object rather than the final value.  Normally used for
51760484Sobrien     _GLOBAL_OFFSET_TABLE_.  */
51860484Sobrien  HOWTO (R_PPC_LOCAL24PC,	/* type */
51960484Sobrien	 0,			/* rightshift */
52060484Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
52160484Sobrien	 26,			/* bitsize */
52260484Sobrien	 true,			/* pc_relative */
52360484Sobrien	 0,			/* bitpos */
52460484Sobrien	 complain_overflow_signed, /* complain_on_overflow */
52560484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
52660484Sobrien	 "R_PPC_LOCAL24PC",	/* name */
52760484Sobrien	 false,			/* partial_inplace */
52860484Sobrien	 0,			/* src_mask */
52960484Sobrien	 0x3fffffc,		/* dst_mask */
53060484Sobrien	 true),			/* pcrel_offset */
53160484Sobrien
53260484Sobrien  /* Like R_PPC_ADDR32, but may be unaligned.  */
53360484Sobrien  HOWTO (R_PPC_UADDR32,		/* type */
53460484Sobrien	 0,			/* rightshift */
53560484Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
53660484Sobrien	 32,			/* bitsize */
53760484Sobrien	 false,			/* pc_relative */
53860484Sobrien	 0,			/* bitpos */
53960484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
54060484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
54160484Sobrien	 "R_PPC_UADDR32",	/* name */
54260484Sobrien	 false,			/* partial_inplace */
54360484Sobrien	 0,			/* src_mask */
54460484Sobrien	 0xffffffff,		/* dst_mask */
54560484Sobrien	 false),		/* pcrel_offset */
54660484Sobrien
54760484Sobrien  /* Like R_PPC_ADDR16, but may be unaligned.  */
54860484Sobrien  HOWTO (R_PPC_UADDR16,		/* type */
54960484Sobrien	 0,			/* rightshift */
55060484Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
55160484Sobrien	 16,			/* bitsize */
55260484Sobrien	 false,			/* pc_relative */
55360484Sobrien	 0,			/* bitpos */
55460484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
55560484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
55660484Sobrien	 "R_PPC_UADDR16",	/* name */
55760484Sobrien	 false,			/* partial_inplace */
55860484Sobrien	 0,			/* src_mask */
55960484Sobrien	 0xffff,		/* dst_mask */
56060484Sobrien	 false),		/* pcrel_offset */
56160484Sobrien
56260484Sobrien  /* 32-bit PC relative */
56360484Sobrien  HOWTO (R_PPC_REL32,		/* type */
56460484Sobrien	 0,			/* rightshift */
56560484Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
56660484Sobrien	 32,			/* bitsize */
56760484Sobrien	 true,			/* pc_relative */
56860484Sobrien	 0,			/* bitpos */
56960484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
57060484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
57160484Sobrien	 "R_PPC_REL32",		/* name */
57260484Sobrien	 false,			/* partial_inplace */
57360484Sobrien	 0,			/* src_mask */
57460484Sobrien	 0xffffffff,		/* dst_mask */
57560484Sobrien	 true),			/* pcrel_offset */
57660484Sobrien
57760484Sobrien  /* 32-bit relocation to the symbol's procedure linkage table.
57877298Sobrien     FIXME: not supported.  */
57960484Sobrien  HOWTO (R_PPC_PLT32,		/* type */
58060484Sobrien	 0,			/* rightshift */
58160484Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
58260484Sobrien	 32,			/* bitsize */
58360484Sobrien	 false,			/* pc_relative */
58460484Sobrien	 0,			/* bitpos */
58560484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
58660484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
58760484Sobrien	 "R_PPC_PLT32",		/* name */
58860484Sobrien	 false,			/* partial_inplace */
58960484Sobrien	 0,			/* src_mask */
59060484Sobrien	 0,			/* dst_mask */
59160484Sobrien	 false),		/* pcrel_offset */
59260484Sobrien
59360484Sobrien  /* 32-bit PC relative relocation to the symbol's procedure linkage table.
59477298Sobrien     FIXME: not supported.  */
59560484Sobrien  HOWTO (R_PPC_PLTREL32,	/* type */
59660484Sobrien	 0,			/* rightshift */
59760484Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
59860484Sobrien	 32,			/* bitsize */
59960484Sobrien	 true,			/* pc_relative */
60060484Sobrien	 0,			/* bitpos */
60160484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
60260484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
60360484Sobrien	 "R_PPC_PLTREL32",	/* name */
60460484Sobrien	 false,			/* partial_inplace */
60560484Sobrien	 0,			/* src_mask */
60660484Sobrien	 0,			/* dst_mask */
60760484Sobrien	 true),			/* pcrel_offset */
60860484Sobrien
60960484Sobrien  /* Like R_PPC_ADDR16_LO, but referring to the PLT table entry for
61060484Sobrien     the symbol.  */
61160484Sobrien  HOWTO (R_PPC_PLT16_LO,	/* type */
61260484Sobrien	 0,			/* rightshift */
61360484Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
61460484Sobrien	 16,			/* bitsize */
61560484Sobrien	 false,			/* pc_relative */
61660484Sobrien	 0,			/* bitpos */
61760484Sobrien	 complain_overflow_dont, /* complain_on_overflow */
61860484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
61960484Sobrien	 "R_PPC_PLT16_LO",	/* name */
62060484Sobrien	 false,			/* partial_inplace */
62160484Sobrien	 0,			/* src_mask */
62260484Sobrien	 0xffff,		/* dst_mask */
62360484Sobrien	 false),		/* pcrel_offset */
62460484Sobrien
62560484Sobrien  /* Like R_PPC_ADDR16_HI, but referring to the PLT table entry for
62660484Sobrien     the symbol.  */
62760484Sobrien  HOWTO (R_PPC_PLT16_HI,	/* type */
62860484Sobrien	 16,			/* rightshift */
62960484Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
63060484Sobrien	 16,			/* bitsize */
63160484Sobrien	 false,			/* pc_relative */
63260484Sobrien	 0,			/* bitpos */
63360484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
63460484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
63560484Sobrien	 "R_PPC_PLT16_HI",	/* name */
63660484Sobrien	 false,			/* partial_inplace */
63760484Sobrien	 0,			/* src_mask */
63860484Sobrien	 0xffff,		/* dst_mask */
63960484Sobrien	 false),		 /* pcrel_offset */
64060484Sobrien
64160484Sobrien  /* Like R_PPC_ADDR16_HA, but referring to the PLT table entry for
64260484Sobrien     the symbol.  */
64360484Sobrien  HOWTO (R_PPC_PLT16_HA,	/* type */
64460484Sobrien	 16,			/* rightshift */
64560484Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
64660484Sobrien	 16,			/* bitsize */
64760484Sobrien	 false,			/* pc_relative */
64860484Sobrien	 0,			/* bitpos */
64960484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
65060484Sobrien	 ppc_elf_addr16_ha_reloc, /* special_function */
65160484Sobrien	 "R_PPC_PLT16_HA",	/* name */
65260484Sobrien	 false,			/* partial_inplace */
65360484Sobrien	 0,			/* src_mask */
65460484Sobrien	 0xffff,		/* dst_mask */
65560484Sobrien	 false),		/* pcrel_offset */
65660484Sobrien
65760484Sobrien  /* A sign-extended 16 bit value relative to _SDA_BASE_, for use with
65860484Sobrien     small data items.  */
65960484Sobrien  HOWTO (R_PPC_SDAREL16,	/* type */
66060484Sobrien	 0,			/* rightshift */
66160484Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
66260484Sobrien	 16,			/* bitsize */
66360484Sobrien	 false,			/* pc_relative */
66460484Sobrien	 0,			/* bitpos */
66560484Sobrien	 complain_overflow_signed, /* complain_on_overflow */
66660484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
66760484Sobrien	 "R_PPC_SDAREL16",	/* name */
66860484Sobrien	 false,			/* partial_inplace */
66960484Sobrien	 0,			/* src_mask */
67060484Sobrien	 0xffff,		/* dst_mask */
67160484Sobrien	 false),		/* pcrel_offset */
67260484Sobrien
67377298Sobrien  /* 32-bit section relative relocation.  */
67460484Sobrien  HOWTO (R_PPC_SECTOFF,		/* type */
67560484Sobrien	 0,			/* rightshift */
67660484Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
67760484Sobrien	 32,			/* bitsize */
67860484Sobrien	 true,			/* pc_relative */
67960484Sobrien	 0,			/* bitpos */
68060484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
68160484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
68260484Sobrien	 "R_PPC_SECTOFF",	/* name */
68360484Sobrien	 false,			/* partial_inplace */
68460484Sobrien	 0,			/* src_mask */
68560484Sobrien	 0,			/* dst_mask */
68660484Sobrien	 true),			/* pcrel_offset */
68760484Sobrien
68877298Sobrien  /* 16-bit lower half section relative relocation.  */
68960484Sobrien  HOWTO (R_PPC_SECTOFF_LO,	  /* type */
69060484Sobrien	 0,			/* rightshift */
69160484Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
69260484Sobrien	 16,			/* bitsize */
69360484Sobrien	 false,			/* pc_relative */
69460484Sobrien	 0,			/* bitpos */
69560484Sobrien	 complain_overflow_dont, /* complain_on_overflow */
69660484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
69760484Sobrien	 "R_PPC_SECTOFF_LO",	/* name */
69860484Sobrien	 false,			/* partial_inplace */
69960484Sobrien	 0,			/* src_mask */
70060484Sobrien	 0xffff,		/* dst_mask */
70160484Sobrien	 false),		/* pcrel_offset */
70260484Sobrien
70377298Sobrien  /* 16-bit upper half section relative relocation.  */
70460484Sobrien  HOWTO (R_PPC_SECTOFF_HI,	/* type */
70560484Sobrien	 16,			/* rightshift */
70660484Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
70760484Sobrien	 16,			/* bitsize */
70860484Sobrien	 false,			/* pc_relative */
70960484Sobrien	 0,			/* bitpos */
71060484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
71160484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
71260484Sobrien	 "R_PPC_SECTOFF_HI",	/* name */
71360484Sobrien	 false,			/* partial_inplace */
71460484Sobrien	 0,			/* src_mask */
71560484Sobrien	 0xffff,		/* dst_mask */
71660484Sobrien	 false),		 /* pcrel_offset */
71760484Sobrien
71877298Sobrien  /* 16-bit upper half adjusted section relative relocation.  */
71960484Sobrien  HOWTO (R_PPC_SECTOFF_HA,	/* type */
72060484Sobrien	 16,			/* rightshift */
72160484Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
72260484Sobrien	 16,			/* bitsize */
72360484Sobrien	 false,			/* pc_relative */
72460484Sobrien	 0,			/* bitpos */
72560484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
72660484Sobrien	 ppc_elf_addr16_ha_reloc, /* special_function */
72760484Sobrien	 "R_PPC_SECTOFF_HA",	/* name */
72860484Sobrien	 false,			/* partial_inplace */
72960484Sobrien	 0,			/* src_mask */
73060484Sobrien	 0xffff,		/* dst_mask */
73160484Sobrien	 false),		/* pcrel_offset */
73260484Sobrien
73360484Sobrien  /* The remaining relocs are from the Embedded ELF ABI, and are not
73460484Sobrien     in the SVR4 ELF ABI.  */
73560484Sobrien
73660484Sobrien  /* 32 bit value resulting from the addend minus the symbol */
73760484Sobrien  HOWTO (R_PPC_EMB_NADDR32,	/* type */
73860484Sobrien	 0,			/* rightshift */
73960484Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
74060484Sobrien	 32,			/* bitsize */
74160484Sobrien	 false,			/* pc_relative */
74260484Sobrien	 0,			/* bitpos */
74360484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
74460484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
74560484Sobrien	 "R_PPC_EMB_NADDR32",	/* name */
74660484Sobrien	 false,			/* partial_inplace */
74760484Sobrien	 0,			/* src_mask */
74860484Sobrien	 0xffffffff,		/* dst_mask */
74960484Sobrien	 false),		/* pcrel_offset */
75060484Sobrien
75160484Sobrien  /* 16 bit value resulting from the addend minus the symbol */
75260484Sobrien  HOWTO (R_PPC_EMB_NADDR16,	/* type */
75360484Sobrien	 0,			/* rightshift */
75460484Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
75560484Sobrien	 16,			/* bitsize */
75660484Sobrien	 false,			/* pc_relative */
75760484Sobrien	 0,			/* bitpos */
75860484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
75960484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
76060484Sobrien	 "R_PPC_EMB_NADDR16",	/* name */
76160484Sobrien	 false,			/* partial_inplace */
76260484Sobrien	 0,			/* src_mask */
76360484Sobrien	 0xffff,		/* dst_mask */
76460484Sobrien	 false),		/* pcrel_offset */
76560484Sobrien
76660484Sobrien  /* 16 bit value resulting from the addend minus the symbol */
76760484Sobrien  HOWTO (R_PPC_EMB_NADDR16_LO,	/* type */
76860484Sobrien	 0,			/* rightshift */
76960484Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
77060484Sobrien	 16,			/* bitsize */
77160484Sobrien	 false,			/* pc_relative */
77260484Sobrien	 0,			/* bitpos */
77360484Sobrien	 complain_overflow_dont,/* complain_on_overflow */
77460484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
77560484Sobrien	 "R_PPC_EMB_ADDR16_LO",	/* name */
77660484Sobrien	 false,			/* partial_inplace */
77760484Sobrien	 0,			/* src_mask */
77860484Sobrien	 0xffff,		/* dst_mask */
77960484Sobrien	 false),		/* pcrel_offset */
78060484Sobrien
78160484Sobrien  /* The high order 16 bits of the addend minus the symbol */
78260484Sobrien  HOWTO (R_PPC_EMB_NADDR16_HI,	/* type */
78360484Sobrien	 16,			/* rightshift */
78460484Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
78560484Sobrien	 16,			/* bitsize */
78660484Sobrien	 false,			/* pc_relative */
78760484Sobrien	 0,			/* bitpos */
78860484Sobrien	 complain_overflow_dont, /* complain_on_overflow */
78960484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
79060484Sobrien	 "R_PPC_EMB_NADDR16_HI", /* name */
79160484Sobrien	 false,			/* partial_inplace */
79260484Sobrien	 0,			/* src_mask */
79360484Sobrien	 0xffff,		/* dst_mask */
79460484Sobrien	 false),		/* pcrel_offset */
79560484Sobrien
79660484Sobrien  /* The high order 16 bits of the result of the addend minus the address,
79760484Sobrien     plus 1 if the contents of the low 16 bits, treated as a signed number,
79860484Sobrien     is negative.  */
79960484Sobrien  HOWTO (R_PPC_EMB_NADDR16_HA,	/* type */
80060484Sobrien	 16,			/* rightshift */
80160484Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
80260484Sobrien	 16,			/* bitsize */
80360484Sobrien	 false,			/* pc_relative */
80460484Sobrien	 0,			/* bitpos */
80560484Sobrien	 complain_overflow_dont, /* complain_on_overflow */
80660484Sobrien	 ppc_elf_addr16_ha_reloc, /* special_function */
80760484Sobrien	 "R_PPC_EMB_NADDR16_HA", /* name */
80860484Sobrien	 false,			/* partial_inplace */
80960484Sobrien	 0,			/* src_mask */
81060484Sobrien	 0xffff,		/* dst_mask */
81160484Sobrien	 false),		/* pcrel_offset */
81260484Sobrien
81360484Sobrien  /* 16 bit value resulting from allocating a 4 byte word to hold an
81460484Sobrien     address in the .sdata section, and returning the offset from
81560484Sobrien     _SDA_BASE_ for that relocation */
81660484Sobrien  HOWTO (R_PPC_EMB_SDAI16,	/* type */
81760484Sobrien	 0,			/* rightshift */
81860484Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
81960484Sobrien	 16,			/* bitsize */
82060484Sobrien	 false,			/* pc_relative */
82160484Sobrien	 0,			/* bitpos */
82260484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
82360484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
82460484Sobrien	 "R_PPC_EMB_SDAI16",	/* name */
82560484Sobrien	 false,			/* partial_inplace */
82660484Sobrien	 0,			/* src_mask */
82760484Sobrien	 0xffff,		/* dst_mask */
82860484Sobrien	 false),		/* pcrel_offset */
82960484Sobrien
83060484Sobrien  /* 16 bit value resulting from allocating a 4 byte word to hold an
83160484Sobrien     address in the .sdata2 section, and returning the offset from
83260484Sobrien     _SDA2_BASE_ for that relocation */
83360484Sobrien  HOWTO (R_PPC_EMB_SDA2I16,	/* type */
83460484Sobrien	 0,			/* rightshift */
83560484Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
83660484Sobrien	 16,			/* bitsize */
83760484Sobrien	 false,			/* pc_relative */
83860484Sobrien	 0,			/* bitpos */
83960484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
84060484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
84160484Sobrien	 "R_PPC_EMB_SDA2I16",	/* name */
84260484Sobrien	 false,			/* partial_inplace */
84360484Sobrien	 0,			/* src_mask */
84460484Sobrien	 0xffff,		/* dst_mask */
84560484Sobrien	 false),		/* pcrel_offset */
84660484Sobrien
84760484Sobrien  /* A sign-extended 16 bit value relative to _SDA2_BASE_, for use with
84860484Sobrien     small data items.	 */
84960484Sobrien  HOWTO (R_PPC_EMB_SDA2REL,	/* type */
85060484Sobrien	 0,			/* rightshift */
85160484Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
85260484Sobrien	 16,			/* bitsize */
85360484Sobrien	 false,			/* pc_relative */
85460484Sobrien	 0,			/* bitpos */
85560484Sobrien	 complain_overflow_signed, /* complain_on_overflow */
85660484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
85760484Sobrien	 "R_PPC_EMB_SDA2REL",	/* name */
85860484Sobrien	 false,			/* partial_inplace */
85960484Sobrien	 0,			/* src_mask */
86060484Sobrien	 0xffff,		/* dst_mask */
86160484Sobrien	 false),		/* pcrel_offset */
86260484Sobrien
86360484Sobrien  /* Relocate against either _SDA_BASE_ or _SDA2_BASE_, filling in the 16 bit
86460484Sobrien     signed offset from the appropriate base, and filling in the register
86560484Sobrien     field with the appropriate register (0, 2, or 13).  */
86660484Sobrien  HOWTO (R_PPC_EMB_SDA21,	/* type */
86760484Sobrien	 0,			/* rightshift */
86860484Sobrien	 2,			/* size (0 = byte, 1 = short, 2 = long) */
86960484Sobrien	 16,			/* bitsize */
87060484Sobrien	 false,			/* pc_relative */
87160484Sobrien	 0,			/* bitpos */
87260484Sobrien	 complain_overflow_signed, /* complain_on_overflow */
87360484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
87460484Sobrien	 "R_PPC_EMB_SDA21",	/* name */
87560484Sobrien	 false,			/* partial_inplace */
87660484Sobrien	 0,			/* src_mask */
87760484Sobrien	 0xffff,		/* dst_mask */
87860484Sobrien	 false),		/* pcrel_offset */
87960484Sobrien
88060484Sobrien  /* Relocation not handled: R_PPC_EMB_MRKREF */
88160484Sobrien  /* Relocation not handled: R_PPC_EMB_RELSEC16 */
88260484Sobrien  /* Relocation not handled: R_PPC_EMB_RELST_LO */
88360484Sobrien  /* Relocation not handled: R_PPC_EMB_RELST_HI */
88460484Sobrien  /* Relocation not handled: R_PPC_EMB_RELST_HA */
88560484Sobrien  /* Relocation not handled: R_PPC_EMB_BIT_FLD */
88660484Sobrien
88760484Sobrien  /* PC relative relocation against either _SDA_BASE_ or _SDA2_BASE_, filling
88860484Sobrien     in the 16 bit signed offset from the appropriate base, and filling in the
88960484Sobrien     register field with the appropriate register (0, 2, or 13).  */
89060484Sobrien  HOWTO (R_PPC_EMB_RELSDA,	/* type */
89160484Sobrien	 0,			/* rightshift */
89260484Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
89360484Sobrien	 16,			/* bitsize */
89460484Sobrien	 true,			/* pc_relative */
89560484Sobrien	 0,			/* bitpos */
89660484Sobrien	 complain_overflow_signed, /* complain_on_overflow */
89760484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
89860484Sobrien	 "R_PPC_EMB_RELSDA",	/* name */
89960484Sobrien	 false,			/* partial_inplace */
90060484Sobrien	 0,			/* src_mask */
90160484Sobrien	 0xffff,		/* dst_mask */
90260484Sobrien	 false),		/* pcrel_offset */
90360484Sobrien
90460484Sobrien  /* GNU extension to record C++ vtable hierarchy */
90560484Sobrien  HOWTO (R_PPC_GNU_VTINHERIT,	/* type */
90660484Sobrien	 0,			/* rightshift */
90760484Sobrien	 0,			/* size (0 = byte, 1 = short, 2 = long) */
90860484Sobrien	 0,			/* bitsize */
90960484Sobrien	 false,			/* pc_relative */
91060484Sobrien	 0,			/* bitpos */
91160484Sobrien	 complain_overflow_dont, /* complain_on_overflow */
91260484Sobrien	 NULL,			/* special_function */
91360484Sobrien	 "R_PPC_GNU_VTINHERIT",	/* name */
91460484Sobrien	 false,			/* partial_inplace */
91560484Sobrien	 0,			/* src_mask */
91660484Sobrien	 0,			/* dst_mask */
91760484Sobrien	 false),		/* pcrel_offset */
91860484Sobrien
91960484Sobrien  /* GNU extension to record C++ vtable member usage */
92060484Sobrien  HOWTO (R_PPC_GNU_VTENTRY,	/* type */
92160484Sobrien	 0,			/* rightshift */
92260484Sobrien	 0,			/* size (0 = byte, 1 = short, 2 = long) */
92360484Sobrien	 0,			/* bitsize */
92460484Sobrien	 false,			/* pc_relative */
92560484Sobrien	 0,			/* bitpos */
92660484Sobrien	 complain_overflow_dont, /* complain_on_overflow */
92760484Sobrien	 NULL,			/* special_function */
92860484Sobrien	 "R_PPC_GNU_VTENTRY",	/* name */
92960484Sobrien	 false,			/* partial_inplace */
93060484Sobrien	 0,			/* src_mask */
93160484Sobrien	 0,			/* dst_mask */
93260484Sobrien	 false),		/* pcrel_offset */
93360484Sobrien
93460484Sobrien  /* Phony reloc to handle AIX style TOC entries */
93560484Sobrien  HOWTO (R_PPC_TOC16,		/* type */
93660484Sobrien	 0,			/* rightshift */
93760484Sobrien	 1,			/* size (0 = byte, 1 = short, 2 = long) */
93860484Sobrien	 16,			/* bitsize */
93960484Sobrien	 false,			/* pc_relative */
94060484Sobrien	 0,			/* bitpos */
94160484Sobrien	 complain_overflow_signed, /* complain_on_overflow */
94260484Sobrien	 bfd_elf_generic_reloc,	/* special_function */
94360484Sobrien	 "R_PPC_TOC16",		/* name */
94460484Sobrien	 false,			/* partial_inplace */
94560484Sobrien	 0,			/* src_mask */
94660484Sobrien	 0xffff,		/* dst_mask */
94760484Sobrien	 false),		/* pcrel_offset */
94860484Sobrien};
94960484Sobrien
95060484Sobrien/* Initialize the ppc_elf_howto_table, so that linear accesses can be done.  */
95160484Sobrien
95260484Sobrienstatic void
95360484Sobrienppc_elf_howto_init ()
95460484Sobrien{
95560484Sobrien  unsigned int i, type;
95660484Sobrien
95760484Sobrien  for (i = 0; i < sizeof (ppc_elf_howto_raw) / sizeof (ppc_elf_howto_raw[0]); i++)
95860484Sobrien    {
95960484Sobrien      type = ppc_elf_howto_raw[i].type;
96077298Sobrien      BFD_ASSERT (type < sizeof (ppc_elf_howto_table) / sizeof (ppc_elf_howto_table[0]));
96160484Sobrien      ppc_elf_howto_table[type] = &ppc_elf_howto_raw[i];
96260484Sobrien    }
96360484Sobrien}
96460484Sobrien
96560484Sobrien/* This function handles relaxing for the PPC with option --mpc860c0[=<n>].
96660484Sobrien
96760484Sobrien   The MPC860, revision C0 or earlier contains a bug in the die.
96860484Sobrien   If all of the following conditions are true, the next instruction
96960484Sobrien   to be executed *may* be treated as a no-op.
97060484Sobrien   1/ A forward branch is executed.
97160484Sobrien   2/ The branch is predicted as not taken.
97260484Sobrien   3/ The branch is taken.
97360484Sobrien   4/ The branch is located in the last 5 words of a page.
97460484Sobrien      (The EOP limit is 5 by default but may be specified as any value from 1-10.)
97577298Sobrien
97660484Sobrien   Our software solution is to detect these problematic branches in a
97760484Sobrien   linker pass and modify them as follows:
97860484Sobrien   1/ Unconditional branches - Since these are always predicted taken,
97960484Sobrien      there is no problem and no action is required.
98060484Sobrien   2/ Conditional backward branches - No problem, no action required.
98160484Sobrien   3/ Conditional forward branches - Ensure that the "inverse prediction
98260484Sobrien      bit" is set (ensure it is predicted taken).
98360484Sobrien   4/ Conditional register branches - Ensure that the "y bit" is set
98460484Sobrien      (ensure it is predicted taken).
98560484Sobrien*/
98660484Sobrien
98760484Sobrien/* Sort sections by address.  */
98860484Sobrien
98960484Sobrienstatic int
99060484Sobrienppc_elf_sort_rela (arg1, arg2)
99177298Sobrien     const void *arg1;
99277298Sobrien     const void *arg2;
99360484Sobrien{
99460484Sobrien  const Elf_Internal_Rela **rela1 = (const Elf_Internal_Rela**) arg1;
99560484Sobrien  const Elf_Internal_Rela **rela2 = (const Elf_Internal_Rela**) arg2;
99660484Sobrien
99777298Sobrien  /* Sort by offset.  */
99860484Sobrien  return ((*rela1)->r_offset - (*rela2)->r_offset);
99960484Sobrien}
100060484Sobrien
100160484Sobrienstatic boolean
100260484Sobrienppc_elf_relax_section (abfd, isec, link_info, again)
100377298Sobrien     bfd *abfd;
100477298Sobrien     asection *isec;
100577298Sobrien     struct bfd_link_info *link_info;
100677298Sobrien     boolean *again;
100760484Sobrien{
100860484Sobrien#define PAGESIZE 0x1000
100960484Sobrien
101060484Sobrien  bfd_byte *contents = NULL;
101160484Sobrien  bfd_byte *free_contents = NULL;
101260484Sobrien  Elf_Internal_Rela *internal_relocs = NULL;
101360484Sobrien  Elf_Internal_Rela *free_relocs = NULL;
101460484Sobrien  Elf_Internal_Rela **rela_comb = NULL;
101560484Sobrien  int comb_curr, comb_count;
101660484Sobrien
101777298Sobrien  /* We never have to do this more than once per input section.  */
101860484Sobrien  *again = false;
101960484Sobrien
102060484Sobrien  /* If needed, initialize this section's cooked size.  */
102160484Sobrien  if (isec->_cooked_size == 0)
102260484Sobrien      isec->_cooked_size = isec->_raw_size;
102360484Sobrien
102460484Sobrien  /* We're only interested in text sections which overlap the
102577298Sobrien     troublesome area at the end of a page.  */
102660484Sobrien  if (link_info->mpc860c0 && (isec->flags & SEC_CODE) && isec->_cooked_size)
102760484Sobrien    {
102860484Sobrien      bfd_vma dot, end_page, end_section;
102960484Sobrien      boolean section_modified;
103060484Sobrien
103177298Sobrien      /* Get the section contents.  */
103260484Sobrien      /* Get cached copy if it exists.  */
103360484Sobrien      if (elf_section_data (isec)->this_hdr.contents != NULL)
103460484Sobrien	  contents = elf_section_data (isec)->this_hdr.contents;
103560484Sobrien      else
103660484Sobrien	{
103760484Sobrien	  /* Go get them off disk.  */
103860484Sobrien	  contents = (bfd_byte *) bfd_malloc (isec->_raw_size);
103960484Sobrien	  if (contents == NULL)
104077298Sobrien	    goto error_return;
104160484Sobrien	  free_contents = contents;
104260484Sobrien
104360484Sobrien	  if (! bfd_get_section_contents (abfd, isec, contents,
104460484Sobrien					  (file_ptr) 0, isec->_raw_size))
104577298Sobrien	    goto error_return;
104660484Sobrien	}
104760484Sobrien
104860484Sobrien      comb_curr = 0;
104960484Sobrien      comb_count = 0;
105060484Sobrien      if (isec->reloc_count)
105177298Sobrien	{
105260484Sobrien          unsigned n;
105360484Sobrien
105460484Sobrien          /* Get a copy of the native relocations.  */
105560484Sobrien          internal_relocs = _bfd_elf32_link_read_relocs (
105677298Sobrien    	    abfd, isec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
105760484Sobrien    	    link_info->keep_memory);
105860484Sobrien          if (internal_relocs == NULL)
105960484Sobrien    	      goto error_return;
106060484Sobrien          if (! link_info->keep_memory)
106160484Sobrien    	      free_relocs = internal_relocs;
106277298Sobrien
106377298Sobrien          /* Setup a faster access method for the reloc info we need.  */
106460484Sobrien          rela_comb = (Elf_Internal_Rela**)
106577298Sobrien	    bfd_malloc (isec->reloc_count*sizeof (Elf_Internal_Rela*));
106660484Sobrien          if (rela_comb == NULL)
106760484Sobrien              goto error_return;
106877298Sobrien          for (n = 0; n < isec->reloc_count; ++n)
106960484Sobrien            {
107060484Sobrien              long r_type;
107177298Sobrien
107260484Sobrien              r_type = ELF32_R_TYPE (internal_relocs[n].r_info);
107377298Sobrien              if (r_type < 0 || r_type >= (int) R_PPC_max)
107460484Sobrien                  goto error_return;
107577298Sobrien
107660484Sobrien              /* Prologue constants are sometimes present in the ".text"
107760484Sobrien              sections and they can be identified by their associated relocation.
107860484Sobrien              We don't want to process those words and some others which
107960484Sobrien              can also be identified by their relocations.  However, not all
108060484Sobrien              conditional branches will have a relocation so we will
108160484Sobrien              only ignore words that 1) have a reloc, and 2) the reloc
108260484Sobrien              is not applicable to a conditional branch.
108377298Sobrien              The array rela_comb is built here for use in the EOP scan loop.  */
108460484Sobrien              switch (r_type)
108560484Sobrien                {
108660484Sobrien                case R_PPC_ADDR14_BRNTAKEN:     /* absolute, predicted not taken */
108777298Sobrien                case R_PPC_REL14:               /* relative cond. br.  */
108860484Sobrien                case R_PPC_REL14_BRNTAKEN:      /* rel. cond. br., predicted not taken */
108977298Sobrien                  /* We should check the instruction.  */
109060484Sobrien                  break;
109160484Sobrien                default:
109277298Sobrien                  /* The word is not a conditional branch - ignore it.  */
109360484Sobrien                  rela_comb[comb_count++] = &internal_relocs[n];
109460484Sobrien                  break;
109560484Sobrien                }
109660484Sobrien            }
109760484Sobrien          if (comb_count > 1)
109877298Sobrien	    qsort (rela_comb, (size_t) comb_count, sizeof (int), ppc_elf_sort_rela);
109977298Sobrien	}
110060484Sobrien
110177298Sobrien      /* Enumerate each EOP region that overlaps this section.  */
110260484Sobrien      end_section = isec->vma + isec->_cooked_size;
110360484Sobrien      dot = end_page = (isec->vma | (PAGESIZE - 1)) + 1;
110460484Sobrien      dot -= link_info->mpc860c0;
110560484Sobrien      section_modified = false;
110660484Sobrien      if (dot < isec->vma)      /* Increment the start position if this section */
110777298Sobrien          dot = isec->vma;      /* begins in the middle of its first EOP region.  */
110860484Sobrien      for (;
110960484Sobrien           dot < end_section;
111060484Sobrien           dot += PAGESIZE, end_page += PAGESIZE)
111160484Sobrien        {
111260484Sobrien
111377298Sobrien          /* Check each word in this EOP region.  */
111460484Sobrien          for (; dot < end_page; dot += 4)
111560484Sobrien            {
111660484Sobrien              bfd_vma isec_offset;
111760484Sobrien              unsigned long insn;
111860484Sobrien              boolean skip, modified;
111960484Sobrien
112060484Sobrien              /* Don't process this word if there is a relocation for it and
112177298Sobrien              the relocation indicates the word is not a conditional branch.  */
112260484Sobrien              skip = false;
112360484Sobrien              isec_offset = dot - isec->vma;
112460484Sobrien              for (; comb_curr<comb_count; ++comb_curr)
112560484Sobrien                {
112660484Sobrien                  bfd_vma r_offset;
112760484Sobrien
112860484Sobrien                  r_offset = rela_comb[comb_curr]->r_offset;
112960484Sobrien                  if (r_offset >= isec_offset)
113060484Sobrien                    {
113160484Sobrien                      if (r_offset == isec_offset) skip = true;
113260484Sobrien                      break;
113360484Sobrien                    }
113460484Sobrien                }
113560484Sobrien              if (skip) continue;
113660484Sobrien
113777298Sobrien              /* Check the current word for a problematic conditional branch.  */
113860484Sobrien#define BO0(insn) ((insn) & 0x02000000)
113960484Sobrien#define BO2(insn) ((insn) & 0x00800000)
114060484Sobrien#define BO4(insn) ((insn) & 0x00200000)
114160484Sobrien              insn = (unsigned long) bfd_get_32 (abfd, contents + isec_offset);
114260484Sobrien              modified = false;
114360484Sobrien              if ((insn & 0xFc000000) == 0x40000000)
114460484Sobrien                {
114560484Sobrien                  /* Instruction is BCx */
114660484Sobrien                  if ((!BO0(insn) || !BO2(insn)) && !BO4(insn))
114760484Sobrien                    {
114860484Sobrien                      bfd_vma target;
114960484Sobrien                      /* This branch is predicted as "normal".
115077298Sobrien                      If this is a forward branch, it is problematic.  */
115160484Sobrien
115260484Sobrien                      target = insn & 0x0000Fffc;               /*extract*/
115360484Sobrien                      target = (target ^ 0x8000) - 0x8000;      /*sign extend*/
115460484Sobrien                      if ((insn & 0x00000002) == 0)
115560484Sobrien                          target += dot;                        /*convert to abs*/
115660484Sobrien                      if (target > dot)
115760484Sobrien                        {
115860484Sobrien                          insn |= 0x00200000;   /* set the prediction bit */
115960484Sobrien                          modified = true;
116060484Sobrien                        }
116160484Sobrien                    }
116260484Sobrien                }
116360484Sobrien              else if ((insn & 0xFc00Fffe) == 0x4c000420)
116460484Sobrien                {
116560484Sobrien                  /* Instruction is BCCTRx */
116660484Sobrien                  if ((!BO0(insn) || !BO2(insn)) && !BO4(insn))
116760484Sobrien		    {
116860484Sobrien		      /* This branch is predicted as not-taken.
116960484Sobrien		      If this is a forward branch, it is problematic.
117060484Sobrien                      Since we can't tell statically if it will branch forward,
117177298Sobrien                      always set the prediction bit.  */
117260484Sobrien                      insn |= 0x00200000;   /* set the prediction bit */
117360484Sobrien                      modified = true;
117460484Sobrien		    }
117560484Sobrien                }
117660484Sobrien              else if ((insn & 0xFc00Fffe) == 0x4c000020)
117760484Sobrien                {
117860484Sobrien                  /* Instruction is BCLRx */
117960484Sobrien                  if ((!BO0(insn) || !BO2(insn)) && !BO4(insn))
118060484Sobrien		    {
118160484Sobrien		      /* This branch is predicted as not-taken.
118260484Sobrien		      If this is a forward branch, it is problematic.
118360484Sobrien                      Since we can't tell statically if it will branch forward,
118477298Sobrien                      always set the prediction bit.  */
118560484Sobrien                      insn |= 0x00200000;   /* set the prediction bit */
118660484Sobrien                      modified = true;
118760484Sobrien		    }
118860484Sobrien                }
118960484Sobrien#undef BO0
119060484Sobrien#undef BO2
119160484Sobrien#undef BO4
119260484Sobrien              if (modified)
119360484Sobrien	        {
119460484Sobrien                  bfd_put_32 (abfd, insn, contents + isec_offset);
119560484Sobrien		  section_modified = true;
119660484Sobrien	        }
119760484Sobrien            }
119860484Sobrien        }
119960484Sobrien      if (section_modified)
120060484Sobrien	{
120160484Sobrien	  elf_section_data (isec)->this_hdr.contents = contents;
120260484Sobrien	  free_contents = NULL;
120360484Sobrien	}
120460484Sobrien    }
120560484Sobrien
120660484Sobrien  if (rela_comb != NULL)
120760484Sobrien    {
120860484Sobrien      free (rela_comb);
120960484Sobrien      rela_comb = NULL;
121060484Sobrien    }
121160484Sobrien
121260484Sobrien  if (free_relocs != NULL)
121360484Sobrien    {
121460484Sobrien      free (free_relocs);
121560484Sobrien      free_relocs = NULL;
121660484Sobrien    }
121760484Sobrien
121860484Sobrien  if (free_contents != NULL)
121960484Sobrien    {
122060484Sobrien      if (! link_info->keep_memory)
122160484Sobrien	free (free_contents);
122260484Sobrien      else
122360484Sobrien	{
122460484Sobrien	  /* Cache the section contents for elf_link_input_bfd.  */
122560484Sobrien	  elf_section_data (isec)->this_hdr.contents = contents;
122660484Sobrien	}
122760484Sobrien      free_contents = NULL;
122860484Sobrien    }
122960484Sobrien
123060484Sobrien  return true;
123160484Sobrien
123260484Sobrienerror_return:
123360484Sobrien  if (rela_comb != NULL)
123460484Sobrien    free (rela_comb);
123560484Sobrien  if (free_relocs != NULL)
123660484Sobrien    free (free_relocs);
123760484Sobrien  if (free_contents != NULL)
123860484Sobrien    free (free_contents);
123960484Sobrien  return false;
124060484Sobrien}
124160484Sobrien
124260484Sobrienstatic reloc_howto_type *
124360484Sobrienppc_elf_reloc_type_lookup (abfd, code)
124460484Sobrien     bfd *abfd ATTRIBUTE_UNUSED;
124560484Sobrien     bfd_reloc_code_real_type code;
124660484Sobrien{
124760484Sobrien  enum elf_ppc_reloc_type ppc_reloc = R_PPC_NONE;
124860484Sobrien
124960484Sobrien  if (!ppc_elf_howto_table[R_PPC_ADDR32])
125077298Sobrien    /* Initialize howto table if needed.  */
125160484Sobrien    ppc_elf_howto_init ();
125260484Sobrien
125377298Sobrien  switch ((int) code)
125460484Sobrien    {
125560484Sobrien    default:
125677298Sobrien      return (reloc_howto_type *) NULL;
125760484Sobrien
125860484Sobrien    case BFD_RELOC_NONE:		ppc_reloc = R_PPC_NONE;			break;
125960484Sobrien    case BFD_RELOC_32:			ppc_reloc = R_PPC_ADDR32;		break;
126060484Sobrien    case BFD_RELOC_PPC_BA26:		ppc_reloc = R_PPC_ADDR24;		break;
126160484Sobrien    case BFD_RELOC_16:			ppc_reloc = R_PPC_ADDR16;		break;
126260484Sobrien    case BFD_RELOC_LO16:		ppc_reloc = R_PPC_ADDR16_LO;		break;
126360484Sobrien    case BFD_RELOC_HI16:		ppc_reloc = R_PPC_ADDR16_HI;		break;
126460484Sobrien    case BFD_RELOC_HI16_S:		ppc_reloc = R_PPC_ADDR16_HA;		break;
126560484Sobrien    case BFD_RELOC_PPC_BA16:		ppc_reloc = R_PPC_ADDR14;		break;
126660484Sobrien    case BFD_RELOC_PPC_BA16_BRTAKEN:	ppc_reloc = R_PPC_ADDR14_BRTAKEN;	break;
126760484Sobrien    case BFD_RELOC_PPC_BA16_BRNTAKEN:	ppc_reloc = R_PPC_ADDR14_BRNTAKEN;	break;
126860484Sobrien    case BFD_RELOC_PPC_B26:		ppc_reloc = R_PPC_REL24;		break;
126960484Sobrien    case BFD_RELOC_PPC_B16:		ppc_reloc = R_PPC_REL14;		break;
127060484Sobrien    case BFD_RELOC_PPC_B16_BRTAKEN:	ppc_reloc = R_PPC_REL14_BRTAKEN;	break;
127160484Sobrien    case BFD_RELOC_PPC_B16_BRNTAKEN:	ppc_reloc = R_PPC_REL14_BRNTAKEN;	break;
127260484Sobrien    case BFD_RELOC_16_GOTOFF:		ppc_reloc = R_PPC_GOT16;		break;
127360484Sobrien    case BFD_RELOC_LO16_GOTOFF:		ppc_reloc = R_PPC_GOT16_LO;		break;
127460484Sobrien    case BFD_RELOC_HI16_GOTOFF:		ppc_reloc = R_PPC_GOT16_HI;		break;
127560484Sobrien    case BFD_RELOC_HI16_S_GOTOFF:	ppc_reloc = R_PPC_GOT16_HA;		break;
127660484Sobrien    case BFD_RELOC_24_PLT_PCREL:	ppc_reloc = R_PPC_PLTREL24;		break;
127760484Sobrien    case BFD_RELOC_PPC_COPY:		ppc_reloc = R_PPC_COPY;			break;
127860484Sobrien    case BFD_RELOC_PPC_GLOB_DAT:	ppc_reloc = R_PPC_GLOB_DAT;		break;
127960484Sobrien    case BFD_RELOC_PPC_LOCAL24PC:	ppc_reloc = R_PPC_LOCAL24PC;		break;
128060484Sobrien    case BFD_RELOC_32_PCREL:		ppc_reloc = R_PPC_REL32;		break;
128160484Sobrien    case BFD_RELOC_32_PLTOFF:		ppc_reloc = R_PPC_PLT32;		break;
128260484Sobrien    case BFD_RELOC_32_PLT_PCREL:	ppc_reloc = R_PPC_PLTREL32;		break;
128360484Sobrien    case BFD_RELOC_LO16_PLTOFF:		ppc_reloc = R_PPC_PLT16_LO;		break;
128460484Sobrien    case BFD_RELOC_HI16_PLTOFF:		ppc_reloc = R_PPC_PLT16_HI;		break;
128560484Sobrien    case BFD_RELOC_HI16_S_PLTOFF:	ppc_reloc = R_PPC_PLT16_HA;		break;
128660484Sobrien    case BFD_RELOC_GPREL16:		ppc_reloc = R_PPC_SDAREL16;		break;
128760484Sobrien    case BFD_RELOC_32_BASEREL:		ppc_reloc = R_PPC_SECTOFF;		break;
128860484Sobrien    case BFD_RELOC_LO16_BASEREL:	ppc_reloc = R_PPC_SECTOFF_LO;		break;
128960484Sobrien    case BFD_RELOC_HI16_BASEREL:	ppc_reloc = R_PPC_SECTOFF_HI;		break;
129060484Sobrien    case BFD_RELOC_HI16_S_BASEREL:	ppc_reloc = R_PPC_SECTOFF_HA;		break;
129160484Sobrien    case BFD_RELOC_CTOR:		ppc_reloc = R_PPC_ADDR32;		break;
129260484Sobrien    case BFD_RELOC_PPC_TOC16:		ppc_reloc = R_PPC_TOC16;		break;
129360484Sobrien    case BFD_RELOC_PPC_EMB_NADDR32:	ppc_reloc = R_PPC_EMB_NADDR32;		break;
129460484Sobrien    case BFD_RELOC_PPC_EMB_NADDR16:	ppc_reloc = R_PPC_EMB_NADDR16;		break;
129560484Sobrien    case BFD_RELOC_PPC_EMB_NADDR16_LO:	ppc_reloc = R_PPC_EMB_NADDR16_LO;	break;
129660484Sobrien    case BFD_RELOC_PPC_EMB_NADDR16_HI:	ppc_reloc = R_PPC_EMB_NADDR16_HI;	break;
129760484Sobrien    case BFD_RELOC_PPC_EMB_NADDR16_HA:	ppc_reloc = R_PPC_EMB_NADDR16_HA;	break;
129860484Sobrien    case BFD_RELOC_PPC_EMB_SDAI16:	ppc_reloc = R_PPC_EMB_SDAI16;		break;
129960484Sobrien    case BFD_RELOC_PPC_EMB_SDA2I16:	ppc_reloc = R_PPC_EMB_SDA2I16;		break;
130060484Sobrien    case BFD_RELOC_PPC_EMB_SDA2REL:	ppc_reloc = R_PPC_EMB_SDA2REL;		break;
130160484Sobrien    case BFD_RELOC_PPC_EMB_SDA21:	ppc_reloc = R_PPC_EMB_SDA21;		break;
130260484Sobrien    case BFD_RELOC_PPC_EMB_MRKREF:	ppc_reloc = R_PPC_EMB_MRKREF;		break;
130360484Sobrien    case BFD_RELOC_PPC_EMB_RELSEC16:	ppc_reloc = R_PPC_EMB_RELSEC16;		break;
130460484Sobrien    case BFD_RELOC_PPC_EMB_RELST_LO:	ppc_reloc = R_PPC_EMB_RELST_LO;		break;
130560484Sobrien    case BFD_RELOC_PPC_EMB_RELST_HI:	ppc_reloc = R_PPC_EMB_RELST_HI;		break;
130660484Sobrien    case BFD_RELOC_PPC_EMB_RELST_HA:	ppc_reloc = R_PPC_EMB_RELST_HA;		break;
130760484Sobrien    case BFD_RELOC_PPC_EMB_BIT_FLD:	ppc_reloc = R_PPC_EMB_BIT_FLD;		break;
130860484Sobrien    case BFD_RELOC_PPC_EMB_RELSDA:	ppc_reloc = R_PPC_EMB_RELSDA;		break;
130960484Sobrien    case BFD_RELOC_VTABLE_INHERIT:	ppc_reloc = R_PPC_GNU_VTINHERIT;	break;
131060484Sobrien    case BFD_RELOC_VTABLE_ENTRY:	ppc_reloc = R_PPC_GNU_VTENTRY;		break;
131160484Sobrien    }
131260484Sobrien
131377298Sobrien  return ppc_elf_howto_table[(int) ppc_reloc];
131460484Sobrien};
131560484Sobrien
131660484Sobrien/* Set the howto pointer for a PowerPC ELF reloc.  */
131760484Sobrien
131860484Sobrienstatic void
131960484Sobrienppc_elf_info_to_howto (abfd, cache_ptr, dst)
132060484Sobrien     bfd *abfd ATTRIBUTE_UNUSED;
132160484Sobrien     arelent *cache_ptr;
132260484Sobrien     Elf32_Internal_Rela *dst;
132360484Sobrien{
132477298Sobrien  if (!ppc_elf_howto_table[R_PPC_ADDR32])
132577298Sobrien    /* Initialize howto table if needed.  */
132660484Sobrien    ppc_elf_howto_init ();
132760484Sobrien
132860484Sobrien  BFD_ASSERT (ELF32_R_TYPE (dst->r_info) < (unsigned int) R_PPC_max);
132960484Sobrien  cache_ptr->howto = ppc_elf_howto_table[ELF32_R_TYPE (dst->r_info)];
133060484Sobrien}
133160484Sobrien
133260484Sobrien/* Handle the R_PPC_ADDR16_HA reloc.  */
133360484Sobrien
133460484Sobrienstatic bfd_reloc_status_type
133560484Sobrienppc_elf_addr16_ha_reloc (abfd, reloc_entry, symbol, data, input_section,
133660484Sobrien			 output_bfd, error_message)
133760484Sobrien     bfd *abfd ATTRIBUTE_UNUSED;
133860484Sobrien     arelent *reloc_entry;
133960484Sobrien     asymbol *symbol;
134060484Sobrien     PTR data ATTRIBUTE_UNUSED;
134160484Sobrien     asection *input_section;
134260484Sobrien     bfd *output_bfd;
134360484Sobrien     char **error_message ATTRIBUTE_UNUSED;
134460484Sobrien{
134560484Sobrien  bfd_vma relocation;
134660484Sobrien
134760484Sobrien  if (output_bfd != NULL)
134860484Sobrien    {
134960484Sobrien      reloc_entry->address += input_section->output_offset;
135060484Sobrien      return bfd_reloc_ok;
135160484Sobrien    }
135260484Sobrien
135360484Sobrien  if (reloc_entry->address > input_section->_cooked_size)
135460484Sobrien    return bfd_reloc_outofrange;
135560484Sobrien
135660484Sobrien  if (bfd_is_com_section (symbol->section))
135760484Sobrien    relocation = 0;
135860484Sobrien  else
135960484Sobrien    relocation = symbol->value;
136060484Sobrien
136160484Sobrien  relocation += symbol->section->output_section->vma;
136260484Sobrien  relocation += symbol->section->output_offset;
136360484Sobrien  relocation += reloc_entry->addend;
136460484Sobrien
136560484Sobrien  reloc_entry->addend += (relocation & 0x8000) << 1;
136660484Sobrien
136760484Sobrien  return bfd_reloc_continue;
136860484Sobrien}
136960484Sobrien
137077298Sobrien/* Function to set whether a module needs the -mrelocatable bit set.  */
137160484Sobrien
137260484Sobrienstatic boolean
137360484Sobrienppc_elf_set_private_flags (abfd, flags)
137460484Sobrien     bfd *abfd;
137560484Sobrien     flagword flags;
137660484Sobrien{
137760484Sobrien  BFD_ASSERT (!elf_flags_init (abfd)
137860484Sobrien	      || elf_elfheader (abfd)->e_flags == flags);
137960484Sobrien
138060484Sobrien  elf_elfheader (abfd)->e_flags = flags;
138160484Sobrien  elf_flags_init (abfd) = true;
138260484Sobrien  return true;
138360484Sobrien}
138460484Sobrien
138560484Sobrien/* Copy backend specific data from one object module to another */
138660484Sobrienstatic boolean
138760484Sobrienppc_elf_copy_private_bfd_data (ibfd, obfd)
138860484Sobrien     bfd *ibfd;
138960484Sobrien     bfd *obfd;
139060484Sobrien{
139160484Sobrien  if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
139260484Sobrien      || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
139360484Sobrien    return true;
139460484Sobrien
139560484Sobrien  BFD_ASSERT (!elf_flags_init (obfd)
139660484Sobrien	      || elf_elfheader (obfd)->e_flags == elf_elfheader (ibfd)->e_flags);
139760484Sobrien
139860484Sobrien  elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
139960484Sobrien  elf_flags_init (obfd) = true;
140060484Sobrien  return true;
140160484Sobrien}
140260484Sobrien
140360484Sobrien/* Merge backend specific data from an object file to the output
140460484Sobrien   object file when linking */
140560484Sobrienstatic boolean
140660484Sobrienppc_elf_merge_private_bfd_data (ibfd, obfd)
140760484Sobrien     bfd *ibfd;
140860484Sobrien     bfd *obfd;
140960484Sobrien{
141060484Sobrien  flagword old_flags;
141160484Sobrien  flagword new_flags;
141260484Sobrien  boolean error;
141360484Sobrien
141460484Sobrien  /* Check if we have the same endianess */
141577298Sobrien  if (_bfd_generic_verify_endian_match (ibfd, obfd) == false)
141677298Sobrien    return false;
141760484Sobrien
141860484Sobrien  if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
141960484Sobrien      || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
142060484Sobrien    return true;
142160484Sobrien
142260484Sobrien  new_flags = elf_elfheader (ibfd)->e_flags;
142360484Sobrien  old_flags = elf_elfheader (obfd)->e_flags;
142460484Sobrien  if (!elf_flags_init (obfd))	/* First call, no flags set */
142560484Sobrien    {
142660484Sobrien      elf_flags_init (obfd) = true;
142760484Sobrien      elf_elfheader (obfd)->e_flags = new_flags;
142860484Sobrien    }
142960484Sobrien
143060484Sobrien  else if (new_flags == old_flags)	/* Compatible flags are ok */
143160484Sobrien    ;
143260484Sobrien
143360484Sobrien  else					/* Incompatible flags */
143460484Sobrien    {
143560484Sobrien      /* Warn about -mrelocatable mismatch.  Allow -mrelocatable-lib to be linked
143660484Sobrien         with either.  */
143760484Sobrien      error = false;
143860484Sobrien      if ((new_flags & EF_PPC_RELOCATABLE) != 0
143960484Sobrien	  && (old_flags & (EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB)) == 0)
144060484Sobrien	{
144160484Sobrien	  error = true;
144260484Sobrien	  (*_bfd_error_handler)
144360484Sobrien	    (_("%s: compiled with -mrelocatable and linked with modules compiled normally"),
144460484Sobrien	     bfd_get_filename (ibfd));
144560484Sobrien	}
144660484Sobrien      else if ((new_flags & (EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB)) == 0
144760484Sobrien	       && (old_flags & EF_PPC_RELOCATABLE) != 0)
144860484Sobrien	{
144960484Sobrien	  error = true;
145060484Sobrien	  (*_bfd_error_handler)
145160484Sobrien	    (_("%s: compiled normally and linked with modules compiled with -mrelocatable"),
145260484Sobrien	     bfd_get_filename (ibfd));
145360484Sobrien	}
145460484Sobrien
145560484Sobrien      /* The output is -mrelocatable-lib iff both the input files are.  */
145660484Sobrien      if (! (new_flags & EF_PPC_RELOCATABLE_LIB))
145760484Sobrien	elf_elfheader (obfd)->e_flags &= ~EF_PPC_RELOCATABLE_LIB;
145860484Sobrien
145960484Sobrien      /* The output is -mrelocatable iff it can't be -mrelocatable-lib,
146060484Sobrien         but each input file is either -mrelocatable or -mrelocatable-lib.  */
146160484Sobrien      if (! (elf_elfheader (obfd)->e_flags & EF_PPC_RELOCATABLE_LIB)
146260484Sobrien	  && (new_flags & (EF_PPC_RELOCATABLE_LIB | EF_PPC_RELOCATABLE))
146360484Sobrien	  && (old_flags & (EF_PPC_RELOCATABLE_LIB | EF_PPC_RELOCATABLE)))
146460484Sobrien	elf_elfheader (obfd)->e_flags |= EF_PPC_RELOCATABLE;
146560484Sobrien
146660484Sobrien      /* Do not warn about eabi vs. V.4 mismatch, just or in the bit if any module uses it */
146760484Sobrien      elf_elfheader (obfd)->e_flags |= (new_flags & EF_PPC_EMB);
146860484Sobrien
146960484Sobrien      new_flags &= ~ (EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB | EF_PPC_EMB);
147060484Sobrien      old_flags &= ~ (EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB | EF_PPC_EMB);
147160484Sobrien
147260484Sobrien      /* Warn about any other mismatches */
147360484Sobrien      if (new_flags != old_flags)
147460484Sobrien	{
147560484Sobrien	  error = true;
147660484Sobrien	  (*_bfd_error_handler)
147760484Sobrien	    (_("%s: uses different e_flags (0x%lx) fields than previous modules (0x%lx)"),
147877298Sobrien	     bfd_get_filename (ibfd), (long) new_flags, (long) old_flags);
147960484Sobrien	}
148060484Sobrien
148160484Sobrien      if (error)
148260484Sobrien	{
148360484Sobrien	  bfd_set_error (bfd_error_bad_value);
148460484Sobrien	  return false;
148560484Sobrien	}
148660484Sobrien    }
148760484Sobrien
148860484Sobrien  return true;
148960484Sobrien}
149060484Sobrien
149160484Sobrien/* Handle a PowerPC specific section when reading an object file.  This
149260484Sobrien   is called when elfcode.h finds a section with an unknown type.  */
149360484Sobrien
149460484Sobrienstatic boolean
149560484Sobrienppc_elf_section_from_shdr (abfd, hdr, name)
149660484Sobrien     bfd *abfd;
149760484Sobrien     Elf32_Internal_Shdr *hdr;
149860484Sobrien     char *name;
149960484Sobrien{
150060484Sobrien  asection *newsect;
150160484Sobrien  flagword flags;
150260484Sobrien
150360484Sobrien  if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name))
150460484Sobrien    return false;
150560484Sobrien
150660484Sobrien  newsect = hdr->bfd_section;
150760484Sobrien  flags = bfd_get_section_flags (abfd, newsect);
150860484Sobrien  if (hdr->sh_flags & SHF_EXCLUDE)
150960484Sobrien    flags |= SEC_EXCLUDE;
151060484Sobrien
151160484Sobrien  if (hdr->sh_type == SHT_ORDERED)
151260484Sobrien    flags |= SEC_SORT_ENTRIES;
151360484Sobrien
151460484Sobrien  bfd_set_section_flags (abfd, newsect, flags);
151560484Sobrien  return true;
151660484Sobrien}
151760484Sobrien
151860484Sobrien/* Set up any other section flags and such that may be necessary.  */
151960484Sobrien
152060484Sobrienstatic boolean
152160484Sobrienppc_elf_fake_sections (abfd, shdr, asect)
152260484Sobrien     bfd *abfd ATTRIBUTE_UNUSED;
152360484Sobrien     Elf32_Internal_Shdr *shdr;
152460484Sobrien     asection *asect;
152560484Sobrien{
152660484Sobrien  if ((asect->flags & SEC_EXCLUDE) != 0)
152760484Sobrien    shdr->sh_flags |= SHF_EXCLUDE;
152860484Sobrien
152960484Sobrien  if ((asect->flags & SEC_SORT_ENTRIES) != 0)
153060484Sobrien    shdr->sh_type = SHT_ORDERED;
153160484Sobrien
153260484Sobrien  return true;
153360484Sobrien}
153460484Sobrien
153560484Sobrien/* Create a special linker section */
153660484Sobrienstatic elf_linker_section_t *
153760484Sobrienppc_elf_create_linker_section (abfd, info, which)
153860484Sobrien     bfd *abfd;
153960484Sobrien     struct bfd_link_info *info;
154060484Sobrien     enum elf_linker_section_enum which;
154160484Sobrien{
154260484Sobrien  bfd *dynobj = elf_hash_table (info)->dynobj;
154360484Sobrien  elf_linker_section_t *lsect;
154460484Sobrien
154560484Sobrien  /* Record the first bfd section that needs the special section */
154660484Sobrien  if (!dynobj)
154760484Sobrien    dynobj = elf_hash_table (info)->dynobj = abfd;
154860484Sobrien
154960484Sobrien  /* If this is the first time, create the section */
155060484Sobrien  lsect = elf_linker_section (dynobj, which);
155160484Sobrien  if (!lsect)
155260484Sobrien    {
155360484Sobrien      elf_linker_section_t defaults;
155460484Sobrien      static elf_linker_section_t zero_section;
155560484Sobrien
155660484Sobrien      defaults = zero_section;
155760484Sobrien      defaults.which = which;
155860484Sobrien      defaults.hole_written_p = false;
155960484Sobrien      defaults.alignment = 2;
156060484Sobrien
156160484Sobrien      /* Both of these sections are (technically) created by the user
156260484Sobrien	 putting data in them, so they shouldn't be marked
156360484Sobrien	 SEC_LINKER_CREATED.
156460484Sobrien
156560484Sobrien	 The linker creates them so it has somewhere to attach their
156660484Sobrien	 respective symbols. In fact, if they were empty it would
156760484Sobrien	 be OK to leave the symbol set to 0 (or any random number), because
156860484Sobrien	 the appropriate register should never be used.  */
156960484Sobrien      defaults.flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
157060484Sobrien			| SEC_IN_MEMORY);
157160484Sobrien
157260484Sobrien      switch (which)
157360484Sobrien	{
157460484Sobrien	default:
157560484Sobrien	  (*_bfd_error_handler) (_("%s: Unknown special linker type %d"),
157660484Sobrien				 bfd_get_filename (abfd),
157777298Sobrien				 (int) which);
157860484Sobrien
157960484Sobrien	  bfd_set_error (bfd_error_bad_value);
158077298Sobrien	  return (elf_linker_section_t *) 0;
158160484Sobrien
158260484Sobrien	case LINKER_SECTION_SDATA:	/* .sdata/.sbss section */
158360484Sobrien	  defaults.name		  = ".sdata";
158460484Sobrien	  defaults.rel_name	  = ".rela.sdata";
158560484Sobrien	  defaults.bss_name	  = ".sbss";
158660484Sobrien	  defaults.sym_name	  = "_SDA_BASE_";
158760484Sobrien	  defaults.sym_offset	  = 32768;
158860484Sobrien	  break;
158960484Sobrien
159060484Sobrien	case LINKER_SECTION_SDATA2:	/* .sdata2/.sbss2 section */
159160484Sobrien	  defaults.name		  = ".sdata2";
159260484Sobrien	  defaults.rel_name	  = ".rela.sdata2";
159360484Sobrien	  defaults.bss_name	  = ".sbss2";
159460484Sobrien	  defaults.sym_name	  = "_SDA2_BASE_";
159560484Sobrien	  defaults.sym_offset	  = 32768;
159660484Sobrien	  defaults.flags	 |= SEC_READONLY;
159760484Sobrien	  break;
159860484Sobrien	}
159960484Sobrien
160060484Sobrien      lsect = _bfd_elf_create_linker_section (abfd, info, which, &defaults);
160160484Sobrien    }
160260484Sobrien
160360484Sobrien  return lsect;
160460484Sobrien}
160560484Sobrien
160677298Sobrien/* If we have a non-zero sized .sbss2 or .PPC.EMB.sbss0 sections, we
160777298Sobrien   need to bump up the number of section headers.  */
160860484Sobrien
160960484Sobrienstatic int
161060484Sobrienppc_elf_additional_program_headers (abfd)
161160484Sobrien     bfd *abfd;
161260484Sobrien{
161360484Sobrien  asection *s;
161460484Sobrien  int ret;
161560484Sobrien
161660484Sobrien  ret = 0;
161760484Sobrien
161860484Sobrien  s = bfd_get_section_by_name (abfd, ".interp");
161960484Sobrien  if (s != NULL)
162060484Sobrien    ++ret;
162160484Sobrien
162260484Sobrien  s = bfd_get_section_by_name (abfd, ".sbss2");
162360484Sobrien  if (s != NULL && (s->flags & SEC_LOAD) != 0 && s->_raw_size > 0)
162460484Sobrien    ++ret;
162560484Sobrien
162660484Sobrien  s = bfd_get_section_by_name (abfd, ".PPC.EMB.sbss0");
162760484Sobrien  if (s != NULL && (s->flags & SEC_LOAD) != 0 && s->_raw_size > 0)
162860484Sobrien    ++ret;
162960484Sobrien
163060484Sobrien  return ret;
163160484Sobrien}
163260484Sobrien
163377298Sobrien/* Modify the segment map if needed.  */
163460484Sobrien
163560484Sobrienstatic boolean
163660484Sobrienppc_elf_modify_segment_map (abfd)
163760484Sobrien     bfd *abfd ATTRIBUTE_UNUSED;
163860484Sobrien{
163960484Sobrien  return true;
164060484Sobrien}
164160484Sobrien
164260484Sobrien/* We have to create .dynsbss and .rela.sbss here so that they get mapped
164360484Sobrien   to output sections (just like _bfd_elf_create_dynamic_sections has
164460484Sobrien   to create .dynbss and .rela.bss).  */
164560484Sobrien
164660484Sobrienstatic boolean
164760484Sobrienppc_elf_create_dynamic_sections (abfd, info)
164860484Sobrien     bfd *abfd;
164960484Sobrien     struct bfd_link_info *info;
165060484Sobrien{
165160484Sobrien  register asection *s;
165260484Sobrien  flagword flags;
165360484Sobrien
165477298Sobrien  if (!_bfd_elf_create_dynamic_sections (abfd, info))
165560484Sobrien    return false;
165660484Sobrien
165760484Sobrien  flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
165860484Sobrien	   | SEC_LINKER_CREATED);
165960484Sobrien
166060484Sobrien  s = bfd_make_section (abfd, ".dynsbss");
166160484Sobrien  if (s == NULL
166260484Sobrien      || ! bfd_set_section_flags (abfd, s, SEC_ALLOC))
166360484Sobrien    return false;
166460484Sobrien
166560484Sobrien  if (! info->shared)
166660484Sobrien    {
166760484Sobrien      s = bfd_make_section (abfd, ".rela.sbss");
166860484Sobrien      if (s == NULL
166960484Sobrien	  || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
167060484Sobrien	  || ! bfd_set_section_alignment (abfd, s, 2))
167160484Sobrien	return false;
167260484Sobrien    }
167360484Sobrien  return true;
167460484Sobrien}
167560484Sobrien
167660484Sobrien/* Adjust a symbol defined by a dynamic object and referenced by a
167760484Sobrien   regular object.  The current definition is in some section of the
167860484Sobrien   dynamic object, but we're not including those sections.  We have to
167960484Sobrien   change the definition to something the rest of the link can
168060484Sobrien   understand.  */
168160484Sobrien
168260484Sobrienstatic boolean
168360484Sobrienppc_elf_adjust_dynamic_symbol (info, h)
168460484Sobrien     struct bfd_link_info *info;
168560484Sobrien     struct elf_link_hash_entry *h;
168660484Sobrien{
168760484Sobrien  bfd *dynobj = elf_hash_table (info)->dynobj;
168860484Sobrien  asection *s;
168960484Sobrien  unsigned int power_of_two;
169060484Sobrien  bfd_vma plt_offset;
169160484Sobrien
169260484Sobrien#ifdef DEBUG
169360484Sobrien  fprintf (stderr, "ppc_elf_adjust_dynamic_symbol called for %s\n", h->root.root.string);
169460484Sobrien#endif
169560484Sobrien
169660484Sobrien  /* Make sure we know what is going on here.  */
169760484Sobrien  BFD_ASSERT (dynobj != NULL
169860484Sobrien	      && ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT)
169960484Sobrien		  || h->weakdef != NULL
170060484Sobrien		  || ((h->elf_link_hash_flags
170160484Sobrien		       & ELF_LINK_HASH_DEF_DYNAMIC) != 0
170260484Sobrien		      && (h->elf_link_hash_flags
170360484Sobrien			  & ELF_LINK_HASH_REF_REGULAR) != 0
170460484Sobrien		      && (h->elf_link_hash_flags
170560484Sobrien			  & ELF_LINK_HASH_DEF_REGULAR) == 0)));
170660484Sobrien
170760484Sobrien  /* If this is a function, put it in the procedure linkage table.  We
170860484Sobrien     will fill in the contents of the procedure linkage table later,
170960484Sobrien     when we know the address of the .got section.  */
171060484Sobrien  if (h->type == STT_FUNC
171160484Sobrien      || (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0)
171260484Sobrien    {
171360484Sobrien      if (! elf_hash_table (info)->dynamic_sections_created
171477298Sobrien 	  || SYMBOL_CALLS_LOCAL (info, h)
171560484Sobrien	  || (info->shared && h->plt.refcount <= 0))
171660484Sobrien	{
171760484Sobrien	  /* A PLT entry is not required/allowed when:
171860484Sobrien
171960484Sobrien	     1. We are not using ld.so; because then the PLT entry
172060484Sobrien	     can't be set up, so we can't use one.
172160484Sobrien
172277298Sobrien	     2. We know for certain that a call to this symbol
172377298Sobrien	     will go to this object.
172460484Sobrien
172560484Sobrien	     3. GC has rendered the entry unused.
172660484Sobrien	     Note, however, that in an executable all references to the
172760484Sobrien	     symbol go to the PLT, so we can't turn it off in that case.
172860484Sobrien	     ??? The correct thing to do here is to reference count
172960484Sobrien	     all uses of the symbol, not just those to the GOT or PLT.  */
173060484Sobrien	  h->plt.offset = (bfd_vma) -1;
173160484Sobrien	  h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
173260484Sobrien	  return true;
173360484Sobrien	}
173460484Sobrien
173560484Sobrien      /* Make sure this symbol is output as a dynamic symbol.  */
173660484Sobrien      if (h->dynindx == -1)
173760484Sobrien	{
173860484Sobrien	  if (! bfd_elf32_link_record_dynamic_symbol (info, h))
173960484Sobrien	    return false;
174060484Sobrien	}
174160484Sobrien      BFD_ASSERT (h->dynindx != -1);
174260484Sobrien
174360484Sobrien      s = bfd_get_section_by_name (dynobj, ".plt");
174460484Sobrien      BFD_ASSERT (s != NULL);
174560484Sobrien
174660484Sobrien      /* If this is the first .plt entry, make room for the special
174760484Sobrien	 first entry.  */
174860484Sobrien      if (s->_raw_size == 0)
174960484Sobrien	s->_raw_size += PLT_INITIAL_ENTRY_SIZE;
175060484Sobrien
175160484Sobrien      /* The PowerPC PLT is actually composed of two parts, the first part
175260484Sobrien	 is 2 words (for a load and a jump), and then there is a remaining
175360484Sobrien	 word available at the end.  */
175460484Sobrien      plt_offset = (PLT_INITIAL_ENTRY_SIZE
175560484Sobrien		    + (PLT_SLOT_SIZE
175660484Sobrien		       * ((s->_raw_size - PLT_INITIAL_ENTRY_SIZE)
175760484Sobrien			  / PLT_ENTRY_SIZE)));
175860484Sobrien
175960484Sobrien      /* If this symbol is not defined in a regular file, and we are
176060484Sobrien	 not generating a shared library, then set the symbol to this
176160484Sobrien	 location in the .plt.  This is required to make function
176260484Sobrien	 pointers compare as equal between the normal executable and
176360484Sobrien	 the shared library.  */
176460484Sobrien      if (! info->shared
176560484Sobrien	  && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
176660484Sobrien	{
176760484Sobrien	  h->root.u.def.section = s;
176860484Sobrien	  h->root.u.def.value = plt_offset;
176960484Sobrien	}
177060484Sobrien
177160484Sobrien      h->plt.offset = plt_offset;
177260484Sobrien
177360484Sobrien      /* Make room for this entry.  After the 8192nd entry, room
177460484Sobrien         for two entries is allocated.  */
177560484Sobrien      if ((s->_raw_size - PLT_INITIAL_ENTRY_SIZE) / PLT_ENTRY_SIZE
177660484Sobrien	  >= PLT_NUM_SINGLE_ENTRIES)
177760484Sobrien	s->_raw_size += 2 * PLT_ENTRY_SIZE;
177860484Sobrien      else
177960484Sobrien	s->_raw_size += PLT_ENTRY_SIZE;
178060484Sobrien
178160484Sobrien      /* We also need to make an entry in the .rela.plt section.  */
178260484Sobrien      s = bfd_get_section_by_name (dynobj, ".rela.plt");
178360484Sobrien      BFD_ASSERT (s != NULL);
178460484Sobrien      s->_raw_size += sizeof (Elf32_External_Rela);
178560484Sobrien
178660484Sobrien      return true;
178760484Sobrien    }
178860484Sobrien
178960484Sobrien  /* If this is a weak symbol, and there is a real definition, the
179060484Sobrien     processor independent code will have arranged for us to see the
179160484Sobrien     real definition first, and we can just use the same value.  */
179260484Sobrien  if (h->weakdef != NULL)
179360484Sobrien    {
179460484Sobrien      BFD_ASSERT (h->weakdef->root.type == bfd_link_hash_defined
179560484Sobrien		  || h->weakdef->root.type == bfd_link_hash_defweak);
179660484Sobrien      h->root.u.def.section = h->weakdef->root.u.def.section;
179760484Sobrien      h->root.u.def.value = h->weakdef->root.u.def.value;
179860484Sobrien      return true;
179960484Sobrien    }
180060484Sobrien
180160484Sobrien  /* This is a reference to a symbol defined by a dynamic object which
180260484Sobrien     is not a function.  */
180360484Sobrien
180460484Sobrien  /* If we are creating a shared library, we must presume that the
180560484Sobrien     only references to the symbol are via the global offset table.
180660484Sobrien     For such cases we need not do anything here; the relocations will
180760484Sobrien     be handled correctly by relocate_section.  */
180860484Sobrien  if (info->shared)
180960484Sobrien    return true;
181060484Sobrien
181160484Sobrien  /* We must allocate the symbol in our .dynbss section, which will
181260484Sobrien     become part of the .bss section of the executable.  There will be
181360484Sobrien     an entry for this symbol in the .dynsym section.  The dynamic
181460484Sobrien     object will contain position independent code, so all references
181560484Sobrien     from the dynamic object to this symbol will go through the global
181660484Sobrien     offset table.  The dynamic linker will use the .dynsym entry to
181760484Sobrien     determine the address it must put in the global offset table, so
181860484Sobrien     both the dynamic object and the regular object will refer to the
181960484Sobrien     same memory location for the variable.
182060484Sobrien
182160484Sobrien     Of course, if the symbol is sufficiently small, we must instead
182260484Sobrien     allocate it in .sbss.  FIXME: It would be better to do this if and
182360484Sobrien     only if there were actually SDAREL relocs for that symbol.  */
182460484Sobrien
182560484Sobrien  if (h->size <= elf_gp_size (dynobj))
182660484Sobrien    s = bfd_get_section_by_name (dynobj, ".dynsbss");
182760484Sobrien  else
182860484Sobrien    s = bfd_get_section_by_name (dynobj, ".dynbss");
182960484Sobrien  BFD_ASSERT (s != NULL);
183060484Sobrien
183160484Sobrien  /* We must generate a R_PPC_COPY reloc to tell the dynamic linker to
183260484Sobrien     copy the initial value out of the dynamic object and into the
183360484Sobrien     runtime process image.  We need to remember the offset into the
183460484Sobrien     .rela.bss section we are going to use.  */
183560484Sobrien  if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
183660484Sobrien    {
183760484Sobrien      asection *srel;
183860484Sobrien
183960484Sobrien      if (h->size <= elf_gp_size (dynobj))
184060484Sobrien	srel = bfd_get_section_by_name (dynobj, ".rela.sbss");
184160484Sobrien      else
184260484Sobrien	srel = bfd_get_section_by_name (dynobj, ".rela.bss");
184360484Sobrien      BFD_ASSERT (srel != NULL);
184460484Sobrien      srel->_raw_size += sizeof (Elf32_External_Rela);
184560484Sobrien      h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_COPY;
184660484Sobrien    }
184760484Sobrien
184860484Sobrien  /* We need to figure out the alignment required for this symbol.  I
184960484Sobrien     have no idea how ELF linkers handle this.  */
185060484Sobrien  power_of_two = bfd_log2 (h->size);
185160484Sobrien  if (power_of_two > 4)
185260484Sobrien    power_of_two = 4;
185360484Sobrien
185460484Sobrien  /* Apply the required alignment.  */
185560484Sobrien  s->_raw_size = BFD_ALIGN (s->_raw_size,
185660484Sobrien			    (bfd_size_type) (1 << power_of_two));
185760484Sobrien  if (power_of_two > bfd_get_section_alignment (dynobj, s))
185860484Sobrien    {
185960484Sobrien      if (! bfd_set_section_alignment (dynobj, s, power_of_two))
186060484Sobrien	return false;
186160484Sobrien    }
186260484Sobrien
186360484Sobrien  /* Define the symbol as being at this point in the section.  */
186460484Sobrien  h->root.u.def.section = s;
186560484Sobrien  h->root.u.def.value = s->_raw_size;
186660484Sobrien
186760484Sobrien  /* Increment the section size to make room for the symbol.  */
186860484Sobrien  s->_raw_size += h->size;
186960484Sobrien
187060484Sobrien  return true;
187160484Sobrien}
187260484Sobrien
187360484Sobrien/* Set the sizes of the dynamic sections.  */
187460484Sobrien
187560484Sobrienstatic boolean
187660484Sobrienppc_elf_size_dynamic_sections (output_bfd, info)
187760484Sobrien     bfd *output_bfd;
187860484Sobrien     struct bfd_link_info *info;
187960484Sobrien{
188060484Sobrien  bfd *dynobj;
188160484Sobrien  asection *s;
188260484Sobrien  boolean plt;
188360484Sobrien  boolean relocs;
188460484Sobrien  boolean reltext;
188560484Sobrien
188660484Sobrien#ifdef DEBUG
188760484Sobrien  fprintf (stderr, "ppc_elf_size_dynamic_sections called\n");
188860484Sobrien#endif
188960484Sobrien
189060484Sobrien  dynobj = elf_hash_table (info)->dynobj;
189160484Sobrien  BFD_ASSERT (dynobj != NULL);
189260484Sobrien
189360484Sobrien  if (elf_hash_table (info)->dynamic_sections_created)
189460484Sobrien    {
189560484Sobrien      /* Set the contents of the .interp section to the interpreter.  */
189660484Sobrien      if (! info->shared)
189760484Sobrien	{
189860484Sobrien	  s = bfd_get_section_by_name (dynobj, ".interp");
189960484Sobrien	  BFD_ASSERT (s != NULL);
190060484Sobrien	  s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER;
190160484Sobrien	  s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
190260484Sobrien	}
190360484Sobrien    }
190460484Sobrien  else
190560484Sobrien    {
190660484Sobrien      /* We may have created entries in the .rela.got, .rela.sdata, and
190760484Sobrien	 .rela.sdata2 sections.  However, if we are not creating the
190860484Sobrien	 dynamic sections, we will not actually use these entries.  Reset
190960484Sobrien	 the size of .rela.got, et al, which will cause it to get
191060484Sobrien	 stripped from the output file below.  */
191160484Sobrien      static char *rela_sections[] = { ".rela.got", ".rela.sdata",
191260484Sobrien				       ".rela.sdata2", ".rela.sbss",
191377298Sobrien				       (char *) 0 };
191460484Sobrien      char **p;
191560484Sobrien
191677298Sobrien      for (p = rela_sections; *p != (char *) 0; p++)
191760484Sobrien	{
191860484Sobrien	  s = bfd_get_section_by_name (dynobj, *p);
191960484Sobrien	  if (s != NULL)
192060484Sobrien	    s->_raw_size = 0;
192160484Sobrien	}
192260484Sobrien    }
192360484Sobrien
192460484Sobrien  /* The check_relocs and adjust_dynamic_symbol entry points have
192560484Sobrien     determined the sizes of the various dynamic sections.  Allocate
192660484Sobrien     memory for them.  */
192760484Sobrien  plt = false;
192860484Sobrien  relocs = false;
192960484Sobrien  reltext = false;
193060484Sobrien  for (s = dynobj->sections; s != NULL; s = s->next)
193160484Sobrien    {
193260484Sobrien      const char *name;
193360484Sobrien      boolean strip;
193460484Sobrien
193560484Sobrien      if ((s->flags & SEC_LINKER_CREATED) == 0)
193660484Sobrien	continue;
193760484Sobrien
193860484Sobrien      /* It's OK to base decisions on the section name, because none
193960484Sobrien	 of the dynobj section names depend upon the input files.  */
194060484Sobrien      name = bfd_get_section_name (dynobj, s);
194160484Sobrien
194260484Sobrien      strip = false;
194360484Sobrien
194460484Sobrien      if (strcmp (name, ".plt") == 0)
194560484Sobrien	{
194660484Sobrien	  if (s->_raw_size == 0)
194760484Sobrien	    {
194860484Sobrien	      /* Strip this section if we don't need it; see the
194960484Sobrien                 comment below.  */
195060484Sobrien	      strip = true;
195160484Sobrien	    }
195260484Sobrien	  else
195360484Sobrien	    {
195460484Sobrien	      /* Remember whether there is a PLT.  */
195560484Sobrien	      plt = true;
195660484Sobrien	    }
195760484Sobrien	}
195860484Sobrien      else if (strncmp (name, ".rela", 5) == 0)
195960484Sobrien	{
196060484Sobrien	  if (s->_raw_size == 0)
196160484Sobrien	    {
196260484Sobrien	      /* If we don't need this section, strip it from the
196360484Sobrien		 output file.  This is mostly to handle .rela.bss and
196460484Sobrien		 .rela.plt.  We must create both sections in
196560484Sobrien		 create_dynamic_sections, because they must be created
196660484Sobrien		 before the linker maps input sections to output
196760484Sobrien		 sections.  The linker does that before
196860484Sobrien		 adjust_dynamic_symbol is called, and it is that
196960484Sobrien		 function which decides whether anything needs to go
197060484Sobrien		 into these sections.  */
197160484Sobrien	      strip = true;
197260484Sobrien	    }
197360484Sobrien	  else
197460484Sobrien	    {
197560484Sobrien	      asection *target;
197660484Sobrien	      const char *outname;
197760484Sobrien
197877298Sobrien	      /* Remember whether there are any relocation sections.  */
197960484Sobrien	      relocs = true;
198060484Sobrien
198160484Sobrien	      /* If this relocation section applies to a read only
198260484Sobrien		 section, then we probably need a DT_TEXTREL entry.  */
198360484Sobrien	      outname = bfd_get_section_name (output_bfd,
198460484Sobrien					      s->output_section);
198560484Sobrien	      target = bfd_get_section_by_name (output_bfd, outname + 5);
198660484Sobrien	      if (target != NULL
198760484Sobrien		  && (target->flags & SEC_READONLY) != 0
198860484Sobrien		  && (target->flags & SEC_ALLOC) != 0)
198960484Sobrien		reltext = true;
199060484Sobrien
199160484Sobrien	      /* We use the reloc_count field as a counter if we need
199260484Sobrien		 to copy relocs into the output file.  */
199360484Sobrien	      s->reloc_count = 0;
199460484Sobrien	    }
199560484Sobrien	}
199660484Sobrien      else if (strcmp (name, ".got") != 0
199760484Sobrien	       && strcmp (name, ".sdata") != 0
199860484Sobrien	       && strcmp (name, ".sdata2") != 0)
199960484Sobrien	{
200060484Sobrien	  /* It's not one of our sections, so don't allocate space.  */
200160484Sobrien	  continue;
200260484Sobrien	}
200360484Sobrien
200460484Sobrien      if (strip)
200560484Sobrien	{
200660484Sobrien	  _bfd_strip_section_from_output (info, s);
200760484Sobrien	  continue;
200860484Sobrien	}
200960484Sobrien
201060484Sobrien      /* Allocate memory for the section contents.  */
201160484Sobrien      s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size);
201260484Sobrien      if (s->contents == NULL && s->_raw_size != 0)
201360484Sobrien	return false;
201460484Sobrien    }
201560484Sobrien
201660484Sobrien  if (elf_hash_table (info)->dynamic_sections_created)
201760484Sobrien    {
201860484Sobrien      /* Add some entries to the .dynamic section.  We fill in the
201960484Sobrien	 values later, in ppc_elf_finish_dynamic_sections, but we
202060484Sobrien	 must add the entries now so that we get the correct size for
202160484Sobrien	 the .dynamic section.  The DT_DEBUG entry is filled in by the
202260484Sobrien	 dynamic linker and used by the debugger.  */
202360484Sobrien      if (! info->shared)
202460484Sobrien	{
202560484Sobrien	  if (! bfd_elf32_add_dynamic_entry (info, DT_DEBUG, 0))
202660484Sobrien	    return false;
202760484Sobrien	}
202860484Sobrien
202960484Sobrien      if (plt)
203060484Sobrien	{
203160484Sobrien	  if (! bfd_elf32_add_dynamic_entry (info, DT_PLTGOT, 0)
203260484Sobrien	      || ! bfd_elf32_add_dynamic_entry (info, DT_PLTRELSZ, 0)
203360484Sobrien	      || ! bfd_elf32_add_dynamic_entry (info, DT_PLTREL, DT_RELA)
203460484Sobrien	      || ! bfd_elf32_add_dynamic_entry (info, DT_JMPREL, 0))
203560484Sobrien	    return false;
203660484Sobrien	}
203760484Sobrien
203860484Sobrien      if (relocs)
203960484Sobrien	{
204060484Sobrien	  if (! bfd_elf32_add_dynamic_entry (info, DT_RELA, 0)
204160484Sobrien	      || ! bfd_elf32_add_dynamic_entry (info, DT_RELASZ, 0)
204260484Sobrien	      || ! bfd_elf32_add_dynamic_entry (info, DT_RELAENT,
204360484Sobrien						sizeof (Elf32_External_Rela)))
204460484Sobrien	    return false;
204560484Sobrien	}
204660484Sobrien
204760484Sobrien      if (reltext)
204860484Sobrien	{
204960484Sobrien	  if (! bfd_elf32_add_dynamic_entry (info, DT_TEXTREL, 0))
205060484Sobrien	    return false;
205177298Sobrien	  info->flags |= DF_TEXTREL;
205260484Sobrien	}
205360484Sobrien    }
205460484Sobrien
205560484Sobrien  return true;
205660484Sobrien}
205760484Sobrien
205860484Sobrien/* Look through the relocs for a section during the first phase, and
205960484Sobrien   allocate space in the global offset table or procedure linkage
206060484Sobrien   table.  */
206160484Sobrien
206260484Sobrienstatic boolean
206360484Sobrienppc_elf_check_relocs (abfd, info, sec, relocs)
206460484Sobrien     bfd *abfd;
206560484Sobrien     struct bfd_link_info *info;
206660484Sobrien     asection *sec;
206760484Sobrien     const Elf_Internal_Rela *relocs;
206860484Sobrien{
206960484Sobrien  bfd *dynobj;
207060484Sobrien  Elf_Internal_Shdr *symtab_hdr;
207160484Sobrien  struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
207260484Sobrien  const Elf_Internal_Rela *rel;
207360484Sobrien  const Elf_Internal_Rela *rel_end;
207460484Sobrien  bfd_signed_vma *local_got_refcounts;
207560484Sobrien  elf_linker_section_t *sdata;
207660484Sobrien  elf_linker_section_t *sdata2;
207760484Sobrien  asection *sreloc;
207860484Sobrien  asection *sgot = NULL;
207960484Sobrien  asection *srelgot = NULL;
208060484Sobrien
208160484Sobrien  if (info->relocateable)
208260484Sobrien    return true;
208360484Sobrien
208460484Sobrien#ifdef DEBUG
208560484Sobrien  fprintf (stderr, "ppc_elf_check_relocs called for section %s in %s\n",
208660484Sobrien	   bfd_get_section_name (abfd, sec),
208760484Sobrien	   bfd_get_filename (abfd));
208860484Sobrien#endif
208960484Sobrien
209060484Sobrien  /* Create the linker generated sections all the time so that the
209160484Sobrien     special symbols are created.  */
209260484Sobrien
209360484Sobrien  if ((sdata = elf_linker_section (abfd, LINKER_SECTION_SDATA)) == NULL)
209460484Sobrien    {
209560484Sobrien      sdata = ppc_elf_create_linker_section (abfd, info, LINKER_SECTION_SDATA);
209660484Sobrien      if (!sdata)
209760484Sobrien	return false;
209860484Sobrien    }
209960484Sobrien
210060484Sobrien  if ((sdata2 = elf_linker_section (abfd, LINKER_SECTION_SDATA2)) == NULL)
210160484Sobrien    {
210260484Sobrien      sdata2 = ppc_elf_create_linker_section (abfd, info, LINKER_SECTION_SDATA2);
210360484Sobrien      if (!sdata2)
210460484Sobrien	return false;
210560484Sobrien    }
210660484Sobrien
210760484Sobrien  dynobj = elf_hash_table (info)->dynobj;
210860484Sobrien  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
210960484Sobrien  local_got_refcounts = elf_local_got_refcounts (abfd);
211060484Sobrien
211160484Sobrien  sym_hashes = elf_sym_hashes (abfd);
211277298Sobrien  sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof (Elf32_External_Sym);
211360484Sobrien  if (!elf_bad_symtab (abfd))
211460484Sobrien    sym_hashes_end -= symtab_hdr->sh_info;
211560484Sobrien
211660484Sobrien  sreloc = NULL;
211760484Sobrien
211860484Sobrien  rel_end = relocs + sec->reloc_count;
211960484Sobrien  for (rel = relocs; rel < rel_end; rel++)
212060484Sobrien    {
212160484Sobrien      unsigned long r_symndx;
212260484Sobrien      struct elf_link_hash_entry *h;
212360484Sobrien
212460484Sobrien      r_symndx = ELF32_R_SYM (rel->r_info);
212560484Sobrien      if (r_symndx < symtab_hdr->sh_info)
212660484Sobrien	h = NULL;
212760484Sobrien      else
212860484Sobrien	h = sym_hashes[r_symndx - symtab_hdr->sh_info];
212960484Sobrien
213060484Sobrien      /* If a relocation refers to _GLOBAL_OFFSET_TABLE_, create the .got.
213160484Sobrien	 This shows up in particular in an R_PPC_ADDR32 in the eabi
213260484Sobrien	 startup code.  */
213360484Sobrien      if (h && strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
213460484Sobrien	{
213560484Sobrien	  if (sgot == NULL)
213660484Sobrien	    {
213760484Sobrien	      if (dynobj == NULL)
213860484Sobrien		elf_hash_table (info)->dynobj = dynobj = abfd;
213960484Sobrien	      if (! _bfd_elf_create_got_section (dynobj, info))
214060484Sobrien		return false;
214160484Sobrien	      sgot = bfd_get_section_by_name (dynobj, ".got");
214260484Sobrien	      BFD_ASSERT (sgot != NULL);
214360484Sobrien	    }
214460484Sobrien	}
214560484Sobrien
214660484Sobrien      switch (ELF32_R_TYPE (rel->r_info))
214760484Sobrien	{
214860484Sobrien	/* GOT16 relocations */
214960484Sobrien	case R_PPC_GOT16:
215060484Sobrien	case R_PPC_GOT16_LO:
215160484Sobrien	case R_PPC_GOT16_HI:
215260484Sobrien	case R_PPC_GOT16_HA:
215360484Sobrien	  /* This symbol requires a global offset table entry.  */
215460484Sobrien
215560484Sobrien	  if (sgot == NULL)
215660484Sobrien	    {
215760484Sobrien	      if (dynobj == NULL)
215860484Sobrien		elf_hash_table (info)->dynobj = dynobj = abfd;
215960484Sobrien	      if (! _bfd_elf_create_got_section (dynobj, info))
216060484Sobrien		return false;
216160484Sobrien	      sgot = bfd_get_section_by_name (dynobj, ".got");
216260484Sobrien	      BFD_ASSERT (sgot != NULL);
216360484Sobrien	    }
216460484Sobrien
216560484Sobrien	  if (srelgot == NULL
216660484Sobrien	      && (h != NULL || info->shared))
216760484Sobrien	    {
216860484Sobrien	      srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
216960484Sobrien	      if (srelgot == NULL)
217060484Sobrien		{
217160484Sobrien		  srelgot = bfd_make_section (dynobj, ".rela.got");
217260484Sobrien		  if (srelgot == NULL
217360484Sobrien		      || ! bfd_set_section_flags (dynobj, srelgot,
217460484Sobrien						  (SEC_ALLOC
217560484Sobrien						   | SEC_LOAD
217660484Sobrien						   | SEC_HAS_CONTENTS
217760484Sobrien						   | SEC_IN_MEMORY
217860484Sobrien						   | SEC_LINKER_CREATED
217960484Sobrien						   | SEC_READONLY))
218060484Sobrien		      || ! bfd_set_section_alignment (dynobj, srelgot, 2))
218160484Sobrien		    return false;
218260484Sobrien		}
218360484Sobrien	    }
218460484Sobrien
218560484Sobrien	  if (h != NULL)
218660484Sobrien	    {
218760484Sobrien	      if (h->got.refcount == -1)
218860484Sobrien		{
218960484Sobrien		  /* Make sure this symbol is output as a dynamic symbol.  */
219060484Sobrien		  if (h->dynindx == -1)
219160484Sobrien		    if (!bfd_elf32_link_record_dynamic_symbol (info, h))
219260484Sobrien		      return false;
219360484Sobrien
219460484Sobrien		  /* Allocate space in the .got.  */
219560484Sobrien		  sgot->_raw_size += 4;
219660484Sobrien		  /* Allocate relocation space.  */
219760484Sobrien		  srelgot->_raw_size += sizeof (Elf32_External_Rela);
219860484Sobrien
219960484Sobrien		  h->got.refcount = 1;
220060484Sobrien		}
220160484Sobrien	      else
220260484Sobrien		h->got.refcount++;
220360484Sobrien	    }
220460484Sobrien	  else
220560484Sobrien	    {
220660484Sobrien	      /* This is a global offset table entry for a local symbol.  */
220760484Sobrien	      if (local_got_refcounts == NULL)
220860484Sobrien		{
220960484Sobrien		  size_t size;
221060484Sobrien
221160484Sobrien		  size = symtab_hdr->sh_info * sizeof (bfd_signed_vma);
221260484Sobrien		  local_got_refcounts = (bfd_signed_vma *)
221360484Sobrien		    bfd_alloc (abfd, size);
221460484Sobrien		  if (local_got_refcounts == NULL)
221560484Sobrien		    return false;
221660484Sobrien		  elf_local_got_refcounts (abfd) = local_got_refcounts;
221760484Sobrien		  memset (local_got_refcounts, -1, size);
221860484Sobrien		}
221960484Sobrien	      if (local_got_refcounts[r_symndx] == -1)
222060484Sobrien		{
222160484Sobrien		  sgot->_raw_size += 4;
222260484Sobrien
222360484Sobrien		  /* If we are generating a shared object, we need to
222460484Sobrien                     output a R_PPC_RELATIVE reloc so that the
222560484Sobrien                     dynamic linker can adjust this GOT entry.  */
222660484Sobrien		  if (info->shared)
222760484Sobrien		    srelgot->_raw_size += sizeof (Elf32_External_Rela);
222860484Sobrien
222960484Sobrien		  local_got_refcounts[r_symndx] = 1;
223060484Sobrien		}
223160484Sobrien	      else
223260484Sobrien		local_got_refcounts[r_symndx]++;
223360484Sobrien	    }
223460484Sobrien	  break;
223560484Sobrien
223660484Sobrien	/* Indirect .sdata relocation */
223760484Sobrien	case R_PPC_EMB_SDAI16:
223860484Sobrien	  if (info->shared)
223960484Sobrien	    {
224060484Sobrien	      ((*_bfd_error_handler)
224160484Sobrien	       (_("%s: relocation %s cannot be used when making a shared object"),
224260484Sobrien		bfd_get_filename (abfd), "R_PPC_EMB_SDAI16"));
224377298Sobrien	      return false;
224460484Sobrien	    }
224560484Sobrien
224660484Sobrien	  if (srelgot == NULL && (h != NULL || info->shared))
224760484Sobrien	    {
224860484Sobrien	      srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
224960484Sobrien	      if (srelgot == NULL)
225060484Sobrien		{
225160484Sobrien		  srelgot = bfd_make_section (dynobj, ".rela.got");
225260484Sobrien		  if (srelgot == NULL
225360484Sobrien		      || ! bfd_set_section_flags (dynobj, srelgot,
225460484Sobrien						  (SEC_ALLOC
225560484Sobrien						   | SEC_LOAD
225660484Sobrien						   | SEC_HAS_CONTENTS
225760484Sobrien						   | SEC_IN_MEMORY
225860484Sobrien						   | SEC_LINKER_CREATED
225960484Sobrien						   | SEC_READONLY))
226060484Sobrien		      || ! bfd_set_section_alignment (dynobj, srelgot, 2))
226160484Sobrien		    return false;
226260484Sobrien		}
226360484Sobrien	    }
226460484Sobrien
226560484Sobrien	  if (!bfd_elf32_create_pointer_linker_section (abfd, info, sdata, h, rel))
226660484Sobrien	    return false;
226760484Sobrien
226860484Sobrien	  break;
226960484Sobrien
227060484Sobrien	/* Indirect .sdata2 relocation */
227160484Sobrien	case R_PPC_EMB_SDA2I16:
227260484Sobrien	  if (info->shared)
227360484Sobrien	    {
227460484Sobrien	      ((*_bfd_error_handler)
227560484Sobrien	       (_("%s: relocation %s cannot be used when making a shared object"),
227660484Sobrien		bfd_get_filename (abfd), "R_PPC_EMB_SDA2I16"));
227760484Sobrien	      return false;
227860484Sobrien	    }
227960484Sobrien
228060484Sobrien	  if (srelgot == NULL && (h != NULL || info->shared))
228160484Sobrien	    {
228260484Sobrien	      srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
228360484Sobrien	      if (srelgot == NULL)
228460484Sobrien		{
228560484Sobrien		  srelgot = bfd_make_section (dynobj, ".rela.got");
228660484Sobrien		  if (srelgot == NULL
228760484Sobrien		      || ! bfd_set_section_flags (dynobj, srelgot,
228860484Sobrien						  (SEC_ALLOC
228960484Sobrien						   | SEC_LOAD
229060484Sobrien						   | SEC_HAS_CONTENTS
229160484Sobrien						   | SEC_IN_MEMORY
229260484Sobrien						   | SEC_LINKER_CREATED
229360484Sobrien						   | SEC_READONLY))
229460484Sobrien		      || ! bfd_set_section_alignment (dynobj, srelgot, 2))
229560484Sobrien		    return false;
229660484Sobrien		}
229760484Sobrien	    }
229860484Sobrien
229960484Sobrien	  if (!bfd_elf32_create_pointer_linker_section (abfd, info, sdata2, h, rel))
230060484Sobrien	    return false;
230160484Sobrien
230260484Sobrien	  break;
230360484Sobrien
230460484Sobrien	case R_PPC_SDAREL16:
230560484Sobrien	case R_PPC_EMB_SDA2REL:
230660484Sobrien	case R_PPC_EMB_SDA21:
230760484Sobrien	  if (info->shared)
230860484Sobrien	    {
230960484Sobrien	      ((*_bfd_error_handler)
231060484Sobrien	       (_("%s: relocation %s cannot be used when making a shared object"),
231160484Sobrien		bfd_get_filename (abfd),
231277298Sobrien		ppc_elf_howto_table[(int) ELF32_R_TYPE (rel->r_info)]->name));
231360484Sobrien	      return false;
231460484Sobrien	    }
231560484Sobrien	  break;
231660484Sobrien
231760484Sobrien	case R_PPC_PLT32:
231860484Sobrien	case R_PPC_PLTREL24:
231960484Sobrien	case R_PPC_PLT16_LO:
232060484Sobrien	case R_PPC_PLT16_HI:
232160484Sobrien	case R_PPC_PLT16_HA:
232260484Sobrien#ifdef DEBUG
232360484Sobrien	  fprintf (stderr, "Reloc requires a PLT entry\n");
232460484Sobrien#endif
232560484Sobrien	  /* This symbol requires a procedure linkage table entry.  We
232660484Sobrien             actually build the entry in adjust_dynamic_symbol,
232760484Sobrien             because this might be a case of linking PIC code without
232860484Sobrien             linking in any dynamic objects, in which case we don't
232960484Sobrien             need to generate a procedure linkage table after all.  */
233060484Sobrien
233160484Sobrien	  if (h == NULL)
233260484Sobrien	    {
233360484Sobrien	      /* It does not make sense to have a procedure linkage
233460484Sobrien                 table entry for a local symbol.  */
233560484Sobrien	      bfd_set_error (bfd_error_bad_value);
233660484Sobrien	      return false;
233760484Sobrien	    }
233860484Sobrien
233960484Sobrien	  /* Make sure this symbol is output as a dynamic symbol.  */
234060484Sobrien	  if (h->dynindx == -1)
234160484Sobrien	    {
234260484Sobrien	      if (! bfd_elf32_link_record_dynamic_symbol (info, h))
234360484Sobrien		return false;
234460484Sobrien	    }
234560484Sobrien	  if (h->plt.refcount == -1)
234660484Sobrien	    {
234760484Sobrien	      h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
234860484Sobrien	      h->plt.refcount = 1;
234960484Sobrien	    }
235060484Sobrien	  else
235160484Sobrien	    h->plt.refcount++;
235260484Sobrien	  break;
235360484Sobrien
235460484Sobrien	  /* The following relocations don't need to propagate the
235560484Sobrien	     relocation if linking a shared object since they are
235660484Sobrien	     section relative.  */
235760484Sobrien	case R_PPC_SECTOFF:
235860484Sobrien	case R_PPC_SECTOFF_LO:
235960484Sobrien	case R_PPC_SECTOFF_HI:
236060484Sobrien	case R_PPC_SECTOFF_HA:
236160484Sobrien	  break;
236260484Sobrien
236360484Sobrien	  /* This refers only to functions defined in the shared library */
236460484Sobrien	case R_PPC_LOCAL24PC:
236560484Sobrien	  break;
236660484Sobrien
236760484Sobrien	  /* This relocation describes the C++ object vtable hierarchy.
236860484Sobrien	     Reconstruct it for later use during GC.  */
236960484Sobrien	case R_PPC_GNU_VTINHERIT:
237060484Sobrien	  if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
237160484Sobrien	    return false;
237260484Sobrien	  break;
237360484Sobrien
237460484Sobrien	  /* This relocation describes which C++ vtable entries are actually
237560484Sobrien	     used.  Record for later use during GC.  */
237660484Sobrien	case R_PPC_GNU_VTENTRY:
237760484Sobrien	  if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
237860484Sobrien	    return false;
237960484Sobrien	  break;
238060484Sobrien
238160484Sobrien	  /* When creating a shared object, we must copy these
238260484Sobrien	     relocs into the output file.  We create a reloc
238360484Sobrien	     section in dynobj and make room for the reloc.  */
238460484Sobrien	case R_PPC_REL24:
238560484Sobrien	case R_PPC_REL14:
238660484Sobrien	case R_PPC_REL14_BRTAKEN:
238760484Sobrien	case R_PPC_REL14_BRNTAKEN:
238860484Sobrien	case R_PPC_REL32:
238960484Sobrien	  if (h == NULL
239077298Sobrien	      || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0
239177298Sobrien	      || SYMBOL_REFERENCES_LOCAL (info, h))
239260484Sobrien	    break;
239360484Sobrien	  /* fall through */
239460484Sobrien
239560484Sobrien	default:
239660484Sobrien	  if (info->shared)
239760484Sobrien	    {
239860484Sobrien#ifdef DEBUG
239960484Sobrien	      fprintf (stderr, "ppc_elf_check_relocs need to create relocation for %s\n",
240060484Sobrien		       (h && h->root.root.string) ? h->root.root.string : "<unknown>");
240160484Sobrien#endif
240260484Sobrien	      if (sreloc == NULL)
240360484Sobrien		{
240460484Sobrien		  const char *name;
240560484Sobrien
240660484Sobrien		  name = (bfd_elf_string_from_elf_section
240760484Sobrien			  (abfd,
240860484Sobrien			   elf_elfheader (abfd)->e_shstrndx,
240960484Sobrien			   elf_section_data (sec)->rel_hdr.sh_name));
241060484Sobrien		  if (name == NULL)
241160484Sobrien		    return false;
241260484Sobrien
241360484Sobrien		  BFD_ASSERT (strncmp (name, ".rela", 5) == 0
241460484Sobrien			      && strcmp (bfd_get_section_name (abfd, sec),
241560484Sobrien					 name + 5) == 0);
241660484Sobrien
241760484Sobrien		  sreloc = bfd_get_section_by_name (dynobj, name);
241860484Sobrien		  if (sreloc == NULL)
241960484Sobrien		    {
242060484Sobrien		      flagword flags;
242160484Sobrien
242260484Sobrien		      sreloc = bfd_make_section (dynobj, name);
242360484Sobrien		      flags = (SEC_HAS_CONTENTS | SEC_READONLY
242460484Sobrien			       | SEC_IN_MEMORY | SEC_LINKER_CREATED);
242560484Sobrien		      if ((sec->flags & SEC_ALLOC) != 0)
242660484Sobrien			flags |= SEC_ALLOC | SEC_LOAD;
242760484Sobrien		      if (sreloc == NULL
242860484Sobrien			  || ! bfd_set_section_flags (dynobj, sreloc, flags)
242960484Sobrien			  || ! bfd_set_section_alignment (dynobj, sreloc, 2))
243060484Sobrien			return false;
243160484Sobrien		    }
243260484Sobrien		}
243360484Sobrien
243460484Sobrien	      sreloc->_raw_size += sizeof (Elf32_External_Rela);
243560484Sobrien
243660484Sobrien	      /* FIXME: We should here do what the m68k and i386
243760484Sobrien		 backends do: if the reloc is pc-relative, record it
243860484Sobrien		 in case it turns out that the reloc is unnecessary
243960484Sobrien		 because the symbol is forced local by versioning or
244060484Sobrien		 we are linking with -Bdynamic.  Fortunately this
244160484Sobrien		 case is not frequent.  */
244260484Sobrien	    }
244360484Sobrien
244460484Sobrien	  break;
244560484Sobrien	}
244660484Sobrien    }
244760484Sobrien
244860484Sobrien  return true;
244960484Sobrien}
245060484Sobrien
245160484Sobrien/* Return the section that should be marked against GC for a given
245260484Sobrien   relocation.  */
245360484Sobrien
245460484Sobrienstatic asection *
245560484Sobrienppc_elf_gc_mark_hook (abfd, info, rel, h, sym)
245660484Sobrien     bfd *abfd;
245760484Sobrien     struct bfd_link_info *info ATTRIBUTE_UNUSED;
245860484Sobrien     Elf_Internal_Rela *rel;
245960484Sobrien     struct elf_link_hash_entry *h;
246060484Sobrien     Elf_Internal_Sym *sym;
246160484Sobrien{
246260484Sobrien  if (h != NULL)
246360484Sobrien    {
246460484Sobrien      switch (ELF32_R_TYPE (rel->r_info))
246560484Sobrien	{
246660484Sobrien	case R_PPC_GNU_VTINHERIT:
246760484Sobrien	case R_PPC_GNU_VTENTRY:
246860484Sobrien	  break;
246960484Sobrien
247060484Sobrien	default:
247160484Sobrien	  switch (h->root.type)
247260484Sobrien	    {
247360484Sobrien	    case bfd_link_hash_defined:
247460484Sobrien	    case bfd_link_hash_defweak:
247560484Sobrien	      return h->root.u.def.section;
247660484Sobrien
247760484Sobrien	    case bfd_link_hash_common:
247860484Sobrien	      return h->root.u.c.p->section;
247960484Sobrien
248060484Sobrien	    default:
248160484Sobrien	      break;
248260484Sobrien	    }
248360484Sobrien	}
248460484Sobrien    }
248560484Sobrien  else
248660484Sobrien    {
248760484Sobrien      if (!(elf_bad_symtab (abfd)
248860484Sobrien	    && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
248960484Sobrien	  && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
249060484Sobrien		&& sym->st_shndx != SHN_COMMON))
249160484Sobrien	{
249260484Sobrien	  return bfd_section_from_elf_index (abfd, sym->st_shndx);
249360484Sobrien	}
249460484Sobrien    }
249560484Sobrien
249660484Sobrien  return NULL;
249760484Sobrien}
249860484Sobrien
249960484Sobrien/* Update the got entry reference counts for the section being removed.  */
250060484Sobrien
250160484Sobrienstatic boolean
250260484Sobrienppc_elf_gc_sweep_hook (abfd, info, sec, relocs)
250360484Sobrien     bfd *abfd;
250460484Sobrien     struct bfd_link_info *info ATTRIBUTE_UNUSED;
250560484Sobrien     asection *sec;
250660484Sobrien     const Elf_Internal_Rela *relocs;
250760484Sobrien{
250860484Sobrien  Elf_Internal_Shdr *symtab_hdr;
250960484Sobrien  struct elf_link_hash_entry **sym_hashes;
251060484Sobrien  bfd_signed_vma *local_got_refcounts;
251160484Sobrien  const Elf_Internal_Rela *rel, *relend;
251260484Sobrien  unsigned long r_symndx;
251360484Sobrien  struct elf_link_hash_entry *h;
251460484Sobrien
251560484Sobrien  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
251660484Sobrien  sym_hashes = elf_sym_hashes (abfd);
251760484Sobrien  local_got_refcounts = elf_local_got_refcounts (abfd);
251860484Sobrien
251960484Sobrien  relend = relocs + sec->reloc_count;
252060484Sobrien  for (rel = relocs; rel < relend; rel++)
252160484Sobrien    switch (ELF32_R_TYPE (rel->r_info))
252260484Sobrien      {
252360484Sobrien      case R_PPC_GOT16:
252460484Sobrien      case R_PPC_GOT16_LO:
252560484Sobrien      case R_PPC_GOT16_HI:
252660484Sobrien      case R_PPC_GOT16_HA:
252760484Sobrien	r_symndx = ELF32_R_SYM (rel->r_info);
252860484Sobrien	if (r_symndx >= symtab_hdr->sh_info)
252960484Sobrien	  {
253060484Sobrien	    h = sym_hashes[r_symndx - symtab_hdr->sh_info];
253160484Sobrien	    if (h->got.refcount > 0)
253260484Sobrien	      h->got.refcount--;
253360484Sobrien	  }
253477298Sobrien	else if (local_got_refcounts != NULL)
253560484Sobrien	  {
253660484Sobrien	    if (local_got_refcounts[r_symndx] > 0)
253760484Sobrien	      local_got_refcounts[r_symndx]--;
253860484Sobrien	  }
253960484Sobrien        break;
254060484Sobrien
254160484Sobrien      case R_PPC_PLT32:
254260484Sobrien      case R_PPC_PLTREL24:
254360484Sobrien      case R_PPC_PLT16_LO:
254460484Sobrien      case R_PPC_PLT16_HI:
254560484Sobrien      case R_PPC_PLT16_HA:
254660484Sobrien	r_symndx = ELF32_R_SYM (rel->r_info);
254760484Sobrien	if (r_symndx >= symtab_hdr->sh_info)
254860484Sobrien	  {
254960484Sobrien	    h = sym_hashes[r_symndx - symtab_hdr->sh_info];
255060484Sobrien	    if (h->plt.refcount > 0)
255160484Sobrien	      h->plt.refcount--;
255260484Sobrien	  }
255360484Sobrien	break;
255460484Sobrien
255560484Sobrien      default:
255660484Sobrien	break;
255760484Sobrien      }
255860484Sobrien
255960484Sobrien  return true;
256060484Sobrien}
256160484Sobrien
256260484Sobrien/* Hook called by the linker routine which adds symbols from an object
256360484Sobrien   file.  We use it to put .comm items in .sbss, and not .bss.  */
256460484Sobrien
256560484Sobrienstatic boolean
256660484Sobrienppc_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
256760484Sobrien     bfd *abfd;
256860484Sobrien     struct bfd_link_info *info;
256960484Sobrien     const Elf_Internal_Sym *sym;
257060484Sobrien     const char **namep ATTRIBUTE_UNUSED;
257160484Sobrien     flagword *flagsp ATTRIBUTE_UNUSED;
257260484Sobrien     asection **secp;
257360484Sobrien     bfd_vma *valp;
257460484Sobrien{
257560484Sobrien  if (sym->st_shndx == SHN_COMMON
257660484Sobrien      && !info->relocateable
257760484Sobrien      && sym->st_size <= (bfd_vma) bfd_get_gp_size (abfd))
257860484Sobrien    {
257960484Sobrien      /* Common symbols less than or equal to -G nn bytes are automatically
258060484Sobrien	 put into .sdata.  */
258160484Sobrien      elf_linker_section_t *sdata
258260484Sobrien	= ppc_elf_create_linker_section (abfd, info, LINKER_SECTION_SDATA);
258360484Sobrien
258460484Sobrien      if (!sdata->bss_section)
258560484Sobrien	{
258660484Sobrien	  /* We don't go through bfd_make_section, because we don't
258760484Sobrien             want to attach this common section to DYNOBJ.  The linker
258860484Sobrien             will move the symbols to the appropriate output section
258960484Sobrien             when it defines common symbols.  */
259060484Sobrien	  sdata->bss_section = ((asection *)
259160484Sobrien				bfd_zalloc (abfd, sizeof (asection)));
259260484Sobrien	  if (sdata->bss_section == NULL)
259360484Sobrien	    return false;
259460484Sobrien	  sdata->bss_section->name = sdata->bss_name;
259560484Sobrien	  sdata->bss_section->flags = SEC_IS_COMMON;
259660484Sobrien	  sdata->bss_section->output_section = sdata->bss_section;
259760484Sobrien	  sdata->bss_section->symbol =
259860484Sobrien	    (asymbol *) bfd_zalloc (abfd, sizeof (asymbol));
259960484Sobrien	  sdata->bss_section->symbol_ptr_ptr =
260060484Sobrien	    (asymbol **) bfd_zalloc (abfd, sizeof (asymbol *));
260160484Sobrien	  if (sdata->bss_section->symbol == NULL
260260484Sobrien	      || sdata->bss_section->symbol_ptr_ptr == NULL)
260360484Sobrien	    return false;
260460484Sobrien	  sdata->bss_section->symbol->name = sdata->bss_name;
260560484Sobrien	  sdata->bss_section->symbol->flags = BSF_SECTION_SYM;
260660484Sobrien	  sdata->bss_section->symbol->section = sdata->bss_section;
260760484Sobrien	  *sdata->bss_section->symbol_ptr_ptr = sdata->bss_section->symbol;
260860484Sobrien	}
260960484Sobrien
261060484Sobrien      *secp = sdata->bss_section;
261160484Sobrien      *valp = sym->st_size;
261260484Sobrien    }
261360484Sobrien
261460484Sobrien  return true;
261560484Sobrien}
261660484Sobrien
261760484Sobrien/* Finish up dynamic symbol handling.  We set the contents of various
261860484Sobrien   dynamic sections here.  */
261960484Sobrien
262060484Sobrienstatic boolean
262160484Sobrienppc_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
262260484Sobrien     bfd *output_bfd;
262360484Sobrien     struct bfd_link_info *info;
262460484Sobrien     struct elf_link_hash_entry *h;
262560484Sobrien     Elf_Internal_Sym *sym;
262660484Sobrien{
262760484Sobrien  bfd *dynobj;
262860484Sobrien
262960484Sobrien#ifdef DEBUG
263060484Sobrien  fprintf (stderr, "ppc_elf_finish_dynamic_symbol called for %s",
263160484Sobrien	   h->root.root.string);
263260484Sobrien#endif
263360484Sobrien
263460484Sobrien  dynobj = elf_hash_table (info)->dynobj;
263560484Sobrien  BFD_ASSERT (dynobj != NULL);
263660484Sobrien
263760484Sobrien  if (h->plt.offset != (bfd_vma) -1)
263860484Sobrien    {
263960484Sobrien      asection *splt;
264060484Sobrien      asection *srela;
264160484Sobrien      Elf_Internal_Rela rela;
264260484Sobrien      bfd_vma reloc_index;
264360484Sobrien
264460484Sobrien#ifdef DEBUG
264560484Sobrien      fprintf (stderr, ", plt_offset = %d", h->plt.offset);
264660484Sobrien#endif
264760484Sobrien
264860484Sobrien      /* This symbol has an entry in the procedure linkage table.  Set
264960484Sobrien         it up.  */
265060484Sobrien
265160484Sobrien      BFD_ASSERT (h->dynindx != -1);
265260484Sobrien
265360484Sobrien      splt = bfd_get_section_by_name (dynobj, ".plt");
265460484Sobrien      srela = bfd_get_section_by_name (dynobj, ".rela.plt");
265560484Sobrien      BFD_ASSERT (splt != NULL && srela != NULL);
265660484Sobrien
265760484Sobrien      /* We don't need to fill in the .plt.  The ppc dynamic linker
265860484Sobrien	 will fill it in.  */
265960484Sobrien
266060484Sobrien      /* Fill in the entry in the .rela.plt section.  */
266160484Sobrien      rela.r_offset = (splt->output_section->vma
266260484Sobrien		       + splt->output_offset
266360484Sobrien		       + h->plt.offset);
266460484Sobrien      rela.r_info = ELF32_R_INFO (h->dynindx, R_PPC_JMP_SLOT);
266560484Sobrien      rela.r_addend = 0;
266660484Sobrien
266760484Sobrien      reloc_index = (h->plt.offset - PLT_INITIAL_ENTRY_SIZE) / PLT_SLOT_SIZE;
266860484Sobrien      if (reloc_index > PLT_NUM_SINGLE_ENTRIES)
266960484Sobrien	reloc_index -= (reloc_index - PLT_NUM_SINGLE_ENTRIES) / 2;
267060484Sobrien      bfd_elf32_swap_reloca_out (output_bfd, &rela,
267160484Sobrien				 ((Elf32_External_Rela *) srela->contents
267260484Sobrien				  + reloc_index));
267360484Sobrien
267460484Sobrien      if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
267560484Sobrien	{
267660484Sobrien	  /* Mark the symbol as undefined, rather than as defined in
267760484Sobrien	     the .plt section.  Leave the value alone.  */
267860484Sobrien	  sym->st_shndx = SHN_UNDEF;
267968765Sobrien	  /* If the symbol is weak, we do need to clear the value.
268068765Sobrien	     Otherwise, the PLT entry would provide a definition for
268168765Sobrien	     the symbol even if the symbol wasn't defined anywhere,
268268765Sobrien	     and so the symbol would never be NULL.  */
268377298Sobrien	  if ((h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR_NONWEAK)
268468765Sobrien	      == 0)
268568765Sobrien	    sym->st_value = 0;
268660484Sobrien	}
268760484Sobrien    }
268860484Sobrien
268960484Sobrien  if (h->got.offset != (bfd_vma) -1)
269060484Sobrien    {
269160484Sobrien      asection *sgot;
269260484Sobrien      asection *srela;
269360484Sobrien      Elf_Internal_Rela rela;
269460484Sobrien
269560484Sobrien      /* This symbol has an entry in the global offset table.  Set it
269660484Sobrien         up.  */
269760484Sobrien
269860484Sobrien      sgot = bfd_get_section_by_name (dynobj, ".got");
269960484Sobrien      srela = bfd_get_section_by_name (dynobj, ".rela.got");
270060484Sobrien      BFD_ASSERT (sgot != NULL && srela != NULL);
270160484Sobrien
270260484Sobrien      rela.r_offset = (sgot->output_section->vma
270360484Sobrien		       + sgot->output_offset
270460484Sobrien		       + (h->got.offset &~ 1));
270560484Sobrien
270660484Sobrien      /* If this is a -Bsymbolic link, and the symbol is defined
270760484Sobrien	 locally, we just want to emit a RELATIVE reloc.  The entry in
270860484Sobrien	 the global offset table will already have been initialized in
270960484Sobrien	 the relocate_section function.  */
271060484Sobrien      if (info->shared
271177298Sobrien	  && SYMBOL_REFERENCES_LOCAL (info, h))
271260484Sobrien	{
271360484Sobrien	  rela.r_info = ELF32_R_INFO (0, R_PPC_RELATIVE);
271460484Sobrien	  rela.r_addend = (h->root.u.def.value
271560484Sobrien			   + h->root.u.def.section->output_section->vma
271660484Sobrien			   + h->root.u.def.section->output_offset);
271760484Sobrien	}
271860484Sobrien      else
271960484Sobrien	{
272077298Sobrien	  BFD_ASSERT ((h->got.offset & 1) == 0);
272160484Sobrien	  bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + h->got.offset);
272260484Sobrien	  rela.r_info = ELF32_R_INFO (h->dynindx, R_PPC_GLOB_DAT);
272360484Sobrien	  rela.r_addend = 0;
272460484Sobrien	}
272560484Sobrien
272660484Sobrien      bfd_elf32_swap_reloca_out (output_bfd, &rela,
272760484Sobrien				 ((Elf32_External_Rela *) srela->contents
272860484Sobrien				  + srela->reloc_count));
272960484Sobrien      ++srela->reloc_count;
273060484Sobrien    }
273160484Sobrien
273260484Sobrien  if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_COPY) != 0)
273360484Sobrien    {
273460484Sobrien      asection *s;
273560484Sobrien      Elf_Internal_Rela rela;
273660484Sobrien
273760484Sobrien      /* This symbols needs a copy reloc.  Set it up.  */
273860484Sobrien
273960484Sobrien#ifdef DEBUG
274060484Sobrien      fprintf (stderr, ", copy");
274160484Sobrien#endif
274260484Sobrien
274360484Sobrien      BFD_ASSERT (h->dynindx != -1);
274460484Sobrien
274560484Sobrien      if (h->size <= elf_gp_size (dynobj))
274660484Sobrien	s = bfd_get_section_by_name (h->root.u.def.section->owner,
274760484Sobrien				     ".rela.sbss");
274860484Sobrien      else
274960484Sobrien	s = bfd_get_section_by_name (h->root.u.def.section->owner,
275060484Sobrien				     ".rela.bss");
275160484Sobrien      BFD_ASSERT (s != NULL);
275260484Sobrien
275360484Sobrien      rela.r_offset = (h->root.u.def.value
275460484Sobrien		       + h->root.u.def.section->output_section->vma
275560484Sobrien		       + h->root.u.def.section->output_offset);
275660484Sobrien      rela.r_info = ELF32_R_INFO (h->dynindx, R_PPC_COPY);
275760484Sobrien      rela.r_addend = 0;
275860484Sobrien      bfd_elf32_swap_reloca_out (output_bfd, &rela,
275960484Sobrien				 ((Elf32_External_Rela *) s->contents
276060484Sobrien				  + s->reloc_count));
276160484Sobrien      ++s->reloc_count;
276260484Sobrien    }
276360484Sobrien
276460484Sobrien#ifdef DEBUG
276560484Sobrien  fprintf (stderr, "\n");
276660484Sobrien#endif
276760484Sobrien
276860484Sobrien  /* Mark some specially defined symbols as absolute.  */
276960484Sobrien  if (strcmp (h->root.root.string, "_DYNAMIC") == 0
277060484Sobrien      || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0
277160484Sobrien      || strcmp (h->root.root.string, "_PROCEDURE_LINKAGE_TABLE_") == 0)
277260484Sobrien    sym->st_shndx = SHN_ABS;
277360484Sobrien
277460484Sobrien  return true;
277560484Sobrien}
277660484Sobrien
277760484Sobrien/* Finish up the dynamic sections.  */
277860484Sobrien
277960484Sobrienstatic boolean
278060484Sobrienppc_elf_finish_dynamic_sections (output_bfd, info)
278160484Sobrien     bfd *output_bfd;
278260484Sobrien     struct bfd_link_info *info;
278360484Sobrien{
278460484Sobrien  asection *sdyn;
278560484Sobrien  bfd *dynobj = elf_hash_table (info)->dynobj;
278660484Sobrien  asection *sgot = bfd_get_section_by_name (dynobj, ".got");
278760484Sobrien
278860484Sobrien#ifdef DEBUG
278960484Sobrien  fprintf (stderr, "ppc_elf_finish_dynamic_sections called\n");
279060484Sobrien#endif
279160484Sobrien
279260484Sobrien  sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
279360484Sobrien
279460484Sobrien  if (elf_hash_table (info)->dynamic_sections_created)
279560484Sobrien    {
279660484Sobrien      asection *splt;
279760484Sobrien      Elf32_External_Dyn *dyncon, *dynconend;
279860484Sobrien
279960484Sobrien      splt = bfd_get_section_by_name (dynobj, ".plt");
280060484Sobrien      BFD_ASSERT (splt != NULL && sdyn != NULL);
280160484Sobrien
280260484Sobrien      dyncon = (Elf32_External_Dyn *) sdyn->contents;
280360484Sobrien      dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->_raw_size);
280460484Sobrien      for (; dyncon < dynconend; dyncon++)
280560484Sobrien	{
280660484Sobrien	  Elf_Internal_Dyn dyn;
280760484Sobrien	  const char *name;
280860484Sobrien	  boolean size;
280960484Sobrien
281060484Sobrien	  bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn);
281160484Sobrien
281260484Sobrien	  switch (dyn.d_tag)
281360484Sobrien	    {
281460484Sobrien	    case DT_PLTGOT:   name = ".plt";	  size = false; break;
281560484Sobrien	    case DT_PLTRELSZ: name = ".rela.plt"; size = true;  break;
281660484Sobrien	    case DT_JMPREL:   name = ".rela.plt"; size = false; break;
281760484Sobrien	    default:	      name = NULL;	  size = false; break;
281860484Sobrien	    }
281960484Sobrien
282060484Sobrien	  if (name != NULL)
282160484Sobrien	    {
282260484Sobrien	      asection *s;
282360484Sobrien
282460484Sobrien	      s = bfd_get_section_by_name (output_bfd, name);
282560484Sobrien	      if (s == NULL)
282660484Sobrien		dyn.d_un.d_val = 0;
282760484Sobrien	      else
282860484Sobrien		{
282960484Sobrien		  if (! size)
283060484Sobrien		    dyn.d_un.d_ptr = s->vma;
283160484Sobrien		  else
283260484Sobrien		    {
283360484Sobrien		      if (s->_cooked_size != 0)
283460484Sobrien			dyn.d_un.d_val = s->_cooked_size;
283560484Sobrien		      else
283660484Sobrien			dyn.d_un.d_val = s->_raw_size;
283760484Sobrien		    }
283860484Sobrien		}
283960484Sobrien	      bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
284060484Sobrien	    }
284160484Sobrien	}
284260484Sobrien    }
284360484Sobrien
284460484Sobrien  /* Add a blrl instruction at _GLOBAL_OFFSET_TABLE_-4 so that a function can
284560484Sobrien     easily find the address of the _GLOBAL_OFFSET_TABLE_.  */
284660484Sobrien  if (sgot)
284760484Sobrien    {
284860484Sobrien      unsigned char *contents = sgot->contents;
284960484Sobrien      bfd_put_32 (output_bfd, 0x4e800021 /* blrl */, contents);
285060484Sobrien
285160484Sobrien      if (sdyn == NULL)
285260484Sobrien	bfd_put_32 (output_bfd, (bfd_vma) 0, contents+4);
285360484Sobrien      else
285460484Sobrien	bfd_put_32 (output_bfd,
285560484Sobrien		    sdyn->output_section->vma + sdyn->output_offset,
285660484Sobrien		    contents+4);
285760484Sobrien
285860484Sobrien      elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4;
285960484Sobrien    }
286060484Sobrien
286160484Sobrien  return true;
286260484Sobrien}
286360484Sobrien
286460484Sobrien/* The RELOCATE_SECTION function is called by the ELF backend linker
286560484Sobrien   to handle the relocations for a section.
286660484Sobrien
286760484Sobrien   The relocs are always passed as Rela structures; if the section
286860484Sobrien   actually uses Rel structures, the r_addend field will always be
286960484Sobrien   zero.
287060484Sobrien
287160484Sobrien   This function is responsible for adjust the section contents as
287260484Sobrien   necessary, and (if using Rela relocs and generating a
287360484Sobrien   relocateable output file) adjusting the reloc addend as
287460484Sobrien   necessary.
287560484Sobrien
287660484Sobrien   This function does not have to worry about setting the reloc
287760484Sobrien   address or the reloc symbol index.
287860484Sobrien
287960484Sobrien   LOCAL_SYMS is a pointer to the swapped in local symbols.
288060484Sobrien
288160484Sobrien   LOCAL_SECTIONS is an array giving the section in the input file
288260484Sobrien   corresponding to the st_shndx field of each local symbol.
288360484Sobrien
288460484Sobrien   The global hash table entry for the global symbols can be found
288560484Sobrien   via elf_sym_hashes (input_bfd).
288660484Sobrien
288760484Sobrien   When generating relocateable output, this function must handle
288860484Sobrien   STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
288960484Sobrien   going to be the section symbol corresponding to the output
289060484Sobrien   section, which means that the addend must be adjusted
289160484Sobrien   accordingly.  */
289260484Sobrien
289360484Sobrienstatic boolean
289460484Sobrienppc_elf_relocate_section (output_bfd, info, input_bfd, input_section,
289560484Sobrien			  contents, relocs, local_syms, local_sections)
289660484Sobrien     bfd *output_bfd;
289760484Sobrien     struct bfd_link_info *info;
289860484Sobrien     bfd *input_bfd;
289960484Sobrien     asection *input_section;
290060484Sobrien     bfd_byte *contents;
290160484Sobrien     Elf_Internal_Rela *relocs;
290260484Sobrien     Elf_Internal_Sym *local_syms;
290360484Sobrien     asection **local_sections;
290460484Sobrien{
290560484Sobrien  Elf_Internal_Shdr *symtab_hdr		  = &elf_tdata (input_bfd)->symtab_hdr;
290660484Sobrien  struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (input_bfd);
290760484Sobrien  bfd *dynobj				  = elf_hash_table (info)->dynobj;
290860484Sobrien  elf_linker_section_t *sdata		  = (dynobj) ? elf_linker_section (dynobj, LINKER_SECTION_SDATA)  : NULL;
290960484Sobrien  elf_linker_section_t *sdata2		  = (dynobj) ? elf_linker_section (dynobj, LINKER_SECTION_SDATA2) : NULL;
291060484Sobrien  Elf_Internal_Rela *rel		  = relocs;
291160484Sobrien  Elf_Internal_Rela *relend		  = relocs + input_section->reloc_count;
291260484Sobrien  asection *sreloc			  = NULL;
291360484Sobrien  asection *splt;
291460484Sobrien  asection *sgot;
291560484Sobrien  bfd_vma *local_got_offsets;
291660484Sobrien  boolean ret				  = true;
291760484Sobrien  long insn;
291860484Sobrien
291960484Sobrien#ifdef DEBUG
292060484Sobrien  fprintf (stderr, "ppc_elf_relocate_section called for %s section %s, %ld relocations%s\n",
292160484Sobrien	   bfd_get_filename (input_bfd),
292260484Sobrien	   bfd_section_name(input_bfd, input_section),
292377298Sobrien	   (long) input_section->reloc_count,
292460484Sobrien	   (info->relocateable) ? " (relocatable)" : "");
292560484Sobrien#endif
292660484Sobrien
292777298Sobrien  if (!ppc_elf_howto_table[R_PPC_ADDR32])
292877298Sobrien    /* Initialize howto table if needed.  */
292960484Sobrien    ppc_elf_howto_init ();
293060484Sobrien
293160484Sobrien  local_got_offsets = elf_local_got_offsets (input_bfd);
293260484Sobrien
293360484Sobrien  splt = sgot = NULL;
293460484Sobrien  if (dynobj != NULL)
293560484Sobrien    {
293660484Sobrien      splt = bfd_get_section_by_name (dynobj, ".plt");
293760484Sobrien      sgot = bfd_get_section_by_name (dynobj, ".got");
293860484Sobrien    }
293960484Sobrien
294060484Sobrien  for (; rel < relend; rel++)
294160484Sobrien    {
294260484Sobrien      enum elf_ppc_reloc_type r_type	= (enum elf_ppc_reloc_type)ELF32_R_TYPE (rel->r_info);
294360484Sobrien      bfd_vma offset			= rel->r_offset;
294460484Sobrien      bfd_vma addend			= rel->r_addend;
294560484Sobrien      bfd_reloc_status_type r		= bfd_reloc_other;
294677298Sobrien      Elf_Internal_Sym *sym		= (Elf_Internal_Sym *) 0;
294777298Sobrien      asection *sec			= (asection *) 0;
294877298Sobrien      struct elf_link_hash_entry *h	= (struct elf_link_hash_entry *) 0;
294977298Sobrien      const char *sym_name		= (const char *) 0;
295060484Sobrien      reloc_howto_type *howto;
295160484Sobrien      unsigned long r_symndx;
295260484Sobrien      bfd_vma relocation;
295377298Sobrien      int will_become_local;
295460484Sobrien
295560484Sobrien      /* Unknown relocation handling */
295677298Sobrien      if ((unsigned) r_type >= (unsigned) R_PPC_max
295777298Sobrien	  || !ppc_elf_howto_table[(int) r_type])
295860484Sobrien	{
295960484Sobrien	  (*_bfd_error_handler) (_("%s: unknown relocation type %d"),
296060484Sobrien				 bfd_get_filename (input_bfd),
296177298Sobrien				 (int) r_type);
296260484Sobrien
296360484Sobrien	  bfd_set_error (bfd_error_bad_value);
296460484Sobrien	  ret = false;
296560484Sobrien	  continue;
296660484Sobrien	}
296760484Sobrien
296877298Sobrien      howto = ppc_elf_howto_table[(int) r_type];
296960484Sobrien      r_symndx = ELF32_R_SYM (rel->r_info);
297060484Sobrien
297160484Sobrien      if (info->relocateable)
297260484Sobrien	{
297360484Sobrien	  /* This is a relocateable link.  We don't have to change
297460484Sobrien	     anything, unless the reloc is against a section symbol,
297560484Sobrien	     in which case we have to adjust according to where the
297660484Sobrien	     section symbol winds up in the output section.  */
297760484Sobrien	  if (r_symndx < symtab_hdr->sh_info)
297860484Sobrien	    {
297960484Sobrien	      sym = local_syms + r_symndx;
298077298Sobrien	      if ((unsigned) ELF_ST_TYPE (sym->st_info) == STT_SECTION)
298160484Sobrien		{
298260484Sobrien		  sec = local_sections[r_symndx];
298360484Sobrien		  addend = rel->r_addend += sec->output_offset + sym->st_value;
298460484Sobrien		}
298560484Sobrien	    }
298660484Sobrien
298760484Sobrien#ifdef DEBUG
298860484Sobrien	  fprintf (stderr, "\ttype = %s (%d), symbol index = %ld, offset = %ld, addend = %ld\n",
298960484Sobrien		   howto->name,
299077298Sobrien		   (int) r_type,
299160484Sobrien		   r_symndx,
299277298Sobrien		   (long) offset,
299377298Sobrien		   (long) addend);
299460484Sobrien#endif
299560484Sobrien	  continue;
299660484Sobrien	}
299760484Sobrien
299860484Sobrien      /* This is a final link.  */
299960484Sobrien      if (r_symndx < symtab_hdr->sh_info)
300060484Sobrien	{
300160484Sobrien	  sym = local_syms + r_symndx;
300260484Sobrien	  sec = local_sections[r_symndx];
300360484Sobrien	  sym_name = "<local symbol>";
300460484Sobrien
300560484Sobrien	  relocation = (sec->output_section->vma
300660484Sobrien			+ sec->output_offset
300760484Sobrien			+ sym->st_value);
300877298Sobrien	  /* Relocs to local symbols are always resolved.  */
300977298Sobrien	  will_become_local = 1;
301060484Sobrien	}
301160484Sobrien      else
301260484Sobrien	{
301360484Sobrien	  h = sym_hashes[r_symndx - symtab_hdr->sh_info];
301460484Sobrien	  while (h->root.type == bfd_link_hash_indirect
301560484Sobrien		 || h->root.type == bfd_link_hash_warning)
301660484Sobrien	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
301760484Sobrien	  sym_name = h->root.root.string;
301877298Sobrien
301977298Sobrien	  /* Can this relocation be resolved immediately?  */
302077298Sobrien	  will_become_local = SYMBOL_REFERENCES_LOCAL (info, h);
302177298Sobrien
302260484Sobrien	  if (h->root.type == bfd_link_hash_defined
302360484Sobrien	      || h->root.type == bfd_link_hash_defweak)
302460484Sobrien	    {
302560484Sobrien	      sec = h->root.u.def.section;
302677298Sobrien	      if (((r_type == R_PPC_PLT32
302777298Sobrien		    || r_type == R_PPC_PLTREL24)
302877298Sobrien		   && splt != NULL
302960484Sobrien		   && h->plt.offset != (bfd_vma) -1)
303060484Sobrien		  || (r_type == R_PPC_LOCAL24PC
303160484Sobrien		      && sec->output_section == NULL)
303260484Sobrien		  || ((r_type == R_PPC_GOT16
303360484Sobrien		       || r_type == R_PPC_GOT16_LO
303460484Sobrien		       || r_type == R_PPC_GOT16_HI
303560484Sobrien		       || r_type == R_PPC_GOT16_HA)
303660484Sobrien		      && elf_hash_table (info)->dynamic_sections_created
303777298Sobrien		      && (! info->shared || ! will_become_local))
303860484Sobrien		  || (info->shared
303977298Sobrien 		      && ! will_become_local
304060484Sobrien		      && ((input_section->flags & SEC_ALLOC) != 0
304160484Sobrien			  /* Testing SEC_DEBUGGING here may be wrong.
304260484Sobrien                             It's here to avoid a crash when
304360484Sobrien                             generating a shared library with DWARF
304460484Sobrien                             debugging information.  */
304577298Sobrien			  || ((input_section->flags & SEC_DEBUGGING) != 0
304677298Sobrien			      && (h->elf_link_hash_flags
304777298Sobrien				  & ELF_LINK_HASH_DEF_DYNAMIC) != 0))
304860484Sobrien		      && (r_type == R_PPC_ADDR32
304960484Sobrien			  || r_type == R_PPC_ADDR24
305060484Sobrien			  || r_type == R_PPC_ADDR16
305160484Sobrien			  || r_type == R_PPC_ADDR16_LO
305260484Sobrien			  || r_type == R_PPC_ADDR16_HI
305360484Sobrien			  || r_type == R_PPC_ADDR16_HA
305460484Sobrien			  || r_type == R_PPC_ADDR14
305560484Sobrien			  || r_type == R_PPC_ADDR14_BRTAKEN
305660484Sobrien			  || r_type == R_PPC_ADDR14_BRNTAKEN
305760484Sobrien			  || r_type == R_PPC_COPY
305860484Sobrien			  || r_type == R_PPC_GLOB_DAT
305960484Sobrien			  || r_type == R_PPC_JMP_SLOT
306060484Sobrien			  || r_type == R_PPC_UADDR32
306160484Sobrien			  || r_type == R_PPC_UADDR16
306260484Sobrien			  || r_type == R_PPC_SDAREL16
306360484Sobrien			  || r_type == R_PPC_EMB_NADDR32
306460484Sobrien			  || r_type == R_PPC_EMB_NADDR16
306560484Sobrien			  || r_type == R_PPC_EMB_NADDR16_LO
306660484Sobrien			  || r_type == R_PPC_EMB_NADDR16_HI
306760484Sobrien			  || r_type == R_PPC_EMB_NADDR16_HA
306860484Sobrien			  || r_type == R_PPC_EMB_SDAI16
306960484Sobrien			  || r_type == R_PPC_EMB_SDA2I16
307060484Sobrien			  || r_type == R_PPC_EMB_SDA2REL
307160484Sobrien			  || r_type == R_PPC_EMB_SDA21
307260484Sobrien			  || r_type == R_PPC_EMB_MRKREF
307360484Sobrien			  || r_type == R_PPC_EMB_BIT_FLD
307460484Sobrien			  || r_type == R_PPC_EMB_RELSDA
307560484Sobrien			  || ((r_type == R_PPC_REL24
307660484Sobrien			       || r_type == R_PPC_REL32
307760484Sobrien			       || r_type == R_PPC_REL14
307860484Sobrien			       || r_type == R_PPC_REL14_BRTAKEN
307960484Sobrien			       || r_type == R_PPC_REL14_BRNTAKEN
308060484Sobrien			       || r_type == R_PPC_RELATIVE)
308160484Sobrien			      && strcmp (h->root.root.string,
308260484Sobrien					 "_GLOBAL_OFFSET_TABLE_") != 0))))
308360484Sobrien		{
308460484Sobrien		  /* In these cases, we don't need the relocation
308560484Sobrien                     value.  We check specially because in some
308660484Sobrien                     obscure cases sec->output_section will be NULL.  */
308760484Sobrien		  relocation = 0;
308860484Sobrien		}
308960484Sobrien	      else if (sec->output_section == NULL)
309077298Sobrien		{
309160484Sobrien                  (*_bfd_error_handler)
309260484Sobrien                    (_("%s: warning: unresolvable relocation against symbol `%s' from %s section"),
309360484Sobrien                     bfd_get_filename (input_bfd), h->root.root.string,
309460484Sobrien                     bfd_get_section_name (input_bfd, input_section));
309560484Sobrien		  relocation = 0;
309677298Sobrien		}
309760484Sobrien	      else
309860484Sobrien		relocation = (h->root.u.def.value
309960484Sobrien			      + sec->output_section->vma
310060484Sobrien			      + sec->output_offset);
310160484Sobrien	    }
310260484Sobrien	  else if (h->root.type == bfd_link_hash_undefweak)
310360484Sobrien	    relocation = 0;
310477298Sobrien	  else if (info->shared && !info->symbolic && !info->no_undefined
310568765Sobrien		   && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
310660484Sobrien	    relocation = 0;
310760484Sobrien	  else
310860484Sobrien	    {
310977298Sobrien	      if (! (*info->callbacks->undefined_symbol) (info,
311060484Sobrien							 h->root.root.string,
311160484Sobrien							 input_bfd,
311260484Sobrien							 input_section,
311360484Sobrien							 rel->r_offset,
311460484Sobrien							 (!info->shared
311568765Sobrien							  || info->no_undefined
311668765Sobrien							  || ELF_ST_VISIBILITY (h->other))))
311760484Sobrien		return false;
311860484Sobrien	      relocation = 0;
311960484Sobrien	    }
312060484Sobrien	}
312160484Sobrien
312277298Sobrien      switch ((int) r_type)
312360484Sobrien	{
312460484Sobrien	default:
312560484Sobrien	  (*_bfd_error_handler) (_("%s: unknown relocation type %d for symbol %s"),
312660484Sobrien				 bfd_get_filename (input_bfd),
312777298Sobrien				 (int) r_type, sym_name);
312860484Sobrien
312960484Sobrien	  bfd_set_error (bfd_error_bad_value);
313060484Sobrien	  ret = false;
313160484Sobrien	  continue;
313260484Sobrien
313360484Sobrien	/* Relocations that need no special processing.  */
313477298Sobrien	case (int) R_PPC_LOCAL24PC:
313560484Sobrien	  /* It makes no sense to point a local relocation
313660484Sobrien	     at a symbol not in this object.  */
313760484Sobrien	  if (h != NULL
313860484Sobrien	      && (h->root.type == bfd_link_hash_defined
313960484Sobrien		  || h->root.type == bfd_link_hash_defweak)
314060484Sobrien	      && sec->output_section == NULL)
314160484Sobrien	    {
314260484Sobrien	      if (! (*info->callbacks->undefined_symbol) (info,
314360484Sobrien							  h->root.root.string,
314460484Sobrien							  input_bfd,
314560484Sobrien							  input_section,
314660484Sobrien							  rel->r_offset,
314760484Sobrien							  true))
314860484Sobrien		return false;
314960484Sobrien	      continue;
315060484Sobrien	    }
315160484Sobrien	  break;
315260484Sobrien
315360484Sobrien	/* Relocations that may need to be propagated if this is a shared
315460484Sobrien           object.  */
315577298Sobrien	case (int) R_PPC_REL24:
315677298Sobrien	case (int) R_PPC_REL32:
315777298Sobrien	case (int) R_PPC_REL14:
315860484Sobrien	  /* If these relocations are not to a named symbol, they can be
315960484Sobrien	     handled right here, no need to bother the dynamic linker.  */
316060484Sobrien	  if (h == NULL
316177298Sobrien	      || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0
316277298Sobrien	      || SYMBOL_REFERENCES_LOCAL (info, h))
316360484Sobrien	    break;
316460484Sobrien	/* fall through */
316560484Sobrien
316660484Sobrien	/* Relocations that always need to be propagated if this is a shared
316760484Sobrien           object.  */
316877298Sobrien	case (int) R_PPC_NONE:
316977298Sobrien	case (int) R_PPC_ADDR32:
317077298Sobrien	case (int) R_PPC_ADDR24:
317177298Sobrien	case (int) R_PPC_ADDR16:
317277298Sobrien	case (int) R_PPC_ADDR16_LO:
317377298Sobrien	case (int) R_PPC_ADDR16_HI:
317477298Sobrien	case (int) R_PPC_ADDR16_HA:
317577298Sobrien	case (int) R_PPC_ADDR14:
317677298Sobrien	case (int) R_PPC_UADDR32:
317777298Sobrien	case (int) R_PPC_UADDR16:
317860484Sobrien	  if (info->shared)
317960484Sobrien	    {
318060484Sobrien	      Elf_Internal_Rela outrel;
318160484Sobrien	      boolean skip;
318260484Sobrien
318360484Sobrien#ifdef DEBUG
318460484Sobrien	      fprintf (stderr, "ppc_elf_relocate_section need to create relocation for %s\n",
318560484Sobrien		       (h && h->root.root.string) ? h->root.root.string : "<unknown>");
318660484Sobrien#endif
318760484Sobrien
318860484Sobrien	      /* When generating a shared object, these relocations
318960484Sobrien                 are copied into the output file to be resolved at run
319060484Sobrien                 time.  */
319160484Sobrien
319260484Sobrien	      if (sreloc == NULL)
319360484Sobrien		{
319460484Sobrien		  const char *name;
319560484Sobrien
319660484Sobrien		  name = (bfd_elf_string_from_elf_section
319760484Sobrien			  (input_bfd,
319860484Sobrien			   elf_elfheader (input_bfd)->e_shstrndx,
319960484Sobrien			   elf_section_data (input_section)->rel_hdr.sh_name));
320060484Sobrien		  if (name == NULL)
320160484Sobrien		    return false;
320260484Sobrien
320360484Sobrien		  BFD_ASSERT (strncmp (name, ".rela", 5) == 0
320460484Sobrien			      && strcmp (bfd_get_section_name (input_bfd,
320560484Sobrien							       input_section),
320660484Sobrien					 name + 5) == 0);
320760484Sobrien
320860484Sobrien		  sreloc = bfd_get_section_by_name (dynobj, name);
320960484Sobrien		  BFD_ASSERT (sreloc != NULL);
321060484Sobrien		}
321160484Sobrien
321260484Sobrien	      skip = false;
321360484Sobrien
321460484Sobrien	      if (elf_section_data (input_section)->stab_info == NULL)
321560484Sobrien		outrel.r_offset = rel->r_offset;
321660484Sobrien	      else
321760484Sobrien		{
321860484Sobrien		  bfd_vma off;
321960484Sobrien
322060484Sobrien		  off = (_bfd_stab_section_offset
322160484Sobrien			 (output_bfd, &elf_hash_table (info)->stab_info,
322260484Sobrien			  input_section,
322360484Sobrien			  &elf_section_data (input_section)->stab_info,
322460484Sobrien			  rel->r_offset));
322560484Sobrien		  if (off == (bfd_vma) -1)
322660484Sobrien		    skip = true;
322760484Sobrien		  outrel.r_offset = off;
322860484Sobrien		}
322960484Sobrien
323060484Sobrien	      outrel.r_offset += (input_section->output_section->vma
323160484Sobrien				  + input_section->output_offset);
323260484Sobrien
323360484Sobrien	      if (skip)
323460484Sobrien		memset (&outrel, 0, sizeof outrel);
323560484Sobrien	      /* h->dynindx may be -1 if this symbol was marked to
323660484Sobrien                 become local.  */
323777298Sobrien	      else if (! will_become_local)
323860484Sobrien		{
323960484Sobrien		  outrel.r_info = ELF32_R_INFO (h->dynindx, r_type);
324060484Sobrien		  outrel.r_addend = rel->r_addend;
324160484Sobrien		}
324260484Sobrien	      else
324360484Sobrien		{
324460484Sobrien		  if (r_type == R_PPC_ADDR32)
324560484Sobrien		    {
324660484Sobrien		      outrel.r_info = ELF32_R_INFO (0, R_PPC_RELATIVE);
324760484Sobrien		      outrel.r_addend = relocation + rel->r_addend;
324860484Sobrien		    }
324960484Sobrien		  else
325060484Sobrien		    {
325160484Sobrien		      long indx;
325260484Sobrien
325360484Sobrien		      if (h == NULL)
325460484Sobrien			sec = local_sections[r_symndx];
325560484Sobrien		      else
325660484Sobrien			{
325760484Sobrien			  BFD_ASSERT (h->root.type == bfd_link_hash_defined
325860484Sobrien				      || (h->root.type
325960484Sobrien					  == bfd_link_hash_defweak));
326060484Sobrien			  sec = h->root.u.def.section;
326160484Sobrien			}
326260484Sobrien		      if (sec != NULL && bfd_is_abs_section (sec))
326360484Sobrien			indx = 0;
326460484Sobrien		      else if (sec == NULL || sec->owner == NULL)
326560484Sobrien			{
326660484Sobrien			  bfd_set_error (bfd_error_bad_value);
326760484Sobrien			  return false;
326860484Sobrien			}
326960484Sobrien		      else
327060484Sobrien			{
327160484Sobrien			  asection *osec;
327260484Sobrien
327360484Sobrien			  osec = sec->output_section;
327460484Sobrien			  indx = elf_section_data (osec)->dynindx;
327577298Sobrien			  BFD_ASSERT (indx > 0);
327660484Sobrien#ifdef DEBUG
327760484Sobrien			  if (indx <= 0)
327860484Sobrien			    {
327977298Sobrien			      printf ("indx=%d section=%s flags=%08x name=%s\n",
328060484Sobrien				     indx, osec->name, osec->flags,
328160484Sobrien				     h->root.root.string);
328260484Sobrien			    }
328360484Sobrien#endif
328460484Sobrien			}
328560484Sobrien
328660484Sobrien		      outrel.r_info = ELF32_R_INFO (indx, r_type);
328760484Sobrien		      outrel.r_addend = relocation + rel->r_addend;
328860484Sobrien		    }
328960484Sobrien		}
329060484Sobrien
329160484Sobrien	      bfd_elf32_swap_reloca_out (output_bfd, &outrel,
329260484Sobrien					 (((Elf32_External_Rela *)
329360484Sobrien					   sreloc->contents)
329460484Sobrien					  + sreloc->reloc_count));
329560484Sobrien	      ++sreloc->reloc_count;
329660484Sobrien
329760484Sobrien	      /* This reloc will be computed at runtime, so there's no
329860484Sobrien                 need to do anything now, unless this is a RELATIVE
329960484Sobrien                 reloc in an unallocated section.  */
330060484Sobrien	      if (skip
330160484Sobrien		  || (input_section->flags & SEC_ALLOC) != 0
330260484Sobrien		  || ELF32_R_TYPE (outrel.r_info) != R_PPC_RELATIVE)
330360484Sobrien		continue;
330460484Sobrien	    }
330560484Sobrien
330660484Sobrien	  /* Arithmetic adjust relocations that aren't going into a
330760484Sobrien	     shared object.  */
330860484Sobrien	  if (r_type == R_PPC_ADDR16_HA
330960484Sobrien	      /* It's just possible that this symbol is a weak symbol
331060484Sobrien		 that's not actually defined anywhere. In that case,
331160484Sobrien		 'sec' would be NULL, and we should leave the symbol
331260484Sobrien		 alone (it will be set to zero elsewhere in the link).  */
331360484Sobrien	      && sec != NULL)
331460484Sobrien	    {
331560484Sobrien	      addend += ((relocation + addend) & 0x8000) << 1;
331660484Sobrien	    }
331760484Sobrien	  break;
331860484Sobrien
331960484Sobrien	/* branch taken prediction relocations */
332077298Sobrien	case (int) R_PPC_ADDR14_BRTAKEN:
332177298Sobrien	case (int) R_PPC_REL14_BRTAKEN:
332260484Sobrien	  insn = bfd_get_32 (output_bfd, contents + offset);
332360484Sobrien	  if ((relocation - offset) & 0x8000)
332460484Sobrien	    insn &= ~BRANCH_PREDICT_BIT;
332560484Sobrien	  else
332660484Sobrien	    insn |= BRANCH_PREDICT_BIT;
332760484Sobrien	  bfd_put_32 (output_bfd, insn, contents + offset);
332860484Sobrien	  break;
332960484Sobrien
333060484Sobrien	/* branch not taken predicition relocations */
333177298Sobrien	case (int) R_PPC_ADDR14_BRNTAKEN:
333277298Sobrien	case (int) R_PPC_REL14_BRNTAKEN:
333360484Sobrien	  insn = bfd_get_32 (output_bfd, contents + offset);
333460484Sobrien	  if ((relocation - offset) & 0x8000)
333560484Sobrien	    insn |= BRANCH_PREDICT_BIT;
333660484Sobrien	  else
333760484Sobrien	    insn &= ~BRANCH_PREDICT_BIT;
333860484Sobrien	  bfd_put_32 (output_bfd, insn, contents + offset);
333960484Sobrien	  break;
334060484Sobrien
334160484Sobrien	/* GOT16 relocations */
334277298Sobrien	case (int) R_PPC_GOT16:
334377298Sobrien	case (int) R_PPC_GOT16_LO:
334477298Sobrien	case (int) R_PPC_GOT16_HI:
334577298Sobrien	case (int) R_PPC_GOT16_HA:
334660484Sobrien	  /* Relocation is to the entry for this symbol in the global
334760484Sobrien             offset table.  */
334860484Sobrien	  BFD_ASSERT (sgot != NULL);
334960484Sobrien
335060484Sobrien	  if (h != NULL)
335160484Sobrien	    {
335260484Sobrien	      bfd_vma off;
335360484Sobrien
335460484Sobrien	      off = h->got.offset;
335560484Sobrien	      BFD_ASSERT (off != (bfd_vma) -1);
335660484Sobrien
335760484Sobrien	      if (! elf_hash_table (info)->dynamic_sections_created
335860484Sobrien		  || (info->shared
335977298Sobrien		      && SYMBOL_REFERENCES_LOCAL (info, h)))
336060484Sobrien		{
336160484Sobrien		  /* This is actually a static link, or it is a
336260484Sobrien                     -Bsymbolic link and the symbol is defined
336360484Sobrien                     locally.  We must initialize this entry in the
336460484Sobrien                     global offset table.  Since the offset must
336560484Sobrien                     always be a multiple of 4, we use the least
336660484Sobrien                     significant bit to record whether we have
336760484Sobrien                     initialized it already.
336860484Sobrien
336960484Sobrien		     When doing a dynamic link, we create a .rela.got
337060484Sobrien		     relocation entry to initialize the value.  This
337160484Sobrien		     is done in the finish_dynamic_symbol routine.  */
337260484Sobrien		  if ((off & 1) != 0)
337360484Sobrien		    off &= ~1;
337460484Sobrien		  else
337560484Sobrien		    {
337660484Sobrien		      bfd_put_32 (output_bfd, relocation,
337760484Sobrien				  sgot->contents + off);
337860484Sobrien		      h->got.offset |= 1;
337960484Sobrien		    }
338060484Sobrien		}
338160484Sobrien
338260484Sobrien	      relocation = sgot->output_offset + off - 4;
338360484Sobrien	    }
338460484Sobrien	  else
338560484Sobrien	    {
338660484Sobrien	      bfd_vma off;
338760484Sobrien
338860484Sobrien	      BFD_ASSERT (local_got_offsets != NULL
338960484Sobrien			  && local_got_offsets[r_symndx] != (bfd_vma) -1);
339060484Sobrien
339160484Sobrien	      off = local_got_offsets[r_symndx];
339260484Sobrien
339360484Sobrien	      /* The offset must always be a multiple of 4.  We use
339460484Sobrien		 the least significant bit to record whether we have
339560484Sobrien		 already processed this entry.  */
339660484Sobrien	      if ((off & 1) != 0)
339760484Sobrien		off &= ~1;
339860484Sobrien	      else
339960484Sobrien		{
340060484Sobrien		  bfd_put_32 (output_bfd, relocation, sgot->contents + off);
340160484Sobrien
340260484Sobrien		  if (info->shared)
340360484Sobrien		    {
340460484Sobrien		      asection *srelgot;
340560484Sobrien		      Elf_Internal_Rela outrel;
340660484Sobrien
340760484Sobrien		      /* We need to generate a R_PPC_RELATIVE reloc
340860484Sobrien			 for the dynamic linker.  */
340960484Sobrien		      srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
341060484Sobrien		      BFD_ASSERT (srelgot != NULL);
341160484Sobrien
341260484Sobrien		      outrel.r_offset = (sgot->output_section->vma
341360484Sobrien					 + sgot->output_offset
341460484Sobrien					 + off);
341560484Sobrien		      outrel.r_info = ELF32_R_INFO (0, R_PPC_RELATIVE);
341660484Sobrien		      outrel.r_addend = relocation;
341760484Sobrien		      bfd_elf32_swap_reloca_out (output_bfd, &outrel,
341860484Sobrien						 (((Elf32_External_Rela *)
341960484Sobrien						   srelgot->contents)
342060484Sobrien						  + srelgot->reloc_count));
342160484Sobrien		      ++srelgot->reloc_count;
342260484Sobrien		    }
342360484Sobrien
342460484Sobrien		  local_got_offsets[r_symndx] |= 1;
342560484Sobrien		}
342660484Sobrien
342760484Sobrien	      relocation = sgot->output_offset + off - 4;
342860484Sobrien	    }
342960484Sobrien	  break;
343060484Sobrien
343160484Sobrien	/* Indirect .sdata relocation */
343277298Sobrien	case (int) R_PPC_EMB_SDAI16:
343360484Sobrien	  BFD_ASSERT (sdata != NULL);
343460484Sobrien	  relocation = bfd_elf32_finish_pointer_linker_section (output_bfd, input_bfd, info,
343560484Sobrien								sdata, h, relocation, rel,
343660484Sobrien								R_PPC_RELATIVE);
343760484Sobrien	  break;
343860484Sobrien
343960484Sobrien	/* Indirect .sdata2 relocation */
344077298Sobrien	case (int) R_PPC_EMB_SDA2I16:
344160484Sobrien	  BFD_ASSERT (sdata2 != NULL);
344260484Sobrien	  relocation = bfd_elf32_finish_pointer_linker_section (output_bfd, input_bfd, info,
344360484Sobrien								sdata2, h, relocation, rel,
344460484Sobrien								R_PPC_RELATIVE);
344560484Sobrien	  break;
344660484Sobrien
344760484Sobrien	/* Handle the TOC16 reloc.  We want to use the offset within the .got
344860484Sobrien	   section, not the actual VMA.  This is appropriate when generating
344960484Sobrien	   an embedded ELF object, for which the .got section acts like the
345060484Sobrien	   AIX .toc section.  */
345177298Sobrien	case (int) R_PPC_TOC16:			/* phony GOT16 relocations */
345277298Sobrien	  BFD_ASSERT (sec != (asection *) 0);
345360484Sobrien	  BFD_ASSERT (bfd_is_und_section (sec)
345460484Sobrien		      || strcmp (bfd_get_section_name (abfd, sec), ".got") == 0
345560484Sobrien		      || strcmp (bfd_get_section_name (abfd, sec), ".cgot") == 0)
345660484Sobrien
345760484Sobrien	  addend -= sec->output_section->vma + sec->output_offset + 0x8000;
345860484Sobrien	  break;
345960484Sobrien
346077298Sobrien	case (int) R_PPC_PLTREL24:
346160484Sobrien	  /* Relocation is to the entry for this symbol in the
346260484Sobrien             procedure linkage table.  */
346360484Sobrien	  BFD_ASSERT (h != NULL);
346460484Sobrien
346560484Sobrien	  if (h->plt.offset == (bfd_vma) -1
346660484Sobrien	      || splt == NULL)
346760484Sobrien	    {
346860484Sobrien	      /* We didn't make a PLT entry for this symbol.  This
346960484Sobrien                 happens when statically linking PIC code, or when
347060484Sobrien                 using -Bsymbolic.  */
347160484Sobrien	      break;
347260484Sobrien	    }
347360484Sobrien
347460484Sobrien	  relocation = (splt->output_section->vma
347560484Sobrien			+ splt->output_offset
347660484Sobrien			+ h->plt.offset);
347777298Sobrien	  break;
347860484Sobrien
347960484Sobrien	/* relocate against _SDA_BASE_ */
348077298Sobrien	case (int) R_PPC_SDAREL16:
348160484Sobrien	  {
348260484Sobrien	    const char *name;
348360484Sobrien
348477298Sobrien	    BFD_ASSERT (sec != (asection *) 0);
348560484Sobrien	    name = bfd_get_section_name (abfd, sec->output_section);
348660484Sobrien	    if (strcmp (name, ".sdata") != 0
348760484Sobrien		&& strcmp (name, ".sbss") != 0)
348860484Sobrien	      {
348960484Sobrien		(*_bfd_error_handler) (_("%s: The target (%s) of a %s relocation is in the wrong output section (%s)"),
349060484Sobrien				       bfd_get_filename (input_bfd),
349160484Sobrien				       sym_name,
349277298Sobrien				       ppc_elf_howto_table[(int) r_type]->name,
349360484Sobrien				       name);
349460484Sobrien	      }
349560484Sobrien	    addend -= (sdata->sym_hash->root.u.def.value
349660484Sobrien		       + sdata->sym_hash->root.u.def.section->output_section->vma
349760484Sobrien		       + sdata->sym_hash->root.u.def.section->output_offset);
349860484Sobrien	  }
349960484Sobrien	  break;
350060484Sobrien
350160484Sobrien	/* relocate against _SDA2_BASE_ */
350277298Sobrien	case (int) R_PPC_EMB_SDA2REL:
350360484Sobrien	  {
350460484Sobrien	    const char *name;
350560484Sobrien
350677298Sobrien	    BFD_ASSERT (sec != (asection *) 0);
350760484Sobrien	    name = bfd_get_section_name (abfd, sec->output_section);
350860484Sobrien	    if (strcmp (name, ".sdata2") != 0 && strcmp (name, ".sbss2") != 0)
350960484Sobrien	      {
351060484Sobrien		(*_bfd_error_handler) (_("%s: The target (%s) of a %s relocation is in the wrong output section (%s)"),
351160484Sobrien				       bfd_get_filename (input_bfd),
351260484Sobrien				       sym_name,
351377298Sobrien				       ppc_elf_howto_table[(int) r_type]->name,
351460484Sobrien				       name);
351577298Sobrien
351660484Sobrien		bfd_set_error (bfd_error_bad_value);
351760484Sobrien		ret = false;
351860484Sobrien		continue;
351960484Sobrien	      }
352060484Sobrien	    addend -= (sdata2->sym_hash->root.u.def.value
352160484Sobrien		       + sdata2->sym_hash->root.u.def.section->output_section->vma
352260484Sobrien		       + sdata2->sym_hash->root.u.def.section->output_offset);
352360484Sobrien	  }
352460484Sobrien	  break;
352560484Sobrien
352660484Sobrien	/* relocate against either _SDA_BASE_, _SDA2_BASE_, or 0 */
352777298Sobrien	case (int) R_PPC_EMB_SDA21:
352877298Sobrien	case (int) R_PPC_EMB_RELSDA:
352960484Sobrien	  {
353060484Sobrien	    const char *name;
353160484Sobrien	    int reg;
353260484Sobrien
353377298Sobrien	    BFD_ASSERT (sec != (asection *) 0);
353460484Sobrien	    name = bfd_get_section_name (abfd, sec->output_section);
353560484Sobrien	    if (strcmp (name, ".sdata") == 0 || strcmp (name, ".sbss") == 0)
353660484Sobrien	      {
353760484Sobrien		reg = 13;
353860484Sobrien		addend -= (sdata->sym_hash->root.u.def.value
353960484Sobrien			   + sdata->sym_hash->root.u.def.section->output_section->vma
354060484Sobrien			   + sdata->sym_hash->root.u.def.section->output_offset);
354160484Sobrien	      }
354260484Sobrien
354377298Sobrien	    else if (strcmp (name, ".sdata2") == 0
354477298Sobrien		     || strcmp (name, ".sbss2") == 0)
354560484Sobrien	      {
354660484Sobrien		reg = 2;
354760484Sobrien		addend -= (sdata2->sym_hash->root.u.def.value
354860484Sobrien			   + sdata2->sym_hash->root.u.def.section->output_section->vma
354960484Sobrien			   + sdata2->sym_hash->root.u.def.section->output_offset);
355060484Sobrien	      }
355160484Sobrien
355277298Sobrien	    else if (strcmp (name, ".PPC.EMB.sdata0") == 0
355377298Sobrien		     || strcmp (name, ".PPC.EMB.sbss0") == 0)
355460484Sobrien	      {
355560484Sobrien		reg = 0;
355660484Sobrien	      }
355760484Sobrien
355860484Sobrien	    else
355960484Sobrien	      {
356060484Sobrien		(*_bfd_error_handler) (_("%s: The target (%s) of a %s relocation is in the wrong output section (%s)"),
356160484Sobrien				       bfd_get_filename (input_bfd),
356260484Sobrien				       sym_name,
356377298Sobrien				       ppc_elf_howto_table[(int) r_type]->name,
356460484Sobrien				       name);
356560484Sobrien
356660484Sobrien		bfd_set_error (bfd_error_bad_value);
356760484Sobrien		ret = false;
356860484Sobrien		continue;
356960484Sobrien	      }
357060484Sobrien
357160484Sobrien	    if (r_type == R_PPC_EMB_SDA21)
357260484Sobrien	      {			/* fill in register field */
357360484Sobrien		insn = bfd_get_32 (output_bfd, contents + offset);
357460484Sobrien		insn = (insn & ~RA_REGISTER_MASK) | (reg << RA_REGISTER_SHIFT);
357560484Sobrien		bfd_put_32 (output_bfd, insn, contents + offset);
357660484Sobrien	      }
357760484Sobrien	  }
357860484Sobrien	  break;
357960484Sobrien
358060484Sobrien	/* Relocate against the beginning of the section */
358177298Sobrien	case (int) R_PPC_SECTOFF:
358277298Sobrien	case (int) R_PPC_SECTOFF_LO:
358377298Sobrien	case (int) R_PPC_SECTOFF_HI:
358477298Sobrien	  BFD_ASSERT (sec != (asection *) 0);
358560484Sobrien	  addend -= sec->output_section->vma;
358660484Sobrien	  break;
358760484Sobrien
358877298Sobrien	case (int) R_PPC_SECTOFF_HA:
358977298Sobrien	  BFD_ASSERT (sec != (asection *) 0);
359060484Sobrien	  addend -= sec->output_section->vma;
359160484Sobrien	  addend += ((relocation + addend) & 0x8000) << 1;
359260484Sobrien	  break;
359360484Sobrien
359460484Sobrien	/* Negative relocations */
359577298Sobrien	case (int) R_PPC_EMB_NADDR32:
359677298Sobrien	case (int) R_PPC_EMB_NADDR16:
359777298Sobrien	case (int) R_PPC_EMB_NADDR16_LO:
359877298Sobrien	case (int) R_PPC_EMB_NADDR16_HI:
359977298Sobrien	  addend -= 2 * relocation;
360060484Sobrien	  break;
360160484Sobrien
360277298Sobrien	case (int) R_PPC_EMB_NADDR16_HA:
360377298Sobrien	  addend -= 2 * relocation;
360460484Sobrien	  addend += ((relocation + addend) & 0x8000) << 1;
360560484Sobrien	  break;
360660484Sobrien
360760484Sobrien	/* NOP relocation that prevents garbage collecting linkers from omitting a
360860484Sobrien	   reference.  */
360977298Sobrien	case (int) R_PPC_EMB_MRKREF:
361060484Sobrien	  continue;
361160484Sobrien
361277298Sobrien	case (int) R_PPC_COPY:
361377298Sobrien	case (int) R_PPC_GLOB_DAT:
361477298Sobrien	case (int) R_PPC_JMP_SLOT:
361577298Sobrien	case (int) R_PPC_RELATIVE:
361677298Sobrien	case (int) R_PPC_PLT32:
361777298Sobrien	case (int) R_PPC_PLTREL32:
361877298Sobrien	case (int) R_PPC_PLT16_LO:
361977298Sobrien	case (int) R_PPC_PLT16_HI:
362077298Sobrien	case (int) R_PPC_PLT16_HA:
362177298Sobrien	case (int) R_PPC_EMB_RELSEC16:
362277298Sobrien	case (int) R_PPC_EMB_RELST_LO:
362377298Sobrien	case (int) R_PPC_EMB_RELST_HI:
362477298Sobrien	case (int) R_PPC_EMB_RELST_HA:
362577298Sobrien	case (int) R_PPC_EMB_BIT_FLD:
362660484Sobrien	  (*_bfd_error_handler) (_("%s: Relocation %s is not yet supported for symbol %s."),
362760484Sobrien				 bfd_get_filename (input_bfd),
362877298Sobrien				 ppc_elf_howto_table[(int) r_type]->name,
362960484Sobrien				 sym_name);
363060484Sobrien
363160484Sobrien	  bfd_set_error (bfd_error_invalid_operation);
363260484Sobrien	  ret = false;
363360484Sobrien	  continue;
363460484Sobrien
363577298Sobrien	case (int) R_PPC_GNU_VTINHERIT:
363677298Sobrien	case (int) R_PPC_GNU_VTENTRY:
363760484Sobrien	  /* These are no-ops in the end.  */
363860484Sobrien	  continue;
363960484Sobrien	}
364060484Sobrien
364160484Sobrien#ifdef DEBUG
364260484Sobrien      fprintf (stderr, "\ttype = %s (%d), name = %s, symbol index = %ld, offset = %ld, addend = %ld\n",
364360484Sobrien	       howto->name,
364477298Sobrien	       (int) r_type,
364560484Sobrien	       sym_name,
364660484Sobrien	       r_symndx,
364777298Sobrien	       (long) offset,
364877298Sobrien	       (long) addend);
364960484Sobrien#endif
365060484Sobrien
365160484Sobrien      r = _bfd_final_link_relocate (howto,
365260484Sobrien				    input_bfd,
365360484Sobrien				    input_section,
365460484Sobrien				    contents,
365560484Sobrien				    offset,
365660484Sobrien				    relocation,
365760484Sobrien				    addend);
365860484Sobrien
365960484Sobrien      if (r == bfd_reloc_ok)
366060484Sobrien	;
366160484Sobrien      else if (r == bfd_reloc_overflow)
366260484Sobrien	{
366360484Sobrien	  const char *name;
366460484Sobrien
366560484Sobrien	  if (h != NULL)
366660484Sobrien	    {
366760484Sobrien	      if (h->root.type == bfd_link_hash_undefweak
366860484Sobrien		  && howto->pc_relative)
366960484Sobrien		{
367060484Sobrien		  /* Assume this is a call protected by other code that
367160484Sobrien		     detect the symbol is undefined.  If this is the case,
367260484Sobrien		     we can safely ignore the overflow.  If not, the
367360484Sobrien		     program is hosed anyway, and a little warning isn't
367460484Sobrien		     going to help.  */
367560484Sobrien
367660484Sobrien		  continue;
367760484Sobrien		}
367860484Sobrien
367960484Sobrien	      name = h->root.root.string;
368060484Sobrien	    }
368160484Sobrien	  else
368260484Sobrien	    {
368360484Sobrien	      name = bfd_elf_string_from_elf_section (input_bfd,
368460484Sobrien						      symtab_hdr->sh_link,
368560484Sobrien						      sym->st_name);
368660484Sobrien	      if (name == NULL)
368760484Sobrien		continue;
368860484Sobrien	      if (*name == '\0')
368960484Sobrien		name = bfd_section_name (input_bfd, sec);
369060484Sobrien	    }
369160484Sobrien
369277298Sobrien	  if (! (*info->callbacks->reloc_overflow) (info,
369360484Sobrien						   name,
369460484Sobrien						   howto->name,
369560484Sobrien						   (bfd_vma) 0,
369660484Sobrien						   input_bfd,
369760484Sobrien						   input_section,
369860484Sobrien						   offset))
369960484Sobrien	    return false;
370060484Sobrien	}
370160484Sobrien      else
370260484Sobrien	ret = false;
370360484Sobrien    }
370460484Sobrien
370560484Sobrien#ifdef DEBUG
370660484Sobrien  fprintf (stderr, "\n");
370760484Sobrien#endif
370860484Sobrien
370960484Sobrien  return ret;
371060484Sobrien}
371160484Sobrien
371260484Sobrien#define TARGET_LITTLE_SYM	bfd_elf32_powerpcle_vec
371360484Sobrien#define TARGET_LITTLE_NAME	"elf32-powerpcle"
371460484Sobrien#define TARGET_BIG_SYM		bfd_elf32_powerpc_vec
371560484Sobrien#define TARGET_BIG_NAME		"elf32-powerpc"
371660484Sobrien#define ELF_ARCH		bfd_arch_powerpc
371760484Sobrien#define ELF_MACHINE_CODE	EM_PPC
371860484Sobrien#define ELF_MAXPAGESIZE		0x10000
371960484Sobrien#define elf_info_to_howto	ppc_elf_info_to_howto
372060484Sobrien
372160484Sobrien#ifdef  EM_CYGNUS_POWERPC
372260484Sobrien#define ELF_MACHINE_ALT1	EM_CYGNUS_POWERPC
372360484Sobrien#endif
372460484Sobrien
372560484Sobrien#ifdef EM_PPC_OLD
372660484Sobrien#define ELF_MACHINE_ALT2	EM_PPC_OLD
372760484Sobrien#endif
372860484Sobrien
372960484Sobrien#define elf_backend_plt_not_loaded	1
373060484Sobrien#define elf_backend_got_symbol_offset	4
373160484Sobrien#define elf_backend_can_gc_sections	1
373260484Sobrien#define elf_backend_got_header_size	12
373360484Sobrien#define elf_backend_plt_header_size	PLT_INITIAL_ENTRY_SIZE
373460484Sobrien
373560484Sobrien#define bfd_elf32_bfd_copy_private_bfd_data	ppc_elf_copy_private_bfd_data
373660484Sobrien#define bfd_elf32_bfd_merge_private_bfd_data	ppc_elf_merge_private_bfd_data
373760484Sobrien#define bfd_elf32_bfd_relax_section             ppc_elf_relax_section
373860484Sobrien#define bfd_elf32_bfd_reloc_type_lookup		ppc_elf_reloc_type_lookup
373960484Sobrien#define bfd_elf32_bfd_set_private_flags		ppc_elf_set_private_flags
374060484Sobrien#define bfd_elf32_bfd_final_link		_bfd_elf32_gc_common_final_link
374160484Sobrien
374260484Sobrien#define elf_backend_gc_mark_hook		ppc_elf_gc_mark_hook
374360484Sobrien#define elf_backend_gc_sweep_hook		ppc_elf_gc_sweep_hook
374460484Sobrien#define elf_backend_section_from_shdr		ppc_elf_section_from_shdr
374560484Sobrien#define elf_backend_relocate_section		ppc_elf_relocate_section
374660484Sobrien#define elf_backend_create_dynamic_sections	ppc_elf_create_dynamic_sections
374760484Sobrien#define elf_backend_check_relocs		ppc_elf_check_relocs
374860484Sobrien#define elf_backend_adjust_dynamic_symbol	ppc_elf_adjust_dynamic_symbol
374960484Sobrien#define elf_backend_add_symbol_hook		ppc_elf_add_symbol_hook
375060484Sobrien#define elf_backend_size_dynamic_sections	ppc_elf_size_dynamic_sections
375160484Sobrien#define elf_backend_finish_dynamic_symbol	ppc_elf_finish_dynamic_symbol
375260484Sobrien#define elf_backend_finish_dynamic_sections	ppc_elf_finish_dynamic_sections
375360484Sobrien#define elf_backend_fake_sections		ppc_elf_fake_sections
375460484Sobrien#define elf_backend_additional_program_headers	ppc_elf_additional_program_headers
375560484Sobrien#define elf_backend_modify_segment_map		ppc_elf_modify_segment_map
375660484Sobrien
375760484Sobrien#include "elf32-target.h"
3758