elf64-alpha.c revision 91049
133965Sjdp/* Alpha specific support for 64-bit ELF 289862Sobrien Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002 378833Sobrien Free Software Foundation, Inc. 433965Sjdp Contributed by Richard Henderson <rth@tamu.edu>. 533965Sjdp 633965SjdpThis file is part of BFD, the Binary File Descriptor library. 733965Sjdp 833965SjdpThis program is free software; you can redistribute it and/or modify 933965Sjdpit under the terms of the GNU General Public License as published by 1033965Sjdpthe Free Software Foundation; either version 2 of the License, or 1133965Sjdp(at your option) any later version. 1233965Sjdp 1333965SjdpThis program is distributed in the hope that it will be useful, 1433965Sjdpbut WITHOUT ANY WARRANTY; without even the implied warranty of 1533965SjdpMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1633965SjdpGNU General Public License for more details. 1733965Sjdp 1833965SjdpYou should have received a copy of the GNU General Public License 1933965Sjdpalong with this program; if not, write to the Free Software 2033965SjdpFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 2133965Sjdp 2257406Sjdp/* $FreeBSD: head/contrib/binutils/bfd/elf64-alpha.c 91049 2002-02-22 04:46:20Z obrien $ */ 2357406Sjdp 2433965Sjdp/* We need a published ABI spec for this. Until one comes out, don't 2533965Sjdp assume this'll remain unchanged forever. */ 2633965Sjdp 2733965Sjdp#include "bfd.h" 2833965Sjdp#include "sysdep.h" 2933965Sjdp#include "libbfd.h" 3033965Sjdp#include "elf-bfd.h" 3133965Sjdp 3233965Sjdp#include "elf/alpha.h" 3333965Sjdp 3433965Sjdp#define ALPHAECOFF 3533965Sjdp 3633965Sjdp#define NO_COFF_RELOCS 3733965Sjdp#define NO_COFF_SYMBOLS 3833965Sjdp#define NO_COFF_LINENOS 3933965Sjdp 4077303Sobrien/* Get the ECOFF swapping routines. Needed for the debug information. */ 4133965Sjdp#include "coff/internal.h" 4233965Sjdp#include "coff/sym.h" 4333965Sjdp#include "coff/symconst.h" 4433965Sjdp#include "coff/ecoff.h" 4533965Sjdp#include "coff/alpha.h" 4633965Sjdp#include "aout/ar.h" 4733965Sjdp#include "libcoff.h" 4833965Sjdp#include "libecoff.h" 4933965Sjdp#define ECOFF_64 5033965Sjdp#include "ecoffswap.h" 5133965Sjdp 5277303Sobrienstatic int alpha_elf_dynamic_symbol_p 5377303Sobrien PARAMS((struct elf_link_hash_entry *, struct bfd_link_info *)); 5433965Sjdpstatic struct bfd_hash_entry * elf64_alpha_link_hash_newfunc 5533965Sjdp PARAMS((struct bfd_hash_entry *, struct bfd_hash_table *, const char *)); 5633965Sjdpstatic struct bfd_link_hash_table * elf64_alpha_bfd_link_hash_table_create 5733965Sjdp PARAMS((bfd *)); 5833965Sjdp 5933965Sjdpstatic bfd_reloc_status_type elf64_alpha_reloc_nil 6033965Sjdp PARAMS((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); 6133965Sjdpstatic bfd_reloc_status_type elf64_alpha_reloc_bad 6233965Sjdp PARAMS((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); 6333965Sjdpstatic bfd_reloc_status_type elf64_alpha_do_reloc_gpdisp 6433965Sjdp PARAMS((bfd *, bfd_vma, bfd_byte *, bfd_byte *)); 6533965Sjdpstatic bfd_reloc_status_type elf64_alpha_reloc_gpdisp 6633965Sjdp PARAMS((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); 6733965Sjdp 6833965Sjdpstatic reloc_howto_type * elf64_alpha_bfd_reloc_type_lookup 6933965Sjdp PARAMS((bfd *, bfd_reloc_code_real_type)); 7033965Sjdpstatic void elf64_alpha_info_to_howto 7133965Sjdp PARAMS((bfd *, arelent *, Elf64_Internal_Rela *)); 7233965Sjdp 7377303Sobrienstatic boolean elf64_alpha_mkobject 7477303Sobrien PARAMS((bfd *)); 7533965Sjdpstatic boolean elf64_alpha_object_p 7633965Sjdp PARAMS((bfd *)); 7733965Sjdpstatic boolean elf64_alpha_section_from_shdr 7833965Sjdp PARAMS((bfd *, Elf64_Internal_Shdr *, char *)); 7989862Sobrienstatic boolean elf64_alpha_section_flags 8089862Sobrien PARAMS((flagword *, Elf64_Internal_Shdr *)); 8133965Sjdpstatic boolean elf64_alpha_fake_sections 8233965Sjdp PARAMS((bfd *, Elf64_Internal_Shdr *, asection *)); 8333965Sjdpstatic boolean elf64_alpha_create_got_section 8433965Sjdp PARAMS((bfd *, struct bfd_link_info *)); 8533965Sjdpstatic boolean elf64_alpha_create_dynamic_sections 8633965Sjdp PARAMS((bfd *, struct bfd_link_info *)); 8733965Sjdp 8833965Sjdpstatic boolean elf64_alpha_read_ecoff_info 8933965Sjdp PARAMS((bfd *, asection *, struct ecoff_debug_info *)); 9033965Sjdpstatic boolean elf64_alpha_is_local_label_name 9133965Sjdp PARAMS((bfd *, const char *)); 9233965Sjdpstatic boolean elf64_alpha_find_nearest_line 9333965Sjdp PARAMS((bfd *, asection *, asymbol **, bfd_vma, const char **, 9433965Sjdp const char **, unsigned int *)); 9533965Sjdp 9633965Sjdp#if defined(__STDC__) || defined(ALMOST_STDC) 9733965Sjdpstruct alpha_elf_link_hash_entry; 9833965Sjdp#endif 9933965Sjdp 10033965Sjdpstatic boolean elf64_alpha_output_extsym 10133965Sjdp PARAMS((struct alpha_elf_link_hash_entry *, PTR)); 10233965Sjdp 10333965Sjdpstatic boolean elf64_alpha_can_merge_gots 10433965Sjdp PARAMS((bfd *, bfd *)); 10533965Sjdpstatic void elf64_alpha_merge_gots 10633965Sjdp PARAMS((bfd *, bfd *)); 10733965Sjdpstatic boolean elf64_alpha_calc_got_offsets_for_symbol 10833965Sjdp PARAMS ((struct alpha_elf_link_hash_entry *, PTR)); 10933965Sjdpstatic void elf64_alpha_calc_got_offsets PARAMS ((struct bfd_link_info *)); 11060510Sobrienstatic boolean elf64_alpha_size_got_sections 11160510Sobrien PARAMS ((bfd *, struct bfd_link_info *)); 11233965Sjdpstatic boolean elf64_alpha_always_size_sections 11333965Sjdp PARAMS ((bfd *, struct bfd_link_info *)); 11433965Sjdpstatic boolean elf64_alpha_calc_dynrel_sizes 11533965Sjdp PARAMS ((struct alpha_elf_link_hash_entry *, struct bfd_link_info *)); 11660510Sobrienstatic boolean elf64_alpha_add_symbol_hook 11760510Sobrien PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Sym *, 11860510Sobrien const char **, flagword *, asection **, bfd_vma *)); 11933965Sjdpstatic boolean elf64_alpha_check_relocs 12033965Sjdp PARAMS((bfd *, struct bfd_link_info *, asection *sec, 12133965Sjdp const Elf_Internal_Rela *)); 12233965Sjdpstatic boolean elf64_alpha_adjust_dynamic_symbol 12333965Sjdp PARAMS((struct bfd_link_info *, struct elf_link_hash_entry *)); 12433965Sjdpstatic boolean elf64_alpha_size_dynamic_sections 12533965Sjdp PARAMS((bfd *, struct bfd_link_info *)); 12633965Sjdpstatic boolean elf64_alpha_relocate_section 12733965Sjdp PARAMS((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, 12833965Sjdp Elf_Internal_Rela *, Elf_Internal_Sym *, asection **)); 12933965Sjdpstatic boolean elf64_alpha_finish_dynamic_symbol 13033965Sjdp PARAMS((bfd *, struct bfd_link_info *, struct elf_link_hash_entry *, 13133965Sjdp Elf_Internal_Sym *)); 13233965Sjdpstatic boolean elf64_alpha_finish_dynamic_sections 13333965Sjdp PARAMS((bfd *, struct bfd_link_info *)); 13433965Sjdpstatic boolean elf64_alpha_final_link 13533965Sjdp PARAMS((bfd *, struct bfd_link_info *)); 13648850Sdfrstatic boolean elf64_alpha_merge_ind_symbols 13748850Sdfr PARAMS((struct alpha_elf_link_hash_entry *, PTR)); 13860510Sobrienstatic Elf_Internal_Rela * elf64_alpha_find_reloc_at_ofs 13960510Sobrien PARAMS ((Elf_Internal_Rela *, Elf_Internal_Rela *, bfd_vma, int)); 14089862Sobrienstatic enum elf_reloc_type_class elf64_alpha_reloc_type_class 14189862Sobrien PARAMS ((const Elf_Internal_Rela *)); 14233965Sjdp 14333965Sjdpstruct alpha_elf_link_hash_entry 14433965Sjdp{ 14533965Sjdp struct elf_link_hash_entry root; 14633965Sjdp 14733965Sjdp /* External symbol information. */ 14833965Sjdp EXTR esym; 14933965Sjdp 15033965Sjdp /* Cumulative flags for all the .got entries. */ 15133965Sjdp int flags; 15233965Sjdp 15333965Sjdp /* Contexts (LITUSE) in which a literal was referenced. */ 15433965Sjdp#define ALPHA_ELF_LINK_HASH_LU_ADDR 0x01 15533965Sjdp#define ALPHA_ELF_LINK_HASH_LU_MEM 0x02 15633965Sjdp#define ALPHA_ELF_LINK_HASH_LU_BYTE 0x04 15733965Sjdp#define ALPHA_ELF_LINK_HASH_LU_FUNC 0x08 15833965Sjdp 15933965Sjdp /* Used to implement multiple .got subsections. */ 16033965Sjdp struct alpha_elf_got_entry 16133965Sjdp { 16233965Sjdp struct alpha_elf_got_entry *next; 16333965Sjdp 16433965Sjdp /* which .got subsection? */ 16533965Sjdp bfd *gotobj; 16633965Sjdp 16733965Sjdp /* the addend in effect for this entry. */ 16833965Sjdp bfd_vma addend; 16933965Sjdp 17033965Sjdp /* the .got offset for this entry. */ 17133965Sjdp int got_offset; 17233965Sjdp 17333965Sjdp int flags; 17433965Sjdp 17589862Sobrien /* Additional flags. */ 17633965Sjdp#define ALPHA_ELF_GOT_ENTRY_RELOCS_DONE 0x10 17789862Sobrien#define ALPHA_ELF_GOT_ENTRY_RELOCS_XLATED 0x20 17860510Sobrien 17960510Sobrien int use_count; 18033965Sjdp } *got_entries; 18133965Sjdp 18233965Sjdp /* used to count non-got, non-plt relocations for delayed sizing 18333965Sjdp of relocation sections. */ 18433965Sjdp struct alpha_elf_reloc_entry 18533965Sjdp { 18633965Sjdp struct alpha_elf_reloc_entry *next; 18733965Sjdp 18833965Sjdp /* which .reloc section? */ 18933965Sjdp asection *srel; 19033965Sjdp 19133965Sjdp /* what kind of relocation? */ 19289862Sobrien unsigned int rtype; 19333965Sjdp 19489862Sobrien /* is this against read-only section? */ 19589862Sobrien unsigned int reltext : 1; 19689862Sobrien 19733965Sjdp /* how many did we find? */ 19833965Sjdp unsigned long count; 19933965Sjdp } *reloc_entries; 20033965Sjdp}; 20133965Sjdp 20233965Sjdp/* Alpha ELF linker hash table. */ 20333965Sjdp 20433965Sjdpstruct alpha_elf_link_hash_table 20533965Sjdp{ 20633965Sjdp struct elf_link_hash_table root; 20733965Sjdp 20833965Sjdp /* The head of a list of .got subsections linked through 20933965Sjdp alpha_elf_tdata(abfd)->got_link_next. */ 21033965Sjdp bfd *got_list; 21133965Sjdp}; 21233965Sjdp 21333965Sjdp/* Look up an entry in a Alpha ELF linker hash table. */ 21433965Sjdp 21533965Sjdp#define alpha_elf_link_hash_lookup(table, string, create, copy, follow) \ 21633965Sjdp ((struct alpha_elf_link_hash_entry *) \ 21733965Sjdp elf_link_hash_lookup (&(table)->root, (string), (create), \ 21833965Sjdp (copy), (follow))) 21933965Sjdp 22033965Sjdp/* Traverse a Alpha ELF linker hash table. */ 22133965Sjdp 22233965Sjdp#define alpha_elf_link_hash_traverse(table, func, info) \ 22333965Sjdp (elf_link_hash_traverse \ 22433965Sjdp (&(table)->root, \ 22533965Sjdp (boolean (*) PARAMS ((struct elf_link_hash_entry *, PTR))) (func), \ 22633965Sjdp (info))) 22733965Sjdp 22833965Sjdp/* Get the Alpha ELF linker hash table from a link_info structure. */ 22933965Sjdp 23033965Sjdp#define alpha_elf_hash_table(p) \ 23133965Sjdp ((struct alpha_elf_link_hash_table *) ((p)->hash)) 23233965Sjdp 23333965Sjdp/* Get the object's symbols as our own entry type. */ 23433965Sjdp 23533965Sjdp#define alpha_elf_sym_hashes(abfd) \ 23633965Sjdp ((struct alpha_elf_link_hash_entry **)elf_sym_hashes(abfd)) 23733965Sjdp 23833965Sjdp/* Should we do dynamic things to this symbol? */ 23933965Sjdp 24077303Sobrienstatic int 24177303Sobrienalpha_elf_dynamic_symbol_p (h, info) 24277303Sobrien struct elf_link_hash_entry *h; 24377303Sobrien struct bfd_link_info *info; 24477303Sobrien{ 24577303Sobrien if (h == NULL) 24677303Sobrien return false; 24733965Sjdp 24877303Sobrien while (h->root.type == bfd_link_hash_indirect 24977303Sobrien || h->root.type == bfd_link_hash_warning) 25077303Sobrien h = (struct elf_link_hash_entry *) h->root.u.i.link; 25177303Sobrien 25277303Sobrien if (h->dynindx == -1) 25377303Sobrien return false; 25477303Sobrien 25577303Sobrien if (h->root.type == bfd_link_hash_undefweak 25677303Sobrien || h->root.type == bfd_link_hash_defweak) 25777303Sobrien return true; 25877303Sobrien 25978833Sobrien switch (ELF_ST_VISIBILITY (h->other)) 26078833Sobrien { 26178833Sobrien case STV_DEFAULT: 26278833Sobrien break; 26378833Sobrien case STV_HIDDEN: 26478833Sobrien case STV_INTERNAL: 26578833Sobrien return false; 26678833Sobrien case STV_PROTECTED: 26778833Sobrien if (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) 26878833Sobrien return false; 26978833Sobrien break; 27078833Sobrien } 27178833Sobrien 27277303Sobrien if ((info->shared && !info->symbolic) 27377303Sobrien || ((h->elf_link_hash_flags 27477303Sobrien & (ELF_LINK_HASH_DEF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR)) 27577303Sobrien == (ELF_LINK_HASH_DEF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR))) 27677303Sobrien return true; 27777303Sobrien 27877303Sobrien return false; 27977303Sobrien} 28077303Sobrien 28133965Sjdp/* Create an entry in a Alpha ELF linker hash table. */ 28233965Sjdp 28333965Sjdpstatic struct bfd_hash_entry * 28433965Sjdpelf64_alpha_link_hash_newfunc (entry, table, string) 28533965Sjdp struct bfd_hash_entry *entry; 28633965Sjdp struct bfd_hash_table *table; 28733965Sjdp const char *string; 28833965Sjdp{ 28933965Sjdp struct alpha_elf_link_hash_entry *ret = 29033965Sjdp (struct alpha_elf_link_hash_entry *) entry; 29133965Sjdp 29233965Sjdp /* Allocate the structure if it has not already been allocated by a 29333965Sjdp subclass. */ 29433965Sjdp if (ret == (struct alpha_elf_link_hash_entry *) NULL) 29533965Sjdp ret = ((struct alpha_elf_link_hash_entry *) 29633965Sjdp bfd_hash_allocate (table, 29733965Sjdp sizeof (struct alpha_elf_link_hash_entry))); 29833965Sjdp if (ret == (struct alpha_elf_link_hash_entry *) NULL) 29933965Sjdp return (struct bfd_hash_entry *) ret; 30033965Sjdp 30133965Sjdp /* Call the allocation method of the superclass. */ 30233965Sjdp ret = ((struct alpha_elf_link_hash_entry *) 30333965Sjdp _bfd_elf_link_hash_newfunc ((struct bfd_hash_entry *) ret, 30433965Sjdp table, string)); 30533965Sjdp if (ret != (struct alpha_elf_link_hash_entry *) NULL) 30633965Sjdp { 30733965Sjdp /* Set local fields. */ 30833965Sjdp memset (&ret->esym, 0, sizeof (EXTR)); 30933965Sjdp /* We use -2 as a marker to indicate that the information has 31033965Sjdp not been set. -1 means there is no associated ifd. */ 31133965Sjdp ret->esym.ifd = -2; 31233965Sjdp ret->flags = 0; 31333965Sjdp ret->got_entries = NULL; 31433965Sjdp ret->reloc_entries = NULL; 31533965Sjdp } 31633965Sjdp 31733965Sjdp return (struct bfd_hash_entry *) ret; 31833965Sjdp} 31933965Sjdp 32033965Sjdp/* Create a Alpha ELF linker hash table. */ 32133965Sjdp 32233965Sjdpstatic struct bfd_link_hash_table * 32333965Sjdpelf64_alpha_bfd_link_hash_table_create (abfd) 32433965Sjdp bfd *abfd; 32533965Sjdp{ 32633965Sjdp struct alpha_elf_link_hash_table *ret; 32789862Sobrien bfd_size_type amt = sizeof (struct alpha_elf_link_hash_table); 32833965Sjdp 32989862Sobrien ret = (struct alpha_elf_link_hash_table *) bfd_zalloc (abfd, amt); 33033965Sjdp if (ret == (struct alpha_elf_link_hash_table *) NULL) 33133965Sjdp return NULL; 33233965Sjdp 33333965Sjdp if (! _bfd_elf_link_hash_table_init (&ret->root, abfd, 33433965Sjdp elf64_alpha_link_hash_newfunc)) 33533965Sjdp { 33633965Sjdp bfd_release (abfd, ret); 33733965Sjdp return NULL; 33833965Sjdp } 33933965Sjdp 34033965Sjdp return &ret->root.root; 34133965Sjdp} 34233965Sjdp 34333965Sjdp/* We have some private fields hanging off of the elf_tdata structure. */ 34433965Sjdp 34533965Sjdpstruct alpha_elf_obj_tdata 34633965Sjdp{ 34733965Sjdp struct elf_obj_tdata root; 34833965Sjdp 34933965Sjdp /* For every input file, these are the got entries for that object's 35033965Sjdp local symbols. */ 35133965Sjdp struct alpha_elf_got_entry ** local_got_entries; 35233965Sjdp 35333965Sjdp /* For every input file, this is the object that owns the got that 35433965Sjdp this input file uses. */ 35533965Sjdp bfd *gotobj; 35633965Sjdp 35733965Sjdp /* For every got, this is a linked list through the objects using this got */ 35833965Sjdp bfd *in_got_link_next; 35933965Sjdp 36033965Sjdp /* For every got, this is a link to the next got subsegment. */ 36133965Sjdp bfd *got_link_next; 36233965Sjdp 36333965Sjdp /* For every got, this is the section. */ 36433965Sjdp asection *got; 36533965Sjdp 36633965Sjdp /* For every got, this is it's total number of *entries*. */ 36733965Sjdp int total_got_entries; 36833965Sjdp 36933965Sjdp /* For every got, this is the sum of the number of *entries* required 37033965Sjdp to hold all of the member object's local got. */ 37133965Sjdp int n_local_got_entries; 37233965Sjdp}; 37333965Sjdp 37433965Sjdp#define alpha_elf_tdata(abfd) \ 37533965Sjdp ((struct alpha_elf_obj_tdata *) (abfd)->tdata.any) 37633965Sjdp 37733965Sjdpstatic boolean 37833965Sjdpelf64_alpha_mkobject (abfd) 37933965Sjdp bfd *abfd; 38033965Sjdp{ 38189862Sobrien bfd_size_type amt = sizeof (struct alpha_elf_obj_tdata); 38289862Sobrien abfd->tdata.any = bfd_zalloc (abfd, amt); 38333965Sjdp if (abfd->tdata.any == NULL) 38433965Sjdp return false; 38533965Sjdp return true; 38633965Sjdp} 38733965Sjdp 38833965Sjdpstatic boolean 38933965Sjdpelf64_alpha_object_p (abfd) 39033965Sjdp bfd *abfd; 39133965Sjdp{ 39233965Sjdp /* Allocate our special target data. */ 39333965Sjdp struct alpha_elf_obj_tdata *new_tdata; 39489862Sobrien bfd_size_type amt = sizeof (struct alpha_elf_obj_tdata); 39589862Sobrien new_tdata = bfd_zalloc (abfd, amt); 39633965Sjdp if (new_tdata == NULL) 39733965Sjdp return false; 39833965Sjdp new_tdata->root = *abfd->tdata.elf_obj_data; 39933965Sjdp abfd->tdata.any = new_tdata; 40033965Sjdp 40133965Sjdp /* Set the right machine number for an Alpha ELF file. */ 40233965Sjdp return bfd_default_set_arch_mach (abfd, bfd_arch_alpha, 0); 40333965Sjdp} 40433965Sjdp 40533965Sjdp/* In case we're on a 32-bit machine, construct a 64-bit "-1" value 40633965Sjdp from smaller values. Start with zero, widen, *then* decrement. */ 40733965Sjdp#define MINUS_ONE (((bfd_vma)0) - 1) 40833965Sjdp 40989862Sobrien#define SKIP_HOWTO(N) \ 41089862Sobrien HOWTO(N, 0, 0, 0, 0, 0, 0, elf64_alpha_reloc_bad, 0, 0, 0, 0, 0) 41189862Sobrien 41233965Sjdpstatic reloc_howto_type elf64_alpha_howto_table[] = 41333965Sjdp{ 41433965Sjdp HOWTO (R_ALPHA_NONE, /* type */ 41533965Sjdp 0, /* rightshift */ 41633965Sjdp 0, /* size (0 = byte, 1 = short, 2 = long) */ 41733965Sjdp 8, /* bitsize */ 41833965Sjdp true, /* pc_relative */ 41933965Sjdp 0, /* bitpos */ 42033965Sjdp complain_overflow_dont, /* complain_on_overflow */ 42133965Sjdp elf64_alpha_reloc_nil, /* special_function */ 42233965Sjdp "NONE", /* name */ 42333965Sjdp false, /* partial_inplace */ 42433965Sjdp 0, /* src_mask */ 42533965Sjdp 0, /* dst_mask */ 42633965Sjdp true), /* pcrel_offset */ 42733965Sjdp 42833965Sjdp /* A 32 bit reference to a symbol. */ 42933965Sjdp HOWTO (R_ALPHA_REFLONG, /* type */ 43033965Sjdp 0, /* rightshift */ 43133965Sjdp 2, /* size (0 = byte, 1 = short, 2 = long) */ 43233965Sjdp 32, /* bitsize */ 43333965Sjdp false, /* pc_relative */ 43433965Sjdp 0, /* bitpos */ 43533965Sjdp complain_overflow_bitfield, /* complain_on_overflow */ 43633965Sjdp 0, /* special_function */ 43733965Sjdp "REFLONG", /* name */ 43833965Sjdp false, /* partial_inplace */ 43933965Sjdp 0xffffffff, /* src_mask */ 44033965Sjdp 0xffffffff, /* dst_mask */ 44133965Sjdp false), /* pcrel_offset */ 44233965Sjdp 44333965Sjdp /* A 64 bit reference to a symbol. */ 44433965Sjdp HOWTO (R_ALPHA_REFQUAD, /* type */ 44533965Sjdp 0, /* rightshift */ 44633965Sjdp 4, /* size (0 = byte, 1 = short, 2 = long) */ 44733965Sjdp 64, /* bitsize */ 44833965Sjdp false, /* pc_relative */ 44933965Sjdp 0, /* bitpos */ 45033965Sjdp complain_overflow_bitfield, /* complain_on_overflow */ 45133965Sjdp 0, /* special_function */ 45233965Sjdp "REFQUAD", /* name */ 45333965Sjdp false, /* partial_inplace */ 45433965Sjdp MINUS_ONE, /* src_mask */ 45533965Sjdp MINUS_ONE, /* dst_mask */ 45633965Sjdp false), /* pcrel_offset */ 45733965Sjdp 45833965Sjdp /* A 32 bit GP relative offset. This is just like REFLONG except 45933965Sjdp that when the value is used the value of the gp register will be 46033965Sjdp added in. */ 46133965Sjdp HOWTO (R_ALPHA_GPREL32, /* type */ 46233965Sjdp 0, /* rightshift */ 46333965Sjdp 2, /* size (0 = byte, 1 = short, 2 = long) */ 46433965Sjdp 32, /* bitsize */ 46533965Sjdp false, /* pc_relative */ 46633965Sjdp 0, /* bitpos */ 46733965Sjdp complain_overflow_bitfield, /* complain_on_overflow */ 46833965Sjdp 0, /* special_function */ 46933965Sjdp "GPREL32", /* name */ 47033965Sjdp false, /* partial_inplace */ 47133965Sjdp 0xffffffff, /* src_mask */ 47233965Sjdp 0xffffffff, /* dst_mask */ 47333965Sjdp false), /* pcrel_offset */ 47433965Sjdp 47533965Sjdp /* Used for an instruction that refers to memory off the GP register. */ 47633965Sjdp HOWTO (R_ALPHA_LITERAL, /* type */ 47733965Sjdp 0, /* rightshift */ 47889862Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 47933965Sjdp 16, /* bitsize */ 48033965Sjdp false, /* pc_relative */ 48133965Sjdp 0, /* bitpos */ 48233965Sjdp complain_overflow_signed, /* complain_on_overflow */ 48333965Sjdp 0, /* special_function */ 48433965Sjdp "ELF_LITERAL", /* name */ 48533965Sjdp false, /* partial_inplace */ 48633965Sjdp 0xffff, /* src_mask */ 48733965Sjdp 0xffff, /* dst_mask */ 48833965Sjdp false), /* pcrel_offset */ 48933965Sjdp 49033965Sjdp /* This reloc only appears immediately following an ELF_LITERAL reloc. 49133965Sjdp It identifies a use of the literal. The symbol index is special: 49233965Sjdp 1 means the literal address is in the base register of a memory 49333965Sjdp format instruction; 2 means the literal address is in the byte 49433965Sjdp offset register of a byte-manipulation instruction; 3 means the 49533965Sjdp literal address is in the target register of a jsr instruction. 49633965Sjdp This does not actually do any relocation. */ 49733965Sjdp HOWTO (R_ALPHA_LITUSE, /* type */ 49833965Sjdp 0, /* rightshift */ 49989862Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 50033965Sjdp 32, /* bitsize */ 50133965Sjdp false, /* pc_relative */ 50233965Sjdp 0, /* bitpos */ 50333965Sjdp complain_overflow_dont, /* complain_on_overflow */ 50433965Sjdp elf64_alpha_reloc_nil, /* special_function */ 50533965Sjdp "LITUSE", /* name */ 50633965Sjdp false, /* partial_inplace */ 50733965Sjdp 0, /* src_mask */ 50833965Sjdp 0, /* dst_mask */ 50933965Sjdp false), /* pcrel_offset */ 51033965Sjdp 51133965Sjdp /* Load the gp register. This is always used for a ldah instruction 51233965Sjdp which loads the upper 16 bits of the gp register. The symbol 51333965Sjdp index of the GPDISP instruction is an offset in bytes to the lda 51433965Sjdp instruction that loads the lower 16 bits. The value to use for 51533965Sjdp the relocation is the difference between the GP value and the 51633965Sjdp current location; the load will always be done against a register 51733965Sjdp holding the current address. 51833965Sjdp 51933965Sjdp NOTE: Unlike ECOFF, partial in-place relocation is not done. If 52033965Sjdp any offset is present in the instructions, it is an offset from 52133965Sjdp the register to the ldah instruction. This lets us avoid any 52233965Sjdp stupid hackery like inventing a gp value to do partial relocation 52333965Sjdp against. Also unlike ECOFF, we do the whole relocation off of 52433965Sjdp the GPDISP rather than a GPDISP_HI16/GPDISP_LO16 pair. An odd, 52533965Sjdp space consuming bit, that, since all the information was present 52633965Sjdp in the GPDISP_HI16 reloc. */ 52733965Sjdp HOWTO (R_ALPHA_GPDISP, /* type */ 52833965Sjdp 16, /* rightshift */ 52933965Sjdp 2, /* size (0 = byte, 1 = short, 2 = long) */ 53033965Sjdp 16, /* bitsize */ 53133965Sjdp false, /* pc_relative */ 53233965Sjdp 0, /* bitpos */ 53333965Sjdp complain_overflow_dont, /* complain_on_overflow */ 53433965Sjdp elf64_alpha_reloc_gpdisp, /* special_function */ 53533965Sjdp "GPDISP", /* name */ 53633965Sjdp false, /* partial_inplace */ 53733965Sjdp 0xffff, /* src_mask */ 53833965Sjdp 0xffff, /* dst_mask */ 53933965Sjdp true), /* pcrel_offset */ 54033965Sjdp 54133965Sjdp /* A 21 bit branch. */ 54233965Sjdp HOWTO (R_ALPHA_BRADDR, /* type */ 54333965Sjdp 2, /* rightshift */ 54433965Sjdp 2, /* size (0 = byte, 1 = short, 2 = long) */ 54533965Sjdp 21, /* bitsize */ 54633965Sjdp true, /* pc_relative */ 54733965Sjdp 0, /* bitpos */ 54833965Sjdp complain_overflow_signed, /* complain_on_overflow */ 54933965Sjdp 0, /* special_function */ 55033965Sjdp "BRADDR", /* name */ 55133965Sjdp false, /* partial_inplace */ 55233965Sjdp 0x1fffff, /* src_mask */ 55333965Sjdp 0x1fffff, /* dst_mask */ 55433965Sjdp true), /* pcrel_offset */ 55533965Sjdp 55633965Sjdp /* A hint for a jump to a register. */ 55733965Sjdp HOWTO (R_ALPHA_HINT, /* type */ 55833965Sjdp 2, /* rightshift */ 55989862Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 56033965Sjdp 14, /* bitsize */ 56133965Sjdp true, /* pc_relative */ 56233965Sjdp 0, /* bitpos */ 56333965Sjdp complain_overflow_dont, /* complain_on_overflow */ 56433965Sjdp 0, /* special_function */ 56533965Sjdp "HINT", /* name */ 56633965Sjdp false, /* partial_inplace */ 56733965Sjdp 0x3fff, /* src_mask */ 56833965Sjdp 0x3fff, /* dst_mask */ 56933965Sjdp true), /* pcrel_offset */ 57033965Sjdp 57133965Sjdp /* 16 bit PC relative offset. */ 57233965Sjdp HOWTO (R_ALPHA_SREL16, /* type */ 57333965Sjdp 0, /* rightshift */ 57433965Sjdp 1, /* size (0 = byte, 1 = short, 2 = long) */ 57533965Sjdp 16, /* bitsize */ 57633965Sjdp true, /* pc_relative */ 57733965Sjdp 0, /* bitpos */ 57833965Sjdp complain_overflow_signed, /* complain_on_overflow */ 57933965Sjdp 0, /* special_function */ 58033965Sjdp "SREL16", /* name */ 58133965Sjdp false, /* partial_inplace */ 58233965Sjdp 0xffff, /* src_mask */ 58333965Sjdp 0xffff, /* dst_mask */ 58478833Sobrien true), /* pcrel_offset */ 58533965Sjdp 58633965Sjdp /* 32 bit PC relative offset. */ 58733965Sjdp HOWTO (R_ALPHA_SREL32, /* type */ 58833965Sjdp 0, /* rightshift */ 58933965Sjdp 2, /* size (0 = byte, 1 = short, 2 = long) */ 59033965Sjdp 32, /* bitsize */ 59133965Sjdp true, /* pc_relative */ 59233965Sjdp 0, /* bitpos */ 59333965Sjdp complain_overflow_signed, /* complain_on_overflow */ 59433965Sjdp 0, /* special_function */ 59533965Sjdp "SREL32", /* name */ 59633965Sjdp false, /* partial_inplace */ 59733965Sjdp 0xffffffff, /* src_mask */ 59833965Sjdp 0xffffffff, /* dst_mask */ 59978833Sobrien true), /* pcrel_offset */ 60033965Sjdp 60133965Sjdp /* A 64 bit PC relative offset. */ 60233965Sjdp HOWTO (R_ALPHA_SREL64, /* type */ 60333965Sjdp 0, /* rightshift */ 60433965Sjdp 4, /* size (0 = byte, 1 = short, 2 = long) */ 60533965Sjdp 64, /* bitsize */ 60633965Sjdp true, /* pc_relative */ 60733965Sjdp 0, /* bitpos */ 60833965Sjdp complain_overflow_signed, /* complain_on_overflow */ 60933965Sjdp 0, /* special_function */ 61033965Sjdp "SREL64", /* name */ 61133965Sjdp false, /* partial_inplace */ 61233965Sjdp MINUS_ONE, /* src_mask */ 61333965Sjdp MINUS_ONE, /* dst_mask */ 61478833Sobrien true), /* pcrel_offset */ 61533965Sjdp 61689862Sobrien /* Skip 12 - 16; deprecated ECOFF relocs. */ 61789862Sobrien SKIP_HOWTO (12), 61889862Sobrien SKIP_HOWTO (13), 61989862Sobrien SKIP_HOWTO (14), 62089862Sobrien SKIP_HOWTO (15), 62189862Sobrien SKIP_HOWTO (16), 62233965Sjdp 62338889Sjdp /* The high 16 bits of the displacement from GP to the target. */ 62438889Sjdp HOWTO (R_ALPHA_GPRELHIGH, 62538889Sjdp 0, /* rightshift */ 62689862Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 62760510Sobrien 16, /* bitsize */ 62838889Sjdp false, /* pc_relative */ 62938889Sjdp 0, /* bitpos */ 63060510Sobrien complain_overflow_signed, /* complain_on_overflow */ 63189862Sobrien 0, /* special_function */ 63238889Sjdp "GPRELHIGH", /* name */ 63338889Sjdp false, /* partial_inplace */ 63460510Sobrien 0xffff, /* src_mask */ 63560510Sobrien 0xffff, /* dst_mask */ 63638889Sjdp false), /* pcrel_offset */ 63738889Sjdp 63838889Sjdp /* The low 16 bits of the displacement from GP to the target. */ 63938889Sjdp HOWTO (R_ALPHA_GPRELLOW, 64038889Sjdp 0, /* rightshift */ 64189862Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 64260510Sobrien 16, /* bitsize */ 64338889Sjdp false, /* pc_relative */ 64438889Sjdp 0, /* bitpos */ 64538889Sjdp complain_overflow_dont, /* complain_on_overflow */ 64689862Sobrien 0, /* special_function */ 64738889Sjdp "GPRELLOW", /* name */ 64838889Sjdp false, /* partial_inplace */ 64960510Sobrien 0xffff, /* src_mask */ 65060510Sobrien 0xffff, /* dst_mask */ 65138889Sjdp false), /* pcrel_offset */ 65238889Sjdp 65338889Sjdp /* A 16-bit displacement from the GP to the target. */ 65489862Sobrien HOWTO (R_ALPHA_GPREL16, 65538889Sjdp 0, /* rightshift */ 65689862Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 65760510Sobrien 16, /* bitsize */ 65838889Sjdp false, /* pc_relative */ 65938889Sjdp 0, /* bitpos */ 66060510Sobrien complain_overflow_signed, /* complain_on_overflow */ 66160510Sobrien 0, /* special_function */ 66289862Sobrien "GPREL16", /* name */ 66338889Sjdp false, /* partial_inplace */ 66460510Sobrien 0xffff, /* src_mask */ 66560510Sobrien 0xffff, /* dst_mask */ 66638889Sjdp false), /* pcrel_offset */ 66738889Sjdp 66889862Sobrien /* Skip 20 - 23; deprecated ECOFF relocs. */ 66989862Sobrien SKIP_HOWTO (20), 67089862Sobrien SKIP_HOWTO (21), 67189862Sobrien SKIP_HOWTO (22), 67289862Sobrien SKIP_HOWTO (23), 67338889Sjdp 67477303Sobrien /* Misc ELF relocations. */ 67538889Sjdp 67638889Sjdp /* A dynamic relocation to copy the target into our .dynbss section. */ 67738889Sjdp /* Not generated, as all Alpha objects use PIC, so it is not needed. It 67838889Sjdp is present because every other ELF has one, but should not be used 67938889Sjdp because .dynbss is an ugly thing. */ 68033965Sjdp HOWTO (R_ALPHA_COPY, 68133965Sjdp 0, 68233965Sjdp 0, 68333965Sjdp 0, 68433965Sjdp false, 68533965Sjdp 0, 68633965Sjdp complain_overflow_dont, 68733965Sjdp bfd_elf_generic_reloc, 68833965Sjdp "COPY", 68933965Sjdp false, 69033965Sjdp 0, 69133965Sjdp 0, 69233965Sjdp true), 69333965Sjdp 69438889Sjdp /* A dynamic relocation for a .got entry. */ 69533965Sjdp HOWTO (R_ALPHA_GLOB_DAT, 69633965Sjdp 0, 69733965Sjdp 0, 69833965Sjdp 0, 69933965Sjdp false, 70033965Sjdp 0, 70133965Sjdp complain_overflow_dont, 70233965Sjdp bfd_elf_generic_reloc, 70333965Sjdp "GLOB_DAT", 70433965Sjdp false, 70533965Sjdp 0, 70633965Sjdp 0, 70733965Sjdp true), 70833965Sjdp 70938889Sjdp /* A dynamic relocation for a .plt entry. */ 71033965Sjdp HOWTO (R_ALPHA_JMP_SLOT, 71133965Sjdp 0, 71233965Sjdp 0, 71333965Sjdp 0, 71433965Sjdp false, 71533965Sjdp 0, 71633965Sjdp complain_overflow_dont, 71733965Sjdp bfd_elf_generic_reloc, 71833965Sjdp "JMP_SLOT", 71933965Sjdp false, 72033965Sjdp 0, 72133965Sjdp 0, 72233965Sjdp true), 72333965Sjdp 72438889Sjdp /* A dynamic relocation to add the base of the DSO to a 64-bit field. */ 72533965Sjdp HOWTO (R_ALPHA_RELATIVE, 72633965Sjdp 0, 72733965Sjdp 0, 72833965Sjdp 0, 72933965Sjdp false, 73033965Sjdp 0, 73133965Sjdp complain_overflow_dont, 73233965Sjdp bfd_elf_generic_reloc, 73333965Sjdp "RELATIVE", 73433965Sjdp false, 73533965Sjdp 0, 73633965Sjdp 0, 73791049Sobrien true), 73891049Sobrien 73991049Sobrien /* A 21 bit branch that adjusts for gp loads. */ 74091049Sobrien HOWTO (R_ALPHA_BRSGP, /* type */ 74191049Sobrien 2, /* rightshift */ 74291049Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 74391049Sobrien 21, /* bitsize */ 74491049Sobrien true, /* pc_relative */ 74591049Sobrien 0, /* bitpos */ 74691049Sobrien complain_overflow_signed, /* complain_on_overflow */ 74791049Sobrien 0, /* special_function */ 74891049Sobrien "BRSGP", /* name */ 74991049Sobrien false, /* partial_inplace */ 75091049Sobrien 0x1fffff, /* src_mask */ 75191049Sobrien 0x1fffff, /* dst_mask */ 75291049Sobrien true), /* pcrel_offset */ 75333965Sjdp}; 75433965Sjdp 75533965Sjdp/* A relocation function which doesn't do anything. */ 75633965Sjdp 75733965Sjdpstatic bfd_reloc_status_type 75833965Sjdpelf64_alpha_reloc_nil (abfd, reloc, sym, data, sec, output_bfd, error_message) 75978833Sobrien bfd *abfd ATTRIBUTE_UNUSED; 76033965Sjdp arelent *reloc; 76178833Sobrien asymbol *sym ATTRIBUTE_UNUSED; 76278833Sobrien PTR data ATTRIBUTE_UNUSED; 76333965Sjdp asection *sec; 76433965Sjdp bfd *output_bfd; 76578833Sobrien char **error_message ATTRIBUTE_UNUSED; 76633965Sjdp{ 76733965Sjdp if (output_bfd) 76833965Sjdp reloc->address += sec->output_offset; 76933965Sjdp return bfd_reloc_ok; 77033965Sjdp} 77133965Sjdp 77233965Sjdp/* A relocation function used for an unsupported reloc. */ 77333965Sjdp 77433965Sjdpstatic bfd_reloc_status_type 77533965Sjdpelf64_alpha_reloc_bad (abfd, reloc, sym, data, sec, output_bfd, error_message) 77678833Sobrien bfd *abfd ATTRIBUTE_UNUSED; 77733965Sjdp arelent *reloc; 77878833Sobrien asymbol *sym ATTRIBUTE_UNUSED; 77978833Sobrien PTR data ATTRIBUTE_UNUSED; 78033965Sjdp asection *sec; 78133965Sjdp bfd *output_bfd; 78278833Sobrien char **error_message ATTRIBUTE_UNUSED; 78333965Sjdp{ 78433965Sjdp if (output_bfd) 78533965Sjdp reloc->address += sec->output_offset; 78633965Sjdp return bfd_reloc_notsupported; 78733965Sjdp} 78833965Sjdp 78933965Sjdp/* Do the work of the GPDISP relocation. */ 79033965Sjdp 79133965Sjdpstatic bfd_reloc_status_type 79233965Sjdpelf64_alpha_do_reloc_gpdisp (abfd, gpdisp, p_ldah, p_lda) 79333965Sjdp bfd *abfd; 79433965Sjdp bfd_vma gpdisp; 79533965Sjdp bfd_byte *p_ldah; 79633965Sjdp bfd_byte *p_lda; 79733965Sjdp{ 79833965Sjdp bfd_reloc_status_type ret = bfd_reloc_ok; 79933965Sjdp bfd_vma addend; 80033965Sjdp unsigned long i_ldah, i_lda; 80133965Sjdp 80233965Sjdp i_ldah = bfd_get_32 (abfd, p_ldah); 80333965Sjdp i_lda = bfd_get_32 (abfd, p_lda); 80433965Sjdp 80533965Sjdp /* Complain if the instructions are not correct. */ 80633965Sjdp if (((i_ldah >> 26) & 0x3f) != 0x09 80733965Sjdp || ((i_lda >> 26) & 0x3f) != 0x08) 80833965Sjdp ret = bfd_reloc_dangerous; 80933965Sjdp 81033965Sjdp /* Extract the user-supplied offset, mirroring the sign extensions 81133965Sjdp that the instructions perform. */ 81233965Sjdp addend = ((i_ldah & 0xffff) << 16) | (i_lda & 0xffff); 81333965Sjdp addend = (addend ^ 0x80008000) - 0x80008000; 81433965Sjdp 81533965Sjdp gpdisp += addend; 81633965Sjdp 81748850Sdfr if ((bfd_signed_vma) gpdisp < -(bfd_signed_vma) 0x80000000 81848850Sdfr || (bfd_signed_vma) gpdisp >= (bfd_signed_vma) 0x7fff8000) 81933965Sjdp ret = bfd_reloc_overflow; 82033965Sjdp 82133965Sjdp /* compensate for the sign extension again. */ 82233965Sjdp i_ldah = ((i_ldah & 0xffff0000) 82333965Sjdp | (((gpdisp >> 16) + ((gpdisp >> 15) & 1)) & 0xffff)); 82433965Sjdp i_lda = (i_lda & 0xffff0000) | (gpdisp & 0xffff); 82533965Sjdp 82689862Sobrien bfd_put_32 (abfd, (bfd_vma) i_ldah, p_ldah); 82789862Sobrien bfd_put_32 (abfd, (bfd_vma) i_lda, p_lda); 82833965Sjdp 82933965Sjdp return ret; 83033965Sjdp} 83133965Sjdp 83233965Sjdp/* The special function for the GPDISP reloc. */ 83333965Sjdp 83433965Sjdpstatic bfd_reloc_status_type 83533965Sjdpelf64_alpha_reloc_gpdisp (abfd, reloc_entry, sym, data, input_section, 83633965Sjdp output_bfd, err_msg) 83733965Sjdp bfd *abfd; 83833965Sjdp arelent *reloc_entry; 83978833Sobrien asymbol *sym ATTRIBUTE_UNUSED; 84033965Sjdp PTR data; 84133965Sjdp asection *input_section; 84233965Sjdp bfd *output_bfd; 84333965Sjdp char **err_msg; 84433965Sjdp{ 84533965Sjdp bfd_reloc_status_type ret; 84633965Sjdp bfd_vma gp, relocation; 84733965Sjdp bfd_byte *p_ldah, *p_lda; 84833965Sjdp 84933965Sjdp /* Don't do anything if we're not doing a final link. */ 85033965Sjdp if (output_bfd) 85133965Sjdp { 85233965Sjdp reloc_entry->address += input_section->output_offset; 85333965Sjdp return bfd_reloc_ok; 85433965Sjdp } 85533965Sjdp 85633965Sjdp if (reloc_entry->address > input_section->_cooked_size || 85733965Sjdp reloc_entry->address + reloc_entry->addend > input_section->_cooked_size) 85833965Sjdp return bfd_reloc_outofrange; 85933965Sjdp 86033965Sjdp /* The gp used in the portion of the output object to which this 86133965Sjdp input object belongs is cached on the input bfd. */ 86233965Sjdp gp = _bfd_get_gp_value (abfd); 86333965Sjdp 86433965Sjdp relocation = (input_section->output_section->vma 86533965Sjdp + input_section->output_offset 86633965Sjdp + reloc_entry->address); 86733965Sjdp 86833965Sjdp p_ldah = (bfd_byte *) data + reloc_entry->address; 86933965Sjdp p_lda = p_ldah + reloc_entry->addend; 87033965Sjdp 87133965Sjdp ret = elf64_alpha_do_reloc_gpdisp (abfd, gp - relocation, p_ldah, p_lda); 87233965Sjdp 87333965Sjdp /* Complain if the instructions are not correct. */ 87433965Sjdp if (ret == bfd_reloc_dangerous) 87560510Sobrien *err_msg = _("GPDISP relocation did not find ldah and lda instructions"); 87633965Sjdp 87733965Sjdp return ret; 87833965Sjdp} 87933965Sjdp 88033965Sjdp/* A mapping from BFD reloc types to Alpha ELF reloc types. */ 88133965Sjdp 88233965Sjdpstruct elf_reloc_map 88333965Sjdp{ 88433965Sjdp bfd_reloc_code_real_type bfd_reloc_val; 88533965Sjdp int elf_reloc_val; 88633965Sjdp}; 88733965Sjdp 88833965Sjdpstatic const struct elf_reloc_map elf64_alpha_reloc_map[] = 88933965Sjdp{ 89089862Sobrien {BFD_RELOC_NONE, R_ALPHA_NONE}, 89189862Sobrien {BFD_RELOC_32, R_ALPHA_REFLONG}, 89289862Sobrien {BFD_RELOC_64, R_ALPHA_REFQUAD}, 89389862Sobrien {BFD_RELOC_CTOR, R_ALPHA_REFQUAD}, 89489862Sobrien {BFD_RELOC_GPREL32, R_ALPHA_GPREL32}, 89589862Sobrien {BFD_RELOC_ALPHA_ELF_LITERAL, R_ALPHA_LITERAL}, 89689862Sobrien {BFD_RELOC_ALPHA_LITUSE, R_ALPHA_LITUSE}, 89789862Sobrien {BFD_RELOC_ALPHA_GPDISP, R_ALPHA_GPDISP}, 89889862Sobrien {BFD_RELOC_23_PCREL_S2, R_ALPHA_BRADDR}, 89989862Sobrien {BFD_RELOC_ALPHA_HINT, R_ALPHA_HINT}, 90089862Sobrien {BFD_RELOC_16_PCREL, R_ALPHA_SREL16}, 90189862Sobrien {BFD_RELOC_32_PCREL, R_ALPHA_SREL32}, 90289862Sobrien {BFD_RELOC_64_PCREL, R_ALPHA_SREL64}, 90389862Sobrien {BFD_RELOC_ALPHA_GPREL_HI16, R_ALPHA_GPRELHIGH}, 90489862Sobrien {BFD_RELOC_ALPHA_GPREL_LO16, R_ALPHA_GPRELLOW}, 90589862Sobrien {BFD_RELOC_GPREL16, R_ALPHA_GPREL16}, 90691049Sobrien {BFD_RELOC_ALPHA_BRSGP, R_ALPHA_BRSGP}, 90733965Sjdp}; 90833965Sjdp 90933965Sjdp/* Given a BFD reloc type, return a HOWTO structure. */ 91033965Sjdp 91133965Sjdpstatic reloc_howto_type * 91233965Sjdpelf64_alpha_bfd_reloc_type_lookup (abfd, code) 91378833Sobrien bfd *abfd ATTRIBUTE_UNUSED; 91433965Sjdp bfd_reloc_code_real_type code; 91533965Sjdp{ 91633965Sjdp const struct elf_reloc_map *i, *e; 91733965Sjdp i = e = elf64_alpha_reloc_map; 91833965Sjdp e += sizeof (elf64_alpha_reloc_map) / sizeof (struct elf_reloc_map); 91933965Sjdp for (; i != e; ++i) 92033965Sjdp { 92133965Sjdp if (i->bfd_reloc_val == code) 92233965Sjdp return &elf64_alpha_howto_table[i->elf_reloc_val]; 92333965Sjdp } 92433965Sjdp return 0; 92533965Sjdp} 92633965Sjdp 92733965Sjdp/* Given an Alpha ELF reloc type, fill in an arelent structure. */ 92833965Sjdp 92933965Sjdpstatic void 93033965Sjdpelf64_alpha_info_to_howto (abfd, cache_ptr, dst) 93178833Sobrien bfd *abfd ATTRIBUTE_UNUSED; 93233965Sjdp arelent *cache_ptr; 93333965Sjdp Elf64_Internal_Rela *dst; 93433965Sjdp{ 93533965Sjdp unsigned r_type; 93633965Sjdp 93733965Sjdp r_type = ELF64_R_TYPE(dst->r_info); 93833965Sjdp BFD_ASSERT (r_type < (unsigned int) R_ALPHA_max); 93933965Sjdp cache_ptr->howto = &elf64_alpha_howto_table[r_type]; 94033965Sjdp} 94133965Sjdp 94277303Sobrien/* These functions do relaxation for Alpha ELF. 94360510Sobrien 94460510Sobrien Currently I'm only handling what I can do with existing compiler 94560510Sobrien and assembler support, which means no instructions are removed, 94660510Sobrien though some may be nopped. At this time GCC does not emit enough 94760510Sobrien information to do all of the relaxing that is possible. It will 94860510Sobrien take some not small amount of work for that to happen. 94960510Sobrien 95060510Sobrien There are a couple of interesting papers that I once read on this 95160510Sobrien subject, that I cannot find references to at the moment, that 95260510Sobrien related to Alpha in particular. They are by David Wall, then of 95360510Sobrien DEC WRL. */ 95460510Sobrien 95560510Sobrien#define OP_LDA 0x08 95660510Sobrien#define OP_LDAH 0x09 95760510Sobrien#define INSN_JSR 0x68004000 95860510Sobrien#define INSN_JSR_MASK 0xfc00c000 95960510Sobrien#define OP_LDQ 0x29 96060510Sobrien#define OP_BR 0x30 96160510Sobrien#define OP_BSR 0x34 96289862Sobrien#define INSN_UNOP 0x2ffe0000 96360510Sobrien 96460510Sobrienstruct alpha_relax_info 96560510Sobrien{ 96660510Sobrien bfd *abfd; 96760510Sobrien asection *sec; 96860510Sobrien bfd_byte *contents; 96960510Sobrien Elf_Internal_Rela *relocs, *relend; 97060510Sobrien struct bfd_link_info *link_info; 97160510Sobrien boolean changed_contents; 97260510Sobrien boolean changed_relocs; 97360510Sobrien bfd_vma gp; 97460510Sobrien bfd *gotobj; 97560510Sobrien asection *tsec; 97660510Sobrien struct alpha_elf_link_hash_entry *h; 97760510Sobrien struct alpha_elf_got_entry *gotent; 97860510Sobrien unsigned char other; 97960510Sobrien}; 98060510Sobrien 98160510Sobrienstatic Elf_Internal_Rela * elf64_alpha_relax_with_lituse 98277303Sobrien PARAMS((struct alpha_relax_info *info, bfd_vma symval, 98360510Sobrien Elf_Internal_Rela *irel, Elf_Internal_Rela *irelend)); 98460510Sobrien 98560510Sobrienstatic boolean elf64_alpha_relax_without_lituse 98677303Sobrien PARAMS((struct alpha_relax_info *info, bfd_vma symval, 98760510Sobrien Elf_Internal_Rela *irel)); 98860510Sobrien 98960510Sobrienstatic bfd_vma elf64_alpha_relax_opt_call 99060510Sobrien PARAMS((struct alpha_relax_info *info, bfd_vma symval)); 99160510Sobrien 99260510Sobrienstatic boolean elf64_alpha_relax_section 99360510Sobrien PARAMS((bfd *abfd, asection *sec, struct bfd_link_info *link_info, 99460510Sobrien boolean *again)); 99560510Sobrien 99660510Sobrienstatic Elf_Internal_Rela * 99760510Sobrienelf64_alpha_find_reloc_at_ofs (rel, relend, offset, type) 99860510Sobrien Elf_Internal_Rela *rel, *relend; 99960510Sobrien bfd_vma offset; 100060510Sobrien int type; 100160510Sobrien{ 100260510Sobrien while (rel < relend) 100360510Sobrien { 100489862Sobrien if (rel->r_offset == offset 100589862Sobrien && ELF64_R_TYPE (rel->r_info) == (unsigned int) type) 100660510Sobrien return rel; 100760510Sobrien ++rel; 100860510Sobrien } 100960510Sobrien return NULL; 101060510Sobrien} 101160510Sobrien 101260510Sobrienstatic Elf_Internal_Rela * 101360510Sobrienelf64_alpha_relax_with_lituse (info, symval, irel, irelend) 101460510Sobrien struct alpha_relax_info *info; 101560510Sobrien bfd_vma symval; 101660510Sobrien Elf_Internal_Rela *irel, *irelend; 101760510Sobrien{ 101860510Sobrien Elf_Internal_Rela *urel; 101960510Sobrien int flags, count, i; 102060510Sobrien bfd_signed_vma disp; 102160510Sobrien boolean fits16; 102260510Sobrien boolean fits32; 102360510Sobrien boolean lit_reused = false; 102460510Sobrien boolean all_optimized = true; 102560510Sobrien unsigned int lit_insn; 102660510Sobrien 102760510Sobrien lit_insn = bfd_get_32 (info->abfd, info->contents + irel->r_offset); 102860510Sobrien if (lit_insn >> 26 != OP_LDQ) 102960510Sobrien { 103060510Sobrien ((*_bfd_error_handler) 103160510Sobrien ("%s: %s+0x%lx: warning: LITERAL relocation against unexpected insn", 103289862Sobrien bfd_archive_filename (info->abfd), info->sec->name, 103389862Sobrien (unsigned long) irel->r_offset)); 103460510Sobrien return irel; 103560510Sobrien } 103660510Sobrien 103760510Sobrien /* Summarize how this particular LITERAL is used. */ 103860510Sobrien for (urel = irel+1, flags = count = 0; urel < irelend; ++urel, ++count) 103960510Sobrien { 104060510Sobrien if (ELF64_R_TYPE (urel->r_info) != R_ALPHA_LITUSE) 104160510Sobrien break; 104289862Sobrien if (urel->r_addend <= 3) 104360510Sobrien flags |= 1 << urel->r_addend; 104460510Sobrien } 104560510Sobrien 104677303Sobrien /* A little preparation for the loop... */ 104760510Sobrien disp = symval - info->gp; 104860510Sobrien 104960510Sobrien for (urel = irel+1, i = 0; i < count; ++i, ++urel) 105060510Sobrien { 105160510Sobrien unsigned int insn; 105277303Sobrien int insn_disp; 105377303Sobrien bfd_signed_vma xdisp; 105477303Sobrien 105560510Sobrien insn = bfd_get_32 (info->abfd, info->contents + urel->r_offset); 105660510Sobrien 105760510Sobrien switch (urel->r_addend) 105860510Sobrien { 105960510Sobrien default: /* 0 = ADDRESS FORMAT */ 106060510Sobrien /* This type is really just a placeholder to note that all 106160510Sobrien uses cannot be optimized, but to still allow some. */ 106260510Sobrien all_optimized = false; 106360510Sobrien break; 106460510Sobrien 106560510Sobrien case 1: /* MEM FORMAT */ 106660510Sobrien /* We can always optimize 16-bit displacements. */ 106777303Sobrien 106877303Sobrien /* Extract the displacement from the instruction, sign-extending 106977303Sobrien it if necessary, then test whether it is within 16 or 32 bits 107077303Sobrien displacement from GP. */ 107177303Sobrien insn_disp = insn & 0x0000ffff; 107277303Sobrien if (insn_disp & 0x00008000) 107377303Sobrien insn_disp |= 0xffff0000; /* Negative: sign-extend. */ 107477303Sobrien 107577303Sobrien xdisp = disp + insn_disp; 107677303Sobrien fits16 = (xdisp >= - (bfd_signed_vma) 0x00008000 && xdisp < 0x00008000); 107777303Sobrien fits32 = (xdisp >= - (bfd_signed_vma) 0x80000000 && xdisp < 0x7fff8000); 107877303Sobrien 107960510Sobrien if (fits16) 108060510Sobrien { 108177303Sobrien /* Take the op code and dest from this insn, take the base 108260510Sobrien register from the literal insn. Leave the offset alone. */ 108377303Sobrien insn = (insn & 0xffe0ffff) | (lit_insn & 0x001f0000); 108460510Sobrien urel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), 108589862Sobrien R_ALPHA_GPREL16); 108660510Sobrien urel->r_addend = irel->r_addend; 108760510Sobrien info->changed_relocs = true; 108860510Sobrien 108989862Sobrien bfd_put_32 (info->abfd, (bfd_vma) insn, 109089862Sobrien info->contents + urel->r_offset); 109160510Sobrien info->changed_contents = true; 109260510Sobrien } 109360510Sobrien 109460510Sobrien /* If all mem+byte, we can optimize 32-bit mem displacements. */ 109560510Sobrien else if (fits32 && !(flags & ~6)) 109660510Sobrien { 109777303Sobrien /* FIXME: sanity check that lit insn Ra is mem insn Rb. */ 109860510Sobrien 109960510Sobrien irel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), 110060510Sobrien R_ALPHA_GPRELHIGH); 110160510Sobrien lit_insn = (OP_LDAH << 26) | (lit_insn & 0x03ff0000); 110289862Sobrien bfd_put_32 (info->abfd, (bfd_vma) lit_insn, 110360510Sobrien info->contents + irel->r_offset); 110460510Sobrien lit_reused = true; 110560510Sobrien info->changed_contents = true; 110660510Sobrien 110760510Sobrien urel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), 110860510Sobrien R_ALPHA_GPRELLOW); 110960510Sobrien urel->r_addend = irel->r_addend; 111060510Sobrien info->changed_relocs = true; 111160510Sobrien } 111260510Sobrien else 111360510Sobrien all_optimized = false; 111460510Sobrien break; 111560510Sobrien 111660510Sobrien case 2: /* BYTE OFFSET FORMAT */ 111760510Sobrien /* We can always optimize byte instructions. */ 111860510Sobrien 111960510Sobrien /* FIXME: sanity check the insn for byte op. Check that the 112060510Sobrien literal dest reg is indeed Rb in the byte insn. */ 112160510Sobrien 112289862Sobrien insn &= ~ (unsigned) 0x001ff000; 112389862Sobrien insn |= ((symval & 7) << 13) | 0x1000; 112460510Sobrien 112560510Sobrien urel->r_info = ELF64_R_INFO (0, R_ALPHA_NONE); 112660510Sobrien urel->r_addend = 0; 112760510Sobrien info->changed_relocs = true; 112860510Sobrien 112989862Sobrien bfd_put_32 (info->abfd, (bfd_vma) insn, 113089862Sobrien info->contents + urel->r_offset); 113160510Sobrien info->changed_contents = true; 113260510Sobrien break; 113360510Sobrien 113460510Sobrien case 3: /* CALL FORMAT */ 113560510Sobrien { 113660510Sobrien /* If not zero, place to jump without needing pv. */ 113760510Sobrien bfd_vma optdest = elf64_alpha_relax_opt_call (info, symval); 113860510Sobrien bfd_vma org = (info->sec->output_section->vma 113960510Sobrien + info->sec->output_offset 114060510Sobrien + urel->r_offset + 4); 114160510Sobrien bfd_signed_vma odisp; 114260510Sobrien 114360510Sobrien odisp = (optdest ? optdest : symval) - org; 114460510Sobrien if (odisp >= -0x400000 && odisp < 0x400000) 114560510Sobrien { 114660510Sobrien Elf_Internal_Rela *xrel; 114760510Sobrien 114877303Sobrien /* Preserve branch prediction call stack when possible. */ 114960510Sobrien if ((insn & INSN_JSR_MASK) == INSN_JSR) 115060510Sobrien insn = (OP_BSR << 26) | (insn & 0x03e00000); 115160510Sobrien else 115260510Sobrien insn = (OP_BR << 26) | (insn & 0x03e00000); 115377303Sobrien 115460510Sobrien urel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), 115560510Sobrien R_ALPHA_BRADDR); 115660510Sobrien urel->r_addend = irel->r_addend; 115760510Sobrien 115860510Sobrien if (optdest) 115960510Sobrien urel->r_addend += optdest - symval; 116060510Sobrien else 116160510Sobrien all_optimized = false; 116260510Sobrien 116389862Sobrien bfd_put_32 (info->abfd, (bfd_vma) insn, 116489862Sobrien info->contents + urel->r_offset); 116560510Sobrien 116660510Sobrien /* Kill any HINT reloc that might exist for this insn. */ 116760510Sobrien xrel = (elf64_alpha_find_reloc_at_ofs 116877303Sobrien (info->relocs, info->relend, urel->r_offset, 116960510Sobrien R_ALPHA_HINT)); 117060510Sobrien if (xrel) 117160510Sobrien xrel->r_info = ELF64_R_INFO (0, R_ALPHA_NONE); 117260510Sobrien 117360510Sobrien info->changed_contents = true; 117460510Sobrien info->changed_relocs = true; 117560510Sobrien } 117660510Sobrien else 117760510Sobrien all_optimized = false; 117860510Sobrien 117989862Sobrien /* Even if the target is not in range for a direct branch, 118089862Sobrien if we share a GP, we can eliminate the gp reload. */ 118189862Sobrien if (optdest) 118289862Sobrien { 118389862Sobrien Elf_Internal_Rela *gpdisp 118489862Sobrien = (elf64_alpha_find_reloc_at_ofs 118589862Sobrien (irel, irelend, urel->r_offset + 4, R_ALPHA_GPDISP)); 118689862Sobrien if (gpdisp) 118789862Sobrien { 118889862Sobrien bfd_byte *p_ldah = info->contents + gpdisp->r_offset; 118989862Sobrien bfd_byte *p_lda = p_ldah + gpdisp->r_addend; 119089862Sobrien unsigned int ldah = bfd_get_32 (info->abfd, p_ldah); 119189862Sobrien unsigned int lda = bfd_get_32 (info->abfd, p_lda); 119260510Sobrien 119389862Sobrien /* Verify that the instruction is "ldah $29,0($26)". 119489862Sobrien Consider a function that ends in a noreturn call, 119589862Sobrien and that the next function begins with an ldgp, 119689862Sobrien and that by accident there is no padding between. 119789862Sobrien In that case the insn would use $27 as the base. */ 119889862Sobrien if (ldah == 0x27ba0000 && lda == 0x23bd0000) 119989862Sobrien { 120089862Sobrien bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP, p_ldah); 120189862Sobrien bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP, p_lda); 120289862Sobrien 120389862Sobrien gpdisp->r_info = ELF64_R_INFO (0, R_ALPHA_NONE); 120489862Sobrien info->changed_contents = true; 120589862Sobrien info->changed_relocs = true; 120689862Sobrien } 120789862Sobrien } 120889862Sobrien } 120960510Sobrien } 121060510Sobrien break; 121160510Sobrien } 121260510Sobrien } 121360510Sobrien 121460510Sobrien /* If all cases were optimized, we can reduce the use count on this 121560510Sobrien got entry by one, possibly eliminating it. */ 121660510Sobrien if (all_optimized) 121760510Sobrien { 121860510Sobrien info->gotent->use_count -= 1; 121960510Sobrien alpha_elf_tdata (info->gotent->gotobj)->total_got_entries -= 1; 122060510Sobrien if (!info->h) 122160510Sobrien alpha_elf_tdata (info->gotent->gotobj)->n_local_got_entries -= 1; 122260510Sobrien 122360510Sobrien /* If the literal instruction is no longer needed (it may have been 122460510Sobrien reused. We can eliminate it. 122560510Sobrien ??? For now, I don't want to deal with compacting the section, 122660510Sobrien so just nop it out. */ 122760510Sobrien if (!lit_reused) 122860510Sobrien { 122960510Sobrien irel->r_info = ELF64_R_INFO (0, R_ALPHA_NONE); 123060510Sobrien info->changed_relocs = true; 123160510Sobrien 123289862Sobrien bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP, 123389862Sobrien info->contents + irel->r_offset); 123460510Sobrien info->changed_contents = true; 123560510Sobrien } 123660510Sobrien } 123760510Sobrien 123860510Sobrien return irel + count; 123960510Sobrien} 124060510Sobrien 124160510Sobrienstatic bfd_vma 124260510Sobrienelf64_alpha_relax_opt_call (info, symval) 124360510Sobrien struct alpha_relax_info *info; 124460510Sobrien bfd_vma symval; 124560510Sobrien{ 124660510Sobrien /* If the function has the same gp, and we can identify that the 124760510Sobrien function does not use its function pointer, we can eliminate the 124860510Sobrien address load. */ 124960510Sobrien 125060510Sobrien /* If the symbol is marked NOPV, we are being told the function never 125160510Sobrien needs its procedure value. */ 125277303Sobrien if ((info->other & STO_ALPHA_STD_GPLOAD) == STO_ALPHA_NOPV) 125360510Sobrien return symval; 125460510Sobrien 125560510Sobrien /* If the symbol is marked STD_GP, we are being told the function does 125677303Sobrien a normal ldgp in the first two words. */ 125777303Sobrien else if ((info->other & STO_ALPHA_STD_GPLOAD) == STO_ALPHA_STD_GPLOAD) 125860510Sobrien ; 125960510Sobrien 126060510Sobrien /* Otherwise, we may be able to identify a GP load in the first two 126160510Sobrien words, which we can then skip. */ 126277303Sobrien else 126360510Sobrien { 126460510Sobrien Elf_Internal_Rela *tsec_relocs, *tsec_relend, *tsec_free, *gpdisp; 126560510Sobrien bfd_vma ofs; 126660510Sobrien 126777303Sobrien /* Load the relocations from the section that the target symbol is in. */ 126860510Sobrien if (info->sec == info->tsec) 126960510Sobrien { 127060510Sobrien tsec_relocs = info->relocs; 127160510Sobrien tsec_relend = info->relend; 127260510Sobrien tsec_free = NULL; 127360510Sobrien } 127460510Sobrien else 127560510Sobrien { 127660510Sobrien tsec_relocs = (_bfd_elf64_link_read_relocs 127760510Sobrien (info->abfd, info->tsec, (PTR) NULL, 127860510Sobrien (Elf_Internal_Rela *) NULL, 127960510Sobrien info->link_info->keep_memory)); 128060510Sobrien if (tsec_relocs == NULL) 128160510Sobrien return 0; 128260510Sobrien tsec_relend = tsec_relocs + info->tsec->reloc_count; 128360510Sobrien tsec_free = (info->link_info->keep_memory ? NULL : tsec_relocs); 128460510Sobrien } 128560510Sobrien 128660510Sobrien /* Recover the symbol's offset within the section. */ 128760510Sobrien ofs = (symval - info->tsec->output_section->vma 128860510Sobrien - info->tsec->output_offset); 128977303Sobrien 129060510Sobrien /* Look for a GPDISP reloc. */ 129160510Sobrien gpdisp = (elf64_alpha_find_reloc_at_ofs 129260510Sobrien (tsec_relocs, tsec_relend, ofs, R_ALPHA_GPDISP)); 129360510Sobrien 129460510Sobrien if (!gpdisp || gpdisp->r_addend != 4) 129560510Sobrien { 129660510Sobrien if (tsec_free) 129760510Sobrien free (tsec_free); 129860510Sobrien return 0; 129960510Sobrien } 130060510Sobrien if (tsec_free) 130160510Sobrien free (tsec_free); 130260510Sobrien } 130360510Sobrien 130477303Sobrien /* We've now determined that we can skip an initial gp load. Verify 130560510Sobrien that the call and the target use the same gp. */ 130660510Sobrien if (info->link_info->hash->creator != info->tsec->owner->xvec 130760510Sobrien || info->gotobj != alpha_elf_tdata (info->tsec->owner)->gotobj) 130860510Sobrien return 0; 130960510Sobrien 131060510Sobrien return symval + 8; 131160510Sobrien} 131260510Sobrien 131360510Sobrienstatic boolean 131460510Sobrienelf64_alpha_relax_without_lituse (info, symval, irel) 131560510Sobrien struct alpha_relax_info *info; 131660510Sobrien bfd_vma symval; 131760510Sobrien Elf_Internal_Rela *irel; 131860510Sobrien{ 131960510Sobrien unsigned int insn; 132060510Sobrien bfd_signed_vma disp; 132160510Sobrien 132260510Sobrien /* Get the instruction. */ 132360510Sobrien insn = bfd_get_32 (info->abfd, info->contents + irel->r_offset); 132460510Sobrien 132560510Sobrien if (insn >> 26 != OP_LDQ) 132660510Sobrien { 132760510Sobrien ((*_bfd_error_handler) 132860510Sobrien ("%s: %s+0x%lx: warning: LITERAL relocation against unexpected insn", 132989862Sobrien bfd_archive_filename (info->abfd), info->sec->name, 133060510Sobrien (unsigned long) irel->r_offset)); 133160510Sobrien return true; 133260510Sobrien } 133360510Sobrien 133460510Sobrien /* So we aren't told much. Do what we can with the address load and 133560510Sobrien fake the rest. All of the optimizations here require that the 133660510Sobrien offset from the GP fit in 16 bits. */ 133760510Sobrien 133860510Sobrien disp = symval - info->gp; 133960510Sobrien if (disp < -0x8000 || disp >= 0x8000) 134060510Sobrien return true; 134160510Sobrien 134260510Sobrien /* On the LITERAL instruction itself, consider exchanging 134360510Sobrien `ldq R,X(gp)' for `lda R,Y(gp)'. */ 134460510Sobrien 134560510Sobrien insn = (OP_LDA << 26) | (insn & 0x03ff0000); 134689862Sobrien bfd_put_32 (info->abfd, (bfd_vma) insn, info->contents + irel->r_offset); 134760510Sobrien info->changed_contents = true; 134860510Sobrien 134989862Sobrien irel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), R_ALPHA_GPREL16); 135060510Sobrien info->changed_relocs = true; 135160510Sobrien 135260510Sobrien /* Reduce the use count on this got entry by one, possibly 135360510Sobrien eliminating it. */ 135460510Sobrien info->gotent->use_count -= 1; 135560510Sobrien alpha_elf_tdata (info->gotent->gotobj)->total_got_entries -= 1; 135660510Sobrien if (!info->h) 135760510Sobrien alpha_elf_tdata (info->gotent->gotobj)->n_local_got_entries -= 1; 135860510Sobrien 135960510Sobrien /* ??? Search forward through this basic block looking for insns 136060510Sobrien that use the target register. Stop after an insn modifying the 136160510Sobrien register is seen, or after a branch or call. 136260510Sobrien 136360510Sobrien Any such memory load insn may be substituted by a load directly 136460510Sobrien off the GP. This allows the memory load insn to be issued before 136577303Sobrien the calculated GP register would otherwise be ready. 136660510Sobrien 136760510Sobrien Any such jsr insn can be replaced by a bsr if it is in range. 136860510Sobrien 136960510Sobrien This would mean that we'd have to _add_ relocations, the pain of 137060510Sobrien which gives one pause. */ 137160510Sobrien 137260510Sobrien return true; 137360510Sobrien} 137460510Sobrien 137560510Sobrienstatic boolean 137660510Sobrienelf64_alpha_relax_section (abfd, sec, link_info, again) 137760510Sobrien bfd *abfd; 137860510Sobrien asection *sec; 137960510Sobrien struct bfd_link_info *link_info; 138060510Sobrien boolean *again; 138160510Sobrien{ 138260510Sobrien Elf_Internal_Shdr *symtab_hdr; 138389862Sobrien Elf_Internal_Shdr *shndx_hdr; 138460510Sobrien Elf_Internal_Rela *internal_relocs; 138560510Sobrien Elf_Internal_Rela *free_relocs = NULL; 138660510Sobrien Elf_Internal_Rela *irel, *irelend; 138760510Sobrien bfd_byte *free_contents = NULL; 138860510Sobrien Elf64_External_Sym *extsyms = NULL; 138960510Sobrien Elf64_External_Sym *free_extsyms = NULL; 139089862Sobrien Elf_External_Sym_Shndx *shndx_buf = NULL; 139160510Sobrien struct alpha_elf_got_entry **local_got_entries; 139260510Sobrien struct alpha_relax_info info; 139360510Sobrien 139460510Sobrien /* We are not currently changing any sizes, so only one pass. */ 139560510Sobrien *again = false; 139660510Sobrien 139760510Sobrien if (link_info->relocateable 139860510Sobrien || (sec->flags & SEC_RELOC) == 0 139960510Sobrien || sec->reloc_count == 0) 140060510Sobrien return true; 140160510Sobrien 140260510Sobrien /* If this is the first time we have been called for this section, 140360510Sobrien initialize the cooked size. */ 140460510Sobrien if (sec->_cooked_size == 0) 140560510Sobrien sec->_cooked_size = sec->_raw_size; 140660510Sobrien 140760510Sobrien symtab_hdr = &elf_tdata (abfd)->symtab_hdr; 140860510Sobrien local_got_entries = alpha_elf_tdata(abfd)->local_got_entries; 140960510Sobrien 141060510Sobrien /* Load the relocations for this section. */ 141160510Sobrien internal_relocs = (_bfd_elf64_link_read_relocs 141260510Sobrien (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL, 141360510Sobrien link_info->keep_memory)); 141460510Sobrien if (internal_relocs == NULL) 141560510Sobrien goto error_return; 141660510Sobrien if (! link_info->keep_memory) 141760510Sobrien free_relocs = internal_relocs; 141860510Sobrien 141977303Sobrien memset(&info, 0, sizeof (info)); 142060510Sobrien info.abfd = abfd; 142160510Sobrien info.sec = sec; 142260510Sobrien info.link_info = link_info; 142360510Sobrien info.relocs = internal_relocs; 142460510Sobrien info.relend = irelend = internal_relocs + sec->reloc_count; 142560510Sobrien 142660510Sobrien /* Find the GP for this object. */ 142760510Sobrien info.gotobj = alpha_elf_tdata (abfd)->gotobj; 142860510Sobrien if (info.gotobj) 142960510Sobrien { 143060510Sobrien asection *sgot = alpha_elf_tdata (info.gotobj)->got; 143160510Sobrien info.gp = _bfd_get_gp_value (info.gotobj); 143260510Sobrien if (info.gp == 0) 143360510Sobrien { 143460510Sobrien info.gp = (sgot->output_section->vma 143560510Sobrien + sgot->output_offset 143660510Sobrien + 0x8000); 143760510Sobrien _bfd_set_gp_value (info.gotobj, info.gp); 143860510Sobrien } 143960510Sobrien } 144060510Sobrien 144160510Sobrien for (irel = internal_relocs; irel < irelend; irel++) 144260510Sobrien { 144360510Sobrien bfd_vma symval; 144460510Sobrien Elf_Internal_Sym isym; 144560510Sobrien struct alpha_elf_got_entry *gotent; 144660510Sobrien 144760510Sobrien if (ELF64_R_TYPE (irel->r_info) != (int) R_ALPHA_LITERAL) 144860510Sobrien continue; 144960510Sobrien 145060510Sobrien /* Get the section contents. */ 145160510Sobrien if (info.contents == NULL) 145260510Sobrien { 145360510Sobrien if (elf_section_data (sec)->this_hdr.contents != NULL) 145460510Sobrien info.contents = elf_section_data (sec)->this_hdr.contents; 145560510Sobrien else 145660510Sobrien { 145760510Sobrien info.contents = (bfd_byte *) bfd_malloc (sec->_raw_size); 145860510Sobrien if (info.contents == NULL) 145960510Sobrien goto error_return; 146060510Sobrien free_contents = info.contents; 146160510Sobrien 146260510Sobrien if (! bfd_get_section_contents (abfd, sec, info.contents, 146360510Sobrien (file_ptr) 0, sec->_raw_size)) 146460510Sobrien goto error_return; 146560510Sobrien } 146660510Sobrien } 146760510Sobrien 146860510Sobrien /* Read this BFD's symbols if we haven't done so already. */ 146960510Sobrien if (extsyms == NULL) 147060510Sobrien { 147189862Sobrien bfd_size_type amt; 147289862Sobrien 147360510Sobrien if (symtab_hdr->contents != NULL) 147460510Sobrien extsyms = (Elf64_External_Sym *) symtab_hdr->contents; 147560510Sobrien else 147660510Sobrien { 147789862Sobrien amt = symtab_hdr->sh_info; 147889862Sobrien amt *= sizeof (Elf64_External_Sym); 147989862Sobrien extsyms = (Elf64_External_Sym *) bfd_malloc (amt); 148060510Sobrien if (extsyms == NULL) 148160510Sobrien goto error_return; 148260510Sobrien free_extsyms = extsyms; 148360510Sobrien if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0 148489862Sobrien || bfd_bread ((PTR) extsyms, amt, abfd) != amt) 148560510Sobrien goto error_return; 148660510Sobrien } 148789862Sobrien 148889862Sobrien shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr; 148989862Sobrien if (shndx_hdr->sh_size != 0) 149089862Sobrien { 149189862Sobrien amt = symtab_hdr->sh_info; 149289862Sobrien amt *= sizeof (Elf_External_Sym_Shndx); 149389862Sobrien shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt); 149489862Sobrien if (shndx_buf == NULL) 149589862Sobrien goto error_return; 149689862Sobrien if (bfd_seek (abfd, shndx_hdr->sh_offset, SEEK_SET) != 0 149789862Sobrien || bfd_bread ((PTR) shndx_buf, amt, abfd) != amt) 149889862Sobrien goto error_return; 149989862Sobrien } 150060510Sobrien } 150160510Sobrien 150260510Sobrien /* Get the value of the symbol referred to by the reloc. */ 150360510Sobrien if (ELF64_R_SYM (irel->r_info) < symtab_hdr->sh_info) 150460510Sobrien { 150560510Sobrien /* A local symbol. */ 150689862Sobrien Elf64_External_Sym *esym; 150789862Sobrien Elf_External_Sym_Shndx *shndx; 150889862Sobrien 150989862Sobrien esym = extsyms + ELF64_R_SYM (irel->r_info); 151089862Sobrien shndx = shndx_buf + (shndx_buf ? ELF64_R_SYM (irel->r_info) : 0); 151189862Sobrien bfd_elf64_swap_symbol_in (abfd, esym, shndx, &isym); 151260510Sobrien if (isym.st_shndx == SHN_UNDEF) 151360510Sobrien info.tsec = bfd_und_section_ptr; 151460510Sobrien else if (isym.st_shndx == SHN_ABS) 151560510Sobrien info.tsec = bfd_abs_section_ptr; 151660510Sobrien else if (isym.st_shndx == SHN_COMMON) 151760510Sobrien info.tsec = bfd_com_section_ptr; 151877303Sobrien else 151989862Sobrien info.tsec = bfd_section_from_elf_index (abfd, isym.st_shndx); 152060510Sobrien 152160510Sobrien info.h = NULL; 152260510Sobrien info.other = isym.st_other; 152360510Sobrien gotent = local_got_entries[ELF64_R_SYM(irel->r_info)]; 152460510Sobrien symval = isym.st_value; 152560510Sobrien } 152660510Sobrien else 152760510Sobrien { 152860510Sobrien unsigned long indx; 152960510Sobrien struct alpha_elf_link_hash_entry *h; 153060510Sobrien 153160510Sobrien indx = ELF64_R_SYM (irel->r_info) - symtab_hdr->sh_info; 153260510Sobrien h = alpha_elf_sym_hashes (abfd)[indx]; 153360510Sobrien BFD_ASSERT (h != NULL); 153460510Sobrien 153560510Sobrien while (h->root.root.type == bfd_link_hash_indirect 153660510Sobrien || h->root.root.type == bfd_link_hash_warning) 153760510Sobrien h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link; 153860510Sobrien 153960510Sobrien /* We can't do anthing with undefined or dynamic symbols. */ 154060510Sobrien if (h->root.root.type == bfd_link_hash_undefined 154160510Sobrien || h->root.root.type == bfd_link_hash_undefweak 154260510Sobrien || alpha_elf_dynamic_symbol_p (&h->root, link_info)) 154360510Sobrien continue; 154460510Sobrien 154560510Sobrien info.h = h; 154660510Sobrien info.tsec = h->root.root.u.def.section; 154760510Sobrien info.other = h->root.other; 154860510Sobrien gotent = h->got_entries; 154960510Sobrien symval = h->root.root.u.def.value; 155060510Sobrien } 155160510Sobrien 155260510Sobrien /* Search for the got entry to be used by this relocation. */ 155360510Sobrien while (gotent->gotobj != info.gotobj || gotent->addend != irel->r_addend) 155460510Sobrien gotent = gotent->next; 155560510Sobrien info.gotent = gotent; 155660510Sobrien 155760510Sobrien symval += info.tsec->output_section->vma + info.tsec->output_offset; 155860510Sobrien symval += irel->r_addend; 155960510Sobrien 156060510Sobrien BFD_ASSERT(info.gotent != NULL); 156160510Sobrien 156260510Sobrien /* If there exist LITUSE relocations immediately following, this 156360510Sobrien opens up all sorts of interesting optimizations, because we 156460510Sobrien now know every location that this address load is used. */ 156560510Sobrien 156660510Sobrien if (irel+1 < irelend && ELF64_R_TYPE (irel[1].r_info) == R_ALPHA_LITUSE) 156760510Sobrien { 156860510Sobrien irel = elf64_alpha_relax_with_lituse (&info, symval, irel, irelend); 156960510Sobrien if (irel == NULL) 157060510Sobrien goto error_return; 157160510Sobrien } 157260510Sobrien else 157360510Sobrien { 157460510Sobrien if (!elf64_alpha_relax_without_lituse (&info, symval, irel)) 157560510Sobrien goto error_return; 157660510Sobrien } 157760510Sobrien } 157860510Sobrien 157960510Sobrien if (!elf64_alpha_size_got_sections (abfd, link_info)) 158060510Sobrien return false; 158160510Sobrien 158260510Sobrien if (info.changed_relocs) 158360510Sobrien { 158460510Sobrien elf_section_data (sec)->relocs = internal_relocs; 158560510Sobrien } 158660510Sobrien else if (free_relocs != NULL) 158760510Sobrien { 158860510Sobrien free (free_relocs); 158960510Sobrien } 159060510Sobrien 159160510Sobrien if (info.changed_contents) 159260510Sobrien { 159360510Sobrien elf_section_data (sec)->this_hdr.contents = info.contents; 159460510Sobrien } 159560510Sobrien else if (free_contents != NULL) 159660510Sobrien { 159760510Sobrien if (! link_info->keep_memory) 159860510Sobrien free (free_contents); 159960510Sobrien else 160060510Sobrien { 160160510Sobrien /* Cache the section contents for elf_link_input_bfd. */ 160260510Sobrien elf_section_data (sec)->this_hdr.contents = info.contents; 160360510Sobrien } 160460510Sobrien } 160560510Sobrien 160689862Sobrien if (shndx_buf != NULL) 160789862Sobrien free (shndx_buf); 160889862Sobrien 160960510Sobrien if (free_extsyms != NULL) 161060510Sobrien { 161160510Sobrien if (! link_info->keep_memory) 161260510Sobrien free (free_extsyms); 161360510Sobrien else 161460510Sobrien { 161560510Sobrien /* Cache the symbols for elf_link_input_bfd. */ 161689862Sobrien symtab_hdr->contents = (unsigned char *) extsyms; 161760510Sobrien } 161860510Sobrien } 161960510Sobrien 162060510Sobrien *again = info.changed_contents || info.changed_relocs; 162160510Sobrien 162260510Sobrien return true; 162360510Sobrien 162460510Sobrien error_return: 162560510Sobrien if (free_relocs != NULL) 162660510Sobrien free (free_relocs); 162760510Sobrien if (free_contents != NULL) 162860510Sobrien free (free_contents); 162989862Sobrien if (shndx_buf != NULL) 163089862Sobrien free (shndx_buf); 163160510Sobrien if (free_extsyms != NULL) 163260510Sobrien free (free_extsyms); 163360510Sobrien return false; 163460510Sobrien} 163560510Sobrien 163633965Sjdp/* PLT/GOT Stuff */ 163733965Sjdp#define PLT_HEADER_SIZE 32 163889862Sobrien#define PLT_HEADER_WORD1 (bfd_vma) 0xc3600000 /* br $27,.+4 */ 163989862Sobrien#define PLT_HEADER_WORD2 (bfd_vma) 0xa77b000c /* ldq $27,12($27) */ 164089862Sobrien#define PLT_HEADER_WORD3 (bfd_vma) 0x47ff041f /* nop */ 164189862Sobrien#define PLT_HEADER_WORD4 (bfd_vma) 0x6b7b0000 /* jmp $27,($27) */ 164233965Sjdp 164333965Sjdp#define PLT_ENTRY_SIZE 12 164438889Sjdp#define PLT_ENTRY_WORD1 0xc3800000 /* br $28, plt0 */ 164538889Sjdp#define PLT_ENTRY_WORD2 0 164638889Sjdp#define PLT_ENTRY_WORD3 0 164733965Sjdp 164833965Sjdp#define MAX_GOT_ENTRIES (64*1024 / 8) 164933965Sjdp 165068770Sobrien#ifndef ELF_DYNAMIC_INTERPRETER 165168770Sobrien#define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so" 165268770Sobrien#endif 165333965Sjdp 165433965Sjdp/* Handle an Alpha specific section when reading an object file. This 165533965Sjdp is called when elfcode.h finds a section with an unknown type. 165660510Sobrien FIXME: We need to handle the SHF_ALPHA_GPREL flag, but I'm not sure 165733965Sjdp how to. */ 165833965Sjdp 165933965Sjdpstatic boolean 166033965Sjdpelf64_alpha_section_from_shdr (abfd, hdr, name) 166133965Sjdp bfd *abfd; 166233965Sjdp Elf64_Internal_Shdr *hdr; 166333965Sjdp char *name; 166433965Sjdp{ 166533965Sjdp asection *newsect; 166633965Sjdp 166733965Sjdp /* There ought to be a place to keep ELF backend specific flags, but 166833965Sjdp at the moment there isn't one. We just keep track of the 166933965Sjdp sections by their name, instead. Fortunately, the ABI gives 167033965Sjdp suggested names for all the MIPS specific sections, so we will 167133965Sjdp probably get away with this. */ 167233965Sjdp switch (hdr->sh_type) 167333965Sjdp { 167433965Sjdp case SHT_ALPHA_DEBUG: 167533965Sjdp if (strcmp (name, ".mdebug") != 0) 167633965Sjdp return false; 167733965Sjdp break; 167833965Sjdp default: 167933965Sjdp return false; 168033965Sjdp } 168133965Sjdp 168233965Sjdp if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name)) 168333965Sjdp return false; 168433965Sjdp newsect = hdr->bfd_section; 168533965Sjdp 168633965Sjdp if (hdr->sh_type == SHT_ALPHA_DEBUG) 168733965Sjdp { 168833965Sjdp if (! bfd_set_section_flags (abfd, newsect, 168933965Sjdp (bfd_get_section_flags (abfd, newsect) 169033965Sjdp | SEC_DEBUGGING))) 169133965Sjdp return false; 169233965Sjdp } 169333965Sjdp 169489862Sobrien return true; 169589862Sobrien} 169633965Sjdp 169789862Sobrien/* Convert Alpha specific section flags to bfd internal section flags. */ 169833965Sjdp 169989862Sobrienstatic boolean 170089862Sobrienelf64_alpha_section_flags (flags, hdr) 170189862Sobrien flagword *flags; 170289862Sobrien Elf64_Internal_Shdr *hdr; 170389862Sobrien{ 170489862Sobrien if (hdr->sh_flags & SHF_ALPHA_GPREL) 170589862Sobrien *flags |= SEC_SMALL_DATA; 170689862Sobrien 170733965Sjdp return true; 170833965Sjdp} 170933965Sjdp 171033965Sjdp/* Set the correct type for an Alpha ELF section. We do this by the 171133965Sjdp section name, which is a hack, but ought to work. */ 171233965Sjdp 171333965Sjdpstatic boolean 171433965Sjdpelf64_alpha_fake_sections (abfd, hdr, sec) 171533965Sjdp bfd *abfd; 171633965Sjdp Elf64_Internal_Shdr *hdr; 171733965Sjdp asection *sec; 171833965Sjdp{ 171933965Sjdp register const char *name; 172033965Sjdp 172133965Sjdp name = bfd_get_section_name (abfd, sec); 172233965Sjdp 172333965Sjdp if (strcmp (name, ".mdebug") == 0) 172433965Sjdp { 172533965Sjdp hdr->sh_type = SHT_ALPHA_DEBUG; 172633965Sjdp /* In a shared object on Irix 5.3, the .mdebug section has an 172733965Sjdp entsize of 0. FIXME: Does this matter? */ 172833965Sjdp if ((abfd->flags & DYNAMIC) != 0 ) 172933965Sjdp hdr->sh_entsize = 0; 173033965Sjdp else 173133965Sjdp hdr->sh_entsize = 1; 173233965Sjdp } 173389862Sobrien else if ((sec->flags & SEC_SMALL_DATA) 173489862Sobrien || strcmp (name, ".sdata") == 0 173533965Sjdp || strcmp (name, ".sbss") == 0 173633965Sjdp || strcmp (name, ".lit4") == 0 173733965Sjdp || strcmp (name, ".lit8") == 0) 173833965Sjdp hdr->sh_flags |= SHF_ALPHA_GPREL; 173933965Sjdp 174033965Sjdp return true; 174133965Sjdp} 174233965Sjdp 174360510Sobrien/* Hook called by the linker routine which adds symbols from an object 174460510Sobrien file. We use it to put .comm items in .sbss, and not .bss. */ 174533965Sjdp 174660510Sobrienstatic boolean 174760510Sobrienelf64_alpha_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp) 174833965Sjdp bfd *abfd; 174960510Sobrien struct bfd_link_info *info; 175060510Sobrien const Elf_Internal_Sym *sym; 175178833Sobrien const char **namep ATTRIBUTE_UNUSED; 175278833Sobrien flagword *flagsp ATTRIBUTE_UNUSED; 175360510Sobrien asection **secp; 175460510Sobrien bfd_vma *valp; 175533965Sjdp{ 175660510Sobrien if (sym->st_shndx == SHN_COMMON 175760510Sobrien && !info->relocateable 175889862Sobrien && sym->st_size <= elf_gp_size (abfd)) 175960510Sobrien { 176060510Sobrien /* Common symbols less than or equal to -G nn bytes are 176160510Sobrien automatically put into .sbss. */ 176233965Sjdp 176360510Sobrien asection *scomm = bfd_get_section_by_name (abfd, ".scommon"); 176433965Sjdp 176560510Sobrien if (scomm == NULL) 176660510Sobrien { 176760510Sobrien scomm = bfd_make_section (abfd, ".scommon"); 176860510Sobrien if (scomm == NULL 176960510Sobrien || !bfd_set_section_flags (abfd, scomm, (SEC_ALLOC 177060510Sobrien | SEC_IS_COMMON 177160510Sobrien | SEC_LINKER_CREATED))) 177260510Sobrien return false; 177360510Sobrien } 177433965Sjdp 177560510Sobrien *secp = scomm; 177660510Sobrien *valp = sym->st_size; 177733965Sjdp } 177833965Sjdp 177960510Sobrien return true; 178033965Sjdp} 178133965Sjdp 178233965Sjdp/* Create the .got section. */ 178333965Sjdp 178433965Sjdpstatic boolean 178533965Sjdpelf64_alpha_create_got_section(abfd, info) 178633965Sjdp bfd *abfd; 178778833Sobrien struct bfd_link_info *info ATTRIBUTE_UNUSED; 178833965Sjdp{ 178933965Sjdp asection *s; 179033965Sjdp 179133965Sjdp if (bfd_get_section_by_name (abfd, ".got")) 179233965Sjdp return true; 179333965Sjdp 179433965Sjdp s = bfd_make_section (abfd, ".got"); 179533965Sjdp if (s == NULL 179633965Sjdp || !bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD 179733965Sjdp | SEC_HAS_CONTENTS 179833965Sjdp | SEC_IN_MEMORY 179933965Sjdp | SEC_LINKER_CREATED)) 180033965Sjdp || !bfd_set_section_alignment (abfd, s, 3)) 180133965Sjdp return false; 180233965Sjdp 180333965Sjdp alpha_elf_tdata (abfd)->got = s; 180433965Sjdp 180533965Sjdp return true; 180633965Sjdp} 180733965Sjdp 180833965Sjdp/* Create all the dynamic sections. */ 180933965Sjdp 181033965Sjdpstatic boolean 181133965Sjdpelf64_alpha_create_dynamic_sections (abfd, info) 181233965Sjdp bfd *abfd; 181333965Sjdp struct bfd_link_info *info; 181433965Sjdp{ 181533965Sjdp asection *s; 181633965Sjdp struct elf_link_hash_entry *h; 181733965Sjdp 181833965Sjdp /* We need to create .plt, .rela.plt, .got, and .rela.got sections. */ 181933965Sjdp 182033965Sjdp s = bfd_make_section (abfd, ".plt"); 182133965Sjdp if (s == NULL 182233965Sjdp || ! bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD 182333965Sjdp | SEC_HAS_CONTENTS 182433965Sjdp | SEC_IN_MEMORY 182533965Sjdp | SEC_LINKER_CREATED 182633965Sjdp | SEC_CODE)) 182733965Sjdp || ! bfd_set_section_alignment (abfd, s, 3)) 182833965Sjdp return false; 182933965Sjdp 183033965Sjdp /* Define the symbol _PROCEDURE_LINKAGE_TABLE_ at the start of the 183133965Sjdp .plt section. */ 183233965Sjdp h = NULL; 183333965Sjdp if (! (_bfd_generic_link_add_one_symbol 183433965Sjdp (info, abfd, "_PROCEDURE_LINKAGE_TABLE_", BSF_GLOBAL, s, 183533965Sjdp (bfd_vma) 0, (const char *) NULL, false, 183633965Sjdp get_elf_backend_data (abfd)->collect, 183733965Sjdp (struct bfd_link_hash_entry **) &h))) 183833965Sjdp return false; 183933965Sjdp h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR; 184033965Sjdp h->type = STT_OBJECT; 184133965Sjdp 184233965Sjdp if (info->shared 184333965Sjdp && ! _bfd_elf_link_record_dynamic_symbol (info, h)) 184433965Sjdp return false; 184533965Sjdp 184633965Sjdp s = bfd_make_section (abfd, ".rela.plt"); 184733965Sjdp if (s == NULL 184833965Sjdp || !bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD 184933965Sjdp | SEC_HAS_CONTENTS 185033965Sjdp | SEC_IN_MEMORY 185133965Sjdp | SEC_LINKER_CREATED 185233965Sjdp | SEC_READONLY)) 185333965Sjdp || ! bfd_set_section_alignment (abfd, s, 3)) 185433965Sjdp return false; 185533965Sjdp 185633965Sjdp /* We may or may not have created a .got section for this object, but 185733965Sjdp we definitely havn't done the rest of the work. */ 185833965Sjdp 185933965Sjdp if (!elf64_alpha_create_got_section (abfd, info)) 186033965Sjdp return false; 186133965Sjdp 186233965Sjdp s = bfd_make_section(abfd, ".rela.got"); 186333965Sjdp if (s == NULL 186433965Sjdp || !bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD 186533965Sjdp | SEC_HAS_CONTENTS 186633965Sjdp | SEC_IN_MEMORY 186733965Sjdp | SEC_LINKER_CREATED 186833965Sjdp | SEC_READONLY)) 186933965Sjdp || !bfd_set_section_alignment (abfd, s, 3)) 187033965Sjdp return false; 187133965Sjdp 187233965Sjdp /* Define the symbol _GLOBAL_OFFSET_TABLE_ at the start of the 187333965Sjdp dynobj's .got section. We don't do this in the linker script 187433965Sjdp because we don't want to define the symbol if we are not creating 187533965Sjdp a global offset table. */ 187633965Sjdp h = NULL; 187733965Sjdp if (!(_bfd_generic_link_add_one_symbol 187833965Sjdp (info, abfd, "_GLOBAL_OFFSET_TABLE_", BSF_GLOBAL, 187933965Sjdp alpha_elf_tdata(abfd)->got, (bfd_vma) 0, (const char *) NULL, 188033965Sjdp false, get_elf_backend_data (abfd)->collect, 188133965Sjdp (struct bfd_link_hash_entry **) &h))) 188233965Sjdp return false; 188333965Sjdp h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR; 188433965Sjdp h->type = STT_OBJECT; 188533965Sjdp 188633965Sjdp if (info->shared 188733965Sjdp && ! _bfd_elf_link_record_dynamic_symbol (info, h)) 188833965Sjdp return false; 188933965Sjdp 189033965Sjdp elf_hash_table (info)->hgot = h; 189133965Sjdp 189233965Sjdp return true; 189333965Sjdp} 189433965Sjdp 189533965Sjdp/* Read ECOFF debugging information from a .mdebug section into a 189633965Sjdp ecoff_debug_info structure. */ 189733965Sjdp 189833965Sjdpstatic boolean 189933965Sjdpelf64_alpha_read_ecoff_info (abfd, section, debug) 190033965Sjdp bfd *abfd; 190133965Sjdp asection *section; 190233965Sjdp struct ecoff_debug_info *debug; 190333965Sjdp{ 190433965Sjdp HDRR *symhdr; 190533965Sjdp const struct ecoff_debug_swap *swap; 190633965Sjdp char *ext_hdr = NULL; 190733965Sjdp 190833965Sjdp swap = get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap; 190977303Sobrien memset (debug, 0, sizeof (*debug)); 191033965Sjdp 191189862Sobrien ext_hdr = (char *) bfd_malloc (swap->external_hdr_size); 191233965Sjdp if (ext_hdr == NULL && swap->external_hdr_size != 0) 191333965Sjdp goto error_return; 191433965Sjdp 191533965Sjdp if (bfd_get_section_contents (abfd, section, ext_hdr, (file_ptr) 0, 191633965Sjdp swap->external_hdr_size) 191733965Sjdp == false) 191833965Sjdp goto error_return; 191933965Sjdp 192033965Sjdp symhdr = &debug->symbolic_header; 192133965Sjdp (*swap->swap_hdr_in) (abfd, ext_hdr, symhdr); 192233965Sjdp 192333965Sjdp /* The symbolic header contains absolute file offsets and sizes to 192433965Sjdp read. */ 192533965Sjdp#define READ(ptr, offset, count, size, type) \ 192633965Sjdp if (symhdr->count == 0) \ 192733965Sjdp debug->ptr = NULL; \ 192833965Sjdp else \ 192933965Sjdp { \ 193089862Sobrien bfd_size_type amt = (bfd_size_type) size * symhdr->count; \ 193189862Sobrien debug->ptr = (type) bfd_malloc (amt); \ 193233965Sjdp if (debug->ptr == NULL) \ 193333965Sjdp goto error_return; \ 193433965Sjdp if (bfd_seek (abfd, (file_ptr) symhdr->offset, SEEK_SET) != 0 \ 193589862Sobrien || bfd_bread (debug->ptr, amt, abfd) != amt) \ 193633965Sjdp goto error_return; \ 193733965Sjdp } 193833965Sjdp 193933965Sjdp READ (line, cbLineOffset, cbLine, sizeof (unsigned char), unsigned char *); 194033965Sjdp READ (external_dnr, cbDnOffset, idnMax, swap->external_dnr_size, PTR); 194133965Sjdp READ (external_pdr, cbPdOffset, ipdMax, swap->external_pdr_size, PTR); 194233965Sjdp READ (external_sym, cbSymOffset, isymMax, swap->external_sym_size, PTR); 194333965Sjdp READ (external_opt, cbOptOffset, ioptMax, swap->external_opt_size, PTR); 194433965Sjdp READ (external_aux, cbAuxOffset, iauxMax, sizeof (union aux_ext), 194533965Sjdp union aux_ext *); 194633965Sjdp READ (ss, cbSsOffset, issMax, sizeof (char), char *); 194733965Sjdp READ (ssext, cbSsExtOffset, issExtMax, sizeof (char), char *); 194833965Sjdp READ (external_fdr, cbFdOffset, ifdMax, swap->external_fdr_size, PTR); 194933965Sjdp READ (external_rfd, cbRfdOffset, crfd, swap->external_rfd_size, PTR); 195033965Sjdp READ (external_ext, cbExtOffset, iextMax, swap->external_ext_size, PTR); 195133965Sjdp#undef READ 195233965Sjdp 195333965Sjdp debug->fdr = NULL; 195433965Sjdp debug->adjust = NULL; 195533965Sjdp 195633965Sjdp return true; 195733965Sjdp 195833965Sjdp error_return: 195933965Sjdp if (ext_hdr != NULL) 196033965Sjdp free (ext_hdr); 196133965Sjdp if (debug->line != NULL) 196233965Sjdp free (debug->line); 196333965Sjdp if (debug->external_dnr != NULL) 196433965Sjdp free (debug->external_dnr); 196533965Sjdp if (debug->external_pdr != NULL) 196633965Sjdp free (debug->external_pdr); 196733965Sjdp if (debug->external_sym != NULL) 196833965Sjdp free (debug->external_sym); 196933965Sjdp if (debug->external_opt != NULL) 197033965Sjdp free (debug->external_opt); 197133965Sjdp if (debug->external_aux != NULL) 197233965Sjdp free (debug->external_aux); 197333965Sjdp if (debug->ss != NULL) 197433965Sjdp free (debug->ss); 197533965Sjdp if (debug->ssext != NULL) 197633965Sjdp free (debug->ssext); 197733965Sjdp if (debug->external_fdr != NULL) 197833965Sjdp free (debug->external_fdr); 197933965Sjdp if (debug->external_rfd != NULL) 198033965Sjdp free (debug->external_rfd); 198133965Sjdp if (debug->external_ext != NULL) 198233965Sjdp free (debug->external_ext); 198333965Sjdp return false; 198433965Sjdp} 198533965Sjdp 198633965Sjdp/* Alpha ELF local labels start with '$'. */ 198733965Sjdp 198833965Sjdpstatic boolean 198933965Sjdpelf64_alpha_is_local_label_name (abfd, name) 199078833Sobrien bfd *abfd ATTRIBUTE_UNUSED; 199133965Sjdp const char *name; 199233965Sjdp{ 199333965Sjdp return name[0] == '$'; 199433965Sjdp} 199533965Sjdp 199633965Sjdp/* Alpha ELF follows MIPS ELF in using a special find_nearest_line 199733965Sjdp routine in order to handle the ECOFF debugging information. We 199833965Sjdp still call this mips_elf_find_line because of the slot 199933965Sjdp find_line_info in elf_obj_tdata is declared that way. */ 200033965Sjdp 200133965Sjdpstruct mips_elf_find_line 200233965Sjdp{ 200333965Sjdp struct ecoff_debug_info d; 200433965Sjdp struct ecoff_find_line i; 200533965Sjdp}; 200633965Sjdp 200733965Sjdpstatic boolean 200833965Sjdpelf64_alpha_find_nearest_line (abfd, section, symbols, offset, filename_ptr, 200933965Sjdp functionname_ptr, line_ptr) 201033965Sjdp bfd *abfd; 201133965Sjdp asection *section; 201233965Sjdp asymbol **symbols; 201333965Sjdp bfd_vma offset; 201433965Sjdp const char **filename_ptr; 201533965Sjdp const char **functionname_ptr; 201633965Sjdp unsigned int *line_ptr; 201733965Sjdp{ 201833965Sjdp asection *msec; 201933965Sjdp 202077303Sobrien if (_bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset, 202177303Sobrien filename_ptr, functionname_ptr, 202277303Sobrien line_ptr, 0, 202377303Sobrien &elf_tdata (abfd)->dwarf2_find_line_info)) 202477303Sobrien return true; 202577303Sobrien 202633965Sjdp msec = bfd_get_section_by_name (abfd, ".mdebug"); 202733965Sjdp if (msec != NULL) 202833965Sjdp { 202933965Sjdp flagword origflags; 203033965Sjdp struct mips_elf_find_line *fi; 203133965Sjdp const struct ecoff_debug_swap * const swap = 203233965Sjdp get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap; 203333965Sjdp 203433965Sjdp /* If we are called during a link, alpha_elf_final_link may have 203533965Sjdp cleared the SEC_HAS_CONTENTS field. We force it back on here 203633965Sjdp if appropriate (which it normally will be). */ 203733965Sjdp origflags = msec->flags; 203833965Sjdp if (elf_section_data (msec)->this_hdr.sh_type != SHT_NOBITS) 203933965Sjdp msec->flags |= SEC_HAS_CONTENTS; 204033965Sjdp 204133965Sjdp fi = elf_tdata (abfd)->find_line_info; 204233965Sjdp if (fi == NULL) 204333965Sjdp { 204433965Sjdp bfd_size_type external_fdr_size; 204533965Sjdp char *fraw_src; 204633965Sjdp char *fraw_end; 204733965Sjdp struct fdr *fdr_ptr; 204889862Sobrien bfd_size_type amt = sizeof (struct mips_elf_find_line); 204933965Sjdp 205089862Sobrien fi = (struct mips_elf_find_line *) bfd_zalloc (abfd, amt); 205133965Sjdp if (fi == NULL) 205233965Sjdp { 205333965Sjdp msec->flags = origflags; 205433965Sjdp return false; 205533965Sjdp } 205633965Sjdp 205733965Sjdp if (!elf64_alpha_read_ecoff_info (abfd, msec, &fi->d)) 205833965Sjdp { 205933965Sjdp msec->flags = origflags; 206033965Sjdp return false; 206133965Sjdp } 206233965Sjdp 206333965Sjdp /* Swap in the FDR information. */ 206489862Sobrien amt = fi->d.symbolic_header.ifdMax * sizeof (struct fdr); 206589862Sobrien fi->d.fdr = (struct fdr *) bfd_alloc (abfd, amt); 206633965Sjdp if (fi->d.fdr == NULL) 206733965Sjdp { 206833965Sjdp msec->flags = origflags; 206933965Sjdp return false; 207033965Sjdp } 207133965Sjdp external_fdr_size = swap->external_fdr_size; 207233965Sjdp fdr_ptr = fi->d.fdr; 207333965Sjdp fraw_src = (char *) fi->d.external_fdr; 207433965Sjdp fraw_end = (fraw_src 207533965Sjdp + fi->d.symbolic_header.ifdMax * external_fdr_size); 207633965Sjdp for (; fraw_src < fraw_end; fraw_src += external_fdr_size, fdr_ptr++) 207733965Sjdp (*swap->swap_fdr_in) (abfd, (PTR) fraw_src, fdr_ptr); 207833965Sjdp 207933965Sjdp elf_tdata (abfd)->find_line_info = fi; 208033965Sjdp 208133965Sjdp /* Note that we don't bother to ever free this information. 208233965Sjdp find_nearest_line is either called all the time, as in 208333965Sjdp objdump -l, so the information should be saved, or it is 208433965Sjdp rarely called, as in ld error messages, so the memory 208533965Sjdp wasted is unimportant. Still, it would probably be a 208633965Sjdp good idea for free_cached_info to throw it away. */ 208733965Sjdp } 208833965Sjdp 208933965Sjdp if (_bfd_ecoff_locate_line (abfd, section, offset, &fi->d, swap, 209033965Sjdp &fi->i, filename_ptr, functionname_ptr, 209133965Sjdp line_ptr)) 209233965Sjdp { 209333965Sjdp msec->flags = origflags; 209433965Sjdp return true; 209533965Sjdp } 209633965Sjdp 209733965Sjdp msec->flags = origflags; 209833965Sjdp } 209933965Sjdp 210033965Sjdp /* Fall back on the generic ELF find_nearest_line routine. */ 210133965Sjdp 210233965Sjdp return _bfd_elf_find_nearest_line (abfd, section, symbols, offset, 210333965Sjdp filename_ptr, functionname_ptr, 210433965Sjdp line_ptr); 210533965Sjdp} 210633965Sjdp 210733965Sjdp/* Structure used to pass information to alpha_elf_output_extsym. */ 210833965Sjdp 210933965Sjdpstruct extsym_info 211033965Sjdp{ 211133965Sjdp bfd *abfd; 211233965Sjdp struct bfd_link_info *info; 211333965Sjdp struct ecoff_debug_info *debug; 211433965Sjdp const struct ecoff_debug_swap *swap; 211533965Sjdp boolean failed; 211633965Sjdp}; 211733965Sjdp 211833965Sjdpstatic boolean 211933965Sjdpelf64_alpha_output_extsym (h, data) 212033965Sjdp struct alpha_elf_link_hash_entry *h; 212133965Sjdp PTR data; 212233965Sjdp{ 212333965Sjdp struct extsym_info *einfo = (struct extsym_info *) data; 212433965Sjdp boolean strip; 212533965Sjdp asection *sec, *output_section; 212633965Sjdp 212733965Sjdp if (h->root.indx == -2) 212833965Sjdp strip = false; 212933965Sjdp else if (((h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0 213033965Sjdp || (h->root.elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) != 0) 213133965Sjdp && (h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0 213233965Sjdp && (h->root.elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) == 0) 213333965Sjdp strip = true; 213433965Sjdp else if (einfo->info->strip == strip_all 213533965Sjdp || (einfo->info->strip == strip_some 213633965Sjdp && bfd_hash_lookup (einfo->info->keep_hash, 213733965Sjdp h->root.root.root.string, 213833965Sjdp false, false) == NULL)) 213933965Sjdp strip = true; 214033965Sjdp else 214133965Sjdp strip = false; 214233965Sjdp 214333965Sjdp if (strip) 214433965Sjdp return true; 214533965Sjdp 214633965Sjdp if (h->esym.ifd == -2) 214733965Sjdp { 214833965Sjdp h->esym.jmptbl = 0; 214933965Sjdp h->esym.cobol_main = 0; 215033965Sjdp h->esym.weakext = 0; 215133965Sjdp h->esym.reserved = 0; 215233965Sjdp h->esym.ifd = ifdNil; 215333965Sjdp h->esym.asym.value = 0; 215433965Sjdp h->esym.asym.st = stGlobal; 215533965Sjdp 215633965Sjdp if (h->root.root.type != bfd_link_hash_defined 215733965Sjdp && h->root.root.type != bfd_link_hash_defweak) 215833965Sjdp h->esym.asym.sc = scAbs; 215933965Sjdp else 216033965Sjdp { 216133965Sjdp const char *name; 216233965Sjdp 216333965Sjdp sec = h->root.root.u.def.section; 216433965Sjdp output_section = sec->output_section; 216533965Sjdp 216633965Sjdp /* When making a shared library and symbol h is the one from 216733965Sjdp the another shared library, OUTPUT_SECTION may be null. */ 216833965Sjdp if (output_section == NULL) 216933965Sjdp h->esym.asym.sc = scUndefined; 217033965Sjdp else 217133965Sjdp { 217233965Sjdp name = bfd_section_name (output_section->owner, output_section); 217333965Sjdp 217433965Sjdp if (strcmp (name, ".text") == 0) 217533965Sjdp h->esym.asym.sc = scText; 217633965Sjdp else if (strcmp (name, ".data") == 0) 217733965Sjdp h->esym.asym.sc = scData; 217833965Sjdp else if (strcmp (name, ".sdata") == 0) 217933965Sjdp h->esym.asym.sc = scSData; 218033965Sjdp else if (strcmp (name, ".rodata") == 0 218133965Sjdp || strcmp (name, ".rdata") == 0) 218233965Sjdp h->esym.asym.sc = scRData; 218333965Sjdp else if (strcmp (name, ".bss") == 0) 218433965Sjdp h->esym.asym.sc = scBss; 218533965Sjdp else if (strcmp (name, ".sbss") == 0) 218633965Sjdp h->esym.asym.sc = scSBss; 218733965Sjdp else if (strcmp (name, ".init") == 0) 218833965Sjdp h->esym.asym.sc = scInit; 218933965Sjdp else if (strcmp (name, ".fini") == 0) 219033965Sjdp h->esym.asym.sc = scFini; 219133965Sjdp else 219233965Sjdp h->esym.asym.sc = scAbs; 219333965Sjdp } 219433965Sjdp } 219533965Sjdp 219633965Sjdp h->esym.asym.reserved = 0; 219733965Sjdp h->esym.asym.index = indexNil; 219833965Sjdp } 219933965Sjdp 220033965Sjdp if (h->root.root.type == bfd_link_hash_common) 220133965Sjdp h->esym.asym.value = h->root.root.u.c.size; 220233965Sjdp else if (h->root.root.type == bfd_link_hash_defined 220333965Sjdp || h->root.root.type == bfd_link_hash_defweak) 220433965Sjdp { 220533965Sjdp if (h->esym.asym.sc == scCommon) 220633965Sjdp h->esym.asym.sc = scBss; 220733965Sjdp else if (h->esym.asym.sc == scSCommon) 220833965Sjdp h->esym.asym.sc = scSBss; 220933965Sjdp 221033965Sjdp sec = h->root.root.u.def.section; 221133965Sjdp output_section = sec->output_section; 221233965Sjdp if (output_section != NULL) 221333965Sjdp h->esym.asym.value = (h->root.root.u.def.value 221433965Sjdp + sec->output_offset 221533965Sjdp + output_section->vma); 221633965Sjdp else 221733965Sjdp h->esym.asym.value = 0; 221833965Sjdp } 221933965Sjdp else if ((h->root.elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0) 222033965Sjdp { 222133965Sjdp /* Set type and value for a symbol with a function stub. */ 222233965Sjdp h->esym.asym.st = stProc; 222333965Sjdp sec = bfd_get_section_by_name (einfo->abfd, ".plt"); 222433965Sjdp if (sec == NULL) 222533965Sjdp h->esym.asym.value = 0; 222633965Sjdp else 222733965Sjdp { 222833965Sjdp output_section = sec->output_section; 222933965Sjdp if (output_section != NULL) 223060510Sobrien h->esym.asym.value = (h->root.plt.offset 223133965Sjdp + sec->output_offset 223233965Sjdp + output_section->vma); 223333965Sjdp else 223433965Sjdp h->esym.asym.value = 0; 223533965Sjdp } 223633965Sjdp } 223733965Sjdp 223833965Sjdp if (! bfd_ecoff_debug_one_external (einfo->abfd, einfo->debug, einfo->swap, 223933965Sjdp h->root.root.root.string, 224033965Sjdp &h->esym)) 224133965Sjdp { 224233965Sjdp einfo->failed = true; 224333965Sjdp return false; 224433965Sjdp } 224533965Sjdp 224633965Sjdp return true; 224733965Sjdp} 224833965Sjdp 224933965Sjdp/* FIXME: Create a runtime procedure table from the .mdebug section. 225033965Sjdp 225133965Sjdpstatic boolean 225233965Sjdpmips_elf_create_procedure_table (handle, abfd, info, s, debug) 225333965Sjdp PTR handle; 225433965Sjdp bfd *abfd; 225533965Sjdp struct bfd_link_info *info; 225633965Sjdp asection *s; 225733965Sjdp struct ecoff_debug_info *debug; 225833965Sjdp*/ 225933965Sjdp 226033965Sjdp/* Handle dynamic relocations when doing an Alpha ELF link. */ 226133965Sjdp 226233965Sjdpstatic boolean 226333965Sjdpelf64_alpha_check_relocs (abfd, info, sec, relocs) 226433965Sjdp bfd *abfd; 226533965Sjdp struct bfd_link_info *info; 226633965Sjdp asection *sec; 226733965Sjdp const Elf_Internal_Rela *relocs; 226833965Sjdp{ 226933965Sjdp bfd *dynobj; 227033965Sjdp asection *sreloc; 227133965Sjdp const char *rel_sec_name; 227233965Sjdp Elf_Internal_Shdr *symtab_hdr; 227333965Sjdp struct alpha_elf_link_hash_entry **sym_hashes; 227433965Sjdp struct alpha_elf_got_entry **local_got_entries; 227533965Sjdp const Elf_Internal_Rela *rel, *relend; 227633965Sjdp int got_created; 227789862Sobrien bfd_size_type amt; 227833965Sjdp 227933965Sjdp if (info->relocateable) 228033965Sjdp return true; 228133965Sjdp 228233965Sjdp dynobj = elf_hash_table(info)->dynobj; 228333965Sjdp if (dynobj == NULL) 228433965Sjdp elf_hash_table(info)->dynobj = dynobj = abfd; 228533965Sjdp 228633965Sjdp sreloc = NULL; 228733965Sjdp rel_sec_name = NULL; 228833965Sjdp symtab_hdr = &elf_tdata(abfd)->symtab_hdr; 228933965Sjdp sym_hashes = alpha_elf_sym_hashes(abfd); 229033965Sjdp local_got_entries = alpha_elf_tdata(abfd)->local_got_entries; 229133965Sjdp got_created = 0; 229233965Sjdp 229333965Sjdp relend = relocs + sec->reloc_count; 229433965Sjdp for (rel = relocs; rel < relend; ++rel) 229533965Sjdp { 229633965Sjdp unsigned long r_symndx, r_type; 229733965Sjdp struct alpha_elf_link_hash_entry *h; 229833965Sjdp 229933965Sjdp r_symndx = ELF64_R_SYM (rel->r_info); 230033965Sjdp if (r_symndx < symtab_hdr->sh_info) 230133965Sjdp h = NULL; 230233965Sjdp else 230333965Sjdp { 230433965Sjdp h = sym_hashes[r_symndx - symtab_hdr->sh_info]; 230538889Sjdp 230638889Sjdp while (h->root.root.type == bfd_link_hash_indirect 230738889Sjdp || h->root.root.type == bfd_link_hash_warning) 230838889Sjdp h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link; 230938889Sjdp 231033965Sjdp h->root.elf_link_hash_flags |= ELF_LINK_HASH_REF_REGULAR; 231133965Sjdp } 231233965Sjdp r_type = ELF64_R_TYPE (rel->r_info); 231333965Sjdp 231433965Sjdp switch (r_type) 231533965Sjdp { 231633965Sjdp case R_ALPHA_LITERAL: 231733965Sjdp { 231833965Sjdp struct alpha_elf_got_entry *gotent; 231933965Sjdp int flags = 0; 232033965Sjdp 232133965Sjdp if (h) 232233965Sjdp { 232333965Sjdp /* Search for and possibly create a got entry. */ 232433965Sjdp for (gotent = h->got_entries; gotent ; gotent = gotent->next) 232533965Sjdp if (gotent->gotobj == abfd && 232633965Sjdp gotent->addend == rel->r_addend) 232733965Sjdp break; 232833965Sjdp 232933965Sjdp if (!gotent) 233033965Sjdp { 233189862Sobrien amt = sizeof (struct alpha_elf_got_entry); 233233965Sjdp gotent = ((struct alpha_elf_got_entry *) 233389862Sobrien bfd_alloc (abfd, amt)); 233433965Sjdp if (!gotent) 233533965Sjdp return false; 233633965Sjdp 233733965Sjdp gotent->gotobj = abfd; 233833965Sjdp gotent->addend = rel->r_addend; 233933965Sjdp gotent->got_offset = -1; 234033965Sjdp gotent->flags = 0; 234160510Sobrien gotent->use_count = 1; 234233965Sjdp 234333965Sjdp gotent->next = h->got_entries; 234433965Sjdp h->got_entries = gotent; 234533965Sjdp 234633965Sjdp alpha_elf_tdata (abfd)->total_got_entries++; 234733965Sjdp } 234860510Sobrien else 234960510Sobrien gotent->use_count += 1; 235033965Sjdp } 235133965Sjdp else 235233965Sjdp { 235333965Sjdp /* This is a local .got entry -- record for merge. */ 235433965Sjdp if (!local_got_entries) 235533965Sjdp { 235689862Sobrien bfd_size_type size; 235789862Sobrien size = symtab_hdr->sh_info; 235889862Sobrien size *= sizeof (struct alpha_elf_got_entry *); 235933965Sjdp 236033965Sjdp local_got_entries = ((struct alpha_elf_got_entry **) 236133965Sjdp bfd_alloc (abfd, size)); 236233965Sjdp if (!local_got_entries) 236333965Sjdp return false; 236433965Sjdp 236589862Sobrien memset (local_got_entries, 0, (size_t) size); 236633965Sjdp alpha_elf_tdata (abfd)->local_got_entries = 236733965Sjdp local_got_entries; 236833965Sjdp } 236933965Sjdp 237033965Sjdp for (gotent = local_got_entries[ELF64_R_SYM(rel->r_info)]; 237133965Sjdp gotent != NULL && gotent->addend != rel->r_addend; 237233965Sjdp gotent = gotent->next) 237333965Sjdp continue; 237433965Sjdp if (!gotent) 237533965Sjdp { 237689862Sobrien amt = sizeof (struct alpha_elf_got_entry); 237733965Sjdp gotent = ((struct alpha_elf_got_entry *) 237889862Sobrien bfd_alloc (abfd, amt)); 237933965Sjdp if (!gotent) 238033965Sjdp return false; 238133965Sjdp 238233965Sjdp gotent->gotobj = abfd; 238333965Sjdp gotent->addend = rel->r_addend; 238433965Sjdp gotent->got_offset = -1; 238533965Sjdp gotent->flags = 0; 238660510Sobrien gotent->use_count = 1; 238733965Sjdp 238833965Sjdp gotent->next = local_got_entries[ELF64_R_SYM(rel->r_info)]; 238933965Sjdp local_got_entries[ELF64_R_SYM(rel->r_info)] = gotent; 239033965Sjdp 239133965Sjdp alpha_elf_tdata(abfd)->total_got_entries++; 239233965Sjdp alpha_elf_tdata(abfd)->n_local_got_entries++; 239333965Sjdp } 239460510Sobrien else 239560510Sobrien gotent->use_count += 1; 239633965Sjdp } 239733965Sjdp 239833965Sjdp /* Remember how this literal is used from its LITUSEs. 239933965Sjdp This will be important when it comes to decide if we can 240033965Sjdp create a .plt entry for a function symbol. */ 240133965Sjdp if (rel+1 < relend 240233965Sjdp && ELF64_R_TYPE (rel[1].r_info) == R_ALPHA_LITUSE) 240333965Sjdp { 240433965Sjdp do 240533965Sjdp { 240633965Sjdp ++rel; 240733965Sjdp if (rel->r_addend >= 1 && rel->r_addend <= 3) 240833965Sjdp flags |= 1 << rel->r_addend; 240933965Sjdp } 241033965Sjdp while (rel+1 < relend && 241133965Sjdp ELF64_R_TYPE (rel[1].r_info) == R_ALPHA_LITUSE); 241233965Sjdp } 241333965Sjdp else 241433965Sjdp { 241533965Sjdp /* No LITUSEs -- presumably the address is not being 241633965Sjdp loaded for nothing. */ 241733965Sjdp flags = ALPHA_ELF_LINK_HASH_LU_ADDR; 241833965Sjdp } 241933965Sjdp 242033965Sjdp gotent->flags |= flags; 242133965Sjdp if (h) 242233965Sjdp { 242333965Sjdp /* Make a guess as to whether a .plt entry will be needed. */ 242433965Sjdp if ((h->flags |= flags) == ALPHA_ELF_LINK_HASH_LU_FUNC) 242533965Sjdp h->root.elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; 242633965Sjdp else 242733965Sjdp h->root.elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; 242833965Sjdp } 242933965Sjdp } 243033965Sjdp /* FALLTHRU */ 243133965Sjdp 243233965Sjdp case R_ALPHA_GPDISP: 243389862Sobrien case R_ALPHA_GPREL16: 243433965Sjdp case R_ALPHA_GPREL32: 243560510Sobrien case R_ALPHA_GPRELHIGH: 243660510Sobrien case R_ALPHA_GPRELLOW: 243791049Sobrien case R_ALPHA_BRSGP: 243833965Sjdp /* We don't actually use the .got here, but the sections must 243933965Sjdp be created before the linker maps input sections to output 244033965Sjdp sections. */ 244133965Sjdp if (!got_created) 244233965Sjdp { 244333965Sjdp if (!elf64_alpha_create_got_section (abfd, info)) 244433965Sjdp return false; 244533965Sjdp 244633965Sjdp /* Make sure the object's gotobj is set to itself so 244733965Sjdp that we default to every object with its own .got. 244833965Sjdp We'll merge .gots later once we've collected each 244933965Sjdp object's info. */ 245033965Sjdp alpha_elf_tdata(abfd)->gotobj = abfd; 245133965Sjdp 245233965Sjdp got_created = 1; 245333965Sjdp } 245433965Sjdp break; 245533965Sjdp 245633965Sjdp case R_ALPHA_SREL16: 245733965Sjdp case R_ALPHA_SREL32: 245833965Sjdp case R_ALPHA_SREL64: 245933965Sjdp if (h == NULL) 246033965Sjdp break; 246133965Sjdp /* FALLTHRU */ 246233965Sjdp 246333965Sjdp case R_ALPHA_REFLONG: 246433965Sjdp case R_ALPHA_REFQUAD: 246533965Sjdp if (rel_sec_name == NULL) 246633965Sjdp { 246733965Sjdp rel_sec_name = (bfd_elf_string_from_elf_section 246833965Sjdp (abfd, elf_elfheader(abfd)->e_shstrndx, 246933965Sjdp elf_section_data(sec)->rel_hdr.sh_name)); 247033965Sjdp if (rel_sec_name == NULL) 247133965Sjdp return false; 247233965Sjdp 247333965Sjdp BFD_ASSERT (strncmp (rel_sec_name, ".rela", 5) == 0 247433965Sjdp && strcmp (bfd_get_section_name (abfd, sec), 247533965Sjdp rel_sec_name+5) == 0); 247633965Sjdp } 247733965Sjdp 247833965Sjdp /* We need to create the section here now whether we eventually 247933965Sjdp use it or not so that it gets mapped to an output section by 248033965Sjdp the linker. If not used, we'll kill it in 248133965Sjdp size_dynamic_sections. */ 248233965Sjdp if (sreloc == NULL) 248333965Sjdp { 248433965Sjdp sreloc = bfd_get_section_by_name (dynobj, rel_sec_name); 248533965Sjdp if (sreloc == NULL) 248633965Sjdp { 248789862Sobrien flagword flags; 248889862Sobrien 248933965Sjdp sreloc = bfd_make_section (dynobj, rel_sec_name); 249089862Sobrien flags = (SEC_HAS_CONTENTS | SEC_IN_MEMORY 249189862Sobrien | SEC_LINKER_CREATED | SEC_READONLY); 249289862Sobrien if (sec->flags & SEC_ALLOC) 249389862Sobrien flags |= SEC_ALLOC | SEC_LOAD; 249433965Sjdp if (sreloc == NULL 249589862Sobrien || !bfd_set_section_flags (dynobj, sreloc, flags) 249633965Sjdp || !bfd_set_section_alignment (dynobj, sreloc, 3)) 249733965Sjdp return false; 249833965Sjdp } 249933965Sjdp } 250033965Sjdp 250133965Sjdp if (h) 250233965Sjdp { 250333965Sjdp /* Since we havn't seen all of the input symbols yet, we 250433965Sjdp don't know whether we'll actually need a dynamic relocation 250533965Sjdp entry for this reloc. So make a record of it. Once we 250633965Sjdp find out if this thing needs dynamic relocation we'll 250777303Sobrien expand the relocation sections by the appropriate amount. */ 250833965Sjdp 250933965Sjdp struct alpha_elf_reloc_entry *rent; 251033965Sjdp 251133965Sjdp for (rent = h->reloc_entries; rent; rent = rent->next) 251233965Sjdp if (rent->rtype == r_type && rent->srel == sreloc) 251333965Sjdp break; 251433965Sjdp 251533965Sjdp if (!rent) 251633965Sjdp { 251789862Sobrien amt = sizeof (struct alpha_elf_reloc_entry); 251889862Sobrien rent = (struct alpha_elf_reloc_entry *) bfd_alloc (abfd, amt); 251933965Sjdp if (!rent) 252033965Sjdp return false; 252133965Sjdp 252233965Sjdp rent->srel = sreloc; 252333965Sjdp rent->rtype = r_type; 252433965Sjdp rent->count = 1; 252589862Sobrien rent->reltext = ((sec->flags & (SEC_READONLY | SEC_ALLOC)) 252689862Sobrien == (SEC_READONLY | SEC_ALLOC)); 252733965Sjdp 252833965Sjdp rent->next = h->reloc_entries; 252933965Sjdp h->reloc_entries = rent; 253033965Sjdp } 253133965Sjdp else 253233965Sjdp rent->count++; 253333965Sjdp } 253460510Sobrien else if (info->shared && (sec->flags & SEC_ALLOC)) 253533965Sjdp { 253660510Sobrien /* If this is a shared library, and the section is to be 253760510Sobrien loaded into memory, we need a RELATIVE reloc. */ 253833965Sjdp sreloc->_raw_size += sizeof (Elf64_External_Rela); 253989862Sobrien if (sec->flags & SEC_READONLY) 254089862Sobrien info->flags |= DF_TEXTREL; 254133965Sjdp } 254233965Sjdp break; 254333965Sjdp } 254433965Sjdp } 254533965Sjdp 254633965Sjdp return true; 254733965Sjdp} 254833965Sjdp 254933965Sjdp/* Adjust a symbol defined by a dynamic object and referenced by a 255033965Sjdp regular object. The current definition is in some section of the 255133965Sjdp dynamic object, but we're not including those sections. We have to 255233965Sjdp change the definition to something the rest of the link can 255333965Sjdp understand. */ 255433965Sjdp 255533965Sjdpstatic boolean 255633965Sjdpelf64_alpha_adjust_dynamic_symbol (info, h) 255733965Sjdp struct bfd_link_info *info; 255833965Sjdp struct elf_link_hash_entry *h; 255933965Sjdp{ 256033965Sjdp bfd *dynobj; 256133965Sjdp asection *s; 256233965Sjdp struct alpha_elf_link_hash_entry *ah; 256333965Sjdp 256433965Sjdp dynobj = elf_hash_table(info)->dynobj; 256533965Sjdp ah = (struct alpha_elf_link_hash_entry *)h; 256633965Sjdp 256733965Sjdp /* Now that we've seen all of the input symbols, finalize our decision 256833965Sjdp about whether this symbol should get a .plt entry. */ 256933965Sjdp 257089862Sobrien if (alpha_elf_dynamic_symbol_p (h, info) 257133965Sjdp && ((h->type == STT_FUNC 257233965Sjdp && !(ah->flags & ALPHA_ELF_LINK_HASH_LU_ADDR)) 257333965Sjdp || (h->type == STT_NOTYPE 257433965Sjdp && ah->flags == ALPHA_ELF_LINK_HASH_LU_FUNC)) 257533965Sjdp /* Don't prevent otherwise valid programs from linking by attempting 257633965Sjdp to create a new .got entry somewhere. A Correct Solution would be 257733965Sjdp to add a new .got section to a new object file and let it be merged 257833965Sjdp somewhere later. But for now don't bother. */ 257933965Sjdp && ah->got_entries) 258033965Sjdp { 258133965Sjdp h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; 258233965Sjdp 258333965Sjdp s = bfd_get_section_by_name(dynobj, ".plt"); 258433965Sjdp if (!s && !elf64_alpha_create_dynamic_sections (dynobj, info)) 258533965Sjdp return false; 258633965Sjdp 258733965Sjdp /* The first bit of the .plt is reserved. */ 258833965Sjdp if (s->_raw_size == 0) 258933965Sjdp s->_raw_size = PLT_HEADER_SIZE; 259033965Sjdp 259160510Sobrien h->plt.offset = s->_raw_size; 259233965Sjdp s->_raw_size += PLT_ENTRY_SIZE; 259333965Sjdp 259433965Sjdp /* If this symbol is not defined in a regular file, and we are not 259533965Sjdp generating a shared library, then set the symbol to the location 259633965Sjdp in the .plt. This is required to make function pointers compare 259733965Sjdp equal between the normal executable and the shared library. */ 259848850Sdfr if (! info->shared 259948850Sdfr && h->root.type != bfd_link_hash_defweak) 260033965Sjdp { 260133965Sjdp h->root.u.def.section = s; 260260510Sobrien h->root.u.def.value = h->plt.offset; 260333965Sjdp } 260433965Sjdp 260533965Sjdp /* We also need a JMP_SLOT entry in the .rela.plt section. */ 260633965Sjdp s = bfd_get_section_by_name (dynobj, ".rela.plt"); 260733965Sjdp BFD_ASSERT (s != NULL); 260833965Sjdp s->_raw_size += sizeof (Elf64_External_Rela); 260933965Sjdp 261033965Sjdp return true; 261133965Sjdp } 261233965Sjdp else 261333965Sjdp h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; 261433965Sjdp 261533965Sjdp /* If this is a weak symbol, and there is a real definition, the 261633965Sjdp processor independent code will have arranged for us to see the 261733965Sjdp real definition first, and we can just use the same value. */ 261833965Sjdp if (h->weakdef != NULL) 261933965Sjdp { 262033965Sjdp BFD_ASSERT (h->weakdef->root.type == bfd_link_hash_defined 262133965Sjdp || h->weakdef->root.type == bfd_link_hash_defweak); 262233965Sjdp h->root.u.def.section = h->weakdef->root.u.def.section; 262333965Sjdp h->root.u.def.value = h->weakdef->root.u.def.value; 262433965Sjdp return true; 262533965Sjdp } 262633965Sjdp 262733965Sjdp /* This is a reference to a symbol defined by a dynamic object which 262833965Sjdp is not a function. The Alpha, since it uses .got entries for all 262933965Sjdp symbols even in regular objects, does not need the hackery of a 263033965Sjdp .dynbss section and COPY dynamic relocations. */ 263133965Sjdp 263233965Sjdp return true; 263333965Sjdp} 263433965Sjdp 263538889Sjdp/* Symbol versioning can create new symbols, and make our old symbols 263638889Sjdp indirect to the new ones. Consolidate the got and reloc information 263738889Sjdp in these situations. */ 263838889Sjdp 263938889Sjdpstatic boolean 264038889Sjdpelf64_alpha_merge_ind_symbols (hi, dummy) 264138889Sjdp struct alpha_elf_link_hash_entry *hi; 264278833Sobrien PTR dummy ATTRIBUTE_UNUSED; 264338889Sjdp{ 264438889Sjdp struct alpha_elf_link_hash_entry *hs; 264538889Sjdp 264638889Sjdp if (hi->root.root.type != bfd_link_hash_indirect) 264738889Sjdp return true; 264838889Sjdp hs = hi; 264938889Sjdp do { 265038889Sjdp hs = (struct alpha_elf_link_hash_entry *)hs->root.root.u.i.link; 265138889Sjdp } while (hs->root.root.type == bfd_link_hash_indirect); 265238889Sjdp 265338889Sjdp /* Merge the flags. Whee. */ 265438889Sjdp 265538889Sjdp hs->flags |= hi->flags; 265638889Sjdp 265738889Sjdp /* Merge the .got entries. Cannibalize the old symbol's list in 265838889Sjdp doing so, since we don't need it anymore. */ 265938889Sjdp 266038889Sjdp if (hs->got_entries == NULL) 266138889Sjdp hs->got_entries = hi->got_entries; 266238889Sjdp else 266338889Sjdp { 266438889Sjdp struct alpha_elf_got_entry *gi, *gs, *gin, *gsh; 266538889Sjdp 266638889Sjdp gsh = hs->got_entries; 266738889Sjdp for (gi = hi->got_entries; gi ; gi = gin) 266838889Sjdp { 266938889Sjdp gin = gi->next; 267038889Sjdp for (gs = gsh; gs ; gs = gs->next) 267160510Sobrien if (gi->gotobj == gs->gotobj && gi->addend == gs->addend) 267238889Sjdp goto got_found; 267338889Sjdp gi->next = hs->got_entries; 267438889Sjdp hs->got_entries = gi; 267538889Sjdp got_found:; 267638889Sjdp } 267738889Sjdp } 267838889Sjdp hi->got_entries = NULL; 267938889Sjdp 268038889Sjdp /* And similar for the reloc entries. */ 268138889Sjdp 268238889Sjdp if (hs->reloc_entries == NULL) 268338889Sjdp hs->reloc_entries = hi->reloc_entries; 268438889Sjdp else 268538889Sjdp { 268638889Sjdp struct alpha_elf_reloc_entry *ri, *rs, *rin, *rsh; 268738889Sjdp 268838889Sjdp rsh = hs->reloc_entries; 268938889Sjdp for (ri = hi->reloc_entries; ri ; ri = rin) 269038889Sjdp { 269138889Sjdp rin = ri->next; 269238889Sjdp for (rs = rsh; rs ; rs = rs->next) 269338889Sjdp if (ri->rtype == rs->rtype) 269438889Sjdp { 269538889Sjdp rs->count += ri->count; 269638889Sjdp goto found_reloc; 269738889Sjdp } 269838889Sjdp ri->next = hs->reloc_entries; 269938889Sjdp hs->reloc_entries = ri; 270038889Sjdp found_reloc:; 270138889Sjdp } 270238889Sjdp } 270338889Sjdp hi->reloc_entries = NULL; 270438889Sjdp 270538889Sjdp return true; 270638889Sjdp} 270738889Sjdp 270833965Sjdp/* Is it possible to merge two object file's .got tables? */ 270933965Sjdp 271033965Sjdpstatic boolean 271133965Sjdpelf64_alpha_can_merge_gots (a, b) 271233965Sjdp bfd *a, *b; 271333965Sjdp{ 271433965Sjdp int total = alpha_elf_tdata (a)->total_got_entries; 271560510Sobrien bfd *bsub; 271633965Sjdp 271733965Sjdp /* Trivial quick fallout test. */ 271833965Sjdp if (total + alpha_elf_tdata (b)->total_got_entries <= MAX_GOT_ENTRIES) 271933965Sjdp return true; 272033965Sjdp 272133965Sjdp /* By their nature, local .got entries cannot be merged. */ 272233965Sjdp if ((total += alpha_elf_tdata (b)->n_local_got_entries) > MAX_GOT_ENTRIES) 272333965Sjdp return false; 272433965Sjdp 272533965Sjdp /* Failing the common trivial comparison, we must effectively 272633965Sjdp perform the merge. Not actually performing the merge means that 272733965Sjdp we don't have to store undo information in case we fail. */ 272860510Sobrien for (bsub = b; bsub ; bsub = alpha_elf_tdata (bsub)->in_got_link_next) 272960510Sobrien { 273060510Sobrien struct alpha_elf_link_hash_entry **hashes = alpha_elf_sym_hashes (bsub); 273160510Sobrien Elf_Internal_Shdr *symtab_hdr = &elf_tdata (bsub)->symtab_hdr; 273260510Sobrien int i, n; 273333965Sjdp 273478833Sobrien n = NUM_SHDR_ENTRIES (symtab_hdr) - symtab_hdr->sh_info; 273560510Sobrien for (i = 0; i < n; ++i) 273660510Sobrien { 273760510Sobrien struct alpha_elf_got_entry *ae, *be; 273860510Sobrien struct alpha_elf_link_hash_entry *h; 273938889Sjdp 274060510Sobrien h = hashes[i]; 274160510Sobrien while (h->root.root.type == bfd_link_hash_indirect 274260510Sobrien || h->root.root.type == bfd_link_hash_warning) 274360510Sobrien h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link; 274438889Sjdp 274560510Sobrien for (be = h->got_entries; be ; be = be->next) 274660510Sobrien { 274760510Sobrien if (be->use_count == 0) 274860510Sobrien continue; 274960510Sobrien if (be->gotobj != b) 275060510Sobrien continue; 275133965Sjdp 275260510Sobrien for (ae = h->got_entries; ae ; ae = ae->next) 275360510Sobrien if (ae->gotobj == a && ae->addend == be->addend) 275460510Sobrien goto global_found; 275533965Sjdp 275660510Sobrien if (++total > MAX_GOT_ENTRIES) 275760510Sobrien return false; 275860510Sobrien global_found:; 275960510Sobrien } 276060510Sobrien } 276160510Sobrien } 276233965Sjdp 276333965Sjdp return true; 276433965Sjdp} 276533965Sjdp 276633965Sjdp/* Actually merge two .got tables. */ 276733965Sjdp 276833965Sjdpstatic void 276933965Sjdpelf64_alpha_merge_gots (a, b) 277033965Sjdp bfd *a, *b; 277133965Sjdp{ 277260510Sobrien int total = alpha_elf_tdata (a)->total_got_entries; 277360510Sobrien bfd *bsub; 277433965Sjdp 277533965Sjdp /* Remember local expansion. */ 277633965Sjdp { 277760510Sobrien int e = alpha_elf_tdata (b)->n_local_got_entries; 277833965Sjdp total += e; 277960510Sobrien alpha_elf_tdata (a)->n_local_got_entries += e; 278033965Sjdp } 278133965Sjdp 278260510Sobrien for (bsub = b; bsub ; bsub = alpha_elf_tdata (bsub)->in_got_link_next) 278360510Sobrien { 278460510Sobrien struct alpha_elf_got_entry **local_got_entries; 278560510Sobrien struct alpha_elf_link_hash_entry **hashes; 278660510Sobrien Elf_Internal_Shdr *symtab_hdr; 278760510Sobrien int i, n; 278833965Sjdp 278960510Sobrien /* Let the local .got entries know they are part of a new subsegment. */ 279060510Sobrien local_got_entries = alpha_elf_tdata (bsub)->local_got_entries; 279160510Sobrien if (local_got_entries) 279260510Sobrien { 279360510Sobrien n = elf_tdata (bsub)->symtab_hdr.sh_info; 279460510Sobrien for (i = 0; i < n; ++i) 279560510Sobrien { 279660510Sobrien struct alpha_elf_got_entry *ent; 279760510Sobrien for (ent = local_got_entries[i]; ent; ent = ent->next) 279860510Sobrien ent->gotobj = a; 279960510Sobrien } 280060510Sobrien } 280133965Sjdp 280260510Sobrien /* Merge the global .got entries. */ 280360510Sobrien hashes = alpha_elf_sym_hashes (bsub); 280460510Sobrien symtab_hdr = &elf_tdata (bsub)->symtab_hdr; 280533965Sjdp 280678833Sobrien n = NUM_SHDR_ENTRIES (symtab_hdr) - symtab_hdr->sh_info; 280760510Sobrien for (i = 0; i < n; ++i) 280860510Sobrien { 280960510Sobrien struct alpha_elf_got_entry *ae, *be, **pbe, **start; 281060510Sobrien struct alpha_elf_link_hash_entry *h; 281138889Sjdp 281260510Sobrien h = hashes[i]; 281360510Sobrien while (h->root.root.type == bfd_link_hash_indirect 281460510Sobrien || h->root.root.type == bfd_link_hash_warning) 281560510Sobrien h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link; 281638889Sjdp 281760510Sobrien start = &h->got_entries; 281860510Sobrien for (pbe = start, be = *start; be ; pbe = &be->next, be = be->next) 281960510Sobrien { 282060510Sobrien if (be->use_count == 0) 282160510Sobrien { 282233965Sjdp *pbe = be->next; 282360510Sobrien continue; 282460510Sobrien } 282560510Sobrien if (be->gotobj != b) 282660510Sobrien continue; 282733965Sjdp 282860510Sobrien for (ae = *start; ae ; ae = ae->next) 282960510Sobrien if (ae->gotobj == a && ae->addend == be->addend) 283060510Sobrien { 283160510Sobrien ae->flags |= be->flags; 283260510Sobrien ae->use_count += be->use_count; 283360510Sobrien *pbe = be->next; 283460510Sobrien goto global_found; 283560510Sobrien } 283660510Sobrien be->gotobj = a; 283760510Sobrien total += 1; 283860510Sobrien 283960510Sobrien global_found:; 284060510Sobrien } 284160510Sobrien } 284260510Sobrien 284360510Sobrien alpha_elf_tdata (bsub)->gotobj = a; 284460510Sobrien } 284560510Sobrien alpha_elf_tdata (a)->total_got_entries = total; 284660510Sobrien 284760510Sobrien /* Merge the two in_got chains. */ 284860510Sobrien { 284960510Sobrien bfd *next; 285060510Sobrien 285160510Sobrien bsub = a; 285260510Sobrien while ((next = alpha_elf_tdata (bsub)->in_got_link_next) != NULL) 285360510Sobrien bsub = next; 285460510Sobrien 285560510Sobrien alpha_elf_tdata (bsub)->in_got_link_next = b; 285633965Sjdp } 285733965Sjdp} 285833965Sjdp 285933965Sjdp/* Calculate the offsets for the got entries. */ 286033965Sjdp 286133965Sjdpstatic boolean 286233965Sjdpelf64_alpha_calc_got_offsets_for_symbol (h, arg) 286333965Sjdp struct alpha_elf_link_hash_entry *h; 286489862Sobrien PTR arg ATTRIBUTE_UNUSED; 286533965Sjdp{ 286633965Sjdp struct alpha_elf_got_entry *gotent; 286733965Sjdp 286833965Sjdp for (gotent = h->got_entries; gotent; gotent = gotent->next) 286960510Sobrien if (gotent->use_count > 0) 287060510Sobrien { 287160510Sobrien bfd_size_type *plge 287260510Sobrien = &alpha_elf_tdata (gotent->gotobj)->got->_raw_size; 287333965Sjdp 287460510Sobrien gotent->got_offset = *plge; 287560510Sobrien *plge += 8; 287660510Sobrien } 287760510Sobrien 287833965Sjdp return true; 287933965Sjdp} 288033965Sjdp 288133965Sjdpstatic void 288233965Sjdpelf64_alpha_calc_got_offsets (info) 288333965Sjdp struct bfd_link_info *info; 288433965Sjdp{ 288533965Sjdp bfd *i, *got_list = alpha_elf_hash_table(info)->got_list; 288633965Sjdp 288733965Sjdp /* First, zero out the .got sizes, as we may be recalculating the 288833965Sjdp .got after optimizing it. */ 288933965Sjdp for (i = got_list; i ; i = alpha_elf_tdata(i)->got_link_next) 289033965Sjdp alpha_elf_tdata(i)->got->_raw_size = 0; 289133965Sjdp 289233965Sjdp /* Next, fill in the offsets for all the global entries. */ 289333965Sjdp alpha_elf_link_hash_traverse (alpha_elf_hash_table (info), 289433965Sjdp elf64_alpha_calc_got_offsets_for_symbol, 289533965Sjdp NULL); 289633965Sjdp 289733965Sjdp /* Finally, fill in the offsets for the local entries. */ 289833965Sjdp for (i = got_list; i ; i = alpha_elf_tdata(i)->got_link_next) 289933965Sjdp { 290033965Sjdp bfd_size_type got_offset = alpha_elf_tdata(i)->got->_raw_size; 290133965Sjdp bfd *j; 290233965Sjdp 290333965Sjdp for (j = i; j ; j = alpha_elf_tdata(j)->in_got_link_next) 290433965Sjdp { 290533965Sjdp struct alpha_elf_got_entry **local_got_entries, *gotent; 290633965Sjdp int k, n; 290733965Sjdp 290833965Sjdp local_got_entries = alpha_elf_tdata(j)->local_got_entries; 290933965Sjdp if (!local_got_entries) 291033965Sjdp continue; 291133965Sjdp 291233965Sjdp for (k = 0, n = elf_tdata(j)->symtab_hdr.sh_info; k < n; ++k) 291333965Sjdp for (gotent = local_got_entries[k]; gotent; gotent = gotent->next) 291460510Sobrien if (gotent->use_count > 0) 291560510Sobrien { 291660510Sobrien gotent->got_offset = got_offset; 291760510Sobrien got_offset += 8; 291860510Sobrien } 291933965Sjdp } 292033965Sjdp 292133965Sjdp alpha_elf_tdata(i)->got->_raw_size = got_offset; 292260510Sobrien alpha_elf_tdata(i)->got->_cooked_size = got_offset; 292333965Sjdp } 292433965Sjdp} 292533965Sjdp 292633965Sjdp/* Constructs the gots. */ 292733965Sjdp 292833965Sjdpstatic boolean 292960510Sobrienelf64_alpha_size_got_sections (output_bfd, info) 293089862Sobrien bfd *output_bfd ATTRIBUTE_UNUSED; 293133965Sjdp struct bfd_link_info *info; 293233965Sjdp{ 293389862Sobrien bfd *i, *got_list, *cur_got_obj = NULL; 293460510Sobrien int something_changed = 0; 293533965Sjdp 293660510Sobrien got_list = alpha_elf_hash_table (info)->got_list; 293733965Sjdp 293860510Sobrien /* On the first time through, pretend we have an existing got list 293960510Sobrien consisting of all of the input files. */ 294060510Sobrien if (got_list == NULL) 294133965Sjdp { 294260510Sobrien for (i = info->input_bfds; i ; i = i->link_next) 294360510Sobrien { 294460510Sobrien bfd *this_got = alpha_elf_tdata (i)->gotobj; 294560510Sobrien if (this_got == NULL) 294660510Sobrien continue; 294733965Sjdp 294860510Sobrien /* We are assuming no merging has yet ocurred. */ 294960510Sobrien BFD_ASSERT (this_got == i); 295033965Sjdp 295160510Sobrien if (alpha_elf_tdata (this_got)->total_got_entries > MAX_GOT_ENTRIES) 295233965Sjdp { 295360510Sobrien /* Yikes! A single object file has too many entries. */ 295460510Sobrien (*_bfd_error_handler) 295560510Sobrien (_("%s: .got subsegment exceeds 64K (size %d)"), 295689862Sobrien bfd_archive_filename (i), 295760510Sobrien alpha_elf_tdata (this_got)->total_got_entries * 8); 295860510Sobrien return false; 295933965Sjdp } 296060510Sobrien 296160510Sobrien if (got_list == NULL) 296260510Sobrien got_list = this_got; 296333965Sjdp else 296460510Sobrien alpha_elf_tdata(cur_got_obj)->got_link_next = this_got; 296560510Sobrien cur_got_obj = this_got; 296633965Sjdp } 296760510Sobrien 296860510Sobrien /* Strange degenerate case of no got references. */ 296960510Sobrien if (got_list == NULL) 297060510Sobrien return true; 297160510Sobrien 297260510Sobrien alpha_elf_hash_table (info)->got_list = got_list; 297360510Sobrien 297460510Sobrien /* Force got offsets to be recalculated. */ 297560510Sobrien something_changed = 1; 297660510Sobrien } 297760510Sobrien 297860510Sobrien cur_got_obj = got_list; 297960510Sobrien i = alpha_elf_tdata(cur_got_obj)->got_link_next; 298060510Sobrien while (i != NULL) 298160510Sobrien { 298260510Sobrien if (elf64_alpha_can_merge_gots (cur_got_obj, i)) 298360510Sobrien { 298460510Sobrien elf64_alpha_merge_gots (cur_got_obj, i); 298560510Sobrien i = alpha_elf_tdata(i)->got_link_next; 298660510Sobrien alpha_elf_tdata(cur_got_obj)->got_link_next = i; 298760510Sobrien something_changed = 1; 298860510Sobrien } 298933965Sjdp else 299033965Sjdp { 299133965Sjdp cur_got_obj = i; 299260510Sobrien i = alpha_elf_tdata(i)->got_link_next; 299333965Sjdp } 299433965Sjdp } 299533965Sjdp 299660510Sobrien /* Once the gots have been merged, fill in the got offsets for 299760510Sobrien everything therein. */ 299860510Sobrien if (1 || something_changed) 299960510Sobrien elf64_alpha_calc_got_offsets (info); 300033965Sjdp 300160510Sobrien return true; 300260510Sobrien} 300333965Sjdp 300460510Sobrienstatic boolean 300560510Sobrienelf64_alpha_always_size_sections (output_bfd, info) 300660510Sobrien bfd *output_bfd; 300760510Sobrien struct bfd_link_info *info; 300860510Sobrien{ 300960510Sobrien bfd *i; 301060510Sobrien 301160510Sobrien if (info->relocateable) 301260510Sobrien return true; 301360510Sobrien 301460510Sobrien /* First, take care of the indirect symbols created by versioning. */ 301560510Sobrien alpha_elf_link_hash_traverse (alpha_elf_hash_table (info), 301660510Sobrien elf64_alpha_merge_ind_symbols, 301760510Sobrien NULL); 301860510Sobrien 301960510Sobrien if (!elf64_alpha_size_got_sections (output_bfd, info)) 302060510Sobrien return false; 302160510Sobrien 302233965Sjdp /* Allocate space for all of the .got subsections. */ 302360510Sobrien i = alpha_elf_hash_table (info)->got_list; 302460510Sobrien for ( ; i ; i = alpha_elf_tdata(i)->got_link_next) 302533965Sjdp { 302633965Sjdp asection *s = alpha_elf_tdata(i)->got; 302733965Sjdp if (s->_raw_size > 0) 302833965Sjdp { 302933965Sjdp s->contents = (bfd_byte *) bfd_zalloc (i, s->_raw_size); 303033965Sjdp if (s->contents == NULL) 303133965Sjdp return false; 303233965Sjdp } 303333965Sjdp } 303433965Sjdp 303533965Sjdp return true; 303633965Sjdp} 303733965Sjdp 303833965Sjdp/* Work out the sizes of the dynamic relocation entries. */ 303933965Sjdp 304033965Sjdpstatic boolean 304133965Sjdpelf64_alpha_calc_dynrel_sizes (h, info) 304233965Sjdp struct alpha_elf_link_hash_entry *h; 304333965Sjdp struct bfd_link_info *info; 304433965Sjdp{ 304533965Sjdp /* If the symbol was defined as a common symbol in a regular object 304633965Sjdp file, and there was no definition in any dynamic object, then the 304733965Sjdp linker will have allocated space for the symbol in a common 304833965Sjdp section but the ELF_LINK_HASH_DEF_REGULAR flag will not have been 304933965Sjdp set. This is done for dynamic symbols in 305033965Sjdp elf_adjust_dynamic_symbol but this is not done for non-dynamic 305133965Sjdp symbols, somehow. */ 305233965Sjdp if (((h->root.elf_link_hash_flags 305333965Sjdp & (ELF_LINK_HASH_DEF_REGULAR 305433965Sjdp | ELF_LINK_HASH_REF_REGULAR 305533965Sjdp | ELF_LINK_HASH_DEF_DYNAMIC)) 305633965Sjdp == ELF_LINK_HASH_REF_REGULAR) 305733965Sjdp && (h->root.root.type == bfd_link_hash_defined 305833965Sjdp || h->root.root.type == bfd_link_hash_defweak) 305933965Sjdp && !(h->root.root.u.def.section->owner->flags & DYNAMIC)) 306033965Sjdp { 306133965Sjdp h->root.elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR; 306233965Sjdp } 306333965Sjdp 306433965Sjdp /* If the symbol is dynamic, we'll need all the relocations in their 306560510Sobrien natural form. If this is a shared object, and it has been forced 306660510Sobrien local, we'll need the same number of RELATIVE relocations. */ 306760510Sobrien 306860510Sobrien if (alpha_elf_dynamic_symbol_p (&h->root, info) || info->shared) 306933965Sjdp { 307033965Sjdp struct alpha_elf_reloc_entry *relent; 307148850Sdfr bfd *dynobj; 307248850Sdfr struct alpha_elf_got_entry *gotent; 307348850Sdfr bfd_size_type count; 307448850Sdfr asection *srel; 307533965Sjdp 307633965Sjdp for (relent = h->reloc_entries; relent; relent = relent->next) 307760510Sobrien if (relent->rtype == R_ALPHA_REFLONG 307860510Sobrien || relent->rtype == R_ALPHA_REFQUAD) 307960510Sobrien { 308060510Sobrien relent->srel->_raw_size += 308177303Sobrien sizeof (Elf64_External_Rela) * relent->count; 308289862Sobrien if (relent->reltext) 308389862Sobrien info->flags |= DT_TEXTREL; 308460510Sobrien } 308533965Sjdp 308648850Sdfr dynobj = elf_hash_table(info)->dynobj; 308748850Sdfr count = 0; 308848850Sdfr 308948850Sdfr for (gotent = h->got_entries; gotent ; gotent = gotent->next) 309048850Sdfr count++; 309148850Sdfr 309248850Sdfr /* If we are using a .plt entry, subtract one, as the first 309348850Sdfr reference uses a .rela.plt entry instead. */ 309460510Sobrien if (h->root.plt.offset != MINUS_ONE) 309548850Sdfr count--; 309648850Sdfr 309748850Sdfr if (count > 0) 309833965Sjdp { 309948850Sdfr srel = bfd_get_section_by_name (dynobj, ".rela.got"); 310048850Sdfr BFD_ASSERT (srel != NULL); 310148850Sdfr srel->_raw_size += sizeof (Elf64_External_Rela) * count; 310233965Sjdp } 310333965Sjdp } 310448850Sdfr 310533965Sjdp return true; 310633965Sjdp} 310733965Sjdp 310833965Sjdp/* Set the sizes of the dynamic sections. */ 310933965Sjdp 311033965Sjdpstatic boolean 311133965Sjdpelf64_alpha_size_dynamic_sections (output_bfd, info) 311289862Sobrien bfd *output_bfd ATTRIBUTE_UNUSED; 311333965Sjdp struct bfd_link_info *info; 311433965Sjdp{ 311533965Sjdp bfd *dynobj; 311633965Sjdp asection *s; 311733965Sjdp boolean relplt; 311833965Sjdp 311933965Sjdp dynobj = elf_hash_table(info)->dynobj; 312033965Sjdp BFD_ASSERT(dynobj != NULL); 312133965Sjdp 312233965Sjdp if (elf_hash_table (info)->dynamic_sections_created) 312333965Sjdp { 312433965Sjdp /* Set the contents of the .interp section to the interpreter. */ 312533965Sjdp if (!info->shared) 312633965Sjdp { 312733965Sjdp s = bfd_get_section_by_name (dynobj, ".interp"); 312833965Sjdp BFD_ASSERT (s != NULL); 312933965Sjdp s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER; 313033965Sjdp s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER; 313133965Sjdp } 313233965Sjdp 313333965Sjdp /* Now that we've seen all of the input files, we can decide which 313433965Sjdp symbols need dynamic relocation entries and which don't. We've 313533965Sjdp collected information in check_relocs that we can now apply to 313633965Sjdp size the dynamic relocation sections. */ 313733965Sjdp alpha_elf_link_hash_traverse (alpha_elf_hash_table (info), 313833965Sjdp elf64_alpha_calc_dynrel_sizes, 313933965Sjdp info); 314033965Sjdp 314133965Sjdp /* When building shared libraries, each local .got entry needs a 314233965Sjdp RELATIVE reloc. */ 314333965Sjdp if (info->shared) 314433965Sjdp { 314533965Sjdp bfd *i; 314633965Sjdp asection *srel; 314733965Sjdp bfd_size_type count; 314833965Sjdp 314933965Sjdp srel = bfd_get_section_by_name (dynobj, ".rela.got"); 315033965Sjdp BFD_ASSERT (srel != NULL); 315133965Sjdp 315233965Sjdp for (i = alpha_elf_hash_table(info)->got_list, count = 0; 315333965Sjdp i != NULL; 315433965Sjdp i = alpha_elf_tdata(i)->got_link_next) 315533965Sjdp count += alpha_elf_tdata(i)->n_local_got_entries; 315633965Sjdp 315777303Sobrien srel->_raw_size += count * sizeof (Elf64_External_Rela); 315833965Sjdp } 315933965Sjdp } 316033965Sjdp /* else we're not dynamic and by definition we don't need such things. */ 316133965Sjdp 316233965Sjdp /* The check_relocs and adjust_dynamic_symbol entry points have 316333965Sjdp determined the sizes of the various dynamic sections. Allocate 316433965Sjdp memory for them. */ 316533965Sjdp relplt = false; 316633965Sjdp for (s = dynobj->sections; s != NULL; s = s->next) 316733965Sjdp { 316833965Sjdp const char *name; 316933965Sjdp boolean strip; 317033965Sjdp 317133965Sjdp if (!(s->flags & SEC_LINKER_CREATED)) 317233965Sjdp continue; 317333965Sjdp 317433965Sjdp /* It's OK to base decisions on the section name, because none 317533965Sjdp of the dynobj section names depend upon the input files. */ 317633965Sjdp name = bfd_get_section_name (dynobj, s); 317733965Sjdp 317833965Sjdp /* If we don't need this section, strip it from the output file. 317933965Sjdp This is to handle .rela.bss and .rela.plt. We must create it 318033965Sjdp in create_dynamic_sections, because it must be created before 318133965Sjdp the linker maps input sections to output sections. The 318233965Sjdp linker does that before adjust_dynamic_symbol is called, and 318333965Sjdp it is that function which decides whether anything needs to 318433965Sjdp go into these sections. */ 318533965Sjdp 318633965Sjdp strip = false; 318733965Sjdp 318833965Sjdp if (strncmp (name, ".rela", 5) == 0) 318933965Sjdp { 319033965Sjdp strip = (s->_raw_size == 0); 319133965Sjdp 319233965Sjdp if (!strip) 319333965Sjdp { 319433965Sjdp if (strcmp(name, ".rela.plt") == 0) 319533965Sjdp relplt = true; 319633965Sjdp 319733965Sjdp /* We use the reloc_count field as a counter if we need 319833965Sjdp to copy relocs into the output file. */ 319933965Sjdp s->reloc_count = 0; 320033965Sjdp } 320133965Sjdp } 320233965Sjdp else if (strcmp (name, ".plt") != 0) 320333965Sjdp { 320433965Sjdp /* It's not one of our dynamic sections, so don't allocate space. */ 320533965Sjdp continue; 320633965Sjdp } 320733965Sjdp 320833965Sjdp if (strip) 320960510Sobrien _bfd_strip_section_from_output (info, s); 321033965Sjdp else 321133965Sjdp { 321233965Sjdp /* Allocate memory for the section contents. */ 321389862Sobrien s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size); 321433965Sjdp if (s->contents == NULL && s->_raw_size != 0) 321533965Sjdp return false; 321633965Sjdp } 321733965Sjdp } 321833965Sjdp 321933965Sjdp if (elf_hash_table (info)->dynamic_sections_created) 322033965Sjdp { 322133965Sjdp /* Add some entries to the .dynamic section. We fill in the 322233965Sjdp values later, in elf64_alpha_finish_dynamic_sections, but we 322333965Sjdp must add the entries now so that we get the correct size for 322433965Sjdp the .dynamic section. The DT_DEBUG entry is filled in by the 322533965Sjdp dynamic linker and used by the debugger. */ 322689862Sobrien#define add_dynamic_entry(TAG, VAL) \ 322789862Sobrien bfd_elf64_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL)) 322889862Sobrien 322933965Sjdp if (!info->shared) 323033965Sjdp { 323189862Sobrien if (!add_dynamic_entry (DT_DEBUG, 0)) 323233965Sjdp return false; 323333965Sjdp } 323433965Sjdp 323589862Sobrien if (!add_dynamic_entry (DT_PLTGOT, 0)) 323633965Sjdp return false; 323733965Sjdp 323833965Sjdp if (relplt) 323933965Sjdp { 324089862Sobrien if (!add_dynamic_entry (DT_PLTRELSZ, 0) 324189862Sobrien || !add_dynamic_entry (DT_PLTREL, DT_RELA) 324289862Sobrien || !add_dynamic_entry (DT_JMPREL, 0)) 324333965Sjdp return false; 324433965Sjdp } 324533965Sjdp 324689862Sobrien if (!add_dynamic_entry (DT_RELA, 0) 324789862Sobrien || !add_dynamic_entry (DT_RELASZ, 0) 324889862Sobrien || !add_dynamic_entry (DT_RELAENT, sizeof (Elf64_External_Rela))) 324933965Sjdp return false; 325033965Sjdp 325189862Sobrien if (info->flags & DF_TEXTREL) 325233965Sjdp { 325389862Sobrien if (!add_dynamic_entry (DT_TEXTREL, 0)) 325433965Sjdp return false; 325533965Sjdp } 325633965Sjdp } 325789862Sobrien#undef add_dynamic_entry 325833965Sjdp 325933965Sjdp return true; 326033965Sjdp} 326133965Sjdp 326233965Sjdp/* Relocate an Alpha ELF section. */ 326333965Sjdp 326433965Sjdpstatic boolean 326533965Sjdpelf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section, 326633965Sjdp contents, relocs, local_syms, local_sections) 326733965Sjdp bfd *output_bfd; 326833965Sjdp struct bfd_link_info *info; 326933965Sjdp bfd *input_bfd; 327033965Sjdp asection *input_section; 327133965Sjdp bfd_byte *contents; 327233965Sjdp Elf_Internal_Rela *relocs; 327333965Sjdp Elf_Internal_Sym *local_syms; 327433965Sjdp asection **local_sections; 327533965Sjdp{ 327633965Sjdp Elf_Internal_Shdr *symtab_hdr; 327733965Sjdp Elf_Internal_Rela *rel; 327833965Sjdp Elf_Internal_Rela *relend; 327933965Sjdp asection *sec, *sgot, *srel, *srelgot; 328033965Sjdp bfd *dynobj, *gotobj; 328133965Sjdp bfd_vma gp; 328289862Sobrien boolean ret_val = true; 328333965Sjdp 328433965Sjdp srelgot = srel = NULL; 328533965Sjdp symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; 328633965Sjdp dynobj = elf_hash_table (info)->dynobj; 328733965Sjdp if (dynobj) 328833965Sjdp { 328933965Sjdp srelgot = bfd_get_section_by_name (dynobj, ".rela.got"); 329033965Sjdp } 329133965Sjdp 329233965Sjdp /* Find the gp value for this input bfd. */ 329333965Sjdp sgot = NULL; 329433965Sjdp gp = 0; 329533965Sjdp gotobj = alpha_elf_tdata (input_bfd)->gotobj; 329633965Sjdp if (gotobj) 329733965Sjdp { 329833965Sjdp sgot = alpha_elf_tdata (gotobj)->got; 329933965Sjdp gp = _bfd_get_gp_value (gotobj); 330033965Sjdp if (gp == 0) 330133965Sjdp { 330233965Sjdp gp = (sgot->output_section->vma 330333965Sjdp + sgot->output_offset 330433965Sjdp + 0x8000); 330533965Sjdp _bfd_set_gp_value (gotobj, gp); 330633965Sjdp } 330733965Sjdp } 330833965Sjdp 330933965Sjdp rel = relocs; 331033965Sjdp relend = relocs + input_section->reloc_count; 331133965Sjdp for (; rel < relend; rel++) 331233965Sjdp { 331333965Sjdp int r_type; 331433965Sjdp reloc_howto_type *howto; 331533965Sjdp unsigned long r_symndx; 331633965Sjdp struct alpha_elf_link_hash_entry *h; 331733965Sjdp Elf_Internal_Sym *sym; 331833965Sjdp bfd_vma relocation; 331933965Sjdp bfd_vma addend; 332033965Sjdp bfd_reloc_status_type r; 332133965Sjdp 332233965Sjdp r_type = ELF64_R_TYPE(rel->r_info); 332333965Sjdp if (r_type < 0 || r_type >= (int) R_ALPHA_max) 332433965Sjdp { 332533965Sjdp bfd_set_error (bfd_error_bad_value); 332633965Sjdp return false; 332733965Sjdp } 332833965Sjdp howto = elf64_alpha_howto_table + r_type; 332933965Sjdp 333033965Sjdp r_symndx = ELF64_R_SYM(rel->r_info); 333133965Sjdp 333233965Sjdp if (info->relocateable) 333333965Sjdp { 333433965Sjdp /* This is a relocateable link. We don't have to change 333533965Sjdp anything, unless the reloc is against a section symbol, 333633965Sjdp in which case we have to adjust according to where the 333733965Sjdp section symbol winds up in the output section. */ 333860510Sobrien 333977303Sobrien /* The symbol associated with GPDISP and LITUSE is 334060510Sobrien immaterial. Only the addend is significant. */ 334160510Sobrien if (r_type == R_ALPHA_GPDISP || r_type == R_ALPHA_LITUSE) 334260510Sobrien continue; 334360510Sobrien 334433965Sjdp if (r_symndx < symtab_hdr->sh_info) 334533965Sjdp { 334633965Sjdp sym = local_syms + r_symndx; 334733965Sjdp if (ELF_ST_TYPE(sym->st_info) == STT_SECTION) 334833965Sjdp { 334933965Sjdp sec = local_sections[r_symndx]; 335033965Sjdp rel->r_addend += sec->output_offset + sym->st_value; 335133965Sjdp } 335233965Sjdp } 335333965Sjdp 335433965Sjdp continue; 335533965Sjdp } 335633965Sjdp 335733965Sjdp /* This is a final link. */ 335833965Sjdp 335933965Sjdp h = NULL; 336033965Sjdp sym = NULL; 336133965Sjdp sec = NULL; 336233965Sjdp 336333965Sjdp if (r_symndx < symtab_hdr->sh_info) 336433965Sjdp { 336533965Sjdp sym = local_syms + r_symndx; 336633965Sjdp sec = local_sections[r_symndx]; 336789862Sobrien relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel); 336833965Sjdp } 336933965Sjdp else 337033965Sjdp { 337133965Sjdp h = alpha_elf_sym_hashes (input_bfd)[r_symndx - symtab_hdr->sh_info]; 337233965Sjdp 337333965Sjdp while (h->root.root.type == bfd_link_hash_indirect 337433965Sjdp || h->root.root.type == bfd_link_hash_warning) 337533965Sjdp h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link; 337633965Sjdp 337733965Sjdp if (h->root.root.type == bfd_link_hash_defined 337833965Sjdp || h->root.root.type == bfd_link_hash_defweak) 337933965Sjdp { 338033965Sjdp sec = h->root.root.u.def.section; 338133965Sjdp 338233965Sjdp if (sec->output_section == NULL) 338333965Sjdp relocation = 0; 338433965Sjdp else 338533965Sjdp { 338633965Sjdp relocation = (h->root.root.u.def.value 338733965Sjdp + sec->output_section->vma 338833965Sjdp + sec->output_offset); 338933965Sjdp } 339033965Sjdp } 339133965Sjdp else if (h->root.root.type == bfd_link_hash_undefweak) 339233965Sjdp relocation = 0; 339389862Sobrien else if (info->shared 339489862Sobrien && (!info->symbolic || info->allow_shlib_undefined) 339568770Sobrien && !info->no_undefined 339668770Sobrien && ELF_ST_VISIBILITY (h->root.other) == STV_DEFAULT) 339733965Sjdp relocation = 0; 339833965Sjdp else 339933965Sjdp { 340033965Sjdp if (!((*info->callbacks->undefined_symbol) 340133965Sjdp (info, h->root.root.root.string, input_bfd, 340260510Sobrien input_section, rel->r_offset, 340368770Sobrien (!info->shared || info->no_undefined 340468770Sobrien || ELF_ST_VISIBILITY (h->root.other))))) 340589862Sobrien ret_val = false; 340633965Sjdp relocation = 0; 340733965Sjdp } 340833965Sjdp } 340933965Sjdp addend = rel->r_addend; 341033965Sjdp 341133965Sjdp switch (r_type) 341233965Sjdp { 341333965Sjdp case R_ALPHA_GPDISP: 341433965Sjdp { 341533965Sjdp bfd_byte *p_ldah, *p_lda; 341633965Sjdp 341733965Sjdp BFD_ASSERT(gp != 0); 341833965Sjdp 341933965Sjdp relocation = (input_section->output_section->vma 342033965Sjdp + input_section->output_offset 342133965Sjdp + rel->r_offset); 342233965Sjdp 342333965Sjdp p_ldah = contents + rel->r_offset - input_section->vma; 342433965Sjdp p_lda = p_ldah + rel->r_addend; 342533965Sjdp 342633965Sjdp r = elf64_alpha_do_reloc_gpdisp (input_bfd, gp - relocation, 342733965Sjdp p_ldah, p_lda); 342833965Sjdp } 342933965Sjdp break; 343033965Sjdp 343133965Sjdp case R_ALPHA_LITERAL: 343233965Sjdp { 343333965Sjdp struct alpha_elf_got_entry *gotent; 343460510Sobrien boolean dynamic_symbol; 343533965Sjdp 343633965Sjdp BFD_ASSERT(sgot != NULL); 343733965Sjdp BFD_ASSERT(gp != 0); 343833965Sjdp 343933965Sjdp if (h != NULL) 344033965Sjdp { 344133965Sjdp gotent = h->got_entries; 344260510Sobrien dynamic_symbol = alpha_elf_dynamic_symbol_p (&h->root, info); 344333965Sjdp } 344433965Sjdp else 344533965Sjdp { 344633965Sjdp gotent = (alpha_elf_tdata(input_bfd)-> 344733965Sjdp local_got_entries[r_symndx]); 344860510Sobrien dynamic_symbol = false; 344989862Sobrien 345089862Sobrien /* Need to adjust local GOT entries' addends for SEC_MERGE 345189862Sobrien unless it has been done already. */ 345289862Sobrien if ((sec->flags & SEC_MERGE) 345389862Sobrien && ELF_ST_TYPE (sym->st_info) == STT_SECTION 345489862Sobrien && (elf_section_data (sec)->sec_info_type 345589862Sobrien == ELF_INFO_TYPE_MERGE) 345689862Sobrien && (gotent->flags & ALPHA_ELF_GOT_ENTRY_RELOCS_XLATED) == 0) 345789862Sobrien { 345889862Sobrien struct alpha_elf_got_entry *ent; 345989862Sobrien asection *msec; 346089862Sobrien 346189862Sobrien for (ent = gotent; ent; ent = ent->next) 346289862Sobrien { 346389862Sobrien ent->flags |= ALPHA_ELF_GOT_ENTRY_RELOCS_XLATED; 346489862Sobrien if (ent->use_count == 0) 346589862Sobrien continue; 346689862Sobrien msec = sec; 346789862Sobrien ent->addend = 346889862Sobrien _bfd_merged_section_offset (output_bfd, &msec, 346989862Sobrien elf_section_data (sec)-> 347089862Sobrien sec_info, 347189862Sobrien sym->st_value 347289862Sobrien + ent->addend, 347389862Sobrien (bfd_vma) 0); 347489862Sobrien ent->addend -= sym->st_value; 347589862Sobrien ent->addend += msec->output_section->vma 347689862Sobrien + msec->output_offset 347789862Sobrien - sec->output_section->vma 347889862Sobrien - sec->output_offset; 347989862Sobrien } 348089862Sobrien } 348160510Sobrien } 348233965Sjdp 348360510Sobrien BFD_ASSERT(gotent != NULL); 348433965Sjdp 348560510Sobrien while (gotent->gotobj != gotobj || gotent->addend != addend) 348660510Sobrien gotent = gotent->next; 348733965Sjdp 348860510Sobrien BFD_ASSERT(gotent->use_count >= 1); 348933965Sjdp 349060510Sobrien /* Initialize the .got entry's value. */ 349160510Sobrien if (!(gotent->flags & ALPHA_ELF_GOT_ENTRY_RELOCS_DONE)) 349260510Sobrien { 349389862Sobrien bfd_put_64 (output_bfd, relocation + addend, 349460510Sobrien sgot->contents + gotent->got_offset); 349533965Sjdp 349660510Sobrien /* If the symbol has been forced local, output a 349760510Sobrien RELATIVE reloc, otherwise it will be handled in 349860510Sobrien finish_dynamic_symbol. */ 349960510Sobrien if (info->shared && !dynamic_symbol) 350060510Sobrien { 350160510Sobrien Elf_Internal_Rela outrel; 350233965Sjdp 350360510Sobrien BFD_ASSERT(srelgot != NULL); 350460510Sobrien 350560510Sobrien outrel.r_offset = (sgot->output_section->vma 350660510Sobrien + sgot->output_offset 350760510Sobrien + gotent->got_offset); 350860510Sobrien outrel.r_info = ELF64_R_INFO(0, R_ALPHA_RELATIVE); 350989862Sobrien outrel.r_addend = relocation + addend; 351060510Sobrien 351160510Sobrien bfd_elf64_swap_reloca_out (output_bfd, &outrel, 351260510Sobrien ((Elf64_External_Rela *) 351360510Sobrien srelgot->contents) 351460510Sobrien + srelgot->reloc_count++); 351577303Sobrien BFD_ASSERT (sizeof (Elf64_External_Rela) 351660510Sobrien * srelgot->reloc_count 351760510Sobrien <= srelgot->_cooked_size); 351833965Sjdp } 351960510Sobrien 352060510Sobrien gotent->flags |= ALPHA_ELF_GOT_ENTRY_RELOCS_DONE; 352133965Sjdp } 352233965Sjdp 352333965Sjdp /* Figure the gprel relocation. */ 352433965Sjdp addend = 0; 352533965Sjdp relocation = (sgot->output_section->vma 352633965Sjdp + sgot->output_offset 352733965Sjdp + gotent->got_offset); 352833965Sjdp relocation -= gp; 352933965Sjdp } 353033965Sjdp /* overflow handled by _bfd_final_link_relocate */ 353133965Sjdp goto default_reloc; 353233965Sjdp 353389862Sobrien case R_ALPHA_GPREL16: 353433965Sjdp case R_ALPHA_GPREL32: 353560510Sobrien case R_ALPHA_GPRELLOW: 353689862Sobrien if (h && alpha_elf_dynamic_symbol_p (&h->root, info)) 353789862Sobrien { 353889862Sobrien (*_bfd_error_handler) 353989862Sobrien (_("%s: gp-relative relocation against dynamic symbol %s"), 354089862Sobrien bfd_archive_filename (input_bfd), h->root.root.root.string); 354189862Sobrien ret_val = false; 354289862Sobrien } 354333965Sjdp BFD_ASSERT(gp != 0); 354433965Sjdp relocation -= gp; 354533965Sjdp goto default_reloc; 354633965Sjdp 354760510Sobrien case R_ALPHA_GPRELHIGH: 354889862Sobrien if (h && alpha_elf_dynamic_symbol_p (&h->root, info)) 354989862Sobrien { 355089862Sobrien (*_bfd_error_handler) 355189862Sobrien (_("%s: gp-relative relocation against dynamic symbol %s"), 355289862Sobrien bfd_archive_filename (input_bfd), h->root.root.root.string); 355389862Sobrien ret_val = false; 355489862Sobrien } 355560510Sobrien BFD_ASSERT(gp != 0); 355660510Sobrien relocation -= gp; 355760510Sobrien relocation += addend; 355860510Sobrien addend = 0; 355960510Sobrien relocation = (((bfd_signed_vma) relocation >> 16) 356060510Sobrien + ((relocation >> 15) & 1)); 356160510Sobrien goto default_reloc; 356260510Sobrien 356389862Sobrien case R_ALPHA_HINT: 356489862Sobrien /* A call to a dynamic symbol is definitely out of range of 356589862Sobrien the 16-bit displacement. Don't bother writing anything. */ 356689862Sobrien if (h && alpha_elf_dynamic_symbol_p (&h->root, info)) 356789862Sobrien { 356889862Sobrien r = bfd_reloc_ok; 356989862Sobrien break; 357089862Sobrien } 357189862Sobrien /* FALLTHRU */ 357289862Sobrien 357333965Sjdp case R_ALPHA_BRADDR: 357433965Sjdp /* The regular PC-relative stuff measures from the start of 357533965Sjdp the instruction rather than the end. */ 357633965Sjdp addend -= 4; 357733965Sjdp goto default_reloc; 357833965Sjdp 357991049Sobrien case R_ALPHA_BRSGP: 358091049Sobrien { 358191049Sobrien int other; 358291049Sobrien const char *name; 358391049Sobrien 358491049Sobrien /* The regular PC-relative stuff measures from the start of 358591049Sobrien the instruction rather than the end. */ 358691049Sobrien addend -= 4; 358791049Sobrien 358891049Sobrien /* The source and destination gp must be the same. Note that 358991049Sobrien the source will always have an assigned gp, since we forced 359091049Sobrien one in check_relocs, but that the destination may not, as 359191049Sobrien it might not have had any relocations at all. Also take 359291049Sobrien care not to crash if H is an undefined symbol. */ 359391049Sobrien if (h != NULL && sec != NULL 359491049Sobrien && alpha_elf_tdata (sec->owner)->gotobj 359591049Sobrien && gotobj != alpha_elf_tdata (sec->owner)->gotobj) 359691049Sobrien { 359791049Sobrien (*_bfd_error_handler) 359891049Sobrien (_("%s: change in gp: BRSGP %s"), 359991049Sobrien bfd_archive_filename (input_bfd), h->root.root.root.string); 360091049Sobrien ret_val = false; 360191049Sobrien } 360291049Sobrien 360391049Sobrien /* The symbol should be marked either NOPV or STD_GPLOAD. */ 360491049Sobrien if (h != NULL) 360591049Sobrien other = h->root.other; 360691049Sobrien else 360791049Sobrien other = sym->st_other; 360891049Sobrien switch (other & STO_ALPHA_STD_GPLOAD) 360991049Sobrien { 361091049Sobrien case STO_ALPHA_NOPV: 361191049Sobrien break; 361291049Sobrien case STO_ALPHA_STD_GPLOAD: 361391049Sobrien addend += 8; 361491049Sobrien break; 361591049Sobrien default: 361691049Sobrien if (h != NULL) 361791049Sobrien name = h->root.root.root.string; 361891049Sobrien else 361991049Sobrien { 362091049Sobrien name = (bfd_elf_string_from_elf_section 362191049Sobrien (input_bfd, symtab_hdr->sh_link, sym->st_name)); 362291049Sobrien if (name == NULL) 362391049Sobrien name = _("<unknown>"); 362491049Sobrien else if (name[0] == 0) 362591049Sobrien name = bfd_section_name (input_bfd, sec); 362691049Sobrien } 362791049Sobrien (*_bfd_error_handler) 362891049Sobrien (_("%s: !samegp reloc against symbol without .prologue: %s"), 362991049Sobrien bfd_archive_filename (input_bfd), name); 363091049Sobrien ret_val = false; 363191049Sobrien break; 363291049Sobrien } 363391049Sobrien 363491049Sobrien goto default_reloc; 363591049Sobrien } 363691049Sobrien 363733965Sjdp case R_ALPHA_REFLONG: 363833965Sjdp case R_ALPHA_REFQUAD: 363933965Sjdp { 364033965Sjdp Elf_Internal_Rela outrel; 364133965Sjdp 364233965Sjdp /* Careful here to remember RELATIVE relocations for global 364333965Sjdp variables for symbolic shared objects. */ 364433965Sjdp 364533965Sjdp if (h && alpha_elf_dynamic_symbol_p (&h->root, info)) 364633965Sjdp { 364733965Sjdp BFD_ASSERT(h->root.dynindx != -1); 364833965Sjdp outrel.r_info = ELF64_R_INFO(h->root.dynindx, r_type); 364933965Sjdp outrel.r_addend = addend; 365033965Sjdp addend = 0, relocation = 0; 365133965Sjdp } 365289862Sobrien else if (info->shared 365389862Sobrien && r_symndx != 0 365489862Sobrien && (input_section->flags & SEC_ALLOC)) 365533965Sjdp { 365633965Sjdp outrel.r_info = ELF64_R_INFO(0, R_ALPHA_RELATIVE); 365789862Sobrien outrel.r_addend = relocation + addend; 365833965Sjdp } 365933965Sjdp else 366033965Sjdp goto default_reloc; 366133965Sjdp 366233965Sjdp if (!srel) 366333965Sjdp { 366433965Sjdp const char *name; 366533965Sjdp 366633965Sjdp name = (bfd_elf_string_from_elf_section 366733965Sjdp (input_bfd, elf_elfheader(input_bfd)->e_shstrndx, 366833965Sjdp elf_section_data(input_section)->rel_hdr.sh_name)); 366933965Sjdp BFD_ASSERT(name != NULL); 367033965Sjdp 367133965Sjdp srel = bfd_get_section_by_name (dynobj, name); 367233965Sjdp BFD_ASSERT(srel != NULL); 367333965Sjdp } 367433965Sjdp 367589862Sobrien outrel.r_offset = 367689862Sobrien _bfd_elf_section_offset (output_bfd, info, input_section, 367789862Sobrien rel->r_offset); 367891049Sobrien if ((outrel.r_offset | 1) != (bfd_vma) -1) 367933965Sjdp outrel.r_offset += (input_section->output_section->vma 368033965Sjdp + input_section->output_offset); 368133965Sjdp else 368233965Sjdp memset (&outrel, 0, sizeof outrel); 368333965Sjdp 368433965Sjdp bfd_elf64_swap_reloca_out (output_bfd, &outrel, 368533965Sjdp ((Elf64_External_Rela *) 368633965Sjdp srel->contents) 368733965Sjdp + srel->reloc_count++); 368877303Sobrien BFD_ASSERT (sizeof (Elf64_External_Rela) * srel->reloc_count 368948850Sdfr <= srel->_cooked_size); 369033965Sjdp } 369133965Sjdp goto default_reloc; 369233965Sjdp 369333965Sjdp default: 369433965Sjdp default_reloc: 369533965Sjdp r = _bfd_final_link_relocate (howto, input_bfd, input_section, 369633965Sjdp contents, rel->r_offset, relocation, 369733965Sjdp addend); 369833965Sjdp break; 369933965Sjdp } 370033965Sjdp 370133965Sjdp switch (r) 370233965Sjdp { 370333965Sjdp case bfd_reloc_ok: 370433965Sjdp break; 370533965Sjdp 370633965Sjdp case bfd_reloc_overflow: 370733965Sjdp { 370833965Sjdp const char *name; 370933965Sjdp 371089862Sobrien /* Don't warn if the overflow is due to pc relative reloc 371189862Sobrien against discarded section. Section optimization code should 371289862Sobrien handle it. */ 371389862Sobrien 371489862Sobrien if (r_symndx < symtab_hdr->sh_info 371589862Sobrien && sec != NULL && howto->pc_relative 371689862Sobrien && elf_discarded_section (sec)) 371789862Sobrien break; 371889862Sobrien 371933965Sjdp if (h != NULL) 372033965Sjdp name = h->root.root.root.string; 372133965Sjdp else 372233965Sjdp { 372333965Sjdp name = (bfd_elf_string_from_elf_section 372433965Sjdp (input_bfd, symtab_hdr->sh_link, sym->st_name)); 372533965Sjdp if (name == NULL) 372633965Sjdp return false; 372733965Sjdp if (*name == '\0') 372833965Sjdp name = bfd_section_name (input_bfd, sec); 372933965Sjdp } 373033965Sjdp if (! ((*info->callbacks->reloc_overflow) 373133965Sjdp (info, name, howto->name, (bfd_vma) 0, 373233965Sjdp input_bfd, input_section, rel->r_offset))) 373389862Sobrien ret_val = false; 373433965Sjdp } 373533965Sjdp break; 373633965Sjdp 373733965Sjdp default: 373833965Sjdp case bfd_reloc_outofrange: 373933965Sjdp abort (); 374033965Sjdp } 374133965Sjdp } 374233965Sjdp 374389862Sobrien return ret_val; 374433965Sjdp} 374533965Sjdp 374633965Sjdp/* Finish up dynamic symbol handling. We set the contents of various 374733965Sjdp dynamic sections here. */ 374833965Sjdp 374933965Sjdpstatic boolean 375033965Sjdpelf64_alpha_finish_dynamic_symbol (output_bfd, info, h, sym) 375133965Sjdp bfd *output_bfd; 375233965Sjdp struct bfd_link_info *info; 375333965Sjdp struct elf_link_hash_entry *h; 375433965Sjdp Elf_Internal_Sym *sym; 375533965Sjdp{ 375633965Sjdp bfd *dynobj = elf_hash_table(info)->dynobj; 375733965Sjdp 375860510Sobrien if (h->plt.offset != MINUS_ONE) 375933965Sjdp { 376033965Sjdp /* Fill in the .plt entry for this symbol. */ 376133965Sjdp asection *splt, *sgot, *srel; 376233965Sjdp Elf_Internal_Rela outrel; 376333965Sjdp bfd_vma got_addr, plt_addr; 376433965Sjdp bfd_vma plt_index; 376533965Sjdp struct alpha_elf_got_entry *gotent; 376633965Sjdp 376733965Sjdp BFD_ASSERT (h->dynindx != -1); 376833965Sjdp 376933965Sjdp /* The first .got entry will be updated by the .plt with the 377033965Sjdp address of the target function. */ 377133965Sjdp gotent = ((struct alpha_elf_link_hash_entry *) h)->got_entries; 377233965Sjdp BFD_ASSERT (gotent && gotent->addend == 0); 377333965Sjdp 377433965Sjdp splt = bfd_get_section_by_name (dynobj, ".plt"); 377533965Sjdp BFD_ASSERT (splt != NULL); 377633965Sjdp srel = bfd_get_section_by_name (dynobj, ".rela.plt"); 377733965Sjdp BFD_ASSERT (srel != NULL); 377833965Sjdp sgot = alpha_elf_tdata (gotent->gotobj)->got; 377933965Sjdp BFD_ASSERT (sgot != NULL); 378033965Sjdp 378133965Sjdp got_addr = (sgot->output_section->vma 378233965Sjdp + sgot->output_offset 378333965Sjdp + gotent->got_offset); 378433965Sjdp plt_addr = (splt->output_section->vma 378533965Sjdp + splt->output_offset 378660510Sobrien + h->plt.offset); 378733965Sjdp 378860510Sobrien plt_index = (h->plt.offset - PLT_HEADER_SIZE) / PLT_ENTRY_SIZE; 378933965Sjdp 379033965Sjdp /* Fill in the entry in the procedure linkage table. */ 379133965Sjdp { 379289862Sobrien bfd_vma insn1, insn2, insn3; 379333965Sjdp 379460510Sobrien insn1 = PLT_ENTRY_WORD1 | ((-(h->plt.offset + 4) >> 2) & 0x1fffff); 379538889Sjdp insn2 = PLT_ENTRY_WORD2; 379638889Sjdp insn3 = PLT_ENTRY_WORD3; 379733965Sjdp 379860510Sobrien bfd_put_32 (output_bfd, insn1, splt->contents + h->plt.offset); 379960510Sobrien bfd_put_32 (output_bfd, insn2, splt->contents + h->plt.offset + 4); 380060510Sobrien bfd_put_32 (output_bfd, insn3, splt->contents + h->plt.offset + 8); 380133965Sjdp } 380233965Sjdp 380333965Sjdp /* Fill in the entry in the .rela.plt section. */ 380433965Sjdp outrel.r_offset = got_addr; 380533965Sjdp outrel.r_info = ELF64_R_INFO(h->dynindx, R_ALPHA_JMP_SLOT); 380633965Sjdp outrel.r_addend = 0; 380733965Sjdp 380833965Sjdp bfd_elf64_swap_reloca_out (output_bfd, &outrel, 380933965Sjdp ((Elf64_External_Rela *)srel->contents 381033965Sjdp + plt_index)); 381133965Sjdp 381233965Sjdp if (!(h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)) 381333965Sjdp { 381433965Sjdp /* Mark the symbol as undefined, rather than as defined in the 381533965Sjdp .plt section. Leave the value alone. */ 381633965Sjdp sym->st_shndx = SHN_UNDEF; 381733965Sjdp } 381833965Sjdp 381933965Sjdp /* Fill in the entries in the .got. */ 382033965Sjdp bfd_put_64 (output_bfd, plt_addr, sgot->contents + gotent->got_offset); 382133965Sjdp 382233965Sjdp /* Subsequent .got entries will continue to bounce through the .plt. */ 382348850Sdfr if (gotent->next) 382433965Sjdp { 382548850Sdfr srel = bfd_get_section_by_name (dynobj, ".rela.got"); 382648850Sdfr BFD_ASSERT (! info->shared || srel != NULL); 382733965Sjdp 382848850Sdfr gotent = gotent->next; 382948850Sdfr do 383048850Sdfr { 383148850Sdfr sgot = alpha_elf_tdata(gotent->gotobj)->got; 383248850Sdfr BFD_ASSERT(sgot != NULL); 383348850Sdfr BFD_ASSERT(gotent->addend == 0); 383448850Sdfr 383548850Sdfr bfd_put_64 (output_bfd, plt_addr, 383648850Sdfr sgot->contents + gotent->got_offset); 383748850Sdfr 383848850Sdfr if (info->shared) 383948850Sdfr { 384048850Sdfr outrel.r_offset = (sgot->output_section->vma 384148850Sdfr + sgot->output_offset 384248850Sdfr + gotent->got_offset); 384348850Sdfr outrel.r_info = ELF64_R_INFO(0, R_ALPHA_RELATIVE); 384489862Sobrien outrel.r_addend = plt_addr; 384548850Sdfr 384648850Sdfr bfd_elf64_swap_reloca_out (output_bfd, &outrel, 384748850Sdfr ((Elf64_External_Rela *) 384848850Sdfr srel->contents) 384948850Sdfr + srel->reloc_count++); 385077303Sobrien BFD_ASSERT (sizeof (Elf64_External_Rela) * srel->reloc_count 385148850Sdfr <= srel->_cooked_size); 385248850Sdfr } 385348850Sdfr 385448850Sdfr gotent = gotent->next; 385548850Sdfr } 385648850Sdfr while (gotent != NULL); 385733965Sjdp } 385833965Sjdp } 385933965Sjdp else if (alpha_elf_dynamic_symbol_p (h, info)) 386033965Sjdp { 386133965Sjdp /* Fill in the dynamic relocations for this symbol's .got entries. */ 386233965Sjdp asection *srel; 386333965Sjdp Elf_Internal_Rela outrel; 386433965Sjdp struct alpha_elf_got_entry *gotent; 386533965Sjdp 386633965Sjdp srel = bfd_get_section_by_name (dynobj, ".rela.got"); 386733965Sjdp BFD_ASSERT (srel != NULL); 386833965Sjdp 386933965Sjdp outrel.r_info = ELF64_R_INFO (h->dynindx, R_ALPHA_GLOB_DAT); 387033965Sjdp for (gotent = ((struct alpha_elf_link_hash_entry *) h)->got_entries; 387133965Sjdp gotent != NULL; 387233965Sjdp gotent = gotent->next) 387333965Sjdp { 387433965Sjdp asection *sgot = alpha_elf_tdata (gotent->gotobj)->got; 387533965Sjdp outrel.r_offset = (sgot->output_section->vma 387633965Sjdp + sgot->output_offset 387733965Sjdp + gotent->got_offset); 387833965Sjdp outrel.r_addend = gotent->addend; 387933965Sjdp 388033965Sjdp bfd_elf64_swap_reloca_out (output_bfd, &outrel, 388133965Sjdp ((Elf64_External_Rela *)srel->contents 388233965Sjdp + srel->reloc_count++)); 388377303Sobrien BFD_ASSERT (sizeof (Elf64_External_Rela) * srel->reloc_count 388448850Sdfr <= srel->_cooked_size); 388533965Sjdp } 388633965Sjdp } 388733965Sjdp 388833965Sjdp /* Mark some specially defined symbols as absolute. */ 388933965Sjdp if (strcmp (h->root.root.string, "_DYNAMIC") == 0 389033965Sjdp || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0 389133965Sjdp || strcmp (h->root.root.string, "_PROCEDURE_LINKAGE_TABLE_") == 0) 389233965Sjdp sym->st_shndx = SHN_ABS; 389333965Sjdp 389433965Sjdp return true; 389533965Sjdp} 389633965Sjdp 389733965Sjdp/* Finish up the dynamic sections. */ 389833965Sjdp 389933965Sjdpstatic boolean 390033965Sjdpelf64_alpha_finish_dynamic_sections (output_bfd, info) 390133965Sjdp bfd *output_bfd; 390233965Sjdp struct bfd_link_info *info; 390333965Sjdp{ 390433965Sjdp bfd *dynobj; 390533965Sjdp asection *sdyn; 390633965Sjdp 390733965Sjdp dynobj = elf_hash_table (info)->dynobj; 390833965Sjdp sdyn = bfd_get_section_by_name (dynobj, ".dynamic"); 390933965Sjdp 391033965Sjdp if (elf_hash_table (info)->dynamic_sections_created) 391133965Sjdp { 391233965Sjdp asection *splt; 391333965Sjdp Elf64_External_Dyn *dyncon, *dynconend; 391433965Sjdp 391533965Sjdp splt = bfd_get_section_by_name (dynobj, ".plt"); 391633965Sjdp BFD_ASSERT (splt != NULL && sdyn != NULL); 391733965Sjdp 391833965Sjdp dyncon = (Elf64_External_Dyn *) sdyn->contents; 391933965Sjdp dynconend = (Elf64_External_Dyn *) (sdyn->contents + sdyn->_raw_size); 392033965Sjdp for (; dyncon < dynconend; dyncon++) 392133965Sjdp { 392233965Sjdp Elf_Internal_Dyn dyn; 392333965Sjdp const char *name; 392433965Sjdp asection *s; 392533965Sjdp 392633965Sjdp bfd_elf64_swap_dyn_in (dynobj, dyncon, &dyn); 392733965Sjdp 392833965Sjdp switch (dyn.d_tag) 392933965Sjdp { 393033965Sjdp case DT_PLTGOT: 393133965Sjdp name = ".plt"; 393233965Sjdp goto get_vma; 393333965Sjdp case DT_PLTRELSZ: 393433965Sjdp name = ".rela.plt"; 393533965Sjdp goto get_size; 393633965Sjdp case DT_JMPREL: 393733965Sjdp name = ".rela.plt"; 393833965Sjdp goto get_vma; 393933965Sjdp 394033965Sjdp case DT_RELASZ: 394133965Sjdp /* My interpretation of the TIS v1.1 ELF document indicates 394233965Sjdp that RELASZ should not include JMPREL. This is not what 394333965Sjdp the rest of the BFD does. It is, however, what the 394433965Sjdp glibc ld.so wants. Do this fixup here until we found 394533965Sjdp out who is right. */ 394633965Sjdp s = bfd_get_section_by_name (output_bfd, ".rela.plt"); 394733965Sjdp if (s) 394833965Sjdp { 394933965Sjdp dyn.d_un.d_val -= 395033965Sjdp (s->_cooked_size ? s->_cooked_size : s->_raw_size); 395133965Sjdp } 395233965Sjdp break; 395333965Sjdp 395433965Sjdp get_vma: 395533965Sjdp s = bfd_get_section_by_name (output_bfd, name); 395633965Sjdp dyn.d_un.d_ptr = (s ? s->vma : 0); 395733965Sjdp break; 395833965Sjdp 395933965Sjdp get_size: 396033965Sjdp s = bfd_get_section_by_name (output_bfd, name); 396133965Sjdp dyn.d_un.d_val = 396233965Sjdp (s->_cooked_size ? s->_cooked_size : s->_raw_size); 396333965Sjdp break; 396433965Sjdp } 396533965Sjdp 396633965Sjdp bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon); 396733965Sjdp } 396833965Sjdp 396933965Sjdp /* Initialize the PLT0 entry */ 397033965Sjdp if (splt->_raw_size > 0) 397133965Sjdp { 397233965Sjdp bfd_put_32 (output_bfd, PLT_HEADER_WORD1, splt->contents); 397333965Sjdp bfd_put_32 (output_bfd, PLT_HEADER_WORD2, splt->contents + 4); 397433965Sjdp bfd_put_32 (output_bfd, PLT_HEADER_WORD3, splt->contents + 8); 397533965Sjdp bfd_put_32 (output_bfd, PLT_HEADER_WORD4, splt->contents + 12); 397633965Sjdp 397733965Sjdp /* The next two words will be filled in by ld.so */ 397889862Sobrien bfd_put_64 (output_bfd, (bfd_vma) 0, splt->contents + 16); 397989862Sobrien bfd_put_64 (output_bfd, (bfd_vma) 0, splt->contents + 24); 398033965Sjdp 398133965Sjdp elf_section_data (splt->output_section)->this_hdr.sh_entsize = 398233965Sjdp PLT_HEADER_SIZE; 398333965Sjdp } 398433965Sjdp } 398533965Sjdp 398633965Sjdp return true; 398733965Sjdp} 398833965Sjdp 398989862Sobrien/* We need to use a special link routine to handle the .mdebug section. 399089862Sobrien We need to merge all instances of these sections together, not write 399189862Sobrien them all out sequentially. */ 399233965Sjdp 399333965Sjdpstatic boolean 399433965Sjdpelf64_alpha_final_link (abfd, info) 399533965Sjdp bfd *abfd; 399633965Sjdp struct bfd_link_info *info; 399733965Sjdp{ 399833965Sjdp asection *o; 399933965Sjdp struct bfd_link_order *p; 400089862Sobrien asection *mdebug_sec; 400133965Sjdp struct ecoff_debug_info debug; 400233965Sjdp const struct ecoff_debug_swap *swap 400333965Sjdp = get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap; 400433965Sjdp HDRR *symhdr = &debug.symbolic_header; 400533965Sjdp PTR mdebug_handle = NULL; 400633965Sjdp 400789862Sobrien /* Go through the sections and collect the mdebug information. */ 400833965Sjdp mdebug_sec = NULL; 400933965Sjdp for (o = abfd->sections; o != (asection *) NULL; o = o->next) 401033965Sjdp { 401133965Sjdp if (strcmp (o->name, ".mdebug") == 0) 401233965Sjdp { 401333965Sjdp struct extsym_info einfo; 401433965Sjdp 401533965Sjdp /* We have found the .mdebug section in the output file. 401633965Sjdp Look through all the link_orders comprising it and merge 401733965Sjdp the information together. */ 401833965Sjdp symhdr->magic = swap->sym_magic; 401933965Sjdp /* FIXME: What should the version stamp be? */ 402033965Sjdp symhdr->vstamp = 0; 402133965Sjdp symhdr->ilineMax = 0; 402233965Sjdp symhdr->cbLine = 0; 402333965Sjdp symhdr->idnMax = 0; 402433965Sjdp symhdr->ipdMax = 0; 402533965Sjdp symhdr->isymMax = 0; 402633965Sjdp symhdr->ioptMax = 0; 402733965Sjdp symhdr->iauxMax = 0; 402833965Sjdp symhdr->issMax = 0; 402933965Sjdp symhdr->issExtMax = 0; 403033965Sjdp symhdr->ifdMax = 0; 403133965Sjdp symhdr->crfd = 0; 403233965Sjdp symhdr->iextMax = 0; 403333965Sjdp 403433965Sjdp /* We accumulate the debugging information itself in the 403533965Sjdp debug_info structure. */ 403633965Sjdp debug.line = NULL; 403733965Sjdp debug.external_dnr = NULL; 403833965Sjdp debug.external_pdr = NULL; 403933965Sjdp debug.external_sym = NULL; 404033965Sjdp debug.external_opt = NULL; 404133965Sjdp debug.external_aux = NULL; 404233965Sjdp debug.ss = NULL; 404333965Sjdp debug.ssext = debug.ssext_end = NULL; 404433965Sjdp debug.external_fdr = NULL; 404533965Sjdp debug.external_rfd = NULL; 404633965Sjdp debug.external_ext = debug.external_ext_end = NULL; 404733965Sjdp 404833965Sjdp mdebug_handle = bfd_ecoff_debug_init (abfd, &debug, swap, info); 404933965Sjdp if (mdebug_handle == (PTR) NULL) 405033965Sjdp return false; 405133965Sjdp 405233965Sjdp if (1) 405333965Sjdp { 405433965Sjdp asection *s; 405533965Sjdp EXTR esym; 405689862Sobrien bfd_vma last = 0; 405733965Sjdp unsigned int i; 405833965Sjdp static const char * const name[] = 405933965Sjdp { 406033965Sjdp ".text", ".init", ".fini", ".data", 406133965Sjdp ".rodata", ".sdata", ".sbss", ".bss" 406233965Sjdp }; 406333965Sjdp static const int sc[] = { scText, scInit, scFini, scData, 406433965Sjdp scRData, scSData, scSBss, scBss }; 406533965Sjdp 406633965Sjdp esym.jmptbl = 0; 406733965Sjdp esym.cobol_main = 0; 406833965Sjdp esym.weakext = 0; 406933965Sjdp esym.reserved = 0; 407033965Sjdp esym.ifd = ifdNil; 407133965Sjdp esym.asym.iss = issNil; 407233965Sjdp esym.asym.st = stLocal; 407333965Sjdp esym.asym.reserved = 0; 407433965Sjdp esym.asym.index = indexNil; 407533965Sjdp for (i = 0; i < 8; i++) 407633965Sjdp { 407733965Sjdp esym.asym.sc = sc[i]; 407833965Sjdp s = bfd_get_section_by_name (abfd, name[i]); 407933965Sjdp if (s != NULL) 408033965Sjdp { 408133965Sjdp esym.asym.value = s->vma; 408233965Sjdp last = s->vma + s->_raw_size; 408333965Sjdp } 408433965Sjdp else 408533965Sjdp esym.asym.value = last; 408633965Sjdp 408733965Sjdp if (! bfd_ecoff_debug_one_external (abfd, &debug, swap, 408833965Sjdp name[i], &esym)) 408933965Sjdp return false; 409033965Sjdp } 409133965Sjdp } 409233965Sjdp 409333965Sjdp for (p = o->link_order_head; 409433965Sjdp p != (struct bfd_link_order *) NULL; 409533965Sjdp p = p->next) 409633965Sjdp { 409733965Sjdp asection *input_section; 409833965Sjdp bfd *input_bfd; 409933965Sjdp const struct ecoff_debug_swap *input_swap; 410033965Sjdp struct ecoff_debug_info input_debug; 410133965Sjdp char *eraw_src; 410233965Sjdp char *eraw_end; 410333965Sjdp 410433965Sjdp if (p->type != bfd_indirect_link_order) 410533965Sjdp { 410633965Sjdp if (p->type == bfd_fill_link_order) 410733965Sjdp continue; 410833965Sjdp abort (); 410933965Sjdp } 411033965Sjdp 411133965Sjdp input_section = p->u.indirect.section; 411233965Sjdp input_bfd = input_section->owner; 411333965Sjdp 411433965Sjdp if (bfd_get_flavour (input_bfd) != bfd_target_elf_flavour 411533965Sjdp || (get_elf_backend_data (input_bfd) 411633965Sjdp ->elf_backend_ecoff_debug_swap) == NULL) 411733965Sjdp { 411833965Sjdp /* I don't know what a non ALPHA ELF bfd would be 411933965Sjdp doing with a .mdebug section, but I don't really 412033965Sjdp want to deal with it. */ 412133965Sjdp continue; 412233965Sjdp } 412333965Sjdp 412433965Sjdp input_swap = (get_elf_backend_data (input_bfd) 412533965Sjdp ->elf_backend_ecoff_debug_swap); 412633965Sjdp 412733965Sjdp BFD_ASSERT (p->size == input_section->_raw_size); 412833965Sjdp 412933965Sjdp /* The ECOFF linking code expects that we have already 413033965Sjdp read in the debugging information and set up an 413133965Sjdp ecoff_debug_info structure, so we do that now. */ 413233965Sjdp if (!elf64_alpha_read_ecoff_info (input_bfd, input_section, 413333965Sjdp &input_debug)) 413433965Sjdp return false; 413533965Sjdp 413633965Sjdp if (! (bfd_ecoff_debug_accumulate 413733965Sjdp (mdebug_handle, abfd, &debug, swap, input_bfd, 413833965Sjdp &input_debug, input_swap, info))) 413933965Sjdp return false; 414033965Sjdp 414133965Sjdp /* Loop through the external symbols. For each one with 414233965Sjdp interesting information, try to find the symbol in 414333965Sjdp the linker global hash table and save the information 414433965Sjdp for the output external symbols. */ 414533965Sjdp eraw_src = input_debug.external_ext; 414633965Sjdp eraw_end = (eraw_src 414733965Sjdp + (input_debug.symbolic_header.iextMax 414833965Sjdp * input_swap->external_ext_size)); 414933965Sjdp for (; 415033965Sjdp eraw_src < eraw_end; 415133965Sjdp eraw_src += input_swap->external_ext_size) 415233965Sjdp { 415333965Sjdp EXTR ext; 415433965Sjdp const char *name; 415533965Sjdp struct alpha_elf_link_hash_entry *h; 415633965Sjdp 415733965Sjdp (*input_swap->swap_ext_in) (input_bfd, (PTR) eraw_src, &ext); 415833965Sjdp if (ext.asym.sc == scNil 415933965Sjdp || ext.asym.sc == scUndefined 416033965Sjdp || ext.asym.sc == scSUndefined) 416133965Sjdp continue; 416233965Sjdp 416333965Sjdp name = input_debug.ssext + ext.asym.iss; 416433965Sjdp h = alpha_elf_link_hash_lookup (alpha_elf_hash_table (info), 416533965Sjdp name, false, false, true); 416633965Sjdp if (h == NULL || h->esym.ifd != -2) 416733965Sjdp continue; 416833965Sjdp 416933965Sjdp if (ext.ifd != -1) 417033965Sjdp { 417133965Sjdp BFD_ASSERT (ext.ifd 417233965Sjdp < input_debug.symbolic_header.ifdMax); 417333965Sjdp ext.ifd = input_debug.ifdmap[ext.ifd]; 417433965Sjdp } 417533965Sjdp 417633965Sjdp h->esym = ext; 417733965Sjdp } 417833965Sjdp 417933965Sjdp /* Free up the information we just read. */ 418033965Sjdp free (input_debug.line); 418133965Sjdp free (input_debug.external_dnr); 418233965Sjdp free (input_debug.external_pdr); 418333965Sjdp free (input_debug.external_sym); 418433965Sjdp free (input_debug.external_opt); 418533965Sjdp free (input_debug.external_aux); 418633965Sjdp free (input_debug.ss); 418733965Sjdp free (input_debug.ssext); 418833965Sjdp free (input_debug.external_fdr); 418933965Sjdp free (input_debug.external_rfd); 419033965Sjdp free (input_debug.external_ext); 419133965Sjdp 419233965Sjdp /* Hack: reset the SEC_HAS_CONTENTS flag so that 419333965Sjdp elf_link_input_bfd ignores this section. */ 419433965Sjdp input_section->flags &=~ SEC_HAS_CONTENTS; 419533965Sjdp } 419633965Sjdp 419733965Sjdp /* Build the external symbol information. */ 419833965Sjdp einfo.abfd = abfd; 419933965Sjdp einfo.info = info; 420033965Sjdp einfo.debug = &debug; 420133965Sjdp einfo.swap = swap; 420233965Sjdp einfo.failed = false; 420333965Sjdp elf_link_hash_traverse (elf_hash_table (info), 420433965Sjdp elf64_alpha_output_extsym, 420533965Sjdp (PTR) &einfo); 420633965Sjdp if (einfo.failed) 420733965Sjdp return false; 420833965Sjdp 420933965Sjdp /* Set the size of the .mdebug section. */ 421033965Sjdp o->_raw_size = bfd_ecoff_debug_size (abfd, &debug, swap); 421133965Sjdp 421233965Sjdp /* Skip this section later on (I don't think this currently 421333965Sjdp matters, but someday it might). */ 421433965Sjdp o->link_order_head = (struct bfd_link_order *) NULL; 421533965Sjdp 421633965Sjdp mdebug_sec = o; 421733965Sjdp } 421833965Sjdp } 421933965Sjdp 422033965Sjdp /* Invoke the regular ELF backend linker to do all the work. */ 422133965Sjdp if (! bfd_elf64_bfd_final_link (abfd, info)) 422233965Sjdp return false; 422333965Sjdp 422433965Sjdp /* Now write out the computed sections. */ 422533965Sjdp 422633965Sjdp /* The .got subsections... */ 422733965Sjdp { 422833965Sjdp bfd *i, *dynobj = elf_hash_table(info)->dynobj; 422933965Sjdp for (i = alpha_elf_hash_table(info)->got_list; 423033965Sjdp i != NULL; 423133965Sjdp i = alpha_elf_tdata(i)->got_link_next) 423233965Sjdp { 423333965Sjdp asection *sgot; 423433965Sjdp 423533965Sjdp /* elf_bfd_final_link already did everything in dynobj. */ 423633965Sjdp if (i == dynobj) 423733965Sjdp continue; 423833965Sjdp 423933965Sjdp sgot = alpha_elf_tdata(i)->got; 424033965Sjdp if (! bfd_set_section_contents (abfd, sgot->output_section, 424189862Sobrien sgot->contents, 424289862Sobrien (file_ptr) sgot->output_offset, 424333965Sjdp sgot->_raw_size)) 424433965Sjdp return false; 424533965Sjdp } 424633965Sjdp } 424733965Sjdp 424833965Sjdp if (mdebug_sec != (asection *) NULL) 424933965Sjdp { 425033965Sjdp BFD_ASSERT (abfd->output_has_begun); 425133965Sjdp if (! bfd_ecoff_write_accumulated_debug (mdebug_handle, abfd, &debug, 425233965Sjdp swap, info, 425333965Sjdp mdebug_sec->filepos)) 425433965Sjdp return false; 425533965Sjdp 425633965Sjdp bfd_ecoff_debug_free (mdebug_handle, abfd, &debug, swap, info); 425733965Sjdp } 425833965Sjdp 425989862Sobrien return true; 426089862Sobrien} 426133965Sjdp 426289862Sobrienstatic enum elf_reloc_type_class 426389862Sobrienelf64_alpha_reloc_type_class (rela) 426489862Sobrien const Elf_Internal_Rela *rela; 426589862Sobrien{ 426689862Sobrien switch ((int) ELF64_R_TYPE (rela->r_info)) 426733965Sjdp { 426889862Sobrien case R_ALPHA_RELATIVE: 426989862Sobrien return reloc_class_relative; 427089862Sobrien case R_ALPHA_JMP_SLOT: 427189862Sobrien return reloc_class_plt; 427289862Sobrien case R_ALPHA_COPY: 427389862Sobrien return reloc_class_copy; 427489862Sobrien default: 427589862Sobrien return reloc_class_normal; 427633965Sjdp } 427733965Sjdp} 427833965Sjdp 427933965Sjdp/* ECOFF swapping routines. These are used when dealing with the 428033965Sjdp .mdebug section, which is in the ECOFF debugging format. Copied 428177303Sobrien from elf32-mips.c. */ 428233965Sjdpstatic const struct ecoff_debug_swap 428333965Sjdpelf64_alpha_ecoff_debug_swap = 428433965Sjdp{ 428533965Sjdp /* Symbol table magic number. */ 428633965Sjdp magicSym2, 428733965Sjdp /* Alignment of debugging information. E.g., 4. */ 428833965Sjdp 8, 428933965Sjdp /* Sizes of external symbolic information. */ 429033965Sjdp sizeof (struct hdr_ext), 429133965Sjdp sizeof (struct dnr_ext), 429233965Sjdp sizeof (struct pdr_ext), 429333965Sjdp sizeof (struct sym_ext), 429433965Sjdp sizeof (struct opt_ext), 429533965Sjdp sizeof (struct fdr_ext), 429633965Sjdp sizeof (struct rfd_ext), 429733965Sjdp sizeof (struct ext_ext), 429833965Sjdp /* Functions to swap in external symbolic data. */ 429933965Sjdp ecoff_swap_hdr_in, 430033965Sjdp ecoff_swap_dnr_in, 430133965Sjdp ecoff_swap_pdr_in, 430233965Sjdp ecoff_swap_sym_in, 430333965Sjdp ecoff_swap_opt_in, 430433965Sjdp ecoff_swap_fdr_in, 430533965Sjdp ecoff_swap_rfd_in, 430633965Sjdp ecoff_swap_ext_in, 430733965Sjdp _bfd_ecoff_swap_tir_in, 430833965Sjdp _bfd_ecoff_swap_rndx_in, 430933965Sjdp /* Functions to swap out external symbolic data. */ 431033965Sjdp ecoff_swap_hdr_out, 431133965Sjdp ecoff_swap_dnr_out, 431233965Sjdp ecoff_swap_pdr_out, 431333965Sjdp ecoff_swap_sym_out, 431433965Sjdp ecoff_swap_opt_out, 431533965Sjdp ecoff_swap_fdr_out, 431633965Sjdp ecoff_swap_rfd_out, 431733965Sjdp ecoff_swap_ext_out, 431833965Sjdp _bfd_ecoff_swap_tir_out, 431933965Sjdp _bfd_ecoff_swap_rndx_out, 432033965Sjdp /* Function to read in symbolic data. */ 432133965Sjdp elf64_alpha_read_ecoff_info 432233965Sjdp}; 432333965Sjdp 432477303Sobrien/* Use a non-standard hash bucket size of 8. */ 432577303Sobrien 432677303Sobrienconst struct elf_size_info alpha_elf_size_info = 432777303Sobrien{ 432877303Sobrien sizeof (Elf64_External_Ehdr), 432977303Sobrien sizeof (Elf64_External_Phdr), 433077303Sobrien sizeof (Elf64_External_Shdr), 433177303Sobrien sizeof (Elf64_External_Rel), 433277303Sobrien sizeof (Elf64_External_Rela), 433377303Sobrien sizeof (Elf64_External_Sym), 433477303Sobrien sizeof (Elf64_External_Dyn), 433577303Sobrien sizeof (Elf_External_Note), 433677303Sobrien 8, 433777303Sobrien 1, 433877303Sobrien 64, 8, 433977303Sobrien ELFCLASS64, EV_CURRENT, 434077303Sobrien bfd_elf64_write_out_phdrs, 434177303Sobrien bfd_elf64_write_shdrs_and_ehdr, 434277303Sobrien bfd_elf64_write_relocs, 434377303Sobrien bfd_elf64_swap_symbol_out, 434477303Sobrien bfd_elf64_slurp_reloc_table, 434577303Sobrien bfd_elf64_slurp_symbol_table, 434677303Sobrien bfd_elf64_swap_dyn_in, 434777303Sobrien bfd_elf64_swap_dyn_out, 434877303Sobrien NULL, 434977303Sobrien NULL, 435077303Sobrien NULL, 435177303Sobrien NULL 435277303Sobrien}; 435377303Sobrien 435433965Sjdp#define TARGET_LITTLE_SYM bfd_elf64_alpha_vec 435533965Sjdp#define TARGET_LITTLE_NAME "elf64-alpha" 435633965Sjdp#define ELF_ARCH bfd_arch_alpha 435778833Sobrien#define ELF_MACHINE_CODE EM_ALPHA 435878833Sobrien#define ELF_MAXPAGESIZE 0x10000 435933965Sjdp 436033965Sjdp#define bfd_elf64_bfd_link_hash_table_create \ 436133965Sjdp elf64_alpha_bfd_link_hash_table_create 436233965Sjdp 436333965Sjdp#define bfd_elf64_bfd_reloc_type_lookup \ 436433965Sjdp elf64_alpha_bfd_reloc_type_lookup 436533965Sjdp#define elf_info_to_howto \ 436633965Sjdp elf64_alpha_info_to_howto 436733965Sjdp 436833965Sjdp#define bfd_elf64_mkobject \ 436933965Sjdp elf64_alpha_mkobject 437033965Sjdp#define elf_backend_object_p \ 437133965Sjdp elf64_alpha_object_p 437233965Sjdp 437333965Sjdp#define elf_backend_section_from_shdr \ 437433965Sjdp elf64_alpha_section_from_shdr 437589862Sobrien#define elf_backend_section_flags \ 437689862Sobrien elf64_alpha_section_flags 437733965Sjdp#define elf_backend_fake_sections \ 437833965Sjdp elf64_alpha_fake_sections 437933965Sjdp 438033965Sjdp#define bfd_elf64_bfd_is_local_label_name \ 438133965Sjdp elf64_alpha_is_local_label_name 438233965Sjdp#define bfd_elf64_find_nearest_line \ 438333965Sjdp elf64_alpha_find_nearest_line 438460510Sobrien#define bfd_elf64_bfd_relax_section \ 438560510Sobrien elf64_alpha_relax_section 438633965Sjdp 438760510Sobrien#define elf_backend_add_symbol_hook \ 438860510Sobrien elf64_alpha_add_symbol_hook 438933965Sjdp#define elf_backend_check_relocs \ 439033965Sjdp elf64_alpha_check_relocs 439133965Sjdp#define elf_backend_create_dynamic_sections \ 439233965Sjdp elf64_alpha_create_dynamic_sections 439333965Sjdp#define elf_backend_adjust_dynamic_symbol \ 439433965Sjdp elf64_alpha_adjust_dynamic_symbol 439533965Sjdp#define elf_backend_always_size_sections \ 439633965Sjdp elf64_alpha_always_size_sections 439733965Sjdp#define elf_backend_size_dynamic_sections \ 439833965Sjdp elf64_alpha_size_dynamic_sections 439933965Sjdp#define elf_backend_relocate_section \ 440033965Sjdp elf64_alpha_relocate_section 440133965Sjdp#define elf_backend_finish_dynamic_symbol \ 440233965Sjdp elf64_alpha_finish_dynamic_symbol 440333965Sjdp#define elf_backend_finish_dynamic_sections \ 440433965Sjdp elf64_alpha_finish_dynamic_sections 440533965Sjdp#define bfd_elf64_bfd_final_link \ 440633965Sjdp elf64_alpha_final_link 440789862Sobrien#define elf_backend_reloc_type_class \ 440889862Sobrien elf64_alpha_reloc_type_class 440933965Sjdp 441033965Sjdp#define elf_backend_ecoff_debug_swap \ 441133965Sjdp &elf64_alpha_ecoff_debug_swap 441233965Sjdp 441377303Sobrien#define elf_backend_size_info \ 441477303Sobrien alpha_elf_size_info 441577303Sobrien 441677303Sobrien/* A few constants that determine how the .plt section is set up. */ 441733965Sjdp#define elf_backend_want_got_plt 0 441833965Sjdp#define elf_backend_plt_readonly 0 441933965Sjdp#define elf_backend_want_plt_sym 1 442060510Sobrien#define elf_backend_got_header_size 0 442160510Sobrien#define elf_backend_plt_header_size PLT_HEADER_SIZE 442233965Sjdp 442333965Sjdp#include "elf64-target.h" 4424