elf32-ppc.c revision 89857
160484Sobrien/* PowerPC-specific support for 32-bit ELF 278828Sobrien Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 378828Sobrien Free Software Foundation, Inc. 460484Sobrien Written by Ian Lance Taylor, Cygnus Support. 560484Sobrien 660484SobrienThis file is part of BFD, the Binary File Descriptor library. 760484Sobrien 860484SobrienThis program is free software; you can redistribute it and/or modify 960484Sobrienit under the terms of the GNU General Public License as published by 1060484Sobrienthe Free Software Foundation; either version 2 of the License, or 1160484Sobrien(at your option) any later version. 1260484Sobrien 1360484SobrienThis program is distributed in the hope that it will be useful, 1460484Sobrienbut WITHOUT ANY WARRANTY; without even the implied warranty of 1560484SobrienMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1660484SobrienGNU General Public License for more details. 1760484Sobrien 1860484SobrienYou should have received a copy of the GNU General Public License 1960484Sobrienalong with this program; if not, write to the Free Software 2060484SobrienFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 2160484Sobrien 2260484Sobrien/* This file is based on a preliminary PowerPC ELF ABI. The 2360484Sobrien information may not match the final PowerPC ELF ABI. It includes 2460484Sobrien suggestions from the in-progress Embedded PowerPC ABI, and that 2560484Sobrien information may also not match. */ 2660484Sobrien 2760484Sobrien#include "bfd.h" 2860484Sobrien#include "sysdep.h" 2960484Sobrien#include "bfdlink.h" 3060484Sobrien#include "libbfd.h" 3160484Sobrien#include "elf-bfd.h" 3260484Sobrien#include "elf/ppc.h" 3360484Sobrien 3460484Sobrien#define USE_RELA /* we want RELA relocations, not REL */ 3560484Sobrien 3660484Sobrienstatic reloc_howto_type *ppc_elf_reloc_type_lookup 3760484Sobrien PARAMS ((bfd *abfd, bfd_reloc_code_real_type code)); 3860484Sobrienstatic void ppc_elf_info_to_howto 3960484Sobrien PARAMS ((bfd *abfd, arelent *cache_ptr, Elf32_Internal_Rela *dst)); 4060484Sobrienstatic void ppc_elf_howto_init PARAMS ((void)); 4189857Sobrienstatic int ppc_elf_sort_rela PARAMS ((const PTR, const PTR)); 4289857Sobrienstatic boolean ppc_elf_relax_section 4389857Sobrien PARAMS ((bfd *, asection *, struct bfd_link_info *, boolean *)); 4460484Sobrienstatic bfd_reloc_status_type ppc_elf_addr16_ha_reloc 4560484Sobrien PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); 4660484Sobrienstatic boolean ppc_elf_set_private_flags PARAMS ((bfd *, flagword)); 4760484Sobrienstatic boolean ppc_elf_merge_private_bfd_data PARAMS ((bfd *, bfd *)); 4860484Sobrien 4960484Sobrienstatic int ppc_elf_additional_program_headers PARAMS ((bfd *)); 5060484Sobrienstatic boolean ppc_elf_modify_segment_map PARAMS ((bfd *)); 5160484Sobrien 5260484Sobrienstatic boolean ppc_elf_create_dynamic_sections 5360484Sobrien PARAMS ((bfd *, struct bfd_link_info *)); 5460484Sobrien 5560484Sobrienstatic boolean ppc_elf_section_from_shdr PARAMS ((bfd *, 5660484Sobrien Elf32_Internal_Shdr *, 5760484Sobrien char *)); 5860484Sobrienstatic boolean ppc_elf_fake_sections 5960484Sobrien PARAMS ((bfd *, Elf32_Internal_Shdr *, asection *)); 6060484Sobrien 6160484Sobrienstatic elf_linker_section_t *ppc_elf_create_linker_section 6260484Sobrien PARAMS ((bfd *abfd, 6360484Sobrien struct bfd_link_info *info, 6460484Sobrien enum elf_linker_section_enum)); 6560484Sobrien 6660484Sobrienstatic boolean ppc_elf_check_relocs PARAMS ((bfd *, 6760484Sobrien struct bfd_link_info *, 6860484Sobrien asection *, 6960484Sobrien const Elf_Internal_Rela *)); 7060484Sobrien 7160484Sobrienstatic asection * ppc_elf_gc_mark_hook PARAMS ((bfd *abfd, 7260484Sobrien struct bfd_link_info *info, 7360484Sobrien Elf_Internal_Rela *rel, 7460484Sobrien struct elf_link_hash_entry *h, 7560484Sobrien Elf_Internal_Sym *sym)); 7660484Sobrien 7760484Sobrienstatic boolean ppc_elf_gc_sweep_hook PARAMS ((bfd *abfd, 7860484Sobrien struct bfd_link_info *info, 7960484Sobrien asection *sec, 8060484Sobrien const Elf_Internal_Rela *relocs)); 8160484Sobrien 8260484Sobrienstatic boolean ppc_elf_adjust_dynamic_symbol PARAMS ((struct bfd_link_info *, 8360484Sobrien struct elf_link_hash_entry *)); 8460484Sobrien 8560484Sobrienstatic boolean ppc_elf_size_dynamic_sections PARAMS ((bfd *, struct bfd_link_info *)); 8660484Sobrien 8760484Sobrienstatic boolean ppc_elf_relocate_section PARAMS ((bfd *, 8860484Sobrien struct bfd_link_info *info, 8960484Sobrien bfd *, 9060484Sobrien asection *, 9160484Sobrien bfd_byte *, 9260484Sobrien Elf_Internal_Rela *relocs, 9360484Sobrien Elf_Internal_Sym *local_syms, 9460484Sobrien asection **)); 9560484Sobrien 9660484Sobrienstatic boolean ppc_elf_add_symbol_hook PARAMS ((bfd *, 9760484Sobrien struct bfd_link_info *, 9860484Sobrien const Elf_Internal_Sym *, 9960484Sobrien const char **, 10060484Sobrien flagword *, 10160484Sobrien asection **, 10260484Sobrien bfd_vma *)); 10360484Sobrien 10460484Sobrienstatic boolean ppc_elf_finish_dynamic_symbol PARAMS ((bfd *, 10560484Sobrien struct bfd_link_info *, 10660484Sobrien struct elf_link_hash_entry *, 10760484Sobrien Elf_Internal_Sym *)); 10860484Sobrien 10960484Sobrienstatic boolean ppc_elf_finish_dynamic_sections PARAMS ((bfd *, struct bfd_link_info *)); 11089857Sobrienstatic enum elf_reloc_type_class ppc_elf_reloc_type_class 11189857Sobrien PARAMS ((const Elf_Internal_Rela *)); 11289857Sobrienstatic boolean ppc_elf_grok_prstatus 11389857Sobrien PARAMS ((bfd *abfd, Elf_Internal_Note *note)); 11489857Sobrienstatic boolean ppc_elf_grok_psinfo 11589857Sobrien PARAMS ((bfd *abfd, Elf_Internal_Note *note)); 11660484Sobrien 11760484Sobrien#define BRANCH_PREDICT_BIT 0x200000 /* branch prediction bit for branch taken relocs */ 11860484Sobrien#define RA_REGISTER_MASK 0x001f0000 /* mask to set RA in memory instructions */ 11960484Sobrien#define RA_REGISTER_SHIFT 16 /* value to shift register by to insert RA */ 12060484Sobrien 12160484Sobrien/* The name of the dynamic interpreter. This is put in the .interp 12260484Sobrien section. */ 12360484Sobrien 12460484Sobrien#define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1" 12560484Sobrien 12660484Sobrien/* The size in bytes of an entry in the procedure linkage table. */ 12760484Sobrien#define PLT_ENTRY_SIZE 12 12860484Sobrien/* The initial size of the plt reserved for the dynamic linker. */ 12960484Sobrien#define PLT_INITIAL_ENTRY_SIZE 72 13060484Sobrien/* The size of the gap between entries in the PLT. */ 13160484Sobrien#define PLT_SLOT_SIZE 8 13260484Sobrien/* The number of single-slot PLT entries (the rest use two slots). */ 13360484Sobrien#define PLT_NUM_SINGLE_ENTRIES 8192 13460484Sobrien 13577298Sobrien/* Will references to this symbol always reference the symbol 13677298Sobrien in this object? */ 13777298Sobrien#define SYMBOL_REFERENCES_LOCAL(INFO, H) \ 13877298Sobrien ((! INFO->shared \ 13977298Sobrien || INFO->symbolic \ 14077298Sobrien || H->dynindx == -1 \ 14177298Sobrien || ELF_ST_VISIBILITY (H->other) == STV_INTERNAL \ 14277298Sobrien || ELF_ST_VISIBILITY (H->other) == STV_HIDDEN) \ 14377298Sobrien && (H->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0) 14477298Sobrien 14577298Sobrien/* Will _calls_ to this symbol always call the version in this object? */ 14677298Sobrien#define SYMBOL_CALLS_LOCAL(INFO, H) \ 14777298Sobrien ((! INFO->shared \ 14877298Sobrien || INFO->symbolic \ 14977298Sobrien || H->dynindx == -1 \ 15077298Sobrien || ELF_ST_VISIBILITY (H->other) != STV_DEFAULT) \ 15177298Sobrien && (H->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0) 15260484Sobrien 15377298Sobrienstatic reloc_howto_type *ppc_elf_howto_table[(int) R_PPC_max]; 15460484Sobrien 15577298Sobrienstatic reloc_howto_type ppc_elf_howto_raw[] = { 15660484Sobrien /* This reloc does nothing. */ 15760484Sobrien HOWTO (R_PPC_NONE, /* type */ 15860484Sobrien 0, /* rightshift */ 15960484Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 16060484Sobrien 32, /* bitsize */ 16160484Sobrien false, /* pc_relative */ 16260484Sobrien 0, /* bitpos */ 16360484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 16460484Sobrien bfd_elf_generic_reloc, /* special_function */ 16560484Sobrien "R_PPC_NONE", /* name */ 16660484Sobrien false, /* partial_inplace */ 16760484Sobrien 0, /* src_mask */ 16860484Sobrien 0, /* dst_mask */ 16960484Sobrien false), /* pcrel_offset */ 17060484Sobrien 17160484Sobrien /* A standard 32 bit relocation. */ 17260484Sobrien HOWTO (R_PPC_ADDR32, /* type */ 17360484Sobrien 0, /* rightshift */ 17460484Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 17560484Sobrien 32, /* bitsize */ 17660484Sobrien false, /* pc_relative */ 17760484Sobrien 0, /* bitpos */ 17860484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 17960484Sobrien bfd_elf_generic_reloc, /* special_function */ 18060484Sobrien "R_PPC_ADDR32", /* name */ 18160484Sobrien false, /* partial_inplace */ 18260484Sobrien 0, /* src_mask */ 18360484Sobrien 0xffffffff, /* dst_mask */ 18460484Sobrien false), /* pcrel_offset */ 18560484Sobrien 18660484Sobrien /* An absolute 26 bit branch; the lower two bits must be zero. 18760484Sobrien FIXME: we don't check that, we just clear them. */ 18860484Sobrien HOWTO (R_PPC_ADDR24, /* type */ 18960484Sobrien 0, /* rightshift */ 19060484Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 19160484Sobrien 26, /* bitsize */ 19260484Sobrien false, /* pc_relative */ 19360484Sobrien 0, /* bitpos */ 19460484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 19560484Sobrien bfd_elf_generic_reloc, /* special_function */ 19660484Sobrien "R_PPC_ADDR24", /* name */ 19760484Sobrien false, /* partial_inplace */ 19860484Sobrien 0, /* src_mask */ 19960484Sobrien 0x3fffffc, /* dst_mask */ 20060484Sobrien false), /* pcrel_offset */ 20160484Sobrien 20260484Sobrien /* A standard 16 bit relocation. */ 20360484Sobrien HOWTO (R_PPC_ADDR16, /* type */ 20460484Sobrien 0, /* rightshift */ 20560484Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 20660484Sobrien 16, /* bitsize */ 20760484Sobrien false, /* pc_relative */ 20860484Sobrien 0, /* bitpos */ 20960484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 21060484Sobrien bfd_elf_generic_reloc, /* special_function */ 21160484Sobrien "R_PPC_ADDR16", /* name */ 21260484Sobrien false, /* partial_inplace */ 21360484Sobrien 0, /* src_mask */ 21460484Sobrien 0xffff, /* dst_mask */ 21560484Sobrien false), /* pcrel_offset */ 21660484Sobrien 21760484Sobrien /* A 16 bit relocation without overflow. */ 21860484Sobrien HOWTO (R_PPC_ADDR16_LO, /* type */ 21960484Sobrien 0, /* rightshift */ 22060484Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 22160484Sobrien 16, /* bitsize */ 22260484Sobrien false, /* pc_relative */ 22360484Sobrien 0, /* bitpos */ 22460484Sobrien complain_overflow_dont,/* complain_on_overflow */ 22560484Sobrien bfd_elf_generic_reloc, /* special_function */ 22660484Sobrien "R_PPC_ADDR16_LO", /* name */ 22760484Sobrien false, /* partial_inplace */ 22860484Sobrien 0, /* src_mask */ 22960484Sobrien 0xffff, /* dst_mask */ 23060484Sobrien false), /* pcrel_offset */ 23160484Sobrien 23260484Sobrien /* The high order 16 bits of an address. */ 23360484Sobrien HOWTO (R_PPC_ADDR16_HI, /* type */ 23460484Sobrien 16, /* rightshift */ 23560484Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 23660484Sobrien 16, /* bitsize */ 23760484Sobrien false, /* pc_relative */ 23860484Sobrien 0, /* bitpos */ 23960484Sobrien complain_overflow_dont, /* complain_on_overflow */ 24060484Sobrien bfd_elf_generic_reloc, /* special_function */ 24160484Sobrien "R_PPC_ADDR16_HI", /* name */ 24260484Sobrien false, /* partial_inplace */ 24360484Sobrien 0, /* src_mask */ 24460484Sobrien 0xffff, /* dst_mask */ 24560484Sobrien false), /* pcrel_offset */ 24660484Sobrien 24760484Sobrien /* The high order 16 bits of an address, plus 1 if the contents of 24877298Sobrien the low 16 bits, treated as a signed number, is negative. */ 24960484Sobrien HOWTO (R_PPC_ADDR16_HA, /* type */ 25060484Sobrien 16, /* rightshift */ 25160484Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 25260484Sobrien 16, /* bitsize */ 25360484Sobrien false, /* pc_relative */ 25460484Sobrien 0, /* bitpos */ 25560484Sobrien complain_overflow_dont, /* complain_on_overflow */ 25660484Sobrien ppc_elf_addr16_ha_reloc, /* special_function */ 25760484Sobrien "R_PPC_ADDR16_HA", /* name */ 25860484Sobrien false, /* partial_inplace */ 25960484Sobrien 0, /* src_mask */ 26060484Sobrien 0xffff, /* dst_mask */ 26160484Sobrien false), /* pcrel_offset */ 26260484Sobrien 26360484Sobrien /* An absolute 16 bit branch; the lower two bits must be zero. 26460484Sobrien FIXME: we don't check that, we just clear them. */ 26560484Sobrien HOWTO (R_PPC_ADDR14, /* type */ 26660484Sobrien 0, /* rightshift */ 26760484Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 26860484Sobrien 16, /* bitsize */ 26960484Sobrien false, /* pc_relative */ 27060484Sobrien 0, /* bitpos */ 27160484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 27260484Sobrien bfd_elf_generic_reloc, /* special_function */ 27360484Sobrien "R_PPC_ADDR14", /* name */ 27460484Sobrien false, /* partial_inplace */ 27560484Sobrien 0, /* src_mask */ 27660484Sobrien 0xfffc, /* dst_mask */ 27760484Sobrien false), /* pcrel_offset */ 27860484Sobrien 27960484Sobrien /* An absolute 16 bit branch, for which bit 10 should be set to 28060484Sobrien indicate that the branch is expected to be taken. The lower two 28177298Sobrien bits must be zero. */ 28260484Sobrien HOWTO (R_PPC_ADDR14_BRTAKEN, /* type */ 28360484Sobrien 0, /* rightshift */ 28460484Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 28560484Sobrien 16, /* bitsize */ 28660484Sobrien false, /* pc_relative */ 28760484Sobrien 0, /* bitpos */ 28860484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 28960484Sobrien bfd_elf_generic_reloc, /* special_function */ 29060484Sobrien "R_PPC_ADDR14_BRTAKEN",/* name */ 29160484Sobrien false, /* partial_inplace */ 29260484Sobrien 0, /* src_mask */ 29360484Sobrien 0xfffc, /* dst_mask */ 29460484Sobrien false), /* pcrel_offset */ 29560484Sobrien 29660484Sobrien /* An absolute 16 bit branch, for which bit 10 should be set to 29760484Sobrien indicate that the branch is not expected to be taken. The lower 29860484Sobrien two bits must be zero. */ 29960484Sobrien HOWTO (R_PPC_ADDR14_BRNTAKEN, /* type */ 30060484Sobrien 0, /* rightshift */ 30160484Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 30260484Sobrien 16, /* bitsize */ 30360484Sobrien false, /* pc_relative */ 30460484Sobrien 0, /* bitpos */ 30560484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 30660484Sobrien bfd_elf_generic_reloc, /* special_function */ 30760484Sobrien "R_PPC_ADDR14_BRNTAKEN",/* name */ 30860484Sobrien false, /* partial_inplace */ 30960484Sobrien 0, /* src_mask */ 31060484Sobrien 0xfffc, /* dst_mask */ 31160484Sobrien false), /* pcrel_offset */ 31260484Sobrien 31377298Sobrien /* A relative 26 bit branch; the lower two bits must be zero. */ 31460484Sobrien HOWTO (R_PPC_REL24, /* type */ 31560484Sobrien 0, /* rightshift */ 31660484Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 31760484Sobrien 26, /* bitsize */ 31860484Sobrien true, /* pc_relative */ 31960484Sobrien 0, /* bitpos */ 32060484Sobrien complain_overflow_signed, /* complain_on_overflow */ 32160484Sobrien bfd_elf_generic_reloc, /* special_function */ 32260484Sobrien "R_PPC_REL24", /* name */ 32360484Sobrien false, /* partial_inplace */ 32460484Sobrien 0, /* src_mask */ 32560484Sobrien 0x3fffffc, /* dst_mask */ 32660484Sobrien true), /* pcrel_offset */ 32760484Sobrien 32877298Sobrien /* A relative 16 bit branch; the lower two bits must be zero. */ 32960484Sobrien HOWTO (R_PPC_REL14, /* type */ 33060484Sobrien 0, /* rightshift */ 33160484Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 33260484Sobrien 16, /* bitsize */ 33360484Sobrien true, /* pc_relative */ 33460484Sobrien 0, /* bitpos */ 33560484Sobrien complain_overflow_signed, /* complain_on_overflow */ 33660484Sobrien bfd_elf_generic_reloc, /* special_function */ 33760484Sobrien "R_PPC_REL14", /* name */ 33860484Sobrien false, /* partial_inplace */ 33960484Sobrien 0, /* src_mask */ 34060484Sobrien 0xfffc, /* dst_mask */ 34160484Sobrien true), /* pcrel_offset */ 34260484Sobrien 34377298Sobrien /* A relative 16 bit branch. Bit 10 should be set to indicate that 34460484Sobrien the branch is expected to be taken. The lower two bits must be 34560484Sobrien zero. */ 34660484Sobrien HOWTO (R_PPC_REL14_BRTAKEN, /* type */ 34760484Sobrien 0, /* rightshift */ 34860484Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 34960484Sobrien 16, /* bitsize */ 35060484Sobrien true, /* pc_relative */ 35160484Sobrien 0, /* bitpos */ 35260484Sobrien complain_overflow_signed, /* complain_on_overflow */ 35360484Sobrien bfd_elf_generic_reloc, /* special_function */ 35460484Sobrien "R_PPC_REL14_BRTAKEN", /* name */ 35560484Sobrien false, /* partial_inplace */ 35660484Sobrien 0, /* src_mask */ 35760484Sobrien 0xfffc, /* dst_mask */ 35860484Sobrien true), /* pcrel_offset */ 35960484Sobrien 36077298Sobrien /* A relative 16 bit branch. Bit 10 should be set to indicate that 36160484Sobrien the branch is not expected to be taken. The lower two bits must 36260484Sobrien be zero. */ 36360484Sobrien HOWTO (R_PPC_REL14_BRNTAKEN, /* type */ 36460484Sobrien 0, /* rightshift */ 36560484Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 36660484Sobrien 16, /* bitsize */ 36760484Sobrien true, /* pc_relative */ 36860484Sobrien 0, /* bitpos */ 36960484Sobrien complain_overflow_signed, /* complain_on_overflow */ 37060484Sobrien bfd_elf_generic_reloc, /* special_function */ 37160484Sobrien "R_PPC_REL14_BRNTAKEN",/* name */ 37260484Sobrien false, /* partial_inplace */ 37360484Sobrien 0, /* src_mask */ 37460484Sobrien 0xfffc, /* dst_mask */ 37560484Sobrien true), /* pcrel_offset */ 37660484Sobrien 37760484Sobrien /* Like R_PPC_ADDR16, but referring to the GOT table entry for the 37860484Sobrien symbol. */ 37960484Sobrien HOWTO (R_PPC_GOT16, /* type */ 38060484Sobrien 0, /* rightshift */ 38160484Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 38260484Sobrien 16, /* bitsize */ 38360484Sobrien false, /* pc_relative */ 38460484Sobrien 0, /* bitpos */ 38560484Sobrien complain_overflow_signed, /* complain_on_overflow */ 38660484Sobrien bfd_elf_generic_reloc, /* special_function */ 38760484Sobrien "R_PPC_GOT16", /* name */ 38860484Sobrien false, /* partial_inplace */ 38960484Sobrien 0, /* src_mask */ 39060484Sobrien 0xffff, /* dst_mask */ 39160484Sobrien false), /* pcrel_offset */ 39260484Sobrien 39360484Sobrien /* Like R_PPC_ADDR16_LO, but referring to the GOT table entry for 39460484Sobrien the symbol. */ 39560484Sobrien HOWTO (R_PPC_GOT16_LO, /* type */ 39660484Sobrien 0, /* rightshift */ 39760484Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 39860484Sobrien 16, /* bitsize */ 39960484Sobrien false, /* pc_relative */ 40060484Sobrien 0, /* bitpos */ 40160484Sobrien complain_overflow_dont, /* complain_on_overflow */ 40260484Sobrien bfd_elf_generic_reloc, /* special_function */ 40360484Sobrien "R_PPC_GOT16_LO", /* name */ 40460484Sobrien false, /* partial_inplace */ 40560484Sobrien 0, /* src_mask */ 40660484Sobrien 0xffff, /* dst_mask */ 40760484Sobrien false), /* pcrel_offset */ 40860484Sobrien 40960484Sobrien /* Like R_PPC_ADDR16_HI, but referring to the GOT table entry for 41060484Sobrien the symbol. */ 41160484Sobrien HOWTO (R_PPC_GOT16_HI, /* type */ 41260484Sobrien 16, /* rightshift */ 41360484Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 41460484Sobrien 16, /* bitsize */ 41560484Sobrien false, /* pc_relative */ 41660484Sobrien 0, /* bitpos */ 41760484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 41860484Sobrien bfd_elf_generic_reloc, /* special_function */ 41960484Sobrien "R_PPC_GOT16_HI", /* name */ 42060484Sobrien false, /* partial_inplace */ 42160484Sobrien 0, /* src_mask */ 42260484Sobrien 0xffff, /* dst_mask */ 42360484Sobrien false), /* pcrel_offset */ 42460484Sobrien 42560484Sobrien /* Like R_PPC_ADDR16_HA, but referring to the GOT table entry for 42660484Sobrien the symbol. */ 42760484Sobrien HOWTO (R_PPC_GOT16_HA, /* type */ 42860484Sobrien 16, /* rightshift */ 42960484Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 43060484Sobrien 16, /* bitsize */ 43160484Sobrien false, /* pc_relative */ 43260484Sobrien 0, /* bitpos */ 43360484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 43460484Sobrien ppc_elf_addr16_ha_reloc, /* special_function */ 43560484Sobrien "R_PPC_GOT16_HA", /* name */ 43660484Sobrien false, /* partial_inplace */ 43760484Sobrien 0, /* src_mask */ 43860484Sobrien 0xffff, /* dst_mask */ 43960484Sobrien false), /* pcrel_offset */ 44060484Sobrien 44160484Sobrien /* Like R_PPC_REL24, but referring to the procedure linkage table 44260484Sobrien entry for the symbol. */ 44360484Sobrien HOWTO (R_PPC_PLTREL24, /* type */ 44460484Sobrien 0, /* rightshift */ 44560484Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 44660484Sobrien 26, /* bitsize */ 44760484Sobrien true, /* pc_relative */ 44860484Sobrien 0, /* bitpos */ 44960484Sobrien complain_overflow_signed, /* complain_on_overflow */ 45060484Sobrien bfd_elf_generic_reloc, /* special_function */ 45160484Sobrien "R_PPC_PLTREL24", /* name */ 45260484Sobrien false, /* partial_inplace */ 45360484Sobrien 0, /* src_mask */ 45460484Sobrien 0x3fffffc, /* dst_mask */ 45560484Sobrien true), /* pcrel_offset */ 45660484Sobrien 45760484Sobrien /* This is used only by the dynamic linker. The symbol should exist 45860484Sobrien both in the object being run and in some shared library. The 45960484Sobrien dynamic linker copies the data addressed by the symbol from the 46060484Sobrien shared library into the object, because the object being 46160484Sobrien run has to have the data at some particular address. */ 46260484Sobrien HOWTO (R_PPC_COPY, /* type */ 46360484Sobrien 0, /* rightshift */ 46460484Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 46560484Sobrien 32, /* bitsize */ 46660484Sobrien false, /* pc_relative */ 46760484Sobrien 0, /* bitpos */ 46860484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 46960484Sobrien bfd_elf_generic_reloc, /* special_function */ 47060484Sobrien "R_PPC_COPY", /* name */ 47160484Sobrien false, /* partial_inplace */ 47260484Sobrien 0, /* src_mask */ 47360484Sobrien 0, /* dst_mask */ 47460484Sobrien false), /* pcrel_offset */ 47560484Sobrien 47660484Sobrien /* Like R_PPC_ADDR32, but used when setting global offset table 47760484Sobrien entries. */ 47860484Sobrien HOWTO (R_PPC_GLOB_DAT, /* type */ 47960484Sobrien 0, /* rightshift */ 48060484Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 48160484Sobrien 32, /* bitsize */ 48260484Sobrien false, /* pc_relative */ 48360484Sobrien 0, /* bitpos */ 48460484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 48560484Sobrien bfd_elf_generic_reloc, /* special_function */ 48660484Sobrien "R_PPC_GLOB_DAT", /* name */ 48760484Sobrien false, /* partial_inplace */ 48860484Sobrien 0, /* src_mask */ 48960484Sobrien 0xffffffff, /* dst_mask */ 49060484Sobrien false), /* pcrel_offset */ 49160484Sobrien 49260484Sobrien /* Marks a procedure linkage table entry for a symbol. */ 49360484Sobrien HOWTO (R_PPC_JMP_SLOT, /* type */ 49460484Sobrien 0, /* rightshift */ 49560484Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 49660484Sobrien 32, /* bitsize */ 49760484Sobrien false, /* pc_relative */ 49860484Sobrien 0, /* bitpos */ 49960484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 50060484Sobrien bfd_elf_generic_reloc, /* special_function */ 50160484Sobrien "R_PPC_JMP_SLOT", /* name */ 50260484Sobrien false, /* partial_inplace */ 50360484Sobrien 0, /* src_mask */ 50460484Sobrien 0, /* dst_mask */ 50560484Sobrien false), /* pcrel_offset */ 50660484Sobrien 50760484Sobrien /* Used only by the dynamic linker. When the object is run, this 50860484Sobrien longword is set to the load address of the object, plus the 50960484Sobrien addend. */ 51060484Sobrien HOWTO (R_PPC_RELATIVE, /* type */ 51160484Sobrien 0, /* rightshift */ 51260484Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 51360484Sobrien 32, /* bitsize */ 51460484Sobrien false, /* pc_relative */ 51560484Sobrien 0, /* bitpos */ 51660484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 51760484Sobrien bfd_elf_generic_reloc, /* special_function */ 51860484Sobrien "R_PPC_RELATIVE", /* name */ 51960484Sobrien false, /* partial_inplace */ 52060484Sobrien 0, /* src_mask */ 52160484Sobrien 0xffffffff, /* dst_mask */ 52260484Sobrien false), /* pcrel_offset */ 52360484Sobrien 52460484Sobrien /* Like R_PPC_REL24, but uses the value of the symbol within the 52560484Sobrien object rather than the final value. Normally used for 52660484Sobrien _GLOBAL_OFFSET_TABLE_. */ 52760484Sobrien HOWTO (R_PPC_LOCAL24PC, /* type */ 52860484Sobrien 0, /* rightshift */ 52960484Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 53060484Sobrien 26, /* bitsize */ 53160484Sobrien true, /* pc_relative */ 53260484Sobrien 0, /* bitpos */ 53360484Sobrien complain_overflow_signed, /* complain_on_overflow */ 53460484Sobrien bfd_elf_generic_reloc, /* special_function */ 53560484Sobrien "R_PPC_LOCAL24PC", /* name */ 53660484Sobrien false, /* partial_inplace */ 53760484Sobrien 0, /* src_mask */ 53860484Sobrien 0x3fffffc, /* dst_mask */ 53960484Sobrien true), /* pcrel_offset */ 54060484Sobrien 54160484Sobrien /* Like R_PPC_ADDR32, but may be unaligned. */ 54260484Sobrien HOWTO (R_PPC_UADDR32, /* type */ 54360484Sobrien 0, /* rightshift */ 54460484Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 54560484Sobrien 32, /* bitsize */ 54660484Sobrien false, /* pc_relative */ 54760484Sobrien 0, /* bitpos */ 54860484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 54960484Sobrien bfd_elf_generic_reloc, /* special_function */ 55060484Sobrien "R_PPC_UADDR32", /* name */ 55160484Sobrien false, /* partial_inplace */ 55260484Sobrien 0, /* src_mask */ 55360484Sobrien 0xffffffff, /* dst_mask */ 55460484Sobrien false), /* pcrel_offset */ 55560484Sobrien 55660484Sobrien /* Like R_PPC_ADDR16, but may be unaligned. */ 55760484Sobrien HOWTO (R_PPC_UADDR16, /* type */ 55860484Sobrien 0, /* rightshift */ 55960484Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 56060484Sobrien 16, /* bitsize */ 56160484Sobrien false, /* pc_relative */ 56260484Sobrien 0, /* bitpos */ 56360484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 56460484Sobrien bfd_elf_generic_reloc, /* special_function */ 56560484Sobrien "R_PPC_UADDR16", /* name */ 56660484Sobrien false, /* partial_inplace */ 56760484Sobrien 0, /* src_mask */ 56860484Sobrien 0xffff, /* dst_mask */ 56960484Sobrien false), /* pcrel_offset */ 57060484Sobrien 57160484Sobrien /* 32-bit PC relative */ 57260484Sobrien HOWTO (R_PPC_REL32, /* type */ 57360484Sobrien 0, /* rightshift */ 57460484Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 57560484Sobrien 32, /* bitsize */ 57660484Sobrien true, /* pc_relative */ 57760484Sobrien 0, /* bitpos */ 57860484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 57960484Sobrien bfd_elf_generic_reloc, /* special_function */ 58060484Sobrien "R_PPC_REL32", /* name */ 58160484Sobrien false, /* partial_inplace */ 58260484Sobrien 0, /* src_mask */ 58360484Sobrien 0xffffffff, /* dst_mask */ 58460484Sobrien true), /* pcrel_offset */ 58560484Sobrien 58660484Sobrien /* 32-bit relocation to the symbol's procedure linkage table. 58777298Sobrien FIXME: not supported. */ 58860484Sobrien HOWTO (R_PPC_PLT32, /* type */ 58960484Sobrien 0, /* rightshift */ 59060484Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 59160484Sobrien 32, /* bitsize */ 59260484Sobrien false, /* pc_relative */ 59360484Sobrien 0, /* bitpos */ 59460484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 59560484Sobrien bfd_elf_generic_reloc, /* special_function */ 59660484Sobrien "R_PPC_PLT32", /* name */ 59760484Sobrien false, /* partial_inplace */ 59860484Sobrien 0, /* src_mask */ 59960484Sobrien 0, /* dst_mask */ 60060484Sobrien false), /* pcrel_offset */ 60160484Sobrien 60260484Sobrien /* 32-bit PC relative relocation to the symbol's procedure linkage table. 60377298Sobrien FIXME: not supported. */ 60460484Sobrien HOWTO (R_PPC_PLTREL32, /* type */ 60560484Sobrien 0, /* rightshift */ 60660484Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 60760484Sobrien 32, /* bitsize */ 60860484Sobrien true, /* pc_relative */ 60960484Sobrien 0, /* bitpos */ 61060484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 61160484Sobrien bfd_elf_generic_reloc, /* special_function */ 61260484Sobrien "R_PPC_PLTREL32", /* name */ 61360484Sobrien false, /* partial_inplace */ 61460484Sobrien 0, /* src_mask */ 61560484Sobrien 0, /* dst_mask */ 61660484Sobrien true), /* pcrel_offset */ 61760484Sobrien 61860484Sobrien /* Like R_PPC_ADDR16_LO, but referring to the PLT table entry for 61960484Sobrien the symbol. */ 62060484Sobrien HOWTO (R_PPC_PLT16_LO, /* type */ 62160484Sobrien 0, /* rightshift */ 62260484Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 62360484Sobrien 16, /* bitsize */ 62460484Sobrien false, /* pc_relative */ 62560484Sobrien 0, /* bitpos */ 62660484Sobrien complain_overflow_dont, /* complain_on_overflow */ 62760484Sobrien bfd_elf_generic_reloc, /* special_function */ 62860484Sobrien "R_PPC_PLT16_LO", /* name */ 62960484Sobrien false, /* partial_inplace */ 63060484Sobrien 0, /* src_mask */ 63160484Sobrien 0xffff, /* dst_mask */ 63260484Sobrien false), /* pcrel_offset */ 63360484Sobrien 63460484Sobrien /* Like R_PPC_ADDR16_HI, but referring to the PLT table entry for 63560484Sobrien the symbol. */ 63660484Sobrien HOWTO (R_PPC_PLT16_HI, /* type */ 63760484Sobrien 16, /* rightshift */ 63860484Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 63960484Sobrien 16, /* bitsize */ 64060484Sobrien false, /* pc_relative */ 64160484Sobrien 0, /* bitpos */ 64260484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 64360484Sobrien bfd_elf_generic_reloc, /* special_function */ 64460484Sobrien "R_PPC_PLT16_HI", /* name */ 64560484Sobrien false, /* partial_inplace */ 64660484Sobrien 0, /* src_mask */ 64760484Sobrien 0xffff, /* dst_mask */ 64860484Sobrien false), /* pcrel_offset */ 64960484Sobrien 65060484Sobrien /* Like R_PPC_ADDR16_HA, but referring to the PLT table entry for 65160484Sobrien the symbol. */ 65260484Sobrien HOWTO (R_PPC_PLT16_HA, /* type */ 65360484Sobrien 16, /* rightshift */ 65460484Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 65560484Sobrien 16, /* bitsize */ 65660484Sobrien false, /* pc_relative */ 65760484Sobrien 0, /* bitpos */ 65860484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 65960484Sobrien ppc_elf_addr16_ha_reloc, /* special_function */ 66060484Sobrien "R_PPC_PLT16_HA", /* name */ 66160484Sobrien false, /* partial_inplace */ 66260484Sobrien 0, /* src_mask */ 66360484Sobrien 0xffff, /* dst_mask */ 66460484Sobrien false), /* pcrel_offset */ 66560484Sobrien 66660484Sobrien /* A sign-extended 16 bit value relative to _SDA_BASE_, for use with 66760484Sobrien small data items. */ 66860484Sobrien HOWTO (R_PPC_SDAREL16, /* type */ 66960484Sobrien 0, /* rightshift */ 67060484Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 67160484Sobrien 16, /* bitsize */ 67260484Sobrien false, /* pc_relative */ 67360484Sobrien 0, /* bitpos */ 67460484Sobrien complain_overflow_signed, /* complain_on_overflow */ 67560484Sobrien bfd_elf_generic_reloc, /* special_function */ 67660484Sobrien "R_PPC_SDAREL16", /* name */ 67760484Sobrien false, /* partial_inplace */ 67860484Sobrien 0, /* src_mask */ 67960484Sobrien 0xffff, /* dst_mask */ 68060484Sobrien false), /* pcrel_offset */ 68160484Sobrien 68277298Sobrien /* 32-bit section relative relocation. */ 68360484Sobrien HOWTO (R_PPC_SECTOFF, /* type */ 68460484Sobrien 0, /* rightshift */ 68560484Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 68660484Sobrien 32, /* bitsize */ 68760484Sobrien true, /* pc_relative */ 68860484Sobrien 0, /* bitpos */ 68960484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 69060484Sobrien bfd_elf_generic_reloc, /* special_function */ 69160484Sobrien "R_PPC_SECTOFF", /* name */ 69260484Sobrien false, /* partial_inplace */ 69360484Sobrien 0, /* src_mask */ 69460484Sobrien 0, /* dst_mask */ 69560484Sobrien true), /* pcrel_offset */ 69660484Sobrien 69777298Sobrien /* 16-bit lower half section relative relocation. */ 69860484Sobrien HOWTO (R_PPC_SECTOFF_LO, /* type */ 69960484Sobrien 0, /* rightshift */ 70060484Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 70160484Sobrien 16, /* bitsize */ 70260484Sobrien false, /* pc_relative */ 70360484Sobrien 0, /* bitpos */ 70460484Sobrien complain_overflow_dont, /* complain_on_overflow */ 70560484Sobrien bfd_elf_generic_reloc, /* special_function */ 70660484Sobrien "R_PPC_SECTOFF_LO", /* name */ 70760484Sobrien false, /* partial_inplace */ 70860484Sobrien 0, /* src_mask */ 70960484Sobrien 0xffff, /* dst_mask */ 71060484Sobrien false), /* pcrel_offset */ 71160484Sobrien 71277298Sobrien /* 16-bit upper half section relative relocation. */ 71360484Sobrien HOWTO (R_PPC_SECTOFF_HI, /* type */ 71460484Sobrien 16, /* rightshift */ 71560484Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 71660484Sobrien 16, /* bitsize */ 71760484Sobrien false, /* pc_relative */ 71860484Sobrien 0, /* bitpos */ 71960484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 72060484Sobrien bfd_elf_generic_reloc, /* special_function */ 72160484Sobrien "R_PPC_SECTOFF_HI", /* name */ 72260484Sobrien false, /* partial_inplace */ 72360484Sobrien 0, /* src_mask */ 72460484Sobrien 0xffff, /* dst_mask */ 72560484Sobrien false), /* pcrel_offset */ 72660484Sobrien 72777298Sobrien /* 16-bit upper half adjusted section relative relocation. */ 72860484Sobrien HOWTO (R_PPC_SECTOFF_HA, /* type */ 72960484Sobrien 16, /* rightshift */ 73060484Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 73160484Sobrien 16, /* bitsize */ 73260484Sobrien false, /* pc_relative */ 73360484Sobrien 0, /* bitpos */ 73460484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 73560484Sobrien ppc_elf_addr16_ha_reloc, /* special_function */ 73660484Sobrien "R_PPC_SECTOFF_HA", /* name */ 73760484Sobrien false, /* partial_inplace */ 73860484Sobrien 0, /* src_mask */ 73960484Sobrien 0xffff, /* dst_mask */ 74060484Sobrien false), /* pcrel_offset */ 74160484Sobrien 74260484Sobrien /* The remaining relocs are from the Embedded ELF ABI, and are not 74360484Sobrien in the SVR4 ELF ABI. */ 74460484Sobrien 74560484Sobrien /* 32 bit value resulting from the addend minus the symbol */ 74660484Sobrien HOWTO (R_PPC_EMB_NADDR32, /* type */ 74760484Sobrien 0, /* rightshift */ 74860484Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 74960484Sobrien 32, /* bitsize */ 75060484Sobrien false, /* pc_relative */ 75160484Sobrien 0, /* bitpos */ 75260484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 75360484Sobrien bfd_elf_generic_reloc, /* special_function */ 75460484Sobrien "R_PPC_EMB_NADDR32", /* name */ 75560484Sobrien false, /* partial_inplace */ 75660484Sobrien 0, /* src_mask */ 75760484Sobrien 0xffffffff, /* dst_mask */ 75860484Sobrien false), /* pcrel_offset */ 75960484Sobrien 76060484Sobrien /* 16 bit value resulting from the addend minus the symbol */ 76160484Sobrien HOWTO (R_PPC_EMB_NADDR16, /* type */ 76260484Sobrien 0, /* rightshift */ 76360484Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 76460484Sobrien 16, /* bitsize */ 76560484Sobrien false, /* pc_relative */ 76660484Sobrien 0, /* bitpos */ 76760484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 76860484Sobrien bfd_elf_generic_reloc, /* special_function */ 76960484Sobrien "R_PPC_EMB_NADDR16", /* name */ 77060484Sobrien false, /* partial_inplace */ 77160484Sobrien 0, /* src_mask */ 77260484Sobrien 0xffff, /* dst_mask */ 77360484Sobrien false), /* pcrel_offset */ 77460484Sobrien 77560484Sobrien /* 16 bit value resulting from the addend minus the symbol */ 77660484Sobrien HOWTO (R_PPC_EMB_NADDR16_LO, /* type */ 77760484Sobrien 0, /* rightshift */ 77860484Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 77960484Sobrien 16, /* bitsize */ 78060484Sobrien false, /* pc_relative */ 78160484Sobrien 0, /* bitpos */ 78260484Sobrien complain_overflow_dont,/* complain_on_overflow */ 78360484Sobrien bfd_elf_generic_reloc, /* special_function */ 78460484Sobrien "R_PPC_EMB_ADDR16_LO", /* name */ 78560484Sobrien false, /* partial_inplace */ 78660484Sobrien 0, /* src_mask */ 78760484Sobrien 0xffff, /* dst_mask */ 78860484Sobrien false), /* pcrel_offset */ 78960484Sobrien 79060484Sobrien /* The high order 16 bits of the addend minus the symbol */ 79160484Sobrien HOWTO (R_PPC_EMB_NADDR16_HI, /* type */ 79260484Sobrien 16, /* rightshift */ 79360484Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 79460484Sobrien 16, /* bitsize */ 79560484Sobrien false, /* pc_relative */ 79660484Sobrien 0, /* bitpos */ 79760484Sobrien complain_overflow_dont, /* complain_on_overflow */ 79860484Sobrien bfd_elf_generic_reloc, /* special_function */ 79960484Sobrien "R_PPC_EMB_NADDR16_HI", /* name */ 80060484Sobrien false, /* partial_inplace */ 80160484Sobrien 0, /* src_mask */ 80260484Sobrien 0xffff, /* dst_mask */ 80360484Sobrien false), /* pcrel_offset */ 80460484Sobrien 80560484Sobrien /* The high order 16 bits of the result of the addend minus the address, 80660484Sobrien plus 1 if the contents of the low 16 bits, treated as a signed number, 80760484Sobrien is negative. */ 80860484Sobrien HOWTO (R_PPC_EMB_NADDR16_HA, /* type */ 80960484Sobrien 16, /* rightshift */ 81060484Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 81160484Sobrien 16, /* bitsize */ 81260484Sobrien false, /* pc_relative */ 81360484Sobrien 0, /* bitpos */ 81460484Sobrien complain_overflow_dont, /* complain_on_overflow */ 81560484Sobrien ppc_elf_addr16_ha_reloc, /* special_function */ 81660484Sobrien "R_PPC_EMB_NADDR16_HA", /* name */ 81760484Sobrien false, /* partial_inplace */ 81860484Sobrien 0, /* src_mask */ 81960484Sobrien 0xffff, /* dst_mask */ 82060484Sobrien false), /* pcrel_offset */ 82160484Sobrien 82260484Sobrien /* 16 bit value resulting from allocating a 4 byte word to hold an 82360484Sobrien address in the .sdata section, and returning the offset from 82460484Sobrien _SDA_BASE_ for that relocation */ 82560484Sobrien HOWTO (R_PPC_EMB_SDAI16, /* type */ 82660484Sobrien 0, /* rightshift */ 82760484Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 82860484Sobrien 16, /* bitsize */ 82960484Sobrien false, /* pc_relative */ 83060484Sobrien 0, /* bitpos */ 83160484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 83260484Sobrien bfd_elf_generic_reloc, /* special_function */ 83360484Sobrien "R_PPC_EMB_SDAI16", /* name */ 83460484Sobrien false, /* partial_inplace */ 83560484Sobrien 0, /* src_mask */ 83660484Sobrien 0xffff, /* dst_mask */ 83760484Sobrien false), /* pcrel_offset */ 83860484Sobrien 83960484Sobrien /* 16 bit value resulting from allocating a 4 byte word to hold an 84060484Sobrien address in the .sdata2 section, and returning the offset from 84160484Sobrien _SDA2_BASE_ for that relocation */ 84260484Sobrien HOWTO (R_PPC_EMB_SDA2I16, /* type */ 84360484Sobrien 0, /* rightshift */ 84460484Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 84560484Sobrien 16, /* bitsize */ 84660484Sobrien false, /* pc_relative */ 84760484Sobrien 0, /* bitpos */ 84860484Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 84960484Sobrien bfd_elf_generic_reloc, /* special_function */ 85060484Sobrien "R_PPC_EMB_SDA2I16", /* name */ 85160484Sobrien false, /* partial_inplace */ 85260484Sobrien 0, /* src_mask */ 85360484Sobrien 0xffff, /* dst_mask */ 85460484Sobrien false), /* pcrel_offset */ 85560484Sobrien 85660484Sobrien /* A sign-extended 16 bit value relative to _SDA2_BASE_, for use with 85760484Sobrien small data items. */ 85860484Sobrien HOWTO (R_PPC_EMB_SDA2REL, /* type */ 85960484Sobrien 0, /* rightshift */ 86060484Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 86160484Sobrien 16, /* bitsize */ 86260484Sobrien false, /* pc_relative */ 86360484Sobrien 0, /* bitpos */ 86460484Sobrien complain_overflow_signed, /* complain_on_overflow */ 86560484Sobrien bfd_elf_generic_reloc, /* special_function */ 86660484Sobrien "R_PPC_EMB_SDA2REL", /* name */ 86760484Sobrien false, /* partial_inplace */ 86860484Sobrien 0, /* src_mask */ 86960484Sobrien 0xffff, /* dst_mask */ 87060484Sobrien false), /* pcrel_offset */ 87160484Sobrien 87260484Sobrien /* Relocate against either _SDA_BASE_ or _SDA2_BASE_, filling in the 16 bit 87360484Sobrien signed offset from the appropriate base, and filling in the register 87460484Sobrien field with the appropriate register (0, 2, or 13). */ 87560484Sobrien HOWTO (R_PPC_EMB_SDA21, /* type */ 87660484Sobrien 0, /* rightshift */ 87760484Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 87860484Sobrien 16, /* bitsize */ 87960484Sobrien false, /* pc_relative */ 88060484Sobrien 0, /* bitpos */ 88160484Sobrien complain_overflow_signed, /* complain_on_overflow */ 88260484Sobrien bfd_elf_generic_reloc, /* special_function */ 88360484Sobrien "R_PPC_EMB_SDA21", /* name */ 88460484Sobrien false, /* partial_inplace */ 88560484Sobrien 0, /* src_mask */ 88660484Sobrien 0xffff, /* dst_mask */ 88760484Sobrien false), /* pcrel_offset */ 88860484Sobrien 88960484Sobrien /* Relocation not handled: R_PPC_EMB_MRKREF */ 89060484Sobrien /* Relocation not handled: R_PPC_EMB_RELSEC16 */ 89160484Sobrien /* Relocation not handled: R_PPC_EMB_RELST_LO */ 89260484Sobrien /* Relocation not handled: R_PPC_EMB_RELST_HI */ 89360484Sobrien /* Relocation not handled: R_PPC_EMB_RELST_HA */ 89460484Sobrien /* Relocation not handled: R_PPC_EMB_BIT_FLD */ 89560484Sobrien 89660484Sobrien /* PC relative relocation against either _SDA_BASE_ or _SDA2_BASE_, filling 89760484Sobrien in the 16 bit signed offset from the appropriate base, and filling in the 89860484Sobrien register field with the appropriate register (0, 2, or 13). */ 89960484Sobrien HOWTO (R_PPC_EMB_RELSDA, /* type */ 90060484Sobrien 0, /* rightshift */ 90160484Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 90260484Sobrien 16, /* bitsize */ 90360484Sobrien true, /* pc_relative */ 90460484Sobrien 0, /* bitpos */ 90560484Sobrien complain_overflow_signed, /* complain_on_overflow */ 90660484Sobrien bfd_elf_generic_reloc, /* special_function */ 90760484Sobrien "R_PPC_EMB_RELSDA", /* name */ 90860484Sobrien false, /* partial_inplace */ 90960484Sobrien 0, /* src_mask */ 91060484Sobrien 0xffff, /* dst_mask */ 91160484Sobrien false), /* pcrel_offset */ 91260484Sobrien 91360484Sobrien /* GNU extension to record C++ vtable hierarchy */ 91460484Sobrien HOWTO (R_PPC_GNU_VTINHERIT, /* type */ 91560484Sobrien 0, /* rightshift */ 91660484Sobrien 0, /* size (0 = byte, 1 = short, 2 = long) */ 91760484Sobrien 0, /* bitsize */ 91860484Sobrien false, /* pc_relative */ 91960484Sobrien 0, /* bitpos */ 92060484Sobrien complain_overflow_dont, /* complain_on_overflow */ 92160484Sobrien NULL, /* special_function */ 92260484Sobrien "R_PPC_GNU_VTINHERIT", /* name */ 92360484Sobrien false, /* partial_inplace */ 92460484Sobrien 0, /* src_mask */ 92560484Sobrien 0, /* dst_mask */ 92660484Sobrien false), /* pcrel_offset */ 92760484Sobrien 92860484Sobrien /* GNU extension to record C++ vtable member usage */ 92960484Sobrien HOWTO (R_PPC_GNU_VTENTRY, /* type */ 93060484Sobrien 0, /* rightshift */ 93160484Sobrien 0, /* size (0 = byte, 1 = short, 2 = long) */ 93260484Sobrien 0, /* bitsize */ 93360484Sobrien false, /* pc_relative */ 93460484Sobrien 0, /* bitpos */ 93560484Sobrien complain_overflow_dont, /* complain_on_overflow */ 93660484Sobrien NULL, /* special_function */ 93760484Sobrien "R_PPC_GNU_VTENTRY", /* name */ 93860484Sobrien false, /* partial_inplace */ 93960484Sobrien 0, /* src_mask */ 94060484Sobrien 0, /* dst_mask */ 94160484Sobrien false), /* pcrel_offset */ 94260484Sobrien 94360484Sobrien /* Phony reloc to handle AIX style TOC entries */ 94460484Sobrien HOWTO (R_PPC_TOC16, /* type */ 94560484Sobrien 0, /* rightshift */ 94660484Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 94760484Sobrien 16, /* bitsize */ 94860484Sobrien false, /* pc_relative */ 94960484Sobrien 0, /* bitpos */ 95060484Sobrien complain_overflow_signed, /* complain_on_overflow */ 95160484Sobrien bfd_elf_generic_reloc, /* special_function */ 95260484Sobrien "R_PPC_TOC16", /* name */ 95360484Sobrien false, /* partial_inplace */ 95460484Sobrien 0, /* src_mask */ 95560484Sobrien 0xffff, /* dst_mask */ 95660484Sobrien false), /* pcrel_offset */ 95760484Sobrien}; 95860484Sobrien 95960484Sobrien/* Initialize the ppc_elf_howto_table, so that linear accesses can be done. */ 96060484Sobrien 96160484Sobrienstatic void 96260484Sobrienppc_elf_howto_init () 96360484Sobrien{ 96460484Sobrien unsigned int i, type; 96560484Sobrien 96660484Sobrien for (i = 0; i < sizeof (ppc_elf_howto_raw) / sizeof (ppc_elf_howto_raw[0]); i++) 96760484Sobrien { 96860484Sobrien type = ppc_elf_howto_raw[i].type; 96977298Sobrien BFD_ASSERT (type < sizeof (ppc_elf_howto_table) / sizeof (ppc_elf_howto_table[0])); 97060484Sobrien ppc_elf_howto_table[type] = &ppc_elf_howto_raw[i]; 97160484Sobrien } 97260484Sobrien} 97360484Sobrien 97460484Sobrien/* This function handles relaxing for the PPC with option --mpc860c0[=<n>]. 97560484Sobrien 97660484Sobrien The MPC860, revision C0 or earlier contains a bug in the die. 97760484Sobrien If all of the following conditions are true, the next instruction 97860484Sobrien to be executed *may* be treated as a no-op. 97960484Sobrien 1/ A forward branch is executed. 98060484Sobrien 2/ The branch is predicted as not taken. 98160484Sobrien 3/ The branch is taken. 98260484Sobrien 4/ The branch is located in the last 5 words of a page. 98360484Sobrien (The EOP limit is 5 by default but may be specified as any value from 1-10.) 98477298Sobrien 98560484Sobrien Our software solution is to detect these problematic branches in a 98660484Sobrien linker pass and modify them as follows: 98760484Sobrien 1/ Unconditional branches - Since these are always predicted taken, 98860484Sobrien there is no problem and no action is required. 98960484Sobrien 2/ Conditional backward branches - No problem, no action required. 99060484Sobrien 3/ Conditional forward branches - Ensure that the "inverse prediction 99160484Sobrien bit" is set (ensure it is predicted taken). 99260484Sobrien 4/ Conditional register branches - Ensure that the "y bit" is set 99360484Sobrien (ensure it is predicted taken). 99460484Sobrien*/ 99560484Sobrien 99660484Sobrien/* Sort sections by address. */ 99760484Sobrien 99860484Sobrienstatic int 99960484Sobrienppc_elf_sort_rela (arg1, arg2) 100089857Sobrien const PTR arg1; 100189857Sobrien const PTR arg2; 100260484Sobrien{ 100360484Sobrien const Elf_Internal_Rela **rela1 = (const Elf_Internal_Rela**) arg1; 100460484Sobrien const Elf_Internal_Rela **rela2 = (const Elf_Internal_Rela**) arg2; 100560484Sobrien 100677298Sobrien /* Sort by offset. */ 100760484Sobrien return ((*rela1)->r_offset - (*rela2)->r_offset); 100860484Sobrien} 100960484Sobrien 101060484Sobrienstatic boolean 101160484Sobrienppc_elf_relax_section (abfd, isec, link_info, again) 101277298Sobrien bfd *abfd; 101377298Sobrien asection *isec; 101477298Sobrien struct bfd_link_info *link_info; 101577298Sobrien boolean *again; 101660484Sobrien{ 101760484Sobrien#define PAGESIZE 0x1000 101860484Sobrien 101960484Sobrien bfd_byte *contents = NULL; 102060484Sobrien bfd_byte *free_contents = NULL; 102160484Sobrien Elf_Internal_Rela *internal_relocs = NULL; 102260484Sobrien Elf_Internal_Rela *free_relocs = NULL; 102360484Sobrien Elf_Internal_Rela **rela_comb = NULL; 102460484Sobrien int comb_curr, comb_count; 102560484Sobrien 102677298Sobrien /* We never have to do this more than once per input section. */ 102760484Sobrien *again = false; 102860484Sobrien 102960484Sobrien /* If needed, initialize this section's cooked size. */ 103060484Sobrien if (isec->_cooked_size == 0) 103160484Sobrien isec->_cooked_size = isec->_raw_size; 103260484Sobrien 103360484Sobrien /* We're only interested in text sections which overlap the 103477298Sobrien troublesome area at the end of a page. */ 103560484Sobrien if (link_info->mpc860c0 && (isec->flags & SEC_CODE) && isec->_cooked_size) 103660484Sobrien { 103760484Sobrien bfd_vma dot, end_page, end_section; 103860484Sobrien boolean section_modified; 103960484Sobrien 104077298Sobrien /* Get the section contents. */ 104160484Sobrien /* Get cached copy if it exists. */ 104260484Sobrien if (elf_section_data (isec)->this_hdr.contents != NULL) 104360484Sobrien contents = elf_section_data (isec)->this_hdr.contents; 104460484Sobrien else 104560484Sobrien { 104660484Sobrien /* Go get them off disk. */ 104760484Sobrien contents = (bfd_byte *) bfd_malloc (isec->_raw_size); 104860484Sobrien if (contents == NULL) 104977298Sobrien goto error_return; 105060484Sobrien free_contents = contents; 105160484Sobrien 105260484Sobrien if (! bfd_get_section_contents (abfd, isec, contents, 105360484Sobrien (file_ptr) 0, isec->_raw_size)) 105477298Sobrien goto error_return; 105560484Sobrien } 105660484Sobrien 105760484Sobrien comb_curr = 0; 105860484Sobrien comb_count = 0; 105960484Sobrien if (isec->reloc_count) 106077298Sobrien { 106160484Sobrien unsigned n; 106289857Sobrien bfd_size_type amt; 106360484Sobrien 106460484Sobrien /* Get a copy of the native relocations. */ 106560484Sobrien internal_relocs = _bfd_elf32_link_read_relocs ( 106677298Sobrien abfd, isec, (PTR) NULL, (Elf_Internal_Rela *) NULL, 106760484Sobrien link_info->keep_memory); 106860484Sobrien if (internal_relocs == NULL) 106960484Sobrien goto error_return; 107060484Sobrien if (! link_info->keep_memory) 107160484Sobrien free_relocs = internal_relocs; 107277298Sobrien 107377298Sobrien /* Setup a faster access method for the reloc info we need. */ 107489857Sobrien amt = isec->reloc_count; 107589857Sobrien amt *= sizeof (Elf_Internal_Rela*); 107689857Sobrien rela_comb = (Elf_Internal_Rela**) bfd_malloc (amt); 107760484Sobrien if (rela_comb == NULL) 107860484Sobrien goto error_return; 107977298Sobrien for (n = 0; n < isec->reloc_count; ++n) 108060484Sobrien { 108160484Sobrien long r_type; 108277298Sobrien 108360484Sobrien r_type = ELF32_R_TYPE (internal_relocs[n].r_info); 108477298Sobrien if (r_type < 0 || r_type >= (int) R_PPC_max) 108560484Sobrien goto error_return; 108677298Sobrien 108760484Sobrien /* Prologue constants are sometimes present in the ".text" 108860484Sobrien sections and they can be identified by their associated relocation. 108960484Sobrien We don't want to process those words and some others which 109060484Sobrien can also be identified by their relocations. However, not all 109160484Sobrien conditional branches will have a relocation so we will 109260484Sobrien only ignore words that 1) have a reloc, and 2) the reloc 109360484Sobrien is not applicable to a conditional branch. 109477298Sobrien The array rela_comb is built here for use in the EOP scan loop. */ 109560484Sobrien switch (r_type) 109660484Sobrien { 109760484Sobrien case R_PPC_ADDR14_BRNTAKEN: /* absolute, predicted not taken */ 109877298Sobrien case R_PPC_REL14: /* relative cond. br. */ 109960484Sobrien case R_PPC_REL14_BRNTAKEN: /* rel. cond. br., predicted not taken */ 110077298Sobrien /* We should check the instruction. */ 110160484Sobrien break; 110260484Sobrien default: 110377298Sobrien /* The word is not a conditional branch - ignore it. */ 110460484Sobrien rela_comb[comb_count++] = &internal_relocs[n]; 110560484Sobrien break; 110660484Sobrien } 110760484Sobrien } 110860484Sobrien if (comb_count > 1) 110977298Sobrien qsort (rela_comb, (size_t) comb_count, sizeof (int), ppc_elf_sort_rela); 111077298Sobrien } 111160484Sobrien 111277298Sobrien /* Enumerate each EOP region that overlaps this section. */ 111360484Sobrien end_section = isec->vma + isec->_cooked_size; 111460484Sobrien dot = end_page = (isec->vma | (PAGESIZE - 1)) + 1; 111560484Sobrien dot -= link_info->mpc860c0; 111660484Sobrien section_modified = false; 111760484Sobrien if (dot < isec->vma) /* Increment the start position if this section */ 111877298Sobrien dot = isec->vma; /* begins in the middle of its first EOP region. */ 111960484Sobrien for (; 112060484Sobrien dot < end_section; 112160484Sobrien dot += PAGESIZE, end_page += PAGESIZE) 112260484Sobrien { 112360484Sobrien 112477298Sobrien /* Check each word in this EOP region. */ 112560484Sobrien for (; dot < end_page; dot += 4) 112660484Sobrien { 112760484Sobrien bfd_vma isec_offset; 112860484Sobrien unsigned long insn; 112960484Sobrien boolean skip, modified; 113060484Sobrien 113160484Sobrien /* Don't process this word if there is a relocation for it and 113277298Sobrien the relocation indicates the word is not a conditional branch. */ 113360484Sobrien skip = false; 113460484Sobrien isec_offset = dot - isec->vma; 113560484Sobrien for (; comb_curr<comb_count; ++comb_curr) 113660484Sobrien { 113760484Sobrien bfd_vma r_offset; 113860484Sobrien 113960484Sobrien r_offset = rela_comb[comb_curr]->r_offset; 114060484Sobrien if (r_offset >= isec_offset) 114160484Sobrien { 114260484Sobrien if (r_offset == isec_offset) skip = true; 114360484Sobrien break; 114460484Sobrien } 114560484Sobrien } 114660484Sobrien if (skip) continue; 114760484Sobrien 114877298Sobrien /* Check the current word for a problematic conditional branch. */ 114960484Sobrien#define BO0(insn) ((insn) & 0x02000000) 115060484Sobrien#define BO2(insn) ((insn) & 0x00800000) 115160484Sobrien#define BO4(insn) ((insn) & 0x00200000) 115260484Sobrien insn = (unsigned long) bfd_get_32 (abfd, contents + isec_offset); 115360484Sobrien modified = false; 115460484Sobrien if ((insn & 0xFc000000) == 0x40000000) 115560484Sobrien { 115660484Sobrien /* Instruction is BCx */ 115760484Sobrien if ((!BO0(insn) || !BO2(insn)) && !BO4(insn)) 115860484Sobrien { 115960484Sobrien bfd_vma target; 116060484Sobrien /* This branch is predicted as "normal". 116177298Sobrien If this is a forward branch, it is problematic. */ 116260484Sobrien 116360484Sobrien target = insn & 0x0000Fffc; /*extract*/ 116460484Sobrien target = (target ^ 0x8000) - 0x8000; /*sign extend*/ 116560484Sobrien if ((insn & 0x00000002) == 0) 116660484Sobrien target += dot; /*convert to abs*/ 116760484Sobrien if (target > dot) 116860484Sobrien { 116960484Sobrien insn |= 0x00200000; /* set the prediction bit */ 117060484Sobrien modified = true; 117160484Sobrien } 117260484Sobrien } 117360484Sobrien } 117460484Sobrien else if ((insn & 0xFc00Fffe) == 0x4c000420) 117560484Sobrien { 117660484Sobrien /* Instruction is BCCTRx */ 117760484Sobrien if ((!BO0(insn) || !BO2(insn)) && !BO4(insn)) 117860484Sobrien { 117960484Sobrien /* This branch is predicted as not-taken. 118060484Sobrien If this is a forward branch, it is problematic. 118160484Sobrien Since we can't tell statically if it will branch forward, 118277298Sobrien always set the prediction bit. */ 118360484Sobrien insn |= 0x00200000; /* set the prediction bit */ 118460484Sobrien modified = true; 118560484Sobrien } 118660484Sobrien } 118760484Sobrien else if ((insn & 0xFc00Fffe) == 0x4c000020) 118860484Sobrien { 118960484Sobrien /* Instruction is BCLRx */ 119060484Sobrien if ((!BO0(insn) || !BO2(insn)) && !BO4(insn)) 119160484Sobrien { 119260484Sobrien /* This branch is predicted as not-taken. 119360484Sobrien If this is a forward branch, it is problematic. 119460484Sobrien Since we can't tell statically if it will branch forward, 119577298Sobrien always set the prediction bit. */ 119660484Sobrien insn |= 0x00200000; /* set the prediction bit */ 119760484Sobrien modified = true; 119860484Sobrien } 119960484Sobrien } 120060484Sobrien#undef BO0 120160484Sobrien#undef BO2 120260484Sobrien#undef BO4 120360484Sobrien if (modified) 120460484Sobrien { 120589857Sobrien bfd_put_32 (abfd, (bfd_vma) insn, contents + isec_offset); 120660484Sobrien section_modified = true; 120760484Sobrien } 120860484Sobrien } 120960484Sobrien } 121060484Sobrien if (section_modified) 121160484Sobrien { 121260484Sobrien elf_section_data (isec)->this_hdr.contents = contents; 121360484Sobrien free_contents = NULL; 121460484Sobrien } 121560484Sobrien } 121660484Sobrien 121760484Sobrien if (rela_comb != NULL) 121860484Sobrien { 121960484Sobrien free (rela_comb); 122060484Sobrien rela_comb = NULL; 122160484Sobrien } 122260484Sobrien 122360484Sobrien if (free_relocs != NULL) 122460484Sobrien { 122560484Sobrien free (free_relocs); 122660484Sobrien free_relocs = NULL; 122760484Sobrien } 122860484Sobrien 122960484Sobrien if (free_contents != NULL) 123060484Sobrien { 123160484Sobrien if (! link_info->keep_memory) 123260484Sobrien free (free_contents); 123360484Sobrien else 123460484Sobrien { 123560484Sobrien /* Cache the section contents for elf_link_input_bfd. */ 123660484Sobrien elf_section_data (isec)->this_hdr.contents = contents; 123760484Sobrien } 123860484Sobrien free_contents = NULL; 123960484Sobrien } 124060484Sobrien 124160484Sobrien return true; 124260484Sobrien 124360484Sobrienerror_return: 124460484Sobrien if (rela_comb != NULL) 124560484Sobrien free (rela_comb); 124660484Sobrien if (free_relocs != NULL) 124760484Sobrien free (free_relocs); 124860484Sobrien if (free_contents != NULL) 124960484Sobrien free (free_contents); 125060484Sobrien return false; 125160484Sobrien} 125260484Sobrien 125360484Sobrienstatic reloc_howto_type * 125460484Sobrienppc_elf_reloc_type_lookup (abfd, code) 125560484Sobrien bfd *abfd ATTRIBUTE_UNUSED; 125660484Sobrien bfd_reloc_code_real_type code; 125760484Sobrien{ 125860484Sobrien enum elf_ppc_reloc_type ppc_reloc = R_PPC_NONE; 125960484Sobrien 126060484Sobrien if (!ppc_elf_howto_table[R_PPC_ADDR32]) 126177298Sobrien /* Initialize howto table if needed. */ 126260484Sobrien ppc_elf_howto_init (); 126360484Sobrien 126477298Sobrien switch ((int) code) 126560484Sobrien { 126660484Sobrien default: 126777298Sobrien return (reloc_howto_type *) NULL; 126860484Sobrien 126960484Sobrien case BFD_RELOC_NONE: ppc_reloc = R_PPC_NONE; break; 127060484Sobrien case BFD_RELOC_32: ppc_reloc = R_PPC_ADDR32; break; 127160484Sobrien case BFD_RELOC_PPC_BA26: ppc_reloc = R_PPC_ADDR24; break; 127260484Sobrien case BFD_RELOC_16: ppc_reloc = R_PPC_ADDR16; break; 127360484Sobrien case BFD_RELOC_LO16: ppc_reloc = R_PPC_ADDR16_LO; break; 127460484Sobrien case BFD_RELOC_HI16: ppc_reloc = R_PPC_ADDR16_HI; break; 127560484Sobrien case BFD_RELOC_HI16_S: ppc_reloc = R_PPC_ADDR16_HA; break; 127660484Sobrien case BFD_RELOC_PPC_BA16: ppc_reloc = R_PPC_ADDR14; break; 127760484Sobrien case BFD_RELOC_PPC_BA16_BRTAKEN: ppc_reloc = R_PPC_ADDR14_BRTAKEN; break; 127860484Sobrien case BFD_RELOC_PPC_BA16_BRNTAKEN: ppc_reloc = R_PPC_ADDR14_BRNTAKEN; break; 127960484Sobrien case BFD_RELOC_PPC_B26: ppc_reloc = R_PPC_REL24; break; 128060484Sobrien case BFD_RELOC_PPC_B16: ppc_reloc = R_PPC_REL14; break; 128160484Sobrien case BFD_RELOC_PPC_B16_BRTAKEN: ppc_reloc = R_PPC_REL14_BRTAKEN; break; 128260484Sobrien case BFD_RELOC_PPC_B16_BRNTAKEN: ppc_reloc = R_PPC_REL14_BRNTAKEN; break; 128360484Sobrien case BFD_RELOC_16_GOTOFF: ppc_reloc = R_PPC_GOT16; break; 128460484Sobrien case BFD_RELOC_LO16_GOTOFF: ppc_reloc = R_PPC_GOT16_LO; break; 128560484Sobrien case BFD_RELOC_HI16_GOTOFF: ppc_reloc = R_PPC_GOT16_HI; break; 128660484Sobrien case BFD_RELOC_HI16_S_GOTOFF: ppc_reloc = R_PPC_GOT16_HA; break; 128760484Sobrien case BFD_RELOC_24_PLT_PCREL: ppc_reloc = R_PPC_PLTREL24; break; 128860484Sobrien case BFD_RELOC_PPC_COPY: ppc_reloc = R_PPC_COPY; break; 128960484Sobrien case BFD_RELOC_PPC_GLOB_DAT: ppc_reloc = R_PPC_GLOB_DAT; break; 129060484Sobrien case BFD_RELOC_PPC_LOCAL24PC: ppc_reloc = R_PPC_LOCAL24PC; break; 129160484Sobrien case BFD_RELOC_32_PCREL: ppc_reloc = R_PPC_REL32; break; 129260484Sobrien case BFD_RELOC_32_PLTOFF: ppc_reloc = R_PPC_PLT32; break; 129360484Sobrien case BFD_RELOC_32_PLT_PCREL: ppc_reloc = R_PPC_PLTREL32; break; 129460484Sobrien case BFD_RELOC_LO16_PLTOFF: ppc_reloc = R_PPC_PLT16_LO; break; 129560484Sobrien case BFD_RELOC_HI16_PLTOFF: ppc_reloc = R_PPC_PLT16_HI; break; 129660484Sobrien case BFD_RELOC_HI16_S_PLTOFF: ppc_reloc = R_PPC_PLT16_HA; break; 129760484Sobrien case BFD_RELOC_GPREL16: ppc_reloc = R_PPC_SDAREL16; break; 129860484Sobrien case BFD_RELOC_32_BASEREL: ppc_reloc = R_PPC_SECTOFF; break; 129960484Sobrien case BFD_RELOC_LO16_BASEREL: ppc_reloc = R_PPC_SECTOFF_LO; break; 130060484Sobrien case BFD_RELOC_HI16_BASEREL: ppc_reloc = R_PPC_SECTOFF_HI; break; 130160484Sobrien case BFD_RELOC_HI16_S_BASEREL: ppc_reloc = R_PPC_SECTOFF_HA; break; 130260484Sobrien case BFD_RELOC_CTOR: ppc_reloc = R_PPC_ADDR32; break; 130360484Sobrien case BFD_RELOC_PPC_TOC16: ppc_reloc = R_PPC_TOC16; break; 130460484Sobrien case BFD_RELOC_PPC_EMB_NADDR32: ppc_reloc = R_PPC_EMB_NADDR32; break; 130560484Sobrien case BFD_RELOC_PPC_EMB_NADDR16: ppc_reloc = R_PPC_EMB_NADDR16; break; 130660484Sobrien case BFD_RELOC_PPC_EMB_NADDR16_LO: ppc_reloc = R_PPC_EMB_NADDR16_LO; break; 130760484Sobrien case BFD_RELOC_PPC_EMB_NADDR16_HI: ppc_reloc = R_PPC_EMB_NADDR16_HI; break; 130860484Sobrien case BFD_RELOC_PPC_EMB_NADDR16_HA: ppc_reloc = R_PPC_EMB_NADDR16_HA; break; 130960484Sobrien case BFD_RELOC_PPC_EMB_SDAI16: ppc_reloc = R_PPC_EMB_SDAI16; break; 131060484Sobrien case BFD_RELOC_PPC_EMB_SDA2I16: ppc_reloc = R_PPC_EMB_SDA2I16; break; 131160484Sobrien case BFD_RELOC_PPC_EMB_SDA2REL: ppc_reloc = R_PPC_EMB_SDA2REL; break; 131260484Sobrien case BFD_RELOC_PPC_EMB_SDA21: ppc_reloc = R_PPC_EMB_SDA21; break; 131360484Sobrien case BFD_RELOC_PPC_EMB_MRKREF: ppc_reloc = R_PPC_EMB_MRKREF; break; 131460484Sobrien case BFD_RELOC_PPC_EMB_RELSEC16: ppc_reloc = R_PPC_EMB_RELSEC16; break; 131560484Sobrien case BFD_RELOC_PPC_EMB_RELST_LO: ppc_reloc = R_PPC_EMB_RELST_LO; break; 131660484Sobrien case BFD_RELOC_PPC_EMB_RELST_HI: ppc_reloc = R_PPC_EMB_RELST_HI; break; 131760484Sobrien case BFD_RELOC_PPC_EMB_RELST_HA: ppc_reloc = R_PPC_EMB_RELST_HA; break; 131860484Sobrien case BFD_RELOC_PPC_EMB_BIT_FLD: ppc_reloc = R_PPC_EMB_BIT_FLD; break; 131960484Sobrien case BFD_RELOC_PPC_EMB_RELSDA: ppc_reloc = R_PPC_EMB_RELSDA; break; 132060484Sobrien case BFD_RELOC_VTABLE_INHERIT: ppc_reloc = R_PPC_GNU_VTINHERIT; break; 132160484Sobrien case BFD_RELOC_VTABLE_ENTRY: ppc_reloc = R_PPC_GNU_VTENTRY; break; 132260484Sobrien } 132360484Sobrien 132477298Sobrien return ppc_elf_howto_table[(int) ppc_reloc]; 132560484Sobrien}; 132660484Sobrien 132760484Sobrien/* Set the howto pointer for a PowerPC ELF reloc. */ 132860484Sobrien 132960484Sobrienstatic void 133060484Sobrienppc_elf_info_to_howto (abfd, cache_ptr, dst) 133160484Sobrien bfd *abfd ATTRIBUTE_UNUSED; 133260484Sobrien arelent *cache_ptr; 133360484Sobrien Elf32_Internal_Rela *dst; 133460484Sobrien{ 133577298Sobrien if (!ppc_elf_howto_table[R_PPC_ADDR32]) 133677298Sobrien /* Initialize howto table if needed. */ 133760484Sobrien ppc_elf_howto_init (); 133860484Sobrien 133960484Sobrien BFD_ASSERT (ELF32_R_TYPE (dst->r_info) < (unsigned int) R_PPC_max); 134060484Sobrien cache_ptr->howto = ppc_elf_howto_table[ELF32_R_TYPE (dst->r_info)]; 134160484Sobrien} 134260484Sobrien 134360484Sobrien/* Handle the R_PPC_ADDR16_HA reloc. */ 134460484Sobrien 134560484Sobrienstatic bfd_reloc_status_type 134660484Sobrienppc_elf_addr16_ha_reloc (abfd, reloc_entry, symbol, data, input_section, 134760484Sobrien output_bfd, error_message) 134860484Sobrien bfd *abfd ATTRIBUTE_UNUSED; 134960484Sobrien arelent *reloc_entry; 135060484Sobrien asymbol *symbol; 135160484Sobrien PTR data ATTRIBUTE_UNUSED; 135260484Sobrien asection *input_section; 135360484Sobrien bfd *output_bfd; 135460484Sobrien char **error_message ATTRIBUTE_UNUSED; 135560484Sobrien{ 135660484Sobrien bfd_vma relocation; 135760484Sobrien 135860484Sobrien if (output_bfd != NULL) 135960484Sobrien { 136060484Sobrien reloc_entry->address += input_section->output_offset; 136160484Sobrien return bfd_reloc_ok; 136260484Sobrien } 136360484Sobrien 136460484Sobrien if (reloc_entry->address > input_section->_cooked_size) 136560484Sobrien return bfd_reloc_outofrange; 136660484Sobrien 136760484Sobrien if (bfd_is_com_section (symbol->section)) 136860484Sobrien relocation = 0; 136960484Sobrien else 137060484Sobrien relocation = symbol->value; 137160484Sobrien 137260484Sobrien relocation += symbol->section->output_section->vma; 137360484Sobrien relocation += symbol->section->output_offset; 137460484Sobrien relocation += reloc_entry->addend; 137560484Sobrien 137660484Sobrien reloc_entry->addend += (relocation & 0x8000) << 1; 137760484Sobrien 137860484Sobrien return bfd_reloc_continue; 137960484Sobrien} 138060484Sobrien 138177298Sobrien/* Function to set whether a module needs the -mrelocatable bit set. */ 138260484Sobrien 138360484Sobrienstatic boolean 138460484Sobrienppc_elf_set_private_flags (abfd, flags) 138560484Sobrien bfd *abfd; 138660484Sobrien flagword flags; 138760484Sobrien{ 138860484Sobrien BFD_ASSERT (!elf_flags_init (abfd) 138960484Sobrien || elf_elfheader (abfd)->e_flags == flags); 139060484Sobrien 139160484Sobrien elf_elfheader (abfd)->e_flags = flags; 139260484Sobrien elf_flags_init (abfd) = true; 139360484Sobrien return true; 139460484Sobrien} 139560484Sobrien 139660484Sobrien/* Merge backend specific data from an object file to the output 139760484Sobrien object file when linking */ 139860484Sobrienstatic boolean 139960484Sobrienppc_elf_merge_private_bfd_data (ibfd, obfd) 140060484Sobrien bfd *ibfd; 140160484Sobrien bfd *obfd; 140260484Sobrien{ 140360484Sobrien flagword old_flags; 140460484Sobrien flagword new_flags; 140560484Sobrien boolean error; 140660484Sobrien 140760484Sobrien /* Check if we have the same endianess */ 140877298Sobrien if (_bfd_generic_verify_endian_match (ibfd, obfd) == false) 140977298Sobrien return false; 141060484Sobrien 141160484Sobrien if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour 141260484Sobrien || bfd_get_flavour (obfd) != bfd_target_elf_flavour) 141360484Sobrien return true; 141460484Sobrien 141560484Sobrien new_flags = elf_elfheader (ibfd)->e_flags; 141660484Sobrien old_flags = elf_elfheader (obfd)->e_flags; 141760484Sobrien if (!elf_flags_init (obfd)) /* First call, no flags set */ 141860484Sobrien { 141960484Sobrien elf_flags_init (obfd) = true; 142060484Sobrien elf_elfheader (obfd)->e_flags = new_flags; 142160484Sobrien } 142260484Sobrien 142360484Sobrien else if (new_flags == old_flags) /* Compatible flags are ok */ 142460484Sobrien ; 142560484Sobrien 142660484Sobrien else /* Incompatible flags */ 142760484Sobrien { 142860484Sobrien /* Warn about -mrelocatable mismatch. Allow -mrelocatable-lib to be linked 142960484Sobrien with either. */ 143060484Sobrien error = false; 143160484Sobrien if ((new_flags & EF_PPC_RELOCATABLE) != 0 143260484Sobrien && (old_flags & (EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB)) == 0) 143360484Sobrien { 143460484Sobrien error = true; 143560484Sobrien (*_bfd_error_handler) 143660484Sobrien (_("%s: compiled with -mrelocatable and linked with modules compiled normally"), 143789857Sobrien bfd_archive_filename (ibfd)); 143860484Sobrien } 143960484Sobrien else if ((new_flags & (EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB)) == 0 144060484Sobrien && (old_flags & EF_PPC_RELOCATABLE) != 0) 144160484Sobrien { 144260484Sobrien error = true; 144360484Sobrien (*_bfd_error_handler) 144460484Sobrien (_("%s: compiled normally and linked with modules compiled with -mrelocatable"), 144589857Sobrien bfd_archive_filename (ibfd)); 144660484Sobrien } 144760484Sobrien 144860484Sobrien /* The output is -mrelocatable-lib iff both the input files are. */ 144960484Sobrien if (! (new_flags & EF_PPC_RELOCATABLE_LIB)) 145060484Sobrien elf_elfheader (obfd)->e_flags &= ~EF_PPC_RELOCATABLE_LIB; 145160484Sobrien 145260484Sobrien /* The output is -mrelocatable iff it can't be -mrelocatable-lib, 145360484Sobrien but each input file is either -mrelocatable or -mrelocatable-lib. */ 145460484Sobrien if (! (elf_elfheader (obfd)->e_flags & EF_PPC_RELOCATABLE_LIB) 145560484Sobrien && (new_flags & (EF_PPC_RELOCATABLE_LIB | EF_PPC_RELOCATABLE)) 145660484Sobrien && (old_flags & (EF_PPC_RELOCATABLE_LIB | EF_PPC_RELOCATABLE))) 145760484Sobrien elf_elfheader (obfd)->e_flags |= EF_PPC_RELOCATABLE; 145860484Sobrien 145960484Sobrien /* Do not warn about eabi vs. V.4 mismatch, just or in the bit if any module uses it */ 146060484Sobrien elf_elfheader (obfd)->e_flags |= (new_flags & EF_PPC_EMB); 146160484Sobrien 146260484Sobrien new_flags &= ~ (EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB | EF_PPC_EMB); 146360484Sobrien old_flags &= ~ (EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB | EF_PPC_EMB); 146460484Sobrien 146560484Sobrien /* Warn about any other mismatches */ 146660484Sobrien if (new_flags != old_flags) 146760484Sobrien { 146860484Sobrien error = true; 146960484Sobrien (*_bfd_error_handler) 147060484Sobrien (_("%s: uses different e_flags (0x%lx) fields than previous modules (0x%lx)"), 147189857Sobrien bfd_archive_filename (ibfd), (long) new_flags, (long) old_flags); 147260484Sobrien } 147360484Sobrien 147460484Sobrien if (error) 147560484Sobrien { 147660484Sobrien bfd_set_error (bfd_error_bad_value); 147760484Sobrien return false; 147860484Sobrien } 147960484Sobrien } 148060484Sobrien 148160484Sobrien return true; 148260484Sobrien} 148360484Sobrien 148460484Sobrien/* Handle a PowerPC specific section when reading an object file. This 148560484Sobrien is called when elfcode.h finds a section with an unknown type. */ 148660484Sobrien 148760484Sobrienstatic boolean 148860484Sobrienppc_elf_section_from_shdr (abfd, hdr, name) 148960484Sobrien bfd *abfd; 149060484Sobrien Elf32_Internal_Shdr *hdr; 149160484Sobrien char *name; 149260484Sobrien{ 149360484Sobrien asection *newsect; 149460484Sobrien flagword flags; 149560484Sobrien 149660484Sobrien if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name)) 149760484Sobrien return false; 149860484Sobrien 149960484Sobrien newsect = hdr->bfd_section; 150060484Sobrien flags = bfd_get_section_flags (abfd, newsect); 150160484Sobrien if (hdr->sh_flags & SHF_EXCLUDE) 150260484Sobrien flags |= SEC_EXCLUDE; 150360484Sobrien 150460484Sobrien if (hdr->sh_type == SHT_ORDERED) 150560484Sobrien flags |= SEC_SORT_ENTRIES; 150660484Sobrien 150760484Sobrien bfd_set_section_flags (abfd, newsect, flags); 150860484Sobrien return true; 150960484Sobrien} 151060484Sobrien 151160484Sobrien/* Set up any other section flags and such that may be necessary. */ 151260484Sobrien 151360484Sobrienstatic boolean 151460484Sobrienppc_elf_fake_sections (abfd, shdr, asect) 151560484Sobrien bfd *abfd ATTRIBUTE_UNUSED; 151660484Sobrien Elf32_Internal_Shdr *shdr; 151760484Sobrien asection *asect; 151860484Sobrien{ 151960484Sobrien if ((asect->flags & SEC_EXCLUDE) != 0) 152060484Sobrien shdr->sh_flags |= SHF_EXCLUDE; 152160484Sobrien 152260484Sobrien if ((asect->flags & SEC_SORT_ENTRIES) != 0) 152360484Sobrien shdr->sh_type = SHT_ORDERED; 152460484Sobrien 152560484Sobrien return true; 152660484Sobrien} 152760484Sobrien 152860484Sobrien/* Create a special linker section */ 152960484Sobrienstatic elf_linker_section_t * 153060484Sobrienppc_elf_create_linker_section (abfd, info, which) 153160484Sobrien bfd *abfd; 153260484Sobrien struct bfd_link_info *info; 153360484Sobrien enum elf_linker_section_enum which; 153460484Sobrien{ 153560484Sobrien bfd *dynobj = elf_hash_table (info)->dynobj; 153660484Sobrien elf_linker_section_t *lsect; 153760484Sobrien 153860484Sobrien /* Record the first bfd section that needs the special section */ 153960484Sobrien if (!dynobj) 154060484Sobrien dynobj = elf_hash_table (info)->dynobj = abfd; 154160484Sobrien 154260484Sobrien /* If this is the first time, create the section */ 154360484Sobrien lsect = elf_linker_section (dynobj, which); 154460484Sobrien if (!lsect) 154560484Sobrien { 154660484Sobrien elf_linker_section_t defaults; 154760484Sobrien static elf_linker_section_t zero_section; 154860484Sobrien 154960484Sobrien defaults = zero_section; 155060484Sobrien defaults.which = which; 155160484Sobrien defaults.hole_written_p = false; 155260484Sobrien defaults.alignment = 2; 155360484Sobrien 155460484Sobrien /* Both of these sections are (technically) created by the user 155560484Sobrien putting data in them, so they shouldn't be marked 155660484Sobrien SEC_LINKER_CREATED. 155760484Sobrien 155860484Sobrien The linker creates them so it has somewhere to attach their 155960484Sobrien respective symbols. In fact, if they were empty it would 156060484Sobrien be OK to leave the symbol set to 0 (or any random number), because 156160484Sobrien the appropriate register should never be used. */ 156260484Sobrien defaults.flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS 156360484Sobrien | SEC_IN_MEMORY); 156460484Sobrien 156560484Sobrien switch (which) 156660484Sobrien { 156760484Sobrien default: 156860484Sobrien (*_bfd_error_handler) (_("%s: Unknown special linker type %d"), 156960484Sobrien bfd_get_filename (abfd), 157077298Sobrien (int) which); 157160484Sobrien 157260484Sobrien bfd_set_error (bfd_error_bad_value); 157377298Sobrien return (elf_linker_section_t *) 0; 157460484Sobrien 157560484Sobrien case LINKER_SECTION_SDATA: /* .sdata/.sbss section */ 157660484Sobrien defaults.name = ".sdata"; 157760484Sobrien defaults.rel_name = ".rela.sdata"; 157860484Sobrien defaults.bss_name = ".sbss"; 157960484Sobrien defaults.sym_name = "_SDA_BASE_"; 158060484Sobrien defaults.sym_offset = 32768; 158160484Sobrien break; 158260484Sobrien 158360484Sobrien case LINKER_SECTION_SDATA2: /* .sdata2/.sbss2 section */ 158460484Sobrien defaults.name = ".sdata2"; 158560484Sobrien defaults.rel_name = ".rela.sdata2"; 158660484Sobrien defaults.bss_name = ".sbss2"; 158760484Sobrien defaults.sym_name = "_SDA2_BASE_"; 158860484Sobrien defaults.sym_offset = 32768; 158960484Sobrien defaults.flags |= SEC_READONLY; 159060484Sobrien break; 159160484Sobrien } 159260484Sobrien 159360484Sobrien lsect = _bfd_elf_create_linker_section (abfd, info, which, &defaults); 159460484Sobrien } 159560484Sobrien 159660484Sobrien return lsect; 159760484Sobrien} 159860484Sobrien 159977298Sobrien/* If we have a non-zero sized .sbss2 or .PPC.EMB.sbss0 sections, we 160077298Sobrien need to bump up the number of section headers. */ 160160484Sobrien 160260484Sobrienstatic int 160360484Sobrienppc_elf_additional_program_headers (abfd) 160460484Sobrien bfd *abfd; 160560484Sobrien{ 160660484Sobrien asection *s; 160760484Sobrien int ret; 160860484Sobrien 160960484Sobrien ret = 0; 161060484Sobrien 161160484Sobrien s = bfd_get_section_by_name (abfd, ".interp"); 161260484Sobrien if (s != NULL) 161360484Sobrien ++ret; 161460484Sobrien 161560484Sobrien s = bfd_get_section_by_name (abfd, ".sbss2"); 161660484Sobrien if (s != NULL && (s->flags & SEC_LOAD) != 0 && s->_raw_size > 0) 161760484Sobrien ++ret; 161860484Sobrien 161960484Sobrien s = bfd_get_section_by_name (abfd, ".PPC.EMB.sbss0"); 162060484Sobrien if (s != NULL && (s->flags & SEC_LOAD) != 0 && s->_raw_size > 0) 162160484Sobrien ++ret; 162260484Sobrien 162360484Sobrien return ret; 162460484Sobrien} 162560484Sobrien 162677298Sobrien/* Modify the segment map if needed. */ 162760484Sobrien 162860484Sobrienstatic boolean 162960484Sobrienppc_elf_modify_segment_map (abfd) 163060484Sobrien bfd *abfd ATTRIBUTE_UNUSED; 163160484Sobrien{ 163260484Sobrien return true; 163360484Sobrien} 163460484Sobrien 163560484Sobrien/* We have to create .dynsbss and .rela.sbss here so that they get mapped 163660484Sobrien to output sections (just like _bfd_elf_create_dynamic_sections has 163760484Sobrien to create .dynbss and .rela.bss). */ 163860484Sobrien 163960484Sobrienstatic boolean 164060484Sobrienppc_elf_create_dynamic_sections (abfd, info) 164160484Sobrien bfd *abfd; 164260484Sobrien struct bfd_link_info *info; 164360484Sobrien{ 164460484Sobrien register asection *s; 164560484Sobrien flagword flags; 164660484Sobrien 164777298Sobrien if (!_bfd_elf_create_dynamic_sections (abfd, info)) 164860484Sobrien return false; 164960484Sobrien 165060484Sobrien flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY 165160484Sobrien | SEC_LINKER_CREATED); 165260484Sobrien 165360484Sobrien s = bfd_make_section (abfd, ".dynsbss"); 165460484Sobrien if (s == NULL 165560484Sobrien || ! bfd_set_section_flags (abfd, s, SEC_ALLOC)) 165660484Sobrien return false; 165760484Sobrien 165860484Sobrien if (! info->shared) 165960484Sobrien { 166060484Sobrien s = bfd_make_section (abfd, ".rela.sbss"); 166160484Sobrien if (s == NULL 166260484Sobrien || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY) 166360484Sobrien || ! bfd_set_section_alignment (abfd, s, 2)) 166460484Sobrien return false; 166560484Sobrien } 166660484Sobrien return true; 166760484Sobrien} 166860484Sobrien 166960484Sobrien/* Adjust a symbol defined by a dynamic object and referenced by a 167060484Sobrien regular object. The current definition is in some section of the 167160484Sobrien dynamic object, but we're not including those sections. We have to 167260484Sobrien change the definition to something the rest of the link can 167360484Sobrien understand. */ 167460484Sobrien 167560484Sobrienstatic boolean 167660484Sobrienppc_elf_adjust_dynamic_symbol (info, h) 167760484Sobrien struct bfd_link_info *info; 167860484Sobrien struct elf_link_hash_entry *h; 167960484Sobrien{ 168060484Sobrien bfd *dynobj = elf_hash_table (info)->dynobj; 168160484Sobrien asection *s; 168260484Sobrien unsigned int power_of_two; 168360484Sobrien bfd_vma plt_offset; 168460484Sobrien 168560484Sobrien#ifdef DEBUG 168660484Sobrien fprintf (stderr, "ppc_elf_adjust_dynamic_symbol called for %s\n", h->root.root.string); 168760484Sobrien#endif 168860484Sobrien 168960484Sobrien /* Make sure we know what is going on here. */ 169060484Sobrien BFD_ASSERT (dynobj != NULL 169160484Sobrien && ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) 169260484Sobrien || h->weakdef != NULL 169360484Sobrien || ((h->elf_link_hash_flags 169460484Sobrien & ELF_LINK_HASH_DEF_DYNAMIC) != 0 169560484Sobrien && (h->elf_link_hash_flags 169660484Sobrien & ELF_LINK_HASH_REF_REGULAR) != 0 169760484Sobrien && (h->elf_link_hash_flags 169860484Sobrien & ELF_LINK_HASH_DEF_REGULAR) == 0))); 169960484Sobrien 170060484Sobrien /* If this is a function, put it in the procedure linkage table. We 170160484Sobrien will fill in the contents of the procedure linkage table later, 170260484Sobrien when we know the address of the .got section. */ 170360484Sobrien if (h->type == STT_FUNC 170460484Sobrien || (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0) 170560484Sobrien { 170660484Sobrien if (! elf_hash_table (info)->dynamic_sections_created 170777298Sobrien || SYMBOL_CALLS_LOCAL (info, h) 170860484Sobrien || (info->shared && h->plt.refcount <= 0)) 170960484Sobrien { 171060484Sobrien /* A PLT entry is not required/allowed when: 171160484Sobrien 171260484Sobrien 1. We are not using ld.so; because then the PLT entry 171360484Sobrien can't be set up, so we can't use one. 171460484Sobrien 171577298Sobrien 2. We know for certain that a call to this symbol 171677298Sobrien will go to this object. 171760484Sobrien 171860484Sobrien 3. GC has rendered the entry unused. 171960484Sobrien Note, however, that in an executable all references to the 172060484Sobrien symbol go to the PLT, so we can't turn it off in that case. 172160484Sobrien ??? The correct thing to do here is to reference count 172260484Sobrien all uses of the symbol, not just those to the GOT or PLT. */ 172360484Sobrien h->plt.offset = (bfd_vma) -1; 172460484Sobrien h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; 172560484Sobrien return true; 172660484Sobrien } 172760484Sobrien 172860484Sobrien /* Make sure this symbol is output as a dynamic symbol. */ 172960484Sobrien if (h->dynindx == -1) 173060484Sobrien { 173160484Sobrien if (! bfd_elf32_link_record_dynamic_symbol (info, h)) 173260484Sobrien return false; 173360484Sobrien } 173460484Sobrien BFD_ASSERT (h->dynindx != -1); 173560484Sobrien 173660484Sobrien s = bfd_get_section_by_name (dynobj, ".plt"); 173760484Sobrien BFD_ASSERT (s != NULL); 173860484Sobrien 173960484Sobrien /* If this is the first .plt entry, make room for the special 174060484Sobrien first entry. */ 174160484Sobrien if (s->_raw_size == 0) 174260484Sobrien s->_raw_size += PLT_INITIAL_ENTRY_SIZE; 174360484Sobrien 174460484Sobrien /* The PowerPC PLT is actually composed of two parts, the first part 174560484Sobrien is 2 words (for a load and a jump), and then there is a remaining 174660484Sobrien word available at the end. */ 174760484Sobrien plt_offset = (PLT_INITIAL_ENTRY_SIZE 174860484Sobrien + (PLT_SLOT_SIZE 174960484Sobrien * ((s->_raw_size - PLT_INITIAL_ENTRY_SIZE) 175060484Sobrien / PLT_ENTRY_SIZE))); 175160484Sobrien 175260484Sobrien /* If this symbol is not defined in a regular file, and we are 175360484Sobrien not generating a shared library, then set the symbol to this 175460484Sobrien location in the .plt. This is required to make function 175560484Sobrien pointers compare as equal between the normal executable and 175660484Sobrien the shared library. */ 175760484Sobrien if (! info->shared 175860484Sobrien && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) 175960484Sobrien { 176060484Sobrien h->root.u.def.section = s; 176160484Sobrien h->root.u.def.value = plt_offset; 176260484Sobrien } 176360484Sobrien 176460484Sobrien h->plt.offset = plt_offset; 176560484Sobrien 176660484Sobrien /* Make room for this entry. After the 8192nd entry, room 176760484Sobrien for two entries is allocated. */ 176860484Sobrien if ((s->_raw_size - PLT_INITIAL_ENTRY_SIZE) / PLT_ENTRY_SIZE 176960484Sobrien >= PLT_NUM_SINGLE_ENTRIES) 177060484Sobrien s->_raw_size += 2 * PLT_ENTRY_SIZE; 177160484Sobrien else 177260484Sobrien s->_raw_size += PLT_ENTRY_SIZE; 177360484Sobrien 177460484Sobrien /* We also need to make an entry in the .rela.plt section. */ 177560484Sobrien s = bfd_get_section_by_name (dynobj, ".rela.plt"); 177660484Sobrien BFD_ASSERT (s != NULL); 177760484Sobrien s->_raw_size += sizeof (Elf32_External_Rela); 177860484Sobrien 177960484Sobrien return true; 178060484Sobrien } 178189857Sobrien else 178289857Sobrien h->plt.offset = (bfd_vma) -1; 178360484Sobrien 178460484Sobrien /* If this is a weak symbol, and there is a real definition, the 178560484Sobrien processor independent code will have arranged for us to see the 178660484Sobrien real definition first, and we can just use the same value. */ 178760484Sobrien if (h->weakdef != NULL) 178860484Sobrien { 178960484Sobrien BFD_ASSERT (h->weakdef->root.type == bfd_link_hash_defined 179060484Sobrien || h->weakdef->root.type == bfd_link_hash_defweak); 179160484Sobrien h->root.u.def.section = h->weakdef->root.u.def.section; 179260484Sobrien h->root.u.def.value = h->weakdef->root.u.def.value; 179360484Sobrien return true; 179460484Sobrien } 179560484Sobrien 179660484Sobrien /* This is a reference to a symbol defined by a dynamic object which 179760484Sobrien is not a function. */ 179860484Sobrien 179960484Sobrien /* If we are creating a shared library, we must presume that the 180060484Sobrien only references to the symbol are via the global offset table. 180160484Sobrien For such cases we need not do anything here; the relocations will 180260484Sobrien be handled correctly by relocate_section. */ 180360484Sobrien if (info->shared) 180460484Sobrien return true; 180560484Sobrien 180660484Sobrien /* We must allocate the symbol in our .dynbss section, which will 180760484Sobrien become part of the .bss section of the executable. There will be 180860484Sobrien an entry for this symbol in the .dynsym section. The dynamic 180960484Sobrien object will contain position independent code, so all references 181060484Sobrien from the dynamic object to this symbol will go through the global 181160484Sobrien offset table. The dynamic linker will use the .dynsym entry to 181260484Sobrien determine the address it must put in the global offset table, so 181360484Sobrien both the dynamic object and the regular object will refer to the 181460484Sobrien same memory location for the variable. 181560484Sobrien 181660484Sobrien Of course, if the symbol is sufficiently small, we must instead 181760484Sobrien allocate it in .sbss. FIXME: It would be better to do this if and 181860484Sobrien only if there were actually SDAREL relocs for that symbol. */ 181960484Sobrien 182060484Sobrien if (h->size <= elf_gp_size (dynobj)) 182160484Sobrien s = bfd_get_section_by_name (dynobj, ".dynsbss"); 182260484Sobrien else 182360484Sobrien s = bfd_get_section_by_name (dynobj, ".dynbss"); 182460484Sobrien BFD_ASSERT (s != NULL); 182560484Sobrien 182660484Sobrien /* We must generate a R_PPC_COPY reloc to tell the dynamic linker to 182760484Sobrien copy the initial value out of the dynamic object and into the 182860484Sobrien runtime process image. We need to remember the offset into the 182960484Sobrien .rela.bss section we are going to use. */ 183060484Sobrien if ((h->root.u.def.section->flags & SEC_ALLOC) != 0) 183160484Sobrien { 183260484Sobrien asection *srel; 183360484Sobrien 183460484Sobrien if (h->size <= elf_gp_size (dynobj)) 183560484Sobrien srel = bfd_get_section_by_name (dynobj, ".rela.sbss"); 183660484Sobrien else 183760484Sobrien srel = bfd_get_section_by_name (dynobj, ".rela.bss"); 183860484Sobrien BFD_ASSERT (srel != NULL); 183960484Sobrien srel->_raw_size += sizeof (Elf32_External_Rela); 184060484Sobrien h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_COPY; 184160484Sobrien } 184260484Sobrien 184360484Sobrien /* We need to figure out the alignment required for this symbol. I 184460484Sobrien have no idea how ELF linkers handle this. */ 184560484Sobrien power_of_two = bfd_log2 (h->size); 184660484Sobrien if (power_of_two > 4) 184760484Sobrien power_of_two = 4; 184860484Sobrien 184960484Sobrien /* Apply the required alignment. */ 185060484Sobrien s->_raw_size = BFD_ALIGN (s->_raw_size, 185160484Sobrien (bfd_size_type) (1 << power_of_two)); 185260484Sobrien if (power_of_two > bfd_get_section_alignment (dynobj, s)) 185360484Sobrien { 185460484Sobrien if (! bfd_set_section_alignment (dynobj, s, power_of_two)) 185560484Sobrien return false; 185660484Sobrien } 185760484Sobrien 185860484Sobrien /* Define the symbol as being at this point in the section. */ 185960484Sobrien h->root.u.def.section = s; 186060484Sobrien h->root.u.def.value = s->_raw_size; 186160484Sobrien 186260484Sobrien /* Increment the section size to make room for the symbol. */ 186360484Sobrien s->_raw_size += h->size; 186460484Sobrien 186560484Sobrien return true; 186660484Sobrien} 186760484Sobrien 186860484Sobrien/* Set the sizes of the dynamic sections. */ 186960484Sobrien 187060484Sobrienstatic boolean 187160484Sobrienppc_elf_size_dynamic_sections (output_bfd, info) 187289857Sobrien bfd *output_bfd ATTRIBUTE_UNUSED; 187360484Sobrien struct bfd_link_info *info; 187460484Sobrien{ 187560484Sobrien bfd *dynobj; 187660484Sobrien asection *s; 187760484Sobrien boolean plt; 187860484Sobrien boolean relocs; 187960484Sobrien 188060484Sobrien#ifdef DEBUG 188160484Sobrien fprintf (stderr, "ppc_elf_size_dynamic_sections called\n"); 188260484Sobrien#endif 188360484Sobrien 188460484Sobrien dynobj = elf_hash_table (info)->dynobj; 188560484Sobrien BFD_ASSERT (dynobj != NULL); 188660484Sobrien 188760484Sobrien if (elf_hash_table (info)->dynamic_sections_created) 188860484Sobrien { 188960484Sobrien /* Set the contents of the .interp section to the interpreter. */ 189060484Sobrien if (! info->shared) 189160484Sobrien { 189260484Sobrien s = bfd_get_section_by_name (dynobj, ".interp"); 189360484Sobrien BFD_ASSERT (s != NULL); 189460484Sobrien s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER; 189560484Sobrien s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER; 189660484Sobrien } 189760484Sobrien } 189860484Sobrien else 189960484Sobrien { 190060484Sobrien /* We may have created entries in the .rela.got, .rela.sdata, and 190160484Sobrien .rela.sdata2 sections. However, if we are not creating the 190260484Sobrien dynamic sections, we will not actually use these entries. Reset 190360484Sobrien the size of .rela.got, et al, which will cause it to get 190460484Sobrien stripped from the output file below. */ 190560484Sobrien static char *rela_sections[] = { ".rela.got", ".rela.sdata", 190660484Sobrien ".rela.sdata2", ".rela.sbss", 190777298Sobrien (char *) 0 }; 190860484Sobrien char **p; 190960484Sobrien 191077298Sobrien for (p = rela_sections; *p != (char *) 0; p++) 191160484Sobrien { 191260484Sobrien s = bfd_get_section_by_name (dynobj, *p); 191360484Sobrien if (s != NULL) 191460484Sobrien s->_raw_size = 0; 191560484Sobrien } 191660484Sobrien } 191760484Sobrien 191860484Sobrien /* The check_relocs and adjust_dynamic_symbol entry points have 191960484Sobrien determined the sizes of the various dynamic sections. Allocate 192060484Sobrien memory for them. */ 192160484Sobrien plt = false; 192260484Sobrien relocs = false; 192360484Sobrien for (s = dynobj->sections; s != NULL; s = s->next) 192460484Sobrien { 192560484Sobrien const char *name; 192660484Sobrien boolean strip; 192760484Sobrien 192860484Sobrien if ((s->flags & SEC_LINKER_CREATED) == 0) 192960484Sobrien continue; 193060484Sobrien 193160484Sobrien /* It's OK to base decisions on the section name, because none 193260484Sobrien of the dynobj section names depend upon the input files. */ 193360484Sobrien name = bfd_get_section_name (dynobj, s); 193460484Sobrien 193560484Sobrien strip = false; 193660484Sobrien 193760484Sobrien if (strcmp (name, ".plt") == 0) 193860484Sobrien { 193960484Sobrien if (s->_raw_size == 0) 194060484Sobrien { 194160484Sobrien /* Strip this section if we don't need it; see the 194260484Sobrien comment below. */ 194360484Sobrien strip = true; 194460484Sobrien } 194560484Sobrien else 194660484Sobrien { 194760484Sobrien /* Remember whether there is a PLT. */ 194860484Sobrien plt = true; 194960484Sobrien } 195060484Sobrien } 195160484Sobrien else if (strncmp (name, ".rela", 5) == 0) 195260484Sobrien { 195360484Sobrien if (s->_raw_size == 0) 195460484Sobrien { 195560484Sobrien /* If we don't need this section, strip it from the 195660484Sobrien output file. This is mostly to handle .rela.bss and 195760484Sobrien .rela.plt. We must create both sections in 195860484Sobrien create_dynamic_sections, because they must be created 195960484Sobrien before the linker maps input sections to output 196060484Sobrien sections. The linker does that before 196160484Sobrien adjust_dynamic_symbol is called, and it is that 196260484Sobrien function which decides whether anything needs to go 196360484Sobrien into these sections. */ 196460484Sobrien strip = true; 196560484Sobrien } 196660484Sobrien else 196760484Sobrien { 196877298Sobrien /* Remember whether there are any relocation sections. */ 196960484Sobrien relocs = true; 197060484Sobrien 197160484Sobrien /* We use the reloc_count field as a counter if we need 197260484Sobrien to copy relocs into the output file. */ 197360484Sobrien s->reloc_count = 0; 197460484Sobrien } 197560484Sobrien } 197660484Sobrien else if (strcmp (name, ".got") != 0 197760484Sobrien && strcmp (name, ".sdata") != 0 197860484Sobrien && strcmp (name, ".sdata2") != 0) 197960484Sobrien { 198060484Sobrien /* It's not one of our sections, so don't allocate space. */ 198160484Sobrien continue; 198260484Sobrien } 198360484Sobrien 198460484Sobrien if (strip) 198560484Sobrien { 198660484Sobrien _bfd_strip_section_from_output (info, s); 198760484Sobrien continue; 198860484Sobrien } 198960484Sobrien 199060484Sobrien /* Allocate memory for the section contents. */ 199160484Sobrien s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size); 199260484Sobrien if (s->contents == NULL && s->_raw_size != 0) 199360484Sobrien return false; 199460484Sobrien } 199560484Sobrien 199660484Sobrien if (elf_hash_table (info)->dynamic_sections_created) 199760484Sobrien { 199860484Sobrien /* Add some entries to the .dynamic section. We fill in the 199960484Sobrien values later, in ppc_elf_finish_dynamic_sections, but we 200060484Sobrien must add the entries now so that we get the correct size for 200160484Sobrien the .dynamic section. The DT_DEBUG entry is filled in by the 200260484Sobrien dynamic linker and used by the debugger. */ 200389857Sobrien#define add_dynamic_entry(TAG, VAL) \ 200489857Sobrien bfd_elf32_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL)) 200589857Sobrien 200689857Sobrien if (!info->shared) 200760484Sobrien { 200889857Sobrien if (!add_dynamic_entry (DT_DEBUG, 0)) 200960484Sobrien return false; 201060484Sobrien } 201160484Sobrien 201260484Sobrien if (plt) 201360484Sobrien { 201489857Sobrien if (!add_dynamic_entry (DT_PLTGOT, 0) 201589857Sobrien || !add_dynamic_entry (DT_PLTRELSZ, 0) 201689857Sobrien || !add_dynamic_entry (DT_PLTREL, DT_RELA) 201789857Sobrien || !add_dynamic_entry (DT_JMPREL, 0)) 201860484Sobrien return false; 201960484Sobrien } 202060484Sobrien 202160484Sobrien if (relocs) 202260484Sobrien { 202389857Sobrien if (!add_dynamic_entry (DT_RELA, 0) 202489857Sobrien || !add_dynamic_entry (DT_RELASZ, 0) 202589857Sobrien || !add_dynamic_entry (DT_RELAENT, sizeof (Elf32_External_Rela))) 202660484Sobrien return false; 202760484Sobrien } 202860484Sobrien 202989857Sobrien if ((info->flags & DF_TEXTREL) != 0) 203060484Sobrien { 203189857Sobrien if (!add_dynamic_entry (DT_TEXTREL, 0)) 203260484Sobrien return false; 203377298Sobrien info->flags |= DF_TEXTREL; 203460484Sobrien } 203560484Sobrien } 203689857Sobrien#undef add_dynamic_entry 203760484Sobrien 203860484Sobrien return true; 203960484Sobrien} 204060484Sobrien 204160484Sobrien/* Look through the relocs for a section during the first phase, and 204260484Sobrien allocate space in the global offset table or procedure linkage 204360484Sobrien table. */ 204460484Sobrien 204560484Sobrienstatic boolean 204660484Sobrienppc_elf_check_relocs (abfd, info, sec, relocs) 204760484Sobrien bfd *abfd; 204860484Sobrien struct bfd_link_info *info; 204960484Sobrien asection *sec; 205060484Sobrien const Elf_Internal_Rela *relocs; 205160484Sobrien{ 205260484Sobrien bfd *dynobj; 205360484Sobrien Elf_Internal_Shdr *symtab_hdr; 205460484Sobrien struct elf_link_hash_entry **sym_hashes, **sym_hashes_end; 205560484Sobrien const Elf_Internal_Rela *rel; 205660484Sobrien const Elf_Internal_Rela *rel_end; 205760484Sobrien bfd_signed_vma *local_got_refcounts; 205860484Sobrien elf_linker_section_t *sdata; 205960484Sobrien elf_linker_section_t *sdata2; 206060484Sobrien asection *sreloc; 206160484Sobrien asection *sgot = NULL; 206260484Sobrien asection *srelgot = NULL; 206360484Sobrien 206460484Sobrien if (info->relocateable) 206560484Sobrien return true; 206660484Sobrien 206760484Sobrien#ifdef DEBUG 206860484Sobrien fprintf (stderr, "ppc_elf_check_relocs called for section %s in %s\n", 206960484Sobrien bfd_get_section_name (abfd, sec), 207089857Sobrien bfd_archive_filename (abfd)); 207160484Sobrien#endif 207260484Sobrien 207360484Sobrien /* Create the linker generated sections all the time so that the 207460484Sobrien special symbols are created. */ 207560484Sobrien 207660484Sobrien if ((sdata = elf_linker_section (abfd, LINKER_SECTION_SDATA)) == NULL) 207760484Sobrien { 207860484Sobrien sdata = ppc_elf_create_linker_section (abfd, info, LINKER_SECTION_SDATA); 207960484Sobrien if (!sdata) 208060484Sobrien return false; 208160484Sobrien } 208260484Sobrien 208360484Sobrien if ((sdata2 = elf_linker_section (abfd, LINKER_SECTION_SDATA2)) == NULL) 208460484Sobrien { 208560484Sobrien sdata2 = ppc_elf_create_linker_section (abfd, info, LINKER_SECTION_SDATA2); 208660484Sobrien if (!sdata2) 208760484Sobrien return false; 208860484Sobrien } 208960484Sobrien 209060484Sobrien dynobj = elf_hash_table (info)->dynobj; 209160484Sobrien symtab_hdr = &elf_tdata (abfd)->symtab_hdr; 209260484Sobrien local_got_refcounts = elf_local_got_refcounts (abfd); 209360484Sobrien 209460484Sobrien sym_hashes = elf_sym_hashes (abfd); 209577298Sobrien sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof (Elf32_External_Sym); 209660484Sobrien if (!elf_bad_symtab (abfd)) 209760484Sobrien sym_hashes_end -= symtab_hdr->sh_info; 209860484Sobrien 209960484Sobrien sreloc = NULL; 210060484Sobrien 210160484Sobrien rel_end = relocs + sec->reloc_count; 210260484Sobrien for (rel = relocs; rel < rel_end; rel++) 210360484Sobrien { 210460484Sobrien unsigned long r_symndx; 210560484Sobrien struct elf_link_hash_entry *h; 210660484Sobrien 210760484Sobrien r_symndx = ELF32_R_SYM (rel->r_info); 210860484Sobrien if (r_symndx < symtab_hdr->sh_info) 210960484Sobrien h = NULL; 211060484Sobrien else 211160484Sobrien h = sym_hashes[r_symndx - symtab_hdr->sh_info]; 211260484Sobrien 211360484Sobrien /* If a relocation refers to _GLOBAL_OFFSET_TABLE_, create the .got. 211460484Sobrien This shows up in particular in an R_PPC_ADDR32 in the eabi 211560484Sobrien startup code. */ 211660484Sobrien if (h && strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0) 211760484Sobrien { 211860484Sobrien if (sgot == NULL) 211960484Sobrien { 212060484Sobrien if (dynobj == NULL) 212160484Sobrien elf_hash_table (info)->dynobj = dynobj = abfd; 212260484Sobrien if (! _bfd_elf_create_got_section (dynobj, info)) 212360484Sobrien return false; 212460484Sobrien sgot = bfd_get_section_by_name (dynobj, ".got"); 212560484Sobrien BFD_ASSERT (sgot != NULL); 212660484Sobrien } 212760484Sobrien } 212860484Sobrien 212960484Sobrien switch (ELF32_R_TYPE (rel->r_info)) 213060484Sobrien { 213160484Sobrien /* GOT16 relocations */ 213260484Sobrien case R_PPC_GOT16: 213360484Sobrien case R_PPC_GOT16_LO: 213460484Sobrien case R_PPC_GOT16_HI: 213560484Sobrien case R_PPC_GOT16_HA: 213660484Sobrien /* This symbol requires a global offset table entry. */ 213760484Sobrien 213860484Sobrien if (sgot == NULL) 213960484Sobrien { 214060484Sobrien if (dynobj == NULL) 214160484Sobrien elf_hash_table (info)->dynobj = dynobj = abfd; 214260484Sobrien if (! _bfd_elf_create_got_section (dynobj, info)) 214360484Sobrien return false; 214460484Sobrien sgot = bfd_get_section_by_name (dynobj, ".got"); 214560484Sobrien BFD_ASSERT (sgot != NULL); 214660484Sobrien } 214760484Sobrien 214860484Sobrien if (srelgot == NULL 214960484Sobrien && (h != NULL || info->shared)) 215060484Sobrien { 215160484Sobrien srelgot = bfd_get_section_by_name (dynobj, ".rela.got"); 215260484Sobrien if (srelgot == NULL) 215360484Sobrien { 215460484Sobrien srelgot = bfd_make_section (dynobj, ".rela.got"); 215560484Sobrien if (srelgot == NULL 215660484Sobrien || ! bfd_set_section_flags (dynobj, srelgot, 215760484Sobrien (SEC_ALLOC 215860484Sobrien | SEC_LOAD 215960484Sobrien | SEC_HAS_CONTENTS 216060484Sobrien | SEC_IN_MEMORY 216160484Sobrien | SEC_LINKER_CREATED 216260484Sobrien | SEC_READONLY)) 216360484Sobrien || ! bfd_set_section_alignment (dynobj, srelgot, 2)) 216460484Sobrien return false; 216560484Sobrien } 216660484Sobrien } 216760484Sobrien 216860484Sobrien if (h != NULL) 216960484Sobrien { 217089857Sobrien if (h->got.refcount == 0) 217160484Sobrien { 217260484Sobrien /* Make sure this symbol is output as a dynamic symbol. */ 217360484Sobrien if (h->dynindx == -1) 217460484Sobrien if (!bfd_elf32_link_record_dynamic_symbol (info, h)) 217560484Sobrien return false; 217660484Sobrien 217760484Sobrien /* Allocate space in the .got. */ 217860484Sobrien sgot->_raw_size += 4; 217960484Sobrien /* Allocate relocation space. */ 218060484Sobrien srelgot->_raw_size += sizeof (Elf32_External_Rela); 218160484Sobrien } 218289857Sobrien h->got.refcount++; 218360484Sobrien } 218460484Sobrien else 218560484Sobrien { 218660484Sobrien /* This is a global offset table entry for a local symbol. */ 218760484Sobrien if (local_got_refcounts == NULL) 218860484Sobrien { 218989857Sobrien bfd_size_type size; 219060484Sobrien 219189857Sobrien size = symtab_hdr->sh_info; 219289857Sobrien size *= sizeof (bfd_signed_vma); 219389857Sobrien local_got_refcounts 219489857Sobrien = (bfd_signed_vma *) bfd_zalloc (abfd, size); 219560484Sobrien if (local_got_refcounts == NULL) 219660484Sobrien return false; 219760484Sobrien elf_local_got_refcounts (abfd) = local_got_refcounts; 219860484Sobrien } 219989857Sobrien if (local_got_refcounts[r_symndx] == 0) 220060484Sobrien { 220160484Sobrien sgot->_raw_size += 4; 220260484Sobrien 220360484Sobrien /* If we are generating a shared object, we need to 220460484Sobrien output a R_PPC_RELATIVE reloc so that the 220560484Sobrien dynamic linker can adjust this GOT entry. */ 220660484Sobrien if (info->shared) 220760484Sobrien srelgot->_raw_size += sizeof (Elf32_External_Rela); 220860484Sobrien } 220989857Sobrien local_got_refcounts[r_symndx]++; 221060484Sobrien } 221160484Sobrien break; 221260484Sobrien 221360484Sobrien /* Indirect .sdata relocation */ 221460484Sobrien case R_PPC_EMB_SDAI16: 221560484Sobrien if (info->shared) 221660484Sobrien { 221760484Sobrien ((*_bfd_error_handler) 221860484Sobrien (_("%s: relocation %s cannot be used when making a shared object"), 221989857Sobrien bfd_archive_filename (abfd), "R_PPC_EMB_SDAI16")); 222077298Sobrien return false; 222160484Sobrien } 222260484Sobrien 222360484Sobrien if (srelgot == NULL && (h != NULL || info->shared)) 222460484Sobrien { 222560484Sobrien srelgot = bfd_get_section_by_name (dynobj, ".rela.got"); 222660484Sobrien if (srelgot == NULL) 222760484Sobrien { 222860484Sobrien srelgot = bfd_make_section (dynobj, ".rela.got"); 222960484Sobrien if (srelgot == NULL 223060484Sobrien || ! bfd_set_section_flags (dynobj, srelgot, 223160484Sobrien (SEC_ALLOC 223260484Sobrien | SEC_LOAD 223360484Sobrien | SEC_HAS_CONTENTS 223460484Sobrien | SEC_IN_MEMORY 223560484Sobrien | SEC_LINKER_CREATED 223660484Sobrien | SEC_READONLY)) 223760484Sobrien || ! bfd_set_section_alignment (dynobj, srelgot, 2)) 223860484Sobrien return false; 223960484Sobrien } 224060484Sobrien } 224160484Sobrien 224260484Sobrien if (!bfd_elf32_create_pointer_linker_section (abfd, info, sdata, h, rel)) 224360484Sobrien return false; 224460484Sobrien 224560484Sobrien break; 224660484Sobrien 224760484Sobrien /* Indirect .sdata2 relocation */ 224860484Sobrien case R_PPC_EMB_SDA2I16: 224960484Sobrien if (info->shared) 225060484Sobrien { 225160484Sobrien ((*_bfd_error_handler) 225260484Sobrien (_("%s: relocation %s cannot be used when making a shared object"), 225389857Sobrien bfd_archive_filename (abfd), "R_PPC_EMB_SDA2I16")); 225460484Sobrien return false; 225560484Sobrien } 225660484Sobrien 225760484Sobrien if (srelgot == NULL && (h != NULL || info->shared)) 225860484Sobrien { 225960484Sobrien srelgot = bfd_get_section_by_name (dynobj, ".rela.got"); 226060484Sobrien if (srelgot == NULL) 226160484Sobrien { 226260484Sobrien srelgot = bfd_make_section (dynobj, ".rela.got"); 226360484Sobrien if (srelgot == NULL 226460484Sobrien || ! bfd_set_section_flags (dynobj, srelgot, 226560484Sobrien (SEC_ALLOC 226660484Sobrien | SEC_LOAD 226760484Sobrien | SEC_HAS_CONTENTS 226860484Sobrien | SEC_IN_MEMORY 226960484Sobrien | SEC_LINKER_CREATED 227060484Sobrien | SEC_READONLY)) 227160484Sobrien || ! bfd_set_section_alignment (dynobj, srelgot, 2)) 227260484Sobrien return false; 227360484Sobrien } 227460484Sobrien } 227560484Sobrien 227660484Sobrien if (!bfd_elf32_create_pointer_linker_section (abfd, info, sdata2, h, rel)) 227760484Sobrien return false; 227860484Sobrien 227960484Sobrien break; 228060484Sobrien 228160484Sobrien case R_PPC_SDAREL16: 228260484Sobrien case R_PPC_EMB_SDA2REL: 228360484Sobrien case R_PPC_EMB_SDA21: 228460484Sobrien if (info->shared) 228560484Sobrien { 228660484Sobrien ((*_bfd_error_handler) 228760484Sobrien (_("%s: relocation %s cannot be used when making a shared object"), 228889857Sobrien bfd_archive_filename (abfd), 228977298Sobrien ppc_elf_howto_table[(int) ELF32_R_TYPE (rel->r_info)]->name)); 229060484Sobrien return false; 229160484Sobrien } 229260484Sobrien break; 229360484Sobrien 229460484Sobrien case R_PPC_PLT32: 229560484Sobrien case R_PPC_PLTREL24: 229660484Sobrien case R_PPC_PLT16_LO: 229760484Sobrien case R_PPC_PLT16_HI: 229860484Sobrien case R_PPC_PLT16_HA: 229960484Sobrien#ifdef DEBUG 230060484Sobrien fprintf (stderr, "Reloc requires a PLT entry\n"); 230160484Sobrien#endif 230260484Sobrien /* This symbol requires a procedure linkage table entry. We 230360484Sobrien actually build the entry in adjust_dynamic_symbol, 230460484Sobrien because this might be a case of linking PIC code without 230560484Sobrien linking in any dynamic objects, in which case we don't 230660484Sobrien need to generate a procedure linkage table after all. */ 230760484Sobrien 230860484Sobrien if (h == NULL) 230960484Sobrien { 231060484Sobrien /* It does not make sense to have a procedure linkage 231160484Sobrien table entry for a local symbol. */ 231260484Sobrien bfd_set_error (bfd_error_bad_value); 231360484Sobrien return false; 231460484Sobrien } 231560484Sobrien 231660484Sobrien /* Make sure this symbol is output as a dynamic symbol. */ 231760484Sobrien if (h->dynindx == -1) 231860484Sobrien { 231960484Sobrien if (! bfd_elf32_link_record_dynamic_symbol (info, h)) 232060484Sobrien return false; 232160484Sobrien } 232289857Sobrien h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; 232389857Sobrien h->plt.refcount++; 232460484Sobrien break; 232560484Sobrien 232660484Sobrien /* The following relocations don't need to propagate the 232760484Sobrien relocation if linking a shared object since they are 232860484Sobrien section relative. */ 232960484Sobrien case R_PPC_SECTOFF: 233060484Sobrien case R_PPC_SECTOFF_LO: 233160484Sobrien case R_PPC_SECTOFF_HI: 233260484Sobrien case R_PPC_SECTOFF_HA: 233360484Sobrien break; 233460484Sobrien 233560484Sobrien /* This refers only to functions defined in the shared library */ 233660484Sobrien case R_PPC_LOCAL24PC: 233760484Sobrien break; 233860484Sobrien 233960484Sobrien /* This relocation describes the C++ object vtable hierarchy. 234060484Sobrien Reconstruct it for later use during GC. */ 234160484Sobrien case R_PPC_GNU_VTINHERIT: 234260484Sobrien if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) 234360484Sobrien return false; 234460484Sobrien break; 234560484Sobrien 234660484Sobrien /* This relocation describes which C++ vtable entries are actually 234760484Sobrien used. Record for later use during GC. */ 234860484Sobrien case R_PPC_GNU_VTENTRY: 234960484Sobrien if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend)) 235060484Sobrien return false; 235160484Sobrien break; 235260484Sobrien 235360484Sobrien /* When creating a shared object, we must copy these 235460484Sobrien relocs into the output file. We create a reloc 235560484Sobrien section in dynobj and make room for the reloc. */ 235660484Sobrien case R_PPC_REL24: 235760484Sobrien case R_PPC_REL14: 235860484Sobrien case R_PPC_REL14_BRTAKEN: 235960484Sobrien case R_PPC_REL14_BRNTAKEN: 236060484Sobrien case R_PPC_REL32: 236160484Sobrien if (h == NULL 236277298Sobrien || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0 236377298Sobrien || SYMBOL_REFERENCES_LOCAL (info, h)) 236460484Sobrien break; 236560484Sobrien /* fall through */ 236660484Sobrien 236760484Sobrien default: 236860484Sobrien if (info->shared) 236960484Sobrien { 237060484Sobrien#ifdef DEBUG 237160484Sobrien fprintf (stderr, "ppc_elf_check_relocs need to create relocation for %s\n", 237260484Sobrien (h && h->root.root.string) ? h->root.root.string : "<unknown>"); 237360484Sobrien#endif 237460484Sobrien if (sreloc == NULL) 237560484Sobrien { 237660484Sobrien const char *name; 237760484Sobrien 237860484Sobrien name = (bfd_elf_string_from_elf_section 237960484Sobrien (abfd, 238060484Sobrien elf_elfheader (abfd)->e_shstrndx, 238160484Sobrien elf_section_data (sec)->rel_hdr.sh_name)); 238260484Sobrien if (name == NULL) 238360484Sobrien return false; 238460484Sobrien 238560484Sobrien BFD_ASSERT (strncmp (name, ".rela", 5) == 0 238660484Sobrien && strcmp (bfd_get_section_name (abfd, sec), 238760484Sobrien name + 5) == 0); 238860484Sobrien 238960484Sobrien sreloc = bfd_get_section_by_name (dynobj, name); 239060484Sobrien if (sreloc == NULL) 239160484Sobrien { 239260484Sobrien flagword flags; 239360484Sobrien 239460484Sobrien sreloc = bfd_make_section (dynobj, name); 239560484Sobrien flags = (SEC_HAS_CONTENTS | SEC_READONLY 239660484Sobrien | SEC_IN_MEMORY | SEC_LINKER_CREATED); 239760484Sobrien if ((sec->flags & SEC_ALLOC) != 0) 239860484Sobrien flags |= SEC_ALLOC | SEC_LOAD; 239960484Sobrien if (sreloc == NULL 240060484Sobrien || ! bfd_set_section_flags (dynobj, sreloc, flags) 240160484Sobrien || ! bfd_set_section_alignment (dynobj, sreloc, 2)) 240260484Sobrien return false; 240360484Sobrien } 240489857Sobrien if (sec->flags & SEC_READONLY) 240589857Sobrien info->flags |= DF_TEXTREL; 240660484Sobrien } 240760484Sobrien 240860484Sobrien sreloc->_raw_size += sizeof (Elf32_External_Rela); 240960484Sobrien 241060484Sobrien /* FIXME: We should here do what the m68k and i386 241160484Sobrien backends do: if the reloc is pc-relative, record it 241260484Sobrien in case it turns out that the reloc is unnecessary 241360484Sobrien because the symbol is forced local by versioning or 241460484Sobrien we are linking with -Bdynamic. Fortunately this 241560484Sobrien case is not frequent. */ 241660484Sobrien } 241760484Sobrien 241860484Sobrien break; 241960484Sobrien } 242060484Sobrien } 242160484Sobrien 242260484Sobrien return true; 242360484Sobrien} 242460484Sobrien 242560484Sobrien/* Return the section that should be marked against GC for a given 242660484Sobrien relocation. */ 242760484Sobrien 242860484Sobrienstatic asection * 242960484Sobrienppc_elf_gc_mark_hook (abfd, info, rel, h, sym) 243060484Sobrien bfd *abfd; 243160484Sobrien struct bfd_link_info *info ATTRIBUTE_UNUSED; 243260484Sobrien Elf_Internal_Rela *rel; 243360484Sobrien struct elf_link_hash_entry *h; 243460484Sobrien Elf_Internal_Sym *sym; 243560484Sobrien{ 243660484Sobrien if (h != NULL) 243760484Sobrien { 243860484Sobrien switch (ELF32_R_TYPE (rel->r_info)) 243960484Sobrien { 244060484Sobrien case R_PPC_GNU_VTINHERIT: 244160484Sobrien case R_PPC_GNU_VTENTRY: 244260484Sobrien break; 244360484Sobrien 244460484Sobrien default: 244560484Sobrien switch (h->root.type) 244660484Sobrien { 244760484Sobrien case bfd_link_hash_defined: 244860484Sobrien case bfd_link_hash_defweak: 244960484Sobrien return h->root.u.def.section; 245060484Sobrien 245160484Sobrien case bfd_link_hash_common: 245260484Sobrien return h->root.u.c.p->section; 245360484Sobrien 245460484Sobrien default: 245560484Sobrien break; 245660484Sobrien } 245760484Sobrien } 245860484Sobrien } 245960484Sobrien else 246060484Sobrien { 246189857Sobrien return bfd_section_from_elf_index (abfd, sym->st_shndx); 246260484Sobrien } 246360484Sobrien 246460484Sobrien return NULL; 246560484Sobrien} 246660484Sobrien 246760484Sobrien/* Update the got entry reference counts for the section being removed. */ 246860484Sobrien 246960484Sobrienstatic boolean 247060484Sobrienppc_elf_gc_sweep_hook (abfd, info, sec, relocs) 247160484Sobrien bfd *abfd; 247260484Sobrien struct bfd_link_info *info ATTRIBUTE_UNUSED; 247360484Sobrien asection *sec; 247460484Sobrien const Elf_Internal_Rela *relocs; 247560484Sobrien{ 247660484Sobrien Elf_Internal_Shdr *symtab_hdr; 247760484Sobrien struct elf_link_hash_entry **sym_hashes; 247860484Sobrien bfd_signed_vma *local_got_refcounts; 247960484Sobrien const Elf_Internal_Rela *rel, *relend; 248060484Sobrien unsigned long r_symndx; 248160484Sobrien struct elf_link_hash_entry *h; 248260484Sobrien 248360484Sobrien symtab_hdr = &elf_tdata (abfd)->symtab_hdr; 248460484Sobrien sym_hashes = elf_sym_hashes (abfd); 248560484Sobrien local_got_refcounts = elf_local_got_refcounts (abfd); 248660484Sobrien 248760484Sobrien relend = relocs + sec->reloc_count; 248860484Sobrien for (rel = relocs; rel < relend; rel++) 248960484Sobrien switch (ELF32_R_TYPE (rel->r_info)) 249060484Sobrien { 249160484Sobrien case R_PPC_GOT16: 249260484Sobrien case R_PPC_GOT16_LO: 249360484Sobrien case R_PPC_GOT16_HI: 249460484Sobrien case R_PPC_GOT16_HA: 249560484Sobrien r_symndx = ELF32_R_SYM (rel->r_info); 249660484Sobrien if (r_symndx >= symtab_hdr->sh_info) 249760484Sobrien { 249860484Sobrien h = sym_hashes[r_symndx - symtab_hdr->sh_info]; 249960484Sobrien if (h->got.refcount > 0) 250060484Sobrien h->got.refcount--; 250160484Sobrien } 250277298Sobrien else if (local_got_refcounts != NULL) 250360484Sobrien { 250460484Sobrien if (local_got_refcounts[r_symndx] > 0) 250560484Sobrien local_got_refcounts[r_symndx]--; 250660484Sobrien } 250760484Sobrien break; 250860484Sobrien 250960484Sobrien case R_PPC_PLT32: 251060484Sobrien case R_PPC_PLTREL24: 251160484Sobrien case R_PPC_PLT16_LO: 251260484Sobrien case R_PPC_PLT16_HI: 251360484Sobrien case R_PPC_PLT16_HA: 251460484Sobrien r_symndx = ELF32_R_SYM (rel->r_info); 251560484Sobrien if (r_symndx >= symtab_hdr->sh_info) 251660484Sobrien { 251760484Sobrien h = sym_hashes[r_symndx - symtab_hdr->sh_info]; 251860484Sobrien if (h->plt.refcount > 0) 251960484Sobrien h->plt.refcount--; 252060484Sobrien } 252160484Sobrien break; 252260484Sobrien 252360484Sobrien default: 252460484Sobrien break; 252560484Sobrien } 252660484Sobrien 252760484Sobrien return true; 252860484Sobrien} 252960484Sobrien 253060484Sobrien/* Hook called by the linker routine which adds symbols from an object 253160484Sobrien file. We use it to put .comm items in .sbss, and not .bss. */ 253260484Sobrien 253360484Sobrienstatic boolean 253460484Sobrienppc_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp) 253560484Sobrien bfd *abfd; 253660484Sobrien struct bfd_link_info *info; 253760484Sobrien const Elf_Internal_Sym *sym; 253860484Sobrien const char **namep ATTRIBUTE_UNUSED; 253960484Sobrien flagword *flagsp ATTRIBUTE_UNUSED; 254060484Sobrien asection **secp; 254160484Sobrien bfd_vma *valp; 254260484Sobrien{ 254360484Sobrien if (sym->st_shndx == SHN_COMMON 254460484Sobrien && !info->relocateable 254589857Sobrien && sym->st_size <= elf_gp_size (abfd)) 254660484Sobrien { 254760484Sobrien /* Common symbols less than or equal to -G nn bytes are automatically 254860484Sobrien put into .sdata. */ 254960484Sobrien elf_linker_section_t *sdata 255060484Sobrien = ppc_elf_create_linker_section (abfd, info, LINKER_SECTION_SDATA); 255160484Sobrien 255260484Sobrien if (!sdata->bss_section) 255360484Sobrien { 255489857Sobrien bfd_size_type amt; 255589857Sobrien 255660484Sobrien /* We don't go through bfd_make_section, because we don't 255760484Sobrien want to attach this common section to DYNOBJ. The linker 255860484Sobrien will move the symbols to the appropriate output section 255960484Sobrien when it defines common symbols. */ 256089857Sobrien amt = sizeof (asection); 256189857Sobrien sdata->bss_section = (asection *) bfd_zalloc (abfd, amt); 256260484Sobrien if (sdata->bss_section == NULL) 256360484Sobrien return false; 256460484Sobrien sdata->bss_section->name = sdata->bss_name; 256560484Sobrien sdata->bss_section->flags = SEC_IS_COMMON; 256660484Sobrien sdata->bss_section->output_section = sdata->bss_section; 256789857Sobrien amt = sizeof (asymbol); 256889857Sobrien sdata->bss_section->symbol = (asymbol *) bfd_zalloc (abfd, amt); 256989857Sobrien amt = sizeof (asymbol *); 257060484Sobrien sdata->bss_section->symbol_ptr_ptr = 257189857Sobrien (asymbol **) bfd_zalloc (abfd, amt); 257260484Sobrien if (sdata->bss_section->symbol == NULL 257360484Sobrien || sdata->bss_section->symbol_ptr_ptr == NULL) 257460484Sobrien return false; 257560484Sobrien sdata->bss_section->symbol->name = sdata->bss_name; 257660484Sobrien sdata->bss_section->symbol->flags = BSF_SECTION_SYM; 257760484Sobrien sdata->bss_section->symbol->section = sdata->bss_section; 257860484Sobrien *sdata->bss_section->symbol_ptr_ptr = sdata->bss_section->symbol; 257960484Sobrien } 258060484Sobrien 258160484Sobrien *secp = sdata->bss_section; 258260484Sobrien *valp = sym->st_size; 258360484Sobrien } 258460484Sobrien 258560484Sobrien return true; 258660484Sobrien} 258760484Sobrien 258860484Sobrien/* Finish up dynamic symbol handling. We set the contents of various 258960484Sobrien dynamic sections here. */ 259060484Sobrien 259160484Sobrienstatic boolean 259260484Sobrienppc_elf_finish_dynamic_symbol (output_bfd, info, h, sym) 259360484Sobrien bfd *output_bfd; 259460484Sobrien struct bfd_link_info *info; 259560484Sobrien struct elf_link_hash_entry *h; 259660484Sobrien Elf_Internal_Sym *sym; 259760484Sobrien{ 259860484Sobrien bfd *dynobj; 259960484Sobrien 260060484Sobrien#ifdef DEBUG 260160484Sobrien fprintf (stderr, "ppc_elf_finish_dynamic_symbol called for %s", 260260484Sobrien h->root.root.string); 260360484Sobrien#endif 260460484Sobrien 260560484Sobrien dynobj = elf_hash_table (info)->dynobj; 260660484Sobrien BFD_ASSERT (dynobj != NULL); 260760484Sobrien 260860484Sobrien if (h->plt.offset != (bfd_vma) -1) 260960484Sobrien { 261060484Sobrien asection *splt; 261160484Sobrien asection *srela; 261260484Sobrien Elf_Internal_Rela rela; 261360484Sobrien bfd_vma reloc_index; 261460484Sobrien 261560484Sobrien#ifdef DEBUG 261660484Sobrien fprintf (stderr, ", plt_offset = %d", h->plt.offset); 261760484Sobrien#endif 261860484Sobrien 261960484Sobrien /* This symbol has an entry in the procedure linkage table. Set 262060484Sobrien it up. */ 262160484Sobrien 262260484Sobrien BFD_ASSERT (h->dynindx != -1); 262360484Sobrien 262460484Sobrien splt = bfd_get_section_by_name (dynobj, ".plt"); 262560484Sobrien srela = bfd_get_section_by_name (dynobj, ".rela.plt"); 262660484Sobrien BFD_ASSERT (splt != NULL && srela != NULL); 262760484Sobrien 262860484Sobrien /* We don't need to fill in the .plt. The ppc dynamic linker 262960484Sobrien will fill it in. */ 263060484Sobrien 263160484Sobrien /* Fill in the entry in the .rela.plt section. */ 263260484Sobrien rela.r_offset = (splt->output_section->vma 263360484Sobrien + splt->output_offset 263460484Sobrien + h->plt.offset); 263560484Sobrien rela.r_info = ELF32_R_INFO (h->dynindx, R_PPC_JMP_SLOT); 263660484Sobrien rela.r_addend = 0; 263760484Sobrien 263860484Sobrien reloc_index = (h->plt.offset - PLT_INITIAL_ENTRY_SIZE) / PLT_SLOT_SIZE; 263960484Sobrien if (reloc_index > PLT_NUM_SINGLE_ENTRIES) 264060484Sobrien reloc_index -= (reloc_index - PLT_NUM_SINGLE_ENTRIES) / 2; 264160484Sobrien bfd_elf32_swap_reloca_out (output_bfd, &rela, 264260484Sobrien ((Elf32_External_Rela *) srela->contents 264360484Sobrien + reloc_index)); 264460484Sobrien 264560484Sobrien if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) 264660484Sobrien { 264760484Sobrien /* Mark the symbol as undefined, rather than as defined in 264860484Sobrien the .plt section. Leave the value alone. */ 264960484Sobrien sym->st_shndx = SHN_UNDEF; 265068765Sobrien /* If the symbol is weak, we do need to clear the value. 265168765Sobrien Otherwise, the PLT entry would provide a definition for 265268765Sobrien the symbol even if the symbol wasn't defined anywhere, 265368765Sobrien and so the symbol would never be NULL. */ 265477298Sobrien if ((h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR_NONWEAK) 265568765Sobrien == 0) 265668765Sobrien sym->st_value = 0; 265760484Sobrien } 265860484Sobrien } 265960484Sobrien 266060484Sobrien if (h->got.offset != (bfd_vma) -1) 266160484Sobrien { 266260484Sobrien asection *sgot; 266360484Sobrien asection *srela; 266460484Sobrien Elf_Internal_Rela rela; 266560484Sobrien 266660484Sobrien /* This symbol has an entry in the global offset table. Set it 266760484Sobrien up. */ 266860484Sobrien 266960484Sobrien sgot = bfd_get_section_by_name (dynobj, ".got"); 267060484Sobrien srela = bfd_get_section_by_name (dynobj, ".rela.got"); 267160484Sobrien BFD_ASSERT (sgot != NULL && srela != NULL); 267260484Sobrien 267360484Sobrien rela.r_offset = (sgot->output_section->vma 267460484Sobrien + sgot->output_offset 267589857Sobrien + (h->got.offset &~ (bfd_vma) 1)); 267660484Sobrien 267760484Sobrien /* If this is a -Bsymbolic link, and the symbol is defined 267860484Sobrien locally, we just want to emit a RELATIVE reloc. The entry in 267960484Sobrien the global offset table will already have been initialized in 268060484Sobrien the relocate_section function. */ 268160484Sobrien if (info->shared 268277298Sobrien && SYMBOL_REFERENCES_LOCAL (info, h)) 268360484Sobrien { 268460484Sobrien rela.r_info = ELF32_R_INFO (0, R_PPC_RELATIVE); 268560484Sobrien rela.r_addend = (h->root.u.def.value 268660484Sobrien + h->root.u.def.section->output_section->vma 268760484Sobrien + h->root.u.def.section->output_offset); 268860484Sobrien } 268960484Sobrien else 269060484Sobrien { 269177298Sobrien BFD_ASSERT ((h->got.offset & 1) == 0); 269260484Sobrien bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + h->got.offset); 269360484Sobrien rela.r_info = ELF32_R_INFO (h->dynindx, R_PPC_GLOB_DAT); 269460484Sobrien rela.r_addend = 0; 269560484Sobrien } 269660484Sobrien 269760484Sobrien bfd_elf32_swap_reloca_out (output_bfd, &rela, 269860484Sobrien ((Elf32_External_Rela *) srela->contents 269960484Sobrien + srela->reloc_count)); 270060484Sobrien ++srela->reloc_count; 270160484Sobrien } 270260484Sobrien 270360484Sobrien if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_COPY) != 0) 270460484Sobrien { 270560484Sobrien asection *s; 270660484Sobrien Elf_Internal_Rela rela; 270760484Sobrien 270860484Sobrien /* This symbols needs a copy reloc. Set it up. */ 270960484Sobrien 271060484Sobrien#ifdef DEBUG 271160484Sobrien fprintf (stderr, ", copy"); 271260484Sobrien#endif 271360484Sobrien 271460484Sobrien BFD_ASSERT (h->dynindx != -1); 271560484Sobrien 271660484Sobrien if (h->size <= elf_gp_size (dynobj)) 271760484Sobrien s = bfd_get_section_by_name (h->root.u.def.section->owner, 271860484Sobrien ".rela.sbss"); 271960484Sobrien else 272060484Sobrien s = bfd_get_section_by_name (h->root.u.def.section->owner, 272160484Sobrien ".rela.bss"); 272260484Sobrien BFD_ASSERT (s != NULL); 272360484Sobrien 272460484Sobrien rela.r_offset = (h->root.u.def.value 272560484Sobrien + h->root.u.def.section->output_section->vma 272660484Sobrien + h->root.u.def.section->output_offset); 272760484Sobrien rela.r_info = ELF32_R_INFO (h->dynindx, R_PPC_COPY); 272860484Sobrien rela.r_addend = 0; 272960484Sobrien bfd_elf32_swap_reloca_out (output_bfd, &rela, 273060484Sobrien ((Elf32_External_Rela *) s->contents 273160484Sobrien + s->reloc_count)); 273260484Sobrien ++s->reloc_count; 273360484Sobrien } 273460484Sobrien 273560484Sobrien#ifdef DEBUG 273660484Sobrien fprintf (stderr, "\n"); 273760484Sobrien#endif 273860484Sobrien 273960484Sobrien /* Mark some specially defined symbols as absolute. */ 274060484Sobrien if (strcmp (h->root.root.string, "_DYNAMIC") == 0 274160484Sobrien || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0 274260484Sobrien || strcmp (h->root.root.string, "_PROCEDURE_LINKAGE_TABLE_") == 0) 274360484Sobrien sym->st_shndx = SHN_ABS; 274460484Sobrien 274560484Sobrien return true; 274660484Sobrien} 274760484Sobrien 274860484Sobrien/* Finish up the dynamic sections. */ 274960484Sobrien 275060484Sobrienstatic boolean 275160484Sobrienppc_elf_finish_dynamic_sections (output_bfd, info) 275260484Sobrien bfd *output_bfd; 275360484Sobrien struct bfd_link_info *info; 275460484Sobrien{ 275560484Sobrien asection *sdyn; 275660484Sobrien bfd *dynobj = elf_hash_table (info)->dynobj; 275760484Sobrien asection *sgot = bfd_get_section_by_name (dynobj, ".got"); 275860484Sobrien 275960484Sobrien#ifdef DEBUG 276060484Sobrien fprintf (stderr, "ppc_elf_finish_dynamic_sections called\n"); 276160484Sobrien#endif 276260484Sobrien 276360484Sobrien sdyn = bfd_get_section_by_name (dynobj, ".dynamic"); 276460484Sobrien 276560484Sobrien if (elf_hash_table (info)->dynamic_sections_created) 276660484Sobrien { 276760484Sobrien asection *splt; 276860484Sobrien Elf32_External_Dyn *dyncon, *dynconend; 276960484Sobrien 277060484Sobrien splt = bfd_get_section_by_name (dynobj, ".plt"); 277160484Sobrien BFD_ASSERT (splt != NULL && sdyn != NULL); 277260484Sobrien 277360484Sobrien dyncon = (Elf32_External_Dyn *) sdyn->contents; 277460484Sobrien dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->_raw_size); 277560484Sobrien for (; dyncon < dynconend; dyncon++) 277660484Sobrien { 277760484Sobrien Elf_Internal_Dyn dyn; 277860484Sobrien const char *name; 277960484Sobrien boolean size; 278060484Sobrien 278160484Sobrien bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn); 278260484Sobrien 278360484Sobrien switch (dyn.d_tag) 278460484Sobrien { 278560484Sobrien case DT_PLTGOT: name = ".plt"; size = false; break; 278660484Sobrien case DT_PLTRELSZ: name = ".rela.plt"; size = true; break; 278760484Sobrien case DT_JMPREL: name = ".rela.plt"; size = false; break; 278860484Sobrien default: name = NULL; size = false; break; 278960484Sobrien } 279060484Sobrien 279160484Sobrien if (name != NULL) 279260484Sobrien { 279360484Sobrien asection *s; 279460484Sobrien 279560484Sobrien s = bfd_get_section_by_name (output_bfd, name); 279660484Sobrien if (s == NULL) 279760484Sobrien dyn.d_un.d_val = 0; 279860484Sobrien else 279960484Sobrien { 280060484Sobrien if (! size) 280160484Sobrien dyn.d_un.d_ptr = s->vma; 280260484Sobrien else 280360484Sobrien { 280460484Sobrien if (s->_cooked_size != 0) 280560484Sobrien dyn.d_un.d_val = s->_cooked_size; 280660484Sobrien else 280760484Sobrien dyn.d_un.d_val = s->_raw_size; 280860484Sobrien } 280960484Sobrien } 281060484Sobrien bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); 281160484Sobrien } 281260484Sobrien } 281360484Sobrien } 281460484Sobrien 281560484Sobrien /* Add a blrl instruction at _GLOBAL_OFFSET_TABLE_-4 so that a function can 281660484Sobrien easily find the address of the _GLOBAL_OFFSET_TABLE_. */ 281760484Sobrien if (sgot) 281860484Sobrien { 281960484Sobrien unsigned char *contents = sgot->contents; 282089857Sobrien bfd_put_32 (output_bfd, (bfd_vma) 0x4e800021 /* blrl */, contents); 282160484Sobrien 282260484Sobrien if (sdyn == NULL) 282360484Sobrien bfd_put_32 (output_bfd, (bfd_vma) 0, contents+4); 282460484Sobrien else 282560484Sobrien bfd_put_32 (output_bfd, 282660484Sobrien sdyn->output_section->vma + sdyn->output_offset, 282760484Sobrien contents+4); 282860484Sobrien 282960484Sobrien elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4; 283060484Sobrien } 283160484Sobrien 283260484Sobrien return true; 283360484Sobrien} 283460484Sobrien 283560484Sobrien/* The RELOCATE_SECTION function is called by the ELF backend linker 283660484Sobrien to handle the relocations for a section. 283760484Sobrien 283860484Sobrien The relocs are always passed as Rela structures; if the section 283960484Sobrien actually uses Rel structures, the r_addend field will always be 284060484Sobrien zero. 284160484Sobrien 284260484Sobrien This function is responsible for adjust the section contents as 284360484Sobrien necessary, and (if using Rela relocs and generating a 284460484Sobrien relocateable output file) adjusting the reloc addend as 284560484Sobrien necessary. 284660484Sobrien 284760484Sobrien This function does not have to worry about setting the reloc 284860484Sobrien address or the reloc symbol index. 284960484Sobrien 285060484Sobrien LOCAL_SYMS is a pointer to the swapped in local symbols. 285160484Sobrien 285260484Sobrien LOCAL_SECTIONS is an array giving the section in the input file 285360484Sobrien corresponding to the st_shndx field of each local symbol. 285460484Sobrien 285560484Sobrien The global hash table entry for the global symbols can be found 285660484Sobrien via elf_sym_hashes (input_bfd). 285760484Sobrien 285860484Sobrien When generating relocateable output, this function must handle 285960484Sobrien STB_LOCAL/STT_SECTION symbols specially. The output symbol is 286060484Sobrien going to be the section symbol corresponding to the output 286160484Sobrien section, which means that the addend must be adjusted 286260484Sobrien accordingly. */ 286360484Sobrien 286460484Sobrienstatic boolean 286560484Sobrienppc_elf_relocate_section (output_bfd, info, input_bfd, input_section, 286660484Sobrien contents, relocs, local_syms, local_sections) 286760484Sobrien bfd *output_bfd; 286860484Sobrien struct bfd_link_info *info; 286960484Sobrien bfd *input_bfd; 287060484Sobrien asection *input_section; 287160484Sobrien bfd_byte *contents; 287260484Sobrien Elf_Internal_Rela *relocs; 287360484Sobrien Elf_Internal_Sym *local_syms; 287460484Sobrien asection **local_sections; 287560484Sobrien{ 287660484Sobrien Elf_Internal_Shdr *symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; 287760484Sobrien struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (input_bfd); 287860484Sobrien bfd *dynobj = elf_hash_table (info)->dynobj; 287960484Sobrien elf_linker_section_t *sdata = (dynobj) ? elf_linker_section (dynobj, LINKER_SECTION_SDATA) : NULL; 288060484Sobrien elf_linker_section_t *sdata2 = (dynobj) ? elf_linker_section (dynobj, LINKER_SECTION_SDATA2) : NULL; 288160484Sobrien Elf_Internal_Rela *rel = relocs; 288260484Sobrien Elf_Internal_Rela *relend = relocs + input_section->reloc_count; 288360484Sobrien asection *sreloc = NULL; 288460484Sobrien asection *splt; 288560484Sobrien asection *sgot; 288660484Sobrien bfd_vma *local_got_offsets; 288760484Sobrien boolean ret = true; 288860484Sobrien long insn; 288960484Sobrien 289060484Sobrien#ifdef DEBUG 289160484Sobrien fprintf (stderr, "ppc_elf_relocate_section called for %s section %s, %ld relocations%s\n", 289289857Sobrien bfd_archive_filename (input_bfd), 289360484Sobrien bfd_section_name(input_bfd, input_section), 289477298Sobrien (long) input_section->reloc_count, 289560484Sobrien (info->relocateable) ? " (relocatable)" : ""); 289660484Sobrien#endif 289760484Sobrien 289877298Sobrien if (!ppc_elf_howto_table[R_PPC_ADDR32]) 289977298Sobrien /* Initialize howto table if needed. */ 290060484Sobrien ppc_elf_howto_init (); 290160484Sobrien 290260484Sobrien local_got_offsets = elf_local_got_offsets (input_bfd); 290360484Sobrien 290460484Sobrien splt = sgot = NULL; 290560484Sobrien if (dynobj != NULL) 290660484Sobrien { 290760484Sobrien splt = bfd_get_section_by_name (dynobj, ".plt"); 290860484Sobrien sgot = bfd_get_section_by_name (dynobj, ".got"); 290960484Sobrien } 291060484Sobrien 291160484Sobrien for (; rel < relend; rel++) 291260484Sobrien { 291360484Sobrien enum elf_ppc_reloc_type r_type = (enum elf_ppc_reloc_type)ELF32_R_TYPE (rel->r_info); 291460484Sobrien bfd_vma offset = rel->r_offset; 291560484Sobrien bfd_vma addend = rel->r_addend; 291660484Sobrien bfd_reloc_status_type r = bfd_reloc_other; 291777298Sobrien Elf_Internal_Sym *sym = (Elf_Internal_Sym *) 0; 291877298Sobrien asection *sec = (asection *) 0; 291977298Sobrien struct elf_link_hash_entry *h = (struct elf_link_hash_entry *) 0; 292077298Sobrien const char *sym_name = (const char *) 0; 292160484Sobrien reloc_howto_type *howto; 292260484Sobrien unsigned long r_symndx; 292360484Sobrien bfd_vma relocation; 292477298Sobrien int will_become_local; 292560484Sobrien 292660484Sobrien /* Unknown relocation handling */ 292777298Sobrien if ((unsigned) r_type >= (unsigned) R_PPC_max 292877298Sobrien || !ppc_elf_howto_table[(int) r_type]) 292960484Sobrien { 293060484Sobrien (*_bfd_error_handler) (_("%s: unknown relocation type %d"), 293189857Sobrien bfd_archive_filename (input_bfd), 293277298Sobrien (int) r_type); 293360484Sobrien 293460484Sobrien bfd_set_error (bfd_error_bad_value); 293560484Sobrien ret = false; 293660484Sobrien continue; 293760484Sobrien } 293860484Sobrien 293977298Sobrien howto = ppc_elf_howto_table[(int) r_type]; 294060484Sobrien r_symndx = ELF32_R_SYM (rel->r_info); 294160484Sobrien 294260484Sobrien if (info->relocateable) 294360484Sobrien { 294460484Sobrien /* This is a relocateable link. We don't have to change 294560484Sobrien anything, unless the reloc is against a section symbol, 294660484Sobrien in which case we have to adjust according to where the 294760484Sobrien section symbol winds up in the output section. */ 294860484Sobrien if (r_symndx < symtab_hdr->sh_info) 294960484Sobrien { 295060484Sobrien sym = local_syms + r_symndx; 295177298Sobrien if ((unsigned) ELF_ST_TYPE (sym->st_info) == STT_SECTION) 295260484Sobrien { 295360484Sobrien sec = local_sections[r_symndx]; 295460484Sobrien addend = rel->r_addend += sec->output_offset + sym->st_value; 295560484Sobrien } 295660484Sobrien } 295760484Sobrien 295860484Sobrien#ifdef DEBUG 295960484Sobrien fprintf (stderr, "\ttype = %s (%d), symbol index = %ld, offset = %ld, addend = %ld\n", 296060484Sobrien howto->name, 296177298Sobrien (int) r_type, 296260484Sobrien r_symndx, 296377298Sobrien (long) offset, 296477298Sobrien (long) addend); 296560484Sobrien#endif 296660484Sobrien continue; 296760484Sobrien } 296860484Sobrien 296960484Sobrien /* This is a final link. */ 297060484Sobrien if (r_symndx < symtab_hdr->sh_info) 297160484Sobrien { 297260484Sobrien sym = local_syms + r_symndx; 297360484Sobrien sec = local_sections[r_symndx]; 297460484Sobrien sym_name = "<local symbol>"; 297560484Sobrien 297689857Sobrien relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel); 297789857Sobrien addend = rel->r_addend; 297877298Sobrien /* Relocs to local symbols are always resolved. */ 297977298Sobrien will_become_local = 1; 298060484Sobrien } 298160484Sobrien else 298260484Sobrien { 298360484Sobrien h = sym_hashes[r_symndx - symtab_hdr->sh_info]; 298460484Sobrien while (h->root.type == bfd_link_hash_indirect 298560484Sobrien || h->root.type == bfd_link_hash_warning) 298660484Sobrien h = (struct elf_link_hash_entry *) h->root.u.i.link; 298760484Sobrien sym_name = h->root.root.string; 298877298Sobrien 298977298Sobrien /* Can this relocation be resolved immediately? */ 299077298Sobrien will_become_local = SYMBOL_REFERENCES_LOCAL (info, h); 299177298Sobrien 299260484Sobrien if (h->root.type == bfd_link_hash_defined 299360484Sobrien || h->root.type == bfd_link_hash_defweak) 299460484Sobrien { 299560484Sobrien sec = h->root.u.def.section; 299677298Sobrien if (((r_type == R_PPC_PLT32 299777298Sobrien || r_type == R_PPC_PLTREL24) 299877298Sobrien && splt != NULL 299960484Sobrien && h->plt.offset != (bfd_vma) -1) 300060484Sobrien || (r_type == R_PPC_LOCAL24PC 300160484Sobrien && sec->output_section == NULL) 300260484Sobrien || ((r_type == R_PPC_GOT16 300360484Sobrien || r_type == R_PPC_GOT16_LO 300460484Sobrien || r_type == R_PPC_GOT16_HI 300560484Sobrien || r_type == R_PPC_GOT16_HA) 300660484Sobrien && elf_hash_table (info)->dynamic_sections_created 300777298Sobrien && (! info->shared || ! will_become_local)) 300860484Sobrien || (info->shared 300977298Sobrien && ! will_become_local 301060484Sobrien && ((input_section->flags & SEC_ALLOC) != 0 301160484Sobrien /* Testing SEC_DEBUGGING here may be wrong. 301260484Sobrien It's here to avoid a crash when 301360484Sobrien generating a shared library with DWARF 301460484Sobrien debugging information. */ 301577298Sobrien || ((input_section->flags & SEC_DEBUGGING) != 0 301677298Sobrien && (h->elf_link_hash_flags 301777298Sobrien & ELF_LINK_HASH_DEF_DYNAMIC) != 0)) 301860484Sobrien && (r_type == R_PPC_ADDR32 301960484Sobrien || r_type == R_PPC_ADDR24 302060484Sobrien || r_type == R_PPC_ADDR16 302160484Sobrien || r_type == R_PPC_ADDR16_LO 302260484Sobrien || r_type == R_PPC_ADDR16_HI 302360484Sobrien || r_type == R_PPC_ADDR16_HA 302460484Sobrien || r_type == R_PPC_ADDR14 302560484Sobrien || r_type == R_PPC_ADDR14_BRTAKEN 302660484Sobrien || r_type == R_PPC_ADDR14_BRNTAKEN 302760484Sobrien || r_type == R_PPC_COPY 302860484Sobrien || r_type == R_PPC_GLOB_DAT 302960484Sobrien || r_type == R_PPC_JMP_SLOT 303060484Sobrien || r_type == R_PPC_UADDR32 303160484Sobrien || r_type == R_PPC_UADDR16 303260484Sobrien || r_type == R_PPC_SDAREL16 303360484Sobrien || r_type == R_PPC_EMB_NADDR32 303460484Sobrien || r_type == R_PPC_EMB_NADDR16 303560484Sobrien || r_type == R_PPC_EMB_NADDR16_LO 303660484Sobrien || r_type == R_PPC_EMB_NADDR16_HI 303760484Sobrien || r_type == R_PPC_EMB_NADDR16_HA 303860484Sobrien || r_type == R_PPC_EMB_SDAI16 303960484Sobrien || r_type == R_PPC_EMB_SDA2I16 304060484Sobrien || r_type == R_PPC_EMB_SDA2REL 304160484Sobrien || r_type == R_PPC_EMB_SDA21 304260484Sobrien || r_type == R_PPC_EMB_MRKREF 304360484Sobrien || r_type == R_PPC_EMB_BIT_FLD 304460484Sobrien || r_type == R_PPC_EMB_RELSDA 304560484Sobrien || ((r_type == R_PPC_REL24 304660484Sobrien || r_type == R_PPC_REL32 304760484Sobrien || r_type == R_PPC_REL14 304860484Sobrien || r_type == R_PPC_REL14_BRTAKEN 304960484Sobrien || r_type == R_PPC_REL14_BRNTAKEN 305060484Sobrien || r_type == R_PPC_RELATIVE) 305160484Sobrien && strcmp (h->root.root.string, 305260484Sobrien "_GLOBAL_OFFSET_TABLE_") != 0)))) 305360484Sobrien { 305460484Sobrien /* In these cases, we don't need the relocation 305560484Sobrien value. We check specially because in some 305660484Sobrien obscure cases sec->output_section will be NULL. */ 305760484Sobrien relocation = 0; 305860484Sobrien } 305960484Sobrien else if (sec->output_section == NULL) 306077298Sobrien { 306160484Sobrien (*_bfd_error_handler) 306260484Sobrien (_("%s: warning: unresolvable relocation against symbol `%s' from %s section"), 306389857Sobrien bfd_archive_filename (input_bfd), h->root.root.string, 306460484Sobrien bfd_get_section_name (input_bfd, input_section)); 306560484Sobrien relocation = 0; 306677298Sobrien } 306760484Sobrien else 306860484Sobrien relocation = (h->root.u.def.value 306960484Sobrien + sec->output_section->vma 307060484Sobrien + sec->output_offset); 307160484Sobrien } 307260484Sobrien else if (h->root.type == bfd_link_hash_undefweak) 307360484Sobrien relocation = 0; 307489857Sobrien else if (info->shared 307589857Sobrien && (!info->symbolic || info->allow_shlib_undefined) 307689857Sobrien && !info->no_undefined 307768765Sobrien && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT) 307860484Sobrien relocation = 0; 307960484Sobrien else 308060484Sobrien { 308177298Sobrien if (! (*info->callbacks->undefined_symbol) (info, 308260484Sobrien h->root.root.string, 308360484Sobrien input_bfd, 308460484Sobrien input_section, 308560484Sobrien rel->r_offset, 308660484Sobrien (!info->shared 308768765Sobrien || info->no_undefined 308868765Sobrien || ELF_ST_VISIBILITY (h->other)))) 308960484Sobrien return false; 309060484Sobrien relocation = 0; 309160484Sobrien } 309260484Sobrien } 309360484Sobrien 309477298Sobrien switch ((int) r_type) 309560484Sobrien { 309660484Sobrien default: 309760484Sobrien (*_bfd_error_handler) (_("%s: unknown relocation type %d for symbol %s"), 309889857Sobrien bfd_archive_filename (input_bfd), 309977298Sobrien (int) r_type, sym_name); 310060484Sobrien 310160484Sobrien bfd_set_error (bfd_error_bad_value); 310260484Sobrien ret = false; 310360484Sobrien continue; 310460484Sobrien 310589857Sobrien case (int) R_PPC_NONE: 310689857Sobrien continue; 310789857Sobrien 310860484Sobrien /* Relocations that need no special processing. */ 310977298Sobrien case (int) R_PPC_LOCAL24PC: 311060484Sobrien /* It makes no sense to point a local relocation 311160484Sobrien at a symbol not in this object. */ 311260484Sobrien if (h != NULL 311360484Sobrien && (h->root.type == bfd_link_hash_defined 311460484Sobrien || h->root.type == bfd_link_hash_defweak) 311560484Sobrien && sec->output_section == NULL) 311660484Sobrien { 311760484Sobrien if (! (*info->callbacks->undefined_symbol) (info, 311860484Sobrien h->root.root.string, 311960484Sobrien input_bfd, 312060484Sobrien input_section, 312160484Sobrien rel->r_offset, 312260484Sobrien true)) 312360484Sobrien return false; 312460484Sobrien continue; 312560484Sobrien } 312660484Sobrien break; 312760484Sobrien 312860484Sobrien /* Relocations that may need to be propagated if this is a shared 312960484Sobrien object. */ 313077298Sobrien case (int) R_PPC_REL24: 313177298Sobrien case (int) R_PPC_REL32: 313277298Sobrien case (int) R_PPC_REL14: 313360484Sobrien /* If these relocations are not to a named symbol, they can be 313460484Sobrien handled right here, no need to bother the dynamic linker. */ 313560484Sobrien if (h == NULL 313677298Sobrien || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0 313777298Sobrien || SYMBOL_REFERENCES_LOCAL (info, h)) 313860484Sobrien break; 313960484Sobrien /* fall through */ 314060484Sobrien 314160484Sobrien /* Relocations that always need to be propagated if this is a shared 314260484Sobrien object. */ 314377298Sobrien case (int) R_PPC_ADDR32: 314477298Sobrien case (int) R_PPC_ADDR24: 314577298Sobrien case (int) R_PPC_ADDR16: 314677298Sobrien case (int) R_PPC_ADDR16_LO: 314777298Sobrien case (int) R_PPC_ADDR16_HI: 314877298Sobrien case (int) R_PPC_ADDR16_HA: 314977298Sobrien case (int) R_PPC_ADDR14: 315077298Sobrien case (int) R_PPC_UADDR32: 315177298Sobrien case (int) R_PPC_UADDR16: 315289857Sobrien if (info->shared && r_symndx != 0) 315360484Sobrien { 315460484Sobrien Elf_Internal_Rela outrel; 315560484Sobrien boolean skip; 315660484Sobrien 315760484Sobrien#ifdef DEBUG 315860484Sobrien fprintf (stderr, "ppc_elf_relocate_section need to create relocation for %s\n", 315960484Sobrien (h && h->root.root.string) ? h->root.root.string : "<unknown>"); 316060484Sobrien#endif 316160484Sobrien 316260484Sobrien /* When generating a shared object, these relocations 316360484Sobrien are copied into the output file to be resolved at run 316460484Sobrien time. */ 316560484Sobrien 316660484Sobrien if (sreloc == NULL) 316760484Sobrien { 316860484Sobrien const char *name; 316960484Sobrien 317060484Sobrien name = (bfd_elf_string_from_elf_section 317160484Sobrien (input_bfd, 317260484Sobrien elf_elfheader (input_bfd)->e_shstrndx, 317360484Sobrien elf_section_data (input_section)->rel_hdr.sh_name)); 317460484Sobrien if (name == NULL) 317560484Sobrien return false; 317660484Sobrien 317760484Sobrien BFD_ASSERT (strncmp (name, ".rela", 5) == 0 317860484Sobrien && strcmp (bfd_get_section_name (input_bfd, 317960484Sobrien input_section), 318060484Sobrien name + 5) == 0); 318160484Sobrien 318260484Sobrien sreloc = bfd_get_section_by_name (dynobj, name); 318360484Sobrien BFD_ASSERT (sreloc != NULL); 318460484Sobrien } 318560484Sobrien 318660484Sobrien skip = false; 318760484Sobrien 318889857Sobrien outrel.r_offset = 318989857Sobrien _bfd_elf_section_offset (output_bfd, info, input_section, 319089857Sobrien rel->r_offset); 319189857Sobrien if (outrel.r_offset == (bfd_vma) -1) 319289857Sobrien skip = true; 319360484Sobrien outrel.r_offset += (input_section->output_section->vma 319460484Sobrien + input_section->output_offset); 319560484Sobrien 319660484Sobrien if (skip) 319760484Sobrien memset (&outrel, 0, sizeof outrel); 319860484Sobrien /* h->dynindx may be -1 if this symbol was marked to 319960484Sobrien become local. */ 320077298Sobrien else if (! will_become_local) 320160484Sobrien { 320260484Sobrien outrel.r_info = ELF32_R_INFO (h->dynindx, r_type); 320360484Sobrien outrel.r_addend = rel->r_addend; 320460484Sobrien } 320560484Sobrien else 320660484Sobrien { 320760484Sobrien if (r_type == R_PPC_ADDR32) 320860484Sobrien { 320960484Sobrien outrel.r_info = ELF32_R_INFO (0, R_PPC_RELATIVE); 321060484Sobrien outrel.r_addend = relocation + rel->r_addend; 321160484Sobrien } 321260484Sobrien else 321360484Sobrien { 321460484Sobrien long indx; 321560484Sobrien 321660484Sobrien if (h == NULL) 321760484Sobrien sec = local_sections[r_symndx]; 321860484Sobrien else 321960484Sobrien { 322060484Sobrien BFD_ASSERT (h->root.type == bfd_link_hash_defined 322160484Sobrien || (h->root.type 322260484Sobrien == bfd_link_hash_defweak)); 322360484Sobrien sec = h->root.u.def.section; 322460484Sobrien } 322560484Sobrien if (sec != NULL && bfd_is_abs_section (sec)) 322660484Sobrien indx = 0; 322760484Sobrien else if (sec == NULL || sec->owner == NULL) 322860484Sobrien { 322960484Sobrien bfd_set_error (bfd_error_bad_value); 323060484Sobrien return false; 323160484Sobrien } 323260484Sobrien else 323360484Sobrien { 323460484Sobrien asection *osec; 323560484Sobrien 323660484Sobrien osec = sec->output_section; 323760484Sobrien indx = elf_section_data (osec)->dynindx; 323877298Sobrien BFD_ASSERT (indx > 0); 323960484Sobrien#ifdef DEBUG 324060484Sobrien if (indx <= 0) 324160484Sobrien { 324277298Sobrien printf ("indx=%d section=%s flags=%08x name=%s\n", 324360484Sobrien indx, osec->name, osec->flags, 324460484Sobrien h->root.root.string); 324560484Sobrien } 324660484Sobrien#endif 324760484Sobrien } 324860484Sobrien 324960484Sobrien outrel.r_info = ELF32_R_INFO (indx, r_type); 325060484Sobrien outrel.r_addend = relocation + rel->r_addend; 325160484Sobrien } 325260484Sobrien } 325360484Sobrien 325460484Sobrien bfd_elf32_swap_reloca_out (output_bfd, &outrel, 325560484Sobrien (((Elf32_External_Rela *) 325660484Sobrien sreloc->contents) 325760484Sobrien + sreloc->reloc_count)); 325860484Sobrien ++sreloc->reloc_count; 325960484Sobrien 326060484Sobrien /* This reloc will be computed at runtime, so there's no 326160484Sobrien need to do anything now, unless this is a RELATIVE 326260484Sobrien reloc in an unallocated section. */ 326360484Sobrien if (skip 326460484Sobrien || (input_section->flags & SEC_ALLOC) != 0 326560484Sobrien || ELF32_R_TYPE (outrel.r_info) != R_PPC_RELATIVE) 326660484Sobrien continue; 326760484Sobrien } 326860484Sobrien 326960484Sobrien /* Arithmetic adjust relocations that aren't going into a 327060484Sobrien shared object. */ 327160484Sobrien if (r_type == R_PPC_ADDR16_HA 327260484Sobrien /* It's just possible that this symbol is a weak symbol 327360484Sobrien that's not actually defined anywhere. In that case, 327460484Sobrien 'sec' would be NULL, and we should leave the symbol 327560484Sobrien alone (it will be set to zero elsewhere in the link). */ 327660484Sobrien && sec != NULL) 327760484Sobrien { 327860484Sobrien addend += ((relocation + addend) & 0x8000) << 1; 327960484Sobrien } 328060484Sobrien break; 328160484Sobrien 328260484Sobrien /* branch taken prediction relocations */ 328377298Sobrien case (int) R_PPC_ADDR14_BRTAKEN: 328477298Sobrien case (int) R_PPC_REL14_BRTAKEN: 328560484Sobrien insn = bfd_get_32 (output_bfd, contents + offset); 328660484Sobrien if ((relocation - offset) & 0x8000) 328760484Sobrien insn &= ~BRANCH_PREDICT_BIT; 328860484Sobrien else 328960484Sobrien insn |= BRANCH_PREDICT_BIT; 329089857Sobrien bfd_put_32 (output_bfd, (bfd_vma) insn, contents + offset); 329160484Sobrien break; 329260484Sobrien 329360484Sobrien /* branch not taken predicition relocations */ 329477298Sobrien case (int) R_PPC_ADDR14_BRNTAKEN: 329577298Sobrien case (int) R_PPC_REL14_BRNTAKEN: 329660484Sobrien insn = bfd_get_32 (output_bfd, contents + offset); 329760484Sobrien if ((relocation - offset) & 0x8000) 329860484Sobrien insn |= BRANCH_PREDICT_BIT; 329960484Sobrien else 330060484Sobrien insn &= ~BRANCH_PREDICT_BIT; 330189857Sobrien bfd_put_32 (output_bfd, (bfd_vma) insn, contents + offset); 330260484Sobrien break; 330360484Sobrien 330460484Sobrien /* GOT16 relocations */ 330577298Sobrien case (int) R_PPC_GOT16: 330677298Sobrien case (int) R_PPC_GOT16_LO: 330777298Sobrien case (int) R_PPC_GOT16_HI: 330877298Sobrien case (int) R_PPC_GOT16_HA: 330960484Sobrien /* Relocation is to the entry for this symbol in the global 331060484Sobrien offset table. */ 331160484Sobrien BFD_ASSERT (sgot != NULL); 331260484Sobrien 331360484Sobrien if (h != NULL) 331460484Sobrien { 331560484Sobrien bfd_vma off; 331660484Sobrien 331760484Sobrien off = h->got.offset; 331860484Sobrien BFD_ASSERT (off != (bfd_vma) -1); 331960484Sobrien 332060484Sobrien if (! elf_hash_table (info)->dynamic_sections_created 332160484Sobrien || (info->shared 332277298Sobrien && SYMBOL_REFERENCES_LOCAL (info, h))) 332360484Sobrien { 332460484Sobrien /* This is actually a static link, or it is a 332560484Sobrien -Bsymbolic link and the symbol is defined 332660484Sobrien locally. We must initialize this entry in the 332760484Sobrien global offset table. Since the offset must 332860484Sobrien always be a multiple of 4, we use the least 332960484Sobrien significant bit to record whether we have 333060484Sobrien initialized it already. 333160484Sobrien 333260484Sobrien When doing a dynamic link, we create a .rela.got 333360484Sobrien relocation entry to initialize the value. This 333460484Sobrien is done in the finish_dynamic_symbol routine. */ 333560484Sobrien if ((off & 1) != 0) 333660484Sobrien off &= ~1; 333760484Sobrien else 333860484Sobrien { 333960484Sobrien bfd_put_32 (output_bfd, relocation, 334060484Sobrien sgot->contents + off); 334160484Sobrien h->got.offset |= 1; 334260484Sobrien } 334360484Sobrien } 334460484Sobrien 334560484Sobrien relocation = sgot->output_offset + off - 4; 334660484Sobrien } 334760484Sobrien else 334860484Sobrien { 334960484Sobrien bfd_vma off; 335060484Sobrien 335160484Sobrien BFD_ASSERT (local_got_offsets != NULL 335260484Sobrien && local_got_offsets[r_symndx] != (bfd_vma) -1); 335360484Sobrien 335460484Sobrien off = local_got_offsets[r_symndx]; 335560484Sobrien 335660484Sobrien /* The offset must always be a multiple of 4. We use 335760484Sobrien the least significant bit to record whether we have 335860484Sobrien already processed this entry. */ 335960484Sobrien if ((off & 1) != 0) 336060484Sobrien off &= ~1; 336160484Sobrien else 336260484Sobrien { 336360484Sobrien bfd_put_32 (output_bfd, relocation, sgot->contents + off); 336460484Sobrien 336560484Sobrien if (info->shared) 336660484Sobrien { 336760484Sobrien asection *srelgot; 336860484Sobrien Elf_Internal_Rela outrel; 336960484Sobrien 337060484Sobrien /* We need to generate a R_PPC_RELATIVE reloc 337160484Sobrien for the dynamic linker. */ 337260484Sobrien srelgot = bfd_get_section_by_name (dynobj, ".rela.got"); 337360484Sobrien BFD_ASSERT (srelgot != NULL); 337460484Sobrien 337560484Sobrien outrel.r_offset = (sgot->output_section->vma 337660484Sobrien + sgot->output_offset 337760484Sobrien + off); 337860484Sobrien outrel.r_info = ELF32_R_INFO (0, R_PPC_RELATIVE); 337960484Sobrien outrel.r_addend = relocation; 338060484Sobrien bfd_elf32_swap_reloca_out (output_bfd, &outrel, 338160484Sobrien (((Elf32_External_Rela *) 338260484Sobrien srelgot->contents) 338360484Sobrien + srelgot->reloc_count)); 338460484Sobrien ++srelgot->reloc_count; 338560484Sobrien } 338660484Sobrien 338760484Sobrien local_got_offsets[r_symndx] |= 1; 338860484Sobrien } 338960484Sobrien 339060484Sobrien relocation = sgot->output_offset + off - 4; 339160484Sobrien } 339260484Sobrien break; 339360484Sobrien 339460484Sobrien /* Indirect .sdata relocation */ 339577298Sobrien case (int) R_PPC_EMB_SDAI16: 339660484Sobrien BFD_ASSERT (sdata != NULL); 339760484Sobrien relocation = bfd_elf32_finish_pointer_linker_section (output_bfd, input_bfd, info, 339860484Sobrien sdata, h, relocation, rel, 339960484Sobrien R_PPC_RELATIVE); 340060484Sobrien break; 340160484Sobrien 340260484Sobrien /* Indirect .sdata2 relocation */ 340377298Sobrien case (int) R_PPC_EMB_SDA2I16: 340460484Sobrien BFD_ASSERT (sdata2 != NULL); 340560484Sobrien relocation = bfd_elf32_finish_pointer_linker_section (output_bfd, input_bfd, info, 340660484Sobrien sdata2, h, relocation, rel, 340760484Sobrien R_PPC_RELATIVE); 340860484Sobrien break; 340960484Sobrien 341060484Sobrien /* Handle the TOC16 reloc. We want to use the offset within the .got 341160484Sobrien section, not the actual VMA. This is appropriate when generating 341260484Sobrien an embedded ELF object, for which the .got section acts like the 341360484Sobrien AIX .toc section. */ 341477298Sobrien case (int) R_PPC_TOC16: /* phony GOT16 relocations */ 341577298Sobrien BFD_ASSERT (sec != (asection *) 0); 341660484Sobrien BFD_ASSERT (bfd_is_und_section (sec) 341760484Sobrien || strcmp (bfd_get_section_name (abfd, sec), ".got") == 0 341860484Sobrien || strcmp (bfd_get_section_name (abfd, sec), ".cgot") == 0) 341960484Sobrien 342060484Sobrien addend -= sec->output_section->vma + sec->output_offset + 0x8000; 342160484Sobrien break; 342260484Sobrien 342377298Sobrien case (int) R_PPC_PLTREL24: 342460484Sobrien /* Relocation is to the entry for this symbol in the 342560484Sobrien procedure linkage table. */ 342660484Sobrien BFD_ASSERT (h != NULL); 342760484Sobrien 342860484Sobrien if (h->plt.offset == (bfd_vma) -1 342960484Sobrien || splt == NULL) 343060484Sobrien { 343160484Sobrien /* We didn't make a PLT entry for this symbol. This 343260484Sobrien happens when statically linking PIC code, or when 343360484Sobrien using -Bsymbolic. */ 343460484Sobrien break; 343560484Sobrien } 343660484Sobrien 343760484Sobrien relocation = (splt->output_section->vma 343860484Sobrien + splt->output_offset 343960484Sobrien + h->plt.offset); 344077298Sobrien break; 344160484Sobrien 344260484Sobrien /* relocate against _SDA_BASE_ */ 344377298Sobrien case (int) R_PPC_SDAREL16: 344460484Sobrien { 344560484Sobrien const char *name; 344660484Sobrien 344777298Sobrien BFD_ASSERT (sec != (asection *) 0); 344860484Sobrien name = bfd_get_section_name (abfd, sec->output_section); 344960484Sobrien if (strcmp (name, ".sdata") != 0 345060484Sobrien && strcmp (name, ".sbss") != 0) 345160484Sobrien { 345260484Sobrien (*_bfd_error_handler) (_("%s: The target (%s) of a %s relocation is in the wrong output section (%s)"), 345389857Sobrien bfd_archive_filename (input_bfd), 345460484Sobrien sym_name, 345577298Sobrien ppc_elf_howto_table[(int) r_type]->name, 345660484Sobrien name); 345760484Sobrien } 345860484Sobrien addend -= (sdata->sym_hash->root.u.def.value 345960484Sobrien + sdata->sym_hash->root.u.def.section->output_section->vma 346060484Sobrien + sdata->sym_hash->root.u.def.section->output_offset); 346160484Sobrien } 346260484Sobrien break; 346360484Sobrien 346460484Sobrien /* relocate against _SDA2_BASE_ */ 346577298Sobrien case (int) R_PPC_EMB_SDA2REL: 346660484Sobrien { 346760484Sobrien const char *name; 346860484Sobrien 346977298Sobrien BFD_ASSERT (sec != (asection *) 0); 347060484Sobrien name = bfd_get_section_name (abfd, sec->output_section); 347160484Sobrien if (strcmp (name, ".sdata2") != 0 && strcmp (name, ".sbss2") != 0) 347260484Sobrien { 347360484Sobrien (*_bfd_error_handler) (_("%s: The target (%s) of a %s relocation is in the wrong output section (%s)"), 347489857Sobrien bfd_archive_filename (input_bfd), 347560484Sobrien sym_name, 347677298Sobrien ppc_elf_howto_table[(int) r_type]->name, 347760484Sobrien name); 347877298Sobrien 347960484Sobrien bfd_set_error (bfd_error_bad_value); 348060484Sobrien ret = false; 348160484Sobrien continue; 348260484Sobrien } 348360484Sobrien addend -= (sdata2->sym_hash->root.u.def.value 348460484Sobrien + sdata2->sym_hash->root.u.def.section->output_section->vma 348560484Sobrien + sdata2->sym_hash->root.u.def.section->output_offset); 348660484Sobrien } 348760484Sobrien break; 348860484Sobrien 348960484Sobrien /* relocate against either _SDA_BASE_, _SDA2_BASE_, or 0 */ 349077298Sobrien case (int) R_PPC_EMB_SDA21: 349177298Sobrien case (int) R_PPC_EMB_RELSDA: 349260484Sobrien { 349360484Sobrien const char *name; 349460484Sobrien int reg; 349560484Sobrien 349677298Sobrien BFD_ASSERT (sec != (asection *) 0); 349760484Sobrien name = bfd_get_section_name (abfd, sec->output_section); 349860484Sobrien if (strcmp (name, ".sdata") == 0 || strcmp (name, ".sbss") == 0) 349960484Sobrien { 350060484Sobrien reg = 13; 350160484Sobrien addend -= (sdata->sym_hash->root.u.def.value 350260484Sobrien + sdata->sym_hash->root.u.def.section->output_section->vma 350360484Sobrien + sdata->sym_hash->root.u.def.section->output_offset); 350460484Sobrien } 350560484Sobrien 350677298Sobrien else if (strcmp (name, ".sdata2") == 0 350777298Sobrien || strcmp (name, ".sbss2") == 0) 350860484Sobrien { 350960484Sobrien reg = 2; 351060484Sobrien addend -= (sdata2->sym_hash->root.u.def.value 351160484Sobrien + sdata2->sym_hash->root.u.def.section->output_section->vma 351260484Sobrien + sdata2->sym_hash->root.u.def.section->output_offset); 351360484Sobrien } 351460484Sobrien 351577298Sobrien else if (strcmp (name, ".PPC.EMB.sdata0") == 0 351677298Sobrien || strcmp (name, ".PPC.EMB.sbss0") == 0) 351760484Sobrien { 351860484Sobrien reg = 0; 351960484Sobrien } 352060484Sobrien 352160484Sobrien else 352260484Sobrien { 352360484Sobrien (*_bfd_error_handler) (_("%s: The target (%s) of a %s relocation is in the wrong output section (%s)"), 352489857Sobrien bfd_archive_filename (input_bfd), 352560484Sobrien sym_name, 352677298Sobrien ppc_elf_howto_table[(int) r_type]->name, 352760484Sobrien name); 352860484Sobrien 352960484Sobrien bfd_set_error (bfd_error_bad_value); 353060484Sobrien ret = false; 353160484Sobrien continue; 353260484Sobrien } 353360484Sobrien 353460484Sobrien if (r_type == R_PPC_EMB_SDA21) 353560484Sobrien { /* fill in register field */ 353660484Sobrien insn = bfd_get_32 (output_bfd, contents + offset); 353760484Sobrien insn = (insn & ~RA_REGISTER_MASK) | (reg << RA_REGISTER_SHIFT); 353889857Sobrien bfd_put_32 (output_bfd, (bfd_vma) insn, contents + offset); 353960484Sobrien } 354060484Sobrien } 354160484Sobrien break; 354260484Sobrien 354360484Sobrien /* Relocate against the beginning of the section */ 354477298Sobrien case (int) R_PPC_SECTOFF: 354577298Sobrien case (int) R_PPC_SECTOFF_LO: 354677298Sobrien case (int) R_PPC_SECTOFF_HI: 354777298Sobrien BFD_ASSERT (sec != (asection *) 0); 354860484Sobrien addend -= sec->output_section->vma; 354960484Sobrien break; 355060484Sobrien 355177298Sobrien case (int) R_PPC_SECTOFF_HA: 355277298Sobrien BFD_ASSERT (sec != (asection *) 0); 355360484Sobrien addend -= sec->output_section->vma; 355460484Sobrien addend += ((relocation + addend) & 0x8000) << 1; 355560484Sobrien break; 355660484Sobrien 355760484Sobrien /* Negative relocations */ 355877298Sobrien case (int) R_PPC_EMB_NADDR32: 355977298Sobrien case (int) R_PPC_EMB_NADDR16: 356077298Sobrien case (int) R_PPC_EMB_NADDR16_LO: 356177298Sobrien case (int) R_PPC_EMB_NADDR16_HI: 356277298Sobrien addend -= 2 * relocation; 356360484Sobrien break; 356460484Sobrien 356577298Sobrien case (int) R_PPC_EMB_NADDR16_HA: 356677298Sobrien addend -= 2 * relocation; 356760484Sobrien addend += ((relocation + addend) & 0x8000) << 1; 356860484Sobrien break; 356960484Sobrien 357060484Sobrien /* NOP relocation that prevents garbage collecting linkers from omitting a 357160484Sobrien reference. */ 357277298Sobrien case (int) R_PPC_EMB_MRKREF: 357360484Sobrien continue; 357460484Sobrien 357577298Sobrien case (int) R_PPC_COPY: 357677298Sobrien case (int) R_PPC_GLOB_DAT: 357777298Sobrien case (int) R_PPC_JMP_SLOT: 357877298Sobrien case (int) R_PPC_RELATIVE: 357977298Sobrien case (int) R_PPC_PLT32: 358077298Sobrien case (int) R_PPC_PLTREL32: 358177298Sobrien case (int) R_PPC_PLT16_LO: 358277298Sobrien case (int) R_PPC_PLT16_HI: 358377298Sobrien case (int) R_PPC_PLT16_HA: 358477298Sobrien case (int) R_PPC_EMB_RELSEC16: 358577298Sobrien case (int) R_PPC_EMB_RELST_LO: 358677298Sobrien case (int) R_PPC_EMB_RELST_HI: 358777298Sobrien case (int) R_PPC_EMB_RELST_HA: 358877298Sobrien case (int) R_PPC_EMB_BIT_FLD: 358960484Sobrien (*_bfd_error_handler) (_("%s: Relocation %s is not yet supported for symbol %s."), 359089857Sobrien bfd_archive_filename (input_bfd), 359177298Sobrien ppc_elf_howto_table[(int) r_type]->name, 359260484Sobrien sym_name); 359360484Sobrien 359460484Sobrien bfd_set_error (bfd_error_invalid_operation); 359560484Sobrien ret = false; 359660484Sobrien continue; 359760484Sobrien 359877298Sobrien case (int) R_PPC_GNU_VTINHERIT: 359977298Sobrien case (int) R_PPC_GNU_VTENTRY: 360060484Sobrien /* These are no-ops in the end. */ 360160484Sobrien continue; 360260484Sobrien } 360360484Sobrien 360460484Sobrien#ifdef DEBUG 360560484Sobrien fprintf (stderr, "\ttype = %s (%d), name = %s, symbol index = %ld, offset = %ld, addend = %ld\n", 360660484Sobrien howto->name, 360777298Sobrien (int) r_type, 360860484Sobrien sym_name, 360960484Sobrien r_symndx, 361077298Sobrien (long) offset, 361177298Sobrien (long) addend); 361260484Sobrien#endif 361360484Sobrien 361460484Sobrien r = _bfd_final_link_relocate (howto, 361560484Sobrien input_bfd, 361660484Sobrien input_section, 361760484Sobrien contents, 361860484Sobrien offset, 361960484Sobrien relocation, 362060484Sobrien addend); 362160484Sobrien 362260484Sobrien if (r == bfd_reloc_ok) 362360484Sobrien ; 362460484Sobrien else if (r == bfd_reloc_overflow) 362560484Sobrien { 362660484Sobrien const char *name; 362760484Sobrien 362860484Sobrien if (h != NULL) 362960484Sobrien { 363060484Sobrien if (h->root.type == bfd_link_hash_undefweak 363160484Sobrien && howto->pc_relative) 363260484Sobrien { 363360484Sobrien /* Assume this is a call protected by other code that 363460484Sobrien detect the symbol is undefined. If this is the case, 363560484Sobrien we can safely ignore the overflow. If not, the 363660484Sobrien program is hosed anyway, and a little warning isn't 363760484Sobrien going to help. */ 363860484Sobrien 363960484Sobrien continue; 364060484Sobrien } 364160484Sobrien 364260484Sobrien name = h->root.root.string; 364360484Sobrien } 364460484Sobrien else 364560484Sobrien { 364660484Sobrien name = bfd_elf_string_from_elf_section (input_bfd, 364760484Sobrien symtab_hdr->sh_link, 364860484Sobrien sym->st_name); 364960484Sobrien if (name == NULL) 365060484Sobrien continue; 365160484Sobrien if (*name == '\0') 365260484Sobrien name = bfd_section_name (input_bfd, sec); 365360484Sobrien } 365460484Sobrien 365577298Sobrien if (! (*info->callbacks->reloc_overflow) (info, 365660484Sobrien name, 365760484Sobrien howto->name, 365860484Sobrien (bfd_vma) 0, 365960484Sobrien input_bfd, 366060484Sobrien input_section, 366160484Sobrien offset)) 366260484Sobrien return false; 366360484Sobrien } 366460484Sobrien else 366560484Sobrien ret = false; 366660484Sobrien } 366760484Sobrien 366860484Sobrien#ifdef DEBUG 366960484Sobrien fprintf (stderr, "\n"); 367060484Sobrien#endif 367160484Sobrien 367260484Sobrien return ret; 367360484Sobrien} 367489857Sobrien 367589857Sobrienstatic enum elf_reloc_type_class 367689857Sobrienppc_elf_reloc_type_class (rela) 367789857Sobrien const Elf_Internal_Rela *rela; 367889857Sobrien{ 367989857Sobrien switch ((int) ELF32_R_TYPE (rela->r_info)) 368089857Sobrien { 368189857Sobrien case R_PPC_RELATIVE: 368289857Sobrien return reloc_class_relative; 368389857Sobrien case R_PPC_REL24: 368489857Sobrien case R_PPC_ADDR24: 368589857Sobrien case R_PPC_JMP_SLOT: 368689857Sobrien return reloc_class_plt; 368789857Sobrien case R_PPC_COPY: 368889857Sobrien return reloc_class_copy; 368989857Sobrien default: 369089857Sobrien return reloc_class_normal; 369189857Sobrien } 369289857Sobrien} 369360484Sobrien 369489857Sobrien/* Support for core dump NOTE sections */ 369589857Sobrienstatic boolean 369689857Sobrienppc_elf_grok_prstatus (abfd, note) 369789857Sobrien bfd *abfd; 369889857Sobrien Elf_Internal_Note *note; 369989857Sobrien{ 370089857Sobrien int offset; 370189857Sobrien unsigned int raw_size; 370289857Sobrien 370389857Sobrien switch (note->descsz) 370489857Sobrien { 370589857Sobrien default: 370689857Sobrien return false; 370789857Sobrien 370889857Sobrien case 268: /* Linux/PPC */ 370989857Sobrien /* pr_cursig */ 371089857Sobrien elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12); 371189857Sobrien 371289857Sobrien /* pr_pid */ 371389857Sobrien elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, note->descdata + 24); 371489857Sobrien 371589857Sobrien /* pr_reg */ 371689857Sobrien offset = 72; 371789857Sobrien raw_size = 192; 371889857Sobrien 371989857Sobrien break; 372089857Sobrien } 372189857Sobrien 372289857Sobrien /* Make a ".reg/999" section. */ 372389857Sobrien return _bfd_elfcore_make_pseudosection (abfd, ".reg", 372489857Sobrien raw_size, note->descpos + offset); 372589857Sobrien} 372689857Sobrien 372789857Sobrienstatic boolean 372889857Sobrienppc_elf_grok_psinfo (abfd, note) 372989857Sobrien bfd *abfd; 373089857Sobrien Elf_Internal_Note *note; 373189857Sobrien{ 373289857Sobrien switch (note->descsz) 373389857Sobrien { 373489857Sobrien default: 373589857Sobrien return false; 373689857Sobrien 373789857Sobrien case 128: /* Linux/PPC elf_prpsinfo */ 373889857Sobrien elf_tdata (abfd)->core_program 373989857Sobrien = _bfd_elfcore_strndup (abfd, note->descdata + 32, 16); 374089857Sobrien elf_tdata (abfd)->core_command 374189857Sobrien = _bfd_elfcore_strndup (abfd, note->descdata + 48, 80); 374289857Sobrien } 374389857Sobrien 374489857Sobrien /* Note that for some reason, a spurious space is tacked 374589857Sobrien onto the end of the args in some (at least one anyway) 374689857Sobrien implementations, so strip it off if it exists. */ 374789857Sobrien 374889857Sobrien { 374989857Sobrien char *command = elf_tdata (abfd)->core_command; 375089857Sobrien int n = strlen (command); 375189857Sobrien 375289857Sobrien if (0 < n && command[n - 1] == ' ') 375389857Sobrien command[n - 1] = '\0'; 375489857Sobrien } 375589857Sobrien 375689857Sobrien return true; 375789857Sobrien} 375889857Sobrien 375960484Sobrien#define TARGET_LITTLE_SYM bfd_elf32_powerpcle_vec 376060484Sobrien#define TARGET_LITTLE_NAME "elf32-powerpcle" 376160484Sobrien#define TARGET_BIG_SYM bfd_elf32_powerpc_vec 376260484Sobrien#define TARGET_BIG_NAME "elf32-powerpc" 376360484Sobrien#define ELF_ARCH bfd_arch_powerpc 376460484Sobrien#define ELF_MACHINE_CODE EM_PPC 376560484Sobrien#define ELF_MAXPAGESIZE 0x10000 376660484Sobrien#define elf_info_to_howto ppc_elf_info_to_howto 376760484Sobrien 376860484Sobrien#ifdef EM_CYGNUS_POWERPC 376960484Sobrien#define ELF_MACHINE_ALT1 EM_CYGNUS_POWERPC 377060484Sobrien#endif 377160484Sobrien 377260484Sobrien#ifdef EM_PPC_OLD 377360484Sobrien#define ELF_MACHINE_ALT2 EM_PPC_OLD 377460484Sobrien#endif 377560484Sobrien 377660484Sobrien#define elf_backend_plt_not_loaded 1 377760484Sobrien#define elf_backend_got_symbol_offset 4 377860484Sobrien#define elf_backend_can_gc_sections 1 377989857Sobrien#define elf_backend_can_refcount 1 378060484Sobrien#define elf_backend_got_header_size 12 378160484Sobrien#define elf_backend_plt_header_size PLT_INITIAL_ENTRY_SIZE 378260484Sobrien 378360484Sobrien#define bfd_elf32_bfd_merge_private_bfd_data ppc_elf_merge_private_bfd_data 378460484Sobrien#define bfd_elf32_bfd_relax_section ppc_elf_relax_section 378560484Sobrien#define bfd_elf32_bfd_reloc_type_lookup ppc_elf_reloc_type_lookup 378660484Sobrien#define bfd_elf32_bfd_set_private_flags ppc_elf_set_private_flags 378760484Sobrien#define bfd_elf32_bfd_final_link _bfd_elf32_gc_common_final_link 378860484Sobrien 378960484Sobrien#define elf_backend_gc_mark_hook ppc_elf_gc_mark_hook 379060484Sobrien#define elf_backend_gc_sweep_hook ppc_elf_gc_sweep_hook 379160484Sobrien#define elf_backend_section_from_shdr ppc_elf_section_from_shdr 379260484Sobrien#define elf_backend_relocate_section ppc_elf_relocate_section 379360484Sobrien#define elf_backend_create_dynamic_sections ppc_elf_create_dynamic_sections 379460484Sobrien#define elf_backend_check_relocs ppc_elf_check_relocs 379560484Sobrien#define elf_backend_adjust_dynamic_symbol ppc_elf_adjust_dynamic_symbol 379660484Sobrien#define elf_backend_add_symbol_hook ppc_elf_add_symbol_hook 379760484Sobrien#define elf_backend_size_dynamic_sections ppc_elf_size_dynamic_sections 379860484Sobrien#define elf_backend_finish_dynamic_symbol ppc_elf_finish_dynamic_symbol 379960484Sobrien#define elf_backend_finish_dynamic_sections ppc_elf_finish_dynamic_sections 380060484Sobrien#define elf_backend_fake_sections ppc_elf_fake_sections 380160484Sobrien#define elf_backend_additional_program_headers ppc_elf_additional_program_headers 380260484Sobrien#define elf_backend_modify_segment_map ppc_elf_modify_segment_map 380389857Sobrien#define elf_backend_grok_prstatus ppc_elf_grok_prstatus 380489857Sobrien#define elf_backend_grok_psinfo ppc_elf_grok_psinfo 380589857Sobrien#define elf_backend_reloc_type_class ppc_elf_reloc_type_class 380660484Sobrien 380760484Sobrien#include "elf32-target.h" 3808