| /* PowerPC64-specific support for 64-bit ELF. |
| Copyright (C) 1999-2016 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. |
| |
| This file is part of BFD, the Binary File Descriptor library. |
| |
| This program is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 3 of the License, or |
| (at your option) any later version. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License along |
| with this program; if not, write to the Free Software Foundation, Inc., |
| 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ |
| |
| |
| /* The 64-bit PowerPC ELF ABI may be found at |
| http://www.linuxbase.org/spec/ELF/ppc64/PPC-elf64abi.txt, and |
| http://www.linuxbase.org/spec/ELF/ppc64/spec/book1.html */ |
| |
| #include "sysdep.h" |
| #include <stdarg.h> |
| #include "bfd.h" |
| #include "bfdlink.h" |
| #include "libbfd.h" |
| #include "elf-bfd.h" |
| #include "elf/ppc64.h" |
| #include "elf64-ppc.h" |
| #include "dwarf2.h" |
| |
| static bfd_reloc_status_type ppc64_elf_ha_reloc |
| (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); |
| static bfd_reloc_status_type ppc64_elf_branch_reloc |
| (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); |
| static bfd_reloc_status_type ppc64_elf_brtaken_reloc |
| (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); |
| static bfd_reloc_status_type ppc64_elf_sectoff_reloc |
| (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); |
| static bfd_reloc_status_type ppc64_elf_sectoff_ha_reloc |
| (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); |
| static bfd_reloc_status_type ppc64_elf_toc_reloc |
| (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); |
| static bfd_reloc_status_type ppc64_elf_toc_ha_reloc |
| (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); |
| static bfd_reloc_status_type ppc64_elf_toc64_reloc |
| (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); |
| 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); |
| |
| #define TARGET_LITTLE_SYM powerpc_elf64_le_vec |
| #define TARGET_LITTLE_NAME "elf64-powerpcle" |
| #define TARGET_BIG_SYM powerpc_elf64_vec |
| #define TARGET_BIG_NAME "elf64-powerpc" |
| #define ELF_ARCH bfd_arch_powerpc |
| #define ELF_TARGET_ID PPC64_ELF_DATA |
| #define ELF_MACHINE_CODE EM_PPC64 |
| #define ELF_MAXPAGESIZE 0x10000 |
| #define ELF_COMMONPAGESIZE 0x10000 |
| #define elf_info_to_howto ppc64_elf_info_to_howto |
| |
| #define elf_backend_want_got_sym 0 |
| #define elf_backend_want_plt_sym 0 |
| #define elf_backend_plt_alignment 3 |
| #define elf_backend_plt_not_loaded 1 |
| #define elf_backend_got_header_size 8 |
| #define elf_backend_can_gc_sections 1 |
| #define elf_backend_can_refcount 1 |
| #define elf_backend_rela_normal 1 |
| #define elf_backend_default_execstack 0 |
| |
| #define bfd_elf64_mkobject ppc64_elf_mkobject |
| #define bfd_elf64_bfd_reloc_type_lookup ppc64_elf_reloc_type_lookup |
| #define bfd_elf64_bfd_reloc_name_lookup ppc64_elf_reloc_name_lookup |
| #define bfd_elf64_bfd_merge_private_bfd_data ppc64_elf_merge_private_bfd_data |
| #define bfd_elf64_bfd_print_private_bfd_data ppc64_elf_print_private_bfd_data |
| #define bfd_elf64_new_section_hook ppc64_elf_new_section_hook |
| #define bfd_elf64_bfd_link_hash_table_create ppc64_elf_link_hash_table_create |
| #define bfd_elf64_get_synthetic_symtab ppc64_elf_get_synthetic_symtab |
| #define bfd_elf64_bfd_link_just_syms ppc64_elf_link_just_syms |
| |
| #define elf_backend_object_p ppc64_elf_object_p |
| #define elf_backend_grok_prstatus ppc64_elf_grok_prstatus |
| #define elf_backend_grok_psinfo ppc64_elf_grok_psinfo |
| #define elf_backend_write_core_note ppc64_elf_write_core_note |
| #define elf_backend_create_dynamic_sections ppc64_elf_create_dynamic_sections |
| #define elf_backend_copy_indirect_symbol ppc64_elf_copy_indirect_symbol |
| #define elf_backend_add_symbol_hook ppc64_elf_add_symbol_hook |
| #define elf_backend_check_directives ppc64_elf_before_check_relocs |
| #define elf_backend_notice_as_needed ppc64_elf_notice_as_needed |
| #define elf_backend_archive_symbol_lookup ppc64_elf_archive_symbol_lookup |
| #define elf_backend_check_relocs ppc64_elf_check_relocs |
| #define elf_backend_gc_keep ppc64_elf_gc_keep |
| #define elf_backend_gc_mark_dynamic_ref ppc64_elf_gc_mark_dynamic_ref |
| #define elf_backend_gc_mark_hook ppc64_elf_gc_mark_hook |
| #define elf_backend_gc_sweep_hook ppc64_elf_gc_sweep_hook |
| #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_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 elf_backend_action_discarded ppc64_elf_action_discarded |
| #define elf_backend_relocate_section ppc64_elf_relocate_section |
| #define elf_backend_finish_dynamic_symbol ppc64_elf_finish_dynamic_symbol |
| #define elf_backend_reloc_type_class ppc64_elf_reloc_type_class |
| #define elf_backend_finish_dynamic_sections ppc64_elf_finish_dynamic_sections |
| #define elf_backend_link_output_symbol_hook ppc64_elf_output_symbol_hook |
| #define elf_backend_special_sections ppc64_elf_special_sections |
| #define elf_backend_merge_symbol_attribute ppc64_elf_merge_symbol_attribute |
| |
| /* The name of the dynamic interpreter. This is put in the .interp |
| section. */ |
| #define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1" |
| |
| /* The size in bytes of an entry in the procedure linkage table. */ |
| #define PLT_ENTRY_SIZE(htab) (htab->opd_abi ? 24 : 8) |
| |
| /* The initial size of the plt reserved for the dynamic linker. */ |
| #define PLT_INITIAL_ENTRY_SIZE(htab) (htab->opd_abi ? 24 : 16) |
| |
| /* Offsets to some stack save slots. */ |
| #define STK_LR 16 |
| #define STK_TOC(htab) (htab->opd_abi ? 40 : 24) |
| /* This one is dodgy. ELFv2 does not have a linker word, so use the |
| CR save slot. Used only by optimised __tls_get_addr call stub, |
| relying on __tls_get_addr_opt not saving CR.. */ |
| #define STK_LINKER(htab) (htab->opd_abi ? 32 : 8) |
| |
| /* TOC base pointers offset from start of TOC. */ |
| #define TOC_BASE_OFF 0x8000 |
| /* TOC base alignment. */ |
| #define TOC_BASE_ALIGN 256 |
| |
| /* Offset of tp and dtp pointers from start of TLS block. */ |
| #define TP_OFFSET 0x7000 |
| #define DTP_OFFSET 0x8000 |
| |
| /* .plt call stub instructions. The normal stub is like this, but |
| sometimes the .plt entry crosses a 64k boundary and we need to |
| insert an addi to adjust r11. */ |
| #define STD_R2_0R1 0xf8410000 /* std %r2,0+40(%r1) */ |
| #define ADDIS_R11_R2 0x3d620000 /* addis %r11,%r2,xxx@ha */ |
| #define LD_R12_0R11 0xe98b0000 /* ld %r12,xxx+0@l(%r11) */ |
| #define MTCTR_R12 0x7d8903a6 /* mtctr %r12 */ |
| #define LD_R2_0R11 0xe84b0000 /* ld %r2,xxx+8@l(%r11) */ |
| #define LD_R11_0R11 0xe96b0000 /* ld %r11,xxx+16@l(%r11) */ |
| #define BCTR 0x4e800420 /* bctr */ |
| |
| #define ADDI_R11_R11 0x396b0000 /* addi %r11,%r11,off@l */ |
| #define ADDIS_R2_R2 0x3c420000 /* addis %r2,%r2,off@ha */ |
| #define ADDI_R2_R2 0x38420000 /* addi %r2,%r2,off@l */ |
| |
| #define XOR_R2_R12_R12 0x7d826278 /* xor %r2,%r12,%r12 */ |
| #define ADD_R11_R11_R2 0x7d6b1214 /* add %r11,%r11,%r2 */ |
| #define XOR_R11_R12_R12 0x7d8b6278 /* xor %r11,%r12,%r12 */ |
| #define ADD_R2_R2_R11 0x7c425a14 /* add %r2,%r2,%r11 */ |
| #define CMPLDI_R2_0 0x28220000 /* cmpldi %r2,0 */ |
| #define BNECTR 0x4ca20420 /* bnectr+ */ |
| #define BNECTR_P4 0x4ce20420 /* bnectr+ */ |
| |
| #define LD_R12_0R2 0xe9820000 /* ld %r12,xxx+0(%r2) */ |
| #define LD_R11_0R2 0xe9620000 /* ld %r11,xxx+0(%r2) */ |
| #define LD_R2_0R2 0xe8420000 /* ld %r2,xxx+0(%r2) */ |
| |
| #define LD_R2_0R1 0xe8410000 /* ld %r2,0(%r1) */ |
| #define LD_R2_0R12 0xe84c0000 /* ld %r2,0(%r12) */ |
| #define ADD_R2_R2_R12 0x7c426214 /* add %r2,%r2,%r12 */ |
| |
| #define LIS_R2 0x3c400000 /* lis %r2,xxx@ha */ |
| #define ADDIS_R2_R12 0x3c4c0000 /* addis %r2,%r12,xxx@ha */ |
| #define ADDIS_R12_R2 0x3d820000 /* addis %r12,%r2,xxx@ha */ |
| #define ADDIS_R12_R12 0x3d8c0000 /* addis %r12,%r12,xxx@ha */ |
| #define LD_R12_0R12 0xe98c0000 /* ld %r12,xxx@l(%r12) */ |
| |
| /* glink call stub instructions. We enter with the index in R0. */ |
| #define GLINK_CALL_STUB_SIZE (16*4) |
| /* 0: */ |
| /* .quad plt0-1f */ |
| /* __glink: */ |
| #define MFLR_R12 0x7d8802a6 /* mflr %12 */ |
| #define BCL_20_31 0x429f0005 /* bcl 20,31,1f */ |
| /* 1: */ |
| #define MFLR_R11 0x7d6802a6 /* mflr %11 */ |
| /* ld %2,(0b-1b)(%11) */ |
| #define MTLR_R12 0x7d8803a6 /* mtlr %12 */ |
| #define ADD_R11_R2_R11 0x7d625a14 /* add %11,%2,%11 */ |
| /* ld %12,0(%11) */ |
| /* ld %2,8(%11) */ |
| /* 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 */ |
| |
| /* Pad with this. */ |
| #define NOP 0x60000000 |
| |
| /* Some other nops. */ |
| #define CROR_151515 0x4def7b82 |
| #define CROR_313131 0x4ffffb82 |
| |
| /* .glink entries for the first 32k functions are two instructions. */ |
| #define LI_R0_0 0x38000000 /* li %r0,0 */ |
| #define B_DOT 0x48000000 /* b . */ |
| |
| /* After that, we need two instructions to load the index, followed by |
| a branch. */ |
| #define LIS_R0_0 0x3c000000 /* lis %r0,0 */ |
| #define ORI_R0_R0_0 0x60000000 /* ori %r0,%r0,0 */ |
| |
| /* Instructions used by the save and restore reg functions. */ |
| #define STD_R0_0R1 0xf8010000 /* std %r0,0(%r1) */ |
| #define STD_R0_0R12 0xf80c0000 /* std %r0,0(%r12) */ |
| #define LD_R0_0R1 0xe8010000 /* ld %r0,0(%r1) */ |
| #define LD_R0_0R12 0xe80c0000 /* ld %r0,0(%r12) */ |
| #define STFD_FR0_0R1 0xd8010000 /* stfd %fr0,0(%r1) */ |
| #define LFD_FR0_0R1 0xc8010000 /* lfd %fr0,0(%r1) */ |
| #define LI_R12_0 0x39800000 /* li %r12,0 */ |
| #define STVX_VR0_R12_R0 0x7c0c01ce /* stvx %v0,%r12,%r0 */ |
| #define LVX_VR0_R12_R0 0x7c0c00ce /* lvx %v0,%r12,%r0 */ |
| #define MTLR_R0 0x7c0803a6 /* mtlr %r0 */ |
| #define BLR 0x4e800020 /* blr */ |
| |
| /* Since .opd is an array of descriptors and each entry will end up |
| with identical R_PPC64_RELATIVE relocs, there is really no need to |
| propagate .opd relocs; The dynamic linker should be taught to |
| relocate .opd without reloc entries. */ |
| #ifndef NO_OPD_RELOCS |
| #define NO_OPD_RELOCS 0 |
| #endif |
| |
| #ifndef ARRAY_SIZE |
| #define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0])) |
| #endif |
| |
| static inline int |
| abiversion (bfd *abfd) |
| { |
| return elf_elfheader (abfd)->e_flags & EF_PPC64_ABI; |
| } |
| |
| static inline void |
| set_abiversion (bfd *abfd, int ver) |
| { |
| elf_elfheader (abfd)->e_flags &= ~EF_PPC64_ABI; |
| elf_elfheader (abfd)->e_flags |= ver & EF_PPC64_ABI; |
| } |
| |
| #define ONES(n) (((bfd_vma) 1 << ((n) - 1) << 1) - 1) |
| |
| /* Relocation HOWTO's. */ |
| static reloc_howto_type *ppc64_elf_howto_table[(int) R_PPC64_max]; |
| |
| static reloc_howto_type ppc64_elf_howto_raw[] = { |
| /* This reloc does nothing. */ |
| HOWTO (R_PPC64_NONE, /* type */ |
| 0, /* rightshift */ |
| 3, /* size (0 = byte, 1 = short, 2 = long) */ |
| 0, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| bfd_elf_generic_reloc, /* special_function */ |
| "R_PPC64_NONE", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* A standard 32 bit relocation. */ |
| HOWTO (R_PPC64_ADDR32, /* type */ |
| 0, /* rightshift */ |
| 2, /* size (0 = byte, 1 = short, 2 = long) */ |
| 32, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_bitfield, /* complain_on_overflow */ |
| bfd_elf_generic_reloc, /* special_function */ |
| "R_PPC64_ADDR32", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffffffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* An absolute 26 bit branch; the lower two bits must be zero. |
| FIXME: we don't check that, we just clear them. */ |
| HOWTO (R_PPC64_ADDR24, /* type */ |
| 0, /* rightshift */ |
| 2, /* size (0 = byte, 1 = short, 2 = long) */ |
| 26, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_bitfield, /* complain_on_overflow */ |
| bfd_elf_generic_reloc, /* special_function */ |
| "R_PPC64_ADDR24", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0x03fffffc, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* A standard 16 bit relocation. */ |
| HOWTO (R_PPC64_ADDR16, /* type */ |
| 0, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_bitfield, /* complain_on_overflow */ |
| bfd_elf_generic_reloc, /* special_function */ |
| "R_PPC64_ADDR16", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* A 16 bit relocation without overflow. */ |
| HOWTO (R_PPC64_ADDR16_LO, /* type */ |
| 0, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont,/* complain_on_overflow */ |
| bfd_elf_generic_reloc, /* special_function */ |
| "R_PPC64_ADDR16_LO", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Bits 16-31 of an address. */ |
| HOWTO (R_PPC64_ADDR16_HI, /* type */ |
| 16, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed, /* complain_on_overflow */ |
| bfd_elf_generic_reloc, /* special_function */ |
| "R_PPC64_ADDR16_HI", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Bits 16-31 of an address, plus 1 if the contents of the low 16 |
| bits, treated as a signed number, is negative. */ |
| HOWTO (R_PPC64_ADDR16_HA, /* type */ |
| 16, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed, /* complain_on_overflow */ |
| ppc64_elf_ha_reloc, /* special_function */ |
| "R_PPC64_ADDR16_HA", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* An absolute 16 bit branch; the lower two bits must be zero. |
| FIXME: we don't check that, we just clear them. */ |
| HOWTO (R_PPC64_ADDR14, /* type */ |
| 0, /* rightshift */ |
| 2, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed, /* complain_on_overflow */ |
| ppc64_elf_branch_reloc, /* special_function */ |
| "R_PPC64_ADDR14", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0x0000fffc, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* An absolute 16 bit branch, for which bit 10 should be set to |
| indicate that the branch is expected to be taken. The lower two |
| bits must be zero. */ |
| HOWTO (R_PPC64_ADDR14_BRTAKEN, /* type */ |
| 0, /* rightshift */ |
| 2, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed, /* complain_on_overflow */ |
| ppc64_elf_brtaken_reloc, /* special_function */ |
| "R_PPC64_ADDR14_BRTAKEN",/* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0x0000fffc, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* An absolute 16 bit branch, for which bit 10 should be set to |
| indicate that the branch is not expected to be taken. The lower |
| two bits must be zero. */ |
| HOWTO (R_PPC64_ADDR14_BRNTAKEN, /* type */ |
| 0, /* rightshift */ |
| 2, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed, /* complain_on_overflow */ |
| ppc64_elf_brtaken_reloc, /* special_function */ |
| "R_PPC64_ADDR14_BRNTAKEN",/* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0x0000fffc, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* A relative 26 bit branch; the lower two bits must be zero. */ |
| HOWTO (R_PPC64_REL24, /* type */ |
| 0, /* rightshift */ |
| 2, /* size (0 = byte, 1 = short, 2 = long) */ |
| 26, /* bitsize */ |
| TRUE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed, /* complain_on_overflow */ |
| ppc64_elf_branch_reloc, /* special_function */ |
| "R_PPC64_REL24", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0x03fffffc, /* dst_mask */ |
| TRUE), /* pcrel_offset */ |
| |
| /* A relative 16 bit branch; the lower two bits must be zero. */ |
| HOWTO (R_PPC64_REL14, /* type */ |
| 0, /* rightshift */ |
| 2, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| TRUE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed, /* complain_on_overflow */ |
| ppc64_elf_branch_reloc, /* special_function */ |
| "R_PPC64_REL14", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0x0000fffc, /* dst_mask */ |
| TRUE), /* pcrel_offset */ |
| |
| /* A relative 16 bit branch. Bit 10 should be set to indicate that |
| the branch is expected to be taken. The lower two bits must be |
| zero. */ |
| HOWTO (R_PPC64_REL14_BRTAKEN, /* type */ |
| 0, /* rightshift */ |
| 2, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| TRUE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed, /* complain_on_overflow */ |
| ppc64_elf_brtaken_reloc, /* special_function */ |
| "R_PPC64_REL14_BRTAKEN", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0x0000fffc, /* dst_mask */ |
| TRUE), /* pcrel_offset */ |
| |
| /* A relative 16 bit branch. Bit 10 should be set to indicate that |
| the branch is not expected to be taken. The lower two bits must |
| be zero. */ |
| HOWTO (R_PPC64_REL14_BRNTAKEN, /* type */ |
| 0, /* rightshift */ |
| 2, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| TRUE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed, /* complain_on_overflow */ |
| ppc64_elf_brtaken_reloc, /* special_function */ |
| "R_PPC64_REL14_BRNTAKEN",/* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0x0000fffc, /* dst_mask */ |
| TRUE), /* pcrel_offset */ |
| |
| /* Like R_PPC64_ADDR16, but referring to the GOT table entry for the |
| symbol. */ |
| HOWTO (R_PPC64_GOT16, /* type */ |
| 0, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_GOT16", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like R_PPC64_ADDR16_LO, but referring to the GOT table entry for |
| the symbol. */ |
| HOWTO (R_PPC64_GOT16_LO, /* type */ |
| 0, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_GOT16_LO", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like R_PPC64_ADDR16_HI, but referring to the GOT table entry for |
| the symbol. */ |
| HOWTO (R_PPC64_GOT16_HI, /* type */ |
| 16, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed,/* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_GOT16_HI", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like R_PPC64_ADDR16_HA, but referring to the GOT table entry for |
| the symbol. */ |
| HOWTO (R_PPC64_GOT16_HA, /* type */ |
| 16, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed,/* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_GOT16_HA", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* This is used only by the dynamic linker. The symbol should exist |
| both in the object being run and in some shared library. The |
| dynamic linker copies the data addressed by the symbol from the |
| shared library into the object, because the object being |
| run has to have the data at some particular address. */ |
| HOWTO (R_PPC64_COPY, /* type */ |
| 0, /* rightshift */ |
| 0, /* this one is variable size */ |
| 0, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_COPY", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like R_PPC64_ADDR64, but used when setting global offset table |
| entries. */ |
| HOWTO (R_PPC64_GLOB_DAT, /* type */ |
| 0, /* rightshift */ |
| 4, /* size (0=byte, 1=short, 2=long, 4=64 bits) */ |
| 64, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_GLOB_DAT", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| ONES (64), /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Created by the link editor. Marks a procedure linkage table |
| entry for a symbol. */ |
| HOWTO (R_PPC64_JMP_SLOT, /* type */ |
| 0, /* rightshift */ |
| 0, /* size (0 = byte, 1 = short, 2 = long) */ |
| 0, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_JMP_SLOT", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Used only by the dynamic linker. When the object is run, this |
| doubleword64 is set to the load address of the object, plus the |
| addend. */ |
| HOWTO (R_PPC64_RELATIVE, /* type */ |
| 0, /* rightshift */ |
| 4, /* size (0=byte, 1=short, 2=long, 4=64 bits) */ |
| 64, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| bfd_elf_generic_reloc, /* special_function */ |
| "R_PPC64_RELATIVE", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| ONES (64), /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like R_PPC64_ADDR32, but may be unaligned. */ |
| HOWTO (R_PPC64_UADDR32, /* type */ |
| 0, /* rightshift */ |
| 2, /* size (0 = byte, 1 = short, 2 = long) */ |
| 32, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_bitfield, /* complain_on_overflow */ |
| bfd_elf_generic_reloc, /* special_function */ |
| "R_PPC64_UADDR32", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffffffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like R_PPC64_ADDR16, but may be unaligned. */ |
| HOWTO (R_PPC64_UADDR16, /* type */ |
| 0, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_bitfield, /* complain_on_overflow */ |
| bfd_elf_generic_reloc, /* special_function */ |
| "R_PPC64_UADDR16", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* 32-bit PC relative. */ |
| HOWTO (R_PPC64_REL32, /* type */ |
| 0, /* rightshift */ |
| 2, /* size (0 = byte, 1 = short, 2 = long) */ |
| 32, /* bitsize */ |
| TRUE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed, /* complain_on_overflow */ |
| bfd_elf_generic_reloc, /* special_function */ |
| "R_PPC64_REL32", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffffffff, /* dst_mask */ |
| TRUE), /* pcrel_offset */ |
| |
| /* 32-bit relocation to the symbol's procedure linkage table. */ |
| HOWTO (R_PPC64_PLT32, /* type */ |
| 0, /* rightshift */ |
| 2, /* size (0 = byte, 1 = short, 2 = long) */ |
| 32, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_bitfield, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_PLT32", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffffffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* 32-bit PC relative relocation to the symbol's procedure linkage table. |
| FIXME: R_PPC64_PLTREL32 not supported. */ |
| HOWTO (R_PPC64_PLTREL32, /* type */ |
| 0, /* rightshift */ |
| 2, /* size (0 = byte, 1 = short, 2 = long) */ |
| 32, /* bitsize */ |
| TRUE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed, /* complain_on_overflow */ |
| bfd_elf_generic_reloc, /* special_function */ |
| "R_PPC64_PLTREL32", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffffffff, /* dst_mask */ |
| TRUE), /* pcrel_offset */ |
| |
| /* Like R_PPC64_ADDR16_LO, but referring to the PLT table entry for |
| the symbol. */ |
| HOWTO (R_PPC64_PLT16_LO, /* type */ |
| 0, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_PLT16_LO", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like R_PPC64_ADDR16_HI, but referring to the PLT table entry for |
| the symbol. */ |
| HOWTO (R_PPC64_PLT16_HI, /* type */ |
| 16, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_PLT16_HI", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like R_PPC64_ADDR16_HA, but referring to the PLT table entry for |
| the symbol. */ |
| HOWTO (R_PPC64_PLT16_HA, /* type */ |
| 16, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_PLT16_HA", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* 16-bit section relative relocation. */ |
| HOWTO (R_PPC64_SECTOFF, /* type */ |
| 0, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed, /* complain_on_overflow */ |
| ppc64_elf_sectoff_reloc, /* special_function */ |
| "R_PPC64_SECTOFF", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like R_PPC64_SECTOFF, but no overflow warning. */ |
| HOWTO (R_PPC64_SECTOFF_LO, /* type */ |
| 0, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| ppc64_elf_sectoff_reloc, /* special_function */ |
| "R_PPC64_SECTOFF_LO", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* 16-bit upper half section relative relocation. */ |
| HOWTO (R_PPC64_SECTOFF_HI, /* type */ |
| 16, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed, /* complain_on_overflow */ |
| ppc64_elf_sectoff_reloc, /* special_function */ |
| "R_PPC64_SECTOFF_HI", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* 16-bit upper half adjusted section relative relocation. */ |
| HOWTO (R_PPC64_SECTOFF_HA, /* type */ |
| 16, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed, /* complain_on_overflow */ |
| ppc64_elf_sectoff_ha_reloc, /* special_function */ |
| "R_PPC64_SECTOFF_HA", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like R_PPC64_REL24 without touching the two least significant bits. */ |
| HOWTO (R_PPC64_REL30, /* type */ |
| 2, /* rightshift */ |
| 2, /* size (0 = byte, 1 = short, 2 = long) */ |
| 30, /* bitsize */ |
| TRUE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| bfd_elf_generic_reloc, /* special_function */ |
| "R_PPC64_REL30", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xfffffffc, /* dst_mask */ |
| TRUE), /* pcrel_offset */ |
| |
| /* Relocs in the 64-bit PowerPC ELF ABI, not in the 32-bit ABI. */ |
| |
| /* A standard 64-bit relocation. */ |
| HOWTO (R_PPC64_ADDR64, /* type */ |
| 0, /* rightshift */ |
| 4, /* size (0=byte, 1=short, 2=long, 4=64 bits) */ |
| 64, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| bfd_elf_generic_reloc, /* special_function */ |
| "R_PPC64_ADDR64", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| ONES (64), /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* The bits 32-47 of an address. */ |
| HOWTO (R_PPC64_ADDR16_HIGHER, /* type */ |
| 32, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| bfd_elf_generic_reloc, /* special_function */ |
| "R_PPC64_ADDR16_HIGHER", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* The bits 32-47 of an address, plus 1 if the contents of the low |
| 16 bits, treated as a signed number, is negative. */ |
| HOWTO (R_PPC64_ADDR16_HIGHERA, /* type */ |
| 32, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| ppc64_elf_ha_reloc, /* special_function */ |
| "R_PPC64_ADDR16_HIGHERA", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* The bits 48-63 of an address. */ |
| HOWTO (R_PPC64_ADDR16_HIGHEST,/* type */ |
| 48, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| bfd_elf_generic_reloc, /* special_function */ |
| "R_PPC64_ADDR16_HIGHEST", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* The bits 48-63 of an address, plus 1 if the contents of the low |
| 16 bits, treated as a signed number, is negative. */ |
| HOWTO (R_PPC64_ADDR16_HIGHESTA,/* type */ |
| 48, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| ppc64_elf_ha_reloc, /* special_function */ |
| "R_PPC64_ADDR16_HIGHESTA", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like ADDR64, but may be unaligned. */ |
| HOWTO (R_PPC64_UADDR64, /* type */ |
| 0, /* rightshift */ |
| 4, /* size (0=byte, 1=short, 2=long, 4=64 bits) */ |
| 64, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| bfd_elf_generic_reloc, /* special_function */ |
| "R_PPC64_UADDR64", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| ONES (64), /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* 64-bit relative relocation. */ |
| HOWTO (R_PPC64_REL64, /* type */ |
| 0, /* rightshift */ |
| 4, /* size (0=byte, 1=short, 2=long, 4=64 bits) */ |
| 64, /* bitsize */ |
| TRUE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| bfd_elf_generic_reloc, /* special_function */ |
| "R_PPC64_REL64", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| ONES (64), /* dst_mask */ |
| TRUE), /* pcrel_offset */ |
| |
| /* 64-bit relocation to the symbol's procedure linkage table. */ |
| HOWTO (R_PPC64_PLT64, /* type */ |
| 0, /* rightshift */ |
| 4, /* size (0=byte, 1=short, 2=long, 4=64 bits) */ |
| 64, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_PLT64", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| ONES (64), /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* 64-bit PC relative relocation to the symbol's procedure linkage |
| table. */ |
| /* FIXME: R_PPC64_PLTREL64 not supported. */ |
| HOWTO (R_PPC64_PLTREL64, /* type */ |
| 0, /* rightshift */ |
| 4, /* size (0=byte, 1=short, 2=long, 4=64 bits) */ |
| 64, /* bitsize */ |
| TRUE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_PLTREL64", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| ONES (64), /* dst_mask */ |
| TRUE), /* pcrel_offset */ |
| |
| /* 16 bit TOC-relative relocation. */ |
| |
| /* R_PPC64_TOC16 47 half16* S + A - .TOC. */ |
| HOWTO (R_PPC64_TOC16, /* type */ |
| 0, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed, /* complain_on_overflow */ |
| ppc64_elf_toc_reloc, /* special_function */ |
| "R_PPC64_TOC16", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* 16 bit TOC-relative relocation without overflow. */ |
| |
| /* R_PPC64_TOC16_LO 48 half16 #lo (S + A - .TOC.) */ |
| HOWTO (R_PPC64_TOC16_LO, /* type */ |
| 0, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| ppc64_elf_toc_reloc, /* special_function */ |
| "R_PPC64_TOC16_LO", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* 16 bit TOC-relative relocation, high 16 bits. */ |
| |
| /* R_PPC64_TOC16_HI 49 half16 #hi (S + A - .TOC.) */ |
| HOWTO (R_PPC64_TOC16_HI, /* type */ |
| 16, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed, /* complain_on_overflow */ |
| ppc64_elf_toc_reloc, /* special_function */ |
| "R_PPC64_TOC16_HI", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* 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.) */ |
| HOWTO (R_PPC64_TOC16_HA, /* type */ |
| 16, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed, /* complain_on_overflow */ |
| ppc64_elf_toc_ha_reloc, /* special_function */ |
| "R_PPC64_TOC16_HA", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* 64-bit relocation; insert value of TOC base (.TOC.). */ |
| |
| /* R_PPC64_TOC 51 doubleword64 .TOC. */ |
| HOWTO (R_PPC64_TOC, /* type */ |
| 0, /* rightshift */ |
| 4, /* size (0=byte, 1=short, 2=long, 4=64 bits) */ |
| 64, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| ppc64_elf_toc64_reloc, /* special_function */ |
| "R_PPC64_TOC", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| ONES (64), /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like R_PPC64_GOT16, but also informs the link editor that the |
| value to relocate may (!) refer to a PLT entry which the link |
| editor (a) may replace with the symbol value. If the link editor |
| is unable to fully resolve the symbol, it may (b) create a PLT |
| entry and store the address to the new PLT entry in the GOT. |
| This permits lazy resolution of function symbols at run time. |
| 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. */ |
| HOWTO (R_PPC64_PLTGOT16, /* type */ |
| 0, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_PLTGOT16", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like R_PPC64_PLTGOT16, but without overflow. */ |
| /* FIXME: R_PPC64_PLTGOT16_LO not implemented. */ |
| HOWTO (R_PPC64_PLTGOT16_LO, /* type */ |
| 0, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_PLTGOT16_LO", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like R_PPC64_PLT_GOT16, but using bits 16-31 of the address. */ |
| /* FIXME: R_PPC64_PLTGOT16_HI not implemented. */ |
| HOWTO (R_PPC64_PLTGOT16_HI, /* type */ |
| 16, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_PLTGOT16_HI", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* 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. */ |
| HOWTO (R_PPC64_PLTGOT16_HA, /* type */ |
| 16, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_PLTGOT16_HA", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like R_PPC64_ADDR16, but for instructions with a DS field. */ |
| HOWTO (R_PPC64_ADDR16_DS, /* type */ |
| 0, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed, /* complain_on_overflow */ |
| bfd_elf_generic_reloc, /* special_function */ |
| "R_PPC64_ADDR16_DS", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xfffc, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like R_PPC64_ADDR16_LO, but for instructions with a DS field. */ |
| HOWTO (R_PPC64_ADDR16_LO_DS, /* type */ |
| 0, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont,/* complain_on_overflow */ |
| bfd_elf_generic_reloc, /* special_function */ |
| "R_PPC64_ADDR16_LO_DS",/* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xfffc, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like R_PPC64_GOT16, but for instructions with a DS field. */ |
| HOWTO (R_PPC64_GOT16_DS, /* type */ |
| 0, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_GOT16_DS", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xfffc, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like R_PPC64_GOT16_LO, but for instructions with a DS field. */ |
| HOWTO (R_PPC64_GOT16_LO_DS, /* type */ |
| 0, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_GOT16_LO_DS", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xfffc, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like R_PPC64_PLT16_LO, but for instructions with a DS field. */ |
| HOWTO (R_PPC64_PLT16_LO_DS, /* type */ |
| 0, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_PLT16_LO_DS", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xfffc, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like R_PPC64_SECTOFF, but for instructions with a DS field. */ |
| HOWTO (R_PPC64_SECTOFF_DS, /* type */ |
| 0, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed, /* complain_on_overflow */ |
| ppc64_elf_sectoff_reloc, /* special_function */ |
| "R_PPC64_SECTOFF_DS", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xfffc, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like R_PPC64_SECTOFF_LO, but for instructions with a DS field. */ |
| HOWTO (R_PPC64_SECTOFF_LO_DS, /* type */ |
| 0, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| ppc64_elf_sectoff_reloc, /* special_function */ |
| "R_PPC64_SECTOFF_LO_DS",/* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xfffc, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like R_PPC64_TOC16, but for instructions with a DS field. */ |
| HOWTO (R_PPC64_TOC16_DS, /* type */ |
| 0, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed, /* complain_on_overflow */ |
| ppc64_elf_toc_reloc, /* special_function */ |
| "R_PPC64_TOC16_DS", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xfffc, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like R_PPC64_TOC16_LO, but for instructions with a DS field. */ |
| HOWTO (R_PPC64_TOC16_LO_DS, /* type */ |
| 0, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| ppc64_elf_toc_reloc, /* special_function */ |
| "R_PPC64_TOC16_LO_DS", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xfffc, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like R_PPC64_PLTGOT16, but for instructions with a DS field. */ |
| /* FIXME: R_PPC64_PLTGOT16_DS not implemented. */ |
| HOWTO (R_PPC64_PLTGOT16_DS, /* type */ |
| 0, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_PLTGOT16_DS", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xfffc, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like R_PPC64_PLTGOT16_LO, but for instructions with a DS field. */ |
| /* FIXME: R_PPC64_PLTGOT16_LO not implemented. */ |
| HOWTO (R_PPC64_PLTGOT16_LO_DS,/* type */ |
| 0, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_PLTGOT16_LO_DS",/* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xfffc, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Marker relocs for TLS. */ |
| HOWTO (R_PPC64_TLS, |
| 0, /* rightshift */ |
| 2, /* size (0 = byte, 1 = short, 2 = long) */ |
| 32, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| bfd_elf_generic_reloc, /* special_function */ |
| "R_PPC64_TLS", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| HOWTO (R_PPC64_TLSGD, |
| 0, /* rightshift */ |
| 2, /* size (0 = byte, 1 = short, 2 = long) */ |
| 32, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| bfd_elf_generic_reloc, /* special_function */ |
| "R_PPC64_TLSGD", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| HOWTO (R_PPC64_TLSLD, |
| 0, /* rightshift */ |
| 2, /* size (0 = byte, 1 = short, 2 = long) */ |
| 32, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| bfd_elf_generic_reloc, /* special_function */ |
| "R_PPC64_TLSLD", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| HOWTO (R_PPC64_TOCSAVE, |
| 0, /* rightshift */ |
| 2, /* size (0 = byte, 1 = short, 2 = long) */ |
| 32, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| bfd_elf_generic_reloc, /* special_function */ |
| "R_PPC64_TOCSAVE", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Computes the load module index of the load module that contains the |
| definition of its TLS sym. */ |
| HOWTO (R_PPC64_DTPMOD64, |
| 0, /* rightshift */ |
| 4, /* size (0 = byte, 1 = short, 2 = long) */ |
| 64, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_DTPMOD64", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| ONES (64), /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Computes a dtv-relative displacement, the difference between the value |
| of sym+add and the base address of the thread-local storage block that |
| contains the definition of sym, minus 0x8000. */ |
| HOWTO (R_PPC64_DTPREL64, |
| 0, /* rightshift */ |
| 4, /* size (0 = byte, 1 = short, 2 = long) */ |
| 64, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_DTPREL64", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| ONES (64), /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* A 16 bit dtprel reloc. */ |
| HOWTO (R_PPC64_DTPREL16, |
| 0, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_DTPREL16", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like DTPREL16, but no overflow. */ |
| HOWTO (R_PPC64_DTPREL16_LO, |
| 0, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_DTPREL16_LO", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like DTPREL16_LO, but next higher group of 16 bits. */ |
| HOWTO (R_PPC64_DTPREL16_HI, |
| 16, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_DTPREL16_HI", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like DTPREL16_HI, but adjust for low 16 bits. */ |
| HOWTO (R_PPC64_DTPREL16_HA, |
| 16, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_DTPREL16_HA", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like DTPREL16_HI, but next higher group of 16 bits. */ |
| HOWTO (R_PPC64_DTPREL16_HIGHER, |
| 32, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_DTPREL16_HIGHER", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like DTPREL16_HIGHER, but adjust for low 16 bits. */ |
| HOWTO (R_PPC64_DTPREL16_HIGHERA, |
| 32, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_DTPREL16_HIGHERA", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like DTPREL16_HIGHER, but next higher group of 16 bits. */ |
| HOWTO (R_PPC64_DTPREL16_HIGHEST, |
| 48, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_DTPREL16_HIGHEST", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like DTPREL16_HIGHEST, but adjust for low 16 bits. */ |
| HOWTO (R_PPC64_DTPREL16_HIGHESTA, |
| 48, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_DTPREL16_HIGHESTA", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like DTPREL16, but for insns with a DS field. */ |
| HOWTO (R_PPC64_DTPREL16_DS, |
| 0, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_DTPREL16_DS", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xfffc, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like DTPREL16_DS, but no overflow. */ |
| HOWTO (R_PPC64_DTPREL16_LO_DS, |
| 0, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_DTPREL16_LO_DS", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xfffc, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Computes a tp-relative displacement, the difference between the value of |
| sym+add and the value of the thread pointer (r13). */ |
| HOWTO (R_PPC64_TPREL64, |
| 0, /* rightshift */ |
| 4, /* size (0 = byte, 1 = short, 2 = long) */ |
| 64, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_TPREL64", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| ONES (64), /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* A 16 bit tprel reloc. */ |
| HOWTO (R_PPC64_TPREL16, |
| 0, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_TPREL16", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like TPREL16, but no overflow. */ |
| HOWTO (R_PPC64_TPREL16_LO, |
| 0, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_TPREL16_LO", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like TPREL16_LO, but next higher group of 16 bits. */ |
| HOWTO (R_PPC64_TPREL16_HI, |
| 16, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_TPREL16_HI", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like TPREL16_HI, but adjust for low 16 bits. */ |
| HOWTO (R_PPC64_TPREL16_HA, |
| 16, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_TPREL16_HA", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like TPREL16_HI, but next higher group of 16 bits. */ |
| HOWTO (R_PPC64_TPREL16_HIGHER, |
| 32, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_TPREL16_HIGHER", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like TPREL16_HIGHER, but adjust for low 16 bits. */ |
| HOWTO (R_PPC64_TPREL16_HIGHERA, |
| 32, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_TPREL16_HIGHERA", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like TPREL16_HIGHER, but next higher group of 16 bits. */ |
| HOWTO (R_PPC64_TPREL16_HIGHEST, |
| 48, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_TPREL16_HIGHEST", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like TPREL16_HIGHEST, but adjust for low 16 bits. */ |
| HOWTO (R_PPC64_TPREL16_HIGHESTA, |
| 48, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_TPREL16_HIGHESTA", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like TPREL16, but for insns with a DS field. */ |
| HOWTO (R_PPC64_TPREL16_DS, |
| 0, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_TPREL16_DS", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xfffc, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like TPREL16_DS, but no overflow. */ |
| HOWTO (R_PPC64_TPREL16_LO_DS, |
| 0, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_TPREL16_LO_DS", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xfffc, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Allocates two contiguous entries in the GOT to hold a tls_index structure, |
| with values (sym+add)@dtpmod and (sym+add)@dtprel, and computes the offset |
| to the first entry relative to the TOC base (r2). */ |
| HOWTO (R_PPC64_GOT_TLSGD16, |
| 0, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_GOT_TLSGD16", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like GOT_TLSGD16, but no overflow. */ |
| HOWTO (R_PPC64_GOT_TLSGD16_LO, |
| 0, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_GOT_TLSGD16_LO", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like GOT_TLSGD16_LO, but next higher group of 16 bits. */ |
| HOWTO (R_PPC64_GOT_TLSGD16_HI, |
| 16, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_GOT_TLSGD16_HI", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like GOT_TLSGD16_HI, but adjust for low 16 bits. */ |
| HOWTO (R_PPC64_GOT_TLSGD16_HA, |
| 16, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_GOT_TLSGD16_HA", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Allocates two contiguous entries in the GOT to hold a tls_index structure, |
| with values (sym+add)@dtpmod and zero, and computes the offset to the |
| first entry relative to the TOC base (r2). */ |
| HOWTO (R_PPC64_GOT_TLSLD16, |
| 0, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_GOT_TLSLD16", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like GOT_TLSLD16, but no overflow. */ |
| HOWTO (R_PPC64_GOT_TLSLD16_LO, |
| 0, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_GOT_TLSLD16_LO", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like GOT_TLSLD16_LO, but next higher group of 16 bits. */ |
| HOWTO (R_PPC64_GOT_TLSLD16_HI, |
| 16, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_GOT_TLSLD16_HI", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like GOT_TLSLD16_HI, but adjust for low 16 bits. */ |
| HOWTO (R_PPC64_GOT_TLSLD16_HA, |
| 16, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_GOT_TLSLD16_HA", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Allocates an entry in the GOT with value (sym+add)@dtprel, and computes |
| the offset to the entry relative to the TOC base (r2). */ |
| HOWTO (R_PPC64_GOT_DTPREL16_DS, |
| 0, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_GOT_DTPREL16_DS", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xfffc, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like GOT_DTPREL16_DS, but no overflow. */ |
| HOWTO (R_PPC64_GOT_DTPREL16_LO_DS, |
| 0, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_GOT_DTPREL16_LO_DS", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xfffc, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like GOT_DTPREL16_LO_DS, but next higher group of 16 bits. */ |
| HOWTO (R_PPC64_GOT_DTPREL16_HI, |
| 16, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_GOT_DTPREL16_HI", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like GOT_DTPREL16_HI, but adjust for low 16 bits. */ |
| HOWTO (R_PPC64_GOT_DTPREL16_HA, |
| 16, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_GOT_DTPREL16_HA", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Allocates an entry in the GOT with value (sym+add)@tprel, and computes the |
| offset to the entry relative to the TOC base (r2). */ |
| HOWTO (R_PPC64_GOT_TPREL16_DS, |
| 0, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_GOT_TPREL16_DS", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xfffc, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like GOT_TPREL16_DS, but no overflow. */ |
| HOWTO (R_PPC64_GOT_TPREL16_LO_DS, |
| 0, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_GOT_TPREL16_LO_DS", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xfffc, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like GOT_TPREL16_LO_DS, but next higher group of 16 bits. */ |
| HOWTO (R_PPC64_GOT_TPREL16_HI, |
| 16, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_GOT_TPREL16_HI", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like GOT_TPREL16_HI, but adjust for low 16 bits. */ |
| HOWTO (R_PPC64_GOT_TPREL16_HA, |
| 16, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_GOT_TPREL16_HA", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| HOWTO (R_PPC64_JMP_IREL, /* type */ |
| 0, /* rightshift */ |
| 0, /* size (0=byte, 1=short, 2=long, 4=64 bits) */ |
| 0, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_JMP_IREL", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| HOWTO (R_PPC64_IRELATIVE, /* type */ |
| 0, /* rightshift */ |
| 4, /* size (0=byte, 1=short, 2=long, 4=64 bits) */ |
| 64, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| bfd_elf_generic_reloc, /* special_function */ |
| "R_PPC64_IRELATIVE", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| ONES (64), /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* A 16 bit relative relocation. */ |
| HOWTO (R_PPC64_REL16, /* type */ |
| 0, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| TRUE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed, /* complain_on_overflow */ |
| bfd_elf_generic_reloc, /* special_function */ |
| "R_PPC64_REL16", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| TRUE), /* pcrel_offset */ |
| |
| /* A 16 bit relative relocation without overflow. */ |
| HOWTO (R_PPC64_REL16_LO, /* type */ |
| 0, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| TRUE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont,/* complain_on_overflow */ |
| bfd_elf_generic_reloc, /* special_function */ |
| "R_PPC64_REL16_LO", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| TRUE), /* pcrel_offset */ |
| |
| /* The high order 16 bits of a relative address. */ |
| HOWTO (R_PPC64_REL16_HI, /* type */ |
| 16, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| TRUE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed, /* complain_on_overflow */ |
| bfd_elf_generic_reloc, /* special_function */ |
| "R_PPC64_REL16_HI", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| TRUE), /* pcrel_offset */ |
| |
| /* The high order 16 bits of a relative address, plus 1 if the contents of |
| the low 16 bits, treated as a signed number, is negative. */ |
| HOWTO (R_PPC64_REL16_HA, /* type */ |
| 16, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| TRUE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed, /* complain_on_overflow */ |
| ppc64_elf_ha_reloc, /* special_function */ |
| "R_PPC64_REL16_HA", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| TRUE), /* pcrel_offset */ |
| |
| /* Like R_PPC64_REL16_HA but for split field in addpcis. */ |
| HOWTO (R_PPC64_REL16DX_HA, /* type */ |
| 16, /* rightshift */ |
| 2, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| TRUE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_signed, /* complain_on_overflow */ |
| ppc64_elf_ha_reloc, /* special_function */ |
| "R_PPC64_REL16DX_HA", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0x1fffc1, /* dst_mask */ |
| TRUE), /* pcrel_offset */ |
| |
| /* Like R_PPC64_ADDR16_HI, but no overflow. */ |
| HOWTO (R_PPC64_ADDR16_HIGH, /* type */ |
| 16, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| bfd_elf_generic_reloc, /* special_function */ |
| "R_PPC64_ADDR16_HIGH", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like R_PPC64_ADDR16_HA, but no overflow. */ |
| HOWTO (R_PPC64_ADDR16_HIGHA, /* type */ |
| 16, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| ppc64_elf_ha_reloc, /* special_function */ |
| "R_PPC64_ADDR16_HIGHA", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like R_PPC64_DTPREL16_HI, but no overflow. */ |
| HOWTO (R_PPC64_DTPREL16_HIGH, |
| 16, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_DTPREL16_HIGH", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like R_PPC64_DTPREL16_HA, but no overflow. */ |
| HOWTO (R_PPC64_DTPREL16_HIGHA, |
| 16, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_DTPREL16_HIGHA", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like R_PPC64_TPREL16_HI, but no overflow. */ |
| HOWTO (R_PPC64_TPREL16_HIGH, |
| 16, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_TPREL16_HIGH", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like R_PPC64_TPREL16_HA, but no overflow. */ |
| HOWTO (R_PPC64_TPREL16_HIGHA, |
| 16, /* rightshift */ |
| 1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 16, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| ppc64_elf_unhandled_reloc, /* special_function */ |
| "R_PPC64_TPREL16_HIGHA", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0xffff, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Marker reloc on ELFv2 large-model function entry. */ |
| HOWTO (R_PPC64_ENTRY, |
| 0, /* rightshift */ |
| 2, /* size (0 = byte, 1 = short, 2 = long) */ |
| 32, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| bfd_elf_generic_reloc, /* special_function */ |
| "R_PPC64_ENTRY", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* Like ADDR64, but use local entry point of function. */ |
| HOWTO (R_PPC64_ADDR64_LOCAL, /* type */ |
| 0, /* rightshift */ |
| 4, /* size (0=byte, 1=short, 2=long, 4=64 bits) */ |
| 64, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| bfd_elf_generic_reloc, /* special_function */ |
| "R_PPC64_ADDR64_LOCAL", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| ONES (64), /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* GNU extension to record C++ vtable hierarchy. */ |
| HOWTO (R_PPC64_GNU_VTINHERIT, /* type */ |
| 0, /* rightshift */ |
| 0, /* size (0 = byte, 1 = short, 2 = long) */ |
| 0, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| NULL, /* special_function */ |
| "R_PPC64_GNU_VTINHERIT", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| |
| /* GNU extension to record C++ vtable member usage. */ |
| HOWTO (R_PPC64_GNU_VTENTRY, /* type */ |
| 0, /* rightshift */ |
| 0, /* size (0 = byte, 1 = short, 2 = long) */ |
| 0, /* bitsize */ |
| FALSE, /* pc_relative */ |
| 0, /* bitpos */ |
| complain_overflow_dont, /* complain_on_overflow */ |
| NULL, /* special_function */ |
| "R_PPC64_GNU_VTENTRY", /* name */ |
| FALSE, /* partial_inplace */ |
| 0, /* src_mask */ |
| 0, /* dst_mask */ |
| FALSE), /* pcrel_offset */ |
| }; |
| |
| |
| /* Initialize the ppc64_elf_howto_table, so that linear accesses can |
| be done. */ |
| |
| static void |
| ppc_howto_init (void) |
| { |
| unsigned int i, type; |
| |
| for (i = 0; i < ARRAY_SIZE (ppc64_elf_howto_raw); i++) |
| { |
| type = ppc64_elf_howto_raw[i].type; |
| BFD_ASSERT (type < ARRAY_SIZE (ppc64_elf_howto_table)); |
| ppc64_elf_howto_table[type] = &ppc64_elf_howto_raw[i]; |
| } |
| } |
| |
| static reloc_howto_type * |
| ppc64_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, |
| bfd_reloc_code_real_type code) |
| { |
| enum elf_ppc64_reloc_type r = R_PPC64_NONE; |
| |
| if (!ppc64_elf_howto_table[R_PPC64_ADDR32]) |
| /* Initialize howto table if needed. */ |
| ppc_howto_init (); |
| |
| switch (code) |
| { |
| default: |
| return NULL; |
| |
| case BFD_RELOC_NONE: r = R_PPC64_NONE; |
| break; |
| case BFD_RELOC_32: r = R_PPC64_ADDR32; |
| break; |
| case BFD_RELOC_PPC_BA26: r = R_PPC64_ADDR24; |
| break; |
| case BFD_RELOC_16: r = R_PPC64_ADDR16; |
| break; |
| case BFD_RELOC_LO16: r = R_PPC64_ADDR16_LO; |
| break; |
| case BFD_RELOC_HI16: r = R_PPC64_ADDR16_HI; |
| break; |
| case BFD_RELOC_PPC64_ADDR16_HIGH: r = R_PPC64_ADDR16_HIGH; |
| break; |
| case BFD_RELOC_HI16_S: r = R_PPC64_ADDR16_HA; |
| break; |
| case BFD_RELOC_PPC64_ADDR16_HIGHA: r = R_PPC64_ADDR16_HIGHA; |
| break; |
| case BFD_RELOC_PPC_BA16: r = R_PPC64_ADDR14; |
| break; |
| case BFD_RELOC_PPC_BA16_BRTAKEN: r = R_PPC64_ADDR14_BRTAKEN; |
| break; |
| case BFD_RELOC_PPC_BA16_BRNTAKEN: r = R_PPC64_ADDR14_BRNTAKEN; |
| break; |
| case BFD_RELOC_PPC_B26: r = R_PPC64_REL24; |
| break; |
| case BFD_RELOC_PPC_B16: r = R_PPC64_REL14; |
| break; |
| case BFD_RELOC_PPC_B16_BRTAKEN: r = R_PPC64_REL14_BRTAKEN; |
| break; |
| case BFD_RELOC_PPC_B16_BRNTAKEN: r = R_PPC64_REL14_BRNTAKEN; |
| break; |
| case BFD_RELOC_16_GOTOFF: r = R_PPC64_GOT16; |
| break; |
| case BFD_RELOC_LO16_GOTOFF: r = R_PPC64_GOT16_LO; |
| break; |
| case BFD_RELOC_HI16_GOTOFF: r = R_PPC64_GOT16_HI; |
| break; |
| case BFD_RELOC_HI16_S_GOTOFF: r = R_PPC64_GOT16_HA; |
| break; |
| case BFD_RELOC_PPC_COPY: r = R_PPC64_COPY; |
| break; |
| case BFD_RELOC_PPC_GLOB_DAT: r = R_PPC64_GLOB_DAT; |
| break; |
| case BFD_RELOC_32_PCREL: r = R_PPC64_REL32; |
| break; |
| case BFD_RELOC_32_PLTOFF: r = R_PPC64_PLT32; |
| break; |
| case BFD_RELOC_32_PLT_PCREL: r = R_PPC64_PLTREL32; |
| break; |
| case BFD_RELOC_LO16_PLTOFF: r = R_PPC64_PLT16_LO; |
| break; |
| case BFD_RELOC_HI16_PLTOFF: r = R_PPC64_PLT16_HI; |
| break; |
| case BFD_RELOC_HI16_S_PLTOFF: r = R_PPC64_PLT16_HA; |
| break; |
| case BFD_RELOC_16_BASEREL: r = R_PPC64_SECTOFF; |
| break; |
| case BFD_RELOC_LO16_BASEREL: r = R_PPC64_SECTOFF_LO; |
| break; |
| case BFD_RELOC_HI16_BASEREL: r = R_PPC64_SECTOFF_HI; |
| break; |
| case BFD_RELOC_HI16_S_BASEREL: r = R_PPC64_SECTOFF_HA; |
| break; |
| case BFD_RELOC_CTOR: r = R_PPC64_ADDR64; |
| break; |
| case BFD_RELOC_64: r = R_PPC64_ADDR64; |
| break; |
| case BFD_RELOC_PPC64_HIGHER: r = R_PPC64_ADDR16_HIGHER; |
| break; |
| case BFD_RELOC_PPC64_HIGHER_S: r = R_PPC64_ADDR16_HIGHERA; |
| break; |
| case BFD_RELOC_PPC64_HIGHEST: r = R_PPC64_ADDR16_HIGHEST; |
| break; |
| case BFD_RELOC_PPC64_HIGHEST_S: r = R_PPC64_ADDR16_HIGHESTA; |
| break; |
| case BFD_RELOC_64_PCREL: r = R_PPC64_REL64; |
| break; |
| case BFD_RELOC_64_PLTOFF: r = R_PPC64_PLT64; |
| break; |
| case BFD_RELOC_64_PLT_PCREL: r = R_PPC64_PLTREL64; |
| break; |
| case BFD_RELOC_PPC_TOC16: r = R_PPC64_TOC16; |
| break; |
| case BFD_RELOC_PPC64_TOC16_LO: r = R_PPC64_TOC16_LO; |
| break; |
| case BFD_RELOC_PPC64_TOC16_HI: r = R_PPC64_TOC16_HI; |
| break; |
| case BFD_RELOC_PPC64_TOC16_HA: r = R_PPC64_TOC16_HA; |
| break; |
| case BFD_RELOC_PPC64_TOC: r = R_PPC64_TOC; |
| break; |
| case BFD_RELOC_PPC64_PLTGOT16: r = R_PPC64_PLTGOT16; |
| break; |
| case BFD_RELOC_PPC64_PLTGOT16_LO: r = R_PPC64_PLTGOT16_LO; |
| break; |
| case BFD_RELOC_PPC64_PLTGOT16_HI: r = R_PPC64_PLTGOT16_HI; |
| break; |
| case BFD_RELOC_PPC64_PLTGOT16_HA: r = R_PPC64_PLTGOT16_HA; |
| break; |
| case BFD_RELOC_PPC64_ADDR16_DS: r = R_PPC64_ADDR16_DS; |
| break; |
| case BFD_RELOC_PPC64_ADDR16_LO_DS: r = R_PPC64_ADDR16_LO_DS; |
| break; |
| case BFD_RELOC_PPC64_GOT16_DS: r = R_PPC64_GOT16_DS; |
| break; |
| case BFD_RELOC_PPC64_GOT16_LO_DS: r = R_PPC64_GOT16_LO_DS; |
| break; |
| case BFD_RELOC_PPC64_PLT16_LO_DS: r = R_PPC64_PLT16_LO_DS; |
| break; |
| case BFD_RELOC_PPC64_SECTOFF_DS: r = R_PPC64_SECTOFF_DS; |
| break; |
| case BFD_RELOC_PPC64_SECTOFF_LO_DS: r = R_PPC64_SECTOFF_LO_DS; |
| break; |
| case BFD_RELOC_PPC64_TOC16_DS: r = R_PPC64_TOC16_DS; |
| break; |
| case BFD_RELOC_PPC64_TOC16_LO_DS: r = R_PPC64_TOC16_LO_DS; |
| break; |
| case BFD_RELOC_PPC64_PLTGOT16_DS: r = R_PPC64_PLTGOT16_DS; |
| break; |
| case BFD_RELOC_PPC64_PLTGOT16_LO_DS: r = R_PPC64_PLTGOT16_LO_DS; |
| break; |
| case BFD_RELOC_PPC_TLS: r = R_PPC64_TLS; |
| break; |
| case BFD_RELOC_PPC_TLSGD: r = R_PPC64_TLSGD; |
| break; |
| case BFD_RELOC_PPC_TLSLD: r = R_PPC64_TLSLD; |
| break; |
| case BFD_RELOC_PPC_DTPMOD: r = R_PPC64_DTPMOD64; |
| break; |
| case BFD_RELOC_PPC_TPREL16: r = R_PPC64_TPREL16; |
| break; |
| case BFD_RELOC_PPC_TPREL16_LO: r = R_PPC64_TPREL16_LO; |
| break; |
| case BFD_RELOC_PPC_TPREL16_HI: r = R_PPC64_TPREL16_HI; |
| break; |
| case BFD_RELOC_PPC64_TPREL16_HIGH: r = R_PPC64_TPREL16_HIGH; |
| break; |
| case BFD_RELOC_PPC_TPREL16_HA: r = R_PPC64_TPREL16_HA; |
| break; |
| case BFD_RELOC_PPC64_TPREL16_HIGHA: r = R_PPC64_TPREL16_HIGHA; |
| break; |
| case BFD_RELOC_PPC_TPREL: r = R_PPC64_TPREL64; |
| break; |
| case BFD_RELOC_PPC_DTPREL16: r = R_PPC64_DTPREL16; |
| break; |
| case BFD_RELOC_PPC_DTPREL16_LO: r = R_PPC64_DTPREL16_LO; |
| break; |
| case BFD_RELOC_PPC_DTPREL16_HI: r = R_PPC64_DTPREL16_HI; |
| break; |
| case BFD_RELOC_PPC64_DTPREL16_HIGH: r = R_PPC64_DTPREL16_HIGH; |
| break; |
| case BFD_RELOC_PPC_DTPREL16_HA: r = R_PPC64_DTPREL16_HA; |
| break; |
| case BFD_RELOC_PPC64_DTPREL16_HIGHA: r = R_PPC64_DTPREL16_HIGHA; |
| break; |
| case BFD_RELOC_PPC_DTPREL: r = R_PPC64_DTPREL64; |
| break; |
| case BFD_RELOC_PPC_GOT_TLSGD16: r = R_PPC64_GOT_TLSGD16; |
| break; |
| case BFD_RELOC_PPC_GOT_TLSGD16_LO: r = R_PPC64_GOT_TLSGD16_LO; |
| break; |
| case BFD_RELOC_PPC_GOT_TLSGD16_HI: r = R_PPC64_GOT_TLSGD16_HI; |
| break; |
| case BFD_RELOC_PPC_GOT_TLSGD16_HA: r = R_PPC64_GOT_TLSGD16_HA; |
| break; |
| case BFD_RELOC_PPC_GOT_TLSLD16: r = R_PPC64_GOT_TLSLD16; |
| break; |
| case BFD_RELOC_PPC_GOT_TLSLD16_LO: r = R_PPC64_GOT_TLSLD16_LO; |
| break; |
| case BFD_RELOC_PPC_GOT_TLSLD16_HI: r = R_PPC64_GOT_TLSLD16_HI; |
| break; |
| case BFD_RELOC_PPC_GOT_TLSLD16_HA: r = R_PPC64_GOT_TLSLD16_HA; |
| break; |
| case BFD_RELOC_PPC_GOT_TPREL16: r = R_PPC64_GOT_TPREL16_DS; |
| break; |
| case BFD_RELOC_PPC_GOT_TPREL16_LO: r = R_PPC64_GOT_TPREL16_LO_DS; |
| break; |
| case BFD_RELOC_PPC_GOT_TPREL16_HI: r = R_PPC64_GOT_TPREL16_HI; |
| break; |
| case BFD_RELOC_PPC_GOT_TPREL16_HA: r = R_PPC64_GOT_TPREL16_HA; |
| break; |
| case BFD_RELOC_PPC_GOT_DTPREL16: r = R_PPC64_GOT_DTPREL16_DS; |
| break; |
| case BFD_RELOC_PPC_GOT_DTPREL16_LO: r = R_PPC64_GOT_DTPREL16_LO_DS; |
| break; |
| case BFD_RELOC_PPC_GOT_DTPREL16_HI: r = R_PPC64_GOT_DTPREL16_HI; |
| break; |
| case BFD_RELOC_PPC_GOT_DTPREL16_HA: r = R_PPC64_GOT_DTPREL16_HA; |
| break; |
| case BFD_RELOC_PPC64_TPREL16_DS: r = R_PPC64_TPREL16_DS; |
| break; |
| case BFD_RELOC_PPC64_TPREL16_LO_DS: r = R_PPC64_TPREL16_LO_DS; |
| break; |
| case BFD_RELOC_PPC64_TPREL16_HIGHER: r = R_PPC64_TPREL16_HIGHER; |
| break; |
| case BFD_RELOC_PPC64_TPREL16_HIGHERA: r = R_PPC64_TPREL16_HIGHERA; |
| break; |
| case BFD_RELOC_PPC64_TPREL16_HIGHEST: r = R_PPC64_TPREL16_HIGHEST; |
| break; |
| case BFD_RELOC_PPC64_TPREL16_HIGHESTA: r = R_PPC64_TPREL16_HIGHESTA; |
| break; |
| case BFD_RELOC_PPC64_DTPREL16_DS: r = R_PPC64_DTPREL16_DS; |
| break; |
| case BFD_RELOC_PPC64_DTPREL16_LO_DS: r = R_PPC64_DTPREL16_LO_DS; |
| break; |
| case BFD_RELOC_PPC64_DTPREL16_HIGHER: r = R_PPC64_DTPREL16_HIGHER; |
| break; |
| case BFD_RELOC_PPC64_DTPREL16_HIGHERA: r = R_PPC64_DTPREL16_HIGHERA; |
| break; |
| case BFD_RELOC_PPC64_DTPREL16_HIGHEST: r = R_PPC64_DTPREL16_HIGHEST; |
| break; |
| case BFD_RELOC_PPC64_DTPREL16_HIGHESTA: r = R_PPC64_DTPREL16_HIGHESTA; |
| break; |
| case BFD_RELOC_16_PCREL: r = R_PPC64_REL16; |
| break; |
| case BFD_RELOC_LO16_PCREL: r = R_PPC64_REL16_LO; |
| break; |
| case BFD_RELOC_HI16_PCREL: r = R_PPC64_REL16_HI; |
| break; |
| case BFD_RELOC_HI16_S_PCREL: r = R_PPC64_REL16_HA; |
| break; |
| case BFD_RELOC_PPC_REL16DX_HA: r = R_PPC64_REL16DX_HA; |
| break; |
| case BFD_RELOC_PPC64_ENTRY: r = R_PPC64_ENTRY; |
| break; |
| case BFD_RELOC_PPC64_ADDR64_LOCAL: r = R_PPC64_ADDR64_LOCAL; |
| break; |
| case BFD_RELOC_VTABLE_INHERIT: r = R_PPC64_GNU_VTINHERIT; |
| break; |
| case BFD_RELOC_VTABLE_ENTRY: r = R_PPC64_GNU_VTENTRY; |
| break; |
| } |
| |
| return ppc64_elf_howto_table[r]; |
| }; |
| |
| static reloc_howto_type * |
| ppc64_elf_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, |
| const char *r_name) |
| { |
| unsigned int i; |
| |
| for (i = 0; i < ARRAY_SIZE (ppc64_elf_howto_raw); i++) |
| if (ppc64_elf_howto_raw[i].name != NULL |
| && strcasecmp (ppc64_elf_howto_raw[i].name, r_name) == 0) |
| return &ppc64_elf_howto_raw[i]; |
| |
| return NULL; |
| } |
| |
| /* Set the howto pointer for a PowerPC ELF reloc. */ |
| |
| static void |
| ppc64_elf_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr, |
| Elf_Internal_Rela *dst) |
| { |
| unsigned int type; |
| |
| /* Initialize howto table if needed. */ |
| if (!ppc64_elf_howto_table[R_PPC64_ADDR32]) |
| ppc_howto_init (); |
| |
| type = ELF64_R_TYPE (dst->r_info); |
| if (type >= ARRAY_SIZE (ppc64_elf_howto_table)) |
| { |
| (*_bfd_error_handler) (_("%B: invalid relocation type %d"), |
| abfd, (int) type); |
| type = R_PPC64_NONE; |
| } |
| cache_ptr->howto = ppc64_elf_howto_table[type]; |
| } |
| |
| /* Handle the R_PPC64_ADDR16_HA and similar relocs. */ |
| |
| static bfd_reloc_status_type |
| ppc64_elf_ha_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, |
| void *data, asection *input_section, |
| bfd *output_bfd, char **error_message) |
| { |
| enum elf_ppc64_reloc_type r_type; |
| long insn; |
| bfd_size_type octets; |
| bfd_vma value; |
| |
| /* If this is a relocatable link (output_bfd test tells us), just |
| call the generic function. Any adjustment will be done at final |
| link time. */ |
| if (output_bfd != NULL) |
| return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, |
| input_section, output_bfd, error_message); |
| |
| /* Adjust the addend for sign extension of the low 16 bits. |
| We won't actually be using the low 16 bits, so trashing them |
| doesn't matter. */ |
| reloc_entry->addend += 0x8000; |
| r_type = reloc_entry->howto->type; |
| if (r_type != R_PPC64_REL16DX_HA) |
| return bfd_reloc_continue; |
| |
| value = 0; |
| if (!bfd_is_com_section (symbol->section)) |
| value = symbol->value; |
| value += (reloc_entry->addend |
| + symbol->section->output_offset |
| + symbol->section->output_section->vma); |
| value -= (reloc_entry->address |
| + input_section->output_offset |
| + input_section->output_section->vma); |
| value = (bfd_signed_vma) value >> 16; |
| |
| octets = reloc_entry->address * bfd_octets_per_byte (abfd); |
| insn = bfd_get_32 (abfd, (bfd_byte *) data + octets); |
| insn &= ~0x1fffc1; |
| insn |= (value & 0xffc1) | ((value & 0x3e) << 15); |
| bfd_put_32 (abfd, insn, (bfd_byte *) data + octets); |
| if (value + 0x8000 > 0xffff) |
| return bfd_reloc_overflow; |
| return bfd_reloc_ok; |
| } |
| |
| static bfd_reloc_status_type |
| ppc64_elf_branch_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, |
| void *data, asection *input_section, |
| bfd *output_bfd, char **error_message) |
| { |
| if (output_bfd != NULL) |
| return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, |
| input_section, output_bfd, error_message); |
| |
| if (strcmp (symbol->section->name, ".opd") == 0 |
| && (symbol->section->owner->flags & DYNAMIC) == 0) |
| { |
| bfd_vma dest = opd_entry_value (symbol->section, |
| symbol->value + reloc_entry->addend, |
| NULL, NULL, FALSE); |
| if (dest != (bfd_vma) -1) |
| reloc_entry->addend = dest - (symbol->value |
| + symbol->section->output_section->vma |
| + symbol->section->output_offset); |
| } |
| else |
| { |
| elf_symbol_type *elfsym = (elf_symbol_type *) symbol; |
| |
| if (symbol->section->owner != abfd |
| && symbol->section->owner != NULL |
| && abiversion (symbol->section->owner) >= 2) |
| { |
| unsigned int i; |
| |
| for (i = 0; i < symbol->section->owner->symcount; ++i) |
| { |
| asymbol *symdef = symbol->section->owner->outsymbols[i]; |
| |
| if (strcmp (symdef->name, symbol->name) == 0) |
| { |
| elfsym = (elf_symbol_type *) symdef; |
| break; |
| } |
| } |
| } |
| reloc_entry->addend |
| += PPC64_LOCAL_ENTRY_OFFSET (elfsym->internal_elf_sym.st_other); |
| } |
| return bfd_reloc_continue; |
| } |
| |
| static bfd_reloc_status_type |
| ppc64_elf_brtaken_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, |
| void *data, asection *input_section, |
| bfd *output_bfd, char **error_message) |
| { |
| long insn; |
| enum elf_ppc64_reloc_type r_type; |
| bfd_size_type octets; |
| /* Assume 'at' branch hints. */ |
| bfd_boolean 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 |
| link time. */ |
| if (output_bfd != NULL) |
| return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, |
| input_section, output_bfd, error_message); |
| |
| octets = reloc_entry->address * bfd_octets_per_byte (abfd); |
| insn = bfd_get_32 (abfd, (bfd_byte *) data + octets); |
| insn &= ~(0x01 << 21); |
| r_type = reloc_entry->howto->type; |
| if (r_type == R_PPC64_ADDR14_BRTAKEN |
| || r_type == R_PPC64_REL14_BRTAKEN) |
| insn |= 0x01 << 21; /* 'y' or 't' bit, lowest bit of BO field. */ |
| |
| if (is_isa_v2) |
| { |
| /* Set 'a' bit. This is 0b00010 in BO field for branch |
| on CR(BI) insns (BO == 001at or 011at), and 0b01000 |
| for branch on CTR insns (BO == 1a00t or 1a01t). */ |
| if ((insn & (0x14 << 21)) == (0x04 << 21)) |
| insn |= 0x02 << 21; |
| else if ((insn & (0x14 << 21)) == (0x10 << 21)) |
| insn |= 0x08 << 21; |
| else |
| goto out; |
| } |
| else |
| { |
| bfd_vma target = 0; |
| bfd_vma from; |
| |
| if (!bfd_is_com_section (symbol->section)) |
| target = symbol->value; |
| target += symbol->section->output_section->vma; |
| target += symbol->section->output_offset; |
| target += reloc_entry->addend; |
| |
| from = (reloc_entry->address |
| + input_section->output_offset |
| + input_section->output_section->vma); |
| |
| /* Invert 'y' bit if not the default. */ |
| if ((bfd_signed_vma) (target - from) < 0) |
| insn ^= 0x01 << 21; |
| } |
| bfd_put_32 (abfd, insn, (bfd_byte *) data + octets); |
| out: |
| return ppc64_elf_branch_reloc (abfd, reloc_entry, symbol, data, |
| input_section, output_bfd, error_message); |
| } |
| |
| static bfd_reloc_status_type |
| ppc64_elf_sectoff_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, |
| void *data, asection *input_section, |
| bfd *output_bfd, char **error_message) |
| { |
| /* If this is a relocatable link (output_bfd test tells us), just |
| call the generic function. Any adjustment will be done at final |
| link time. */ |
| if (output_bfd != NULL) |
| return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, |
| input_section, output_bfd, error_message); |
| |
| /* Subtract the symbol section base address. */ |
| reloc_entry->addend -= symbol->section->output_section->vma; |
| return bfd_reloc_continue; |
| } |
| |
| static bfd_reloc_status_type |
| ppc64_elf_sectoff_ha_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, |
| void *data, asection *input_section, |
| bfd *output_bfd, char **error_message) |
| { |
| /* If this is a relocatable link (output_bfd test tells us), just |
| call the generic function. Any adjustment will be done at final |
| link time. */ |
| if (output_bfd != NULL) |
| return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, |
| input_section, output_bfd, error_message); |
| |
| /* Subtract the symbol section base address. */ |
| reloc_entry->addend -= symbol->section->output_section->vma; |
| |
| /* Adjust the addend for sign extension of the low 16 bits. */ |
| reloc_entry->addend += 0x8000; |
| return bfd_reloc_continue; |
| } |
| |
| static bfd_reloc_status_type |
| ppc64_elf_toc_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, |
| void *data, asection *input_section, |
| bfd *output_bfd, char **error_message) |
| { |
| bfd_vma TOCstart; |
| |
| /* If this is a relocatable link (output_bfd test tells us), just |
| call the generic function. Any adjustment will be done at final |
| link time. */ |
| if (output_bfd != NULL) |
| return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, |
| input_section, output_bfd, error_message); |
| |
| TOCstart = _bfd_get_gp_value (input_section->output_section->owner); |
| if (TOCstart == 0) |
| TOCstart = ppc64_elf_set_toc (NULL, input_section->output_section->owner); |
| |
| /* Subtract the TOC base address. */ |
| reloc_entry->addend -= TOCstart + TOC_BASE_OFF; |
| return bfd_reloc_continue; |
| } |
| |
| static bfd_reloc_status_type |
| ppc64_elf_toc_ha_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, |
| void *data, asection *input_section, |
| bfd *output_bfd, char **error_message) |
| { |
| bfd_vma TOCstart; |
| |
| /* If this is a relocatable link (output_bfd test tells us), just |
| call the generic function. Any adjustment will be done at final |
| link time. */ |
| if (output_bfd != NULL) |
| return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, |
| input_section, output_bfd, error_message); |
| |
| TOCstart = _bfd_get_gp_value (input_section->output_section->owner); |
| if (TOCstart == 0) |
| TOCstart = ppc64_elf_set_toc (NULL, input_section->output_section->owner); |
| |
| /* Subtract the TOC base address. */ |
| reloc_entry->addend -= TOCstart + TOC_BASE_OFF; |
| |
| /* Adjust the addend for sign extension of the low 16 bits. */ |
| reloc_entry->addend += 0x8000; |
| return bfd_reloc_continue; |
| } |
| |
| static bfd_reloc_status_type |
| ppc64_elf_toc64_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, |
| void *data, asection *input_section, |
| bfd *output_bfd, char **error_message) |
| { |
| bfd_vma TOCstart; |
| bfd_size_type octets; |
| |
| /* If this is a relocatable link (output_bfd test tells us), just |
| call the generic function. Any adjustment will be done at final |
| link time. */ |
| if (output_bfd != NULL) |
| return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, |
| input_section, output_bfd, error_message); |
| |
| TOCstart = _bfd_get_gp_value (input_section->output_section->owner); |
| if (TOCstart == 0) |
| TOCstart = ppc64_elf_set_toc (NULL, input_section->output_section->owner); |
| |
| octets = reloc_entry->address * bfd_octets_per_byte (abfd); |
| bfd_put_64 (abfd, TOCstart + TOC_BASE_OFF, (bfd_byte *) data + octets); |
| return bfd_reloc_ok; |
| } |
| |
| static bfd_reloc_status_type |
| ppc64_elf_unhandled_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, |
| void *data, asection *input_section, |
| bfd *output_bfd, char **error_message) |
| { |
| /* If this is a relocatable link (output_bfd test tells us), just |
| call the generic function. Any adjustment will be done at final |
| link time. */ |
| if (output_bfd != NULL) |
| return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, |
| input_section, output_bfd, error_message); |
| |
| if (error_message != NULL) |
| { |
| static char buf[60]; |
| sprintf (buf, "generic linker can't handle %s", |
| reloc_entry->howto->name); |
| *error_message = buf; |
| } |
| return bfd_reloc_dangerous; |
| } |
| |
| /* Track GOT entries needed for a given symbol. We might need more |
| than one got entry per symbol. */ |
| struct got_entry |
| { |
| struct got_entry *next; |
| |
| /* The symbol addend that we'll be placing in the GOT. */ |
| bfd_vma addend; |
| |
| /* Unlike other ELF targets, we use separate GOT entries for the same |
| symbol referenced from different input files. This is to support |
| automatic multiple TOC/GOT sections, where the TOC base can vary |
| from one input file to another. After partitioning into TOC groups |
| we merge entries within the group. |
| |
| Point to the BFD owning this GOT entry. */ |
| bfd *owner; |
| |
| /* Zero for non-tls entries, or TLS_TLS and one of TLS_GD, TLS_LD, |
| TLS_TPREL or TLS_DTPREL for tls entries. */ |
| unsigned char tls_type; |
| |
| /* Non-zero if got.ent points to real entry. */ |
| unsigned char is_indirect; |
| |
| /* Reference count until size_dynamic_sections, GOT offset thereafter. */ |
| union |
| { |
| bfd_signed_vma refcount; |
| bfd_vma offset; |
| struct got_entry *ent; |
| } got; |
| }; |
| |
| /* The same for PLT. */ |
| struct plt_entry |
| { |
| struct plt_entry *next; |
| |
| bfd_vma addend; |
| |
| union |
| { |
| bfd_signed_vma refcount; |
| bfd_vma offset; |
| } plt; |
| }; |
| |
| struct ppc64_elf_obj_tdata |
| { |
| struct elf_obj_tdata elf; |
| |
| /* Shortcuts to dynamic linker sections. */ |
| asection *got; |
| asection *relgot; |
| |
| /* Used during garbage collection. We attach global symbols defined |
| on removed .opd entries to this section so that the sym is removed. */ |
| asection *deleted_section; |
| |
| /* TLS local dynamic got entry handling. Support for multiple GOT |
| sections means we potentially need one of these for each input bfd. */ |
| struct got_entry tlsld_got; |
| |
| union { |
| /* A copy of relocs before they are modified for --emit-relocs. */ |
|