| /* PowerPC64-specific support for 64-bit ELF. |
| Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, |
| 2009, 2010, 2011, 2012 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 bfd_elf64_powerpcle_vec |
| #define TARGET_LITTLE_NAME "elf64-powerpcle" |
| #define TARGET_BIG_SYM bfd_elf64_powerpc_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 0x1000 |
| #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 _bfd_generic_verify_endian_match |
| #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_bfd_link_hash_table_free ppc64_elf_link_hash_table_free |
| #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_process_dot_syms |
| #define elf_backend_as_needed_cleanup ppc64_elf_as_needed_cleanup |
| #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_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_post_process_headers _bfd_elf_set_osabi |
| |
| /* 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 24 |
| |
| /* The initial size of the plt reserved for the dynamic linker. */ |
| #define PLT_INITIAL_ENTRY_SIZE PLT_ENTRY_SIZE |
| |
| /* TOC base pointers offset from start of TOC. */ |
| #define TOC_BASE_OFF 0x8000 |
| |
| /* 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 r12. */ |
| #define PLT_CALL_STUB_SIZE (7*4) |
| #define ADDIS_R12_R2 0x3d820000 /* addis %r12,%r2,xxx@ha */ |
| #define STD_R2_40R1 0xf8410028 /* std %r2,40(%r1) */ |
| #define LD_R11_0R12 0xe96c0000 /* ld %r11,xxx+0@l(%r12) */ |
| #define MTCTR_R11 0x7d6903a6 /* mtctr %r11 */ |
| #define LD_R2_0R12 0xe84c0000 /* ld %r2,xxx+8@l(%r12) */ |
| /* ld %r11,xxx+16@l(%r12) */ |
| #define BCTR 0x4e800420 /* bctr */ |
| |
| |
| #define ADDIS_R12_R12 0x3d8c0000 /* addis %r12,%r12,off@ha */ |
| #define ADDI_R12_R12 0x398c0000 /* addi %r12,%r12,off@l */ |
| #define ADDIS_R2_R2 0x3c420000 /* addis %r2,%r2,off@ha */ |
| #define ADDI_R2_R2 0x38420000 /* addi %r2,%r2,off@l */ |
| |
| #define XOR_R11_R11_R11 0x7d6b5a78 /* xor %r11,%r11,%r11 */ |
| #define ADD_R12_R12_R11 0x7d8c5a14 /* add %r12,%r12,%r11 */ |
| #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_R11_0R2 0xe9620000 /* ld %r11,xxx+0(%r2) */ |
| #define LD_R2_0R2 0xe8420000 /* ld %r2,xxx+0(%r2) */ |
| |
| #define LD_R2_40R1 0xe8410028 /* ld %r2,40(%r1) */ |
| |
| /* 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 */ |
| #define LD_R2_M16R11 0xe84bfff0 /* ld %2,(0b-1b)(%11) */ |
| #define MTLR_R12 0x7d8803a6 /* mtlr %12 */ |
| #define ADD_R12_R2_R11 0x7d825a14 /* add %12,%2,%11 */ |
| /* ld %11,0(%12) */ |
| /* ld %2,8(%12) */ |
| /* mtctr %11 */ |
| /* ld %11,16(%12) */ |
| /* bctr */ |
| |
| /* 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 |
| |
| #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 */ |
| 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_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_dont, /* 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_dont, /* 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_bitfield, /* 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_bitfield, /* 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_bitfield, /* 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_dont,/* 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_dont,/* 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 */ |
| /* FIXME: Verify. Was complain_overflow_bitfield. */ |
| 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_dont, /* 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_dont, /* 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_bitfield, /* 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_dont, /* 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_dont, /* 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_dont, /* 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_dont, /* 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_bitfield, /* 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_dont, /* 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_dont,/* 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_bitfield, /* 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_bitfield, /* 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_dont, /* 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_dont, /* 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_dont, /* 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_dont, /* 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_dont, /* 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_dont, /* 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_dont, /* 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_dont, /* 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_dont, /* 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_dont, /* 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_dont, /* 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_dont, /* 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_bitfield, /* 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_dont, /* 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_dont, /* 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 */ |
| |
| /* 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 < sizeof (ppc64_elf_howto_raw) / sizeof (ppc64_elf_howto_raw[0]); |
| i++) |
| { |
| type = ppc64_elf_howto_raw[i].type; |
| BFD_ASSERT (type < (sizeof (ppc64_elf_howto_table) |
| / sizeof (ppc64_elf_howto_table[0]))); |
| 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_HI16_S: r = R_PPC64_ADDR16_HA; |
| 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_PPC_TPREL16_HA: r = R_PPC64_TPREL16_HA; |
| 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_PPC_DTPREL16_HA: r = R_PPC64_DTPREL16_HA; |
| 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_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 < sizeof (ppc64_elf_howto_raw) / sizeof (ppc64_elf_howto_raw[0]); |
| 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 >= (sizeof (ppc64_elf_howto_table) |
| / sizeof (ppc64_elf_howto_table[0]))) |
| { |
| (*_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) |
| { |
| /* 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; |
| return bfd_reloc_continue; |
| } |
| |
| 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); |
| } |
| 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_toc (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_toc (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_toc (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; |
| |
| /* A copy of relocs before they are modified for --emit-relocs. */ |
| Elf_Internal_Rela *opd_relocs; |
| |
| /* Nonzero if this bfd has small toc/got relocs, ie. that expect |
| the reloc to be in the range -32768 to 32767. */ |
| unsigned int has_small_toc_reloc : 1; |
| |
| /* Set if toc/got ha relocs detected not using r2, or lo reloc |
| instruction not one we handle. */ |
| unsigned int unexpected_toc_insn : 1; |
| }; |
| |
| #define ppc64_elf_tdata(bfd) \ |
| ((struct ppc64_elf_obj_tdata *) (bfd)->tdata.any) |
| |
| #define ppc64_tlsld_got(bfd) \ |
| (&ppc64_elf_tdata (bfd)->tlsld_got) |
| |
| #define is_ppc64_elf(bfd) \ |
| (bfd_get_flavour (bfd) == bfd_target_elf_flavour \ |
| && elf_object_id (bfd) == PPC64_ELF_DATA) |
| |
| /* Override the generic function because we store some extras. */ |
| |
| static bfd_boolean |
| ppc64_elf_mkobject (bfd *abfd) |
| { |
| return bfd_elf_allocate_object (abfd, sizeof (struct ppc64_elf_obj_tdata), |
| PPC64_ELF_DATA); |
| } |
| |
| /* Fix bad default arch selected for a 64 bit input bfd when the |
| default is 32 bit. */ |
| |
| static bfd_boolean |
| ppc64_elf_object_p (bfd *abfd) |
| { |
| if (abfd->arch_info->the_default && abfd->arch_info->bits_per_word == 32) |
| { |
| Elf_Internal_Ehdr *i_ehdr = elf_elfheader (abfd); |
| |
| if (i_ehdr->e_ident[EI_CLASS] == ELFCLASS64) |
| { |
| /* Relies on arch after 32 bit default being 64 bit default. */ |
| abfd->arch_info = abfd->arch_info->next; |
| BFD_ASSERT (abfd->arch_info->bits_per_word == 64); |
| } |
| } |
| return TRUE; |
| } |
| |
| /* Support for core dump NOTE sections. */ |
| |
| static bfd_boolean |
| ppc64_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) |
| { |
| size_t offset, size; |
| |
| if (note->descsz != 504) |
| return FALSE; |
| |
| /* pr_cursig */ |
| elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12); |
| |
| /* pr_pid */ |
| elf_tdata (abfd)->core_lwpid = bfd_get_32 (abfd, note->descdata + 32); |
| |
| /* pr_reg */ |
| offset = 112; |
| size = 384; |
| |
| /* Make a ".reg/999" section. */ |
| return _bfd_elfcore_make_pseudosection (abfd, ".reg", |
| size, note->descpos + offset); |
| } |
| |
| static bfd_boolean |
| ppc64_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) |
| { |
| if (note->descsz != 136) |
| return FALSE; |
| |
| elf_tdata (abfd)->core_pid |
| = bfd_get_32 (abfd, note->descdata + 24); |
| elf_tdata (abfd)->core_program |
| = _bfd_elfcore_strndup (abfd, note->descdata + 40, 16); |
| elf_tdata (abfd)->core_command |
| = _bfd_elfcore_strndup (abfd, note->descdata + 56, 80); |
| |
| return TRUE; |
| } |
| |
| static char * |
| ppc64_elf_write_core_note (bfd *abfd, char *buf, int *bufsiz, int note_type, |
| ...) |
| { |
| switch (note_type) |
| { |
| default: |
| return NULL; |
| |
| case NT_PRPSINFO: |
| { |
| char data[136]; |
| va_list ap; |
| |
| va_start (ap, note_type); |
| memset (data, 0, sizeof (data)); |
| strncpy (data + 40, va_arg (ap, const char *), 16); |
| strncpy (data + 56, va_arg (ap, const char *), 80); |
| va_end (ap); |
| return elfcore_write_note (abfd, buf, bufsiz, |
| "CORE", note_type, data, sizeof (data)); |
| } |
| |
| case NT_PRSTATUS: |
| { |
| char data[504]; |
| va_list ap; |
| long pid; |
| int cursig; |
| const void *greg; |
| |
| va_start (ap, note_type); |
| memset (data, 0, 112); |
| pid = va_arg (ap, long); |
| bfd_put_32 (abfd, pid, data + 32); |
| cursig = va_arg (ap, int); |
| bfd_put_16 (abfd, cursig, data + 12); |
| greg = va_arg (ap, const void *); |
| memcpy (data + 112, greg, 384); |
| memset (data + 496, 0, 8); |
| va_end (ap); |
| return elfcore_write_note (abfd, buf, bufsiz, |
| "CORE", note_type, data, sizeof (data)); |
| } |
| } |
| } |
| |
| /* Add extra PPC sections. */ |
| |
| static const struct bfd_elf_special_section ppc64_elf_special_sections[]= |
| { |
| { STRING_COMMA_LEN (".plt"), 0, SHT_NOBITS, 0 }, |
| { STRING_COMMA_LEN (".sbss"), -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE }, |
| { STRING_COMMA_LEN (".sdata"), -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE }, |
| { STRING_COMMA_LEN (".toc"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE }, |
| { STRING_COMMA_LEN (".toc1"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE }, |
| { STRING_COMMA_LEN (".tocbss"), 0, SHT_NOBITS, SHF_ALLOC + SHF_WRITE }, |
| { NULL, 0, 0, 0, 0 } |
| }; |
| |
| enum _ppc64_sec_type { |
| sec_normal = 0, |
| sec_opd = 1, |
| sec_toc = 2 |
| }; |
| |
| struct _ppc64_elf_section_data |
| { |
| struct bfd_elf_section_data elf; |
| |
| union |
| { |
| /* An array with one entry for each opd function descriptor. */ |
| struct _opd_sec_data |
| { |
| /* Points to the function code section for local opd entries. */ |
| asection **func_sec; |
| |
| /* After editing .opd, adjust references to opd local syms. */ |
| long *adjust; |
| } opd; |
| |
| /* An array for toc sections, indexed by offset/8. */ |
| struct _toc_sec_data |
| { |
| /* Specifies the relocation symbol index used at a given toc offset. */ |
| unsigned *symndx; |
| |
| /* And the relocation addend. */ |
| bfd_vma *add; |
| } toc; |
| } u; |
| |
| enum _ppc64_sec_type sec_type:2; |
| |
| /* Flag set when small branches are detected. Used to |
| select suitable defaults for the stub group size. */ |
| unsigned int has_14bit_branch:1; |
| }; |
| |
| #define ppc64_elf_section_data(sec) \ |
| ((struct _ppc64_elf_section_data *) elf_section_data (sec)) |
| |
| static bfd_boolean |
| ppc64_elf_new_section_hook (bfd *abfd, asection *sec) |
| { |
| if (!sec->used_by_bfd) |
| { |
| struct _ppc64_elf_section_data *sdata; |
| bfd_size_type amt = sizeof (*sdata); |
| |
| sdata = bfd_zalloc (abfd, amt); |
| if (sdata == NULL) |
| return FALSE; |
| sec->used_by_bfd = sdata; |
| } |
| |
| return _bfd_elf_new_section_hook (abfd, sec); |
| } |
| |
| static struct _opd_sec_data * |
| get_opd_info (asection * sec) |
| { |
| if (sec != NULL |
| && ppc64_elf_section_data (sec) != NULL |
| && ppc64_elf_section_data (sec)->sec_type == sec_opd) |
| return &ppc64_elf_section_data (sec)->u.opd; |
| return NULL; |
| } |
| |
| /* Parameters for the qsort hook. */ |
| static bfd_boolean synthetic_relocatable; |
| |
| /* qsort comparison function for ppc64_elf_get_synthetic_symtab. */ |
| |
| static int |
| compare_symbols (const void *ap, const void *bp) |
| { |
| const asymbol *a = * (const asymbol **) ap; |
| const asymbol *b = * (const asymbol **) bp; |
| |
| /* Section symbols first. */ |
| if ((a->flags & BSF_SECTION_SYM) && !(b->flags & BSF_SECTION_SYM)) |
| return -1; |
| if (!(a->flags & BSF_SECTION_SYM) && (b->flags & BSF_SECTION_SYM)) |
| return 1; |
| |
| /* then .opd symbols. */ |
| if (strcmp (a->section->name, ".opd") == 0 |
|