From f8aad68778cdb783c3e3afb9732ae611e0a3d22f Mon Sep 17 00:00:00 2001 From: Chris Young Date: Mon, 8 Jan 2018 21:25:33 +0000 Subject: Update with latest binutils patches from github.com/sba1/adtools --- .../0001-Changes-for-various-Amiga-targets.p | 1601 ++- ...rrors-occuring-with-more-recent-versions-of-t.p | 40 +- ...d-some-stuff-such-that-68k-vtarget-builds-aga.p | 8 +- ...ymbol-name-when-an-unexpected-type-was-encoun.p | 8 +- .../binutils/0005-Bind-in-the-ld-unwind-options.p | 8 +- .../0006-Introduced-strip-unneeded-rel-relocs.p | 8 +- ...mbols-for-stripped-sections.-This-is-importan.p | 8 +- .../binutils/0008-Fix-undefined-behaviour.p | 113 + .../recipes/patches/binutils/missing-files.p | 12492 ------------------- 9 files changed, 1573 insertions(+), 12713 deletions(-) create mode 100644 ppc-amigaos/recipes/patches/binutils/0008-Fix-undefined-behaviour.p delete mode 100644 ppc-amigaos/recipes/patches/binutils/missing-files.p (limited to 'ppc-amigaos/recipes') diff --git a/ppc-amigaos/recipes/patches/binutils/0001-Changes-for-various-Amiga-targets.p b/ppc-amigaos/recipes/patches/binutils/0001-Changes-for-various-Amiga-targets.p index ccc8a07..06d746a 100644 --- a/ppc-amigaos/recipes/patches/binutils/0001-Changes-for-various-Amiga-targets.p +++ b/ppc-amigaos/recipes/patches/binutils/0001-Changes-for-various-Amiga-targets.p @@ -1,7 +1,7 @@ From 1678a95339b8893195b307a953a0053ceeca0133 Mon Sep 17 00:00:00 2001 From: Sebastian Bauer Date: Sat, 14 Feb 2015 14:54:44 +0100 -Subject: [PATCH 1/7] Changes for various Amiga targets. +Subject: [PATCH 1/8] Changes for various Amiga targets. --- bfd/ChangeLog-9697 | 64 + @@ -156,8 +156,8 @@ Subject: [PATCH 1/7] Changes for various Amiga targets. diff --git a/bfd/ChangeLog-9697 b/bfd/ChangeLog-9697 index e9a5c1d60a313aaf09d1a8add619022cfdf575fa..1c2bb3f3c91d32e8b95f8b0cf16b98c58cde454b 100644 ---- bfd/ChangeLog-9697 -+++ bfd/ChangeLog-9697 +--- a/bfd/ChangeLog-9697 ++++ b/bfd/ChangeLog-9697 @@ -46,12 +46,19 @@ Mon Dec 22 13:20:57 1997 Ian Lance Taylor Mon Dec 22 13:04:33 1997 Joel Sherrill @@ -341,8 +341,8 @@ index e9a5c1d60a313aaf09d1a8add619022cfdf575fa..1c2bb3f3c91d32e8b95f8b0cf16b98c5 (h8300_symbol_address_p): New function. diff --git a/bfd/ChangeLog-9899 b/bfd/ChangeLog-9899 index 6d7f5cd616db22097b8238d8686f60484c9e6ee6..6e25901995a73646a13037d32c14563df20f74b3 100644 ---- bfd/ChangeLog-9899 -+++ bfd/ChangeLog-9899 +--- a/bfd/ChangeLog-9899 ++++ b/bfd/ChangeLog-9899 @@ -5570,12 +5570,17 @@ Wed Jan 21 21:16:06 1998 Manfred Hollstein (GET_SCNDHR_NLNNO): Likewise. @@ -363,8 +363,8 @@ index 6d7f5cd616db22097b8238d8686f60484c9e6ee6..6e25901995a73646a13037d32c14563d diff --git a/bfd/Makefile.am b/bfd/Makefile.am index 9ab2aa947a0a96ba5a469652c579a4d181793646..c224a3cecc392df96a6bc20c8dc73eb81c677269 100644 ---- bfd/Makefile.am -+++ bfd/Makefile.am +--- a/bfd/Makefile.am ++++ b/bfd/Makefile.am @@ -232,13 +232,16 @@ ALL_MACHINES_CFILES = \ cpu-z80.c \ cpu-z8k.c @@ -485,8 +485,8 @@ index 9ab2aa947a0a96ba5a469652c579a4d181793646..c224a3cecc392df96a6bc20c8dc73eb8 -@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< $(NO_WERROR) diff --git a/bfd/Makefile.in b/bfd/Makefile.in index 99902757111d8011447cde1dda030e5a9c817ff2..bcdf435a15eb144bca66d8bfe04122a45e647446 100644 ---- bfd/Makefile.in -+++ bfd/Makefile.in +--- a/bfd/Makefile.in ++++ b/bfd/Makefile.in @@ -532,13 +532,16 @@ ALL_MACHINES_CFILES = \ cpu-z8k.c @@ -658,7 +658,7 @@ diff --git a/bfd/amigaos.c b/bfd/amigaos.c new file mode 100644 index 0000000000000000000000000000000000000000..9d715d64d458e6599c19ed65fbb61c253d2ab208 --- /dev/null -+++ bfd/amigaos.c ++++ b/bfd/amigaos.c @@ -0,0 +1,3189 @@ +/* BFD back-end for Commodore-Amiga AmigaOS binaries. + Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998 @@ -3853,7 +3853,7 @@ diff --git a/bfd/amigaoslink.c b/bfd/amigaoslink.c new file mode 100644 index 0000000000000000000000000000000000000000..9067a0a06b933c67bfd3542b299d1adb281182c3 --- /dev/null -+++ bfd/amigaoslink.c ++++ b/bfd/amigaoslink.c @@ -0,0 +1,1032 @@ +/* BFD back-end for Commodore-Amiga AmigaOS binaries. Linker routines. + Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998 @@ -4891,7 +4891,7 @@ diff --git a/bfd/aout-amiga.c b/bfd/aout-amiga.c new file mode 100644 index 0000000000000000000000000000000000000000..ced7584521b89943b1636d2b4c9b884242cd81c6 --- /dev/null -+++ bfd/aout-amiga.c ++++ b/bfd/aout-amiga.c @@ -0,0 +1,152 @@ +/* BFD back-end for Amiga style m68k a.out binaries. + Copyright (C) 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc. @@ -5047,8 +5047,8 @@ index 0000000000000000000000000000000000000000..ced7584521b89943b1636d2b4c9b8842 +} diff --git a/bfd/aoutx.h b/bfd/aoutx.h index 1e0ad38f95bcf990a9ffd4cfb89eae3f6496740c..2641f975fd575d0a651540dc886eeee68cf4b173 100644 ---- bfd/aoutx.h -+++ bfd/aoutx.h +--- a/bfd/aoutx.h ++++ b/bfd/aoutx.h @@ -127,12 +127,16 @@ DESCRIPTION #include "libaout.h" #include "libbfd.h" @@ -5135,8 +5135,8 @@ index 1e0ad38f95bcf990a9ffd4cfb89eae3f6496740c..2641f975fd575d0a651540dc886eeee6 r_extern = 0; diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index e496083d6ebb0842cfe0a7777dc76cdbd18c7134..8a4d566298f86c56c4a2d21895a39e0d7c5002d7 100644 ---- bfd/bfd-in2.h -+++ bfd/bfd-in2.h +--- a/bfd/bfd-in2.h ++++ b/bfd/bfd-in2.h @@ -3128,12 +3128,16 @@ instruction. */ BFD_RELOC_PPC_EMB_RELSEC16, BFD_RELOC_PPC_EMB_RELST_LO, @@ -5203,8 +5203,8 @@ index e496083d6ebb0842cfe0a7777dc76cdbd18c7134..8a4d566298f86c56c4a2d21895a39e0d bfd_target_ieee_flavour, diff --git a/bfd/bfd.c b/bfd/bfd.c index eed18960855bdc51be8b57ddba27975afb6b02ef..3487694a541417ec20453ca9116bbb86c383f979 100644 ---- bfd/bfd.c -+++ bfd/bfd.c +--- a/bfd/bfd.c ++++ b/bfd/bfd.c @@ -261,12 +261,13 @@ CODE_FRAGMENT . struct mach_o_data_struct *mach_o_data; . struct mach_o_fat_data_struct *mach_o_fat_data; @@ -5221,8 +5221,8 @@ index eed18960855bdc51be8b57ddba27975afb6b02ef..3487694a541417ec20453ca9116bbb86 . void *usrdata; diff --git a/bfd/bfdio.c b/bfd/bfdio.c index be05581aeb4026addd3f4caf2b185ae73d893a24..a15208b16635c7174592b6ccf26685c4b1d05bc8 100644 ---- bfd/bfdio.c -+++ bfd/bfdio.c +--- a/bfd/bfdio.c ++++ b/bfd/bfdio.c @@ -325,12 +325,37 @@ bfd_seek (bfd *abfd, file_ptr position, int direction) if (abfd->iovec) @@ -5263,8 +5263,8 @@ index be05581aeb4026addd3f4caf2b185ae73d893a24..a15208b16635c7174592b6ccf26685c4 bfd_tell (abfd); diff --git a/bfd/config.bfd b/bfd/config.bfd index 6025f2641b47915c79a7d643963e9d9080e0ed5c..fcbbce847bc65a44ee68deedd93b2943aac9f77f 100644 ---- bfd/config.bfd -+++ bfd/config.bfd +--- a/bfd/config.bfd ++++ b/bfd/config.bfd @@ -78,15 +78,17 @@ c30*) targ_archs=bfd_tic30_arch ;; c4x*) targ_archs=bfd_tic4x_arch ;; c54x*) targ_archs=bfd_tic54x_arch ;; @@ -5362,8 +5362,8 @@ index 6025f2641b47915c79a7d643963e9d9080e0ed5c..fcbbce847bc65a44ee68deedd93b2943 ;; diff --git a/bfd/configure b/bfd/configure index e965796ef43d9346cd917bf20243707633fc632e..018a5913f1d96081342c66a64f0167b11cdb1add 100755 ---- bfd/configure -+++ bfd/configure +--- a/bfd/configure ++++ b/bfd/configure @@ -15172,13 +15172,15 @@ do case "$vec" in # This list is alphabetized to make it easy to compare @@ -5424,8 +5424,8 @@ index e965796ef43d9346cd917bf20243707633fc632e..018a5913f1d96081342c66a64f0167b1 tb="$tb elfn32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;; diff --git a/bfd/configure.host b/bfd/configure.host index 7c63de58397426d08501dd7a0fd527cb59a9809c..afa7c909a787d9121d01e4e99d8047cf7f11f0b7 100644 ---- bfd/configure.host -+++ bfd/configure.host +--- a/bfd/configure.host ++++ b/bfd/configure.host @@ -53,12 +53,13 @@ mips64*-*-linux*) host64=true;; mips64*-*-freebsd* | mips64*-*-kfreebsd*-gnu) host64=true;; mips*-*-sysv4*) ;; @@ -5442,8 +5442,8 @@ index 7c63de58397426d08501dd7a0fd527cb59a9809c..afa7c909a787d9121d01e4e99d8047cf *-*-solaris2.11) HDEFINES=-DCP_ACP=1 ;; diff --git a/bfd/configure.in b/bfd/configure.in index 4b4cb617ef74f5fb33e4de13856d685f5ffba025..5d882b3701b6e0d93f97be655123a2bb2728d63a 100644 ---- bfd/configure.in -+++ bfd/configure.in +--- a/bfd/configure.in ++++ b/bfd/configure.in @@ -664,13 +664,15 @@ do case "$vec" in # This list is alphabetized to make it easy to compare @@ -5504,8 +5504,8 @@ index 4b4cb617ef74f5fb33e4de13856d685f5ffba025..5d882b3701b6e0d93f97be655123a2bb tb="$tb elfn32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;; diff --git a/bfd/doc/Makefile.am b/bfd/doc/Makefile.am index 7476ee5bab710b6b418072124b473cf0d340b247..1ddc9e3d2153b55f6f26645e5fc584074bb369fd 100644 ---- bfd/doc/Makefile.am -+++ bfd/doc/Makefile.am +--- a/bfd/doc/Makefile.am ++++ b/bfd/doc/Makefile.am @@ -1,11 +1,11 @@ ## Process this file with automake to generate Makefile.in @@ -5560,8 +5560,8 @@ index 7476ee5bab710b6b418072124b473cf0d340b247..1ddc9e3d2153b55f6f26645e5fc58407 $(srcdir)/../bfdwin.c \ diff --git a/bfd/doc/Makefile.in b/bfd/doc/Makefile.in index 7ba351d742bf53f9e5f51ad7ef74150295519f1a..67db3caf9886839b8d8f52a2a1878de878bb2f6a 100644 ---- bfd/doc/Makefile.in -+++ bfd/doc/Makefile.in +--- a/bfd/doc/Makefile.in ++++ b/bfd/doc/Makefile.in @@ -268,13 +268,13 @@ target_vendor = @target_vendor@ tdefaults = @tdefaults@ top_build_prefix = @top_build_prefix@ @@ -5618,8 +5618,8 @@ index 7ba351d742bf53f9e5f51ad7ef74150295519f1a..67db3caf9886839b8d8f52a2a1878de8 */header.sed) break ;; \ diff --git a/bfd/doc/bfd.texinfo b/bfd/doc/bfd.texinfo index 45ffa73240ea22a74debe916fcd7e068a947a7dc..7b9774b71a3cb9b3c154c8c75a41de29a6813146 100644 ---- bfd/doc/bfd.texinfo -+++ bfd/doc/bfd.texinfo +--- a/bfd/doc/bfd.texinfo ++++ b/bfd/doc/bfd.texinfo @@ -286,12 +286,13 @@ structures. @chapter BFD back ends @menu @@ -5663,7 +5663,7 @@ diff --git a/bfd/elf32-amiga.c b/bfd/elf32-amiga.c new file mode 100644 index 0000000000000000000000000000000000000000..cf6c6cb9efdd15c786932adedd2476ec3a4bc08d --- /dev/null -+++ bfd/elf32-amiga.c ++++ b/bfd/elf32-amiga.c @@ -0,0 +1,3844 @@ +/* PowerPC-specific support for 32-bit ELF + Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 @@ -9509,11 +9509,790 @@ index 0000000000000000000000000000000000000000..cf6c6cb9efdd15c786932adedd2476ec +#define elf_backend_reloc_type_class ppc_elf_reloc_type_class + +#include "elf32-target.h" +diff --git a/bfd/elf32-ppc.c b/bfd/elf32-amigaos.c +similarity index 97% +copy from bfd/elf32-ppc.c +copy to bfd/elf32-amigaos.c +index 6454a8350da35adf6ed1e2209d9e4774ab7c50e3..9bf9535888f2345d60a8f802680ae03f41f67a5f 100644 +--- a/bfd/elf32-ppc.c ++++ b/bfd/elf32-amigaos.c +@@ -31,32 +31,50 @@ + #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 +@@ -1381,12 +1399,74 @@ static reloc_howto_type ppc_elf_howto_raw[] = { + /* 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) */ +@@ -1935,12 +2015,16 @@ ppc_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, + 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]; + }; +@@ -2268,13 +2352,13 @@ ppc_elf_lookup_section_flags (char *flag_name) + return 0; + } + + /* Add the VLE flag if required. */ + + bfd_boolean +-ppc_elf_section_processing (bfd *abfd, Elf_Internal_Shdr *shdr) ++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; +@@ -2285,12 +2369,15 @@ ppc_elf_section_processing (bfd *abfd, Elf_Internal_Shdr *shdr) + + 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. */ +@@ -2337,13 +2424,14 @@ ppc_elf_fake_sections (bfd *abfd ATTRIBUTE_UNUSED, + + static int + ppc_elf_additional_program_headers (bfd *abfd, + struct bfd_link_info *info ATTRIBUTE_UNUSED) + { + asection *s; +- int ret = 0; ++// 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"); +@@ -2353,13 +2441,13 @@ ppc_elf_additional_program_headers (bfd *abfd, + return ret; + } + + /* Modify the segment map for VLE executables. */ + + bfd_boolean +-ppc_elf_modify_segment_map (bfd *abfd, ++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; +@@ -2546,13 +2634,13 @@ apuinfo_list_finish (void) + #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_begin_write_processing (bfd *abfd, struct bfd_link_info *link_info) ++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; +@@ -2646,24 +2734,24 @@ ppc_elf_begin_write_processing (bfd *abfd, struct bfd_link_info *link_info) + } + + /* 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_write_section (bfd *abfd ATTRIBUTE_UNUSED, ++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_final_write_processing (bfd *abfd, bfd_boolean linker ATTRIBUTE_UNUSED) ++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; +@@ -3232,13 +3320,13 @@ ppc_elf_create_got (bfd *abfd, struct bfd_link_info *info) + abort (); + } + else + { + /* The powerpc .got has a blrl instruction in it. Mark it + executable. */ +- flags = (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS ++ 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"); +@@ -3340,13 +3428,13 @@ ppc_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) + + 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; ++ 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); + } + +@@ -3410,13 +3498,13 @@ ppc_elf_copy_indirect_symbol (struct bfd_link_info *info, + 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 ++ 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; + +@@ -4186,12 +4274,19 @@ ppc_elf_check_relocs (bfd *abfd, + 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; +@@ -4679,13 +4774,13 @@ ppc_elf_vle_split16 (bfd *output_bfd, bfd_byte *contents, + } + + + /* 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_select_plt_layout (bfd *output_bfd ATTRIBUTE_UNUSED, ++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; +@@ -4976,13 +5071,13 @@ ppc_elf_gc_sweep_hook (bfd *abfd, + } + + /* Set plt output section type, htab->tls_get_addr, and call the + generic ELF tls_setup function. */ + + asection * +-ppc_elf_tls_setup (bfd *obfd, ++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); +@@ -5075,13 +5170,13 @@ branch_reloc_hash_match (const bfd *ibfd, + } + + /* Run through all the TLS relocs looking for optimization + opportunities. */ + + bfd_boolean +-ppc_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, ++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; +@@ -6008,12 +6103,16 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, + 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"); +@@ -6037,12 +6136,16 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, + 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; +@@ -6400,12 +6503,16 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, + 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) + { +@@ -7172,13 +7279,13 @@ is_static_defined (struct elf_link_hash_entry *h) + + /* 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_ppc_at_tls_transform (unsigned int insn, unsigned int reg) ++_bfd_elf_amigaos_ppc_at_tls_transform (unsigned int insn, unsigned int reg) + { + unsigned int rtra; + + if ((insn & (0x3f << 26)) != 31 << 26) + return 0; + +@@ -7212,13 +7319,13 @@ _bfd_elf_ppc_at_tls_transform (unsigned int insn, unsigned int reg) + + /* 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_ppc_at_tprel_transform (unsigned int insn, unsigned int reg) ++_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 */ +@@ -8076,13 +8183,13 @@ ppc_elf_relocate_section (bfd *output_bfd, + /* 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_ppc_at_tprel_transform (insn, 2); ++ 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 +@@ -8502,13 +8609,47 @@ ppc_elf_relocate_section (bfd *output_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; + +@@ -8899,12 +9040,15 @@ ppc_elf_relocate_section (bfd *output_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; +@@ -9124,18 +9268,24 @@ ppc_elf_finish_dynamic_symbol (bfd *output_bfd, + || 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); +@@ -9166,24 +9316,34 @@ ppc_elf_finish_dynamic_symbol (bfd *output_bfd, + * 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) +- sym->st_value = 0; ++ { ++ /* 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; +@@ -9275,12 +9435,15 @@ ppc_elf_finish_dynamic_symbol (bfd *output_bfd, + 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; + } + +@@ -9735,16 +9898,14 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd, + return FALSE; + } + + return ret; + } + +-#define TARGET_LITTLE_SYM bfd_elf32_powerpcle_vec +-#define TARGET_LITTLE_NAME "elf32-powerpcle" +-#define TARGET_BIG_SYM bfd_elf32_powerpc_vec +-#define TARGET_BIG_NAME "elf32-powerpc" ++#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 +@@ -9789,153 +9950,23 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd, + #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_modify_segment_map ++#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_begin_write_processing +-#define elf_backend_final_write_processing ppc_elf_final_write_processing +-#define elf_backend_write_section ppc_elf_write_section ++#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_section_processing +- +-#include "elf32-target.h" +- +-/* FreeBSD Target */ +- +-#undef TARGET_LITTLE_SYM +-#undef TARGET_LITTLE_NAME +- +-#undef TARGET_BIG_SYM +-#define TARGET_BIG_SYM bfd_elf32_powerpc_freebsd_vec +-#undef TARGET_BIG_NAME +-#define TARGET_BIG_NAME "elf32-powerpc-freebsd" +- +-#undef ELF_OSABI +-#define ELF_OSABI ELFOSABI_FREEBSD +- +-#undef elf32_bed +-#define elf32_bed elf32_powerpc_fbsd_bed +- +-#include "elf32-target.h" +- +-/* VxWorks Target */ +- +-#undef TARGET_LITTLE_SYM +-#undef TARGET_LITTLE_NAME +- +-#undef TARGET_BIG_SYM +-#define TARGET_BIG_SYM bfd_elf32_powerpc_vxworks_vec +-#undef TARGET_BIG_NAME +-#define TARGET_BIG_NAME "elf32-powerpc-vxworks" +- +-#undef ELF_OSABI +- +-/* VxWorks uses the elf default section flags for .plt. */ +-static const struct bfd_elf_special_section * +-ppc_elf_vxworks_get_sec_type_attr (bfd *abfd ATTRIBUTE_UNUSED, asection *sec) +-{ +- if (sec->name == NULL) +- return NULL; +- +- if (strcmp (sec->name, ".plt") == 0) +- return _bfd_elf_get_sec_type_attr (abfd, sec); +- +- return ppc_elf_get_sec_type_attr (abfd, sec); +-} +- +-/* Like ppc_elf_link_hash_table_create, but overrides +- appropriately for VxWorks. */ +-static struct bfd_link_hash_table * +-ppc_elf_vxworks_link_hash_table_create (bfd *abfd) +-{ +- struct bfd_link_hash_table *ret; +- +- ret = ppc_elf_link_hash_table_create (abfd); +- if (ret) +- { +- struct ppc_elf_link_hash_table *htab +- = (struct ppc_elf_link_hash_table *)ret; +- htab->is_vxworks = 1; +- htab->plt_type = PLT_VXWORKS; +- htab->plt_entry_size = VXWORKS_PLT_ENTRY_SIZE; +- htab->plt_slot_size = VXWORKS_PLT_ENTRY_SIZE; +- htab->plt_initial_entry_size = VXWORKS_PLT_INITIAL_ENTRY_SIZE; +- } +- return ret; +-} +- +-/* Tweak magic VxWorks symbols as they are loaded. */ +-static bfd_boolean +-ppc_elf_vxworks_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 (!elf_vxworks_add_symbol_hook(abfd, info, sym,namep, flagsp, secp, +- valp)) +- return FALSE; +- +- return ppc_elf_add_symbol_hook(abfd, info, sym,namep, flagsp, secp, valp); +-} +- +-static void +-ppc_elf_vxworks_final_write_processing (bfd *abfd, bfd_boolean linker) +-{ +- ppc_elf_final_write_processing(abfd, linker); +- elf_vxworks_final_write_processing(abfd, linker); +-} +- +-/* On VxWorks, we emit relocations against _PROCEDURE_LINKAGE_TABLE_, so +- define it. */ +-#undef elf_backend_want_plt_sym +-#define elf_backend_want_plt_sym 1 +-#undef elf_backend_want_got_plt +-#define elf_backend_want_got_plt 1 +-#undef elf_backend_got_symbol_offset +-#define elf_backend_got_symbol_offset 0 +-#undef elf_backend_plt_not_loaded +-#define elf_backend_plt_not_loaded 0 +-#undef elf_backend_plt_readonly +-#define elf_backend_plt_readonly 1 +-#undef elf_backend_got_header_size +-#define elf_backend_got_header_size 12 +- +-#undef bfd_elf32_get_synthetic_symtab +- +-#undef bfd_elf32_bfd_link_hash_table_create +-#define bfd_elf32_bfd_link_hash_table_create \ +- ppc_elf_vxworks_link_hash_table_create +-#undef elf_backend_add_symbol_hook +-#define elf_backend_add_symbol_hook \ +- ppc_elf_vxworks_add_symbol_hook +-#undef elf_backend_link_output_symbol_hook +-#define elf_backend_link_output_symbol_hook \ +- elf_vxworks_link_output_symbol_hook +-#undef elf_backend_final_write_processing +-#define elf_backend_final_write_processing \ +- ppc_elf_vxworks_final_write_processing +-#undef elf_backend_get_sec_type_attr +-#define elf_backend_get_sec_type_attr \ +- ppc_elf_vxworks_get_sec_type_attr +-#undef elf_backend_emit_relocs +-#define elf_backend_emit_relocs \ +- elf_vxworks_emit_relocs +- +-#undef elf32_bed +-#define elf32_bed ppc_elf_vxworks_bed +-#undef elf_backend_post_process_headers ++#define elf_backend_section_processing ppc_elf_amigaos_section_processing + + #include "elf32-target.h" diff --git a/bfd/elf32-i386-amithlon.c b/bfd/elf32-i386-amithlon.c new file mode 100644 index 0000000000000000000000000000000000000000..4e029a5e90187a96013ed97e078fba920d95db28 --- /dev/null -+++ bfd/elf32-i386-amithlon.c ++++ b/bfd/elf32-i386-amithlon.c @@ -0,0 +1,198 @@ +/* Intel IA-32 specific support for 32-bit big endian ELF on Amithlon. + Copyright 2002 Free Software Foundation, Inc. @@ -9715,8 +10494,8 @@ index 0000000000000000000000000000000000000000..4e029a5e90187a96013ed97e078fba92 +#include "elf32-i386.c" diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c index 0a6b22ec19ec9daee29e49c64c5d3ba2299e99c1..46396c83d45bab97de1470ee44ffa21f9d03e4b4 100644 ---- bfd/elf32-i386.c -+++ bfd/elf32-i386.c +--- a/bfd/elf32-i386.c ++++ b/bfd/elf32-i386.c @@ -29,12 +29,16 @@ #include "elf-vxworks.h" #include "bfd_stdint.h" @@ -9824,7 +10603,7 @@ diff --git a/bfd/elf32-morphos.c b/bfd/elf32-morphos.c new file mode 100644 index 0000000000000000000000000000000000000000..accc2d426bede6c9441313115fcd5ab5f99630f9 --- /dev/null -+++ bfd/elf32-morphos.c ++++ b/bfd/elf32-morphos.c @@ -0,0 +1,7137 @@ +/* PowerPC-specific support for 32-bit ELF + Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 @@ -16965,8 +17744,8 @@ index 0000000000000000000000000000000000000000..accc2d426bede6c9441313115fcd5ab5 +#include "elf32-target.h" diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c index 6454a8350da35adf6ed1e2209d9e4774ab7c50e3..5c92c53da7b3dec8f85a0a0b930190635f89dcfb 100644 ---- bfd/elf32-ppc.c -+++ bfd/elf32-ppc.c +--- a/bfd/elf32-ppc.c ++++ b/bfd/elf32-ppc.c @@ -4412,12 +4412,16 @@ ppc_elf_check_relocs (bfd *abfd, p->count += 1; if (!must_be_dyn_reloc (info, r_type)) @@ -16988,7 +17767,7 @@ diff --git a/bfd/hosts/amigaos.h b/bfd/hosts/amigaos.h new file mode 100644 index 0000000000000000000000000000000000000000..dc62d7f837f333ae8d2c5b47d01144cb0d3625f2 --- /dev/null -+++ bfd/hosts/amigaos.h ++++ b/bfd/hosts/amigaos.h @@ -0,0 +1,5 @@ +/* Host configuration for AmigaOS */ +#ifndef hosts_amigaos_h @@ -16999,7 +17778,7 @@ diff --git a/bfd/hosts/morphos.h b/bfd/hosts/morphos.h new file mode 100644 index 0000000000000000000000000000000000000000..d3c60ea9f5767ad0bfa22ba2c8c1e5ed9d94d481 --- /dev/null -+++ bfd/hosts/morphos.h ++++ b/bfd/hosts/morphos.h @@ -0,0 +1,5 @@ +/* Host configuration for MorphOS */ +#ifndef hosts_morphos_h @@ -17010,7 +17789,7 @@ diff --git a/bfd/libamiga.h b/bfd/libamiga.h new file mode 100644 index 0000000000000000000000000000000000000000..351f0fa16a45680982f5b5807c8ba756defe1764 --- /dev/null -+++ bfd/libamiga.h ++++ b/bfd/libamiga.h @@ -0,0 +1,187 @@ +/* BFD back-end for Commodore-Amiga AmigaOS binaries. Data structures. + Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998 @@ -17201,8 +17980,8 @@ index 0000000000000000000000000000000000000000..351f0fa16a45680982f5b5807c8ba756 +#endif /* MEMF_ANY */ diff --git a/bfd/libbfd.h b/bfd/libbfd.h index 6c48d641f606b9ed6158b4567021769bacfbd54a..3cb9b36fe2379a5d7f118472e106c151d6153aea 100644 ---- bfd/libbfd.h -+++ bfd/libbfd.h +--- a/bfd/libbfd.h ++++ b/bfd/libbfd.h @@ -1345,12 +1345,16 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_PPC_EMB_RELSEC16", "BFD_RELOC_PPC_EMB_RELST_LO", @@ -17239,8 +18018,8 @@ index 6c48d641f606b9ed6158b4567021769bacfbd54a..3cb9b36fe2379a5d7f118472e106c151 "BFD_RELOC_ARM_PCREL_CALL", diff --git a/bfd/linker.c b/bfd/linker.c index d3ef9a43a5bca8096221870248daf58007c6ef78..4f0aa188f5017ea68023530f6ae9eaa6b98b5b11 100644 ---- bfd/linker.c -+++ bfd/linker.c +--- a/bfd/linker.c ++++ b/bfd/linker.c @@ -430,13 +430,14 @@ static bfd_boolean generic_link_add_symbol_list (bfd *, struct bfd_link_info *, bfd_size_type count, asymbol **, bfd_boolean); @@ -17334,8 +18113,8 @@ index d3ef9a43a5bca8096221870248daf58007c6ef78..4f0aa188f5017ea68023530f6ae9eaa6 { diff --git a/bfd/reloc.c b/bfd/reloc.c index 47d052d1345847a7178f4c7ebe4f529396ae0a4f..6c3bb68f2da65b201b6288b8709fd60d9b0d5b2c 100644 ---- bfd/reloc.c -+++ bfd/reloc.c +--- a/bfd/reloc.c ++++ b/bfd/reloc.c @@ -2803,12 +2803,20 @@ ENUMX BFD_RELOC_PPC_EMB_RELST_HA ENUMX @@ -17383,8 +18162,8 @@ index 47d052d1345847a7178f4c7ebe4f529396ae0a4f..6c3bb68f2da65b201b6288b8709fd60d BFD_RELOC_CTOR diff --git a/bfd/targets.c b/bfd/targets.c index fa206d24bef3a22255f6be42221647db3142eb06..9df24504bab564048f724fbbb641ca13c5805602 100644 ---- bfd/targets.c -+++ bfd/targets.c +--- a/bfd/targets.c ++++ b/bfd/targets.c @@ -144,12 +144,13 @@ DESCRIPTION the entry points which call them. Too bad we can't have one macro to define them both! @@ -17515,8 +18294,8 @@ index fa206d24bef3a22255f6be42221647db3142eb06..9df24504bab564048f724fbbb641ca13 &bfd_elf32_ntradbigmips_vec, diff --git a/binutils/objcopy.c b/binutils/objcopy.c index 020d54d6fbe27a5c90600e1d034a93e8fade0ff6..88bd071eefa8b5426eaadfd6431e9de5d4a4591b 100644 ---- binutils/objcopy.c -+++ binutils/objcopy.c +--- a/binutils/objcopy.c ++++ b/binutils/objcopy.c @@ -1101,12 +1101,17 @@ filter_symbols (bfd *abfd, bfd *obfd, asymbol **osyms, bfd_boolean undefined; bfd_boolean rem_leading_char; @@ -17659,8 +18438,8 @@ index 020d54d6fbe27a5c90600e1d034a93e8fade0ff6..88bd071eefa8b5426eaadfd6431e9de5 diff --git a/binutils/readelf.c b/binutils/readelf.c index d9ec436af6fbea0bbc3dfa8e9cd40fcf9be140cf..f52d7168af3bc6559bd2483ff1fc126da385b38d 100644 ---- binutils/readelf.c -+++ binutils/readelf.c +--- a/binutils/readelf.c ++++ b/binutils/readelf.c @@ -150,12 +150,13 @@ #include "elf/vax.h" #include "elf/x86-64.h" @@ -17707,8 +18486,8 @@ index d9ec436af6fbea0bbc3dfa8e9cd40fcf9be140cf..f52d7168af3bc6559bd2483ff1fc126d break; diff --git a/binutils/rename.c b/binutils/rename.c index 5923a3f4ce2b2b5b0da96ff8225bf3c7750563bc..354b6fd1eab7f632995fed27698c76826ee8e753 100644 ---- binutils/rename.c -+++ binutils/rename.c +--- a/binutils/rename.c ++++ b/binutils/rename.c @@ -27,13 +27,13 @@ #else /* ! HAVE_GOOD_UTIME_H */ #ifdef HAVE_UTIMES @@ -17741,8 +18520,8 @@ index 5923a3f4ce2b2b5b0da96ff8225bf3c7750563bc..354b6fd1eab7f632995fed27698c7682 diff --git a/config.sub b/config.sub index 59bb593f109c8d795df4cbb96b015222eed91c07..88ccfd90050ad0d8d341c091b9920f62fc5996f8 100755 ---- config.sub -+++ config.sub +--- a/config.sub ++++ b/config.sub @@ -353,13 +353,13 @@ case $basic_machine in basic_machine=armel-unknown ;; @@ -17797,7 +18576,7 @@ diff --git a/config/mh-amigaos b/config/mh-amigaos new file mode 100644 index 0000000000000000000000000000000000000000..4889ea41c6889e2e15c06c8f355c30b5eb2aa5f4 --- /dev/null -+++ config/mh-amigaos ++++ b/config/mh-amigaos @@ -0,0 +1,13 @@ +# Host makefile fragment for Commodore Amiga running AmigaOS. + @@ -17816,7 +18595,7 @@ diff --git a/config/mh-morphos b/config/mh-morphos new file mode 100644 index 0000000000000000000000000000000000000000..c00202aec0389eaa067ea48818a7d8fa4fd5fc6b --- /dev/null -+++ config/mh-morphos ++++ b/config/mh-morphos @@ -0,0 +1,13 @@ +# Host makefile fragment for Commodore Amiga running AmigaOS. + @@ -17833,8 +18612,8 @@ index 0000000000000000000000000000000000000000..c00202aec0389eaa067ea48818a7d8fa +HARDLINK = cp diff --git a/configure b/configure index 6079e6c07511e12bb51ae5197e7110d79c36b098..9667d72a79baf032fa22e054b88fb03e64673b63 100755 ---- configure -+++ configure +--- a/configure ++++ b/configure @@ -3630,12 +3630,15 @@ case "${noconfigdirs}" in esac @@ -17869,8 +18648,8 @@ index 6079e6c07511e12bb51ae5197e7110d79c36b098..9667d72a79baf032fa22e054b88fb03e ;; diff --git a/configure.ac b/configure.ac index 5efb4a32f114f23b90f838a5108f5016dc01bf43..fea7239acf315d982587796d8b93de4c894a14d8 100644 ---- configure.ac -+++ configure.ac +--- a/configure.ac ++++ b/configure.ac @@ -1056,12 +1056,15 @@ case "${noconfigdirs}" in esac @@ -17905,8 +18684,8 @@ index 5efb4a32f114f23b90f838a5108f5016dc01bf43..fea7239acf315d982587796d8b93de4c ;; diff --git a/gas/ChangeLog-9697 b/gas/ChangeLog-9697 index f39e99554e87446d7eb8f0869701984c5df2137d..08dbfbc1d36608ec8e553593d445431cb1792cc5 100644 ---- gas/ChangeLog-9697 -+++ gas/ChangeLog-9697 +--- a/gas/ChangeLog-9697 ++++ b/gas/ChangeLog-9697 @@ -874,12 +874,18 @@ Tue Aug 26 12:23:25 1997 Ian Lance Taylor Gabriel Paubert . @@ -17947,8 +18726,8 @@ index f39e99554e87446d7eb8f0869701984c5df2137d..08dbfbc1d36608ec8e553593d445431c Fri Nov 8 13:55:03 1996 Martin M. Hunt diff --git a/gas/ChangeLog-9899 b/gas/ChangeLog-9899 index ae38e5dd9223cf4e26355263197ea9f2cd0296c0..76861df24938b7ec7a3051da5cf20c44465b145e 100644 ---- gas/ChangeLog-9899 -+++ gas/ChangeLog-9899 +--- a/gas/ChangeLog-9899 ++++ b/gas/ChangeLog-9899 @@ -3574,12 +3574,16 @@ Wed Jun 3 14:10:36 1998 Ian Lance Taylor Wed Jun 3 09:16:00 1998 Catherine Moore @@ -17968,8 +18747,8 @@ index ae38e5dd9223cf4e26355263197ea9f2cd0296c0..76861df24938b7ec7a3051da5cf20c44 Tue Jun 2 15:36:13 1998 Ian Lance Taylor diff --git a/gas/Makefile.am b/gas/Makefile.am index 256e2322fd80f84d8fa8fab735c85446dff4f506..851de3dc36be1138ad52026f7ace0ebd49da94b6 100644 ---- gas/Makefile.am -+++ gas/Makefile.am +--- a/gas/Makefile.am ++++ b/gas/Makefile.am @@ -245,23 +245,25 @@ TARGET_CPU_HFILES = \ config/tc-z8k.h \ config/xtensa-relax.h @@ -18027,8 +18806,8 @@ index 256e2322fd80f84d8fa8fab735c85446dff4f506..851de3dc36be1138ad52026f7ace0ebd BASEDIR = $(srcdir)/.. diff --git a/gas/Makefile.in b/gas/Makefile.in index 94812d96db9cb13bdbdd0243a6b9a021e95e0a0b..c04f7d53feacb96ac3a82109375c3c94bcb15d56 100644 ---- gas/Makefile.in -+++ gas/Makefile.in +--- a/gas/Makefile.in ++++ b/gas/Makefile.in @@ -513,23 +513,25 @@ TARGET_CPU_HFILES = \ config/tc-z8k.h \ config/xtensa-relax.h @@ -18127,8 +18906,8 @@ index 94812d96db9cb13bdbdd0243a6b9a021e95e0a0b..c04f7d53feacb96ac3a82109375c3c94 mkdir testsuite; \ diff --git a/gas/as.c b/gas/as.c index fa4141f92bc887cfd403ec3eb93a7a20f26b642a..7b35f0e3f23662e09e8ce56c525239cf68b5dd3a 100644 ---- gas/as.c -+++ gas/as.c +--- a/gas/as.c ++++ b/gas/as.c @@ -105,12 +105,17 @@ int keep_it = 0; segT reg_section; segT expr_section; @@ -18181,8 +18960,8 @@ index fa4141f92bc887cfd403ec3eb93a7a20f26b642a..7b35f0e3f23662e09e8ce56c525239cf expr_section = subseg_new ("*GAS `expr' section*", 0); diff --git a/gas/config/m68k-parse.h b/gas/config/m68k-parse.h index 4f91385f9222dc52c8cc9f490860729c2183e445..08e766c5523b90ac3cd2d685b239c0a7ed4d8230 100644 ---- gas/config/m68k-parse.h -+++ gas/config/m68k-parse.h +--- a/gas/config/m68k-parse.h ++++ b/gas/config/m68k-parse.h @@ -293,12 +293,15 @@ struct m68k_exp /* The type of pic relocation if any. */ enum pic_relocation pic_reloc; @@ -18201,8 +18980,8 @@ index 4f91385f9222dc52c8cc9f490860729c2183e445..08e766c5523b90ac3cd2d685b239c0a7 { diff --git a/gas/config/m68k-parse.y b/gas/config/m68k-parse.y index 2c58266fb8e6bd8d57515fe5200daaf9a1e450a2..742cbf2eeaaa15766a4d44de76a9d58d56993367 100644 ---- gas/config/m68k-parse.y -+++ gas/config/m68k-parse.y +--- a/gas/config/m68k-parse.y ++++ b/gas/config/m68k-parse.y @@ -972,31 +972,35 @@ yylex () else if (parens == 0 && (*s == ',' || *s == ']')) @@ -18246,7 +19025,7 @@ diff --git a/gas/config/obj-amigahunk.c b/gas/config/obj-amigahunk.c new file mode 100644 index 0000000000000000000000000000000000000000..8755475ecfdfd5aafbf876ed1f87c9d343b560e9 --- /dev/null -+++ gas/config/obj-amigahunk.c ++++ b/gas/config/obj-amigahunk.c @@ -0,0 +1,212 @@ +/* AmigaOS object file format + Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc. @@ -18464,7 +19243,7 @@ diff --git a/gas/config/obj-amigahunk.h b/gas/config/obj-amigahunk.h new file mode 100644 index 0000000000000000000000000000000000000000..0b7d80eeb291878dc871ce0591b2223bf6cb1de2 --- /dev/null -+++ gas/config/obj-amigahunk.h ++++ b/gas/config/obj-amigahunk.h @@ -0,0 +1,54 @@ +/* obj-amigahunk.h, AmigaOS object file format for gas, the assembler. + Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc. @@ -18522,8 +19301,8 @@ index 0000000000000000000000000000000000000000..0b7d80eeb291878dc871ce0591b2223b +#define AOUT_STABS diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c index d7c766513ccc4111f51904a7e01904b7ebe96a03..bb8d9d1ebee6b76deee86848202fd06d5b1a4dfa 100644 ---- gas/config/obj-elf.c -+++ gas/config/obj-elf.c +--- a/gas/config/obj-elf.c ++++ b/gas/config/obj-elf.c @@ -1390,13 +1390,13 @@ obj_elf_vtable_inherit (int ignore ATTRIBUTE_UNUSED) if (bad) return NULL; @@ -18556,8 +19335,8 @@ index d7c766513ccc4111f51904a7e01904b7ebe96a03..bb8d9d1ebee6b76deee86848202fd06d #ifdef NEED_ECOFF_DEBUG diff --git a/gas/config/tc-i386.h b/gas/config/tc-i386.h index de132d69d7ac3f854ea517a15267e8c75365714d..14b67f0506eacf6d3dbb11dbd08689fa69354678 100644 ---- gas/config/tc-i386.h -+++ gas/config/tc-i386.h +--- a/gas/config/tc-i386.h ++++ b/gas/config/tc-i386.h @@ -24,13 +24,20 @@ #define TC_I386 1 @@ -18628,8 +19407,8 @@ index de132d69d7ac3f854ea517a15267e8c75365714d..14b67f0506eacf6d3dbb11dbd08689fa PROCESSOR_I486, diff --git a/gas/config/tc-m68k.c b/gas/config/tc-m68k.c index 21accf605b22ebc5af491e173faeef93888b6667..8b5f6c60f2141ee91d6e9d1d639815abdf4e5042 100644 ---- gas/config/tc-m68k.c -+++ gas/config/tc-m68k.c +--- a/gas/config/tc-m68k.c ++++ b/gas/config/tc-m68k.c @@ -35,12 +35,22 @@ #endif @@ -19589,8 +20368,8 @@ index 21accf605b22ebc5af491e173faeef93888b6667..8b5f6c60f2141ee91d6e9d1d639815ab m68k_elf_final_processing (void) diff --git a/gas/config/tc-m68k.h b/gas/config/tc-m68k.h index bcf4607ebebe16d575166d666a536fb1fbdfeaee..144b7c7d783bab80bd84fa0e57cfce9f349a528f 100644 ---- gas/config/tc-m68k.h -+++ gas/config/tc-m68k.h +--- a/gas/config/tc-m68k.h ++++ b/gas/config/tc-m68k.h @@ -30,20 +30,27 @@ struct fix; #ifdef TE_SUN3 #define TARGET_FORMAT "a.out-sunos-big" @@ -19655,8 +20434,8 @@ index bcf4607ebebe16d575166d666a536fb1fbdfeaee..144b7c7d783bab80bd84fa0e57cfce9f if (aim == 0 && this_type->rlx_forward == 127) \ diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c index 208d76d847128c833f73713eff2b78deb610a764..11949323d80802138ec23fb8174727c0a7c4fd45 100644 ---- gas/config/tc-ppc.c -+++ gas/config/tc-ppc.c +--- a/gas/config/tc-ppc.c ++++ b/gas/config/tc-ppc.c @@ -1421,22 +1421,28 @@ ppc_target_format (void) # else return (ppc_obj64 ? "aixcoff64-rs6000" : "aixcoff-rs6000"); @@ -19794,8 +20573,8 @@ index 208d76d847128c833f73713eff2b78deb610a764..11949323d80802138ec23fb8174727c0 size = 2; diff --git a/gas/config/tc-sh.c b/gas/config/tc-sh.c index 4db1a0913602aaf18d1390cc315f6db0fbdef649..ba0ed8e89e44a9ab8411662047e6f85b4f28d5d9 100644 ---- gas/config/tc-sh.c -+++ gas/config/tc-sh.c +--- a/gas/config/tc-sh.c ++++ b/gas/config/tc-sh.c @@ -800,13 +800,13 @@ sh_cons_fix_new (fragS *frag, int off, int size, expressionS *exp) { error: @@ -19993,7 +20772,7 @@ diff --git a/gas/config/te-amiga.h b/gas/config/te-amiga.h new file mode 100644 index 0000000000000000000000000000000000000000..a7b93727031092cdeb4bf66e3813663d66d79c3b --- /dev/null -+++ gas/config/te-amiga.h ++++ b/gas/config/te-amiga.h @@ -0,0 +1,24 @@ +/* + * te-amiga.h -- Amiga target environment declarations. @@ -20023,7 +20802,7 @@ diff --git a/gas/config/te-amigaos.h b/gas/config/te-amigaos.h new file mode 100644 index 0000000000000000000000000000000000000000..8bd15a3d19b3f383e6756d6e307bd10dc4dcfb6f --- /dev/null -+++ gas/config/te-amigaos.h ++++ b/gas/config/te-amigaos.h @@ -0,0 +1,14 @@ +/* + * te-amigaos.h -- Amiga target environment declarations. @@ -20044,8 +20823,8 @@ similarity index 65% copy from gas/config/te-nbsd.h copy to gas/config/te-amithlon.h index ce291014824771b2081438766002c479eeb60d9b..2fbd88551330d46e5cd585d142d67e6b7efe1624 100644 ---- gas/config/te-nbsd.h -+++ gas/config/te-amithlon.h +--- a/gas/config/te-nbsd.h ++++ b/gas/config/te-amithlon.h @@ -1,24 +1,26 @@ -/* te-nbsd.h -- NetBSD target environment declarations. - Copyright 1987, 1990, 1991, 1992, 1994, 1998, 2000, 2005, 2007 @@ -20084,7 +20863,7 @@ diff --git a/gas/config/te-morphos.h b/gas/config/te-morphos.h new file mode 100644 index 0000000000000000000000000000000000000000..43b0826fa79d9e9c97485cc6dd7d919771defbf9 --- /dev/null -+++ gas/config/te-morphos.h ++++ b/gas/config/te-morphos.h @@ -0,0 +1,14 @@ +/* + * te-amiga.h -- Amiga target environment declarations. @@ -20102,8 +20881,8 @@ index 0000000000000000000000000000000000000000..43b0826fa79d9e9c97485cc6dd7d9197 +#endif diff --git a/gas/configure b/gas/configure index 2e674491f392b756186c52f7b0d28de8a20398c5..6eabef030df837c80ab009e12ad99a3086df5e43 100755 ---- gas/configure -+++ gas/configure +--- a/gas/configure ++++ b/gas/configure @@ -12500,12 +12500,19 @@ _ACEOF cat >>confdefs.h <<_ACEOF @@ -20152,8 +20931,8 @@ index 2e674491f392b756186c52f7b0d28de8a20398c5..6eabef030df837c80ab009e12ad99a30 $as_echo_n "checking for $ac_word... " >&6; } diff --git a/gas/configure.in b/gas/configure.in index 14f6edfe5deb041e968454931c451e1da226e0d1..183d98e8a4ac56e2e8a7a87f7b824f302bbb04f4 100644 ---- gas/configure.in -+++ gas/configure.in +--- a/gas/configure.in ++++ b/gas/configure.in @@ -598,12 +598,19 @@ if test `set . $emfiles ; shift ; echo $#` -gt 0 ; then fi AC_SUBST(extra_objects) @@ -20200,8 +20979,8 @@ index 14f6edfe5deb041e968454931c451e1da226e0d1..183d98e8a4ac56e2e8a7a87f7b824f30 AM_PO_SUBDIRS diff --git a/gas/configure.tgt b/gas/configure.tgt index 9e44de000145c39abfd3ea325656a4d4bc066198..61f24acdb98484f43ac0c08d3cacfd38b1c1fb8b 100644 ---- gas/configure.tgt -+++ gas/configure.tgt +--- a/gas/configure.tgt ++++ b/gas/configure.tgt @@ -40,13 +40,14 @@ case ${cpu} in cr16*) cpu_type=cr16 endian=little ;; crisv32) cpu_type=cris arch=crisv32 ;; @@ -20264,8 +21043,8 @@ index 9e44de000145c39abfd3ea325656a4d4bc066198..61f24acdb98484f43ac0c08d3cacfd38 ppc-*-beos*) fmt=coff ;; diff --git a/gas/read.c b/gas/read.c index 21c42b27342fb8e2c687417bcdacc4c16e3905b7..9de62b9c512025212d52a19833ffe28004944dd1 100644 ---- gas/read.c -+++ gas/read.c +--- a/gas/read.c ++++ b/gas/read.c @@ -43,12 +43,16 @@ #include "wchar.h" @@ -20354,8 +21133,8 @@ index 21c42b27342fb8e2c687417bcdacc4c16e3905b7..9de62b9c512025212d52a19833ffe280 diff --git a/gas/read.h b/gas/read.h index 4e5d1bbd2dc7b0724a2fc047db01f97aec8a4bac..59e787e754a14e11195607d382f81992423584cb 100644 ---- gas/read.h -+++ gas/read.h +--- a/gas/read.h ++++ b/gas/read.h @@ -130,12 +130,16 @@ extern void do_repeat (int,const char *,const char *); extern void do_repeat_with_expander (int, const char *, const char *, const char *); extern void end_repeat (int); @@ -20375,8 +21154,8 @@ index 4e5d1bbd2dc7b0724a2fc047db01f97aec8a4bac..59e787e754a14e11195607d382f81992 extern symbolS *s_comm_internal (int, symbolS *(*) (int, symbolS *, addressT)); diff --git a/gas/write.c b/gas/write.c index 56ebb6c565bea35df43565b53206156270a41b66..8a9746c927a3e8b7007cdec9c7f16e47509b5f45 100644 ---- gas/write.c -+++ gas/write.c +--- a/gas/write.c ++++ b/gas/write.c @@ -149,13 +149,14 @@ fix_new_internal (fragS *frag, /* Which frag? */ int size, /* 1, 2, or 4 usually. */ symbolS *add_symbol, /* X_add_symbol. */ @@ -20530,8 +21309,8 @@ index 56ebb6c565bea35df43565b53206156270a41b66..8a9746c927a3e8b7007cdec9c7f16e47 diff --git a/gas/write.h b/gas/write.h index 8303f1be98b6548e4e30a326f042f78e07aed7f5..5f3598655b2665fa86d7b5291643f563536e2f31 100644 ---- gas/write.h -+++ gas/write.h +--- a/gas/write.h ++++ b/gas/write.h @@ -172,16 +172,16 @@ extern void write_object_file (void); extern long relax_frag (segT, fragS *, long); extern int relax_segment (struct frag *, segT, int); @@ -20553,8 +21332,8 @@ index 8303f1be98b6548e4e30a326f042f78e07aed7f5..5f3598655b2665fa86d7b5291643f563 #endif /* __write_h__ */ diff --git a/gprof/Makefile.am b/gprof/Makefile.am index edd100ac924458a1e69da65cab55ddb6a3b61555..286d29546ecdfa6cfafbfc7f7fb83a0fdeadfb83 100644 ---- gprof/Makefile.am -+++ gprof/Makefile.am +--- a/gprof/Makefile.am ++++ b/gprof/Makefile.am @@ -36,13 +36,13 @@ noinst_HEADERS = \ corefile.h gmon.h gmon_io.h gmon_out.h gprof.h hertz.h hist.h \ search_list.h source.h sym_ids.h symtab.h utils.h @@ -20572,8 +21351,8 @@ index edd100ac924458a1e69da65cab55ddb6a3b61555..286d29546ecdfa6cfafbfc7f7fb83a0f # This empty rule is a hack against gmake patched by Apple. diff --git a/gprof/Makefile.in b/gprof/Makefile.in index a9d7073c799863dc3b39124f83dbcba73bf8bf85..4d487c22a56406d567643a6bd53310e501fa99aa 100644 ---- gprof/Makefile.in -+++ gprof/Makefile.in +--- a/gprof/Makefile.in ++++ b/gprof/Makefile.in @@ -1013,13 +1013,13 @@ uninstall-man: uninstall-man1 mostlyclean-libtool pdf pdf-am ps ps-am tags tags-recursive \ uninstall uninstall-am uninstall-binPROGRAMS uninstall-dvi-am \ @@ -20591,8 +21370,8 @@ index a9d7073c799863dc3b39124f83dbcba73bf8bf85..4d487c22a56406d567643a6bd53310e5 awk -f $(srcdir)/gen-c-prog.awk > ./$*.c \ diff --git a/gprof/configure b/gprof/configure index 6ffdbe30cef942eb7e28f26674b03c8ff5907711..665d5009457e7e17d7acc0c8bfb81301cd546b32 100755 ---- gprof/configure -+++ gprof/configure +--- a/gprof/configure ++++ b/gprof/configure @@ -11850,12 +11850,25 @@ $as_echo "found xgettext program is not GNU xgettext; ignore it" >&6; } fi @@ -20621,8 +21400,8 @@ index 6ffdbe30cef942eb7e28f26674b03c8ff5907711..665d5009457e7e17d7acc0c8bfb81301 enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval diff --git a/gprof/configure.in b/gprof/configure.in index 631e3e467314f3740c737f1534537c7532a00d08..7b4586b0aeee56169f321af15214054feec0c349 100644 ---- gprof/configure.in -+++ gprof/configure.in +--- a/gprof/configure.in ++++ b/gprof/configure.in @@ -28,12 +28,23 @@ LT_INIT AC_CHECK_FUNCS(setmode) @@ -20649,8 +21428,8 @@ index 631e3e467314f3740c737f1534537c7532a00d08..7b4586b0aeee56169f321af15214054f diff --git a/gprof/gconfig.in b/gprof/gconfig.in index 25679910ee73fb2ae8f1c3f7b1cb2951166da71f..4ad8775fd559a1c06b6f572b4af24ca46f7f7f3e 100644 ---- gprof/gconfig.in -+++ gprof/gconfig.in +--- a/gprof/gconfig.in ++++ b/gprof/gconfig.in @@ -1,12 +1,8 @@ /* gconfig.in. Generated from configure.in by autoheader. */ @@ -20668,7 +21447,7 @@ diff --git a/include/elf/amigaos.h b/include/elf/amigaos.h new file mode 100644 index 0000000000000000000000000000000000000000..2cbcd490a300f0248aecf2ca6d50865181a3c1f0 --- /dev/null -+++ include/elf/amigaos.h ++++ b/include/elf/amigaos.h @@ -0,0 +1,27 @@ +/* AmigaOS ELF support for BFD. + Copyright 2001 Free Software Foundation, Inc. @@ -20699,15 +21478,21 @@ index 0000000000000000000000000000000000000000..2cbcd490a300f0248aecf2ca6d508651 +#endif /* _ELF_AMIGAOS_H */ diff --git a/include/elf/ppc.h b/include/elf/ppc.h index f80a1e8a3e9c5852902beaafbb6a2a9e36d815c3..9893a88d96a77d730d91ef2bfe89a18d75029dd1 100644 ---- include/elf/ppc.h -+++ include/elf/ppc.h -@@ -128,12 +128,18 @@ START_RELOC_NUMBERS (elf_ppc_reloc_type) +--- a/include/elf/ppc.h ++++ b/include/elf/ppc.h +@@ -128,12 +128,24 @@ START_RELOC_NUMBERS (elf_ppc_reloc_type) RELOC_NUMBER (R_PPC_EMB_RELST_LO, 112) RELOC_NUMBER (R_PPC_EMB_RELST_HI, 113) RELOC_NUMBER (R_PPC_EMB_RELST_HA, 114) RELOC_NUMBER (R_PPC_EMB_BIT_FLD, 115) RELOC_NUMBER (R_PPC_EMB_RELSDA, 116) ++/* Special MorphOS relocs. */ ++ RELOC_NUMBER (R_PPC_MORPHOS_DREL, 200) ++ RELOC_NUMBER (R_PPC_MORPHOS_DREL_LO, 201) ++ RELOC_NUMBER (R_PPC_MORPHOS_DREL_HI, 202) ++ RELOC_NUMBER (R_PPC_MORPHOS_DREL_HA, 203) ++ +/* AmigaOS4 relocs */ + RELOC_NUMBER (R_PPC_AMIGAOS_BREL, 210) + RELOC_NUMBER (R_PPC_AMIGAOS_BREL_LO, 211) @@ -20722,8 +21507,8 @@ index f80a1e8a3e9c5852902beaafbb6a2a9e36d815c3..9893a88d96a77d730d91ef2bfe89a18d RELOC_NUMBER (R_PPC_VLE_LO16D, 220) diff --git a/include/libiberty.h b/include/libiberty.h index cacde800ea3dda438ea8292ab4b9354a63ad048b..595ecf48242a2067dd71c4dda07a57994bdb4981 100644 ---- include/libiberty.h -+++ include/libiberty.h +--- a/include/libiberty.h ++++ b/include/libiberty.h @@ -103,13 +103,13 @@ extern int countargv (char**); /* HAVE_DECL_* is a three-state macro: undefined, 0 or 1. If it is undefined, we haven't run the autoconf check so provide the @@ -20741,8 +21526,8 @@ index cacde800ea3dda438ea8292ab4b9354a63ad048b..595ecf48242a2067dd71c4dda07a5799 #define basename basename_cannot_be_used_without_a_prototype diff --git a/ld/ChangeLog-9197 b/ld/ChangeLog-9197 index 9307f333e3b156758598c19ff0873c21fc1dad29..0f0e189765f0438cd3bbd7a04f36c8e006cef91c 100644 ---- ld/ChangeLog-9197 -+++ ld/ChangeLog-9197 +--- a/ld/ChangeLog-9197 ++++ b/ld/ChangeLog-9197 @@ -144,12 +144,17 @@ Wed Oct 22 11:29:25 1997 Ian Lance Taylor Fri Oct 17 00:00:13 1997 Richard Henderson @@ -20799,8 +21584,8 @@ index 9307f333e3b156758598c19ff0873c21fc1dad29..0f0e189765f0438cd3bbd7a04f36c8e0 diff --git a/ld/ChangeLog-9899 b/ld/ChangeLog-9899 index 866e4a0cfbb8a086ae01716e4a806e3386914cab..de288123cb7b80422bfc2973640bbdd16c6af900 100644 ---- ld/ChangeLog-9899 -+++ ld/ChangeLog-9899 +--- a/ld/ChangeLog-9899 ++++ b/ld/ChangeLog-9899 @@ -1881,12 +1881,17 @@ Wed Mar 18 09:42:24 1998 Nick Clifton * configure.tgt (targ_extra_emuls): Add thumb-pe target. @@ -20821,8 +21606,8 @@ index 866e4a0cfbb8a086ae01716e4a806e3386914cab..de288123cb7b80422bfc2973640bbdd1 Thu Feb 26 17:09:53 1998 Michael Meissner diff --git a/ld/Makefile.am b/ld/Makefile.am index e343ab06531054392ae09d67ecb2dc3022053c07..cbaa4c736f8e87f05a60d8580174e207069872fd 100644 ---- ld/Makefile.am -+++ ld/Makefile.am +--- a/ld/Makefile.am ++++ b/ld/Makefile.am @@ -128,12 +128,16 @@ LIBIBERTY = ../libiberty/libiberty.a ALL_EMULATION_SOURCES = \ @@ -20941,8 +21726,8 @@ index e343ab06531054392ae09d67ecb2dc3022053c07..cbaa4c736f8e87f05a60d8580174e207 ${GENSCRIPTS} ppcmacos "$(tdir_ppcmacos)" diff --git a/ld/Makefile.in b/ld/Makefile.in index 7da93b46501b8f8aa076134b903e1cdf34025941..43947832717c60ff3a89a8fcea838f5151afd56e 100644 ---- ld/Makefile.in -+++ ld/Makefile.in +--- a/ld/Makefile.in ++++ b/ld/Makefile.in @@ -435,12 +435,16 @@ BFDLIB = ../bfd/libbfd.la LIBIBERTY = ../libiberty/libiberty.a ALL_EMULATION_SOURCES = \ @@ -21108,8 +21893,8 @@ index 7da93b46501b8f8aa076134b903e1cdf34025941..43947832717c60ff3a89a8fcea838f51 ${GENSCRIPTS} ppcmacos "$(tdir_ppcmacos)" diff --git a/ld/configure.host b/ld/configure.host index f47b961176fa37c2786aa9ff322b21b06081cdfd..c7e1e700c24e48e783d07023b678dbd59bee0b11 100644 ---- ld/configure.host -+++ ld/configure.host +--- a/ld/configure.host ++++ b/ld/configure.host @@ -170,12 +170,16 @@ mips*-sgi-irix4* | mips*-sgi-irix5*) mips*-sgi-irix6*) @@ -21129,8 +21914,8 @@ index f47b961176fa37c2786aa9ff322b21b06081cdfd..c7e1e700c24e48e783d07023b678dbd5 ;; diff --git a/ld/configure.tgt b/ld/configure.tgt index 72bc5bca48d7c93f838de826a0685c13ef1db3c2..ddba96d6da87eb2f033eae77509639b6a630ec2a 100644 ---- ld/configure.tgt -+++ ld/configure.tgt +--- a/ld/configure.tgt ++++ b/ld/configure.tgt @@ -298,12 +298,13 @@ x86_64-*-pe | x86_64-*-pep) targ_emul=i386pep ; targ_extra_ofiles="deffilep.o pep-dll.o pe-dll.o" ;; x86_64-*-mingw*) targ_emul=i386pep ; @@ -21195,7 +21980,7 @@ diff --git a/ld/emulparams/amiga.sh b/ld/emulparams/amiga.sh new file mode 100644 index 0000000000000000000000000000000000000000..c2915d47d7964c6406eae9079ce90d695ecdbfda --- /dev/null -+++ ld/emulparams/amiga.sh ++++ b/ld/emulparams/amiga.sh @@ -0,0 +1,6 @@ +SCRIPT_NAME=amiga +OUTPUT_FORMAT="amiga" @@ -21207,7 +21992,7 @@ diff --git a/ld/emulparams/amiga_bss.sh b/ld/emulparams/amiga_bss.sh new file mode 100644 index 0000000000000000000000000000000000000000..5405d737448875ea39e5d9c4edfd59ee32c8a7b4 --- /dev/null -+++ ld/emulparams/amiga_bss.sh ++++ b/ld/emulparams/amiga_bss.sh @@ -0,0 +1,6 @@ +SCRIPT_NAME=amiga_bss +OUTPUT_FORMAT="amiga" @@ -21219,7 +22004,7 @@ diff --git a/ld/emulparams/amigaos.sh b/ld/emulparams/amigaos.sh new file mode 100644 index 0000000000000000000000000000000000000000..605b81e76bcbbd2322561d7d9502190dc7c00674 --- /dev/null -+++ ld/emulparams/amigaos.sh ++++ b/ld/emulparams/amigaos.sh @@ -0,0 +1,26 @@ +#. ${srcdir}/emulparams/elf32ppccommon.sh +TEMPLATE_NAME=amigaos @@ -21251,7 +22036,7 @@ diff --git a/ld/emulparams/amithlon.sh b/ld/emulparams/amithlon.sh new file mode 100644 index 0000000000000000000000000000000000000000..14b1c776396e2424af51c9b409e2d05f2881a84d --- /dev/null -+++ ld/emulparams/amithlon.sh ++++ b/ld/emulparams/amithlon.sh @@ -0,0 +1,11 @@ +SCRIPT_NAME=amithlon +OUTPUT_FORMAT="elf32-i386be-amithlon" @@ -21268,7 +22053,7 @@ diff --git a/ld/emulparams/morphos.sh b/ld/emulparams/morphos.sh new file mode 100644 index 0000000000000000000000000000000000000000..45908c662f9b6085877dd39621e813da45a9f5f7 --- /dev/null -+++ ld/emulparams/morphos.sh ++++ b/ld/emulparams/morphos.sh @@ -0,0 +1,6 @@ +TEMPLATE_NAME=morphos +SCRIPT_NAME=morphos @@ -21280,7 +22065,7 @@ diff --git a/ld/emulparams/morphos_baserel.sh b/ld/emulparams/morphos_baserel.sh new file mode 100644 index 0000000000000000000000000000000000000000..46c483484813395904772673d1ae1eed0bc9109f --- /dev/null -+++ ld/emulparams/morphos_baserel.sh ++++ b/ld/emulparams/morphos_baserel.sh @@ -0,0 +1,6 @@ +TEMPLATE_NAME=morphos +SCRIPT_NAME=morphos_baserel @@ -21292,7 +22077,7 @@ diff --git a/ld/emulparams/ppcamiga.sh b/ld/emulparams/ppcamiga.sh new file mode 100644 index 0000000000000000000000000000000000000000..3f266cf5265f13748eeb78f67dd93227ade92de5 --- /dev/null -+++ ld/emulparams/ppcamiga.sh ++++ b/ld/emulparams/ppcamiga.sh @@ -0,0 +1,8 @@ +SCRIPT_NAME=amiga +OUTPUT_FORMAT="amiga" @@ -21306,7 +22091,7 @@ diff --git a/ld/emulparams/ppcamiga_bss.sh b/ld/emulparams/ppcamiga_bss.sh new file mode 100644 index 0000000000000000000000000000000000000000..8d1720fb17c876d55b75f0885eb9f6eb0c7e9f1e --- /dev/null -+++ ld/emulparams/ppcamiga_bss.sh ++++ b/ld/emulparams/ppcamiga_bss.sh @@ -0,0 +1,8 @@ +SCRIPT_NAME=amiga_bss +OUTPUT_FORMAT="amiga" @@ -21320,7 +22105,7 @@ diff --git a/ld/emultempl/amiga.em b/ld/emultempl/amiga.em new file mode 100644 index 0000000000000000000000000000000000000000..c6abc5c644d3d93609d66972752e6cd3d474d70e --- /dev/null -+++ ld/emultempl/amiga.em ++++ b/ld/emultempl/amiga.em @@ -0,0 +1,288 @@ +# This shell script emits a C file. -*- C -*- +# It does some substitutions. @@ -21618,7 +22403,7 @@ diff --git a/ld/emultempl/amithlon.em b/ld/emultempl/amithlon.em new file mode 100644 index 0000000000000000000000000000000000000000..5e453a72f8c01e621d110d505b83d1abbcd19831 --- /dev/null -+++ ld/emultempl/amithlon.em ++++ b/ld/emultempl/amithlon.em @@ -0,0 +1,1698 @@ +# This shell script emits a C file. -*- C -*- +# It does some substitutions. @@ -23322,7 +24107,7 @@ diff --git a/ld/emultempl/morphos.em b/ld/emultempl/morphos.em new file mode 100644 index 0000000000000000000000000000000000000000..cd3b9a790fb286187d8fa3e11af9382f1603d16b --- /dev/null -+++ ld/emultempl/morphos.em ++++ b/ld/emultempl/morphos.em @@ -0,0 +1,1104 @@ +# This shell script emits a C file. -*- C -*- +# It does some substitutions. @@ -24430,8 +25215,8 @@ index 0000000000000000000000000000000000000000..cd3b9a790fb286187d8fa3e11af9382f +EOF diff --git a/ld/emultempl/ppc32elf.em b/ld/emultempl/ppc32elf.em index 6843770ca9431d7a4b698bfda7060082b215c41f..801d1d6424bc1f61bb0e7171de9f9b5178bc8100 100644 ---- ld/emultempl/ppc32elf.em -+++ ld/emultempl/ppc32elf.em +--- a/ld/emultempl/ppc32elf.em ++++ b/ld/emultempl/ppc32elf.em @@ -26,12 +26,15 @@ fragment < Date: Sat, 29 Nov 2014 11:32:22 +0100 -Subject: [PATCH 2/7] Fixed errors occuring with more recent versions of +Subject: [PATCH 2/8] Fixed errors occuring with more recent versions of texinfo. --- @@ -18,8 +18,8 @@ Subject: [PATCH 2/7] Fixed errors occuring with more recent versions of diff --git a/bfd/doc/bfd.texinfo b/bfd/doc/bfd.texinfo index 7b9774b71a3cb9b3c154c8c75a41de29a6813146..d3b14c56449321b5dfe33206b2c5cfcd87eb0b91 100644 ---- bfd/doc/bfd.texinfo -+++ bfd/doc/bfd.texinfo +--- a/bfd/doc/bfd.texinfo ++++ b/bfd/doc/bfd.texinfo @@ -324,21 +324,21 @@ All of BFD lives in one directory. @node BFD Index, , GNU Free Documentation License, Top @@ -46,8 +46,8 @@ index 7b9774b71a3cb9b3c154c8c75a41de29a6813146..d3b14c56449321b5dfe33206b2c5cfcd @bye diff --git a/binutils/doc/binutils.texi b/binutils/doc/binutils.texi index 45174b739e568d8f7f01fc373035e010ffeced3d..ce7746c103d9f6a5770b43a850a2e26b68b4b58d 100644 ---- binutils/doc/binutils.texi -+++ binutils/doc/binutils.texi +--- a/binutils/doc/binutils.texi ++++ b/binutils/doc/binutils.texi @@ -4410,45 +4410,45 @@ which fields in the ELF header should be updated. The long and short forms of options, shown here as alternatives, are equivalent. At least one of the @option{--output-mach}, @@ -102,8 +102,8 @@ index 45174b739e568d8f7f01fc373035e010ffeced3d..ce7746c103d9f6a5770b43a850a2e26b Display the version number of @command{elfedit}. diff --git a/gas/doc/c-arc.texi b/gas/doc/c-arc.texi index ea0fa4eb522c265700bdc3b6712894ec2ad61d7c..f27b3270abce6c40a7ff1b068313a14572c79b56 100644 ---- gas/doc/c-arc.texi -+++ gas/doc/c-arc.texi +--- a/gas/doc/c-arc.texi ++++ b/gas/doc/c-arc.texi @@ -217,13 +217,13 @@ can shortcut the pipeline. @item .extInstruction @var{name},@var{opcode},@var{subopcode},@var{suffixclass},@var{syntaxclass} The ARCtangent A4 allows the user to specify extension instructions. @@ -136,8 +136,8 @@ index ea0fa4eb522c265700bdc3b6712894ec2ad61d7c..f27b3270abce6c40a7ff1b068313a145 SYNTAX_3OP|OP1_MUST_BE_IMM diff --git a/gas/doc/c-arm.texi b/gas/doc/c-arm.texi index a46e08f4400ef64851828be4ab4df1046678699e..1944862d1caeb8f2aca57902f4ec1be55b68eb7e 100644 ---- gas/doc/c-arm.texi -+++ gas/doc/c-arm.texi +--- a/gas/doc/c-arm.texi ++++ b/gas/doc/c-arm.texi @@ -387,13 +387,13 @@ features. The default is to warn. Two slightly different syntaxes are support for ARM and THUMB instructions. The default, @code{divided}, uses the old style where @@ -210,8 +210,8 @@ index a46e08f4400ef64851828be4ab4df1046678699e..1944862d1caeb8f2aca57902f4ec1be5 @table @code diff --git a/gas/doc/c-cr16.texi b/gas/doc/c-cr16.texi index 19f859f71d8f8712e8250fda07ee5b148d2d13ac..592dc5a5459d0e48ba1ca2e2846dc5e380f18e63 100644 ---- gas/doc/c-cr16.texi -+++ gas/doc/c-cr16.texi +--- a/gas/doc/c-cr16.texi ++++ b/gas/doc/c-cr16.texi @@ -41,32 +41,39 @@ Operand expression type qualifier is an optional field in the instruction operan - @code{Specifies the CompactRISC Assembler generates a relocation entry for the operand, where pc has implied bit, the expression is adjusted accordingly. The linker uses the relocation entry to update the operand address at link time.} @end table @@ -274,8 +274,8 @@ index 19f859f71d8f8712e8250fda07ee5b148d2d13ac..592dc5a5459d0e48ba1ca2e2846dc5e3 diff --git a/gas/doc/c-mips.texi b/gas/doc/c-mips.texi index 9ed0420549220079a9c44d2eed0b9daca7805af5..6054ab90442b3de4622743ef73720b5c891334e4 100644 ---- gas/doc/c-mips.texi -+++ gas/doc/c-mips.texi +--- a/gas/doc/c-mips.texi ++++ b/gas/doc/c-mips.texi @@ -231,13 +231,13 @@ option. @itemx -no-m4650 Generate code for the MIPS @sc{r4650} chip. This tells the assembler to accept @@ -293,8 +293,8 @@ index 9ed0420549220079a9c44d2eed0b9daca7805af5..6054ab90442b3de4622743ef73720b5c specific to that chip, and to schedule for that chip's hazards. diff --git a/gas/doc/c-score.texi b/gas/doc/c-score.texi index 3af20a381dccc9738b4e6f5152a0f83edba9892e..40959f5b9cb2aef21b5e55289b6b9c981d57ce79 100644 ---- gas/doc/c-score.texi -+++ gas/doc/c-score.texi +--- a/gas/doc/c-score.texi ++++ b/gas/doc/c-score.texi @@ -34,31 +34,31 @@ The following table lists all available SCORE options. This option sets the largest size of an object that can be referenced implicitly with the @code{gp} register. The default value is 8. @@ -333,8 +333,8 @@ index 3af20a381dccc9738b4e6f5152a0f83edba9892e..40959f5b9cb2aef21b5e55289b6b9c98 @item -march=score3 diff --git a/gas/doc/c-tic54x.texi b/gas/doc/c-tic54x.texi index d61ec3af1a7de0b52e9a8230e65d8b55992c8540..2c3b0f2c111461debe9d4ea20d0219a04764c734 100644 ---- gas/doc/c-tic54x.texi -+++ gas/doc/c-tic54x.texi +--- a/gas/doc/c-tic54x.texi ++++ b/gas/doc/c-tic54x.texi @@ -106,13 +106,13 @@ Expansion is recursive until a previously encountered symbol is seen, at which point substitution stops. @@ -405,8 +405,8 @@ index d61ec3af1a7de0b52e9a8230e65d8b55992c8540..2c3b0f2c111461debe9d4ea20d0219a0 @item .bss @var{symbol}, @var{size} [, [@var{blocking_flag}] [,@var{alignment_flag}]] diff --git a/ld/ld.texinfo b/ld/ld.texinfo index 71e909e4b61606d4ca8d1f855d9cd10a3ae1947b..81d538bad91eee08ae24dc88f589b6d07719fff0 100644 ---- ld/ld.texinfo -+++ ld/ld.texinfo +--- a/ld/ld.texinfo ++++ b/ld/ld.texinfo @@ -7860,21 +7860,21 @@ If you have more than one @code{SECT} statement for the same @node LD Index @unnumbered LD Index @@ -432,5 +432,5 @@ index 71e909e4b61606d4ca8d1f855d9cd10a3ae1947b..81d538bad91eee08ae24dc88f589b6d0 @bye -- -2.1.4 +2.11.0 diff --git a/ppc-amigaos/recipes/patches/binutils/0003-Disabled-some-stuff-such-that-68k-vtarget-builds-aga.p b/ppc-amigaos/recipes/patches/binutils/0003-Disabled-some-stuff-such-that-68k-vtarget-builds-aga.p index f3b89fd..9ddeb6b 100644 --- a/ppc-amigaos/recipes/patches/binutils/0003-Disabled-some-stuff-such-that-68k-vtarget-builds-aga.p +++ b/ppc-amigaos/recipes/patches/binutils/0003-Disabled-some-stuff-such-that-68k-vtarget-builds-aga.p @@ -1,7 +1,7 @@ From be1c62376ea16552979036768972be85ca66c9ed Mon Sep 17 00:00:00 2001 From: Sebastian Bauer Date: Tue, 17 Mar 2015 19:30:24 +0100 -Subject: [PATCH 3/7] Disabled some stuff such that 68k vtarget builds again. +Subject: [PATCH 3/8] Disabled some stuff such that 68k vtarget builds again. This doesn't imply that it is working. --- @@ -10,8 +10,8 @@ This doesn't imply that it is working. diff --git a/gas/config/tc-m68k.c b/gas/config/tc-m68k.c index 8b5f6c60f2141ee91d6e9d1d639815abdf4e5042..9070a862b9c1266e84a8cea8da697f333227fa98 100644 ---- gas/config/tc-m68k.c -+++ gas/config/tc-m68k.c +--- a/gas/config/tc-m68k.c ++++ b/gas/config/tc-m68k.c @@ -5158,22 +5158,22 @@ md_convert_frag_1 (fragS *fragP) case TAB (BRANCHBWPL, LONG): /* Here we are converting an unconditional branch into a pair of @@ -106,5 +106,5 @@ index 8b5f6c60f2141ee91d6e9d1d639815abdf4e5042..9070a862b9c1266e84a8cea8da697f33 } while (*input_line_pointer++ == ','); -- -2.1.4 +2.11.0 diff --git a/ppc-amigaos/recipes/patches/binutils/0004-Print-symbol-name-when-an-unexpected-type-was-encoun.p b/ppc-amigaos/recipes/patches/binutils/0004-Print-symbol-name-when-an-unexpected-type-was-encoun.p index 7c4f7a6..913b50e 100644 --- a/ppc-amigaos/recipes/patches/binutils/0004-Print-symbol-name-when-an-unexpected-type-was-encoun.p +++ b/ppc-amigaos/recipes/patches/binutils/0004-Print-symbol-name-when-an-unexpected-type-was-encoun.p @@ -1,7 +1,7 @@ From 5e5e0a5505d8e5fc67697f3ab397fa5a39e085cc Mon Sep 17 00:00:00 2001 From: Sebastian Bauer Date: Sat, 12 Sep 2015 11:29:01 +0200 -Subject: [PATCH 4/7] Print symbol name when an unexpected type was +Subject: [PATCH 4/8] Print symbol name when an unexpected type was encountered. --- @@ -10,8 +10,8 @@ Subject: [PATCH 4/7] Print symbol name when an unexpected type was diff --git a/bfd/elflink.c b/bfd/elflink.c index bcd3add478ab13addffee21b54919afd5cdcd7d6..f10801b99e366ad956faf039401cfcbf0c42aaa1 100644 ---- bfd/elflink.c -+++ bfd/elflink.c +--- a/bfd/elflink.c ++++ b/bfd/elflink.c @@ -8801,12 +8801,13 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) switch (h->root.type) @@ -27,5 +27,5 @@ index bcd3add478ab13addffee21b54919afd5cdcd7d6..f10801b99e366ad956faf039401cfcbf case bfd_link_hash_undefweak: input_sec = bfd_und_section_ptr; -- -2.1.4 +2.11.0 diff --git a/ppc-amigaos/recipes/patches/binutils/0005-Bind-in-the-ld-unwind-options.p b/ppc-amigaos/recipes/patches/binutils/0005-Bind-in-the-ld-unwind-options.p index f82d880..0ecd59a 100644 --- a/ppc-amigaos/recipes/patches/binutils/0005-Bind-in-the-ld-unwind-options.p +++ b/ppc-amigaos/recipes/patches/binutils/0005-Bind-in-the-ld-unwind-options.p @@ -1,7 +1,7 @@ From ce074fe73deeb899bf1cd863092c174034f56e67 Mon Sep 17 00:00:00 2001 From: Sebastian Bauer Date: Thu, 22 Oct 2015 09:48:26 +0200 -Subject: [PATCH 5/7] Bind in the ld unwind options. +Subject: [PATCH 5/8] Bind in the ld unwind options. --- ld/emulparams/amigaos.sh | 4 +++- @@ -9,8 +9,8 @@ Subject: [PATCH 5/7] Bind in the ld unwind options. diff --git a/ld/emulparams/amigaos.sh b/ld/emulparams/amigaos.sh index 605b81e76bcbbd2322561d7d9502190dc7c00674..2661d4ddcd1c5ecab9adea84af7f7d0ba054aa95 100644 ---- ld/emulparams/amigaos.sh -+++ ld/emulparams/amigaos.sh +--- a/ld/emulparams/amigaos.sh ++++ b/ld/emulparams/amigaos.sh @@ -1,7 +1,9 @@ -#. ${srcdir}/emulparams/elf32ppccommon.sh +. ${srcdir}/emulparams/elf32ppccommon.sh @@ -23,5 +23,5 @@ index 605b81e76bcbbd2322561d7d9502190dc7c00674..2661d4ddcd1c5ecab9adea84af7f7d0b COMMONPAGESIZE="CONSTANT (COMMONPAGESIZE)" ALIGNMENT=16 -- -2.1.4 +2.11.0 diff --git a/ppc-amigaos/recipes/patches/binutils/0006-Introduced-strip-unneeded-rel-relocs.p b/ppc-amigaos/recipes/patches/binutils/0006-Introduced-strip-unneeded-rel-relocs.p index db15c54..9cb51d1 100644 --- a/ppc-amigaos/recipes/patches/binutils/0006-Introduced-strip-unneeded-rel-relocs.p +++ b/ppc-amigaos/recipes/patches/binutils/0006-Introduced-strip-unneeded-rel-relocs.p @@ -1,7 +1,7 @@ From 6b64c328f239a146c1ce5a85c27b0ff1636f3987 Mon Sep 17 00:00:00 2001 From: Sebastian Bauer Date: Tue, 1 Dec 2015 13:51:20 +0100 -Subject: [PATCH 6/7] Introduced strip-unneeded-rel-relocs. +Subject: [PATCH 6/8] Introduced strip-unneeded-rel-relocs. Normally, on AmigaOS we keep all relocs for executables as we don't have an isolated address space. However, not all relative relocs are necessary @@ -14,8 +14,8 @@ can be removed now. diff --git a/binutils/objcopy.c b/binutils/objcopy.c index 88bd071eefa8b5426eaadfd6431e9de5d4a4591b..4beee77179b85479d5b43507d9eb2a6e0caf384e 100644 ---- binutils/objcopy.c -+++ binutils/objcopy.c +--- a/binutils/objcopy.c ++++ b/binutils/objcopy.c @@ -101,12 +101,15 @@ enum strip_action STRIP_ALL /* Strip all symbols. */ }; @@ -124,5 +124,5 @@ index 88bd071eefa8b5426eaadfd6431e9de5d4a4591b..4beee77179b85479d5b43507d9eb2a6e add_specific_symbol (optarg, strip_specific_htab); break; -- -2.1.4 +2.11.0 diff --git a/ppc-amigaos/recipes/patches/binutils/0007-Keep-symbols-for-stripped-sections.-This-is-importan.p b/ppc-amigaos/recipes/patches/binutils/0007-Keep-symbols-for-stripped-sections.-This-is-importan.p index 7681051..30319d5 100644 --- a/ppc-amigaos/recipes/patches/binutils/0007-Keep-symbols-for-stripped-sections.-This-is-importan.p +++ b/ppc-amigaos/recipes/patches/binutils/0007-Keep-symbols-for-stripped-sections.-This-is-importan.p @@ -1,7 +1,7 @@ From 035f3afce47e01ee70c7972a71a9dccea2b61e6f Mon Sep 17 00:00:00 2001 From: Sebastian Bauer Date: Thu, 3 Dec 2015 23:48:21 +0100 -Subject: [PATCH 7/7] Keep symbols for stripped sections. This is important for +Subject: [PATCH 7/8] Keep symbols for stripped sections. This is important for _SDA_BASE_, --- @@ -10,8 +10,8 @@ Subject: [PATCH 7/7] Keep symbols for stripped sections. This is important for diff --git a/binutils/objcopy.c b/binutils/objcopy.c index 4beee77179b85479d5b43507d9eb2a6e0caf384e..8750db51279ec56080aba114cd61780d061b168f 100644 ---- binutils/objcopy.c -+++ binutils/objcopy.c +--- a/binutils/objcopy.c ++++ b/binutils/objcopy.c @@ -1239,13 +1239,23 @@ filter_symbols (bfd *abfd, bfd *obfd, asymbol **osyms, if (!keep && ((keep_file_symbols && (flags & BSF_FILE)) @@ -38,5 +38,5 @@ index 4beee77179b85479d5b43507d9eb2a6e0caf384e..8750db51279ec56080aba114cd61780d && (weaken || is_specified_symbol (name, weaken_specific_htab))) { -- -2.1.4 +2.11.0 diff --git a/ppc-amigaos/recipes/patches/binutils/0008-Fix-undefined-behaviour.p b/ppc-amigaos/recipes/patches/binutils/0008-Fix-undefined-behaviour.p new file mode 100644 index 0000000..ebfe1e8 --- /dev/null +++ b/ppc-amigaos/recipes/patches/binutils/0008-Fix-undefined-behaviour.p @@ -0,0 +1,113 @@ +From 9592197f4e9723b6a435318b9c39521beab07c7b Mon Sep 17 00:00:00 2001 +From: Sebastian Bauer +Date: Wed, 15 Feb 2017 22:12:54 +0100 +Subject: [PATCH 8/8] Fix undefined behaviour. + +This should ensure that the code compiles with more recent version of GCC. +Changes have been backported from more recent version of binutils. +--- + binutils/dwarf.c | 2 +- + gas/config/tc-ppc.c | 2 +- + gas/read.c | 2 +- + gas/write.c | 2 +- + include/opcode/ppc.h | 2 +- + 5 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/binutils/dwarf.c b/binutils/dwarf.c +index 6e93906af385ff3dd0f8785792a1e8cc3d04a774..9fc4a594cfe83693f44f686fc752987b3e2a5653 100644 +--- a/binutils/dwarf.c ++++ b/binutils/dwarf.c +@@ -214,13 +214,13 @@ read_leb128 (unsigned char *data, unsigned int *length_return, int sign) + while (byte & 0x80); + + if (length_return != NULL) + *length_return = num_read; + + if (sign && (shift < 8 * sizeof (result)) && (byte & 0x40)) +- result |= -1L << shift; ++ result |= -((dwarf_vma) 1 << shift); + + return result; + } + + /* Create a signed version to avoid painful typecasts. */ + static dwarf_signed_vma +diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c +index 11949323d80802138ec23fb8174727c0a7c4fd45..14346e30661d408d5dba4d456cc274f2f4dc3820 100644 +--- a/gas/config/tc-ppc.c ++++ b/gas/config/tc-ppc.c +@@ -1466,13 +1466,13 @@ insn_validate (const struct powerpc_opcode *op) + as_bad (_("operand index error for %s"), op->name); + return TRUE; + } + else + { + const struct powerpc_operand *operand = &powerpc_operands[*o]; +- if (operand->shift != PPC_OPSHIFT_INV) ++ if (operand->shift != (int) PPC_OPSHIFT_INV) + { + unsigned long mask; + + if (operand->shift >= 0) + mask = operand->bitm << operand->shift; + else +diff --git a/gas/read.c b/gas/read.c +index 9de62b9c512025212d52a19833ffe28004944dd1..dfd466be7934cfd379b2a0c99f08c7ea877fdbe0 100644 +--- a/gas/read.c ++++ b/gas/read.c +@@ -5172,13 +5172,13 @@ output_big_sleb128 (char *p, LITTLENUM_TYPE *bignum, int size) + + /* Mop up any left-over bits (of which there will be less than 7). */ + if ((byte & 0x80) != 0) + { + /* Sign-extend VAL. */ + if (val & (1 << (loaded - 1))) +- val |= ~0 << loaded; ++ val |= ~0U << loaded; + if (orig) + *p = val & 0x7f; + p++; + } + + return p - orig; +diff --git a/gas/write.c b/gas/write.c +index 8a9746c927a3e8b7007cdec9c7f16e47509b5f45..be6969865f7373cdeb396df44506ef537206fbd8 100644 +--- a/gas/write.c ++++ b/gas/write.c +@@ -2310,13 +2310,13 @@ static relax_addressT + relax_align (register relax_addressT address, /* Address now. */ + register int alignment /* Alignment (binary). */) + { + relax_addressT mask; + relax_addressT new_address; + +- mask = ~((~0) << alignment); ++ mask = ~((relax_addressT) ~0 << alignment); + new_address = (address + mask) & (~mask); + #ifdef LINKER_RELAXING_SHRINKS_ONLY + if (linkrelax) + /* We must provide lots of padding, so the linker can discard it + when needed. The linker will not add extra space, ever. */ + new_address += (1 << alignment); +diff --git a/include/opcode/ppc.h b/include/opcode/ppc.h +index e57b118b02e5a2faba62f5dbd524f03827f719c0..40a1262ecd17944de229f6b192f8c6e078f70728 100644 +--- a/include/opcode/ppc.h ++++ b/include/opcode/ppc.h +@@ -267,13 +267,13 @@ struct powerpc_operand + extern const struct powerpc_operand powerpc_operands[]; + extern const unsigned int num_powerpc_operands; + + /* Use with the shift field of a struct powerpc_operand to indicate + that BITM and SHIFT cannot be used to determine where the operand + goes in the insn. */ +-#define PPC_OPSHIFT_INV (-1 << 31) ++#define PPC_OPSHIFT_INV (-1U << 31) + + /* Values defined for the flags field of a struct powerpc_operand. */ + + /* This operand takes signed values. */ + #define PPC_OPERAND_SIGNED (0x1) + +-- +2.11.0 + diff --git a/ppc-amigaos/recipes/patches/binutils/missing-files.p b/ppc-amigaos/recipes/patches/binutils/missing-files.p deleted file mode 100644 index 7911090..0000000 --- a/ppc-amigaos/recipes/patches/binutils/missing-files.p +++ /dev/null @@ -1,12492 +0,0 @@ ---- /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 -*- -+# It does some substitutions. -+# This file is now misnamed, because it supports both 32 bit and 64 bit -+# ELF emulations. -+test -z "${ELFSIZE}" && ELFSIZE=32 -+if [ -z "$MACHINE" ]; then -+ OUTPUT_ARCH=${ARCH} -+else -+ OUTPUT_ARCH=${ARCH}:${MACHINE} -+fi -+fragment < -+ ELF support by Ian Lance Taylor -+ -+ This file is part of the GNU Binutils. -+ -+ 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. */ -+ -+#define TARGET_IS_${EMULATION_NAME} -+ -+#include "sysdep.h" -+#include "bfd.h" -+#include "libiberty.h" -+#include "filenames.h" -+#include "safe-ctype.h" -+#include "getopt.h" -+#include "md5.h" -+#include "sha1.h" -+#include -+ -+#include "bfdlink.h" -+ -+#include "ld.h" -+#include "ldmain.h" -+#include "ldmisc.h" -+#include "ldexp.h" -+#include "ldlang.h" -+#include "ldfile.h" -+#include "ldemul.h" -+#include -+#include "elf/common.h" -+#include "elf-bfd.h" -+#include "filenames.h" -+ -+/* Declare functions used by various EXTRA_EM_FILEs. */ -+static void gld${EMULATION_NAME}_before_parse (void); -+static void gld${EMULATION_NAME}_after_open (void); -+static void gld${EMULATION_NAME}_before_allocation (void); -+static void gld${EMULATION_NAME}_after_allocation (void); -+static lang_output_section_statement_type *gld${EMULATION_NAME}_place_orphan -+ (asection *, const char *, int); -+EOF -+ -+if [ "x${USE_LIBPATH}" = xyes ] ; then -+ case ${target} in -+ *-*-linux-* | *-*-k*bsd*-* | *-*-gnu*) -+ fragment < -+#endif -+EOF -+ ;; -+ esac -+fi -+ -+# Import any needed special functions and/or overrides. -+# -+source_em ${srcdir}/emultempl/elf-generic.em -+if test -n "$EXTRA_EM_FILE" ; then -+ source_em ${srcdir}/emultempl/${EXTRA_EM_FILE}.em -+fi -+ -+# Functions in this file can be overridden by setting the LDEMUL_* shell -+# variables. If the name of the overriding function is the same as is -+# defined in this file, then don't output this file's version. -+# If a different overriding name is given then output the standard function -+# as presumably it is called from the overriding function. -+# -+if test x"$LDEMUL_BEFORE_PARSE" != xgld"$EMULATION_NAME"_before_parse; then -+fragment <flags.add_DT_NEEDED_for_regular) -+ link_class = DYN_AS_NEEDED; -+ -+ /* Tell the ELF linker that we don't want the output file to have a -+ DT_NEEDED entry for any dynamic library in DT_NEEDED tags from -+ this file at all. */ -+ if (!entry->flags.add_DT_NEEDED_for_dynamic) -+ link_class |= DYN_NO_ADD_NEEDED; -+ -+ if (entry->flags.just_syms -+ && (bfd_get_file_flags (entry->the_bfd) & DYNAMIC) != 0) -+ einfo (_("%P%F: --just-symbols may not be used on DSO: %B\n"), -+ entry->the_bfd); -+ -+ if (link_class == 0 -+ || (bfd_get_file_flags (entry->the_bfd) & DYNAMIC) == 0) -+ return FALSE; -+ -+ bfd_elf_set_dyn_lib_class (entry->the_bfd, -+ (enum dynamic_lib_link_class) link_class); -+ -+ /* Continue on with normal load_symbols processing. */ -+ return FALSE; -+} -+EOF -+fi -+ -+fragment <the_bfd == NULL -+ || (bfd_get_file_flags (s->the_bfd) & DYNAMIC) == 0) -+ return; -+ -+ soname = bfd_elf_get_dt_soname (s->the_bfd); -+ if (soname == NULL) -+ soname = lbasename (bfd_get_filename (s->the_bfd)); -+ -+ for (l = global_vercheck_needed; l != NULL; l = l->next) -+ { -+ const char *suffix; -+ -+ if (filename_cmp (soname, l->name) == 0) -+ { -+ /* Probably can't happen, but it's an easy check. */ -+ continue; -+ } -+ -+ if (strchr (l->name, '/') != NULL) -+ continue; -+ -+ suffix = strstr (l->name, ".so."); -+ if (suffix == NULL) -+ continue; -+ -+ suffix += sizeof ".so." - 1; -+ -+ if (filename_ncmp (soname, l->name, suffix - l->name) == 0) -+ { -+ /* Here we know that S is a dynamic object FOO.SO.VER1, and -+ the object we are considering needs a dynamic object -+ FOO.SO.VER2, and VER1 and VER2 are different. This -+ appears to be a version mismatch, so we tell the caller -+ to try a different version of this library. */ -+ global_vercheck_failed = TRUE; -+ return; -+ } -+ } -+} -+ -+ -+/* See if an input file matches a DT_NEEDED entry by running stat on -+ the file. */ -+ -+static void -+gld${EMULATION_NAME}_stat_needed (lang_input_statement_type *s) -+{ -+ struct stat st; -+ const char *suffix; -+ const char *soname; -+ -+ if (global_found != NULL) -+ return; -+ if (s->the_bfd == NULL) -+ return; -+ -+ /* If this input file was an as-needed entry, and wasn't found to be -+ needed at the stage it was linked, then don't say we have loaded it. */ -+ if ((bfd_elf_get_dyn_lib_class (s->the_bfd) & DYN_AS_NEEDED) != 0) -+ return; -+ -+ if (bfd_stat (s->the_bfd, &st) != 0) -+ { -+ einfo ("%P:%B: bfd_stat failed: %E\n", s->the_bfd); -+ return; -+ } -+ -+ /* Some operating systems, e.g. Windows, do not provide a meaningful -+ st_ino; they always set it to zero. (Windows does provide a -+ meaningful st_dev.) Do not indicate a duplicate library in that -+ case. While there is no guarantee that a system that provides -+ meaningful inode numbers will never set st_ino to zero, this is -+ merely an optimization, so we do not need to worry about false -+ negatives. */ -+ if (st.st_dev == global_stat.st_dev -+ && st.st_ino == global_stat.st_ino -+ && st.st_ino != 0) -+ { -+ global_found = s; -+ return; -+ } -+ -+ /* We issue a warning if it looks like we are including two -+ different versions of the same shared library. For example, -+ there may be a problem if -lc picks up libc.so.6 but some other -+ shared library has a DT_NEEDED entry of libc.so.5. This is a -+ heuristic test, and it will only work if the name looks like -+ NAME.so.VERSION. FIXME: Depending on file names is error-prone. -+ If we really want to issue warnings about mixing version numbers -+ of shared libraries, we need to find a better way. */ -+ -+ if (strchr (global_needed->name, '/') != NULL) -+ return; -+ suffix = strstr (global_needed->name, ".so."); -+ if (suffix == NULL) -+ return; -+ suffix += sizeof ".so." - 1; -+ -+ soname = bfd_elf_get_dt_soname (s->the_bfd); -+ if (soname == NULL) -+ soname = lbasename (s->filename); -+ -+ if (filename_ncmp (soname, global_needed->name, suffix - global_needed->name) == 0) -+ einfo ("%P: warning: %s, needed by %B, may conflict with %s\n", -+ global_needed->name, global_needed->by, soname); -+} -+ -+struct dt_needed -+{ -+ bfd *by; -+ const char *name; -+}; -+ -+/* This function is called for each possible name for a dynamic object -+ named by a DT_NEEDED entry. The FORCE parameter indicates whether -+ to skip the check for a conflicting version. */ -+ -+static bfd_boolean -+gld${EMULATION_NAME}_try_needed (struct dt_needed *needed, -+ int force) -+{ -+ bfd *abfd; -+ const char *name = needed->name; -+ const char *soname; -+ int link_class; -+ -+ abfd = bfd_openr (name, bfd_get_target (link_info.output_bfd)); -+ if (abfd == NULL) -+ return FALSE; -+ -+ /* Linker needs to decompress sections. */ -+ abfd->flags |= BFD_DECOMPRESS; -+ -+ if (! bfd_check_format (abfd, bfd_object)) -+ { -+ bfd_close (abfd); -+ return FALSE; -+ } -+ if ((bfd_get_file_flags (abfd) & DYNAMIC) == 0) -+ { -+ bfd_close (abfd); -+ return FALSE; -+ } -+ -+ /* For DT_NEEDED, they have to match. */ -+ if (abfd->xvec != link_info.output_bfd->xvec) -+ { -+ bfd_close (abfd); -+ return FALSE; -+ } -+ -+ /* Check whether this object would include any conflicting library -+ versions. If FORCE is set, then we skip this check; we use this -+ the second time around, if we couldn't find any compatible -+ instance of the shared library. */ -+ -+ if (! force) -+ { -+ struct bfd_link_needed_list *needs; -+ -+ if (! bfd_elf_get_bfd_needed_list (abfd, &needs)) -+ einfo ("%F%P:%B: bfd_elf_get_bfd_needed_list failed: %E\n", abfd); -+ -+ if (needs != NULL) -+ { -+ global_vercheck_needed = needs; -+ global_vercheck_failed = FALSE; -+ lang_for_each_input_file (gld${EMULATION_NAME}_vercheck); -+ if (global_vercheck_failed) -+ { -+ bfd_close (abfd); -+ /* Return FALSE to force the caller to move on to try -+ another file on the search path. */ -+ return FALSE; -+ } -+ -+ /* But wait! It gets much worse. On Linux, if a shared -+ library does not use libc at all, we are supposed to skip -+ it the first time around in case we encounter a shared -+ library later on with the same name which does use the -+ version of libc that we want. This is much too horrible -+ to use on any system other than Linux. */ -+ -+EOF -+case ${target} in -+ *-*-linux-* | *-*-k*bsd*-* | *-*-gnu*) -+ fragment <next) -+ if (CONST_STRNEQ (l->name, "libc.so")) -+ break; -+ if (l == NULL) -+ { -+ bfd_close (abfd); -+ return FALSE; -+ } -+ } -+ -+EOF -+ ;; -+esac -+fragment <filename); -+ -+ if (verbose) -+ info_msg (_("found %s at %s\n"), soname, name); -+ -+ global_found = NULL; -+ lang_for_each_input_file (gld${EMULATION_NAME}_stat_needed); -+ if (global_found != NULL) -+ { -+ /* Return TRUE to indicate that we found the file, even though -+ we aren't going to do anything with it. */ -+ return TRUE; -+ } -+ -+ /* Specify the soname to use. */ -+ bfd_elf_set_dt_needed_name (abfd, soname); -+ -+ /* Tell the ELF linker that we don't want the output file to have a -+ DT_NEEDED entry for this file, unless it is used to resolve -+ references in a regular object. */ -+ link_class = DYN_DT_NEEDED; -+ -+ /* Tell the ELF linker that we don't want the output file to have a -+ DT_NEEDED entry for this file at all if the entry is from a file -+ with DYN_NO_ADD_NEEDED. */ -+ if (needed->by != NULL -+ && (bfd_elf_get_dyn_lib_class (needed->by) & DYN_NO_ADD_NEEDED) != 0) -+ link_class |= DYN_NO_NEEDED | DYN_NO_ADD_NEEDED; -+ -+ bfd_elf_set_dyn_lib_class (abfd, (enum dynamic_lib_link_class) link_class); -+ -+ /* Add this file into the symbol table. */ -+ if (! bfd_link_add_symbols (abfd, &link_info)) -+ einfo ("%F%B: could not read symbols: %E\n", abfd); -+ -+ return TRUE; -+} -+ -+ -+/* Search for a needed file in a path. */ -+ -+static bfd_boolean -+gld${EMULATION_NAME}_search_needed (const char *path, -+ struct dt_needed *n, int force) -+{ -+ const char *s; -+ const char *name = n->name; -+ size_t len; -+ struct dt_needed needed; -+ -+ if (name[0] == '/') -+ return gld${EMULATION_NAME}_try_needed (n, force); -+ -+ if (path == NULL || *path == '\0') -+ return FALSE; -+ -+ needed.by = n->by; -+ needed.name = n->name; -+ -+ len = strlen (name); -+ while (1) -+ { -+ char *filename, *sset; -+ -+ s = strchr (path, config.rpath_separator); -+ if (s == NULL) -+ s = path + strlen (path); -+ -+#if HAVE_DOS_BASED_FILE_SYSTEM -+ /* Assume a match on the second char is part of drive specifier. */ -+ else if (config.rpath_separator == ':' -+ && s == path + 1 -+ && ISALPHA (*path)) -+ { -+ s = strchr (s + 1, config.rpath_separator); -+ if (s == NULL) -+ s = path + strlen (path); -+ } -+#endif -+ filename = (char *) xmalloc (s - path + len + 2); -+ if (s == path) -+ sset = filename; -+ else -+ { -+ memcpy (filename, path, s - path); -+ filename[s - path] = '/'; -+ sset = filename + (s - path) + 1; -+ } -+ strcpy (sset, name); -+ -+ needed.name = filename; -+ if (gld${EMULATION_NAME}_try_needed (&needed, force)) -+ return TRUE; -+ -+ free (filename); -+ -+ if (*s == '\0') -+ break; -+ path = s + 1; -+ } -+ -+ return FALSE; -+} -+ -+EOF -+if [ "x${USE_LIBPATH}" = xyes ] ; then -+ fragment < -+#else -+#include "elf-hints-local.h" -+#endif -+ -+static bfd_boolean -+gld${EMULATION_NAME}_check_ld_elf_hints (const struct bfd_link_needed_list *l, -+ int force) -+{ -+ static bfd_boolean initialized; -+ static char *ld_elf_hints; -+ struct dt_needed needed; -+ -+ if (!initialized) -+ { -+ FILE *f; -+ char *tmppath; -+ -+ tmppath = concat (ld_sysroot, _PATH_ELF_HINTS, (const char *) NULL); -+ f = fopen (tmppath, FOPEN_RB); -+ free (tmppath); -+ if (f != NULL) -+ { -+ struct elfhints_hdr hdr; -+ -+ if (fread (&hdr, 1, sizeof (hdr), f) == sizeof (hdr) -+ && hdr.magic == ELFHINTS_MAGIC -+ && hdr.version == 1) -+ { -+ if (fseek (f, hdr.strtab + hdr.dirlist, SEEK_SET) != -1) -+ { -+ char *b; -+ -+ b = xmalloc (hdr.dirlistlen + 1); -+ if (fread (b, 1, hdr.dirlistlen + 1, f) == -+ hdr.dirlistlen + 1) -+ ld_elf_hints = gld${EMULATION_NAME}_add_sysroot (b); -+ -+ free (b); -+ } -+ } -+ fclose (f); -+ } -+ -+ initialized = TRUE; -+ } -+ -+ if (ld_elf_hints == NULL) -+ return FALSE; -+ -+ needed.by = l->by; -+ needed.name = l->name; -+ return gld${EMULATION_NAME}_search_needed (ld_elf_hints, &needed, force); -+} -+EOF -+ # FreeBSD -+ ;; -+ -+ *-*-linux-* | *-*-k*bsd*-* | *-*-gnu*) -+ fragment <path == NULL) -+ { -+ info->alloc = p - dir + 1 + 256; -+ info->path = xmalloc (info->alloc); -+ info->len = 0; -+ } -+ else -+ { -+ if (info->len + 1 + (p - dir) >= info->alloc) -+ { -+ info->alloc += p - dir + 256; -+ info->path = xrealloc (info->path, info->alloc); -+ } -+ info->path[info->len++] = config.rpath_separator; -+ } -+ memcpy (info->path + info->len, dir, p - dir); -+ info->len += p - dir; -+ info->path[info->len] = '\0'; -+ } -+ } -+ while (! feof (f)); -+ free (line); -+ fclose (f); -+ return TRUE; -+} -+ -+static bfd_boolean -+gld${EMULATION_NAME}_check_ld_so_conf (const struct bfd_link_needed_list *l, -+ int force) -+{ -+ static bfd_boolean initialized; -+ static char *ld_so_conf; -+ struct dt_needed needed; -+ -+ if (! initialized) -+ { -+ char *tmppath; -+ struct gld${EMULATION_NAME}_ld_so_conf info; -+ -+ info.path = NULL; -+ info.len = info.alloc = 0; -+ tmppath = concat (ld_sysroot, "${prefix}/etc/ld.so.conf", -+ (const char *) NULL); -+ if (!gld${EMULATION_NAME}_parse_ld_so_conf (&info, tmppath)) -+ { -+ free (tmppath); -+ tmppath = concat (ld_sysroot, "/etc/ld.so.conf", -+ (const char *) NULL); -+ gld${EMULATION_NAME}_parse_ld_so_conf (&info, tmppath); -+ } -+ free (tmppath); -+ -+ if (info.path) -+ { -+ char *d = gld${EMULATION_NAME}_add_sysroot (info.path); -+ free (info.path); -+ ld_so_conf = d; -+ } -+ initialized = TRUE; -+ } -+ -+ if (ld_so_conf == NULL) -+ return FALSE; -+ -+ -+ needed.by = l->by; -+ needed.name = l->name; -+ return gld${EMULATION_NAME}_search_needed (ld_so_conf, &needed, force); -+} -+ -+EOF -+ # Linux -+ ;; -+ esac -+fi -+fragment <the_bfd) -+ & DYN_AS_NEEDED) == 0) -+ return; -+ -+ if (s->filename == NULL || s->the_bfd == NULL) -+ return; -+ -+ /* Don't look for a second non-loaded as-needed lib. */ -+ if (global_found != NULL -+ && (bfd_elf_get_dyn_lib_class (s->the_bfd) & DYN_AS_NEEDED) != 0) -+ return; -+ -+ if (filename_cmp (s->filename, global_needed->name) == 0) -+ { -+ global_found = s; -+ return; -+ } -+ -+ if (s->flags.search_dirs) -+ { -+ const char *f = strrchr (s->filename, '/'); -+ if (f != NULL -+ && filename_cmp (f + 1, global_needed->name) == 0) -+ { -+ global_found = s; -+ return; -+ } -+ } -+ -+ soname = bfd_elf_get_dt_soname (s->the_bfd); -+ if (soname != NULL -+ && filename_cmp (soname, global_needed->name) == 0) -+ { -+ global_found = s; -+ return; -+ } -+} -+ -+EOF -+ -+if test x"$LDEMUL_AFTER_OPEN" != xgld"$EMULATION_NAME"_after_open; then -+fragment <emit_note_gnu_build_id; -+ bfd_size_type size; -+ -+ abfd = abfd; -+ -+ size = offsetof (Elf_External_Note, name[sizeof "GNU"]); -+ size = (size + 3) & -(bfd_size_type) 4; -+ -+ if (!strcmp (style, "md5") || !strcmp (style, "uuid")) -+ size += 128 / 8; -+ else if (!strcmp (style, "sha1")) -+ size += 160 / 8; -+ else if (!strncmp (style, "0x", 2)) -+ { -+ /* ID is in string form (hex). Convert to bits. */ -+ const char *id = style + 2; -+ do -+ { -+ if (ISXDIGIT (id[0]) && ISXDIGIT (id[1])) -+ { -+ ++size; -+ id += 2; -+ } -+ else if (*id == '-' || *id == ':') -+ ++id; -+ else -+ { -+ size = 0; -+ break; -+ } -+ } while (*id != '\0'); -+ } -+ else -+ size = 0; -+ -+ return size; -+} -+ -+static unsigned char -+read_hex (const char xdigit) -+{ -+ if (ISDIGIT (xdigit)) -+ return xdigit - '0'; -+ if (ISUPPER (xdigit)) -+ return xdigit - 'A' + 0xa; -+ if (ISLOWER (xdigit)) -+ return xdigit - 'a' + 0xa; -+ abort (); -+ return 0; -+} -+ -+struct build_id_info -+{ -+ const char *style; -+ asection *sec; -+}; -+ -+static bfd_boolean -+gld${EMULATION_NAME}_write_build_id_section (bfd *abfd) -+{ -+ const struct elf_backend_data *bed = get_elf_backend_data (abfd); -+ struct build_id_info *info = (struct build_id_info *) -+ elf_tdata (abfd)->after_write_object_contents_info; -+ asection *asec; -+ Elf_Internal_Shdr *i_shdr; -+ unsigned char *contents, *id_bits; -+ bfd_size_type size; -+ Elf_External_Note *e_note; -+ -+ asec = info->sec; -+ if (bfd_is_abs_section (asec->output_section)) -+ { -+ einfo (_("%P: warning: .note.gnu.build-id section discarded," -+ " --build-id ignored.\n")); -+ return TRUE; -+ } -+ i_shdr = &elf_section_data (asec->output_section)->this_hdr; -+ -+ if (i_shdr->contents == NULL) -+ { -+ if (asec->contents == NULL) -+ asec->contents = (unsigned char *) xmalloc (asec->size); -+ contents = asec->contents; -+ } -+ else -+ contents = i_shdr->contents + asec->output_offset; -+ -+ e_note = (Elf_External_Note *) contents; -+ size = offsetof (Elf_External_Note, name[sizeof "GNU"]); -+ size = (size + 3) & -(bfd_size_type) 4; -+ id_bits = contents + size; -+ size = asec->size - size; -+ -+ bfd_h_put_32 (abfd, sizeof "GNU", &e_note->namesz); -+ bfd_h_put_32 (abfd, size, &e_note->descsz); -+ bfd_h_put_32 (abfd, NT_GNU_BUILD_ID, &e_note->type); -+ memcpy (e_note->name, "GNU", sizeof "GNU"); -+ -+ if (!strcmp (info->style, "md5")) -+ { -+ struct md5_ctx ctx; -+ md5_init_ctx (&ctx); -+ if (bed->s->checksum_contents (abfd, -+ (void (*) (const void *, size_t, void *)) -+ &md5_process_bytes, -+ &ctx)) -+ md5_finish_ctx (&ctx, id_bits); -+ else -+ return FALSE; -+ } -+ else if (!strcmp (info->style, "sha1")) -+ { -+ struct sha1_ctx ctx; -+ sha1_init_ctx (&ctx); -+ if (bed->s->checksum_contents (abfd, -+ (void (*) (const void *, size_t, void *)) -+ &sha1_process_bytes, -+ &ctx)) -+ sha1_finish_ctx (&ctx, id_bits); -+ else -+ return FALSE; -+ } -+ else if (!strcmp (info->style, "uuid")) -+ { -+ int n; -+ int fd = open ("/dev/urandom", O_RDONLY); -+ if (fd < 0) -+ return FALSE; -+ n = read (fd, id_bits, size); -+ close (fd); -+ if (n < (int) size) -+ return FALSE; -+ } -+ else if (!strncmp (info->style, "0x", 2)) -+ { -+ /* ID is in string form (hex). Convert to bits. */ -+ const char *id = info->style + 2; -+ size_t n = 0; -+ do -+ { -+ if (ISXDIGIT (id[0]) && ISXDIGIT (id[1])) -+ { -+ id_bits[n] = read_hex (*id++) << 4; -+ id_bits[n++] |= read_hex (*id++); -+ } -+ else if (*id == '-' || *id == ':') -+ ++id; -+ else -+ abort (); /* Should have been validated earlier. */ -+ } while (*id != '\0'); -+ } -+ else -+ abort (); /* Should have been validated earlier. */ -+ -+ size = asec->size; -+ return (bfd_seek (abfd, -+ i_shdr->sh_offset + asec->output_offset, SEEK_SET) == 0 -+ && bfd_bwrite (contents, size, abfd) == size); -+} -+ -+ -+/* This is called after all the input files have been opened. */ -+ -+static void -+gld${EMULATION_NAME}_after_open (void) -+{ -+ struct bfd_link_needed_list *needed, *l; -+ struct elf_link_hash_table *htab; -+ -+ after_open_default (); -+ -+ htab = elf_hash_table (&link_info); -+ if (!is_elf_hash_table (htab)) -+ return; -+ -+ if (link_info.emit_note_gnu_build_id) -+ { -+ bfd *abfd; -+ asection *s; -+ bfd_size_type size; -+ -+ /* Find an ELF input. */ -+ for (abfd = link_info.input_bfds; -+ abfd != (bfd *) NULL; abfd = abfd->link_next) -+ if (bfd_get_flavour (abfd) == bfd_target_elf_flavour) -+ break; -+ -+ if (abfd == NULL) -+ { -+ /* PR 10555: If there are no input files do not -+ try to create a .note.gnu-build-id section. */ -+ free (link_info.emit_note_gnu_build_id); -+ link_info.emit_note_gnu_build_id = NULL; -+ } -+ else -+ { -+ size = gld${EMULATION_NAME}_id_note_section_size (abfd, &link_info); -+ if (size == 0) -+ { -+ einfo ("%P: warning: unrecognized --build-id style ignored.\n"); -+ free (link_info.emit_note_gnu_build_id); -+ link_info.emit_note_gnu_build_id = NULL; -+ } -+ else -+ { -+ s = bfd_make_section_with_flags (abfd, ".note.gnu.build-id", -+ SEC_ALLOC | SEC_LOAD -+ | SEC_IN_MEMORY | SEC_LINKER_CREATED -+ | SEC_READONLY | SEC_DATA); -+ if (s != NULL && bfd_set_section_alignment (abfd, s, 2)) -+ { -+ struct elf_obj_tdata *t = elf_tdata (link_info.output_bfd); -+ struct build_id_info *b = -+ (struct build_id_info *) xmalloc (sizeof *b); -+ -+ b->style = link_info.emit_note_gnu_build_id; -+ b->sec = s; -+ elf_section_type (s) = SHT_NOTE; -+ s->size = size; -+ t->after_write_object_contents -+ = &gld${EMULATION_NAME}_write_build_id_section; -+ t->after_write_object_contents_info = b; -+ } -+ else -+ { -+ einfo ("%P: warning: Cannot create .note.gnu.build-id section," -+ " --build-id ignored.\n"); -+ free (link_info.emit_note_gnu_build_id); -+ link_info.emit_note_gnu_build_id = NULL; -+ } -+ } -+ } -+ } -+ -+ if (link_info.relocatable) -+ return; -+ -+ if (link_info.eh_frame_hdr -+ && !link_info.traditional_format) -+ { -+ bfd *abfd, *elfbfd = NULL; -+ bfd_boolean warn_eh_frame = FALSE; -+ asection *s; -+ -+ for (abfd = link_info.input_bfds; abfd; abfd = abfd->link_next) -+ { -+ if (bfd_get_flavour (abfd) == bfd_target_elf_flavour) -+ elfbfd = abfd; -+ if (!warn_eh_frame) -+ { -+ s = bfd_get_section_by_name (abfd, ".eh_frame"); -+ while (s != NULL -+ && (s->size <= 8 -+ || bfd_is_abs_section (s->output_section))) -+ s = bfd_get_next_section_by_name (s); -+ warn_eh_frame = s != NULL; -+ } -+ if (elfbfd && warn_eh_frame) -+ break; -+ } -+ if (elfbfd) -+ { -+ const struct elf_backend_data *bed; -+ -+ bed = get_elf_backend_data (elfbfd); -+ s = bfd_make_section_with_flags (elfbfd, ".eh_frame_hdr", -+ bed->dynamic_sec_flags -+ | SEC_READONLY); -+ if (s != NULL -+ && bfd_set_section_alignment (elfbfd, s, 2)) -+ { -+ htab->eh_info.hdr_sec = s; -+ warn_eh_frame = FALSE; -+ } -+ } -+ if (warn_eh_frame) -+ einfo ("%P: warning: Cannot create .eh_frame_hdr section," -+ " --eh-frame-hdr ignored.\n"); -+ } -+ -+ /* Get the list of files which appear in DT_NEEDED entries in -+ dynamic objects included in the link (often there will be none). -+ For each such file, we want to track down the corresponding -+ library, and include the symbol table in the link. This is what -+ the runtime dynamic linker will do. Tracking the files down here -+ permits one dynamic object to include another without requiring -+ special action by the person doing the link. Note that the -+ needed list can actually grow while we are stepping through this -+ loop. */ -+ needed = bfd_elf_get_needed_list (link_info.output_bfd, &link_info); -+ for (l = needed; l != NULL; l = l->next) -+ { -+ struct bfd_link_needed_list *ll; -+ struct dt_needed n, nn; -+ int force; -+ -+ /* If the lib that needs this one was --as-needed and wasn't -+ found to be needed, then this lib isn't needed either. Skip -+ the lib when creating a shared object unless we are copying -+ DT_NEEDED entres. */ -+ if (l->by != NULL -+ && ((bfd_elf_get_dyn_lib_class (l->by) & DYN_AS_NEEDED) != 0 -+ || (!link_info.executable -+ && bfd_elf_get_dyn_lib_class (l->by) & DYN_NO_ADD_NEEDED) != 0)) -+ continue; -+ -+ /* If we've already seen this file, skip it. */ -+ for (ll = needed; ll != l; ll = ll->next) -+ if ((ll->by == NULL -+ || (bfd_elf_get_dyn_lib_class (ll->by) & DYN_AS_NEEDED) == 0) -+ && strcmp (ll->name, l->name) == 0) -+ break; -+ if (ll != l) -+ continue; -+ -+ /* See if this file was included in the link explicitly. */ -+ global_needed = l; -+ global_found = NULL; -+ lang_for_each_input_file (gld${EMULATION_NAME}_check_needed); -+ if (global_found != NULL -+ && (bfd_elf_get_dyn_lib_class (global_found->the_bfd) -+ & DYN_AS_NEEDED) == 0) -+ continue; -+ -+ n.by = l->by; -+ n.name = l->name; -+ nn.by = l->by; -+ if (verbose) -+ info_msg (_("%s needed by %B\n"), l->name, l->by); -+ -+ /* As-needed libs specified on the command line (or linker script) -+ take priority over libs found in search dirs. */ -+ if (global_found != NULL) -+ { -+ nn.name = global_found->filename; -+ if (gld${EMULATION_NAME}_try_needed (&nn, TRUE)) -+ continue; -+ } -+ -+ /* We need to find this file and include the symbol table. We -+ want to search for the file in the same way that the dynamic -+ linker will search. That means that we want to use -+ rpath_link, rpath, then the environment variable -+ LD_LIBRARY_PATH (native only), then the DT_RPATH/DT_RUNPATH -+ entries (native only), then the linker script LIB_SEARCH_DIRS. -+ We do not search using the -L arguments. -+ -+ We search twice. The first time, we skip objects which may -+ introduce version mismatches. The second time, we force -+ their use. See gld${EMULATION_NAME}_vercheck comment. */ -+ for (force = 0; force < 2; force++) -+ { -+ size_t len; -+ search_dirs_type *search; -+EOF -+if [ "x${NATIVE}" = xyes ] ; then -+fragment <next) -+ { -+ char *tmpname = gld${EMULATION_NAME}_add_sysroot (rp->name); -+ found = (rp->by == l->by -+ && gld${EMULATION_NAME}_search_needed (tmpname, -+ &n, -+ force)); -+ free (tmpname); -+ } -+ if (found) -+ break; -+ -+EOF -+fi -+if [ "x${USE_LIBPATH}" = xyes ] ; then -+ case ${target} in -+ *-*-freebsd* | *-*-dragonfly*) -+ fragment <name); -+ for (search = search_head; search != NULL; search = search->next) -+ { -+ char *filename; -+ -+ if (search->cmdline) -+ continue; -+ filename = (char *) xmalloc (strlen (search->name) + len + 2); -+ sprintf (filename, "%s/%s", search->name, l->name); -+ nn.name = filename; -+ if (gld${EMULATION_NAME}_try_needed (&nn, force)) -+ break; -+ free (filename); -+ } -+ if (search != NULL) -+ break; -+EOF -+fragment <name, l->by); -+ } -+} -+ -+EOF -+fi -+ -+fragment <type.node_class) -+ { -+ case etree_provide: -+ case etree_provided: -+ provide = TRUE; -+ /* Fall thru */ -+ case etree_assign: -+ /* We call record_link_assignment even if the symbol is defined. -+ This is because if it is defined by a dynamic object, we -+ actually want to use the value defined by the linker script, -+ not the value from the dynamic object (because we are setting -+ symbols like etext). If the symbol is defined by a regular -+ object, then, as it happens, calling record_link_assignment -+ will do no harm. */ -+ if (strcmp (exp->assign.dst, ".") != 0) -+ { -+ if (!bfd_elf_record_link_assignment (link_info.output_bfd, -+ &link_info, -+ exp->assign.dst, provide, -+ exp->assign.hidden)) -+ einfo ("%P%F: failed to record assignment to %s: %E\n", -+ exp->assign.dst); -+ } -+ gld${EMULATION_NAME}_find_exp_assignment (exp->assign.src); -+ break; -+ -+ case etree_binary: -+ gld${EMULATION_NAME}_find_exp_assignment (exp->binary.lhs); -+ gld${EMULATION_NAME}_find_exp_assignment (exp->binary.rhs); -+ break; -+ -+ case etree_trinary: -+ gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.cond); -+ gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.lhs); -+ gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.rhs); -+ break; -+ -+ case etree_unary: -+ gld${EMULATION_NAME}_find_exp_assignment (exp->unary.child); -+ break; -+ -+ default: -+ break; -+ } -+} -+ -+ -+/* This is called by the before_allocation routine via -+ lang_for_each_statement. It locates any assignment statements, and -+ tells the ELF backend about them, in case they are assignments to -+ symbols which are referred to by dynamic objects. */ -+ -+static void -+gld${EMULATION_NAME}_find_statement_assignment (lang_statement_union_type *s) -+{ -+ if (s->header.type == lang_assignment_statement_enum) -+ gld${EMULATION_NAME}_find_exp_assignment (s->assignment_statement.exp); -+} -+ -+EOF -+ -+if test x"$LDEMUL_BEFORE_ALLOCATION" != xgld"$EMULATION_NAME"_before_allocation; then -+ if test x"${ELF_INTERPRETER_NAME+set}" = xset; then -+ ELF_INTERPRETER_SET_DEFAULT=" -+ if (sinterp != NULL) -+ { -+ sinterp->contents = (unsigned char *) ${ELF_INTERPRETER_NAME}; -+ sinterp->size = strlen ((char *) sinterp->contents) + 1; -+ } -+ -+" -+ else -+ ELF_INTERPRETER_SET_DEFAULT= -+ fi -+fragment <type == bfd_link_elf_hash_table) -+ _bfd_elf_tls_setup (link_info.output_bfd, &link_info); -+ -+ /* If we are going to make any variable assignments, we need to let -+ the ELF backend know about them in case the variables are -+ referred to by dynamic objects. */ -+ lang_for_each_statement (gld${EMULATION_NAME}_find_statement_assignment); -+ -+ /* Let the ELF backend work out the sizes of any sections required -+ by dynamic linking. */ -+ rpath = command_line.rpath; -+ if (rpath == NULL) -+ rpath = (const char *) getenv ("LD_RUN_PATH"); -+ -+ for (abfd = link_info.input_bfds; abfd; abfd = abfd->link_next) -+ if (bfd_get_flavour (abfd) == bfd_target_elf_flavour) -+ { -+ const char *audit_libs = elf_dt_audit (abfd); -+ -+ /* If the input bfd contains an audit entry, we need to add it as -+ a dep audit entry. */ -+ if (audit_libs && *audit_libs != '\0') -+ { -+ char *cp = xstrdup (audit_libs); -+ do -+ { -+ int more = 0; -+ char *cp2 = strchr (cp, config.rpath_separator); -+ -+ if (cp2) -+ { -+ *cp2 = '\0'; -+ more = 1; -+ } -+ -+ if (cp != NULL && *cp != '\0') -+ gld${EMULATION_NAME}_append_to_separated_string (&depaudit, cp); -+ -+ cp = more ? ++cp2 : NULL; -+ } -+ while (cp != NULL); -+ } -+ } -+ -+ if (! (bfd_elf_size_dynamic_sections -+ (link_info.output_bfd, command_line.soname, rpath, -+ command_line.filter_shlib, audit, depaudit, -+ (const char * const *) command_line.auxiliary_filters, -+ &link_info, &sinterp))) -+ einfo ("%P%F: failed to set dynamic section sizes: %E\n"); -+ -+${ELF_INTERPRETER_SET_DEFAULT} -+ /* Let the user override the dynamic linker we are using. */ -+ if (command_line.interpreter != NULL -+ && sinterp != NULL) -+ { -+ sinterp->contents = (bfd_byte *) command_line.interpreter; -+ sinterp->size = strlen (command_line.interpreter) + 1; -+ } -+ -+ /* Look for any sections named .gnu.warning. As a GNU extensions, -+ we treat such sections as containing warning messages. We print -+ out the warning message, and then zero out the section size so -+ that it does not get copied into the output file. */ -+ -+ { -+ LANG_FOR_EACH_INPUT_STATEMENT (is) -+ { -+ asection *s; -+ bfd_size_type sz; -+ char *msg; -+ bfd_boolean ret; -+ -+ if (is->flags.just_syms) -+ continue; -+ -+ s = bfd_get_section_by_name (is->the_bfd, ".gnu.warning"); -+ if (s == NULL) -+ continue; -+ -+ sz = s->size; -+ msg = (char *) xmalloc ((size_t) (sz + 1)); -+ if (! bfd_get_section_contents (is->the_bfd, s, msg, -+ (file_ptr) 0, sz)) -+ einfo ("%F%B: Can't read contents of section .gnu.warning: %E\n", -+ is->the_bfd); -+ msg[sz] = '\0'; -+ ret = link_info.callbacks->warning (&link_info, msg, -+ (const char *) NULL, -+ is->the_bfd, (asection *) NULL, -+ (bfd_vma) 0); -+ ASSERT (ret); -+ free (msg); -+ -+ /* Clobber the section size, so that we don't waste space -+ copying the warning into the output file. If we've already -+ sized the output section, adjust its size. The adjustment -+ is on rawsize because targets that size sections early will -+ have called lang_reset_memory_regions after sizing. */ -+ if (s->output_section != NULL -+ && s->output_section->rawsize >= s->size) -+ s->output_section->rawsize -= s->size; -+ -+ s->size = 0; -+ -+ /* Also set SEC_EXCLUDE, so that local symbols defined in the -+ warning section don't get copied to the output. */ -+ s->flags |= SEC_EXCLUDE | SEC_KEEP; -+ } -+ } -+ -+ before_allocation_default (); -+ -+ if (!bfd_elf_size_dynsym_hash_dynstr (link_info.output_bfd, &link_info)) -+ einfo ("%P%F: failed to set dynamic section sizes: %E\n"); -+} -+ -+EOF -+fi -+ -+if test x"$LDEMUL_OPEN_DYNAMIC_ARCHIVE" != xgld"$EMULATION_NAME"_open_dynamic_archive; then -+fragment <flags.maybe_archive) -+ return FALSE; -+ -+ filename = entry->filename; -+ -+ /* This allocates a few bytes too many when EXTRA_SHLIB_EXTENSION -+ is defined, but it does not seem worth the headache to optimize -+ away those two bytes of space. */ -+ string = (char *) xmalloc (strlen (search->name) -+ + strlen (filename) -+ + strlen (arch) -+#ifdef EXTRA_SHLIB_EXTENSION -+ + strlen (EXTRA_SHLIB_EXTENSION) -+#endif -+ + sizeof "/lib.so"); -+ -+ sprintf (string, "%s/lib%s%s.so", search->name, filename, arch); -+ -+#ifdef EXTRA_SHLIB_EXTENSION -+ /* Try the .so extension first. If that fails build a new filename -+ using EXTRA_SHLIB_EXTENSION. */ -+ if (! ldfile_try_open_bfd (string, entry)) -+ { -+ sprintf (string, "%s/lib%s%s%s", search->name, -+ filename, arch, EXTRA_SHLIB_EXTENSION); -+#endif -+ -+ if (! ldfile_try_open_bfd (string, entry)) -+ { -+ free (string); -+ return FALSE; -+ } -+#ifdef EXTRA_SHLIB_EXTENSION -+ } -+#endif -+ -+ entry->filename = string; -+ -+ /* We have found a dynamic object to include in the link. The ELF -+ backend linker will create a DT_NEEDED entry in the .dynamic -+ section naming this file. If this file includes a DT_SONAME -+ entry, it will be used. Otherwise, the ELF linker will just use -+ the name of the file. For an archive found by searching, like -+ this one, the DT_NEEDED entry should consist of just the name of -+ the file, without the path information used to find it. Note -+ that we only need to do this if we have a dynamic object; an -+ archive will never be referenced by a DT_NEEDED entry. -+ -+ FIXME: This approach--using bfd_elf_set_dt_needed_name--is not -+ very pretty. I haven't been able to think of anything that is -+ pretty, though. */ -+ if (bfd_check_format (entry->the_bfd, bfd_object) -+ && (entry->the_bfd->flags & DYNAMIC) != 0) -+ { -+ ASSERT (entry->flags.maybe_archive && entry->flags.search_dirs); -+ -+ /* Rather than duplicating the logic above. Just use the -+ filename we recorded earlier. */ -+ -+ filename = lbasename (entry->filename); -+ bfd_elf_set_dt_needed_name (entry->the_bfd, filename); -+ } -+ -+ return TRUE; -+} -+ -+EOF -+fi -+ -+if test x"$LDEMUL_PLACE_ORPHAN" != xgld"$EMULATION_NAME"_place_orphan; then -+fragment <name[4] == 'a'; -+ -+ for (lookup = &lang_output_section_statement.head->output_section_statement; -+ lookup != NULL; -+ lookup = lookup->next) -+ { -+ if (lookup->constraint >= 0 -+ && CONST_STRNEQ (lookup->name, ".rel")) -+ { -+ int lookrela = lookup->name[4] == 'a'; -+ -+ /* .rel.dyn must come before all other reloc sections, to suit -+ GNU ld.so. */ -+ if (isdyn) -+ break; -+ -+ /* Don't place after .rel.plt as doing so results in wrong -+ dynamic tags. */ -+ if (strcmp (".plt", lookup->name + 4 + lookrela) == 0) -+ break; -+ -+ if (rela == lookrela || last_rel == NULL) -+ last_rel = lookup; -+ if ((rela == lookrela || last_rel_alloc == NULL) -+ && lookup->bfd_section != NULL -+ && (lookup->bfd_section->flags & SEC_ALLOC) != 0) -+ last_rel_alloc = lookup; -+ } -+ -+ last = lookup; -+ if (lookup->bfd_section != NULL -+ && (lookup->bfd_section->flags & SEC_ALLOC) != 0) -+ { -+ last_alloc = lookup; -+ if ((lookup->bfd_section->flags & SEC_READONLY) != 0) -+ last_ro_alloc = lookup; -+ } -+ } -+ -+ if (last_rel_alloc) -+ return last_rel_alloc; -+ -+ if (last_rel) -+ return last_rel; -+ -+ if (last_ro_alloc) -+ return last_ro_alloc; -+ -+ if (last_alloc) -+ return last_alloc; -+ -+ return last; -+} -+ -+/* Place an orphan section. We use this to put random SHF_ALLOC -+ sections in the right segment. */ -+ -+static lang_output_section_statement_type * -+gld${EMULATION_NAME}_place_orphan (asection *s, -+ const char *secname, -+ int constraint) -+{ -+ static struct orphan_save hold[] = -+ { -+ { ".text", -+ SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE, -+ 0, 0, 0, 0 }, -+ { ".rodata", -+ SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_DATA, -+ 0, 0, 0, 0 }, -+ { ".data", -+ SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_DATA, -+ 0, 0, 0, 0 }, -+ { ".bss", -+ SEC_ALLOC, -+ 0, 0, 0, 0 }, -+ { 0, -+ SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_DATA, -+ 0, 0, 0, 0 }, -+ { ".interp", -+ SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_DATA, -+ 0, 0, 0, 0 }, -+ { ".sdata", -+ SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_SMALL_DATA, -+ 0, 0, 0, 0 }, -+ { ".comment", -+ SEC_HAS_CONTENTS, -+ 0, 0, 0, 0 }, -+ }; -+ enum orphan_save_index -+ { -+ orphan_text = 0, -+ orphan_rodata, -+ orphan_data, -+ orphan_bss, -+ orphan_rel, -+ orphan_interp, -+ orphan_sdata, -+ orphan_nonalloc -+ }; -+ static int orphan_init_done = 0; -+ struct orphan_save *place; -+ lang_output_section_statement_type *after; -+ lang_output_section_statement_type *os; -+ lang_output_section_statement_type *match_by_name = NULL; -+ int isdyn = 0; -+ int iself = s->owner->xvec->flavour == bfd_target_elf_flavour; -+ unsigned int sh_type = iself ? elf_section_type (s) : SHT_NULL; -+ -+ if (! link_info.relocatable -+ && link_info.combreloc -+ && (s->flags & SEC_ALLOC)) -+ { -+ if (iself) -+ switch (sh_type) -+ { -+ case SHT_RELA: -+ secname = ".rela.dyn"; -+ isdyn = 1; -+ break; -+ case SHT_REL: -+ secname = ".rel.dyn"; -+ isdyn = 1; -+ break; -+ default: -+ break; -+ } -+ else if (CONST_STRNEQ (secname, ".rel")) -+ { -+ secname = secname[4] == 'a' ? ".rela.dyn" : ".rel.dyn"; -+ isdyn = 1; -+ } -+ } -+ -+ /* Look through the script to see where to place this section. */ -+ if (constraint == 0) -+ for (os = lang_output_section_find (secname); -+ os != NULL; -+ os = next_matching_output_section_statement (os, 0)) -+ { -+ /* If we don't match an existing output section, tell -+ lang_insert_orphan to create a new output section. */ -+ constraint = SPECIAL; -+ -+ if (os->bfd_section != NULL -+ && (os->bfd_section->flags == 0 -+ || (_bfd_elf_match_sections_by_type (link_info.output_bfd, -+ os->bfd_section, -+ s->owner, s) -+ && ((s->flags ^ os->bfd_section->flags) -+ & (SEC_LOAD | SEC_ALLOC)) == 0))) -+ { -+ /* We already have an output section statement with this -+ name, and its bfd section has compatible flags. -+ If the section already exists but does not have any flags -+ set, then it has been created by the linker, probably as a -+ result of a --section-start command line switch. */ -+ lang_add_section (&os->children, s, NULL, os); -+ return os; -+ } -+ -+ /* Save unused output sections in case we can match them -+ against orphans later. */ -+ if (os->bfd_section == NULL) -+ match_by_name = os; -+ } -+ -+ /* If we didn't match an active output section, see if we matched an -+ unused one and use that. */ -+ if (match_by_name) -+ { -+ lang_add_section (&match_by_name->children, s, NULL, match_by_name); -+ return match_by_name; -+ } -+ -+ if (!orphan_init_done) -+ { -+ struct orphan_save *ho; -+ -+ for (ho = hold; ho < hold + sizeof (hold) / sizeof (hold[0]); ++ho) -+ if (ho->name != NULL) -+ { -+ ho->os = lang_output_section_find (ho->name); -+ if (ho->os != NULL && ho->os->flags == 0) -+ ho->os->flags = ho->flags; -+ } -+ orphan_init_done = 1; -+ } -+ -+ /* If this is a final link, then always put .gnu.warning.SYMBOL -+ sections into the .text section to get them out of the way. */ -+ if (link_info.executable -+ && ! link_info.relocatable -+ && CONST_STRNEQ (s->name, ".gnu.warning.") -+ && hold[orphan_text].os != NULL) -+ { -+ os = hold[orphan_text].os; -+ lang_add_section (&os->children, s, NULL, os); -+ return os; -+ } -+ -+ /* Decide which segment the section should go in based on the -+ section name and section flags. We put loadable .note sections -+ right after the .interp section, so that the PT_NOTE segment is -+ stored right after the program headers where the OS can read it -+ in the first page. */ -+ -+ place = NULL; -+ if ((s->flags & (SEC_ALLOC | SEC_DEBUGGING)) == 0) -+ place = &hold[orphan_nonalloc]; -+ else if ((s->flags & SEC_ALLOC) == 0) -+ ; -+ else if ((s->flags & SEC_LOAD) != 0 -+ && ((iself && sh_type == SHT_NOTE) -+ || (!iself && CONST_STRNEQ (secname, ".note")))) -+ place = &hold[orphan_interp]; -+ else if ((s->flags & (SEC_LOAD | SEC_HAS_CONTENTS | SEC_THREAD_LOCAL)) == 0) -+ place = &hold[orphan_bss]; -+ else if ((s->flags & SEC_SMALL_DATA) != 0) -+ place = &hold[orphan_sdata]; -+ else if ((s->flags & SEC_READONLY) == 0) -+ place = &hold[orphan_data]; -+ else if (((iself && (sh_type == SHT_RELA || sh_type == SHT_REL)) -+ || (!iself && CONST_STRNEQ (secname, ".rel"))) -+ && (s->flags & SEC_LOAD) != 0) -+ place = &hold[orphan_rel]; -+ else if ((s->flags & SEC_CODE) == 0) -+ place = &hold[orphan_rodata]; -+ else -+ place = &hold[orphan_text]; -+ -+ after = NULL; -+ if (place != NULL) -+ { -+ if (place->os == NULL) -+ { -+ if (place->name != NULL) -+ place->os = lang_output_section_find (place->name); -+ else -+ place->os = output_rel_find (s, isdyn); -+ } -+ after = place->os; -+ if (after == NULL) -+ after = lang_output_section_find_by_flags -+ (s, &place->os, _bfd_elf_match_sections_by_type); -+ if (after == NULL) -+ /* *ABS* is always the first output section statement. */ -+ after = &lang_output_section_statement.head->output_section_statement; -+ } -+ -+ return lang_insert_orphan (s, secname, constraint, after, place, NULL, NULL); -+} -+EOF -+fi -+ -+if test x"$LDEMUL_AFTER_ALLOCATION" != xgld"$EMULATION_NAME"_after_allocation; then -+fragment <> e${EMULATION_NAME}.c -+echo ' ; else if (link_info.relocatable) return' >> e${EMULATION_NAME}.c -+sed $sc ldscripts/${EMULATION_NAME}.xr >> e${EMULATION_NAME}.c -+echo ' ; else if (!config.text_read_only) return' >> e${EMULATION_NAME}.c -+sed $sc ldscripts/${EMULATION_NAME}.xbn >> e${EMULATION_NAME}.c -+if cmp -s ldscripts/${EMULATION_NAME}.x ldscripts/${EMULATION_NAME}.xn; then : ; else -+echo ' ; else if (!config.magic_demand_paged) return' >> e${EMULATION_NAME}.c -+sed $sc ldscripts/${EMULATION_NAME}.xn >> e${EMULATION_NAME}.c -+fi -+if test -n "$GENERATE_PIE_SCRIPT" ; then -+if test -n "$GENERATE_COMBRELOC_SCRIPT" ; then -+echo ' ; else if (link_info.pie && link_info.combreloc' >> e${EMULATION_NAME}.c -+echo ' && link_info.relro' >> e${EMULATION_NAME}.c -+echo ' && (link_info.flags & DF_BIND_NOW)) return' >> e${EMULATION_NAME}.c -+sed $sc ldscripts/${EMULATION_NAME}.xdw >> e${EMULATION_NAME}.c -+echo ' ; else if (link_info.pie && link_info.combreloc) return' >> e${EMULATION_NAME}.c -+sed $sc ldscripts/${EMULATION_NAME}.xdc >> e${EMULATION_NAME}.c -+fi -+echo ' ; else if (link_info.pie) return' >> e${EMULATION_NAME}.c -+sed $sc ldscripts/${EMULATION_NAME}.xd >> e${EMULATION_NAME}.c -+fi -+if test -n "$GENERATE_SHLIB_SCRIPT" ; then -+if test -n "$GENERATE_COMBRELOC_SCRIPT" ; then -+echo ' ; else if (link_info.shared && link_info.combreloc' >> e${EMULATION_NAME}.c -+echo ' && link_info.relro' >> e${EMULATION_NAME}.c -+echo ' && (link_info.flags & DF_BIND_NOW)) return' >> e${EMULATION_NAME}.c -+sed $sc ldscripts/${EMULATION_NAME}.xsw >> e${EMULATION_NAME}.c -+echo ' ; else if (link_info.shared && link_info.combreloc) return' >> e${EMULATION_NAME}.c -+sed $sc ldscripts/${EMULATION_NAME}.xsc >> e${EMULATION_NAME}.c -+fi -+echo ' ; else if (link_info.shared) return' >> e${EMULATION_NAME}.c -+sed $sc ldscripts/${EMULATION_NAME}.xs >> e${EMULATION_NAME}.c -+fi -+if test -n "$GENERATE_COMBRELOC_SCRIPT" ; then -+echo ' ; else if (link_info.combreloc && link_info.relro' >> e${EMULATION_NAME}.c -+echo ' && (link_info.flags & DF_BIND_NOW)) return' >> e${EMULATION_NAME}.c -+sed $sc ldscripts/${EMULATION_NAME}.xw >> e${EMULATION_NAME}.c -+echo ' ; else if (link_info.combreloc) return' >> e${EMULATION_NAME}.c -+sed $sc ldscripts/${EMULATION_NAME}.xc >> e${EMULATION_NAME}.c -+fi -+echo ' ; else return' >> e${EMULATION_NAME}.c -+sed $sc ldscripts/${EMULATION_NAME}.x >> e${EMULATION_NAME}.c -+echo '; }' >> e${EMULATION_NAME}.c -+ -+else -+# Scripts read from the filesystem. -+ -+fragment <