X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=bfd%2Felf32-ppc.c;h=1f77e18133addee44bc5df8022a552501183f024;hb=77b38f6db98e046232ecaac11b61c453965fb75a;hp=588b79781d80acc85be4f9105781ecdf3625bbb5;hpb=5dbc8b372f3a15fa4dce65d460a3cce7ed081f6c;p=binutils-gdb.git diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c index 588b79781d8..1f77e18133a 100644 --- a/bfd/elf32-ppc.c +++ b/bfd/elf32-ppc.c @@ -1,5 +1,5 @@ /* PowerPC-specific support for 32-bit ELF - Copyright (C) 1994-2020 Free Software Foundation, Inc. + Copyright (C) 1994-2022 Free Software Foundation, Inc. Written by Ian Lance Taylor, Cygnus Support. This file is part of BFD, the Binary File Descriptor library. @@ -19,11 +19,10 @@ 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. */ +/* The assembler should generate a full set of section symbols even + when they appear unused. The linux kernel build tool recordmcount + needs them. */ +#define TARGET_KEEP_UNUSED_SECTION_SYMBOLS true #include "sysdep.h" #include @@ -201,101 +200,101 @@ static const bfd_vma ppc_elf_vxworks_pic_plt0_entry complain, special_func) \ HOWTO (type, rightshift, size, bitsize, pc_relative, 0, \ complain_overflow_ ## complain, special_func, \ - #type, FALSE, 0, mask, pc_relative) + #type, false, 0, mask, pc_relative) static reloc_howto_type *ppc_elf_howto_table[R_PPC_max]; static reloc_howto_type ppc_elf_howto_raw[] = { /* This reloc does nothing. */ - HOW (R_PPC_NONE, 3, 0, 0, 0, FALSE, dont, + HOW (R_PPC_NONE, 0, 0, 0, 0, false, dont, bfd_elf_generic_reloc), /* A standard 32 bit relocation. */ - HOW (R_PPC_ADDR32, 2, 32, 0xffffffff, 0, FALSE, dont, + HOW (R_PPC_ADDR32, 4, 32, 0xffffffff, 0, false, dont, bfd_elf_generic_reloc), /* An absolute 26 bit branch; the lower two bits must be zero. FIXME: we don't check that, we just clear them. */ - HOW (R_PPC_ADDR24, 2, 26, 0x3fffffc, 0, FALSE, signed, + HOW (R_PPC_ADDR24, 4, 26, 0x3fffffc, 0, false, signed, bfd_elf_generic_reloc), /* A standard 16 bit relocation. */ - HOW (R_PPC_ADDR16, 1, 16, 0xffff, 0, FALSE, bitfield, + HOW (R_PPC_ADDR16, 2, 16, 0xffff, 0, false, bitfield, bfd_elf_generic_reloc), /* A 16 bit relocation without overflow. */ - HOW (R_PPC_ADDR16_LO, 1, 16, 0xffff, 0, FALSE, dont, + HOW (R_PPC_ADDR16_LO, 2, 16, 0xffff, 0, false, dont, bfd_elf_generic_reloc), /* The high order 16 bits of an address. */ - HOW (R_PPC_ADDR16_HI, 1, 16, 0xffff, 16, FALSE, dont, + HOW (R_PPC_ADDR16_HI, 2, 16, 0xffff, 16, false, dont, bfd_elf_generic_reloc), /* 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. */ - HOW (R_PPC_ADDR16_HA, 1, 16, 0xffff, 16, FALSE, dont, + HOW (R_PPC_ADDR16_HA, 2, 16, 0xffff, 16, false, dont, ppc_elf_addr16_ha_reloc), /* An absolute 16 bit branch; the lower two bits must be zero. FIXME: we don't check that, we just clear them. */ - HOW (R_PPC_ADDR14, 2, 16, 0xfffc, 0, FALSE, signed, + HOW (R_PPC_ADDR14, 4, 16, 0xfffc, 0, false, signed, bfd_elf_generic_reloc), /* 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. */ - HOW (R_PPC_ADDR14_BRTAKEN, 2, 16, 0xfffc, 0, FALSE, signed, + HOW (R_PPC_ADDR14_BRTAKEN, 4, 16, 0xfffc, 0, false, signed, bfd_elf_generic_reloc), /* 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. */ - HOW (R_PPC_ADDR14_BRNTAKEN, 2, 16, 0xfffc, 0, FALSE, signed, + HOW (R_PPC_ADDR14_BRNTAKEN, 4, 16, 0xfffc, 0, false, signed, bfd_elf_generic_reloc), /* A relative 26 bit branch; the lower two bits must be zero. */ - HOW (R_PPC_REL24, 2, 26, 0x3fffffc, 0, TRUE, signed, + HOW (R_PPC_REL24, 4, 26, 0x3fffffc, 0, true, signed, bfd_elf_generic_reloc), /* A relative 16 bit branch; the lower two bits must be zero. */ - HOW (R_PPC_REL14, 2, 16, 0xfffc, 0, TRUE, signed, + HOW (R_PPC_REL14, 4, 16, 0xfffc, 0, true, signed, bfd_elf_generic_reloc), /* 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. */ - HOW (R_PPC_REL14_BRTAKEN, 2, 16, 0xfffc, 0, TRUE, signed, + HOW (R_PPC_REL14_BRTAKEN, 4, 16, 0xfffc, 0, true, signed, bfd_elf_generic_reloc), /* 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. */ - HOW (R_PPC_REL14_BRNTAKEN, 2, 16, 0xfffc, 0, TRUE, signed, + HOW (R_PPC_REL14_BRNTAKEN, 4, 16, 0xfffc, 0, true, signed, bfd_elf_generic_reloc), /* Like R_PPC_ADDR16, but referring to the GOT table entry for the symbol. */ - HOW (R_PPC_GOT16, 1, 16, 0xffff, 0, FALSE, signed, + HOW (R_PPC_GOT16, 2, 16, 0xffff, 0, false, signed, ppc_elf_unhandled_reloc), /* Like R_PPC_ADDR16_LO, but referring to the GOT table entry for the symbol. */ - HOW (R_PPC_GOT16_LO, 1, 16, 0xffff, 0, FALSE, dont, + HOW (R_PPC_GOT16_LO, 2, 16, 0xffff, 0, false, dont, ppc_elf_unhandled_reloc), /* Like R_PPC_ADDR16_HI, but referring to the GOT table entry for the symbol. */ - HOW (R_PPC_GOT16_HI, 1, 16, 0xffff, 16, FALSE, dont, + HOW (R_PPC_GOT16_HI, 2, 16, 0xffff, 16, false, dont, ppc_elf_unhandled_reloc), /* Like R_PPC_ADDR16_HA, but referring to the GOT table entry for the symbol. */ - HOW (R_PPC_GOT16_HA, 1, 16, 0xffff, 16, FALSE, dont, + HOW (R_PPC_GOT16_HA, 2, 16, 0xffff, 16, false, dont, ppc_elf_unhandled_reloc), /* Like R_PPC_REL24, but referring to the procedure linkage table entry for the symbol. */ - HOW (R_PPC_PLTREL24, 2, 26, 0x3fffffc, 0, TRUE, signed, + HOW (R_PPC_PLTREL24, 4, 26, 0x3fffffc, 0, true, signed, ppc_elf_unhandled_reloc), /* This is used only by the dynamic linker. The symbol should exist @@ -303,269 +302,269 @@ static reloc_howto_type ppc_elf_howto_raw[] = { 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. */ - HOW (R_PPC_COPY, 2, 32, 0, 0, FALSE, dont, + HOW (R_PPC_COPY, 4, 32, 0, 0, false, dont, ppc_elf_unhandled_reloc), /* Like R_PPC_ADDR32, but used when setting global offset table entries. */ - HOW (R_PPC_GLOB_DAT, 2, 32, 0xffffffff, 0, FALSE, dont, + HOW (R_PPC_GLOB_DAT, 4, 32, 0xffffffff, 0, false, dont, ppc_elf_unhandled_reloc), /* Marks a procedure linkage table entry for a symbol. */ - HOW (R_PPC_JMP_SLOT, 2, 32, 0, 0, FALSE, dont, + HOW (R_PPC_JMP_SLOT, 4, 32, 0, 0, false, dont, ppc_elf_unhandled_reloc), /* 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. */ - HOW (R_PPC_RELATIVE, 2, 32, 0xffffffff, 0, FALSE, dont, + HOW (R_PPC_RELATIVE, 4, 32, 0xffffffff, 0, false, dont, bfd_elf_generic_reloc), /* 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_. */ - HOW (R_PPC_LOCAL24PC, 2, 26, 0x3fffffc, 0, TRUE, signed, + HOW (R_PPC_LOCAL24PC, 4, 26, 0x3fffffc, 0, true, signed, bfd_elf_generic_reloc), /* Like R_PPC_ADDR32, but may be unaligned. */ - HOW (R_PPC_UADDR32, 2, 32, 0xffffffff, 0, FALSE, dont, + HOW (R_PPC_UADDR32, 4, 32, 0xffffffff, 0, false, dont, bfd_elf_generic_reloc), /* Like R_PPC_ADDR16, but may be unaligned. */ - HOW (R_PPC_UADDR16, 1, 16, 0xffff, 0, FALSE, bitfield, + HOW (R_PPC_UADDR16, 2, 16, 0xffff, 0, false, bitfield, bfd_elf_generic_reloc), /* 32-bit PC relative */ - HOW (R_PPC_REL32, 2, 32, 0xffffffff, 0, TRUE, dont, + HOW (R_PPC_REL32, 4, 32, 0xffffffff, 0, true, dont, bfd_elf_generic_reloc), /* 32-bit relocation to the symbol's procedure linkage table. FIXME: not supported. */ - HOW (R_PPC_PLT32, 2, 32, 0, 0, FALSE, dont, + HOW (R_PPC_PLT32, 4, 32, 0, 0, false, dont, ppc_elf_unhandled_reloc), /* 32-bit PC relative relocation to the symbol's procedure linkage table. FIXME: not supported. */ - HOW (R_PPC_PLTREL32, 2, 32, 0, 0, TRUE, dont, + HOW (R_PPC_PLTREL32, 4, 32, 0, 0, true, dont, ppc_elf_unhandled_reloc), /* Like R_PPC_ADDR16_LO, but referring to the PLT table entry for the symbol. */ - HOW (R_PPC_PLT16_LO, 1, 16, 0xffff, 0, FALSE, dont, + HOW (R_PPC_PLT16_LO, 2, 16, 0xffff, 0, false, dont, ppc_elf_unhandled_reloc), /* Like R_PPC_ADDR16_HI, but referring to the PLT table entry for the symbol. */ - HOW (R_PPC_PLT16_HI, 1, 16, 0xffff, 16, FALSE, dont, + HOW (R_PPC_PLT16_HI, 2, 16, 0xffff, 16, false, dont, ppc_elf_unhandled_reloc), /* Like R_PPC_ADDR16_HA, but referring to the PLT table entry for the symbol. */ - HOW (R_PPC_PLT16_HA, 1, 16, 0xffff, 16, FALSE, dont, + HOW (R_PPC_PLT16_HA, 2, 16, 0xffff, 16, false, dont, ppc_elf_unhandled_reloc), /* A sign-extended 16 bit value relative to _SDA_BASE_, for use with small data items. */ - HOW (R_PPC_SDAREL16, 1, 16, 0xffff, 0, FALSE, signed, + HOW (R_PPC_SDAREL16, 2, 16, 0xffff, 0, false, signed, ppc_elf_unhandled_reloc), /* 16-bit section relative relocation. */ - HOW (R_PPC_SECTOFF, 1, 16, 0xffff, 0, FALSE, signed, + HOW (R_PPC_SECTOFF, 2, 16, 0xffff, 0, false, signed, ppc_elf_unhandled_reloc), /* 16-bit lower half section relative relocation. */ - HOW (R_PPC_SECTOFF_LO, 1, 16, 0xffff, 0, FALSE, dont, + HOW (R_PPC_SECTOFF_LO, 2, 16, 0xffff, 0, false, dont, ppc_elf_unhandled_reloc), /* 16-bit upper half section relative relocation. */ - HOW (R_PPC_SECTOFF_HI, 1, 16, 0xffff, 16, FALSE, dont, + HOW (R_PPC_SECTOFF_HI, 2, 16, 0xffff, 16, false, dont, ppc_elf_unhandled_reloc), /* 16-bit upper half adjusted section relative relocation. */ - HOW (R_PPC_SECTOFF_HA, 1, 16, 0xffff, 16, FALSE, dont, + HOW (R_PPC_SECTOFF_HA, 2, 16, 0xffff, 16, false, dont, ppc_elf_unhandled_reloc), /* Marker relocs for TLS. */ - HOW (R_PPC_TLS, 2, 32, 0, 0, FALSE, dont, + HOW (R_PPC_TLS, 4, 32, 0, 0, false, dont, bfd_elf_generic_reloc), - HOW (R_PPC_TLSGD, 2, 32, 0, 0, FALSE, dont, + HOW (R_PPC_TLSGD, 4, 32, 0, 0, false, dont, bfd_elf_generic_reloc), - HOW (R_PPC_TLSLD, 2, 32, 0, 0, FALSE, dont, + HOW (R_PPC_TLSLD, 4, 32, 0, 0, false, dont, bfd_elf_generic_reloc), /* Marker relocs on inline plt call instructions. */ - HOW (R_PPC_PLTSEQ, 2, 32, 0, 0, FALSE, dont, + HOW (R_PPC_PLTSEQ, 4, 32, 0, 0, false, dont, bfd_elf_generic_reloc), - HOW (R_PPC_PLTCALL, 2, 32, 0, 0, FALSE, dont, + HOW (R_PPC_PLTCALL, 4, 32, 0, 0, false, dont, bfd_elf_generic_reloc), /* Computes the load module index of the load module that contains the definition of its TLS sym. */ - HOW (R_PPC_DTPMOD32, 2, 32, 0xffffffff, 0, FALSE, dont, + HOW (R_PPC_DTPMOD32, 4, 32, 0xffffffff, 0, false, dont, ppc_elf_unhandled_reloc), /* 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. */ - HOW (R_PPC_DTPREL32, 2, 32, 0xffffffff, 0, FALSE, dont, + HOW (R_PPC_DTPREL32, 4, 32, 0xffffffff, 0, false, dont, ppc_elf_unhandled_reloc), /* A 16 bit dtprel reloc. */ - HOW (R_PPC_DTPREL16, 1, 16, 0xffff, 0, FALSE, signed, + HOW (R_PPC_DTPREL16, 2, 16, 0xffff, 0, false, signed, ppc_elf_unhandled_reloc), /* Like DTPREL16, but no overflow. */ - HOW (R_PPC_DTPREL16_LO, 1, 16, 0xffff, 0, FALSE, dont, + HOW (R_PPC_DTPREL16_LO, 2, 16, 0xffff, 0, false, dont, ppc_elf_unhandled_reloc), /* Like DTPREL16_LO, but next higher group of 16 bits. */ - HOW (R_PPC_DTPREL16_HI, 1, 16, 0xffff, 16, FALSE, dont, + HOW (R_PPC_DTPREL16_HI, 2, 16, 0xffff, 16, false, dont, ppc_elf_unhandled_reloc), /* Like DTPREL16_HI, but adjust for low 16 bits. */ - HOW (R_PPC_DTPREL16_HA, 1, 16, 0xffff, 16, FALSE, dont, + HOW (R_PPC_DTPREL16_HA, 2, 16, 0xffff, 16, false, dont, ppc_elf_unhandled_reloc), /* Computes a tp-relative displacement, the difference between the value of sym+add and the value of the thread pointer (r13). */ - HOW (R_PPC_TPREL32, 2, 32, 0xffffffff, 0, FALSE, dont, + HOW (R_PPC_TPREL32, 4, 32, 0xffffffff, 0, false, dont, ppc_elf_unhandled_reloc), /* A 16 bit tprel reloc. */ - HOW (R_PPC_TPREL16, 1, 16, 0xffff, 0, FALSE, signed, + HOW (R_PPC_TPREL16, 2, 16, 0xffff, 0, false, signed, ppc_elf_unhandled_reloc), /* Like TPREL16, but no overflow. */ - HOW (R_PPC_TPREL16_LO, 1, 16, 0xffff, 0, FALSE, dont, + HOW (R_PPC_TPREL16_LO, 2, 16, 0xffff, 0, false, dont, ppc_elf_unhandled_reloc), /* Like TPREL16_LO, but next higher group of 16 bits. */ - HOW (R_PPC_TPREL16_HI, 1, 16, 0xffff, 16, FALSE, dont, + HOW (R_PPC_TPREL16_HI, 2, 16, 0xffff, 16, false, dont, ppc_elf_unhandled_reloc), /* Like TPREL16_HI, but adjust for low 16 bits. */ - HOW (R_PPC_TPREL16_HA, 1, 16, 0xffff, 16, FALSE, dont, + HOW (R_PPC_TPREL16_HA, 2, 16, 0xffff, 16, false, dont, ppc_elf_unhandled_reloc), /* 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. */ - HOW (R_PPC_GOT_TLSGD16, 1, 16, 0xffff, 0, FALSE, signed, + HOW (R_PPC_GOT_TLSGD16, 2, 16, 0xffff, 0, false, signed, ppc_elf_unhandled_reloc), /* Like GOT_TLSGD16, but no overflow. */ - HOW (R_PPC_GOT_TLSGD16_LO, 1, 16, 0xffff, 0, FALSE, dont, + HOW (R_PPC_GOT_TLSGD16_LO, 2, 16, 0xffff, 0, false, dont, ppc_elf_unhandled_reloc), /* Like GOT_TLSGD16_LO, but next higher group of 16 bits. */ - HOW (R_PPC_GOT_TLSGD16_HI, 1, 16, 0xffff, 16, FALSE, dont, + HOW (R_PPC_GOT_TLSGD16_HI, 2, 16, 0xffff, 16, false, dont, ppc_elf_unhandled_reloc), /* Like GOT_TLSGD16_HI, but adjust for low 16 bits. */ - HOW (R_PPC_GOT_TLSGD16_HA, 1, 16, 0xffff, 16, FALSE, dont, + HOW (R_PPC_GOT_TLSGD16_HA, 2, 16, 0xffff, 16, false, dont, ppc_elf_unhandled_reloc), /* 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. */ - HOW (R_PPC_GOT_TLSLD16, 1, 16, 0xffff, 0, FALSE, signed, + HOW (R_PPC_GOT_TLSLD16, 2, 16, 0xffff, 0, false, signed, ppc_elf_unhandled_reloc), /* Like GOT_TLSLD16, but no overflow. */ - HOW (R_PPC_GOT_TLSLD16_LO, 1, 16, 0xffff, 0, FALSE, dont, + HOW (R_PPC_GOT_TLSLD16_LO, 2, 16, 0xffff, 0, false, dont, ppc_elf_unhandled_reloc), /* Like GOT_TLSLD16_LO, but next higher group of 16 bits. */ - HOW (R_PPC_GOT_TLSLD16_HI, 1, 16, 0xffff, 16, FALSE, dont, + HOW (R_PPC_GOT_TLSLD16_HI, 2, 16, 0xffff, 16, false, dont, ppc_elf_unhandled_reloc), /* Like GOT_TLSLD16_HI, but adjust for low 16 bits. */ - HOW (R_PPC_GOT_TLSLD16_HA, 1, 16, 0xffff, 16, FALSE, dont, + HOW (R_PPC_GOT_TLSLD16_HA, 2, 16, 0xffff, 16, false, dont, ppc_elf_unhandled_reloc), /* Allocates an entry in the GOT with value (sym+add)@dtprel, and computes the offset to the entry. */ - HOW (R_PPC_GOT_DTPREL16, 1, 16, 0xffff, 0, FALSE, signed, + HOW (R_PPC_GOT_DTPREL16, 2, 16, 0xffff, 0, false, signed, ppc_elf_unhandled_reloc), /* Like GOT_DTPREL16, but no overflow. */ - HOW (R_PPC_GOT_DTPREL16_LO, 1, 16, 0xffff, 0, FALSE, dont, + HOW (R_PPC_GOT_DTPREL16_LO, 2, 16, 0xffff, 0, false, dont, ppc_elf_unhandled_reloc), /* Like GOT_DTPREL16_LO, but next higher group of 16 bits. */ - HOW (R_PPC_GOT_DTPREL16_HI, 1, 16, 0xffff, 16, FALSE, dont, + HOW (R_PPC_GOT_DTPREL16_HI, 2, 16, 0xffff, 16, false, dont, ppc_elf_unhandled_reloc), /* Like GOT_DTPREL16_HI, but adjust for low 16 bits. */ - HOW (R_PPC_GOT_DTPREL16_HA, 1, 16, 0xffff, 16, FALSE, dont, + HOW (R_PPC_GOT_DTPREL16_HA, 2, 16, 0xffff, 16, false, dont, ppc_elf_unhandled_reloc), /* Allocates an entry in the GOT with value (sym+add)@tprel, and computes the offset to the entry. */ - HOW (R_PPC_GOT_TPREL16, 1, 16, 0xffff, 0, FALSE, signed, + HOW (R_PPC_GOT_TPREL16, 2, 16, 0xffff, 0, false, signed, ppc_elf_unhandled_reloc), /* Like GOT_TPREL16, but no overflow. */ - HOW (R_PPC_GOT_TPREL16_LO, 1, 16, 0xffff, 0, FALSE, dont, + HOW (R_PPC_GOT_TPREL16_LO, 2, 16, 0xffff, 0, false, dont, ppc_elf_unhandled_reloc), /* Like GOT_TPREL16_LO, but next higher group of 16 bits. */ - HOW (R_PPC_GOT_TPREL16_HI, 1, 16, 0xffff, 16, FALSE, dont, + HOW (R_PPC_GOT_TPREL16_HI, 2, 16, 0xffff, 16, false, dont, ppc_elf_unhandled_reloc), /* Like GOT_TPREL16_HI, but adjust for low 16 bits. */ - HOW (R_PPC_GOT_TPREL16_HA, 1, 16, 0xffff, 16, FALSE, dont, + HOW (R_PPC_GOT_TPREL16_HA, 2, 16, 0xffff, 16, false, dont, ppc_elf_unhandled_reloc), /* 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. */ - HOW (R_PPC_EMB_NADDR32, 2, 32, 0xffffffff, 0, FALSE, dont, + HOW (R_PPC_EMB_NADDR32, 4, 32, 0xffffffff, 0, false, dont, ppc_elf_unhandled_reloc), /* 16 bit value resulting from the addend minus the symbol. */ - HOW (R_PPC_EMB_NADDR16, 1, 16, 0xffff, 0, FALSE, signed, + HOW (R_PPC_EMB_NADDR16, 2, 16, 0xffff, 0, false, signed, ppc_elf_unhandled_reloc), /* 16 bit value resulting from the addend minus the symbol. */ - HOW (R_PPC_EMB_NADDR16_LO, 1, 16, 0xffff, 0, FALSE, dont, + HOW (R_PPC_EMB_NADDR16_LO, 2, 16, 0xffff, 0, false, dont, ppc_elf_unhandled_reloc), /* The high order 16 bits of the addend minus the symbol. */ - HOW (R_PPC_EMB_NADDR16_HI, 1, 16, 0xffff, 16, FALSE, dont, + HOW (R_PPC_EMB_NADDR16_HI, 2, 16, 0xffff, 16, false, dont, ppc_elf_unhandled_reloc), /* 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. */ - HOW (R_PPC_EMB_NADDR16_HA, 1, 16, 0xffff, 16, FALSE, dont, + HOW (R_PPC_EMB_NADDR16_HA, 2, 16, 0xffff, 16, false, dont, ppc_elf_unhandled_reloc), /* 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. */ - HOW (R_PPC_EMB_SDAI16, 1, 16, 0xffff, 0, FALSE, signed, + HOW (R_PPC_EMB_SDAI16, 2, 16, 0xffff, 0, false, signed, ppc_elf_unhandled_reloc), /* 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. */ - HOW (R_PPC_EMB_SDA2I16, 1, 16, 0xffff, 0, FALSE, signed, + HOW (R_PPC_EMB_SDA2I16, 2, 16, 0xffff, 0, false, signed, ppc_elf_unhandled_reloc), /* A sign-extended 16 bit value relative to _SDA2_BASE_, for use with small data items. */ - HOW (R_PPC_EMB_SDA2REL, 1, 16, 0xffff, 0, FALSE, signed, + HOW (R_PPC_EMB_SDA2REL, 2, 16, 0xffff, 0, false, signed, ppc_elf_unhandled_reloc), /* 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). */ - HOW (R_PPC_EMB_SDA21, 2, 16, 0xffff, 0, FALSE, signed, + HOW (R_PPC_EMB_SDA21, 4, 16, 0xffff, 0, false, signed, ppc_elf_unhandled_reloc), /* Relocation not handled: R_PPC_EMB_MRKREF */ @@ -578,121 +577,121 @@ static reloc_howto_type ppc_elf_howto_raw[] = { /* 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). */ - HOW (R_PPC_EMB_RELSDA, 1, 16, 0xffff, 0, FALSE, signed, + HOW (R_PPC_EMB_RELSDA, 2, 16, 0xffff, 0, false, signed, ppc_elf_unhandled_reloc), /* A relative 8 bit branch. */ - HOW (R_PPC_VLE_REL8, 1, 8, 0xff, 1, TRUE, signed, + HOW (R_PPC_VLE_REL8, 2, 8, 0xff, 1, true, signed, bfd_elf_generic_reloc), /* A relative 15 bit branch. */ - HOW (R_PPC_VLE_REL15, 2, 16, 0xfffe, 0, TRUE, signed, + HOW (R_PPC_VLE_REL15, 4, 16, 0xfffe, 0, true, signed, bfd_elf_generic_reloc), /* A relative 24 bit branch. */ - HOW (R_PPC_VLE_REL24, 2, 25, 0x1fffffe, 0, TRUE, signed, + HOW (R_PPC_VLE_REL24, 4, 25, 0x1fffffe, 0, true, signed, bfd_elf_generic_reloc), /* The 16 LSBS in split16a format. */ - HOW (R_PPC_VLE_LO16A, 2, 16, 0x1f07ff, 0, FALSE, dont, + HOW (R_PPC_VLE_LO16A, 4, 16, 0x1f07ff, 0, false, dont, ppc_elf_unhandled_reloc), /* The 16 LSBS in split16d format. */ - HOW (R_PPC_VLE_LO16D, 2, 16, 0x3e007ff, 0, FALSE, dont, + HOW (R_PPC_VLE_LO16D, 4, 16, 0x3e007ff, 0, false, dont, ppc_elf_unhandled_reloc), /* Bits 16-31 split16a format. */ - HOW (R_PPC_VLE_HI16A, 2, 16, 0x1f07ff, 16, FALSE, dont, + HOW (R_PPC_VLE_HI16A, 4, 16, 0x1f07ff, 16, false, dont, ppc_elf_unhandled_reloc), /* Bits 16-31 split16d format. */ - HOW (R_PPC_VLE_HI16D, 2, 16, 0x3e007ff, 16, FALSE, dont, + HOW (R_PPC_VLE_HI16D, 4, 16, 0x3e007ff, 16, false, dont, ppc_elf_unhandled_reloc), /* Bits 16-31 (High Adjusted) in split16a format. */ - HOW (R_PPC_VLE_HA16A, 2, 16, 0x1f07ff, 16, FALSE, dont, + HOW (R_PPC_VLE_HA16A, 4, 16, 0x1f07ff, 16, false, dont, ppc_elf_unhandled_reloc), /* Bits 16-31 (High Adjusted) in split16d format. */ - HOW (R_PPC_VLE_HA16D, 2, 16, 0x3e007ff, 16, FALSE, dont, + HOW (R_PPC_VLE_HA16D, 4, 16, 0x3e007ff, 16, false, dont, ppc_elf_unhandled_reloc), /* This reloc is like R_PPC_EMB_SDA21 but only applies to e_add16i instructions. If the register base is 0 then the linker changes the e_add16i to an e_li instruction. */ - HOW (R_PPC_VLE_SDA21, 2, 16, 0xffff, 0, FALSE, signed, + HOW (R_PPC_VLE_SDA21, 4, 16, 0xffff, 0, false, signed, ppc_elf_unhandled_reloc), /* Like R_PPC_VLE_SDA21 but ignore overflow. */ - HOW (R_PPC_VLE_SDA21_LO, 2, 16, 0xffff, 0, FALSE, dont, + HOW (R_PPC_VLE_SDA21_LO, 4, 16, 0xffff, 0, false, dont, ppc_elf_unhandled_reloc), /* The 16 LSBS relative to _SDA_BASE_ in split16a format. */ - HOW (R_PPC_VLE_SDAREL_LO16A, 2, 16, 0x1f07ff, 0, FALSE, dont, + HOW (R_PPC_VLE_SDAREL_LO16A, 4, 16, 0x1f07ff, 0, false, dont, ppc_elf_unhandled_reloc), /* The 16 LSBS relative to _SDA_BASE_ in split16d format. */ - HOW (R_PPC_VLE_SDAREL_LO16D, 2, 16, 0x3e007ff, 0, FALSE, dont, + HOW (R_PPC_VLE_SDAREL_LO16D, 4, 16, 0x3e007ff, 0, false, dont, ppc_elf_unhandled_reloc), /* Bits 16-31 relative to _SDA_BASE_ in split16a format. */ - HOW (R_PPC_VLE_SDAREL_HI16A, 2, 16, 0x1f07ff, 16, FALSE, dont, + HOW (R_PPC_VLE_SDAREL_HI16A, 4, 16, 0x1f07ff, 16, false, dont, ppc_elf_unhandled_reloc), /* Bits 16-31 relative to _SDA_BASE_ in split16d format. */ - HOW (R_PPC_VLE_SDAREL_HI16D, 2, 16, 0x3e007ff, 16, FALSE, dont, + HOW (R_PPC_VLE_SDAREL_HI16D, 4, 16, 0x3e007ff, 16, false, dont, ppc_elf_unhandled_reloc), /* Bits 16-31 (HA) relative to _SDA_BASE split16a format. */ - HOW (R_PPC_VLE_SDAREL_HA16A, 2, 16, 0x1f07ff, 16, FALSE, dont, + HOW (R_PPC_VLE_SDAREL_HA16A, 4, 16, 0x1f07ff, 16, false, dont, ppc_elf_unhandled_reloc), /* Bits 16-31 (HA) relative to _SDA_BASE split16d format. */ - HOW (R_PPC_VLE_SDAREL_HA16D, 2, 16, 0x3e007ff, 16, FALSE, dont, + HOW (R_PPC_VLE_SDAREL_HA16D, 4, 16, 0x3e007ff, 16, false, dont, ppc_elf_unhandled_reloc), /* e_li split20 format. */ - HOW (R_PPC_VLE_ADDR20, 2, 20, 0x1f7fff, 0, FALSE, dont, + HOW (R_PPC_VLE_ADDR20, 4, 20, 0x1f7fff, 0, false, dont, ppc_elf_unhandled_reloc), - HOW (R_PPC_IRELATIVE, 2, 32, 0xffffffff, 0, FALSE, dont, + HOW (R_PPC_IRELATIVE, 4, 32, 0xffffffff, 0, false, dont, ppc_elf_unhandled_reloc), /* A 16 bit relative relocation. */ - HOW (R_PPC_REL16, 1, 16, 0xffff, 0, TRUE, signed, + HOW (R_PPC_REL16, 2, 16, 0xffff, 0, true, signed, bfd_elf_generic_reloc), /* A 16 bit relative relocation without overflow. */ - HOW (R_PPC_REL16_LO, 1, 16, 0xffff, 0, TRUE, dont, + HOW (R_PPC_REL16_LO, 2, 16, 0xffff, 0, true, dont, bfd_elf_generic_reloc), /* The high order 16 bits of a relative address. */ - HOW (R_PPC_REL16_HI, 1, 16, 0xffff, 16, TRUE, dont, + HOW (R_PPC_REL16_HI, 2, 16, 0xffff, 16, true, dont, bfd_elf_generic_reloc), /* 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. */ - HOW (R_PPC_REL16_HA, 1, 16, 0xffff, 16, TRUE, dont, + HOW (R_PPC_REL16_HA, 2, 16, 0xffff, 16, true, dont, ppc_elf_addr16_ha_reloc), /* Like R_PPC_REL16_HA but for split field in addpcis. */ - HOW (R_PPC_REL16DX_HA, 2, 16, 0x1fffc1, 16, TRUE, signed, + HOW (R_PPC_REL16DX_HA, 4, 16, 0x1fffc1, 16, true, signed, ppc_elf_addr16_ha_reloc), /* A split-field reloc for addpcis, non-relative (gas internal use only). */ - HOW (R_PPC_16DX_HA, 2, 16, 0x1fffc1, 16, FALSE, signed, + HOW (R_PPC_16DX_HA, 4, 16, 0x1fffc1, 16, false, signed, ppc_elf_addr16_ha_reloc), /* GNU extension to record C++ vtable hierarchy. */ - HOW (R_PPC_GNU_VTINHERIT, 0, 0, 0, 0, FALSE, dont, + HOW (R_PPC_GNU_VTINHERIT, 0, 0, 0, 0, false, dont, NULL), /* GNU extension to record C++ vtable member usage. */ - HOW (R_PPC_GNU_VTENTRY, 0, 0, 0, 0, FALSE, dont, + HOW (R_PPC_GNU_VTENTRY, 0, 0, 0, 0, false, dont, NULL), /* Phony reloc to handle AIX style TOC entries. */ - HOW (R_PPC_TOC16, 1, 16, 0xffff, 0, FALSE, signed, + HOW (R_PPC_TOC16, 2, 16, 0xffff, 0, false, signed, ppc_elf_unhandled_reloc), }; @@ -883,7 +882,7 @@ ppc_elf_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, /* Set the howto pointer for a PowerPC ELF reloc. */ -static bfd_boolean +static bool ppc_elf_info_to_howto (bfd *abfd, arelent *cache_ptr, Elf_Internal_Rela *dst) @@ -901,7 +900,7 @@ ppc_elf_info_to_howto (bfd *abfd, _bfd_error_handler (_("%pB: unsupported relocation type %#x"), abfd, r_type); bfd_set_error (bfd_error_bad_value); - return FALSE; + return false; } cache_ptr->howto = ppc_elf_howto_table[r_type]; @@ -915,10 +914,10 @@ ppc_elf_info_to_howto (bfd *abfd, abfd, r_type); bfd_set_error (bfd_error_bad_value); - return FALSE; + return false; } - return TRUE; + return true; } /* Handle the R_PPC_ADDR16_HA and R_PPC_REL16_HA relocs. */ @@ -960,6 +959,10 @@ ppc_elf_addr16_ha_reloc (bfd *abfd, value >>= 16; octets = reloc_entry->address * OCTETS_PER_BYTE (abfd, input_section); + if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd, + input_section, octets)) + return bfd_reloc_outofrange; + insn = bfd_get_32 (abfd, (bfd_byte *) data + octets); insn &= ~0x1fffc1; insn |= (value & 0xffc1) | ((value & 0x3e) << 15); @@ -985,10 +988,12 @@ ppc_elf_unhandled_reloc (bfd *abfd, if (error_message != NULL) { - static char buf[60]; - sprintf (buf, _("generic linker can't handle %s"), - reloc_entry->howto->name); - *error_message = buf; + static char *message; + free (message); + if (asprintf (&message, _("generic linker can't handle %s"), + reloc_entry->howto->name) < 0) + message = NULL; + *error_message = message; } return bfd_reloc_dangerous; } @@ -1050,7 +1055,7 @@ struct ppc_elf_obj_tdata /* Override the generic function because we store some extras. */ -static bfd_boolean +static bool ppc_elf_mkobject (bfd *abfd) { return bfd_elf_allocate_object (abfd, sizeof (struct ppc_elf_obj_tdata), @@ -1059,7 +1064,7 @@ ppc_elf_mkobject (bfd *abfd) /* When defaulting arch/mach, decode apuinfo to find a better match. */ -bfd_boolean +bool _bfd_elf_ppc_set_arch (bfd *abfd) { unsigned long mach = 0; @@ -1134,17 +1139,17 @@ _bfd_elf_ppc_set_arch (bfd *abfd) break; } } - return TRUE; + return true; } /* Fix bad default arch selected for a 32 bit input bfd when the default is 64 bit. Also select arch based on apuinfo. */ -static bfd_boolean +static bool ppc_elf_object_p (bfd *abfd) { if (!abfd->arch_info->the_default) - return TRUE; + return true; if (abfd->arch_info->bits_per_word == 64) { @@ -1162,20 +1167,20 @@ ppc_elf_object_p (bfd *abfd) /* Function to set whether a module needs the -mrelocatable bit set. */ -static bfd_boolean +static bool 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; + elf_flags_init (abfd) = true; + return true; } /* Support for core dump NOTE sections. */ -static bfd_boolean +static bool ppc_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) { int offset; @@ -1184,7 +1189,7 @@ ppc_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) switch (note->descsz) { default: - return FALSE; + return false; case 268: /* Linux/PPC. */ /* pr_cursig */ @@ -1205,13 +1210,13 @@ ppc_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) size, note->descpos + offset); } -static bfd_boolean +static bool ppc_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) { switch (note->descsz) { default: - return FALSE; + return false; case 128: /* Linux/PPC elf_prpsinfo. */ elf_tdata (abfd)->core->pid @@ -1234,7 +1239,7 @@ ppc_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) command[n - 1] = '\0'; } - return TRUE; + return true; } static char * @@ -1319,7 +1324,7 @@ ppc_elf_plt_sym_val (bfd_vma i ATTRIBUTE_UNUSED, is called when bfd_section_from_shdr finds a section with an unknown type. */ -static bfd_boolean +static bool ppc_elf_section_from_shdr (bfd *abfd, Elf_Internal_Shdr *hdr, const char *name, @@ -1329,7 +1334,7 @@ ppc_elf_section_from_shdr (bfd *abfd, flagword flags; if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex)) - return FALSE; + return false; newsect = hdr->bfd_section; flags = 0; @@ -1339,10 +1344,10 @@ ppc_elf_section_from_shdr (bfd *abfd, if (hdr->sh_type == SHT_ORDERED) flags |= SEC_SORT_ENTRIES; - if (strncmp (name, ".PPC.EMB", 8) == 0) + if (startswith (name, ".PPC.EMB")) name += 8; - if (strncmp (name, ".sbss", 5) == 0 - || strncmp (name, ".sdata", 6) == 0) + if (startswith (name, ".sbss") + || startswith (name, ".sdata")) flags |= SEC_SMALL_DATA; return (flags == 0 @@ -1351,7 +1356,7 @@ ppc_elf_section_from_shdr (bfd *abfd, /* Set up any other section flags and such that may be necessary. */ -static bfd_boolean +static bool ppc_elf_fake_sections (bfd *abfd ATTRIBUTE_UNUSED, Elf_Internal_Shdr *shdr, asection *asect) @@ -1359,7 +1364,7 @@ ppc_elf_fake_sections (bfd *abfd ATTRIBUTE_UNUSED, if ((asect->flags & SEC_SORT_ENTRIES) != 0) shdr->sh_type = SHT_ORDERED; - return TRUE; + return true; } /* If we have .sbss2 or .PPC.EMB.sbss0 output sections, we @@ -1385,7 +1390,7 @@ ppc_elf_additional_program_headers (bfd *abfd, /* Modify the segment map for VLE executables. */ -bfd_boolean +bool ppc_elf_modify_segment_map (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED) { @@ -1456,7 +1461,7 @@ ppc_elf_modify_segment_map (bfd *abfd, amt += (m->count - j - 1) * sizeof (asection *); n = (struct elf_segment_map *) bfd_zalloc (abfd, amt); if (n == NULL) - return FALSE; + return false; n->p_type = PT_LOAD; n->count = m->count - j; @@ -1468,7 +1473,7 @@ ppc_elf_modify_segment_map (bfd *abfd, m->next = n; } - return TRUE; + return true; } /* Add extra PPC sections -- Note, for now, make .sbss2 and @@ -1491,7 +1496,7 @@ static const struct bfd_elf_special_section ppc_elf_special_sections[] = }; /* This is what we want for new plt/got. */ -static struct bfd_elf_special_section ppc_alt_plt = +static const struct bfd_elf_special_section ppc_alt_plt = { STRING_COMMA_LEN (".plt"), 0, SHT_PROGBITS, SHF_ALLOC }; static const struct bfd_elf_special_section * @@ -1524,13 +1529,13 @@ typedef struct apuinfo_list apuinfo_list; static apuinfo_list *head; -static bfd_boolean apuinfo_set; +static bool apuinfo_set; static void apuinfo_list_init (void) { head = NULL; - apuinfo_set = FALSE; + apuinfo_set = false; } static void @@ -1630,7 +1635,7 @@ ppc_elf_begin_write_processing (bfd *abfd, struct bfd_link_info *link_info) if (length < 20) goto fail; - apuinfo_set = TRUE; + apuinfo_set = true; if (largest_input_size < asec->size) { free (buffer); @@ -1700,7 +1705,7 @@ 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 +static bool ppc_elf_write_section (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *link_info ATTRIBUTE_UNUSED, asection *asec, @@ -1764,20 +1769,20 @@ ppc_final_write_processing (bfd *abfd) apuinfo_list_finish (); } -static bfd_boolean +static bool ppc_elf_final_write_processing (bfd *abfd) { ppc_final_write_processing (abfd); return _bfd_elf_final_write_processing (abfd); } -static bfd_boolean +static bool is_nonpic_glink_stub (bfd *abfd, asection *glink, bfd_vma off) { bfd_byte buf[4 * 4]; if (!bfd_get_section_contents (abfd, glink, buf, off, sizeof buf)) - return FALSE; + return false; return ((bfd_get_32 (abfd, buf + 0) & 0xffff0000) == LIS_11 && (bfd_get_32 (abfd, buf + 4) & 0xffff0000) == LWZ_11_11 @@ -1785,7 +1790,7 @@ is_nonpic_glink_stub (bfd *abfd, asection *glink, bfd_vma off) && bfd_get_32 (abfd, buf + 12) == BCTR); } -static bfd_boolean +static bool section_covers_vma (bfd *abfd ATTRIBUTE_UNUSED, asection *section, void *ptr) { bfd_vma vma = *(bfd_vma *) ptr; @@ -1799,7 +1804,7 @@ 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); + bool (*slurp_relocs) (bfd *, asection *, asymbol **, bool); asection *plt, *relplt, *dynamic, *glink; bfd_vma glink_vma = 0; bfd_vma resolv_vma = 0; @@ -1847,9 +1852,9 @@ ppc_elf_get_synthetic_symtab (bfd *abfd, long symcount, asymbol **syms, 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) + for (extdyn = dynbuf, extdynend = dynbuf + dynamic->size; + (size_t) (extdynend - extdyn) >= extdynsize; + extdyn += extdynsize) { Elf_Internal_Dyn dyn; (*swap_dyn_in) (abfd, extdyn, &dyn); @@ -1928,7 +1933,7 @@ ppc_elf_get_synthetic_symtab (bfd *abfd, long symcount, asymbol **syms, return 0; slurp_relocs = get_elf_backend_data (abfd)->s->slurp_reloc_table; - if (! (*slurp_relocs) (abfd, relplt, dynsyms, TRUE)) + if (! (*slurp_relocs) (abfd, relplt, dynsyms, true)) return -1; size = count * sizeof (asymbol); @@ -2195,9 +2200,6 @@ struct ppc_elf_link_hash_table /* The type of PLT we have chosen to use. */ enum ppc_elf_plt_type plt_type; - /* True if the target system is VxWorks. */ - unsigned int is_vxworks:1; - /* Whether there exist local gnu indirect function resolvers, referenced by dynamic relocations. */ unsigned int local_ifunc_resolver:1; @@ -2215,9 +2217,6 @@ struct ppc_elf_link_hash_table 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 @@ -2236,8 +2235,9 @@ struct ppc_elf_link_hash_table /* 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) + ((is_elf_hash_table ((p)->hash) \ + && elf_hash_table_id (elf_hash_table (p)) == PPC32_ELF_DATA) \ + ? (struct ppc_elf_link_hash_table *) (p)->hash : NULL) /* Create an entry in a PPC ELF linker hash table. */ @@ -2326,33 +2326,33 @@ ppc_elf_link_params (struct bfd_link_info *info, struct ppc_elf_params *params) /* Create .got and the related sections. */ -static bfd_boolean +static bool ppc_elf_create_got (bfd *abfd, struct bfd_link_info *info) { struct ppc_elf_link_hash_table *htab; if (!_bfd_elf_create_got_section (abfd, info)) - return FALSE; + return false; htab = ppc_elf_hash_table (info); - if (!htab->is_vxworks) + if (htab->elf.target_os != is_vxworks) { /* The powerpc .got has a blrl instruction in it. Mark it executable. */ flagword flags = (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED); if (!bfd_set_section_flags (htab->elf.sgot, flags)) - return FALSE; + return false; } - return TRUE; + return true; } /* Create a special linker section, used for R_PPC_EMB_SDAI16 and R_PPC_EMB_SDA2I16 pointers. These sections become part of .sdata and .sdata2. Create _SDA_BASE_ and _SDA2_BASE too. */ -static bfd_boolean +static bool ppc_elf_create_linker_section (bfd *abfd, struct bfd_link_info *info, flagword flags, @@ -2365,7 +2365,7 @@ ppc_elf_create_linker_section (bfd *abfd, s = bfd_make_section_anyway_with_flags (abfd, lsect->name, flags); if (s == NULL) - return FALSE; + return false; lsect->section = s; /* Define the sym on the first section of this name. */ @@ -2373,12 +2373,12 @@ ppc_elf_create_linker_section (bfd *abfd, lsect->sym = _bfd_elf_define_linkage_sym (abfd, info, s, lsect->sym_name); if (lsect->sym == NULL) - return FALSE; + return false; lsect->sym->root.u.def.value = 0x8000; - return TRUE; + return true; } -static bfd_boolean +static bool ppc_elf_create_glink (bfd *abfd, struct bfd_link_info *info) { struct ppc_elf_link_hash_table *htab = ppc_elf_hash_table (info); @@ -2395,7 +2395,7 @@ ppc_elf_create_glink (bfd *abfd, struct bfd_link_info *info) p2align = htab->params->plt_stub_align; if (s == NULL || !bfd_set_section_alignment (s, p2align)) - return FALSE; + return false; if (!info->no_ld_generated_unwind_info) { @@ -2405,7 +2405,7 @@ ppc_elf_create_glink (bfd *abfd, struct bfd_link_info *info) htab->glink_eh_frame = s; if (s == NULL || !bfd_set_section_alignment (s, 2)) - return FALSE; + return false; } flags = SEC_ALLOC | SEC_LINKER_CREATED; @@ -2413,7 +2413,7 @@ ppc_elf_create_glink (bfd *abfd, struct bfd_link_info *info) htab->elf.iplt = s; if (s == NULL || !bfd_set_section_alignment (s, 4)) - return FALSE; + return false; flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED); @@ -2421,7 +2421,7 @@ ppc_elf_create_glink (bfd *abfd, struct bfd_link_info *info) htab->elf.irelplt = s; if (s == NULL || ! bfd_set_section_alignment (s, 2)) - return FALSE; + return false; /* Local plt entries. */ flags = (SEC_ALLOC | SEC_LOAD @@ -2430,7 +2430,7 @@ ppc_elf_create_glink (bfd *abfd, struct bfd_link_info *info) flags); if (htab->pltlocal == NULL || !bfd_set_section_alignment (htab->pltlocal, 2)) - return FALSE; + return false; if (bfd_link_pic (info)) { @@ -2440,25 +2440,25 @@ ppc_elf_create_glink (bfd *abfd, struct bfd_link_info *info) = bfd_make_section_anyway_with_flags (abfd, ".rela.branch_lt", flags); if (htab->relpltlocal == NULL || !bfd_set_section_alignment (htab->relpltlocal, 2)) - return FALSE; + return false; } if (!ppc_elf_create_linker_section (abfd, info, 0, &htab->sdata[0])) - return FALSE; + return false; if (!ppc_elf_create_linker_section (abfd, info, SEC_READONLY, &htab->sdata[1])) - return FALSE; + return false; - return TRUE; + 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 +static bool ppc_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) { struct ppc_elf_link_hash_table *htab; @@ -2469,20 +2469,20 @@ ppc_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) if (htab->elf.sgot == NULL && !ppc_elf_create_got (abfd, info)) - return FALSE; + return false; if (!_bfd_elf_create_dynamic_sections (abfd, info)) - return FALSE; + return false; if (htab->glink == NULL && !ppc_elf_create_glink (abfd, info)) - return FALSE; + return false; s = bfd_make_section_anyway_with_flags (abfd, ".dynsbss", SEC_ALLOC | SEC_LINKER_CREATED); htab->dynsbss = s; if (s == NULL) - return FALSE; + return false; if (! bfd_link_pic (info)) { @@ -2492,12 +2492,12 @@ ppc_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) htab->relsbss = s; if (s == NULL || !bfd_set_section_alignment (s, 2)) - return FALSE; + return false; } - if (htab->is_vxworks + if (htab->elf.target_os == is_vxworks && !elf_vxworks_create_dynamic_sections (abfd, info, &htab->srelplt2)) - return FALSE; + return false; s = htab->elf.splt; flags = SEC_ALLOC | SEC_CODE | SEC_LINKER_CREATED; @@ -2614,7 +2614,7 @@ ppc_elf_copy_indirect_symbol (struct bfd_link_info *info, /* 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 +static bool ppc_elf_add_symbol_hook (bfd *abfd, struct bfd_link_info *info, Elf_Internal_Sym *sym, @@ -2635,7 +2635,7 @@ ppc_elf_add_symbol_hook (bfd *abfd, htab = ppc_elf_hash_table (info); if (htab->sbss == NULL) { - flagword flags = SEC_IS_COMMON | SEC_LINKER_CREATED; + flagword flags = SEC_IS_COMMON | SEC_SMALL_DATA | SEC_LINKER_CREATED; if (!htab->elf.dynobj) htab->elf.dynobj = abfd; @@ -2644,14 +2644,14 @@ ppc_elf_add_symbol_hook (bfd *abfd, ".sbss", flags); if (htab->sbss == NULL) - return FALSE; + return false; } *secp = htab->sbss; *valp = sym->st_size; } - return TRUE; + return true; } /* Find a linker generated pointer with a given addend and type. */ @@ -2671,7 +2671,7 @@ elf_find_pointer_linker_section /* Allocate a pointer to live in a linker created section. */ -static bfd_boolean +static bool elf_allocate_pointer_linker_section (bfd *abfd, elf_linker_section_t *lsect, struct elf_link_hash_entry *h, @@ -2694,7 +2694,7 @@ elf_allocate_pointer_linker_section (bfd *abfd, if (elf_find_pointer_linker_section (eh->linker_section_pointer, rel->r_addend, lsect)) - return TRUE; + return true; ptr_linker_section_ptr = &eh->linker_section_pointer; } @@ -2715,7 +2715,7 @@ elf_allocate_pointer_linker_section (bfd *abfd, ptr = bfd_zalloc (abfd, amt); if (!ptr) - return FALSE; + return false; elf_local_ptr_offsets (abfd) = ptr; } @@ -2724,7 +2724,7 @@ elf_allocate_pointer_linker_section (bfd *abfd, if (elf_find_pointer_linker_section (ptr[r_symndx], rel->r_addend, lsect)) - return TRUE; + return true; ptr_linker_section_ptr = &ptr[r_symndx]; } @@ -2736,7 +2736,7 @@ elf_allocate_pointer_linker_section (bfd *abfd, linker_section_ptr = bfd_alloc (abfd, amt); if (!linker_section_ptr) - return FALSE; + return false; linker_section_ptr->next = *ptr_linker_section_ptr; linker_section_ptr->addend = rel->r_addend; @@ -2744,7 +2744,7 @@ elf_allocate_pointer_linker_section (bfd *abfd, *ptr_linker_section_ptr = linker_section_ptr; if (!bfd_set_section_alignment (lsect->section, 2)) - return FALSE; + return false; linker_section_ptr->offset = lsect->section->size; lsect->section->size += 4; @@ -2755,7 +2755,7 @@ elf_allocate_pointer_linker_section (bfd *abfd, (long) lsect->section->size); #endif - return TRUE; + return true; } static struct plt_entry ** @@ -2789,7 +2789,7 @@ update_local_sym_info (bfd *abfd, return local_plt + r_symndx; } -static bfd_boolean +static bool update_plt_info (bfd *abfd, struct plt_entry **plist, asection *sec, bfd_vma addend) { @@ -2805,7 +2805,7 @@ update_plt_info (bfd *abfd, struct plt_entry **plist, size_t amt = sizeof (*ent); ent = bfd_alloc (abfd, amt); if (ent == NULL) - return FALSE; + return false; ent->next = *plist; ent->sec = sec; ent->addend = addend; @@ -2813,7 +2813,7 @@ update_plt_info (bfd *abfd, struct plt_entry **plist, *plist = ent; } ent->plt.refcount += 1; - return TRUE; + return true; } static struct plt_entry * @@ -2829,7 +2829,7 @@ find_plt_ent (struct plt_entry **plist, asection *sec, bfd_vma addend) return ent; } -static bfd_boolean +static bool is_branch_reloc (enum elf_ppc_reloc_type r_type) { return (r_type == R_PPC_PLTREL24 @@ -2847,7 +2847,7 @@ is_branch_reloc (enum elf_ppc_reloc_type r_type) /* Relocs on inline plt call sequence insns prior to the call. */ -static bfd_boolean +static bool is_plt_seq_reloc (enum elf_ppc_reloc_type r_type) { return (r_type == R_PPC_PLT16_HA @@ -2856,6 +2856,15 @@ is_plt_seq_reloc (enum elf_ppc_reloc_type r_type) || r_type == R_PPC_PLTSEQ); } +/* Like bfd_reloc_offset_in_range but without a howto. Return true + iff a field of SIZE bytes at OFFSET is within SEC limits. */ + +static bool +offset_in_range (asection *sec, bfd_vma offset, size_t size) +{ + return offset <= sec->size && size <= sec->size - offset; +} + static void bad_shared_reloc (bfd *abfd, enum elf_ppc_reloc_type r_type) { @@ -2871,7 +2880,7 @@ bad_shared_reloc (bfd *abfd, enum elf_ppc_reloc_type r_type) allocate space in the global offset table or procedure linkage table. */ -static bfd_boolean +static bool ppc_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, asection *sec, @@ -2886,16 +2895,7 @@ ppc_elf_check_relocs (bfd *abfd, struct elf_link_hash_entry *tga; if (bfd_link_relocatable (info)) - 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; + return true; #ifdef DEBUG _bfd_error_handler ("ppc_elf_check_relocs called for section %pA in %pB", @@ -2914,10 +2914,10 @@ ppc_elf_check_relocs (bfd *abfd, if (htab->elf.dynobj == NULL) htab->elf.dynobj = abfd; if (!ppc_elf_create_glink (htab->elf.dynobj, info)) - return FALSE; + return false; } tga = elf_link_hash_lookup (&htab->elf, "__tls_get_addr", - FALSE, FALSE, TRUE); + false, false, true); symtab_hdr = &elf_symtab_hdr (abfd); sym_hashes = elf_sym_hashes (abfd); got2 = bfd_get_section_by_name (abfd, ".got2"); @@ -2929,6 +2929,7 @@ ppc_elf_check_relocs (bfd *abfd, unsigned long r_symndx; enum elf_ppc_reloc_type r_type; struct elf_link_hash_entry *h; + Elf_Internal_Sym *isym; int tls_type; struct plt_entry **ifunc; struct plt_entry **pltent; @@ -2936,13 +2937,19 @@ ppc_elf_check_relocs (bfd *abfd, r_symndx = ELF32_R_SYM (rel->r_info); if (r_symndx < symtab_hdr->sh_info) - h = NULL; + { + h = NULL; + isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache, abfd, r_symndx); + if (isym == NULL) + return false; + } 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; + isym = NULL; } /* If a relocation refers to _GLOBAL_OFFSET_TABLE_, create the .got. @@ -2955,27 +2962,30 @@ ppc_elf_check_relocs (bfd *abfd, if (htab->elf.dynobj == NULL) htab->elf.dynobj = abfd; if (!ppc_elf_create_got (htab->elf.dynobj, info)) - return FALSE; + return false; BFD_ASSERT (h == htab->elf.hgot); } tls_type = 0; r_type = ELF32_R_TYPE (rel->r_info); ifunc = NULL; - if (h == NULL && !htab->is_vxworks) + if (h != NULL) + { + if (h->type == STT_GNU_IFUNC) + { + h->needs_plt = 1; + ifunc = &h->plt.plist; + } + } + else if (htab->elf.target_os != 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) { /* Set PLT_IFUNC flag for this sym, no GOT entry yet. */ ifunc = update_local_sym_info (abfd, symtab_hdr, r_symndx, NON_GOT | PLT_IFUNC); if (ifunc == NULL) - return FALSE; + return false; /* STT_GNU_IFUNC symbols must have a PLT entry; In a non-pie executable even when there are @@ -2996,12 +3006,12 @@ ppc_elf_check_relocs (bfd *abfd, || r_type == R_PPC_PLT16_HA)) addend = rel->r_addend; if (!update_plt_info (abfd, ifunc, got2, addend)) - return FALSE; + return false; } } } - if (!htab->is_vxworks + if (htab->elf.target_os != is_vxworks && is_branch_reloc (r_type) && h != NULL && h == tga) @@ -3028,7 +3038,7 @@ ppc_elf_check_relocs (bfd *abfd, else if (!update_local_sym_info (abfd, symtab_hdr, r_symndx, NON_GOT | TLS_TLS | TLS_MARK)) - return FALSE; + return false; break; case R_PPC_PLTSEQ: @@ -3077,7 +3087,7 @@ ppc_elf_check_relocs (bfd *abfd, if (htab->elf.dynobj == NULL) htab->elf.dynobj = abfd; if (!ppc_elf_create_got (htab->elf.dynobj, info)) - return FALSE; + return false; } if (h != NULL) { @@ -3087,14 +3097,14 @@ ppc_elf_check_relocs (bfd *abfd, 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; + return false; /* We may also need a plt entry if the symbol turns out to be an ifunc. */ if (h != NULL && !bfd_link_pic (info)) { if (!update_plt_info (abfd, &h->plt.plist, NULL, 0)) - return FALSE; + return false; } break; @@ -3103,11 +3113,11 @@ ppc_elf_check_relocs (bfd *abfd, htab->sdata[0].sym->ref_regular = 1; if (!elf_allocate_pointer_linker_section (abfd, &htab->sdata[0], h, rel)) - return FALSE; + return false; if (h != NULL) { - ppc_elf_hash_entry (h)->has_sda_refs = TRUE; - h->non_got_ref = TRUE; + ppc_elf_hash_entry (h)->has_sda_refs = true; + h->non_got_ref = true; } break; @@ -3116,16 +3126,16 @@ ppc_elf_check_relocs (bfd *abfd, if (!bfd_link_executable (info)) { bad_shared_reloc (abfd, r_type); - return FALSE; + return false; } htab->sdata[1].sym->ref_regular = 1; if (!elf_allocate_pointer_linker_section (abfd, &htab->sdata[1], h, rel)) - return FALSE; + return false; if (h != NULL) { - ppc_elf_hash_entry (h)->has_sda_refs = TRUE; - h->non_got_ref = TRUE; + ppc_elf_hash_entry (h)->has_sda_refs = true; + h->non_got_ref = true; } break; @@ -3141,8 +3151,8 @@ ppc_elf_check_relocs (bfd *abfd, case R_PPC_VLE_SDAREL_HA16D: if (h != NULL) { - ppc_elf_hash_entry (h)->has_sda_refs = TRUE; - h->non_got_ref = TRUE; + ppc_elf_hash_entry (h)->has_sda_refs = true; + h->non_got_ref = true; } break; @@ -3162,13 +3172,13 @@ ppc_elf_check_relocs (bfd *abfd, if (!bfd_link_executable (info)) { bad_shared_reloc (abfd, r_type); - return FALSE; + return false; } htab->sdata[1].sym->ref_regular = 1; if (h != NULL) { - ppc_elf_hash_entry (h)->has_sda_refs = TRUE; - h->non_got_ref = TRUE; + ppc_elf_hash_entry (h)->has_sda_refs = true; + h->non_got_ref = true; } break; @@ -3178,8 +3188,8 @@ ppc_elf_check_relocs (bfd *abfd, case R_PPC_EMB_RELSDA: if (h != NULL) { - ppc_elf_hash_entry (h)->has_sda_refs = TRUE; - h->non_got_ref = TRUE; + ppc_elf_hash_entry (h)->has_sda_refs = true; + h->non_got_ref = true; } break; @@ -3189,7 +3199,7 @@ ppc_elf_check_relocs (bfd *abfd, case R_PPC_EMB_NADDR16_HI: case R_PPC_EMB_NADDR16_HA: if (h != NULL) - h->non_got_ref = TRUE; + h->non_got_ref = true; break; case R_PPC_PLTREL24: @@ -3217,7 +3227,7 @@ ppc_elf_check_relocs (bfd *abfd, pltent = update_local_sym_info (abfd, symtab_hdr, r_symndx, NON_GOT | PLT_KEEP); if (pltent == NULL) - return FALSE; + return false; } else { @@ -3234,7 +3244,7 @@ ppc_elf_check_relocs (bfd *abfd, || r_type == R_PPC_PLT16_HA)) addend = rel->r_addend; if (!update_plt_info (abfd, pltent, got2, addend)) - return FALSE; + return false; break; /* The following relocations don't need to propagate the @@ -3294,34 +3304,34 @@ ppc_elf_check_relocs (bfd *abfd, htab->plt_type = PLT_OLD; htab->old_bfd = abfd; } - if (h != NULL && h->type == STT_GNU_IFUNC) - { - h->needs_plt = 1; - if (!update_plt_info (abfd, &h->plt.plist, NULL, 0)) - return FALSE; - } + if (h != NULL + && ifunc != NULL + && !update_plt_info (abfd, ifunc, NULL, 0)) + return false; 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; + return false; break; /* This relocation describes which C++ vtable entries are actually used. Record for later use during GC. */ case R_PPC_GNU_VTENTRY: if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend)) - return FALSE; + return false; break; + case R_PPC_TPREL16_HI: + case R_PPC_TPREL16_HA: + sec->has_tls_reloc = 1; + /* Fall through. */ /* We shouldn't really be seeing TPREL32. */ case R_PPC_TPREL32: case R_PPC_TPREL16: case R_PPC_TPREL16_LO: - case R_PPC_TPREL16_HI: - case R_PPC_TPREL16_HA: if (bfd_link_dll (info)) info->flags |= DF_STATIC_TLS; goto dodyn; @@ -3345,12 +3355,6 @@ ppc_elf_check_relocs (bfd *abfd, 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) @@ -3375,7 +3379,7 @@ ppc_elf_check_relocs (bfd *abfd, /* 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; + return false; /* We may need a copy reloc too. */ h->non_got_ref = 1; @@ -3414,43 +3418,26 @@ ppc_elf_check_relocs (bfd *abfd, a function defined in a dynamic object. */ h->needs_plt = 1; if (!update_plt_info (abfd, &h->plt.plist, NULL, 0)) - return FALSE; + 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 ((bfd_link_pic (info) - && (must_be_dyn_reloc (info, r_type) - || (h != NULL - && (!SYMBOLIC_BIND (info, h) - || h->root.type == bfd_link_hash_defweak - || !h->def_regular)))) - || (ELIMINATE_COPY_RELOCS - && !bfd_link_pic (info) - && h != NULL - && (h->root.type == bfd_link_hash_defweak - || !h->def_regular))) + /* Set up information for symbols that might need dynamic + relocations. At this point in linking we have read all + the input files and resolved most symbols, but have not + yet decided whether symbols are dynamic or finalized + symbol flags. In some cases we might be setting dynamic + reloc info for symbols that do not end up needing such. + That's OK, adjust_dynamic_symbol and allocate_dynrelocs + work together with this code. */ + if ((h != NULL + && !SYMBOL_REFERENCES_LOCAL (info, h)) + || (bfd_link_pic (info) + && (h != NULL + ? !bfd_is_abs_symbol (&h->root) + : isym->st_shndx != SHN_ABS) + && must_be_dyn_reloc (info, r_type))) { #ifdef DEBUG fprintf (stderr, @@ -3465,10 +3452,10 @@ ppc_elf_check_relocs (bfd *abfd, htab->elf.dynobj = abfd; sreloc = _bfd_elf_make_dynamic_reloc_section - (sec, htab->elf.dynobj, 2, abfd, /*rela?*/ TRUE); + (sec, htab->elf.dynobj, 2, abfd, /*rela?*/ true); if (sreloc == NULL) - return FALSE; + return false; } /* If this is a global symbol, we count the number of @@ -3484,7 +3471,7 @@ ppc_elf_check_relocs (bfd *abfd, { p = bfd_alloc (htab->elf.dynobj, sizeof *p); if (p == NULL) - return FALSE; + return false; p->next = *rel_head; *rel_head = p; p->sec = sec; @@ -3502,15 +3489,9 @@ ppc_elf_check_relocs (bfd *abfd, easily. Oh well. */ struct ppc_dyn_relocs *p; struct ppc_dyn_relocs **rel_head; - bfd_boolean is_ifunc; + bool is_ifunc; 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) @@ -3518,7 +3499,7 @@ ppc_elf_check_relocs (bfd *abfd, vpp = &elf_section_data (s)->local_dynrel; rel_head = (struct ppc_dyn_relocs **) vpp; - is_ifunc = ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC; + is_ifunc = ifunc != NULL; p = *rel_head; if (p != NULL && p->sec == sec && p->ifunc != is_ifunc) p = p->next; @@ -3526,7 +3507,7 @@ ppc_elf_check_relocs (bfd *abfd, { p = bfd_alloc (htab->elf.dynobj, sizeof *p); if (p == NULL) - return FALSE; + return false; p->next = *rel_head; *rel_head = p; p->sec = sec; @@ -3541,19 +3522,19 @@ ppc_elf_check_relocs (bfd *abfd, } } - return TRUE; + return true; } /* Warn for conflicting Tag_GNU_Power_ABI_FP attributes between IBFD and OBFD, and merge non-conflicting ones. */ -bfd_boolean +bool _bfd_elf_ppc_merge_fp_attributes (bfd *ibfd, struct bfd_link_info *info) { bfd *obfd = info->output_bfd; obj_attribute *in_attr, *in_attrs; obj_attribute *out_attr, *out_attrs; - bfd_boolean ret = TRUE; - bfd_boolean warn_only; + bool ret = true; + bool warn_only; /* We only warn about shared library mismatches, because common libraries advertise support for a particular long double variant @@ -3678,16 +3659,16 @@ _bfd_elf_ppc_merge_fp_attributes (bfd *ibfd, struct bfd_link_info *info) /* Merge object attributes from IBFD into OBFD. Warn if there are conflicting attributes. */ -static bfd_boolean +static bool ppc_elf_merge_obj_attributes (bfd *ibfd, struct bfd_link_info *info) { bfd *obfd; obj_attribute *in_attr, *in_attrs; obj_attribute *out_attr, *out_attrs; - bfd_boolean ret; + bool ret; if (!_bfd_elf_ppc_merge_fp_attributes (ibfd, info)) - return FALSE; + return false; obfd = info->output_bfd; in_attrs = elf_known_obj_attributes (ibfd)[OBJ_ATTR_GNU]; @@ -3697,7 +3678,7 @@ ppc_elf_merge_obj_attributes (bfd *ibfd, struct bfd_link_info *info) merge non-conflicting ones. */ in_attr = &in_attrs[Tag_GNU_Power_ABI_Vector]; out_attr = &out_attrs[Tag_GNU_Power_ABI_Vector]; - ret = TRUE; + ret = true; if (in_attr->i != out_attr->i) { int in_vec = in_attr->i & 3; @@ -3732,7 +3713,7 @@ ppc_elf_merge_obj_attributes (bfd *ibfd, struct bfd_link_info *info) (_("%pB uses AltiVec vector ABI, %pB uses SPE vector ABI"), last_vec, ibfd); out_attr->type = ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_ERROR; - ret = FALSE; + ret = false; } else if (out_vec > in_vec) { @@ -3741,7 +3722,7 @@ ppc_elf_merge_obj_attributes (bfd *ibfd, struct bfd_link_info *info) (_("%pB uses AltiVec vector ABI, %pB uses SPE vector ABI"), ibfd, last_vec); out_attr->type = ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_ERROR; - ret = FALSE; + ret = false; } } @@ -3770,7 +3751,7 @@ ppc_elf_merge_obj_attributes (bfd *ibfd, struct bfd_link_info *info) (_("%pB uses r3/r4 for small structure returns, " "%pB uses memory"), last_struct, ibfd); out_attr->type = ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_ERROR; - ret = FALSE; + ret = false; } else if (out_struct > in_struct) { @@ -3779,13 +3760,13 @@ ppc_elf_merge_obj_attributes (bfd *ibfd, struct bfd_link_info *info) (_("%pB uses r3/r4 for small structure returns, " "%pB uses memory"), ibfd, last_struct); out_attr->type = ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_ERROR; - ret = FALSE; + ret = false; } } if (!ret) { bfd_set_error (bfd_error_bad_value); - return FALSE; + return false; } /* Merge Tag_compatibility attributes and any common GNU ones. */ @@ -3795,33 +3776,33 @@ ppc_elf_merge_obj_attributes (bfd *ibfd, struct bfd_link_info *info) /* Merge backend specific data from an object file to the output object file when linking. */ -static bfd_boolean +static bool ppc_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) { bfd *obfd = info->output_bfd; flagword old_flags; flagword new_flags; - bfd_boolean error; + bool error; if (!is_ppc_elf (ibfd) || !is_ppc_elf (obfd)) - return TRUE; + return true; /* Check if we have the same endianness. */ if (! _bfd_generic_verify_endian_match (ibfd, info)) - return FALSE; + return false; if (!ppc_elf_merge_obj_attributes (ibfd, info)) - return FALSE; + return false; if ((ibfd->flags & DYNAMIC) != 0) - return TRUE; + return true; 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_flags_init (obfd) = true; elf_elfheader (obfd)->e_flags = new_flags; } @@ -3834,11 +3815,11 @@ ppc_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) { /* Warn about -mrelocatable mismatch. Allow -mrelocatable-lib to be linked with either. */ - error = FALSE; + error = false; if ((new_flags & EF_PPC_RELOCATABLE) != 0 && (old_flags & (EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB)) == 0) { - error = TRUE; + error = true; _bfd_error_handler (_("%pB: compiled with -mrelocatable and linked with " "modules compiled normally"), ibfd); @@ -3846,7 +3827,7 @@ ppc_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) else if ((new_flags & (EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB)) == 0 && (old_flags & EF_PPC_RELOCATABLE) != 0) { - error = TRUE; + error = true; _bfd_error_handler (_("%pB: compiled normally and linked with " "modules compiled with -mrelocatable"), ibfd); @@ -3873,7 +3854,7 @@ ppc_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) /* Warn about any other mismatches. */ if (new_flags != old_flags) { - error = TRUE; + error = true; _bfd_error_handler /* xgettext:c-format */ (_("%pB: uses different e_flags (%#x) fields " @@ -3884,24 +3865,26 @@ ppc_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) if (error) { bfd_set_error (bfd_error_bad_value); - return FALSE; + return false; } } - return TRUE; + return true; } -static void +static bfd_reloc_status_type ppc_elf_vle_split16 (bfd *input_bfd, asection *input_section, unsigned long offset, bfd_byte *loc, bfd_vma value, split16_format_type split16_format, - bfd_boolean fixup) + bool fixup) { unsigned int insn, opcode; + if (!offset_in_range (input_section, offset, 4)) + return bfd_reloc_outofrange; insn = bfd_get_32 (input_bfd, loc); opcode = insn & E_OPCODE_MASK; if (opcode == E_OR2I_INSN @@ -3958,6 +3941,7 @@ ppc_elf_vle_split16 (bfd *input_bfd, } insn |= value & 0x7ff; bfd_put_32 (input_bfd, insn, loc); + return bfd_reloc_ok; } static void @@ -3997,7 +3981,7 @@ ppc_elf_select_plt_layout (bfd *output_bfd ATTRIBUTE_UNUSED, else if (bfd_link_pic (info) && htab->elf.dynamic_sections_created && (h = elf_link_hash_lookup (&htab->elf, "_mcount", - FALSE, FALSE, TRUE)) != NULL + false, false, true)) != NULL && (h->type == STT_FUNC || h->needs_plt) && h->ref_regular @@ -4092,7 +4076,7 @@ ppc_elf_gc_mark_hook (asection *sec, return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym); } -static bfd_boolean +static bool get_sym_h (struct elf_link_hash_entry **hp, Elf_Internal_Sym **symp, asection **symsecp, @@ -4144,7 +4128,7 @@ get_sym_h (struct elf_link_hash_entry **hp, symtab_hdr->sh_info, 0, NULL, NULL, NULL); if (locsyms == NULL) - return FALSE; + return false; *locsymsp = locsyms; } sym = locsyms + r_symndx; @@ -4176,13 +4160,13 @@ get_sym_h (struct elf_link_hash_entry **hp, *tls_maskp = tls_mask; } } - return TRUE; + return true; } /* Analyze inline PLT call relocations to see whether calls to locally defined functions can be converted to direct calls. */ -bfd_boolean +bool ppc_elf_inline_plt (struct bfd_link_info *info) { struct ppc_elf_link_hash_table *htab; @@ -4192,7 +4176,7 @@ ppc_elf_inline_plt (struct bfd_link_info *info) htab = ppc_elf_hash_table (info); if (htab == NULL) - return FALSE; + return false; /* A bl insn can reach -0x2000000 to 0x1fffffc. The limit is reduced somewhat to cater for possible stubs that might be added @@ -4215,7 +4199,7 @@ ppc_elf_inline_plt (struct bfd_link_info *info) if (high_vma - low_vma < limit) { htab->can_convert_all_inline_plt = 1; - return TRUE; + return true; } /* Otherwise, go looking through relocs for cases where a direct @@ -4252,10 +4236,10 @@ ppc_elf_inline_plt (struct bfd_link_info *info) relstart = _bfd_elf_link_read_relocs (ibfd, sec, NULL, NULL, info->keep_memory); if (relstart == NULL) - return FALSE; + return false; relend = relstart + sec->reloc_count; - for (rel = relstart; rel < relend; ) + for (rel = relstart; rel < relend; rel++) { enum elf_ppc_reloc_type r_type; unsigned long r_symndx; @@ -4276,7 +4260,7 @@ ppc_elf_inline_plt (struct bfd_link_info *info) free (relstart); if (symtab_hdr->contents != (unsigned char *) local_syms) free (local_syms); - return FALSE; + return false; } if (sym_sec != NULL && sym_sec->output_section != NULL) @@ -4310,7 +4294,7 @@ ppc_elf_inline_plt (struct bfd_link_info *info) } } - return TRUE; + return true; } /* Set plt output section type, htab->tls_get_addr, and call the @@ -4323,15 +4307,15 @@ ppc_elf_tls_setup (bfd *obfd, struct bfd_link_info *info) htab = ppc_elf_hash_table (info); htab->tls_get_addr = elf_link_hash_lookup (&htab->elf, "__tls_get_addr", - FALSE, FALSE, TRUE); + false, false, true); if (htab->plt_type != PLT_NEW) - htab->params->no_tls_get_addr_opt = TRUE; + htab->params->no_tls_get_addr_opt = true; if (!htab->params->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); + false, false, true); if (opt != NULL && (opt->root.type == bfd_link_hash_defined || opt->root.type == bfd_link_hash_defweak)) @@ -4365,14 +4349,14 @@ ppc_elf_tls_setup (bfd *obfd, struct bfd_link_info *info) _bfd_elf_strtab_delref (elf_hash_table (info)->dynstr, opt->dynstr_index); if (!bfd_elf_link_record_dynamic_symbol (info, opt)) - return FALSE; + return false; } htab->tls_get_addr = opt; } } } else - htab->params->no_tls_get_addr_opt = TRUE; + htab->params->no_tls_get_addr_opt = true; } if (htab->plt_type == PLT_NEW && htab->elf.splt != NULL @@ -4388,7 +4372,7 @@ ppc_elf_tls_setup (bfd *obfd, struct bfd_link_info *info) /* Return TRUE iff REL is a branch reloc with a global symbol matching HASH. */ -static bfd_boolean +static bool branch_reloc_hash_match (const bfd *ibfd, const Elf_Internal_Rela *rel, const struct elf_link_hash_entry *hash) @@ -4407,15 +4391,15 @@ branch_reloc_hash_match (const bfd *ibfd, || h->root.type == bfd_link_hash_warning) h = (struct elf_link_hash_entry *) h->root.u.i.link; if (h == hash) - return TRUE; + return true; } - return FALSE; + return false; } /* Run through all the TLS relocs looking for optimization opportunities. */ -bfd_boolean +bool ppc_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, struct bfd_link_info *info) { @@ -4425,11 +4409,13 @@ ppc_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, int pass; if (!bfd_link_executable (info)) - return TRUE; + return true; htab = ppc_elf_hash_table (info); if (htab == NULL) - return FALSE; + return false; + + htab->do_tls_opt = 1; /* Make two passes through the relocs. First time check that tls relocs involved in setting up a tls_get_addr call are indeed @@ -4453,7 +4439,7 @@ ppc_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, relstart = _bfd_elf_link_read_relocs (ibfd, sec, NULL, NULL, info->keep_memory); if (relstart == NULL) - return FALSE; + return false; relend = relstart + sec->reloc_count; for (rel = relstart; rel < relend; rel++) @@ -4463,7 +4449,7 @@ ppc_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, struct elf_link_hash_entry *h = NULL; unsigned char *tls_mask; unsigned char tls_set, tls_clear; - bfd_boolean is_local; + bool is_local; bfd_signed_vma *got_count; r_symndx = ELF32_R_SYM (rel->r_info); @@ -4498,7 +4484,7 @@ ppc_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, ibfd, sec, rel->r_offset); if (elf_section_data (sec)->relocs != relstart) free (relstart); - return TRUE; + return true; } expecting_tls_get_addr = 0; @@ -4596,6 +4582,37 @@ ppc_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, tls_clear = 0; break; + case R_PPC_TPREL16_HA: + if (pass == 0) + { + unsigned char buf[4]; + unsigned int insn; + bfd_vma off = rel->r_offset & ~3; + if (!bfd_get_section_contents (ibfd, sec, buf, + off, 4)) + { + if (elf_section_data (sec)->relocs != relstart) + free (relstart); + return false; + } + insn = bfd_get_32 (ibfd, buf); + /* addis rt,2,imm */ + if ((insn & ((0x3fu << 26) | 0x1f << 16)) + != ((15u << 26) | (2 << 16))) + { + /* xgettext:c-format */ + info->callbacks->minfo + (_("%H: warning: %s unexpected insn %#x.\n"), + ibfd, sec, off, "R_PPC_TPREL16_HA", insn); + htab->do_tls_opt = 0; + } + } + continue; + + case R_PPC_TPREL16_HI: + htab->do_tls_opt = 0; + continue; + default: continue; } @@ -4620,7 +4637,7 @@ ppc_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, ibfd, sec, rel->r_offset); if (elf_section_data (sec)->relocs != relstart) free (relstart); - return TRUE; + return true; } if (h != NULL) @@ -4690,39 +4707,38 @@ ppc_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, free (relstart); } } - htab->do_tls_opt = 1; - return TRUE; + return true; } /* Return true if we have dynamic relocs against H or any of its weak aliases, that apply to read-only sections. Cannot be used after size_dynamic_sections. */ -static bfd_boolean +static bool alias_readonly_dynrelocs (struct elf_link_hash_entry *h) { struct ppc_elf_link_hash_entry *eh = ppc_elf_hash_entry (h); do { if (_bfd_elf_readonly_dynrelocs (&eh->elf)) - return TRUE; + return true; eh = ppc_elf_hash_entry (eh->elf.u.alias); } while (eh != NULL && &eh->elf != h); - return FALSE; + return false; } /* Return whether H has pc-relative dynamic relocs. */ -static bfd_boolean +static bool pc_dynrelocs (struct elf_link_hash_entry *h) { struct elf_dyn_relocs *p; for (p = h->dyn_relocs; p != NULL; p = p->next) if (p->pc_count != 0) - return TRUE; - return FALSE; + return true; + return false; } /* Adjust a symbol defined by a dynamic object and referenced by a @@ -4731,7 +4747,7 @@ pc_dynrelocs (struct elf_link_hash_entry *h) change the definition to something the rest of the link can understand. */ -static bfd_boolean +static bool ppc_elf_adjust_dynamic_symbol (struct bfd_link_info *info, struct elf_link_hash_entry *h) { @@ -4758,7 +4774,7 @@ ppc_elf_adjust_dynamic_symbol (struct bfd_link_info *info, || h->type == STT_GNU_IFUNC || h->needs_plt) { - bfd_boolean local = (SYMBOL_CALLS_LOCAL (info, h) + bool local = (SYMBOL_CALLS_LOCAL (info, h) || UNDEFWEAK_NO_DYNAMIC_RELOC (info, h)); /* Discard dyn_relocs when non-pic if we've decided that a function symbol is local. */ @@ -4807,7 +4823,7 @@ ppc_elf_adjust_dynamic_symbol (struct bfd_link_info *info, || (h->non_got_ref && !h->ref_regular_nonweak && !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))) - && !htab->is_vxworks + && htab->elf.target_os != is_vxworks && !ppc_elf_hash_entry (h)->has_sda_refs && !_bfd_elf_readonly_dynrelocs (h)) { @@ -4824,7 +4840,7 @@ ppc_elf_adjust_dynamic_symbol (struct bfd_link_info *info, } h->protected_def = 0; /* Function symbols can't have copy relocs. */ - return TRUE; + return true; } else h->plt.plist = NULL; @@ -4842,7 +4858,7 @@ ppc_elf_adjust_dynamic_symbol (struct bfd_link_info *info, || def->root.u.def.section == htab->elf.sdynrelro || def->root.u.def.section == htab->dynsbss) h->dyn_relocs = NULL; - return TRUE; + return true; } /* This is a reference to a symbol defined by a dynamic object which @@ -4855,7 +4871,7 @@ ppc_elf_adjust_dynamic_symbol (struct bfd_link_info *info, if (bfd_link_pic (info)) { h->protected_def = 0; - return TRUE; + return true; } /* If there are no references to this symbol that do not use the @@ -4863,7 +4879,7 @@ ppc_elf_adjust_dynamic_symbol (struct bfd_link_info *info, if (!h->non_got_ref) { h->protected_def = 0; - return TRUE; + return true; } /* Protected variables do not work with .dynbss. The copy in @@ -4878,12 +4894,12 @@ ppc_elf_adjust_dynamic_symbol (struct bfd_link_info *info, && htab->params->pic_fixup == 0 && info->disable_target_specific_optimizations <= 1) htab->params->pic_fixup = 1; - return TRUE; + return true; } /* If -z nocopyreloc was given, we won't generate them either. */ if (info->nocopyreloc) - return TRUE; + return true; /* If we don't find any dynamic relocs in read-only sections, then we'll be keeping the dynamic relocs and avoiding the copy reloc. @@ -4893,10 +4909,10 @@ ppc_elf_adjust_dynamic_symbol (struct bfd_link_info *info, executable. */ if (ELIMINATE_COPY_RELOCS && !ppc_elf_hash_entry (h)->has_sda_refs - && !htab->is_vxworks + && htab->elf.target_os != is_vxworks && !h->def_regular && !alias_readonly_dynrelocs (h)) - return TRUE; + 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 @@ -4947,7 +4963,7 @@ ppc_elf_adjust_dynamic_symbol (struct bfd_link_info *info, is xxxxxxxx.plt_pic32., and for -fPIC xxxxxxxx.got2.plt_pic32.. */ -static bfd_boolean +static bool add_stub_sym (struct plt_entry *ent, struct elf_link_hash_entry *h, struct bfd_link_info *info) @@ -4970,15 +4986,15 @@ add_stub_sym (struct plt_entry *ent, len3 = strlen (ent->sec->name); name = bfd_malloc (len1 + len2 + len3 + 9); if (name == NULL) - return FALSE; + 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); + sh = elf_link_hash_lookup (&htab->elf, name, true, false, false); if (sh == NULL) - return FALSE; + return false; if (sh->root.type == bfd_link_hash_new) { sh->root.type = bfd_link_hash_defined; @@ -4991,7 +5007,7 @@ add_stub_sym (struct plt_entry *ent, sh->non_elf = 0; sh->root.linker_def = 1; } - return TRUE; + return true; } /* Allocate NEED contiguous space in .got, and return the offset. @@ -5055,7 +5071,7 @@ got_entries_needed (int tls_mask) /* If H is undefined, make it dynamic if that makes sense. */ -static bfd_boolean +static bool ensure_undef_dynamic (struct bfd_link_info *info, struct elf_link_hash_entry *h) { @@ -5069,22 +5085,33 @@ ensure_undef_dynamic (struct bfd_link_info *info, && !h->forced_local && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT) return bfd_elf_link_record_dynamic_symbol (info, h); - return TRUE; + return true; +} + +/* Choose whether to use htab->iplt or htab->pltlocal rather than the + usual htab->elf.splt section for a PLT entry. */ + +static inline +bool use_local_plt (struct bfd_link_info *info, + struct elf_link_hash_entry *h) +{ + return (h == NULL + || h->dynindx == -1 + || !elf_hash_table (info)->dynamic_sections_created); } /* Allocate space in associated reloc sections for dynamic relocs. */ -static bfd_boolean +static bool 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; - bfd_boolean dyn; if (h->root.type == bfd_link_hash_indirect) - return TRUE; + return true; htab = ppc_elf_hash_table (info); eh = (struct ppc_elf_link_hash_entry *) h; @@ -5100,7 +5127,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) /* Make sure this symbol is output as a dynamic symbol. */ if (!ensure_undef_dynamic (info, &eh->elf)) - return FALSE; + return false; need = 0; if ((eh->tls_mask & (TLS_TLS | TLS_LD)) == (TLS_TLS | TLS_LD)) @@ -5122,7 +5149,8 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) if (((bfd_link_pic (info) && !((eh->tls_mask & TLS_TLS) != 0 && bfd_link_executable (info) - && SYMBOL_REFERENCES_LOCAL (info, &eh->elf))) + && SYMBOL_REFERENCES_LOCAL (info, &eh->elf)) + && !bfd_is_abs_symbol (&h->root)) || (htab->elf.dynamic_sections_created && eh->elf.dynindx != -1 && !SYMBOL_REFERENCES_LOCAL (info, &eh->elf))) @@ -5190,7 +5218,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) } } - if (htab->is_vxworks) + if (htab->elf.target_os == is_vxworks) { struct elf_dyn_relocs **pp; @@ -5207,7 +5235,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) { /* Make sure this symbol is output as a dynamic symbol. */ if (!ensure_undef_dynamic (info, h)) - return FALSE; + return false; } } else if (ELIMINATE_COPY_RELOCS) @@ -5215,7 +5243,11 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) /* For the non-pic case, discard space for relocs against symbols which turn out to need copy relocs or are not dynamic. */ - if (h->dynamic_adjusted + if ((h->dynamic_adjusted + || (h->ref_regular + && h->root.type == bfd_link_hash_undefweak + && (info->dynamic_undefined_weak > 0 + || !_bfd_elf_readonly_dynrelocs (h)))) && !h->def_regular && !ELF_COMMON_DEF_P (h) && !(h->protected_def @@ -5225,7 +5257,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) { /* Make sure this symbol is output as a dynamic symbol. */ if (!ensure_undef_dynamic (info, h)) - return FALSE; + return false; if (h->dynindx == -1) h->dyn_relocs = NULL; @@ -5249,8 +5281,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) b) is an ifunc, or c) has plt16 relocs and has been processed by adjust_dynamic_symbol, or d) has plt16 relocs and we are linking statically. */ - dyn = htab->elf.dynamic_sections_created && h->dynindx != -1; - if (dyn + if ((htab->elf.dynamic_sections_created && h->dynindx != -1) || h->type == STT_GNU_IFUNC || (h->needs_plt && h->dynamic_adjusted) || (h->needs_plt @@ -5261,14 +5292,20 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) & (TLS_TLS | PLT_KEEP)) == PLT_KEEP)) { struct plt_entry *ent; - bfd_boolean doneone = FALSE; + bool doneone = false; bfd_vma plt_offset = 0, glink_offset = (bfd_vma) -1; for (ent = h->plt.plist; ent != NULL; ent = ent->next) if (ent->plt.refcount > 0) { - asection *s = htab->elf.splt; + asection *s; + bool dyn; + + if (!ensure_undef_dynamic (info, h)) + return false; + dyn = !use_local_plt (info, h); + s = htab->elf.splt; if (!dyn) { if (h->type == STT_GNU_IFUNC) @@ -5308,7 +5345,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) if (htab->params->emit_stub_syms && !add_stub_sym (ent, h, info)) - return FALSE; + return false; } } else @@ -5402,7 +5439,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) htab->elf.sgotplt->size += 4; } } - doneone = TRUE; + doneone = true; } } else @@ -5420,34 +5457,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) h->needs_plt = 0; } - 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_p) -{ - asection *sec; - - if (h->root.type == bfd_link_hash_indirect) - return TRUE; - - sec = _bfd_elf_readonly_dynrelocs (h); - if (sec != NULL) - { - struct bfd_link_info *info = (struct bfd_link_info *) info_p; - - info->flags |= DF_TEXTREL; - info->callbacks->minfo - (_("%pB: dynamic relocation against `%pT' in read-only section `%pA'\n"), - sec->owner, h->root.root.string, sec); - - /* Not an error, just cut short the traversal. */ - return FALSE; - } - return TRUE; + return true; } static const unsigned char glink_eh_frame_cie[] = @@ -5466,13 +5476,13 @@ static const unsigned char glink_eh_frame_cie[] = /* Set the sizes of the dynamic sections. */ -static bfd_boolean +static bool ppc_elf_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) { struct ppc_elf_link_hash_table *htab; asection *s; - bfd_boolean relocs; + bool relocs; bfd *ibfd; #ifdef DEBUG @@ -5510,6 +5520,8 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd, char *lgot_masks; bfd_size_type locsymcount; Elf_Internal_Shdr *symtab_hdr; + Elf_Internal_Sym *local_syms; + Elf_Internal_Sym *isym; if (!is_ppc_elf (ibfd)) continue; @@ -5531,7 +5543,7 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd, linker script /DISCARD/, so we'll be discarding the relocs too. */ } - else if (htab->is_vxworks + else if (htab->elf.target_os == is_vxworks && strcmp (p->sec->output_section->name, ".tls_vars") == 0) { @@ -5566,8 +5578,18 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd, local_plt = (struct plt_entry **) end_local_got; end_local_plt = local_plt + locsymcount; lgot_masks = (char *) end_local_plt; + local_syms = (Elf_Internal_Sym *) symtab_hdr->contents; + if (local_syms == NULL && locsymcount != 0) + { + local_syms = bfd_elf_get_elf_syms (ibfd, symtab_hdr, locsymcount, + 0, NULL, NULL, NULL); + if (local_syms == NULL) + return false; + } - for (; local_got < end_local_got; ++local_got, ++lgot_masks) + for (isym = local_syms; + local_got < end_local_got; + ++local_got, ++lgot_masks, ++isym) if (*local_got > 0) { unsigned int need; @@ -5581,7 +5603,8 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd, *local_got = allocate_got (htab, need); if (bfd_link_pic (info) && !((*lgot_masks & TLS_TLS) != 0 - && bfd_link_executable (info))) + && bfd_link_executable (info)) + && isym->st_shndx != SHN_ABS) { asection *srel; @@ -5596,7 +5619,7 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd, else *local_got = (bfd_vma) -1; - if (htab->is_vxworks) + if (htab->elf.target_os == is_vxworks) continue; /* Allocate space for calls to local STT_GNU_IFUNC syms in .iplt. */ @@ -5604,7 +5627,7 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd, for (; local_plt < end_local_plt; ++local_plt, ++lgot_masks) { struct plt_entry *ent; - bfd_boolean doneone = FALSE; + bool doneone = false; bfd_vma plt_offset = 0, glink_offset = (bfd_vma) -1; for (ent = *local_plt; ent != NULL; ent = ent->next) @@ -5648,12 +5671,21 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd, s = htab->relpltlocal; s->size += sizeof (Elf32_External_Rela); } - doneone = TRUE; + doneone = true; } } else ent->plt.offset = (bfd_vma) -1; } + + if (local_syms != NULL + && symtab_hdr->contents != (unsigned char *) local_syms) + { + if (!info->keep_memory) + free (local_syms); + else + symtab_hdr->contents = (unsigned char *) local_syms; + } } /* Allocate space for global sym dynamic relocs. */ @@ -5721,9 +5753,9 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd, { struct elf_link_hash_entry *sh; sh = elf_link_hash_lookup (&htab->elf, "__glink", - TRUE, FALSE, FALSE); + true, false, false); if (sh == NULL) - return FALSE; + return false; if (sh->root.type == bfd_link_hash_new) { sh->root.type = bfd_link_hash_defined; @@ -5737,9 +5769,9 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd, sh->root.linker_def = 1; } sh = elf_link_hash_lookup (&htab->elf, "__glink_PLTresolve", - TRUE, FALSE, FALSE); + true, false, false); if (sh == NULL) - return FALSE; + return false; if (sh->root.type == bfd_link_hash_new) { sh->root.type = bfd_link_hash_defined; @@ -5773,10 +5805,10 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd, /* We've now determined the sizes of the various dynamic sections. Allocate memory for them. */ - relocs = FALSE; + relocs = false; for (s = htab->elf.dynobj->sections; s != NULL; s = s->next) { - bfd_boolean strip_section = TRUE; + bool strip_section = true; if ((s->flags & SEC_LINKER_CREATED) == 0) continue; @@ -5788,7 +5820,7 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd, 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_section = false; /* Strip this section if we don't need it; see the comment below. */ } @@ -5809,12 +5841,12 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd, { strip_section = (s->flags & SEC_KEEP) == 0; } - else if (CONST_STRNEQ (bfd_section_name (s), ".rela")) + else if (startswith (bfd_section_name (s), ".rela")) { if (s->size != 0) { /* Remember whether there are any relocation sections. */ - relocs = TRUE; + relocs = true; /* We use the reloc_count field as a counter if we need to copy relocs into the output file. */ @@ -5848,7 +5880,7 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd, /* Allocate memory for the section contents. */ s->contents = bfd_zalloc (htab->elf.dynobj, s->size); if (s->contents == NULL) - return FALSE; + return false; } if (htab->elf.dynamic_sections_created) @@ -5861,56 +5893,22 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd, #define add_dynamic_entry(TAG, VAL) \ _bfd_elf_add_dynamic_entry (info, TAG, VAL) - if (bfd_link_executable (info)) - { - if (!add_dynamic_entry (DT_DEBUG, 0)) - return FALSE; - } - - if (htab->elf.splt != NULL && htab->elf.splt->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 (!_bfd_elf_maybe_vxworks_add_dynamic_tags (output_bfd, info, + relocs)) + return false; if (htab->plt_type == PLT_NEW && htab->glink != NULL && htab->glink->size != 0) { if (!add_dynamic_entry (DT_PPC_GOT, 0)) - return FALSE; + return false; if (!htab->params->no_tls_get_addr_opt && htab->tls_get_addr != NULL && htab->tls_get_addr->plt.plist != NULL && !add_dynamic_entry (DT_PPC_OPT, PPC_OPT_TLS)) - 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; + return false; } - if (htab->is_vxworks - && !elf_vxworks_add_dynamic_entries (output_bfd, info)) - return FALSE; } #undef add_dynamic_entry @@ -5974,7 +5972,7 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd, == htab->glink_eh_frame->size); } - return TRUE; + return true; } /* Arrange to have _SDA_BASE_ or _SDA2_BASE_ stripped from the output @@ -6019,14 +6017,14 @@ ppc_elf_maybe_strip_sdata_syms (struct bfd_link_info *info) /* Return TRUE if symbol should be hashed in the `.gnu.hash' section. */ -static bfd_boolean +static bool 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 false; return _bfd_elf_hash_symbol (h); } @@ -6066,11 +6064,11 @@ struct ppc_elf_relax_info space for the workaround has its size extended so that we can add trampolines at the end of the section. */ -static bfd_boolean +static bool ppc_elf_relax_section (bfd *abfd, asection *isec, struct bfd_link_info *link_info, - bfd_boolean *again) + bool *again) { struct one_branch_fixup { @@ -6090,30 +6088,30 @@ ppc_elf_relax_section (bfd *abfd, struct one_branch_fixup *branch_fixups = NULL; struct ppc_elf_relax_info *relax_info = NULL; unsigned changes = 0; - bfd_boolean workaround_change; + bool workaround_change; struct ppc_elf_link_hash_table *htab; bfd_size_type trampbase, trampoff, newsize, picfixup_size; asection *got2; - bfd_boolean maybe_pasted; + bool maybe_pasted; - *again = FALSE; + *again = false; /* 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_LINKER_CREATED) != 0 || isec->size < 4) - return TRUE; + 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 (bfd_link_relocatable (link_info) && bfd_link_pic (link_info)) - return TRUE; + return true; htab = ppc_elf_hash_table (link_info); if (htab == NULL) - return TRUE; + return true; isec->size = (isec->size + 3) & -4; if (isec->rawsize == 0) @@ -6132,7 +6130,7 @@ ppc_elf_relax_section (bfd *abfd, elf_section_data (isec)->sec_info = bfd_zalloc (abfd, sizeof (struct ppc_elf_relax_info)); if (elf_section_data (isec)->sec_info == NULL) - return FALSE; + return false; } relax_info = elf_section_data (isec)->sec_info; trampbase -= relax_info->workaround_size; @@ -6550,7 +6548,7 @@ ppc_elf_relax_section (bfd *abfd, } } - workaround_change = FALSE; + workaround_change = false; newsize = trampoff; if (htab->params->ppc476_workaround && (!bfd_link_relocatable (link_info) @@ -6574,7 +6572,7 @@ ppc_elf_relax_section (bfd *abfd, if (relax_info->workaround_size < newsize) { relax_info->workaround_size = newsize; - workaround_change = TRUE; + workaround_change = true; } /* Ensure relocate_section is called. */ isec->flags |= SEC_RELOC; @@ -6648,7 +6646,7 @@ ppc_elf_relax_section (bfd *abfd, free (internal_relocs); *again = changes != 0 || workaround_change; - return TRUE; + return true; error_return: while (branch_fixups != NULL) @@ -6663,7 +6661,7 @@ ppc_elf_relax_section (bfd *abfd, free (contents); if (elf_section_data (isec)->relocs != internal_relocs) free (internal_relocs); - return FALSE; + return false; } /* What to do when ld finds relocations against symbols defined in @@ -6824,7 +6822,7 @@ write_glink_stub (struct elf_link_hash_entry *h, struct plt_entry *ent, /* Return true if symbol is defined statically. */ -static bfd_boolean +static bool is_static_defined (struct elf_link_hash_entry *h) { return ((h->root.type == bfd_link_hash_defined @@ -6918,7 +6916,7 @@ _bfd_elf_ppc_at_tprel_transform (unsigned int insn, unsigned int reg) return insn; } -static bfd_boolean +static bool is_insn_ds_form (unsigned int insn) { return ((insn & (0x3fu << 26)) == 58u << 26 /* ld,ldu,lwa */ @@ -6927,7 +6925,7 @@ is_insn_ds_form (unsigned int insn) || (insn & (0x3fu << 26)) == 61u << 26 /* stfdp */); } -static bfd_boolean +static bool is_insn_dq_form (unsigned int insn) { return ((insn & (0x3fu << 26)) == 56u << 26 /* lq */ @@ -6964,7 +6962,7 @@ is_insn_dq_form (unsigned int insn) section, which means that the addend must be adjusted accordingly. */ -static bfd_boolean +static int ppc_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, bfd *input_bfd, @@ -6983,9 +6981,9 @@ ppc_elf_relocate_section (bfd *output_bfd, Elf_Internal_Rela outrel; asection *got2; bfd_vma *local_got_offsets; - bfd_boolean ret = TRUE; + bool ret = true; bfd_vma d_offset = (bfd_big_endian (input_bfd) ? 2 : 0); - bfd_boolean is_vxworks_tls; + bool is_vxworks_tls; unsigned int picfixup_size = 0; struct ppc_elf_relax_info *relax_info = NULL; @@ -7000,7 +6998,7 @@ ppc_elf_relocate_section (bfd *output_bfd, if (!is_ppc_elf (input_bfd)) { bfd_set_error (bfd_error_wrong_format); - return FALSE; + return false; } got2 = bfd_get_section_by_name (input_bfd, ".got2"); @@ -7015,7 +7013,7 @@ ppc_elf_relocate_section (bfd *output_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 && bfd_link_pic (info) + is_vxworks_tls = (htab->elf.target_os == is_vxworks && bfd_link_pic (info) && !strcmp (input_section->output_section->name, ".tls_vars")); if (input_section->sec_info_type == SEC_INFO_TYPE_TARGET) @@ -7035,8 +7033,8 @@ ppc_elf_relocate_section (bfd *output_bfd, unsigned long r_symndx; bfd_vma relocation; bfd_vma branch_bit, from; - bfd_boolean unresolved_reloc, save_unresolved_reloc; - bfd_boolean warned; + bool unresolved_reloc, save_unresolved_reloc; + bool warned; unsigned int tls_type, tls_mask, tls_gd; struct plt_entry **ifunc, **plt_list; struct reloc_howto_struct alt_howto; @@ -7046,8 +7044,8 @@ ppc_elf_relocate_section (bfd *output_bfd, sym = NULL; sec = NULL; h = NULL; - unresolved_reloc = FALSE; - warned = FALSE; + unresolved_reloc = false; + warned = false; r_symndx = ELF32_R_SYM (rel->r_info); if (r_symndx < symtab_hdr->sh_info) @@ -7060,7 +7058,7 @@ ppc_elf_relocate_section (bfd *output_bfd, } else { - bfd_boolean ignored; + bool ignored; RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, r_symndx, symtab_hdr, sym_hashes, @@ -7148,7 +7146,8 @@ ppc_elf_relocate_section (bfd *output_bfd, case R_PPC_GOT_TPREL16: case R_PPC_GOT_TPREL16_LO: if ((tls_mask & TLS_TLS) != 0 - && (tls_mask & TLS_TPREL) == 0) + && (tls_mask & TLS_TPREL) == 0 + && offset_in_range (input_section, rel->r_offset - d_offset, 4)) { bfd_vma insn; @@ -7165,7 +7164,8 @@ ppc_elf_relocate_section (bfd *output_bfd, case R_PPC_TLS: if ((tls_mask & TLS_TLS) != 0 - && (tls_mask & TLS_TPREL) == 0) + && (tls_mask & TLS_TPREL) == 0 + && offset_in_range (input_section, rel->r_offset, 4)) { bfd_vma insn; @@ -7186,13 +7186,15 @@ ppc_elf_relocate_section (bfd *output_bfd, case R_PPC_GOT_TLSGD16_HI: case R_PPC_GOT_TLSGD16_HA: tls_gd = TLS_GDIE; - if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_GD) == 0) + if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_GD) == 0 + && offset_in_range (input_section, rel->r_offset - d_offset, 4)) 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) + if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_LD) == 0 + && offset_in_range (input_section, rel->r_offset - d_offset, 4)) { tls_gdld_hi: if ((tls_mask & tls_gd) != 0) @@ -7211,13 +7213,15 @@ ppc_elf_relocate_section (bfd *output_bfd, case R_PPC_GOT_TLSGD16: case R_PPC_GOT_TLSGD16_LO: tls_gd = TLS_GDIE; - if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_GD) == 0) + if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_GD) == 0 + && offset_in_range (input_section, rel->r_offset - d_offset, 4)) 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) + if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_LD) == 0 + && offset_in_range (input_section, rel->r_offset - d_offset, 4)) { unsigned int insn1, insn2; bfd_vma offset; @@ -7245,7 +7249,8 @@ ppc_elf_relocate_section (bfd *output_bfd, /* IE */ insn1 &= (0x1f << 21) | (0x1f << 16); insn1 |= 32u << 26; /* lwz */ - if (offset != (bfd_vma) -1) + if (offset != (bfd_vma) -1 + && offset_in_range (input_section, offset, 4)) { rel[1].r_info = ELF32_R_INFO (STN_UNDEF, R_PPC_NONE); insn2 = 0x7c631214; /* add 3,3,2 */ @@ -7278,7 +7283,8 @@ ppc_elf_relocate_section (bfd *output_bfd, } r_type = R_PPC_TPREL16_HA; rel->r_info = ELF32_R_INFO (r_symndx, r_type); - if (offset != (bfd_vma) -1) + if (offset != (bfd_vma) -1 + && offset_in_range (input_section, offset, 4)) { rel[1].r_info = ELF32_R_INFO (r_symndx, R_PPC_TPREL16_LO); rel[1].r_offset = offset + d_offset; @@ -7300,7 +7306,8 @@ ppc_elf_relocate_section (bfd *output_bfd, case R_PPC_TLSGD: if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_GD) == 0 - && rel + 1 < relend) + && rel + 1 < relend + && offset_in_range (input_section, rel->r_offset, 4)) { unsigned int insn2; bfd_vma offset = rel->r_offset; @@ -7335,7 +7342,8 @@ ppc_elf_relocate_section (bfd *output_bfd, case R_PPC_TLSLD: if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_LD) == 0 - && rel + 1 < relend) + && rel + 1 < relend + && offset_in_range (input_section, rel->r_offset, 4)) { unsigned int insn2; @@ -7388,48 +7396,50 @@ ppc_elf_relocate_section (bfd *output_bfd, /* Branch not taken prediction relocations. */ case R_PPC_ADDR14_BRNTAKEN: case R_PPC_REL14_BRNTAKEN: - { - unsigned int insn; + if (offset_in_range (input_section, rel->r_offset, 4)) + { + unsigned int insn; - insn = bfd_get_32 (input_bfd, contents + rel->r_offset); - insn &= ~BRANCH_PREDICT_BIT; - insn |= branch_bit; + insn = bfd_get_32 (input_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); + 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; + /* Invert 'y' bit if not the default. */ + if ((bfd_signed_vma) (relocation + rel->r_addend - from) < 0) + insn ^= BRANCH_PREDICT_BIT; - bfd_put_32 (input_bfd, insn, contents + rel->r_offset); - } + bfd_put_32 (input_bfd, insn, contents + rel->r_offset); + } break; case R_PPC_PLT16_HA: - { - unsigned int insn; + if (offset_in_range (input_section, rel->r_offset - d_offset, 4)) + { + unsigned int insn; - insn = bfd_get_32 (input_bfd, - contents + rel->r_offset - d_offset); - if ((insn & (0x3fu << 26)) == 15u << 26 - && (insn & (0x1f << 16)) != 0) - { - if (!bfd_link_pic (info)) - { - /* Convert addis to lis. */ - insn &= ~(0x1f << 16); - bfd_put_32 (input_bfd, insn, - contents + rel->r_offset - d_offset); - } - } - else if (bfd_link_pic (info)) - info->callbacks->einfo - (_("%P: %H: error: %s with unexpected instruction %x\n"), - input_bfd, input_section, rel->r_offset, - "R_PPC_PLT16_HA", insn); - } + insn = bfd_get_32 (input_bfd, + contents + rel->r_offset - d_offset); + if ((insn & (0x3fu << 26)) == 15u << 26 + && (insn & (0x1f << 16)) != 0) + { + if (!bfd_link_pic (info)) + { + /* Convert addis to lis. */ + insn &= ~(0x1f << 16); + bfd_put_32 (input_bfd, insn, + contents + rel->r_offset - d_offset); + } + } + else if (bfd_link_pic (info)) + info->callbacks->einfo + (_("%P: %H: error: %s with unexpected instruction %x\n"), + input_bfd, input_section, rel->r_offset, + "R_PPC_PLT16_HA", insn); + } break; } @@ -7445,7 +7455,8 @@ ppc_elf_relocate_section (bfd *output_bfd, variable defined in a shared library to PIC. */ unsigned int insn; - if (r_type == R_PPC_ADDR16_HA) + if (r_type == R_PPC_ADDR16_HA + && offset_in_range (input_section, rel->r_offset - d_offset, 4)) { insn = bfd_get_32 (input_bfd, contents + rel->r_offset - d_offset); @@ -7508,7 +7519,9 @@ ppc_elf_relocate_section (bfd *output_bfd, input_bfd, input_section, (uint64_t) rel->r_offset, "R_PPC_ADDR16_HA", insn); } - else if (r_type == R_PPC_ADDR16_LO) + else if (r_type == R_PPC_ADDR16_LO + && offset_in_range (input_section, + rel->r_offset - d_offset, 4)) { insn = bfd_get_32 (input_bfd, contents + rel->r_offset - d_offset); @@ -7533,7 +7546,7 @@ ppc_elf_relocate_section (bfd *output_bfd, { /* Arrange to apply the reloc addend, if any. */ relocation = 0; - unresolved_reloc = FALSE; + unresolved_reloc = false; rel->r_info = ELF32_R_INFO (0, r_type); } else @@ -7547,7 +7560,7 @@ ppc_elf_relocate_section (bfd *output_bfd, } ifunc = NULL; - if (!htab->is_vxworks) + if (htab->elf.target_os != is_vxworks) { struct plt_entry *ent; @@ -7607,7 +7620,7 @@ ppc_elf_relocate_section (bfd *output_bfd, input_bfd, input_section, rel->r_offset, sym_name); } - unresolved_reloc = FALSE; + unresolved_reloc = false; if (htab->plt_type == PLT_NEW || !htab->elf.dynamic_sections_created || h == NULL @@ -7628,49 +7641,22 @@ ppc_elf_relocate_section (bfd *output_bfd, if (r_type < R_PPC_max) howto = ppc_elf_howto_table[r_type]; - switch (r_type) - { - default: - break; - - case R_PPC_TPREL16_HA: - if (htab->do_tls_opt && relocation + addend + 0x8000 < 0x10000) - { - bfd_byte *p = contents + (rel->r_offset & ~3); - unsigned int insn = bfd_get_32 (input_bfd, p); - if ((insn & ((0x3fu << 26) | 0x1f << 16)) - != ((15u << 26) | (2 << 16)) /* addis rt,2,imm */) - /* xgettext:c-format */ - info->callbacks->minfo - (_("%H: warning: %s unexpected insn %#x.\n"), - input_bfd, input_section, rel->r_offset, howto->name, insn); - else - bfd_put_32 (input_bfd, NOP, p); - } - break; - - case R_PPC_TPREL16_LO: - if (htab->do_tls_opt && relocation + addend + 0x8000 < 0x10000) - { - bfd_byte *p = contents + (rel->r_offset & ~3); - unsigned int insn = bfd_get_32 (input_bfd, p); - insn &= ~(0x1f << 16); - insn |= 2 << 16; - bfd_put_32 (input_bfd, insn, p); - } - break; - } - tls_type = 0; switch (r_type) { default: - /* xgettext:c-format */ - _bfd_error_handler (_("%pB: %s unsupported"), - input_bfd, howto->name); + de_fault: + if (howto) + /* xgettext:c-format */ + _bfd_error_handler (_("%pB: %s unsupported"), + input_bfd, howto->name); + else + /* xgettext:c-format */ + _bfd_error_handler (_("%pB: reloc %#x unsupported"), + input_bfd, r_type); bfd_set_error (bfd_error_bad_value); - ret = FALSE; + ret = false; goto copy_reloc; case R_PPC_NONE: @@ -7748,7 +7734,7 @@ ppc_elf_relocate_section (bfd *output_bfd, else { indx = h->dynindx; - unresolved_reloc = FALSE; + unresolved_reloc = false; } offp = &h->got.offset; } @@ -7812,7 +7798,10 @@ ppc_elf_relocate_section (bfd *output_bfd, || !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h)) && !(tls_ty != 0 && bfd_link_executable (info) - && SYMBOL_REFERENCES_LOCAL (info, h)))) + && SYMBOL_REFERENCES_LOCAL (info, h)) + && (h != NULL + ? !bfd_is_abs_symbol (&h->root) + : sym->st_shndx != SHN_ABS))) { asection *rsec = htab->elf.srelgot; bfd_byte * loc; @@ -7969,7 +7958,7 @@ ppc_elf_relocate_section (bfd *output_bfd, input_bfd, input_section, rel->r_offset, - TRUE); + true); goto copy_reloc; } if (h != NULL && h->type == STT_GNU_IFUNC && bfd_link_pic (info)) @@ -8005,7 +7994,8 @@ ppc_elf_relocate_section (bfd *output_bfd, case R_PPC_TPREL16_HA: if (h != NULL && h->root.type == bfd_link_hash_undefweak - && h->dynindx == -1) + && h->dynindx == -1 + && offset_in_range (input_section, rel->r_offset - d_offset, 4)) { /* Make this relocation against an undefined weak symbol resolve to zero. This is really just a tweak, since @@ -8135,7 +8125,7 @@ ppc_elf_relocate_section (bfd *output_bfd, { indx = h->dynindx; BFD_ASSERT (indx != -1); - unresolved_reloc = FALSE; + unresolved_reloc = false; outrel.r_info = ELF32_R_INFO (indx, r_type); outrel.r_addend = rel->r_addend; } @@ -8166,14 +8156,14 @@ ppc_elf_relocate_section (bfd *output_bfd, input_bfd, input_section, rel->r_offset, howto->name, sym_name); - ret = FALSE; + 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; + ret = false; } else { @@ -8227,7 +8217,7 @@ ppc_elf_relocate_section (bfd *output_bfd, htab->maybe_local_ifunc_resolver = 1; } if (sreloc == NULL) - return FALSE; + return false; loc = sreloc->contents; loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rela); @@ -8273,66 +8263,73 @@ ppc_elf_relocate_section (bfd *output_bfd, /* Fall through. */ case R_PPC_RELAX: - { - const int *stub; - size_t size; - size_t insn_offset = rel->r_offset; - unsigned int insn; - - if (bfd_link_pic (info)) - { - relocation -= (input_section->output_section->vma - + input_section->output_offset - + rel->r_offset - 4); - stub = shared_stub_entry; - bfd_put_32 (input_bfd, stub[0], contents + insn_offset - 12); - bfd_put_32 (input_bfd, stub[1], contents + insn_offset - 8); - bfd_put_32 (input_bfd, stub[2], contents + insn_offset - 4); - stub += 3; - size = ARRAY_SIZE (shared_stub_entry) - 3; - } - else - { - stub = stub_entry; - size = ARRAY_SIZE (stub_entry); - } - - relocation += addend; - if (bfd_link_relocatable (info)) - relocation = 0; - - /* First insn is HA, second is LO. */ - insn = *stub++; - insn |= ((relocation + 0x8000) >> 16) & 0xffff; - bfd_put_32 (input_bfd, insn, contents + insn_offset); - insn_offset += 4; + if (bfd_link_pic (info) + ? offset_in_range (input_section, rel->r_offset - 12, + ARRAY_SIZE (shared_stub_entry) * 4) + : offset_in_range (input_section, rel->r_offset, + ARRAY_SIZE (stub_entry) * 4)) + { + const int *stub; + size_t size; + size_t insn_offset = rel->r_offset; + unsigned int insn; - insn = *stub++; - insn |= relocation & 0xffff; - bfd_put_32 (input_bfd, insn, contents + insn_offset); - insn_offset += 4; - size -= 2; + if (bfd_link_pic (info)) + { + relocation -= (input_section->output_section->vma + + input_section->output_offset + + rel->r_offset - 4); + stub = shared_stub_entry; + bfd_put_32 (input_bfd, stub[0], contents + insn_offset - 12); + bfd_put_32 (input_bfd, stub[1], contents + insn_offset - 8); + bfd_put_32 (input_bfd, stub[2], contents + insn_offset - 4); + stub += 3; + size = ARRAY_SIZE (shared_stub_entry) - 3; + } + else + { + stub = stub_entry; + size = ARRAY_SIZE (stub_entry); + } - while (size != 0) - { - insn = *stub++; - --size; - bfd_put_32 (input_bfd, insn, contents + insn_offset); - insn_offset += 4; - } + relocation += addend; + if (bfd_link_relocatable (info)) + relocation = 0; + + /* First insn is HA, second is LO. */ + insn = *stub++; + insn |= ((relocation + 0x8000) >> 16) & 0xffff; + bfd_put_32 (input_bfd, insn, contents + insn_offset); + insn_offset += 4; + + insn = *stub++; + insn |= relocation & 0xffff; + bfd_put_32 (input_bfd, insn, contents + insn_offset); + insn_offset += 4; + size -= 2; + + while (size != 0) + { + insn = *stub++; + --size; + bfd_put_32 (input_bfd, insn, contents + insn_offset); + insn_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 */ - wrel->r_offset = rel->r_offset + d_offset; - wrel->r_info = ELF32_R_INFO (r_symndx, R_PPC_ADDR16_HA); - wrel->r_addend = rel->r_addend; - memmove (wrel + 1, wrel, (relend - wrel - 1) * sizeof (*wrel)); - wrel++, rel++; - wrel->r_offset += 4; - wrel->r_info = ELF32_R_INFO (r_symndx, R_PPC_ADDR16_LO); - } + /* 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 */ + wrel->r_offset = rel->r_offset + d_offset; + wrel->r_info = ELF32_R_INFO (r_symndx, R_PPC_ADDR16_HA); + wrel->r_addend = rel->r_addend; + memmove (wrel + 1, wrel, (relend - wrel - 1) * sizeof (*wrel)); + wrel++, rel++; + wrel->r_offset += 4; + wrel->r_info = ELF32_R_INFO (r_symndx, R_PPC_ADDR16_LO); + } + else + goto de_fault; continue; /* Indirect .sdata relocation. */ @@ -8340,7 +8337,7 @@ ppc_elf_relocate_section (bfd *output_bfd, BFD_ASSERT (htab->sdata[0].section != NULL); if (!is_static_defined (htab->sdata[0].sym)) { - unresolved_reloc = TRUE; + unresolved_reloc = true; break; } relocation @@ -8354,7 +8351,7 @@ ppc_elf_relocate_section (bfd *output_bfd, BFD_ASSERT (htab->sdata[1].section != NULL); if (!is_static_defined (htab->sdata[1].sym)) { - unresolved_reloc = TRUE; + unresolved_reloc = true; break; } relocation @@ -8370,7 +8367,7 @@ ppc_elf_relocate_section (bfd *output_bfd, case R_PPC_TOC16: /* phony GOT16 relocations */ if (sec == NULL || sec->output_section == NULL) { - unresolved_reloc = TRUE; + unresolved_reloc = true; break; } BFD_ASSERT (strcmp (bfd_section_name (sec), ".got") == 0 @@ -8397,7 +8394,7 @@ ppc_elf_relocate_section (bfd *output_bfd, { /* Relocation is to the entry for this symbol in the procedure linkage table. */ - unresolved_reloc = FALSE; + unresolved_reloc = false; if (htab->plt_type == PLT_NEW) relocation = (htab->glink->output_section->vma + htab->glink->output_offset @@ -8432,7 +8429,7 @@ ppc_elf_relocate_section (bfd *output_bfd, + symtab_hdr->sh_info); plt_list = local_plt + r_symndx; } - unresolved_reloc = TRUE; + unresolved_reloc = true; if (plt_list != NULL) { struct plt_entry *ent; @@ -8443,11 +8440,9 @@ ppc_elf_relocate_section (bfd *output_bfd, { asection *plt; - unresolved_reloc = FALSE; + unresolved_reloc = false; plt = htab->elf.splt; - if (!htab->elf.dynamic_sections_created - || h == NULL - || h->dynindx == -1) + if (use_local_plt (info, h)) { if (ifunc != NULL) plt = htab->elf.iplt; @@ -8484,7 +8479,7 @@ ppc_elf_relocate_section (bfd *output_bfd, || sec->output_section == NULL || !is_static_defined (sda)) { - unresolved_reloc = TRUE; + unresolved_reloc = true; break; } addend -= SYM_VAL (sda); @@ -8515,7 +8510,7 @@ ppc_elf_relocate_section (bfd *output_bfd, || sec->output_section == NULL || !is_static_defined (sda)) { - unresolved_reloc = TRUE; + unresolved_reloc = true; break; } addend -= SYM_VAL (sda); @@ -8538,151 +8533,164 @@ ppc_elf_relocate_section (bfd *output_bfd, case R_PPC_VLE_LO16A: relocation = relocation + addend; - ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset, - contents + rel->r_offset, relocation, - split16a_type, htab->params->vle_reloc_fixup); - goto copy_reloc; + r = ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset, + contents + rel->r_offset, relocation, + split16a_type, + htab->params->vle_reloc_fixup); + goto report_reloc; case R_PPC_VLE_LO16D: relocation = relocation + addend; - ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset, - contents + rel->r_offset, relocation, - split16d_type, htab->params->vle_reloc_fixup); - goto copy_reloc; + r = ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset, + contents + rel->r_offset, relocation, + split16d_type, + htab->params->vle_reloc_fixup); + goto report_reloc; case R_PPC_VLE_HI16A: relocation = (relocation + addend) >> 16; - ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset, - contents + rel->r_offset, relocation, - split16a_type, htab->params->vle_reloc_fixup); - goto copy_reloc; + r = ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset, + contents + rel->r_offset, relocation, + split16a_type, + htab->params->vle_reloc_fixup); + goto report_reloc; case R_PPC_VLE_HI16D: relocation = (relocation + addend) >> 16; - ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset, - contents + rel->r_offset, relocation, - split16d_type, htab->params->vle_reloc_fixup); - goto copy_reloc; + r = ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset, + contents + rel->r_offset, relocation, + split16d_type, + htab->params->vle_reloc_fixup); + goto report_reloc; case R_PPC_VLE_HA16A: relocation = (relocation + addend + 0x8000) >> 16; - ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset, - contents + rel->r_offset, relocation, - split16a_type, htab->params->vle_reloc_fixup); - goto copy_reloc; + r = ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset, + contents + rel->r_offset, relocation, + split16a_type, + htab->params->vle_reloc_fixup); + goto report_reloc; case R_PPC_VLE_HA16D: relocation = (relocation + addend + 0x8000) >> 16; - ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset, - contents + rel->r_offset, relocation, - split16d_type, htab->params->vle_reloc_fixup); - goto copy_reloc; + r = ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset, + contents + rel->r_offset, relocation, + split16d_type, + htab->params->vle_reloc_fixup); + goto report_reloc; /* 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; - unsigned int insn; - struct elf_link_hash_entry *sda = NULL; + if (!offset_in_range (input_section, rel->r_offset, 4)) + { + r = bfd_reloc_outofrange; + goto report_reloc; + } + else + { + const char *name; + int reg; + unsigned int insn; + struct elf_link_hash_entry *sda = NULL; - if (sec == NULL || sec->output_section == NULL) - { - unresolved_reloc = TRUE; - break; - } + if (sec == NULL || sec->output_section == NULL) + { + unresolved_reloc = true; + break; + } - name = bfd_section_name (sec->output_section); - if (strcmp (name, ".sdata") == 0 - || strcmp (name, ".sbss") == 0) - { - reg = 13; - sda = htab->sdata[0].sym; - } - else if (strcmp (name, ".sdata2") == 0 - || strcmp (name, ".sbss2") == 0) - { - reg = 2; - sda = htab->sdata[1].sym; - } - else if (strcmp (name, ".PPC.EMB.sdata0") == 0 - || strcmp (name, ".PPC.EMB.sbss0") == 0) - { - reg = 0; - } - else - { - _bfd_error_handler - /* xgettext:c-format */ - (_("%pB: the target (%s) of a %s relocation is " - "in the wrong output section (%s)"), - input_bfd, - sym_name, - howto->name, - name); + name = bfd_section_name (sec->output_section); + if (strcmp (name, ".sdata") == 0 + || strcmp (name, ".sbss") == 0) + { + reg = 13; + sda = htab->sdata[0].sym; + } + else if (strcmp (name, ".sdata2") == 0 + || strcmp (name, ".sbss2") == 0) + { + reg = 2; + sda = htab->sdata[1].sym; + } + else if (strcmp (name, ".PPC.EMB.sdata0") == 0 + || strcmp (name, ".PPC.EMB.sbss0") == 0) + { + reg = 0; + } + else + { + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB: 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; + goto copy_reloc; + } - bfd_set_error (bfd_error_bad_value); - ret = FALSE; - goto copy_reloc; - } + if (sda != NULL) + { + if (!is_static_defined (sda)) + { + unresolved_reloc = true; + break; + } + addend -= SYM_VAL (sda); + } - if (sda != NULL) - { - if (!is_static_defined (sda)) - { - unresolved_reloc = TRUE; - break; - } - addend -= SYM_VAL (sda); - } + if (r_type == R_PPC_EMB_RELSDA) + break; - if (r_type == R_PPC_EMB_RELSDA) - break; + /* The PowerPC Embedded Application Binary Interface + version 1.0 insanely chose to specify R_PPC_EMB_SDA21 + operating on a 24-bit field at r_offset. GNU as and + GNU ld have always assumed R_PPC_EMB_SDA21 operates on + a 32-bit bit insn at r_offset. Cope with object file + producers that possibly comply with the EABI in + generating an odd r_offset for big-endian objects. */ + if (r_type == R_PPC_EMB_SDA21) + rel->r_offset &= ~1; - /* The PowerPC Embedded Application Binary Interface - version 1.0 insanely chose to specify R_PPC_EMB_SDA21 - operating on a 24-bit field at r_offset. GNU as and - GNU ld have always assumed R_PPC_EMB_SDA21 operates on - a 32-bit bit insn at r_offset. Cope with object file - producers that possibly comply with the EABI in - generating an odd r_offset for big-endian objects. */ - if (r_type == R_PPC_EMB_SDA21) - rel->r_offset &= ~1; - - insn = bfd_get_32 (input_bfd, contents + rel->r_offset); - if (reg == 0 - && (r_type == R_PPC_VLE_SDA21 - || r_type == R_PPC_VLE_SDA21_LO)) - { - relocation = relocation + addend; - addend = 0; - - /* Force e_li insn, keeping RT from original insn. */ - insn &= 0x1f << 21; - insn |= 28u << 26; - - /* We have an li20 field, bits 17..20, 11..15, 21..31. */ - /* Top 4 bits of value to 17..20. */ - insn |= (relocation & 0xf0000) >> 5; - /* Next 5 bits of the value to 11..15. */ - insn |= (relocation & 0xf800) << 5; - /* And the final 11 bits of the value to bits 21 to 31. */ - insn |= relocation & 0x7ff; - - bfd_put_32 (input_bfd, insn, contents + rel->r_offset); - - if (r_type == R_PPC_VLE_SDA21 - && ((relocation + 0x80000) & 0xffffffff) > 0x100000) - goto overflow; - goto copy_reloc; - } - /* Fill in register field. */ - insn = (insn & ~RA_REGISTER_MASK) | (reg << RA_REGISTER_SHIFT); - bfd_put_32 (input_bfd, insn, contents + rel->r_offset); - } + insn = bfd_get_32 (input_bfd, contents + rel->r_offset); + if (reg == 0 + && (r_type == R_PPC_VLE_SDA21 + || r_type == R_PPC_VLE_SDA21_LO)) + { + relocation = relocation + addend; + addend = 0; + + /* Force e_li insn, keeping RT from original insn. */ + insn &= 0x1f << 21; + insn |= 28u << 26; + + /* We have an li20 field, bits 17..20, 11..15, 21..31. */ + /* Top 4 bits of value to 17..20. */ + insn |= (relocation & 0xf0000) >> 5; + /* Next 5 bits of the value to 11..15. */ + insn |= (relocation & 0xf800) << 5; + /* And the final 11 bits of the value to bits 21 to 31. */ + insn |= relocation & 0x7ff; + + bfd_put_32 (input_bfd, insn, contents + rel->r_offset); + + r = bfd_reloc_ok; + if (r_type == R_PPC_VLE_SDA21 + && ((relocation + 0x80000) & 0xffffffff) > 0x100000) + r = bfd_reloc_overflow; + goto report_reloc; + } + /* Fill in register field. */ + insn = (insn & ~RA_REGISTER_MASK) | (reg << RA_REGISTER_SHIFT); + bfd_put_32 (input_bfd, insn, contents + rel->r_offset); + } break; case R_PPC_VLE_SDAREL_LO16A: @@ -8691,95 +8699,113 @@ ppc_elf_relocate_section (bfd *output_bfd, case R_PPC_VLE_SDAREL_HI16D: case R_PPC_VLE_SDAREL_HA16A: case R_PPC_VLE_SDAREL_HA16D: - { - bfd_vma value; - const char *name; - struct elf_link_hash_entry *sda = NULL; - - if (sec == NULL || sec->output_section == NULL) - { - unresolved_reloc = TRUE; - break; - } - - name = bfd_section_name (sec->output_section); - if (strcmp (name, ".sdata") == 0 - || strcmp (name, ".sbss") == 0) - sda = htab->sdata[0].sym; - else if (strcmp (name, ".sdata2") == 0 - || strcmp (name, ".sbss2") == 0) - sda = htab->sdata[1].sym; - else - { - _bfd_error_handler - /* xgettext:c-format */ - (_("%pB: the target (%s) of a %s relocation is " - "in the wrong output section (%s)"), - input_bfd, - sym_name, - howto->name, - name); + if (!offset_in_range (input_section, rel->r_offset, 4)) + r = bfd_reloc_outofrange; + else + { + bfd_vma value; + const char *name; + struct elf_link_hash_entry *sda = NULL; - bfd_set_error (bfd_error_bad_value); - ret = FALSE; - goto copy_reloc; - } + if (sec == NULL || sec->output_section == NULL) + { + unresolved_reloc = true; + break; + } - if (sda == NULL || !is_static_defined (sda)) - { - unresolved_reloc = TRUE; - break; - } - value = relocation + addend - SYM_VAL (sda); + name = bfd_section_name (sec->output_section); + if (strcmp (name, ".sdata") == 0 + || strcmp (name, ".sbss") == 0) + sda = htab->sdata[0].sym; + else if (strcmp (name, ".sdata2") == 0 + || strcmp (name, ".sbss2") == 0) + sda = htab->sdata[1].sym; + else + { + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB: 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; + goto copy_reloc; + } - if (r_type == R_PPC_VLE_SDAREL_LO16A) - ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset, - contents + rel->r_offset, value, - split16a_type, - htab->params->vle_reloc_fixup); - else if (r_type == R_PPC_VLE_SDAREL_LO16D) - ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset, - contents + rel->r_offset, value, - split16d_type, - htab->params->vle_reloc_fixup); - else if (r_type == R_PPC_VLE_SDAREL_HI16A) - { - value = value >> 16; - ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset, - contents + rel->r_offset, value, - split16a_type, - htab->params->vle_reloc_fixup); - } - else if (r_type == R_PPC_VLE_SDAREL_HI16D) - { - value = value >> 16; - ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset, - contents + rel->r_offset, value, - split16d_type, - htab->params->vle_reloc_fixup); - } - else if (r_type == R_PPC_VLE_SDAREL_HA16A) - { - value = (value + 0x8000) >> 16; - ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset, - contents + rel->r_offset, value, - split16a_type, - htab->params->vle_reloc_fixup); - } - else if (r_type == R_PPC_VLE_SDAREL_HA16D) - { - value = (value + 0x8000) >> 16; - ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset, - contents + rel->r_offset, value, - split16d_type, - htab->params->vle_reloc_fixup); - } - } - goto copy_reloc; + if (sda == NULL || !is_static_defined (sda)) + { + unresolved_reloc = true; + break; + } + value = relocation + addend - SYM_VAL (sda); + + if (r_type == R_PPC_VLE_SDAREL_LO16A) + r = ppc_elf_vle_split16 (input_bfd, input_section, + rel->r_offset, + contents + rel->r_offset, value, + split16a_type, + htab->params->vle_reloc_fixup); + else if (r_type == R_PPC_VLE_SDAREL_LO16D) + r = ppc_elf_vle_split16 (input_bfd, input_section, + rel->r_offset, + contents + rel->r_offset, value, + split16d_type, + htab->params->vle_reloc_fixup); + else if (r_type == R_PPC_VLE_SDAREL_HI16A) + { + value = value >> 16; + r = ppc_elf_vle_split16 (input_bfd, input_section, + rel->r_offset, + contents + rel->r_offset, value, + split16a_type, + htab->params->vle_reloc_fixup); + } + else if (r_type == R_PPC_VLE_SDAREL_HI16D) + { + value = value >> 16; + r = ppc_elf_vle_split16 (input_bfd, input_section, + rel->r_offset, + contents + rel->r_offset, value, + split16d_type, + htab->params->vle_reloc_fixup); + } + else if (r_type == R_PPC_VLE_SDAREL_HA16A) + { + value = (value + 0x8000) >> 16; + r = ppc_elf_vle_split16 (input_bfd, input_section, + rel->r_offset, + contents + rel->r_offset, value, + split16a_type, + htab->params->vle_reloc_fixup); + } + else if (r_type == R_PPC_VLE_SDAREL_HA16D) + { + value = (value + 0x8000) >> 16; + r = ppc_elf_vle_split16 (input_bfd, input_section, + rel->r_offset, + contents + rel->r_offset, value, + split16d_type, + htab->params->vle_reloc_fixup); + } + else + abort (); + } + goto report_reloc; case R_PPC_VLE_ADDR20: - ppc_elf_vle_split20 (output_bfd, contents + rel->r_offset, relocation); - goto copy_reloc; + if (!offset_in_range (input_section, rel->r_offset, 4)) + r = bfd_reloc_outofrange; + else + { + ppc_elf_vle_split20 (output_bfd, contents + rel->r_offset, + relocation); + r = bfd_reloc_ok; + } + goto report_reloc; /* Relocate against the beginning of the section. */ case R_PPC_SECTOFF: @@ -8788,7 +8814,7 @@ ppc_elf_relocate_section (bfd *output_bfd, case R_PPC_SECTOFF_HA: if (sec == NULL || sec->output_section == NULL) { - unresolved_reloc = TRUE; + unresolved_reloc = true; break; } addend -= sec->output_section->vma; @@ -8821,10 +8847,40 @@ ppc_elf_relocate_section (bfd *output_bfd, input_bfd, howto->name); bfd_set_error (bfd_error_invalid_operation); - ret = FALSE; + ret = false; goto copy_reloc; } + switch (r_type) + { + default: + break; + + case R_PPC_TPREL16_HA: + if (htab->do_tls_opt + && relocation + addend + 0x8000 < 0x10000 + && offset_in_range (input_section, rel->r_offset & ~3, 4)) + + { + bfd_byte *p = contents + (rel->r_offset & ~3); + bfd_put_32 (input_bfd, NOP, p); + } + break; + + case R_PPC_TPREL16_LO: + if (htab->do_tls_opt + && relocation + addend + 0x8000 < 0x10000 + && offset_in_range (input_section, rel->r_offset & ~3, 4)) + { + bfd_byte *p = contents + (rel->r_offset & ~3); + unsigned int insn = bfd_get_32 (input_bfd, p); + insn &= ~(0x1f << 16); + insn |= 2 << 16; + bfd_put_32 (input_bfd, insn, p); + } + break; + } + switch (r_type) { default: @@ -8833,13 +8889,16 @@ ppc_elf_relocate_section (bfd *output_bfd, case R_PPC_PLTCALL: if (unresolved_reloc) { - bfd_byte *p = contents + rel->r_offset; - unsigned int insn = bfd_get_32 (input_bfd, p); - insn &= 1; - bfd_put_32 (input_bfd, B | insn, p); - unresolved_reloc = save_unresolved_reloc; - r_type = R_PPC_REL24; - howto = ppc_elf_howto_table[r_type]; + if (offset_in_range (input_section, rel->r_offset, 4)) + { + bfd_byte *p = contents + rel->r_offset; + unsigned int insn = bfd_get_32 (input_bfd, p); + insn &= 1; + bfd_put_32 (input_bfd, B | insn, p); + unresolved_reloc = save_unresolved_reloc; + r_type = R_PPC_REL24; + howto = ppc_elf_howto_table[r_type]; + } } else if (htab->plt_type != PLT_NEW) info->callbacks->einfo @@ -8853,11 +8912,14 @@ ppc_elf_relocate_section (bfd *output_bfd, case R_PPC_PLT16_LO: if (unresolved_reloc) { - bfd_byte *p = contents + (rel->r_offset & ~3); - bfd_put_32 (input_bfd, NOP, p); - unresolved_reloc = FALSE; - r_type = R_PPC_NONE; - howto = ppc_elf_howto_table[r_type]; + if (offset_in_range (input_section, rel->r_offset & ~3, 4)) + { + bfd_byte *p = contents + (rel->r_offset & ~3); + bfd_put_32 (input_bfd, NOP, p); + unresolved_reloc = false; + r_type = R_PPC_NONE; + howto = ppc_elf_howto_table[r_type]; + } } else if (htab->plt_type != PLT_NEW) info->callbacks->einfo @@ -8919,36 +8981,37 @@ ppc_elf_relocate_section (bfd *output_bfd, 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 (input_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; - relocation += addend; - addend = insn & mask; - lobit = mask & relocation; - if (lobit != 0) - { - relocation ^= lobit; - info->callbacks->einfo - /* xgettext:c-format */ - (_("%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; - } - } + if (offset_in_range (input_section, rel->r_offset - d_offset, 4)) + { + /* 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 (input_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; + relocation += addend; + addend = insn & mask; + lobit = mask & relocation; + if (lobit != 0) + { + relocation ^= lobit; + info->callbacks->einfo + /* xgettext:c-format */ + (_("%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; + } + } break; } @@ -8975,7 +9038,7 @@ ppc_elf_relocate_section (bfd *output_bfd, input_bfd, input_section, rel->r_offset, howto->name, sym_name); - ret = FALSE; + ret = false; } /* 16-bit fields in insns mostly have signed values, but a @@ -8983,7 +9046,8 @@ ppc_elf_relocate_section (bfd *output_bfd, have different reloc types. */ if (howto->complain_on_overflow != complain_overflow_dont && howto->dst_mask == 0xffff - && (input_section->flags & SEC_CODE) != 0) + && (input_section->flags & SEC_CODE) != 0 + && offset_in_range (input_section, rel->r_offset & ~3, 4)) { enum complain_overflow complain = complain_overflow_signed; @@ -9010,7 +9074,7 @@ ppc_elf_relocate_section (bfd *output_bfd, if (r_type == R_PPC_REL16DX_HA) { /* Split field reloc isn't handled by _bfd_final_link_relocate. */ - if (rel->r_offset + 4 > input_section->size) + if (offset_in_range (input_section, rel->r_offset, 4)) r = bfd_reloc_outofrange; else { @@ -9032,11 +9096,11 @@ ppc_elf_relocate_section (bfd *output_bfd, r = _bfd_final_link_relocate (howto, input_bfd, input_section, contents, rel->r_offset, relocation, addend); + report_reloc: if (r != bfd_reloc_ok) { if (r == bfd_reloc_overflow) { - overflow: /* On code like "if (foo) foo();" don't report overflow on a branch to zero when foo is undefined. */ if (!warned @@ -9055,7 +9119,7 @@ ppc_elf_relocate_section (bfd *output_bfd, (_("%H: %s reloc against `%s': error %d\n"), input_bfd, input_section, rel->r_offset, howto->name, sym_name, (int) r); - ret = FALSE; + ret = false; } } copy_reloc: @@ -9140,13 +9204,13 @@ ppc_elf_relocate_section (bfd *output_bfd, { bfd_vma offset = addr - start_addr; Elf_Internal_Rela *lo, *hi; - bfd_boolean is_data; + bool is_data; bfd_vma patch_off, patch_addr; unsigned int insn; /* Do we have a data reloc at this offset? If so, leave the word alone. */ - is_data = FALSE; + is_data = false; lo = relocs; hi = relend; rel = NULL; @@ -9165,7 +9229,7 @@ ppc_elf_relocate_section (bfd *output_bfd, case R_PPC_UADDR32: case R_PPC_REL32: case R_PPC_ADDR30: - is_data = TRUE; + is_data = true; break; default: break; @@ -9386,18 +9450,20 @@ ppc_elf_relocate_section (bfd *output_bfd, /* Write out the PLT relocs and entries for H. */ -static bfd_boolean +static bool write_global_sym_plt (struct elf_link_hash_entry *h, void *inf) { struct bfd_link_info *info = (struct bfd_link_info *) inf; struct ppc_elf_link_hash_table *htab = ppc_elf_hash_table (info); struct plt_entry *ent; - bfd_boolean doneone; + bool doneone; - doneone = FALSE; + doneone = false; for (ent = h->plt.plist; ent != NULL; ent = ent->next) if (ent->plt.offset != (bfd_vma) -1) { + bool dyn = !use_local_plt (info, h); + if (!doneone) { Elf_Internal_Rela rela; @@ -9406,9 +9472,7 @@ write_global_sym_plt (struct elf_link_hash_entry *h, void *inf) asection *plt = htab->elf.splt; asection *relplt = htab->elf.srelplt; - if (htab->plt_type == PLT_NEW - || !htab->elf.dynamic_sections_created - || h->dynindx == -1) + if (htab->plt_type == PLT_NEW || !dyn) reloc_index = ent->plt.offset / 4; else { @@ -9421,9 +9485,7 @@ write_global_sym_plt (struct elf_link_hash_entry *h, void *inf) /* 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) + if (htab->plt_type == PLT_VXWORKS && dyn) { bfd_vma got_offset; const bfd_vma *plt_entry; @@ -9546,8 +9608,7 @@ write_global_sym_plt (struct elf_link_hash_entry *h, void *inf) else { rela.r_addend = 0; - if (!htab->elf.dynamic_sections_created - || h->dynindx == -1) + if (!dyn) { if (h->type == STT_GNU_IFUNC) { @@ -9576,9 +9637,7 @@ write_global_sym_plt (struct elf_link_hash_entry *h, void *inf) + plt->output_offset + ent->plt.offset); - if (htab->plt_type == PLT_OLD - || !htab->elf.dynamic_sections_created - || h->dynindx == -1) + if (htab->plt_type == PLT_OLD || !dyn) { /* We don't need to fill in the .plt. The ppc dynamic linker will fill it in. */ @@ -9597,8 +9656,7 @@ write_global_sym_plt (struct elf_link_hash_entry *h, void *inf) if (relplt != NULL) { /* Fill in the entry in the .rela.plt section. */ - if (!htab->elf.dynamic_sections_created - || h->dynindx == -1) + if (!dyn) { if (h->type == STT_GNU_IFUNC) rela.r_info = ELF32_R_INFO (0, R_PPC_IRELATIVE); @@ -9618,18 +9676,15 @@ write_global_sym_plt (struct elf_link_hash_entry *h, void *inf) } bfd_elf32_swap_reloca_out (info->output_bfd, &rela, loc); } - doneone = TRUE; + doneone = true; } - if (htab->plt_type == PLT_NEW - || !htab->elf.dynamic_sections_created - || h->dynindx == -1) + if (htab->plt_type == PLT_NEW || !dyn) { unsigned char *p; asection *plt = htab->elf.splt; - if (!htab->elf.dynamic_sections_created - || h->dynindx == -1) + if (!dyn) { if (h->type == STT_GNU_IFUNC) plt = htab->elf.iplt; @@ -9647,19 +9702,19 @@ write_global_sym_plt (struct elf_link_hash_entry *h, void *inf) else break; } - return TRUE; + return true; } /* Finish up PLT handling. */ -bfd_boolean +bool ppc_finish_symbols (struct bfd_link_info *info) { struct ppc_elf_link_hash_table *htab = ppc_elf_hash_table (info); bfd *ibfd; if (!htab) - return TRUE; + return true; elf_link_hash_traverse (&htab->elf, write_global_sym_plt, info); @@ -9702,7 +9757,7 @@ ppc_finish_symbols (struct bfd_link_info *info) { if (symtab_hdr->contents != (unsigned char *) local_syms) free (local_syms); - return FALSE; + return false; } val = sym->st_value; @@ -9754,13 +9809,13 @@ ppc_finish_symbols (struct bfd_link_info *info) symtab_hdr->contents = (unsigned char *) local_syms; } } - return TRUE; + return true; } /* Finish up dynamic symbol handling. We set the contents of various dynamic sections here. */ -static bfd_boolean +static bool ppc_elf_finish_dynamic_symbol (bfd *output_bfd, struct bfd_link_info *info, struct elf_link_hash_entry *h, @@ -9851,7 +9906,7 @@ ppc_elf_finish_dynamic_symbol (bfd *output_bfd, fprintf (stderr, "\n"); #endif - return TRUE; + return true; } static enum elf_reloc_type_class @@ -9879,7 +9934,7 @@ ppc_elf_reloc_type_class (const struct bfd_link_info *info, /* Finish up the dynamic sections. */ -static bfd_boolean +static bool ppc_elf_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) { @@ -9887,7 +9942,7 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd, struct ppc_elf_link_hash_table *htab; bfd_vma got; bfd *dynobj; - bfd_boolean ret = TRUE; + bool ret = true; #ifdef DEBUG fprintf (stderr, "ppc_elf_finish_dynamic_sections called\n"); @@ -9919,7 +9974,7 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd, switch (dyn.d_tag) { case DT_PLTGOT: - if (htab->is_vxworks) + if (htab->elf.target_os == is_vxworks) s = htab->elf.sgotplt; else s = htab->elf.splt; @@ -9951,7 +10006,7 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd, continue; default: - if (htab->is_vxworks + if (htab->elf.target_os == is_vxworks && elf_vxworks_finish_dynamic_entry (output_bfd, &dyn)) break; continue; @@ -9996,14 +10051,14 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd, (htab->elf.sgotplt != NULL ? htab->elf.sgotplt : htab->elf.sgot)); bfd_set_error (bfd_error_bad_value); - ret = FALSE; + ret = false; } elf_section_data (htab->elf.sgot->output_section)->this_hdr.sh_entsize = 4; } /* Fill in the first entry in the VxWorks procedure linkage table. */ - if (htab->is_vxworks + if (htab->elf.target_os == is_vxworks && htab->elf.splt != NULL && htab->elf.splt->size != 0 && htab->elf.splt->output_section != bfd_abs_section_ptr) @@ -10308,7 +10363,7 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd, && !_bfd_elf_write_section_eh_frame (output_bfd, info, htab->glink_eh_frame, htab->glink_eh_frame->contents)) - return FALSE; + return false; } return ret; @@ -10323,7 +10378,6 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd, #define ELF_MACHINE_CODE EM_PPC #define ELF_MAXPAGESIZE 0x10000 #define ELF_COMMONPAGESIZE 0x1000 -#define ELF_RELROPAGESIZE ELF_MAXPAGESIZE #define elf_info_to_howto ppc_elf_info_to_howto #ifdef EM_CYGNUS_POWERPC @@ -10412,6 +10466,9 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd, #undef ELF_OSABI +#undef ELF_TARGET_OS +#define ELF_TARGET_OS is_vxworks + /* 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, asection *sec) @@ -10437,7 +10494,6 @@ ppc_elf_vxworks_link_hash_table_create (bfd *abfd) { 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; @@ -10447,7 +10503,7 @@ ppc_elf_vxworks_link_hash_table_create (bfd *abfd) } /* Tweak magic VxWorks symbols as they are loaded. */ -static bfd_boolean +static bool ppc_elf_vxworks_add_symbol_hook (bfd *abfd, struct bfd_link_info *info, Elf_Internal_Sym *sym, @@ -10458,12 +10514,12 @@ ppc_elf_vxworks_add_symbol_hook (bfd *abfd, { if (!elf_vxworks_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)) - return FALSE; + return false; return ppc_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp); } -static bfd_boolean +static bool ppc_elf_vxworks_final_write_processing (bfd *abfd) { ppc_final_write_processing (abfd);