elf32-ppc.c revision 77298
160484Sobrien/* PowerPC-specific support for 32-bit ELF 260484Sobrien Copyright 1994, 95, 96, 97, 98, 1999 Free Software Foundation, Inc. 360484Sobrien Written by Ian Lance Taylor, Cygnus Support. 460484Sobrien 560484SobrienThis file is part of BFD, the Binary File Descriptor library. 660484Sobrien 760484SobrienThis program is free software; you can redistribute it and/or modify 860484Sobrienit under the terms of the GNU General Public License as published by 960484Sobrienthe Free Software Foundation; either version 2 of the License, or 1060484Sobrien(at your option) any later version. 1160484Sobrien 1260484SobrienThis program is distributed in the hope that it will be useful, 1360484Sobrienbut WITHOUT ANY WARRANTY; without even the implied warranty of 1460484SobrienMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1560484SobrienGNU General Public License for more details. 1660484Sobrien 1760484SobrienYou should have received a copy of the GNU General Public License 1860484Sobrienalong with this program; if not, write to the Free Software 1960484SobrienFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 2060484Sobrien 2160484Sobrien/* This file is based on a preliminary PowerPC ELF ABI. The 2260484Sobrien information may not match the final PowerPC ELF ABI. It includes 2360484Sobrien suggestions from the in-progress Embedded PowerPC ABI, and that 2460484Sobrien information may also not match. */ 2560484Sobrien 2660484Sobrien#include "bfd.h" 2760484Sobrien#include "sysdep.h" 2860484Sobrien#include "bfdlink.h" 2960484Sobrien#include "libbfd.h" 3060484Sobrien#include "elf-bfd.h" 3160484Sobrien#include "elf/ppc.h" 3260484Sobrien 3360484Sobrien#define USE_RELA /* we want RELA relocations, not REL */ 3460484Sobrien 3560484Sobrienstatic reloc_howto_type *ppc_elf_reloc_type_lookup 3660484Sobrien PARAMS ((bfd *abfd, bfd_reloc_code_real_type code)); 3760484Sobrienstatic void ppc_elf_info_to_howto 3860484Sobrien PARAMS ((bfd *abfd, arelent *cache_ptr, Elf32_Internal_Rela *dst)); 3960484Sobrienstatic void ppc_elf_howto_init PARAMS ((void)); 4060484Sobrienstatic bfd_reloc_status_type ppc_elf_addr16_ha_reloc 4160484Sobrien PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); 4260484Sobrienstatic boolean ppc_elf_set_private_flags PARAMS ((bfd *, flagword)); 4360484Sobrienstatic boolean ppc_elf_copy_private_bfd_data PARAMS ((bfd *, bfd *)); 4460484Sobrienstatic boolean ppc_elf_merge_private_bfd_data PARAMS ((bfd *, bfd *)); 4560484Sobrien 4660484Sobrienstatic int ppc_elf_additional_program_headers PARAMS ((bfd *)); 4760484Sobrienstatic boolean ppc_elf_modify_segment_map PARAMS ((bfd *)); 4860484Sobrien 4960484Sobrienstatic boolean ppc_elf_create_dynamic_sections 5060484Sobrien PARAMS ((bfd *, struct bfd_link_info *)); 5160484Sobrien 5260484Sobrienstatic boolean ppc_elf_section_from_shdr PARAMS ((bfd *, 5360484Sobrien Elf32_Internal_Shdr *, 5460484Sobrien char *)); 5560484Sobrienstatic boolean ppc_elf_fake_sections 5660484Sobrien PARAMS ((bfd *, Elf32_Internal_Shdr *, asection *)); 5760484Sobrien 5860484Sobrienstatic elf_linker_section_t *ppc_elf_create_linker_section 5960484Sobrien PARAMS ((bfd *abfd, 6060484Sobrien struct bfd_link_info *info, 6160484Sobrien enum elf_linker_section_enum)); 6260484Sobrien 6360484Sobrienstatic boolean ppc_elf_check_relocs PARAMS ((bfd *, 6460484Sobrien struct bfd_link_info *, 6560484Sobrien asection *, 6660484Sobrien const Elf_Internal_Rela *)); 6760484Sobrien 6860484Sobrienstatic asection * ppc_elf_gc_mark_hook PARAMS ((bfd *abfd, 6960484Sobrien struct bfd_link_info *info, 7060484Sobrien Elf_Internal_Rela *rel, 7160484Sobrien struct elf_link_hash_entry *h, 7260484Sobrien Elf_Internal_Sym *sym)); 7360484Sobrien 7460484Sobrienstatic boolean ppc_elf_gc_sweep_hook PARAMS ((bfd *abfd, 7560484Sobrien struct bfd_link_info *info, 7660484Sobrien asection *sec, 7760484Sobrien const Elf_Internal_Rela *relocs)); 7860484Sobrien 7960484Sobrienstatic boolean ppc_elf_adjust_dynamic_symbol PARAMS ((struct bfd_link_info *, 8060484Sobrien struct elf_link_hash_entry *)); 8160484Sobrien 8260484Sobrienstatic boolean ppc_elf_size_dynamic_sections PARAMS ((bfd *, struct bfd_link_info *)); 8360484Sobrien 8460484Sobrienstatic boolean ppc_elf_relocate_section PARAMS ((bfd *, 8560484Sobrien struct bfd_link_info *info, 8660484Sobrien bfd *, 8760484Sobrien asection *, 8860484Sobrien bfd_byte *, 8960484Sobrien Elf_Internal_Rela *relocs, 9060484Sobrien Elf_Internal_Sym *local_syms, 9160484Sobrien asection **)); 9260484Sobrien 9360484Sobrienstatic boolean ppc_elf_add_symbol_hook PARAMS ((bfd *, 9460484Sobrien struct bfd_link_info *, 9560484Sobrien const Elf_Internal_Sym *, 9660484Sobrien const char **, 9760484Sobrien flagword *, 9860484Sobrien asection **, 9960484Sobrien bfd_vma *)); 10060484Sobrien 10160484Sobrienstatic boolean ppc_elf_finish_dynamic_symbol PARAMS ((bfd *, 10260484Sobrien struct bfd_link_info *, 10360484Sobrien struct elf_link_hash_entry *, 10460484Sobrien Elf_Internal_Sym *)); 10560484Sobrien 10660484Sobrienstatic boolean ppc_elf_finish_dynamic_sections PARAMS ((bfd *, struct bfd_link_info *)); 10760484Sobrien 10860484Sobrien#define BRANCH_PREDICT_BIT 0x200000 /* branch prediction bit for branch taken relocs */ 10960484Sobrien#define RA_REGISTER_MASK 0x001f0000 /* mask to set RA in memory instructions */ 11060484Sobrien#define RA_REGISTER_SHIFT 16 /* value to shift register by to insert RA */ 11160484Sobrien 11260484Sobrien/* The name of the dynamic interpreter. This is put in the .interp 11360484Sobrien section. */ 11460484Sobrien 11560484Sobrien#define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1" 11660484Sobrien 11760484Sobrien/* The size in bytes of an entry in the procedure linkage table. */ 11860484Sobrien#define PLT_ENTRY_SIZE 12 11960484Sobrien/* The initial size of the plt reserved for the dynamic linker. */ 12060484Sobrien#define PLT_INITIAL_ENTRY_SIZE 72 12160484Sobrien/* The size of the gap between entries in the PLT. */ 12260484Sobrien#define PLT_SLOT_SIZE 8 12360484Sobrien/* The number of single-slot PLT entries (the rest use two slots). */ 12460484Sobrien#define PLT_NUM_SINGLE_ENTRIES 8192 12560484Sobrien 12677298Sobrien/* Will references to this symbol always reference the symbol 12777298Sobrien in this object? */ 12877298Sobrien#define SYMBOL_REFERENCES_LOCAL(INFO, H) \ 12977298Sobrien ((! INFO->shared \ 13077298Sobrien || INFO->symbolic \ 13177298Sobrien || H->dynindx == -1 \ 13277298Sobrien || ELF_ST_VISIBILITY (H->other) == STV_INTERNAL \ 13377298Sobrien || ELF_ST_VISIBILITY (H->other) == STV_HIDDEN) \ 13477298Sobrien && (H->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0) 13577298Sobrien 13677298Sobrien/* Will _calls_ to this symbol always call the version in this object? */ 13777298Sobrien#define SYMBOL_CALLS_LOCAL(INFO, H) \ 13877298Sobrien ((! INFO->shared \ 13977298Sobrien || INFO->symbolic \ 14077298Sobrien || H->dynindx == -1 \ 14177298Sobrien || ELF_ST_VISIBILITY (H->other) != STV_DEFAULT) \ 14277298Sobrien && (H->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0) 14360484Sobrien 14477298Sobrienstatic reloc_howto_type *ppc_elf_howto_table[(int) R_PPC_max]; 14560484Sobrien 14677298Sobrienstatic reloc_howto_type ppc_elf_howto_raw[] = { 14760484Sobrien /* This reloc does nothing. */ 14860484Sobrien HOWTO (R_PPC_NONE, /* type */ 14960484Sobrien 0, /* rightshift */ 15060484Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 15160484Sobrien 32, /* bitsize */ 15260484Sobrien false, /* pc_relative */ 15360484Sobrien 0, /* bitpos */ 15460484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 15560484Sobrien bfd_elf_generic_reloc, /* special_function */ 15660484Sobrien "R_PPC_NONE", /* name */ 15760484Sobrien false, /* partial_inplace */ 15860484Sobrien 0, /* src_mask */ 15960484Sobrien 0, /* dst_mask */ 16060484Sobrien false), /* pcrel_offset */ 16160484Sobrien 16260484Sobrien /* A standard 32 bit relocation. */ 16360484Sobrien HOWTO (R_PPC_ADDR32, /* type */ 16460484Sobrien 0, /* rightshift */ 16560484Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 16660484Sobrien 32, /* bitsize */ 16760484Sobrien false, /* pc_relative */ 16860484Sobrien 0, /* bitpos */ 16960484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 17060484Sobrien bfd_elf_generic_reloc, /* special_function */ 17160484Sobrien "R_PPC_ADDR32", /* name */ 17260484Sobrien false, /* partial_inplace */ 17360484Sobrien 0, /* src_mask */ 17460484Sobrien 0xffffffff, /* dst_mask */ 17560484Sobrien false), /* pcrel_offset */ 17660484Sobrien 17760484Sobrien /* An absolute 26 bit branch; the lower two bits must be zero. 17860484Sobrien FIXME: we don't check that, we just clear them. */ 17960484Sobrien HOWTO (R_PPC_ADDR24, /* type */ 18060484Sobrien 0, /* rightshift */ 18160484Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 18260484Sobrien 26, /* bitsize */ 18360484Sobrien false, /* pc_relative */ 18460484Sobrien 0, /* bitpos */ 18560484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 18660484Sobrien bfd_elf_generic_reloc, /* special_function */ 18760484Sobrien "R_PPC_ADDR24", /* name */ 18860484Sobrien false, /* partial_inplace */ 18960484Sobrien 0, /* src_mask */ 19060484Sobrien 0x3fffffc, /* dst_mask */ 19160484Sobrien false), /* pcrel_offset */ 19260484Sobrien 19360484Sobrien /* A standard 16 bit relocation. */ 19460484Sobrien HOWTO (R_PPC_ADDR16, /* type */ 19560484Sobrien 0, /* rightshift */ 19660484Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 19760484Sobrien 16, /* bitsize */ 19860484Sobrien false, /* pc_relative */ 19960484Sobrien 0, /* bitpos */ 20060484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 20160484Sobrien bfd_elf_generic_reloc, /* special_function */ 20260484Sobrien "R_PPC_ADDR16", /* name */ 20360484Sobrien false, /* partial_inplace */ 20460484Sobrien 0, /* src_mask */ 20560484Sobrien 0xffff, /* dst_mask */ 20660484Sobrien false), /* pcrel_offset */ 20760484Sobrien 20860484Sobrien /* A 16 bit relocation without overflow. */ 20960484Sobrien HOWTO (R_PPC_ADDR16_LO, /* type */ 21060484Sobrien 0, /* rightshift */ 21160484Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 21260484Sobrien 16, /* bitsize */ 21360484Sobrien false, /* pc_relative */ 21460484Sobrien 0, /* bitpos */ 21560484Sobrien complain_overflow_dont,/* complain_on_overflow */ 21660484Sobrien bfd_elf_generic_reloc, /* special_function */ 21760484Sobrien "R_PPC_ADDR16_LO", /* name */ 21860484Sobrien false, /* partial_inplace */ 21960484Sobrien 0, /* src_mask */ 22060484Sobrien 0xffff, /* dst_mask */ 22160484Sobrien false), /* pcrel_offset */ 22260484Sobrien 22360484Sobrien /* The high order 16 bits of an address. */ 22460484Sobrien HOWTO (R_PPC_ADDR16_HI, /* type */ 22560484Sobrien 16, /* rightshift */ 22660484Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 22760484Sobrien 16, /* bitsize */ 22860484Sobrien false, /* pc_relative */ 22960484Sobrien 0, /* bitpos */ 23060484Sobrien complain_overflow_dont, /* complain_on_overflow */ 23160484Sobrien bfd_elf_generic_reloc, /* special_function */ 23260484Sobrien "R_PPC_ADDR16_HI", /* name */ 23360484Sobrien false, /* partial_inplace */ 23460484Sobrien 0, /* src_mask */ 23560484Sobrien 0xffff, /* dst_mask */ 23660484Sobrien false), /* pcrel_offset */ 23760484Sobrien 23860484Sobrien /* The high order 16 bits of an address, plus 1 if the contents of 23977298Sobrien the low 16 bits, treated as a signed number, is negative. */ 24060484Sobrien HOWTO (R_PPC_ADDR16_HA, /* type */ 24160484Sobrien 16, /* rightshift */ 24260484Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 24360484Sobrien 16, /* bitsize */ 24460484Sobrien false, /* pc_relative */ 24560484Sobrien 0, /* bitpos */ 24660484Sobrien complain_overflow_dont, /* complain_on_overflow */ 24760484Sobrien ppc_elf_addr16_ha_reloc, /* special_function */ 24860484Sobrien "R_PPC_ADDR16_HA", /* name */ 24960484Sobrien false, /* partial_inplace */ 25060484Sobrien 0, /* src_mask */ 25160484Sobrien 0xffff, /* dst_mask */ 25260484Sobrien false), /* pcrel_offset */ 25360484Sobrien 25460484Sobrien /* An absolute 16 bit branch; the lower two bits must be zero. 25560484Sobrien FIXME: we don't check that, we just clear them. */ 25660484Sobrien HOWTO (R_PPC_ADDR14, /* type */ 25760484Sobrien 0, /* rightshift */ 25860484Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 25960484Sobrien 16, /* bitsize */ 26060484Sobrien false, /* pc_relative */ 26160484Sobrien 0, /* bitpos */ 26260484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 26360484Sobrien bfd_elf_generic_reloc, /* special_function */ 26460484Sobrien "R_PPC_ADDR14", /* name */ 26560484Sobrien false, /* partial_inplace */ 26660484Sobrien 0, /* src_mask */ 26760484Sobrien 0xfffc, /* dst_mask */ 26860484Sobrien false), /* pcrel_offset */ 26960484Sobrien 27060484Sobrien /* An absolute 16 bit branch, for which bit 10 should be set to 27160484Sobrien indicate that the branch is expected to be taken. The lower two 27277298Sobrien bits must be zero. */ 27360484Sobrien HOWTO (R_PPC_ADDR14_BRTAKEN, /* type */ 27460484Sobrien 0, /* rightshift */ 27560484Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 27660484Sobrien 16, /* bitsize */ 27760484Sobrien false, /* pc_relative */ 27860484Sobrien 0, /* bitpos */ 27960484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 28060484Sobrien bfd_elf_generic_reloc, /* special_function */ 28160484Sobrien "R_PPC_ADDR14_BRTAKEN",/* name */ 28260484Sobrien false, /* partial_inplace */ 28360484Sobrien 0, /* src_mask */ 28460484Sobrien 0xfffc, /* dst_mask */ 28560484Sobrien false), /* pcrel_offset */ 28660484Sobrien 28760484Sobrien /* An absolute 16 bit branch, for which bit 10 should be set to 28860484Sobrien indicate that the branch is not expected to be taken. The lower 28960484Sobrien two bits must be zero. */ 29060484Sobrien HOWTO (R_PPC_ADDR14_BRNTAKEN, /* type */ 29160484Sobrien 0, /* rightshift */ 29260484Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 29360484Sobrien 16, /* bitsize */ 29460484Sobrien false, /* pc_relative */ 29560484Sobrien 0, /* bitpos */ 29660484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 29760484Sobrien bfd_elf_generic_reloc, /* special_function */ 29860484Sobrien "R_PPC_ADDR14_BRNTAKEN",/* name */ 29960484Sobrien false, /* partial_inplace */ 30060484Sobrien 0, /* src_mask */ 30160484Sobrien 0xfffc, /* dst_mask */ 30260484Sobrien false), /* pcrel_offset */ 30360484Sobrien 30477298Sobrien /* A relative 26 bit branch; the lower two bits must be zero. */ 30560484Sobrien HOWTO (R_PPC_REL24, /* type */ 30660484Sobrien 0, /* rightshift */ 30760484Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 30860484Sobrien 26, /* bitsize */ 30960484Sobrien true, /* pc_relative */ 31060484Sobrien 0, /* bitpos */ 31160484Sobrien complain_overflow_signed, /* complain_on_overflow */ 31260484Sobrien bfd_elf_generic_reloc, /* special_function */ 31360484Sobrien "R_PPC_REL24", /* name */ 31460484Sobrien false, /* partial_inplace */ 31560484Sobrien 0, /* src_mask */ 31660484Sobrien 0x3fffffc, /* dst_mask */ 31760484Sobrien true), /* pcrel_offset */ 31860484Sobrien 31977298Sobrien /* A relative 16 bit branch; the lower two bits must be zero. */ 32060484Sobrien HOWTO (R_PPC_REL14, /* type */ 32160484Sobrien 0, /* rightshift */ 32260484Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 32360484Sobrien 16, /* bitsize */ 32460484Sobrien true, /* pc_relative */ 32560484Sobrien 0, /* bitpos */ 32660484Sobrien complain_overflow_signed, /* complain_on_overflow */ 32760484Sobrien bfd_elf_generic_reloc, /* special_function */ 32860484Sobrien "R_PPC_REL14", /* name */ 32960484Sobrien false, /* partial_inplace */ 33060484Sobrien 0, /* src_mask */ 33160484Sobrien 0xfffc, /* dst_mask */ 33260484Sobrien true), /* pcrel_offset */ 33360484Sobrien 33477298Sobrien /* A relative 16 bit branch. Bit 10 should be set to indicate that 33560484Sobrien the branch is expected to be taken. The lower two bits must be 33660484Sobrien zero. */ 33760484Sobrien HOWTO (R_PPC_REL14_BRTAKEN, /* type */ 33860484Sobrien 0, /* rightshift */ 33960484Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 34060484Sobrien 16, /* bitsize */ 34160484Sobrien true, /* pc_relative */ 34260484Sobrien 0, /* bitpos */ 34360484Sobrien complain_overflow_signed, /* complain_on_overflow */ 34460484Sobrien bfd_elf_generic_reloc, /* special_function */ 34560484Sobrien "R_PPC_REL14_BRTAKEN", /* name */ 34660484Sobrien false, /* partial_inplace */ 34760484Sobrien 0, /* src_mask */ 34860484Sobrien 0xfffc, /* dst_mask */ 34960484Sobrien true), /* pcrel_offset */ 35060484Sobrien 35177298Sobrien /* A relative 16 bit branch. Bit 10 should be set to indicate that 35260484Sobrien the branch is not expected to be taken. The lower two bits must 35360484Sobrien be zero. */ 35460484Sobrien HOWTO (R_PPC_REL14_BRNTAKEN, /* type */ 35560484Sobrien 0, /* rightshift */ 35660484Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 35760484Sobrien 16, /* bitsize */ 35860484Sobrien true, /* pc_relative */ 35960484Sobrien 0, /* bitpos */ 36060484Sobrien complain_overflow_signed, /* complain_on_overflow */ 36160484Sobrien bfd_elf_generic_reloc, /* special_function */ 36260484Sobrien "R_PPC_REL14_BRNTAKEN",/* name */ 36360484Sobrien false, /* partial_inplace */ 36460484Sobrien 0, /* src_mask */ 36560484Sobrien 0xfffc, /* dst_mask */ 36660484Sobrien true), /* pcrel_offset */ 36760484Sobrien 36860484Sobrien /* Like R_PPC_ADDR16, but referring to the GOT table entry for the 36960484Sobrien symbol. */ 37060484Sobrien HOWTO (R_PPC_GOT16, /* type */ 37160484Sobrien 0, /* rightshift */ 37260484Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 37360484Sobrien 16, /* bitsize */ 37460484Sobrien false, /* pc_relative */ 37560484Sobrien 0, /* bitpos */ 37660484Sobrien complain_overflow_signed, /* complain_on_overflow */ 37760484Sobrien bfd_elf_generic_reloc, /* special_function */ 37860484Sobrien "R_PPC_GOT16", /* name */ 37960484Sobrien false, /* partial_inplace */ 38060484Sobrien 0, /* src_mask */ 38160484Sobrien 0xffff, /* dst_mask */ 38260484Sobrien false), /* pcrel_offset */ 38360484Sobrien 38460484Sobrien /* Like R_PPC_ADDR16_LO, but referring to the GOT table entry for 38560484Sobrien the symbol. */ 38660484Sobrien HOWTO (R_PPC_GOT16_LO, /* type */ 38760484Sobrien 0, /* rightshift */ 38860484Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 38960484Sobrien 16, /* bitsize */ 39060484Sobrien false, /* pc_relative */ 39160484Sobrien 0, /* bitpos */ 39260484Sobrien complain_overflow_dont, /* complain_on_overflow */ 39360484Sobrien bfd_elf_generic_reloc, /* special_function */ 39460484Sobrien "R_PPC_GOT16_LO", /* name */ 39560484Sobrien false, /* partial_inplace */ 39660484Sobrien 0, /* src_mask */ 39760484Sobrien 0xffff, /* dst_mask */ 39860484Sobrien false), /* pcrel_offset */ 39960484Sobrien 40060484Sobrien /* Like R_PPC_ADDR16_HI, but referring to the GOT table entry for 40160484Sobrien the symbol. */ 40260484Sobrien HOWTO (R_PPC_GOT16_HI, /* type */ 40360484Sobrien 16, /* rightshift */ 40460484Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 40560484Sobrien 16, /* bitsize */ 40660484Sobrien false, /* pc_relative */ 40760484Sobrien 0, /* bitpos */ 40860484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 40960484Sobrien bfd_elf_generic_reloc, /* special_function */ 41060484Sobrien "R_PPC_GOT16_HI", /* name */ 41160484Sobrien false, /* partial_inplace */ 41260484Sobrien 0, /* src_mask */ 41360484Sobrien 0xffff, /* dst_mask */ 41460484Sobrien false), /* pcrel_offset */ 41560484Sobrien 41660484Sobrien /* Like R_PPC_ADDR16_HA, but referring to the GOT table entry for 41760484Sobrien the symbol. */ 41860484Sobrien HOWTO (R_PPC_GOT16_HA, /* type */ 41960484Sobrien 16, /* rightshift */ 42060484Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 42160484Sobrien 16, /* bitsize */ 42260484Sobrien false, /* pc_relative */ 42360484Sobrien 0, /* bitpos */ 42460484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 42560484Sobrien ppc_elf_addr16_ha_reloc, /* special_function */ 42660484Sobrien "R_PPC_GOT16_HA", /* name */ 42760484Sobrien false, /* partial_inplace */ 42860484Sobrien 0, /* src_mask */ 42960484Sobrien 0xffff, /* dst_mask */ 43060484Sobrien false), /* pcrel_offset */ 43160484Sobrien 43260484Sobrien /* Like R_PPC_REL24, but referring to the procedure linkage table 43360484Sobrien entry for the symbol. */ 43460484Sobrien HOWTO (R_PPC_PLTREL24, /* type */ 43560484Sobrien 0, /* rightshift */ 43660484Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 43760484Sobrien 26, /* bitsize */ 43860484Sobrien true, /* pc_relative */ 43960484Sobrien 0, /* bitpos */ 44060484Sobrien complain_overflow_signed, /* complain_on_overflow */ 44160484Sobrien bfd_elf_generic_reloc, /* special_function */ 44260484Sobrien "R_PPC_PLTREL24", /* name */ 44360484Sobrien false, /* partial_inplace */ 44460484Sobrien 0, /* src_mask */ 44560484Sobrien 0x3fffffc, /* dst_mask */ 44660484Sobrien true), /* pcrel_offset */ 44760484Sobrien 44860484Sobrien /* This is used only by the dynamic linker. The symbol should exist 44960484Sobrien both in the object being run and in some shared library. The 45060484Sobrien dynamic linker copies the data addressed by the symbol from the 45160484Sobrien shared library into the object, because the object being 45260484Sobrien run has to have the data at some particular address. */ 45360484Sobrien HOWTO (R_PPC_COPY, /* type */ 45460484Sobrien 0, /* rightshift */ 45560484Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 45660484Sobrien 32, /* bitsize */ 45760484Sobrien false, /* pc_relative */ 45860484Sobrien 0, /* bitpos */ 45960484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 46060484Sobrien bfd_elf_generic_reloc, /* special_function */ 46160484Sobrien "R_PPC_COPY", /* name */ 46260484Sobrien false, /* partial_inplace */ 46360484Sobrien 0, /* src_mask */ 46460484Sobrien 0, /* dst_mask */ 46560484Sobrien false), /* pcrel_offset */ 46660484Sobrien 46760484Sobrien /* Like R_PPC_ADDR32, but used when setting global offset table 46860484Sobrien entries. */ 46960484Sobrien HOWTO (R_PPC_GLOB_DAT, /* type */ 47060484Sobrien 0, /* rightshift */ 47160484Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 47260484Sobrien 32, /* bitsize */ 47360484Sobrien false, /* pc_relative */ 47460484Sobrien 0, /* bitpos */ 47560484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 47660484Sobrien bfd_elf_generic_reloc, /* special_function */ 47760484Sobrien "R_PPC_GLOB_DAT", /* name */ 47860484Sobrien false, /* partial_inplace */ 47960484Sobrien 0, /* src_mask */ 48060484Sobrien 0xffffffff, /* dst_mask */ 48160484Sobrien false), /* pcrel_offset */ 48260484Sobrien 48360484Sobrien /* Marks a procedure linkage table entry for a symbol. */ 48460484Sobrien HOWTO (R_PPC_JMP_SLOT, /* type */ 48560484Sobrien 0, /* rightshift */ 48660484Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 48760484Sobrien 32, /* bitsize */ 48860484Sobrien false, /* pc_relative */ 48960484Sobrien 0, /* bitpos */ 49060484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 49160484Sobrien bfd_elf_generic_reloc, /* special_function */ 49260484Sobrien "R_PPC_JMP_SLOT", /* name */ 49360484Sobrien false, /* partial_inplace */ 49460484Sobrien 0, /* src_mask */ 49560484Sobrien 0, /* dst_mask */ 49660484Sobrien false), /* pcrel_offset */ 49760484Sobrien 49860484Sobrien /* Used only by the dynamic linker. When the object is run, this 49960484Sobrien longword is set to the load address of the object, plus the 50060484Sobrien addend. */ 50160484Sobrien HOWTO (R_PPC_RELATIVE, /* type */ 50260484Sobrien 0, /* rightshift */ 50360484Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 50460484Sobrien 32, /* bitsize */ 50560484Sobrien false, /* pc_relative */ 50660484Sobrien 0, /* bitpos */ 50760484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 50860484Sobrien bfd_elf_generic_reloc, /* special_function */ 50960484Sobrien "R_PPC_RELATIVE", /* name */ 51060484Sobrien false, /* partial_inplace */ 51160484Sobrien 0, /* src_mask */ 51260484Sobrien 0xffffffff, /* dst_mask */ 51360484Sobrien false), /* pcrel_offset */ 51460484Sobrien 51560484Sobrien /* Like R_PPC_REL24, but uses the value of the symbol within the 51660484Sobrien object rather than the final value. Normally used for 51760484Sobrien _GLOBAL_OFFSET_TABLE_. */ 51860484Sobrien HOWTO (R_PPC_LOCAL24PC, /* type */ 51960484Sobrien 0, /* rightshift */ 52060484Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 52160484Sobrien 26, /* bitsize */ 52260484Sobrien true, /* pc_relative */ 52360484Sobrien 0, /* bitpos */ 52460484Sobrien complain_overflow_signed, /* complain_on_overflow */ 52560484Sobrien bfd_elf_generic_reloc, /* special_function */ 52660484Sobrien "R_PPC_LOCAL24PC", /* name */ 52760484Sobrien false, /* partial_inplace */ 52860484Sobrien 0, /* src_mask */ 52960484Sobrien 0x3fffffc, /* dst_mask */ 53060484Sobrien true), /* pcrel_offset */ 53160484Sobrien 53260484Sobrien /* Like R_PPC_ADDR32, but may be unaligned. */ 53360484Sobrien HOWTO (R_PPC_UADDR32, /* type */ 53460484Sobrien 0, /* rightshift */ 53560484Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 53660484Sobrien 32, /* bitsize */ 53760484Sobrien false, /* pc_relative */ 53860484Sobrien 0, /* bitpos */ 53960484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 54060484Sobrien bfd_elf_generic_reloc, /* special_function */ 54160484Sobrien "R_PPC_UADDR32", /* name */ 54260484Sobrien false, /* partial_inplace */ 54360484Sobrien 0, /* src_mask */ 54460484Sobrien 0xffffffff, /* dst_mask */ 54560484Sobrien false), /* pcrel_offset */ 54660484Sobrien 54760484Sobrien /* Like R_PPC_ADDR16, but may be unaligned. */ 54860484Sobrien HOWTO (R_PPC_UADDR16, /* type */ 54960484Sobrien 0, /* rightshift */ 55060484Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 55160484Sobrien 16, /* bitsize */ 55260484Sobrien false, /* pc_relative */ 55360484Sobrien 0, /* bitpos */ 55460484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 55560484Sobrien bfd_elf_generic_reloc, /* special_function */ 55660484Sobrien "R_PPC_UADDR16", /* name */ 55760484Sobrien false, /* partial_inplace */ 55860484Sobrien 0, /* src_mask */ 55960484Sobrien 0xffff, /* dst_mask */ 56060484Sobrien false), /* pcrel_offset */ 56160484Sobrien 56260484Sobrien /* 32-bit PC relative */ 56360484Sobrien HOWTO (R_PPC_REL32, /* type */ 56460484Sobrien 0, /* rightshift */ 56560484Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 56660484Sobrien 32, /* bitsize */ 56760484Sobrien true, /* pc_relative */ 56860484Sobrien 0, /* bitpos */ 56960484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 57060484Sobrien bfd_elf_generic_reloc, /* special_function */ 57160484Sobrien "R_PPC_REL32", /* name */ 57260484Sobrien false, /* partial_inplace */ 57360484Sobrien 0, /* src_mask */ 57460484Sobrien 0xffffffff, /* dst_mask */ 57560484Sobrien true), /* pcrel_offset */ 57660484Sobrien 57760484Sobrien /* 32-bit relocation to the symbol's procedure linkage table. 57877298Sobrien FIXME: not supported. */ 57960484Sobrien HOWTO (R_PPC_PLT32, /* type */ 58060484Sobrien 0, /* rightshift */ 58160484Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 58260484Sobrien 32, /* bitsize */ 58360484Sobrien false, /* pc_relative */ 58460484Sobrien 0, /* bitpos */ 58560484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 58660484Sobrien bfd_elf_generic_reloc, /* special_function */ 58760484Sobrien "R_PPC_PLT32", /* name */ 58860484Sobrien false, /* partial_inplace */ 58960484Sobrien 0, /* src_mask */ 59060484Sobrien 0, /* dst_mask */ 59160484Sobrien false), /* pcrel_offset */ 59260484Sobrien 59360484Sobrien /* 32-bit PC relative relocation to the symbol's procedure linkage table. 59477298Sobrien FIXME: not supported. */ 59560484Sobrien HOWTO (R_PPC_PLTREL32, /* type */ 59660484Sobrien 0, /* rightshift */ 59760484Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 59860484Sobrien 32, /* bitsize */ 59960484Sobrien true, /* pc_relative */ 60060484Sobrien 0, /* bitpos */ 60160484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 60260484Sobrien bfd_elf_generic_reloc, /* special_function */ 60360484Sobrien "R_PPC_PLTREL32", /* name */ 60460484Sobrien false, /* partial_inplace */ 60560484Sobrien 0, /* src_mask */ 60660484Sobrien 0, /* dst_mask */ 60760484Sobrien true), /* pcrel_offset */ 60860484Sobrien 60960484Sobrien /* Like R_PPC_ADDR16_LO, but referring to the PLT table entry for 61060484Sobrien the symbol. */ 61160484Sobrien HOWTO (R_PPC_PLT16_LO, /* type */ 61260484Sobrien 0, /* rightshift */ 61360484Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 61460484Sobrien 16, /* bitsize */ 61560484Sobrien false, /* pc_relative */ 61660484Sobrien 0, /* bitpos */ 61760484Sobrien complain_overflow_dont, /* complain_on_overflow */ 61860484Sobrien bfd_elf_generic_reloc, /* special_function */ 61960484Sobrien "R_PPC_PLT16_LO", /* name */ 62060484Sobrien false, /* partial_inplace */ 62160484Sobrien 0, /* src_mask */ 62260484Sobrien 0xffff, /* dst_mask */ 62360484Sobrien false), /* pcrel_offset */ 62460484Sobrien 62560484Sobrien /* Like R_PPC_ADDR16_HI, but referring to the PLT table entry for 62660484Sobrien the symbol. */ 62760484Sobrien HOWTO (R_PPC_PLT16_HI, /* type */ 62860484Sobrien 16, /* rightshift */ 62960484Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 63060484Sobrien 16, /* bitsize */ 63160484Sobrien false, /* pc_relative */ 63260484Sobrien 0, /* bitpos */ 63360484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 63460484Sobrien bfd_elf_generic_reloc, /* special_function */ 63560484Sobrien "R_PPC_PLT16_HI", /* name */ 63660484Sobrien false, /* partial_inplace */ 63760484Sobrien 0, /* src_mask */ 63860484Sobrien 0xffff, /* dst_mask */ 63960484Sobrien false), /* pcrel_offset */ 64060484Sobrien 64160484Sobrien /* Like R_PPC_ADDR16_HA, but referring to the PLT table entry for 64260484Sobrien the symbol. */ 64360484Sobrien HOWTO (R_PPC_PLT16_HA, /* type */ 64460484Sobrien 16, /* rightshift */ 64560484Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 64660484Sobrien 16, /* bitsize */ 64760484Sobrien false, /* pc_relative */ 64860484Sobrien 0, /* bitpos */ 64960484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 65060484Sobrien ppc_elf_addr16_ha_reloc, /* special_function */ 65160484Sobrien "R_PPC_PLT16_HA", /* name */ 65260484Sobrien false, /* partial_inplace */ 65360484Sobrien 0, /* src_mask */ 65460484Sobrien 0xffff, /* dst_mask */ 65560484Sobrien false), /* pcrel_offset */ 65660484Sobrien 65760484Sobrien /* A sign-extended 16 bit value relative to _SDA_BASE_, for use with 65860484Sobrien small data items. */ 65960484Sobrien HOWTO (R_PPC_SDAREL16, /* type */ 66060484Sobrien 0, /* rightshift */ 66160484Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 66260484Sobrien 16, /* bitsize */ 66360484Sobrien false, /* pc_relative */ 66460484Sobrien 0, /* bitpos */ 66560484Sobrien complain_overflow_signed, /* complain_on_overflow */ 66660484Sobrien bfd_elf_generic_reloc, /* special_function */ 66760484Sobrien "R_PPC_SDAREL16", /* name */ 66860484Sobrien false, /* partial_inplace */ 66960484Sobrien 0, /* src_mask */ 67060484Sobrien 0xffff, /* dst_mask */ 67160484Sobrien false), /* pcrel_offset */ 67260484Sobrien 67377298Sobrien /* 32-bit section relative relocation. */ 67460484Sobrien HOWTO (R_PPC_SECTOFF, /* type */ 67560484Sobrien 0, /* rightshift */ 67660484Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 67760484Sobrien 32, /* bitsize */ 67860484Sobrien true, /* pc_relative */ 67960484Sobrien 0, /* bitpos */ 68060484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 68160484Sobrien bfd_elf_generic_reloc, /* special_function */ 68260484Sobrien "R_PPC_SECTOFF", /* name */ 68360484Sobrien false, /* partial_inplace */ 68460484Sobrien 0, /* src_mask */ 68560484Sobrien 0, /* dst_mask */ 68660484Sobrien true), /* pcrel_offset */ 68760484Sobrien 68877298Sobrien /* 16-bit lower half section relative relocation. */ 68960484Sobrien HOWTO (R_PPC_SECTOFF_LO, /* type */ 69060484Sobrien 0, /* rightshift */ 69160484Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 69260484Sobrien 16, /* bitsize */ 69360484Sobrien false, /* pc_relative */ 69460484Sobrien 0, /* bitpos */ 69560484Sobrien complain_overflow_dont, /* complain_on_overflow */ 69660484Sobrien bfd_elf_generic_reloc, /* special_function */ 69760484Sobrien "R_PPC_SECTOFF_LO", /* name */ 69860484Sobrien false, /* partial_inplace */ 69960484Sobrien 0, /* src_mask */ 70060484Sobrien 0xffff, /* dst_mask */ 70160484Sobrien false), /* pcrel_offset */ 70260484Sobrien 70377298Sobrien /* 16-bit upper half section relative relocation. */ 70460484Sobrien HOWTO (R_PPC_SECTOFF_HI, /* type */ 70560484Sobrien 16, /* rightshift */ 70660484Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 70760484Sobrien 16, /* bitsize */ 70860484Sobrien false, /* pc_relative */ 70960484Sobrien 0, /* bitpos */ 71060484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 71160484Sobrien bfd_elf_generic_reloc, /* special_function */ 71260484Sobrien "R_PPC_SECTOFF_HI", /* name */ 71360484Sobrien false, /* partial_inplace */ 71460484Sobrien 0, /* src_mask */ 71560484Sobrien 0xffff, /* dst_mask */ 71660484Sobrien false), /* pcrel_offset */ 71760484Sobrien 71877298Sobrien /* 16-bit upper half adjusted section relative relocation. */ 71960484Sobrien HOWTO (R_PPC_SECTOFF_HA, /* type */ 72060484Sobrien 16, /* rightshift */ 72160484Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 72260484Sobrien 16, /* bitsize */ 72360484Sobrien false, /* pc_relative */ 72460484Sobrien 0, /* bitpos */ 72560484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 72660484Sobrien ppc_elf_addr16_ha_reloc, /* special_function */ 72760484Sobrien "R_PPC_SECTOFF_HA", /* name */ 72860484Sobrien false, /* partial_inplace */ 72960484Sobrien 0, /* src_mask */ 73060484Sobrien 0xffff, /* dst_mask */ 73160484Sobrien false), /* pcrel_offset */ 73260484Sobrien 73360484Sobrien /* The remaining relocs are from the Embedded ELF ABI, and are not 73460484Sobrien in the SVR4 ELF ABI. */ 73560484Sobrien 73660484Sobrien /* 32 bit value resulting from the addend minus the symbol */ 73760484Sobrien HOWTO (R_PPC_EMB_NADDR32, /* type */ 73860484Sobrien 0, /* rightshift */ 73960484Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 74060484Sobrien 32, /* bitsize */ 74160484Sobrien false, /* pc_relative */ 74260484Sobrien 0, /* bitpos */ 74360484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 74460484Sobrien bfd_elf_generic_reloc, /* special_function */ 74560484Sobrien "R_PPC_EMB_NADDR32", /* name */ 74660484Sobrien false, /* partial_inplace */ 74760484Sobrien 0, /* src_mask */ 74860484Sobrien 0xffffffff, /* dst_mask */ 74960484Sobrien false), /* pcrel_offset */ 75060484Sobrien 75160484Sobrien /* 16 bit value resulting from the addend minus the symbol */ 75260484Sobrien HOWTO (R_PPC_EMB_NADDR16, /* type */ 75360484Sobrien 0, /* rightshift */ 75460484Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 75560484Sobrien 16, /* bitsize */ 75660484Sobrien false, /* pc_relative */ 75760484Sobrien 0, /* bitpos */ 75860484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 75960484Sobrien bfd_elf_generic_reloc, /* special_function */ 76060484Sobrien "R_PPC_EMB_NADDR16", /* name */ 76160484Sobrien false, /* partial_inplace */ 76260484Sobrien 0, /* src_mask */ 76360484Sobrien 0xffff, /* dst_mask */ 76460484Sobrien false), /* pcrel_offset */ 76560484Sobrien 76660484Sobrien /* 16 bit value resulting from the addend minus the symbol */ 76760484Sobrien HOWTO (R_PPC_EMB_NADDR16_LO, /* type */ 76860484Sobrien 0, /* rightshift */ 76960484Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 77060484Sobrien 16, /* bitsize */ 77160484Sobrien false, /* pc_relative */ 77260484Sobrien 0, /* bitpos */ 77360484Sobrien complain_overflow_dont,/* complain_on_overflow */ 77460484Sobrien bfd_elf_generic_reloc, /* special_function */ 77560484Sobrien "R_PPC_EMB_ADDR16_LO", /* name */ 77660484Sobrien false, /* partial_inplace */ 77760484Sobrien 0, /* src_mask */ 77860484Sobrien 0xffff, /* dst_mask */ 77960484Sobrien false), /* pcrel_offset */ 78060484Sobrien 78160484Sobrien /* The high order 16 bits of the addend minus the symbol */ 78260484Sobrien HOWTO (R_PPC_EMB_NADDR16_HI, /* type */ 78360484Sobrien 16, /* rightshift */ 78460484Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 78560484Sobrien 16, /* bitsize */ 78660484Sobrien false, /* pc_relative */ 78760484Sobrien 0, /* bitpos */ 78860484Sobrien complain_overflow_dont, /* complain_on_overflow */ 78960484Sobrien bfd_elf_generic_reloc, /* special_function */ 79060484Sobrien "R_PPC_EMB_NADDR16_HI", /* name */ 79160484Sobrien false, /* partial_inplace */ 79260484Sobrien 0, /* src_mask */ 79360484Sobrien 0xffff, /* dst_mask */ 79460484Sobrien false), /* pcrel_offset */ 79560484Sobrien 79660484Sobrien /* The high order 16 bits of the result of the addend minus the address, 79760484Sobrien plus 1 if the contents of the low 16 bits, treated as a signed number, 79860484Sobrien is negative. */ 79960484Sobrien HOWTO (R_PPC_EMB_NADDR16_HA, /* type */ 80060484Sobrien 16, /* rightshift */ 80160484Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 80260484Sobrien 16, /* bitsize */ 80360484Sobrien false, /* pc_relative */ 80460484Sobrien 0, /* bitpos */ 80560484Sobrien complain_overflow_dont, /* complain_on_overflow */ 80660484Sobrien ppc_elf_addr16_ha_reloc, /* special_function */ 80760484Sobrien "R_PPC_EMB_NADDR16_HA", /* name */ 80860484Sobrien false, /* partial_inplace */ 80960484Sobrien 0, /* src_mask */ 81060484Sobrien 0xffff, /* dst_mask */ 81160484Sobrien false), /* pcrel_offset */ 81260484Sobrien 81360484Sobrien /* 16 bit value resulting from allocating a 4 byte word to hold an 81460484Sobrien address in the .sdata section, and returning the offset from 81560484Sobrien _SDA_BASE_ for that relocation */ 81660484Sobrien HOWTO (R_PPC_EMB_SDAI16, /* type */ 81760484Sobrien 0, /* rightshift */ 81860484Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 81960484Sobrien 16, /* bitsize */ 82060484Sobrien false, /* pc_relative */ 82160484Sobrien 0, /* bitpos */ 82260484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 82360484Sobrien bfd_elf_generic_reloc, /* special_function */ 82460484Sobrien "R_PPC_EMB_SDAI16", /* name */ 82560484Sobrien false, /* partial_inplace */ 82660484Sobrien 0, /* src_mask */ 82760484Sobrien 0xffff, /* dst_mask */ 82860484Sobrien false), /* pcrel_offset */ 82960484Sobrien 83060484Sobrien /* 16 bit value resulting from allocating a 4 byte word to hold an 83160484Sobrien address in the .sdata2 section, and returning the offset from 83260484Sobrien _SDA2_BASE_ for that relocation */ 83360484Sobrien HOWTO (R_PPC_EMB_SDA2I16, /* type */ 83460484Sobrien 0, /* rightshift */ 83560484Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 83660484Sobrien 16, /* bitsize */ 83760484Sobrien false, /* pc_relative */ 83860484Sobrien 0, /* bitpos */ 83960484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 84060484Sobrien bfd_elf_generic_reloc, /* special_function */ 84160484Sobrien "R_PPC_EMB_SDA2I16", /* name */ 84260484Sobrien false, /* partial_inplace */ 84360484Sobrien 0, /* src_mask */ 84460484Sobrien 0xffff, /* dst_mask */ 84560484Sobrien false), /* pcrel_offset */ 84660484Sobrien 84760484Sobrien /* A sign-extended 16 bit value relative to _SDA2_BASE_, for use with 84860484Sobrien small data items. */ 84960484Sobrien HOWTO (R_PPC_EMB_SDA2REL, /* type */ 85060484Sobrien 0, /* rightshift */ 85160484Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 85260484Sobrien 16, /* bitsize */ 85360484Sobrien false, /* pc_relative */ 85460484Sobrien 0, /* bitpos */ 85560484Sobrien complain_overflow_signed, /* complain_on_overflow */ 85660484Sobrien bfd_elf_generic_reloc, /* special_function */ 85760484Sobrien "R_PPC_EMB_SDA2REL", /* name */ 85860484Sobrien false, /* partial_inplace */ 85960484Sobrien 0, /* src_mask */ 86060484Sobrien 0xffff, /* dst_mask */ 86160484Sobrien false), /* pcrel_offset */ 86260484Sobrien 86360484Sobrien /* Relocate against either _SDA_BASE_ or _SDA2_BASE_, filling in the 16 bit 86460484Sobrien signed offset from the appropriate base, and filling in the register 86560484Sobrien field with the appropriate register (0, 2, or 13). */ 86660484Sobrien HOWTO (R_PPC_EMB_SDA21, /* type */ 86760484Sobrien 0, /* rightshift */ 86860484Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 86960484Sobrien 16, /* bitsize */ 87060484Sobrien false, /* pc_relative */ 87160484Sobrien 0, /* bitpos */ 87260484Sobrien complain_overflow_signed, /* complain_on_overflow */ 87360484Sobrien bfd_elf_generic_reloc, /* special_function */ 87460484Sobrien "R_PPC_EMB_SDA21", /* name */ 87560484Sobrien false, /* partial_inplace */ 87660484Sobrien 0, /* src_mask */ 87760484Sobrien 0xffff, /* dst_mask */ 87860484Sobrien false), /* pcrel_offset */ 87960484Sobrien 88060484Sobrien /* Relocation not handled: R_PPC_EMB_MRKREF */ 88160484Sobrien /* Relocation not handled: R_PPC_EMB_RELSEC16 */ 88260484Sobrien /* Relocation not handled: R_PPC_EMB_RELST_LO */ 88360484Sobrien /* Relocation not handled: R_PPC_EMB_RELST_HI */ 88460484Sobrien /* Relocation not handled: R_PPC_EMB_RELST_HA */ 88560484Sobrien /* Relocation not handled: R_PPC_EMB_BIT_FLD */ 88660484Sobrien 88760484Sobrien /* PC relative relocation against either _SDA_BASE_ or _SDA2_BASE_, filling 88860484Sobrien in the 16 bit signed offset from the appropriate base, and filling in the 88960484Sobrien register field with the appropriate register (0, 2, or 13). */ 89060484Sobrien HOWTO (R_PPC_EMB_RELSDA, /* type */ 89160484Sobrien 0, /* rightshift */ 89260484Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 89360484Sobrien 16, /* bitsize */ 89460484Sobrien true, /* pc_relative */ 89560484Sobrien 0, /* bitpos */ 89660484Sobrien complain_overflow_signed, /* complain_on_overflow */ 89760484Sobrien bfd_elf_generic_reloc, /* special_function */ 89860484Sobrien "R_PPC_EMB_RELSDA", /* name */ 89960484Sobrien false, /* partial_inplace */ 90060484Sobrien 0, /* src_mask */ 90160484Sobrien 0xffff, /* dst_mask */ 90260484Sobrien false), /* pcrel_offset */ 90360484Sobrien 90460484Sobrien /* GNU extension to record C++ vtable hierarchy */ 90560484Sobrien HOWTO (R_PPC_GNU_VTINHERIT, /* type */ 90660484Sobrien 0, /* rightshift */ 90760484Sobrien 0, /* size (0 = byte, 1 = short, 2 = long) */ 90860484Sobrien 0, /* bitsize */ 90960484Sobrien false, /* pc_relative */ 91060484Sobrien 0, /* bitpos */ 91160484Sobrien complain_overflow_dont, /* complain_on_overflow */ 91260484Sobrien NULL, /* special_function */ 91360484Sobrien "R_PPC_GNU_VTINHERIT", /* name */ 91460484Sobrien false, /* partial_inplace */ 91560484Sobrien 0, /* src_mask */ 91660484Sobrien 0, /* dst_mask */ 91760484Sobrien false), /* pcrel_offset */ 91860484Sobrien 91960484Sobrien /* GNU extension to record C++ vtable member usage */ 92060484Sobrien HOWTO (R_PPC_GNU_VTENTRY, /* type */ 92160484Sobrien 0, /* rightshift */ 92260484Sobrien 0, /* size (0 = byte, 1 = short, 2 = long) */ 92360484Sobrien 0, /* bitsize */ 92460484Sobrien false, /* pc_relative */ 92560484Sobrien 0, /* bitpos */ 92660484Sobrien complain_overflow_dont, /* complain_on_overflow */ 92760484Sobrien NULL, /* special_function */ 92860484Sobrien "R_PPC_GNU_VTENTRY", /* name */ 92960484Sobrien false, /* partial_inplace */ 93060484Sobrien 0, /* src_mask */ 93160484Sobrien 0, /* dst_mask */ 93260484Sobrien false), /* pcrel_offset */ 93360484Sobrien 93460484Sobrien /* Phony reloc to handle AIX style TOC entries */ 93560484Sobrien HOWTO (R_PPC_TOC16, /* type */ 93660484Sobrien 0, /* rightshift */ 93760484Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 93860484Sobrien 16, /* bitsize */ 93960484Sobrien false, /* pc_relative */ 94060484Sobrien 0, /* bitpos */ 94160484Sobrien complain_overflow_signed, /* complain_on_overflow */ 94260484Sobrien bfd_elf_generic_reloc, /* special_function */ 94360484Sobrien "R_PPC_TOC16", /* name */ 94460484Sobrien false, /* partial_inplace */ 94560484Sobrien 0, /* src_mask */ 94660484Sobrien 0xffff, /* dst_mask */ 94760484Sobrien false), /* pcrel_offset */ 94860484Sobrien}; 94960484Sobrien 95060484Sobrien/* Initialize the ppc_elf_howto_table, so that linear accesses can be done. */ 95160484Sobrien 95260484Sobrienstatic void 95360484Sobrienppc_elf_howto_init () 95460484Sobrien{ 95560484Sobrien unsigned int i, type; 95660484Sobrien 95760484Sobrien for (i = 0; i < sizeof (ppc_elf_howto_raw) / sizeof (ppc_elf_howto_raw[0]); i++) 95860484Sobrien { 95960484Sobrien type = ppc_elf_howto_raw[i].type; 96077298Sobrien BFD_ASSERT (type < sizeof (ppc_elf_howto_table) / sizeof (ppc_elf_howto_table[0])); 96160484Sobrien ppc_elf_howto_table[type] = &ppc_elf_howto_raw[i]; 96260484Sobrien } 96360484Sobrien} 96460484Sobrien 96560484Sobrien/* This function handles relaxing for the PPC with option --mpc860c0[=<n>]. 96660484Sobrien 96760484Sobrien The MPC860, revision C0 or earlier contains a bug in the die. 96860484Sobrien If all of the following conditions are true, the next instruction 96960484Sobrien to be executed *may* be treated as a no-op. 97060484Sobrien 1/ A forward branch is executed. 97160484Sobrien 2/ The branch is predicted as not taken. 97260484Sobrien 3/ The branch is taken. 97360484Sobrien 4/ The branch is located in the last 5 words of a page. 97460484Sobrien (The EOP limit is 5 by default but may be specified as any value from 1-10.) 97577298Sobrien 97660484Sobrien Our software solution is to detect these problematic branches in a 97760484Sobrien linker pass and modify them as follows: 97860484Sobrien 1/ Unconditional branches - Since these are always predicted taken, 97960484Sobrien there is no problem and no action is required. 98060484Sobrien 2/ Conditional backward branches - No problem, no action required. 98160484Sobrien 3/ Conditional forward branches - Ensure that the "inverse prediction 98260484Sobrien bit" is set (ensure it is predicted taken). 98360484Sobrien 4/ Conditional register branches - Ensure that the "y bit" is set 98460484Sobrien (ensure it is predicted taken). 98560484Sobrien*/ 98660484Sobrien 98760484Sobrien/* Sort sections by address. */ 98860484Sobrien 98960484Sobrienstatic int 99060484Sobrienppc_elf_sort_rela (arg1, arg2) 99177298Sobrien const void *arg1; 99277298Sobrien const void *arg2; 99360484Sobrien{ 99460484Sobrien const Elf_Internal_Rela **rela1 = (const Elf_Internal_Rela**) arg1; 99560484Sobrien const Elf_Internal_Rela **rela2 = (const Elf_Internal_Rela**) arg2; 99660484Sobrien 99777298Sobrien /* Sort by offset. */ 99860484Sobrien return ((*rela1)->r_offset - (*rela2)->r_offset); 99960484Sobrien} 100060484Sobrien 100160484Sobrienstatic boolean 100260484Sobrienppc_elf_relax_section (abfd, isec, link_info, again) 100377298Sobrien bfd *abfd; 100477298Sobrien asection *isec; 100577298Sobrien struct bfd_link_info *link_info; 100677298Sobrien boolean *again; 100760484Sobrien{ 100860484Sobrien#define PAGESIZE 0x1000 100960484Sobrien 101060484Sobrien bfd_byte *contents = NULL; 101160484Sobrien bfd_byte *free_contents = NULL; 101260484Sobrien Elf_Internal_Rela *internal_relocs = NULL; 101360484Sobrien Elf_Internal_Rela *free_relocs = NULL; 101460484Sobrien Elf_Internal_Rela **rela_comb = NULL; 101560484Sobrien int comb_curr, comb_count; 101660484Sobrien 101777298Sobrien /* We never have to do this more than once per input section. */ 101860484Sobrien *again = false; 101960484Sobrien 102060484Sobrien /* If needed, initialize this section's cooked size. */ 102160484Sobrien if (isec->_cooked_size == 0) 102260484Sobrien isec->_cooked_size = isec->_raw_size; 102360484Sobrien 102460484Sobrien /* We're only interested in text sections which overlap the 102577298Sobrien troublesome area at the end of a page. */ 102660484Sobrien if (link_info->mpc860c0 && (isec->flags & SEC_CODE) && isec->_cooked_size) 102760484Sobrien { 102860484Sobrien bfd_vma dot, end_page, end_section; 102960484Sobrien boolean section_modified; 103060484Sobrien 103177298Sobrien /* Get the section contents. */ 103260484Sobrien /* Get cached copy if it exists. */ 103360484Sobrien if (elf_section_data (isec)->this_hdr.contents != NULL) 103460484Sobrien contents = elf_section_data (isec)->this_hdr.contents; 103560484Sobrien else 103660484Sobrien { 103760484Sobrien /* Go get them off disk. */ 103860484Sobrien contents = (bfd_byte *) bfd_malloc (isec->_raw_size); 103960484Sobrien if (contents == NULL) 104077298Sobrien goto error_return; 104160484Sobrien free_contents = contents; 104260484Sobrien 104360484Sobrien if (! bfd_get_section_contents (abfd, isec, contents, 104460484Sobrien (file_ptr) 0, isec->_raw_size)) 104577298Sobrien goto error_return; 104660484Sobrien } 104760484Sobrien 104860484Sobrien comb_curr = 0; 104960484Sobrien comb_count = 0; 105060484Sobrien if (isec->reloc_count) 105177298Sobrien { 105260484Sobrien unsigned n; 105360484Sobrien 105460484Sobrien /* Get a copy of the native relocations. */ 105560484Sobrien internal_relocs = _bfd_elf32_link_read_relocs ( 105677298Sobrien abfd, isec, (PTR) NULL, (Elf_Internal_Rela *) NULL, 105760484Sobrien link_info->keep_memory); 105860484Sobrien if (internal_relocs == NULL) 105960484Sobrien goto error_return; 106060484Sobrien if (! link_info->keep_memory) 106160484Sobrien free_relocs = internal_relocs; 106277298Sobrien 106377298Sobrien /* Setup a faster access method for the reloc info we need. */ 106460484Sobrien rela_comb = (Elf_Internal_Rela**) 106577298Sobrien bfd_malloc (isec->reloc_count*sizeof (Elf_Internal_Rela*)); 106660484Sobrien if (rela_comb == NULL) 106760484Sobrien goto error_return; 106877298Sobrien for (n = 0; n < isec->reloc_count; ++n) 106960484Sobrien { 107060484Sobrien long r_type; 107177298Sobrien 107260484Sobrien r_type = ELF32_R_TYPE (internal_relocs[n].r_info); 107377298Sobrien if (r_type < 0 || r_type >= (int) R_PPC_max) 107460484Sobrien goto error_return; 107577298Sobrien 107660484Sobrien /* Prologue constants are sometimes present in the ".text" 107760484Sobrien sections and they can be identified by their associated relocation. 107860484Sobrien We don't want to process those words and some others which 107960484Sobrien can also be identified by their relocations. However, not all 108060484Sobrien conditional branches will have a relocation so we will 108160484Sobrien only ignore words that 1) have a reloc, and 2) the reloc 108260484Sobrien is not applicable to a conditional branch. 108377298Sobrien The array rela_comb is built here for use in the EOP scan loop. */ 108460484Sobrien switch (r_type) 108560484Sobrien { 108660484Sobrien case R_PPC_ADDR14_BRNTAKEN: /* absolute, predicted not taken */ 108777298Sobrien case R_PPC_REL14: /* relative cond. br. */ 108860484Sobrien case R_PPC_REL14_BRNTAKEN: /* rel. cond. br., predicted not taken */ 108977298Sobrien /* We should check the instruction. */ 109060484Sobrien break; 109160484Sobrien default: 109277298Sobrien /* The word is not a conditional branch - ignore it. */ 109360484Sobrien rela_comb[comb_count++] = &internal_relocs[n]; 109460484Sobrien break; 109560484Sobrien } 109660484Sobrien } 109760484Sobrien if (comb_count > 1) 109877298Sobrien qsort (rela_comb, (size_t) comb_count, sizeof (int), ppc_elf_sort_rela); 109977298Sobrien } 110060484Sobrien 110177298Sobrien /* Enumerate each EOP region that overlaps this section. */ 110260484Sobrien end_section = isec->vma + isec->_cooked_size; 110360484Sobrien dot = end_page = (isec->vma | (PAGESIZE - 1)) + 1; 110460484Sobrien dot -= link_info->mpc860c0; 110560484Sobrien section_modified = false; 110660484Sobrien if (dot < isec->vma) /* Increment the start position if this section */ 110777298Sobrien dot = isec->vma; /* begins in the middle of its first EOP region. */ 110860484Sobrien for (; 110960484Sobrien dot < end_section; 111060484Sobrien dot += PAGESIZE, end_page += PAGESIZE) 111160484Sobrien { 111260484Sobrien 111377298Sobrien /* Check each word in this EOP region. */ 111460484Sobrien for (; dot < end_page; dot += 4) 111560484Sobrien { 111660484Sobrien bfd_vma isec_offset; 111760484Sobrien unsigned long insn; 111860484Sobrien boolean skip, modified; 111960484Sobrien 112060484Sobrien /* Don't process this word if there is a relocation for it and 112177298Sobrien the relocation indicates the word is not a conditional branch. */ 112260484Sobrien skip = false; 112360484Sobrien isec_offset = dot - isec->vma; 112460484Sobrien for (; comb_curr<comb_count; ++comb_curr) 112560484Sobrien { 112660484Sobrien bfd_vma r_offset; 112760484Sobrien 112860484Sobrien r_offset = rela_comb[comb_curr]->r_offset; 112960484Sobrien if (r_offset >= isec_offset) 113060484Sobrien { 113160484Sobrien if (r_offset == isec_offset) skip = true; 113260484Sobrien break; 113360484Sobrien } 113460484Sobrien } 113560484Sobrien if (skip) continue; 113660484Sobrien 113777298Sobrien /* Check the current word for a problematic conditional branch. */ 113860484Sobrien#define BO0(insn) ((insn) & 0x02000000) 113960484Sobrien#define BO2(insn) ((insn) & 0x00800000) 114060484Sobrien#define BO4(insn) ((insn) & 0x00200000) 114160484Sobrien insn = (unsigned long) bfd_get_32 (abfd, contents + isec_offset); 114260484Sobrien modified = false; 114360484Sobrien if ((insn & 0xFc000000) == 0x40000000) 114460484Sobrien { 114560484Sobrien /* Instruction is BCx */ 114660484Sobrien if ((!BO0(insn) || !BO2(insn)) && !BO4(insn)) 114760484Sobrien { 114860484Sobrien bfd_vma target; 114960484Sobrien /* This branch is predicted as "normal". 115077298Sobrien If this is a forward branch, it is problematic. */ 115160484Sobrien 115260484Sobrien target = insn & 0x0000Fffc; /*extract*/ 115360484Sobrien target = (target ^ 0x8000) - 0x8000; /*sign extend*/ 115460484Sobrien if ((insn & 0x00000002) == 0) 115560484Sobrien target += dot; /*convert to abs*/ 115660484Sobrien if (target > dot) 115760484Sobrien { 115860484Sobrien insn |= 0x00200000; /* set the prediction bit */ 115960484Sobrien modified = true; 116060484Sobrien } 116160484Sobrien } 116260484Sobrien } 116360484Sobrien else if ((insn & 0xFc00Fffe) == 0x4c000420) 116460484Sobrien { 116560484Sobrien /* Instruction is BCCTRx */ 116660484Sobrien if ((!BO0(insn) || !BO2(insn)) && !BO4(insn)) 116760484Sobrien { 116860484Sobrien /* This branch is predicted as not-taken. 116960484Sobrien If this is a forward branch, it is problematic. 117060484Sobrien Since we can't tell statically if it will branch forward, 117177298Sobrien always set the prediction bit. */ 117260484Sobrien insn |= 0x00200000; /* set the prediction bit */ 117360484Sobrien modified = true; 117460484Sobrien } 117560484Sobrien } 117660484Sobrien else if ((insn & 0xFc00Fffe) == 0x4c000020) 117760484Sobrien { 117860484Sobrien /* Instruction is BCLRx */ 117960484Sobrien if ((!BO0(insn) || !BO2(insn)) && !BO4(insn)) 118060484Sobrien { 118160484Sobrien /* This branch is predicted as not-taken. 118260484Sobrien If this is a forward branch, it is problematic. 118360484Sobrien Since we can't tell statically if it will branch forward, 118477298Sobrien always set the prediction bit. */ 118560484Sobrien insn |= 0x00200000; /* set the prediction bit */ 118660484Sobrien modified = true; 118760484Sobrien } 118860484Sobrien } 118960484Sobrien#undef BO0 119060484Sobrien#undef BO2 119160484Sobrien#undef BO4 119260484Sobrien if (modified) 119360484Sobrien { 119460484Sobrien bfd_put_32 (abfd, insn, contents + isec_offset); 119560484Sobrien section_modified = true; 119660484Sobrien } 119760484Sobrien } 119860484Sobrien } 119960484Sobrien if (section_modified) 120060484Sobrien { 120160484Sobrien elf_section_data (isec)->this_hdr.contents = contents; 120260484Sobrien free_contents = NULL; 120360484Sobrien } 120460484Sobrien } 120560484Sobrien 120660484Sobrien if (rela_comb != NULL) 120760484Sobrien { 120860484Sobrien free (rela_comb); 120960484Sobrien rela_comb = NULL; 121060484Sobrien } 121160484Sobrien 121260484Sobrien if (free_relocs != NULL) 121360484Sobrien { 121460484Sobrien free (free_relocs); 121560484Sobrien free_relocs = NULL; 121660484Sobrien } 121760484Sobrien 121860484Sobrien if (free_contents != NULL) 121960484Sobrien { 122060484Sobrien if (! link_info->keep_memory) 122160484Sobrien free (free_contents); 122260484Sobrien else 122360484Sobrien { 122460484Sobrien /* Cache the section contents for elf_link_input_bfd. */ 122560484Sobrien elf_section_data (isec)->this_hdr.contents = contents; 122660484Sobrien } 122760484Sobrien free_contents = NULL; 122860484Sobrien } 122960484Sobrien 123060484Sobrien return true; 123160484Sobrien 123260484Sobrienerror_return: 123360484Sobrien if (rela_comb != NULL) 123460484Sobrien free (rela_comb); 123560484Sobrien if (free_relocs != NULL) 123660484Sobrien free (free_relocs); 123760484Sobrien if (free_contents != NULL) 123860484Sobrien free (free_contents); 123960484Sobrien return false; 124060484Sobrien} 124160484Sobrien 124260484Sobrienstatic reloc_howto_type * 124360484Sobrienppc_elf_reloc_type_lookup (abfd, code) 124460484Sobrien bfd *abfd ATTRIBUTE_UNUSED; 124560484Sobrien bfd_reloc_code_real_type code; 124660484Sobrien{ 124760484Sobrien enum elf_ppc_reloc_type ppc_reloc = R_PPC_NONE; 124860484Sobrien 124960484Sobrien if (!ppc_elf_howto_table[R_PPC_ADDR32]) 125077298Sobrien /* Initialize howto table if needed. */ 125160484Sobrien ppc_elf_howto_init (); 125260484Sobrien 125377298Sobrien switch ((int) code) 125460484Sobrien { 125560484Sobrien default: 125677298Sobrien return (reloc_howto_type *) NULL; 125760484Sobrien 125860484Sobrien case BFD_RELOC_NONE: ppc_reloc = R_PPC_NONE; break; 125960484Sobrien case BFD_RELOC_32: ppc_reloc = R_PPC_ADDR32; break; 126060484Sobrien case BFD_RELOC_PPC_BA26: ppc_reloc = R_PPC_ADDR24; break; 126160484Sobrien case BFD_RELOC_16: ppc_reloc = R_PPC_ADDR16; break; 126260484Sobrien case BFD_RELOC_LO16: ppc_reloc = R_PPC_ADDR16_LO; break; 126360484Sobrien case BFD_RELOC_HI16: ppc_reloc = R_PPC_ADDR16_HI; break; 126460484Sobrien case BFD_RELOC_HI16_S: ppc_reloc = R_PPC_ADDR16_HA; break; 126560484Sobrien case BFD_RELOC_PPC_BA16: ppc_reloc = R_PPC_ADDR14; break; 126660484Sobrien case BFD_RELOC_PPC_BA16_BRTAKEN: ppc_reloc = R_PPC_ADDR14_BRTAKEN; break; 126760484Sobrien case BFD_RELOC_PPC_BA16_BRNTAKEN: ppc_reloc = R_PPC_ADDR14_BRNTAKEN; break; 126860484Sobrien case BFD_RELOC_PPC_B26: ppc_reloc = R_PPC_REL24; break; 126960484Sobrien case BFD_RELOC_PPC_B16: ppc_reloc = R_PPC_REL14; break; 127060484Sobrien case BFD_RELOC_PPC_B16_BRTAKEN: ppc_reloc = R_PPC_REL14_BRTAKEN; break; 127160484Sobrien case BFD_RELOC_PPC_B16_BRNTAKEN: ppc_reloc = R_PPC_REL14_BRNTAKEN; break; 127260484Sobrien case BFD_RELOC_16_GOTOFF: ppc_reloc = R_PPC_GOT16; break; 127360484Sobrien case BFD_RELOC_LO16_GOTOFF: ppc_reloc = R_PPC_GOT16_LO; break; 127460484Sobrien case BFD_RELOC_HI16_GOTOFF: ppc_reloc = R_PPC_GOT16_HI; break; 127560484Sobrien case BFD_RELOC_HI16_S_GOTOFF: ppc_reloc = R_PPC_GOT16_HA; break; 127660484Sobrien case BFD_RELOC_24_PLT_PCREL: ppc_reloc = R_PPC_PLTREL24; break; 127760484Sobrien case BFD_RELOC_PPC_COPY: ppc_reloc = R_PPC_COPY; break; 127860484Sobrien case BFD_RELOC_PPC_GLOB_DAT: ppc_reloc = R_PPC_GLOB_DAT; break; 127960484Sobrien case BFD_RELOC_PPC_LOCAL24PC: ppc_reloc = R_PPC_LOCAL24PC; break; 128060484Sobrien case BFD_RELOC_32_PCREL: ppc_reloc = R_PPC_REL32; break; 128160484Sobrien case BFD_RELOC_32_PLTOFF: ppc_reloc = R_PPC_PLT32; break; 128260484Sobrien case BFD_RELOC_32_PLT_PCREL: ppc_reloc = R_PPC_PLTREL32; break; 128360484Sobrien case BFD_RELOC_LO16_PLTOFF: ppc_reloc = R_PPC_PLT16_LO; break; 128460484Sobrien case BFD_RELOC_HI16_PLTOFF: ppc_reloc = R_PPC_PLT16_HI; break; 128560484Sobrien case BFD_RELOC_HI16_S_PLTOFF: ppc_reloc = R_PPC_PLT16_HA; break; 128660484Sobrien case BFD_RELOC_GPREL16: ppc_reloc = R_PPC_SDAREL16; break; 128760484Sobrien case BFD_RELOC_32_BASEREL: ppc_reloc = R_PPC_SECTOFF; break; 128860484Sobrien case BFD_RELOC_LO16_BASEREL: ppc_reloc = R_PPC_SECTOFF_LO; break; 128960484Sobrien case BFD_RELOC_HI16_BASEREL: ppc_reloc = R_PPC_SECTOFF_HI; break; 129060484Sobrien case BFD_RELOC_HI16_S_BASEREL: ppc_reloc = R_PPC_SECTOFF_HA; break; 129160484Sobrien case BFD_RELOC_CTOR: ppc_reloc = R_PPC_ADDR32; break; 129260484Sobrien case BFD_RELOC_PPC_TOC16: ppc_reloc = R_PPC_TOC16; break; 129360484Sobrien case BFD_RELOC_PPC_EMB_NADDR32: ppc_reloc = R_PPC_EMB_NADDR32; break; 129460484Sobrien case BFD_RELOC_PPC_EMB_NADDR16: ppc_reloc = R_PPC_EMB_NADDR16; break; 129560484Sobrien case BFD_RELOC_PPC_EMB_NADDR16_LO: ppc_reloc = R_PPC_EMB_NADDR16_LO; break; 129660484Sobrien case BFD_RELOC_PPC_EMB_NADDR16_HI: ppc_reloc = R_PPC_EMB_NADDR16_HI; break; 129760484Sobrien case BFD_RELOC_PPC_EMB_NADDR16_HA: ppc_reloc = R_PPC_EMB_NADDR16_HA; break; 129860484Sobrien case BFD_RELOC_PPC_EMB_SDAI16: ppc_reloc = R_PPC_EMB_SDAI16; break; 129960484Sobrien case BFD_RELOC_PPC_EMB_SDA2I16: ppc_reloc = R_PPC_EMB_SDA2I16; break; 130060484Sobrien case BFD_RELOC_PPC_EMB_SDA2REL: ppc_reloc = R_PPC_EMB_SDA2REL; break; 130160484Sobrien case BFD_RELOC_PPC_EMB_SDA21: ppc_reloc = R_PPC_EMB_SDA21; break; 130260484Sobrien case BFD_RELOC_PPC_EMB_MRKREF: ppc_reloc = R_PPC_EMB_MRKREF; break; 130360484Sobrien case BFD_RELOC_PPC_EMB_RELSEC16: ppc_reloc = R_PPC_EMB_RELSEC16; break; 130460484Sobrien case BFD_RELOC_PPC_EMB_RELST_LO: ppc_reloc = R_PPC_EMB_RELST_LO; break; 130560484Sobrien case BFD_RELOC_PPC_EMB_RELST_HI: ppc_reloc = R_PPC_EMB_RELST_HI; break; 130660484Sobrien case BFD_RELOC_PPC_EMB_RELST_HA: ppc_reloc = R_PPC_EMB_RELST_HA; break; 130760484Sobrien case BFD_RELOC_PPC_EMB_BIT_FLD: ppc_reloc = R_PPC_EMB_BIT_FLD; break; 130860484Sobrien case BFD_RELOC_PPC_EMB_RELSDA: ppc_reloc = R_PPC_EMB_RELSDA; break; 130960484Sobrien case BFD_RELOC_VTABLE_INHERIT: ppc_reloc = R_PPC_GNU_VTINHERIT; break; 131060484Sobrien case BFD_RELOC_VTABLE_ENTRY: ppc_reloc = R_PPC_GNU_VTENTRY; break; 131160484Sobrien } 131260484Sobrien 131377298Sobrien return ppc_elf_howto_table[(int) ppc_reloc]; 131460484Sobrien}; 131560484Sobrien 131660484Sobrien/* Set the howto pointer for a PowerPC ELF reloc. */ 131760484Sobrien 131860484Sobrienstatic void 131960484Sobrienppc_elf_info_to_howto (abfd, cache_ptr, dst) 132060484Sobrien bfd *abfd ATTRIBUTE_UNUSED; 132160484Sobrien arelent *cache_ptr; 132260484Sobrien Elf32_Internal_Rela *dst; 132360484Sobrien{ 132477298Sobrien if (!ppc_elf_howto_table[R_PPC_ADDR32]) 132577298Sobrien /* Initialize howto table if needed. */ 132660484Sobrien ppc_elf_howto_init (); 132760484Sobrien 132860484Sobrien BFD_ASSERT (ELF32_R_TYPE (dst->r_info) < (unsigned int) R_PPC_max); 132960484Sobrien cache_ptr->howto = ppc_elf_howto_table[ELF32_R_TYPE (dst->r_info)]; 133060484Sobrien} 133160484Sobrien 133260484Sobrien/* Handle the R_PPC_ADDR16_HA reloc. */ 133360484Sobrien 133460484Sobrienstatic bfd_reloc_status_type 133560484Sobrienppc_elf_addr16_ha_reloc (abfd, reloc_entry, symbol, data, input_section, 133660484Sobrien output_bfd, error_message) 133760484Sobrien bfd *abfd ATTRIBUTE_UNUSED; 133860484Sobrien arelent *reloc_entry; 133960484Sobrien asymbol *symbol; 134060484Sobrien PTR data ATTRIBUTE_UNUSED; 134160484Sobrien asection *input_section; 134260484Sobrien bfd *output_bfd; 134360484Sobrien char **error_message ATTRIBUTE_UNUSED; 134460484Sobrien{ 134560484Sobrien bfd_vma relocation; 134660484Sobrien 134760484Sobrien if (output_bfd != NULL) 134860484Sobrien { 134960484Sobrien reloc_entry->address += input_section->output_offset; 135060484Sobrien return bfd_reloc_ok; 135160484Sobrien } 135260484Sobrien 135360484Sobrien if (reloc_entry->address > input_section->_cooked_size) 135460484Sobrien return bfd_reloc_outofrange; 135560484Sobrien 135660484Sobrien if (bfd_is_com_section (symbol->section)) 135760484Sobrien relocation = 0; 135860484Sobrien else 135960484Sobrien relocation = symbol->value; 136060484Sobrien 136160484Sobrien relocation += symbol->section->output_section->vma; 136260484Sobrien relocation += symbol->section->output_offset; 136360484Sobrien relocation += reloc_entry->addend; 136460484Sobrien 136560484Sobrien reloc_entry->addend += (relocation & 0x8000) << 1; 136660484Sobrien 136760484Sobrien return bfd_reloc_continue; 136860484Sobrien} 136960484Sobrien 137077298Sobrien/* Function to set whether a module needs the -mrelocatable bit set. */ 137160484Sobrien 137260484Sobrienstatic boolean 137360484Sobrienppc_elf_set_private_flags (abfd, flags) 137460484Sobrien bfd *abfd; 137560484Sobrien flagword flags; 137660484Sobrien{ 137760484Sobrien BFD_ASSERT (!elf_flags_init (abfd) 137860484Sobrien || elf_elfheader (abfd)->e_flags == flags); 137960484Sobrien 138060484Sobrien elf_elfheader (abfd)->e_flags = flags; 138160484Sobrien elf_flags_init (abfd) = true; 138260484Sobrien return true; 138360484Sobrien} 138460484Sobrien 138560484Sobrien/* Copy backend specific data from one object module to another */ 138660484Sobrienstatic boolean 138760484Sobrienppc_elf_copy_private_bfd_data (ibfd, obfd) 138860484Sobrien bfd *ibfd; 138960484Sobrien bfd *obfd; 139060484Sobrien{ 139160484Sobrien if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour 139260484Sobrien || bfd_get_flavour (obfd) != bfd_target_elf_flavour) 139360484Sobrien return true; 139460484Sobrien 139560484Sobrien BFD_ASSERT (!elf_flags_init (obfd) 139660484Sobrien || elf_elfheader (obfd)->e_flags == elf_elfheader (ibfd)->e_flags); 139760484Sobrien 139860484Sobrien elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags; 139960484Sobrien elf_flags_init (obfd) = true; 140060484Sobrien return true; 140160484Sobrien} 140260484Sobrien 140360484Sobrien/* Merge backend specific data from an object file to the output 140460484Sobrien object file when linking */ 140560484Sobrienstatic boolean 140660484Sobrienppc_elf_merge_private_bfd_data (ibfd, obfd) 140760484Sobrien bfd *ibfd; 140860484Sobrien bfd *obfd; 140960484Sobrien{ 141060484Sobrien flagword old_flags; 141160484Sobrien flagword new_flags; 141260484Sobrien boolean error; 141360484Sobrien 141460484Sobrien /* Check if we have the same endianess */ 141577298Sobrien if (_bfd_generic_verify_endian_match (ibfd, obfd) == false) 141677298Sobrien return false; 141760484Sobrien 141860484Sobrien if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour 141960484Sobrien || bfd_get_flavour (obfd) != bfd_target_elf_flavour) 142060484Sobrien return true; 142160484Sobrien 142260484Sobrien new_flags = elf_elfheader (ibfd)->e_flags; 142360484Sobrien old_flags = elf_elfheader (obfd)->e_flags; 142460484Sobrien if (!elf_flags_init (obfd)) /* First call, no flags set */ 142560484Sobrien { 142660484Sobrien elf_flags_init (obfd) = true; 142760484Sobrien elf_elfheader (obfd)->e_flags = new_flags; 142860484Sobrien } 142960484Sobrien 143060484Sobrien else if (new_flags == old_flags) /* Compatible flags are ok */ 143160484Sobrien ; 143260484Sobrien 143360484Sobrien else /* Incompatible flags */ 143460484Sobrien { 143560484Sobrien /* Warn about -mrelocatable mismatch. Allow -mrelocatable-lib to be linked 143660484Sobrien with either. */ 143760484Sobrien error = false; 143860484Sobrien if ((new_flags & EF_PPC_RELOCATABLE) != 0 143960484Sobrien && (old_flags & (EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB)) == 0) 144060484Sobrien { 144160484Sobrien error = true; 144260484Sobrien (*_bfd_error_handler) 144360484Sobrien (_("%s: compiled with -mrelocatable and linked with modules compiled normally"), 144460484Sobrien bfd_get_filename (ibfd)); 144560484Sobrien } 144660484Sobrien else if ((new_flags & (EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB)) == 0 144760484Sobrien && (old_flags & EF_PPC_RELOCATABLE) != 0) 144860484Sobrien { 144960484Sobrien error = true; 145060484Sobrien (*_bfd_error_handler) 145160484Sobrien (_("%s: compiled normally and linked with modules compiled with -mrelocatable"), 145260484Sobrien bfd_get_filename (ibfd)); 145360484Sobrien } 145460484Sobrien 145560484Sobrien /* The output is -mrelocatable-lib iff both the input files are. */ 145660484Sobrien if (! (new_flags & EF_PPC_RELOCATABLE_LIB)) 145760484Sobrien elf_elfheader (obfd)->e_flags &= ~EF_PPC_RELOCATABLE_LIB; 145860484Sobrien 145960484Sobrien /* The output is -mrelocatable iff it can't be -mrelocatable-lib, 146060484Sobrien but each input file is either -mrelocatable or -mrelocatable-lib. */ 146160484Sobrien if (! (elf_elfheader (obfd)->e_flags & EF_PPC_RELOCATABLE_LIB) 146260484Sobrien && (new_flags & (EF_PPC_RELOCATABLE_LIB | EF_PPC_RELOCATABLE)) 146360484Sobrien && (old_flags & (EF_PPC_RELOCATABLE_LIB | EF_PPC_RELOCATABLE))) 146460484Sobrien elf_elfheader (obfd)->e_flags |= EF_PPC_RELOCATABLE; 146560484Sobrien 146660484Sobrien /* Do not warn about eabi vs. V.4 mismatch, just or in the bit if any module uses it */ 146760484Sobrien elf_elfheader (obfd)->e_flags |= (new_flags & EF_PPC_EMB); 146860484Sobrien 146960484Sobrien new_flags &= ~ (EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB | EF_PPC_EMB); 147060484Sobrien old_flags &= ~ (EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB | EF_PPC_EMB); 147160484Sobrien 147260484Sobrien /* Warn about any other mismatches */ 147360484Sobrien if (new_flags != old_flags) 147460484Sobrien { 147560484Sobrien error = true; 147660484Sobrien (*_bfd_error_handler) 147760484Sobrien (_("%s: uses different e_flags (0x%lx) fields than previous modules (0x%lx)"), 147877298Sobrien bfd_get_filename (ibfd), (long) new_flags, (long) old_flags); 147960484Sobrien } 148060484Sobrien 148160484Sobrien if (error) 148260484Sobrien { 148360484Sobrien bfd_set_error (bfd_error_bad_value); 148460484Sobrien return false; 148560484Sobrien } 148660484Sobrien } 148760484Sobrien 148860484Sobrien return true; 148960484Sobrien} 149060484Sobrien 149160484Sobrien/* Handle a PowerPC specific section when reading an object file. This 149260484Sobrien is called when elfcode.h finds a section with an unknown type. */ 149360484Sobrien 149460484Sobrienstatic boolean 149560484Sobrienppc_elf_section_from_shdr (abfd, hdr, name) 149660484Sobrien bfd *abfd; 149760484Sobrien Elf32_Internal_Shdr *hdr; 149860484Sobrien char *name; 149960484Sobrien{ 150060484Sobrien asection *newsect; 150160484Sobrien flagword flags; 150260484Sobrien 150360484Sobrien if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name)) 150460484Sobrien return false; 150560484Sobrien 150660484Sobrien newsect = hdr->bfd_section; 150760484Sobrien flags = bfd_get_section_flags (abfd, newsect); 150860484Sobrien if (hdr->sh_flags & SHF_EXCLUDE) 150960484Sobrien flags |= SEC_EXCLUDE; 151060484Sobrien 151160484Sobrien if (hdr->sh_type == SHT_ORDERED) 151260484Sobrien flags |= SEC_SORT_ENTRIES; 151360484Sobrien 151460484Sobrien bfd_set_section_flags (abfd, newsect, flags); 151560484Sobrien return true; 151660484Sobrien} 151760484Sobrien 151860484Sobrien/* Set up any other section flags and such that may be necessary. */ 151960484Sobrien 152060484Sobrienstatic boolean 152160484Sobrienppc_elf_fake_sections (abfd, shdr, asect) 152260484Sobrien bfd *abfd ATTRIBUTE_UNUSED; 152360484Sobrien Elf32_Internal_Shdr *shdr; 152460484Sobrien asection *asect; 152560484Sobrien{ 152660484Sobrien if ((asect->flags & SEC_EXCLUDE) != 0) 152760484Sobrien shdr->sh_flags |= SHF_EXCLUDE; 152860484Sobrien 152960484Sobrien if ((asect->flags & SEC_SORT_ENTRIES) != 0) 153060484Sobrien shdr->sh_type = SHT_ORDERED; 153160484Sobrien 153260484Sobrien return true; 153360484Sobrien} 153460484Sobrien 153560484Sobrien/* Create a special linker section */ 153660484Sobrienstatic elf_linker_section_t * 153760484Sobrienppc_elf_create_linker_section (abfd, info, which) 153860484Sobrien bfd *abfd; 153960484Sobrien struct bfd_link_info *info; 154060484Sobrien enum elf_linker_section_enum which; 154160484Sobrien{ 154260484Sobrien bfd *dynobj = elf_hash_table (info)->dynobj; 154360484Sobrien elf_linker_section_t *lsect; 154460484Sobrien 154560484Sobrien /* Record the first bfd section that needs the special section */ 154660484Sobrien if (!dynobj) 154760484Sobrien dynobj = elf_hash_table (info)->dynobj = abfd; 154860484Sobrien 154960484Sobrien /* If this is the first time, create the section */ 155060484Sobrien lsect = elf_linker_section (dynobj, which); 155160484Sobrien if (!lsect) 155260484Sobrien { 155360484Sobrien elf_linker_section_t defaults; 155460484Sobrien static elf_linker_section_t zero_section; 155560484Sobrien 155660484Sobrien defaults = zero_section; 155760484Sobrien defaults.which = which; 155860484Sobrien defaults.hole_written_p = false; 155960484Sobrien defaults.alignment = 2; 156060484Sobrien 156160484Sobrien /* Both of these sections are (technically) created by the user 156260484Sobrien putting data in them, so they shouldn't be marked 156360484Sobrien SEC_LINKER_CREATED. 156460484Sobrien 156560484Sobrien The linker creates them so it has somewhere to attach their 156660484Sobrien respective symbols. In fact, if they were empty it would 156760484Sobrien be OK to leave the symbol set to 0 (or any random number), because 156860484Sobrien the appropriate register should never be used. */ 156960484Sobrien defaults.flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS 157060484Sobrien | SEC_IN_MEMORY); 157160484Sobrien 157260484Sobrien switch (which) 157360484Sobrien { 157460484Sobrien default: 157560484Sobrien (*_bfd_error_handler) (_("%s: Unknown special linker type %d"), 157660484Sobrien bfd_get_filename (abfd), 157777298Sobrien (int) which); 157860484Sobrien 157960484Sobrien bfd_set_error (bfd_error_bad_value); 158077298Sobrien return (elf_linker_section_t *) 0; 158160484Sobrien 158260484Sobrien case LINKER_SECTION_SDATA: /* .sdata/.sbss section */ 158360484Sobrien defaults.name = ".sdata"; 158460484Sobrien defaults.rel_name = ".rela.sdata"; 158560484Sobrien defaults.bss_name = ".sbss"; 158660484Sobrien defaults.sym_name = "_SDA_BASE_"; 158760484Sobrien defaults.sym_offset = 32768; 158860484Sobrien break; 158960484Sobrien 159060484Sobrien case LINKER_SECTION_SDATA2: /* .sdata2/.sbss2 section */ 159160484Sobrien defaults.name = ".sdata2"; 159260484Sobrien defaults.rel_name = ".rela.sdata2"; 159360484Sobrien defaults.bss_name = ".sbss2"; 159460484Sobrien defaults.sym_name = "_SDA2_BASE_"; 159560484Sobrien defaults.sym_offset = 32768; 159660484Sobrien defaults.flags |= SEC_READONLY; 159760484Sobrien break; 159860484Sobrien } 159960484Sobrien 160060484Sobrien lsect = _bfd_elf_create_linker_section (abfd, info, which, &defaults); 160160484Sobrien } 160260484Sobrien 160360484Sobrien return lsect; 160460484Sobrien} 160560484Sobrien 160677298Sobrien/* If we have a non-zero sized .sbss2 or .PPC.EMB.sbss0 sections, we 160777298Sobrien need to bump up the number of section headers. */ 160860484Sobrien 160960484Sobrienstatic int 161060484Sobrienppc_elf_additional_program_headers (abfd) 161160484Sobrien bfd *abfd; 161260484Sobrien{ 161360484Sobrien asection *s; 161460484Sobrien int ret; 161560484Sobrien 161660484Sobrien ret = 0; 161760484Sobrien 161860484Sobrien s = bfd_get_section_by_name (abfd, ".interp"); 161960484Sobrien if (s != NULL) 162060484Sobrien ++ret; 162160484Sobrien 162260484Sobrien s = bfd_get_section_by_name (abfd, ".sbss2"); 162360484Sobrien if (s != NULL && (s->flags & SEC_LOAD) != 0 && s->_raw_size > 0) 162460484Sobrien ++ret; 162560484Sobrien 162660484Sobrien s = bfd_get_section_by_name (abfd, ".PPC.EMB.sbss0"); 162760484Sobrien if (s != NULL && (s->flags & SEC_LOAD) != 0 && s->_raw_size > 0) 162860484Sobrien ++ret; 162960484Sobrien 163060484Sobrien return ret; 163160484Sobrien} 163260484Sobrien 163377298Sobrien/* Modify the segment map if needed. */ 163460484Sobrien 163560484Sobrienstatic boolean 163660484Sobrienppc_elf_modify_segment_map (abfd) 163760484Sobrien bfd *abfd ATTRIBUTE_UNUSED; 163860484Sobrien{ 163960484Sobrien return true; 164060484Sobrien} 164160484Sobrien 164260484Sobrien/* We have to create .dynsbss and .rela.sbss here so that they get mapped 164360484Sobrien to output sections (just like _bfd_elf_create_dynamic_sections has 164460484Sobrien to create .dynbss and .rela.bss). */ 164560484Sobrien 164660484Sobrienstatic boolean 164760484Sobrienppc_elf_create_dynamic_sections (abfd, info) 164860484Sobrien bfd *abfd; 164960484Sobrien struct bfd_link_info *info; 165060484Sobrien{ 165160484Sobrien register asection *s; 165260484Sobrien flagword flags; 165360484Sobrien 165477298Sobrien if (!_bfd_elf_create_dynamic_sections (abfd, info)) 165560484Sobrien return false; 165660484Sobrien 165760484Sobrien flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY 165860484Sobrien | SEC_LINKER_CREATED); 165960484Sobrien 166060484Sobrien s = bfd_make_section (abfd, ".dynsbss"); 166160484Sobrien if (s == NULL 166260484Sobrien || ! bfd_set_section_flags (abfd, s, SEC_ALLOC)) 166360484Sobrien return false; 166460484Sobrien 166560484Sobrien if (! info->shared) 166660484Sobrien { 166760484Sobrien s = bfd_make_section (abfd, ".rela.sbss"); 166860484Sobrien if (s == NULL 166960484Sobrien || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY) 167060484Sobrien || ! bfd_set_section_alignment (abfd, s, 2)) 167160484Sobrien return false; 167260484Sobrien } 167360484Sobrien return true; 167460484Sobrien} 167560484Sobrien 167660484Sobrien/* Adjust a symbol defined by a dynamic object and referenced by a 167760484Sobrien regular object. The current definition is in some section of the 167860484Sobrien dynamic object, but we're not including those sections. We have to 167960484Sobrien change the definition to something the rest of the link can 168060484Sobrien understand. */ 168160484Sobrien 168260484Sobrienstatic boolean 168360484Sobrienppc_elf_adjust_dynamic_symbol (info, h) 168460484Sobrien struct bfd_link_info *info; 168560484Sobrien struct elf_link_hash_entry *h; 168660484Sobrien{ 168760484Sobrien bfd *dynobj = elf_hash_table (info)->dynobj; 168860484Sobrien asection *s; 168960484Sobrien unsigned int power_of_two; 169060484Sobrien bfd_vma plt_offset; 169160484Sobrien 169260484Sobrien#ifdef DEBUG 169360484Sobrien fprintf (stderr, "ppc_elf_adjust_dynamic_symbol called for %s\n", h->root.root.string); 169460484Sobrien#endif 169560484Sobrien 169660484Sobrien /* Make sure we know what is going on here. */ 169760484Sobrien BFD_ASSERT (dynobj != NULL 169860484Sobrien && ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) 169960484Sobrien || h->weakdef != NULL 170060484Sobrien || ((h->elf_link_hash_flags 170160484Sobrien & ELF_LINK_HASH_DEF_DYNAMIC) != 0 170260484Sobrien && (h->elf_link_hash_flags 170360484Sobrien & ELF_LINK_HASH_REF_REGULAR) != 0 170460484Sobrien && (h->elf_link_hash_flags 170560484Sobrien & ELF_LINK_HASH_DEF_REGULAR) == 0))); 170660484Sobrien 170760484Sobrien /* If this is a function, put it in the procedure linkage table. We 170860484Sobrien will fill in the contents of the procedure linkage table later, 170960484Sobrien when we know the address of the .got section. */ 171060484Sobrien if (h->type == STT_FUNC 171160484Sobrien || (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0) 171260484Sobrien { 171360484Sobrien if (! elf_hash_table (info)->dynamic_sections_created 171477298Sobrien || SYMBOL_CALLS_LOCAL (info, h) 171560484Sobrien || (info->shared && h->plt.refcount <= 0)) 171660484Sobrien { 171760484Sobrien /* A PLT entry is not required/allowed when: 171860484Sobrien 171960484Sobrien 1. We are not using ld.so; because then the PLT entry 172060484Sobrien can't be set up, so we can't use one. 172160484Sobrien 172277298Sobrien 2. We know for certain that a call to this symbol 172377298Sobrien will go to this object. 172460484Sobrien 172560484Sobrien 3. GC has rendered the entry unused. 172660484Sobrien Note, however, that in an executable all references to the 172760484Sobrien symbol go to the PLT, so we can't turn it off in that case. 172860484Sobrien ??? The correct thing to do here is to reference count 172960484Sobrien all uses of the symbol, not just those to the GOT or PLT. */ 173060484Sobrien h->plt.offset = (bfd_vma) -1; 173160484Sobrien h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; 173260484Sobrien return true; 173360484Sobrien } 173460484Sobrien 173560484Sobrien /* Make sure this symbol is output as a dynamic symbol. */ 173660484Sobrien if (h->dynindx == -1) 173760484Sobrien { 173860484Sobrien if (! bfd_elf32_link_record_dynamic_symbol (info, h)) 173960484Sobrien return false; 174060484Sobrien } 174160484Sobrien BFD_ASSERT (h->dynindx != -1); 174260484Sobrien 174360484Sobrien s = bfd_get_section_by_name (dynobj, ".plt"); 174460484Sobrien BFD_ASSERT (s != NULL); 174560484Sobrien 174660484Sobrien /* If this is the first .plt entry, make room for the special 174760484Sobrien first entry. */ 174860484Sobrien if (s->_raw_size == 0) 174960484Sobrien s->_raw_size += PLT_INITIAL_ENTRY_SIZE; 175060484Sobrien 175160484Sobrien /* The PowerPC PLT is actually composed of two parts, the first part 175260484Sobrien is 2 words (for a load and a jump), and then there is a remaining 175360484Sobrien word available at the end. */ 175460484Sobrien plt_offset = (PLT_INITIAL_ENTRY_SIZE 175560484Sobrien + (PLT_SLOT_SIZE 175660484Sobrien * ((s->_raw_size - PLT_INITIAL_ENTRY_SIZE) 175760484Sobrien / PLT_ENTRY_SIZE))); 175860484Sobrien 175960484Sobrien /* If this symbol is not defined in a regular file, and we are 176060484Sobrien not generating a shared library, then set the symbol to this 176160484Sobrien location in the .plt. This is required to make function 176260484Sobrien pointers compare as equal between the normal executable and 176360484Sobrien the shared library. */ 176460484Sobrien if (! info->shared 176560484Sobrien && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) 176660484Sobrien { 176760484Sobrien h->root.u.def.section = s; 176860484Sobrien h->root.u.def.value = plt_offset; 176960484Sobrien } 177060484Sobrien 177160484Sobrien h->plt.offset = plt_offset; 177260484Sobrien 177360484Sobrien /* Make room for this entry. After the 8192nd entry, room 177460484Sobrien for two entries is allocated. */ 177560484Sobrien if ((s->_raw_size - PLT_INITIAL_ENTRY_SIZE) / PLT_ENTRY_SIZE 177660484Sobrien >= PLT_NUM_SINGLE_ENTRIES) 177760484Sobrien s->_raw_size += 2 * PLT_ENTRY_SIZE; 177860484Sobrien else 177960484Sobrien s->_raw_size += PLT_ENTRY_SIZE; 178060484Sobrien 178160484Sobrien /* We also need to make an entry in the .rela.plt section. */ 178260484Sobrien s = bfd_get_section_by_name (dynobj, ".rela.plt"); 178360484Sobrien BFD_ASSERT (s != NULL); 178460484Sobrien s->_raw_size += sizeof (Elf32_External_Rela); 178560484Sobrien 178660484Sobrien return true; 178760484Sobrien } 178860484Sobrien 178960484Sobrien /* If this is a weak symbol, and there is a real definition, the 179060484Sobrien processor independent code will have arranged for us to see the 179160484Sobrien real definition first, and we can just use the same value. */ 179260484Sobrien if (h->weakdef != NULL) 179360484Sobrien { 179460484Sobrien BFD_ASSERT (h->weakdef->root.type == bfd_link_hash_defined 179560484Sobrien || h->weakdef->root.type == bfd_link_hash_defweak); 179660484Sobrien h->root.u.def.section = h->weakdef->root.u.def.section; 179760484Sobrien h->root.u.def.value = h->weakdef->root.u.def.value; 179860484Sobrien return true; 179960484Sobrien } 180060484Sobrien 180160484Sobrien /* This is a reference to a symbol defined by a dynamic object which 180260484Sobrien is not a function. */ 180360484Sobrien 180460484Sobrien /* If we are creating a shared library, we must presume that the 180560484Sobrien only references to the symbol are via the global offset table. 180660484Sobrien For such cases we need not do anything here; the relocations will 180760484Sobrien be handled correctly by relocate_section. */ 180860484Sobrien if (info->shared) 180960484Sobrien return true; 181060484Sobrien 181160484Sobrien /* We must allocate the symbol in our .dynbss section, which will 181260484Sobrien become part of the .bss section of the executable. There will be 181360484Sobrien an entry for this symbol in the .dynsym section. The dynamic 181460484Sobrien object will contain position independent code, so all references 181560484Sobrien from the dynamic object to this symbol will go through the global 181660484Sobrien offset table. The dynamic linker will use the .dynsym entry to 181760484Sobrien determine the address it must put in the global offset table, so 181860484Sobrien both the dynamic object and the regular object will refer to the 181960484Sobrien same memory location for the variable. 182060484Sobrien 182160484Sobrien Of course, if the symbol is sufficiently small, we must instead 182260484Sobrien allocate it in .sbss. FIXME: It would be better to do this if and 182360484Sobrien only if there were actually SDAREL relocs for that symbol. */ 182460484Sobrien 182560484Sobrien if (h->size <= elf_gp_size (dynobj)) 182660484Sobrien s = bfd_get_section_by_name (dynobj, ".dynsbss"); 182760484Sobrien else 182860484Sobrien s = bfd_get_section_by_name (dynobj, ".dynbss"); 182960484Sobrien BFD_ASSERT (s != NULL); 183060484Sobrien 183160484Sobrien /* We must generate a R_PPC_COPY reloc to tell the dynamic linker to 183260484Sobrien copy the initial value out of the dynamic object and into the 183360484Sobrien runtime process image. We need to remember the offset into the 183460484Sobrien .rela.bss section we are going to use. */ 183560484Sobrien if ((h->root.u.def.section->flags & SEC_ALLOC) != 0) 183660484Sobrien { 183760484Sobrien asection *srel; 183860484Sobrien 183960484Sobrien if (h->size <= elf_gp_size (dynobj)) 184060484Sobrien srel = bfd_get_section_by_name (dynobj, ".rela.sbss"); 184160484Sobrien else 184260484Sobrien srel = bfd_get_section_by_name (dynobj, ".rela.bss"); 184360484Sobrien BFD_ASSERT (srel != NULL); 184460484Sobrien srel->_raw_size += sizeof (Elf32_External_Rela); 184560484Sobrien h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_COPY; 184660484Sobrien } 184760484Sobrien 184860484Sobrien /* We need to figure out the alignment required for this symbol. I 184960484Sobrien have no idea how ELF linkers handle this. */ 185060484Sobrien power_of_two = bfd_log2 (h->size); 185160484Sobrien if (power_of_two > 4) 185260484Sobrien power_of_two = 4; 185360484Sobrien 185460484Sobrien /* Apply the required alignment. */ 185560484Sobrien s->_raw_size = BFD_ALIGN (s->_raw_size, 185660484Sobrien (bfd_size_type) (1 << power_of_two)); 185760484Sobrien if (power_of_two > bfd_get_section_alignment (dynobj, s)) 185860484Sobrien { 185960484Sobrien if (! bfd_set_section_alignment (dynobj, s, power_of_two)) 186060484Sobrien return false; 186160484Sobrien } 186260484Sobrien 186360484Sobrien /* Define the symbol as being at this point in the section. */ 186460484Sobrien h->root.u.def.section = s; 186560484Sobrien h->root.u.def.value = s->_raw_size; 186660484Sobrien 186760484Sobrien /* Increment the section size to make room for the symbol. */ 186860484Sobrien s->_raw_size += h->size; 186960484Sobrien 187060484Sobrien return true; 187160484Sobrien} 187260484Sobrien 187360484Sobrien/* Set the sizes of the dynamic sections. */ 187460484Sobrien 187560484Sobrienstatic boolean 187660484Sobrienppc_elf_size_dynamic_sections (output_bfd, info) 187760484Sobrien bfd *output_bfd; 187860484Sobrien struct bfd_link_info *info; 187960484Sobrien{ 188060484Sobrien bfd *dynobj; 188160484Sobrien asection *s; 188260484Sobrien boolean plt; 188360484Sobrien boolean relocs; 188460484Sobrien boolean reltext; 188560484Sobrien 188660484Sobrien#ifdef DEBUG 188760484Sobrien fprintf (stderr, "ppc_elf_size_dynamic_sections called\n"); 188860484Sobrien#endif 188960484Sobrien 189060484Sobrien dynobj = elf_hash_table (info)->dynobj; 189160484Sobrien BFD_ASSERT (dynobj != NULL); 189260484Sobrien 189360484Sobrien if (elf_hash_table (info)->dynamic_sections_created) 189460484Sobrien { 189560484Sobrien /* Set the contents of the .interp section to the interpreter. */ 189660484Sobrien if (! info->shared) 189760484Sobrien { 189860484Sobrien s = bfd_get_section_by_name (dynobj, ".interp"); 189960484Sobrien BFD_ASSERT (s != NULL); 190060484Sobrien s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER; 190160484Sobrien s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER; 190260484Sobrien } 190360484Sobrien } 190460484Sobrien else 190560484Sobrien { 190660484Sobrien /* We may have created entries in the .rela.got, .rela.sdata, and 190760484Sobrien .rela.sdata2 sections. However, if we are not creating the 190860484Sobrien dynamic sections, we will not actually use these entries. Reset 190960484Sobrien the size of .rela.got, et al, which will cause it to get 191060484Sobrien stripped from the output file below. */ 191160484Sobrien static char *rela_sections[] = { ".rela.got", ".rela.sdata", 191260484Sobrien ".rela.sdata2", ".rela.sbss", 191377298Sobrien (char *) 0 }; 191460484Sobrien char **p; 191560484Sobrien 191677298Sobrien for (p = rela_sections; *p != (char *) 0; p++) 191760484Sobrien { 191860484Sobrien s = bfd_get_section_by_name (dynobj, *p); 191960484Sobrien if (s != NULL) 192060484Sobrien s->_raw_size = 0; 192160484Sobrien } 192260484Sobrien } 192360484Sobrien 192460484Sobrien /* The check_relocs and adjust_dynamic_symbol entry points have 192560484Sobrien determined the sizes of the various dynamic sections. Allocate 192660484Sobrien memory for them. */ 192760484Sobrien plt = false; 192860484Sobrien relocs = false; 192960484Sobrien reltext = false; 193060484Sobrien for (s = dynobj->sections; s != NULL; s = s->next) 193160484Sobrien { 193260484Sobrien const char *name; 193360484Sobrien boolean strip; 193460484Sobrien 193560484Sobrien if ((s->flags & SEC_LINKER_CREATED) == 0) 193660484Sobrien continue; 193760484Sobrien 193860484Sobrien /* It's OK to base decisions on the section name, because none 193960484Sobrien of the dynobj section names depend upon the input files. */ 194060484Sobrien name = bfd_get_section_name (dynobj, s); 194160484Sobrien 194260484Sobrien strip = false; 194360484Sobrien 194460484Sobrien if (strcmp (name, ".plt") == 0) 194560484Sobrien { 194660484Sobrien if (s->_raw_size == 0) 194760484Sobrien { 194860484Sobrien /* Strip this section if we don't need it; see the 194960484Sobrien comment below. */ 195060484Sobrien strip = true; 195160484Sobrien } 195260484Sobrien else 195360484Sobrien { 195460484Sobrien /* Remember whether there is a PLT. */ 195560484Sobrien plt = true; 195660484Sobrien } 195760484Sobrien } 195860484Sobrien else if (strncmp (name, ".rela", 5) == 0) 195960484Sobrien { 196060484Sobrien if (s->_raw_size == 0) 196160484Sobrien { 196260484Sobrien /* If we don't need this section, strip it from the 196360484Sobrien output file. This is mostly to handle .rela.bss and 196460484Sobrien .rela.plt. We must create both sections in 196560484Sobrien create_dynamic_sections, because they must be created 196660484Sobrien before the linker maps input sections to output 196760484Sobrien sections. The linker does that before 196860484Sobrien adjust_dynamic_symbol is called, and it is that 196960484Sobrien function which decides whether anything needs to go 197060484Sobrien into these sections. */ 197160484Sobrien strip = true; 197260484Sobrien } 197360484Sobrien else 197460484Sobrien { 197560484Sobrien asection *target; 197660484Sobrien const char *outname; 197760484Sobrien 197877298Sobrien /* Remember whether there are any relocation sections. */ 197960484Sobrien relocs = true; 198060484Sobrien 198160484Sobrien /* If this relocation section applies to a read only 198260484Sobrien section, then we probably need a DT_TEXTREL entry. */ 198360484Sobrien outname = bfd_get_section_name (output_bfd, 198460484Sobrien s->output_section); 198560484Sobrien target = bfd_get_section_by_name (output_bfd, outname + 5); 198660484Sobrien if (target != NULL 198760484Sobrien && (target->flags & SEC_READONLY) != 0 198860484Sobrien && (target->flags & SEC_ALLOC) != 0) 198960484Sobrien reltext = true; 199060484Sobrien 199160484Sobrien /* We use the reloc_count field as a counter if we need 199260484Sobrien to copy relocs into the output file. */ 199360484Sobrien s->reloc_count = 0; 199460484Sobrien } 199560484Sobrien } 199660484Sobrien else if (strcmp (name, ".got") != 0 199760484Sobrien && strcmp (name, ".sdata") != 0 199860484Sobrien && strcmp (name, ".sdata2") != 0) 199960484Sobrien { 200060484Sobrien /* It's not one of our sections, so don't allocate space. */ 200160484Sobrien continue; 200260484Sobrien } 200360484Sobrien 200460484Sobrien if (strip) 200560484Sobrien { 200660484Sobrien _bfd_strip_section_from_output (info, s); 200760484Sobrien continue; 200860484Sobrien } 200960484Sobrien 201060484Sobrien /* Allocate memory for the section contents. */ 201160484Sobrien s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size); 201260484Sobrien if (s->contents == NULL && s->_raw_size != 0) 201360484Sobrien return false; 201460484Sobrien } 201560484Sobrien 201660484Sobrien if (elf_hash_table (info)->dynamic_sections_created) 201760484Sobrien { 201860484Sobrien /* Add some entries to the .dynamic section. We fill in the 201960484Sobrien values later, in ppc_elf_finish_dynamic_sections, but we 202060484Sobrien must add the entries now so that we get the correct size for 202160484Sobrien the .dynamic section. The DT_DEBUG entry is filled in by the 202260484Sobrien dynamic linker and used by the debugger. */ 202360484Sobrien if (! info->shared) 202460484Sobrien { 202560484Sobrien if (! bfd_elf32_add_dynamic_entry (info, DT_DEBUG, 0)) 202660484Sobrien return false; 202760484Sobrien } 202860484Sobrien 202960484Sobrien if (plt) 203060484Sobrien { 203160484Sobrien if (! bfd_elf32_add_dynamic_entry (info, DT_PLTGOT, 0) 203260484Sobrien || ! bfd_elf32_add_dynamic_entry (info, DT_PLTRELSZ, 0) 203360484Sobrien || ! bfd_elf32_add_dynamic_entry (info, DT_PLTREL, DT_RELA) 203460484Sobrien || ! bfd_elf32_add_dynamic_entry (info, DT_JMPREL, 0)) 203560484Sobrien return false; 203660484Sobrien } 203760484Sobrien 203860484Sobrien if (relocs) 203960484Sobrien { 204060484Sobrien if (! bfd_elf32_add_dynamic_entry (info, DT_RELA, 0) 204160484Sobrien || ! bfd_elf32_add_dynamic_entry (info, DT_RELASZ, 0) 204260484Sobrien || ! bfd_elf32_add_dynamic_entry (info, DT_RELAENT, 204360484Sobrien sizeof (Elf32_External_Rela))) 204460484Sobrien return false; 204560484Sobrien } 204660484Sobrien 204760484Sobrien if (reltext) 204860484Sobrien { 204960484Sobrien if (! bfd_elf32_add_dynamic_entry (info, DT_TEXTREL, 0)) 205060484Sobrien return false; 205177298Sobrien info->flags |= DF_TEXTREL; 205260484Sobrien } 205360484Sobrien } 205460484Sobrien 205560484Sobrien return true; 205660484Sobrien} 205760484Sobrien 205860484Sobrien/* Look through the relocs for a section during the first phase, and 205960484Sobrien allocate space in the global offset table or procedure linkage 206060484Sobrien table. */ 206160484Sobrien 206260484Sobrienstatic boolean 206360484Sobrienppc_elf_check_relocs (abfd, info, sec, relocs) 206460484Sobrien bfd *abfd; 206560484Sobrien struct bfd_link_info *info; 206660484Sobrien asection *sec; 206760484Sobrien const Elf_Internal_Rela *relocs; 206860484Sobrien{ 206960484Sobrien bfd *dynobj; 207060484Sobrien Elf_Internal_Shdr *symtab_hdr; 207160484Sobrien struct elf_link_hash_entry **sym_hashes, **sym_hashes_end; 207260484Sobrien const Elf_Internal_Rela *rel; 207360484Sobrien const Elf_Internal_Rela *rel_end; 207460484Sobrien bfd_signed_vma *local_got_refcounts; 207560484Sobrien elf_linker_section_t *sdata; 207660484Sobrien elf_linker_section_t *sdata2; 207760484Sobrien asection *sreloc; 207860484Sobrien asection *sgot = NULL; 207960484Sobrien asection *srelgot = NULL; 208060484Sobrien 208160484Sobrien if (info->relocateable) 208260484Sobrien return true; 208360484Sobrien 208460484Sobrien#ifdef DEBUG 208560484Sobrien fprintf (stderr, "ppc_elf_check_relocs called for section %s in %s\n", 208660484Sobrien bfd_get_section_name (abfd, sec), 208760484Sobrien bfd_get_filename (abfd)); 208860484Sobrien#endif 208960484Sobrien 209060484Sobrien /* Create the linker generated sections all the time so that the 209160484Sobrien special symbols are created. */ 209260484Sobrien 209360484Sobrien if ((sdata = elf_linker_section (abfd, LINKER_SECTION_SDATA)) == NULL) 209460484Sobrien { 209560484Sobrien sdata = ppc_elf_create_linker_section (abfd, info, LINKER_SECTION_SDATA); 209660484Sobrien if (!sdata) 209760484Sobrien return false; 209860484Sobrien } 209960484Sobrien 210060484Sobrien if ((sdata2 = elf_linker_section (abfd, LINKER_SECTION_SDATA2)) == NULL) 210160484Sobrien { 210260484Sobrien sdata2 = ppc_elf_create_linker_section (abfd, info, LINKER_SECTION_SDATA2); 210360484Sobrien if (!sdata2) 210460484Sobrien return false; 210560484Sobrien } 210660484Sobrien 210760484Sobrien dynobj = elf_hash_table (info)->dynobj; 210860484Sobrien symtab_hdr = &elf_tdata (abfd)->symtab_hdr; 210960484Sobrien local_got_refcounts = elf_local_got_refcounts (abfd); 211060484Sobrien 211160484Sobrien sym_hashes = elf_sym_hashes (abfd); 211277298Sobrien sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof (Elf32_External_Sym); 211360484Sobrien if (!elf_bad_symtab (abfd)) 211460484Sobrien sym_hashes_end -= symtab_hdr->sh_info; 211560484Sobrien 211660484Sobrien sreloc = NULL; 211760484Sobrien 211860484Sobrien rel_end = relocs + sec->reloc_count; 211960484Sobrien for (rel = relocs; rel < rel_end; rel++) 212060484Sobrien { 212160484Sobrien unsigned long r_symndx; 212260484Sobrien struct elf_link_hash_entry *h; 212360484Sobrien 212460484Sobrien r_symndx = ELF32_R_SYM (rel->r_info); 212560484Sobrien if (r_symndx < symtab_hdr->sh_info) 212660484Sobrien h = NULL; 212760484Sobrien else 212860484Sobrien h = sym_hashes[r_symndx - symtab_hdr->sh_info]; 212960484Sobrien 213060484Sobrien /* If a relocation refers to _GLOBAL_OFFSET_TABLE_, create the .got. 213160484Sobrien This shows up in particular in an R_PPC_ADDR32 in the eabi 213260484Sobrien startup code. */ 213360484Sobrien if (h && strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0) 213460484Sobrien { 213560484Sobrien if (sgot == NULL) 213660484Sobrien { 213760484Sobrien if (dynobj == NULL) 213860484Sobrien elf_hash_table (info)->dynobj = dynobj = abfd; 213960484Sobrien if (! _bfd_elf_create_got_section (dynobj, info)) 214060484Sobrien return false; 214160484Sobrien sgot = bfd_get_section_by_name (dynobj, ".got"); 214260484Sobrien BFD_ASSERT (sgot != NULL); 214360484Sobrien } 214460484Sobrien } 214560484Sobrien 214660484Sobrien switch (ELF32_R_TYPE (rel->r_info)) 214760484Sobrien { 214860484Sobrien /* GOT16 relocations */ 214960484Sobrien case R_PPC_GOT16: 215060484Sobrien case R_PPC_GOT16_LO: 215160484Sobrien case R_PPC_GOT16_HI: 215260484Sobrien case R_PPC_GOT16_HA: 215360484Sobrien /* This symbol requires a global offset table entry. */ 215460484Sobrien 215560484Sobrien if (sgot == NULL) 215660484Sobrien { 215760484Sobrien if (dynobj == NULL) 215860484Sobrien elf_hash_table (info)->dynobj = dynobj = abfd; 215960484Sobrien if (! _bfd_elf_create_got_section (dynobj, info)) 216060484Sobrien return false; 216160484Sobrien sgot = bfd_get_section_by_name (dynobj, ".got"); 216260484Sobrien BFD_ASSERT (sgot != NULL); 216360484Sobrien } 216460484Sobrien 216560484Sobrien if (srelgot == NULL 216660484Sobrien && (h != NULL || info->shared)) 216760484Sobrien { 216860484Sobrien srelgot = bfd_get_section_by_name (dynobj, ".rela.got"); 216960484Sobrien if (srelgot == NULL) 217060484Sobrien { 217160484Sobrien srelgot = bfd_make_section (dynobj, ".rela.got"); 217260484Sobrien if (srelgot == NULL 217360484Sobrien || ! bfd_set_section_flags (dynobj, srelgot, 217460484Sobrien (SEC_ALLOC 217560484Sobrien | SEC_LOAD 217660484Sobrien | SEC_HAS_CONTENTS 217760484Sobrien | SEC_IN_MEMORY 217860484Sobrien | SEC_LINKER_CREATED 217960484Sobrien | SEC_READONLY)) 218060484Sobrien || ! bfd_set_section_alignment (dynobj, srelgot, 2)) 218160484Sobrien return false; 218260484Sobrien } 218360484Sobrien } 218460484Sobrien 218560484Sobrien if (h != NULL) 218660484Sobrien { 218760484Sobrien if (h->got.refcount == -1) 218860484Sobrien { 218960484Sobrien /* Make sure this symbol is output as a dynamic symbol. */ 219060484Sobrien if (h->dynindx == -1) 219160484Sobrien if (!bfd_elf32_link_record_dynamic_symbol (info, h)) 219260484Sobrien return false; 219360484Sobrien 219460484Sobrien /* Allocate space in the .got. */ 219560484Sobrien sgot->_raw_size += 4; 219660484Sobrien /* Allocate relocation space. */ 219760484Sobrien srelgot->_raw_size += sizeof (Elf32_External_Rela); 219860484Sobrien 219960484Sobrien h->got.refcount = 1; 220060484Sobrien } 220160484Sobrien else 220260484Sobrien h->got.refcount++; 220360484Sobrien } 220460484Sobrien else 220560484Sobrien { 220660484Sobrien /* This is a global offset table entry for a local symbol. */ 220760484Sobrien if (local_got_refcounts == NULL) 220860484Sobrien { 220960484Sobrien size_t size; 221060484Sobrien 221160484Sobrien size = symtab_hdr->sh_info * sizeof (bfd_signed_vma); 221260484Sobrien local_got_refcounts = (bfd_signed_vma *) 221360484Sobrien bfd_alloc (abfd, size); 221460484Sobrien if (local_got_refcounts == NULL) 221560484Sobrien return false; 221660484Sobrien elf_local_got_refcounts (abfd) = local_got_refcounts; 221760484Sobrien memset (local_got_refcounts, -1, size); 221860484Sobrien } 221960484Sobrien if (local_got_refcounts[r_symndx] == -1) 222060484Sobrien { 222160484Sobrien sgot->_raw_size += 4; 222260484Sobrien 222360484Sobrien /* If we are generating a shared object, we need to 222460484Sobrien output a R_PPC_RELATIVE reloc so that the 222560484Sobrien dynamic linker can adjust this GOT entry. */ 222660484Sobrien if (info->shared) 222760484Sobrien srelgot->_raw_size += sizeof (Elf32_External_Rela); 222860484Sobrien 222960484Sobrien local_got_refcounts[r_symndx] = 1; 223060484Sobrien } 223160484Sobrien else 223260484Sobrien local_got_refcounts[r_symndx]++; 223360484Sobrien } 223460484Sobrien break; 223560484Sobrien 223660484Sobrien /* Indirect .sdata relocation */ 223760484Sobrien case R_PPC_EMB_SDAI16: 223860484Sobrien if (info->shared) 223960484Sobrien { 224060484Sobrien ((*_bfd_error_handler) 224160484Sobrien (_("%s: relocation %s cannot be used when making a shared object"), 224260484Sobrien bfd_get_filename (abfd), "R_PPC_EMB_SDAI16")); 224377298Sobrien return false; 224460484Sobrien } 224560484Sobrien 224660484Sobrien if (srelgot == NULL && (h != NULL || info->shared)) 224760484Sobrien { 224860484Sobrien srelgot = bfd_get_section_by_name (dynobj, ".rela.got"); 224960484Sobrien if (srelgot == NULL) 225060484Sobrien { 225160484Sobrien srelgot = bfd_make_section (dynobj, ".rela.got"); 225260484Sobrien if (srelgot == NULL 225360484Sobrien || ! bfd_set_section_flags (dynobj, srelgot, 225460484Sobrien (SEC_ALLOC 225560484Sobrien | SEC_LOAD 225660484Sobrien | SEC_HAS_CONTENTS 225760484Sobrien | SEC_IN_MEMORY 225860484Sobrien | SEC_LINKER_CREATED 225960484Sobrien | SEC_READONLY)) 226060484Sobrien || ! bfd_set_section_alignment (dynobj, srelgot, 2)) 226160484Sobrien return false; 226260484Sobrien } 226360484Sobrien } 226460484Sobrien 226560484Sobrien if (!bfd_elf32_create_pointer_linker_section (abfd, info, sdata, h, rel)) 226660484Sobrien return false; 226760484Sobrien 226860484Sobrien break; 226960484Sobrien 227060484Sobrien /* Indirect .sdata2 relocation */ 227160484Sobrien case R_PPC_EMB_SDA2I16: 227260484Sobrien if (info->shared) 227360484Sobrien { 227460484Sobrien ((*_bfd_error_handler) 227560484Sobrien (_("%s: relocation %s cannot be used when making a shared object"), 227660484Sobrien bfd_get_filename (abfd), "R_PPC_EMB_SDA2I16")); 227760484Sobrien return false; 227860484Sobrien } 227960484Sobrien 228060484Sobrien if (srelgot == NULL && (h != NULL || info->shared)) 228160484Sobrien { 228260484Sobrien srelgot = bfd_get_section_by_name (dynobj, ".rela.got"); 228360484Sobrien if (srelgot == NULL) 228460484Sobrien { 228560484Sobrien srelgot = bfd_make_section (dynobj, ".rela.got"); 228660484Sobrien if (srelgot == NULL 228760484Sobrien || ! bfd_set_section_flags (dynobj, srelgot, 228860484Sobrien (SEC_ALLOC 228960484Sobrien | SEC_LOAD 229060484Sobrien | SEC_HAS_CONTENTS 229160484Sobrien | SEC_IN_MEMORY 229260484Sobrien | SEC_LINKER_CREATED 229360484Sobrien | SEC_READONLY)) 229460484Sobrien || ! bfd_set_section_alignment (dynobj, srelgot, 2)) 229560484Sobrien return false; 229660484Sobrien } 229760484Sobrien } 229860484Sobrien 229960484Sobrien if (!bfd_elf32_create_pointer_linker_section (abfd, info, sdata2, h, rel)) 230060484Sobrien return false; 230160484Sobrien 230260484Sobrien break; 230360484Sobrien 230460484Sobrien case R_PPC_SDAREL16: 230560484Sobrien case R_PPC_EMB_SDA2REL: 230660484Sobrien case R_PPC_EMB_SDA21: 230760484Sobrien if (info->shared) 230860484Sobrien { 230960484Sobrien ((*_bfd_error_handler) 231060484Sobrien (_("%s: relocation %s cannot be used when making a shared object"), 231160484Sobrien bfd_get_filename (abfd), 231277298Sobrien ppc_elf_howto_table[(int) ELF32_R_TYPE (rel->r_info)]->name)); 231360484Sobrien return false; 231460484Sobrien } 231560484Sobrien break; 231660484Sobrien 231760484Sobrien case R_PPC_PLT32: 231860484Sobrien case R_PPC_PLTREL24: 231960484Sobrien case R_PPC_PLT16_LO: 232060484Sobrien case R_PPC_PLT16_HI: 232160484Sobrien case R_PPC_PLT16_HA: 232260484Sobrien#ifdef DEBUG 232360484Sobrien fprintf (stderr, "Reloc requires a PLT entry\n"); 232460484Sobrien#endif 232560484Sobrien /* This symbol requires a procedure linkage table entry. We 232660484Sobrien actually build the entry in adjust_dynamic_symbol, 232760484Sobrien because this might be a case of linking PIC code without 232860484Sobrien linking in any dynamic objects, in which case we don't 232960484Sobrien need to generate a procedure linkage table after all. */ 233060484Sobrien 233160484Sobrien if (h == NULL) 233260484Sobrien { 233360484Sobrien /* It does not make sense to have a procedure linkage 233460484Sobrien table entry for a local symbol. */ 233560484Sobrien bfd_set_error (bfd_error_bad_value); 233660484Sobrien return false; 233760484Sobrien } 233860484Sobrien 233960484Sobrien /* Make sure this symbol is output as a dynamic symbol. */ 234060484Sobrien if (h->dynindx == -1) 234160484Sobrien { 234260484Sobrien if (! bfd_elf32_link_record_dynamic_symbol (info, h)) 234360484Sobrien return false; 234460484Sobrien } 234560484Sobrien if (h->plt.refcount == -1) 234660484Sobrien { 234760484Sobrien h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; 234860484Sobrien h->plt.refcount = 1; 234960484Sobrien } 235060484Sobrien else 235160484Sobrien h->plt.refcount++; 235260484Sobrien break; 235360484Sobrien 235460484Sobrien /* The following relocations don't need to propagate the 235560484Sobrien relocation if linking a shared object since they are 235660484Sobrien section relative. */ 235760484Sobrien case R_PPC_SECTOFF: 235860484Sobrien case R_PPC_SECTOFF_LO: 235960484Sobrien case R_PPC_SECTOFF_HI: 236060484Sobrien case R_PPC_SECTOFF_HA: 236160484Sobrien break; 236260484Sobrien 236360484Sobrien /* This refers only to functions defined in the shared library */ 236460484Sobrien case R_PPC_LOCAL24PC: 236560484Sobrien break; 236660484Sobrien 236760484Sobrien /* This relocation describes the C++ object vtable hierarchy. 236860484Sobrien Reconstruct it for later use during GC. */ 236960484Sobrien case R_PPC_GNU_VTINHERIT: 237060484Sobrien if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) 237160484Sobrien return false; 237260484Sobrien break; 237360484Sobrien 237460484Sobrien /* This relocation describes which C++ vtable entries are actually 237560484Sobrien used. Record for later use during GC. */ 237660484Sobrien case R_PPC_GNU_VTENTRY: 237760484Sobrien if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend)) 237860484Sobrien return false; 237960484Sobrien break; 238060484Sobrien 238160484Sobrien /* When creating a shared object, we must copy these 238260484Sobrien relocs into the output file. We create a reloc 238360484Sobrien section in dynobj and make room for the reloc. */ 238460484Sobrien case R_PPC_REL24: 238560484Sobrien case R_PPC_REL14: 238660484Sobrien case R_PPC_REL14_BRTAKEN: 238760484Sobrien case R_PPC_REL14_BRNTAKEN: 238860484Sobrien case R_PPC_REL32: 238960484Sobrien if (h == NULL 239077298Sobrien || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0 239177298Sobrien || SYMBOL_REFERENCES_LOCAL (info, h)) 239260484Sobrien break; 239360484Sobrien /* fall through */ 239460484Sobrien 239560484Sobrien default: 239660484Sobrien if (info->shared) 239760484Sobrien { 239860484Sobrien#ifdef DEBUG 239960484Sobrien fprintf (stderr, "ppc_elf_check_relocs need to create relocation for %s\n", 240060484Sobrien (h && h->root.root.string) ? h->root.root.string : "<unknown>"); 240160484Sobrien#endif 240260484Sobrien if (sreloc == NULL) 240360484Sobrien { 240460484Sobrien const char *name; 240560484Sobrien 240660484Sobrien name = (bfd_elf_string_from_elf_section 240760484Sobrien (abfd, 240860484Sobrien elf_elfheader (abfd)->e_shstrndx, 240960484Sobrien elf_section_data (sec)->rel_hdr.sh_name)); 241060484Sobrien if (name == NULL) 241160484Sobrien return false; 241260484Sobrien 241360484Sobrien BFD_ASSERT (strncmp (name, ".rela", 5) == 0 241460484Sobrien && strcmp (bfd_get_section_name (abfd, sec), 241560484Sobrien name + 5) == 0); 241660484Sobrien 241760484Sobrien sreloc = bfd_get_section_by_name (dynobj, name); 241860484Sobrien if (sreloc == NULL) 241960484Sobrien { 242060484Sobrien flagword flags; 242160484Sobrien 242260484Sobrien sreloc = bfd_make_section (dynobj, name); 242360484Sobrien flags = (SEC_HAS_CONTENTS | SEC_READONLY 242460484Sobrien | SEC_IN_MEMORY | SEC_LINKER_CREATED); 242560484Sobrien if ((sec->flags & SEC_ALLOC) != 0) 242660484Sobrien flags |= SEC_ALLOC | SEC_LOAD; 242760484Sobrien if (sreloc == NULL 242860484Sobrien || ! bfd_set_section_flags (dynobj, sreloc, flags) 242960484Sobrien || ! bfd_set_section_alignment (dynobj, sreloc, 2)) 243060484Sobrien return false; 243160484Sobrien } 243260484Sobrien } 243360484Sobrien 243460484Sobrien sreloc->_raw_size += sizeof (Elf32_External_Rela); 243560484Sobrien 243660484Sobrien /* FIXME: We should here do what the m68k and i386 243760484Sobrien backends do: if the reloc is pc-relative, record it 243860484Sobrien in case it turns out that the reloc is unnecessary 243960484Sobrien because the symbol is forced local by versioning or 244060484Sobrien we are linking with -Bdynamic. Fortunately this 244160484Sobrien case is not frequent. */ 244260484Sobrien } 244360484Sobrien 244460484Sobrien break; 244560484Sobrien } 244660484Sobrien } 244760484Sobrien 244860484Sobrien return true; 244960484Sobrien} 245060484Sobrien 245160484Sobrien/* Return the section that should be marked against GC for a given 245260484Sobrien relocation. */ 245360484Sobrien 245460484Sobrienstatic asection * 245560484Sobrienppc_elf_gc_mark_hook (abfd, info, rel, h, sym) 245660484Sobrien bfd *abfd; 245760484Sobrien struct bfd_link_info *info ATTRIBUTE_UNUSED; 245860484Sobrien Elf_Internal_Rela *rel; 245960484Sobrien struct elf_link_hash_entry *h; 246060484Sobrien Elf_Internal_Sym *sym; 246160484Sobrien{ 246260484Sobrien if (h != NULL) 246360484Sobrien { 246460484Sobrien switch (ELF32_R_TYPE (rel->r_info)) 246560484Sobrien { 246660484Sobrien case R_PPC_GNU_VTINHERIT: 246760484Sobrien case R_PPC_GNU_VTENTRY: 246860484Sobrien break; 246960484Sobrien 247060484Sobrien default: 247160484Sobrien switch (h->root.type) 247260484Sobrien { 247360484Sobrien case bfd_link_hash_defined: 247460484Sobrien case bfd_link_hash_defweak: 247560484Sobrien return h->root.u.def.section; 247660484Sobrien 247760484Sobrien case bfd_link_hash_common: 247860484Sobrien return h->root.u.c.p->section; 247960484Sobrien 248060484Sobrien default: 248160484Sobrien break; 248260484Sobrien } 248360484Sobrien } 248460484Sobrien } 248560484Sobrien else 248660484Sobrien { 248760484Sobrien if (!(elf_bad_symtab (abfd) 248860484Sobrien && ELF_ST_BIND (sym->st_info) != STB_LOCAL) 248960484Sobrien && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE) 249060484Sobrien && sym->st_shndx != SHN_COMMON)) 249160484Sobrien { 249260484Sobrien return bfd_section_from_elf_index (abfd, sym->st_shndx); 249360484Sobrien } 249460484Sobrien } 249560484Sobrien 249660484Sobrien return NULL; 249760484Sobrien} 249860484Sobrien 249960484Sobrien/* Update the got entry reference counts for the section being removed. */ 250060484Sobrien 250160484Sobrienstatic boolean 250260484Sobrienppc_elf_gc_sweep_hook (abfd, info, sec, relocs) 250360484Sobrien bfd *abfd; 250460484Sobrien struct bfd_link_info *info ATTRIBUTE_UNUSED; 250560484Sobrien asection *sec; 250660484Sobrien const Elf_Internal_Rela *relocs; 250760484Sobrien{ 250860484Sobrien Elf_Internal_Shdr *symtab_hdr; 250960484Sobrien struct elf_link_hash_entry **sym_hashes; 251060484Sobrien bfd_signed_vma *local_got_refcounts; 251160484Sobrien const Elf_Internal_Rela *rel, *relend; 251260484Sobrien unsigned long r_symndx; 251360484Sobrien struct elf_link_hash_entry *h; 251460484Sobrien 251560484Sobrien symtab_hdr = &elf_tdata (abfd)->symtab_hdr; 251660484Sobrien sym_hashes = elf_sym_hashes (abfd); 251760484Sobrien local_got_refcounts = elf_local_got_refcounts (abfd); 251860484Sobrien 251960484Sobrien relend = relocs + sec->reloc_count; 252060484Sobrien for (rel = relocs; rel < relend; rel++) 252160484Sobrien switch (ELF32_R_TYPE (rel->r_info)) 252260484Sobrien { 252360484Sobrien case R_PPC_GOT16: 252460484Sobrien case R_PPC_GOT16_LO: 252560484Sobrien case R_PPC_GOT16_HI: 252660484Sobrien case R_PPC_GOT16_HA: 252760484Sobrien r_symndx = ELF32_R_SYM (rel->r_info); 252860484Sobrien if (r_symndx >= symtab_hdr->sh_info) 252960484Sobrien { 253060484Sobrien h = sym_hashes[r_symndx - symtab_hdr->sh_info]; 253160484Sobrien if (h->got.refcount > 0) 253260484Sobrien h->got.refcount--; 253360484Sobrien } 253477298Sobrien else if (local_got_refcounts != NULL) 253560484Sobrien { 253660484Sobrien if (local_got_refcounts[r_symndx] > 0) 253760484Sobrien local_got_refcounts[r_symndx]--; 253860484Sobrien } 253960484Sobrien break; 254060484Sobrien 254160484Sobrien case R_PPC_PLT32: 254260484Sobrien case R_PPC_PLTREL24: 254360484Sobrien case R_PPC_PLT16_LO: 254460484Sobrien case R_PPC_PLT16_HI: 254560484Sobrien case R_PPC_PLT16_HA: 254660484Sobrien r_symndx = ELF32_R_SYM (rel->r_info); 254760484Sobrien if (r_symndx >= symtab_hdr->sh_info) 254860484Sobrien { 254960484Sobrien h = sym_hashes[r_symndx - symtab_hdr->sh_info]; 255060484Sobrien if (h->plt.refcount > 0) 255160484Sobrien h->plt.refcount--; 255260484Sobrien } 255360484Sobrien break; 255460484Sobrien 255560484Sobrien default: 255660484Sobrien break; 255760484Sobrien } 255860484Sobrien 255960484Sobrien return true; 256060484Sobrien} 256160484Sobrien 256260484Sobrien/* Hook called by the linker routine which adds symbols from an object 256360484Sobrien file. We use it to put .comm items in .sbss, and not .bss. */ 256460484Sobrien 256560484Sobrienstatic boolean 256660484Sobrienppc_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp) 256760484Sobrien bfd *abfd; 256860484Sobrien struct bfd_link_info *info; 256960484Sobrien const Elf_Internal_Sym *sym; 257060484Sobrien const char **namep ATTRIBUTE_UNUSED; 257160484Sobrien flagword *flagsp ATTRIBUTE_UNUSED; 257260484Sobrien asection **secp; 257360484Sobrien bfd_vma *valp; 257460484Sobrien{ 257560484Sobrien if (sym->st_shndx == SHN_COMMON 257660484Sobrien && !info->relocateable 257760484Sobrien && sym->st_size <= (bfd_vma) bfd_get_gp_size (abfd)) 257860484Sobrien { 257960484Sobrien /* Common symbols less than or equal to -G nn bytes are automatically 258060484Sobrien put into .sdata. */ 258160484Sobrien elf_linker_section_t *sdata 258260484Sobrien = ppc_elf_create_linker_section (abfd, info, LINKER_SECTION_SDATA); 258360484Sobrien 258460484Sobrien if (!sdata->bss_section) 258560484Sobrien { 258660484Sobrien /* We don't go through bfd_make_section, because we don't 258760484Sobrien want to attach this common section to DYNOBJ. The linker 258860484Sobrien will move the symbols to the appropriate output section 258960484Sobrien when it defines common symbols. */ 259060484Sobrien sdata->bss_section = ((asection *) 259160484Sobrien bfd_zalloc (abfd, sizeof (asection))); 259260484Sobrien if (sdata->bss_section == NULL) 259360484Sobrien return false; 259460484Sobrien sdata->bss_section->name = sdata->bss_name; 259560484Sobrien sdata->bss_section->flags = SEC_IS_COMMON; 259660484Sobrien sdata->bss_section->output_section = sdata->bss_section; 259760484Sobrien sdata->bss_section->symbol = 259860484Sobrien (asymbol *) bfd_zalloc (abfd, sizeof (asymbol)); 259960484Sobrien sdata->bss_section->symbol_ptr_ptr = 260060484Sobrien (asymbol **) bfd_zalloc (abfd, sizeof (asymbol *)); 260160484Sobrien if (sdata->bss_section->symbol == NULL 260260484Sobrien || sdata->bss_section->symbol_ptr_ptr == NULL) 260360484Sobrien return false; 260460484Sobrien sdata->bss_section->symbol->name = sdata->bss_name; 260560484Sobrien sdata->bss_section->symbol->flags = BSF_SECTION_SYM; 260660484Sobrien sdata->bss_section->symbol->section = sdata->bss_section; 260760484Sobrien *sdata->bss_section->symbol_ptr_ptr = sdata->bss_section->symbol; 260860484Sobrien } 260960484Sobrien 261060484Sobrien *secp = sdata->bss_section; 261160484Sobrien *valp = sym->st_size; 261260484Sobrien } 261360484Sobrien 261460484Sobrien return true; 261560484Sobrien} 261660484Sobrien 261760484Sobrien/* Finish up dynamic symbol handling. We set the contents of various 261860484Sobrien dynamic sections here. */ 261960484Sobrien 262060484Sobrienstatic boolean 262160484Sobrienppc_elf_finish_dynamic_symbol (output_bfd, info, h, sym) 262260484Sobrien bfd *output_bfd; 262360484Sobrien struct bfd_link_info *info; 262460484Sobrien struct elf_link_hash_entry *h; 262560484Sobrien Elf_Internal_Sym *sym; 262660484Sobrien{ 262760484Sobrien bfd *dynobj; 262860484Sobrien 262960484Sobrien#ifdef DEBUG 263060484Sobrien fprintf (stderr, "ppc_elf_finish_dynamic_symbol called for %s", 263160484Sobrien h->root.root.string); 263260484Sobrien#endif 263360484Sobrien 263460484Sobrien dynobj = elf_hash_table (info)->dynobj; 263560484Sobrien BFD_ASSERT (dynobj != NULL); 263660484Sobrien 263760484Sobrien if (h->plt.offset != (bfd_vma) -1) 263860484Sobrien { 263960484Sobrien asection *splt; 264060484Sobrien asection *srela; 264160484Sobrien Elf_Internal_Rela rela; 264260484Sobrien bfd_vma reloc_index; 264360484Sobrien 264460484Sobrien#ifdef DEBUG 264560484Sobrien fprintf (stderr, ", plt_offset = %d", h->plt.offset); 264660484Sobrien#endif 264760484Sobrien 264860484Sobrien /* This symbol has an entry in the procedure linkage table. Set 264960484Sobrien it up. */ 265060484Sobrien 265160484Sobrien BFD_ASSERT (h->dynindx != -1); 265260484Sobrien 265360484Sobrien splt = bfd_get_section_by_name (dynobj, ".plt"); 265460484Sobrien srela = bfd_get_section_by_name (dynobj, ".rela.plt"); 265560484Sobrien BFD_ASSERT (splt != NULL && srela != NULL); 265660484Sobrien 265760484Sobrien /* We don't need to fill in the .plt. The ppc dynamic linker 265860484Sobrien will fill it in. */ 265960484Sobrien 266060484Sobrien /* Fill in the entry in the .rela.plt section. */ 266160484Sobrien rela.r_offset = (splt->output_section->vma 266260484Sobrien + splt->output_offset 266360484Sobrien + h->plt.offset); 266460484Sobrien rela.r_info = ELF32_R_INFO (h->dynindx, R_PPC_JMP_SLOT); 266560484Sobrien rela.r_addend = 0; 266660484Sobrien 266760484Sobrien reloc_index = (h->plt.offset - PLT_INITIAL_ENTRY_SIZE) / PLT_SLOT_SIZE; 266860484Sobrien if (reloc_index > PLT_NUM_SINGLE_ENTRIES) 266960484Sobrien reloc_index -= (reloc_index - PLT_NUM_SINGLE_ENTRIES) / 2; 267060484Sobrien bfd_elf32_swap_reloca_out (output_bfd, &rela, 267160484Sobrien ((Elf32_External_Rela *) srela->contents 267260484Sobrien + reloc_index)); 267360484Sobrien 267460484Sobrien if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) 267560484Sobrien { 267660484Sobrien /* Mark the symbol as undefined, rather than as defined in 267760484Sobrien the .plt section. Leave the value alone. */ 267860484Sobrien sym->st_shndx = SHN_UNDEF; 267968765Sobrien /* If the symbol is weak, we do need to clear the value. 268068765Sobrien Otherwise, the PLT entry would provide a definition for 268168765Sobrien the symbol even if the symbol wasn't defined anywhere, 268268765Sobrien and so the symbol would never be NULL. */ 268377298Sobrien if ((h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR_NONWEAK) 268468765Sobrien == 0) 268568765Sobrien sym->st_value = 0; 268660484Sobrien } 268760484Sobrien } 268860484Sobrien 268960484Sobrien if (h->got.offset != (bfd_vma) -1) 269060484Sobrien { 269160484Sobrien asection *sgot; 269260484Sobrien asection *srela; 269360484Sobrien Elf_Internal_Rela rela; 269460484Sobrien 269560484Sobrien /* This symbol has an entry in the global offset table. Set it 269660484Sobrien up. */ 269760484Sobrien 269860484Sobrien sgot = bfd_get_section_by_name (dynobj, ".got"); 269960484Sobrien srela = bfd_get_section_by_name (dynobj, ".rela.got"); 270060484Sobrien BFD_ASSERT (sgot != NULL && srela != NULL); 270160484Sobrien 270260484Sobrien rela.r_offset = (sgot->output_section->vma 270360484Sobrien + sgot->output_offset 270460484Sobrien + (h->got.offset &~ 1)); 270560484Sobrien 270660484Sobrien /* If this is a -Bsymbolic link, and the symbol is defined 270760484Sobrien locally, we just want to emit a RELATIVE reloc. The entry in 270860484Sobrien the global offset table will already have been initialized in 270960484Sobrien the relocate_section function. */ 271060484Sobrien if (info->shared 271177298Sobrien && SYMBOL_REFERENCES_LOCAL (info, h)) 271260484Sobrien { 271360484Sobrien rela.r_info = ELF32_R_INFO (0, R_PPC_RELATIVE); 271460484Sobrien rela.r_addend = (h->root.u.def.value 271560484Sobrien + h->root.u.def.section->output_section->vma 271660484Sobrien + h->root.u.def.section->output_offset); 271760484Sobrien } 271860484Sobrien else 271960484Sobrien { 272077298Sobrien BFD_ASSERT ((h->got.offset & 1) == 0); 272160484Sobrien bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + h->got.offset); 272260484Sobrien rela.r_info = ELF32_R_INFO (h->dynindx, R_PPC_GLOB_DAT); 272360484Sobrien rela.r_addend = 0; 272460484Sobrien } 272560484Sobrien 272660484Sobrien bfd_elf32_swap_reloca_out (output_bfd, &rela, 272760484Sobrien ((Elf32_External_Rela *) srela->contents 272860484Sobrien + srela->reloc_count)); 272960484Sobrien ++srela->reloc_count; 273060484Sobrien } 273160484Sobrien 273260484Sobrien if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_COPY) != 0) 273360484Sobrien { 273460484Sobrien asection *s; 273560484Sobrien Elf_Internal_Rela rela; 273660484Sobrien 273760484Sobrien /* This symbols needs a copy reloc. Set it up. */ 273860484Sobrien 273960484Sobrien#ifdef DEBUG 274060484Sobrien fprintf (stderr, ", copy"); 274160484Sobrien#endif 274260484Sobrien 274360484Sobrien BFD_ASSERT (h->dynindx != -1); 274460484Sobrien 274560484Sobrien if (h->size <= elf_gp_size (dynobj)) 274660484Sobrien s = bfd_get_section_by_name (h->root.u.def.section->owner, 274760484Sobrien ".rela.sbss"); 274860484Sobrien else 274960484Sobrien s = bfd_get_section_by_name (h->root.u.def.section->owner, 275060484Sobrien ".rela.bss"); 275160484Sobrien BFD_ASSERT (s != NULL); 275260484Sobrien 275360484Sobrien rela.r_offset = (h->root.u.def.value 275460484Sobrien + h->root.u.def.section->output_section->vma 275560484Sobrien + h->root.u.def.section->output_offset); 275660484Sobrien rela.r_info = ELF32_R_INFO (h->dynindx, R_PPC_COPY); 275760484Sobrien rela.r_addend = 0; 275860484Sobrien bfd_elf32_swap_reloca_out (output_bfd, &rela, 275960484Sobrien ((Elf32_External_Rela *) s->contents 276060484Sobrien + s->reloc_count)); 276160484Sobrien ++s->reloc_count; 276260484Sobrien } 276360484Sobrien 276460484Sobrien#ifdef DEBUG 276560484Sobrien fprintf (stderr, "\n"); 276660484Sobrien#endif 276760484Sobrien 276860484Sobrien /* Mark some specially defined symbols as absolute. */ 276960484Sobrien if (strcmp (h->root.root.string, "_DYNAMIC") == 0 277060484Sobrien || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0 277160484Sobrien || strcmp (h->root.root.string, "_PROCEDURE_LINKAGE_TABLE_") == 0) 277260484Sobrien sym->st_shndx = SHN_ABS; 277360484Sobrien 277460484Sobrien return true; 277560484Sobrien} 277660484Sobrien 277760484Sobrien/* Finish up the dynamic sections. */ 277860484Sobrien 277960484Sobrienstatic boolean 278060484Sobrienppc_elf_finish_dynamic_sections (output_bfd, info) 278160484Sobrien bfd *output_bfd; 278260484Sobrien struct bfd_link_info *info; 278360484Sobrien{ 278460484Sobrien asection *sdyn; 278560484Sobrien bfd *dynobj = elf_hash_table (info)->dynobj; 278660484Sobrien asection *sgot = bfd_get_section_by_name (dynobj, ".got"); 278760484Sobrien 278860484Sobrien#ifdef DEBUG 278960484Sobrien fprintf (stderr, "ppc_elf_finish_dynamic_sections called\n"); 279060484Sobrien#endif 279160484Sobrien 279260484Sobrien sdyn = bfd_get_section_by_name (dynobj, ".dynamic"); 279360484Sobrien 279460484Sobrien if (elf_hash_table (info)->dynamic_sections_created) 279560484Sobrien { 279660484Sobrien asection *splt; 279760484Sobrien Elf32_External_Dyn *dyncon, *dynconend; 279860484Sobrien 279960484Sobrien splt = bfd_get_section_by_name (dynobj, ".plt"); 280060484Sobrien BFD_ASSERT (splt != NULL && sdyn != NULL); 280160484Sobrien 280260484Sobrien dyncon = (Elf32_External_Dyn *) sdyn->contents; 280360484Sobrien dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->_raw_size); 280460484Sobrien for (; dyncon < dynconend; dyncon++) 280560484Sobrien { 280660484Sobrien Elf_Internal_Dyn dyn; 280760484Sobrien const char *name; 280860484Sobrien boolean size; 280960484Sobrien 281060484Sobrien bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn); 281160484Sobrien 281260484Sobrien switch (dyn.d_tag) 281360484Sobrien { 281460484Sobrien case DT_PLTGOT: name = ".plt"; size = false; break; 281560484Sobrien case DT_PLTRELSZ: name = ".rela.plt"; size = true; break; 281660484Sobrien case DT_JMPREL: name = ".rela.plt"; size = false; break; 281760484Sobrien default: name = NULL; size = false; break; 281860484Sobrien } 281960484Sobrien 282060484Sobrien if (name != NULL) 282160484Sobrien { 282260484Sobrien asection *s; 282360484Sobrien 282460484Sobrien s = bfd_get_section_by_name (output_bfd, name); 282560484Sobrien if (s == NULL) 282660484Sobrien dyn.d_un.d_val = 0; 282760484Sobrien else 282860484Sobrien { 282960484Sobrien if (! size) 283060484Sobrien dyn.d_un.d_ptr = s->vma; 283160484Sobrien else 283260484Sobrien { 283360484Sobrien if (s->_cooked_size != 0) 283460484Sobrien dyn.d_un.d_val = s->_cooked_size; 283560484Sobrien else 283660484Sobrien dyn.d_un.d_val = s->_raw_size; 283760484Sobrien } 283860484Sobrien } 283960484Sobrien bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); 284060484Sobrien } 284160484Sobrien } 284260484Sobrien } 284360484Sobrien 284460484Sobrien /* Add a blrl instruction at _GLOBAL_OFFSET_TABLE_-4 so that a function can 284560484Sobrien easily find the address of the _GLOBAL_OFFSET_TABLE_. */ 284660484Sobrien if (sgot) 284760484Sobrien { 284860484Sobrien unsigned char *contents = sgot->contents; 284960484Sobrien bfd_put_32 (output_bfd, 0x4e800021 /* blrl */, contents); 285060484Sobrien 285160484Sobrien if (sdyn == NULL) 285260484Sobrien bfd_put_32 (output_bfd, (bfd_vma) 0, contents+4); 285360484Sobrien else 285460484Sobrien bfd_put_32 (output_bfd, 285560484Sobrien sdyn->output_section->vma + sdyn->output_offset, 285660484Sobrien contents+4); 285760484Sobrien 285860484Sobrien elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4; 285960484Sobrien } 286060484Sobrien 286160484Sobrien return true; 286260484Sobrien} 286360484Sobrien 286460484Sobrien/* The RELOCATE_SECTION function is called by the ELF backend linker 286560484Sobrien to handle the relocations for a section. 286660484Sobrien 286760484Sobrien The relocs are always passed as Rela structures; if the section 286860484Sobrien actually uses Rel structures, the r_addend field will always be 286960484Sobrien zero. 287060484Sobrien 287160484Sobrien This function is responsible for adjust the section contents as 287260484Sobrien necessary, and (if using Rela relocs and generating a 287360484Sobrien relocateable output file) adjusting the reloc addend as 287460484Sobrien necessary. 287560484Sobrien 287660484Sobrien This function does not have to worry about setting the reloc 287760484Sobrien address or the reloc symbol index. 287860484Sobrien 287960484Sobrien LOCAL_SYMS is a pointer to the swapped in local symbols. 288060484Sobrien 288160484Sobrien LOCAL_SECTIONS is an array giving the section in the input file 288260484Sobrien corresponding to the st_shndx field of each local symbol. 288360484Sobrien 288460484Sobrien The global hash table entry for the global symbols can be found 288560484Sobrien via elf_sym_hashes (input_bfd). 288660484Sobrien 288760484Sobrien When generating relocateable output, this function must handle 288860484Sobrien STB_LOCAL/STT_SECTION symbols specially. The output symbol is 288960484Sobrien going to be the section symbol corresponding to the output 289060484Sobrien section, which means that the addend must be adjusted 289160484Sobrien accordingly. */ 289260484Sobrien 289360484Sobrienstatic boolean 289460484Sobrienppc_elf_relocate_section (output_bfd, info, input_bfd, input_section, 289560484Sobrien contents, relocs, local_syms, local_sections) 289660484Sobrien bfd *output_bfd; 289760484Sobrien struct bfd_link_info *info; 289860484Sobrien bfd *input_bfd; 289960484Sobrien asection *input_section; 290060484Sobrien bfd_byte *contents; 290160484Sobrien Elf_Internal_Rela *relocs; 290260484Sobrien Elf_Internal_Sym *local_syms; 290360484Sobrien asection **local_sections; 290460484Sobrien{ 290560484Sobrien Elf_Internal_Shdr *symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; 290660484Sobrien struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (input_bfd); 290760484Sobrien bfd *dynobj = elf_hash_table (info)->dynobj; 290860484Sobrien elf_linker_section_t *sdata = (dynobj) ? elf_linker_section (dynobj, LINKER_SECTION_SDATA) : NULL; 290960484Sobrien elf_linker_section_t *sdata2 = (dynobj) ? elf_linker_section (dynobj, LINKER_SECTION_SDATA2) : NULL; 291060484Sobrien Elf_Internal_Rela *rel = relocs; 291160484Sobrien Elf_Internal_Rela *relend = relocs + input_section->reloc_count; 291260484Sobrien asection *sreloc = NULL; 291360484Sobrien asection *splt; 291460484Sobrien asection *sgot; 291560484Sobrien bfd_vma *local_got_offsets; 291660484Sobrien boolean ret = true; 291760484Sobrien long insn; 291860484Sobrien 291960484Sobrien#ifdef DEBUG 292060484Sobrien fprintf (stderr, "ppc_elf_relocate_section called for %s section %s, %ld relocations%s\n", 292160484Sobrien bfd_get_filename (input_bfd), 292260484Sobrien bfd_section_name(input_bfd, input_section), 292377298Sobrien (long) input_section->reloc_count, 292460484Sobrien (info->relocateable) ? " (relocatable)" : ""); 292560484Sobrien#endif 292660484Sobrien 292777298Sobrien if (!ppc_elf_howto_table[R_PPC_ADDR32]) 292877298Sobrien /* Initialize howto table if needed. */ 292960484Sobrien ppc_elf_howto_init (); 293060484Sobrien 293160484Sobrien local_got_offsets = elf_local_got_offsets (input_bfd); 293260484Sobrien 293360484Sobrien splt = sgot = NULL; 293460484Sobrien if (dynobj != NULL) 293560484Sobrien { 293660484Sobrien splt = bfd_get_section_by_name (dynobj, ".plt"); 293760484Sobrien sgot = bfd_get_section_by_name (dynobj, ".got"); 293860484Sobrien } 293960484Sobrien 294060484Sobrien for (; rel < relend; rel++) 294160484Sobrien { 294260484Sobrien enum elf_ppc_reloc_type r_type = (enum elf_ppc_reloc_type)ELF32_R_TYPE (rel->r_info); 294360484Sobrien bfd_vma offset = rel->r_offset; 294460484Sobrien bfd_vma addend = rel->r_addend; 294560484Sobrien bfd_reloc_status_type r = bfd_reloc_other; 294677298Sobrien Elf_Internal_Sym *sym = (Elf_Internal_Sym *) 0; 294777298Sobrien asection *sec = (asection *) 0; 294877298Sobrien struct elf_link_hash_entry *h = (struct elf_link_hash_entry *) 0; 294977298Sobrien const char *sym_name = (const char *) 0; 295060484Sobrien reloc_howto_type *howto; 295160484Sobrien unsigned long r_symndx; 295260484Sobrien bfd_vma relocation; 295377298Sobrien int will_become_local; 295460484Sobrien 295560484Sobrien /* Unknown relocation handling */ 295677298Sobrien if ((unsigned) r_type >= (unsigned) R_PPC_max 295777298Sobrien || !ppc_elf_howto_table[(int) r_type]) 295860484Sobrien { 295960484Sobrien (*_bfd_error_handler) (_("%s: unknown relocation type %d"), 296060484Sobrien bfd_get_filename (input_bfd), 296177298Sobrien (int) r_type); 296260484Sobrien 296360484Sobrien bfd_set_error (bfd_error_bad_value); 296460484Sobrien ret = false; 296560484Sobrien continue; 296660484Sobrien } 296760484Sobrien 296877298Sobrien howto = ppc_elf_howto_table[(int) r_type]; 296960484Sobrien r_symndx = ELF32_R_SYM (rel->r_info); 297060484Sobrien 297160484Sobrien if (info->relocateable) 297260484Sobrien { 297360484Sobrien /* This is a relocateable link. We don't have to change 297460484Sobrien anything, unless the reloc is against a section symbol, 297560484Sobrien in which case we have to adjust according to where the 297660484Sobrien section symbol winds up in the output section. */ 297760484Sobrien if (r_symndx < symtab_hdr->sh_info) 297860484Sobrien { 297960484Sobrien sym = local_syms + r_symndx; 298077298Sobrien if ((unsigned) ELF_ST_TYPE (sym->st_info) == STT_SECTION) 298160484Sobrien { 298260484Sobrien sec = local_sections[r_symndx]; 298360484Sobrien addend = rel->r_addend += sec->output_offset + sym->st_value; 298460484Sobrien } 298560484Sobrien } 298660484Sobrien 298760484Sobrien#ifdef DEBUG 298860484Sobrien fprintf (stderr, "\ttype = %s (%d), symbol index = %ld, offset = %ld, addend = %ld\n", 298960484Sobrien howto->name, 299077298Sobrien (int) r_type, 299160484Sobrien r_symndx, 299277298Sobrien (long) offset, 299377298Sobrien (long) addend); 299460484Sobrien#endif 299560484Sobrien continue; 299660484Sobrien } 299760484Sobrien 299860484Sobrien /* This is a final link. */ 299960484Sobrien if (r_symndx < symtab_hdr->sh_info) 300060484Sobrien { 300160484Sobrien sym = local_syms + r_symndx; 300260484Sobrien sec = local_sections[r_symndx]; 300360484Sobrien sym_name = "<local symbol>"; 300460484Sobrien 300560484Sobrien relocation = (sec->output_section->vma 300660484Sobrien + sec->output_offset 300760484Sobrien + sym->st_value); 300877298Sobrien /* Relocs to local symbols are always resolved. */ 300977298Sobrien will_become_local = 1; 301060484Sobrien } 301160484Sobrien else 301260484Sobrien { 301360484Sobrien h = sym_hashes[r_symndx - symtab_hdr->sh_info]; 301460484Sobrien while (h->root.type == bfd_link_hash_indirect 301560484Sobrien || h->root.type == bfd_link_hash_warning) 301660484Sobrien h = (struct elf_link_hash_entry *) h->root.u.i.link; 301760484Sobrien sym_name = h->root.root.string; 301877298Sobrien 301977298Sobrien /* Can this relocation be resolved immediately? */ 302077298Sobrien will_become_local = SYMBOL_REFERENCES_LOCAL (info, h); 302177298Sobrien 302260484Sobrien if (h->root.type == bfd_link_hash_defined 302360484Sobrien || h->root.type == bfd_link_hash_defweak) 302460484Sobrien { 302560484Sobrien sec = h->root.u.def.section; 302677298Sobrien if (((r_type == R_PPC_PLT32 302777298Sobrien || r_type == R_PPC_PLTREL24) 302877298Sobrien && splt != NULL 302960484Sobrien && h->plt.offset != (bfd_vma) -1) 303060484Sobrien || (r_type == R_PPC_LOCAL24PC 303160484Sobrien && sec->output_section == NULL) 303260484Sobrien || ((r_type == R_PPC_GOT16 303360484Sobrien || r_type == R_PPC_GOT16_LO 303460484Sobrien || r_type == R_PPC_GOT16_HI 303560484Sobrien || r_type == R_PPC_GOT16_HA) 303660484Sobrien && elf_hash_table (info)->dynamic_sections_created 303777298Sobrien && (! info->shared || ! will_become_local)) 303860484Sobrien || (info->shared 303977298Sobrien && ! will_become_local 304060484Sobrien && ((input_section->flags & SEC_ALLOC) != 0 304160484Sobrien /* Testing SEC_DEBUGGING here may be wrong. 304260484Sobrien It's here to avoid a crash when 304360484Sobrien generating a shared library with DWARF 304460484Sobrien debugging information. */ 304577298Sobrien || ((input_section->flags & SEC_DEBUGGING) != 0 304677298Sobrien && (h->elf_link_hash_flags 304777298Sobrien & ELF_LINK_HASH_DEF_DYNAMIC) != 0)) 304860484Sobrien && (r_type == R_PPC_ADDR32 304960484Sobrien || r_type == R_PPC_ADDR24 305060484Sobrien || r_type == R_PPC_ADDR16 305160484Sobrien || r_type == R_PPC_ADDR16_LO 305260484Sobrien || r_type == R_PPC_ADDR16_HI 305360484Sobrien || r_type == R_PPC_ADDR16_HA 305460484Sobrien || r_type == R_PPC_ADDR14 305560484Sobrien || r_type == R_PPC_ADDR14_BRTAKEN 305660484Sobrien || r_type == R_PPC_ADDR14_BRNTAKEN 305760484Sobrien || r_type == R_PPC_COPY 305860484Sobrien || r_type == R_PPC_GLOB_DAT 305960484Sobrien || r_type == R_PPC_JMP_SLOT 306060484Sobrien || r_type == R_PPC_UADDR32 306160484Sobrien || r_type == R_PPC_UADDR16 306260484Sobrien || r_type == R_PPC_SDAREL16 306360484Sobrien || r_type == R_PPC_EMB_NADDR32 306460484Sobrien || r_type == R_PPC_EMB_NADDR16 306560484Sobrien || r_type == R_PPC_EMB_NADDR16_LO 306660484Sobrien || r_type == R_PPC_EMB_NADDR16_HI 306760484Sobrien || r_type == R_PPC_EMB_NADDR16_HA 306860484Sobrien || r_type == R_PPC_EMB_SDAI16 306960484Sobrien || r_type == R_PPC_EMB_SDA2I16 307060484Sobrien || r_type == R_PPC_EMB_SDA2REL 307160484Sobrien || r_type == R_PPC_EMB_SDA21 307260484Sobrien || r_type == R_PPC_EMB_MRKREF 307360484Sobrien || r_type == R_PPC_EMB_BIT_FLD 307460484Sobrien || r_type == R_PPC_EMB_RELSDA 307560484Sobrien || ((r_type == R_PPC_REL24 307660484Sobrien || r_type == R_PPC_REL32 307760484Sobrien || r_type == R_PPC_REL14 307860484Sobrien || r_type == R_PPC_REL14_BRTAKEN 307960484Sobrien || r_type == R_PPC_REL14_BRNTAKEN 308060484Sobrien || r_type == R_PPC_RELATIVE) 308160484Sobrien && strcmp (h->root.root.string, 308260484Sobrien "_GLOBAL_OFFSET_TABLE_") != 0)))) 308360484Sobrien { 308460484Sobrien /* In these cases, we don't need the relocation 308560484Sobrien value. We check specially because in some 308660484Sobrien obscure cases sec->output_section will be NULL. */ 308760484Sobrien relocation = 0; 308860484Sobrien } 308960484Sobrien else if (sec->output_section == NULL) 309077298Sobrien { 309160484Sobrien (*_bfd_error_handler) 309260484Sobrien (_("%s: warning: unresolvable relocation against symbol `%s' from %s section"), 309360484Sobrien bfd_get_filename (input_bfd), h->root.root.string, 309460484Sobrien bfd_get_section_name (input_bfd, input_section)); 309560484Sobrien relocation = 0; 309677298Sobrien } 309760484Sobrien else 309860484Sobrien relocation = (h->root.u.def.value 309960484Sobrien + sec->output_section->vma 310060484Sobrien + sec->output_offset); 310160484Sobrien } 310260484Sobrien else if (h->root.type == bfd_link_hash_undefweak) 310360484Sobrien relocation = 0; 310477298Sobrien else if (info->shared && !info->symbolic && !info->no_undefined 310568765Sobrien && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT) 310660484Sobrien relocation = 0; 310760484Sobrien else 310860484Sobrien { 310977298Sobrien if (! (*info->callbacks->undefined_symbol) (info, 311060484Sobrien h->root.root.string, 311160484Sobrien input_bfd, 311260484Sobrien input_section, 311360484Sobrien rel->r_offset, 311460484Sobrien (!info->shared 311568765Sobrien || info->no_undefined 311668765Sobrien || ELF_ST_VISIBILITY (h->other)))) 311760484Sobrien return false; 311860484Sobrien relocation = 0; 311960484Sobrien } 312060484Sobrien } 312160484Sobrien 312277298Sobrien switch ((int) r_type) 312360484Sobrien { 312460484Sobrien default: 312560484Sobrien (*_bfd_error_handler) (_("%s: unknown relocation type %d for symbol %s"), 312660484Sobrien bfd_get_filename (input_bfd), 312777298Sobrien (int) r_type, sym_name); 312860484Sobrien 312960484Sobrien bfd_set_error (bfd_error_bad_value); 313060484Sobrien ret = false; 313160484Sobrien continue; 313260484Sobrien 313360484Sobrien /* Relocations that need no special processing. */ 313477298Sobrien case (int) R_PPC_LOCAL24PC: 313560484Sobrien /* It makes no sense to point a local relocation 313660484Sobrien at a symbol not in this object. */ 313760484Sobrien if (h != NULL 313860484Sobrien && (h->root.type == bfd_link_hash_defined 313960484Sobrien || h->root.type == bfd_link_hash_defweak) 314060484Sobrien && sec->output_section == NULL) 314160484Sobrien { 314260484Sobrien if (! (*info->callbacks->undefined_symbol) (info, 314360484Sobrien h->root.root.string, 314460484Sobrien input_bfd, 314560484Sobrien input_section, 314660484Sobrien rel->r_offset, 314760484Sobrien true)) 314860484Sobrien return false; 314960484Sobrien continue; 315060484Sobrien } 315160484Sobrien break; 315260484Sobrien 315360484Sobrien /* Relocations that may need to be propagated if this is a shared 315460484Sobrien object. */ 315577298Sobrien case (int) R_PPC_REL24: 315677298Sobrien case (int) R_PPC_REL32: 315777298Sobrien case (int) R_PPC_REL14: 315860484Sobrien /* If these relocations are not to a named symbol, they can be 315960484Sobrien handled right here, no need to bother the dynamic linker. */ 316060484Sobrien if (h == NULL 316177298Sobrien || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0 316277298Sobrien || SYMBOL_REFERENCES_LOCAL (info, h)) 316360484Sobrien break; 316460484Sobrien /* fall through */ 316560484Sobrien 316660484Sobrien /* Relocations that always need to be propagated if this is a shared 316760484Sobrien object. */ 316877298Sobrien case (int) R_PPC_NONE: 316977298Sobrien case (int) R_PPC_ADDR32: 317077298Sobrien case (int) R_PPC_ADDR24: 317177298Sobrien case (int) R_PPC_ADDR16: 317277298Sobrien case (int) R_PPC_ADDR16_LO: 317377298Sobrien case (int) R_PPC_ADDR16_HI: 317477298Sobrien case (int) R_PPC_ADDR16_HA: 317577298Sobrien case (int) R_PPC_ADDR14: 317677298Sobrien case (int) R_PPC_UADDR32: 317777298Sobrien case (int) R_PPC_UADDR16: 317860484Sobrien if (info->shared) 317960484Sobrien { 318060484Sobrien Elf_Internal_Rela outrel; 318160484Sobrien boolean skip; 318260484Sobrien 318360484Sobrien#ifdef DEBUG 318460484Sobrien fprintf (stderr, "ppc_elf_relocate_section need to create relocation for %s\n", 318560484Sobrien (h && h->root.root.string) ? h->root.root.string : "<unknown>"); 318660484Sobrien#endif 318760484Sobrien 318860484Sobrien /* When generating a shared object, these relocations 318960484Sobrien are copied into the output file to be resolved at run 319060484Sobrien time. */ 319160484Sobrien 319260484Sobrien if (sreloc == NULL) 319360484Sobrien { 319460484Sobrien const char *name; 319560484Sobrien 319660484Sobrien name = (bfd_elf_string_from_elf_section 319760484Sobrien (input_bfd, 319860484Sobrien elf_elfheader (input_bfd)->e_shstrndx, 319960484Sobrien elf_section_data (input_section)->rel_hdr.sh_name)); 320060484Sobrien if (name == NULL) 320160484Sobrien return false; 320260484Sobrien 320360484Sobrien BFD_ASSERT (strncmp (name, ".rela", 5) == 0 320460484Sobrien && strcmp (bfd_get_section_name (input_bfd, 320560484Sobrien input_section), 320660484Sobrien name + 5) == 0); 320760484Sobrien 320860484Sobrien sreloc = bfd_get_section_by_name (dynobj, name); 320960484Sobrien BFD_ASSERT (sreloc != NULL); 321060484Sobrien } 321160484Sobrien 321260484Sobrien skip = false; 321360484Sobrien 321460484Sobrien if (elf_section_data (input_section)->stab_info == NULL) 321560484Sobrien outrel.r_offset = rel->r_offset; 321660484Sobrien else 321760484Sobrien { 321860484Sobrien bfd_vma off; 321960484Sobrien 322060484Sobrien off = (_bfd_stab_section_offset 322160484Sobrien (output_bfd, &elf_hash_table (info)->stab_info, 322260484Sobrien input_section, 322360484Sobrien &elf_section_data (input_section)->stab_info, 322460484Sobrien rel->r_offset)); 322560484Sobrien if (off == (bfd_vma) -1) 322660484Sobrien skip = true; 322760484Sobrien outrel.r_offset = off; 322860484Sobrien } 322960484Sobrien 323060484Sobrien outrel.r_offset += (input_section->output_section->vma 323160484Sobrien + input_section->output_offset); 323260484Sobrien 323360484Sobrien if (skip) 323460484Sobrien memset (&outrel, 0, sizeof outrel); 323560484Sobrien /* h->dynindx may be -1 if this symbol was marked to 323660484Sobrien become local. */ 323777298Sobrien else if (! will_become_local) 323860484Sobrien { 323960484Sobrien outrel.r_info = ELF32_R_INFO (h->dynindx, r_type); 324060484Sobrien outrel.r_addend = rel->r_addend; 324160484Sobrien } 324260484Sobrien else 324360484Sobrien { 324460484Sobrien if (r_type == R_PPC_ADDR32) 324560484Sobrien { 324660484Sobrien outrel.r_info = ELF32_R_INFO (0, R_PPC_RELATIVE); 324760484Sobrien outrel.r_addend = relocation + rel->r_addend; 324860484Sobrien } 324960484Sobrien else 325060484Sobrien { 325160484Sobrien long indx; 325260484Sobrien 325360484Sobrien if (h == NULL) 325460484Sobrien sec = local_sections[r_symndx]; 325560484Sobrien else 325660484Sobrien { 325760484Sobrien BFD_ASSERT (h->root.type == bfd_link_hash_defined 325860484Sobrien || (h->root.type 325960484Sobrien == bfd_link_hash_defweak)); 326060484Sobrien sec = h->root.u.def.section; 326160484Sobrien } 326260484Sobrien if (sec != NULL && bfd_is_abs_section (sec)) 326360484Sobrien indx = 0; 326460484Sobrien else if (sec == NULL || sec->owner == NULL) 326560484Sobrien { 326660484Sobrien bfd_set_error (bfd_error_bad_value); 326760484Sobrien return false; 326860484Sobrien } 326960484Sobrien else 327060484Sobrien { 327160484Sobrien asection *osec; 327260484Sobrien 327360484Sobrien osec = sec->output_section; 327460484Sobrien indx = elf_section_data (osec)->dynindx; 327577298Sobrien BFD_ASSERT (indx > 0); 327660484Sobrien#ifdef DEBUG 327760484Sobrien if (indx <= 0) 327860484Sobrien { 327977298Sobrien printf ("indx=%d section=%s flags=%08x name=%s\n", 328060484Sobrien indx, osec->name, osec->flags, 328160484Sobrien h->root.root.string); 328260484Sobrien } 328360484Sobrien#endif 328460484Sobrien } 328560484Sobrien 328660484Sobrien outrel.r_info = ELF32_R_INFO (indx, r_type); 328760484Sobrien outrel.r_addend = relocation + rel->r_addend; 328860484Sobrien } 328960484Sobrien } 329060484Sobrien 329160484Sobrien bfd_elf32_swap_reloca_out (output_bfd, &outrel, 329260484Sobrien (((Elf32_External_Rela *) 329360484Sobrien sreloc->contents) 329460484Sobrien + sreloc->reloc_count)); 329560484Sobrien ++sreloc->reloc_count; 329660484Sobrien 329760484Sobrien /* This reloc will be computed at runtime, so there's no 329860484Sobrien need to do anything now, unless this is a RELATIVE 329960484Sobrien reloc in an unallocated section. */ 330060484Sobrien if (skip 330160484Sobrien || (input_section->flags & SEC_ALLOC) != 0 330260484Sobrien || ELF32_R_TYPE (outrel.r_info) != R_PPC_RELATIVE) 330360484Sobrien continue; 330460484Sobrien } 330560484Sobrien 330660484Sobrien /* Arithmetic adjust relocations that aren't going into a 330760484Sobrien shared object. */ 330860484Sobrien if (r_type == R_PPC_ADDR16_HA 330960484Sobrien /* It's just possible that this symbol is a weak symbol 331060484Sobrien that's not actually defined anywhere. In that case, 331160484Sobrien 'sec' would be NULL, and we should leave the symbol 331260484Sobrien alone (it will be set to zero elsewhere in the link). */ 331360484Sobrien && sec != NULL) 331460484Sobrien { 331560484Sobrien addend += ((relocation + addend) & 0x8000) << 1; 331660484Sobrien } 331760484Sobrien break; 331860484Sobrien 331960484Sobrien /* branch taken prediction relocations */ 332077298Sobrien case (int) R_PPC_ADDR14_BRTAKEN: 332177298Sobrien case (int) R_PPC_REL14_BRTAKEN: 332260484Sobrien insn = bfd_get_32 (output_bfd, contents + offset); 332360484Sobrien if ((relocation - offset) & 0x8000) 332460484Sobrien insn &= ~BRANCH_PREDICT_BIT; 332560484Sobrien else 332660484Sobrien insn |= BRANCH_PREDICT_BIT; 332760484Sobrien bfd_put_32 (output_bfd, insn, contents + offset); 332860484Sobrien break; 332960484Sobrien 333060484Sobrien /* branch not taken predicition relocations */ 333177298Sobrien case (int) R_PPC_ADDR14_BRNTAKEN: 333277298Sobrien case (int) R_PPC_REL14_BRNTAKEN: 333360484Sobrien insn = bfd_get_32 (output_bfd, contents + offset); 333460484Sobrien if ((relocation - offset) & 0x8000) 333560484Sobrien insn |= BRANCH_PREDICT_BIT; 333660484Sobrien else 333760484Sobrien insn &= ~BRANCH_PREDICT_BIT; 333860484Sobrien bfd_put_32 (output_bfd, insn, contents + offset); 333960484Sobrien break; 334060484Sobrien 334160484Sobrien /* GOT16 relocations */ 334277298Sobrien case (int) R_PPC_GOT16: 334377298Sobrien case (int) R_PPC_GOT16_LO: 334477298Sobrien case (int) R_PPC_GOT16_HI: 334577298Sobrien case (int) R_PPC_GOT16_HA: 334660484Sobrien /* Relocation is to the entry for this symbol in the global 334760484Sobrien offset table. */ 334860484Sobrien BFD_ASSERT (sgot != NULL); 334960484Sobrien 335060484Sobrien if (h != NULL) 335160484Sobrien { 335260484Sobrien bfd_vma off; 335360484Sobrien 335460484Sobrien off = h->got.offset; 335560484Sobrien BFD_ASSERT (off != (bfd_vma) -1); 335660484Sobrien 335760484Sobrien if (! elf_hash_table (info)->dynamic_sections_created 335860484Sobrien || (info->shared 335977298Sobrien && SYMBOL_REFERENCES_LOCAL (info, h))) 336060484Sobrien { 336160484Sobrien /* This is actually a static link, or it is a 336260484Sobrien -Bsymbolic link and the symbol is defined 336360484Sobrien locally. We must initialize this entry in the 336460484Sobrien global offset table. Since the offset must 336560484Sobrien always be a multiple of 4, we use the least 336660484Sobrien significant bit to record whether we have 336760484Sobrien initialized it already. 336860484Sobrien 336960484Sobrien When doing a dynamic link, we create a .rela.got 337060484Sobrien relocation entry to initialize the value. This 337160484Sobrien is done in the finish_dynamic_symbol routine. */ 337260484Sobrien if ((off & 1) != 0) 337360484Sobrien off &= ~1; 337460484Sobrien else 337560484Sobrien { 337660484Sobrien bfd_put_32 (output_bfd, relocation, 337760484Sobrien sgot->contents + off); 337860484Sobrien h->got.offset |= 1; 337960484Sobrien } 338060484Sobrien } 338160484Sobrien 338260484Sobrien relocation = sgot->output_offset + off - 4; 338360484Sobrien } 338460484Sobrien else 338560484Sobrien { 338660484Sobrien bfd_vma off; 338760484Sobrien 338860484Sobrien BFD_ASSERT (local_got_offsets != NULL 338960484Sobrien && local_got_offsets[r_symndx] != (bfd_vma) -1); 339060484Sobrien 339160484Sobrien off = local_got_offsets[r_symndx]; 339260484Sobrien 339360484Sobrien /* The offset must always be a multiple of 4. We use 339460484Sobrien the least significant bit to record whether we have 339560484Sobrien already processed this entry. */ 339660484Sobrien if ((off & 1) != 0) 339760484Sobrien off &= ~1; 339860484Sobrien else 339960484Sobrien { 340060484Sobrien bfd_put_32 (output_bfd, relocation, sgot->contents + off); 340160484Sobrien 340260484Sobrien if (info->shared) 340360484Sobrien { 340460484Sobrien asection *srelgot; 340560484Sobrien Elf_Internal_Rela outrel; 340660484Sobrien 340760484Sobrien /* We need to generate a R_PPC_RELATIVE reloc 340860484Sobrien for the dynamic linker. */ 340960484Sobrien srelgot = bfd_get_section_by_name (dynobj, ".rela.got"); 341060484Sobrien BFD_ASSERT (srelgot != NULL); 341160484Sobrien 341260484Sobrien outrel.r_offset = (sgot->output_section->vma 341360484Sobrien + sgot->output_offset 341460484Sobrien + off); 341560484Sobrien outrel.r_info = ELF32_R_INFO (0, R_PPC_RELATIVE); 341660484Sobrien outrel.r_addend = relocation; 341760484Sobrien bfd_elf32_swap_reloca_out (output_bfd, &outrel, 341860484Sobrien (((Elf32_External_Rela *) 341960484Sobrien srelgot->contents) 342060484Sobrien + srelgot->reloc_count)); 342160484Sobrien ++srelgot->reloc_count; 342260484Sobrien } 342360484Sobrien 342460484Sobrien local_got_offsets[r_symndx] |= 1; 342560484Sobrien } 342660484Sobrien 342760484Sobrien relocation = sgot->output_offset + off - 4; 342860484Sobrien } 342960484Sobrien break; 343060484Sobrien 343160484Sobrien /* Indirect .sdata relocation */ 343277298Sobrien case (int) R_PPC_EMB_SDAI16: 343360484Sobrien BFD_ASSERT (sdata != NULL); 343460484Sobrien relocation = bfd_elf32_finish_pointer_linker_section (output_bfd, input_bfd, info, 343560484Sobrien sdata, h, relocation, rel, 343660484Sobrien R_PPC_RELATIVE); 343760484Sobrien break; 343860484Sobrien 343960484Sobrien /* Indirect .sdata2 relocation */ 344077298Sobrien case (int) R_PPC_EMB_SDA2I16: 344160484Sobrien BFD_ASSERT (sdata2 != NULL); 344260484Sobrien relocation = bfd_elf32_finish_pointer_linker_section (output_bfd, input_bfd, info, 344360484Sobrien sdata2, h, relocation, rel, 344460484Sobrien R_PPC_RELATIVE); 344560484Sobrien break; 344660484Sobrien 344760484Sobrien /* Handle the TOC16 reloc. We want to use the offset within the .got 344860484Sobrien section, not the actual VMA. This is appropriate when generating 344960484Sobrien an embedded ELF object, for which the .got section acts like the 345060484Sobrien AIX .toc section. */ 345177298Sobrien case (int) R_PPC_TOC16: /* phony GOT16 relocations */ 345277298Sobrien BFD_ASSERT (sec != (asection *) 0); 345360484Sobrien BFD_ASSERT (bfd_is_und_section (sec) 345460484Sobrien || strcmp (bfd_get_section_name (abfd, sec), ".got") == 0 345560484Sobrien || strcmp (bfd_get_section_name (abfd, sec), ".cgot") == 0) 345660484Sobrien 345760484Sobrien addend -= sec->output_section->vma + sec->output_offset + 0x8000; 345860484Sobrien break; 345960484Sobrien 346077298Sobrien case (int) R_PPC_PLTREL24: 346160484Sobrien /* Relocation is to the entry for this symbol in the 346260484Sobrien procedure linkage table. */ 346360484Sobrien BFD_ASSERT (h != NULL); 346460484Sobrien 346560484Sobrien if (h->plt.offset == (bfd_vma) -1 346660484Sobrien || splt == NULL) 346760484Sobrien { 346860484Sobrien /* We didn't make a PLT entry for this symbol. This 346960484Sobrien happens when statically linking PIC code, or when 347060484Sobrien using -Bsymbolic. */ 347160484Sobrien break; 347260484Sobrien } 347360484Sobrien 347460484Sobrien relocation = (splt->output_section->vma 347560484Sobrien + splt->output_offset 347660484Sobrien + h->plt.offset); 347777298Sobrien break; 347860484Sobrien 347960484Sobrien /* relocate against _SDA_BASE_ */ 348077298Sobrien case (int) R_PPC_SDAREL16: 348160484Sobrien { 348260484Sobrien const char *name; 348360484Sobrien 348477298Sobrien BFD_ASSERT (sec != (asection *) 0); 348560484Sobrien name = bfd_get_section_name (abfd, sec->output_section); 348660484Sobrien if (strcmp (name, ".sdata") != 0 348760484Sobrien && strcmp (name, ".sbss") != 0) 348860484Sobrien { 348960484Sobrien (*_bfd_error_handler) (_("%s: The target (%s) of a %s relocation is in the wrong output section (%s)"), 349060484Sobrien bfd_get_filename (input_bfd), 349160484Sobrien sym_name, 349277298Sobrien ppc_elf_howto_table[(int) r_type]->name, 349360484Sobrien name); 349460484Sobrien } 349560484Sobrien addend -= (sdata->sym_hash->root.u.def.value 349660484Sobrien + sdata->sym_hash->root.u.def.section->output_section->vma 349760484Sobrien + sdata->sym_hash->root.u.def.section->output_offset); 349860484Sobrien } 349960484Sobrien break; 350060484Sobrien 350160484Sobrien /* relocate against _SDA2_BASE_ */ 350277298Sobrien case (int) R_PPC_EMB_SDA2REL: 350360484Sobrien { 350460484Sobrien const char *name; 350560484Sobrien 350677298Sobrien BFD_ASSERT (sec != (asection *) 0); 350760484Sobrien name = bfd_get_section_name (abfd, sec->output_section); 350860484Sobrien if (strcmp (name, ".sdata2") != 0 && strcmp (name, ".sbss2") != 0) 350960484Sobrien { 351060484Sobrien (*_bfd_error_handler) (_("%s: The target (%s) of a %s relocation is in the wrong output section (%s)"), 351160484Sobrien bfd_get_filename (input_bfd), 351260484Sobrien sym_name, 351377298Sobrien ppc_elf_howto_table[(int) r_type]->name, 351460484Sobrien name); 351577298Sobrien 351660484Sobrien bfd_set_error (bfd_error_bad_value); 351760484Sobrien ret = false; 351860484Sobrien continue; 351960484Sobrien } 352060484Sobrien addend -= (sdata2->sym_hash->root.u.def.value 352160484Sobrien + sdata2->sym_hash->root.u.def.section->output_section->vma 352260484Sobrien + sdata2->sym_hash->root.u.def.section->output_offset); 352360484Sobrien } 352460484Sobrien break; 352560484Sobrien 352660484Sobrien /* relocate against either _SDA_BASE_, _SDA2_BASE_, or 0 */ 352777298Sobrien case (int) R_PPC_EMB_SDA21: 352877298Sobrien case (int) R_PPC_EMB_RELSDA: 352960484Sobrien { 353060484Sobrien const char *name; 353160484Sobrien int reg; 353260484Sobrien 353377298Sobrien BFD_ASSERT (sec != (asection *) 0); 353460484Sobrien name = bfd_get_section_name (abfd, sec->output_section); 353560484Sobrien if (strcmp (name, ".sdata") == 0 || strcmp (name, ".sbss") == 0) 353660484Sobrien { 353760484Sobrien reg = 13; 353860484Sobrien addend -= (sdata->sym_hash->root.u.def.value 353960484Sobrien + sdata->sym_hash->root.u.def.section->output_section->vma 354060484Sobrien + sdata->sym_hash->root.u.def.section->output_offset); 354160484Sobrien } 354260484Sobrien 354377298Sobrien else if (strcmp (name, ".sdata2") == 0 354477298Sobrien || strcmp (name, ".sbss2") == 0) 354560484Sobrien { 354660484Sobrien reg = 2; 354760484Sobrien addend -= (sdata2->sym_hash->root.u.def.value 354860484Sobrien + sdata2->sym_hash->root.u.def.section->output_section->vma 354960484Sobrien + sdata2->sym_hash->root.u.def.section->output_offset); 355060484Sobrien } 355160484Sobrien 355277298Sobrien else if (strcmp (name, ".PPC.EMB.sdata0") == 0 355377298Sobrien || strcmp (name, ".PPC.EMB.sbss0") == 0) 355460484Sobrien { 355560484Sobrien reg = 0; 355660484Sobrien } 355760484Sobrien 355860484Sobrien else 355960484Sobrien { 356060484Sobrien (*_bfd_error_handler) (_("%s: The target (%s) of a %s relocation is in the wrong output section (%s)"), 356160484Sobrien bfd_get_filename (input_bfd), 356260484Sobrien sym_name, 356377298Sobrien ppc_elf_howto_table[(int) r_type]->name, 356460484Sobrien name); 356560484Sobrien 356660484Sobrien bfd_set_error (bfd_error_bad_value); 356760484Sobrien ret = false; 356860484Sobrien continue; 356960484Sobrien } 357060484Sobrien 357160484Sobrien if (r_type == R_PPC_EMB_SDA21) 357260484Sobrien { /* fill in register field */ 357360484Sobrien insn = bfd_get_32 (output_bfd, contents + offset); 357460484Sobrien insn = (insn & ~RA_REGISTER_MASK) | (reg << RA_REGISTER_SHIFT); 357560484Sobrien bfd_put_32 (output_bfd, insn, contents + offset); 357660484Sobrien } 357760484Sobrien } 357860484Sobrien break; 357960484Sobrien 358060484Sobrien /* Relocate against the beginning of the section */ 358177298Sobrien case (int) R_PPC_SECTOFF: 358277298Sobrien case (int) R_PPC_SECTOFF_LO: 358377298Sobrien case (int) R_PPC_SECTOFF_HI: 358477298Sobrien BFD_ASSERT (sec != (asection *) 0); 358560484Sobrien addend -= sec->output_section->vma; 358660484Sobrien break; 358760484Sobrien 358877298Sobrien case (int) R_PPC_SECTOFF_HA: 358977298Sobrien BFD_ASSERT (sec != (asection *) 0); 359060484Sobrien addend -= sec->output_section->vma; 359160484Sobrien addend += ((relocation + addend) & 0x8000) << 1; 359260484Sobrien break; 359360484Sobrien 359460484Sobrien /* Negative relocations */ 359577298Sobrien case (int) R_PPC_EMB_NADDR32: 359677298Sobrien case (int) R_PPC_EMB_NADDR16: 359777298Sobrien case (int) R_PPC_EMB_NADDR16_LO: 359877298Sobrien case (int) R_PPC_EMB_NADDR16_HI: 359977298Sobrien addend -= 2 * relocation; 360060484Sobrien break; 360160484Sobrien 360277298Sobrien case (int) R_PPC_EMB_NADDR16_HA: 360377298Sobrien addend -= 2 * relocation; 360460484Sobrien addend += ((relocation + addend) & 0x8000) << 1; 360560484Sobrien break; 360660484Sobrien 360760484Sobrien /* NOP relocation that prevents garbage collecting linkers from omitting a 360860484Sobrien reference. */ 360977298Sobrien case (int) R_PPC_EMB_MRKREF: 361060484Sobrien continue; 361160484Sobrien 361277298Sobrien case (int) R_PPC_COPY: 361377298Sobrien case (int) R_PPC_GLOB_DAT: 361477298Sobrien case (int) R_PPC_JMP_SLOT: 361577298Sobrien case (int) R_PPC_RELATIVE: 361677298Sobrien case (int) R_PPC_PLT32: 361777298Sobrien case (int) R_PPC_PLTREL32: 361877298Sobrien case (int) R_PPC_PLT16_LO: 361977298Sobrien case (int) R_PPC_PLT16_HI: 362077298Sobrien case (int) R_PPC_PLT16_HA: 362177298Sobrien case (int) R_PPC_EMB_RELSEC16: 362277298Sobrien case (int) R_PPC_EMB_RELST_LO: 362377298Sobrien case (int) R_PPC_EMB_RELST_HI: 362477298Sobrien case (int) R_PPC_EMB_RELST_HA: 362577298Sobrien case (int) R_PPC_EMB_BIT_FLD: 362660484Sobrien (*_bfd_error_handler) (_("%s: Relocation %s is not yet supported for symbol %s."), 362760484Sobrien bfd_get_filename (input_bfd), 362877298Sobrien ppc_elf_howto_table[(int) r_type]->name, 362960484Sobrien sym_name); 363060484Sobrien 363160484Sobrien bfd_set_error (bfd_error_invalid_operation); 363260484Sobrien ret = false; 363360484Sobrien continue; 363460484Sobrien 363577298Sobrien case (int) R_PPC_GNU_VTINHERIT: 363677298Sobrien case (int) R_PPC_GNU_VTENTRY: 363760484Sobrien /* These are no-ops in the end. */ 363860484Sobrien continue; 363960484Sobrien } 364060484Sobrien 364160484Sobrien#ifdef DEBUG 364260484Sobrien fprintf (stderr, "\ttype = %s (%d), name = %s, symbol index = %ld, offset = %ld, addend = %ld\n", 364360484Sobrien howto->name, 364477298Sobrien (int) r_type, 364560484Sobrien sym_name, 364660484Sobrien r_symndx, 364777298Sobrien (long) offset, 364877298Sobrien (long) addend); 364960484Sobrien#endif 365060484Sobrien 365160484Sobrien r = _bfd_final_link_relocate (howto, 365260484Sobrien input_bfd, 365360484Sobrien input_section, 365460484Sobrien contents, 365560484Sobrien offset, 365660484Sobrien relocation, 365760484Sobrien addend); 365860484Sobrien 365960484Sobrien if (r == bfd_reloc_ok) 366060484Sobrien ; 366160484Sobrien else if (r == bfd_reloc_overflow) 366260484Sobrien { 366360484Sobrien const char *name; 366460484Sobrien 366560484Sobrien if (h != NULL) 366660484Sobrien { 366760484Sobrien if (h->root.type == bfd_link_hash_undefweak 366860484Sobrien && howto->pc_relative) 366960484Sobrien { 367060484Sobrien /* Assume this is a call protected by other code that 367160484Sobrien detect the symbol is undefined. If this is the case, 367260484Sobrien we can safely ignore the overflow. If not, the 367360484Sobrien program is hosed anyway, and a little warning isn't 367460484Sobrien going to help. */ 367560484Sobrien 367660484Sobrien continue; 367760484Sobrien } 367860484Sobrien 367960484Sobrien name = h->root.root.string; 368060484Sobrien } 368160484Sobrien else 368260484Sobrien { 368360484Sobrien name = bfd_elf_string_from_elf_section (input_bfd, 368460484Sobrien symtab_hdr->sh_link, 368560484Sobrien sym->st_name); 368660484Sobrien if (name == NULL) 368760484Sobrien continue; 368860484Sobrien if (*name == '\0') 368960484Sobrien name = bfd_section_name (input_bfd, sec); 369060484Sobrien } 369160484Sobrien 369277298Sobrien if (! (*info->callbacks->reloc_overflow) (info, 369360484Sobrien name, 369460484Sobrien howto->name, 369560484Sobrien (bfd_vma) 0, 369660484Sobrien input_bfd, 369760484Sobrien input_section, 369860484Sobrien offset)) 369960484Sobrien return false; 370060484Sobrien } 370160484Sobrien else 370260484Sobrien ret = false; 370360484Sobrien } 370460484Sobrien 370560484Sobrien#ifdef DEBUG 370660484Sobrien fprintf (stderr, "\n"); 370760484Sobrien#endif 370860484Sobrien 370960484Sobrien return ret; 371060484Sobrien} 371160484Sobrien 371260484Sobrien#define TARGET_LITTLE_SYM bfd_elf32_powerpcle_vec 371360484Sobrien#define TARGET_LITTLE_NAME "elf32-powerpcle" 371460484Sobrien#define TARGET_BIG_SYM bfd_elf32_powerpc_vec 371560484Sobrien#define TARGET_BIG_NAME "elf32-powerpc" 371660484Sobrien#define ELF_ARCH bfd_arch_powerpc 371760484Sobrien#define ELF_MACHINE_CODE EM_PPC 371860484Sobrien#define ELF_MAXPAGESIZE 0x10000 371960484Sobrien#define elf_info_to_howto ppc_elf_info_to_howto 372060484Sobrien 372160484Sobrien#ifdef EM_CYGNUS_POWERPC 372260484Sobrien#define ELF_MACHINE_ALT1 EM_CYGNUS_POWERPC 372360484Sobrien#endif 372460484Sobrien 372560484Sobrien#ifdef EM_PPC_OLD 372660484Sobrien#define ELF_MACHINE_ALT2 EM_PPC_OLD 372760484Sobrien#endif 372860484Sobrien 372960484Sobrien#define elf_backend_plt_not_loaded 1 373060484Sobrien#define elf_backend_got_symbol_offset 4 373160484Sobrien#define elf_backend_can_gc_sections 1 373260484Sobrien#define elf_backend_got_header_size 12 373360484Sobrien#define elf_backend_plt_header_size PLT_INITIAL_ENTRY_SIZE 373460484Sobrien 373560484Sobrien#define bfd_elf32_bfd_copy_private_bfd_data ppc_elf_copy_private_bfd_data 373660484Sobrien#define bfd_elf32_bfd_merge_private_bfd_data ppc_elf_merge_private_bfd_data 373760484Sobrien#define bfd_elf32_bfd_relax_section ppc_elf_relax_section 373860484Sobrien#define bfd_elf32_bfd_reloc_type_lookup ppc_elf_reloc_type_lookup 373960484Sobrien#define bfd_elf32_bfd_set_private_flags ppc_elf_set_private_flags 374060484Sobrien#define bfd_elf32_bfd_final_link _bfd_elf32_gc_common_final_link 374160484Sobrien 374260484Sobrien#define elf_backend_gc_mark_hook ppc_elf_gc_mark_hook 374360484Sobrien#define elf_backend_gc_sweep_hook ppc_elf_gc_sweep_hook 374460484Sobrien#define elf_backend_section_from_shdr ppc_elf_section_from_shdr 374560484Sobrien#define elf_backend_relocate_section ppc_elf_relocate_section 374660484Sobrien#define elf_backend_create_dynamic_sections ppc_elf_create_dynamic_sections 374760484Sobrien#define elf_backend_check_relocs ppc_elf_check_relocs 374860484Sobrien#define elf_backend_adjust_dynamic_symbol ppc_elf_adjust_dynamic_symbol 374960484Sobrien#define elf_backend_add_symbol_hook ppc_elf_add_symbol_hook 375060484Sobrien#define elf_backend_size_dynamic_sections ppc_elf_size_dynamic_sections 375160484Sobrien#define elf_backend_finish_dynamic_symbol ppc_elf_finish_dynamic_symbol 375260484Sobrien#define elf_backend_finish_dynamic_sections ppc_elf_finish_dynamic_sections 375360484Sobrien#define elf_backend_fake_sections ppc_elf_fake_sections 375460484Sobrien#define elf_backend_additional_program_headers ppc_elf_additional_program_headers 375560484Sobrien#define elf_backend_modify_segment_map ppc_elf_modify_segment_map 375660484Sobrien 375760484Sobrien#include "elf32-target.h" 3758