From 8c54b1f726591a91e1002e3d219688bcb5fa9447 Mon Sep 17 00:00:00 2001 From: Chris Young Date: Mon, 8 Jan 2018 22:36:56 +0000 Subject: Only one of the previously missing files is still missing --- .../recipes/patches/binutils/missing-files.p | 9975 -------------------- 1 file changed, 9975 deletions(-) (limited to 'ppc-amigaos/recipes') diff --git a/ppc-amigaos/recipes/patches/binutils/missing-files.p b/ppc-amigaos/recipes/patches/binutils/missing-files.p index 7911090..a0650ca 100644 --- a/ppc-amigaos/recipes/patches/binutils/missing-files.p +++ b/ppc-amigaos/recipes/patches/binutils/missing-files.p @@ -1,9979 +1,4 @@ --- /dev/null 2015-09-06 08:42:34.091999986 +0100 -+++ bfd/elf32-amigaos.c 2016-01-03 01:46:50.503001072 +0000 -@@ -0,0 +1,9972 @@ -+/* PowerPC-specific support for 32-bit ELF -+ Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, -+ 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 -+ Free Software Foundation, Inc. -+ Written by Ian Lance Taylor, Cygnus Support. -+ -+ This file is part of BFD, the Binary File Descriptor library. -+ -+ This program is free software; you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 3 of the License, or -+ (at your option) any later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this program; if not, write to the -+ Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, -+ Boston, MA 02110-1301, USA. */ -+ -+ -+/* This file is based on a preliminary PowerPC ELF ABI. The -+ information may not match the final PowerPC ELF ABI. It includes -+ suggestions from the in-progress Embedded PowerPC ABI, and that -+ information may also not match. */ -+ -+#include "sysdep.h" -+#include -+#include "bfd.h" -+#include "bfdlink.h" -+#include "libbfd.h" -+#include "elf-bfd.h" -+#include "elf/ppc.h" -+#include "elf/amigaos.h" -+#include "elf32-ppc.h" -+#include "elf-vxworks.h" -+#include "dwarf2.h" -+ -+#undef DEBUG -+ -+typedef enum split16_format_type -+{ -+ split16a_type = 0, -+ split16d_type -+} -+split16_format_type; -+ -+/* RELA relocations are used here. */ -+#define USE_RELA -+#define USE_REL 0 -+ -+static bfd_reloc_status_type ppc_elf_addr16_ha_reloc -+ (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); -+static bfd_reloc_status_type ppc_elf_unhandled_reloc -+ (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); -+static void ppc_elf_vle_split16 -+ (bfd *, bfd_byte *, bfd_vma, bfd_vma, split16_format_type); -+ -+int ppc_elf_amigaos_select_plt_layout (bfd *, struct bfd_link_info *, -+ enum ppc_elf_plt_type, int); -+ -+bfd_boolean ppc_elf_amigaos_section_processing (bfd *abfd, Elf_Internal_Shdr *shdr); -+bfd_boolean ppc_elf_amigaos_modify_segment_map (bfd *abfd, -+ struct bfd_link_info *info ATTRIBUTE_UNUSED); -+asection *ppc_elf_amigaos_tls_setup (bfd *obfd, struct bfd_link_info *info, -+ int no_tls_get_addr_opt); -+bfd_boolean ppc_elf_amigaos_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, -+ struct bfd_link_info *info); -+unsigned int _bfd_elf_amigaos_ppc_at_tls_transform (unsigned int insn, unsigned int reg); -+unsigned int _bfd_elf_amigaos_ppc_at_tprel_transform (unsigned int insn, unsigned int reg); -+ -+/* Branch prediction bit for branch taken relocs. */ -+#define BRANCH_PREDICT_BIT 0x200000 -+/* Mask to set RA in memory instructions. */ -+#define RA_REGISTER_MASK 0x001f0000 -+/* Value to shift register by to insert RA. */ -+#define RA_REGISTER_SHIFT 16 -+ -+/* The name of the dynamic interpreter. This is put in the .interp -+ section. */ -+#define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1" -+ -+/* For old-style PLT. */ -+/* The number of single-slot PLT entries (the rest use two slots). */ -+#define PLT_NUM_SINGLE_ENTRIES 8192 -+ -+/* For new-style .glink and .plt. */ -+#define GLINK_PLTRESOLVE 16*4 -+#define GLINK_ENTRY_SIZE 4*4 -+#define TLS_GET_ADDR_GLINK_SIZE 12*4 -+ -+/* VxWorks uses its own plt layout, filled in by the static linker. */ -+ -+/* The standard VxWorks PLT entry. */ -+#define VXWORKS_PLT_ENTRY_SIZE 32 -+static const bfd_vma ppc_elf_vxworks_plt_entry -+ [VXWORKS_PLT_ENTRY_SIZE / 4] = -+ { -+ 0x3d800000, /* lis r12,0 */ -+ 0x818c0000, /* lwz r12,0(r12) */ -+ 0x7d8903a6, /* mtctr r12 */ -+ 0x4e800420, /* bctr */ -+ 0x39600000, /* li r11,0 */ -+ 0x48000000, /* b 14 <.PLT0resolve+0x4> */ -+ 0x60000000, /* nop */ -+ 0x60000000, /* nop */ -+ }; -+static const bfd_vma ppc_elf_vxworks_pic_plt_entry -+ [VXWORKS_PLT_ENTRY_SIZE / 4] = -+ { -+ 0x3d9e0000, /* addis r12,r30,0 */ -+ 0x818c0000, /* lwz r12,0(r12) */ -+ 0x7d8903a6, /* mtctr r12 */ -+ 0x4e800420, /* bctr */ -+ 0x39600000, /* li r11,0 */ -+ 0x48000000, /* b 14 <.PLT0resolve+0x4> 14: R_PPC_REL24 .PLTresolve */ -+ 0x60000000, /* nop */ -+ 0x60000000, /* nop */ -+ }; -+ -+/* The initial VxWorks PLT entry. */ -+#define VXWORKS_PLT_INITIAL_ENTRY_SIZE 32 -+static const bfd_vma ppc_elf_vxworks_plt0_entry -+ [VXWORKS_PLT_INITIAL_ENTRY_SIZE / 4] = -+ { -+ 0x3d800000, /* lis r12,0 */ -+ 0x398c0000, /* addi r12,r12,0 */ -+ 0x800c0008, /* lwz r0,8(r12) */ -+ 0x7c0903a6, /* mtctr r0 */ -+ 0x818c0004, /* lwz r12,4(r12) */ -+ 0x4e800420, /* bctr */ -+ 0x60000000, /* nop */ -+ 0x60000000, /* nop */ -+ }; -+static const bfd_vma ppc_elf_vxworks_pic_plt0_entry -+ [VXWORKS_PLT_INITIAL_ENTRY_SIZE / 4] = -+ { -+ 0x819e0008, /* lwz r12,8(r30) */ -+ 0x7d8903a6, /* mtctr r12 */ -+ 0x819e0004, /* lwz r12,4(r30) */ -+ 0x4e800420, /* bctr */ -+ 0x60000000, /* nop */ -+ 0x60000000, /* nop */ -+ 0x60000000, /* nop */ -+ 0x60000000, /* nop */ -+ }; -+ -+/* For executables, we have some additional relocations in -+ .rela.plt.unloaded, for the kernel loader. */ -+ -+/* The number of non-JMP_SLOT relocations per PLT0 slot. */ -+#define VXWORKS_PLT_NON_JMP_SLOT_RELOCS 3 -+/* The number of relocations in the PLTResolve slot. */ -+#define VXWORKS_PLTRESOLVE_RELOCS 2 -+/* The number of relocations in the PLTResolve slot when when creating -+ a shared library. */ -+#define VXWORKS_PLTRESOLVE_RELOCS_SHLIB 0 -+ -+/* Some instructions. */ -+#define ADDIS_11_11 0x3d6b0000 -+#define ADDIS_11_30 0x3d7e0000 -+#define ADDIS_12_12 0x3d8c0000 -+#define ADDI_11_11 0x396b0000 -+#define ADD_0_11_11 0x7c0b5a14 -+#define ADD_3_12_2 0x7c6c1214 -+#define ADD_11_0_11 0x7d605a14 -+#define B 0x48000000 -+#define BCL_20_31 0x429f0005 -+#define BCTR 0x4e800420 -+#define BEQLR 0x4d820020 -+#define CMPWI_11_0 0x2c0b0000 -+#define LIS_11 0x3d600000 -+#define LIS_12 0x3d800000 -+#define LWZU_0_12 0x840c0000 -+#define LWZ_0_12 0x800c0000 -+#define LWZ_11_3 0x81630000 -+#define LWZ_11_11 0x816b0000 -+#define LWZ_11_30 0x817e0000 -+#define LWZ_12_3 0x81830000 -+#define LWZ_12_12 0x818c0000 -+#define MR_0_3 0x7c601b78 -+#define MR_3_0 0x7c030378 -+#define MFLR_0 0x7c0802a6 -+#define MFLR_12 0x7d8802a6 -+#define MTCTR_0 0x7c0903a6 -+#define MTCTR_11 0x7d6903a6 -+#define MTLR_0 0x7c0803a6 -+#define NOP 0x60000000 -+#define SUB_11_11_12 0x7d6c5850 -+ -+/* Offset of tp and dtp pointers from start of TLS block. */ -+#define TP_OFFSET 0x7000 -+#define DTP_OFFSET 0x8000 -+ -+/* The value of a defined global symbol. */ -+#define SYM_VAL(SYM) \ -+ ((SYM)->root.u.def.section->output_section->vma \ -+ + (SYM)->root.u.def.section->output_offset \ -+ + (SYM)->root.u.def.value) -+ -+static reloc_howto_type *ppc_elf_howto_table[R_PPC_max]; -+ -+static reloc_howto_type ppc_elf_howto_raw[] = { -+ /* This reloc does nothing. */ -+ HOWTO (R_PPC_NONE, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_NONE", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* A standard 32 bit relocation. */ -+ HOWTO (R_PPC_ADDR32, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_ADDR32", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* An absolute 26 bit branch; the lower two bits must be zero. -+ FIXME: we don't check that, we just clear them. */ -+ HOWTO (R_PPC_ADDR24, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 26, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_ADDR24", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0x3fffffc, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* A standard 16 bit relocation. */ -+ HOWTO (R_PPC_ADDR16, /* type */ -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_ADDR16", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* A 16 bit relocation without overflow. */ -+ HOWTO (R_PPC_ADDR16_LO, /* type */ -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_ADDR16_LO", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* The high order 16 bits of an address. */ -+ HOWTO (R_PPC_ADDR16_HI, /* type */ -+ 16, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_ADDR16_HI", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* The high order 16 bits of an address, plus 1 if the contents of -+ the low 16 bits, treated as a signed number, is negative. */ -+ HOWTO (R_PPC_ADDR16_HA, /* type */ -+ 16, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont, /* complain_on_overflow */ -+ ppc_elf_addr16_ha_reloc, /* special_function */ -+ "R_PPC_ADDR16_HA", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* An absolute 16 bit branch; the lower two bits must be zero. -+ FIXME: we don't check that, we just clear them. */ -+ HOWTO (R_PPC_ADDR14, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_ADDR14", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xfffc, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* An absolute 16 bit branch, for which bit 10 should be set to -+ indicate that the branch is expected to be taken. The lower two -+ bits must be zero. */ -+ HOWTO (R_PPC_ADDR14_BRTAKEN, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_ADDR14_BRTAKEN",/* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xfffc, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* An absolute 16 bit branch, for which bit 10 should be set to -+ indicate that the branch is not expected to be taken. The lower -+ two bits must be zero. */ -+ HOWTO (R_PPC_ADDR14_BRNTAKEN, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_ADDR14_BRNTAKEN",/* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xfffc, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* A relative 26 bit branch; the lower two bits must be zero. */ -+ HOWTO (R_PPC_REL24, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 26, /* bitsize */ -+ TRUE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_REL24", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0x3fffffc, /* dst_mask */ -+ TRUE), /* pcrel_offset */ -+ -+ /* A relative 16 bit branch; the lower two bits must be zero. */ -+ HOWTO (R_PPC_REL14, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ TRUE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_REL14", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xfffc, /* dst_mask */ -+ TRUE), /* pcrel_offset */ -+ -+ /* A relative 16 bit branch. Bit 10 should be set to indicate that -+ the branch is expected to be taken. The lower two bits must be -+ zero. */ -+ HOWTO (R_PPC_REL14_BRTAKEN, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ TRUE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_REL14_BRTAKEN", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xfffc, /* dst_mask */ -+ TRUE), /* pcrel_offset */ -+ -+ /* A relative 16 bit branch. Bit 10 should be set to indicate that -+ the branch is not expected to be taken. The lower two bits must -+ be zero. */ -+ HOWTO (R_PPC_REL14_BRNTAKEN, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ TRUE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_REL14_BRNTAKEN",/* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xfffc, /* dst_mask */ -+ TRUE), /* pcrel_offset */ -+ -+ /* Like R_PPC_ADDR16, but referring to the GOT table entry for the -+ symbol. */ -+ HOWTO (R_PPC_GOT16, /* type */ -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_GOT16", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* Like R_PPC_ADDR16_LO, but referring to the GOT table entry for -+ the symbol. */ -+ HOWTO (R_PPC_GOT16_LO, /* type */ -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_GOT16_LO", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* Like R_PPC_ADDR16_HI, but referring to the GOT table entry for -+ the symbol. */ -+ HOWTO (R_PPC_GOT16_HI, /* type */ -+ 16, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_GOT16_HI", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* Like R_PPC_ADDR16_HA, but referring to the GOT table entry for -+ the symbol. */ -+ HOWTO (R_PPC_GOT16_HA, /* type */ -+ 16, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield, /* complain_on_overflow */ -+ ppc_elf_addr16_ha_reloc, /* special_function */ -+ "R_PPC_GOT16_HA", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* Like R_PPC_REL24, but referring to the procedure linkage table -+ entry for the symbol. */ -+ HOWTO (R_PPC_PLTREL24, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 26, /* bitsize */ -+ TRUE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_PLTREL24", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0x3fffffc, /* dst_mask */ -+ TRUE), /* pcrel_offset */ -+ -+ /* This is used only by the dynamic linker. The symbol should exist -+ both in the object being run and in some shared library. The -+ dynamic linker copies the data addressed by the symbol from the -+ shared library into the object, because the object being -+ run has to have the data at some particular address. */ -+ HOWTO (R_PPC_COPY, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_COPY", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* Like R_PPC_ADDR32, but used when setting global offset table -+ entries. */ -+ HOWTO (R_PPC_GLOB_DAT, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_GLOB_DAT", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* Marks a procedure linkage table entry for a symbol. */ -+ HOWTO (R_PPC_JMP_SLOT, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_JMP_SLOT", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* Used only by the dynamic linker. When the object is run, this -+ longword is set to the load address of the object, plus the -+ addend. */ -+ HOWTO (R_PPC_RELATIVE, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_RELATIVE", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* Like R_PPC_REL24, but uses the value of the symbol within the -+ object rather than the final value. Normally used for -+ _GLOBAL_OFFSET_TABLE_. */ -+ HOWTO (R_PPC_LOCAL24PC, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 26, /* bitsize */ -+ TRUE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_LOCAL24PC", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0x3fffffc, /* dst_mask */ -+ TRUE), /* pcrel_offset */ -+ -+ /* Like R_PPC_ADDR32, but may be unaligned. */ -+ HOWTO (R_PPC_UADDR32, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_UADDR32", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* Like R_PPC_ADDR16, but may be unaligned. */ -+ HOWTO (R_PPC_UADDR16, /* type */ -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_UADDR16", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* 32-bit PC relative */ -+ HOWTO (R_PPC_REL32, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ TRUE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_REL32", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ TRUE), /* pcrel_offset */ -+ -+ /* 32-bit relocation to the symbol's procedure linkage table. -+ FIXME: not supported. */ -+ HOWTO (R_PPC_PLT32, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_PLT32", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* 32-bit PC relative relocation to the symbol's procedure linkage table. -+ FIXME: not supported. */ -+ HOWTO (R_PPC_PLTREL32, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ TRUE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_PLTREL32", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0, /* dst_mask */ -+ TRUE), /* pcrel_offset */ -+ -+ /* Like R_PPC_ADDR16_LO, but referring to the PLT table entry for -+ the symbol. */ -+ HOWTO (R_PPC_PLT16_LO, /* type */ -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_PLT16_LO", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* Like R_PPC_ADDR16_HI, but referring to the PLT table entry for -+ the symbol. */ -+ HOWTO (R_PPC_PLT16_HI, /* type */ -+ 16, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_PLT16_HI", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* Like R_PPC_ADDR16_HA, but referring to the PLT table entry for -+ the symbol. */ -+ HOWTO (R_PPC_PLT16_HA, /* type */ -+ 16, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield, /* complain_on_overflow */ -+ ppc_elf_addr16_ha_reloc, /* special_function */ -+ "R_PPC_PLT16_HA", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* A sign-extended 16 bit value relative to _SDA_BASE_, for use with -+ small data items. */ -+ HOWTO (R_PPC_SDAREL16, /* type */ -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_SDAREL16", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* 16-bit section relative relocation. */ -+ HOWTO (R_PPC_SECTOFF, /* type */ -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_SECTOFF", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* 16-bit lower half section relative relocation. */ -+ HOWTO (R_PPC_SECTOFF_LO, /* type */ -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_SECTOFF_LO", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* 16-bit upper half section relative relocation. */ -+ HOWTO (R_PPC_SECTOFF_HI, /* type */ -+ 16, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_SECTOFF_HI", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* 16-bit upper half adjusted section relative relocation. */ -+ HOWTO (R_PPC_SECTOFF_HA, /* type */ -+ 16, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield, /* complain_on_overflow */ -+ ppc_elf_addr16_ha_reloc, /* special_function */ -+ "R_PPC_SECTOFF_HA", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* Marker relocs for TLS. */ -+ HOWTO (R_PPC_TLS, -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_TLS", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ HOWTO (R_PPC_TLSGD, -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_TLSGD", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ HOWTO (R_PPC_TLSLD, -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_TLSLD", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* Computes the load module index of the load module that contains the -+ definition of its TLS sym. */ -+ HOWTO (R_PPC_DTPMOD32, -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont, /* complain_on_overflow */ -+ ppc_elf_unhandled_reloc, /* special_function */ -+ "R_PPC_DTPMOD32", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* Computes a dtv-relative displacement, the difference between the value -+ of sym+add and the base address of the thread-local storage block that -+ contains the definition of sym, minus 0x8000. */ -+ HOWTO (R_PPC_DTPREL32, -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont, /* complain_on_overflow */ -+ ppc_elf_unhandled_reloc, /* special_function */ -+ "R_PPC_DTPREL32", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* A 16 bit dtprel reloc. */ -+ HOWTO (R_PPC_DTPREL16, -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed, /* complain_on_overflow */ -+ ppc_elf_unhandled_reloc, /* special_function */ -+ "R_PPC_DTPREL16", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* Like DTPREL16, but no overflow. */ -+ HOWTO (R_PPC_DTPREL16_LO, -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont, /* complain_on_overflow */ -+ ppc_elf_unhandled_reloc, /* special_function */ -+ "R_PPC_DTPREL16_LO", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* Like DTPREL16_LO, but next higher group of 16 bits. */ -+ HOWTO (R_PPC_DTPREL16_HI, -+ 16, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont, /* complain_on_overflow */ -+ ppc_elf_unhandled_reloc, /* special_function */ -+ "R_PPC_DTPREL16_HI", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* Like DTPREL16_HI, but adjust for low 16 bits. */ -+ HOWTO (R_PPC_DTPREL16_HA, -+ 16, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont, /* complain_on_overflow */ -+ ppc_elf_unhandled_reloc, /* special_function */ -+ "R_PPC_DTPREL16_HA", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* Computes a tp-relative displacement, the difference between the value of -+ sym+add and the value of the thread pointer (r13). */ -+ HOWTO (R_PPC_TPREL32, -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont, /* complain_on_overflow */ -+ ppc_elf_unhandled_reloc, /* special_function */ -+ "R_PPC_TPREL32", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* A 16 bit tprel reloc. */ -+ HOWTO (R_PPC_TPREL16, -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed, /* complain_on_overflow */ -+ ppc_elf_unhandled_reloc, /* special_function */ -+ "R_PPC_TPREL16", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* Like TPREL16, but no overflow. */ -+ HOWTO (R_PPC_TPREL16_LO, -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont, /* complain_on_overflow */ -+ ppc_elf_unhandled_reloc, /* special_function */ -+ "R_PPC_TPREL16_LO", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* Like TPREL16_LO, but next higher group of 16 bits. */ -+ HOWTO (R_PPC_TPREL16_HI, -+ 16, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont, /* complain_on_overflow */ -+ ppc_elf_unhandled_reloc, /* special_function */ -+ "R_PPC_TPREL16_HI", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* Like TPREL16_HI, but adjust for low 16 bits. */ -+ HOWTO (R_PPC_TPREL16_HA, -+ 16, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont, /* complain_on_overflow */ -+ ppc_elf_unhandled_reloc, /* special_function */ -+ "R_PPC_TPREL16_HA", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* Allocates two contiguous entries in the GOT to hold a tls_index structure, -+ with values (sym+add)@dtpmod and (sym+add)@dtprel, and computes the offset -+ to the first entry. */ -+ HOWTO (R_PPC_GOT_TLSGD16, -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed, /* complain_on_overflow */ -+ ppc_elf_unhandled_reloc, /* special_function */ -+ "R_PPC_GOT_TLSGD16", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* Like GOT_TLSGD16, but no overflow. */ -+ HOWTO (R_PPC_GOT_TLSGD16_LO, -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont, /* complain_on_overflow */ -+ ppc_elf_unhandled_reloc, /* special_function */ -+ "R_PPC_GOT_TLSGD16_LO", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* Like GOT_TLSGD16_LO, but next higher group of 16 bits. */ -+ HOWTO (R_PPC_GOT_TLSGD16_HI, -+ 16, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont, /* complain_on_overflow */ -+ ppc_elf_unhandled_reloc, /* special_function */ -+ "R_PPC_GOT_TLSGD16_HI", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* Like GOT_TLSGD16_HI, but adjust for low 16 bits. */ -+ HOWTO (R_PPC_GOT_TLSGD16_HA, -+ 16, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont, /* complain_on_overflow */ -+ ppc_elf_unhandled_reloc, /* special_function */ -+ "R_PPC_GOT_TLSGD16_HA", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* Allocates two contiguous entries in the GOT to hold a tls_index structure, -+ with values (sym+add)@dtpmod and zero, and computes the offset to the -+ first entry. */ -+ HOWTO (R_PPC_GOT_TLSLD16, -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed, /* complain_on_overflow */ -+ ppc_elf_unhandled_reloc, /* special_function */ -+ "R_PPC_GOT_TLSLD16", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* Like GOT_TLSLD16, but no overflow. */ -+ HOWTO (R_PPC_GOT_TLSLD16_LO, -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont, /* complain_on_overflow */ -+ ppc_elf_unhandled_reloc, /* special_function */ -+ "R_PPC_GOT_TLSLD16_LO", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* Like GOT_TLSLD16_LO, but next higher group of 16 bits. */ -+ HOWTO (R_PPC_GOT_TLSLD16_HI, -+ 16, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont, /* complain_on_overflow */ -+ ppc_elf_unhandled_reloc, /* special_function */ -+ "R_PPC_GOT_TLSLD16_HI", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* Like GOT_TLSLD16_HI, but adjust for low 16 bits. */ -+ HOWTO (R_PPC_GOT_TLSLD16_HA, -+ 16, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont, /* complain_on_overflow */ -+ ppc_elf_unhandled_reloc, /* special_function */ -+ "R_PPC_GOT_TLSLD16_HA", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* Allocates an entry in the GOT with value (sym+add)@dtprel, and computes -+ the offset to the entry. */ -+ HOWTO (R_PPC_GOT_DTPREL16, -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed, /* complain_on_overflow */ -+ ppc_elf_unhandled_reloc, /* special_function */ -+ "R_PPC_GOT_DTPREL16", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* Like GOT_DTPREL16, but no overflow. */ -+ HOWTO (R_PPC_GOT_DTPREL16_LO, -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont, /* complain_on_overflow */ -+ ppc_elf_unhandled_reloc, /* special_function */ -+ "R_PPC_GOT_DTPREL16_LO", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* Like GOT_DTPREL16_LO, but next higher group of 16 bits. */ -+ HOWTO (R_PPC_GOT_DTPREL16_HI, -+ 16, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont, /* complain_on_overflow */ -+ ppc_elf_unhandled_reloc, /* special_function */ -+ "R_PPC_GOT_DTPREL16_HI", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* Like GOT_DTPREL16_HI, but adjust for low 16 bits. */ -+ HOWTO (R_PPC_GOT_DTPREL16_HA, -+ 16, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont, /* complain_on_overflow */ -+ ppc_elf_unhandled_reloc, /* special_function */ -+ "R_PPC_GOT_DTPREL16_HA", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* Allocates an entry in the GOT with value (sym+add)@tprel, and computes the -+ offset to the entry. */ -+ HOWTO (R_PPC_GOT_TPREL16, -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed, /* complain_on_overflow */ -+ ppc_elf_unhandled_reloc, /* special_function */ -+ "R_PPC_GOT_TPREL16", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* Like GOT_TPREL16, but no overflow. */ -+ HOWTO (R_PPC_GOT_TPREL16_LO, -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont, /* complain_on_overflow */ -+ ppc_elf_unhandled_reloc, /* special_function */ -+ "R_PPC_GOT_TPREL16_LO", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* Like GOT_TPREL16_LO, but next higher group of 16 bits. */ -+ HOWTO (R_PPC_GOT_TPREL16_HI, -+ 16, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont, /* complain_on_overflow */ -+ ppc_elf_unhandled_reloc, /* special_function */ -+ "R_PPC_GOT_TPREL16_HI", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* Like GOT_TPREL16_HI, but adjust for low 16 bits. */ -+ HOWTO (R_PPC_GOT_TPREL16_HA, -+ 16, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont, /* complain_on_overflow */ -+ ppc_elf_unhandled_reloc, /* special_function */ -+ "R_PPC_GOT_TPREL16_HA", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* The remaining relocs are from the Embedded ELF ABI, and are not -+ in the SVR4 ELF ABI. */ -+ -+ /* 32 bit value resulting from the addend minus the symbol. */ -+ HOWTO (R_PPC_EMB_NADDR32, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_EMB_NADDR32", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* 16 bit value resulting from the addend minus the symbol. */ -+ HOWTO (R_PPC_EMB_NADDR16, /* type */ -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_EMB_NADDR16", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* 16 bit value resulting from the addend minus the symbol. */ -+ HOWTO (R_PPC_EMB_NADDR16_LO, /* type */ -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_EMB_ADDR16_LO", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* The high order 16 bits of the addend minus the symbol. */ -+ HOWTO (R_PPC_EMB_NADDR16_HI, /* type */ -+ 16, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_EMB_NADDR16_HI", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* The high order 16 bits of the result of the addend minus the address, -+ plus 1 if the contents of the low 16 bits, treated as a signed number, -+ is negative. */ -+ HOWTO (R_PPC_EMB_NADDR16_HA, /* type */ -+ 16, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont, /* complain_on_overflow */ -+ ppc_elf_addr16_ha_reloc, /* special_function */ -+ "R_PPC_EMB_NADDR16_HA", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* 16 bit value resulting from allocating a 4 byte word to hold an -+ address in the .sdata section, and returning the offset from -+ _SDA_BASE_ for that relocation. */ -+ HOWTO (R_PPC_EMB_SDAI16, /* type */ -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_EMB_SDAI16", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* 16 bit value resulting from allocating a 4 byte word to hold an -+ address in the .sdata2 section, and returning the offset from -+ _SDA2_BASE_ for that relocation. */ -+ HOWTO (R_PPC_EMB_SDA2I16, /* type */ -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_EMB_SDA2I16", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* A sign-extended 16 bit value relative to _SDA2_BASE_, for use with -+ small data items. */ -+ HOWTO (R_PPC_EMB_SDA2REL, /* type */ -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_EMB_SDA2REL", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* Relocate against either _SDA_BASE_ or _SDA2_BASE_, filling in the 16 bit -+ signed offset from the appropriate base, and filling in the register -+ field with the appropriate register (0, 2, or 13). */ -+ HOWTO (R_PPC_EMB_SDA21, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_EMB_SDA21", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* Relocation not handled: R_PPC_EMB_MRKREF */ -+ /* Relocation not handled: R_PPC_EMB_RELSEC16 */ -+ /* Relocation not handled: R_PPC_EMB_RELST_LO */ -+ /* Relocation not handled: R_PPC_EMB_RELST_HI */ -+ /* Relocation not handled: R_PPC_EMB_RELST_HA */ -+ /* Relocation not handled: R_PPC_EMB_BIT_FLD */ -+ -+ -+ /* A standard 32 bit base relative relocation. */ -+ HOWTO (R_PPC_AMIGAOS_BREL, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_AMIGAOS_BREL", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* A 16 bit base relative relocation without overflow. */ -+ HOWTO (R_PPC_AMIGAOS_BREL_LO, /* type */ -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_AMIGAOS_BREL_LO",/* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* The high order 16 bits of a base relative address. */ -+ HOWTO (R_PPC_AMIGAOS_BREL_HI, /* type */ -+ 16, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_AMIGAOS_BREL_HI",/* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* The high order 16 bits of a base relative address, plus 1 if the contents -+ of the low 16 bits, treated as a signed number, is negative. */ -+ HOWTO (R_PPC_AMIGAOS_BREL_HA, /* type */ -+ 16, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont, /* complain_on_overflow */ -+ ppc_elf_addr16_ha_reloc, /* special_function */ -+ "R_PPC_AMIGAOS_BREL_HA",/* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* PC relative relocation against either _SDA_BASE_ or _SDA2_BASE_, filling -+ in the 16 bit signed offset from the appropriate base, and filling in the -+ register field with the appropriate register (0, 2, or 13). */ -+ HOWTO (R_PPC_EMB_RELSDA, /* type */ -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_EMB_RELSDA", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* A relative 8 bit branch. */ -+ HOWTO (R_PPC_VLE_REL8, /* type */ -+ 1, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 8, /* bitsize */ -+ TRUE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_VLE_REL8", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xff, /* dst_mask */ -+ TRUE), /* pcrel_offset */ -+ -+ /* A relative 15 bit branch. */ -+ HOWTO (R_PPC_VLE_REL15, /* type */ -+ 1, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 15, /* bitsize */ -+ TRUE, /* pc_relative */ -+ 1, /* bitpos */ -+ complain_overflow_signed, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_VLE_REL15", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xfe, /* dst_mask */ -+ TRUE), /* pcrel_offset */ -+ -+ /* A relative 24 bit branch. */ -+ HOWTO (R_PPC_VLE_REL24, /* type */ -+ 1, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 24, /* bitsize */ -+ TRUE, /* pc_relative */ -+ 1, /* bitpos */ -+ complain_overflow_signed, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_VLE_REL24", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0x1fffffe, /* dst_mask */ -+ TRUE), /* pcrel_offset */ -+ -+ /* The 16 LSBS in split16a format. */ -+ HOWTO (R_PPC_VLE_LO16A, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_VLE_LO16A", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0x1f007ff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* The 16 LSBS in split16d format. */ -+ HOWTO (R_PPC_VLE_LO16D, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_VLE_LO16D", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0x1f07ff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* Bits 16-31 split16a format. */ -+ HOWTO (R_PPC_VLE_HI16A, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_VLE_HI16A", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0x1f007ff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* Bits 16-31 split16d format. */ -+ HOWTO (R_PPC_VLE_HI16D, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_VLE_HI16D", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0x1f07ff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* Bits 16-31 (High Adjusted) in split16a format. */ -+ HOWTO (R_PPC_VLE_HA16A, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_VLE_HA16A", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0x1f007ff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* Bits 16-31 (High Adjusted) in split16d format. */ -+ HOWTO (R_PPC_VLE_HA16D, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_VLE_HA16D", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0x1f07ff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* This reloc does nothing. */ -+ HOWTO (R_PPC_VLE_SDA21, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_VLE_SDA21", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* This reloc does nothing. */ -+ HOWTO (R_PPC_VLE_SDA21_LO, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_VLE_SDA21_LO", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* The 16 LSBS relative to _SDA_BASE_ in split16a format. */ -+ HOWTO (R_PPC_VLE_SDAREL_LO16A,/* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_VLE_SDAREL_LO16A", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0x1f007ff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* The 16 LSBS relative to _SDA_BASE_ in split16d format. */ -+ /* This reloc does nothing. */ -+ HOWTO (R_PPC_VLE_SDAREL_LO16D, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_VLE_SDAREL_LO16D", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0x1f07ff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* Bits 16-31 relative to _SDA_BASE_ in split16a format. */ -+ HOWTO (R_PPC_VLE_SDAREL_HI16A, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_VLE_SDAREL_HI16A", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0x1f007ff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* Bits 16-31 relative to _SDA_BASE_ in split16d format. */ -+ HOWTO (R_PPC_VLE_SDAREL_HI16D, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_VLE_SDAREL_HI16D", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0x1f07ff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* Bits 16-31 (HA) relative to _SDA_BASE split16a format. */ -+ HOWTO (R_PPC_VLE_SDAREL_HA16A, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_VLE_SDAREL_HA16A", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0x1f007ff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* Bits 16-31 (HA) relative to _SDA_BASE split16d format. */ -+ HOWTO (R_PPC_VLE_SDAREL_HA16D, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_VLE_SDAREL_HA16D", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0x1f07ff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ HOWTO (R_PPC_IRELATIVE, /* type */ -+ 0, /* rightshift */ -+ 2, /* size (0 = byte, 1 = short, 2 = long) */ -+ 32, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_IRELATIVE", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffffffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* A 16 bit relative relocation. */ -+ HOWTO (R_PPC_REL16, /* type */ -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ TRUE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_bitfield, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_REL16", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ TRUE), /* pcrel_offset */ -+ -+ /* A 16 bit relative relocation without overflow. */ -+ HOWTO (R_PPC_REL16_LO, /* type */ -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ TRUE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont,/* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_REL16_LO", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ TRUE), /* pcrel_offset */ -+ -+ /* The high order 16 bits of a relative address. */ -+ HOWTO (R_PPC_REL16_HI, /* type */ -+ 16, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ TRUE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_REL16_HI", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ TRUE), /* pcrel_offset */ -+ -+ /* The high order 16 bits of a relative address, plus 1 if the contents of -+ the low 16 bits, treated as a signed number, is negative. */ -+ HOWTO (R_PPC_REL16_HA, /* type */ -+ 16, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ TRUE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont, /* complain_on_overflow */ -+ ppc_elf_addr16_ha_reloc, /* special_function */ -+ "R_PPC_REL16_HA", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ TRUE), /* pcrel_offset */ -+ -+ /* GNU extension to record C++ vtable hierarchy. */ -+ HOWTO (R_PPC_GNU_VTINHERIT, /* type */ -+ 0, /* rightshift */ -+ 0, /* size (0 = byte, 1 = short, 2 = long) */ -+ 0, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont, /* complain_on_overflow */ -+ NULL, /* special_function */ -+ "R_PPC_GNU_VTINHERIT", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* GNU extension to record C++ vtable member usage. */ -+ HOWTO (R_PPC_GNU_VTENTRY, /* type */ -+ 0, /* rightshift */ -+ 0, /* size (0 = byte, 1 = short, 2 = long) */ -+ 0, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_dont, /* complain_on_overflow */ -+ NULL, /* special_function */ -+ "R_PPC_GNU_VTENTRY", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+ -+ /* Phony reloc to handle AIX style TOC entries. */ -+ HOWTO (R_PPC_TOC16, /* type */ -+ 0, /* rightshift */ -+ 1, /* size (0 = byte, 1 = short, 2 = long) */ -+ 16, /* bitsize */ -+ FALSE, /* pc_relative */ -+ 0, /* bitpos */ -+ complain_overflow_signed, /* complain_on_overflow */ -+ bfd_elf_generic_reloc, /* special_function */ -+ "R_PPC_TOC16", /* name */ -+ FALSE, /* partial_inplace */ -+ 0, /* src_mask */ -+ 0xffff, /* dst_mask */ -+ FALSE), /* pcrel_offset */ -+}; -+ -+/* Initialize the ppc_elf_howto_table, so that linear accesses can be done. */ -+ -+static void -+ppc_elf_howto_init (void) -+{ -+ unsigned int i, type; -+ -+ for (i = 0; -+ i < sizeof (ppc_elf_howto_raw) / sizeof (ppc_elf_howto_raw[0]); -+ i++) -+ { -+ type = ppc_elf_howto_raw[i].type; -+ if (type >= (sizeof (ppc_elf_howto_table) -+ / sizeof (ppc_elf_howto_table[0]))) -+ abort (); -+ ppc_elf_howto_table[type] = &ppc_elf_howto_raw[i]; -+ } -+} -+ -+static reloc_howto_type * -+ppc_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, -+ bfd_reloc_code_real_type code) -+{ -+ enum elf_ppc_reloc_type r; -+ -+ /* Initialize howto table if not already done. */ -+ if (!ppc_elf_howto_table[R_PPC_ADDR32]) -+ ppc_elf_howto_init (); -+ -+ switch (code) -+ { -+ default: -+ return NULL; -+ -+ case BFD_RELOC_NONE: r = R_PPC_NONE; break; -+ case BFD_RELOC_32: r = R_PPC_ADDR32; break; -+ case BFD_RELOC_PPC_BA26: r = R_PPC_ADDR24; break; -+ case BFD_RELOC_PPC64_ADDR16_DS: -+ case BFD_RELOC_16: r = R_PPC_ADDR16; break; -+ case BFD_RELOC_PPC64_ADDR16_LO_DS: -+ case BFD_RELOC_LO16: r = R_PPC_ADDR16_LO; break; -+ case BFD_RELOC_HI16: r = R_PPC_ADDR16_HI; break; -+ case BFD_RELOC_HI16_S: r = R_PPC_ADDR16_HA; break; -+ case BFD_RELOC_PPC_BA16: r = R_PPC_ADDR14; break; -+ case BFD_RELOC_PPC_BA16_BRTAKEN: r = R_PPC_ADDR14_BRTAKEN; break; -+ case BFD_RELOC_PPC_BA16_BRNTAKEN: r = R_PPC_ADDR14_BRNTAKEN; break; -+ case BFD_RELOC_PPC_B26: r = R_PPC_REL24; break; -+ case BFD_RELOC_PPC_B16: r = R_PPC_REL14; break; -+ case BFD_RELOC_PPC_B16_BRTAKEN: r = R_PPC_REL14_BRTAKEN; break; -+ case BFD_RELOC_PPC_B16_BRNTAKEN: r = R_PPC_REL14_BRNTAKEN; break; -+ case BFD_RELOC_PPC64_GOT16_DS: -+ case BFD_RELOC_16_GOTOFF: r = R_PPC_GOT16; break; -+ case BFD_RELOC_PPC64_GOT16_LO_DS: -+ case BFD_RELOC_LO16_GOTOFF: r = R_PPC_GOT16_LO; break; -+ case BFD_RELOC_HI16_GOTOFF: r = R_PPC_GOT16_HI; break; -+ case BFD_RELOC_HI16_S_GOTOFF: r = R_PPC_GOT16_HA; break; -+ case BFD_RELOC_24_PLT_PCREL: r = R_PPC_PLTREL24; break; -+ case BFD_RELOC_PPC_COPY: r = R_PPC_COPY; break; -+ case BFD_RELOC_PPC_GLOB_DAT: r = R_PPC_GLOB_DAT; break; -+ case BFD_RELOC_PPC_LOCAL24PC: r = R_PPC_LOCAL24PC; break; -+ case BFD_RELOC_32_PCREL: r = R_PPC_REL32; break; -+ case BFD_RELOC_32_PLTOFF: r = R_PPC_PLT32; break; -+ case BFD_RELOC_32_PLT_PCREL: r = R_PPC_PLTREL32; break; -+ case BFD_RELOC_PPC64_PLT16_LO_DS: -+ case BFD_RELOC_LO16_PLTOFF: r = R_PPC_PLT16_LO; break; -+ case BFD_RELOC_HI16_PLTOFF: r = R_PPC_PLT16_HI; break; -+ case BFD_RELOC_HI16_S_PLTOFF: r = R_PPC_PLT16_HA; break; -+ case BFD_RELOC_GPREL16: r = R_PPC_SDAREL16; break; -+ case BFD_RELOC_PPC64_SECTOFF_DS: -+ case BFD_RELOC_16_BASEREL: r = R_PPC_SECTOFF; break; -+ case BFD_RELOC_PPC64_SECTOFF_LO_DS: -+ case BFD_RELOC_LO16_BASEREL: r = R_PPC_SECTOFF_LO; break; -+ case BFD_RELOC_HI16_BASEREL: r = R_PPC_SECTOFF_HI; break; -+ case BFD_RELOC_HI16_S_BASEREL: r = R_PPC_SECTOFF_HA; break; -+ case BFD_RELOC_CTOR: r = R_PPC_ADDR32; break; -+ case BFD_RELOC_PPC64_TOC16_DS: -+ case BFD_RELOC_PPC_TOC16: r = R_PPC_TOC16; break; -+ case BFD_RELOC_PPC_TLS: r = R_PPC_TLS; break; -+ case BFD_RELOC_PPC_TLSGD: r = R_PPC_TLSGD; break; -+ case BFD_RELOC_PPC_TLSLD: r = R_PPC_TLSLD; break; -+ case BFD_RELOC_PPC_DTPMOD: r = R_PPC_DTPMOD32; break; -+ case BFD_RELOC_PPC64_TPREL16_DS: -+ case BFD_RELOC_PPC_TPREL16: r = R_PPC_TPREL16; break; -+ case BFD_RELOC_PPC64_TPREL16_LO_DS: -+ case BFD_RELOC_PPC_TPREL16_LO: r = R_PPC_TPREL16_LO; break; -+ case BFD_RELOC_PPC_TPREL16_HI: r = R_PPC_TPREL16_HI; break; -+ case BFD_RELOC_PPC_TPREL16_HA: r = R_PPC_TPREL16_HA; break; -+ case BFD_RELOC_PPC_TPREL: r = R_PPC_TPREL32; break; -+ case BFD_RELOC_PPC64_DTPREL16_DS: -+ case BFD_RELOC_PPC_DTPREL16: r = R_PPC_DTPREL16; break; -+ case BFD_RELOC_PPC64_DTPREL16_LO_DS: -+ case BFD_RELOC_PPC_DTPREL16_LO: r = R_PPC_DTPREL16_LO; break; -+ case BFD_RELOC_PPC_DTPREL16_HI: r = R_PPC_DTPREL16_HI; break; -+ case BFD_RELOC_PPC_DTPREL16_HA: r = R_PPC_DTPREL16_HA; break; -+ case BFD_RELOC_PPC_DTPREL: r = R_PPC_DTPREL32; break; -+ case BFD_RELOC_PPC_GOT_TLSGD16: r = R_PPC_GOT_TLSGD16; break; -+ case BFD_RELOC_PPC_GOT_TLSGD16_LO: r = R_PPC_GOT_TLSGD16_LO; break; -+ case BFD_RELOC_PPC_GOT_TLSGD16_HI: r = R_PPC_GOT_TLSGD16_HI; break; -+ case BFD_RELOC_PPC_GOT_TLSGD16_HA: r = R_PPC_GOT_TLSGD16_HA; break; -+ case BFD_RELOC_PPC_GOT_TLSLD16: r = R_PPC_GOT_TLSLD16; break; -+ case BFD_RELOC_PPC_GOT_TLSLD16_LO: r = R_PPC_GOT_TLSLD16_LO; break; -+ case BFD_RELOC_PPC_GOT_TLSLD16_HI: r = R_PPC_GOT_TLSLD16_HI; break; -+ case BFD_RELOC_PPC_GOT_TLSLD16_HA: r = R_PPC_GOT_TLSLD16_HA; break; -+ case BFD_RELOC_PPC_GOT_TPREL16: r = R_PPC_GOT_TPREL16; break; -+ case BFD_RELOC_PPC_GOT_TPREL16_LO: r = R_PPC_GOT_TPREL16_LO; break; -+ case BFD_RELOC_PPC_GOT_TPREL16_HI: r = R_PPC_GOT_TPREL16_HI; break; -+ case BFD_RELOC_PPC_GOT_TPREL16_HA: r = R_PPC_GOT_TPREL16_HA; break; -+ case BFD_RELOC_PPC_GOT_DTPREL16: r = R_PPC_GOT_DTPREL16; break; -+ case BFD_RELOC_PPC_GOT_DTPREL16_LO: r = R_PPC_GOT_DTPREL16_LO; break; -+ case BFD_RELOC_PPC_GOT_DTPREL16_HI: r = R_PPC_GOT_DTPREL16_HI; break; -+ case BFD_RELOC_PPC_GOT_DTPREL16_HA: r = R_PPC_GOT_DTPREL16_HA; break; -+ case BFD_RELOC_PPC_EMB_NADDR32: r = R_PPC_EMB_NADDR32; break; -+ case BFD_RELOC_PPC_EMB_NADDR16: r = R_PPC_EMB_NADDR16; break; -+ case BFD_RELOC_PPC_EMB_NADDR16_LO: r = R_PPC_EMB_NADDR16_LO; break; -+ case BFD_RELOC_PPC_EMB_NADDR16_HI: r = R_PPC_EMB_NADDR16_HI; break; -+ case BFD_RELOC_PPC_EMB_NADDR16_HA: r = R_PPC_EMB_NADDR16_HA; break; -+ case BFD_RELOC_PPC_EMB_SDAI16: r = R_PPC_EMB_SDAI16; break; -+ case BFD_RELOC_PPC_EMB_SDA2I16: r = R_PPC_EMB_SDA2I16; break; -+ case BFD_RELOC_PPC_EMB_SDA2REL: r = R_PPC_EMB_SDA2REL; break; -+ case BFD_RELOC_PPC_EMB_SDA21: r = R_PPC_EMB_SDA21; break; -+ case BFD_RELOC_PPC_EMB_MRKREF: r = R_PPC_EMB_MRKREF; break; -+ case BFD_RELOC_PPC_EMB_RELSEC16: r = R_PPC_EMB_RELSEC16; break; -+ case BFD_RELOC_PPC_EMB_RELST_LO: r = R_PPC_EMB_RELST_LO; break; -+ case BFD_RELOC_PPC_EMB_RELST_HI: r = R_PPC_EMB_RELST_HI; break; -+ case BFD_RELOC_PPC_EMB_RELST_HA: r = R_PPC_EMB_RELST_HA; break; -+ case BFD_RELOC_PPC_EMB_BIT_FLD: r = R_PPC_EMB_BIT_FLD; break; -+ case BFD_RELOC_PPC_EMB_RELSDA: r = R_PPC_EMB_RELSDA; break; -+ case BFD_RELOC_PPC_VLE_REL8: r = R_PPC_VLE_REL8; break; -+ case BFD_RELOC_PPC_VLE_REL15: r = R_PPC_VLE_REL15; break; -+ case BFD_RELOC_PPC_VLE_REL24: r = R_PPC_VLE_REL24; break; -+ case BFD_RELOC_PPC_VLE_LO16A: r = R_PPC_VLE_LO16A; break; -+ case BFD_RELOC_PPC_VLE_LO16D: r = R_PPC_VLE_LO16D; break; -+ case BFD_RELOC_PPC_VLE_HI16A: r = R_PPC_VLE_HI16A; break; -+ case BFD_RELOC_PPC_VLE_HI16D: r = R_PPC_VLE_HI16D; break; -+ case BFD_RELOC_PPC_VLE_HA16A: r = R_PPC_VLE_HA16A; break; -+ case BFD_RELOC_PPC_VLE_HA16D: r = R_PPC_VLE_HA16D; break; -+ case BFD_RELOC_PPC_VLE_SDA21: r = R_PPC_VLE_SDA21; break; -+ case BFD_RELOC_PPC_VLE_SDA21_LO: r = R_PPC_VLE_SDA21_LO; break; -+ case BFD_RELOC_PPC_VLE_SDAREL_LO16A: -+ r = R_PPC_VLE_SDAREL_LO16A; -+ break; -+ case BFD_RELOC_PPC_VLE_SDAREL_LO16D: -+ r = R_PPC_VLE_SDAREL_LO16D; -+ break; -+ case BFD_RELOC_PPC_VLE_SDAREL_HI16A: -+ r = R_PPC_VLE_SDAREL_HI16A; -+ break; -+ case BFD_RELOC_PPC_VLE_SDAREL_HI16D: -+ r = R_PPC_VLE_SDAREL_HI16D; -+ break; -+ case BFD_RELOC_PPC_VLE_SDAREL_HA16A: -+ r = R_PPC_VLE_SDAREL_HA16A; -+ break; -+ case BFD_RELOC_PPC_VLE_SDAREL_HA16D: -+ r = R_PPC_VLE_SDAREL_HA16D; -+ break; -+ case BFD_RELOC_16_PCREL: r = R_PPC_REL16; break; -+ case BFD_RELOC_LO16_PCREL: r = R_PPC_REL16_LO; break; -+ case BFD_RELOC_HI16_PCREL: r = R_PPC_REL16_HI; break; -+ case BFD_RELOC_HI16_S_PCREL: r = R_PPC_REL16_HA; break; -+ case BFD_RELOC_PPC_AMIGAOS_BREL: r = R_PPC_AMIGAOS_BREL; break; -+ case BFD_RELOC_PPC_AMIGAOS_BREL_LO: r = R_PPC_AMIGAOS_BREL_LO; break; -+ case BFD_RELOC_PPC_AMIGAOS_BREL_HI: r = R_PPC_AMIGAOS_BREL_HI; break; -+ case BFD_RELOC_PPC_AMIGAOS_BREL_HA: r = R_PPC_AMIGAOS_BREL_HA; break; -+ case BFD_RELOC_VTABLE_INHERIT: r = R_PPC_GNU_VTINHERIT; break; -+ case BFD_RELOC_VTABLE_ENTRY: r = R_PPC_GNU_VTENTRY; break; -+ } -+ -+ return ppc_elf_howto_table[r]; -+}; -+ -+static reloc_howto_type * -+ppc_elf_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, -+ const char *r_name) -+{ -+ unsigned int i; -+ -+ for (i = 0; -+ i < sizeof (ppc_elf_howto_raw) / sizeof (ppc_elf_howto_raw[0]); -+ i++) -+ if (ppc_elf_howto_raw[i].name != NULL -+ && strcasecmp (ppc_elf_howto_raw[i].name, r_name) == 0) -+ return &ppc_elf_howto_raw[i]; -+ -+ return NULL; -+} -+ -+/* Set the howto pointer for a PowerPC ELF reloc. */ -+ -+static void -+ppc_elf_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, -+ arelent *cache_ptr, -+ Elf_Internal_Rela *dst) -+{ -+ /* Initialize howto table if not already done. */ -+ if (!ppc_elf_howto_table[R_PPC_ADDR32]) -+ ppc_elf_howto_init (); -+ -+ BFD_ASSERT (ELF32_R_TYPE (dst->r_info) < (unsigned int) R_PPC_max); -+ cache_ptr->howto = ppc_elf_howto_table[ELF32_R_TYPE (dst->r_info)]; -+ -+ /* Just because the above assert didn't trigger doesn't mean that -+ ELF32_R_TYPE (dst->r_info) is necessarily a valid relocation. */ -+ if (!cache_ptr->howto) -+ { -+ (*_bfd_error_handler) (_("%B: invalid relocation type %d"), -+ abfd, ELF32_R_TYPE (dst->r_info)); -+ bfd_set_error (bfd_error_bad_value); -+ -+ cache_ptr->howto = ppc_elf_howto_table[R_PPC_NONE]; -+ } -+} -+ -+/* Handle the R_PPC_ADDR16_HA and R_PPC_REL16_HA relocs. */ -+ -+static bfd_reloc_status_type -+ppc_elf_addr16_ha_reloc (bfd *abfd ATTRIBUTE_UNUSED, -+ arelent *reloc_entry, -+ asymbol *symbol, -+ void *data ATTRIBUTE_UNUSED, -+ asection *input_section, -+ bfd *output_bfd, -+ char **error_message ATTRIBUTE_UNUSED) -+{ -+ bfd_vma relocation; -+ -+ if (output_bfd != NULL) -+ { -+ reloc_entry->address += input_section->output_offset; -+ return bfd_reloc_ok; -+ } -+ -+ if (reloc_entry->address > bfd_get_section_limit (abfd, input_section)) -+ return bfd_reloc_outofrange; -+ -+ if (bfd_is_com_section (symbol->section)) -+ relocation = 0; -+ else -+ relocation = symbol->value; -+ -+ relocation += symbol->section->output_section->vma; -+ relocation += symbol->section->output_offset; -+ relocation += reloc_entry->addend; -+ if (reloc_entry->howto->pc_relative) -+ relocation -= reloc_entry->address; -+ -+ reloc_entry->addend += (relocation & 0x8000) << 1; -+ -+ return bfd_reloc_continue; -+} -+ -+static bfd_reloc_status_type -+ppc_elf_unhandled_reloc (bfd *abfd, -+ arelent *reloc_entry, -+ asymbol *symbol, -+ void *data, -+ asection *input_section, -+ bfd *output_bfd, -+ char **error_message) -+{ -+ /* If this is a relocatable link (output_bfd test tells us), just -+ call the generic function. Any adjustment will be done at final -+ link time. */ -+ if (output_bfd != NULL) -+ return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, -+ input_section, output_bfd, error_message); -+ -+ if (error_message != NULL) -+ { -+ static char buf[60]; -+ sprintf (buf, _("generic linker can't handle %s"), -+ reloc_entry->howto->name); -+ *error_message = buf; -+ } -+ return bfd_reloc_dangerous; -+} -+ -+/* Sections created by the linker. */ -+ -+typedef struct elf_linker_section -+{ -+ /* Pointer to the bfd section. */ -+ asection *section; -+ /* Section name. */ -+ const char *name; -+ /* Associated bss section name. */ -+ const char *bss_name; -+ /* Associated symbol name. */ -+ const char *sym_name; -+ /* Associated symbol. */ -+ struct elf_link_hash_entry *sym; -+} elf_linker_section_t; -+ -+/* Linked list of allocated pointer entries. This hangs off of the -+ symbol lists, and provides allows us to return different pointers, -+ based on different addend's. */ -+ -+typedef struct elf_linker_section_pointers -+{ -+ /* next allocated pointer for this symbol */ -+ struct elf_linker_section_pointers *next; -+ /* offset of pointer from beginning of section */ -+ bfd_vma offset; -+ /* addend used */ -+ bfd_vma addend; -+ /* which linker section this is */ -+ elf_linker_section_t *lsect; -+} elf_linker_section_pointers_t; -+ -+struct ppc_elf_obj_tdata -+{ -+ struct elf_obj_tdata elf; -+ -+ /* A mapping from local symbols to offsets into the various linker -+ sections added. This is index by the symbol index. */ -+ elf_linker_section_pointers_t **linker_section_pointers; -+ -+ /* Flags used to auto-detect plt type. */ -+ unsigned int makes_plt_call : 1; -+ unsigned int has_rel16 : 1; -+}; -+ -+#define ppc_elf_tdata(bfd) \ -+ ((struct ppc_elf_obj_tdata *) (bfd)->tdata.any) -+ -+#define elf_local_ptr_offsets(bfd) \ -+ (ppc_elf_tdata (bfd)->linker_section_pointers) -+ -+#define is_ppc_elf(bfd) \ -+ (bfd_get_flavour (bfd) == bfd_target_elf_flavour \ -+ && elf_object_id (bfd) == PPC32_ELF_DATA) -+ -+/* Override the generic function because we store some extras. */ -+ -+static bfd_boolean -+ppc_elf_mkobject (bfd *abfd) -+{ -+ return bfd_elf_allocate_object (abfd, sizeof (struct ppc_elf_obj_tdata), -+ PPC32_ELF_DATA); -+} -+ -+/* Fix bad default arch selected for a 32 bit input bfd when the -+ default is 64 bit. */ -+ -+static bfd_boolean -+ppc_elf_object_p (bfd *abfd) -+{ -+ if (abfd->arch_info->the_default && abfd->arch_info->bits_per_word == 64) -+ { -+ Elf_Internal_Ehdr *i_ehdr = elf_elfheader (abfd); -+ -+ if (i_ehdr->e_ident[EI_CLASS] == ELFCLASS32) -+ { -+ /* Relies on arch after 64 bit default being 32 bit default. */ -+ abfd->arch_info = abfd->arch_info->next; -+ BFD_ASSERT (abfd->arch_info->bits_per_word == 32); -+ } -+ } -+ return TRUE; -+} -+ -+/* Function to set whether a module needs the -mrelocatable bit set. */ -+ -+static bfd_boolean -+ppc_elf_set_private_flags (bfd *abfd, flagword flags) -+{ -+ BFD_ASSERT (!elf_flags_init (abfd) -+ || elf_elfheader (abfd)->e_flags == flags); -+ -+ elf_elfheader (abfd)->e_flags = flags; -+ elf_flags_init (abfd) = TRUE; -+ return TRUE; -+} -+ -+/* Support for core dump NOTE sections. */ -+ -+static bfd_boolean -+ppc_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) -+{ -+ int offset; -+ unsigned int size; -+ -+ switch (note->descsz) -+ { -+ default: -+ return FALSE; -+ -+ case 268: /* Linux/PPC. */ -+ /* pr_cursig */ -+ elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12); -+ -+ /* pr_pid */ -+ elf_tdata (abfd)->core_lwpid = bfd_get_32 (abfd, note->descdata + 24); -+ -+ /* pr_reg */ -+ offset = 72; -+ size = 192; -+ -+ break; -+ } -+ -+ /* Make a ".reg/999" section. */ -+ return _bfd_elfcore_make_pseudosection (abfd, ".reg", -+ size, note->descpos + offset); -+} -+ -+static bfd_boolean -+ppc_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) -+{ -+ switch (note->descsz) -+ { -+ default: -+ return FALSE; -+ -+ case 128: /* Linux/PPC elf_prpsinfo. */ -+ elf_tdata (abfd)->core_pid -+ = bfd_get_32 (abfd, note->descdata + 16); -+ elf_tdata (abfd)->core_program -+ = _bfd_elfcore_strndup (abfd, note->descdata + 32, 16); -+ elf_tdata (abfd)->core_command -+ = _bfd_elfcore_strndup (abfd, note->descdata + 48, 80); -+ } -+ -+ /* Note that for some reason, a spurious space is tacked -+ onto the end of the args in some (at least one anyway) -+ implementations, so strip it off if it exists. */ -+ -+ { -+ char *command = elf_tdata (abfd)->core_command; -+ int n = strlen (command); -+ -+ if (0 < n && command[n - 1] == ' ') -+ command[n - 1] = '\0'; -+ } -+ -+ return TRUE; -+} -+ -+static char * -+ppc_elf_write_core_note (bfd *abfd, char *buf, int *bufsiz, int note_type, ...) -+{ -+ switch (note_type) -+ { -+ default: -+ return NULL; -+ -+ case NT_PRPSINFO: -+ { -+ char data[128]; -+ va_list ap; -+ -+ va_start (ap, note_type); -+ memset (data, 0, sizeof (data)); -+ strncpy (data + 32, va_arg (ap, const char *), 16); -+ strncpy (data + 48, va_arg (ap, const char *), 80); -+ va_end (ap); -+ return elfcore_write_note (abfd, buf, bufsiz, -+ "CORE", note_type, data, sizeof (data)); -+ } -+ -+ case NT_PRSTATUS: -+ { -+ char data[268]; -+ va_list ap; -+ long pid; -+ int cursig; -+ const void *greg; -+ -+ va_start (ap, note_type); -+ memset (data, 0, 72); -+ pid = va_arg (ap, long); -+ bfd_put_32 (abfd, pid, data + 24); -+ cursig = va_arg (ap, int); -+ bfd_put_16 (abfd, cursig, data + 12); -+ greg = va_arg (ap, const void *); -+ memcpy (data + 72, greg, 192); -+ memset (data + 264, 0, 4); -+ va_end (ap); -+ return elfcore_write_note (abfd, buf, bufsiz, -+ "CORE", note_type, data, sizeof (data)); -+ } -+ } -+} -+ -+static flagword -+ppc_elf_lookup_section_flags (char *flag_name) -+{ -+ -+ if (!strcmp (flag_name, "SHF_PPC_VLE")) -+ return SHF_PPC_VLE; -+ -+ return 0; -+} -+ -+/* Add the VLE flag if required. */ -+ -+bfd_boolean -+ppc_elf_amigaos_section_processing (bfd *abfd, Elf_Internal_Shdr *shdr) -+{ -+ if (bfd_get_mach (abfd) == bfd_mach_ppc_vle -+ && (shdr->sh_flags & SHF_EXECINSTR) != 0) -+ shdr->sh_flags |= SHF_PPC_VLE; -+ -+ return TRUE; -+} -+ -+/* Return address for Ith PLT stub in section PLT, for relocation REL -+ or (bfd_vma) -1 if it should not be included. */ -+ -+static bfd_vma -+ppc_elf_plt_sym_val (bfd_vma i ATTRIBUTE_UNUSED, -+ const asection *plt ATTRIBUTE_UNUSED, -+ const arelent *rel) -+{ -+#ifdef DEBUG -+ fprintf (stderr, "ppc_elf_plt_sym_cal (0x%08x)\n", (unsigned int)rel->address); -+#endif -+ return rel->address; -+} -+ -+/* Handle a PowerPC specific section when reading an object file. This -+ is called when bfd_section_from_shdr finds a section with an unknown -+ type. */ -+ -+static bfd_boolean -+ppc_elf_section_from_shdr (bfd *abfd, -+ Elf_Internal_Shdr *hdr, -+ const char *name, -+ int shindex) -+{ -+ asection *newsect; -+ flagword flags; -+ -+ if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex)) -+ return FALSE; -+ -+ newsect = hdr->bfd_section; -+ flags = bfd_get_section_flags (abfd, newsect); -+ if (hdr->sh_flags & SHF_EXCLUDE) -+ flags |= SEC_EXCLUDE; -+ -+ if (hdr->sh_type == SHT_ORDERED) -+ flags |= SEC_SORT_ENTRIES; -+ -+ bfd_set_section_flags (abfd, newsect, flags); -+ return TRUE; -+} -+ -+/* Set up any other section flags and such that may be necessary. */ -+ -+static bfd_boolean -+ppc_elf_fake_sections (bfd *abfd ATTRIBUTE_UNUSED, -+ Elf_Internal_Shdr *shdr, -+ asection *asect) -+{ -+ if ((asect->flags & SEC_SORT_ENTRIES) != 0) -+ shdr->sh_type = SHT_ORDERED; -+ -+ return TRUE; -+} -+ -+/* If we have .sbss2 or .PPC.EMB.sbss0 output sections, we -+ need to bump up the number of section headers. */ -+ -+static int -+ppc_elf_additional_program_headers (bfd *abfd, -+ struct bfd_link_info *info ATTRIBUTE_UNUSED) -+{ -+ asection *s; -+// int ret = 0; -+ int ret = 1; -+ -+ s = bfd_get_section_by_name (abfd, ".sbss2"); -+ if (s != NULL && (s->flags & SEC_ALLOC) != 0) -+ ++ret; -+ -+ s = bfd_get_section_by_name (abfd, ".PPC.EMB.sbss0"); -+ if (s != NULL && (s->flags & SEC_ALLOC) != 0) -+ ++ret; -+ -+ return ret; -+} -+ -+/* Modify the segment map for VLE executables. */ -+ -+bfd_boolean -+ppc_elf_amigaos_modify_segment_map (bfd *abfd, -+ struct bfd_link_info *info ATTRIBUTE_UNUSED) -+{ -+ struct elf_segment_map *m, *n; -+ bfd_size_type amt; -+ unsigned int j, k; -+ bfd_boolean sect0_vle, sectj_vle; -+ -+ /* At this point in the link, output sections have already been sorted by -+ LMA and assigned to segments. All that is left to do is to ensure -+ there is no mixing of VLE & non-VLE sections in a text segment. -+ If we find that case, we split the segment. -+ We maintain the original output section order. */ -+ -+ for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next) -+ { -+ if (m->count == 0) -+ continue; -+ -+ sect0_vle = (elf_section_flags (m->sections[0]) & SHF_PPC_VLE) != 0; -+ for (j = 1; j < m->count; ++j) -+ { -+ sectj_vle = (elf_section_flags (m->sections[j]) & SHF_PPC_VLE) != 0; -+ -+ if (sectj_vle != sect0_vle) -+ break; -+ } -+ if (j >= m->count) -+ continue; -+ -+ /* sections 0..j-1 stay in this (current) segment, -+ the remainder are put in a new segment. -+ The scan resumes with the new segment. */ -+ -+ /* Fix the new segment. */ -+ amt = sizeof (struct elf_segment_map); -+ amt += (m->count - j - 1) * sizeof (asection *); -+ n = (struct elf_segment_map *) bfd_zalloc (abfd, amt); -+ if (n == NULL) -+ return FALSE; -+ -+ n->p_type = PT_LOAD; -+ n->p_flags = PF_X | PF_R; -+ if (sectj_vle) -+ n->p_flags |= PF_PPC_VLE; -+ n->count = m->count - j; -+ for (k = 0; k < n->count; ++k) -+ { -+ n->sections[k] = m->sections[j+k]; -+ m->sections[j+k] = NULL; -+ } -+ n->next = m->next; -+ m->next = n; -+ -+ /* Fix the current segment */ -+ m->count = j; -+ } -+ -+ return TRUE; -+} -+ -+/* Add extra PPC sections -- Note, for now, make .sbss2 and -+ .PPC.EMB.sbss0 a normal section, and not a bss section so -+ that the linker doesn't crater when trying to make more than -+ 2 sections. */ -+ -+static const struct bfd_elf_special_section ppc_elf_special_sections[] = -+{ -+ { STRING_COMMA_LEN (".plt"), 0, SHT_NOBITS, SHF_ALLOC + SHF_EXECINSTR }, -+ { STRING_COMMA_LEN (".sbss"), -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE }, -+ { STRING_COMMA_LEN (".sbss2"), -2, SHT_PROGBITS, SHF_ALLOC }, -+ { STRING_COMMA_LEN (".sdata"), -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE }, -+ { STRING_COMMA_LEN (".sdata2"), -2, SHT_PROGBITS, SHF_ALLOC }, -+ { STRING_COMMA_LEN (".tags"), 0, SHT_ORDERED, SHF_ALLOC }, -+ { STRING_COMMA_LEN (".PPC.EMB.apuinfo"), 0, SHT_NOTE, 0 }, -+ { STRING_COMMA_LEN (".PPC.EMB.sbss0"), 0, SHT_PROGBITS, SHF_ALLOC }, -+ { STRING_COMMA_LEN (".PPC.EMB.sdata0"), 0, SHT_PROGBITS, SHF_ALLOC }, -+ { NULL, 0, 0, 0, 0 } -+}; -+ -+/* This is what we want for new plt/got. */ -+static struct bfd_elf_special_section ppc_alt_plt = -+ { STRING_COMMA_LEN (".plt"), 0, SHT_PROGBITS, SHF_ALLOC }; -+ -+static const struct bfd_elf_special_section * -+ppc_elf_get_sec_type_attr (bfd *abfd ATTRIBUTE_UNUSED, asection *sec) -+{ -+ const struct bfd_elf_special_section *ssect; -+ -+ /* See if this is one of the special sections. */ -+ if (sec->name == NULL) -+ return NULL; -+ -+ ssect = _bfd_elf_get_special_section (sec->name, ppc_elf_special_sections, -+ sec->use_rela_p); -+ if (ssect != NULL) -+ { -+ if (ssect == ppc_elf_special_sections && (sec->flags & SEC_LOAD) != 0) -+ ssect = &ppc_alt_plt; -+ return ssect; -+ } -+ -+ return _bfd_elf_get_sec_type_attr (abfd, sec); -+} -+ -+/* Very simple linked list structure for recording apuinfo values. */ -+typedef struct apuinfo_list -+{ -+ struct apuinfo_list *next; -+ unsigned long value; -+} -+apuinfo_list; -+ -+static apuinfo_list *head; -+static bfd_boolean apuinfo_set; -+ -+static void -+apuinfo_list_init (void) -+{ -+ head = NULL; -+ apuinfo_set = FALSE; -+} -+ -+static void -+apuinfo_list_add (unsigned long value) -+{ -+ apuinfo_list *entry = head; -+ -+ while (entry != NULL) -+ { -+ if (entry->value == value) -+ return; -+ entry = entry->next; -+ } -+ -+ entry = bfd_malloc (sizeof (* entry)); -+ if (entry == NULL) -+ return; -+ -+ entry->value = value; -+ entry->next = head; -+ head = entry; -+} -+ -+static unsigned -+apuinfo_list_length (void) -+{ -+ apuinfo_list *entry; -+ unsigned long count; -+ -+ for (entry = head, count = 0; -+ entry; -+ entry = entry->next) -+ ++ count; -+ -+ return count; -+} -+ -+static inline unsigned long -+apuinfo_list_element (unsigned long number) -+{ -+ apuinfo_list * entry; -+ -+ for (entry = head; -+ entry && number --; -+ entry = entry->next) -+ ; -+ -+ return entry ? entry->value : 0; -+} -+ -+static void -+apuinfo_list_finish (void) -+{ -+ apuinfo_list *entry; -+ -+ for (entry = head; entry;) -+ { -+ apuinfo_list *next = entry->next; -+ free (entry); -+ entry = next; -+ } -+ -+ head = NULL; -+} -+ -+#define APUINFO_SECTION_NAME ".PPC.EMB.apuinfo" -+#define APUINFO_LABEL "APUinfo" -+ -+/* Scan the input BFDs and create a linked list of -+ the APUinfo values that will need to be emitted. */ -+ -+static void -+ppc_elf_amigaos_begin_write_processing (bfd *abfd, struct bfd_link_info *link_info) -+{ -+ bfd *ibfd; -+ asection *asec; -+ char *buffer = NULL; -+ bfd_size_type largest_input_size = 0; -+ unsigned i; -+ unsigned long length; -+ const char *error_message = NULL; -+ -+ if (link_info == NULL) -+ return; -+ -+ apuinfo_list_init (); -+ -+ /* Read in the input sections contents. */ -+ for (ibfd = link_info->input_bfds; ibfd; ibfd = ibfd->link_next) -+ { -+ unsigned long datum; -+ -+ asec = bfd_get_section_by_name (ibfd, APUINFO_SECTION_NAME); -+ if (asec == NULL) -+ continue; -+ -+ error_message = _("corrupt %s section in %B"); -+ length = asec->size; -+ if (length < 20) -+ goto fail; -+ -+ apuinfo_set = TRUE; -+ if (largest_input_size < asec->size) -+ { -+ if (buffer) -+ free (buffer); -+ largest_input_size = asec->size; -+ buffer = bfd_malloc (largest_input_size); -+ if (!buffer) -+ return; -+ } -+ -+ if (bfd_seek (ibfd, asec->filepos, SEEK_SET) != 0 -+ || (bfd_bread (buffer, length, ibfd) != length)) -+ { -+ error_message = _("unable to read in %s section from %B"); -+ goto fail; -+ } -+ -+ /* Verify the contents of the header. Note - we have to -+ extract the values this way in order to allow for a -+ host whose endian-ness is different from the target. */ -+ datum = bfd_get_32 (ibfd, buffer); -+ if (datum != sizeof APUINFO_LABEL) -+ goto fail; -+ -+ datum = bfd_get_32 (ibfd, buffer + 8); -+ if (datum != 0x2) -+ goto fail; -+ -+ if (strcmp (buffer + 12, APUINFO_LABEL) != 0) -+ goto fail; -+ -+ /* Get the number of bytes used for apuinfo entries. */ -+ datum = bfd_get_32 (ibfd, buffer + 4); -+ if (datum + 20 != length) -+ goto fail; -+ -+ /* Scan the apuinfo section, building a list of apuinfo numbers. */ -+ for (i = 0; i < datum; i += 4) -+ apuinfo_list_add (bfd_get_32 (ibfd, buffer + 20 + i)); -+ } -+ -+ error_message = NULL; -+ -+ if (apuinfo_set) -+ { -+ /* Compute the size of the output section. */ -+ unsigned num_entries = apuinfo_list_length (); -+ -+ /* Set the output section size, if it exists. */ -+ asec = bfd_get_section_by_name (abfd, APUINFO_SECTION_NAME); -+ -+ if (asec && ! bfd_set_section_size (abfd, asec, 20 + num_entries * 4)) -+ { -+ ibfd = abfd; -+ error_message = _("warning: unable to set size of %s section in %B"); -+ } -+ } -+ -+ fail: -+ if (buffer) -+ free (buffer); -+ -+ if (error_message) -+ (*_bfd_error_handler) (error_message, ibfd, APUINFO_SECTION_NAME); -+} -+ -+/* Prevent the output section from accumulating the input sections' -+ contents. We have already stored this in our linked list structure. */ -+ -+static bfd_boolean -+ppc_elf_amigaos_write_section (bfd *abfd ATTRIBUTE_UNUSED, -+ struct bfd_link_info *link_info ATTRIBUTE_UNUSED, -+ asection *asec, -+ bfd_byte *contents ATTRIBUTE_UNUSED) -+{ -+ return apuinfo_set && strcmp (asec->name, APUINFO_SECTION_NAME) == 0; -+} -+ -+/* Finally we can generate the output section. */ -+ -+static void -+ppc_elf_amigaos_final_write_processing (bfd *abfd, bfd_boolean linker ATTRIBUTE_UNUSED) -+{ -+ bfd_byte *buffer; -+ asection *asec; -+ unsigned i; -+ unsigned num_entries; -+ bfd_size_type length; -+ -+ asec = bfd_get_section_by_name (abfd, APUINFO_SECTION_NAME); -+ if (asec == NULL) -+ return; -+ -+ if (!apuinfo_set) -+ return; -+ -+ length = asec->size; -+ if (length < 20) -+ return; -+ -+ buffer = bfd_malloc (length); -+ if (buffer == NULL) -+ { -+ (*_bfd_error_handler) -+ (_("failed to allocate space for new APUinfo section.")); -+ return; -+ } -+ -+ /* Create the apuinfo header. */ -+ num_entries = apuinfo_list_length (); -+ bfd_put_32 (abfd, sizeof APUINFO_LABEL, buffer); -+ bfd_put_32 (abfd, num_entries * 4, buffer + 4); -+ bfd_put_32 (abfd, 0x2, buffer + 8); -+ strcpy ((char *) buffer + 12, APUINFO_LABEL); -+ -+ length = 20; -+ for (i = 0; i < num_entries; i++) -+ { -+ bfd_put_32 (abfd, apuinfo_list_element (i), buffer + length); -+ length += 4; -+ } -+ -+ if (length != asec->size) -+ (*_bfd_error_handler) (_("failed to compute new APUinfo section.")); -+ -+ if (! bfd_set_section_contents (abfd, asec, buffer, (file_ptr) 0, length)) -+ (*_bfd_error_handler) (_("failed to install new APUinfo section.")); -+ -+ free (buffer); -+ -+ apuinfo_list_finish (); -+} -+ -+static bfd_boolean -+is_nonpic_glink_stub (bfd *abfd, asection *glink, bfd_vma off) -+{ -+ bfd_byte buf[GLINK_ENTRY_SIZE]; -+ -+ if (!bfd_get_section_contents (abfd, glink, buf, off, GLINK_ENTRY_SIZE)) -+ return FALSE; -+ -+ return ((bfd_get_32 (abfd, buf + 0) & 0xffff0000) == LIS_11 -+ && (bfd_get_32 (abfd, buf + 4) & 0xffff0000) == LWZ_11_11 -+ && bfd_get_32 (abfd, buf + 8) == MTCTR_11 -+ && bfd_get_32 (abfd, buf + 12) == BCTR); -+} -+ -+static bfd_boolean -+section_covers_vma (bfd *abfd ATTRIBUTE_UNUSED, asection *section, void *ptr) -+{ -+ bfd_vma vma = *(bfd_vma *) ptr; -+ return ((section->flags & SEC_ALLOC) != 0 -+ && section->vma <= vma -+ && vma < section->vma + section->size); -+} -+ -+static long -+ppc_elf_get_synthetic_symtab (bfd *abfd, long symcount, asymbol **syms, -+ long dynsymcount, asymbol **dynsyms, -+ asymbol **ret) -+{ -+ bfd_boolean (*slurp_relocs) (bfd *, asection *, asymbol **, bfd_boolean); -+ asection *plt, *relplt, *dynamic, *glink; -+ bfd_vma glink_vma = 0; -+ bfd_vma resolv_vma = 0; -+ bfd_vma stub_vma; -+ asymbol *s; -+ arelent *p; -+ long count, i; -+ size_t size; -+ char *names; -+ bfd_byte buf[4]; -+ -+ *ret = NULL; -+ -+ if ((abfd->flags & (DYNAMIC | EXEC_P)) == 0) -+ return 0; -+ -+ if (dynsymcount <= 0) -+ return 0; -+ -+ relplt = bfd_get_section_by_name (abfd, ".rela.plt"); -+ if (relplt == NULL) -+ return 0; -+ -+ plt = bfd_get_section_by_name (abfd, ".plt"); -+ if (plt == NULL) -+ return 0; -+ -+ /* Call common code to handle old-style executable PLTs. */ -+ if (elf_section_flags (plt) & SHF_EXECINSTR) -+ return _bfd_elf_get_synthetic_symtab (abfd, symcount, syms, -+ dynsymcount, dynsyms, ret); -+ -+ /* If this object was prelinked, the prelinker stored the address -+ of .glink at got[1]. If it wasn't prelinked, got[1] will be zero. */ -+ dynamic = bfd_get_section_by_name (abfd, ".dynamic"); -+ if (dynamic != NULL) -+ { -+ bfd_byte *dynbuf, *extdyn, *extdynend; -+ size_t extdynsize; -+ void (*swap_dyn_in) (bfd *, const void *, Elf_Internal_Dyn *); -+ -+ if (!bfd_malloc_and_get_section (abfd, dynamic, &dynbuf)) -+ return -1; -+ -+ extdynsize = get_elf_backend_data (abfd)->s->sizeof_dyn; -+ swap_dyn_in = get_elf_backend_data (abfd)->s->swap_dyn_in; -+ -+ extdyn = dynbuf; -+ extdynend = extdyn + dynamic->size; -+ for (; extdyn < extdynend; extdyn += extdynsize) -+ { -+ Elf_Internal_Dyn dyn; -+ (*swap_dyn_in) (abfd, extdyn, &dyn); -+ -+ if (dyn.d_tag == DT_NULL) -+ break; -+ -+ if (dyn.d_tag == DT_PPC_GOT) -+ { -+ unsigned int g_o_t = dyn.d_un.d_val; -+ asection *got = bfd_get_section_by_name (abfd, ".got"); -+ if (got != NULL -+ && bfd_get_section_contents (abfd, got, buf, -+ g_o_t - got->vma + 4, 4)) -+ glink_vma = bfd_get_32 (abfd, buf); -+ break; -+ } -+ } -+ free (dynbuf); -+ } -+ -+ /* Otherwise we read the first plt entry. */ -+ if (glink_vma == 0) -+ { -+ if (bfd_get_section_contents (abfd, plt, buf, 0, 4)) -+ glink_vma = bfd_get_32 (abfd, buf); -+ } -+ -+ if (glink_vma == 0) -+ return 0; -+ -+ /* The .glink section usually does not survive the final -+ link; search for the section (usually .text) where the -+ glink stubs now reside. */ -+ glink = bfd_sections_find_if (abfd, section_covers_vma, &glink_vma); -+ if (glink == NULL) -+ return 0; -+ -+ /* Determine glink PLT resolver by reading the relative branch -+ from the first glink stub. */ -+ if (bfd_get_section_contents (abfd, glink, buf, -+ glink_vma - glink->vma, 4)) -+ { -+ unsigned int insn = bfd_get_32 (abfd, buf); -+ -+ /* The first glink stub may either branch to the resolver ... */ -+ insn ^= B; -+ if ((insn & ~0x3fffffc) == 0) -+ resolv_vma = glink_vma + (insn ^ 0x2000000) - 0x2000000; -+ -+ /* ... or fall through a bunch of NOPs. */ -+ else if ((insn ^ B ^ NOP) == 0) -+ for (i = 4; -+ bfd_get_section_contents (abfd, glink, buf, -+ glink_vma - glink->vma + i, 4); -+ i += 4) -+ if (bfd_get_32 (abfd, buf) != NOP) -+ { -+ resolv_vma = glink_vma + i; -+ break; -+ } -+ } -+ -+ count = relplt->size / sizeof (Elf32_External_Rela); -+ stub_vma = glink_vma - (bfd_vma) count * 16; -+ /* If the stubs are those for -shared/-pie then we might have -+ multiple stubs for each plt entry. If that is the case then -+ there is no way to associate stubs with their plt entries short -+ of figuring out the GOT pointer value used in the stub. */ -+ if (!is_nonpic_glink_stub (abfd, glink, -+ glink_vma - GLINK_ENTRY_SIZE - glink->vma)) -+ return 0; -+ -+ slurp_relocs = get_elf_backend_data (abfd)->s->slurp_reloc_table; -+ if (! (*slurp_relocs) (abfd, relplt, dynsyms, TRUE)) -+ return -1; -+ -+ size = count * sizeof (asymbol); -+ p = relplt->relocation; -+ for (i = 0; i < count; i++, p++) -+ { -+ size += strlen ((*p->sym_ptr_ptr)->name) + sizeof ("@plt"); -+ if (p->addend != 0) -+ size += sizeof ("+0x") - 1 + 8; -+ } -+ -+ size += sizeof (asymbol) + sizeof ("__glink"); -+ -+ if (resolv_vma) -+ size += sizeof (asymbol) + sizeof ("__glink_PLTresolve"); -+ -+ s = *ret = bfd_malloc (size); -+ if (s == NULL) -+ return -1; -+ -+ names = (char *) (s + count + 1 + (resolv_vma != 0)); -+ p = relplt->relocation; -+ for (i = 0; i < count; i++, p++) -+ { -+ size_t len; -+ -+ *s = **p->sym_ptr_ptr; -+ /* Undefined syms won't have BSF_LOCAL or BSF_GLOBAL set. Since -+ we are defining a symbol, ensure one of them is set. */ -+ if ((s->flags & BSF_LOCAL) == 0) -+ s->flags |= BSF_GLOBAL; -+ s->flags |= BSF_SYNTHETIC; -+ s->section = glink; -+ s->value = stub_vma - glink->vma; -+ s->name = names; -+ s->udata.p = NULL; -+ len = strlen ((*p->sym_ptr_ptr)->name); -+ memcpy (names, (*p->sym_ptr_ptr)->name, len); -+ names += len; -+ if (p->addend != 0) -+ { -+ memcpy (names, "+0x", sizeof ("+0x") - 1); -+ names += sizeof ("+0x") - 1; -+ bfd_sprintf_vma (abfd, names, p->addend); -+ names += strlen (names); -+ } -+ memcpy (names, "@plt", sizeof ("@plt")); -+ names += sizeof ("@plt"); -+ ++s; -+ stub_vma += 16; -+ } -+ -+ /* Add a symbol at the start of the glink branch table. */ -+ memset (s, 0, sizeof *s); -+ s->the_bfd = abfd; -+ s->flags = BSF_GLOBAL | BSF_SYNTHETIC; -+ s->section = glink; -+ s->value = glink_vma - glink->vma; -+ s->name = names; -+ memcpy (names, "__glink", sizeof ("__glink")); -+ names += sizeof ("__glink"); -+ s++; -+ count++; -+ -+ if (resolv_vma) -+ { -+ /* Add a symbol for the glink PLT resolver. */ -+ memset (s, 0, sizeof *s); -+ s->the_bfd = abfd; -+ s->flags = BSF_GLOBAL | BSF_SYNTHETIC; -+ s->section = glink; -+ s->value = resolv_vma - glink->vma; -+ s->name = names; -+ memcpy (names, "__glink_PLTresolve", sizeof ("__glink_PLTresolve")); -+ names += sizeof ("__glink_PLTresolve"); -+ s++; -+ count++; -+ } -+ -+ return count; -+} -+ -+/* The following functions are specific to the ELF linker, while -+ functions above are used generally. They appear in this file more -+ or less in the order in which they are called. eg. -+ ppc_elf_check_relocs is called early in the link process, -+ ppc_elf_finish_dynamic_sections is one of the last functions -+ called. */ -+ -+/* Track PLT entries needed for a given symbol. We might need more -+ than one glink entry per symbol when generating a pic binary. */ -+struct plt_entry -+{ -+ struct plt_entry *next; -+ -+ /* -fPIC uses multiple GOT sections, one per file, called ".got2". -+ This field stores the offset into .got2 used to initialise the -+ GOT pointer reg. It will always be at least 32768. (Current -+ gcc always uses an offset of 32768, but ld -r will pack .got2 -+ sections together resulting in larger offsets). */ -+ bfd_vma addend; -+ -+ /* The .got2 section. */ -+ asection *sec; -+ -+ /* PLT refcount or offset. */ -+ union -+ { -+ bfd_signed_vma refcount; -+ bfd_vma offset; -+ } plt; -+ -+ /* .glink stub offset. */ -+ bfd_vma glink_offset; -+}; -+ -+/* Of those relocs that might be copied as dynamic relocs, this function -+ selects those that must be copied when linking a shared library, -+ even when the symbol is local. */ -+ -+static int -+must_be_dyn_reloc (struct bfd_link_info *info, -+ enum elf_ppc_reloc_type r_type) -+{ -+ switch (r_type) -+ { -+ default: -+ return 1; -+ -+ case R_PPC_REL24: -+ case R_PPC_REL14: -+ case R_PPC_REL14_BRTAKEN: -+ case R_PPC_REL14_BRNTAKEN: -+ case R_PPC_REL32: -+ return 0; -+ -+ case R_PPC_TPREL32: -+ case R_PPC_TPREL16: -+ case R_PPC_TPREL16_LO: -+ case R_PPC_TPREL16_HI: -+ case R_PPC_TPREL16_HA: -+ return !info->executable; -+ } -+} -+ -+/* If ELIMINATE_COPY_RELOCS is non-zero, the linker will try to avoid -+ copying dynamic variables from a shared lib into an app's dynbss -+ section, and instead use a dynamic relocation to point into the -+ shared lib. */ -+#define ELIMINATE_COPY_RELOCS 1 -+ -+/* PPC ELF linker hash entry. */ -+ -+struct ppc_elf_link_hash_entry -+{ -+ struct elf_link_hash_entry elf; -+ -+ /* If this symbol is used in the linker created sections, the processor -+ specific backend uses this field to map the field into the offset -+ from the beginning of the section. */ -+ elf_linker_section_pointers_t *linker_section_pointer; -+ -+ /* Track dynamic relocs copied for this symbol. */ -+ struct elf_dyn_relocs *dyn_relocs; -+ -+ /* Contexts in which symbol is used in the GOT (or TOC). -+ TLS_GD .. TLS_TLS bits are or'd into the mask as the -+ corresponding relocs are encountered during check_relocs. -+ tls_optimize clears TLS_GD .. TLS_TPREL when optimizing to -+ indicate the corresponding GOT entry type is not needed. */ -+#define TLS_GD 1 /* GD reloc. */ -+#define TLS_LD 2 /* LD reloc. */ -+#define TLS_TPREL 4 /* TPREL reloc, => IE. */ -+#define TLS_DTPREL 8 /* DTPREL reloc, => LD. */ -+#define TLS_TLS 16 /* Any TLS reloc. */ -+#define TLS_TPRELGD 32 /* TPREL reloc resulting from GD->IE. */ -+#define PLT_IFUNC 64 /* STT_GNU_IFUNC. */ -+ char tls_mask; -+ -+ /* Nonzero if we have seen a small data relocation referring to this -+ symbol. */ -+ unsigned char has_sda_refs; -+}; -+ -+#define ppc_elf_hash_entry(ent) ((struct ppc_elf_link_hash_entry *) (ent)) -+ -+/* PPC ELF linker hash table. */ -+ -+struct ppc_elf_link_hash_table -+{ -+ struct elf_link_hash_table elf; -+ -+ /* Short-cuts to get to dynamic linker sections. */ -+ asection *got; -+ asection *relgot; -+ asection *glink; -+ asection *plt; -+ asection *relplt; -+ asection *iplt; -+ asection *reliplt; -+ asection *dynbss; -+ asection *relbss; -+ asection *dynsbss; -+ asection *relsbss; -+ elf_linker_section_t sdata[2]; -+ asection *sbss; -+ asection *glink_eh_frame; -+ -+ /* The (unloaded but important) .rela.plt.unloaded on VxWorks. */ -+ asection *srelplt2; -+ -+ /* The .got.plt section (VxWorks only)*/ -+ asection *sgotplt; -+ -+ /* Shortcut to __tls_get_addr. */ -+ struct elf_link_hash_entry *tls_get_addr; -+ -+ /* The bfd that forced an old-style PLT. */ -+ bfd *old_bfd; -+ -+ /* TLS local dynamic got entry handling. */ -+ union { -+ bfd_signed_vma refcount; -+ bfd_vma offset; -+ } tlsld_got; -+ -+ /* Offset of branch table to PltResolve function in glink. */ -+ bfd_vma glink_pltresolve; -+ -+ /* Size of reserved GOT entries. */ -+ unsigned int got_header_size; -+ /* Non-zero if allocating the header left a gap. */ -+ unsigned int got_gap; -+ -+ /* The type of PLT we have chosen to use. */ -+ enum ppc_elf_plt_type plt_type; -+ -+ /* Set if we should emit symbols for stubs. */ -+ unsigned int emit_stub_syms:1; -+ -+ /* Set if __tls_get_addr optimization should not be done. */ -+ unsigned int no_tls_get_addr_opt:1; -+ -+ /* True if the target system is VxWorks. */ -+ unsigned int is_vxworks:1; -+ -+ /* The size of PLT entries. */ -+ int plt_entry_size; -+ /* The distance between adjacent PLT slots. */ -+ int plt_slot_size; -+ /* The size of the first PLT entry. */ -+ int plt_initial_entry_size; -+ -+ /* Small local sym cache. */ -+ struct sym_cache sym_cache; -+}; -+ -+/* Rename some of the generic section flags to better document how they -+ are used for ppc32. The flags are only valid for ppc32 elf objects. */ -+ -+/* Nonzero if this section has TLS related relocations. */ -+#define has_tls_reloc sec_flg0 -+ -+/* Nonzero if this section has a call to __tls_get_addr. */ -+#define has_tls_get_addr_call sec_flg1 -+ -+/* Get the PPC ELF linker hash table from a link_info structure. */ -+ -+#define ppc_elf_hash_table(p) \ -+ (elf_hash_table_id ((struct elf_link_hash_table *) ((p)->hash)) \ -+ == PPC32_ELF_DATA ? ((struct ppc_elf_link_hash_table *) ((p)->hash)) : NULL) -+ -+/* Create an entry in a PPC ELF linker hash table. */ -+ -+static struct bfd_hash_entry * -+ppc_elf_link_hash_newfunc (struct bfd_hash_entry *entry, -+ struct bfd_hash_table *table, -+ const char *string) -+{ -+ /* Allocate the structure if it has not already been allocated by a -+ subclass. */ -+ if (entry == NULL) -+ { -+ entry = bfd_hash_allocate (table, -+ sizeof (struct ppc_elf_link_hash_entry)); -+ if (entry == NULL) -+ return entry; -+ } -+ -+ /* Call the allocation method of the superclass. */ -+ entry = _bfd_elf_link_hash_newfunc (entry, table, string); -+ if (entry != NULL) -+ { -+ ppc_elf_hash_entry (entry)->linker_section_pointer = NULL; -+ ppc_elf_hash_entry (entry)->dyn_relocs = NULL; -+ ppc_elf_hash_entry (entry)->tls_mask = 0; -+ ppc_elf_hash_entry (entry)->has_sda_refs = 0; -+ } -+ -+ return entry; -+} -+ -+/* Create a PPC ELF linker hash table. */ -+ -+static struct bfd_link_hash_table * -+ppc_elf_link_hash_table_create (bfd *abfd) -+{ -+ struct ppc_elf_link_hash_table *ret; -+ -+ ret = bfd_zmalloc (sizeof (struct ppc_elf_link_hash_table)); -+ if (ret == NULL) -+ return NULL; -+ -+ if (!_bfd_elf_link_hash_table_init (&ret->elf, abfd, -+ ppc_elf_link_hash_newfunc, -+ sizeof (struct ppc_elf_link_hash_entry), -+ PPC32_ELF_DATA)) -+ { -+ free (ret); -+ return NULL; -+ } -+ -+ ret->elf.init_plt_refcount.refcount = 0; -+ ret->elf.init_plt_refcount.glist = NULL; -+ ret->elf.init_plt_offset.offset = 0; -+ ret->elf.init_plt_offset.glist = NULL; -+ -+ ret->sdata[0].name = ".sdata"; -+ ret->sdata[0].sym_name = "_SDA_BASE_"; -+ ret->sdata[0].bss_name = ".sbss"; -+ -+ ret->sdata[1].name = ".sdata2"; -+ ret->sdata[1].sym_name = "_SDA2_BASE_"; -+ ret->sdata[1].bss_name = ".sbss2"; -+ -+ ret->plt_entry_size = 12; -+ ret->plt_slot_size = 8; -+ ret->plt_initial_entry_size = 72; -+ -+ return &ret->elf.root; -+} -+ -+/* Create .got and the related sections. */ -+ -+static bfd_boolean -+ppc_elf_create_got (bfd *abfd, struct bfd_link_info *info) -+{ -+ struct ppc_elf_link_hash_table *htab; -+ asection *s; -+ flagword flags; -+ -+ if (!_bfd_elf_create_got_section (abfd, info)) -+ return FALSE; -+ -+ htab = ppc_elf_hash_table (info); -+ htab->got = s = bfd_get_linker_section (abfd, ".got"); -+ if (s == NULL) -+ abort (); -+ -+ if (htab->is_vxworks) -+ { -+ htab->sgotplt = bfd_get_linker_section (abfd, ".got.plt"); -+ if (!htab->sgotplt) -+ abort (); -+ } -+ else -+ { -+ /* The powerpc .got has a blrl instruction in it. Mark it -+ executable. */ -+ flags = (SEC_ALLOC | SEC_LOAD | /*SEC_CODE |*/ SEC_HAS_CONTENTS -+ | SEC_IN_MEMORY | SEC_LINKER_CREATED); -+ if (!bfd_set_section_flags (abfd, s, flags)) -+ return FALSE; -+ } -+ -+ htab->relgot = bfd_get_linker_section (abfd, ".rela.got"); -+ if (!htab->relgot) -+ abort (); -+ -+ return TRUE; -+} -+ -+static bfd_boolean -+ppc_elf_create_glink (bfd *abfd, struct bfd_link_info *info) -+{ -+ struct ppc_elf_link_hash_table *htab = ppc_elf_hash_table (info); -+ asection *s; -+ flagword flags; -+ -+ flags = (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_READONLY | SEC_HAS_CONTENTS -+ | SEC_IN_MEMORY | SEC_LINKER_CREATED); -+ s = bfd_make_section_anyway_with_flags (abfd, ".glink", flags); -+ htab->glink = s; -+ if (s == NULL -+ || !bfd_set_section_alignment (abfd, s, 4)) -+ return FALSE; -+ -+ if (!info->no_ld_generated_unwind_info) -+ { -+ flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_HAS_CONTENTS -+ | SEC_IN_MEMORY | SEC_LINKER_CREATED); -+ s = bfd_make_section_anyway_with_flags (abfd, ".eh_frame", flags); -+ htab->glink_eh_frame = s; -+ if (s == NULL -+ || !bfd_set_section_alignment (abfd, s, 2)) -+ return FALSE; -+ } -+ -+ flags = SEC_ALLOC | SEC_LINKER_CREATED; -+ s = bfd_make_section_anyway_with_flags (abfd, ".iplt", flags); -+ htab->iplt = s; -+ if (s == NULL -+ || !bfd_set_section_alignment (abfd, s, 4)) -+ return FALSE; -+ -+ flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_HAS_CONTENTS -+ | SEC_IN_MEMORY | SEC_LINKER_CREATED); -+ s = bfd_make_section_anyway_with_flags (abfd, ".rela.iplt", flags); -+ htab->reliplt = s; -+ if (s == NULL -+ || ! bfd_set_section_alignment (abfd, s, 2)) -+ return FALSE; -+ return TRUE; -+} -+ -+/* We have to create .dynsbss and .rela.sbss here so that they get mapped -+ to output sections (just like _bfd_elf_create_dynamic_sections has -+ to create .dynbss and .rela.bss). */ -+ -+static bfd_boolean -+ppc_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) -+{ -+ struct ppc_elf_link_hash_table *htab; -+ asection *s; -+ flagword flags; -+ -+ htab = ppc_elf_hash_table (info); -+ -+ if (htab->got == NULL -+ && !ppc_elf_create_got (abfd, info)) -+ return FALSE; -+ -+ if (!_bfd_elf_create_dynamic_sections (abfd, info)) -+ return FALSE; -+ -+ if (htab->glink == NULL -+ && !ppc_elf_create_glink (abfd, info)) -+ return FALSE; -+ -+ htab->dynbss = bfd_get_linker_section (abfd, ".dynbss"); -+ s = bfd_make_section_anyway_with_flags (abfd, ".dynsbss", -+ SEC_ALLOC | SEC_LINKER_CREATED); -+ htab->dynsbss = s; -+ if (s == NULL) -+ return FALSE; -+ -+ if (! info->shared) -+ { -+ htab->relbss = bfd_get_linker_section (abfd, ".rela.bss"); -+ flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_HAS_CONTENTS -+ | SEC_IN_MEMORY | SEC_LINKER_CREATED); -+ s = bfd_make_section_anyway_with_flags (abfd, ".rela.sbss", flags); -+ htab->relsbss = s; -+ if (s == NULL -+ || ! bfd_set_section_alignment (abfd, s, 2)) -+ return FALSE; -+ } -+ -+ if (htab->is_vxworks -+ && !elf_vxworks_create_dynamic_sections (abfd, info, &htab->srelplt2)) -+ return FALSE; -+ -+ htab->relplt = bfd_get_linker_section (abfd, ".rela.plt"); -+ htab->plt = s = bfd_get_linker_section (abfd, ".plt"); -+ if (s == NULL) -+ abort (); -+ -+ flags = SEC_ALLOC | SEC_CODE | SEC_LINKER_CREATED | SEC_READONLY; -+ if (htab->plt_type == PLT_VXWORKS) -+ /* The VxWorks PLT is a loaded section with contents. */ -+ flags |= SEC_HAS_CONTENTS | SEC_LOAD | SEC_READONLY; -+ return bfd_set_section_flags (abfd, s, flags); -+} -+ -+/* Copy the extra info we tack onto an elf_link_hash_entry. */ -+ -+static void -+ppc_elf_copy_indirect_symbol (struct bfd_link_info *info, -+ struct elf_link_hash_entry *dir, -+ struct elf_link_hash_entry *ind) -+{ -+ struct ppc_elf_link_hash_entry *edir, *eind; -+ -+ edir = (struct ppc_elf_link_hash_entry *) dir; -+ eind = (struct ppc_elf_link_hash_entry *) ind; -+ -+ edir->tls_mask |= eind->tls_mask; -+ edir->has_sda_refs |= eind->has_sda_refs; -+ -+ /* If called to transfer flags for a weakdef during processing -+ of elf_adjust_dynamic_symbol, don't copy non_got_ref. -+ We clear it ourselves for ELIMINATE_COPY_RELOCS. */ -+ if (!(ELIMINATE_COPY_RELOCS -+ && eind->elf.root.type != bfd_link_hash_indirect -+ && edir->elf.dynamic_adjusted)) -+ edir->elf.non_got_ref |= eind->elf.non_got_ref; -+ -+ edir->elf.ref_dynamic |= eind->elf.ref_dynamic; -+ edir->elf.ref_regular |= eind->elf.ref_regular; -+ edir->elf.ref_regular_nonweak |= eind->elf.ref_regular_nonweak; -+ edir->elf.needs_plt |= eind->elf.needs_plt; -+ edir->elf.pointer_equality_needed |= eind->elf.pointer_equality_needed; -+ -+ if (eind->dyn_relocs != NULL) -+ { -+ if (edir->dyn_relocs != NULL) -+ { -+ struct elf_dyn_relocs **pp; -+ struct elf_dyn_relocs *p; -+ -+ /* Add reloc counts against the indirect sym to the direct sym -+ list. Merge any entries against the same section. */ -+ for (pp = &eind->dyn_relocs; (p = *pp) != NULL; ) -+ { -+ struct elf_dyn_relocs *q; -+ -+ for (q = edir->dyn_relocs; q != NULL; q = q->next) -+ if (q->sec == p->sec) -+ { -+ q->pc_count += p->pc_count; -+ q->count += p->count; -+ *pp = p->next; -+ break; -+ } -+ if (q == NULL) -+ pp = &p->next; -+ } -+ *pp = edir->dyn_relocs; -+ } -+ -+ edir->dyn_relocs = eind->dyn_relocs; -+ eind->dyn_relocs = NULL; -+ } -+ -+ /* If we were called to copy over info for a weak sym, that's all. -+ You might think dyn_relocs need not be copied over; After all, -+ both syms will be dynamic or both non-dynamic so we're just -+ moving reloc accounting around. However, ELIMINATE_COPY_RELOCS -+ code in ppc_elf_adjust_dynamic_symbol needs to check for -+ dyn_relocs in read-only sections, and it does so on what is the -+ DIR sym here. */ -+ if (eind->elf.root.type != bfd_link_hash_indirect) -+ return; -+ -+ /* Copy over the GOT refcount entries that we may have already seen to -+ the symbol which just became indirect. */ -+ edir->elf.got.refcount += eind->elf.got.refcount; -+ eind->elf.got.refcount = 0; -+ -+ /* And plt entries. */ -+ if (eind->elf.plt.plist != NULL) -+ { -+ if (edir->elf.plt.plist != NULL) -+ { -+ struct plt_entry **entp; -+ struct plt_entry *ent; -+ -+ for (entp = &eind->elf.plt.plist; (ent = *entp) != NULL; ) -+ { -+ struct plt_entry *dent; -+ -+ for (dent = edir->elf.plt.plist; dent != NULL; dent = dent->next) -+ if (dent->sec == ent->sec && dent->addend == ent->addend) -+ { -+ dent->plt.refcount += ent->plt.refcount; -+ *entp = ent->next; -+ break; -+ } -+ if (dent == NULL) -+ entp = &ent->next; -+ } -+ *entp = edir->elf.plt.plist; -+ } -+ -+ edir->elf.plt.plist = eind->elf.plt.plist; -+ eind->elf.plt.plist = NULL; -+ } -+ -+ if (eind->elf.dynindx != -1) -+ { -+ if (edir->elf.dynindx != -1) -+ _bfd_elf_strtab_delref (elf_hash_table (info)->dynstr, -+ edir->elf.dynstr_index); -+ edir->elf.dynindx = eind->elf.dynindx; -+ edir->elf.dynstr_index = eind->elf.dynstr_index; -+ eind->elf.dynindx = -1; -+ eind->elf.dynstr_index = 0; -+ } -+} -+ -+/* Hook called by the linker routine which adds symbols from an object -+ file. We use it to put .comm items in .sbss, and not .bss. */ -+ -+static bfd_boolean -+ppc_elf_add_symbol_hook (bfd *abfd, -+ struct bfd_link_info *info, -+ Elf_Internal_Sym *sym, -+ const char **namep ATTRIBUTE_UNUSED, -+ flagword *flagsp ATTRIBUTE_UNUSED, -+ asection **secp, -+ bfd_vma *valp) -+{ -+ if (sym->st_shndx == SHN_COMMON -+ && !info->relocatable -+ && is_ppc_elf (info->output_bfd) -+ && sym->st_size <= elf_gp_size (abfd)) -+ { -+ /* Common symbols less than or equal to -G nn bytes are automatically -+ put into .sbss. */ -+ struct ppc_elf_link_hash_table *htab; -+ -+ htab = ppc_elf_hash_table (info); -+ if (htab->sbss == NULL) -+ { -+ flagword flags = SEC_IS_COMMON | SEC_LINKER_CREATED; -+ -+ if (!htab->elf.dynobj) -+ htab->elf.dynobj = abfd; -+ -+ htab->sbss = bfd_make_section_anyway_with_flags (htab->elf.dynobj, -+ ".sbss", -+ flags); -+ if (htab->sbss == NULL) -+ return FALSE; -+ } -+ -+ *secp = htab->sbss; -+ *valp = sym->st_size; -+ } -+ -+ if ((abfd->flags & DYNAMIC) == 0 -+ && (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC -+ || ELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE)) -+ elf_tdata (info->output_bfd)->has_gnu_symbols = TRUE; -+ -+ return TRUE; -+} -+ -+static bfd_boolean -+create_sdata_sym (struct bfd_link_info *info, elf_linker_section_t *lsect) -+{ -+ struct ppc_elf_link_hash_table *htab = ppc_elf_hash_table (info); -+ -+ lsect->sym = elf_link_hash_lookup (&htab->elf, lsect->sym_name, -+ TRUE, FALSE, TRUE); -+ if (lsect->sym == NULL) -+ return FALSE; -+ if (lsect->sym->root.type == bfd_link_hash_new) -+ lsect->sym->non_elf = 0; -+ lsect->sym->ref_regular = 1; -+ _bfd_elf_link_hash_hide_symbol (info, lsect->sym, TRUE); -+ return TRUE; -+} -+ -+/* Create a special linker section. */ -+ -+static bfd_boolean -+ppc_elf_create_linker_section (bfd *abfd, -+ struct bfd_link_info *info, -+ flagword flags, -+ elf_linker_section_t *lsect) -+{ -+ struct ppc_elf_link_hash_table *htab = ppc_elf_hash_table (info); -+ asection *s; -+ -+ flags |= (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY -+ | SEC_LINKER_CREATED); -+ -+ /* Record the first bfd that needs the special sections. */ -+ if (!htab->elf.dynobj) -+ htab->elf.dynobj = abfd; -+ -+ s = bfd_make_section_anyway_with_flags (htab->elf.dynobj, -+ lsect->name, -+ flags); -+ if (s == NULL -+ || !bfd_set_section_alignment (htab->elf.dynobj, s, 2)) -+ return FALSE; -+ lsect->section = s; -+ -+ return create_sdata_sym (info, lsect); -+} -+ -+/* Find a linker generated pointer with a given addend and type. */ -+ -+static elf_linker_section_pointers_t * -+elf_find_pointer_linker_section -+ (elf_linker_section_pointers_t *linker_pointers, -+ bfd_vma addend, -+ elf_linker_section_t *lsect) -+{ -+ for ( ; linker_pointers != NULL; linker_pointers = linker_pointers->next) -+ if (lsect == linker_pointers->lsect && addend == linker_pointers->addend) -+ return linker_pointers; -+ -+ return NULL; -+} -+ -+/* Allocate a pointer to live in a linker created section. */ -+ -+static bfd_boolean -+elf_create_pointer_linker_section (bfd *abfd, -+ elf_linker_section_t *lsect, -+ struct elf_link_hash_entry *h, -+ const Elf_Internal_Rela *rel) -+{ -+ elf_linker_section_pointers_t **ptr_linker_section_ptr = NULL; -+ elf_linker_section_pointers_t *linker_section_ptr; -+ unsigned long r_symndx = ELF32_R_SYM (rel->r_info); -+ bfd_size_type amt; -+ -+ BFD_ASSERT (lsect != NULL); -+ -+ /* Is this a global symbol? */ -+ if (h != NULL) -+ { -+ struct ppc_elf_link_hash_entry *eh; -+ -+ /* Has this symbol already been allocated? If so, our work is done. */ -+ eh = (struct ppc_elf_link_hash_entry *) h; -+ if (elf_find_pointer_linker_section (eh->linker_section_pointer, -+ rel->r_addend, -+ lsect)) -+ return TRUE; -+ -+ ptr_linker_section_ptr = &eh->linker_section_pointer; -+ } -+ else -+ { -+ BFD_ASSERT (is_ppc_elf (abfd)); -+ -+ /* Allocation of a pointer to a local symbol. */ -+ elf_linker_section_pointers_t **ptr = elf_local_ptr_offsets (abfd); -+ -+ /* Allocate a table to hold the local symbols if first time. */ -+ if (!ptr) -+ { -+ unsigned int num_symbols = elf_symtab_hdr (abfd).sh_info; -+ -+ amt = num_symbols; -+ amt *= sizeof (elf_linker_section_pointers_t *); -+ ptr = bfd_zalloc (abfd, amt); -+ -+ if (!ptr) -+ return FALSE; -+ -+ elf_local_ptr_offsets (abfd) = ptr; -+ } -+ -+ /* Has this symbol already been allocated? If so, our work is done. */ -+ if (elf_find_pointer_linker_section (ptr[r_symndx], -+ rel->r_addend, -+ lsect)) -+ return TRUE; -+ -+ ptr_linker_section_ptr = &ptr[r_symndx]; -+ } -+ -+ /* Allocate space for a pointer in the linker section, and allocate -+ a new pointer record from internal memory. */ -+ BFD_ASSERT (ptr_linker_section_ptr != NULL); -+ amt = sizeof (elf_linker_section_pointers_t); -+ linker_section_ptr = bfd_alloc (abfd, amt); -+ -+ if (!linker_section_ptr) -+ return FALSE; -+ -+ linker_section_ptr->next = *ptr_linker_section_ptr; -+ linker_section_ptr->addend = rel->r_addend; -+ linker_section_ptr->lsect = lsect; -+ *ptr_linker_section_ptr = linker_section_ptr; -+ -+ linker_section_ptr->offset = lsect->section->size; -+ lsect->section->size += 4; -+ -+#ifdef DEBUG -+ fprintf (stderr, -+ "Create pointer in linker section %s, offset = %ld, section size = %ld\n", -+ lsect->name, (long) linker_section_ptr->offset, -+ (long) lsect->section->size); -+#endif -+ -+ return TRUE; -+} -+ -+static struct plt_entry ** -+update_local_sym_info (bfd *abfd, -+ Elf_Internal_Shdr *symtab_hdr, -+ unsigned long r_symndx, -+ int tls_type) -+{ -+ bfd_signed_vma *local_got_refcounts = elf_local_got_refcounts (abfd); -+ struct plt_entry **local_plt; -+ char *local_got_tls_masks; -+ -+ if (local_got_refcounts == NULL) -+ { -+ bfd_size_type size = symtab_hdr->sh_info; -+ -+ size *= (sizeof (*local_got_refcounts) -+ + sizeof (*local_plt) -+ + sizeof (*local_got_tls_masks)); -+ local_got_refcounts = bfd_zalloc (abfd, size); -+ if (local_got_refcounts == NULL) -+ return NULL; -+ elf_local_got_refcounts (abfd) = local_got_refcounts; -+ } -+ -+ local_plt = (struct plt_entry **) (local_got_refcounts + symtab_hdr->sh_info); -+ local_got_tls_masks = (char *) (local_plt + symtab_hdr->sh_info); -+ local_got_tls_masks[r_symndx] |= tls_type; -+ if (tls_type != PLT_IFUNC) -+ local_got_refcounts[r_symndx] += 1; -+ return local_plt + r_symndx; -+} -+ -+static bfd_boolean -+update_plt_info (bfd *abfd, struct plt_entry **plist, -+ asection *sec, bfd_vma addend) -+{ -+ struct plt_entry *ent; -+ -+ if (addend < 32768) -+ sec = NULL; -+ for (ent = *plist; ent != NULL; ent = ent->next) -+ if (ent->sec == sec && ent->addend == addend) -+ break; -+ if (ent == NULL) -+ { -+ bfd_size_type amt = sizeof (*ent); -+ ent = bfd_alloc (abfd, amt); -+ if (ent == NULL) -+ return FALSE; -+ ent->next = *plist; -+ ent->sec = sec; -+ ent->addend = addend; -+ ent->plt.refcount = 0; -+ *plist = ent; -+ } -+ ent->plt.refcount += 1; -+ return TRUE; -+} -+ -+static struct plt_entry * -+find_plt_ent (struct plt_entry **plist, asection *sec, bfd_vma addend) -+{ -+ struct plt_entry *ent; -+ -+ if (addend < 32768) -+ sec = NULL; -+ for (ent = *plist; ent != NULL; ent = ent->next) -+ if (ent->sec == sec && ent->addend == addend) -+ break; -+ return ent; -+} -+ -+static bfd_boolean -+is_branch_reloc (enum elf_ppc_reloc_type r_type) -+{ -+ return (r_type == R_PPC_PLTREL24 -+ || r_type == R_PPC_LOCAL24PC -+ || r_type == R_PPC_REL24 -+ || r_type == R_PPC_REL14 -+ || r_type == R_PPC_REL14_BRTAKEN -+ || r_type == R_PPC_REL14_BRNTAKEN -+ || r_type == R_PPC_ADDR24 -+ || r_type == R_PPC_ADDR14 -+ || r_type == R_PPC_ADDR14_BRTAKEN -+ || r_type == R_PPC_ADDR14_BRNTAKEN); -+} -+ -+static void -+bad_shared_reloc (bfd *abfd, enum elf_ppc_reloc_type r_type) -+{ -+ (*_bfd_error_handler) -+ (_("%B: relocation %s cannot be used when making a shared object"), -+ abfd, -+ ppc_elf_howto_table[r_type]->name); -+ bfd_set_error (bfd_error_bad_value); -+} -+ -+/* Look through the relocs for a section during the first phase, and -+ allocate space in the global offset table or procedure linkage -+ table. */ -+ -+static bfd_boolean -+ppc_elf_check_relocs (bfd *abfd, -+ struct bfd_link_info *info, -+ asection *sec, -+ const Elf_Internal_Rela *relocs) -+{ -+ struct ppc_elf_link_hash_table *htab; -+ Elf_Internal_Shdr *symtab_hdr; -+ struct elf_link_hash_entry **sym_hashes; -+ const Elf_Internal_Rela *rel; -+ const Elf_Internal_Rela *rel_end; -+ asection *got2, *sreloc; -+ struct elf_link_hash_entry *tga; -+ -+ if (info->relocatable) -+ return TRUE; -+ -+ /* Don't do anything special with non-loaded, non-alloced sections. -+ In particular, any relocs in such sections should not affect GOT -+ and PLT reference counting (ie. we don't allow them to create GOT -+ or PLT entries), there's no possibility or desire to optimize TLS -+ relocs, and there's not much point in propagating relocs to shared -+ libs that the dynamic linker won't relocate. */ -+ if ((sec->flags & SEC_ALLOC) == 0) -+ return TRUE; -+ -+#ifdef DEBUG -+ _bfd_error_handler ("ppc_elf_check_relocs called for section %A in %B", -+ sec, abfd); -+#endif -+ -+ BFD_ASSERT (is_ppc_elf (abfd)); -+ -+ /* Initialize howto table if not already done. */ -+ if (!ppc_elf_howto_table[R_PPC_ADDR32]) -+ ppc_elf_howto_init (); -+ -+ htab = ppc_elf_hash_table (info); -+ if (htab->glink == NULL) -+ { -+ if (htab->elf.dynobj == NULL) -+ htab->elf.dynobj = abfd; -+ if (!ppc_elf_create_glink (htab->elf.dynobj, info)) -+ return FALSE; -+ } -+ tga = elf_link_hash_lookup (&htab->elf, "__tls_get_addr", -+ FALSE, FALSE, TRUE); -+ symtab_hdr = &elf_symtab_hdr (abfd); -+ sym_hashes = elf_sym_hashes (abfd); -+ got2 = bfd_get_section_by_name (abfd, ".got2"); -+ sreloc = NULL; -+ -+ rel_end = relocs + sec->reloc_count; -+ for (rel = relocs; rel < rel_end; rel++) -+ { -+ unsigned long r_symndx; -+ enum elf_ppc_reloc_type r_type; -+ struct elf_link_hash_entry *h; -+ int tls_type; -+ -+ r_symndx = ELF32_R_SYM (rel->r_info); -+ if (r_symndx < symtab_hdr->sh_info) -+ h = NULL; -+ else -+ { -+ h = sym_hashes[r_symndx - symtab_hdr->sh_info]; -+ while (h->root.type == bfd_link_hash_indirect -+ || h->root.type == bfd_link_hash_warning) -+ h = (struct elf_link_hash_entry *) h->root.u.i.link; -+ } -+ -+ /* If a relocation refers to _GLOBAL_OFFSET_TABLE_, create the .got. -+ This shows up in particular in an R_PPC_ADDR32 in the eabi -+ startup code. */ -+ if (h != NULL -+ && htab->got == NULL -+ && strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0) -+ { -+ if (htab->elf.dynobj == NULL) -+ htab->elf.dynobj = abfd; -+ if (!ppc_elf_create_got (htab->elf.dynobj, info)) -+ return FALSE; -+ BFD_ASSERT (h == htab->elf.hgot); -+ } -+ -+ tls_type = 0; -+ r_type = ELF32_R_TYPE (rel->r_info); -+ if (h == NULL && !htab->is_vxworks) -+ { -+ Elf_Internal_Sym *isym = bfd_sym_from_r_symndx (&htab->sym_cache, -+ abfd, r_symndx); -+ if (isym == NULL) -+ return FALSE; -+ -+ if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC -+ && (!info->shared -+ || is_branch_reloc (r_type))) -+ { -+ struct plt_entry **ifunc; -+ bfd_vma addend; -+ -+ ifunc = update_local_sym_info (abfd, symtab_hdr, r_symndx, -+ PLT_IFUNC); -+ if (ifunc == NULL) -+ return FALSE; -+ -+ /* STT_GNU_IFUNC symbols must have a PLT entry; -+ In a non-pie executable even when there are -+ no plt calls. */ -+ addend = 0; -+ if (r_type == R_PPC_PLTREL24) -+ { -+ ppc_elf_tdata (abfd)->makes_plt_call = 1; -+ if (info->shared) -+ addend = rel->r_addend; -+ } -+ if (!update_plt_info (abfd, ifunc, got2, addend)) -+ return FALSE; -+ } -+ } -+ -+ if (!htab->is_vxworks -+ && is_branch_reloc (r_type) -+ && h != NULL -+ && h == tga) -+ { -+ if (rel != relocs -+ && (ELF32_R_TYPE (rel[-1].r_info) == R_PPC_TLSGD -+ || ELF32_R_TYPE (rel[-1].r_info) == R_PPC_TLSLD)) -+ /* We have a new-style __tls_get_addr call with a marker -+ reloc. */ -+ ; -+ else -+ /* Mark this section as having an old-style call. */ -+ sec->has_tls_get_addr_call = 1; -+ } -+ -+ switch (r_type) -+ { -+ case R_PPC_TLSGD: -+ case R_PPC_TLSLD: -+ /* These special tls relocs tie a call to __tls_get_addr with -+ its parameter symbol. */ -+ break; -+ -+ case R_PPC_GOT_TLSLD16: -+ case R_PPC_GOT_TLSLD16_LO: -+ case R_PPC_GOT_TLSLD16_HI: -+ case R_PPC_GOT_TLSLD16_HA: -+ tls_type = TLS_TLS | TLS_LD; -+ goto dogottls; -+ -+ case R_PPC_GOT_TLSGD16: -+ case R_PPC_GOT_TLSGD16_LO: -+ case R_PPC_GOT_TLSGD16_HI: -+ case R_PPC_GOT_TLSGD16_HA: -+ tls_type = TLS_TLS | TLS_GD; -+ goto dogottls; -+ -+ case R_PPC_GOT_TPREL16: -+ case R_PPC_GOT_TPREL16_LO: -+ case R_PPC_GOT_TPREL16_HI: -+ case R_PPC_GOT_TPREL16_HA: -+ if (!info->executable) -+ info->flags |= DF_STATIC_TLS; -+ tls_type = TLS_TLS | TLS_TPREL; -+ goto dogottls; -+ -+ case R_PPC_GOT_DTPREL16: -+ case R_PPC_GOT_DTPREL16_LO: -+ case R_PPC_GOT_DTPREL16_HI: -+ case R_PPC_GOT_DTPREL16_HA: -+ tls_type = TLS_TLS | TLS_DTPREL; -+ dogottls: -+ sec->has_tls_reloc = 1; -+ /* Fall thru */ -+ -+ /* GOT16 relocations */ -+ case R_PPC_GOT16: -+ case R_PPC_GOT16_LO: -+ case R_PPC_GOT16_HI: -+ case R_PPC_GOT16_HA: -+ /* This symbol requires a global offset table entry. */ -+ if (htab->got == NULL) -+ { -+ if (htab->elf.dynobj == NULL) -+ htab->elf.dynobj = abfd; -+ if (!ppc_elf_create_got (htab->elf.dynobj, info)) -+ return FALSE; -+ } -+ if (h != NULL) -+ { -+ h->got.refcount += 1; -+ ppc_elf_hash_entry (h)->tls_mask |= tls_type; -+ } -+ else -+ /* This is a global offset table entry for a local symbol. */ -+ if (!update_local_sym_info (abfd, symtab_hdr, r_symndx, tls_type)) -+ return FALSE; -+ -+ /* We may also need a plt entry if the symbol turns out to be -+ an ifunc. */ -+ if (h != NULL && !info->shared) -+ { -+ if (!update_plt_info (abfd, &h->plt.plist, NULL, 0)) -+ return FALSE; -+ } -+ break; -+ -+ /* Indirect .sdata relocation. */ -+ case R_PPC_EMB_SDAI16: -+ if (info->shared) -+ { -+ bad_shared_reloc (abfd, r_type); -+ return FALSE; -+ } -+ if (htab->sdata[0].section == NULL -+ && !ppc_elf_create_linker_section (abfd, info, 0, -+ &htab->sdata[0])) -+ return FALSE; -+ if (!elf_create_pointer_linker_section (abfd, &htab->sdata[0], -+ h, rel)) -+ return FALSE; -+ if (h != NULL) -+ { -+ ppc_elf_hash_entry (h)->has_sda_refs = TRUE; -+ h->non_got_ref = TRUE; -+ } -+ break; -+ -+ /* Indirect .sdata2 relocation. */ -+ case R_PPC_EMB_SDA2I16: -+ if (info->shared) -+ { -+ bad_shared_reloc (abfd, r_type); -+ return FALSE; -+ } -+ if (htab->sdata[1].section == NULL -+ && !ppc_elf_create_linker_section (abfd, info, SEC_READONLY, -+ &htab->sdata[1])) -+ return FALSE; -+ if (!elf_create_pointer_linker_section (abfd, &htab->sdata[1], -+ h, rel)) -+ return FALSE; -+ if (h != NULL) -+ { -+ ppc_elf_hash_entry (h)->has_sda_refs = TRUE; -+ h->non_got_ref = TRUE; -+ } -+ break; -+ -+ case R_PPC_VLE_SDAREL_LO16A: -+ case R_PPC_VLE_SDAREL_LO16D: -+ case R_PPC_VLE_SDAREL_HI16A: -+ case R_PPC_VLE_SDAREL_HI16D: -+ case R_PPC_VLE_SDAREL_HA16A: -+ case R_PPC_VLE_SDAREL_HA16D: -+ case R_PPC_SDAREL16: -+ if (htab->sdata[0].sym == NULL -+ && !create_sdata_sym (info, &htab->sdata[0])) -+ return FALSE; -+ -+ if (htab->sdata[1].sym == NULL -+ && !create_sdata_sym (info, &htab->sdata[1])) -+ return FALSE; -+ -+ if (h != NULL) -+ { -+ ppc_elf_hash_entry (h)->has_sda_refs = TRUE; -+ h->non_got_ref = TRUE; -+ } -+ break; -+ -+ case R_PPC_VLE_REL8: -+ case R_PPC_VLE_REL15: -+ case R_PPC_VLE_REL24: -+ case R_PPC_VLE_LO16A: -+ case R_PPC_VLE_LO16D: -+ case R_PPC_VLE_HI16A: -+ case R_PPC_VLE_HI16D: -+ case R_PPC_VLE_HA16A: -+ case R_PPC_VLE_HA16D: -+ break; -+ -+ case R_PPC_EMB_SDA2REL: -+ if (info->shared) -+ { -+ bad_shared_reloc (abfd, r_type); -+ return FALSE; -+ } -+ if (htab->sdata[1].sym == NULL -+ && !create_sdata_sym (info, &htab->sdata[1])) -+ return FALSE; -+ if (h != NULL) -+ { -+ ppc_elf_hash_entry (h)->has_sda_refs = TRUE; -+ h->non_got_ref = TRUE; -+ } -+ break; -+ -+ case R_PPC_VLE_SDA21_LO: -+ case R_PPC_VLE_SDA21: -+ case R_PPC_EMB_SDA21: -+ case R_PPC_EMB_RELSDA: -+ if (info->shared) -+ { -+ bad_shared_reloc (abfd, r_type); -+ return FALSE; -+ } -+ if (htab->sdata[0].sym == NULL -+ && !create_sdata_sym (info, &htab->sdata[0])) -+ return FALSE; -+ if (htab->sdata[1].sym == NULL -+ && !create_sdata_sym (info, &htab->sdata[1])) -+ return FALSE; -+ if (h != NULL) -+ { -+ ppc_elf_hash_entry (h)->has_sda_refs = TRUE; -+ h->non_got_ref = TRUE; -+ } -+ break; -+ -+ case R_PPC_EMB_NADDR32: -+ case R_PPC_EMB_NADDR16: -+ case R_PPC_EMB_NADDR16_LO: -+ case R_PPC_EMB_NADDR16_HI: -+ case R_PPC_EMB_NADDR16_HA: -+ if (info->shared) -+ { -+ bad_shared_reloc (abfd, r_type); -+ return FALSE; -+ } -+ if (h != NULL) -+ h->non_got_ref = TRUE; -+ break; -+ -+ case R_PPC_PLTREL24: -+ if (h == NULL) -+ break; -+ /* Fall through */ -+ case R_PPC_PLT32: -+ case R_PPC_PLTREL32: -+ case R_PPC_PLT16_LO: -+ case R_PPC_PLT16_HI: -+ case R_PPC_PLT16_HA: -+#ifdef DEBUG -+ fprintf (stderr, "Reloc requires a PLT entry\n"); -+#endif -+ /* This symbol requires a procedure linkage table entry. We -+ actually build the entry in finish_dynamic_symbol, -+ because this might be a case of linking PIC code without -+ linking in any dynamic objects, in which case we don't -+ need to generate a procedure linkage table after all. */ -+ -+ if (h == NULL) -+ { -+ /* It does not make sense to have a procedure linkage -+ table entry for a local symbol. */ -+ info->callbacks->einfo (_("%P: %H: %s reloc against local symbol\n"), -+ abfd, sec, rel->r_offset, -+ ppc_elf_howto_table[r_type]->name); -+ bfd_set_error (bfd_error_bad_value); -+ return FALSE; -+ } -+ else -+ { -+ bfd_vma addend = 0; -+ -+ if (r_type == R_PPC_PLTREL24) -+ { -+ ppc_elf_tdata (abfd)->makes_plt_call = 1; -+ if (info->shared) -+ addend = rel->r_addend; -+ } -+ h->needs_plt = 1; -+ if (!update_plt_info (abfd, &h->plt.plist, got2, addend)) -+ return FALSE; -+ } -+ break; -+ -+ /* The following relocations don't need to propagate the -+ relocation if linking a shared object since they are -+ section relative. */ -+ case R_PPC_SECTOFF: -+ case R_PPC_SECTOFF_LO: -+ case R_PPC_SECTOFF_HI: -+ case R_PPC_SECTOFF_HA: -+ case R_PPC_DTPREL16: -+ case R_PPC_DTPREL16_LO: -+ case R_PPC_DTPREL16_HI: -+ case R_PPC_DTPREL16_HA: -+ case R_PPC_TOC16: -+ break; -+ -+ case R_PPC_REL16: -+ case R_PPC_REL16_LO: -+ case R_PPC_REL16_HI: -+ case R_PPC_REL16_HA: -+ ppc_elf_tdata (abfd)->has_rel16 = 1; -+ break; -+ -+ /* These are just markers. */ -+ case R_PPC_TLS: -+ case R_PPC_EMB_MRKREF: -+ case R_PPC_NONE: -+ case R_PPC_max: -+ case R_PPC_RELAX: -+ case R_PPC_RELAX_PLT: -+ case R_PPC_RELAX_PLTREL24: -+ break; -+ -+ /* These should only appear in dynamic objects. */ -+ case R_PPC_COPY: -+ case R_PPC_GLOB_DAT: -+ case R_PPC_JMP_SLOT: -+ case R_PPC_RELATIVE: -+ case R_PPC_IRELATIVE: -+ break; -+ -+ /* These aren't handled yet. We'll report an error later. */ -+ case R_PPC_ADDR30: -+ case R_PPC_EMB_RELSEC16: -+ case R_PPC_EMB_RELST_LO: -+ case R_PPC_EMB_RELST_HI: -+ case R_PPC_EMB_RELST_HA: -+ case R_PPC_EMB_BIT_FLD: -+ break; -+ -+ /* These don't work with a GOT */ -+ case R_PPC_AMIGAOS_BREL: -+ case R_PPC_AMIGAOS_BREL_HI: -+ case R_PPC_AMIGAOS_BREL_LO: -+ case R_PPC_AMIGAOS_BREL_HA: -+ break; -+ -+ /* This refers only to functions defined in the shared library. */ -+ case R_PPC_LOCAL24PC: -+ if (h != NULL && h == htab->elf.hgot && htab->plt_type == PLT_UNSET) -+ { -+ htab->plt_type = PLT_OLD; -+ htab->old_bfd = abfd; -+ } -+ break; -+ -+ /* This relocation describes the C++ object vtable hierarchy. -+ Reconstruct it for later use during GC. */ -+ case R_PPC_GNU_VTINHERIT: -+ if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) -+ return FALSE; -+ break; -+ -+ /* This relocation describes which C++ vtable entries are actually -+ used. Record for later use during GC. */ -+ case R_PPC_GNU_VTENTRY: -+ BFD_ASSERT (h != NULL); -+ if (h != NULL -+ && !bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend)) -+ return FALSE; -+ break; -+ -+ /* We shouldn't really be seeing these. */ -+ case R_PPC_TPREL32: -+ case R_PPC_TPREL16: -+ case R_PPC_TPREL16_LO: -+ case R_PPC_TPREL16_HI: -+ case R_PPC_TPREL16_HA: -+ if (!info->executable) -+ info->flags |= DF_STATIC_TLS; -+ goto dodyn; -+ -+ /* Nor these. */ -+ case R_PPC_DTPMOD32: -+ case R_PPC_DTPREL32: -+ goto dodyn; -+ -+ case R_PPC_REL32: -+ if (h == NULL -+ && got2 != NULL -+ && (sec->flags & SEC_CODE) != 0 -+ && info->shared -+ && htab->plt_type == PLT_UNSET) -+ { -+ /* Old -fPIC gcc code has .long LCTOC1-LCFx just before -+ the start of a function, which assembles to a REL32 -+ reference to .got2. If we detect one of these, then -+ force the old PLT layout because the linker cannot -+ reliably deduce the GOT pointer value needed for -+ PLT call stubs. */ -+ asection *s; -+ Elf_Internal_Sym *isym; -+ -+ isym = bfd_sym_from_r_symndx (&htab->sym_cache, -+ abfd, r_symndx); -+ if (isym == NULL) -+ return FALSE; -+ -+ s = bfd_section_from_elf_index (abfd, isym->st_shndx); -+ if (s == got2) -+ { -+ htab->plt_type = PLT_OLD; -+ htab->old_bfd = abfd; -+ } -+ } -+ if (h == NULL || h == htab->elf.hgot) -+ break; -+ /* fall through */ -+ -+ case R_PPC_ADDR32: -+ case R_PPC_ADDR16: -+ case R_PPC_ADDR16_LO: -+ case R_PPC_ADDR16_HI: -+ case R_PPC_ADDR16_HA: -+ case R_PPC_UADDR32: -+ case R_PPC_UADDR16: -+ if (h != NULL && !info->shared) -+ { -+ /* We may need a plt entry if the symbol turns out to be -+ a function defined in a dynamic object. */ -+ if (!update_plt_info (abfd, &h->plt.plist, NULL, 0)) -+ return FALSE; -+ -+ /* We may need a copy reloc too. */ -+ h->non_got_ref = 1; -+ h->pointer_equality_needed = 1; -+ } -+ goto dodyn; -+ -+ case R_PPC_REL24: -+ case R_PPC_REL14: -+ case R_PPC_REL14_BRTAKEN: -+ case R_PPC_REL14_BRNTAKEN: -+ if (h == NULL) -+ break; -+ if (h == htab->elf.hgot) -+ { -+ if (htab->plt_type == PLT_UNSET) -+ { -+ htab->plt_type = PLT_OLD; -+ htab->old_bfd = abfd; -+ } -+ break; -+ } -+ /* fall through */ -+ -+ case R_PPC_ADDR24: -+ case R_PPC_ADDR14: -+ case R_PPC_ADDR14_BRTAKEN: -+ case R_PPC_ADDR14_BRNTAKEN: -+ if (h != NULL && !info->shared) -+ { -+ /* We may need a plt entry if the symbol turns out to be -+ a function defined in a dynamic object. */ -+ h->needs_plt = 1; -+ if (!update_plt_info (abfd, &h->plt.plist, NULL, 0)) -+ return FALSE; -+ break; -+ } -+ -+ dodyn: -+ /* If we are creating a shared library, and this is a reloc -+ against a global symbol, or a non PC relative reloc -+ against a local symbol, then we need to copy the reloc -+ into the shared library. However, if we are linking with -+ -Bsymbolic, we do not need to copy a reloc against a -+ global symbol which is defined in an object we are -+ including in the link (i.e., DEF_REGULAR is set). At -+ this point we have not seen all the input files, so it is -+ possible that DEF_REGULAR is not set now but will be set -+ later (it is never cleared). In case of a weak definition, -+ DEF_REGULAR may be cleared later by a strong definition in -+ a shared library. We account for that possibility below by -+ storing information in the dyn_relocs field of the hash -+ table entry. A similar situation occurs when creating -+ shared libraries and symbol visibility changes render the -+ symbol local. -+ -+ If on the other hand, we are creating an executable, we -+ may need to keep relocations for symbols satisfied by a -+ dynamic library if we manage to avoid copy relocs for the -+ symbol. */ -+ if ((info->shared -+ && (must_be_dyn_reloc (info, r_type) -+ || (h != NULL -+ && (! info->symbolic -+ || h->root.type == bfd_link_hash_defweak -+ || !h->def_regular)))) -+ || (ELIMINATE_COPY_RELOCS -+ && !info->shared -+ && h != NULL -+ && (h->root.type == bfd_link_hash_defweak -+ || !h->def_regular))) -+ { -+ struct elf_dyn_relocs *p; -+ struct elf_dyn_relocs **rel_head; -+ -+#ifdef DEBUG -+ fprintf (stderr, -+ "ppc_elf_check_relocs needs to " -+ "create relocation for %s\n", -+ (h && h->root.root.string -+ ? h->root.root.string : "")); -+#endif -+ if (sreloc == NULL) -+ { -+ if (htab->elf.dynobj == NULL) -+ htab->elf.dynobj = abfd; -+ -+ sreloc = _bfd_elf_make_dynamic_reloc_section -+ (sec, htab->elf.dynobj, 2, abfd, /*rela?*/ TRUE); -+ -+ if (sreloc == NULL) -+ return FALSE; -+ } -+ -+ /* If this is a global symbol, we count the number of -+ relocations we need for this symbol. */ -+ if (h != NULL) -+ { -+ rel_head = &ppc_elf_hash_entry (h)->dyn_relocs; -+ } -+ else -+ { -+ /* Track dynamic relocs needed for local syms too. -+ We really need local syms available to do this -+ easily. Oh well. */ -+ asection *s; -+ void *vpp; -+ Elf_Internal_Sym *isym; -+ -+ isym = bfd_sym_from_r_symndx (&htab->sym_cache, -+ abfd, r_symndx); -+ if (isym == NULL) -+ return FALSE; -+ -+ s = bfd_section_from_elf_index (abfd, isym->st_shndx); -+ if (s == NULL) -+ s = sec; -+ -+ vpp = &elf_section_data (s)->local_dynrel; -+ rel_head = (struct elf_dyn_relocs **) vpp; -+ } -+ -+ p = *rel_head; -+ if (p == NULL || p->sec != sec) -+ { -+ p = bfd_alloc (htab->elf.dynobj, sizeof *p); -+ if (p == NULL) -+ return FALSE; -+ p->next = *rel_head; -+ *rel_head = p; -+ p->sec = sec; -+ p->count = 0; -+ p->pc_count = 0; -+ } -+ -+ p->count += 1; -+ if (!must_be_dyn_reloc (info, r_type)) -+ p->pc_count += 1; -+ } -+ -+ break; -+ } -+ } -+ -+ return TRUE; -+} -+ -+ -+/* Merge object attributes from IBFD into OBFD. Raise an error if -+ there are conflicting attributes. */ -+static bfd_boolean -+ppc_elf_merge_obj_attributes (bfd *ibfd, bfd *obfd) -+{ -+ obj_attribute *in_attr, *in_attrs; -+ obj_attribute *out_attr, *out_attrs; -+ -+ if (!elf_known_obj_attributes_proc (obfd)[0].i) -+ { -+ /* This is the first object. Copy the attributes. */ -+ _bfd_elf_copy_obj_attributes (ibfd, obfd); -+ -+ /* Use the Tag_null value to indicate the attributes have been -+ initialized. */ -+ elf_known_obj_attributes_proc (obfd)[0].i = 1; -+ -+ return TRUE; -+ } -+ -+ in_attrs = elf_known_obj_attributes (ibfd)[OBJ_ATTR_GNU]; -+ out_attrs = elf_known_obj_attributes (obfd)[OBJ_ATTR_GNU]; -+ -+ /* Check for conflicting Tag_GNU_Power_ABI_FP attributes and merge -+ non-conflicting ones. */ -+ in_attr = &in_attrs[Tag_GNU_Power_ABI_FP]; -+ out_attr = &out_attrs[Tag_GNU_Power_ABI_FP]; -+ if (in_attr->i != out_attr->i) -+ { -+ out_attr->type = 1; -+ if (out_attr->i == 0) -+ out_attr->i = in_attr->i; -+ else if (in_attr->i == 0) -+ ; -+ else if (out_attr->i == 1 && in_attr->i == 2) -+ _bfd_error_handler -+ (_("Warning: %B uses hard float, %B uses soft float"), obfd, ibfd); -+ else if (out_attr->i == 1 && in_attr->i == 3) -+ _bfd_error_handler -+ (_("Warning: %B uses double-precision hard float, %B uses single-precision hard float"), -+ obfd, ibfd); -+ else if (out_attr->i == 3 && in_attr->i == 1) -+ _bfd_error_handler -+ (_("Warning: %B uses double-precision hard float, %B uses single-precision hard float"), -+ ibfd, obfd); -+ else if (out_attr->i == 3 && in_attr->i == 2) -+ _bfd_error_handler -+ (_("Warning: %B uses soft float, %B uses single-precision hard float"), -+ ibfd, obfd); -+ else if (out_attr->i == 2 && (in_attr->i == 1 || in_attr->i == 3)) -+ _bfd_error_handler -+ (_("Warning: %B uses hard float, %B uses soft float"), ibfd, obfd); -+ else if (in_attr->i > 3) -+ _bfd_error_handler -+ (_("Warning: %B uses unknown floating point ABI %d"), ibfd, -+ in_attr->i); -+ else -+ _bfd_error_handler -+ (_("Warning: %B uses unknown floating point ABI %d"), obfd, -+ out_attr->i); -+ } -+ -+ /* Check for conflicting Tag_GNU_Power_ABI_Vector attributes and -+ merge non-conflicting ones. */ -+ in_attr = &in_attrs[Tag_GNU_Power_ABI_Vector]; -+ out_attr = &out_attrs[Tag_GNU_Power_ABI_Vector]; -+ if (in_attr->i != out_attr->i) -+ { -+ const char *in_abi = NULL, *out_abi = NULL; -+ -+ switch (in_attr->i) -+ { -+ case 1: in_abi = "generic"; break; -+ case 2: in_abi = "AltiVec"; break; -+ case 3: in_abi = "SPE"; break; -+ } -+ -+ switch (out_attr->i) -+ { -+ case 1: out_abi = "generic"; break; -+ case 2: out_abi = "AltiVec"; break; -+ case 3: out_abi = "SPE"; break; -+ } -+ -+ out_attr->type = 1; -+ if (out_attr->i == 0) -+ out_attr->i = in_attr->i; -+ else if (in_attr->i == 0) -+ ; -+ /* For now, allow generic to transition to AltiVec or SPE -+ without a warning. If GCC marked files with their stack -+ alignment and used don't-care markings for files which are -+ not affected by the vector ABI, we could warn about this -+ case too. */ -+ else if (out_attr->i == 1) -+ out_attr->i = in_attr->i; -+ else if (in_attr->i == 1) -+ ; -+ else if (in_abi == NULL) -+ _bfd_error_handler -+ (_("Warning: %B uses unknown vector ABI %d"), ibfd, -+ in_attr->i); -+ else if (out_abi == NULL) -+ _bfd_error_handler -+ (_("Warning: %B uses unknown vector ABI %d"), obfd, -+ in_attr->i); -+ else -+ _bfd_error_handler -+ (_("Warning: %B uses vector ABI \"%s\", %B uses \"%s\""), -+ ibfd, obfd, in_abi, out_abi); -+ } -+ -+ /* Check for conflicting Tag_GNU_Power_ABI_Struct_Return attributes -+ and merge non-conflicting ones. */ -+ in_attr = &in_attrs[Tag_GNU_Power_ABI_Struct_Return]; -+ out_attr = &out_attrs[Tag_GNU_Power_ABI_Struct_Return]; -+ if (in_attr->i != out_attr->i) -+ { -+ out_attr->type = 1; -+ if (out_attr->i == 0) -+ out_attr->i = in_attr->i; -+ else if (in_attr->i == 0) -+ ; -+ else if (out_attr->i == 1 && in_attr->i == 2) -+ _bfd_error_handler -+ (_("Warning: %B uses r3/r4 for small structure returns, %B uses memory"), obfd, ibfd); -+ else if (out_attr->i == 2 && in_attr->i == 1) -+ _bfd_error_handler -+ (_("Warning: %B uses r3/r4 for small structure returns, %B uses memory"), ibfd, obfd); -+ else if (in_attr->i > 2) -+ _bfd_error_handler -+ (_("Warning: %B uses unknown small structure return convention %d"), ibfd, -+ in_attr->i); -+ else -+ _bfd_error_handler -+ (_("Warning: %B uses unknown small structure return convention %d"), obfd, -+ out_attr->i); -+ } -+ -+ /* Merge Tag_compatibility attributes and any common GNU ones. */ -+ _bfd_elf_merge_object_attributes (ibfd, obfd); -+ -+ return TRUE; -+} -+ -+/* Merge backend specific data from an object file to the output -+ object file when linking. */ -+ -+static bfd_boolean -+ppc_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd) -+{ -+ flagword old_flags; -+ flagword new_flags; -+ bfd_boolean error; -+ -+ if (!is_ppc_elf (ibfd) || !is_ppc_elf (obfd)) -+ return TRUE; -+ -+ /* Check if we have the same endianness. */ -+ if (! _bfd_generic_verify_endian_match (ibfd, obfd)) -+ return FALSE; -+ -+ if (!ppc_elf_merge_obj_attributes (ibfd, obfd)) -+ return FALSE; -+ -+ new_flags = elf_elfheader (ibfd)->e_flags; -+ old_flags = elf_elfheader (obfd)->e_flags; -+ if (!elf_flags_init (obfd)) -+ { -+ /* First call, no flags set. */ -+ elf_flags_init (obfd) = TRUE; -+ elf_elfheader (obfd)->e_flags = new_flags; -+ } -+ -+ /* Compatible flags are ok. */ -+ else if (new_flags == old_flags) -+ ; -+ -+ /* Incompatible flags. */ -+ else -+ { -+ /* Warn about -mrelocatable mismatch. Allow -mrelocatable-lib -+ to be linked with either. */ -+ error = FALSE; -+ if ((new_flags & EF_PPC_RELOCATABLE) != 0 -+ && (old_flags & (EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB)) == 0) -+ { -+ error = TRUE; -+ (*_bfd_error_handler) -+ (_("%B: compiled with -mrelocatable and linked with " -+ "modules compiled normally"), ibfd); -+ } -+ else if ((new_flags & (EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB)) == 0 -+ && (old_flags & EF_PPC_RELOCATABLE) != 0) -+ { -+ error = TRUE; -+ (*_bfd_error_handler) -+ (_("%B: compiled normally and linked with " -+ "modules compiled with -mrelocatable"), ibfd); -+ } -+ -+ /* The output is -mrelocatable-lib iff both the input files are. */ -+ if (! (new_flags & EF_PPC_RELOCATABLE_LIB)) -+ elf_elfheader (obfd)->e_flags &= ~EF_PPC_RELOCATABLE_LIB; -+ -+ /* The output is -mrelocatable iff it can't be -mrelocatable-lib, -+ but each input file is either -mrelocatable or -mrelocatable-lib. */ -+ if (! (elf_elfheader (obfd)->e_flags & EF_PPC_RELOCATABLE_LIB) -+ && (new_flags & (EF_PPC_RELOCATABLE_LIB | EF_PPC_RELOCATABLE)) -+ && (old_flags & (EF_PPC_RELOCATABLE_LIB | EF_PPC_RELOCATABLE))) -+ elf_elfheader (obfd)->e_flags |= EF_PPC_RELOCATABLE; -+ -+ /* Do not warn about eabi vs. V.4 mismatch, just or in the bit if -+ any module uses it. */ -+ elf_elfheader (obfd)->e_flags |= (new_flags & EF_PPC_EMB); -+ -+ new_flags &= ~(EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB | EF_PPC_EMB); -+ old_flags &= ~(EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB | EF_PPC_EMB); -+ -+ /* Warn about any other mismatches. */ -+ if (new_flags != old_flags) -+ { -+ error = TRUE; -+ (*_bfd_error_handler) -+ (_("%B: uses different e_flags (0x%lx) fields " -+ "than previous modules (0x%lx)"), -+ ibfd, (long) new_flags, (long) old_flags); -+ } -+ -+ if (error) -+ { -+ bfd_set_error (bfd_error_bad_value); -+ return FALSE; -+ } -+ } -+ -+ return TRUE; -+} -+ -+static void -+ppc_elf_vle_split16 (bfd *output_bfd, bfd_byte *contents, -+ bfd_vma offset, bfd_vma relocation, -+ split16_format_type split16_format) -+ -+{ -+ bfd_vma insn, top5, bottom11; -+ -+ insn = bfd_get_32 (output_bfd, contents + offset); -+ top5 = relocation >> 11; -+ top5 = top5 << (split16_format == split16a_type ? 20 : 16); -+ bottom11 = relocation & 0x7ff; -+ insn |= top5; -+ insn |= bottom11; -+ bfd_put_32 (output_bfd, insn, contents + offset); -+} -+ -+ -+/* Choose which PLT scheme to use, and set .plt flags appropriately. -+ Returns -1 on error, 0 for old PLT, 1 for new PLT. */ -+int -+ppc_elf_amigaos_select_plt_layout (bfd *output_bfd ATTRIBUTE_UNUSED, -+ struct bfd_link_info *info, -+ enum ppc_elf_plt_type plt_style, -+ int emit_stub_syms) -+{ -+ struct ppc_elf_link_hash_table *htab; -+ flagword flags; -+ -+ htab = ppc_elf_hash_table (info); -+ -+ htab->emit_stub_syms = emit_stub_syms; -+ -+ if (htab->plt_type == PLT_UNSET) -+ { -+ struct elf_link_hash_entry *h; -+ -+ if (plt_style == PLT_OLD) -+ htab->plt_type = PLT_OLD; -+ else if (info->shared -+ && htab->elf.dynamic_sections_created -+ && (h = elf_link_hash_lookup (&htab->elf, "_mcount", -+ FALSE, FALSE, TRUE)) != NULL -+ && (h->type == STT_FUNC -+ || h->needs_plt) -+ && h->ref_regular -+ && !(SYMBOL_CALLS_LOCAL (info, h) -+ || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT -+ && h->root.type == bfd_link_hash_undefweak))) -+ { -+ /* Profiling of shared libs (and pies) is not supported with -+ secure plt, because ppc32 does profiling before a -+ function prologue and a secure plt pic call stubs needs -+ r30 to be set up. */ -+ htab->plt_type = PLT_OLD; -+ } -+ else -+ { -+ bfd *ibfd; -+ enum ppc_elf_plt_type plt_type = plt_style; -+ -+ /* Look through the reloc flags left by ppc_elf_check_relocs. -+ Use the old style bss plt if a file makes plt calls -+ without using the new relocs, and if ld isn't given -+ --secure-plt and we never see REL16 relocs. */ -+ if (plt_type == PLT_UNSET) -+ plt_type = PLT_OLD; -+ for (ibfd = info->input_bfds; ibfd; ibfd = ibfd->link_next) -+ if (is_ppc_elf (ibfd)) -+ { -+ if (ppc_elf_tdata (ibfd)->has_rel16) -+ plt_type = PLT_NEW; -+ else if (ppc_elf_tdata (ibfd)->makes_plt_call) -+ { -+ plt_type = PLT_OLD; -+ htab->old_bfd = ibfd; -+ break; -+ } -+ } -+ htab->plt_type = plt_type; -+ } -+ } -+ if (htab->plt_type == PLT_OLD && plt_style == PLT_NEW) -+ { -+ if (htab->old_bfd != NULL) -+ info->callbacks->einfo (_("%P: bss-plt forced due to %B\n"), -+ htab->old_bfd); -+ else -+ info->callbacks->einfo (_("%P: bss-plt forced by profiling\n")); -+ } -+ -+ BFD_ASSERT (htab->plt_type != PLT_VXWORKS); -+ -+ if (htab->plt_type == PLT_NEW) -+ { -+ flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS -+ | SEC_IN_MEMORY | SEC_LINKER_CREATED); -+ -+ /* The new PLT is a loaded section. */ -+ if (htab->plt != NULL -+ && !bfd_set_section_flags (htab->elf.dynobj, htab->plt, flags)) -+ return -1; -+ -+ /* The new GOT is not executable. */ -+ if (htab->got != NULL -+ && !bfd_set_section_flags (htab->elf.dynobj, htab->got, flags)) -+ return -1; -+ } -+ else -+ { -+ /* Stop an unused .glink section from affecting .text alignment. */ -+ if (htab->glink != NULL -+ && !bfd_set_section_alignment (htab->elf.dynobj, htab->glink, 0)) -+ return -1; -+ } -+ return htab->plt_type == PLT_NEW; -+} -+ -+/* Return the section that should be marked against GC for a given -+ relocation. */ -+ -+static asection * -+ppc_elf_gc_mark_hook (asection *sec, -+ struct bfd_link_info *info, -+ Elf_Internal_Rela *rel, -+ struct elf_link_hash_entry *h, -+ Elf_Internal_Sym *sym) -+{ -+ if (h != NULL) -+ switch (ELF32_R_TYPE (rel->r_info)) -+ { -+ case R_PPC_GNU_VTINHERIT: -+ case R_PPC_GNU_VTENTRY: -+ return NULL; -+ } -+ -+ return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym); -+} -+ -+/* Update the got, plt and dynamic reloc reference counts for the -+ section being removed. */ -+ -+static bfd_boolean -+ppc_elf_gc_sweep_hook (bfd *abfd, -+ struct bfd_link_info *info, -+ asection *sec, -+ const Elf_Internal_Rela *relocs) -+{ -+ struct ppc_elf_link_hash_table *htab; -+ Elf_Internal_Shdr *symtab_hdr; -+ struct elf_link_hash_entry **sym_hashes; -+ bfd_signed_vma *local_got_refcounts; -+ const Elf_Internal_Rela *rel, *relend; -+ asection *got2; -+ -+ if (info->relocatable) -+ return TRUE; -+ -+ if ((sec->flags & SEC_ALLOC) == 0) -+ return TRUE; -+ -+ elf_section_data (sec)->local_dynrel = NULL; -+ -+ htab = ppc_elf_hash_table (info); -+ symtab_hdr = &elf_symtab_hdr (abfd); -+ sym_hashes = elf_sym_hashes (abfd); -+ local_got_refcounts = elf_local_got_refcounts (abfd); -+ got2 = bfd_get_section_by_name (abfd, ".got2"); -+ -+ relend = relocs + sec->reloc_count; -+ for (rel = relocs; rel < relend; rel++) -+ { -+ unsigned long r_symndx; -+ enum elf_ppc_reloc_type r_type; -+ struct elf_link_hash_entry *h = NULL; -+ -+ r_symndx = ELF32_R_SYM (rel->r_info); -+ if (r_symndx >= symtab_hdr->sh_info) -+ { -+ struct elf_dyn_relocs **pp, *p; -+ struct ppc_elf_link_hash_entry *eh; -+ -+ h = sym_hashes[r_symndx - symtab_hdr->sh_info]; -+ while (h->root.type == bfd_link_hash_indirect -+ || h->root.type == bfd_link_hash_warning) -+ h = (struct elf_link_hash_entry *) h->root.u.i.link; -+ eh = (struct ppc_elf_link_hash_entry *) h; -+ -+ for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next) -+ if (p->sec == sec) -+ { -+ /* Everything must go for SEC. */ -+ *pp = p->next; -+ break; -+ } -+ } -+ -+ r_type = ELF32_R_TYPE (rel->r_info); -+ if (!htab->is_vxworks -+ && h == NULL -+ && local_got_refcounts != NULL -+ && (!info->shared -+ || is_branch_reloc (r_type))) -+ { -+ struct plt_entry **local_plt = (struct plt_entry **) -+ (local_got_refcounts + symtab_hdr->sh_info); -+ char *local_got_tls_masks = (char *) -+ (local_plt + symtab_hdr->sh_info); -+ if ((local_got_tls_masks[r_symndx] & PLT_IFUNC) != 0) -+ { -+ struct plt_entry **ifunc = local_plt + r_symndx; -+ bfd_vma addend = 0; -+ struct plt_entry *ent; -+ -+ if (r_type == R_PPC_PLTREL24 && info->shared) -+ addend = rel->r_addend; -+ ent = find_plt_ent (ifunc, got2, addend); -+ if (ent->plt.refcount > 0) -+ ent->plt.refcount -= 1; -+ continue; -+ } -+ } -+ -+ switch (r_type) -+ { -+ case R_PPC_GOT_TLSLD16: -+ case R_PPC_GOT_TLSLD16_LO: -+ case R_PPC_GOT_TLSLD16_HI: -+ case R_PPC_GOT_TLSLD16_HA: -+ case R_PPC_GOT_TLSGD16: -+ case R_PPC_GOT_TLSGD16_LO: -+ case R_PPC_GOT_TLSGD16_HI: -+ case R_PPC_GOT_TLSGD16_HA: -+ case R_PPC_GOT_TPREL16: -+ case R_PPC_GOT_TPREL16_LO: -+ case R_PPC_GOT_TPREL16_HI: -+ case R_PPC_GOT_TPREL16_HA: -+ case R_PPC_GOT_DTPREL16: -+ case R_PPC_GOT_DTPREL16_LO: -+ case R_PPC_GOT_DTPREL16_HI: -+ case R_PPC_GOT_DTPREL16_HA: -+ case R_PPC_GOT16: -+ case R_PPC_GOT16_LO: -+ case R_PPC_GOT16_HI: -+ case R_PPC_GOT16_HA: -+ if (h != NULL) -+ { -+ if (h->got.refcount > 0) -+ h->got.refcount--; -+ if (!info->shared) -+ { -+ struct plt_entry *ent; -+ -+ ent = find_plt_ent (&h->plt.plist, NULL, 0); -+ if (ent != NULL && ent->plt.refcount > 0) -+ ent->plt.refcount -= 1; -+ } -+ } -+ else if (local_got_refcounts != NULL) -+ { -+ if (local_got_refcounts[r_symndx] > 0) -+ local_got_refcounts[r_symndx]--; -+ } -+ break; -+ -+ case R_PPC_REL24: -+ case R_PPC_REL14: -+ case R_PPC_REL14_BRTAKEN: -+ case R_PPC_REL14_BRNTAKEN: -+ case R_PPC_REL32: -+ if (h == NULL || h == htab->elf.hgot) -+ break; -+ /* Fall thru */ -+ -+ case R_PPC_ADDR32: -+ case R_PPC_ADDR24: -+ case R_PPC_ADDR16: -+ case R_PPC_ADDR16_LO: -+ case R_PPC_ADDR16_HI: -+ case R_PPC_ADDR16_HA: -+ case R_PPC_ADDR14: -+ case R_PPC_ADDR14_BRTAKEN: -+ case R_PPC_ADDR14_BRNTAKEN: -+ case R_PPC_UADDR32: -+ case R_PPC_UADDR16: -+ if (info->shared) -+ break; -+ -+ case R_PPC_PLT32: -+ case R_PPC_PLTREL24: -+ case R_PPC_PLTREL32: -+ case R_PPC_PLT16_LO: -+ case R_PPC_PLT16_HI: -+ case R_PPC_PLT16_HA: -+ if (h != NULL) -+ { -+ bfd_vma addend = 0; -+ struct plt_entry *ent; -+ -+ if (r_type == R_PPC_PLTREL24 && info->shared) -+ addend = rel->r_addend; -+ ent = find_plt_ent (&h->plt.plist, got2, addend); -+ if (ent != NULL && ent->plt.refcount > 0) -+ ent->plt.refcount -= 1; -+ } -+ break; -+ -+ default: -+ break; -+ } -+ } -+ return TRUE; -+} -+ -+/* Set plt output section type, htab->tls_get_addr, and call the -+ generic ELF tls_setup function. */ -+ -+asection * -+ppc_elf_amigaos_tls_setup (bfd *obfd, -+ struct bfd_link_info *info, -+ int no_tls_get_addr_opt) -+{ -+ struct ppc_elf_link_hash_table *htab; -+ -+ htab = ppc_elf_hash_table (info); -+ htab->tls_get_addr = elf_link_hash_lookup (&htab->elf, "__tls_get_addr", -+ FALSE, FALSE, TRUE); -+ if (!no_tls_get_addr_opt) -+ { -+ struct elf_link_hash_entry *opt, *tga; -+ opt = elf_link_hash_lookup (&htab->elf, "__tls_get_addr_opt", -+ FALSE, FALSE, TRUE); -+ if (opt != NULL -+ && (opt->root.type == bfd_link_hash_defined -+ || opt->root.type == bfd_link_hash_defweak)) -+ { -+ /* If glibc supports an optimized __tls_get_addr call stub, -+ signalled by the presence of __tls_get_addr_opt, and we'll -+ be calling __tls_get_addr via a plt call stub, then -+ make __tls_get_addr point to __tls_get_addr_opt. */ -+ tga = htab->tls_get_addr; -+ if (htab->elf.dynamic_sections_created -+ && tga != NULL -+ && (tga->type == STT_FUNC -+ || tga->needs_plt) -+ && !(SYMBOL_CALLS_LOCAL (info, tga) -+ || (ELF_ST_VISIBILITY (tga->other) != STV_DEFAULT -+ && tga->root.type == bfd_link_hash_undefweak))) -+ { -+ struct plt_entry *ent; -+ for (ent = tga->plt.plist; ent != NULL; ent = ent->next) -+ if (ent->plt.refcount > 0) -+ break; -+ if (ent != NULL) -+ { -+ tga->root.type = bfd_link_hash_indirect; -+ tga->root.u.i.link = &opt->root; -+ ppc_elf_copy_indirect_symbol (info, opt, tga); -+ if (opt->dynindx != -1) -+ { -+ /* Use __tls_get_addr_opt in dynamic relocations. */ -+ opt->dynindx = -1; -+ _bfd_elf_strtab_delref (elf_hash_table (info)->dynstr, -+ opt->dynstr_index); -+ if (!bfd_elf_link_record_dynamic_symbol (info, opt)) -+ return FALSE; -+ } -+ htab->tls_get_addr = opt; -+ } -+ } -+ } -+ else -+ no_tls_get_addr_opt = TRUE; -+ } -+ htab->no_tls_get_addr_opt = no_tls_get_addr_opt; -+ if (htab->plt_type == PLT_NEW -+ && htab->plt != NULL -+ && htab->plt->output_section != NULL) -+ { -+ elf_section_type (htab->plt->output_section) = SHT_PROGBITS; -+ elf_section_flags (htab->plt->output_section) = SHF_ALLOC + SHF_WRITE; -+ } -+ -+ return _bfd_elf_tls_setup (obfd, info); -+} -+ -+/* Return TRUE iff REL is a branch reloc with a global symbol matching -+ HASH. */ -+ -+static bfd_boolean -+branch_reloc_hash_match (const bfd *ibfd, -+ const Elf_Internal_Rela *rel, -+ const struct elf_link_hash_entry *hash) -+{ -+ Elf_Internal_Shdr *symtab_hdr = &elf_symtab_hdr (ibfd); -+ enum elf_ppc_reloc_type r_type = ELF32_R_TYPE (rel->r_info); -+ unsigned int r_symndx = ELF32_R_SYM (rel->r_info); -+ -+ if (r_symndx >= symtab_hdr->sh_info && is_branch_reloc (r_type)) -+ { -+ struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (ibfd); -+ struct elf_link_hash_entry *h; -+ -+ h = sym_hashes[r_symndx - symtab_hdr->sh_info]; -+ while (h->root.type == bfd_link_hash_indirect -+ || h->root.type == bfd_link_hash_warning) -+ h = (struct elf_link_hash_entry *) h->root.u.i.link; -+ if (h == hash) -+ return TRUE; -+ } -+ return FALSE; -+} -+ -+/* Run through all the TLS relocs looking for optimization -+ opportunities. */ -+ -+bfd_boolean -+ppc_elf_amigaos_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, -+ struct bfd_link_info *info) -+{ -+ bfd *ibfd; -+ asection *sec; -+ struct ppc_elf_link_hash_table *htab; -+ int pass; -+ -+ if (info->relocatable || !info->executable) -+ return TRUE; -+ -+ htab = ppc_elf_hash_table (info); -+ if (htab == NULL) -+ return FALSE; -+ -+ /* Make two passes through the relocs. First time check that tls -+ relocs involved in setting up a tls_get_addr call are indeed -+ followed by such a call. If they are not, don't do any tls -+ optimization. On the second pass twiddle tls_mask flags to -+ notify relocate_section that optimization can be done, and -+ adjust got and plt refcounts. */ -+ for (pass = 0; pass < 2; ++pass) -+ for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) -+ { -+ Elf_Internal_Sym *locsyms = NULL; -+ Elf_Internal_Shdr *symtab_hdr = &elf_symtab_hdr (ibfd); -+ asection *got2 = bfd_get_section_by_name (ibfd, ".got2"); -+ -+ for (sec = ibfd->sections; sec != NULL; sec = sec->next) -+ if (sec->has_tls_reloc && !bfd_is_abs_section (sec->output_section)) -+ { -+ Elf_Internal_Rela *relstart, *rel, *relend; -+ int expecting_tls_get_addr = 0; -+ -+ /* Read the relocations. */ -+ relstart = _bfd_elf_link_read_relocs (ibfd, sec, NULL, NULL, -+ info->keep_memory); -+ if (relstart == NULL) -+ return FALSE; -+ -+ relend = relstart + sec->reloc_count; -+ for (rel = relstart; rel < relend; rel++) -+ { -+ enum elf_ppc_reloc_type r_type; -+ unsigned long r_symndx; -+ struct elf_link_hash_entry *h = NULL; -+ char *tls_mask; -+ char tls_set, tls_clear; -+ bfd_boolean is_local; -+ bfd_signed_vma *got_count; -+ -+ r_symndx = ELF32_R_SYM (rel->r_info); -+ if (r_symndx >= symtab_hdr->sh_info) -+ { -+ struct elf_link_hash_entry **sym_hashes; -+ -+ sym_hashes = elf_sym_hashes (ibfd); -+ h = sym_hashes[r_symndx - symtab_hdr->sh_info]; -+ while (h->root.type == bfd_link_hash_indirect -+ || h->root.type == bfd_link_hash_warning) -+ h = (struct elf_link_hash_entry *) h->root.u.i.link; -+ } -+ -+ is_local = FALSE; -+ if (h == NULL -+ || !h->def_dynamic) -+ is_local = TRUE; -+ -+ r_type = ELF32_R_TYPE (rel->r_info); -+ /* If this section has old-style __tls_get_addr calls -+ without marker relocs, then check that each -+ __tls_get_addr call reloc is preceded by a reloc -+ that conceivably belongs to the __tls_get_addr arg -+ setup insn. If we don't find matching arg setup -+ relocs, don't do any tls optimization. */ -+ if (pass == 0 -+ && sec->has_tls_get_addr_call -+ && h != NULL -+ && h == htab->tls_get_addr -+ && !expecting_tls_get_addr -+ && is_branch_reloc (r_type)) -+ { -+ info->callbacks->minfo ("%H __tls_get_addr lost arg, " -+ "TLS optimization disabled\n", -+ ibfd, sec, rel->r_offset); -+ if (elf_section_data (sec)->relocs != relstart) -+ free (relstart); -+ return TRUE; -+ } -+ -+ expecting_tls_get_addr = 0; -+ switch (r_type) -+ { -+ case R_PPC_GOT_TLSLD16: -+ case R_PPC_GOT_TLSLD16_LO: -+ expecting_tls_get_addr = 1; -+ /* Fall thru */ -+ -+ case R_PPC_GOT_TLSLD16_HI: -+ case R_PPC_GOT_TLSLD16_HA: -+ /* These relocs should never be against a symbol -+ defined in a shared lib. Leave them alone if -+ that turns out to be the case. */ -+ if (!is_local) -+ continue; -+ -+ /* LD -> LE */ -+ tls_set = 0; -+ tls_clear = TLS_LD; -+ break; -+ -+ case R_PPC_GOT_TLSGD16: -+ case R_PPC_GOT_TLSGD16_LO: -+ expecting_tls_get_addr = 1; -+ /* Fall thru */ -+ -+ case R_PPC_GOT_TLSGD16_HI: -+ case R_PPC_GOT_TLSGD16_HA: -+ if (is_local) -+ /* GD -> LE */ -+ tls_set = 0; -+ else -+ /* GD -> IE */ -+ tls_set = TLS_TLS | TLS_TPRELGD; -+ tls_clear = TLS_GD; -+ break; -+ -+ case R_PPC_GOT_TPREL16: -+ case R_PPC_GOT_TPREL16_LO: -+ case R_PPC_GOT_TPREL16_HI: -+ case R_PPC_GOT_TPREL16_HA: -+ if (is_local) -+ { -+ /* IE -> LE */ -+ tls_set = 0; -+ tls_clear = TLS_TPREL; -+ break; -+ } -+ else -+ continue; -+ -+ case R_PPC_TLSGD: -+ case R_PPC_TLSLD: -+ expecting_tls_get_addr = 2; -+ tls_set = 0; -+ tls_clear = 0; -+ break; -+ -+ default: -+ continue; -+ } -+ -+ if (pass == 0) -+ { -+ if (!expecting_tls_get_addr -+ || (expecting_tls_get_addr == 1 -+ && !sec->has_tls_get_addr_call)) -+ continue; -+ -+ if (rel + 1 < relend -+ && branch_reloc_hash_match (ibfd, rel + 1, -+ htab->tls_get_addr)) -+ continue; -+ -+ /* Uh oh, we didn't find the expected call. We -+ could just mark this symbol to exclude it -+ from tls optimization but it's safer to skip -+ the entire optimization. */ -+ info->callbacks->minfo (_("%H arg lost __tls_get_addr, " -+ "TLS optimization disabled\n"), -+ ibfd, sec, rel->r_offset); -+ if (elf_section_data (sec)->relocs != relstart) -+ free (relstart); -+ return TRUE; -+ } -+ -+ if (expecting_tls_get_addr) -+ { -+ struct plt_entry *ent; -+ bfd_vma addend = 0; -+ -+ if (info->shared -+ && ELF32_R_TYPE (rel[1].r_info) == R_PPC_PLTREL24) -+ addend = rel[1].r_addend; -+ ent = find_plt_ent (&htab->tls_get_addr->plt.plist, -+ got2, addend); -+ if (ent != NULL && ent->plt.refcount > 0) -+ ent->plt.refcount -= 1; -+ -+ if (expecting_tls_get_addr == 2) -+ continue; -+ } -+ -+ if (h != NULL) -+ { -+ tls_mask = &ppc_elf_hash_entry (h)->tls_mask; -+ got_count = &h->got.refcount; -+ } -+ else -+ { -+ bfd_signed_vma *lgot_refs; -+ struct plt_entry **local_plt; -+ char *lgot_masks; -+ -+ if (locsyms == NULL) -+ { -+ locsyms = (Elf_Internal_Sym *) symtab_hdr->contents; -+ if (locsyms == NULL) -+ locsyms = bfd_elf_get_elf_syms (ibfd, symtab_hdr, -+ symtab_hdr->sh_info, -+ 0, NULL, NULL, NULL); -+ if (locsyms == NULL) -+ { -+ if (elf_section_data (sec)->relocs != relstart) -+ free (relstart); -+ return FALSE; -+ } -+ } -+ lgot_refs = elf_local_got_refcounts (ibfd); -+ if (lgot_refs == NULL) -+ abort (); -+ local_plt = (struct plt_entry **) -+ (lgot_refs + symtab_hdr->sh_info); -+ lgot_masks = (char *) (local_plt + symtab_hdr->sh_info); -+ tls_mask = &lgot_masks[r_symndx]; -+ got_count = &lgot_refs[r_symndx]; -+ } -+ -+ if (tls_set == 0) -+ { -+ /* We managed to get rid of a got entry. */ -+ if (*got_count > 0) -+ *got_count -= 1; -+ } -+ -+ *tls_mask |= tls_set; -+ *tls_mask &= ~tls_clear; -+ } -+ -+ if (elf_section_data (sec)->relocs != relstart) -+ free (relstart); -+ } -+ -+ if (locsyms != NULL -+ && (symtab_hdr->contents != (unsigned char *) locsyms)) -+ { -+ if (!info->keep_memory) -+ free (locsyms); -+ else -+ symtab_hdr->contents = (unsigned char *) locsyms; -+ } -+ } -+ return TRUE; -+} -+ -+/* Return true if we have dynamic relocs that apply to read-only sections. */ -+ -+static bfd_boolean -+readonly_dynrelocs (struct elf_link_hash_entry *h) -+{ -+ struct elf_dyn_relocs *p; -+ -+ for (p = ppc_elf_hash_entry (h)->dyn_relocs; p != NULL; p = p->next) -+ { -+ asection *s = p->sec->output_section; -+ -+ if (s != NULL -+ && ((s->flags & (SEC_READONLY | SEC_ALLOC)) -+ == (SEC_READONLY | SEC_ALLOC))) -+ return TRUE; -+ } -+ return FALSE; -+} -+ -+/* Adjust a symbol defined by a dynamic object and referenced by a -+ regular object. The current definition is in some section of the -+ dynamic object, but we're not including those sections. We have to -+ change the definition to something the rest of the link can -+ understand. */ -+ -+static bfd_boolean -+ppc_elf_adjust_dynamic_symbol (struct bfd_link_info *info, -+ struct elf_link_hash_entry *h) -+{ -+ struct ppc_elf_link_hash_table *htab; -+ asection *s; -+ -+#ifdef DEBUG -+ fprintf (stderr, "ppc_elf_adjust_dynamic_symbol called for %s\n", -+ h->root.root.string); -+#endif -+ -+ /* Make sure we know what is going on here. */ -+ htab = ppc_elf_hash_table (info); -+ BFD_ASSERT (htab->elf.dynobj != NULL -+ && (h->needs_plt -+ || h->type == STT_GNU_IFUNC -+ || h->u.weakdef != NULL -+ || (h->def_dynamic -+ && h->ref_regular -+ && !h->def_regular))); -+ -+ /* Deal with function syms. */ -+ if (h->type == STT_FUNC -+ || h->type == STT_GNU_IFUNC -+ || h->needs_plt) -+ { -+ /* Clear procedure linkage table information for any symbol that -+ won't need a .plt entry. */ -+ struct plt_entry *ent; -+ for (ent = h->plt.plist; ent != NULL; ent = ent->next) -+ if (ent->plt.refcount > 0) -+ break; -+ if (ent == NULL -+ || (h->type != STT_GNU_IFUNC -+ && (SYMBOL_CALLS_LOCAL (info, h) -+ || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT -+ && h->root.type == bfd_link_hash_undefweak)))) -+ { -+ /* A PLT entry is not required/allowed when: -+ -+ 1. We are not using ld.so; because then the PLT entry -+ can't be set up, so we can't use one. In this case, -+ ppc_elf_adjust_dynamic_symbol won't even be called. -+ -+ 2. GC has rendered the entry unused. -+ -+ 3. We know for certain that a call to this symbol -+ will go to this object, or will remain undefined. */ -+ h->plt.plist = NULL; -+ h->needs_plt = 0; -+ } -+ else -+ { -+ /* After adjust_dynamic_symbol, non_got_ref set in the -+ non-shared case means that we have allocated space in -+ .dynbss for the symbol and thus dyn_relocs for this -+ symbol should be discarded. -+ If we get here we know we are making a PLT entry for this -+ symbol, and in an executable we'd normally resolve -+ relocations against this symbol to the PLT entry. Allow -+ dynamic relocs if the reference is weak, and the dynamic -+ relocs will not cause text relocation. */ -+ if (!h->ref_regular_nonweak -+ && h->non_got_ref -+ && h->type != STT_GNU_IFUNC -+ && !htab->is_vxworks -+ && !ppc_elf_hash_entry (h)->has_sda_refs -+ && !readonly_dynrelocs (h)) -+ h->non_got_ref = 0; -+ } -+ return TRUE; -+ } -+ else -+ h->plt.plist = NULL; -+ -+ /* If this is a weak symbol, and there is a real definition, the -+ processor independent code will have arranged for us to see the -+ real definition first, and we can just use the same value. */ -+ if (h->u.weakdef != NULL) -+ { -+ BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined -+ || h->u.weakdef->root.type == bfd_link_hash_defweak); -+ h->root.u.def.section = h->u.weakdef->root.u.def.section; -+ h->root.u.def.value = h->u.weakdef->root.u.def.value; -+ if (ELIMINATE_COPY_RELOCS) -+ h->non_got_ref = h->u.weakdef->non_got_ref; -+ return TRUE; -+ } -+ -+ /* This is a reference to a symbol defined by a dynamic object which -+ is not a function. */ -+ -+ /* If we are creating a shared library, we must presume that the -+ only references to the symbol are via the global offset table. -+ For such cases we need not do anything here; the relocations will -+ be handled correctly by relocate_section. */ -+ if (info->shared) -+ return TRUE; -+ -+ /* If there are no references to this symbol that do not use the -+ GOT, we don't need to generate a copy reloc. */ -+ if (!h->non_got_ref) -+ return TRUE; -+ -+ /* If we didn't find any dynamic relocs in read-only sections, then -+ we'll be keeping the dynamic relocs and avoiding the copy reloc. -+ We can't do this if there are any small data relocations. This -+ doesn't work on VxWorks, where we can not have dynamic -+ relocations (other than copy and jump slot relocations) in an -+ executable. */ -+ if (ELIMINATE_COPY_RELOCS -+ && !ppc_elf_hash_entry (h)->has_sda_refs -+ && !htab->is_vxworks -+ && !h->def_regular -+ && !readonly_dynrelocs (h)) -+ { -+ h->non_got_ref = 0; -+ return TRUE; -+ } -+ -+ /* We must allocate the symbol in our .dynbss section, which will -+ become part of the .bss section of the executable. There will be -+ an entry for this symbol in the .dynsym section. The dynamic -+ object will contain position independent code, so all references -+ from the dynamic object to this symbol will go through the global -+ offset table. The dynamic linker will use the .dynsym entry to -+ determine the address it must put in the global offset table, so -+ both the dynamic object and the regular object will refer to the -+ same memory location for the variable. -+ -+ Of course, if the symbol is referenced using SDAREL relocs, we -+ must instead allocate it in .sbss. */ -+ -+ if (ppc_elf_hash_entry (h)->has_sda_refs) -+ s = htab->dynsbss; -+ else -+ s = htab->dynbss; -+ BFD_ASSERT (s != NULL); -+ -+ /* We must generate a R_PPC_COPY reloc to tell the dynamic linker to -+ copy the initial value out of the dynamic object and into the -+ runtime process image. We need to remember the offset into the -+ .rela.bss section we are going to use. */ -+ if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0) -+ { -+ asection *srel; -+ -+ if (ppc_elf_hash_entry (h)->has_sda_refs) -+ srel = htab->relsbss; -+ else -+ srel = htab->relbss; -+ BFD_ASSERT (srel != NULL); -+ srel->size += sizeof (Elf32_External_Rela); -+ h->needs_copy = 1; -+ } -+ -+ return _bfd_elf_adjust_dynamic_copy (h, s); -+} -+ -+/* Generate a symbol to mark plt call stubs. For non-PIC code the sym is -+ xxxxxxxx.plt_call32. where xxxxxxxx is a hex number, usually 0, -+ specifying the addend on the plt relocation. For -fpic code, the sym -+ is xxxxxxxx.plt_pic32., and for -fPIC -+ xxxxxxxx.got2.plt_pic32.. */ -+ -+static bfd_boolean -+add_stub_sym (struct plt_entry *ent, -+ struct elf_link_hash_entry *h, -+ struct bfd_link_info *info) -+{ -+ struct elf_link_hash_entry *sh; -+ size_t len1, len2, len3; -+ char *name; -+ const char *stub; -+ struct ppc_elf_link_hash_table *htab = ppc_elf_hash_table (info); -+ -+ if (info->shared) -+ stub = ".plt_pic32."; -+ else -+ stub = ".plt_call32."; -+ -+ len1 = strlen (h->root.root.string); -+ len2 = strlen (stub); -+ len3 = 0; -+ if (ent->sec) -+ len3 = strlen (ent->sec->name); -+ name = bfd_malloc (len1 + len2 + len3 + 9); -+ if (name == NULL) -+ return FALSE; -+ sprintf (name, "%08x", (unsigned) ent->addend & 0xffffffff); -+ if (ent->sec) -+ memcpy (name + 8, ent->sec->name, len3); -+ memcpy (name + 8 + len3, stub, len2); -+ memcpy (name + 8 + len3 + len2, h->root.root.string, len1 + 1); -+ sh = elf_link_hash_lookup (&htab->elf, name, TRUE, FALSE, FALSE); -+ if (sh == NULL) -+ return FALSE; -+ if (sh->root.type == bfd_link_hash_new) -+ { -+ sh->root.type = bfd_link_hash_defined; -+ sh->root.u.def.section = htab->glink; -+ sh->root.u.def.value = ent->glink_offset; -+ sh->ref_regular = 1; -+ sh->def_regular = 1; -+ sh->ref_regular_nonweak = 1; -+ sh->forced_local = 1; -+ sh->non_elf = 0; -+ } -+ return TRUE; -+} -+ -+/* Allocate NEED contiguous space in .got, and return the offset. -+ Handles allocation of the got header when crossing 32k. */ -+ -+static bfd_vma -+allocate_got (struct ppc_elf_link_hash_table *htab, unsigned int need) -+{ -+ bfd_vma where; -+ unsigned int max_before_header; -+ -+ if (htab->plt_type == PLT_VXWORKS) -+ { -+ where = htab->got->size; -+ htab->got->size += need; -+ } -+ else -+ { -+ max_before_header = htab->plt_type == PLT_NEW ? 32768 : 32764; -+ if (need <= htab->got_gap) -+ { -+ where = max_before_header - htab->got_gap; -+ htab->got_gap -= need; -+ } -+ else -+ { -+ if (htab->got->size + need > max_before_header -+ && htab->got->size <= max_before_header) -+ { -+ htab->got_gap = max_before_header - htab->got->size; -+ htab->got->size = max_before_header + htab->got_header_size; -+ } -+ where = htab->got->size; -+ htab->got->size += need; -+ } -+ } -+ return where; -+} -+ -+/* Allocate space in associated reloc sections for dynamic relocs. */ -+ -+static bfd_boolean -+allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) -+{ -+ struct bfd_link_info *info = inf; -+ struct ppc_elf_link_hash_entry *eh; -+ struct ppc_elf_link_hash_table *htab; -+ struct elf_dyn_relocs *p; -+ -+ if (h->root.type == bfd_link_hash_indirect) -+ return TRUE; -+ -+ htab = ppc_elf_hash_table (info); -+ if (htab->elf.dynamic_sections_created -+ || h->type == STT_GNU_IFUNC) -+ { -+ struct plt_entry *ent; -+ bfd_boolean doneone = FALSE; -+ bfd_vma plt_offset = 0, glink_offset = 0; -+ bfd_boolean dyn; -+ -+ for (ent = h->plt.plist; ent != NULL; ent = ent->next) -+ if (ent->plt.refcount > 0) -+ { -+ /* Make sure this symbol is output as a dynamic symbol. */ -+ if (h->dynindx == -1 -+ && !h->forced_local -+ && !h->def_regular -+ && htab->elf.dynamic_sections_created) -+ { -+ if (! bfd_elf_link_record_dynamic_symbol (info, h)) -+ return FALSE; -+ } -+ -+ dyn = htab->elf.dynamic_sections_created; -+ if (info->shared -+ || h->type == STT_GNU_IFUNC -+ || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h)) -+ { -+ asection *s = htab->plt; -+ if (!dyn || h->dynindx == -1) -+ s = htab->iplt; -+ -+ if (htab->plt_type == PLT_NEW || !dyn || h->dynindx == -1) -+ { -+ if (!doneone) -+ { -+ plt_offset = s->size; -+ s->size += 4; -+ } -+ ent->plt.offset = plt_offset; -+ -+ s = htab->glink; -+ if (!doneone || info->shared) -+ { -+ glink_offset = s->size; -+ s->size += GLINK_ENTRY_SIZE; -+ if (h == htab->tls_get_addr -+ && !htab->no_tls_get_addr_opt) -+ s->size += TLS_GET_ADDR_GLINK_SIZE - GLINK_ENTRY_SIZE; -+ } -+ if (!doneone -+ && !info->shared -+ && h->def_dynamic -+ && !h->def_regular) -+ { -+ h->root.u.def.section = s; -+ h->root.u.def.value = glink_offset; -+ } -+ ent->glink_offset = glink_offset; -+ -+ if (htab->emit_stub_syms -+ && !add_stub_sym (ent, h, info)) -+ return FALSE; -+ } -+ else -+ { -+ if (!doneone) -+ { -+ /* If this is the first .plt entry, make room -+ for the special first entry. */ -+ if (s->size == 0) -+ s->size += htab->plt_initial_entry_size; -+ -+ /* The PowerPC PLT is actually composed of two -+ parts, the first part is 2 words (for a load -+ and a jump), and then there is a remaining -+ word available at the end. */ -+ plt_offset = (htab->plt_initial_entry_size -+ + (htab->plt_slot_size -+ * ((s->size -+ - htab->plt_initial_entry_size) -+ / htab->plt_entry_size))); -+ -+ /* If this symbol is not defined in a regular -+ file, and we are not generating a shared -+ library, then set the symbol to this location -+ in the .plt. This is to avoid text -+ relocations, and is required to make -+ function pointers compare as equal between -+ the normal executable and the shared library. */ -+ if (! info->shared -+ && h->def_dynamic -+ && !h->def_regular) -+ { -+ h->root.u.def.section = s; -+ h->root.u.def.value = plt_offset; -+ } -+ -+ /* Make room for this entry. */ -+ s->size += htab->plt_entry_size; -+ /* After the 8192nd entry, room for two entries -+ is allocated. */ -+ if (htab->plt_type == PLT_OLD -+ && (s->size - htab->plt_initial_entry_size) -+ / htab->plt_entry_size -+ > PLT_NUM_SINGLE_ENTRIES) -+ s->size += htab->plt_entry_size; -+ } -+ ent->plt.offset = plt_offset; -+ } -+ -+ /* We also need to make an entry in the .rela.plt section. */ -+ if (!doneone) -+ { -+ if (!htab->elf.dynamic_sections_created -+ || h->dynindx == -1) -+ htab->reliplt->size += sizeof (Elf32_External_Rela); -+ else -+ { -+ htab->relplt->size += sizeof (Elf32_External_Rela); -+ -+ if (htab->plt_type == PLT_VXWORKS) -+ { -+ /* Allocate space for the unloaded relocations. */ -+ if (!info->shared -+ && htab->elf.dynamic_sections_created) -+ { -+ if (ent->plt.offset -+ == (bfd_vma) htab->plt_initial_entry_size) -+ { -+ htab->srelplt2->size -+ += (sizeof (Elf32_External_Rela) -+ * VXWORKS_PLTRESOLVE_RELOCS); -+ } -+ -+ htab->srelplt2->size -+ += (sizeof (Elf32_External_Rela) -+ * VXWORKS_PLT_NON_JMP_SLOT_RELOCS); -+ } -+ -+ /* Every PLT entry has an associated GOT entry in -+ .got.plt. */ -+ htab->sgotplt->size += 4; -+ } -+ } -+ doneone = TRUE; -+ } -+ } -+ else -+ ent->plt.offset = (bfd_vma) -1; -+ } -+ else -+ ent->plt.offset = (bfd_vma) -1; -+ -+ if (!doneone) -+ { -+ h->plt.plist = NULL; -+ h->needs_plt = 0; -+ } -+ } -+ else -+ { -+ h->plt.plist = NULL; -+ h->needs_plt = 0; -+ } -+ -+ eh = (struct ppc_elf_link_hash_entry *) h; -+ if (eh->elf.got.refcount > 0) -+ { -+ bfd_boolean dyn; -+ unsigned int need; -+ -+ /* Make sure this symbol is output as a dynamic symbol. */ -+ if (eh->elf.dynindx == -1 -+ && !eh->elf.forced_local -+ && eh->elf.type != STT_GNU_IFUNC -+ && htab->elf.dynamic_sections_created) -+ { -+ if (!bfd_elf_link_record_dynamic_symbol (info, &eh->elf)) -+ return FALSE; -+ } -+ -+ need = 0; -+ if ((eh->tls_mask & TLS_TLS) != 0) -+ { -+ if ((eh->tls_mask & TLS_LD) != 0) -+ { -+ if (!eh->elf.def_dynamic) -+ /* We'll just use htab->tlsld_got.offset. This should -+ always be the case. It's a little odd if we have -+ a local dynamic reloc against a non-local symbol. */ -+ htab->tlsld_got.refcount += 1; -+ else -+ need += 8; -+ } -+ if ((eh->tls_mask & TLS_GD) != 0) -+ need += 8; -+ if ((eh->tls_mask & (TLS_TPREL | TLS_TPRELGD)) != 0) -+ need += 4; -+ if ((eh->tls_mask & TLS_DTPREL) != 0) -+ need += 4; -+ } -+ else -+ need += 4; -+ if (need == 0) -+ eh->elf.got.offset = (bfd_vma) -1; -+ else -+ { -+ eh->elf.got.offset = allocate_got (htab, need); -+ dyn = htab->elf.dynamic_sections_created; -+ if ((info->shared -+ || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, &eh->elf)) -+ && (ELF_ST_VISIBILITY (eh->elf.other) == STV_DEFAULT -+ || eh->elf.root.type != bfd_link_hash_undefweak)) -+ { -+ asection *rsec = htab->relgot; -+ /* All the entries we allocated need relocs. -+ Except LD only needs one. */ -+ if ((eh->tls_mask & TLS_LD) != 0 -+ && eh->elf.def_dynamic) -+ need -= 4; -+ rsec->size += need * (sizeof (Elf32_External_Rela) / 4); -+ } -+ } -+ } -+ else -+ eh->elf.got.offset = (bfd_vma) -1; -+ -+ if (eh->dyn_relocs == NULL -+ || !htab->elf.dynamic_sections_created) -+ return TRUE; -+ -+ /* In the shared -Bsymbolic case, discard space allocated for -+ dynamic pc-relative relocs against symbols which turn out to be -+ defined in regular objects. For the normal shared case, discard -+ space for relocs that have become local due to symbol visibility -+ changes. */ -+ -+ if (info->shared) -+ { -+ /* Relocs that use pc_count are those that appear on a call insn, -+ or certain REL relocs (see must_be_dyn_reloc) that can be -+ generated via assembly. We want calls to protected symbols to -+ resolve directly to the function rather than going via the plt. -+ If people want function pointer comparisons to work as expected -+ then they should avoid writing weird assembly. */ -+ if (SYMBOL_CALLS_LOCAL (info, h)) -+ { -+ struct elf_dyn_relocs **pp; -+ -+ for (pp = &eh->dyn_relocs; (p = *pp) != NULL; ) -+ { -+ p->count -= p->pc_count; -+ p->pc_count = 0; -+ if (p->count == 0) -+ *pp = p->next; -+ else -+ pp = &p->next; -+ } -+ } -+ -+ if (htab->is_vxworks) -+ { -+ struct elf_dyn_relocs **pp; -+ -+ for (pp = &eh->dyn_relocs; (p = *pp) != NULL; ) -+ { -+ if (strcmp (p->sec->output_section->name, ".tls_vars") == 0) -+ *pp = p->next; -+ else -+ pp = &p->next; -+ } -+ } -+ -+ /* Discard relocs on undefined symbols that must be local. */ -+ if (eh->dyn_relocs != NULL -+ && h->root.type == bfd_link_hash_undefined -+ && (ELF_ST_VISIBILITY (h->other) == STV_HIDDEN -+ || ELF_ST_VISIBILITY (h->other) == STV_INTERNAL)) -+ eh->dyn_relocs = NULL; -+ -+ /* Also discard relocs on undefined weak syms with non-default -+ visibility. */ -+ if (eh->dyn_relocs != NULL -+ && h->root.type == bfd_link_hash_undefweak) -+ { -+ if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT) -+ eh->dyn_relocs = NULL; -+ -+ /* Make sure undefined weak symbols are output as a dynamic -+ symbol in PIEs. */ -+ else if (h->dynindx == -1 -+ && !h->forced_local -+ && !h->def_regular) -+ { -+ if (! bfd_elf_link_record_dynamic_symbol (info, h)) -+ return FALSE; -+ } -+ } -+ } -+ else if (ELIMINATE_COPY_RELOCS) -+ { -+ /* For the non-shared case, discard space for relocs against -+ symbols which turn out to need copy relocs or are not -+ dynamic. */ -+ -+ if (!h->non_got_ref -+ && !h->def_regular) -+ { -+ /* Make sure this symbol is output as a dynamic symbol. -+ Undefined weak syms won't yet be marked as dynamic. */ -+ if (h->dynindx == -1 -+ && !h->forced_local) -+ { -+ if (! bfd_elf_link_record_dynamic_symbol (info, h)) -+ return FALSE; -+ } -+ -+ /* If that succeeded, we know we'll be keeping all the -+ relocs. */ -+ if (h->dynindx != -1) -+ goto keep; -+ } -+ -+ eh->dyn_relocs = NULL; -+ -+ keep: ; -+ } -+ -+ /* Finally, allocate space. */ -+ for (p = eh->dyn_relocs; p != NULL; p = p->next) -+ { -+ asection *sreloc = elf_section_data (p->sec)->sreloc; -+ if (!htab->elf.dynamic_sections_created) -+ sreloc = htab->reliplt; -+ sreloc->size += p->count * sizeof (Elf32_External_Rela); -+ } -+ -+ return TRUE; -+} -+ -+/* Set DF_TEXTREL if we find any dynamic relocs that apply to -+ read-only sections. */ -+ -+static bfd_boolean -+maybe_set_textrel (struct elf_link_hash_entry *h, void *info) -+{ -+ if (h->root.type == bfd_link_hash_indirect) -+ return TRUE; -+ -+ if (readonly_dynrelocs (h)) -+ { -+ ((struct bfd_link_info *) info)->flags |= DF_TEXTREL; -+ -+ /* Not an error, just cut short the traversal. */ -+ return FALSE; -+ } -+ return TRUE; -+} -+ -+static const unsigned char glink_eh_frame_cie[] = -+{ -+ 0, 0, 0, 16, /* length. */ -+ 0, 0, 0, 0, /* id. */ -+ 1, /* CIE version. */ -+ 'z', 'R', 0, /* Augmentation string. */ -+ 4, /* Code alignment. */ -+ 0x7c, /* Data alignment. */ -+ 65, /* RA reg. */ -+ 1, /* Augmentation size. */ -+ DW_EH_PE_pcrel | DW_EH_PE_sdata4, /* FDE encoding. */ -+ DW_CFA_def_cfa, 1, 0 /* def_cfa: r1 offset 0. */ -+}; -+ -+/* Set the sizes of the dynamic sections. */ -+ -+static bfd_boolean -+ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, -+ struct bfd_link_info *info) -+{ -+ struct ppc_elf_link_hash_table *htab; -+ asection *s; -+ bfd_boolean relocs; -+ bfd *ibfd; -+ -+#ifdef DEBUG -+ fprintf (stderr, "ppc_elf_size_dynamic_sections called\n"); -+#endif -+ -+ htab = ppc_elf_hash_table (info); -+ BFD_ASSERT (htab->elf.dynobj != NULL); -+ -+#ifdef DEBUG -+ fprintf (stderr, "ppc_elf_size_dynamic_sections: dynamic_sections_created = %d\n", elf_hash_table (info)->dynamic_sections_created); -+#endif -+ -+ if (elf_hash_table (info)->dynamic_sections_created) -+ { -+ /* Set the contents of the .interp section to the interpreter. */ -+ if (info->executable) -+ { -+ s = bfd_get_linker_section (htab->elf.dynobj, ".interp"); -+ BFD_ASSERT (s != NULL); -+ s->size = sizeof ELF_DYNAMIC_INTERPRETER; -+ s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER; -+ } -+ } -+ -+ if (htab->plt_type == PLT_OLD) -+ htab->got_header_size = 16; -+ else if (htab->plt_type == PLT_NEW) -+ htab->got_header_size = 12; -+ -+ /* Set up .got offsets for local syms, and space for local dynamic -+ relocs. */ -+ for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) -+ { -+ bfd_signed_vma *local_got; -+ bfd_signed_vma *end_local_got; -+ struct plt_entry **local_plt; -+ struct plt_entry **end_local_plt; -+ char *lgot_masks; -+ bfd_size_type locsymcount; -+ Elf_Internal_Shdr *symtab_hdr; -+ -+#ifdef DEBUG -+ fprintf (stderr, "ppc_elf_size_dynamic_sections: is_ppc_elf() = %d (flavour = %d)\n", is_ppc_elf (ibfd), bfd_get_flavour (ibfd)); -+#endif -+ -+ if (!is_ppc_elf (ibfd)) -+ continue; -+ -+ for (s = ibfd->sections; s != NULL; s = s->next) -+ { -+ struct elf_dyn_relocs *p; -+ -+ for (p = ((struct elf_dyn_relocs *) -+ elf_section_data (s)->local_dynrel); -+ p != NULL; -+ p = p->next) -+ { -+ if (!bfd_is_abs_section (p->sec) -+ && bfd_is_abs_section (p->sec->output_section)) -+ { -+ /* Input section has been discarded, either because -+ it is a copy of a linkonce section or due to -+ linker script /DISCARD/, so we'll be discarding -+ the relocs too. */ -+ } -+ else if (htab->is_vxworks -+ && strcmp (p->sec->output_section->name, -+ ".tls_vars") == 0) -+ { -+ /* Relocations in vxworks .tls_vars sections are -+ handled specially by the loader. */ -+ } -+ else if (p->count != 0) -+ { -+ asection *sreloc = elf_section_data (p->sec)->sreloc; -+ if (!htab->elf.dynamic_sections_created) -+ sreloc = htab->reliplt; -+ sreloc->size += p->count * sizeof (Elf32_External_Rela); -+ if ((p->sec->output_section->flags -+ & (SEC_READONLY | SEC_ALLOC)) -+ == (SEC_READONLY | SEC_ALLOC)) -+ info->flags |= DF_TEXTREL; -+ } -+ } -+ } -+ -+ local_got = elf_local_got_refcounts (ibfd); -+ if (!local_got) -+ continue; -+ -+ symtab_hdr = &elf_symtab_hdr (ibfd); -+ locsymcount = symtab_hdr->sh_info; -+ end_local_got = local_got + locsymcount; -+ local_plt = (struct plt_entry **) end_local_got; -+ end_local_plt = local_plt + locsymcount; -+ lgot_masks = (char *) end_local_plt; -+ -+ for (; local_got < end_local_got; ++local_got, ++lgot_masks) -+ if (*local_got > 0) -+ { -+ unsigned int need = 0; -+ if ((*lgot_masks & TLS_TLS) != 0) -+ { -+ if ((*lgot_masks & TLS_GD) != 0) -+ need += 8; -+ if ((*lgot_masks & TLS_LD) != 0) -+ htab->tlsld_got.refcount += 1; -+ if ((*lgot_masks & (TLS_TPREL | TLS_TPRELGD)) != 0) -+ need += 4; -+ if ((*lgot_masks & TLS_DTPREL) != 0) -+ need += 4; -+ } -+ else -+ need += 4; -+ if (need == 0) -+ *local_got = (bfd_vma) -1; -+ else -+ { -+ *local_got = allocate_got (htab, need); -+ if (info->shared) -+ htab->relgot->size += (need -+ * (sizeof (Elf32_External_Rela) / 4)); -+ } -+ } -+ else -+ *local_got = (bfd_vma) -1; -+ -+ if (htab->is_vxworks) -+ continue; -+ -+ /* Allocate space for calls to local STT_GNU_IFUNC syms in .iplt. */ -+ for (; local_plt < end_local_plt; ++local_plt) -+ { -+ struct plt_entry *ent; -+ bfd_boolean doneone = FALSE; -+ bfd_vma plt_offset = 0, glink_offset = 0; -+ -+ for (ent = *local_plt; ent != NULL; ent = ent->next) -+ if (ent->plt.refcount > 0) -+ { -+ s = htab->iplt; -+ -+ if (!doneone) -+ { -+ plt_offset = s->size; -+ s->size += 4; -+ } -+ ent->plt.offset = plt_offset; -+ -+ s = htab->glink; -+ if (!doneone || info->shared) -+ { -+ glink_offset = s->size; -+ s->size += GLINK_ENTRY_SIZE; -+ } -+ ent->glink_offset = glink_offset; -+ -+ if (!doneone) -+ { -+ htab->reliplt->size += sizeof (Elf32_External_Rela); -+ doneone = TRUE; -+ } -+ } -+ else -+ ent->plt.offset = (bfd_vma) -1; -+ } -+ } -+ -+ /* Allocate space for global sym dynamic relocs. */ -+ elf_link_hash_traverse (elf_hash_table (info), allocate_dynrelocs, info); -+ -+ if (htab->tlsld_got.refcount > 0) -+ { -+ htab->tlsld_got.offset = allocate_got (htab, 8); -+ if (info->shared) -+ htab->relgot->size += sizeof (Elf32_External_Rela); -+ } -+ else -+ htab->tlsld_got.offset = (bfd_vma) -1; -+ -+ if (htab->got != NULL && htab->plt_type != PLT_VXWORKS) -+ { -+ unsigned int g_o_t = 32768; -+ -+ /* If we haven't allocated the header, do so now. When we get here, -+ for old plt/got the got size will be 0 to 32764 (not allocated), -+ or 32780 to 65536 (header allocated). For new plt/got, the -+ corresponding ranges are 0 to 32768 and 32780 to 65536. */ -+ if (htab->got->size <= 32768) -+ { -+ g_o_t = htab->got->size; -+ if (htab->plt_type == PLT_OLD) -+ g_o_t += 4; -+ htab->got->size += htab->got_header_size; -+ } -+ -+ htab->elf.hgot->root.u.def.value = g_o_t; -+ } -+ if (info->shared) -+ { -+ struct elf_link_hash_entry *sda = htab->sdata[0].sym; -+ if (sda != NULL -+ && !(sda->root.type == bfd_link_hash_defined -+ || sda->root.type == bfd_link_hash_defweak)) -+ { -+ sda->root.type = bfd_link_hash_defined; -+ sda->root.u.def.section = htab->elf.hgot->root.u.def.section; -+ sda->root.u.def.value = htab->elf.hgot->root.u.def.value; -+ } -+ } -+ -+ if (htab->glink != NULL -+ && htab->glink->size != 0 -+ && htab->elf.dynamic_sections_created) -+ { -+ htab->glink_pltresolve = htab->glink->size; -+ /* Space for the branch table. */ -+ htab->glink->size += htab->glink->size / (GLINK_ENTRY_SIZE / 4) - 4; -+ /* Pad out to align the start of PLTresolve. */ -+ htab->glink->size += -htab->glink->size & 15; -+ htab->glink->size += GLINK_PLTRESOLVE; -+ -+ if (htab->emit_stub_syms) -+ { -+ struct elf_link_hash_entry *sh; -+ sh = elf_link_hash_lookup (&htab->elf, "__glink", -+ TRUE, FALSE, FALSE); -+ if (sh == NULL) -+ return FALSE; -+ if (sh->root.type == bfd_link_hash_new) -+ { -+ sh->root.type = bfd_link_hash_defined; -+ sh->root.u.def.section = htab->glink; -+ sh->root.u.def.value = htab->glink_pltresolve; -+ sh->ref_regular = 1; -+ sh->def_regular = 1; -+ sh->ref_regular_nonweak = 1; -+ sh->forced_local = 1; -+ sh->non_elf = 0; -+ } -+ sh = elf_link_hash_lookup (&htab->elf, "__glink_PLTresolve", -+ TRUE, FALSE, FALSE); -+ if (sh == NULL) -+ return FALSE; -+ if (sh->root.type == bfd_link_hash_new) -+ { -+ sh->root.type = bfd_link_hash_defined; -+ sh->root.u.def.section = htab->glink; -+ sh->root.u.def.value = htab->glink->size - GLINK_PLTRESOLVE; -+ sh->ref_regular = 1; -+ sh->def_regular = 1; -+ sh->ref_regular_nonweak = 1; -+ sh->forced_local = 1; -+ sh->non_elf = 0; -+ } -+ } -+ } -+ -+ if (htab->glink != NULL -+ && htab->glink->size != 0 -+ && htab->glink_eh_frame != NULL -+ && !bfd_is_abs_section (htab->glink_eh_frame->output_section) -+ && _bfd_elf_eh_frame_present (info)) -+ { -+ s = htab->glink_eh_frame; -+ s->size = sizeof (glink_eh_frame_cie) + 20; -+ if (info->shared) -+ { -+ s->size += 4; -+ if (htab->glink->size - GLINK_PLTRESOLVE + 8 >= 256) -+ s->size += 4; -+ } -+ } -+ -+ /* We've now determined the sizes of the various dynamic sections. -+ Allocate memory for them. */ -+ relocs = FALSE; -+ for (s = htab->elf.dynobj->sections; s != NULL; s = s->next) -+ { -+ bfd_boolean strip_section = TRUE; -+ -+ if ((s->flags & SEC_LINKER_CREATED) == 0) -+ continue; -+ -+ if (s == htab->plt -+ || s == htab->got) -+ { -+ /* We'd like to strip these sections if they aren't needed, but if -+ we've exported dynamic symbols from them we must leave them. -+ It's too late to tell BFD to get rid of the symbols. */ -+ if (htab->elf.hplt != NULL) -+ strip_section = FALSE; -+ /* Strip this section if we don't need it; see the -+ comment below. */ -+ } -+ else if (s == htab->iplt -+ || s == htab->glink -+ || s == htab->glink_eh_frame -+ || s == htab->sgotplt -+ || s == htab->sbss -+ || s == htab->dynbss -+ || s == htab->dynsbss -+ || s == htab->sdata[0].section -+ || s == htab->sdata[1].section) -+ { -+ /* Strip these too. */ -+ } -+ else if (CONST_STRNEQ (bfd_get_section_name (htab->elf.dynobj, s), -+ ".rela")) -+ { -+ if (s->size != 0) -+ { -+ /* Remember whether there are any relocation sections. */ -+ relocs = TRUE; -+ -+ /* We use the reloc_count field as a counter if we need -+ to copy relocs into the output file. */ -+ s->reloc_count = 0; -+ } -+ } -+ else -+ { -+ /* It's not one of our sections, so don't allocate space. */ -+ continue; -+ } -+ -+ if (s->size == 0 && strip_section) -+ { -+ /* If we don't need this section, strip it from the -+ output file. This is mostly to handle .rela.bss and -+ .rela.plt. We must create both sections in -+ create_dynamic_sections, because they must be created -+ before the linker maps input sections to output -+ sections. The linker does that before -+ adjust_dynamic_symbol is called, and it is that -+ function which decides whether anything needs to go -+ into these sections. */ -+ s->flags |= SEC_EXCLUDE; -+ continue; -+ } -+ -+ if ((s->flags & SEC_HAS_CONTENTS) == 0) -+ continue; -+ -+ /* Allocate memory for the section contents. */ -+ s->contents = bfd_zalloc (htab->elf.dynobj, s->size); -+ if (s->contents == NULL) -+ return FALSE; -+ } -+ -+ if (htab->elf.dynamic_sections_created) -+ { -+ /* Add some entries to the .dynamic section. We fill in the -+ values later, in ppc_elf_finish_dynamic_sections, but we -+ must add the entries now so that we get the correct size for -+ the .dynamic section. The DT_DEBUG entry is filled in by the -+ dynamic linker and used by the debugger. */ -+#define add_dynamic_entry(TAG, VAL) \ -+ _bfd_elf_add_dynamic_entry (info, TAG, VAL) -+ -+ if (info->executable) -+ { -+ if (!add_dynamic_entry (DT_DEBUG, 0)) -+ return FALSE; -+ } -+ -+ if (htab->plt != NULL && htab->plt->size != 0) -+ { -+ if (!add_dynamic_entry (DT_PLTGOT, 0) -+ || !add_dynamic_entry (DT_PLTRELSZ, 0) -+ || !add_dynamic_entry (DT_PLTREL, DT_RELA) -+ || !add_dynamic_entry (DT_JMPREL, 0)) -+ return FALSE; -+ } -+ -+ if (htab->glink != NULL && htab->glink->size != 0) -+ { -+ if (!add_dynamic_entry (DT_PPC_GOT, 0)) -+ return FALSE; -+ if (!htab->no_tls_get_addr_opt -+ && htab->tls_get_addr != NULL -+ && htab->tls_get_addr->plt.plist != NULL -+ && !add_dynamic_entry (DT_PPC_TLSOPT, 0)) -+ return FALSE; -+ } -+ -+ if (relocs) -+ { -+ if (!add_dynamic_entry (DT_RELA, 0) -+ || !add_dynamic_entry (DT_RELASZ, 0) -+ || !add_dynamic_entry (DT_RELAENT, sizeof (Elf32_External_Rela))) -+ return FALSE; -+ } -+ -+ /* If any dynamic relocs apply to a read-only section, then we -+ need a DT_TEXTREL entry. */ -+ if ((info->flags & DF_TEXTREL) == 0) -+ elf_link_hash_traverse (elf_hash_table (info), maybe_set_textrel, -+ info); -+ -+ if ((info->flags & DF_TEXTREL) != 0) -+ { -+ if (!add_dynamic_entry (DT_TEXTREL, 0)) -+ return FALSE; -+ } -+ if (htab->is_vxworks -+ && !elf_vxworks_add_dynamic_entries (output_bfd, info)) -+ return FALSE; -+ -+ /* Flag it as a version 2 dynamic binary */ -+ if (!add_dynamic_entry(DT_AMIGAOS_DYNVERSION, 2)) -+ return FALSE; -+ } -+#undef add_dynamic_entry -+ -+ if (htab->glink_eh_frame != NULL -+ && htab->glink_eh_frame->contents != NULL) -+ { -+ unsigned char *p = htab->glink_eh_frame->contents; -+ bfd_vma val; -+ -+ memcpy (p, glink_eh_frame_cie, sizeof (glink_eh_frame_cie)); -+ /* CIE length (rewrite in case little-endian). */ -+ bfd_put_32 (htab->elf.dynobj, sizeof (glink_eh_frame_cie) - 4, p); -+ p += sizeof (glink_eh_frame_cie); -+ /* FDE length. */ -+ val = htab->glink_eh_frame->size - 4 - sizeof (glink_eh_frame_cie); -+ bfd_put_32 (htab->elf.dynobj, val, p); -+ p += 4; -+ /* CIE pointer. */ -+ val = p - htab->glink_eh_frame->contents; -+ bfd_put_32 (htab->elf.dynobj, val, p); -+ p += 4; -+ /* Offset to .glink. Set later. */ -+ p += 4; -+ /* .glink size. */ -+ bfd_put_32 (htab->elf.dynobj, htab->glink->size, p); -+ p += 4; -+ /* Augmentation. */ -+ p += 1; -+ -+ if (info->shared -+ && htab->elf.dynamic_sections_created) -+ { -+ bfd_vma adv = (htab->glink->size - GLINK_PLTRESOLVE + 8) >> 2; -+ if (adv < 64) -+ *p++ = DW_CFA_advance_loc + adv; -+ else if (adv < 256) -+ { -+ *p++ = DW_CFA_advance_loc1; -+ *p++ = adv; -+ } -+ else if (adv < 65536) -+ { -+ *p++ = DW_CFA_advance_loc2; -+ bfd_put_16 (htab->elf.dynobj, adv, p); -+ p += 2; -+ } -+ else -+ { -+ *p++ = DW_CFA_advance_loc4; -+ bfd_put_32 (htab->elf.dynobj, adv, p); -+ p += 4; -+ } -+ *p++ = DW_CFA_register; -+ *p++ = 65; -+ p++; -+ *p++ = DW_CFA_advance_loc + 4; -+ *p++ = DW_CFA_restore_extended; -+ *p++ = 65; -+ } -+ BFD_ASSERT ((bfd_vma) ((p + 3 - htab->glink_eh_frame->contents) & -4) -+ == htab->glink_eh_frame->size); -+ } -+ -+ return TRUE; -+} -+ -+/* Return TRUE if symbol should be hashed in the `.gnu.hash' section. */ -+ -+static bfd_boolean -+ppc_elf_hash_symbol (struct elf_link_hash_entry *h) -+{ -+ if (h->plt.plist != NULL -+ && !h->def_regular -+ && (!h->pointer_equality_needed -+ || !h->ref_regular_nonweak)) -+ return FALSE; -+ -+ return _bfd_elf_hash_symbol (h); -+} -+ -+#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0])) -+ -+/* Relaxation trampolines. r12 is available for clobbering (r11, is -+ used for some functions that are allowed to break the ABI). */ -+static const int shared_stub_entry[] = -+ { -+ 0x7c0802a6, /* mflr 0 */ -+ 0x429f0005, /* bcl 20, 31, .Lxxx */ -+ 0x7d8802a6, /* mflr 12 */ -+ 0x3d8c0000, /* addis 12, 12, (xxx-.Lxxx)@ha */ -+ 0x398c0008, /* addi 12, 12, (xxx-.Lxxx)@l */ -+ 0x7c0803a6, /* mtlr 0 */ -+ 0x7d8903a6, /* mtctr 12 */ -+ 0x4e800420, /* bctr */ -+ }; -+ -+static const int stub_entry[] = -+ { -+ 0x3d800000, /* lis 12,xxx@ha */ -+ 0x398c0000, /* addi 12,12,xxx@l */ -+ 0x7d8903a6, /* mtctr 12 */ -+ 0x4e800420, /* bctr */ -+ }; -+ -+static bfd_boolean -+ppc_elf_relax_section (bfd *abfd, -+ asection *isec, -+ struct bfd_link_info *link_info, -+ bfd_boolean *again) -+{ -+ struct one_fixup -+ { -+ struct one_fixup *next; -+ asection *tsec; -+ /* Final link, can use the symbol offset. For a -+ relocatable link we use the symbol's index. */ -+ bfd_vma toff; -+ bfd_vma trampoff; -+ }; -+ -+ Elf_Internal_Shdr *symtab_hdr; -+ bfd_byte *contents = NULL; -+ Elf_Internal_Sym *isymbuf = NULL; -+ Elf_Internal_Rela *internal_relocs = NULL; -+ Elf_Internal_Rela *irel, *irelend; -+ struct one_fixup *fixups = NULL; -+ unsigned changes = 0; -+ struct ppc_elf_link_hash_table *htab; -+ bfd_size_type trampoff; -+ asection *got2; -+ bfd_boolean maybe_pasted; -+ -+ *again = FALSE; -+ -+ /* Nothing to do if there are no relocations, and no need to do -+ anything with non-alloc or non-code sections. */ -+ if ((isec->flags & SEC_ALLOC) == 0 -+ || (isec->flags & SEC_CODE) == 0 -+ || (isec->flags & SEC_RELOC) == 0 -+ || isec->reloc_count == 0) -+ return TRUE; -+ -+ /* We cannot represent the required PIC relocs in the output, so don't -+ do anything. The linker doesn't support mixing -shared and -r -+ anyway. */ -+ if (link_info->relocatable && link_info->shared) -+ return TRUE; -+ -+ trampoff = (isec->size + 3) & (bfd_vma) -4; -+ maybe_pasted = (strcmp (isec->output_section->name, ".init") == 0 -+ || strcmp (isec->output_section->name, ".fini") == 0); -+ /* Space for a branch around any trampolines. */ -+ if (maybe_pasted) -+ trampoff += 4; -+ -+ symtab_hdr = &elf_symtab_hdr (abfd); -+ -+ /* Get a copy of the native relocations. */ -+ internal_relocs = _bfd_elf_link_read_relocs (abfd, isec, NULL, NULL, -+ link_info->keep_memory); -+ if (internal_relocs == NULL) -+ goto error_return; -+ -+ htab = ppc_elf_hash_table (link_info); -+ got2 = bfd_get_section_by_name (abfd, ".got2"); -+ -+ irelend = internal_relocs + isec->reloc_count; -+ for (irel = internal_relocs; irel < irelend; irel++) -+ { -+ unsigned long r_type = ELF32_R_TYPE (irel->r_info); -+ bfd_vma toff, roff; -+ asection *tsec; -+ struct one_fixup *f; -+ size_t insn_offset = 0; -+ bfd_vma max_branch_offset, val; -+ bfd_byte *hit_addr; -+ unsigned long t0; -+ struct elf_link_hash_entry *h; -+ struct plt_entry **plist; -+ unsigned char sym_type; -+ -+ switch (r_type) -+ { -+ case R_PPC_REL24: -+ case R_PPC_LOCAL24PC: -+ case R_PPC_PLTREL24: -+ max_branch_offset = 1 << 25; -+ break; -+ -+ case R_PPC_REL14: -+ case R_PPC_REL14_BRTAKEN: -+ case R_PPC_REL14_BRNTAKEN: -+ max_branch_offset = 1 << 15; -+ break; -+ -+ default: -+ continue; -+ } -+ -+ /* Get the value of the symbol referred to by the reloc. */ -+ h = NULL; -+ if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info) -+ { -+ /* A local symbol. */ -+ Elf_Internal_Sym *isym; -+ -+ /* Read this BFD's local symbols. */ -+ if (isymbuf == NULL) -+ { -+ isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; -+ if (isymbuf == NULL) -+ isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr, -+ symtab_hdr->sh_info, 0, -+ NULL, NULL, NULL); -+ if (isymbuf == 0) -+ goto error_return; -+ } -+ isym = isymbuf + ELF32_R_SYM (irel->r_info); -+ if (isym->st_shndx == SHN_UNDEF) -+ tsec = bfd_und_section_ptr; -+ else if (isym->st_shndx == SHN_ABS) -+ tsec = bfd_abs_section_ptr; -+ else if (isym->st_shndx == SHN_COMMON) -+ tsec = bfd_com_section_ptr; -+ else -+ tsec = bfd_section_from_elf_index (abfd, isym->st_shndx); -+ -+ toff = isym->st_value; -+ sym_type = ELF_ST_TYPE (isym->st_info); -+ } -+ else -+ { -+ /* Global symbol handling. */ -+ unsigned long indx; -+ -+ indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info; -+ h = elf_sym_hashes (abfd)[indx]; -+ -+ while (h->root.type == bfd_link_hash_indirect -+ || h->root.type == bfd_link_hash_warning) -+ h = (struct elf_link_hash_entry *) h->root.u.i.link; -+ -+ if (h->root.type == bfd_link_hash_defined -+ || h->root.type == bfd_link_hash_defweak) -+ { -+ tsec = h->root.u.def.section; -+ toff = h->root.u.def.value; -+ } -+ else if (h->root.type == bfd_link_hash_undefined -+ || h->root.type == bfd_link_hash_undefweak) -+ { -+ tsec = bfd_und_section_ptr; -+ toff = link_info->relocatable ? indx : 0; -+ } -+ else -+ continue; -+ -+ sym_type = h->type; -+ } -+ -+ /* The condition here under which we call find_plt_ent must -+ match that in relocate_section. If we call find_plt_ent here -+ but not in relocate_section, or vice versa, then the branch -+ destination used here may be incorrect. */ -+ plist = NULL; -+ if (h != NULL) -+ { -+ /* We know is_branch_reloc (r_type) is true. */ -+ if (h->type == STT_GNU_IFUNC -+ || r_type == R_PPC_PLTREL24) -+ plist = &h->plt.plist; -+ } -+ else if (sym_type == STT_GNU_IFUNC -+ && elf_local_got_offsets (abfd) != NULL) -+ { -+ bfd_vma *local_got_offsets = elf_local_got_offsets (abfd); -+ struct plt_entry **local_plt = (struct plt_entry **) -+ (local_got_offsets + symtab_hdr->sh_info); -+ plist = local_plt + ELF32_R_SYM (irel->r_info); -+ } -+ if (plist != NULL) -+ { -+ bfd_vma addend = 0; -+ struct plt_entry *ent; -+ -+ if (r_type == R_PPC_PLTREL24 && link_info->shared) -+ addend = irel->r_addend; -+ ent = find_plt_ent (plist, got2, addend); -+ if (ent != NULL) -+ { -+ if (htab->plt_type == PLT_NEW -+ || h == NULL -+ || !htab->elf.dynamic_sections_created -+ || h->dynindx == -1) -+ { -+ tsec = htab->glink; -+ toff = ent->glink_offset; -+ } -+ else -+ { -+ tsec = htab->plt; -+ toff = ent->plt.offset; -+ } -+ } -+ } -+ -+ /* If the branch and target are in the same section, you have -+ no hope of adding stubs. We'll error out later should the -+ branch overflow. */ -+ if (tsec == isec) -+ continue; -+ -+ /* There probably isn't any reason to handle symbols in -+ SEC_MERGE sections; SEC_MERGE doesn't seem a likely -+ attribute for a code section, and we are only looking at -+ branches. However, implement it correctly here as a -+ reference for other target relax_section functions. */ -+ if (0 && tsec->sec_info_type == SEC_INFO_TYPE_MERGE) -+ { -+ /* At this stage in linking, no SEC_MERGE symbol has been -+ adjusted, so all references to such symbols need to be -+ passed through _bfd_merged_section_offset. (Later, in -+ relocate_section, all SEC_MERGE symbols *except* for -+ section symbols have been adjusted.) -+ -+ gas may reduce relocations against symbols in SEC_MERGE -+ sections to a relocation against the section symbol when -+ the original addend was zero. When the reloc is against -+ a section symbol we should include the addend in the -+ offset passed to _bfd_merged_section_offset, since the -+ location of interest is the original symbol. On the -+ other hand, an access to "sym+addend" where "sym" is not -+ a section symbol should not include the addend; Such an -+ access is presumed to be an offset from "sym"; The -+ location of interest is just "sym". */ -+ if (sym_type == STT_SECTION) -+ toff += irel->r_addend; -+ -+ toff = _bfd_merged_section_offset (abfd, &tsec, -+ elf_section_data (tsec)->sec_info, -+ toff); -+ -+ if (sym_type != STT_SECTION) -+ toff += irel->r_addend; -+ } -+ /* PLTREL24 addends are special. */ -+ else if (r_type != R_PPC_PLTREL24) -+ toff += irel->r_addend; -+ -+ /* Attempted -shared link of non-pic code loses. */ -+ if (tsec->output_section == NULL) -+ continue; -+ -+ roff = irel->r_offset; -+ -+ /* If the branch is in range, no need to do anything. */ -+ if (tsec != bfd_und_section_ptr -+ && (!link_info->relocatable -+ /* A relocatable link may have sections moved during -+ final link, so do not presume they remain in range. */ -+ || tsec->output_section == isec->output_section)) -+ { -+ bfd_vma symaddr, reladdr; -+ -+ symaddr = tsec->output_section->vma + tsec->output_offset + toff; -+ reladdr = isec->output_section->vma + isec->output_offset + roff; -+ if (symaddr - reladdr + max_branch_offset < 2 * max_branch_offset) -+ continue; -+ } -+ -+ /* Look for an existing fixup to this address. */ -+ for (f = fixups; f ; f = f->next) -+ if (f->tsec == tsec && f->toff == toff) -+ break; -+ -+ if (f == NULL) -+ { -+ size_t size; -+ unsigned long stub_rtype; -+ -+ val = trampoff - roff; -+ if (val >= max_branch_offset) -+ /* Oh dear, we can't reach a trampoline. Don't try to add -+ one. We'll report an error later. */ -+ continue; -+ -+ if (link_info->shared) -+ { -+ size = 4 * ARRAY_SIZE (shared_stub_entry); -+ insn_offset = 12; -+ } -+ else -+ { -+ size = 4 * ARRAY_SIZE (stub_entry); -+ insn_offset = 0; -+ } -+ stub_rtype = R_PPC_RELAX; -+ if (tsec == htab->plt -+ || tsec == htab->glink) -+ { -+ stub_rtype = R_PPC_RELAX_PLT; -+ if (r_type == R_PPC_PLTREL24) -+ stub_rtype = R_PPC_RELAX_PLTREL24; -+ } -+ -+ /* Hijack the old relocation. Since we need two -+ relocations for this use a "composite" reloc. */ -+ irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), -+ stub_rtype); -+ irel->r_offset = trampoff + insn_offset; -+ if (r_type == R_PPC_PLTREL24 -+ && stub_rtype != R_PPC_RELAX_PLTREL24) -+ irel->r_addend = 0; -+ -+ /* Record the fixup so we don't do it again this section. */ -+ f = bfd_malloc (sizeof (*f)); -+ f->next = fixups; -+ f->tsec = tsec; -+ f->toff = toff; -+ f->trampoff = trampoff; -+ fixups = f; -+ -+ trampoff += size; -+ changes++; -+ } -+ else -+ { -+ val = f->trampoff - roff; -+ if (val >= max_branch_offset) -+ continue; -+ -+ /* Nop out the reloc, since we're finalizing things here. */ -+ irel->r_info = ELF32_R_INFO (0, R_PPC_NONE); -+ } -+ -+ /* Get the section contents. */ -+ if (contents == NULL) -+ { -+ /* Get cached copy if it exists. */ -+ if (elf_section_data (isec)->this_hdr.contents != NULL) -+ contents = elf_section_data (isec)->this_hdr.contents; -+ else -+ { -+ /* Go get them off disk. */ -+ if (!bfd_malloc_and_get_section (abfd, isec, &contents)) -+ goto error_return; -+ } -+ } -+ -+ /* Fix up the existing branch to hit the trampoline. */ -+ hit_addr = contents + roff; -+ switch (r_type) -+ { -+ case R_PPC_REL24: -+ case R_PPC_LOCAL24PC: -+ case R_PPC_PLTREL24: -+ t0 = bfd_get_32 (abfd, hit_addr); -+ t0 &= ~0x3fffffc; -+ t0 |= val & 0x3fffffc; -+ bfd_put_32 (abfd, t0, hit_addr); -+ break; -+ -+ case R_PPC_REL14: -+ case R_PPC_REL14_BRTAKEN: -+ case R_PPC_REL14_BRNTAKEN: -+ t0 = bfd_get_32 (abfd, hit_addr); -+ t0 &= ~0xfffc; -+ t0 |= val & 0xfffc; -+ bfd_put_32 (abfd, t0, hit_addr); -+ break; -+ } -+ } -+ -+ /* Write out the trampolines. */ -+ if (fixups != NULL) -+ { -+ const int *stub; -+ bfd_byte *dest; -+ int i, size; -+ -+ do -+ { -+ struct one_fixup *f = fixups; -+ fixups = fixups->next; -+ free (f); -+ } -+ while (fixups); -+ -+ contents = bfd_realloc_or_free (contents, trampoff); -+ if (contents == NULL) -+ goto error_return; -+ -+ isec->size = (isec->size + 3) & (bfd_vma) -4; -+ dest = contents + isec->size; -+ /* Branch around the trampolines. */ -+ if (maybe_pasted) -+ { -+ bfd_vma val = B + trampoff - isec->size; -+ bfd_put_32 (abfd, val, dest); -+ dest += 4; -+ } -+ isec->size = trampoff; -+ -+ if (link_info->shared) -+ { -+ stub = shared_stub_entry; -+ size = ARRAY_SIZE (shared_stub_entry); -+ } -+ else -+ { -+ stub = stub_entry; -+ size = ARRAY_SIZE (stub_entry); -+ } -+ -+ i = 0; -+ while (dest < contents + trampoff) -+ { -+ bfd_put_32 (abfd, stub[i], dest); -+ i++; -+ if (i == size) -+ i = 0; -+ dest += 4; -+ } -+ BFD_ASSERT (i == 0); -+ } -+ -+ if (isymbuf != NULL -+ && symtab_hdr->contents != (unsigned char *) isymbuf) -+ { -+ if (! link_info->keep_memory) -+ free (isymbuf); -+ else -+ { -+ /* Cache the symbols for elf_link_input_bfd. */ -+ symtab_hdr->contents = (unsigned char *) isymbuf; -+ } -+ } -+ -+ if (contents != NULL -+ && elf_section_data (isec)->this_hdr.contents != contents) -+ { -+ if (!changes && !link_info->keep_memory) -+ free (contents); -+ else -+ { -+ /* Cache the section contents for elf_link_input_bfd. */ -+ elf_section_data (isec)->this_hdr.contents = contents; -+ } -+ } -+ -+ if (changes != 0) -+ { -+ /* Append sufficient NOP relocs so we can write out relocation -+ information for the trampolines. */ -+ Elf_Internal_Shdr *rel_hdr; -+ Elf_Internal_Rela *new_relocs = bfd_malloc ((changes + isec->reloc_count) -+ * sizeof (*new_relocs)); -+ unsigned ix; -+ -+ if (!new_relocs) -+ goto error_return; -+ memcpy (new_relocs, internal_relocs, -+ isec->reloc_count * sizeof (*new_relocs)); -+ for (ix = changes; ix--;) -+ { -+ irel = new_relocs + ix + isec->reloc_count; -+ -+ irel->r_info = ELF32_R_INFO (0, R_PPC_NONE); -+ } -+ if (internal_relocs != elf_section_data (isec)->relocs) -+ free (internal_relocs); -+ elf_section_data (isec)->relocs = new_relocs; -+ isec->reloc_count += changes; -+ rel_hdr = _bfd_elf_single_rel_hdr (isec); -+ rel_hdr->sh_size += changes * rel_hdr->sh_entsize; -+ } -+ else if (elf_section_data (isec)->relocs != internal_relocs) -+ free (internal_relocs); -+ -+ *again = changes != 0; -+ if (!*again && link_info->relocatable) -+ { -+ /* Convert the internal relax relocs to external form. */ -+ for (irel = internal_relocs; irel < irelend; irel++) -+ if (ELF32_R_TYPE (irel->r_info) == R_PPC_RELAX) -+ { -+ unsigned long r_symndx = ELF32_R_SYM (irel->r_info); -+ -+ /* Rewrite the reloc and convert one of the trailing nop -+ relocs to describe this relocation. */ -+ BFD_ASSERT (ELF32_R_TYPE (irelend[-1].r_info) == R_PPC_NONE); -+ /* The relocs are at the bottom 2 bytes */ -+ irel[0].r_offset += 2; -+ memmove (irel + 1, irel, (irelend - irel - 1) * sizeof (*irel)); -+ irel[0].r_info = ELF32_R_INFO (r_symndx, R_PPC_ADDR16_HA); -+ irel[1].r_offset += 4; -+ irel[1].r_info = ELF32_R_INFO (r_symndx, R_PPC_ADDR16_LO); -+ irel++; -+ } -+ } -+ -+ return TRUE; -+ -+ error_return: -+ if (isymbuf != NULL && (unsigned char *) isymbuf != symtab_hdr->contents) -+ free (isymbuf); -+ if (contents != NULL -+ && elf_section_data (isec)->this_hdr.contents != contents) -+ free (contents); -+ if (internal_relocs != NULL -+ && elf_section_data (isec)->relocs != internal_relocs) -+ free (internal_relocs); -+ return FALSE; -+} -+ -+/* What to do when ld finds relocations against symbols defined in -+ discarded sections. */ -+ -+static unsigned int -+ppc_elf_action_discarded (asection *sec) -+{ -+ if (strcmp (".fixup", sec->name) == 0) -+ return 0; -+ -+ if (strcmp (".got2", sec->name) == 0) -+ return 0; -+ -+ return _bfd_elf_default_action_discarded (sec); -+} -+ -+/* Fill in the address for a pointer generated in a linker section. */ -+ -+static bfd_vma -+elf_finish_pointer_linker_section (bfd *input_bfd, -+ elf_linker_section_t *lsect, -+ struct elf_link_hash_entry *h, -+ bfd_vma relocation, -+ const Elf_Internal_Rela *rel) -+{ -+ elf_linker_section_pointers_t *linker_section_ptr; -+ -+ BFD_ASSERT (lsect != NULL); -+ -+ if (h != NULL) -+ { -+ /* Handle global symbol. */ -+ struct ppc_elf_link_hash_entry *eh; -+ -+ eh = (struct ppc_elf_link_hash_entry *) h; -+ BFD_ASSERT (eh->elf.def_regular); -+ linker_section_ptr = eh->linker_section_pointer; -+ } -+ else -+ { -+ /* Handle local symbol. */ -+ unsigned long r_symndx = ELF32_R_SYM (rel->r_info); -+ -+ BFD_ASSERT (is_ppc_elf (input_bfd)); -+ BFD_ASSERT (elf_local_ptr_offsets (input_bfd) != NULL); -+ linker_section_ptr = elf_local_ptr_offsets (input_bfd)[r_symndx]; -+ } -+ -+ linker_section_ptr = elf_find_pointer_linker_section (linker_section_ptr, -+ rel->r_addend, -+ lsect); -+ BFD_ASSERT (linker_section_ptr != NULL); -+ -+ /* Offset will always be a multiple of four, so use the bottom bit -+ as a "written" flag. */ -+ if ((linker_section_ptr->offset & 1) == 0) -+ { -+ bfd_put_32 (lsect->section->owner, -+ relocation + linker_section_ptr->addend, -+ lsect->section->contents + linker_section_ptr->offset); -+ linker_section_ptr->offset += 1; -+ } -+ -+ relocation = (lsect->section->output_section->vma -+ + lsect->section->output_offset -+ + linker_section_ptr->offset - 1 -+ - SYM_VAL (lsect->sym)); -+ -+#ifdef DEBUG -+ fprintf (stderr, -+ "Finish pointer in linker section %s, offset = %ld (0x%lx)\n", -+ lsect->name, (long) relocation, (long) relocation); -+#endif -+ -+ return relocation; -+} -+ -+#define PPC_LO(v) ((v) & 0xffff) -+#define PPC_HI(v) (((v) >> 16) & 0xffff) -+#define PPC_HA(v) PPC_HI ((v) + 0x8000) -+ -+static void -+write_glink_stub (struct plt_entry *ent, asection *plt_sec, unsigned char *p, -+ struct bfd_link_info *info) -+{ -+ struct ppc_elf_link_hash_table *htab = ppc_elf_hash_table (info); -+ bfd *output_bfd = info->output_bfd; -+ bfd_vma plt; -+ -+ plt = ((ent->plt.offset & ~1) -+ + plt_sec->output_section->vma -+ + plt_sec->output_offset); -+ -+ if (info->shared) -+ { -+ bfd_vma got = 0; -+ -+ if (ent->addend >= 32768) -+ got = (ent->addend -+ + ent->sec->output_section->vma -+ + ent->sec->output_offset); -+ else if (htab->elf.hgot != NULL) -+ got = SYM_VAL (htab->elf.hgot); -+ -+ plt -= got; -+ -+ if (plt + 0x8000 < 0x10000) -+ { -+ bfd_put_32 (output_bfd, LWZ_11_30 + PPC_LO (plt), p); -+ p += 4; -+ bfd_put_32 (output_bfd, MTCTR_11, p); -+ p += 4; -+ bfd_put_32 (output_bfd, BCTR, p); -+ p += 4; -+ bfd_put_32 (output_bfd, NOP, p); -+ p += 4; -+ } -+ else -+ { -+ bfd_put_32 (output_bfd, ADDIS_11_30 + PPC_HA (plt), p); -+ p += 4; -+ bfd_put_32 (output_bfd, LWZ_11_11 + PPC_LO (plt), p); -+ p += 4; -+ bfd_put_32 (output_bfd, MTCTR_11, p); -+ p += 4; -+ bfd_put_32 (output_bfd, BCTR, p); -+ p += 4; -+ } -+ } -+ else -+ { -+ bfd_put_32 (output_bfd, LIS_11 + PPC_HA (plt), p); -+ p += 4; -+ bfd_put_32 (output_bfd, LWZ_11_11 + PPC_LO (plt), p); -+ p += 4; -+ bfd_put_32 (output_bfd, MTCTR_11, p); -+ p += 4; -+ bfd_put_32 (output_bfd, BCTR, p); -+ p += 4; -+ } -+} -+ -+/* Return true if symbol is defined statically. */ -+ -+static bfd_boolean -+is_static_defined (struct elf_link_hash_entry *h) -+{ -+ return ((h->root.type == bfd_link_hash_defined -+ || h->root.type == bfd_link_hash_defweak) -+ && h->root.u.def.section != NULL -+ && h->root.u.def.section->output_section != NULL); -+} -+ -+/* If INSN is an opcode that may be used with an @tls operand, return -+ the transformed insn for TLS optimisation, otherwise return 0. If -+ REG is non-zero only match an insn with RB or RA equal to REG. */ -+ -+unsigned int -+_bfd_elf_amigaos_ppc_at_tls_transform (unsigned int insn, unsigned int reg) -+{ -+ unsigned int rtra; -+ -+ if ((insn & (0x3f << 26)) != 31 << 26) -+ return 0; -+ -+ if (reg == 0 || ((insn >> 11) & 0x1f) == reg) -+ rtra = insn & ((1 << 26) - (1 << 16)); -+ else if (((insn >> 16) & 0x1f) == reg) -+ rtra = (insn & (0x1f << 21)) | ((insn & (0x1f << 11)) << 5); -+ else -+ return 0; -+ -+ if ((insn & (0x3ff << 1)) == 266 << 1) -+ /* add -> addi. */ -+ insn = 14 << 26; -+ else if ((insn & (0x1f << 1)) == 23 << 1 -+ && ((insn & (0x1f << 6)) < 14 << 6 -+ || ((insn & (0x1f << 6)) >= 16 << 6 -+ && (insn & (0x1f << 6)) < 24 << 6))) -+ /* load and store indexed -> dform. */ -+ insn = (32 | ((insn >> 6) & 0x1f)) << 26; -+ else if ((insn & (((0x1a << 5) | 0x1f) << 1)) == 21 << 1) -+ /* ldx, ldux, stdx, stdux -> ld, ldu, std, stdu. */ -+ insn = ((58 | ((insn >> 6) & 4)) << 26) | ((insn >> 6) & 1); -+ else if ((insn & (((0x1f << 5) | 0x1f) << 1)) == 341 << 1) -+ /* lwax -> lwa. */ -+ insn = (58 << 26) | 2; -+ else -+ return 0; -+ insn |= rtra; -+ return insn; -+} -+ -+/* If INSN is an opcode that may be used with an @tprel operand, return -+ the transformed insn for an undefined weak symbol, ie. with the -+ thread pointer REG operand removed. Otherwise return 0. */ -+ -+unsigned int -+_bfd_elf_amigaos_ppc_at_tprel_transform (unsigned int insn, unsigned int reg) -+{ -+ if ((insn & (0x1f << 16)) == reg << 16 -+ && ((insn & (0x3f << 26)) == 14u << 26 /* addi */ -+ || (insn & (0x3f << 26)) == 15u << 26 /* addis */ -+ || (insn & (0x3f << 26)) == 32u << 26 /* lwz */ -+ || (insn & (0x3f << 26)) == 34u << 26 /* lbz */ -+ || (insn & (0x3f << 26)) == 36u << 26 /* stw */ -+ || (insn & (0x3f << 26)) == 38u << 26 /* stb */ -+ || (insn & (0x3f << 26)) == 40u << 26 /* lhz */ -+ || (insn & (0x3f << 26)) == 42u << 26 /* lha */ -+ || (insn & (0x3f << 26)) == 44u << 26 /* sth */ -+ || (insn & (0x3f << 26)) == 46u << 26 /* lmw */ -+ || (insn & (0x3f << 26)) == 47u << 26 /* stmw */ -+ || (insn & (0x3f << 26)) == 48u << 26 /* lfs */ -+ || (insn & (0x3f << 26)) == 50u << 26 /* lfd */ -+ || (insn & (0x3f << 26)) == 52u << 26 /* stfs */ -+ || (insn & (0x3f << 26)) == 54u << 26 /* stfd */ -+ || ((insn & (0x3f << 26)) == 58u << 26 /* lwa,ld,lmd */ -+ && (insn & 3) != 1) -+ || ((insn & (0x3f << 26)) == 62u << 26 /* std, stmd */ -+ && ((insn & 3) == 0 || (insn & 3) == 3)))) -+ { -+ insn &= ~(0x1f << 16); -+ } -+ else if ((insn & (0x1f << 21)) == reg << 21 -+ && ((insn & (0x3e << 26)) == 24u << 26 /* ori, oris */ -+ || (insn & (0x3e << 26)) == 26u << 26 /* xori,xoris */ -+ || (insn & (0x3e << 26)) == 28u << 26 /* andi,andis */)) -+ { -+ insn &= ~(0x1f << 21); -+ insn |= (insn & (0x1f << 16)) << 5; -+ if ((insn & (0x3e << 26)) == 26 << 26 /* xori,xoris */) -+ insn -= 2 >> 26; /* convert to ori,oris */ -+ } -+ else -+ insn = 0; -+ return insn; -+} -+ -+static bfd_boolean -+is_insn_ds_form (unsigned int insn) -+{ -+ return ((insn & (0x3f << 26)) == 58u << 26 /* ld,ldu,lwa */ -+ || (insn & (0x3f << 26)) == 62u << 26 /* std,stdu,stq */ -+ || (insn & (0x3f << 26)) == 57u << 26 /* lfdp */ -+ || (insn & (0x3f << 26)) == 61u << 26 /* stfdp */); -+} -+ -+static bfd_boolean -+is_insn_dq_form (unsigned int insn) -+{ -+ return (insn & (0x3f << 26)) == 56u << 26; /* lq */ -+} -+ -+/* The RELOCATE_SECTION function is called by the ELF backend linker -+ to handle the relocations for a section. -+ -+ The relocs are always passed as Rela structures; if the section -+ actually uses Rel structures, the r_addend field will always be -+ zero. -+ -+ This function is responsible for adjust the section contents as -+ necessary, and (if using Rela relocs and generating a -+ relocatable output file) adjusting the reloc addend as -+ necessary. -+ -+ This function does not have to worry about setting the reloc -+ address or the reloc symbol index. -+ -+ LOCAL_SYMS is a pointer to the swapped in local symbols. -+ -+ LOCAL_SECTIONS is an array giving the section in the input file -+ corresponding to the st_shndx field of each local symbol. -+ -+ The global hash table entry for the global symbols can be found -+ via elf_sym_hashes (input_bfd). -+ -+ When generating relocatable output, this function must handle -+ STB_LOCAL/STT_SECTION symbols specially. The output symbol is -+ going to be the section symbol corresponding to the output -+ section, which means that the addend must be adjusted -+ accordingly. */ -+ -+static bfd_boolean -+ppc_elf_relocate_section (bfd *output_bfd, -+ struct bfd_link_info *info, -+ bfd *input_bfd, -+ asection *input_section, -+ bfd_byte *contents, -+ Elf_Internal_Rela *relocs, -+ Elf_Internal_Sym *local_syms, -+ asection **local_sections) -+{ -+ Elf_Internal_Shdr *symtab_hdr; -+ struct elf_link_hash_entry **sym_hashes; -+ struct ppc_elf_link_hash_table *htab; -+ Elf_Internal_Rela *rel; -+ Elf_Internal_Rela *relend; -+ Elf_Internal_Rela outrel; -+ asection *got2, *sreloc = NULL; -+ bfd_vma *local_got_offsets; -+ bfd_boolean ret = TRUE; -+ bfd_vma d_offset = (bfd_big_endian (output_bfd) ? 2 : 0); -+ bfd_boolean is_vxworks_tls; -+ -+#ifdef DEBUG -+ _bfd_error_handler ("ppc_elf_relocate_section called for %B section %A, " -+ "%ld relocations%s", -+ input_bfd, input_section, -+ (long) input_section->reloc_count, -+ (info->relocatable) ? " (relocatable)" : ""); -+#endif -+ -+ got2 = bfd_get_section_by_name (input_bfd, ".got2"); -+ -+ /* Initialize howto table if not already done. */ -+ if (!ppc_elf_howto_table[R_PPC_ADDR32]) -+ ppc_elf_howto_init (); -+ -+ htab = ppc_elf_hash_table (info); -+ local_got_offsets = elf_local_got_offsets (input_bfd); -+ symtab_hdr = &elf_symtab_hdr (input_bfd); -+ sym_hashes = elf_sym_hashes (input_bfd); -+ /* We have to handle relocations in vxworks .tls_vars sections -+ specially, because the dynamic loader is 'weird'. */ -+ is_vxworks_tls = (htab->is_vxworks && info->shared -+ && !strcmp (input_section->output_section->name, -+ ".tls_vars")); -+ rel = relocs; -+ relend = relocs + input_section->reloc_count; -+ for (; rel < relend; rel++) -+ { -+ enum elf_ppc_reloc_type r_type; -+ bfd_vma addend; -+ bfd_reloc_status_type r; -+ Elf_Internal_Sym *sym; -+ asection *sec; -+ struct elf_link_hash_entry *h; -+ const char *sym_name; -+ reloc_howto_type *howto; -+ unsigned long r_symndx; -+ bfd_vma relocation; -+ bfd_vma branch_bit, from; -+ bfd_boolean unresolved_reloc; -+ bfd_boolean warned; -+ unsigned int tls_type, tls_mask, tls_gd; -+ struct plt_entry **ifunc; -+ -+ r_type = ELF32_R_TYPE (rel->r_info); -+ sym = NULL; -+ sec = NULL; -+ h = NULL; -+ unresolved_reloc = FALSE; -+ warned = FALSE; -+ r_symndx = ELF32_R_SYM (rel->r_info); -+ -+ if (r_symndx < symtab_hdr->sh_info) -+ { -+ sym = local_syms + r_symndx; -+ sec = local_sections[r_symndx]; -+ sym_name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym, sec); -+ -+ relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel); -+ } -+ else -+ { -+ RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, -+ r_symndx, symtab_hdr, sym_hashes, -+ h, sec, relocation, -+ unresolved_reloc, warned); -+ -+ sym_name = h->root.root.string; -+ } -+ -+ if (sec != NULL && discarded_section (sec)) -+ { -+ /* For relocs against symbols from removed linkonce sections, -+ or sections discarded by a linker script, we just want the -+ section contents zeroed. Avoid any special processing. */ -+ howto = NULL; -+ if (r_type < R_PPC_max) -+ howto = ppc_elf_howto_table[r_type]; -+ RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section, -+ rel, 1, relend, howto, 0, contents); -+ } -+ -+ if (info->relocatable) -+ { -+ if (got2 != NULL -+ && r_type == R_PPC_PLTREL24 -+ && rel->r_addend != 0) -+ { -+ /* R_PPC_PLTREL24 is rather special. If non-zero, the -+ addend specifies the GOT pointer offset within .got2. */ -+ rel->r_addend += got2->output_offset; -+ } -+ continue; -+ } -+ -+ /* TLS optimizations. Replace instruction sequences and relocs -+ based on information we collected in tls_optimize. We edit -+ RELOCS so that --emit-relocs will output something sensible -+ for the final instruction stream. */ -+ tls_mask = 0; -+ tls_gd = 0; -+ if (h != NULL) -+ tls_mask = ((struct ppc_elf_link_hash_entry *) h)->tls_mask; -+ else if (local_got_offsets != NULL) -+ { -+ struct plt_entry **local_plt; -+ char *lgot_masks; -+ local_plt -+ = (struct plt_entry **) (local_got_offsets + symtab_hdr->sh_info); -+ lgot_masks = (char *) (local_plt + symtab_hdr->sh_info); -+ tls_mask = lgot_masks[r_symndx]; -+ } -+ -+ /* Ensure reloc mapping code below stays sane. */ -+ if ((R_PPC_GOT_TLSLD16 & 3) != (R_PPC_GOT_TLSGD16 & 3) -+ || (R_PPC_GOT_TLSLD16_LO & 3) != (R_PPC_GOT_TLSGD16_LO & 3) -+ || (R_PPC_GOT_TLSLD16_HI & 3) != (R_PPC_GOT_TLSGD16_HI & 3) -+ || (R_PPC_GOT_TLSLD16_HA & 3) != (R_PPC_GOT_TLSGD16_HA & 3) -+ || (R_PPC_GOT_TLSLD16 & 3) != (R_PPC_GOT_TPREL16 & 3) -+ || (R_PPC_GOT_TLSLD16_LO & 3) != (R_PPC_GOT_TPREL16_LO & 3) -+ || (R_PPC_GOT_TLSLD16_HI & 3) != (R_PPC_GOT_TPREL16_HI & 3) -+ || (R_PPC_GOT_TLSLD16_HA & 3) != (R_PPC_GOT_TPREL16_HA & 3)) -+ abort (); -+ switch (r_type) -+ { -+ default: -+ break; -+ -+ case R_PPC_GOT_TPREL16: -+ case R_PPC_GOT_TPREL16_LO: -+ if ((tls_mask & TLS_TLS) != 0 -+ && (tls_mask & TLS_TPREL) == 0) -+ { -+ bfd_vma insn; -+ -+ insn = bfd_get_32 (output_bfd, contents + rel->r_offset - d_offset); -+ insn &= 31 << 21; -+ insn |= 0x3c020000; /* addis 0,2,0 */ -+ bfd_put_32 (output_bfd, insn, contents + rel->r_offset - d_offset); -+ r_type = R_PPC_TPREL16_HA; -+ rel->r_info = ELF32_R_INFO (r_symndx, r_type); -+ } -+ break; -+ -+ case R_PPC_TLS: -+ if ((tls_mask & TLS_TLS) != 0 -+ && (tls_mask & TLS_TPREL) == 0) -+ { -+ bfd_vma insn; -+ -+ insn = bfd_get_32 (output_bfd, contents + rel->r_offset); -+ insn = _bfd_elf_ppc_at_tls_transform (insn, 2); -+ if (insn == 0) -+ abort (); -+ bfd_put_32 (output_bfd, insn, contents + rel->r_offset); -+ r_type = R_PPC_TPREL16_LO; -+ rel->r_info = ELF32_R_INFO (r_symndx, r_type); -+ -+ /* Was PPC_TLS which sits on insn boundary, now -+ PPC_TPREL16_LO which is at low-order half-word. */ -+ rel->r_offset += d_offset; -+ } -+ break; -+ -+ case R_PPC_GOT_TLSGD16_HI: -+ case R_PPC_GOT_TLSGD16_HA: -+ tls_gd = TLS_TPRELGD; -+ if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_GD) == 0) -+ goto tls_gdld_hi; -+ break; -+ -+ case R_PPC_GOT_TLSLD16_HI: -+ case R_PPC_GOT_TLSLD16_HA: -+ if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_LD) == 0) -+ { -+ tls_gdld_hi: -+ if ((tls_mask & tls_gd) != 0) -+ r_type = (((r_type - (R_PPC_GOT_TLSGD16 & 3)) & 3) -+ + R_PPC_GOT_TPREL16); -+ else -+ { -+ bfd_put_32 (output_bfd, NOP, contents + rel->r_offset); -+ rel->r_offset -= d_offset; -+ r_type = R_PPC_NONE; -+ } -+ rel->r_info = ELF32_R_INFO (r_symndx, r_type); -+ } -+ break; -+ -+ case R_PPC_GOT_TLSGD16: -+ case R_PPC_GOT_TLSGD16_LO: -+ tls_gd = TLS_TPRELGD; -+ if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_GD) == 0) -+ goto tls_ldgd_opt; -+ break; -+ -+ case R_PPC_GOT_TLSLD16: -+ case R_PPC_GOT_TLSLD16_LO: -+ if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_LD) == 0) -+ { -+ unsigned int insn1, insn2; -+ bfd_vma offset; -+ -+ tls_ldgd_opt: -+ offset = (bfd_vma) -1; -+ /* If not using the newer R_PPC_TLSGD/LD to mark -+ __tls_get_addr calls, we must trust that the call -+ stays with its arg setup insns, ie. that the next -+ reloc is the __tls_get_addr call associated with -+ the current reloc. Edit both insns. */ -+ if (input_section->has_tls_get_addr_call -+ && rel + 1 < relend -+ && branch_reloc_hash_match (input_bfd, rel + 1, -+ htab->tls_get_addr)) -+ offset = rel[1].r_offset; -+ if ((tls_mask & tls_gd) != 0) -+ { -+ /* IE */ -+ insn1 = bfd_get_32 (output_bfd, -+ contents + rel->r_offset - d_offset); -+ insn1 &= (1 << 26) - 1; -+ insn1 |= 32 << 26; /* lwz */ -+ if (offset != (bfd_vma) -1) -+ { -+ rel[1].r_info = ELF32_R_INFO (STN_UNDEF, R_PPC_NONE); -+ insn2 = 0x7c631214; /* add 3,3,2 */ -+ bfd_put_32 (output_bfd, insn2, contents + offset); -+ } -+ r_type = (((r_type - (R_PPC_GOT_TLSGD16 & 3)) & 3) -+ + R_PPC_GOT_TPREL16); -+ rel->r_info = ELF32_R_INFO (r_symndx, r_type); -+ } -+ else -+ { -+ /* LE */ -+ insn1 = 0x3c620000; /* addis 3,2,0 */ -+ if (tls_gd == 0) -+ { -+ /* Was an LD reloc. */ -+ for (r_symndx = 0; -+ r_symndx < symtab_hdr->sh_info; -+ r_symndx++) -+ if (local_sections[r_symndx] == sec) -+ break; -+ if (r_symndx >= symtab_hdr->sh_info) -+ r_symndx = STN_UNDEF; -+ rel->r_addend = htab->elf.tls_sec->vma + DTP_OFFSET; -+ if (r_symndx != STN_UNDEF) -+ rel->r_addend -= (local_syms[r_symndx].st_value -+ + sec->output_offset -+ + sec->output_section->vma); -+ } -+ r_type = R_PPC_TPREL16_HA; -+ rel->r_info = ELF32_R_INFO (r_symndx, r_type); -+ if (offset != (bfd_vma) -1) -+ { -+ rel[1].r_info = ELF32_R_INFO (r_symndx, R_PPC_TPREL16_LO); -+ rel[1].r_offset = offset + d_offset; -+ rel[1].r_addend = rel->r_addend; -+ insn2 = 0x38630000; /* addi 3,3,0 */ -+ bfd_put_32 (output_bfd, insn2, contents + offset); -+ } -+ } -+ bfd_put_32 (output_bfd, insn1, -+ contents + rel->r_offset - d_offset); -+ if (tls_gd == 0) -+ { -+ /* We changed the symbol on an LD reloc. Start over -+ in order to get h, sym, sec etc. right. */ -+ rel--; -+ continue; -+ } -+ } -+ break; -+ -+ case R_PPC_TLSGD: -+ if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_GD) == 0) -+ { -+ unsigned int insn2; -+ bfd_vma offset = rel->r_offset; -+ -+ if ((tls_mask & TLS_TPRELGD) != 0) -+ { -+ /* IE */ -+ r_type = R_PPC_NONE; -+ insn2 = 0x7c631214; /* add 3,3,2 */ -+ } -+ else -+ { -+ /* LE */ -+ r_type = R_PPC_TPREL16_LO; -+ rel->r_offset += d_offset; -+ insn2 = 0x38630000; /* addi 3,3,0 */ -+ } -+ rel->r_info = ELF32_R_INFO (r_symndx, r_type); -+ bfd_put_32 (output_bfd, insn2, contents + offset); -+ /* Zap the reloc on the _tls_get_addr call too. */ -+ BFD_ASSERT (offset == rel[1].r_offset); -+ rel[1].r_info = ELF32_R_INFO (STN_UNDEF, R_PPC_NONE); -+ } -+ break; -+ -+ case R_PPC_TLSLD: -+ if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_LD) == 0) -+ { -+ unsigned int insn2; -+ -+ for (r_symndx = 0; -+ r_symndx < symtab_hdr->sh_info; -+ r_symndx++) -+ if (local_sections[r_symndx] == sec) -+ break; -+ if (r_symndx >= symtab_hdr->sh_info) -+ r_symndx = STN_UNDEF; -+ rel->r_addend = htab->elf.tls_sec->vma + DTP_OFFSET; -+ if (r_symndx != STN_UNDEF) -+ rel->r_addend -= (local_syms[r_symndx].st_value -+ + sec->output_offset -+ + sec->output_section->vma); -+ -+ rel->r_info = ELF32_R_INFO (r_symndx, R_PPC_TPREL16_LO); -+ rel->r_offset += d_offset; -+ insn2 = 0x38630000; /* addi 3,3,0 */ -+ bfd_put_32 (output_bfd, insn2, -+ contents + rel->r_offset - d_offset); -+ /* Zap the reloc on the _tls_get_addr call too. */ -+ BFD_ASSERT (rel->r_offset - d_offset == rel[1].r_offset); -+ rel[1].r_info = ELF32_R_INFO (STN_UNDEF, R_PPC_NONE); -+ rel--; -+ continue; -+ } -+ break; -+ } -+ -+ /* Handle other relocations that tweak non-addend part of insn. */ -+ branch_bit = 0; -+ switch (r_type) -+ { -+ default: -+ break; -+ -+ /* Branch taken prediction relocations. */ -+ case R_PPC_ADDR14_BRTAKEN: -+ case R_PPC_REL14_BRTAKEN: -+ branch_bit = BRANCH_PREDICT_BIT; -+ /* Fall thru */ -+ -+ /* Branch not taken prediction relocations. */ -+ case R_PPC_ADDR14_BRNTAKEN: -+ case R_PPC_REL14_BRNTAKEN: -+ { -+ bfd_vma insn; -+ -+ insn = bfd_get_32 (output_bfd, contents + rel->r_offset); -+ insn &= ~BRANCH_PREDICT_BIT; -+ insn |= branch_bit; -+ -+ from = (rel->r_offset -+ + input_section->output_offset -+ + input_section->output_section->vma); -+ -+ /* Invert 'y' bit if not the default. */ -+ if ((bfd_signed_vma) (relocation + rel->r_addend - from) < 0) -+ insn ^= BRANCH_PREDICT_BIT; -+ -+ bfd_put_32 (output_bfd, insn, contents + rel->r_offset); -+ break; -+ } -+ } -+ -+ ifunc = NULL; -+ if (!htab->is_vxworks) -+ { -+ struct plt_entry *ent; -+ -+ if (h != NULL) -+ { -+ if (h->type == STT_GNU_IFUNC) -+ ifunc = &h->plt.plist; -+ } -+ else if (local_got_offsets != NULL -+ && ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC) -+ { -+ struct plt_entry **local_plt; -+ -+ local_plt = (struct plt_entry **) (local_got_offsets -+ + symtab_hdr->sh_info); -+ ifunc = local_plt + r_symndx; -+ } -+ -+ ent = NULL; -+ if (ifunc != NULL -+ && (!info->shared -+ || is_branch_reloc (r_type))) -+ { -+ addend = 0; -+ if (r_type == R_PPC_PLTREL24 && info->shared) -+ addend = rel->r_addend; -+ ent = find_plt_ent (ifunc, got2, addend); -+ } -+ if (ent != NULL) -+ { -+ if (h == NULL && (ent->plt.offset & 1) == 0) -+ { -+ Elf_Internal_Rela rela; -+ bfd_byte *loc; -+ -+ rela.r_offset = (htab->iplt->output_section->vma -+ + htab->iplt->output_offset -+ + ent->plt.offset); -+ rela.r_info = ELF32_R_INFO (0, R_PPC_IRELATIVE); -+ rela.r_addend = relocation; -+ loc = htab->reliplt->contents; -+ loc += (htab->reliplt->reloc_count++ -+ * sizeof (Elf32_External_Rela)); -+ bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); -+ -+ ent->plt.offset |= 1; -+ } -+ if (h == NULL && (ent->glink_offset & 1) == 0) -+ { -+ unsigned char *p = ((unsigned char *) htab->glink->contents -+ + ent->glink_offset); -+ write_glink_stub (ent, htab->iplt, p, info); -+ ent->glink_offset |= 1; -+ } -+ -+ unresolved_reloc = FALSE; -+ if (htab->plt_type == PLT_NEW -+ || !htab->elf.dynamic_sections_created -+ || h == NULL) -+ relocation = (htab->glink->output_section->vma -+ + htab->glink->output_offset -+ + (ent->glink_offset & ~1)); -+ else -+ relocation = (htab->plt->output_section->vma -+ + htab->plt->output_offset -+ + ent->plt.offset); -+ } -+ } -+ -+ addend = rel->r_addend; -+ tls_type = 0; -+ howto = NULL; -+ if (r_type < R_PPC_max) -+ howto = ppc_elf_howto_table[r_type]; -+ switch (r_type) -+ { -+ default: -+ info->callbacks->einfo -+ (_("%P: %B: unknown relocation type %d for symbol %s\n"), -+ input_bfd, (int) r_type, sym_name); -+ -+ bfd_set_error (bfd_error_bad_value); -+ ret = FALSE; -+ continue; -+ -+ case R_PPC_NONE: -+ case R_PPC_TLS: -+ case R_PPC_TLSGD: -+ case R_PPC_TLSLD: -+ case R_PPC_EMB_MRKREF: -+ case R_PPC_GNU_VTINHERIT: -+ case R_PPC_GNU_VTENTRY: -+ continue; -+ -+ /* GOT16 relocations. Like an ADDR16 using the symbol's -+ address in the GOT as relocation value instead of the -+ symbol's value itself. Also, create a GOT entry for the -+ symbol and put the symbol value there. */ -+ case R_PPC_GOT_TLSGD16: -+ case R_PPC_GOT_TLSGD16_LO: -+ case R_PPC_GOT_TLSGD16_HI: -+ case R_PPC_GOT_TLSGD16_HA: -+ tls_type = TLS_TLS | TLS_GD; -+ goto dogot; -+ -+ case R_PPC_GOT_TLSLD16: -+ case R_PPC_GOT_TLSLD16_LO: -+ case R_PPC_GOT_TLSLD16_HI: -+ case R_PPC_GOT_TLSLD16_HA: -+ tls_type = TLS_TLS | TLS_LD; -+ goto dogot; -+ -+ case R_PPC_GOT_TPREL16: -+ case R_PPC_GOT_TPREL16_LO: -+ case R_PPC_GOT_TPREL16_HI: -+ case R_PPC_GOT_TPREL16_HA: -+ tls_type = TLS_TLS | TLS_TPREL; -+ goto dogot; -+ -+ case R_PPC_GOT_DTPREL16: -+ case R_PPC_GOT_DTPREL16_LO: -+ case R_PPC_GOT_DTPREL16_HI: -+ case R_PPC_GOT_DTPREL16_HA: -+ tls_type = TLS_TLS | TLS_DTPREL; -+ goto dogot; -+ -+ case R_PPC_GOT16: -+ case R_PPC_GOT16_LO: -+ case R_PPC_GOT16_HI: -+ case R_PPC_GOT16_HA: -+ tls_mask = 0; -+ dogot: -+ { -+ /* Relocation is to the entry for this symbol in the global -+ offset table. */ -+ bfd_vma off; -+ bfd_vma *offp; -+ unsigned long indx; -+ -+ if (htab->got == NULL) -+ abort (); -+ -+ indx = 0; -+ if (tls_type == (TLS_TLS | TLS_LD) -+ && (h == NULL -+ || !h->def_dynamic)) -+ offp = &htab->tlsld_got.offset; -+ else if (h != NULL) -+ { -+ bfd_boolean dyn; -+ dyn = htab->elf.dynamic_sections_created; -+ if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h) -+ || (info->shared -+ && SYMBOL_REFERENCES_LOCAL (info, h))) -+ /* This is actually a static link, or it is a -+ -Bsymbolic link and the symbol is defined -+ locally, or the symbol was forced to be local -+ because of a version file. */ -+ ; -+ else -+ { -+ BFD_ASSERT (h->dynindx != -1); -+ indx = h->dynindx; -+ unresolved_reloc = FALSE; -+ } -+ offp = &h->got.offset; -+ } -+ else -+ { -+ if (local_got_offsets == NULL) -+ abort (); -+ offp = &local_got_offsets[r_symndx]; -+ } -+ -+ /* The offset must always be a multiple of 4. We use the -+ least significant bit to record whether we have already -+ processed this entry. */ -+ off = *offp; -+ if ((off & 1) != 0) -+ off &= ~1; -+ else -+ { -+ unsigned int tls_m = (tls_mask -+ & (TLS_LD | TLS_GD | TLS_DTPREL -+ | TLS_TPREL | TLS_TPRELGD)); -+ -+ if (offp == &htab->tlsld_got.offset) -+ tls_m = TLS_LD; -+ else if (h == NULL -+ || !h->def_dynamic) -+ tls_m &= ~TLS_LD; -+ -+ /* We might have multiple got entries for this sym. -+ Initialize them all. */ -+ do -+ { -+ int tls_ty = 0; -+ -+ if ((tls_m & TLS_LD) != 0) -+ { -+ tls_ty = TLS_TLS | TLS_LD; -+ tls_m &= ~TLS_LD; -+ } -+ else if ((tls_m & TLS_GD) != 0) -+ { -+ tls_ty = TLS_TLS | TLS_GD; -+ tls_m &= ~TLS_GD; -+ } -+ else if ((tls_m & TLS_DTPREL) != 0) -+ { -+ tls_ty = TLS_TLS | TLS_DTPREL; -+ tls_m &= ~TLS_DTPREL; -+ } -+ else if ((tls_m & (TLS_TPREL | TLS_TPRELGD)) != 0) -+ { -+ tls_ty = TLS_TLS | TLS_TPREL; -+ tls_m = 0; -+ } -+ -+ /* Generate relocs for the dynamic linker. */ -+ if ((info->shared || indx != 0) -+ && (offp == &htab->tlsld_got.offset -+ || h == NULL -+ || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT -+ || h->root.type != bfd_link_hash_undefweak)) -+ { -+ asection *rsec = htab->relgot; -+ bfd_byte * loc; -+ -+ outrel.r_offset = (htab->got->output_section->vma -+ + htab->got->output_offset -+ + off); -+ outrel.r_addend = 0; -+ if (tls_ty & (TLS_LD | TLS_GD)) -+ { -+ outrel.r_info = ELF32_R_INFO (indx, R_PPC_DTPMOD32); -+ if (tls_ty == (TLS_TLS | TLS_GD)) -+ { -+ loc = rsec->contents; -+ loc += (rsec->reloc_count++ -+ * sizeof (Elf32_External_Rela)); -+ bfd_elf32_swap_reloca_out (output_bfd, -+ &outrel, loc); -+ outrel.r_offset += 4; -+ outrel.r_info -+ = ELF32_R_INFO (indx, R_PPC_DTPREL32); -+ } -+ } -+ else if (tls_ty == (TLS_TLS | TLS_DTPREL)) -+ outrel.r_info = ELF32_R_INFO (indx, R_PPC_DTPREL32); -+ else if (tls_ty == (TLS_TLS | TLS_TPREL)) -+ outrel.r_info = ELF32_R_INFO (indx, R_PPC_TPREL32); -+ else if (indx != 0) -+ outrel.r_info = ELF32_R_INFO (indx, R_PPC_GLOB_DAT); -+ else if (ifunc != NULL) -+ outrel.r_info = ELF32_R_INFO (0, R_PPC_IRELATIVE); -+ else -+ outrel.r_info = ELF32_R_INFO (0, R_PPC_RELATIVE); -+ if (indx == 0 && tls_ty != (TLS_TLS | TLS_LD)) -+ { -+ outrel.r_addend += relocation; -+ if (tls_ty & (TLS_GD | TLS_DTPREL | TLS_TPREL)) -+ outrel.r_addend -= htab->elf.tls_sec->vma; -+ } -+ loc = rsec->contents; -+ loc += (rsec->reloc_count++ -+ * sizeof (Elf32_External_Rela)); -+ bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc); -+ } -+ -+ /* Init the .got section contents if we're not -+ emitting a reloc. */ -+ else -+ { -+ bfd_vma value = relocation; -+ -+ if (tls_ty == (TLS_TLS | TLS_LD)) -+ value = 1; -+ else if (tls_ty != 0) -+ { -+ value -= htab->elf.tls_sec->vma + DTP_OFFSET; -+ if (tls_ty == (TLS_TLS | TLS_TPREL)) -+ value += DTP_OFFSET - TP_OFFSET; -+ -+ if (tls_ty == (TLS_TLS | TLS_GD)) -+ { -+ bfd_put_32 (output_bfd, value, -+ htab->got->contents + off + 4); -+ value = 1; -+ } -+ } -+ bfd_put_32 (output_bfd, value, -+ htab->got->contents + off); -+ } -+ -+ off += 4; -+ if (tls_ty & (TLS_LD | TLS_GD)) -+ off += 4; -+ } -+ while (tls_m != 0); -+ -+ off = *offp; -+ *offp = off | 1; -+ } -+ -+ if (off >= (bfd_vma) -2) -+ abort (); -+ -+ if ((tls_type & TLS_TLS) != 0) -+ { -+ if (tls_type != (TLS_TLS | TLS_LD)) -+ { -+ if ((tls_mask & TLS_LD) != 0 -+ && !(h == NULL -+ || !h->def_dynamic)) -+ off += 8; -+ if (tls_type != (TLS_TLS | TLS_GD)) -+ { -+ if ((tls_mask & TLS_GD) != 0) -+ off += 8; -+ if (tls_type != (TLS_TLS | TLS_DTPREL)) -+ { -+ if ((tls_mask & TLS_DTPREL) != 0) -+ off += 4; -+ } -+ } -+ } -+ } -+ -+ relocation = (htab->got->output_section->vma -+ + htab->got->output_offset -+ + off -+ - SYM_VAL (htab->elf.hgot)); -+ -+ /* Addends on got relocations don't make much sense. -+ x+off@got is actually x@got+off, and since the got is -+ generated by a hash table traversal, the value in the -+ got at entry m+n bears little relation to the entry m. */ -+ if (addend != 0) -+ info->callbacks->einfo -+ (_("%P: %H: non-zero addend on %s reloc against `%s'\n"), -+ input_bfd, input_section, rel->r_offset, -+ howto->name, -+ sym_name); -+ } -+ break; -+ -+ /* Relocations that need no special processing. */ -+ case R_PPC_LOCAL24PC: -+ /* It makes no sense to point a local relocation -+ at a symbol not in this object. */ -+ if (unresolved_reloc) -+ { -+ if (! (*info->callbacks->undefined_symbol) (info, -+ h->root.root.string, -+ input_bfd, -+ input_section, -+ rel->r_offset, -+ TRUE)) -+ return FALSE; -+ continue; -+ } -+ break; -+ -+ case R_PPC_DTPREL16: -+ case R_PPC_DTPREL16_LO: -+ case R_PPC_DTPREL16_HI: -+ case R_PPC_DTPREL16_HA: -+ addend -= htab->elf.tls_sec->vma + DTP_OFFSET; -+ break; -+ -+ /* Relocations that may need to be propagated if this is a shared -+ object. */ -+ case R_PPC_TPREL16: -+ case R_PPC_TPREL16_LO: -+ case R_PPC_TPREL16_HI: -+ case R_PPC_TPREL16_HA: -+ if (h != NULL -+ && h->root.type == bfd_link_hash_undefweak -+ && h->dynindx == -1) -+ { -+ /* Make this relocation against an undefined weak symbol -+ resolve to zero. This is really just a tweak, since -+ code using weak externs ought to check that they are -+ defined before using them. */ -+ bfd_byte *p = contents + rel->r_offset - d_offset; -+ unsigned int insn = bfd_get_32 (output_bfd, p); -+ insn = _bfd_elf_amigaos_ppc_at_tprel_transform (insn, 2); -+ if (insn != 0) -+ bfd_put_32 (output_bfd, insn, p); -+ break; -+ } -+ addend -= htab->elf.tls_sec->vma + TP_OFFSET; -+ /* The TPREL16 relocs shouldn't really be used in shared -+ libs as they will result in DT_TEXTREL being set, but -+ support them anyway. */ -+ goto dodyn; -+ -+ case R_PPC_TPREL32: -+ addend -= htab->elf.tls_sec->vma + TP_OFFSET; -+ goto dodyn; -+ -+ case R_PPC_DTPREL32: -+ addend -= htab->elf.tls_sec->vma + DTP_OFFSET; -+ goto dodyn; -+ -+ case R_PPC_DTPMOD32: -+ relocation = 1; -+ addend = 0; -+ goto dodyn; -+ -+ case R_PPC_REL16: -+ case R_PPC_REL16_LO: -+ case R_PPC_REL16_HI: -+ case R_PPC_REL16_HA: -+ break; -+ -+ case R_PPC_REL32: -+ if (h == NULL || h == htab->elf.hgot) -+ break; -+ /* fall through */ -+ -+ case R_PPC_ADDR32: -+ case R_PPC_ADDR16: -+ case R_PPC_ADDR16_LO: -+ case R_PPC_ADDR16_HI: -+ case R_PPC_ADDR16_HA: -+ case R_PPC_UADDR32: -+ case R_PPC_UADDR16: -+ goto dodyn; -+ -+ case R_PPC_VLE_REL8: -+ case R_PPC_VLE_REL15: -+ case R_PPC_VLE_REL24: -+ case R_PPC_REL24: -+ case R_PPC_REL14: -+ case R_PPC_REL14_BRTAKEN: -+ case R_PPC_REL14_BRNTAKEN: -+ /* If these relocations are not to a named symbol, they can be -+ handled right here, no need to bother the dynamic linker. */ -+ if (SYMBOL_CALLS_LOCAL (info, h) -+ || h == htab->elf.hgot) -+ break; -+ /* fall through */ -+ -+ case R_PPC_ADDR24: -+ case R_PPC_ADDR14: -+ case R_PPC_ADDR14_BRTAKEN: -+ case R_PPC_ADDR14_BRNTAKEN: -+ if (h != NULL && !info->shared) -+ break; -+ /* fall through */ -+ -+ dodyn: -+ if ((input_section->flags & SEC_ALLOC) == 0 -+ || is_vxworks_tls) -+ break; -+ -+ if ((info->shared -+ && !(h != NULL -+ && ((h->root.type == bfd_link_hash_undefined -+ && (ELF_ST_VISIBILITY (h->other) == STV_HIDDEN -+ || ELF_ST_VISIBILITY (h->other) == STV_INTERNAL)) -+ || (h->root.type == bfd_link_hash_undefweak -+ && ELF_ST_VISIBILITY (h->other) != STV_DEFAULT))) -+ && (must_be_dyn_reloc (info, r_type) -+ || !SYMBOL_CALLS_LOCAL (info, h))) -+ || (ELIMINATE_COPY_RELOCS -+ && !info->shared -+ && h != NULL -+ && h->dynindx != -1 -+ && !h->non_got_ref -+ && !h->def_regular)) -+ { -+ int skip; -+ bfd_byte * loc; -+#ifdef DEBUG -+ fprintf (stderr, "ppc_elf_relocate_section needs to " -+ "create relocation for %s\n", -+ (h && h->root.root.string -+ ? h->root.root.string : "")); -+#endif -+ -+ /* When generating a shared object, these relocations -+ are copied into the output file to be resolved at run -+ time. */ -+ if (sreloc == NULL) -+ { -+ sreloc = elf_section_data (input_section)->sreloc; -+ if (!htab->elf.dynamic_sections_created) -+ sreloc = htab->reliplt; -+ if (sreloc == NULL) -+ return FALSE; -+ } -+ -+ skip = 0; -+ outrel.r_offset = _bfd_elf_section_offset (output_bfd, info, -+ input_section, -+ rel->r_offset); -+ if (outrel.r_offset == (bfd_vma) -1 -+ || outrel.r_offset == (bfd_vma) -2) -+ skip = (int) outrel.r_offset; -+ outrel.r_offset += (input_section->output_section->vma -+ + input_section->output_offset); -+ -+ if (skip) -+ memset (&outrel, 0, sizeof outrel); -+ else if ((h != NULL -+ && (h->root.type == bfd_link_hash_undefined -+ || h->root.type == bfd_link_hash_undefweak)) -+ || !SYMBOL_REFERENCES_LOCAL (info, h)) -+ { -+ BFD_ASSERT (h->dynindx != -1); -+ unresolved_reloc = FALSE; -+ outrel.r_info = ELF32_R_INFO (h->dynindx, r_type); -+ outrel.r_addend = rel->r_addend; -+ } -+ else -+ { -+ outrel.r_addend = relocation + rel->r_addend; -+ -+ if (r_type != R_PPC_ADDR32) -+ { -+ long indx = 0; -+ -+ if (ifunc != NULL) -+ { -+ /* If we get here when building a static -+ executable, then the libc startup function -+ responsible for applying indirect function -+ relocations is going to complain about -+ the reloc type. -+ If we get here when building a dynamic -+ executable, it will be because we have -+ a text relocation. The dynamic loader -+ will set the text segment writable and -+ non-executable to apply text relocations. -+ So we'll segfault when trying to run the -+ indirection function to resolve the reloc. */ -+ info->callbacks->einfo -+ (_("%P: %H: relocation %s for indirect " -+ "function %s unsupported\n"), -+ input_bfd, input_section, rel->r_offset, -+ howto->name, -+ sym_name); -+ ret = FALSE; -+ } -+ else if (r_symndx == STN_UNDEF || bfd_is_abs_section (sec)) -+ ; -+ else if (sec == NULL || sec->owner == NULL) -+ { -+ bfd_set_error (bfd_error_bad_value); -+ ret = FALSE; -+ } -+ else -+ { -+ asection *osec; -+ -+ /* We are turning this relocation into one -+ against a section symbol. It would be -+ proper to subtract the symbol's value, -+ osec->vma, from the emitted reloc addend, -+ but ld.so expects buggy relocs. -+ FIXME: Why not always use a zero index? */ -+ osec = sec->output_section; -+ indx = elf_section_data (osec)->dynindx; -+ if (indx == 0) -+ { -+ osec = htab->elf.text_index_section; -+ indx = elf_section_data (osec)->dynindx; -+ } -+ BFD_ASSERT (indx != 0); -+#ifdef DEBUG -+ if (indx == 0) -+ printf ("indx=%ld section=%s flags=%08x name=%s\n", -+ indx, osec->name, osec->flags, -+ h->root.root.string); -+#endif -+ } -+ -+ outrel.r_info = ELF32_R_INFO (indx, r_type); -+ } -+ else if (ifunc != NULL) -+ outrel.r_info = ELF32_R_INFO (0, R_PPC_IRELATIVE); -+ else -+ outrel.r_info = ELF32_R_INFO (0, R_PPC_RELATIVE); -+ } -+ -+ loc = sreloc->contents; -+ loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rela); -+ bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc); -+ -+ if (skip == -1) -+ continue; -+ -+ /* This reloc will be computed at runtime. We clear the memory -+ so that it contains predictable value. */ -+ if (! skip -+ && ((input_section->flags & SEC_ALLOC) != 0 -+ || ELF32_R_TYPE (outrel.r_info) != R_PPC_RELATIVE)) -+ { -+ relocation = howto->pc_relative ? outrel.r_offset : 0; -+ addend = 0; -+ break; -+ } -+ } -+ break; -+ -+ case R_PPC_RELAX_PLT: -+ case R_PPC_RELAX_PLTREL24: -+ if (h != NULL) -+ { -+ struct plt_entry *ent; -+ bfd_vma got2_addend = 0; -+ -+ if (r_type == R_PPC_RELAX_PLTREL24) -+ { -+ if (info->shared) -+ got2_addend = addend; -+ addend = 0; -+ } -+ ent = find_plt_ent (&h->plt.plist, got2, got2_addend); -+ if (htab->plt_type == PLT_NEW) -+ relocation = (htab->glink->output_section->vma -+ + htab->glink->output_offset -+ + ent->glink_offset); -+ else -+ relocation = (htab->plt->output_section->vma -+ + htab->plt->output_offset -+ + ent->plt.offset); -+ } -+ /* Fall thru */ -+ -+ case R_PPC_RELAX: -+ if (info->shared) -+ relocation -= (input_section->output_section->vma -+ + input_section->output_offset -+ + rel->r_offset - 4); -+ -+ { -+ unsigned long t0; -+ unsigned long t1; -+ -+ t0 = bfd_get_32 (output_bfd, contents + rel->r_offset); -+ t1 = bfd_get_32 (output_bfd, contents + rel->r_offset + 4); -+ -+ /* We're clearing the bits for R_PPC_ADDR16_HA -+ and R_PPC_ADDR16_LO here. */ -+ t0 &= ~0xffff; -+ t1 &= ~0xffff; -+ -+ /* t0 is HA, t1 is LO */ -+ relocation += addend; -+ t0 |= ((relocation + 0x8000) >> 16) & 0xffff; -+ t1 |= relocation & 0xffff; -+ -+ bfd_put_32 (output_bfd, t0, contents + rel->r_offset); -+ bfd_put_32 (output_bfd, t1, contents + rel->r_offset + 4); -+ -+ /* Rewrite the reloc and convert one of the trailing nop -+ relocs to describe this relocation. */ -+ BFD_ASSERT (ELF32_R_TYPE (relend[-1].r_info) == R_PPC_NONE); -+ /* The relocs are at the bottom 2 bytes */ -+ rel[0].r_offset += 2; -+ memmove (rel + 1, rel, (relend - rel - 1) * sizeof (*rel)); -+ rel[0].r_info = ELF32_R_INFO (r_symndx, R_PPC_ADDR16_HA); -+ rel[1].r_offset += 4; -+ rel[1].r_info = ELF32_R_INFO (r_symndx, R_PPC_ADDR16_LO); -+ rel++; -+ } -+ continue; -+ -+ /* Indirect .sdata relocation. */ -+ case R_PPC_EMB_SDAI16: -+ BFD_ASSERT (htab->sdata[0].section != NULL); -+ if (!is_static_defined (htab->sdata[0].sym)) -+ { -+ unresolved_reloc = TRUE; -+ break; -+ } -+ relocation -+ = elf_finish_pointer_linker_section (input_bfd, &htab->sdata[0], -+ h, relocation, rel); -+ addend = 0; -+ break; -+ -+ /* Indirect .sdata2 relocation. */ -+ case R_PPC_EMB_SDA2I16: -+ BFD_ASSERT (htab->sdata[1].section != NULL); -+ if (!is_static_defined (htab->sdata[1].sym)) -+ { -+ unresolved_reloc = TRUE; -+ break; -+ } -+ relocation -+ = elf_finish_pointer_linker_section (input_bfd, &htab->sdata[1], -+ h, relocation, rel); -+ addend = 0; -+ break; -+ -+ /* Handle the TOC16 reloc. We want to use the offset within the .got -+ section, not the actual VMA. This is appropriate when generating -+ an embedded ELF object, for which the .got section acts like the -+ AIX .toc section. */ -+ case R_PPC_TOC16: /* phony GOT16 relocations */ -+ if (sec == NULL || sec->output_section == NULL) -+ { -+ unresolved_reloc = TRUE; -+ break; -+ } -+ BFD_ASSERT (strcmp (bfd_get_section_name (sec->owner, sec), -+ ".got") == 0 -+ || strcmp (bfd_get_section_name (sec->owner, sec), -+ ".cgot") == 0); -+ -+ addend -= sec->output_section->vma + sec->output_offset + 0x8000; -+ break; -+ -+ case R_PPC_PLTREL24: -+ if (h != NULL && ifunc == NULL) -+ { -+ struct plt_entry *ent = find_plt_ent (&h->plt.plist, got2, -+ info->shared ? addend : 0); -+ if (ent == NULL -+ || htab->plt == NULL) -+ { -+ /* We didn't make a PLT entry for this symbol. This -+ happens when statically linking PIC code, or when -+ using -Bsymbolic. */ -+ } -+ else -+ { -+ /* Relocation is to the entry for this symbol in the -+ procedure linkage table. */ -+ unresolved_reloc = FALSE; -+ if (htab->plt_type == PLT_NEW) -+ relocation = (htab->glink->output_section->vma -+ + htab->glink->output_offset -+ + ent->glink_offset); -+ else -+ relocation = (htab->plt->output_section->vma -+ + htab->plt->output_offset -+ + ent->plt.offset); -+ } -+ } -+ -+ /* R_PPC_PLTREL24 is rather special. If non-zero, the -+ addend specifies the GOT pointer offset within .got2. -+ Don't apply it to the relocation field. */ -+ addend = 0; -+ break; -+ -+ /* Relocate against _SDA_BASE_. */ -+ case R_PPC_SDAREL16: -+ { -+ const char *name; -+ struct elf_link_hash_entry *sda = htab->sdata[0].sym; -+ -+ if (sec == NULL -+ || sec->output_section == NULL -+ || !is_static_defined (sda)) -+ { -+ unresolved_reloc = TRUE; -+ break; -+ } -+ addend -= SYM_VAL (sda); -+ -+ name = bfd_get_section_name (output_bfd, sec->output_section); -+ if (! ((CONST_STRNEQ (name, ".sdata") -+ && (name[6] == 0 || name[6] == '.')) -+ || (CONST_STRNEQ (name, ".sbss") -+ && (name[5] == 0 || name[5] == '.')))) -+ { -+ info->callbacks->einfo -+ (_("%P: %B: the target (%s) of a %s relocation is " -+ "in the wrong output section (%s)\n"), -+ input_bfd, -+ sym_name, -+ howto->name, -+ name); -+ } -+ } -+ break; -+ -+ /* Relocate against _SDA2_BASE_. */ -+ case R_PPC_EMB_SDA2REL: -+ { -+ const char *name; -+ struct elf_link_hash_entry *sda = htab->sdata[1].sym; -+ -+ if (sec == NULL -+ || sec->output_section == NULL -+ || !is_static_defined (sda)) -+ { -+ unresolved_reloc = TRUE; -+ break; -+ } -+ addend -= SYM_VAL (sda); -+ -+ name = bfd_get_section_name (output_bfd, sec->output_section); -+ if (! (CONST_STRNEQ (name, ".sdata2") -+ || CONST_STRNEQ (name, ".sbss2"))) -+ { -+ info->callbacks->einfo -+ (_("%P: %B: the target (%s) of a %s relocation is " -+ "in the wrong output section (%s)\n"), -+ input_bfd, -+ sym_name, -+ howto->name, -+ name); -+ } -+ } -+ break; -+#if 0 -+ case R_PPC_AMIGAOS_BREL: -+ case R_PPC_AMIGAOS_BREL_HI: -+ case R_PPC_AMIGAOS_BREL_LO: -+ case R_PPC_AMIGAOS_BREL_HA: -+ { -+ if (data_section == NULL) -+ data_section = bfd_get_section_by_name (output_bfd, ".data"); -+ -+ if (sec) -+ { -+ const char *name = bfd_get_section_name (abfd, sec->output_section); -+ if (strcmp (name, ".sdata") != 0 -+ && strcmp (name, ".sbss") != 0 -+ && strcmp (name, ".data") != 0 -+ && strcmp (name, ".bss") != 0 -+ && strncmp (name, ".ctors", 6) != 0 -+ && strncmp (name, ".dtors", 6) != 0) -+ { -+ (*_bfd_error_handler) (_("%s: The target (%s) of a %s relocation is in the wrong output section (%s)"), -+ input_bfd, -+ sym_name, -+ howto->name, -+ name); -+ } -+ } -+ -+ addend = addend - data_section->vma; -+ -+ if (r_type == R_PPC_AMIGAOS_BREL_HA) -+ addend += ((relocation + addend) & 0x8000) << 1; -+ -+ } -+ break; -+#endif -+ case R_PPC_VLE_LO16A: -+ relocation = (relocation + addend) & 0xffff; -+ ppc_elf_vle_split16 (output_bfd, contents, rel->r_offset, -+ relocation, split16a_type); -+ continue; -+ -+ case R_PPC_VLE_LO16D: -+ relocation = (relocation + addend) & 0xffff; -+ ppc_elf_vle_split16 (output_bfd, contents, rel->r_offset, -+ relocation, split16d_type); -+ continue; -+ -+ case R_PPC_VLE_HI16A: -+ relocation = ((relocation + addend) >> 16) & 0xffff; -+ ppc_elf_vle_split16 (output_bfd, contents, rel->r_offset, -+ relocation, split16a_type); -+ continue; -+ -+ case R_PPC_VLE_HI16D: -+ relocation = ((relocation + addend) >> 16) & 0xffff; -+ ppc_elf_vle_split16 (output_bfd, contents, rel->r_offset, -+ relocation, split16d_type); -+ continue; -+ -+ case R_PPC_VLE_HA16A: -+ { -+ bfd_vma value = relocation + addend; -+ value = (((value >> 16) + ((value & 0x8000) ? 1 : 0)) & 0xffff); -+ ppc_elf_vle_split16 (output_bfd, contents, rel->r_offset, -+ value, split16a_type); -+ } -+ continue; -+ -+ case R_PPC_VLE_HA16D: -+ { -+ bfd_vma value = relocation + addend; -+ value = (((value >> 16) + ((value & 0x8000) ? 1 : 0)) & 0xffff); -+ ppc_elf_vle_split16 (output_bfd, contents, rel->r_offset, -+ value, split16d_type); -+ } -+ continue; -+ -+ /* Relocate against either _SDA_BASE_, _SDA2_BASE_, or 0. */ -+ case R_PPC_EMB_SDA21: -+ case R_PPC_VLE_SDA21: -+ case R_PPC_EMB_RELSDA: -+ case R_PPC_VLE_SDA21_LO: -+ { -+ const char *name; -+ int reg; -+ struct elf_link_hash_entry *sda = NULL; -+ -+ if (sec == NULL || sec->output_section == NULL) -+ { -+ unresolved_reloc = TRUE; -+ break; -+ } -+ -+ name = bfd_get_section_name (output_bfd, sec->output_section); -+ if (((CONST_STRNEQ (name, ".sdata") -+ && (name[6] == 0 || name[6] == '.')) -+ || (CONST_STRNEQ (name, ".sbss") -+ && (name[5] == 0 || name[5] == '.')))) -+ { -+ reg = 13; -+ sda = htab->sdata[0].sym; -+ } -+ else if (CONST_STRNEQ (name, ".sdata2") -+ || CONST_STRNEQ (name, ".sbss2")) -+ { -+ reg = 2; -+ sda = htab->sdata[1].sym; -+ } -+ else if (strcmp (name, ".PPC.EMB.sdata0") == 0 -+ || strcmp (name, ".PPC.EMB.sbss0") == 0) -+ { -+ reg = 0; -+ } -+ else -+ { -+ info->callbacks->einfo -+ (_("%P: %B: the target (%s) of a %s relocation is " -+ "in the wrong output section (%s)\n"), -+ input_bfd, -+ sym_name, -+ howto->name, -+ name); -+ -+ bfd_set_error (bfd_error_bad_value); -+ ret = FALSE; -+ continue; -+ } -+ -+ if (sda != NULL) -+ { -+ if (!is_static_defined (sda)) -+ { -+ unresolved_reloc = TRUE; -+ break; -+ } -+ addend -= SYM_VAL (sda); -+ } -+ -+ if (reg == 0 -+ && (r_type == R_PPC_VLE_SDA21 -+ || r_type == R_PPC_VLE_SDA21_LO)) -+ { -+ /* Use the split20 format. */ -+ bfd_vma insn, bits12to15, bits21to31; -+ bfd_vma value = (relocation + rel->r_offset) & 0xffff; -+ /* Propagate sign bit, if necessary. */ -+ insn = (value & 0x8000) ? 0x70107800 : 0x70000000; -+ bits12to15 = value & 0x700; -+ bits21to31 = value & 0x7ff; -+ insn |= bits12to15; -+ insn |= bits21to31; -+ bfd_put_32 (output_bfd, insn, contents + rel->r_offset); -+ continue; -+ } -+ else if (r_type == R_PPC_EMB_SDA21 -+ || r_type == R_PPC_VLE_SDA21 -+ || r_type == R_PPC_VLE_SDA21_LO) -+ { -+ bfd_vma insn; /* Fill in register field. */ -+ -+ insn = bfd_get_32 (output_bfd, contents + rel->r_offset); -+ insn = (insn & ~RA_REGISTER_MASK) | (reg << RA_REGISTER_SHIFT); -+ bfd_put_32 (output_bfd, insn, contents + rel->r_offset); -+ } -+ } -+ break; -+ -+ case R_PPC_VLE_SDAREL_LO16A: -+ case R_PPC_VLE_SDAREL_LO16D: -+ case R_PPC_VLE_SDAREL_HI16A: -+ case R_PPC_VLE_SDAREL_HI16D: -+ case R_PPC_VLE_SDAREL_HA16A: -+ case R_PPC_VLE_SDAREL_HA16D: -+ { -+ bfd_vma value; -+ const char *name; -+ //int reg; -+ struct elf_link_hash_entry *sda = NULL; -+ -+ if (sec == NULL || sec->output_section == NULL) -+ { -+ unresolved_reloc = TRUE; -+ break; -+ } -+ -+ name = bfd_get_section_name (output_bfd, sec->output_section); -+ if (((CONST_STRNEQ (name, ".sdata") -+ && (name[6] == 0 || name[6] == '.')) -+ || (CONST_STRNEQ (name, ".sbss") -+ && (name[5] == 0 || name[5] == '.')))) -+ { -+ //reg = 13; -+ sda = htab->sdata[0].sym; -+ } -+ else if (CONST_STRNEQ (name, ".sdata2") -+ || CONST_STRNEQ (name, ".sbss2")) -+ { -+ //reg = 2; -+ sda = htab->sdata[1].sym; -+ } -+ else -+ { -+ (*_bfd_error_handler) -+ (_("%B: the target (%s) of a %s relocation is " -+ "in the wrong output section (%s)"), -+ input_bfd, -+ sym_name, -+ howto->name, -+ name); -+ -+ bfd_set_error (bfd_error_bad_value); -+ ret = FALSE; -+ continue; -+ } -+ -+ if (sda != NULL) -+ { -+ if (!is_static_defined (sda)) -+ { -+ unresolved_reloc = TRUE; -+ break; -+ } -+ } -+ -+ value = sda->root.u.def.section->output_section->vma -+ + sda->root.u.def.section->output_offset; -+ -+ if (r_type == R_PPC_VLE_SDAREL_LO16A) -+ { -+ value = (value + addend) & 0xffff; -+ ppc_elf_vle_split16 (output_bfd, contents, rel->r_offset, -+ value, split16a_type); -+ } -+ else if (r_type == R_PPC_VLE_SDAREL_LO16D) -+ { -+ value = (value + addend) & 0xffff; -+ ppc_elf_vle_split16 (output_bfd, contents, rel->r_offset, -+ value, split16d_type); -+ } -+ else if (r_type == R_PPC_VLE_SDAREL_HI16A) -+ { -+ value = ((value + addend) >> 16) & 0xffff; -+ ppc_elf_vle_split16 (output_bfd, contents, rel->r_offset, -+ value, split16a_type); -+ } -+ else if (r_type == R_PPC_VLE_SDAREL_HI16D) -+ { -+ value = ((value + addend) >> 16) & 0xffff; -+ ppc_elf_vle_split16 (output_bfd, contents, rel->r_offset, -+ value, split16d_type); -+ } -+ else if (r_type == R_PPC_VLE_SDAREL_HA16A) -+ { -+ value += addend; -+ value = (((value >> 16) + ((value & 0x8000) ? 1 : 0)) & 0xffff); -+ ppc_elf_vle_split16 (output_bfd, contents, rel->r_offset, -+ value, split16a_type); -+ } -+ else if (r_type == R_PPC_VLE_SDAREL_HA16D) -+ { -+ value += addend; -+ value = (((value >> 16) + ((value & 0x8000) ? 1 : 0)) & 0xffff); -+ ppc_elf_vle_split16 (output_bfd, contents, rel->r_offset, -+ value, split16d_type); -+ } -+ } -+ continue; -+ -+ /* Relocate against the beginning of the section. */ -+ case R_PPC_SECTOFF: -+ case R_PPC_SECTOFF_LO: -+ case R_PPC_SECTOFF_HI: -+ case R_PPC_SECTOFF_HA: -+ if (sec == NULL || sec->output_section == NULL) -+ { -+ unresolved_reloc = TRUE; -+ break; -+ } -+ addend -= sec->output_section->vma; -+ break; -+ -+ /* Negative relocations. */ -+ case R_PPC_EMB_NADDR32: -+ case R_PPC_EMB_NADDR16: -+ case R_PPC_EMB_NADDR16_LO: -+ case R_PPC_EMB_NADDR16_HI: -+ case R_PPC_EMB_NADDR16_HA: -+ addend -= 2 * relocation; -+ break; -+ -+ case R_PPC_COPY: -+ case R_PPC_GLOB_DAT: -+ case R_PPC_JMP_SLOT: -+ case R_PPC_RELATIVE: -+ case R_PPC_IRELATIVE: -+ case R_PPC_PLT32: -+ case R_PPC_PLTREL32: -+ case R_PPC_PLT16_LO: -+ case R_PPC_PLT16_HI: -+ case R_PPC_PLT16_HA: -+ case R_PPC_ADDR30: -+ case R_PPC_EMB_RELSEC16: -+ case R_PPC_EMB_RELST_LO: -+ case R_PPC_EMB_RELST_HI: -+ case R_PPC_EMB_RELST_HA: -+ case R_PPC_EMB_BIT_FLD: -+ info->callbacks->einfo -+ (_("%P: %B: relocation %s is not yet supported for symbol %s\n"), -+ input_bfd, -+ howto->name, -+ sym_name); -+ -+ bfd_set_error (bfd_error_invalid_operation); -+ ret = FALSE; -+ continue; -+ } -+ -+ /* Do any further special processing. */ -+ switch (r_type) -+ { -+ default: -+ break; -+ -+ case R_PPC_ADDR16_HA: -+ case R_PPC_REL16_HA: -+ case R_PPC_SECTOFF_HA: -+ case R_PPC_TPREL16_HA: -+ case R_PPC_DTPREL16_HA: -+ case R_PPC_EMB_NADDR16_HA: -+ case R_PPC_EMB_RELST_HA: -+ /* It's just possible that this symbol is a weak symbol -+ that's not actually defined anywhere. In that case, -+ 'sec' would be NULL, and we should leave the symbol -+ alone (it will be set to zero elsewhere in the link). */ -+ if (sec == NULL) -+ break; -+ /* Fall thru */ -+ -+ case R_PPC_PLT16_HA: -+ case R_PPC_GOT16_HA: -+ case R_PPC_GOT_TLSGD16_HA: -+ case R_PPC_GOT_TLSLD16_HA: -+ case R_PPC_GOT_TPREL16_HA: -+ case R_PPC_GOT_DTPREL16_HA: -+ /* Add 0x10000 if sign bit in 0:15 is set. -+ Bits 0:15 are not used. */ -+ addend += 0x8000; -+ break; -+ -+ case R_PPC_ADDR16: -+ case R_PPC_ADDR16_LO: -+ case R_PPC_GOT16: -+ case R_PPC_GOT16_LO: -+ case R_PPC_SDAREL16: -+ case R_PPC_SECTOFF: -+ case R_PPC_SECTOFF_LO: -+ case R_PPC_DTPREL16: -+ case R_PPC_DTPREL16_LO: -+ case R_PPC_TPREL16: -+ case R_PPC_TPREL16_LO: -+ case R_PPC_GOT_TLSGD16: -+ case R_PPC_GOT_TLSGD16_LO: -+ case R_PPC_GOT_TLSLD16: -+ case R_PPC_GOT_TLSLD16_LO: -+ case R_PPC_GOT_DTPREL16: -+ case R_PPC_GOT_DTPREL16_LO: -+ case R_PPC_GOT_TPREL16: -+ case R_PPC_GOT_TPREL16_LO: -+ { -+ /* The 32-bit ABI lacks proper relocations to deal with -+ certain 64-bit instructions. Prevent damage to bits -+ that make up part of the insn opcode. */ -+ unsigned int insn, mask, lobit; -+ -+ insn = bfd_get_32 (output_bfd, contents + rel->r_offset - d_offset); -+ mask = 0; -+ if (is_insn_ds_form (insn)) -+ mask = 3; -+ else if (is_insn_dq_form (insn)) -+ mask = 15; -+ else -+ break; -+ lobit = mask & (relocation + addend); -+ if (lobit != 0) -+ { -+ addend -= lobit; -+ info->callbacks->einfo -+ (_("%P: %H: error: %s against `%s' not a multiple of %u\n"), -+ input_bfd, input_section, rel->r_offset, -+ howto->name, sym_name, mask + 1); -+ bfd_set_error (bfd_error_bad_value); -+ ret = FALSE; -+ } -+ addend += insn & mask; -+ } -+ break; -+ } -+ -+#ifdef DEBUG -+ fprintf (stderr, "\ttype = %s (%d), name = %s, symbol index = %ld, " -+ "offset = %ld, addend = %ld\n", -+ howto->name, -+ (int) r_type, -+ sym_name, -+ r_symndx, -+ (long) rel->r_offset, -+ (long) addend); -+#endif -+ -+ if (unresolved_reloc -+ && !((input_section->flags & SEC_DEBUGGING) != 0 -+ && h->def_dynamic) -+ && _bfd_elf_section_offset (output_bfd, info, input_section, -+ rel->r_offset) != (bfd_vma) -1) -+ { -+ info->callbacks->einfo -+ (_("%P: %H: unresolvable %s relocation against symbol `%s'\n"), -+ input_bfd, input_section, rel->r_offset, -+ howto->name, -+ sym_name); -+ ret = FALSE; -+ } -+ -+ r = _bfd_final_link_relocate (howto, -+ input_bfd, -+ input_section, -+ contents, -+ rel->r_offset, -+ relocation, -+ addend); -+ -+#ifdef DEBUG -+ fprintf (stderr, "%p %p %p\n", (void *)rel->r_offset, (void *)relocation, (void *)addend); -+#endif -+ if (r != bfd_reloc_ok) -+ { -+ if (r == bfd_reloc_overflow) -+ { -+ if (warned) -+ continue; -+ if (h != NULL -+ && h->root.type == bfd_link_hash_undefweak -+ && howto->pc_relative) -+ { -+ /* Assume this is a call protected by other code that -+ detect the symbol is undefined. If this is the case, -+ we can safely ignore the overflow. If not, the -+ program is hosed anyway, and a little warning isn't -+ going to help. */ -+ -+ continue; -+ } -+ -+ if (! (*info->callbacks->reloc_overflow) (info, -+ (h ? &h->root : NULL), -+ sym_name, -+ howto->name, -+ rel->r_addend, -+ input_bfd, -+ input_section, -+ rel->r_offset)) -+ return FALSE; -+ } -+ else -+ { -+ info->callbacks->einfo -+ (_("%P: %H: %s reloc against `%s': error %d\n"), -+ input_bfd, input_section, rel->r_offset, -+ howto->name, sym_name, (int) r); -+ ret = FALSE; -+ } -+ } -+ } -+ -+#ifdef DEBUG -+ fprintf (stderr, "\n"); -+#endif -+ -+ return ret; -+} -+ -+/* Finish up dynamic symbol handling. We set the contents of various -+ dynamic sections here. */ -+ -+static bfd_boolean -+ppc_elf_finish_dynamic_symbol (bfd *output_bfd, -+ struct bfd_link_info *info, -+ struct elf_link_hash_entry *h, -+ Elf_Internal_Sym *sym) -+{ -+ struct ppc_elf_link_hash_table *htab; -+ struct plt_entry *ent; -+ bfd_boolean doneone; -+ -+#ifdef DEBUG -+ fprintf (stderr, "ppc_elf_finish_dynamic_symbol called for %s", -+ h->root.root.string); -+#endif -+ -+ htab = ppc_elf_hash_table (info); -+ BFD_ASSERT (htab->elf.dynobj != NULL); -+ -+ doneone = FALSE; -+ for (ent = h->plt.plist; ent != NULL; ent = ent->next) -+ if (ent->plt.offset != (bfd_vma) -1) -+ { -+ if (!doneone) -+ { -+ Elf_Internal_Rela rela; -+ bfd_byte *loc; -+ bfd_vma reloc_index; -+ -+ if (htab->plt_type == PLT_NEW -+ || !htab->elf.dynamic_sections_created -+ || h->dynindx == -1) -+ reloc_index = ent->plt.offset / 4; -+ else -+ { -+ reloc_index = ((ent->plt.offset - htab->plt_initial_entry_size) -+ / htab->plt_slot_size); -+ if (reloc_index > PLT_NUM_SINGLE_ENTRIES -+ && htab->plt_type == PLT_OLD) -+ reloc_index -= (reloc_index - PLT_NUM_SINGLE_ENTRIES) / 2; -+ } -+ -+ /* This symbol has an entry in the procedure linkage table. -+ Set it up. */ -+ if (htab->plt_type == PLT_VXWORKS -+ && htab->elf.dynamic_sections_created -+ && h->dynindx != -1) -+ { -+ bfd_vma got_offset; -+ const bfd_vma *plt_entry; -+ -+ /* The first three entries in .got.plt are reserved. */ -+ got_offset = (reloc_index + 3) * 4; -+ -+ /* Use the right PLT. */ -+ plt_entry = info->shared ? ppc_elf_vxworks_pic_plt_entry -+ : ppc_elf_vxworks_plt_entry; -+ -+ /* Fill in the .plt on VxWorks. */ -+ if (info->shared) -+ { -+ bfd_put_32 (output_bfd, -+ plt_entry[0] | PPC_HA (got_offset), -+ htab->plt->contents + ent->plt.offset + 0); -+ bfd_put_32 (output_bfd, -+ plt_entry[1] | PPC_LO (got_offset), -+ htab->plt->contents + ent->plt.offset + 4); -+ } -+ else -+ { -+ bfd_vma got_loc = got_offset + SYM_VAL (htab->elf.hgot); -+ -+ bfd_put_32 (output_bfd, -+ plt_entry[0] | PPC_HA (got_loc), -+ htab->plt->contents + ent->plt.offset + 0); -+ bfd_put_32 (output_bfd, -+ plt_entry[1] | PPC_LO (got_loc), -+ htab->plt->contents + ent->plt.offset + 4); -+ } -+ -+ bfd_put_32 (output_bfd, plt_entry[2], -+ htab->plt->contents + ent->plt.offset + 8); -+ bfd_put_32 (output_bfd, plt_entry[3], -+ htab->plt->contents + ent->plt.offset + 12); -+ -+ /* This instruction is an immediate load. The value loaded is -+ the byte offset of the R_PPC_JMP_SLOT relocation from the -+ start of the .rela.plt section. The value is stored in the -+ low-order 16 bits of the load instruction. */ -+ /* NOTE: It appears that this is now an index rather than a -+ prescaled offset. */ -+ bfd_put_32 (output_bfd, -+ plt_entry[4] | reloc_index, -+ htab->plt->contents + ent->plt.offset + 16); -+ /* This instruction is a PC-relative branch whose target is -+ the start of the PLT section. The address of this branch -+ instruction is 20 bytes beyond the start of this PLT entry. -+ The address is encoded in bits 6-29, inclusive. The value -+ stored is right-shifted by two bits, permitting a 26-bit -+ offset. */ -+ bfd_put_32 (output_bfd, -+ (plt_entry[5] -+ | (-(ent->plt.offset + 20) & 0x03fffffc)), -+ htab->plt->contents + ent->plt.offset + 20); -+ bfd_put_32 (output_bfd, plt_entry[6], -+ htab->plt->contents + ent->plt.offset + 24); -+ bfd_put_32 (output_bfd, plt_entry[7], -+ htab->plt->contents + ent->plt.offset + 28); -+ -+ /* Fill in the GOT entry corresponding to this PLT slot with -+ the address immediately after the "bctr" instruction -+ in this PLT entry. */ -+ bfd_put_32 (output_bfd, (htab->plt->output_section->vma -+ + htab->plt->output_offset -+ + ent->plt.offset + 16), -+ htab->sgotplt->contents + got_offset); -+ -+ if (!info->shared) -+ { -+ /* Fill in a couple of entries in .rela.plt.unloaded. */ -+ loc = htab->srelplt2->contents -+ + ((VXWORKS_PLTRESOLVE_RELOCS + reloc_index -+ * VXWORKS_PLT_NON_JMP_SLOT_RELOCS) -+ * sizeof (Elf32_External_Rela)); -+ -+ /* Provide the @ha relocation for the first instruction. */ -+ rela.r_offset = (htab->plt->output_section->vma -+ + htab->plt->output_offset -+ + ent->plt.offset + 2); -+ rela.r_info = ELF32_R_INFO (htab->elf.hgot->indx, -+ R_PPC_ADDR16_HA); -+ rela.r_addend = got_offset; -+ bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); -+ loc += sizeof (Elf32_External_Rela); -+ -+ /* Provide the @l relocation for the second instruction. */ -+ rela.r_offset = (htab->plt->output_section->vma -+ + htab->plt->output_offset -+ + ent->plt.offset + 6); -+ rela.r_info = ELF32_R_INFO (htab->elf.hgot->indx, -+ R_PPC_ADDR16_LO); -+ rela.r_addend = got_offset; -+ bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); -+ loc += sizeof (Elf32_External_Rela); -+ -+ /* Provide a relocation for the GOT entry corresponding to this -+ PLT slot. Point it at the middle of the .plt entry. */ -+ rela.r_offset = (htab->sgotplt->output_section->vma -+ + htab->sgotplt->output_offset -+ + got_offset); -+ rela.r_info = ELF32_R_INFO (htab->elf.hplt->indx, -+ R_PPC_ADDR32); -+ rela.r_addend = ent->plt.offset + 16; -+ bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); -+ } -+ -+ /* VxWorks uses non-standard semantics for R_PPC_JMP_SLOT. -+ In particular, the offset for the relocation is not the -+ address of the PLT entry for this function, as specified -+ by the ABI. Instead, the offset is set to the address of -+ the GOT slot for this function. See EABI 4.4.4.1. */ -+ rela.r_offset = (htab->sgotplt->output_section->vma -+ + htab->sgotplt->output_offset -+ + got_offset); -+ -+ } -+ else -+ { -+ asection *splt = htab->plt; -+ if (!htab->elf.dynamic_sections_created -+ || h->dynindx == -1) -+ splt = htab->iplt; -+ -+ rela.r_offset = (splt->output_section->vma -+ + splt->output_offset -+ + ent->plt.offset); -+#ifdef DEBUG -+ fprintf (stderr, " r_offset = %p ", (void *)rela.r_offset); -+#endif -+ if (htab->plt_type == PLT_OLD -+ || !htab->elf.dynamic_sections_created -+ || h->dynindx == -1) -+ { -+ /* We don't need to fill in the .plt. The ppc dynamic -+ linker will fill it in. */ -+#ifdef DEBUG -+ fprintf (stderr, " not filling in .plt "); -+#endif -+ } -+ else -+ { -+ bfd_vma val = (htab->glink_pltresolve + ent->plt.offset -+ + htab->glink->output_section->vma -+ + htab->glink->output_offset); -+ bfd_put_32 (output_bfd, val, -+ splt->contents + ent->plt.offset); -+ } -+ } -+ -+ /* Fill in the entry in the .rela.plt section. */ -+ rela.r_addend = 0; -+ if (!htab->elf.dynamic_sections_created -+ || h->dynindx == -1) -+ { -+ BFD_ASSERT (h->type == STT_GNU_IFUNC -+ && h->def_regular -+ && (h->root.type == bfd_link_hash_defined -+ || h->root.type == bfd_link_hash_defweak)); -+ rela.r_info = ELF32_R_INFO (0, R_PPC_IRELATIVE); -+ rela.r_addend = SYM_VAL (h); -+ } -+ else -+ rela.r_info = ELF32_R_INFO (h->dynindx, R_PPC_JMP_SLOT); -+ -+ if (!htab->elf.dynamic_sections_created -+ || h->dynindx == -1) -+ loc = (htab->reliplt->contents -+ + (htab->reliplt->reloc_count++ -+ * sizeof (Elf32_External_Rela))); -+ else -+ loc = (htab->relplt->contents -+ + reloc_index * sizeof (Elf32_External_Rela)); -+ bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); -+ -+#ifdef DEBUG -+ fprintf (stderr, " r_offset = %p r_addednd = %p, r_info = 0x%08x, h->def_regular = %d", (void *)rela.r_offset, (void *)rela.r_addend, (unsigned int)rela.r_info, (int)h->def_regular); -+#endif -+ if (!h->def_regular) -+ { -+ /* Mark the symbol as undefined, rather than as -+ defined in the .plt section. Leave the value if -+ there were any relocations where pointer equality -+ matters (this is a clue for the dynamic linker, to -+ make function pointer comparisons work between an -+ application and shared library), otherwise set it -+ to zero. */ -+ sym->st_shndx = SHN_UNDEF; -+ if (!h->pointer_equality_needed) -+ { -+ /* THF: This is peculiar. The compiler generates a R_PPC_REL24 for externally referenced -+ * symbols impoted from libc.so. Relocation in elf.library requires the symbol to have it's .plt -+ * stub value, but the linker specifically clears the value to 0, resulting in run-time -+ * errors when the binary tries to call libc functions. -+ */ -+ // sym->st_value = 0; -+ } -+ else if (!h->ref_regular_nonweak) -+ { -+ /* This breaks function pointer comparisons, but -+ that is better than breaking tests for a NULL -+ function pointer. */ -+ sym->st_value = 0; -+ } -+ } -+ else if (h->type == STT_GNU_IFUNC -+ && !info->shared) -+ { -+ /* Set the value of ifunc symbols in a non-pie -+ executable to the glink entry. This is to avoid -+ text relocations. We can't do this for ifunc in -+ allocate_dynrelocs, as we do for normal dynamic -+ function symbols with plt entries, because we need -+ to keep the original value around for the ifunc -+ relocation. */ -+ sym->st_shndx = (_bfd_elf_section_from_bfd_section -+ (output_bfd, htab->glink->output_section)); -+ sym->st_value = (ent->glink_offset -+ + htab->glink->output_offset -+ + htab->glink->output_section->vma); -+ } -+ doneone = TRUE; -+ } -+ -+ if (htab->plt_type == PLT_NEW -+ || !htab->elf.dynamic_sections_created -+ || h->dynindx == -1) -+ { -+ unsigned char *p; -+ asection *splt = htab->plt; -+ if (!htab->elf.dynamic_sections_created -+ || h->dynindx == -1) -+ splt = htab->iplt; -+ -+ p = (unsigned char *) htab->glink->contents + ent->glink_offset; -+ -+ if (h == htab->tls_get_addr && !htab->no_tls_get_addr_opt) -+ { -+ bfd_put_32 (output_bfd, LWZ_11_3, p); -+ p += 4; -+ bfd_put_32 (output_bfd, LWZ_12_3 + 4, p); -+ p += 4; -+ bfd_put_32 (output_bfd, MR_0_3, p); -+ p += 4; -+ bfd_put_32 (output_bfd, CMPWI_11_0, p); -+ p += 4; -+ bfd_put_32 (output_bfd, ADD_3_12_2, p); -+ p += 4; -+ bfd_put_32 (output_bfd, BEQLR, p); -+ p += 4; -+ bfd_put_32 (output_bfd, MR_3_0, p); -+ p += 4; -+ bfd_put_32 (output_bfd, NOP, p); -+ p += 4; -+ } -+ -+ write_glink_stub (ent, splt, p, info); -+ -+ if (!info->shared) -+ /* We only need one non-PIC glink stub. */ -+ break; -+ } -+ else -+ break; -+ } -+ -+ if (h->needs_copy) -+ { -+ asection *s; -+ Elf_Internal_Rela rela; -+ bfd_byte *loc; -+ -+ /* This symbols needs a copy reloc. Set it up. */ -+ -+#ifdef DEBUG -+ fprintf (stderr, ", copy"); -+#endif -+ -+ BFD_ASSERT (h->dynindx != -1); -+ -+ if (ppc_elf_hash_entry (h)->has_sda_refs) -+ s = htab->relsbss; -+ else -+ s = htab->relbss; -+ BFD_ASSERT (s != NULL); -+ -+ rela.r_offset = SYM_VAL (h); -+ rela.r_info = ELF32_R_INFO (h->dynindx, R_PPC_COPY); -+ rela.r_addend = 0; -+ loc = s->contents + s->reloc_count++ * sizeof (Elf32_External_Rela); -+ bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); -+ } -+ -+#ifdef DEBUG -+ fprintf (stderr, " SYM_VAL(%p) ", (void *)SYM_VAL(h)); -+#endif -+#ifdef DEBUG -+ fprintf (stderr, "\n"); -+#endif -+ -+ return TRUE; -+} -+ -+static enum elf_reloc_type_class -+ppc_elf_reloc_type_class (const Elf_Internal_Rela *rela) -+{ -+ switch (ELF32_R_TYPE (rela->r_info)) -+ { -+ case R_PPC_RELATIVE: -+ return reloc_class_relative; -+ case R_PPC_REL24: -+ case R_PPC_ADDR24: -+ case R_PPC_JMP_SLOT: -+ return reloc_class_plt; -+ case R_PPC_COPY: -+ return reloc_class_copy; -+ default: -+ return reloc_class_normal; -+ } -+} -+ -+/* Finish up the dynamic sections. */ -+ -+static bfd_boolean -+ppc_elf_finish_dynamic_sections (bfd *output_bfd, -+ struct bfd_link_info *info) -+{ -+ asection *sdyn; -+ asection *splt; -+ struct ppc_elf_link_hash_table *htab; -+ bfd_vma got; -+ bfd *dynobj; -+ bfd_boolean ret = TRUE; -+ -+#ifdef DEBUG -+ fprintf (stderr, "ppc_elf_finish_dynamic_sections called\n"); -+#endif -+ -+ htab = ppc_elf_hash_table (info); -+ dynobj = elf_hash_table (info)->dynobj; -+ sdyn = bfd_get_linker_section (dynobj, ".dynamic"); -+ if (htab->is_vxworks) -+ splt = bfd_get_linker_section (dynobj, ".plt"); -+ else -+ splt = NULL; -+ -+ got = 0; -+ if (htab->elf.hgot != NULL) -+ got = SYM_VAL (htab->elf.hgot); -+ -+ if (htab->elf.dynamic_sections_created) -+ { -+ Elf32_External_Dyn *dyncon, *dynconend; -+ -+ BFD_ASSERT (htab->plt != NULL && sdyn != NULL); -+ -+ dyncon = (Elf32_External_Dyn *) sdyn->contents; -+ dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->size); -+ for (; dyncon < dynconend; dyncon++) -+ { -+ Elf_Internal_Dyn dyn; -+ asection *s; -+ -+ bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn); -+ -+ switch (dyn.d_tag) -+ { -+ case DT_PLTGOT: -+ if (htab->is_vxworks) -+ s = htab->sgotplt; -+ else -+ s = htab->plt; -+ dyn.d_un.d_ptr = s->output_section->vma + s->output_offset; -+ break; -+ -+ case DT_PLTRELSZ: -+ dyn.d_un.d_val = htab->relplt->size; -+ break; -+ -+ case DT_JMPREL: -+ s = htab->relplt; -+ dyn.d_un.d_ptr = s->output_section->vma + s->output_offset; -+ break; -+ -+ case DT_PPC_GOT: -+ dyn.d_un.d_ptr = got; -+ break; -+ -+ case DT_RELASZ: -+ if (htab->is_vxworks) -+ { -+ if (htab->relplt) -+ dyn.d_un.d_ptr -= htab->relplt->size; -+ break; -+ } -+ continue; -+ -+ default: -+ if (htab->is_vxworks -+ && elf_vxworks_finish_dynamic_entry (output_bfd, &dyn)) -+ break; -+ continue; -+ } -+ -+ bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); -+ } -+ } -+ -+ if (htab->got != NULL) -+ { -+ if (htab->elf.hgot->root.u.def.section == htab->got -+ || htab->elf.hgot->root.u.def.section == htab->sgotplt) -+ { -+ unsigned char *p = htab->elf.hgot->root.u.def.section->contents; -+ -+ p += htab->elf.hgot->root.u.def.value; -+ if (htab->plt_type == PLT_OLD) -+ { -+ /* Add a blrl instruction at _GLOBAL_OFFSET_TABLE_-4 -+ so that a function can easily find the address of -+ _GLOBAL_OFFSET_TABLE_. */ -+ BFD_ASSERT (htab->elf.hgot->root.u.def.value - 4 -+ < htab->elf.hgot->root.u.def.section->size); -+ bfd_put_32 (output_bfd, 0x4e800021, p - 4); -+ } -+ -+ if (sdyn != NULL) -+ { -+ bfd_vma val = sdyn->output_section->vma + sdyn->output_offset; -+ BFD_ASSERT (htab->elf.hgot->root.u.def.value -+ < htab->elf.hgot->root.u.def.section->size); -+ bfd_put_32 (output_bfd, val, p); -+ } -+ } -+ else -+ { -+ info->callbacks->einfo (_("%P: %s not defined in linker created %s\n"), -+ htab->elf.hgot->root.root.string, -+ (htab->sgotplt != NULL -+ ? htab->sgotplt->name : htab->got->name)); -+ bfd_set_error (bfd_error_bad_value); -+ ret = FALSE; -+ } -+ -+ elf_section_data (htab->got->output_section)->this_hdr.sh_entsize = 4; -+ } -+ -+ /* Fill in the first entry in the VxWorks procedure linkage table. */ -+ if (splt && splt->size > 0) -+ { -+ /* Use the right PLT. */ -+ const bfd_vma *plt_entry = (info->shared -+ ? ppc_elf_vxworks_pic_plt0_entry -+ : ppc_elf_vxworks_plt0_entry); -+ -+ if (!info->shared) -+ { -+ bfd_vma got_value = SYM_VAL (htab->elf.hgot); -+ -+ bfd_put_32 (output_bfd, plt_entry[0] | PPC_HA (got_value), -+ splt->contents + 0); -+ bfd_put_32 (output_bfd, plt_entry[1] | PPC_LO (got_value), -+ splt->contents + 4); -+ } -+ else -+ { -+ bfd_put_32 (output_bfd, plt_entry[0], splt->contents + 0); -+ bfd_put_32 (output_bfd, plt_entry[1], splt->contents + 4); -+ } -+ bfd_put_32 (output_bfd, plt_entry[2], splt->contents + 8); -+ bfd_put_32 (output_bfd, plt_entry[3], splt->contents + 12); -+ bfd_put_32 (output_bfd, plt_entry[4], splt->contents + 16); -+ bfd_put_32 (output_bfd, plt_entry[5], splt->contents + 20); -+ bfd_put_32 (output_bfd, plt_entry[6], splt->contents + 24); -+ bfd_put_32 (output_bfd, plt_entry[7], splt->contents + 28); -+ -+ if (! info->shared) -+ { -+ Elf_Internal_Rela rela; -+ bfd_byte *loc; -+ -+ loc = htab->srelplt2->contents; -+ -+ /* Output the @ha relocation for the first instruction. */ -+ rela.r_offset = (htab->plt->output_section->vma -+ + htab->plt->output_offset -+ + 2); -+ rela.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_PPC_ADDR16_HA); -+ rela.r_addend = 0; -+ bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); -+ loc += sizeof (Elf32_External_Rela); -+ -+ /* Output the @l relocation for the second instruction. */ -+ rela.r_offset = (htab->plt->output_section->vma -+ + htab->plt->output_offset -+ + 6); -+ rela.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_PPC_ADDR16_LO); -+ rela.r_addend = 0; -+ bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); -+ loc += sizeof (Elf32_External_Rela); -+ -+ /* Fix up the remaining relocations. They may have the wrong -+ symbol index for _G_O_T_ or _P_L_T_ depending on the order -+ in which symbols were output. */ -+ while (loc < htab->srelplt2->contents + htab->srelplt2->size) -+ { -+ Elf_Internal_Rela rel; -+ -+ bfd_elf32_swap_reloc_in (output_bfd, loc, &rel); -+ rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_PPC_ADDR16_HA); -+ bfd_elf32_swap_reloc_out (output_bfd, &rel, loc); -+ loc += sizeof (Elf32_External_Rela); -+ -+ bfd_elf32_swap_reloc_in (output_bfd, loc, &rel); -+ rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_PPC_ADDR16_LO); -+ bfd_elf32_swap_reloc_out (output_bfd, &rel, loc); -+ loc += sizeof (Elf32_External_Rela); -+ -+ bfd_elf32_swap_reloc_in (output_bfd, loc, &rel); -+ rel.r_info = ELF32_R_INFO (htab->elf.hplt->indx, R_PPC_ADDR32); -+ bfd_elf32_swap_reloc_out (output_bfd, &rel, loc); -+ loc += sizeof (Elf32_External_Rela); -+ } -+ } -+ } -+ -+ if (htab->glink != NULL -+ && htab->glink->contents != NULL -+ && htab->elf.dynamic_sections_created) -+ { -+ unsigned char *p; -+ unsigned char *endp; -+ bfd_vma res0; -+ unsigned int i; -+ -+ /* -+ * PIC glink code is the following: -+ * -+ * # ith PLT code stub. -+ * addis 11,30,(plt+(i-1)*4-got)@ha -+ * lwz 11,(plt+(i-1)*4-got)@l(11) -+ * mtctr 11 -+ * bctr -+ * -+ * # A table of branches, one for each plt entry. -+ * # The idea is that the plt call stub loads ctr and r11 with these -+ * # addresses, so (r11 - res_0) gives the plt index * 4. -+ * res_0: b PLTresolve -+ * res_1: b PLTresolve -+ * . -+ * # Some number of entries towards the end can be nops -+ * res_n_m3: nop -+ * res_n_m2: nop -+ * res_n_m1: -+ * -+ * PLTresolve: -+ * addis 11,11,(1f-res_0)@ha -+ * mflr 0 -+ * bcl 20,31,1f -+ * 1: addi 11,11,(1b-res_0)@l -+ * mflr 12 -+ * mtlr 0 -+ * sub 11,11,12 # r11 = index * 4 -+ * addis 12,12,(got+4-1b)@ha -+ * lwz 0,(got+4-1b)@l(12) # got[1] address of dl_runtime_resolve -+ * lwz 12,(got+8-1b)@l(12) # got[2] contains the map address -+ * mtctr 0 -+ * add 0,11,11 -+ * add 11,0,11 # r11 = index * 12 = reloc offset. -+ * bctr -+ */ -+ static const unsigned int pic_plt_resolve[] = -+ { -+ ADDIS_11_11, -+ MFLR_0, -+ BCL_20_31, -+ ADDI_11_11, -+ MFLR_12, -+ MTLR_0, -+ SUB_11_11_12, -+ ADDIS_12_12, -+ LWZ_0_12, -+ LWZ_12_12, -+ MTCTR_0, -+ ADD_0_11_11, -+ ADD_11_0_11, -+ BCTR, -+ NOP, -+ NOP -+ }; -+ -+ /* -+ * Non-PIC glink code is a little simpler. -+ * -+ * # ith PLT code stub. -+ * lis 11,(plt+(i-1)*4)@ha -+ * lwz 11,(plt+(i-1)*4)@l(11) -+ * mtctr 11 -+ * bctr -+ * -+ * The branch table is the same, then comes -+ * -+ * PLTresolve: -+ * lis 12,(got+4)@ha -+ * addis 11,11,(-res_0)@ha -+ * lwz 0,(got+4)@l(12) # got[1] address of dl_runtime_resolve -+ * addi 11,11,(-res_0)@l # r11 = index * 4 -+ * mtctr 0 -+ * add 0,11,11 -+ * lwz 12,(got+8)@l(12) # got[2] contains the map address -+ * add 11,0,11 # r11 = index * 12 = reloc offset. -+ * bctr -+ */ -+ static const unsigned int plt_resolve[] = -+ { -+ LIS_12, -+ ADDIS_11_11, -+ LWZ_0_12, -+ ADDI_11_11, -+ MTCTR_0, -+ ADD_0_11_11, -+ LWZ_12_12, -+ ADD_11_0_11, -+ BCTR, -+ NOP, -+ NOP, -+ NOP, -+ NOP, -+ NOP, -+ NOP, -+ NOP -+ }; -+ -+ if (ARRAY_SIZE (pic_plt_resolve) != GLINK_PLTRESOLVE / 4) -+ abort (); -+ if (ARRAY_SIZE (plt_resolve) != GLINK_PLTRESOLVE / 4) -+ abort (); -+ -+ /* Build the branch table, one for each plt entry (less one), -+ and perhaps some padding. */ -+ p = htab->glink->contents; -+ p += htab->glink_pltresolve; -+ endp = htab->glink->contents; -+ endp += htab->glink->size - GLINK_PLTRESOLVE; -+ while (p < endp - 8 * 4) -+ { -+ bfd_put_32 (output_bfd, B + endp - p, p); -+ p += 4; -+ } -+ while (p < endp) -+ { -+ bfd_put_32 (output_bfd, NOP, p); -+ p += 4; -+ } -+ -+ res0 = (htab->glink_pltresolve -+ + htab->glink->output_section->vma -+ + htab->glink->output_offset); -+ -+ /* Last comes the PLTresolve stub. */ -+ if (info->shared) -+ { -+ bfd_vma bcl; -+ -+ for (i = 0; i < ARRAY_SIZE (pic_plt_resolve); i++) -+ { -+ bfd_put_32 (output_bfd, pic_plt_resolve[i], p); -+ p += 4; -+ } -+ p -= 4 * ARRAY_SIZE (pic_plt_resolve); -+ -+ bcl = (htab->glink->size - GLINK_PLTRESOLVE + 3*4 -+ + htab->glink->output_section->vma -+ + htab->glink->output_offset); -+ -+ bfd_put_32 (output_bfd, -+ ADDIS_11_11 + PPC_HA (bcl - res0), p + 0*4); -+ bfd_put_32 (output_bfd, -+ ADDI_11_11 + PPC_LO (bcl - res0), p + 3*4); -+ bfd_put_32 (output_bfd, -+ ADDIS_12_12 + PPC_HA (got + 4 - bcl), p + 7*4); -+ if (PPC_HA (got + 4 - bcl) == PPC_HA (got + 8 - bcl)) -+ { -+ bfd_put_32 (output_bfd, -+ LWZ_0_12 + PPC_LO (got + 4 - bcl), p + 8*4); -+ bfd_put_32 (output_bfd, -+ LWZ_12_12 + PPC_LO (got + 8 - bcl), p + 9*4); -+ } -+ else -+ { -+ bfd_put_32 (output_bfd, -+ LWZU_0_12 + PPC_LO (got + 4 - bcl), p + 8*4); -+ bfd_put_32 (output_bfd, -+ LWZ_12_12 + 4, p + 9*4); -+ } -+ } -+ else -+ { -+ for (i = 0; i < ARRAY_SIZE (plt_resolve); i++) -+ { -+ bfd_put_32 (output_bfd, plt_resolve[i], p); -+ p += 4; -+ } -+ p -= 4 * ARRAY_SIZE (plt_resolve); -+ -+ bfd_put_32 (output_bfd, -+ LIS_12 + PPC_HA (got + 4), p + 0*4); -+ bfd_put_32 (output_bfd, -+ ADDIS_11_11 + PPC_HA (-res0), p + 1*4); -+ bfd_put_32 (output_bfd, -+ ADDI_11_11 + PPC_LO (-res0), p + 3*4); -+ if (PPC_HA (got + 4) == PPC_HA (got + 8)) -+ { -+ bfd_put_32 (output_bfd, -+ LWZ_0_12 + PPC_LO (got + 4), p + 2*4); -+ bfd_put_32 (output_bfd, -+ LWZ_12_12 + PPC_LO (got + 8), p + 6*4); -+ } -+ else -+ { -+ bfd_put_32 (output_bfd, -+ LWZU_0_12 + PPC_LO (got + 4), p + 2*4); -+ bfd_put_32 (output_bfd, -+ LWZ_12_12 + 4, p + 6*4); -+ } -+ } -+ } -+ -+ if (htab->glink_eh_frame != NULL -+ && htab->glink_eh_frame->contents != NULL) -+ { -+ unsigned char *p = htab->glink_eh_frame->contents; -+ bfd_vma val; -+ -+ p += sizeof (glink_eh_frame_cie); -+ /* FDE length. */ -+ p += 4; -+ /* CIE pointer. */ -+ p += 4; -+ /* Offset to .glink. */ -+ val = (htab->glink->output_section->vma -+ + htab->glink->output_offset); -+ val -= (htab->glink_eh_frame->output_section->vma -+ + htab->glink_eh_frame->output_offset); -+ val -= p - htab->glink_eh_frame->contents; -+ bfd_put_32 (htab->elf.dynobj, val, p); -+ -+ if (htab->glink_eh_frame->sec_info_type == SEC_INFO_TYPE_EH_FRAME -+ && !_bfd_elf_write_section_eh_frame (output_bfd, info, -+ htab->glink_eh_frame, -+ htab->glink_eh_frame->contents)) -+ return FALSE; -+ } -+ -+ return ret; -+} -+ -+#define TARGET_BIG_SYM bfd_elf32_amigaos_vec -+#define TARGET_BIG_NAME "elf32-amigaos" -+#define ELF_ARCH bfd_arch_powerpc -+#define ELF_TARGET_ID PPC32_ELF_DATA -+#define ELF_MACHINE_CODE EM_PPC -+#ifdef __QNXTARGET__ -+#define ELF_MAXPAGESIZE 0x1000 -+#else -+#define ELF_MAXPAGESIZE 0x10000 -+#endif -+#define ELF_MINPAGESIZE 0x1000 -+#define ELF_COMMONPAGESIZE 0x1000 -+#define elf_info_to_howto ppc_elf_info_to_howto -+ -+#ifdef EM_CYGNUS_POWERPC -+#define ELF_MACHINE_ALT1 EM_CYGNUS_POWERPC -+#endif -+ -+#ifdef EM_PPC_OLD -+#define ELF_MACHINE_ALT2 EM_PPC_OLD -+#endif -+ -+#define elf_backend_plt_not_loaded 1 -+#define elf_backend_can_gc_sections 1 -+#define elf_backend_can_refcount 1 -+#define elf_backend_rela_normal 1 -+ -+#define bfd_elf32_mkobject ppc_elf_mkobject -+#define bfd_elf32_bfd_merge_private_bfd_data ppc_elf_merge_private_bfd_data -+#define bfd_elf32_bfd_relax_section ppc_elf_relax_section -+#define bfd_elf32_bfd_reloc_type_lookup ppc_elf_reloc_type_lookup -+#define bfd_elf32_bfd_reloc_name_lookup ppc_elf_reloc_name_lookup -+#define bfd_elf32_bfd_set_private_flags ppc_elf_set_private_flags -+#define bfd_elf32_bfd_link_hash_table_create ppc_elf_link_hash_table_create -+#define bfd_elf32_get_synthetic_symtab ppc_elf_get_synthetic_symtab -+ -+#define elf_backend_object_p ppc_elf_object_p -+#define elf_backend_gc_mark_hook ppc_elf_gc_mark_hook -+#define elf_backend_gc_sweep_hook ppc_elf_gc_sweep_hook -+#define elf_backend_section_from_shdr ppc_elf_section_from_shdr -+#define elf_backend_relocate_section ppc_elf_relocate_section -+#define elf_backend_create_dynamic_sections ppc_elf_create_dynamic_sections -+#define elf_backend_check_relocs ppc_elf_check_relocs -+#define elf_backend_copy_indirect_symbol ppc_elf_copy_indirect_symbol -+#define elf_backend_adjust_dynamic_symbol ppc_elf_adjust_dynamic_symbol -+#define elf_backend_add_symbol_hook ppc_elf_add_symbol_hook -+#define elf_backend_size_dynamic_sections ppc_elf_size_dynamic_sections -+#define elf_backend_hash_symbol ppc_elf_hash_symbol -+#define elf_backend_finish_dynamic_symbol ppc_elf_finish_dynamic_symbol -+#define elf_backend_finish_dynamic_sections ppc_elf_finish_dynamic_sections -+#define elf_backend_fake_sections ppc_elf_fake_sections -+#define elf_backend_additional_program_headers ppc_elf_additional_program_headers -+#define elf_backend_modify_segment_map ppc_elf_amigaos_modify_segment_map -+#define elf_backend_grok_prstatus ppc_elf_grok_prstatus -+#define elf_backend_grok_psinfo ppc_elf_grok_psinfo -+#define elf_backend_write_core_note ppc_elf_write_core_note -+#define elf_backend_reloc_type_class ppc_elf_reloc_type_class -+#define elf_backend_begin_write_processing ppc_elf_amigaos_begin_write_processing -+#define elf_backend_final_write_processing ppc_elf_amigaos_final_write_processing -+#define elf_backend_write_section ppc_elf_amigaos_write_section -+#define elf_backend_get_sec_type_attr ppc_elf_get_sec_type_attr -+#define elf_backend_plt_sym_val ppc_elf_plt_sym_val -+#define elf_backend_action_discarded ppc_elf_action_discarded -+#define elf_backend_init_index_section _bfd_elf_init_1_index_section -+#define elf_backend_post_process_headers _bfd_elf_set_osabi -+#define elf_backend_lookup_section_flags_hook ppc_elf_lookup_section_flags -+#define elf_backend_section_processing ppc_elf_amigaos_section_processing -+ -+#include "elf32-target.h" ---- /dev/null 2015-09-06 08:42:34.091999986 +0100 +++ ld/emultempl/amigaos.em 2016-01-03 01:46:50.647001071 +0000 @@ -0,0 +1,2513 @@ +# This shell script emits a C file. -*- C -*- -- cgit v1.2.3