/* PowerPC64-specific support for 64-bit ELF.
- Copyright (C) 1999-2020 Free Software Foundation, Inc.
+ Copyright (C) 1999-2021 Free Software Foundation, Inc.
Written by Linus Nordberg, Swox AB <info@swox.com>,
based on elf32-ppc.c by Ian Lance Taylor.
Largely rewritten by Alan Modra.
http://www.linuxbase.org/spec/ELF/ppc64/PPC-elf64abi.txt, and
http://www.linuxbase.org/spec/ELF/ppc64/spec/book1.html */
+/* Don't generate unused section symbols. */
+#define TARGET_KEEP_UNUSED_SECTION_SYMBOLS false
+
#include "sysdep.h"
#include <stdarg.h>
#include "bfd.h"
static bfd_reloc_status_type ppc64_elf_unhandled_reloc
(bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
static bfd_vma opd_entry_value
- (asection *, bfd_vma, asection **, bfd_vma *, bfd_boolean);
+ (asection *, bfd_vma, asection **, bfd_vma *, bool);
#define TARGET_LITTLE_SYM powerpc_elf64_le_vec
#define TARGET_LITTLE_NAME "elf64-powerpcle"
#define elf_backend_adjust_dynamic_symbol ppc64_elf_adjust_dynamic_symbol
#define elf_backend_hide_symbol ppc64_elf_hide_symbol
#define elf_backend_maybe_function_sym ppc64_elf_maybe_function_sym
-#define elf_backend_always_size_sections ppc64_elf_func_desc_adjust
+#define elf_backend_always_size_sections ppc64_elf_edit
#define elf_backend_size_dynamic_sections ppc64_elf_size_dynamic_sections
#define elf_backend_hash_symbol ppc64_elf_hash_symbol
#define elf_backend_init_index_section _bfd_elf_init_2_index_sections
#define PLD_R12_PC 0x04100000e5800000ULL
#define PNOP 0x0700000000000000ULL
-/* __glink_PLTresolve stub instructions. We enter with the index in R0. */
+/* __glink_PLTresolve stub instructions. We enter with the index in
+ R0 for ELFv1, and the address of a glink branch in R12 for ELFv2. */
#define GLINK_PLTRESOLVE_SIZE(htab) \
- (8u + (htab->opd_abi ? 11 * 4 : 14 * 4))
+ (8u + (htab->opd_abi ? 11 * 4 : htab->has_plt_localentry0 ? 14 * 4 : 13 * 4))
/* 0: */
/* .quad plt0-1f */
/* __glink: */
/* mtctr %12 */
/* ld %11,16(%11) */
/* bctr */
-#define MFLR_R0 0x7c0802a6 /* mflr %r0 */
-#define MTLR_R0 0x7c0803a6 /* mtlr %r0 */
-#define SUB_R12_R12_R11 0x7d8b6050 /* subf %r12,%r11,%r12 */
-#define ADDI_R0_R12 0x380c0000 /* addi %r0,%r12,0 */
-#define SRDI_R0_R0_2 0x7800f082 /* rldicl %r0,%r0,62,2 */
+
+#define MFLR_R0 0x7c0802a6 /* mflr %r0 */
+#define MTLR_R0 0x7c0803a6 /* mtlr %r0 */
+#define SUB_R12_R12_R11 0x7d8b6050 /* subf %r12,%r11,%r12 */
+#define ADDI_R0_R12 0x380c0000 /* addi %r0,%r12,0 */
+#define SRDI_R0_R0_2 0x7800f082 /* rldicl %r0,%r0,62,2 */
+#define LD_R0_0R11 0xe80b0000 /* ld %r0,0(%r11) */
+#define ADD_R11_R0_R11 0x7d605a14 /* add %r11,%r0,%r11 */
/* Pad with this. */
#define NOP 0x60000000
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 *ppc64_elf_howto_table[(int) R_PPC64_max];
static reloc_howto_type ppc64_elf_howto_raw[] =
{
/* This reloc does nothing. */
- HOW (R_PPC64_NONE, 3, 0, 0, 0, FALSE, dont,
+ HOW (R_PPC64_NONE, 3, 0, 0, 0, false, dont,
bfd_elf_generic_reloc),
/* A standard 32 bit relocation. */
- HOW (R_PPC64_ADDR32, 2, 32, 0xffffffff, 0, FALSE, bitfield,
+ HOW (R_PPC64_ADDR32, 2, 32, 0xffffffff, 0, false, bitfield,
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_PPC64_ADDR24, 2, 26, 0x03fffffc, 0, FALSE, bitfield,
+ HOW (R_PPC64_ADDR24, 2, 26, 0x03fffffc, 0, false, bitfield,
bfd_elf_generic_reloc),
/* A standard 16 bit relocation. */
- HOW (R_PPC64_ADDR16, 1, 16, 0xffff, 0, FALSE, bitfield,
+ HOW (R_PPC64_ADDR16, 1, 16, 0xffff, 0, false, bitfield,
bfd_elf_generic_reloc),
/* A 16 bit relocation without overflow. */
- HOW (R_PPC64_ADDR16_LO, 1, 16, 0xffff, 0, FALSE, dont,
+ HOW (R_PPC64_ADDR16_LO, 1, 16, 0xffff, 0, false, dont,
bfd_elf_generic_reloc),
/* Bits 16-31 of an address. */
- HOW (R_PPC64_ADDR16_HI, 1, 16, 0xffff, 16, FALSE, signed,
+ HOW (R_PPC64_ADDR16_HI, 1, 16, 0xffff, 16, false, signed,
bfd_elf_generic_reloc),
/* Bits 16-31 of an address, plus 1 if the contents of the low 16
bits, treated as a signed number, is negative. */
- HOW (R_PPC64_ADDR16_HA, 1, 16, 0xffff, 16, FALSE, signed,
+ HOW (R_PPC64_ADDR16_HA, 1, 16, 0xffff, 16, false, signed,
ppc64_elf_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_PPC64_ADDR14, 2, 16, 0x0000fffc, 0, FALSE, signed,
+ HOW (R_PPC64_ADDR14, 2, 16, 0x0000fffc, 0, false, signed,
ppc64_elf_branch_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_PPC64_ADDR14_BRTAKEN, 2, 16, 0x0000fffc, 0, FALSE, signed,
+ HOW (R_PPC64_ADDR14_BRTAKEN, 2, 16, 0x0000fffc, 0, false, signed,
ppc64_elf_brtaken_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_PPC64_ADDR14_BRNTAKEN, 2, 16, 0x0000fffc, 0, FALSE, signed,
+ HOW (R_PPC64_ADDR14_BRNTAKEN, 2, 16, 0x0000fffc, 0, false, signed,
ppc64_elf_brtaken_reloc),
/* A relative 26 bit branch; the lower two bits must be zero. */
- HOW (R_PPC64_REL24, 2, 26, 0x03fffffc, 0, TRUE, signed,
+ HOW (R_PPC64_REL24, 2, 26, 0x03fffffc, 0, true, signed,
ppc64_elf_branch_reloc),
/* A variant of R_PPC64_REL24, used when r2 is not the toc pointer. */
- HOW (R_PPC64_REL24_NOTOC, 2, 26, 0x03fffffc, 0, TRUE, signed,
+ HOW (R_PPC64_REL24_NOTOC, 2, 26, 0x03fffffc, 0, true, signed,
ppc64_elf_branch_reloc),
/* A relative 16 bit branch; the lower two bits must be zero. */
- HOW (R_PPC64_REL14, 2, 16, 0x0000fffc, 0, TRUE, signed,
+ HOW (R_PPC64_REL14, 2, 16, 0x0000fffc, 0, true, signed,
ppc64_elf_branch_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_PPC64_REL14_BRTAKEN, 2, 16, 0x0000fffc, 0, TRUE, signed,
+ HOW (R_PPC64_REL14_BRTAKEN, 2, 16, 0x0000fffc, 0, true, signed,
ppc64_elf_brtaken_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_PPC64_REL14_BRNTAKEN, 2, 16, 0x0000fffc, 0, TRUE, signed,
+ HOW (R_PPC64_REL14_BRNTAKEN, 2, 16, 0x0000fffc, 0, true, signed,
ppc64_elf_brtaken_reloc),
/* Like R_PPC64_ADDR16, but referring to the GOT table entry for the
symbol. */
- HOW (R_PPC64_GOT16, 1, 16, 0xffff, 0, FALSE, signed,
+ HOW (R_PPC64_GOT16, 1, 16, 0xffff, 0, false, signed,
ppc64_elf_unhandled_reloc),
/* Like R_PPC64_ADDR16_LO, but referring to the GOT table entry for
the symbol. */
- HOW (R_PPC64_GOT16_LO, 1, 16, 0xffff, 0, FALSE, dont,
+ HOW (R_PPC64_GOT16_LO, 1, 16, 0xffff, 0, false, dont,
ppc64_elf_unhandled_reloc),
/* Like R_PPC64_ADDR16_HI, but referring to the GOT table entry for
the symbol. */
- HOW (R_PPC64_GOT16_HI, 1, 16, 0xffff, 16, FALSE, signed,
+ HOW (R_PPC64_GOT16_HI, 1, 16, 0xffff, 16, false, signed,
ppc64_elf_unhandled_reloc),
/* Like R_PPC64_ADDR16_HA, but referring to the GOT table entry for
the symbol. */
- HOW (R_PPC64_GOT16_HA, 1, 16, 0xffff, 16, FALSE, signed,
+ HOW (R_PPC64_GOT16_HA, 1, 16, 0xffff, 16, false, signed,
ppc64_elf_unhandled_reloc),
/* This is used only by the dynamic linker. The symbol should exist
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_PPC64_COPY, 0, 0, 0, 0, FALSE, dont,
+ HOW (R_PPC64_COPY, 0, 0, 0, 0, false, dont,
ppc64_elf_unhandled_reloc),
/* Like R_PPC64_ADDR64, but used when setting global offset table
entries. */
- HOW (R_PPC64_GLOB_DAT, 4, 64, 0xffffffffffffffffULL, 0, FALSE, dont,
+ HOW (R_PPC64_GLOB_DAT, 4, 64, 0xffffffffffffffffULL, 0, false, dont,
ppc64_elf_unhandled_reloc),
/* Created by the link editor. Marks a procedure linkage table
entry for a symbol. */
- HOW (R_PPC64_JMP_SLOT, 0, 0, 0, 0, FALSE, dont,
+ HOW (R_PPC64_JMP_SLOT, 0, 0, 0, 0, false, dont,
ppc64_elf_unhandled_reloc),
/* Used only by the dynamic linker. When the object is run, this
doubleword64 is set to the load address of the object, plus the
addend. */
- HOW (R_PPC64_RELATIVE, 4, 64, 0xffffffffffffffffULL, 0, FALSE, dont,
+ HOW (R_PPC64_RELATIVE, 4, 64, 0xffffffffffffffffULL, 0, false, dont,
bfd_elf_generic_reloc),
/* Like R_PPC64_ADDR32, but may be unaligned. */
- HOW (R_PPC64_UADDR32, 2, 32, 0xffffffff, 0, FALSE, bitfield,
+ HOW (R_PPC64_UADDR32, 2, 32, 0xffffffff, 0, false, bitfield,
bfd_elf_generic_reloc),
/* Like R_PPC64_ADDR16, but may be unaligned. */
- HOW (R_PPC64_UADDR16, 1, 16, 0xffff, 0, FALSE, bitfield,
+ HOW (R_PPC64_UADDR16, 1, 16, 0xffff, 0, false, bitfield,
bfd_elf_generic_reloc),
/* 32-bit PC relative. */
- HOW (R_PPC64_REL32, 2, 32, 0xffffffff, 0, TRUE, signed,
+ HOW (R_PPC64_REL32, 2, 32, 0xffffffff, 0, true, signed,
bfd_elf_generic_reloc),
/* 32-bit relocation to the symbol's procedure linkage table. */
- HOW (R_PPC64_PLT32, 2, 32, 0xffffffff, 0, FALSE, bitfield,
+ HOW (R_PPC64_PLT32, 2, 32, 0xffffffff, 0, false, bitfield,
ppc64_elf_unhandled_reloc),
/* 32-bit PC relative relocation to the symbol's procedure linkage table.
FIXME: R_PPC64_PLTREL32 not supported. */
- HOW (R_PPC64_PLTREL32, 2, 32, 0xffffffff, 0, TRUE, signed,
+ HOW (R_PPC64_PLTREL32, 2, 32, 0xffffffff, 0, true, signed,
ppc64_elf_unhandled_reloc),
/* Like R_PPC64_ADDR16_LO, but referring to the PLT table entry for
the symbol. */
- HOW (R_PPC64_PLT16_LO, 1, 16, 0xffff, 0, FALSE, dont,
+ HOW (R_PPC64_PLT16_LO, 1, 16, 0xffff, 0, false, dont,
ppc64_elf_unhandled_reloc),
/* Like R_PPC64_ADDR16_HI, but referring to the PLT table entry for
the symbol. */
- HOW (R_PPC64_PLT16_HI, 1, 16, 0xffff, 16, FALSE, signed,
+ HOW (R_PPC64_PLT16_HI, 1, 16, 0xffff, 16, false, signed,
ppc64_elf_unhandled_reloc),
/* Like R_PPC64_ADDR16_HA, but referring to the PLT table entry for
the symbol. */
- HOW (R_PPC64_PLT16_HA, 1, 16, 0xffff, 16, FALSE, signed,
+ HOW (R_PPC64_PLT16_HA, 1, 16, 0xffff, 16, false, signed,
ppc64_elf_unhandled_reloc),
/* 16-bit section relative relocation. */
- HOW (R_PPC64_SECTOFF, 1, 16, 0xffff, 0, FALSE, signed,
+ HOW (R_PPC64_SECTOFF, 1, 16, 0xffff, 0, false, signed,
ppc64_elf_sectoff_reloc),
/* Like R_PPC64_SECTOFF, but no overflow warning. */
- HOW (R_PPC64_SECTOFF_LO, 1, 16, 0xffff, 0, FALSE, dont,
+ HOW (R_PPC64_SECTOFF_LO, 1, 16, 0xffff, 0, false, dont,
ppc64_elf_sectoff_reloc),
/* 16-bit upper half section relative relocation. */
- HOW (R_PPC64_SECTOFF_HI, 1, 16, 0xffff, 16, FALSE, signed,
+ HOW (R_PPC64_SECTOFF_HI, 1, 16, 0xffff, 16, false, signed,
ppc64_elf_sectoff_reloc),
/* 16-bit upper half adjusted section relative relocation. */
- HOW (R_PPC64_SECTOFF_HA, 1, 16, 0xffff, 16, FALSE, signed,
+ HOW (R_PPC64_SECTOFF_HA, 1, 16, 0xffff, 16, false, signed,
ppc64_elf_sectoff_ha_reloc),
/* Like R_PPC64_REL24 without touching the two least significant bits. */
- HOW (R_PPC64_REL30, 2, 30, 0xfffffffc, 2, TRUE, dont,
+ HOW (R_PPC64_REL30, 2, 30, 0xfffffffc, 2, true, dont,
bfd_elf_generic_reloc),
/* Relocs in the 64-bit PowerPC ELF ABI, not in the 32-bit ABI. */
/* A standard 64-bit relocation. */
- HOW (R_PPC64_ADDR64, 4, 64, 0xffffffffffffffffULL, 0, FALSE, dont,
+ HOW (R_PPC64_ADDR64, 4, 64, 0xffffffffffffffffULL, 0, false, dont,
bfd_elf_generic_reloc),
/* The bits 32-47 of an address. */
- HOW (R_PPC64_ADDR16_HIGHER, 1, 16, 0xffff, 32, FALSE, dont,
+ HOW (R_PPC64_ADDR16_HIGHER, 1, 16, 0xffff, 32, false, dont,
bfd_elf_generic_reloc),
/* The bits 32-47 of an address, plus 1 if the contents of the low
16 bits, treated as a signed number, is negative. */
- HOW (R_PPC64_ADDR16_HIGHERA, 1, 16, 0xffff, 32, FALSE, dont,
+ HOW (R_PPC64_ADDR16_HIGHERA, 1, 16, 0xffff, 32, false, dont,
ppc64_elf_ha_reloc),
/* The bits 48-63 of an address. */
- HOW (R_PPC64_ADDR16_HIGHEST, 1, 16, 0xffff, 48, FALSE, dont,
+ HOW (R_PPC64_ADDR16_HIGHEST, 1, 16, 0xffff, 48, false, dont,
bfd_elf_generic_reloc),
/* The bits 48-63 of an address, plus 1 if the contents of the low
16 bits, treated as a signed number, is negative. */
- HOW (R_PPC64_ADDR16_HIGHESTA, 1, 16, 0xffff, 48, FALSE, dont,
+ HOW (R_PPC64_ADDR16_HIGHESTA, 1, 16, 0xffff, 48, false, dont,
ppc64_elf_ha_reloc),
/* Like ADDR64, but may be unaligned. */
- HOW (R_PPC64_UADDR64, 4, 64, 0xffffffffffffffffULL, 0, FALSE, dont,
+ HOW (R_PPC64_UADDR64, 4, 64, 0xffffffffffffffffULL, 0, false, dont,
bfd_elf_generic_reloc),
/* 64-bit relative relocation. */
- HOW (R_PPC64_REL64, 4, 64, 0xffffffffffffffffULL, 0, TRUE, dont,
+ HOW (R_PPC64_REL64, 4, 64, 0xffffffffffffffffULL, 0, true, dont,
bfd_elf_generic_reloc),
/* 64-bit relocation to the symbol's procedure linkage table. */
- HOW (R_PPC64_PLT64, 4, 64, 0xffffffffffffffffULL, 0, FALSE, dont,
+ HOW (R_PPC64_PLT64, 4, 64, 0xffffffffffffffffULL, 0, false, dont,
ppc64_elf_unhandled_reloc),
/* 64-bit PC relative relocation to the symbol's procedure linkage
table. */
/* FIXME: R_PPC64_PLTREL64 not supported. */
- HOW (R_PPC64_PLTREL64, 4, 64, 0xffffffffffffffffULL, 0, TRUE, dont,
+ HOW (R_PPC64_PLTREL64, 4, 64, 0xffffffffffffffffULL, 0, true, dont,
ppc64_elf_unhandled_reloc),
/* 16 bit TOC-relative relocation. */
/* R_PPC64_TOC16 47 half16* S + A - .TOC. */
- HOW (R_PPC64_TOC16, 1, 16, 0xffff, 0, FALSE, signed,
+ HOW (R_PPC64_TOC16, 1, 16, 0xffff, 0, false, signed,
ppc64_elf_toc_reloc),
/* 16 bit TOC-relative relocation without overflow. */
/* R_PPC64_TOC16_LO 48 half16 #lo (S + A - .TOC.) */
- HOW (R_PPC64_TOC16_LO, 1, 16, 0xffff, 0, FALSE, dont,
+ HOW (R_PPC64_TOC16_LO, 1, 16, 0xffff, 0, false, dont,
ppc64_elf_toc_reloc),
/* 16 bit TOC-relative relocation, high 16 bits. */
/* R_PPC64_TOC16_HI 49 half16 #hi (S + A - .TOC.) */
- HOW (R_PPC64_TOC16_HI, 1, 16, 0xffff, 16, FALSE, signed,
+ HOW (R_PPC64_TOC16_HI, 1, 16, 0xffff, 16, false, signed,
ppc64_elf_toc_reloc),
/* 16 bit TOC-relative relocation, high 16 bits, plus 1 if the
contents of the low 16 bits, treated as a signed number, is
negative. */
/* R_PPC64_TOC16_HA 50 half16 #ha (S + A - .TOC.) */
- HOW (R_PPC64_TOC16_HA, 1, 16, 0xffff, 16, FALSE, signed,
+ HOW (R_PPC64_TOC16_HA, 1, 16, 0xffff, 16, false, signed,
ppc64_elf_toc_ha_reloc),
/* 64-bit relocation; insert value of TOC base (.TOC.). */
/* R_PPC64_TOC 51 doubleword64 .TOC. */
- HOW (R_PPC64_TOC, 4, 64, 0xffffffffffffffffULL, 0, FALSE, dont,
+ HOW (R_PPC64_TOC, 4, 64, 0xffffffffffffffffULL, 0, false, dont,
ppc64_elf_toc64_reloc),
/* Like R_PPC64_GOT16, but also informs the link editor that the
The link editor may also skip all of this and just (c) emit a
R_PPC64_GLOB_DAT to tie the symbol to the GOT entry. */
/* FIXME: R_PPC64_PLTGOT16 not implemented. */
- HOW (R_PPC64_PLTGOT16, 1, 16, 0xffff, 0, FALSE,signed,
+ HOW (R_PPC64_PLTGOT16, 1, 16, 0xffff, 0, false,signed,
ppc64_elf_unhandled_reloc),
/* Like R_PPC64_PLTGOT16, but without overflow. */
/* FIXME: R_PPC64_PLTGOT16_LO not implemented. */
- HOW (R_PPC64_PLTGOT16_LO, 1, 16, 0xffff, 0, FALSE, dont,
+ HOW (R_PPC64_PLTGOT16_LO, 1, 16, 0xffff, 0, false, dont,
ppc64_elf_unhandled_reloc),
/* Like R_PPC64_PLT_GOT16, but using bits 16-31 of the address. */
/* FIXME: R_PPC64_PLTGOT16_HI not implemented. */
- HOW (R_PPC64_PLTGOT16_HI, 1, 16, 0xffff, 16, FALSE, signed,
+ HOW (R_PPC64_PLTGOT16_HI, 1, 16, 0xffff, 16, false, signed,
ppc64_elf_unhandled_reloc),
/* Like R_PPC64_PLT_GOT16, but using bits 16-31 of the address, plus
1 if the contents of the low 16 bits, treated as a signed number,
is negative. */
/* FIXME: R_PPC64_PLTGOT16_HA not implemented. */
- HOW (R_PPC64_PLTGOT16_HA, 1, 16, 0xffff, 16, FALSE, signed,
+ HOW (R_PPC64_PLTGOT16_HA, 1, 16, 0xffff, 16, false, signed,
ppc64_elf_unhandled_reloc),
/* Like R_PPC64_ADDR16, but for instructions with a DS field. */
- HOW (R_PPC64_ADDR16_DS, 1, 16, 0xfffc, 0, FALSE, signed,
+ HOW (R_PPC64_ADDR16_DS, 1, 16, 0xfffc, 0, false, signed,
bfd_elf_generic_reloc),
/* Like R_PPC64_ADDR16_LO, but for instructions with a DS field. */
- HOW (R_PPC64_ADDR16_LO_DS, 1, 16, 0xfffc, 0, FALSE, dont,
+ HOW (R_PPC64_ADDR16_LO_DS, 1, 16, 0xfffc, 0, false, dont,
bfd_elf_generic_reloc),
/* Like R_PPC64_GOT16, but for instructions with a DS field. */
- HOW (R_PPC64_GOT16_DS, 1, 16, 0xfffc, 0, FALSE, signed,
+ HOW (R_PPC64_GOT16_DS, 1, 16, 0xfffc, 0, false, signed,
ppc64_elf_unhandled_reloc),
/* Like R_PPC64_GOT16_LO, but for instructions with a DS field. */
- HOW (R_PPC64_GOT16_LO_DS, 1, 16, 0xfffc, 0, FALSE, dont,
+ HOW (R_PPC64_GOT16_LO_DS, 1, 16, 0xfffc, 0, false, dont,
ppc64_elf_unhandled_reloc),
/* Like R_PPC64_PLT16_LO, but for instructions with a DS field. */
- HOW (R_PPC64_PLT16_LO_DS, 1, 16, 0xfffc, 0, FALSE, dont,
+ HOW (R_PPC64_PLT16_LO_DS, 1, 16, 0xfffc, 0, false, dont,
ppc64_elf_unhandled_reloc),
/* Like R_PPC64_SECTOFF, but for instructions with a DS field. */
- HOW (R_PPC64_SECTOFF_DS, 1, 16, 0xfffc, 0, FALSE, signed,
+ HOW (R_PPC64_SECTOFF_DS, 1, 16, 0xfffc, 0, false, signed,
ppc64_elf_sectoff_reloc),
/* Like R_PPC64_SECTOFF_LO, but for instructions with a DS field. */
- HOW (R_PPC64_SECTOFF_LO_DS, 1, 16, 0xfffc, 0, FALSE, dont,
+ HOW (R_PPC64_SECTOFF_LO_DS, 1, 16, 0xfffc, 0, false, dont,
ppc64_elf_sectoff_reloc),
/* Like R_PPC64_TOC16, but for instructions with a DS field. */
- HOW (R_PPC64_TOC16_DS, 1, 16, 0xfffc, 0, FALSE, signed,
+ HOW (R_PPC64_TOC16_DS, 1, 16, 0xfffc, 0, false, signed,
ppc64_elf_toc_reloc),
/* Like R_PPC64_TOC16_LO, but for instructions with a DS field. */
- HOW (R_PPC64_TOC16_LO_DS, 1, 16, 0xfffc, 0, FALSE, dont,
+ HOW (R_PPC64_TOC16_LO_DS, 1, 16, 0xfffc, 0, false, dont,
ppc64_elf_toc_reloc),
/* Like R_PPC64_PLTGOT16, but for instructions with a DS field. */
/* FIXME: R_PPC64_PLTGOT16_DS not implemented. */
- HOW (R_PPC64_PLTGOT16_DS, 1, 16, 0xfffc, 0, FALSE, signed,
+ HOW (R_PPC64_PLTGOT16_DS, 1, 16, 0xfffc, 0, false, signed,
ppc64_elf_unhandled_reloc),
/* Like R_PPC64_PLTGOT16_LO, but for instructions with a DS field. */
/* FIXME: R_PPC64_PLTGOT16_LO not implemented. */
- HOW (R_PPC64_PLTGOT16_LO_DS, 1, 16, 0xfffc, 0, FALSE, dont,
+ HOW (R_PPC64_PLTGOT16_LO_DS, 1, 16, 0xfffc, 0, false, dont,
ppc64_elf_unhandled_reloc),
/* Marker relocs for TLS. */
- HOW (R_PPC64_TLS, 2, 32, 0, 0, FALSE, dont,
+ HOW (R_PPC64_TLS, 2, 32, 0, 0, false, dont,
bfd_elf_generic_reloc),
- HOW (R_PPC64_TLSGD, 2, 32, 0, 0, FALSE, dont,
+ HOW (R_PPC64_TLSGD, 2, 32, 0, 0, false, dont,
bfd_elf_generic_reloc),
- HOW (R_PPC64_TLSLD, 2, 32, 0, 0, FALSE, dont,
+ HOW (R_PPC64_TLSLD, 2, 32, 0, 0, false, dont,
bfd_elf_generic_reloc),
/* Marker reloc for optimizing r2 save in prologue rather than on
each plt call stub. */
- HOW (R_PPC64_TOCSAVE, 2, 32, 0, 0, FALSE, dont,
+ HOW (R_PPC64_TOCSAVE, 2, 32, 0, 0, false, dont,
bfd_elf_generic_reloc),
/* Marker relocs on inline plt call instructions. */
- HOW (R_PPC64_PLTSEQ, 2, 32, 0, 0, FALSE, dont,
+ HOW (R_PPC64_PLTSEQ, 2, 32, 0, 0, false, dont,
bfd_elf_generic_reloc),
- HOW (R_PPC64_PLTCALL, 2, 32, 0, 0, FALSE, dont,
+ HOW (R_PPC64_PLTCALL, 2, 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_PPC64_DTPMOD64, 4, 64, 0xffffffffffffffffULL, 0, FALSE, dont,
+ HOW (R_PPC64_DTPMOD64, 4, 64, 0xffffffffffffffffULL, 0, false, dont,
ppc64_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_PPC64_DTPREL64, 4, 64, 0xffffffffffffffffULL, 0, FALSE, dont,
+ HOW (R_PPC64_DTPREL64, 4, 64, 0xffffffffffffffffULL, 0, false, dont,
ppc64_elf_unhandled_reloc),
/* A 16 bit dtprel reloc. */
- HOW (R_PPC64_DTPREL16, 1, 16, 0xffff, 0, FALSE, signed,
+ HOW (R_PPC64_DTPREL16, 1, 16, 0xffff, 0, false, signed,
ppc64_elf_unhandled_reloc),
/* Like DTPREL16, but no overflow. */
- HOW (R_PPC64_DTPREL16_LO, 1, 16, 0xffff, 0, FALSE, dont,
+ HOW (R_PPC64_DTPREL16_LO, 1, 16, 0xffff, 0, false, dont,
ppc64_elf_unhandled_reloc),
/* Like DTPREL16_LO, but next higher group of 16 bits. */
- HOW (R_PPC64_DTPREL16_HI, 1, 16, 0xffff, 16, FALSE, signed,
+ HOW (R_PPC64_DTPREL16_HI, 1, 16, 0xffff, 16, false, signed,
ppc64_elf_unhandled_reloc),
/* Like DTPREL16_HI, but adjust for low 16 bits. */
- HOW (R_PPC64_DTPREL16_HA, 1, 16, 0xffff, 16, FALSE, signed,
+ HOW (R_PPC64_DTPREL16_HA, 1, 16, 0xffff, 16, false, signed,
ppc64_elf_unhandled_reloc),
/* Like DTPREL16_HI, but next higher group of 16 bits. */
- HOW (R_PPC64_DTPREL16_HIGHER, 1, 16, 0xffff, 32, FALSE, dont,
+ HOW (R_PPC64_DTPREL16_HIGHER, 1, 16, 0xffff, 32, false, dont,
ppc64_elf_unhandled_reloc),
/* Like DTPREL16_HIGHER, but adjust for low 16 bits. */
- HOW (R_PPC64_DTPREL16_HIGHERA, 1, 16, 0xffff, 32, FALSE, dont,
+ HOW (R_PPC64_DTPREL16_HIGHERA, 1, 16, 0xffff, 32, false, dont,
ppc64_elf_unhandled_reloc),
/* Like DTPREL16_HIGHER, but next higher group of 16 bits. */
- HOW (R_PPC64_DTPREL16_HIGHEST, 1, 16, 0xffff, 48, FALSE, dont,
+ HOW (R_PPC64_DTPREL16_HIGHEST, 1, 16, 0xffff, 48, false, dont,
ppc64_elf_unhandled_reloc),
/* Like DTPREL16_HIGHEST, but adjust for low 16 bits. */
- HOW (R_PPC64_DTPREL16_HIGHESTA, 1, 16, 0xffff, 48, FALSE, dont,
+ HOW (R_PPC64_DTPREL16_HIGHESTA, 1, 16, 0xffff, 48, false, dont,
ppc64_elf_unhandled_reloc),
/* Like DTPREL16, but for insns with a DS field. */
- HOW (R_PPC64_DTPREL16_DS, 1, 16, 0xfffc, 0, FALSE, signed,
+ HOW (R_PPC64_DTPREL16_DS, 1, 16, 0xfffc, 0, false, signed,
ppc64_elf_unhandled_reloc),
/* Like DTPREL16_DS, but no overflow. */
- HOW (R_PPC64_DTPREL16_LO_DS, 1, 16, 0xfffc, 0, FALSE, dont,
+ HOW (R_PPC64_DTPREL16_LO_DS, 1, 16, 0xfffc, 0, false, dont,
ppc64_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_PPC64_TPREL64, 4, 64, 0xffffffffffffffffULL, 0, FALSE, dont,
+ HOW (R_PPC64_TPREL64, 4, 64, 0xffffffffffffffffULL, 0, false, dont,
ppc64_elf_unhandled_reloc),
/* A 16 bit tprel reloc. */
- HOW (R_PPC64_TPREL16, 1, 16, 0xffff, 0, FALSE, signed,
+ HOW (R_PPC64_TPREL16, 1, 16, 0xffff, 0, false, signed,
ppc64_elf_unhandled_reloc),
/* Like TPREL16, but no overflow. */
- HOW (R_PPC64_TPREL16_LO, 1, 16, 0xffff, 0, FALSE, dont,
+ HOW (R_PPC64_TPREL16_LO, 1, 16, 0xffff, 0, false, dont,
ppc64_elf_unhandled_reloc),
/* Like TPREL16_LO, but next higher group of 16 bits. */
- HOW (R_PPC64_TPREL16_HI, 1, 16, 0xffff, 16, FALSE, signed,
+ HOW (R_PPC64_TPREL16_HI, 1, 16, 0xffff, 16, false, signed,
ppc64_elf_unhandled_reloc),
/* Like TPREL16_HI, but adjust for low 16 bits. */
- HOW (R_PPC64_TPREL16_HA, 1, 16, 0xffff, 16, FALSE, signed,
+ HOW (R_PPC64_TPREL16_HA, 1, 16, 0xffff, 16, false, signed,
ppc64_elf_unhandled_reloc),
/* Like TPREL16_HI, but next higher group of 16 bits. */
- HOW (R_PPC64_TPREL16_HIGHER, 1, 16, 0xffff, 32, FALSE, dont,
+ HOW (R_PPC64_TPREL16_HIGHER, 1, 16, 0xffff, 32, false, dont,
ppc64_elf_unhandled_reloc),
/* Like TPREL16_HIGHER, but adjust for low 16 bits. */
- HOW (R_PPC64_TPREL16_HIGHERA, 1, 16, 0xffff, 32, FALSE, dont,
+ HOW (R_PPC64_TPREL16_HIGHERA, 1, 16, 0xffff, 32, false, dont,
ppc64_elf_unhandled_reloc),
/* Like TPREL16_HIGHER, but next higher group of 16 bits. */
- HOW (R_PPC64_TPREL16_HIGHEST, 1, 16, 0xffff, 48, FALSE, dont,
+ HOW (R_PPC64_TPREL16_HIGHEST, 1, 16, 0xffff, 48, false, dont,
ppc64_elf_unhandled_reloc),
/* Like TPREL16_HIGHEST, but adjust for low 16 bits. */
- HOW (R_PPC64_TPREL16_HIGHESTA, 1, 16, 0xffff, 48, FALSE, dont,
+ HOW (R_PPC64_TPREL16_HIGHESTA, 1, 16, 0xffff, 48, false, dont,
ppc64_elf_unhandled_reloc),
/* Like TPREL16, but for insns with a DS field. */
- HOW (R_PPC64_TPREL16_DS, 1, 16, 0xfffc, 0, FALSE, signed,
+ HOW (R_PPC64_TPREL16_DS, 1, 16, 0xfffc, 0, false, signed,
ppc64_elf_unhandled_reloc),
/* Like TPREL16_DS, but no overflow. */
- HOW (R_PPC64_TPREL16_LO_DS, 1, 16, 0xfffc, 0, FALSE, dont,
+ HOW (R_PPC64_TPREL16_LO_DS, 1, 16, 0xfffc, 0, false, dont,
ppc64_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 relative to the TOC base (r2). */
- HOW (R_PPC64_GOT_TLSGD16, 1, 16, 0xffff, 0, FALSE, signed,
+ HOW (R_PPC64_GOT_TLSGD16, 1, 16, 0xffff, 0, false, signed,
ppc64_elf_unhandled_reloc),
/* Like GOT_TLSGD16, but no overflow. */
- HOW (R_PPC64_GOT_TLSGD16_LO, 1, 16, 0xffff, 0, FALSE, dont,
+ HOW (R_PPC64_GOT_TLSGD16_LO, 1, 16, 0xffff, 0, false, dont,
ppc64_elf_unhandled_reloc),
/* Like GOT_TLSGD16_LO, but next higher group of 16 bits. */
- HOW (R_PPC64_GOT_TLSGD16_HI, 1, 16, 0xffff, 16, FALSE, signed,
+ HOW (R_PPC64_GOT_TLSGD16_HI, 1, 16, 0xffff, 16, false, signed,
ppc64_elf_unhandled_reloc),
/* Like GOT_TLSGD16_HI, but adjust for low 16 bits. */
- HOW (R_PPC64_GOT_TLSGD16_HA, 1, 16, 0xffff, 16, FALSE, signed,
+ HOW (R_PPC64_GOT_TLSGD16_HA, 1, 16, 0xffff, 16, false, signed,
ppc64_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 relative to the TOC base (r2). */
- HOW (R_PPC64_GOT_TLSLD16, 1, 16, 0xffff, 0, FALSE, signed,
+ HOW (R_PPC64_GOT_TLSLD16, 1, 16, 0xffff, 0, false, signed,
ppc64_elf_unhandled_reloc),
/* Like GOT_TLSLD16, but no overflow. */
- HOW (R_PPC64_GOT_TLSLD16_LO, 1, 16, 0xffff, 0, FALSE, dont,
+ HOW (R_PPC64_GOT_TLSLD16_LO, 1, 16, 0xffff, 0, false, dont,
ppc64_elf_unhandled_reloc),
/* Like GOT_TLSLD16_LO, but next higher group of 16 bits. */
- HOW (R_PPC64_GOT_TLSLD16_HI, 1, 16, 0xffff, 16, FALSE, signed,
+ HOW (R_PPC64_GOT_TLSLD16_HI, 1, 16, 0xffff, 16, false, signed,
ppc64_elf_unhandled_reloc),
/* Like GOT_TLSLD16_HI, but adjust for low 16 bits. */
- HOW (R_PPC64_GOT_TLSLD16_HA, 1, 16, 0xffff, 16, FALSE, signed,
+ HOW (R_PPC64_GOT_TLSLD16_HA, 1, 16, 0xffff, 16, false, signed,
ppc64_elf_unhandled_reloc),
/* Allocates an entry in the GOT with value (sym+add)@dtprel, and computes
the offset to the entry relative to the TOC base (r2). */
- HOW (R_PPC64_GOT_DTPREL16_DS, 1, 16, 0xfffc, 0, FALSE, signed,
+ HOW (R_PPC64_GOT_DTPREL16_DS, 1, 16, 0xfffc, 0, false, signed,
ppc64_elf_unhandled_reloc),
/* Like GOT_DTPREL16_DS, but no overflow. */
- HOW (R_PPC64_GOT_DTPREL16_LO_DS, 1, 16, 0xfffc, 0, FALSE, dont,
+ HOW (R_PPC64_GOT_DTPREL16_LO_DS, 1, 16, 0xfffc, 0, false, dont,
ppc64_elf_unhandled_reloc),
/* Like GOT_DTPREL16_LO_DS, but next higher group of 16 bits. */
- HOW (R_PPC64_GOT_DTPREL16_HI, 1, 16, 0xffff, 16, FALSE, signed,
+ HOW (R_PPC64_GOT_DTPREL16_HI, 1, 16, 0xffff, 16, false, signed,
ppc64_elf_unhandled_reloc),
/* Like GOT_DTPREL16_HI, but adjust for low 16 bits. */
- HOW (R_PPC64_GOT_DTPREL16_HA, 1, 16, 0xffff, 16, FALSE, signed,
+ HOW (R_PPC64_GOT_DTPREL16_HA, 1, 16, 0xffff, 16, false, signed,
ppc64_elf_unhandled_reloc),
/* Allocates an entry in the GOT with value (sym+add)@tprel, and computes the
offset to the entry relative to the TOC base (r2). */
- HOW (R_PPC64_GOT_TPREL16_DS, 1, 16, 0xfffc, 0, FALSE, signed,
+ HOW (R_PPC64_GOT_TPREL16_DS, 1, 16, 0xfffc, 0, false, signed,
ppc64_elf_unhandled_reloc),
/* Like GOT_TPREL16_DS, but no overflow. */
- HOW (R_PPC64_GOT_TPREL16_LO_DS, 1, 16, 0xfffc, 0, FALSE, dont,
+ HOW (R_PPC64_GOT_TPREL16_LO_DS, 1, 16, 0xfffc, 0, false, dont,
ppc64_elf_unhandled_reloc),
/* Like GOT_TPREL16_LO_DS, but next higher group of 16 bits. */
- HOW (R_PPC64_GOT_TPREL16_HI, 1, 16, 0xffff, 16, FALSE, signed,
+ HOW (R_PPC64_GOT_TPREL16_HI, 1, 16, 0xffff, 16, false, signed,
ppc64_elf_unhandled_reloc),
/* Like GOT_TPREL16_HI, but adjust for low 16 bits. */
- HOW (R_PPC64_GOT_TPREL16_HA, 1, 16, 0xffff, 16, FALSE, signed,
+ HOW (R_PPC64_GOT_TPREL16_HA, 1, 16, 0xffff, 16, false, signed,
ppc64_elf_unhandled_reloc),
- HOW (R_PPC64_JMP_IREL, 0, 0, 0, 0, FALSE, dont,
+ HOW (R_PPC64_JMP_IREL, 0, 0, 0, 0, false, dont,
ppc64_elf_unhandled_reloc),
- HOW (R_PPC64_IRELATIVE, 4, 64, 0xffffffffffffffffULL, 0, FALSE, dont,
+ HOW (R_PPC64_IRELATIVE, 4, 64, 0xffffffffffffffffULL, 0, false, dont,
bfd_elf_generic_reloc),
/* A 16 bit relative relocation. */
- HOW (R_PPC64_REL16, 1, 16, 0xffff, 0, TRUE, signed,
+ HOW (R_PPC64_REL16, 1, 16, 0xffff, 0, true, signed,
bfd_elf_generic_reloc),
/* A 16 bit relative relocation without overflow. */
- HOW (R_PPC64_REL16_LO, 1, 16, 0xffff, 0, TRUE, dont,
+ HOW (R_PPC64_REL16_LO, 1, 16, 0xffff, 0, true, dont,
bfd_elf_generic_reloc),
/* The high order 16 bits of a relative address. */
- HOW (R_PPC64_REL16_HI, 1, 16, 0xffff, 16, TRUE, signed,
+ HOW (R_PPC64_REL16_HI, 1, 16, 0xffff, 16, true, signed,
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_PPC64_REL16_HA, 1, 16, 0xffff, 16, TRUE, signed,
+ HOW (R_PPC64_REL16_HA, 1, 16, 0xffff, 16, true, signed,
ppc64_elf_ha_reloc),
- HOW (R_PPC64_REL16_HIGH, 1, 16, 0xffff, 16, TRUE, dont,
+ HOW (R_PPC64_REL16_HIGH, 1, 16, 0xffff, 16, true, dont,
bfd_elf_generic_reloc),
- HOW (R_PPC64_REL16_HIGHA, 1, 16, 0xffff, 16, TRUE, dont,
+ HOW (R_PPC64_REL16_HIGHA, 1, 16, 0xffff, 16, true, dont,
ppc64_elf_ha_reloc),
- HOW (R_PPC64_REL16_HIGHER, 1, 16, 0xffff, 32, TRUE, dont,
+ HOW (R_PPC64_REL16_HIGHER, 1, 16, 0xffff, 32, true, dont,
bfd_elf_generic_reloc),
- HOW (R_PPC64_REL16_HIGHERA, 1, 16, 0xffff, 32, TRUE, dont,
+ HOW (R_PPC64_REL16_HIGHERA, 1, 16, 0xffff, 32, true, dont,
ppc64_elf_ha_reloc),
- HOW (R_PPC64_REL16_HIGHEST, 1, 16, 0xffff, 48, TRUE, dont,
+ HOW (R_PPC64_REL16_HIGHEST, 1, 16, 0xffff, 48, true, dont,
bfd_elf_generic_reloc),
- HOW (R_PPC64_REL16_HIGHESTA, 1, 16, 0xffff, 48, TRUE, dont,
+ HOW (R_PPC64_REL16_HIGHESTA, 1, 16, 0xffff, 48, true, dont,
ppc64_elf_ha_reloc),
/* Like R_PPC64_REL16_HA but for split field in addpcis. */
- HOW (R_PPC64_REL16DX_HA, 2, 16, 0x1fffc1, 16, TRUE, signed,
+ HOW (R_PPC64_REL16DX_HA, 2, 16, 0x1fffc1, 16, true, signed,
ppc64_elf_ha_reloc),
/* A split-field reloc for addpcis, non-relative (gas internal use only). */
- HOW (R_PPC64_16DX_HA, 2, 16, 0x1fffc1, 16, FALSE, signed,
+ HOW (R_PPC64_16DX_HA, 2, 16, 0x1fffc1, 16, false, signed,
ppc64_elf_ha_reloc),
/* Like R_PPC64_ADDR16_HI, but no overflow. */
- HOW (R_PPC64_ADDR16_HIGH, 1, 16, 0xffff, 16, FALSE, dont,
+ HOW (R_PPC64_ADDR16_HIGH, 1, 16, 0xffff, 16, false, dont,
bfd_elf_generic_reloc),
/* Like R_PPC64_ADDR16_HA, but no overflow. */
- HOW (R_PPC64_ADDR16_HIGHA, 1, 16, 0xffff, 16, FALSE, dont,
+ HOW (R_PPC64_ADDR16_HIGHA, 1, 16, 0xffff, 16, false, dont,
ppc64_elf_ha_reloc),
/* Like R_PPC64_DTPREL16_HI, but no overflow. */
- HOW (R_PPC64_DTPREL16_HIGH, 1, 16, 0xffff, 16, FALSE, dont,
+ HOW (R_PPC64_DTPREL16_HIGH, 1, 16, 0xffff, 16, false, dont,
ppc64_elf_unhandled_reloc),
/* Like R_PPC64_DTPREL16_HA, but no overflow. */
- HOW (R_PPC64_DTPREL16_HIGHA, 1, 16, 0xffff, 16, FALSE, dont,
+ HOW (R_PPC64_DTPREL16_HIGHA, 1, 16, 0xffff, 16, false, dont,
ppc64_elf_unhandled_reloc),
/* Like R_PPC64_TPREL16_HI, but no overflow. */
- HOW (R_PPC64_TPREL16_HIGH, 1, 16, 0xffff, 16, FALSE, dont,
+ HOW (R_PPC64_TPREL16_HIGH, 1, 16, 0xffff, 16, false, dont,
ppc64_elf_unhandled_reloc),
/* Like R_PPC64_TPREL16_HA, but no overflow. */
- HOW (R_PPC64_TPREL16_HIGHA, 1, 16, 0xffff, 16, FALSE, dont,
+ HOW (R_PPC64_TPREL16_HIGHA, 1, 16, 0xffff, 16, false, dont,
ppc64_elf_unhandled_reloc),
/* Marker reloc on ELFv2 large-model function entry. */
- HOW (R_PPC64_ENTRY, 2, 32, 0, 0, FALSE, dont,
+ HOW (R_PPC64_ENTRY, 2, 32, 0, 0, false, dont,
bfd_elf_generic_reloc),
/* Like ADDR64, but use local entry point of function. */
- HOW (R_PPC64_ADDR64_LOCAL, 4, 64, 0xffffffffffffffffULL, 0, FALSE, dont,
+ HOW (R_PPC64_ADDR64_LOCAL, 4, 64, 0xffffffffffffffffULL, 0, false, dont,
bfd_elf_generic_reloc),
- HOW (R_PPC64_PLTSEQ_NOTOC, 2, 32, 0, 0, FALSE, dont,
+ HOW (R_PPC64_PLTSEQ_NOTOC, 2, 32, 0, 0, false, dont,
bfd_elf_generic_reloc),
- HOW (R_PPC64_PLTCALL_NOTOC, 2, 32, 0, 0, FALSE, dont,
+ HOW (R_PPC64_PLTCALL_NOTOC, 2, 32, 0, 0, false, dont,
bfd_elf_generic_reloc),
- HOW (R_PPC64_PCREL_OPT, 2, 32, 0, 0, FALSE, dont,
+ HOW (R_PPC64_PCREL_OPT, 2, 32, 0, 0, false, dont,
bfd_elf_generic_reloc),
- HOW (R_PPC64_D34, 4, 34, 0x3ffff0000ffffULL, 0, FALSE, signed,
+ HOW (R_PPC64_D34, 4, 34, 0x3ffff0000ffffULL, 0, false, signed,
ppc64_elf_prefix_reloc),
- HOW (R_PPC64_D34_LO, 4, 34, 0x3ffff0000ffffULL, 0, FALSE, dont,
+ HOW (R_PPC64_D34_LO, 4, 34, 0x3ffff0000ffffULL, 0, false, dont,
ppc64_elf_prefix_reloc),
- HOW (R_PPC64_D34_HI30, 4, 34, 0x3ffff0000ffffULL, 34, FALSE, dont,
+ HOW (R_PPC64_D34_HI30, 4, 34, 0x3ffff0000ffffULL, 34, false, dont,
ppc64_elf_prefix_reloc),
- HOW (R_PPC64_D34_HA30, 4, 34, 0x3ffff0000ffffULL, 34, FALSE, dont,
+ HOW (R_PPC64_D34_HA30, 4, 34, 0x3ffff0000ffffULL, 34, false, dont,
ppc64_elf_prefix_reloc),
- HOW (R_PPC64_PCREL34, 4, 34, 0x3ffff0000ffffULL, 0, TRUE, signed,
+ HOW (R_PPC64_PCREL34, 4, 34, 0x3ffff0000ffffULL, 0, true, signed,
ppc64_elf_prefix_reloc),
- HOW (R_PPC64_GOT_PCREL34, 4, 34, 0x3ffff0000ffffULL, 0, TRUE, signed,
+ HOW (R_PPC64_GOT_PCREL34, 4, 34, 0x3ffff0000ffffULL, 0, true, signed,
ppc64_elf_unhandled_reloc),
- HOW (R_PPC64_PLT_PCREL34, 4, 34, 0x3ffff0000ffffULL, 0, TRUE, signed,
+ HOW (R_PPC64_PLT_PCREL34, 4, 34, 0x3ffff0000ffffULL, 0, true, signed,
ppc64_elf_unhandled_reloc),
- HOW (R_PPC64_PLT_PCREL34_NOTOC, 4, 34, 0x3ffff0000ffffULL, 0, TRUE, signed,
+ HOW (R_PPC64_PLT_PCREL34_NOTOC, 4, 34, 0x3ffff0000ffffULL, 0, true, signed,
ppc64_elf_unhandled_reloc),
- HOW (R_PPC64_TPREL34, 4, 34, 0x3ffff0000ffffULL, 0, FALSE, signed,
+ HOW (R_PPC64_TPREL34, 4, 34, 0x3ffff0000ffffULL, 0, false, signed,
ppc64_elf_unhandled_reloc),
- HOW (R_PPC64_DTPREL34, 4, 34, 0x3ffff0000ffffULL, 0, FALSE, signed,
+ HOW (R_PPC64_DTPREL34, 4, 34, 0x3ffff0000ffffULL, 0, false, signed,
ppc64_elf_unhandled_reloc),
- HOW (R_PPC64_GOT_TLSGD_PCREL34, 4, 34, 0x3ffff0000ffffULL, 0, TRUE, signed,
+ HOW (R_PPC64_GOT_TLSGD_PCREL34, 4, 34, 0x3ffff0000ffffULL, 0, true, signed,
ppc64_elf_unhandled_reloc),
- HOW (R_PPC64_GOT_TLSLD_PCREL34, 4, 34, 0x3ffff0000ffffULL, 0, TRUE, signed,
+ HOW (R_PPC64_GOT_TLSLD_PCREL34, 4, 34, 0x3ffff0000ffffULL, 0, true, signed,
ppc64_elf_unhandled_reloc),
- HOW (R_PPC64_GOT_TPREL_PCREL34, 4, 34, 0x3ffff0000ffffULL, 0, TRUE, signed,
+ HOW (R_PPC64_GOT_TPREL_PCREL34, 4, 34, 0x3ffff0000ffffULL, 0, true, signed,
ppc64_elf_unhandled_reloc),
- HOW (R_PPC64_GOT_DTPREL_PCREL34, 4, 34, 0x3ffff0000ffffULL, 0, TRUE, signed,
+ HOW (R_PPC64_GOT_DTPREL_PCREL34, 4, 34, 0x3ffff0000ffffULL, 0, true, signed,
ppc64_elf_unhandled_reloc),
- HOW (R_PPC64_ADDR16_HIGHER34, 1, 16, 0xffff, 34, FALSE, dont,
+ HOW (R_PPC64_ADDR16_HIGHER34, 1, 16, 0xffff, 34, false, dont,
bfd_elf_generic_reloc),
- HOW (R_PPC64_ADDR16_HIGHERA34, 1, 16, 0xffff, 34, FALSE, dont,
+ HOW (R_PPC64_ADDR16_HIGHERA34, 1, 16, 0xffff, 34, false, dont,
ppc64_elf_ha_reloc),
- HOW (R_PPC64_ADDR16_HIGHEST34, 1, 16, 0xffff, 50, FALSE, dont,
+ HOW (R_PPC64_ADDR16_HIGHEST34, 1, 16, 0xffff, 50, false, dont,
bfd_elf_generic_reloc),
- HOW (R_PPC64_ADDR16_HIGHESTA34, 1, 16, 0xffff, 50, FALSE, dont,
+ HOW (R_PPC64_ADDR16_HIGHESTA34, 1, 16, 0xffff, 50, false, dont,
ppc64_elf_ha_reloc),
- HOW (R_PPC64_REL16_HIGHER34, 1, 16, 0xffff, 34, TRUE, dont,
+ HOW (R_PPC64_REL16_HIGHER34, 1, 16, 0xffff, 34, true, dont,
bfd_elf_generic_reloc),
- HOW (R_PPC64_REL16_HIGHERA34, 1, 16, 0xffff, 34, TRUE, dont,
+ HOW (R_PPC64_REL16_HIGHERA34, 1, 16, 0xffff, 34, true, dont,
ppc64_elf_ha_reloc),
- HOW (R_PPC64_REL16_HIGHEST34, 1, 16, 0xffff, 50, TRUE, dont,
+ HOW (R_PPC64_REL16_HIGHEST34, 1, 16, 0xffff, 50, true, dont,
bfd_elf_generic_reloc),
- HOW (R_PPC64_REL16_HIGHESTA34, 1, 16, 0xffff, 50, TRUE, dont,
+ HOW (R_PPC64_REL16_HIGHESTA34, 1, 16, 0xffff, 50, true, dont,
ppc64_elf_ha_reloc),
- HOW (R_PPC64_D28, 4, 28, 0xfff0000ffffULL, 0, FALSE, signed,
+ HOW (R_PPC64_D28, 4, 28, 0xfff0000ffffULL, 0, false, signed,
ppc64_elf_prefix_reloc),
- HOW (R_PPC64_PCREL28, 4, 28, 0xfff0000ffffULL, 0, TRUE, signed,
+ HOW (R_PPC64_PCREL28, 4, 28, 0xfff0000ffffULL, 0, true, signed,
ppc64_elf_prefix_reloc),
/* GNU extension to record C++ vtable hierarchy. */
- HOW (R_PPC64_GNU_VTINHERIT, 0, 0, 0, 0, FALSE, dont,
+ HOW (R_PPC64_GNU_VTINHERIT, 0, 0, 0, 0, false, dont,
NULL),
/* GNU extension to record C++ vtable member usage. */
- HOW (R_PPC64_GNU_VTENTRY, 0, 0, 0, 0, FALSE, dont,
+ HOW (R_PPC64_GNU_VTENTRY, 0, 0, 0, 0, false, dont,
NULL),
};
/* Set the howto pointer for a PowerPC ELF reloc. */
-static bfd_boolean
+static bool
ppc64_elf_info_to_howto (bfd *abfd, arelent *cache_ptr,
Elf_Internal_Rela *dst)
{
_bfd_error_handler (_("%pB: unsupported relocation type %#x"),
abfd, type);
bfd_set_error (bfd_error_bad_value);
- return FALSE;
+ return false;
}
cache_ptr->howto = ppc64_elf_howto_table[type];
if (cache_ptr->howto == NULL || cache_ptr->howto->name == NULL)
_bfd_error_handler (_("%pB: unsupported relocation type %#x"),
abfd, type);
bfd_set_error (bfd_error_bad_value);
- return FALSE;
+ return false;
}
- return TRUE;
+ return true;
}
/* Handle the R_PPC64_ADDR16_HA and similar relocs. */
{
bfd_vma dest = opd_entry_value (symbol->section,
symbol->value + reloc_entry->addend,
- NULL, NULL, FALSE);
+ NULL, NULL, false);
if (dest != (bfd_vma) -1)
reloc_entry->addend = dest - (symbol->value
+ symbol->section->output_section->vma
enum elf_ppc64_reloc_type r_type;
bfd_size_type octets;
/* Assume 'at' branch hints. */
- bfd_boolean is_isa_v2 = TRUE;
+ bool is_isa_v2 = true;
/* If this is a relocatable link (output_bfd test tells us), just
call the generic function. Any adjustment will be done at final
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;
}
/* Override the generic function because we store some extras. */
-static bfd_boolean
+static bool
ppc64_elf_mkobject (bfd *abfd)
{
return bfd_elf_allocate_object (abfd, sizeof (struct ppc64_elf_obj_tdata),
/* Fix bad default arch selected for a 64 bit input bfd when the
default is 32 bit. Also select arch based on apuinfo. */
-static bfd_boolean
+static bool
ppc64_elf_object_p (bfd *abfd)
{
if (!abfd->arch_info->the_default)
- return TRUE;
+ return true;
if (abfd->arch_info->bits_per_word == 32)
{
/* Support for core dump NOTE sections. */
-static bfd_boolean
+static bool
ppc64_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
{
size_t offset, size;
if (note->descsz != 504)
- return FALSE;
+ return false;
/* pr_cursig */
elf_tdata (abfd)->core->signal = bfd_get_16 (abfd, note->descdata + 12);
size, note->descpos + offset);
}
-static bfd_boolean
+static bool
ppc64_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
{
if (note->descsz != 136)
- return FALSE;
+ return false;
elf_tdata (abfd)->core->pid
= bfd_get_32 (abfd, note->descdata + 24);
elf_tdata (abfd)->core->command
= _bfd_elfcore_strndup (abfd, note->descdata + 56, 80);
- return TRUE;
+ return true;
}
static char *
#define ppc64_elf_section_data(sec) \
((struct _ppc64_elf_section_data *) elf_section_data (sec))
-static bfd_boolean
+static bool
ppc64_elf_new_section_hook (bfd *abfd, asection *sec)
{
if (!sec->used_by_bfd)
sdata = bfd_zalloc (abfd, amt);
if (sdata == NULL)
- return FALSE;
+ return false;
sec->used_by_bfd = sdata;
}
return _bfd_elf_new_section_hook (abfd, sec);
}
-static bfd_boolean
+static bool
ppc64_elf_section_flags (const Elf_Internal_Shdr *hdr)
{
const char *name = hdr->bfd_section->name;
- if (strncmp (name, ".sbss", 5) == 0
- || strncmp (name, ".sdata", 6) == 0)
+ if (startswith (name, ".sbss")
+ || startswith (name, ".sdata"))
hdr->bfd_section->flags |= SEC_SMALL_DATA;
- return TRUE;
+ return true;
}
static struct _opd_sec_data *
}
\f
/* Parameters for the qsort hook. */
-static bfd_boolean synthetic_relocatable;
-static asection *synthetic_opd;
+static bool synthetic_relocatable;
+static const asection *synthetic_opd;
/* qsort comparison function for ppc64_elf_get_synthetic_symtab. */
return NULL;
}
-static bfd_boolean
+static bool
section_covers_vma (bfd *abfd ATTRIBUTE_UNUSED, asection *section, void *ptr)
{
bfd_vma vma = *(bfd_vma *) ptr;
char *names;
size_t symcount, codesecsym, codesecsymend, secsymend, opdsymend;
asection *opd = NULL;
- bfd_boolean relocatable = (abfd->flags & (EXEC_P | DYNAMIC)) == 0;
+ bool relocatable = (abfd->flags & (EXEC_P | DYNAMIC)) == 0;
asymbol **syms;
int abi = abiversion (abfd);
sym->section directly. With separate debug info files, the
symbols will be extracted from the debug file while abfd passed
to this function is the real binary. */
- if (strcmp (syms[i]->section->name, ".opd") == 0)
+ if ((syms[i]->flags & BSF_SECTION_SYM) != 0
+ && strcmp (syms[i]->section->name, ".opd") == 0)
++i;
codesecsym = i;
if (relocatable)
{
- bfd_boolean (*slurp_relocs) (bfd *, asection *, asymbol **, bfd_boolean);
+ bool (*slurp_relocs) (bfd *, asection *, asymbol **, bool);
arelent *r;
size_t size;
size_t relcount;
if (relcount == 0)
goto done;
- if (!(*slurp_relocs) (abfd, opd, static_syms, FALSE))
+ if (!(*slurp_relocs) (abfd, opd, static_syms, false))
{
count = -1;
goto done;
}
else
{
- bfd_boolean (*slurp_relocs) (bfd *, asection *, asymbol **, bfd_boolean);
+ bool (*slurp_relocs) (bfd *, asection *, asymbol **, bool);
bfd_byte *contents = NULL;
size_t size;
size_t plt_count = 0;
if (relplt != NULL)
{
slurp_relocs = get_elf_backend_data (abfd)->s->slurp_reloc_table;
- if (!(*slurp_relocs) (abfd, relplt, dyn_syms, TRUE))
+ if (!(*slurp_relocs) (abfd, relplt, dyn_syms, true))
goto free_contents_and_exit_err;
plt_count = relplt->size / sizeof (Elf64_External_Rela);
return (struct ppc_link_hash_entry *) ent;
}
+static inline struct elf_link_hash_entry *
+elf_hash_entry (struct ppc_link_hash_entry *ent)
+{
+ return (struct elf_link_hash_entry *) ent;
+}
+
/* ppc64 ELF linker hash table. */
struct ppc_link_hash_table
/* Get the ppc64 ELF linker hash table from a link_info structure. */
#define ppc_hash_table(p) \
- (elf_hash_table_id ((struct elf_link_hash_table *) ((p)->hash)) \
- == PPC64_ELF_DATA ? ((struct ppc_link_hash_table *) ((p)->hash)) : NULL)
+ ((is_elf_hash_table ((p)->hash) \
+ && elf_hash_table_id (elf_hash_table (p)) == PPC64_ELF_DATA) \
+ ? (struct ppc_link_hash_table *) (p)->hash : NULL)
#define ppc_stub_hash_lookup(table, string, create, copy) \
((struct ppc_stub_hash_entry *) \
/* Create sections for linker generated code. */
-static bfd_boolean
+static bool
create_linkage_sections (bfd *dynobj, struct bfd_link_info *info)
{
struct ppc_link_hash_table *htab;
flags);
if (htab->sfpr == NULL
|| !bfd_set_section_alignment (htab->sfpr, 2))
- return FALSE;
+ return false;
}
if (bfd_link_relocatable (info))
- return TRUE;
+ return true;
/* Create .glink for lazy dynamic linking support. */
htab->glink = bfd_make_section_anyway_with_flags (dynobj, ".glink",
flags);
if (htab->glink == NULL
|| !bfd_set_section_alignment (htab->glink, 3))
- return FALSE;
+ return false;
/* The part of .glink used by global entry stubs, separate so that
it can be aligned appropriately without affecting htab->glink. */
flags);
if (htab->global_entry == NULL
|| !bfd_set_section_alignment (htab->global_entry, 2))
- return FALSE;
+ return false;
if (!info->no_ld_generated_unwind_info)
{
flags);
if (htab->glink_eh_frame == NULL
|| !bfd_set_section_alignment (htab->glink_eh_frame, 2))
- return FALSE;
+ return false;
}
flags = SEC_ALLOC | SEC_LINKER_CREATED;
htab->elf.iplt = bfd_make_section_anyway_with_flags (dynobj, ".iplt", flags);
if (htab->elf.iplt == NULL
|| !bfd_set_section_alignment (htab->elf.iplt, 3))
- return FALSE;
+ return false;
flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY
| SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED);
= bfd_make_section_anyway_with_flags (dynobj, ".rela.iplt", flags);
if (htab->elf.irelplt == NULL
|| !bfd_set_section_alignment (htab->elf.irelplt, 3))
- return FALSE;
+ return false;
/* Create branch lookup table for plt_branch stubs. */
flags = (SEC_ALLOC | SEC_LOAD
flags);
if (htab->brlt == NULL
|| !bfd_set_section_alignment (htab->brlt, 3))
- return FALSE;
+ return false;
/* Local plt entries, put in .branch_lt but a separate section for
convenience. */
flags);
if (htab->pltlocal == NULL
|| !bfd_set_section_alignment (htab->pltlocal, 3))
- return FALSE;
+ return false;
if (!bfd_link_pic (info))
- return TRUE;
+ return true;
flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY
| SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED);
= bfd_make_section_anyway_with_flags (dynobj, ".rela.branch_lt", flags);
if (htab->relbrlt == NULL
|| !bfd_set_section_alignment (htab->relbrlt, 3))
- return FALSE;
+ return false;
htab->relpltlocal
= bfd_make_section_anyway_with_flags (dynobj, ".rela.branch_lt", flags);
if (htab->relpltlocal == NULL
|| !bfd_set_section_alignment (htab->relpltlocal, 3))
- return FALSE;
+ return false;
- return TRUE;
+ return true;
}
/* Satisfy the ELF linker by filling in some fields in our fake bfd. */
-bfd_boolean
+bool
ppc64_elf_init_stub_bfd (struct bfd_link_info *info,
struct ppc64_elf_params *params)
{
occurs. This function selects the correct entry to use. */
static struct ppc_stub_hash_entry *
-select_alt_stub (struct ppc_stub_hash_entry *entry, bfd_boolean notoc)
+select_alt_stub (struct ppc_stub_hash_entry *entry, bool notoc)
{
- bfd_boolean have_notoc;
+ bool have_notoc;
have_notoc = (entry->stub_type == ppc_stub_plt_call_notoc
|| entry->stub_type == ppc_stub_plt_branch_notoc
return NULL;
stub_entry = ppc_stub_hash_lookup (&htab->stub_hash_table,
- stub_name, FALSE, FALSE);
+ stub_name, false, false);
if (h != NULL)
h->u.stub_cache = stub_entry;
if (stub_entry != NULL && htab->params->power10_stubs == -1)
{
- bfd_boolean notoc = ELF64_R_TYPE (rel->r_info) == R_PPC64_REL24_NOTOC;
+ bool notoc = ELF64_R_TYPE (rel->r_info) == R_PPC64_REL24_NOTOC;
stub_entry = select_alt_stub (stub_entry, notoc);
}
/* Enter this entry into the linker stub hash table. */
stub_entry = ppc_stub_hash_lookup (&htab->stub_hash_table, stub_name,
- TRUE, FALSE);
+ true, false);
if (stub_entry == NULL)
{
/* xgettext:c-format */
/* Create .got and .rela.got sections in ABFD, and .got in dynobj if
not already done. */
-static bfd_boolean
+static bool
create_got_section (bfd *abfd, struct bfd_link_info *info)
{
asection *got, *relgot;
struct ppc_link_hash_table *htab = ppc_hash_table (info);
if (!is_ppc64_elf (abfd))
- return FALSE;
+ return false;
if (htab == NULL)
- return FALSE;
+ return false;
if (!htab->elf.sgot
&& !_bfd_elf_create_got_section (htab->elf.dynobj, info))
- return FALSE;
+ return false;
flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
| SEC_LINKER_CREATED);
got = bfd_make_section_anyway_with_flags (abfd, ".got", flags);
if (!got
|| !bfd_set_section_alignment (got, 3))
- return FALSE;
+ return false;
relgot = bfd_make_section_anyway_with_flags (abfd, ".rela.got",
flags | SEC_READONLY);
if (!relgot
|| !bfd_set_section_alignment (relgot, 3))
- return FALSE;
+ return false;
ppc64_elf_tdata (abfd)->got = got;
ppc64_elf_tdata (abfd)->relgot = relgot;
- return TRUE;
+ return true;
}
/* Follow indirect and warning symbol links. */
const char *fd_name = fh->elf.root.root.string + 1;
fdh = ppc_elf_hash_entry (elf_link_hash_lookup (&htab->elf, fd_name,
- FALSE, FALSE, FALSE));
+ false, false, false));
if (fdh == NULL)
return fdh;
if (!_bfd_generic_link_add_one_symbol (info, abfd,
fh->elf.root.root.string + 1,
flags, bfd_und_section_ptr, 0,
- NULL, FALSE, FALSE, &bh))
+ NULL, false, false, &bh))
return NULL;
fdh = (struct ppc_link_hash_entry *) bh;
/* Fix function descriptor symbols defined in .opd sections to be
function type. */
-static bfd_boolean
+static bool
ppc64_elf_add_symbol_hook (bfd *ibfd,
struct bfd_link_info *info,
Elf_Internal_Sym *isym,
if (!bfd_link_relocatable (info)
&& (*sec)->reloc_count != 0
&& opd_entry_value (*sec, *value, &code_sec, NULL,
- FALSE) != (bfd_vma) -1
+ false) != (bfd_vma) -1
&& discarded_section (code_sec))
{
*sec = bfd_und_section_ptr;
_bfd_error_handler (_("symbol '%s' has invalid st_other"
" for ABI version 1"), *name);
bfd_set_error (bfd_error_bad_value);
- return FALSE;
+ return false;
}
}
- return TRUE;
+ return true;
}
/* Merge non-visibility st_other attributes: local entry point. */
static void
ppc64_elf_merge_symbol_attribute (struct elf_link_hash_entry *h,
- const Elf_Internal_Sym *isym,
- bfd_boolean definition,
- bfd_boolean dynamic)
+ unsigned int st_other,
+ bool definition,
+ bool dynamic)
{
if (definition && (!dynamic || !h->def_regular))
- h->other = ((isym->st_other & ~ELF_ST_VISIBILITY (-1))
+ h->other = ((st_other & ~ELF_ST_VISIBILITY (-1))
| ELF_ST_VISIBILITY (h->other));
}
/* Hook called on merging a symbol. We use this to clear "fake" since
we now have a real symbol. */
-static bfd_boolean
+static bool
ppc64_elf_merge_symbol (struct elf_link_hash_entry *h,
const Elf_Internal_Sym *isym,
asection **psec ATTRIBUTE_UNUSED,
- bfd_boolean newdef ATTRIBUTE_UNUSED,
- bfd_boolean olddef ATTRIBUTE_UNUSED,
+ bool newdef ATTRIBUTE_UNUSED,
+ bool olddef ATTRIBUTE_UNUSED,
bfd *oldbfd ATTRIBUTE_UNUSED,
const asection *oldsec ATTRIBUTE_UNUSED)
{
ppc_elf_hash_entry (h)->fake = 0;
if ((STO_PPC64_LOCAL_MASK & isym->st_other) != 0)
ppc_elf_hash_entry (h)->non_zero_localentry = 1;
- return TRUE;
+ return true;
}
/* This function makes an old ABI object reference to ".bar" cause the
NAME is a symbol defined in an archive. Return a symbol in the hash
table that might be satisfied by the archive symbols. */
-static struct elf_link_hash_entry *
+static struct bfd_link_hash_entry *
ppc64_elf_archive_symbol_lookup (bfd *abfd,
struct bfd_link_info *info,
const char *name)
{
- struct elf_link_hash_entry *h;
+ struct bfd_link_hash_entry *h;
char *dot_name;
size_t len;
h = _bfd_elf_archive_symbol_lookup (abfd, info, name);
if (h != NULL
+ && ppc_hash_table (info) != NULL
/* Don't return this sym if it is a fake function descriptor
created by add_symbol_adjust. */
- && !ppc_elf_hash_entry (h)->fake)
+ && !((struct ppc_link_hash_entry *) h)->fake)
return h;
if (name[0] == '.')
len = strlen (name);
dot_name = bfd_alloc (abfd, len + 2);
if (dot_name == NULL)
- return (struct elf_link_hash_entry *) -1;
+ return (struct bfd_link_hash_entry *) -1;
dot_name[0] = '.';
memcpy (dot_name + 1, name, len + 1);
h = _bfd_elf_archive_symbol_lookup (abfd, info, dot_name);
most restrictive visibility of the function descriptor and the
function entry symbol is used. */
-static bfd_boolean
+static bool
add_symbol_adjust (struct ppc_link_hash_entry *eh, struct bfd_link_info *info)
{
struct ppc_link_hash_table *htab;
eh = (struct ppc_link_hash_entry *) eh->elf.root.u.i.link;
if (eh->elf.root.type == bfd_link_hash_indirect)
- return TRUE;
+ return true;
if (eh->elf.root.root.string[0] != '.')
abort ();
htab = ppc_hash_table (info);
if (htab == NULL)
- return FALSE;
+ return false;
fdh = lookup_fdh (eh, htab);
if (fdh == NULL
elsewhere. */
fdh = make_fdh (info, eh);
if (fdh == NULL)
- return FALSE;
+ return false;
}
if (fdh != NULL)
|| eh->elf.def_regular))
{
if (!bfd_elf_link_record_dynamic_symbol (info, &fdh->elf))
- return FALSE;
+ return false;
}
}
- return TRUE;
+ return true;
}
/* Set up opd section info and abiversion for IBFD, and process list
of dot-symbols we made in link_hash_newfunc. */
-static bfd_boolean
+static bool
ppc64_elf_before_check_relocs (bfd *ibfd, struct bfd_link_info *info)
{
struct ppc_link_hash_table *htab;
_bfd_error_handler (_("%pB .opd not allowed in ABI version %d"),
ibfd, abiversion (ibfd));
bfd_set_error (bfd_error_bad_value);
- return FALSE;
+ return false;
}
}
htab = ppc_hash_table (info);
if (htab == NULL)
- return TRUE;
+ return true;
if (opd != NULL && opd->size != 0
&& (ibfd->flags & DYNAMIC) == 0
amt = OPD_NDX (opd->size) * sizeof (*opd_sym_map);
opd_sym_map = bfd_zalloc (ibfd, amt);
if (opd_sym_map == NULL)
- return FALSE;
+ return false;
ppc64_elf_section_data (opd)->u.opd.func_sec = opd_sym_map;
relocs = _bfd_elf_link_read_relocs (ibfd, opd, NULL, NULL,
info->keep_memory);
if (relocs == NULL)
- return FALSE;
+ return false;
symtab_hdr = &elf_symtab_hdr (ibfd);
rel_end = relocs + opd->reloc_count - 1;
for (rel = relocs; rel < rel_end; rel++)
{
if (elf_section_data (opd)->relocs != relocs)
free (relocs);
- return FALSE;
+ return false;
}
s = bfd_section_from_elf_index (ibfd, isym->st_shndx);
{
htab->need_func_desc_adj = 1;
if (!add_symbol_adjust (eh, info))
- return FALSE;
+ return false;
}
p = &eh->u.next_dot_sym;
}
- return TRUE;
+ return true;
}
/* Undo hash table changes when an --as-needed input file is determined
not to be needed. */
-static bfd_boolean
+static bool
ppc64_elf_notice_as_needed (bfd *ibfd,
struct bfd_link_info *info,
enum notice_asneeded_action act)
struct ppc_link_hash_table *htab = ppc_hash_table (info);
if (htab == NULL)
- return FALSE;
+ return false;
htab->dot_syms = NULL;
}
size_t amt = sizeof (*ent);
ent = bfd_alloc (abfd, amt);
if (ent == NULL)
- return FALSE;
+ return false;
ent->next = local_got_ents[r_symndx];
ent->addend = r_addend;
ent->owner = abfd;
ent->tls_type = tls_type;
- ent->is_indirect = FALSE;
+ ent->is_indirect = false;
ent->got.refcount = 0;
local_got_ents[r_symndx] = ent;
}
return local_plt + r_symndx;
}
-static bfd_boolean
+static bool
update_plt_info (bfd *abfd, struct plt_entry **plist, bfd_vma addend)
{
struct plt_entry *ent;
size_t amt = sizeof (*ent);
ent = bfd_alloc (abfd, amt);
if (ent == NULL)
- return FALSE;
+ return false;
ent->next = *plist;
ent->addend = addend;
ent->plt.refcount = 0;
*plist = ent;
}
ent->plt.refcount += 1;
- return TRUE;
+ return true;
}
-static bfd_boolean
+static bool
is_branch_reloc (enum elf_ppc64_reloc_type r_type)
{
return (r_type == R_PPC64_REL24
/* Relocs on inline plt call sequence insns prior to the call. */
-static bfd_boolean
+static bool
is_plt_seq_reloc (enum elf_ppc64_reloc_type r_type)
{
return (r_type == R_PPC64_PLT16_HA
calculate needed space in the global offset table, procedure
linkage table, and dynamic reloc sections. */
-static bfd_boolean
+static bool
ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
asection *sec, const Elf_Internal_Rela *relocs)
{
const Elf_Internal_Rela *rel_end;
asection *sreloc;
struct elf_link_hash_entry *tga, *dottga;
- bfd_boolean is_opd;
+ bool is_opd;
if (bfd_link_relocatable (info))
- return TRUE;
+ return true;
BFD_ASSERT (is_ppc64_elf (abfd));
htab = ppc_hash_table (info);
if (htab == NULL)
- return FALSE;
+ return false;
tga = elf_link_hash_lookup (&htab->elf, "__tls_get_addr",
- FALSE, FALSE, TRUE);
+ false, false, true);
dottga = 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);
sreloc = NULL;
Elf_Internal_Sym *isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache,
abfd, r_symndx);
if (isym == NULL)
- return FALSE;
+ return false;
if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
{
rel->r_addend,
NON_GOT | PLT_IFUNC);
if (ifunc == NULL)
- return FALSE;
+ return false;
}
}
if (!update_local_sym_info (abfd, symtab_hdr, r_symndx,
rel->r_addend,
NON_GOT | TLS_TLS | TLS_MARK))
- return FALSE;
+ return false;
sec->has_tls_reloc = 1;
break;
if (ppc64_elf_tdata (abfd)->got == NULL
&& !create_got_section (abfd, info))
- return FALSE;
+ return false;
if (h != NULL)
{
size_t amt = sizeof (*ent);
ent = bfd_alloc (abfd, amt);
if (ent == NULL)
- return FALSE;
+ return false;
ent->next = eh->elf.got.glist;
ent->addend = rel->r_addend;
ent->owner = abfd;
ent->tls_type = tls_type;
- ent->is_indirect = FALSE;
+ ent->is_indirect = false;
ent->got.refcount = 0;
eh->elf.got.glist = ent;
}
/* This is a global offset table entry for a local symbol. */
if (!update_local_sym_info (abfd, symtab_hdr, r_symndx,
rel->r_addend, tls_type))
- return FALSE;
+ return false;
break;
case R_PPC64_PLT16_HA:
rel->r_addend,
NON_GOT | PLT_KEEP);
if (!update_plt_info (abfd, plt_list, rel->r_addend))
- return FALSE;
+ return false;
break;
/* The following relocations don't need to propagate the
abfd, sec, rel->r_offset,
ppc64_elf_howto_table[r_type]->name);
bfd_set_error (bfd_error_bad_value);
- return FALSE;
+ return false;
}
break;
Reconstruct it for later use during GC. */
case R_PPC64_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_PPC64_GNU_VTENTRY:
if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
- return FALSE;
+ return false;
break;
case R_PPC64_REL14:
isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache,
abfd, r_symndx);
if (isym == NULL)
- return FALSE;
+ return false;
dest = bfd_section_from_elf_index (abfd, isym->st_shndx);
}
refers to is in a shared lib. */
if (plt_list
&& !update_plt_info (abfd, plt_list, rel->r_addend))
- return FALSE;
+ return false;
break;
case R_PPC64_ADDR14:
else
if (!update_local_sym_info (abfd, symtab_hdr, r_symndx,
rel->r_addend, tls_type))
- return FALSE;
+ return false;
ppc64_sec = ppc64_elf_section_data (sec);
if (ppc64_sec->sec_type != sec_toc)
amt = sec->size * sizeof (unsigned) / 8 + sizeof (unsigned);
ppc64_sec->u.toc.symndx = bfd_zalloc (abfd, amt);
if (ppc64_sec->u.toc.symndx == NULL)
- return FALSE;
+ return false;
amt = sec->size * sizeof (bfd_vma) / 8;
ppc64_sec->u.toc.add = bfd_zalloc (abfd, amt);
if (ppc64_sec->u.toc.add == NULL)
- return FALSE;
+ return false;
BFD_ASSERT (ppc64_sec->sec_type == sec_normal);
ppc64_sec->sec_type = sec_toc;
}
ppc64_sec->u.toc.symndx[rel->r_offset / 8 + 1] = -2;
goto dodyn;
- case R_PPC64_TPREL16:
- case R_PPC64_TPREL16_LO:
case R_PPC64_TPREL16_HI:
case R_PPC64_TPREL16_HA:
- case R_PPC64_TPREL16_DS:
- case R_PPC64_TPREL16_LO_DS:
case R_PPC64_TPREL16_HIGH:
case R_PPC64_TPREL16_HIGHA:
case R_PPC64_TPREL16_HIGHER:
case R_PPC64_TPREL16_HIGHERA:
case R_PPC64_TPREL16_HIGHEST:
case R_PPC64_TPREL16_HIGHESTA:
+ sec->has_tls_reloc = 1;
+ /* Fall through. */
case R_PPC64_TPREL34:
+ case R_PPC64_TPREL16:
+ case R_PPC64_TPREL16_DS:
+ case R_PPC64_TPREL16_LO:
+ case R_PPC64_TPREL16_LO_DS:
if (bfd_link_dll (info))
info->flags |= DF_STATIC_TLS;
goto dodyn;
/* We may need a .plt entry if this reloc refers to a
function in a shared lib. */
if (!update_plt_info (abfd, &h->plt.plist, 0))
- return FALSE;
+ return false;
h->pointer_equality_needed = 1;
}
/* Fall through. */
if (sreloc == NULL)
{
sreloc = _bfd_elf_make_dynamic_reloc_section
- (sec, htab->elf.dynobj, 3, abfd, /*rela?*/ TRUE);
+ (sec, htab->elf.dynobj, 3, abfd, /*rela?*/ true);
if (sreloc == NULL)
- return FALSE;
+ return false;
}
/* If this is a global symbol, we count the number of
{
p = bfd_alloc (htab->elf.dynobj, sizeof *p);
if (p == NULL)
- return FALSE;
+ return false;
p->next = *head;
*head = p;
p->sec = sec;
easily. Oh well. */
struct ppc_dyn_relocs *p;
struct ppc_dyn_relocs **head;
- bfd_boolean is_ifunc;
+ bool is_ifunc;
asection *s;
void *vpp;
Elf_Internal_Sym *isym;
isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache,
abfd, r_symndx);
if (isym == NULL)
- return FALSE;
+ return false;
s = bfd_section_from_elf_index (abfd, isym->st_shndx);
if (s == NULL)
{
p = bfd_alloc (htab->elf.dynobj, sizeof *p);
if (p == NULL)
- return FALSE;
+ return false;
p->next = *head;
*head = p;
p->sec = sec;
}
}
- return TRUE;
+ return true;
}
/* Merge backend specific data from an object file to the output
object file when linking. */
-static bfd_boolean
+static bool
ppc64_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
{
bfd *obfd = info->output_bfd;
unsigned long iflags, oflags;
if ((ibfd->flags & BFD_LINKER_CREATED) != 0)
- return TRUE;
+ return true;
if (!is_ppc64_elf (ibfd) || !is_ppc64_elf (obfd))
- return TRUE;
+ return true;
if (!_bfd_generic_verify_endian_match (ibfd, info))
- return FALSE;
+ return false;
iflags = elf_elfheader (ibfd)->e_flags;
oflags = elf_elfheader (obfd)->e_flags;
/* xgettext:c-format */
(_("%pB uses unknown e_flags 0x%lx"), ibfd, iflags);
bfd_set_error (bfd_error_bad_value);
- return FALSE;
+ return false;
}
else if (iflags != oflags && iflags != 0)
{
(_("%pB: ABI version %ld is not compatible with ABI version %ld output"),
ibfd, iflags, oflags);
bfd_set_error (bfd_error_bad_value);
- return FALSE;
+ return false;
}
if (!_bfd_elf_ppc_merge_fp_attributes (ibfd, info))
- return FALSE;
+ return false;
/* Merge Tag_compatibility attributes and any common GNU ones. */
return _bfd_elf_merge_object_attributes (ibfd, info);
}
-static bfd_boolean
+static bool
ppc64_elf_print_private_bfd_data (bfd *abfd, void *ptr)
{
/* Print normal ELF private data. */
fputc ('\n', file);
}
- return TRUE;
+ return true;
}
/* OFFSET in OPD_SEC specifies a function descriptor. Return the address
bfd_vma offset,
asection **code_sec,
bfd_vma *code_off,
- bfd_boolean in_code_sec)
+ bool in_code_sec)
{
bfd *opd_bfd = opd_sec->owner;
Elf_Internal_Rela *relocs;
relocs = ppc64_elf_tdata (opd_bfd)->opd.relocs;
if (relocs == NULL)
- relocs = _bfd_elf_link_read_relocs (opd_bfd, opd_sec, NULL, NULL, TRUE);
+ relocs = _bfd_elf_link_read_relocs (opd_bfd, opd_sec, NULL, NULL, true);
/* PR 17512: file: df8e1fd6. */
if (relocs == NULL)
return (bfd_vma) -1;
bfd_vma *code_off)
{
bfd_size_type size;
+ elf_symbol_type * elf_sym = (elf_symbol_type *) sym;
if ((sym->flags & (BSF_SECTION_SYM | BSF_FILE | BSF_OBJECT
| BSF_THREAD_LOCAL | BSF_RELC | BSF_SRELC)) != 0)
return 0;
- size = 0;
- if (!(sym->flags & BSF_SYNTHETIC))
- size = ((elf_symbol_type *) sym)->internal_elf_sym.st_size;
+ size = (sym->flags & BSF_SYNTHETIC) ? 0 : elf_sym->internal_elf_sym.st_size;
+
+ /* In theory we should check that the symbol's type satisfies
+ _bfd_elf_is_function_type(), but there are some function-like
+ symbols which would fail this test. (eg _start). Instead
+ we check for hidden, local, notype symbols with zero size.
+ This type of symbol is generated by the annobin plugin for gcc
+ and clang, and should not be considered to be a function symbol. */
+ if (size == 0
+ && ((sym->flags & (BSF_SYNTHETIC | BSF_LOCAL)) == BSF_LOCAL)
+ && ELF_ST_TYPE (elf_sym->internal_elf_sym.st_info) == STT_NOTYPE
+ && ELF_ST_VISIBILITY (elf_sym->internal_elf_sym.st_other) == STV_HIDDEN)
+ return 0;
if (strcmp (sym->section->name, ".opd") == 0)
{
}
if (opd_entry_value (sym->section, symval,
- &sec, code_off, TRUE) == (bfd_vma) -1)
+ &sec, code_off, true) == (bfd_vma) -1)
return 0;
/* An old ABI binary with dot-syms has a size of 24 on the .opd
symbol. This size has nothing to do with the code size of the
return 0;
*code_off = sym->value;
}
- if (size == 0)
- size = 1;
- return size;
+
+ /* Do not return 0 for the function's size. */
+ return size ? size : 1;
}
/* Return true if symbol is a strong function defined in an ELFv2
object with st_other localentry bits of zero, ie. its local entry
point coincides with its global entry point. */
-static bfd_boolean
+static bool
is_elfv2_localentry0 (struct elf_link_hash_entry *h)
{
return (h != NULL
/* Return true if symbol is defined in a regular object file. */
-static bfd_boolean
+static bool
is_static_defined (struct elf_link_hash_entry *h)
{
return ((h->root.type == bfd_link_hash_defined
/* Return true if H matches __tls_get_addr or one of its variants. */
-static bfd_boolean
+static bool
is_tls_get_addr (struct elf_link_hash_entry *h,
struct ppc_link_hash_table *htab)
{
- return (h == &htab->tls_get_addr_fd->elf || h == &htab->tga_desc_fd->elf
- || h == &htab->tls_get_addr->elf || h == &htab->tga_desc->elf);
+ return (h == elf_hash_entry (htab->tls_get_addr_fd)
+ || h == elf_hash_entry (htab->tga_desc_fd)
+ || h == elf_hash_entry (htab->tls_get_addr)
+ || h == elf_hash_entry (htab->tga_desc));
}
-static bfd_boolean func_desc_adjust (struct elf_link_hash_entry *, void *);
+static bool func_desc_adjust (struct elf_link_hash_entry *, void *);
/* Garbage collect sections, after first dealing with dot-symbols. */
-static bfd_boolean
+static bool
ppc64_elf_gc_sections (bfd *abfd, struct bfd_link_info *info)
{
struct ppc_link_hash_table *htab = ppc_hash_table (info);
asection *sec;
eh = ppc_elf_hash_entry (elf_link_hash_lookup (&htab->elf, sym->name,
- FALSE, FALSE, TRUE));
+ false, false, true));
if (eh == NULL)
continue;
if (eh->elf.root.type != bfd_link_hash_defined
else if (get_opd_info (eh->elf.root.u.def.section) != NULL
&& opd_entry_value (eh->elf.root.u.def.section,
eh->elf.root.u.def.value,
- &sec, NULL, FALSE) != (bfd_vma) -1)
+ &sec, NULL, false) != (bfd_vma) -1)
sec->flags |= SEC_KEEP;
sec = eh->elf.root.u.def.section;
building shared libraries, we must assume that any visible symbol is
referenced. */
-static bfd_boolean
+static bool
ppc64_elf_gc_mark_dynamic_ref (struct elf_link_hash_entry *h, void *inf)
{
struct bfd_link_info *info = (struct bfd_link_info *) inf;
if ((eh->elf.root.type == bfd_link_hash_defined
|| eh->elf.root.type == bfd_link_hash_defweak)
+ && (!eh->elf.start_stop
+ || eh->elf.root.ldscript_def
+ || !info->start_stop_gc)
&& ((eh->elf.ref_dynamic && !eh->elf.forced_local)
|| ((eh->elf.def_regular || ELF_COMMON_DEF_P (&eh->elf))
&& ELF_ST_VISIBILITY (eh->elf.other) != STV_INTERNAL
else if (get_opd_info (eh->elf.root.u.def.section) != NULL
&& opd_entry_value (eh->elf.root.u.def.section,
eh->elf.root.u.def.value,
- &code_sec, NULL, FALSE) != (bfd_vma) -1)
+ &code_sec, NULL, false) != (bfd_vma) -1)
code_sec->flags |= SEC_KEEP;
}
- return TRUE;
+ return true;
}
/* Return the section that should be marked against GC for a given
else if (get_opd_info (eh->elf.root.u.def.section) != NULL
&& opd_entry_value (eh->elf.root.u.def.section,
eh->elf.root.u.def.value,
- &rsec, NULL, FALSE) != (bfd_vma) -1)
+ &rsec, NULL, false) != (bfd_vma) -1)
eh->elf.root.u.def.section->gc_mark = 1;
else
rsec = h->root.u.def.section;
If STUB_SEC is non-null, define alias symbols in STUB_SEC
instead. */
-static bfd_boolean
+static bool
sfpr_define (struct bfd_link_info *info,
const struct sfpr_def_parms *parm,
asection *stub_sec)
struct ppc_link_hash_table *htab = ppc_hash_table (info);
unsigned int i;
size_t len = strlen (parm->name);
- bfd_boolean writing = FALSE;
+ bool writing = false;
char sym[16];
if (htab == NULL)
- return FALSE;
+ return false;
memcpy (sym, parm->name, len);
sym[len + 2] = 0;
sym[len + 0] = i / 10 + '0';
sym[len + 1] = i % 10 + '0';
h = ppc_elf_hash_entry (elf_link_hash_lookup (&htab->elf, sym,
- writing, TRUE, TRUE));
+ writing, true, true));
if (stub_sec != NULL)
{
if (h != NULL
struct elf_link_hash_entry *s;
char buf[32];
sprintf (buf, "%08x.%s", stub_sec->id & 0xffffffff, sym);
- s = elf_link_hash_lookup (&htab->elf, buf, TRUE, TRUE, FALSE);
+ s = elf_link_hash_lookup (&htab->elf, buf, true, true, false);
if (s == NULL)
- return FALSE;
+ return false;
if (s->root.type == bfd_link_hash_new)
{
s->root.type = bfd_link_hash_defined;
h->elf.type = STT_FUNC;
h->elf.def_regular = 1;
h->elf.non_elf = 0;
- _bfd_elf_link_hash_hide_symbol (info, &h->elf, TRUE);
- writing = TRUE;
+ _bfd_elf_link_hash_hide_symbol (info, &h->elf, true);
+ writing = true;
if (htab->sfpr->contents == NULL)
{
htab->sfpr->contents
= bfd_alloc (htab->elf.dynobj, SFPR_MAX);
if (htab->sfpr->contents == NULL)
- return FALSE;
+ return false;
}
}
}
}
}
- return TRUE;
+ return true;
}
static bfd_byte *
information on function code symbol entries to their corresponding
function descriptor symbol entries. */
-static bfd_boolean
+static bool
func_desc_adjust (struct elf_link_hash_entry *h, void *inf)
{
struct bfd_link_info *info;
struct ppc_link_hash_table *htab;
struct ppc_link_hash_entry *fh;
struct ppc_link_hash_entry *fdh;
- bfd_boolean force_local;
+ bool force_local;
fh = ppc_elf_hash_entry (h);
if (fh->elf.root.type == bfd_link_hash_indirect)
- return TRUE;
+ return true;
if (!fh->is_func)
- return TRUE;
+ return true;
if (fh->elf.root.root.string[0] != '.'
|| fh->elf.root.root.string[1] == '\0')
- return TRUE;
+ return true;
info = inf;
htab = ppc_hash_table (info);
if (htab == NULL)
- return FALSE;
+ return false;
/* Find the corresponding function descriptor symbol. */
fdh = lookup_fdh (fh, htab);
&& opd_entry_value (fdh->elf.root.u.def.section,
fdh->elf.root.u.def.value,
&fh->elf.root.u.def.section,
- &fh->elf.root.u.def.value, FALSE) != (bfd_vma) -1)
+ &fh->elf.root.u.def.value, false) != (bfd_vma) -1)
{
fh->elf.root.type = fdh->elf.root.type;
fh->elf.forced_local = 1;
if (ent->plt.refcount > 0)
break;
if (ent == NULL)
- return TRUE;
+ return true;
}
/* Create a descriptor as undefined if necessary. */
{
fdh = make_fdh (info, fh);
if (fdh == NULL)
- return FALSE;
+ return false;
}
/* We can't support overriding of symbols on a fake descriptor. */
&& fdh->fake
&& (fh->elf.root.type == bfd_link_hash_defined
|| fh->elf.root.type == bfd_link_hash_defweak))
- _bfd_elf_link_hash_hide_symbol (info, &fdh->elf, TRUE);
+ _bfd_elf_link_hash_hide_symbol (info, &fdh->elf, true);
/* Transfer dynamic linking information to the function descriptor. */
if (fdh != NULL)
if (!fdh->elf.forced_local
&& fh->elf.dynindx != -1)
if (!bfd_elf_link_record_dynamic_symbol (info, &fdh->elf))
- return FALSE;
+ return false;
}
/* Now that the info is on the function descriptor, clear the
|| fdh->elf.forced_local);
_bfd_elf_link_hash_hide_symbol (info, &fh->elf, force_local);
- return TRUE;
+ return true;
}
static const struct sfpr_def_parms save_res_funcs[] =
};
/* Called near the start of bfd_elf_size_dynamic_sections. We use
- this hook to a) provide some gcc support functions, and b) transfer
- dynamic linking information gathered so far on function code symbol
- entries, to their corresponding function descriptor symbol entries. */
+ this hook to a) run the edit functions in this file, b) provide
+ some gcc support functions, and c) transfer dynamic linking
+ information gathered so far on function code symbol entries, to
+ their corresponding function descriptor symbol entries. */
-static bfd_boolean
-ppc64_elf_func_desc_adjust (bfd *obfd ATTRIBUTE_UNUSED,
- struct bfd_link_info *info)
+static bool
+ppc64_elf_edit (bfd *obfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
{
struct ppc_link_hash_table *htab;
htab = ppc_hash_table (info);
if (htab == NULL)
- return FALSE;
+ return false;
+
+ /* Call back into the linker, which then runs the edit functions. */
+ htab->params->edit ();
/* Provide any missing _save* and _rest* functions. */
if (htab->sfpr != NULL)
htab->sfpr->size = 0;
for (i = 0; i < ARRAY_SIZE (save_res_funcs); i++)
if (!sfpr_define (info, &save_res_funcs[i], NULL))
- return FALSE;
+ return false;
if (htab->sfpr->size == 0)
htab->sfpr->flags |= SEC_EXCLUDE;
}
if (bfd_link_relocatable (info))
- return TRUE;
+ return true;
if (htab->elf.hgot != NULL)
{
- _bfd_elf_link_hash_hide_symbol (info, htab->elf.hgot, TRUE);
+ _bfd_elf_link_hash_hide_symbol (info, htab->elf.hgot, true);
/* Make .TOC. defined so as to prevent it being made dynamic.
The wrong value here is fixed later in ppc64_elf_set_toc. */
if (!htab->elf.hgot->def_regular
htab->need_func_desc_adj = 0;
}
- 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_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 EH has pc-relative dynamic relocs. */
-static bfd_boolean
+static bool
pc_dynrelocs (struct ppc_link_hash_entry *eh)
{
struct elf_dyn_relocs *p;
for (p = eh->elf.dyn_relocs; p != NULL; p = p->next)
if (p->pc_count != 0)
- return TRUE;
- return FALSE;
+ return true;
+ return false;
}
/* Return true if a global entry stub will be created for H. Valid
for ELFv2 before plt entries have been allocated. */
-static bfd_boolean
+static bool
global_entry_stub (struct elf_link_hash_entry *h)
{
struct plt_entry *pent;
if (!h->pointer_equality_needed
|| h->def_regular)
- return FALSE;
+ return false;
for (pent = h->plt.plist; pent != NULL; pent = pent->next)
if (pent->plt.refcount > 0
&& pent->addend == 0)
- return TRUE;
+ return true;
- return FALSE;
+ return false;
}
/* Adjust a symbol defined by a dynamic object and referenced by a
change the definition to something the rest of the link can
understand. */
-static bfd_boolean
+static bool
ppc64_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
struct elf_link_hash_entry *h)
{
htab = ppc_hash_table (info);
if (htab == NULL)
- return FALSE;
+ return false;
/* Deal with function syms. */
if (h->type == STT_FUNC
|| h->type == STT_GNU_IFUNC
|| h->needs_plt)
{
- bfd_boolean local = (ppc_elf_hash_entry (h)->save_res
- || SYMBOL_CALLS_LOCAL (info, h)
- || UNDEFWEAK_NO_DYNAMIC_RELOC (info, h));
+ bool local = (ppc_elf_hash_entry (h)->save_res
+ || 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 and not an ifunc. We keep dynamic
relocs for ifuncs when local rather than always emitting a
}
/* ELFv2 function symbols can't have copy relocs. */
- return TRUE;
+ return true;
}
else if (!h->needs_plt
&& !_bfd_elf_readonly_dynrelocs (h))
ifunc then we don't need a plt entry. */
h->plt.plist = NULL;
h->pointer_equality_needed = 0;
- return TRUE;
+ return true;
}
}
else
if (def->root.u.def.section == htab->elf.sdynbss
|| def->root.u.def.section == htab->elf.sdynrelro)
h->dyn_relocs = NULL;
- return TRUE;
+ return true;
}
/* If we are creating a shared library, we must presume that the
For such cases we need not do anything here; the relocations will
be handled correctly by relocate_section. */
if (!bfd_link_executable (info))
- return TRUE;
+ return true;
/* If there are no references to this symbol that do not use the
GOT, we don't need to generate a copy reloc. */
if (!h->non_got_ref)
- return TRUE;
+ return true;
/* Don't generate a copy reloc for symbols defined in the executable. */
if (!h->def_dynamic || !h->ref_regular || h->def_regular
definition for the variable. Text relocations are preferable
to an incorrect program. */
|| h->protected_def)
- return TRUE;
+ return true;
if (h->type == STT_FUNC
|| h->type == STT_GNU_IFUNC)
That's wrong for copying a descriptor. */
if (ppc_elf_hash_entry (h)->oh == NULL
|| !(h->size == 24 || h->size == 16))
- return TRUE;
+ return true;
/* We should never get here, but unfortunately there are old
versions of gcc (circa gcc-3.2) that improperly for the
static void
ppc64_elf_hide_symbol (struct bfd_link_info *info,
struct elf_link_hash_entry *h,
- bfd_boolean force_local)
+ bool force_local)
{
struct ppc_link_hash_entry *eh;
_bfd_elf_link_hash_hide_symbol (info, h, force_local);
p = eh->elf.root.root.string - 1;
save = *p;
*(char *) p = '.';
- fh = ppc_elf_hash_entry (elf_link_hash_lookup (htab, p, FALSE,
- FALSE, FALSE));
+ fh = ppc_elf_hash_entry (elf_link_hash_lookup (htab, p, false,
+ false, false));
*(char *) p = save;
/* Unfortunately, if it so happens that the string we were
while (q >= eh->elf.root.root.string && *q == *p)
--q, --p;
if (q < eh->elf.root.root.string && *p == '.')
- fh = ppc_elf_hash_entry (elf_link_hash_lookup (htab, p, FALSE,
- FALSE, FALSE));
+ fh = ppc_elf_hash_entry (elf_link_hash_lookup (htab, p, false,
+ false, false));
}
if (fh != NULL)
{
}
}
-static bfd_boolean
+static bool
get_sym_h (struct elf_link_hash_entry **hp,
Elf_Internal_Sym **symp,
asection **symsecp,
symtab_hdr->sh_info,
0, NULL, NULL, NULL);
if (locsyms == NULL)
- return FALSE;
+ return false;
*locsymsp = locsyms;
}
sym = locsyms + r_symndx;
*tls_maskp = tls_mask;
}
}
- return TRUE;
+ return true;
}
/* Returns TLS_MASKP for the given REL symbol. Function return is 0 on
/* Adjust all global syms defined in opd sections. In gcc generated
code for the old ABI, these will already have been done. */
-static bfd_boolean
+static bool
adjust_opd_syms (struct elf_link_hash_entry *h, void *inf ATTRIBUTE_UNUSED)
{
struct ppc_link_hash_entry *eh;
struct _opd_sec_data *opd;
if (h->root.type == bfd_link_hash_indirect)
- return TRUE;
+ return true;
if (h->root.type != bfd_link_hash_defined
&& h->root.type != bfd_link_hash_defweak)
- return TRUE;
+ return true;
eh = ppc_elf_hash_entry (h);
if (eh->adjust_done)
- return TRUE;
+ return true;
sym_sec = eh->elf.root.u.def.section;
opd = get_opd_info (sym_sec);
eh->elf.root.u.def.value += adjust;
eh->adjust_done = 1;
}
- return TRUE;
+ return true;
}
/* Handles decrementing dynamic reloc counts for the reloc specified by
R_INFO in section SEC. If LOCAL_SYMS is NULL, then H and SYM
have already been determined. */
-static bfd_boolean
+static bool
dec_dynrel_count (bfd_vma r_info,
asection *sec,
struct bfd_link_info *info,
switch (r_type)
{
default:
- return TRUE;
+ return true;
case R_PPC64_TOC16:
case R_PPC64_TOC16_DS:
case R_PPC64_TOC16_HA:
case R_PPC64_TOC16_LO_DS:
if (h == NULL)
- return TRUE;
+ return true;
break;
case R_PPC64_TPREL16:
r_symndx = ELF64_R_SYM (r_info);
if (!get_sym_h (&h, &sym, &sym_sec, NULL, local_syms, r_symndx, ibfd))
- return FALSE;
+ return false;
}
if ((h != NULL
: ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)))
;
else
- return TRUE;
+ return true;
if (h != NULL)
{
changed by elf_gc_sweep_symbol, confusing the test above. Don't
report a dynreloc miscount. */
if (*pp == NULL && info->gc_sections)
- return TRUE;
+ return true;
while ((p = *pp) != NULL)
{
p->count -= 1;
if (p->count == 0)
*pp = p->next;
- return TRUE;
+ return true;
}
pp = &p->next;
}
struct ppc_dyn_relocs *p;
struct ppc_dyn_relocs **pp;
void *vpp;
- bfd_boolean is_ifunc;
+ bool is_ifunc;
if (local_syms == NULL)
sym_sec = bfd_section_from_elf_index (sec->owner, sym->st_shndx);
pp = (struct ppc_dyn_relocs **) vpp;
if (*pp == NULL && info->gc_sections)
- return TRUE;
+ return true;
is_ifunc = ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC;
while ((p = *pp) != NULL)
p->count -= 1;
if (p->count == 0)
*pp = p->next;
- return TRUE;
+ return true;
}
pp = &p->next;
}
_bfd_error_handler (_("dynreloc miscount for %pB, section %pA"),
sec->owner, sec);
bfd_set_error (bfd_error_bad_value);
- return FALSE;
+ return false;
}
/* Remove unused Official Procedure Descriptor entries. Currently we
would be possible to remove many more entries for statically linked
applications. */
-bfd_boolean
+bool
ppc64_elf_edit_opd (struct bfd_link_info *info)
{
bfd *ibfd;
- bfd_boolean some_edited = FALSE;
+ bool some_edited = false;
asection *need_pad = NULL;
struct ppc_link_hash_table *htab;
htab = ppc_hash_table (info);
if (htab == NULL)
- return FALSE;
+ return false;
for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
{
Elf_Internal_Shdr *symtab_hdr;
Elf_Internal_Sym *local_syms;
struct _opd_sec_data *opd;
- bfd_boolean need_edit, add_aux_fields, broken;
+ bool need_edit, add_aux_fields, broken;
bfd_size_type cnt_16b = 0;
if (!is_ppc64_elf (ibfd))
relstart = _bfd_elf_link_read_relocs (ibfd, sec, NULL, NULL,
info->keep_memory);
if (relstart == NULL)
- return FALSE;
+ return false;
/* First run through the relocs to check they are sane, and to
determine whether we need to edit this opd section. */
- need_edit = FALSE;
- broken = FALSE;
+ need_edit = false;
+ broken = false;
need_pad = sec;
relend = relstart + sec->reloc_count;
for (rel = relstart; rel < relend; )
broken_opd:
_bfd_error_handler
(_("%pB: .opd is not a regular array of opd entries"), ibfd);
- broken = TRUE;
+ broken = true;
break;
}
/* xgettext:c-format */
(_("%pB: unexpected reloc type %u in .opd section"),
ibfd, r_type);
- broken = TRUE;
+ broken = true;
break;
}
/* xgettext:c-format */
(_("%pB: undefined sym `%s' in .opd section"),
ibfd, sym_name);
- broken = TRUE;
+ broken = true;
break;
}
which we test for via the output_section. */
if (sym_sec->owner != ibfd
|| sym_sec->output_section == bfd_abs_section_ptr)
- need_edit = TRUE;
+ need_edit = true;
rel += 2;
if (rel + 1 == relend
opd = &ppc64_elf_section_data (sec)->u.opd;
opd->adjust = bfd_zalloc (sec->owner, amt);
if (opd->adjust == NULL)
- return FALSE;
+ return false;
/* This seems a waste of time as input .opd sections are all
zeros as generated by gcc, but I suppose there's no reason
free (local_syms);
if (elf_section_data (sec)->relocs != relstart)
free (relstart);
- return FALSE;
+ return false;
}
sec->contents = loc;
sec->flags |= (SEC_IN_MEMORY | SEC_HAS_CONTENTS);
{
new_contents = bfd_malloc (sec->size + cnt_16b * 8);
if (new_contents == NULL)
- return FALSE;
+ return false;
need_pad = NULL;
}
wptr = new_contents;
Elf_Internal_Sym *sym;
long opd_ent_size;
Elf_Internal_Rela *next_rel;
- bfd_boolean skip;
+ bool skip;
r_symndx = ELF64_R_SYM (rel->r_info);
if (!get_sym_h (&h, &sym, &sym_sec, NULL, &local_syms,
elf_bfd_final_link if we are emitting relocs. */
rel_hdr = _bfd_elf_single_rel_hdr (sec);
rel_hdr->sh_size = sec->reloc_count * rel_hdr->sh_entsize;
- some_edited = TRUE;
+ some_edited = true;
}
else if (elf_section_data (sec)->relocs != relstart)
free (relstart);
p = bfd_malloc (need_pad->size + 8);
if (p == NULL)
- return FALSE;
+ return false;
if (!bfd_get_section_contents (need_pad->owner, need_pad,
p, 0, need_pad->size))
- return FALSE;
+ return false;
need_pad->contents = p;
need_pad->flags |= (SEC_IN_MEMORY | SEC_HAS_CONTENTS);
{
p = bfd_realloc (need_pad->contents, need_pad->size + 8);
if (p == NULL)
- return FALSE;
+ return false;
need_pad->contents = p;
}
need_pad->size += 8;
}
- 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
ppc64_elf_inline_plt (struct bfd_link_info *info)
{
struct ppc_link_hash_table *htab;
htab = ppc_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
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
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++)
free (relstart);
if (symtab_hdr->contents != (bfd_byte *) local_syms)
free (local_syms);
- return FALSE;
+ return false;
}
if (sym_sec != NULL && sym_sec->output_section != NULL)
}
}
- return TRUE;
+ return true;
}
-/* Set htab->tls_get_addr and call the generic ELF tls_setup function. */
+/* Set htab->tls_get_addr and various other info specific to TLS.
+ This needs to run before dynamic symbols are processed in
+ bfd_elf_size_dynamic_sections. */
-asection *
+bool
ppc64_elf_tls_setup (struct bfd_link_info *info)
{
struct ppc_link_hash_table *htab;
htab = ppc_hash_table (info);
if (htab == NULL)
- return NULL;
+ return false;
if (abiversion (info->output_bfd) == 1)
htab->opd_abi = 1;
--plt-localentry can cause trouble. */
if (htab->params->plt_localentry0 < 0)
htab->params->plt_localentry0 = 0;
+ if (htab->params->plt_localentry0 && htab->has_power10_relocs)
+ {
+ /* The issue is that __glink_PLTresolve saves r2, which is done
+ because glibc ld.so _dl_runtime_resolve restores r2 to support
+ a glibc plt call optimisation where global entry code is
+ skipped on calls that resolve to the same binary. The
+ __glink_PLTresolve save of r2 is incompatible with code
+ making tail calls, because the tail call might go via the
+ resolver and thus overwrite the proper saved r2. */
+ _bfd_error_handler (_("warning: --plt-localentry is incompatible with "
+ "power10 pc-relative code"));
+ htab->params->plt_localentry0 = 0;
+ }
if (htab->params->plt_localentry0
&& elf_link_hash_lookup (&htab->elf, "GLIBC_2.26",
- FALSE, FALSE, FALSE) == NULL)
+ false, false, false) == NULL)
_bfd_error_handler
(_("warning: --plt-localentry is especially dangerous without "
"ld.so support to detect ABI violations"));
tga = elf_link_hash_lookup (&htab->elf, ".__tls_get_addr",
- FALSE, FALSE, TRUE);
+ false, false, true);
htab->tls_get_addr = ppc_elf_hash_entry (tga);
/* Move dynamic linking info to the function descriptor sym. */
if (tga != NULL)
func_desc_adjust (tga, info);
tga_fd = elf_link_hash_lookup (&htab->elf, "__tls_get_addr",
- FALSE, FALSE, TRUE);
+ false, false, true);
htab->tls_get_addr_fd = ppc_elf_hash_entry (tga_fd);
desc = elf_link_hash_lookup (&htab->elf, ".__tls_get_addr_desc",
- FALSE, FALSE, TRUE);
+ false, false, true);
htab->tga_desc = ppc_elf_hash_entry (desc);
if (desc != NULL)
func_desc_adjust (desc, info);
desc_fd = elf_link_hash_lookup (&htab->elf, "__tls_get_addr_desc",
- FALSE, FALSE, TRUE);
+ false, false, true);
htab->tga_desc_fd = ppc_elf_hash_entry (desc_fd);
if (htab->params->tls_get_addr_opt)
struct elf_link_hash_entry *opt, *opt_fd;
opt = elf_link_hash_lookup (&htab->elf, ".__tls_get_addr_opt",
- FALSE, FALSE, TRUE);
+ false, false, true);
if (opt != NULL)
func_desc_adjust (opt, info);
opt_fd = elf_link_hash_lookup (&htab->elf, "__tls_get_addr_opt",
- FALSE, FALSE, TRUE);
+ false, false, true);
if (opt_fd != NULL
&& (opt_fd->root.type == bfd_link_hash_defined
|| opt_fd->root.type == bfd_link_hash_defweak))
_bfd_elf_strtab_delref (elf_hash_table (info)->dynstr,
opt_fd->dynstr_index);
if (!bfd_elf_link_record_dynamic_symbol (info, opt_fd))
- return NULL;
+ return false;
}
if (tga_fd != NULL)
{
htab->tls_get_addr_fd = ppc_elf_hash_entry (opt_fd);
- tga = &htab->tls_get_addr->elf;
+ tga = elf_hash_entry (htab->tls_get_addr);
if (opt != NULL && tga != NULL)
{
tga->root.type = bfd_link_hash_indirect;
&& htab->params->no_tls_get_addr_regsave == -1)
htab->params->no_tls_get_addr_regsave = 0;
- return _bfd_elf_tls_setup (info->output_bfd, info);
+ return true;
}
/* Return TRUE iff REL is a branch reloc with a global symbol matching
any of HASH1, HASH2, HASH3, or HASH4. */
-static bfd_boolean
-branch_reloc_hash_match (const bfd *ibfd,
- const Elf_Internal_Rela *rel,
- const struct ppc_link_hash_entry *hash1,
- const struct ppc_link_hash_entry *hash2,
- const struct ppc_link_hash_entry *hash3,
- const struct ppc_link_hash_entry *hash4)
+static bool
+branch_reloc_hash_match (bfd *ibfd,
+ Elf_Internal_Rela *rel,
+ struct ppc_link_hash_entry *hash1,
+ struct ppc_link_hash_entry *hash2,
+ struct ppc_link_hash_entry *hash3,
+ struct ppc_link_hash_entry *hash4)
{
Elf_Internal_Shdr *symtab_hdr = &elf_symtab_hdr (ibfd);
enum elf_ppc64_reloc_type r_type = ELF64_R_TYPE (rel->r_info);
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
h = elf_follow_link (h);
- if (h == &hash1->elf || h == &hash2->elf
- || h == &hash3->elf || h == &hash4->elf)
- return TRUE;
+ if (h == elf_hash_entry (hash1)
+ || h == elf_hash_entry (hash2)
+ || h == elf_hash_entry (hash3)
+ || h == elf_hash_entry (hash4))
+ return true;
}
- return FALSE;
+ return false;
}
/* Run through all the TLS relocs looking for optimization
to know the tp offset, and we need to optimize before allocating
dynamic relocations. */
-bfd_boolean
+bool
ppc64_elf_tls_optimize (struct bfd_link_info *info)
{
bfd *ibfd;
int pass;
if (!bfd_link_executable (info))
- return TRUE;
+ return true;
htab = ppc_hash_table (info);
if (htab == NULL)
- return FALSE;
+ return false;
+
+ htab->do_tls_opt = 1;
/* Make two passes over the relocs. On the first pass, mark toc
entries involved with tls relocs, and check that tls relocs
if (sec->has_tls_reloc && !bfd_is_abs_section (sec->output_section))
{
Elf_Internal_Rela *relstart, *rel, *relend;
- bfd_boolean found_tls_get_addr_arg = 0;
+ bool found_tls_get_addr_arg = 0;
/* Read the relocations. */
relstart = _bfd_elf_link_read_relocs (ibfd, sec, NULL, NULL,
if (relstart == NULL)
{
free (toc_ref);
- return FALSE;
+ return false;
}
relend = relstart + sec->reloc_count;
unsigned char *tls_mask;
unsigned int tls_set, tls_clear, tls_type = 0;
bfd_vma value;
- bfd_boolean ok_tprel, is_local;
+ bool ok_tprel, is_local;
long toc_ref_index = 0;
int expecting_tls_get_addr = 0;
- bfd_boolean ret = FALSE;
+ bool ret = false;
r_symndx = ELF64_R_SYM (rel->r_info);
if (!get_sym_h (&h, &sym, &sym_sec, &tls_mask, &locsyms,
STT_TLS. So no need for .opd local sym adjust. */
value = sym->st_value;
- ok_tprel = FALSE;
+ ok_tprel = false;
is_local = SYMBOL_REFERENCES_LOCAL (info, h);
if (is_local)
{
if (h != NULL
&& h->root.type == bfd_link_hash_undefweak)
- ok_tprel = TRUE;
+ ok_tprel = true;
else if (sym_sec != NULL
&& sym_sec->output_section != NULL)
{
info->callbacks->minfo (_("%H __tls_get_addr lost arg, "
"TLS optimization disabled\n"),
ibfd, sec, rel->r_offset);
- ret = TRUE;
+ ret = true;
goto err_free_rel;
}
}
break;
+ case R_PPC64_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))
+ goto err_free_rel;
+ insn = bfd_get_32 (ibfd, buf);
+ /* addis rt,13,imm */
+ if ((insn & ((0x3fu << 26) | 0x1f << 16))
+ != ((15u << 26) | (13 << 16)))
+ {
+ /* xgettext:c-format */
+ info->callbacks->minfo
+ (_("%H: warning: %s unexpected insn %#x.\n"),
+ ibfd, sec, off, "R_PPC64_TPREL16_HA", insn);
+ htab->do_tls_opt = 0;
+ }
+ }
+ continue;
+
+ case R_PPC64_TPREL16_HI:
+ case R_PPC64_TPREL16_HIGH:
+ case R_PPC64_TPREL16_HIGHA:
+ case R_PPC64_TPREL16_HIGHER:
+ case R_PPC64_TPREL16_HIGHERA:
+ case R_PPC64_TPREL16_HIGHEST:
+ case R_PPC64_TPREL16_HIGHESTA:
+ /* These can all be used in sequences along with
+ TPREL16_LO or TPREL16_LO_DS in ways we aren't
+ able to verify easily. */
+ htab->do_tls_opt = 0;
+ continue;
+
default:
continue;
}
info->callbacks->minfo (_("%H arg lost __tls_get_addr, "
"TLS optimization disabled\n"),
ibfd, sec, rel->r_offset);
- ret = TRUE;
+ ret = true;
goto err_free_rel;
}
we'll lose one or two dyn relocs. */
if (!dec_dynrel_count (rel->r_info, sec, info,
NULL, h, sym))
- return FALSE;
+ return false;
if (tls_set == (TLS_EXPLICIT | TLS_GD))
{
if (!dec_dynrel_count ((rel + 1)->r_info, sec, info,
NULL, h, sym))
- return FALSE;
+ return false;
}
}
}
free (toc_ref);
- htab->do_tls_opt = 1;
- return TRUE;
+ return true;
}
/* Called via elf_link_hash_traverse from ppc64_elf_edit_toc to adjust
{
asection *toc;
unsigned long *skip;
- bfd_boolean global_toc_syms;
+ bool global_toc_syms;
};
enum toc_skip_enum { ref_from_discarded = 1, can_optimize = 2 };
-static bfd_boolean
+static bool
adjust_toc_syms (struct elf_link_hash_entry *h, void *inf)
{
struct ppc_link_hash_entry *eh;
if (h->root.type != bfd_link_hash_defined
&& h->root.type != bfd_link_hash_defweak)
- return TRUE;
+ return true;
eh = ppc_elf_hash_entry (h);
if (eh->adjust_done)
- return TRUE;
+ return true;
if (eh->elf.root.u.def.section == toc_inf->toc)
{
eh->adjust_done = 1;
}
else if (strcmp (eh->elf.root.u.def.section->name, ".toc") == 0)
- toc_inf->global_toc_syms = TRUE;
+ toc_inf->global_toc_syms = true;
- return TRUE;
+ return true;
}
/* Return TRUE iff INSN with a relocation of R_TYPE is one we expect
on a _LO variety toc/got reloc. */
-static bfd_boolean
+static bool
ok_lo_toc_insn (unsigned int insn, enum elf_ppc64_reloc_type r_type)
{
return ((insn & (0x3fu << 26)) == 12u << 26 /* addic */
the pld can be replaced with pla: *PINSN1 is that pla insn,
while *PINSN2 is the second instruction. */
-static bfd_boolean
+static bool
xlate_pcrel_opt (uint64_t *pinsn1, uint64_t *pinsn2, bfd_signed_vma *poff)
{
uint64_t insn1 = *pinsn1;
{
/* Check that regs match. */
if (((insn2 >> 16) & 31) != ((insn1 >> 21) & 31))
- return FALSE;
+ return false;
/* P8LS or PMLS form, non-pcrel. */
if ((insn2 & (-1ULL << 50) & ~(1ULL << 56)) != (1ULL << 58))
- return FALSE;
+ return false;
*pinsn1 = (insn2 & ~(31 << 16) & ~0x3ffff0000ffffULL) | (1ULL << 52);
*pinsn2 = PNOP;
off = ((insn2 >> 16) & 0x3ffff0000ULL) | (insn2 & 0xffff);
*poff = (off ^ 0x200000000ULL) - 0x200000000ULL;
- return TRUE;
+ return true;
}
insn2 >>= 32;
/* Check that regs match. */
if (((insn2 >> 16) & 31) != ((insn1 >> 21) & 31))
- return FALSE;
+ return false;
switch ((insn2 >> 26) & 63)
{
default:
- return FALSE;
+ return false;
case 32: /* lwz */
case 34: /* lbz */
case 58: /* lwa, ld */
if ((insn2 & 1) != 0)
- return FALSE;
+ return false;
insn1 = ((1ULL << 58) | (1ULL << 52)
| (insn2 & 2 ? 41ULL << 26 : 57ULL << 26)
| (insn2 & (31ULL << 21)));
case 57: /* lxsd, lxssp */
if ((insn2 & 3) < 2)
- return FALSE;
+ return false;
insn1 = ((1ULL << 58) | (1ULL << 52)
| ((40ULL | (insn2 & 3)) << 26)
| (insn2 & (31ULL << 21)));
case 61: /* stxsd, stxssp, lxv, stxv */
if ((insn2 & 3) == 0)
- return FALSE;
+ return false;
else if ((insn2 & 3) >= 2)
{
insn1 = ((1ULL << 58) | (1ULL << 52)
case 6: /* lxvp, stxvp */
if ((insn2 & 0xe) != 0)
- return FALSE;
+ return false;
insn1 = ((1ULL << 58) | (1ULL << 52)
| ((insn2 & 1) == 0 ? 58ULL << 26 : 62ULL << 26)
| (insn2 & (31ULL << 21)));
case 62: /* std, stq */
if ((insn2 & 1) != 0)
- return FALSE;
+ return false;
insn1 = ((1ULL << 58) | (1ULL << 52)
| ((insn2 & 2) == 0 ? 61ULL << 26 : 60ULL << 26)
| (insn2 & (31ULL << 21)));
*pinsn1 = insn1;
*pinsn2 = (uint64_t) NOP << 32;
*poff = (off ^ 0x8000) - 0x8000;
- return TRUE;
+ return true;
}
/* Examine all relocs referencing .toc sections in order to remove
unused .toc entries. */
-bfd_boolean
+bool
ppc64_elf_edit_toc (struct bfd_link_info *info)
{
bfd *ibfd;
struct ppc_link_hash_table *htab = ppc_hash_table (info);
htab->do_toc_opt = 1;
- toc_inf.global_toc_syms = TRUE;
+ toc_inf.global_toc_syms = true;
for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
{
asection *toc, *sec;
|| (sec->flags & SEC_DEBUGGING) != 0)
continue;
- relstart = _bfd_elf_link_read_relocs (ibfd, sec, NULL, NULL, FALSE);
+ relstart = _bfd_elf_link_read_relocs (ibfd, sec, NULL, NULL, false);
if (relstart == NULL)
goto error_ret;
if (elf_section_data (toc)->relocs != toc_relocs)
free (toc_relocs);
free (skip);
- return FALSE;
+ return false;
}
/* Now check all kept sections that might reference the toc.
bfd_byte *contents, *src;
unsigned long off;
Elf_Internal_Sym *sym;
- bfd_boolean local_toc_syms = FALSE;
+ bool local_toc_syms = false;
/* Shuffle the toc contents, and at the same time convert the
skip array from booleans into offsets. */
{
val = sym->st_value;
if (val != 0)
- local_toc_syms = TRUE;
+ local_toc_syms = true;
}
val += rel->r_addend;
{
toc_inf.toc = toc;
toc_inf.skip = skip;
- toc_inf.global_toc_syms = FALSE;
+ toc_inf.global_toc_syms = false;
elf_link_hash_traverse (elf_hash_table (info), adjust_toc_syms,
&toc_inf);
}
if (sec != NULL
&& elf_section_data (sec)->relocs != relstart)
free (relstart);
- return FALSE;
+ return false;
}
for (rel = relstart; rel < relstart + sec->reloc_count; ++rel)
}
}
- return TRUE;
+ return true;
}
/* Return true iff input section I references the TOC using
instructions limited to +/-32k offsets. */
-bfd_boolean
+bool
ppc64_elf_has_small_toc_reloc (asection *i)
{
return (is_ppc64_elf (i->owner)
&& ent2->tls_type == ent->tls_type
&& elf_gp (ent2->owner) == elf_gp (ent->owner))
{
- ent2->is_indirect = TRUE;
+ ent2->is_indirect = true;
ent2->got.ent = ent;
}
}
/* 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)
{
&& !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 .plt, .got and 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;
struct got_entry **pgent, *gent;
if (h->root.type == bfd_link_hash_indirect)
- return TRUE;
+ return true;
info = (struct bfd_link_info *) inf;
htab = ppc_hash_table (info);
if (htab == NULL)
- return FALSE;
+ return false;
eh = ppc_elf_hash_entry (h);
/* Run through the TLS GD got entries first if we're changing them
/* Ensure we catch all the cases where this symbol should
be made dynamic. */
if (!ensure_undef_dynamic (info, h))
- return FALSE;
+ return false;
if (!is_ppc64_elf (gent->owner))
abort ();
/* Ensure we catch all the cases where this symbol
should be made dynamic. */
if (!ensure_undef_dynamic (info, h))
- return FALSE;
+ return false;
}
}
relocs against symbols which are not dynamic. */
else if (h->type != STT_GNU_IFUNC)
{
- 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))
{
/* Ensure we catch all the cases where this symbol
should be made dynamic. */
if (!ensure_undef_dynamic (info, h))
- return FALSE;
+ return false;
/* But if that didn't work out, discard dynamic relocs. */
if (h->dynindx == -1)
& (TLS_TLS | PLT_KEEP)) == PLT_KEEP))
{
struct plt_entry *pent;
- bfd_boolean doneone = FALSE;
+ bool doneone = false;
for (pent = h->plt.plist; pent != NULL; pent = pent->next)
if (pent->plt.refcount > 0)
{
- if (!htab->elf.dynamic_sections_created
- || h->dynindx == -1)
+ if (!ensure_undef_dynamic (info, h))
+ return false;
+
+ if (use_local_plt (info, h))
{
if (h->type == STT_GNU_IFUNC)
{
}
if (s != NULL)
s->size += sizeof (Elf64_External_Rela);
- doneone = TRUE;
+ doneone = true;
}
else
pent->plt.offset = (bfd_vma) -1;
h->needs_plt = 0;
}
- return TRUE;
+ return true;
}
#define PPC_LO(v) ((v) & 0xffff)
to set up space for global entry stubs. These are put in glink,
after the branch table. */
-static bfd_boolean
+static bool
size_global_entry_stubs (struct elf_link_hash_entry *h, void *inf)
{
struct bfd_link_info *info;
asection *s, *plt;
if (h->root.type == bfd_link_hash_indirect)
- return TRUE;
+ return true;
if (!h->pointer_equality_needed)
- return TRUE;
+ return true;
if (h->def_regular)
- return TRUE;
+ return true;
info = inf;
htab = ppc_hash_table (info);
if (htab == NULL)
- return FALSE;
+ return false;
s = htab->global_entry;
plt = htab->elf.splt;
s->size = stub_off + stub_size;
break;
}
- return TRUE;
+ return true;
}
/* Set the sizes of the dynamic sections. */
-static bfd_boolean
+static bool
ppc64_elf_size_dynamic_sections (bfd *output_bfd,
struct bfd_link_info *info)
{
struct ppc_link_hash_table *htab;
bfd *dynobj;
asection *s;
- bfd_boolean relocs;
+ bool relocs;
bfd *ibfd;
struct got_entry *first_tlsld;
htab = ppc_hash_table (info);
if (htab == NULL)
- return FALSE;
+ return false;
dynobj = htab->elf.dynobj;
if (dynobj == NULL)
{
if (!htab->do_multi_toc && first_tlsld != NULL)
{
- ent->is_indirect = TRUE;
+ ent->is_indirect = true;
ent->got.ent = first_tlsld;
}
else
/* We now have determined the sizes of the various dynamic sections.
Allocate memory for them. */
- relocs = FALSE;
+ relocs = false;
for (s = dynobj->sections; s != NULL; s = s->next)
{
if ((s->flags & SEC_LINKER_CREATED) == 0)
/* Not sized yet. */
continue;
}
- else if (CONST_STRNEQ (s->name, ".rela"))
+ else if (startswith (s->name, ".rela"))
{
if (s->size != 0)
{
if (s != htab->elf.srelplt)
- relocs = TRUE;
+ relocs = true;
/* We use the reloc_count field as a counter if we need
to copy relocs into the output file. */
the GOT and .dynrelro. */
s->contents = bfd_zalloc (dynobj, s->size);
if (s->contents == NULL)
- return FALSE;
+ return false;
}
for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
{
s->contents = bfd_zalloc (ibfd, s->size);
if (s->contents == NULL)
- return FALSE;
+ return false;
}
}
s = ppc64_elf_tdata (ibfd)->relgot;
{
s->contents = bfd_zalloc (ibfd, s->size);
if (s->contents == NULL)
- return FALSE;
- relocs = TRUE;
+ return false;
+ relocs = true;
s->reloc_count = 0;
}
}
if (htab->elf.dynamic_sections_created)
{
- bfd_boolean tls_opt;
+ bool tls_opt;
/* Add some entries to the .dynamic section. We fill in the
values later, in ppc64_elf_finish_dynamic_sections, but we
if (bfd_link_executable (info))
{
if (!add_dynamic_entry (DT_DEBUG, 0))
- return FALSE;
+ return false;
}
if (htab->elf.splt != NULL && htab->elf.splt->size != 0)
|| !add_dynamic_entry (DT_PLTREL, DT_RELA)
|| !add_dynamic_entry (DT_JMPREL, 0)
|| !add_dynamic_entry (DT_PPC64_GLINK, 0))
- return FALSE;
+ return false;
}
if (NO_OPD_RELOCS && abiversion (output_bfd) <= 1)
{
if (!add_dynamic_entry (DT_PPC64_OPD, 0)
|| !add_dynamic_entry (DT_PPC64_OPDSZ, 0))
- return FALSE;
+ return false;
}
tls_opt = (htab->params->tls_get_addr_opt
if (tls_opt || !htab->opd_abi)
{
if (!add_dynamic_entry (DT_PPC64_OPT, tls_opt ? PPC64_OPT_TLS : 0))
- return FALSE;
+ return false;
}
if (relocs)
if (!add_dynamic_entry (DT_RELA, 0)
|| !add_dynamic_entry (DT_RELASZ, 0)
|| !add_dynamic_entry (DT_RELAENT, sizeof (Elf64_External_Rela)))
- return FALSE;
+ 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)
{
if (!add_dynamic_entry (DT_TEXTREL, 0))
- return FALSE;
+ return false;
}
}
}
#undef add_dynamic_entry
- return TRUE;
+ return true;
}
/* Return TRUE if symbol should be hashed in the `.gnu.hash' section. */
-static bfd_boolean
+static bool
ppc64_elf_hash_symbol (struct elf_link_hash_entry *h)
{
if (h->plt.plist != NULL
&& !h->def_regular
&& !h->pointer_equality_needed)
- return FALSE;
+ return false;
return _bfd_elf_hash_symbol (h);
}
. add/ldx %r12,%r11,%r12 */
static bfd_byte *
-build_offset (bfd *abfd, bfd_byte *p, bfd_vma off, bfd_boolean load)
+build_offset (bfd *abfd, bfd_byte *p, bfd_vma off, bool load)
{
bfd_put_32 (abfd, MFLR_R12, p);
p += 4;
static bfd_byte *
build_power10_offset (bfd *abfd, bfd_byte *p, bfd_vma off, int odd,
- bfd_boolean load)
+ bool load)
{
uint64_t insn;
if (off - odd + (1ULL << 33) < 1ULL << 34)
static inline unsigned int
plt_stub_size (struct ppc_link_hash_table *htab,
struct ppc_stub_hash_entry *stub_entry,
- bfd_vma off)
+ bfd_vma off,
+ unsigned int odd)
{
unsigned size;
if (stub_entry->stub_type >= ppc_stub_plt_call_notoc)
{
if (htab->params->power10_stubs != 0)
- {
- bfd_vma start = (stub_entry->stub_offset
- + stub_entry->group->stub_sec->output_offset
- + stub_entry->group->stub_sec->output_section->vma);
- if (stub_entry->stub_type > ppc_stub_plt_call_notoc)
- start += 4;
- size = 8 + size_power10_offset (off, start & 4);
- }
+ size = 8 + size_power10_offset (off, odd);
else
size = 8 + size_offset (off - 8);
if (stub_entry->stub_type > ppc_stub_plt_call_notoc)
size += 4;
- return size;
}
-
- size = 12;
- if (ALWAYS_EMIT_R2SAVE
- || stub_entry->stub_type == ppc_stub_plt_call_r2save)
- size += 4;
- if (PPC_HA (off) != 0)
- size += 4;
- if (htab->opd_abi)
+ else
{
- size += 4;
- if (htab->params->plt_static_chain)
+ size = 12;
+ if (ALWAYS_EMIT_R2SAVE
+ || stub_entry->stub_type == ppc_stub_plt_call_r2save)
size += 4;
- if (htab->params->plt_thread_safe
- && htab->elf.dynamic_sections_created
- && stub_entry->h != NULL
- && stub_entry->h->elf.dynindx != -1)
- size += 8;
- if (PPC_HA (off + 8 + 8 * htab->params->plt_static_chain) != PPC_HA (off))
+ if (PPC_HA (off) != 0)
size += 4;
+ if (htab->opd_abi)
+ {
+ size += 4;
+ if (htab->params->plt_static_chain)
+ size += 4;
+ if (htab->params->plt_thread_safe
+ && htab->elf.dynamic_sections_created
+ && stub_entry->h != NULL
+ && stub_entry->h->elf.dynindx != -1)
+ size += 8;
+ if (PPC_HA (off + 8 + 8 * htab->params->plt_static_chain)
+ != PPC_HA (off))
+ size += 4;
+ }
}
if (stub_entry->h != NULL
&& is_tls_get_addr (&stub_entry->h->elf, htab)
&& htab->params->tls_get_addr_opt)
{
- if (htab->params->no_tls_get_addr_regsave)
+ if (!htab->params->no_tls_get_addr_regsave)
{
- size += 7 * 4;
- if (stub_entry->stub_type == ppc_stub_plt_call_r2save)
- size += 6 * 4;
+ size += 30 * 4;
+ if (stub_entry->stub_type == ppc_stub_plt_call_r2save
+ || stub_entry->stub_type == ppc_stub_plt_call_both)
+ size += 4;
}
else
{
- size += 30 * 4;
- if (stub_entry->stub_type == ppc_stub_plt_call_r2save)
- size += 4;
+ size += 7 * 4;
+ if (stub_entry->stub_type == ppc_stub_plt_call_r2save
+ || stub_entry->stub_type == ppc_stub_plt_call_both)
+ size += 6 * 4;
}
}
return size;
static inline unsigned int
plt_stub_pad (struct ppc_link_hash_table *htab,
struct ppc_stub_hash_entry *stub_entry,
- bfd_vma plt_off)
+ bfd_vma plt_off,
+ unsigned int odd)
{
int stub_align;
unsigned stub_size;
}
stub_align = 1 << -htab->params->plt_stub_align;
- stub_size = plt_stub_size (htab, stub_entry, plt_off);
+ stub_size = plt_stub_size (htab, stub_entry, plt_off, odd);
if (((stub_off + stub_size - 1) & -stub_align) - (stub_off & -stub_align)
> ((stub_size - 1) & -stub_align))
return stub_align - (stub_off & (stub_align - 1));
bfd_byte *p, bfd_vma offset, Elf_Internal_Rela *r)
{
bfd *obfd = htab->params->stub_bfd;
- bfd_boolean plt_load_toc = htab->opd_abi;
- bfd_boolean plt_static_chain = htab->params->plt_static_chain;
- bfd_boolean plt_thread_safe = (htab->params->plt_thread_safe
- && htab->elf.dynamic_sections_created
- && stub_entry->h != NULL
- && stub_entry->h->elf.dynindx != -1);
- bfd_boolean use_fake_dep = plt_thread_safe;
+ bool plt_load_toc = htab->opd_abi;
+ bool plt_static_chain = htab->params->plt_static_chain;
+ bool plt_thread_safe = (htab->params->plt_thread_safe
+ && htab->elf.dynamic_sections_created
+ && stub_entry->h != NULL
+ && stub_entry->h->elf.dynindx != -1);
+ bool use_fake_dep = plt_thread_safe;
bfd_vma cmp_branch_off = 0;
if (!ALWAYS_USE_FAKE_DEP
&& plt_load_toc
&& plt_thread_safe
- && !(is_tls_get_addr (&stub_entry->h->elf, htab)
+ && !(stub_entry->h != NULL
+ && is_tls_get_addr (&stub_entry->h->elf, htab)
&& htab->params->tls_get_addr_opt))
{
bfd_vma pltoff = stub_entry->plt_ent->plt.offset & ~1;
#define MR_R3_R0 0x7c030378
#define BCTRL 0x4e800421
-static inline bfd_byte *
-build_tls_get_addr_stub (struct ppc_link_hash_table *htab,
+static bfd_byte *
+build_tls_get_addr_head (struct ppc_link_hash_table *htab,
struct ppc_stub_hash_entry *stub_entry,
- bfd_byte *p, bfd_vma offset, Elf_Internal_Rela *r)
+ bfd_byte *p)
{
bfd *obfd = htab->params->stub_bfd;
- bfd_byte *loc = p;
- unsigned int i;
bfd_put_32 (obfd, LD_R0_0R3 + 0, p), p += 4;
bfd_put_32 (obfd, LD_R12_0R3 + 8, p), p += 4;
bfd_put_32 (obfd, ADD_R3_R12_R13, p), p += 4;
bfd_put_32 (obfd, BEQLR, p), p += 4;
bfd_put_32 (obfd, MR_R3_R0, p), p += 4;
- if (htab->params->no_tls_get_addr_regsave)
- {
- if (r != NULL)
- r[0].r_offset += 7 * 4;
- if (stub_entry->stub_type != ppc_stub_plt_call_r2save)
- return build_plt_stub (htab, stub_entry, p, offset, r);
+ if (!htab->params->no_tls_get_addr_regsave)
+ p = tls_get_addr_prologue (obfd, p, htab);
+ else if (stub_entry->stub_type == ppc_stub_plt_call_r2save
+ || stub_entry->stub_type == ppc_stub_plt_call_both)
+ {
bfd_put_32 (obfd, MFLR_R0, p);
p += 4;
bfd_put_32 (obfd, STD_R0_0R1 + STK_LINKER (htab), p);
p += 4;
+ }
+ return p;
+}
- if (r != NULL)
- r[0].r_offset += 2 * 4;
- p = build_plt_stub (htab, stub_entry, p, offset, r);
+static bfd_byte *
+build_tls_get_addr_tail (struct ppc_link_hash_table *htab,
+ struct ppc_stub_hash_entry *stub_entry,
+ bfd_byte *p,
+ bfd_byte *loc)
+{
+ bfd *obfd = htab->params->stub_bfd;
+
+ if (!htab->params->no_tls_get_addr_regsave)
+ {
+ bfd_put_32 (obfd, BCTRL, p - 4);
+
+ if (stub_entry->stub_type == ppc_stub_plt_call_r2save
+ || stub_entry->stub_type == ppc_stub_plt_call_both)
+ {
+ bfd_put_32 (obfd, LD_R2_0R1 + STK_TOC (htab), p);
+ p += 4;
+ }
+ p = tls_get_addr_epilogue (obfd, p, htab);
+ }
+ else if (stub_entry->stub_type == ppc_stub_plt_call_r2save
+ || stub_entry->stub_type == ppc_stub_plt_call_both)
+ {
bfd_put_32 (obfd, BCTRL, p - 4);
bfd_put_32 (obfd, LD_R2_0R1 + STK_TOC (htab), p);
bfd_put_32 (obfd, BLR, p);
p += 4;
}
- else
- {
- p = tls_get_addr_prologue (obfd, p, htab);
-
- if (r != NULL)
- r[0].r_offset += 18 * 4;
-
- p = build_plt_stub (htab, stub_entry, p, offset, r);
- bfd_put_32 (obfd, BCTRL, p - 4);
-
- if (stub_entry->stub_type == ppc_stub_plt_call_r2save)
- {
- bfd_put_32 (obfd, LD_R2_0R1 + STK_TOC (htab), p);
- p += 4;
- }
-
- p = tls_get_addr_epilogue (obfd, p, htab);
- }
if (htab->glink_eh_frame != NULL
&& htab->glink_eh_frame->size != 0)
base = htab->glink_eh_frame->contents + stub_entry->group->eh_base + 17;
eh = base + stub_entry->group->eh_size;
- if (htab->params->no_tls_get_addr_regsave)
- {
- unsigned int lr_used, delta;
- lr_used = stub_entry->stub_offset + (p - 20 - loc);
- delta = lr_used - stub_entry->group->lr_restore;
- stub_entry->group->lr_restore = lr_used + 16;
- eh = eh_advance (htab->elf.dynobj, eh, delta);
- *eh++ = DW_CFA_offset_extended_sf;
- *eh++ = 65;
- *eh++ = -(STK_LINKER (htab) / 8) & 0x7f;
- *eh++ = DW_CFA_advance_loc + 4;
- }
- else
+
+ if (!htab->params->no_tls_get_addr_regsave)
{
- unsigned int cfa_updt, delta;
+ unsigned int cfa_updt, delta, i;
+
/* After the bctrl, lr has been modified so we need to emit
.eh_frame info saying the return address is on the stack. In
fact we must put the EH info at or before the call rather
for (i = 4; i < 12; i++)
*eh++ = DW_CFA_restore + i;
*eh++ = DW_CFA_advance_loc + 2;
+ *eh++ = DW_CFA_restore_extended;
+ *eh++ = 65;
+ stub_entry->group->eh_size = eh - base;
+ }
+ else if (stub_entry->stub_type == ppc_stub_plt_call_r2save
+ || stub_entry->stub_type == ppc_stub_plt_call_both)
+ {
+ unsigned int lr_used, delta;
+
+ lr_used = stub_entry->stub_offset + (p - 20 - loc);
+ delta = lr_used - stub_entry->group->lr_restore;
+ stub_entry->group->lr_restore = lr_used + 16;
+ eh = eh_advance (htab->elf.dynobj, eh, delta);
+ *eh++ = DW_CFA_offset_extended_sf;
+ *eh++ = 65;
+ *eh++ = -(STK_LINKER (htab) / 8) & 0x7f;
+ *eh++ = DW_CFA_advance_loc + 4;
+ *eh++ = DW_CFA_restore_extended;
+ *eh++ = 65;
+ stub_entry->group->eh_size = eh - base;
}
- *eh++ = DW_CFA_restore_extended;
- *eh++ = 65;
- stub_entry->group->eh_size = eh - base;
}
return p;
}
forms, to the equivalent relocs against the global symbol given by
STUB_ENTRY->H. */
-static bfd_boolean
+static bool
use_global_in_relocs (struct ppc_link_hash_table *htab,
struct ppc_stub_hash_entry *stub_entry,
Elf_Internal_Rela *r, unsigned int num_rel)
hsize = (htab->stub_globals + 1) * sizeof (*hashes);
hashes = bfd_zalloc (htab->params->stub_bfd, hsize);
if (hashes == NULL)
- return FALSE;
+ return false;
elf_sym_hashes (htab->params->stub_bfd) = hashes;
htab->stub_globals = 1;
}
r->r_addend -= symval;
--r;
}
- return TRUE;
+ return true;
}
static bfd_vma
return r2off;
}
-static bfd_boolean
+static bool
ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
{
struct ppc_stub_hash_entry *stub_entry;
struct ppc_branch_hash_entry *br_entry;
struct bfd_link_info *info;
struct ppc_link_hash_table *htab;
+ bfd *obfd;
bfd_byte *loc;
bfd_byte *p, *relp;
bfd_vma targ, off;
asection *plt;
int num_rel;
int odd;
+ bool is_tga;
/* Massage our args to the form they really have. */
stub_entry = (struct ppc_stub_hash_entry *) gen_entry;
htab = ppc_hash_table (info);
if (htab == NULL)
- return FALSE;
+ return false;
BFD_ASSERT (stub_entry->stub_offset >= stub_entry->group->stub_sec->size);
loc = stub_entry->group->stub_sec->contents + stub_entry->stub_offset;
off = targ - off;
p = loc;
+ obfd = htab->params->stub_bfd;
if (stub_entry->stub_type == ppc_stub_long_branch_r2off)
{
bfd_vma r2off = get_r2off (info, stub_entry);
if (r2off == (bfd_vma) -1)
{
- htab->stub_error = TRUE;
- return FALSE;
+ htab->stub_error = true;
+ return false;
}
- bfd_put_32 (htab->params->stub_bfd, STD_R2_0R1 + STK_TOC (htab), p);
+ bfd_put_32 (obfd, STD_R2_0R1 + STK_TOC (htab), p);
p += 4;
if (PPC_HA (r2off) != 0)
{
- bfd_put_32 (htab->params->stub_bfd,
- ADDIS_R2_R2 | PPC_HA (r2off), p);
+ bfd_put_32 (obfd, ADDIS_R2_R2 | PPC_HA (r2off), p);
p += 4;
}
if (PPC_LO (r2off) != 0)
{
- bfd_put_32 (htab->params->stub_bfd,
- ADDI_R2_R2 | PPC_LO (r2off), p);
+ bfd_put_32 (obfd, ADDI_R2_R2 | PPC_LO (r2off), p);
p += 4;
}
off -= p - loc;
}
- bfd_put_32 (htab->params->stub_bfd, B_DOT | (off & 0x3fffffc), p);
+ bfd_put_32 (obfd, B_DOT | (off & 0x3fffffc), p);
p += 4;
if (off + (1 << 25) >= (bfd_vma) (1 << 26))
_bfd_error_handler
(_("long branch stub `%s' offset overflow"),
stub_entry->root.string);
- htab->stub_error = TRUE;
- return FALSE;
+ htab->stub_error = true;
+ return false;
}
if (info->emitrelocations)
{
r = get_relocs (stub_entry->group->stub_sec, 1);
if (r == NULL)
- return FALSE;
+ return false;
r->r_offset = p - 4 - stub_entry->group->stub_sec->contents;
r->r_info = ELF64_R_INFO (0, R_PPC64_REL24);
r->r_addend = targ;
if (stub_entry->h != NULL
&& !use_global_in_relocs (htab, stub_entry, r, 1))
- return FALSE;
+ return false;
}
break;
case ppc_stub_plt_branch_r2off:
br_entry = ppc_branch_hash_lookup (&htab->branch_hash_table,
stub_entry->root.string + 9,
- FALSE, FALSE);
+ false, false);
if (br_entry == NULL)
{
_bfd_error_handler (_("can't find branch stub `%s'"),
stub_entry->root.string);
- htab->stub_error = TRUE;
- return FALSE;
+ htab->stub_error = true;
+ return false;
}
targ = (stub_entry->target_value
{
r = get_relocs (htab->brlt, 1);
if (r == NULL)
- return FALSE;
+ return false;
/* brlt, being SEC_LINKER_CREATED does not go through the
normal reloc processing. Symbols and offsets are not
translated from input file to output file form, so
(_("%P: linkage table error against `%pT'\n"),
stub_entry->root.string);
bfd_set_error (bfd_error_bad_value);
- htab->stub_error = TRUE;
- return FALSE;
+ htab->stub_error = true;
+ return false;
}
if (info->emitrelocations)
{
r = get_relocs (stub_entry->group->stub_sec, 1 + (PPC_HA (off) != 0));
if (r == NULL)
- return FALSE;
+ return false;
r[0].r_offset = loc - stub_entry->group->stub_sec->contents;
if (bfd_big_endian (info->output_bfd))
r[0].r_offset += 2;
}
p = loc;
+ obfd = htab->params->stub_bfd;
if (stub_entry->stub_type != ppc_stub_plt_branch_r2off)
{
if (PPC_HA (off) != 0)
{
- bfd_put_32 (htab->params->stub_bfd,
- ADDIS_R12_R2 | PPC_HA (off), p);
+ bfd_put_32 (obfd, ADDIS_R12_R2 | PPC_HA (off), p);
p += 4;
- bfd_put_32 (htab->params->stub_bfd,
- LD_R12_0R12 | PPC_LO (off), p);
+ bfd_put_32 (obfd, LD_R12_0R12 | PPC_LO (off), p);
}
else
- bfd_put_32 (htab->params->stub_bfd,
- LD_R12_0R2 | PPC_LO (off), p);
+ bfd_put_32 (obfd, LD_R12_0R2 | PPC_LO (off), p);
}
else
{
if (r2off == (bfd_vma) -1)
{
- htab->stub_error = TRUE;
- return FALSE;
+ htab->stub_error = true;
+ return false;
}
- bfd_put_32 (htab->params->stub_bfd, STD_R2_0R1 + STK_TOC (htab), p);
+ bfd_put_32 (obfd, STD_R2_0R1 + STK_TOC (htab), p);
p += 4;
if (PPC_HA (off) != 0)
{
- bfd_put_32 (htab->params->stub_bfd,
- ADDIS_R12_R2 | PPC_HA (off), p);
+ bfd_put_32 (obfd, ADDIS_R12_R2 | PPC_HA (off), p);
p += 4;
- bfd_put_32 (htab->params->stub_bfd,
- LD_R12_0R12 | PPC_LO (off), p);
+ bfd_put_32 (obfd, LD_R12_0R12 | PPC_LO (off), p);
}
else
- bfd_put_32 (htab->params->stub_bfd, LD_R12_0R2 | PPC_LO (off), p);
+ bfd_put_32 (obfd, LD_R12_0R2 | PPC_LO (off), p);
if (PPC_HA (r2off) != 0)
{
p += 4;
- bfd_put_32 (htab->params->stub_bfd,
- ADDIS_R2_R2 | PPC_HA (r2off), p);
+ bfd_put_32 (obfd, ADDIS_R2_R2 | PPC_HA (r2off), p);
}
if (PPC_LO (r2off) != 0)
{
p += 4;
- bfd_put_32 (htab->params->stub_bfd,
- ADDI_R2_R2 | PPC_LO (r2off), p);
+ bfd_put_32 (obfd, ADDI_R2_R2 | PPC_LO (r2off), p);
}
}
p += 4;
- bfd_put_32 (htab->params->stub_bfd, MTCTR_R12, p);
+ bfd_put_32 (obfd, MTCTR_R12, p);
p += 4;
- bfd_put_32 (htab->params->stub_bfd, BCTR, p);
+ bfd_put_32 (obfd, BCTR, p);
p += 4;
break;
off = (stub_entry->stub_offset
+ stub_entry->group->stub_sec->output_offset
+ stub_entry->group->stub_sec->output_section->vma);
+ obfd = htab->params->stub_bfd;
+ is_tga = ((stub_entry->stub_type == ppc_stub_plt_call_notoc
+ || stub_entry->stub_type == ppc_stub_plt_call_both)
+ && stub_entry->h != NULL
+ && is_tls_get_addr (&stub_entry->h->elf, htab)
+ && htab->params->tls_get_addr_opt);
+ if (is_tga)
+ {
+ p = build_tls_get_addr_head (htab, stub_entry, p);
+ off += p - loc;
+ }
if (stub_entry->stub_type == ppc_stub_long_branch_both
|| stub_entry->stub_type == ppc_stub_plt_branch_both
|| stub_entry->stub_type == ppc_stub_plt_call_both)
{
off += 4;
- bfd_put_32 (htab->params->stub_bfd, STD_R2_0R1 + STK_TOC (htab), p);
+ bfd_put_32 (obfd, STD_R2_0R1 + STK_TOC (htab), p);
p += 4;
}
if (stub_entry->stub_type >= ppc_stub_plt_call_notoc)
abort ();
plt = htab->elf.splt;
- if (!htab->elf.dynamic_sections_created
- || stub_entry->h == NULL
- || stub_entry->h->elf.dynindx == -1)
+ if (use_local_plt (info, elf_hash_entry (stub_entry->h)))
{
if (stub_entry->symtype == STT_GNU_IFUNC)
plt = htab->elf.iplt;
num_rel = 0;
if (htab->params->power10_stubs != 0)
{
- bfd_boolean load = stub_entry->stub_type >= ppc_stub_plt_call_notoc;
- p = build_power10_offset (htab->params->stub_bfd, p, off, odd, load);
+ bool load = stub_entry->stub_type >= ppc_stub_plt_call_notoc;
+ p = build_power10_offset (obfd, p, off, odd, load);
}
else
{
+ if (htab->glink_eh_frame != NULL
+ && htab->glink_eh_frame->size != 0)
+ {
+ bfd_byte *base, *eh;
+ unsigned int lr_used, delta;
+
+ base = (htab->glink_eh_frame->contents
+ + stub_entry->group->eh_base + 17);
+ eh = base + stub_entry->group->eh_size;
+ lr_used = stub_entry->stub_offset + (p - loc) + 8;
+ delta = lr_used - stub_entry->group->lr_restore;
+ stub_entry->group->lr_restore = lr_used + 8;
+ eh = eh_advance (htab->elf.dynobj, eh, delta);
+ *eh++ = DW_CFA_register;
+ *eh++ = 65;
+ *eh++ = 12;
+ *eh++ = DW_CFA_advance_loc + 2;
+ *eh++ = DW_CFA_restore_extended;
+ *eh++ = 65;
+ stub_entry->group->eh_size = eh - base;
+ }
+
/* The notoc stubs calculate their target (either a PLT entry or
the global entry point of a function) relative to the PC
returned by the "bcl" two instructions past the start of the
sequence emitted by build_offset. The offset is therefore 8
less than calculated from the start of the sequence. */
off -= 8;
- p = build_offset (htab->params->stub_bfd, p, off,
+ p = build_offset (obfd, p, off,
stub_entry->stub_type >= ppc_stub_plt_call_notoc);
}
+ stub_entry->group->stub_sec->output_offset
+ stub_entry->group->stub_sec->output_section->vma
+ (p - loc));
- bfd_put_32 (htab->params->stub_bfd,
- B_DOT | ((targ - from) & 0x3fffffc), p);
+ bfd_put_32 (obfd, B_DOT | ((targ - from) & 0x3fffffc), p);
}
else
{
- bfd_put_32 (htab->params->stub_bfd, MTCTR_R12, p);
+ bfd_put_32 (obfd, MTCTR_R12, p);
p += 4;
- bfd_put_32 (htab->params->stub_bfd, BCTR, p);
+ bfd_put_32 (obfd, BCTR, p);
}
p += 4;
+ if (is_tga)
+ p = build_tls_get_addr_tail (htab, stub_entry, p, loc);
+
if (info->emitrelocations)
{
bfd_vma roff = relp - stub_entry->group->stub_sec->contents;
}
r = get_relocs (stub_entry->group->stub_sec, num_rel);
if (r == NULL)
- return FALSE;
+ return false;
if (htab->params->power10_stubs != 0)
r = emit_relocs_for_power10_offset (info, r, roff, targ, off, odd);
else
r->r_addend = targ;
if (stub_entry->h != NULL
&& !use_global_in_relocs (htab, stub_entry, r, num_rel))
- return FALSE;
+ return false;
}
}
-
- if (htab->params->power10_stubs == 0
- && htab->glink_eh_frame != NULL
- && htab->glink_eh_frame->size != 0)
- {
- bfd_byte *base, *eh;
- unsigned int lr_used, delta;
-
- base = (htab->glink_eh_frame->contents
- + stub_entry->group->eh_base + 17);
- eh = base + stub_entry->group->eh_size;
- lr_used = stub_entry->stub_offset + 8;
- if (stub_entry->stub_type == ppc_stub_long_branch_both
- || stub_entry->stub_type == ppc_stub_plt_branch_both
- || stub_entry->stub_type == ppc_stub_plt_call_both)
- lr_used += 4;
- delta = lr_used - stub_entry->group->lr_restore;
- stub_entry->group->lr_restore = lr_used + 8;
- eh = eh_advance (htab->elf.dynobj, eh, delta);
- *eh++ = DW_CFA_register;
- *eh++ = 65;
- *eh++ = 12;
- *eh++ = DW_CFA_advance_loc + 2;
- *eh++ = DW_CFA_restore_extended;
- *eh++ = 65;
- stub_entry->group->eh_size = eh - base;
- }
break;
case ppc_stub_plt_call:
abort ();
plt = htab->elf.splt;
- if (!htab->elf.dynamic_sections_created
- || stub_entry->h == NULL
- || stub_entry->h->elf.dynindx == -1)
+ if (use_local_plt (info, elf_hash_entry (stub_entry->h)))
{
if (stub_entry->symtype == STT_GNU_IFUNC)
plt = htab->elf.iplt;
? stub_entry->h->elf.root.root.string
: "<local sym>");
bfd_set_error (bfd_error_bad_value);
- htab->stub_error = TRUE;
- return FALSE;
+ htab->stub_error = true;
+ return false;
}
r = NULL;
&& PPC_HA (off + 16) == PPC_HA (off))
: 1)));
if (r == NULL)
- return FALSE;
+ return false;
r[0].r_offset = loc - stub_entry->group->stub_sec->contents;
if (bfd_big_endian (info->output_bfd))
r[0].r_offset += 2;
r[0].r_addend = targ;
}
- if (stub_entry->h != NULL
- && is_tls_get_addr (&stub_entry->h->elf, htab)
- && htab->params->tls_get_addr_opt)
- p = build_tls_get_addr_stub (htab, stub_entry, loc, off, r);
- else
- p = build_plt_stub (htab, stub_entry, loc, off, r);
+ p = loc;
+ obfd = htab->params->stub_bfd;
+ is_tga = (stub_entry->h != NULL
+ && is_tls_get_addr (&stub_entry->h->elf, htab)
+ && htab->params->tls_get_addr_opt);
+ if (is_tga)
+ {
+ p = build_tls_get_addr_head (htab, stub_entry, p);
+ if (r != NULL)
+ r[0].r_offset += p - loc;
+ }
+ p = build_plt_stub (htab, stub_entry, p, off, r);
+ if (is_tga)
+ p = build_tls_get_addr_tail (htab, stub_entry, p, loc);
break;
case ppc_stub_save_res:
- return TRUE;
+ return true;
default:
BFD_FAIL ();
- return FALSE;
+ return false;
}
stub_entry->group->stub_sec->size = stub_entry->stub_offset + (p - loc);
len2 = strlen (stub_entry->root.string);
name = bfd_malloc (len1 + len2 + 2);
if (name == NULL)
- return FALSE;
+ return false;
memcpy (name, stub_entry->root.string, 9);
memcpy (name + 9, stub_str[stub_entry->stub_type - 1], len1);
memcpy (name + len1 + 9, stub_entry->root.string + 8, len2 - 8 + 1);
- h = elf_link_hash_lookup (&htab->elf, name, TRUE, FALSE, FALSE);
+ h = elf_link_hash_lookup (&htab->elf, name, true, false, false);
if (h == NULL)
- return FALSE;
+ return false;
if (h->root.type == bfd_link_hash_new)
{
h->root.type = bfd_link_hash_defined;
}
}
- return TRUE;
+ return true;
}
/* As above, but don't actually build the stub. Just bump offset so
we know stub section sizes, and select plt_branch stubs where
long_branch stubs won't do. */
-static bfd_boolean
+static bool
ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
{
struct ppc_stub_hash_entry *stub_entry;
htab = ppc_hash_table (info);
if (htab == NULL)
- return FALSE;
+ return false;
/* Fail if the target section could not be assigned to an output
section. The user should fix his linker script. */
functions. Instead, emit copies of the functions. */
stub_entry->group->needs_save_res = 1;
stub_entry->stub_type = ppc_stub_save_res;
- return TRUE;
+ return true;
}
switch (stub_entry->stub_type)
r2off = get_r2off (info, stub_entry);
if (r2off == (bfd_vma) -1)
{
- htab->stub_error = TRUE;
- return FALSE;
+ htab->stub_error = true;
+ return false;
}
size = 8;
if (PPC_HA (r2off) != 0)
br_entry = ppc_branch_hash_lookup (&htab->branch_hash_table,
stub_entry->root.string + 9,
- TRUE, FALSE);
+ true, false);
if (br_entry == NULL)
{
_bfd_error_handler (_("can't build branch stub `%s'"),
stub_entry->root.string);
- htab->stub_error = TRUE;
- return FALSE;
+ htab->stub_error = true;
+ return false;
}
if (br_entry->iter != htab->stub_iteration)
case ppc_stub_plt_call_notoc:
case ppc_stub_plt_call_both:
- off = (stub_entry->stub_offset
- + stub_entry->group->stub_sec->output_offset
- + stub_entry->group->stub_sec->output_section->vma);
+ lr_used = 0;
+ if (stub_entry->h != NULL
+ && is_tls_get_addr (&stub_entry->h->elf, htab)
+ && htab->params->tls_get_addr_opt)
+ {
+ lr_used += 7 * 4;
+ if (!htab->params->no_tls_get_addr_regsave)
+ lr_used += 11 * 4;
+ else if (stub_entry->stub_type == ppc_stub_plt_call_both)
+ lr_used += 2 * 4;
+ }
if (stub_entry->stub_type == ppc_stub_plt_call_both)
- off += 4;
+ lr_used += 4;
targ = stub_entry->plt_ent->plt.offset & ~1;
if (targ >= (bfd_vma) -2)
abort ();
plt = htab->elf.splt;
- if (!htab->elf.dynamic_sections_created
- || stub_entry->h == NULL
- || stub_entry->h->elf.dynindx == -1)
+ if (use_local_plt (info, elf_hash_entry (stub_entry->h)))
{
if (stub_entry->symtype == STT_GNU_IFUNC)
plt = htab->elf.iplt;
plt = htab->pltlocal;
}
targ += plt->output_offset + plt->output_section->vma;
+ off = (stub_entry->stub_offset
+ + stub_entry->group->stub_sec->output_offset
+ + stub_entry->group->stub_sec->output_section->vma
+ + lr_used);
odd = off & 4;
off = targ - off;
if (htab->params->plt_stub_align != 0)
{
- unsigned pad = plt_stub_pad (htab, stub_entry, off);
+ unsigned pad = plt_stub_pad (htab, stub_entry, off, odd);
stub_entry->group->stub_sec->size += pad;
stub_entry->stub_offset = stub_entry->group->stub_sec->size;
off -= pad;
+ odd ^= pad & 4;
}
if (info->emitrelocations)
stub_entry->group->stub_sec->flags |= SEC_RELOC;
}
- size = plt_stub_size (htab, stub_entry, off);
+ size = plt_stub_size (htab, stub_entry, off, odd);
if (htab->params->power10_stubs == 0)
{
/* After the bcl, lr has been modified so we need to emit
.eh_frame info saying the return address is in r12. */
- lr_used = stub_entry->stub_offset + 8;
- if (stub_entry->stub_type == ppc_stub_plt_call_both)
- lr_used += 4;
+ lr_used += stub_entry->stub_offset + 8;
/* The eh_frame info will consist of a DW_CFA_advance_loc or
variant, DW_CFA_register, 65, 12, DW_CFA_advance_loc+2,
DW_CFA_restore_extended 65. */
stub_entry->group->eh_size += eh_advance_size (delta) + 6;
stub_entry->group->lr_restore = lr_used + 8;
}
+ if ((stub_entry->stub_type == ppc_stub_plt_call_notoc
+ || stub_entry->stub_type == ppc_stub_plt_call_both)
+ && stub_entry->h != NULL
+ && is_tls_get_addr (&stub_entry->h->elf, htab)
+ && htab->params->tls_get_addr_opt)
+ {
+ if (!htab->params->no_tls_get_addr_regsave)
+ {
+ unsigned int cfa_updt = stub_entry->stub_offset + 18 * 4;
+ delta = cfa_updt - stub_entry->group->lr_restore;
+ stub_entry->group->eh_size += eh_advance_size (delta);
+ stub_entry->group->eh_size += htab->opd_abi ? 36 : 35;
+ stub_entry->group->lr_restore
+ = stub_entry->stub_offset + size - 4;
+ }
+ else if (stub_entry->stub_type == ppc_stub_plt_call_both)
+ {
+ lr_used = stub_entry->stub_offset + size - 20;
+ delta = lr_used - stub_entry->group->lr_restore;
+ stub_entry->group->eh_size += eh_advance_size (delta) + 6;
+ stub_entry->group->lr_restore
+ = stub_entry->stub_offset + size - 4;
+ }
+ }
break;
case ppc_stub_plt_call:
if (targ >= (bfd_vma) -2)
abort ();
plt = htab->elf.splt;
- if (!htab->elf.dynamic_sections_created
- || stub_entry->h == NULL
- || stub_entry->h->elf.dynindx == -1)
+ if (use_local_plt (info, elf_hash_entry (stub_entry->h)))
{
if (stub_entry->symtype == STT_GNU_IFUNC)
plt = htab->elf.iplt;
if (htab->params->plt_stub_align != 0)
{
- unsigned pad = plt_stub_pad (htab, stub_entry, off);
+ unsigned pad = plt_stub_pad (htab, stub_entry, off, 0);
stub_entry->group->stub_sec->size += pad;
stub_entry->stub_offset = stub_entry->group->stub_sec->size;
stub_entry->group->stub_sec->flags |= SEC_RELOC;
}
- size = plt_stub_size (htab, stub_entry, off);
+ size = plt_stub_size (htab, stub_entry, off, 0);
if (stub_entry->h != NULL
&& is_tls_get_addr (&stub_entry->h->elf, htab)
&& htab->params->tls_get_addr_opt
&& stub_entry->stub_type == ppc_stub_plt_call_r2save)
{
- if (htab->params->no_tls_get_addr_regsave)
+ if (!htab->params->no_tls_get_addr_regsave)
+ {
+ /* Adjustments to r1 need to be described. */
+ unsigned int cfa_updt = stub_entry->stub_offset + 18 * 4;
+ delta = cfa_updt - stub_entry->group->lr_restore;
+ stub_entry->group->eh_size += eh_advance_size (delta);
+ stub_entry->group->eh_size += htab->opd_abi ? 36 : 35;
+ }
+ else
{
lr_used = stub_entry->stub_offset + size - 20;
/* The eh_frame info will consist of a DW_CFA_advance_loc
delta = lr_used - stub_entry->group->lr_restore;
stub_entry->group->eh_size += eh_advance_size (delta) + 6;
}
- else
- {
- /* Adjustments to r1 need to be described. */
- unsigned int cfa_updt = stub_entry->stub_offset + 18 * 4;
- delta = cfa_updt - stub_entry->group->lr_restore;
- stub_entry->group->eh_size += eh_advance_size (delta);
- stub_entry->group->eh_size += htab->opd_abi ? 36 : 35;
- }
- stub_entry->group->lr_restore = size - 4;
+ stub_entry->group->lr_restore = stub_entry->stub_offset + size - 4;
}
break;
default:
BFD_FAIL ();
- return FALSE;
+ return false;
}
stub_entry->group->stub_sec->size += size;
- return TRUE;
+ return true;
}
/* Set up various things so that we can make a list of input sections
and linker generated GOT section. Group input bfds such that the toc
within a group is less than 64k in size. */
-bfd_boolean
+bool
ppc64_elf_next_toc_section (struct bfd_link_info *info, asection *isec)
{
struct ppc_link_hash_table *htab = ppc_hash_table (info);
bfd_vma addr, off, limit;
if (htab == NULL)
- return FALSE;
+ return false;
if (!htab->second_toc_pass)
{
/* Keep track of the first .toc or .got section for this input bfd. */
- bfd_boolean new_bfd = htab->toc_bfd != isec->owner;
+ bool new_bfd = htab->toc_bfd != isec->owner;
if (new_bfd)
{
if (new_bfd
&& elf_gp (isec->owner) != 0
&& elf_gp (isec->owner) != off)
- return FALSE;
+ return false;
elf_gp (isec->owner) = off;
- return TRUE;
+ return true;
}
/* During the second pass toc_first_sec points to the start of
a toc group, and toc_curr is used to track the old elf_gp.
We use toc_bfd to ensure we only look at each bfd once. */
if (htab->toc_bfd == isec->owner)
- return TRUE;
+ return true;
htab->toc_bfd = isec->owner;
if (htab->toc_first_sec == NULL
off = addr - elf_gp (info->output_bfd) + TOC_BASE_OFF;
elf_gp (isec->owner) = off;
- return TRUE;
+ return true;
}
/* Called via elf_link_hash_traverse to merge GOT entries for global
symbol H. */
-static bfd_boolean
+static bool
merge_global_got (struct elf_link_hash_entry *h, void *inf ATTRIBUTE_UNUSED)
{
if (h->root.type == bfd_link_hash_indirect)
- return TRUE;
+ return true;
merge_got_entries (&h->got.glist);
- return TRUE;
+ return true;
}
/* Called via elf_link_hash_traverse to allocate GOT entries for global
symbol H. */
-static bfd_boolean
+static bool
reallocate_got (struct elf_link_hash_entry *h, void *inf)
{
struct got_entry *gent;
if (h->root.type == bfd_link_hash_indirect)
- return TRUE;
+ return true;
for (gent = h->got.glist; gent != NULL; gent = gent->next)
if (!gent->is_indirect)
allocate_got (h, (struct bfd_link_info *) inf, gent);
- return TRUE;
+ return true;
}
/* Called on the first multitoc pass after the last call to
ppc64_elf_next_toc_section. This function removes duplicate GOT
entries. */
-bfd_boolean
+bool
ppc64_elf_layout_multitoc (struct bfd_link_info *info)
{
struct ppc_link_hash_table *htab = ppc_hash_table (info);
struct bfd *ibfd, *ibfd2;
- bfd_boolean done_something;
+ bool done_something;
htab->multi_toc_needed = htab->toc_curr != elf_gp (info->output_bfd);
if (!htab->do_multi_toc)
- return FALSE;
+ return false;
/* Merge global sym got entries within a toc group. */
elf_link_hash_traverse (&htab->elf, merge_global_got, info);
&& ent2->got.offset != (bfd_vma) -1
&& elf_gp (ibfd2) == elf_gp (ibfd))
{
- ent2->is_indirect = TRUE;
+ ent2->is_indirect = true;
ent2->got.ent = ent;
}
}
on input sections. */
htab->toc_bfd = NULL;
htab->toc_first_sec = NULL;
- htab->second_toc_pass = TRUE;
+ htab->second_toc_pass = true;
return done_something;
}
}
dest = opd_entry_value (sym_sec, sym_value,
- &sym_sec, NULL, FALSE);
+ &sym_sec, NULL, false);
if (dest == (bfd_vma) -1)
continue;
}
Build lists of input sections to determine groupings between which
we may insert linker stubs. */
-bfd_boolean
+bool
ppc64_elf_next_input_section (struct bfd_link_info *info, asection *isec)
{
struct ppc_link_hash_table *htab = ppc_hash_table (info);
if (htab == NULL)
- return FALSE;
+ return false;
if ((isec->output_section->flags & SEC_CODE) != 0
&& isec->output_section->id < htab->sec_info_arr_size)
|| isec->call_check_done))
{
if (toc_adjusting_stub_needed (info, isec) < 0)
- return FALSE;
+ return false;
}
/* Make all sections use the TOC assigned for this object file.
This will be wrong for pasted sections; We fix that in
}
htab->sec_info[isec->id].toc_off = htab->toc_curr;
- return TRUE;
+ return true;
}
/* Check that all .init and .fini sections use the same toc, if they
have toc relocs. */
-static bfd_boolean
+static bool
check_pasted_section (struct bfd_link_info *info, const char *name)
{
asection *o = bfd_get_section_by_name (info->output_bfd, name);
if (toc_off == 0)
toc_off = htab->sec_info[i->id].toc_off;
else if (toc_off != htab->sec_info[i->id].toc_off)
- return FALSE;
+ return false;
}
if (toc_off == 0)
for (i = o->map_head.s; i != NULL; i = i->map_head.s)
htab->sec_info[i->id].toc_off = toc_off;
}
- return TRUE;
+ return true;
}
-bfd_boolean
+bool
ppc64_elf_check_init_fini (struct bfd_link_info *info)
{
return (check_pasted_section (info, ".init")
_init and _fini functions into multiple parts. Putting a stub in
the middle of a function is not a good idea. */
-static bfd_boolean
+static bool
group_sections (struct bfd_link_info *info,
bfd_size_type stub_group_size,
- bfd_boolean stubs_always_before_branch)
+ bool stubs_always_before_branch)
{
struct ppc_link_hash_table *htab;
asection *osec;
- bfd_boolean suppress_size_errors;
+ bool suppress_size_errors;
htab = ppc_hash_table (info);
if (htab == NULL)
- return FALSE;
+ return false;
- suppress_size_errors = FALSE;
+ suppress_size_errors = false;
if (stub_group_size == 1)
{
/* Default values. */
stub_group_size = 0x1e00000;
else
stub_group_size = 0x1c00000;
- suppress_size_errors = TRUE;
+ suppress_size_errors = true;
}
for (osec = info->output_bfd->sections; osec != NULL; osec = osec->next)
asection *curr;
asection *prev;
bfd_size_type total;
- bfd_boolean big_sec;
+ bool big_sec;
bfd_vma curr_toc;
struct map_stub *group;
bfd_size_type group_size;
than 2097152 bytes, or nearly 75000 plt call stubs. */
group = bfd_alloc (curr->owner, sizeof (*group));
if (group == NULL)
- return FALSE;
+ return false;
group->link_sec = curr;
group->stub_sec = NULL;
group->needs_save_res = 0;
tail = prev;
}
}
- return TRUE;
+ return true;
}
static const unsigned char glink_eh_frame_cie[] =
PC-relative calls to a target that is unreachable with a "bl"
instruction. */
-bfd_boolean
+bool
ppc64_elf_size_stubs (struct bfd_link_info *info)
{
bfd_size_type stub_group_size;
- bfd_boolean stubs_always_before_branch;
+ bool stubs_always_before_branch;
struct ppc_link_hash_table *htab = ppc_hash_table (info);
if (htab == NULL)
- return FALSE;
+ return false;
if (htab->params->power10_stubs == -1 && !htab->has_power10_relocs)
htab->params->power10_stubs = 0;
{
struct elf_link_hash_entry *h;
h = elf_link_hash_lookup (&htab->elf, thread_starter[i],
- FALSE, FALSE, TRUE);
+ false, false, true);
htab->params->plt_thread_safe = h != NULL && h->ref_regular;
if (htab->params->plt_thread_safe)
break;
stub_group_size = htab->params->group_size;
if (!group_sections (info, stub_group_size, stubs_always_before_branch))
- return FALSE;
+ return false;
htab->tga_group = NULL;
if (!htab->params->no_tls_get_addr_regsave
code_sec = sym_sec;
opd = get_opd_info (sym_sec);
if (opd != NULL)
- opd_entry_value (sym_sec, sym_value, &code_sec, NULL, FALSE);
+ opd_entry_value (sym_sec, sym_value, &code_sec, NULL, false);
htab->tga_group = htab->sec_info[code_sec->id].u.group;
stub_sec = (*htab->params->add_stub_section) (".tga_desc.stub",
htab->tga_group->link_sec);
if (stub_sec == NULL)
- return FALSE;
+ return false;
htab->tga_group->stub_sec = stub_sec;
htab->tga_desc_fd->elf.root.type = bfd_link_hash_defined;
htab->tga_desc_fd->elf.type = STT_FUNC;
htab->tga_desc_fd->elf.def_regular = 1;
htab->tga_desc_fd->elf.non_elf = 0;
- _bfd_elf_link_hash_hide_symbol (info, &htab->tga_desc_fd->elf, TRUE);
+ _bfd_elf_link_hash_hide_symbol (info, &htab->tga_desc_fd->elf, true);
}
#define STUB_SHRINK_ITER 20
bfd_vma sym_value, code_value;
bfd_vma destination;
unsigned long local_off;
- bfd_boolean ok_dest;
+ bool ok_dest;
struct ppc_link_hash_entry *hash;
struct ppc_link_hash_entry *fdh;
struct elf_link_hash_entry *h;
goto error_ret_free_internal;
hash = ppc_elf_hash_entry (h);
- ok_dest = FALSE;
+ ok_dest = false;
fdh = NULL;
sym_value = 0;
if (hash == NULL)
sym_value = sym->st_value;
if (sym_sec != NULL
&& sym_sec->output_section != NULL)
- ok_dest = TRUE;
+ ok_dest = true;
}
else if (hash->elf.root.type == bfd_link_hash_defined
|| hash->elf.root.type == bfd_link_hash_defweak)
{
sym_value = hash->elf.root.u.def.value;
if (sym_sec->output_section != NULL)
- ok_dest = TRUE;
+ ok_dest = true;
}
else if (hash->elf.root.type == bfd_link_hash_undefweak
|| hash->elf.root.type == bfd_link_hash_undefined)
sym_sec = fdh->elf.root.u.def.section;
sym_value = fdh->elf.root.u.def.value;
if (sym_sec->output_section != NULL)
- ok_dest = TRUE;
+ ok_dest = true;
}
else
fdh = NULL;
sym_value += adjust;
}
dest = opd_entry_value (sym_sec, sym_value,
- &code_sec, &code_value, FALSE);
+ &code_sec, &code_value, false);
if (dest != (bfd_vma) -1)
{
destination = dest;
fact a call needing a TOC adjustment. */
if ((code_sec != NULL
&& code_sec->output_section != NULL
- && (htab->sec_info[code_sec->id].toc_off
- != htab->sec_info[section->id].toc_off)
&& (code_sec->has_toc_reloc
- || code_sec->makes_toc_func_call))
+ || code_sec->makes_toc_func_call)
+ && (htab->sec_info[code_sec->id].toc_off
+ != htab->sec_info[section->id].toc_off))
|| (((hash ? hash->elf.other : sym->st_other)
& STO_PPC64_LOCAL_MASK)
== 1 << STO_PPC64_LOCAL_BIT))
goto error_ret_free_internal;
stub_entry = ppc_stub_hash_lookup (&htab->stub_hash_table,
- stub_name, FALSE, FALSE);
+ stub_name, false, false);
if (stub_entry != NULL)
{
enum ppc_stub_type old_type;
/* For --power10-stubs=auto, don't merge _notoc
and other varieties of stubs. (The _both
variety won't be created.) */
- bfd_boolean notoc = r_type == R_PPC64_REL24_NOTOC;
+ bool notoc = r_type == R_PPC64_REL24_NOTOC;
struct ppc_stub_hash_entry *alt_stub
= select_alt_stub (stub_entry, notoc);
if (symtab_hdr->contents
!= (unsigned char *) local_syms)
free (local_syms);
- return FALSE;
+ return false;
}
stub_entry->stub_type = stub_type;
indexed in .eh_frame_hdr. */
p = bfd_zalloc (htab->glink_eh_frame->owner, htab->glink_eh_frame->size);
if (p == NULL)
- return FALSE;
+ return false;
htab->glink_eh_frame->contents = p;
last_fde = p;
align = 4;
/* Augmentation. */
p += 1;
- *p++ = DW_CFA_advance_loc + 1;
+ *p++ = DW_CFA_advance_loc + (htab->has_plt_localentry0 ? 3 : 2);
*p++ = DW_CFA_register;
*p++ = 65;
*p++ = htab->opd_abi ? 12 : 0;
- *p++ = DW_CFA_advance_loc + (htab->opd_abi ? 5 : 7);
+ *p++ = DW_CFA_advance_loc + (htab->opd_abi ? 4 : 2);
*p++ = DW_CFA_restore_extended;
*p++ = 65;
p += ((24 + align - 1) & -align) - 24;
if (htab->glink_eh_frame != NULL)
maybe_strip_output (info, htab->glink_eh_frame);
- return TRUE;
+ return true;
}
/* Called after we have determined section placement. If sections
struct elf_link_hash_entry *h;
struct elf_link_hash_table *htab = elf_hash_table (info);
- if (is_elf_hash_table (htab)
+ if (is_elf_hash_table (&htab->root)
&& htab->hgot != NULL)
h = htab->hgot;
else
{
- h = elf_link_hash_lookup (htab, ".TOC.", FALSE, FALSE, TRUE);
- if (is_elf_hash_table (htab))
+ h = (struct elf_link_hash_entry *)
+ bfd_link_hash_lookup (&htab->root, ".TOC.", false, false, true);
+ if (is_elf_hash_table (&htab->root))
htab->hgot = h;
}
if (h != NULL
&& h->root.type == bfd_link_hash_defined
&& !h->root.linker_def
- && (!is_elf_hash_table (htab)
+ && (!is_elf_hash_table (&htab->root)
|| h->def_regular))
{
TOCstart = defined_sym_val (h) - TOC_BASE_OFF;
struct bfd_link_hash_entry *bh = NULL;
_bfd_generic_link_add_one_symbol (info, obfd, ".TOC.", BSF_GLOBAL,
s, TOC_BASE_OFF - adjust,
- NULL, FALSE, FALSE, &bh);
+ NULL, false, false, &bh);
}
}
return TOCstart;
/* Called via elf_link_hash_traverse from ppc64_elf_build_stubs to
write out any global entry stubs, and PLT relocations. */
-static bfd_boolean
+static bool
build_global_entry_stubs_and_plt (struct elf_link_hash_entry *h, void *inf)
{
struct bfd_link_info *info;
asection *s;
if (h->root.type == bfd_link_hash_indirect)
- return TRUE;
+ return true;
info = inf;
htab = ppc_hash_table (info);
if (htab == NULL)
- return FALSE;
+ return false;
for (ent = h->plt.plist; ent != NULL; ent = ent->next)
if (ent->plt.offset != (bfd_vma) -1)
asection *plt, *relplt;
bfd_byte *loc;
- if (!htab->elf.dynamic_sections_created
- || h->dynindx == -1)
+ if (use_local_plt (info, h))
{
if (!(h->def_regular
&& (h->root.type == bfd_link_hash_defined
{
plt = htab->elf.iplt;
relplt = htab->elf.irelplt;
- htab->elf.ifunc_resolvers = TRUE;
+ htab->elf.ifunc_resolvers = true;
if (htab->opd_abi)
rela.r_info = ELF64_R_INFO (0, R_PPC64_JMP_IREL);
else
+ ((ent->plt.offset - PLT_INITIAL_ENTRY_SIZE (htab))
/ PLT_ENTRY_SIZE (htab) * sizeof (Elf64_External_Rela)));
if (h->type == STT_GNU_IFUNC && is_static_defined (h))
- htab->elf.ifunc_resolvers = TRUE;
+ htab->elf.ifunc_resolvers = true;
bfd_elf64_swap_reloca_out (info->output_bfd, &rela, loc);
}
}
if (!h->pointer_equality_needed)
- return TRUE;
+ return true;
if (h->def_regular)
- return TRUE;
+ return true;
s = htab->global_entry;
if (s == NULL || s->size == 0)
- return TRUE;
+ return true;
for (ent = h->plt.plist; ent != NULL; ent = ent->next)
if (ent->plt.offset != (bfd_vma) -1
p = s->contents + h->root.u.def.value;
plt = htab->elf.splt;
- if (!htab->elf.dynamic_sections_created
- || h->dynindx == -1)
+ if (use_local_plt (info, h))
{
if (h->type == STT_GNU_IFUNC)
plt = htab->elf.iplt;
(_("%P: linkage table error against `%pT'\n"),
h->root.root.string);
bfd_set_error (bfd_error_bad_value);
- htab->stub_error = TRUE;
+ htab->stub_error = true;
}
htab->stub_count[ppc_stub_global_entry - 1] += 1;
char *name = bfd_malloc (sizeof "12345678.global_entry." + len);
if (name == NULL)
- return FALSE;
+ return false;
sprintf (name, "%08x.global_entry.%s", s->id, h->root.root.string);
- h = elf_link_hash_lookup (&htab->elf, name, TRUE, FALSE, FALSE);
+ h = elf_link_hash_lookup (&htab->elf, name, true, false, false);
if (h == NULL)
- return FALSE;
+ return false;
if (h->root.type == bfd_link_hash_new)
{
h->root.type = bfd_link_hash_defined;
bfd_put_32 (s->owner, BCTR, p);
break;
}
- return TRUE;
+ return true;
}
/* Write PLT relocs for locals. */
-static bfd_boolean
+static bool
write_plt_relocs_for_local_syms (struct bfd_link_info *info)
{
struct ppc_link_hash_table *htab = ppc_hash_table (info);
{
if (symtab_hdr->contents != (unsigned char *) local_syms)
free (local_syms);
- return FALSE;
+ return false;
}
val = sym->st_value + ent->addend;
- if (ELF_ST_TYPE (sym->st_info) != STT_GNU_IFUNC)
- val += PPC64_LOCAL_ENTRY_OFFSET (sym->st_other);
if (sym_sec != NULL && sym_sec->output_section != NULL)
val += sym_sec->output_offset + sym_sec->output_section->vma;
if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
{
- htab->elf.ifunc_resolvers = TRUE;
+ htab->elf.ifunc_resolvers = true;
plt = htab->elf.iplt;
relplt = htab->elf.irelplt;
}
symtab_hdr->contents = (unsigned char *) local_syms;
}
}
- return TRUE;
+ return true;
}
/* Emit the static wrapper function preserving registers around a
__tls_get_addr_opt call. */
-static bfd_boolean
+static bool
emit_tga_desc (struct ppc_link_hash_table *htab)
{
asection *stub_sec = htab->tga_group->stub_sec;
if (delta + (1 << 25) >= 1 << 26)
{
_bfd_error_handler (_("__tls_get_addr call offset overflow"));
- htab->stub_error = TRUE;
- return FALSE;
+ htab->stub_error = true;
+ return false;
}
p = stub_sec->contents;
The stubs are kept in a hash table attached to the main linker
hash table. This function is called via gldelf64ppc_finish. */
-bfd_boolean
+bool
ppc64_elf_build_stubs (struct bfd_link_info *info,
char **stats)
{
int stub_sec_count = 0;
if (htab == NULL)
- return FALSE;
+ return false;
/* Allocate memory to hold the linker stubs. */
for (group = htab->group; group != NULL; group = group->next)
stub_sec->contents = bfd_zalloc (htab->params->stub_bfd,
stub_sec->size);
if (stub_sec->contents == NULL)
- return FALSE;
+ return false;
stub_sec->size = 0;
}
}
{
struct elf_link_hash_entry *h;
h = elf_link_hash_lookup (&htab->elf, "__glink_PLTresolve",
- TRUE, FALSE, FALSE);
+ true, false, false);
if (h == NULL)
- return FALSE;
+ return false;
if (h->root.type == bfd_link_hash_new)
{
h->root.type = bfd_link_hash_defined;
{
Elf_Internal_Rela *r = get_relocs (htab->glink, 1);
if (r == NULL)
- return FALSE;
+ return false;
r->r_offset = (htab->glink->output_offset
+ htab->glink->output_section->vma);
r->r_info = ELF64_R_INFO (0, R_PPC64_REL64);
}
else
{
+ unsigned int insn;
+
+ /* 0:
+ . .quad plt0-1f # plt0 entry relative to 1:
+ #
+ # We get here with r12 initially @ a glink branch
+ # Load the address of _dl_runtime_resolve from plt0 and
+ # jump to it, with r0 set to the index of the PLT entry
+ # to be resolved and r11 the link map.
+ __glink_PLTresolve:
+ . std %r2,24(%r1) # optional
+ . mflr %r0
+ . bcl 20,31,1f
+ 1:
+ . mflr %r11
+ . mtlr %r0
+ . ld %r0,(0b-1b)(%r11)
+ . sub %r12,%r12,%r11
+ . add %r11,%r0,%r11
+ . addi %r0,%r12,1b-2f
+ . ld %r12,0(%r11)
+ . srdi %r0,%r0,2
+ . mtctr %r12
+ . ld %r11,8(%r11)
+ . bctr
+ 2:
+ . b __glink_PLTresolve
+ . ...
+ . b __glink_PLTresolve */
+
+ if (htab->has_plt_localentry0)
+ {
+ bfd_put_32 (htab->glink->owner, STD_R2_0R1 + 24, p);
+ p += 4;
+ }
bfd_put_32 (htab->glink->owner, MFLR_R0, p);
p += 4;
bfd_put_32 (htab->glink->owner, BCL_20_31, p);
p += 4;
bfd_put_32 (htab->glink->owner, MFLR_R11, p);
p += 4;
- bfd_put_32 (htab->glink->owner, STD_R2_0R1 + 24, p);
- p += 4;
- bfd_put_32 (htab->glink->owner, LD_R2_0R11 | (-16 & 0xfffc), p);
- p += 4;
bfd_put_32 (htab->glink->owner, MTLR_R0, p);
p += 4;
+ if (htab->has_plt_localentry0)
+ insn = LD_R0_0R11 | (-20 & 0xfffc);
+ else
+ insn = LD_R0_0R11 | (-16 & 0xfffc);
+ bfd_put_32 (htab->glink->owner, insn, p);
+ p += 4;
bfd_put_32 (htab->glink->owner, SUB_R12_R12_R11, p);
p += 4;
- bfd_put_32 (htab->glink->owner, ADD_R11_R2_R11, p);
+ bfd_put_32 (htab->glink->owner, ADD_R11_R0_R11, p);
p += 4;
- bfd_put_32 (htab->glink->owner, ADDI_R0_R12 | (-48 & 0xffff), p);
+ bfd_put_32 (htab->glink->owner, ADDI_R0_R12 | (-44 & 0xffff), p);
p += 4;
bfd_put_32 (htab->glink->owner, LD_R12_0R11, p);
p += 4;
htab->tga_group->lr_restore = 23 * 4;
htab->tga_group->stub_sec->size = 24 * 4;
if (!emit_tga_desc (htab))
- return FALSE;
+ return false;
if (htab->glink_eh_frame != NULL
&& htab->glink_eh_frame->size != 0)
{
elf_link_hash_traverse (&htab->elf, build_global_entry_stubs_and_plt, info);
if (!write_plt_relocs_for_local_syms (info))
- return FALSE;
+ return false;
if (htab->brlt != NULL && htab->brlt->size != 0)
{
htab->brlt->contents = bfd_zalloc (htab->brlt->owner,
htab->brlt->size);
if (htab->brlt->contents == NULL)
- return FALSE;
+ return false;
}
if (htab->relbrlt != NULL && htab->relbrlt->size != 0)
{
htab->relbrlt->contents = bfd_zalloc (htab->relbrlt->owner,
htab->relbrlt->size);
if (htab->relbrlt->contents == NULL)
- return FALSE;
+ return false;
}
/* Build the stubs as directed by the stub hash table. */
for (i = 0; i < ARRAY_SIZE (save_res_funcs); i++)
if (!sfpr_define (info, &save_res_funcs[i], stub_sec))
- return FALSE;
+ return false;
}
}
_bfd_error_handler
(_("%s offset too large for .eh_frame sdata4 encoding"),
group->stub_sec->name);
- return FALSE;
+ return false;
}
bfd_put_32 (htab->elf.dynobj, val, p + 8);
p += (group->eh_size + 17 + 3) & -4;
_bfd_error_handler
(_("%s offset too large for .eh_frame sdata4 encoding"),
htab->glink->name);
- return FALSE;
+ return false;
}
bfd_put_32 (htab->elf.dynobj, val, p + 8);
p += (24 + align - 1) & -align;
if (group != NULL)
{
- htab->stub_error = TRUE;
+ htab->stub_error = true;
_bfd_error_handler (_("stubs don't match calculated size"));
}
if (htab->stub_error)
- return FALSE;
+ return false;
if (stats != NULL)
{
free (groupmsg);
}
}
- return TRUE;
+ return true;
}
/* What to do when ld finds relocations against symbols defined in
/* These are the dynamic relocations supported by glibc. */
-static bfd_boolean
+static bool
ppc64_glibc_dynamic_reloc (enum elf_ppc64_reloc_type r_type)
{
switch (r_type)
case R_PPC64_ADDR14_BRNTAKEN:
case R_PPC64_REL32:
case R_PPC64_REL64:
- return TRUE;
+ return true;
default:
- return FALSE;
+ return false;
}
}
section, which means that the addend must be adjusted
accordingly. */
-static bfd_boolean
+static int
ppc64_elf_relocate_section (bfd *output_bfd,
struct bfd_link_info *info,
bfd *input_bfd,
bfd_byte *loc;
struct got_entry **local_got_ents;
bfd_vma TOCstart;
- bfd_boolean ret = TRUE;
- bfd_boolean is_opd;
+ bool ret = true;
+ bool is_opd;
/* Assume 'at' branch hints. */
- bfd_boolean is_isa_v2 = TRUE;
- bfd_boolean warned_dynamic = FALSE;
+ bool is_isa_v2 = true;
+ bool warned_dynamic = false;
bfd_vma d_offset = (bfd_big_endian (input_bfd) ? 2 : 0);
/* Initialize howto table if needed. */
htab = ppc_hash_table (info);
if (htab == NULL)
- return FALSE;
+ return false;
/* Don't relocate stub sections. */
if (input_section->owner == htab->params->stub_bfd)
- return TRUE;
+ return true;
if (!is_ppc64_elf (input_bfd))
{
bfd_set_error (bfd_error_wrong_format);
- return FALSE;
+ return false;
}
local_got_ents = elf_local_got_ents (input_bfd);
unsigned char tls_mask, tls_gd, tls_type;
unsigned char sym_type;
bfd_vma relocation;
- bfd_boolean unresolved_reloc, save_unresolved_reloc;
- bfd_boolean warned;
+ bool unresolved_reloc, save_unresolved_reloc;
+ bool warned;
enum { DEST_NORMAL, DEST_OPD, DEST_STUB } reloc_dest;
unsigned int insn;
unsigned int mask;
sec = NULL;
h_elf = NULL;
sym_name = NULL;
- unresolved_reloc = FALSE;
- warned = FALSE;
+ unresolved_reloc = false;
+ warned = false;
if (r_symndx < symtab_hdr->sh_info)
{
}
else
{
- bfd_boolean ignored;
+ bool ignored;
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
{
relocation = TOCstart + htab->sec_info[input_section->id].toc_off;
sec = bfd_abs_section_ptr;
- unresolved_reloc = FALSE;
+ unresolved_reloc = false;
}
/* TLS optimizations. Replace instruction sequences and relocs
if (!get_tls_mask (&toc_tls, &toc_symndx, &toc_addend,
&local_syms, rel, input_bfd))
- return FALSE;
+ return false;
if (toc_tls)
tls_mask = *toc_tls;
retval = get_tls_mask (&toc_tls, &toc_symndx, &toc_addend,
&local_syms, rel, input_bfd);
if (retval == 0)
- return FALSE;
+ return false;
if (toc_tls)
{
|| stub_entry->stub_type == ppc_stub_long_branch_r2off
|| stub_entry->stub_type == ppc_stub_long_branch_both))
{
- bfd_boolean can_plt_call = FALSE;
+ bool can_plt_call = false;
if (stub_entry->stub_type == ppc_stub_plt_call
&& !htab->opd_abi
&& htab->params->plt_localentry0 != 0
+ && h != NULL
&& is_elfv2_localentry0 (&h->elf))
{
/* The function doesn't use or change r2. */
- can_plt_call = TRUE;
+ can_plt_call = true;
}
else if (r_type == R_PPC64_REL24_NOTOC)
{
/* NOTOC calls don't need to restore r2. */
- can_plt_call = TRUE;
+ can_plt_call = true;
}
/* All of these stubs may modify r2, so there must be a
nop = bfd_get_32 (input_bfd,
contents + rel->r_offset + 4);
if (nop == LD_R2_0R1 + STK_TOC (htab))
- can_plt_call = TRUE;
+ can_plt_call = true;
else if (nop == NOP
|| nop == CROR_151515
|| nop == CROR_313131)
bfd_put_32 (input_bfd,
LD_R2_0R1 + STK_TOC (htab),
contents + rel->r_offset + 4);
- can_plt_call = TRUE;
+ can_plt_call = true;
}
}
}
if (*name == '.')
++name;
- if (strncmp (name, "__libc_start_main", 17) == 0
+ if (startswith (name, "__libc_start_main")
&& (name[17] == 0 || name[17] == '@'))
{
/* Allow crt1 branch to go via a toc adjusting
stub. Other calls that never return could do
the same, if we could detect such. */
- can_plt_call = TRUE;
+ can_plt_call = true;
}
}
- sec->output_section->vma
- sec->output_offset);
- opd_entry_value (sec, off, &code_sec, NULL, FALSE);
+ opd_entry_value (sec, off, &code_sec, NULL, false);
}
if (code_sec == input_section)
- can_plt_call = TRUE;
+ can_plt_call = true;
}
if (!can_plt_call)
input_bfd, input_section, rel->r_offset, sym_name);
bfd_set_error (bfd_error_bad_value);
- ret = FALSE;
+ ret = false;
}
if (can_plt_call
&& stub_entry->stub_type >= ppc_stub_plt_call
&& stub_entry->stub_type <= ppc_stub_plt_call_both)
- unresolved_reloc = FALSE;
+ unresolved_reloc = false;
}
if ((stub_entry == NULL
bfd_vma off = (relocation + addend
- sec->output_section->vma
- sec->output_offset);
- bfd_vma dest = opd_entry_value (sec, off, NULL, NULL, FALSE);
+ bfd_vma dest = opd_entry_value (sec, off, NULL, NULL, false);
if (dest != (bfd_vma) -1)
{
relocation = dest;
addend = 0;
reloc_dest = DEST_STUB;
- if (((stub_entry->stub_type == ppc_stub_plt_call
- && ALWAYS_EMIT_R2SAVE)
- || stub_entry->stub_type == ppc_stub_plt_call_r2save
- || stub_entry->stub_type == ppc_stub_plt_call_both)
- && !(h != NULL
- && is_tls_get_addr (&h->elf, htab)
- && htab->params->tls_get_addr_opt)
- && rel + 1 < relend
- && rel[1].r_offset == rel->r_offset + 4
- && ELF64_R_TYPE (rel[1].r_info) == R_PPC64_TOCSAVE)
- relocation += 4;
- else if ((stub_entry->stub_type == ppc_stub_long_branch_both
- || stub_entry->stub_type == ppc_stub_plt_branch_both
- || stub_entry->stub_type == ppc_stub_plt_call_both)
- && r_type == R_PPC64_REL24_NOTOC)
- relocation += 4;
+ if ((((stub_entry->stub_type == ppc_stub_plt_call
+ && ALWAYS_EMIT_R2SAVE)
+ || stub_entry->stub_type == ppc_stub_plt_call_r2save
+ || stub_entry->stub_type == ppc_stub_plt_call_both)
+ && rel + 1 < relend
+ && rel[1].r_offset == rel->r_offset + 4
+ && ELF64_R_TYPE (rel[1].r_info) == R_PPC64_TOCSAVE)
+ || ((stub_entry->stub_type == ppc_stub_long_branch_both
+ || stub_entry->stub_type == ppc_stub_plt_branch_both
+ || stub_entry->stub_type == ppc_stub_plt_call_both)
+ && r_type == R_PPC64_REL24_NOTOC))
+ {
+ /* Skip over the r2 store at the start of the stub. */
+ if (!(stub_entry->stub_type >= ppc_stub_plt_call
+ && htab->params->tls_get_addr_opt
+ && h != NULL
+ && is_tls_get_addr (&h->elf, htab)))
+ relocation += 4;
+ }
if (r_type == R_PPC64_REL24_NOTOC
&& (stub_entry->stub_type == ppc_stub_plt_call_notoc
break;
case R_PPC64_GOT16_DS:
- if ((h ? h->elf.type : ELF_ST_TYPE (sym->st_info)) == STT_GNU_IFUNC)
+ if ((h ? h->elf.type : ELF_ST_TYPE (sym->st_info)) == STT_GNU_IFUNC
+ || !htab->do_toc_opt)
break;
from = TOCstart + htab->sec_info[input_section->id].toc_off;
if (relocation + addend - from + 0x8000 < 0x10000
- && SYMBOL_REFERENCES_LOCAL (info, &h->elf))
+ && sec != NULL
+ && sec->output_section != NULL
+ && !discarded_section (sec)
+ && (h == NULL || SYMBOL_REFERENCES_LOCAL (info, &h->elf)))
{
insn = bfd_get_32 (input_bfd, contents + (rel->r_offset & ~3));
if ((insn & (0x3fu << 26 | 0x3)) == 58u << 26 /* ld */)
case R_PPC64_GOT16_LO_DS:
case R_PPC64_GOT16_HA:
- if ((h ? h->elf.type : ELF_ST_TYPE (sym->st_info)) == STT_GNU_IFUNC)
+ if ((h ? h->elf.type : ELF_ST_TYPE (sym->st_info)) == STT_GNU_IFUNC
+ || !htab->do_toc_opt)
break;
from = TOCstart + htab->sec_info[input_section->id].toc_off;
if (relocation + addend - from + 0x80008000ULL < 0x100000000ULL
- && SYMBOL_REFERENCES_LOCAL (info, &h->elf))
+ && sec != NULL
+ && sec->output_section != NULL
+ && !discarded_section (sec)
+ && (h == NULL || SYMBOL_REFERENCES_LOCAL (info, &h->elf)))
{
insn = bfd_get_32 (input_bfd, contents + (rel->r_offset & ~3));
- if ((insn & (0x3fu << 26 | 0x3)) == 58u << 26 /* ld */)
+ if (r_type == R_PPC64_GOT16_LO_DS
+ && (insn & (0x3fu << 26 | 0x3)) == 58u << 26 /* ld */)
{
insn += (14u << 26) - (58u << 26);
bfd_put_32 (input_bfd, insn, contents + (rel->r_offset & ~3));
r_type = R_PPC64_TOC16_LO;
rel->r_info = ELF64_R_INFO (r_symndx, r_type);
}
- else if ((insn & (0x3fu << 26)) == 15u << 26 /* addis */)
+ else if (r_type == R_PPC64_GOT16_HA
+ && (insn & (0x3fu << 26)) == 15u << 26 /* addis */)
{
r_type = R_PPC64_TOC16_HA;
rel->r_info = ELF64_R_INFO (r_symndx, r_type);
break;
case R_PPC64_GOT_PCREL34:
- if ((h ? h->elf.type : ELF_ST_TYPE (sym->st_info)) == STT_GNU_IFUNC)
+ if ((h ? h->elf.type : ELF_ST_TYPE (sym->st_info)) == STT_GNU_IFUNC
+ || !htab->do_toc_opt)
break;
from = (rel->r_offset
+ input_section->output_section->vma
+ input_section->output_offset);
- if (relocation - from + (1ULL << 33) < 1ULL << 34
- && SYMBOL_REFERENCES_LOCAL (info, &h->elf))
- {
- offset = rel->r_offset;
- pinsn = bfd_get_32 (input_bfd, contents + offset);
- pinsn <<= 32;
- pinsn |= bfd_get_32 (input_bfd, contents + offset + 4);
- if ((pinsn & ((-1ULL << 50) | (63ULL << 26)))
- == ((1ULL << 58) | (1ULL << 52) | (57ULL << 26) /* pld */))
- {
- /* Replace with paddi. */
- pinsn += (2ULL << 56) + (14ULL << 26) - (57ULL << 26);
- r_type = R_PPC64_PCREL34;
- rel->r_info = ELF64_R_INFO (r_symndx, r_type);
- bfd_put_32 (input_bfd, pinsn >> 32, contents + offset);
- bfd_put_32 (input_bfd, pinsn, contents + offset + 4);
- goto pcrelopt;
- }
- }
- break;
+ if (!(relocation - from + (1ULL << 33) < 1ULL << 34
+ && sec != NULL
+ && sec->output_section != NULL
+ && !discarded_section (sec)
+ && (h == NULL || SYMBOL_REFERENCES_LOCAL (info, &h->elf))))
+ break;
+
+ offset = rel->r_offset;
+ pinsn = bfd_get_32 (input_bfd, contents + offset);
+ pinsn <<= 32;
+ pinsn |= bfd_get_32 (input_bfd, contents + offset + 4);
+ if ((pinsn & ((-1ULL << 50) | (63ULL << 26)))
+ != ((1ULL << 58) | (1ULL << 52) | (57ULL << 26) /* pld */))
+ break;
+
+ /* Replace with paddi. */
+ pinsn += (2ULL << 56) + (14ULL << 26) - (57ULL << 26);
+ r_type = R_PPC64_PCREL34;
+ rel->r_info = ELF64_R_INFO (r_symndx, r_type);
+ bfd_put_32 (input_bfd, pinsn >> 32, contents + offset);
+ bfd_put_32 (input_bfd, pinsn, contents + offset + 4);
+ /* Fall through. */
case R_PPC64_PCREL34:
- if (SYMBOL_REFERENCES_LOCAL (info, &h->elf))
+ if (!htab->params->no_pcrel_opt
+ && rel + 1 < relend
+ && rel[1].r_offset == rel->r_offset
+ && rel[1].r_info == ELF64_R_INFO (0, R_PPC64_PCREL_OPT)
+ && (h == NULL || SYMBOL_REFERENCES_LOCAL (info, &h->elf)))
{
offset = rel->r_offset;
pinsn = bfd_get_32 (input_bfd, contents + offset);
== ((1ULL << 58) | (2ULL << 56) | (1ULL << 52)
| (14ULL << 26) /* paddi */))
{
- pcrelopt:
- if (rel + 1 < relend
- && rel[1].r_offset == offset
- && rel[1].r_info == ELF64_R_INFO (0, R_PPC64_PCREL_OPT))
+ bfd_vma off2 = rel[1].r_addend;
+ if (off2 == 0)
+ /* zero means next insn. */
+ off2 = 8;
+ off2 += offset;
+ if (off2 + 4 <= input_section->size)
{
- bfd_vma off2 = rel[1].r_addend;
- if (off2 == 0)
- /* zero means next insn. */
- off2 = 8;
- off2 += offset;
- if (off2 + 4 <= input_section->size)
+ uint64_t pinsn2;
+ bfd_signed_vma addend_off;
+ pinsn2 = bfd_get_32 (input_bfd, contents + off2);
+ pinsn2 <<= 32;
+ if ((pinsn2 & (63ULL << 58)) == 1ULL << 58)
+ {
+ if (off2 + 8 > input_section->size)
+ break;
+ pinsn2 |= bfd_get_32 (input_bfd,
+ contents + off2 + 4);
+ }
+ if (xlate_pcrel_opt (&pinsn, &pinsn2, &addend_off))
{
- uint64_t pinsn2;
- bfd_signed_vma addend_off;
- pinsn2 = bfd_get_32 (input_bfd, contents + off2);
- pinsn2 <<= 32;
+ addend += addend_off;
+ rel->r_addend = addend;
+ bfd_put_32 (input_bfd, pinsn >> 32,
+ contents + offset);
+ bfd_put_32 (input_bfd, pinsn,
+ contents + offset + 4);
+ bfd_put_32 (input_bfd, pinsn2 >> 32,
+ contents + off2);
if ((pinsn2 & (63ULL << 58)) == 1ULL << 58)
- {
- if (off2 + 8 > input_section->size)
- break;
- pinsn2 |= bfd_get_32 (input_bfd,
- contents + off2 + 4);
- }
- if (xlate_pcrel_opt (&pinsn, &pinsn2, &addend_off))
- {
- addend += addend_off;
- rel->r_addend = addend;
- bfd_put_32 (input_bfd, pinsn >> 32,
- contents + offset);
- bfd_put_32 (input_bfd, pinsn,
- contents + offset + 4);
- bfd_put_32 (input_bfd, pinsn2 >> 32,
- contents + off2);
- if ((pinsn2 & (63ULL << 58)) == 1ULL << 58)
- bfd_put_32 (input_bfd, pinsn2,
- contents + off2 + 4);
- }
+ bfd_put_32 (input_bfd, pinsn2,
+ contents + off2 + 4);
}
}
}
input_bfd, ppc64_elf_howto_table[r_type]->name);
bfd_set_error (bfd_error_bad_value);
- ret = FALSE;
+ ret = false;
goto copy_reloc;
case R_PPC64_NONE:
struct got_entry *ent;
if (tls_type == (TLS_TLS | TLS_LD)
- && SYMBOL_REFERENCES_LOCAL (info, &h->elf))
+ && (h == NULL || SYMBOL_REFERENCES_LOCAL (info, &h->elf)))
ent = ppc64_tlsld_got (input_bfd);
else
{
else
{
indx = h->elf.dynindx;
- unresolved_reloc = FALSE;
+ unresolved_reloc = false;
}
ent = h->elf.got.glist;
}
the case of TLSLD where we'll use one entry per
module. */
asection *relgot;
- bfd_boolean ifunc;
+ bool ifunc;
*offp = off | 1;
relgot = NULL;
{
relgot = htab->elf.irelplt;
if (indx == 0 || is_static_defined (&h->elf))
- htab->elf.ifunc_resolvers = TRUE;
+ htab->elf.ifunc_resolvers = true;
}
else if (indx != 0
|| (bfd_link_pic (info)
|| !UNDEFWEAK_NO_DYNAMIC_RELOC (info, &h->elf))
&& !(tls_type != 0
&& bfd_link_executable (info)
- && SYMBOL_REFERENCES_LOCAL (info, &h->elf))))
+ && (h == NULL
+ || SYMBOL_REFERENCES_LOCAL (info,
+ &h->elf)))))
relgot = ppc64_elf_tdata (ent->owner)->relgot;
if (relgot != NULL)
{
case R_PPC64_PLTCALL_NOTOC:
/* Relocation is to the entry for this symbol in the
procedure linkage table. */
- unresolved_reloc = TRUE;
+ unresolved_reloc = true;
{
struct plt_entry **plt_list = NULL;
if (h != NULL)
bfd_vma got;
plt = htab->elf.splt;
- if (!htab->elf.dynamic_sections_created
- || h == NULL
- || h->elf.dynindx == -1)
+ if (use_local_plt (info, elf_hash_entry (h)))
{
if (h != NULL
? h->elf.type == STT_GNU_IFUNC
relocation -= got;
}
addend = 0;
- unresolved_reloc = FALSE;
+ unresolved_reloc = false;
break;
}
}
else if (sec != NULL && sec->id < htab->sec_info_arr_size)
relocation += htab->sec_info[sec->id].toc_off;
else
- unresolved_reloc = TRUE;
+ unresolved_reloc = true;
goto dodyn;
/* TOC16 relocs. We want the offset relative to the TOC base,
? h->elf.dyn_relocs != NULL
: ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC))
{
- bfd_boolean skip, relocate;
+ bool skip, relocate;
asection *sreloc;
bfd_vma out_off;
long indx = 0;
are copied into the output file to be resolved at run
time. */
- skip = FALSE;
- relocate = FALSE;
+ skip = false;
+ relocate = false;
out_off = _bfd_elf_section_offset (output_bfd, info,
input_section, rel->r_offset);
if (out_off == (bfd_vma) -1)
- skip = TRUE;
+ skip = true;
else if (out_off == (bfd_vma) -2)
- skip = TRUE, relocate = TRUE;
+ skip = true, relocate = true;
out_off += (input_section->output_section->vma
+ input_section->output_offset);
outrel.r_offset = out_off;
if (skip)
memset (&outrel, 0, sizeof outrel);
- else if (!SYMBOL_REFERENCES_LOCAL (info, &h->elf)
+ else if (h != NULL
+ && !SYMBOL_REFERENCES_LOCAL (info, &h->elf)
&& !is_opd
&& r_type != R_PPC64_TOC)
{
bug in binutils handling of weak syms.)
In these cases we won't use the opd
entry in this lib. */
- unresolved_reloc = FALSE;
+ unresolved_reloc = false;
}
if (!is_opd
&& r_type == R_PPC64_ADDR64
Prelink also wants simple and consistent rules
for relocs. This make all RELATIVE relocs have
*r_offset equal to r_addend. */
- relocate = TRUE;
+ relocate = true;
}
}
else
input_bfd, input_section, rel->r_offset,
ppc64_elf_howto_table[r_type]->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);
- return FALSE;
+ return false;
}
else
{
{
sreloc = htab->elf.irelplt;
if (indx == 0 || is_static_defined (&h->elf))
- htab->elf.ifunc_resolvers = TRUE;
+ htab->elf.ifunc_resolvers = true;
}
if (sreloc == NULL)
abort ();
input_bfd,
ppc64_elf_howto_table[ELF64_R_TYPE (outrel.r_info)]->name,
sym_name);
- warned_dynamic = TRUE;
+ warned_dynamic = true;
}
/* If this reloc is against an external symbol, it will
that the section contents are a known value. */
if (!relocate)
{
- unresolved_reloc = FALSE;
+ unresolved_reloc = false;
/* The value chosen here is quite arbitrary as ld.so
ignores section contents except for the special
case of .opd where the contents might be accessed
ppc64_elf_howto_table[r_type]->name, sym_name);
bfd_set_error (bfd_error_invalid_operation);
- ret = FALSE;
+ ret = false;
goto copy_reloc;
}
case R_PPC64_PLTSEQ:
if (unresolved_reloc)
{
- unresolved_reloc = FALSE;
+ unresolved_reloc = false;
goto nop_it;
}
break;
bfd_byte *p = contents + rel->r_offset;
bfd_put_32 (input_bfd, PNOP >> 32, p);
bfd_put_32 (input_bfd, PNOP, p + 4);
- unresolved_reloc = FALSE;
+ unresolved_reloc = false;
goto copy_reloc;
}
break;
case R_PPC64_PLT16_HA:
if (unresolved_reloc)
{
- unresolved_reloc = FALSE;
+ unresolved_reloc = false;
goto nop_it;
}
/* Fall through. */
case R_PPC64_PLT16_LO_DS:
if (unresolved_reloc)
{
- unresolved_reloc = FALSE;
+ unresolved_reloc = false;
goto nop_it;
}
/* Fall through. */
if (htab->do_tls_opt && relocation + addend + 0x8000 < 0x10000)
{
bfd_byte *p = contents + (rel->r_offset & ~3);
- insn = bfd_get_32 (input_bfd, p);
- if ((insn & ((0x3fu << 26) | 0x1f << 16))
- != ((15u << 26) | (13 << 16)) /* addis rt,13,imm */)
- /* xgettext:c-format */
- info->callbacks->minfo
- (_("%H: warning: %s unexpected insn %#x.\n"),
- input_bfd, input_section, rel->r_offset,
- ppc64_elf_howto_table[r_type]->name, insn);
- else
- {
- bfd_put_32 (input_bfd, NOP, p);
- goto copy_reloc;
- }
+ bfd_put_32 (input_bfd, NOP, p);
+ goto copy_reloc;
}
break;
ppc64_elf_howto_table[r_type]->name,
mask + 1);
bfd_set_error (bfd_error_bad_value);
- ret = FALSE;
+ ret = false;
goto copy_reloc;
}
break;
input_bfd, input_section, rel->r_offset,
howto->name,
h->elf.root.root.string);
- ret = FALSE;
+ ret = false;
}
/* 16-bit fields in insns mostly have signed values, but a
&& (h->elf.root.type == bfd_link_hash_undefweak
|| h->elf.root.type == bfd_link_hash_undefined)
&& is_branch_reloc (r_type))))
- info->callbacks->reloc_overflow (info, &h->elf.root,
- sym_name, reloc_name,
- orig_rel.r_addend,
- input_bfd, input_section,
- rel->r_offset);
+ info->callbacks->reloc_overflow
+ (info, (struct bfd_link_hash_entry *) h, sym_name,
+ reloc_name, orig_rel.r_addend, input_bfd, input_section,
+ rel->r_offset);
}
else
{
(_("%H: %s against `%pT': error %d\n"),
input_bfd, input_section, rel->r_offset,
reloc_name, sym_name, (int) r);
- ret = FALSE;
+ ret = false;
}
free (more_info);
}
BFD_ASSERT (ppc64_elf_tdata (input_bfd)->opd.relocs == NULL);
ppc64_elf_tdata (input_bfd)->opd.relocs = rel;
if (rel == NULL)
- return FALSE;
+ return false;
memcpy (rel, relocs, amt);
}
return ret;
/* Finish up dynamic symbol handling. We set the contents of various
dynamic sections here. */
-static bfd_boolean
+static bool
ppc64_elf_finish_dynamic_symbol (bfd *output_bfd,
struct bfd_link_info *info,
struct elf_link_hash_entry *h,
htab = ppc_hash_table (info);
if (htab == NULL)
- return FALSE;
+ return false;
if (!htab->opd_abi && !h->def_regular)
for (ent = h->plt.plist; ent != NULL; ent = ent->next)
bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
}
- return TRUE;
+ return true;
}
/* Used to decide how to sort relocs in an optimal manner for the
/* Finish up the dynamic sections. */
-static bfd_boolean
+static bool
ppc64_elf_finish_dynamic_sections (bfd *output_bfd,
struct bfd_link_info *info)
{
htab = ppc_hash_table (info);
if (htab == NULL)
- return FALSE;
+ return false;
dynobj = htab->elf.dynobj;
sdyn = bfd_get_linker_section (dynobj, ".dynamic");
elf_section_data (htab->brlt)->rela.hdr,
elf_section_data (htab->brlt)->relocs,
NULL))
- return FALSE;
+ return false;
if (htab->glink != NULL
&& htab->glink->reloc_count != 0
elf_section_data (htab->glink)->rela.hdr,
elf_section_data (htab->glink)->relocs,
NULL))
- return FALSE;
+ return false;
if (htab->glink_eh_frame != NULL
&& !_bfd_elf_write_section_eh_frame (output_bfd, info,
htab->glink_eh_frame,
htab->glink_eh_frame->contents))
- return FALSE;
+ return false;
/* We need to handle writing out multiple GOT sections ourselves,
since we didn't add them to DYNOBJ. We know dynobj is the first
&& !bfd_set_section_contents (output_bfd, s->output_section,
s->contents, s->output_offset,
s->size))
- return FALSE;
+ return false;
s = ppc64_elf_tdata (dynobj)->relgot;
if (s != NULL
&& s->size != 0
&& !bfd_set_section_contents (output_bfd, s->output_section,
s->contents, s->output_offset,
s->size))
- return FALSE;
+ return false;
}
- return TRUE;
+ return true;
}
#include "elf64-target.h"
/* FreeBSD support */
#undef TARGET_LITTLE_SYM
+#define TARGET_LITTLE_SYM powerpc_elf64_fbsd_le_vec
#undef TARGET_LITTLE_NAME
+#define TARGET_LITTLE_NAME "elf64-powerpcle-freebsd"
#undef TARGET_BIG_SYM
#define TARGET_BIG_SYM powerpc_elf64_fbsd_vec