elf64-alpha.c revision 89862
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 89862 2002-01-27 12:08:15Z 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, 73733965Sjdp true) 73833965Sjdp}; 73933965Sjdp 74033965Sjdp/* A relocation function which doesn't do anything. */ 74133965Sjdp 74233965Sjdpstatic bfd_reloc_status_type 74333965Sjdpelf64_alpha_reloc_nil (abfd, reloc, sym, data, sec, output_bfd, error_message) 74478833Sobrien bfd *abfd ATTRIBUTE_UNUSED; 74533965Sjdp arelent *reloc; 74678833Sobrien asymbol *sym ATTRIBUTE_UNUSED; 74778833Sobrien PTR data ATTRIBUTE_UNUSED; 74833965Sjdp asection *sec; 74933965Sjdp bfd *output_bfd; 75078833Sobrien char **error_message ATTRIBUTE_UNUSED; 75133965Sjdp{ 75233965Sjdp if (output_bfd) 75333965Sjdp reloc->address += sec->output_offset; 75433965Sjdp return bfd_reloc_ok; 75533965Sjdp} 75633965Sjdp 75733965Sjdp/* A relocation function used for an unsupported reloc. */ 75833965Sjdp 75933965Sjdpstatic bfd_reloc_status_type 76033965Sjdpelf64_alpha_reloc_bad (abfd, reloc, sym, data, sec, output_bfd, error_message) 76178833Sobrien bfd *abfd ATTRIBUTE_UNUSED; 76233965Sjdp arelent *reloc; 76378833Sobrien asymbol *sym ATTRIBUTE_UNUSED; 76478833Sobrien PTR data ATTRIBUTE_UNUSED; 76533965Sjdp asection *sec; 76633965Sjdp bfd *output_bfd; 76778833Sobrien char **error_message ATTRIBUTE_UNUSED; 76833965Sjdp{ 76933965Sjdp if (output_bfd) 77033965Sjdp reloc->address += sec->output_offset; 77133965Sjdp return bfd_reloc_notsupported; 77233965Sjdp} 77333965Sjdp 77433965Sjdp/* Do the work of the GPDISP relocation. */ 77533965Sjdp 77633965Sjdpstatic bfd_reloc_status_type 77733965Sjdpelf64_alpha_do_reloc_gpdisp (abfd, gpdisp, p_ldah, p_lda) 77833965Sjdp bfd *abfd; 77933965Sjdp bfd_vma gpdisp; 78033965Sjdp bfd_byte *p_ldah; 78133965Sjdp bfd_byte *p_lda; 78233965Sjdp{ 78333965Sjdp bfd_reloc_status_type ret = bfd_reloc_ok; 78433965Sjdp bfd_vma addend; 78533965Sjdp unsigned long i_ldah, i_lda; 78633965Sjdp 78733965Sjdp i_ldah = bfd_get_32 (abfd, p_ldah); 78833965Sjdp i_lda = bfd_get_32 (abfd, p_lda); 78933965Sjdp 79033965Sjdp /* Complain if the instructions are not correct. */ 79133965Sjdp if (((i_ldah >> 26) & 0x3f) != 0x09 79233965Sjdp || ((i_lda >> 26) & 0x3f) != 0x08) 79333965Sjdp ret = bfd_reloc_dangerous; 79433965Sjdp 79533965Sjdp /* Extract the user-supplied offset, mirroring the sign extensions 79633965Sjdp that the instructions perform. */ 79733965Sjdp addend = ((i_ldah & 0xffff) << 16) | (i_lda & 0xffff); 79833965Sjdp addend = (addend ^ 0x80008000) - 0x80008000; 79933965Sjdp 80033965Sjdp gpdisp += addend; 80133965Sjdp 80248850Sdfr if ((bfd_signed_vma) gpdisp < -(bfd_signed_vma) 0x80000000 80348850Sdfr || (bfd_signed_vma) gpdisp >= (bfd_signed_vma) 0x7fff8000) 80433965Sjdp ret = bfd_reloc_overflow; 80533965Sjdp 80633965Sjdp /* compensate for the sign extension again. */ 80733965Sjdp i_ldah = ((i_ldah & 0xffff0000) 80833965Sjdp | (((gpdisp >> 16) + ((gpdisp >> 15) & 1)) & 0xffff)); 80933965Sjdp i_lda = (i_lda & 0xffff0000) | (gpdisp & 0xffff); 81033965Sjdp 81189862Sobrien bfd_put_32 (abfd, (bfd_vma) i_ldah, p_ldah); 81289862Sobrien bfd_put_32 (abfd, (bfd_vma) i_lda, p_lda); 81333965Sjdp 81433965Sjdp return ret; 81533965Sjdp} 81633965Sjdp 81733965Sjdp/* The special function for the GPDISP reloc. */ 81833965Sjdp 81933965Sjdpstatic bfd_reloc_status_type 82033965Sjdpelf64_alpha_reloc_gpdisp (abfd, reloc_entry, sym, data, input_section, 82133965Sjdp output_bfd, err_msg) 82233965Sjdp bfd *abfd; 82333965Sjdp arelent *reloc_entry; 82478833Sobrien asymbol *sym ATTRIBUTE_UNUSED; 82533965Sjdp PTR data; 82633965Sjdp asection *input_section; 82733965Sjdp bfd *output_bfd; 82833965Sjdp char **err_msg; 82933965Sjdp{ 83033965Sjdp bfd_reloc_status_type ret; 83133965Sjdp bfd_vma gp, relocation; 83233965Sjdp bfd_byte *p_ldah, *p_lda; 83333965Sjdp 83433965Sjdp /* Don't do anything if we're not doing a final link. */ 83533965Sjdp if (output_bfd) 83633965Sjdp { 83733965Sjdp reloc_entry->address += input_section->output_offset; 83833965Sjdp return bfd_reloc_ok; 83933965Sjdp } 84033965Sjdp 84133965Sjdp if (reloc_entry->address > input_section->_cooked_size || 84233965Sjdp reloc_entry->address + reloc_entry->addend > input_section->_cooked_size) 84333965Sjdp return bfd_reloc_outofrange; 84433965Sjdp 84533965Sjdp /* The gp used in the portion of the output object to which this 84633965Sjdp input object belongs is cached on the input bfd. */ 84733965Sjdp gp = _bfd_get_gp_value (abfd); 84833965Sjdp 84933965Sjdp relocation = (input_section->output_section->vma 85033965Sjdp + input_section->output_offset 85133965Sjdp + reloc_entry->address); 85233965Sjdp 85333965Sjdp p_ldah = (bfd_byte *) data + reloc_entry->address; 85433965Sjdp p_lda = p_ldah + reloc_entry->addend; 85533965Sjdp 85633965Sjdp ret = elf64_alpha_do_reloc_gpdisp (abfd, gp - relocation, p_ldah, p_lda); 85733965Sjdp 85833965Sjdp /* Complain if the instructions are not correct. */ 85933965Sjdp if (ret == bfd_reloc_dangerous) 86060510Sobrien *err_msg = _("GPDISP relocation did not find ldah and lda instructions"); 86133965Sjdp 86233965Sjdp return ret; 86333965Sjdp} 86433965Sjdp 86533965Sjdp/* A mapping from BFD reloc types to Alpha ELF reloc types. */ 86633965Sjdp 86733965Sjdpstruct elf_reloc_map 86833965Sjdp{ 86933965Sjdp bfd_reloc_code_real_type bfd_reloc_val; 87033965Sjdp int elf_reloc_val; 87133965Sjdp}; 87233965Sjdp 87333965Sjdpstatic const struct elf_reloc_map elf64_alpha_reloc_map[] = 87433965Sjdp{ 87589862Sobrien {BFD_RELOC_NONE, R_ALPHA_NONE}, 87689862Sobrien {BFD_RELOC_32, R_ALPHA_REFLONG}, 87789862Sobrien {BFD_RELOC_64, R_ALPHA_REFQUAD}, 87889862Sobrien {BFD_RELOC_CTOR, R_ALPHA_REFQUAD}, 87989862Sobrien {BFD_RELOC_GPREL32, R_ALPHA_GPREL32}, 88089862Sobrien {BFD_RELOC_ALPHA_ELF_LITERAL, R_ALPHA_LITERAL}, 88189862Sobrien {BFD_RELOC_ALPHA_LITUSE, R_ALPHA_LITUSE}, 88289862Sobrien {BFD_RELOC_ALPHA_GPDISP, R_ALPHA_GPDISP}, 88389862Sobrien {BFD_RELOC_23_PCREL_S2, R_ALPHA_BRADDR}, 88489862Sobrien {BFD_RELOC_ALPHA_HINT, R_ALPHA_HINT}, 88589862Sobrien {BFD_RELOC_16_PCREL, R_ALPHA_SREL16}, 88689862Sobrien {BFD_RELOC_32_PCREL, R_ALPHA_SREL32}, 88789862Sobrien {BFD_RELOC_64_PCREL, R_ALPHA_SREL64}, 88889862Sobrien {BFD_RELOC_ALPHA_GPREL_HI16, R_ALPHA_GPRELHIGH}, 88989862Sobrien {BFD_RELOC_ALPHA_GPREL_LO16, R_ALPHA_GPRELLOW}, 89089862Sobrien {BFD_RELOC_GPREL16, R_ALPHA_GPREL16}, 89133965Sjdp}; 89233965Sjdp 89333965Sjdp/* Given a BFD reloc type, return a HOWTO structure. */ 89433965Sjdp 89533965Sjdpstatic reloc_howto_type * 89633965Sjdpelf64_alpha_bfd_reloc_type_lookup (abfd, code) 89778833Sobrien bfd *abfd ATTRIBUTE_UNUSED; 89833965Sjdp bfd_reloc_code_real_type code; 89933965Sjdp{ 90033965Sjdp const struct elf_reloc_map *i, *e; 90133965Sjdp i = e = elf64_alpha_reloc_map; 90233965Sjdp e += sizeof (elf64_alpha_reloc_map) / sizeof (struct elf_reloc_map); 90333965Sjdp for (; i != e; ++i) 90433965Sjdp { 90533965Sjdp if (i->bfd_reloc_val == code) 90633965Sjdp return &elf64_alpha_howto_table[i->elf_reloc_val]; 90733965Sjdp } 90833965Sjdp return 0; 90933965Sjdp} 91033965Sjdp 91133965Sjdp/* Given an Alpha ELF reloc type, fill in an arelent structure. */ 91233965Sjdp 91333965Sjdpstatic void 91433965Sjdpelf64_alpha_info_to_howto (abfd, cache_ptr, dst) 91578833Sobrien bfd *abfd ATTRIBUTE_UNUSED; 91633965Sjdp arelent *cache_ptr; 91733965Sjdp Elf64_Internal_Rela *dst; 91833965Sjdp{ 91933965Sjdp unsigned r_type; 92033965Sjdp 92133965Sjdp r_type = ELF64_R_TYPE(dst->r_info); 92233965Sjdp BFD_ASSERT (r_type < (unsigned int) R_ALPHA_max); 92333965Sjdp cache_ptr->howto = &elf64_alpha_howto_table[r_type]; 92433965Sjdp} 92533965Sjdp 92677303Sobrien/* These functions do relaxation for Alpha ELF. 92760510Sobrien 92860510Sobrien Currently I'm only handling what I can do with existing compiler 92960510Sobrien and assembler support, which means no instructions are removed, 93060510Sobrien though some may be nopped. At this time GCC does not emit enough 93160510Sobrien information to do all of the relaxing that is possible. It will 93260510Sobrien take some not small amount of work for that to happen. 93360510Sobrien 93460510Sobrien There are a couple of interesting papers that I once read on this 93560510Sobrien subject, that I cannot find references to at the moment, that 93660510Sobrien related to Alpha in particular. They are by David Wall, then of 93760510Sobrien DEC WRL. */ 93860510Sobrien 93960510Sobrien#define OP_LDA 0x08 94060510Sobrien#define OP_LDAH 0x09 94160510Sobrien#define INSN_JSR 0x68004000 94260510Sobrien#define INSN_JSR_MASK 0xfc00c000 94360510Sobrien#define OP_LDQ 0x29 94460510Sobrien#define OP_BR 0x30 94560510Sobrien#define OP_BSR 0x34 94689862Sobrien#define INSN_UNOP 0x2ffe0000 94760510Sobrien 94860510Sobrienstruct alpha_relax_info 94960510Sobrien{ 95060510Sobrien bfd *abfd; 95160510Sobrien asection *sec; 95260510Sobrien bfd_byte *contents; 95360510Sobrien Elf_Internal_Rela *relocs, *relend; 95460510Sobrien struct bfd_link_info *link_info; 95560510Sobrien boolean changed_contents; 95660510Sobrien boolean changed_relocs; 95760510Sobrien bfd_vma gp; 95860510Sobrien bfd *gotobj; 95960510Sobrien asection *tsec; 96060510Sobrien struct alpha_elf_link_hash_entry *h; 96160510Sobrien struct alpha_elf_got_entry *gotent; 96260510Sobrien unsigned char other; 96360510Sobrien}; 96460510Sobrien 96560510Sobrienstatic Elf_Internal_Rela * elf64_alpha_relax_with_lituse 96677303Sobrien PARAMS((struct alpha_relax_info *info, bfd_vma symval, 96760510Sobrien Elf_Internal_Rela *irel, Elf_Internal_Rela *irelend)); 96860510Sobrien 96960510Sobrienstatic boolean elf64_alpha_relax_without_lituse 97077303Sobrien PARAMS((struct alpha_relax_info *info, bfd_vma symval, 97160510Sobrien Elf_Internal_Rela *irel)); 97260510Sobrien 97360510Sobrienstatic bfd_vma elf64_alpha_relax_opt_call 97460510Sobrien PARAMS((struct alpha_relax_info *info, bfd_vma symval)); 97560510Sobrien 97660510Sobrienstatic boolean elf64_alpha_relax_section 97760510Sobrien PARAMS((bfd *abfd, asection *sec, struct bfd_link_info *link_info, 97860510Sobrien boolean *again)); 97960510Sobrien 98060510Sobrienstatic Elf_Internal_Rela * 98160510Sobrienelf64_alpha_find_reloc_at_ofs (rel, relend, offset, type) 98260510Sobrien Elf_Internal_Rela *rel, *relend; 98360510Sobrien bfd_vma offset; 98460510Sobrien int type; 98560510Sobrien{ 98660510Sobrien while (rel < relend) 98760510Sobrien { 98889862Sobrien if (rel->r_offset == offset 98989862Sobrien && ELF64_R_TYPE (rel->r_info) == (unsigned int) type) 99060510Sobrien return rel; 99160510Sobrien ++rel; 99260510Sobrien } 99360510Sobrien return NULL; 99460510Sobrien} 99560510Sobrien 99660510Sobrienstatic Elf_Internal_Rela * 99760510Sobrienelf64_alpha_relax_with_lituse (info, symval, irel, irelend) 99860510Sobrien struct alpha_relax_info *info; 99960510Sobrien bfd_vma symval; 100060510Sobrien Elf_Internal_Rela *irel, *irelend; 100160510Sobrien{ 100260510Sobrien Elf_Internal_Rela *urel; 100360510Sobrien int flags, count, i; 100460510Sobrien bfd_signed_vma disp; 100560510Sobrien boolean fits16; 100660510Sobrien boolean fits32; 100760510Sobrien boolean lit_reused = false; 100860510Sobrien boolean all_optimized = true; 100960510Sobrien unsigned int lit_insn; 101060510Sobrien 101160510Sobrien lit_insn = bfd_get_32 (info->abfd, info->contents + irel->r_offset); 101260510Sobrien if (lit_insn >> 26 != OP_LDQ) 101360510Sobrien { 101460510Sobrien ((*_bfd_error_handler) 101560510Sobrien ("%s: %s+0x%lx: warning: LITERAL relocation against unexpected insn", 101689862Sobrien bfd_archive_filename (info->abfd), info->sec->name, 101789862Sobrien (unsigned long) irel->r_offset)); 101860510Sobrien return irel; 101960510Sobrien } 102060510Sobrien 102160510Sobrien /* Summarize how this particular LITERAL is used. */ 102260510Sobrien for (urel = irel+1, flags = count = 0; urel < irelend; ++urel, ++count) 102360510Sobrien { 102460510Sobrien if (ELF64_R_TYPE (urel->r_info) != R_ALPHA_LITUSE) 102560510Sobrien break; 102689862Sobrien if (urel->r_addend <= 3) 102760510Sobrien flags |= 1 << urel->r_addend; 102860510Sobrien } 102960510Sobrien 103077303Sobrien /* A little preparation for the loop... */ 103160510Sobrien disp = symval - info->gp; 103260510Sobrien 103360510Sobrien for (urel = irel+1, i = 0; i < count; ++i, ++urel) 103460510Sobrien { 103560510Sobrien unsigned int insn; 103677303Sobrien int insn_disp; 103777303Sobrien bfd_signed_vma xdisp; 103877303Sobrien 103960510Sobrien insn = bfd_get_32 (info->abfd, info->contents + urel->r_offset); 104060510Sobrien 104160510Sobrien switch (urel->r_addend) 104260510Sobrien { 104360510Sobrien default: /* 0 = ADDRESS FORMAT */ 104460510Sobrien /* This type is really just a placeholder to note that all 104560510Sobrien uses cannot be optimized, but to still allow some. */ 104660510Sobrien all_optimized = false; 104760510Sobrien break; 104860510Sobrien 104960510Sobrien case 1: /* MEM FORMAT */ 105060510Sobrien /* We can always optimize 16-bit displacements. */ 105177303Sobrien 105277303Sobrien /* Extract the displacement from the instruction, sign-extending 105377303Sobrien it if necessary, then test whether it is within 16 or 32 bits 105477303Sobrien displacement from GP. */ 105577303Sobrien insn_disp = insn & 0x0000ffff; 105677303Sobrien if (insn_disp & 0x00008000) 105777303Sobrien insn_disp |= 0xffff0000; /* Negative: sign-extend. */ 105877303Sobrien 105977303Sobrien xdisp = disp + insn_disp; 106077303Sobrien fits16 = (xdisp >= - (bfd_signed_vma) 0x00008000 && xdisp < 0x00008000); 106177303Sobrien fits32 = (xdisp >= - (bfd_signed_vma) 0x80000000 && xdisp < 0x7fff8000); 106277303Sobrien 106360510Sobrien if (fits16) 106460510Sobrien { 106577303Sobrien /* Take the op code and dest from this insn, take the base 106660510Sobrien register from the literal insn. Leave the offset alone. */ 106777303Sobrien insn = (insn & 0xffe0ffff) | (lit_insn & 0x001f0000); 106860510Sobrien urel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), 106989862Sobrien R_ALPHA_GPREL16); 107060510Sobrien urel->r_addend = irel->r_addend; 107160510Sobrien info->changed_relocs = true; 107260510Sobrien 107389862Sobrien bfd_put_32 (info->abfd, (bfd_vma) insn, 107489862Sobrien info->contents + urel->r_offset); 107560510Sobrien info->changed_contents = true; 107660510Sobrien } 107760510Sobrien 107860510Sobrien /* If all mem+byte, we can optimize 32-bit mem displacements. */ 107960510Sobrien else if (fits32 && !(flags & ~6)) 108060510Sobrien { 108177303Sobrien /* FIXME: sanity check that lit insn Ra is mem insn Rb. */ 108260510Sobrien 108360510Sobrien irel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), 108460510Sobrien R_ALPHA_GPRELHIGH); 108560510Sobrien lit_insn = (OP_LDAH << 26) | (lit_insn & 0x03ff0000); 108689862Sobrien bfd_put_32 (info->abfd, (bfd_vma) lit_insn, 108760510Sobrien info->contents + irel->r_offset); 108860510Sobrien lit_reused = true; 108960510Sobrien info->changed_contents = true; 109060510Sobrien 109160510Sobrien urel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), 109260510Sobrien R_ALPHA_GPRELLOW); 109360510Sobrien urel->r_addend = irel->r_addend; 109460510Sobrien info->changed_relocs = true; 109560510Sobrien } 109660510Sobrien else 109760510Sobrien all_optimized = false; 109860510Sobrien break; 109960510Sobrien 110060510Sobrien case 2: /* BYTE OFFSET FORMAT */ 110160510Sobrien /* We can always optimize byte instructions. */ 110260510Sobrien 110360510Sobrien /* FIXME: sanity check the insn for byte op. Check that the 110460510Sobrien literal dest reg is indeed Rb in the byte insn. */ 110560510Sobrien 110689862Sobrien insn &= ~ (unsigned) 0x001ff000; 110789862Sobrien insn |= ((symval & 7) << 13) | 0x1000; 110860510Sobrien 110960510Sobrien urel->r_info = ELF64_R_INFO (0, R_ALPHA_NONE); 111060510Sobrien urel->r_addend = 0; 111160510Sobrien info->changed_relocs = true; 111260510Sobrien 111389862Sobrien bfd_put_32 (info->abfd, (bfd_vma) insn, 111489862Sobrien info->contents + urel->r_offset); 111560510Sobrien info->changed_contents = true; 111660510Sobrien break; 111760510Sobrien 111860510Sobrien case 3: /* CALL FORMAT */ 111960510Sobrien { 112060510Sobrien /* If not zero, place to jump without needing pv. */ 112160510Sobrien bfd_vma optdest = elf64_alpha_relax_opt_call (info, symval); 112260510Sobrien bfd_vma org = (info->sec->output_section->vma 112360510Sobrien + info->sec->output_offset 112460510Sobrien + urel->r_offset + 4); 112560510Sobrien bfd_signed_vma odisp; 112660510Sobrien 112760510Sobrien odisp = (optdest ? optdest : symval) - org; 112860510Sobrien if (odisp >= -0x400000 && odisp < 0x400000) 112960510Sobrien { 113060510Sobrien Elf_Internal_Rela *xrel; 113160510Sobrien 113277303Sobrien /* Preserve branch prediction call stack when possible. */ 113360510Sobrien if ((insn & INSN_JSR_MASK) == INSN_JSR) 113460510Sobrien insn = (OP_BSR << 26) | (insn & 0x03e00000); 113560510Sobrien else 113660510Sobrien insn = (OP_BR << 26) | (insn & 0x03e00000); 113777303Sobrien 113860510Sobrien urel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), 113960510Sobrien R_ALPHA_BRADDR); 114060510Sobrien urel->r_addend = irel->r_addend; 114160510Sobrien 114260510Sobrien if (optdest) 114360510Sobrien urel->r_addend += optdest - symval; 114460510Sobrien else 114560510Sobrien all_optimized = false; 114660510Sobrien 114789862Sobrien bfd_put_32 (info->abfd, (bfd_vma) insn, 114889862Sobrien info->contents + urel->r_offset); 114960510Sobrien 115060510Sobrien /* Kill any HINT reloc that might exist for this insn. */ 115160510Sobrien xrel = (elf64_alpha_find_reloc_at_ofs 115277303Sobrien (info->relocs, info->relend, urel->r_offset, 115360510Sobrien R_ALPHA_HINT)); 115460510Sobrien if (xrel) 115560510Sobrien xrel->r_info = ELF64_R_INFO (0, R_ALPHA_NONE); 115660510Sobrien 115760510Sobrien info->changed_contents = true; 115860510Sobrien info->changed_relocs = true; 115960510Sobrien } 116060510Sobrien else 116160510Sobrien all_optimized = false; 116260510Sobrien 116389862Sobrien /* Even if the target is not in range for a direct branch, 116489862Sobrien if we share a GP, we can eliminate the gp reload. */ 116589862Sobrien if (optdest) 116689862Sobrien { 116789862Sobrien Elf_Internal_Rela *gpdisp 116889862Sobrien = (elf64_alpha_find_reloc_at_ofs 116989862Sobrien (irel, irelend, urel->r_offset + 4, R_ALPHA_GPDISP)); 117089862Sobrien if (gpdisp) 117189862Sobrien { 117289862Sobrien bfd_byte *p_ldah = info->contents + gpdisp->r_offset; 117389862Sobrien bfd_byte *p_lda = p_ldah + gpdisp->r_addend; 117489862Sobrien unsigned int ldah = bfd_get_32 (info->abfd, p_ldah); 117589862Sobrien unsigned int lda = bfd_get_32 (info->abfd, p_lda); 117660510Sobrien 117789862Sobrien /* Verify that the instruction is "ldah $29,0($26)". 117889862Sobrien Consider a function that ends in a noreturn call, 117989862Sobrien and that the next function begins with an ldgp, 118089862Sobrien and that by accident there is no padding between. 118189862Sobrien In that case the insn would use $27 as the base. */ 118289862Sobrien if (ldah == 0x27ba0000 && lda == 0x23bd0000) 118389862Sobrien { 118489862Sobrien bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP, p_ldah); 118589862Sobrien bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP, p_lda); 118689862Sobrien 118789862Sobrien gpdisp->r_info = ELF64_R_INFO (0, R_ALPHA_NONE); 118889862Sobrien info->changed_contents = true; 118989862Sobrien info->changed_relocs = true; 119089862Sobrien } 119189862Sobrien } 119289862Sobrien } 119360510Sobrien } 119460510Sobrien break; 119560510Sobrien } 119660510Sobrien } 119760510Sobrien 119860510Sobrien /* If all cases were optimized, we can reduce the use count on this 119960510Sobrien got entry by one, possibly eliminating it. */ 120060510Sobrien if (all_optimized) 120160510Sobrien { 120260510Sobrien info->gotent->use_count -= 1; 120360510Sobrien alpha_elf_tdata (info->gotent->gotobj)->total_got_entries -= 1; 120460510Sobrien if (!info->h) 120560510Sobrien alpha_elf_tdata (info->gotent->gotobj)->n_local_got_entries -= 1; 120660510Sobrien 120760510Sobrien /* If the literal instruction is no longer needed (it may have been 120860510Sobrien reused. We can eliminate it. 120960510Sobrien ??? For now, I don't want to deal with compacting the section, 121060510Sobrien so just nop it out. */ 121160510Sobrien if (!lit_reused) 121260510Sobrien { 121360510Sobrien irel->r_info = ELF64_R_INFO (0, R_ALPHA_NONE); 121460510Sobrien info->changed_relocs = true; 121560510Sobrien 121689862Sobrien bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP, 121789862Sobrien info->contents + irel->r_offset); 121860510Sobrien info->changed_contents = true; 121960510Sobrien } 122060510Sobrien } 122160510Sobrien 122260510Sobrien return irel + count; 122360510Sobrien} 122460510Sobrien 122560510Sobrienstatic bfd_vma 122660510Sobrienelf64_alpha_relax_opt_call (info, symval) 122760510Sobrien struct alpha_relax_info *info; 122860510Sobrien bfd_vma symval; 122960510Sobrien{ 123060510Sobrien /* If the function has the same gp, and we can identify that the 123160510Sobrien function does not use its function pointer, we can eliminate the 123260510Sobrien address load. */ 123360510Sobrien 123460510Sobrien /* If the symbol is marked NOPV, we are being told the function never 123560510Sobrien needs its procedure value. */ 123677303Sobrien if ((info->other & STO_ALPHA_STD_GPLOAD) == STO_ALPHA_NOPV) 123760510Sobrien return symval; 123860510Sobrien 123960510Sobrien /* If the symbol is marked STD_GP, we are being told the function does 124077303Sobrien a normal ldgp in the first two words. */ 124177303Sobrien else if ((info->other & STO_ALPHA_STD_GPLOAD) == STO_ALPHA_STD_GPLOAD) 124260510Sobrien ; 124360510Sobrien 124460510Sobrien /* Otherwise, we may be able to identify a GP load in the first two 124560510Sobrien words, which we can then skip. */ 124677303Sobrien else 124760510Sobrien { 124860510Sobrien Elf_Internal_Rela *tsec_relocs, *tsec_relend, *tsec_free, *gpdisp; 124960510Sobrien bfd_vma ofs; 125060510Sobrien 125177303Sobrien /* Load the relocations from the section that the target symbol is in. */ 125260510Sobrien if (info->sec == info->tsec) 125360510Sobrien { 125460510Sobrien tsec_relocs = info->relocs; 125560510Sobrien tsec_relend = info->relend; 125660510Sobrien tsec_free = NULL; 125760510Sobrien } 125860510Sobrien else 125960510Sobrien { 126060510Sobrien tsec_relocs = (_bfd_elf64_link_read_relocs 126160510Sobrien (info->abfd, info->tsec, (PTR) NULL, 126260510Sobrien (Elf_Internal_Rela *) NULL, 126360510Sobrien info->link_info->keep_memory)); 126460510Sobrien if (tsec_relocs == NULL) 126560510Sobrien return 0; 126660510Sobrien tsec_relend = tsec_relocs + info->tsec->reloc_count; 126760510Sobrien tsec_free = (info->link_info->keep_memory ? NULL : tsec_relocs); 126860510Sobrien } 126960510Sobrien 127060510Sobrien /* Recover the symbol's offset within the section. */ 127160510Sobrien ofs = (symval - info->tsec->output_section->vma 127260510Sobrien - info->tsec->output_offset); 127377303Sobrien 127460510Sobrien /* Look for a GPDISP reloc. */ 127560510Sobrien gpdisp = (elf64_alpha_find_reloc_at_ofs 127660510Sobrien (tsec_relocs, tsec_relend, ofs, R_ALPHA_GPDISP)); 127760510Sobrien 127860510Sobrien if (!gpdisp || gpdisp->r_addend != 4) 127960510Sobrien { 128060510Sobrien if (tsec_free) 128160510Sobrien free (tsec_free); 128260510Sobrien return 0; 128360510Sobrien } 128460510Sobrien if (tsec_free) 128560510Sobrien free (tsec_free); 128660510Sobrien } 128760510Sobrien 128877303Sobrien /* We've now determined that we can skip an initial gp load. Verify 128960510Sobrien that the call and the target use the same gp. */ 129060510Sobrien if (info->link_info->hash->creator != info->tsec->owner->xvec 129160510Sobrien || info->gotobj != alpha_elf_tdata (info->tsec->owner)->gotobj) 129260510Sobrien return 0; 129360510Sobrien 129460510Sobrien return symval + 8; 129560510Sobrien} 129660510Sobrien 129760510Sobrienstatic boolean 129860510Sobrienelf64_alpha_relax_without_lituse (info, symval, irel) 129960510Sobrien struct alpha_relax_info *info; 130060510Sobrien bfd_vma symval; 130160510Sobrien Elf_Internal_Rela *irel; 130260510Sobrien{ 130360510Sobrien unsigned int insn; 130460510Sobrien bfd_signed_vma disp; 130560510Sobrien 130660510Sobrien /* Get the instruction. */ 130760510Sobrien insn = bfd_get_32 (info->abfd, info->contents + irel->r_offset); 130860510Sobrien 130960510Sobrien if (insn >> 26 != OP_LDQ) 131060510Sobrien { 131160510Sobrien ((*_bfd_error_handler) 131260510Sobrien ("%s: %s+0x%lx: warning: LITERAL relocation against unexpected insn", 131389862Sobrien bfd_archive_filename (info->abfd), info->sec->name, 131460510Sobrien (unsigned long) irel->r_offset)); 131560510Sobrien return true; 131660510Sobrien } 131760510Sobrien 131860510Sobrien /* So we aren't told much. Do what we can with the address load and 131960510Sobrien fake the rest. All of the optimizations here require that the 132060510Sobrien offset from the GP fit in 16 bits. */ 132160510Sobrien 132260510Sobrien disp = symval - info->gp; 132360510Sobrien if (disp < -0x8000 || disp >= 0x8000) 132460510Sobrien return true; 132560510Sobrien 132660510Sobrien /* On the LITERAL instruction itself, consider exchanging 132760510Sobrien `ldq R,X(gp)' for `lda R,Y(gp)'. */ 132860510Sobrien 132960510Sobrien insn = (OP_LDA << 26) | (insn & 0x03ff0000); 133089862Sobrien bfd_put_32 (info->abfd, (bfd_vma) insn, info->contents + irel->r_offset); 133160510Sobrien info->changed_contents = true; 133260510Sobrien 133389862Sobrien irel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), R_ALPHA_GPREL16); 133460510Sobrien info->changed_relocs = true; 133560510Sobrien 133660510Sobrien /* Reduce the use count on this got entry by one, possibly 133760510Sobrien eliminating it. */ 133860510Sobrien info->gotent->use_count -= 1; 133960510Sobrien alpha_elf_tdata (info->gotent->gotobj)->total_got_entries -= 1; 134060510Sobrien if (!info->h) 134160510Sobrien alpha_elf_tdata (info->gotent->gotobj)->n_local_got_entries -= 1; 134260510Sobrien 134360510Sobrien /* ??? Search forward through this basic block looking for insns 134460510Sobrien that use the target register. Stop after an insn modifying the 134560510Sobrien register is seen, or after a branch or call. 134660510Sobrien 134760510Sobrien Any such memory load insn may be substituted by a load directly 134860510Sobrien off the GP. This allows the memory load insn to be issued before 134977303Sobrien the calculated GP register would otherwise be ready. 135060510Sobrien 135160510Sobrien Any such jsr insn can be replaced by a bsr if it is in range. 135260510Sobrien 135360510Sobrien This would mean that we'd have to _add_ relocations, the pain of 135460510Sobrien which gives one pause. */ 135560510Sobrien 135660510Sobrien return true; 135760510Sobrien} 135860510Sobrien 135960510Sobrienstatic boolean 136060510Sobrienelf64_alpha_relax_section (abfd, sec, link_info, again) 136160510Sobrien bfd *abfd; 136260510Sobrien asection *sec; 136360510Sobrien struct bfd_link_info *link_info; 136460510Sobrien boolean *again; 136560510Sobrien{ 136660510Sobrien Elf_Internal_Shdr *symtab_hdr; 136789862Sobrien Elf_Internal_Shdr *shndx_hdr; 136860510Sobrien Elf_Internal_Rela *internal_relocs; 136960510Sobrien Elf_Internal_Rela *free_relocs = NULL; 137060510Sobrien Elf_Internal_Rela *irel, *irelend; 137160510Sobrien bfd_byte *free_contents = NULL; 137260510Sobrien Elf64_External_Sym *extsyms = NULL; 137360510Sobrien Elf64_External_Sym *free_extsyms = NULL; 137489862Sobrien Elf_External_Sym_Shndx *shndx_buf = NULL; 137560510Sobrien struct alpha_elf_got_entry **local_got_entries; 137660510Sobrien struct alpha_relax_info info; 137760510Sobrien 137860510Sobrien /* We are not currently changing any sizes, so only one pass. */ 137960510Sobrien *again = false; 138060510Sobrien 138160510Sobrien if (link_info->relocateable 138260510Sobrien || (sec->flags & SEC_RELOC) == 0 138360510Sobrien || sec->reloc_count == 0) 138460510Sobrien return true; 138560510Sobrien 138660510Sobrien /* If this is the first time we have been called for this section, 138760510Sobrien initialize the cooked size. */ 138860510Sobrien if (sec->_cooked_size == 0) 138960510Sobrien sec->_cooked_size = sec->_raw_size; 139060510Sobrien 139160510Sobrien symtab_hdr = &elf_tdata (abfd)->symtab_hdr; 139260510Sobrien local_got_entries = alpha_elf_tdata(abfd)->local_got_entries; 139360510Sobrien 139460510Sobrien /* Load the relocations for this section. */ 139560510Sobrien internal_relocs = (_bfd_elf64_link_read_relocs 139660510Sobrien (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL, 139760510Sobrien link_info->keep_memory)); 139860510Sobrien if (internal_relocs == NULL) 139960510Sobrien goto error_return; 140060510Sobrien if (! link_info->keep_memory) 140160510Sobrien free_relocs = internal_relocs; 140260510Sobrien 140377303Sobrien memset(&info, 0, sizeof (info)); 140460510Sobrien info.abfd = abfd; 140560510Sobrien info.sec = sec; 140660510Sobrien info.link_info = link_info; 140760510Sobrien info.relocs = internal_relocs; 140860510Sobrien info.relend = irelend = internal_relocs + sec->reloc_count; 140960510Sobrien 141060510Sobrien /* Find the GP for this object. */ 141160510Sobrien info.gotobj = alpha_elf_tdata (abfd)->gotobj; 141260510Sobrien if (info.gotobj) 141360510Sobrien { 141460510Sobrien asection *sgot = alpha_elf_tdata (info.gotobj)->got; 141560510Sobrien info.gp = _bfd_get_gp_value (info.gotobj); 141660510Sobrien if (info.gp == 0) 141760510Sobrien { 141860510Sobrien info.gp = (sgot->output_section->vma 141960510Sobrien + sgot->output_offset 142060510Sobrien + 0x8000); 142160510Sobrien _bfd_set_gp_value (info.gotobj, info.gp); 142260510Sobrien } 142360510Sobrien } 142460510Sobrien 142560510Sobrien for (irel = internal_relocs; irel < irelend; irel++) 142660510Sobrien { 142760510Sobrien bfd_vma symval; 142860510Sobrien Elf_Internal_Sym isym; 142960510Sobrien struct alpha_elf_got_entry *gotent; 143060510Sobrien 143160510Sobrien if (ELF64_R_TYPE (irel->r_info) != (int) R_ALPHA_LITERAL) 143260510Sobrien continue; 143360510Sobrien 143460510Sobrien /* Get the section contents. */ 143560510Sobrien if (info.contents == NULL) 143660510Sobrien { 143760510Sobrien if (elf_section_data (sec)->this_hdr.contents != NULL) 143860510Sobrien info.contents = elf_section_data (sec)->this_hdr.contents; 143960510Sobrien else 144060510Sobrien { 144160510Sobrien info.contents = (bfd_byte *) bfd_malloc (sec->_raw_size); 144260510Sobrien if (info.contents == NULL) 144360510Sobrien goto error_return; 144460510Sobrien free_contents = info.contents; 144560510Sobrien 144660510Sobrien if (! bfd_get_section_contents (abfd, sec, info.contents, 144760510Sobrien (file_ptr) 0, sec->_raw_size)) 144860510Sobrien goto error_return; 144960510Sobrien } 145060510Sobrien } 145160510Sobrien 145260510Sobrien /* Read this BFD's symbols if we haven't done so already. */ 145360510Sobrien if (extsyms == NULL) 145460510Sobrien { 145589862Sobrien bfd_size_type amt; 145689862Sobrien 145760510Sobrien if (symtab_hdr->contents != NULL) 145860510Sobrien extsyms = (Elf64_External_Sym *) symtab_hdr->contents; 145960510Sobrien else 146060510Sobrien { 146189862Sobrien amt = symtab_hdr->sh_info; 146289862Sobrien amt *= sizeof (Elf64_External_Sym); 146389862Sobrien extsyms = (Elf64_External_Sym *) bfd_malloc (amt); 146460510Sobrien if (extsyms == NULL) 146560510Sobrien goto error_return; 146660510Sobrien free_extsyms = extsyms; 146760510Sobrien if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0 146889862Sobrien || bfd_bread ((PTR) extsyms, amt, abfd) != amt) 146960510Sobrien goto error_return; 147060510Sobrien } 147189862Sobrien 147289862Sobrien shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr; 147389862Sobrien if (shndx_hdr->sh_size != 0) 147489862Sobrien { 147589862Sobrien amt = symtab_hdr->sh_info; 147689862Sobrien amt *= sizeof (Elf_External_Sym_Shndx); 147789862Sobrien shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt); 147889862Sobrien if (shndx_buf == NULL) 147989862Sobrien goto error_return; 148089862Sobrien if (bfd_seek (abfd, shndx_hdr->sh_offset, SEEK_SET) != 0 148189862Sobrien || bfd_bread ((PTR) shndx_buf, amt, abfd) != amt) 148289862Sobrien goto error_return; 148389862Sobrien } 148460510Sobrien } 148560510Sobrien 148660510Sobrien /* Get the value of the symbol referred to by the reloc. */ 148760510Sobrien if (ELF64_R_SYM (irel->r_info) < symtab_hdr->sh_info) 148860510Sobrien { 148960510Sobrien /* A local symbol. */ 149089862Sobrien Elf64_External_Sym *esym; 149189862Sobrien Elf_External_Sym_Shndx *shndx; 149289862Sobrien 149389862Sobrien esym = extsyms + ELF64_R_SYM (irel->r_info); 149489862Sobrien shndx = shndx_buf + (shndx_buf ? ELF64_R_SYM (irel->r_info) : 0); 149589862Sobrien bfd_elf64_swap_symbol_in (abfd, esym, shndx, &isym); 149660510Sobrien if (isym.st_shndx == SHN_UNDEF) 149760510Sobrien info.tsec = bfd_und_section_ptr; 149860510Sobrien else if (isym.st_shndx == SHN_ABS) 149960510Sobrien info.tsec = bfd_abs_section_ptr; 150060510Sobrien else if (isym.st_shndx == SHN_COMMON) 150160510Sobrien info.tsec = bfd_com_section_ptr; 150277303Sobrien else 150389862Sobrien info.tsec = bfd_section_from_elf_index (abfd, isym.st_shndx); 150460510Sobrien 150560510Sobrien info.h = NULL; 150660510Sobrien info.other = isym.st_other; 150760510Sobrien gotent = local_got_entries[ELF64_R_SYM(irel->r_info)]; 150860510Sobrien symval = isym.st_value; 150960510Sobrien } 151060510Sobrien else 151160510Sobrien { 151260510Sobrien unsigned long indx; 151360510Sobrien struct alpha_elf_link_hash_entry *h; 151460510Sobrien 151560510Sobrien indx = ELF64_R_SYM (irel->r_info) - symtab_hdr->sh_info; 151660510Sobrien h = alpha_elf_sym_hashes (abfd)[indx]; 151760510Sobrien BFD_ASSERT (h != NULL); 151860510Sobrien 151960510Sobrien while (h->root.root.type == bfd_link_hash_indirect 152060510Sobrien || h->root.root.type == bfd_link_hash_warning) 152160510Sobrien h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link; 152260510Sobrien 152360510Sobrien /* We can't do anthing with undefined or dynamic symbols. */ 152460510Sobrien if (h->root.root.type == bfd_link_hash_undefined 152560510Sobrien || h->root.root.type == bfd_link_hash_undefweak 152660510Sobrien || alpha_elf_dynamic_symbol_p (&h->root, link_info)) 152760510Sobrien continue; 152860510Sobrien 152960510Sobrien info.h = h; 153060510Sobrien info.tsec = h->root.root.u.def.section; 153160510Sobrien info.other = h->root.other; 153260510Sobrien gotent = h->got_entries; 153360510Sobrien symval = h->root.root.u.def.value; 153460510Sobrien } 153560510Sobrien 153660510Sobrien /* Search for the got entry to be used by this relocation. */ 153760510Sobrien while (gotent->gotobj != info.gotobj || gotent->addend != irel->r_addend) 153860510Sobrien gotent = gotent->next; 153960510Sobrien info.gotent = gotent; 154060510Sobrien 154160510Sobrien symval += info.tsec->output_section->vma + info.tsec->output_offset; 154260510Sobrien symval += irel->r_addend; 154360510Sobrien 154460510Sobrien BFD_ASSERT(info.gotent != NULL); 154560510Sobrien 154660510Sobrien /* If there exist LITUSE relocations immediately following, this 154760510Sobrien opens up all sorts of interesting optimizations, because we 154860510Sobrien now know every location that this address load is used. */ 154960510Sobrien 155060510Sobrien if (irel+1 < irelend && ELF64_R_TYPE (irel[1].r_info) == R_ALPHA_LITUSE) 155160510Sobrien { 155260510Sobrien irel = elf64_alpha_relax_with_lituse (&info, symval, irel, irelend); 155360510Sobrien if (irel == NULL) 155460510Sobrien goto error_return; 155560510Sobrien } 155660510Sobrien else 155760510Sobrien { 155860510Sobrien if (!elf64_alpha_relax_without_lituse (&info, symval, irel)) 155960510Sobrien goto error_return; 156060510Sobrien } 156160510Sobrien } 156260510Sobrien 156360510Sobrien if (!elf64_alpha_size_got_sections (abfd, link_info)) 156460510Sobrien return false; 156560510Sobrien 156660510Sobrien if (info.changed_relocs) 156760510Sobrien { 156860510Sobrien elf_section_data (sec)->relocs = internal_relocs; 156960510Sobrien } 157060510Sobrien else if (free_relocs != NULL) 157160510Sobrien { 157260510Sobrien free (free_relocs); 157360510Sobrien } 157460510Sobrien 157560510Sobrien if (info.changed_contents) 157660510Sobrien { 157760510Sobrien elf_section_data (sec)->this_hdr.contents = info.contents; 157860510Sobrien } 157960510Sobrien else if (free_contents != NULL) 158060510Sobrien { 158160510Sobrien if (! link_info->keep_memory) 158260510Sobrien free (free_contents); 158360510Sobrien else 158460510Sobrien { 158560510Sobrien /* Cache the section contents for elf_link_input_bfd. */ 158660510Sobrien elf_section_data (sec)->this_hdr.contents = info.contents; 158760510Sobrien } 158860510Sobrien } 158960510Sobrien 159089862Sobrien if (shndx_buf != NULL) 159189862Sobrien free (shndx_buf); 159289862Sobrien 159360510Sobrien if (free_extsyms != NULL) 159460510Sobrien { 159560510Sobrien if (! link_info->keep_memory) 159660510Sobrien free (free_extsyms); 159760510Sobrien else 159860510Sobrien { 159960510Sobrien /* Cache the symbols for elf_link_input_bfd. */ 160089862Sobrien symtab_hdr->contents = (unsigned char *) extsyms; 160160510Sobrien } 160260510Sobrien } 160360510Sobrien 160460510Sobrien *again = info.changed_contents || info.changed_relocs; 160560510Sobrien 160660510Sobrien return true; 160760510Sobrien 160860510Sobrien error_return: 160960510Sobrien if (free_relocs != NULL) 161060510Sobrien free (free_relocs); 161160510Sobrien if (free_contents != NULL) 161260510Sobrien free (free_contents); 161389862Sobrien if (shndx_buf != NULL) 161489862Sobrien free (shndx_buf); 161560510Sobrien if (free_extsyms != NULL) 161660510Sobrien free (free_extsyms); 161760510Sobrien return false; 161860510Sobrien} 161960510Sobrien 162033965Sjdp/* PLT/GOT Stuff */ 162133965Sjdp#define PLT_HEADER_SIZE 32 162289862Sobrien#define PLT_HEADER_WORD1 (bfd_vma) 0xc3600000 /* br $27,.+4 */ 162389862Sobrien#define PLT_HEADER_WORD2 (bfd_vma) 0xa77b000c /* ldq $27,12($27) */ 162489862Sobrien#define PLT_HEADER_WORD3 (bfd_vma) 0x47ff041f /* nop */ 162589862Sobrien#define PLT_HEADER_WORD4 (bfd_vma) 0x6b7b0000 /* jmp $27,($27) */ 162633965Sjdp 162733965Sjdp#define PLT_ENTRY_SIZE 12 162838889Sjdp#define PLT_ENTRY_WORD1 0xc3800000 /* br $28, plt0 */ 162938889Sjdp#define PLT_ENTRY_WORD2 0 163038889Sjdp#define PLT_ENTRY_WORD3 0 163133965Sjdp 163233965Sjdp#define MAX_GOT_ENTRIES (64*1024 / 8) 163333965Sjdp 163468770Sobrien#ifndef ELF_DYNAMIC_INTERPRETER 163568770Sobrien#define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so" 163668770Sobrien#endif 163733965Sjdp 163833965Sjdp/* Handle an Alpha specific section when reading an object file. This 163933965Sjdp is called when elfcode.h finds a section with an unknown type. 164060510Sobrien FIXME: We need to handle the SHF_ALPHA_GPREL flag, but I'm not sure 164133965Sjdp how to. */ 164233965Sjdp 164333965Sjdpstatic boolean 164433965Sjdpelf64_alpha_section_from_shdr (abfd, hdr, name) 164533965Sjdp bfd *abfd; 164633965Sjdp Elf64_Internal_Shdr *hdr; 164733965Sjdp char *name; 164833965Sjdp{ 164933965Sjdp asection *newsect; 165033965Sjdp 165133965Sjdp /* There ought to be a place to keep ELF backend specific flags, but 165233965Sjdp at the moment there isn't one. We just keep track of the 165333965Sjdp sections by their name, instead. Fortunately, the ABI gives 165433965Sjdp suggested names for all the MIPS specific sections, so we will 165533965Sjdp probably get away with this. */ 165633965Sjdp switch (hdr->sh_type) 165733965Sjdp { 165833965Sjdp case SHT_ALPHA_DEBUG: 165933965Sjdp if (strcmp (name, ".mdebug") != 0) 166033965Sjdp return false; 166133965Sjdp break; 166233965Sjdp default: 166333965Sjdp return false; 166433965Sjdp } 166533965Sjdp 166633965Sjdp if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name)) 166733965Sjdp return false; 166833965Sjdp newsect = hdr->bfd_section; 166933965Sjdp 167033965Sjdp if (hdr->sh_type == SHT_ALPHA_DEBUG) 167133965Sjdp { 167233965Sjdp if (! bfd_set_section_flags (abfd, newsect, 167333965Sjdp (bfd_get_section_flags (abfd, newsect) 167433965Sjdp | SEC_DEBUGGING))) 167533965Sjdp return false; 167633965Sjdp } 167733965Sjdp 167889862Sobrien return true; 167989862Sobrien} 168033965Sjdp 168189862Sobrien/* Convert Alpha specific section flags to bfd internal section flags. */ 168233965Sjdp 168389862Sobrienstatic boolean 168489862Sobrienelf64_alpha_section_flags (flags, hdr) 168589862Sobrien flagword *flags; 168689862Sobrien Elf64_Internal_Shdr *hdr; 168789862Sobrien{ 168889862Sobrien if (hdr->sh_flags & SHF_ALPHA_GPREL) 168989862Sobrien *flags |= SEC_SMALL_DATA; 169089862Sobrien 169133965Sjdp return true; 169233965Sjdp} 169333965Sjdp 169433965Sjdp/* Set the correct type for an Alpha ELF section. We do this by the 169533965Sjdp section name, which is a hack, but ought to work. */ 169633965Sjdp 169733965Sjdpstatic boolean 169833965Sjdpelf64_alpha_fake_sections (abfd, hdr, sec) 169933965Sjdp bfd *abfd; 170033965Sjdp Elf64_Internal_Shdr *hdr; 170133965Sjdp asection *sec; 170233965Sjdp{ 170333965Sjdp register const char *name; 170433965Sjdp 170533965Sjdp name = bfd_get_section_name (abfd, sec); 170633965Sjdp 170733965Sjdp if (strcmp (name, ".mdebug") == 0) 170833965Sjdp { 170933965Sjdp hdr->sh_type = SHT_ALPHA_DEBUG; 171033965Sjdp /* In a shared object on Irix 5.3, the .mdebug section has an 171133965Sjdp entsize of 0. FIXME: Does this matter? */ 171233965Sjdp if ((abfd->flags & DYNAMIC) != 0 ) 171333965Sjdp hdr->sh_entsize = 0; 171433965Sjdp else 171533965Sjdp hdr->sh_entsize = 1; 171633965Sjdp } 171789862Sobrien else if ((sec->flags & SEC_SMALL_DATA) 171889862Sobrien || strcmp (name, ".sdata") == 0 171933965Sjdp || strcmp (name, ".sbss") == 0 172033965Sjdp || strcmp (name, ".lit4") == 0 172133965Sjdp || strcmp (name, ".lit8") == 0) 172233965Sjdp hdr->sh_flags |= SHF_ALPHA_GPREL; 172333965Sjdp 172433965Sjdp return true; 172533965Sjdp} 172633965Sjdp 172760510Sobrien/* Hook called by the linker routine which adds symbols from an object 172860510Sobrien file. We use it to put .comm items in .sbss, and not .bss. */ 172933965Sjdp 173060510Sobrienstatic boolean 173160510Sobrienelf64_alpha_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp) 173233965Sjdp bfd *abfd; 173360510Sobrien struct bfd_link_info *info; 173460510Sobrien const Elf_Internal_Sym *sym; 173578833Sobrien const char **namep ATTRIBUTE_UNUSED; 173678833Sobrien flagword *flagsp ATTRIBUTE_UNUSED; 173760510Sobrien asection **secp; 173860510Sobrien bfd_vma *valp; 173933965Sjdp{ 174060510Sobrien if (sym->st_shndx == SHN_COMMON 174160510Sobrien && !info->relocateable 174289862Sobrien && sym->st_size <= elf_gp_size (abfd)) 174360510Sobrien { 174460510Sobrien /* Common symbols less than or equal to -G nn bytes are 174560510Sobrien automatically put into .sbss. */ 174633965Sjdp 174760510Sobrien asection *scomm = bfd_get_section_by_name (abfd, ".scommon"); 174833965Sjdp 174960510Sobrien if (scomm == NULL) 175060510Sobrien { 175160510Sobrien scomm = bfd_make_section (abfd, ".scommon"); 175260510Sobrien if (scomm == NULL 175360510Sobrien || !bfd_set_section_flags (abfd, scomm, (SEC_ALLOC 175460510Sobrien | SEC_IS_COMMON 175560510Sobrien | SEC_LINKER_CREATED))) 175660510Sobrien return false; 175760510Sobrien } 175833965Sjdp 175960510Sobrien *secp = scomm; 176060510Sobrien *valp = sym->st_size; 176133965Sjdp } 176233965Sjdp 176360510Sobrien return true; 176433965Sjdp} 176533965Sjdp 176633965Sjdp/* Create the .got section. */ 176733965Sjdp 176833965Sjdpstatic boolean 176933965Sjdpelf64_alpha_create_got_section(abfd, info) 177033965Sjdp bfd *abfd; 177178833Sobrien struct bfd_link_info *info ATTRIBUTE_UNUSED; 177233965Sjdp{ 177333965Sjdp asection *s; 177433965Sjdp 177533965Sjdp if (bfd_get_section_by_name (abfd, ".got")) 177633965Sjdp return true; 177733965Sjdp 177833965Sjdp s = bfd_make_section (abfd, ".got"); 177933965Sjdp if (s == NULL 178033965Sjdp || !bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD 178133965Sjdp | SEC_HAS_CONTENTS 178233965Sjdp | SEC_IN_MEMORY 178333965Sjdp | SEC_LINKER_CREATED)) 178433965Sjdp || !bfd_set_section_alignment (abfd, s, 3)) 178533965Sjdp return false; 178633965Sjdp 178733965Sjdp alpha_elf_tdata (abfd)->got = s; 178833965Sjdp 178933965Sjdp return true; 179033965Sjdp} 179133965Sjdp 179233965Sjdp/* Create all the dynamic sections. */ 179333965Sjdp 179433965Sjdpstatic boolean 179533965Sjdpelf64_alpha_create_dynamic_sections (abfd, info) 179633965Sjdp bfd *abfd; 179733965Sjdp struct bfd_link_info *info; 179833965Sjdp{ 179933965Sjdp asection *s; 180033965Sjdp struct elf_link_hash_entry *h; 180133965Sjdp 180233965Sjdp /* We need to create .plt, .rela.plt, .got, and .rela.got sections. */ 180333965Sjdp 180433965Sjdp s = bfd_make_section (abfd, ".plt"); 180533965Sjdp if (s == NULL 180633965Sjdp || ! bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD 180733965Sjdp | SEC_HAS_CONTENTS 180833965Sjdp | SEC_IN_MEMORY 180933965Sjdp | SEC_LINKER_CREATED 181033965Sjdp | SEC_CODE)) 181133965Sjdp || ! bfd_set_section_alignment (abfd, s, 3)) 181233965Sjdp return false; 181333965Sjdp 181433965Sjdp /* Define the symbol _PROCEDURE_LINKAGE_TABLE_ at the start of the 181533965Sjdp .plt section. */ 181633965Sjdp h = NULL; 181733965Sjdp if (! (_bfd_generic_link_add_one_symbol 181833965Sjdp (info, abfd, "_PROCEDURE_LINKAGE_TABLE_", BSF_GLOBAL, s, 181933965Sjdp (bfd_vma) 0, (const char *) NULL, false, 182033965Sjdp get_elf_backend_data (abfd)->collect, 182133965Sjdp (struct bfd_link_hash_entry **) &h))) 182233965Sjdp return false; 182333965Sjdp h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR; 182433965Sjdp h->type = STT_OBJECT; 182533965Sjdp 182633965Sjdp if (info->shared 182733965Sjdp && ! _bfd_elf_link_record_dynamic_symbol (info, h)) 182833965Sjdp return false; 182933965Sjdp 183033965Sjdp s = bfd_make_section (abfd, ".rela.plt"); 183133965Sjdp if (s == NULL 183233965Sjdp || !bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD 183333965Sjdp | SEC_HAS_CONTENTS 183433965Sjdp | SEC_IN_MEMORY 183533965Sjdp | SEC_LINKER_CREATED 183633965Sjdp | SEC_READONLY)) 183733965Sjdp || ! bfd_set_section_alignment (abfd, s, 3)) 183833965Sjdp return false; 183933965Sjdp 184033965Sjdp /* We may or may not have created a .got section for this object, but 184133965Sjdp we definitely havn't done the rest of the work. */ 184233965Sjdp 184333965Sjdp if (!elf64_alpha_create_got_section (abfd, info)) 184433965Sjdp return false; 184533965Sjdp 184633965Sjdp s = bfd_make_section(abfd, ".rela.got"); 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 /* Define the symbol _GLOBAL_OFFSET_TABLE_ at the start of the 185733965Sjdp dynobj's .got section. We don't do this in the linker script 185833965Sjdp because we don't want to define the symbol if we are not creating 185933965Sjdp a global offset table. */ 186033965Sjdp h = NULL; 186133965Sjdp if (!(_bfd_generic_link_add_one_symbol 186233965Sjdp (info, abfd, "_GLOBAL_OFFSET_TABLE_", BSF_GLOBAL, 186333965Sjdp alpha_elf_tdata(abfd)->got, (bfd_vma) 0, (const char *) NULL, 186433965Sjdp false, get_elf_backend_data (abfd)->collect, 186533965Sjdp (struct bfd_link_hash_entry **) &h))) 186633965Sjdp return false; 186733965Sjdp h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR; 186833965Sjdp h->type = STT_OBJECT; 186933965Sjdp 187033965Sjdp if (info->shared 187133965Sjdp && ! _bfd_elf_link_record_dynamic_symbol (info, h)) 187233965Sjdp return false; 187333965Sjdp 187433965Sjdp elf_hash_table (info)->hgot = h; 187533965Sjdp 187633965Sjdp return true; 187733965Sjdp} 187833965Sjdp 187933965Sjdp/* Read ECOFF debugging information from a .mdebug section into a 188033965Sjdp ecoff_debug_info structure. */ 188133965Sjdp 188233965Sjdpstatic boolean 188333965Sjdpelf64_alpha_read_ecoff_info (abfd, section, debug) 188433965Sjdp bfd *abfd; 188533965Sjdp asection *section; 188633965Sjdp struct ecoff_debug_info *debug; 188733965Sjdp{ 188833965Sjdp HDRR *symhdr; 188933965Sjdp const struct ecoff_debug_swap *swap; 189033965Sjdp char *ext_hdr = NULL; 189133965Sjdp 189233965Sjdp swap = get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap; 189377303Sobrien memset (debug, 0, sizeof (*debug)); 189433965Sjdp 189589862Sobrien ext_hdr = (char *) bfd_malloc (swap->external_hdr_size); 189633965Sjdp if (ext_hdr == NULL && swap->external_hdr_size != 0) 189733965Sjdp goto error_return; 189833965Sjdp 189933965Sjdp if (bfd_get_section_contents (abfd, section, ext_hdr, (file_ptr) 0, 190033965Sjdp swap->external_hdr_size) 190133965Sjdp == false) 190233965Sjdp goto error_return; 190333965Sjdp 190433965Sjdp symhdr = &debug->symbolic_header; 190533965Sjdp (*swap->swap_hdr_in) (abfd, ext_hdr, symhdr); 190633965Sjdp 190733965Sjdp /* The symbolic header contains absolute file offsets and sizes to 190833965Sjdp read. */ 190933965Sjdp#define READ(ptr, offset, count, size, type) \ 191033965Sjdp if (symhdr->count == 0) \ 191133965Sjdp debug->ptr = NULL; \ 191233965Sjdp else \ 191333965Sjdp { \ 191489862Sobrien bfd_size_type amt = (bfd_size_type) size * symhdr->count; \ 191589862Sobrien debug->ptr = (type) bfd_malloc (amt); \ 191633965Sjdp if (debug->ptr == NULL) \ 191733965Sjdp goto error_return; \ 191833965Sjdp if (bfd_seek (abfd, (file_ptr) symhdr->offset, SEEK_SET) != 0 \ 191989862Sobrien || bfd_bread (debug->ptr, amt, abfd) != amt) \ 192033965Sjdp goto error_return; \ 192133965Sjdp } 192233965Sjdp 192333965Sjdp READ (line, cbLineOffset, cbLine, sizeof (unsigned char), unsigned char *); 192433965Sjdp READ (external_dnr, cbDnOffset, idnMax, swap->external_dnr_size, PTR); 192533965Sjdp READ (external_pdr, cbPdOffset, ipdMax, swap->external_pdr_size, PTR); 192633965Sjdp READ (external_sym, cbSymOffset, isymMax, swap->external_sym_size, PTR); 192733965Sjdp READ (external_opt, cbOptOffset, ioptMax, swap->external_opt_size, PTR); 192833965Sjdp READ (external_aux, cbAuxOffset, iauxMax, sizeof (union aux_ext), 192933965Sjdp union aux_ext *); 193033965Sjdp READ (ss, cbSsOffset, issMax, sizeof (char), char *); 193133965Sjdp READ (ssext, cbSsExtOffset, issExtMax, sizeof (char), char *); 193233965Sjdp READ (external_fdr, cbFdOffset, ifdMax, swap->external_fdr_size, PTR); 193333965Sjdp READ (external_rfd, cbRfdOffset, crfd, swap->external_rfd_size, PTR); 193433965Sjdp READ (external_ext, cbExtOffset, iextMax, swap->external_ext_size, PTR); 193533965Sjdp#undef READ 193633965Sjdp 193733965Sjdp debug->fdr = NULL; 193833965Sjdp debug->adjust = NULL; 193933965Sjdp 194033965Sjdp return true; 194133965Sjdp 194233965Sjdp error_return: 194333965Sjdp if (ext_hdr != NULL) 194433965Sjdp free (ext_hdr); 194533965Sjdp if (debug->line != NULL) 194633965Sjdp free (debug->line); 194733965Sjdp if (debug->external_dnr != NULL) 194833965Sjdp free (debug->external_dnr); 194933965Sjdp if (debug->external_pdr != NULL) 195033965Sjdp free (debug->external_pdr); 195133965Sjdp if (debug->external_sym != NULL) 195233965Sjdp free (debug->external_sym); 195333965Sjdp if (debug->external_opt != NULL) 195433965Sjdp free (debug->external_opt); 195533965Sjdp if (debug->external_aux != NULL) 195633965Sjdp free (debug->external_aux); 195733965Sjdp if (debug->ss != NULL) 195833965Sjdp free (debug->ss); 195933965Sjdp if (debug->ssext != NULL) 196033965Sjdp free (debug->ssext); 196133965Sjdp if (debug->external_fdr != NULL) 196233965Sjdp free (debug->external_fdr); 196333965Sjdp if (debug->external_rfd != NULL) 196433965Sjdp free (debug->external_rfd); 196533965Sjdp if (debug->external_ext != NULL) 196633965Sjdp free (debug->external_ext); 196733965Sjdp return false; 196833965Sjdp} 196933965Sjdp 197033965Sjdp/* Alpha ELF local labels start with '$'. */ 197133965Sjdp 197233965Sjdpstatic boolean 197333965Sjdpelf64_alpha_is_local_label_name (abfd, name) 197478833Sobrien bfd *abfd ATTRIBUTE_UNUSED; 197533965Sjdp const char *name; 197633965Sjdp{ 197733965Sjdp return name[0] == '$'; 197833965Sjdp} 197933965Sjdp 198033965Sjdp/* Alpha ELF follows MIPS ELF in using a special find_nearest_line 198133965Sjdp routine in order to handle the ECOFF debugging information. We 198233965Sjdp still call this mips_elf_find_line because of the slot 198333965Sjdp find_line_info in elf_obj_tdata is declared that way. */ 198433965Sjdp 198533965Sjdpstruct mips_elf_find_line 198633965Sjdp{ 198733965Sjdp struct ecoff_debug_info d; 198833965Sjdp struct ecoff_find_line i; 198933965Sjdp}; 199033965Sjdp 199133965Sjdpstatic boolean 199233965Sjdpelf64_alpha_find_nearest_line (abfd, section, symbols, offset, filename_ptr, 199333965Sjdp functionname_ptr, line_ptr) 199433965Sjdp bfd *abfd; 199533965Sjdp asection *section; 199633965Sjdp asymbol **symbols; 199733965Sjdp bfd_vma offset; 199833965Sjdp const char **filename_ptr; 199933965Sjdp const char **functionname_ptr; 200033965Sjdp unsigned int *line_ptr; 200133965Sjdp{ 200233965Sjdp asection *msec; 200333965Sjdp 200477303Sobrien if (_bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset, 200577303Sobrien filename_ptr, functionname_ptr, 200677303Sobrien line_ptr, 0, 200777303Sobrien &elf_tdata (abfd)->dwarf2_find_line_info)) 200877303Sobrien return true; 200977303Sobrien 201033965Sjdp msec = bfd_get_section_by_name (abfd, ".mdebug"); 201133965Sjdp if (msec != NULL) 201233965Sjdp { 201333965Sjdp flagword origflags; 201433965Sjdp struct mips_elf_find_line *fi; 201533965Sjdp const struct ecoff_debug_swap * const swap = 201633965Sjdp get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap; 201733965Sjdp 201833965Sjdp /* If we are called during a link, alpha_elf_final_link may have 201933965Sjdp cleared the SEC_HAS_CONTENTS field. We force it back on here 202033965Sjdp if appropriate (which it normally will be). */ 202133965Sjdp origflags = msec->flags; 202233965Sjdp if (elf_section_data (msec)->this_hdr.sh_type != SHT_NOBITS) 202333965Sjdp msec->flags |= SEC_HAS_CONTENTS; 202433965Sjdp 202533965Sjdp fi = elf_tdata (abfd)->find_line_info; 202633965Sjdp if (fi == NULL) 202733965Sjdp { 202833965Sjdp bfd_size_type external_fdr_size; 202933965Sjdp char *fraw_src; 203033965Sjdp char *fraw_end; 203133965Sjdp struct fdr *fdr_ptr; 203289862Sobrien bfd_size_type amt = sizeof (struct mips_elf_find_line); 203333965Sjdp 203489862Sobrien fi = (struct mips_elf_find_line *) bfd_zalloc (abfd, amt); 203533965Sjdp if (fi == NULL) 203633965Sjdp { 203733965Sjdp msec->flags = origflags; 203833965Sjdp return false; 203933965Sjdp } 204033965Sjdp 204133965Sjdp if (!elf64_alpha_read_ecoff_info (abfd, msec, &fi->d)) 204233965Sjdp { 204333965Sjdp msec->flags = origflags; 204433965Sjdp return false; 204533965Sjdp } 204633965Sjdp 204733965Sjdp /* Swap in the FDR information. */ 204889862Sobrien amt = fi->d.symbolic_header.ifdMax * sizeof (struct fdr); 204989862Sobrien fi->d.fdr = (struct fdr *) bfd_alloc (abfd, amt); 205033965Sjdp if (fi->d.fdr == NULL) 205133965Sjdp { 205233965Sjdp msec->flags = origflags; 205333965Sjdp return false; 205433965Sjdp } 205533965Sjdp external_fdr_size = swap->external_fdr_size; 205633965Sjdp fdr_ptr = fi->d.fdr; 205733965Sjdp fraw_src = (char *) fi->d.external_fdr; 205833965Sjdp fraw_end = (fraw_src 205933965Sjdp + fi->d.symbolic_header.ifdMax * external_fdr_size); 206033965Sjdp for (; fraw_src < fraw_end; fraw_src += external_fdr_size, fdr_ptr++) 206133965Sjdp (*swap->swap_fdr_in) (abfd, (PTR) fraw_src, fdr_ptr); 206233965Sjdp 206333965Sjdp elf_tdata (abfd)->find_line_info = fi; 206433965Sjdp 206533965Sjdp /* Note that we don't bother to ever free this information. 206633965Sjdp find_nearest_line is either called all the time, as in 206733965Sjdp objdump -l, so the information should be saved, or it is 206833965Sjdp rarely called, as in ld error messages, so the memory 206933965Sjdp wasted is unimportant. Still, it would probably be a 207033965Sjdp good idea for free_cached_info to throw it away. */ 207133965Sjdp } 207233965Sjdp 207333965Sjdp if (_bfd_ecoff_locate_line (abfd, section, offset, &fi->d, swap, 207433965Sjdp &fi->i, filename_ptr, functionname_ptr, 207533965Sjdp line_ptr)) 207633965Sjdp { 207733965Sjdp msec->flags = origflags; 207833965Sjdp return true; 207933965Sjdp } 208033965Sjdp 208133965Sjdp msec->flags = origflags; 208233965Sjdp } 208333965Sjdp 208433965Sjdp /* Fall back on the generic ELF find_nearest_line routine. */ 208533965Sjdp 208633965Sjdp return _bfd_elf_find_nearest_line (abfd, section, symbols, offset, 208733965Sjdp filename_ptr, functionname_ptr, 208833965Sjdp line_ptr); 208933965Sjdp} 209033965Sjdp 209133965Sjdp/* Structure used to pass information to alpha_elf_output_extsym. */ 209233965Sjdp 209333965Sjdpstruct extsym_info 209433965Sjdp{ 209533965Sjdp bfd *abfd; 209633965Sjdp struct bfd_link_info *info; 209733965Sjdp struct ecoff_debug_info *debug; 209833965Sjdp const struct ecoff_debug_swap *swap; 209933965Sjdp boolean failed; 210033965Sjdp}; 210133965Sjdp 210233965Sjdpstatic boolean 210333965Sjdpelf64_alpha_output_extsym (h, data) 210433965Sjdp struct alpha_elf_link_hash_entry *h; 210533965Sjdp PTR data; 210633965Sjdp{ 210733965Sjdp struct extsym_info *einfo = (struct extsym_info *) data; 210833965Sjdp boolean strip; 210933965Sjdp asection *sec, *output_section; 211033965Sjdp 211133965Sjdp if (h->root.indx == -2) 211233965Sjdp strip = false; 211333965Sjdp else if (((h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0 211433965Sjdp || (h->root.elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) != 0) 211533965Sjdp && (h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0 211633965Sjdp && (h->root.elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) == 0) 211733965Sjdp strip = true; 211833965Sjdp else if (einfo->info->strip == strip_all 211933965Sjdp || (einfo->info->strip == strip_some 212033965Sjdp && bfd_hash_lookup (einfo->info->keep_hash, 212133965Sjdp h->root.root.root.string, 212233965Sjdp false, false) == NULL)) 212333965Sjdp strip = true; 212433965Sjdp else 212533965Sjdp strip = false; 212633965Sjdp 212733965Sjdp if (strip) 212833965Sjdp return true; 212933965Sjdp 213033965Sjdp if (h->esym.ifd == -2) 213133965Sjdp { 213233965Sjdp h->esym.jmptbl = 0; 213333965Sjdp h->esym.cobol_main = 0; 213433965Sjdp h->esym.weakext = 0; 213533965Sjdp h->esym.reserved = 0; 213633965Sjdp h->esym.ifd = ifdNil; 213733965Sjdp h->esym.asym.value = 0; 213833965Sjdp h->esym.asym.st = stGlobal; 213933965Sjdp 214033965Sjdp if (h->root.root.type != bfd_link_hash_defined 214133965Sjdp && h->root.root.type != bfd_link_hash_defweak) 214233965Sjdp h->esym.asym.sc = scAbs; 214333965Sjdp else 214433965Sjdp { 214533965Sjdp const char *name; 214633965Sjdp 214733965Sjdp sec = h->root.root.u.def.section; 214833965Sjdp output_section = sec->output_section; 214933965Sjdp 215033965Sjdp /* When making a shared library and symbol h is the one from 215133965Sjdp the another shared library, OUTPUT_SECTION may be null. */ 215233965Sjdp if (output_section == NULL) 215333965Sjdp h->esym.asym.sc = scUndefined; 215433965Sjdp else 215533965Sjdp { 215633965Sjdp name = bfd_section_name (output_section->owner, output_section); 215733965Sjdp 215833965Sjdp if (strcmp (name, ".text") == 0) 215933965Sjdp h->esym.asym.sc = scText; 216033965Sjdp else if (strcmp (name, ".data") == 0) 216133965Sjdp h->esym.asym.sc = scData; 216233965Sjdp else if (strcmp (name, ".sdata") == 0) 216333965Sjdp h->esym.asym.sc = scSData; 216433965Sjdp else if (strcmp (name, ".rodata") == 0 216533965Sjdp || strcmp (name, ".rdata") == 0) 216633965Sjdp h->esym.asym.sc = scRData; 216733965Sjdp else if (strcmp (name, ".bss") == 0) 216833965Sjdp h->esym.asym.sc = scBss; 216933965Sjdp else if (strcmp (name, ".sbss") == 0) 217033965Sjdp h->esym.asym.sc = scSBss; 217133965Sjdp else if (strcmp (name, ".init") == 0) 217233965Sjdp h->esym.asym.sc = scInit; 217333965Sjdp else if (strcmp (name, ".fini") == 0) 217433965Sjdp h->esym.asym.sc = scFini; 217533965Sjdp else 217633965Sjdp h->esym.asym.sc = scAbs; 217733965Sjdp } 217833965Sjdp } 217933965Sjdp 218033965Sjdp h->esym.asym.reserved = 0; 218133965Sjdp h->esym.asym.index = indexNil; 218233965Sjdp } 218333965Sjdp 218433965Sjdp if (h->root.root.type == bfd_link_hash_common) 218533965Sjdp h->esym.asym.value = h->root.root.u.c.size; 218633965Sjdp else if (h->root.root.type == bfd_link_hash_defined 218733965Sjdp || h->root.root.type == bfd_link_hash_defweak) 218833965Sjdp { 218933965Sjdp if (h->esym.asym.sc == scCommon) 219033965Sjdp h->esym.asym.sc = scBss; 219133965Sjdp else if (h->esym.asym.sc == scSCommon) 219233965Sjdp h->esym.asym.sc = scSBss; 219333965Sjdp 219433965Sjdp sec = h->root.root.u.def.section; 219533965Sjdp output_section = sec->output_section; 219633965Sjdp if (output_section != NULL) 219733965Sjdp h->esym.asym.value = (h->root.root.u.def.value 219833965Sjdp + sec->output_offset 219933965Sjdp + output_section->vma); 220033965Sjdp else 220133965Sjdp h->esym.asym.value = 0; 220233965Sjdp } 220333965Sjdp else if ((h->root.elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0) 220433965Sjdp { 220533965Sjdp /* Set type and value for a symbol with a function stub. */ 220633965Sjdp h->esym.asym.st = stProc; 220733965Sjdp sec = bfd_get_section_by_name (einfo->abfd, ".plt"); 220833965Sjdp if (sec == NULL) 220933965Sjdp h->esym.asym.value = 0; 221033965Sjdp else 221133965Sjdp { 221233965Sjdp output_section = sec->output_section; 221333965Sjdp if (output_section != NULL) 221460510Sobrien h->esym.asym.value = (h->root.plt.offset 221533965Sjdp + sec->output_offset 221633965Sjdp + output_section->vma); 221733965Sjdp else 221833965Sjdp h->esym.asym.value = 0; 221933965Sjdp } 222033965Sjdp } 222133965Sjdp 222233965Sjdp if (! bfd_ecoff_debug_one_external (einfo->abfd, einfo->debug, einfo->swap, 222333965Sjdp h->root.root.root.string, 222433965Sjdp &h->esym)) 222533965Sjdp { 222633965Sjdp einfo->failed = true; 222733965Sjdp return false; 222833965Sjdp } 222933965Sjdp 223033965Sjdp return true; 223133965Sjdp} 223233965Sjdp 223333965Sjdp/* FIXME: Create a runtime procedure table from the .mdebug section. 223433965Sjdp 223533965Sjdpstatic boolean 223633965Sjdpmips_elf_create_procedure_table (handle, abfd, info, s, debug) 223733965Sjdp PTR handle; 223833965Sjdp bfd *abfd; 223933965Sjdp struct bfd_link_info *info; 224033965Sjdp asection *s; 224133965Sjdp struct ecoff_debug_info *debug; 224233965Sjdp*/ 224333965Sjdp 224433965Sjdp/* Handle dynamic relocations when doing an Alpha ELF link. */ 224533965Sjdp 224633965Sjdpstatic boolean 224733965Sjdpelf64_alpha_check_relocs (abfd, info, sec, relocs) 224833965Sjdp bfd *abfd; 224933965Sjdp struct bfd_link_info *info; 225033965Sjdp asection *sec; 225133965Sjdp const Elf_Internal_Rela *relocs; 225233965Sjdp{ 225333965Sjdp bfd *dynobj; 225433965Sjdp asection *sreloc; 225533965Sjdp const char *rel_sec_name; 225633965Sjdp Elf_Internal_Shdr *symtab_hdr; 225733965Sjdp struct alpha_elf_link_hash_entry **sym_hashes; 225833965Sjdp struct alpha_elf_got_entry **local_got_entries; 225933965Sjdp const Elf_Internal_Rela *rel, *relend; 226033965Sjdp int got_created; 226189862Sobrien bfd_size_type amt; 226233965Sjdp 226333965Sjdp if (info->relocateable) 226433965Sjdp return true; 226533965Sjdp 226633965Sjdp dynobj = elf_hash_table(info)->dynobj; 226733965Sjdp if (dynobj == NULL) 226833965Sjdp elf_hash_table(info)->dynobj = dynobj = abfd; 226933965Sjdp 227033965Sjdp sreloc = NULL; 227133965Sjdp rel_sec_name = NULL; 227233965Sjdp symtab_hdr = &elf_tdata(abfd)->symtab_hdr; 227333965Sjdp sym_hashes = alpha_elf_sym_hashes(abfd); 227433965Sjdp local_got_entries = alpha_elf_tdata(abfd)->local_got_entries; 227533965Sjdp got_created = 0; 227633965Sjdp 227733965Sjdp relend = relocs + sec->reloc_count; 227833965Sjdp for (rel = relocs; rel < relend; ++rel) 227933965Sjdp { 228033965Sjdp unsigned long r_symndx, r_type; 228133965Sjdp struct alpha_elf_link_hash_entry *h; 228233965Sjdp 228333965Sjdp r_symndx = ELF64_R_SYM (rel->r_info); 228433965Sjdp if (r_symndx < symtab_hdr->sh_info) 228533965Sjdp h = NULL; 228633965Sjdp else 228733965Sjdp { 228833965Sjdp h = sym_hashes[r_symndx - symtab_hdr->sh_info]; 228938889Sjdp 229038889Sjdp while (h->root.root.type == bfd_link_hash_indirect 229138889Sjdp || h->root.root.type == bfd_link_hash_warning) 229238889Sjdp h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link; 229338889Sjdp 229433965Sjdp h->root.elf_link_hash_flags |= ELF_LINK_HASH_REF_REGULAR; 229533965Sjdp } 229633965Sjdp r_type = ELF64_R_TYPE (rel->r_info); 229733965Sjdp 229833965Sjdp switch (r_type) 229933965Sjdp { 230033965Sjdp case R_ALPHA_LITERAL: 230133965Sjdp { 230233965Sjdp struct alpha_elf_got_entry *gotent; 230333965Sjdp int flags = 0; 230433965Sjdp 230533965Sjdp if (h) 230633965Sjdp { 230733965Sjdp /* Search for and possibly create a got entry. */ 230833965Sjdp for (gotent = h->got_entries; gotent ; gotent = gotent->next) 230933965Sjdp if (gotent->gotobj == abfd && 231033965Sjdp gotent->addend == rel->r_addend) 231133965Sjdp break; 231233965Sjdp 231333965Sjdp if (!gotent) 231433965Sjdp { 231589862Sobrien amt = sizeof (struct alpha_elf_got_entry); 231633965Sjdp gotent = ((struct alpha_elf_got_entry *) 231789862Sobrien bfd_alloc (abfd, amt)); 231833965Sjdp if (!gotent) 231933965Sjdp return false; 232033965Sjdp 232133965Sjdp gotent->gotobj = abfd; 232233965Sjdp gotent->addend = rel->r_addend; 232333965Sjdp gotent->got_offset = -1; 232433965Sjdp gotent->flags = 0; 232560510Sobrien gotent->use_count = 1; 232633965Sjdp 232733965Sjdp gotent->next = h->got_entries; 232833965Sjdp h->got_entries = gotent; 232933965Sjdp 233033965Sjdp alpha_elf_tdata (abfd)->total_got_entries++; 233133965Sjdp } 233260510Sobrien else 233360510Sobrien gotent->use_count += 1; 233433965Sjdp } 233533965Sjdp else 233633965Sjdp { 233733965Sjdp /* This is a local .got entry -- record for merge. */ 233833965Sjdp if (!local_got_entries) 233933965Sjdp { 234089862Sobrien bfd_size_type size; 234189862Sobrien size = symtab_hdr->sh_info; 234289862Sobrien size *= sizeof (struct alpha_elf_got_entry *); 234333965Sjdp 234433965Sjdp local_got_entries = ((struct alpha_elf_got_entry **) 234533965Sjdp bfd_alloc (abfd, size)); 234633965Sjdp if (!local_got_entries) 234733965Sjdp return false; 234833965Sjdp 234989862Sobrien memset (local_got_entries, 0, (size_t) size); 235033965Sjdp alpha_elf_tdata (abfd)->local_got_entries = 235133965Sjdp local_got_entries; 235233965Sjdp } 235333965Sjdp 235433965Sjdp for (gotent = local_got_entries[ELF64_R_SYM(rel->r_info)]; 235533965Sjdp gotent != NULL && gotent->addend != rel->r_addend; 235633965Sjdp gotent = gotent->next) 235733965Sjdp continue; 235833965Sjdp if (!gotent) 235933965Sjdp { 236089862Sobrien amt = sizeof (struct alpha_elf_got_entry); 236133965Sjdp gotent = ((struct alpha_elf_got_entry *) 236289862Sobrien bfd_alloc (abfd, amt)); 236333965Sjdp if (!gotent) 236433965Sjdp return false; 236533965Sjdp 236633965Sjdp gotent->gotobj = abfd; 236733965Sjdp gotent->addend = rel->r_addend; 236833965Sjdp gotent->got_offset = -1; 236933965Sjdp gotent->flags = 0; 237060510Sobrien gotent->use_count = 1; 237133965Sjdp 237233965Sjdp gotent->next = local_got_entries[ELF64_R_SYM(rel->r_info)]; 237333965Sjdp local_got_entries[ELF64_R_SYM(rel->r_info)] = gotent; 237433965Sjdp 237533965Sjdp alpha_elf_tdata(abfd)->total_got_entries++; 237633965Sjdp alpha_elf_tdata(abfd)->n_local_got_entries++; 237733965Sjdp } 237860510Sobrien else 237960510Sobrien gotent->use_count += 1; 238033965Sjdp } 238133965Sjdp 238233965Sjdp /* Remember how this literal is used from its LITUSEs. 238333965Sjdp This will be important when it comes to decide if we can 238433965Sjdp create a .plt entry for a function symbol. */ 238533965Sjdp if (rel+1 < relend 238633965Sjdp && ELF64_R_TYPE (rel[1].r_info) == R_ALPHA_LITUSE) 238733965Sjdp { 238833965Sjdp do 238933965Sjdp { 239033965Sjdp ++rel; 239133965Sjdp if (rel->r_addend >= 1 && rel->r_addend <= 3) 239233965Sjdp flags |= 1 << rel->r_addend; 239333965Sjdp } 239433965Sjdp while (rel+1 < relend && 239533965Sjdp ELF64_R_TYPE (rel[1].r_info) == R_ALPHA_LITUSE); 239633965Sjdp } 239733965Sjdp else 239833965Sjdp { 239933965Sjdp /* No LITUSEs -- presumably the address is not being 240033965Sjdp loaded for nothing. */ 240133965Sjdp flags = ALPHA_ELF_LINK_HASH_LU_ADDR; 240233965Sjdp } 240333965Sjdp 240433965Sjdp gotent->flags |= flags; 240533965Sjdp if (h) 240633965Sjdp { 240733965Sjdp /* Make a guess as to whether a .plt entry will be needed. */ 240833965Sjdp if ((h->flags |= flags) == ALPHA_ELF_LINK_HASH_LU_FUNC) 240933965Sjdp h->root.elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; 241033965Sjdp else 241133965Sjdp h->root.elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; 241233965Sjdp } 241333965Sjdp } 241433965Sjdp /* FALLTHRU */ 241533965Sjdp 241633965Sjdp case R_ALPHA_GPDISP: 241789862Sobrien case R_ALPHA_GPREL16: 241833965Sjdp case R_ALPHA_GPREL32: 241960510Sobrien case R_ALPHA_GPRELHIGH: 242060510Sobrien case R_ALPHA_GPRELLOW: 242133965Sjdp /* We don't actually use the .got here, but the sections must 242233965Sjdp be created before the linker maps input sections to output 242333965Sjdp sections. */ 242433965Sjdp if (!got_created) 242533965Sjdp { 242633965Sjdp if (!elf64_alpha_create_got_section (abfd, info)) 242733965Sjdp return false; 242833965Sjdp 242933965Sjdp /* Make sure the object's gotobj is set to itself so 243033965Sjdp that we default to every object with its own .got. 243133965Sjdp We'll merge .gots later once we've collected each 243233965Sjdp object's info. */ 243333965Sjdp alpha_elf_tdata(abfd)->gotobj = abfd; 243433965Sjdp 243533965Sjdp got_created = 1; 243633965Sjdp } 243733965Sjdp break; 243833965Sjdp 243933965Sjdp case R_ALPHA_SREL16: 244033965Sjdp case R_ALPHA_SREL32: 244133965Sjdp case R_ALPHA_SREL64: 244233965Sjdp if (h == NULL) 244333965Sjdp break; 244433965Sjdp /* FALLTHRU */ 244533965Sjdp 244633965Sjdp case R_ALPHA_REFLONG: 244733965Sjdp case R_ALPHA_REFQUAD: 244833965Sjdp if (rel_sec_name == NULL) 244933965Sjdp { 245033965Sjdp rel_sec_name = (bfd_elf_string_from_elf_section 245133965Sjdp (abfd, elf_elfheader(abfd)->e_shstrndx, 245233965Sjdp elf_section_data(sec)->rel_hdr.sh_name)); 245333965Sjdp if (rel_sec_name == NULL) 245433965Sjdp return false; 245533965Sjdp 245633965Sjdp BFD_ASSERT (strncmp (rel_sec_name, ".rela", 5) == 0 245733965Sjdp && strcmp (bfd_get_section_name (abfd, sec), 245833965Sjdp rel_sec_name+5) == 0); 245933965Sjdp } 246033965Sjdp 246133965Sjdp /* We need to create the section here now whether we eventually 246233965Sjdp use it or not so that it gets mapped to an output section by 246333965Sjdp the linker. If not used, we'll kill it in 246433965Sjdp size_dynamic_sections. */ 246533965Sjdp if (sreloc == NULL) 246633965Sjdp { 246733965Sjdp sreloc = bfd_get_section_by_name (dynobj, rel_sec_name); 246833965Sjdp if (sreloc == NULL) 246933965Sjdp { 247089862Sobrien flagword flags; 247189862Sobrien 247233965Sjdp sreloc = bfd_make_section (dynobj, rel_sec_name); 247389862Sobrien flags = (SEC_HAS_CONTENTS | SEC_IN_MEMORY 247489862Sobrien | SEC_LINKER_CREATED | SEC_READONLY); 247589862Sobrien if (sec->flags & SEC_ALLOC) 247689862Sobrien flags |= SEC_ALLOC | SEC_LOAD; 247733965Sjdp if (sreloc == NULL 247889862Sobrien || !bfd_set_section_flags (dynobj, sreloc, flags) 247933965Sjdp || !bfd_set_section_alignment (dynobj, sreloc, 3)) 248033965Sjdp return false; 248133965Sjdp } 248233965Sjdp } 248333965Sjdp 248433965Sjdp if (h) 248533965Sjdp { 248633965Sjdp /* Since we havn't seen all of the input symbols yet, we 248733965Sjdp don't know whether we'll actually need a dynamic relocation 248833965Sjdp entry for this reloc. So make a record of it. Once we 248933965Sjdp find out if this thing needs dynamic relocation we'll 249077303Sobrien expand the relocation sections by the appropriate amount. */ 249133965Sjdp 249233965Sjdp struct alpha_elf_reloc_entry *rent; 249333965Sjdp 249433965Sjdp for (rent = h->reloc_entries; rent; rent = rent->next) 249533965Sjdp if (rent->rtype == r_type && rent->srel == sreloc) 249633965Sjdp break; 249733965Sjdp 249833965Sjdp if (!rent) 249933965Sjdp { 250089862Sobrien amt = sizeof (struct alpha_elf_reloc_entry); 250189862Sobrien rent = (struct alpha_elf_reloc_entry *) bfd_alloc (abfd, amt); 250233965Sjdp if (!rent) 250333965Sjdp return false; 250433965Sjdp 250533965Sjdp rent->srel = sreloc; 250633965Sjdp rent->rtype = r_type; 250733965Sjdp rent->count = 1; 250889862Sobrien rent->reltext = ((sec->flags & (SEC_READONLY | SEC_ALLOC)) 250989862Sobrien == (SEC_READONLY | SEC_ALLOC)); 251033965Sjdp 251133965Sjdp rent->next = h->reloc_entries; 251233965Sjdp h->reloc_entries = rent; 251333965Sjdp } 251433965Sjdp else 251533965Sjdp rent->count++; 251633965Sjdp } 251760510Sobrien else if (info->shared && (sec->flags & SEC_ALLOC)) 251833965Sjdp { 251960510Sobrien /* If this is a shared library, and the section is to be 252060510Sobrien loaded into memory, we need a RELATIVE reloc. */ 252133965Sjdp sreloc->_raw_size += sizeof (Elf64_External_Rela); 252289862Sobrien if (sec->flags & SEC_READONLY) 252389862Sobrien info->flags |= DF_TEXTREL; 252433965Sjdp } 252533965Sjdp break; 252633965Sjdp } 252733965Sjdp } 252833965Sjdp 252933965Sjdp return true; 253033965Sjdp} 253133965Sjdp 253233965Sjdp/* Adjust a symbol defined by a dynamic object and referenced by a 253333965Sjdp regular object. The current definition is in some section of the 253433965Sjdp dynamic object, but we're not including those sections. We have to 253533965Sjdp change the definition to something the rest of the link can 253633965Sjdp understand. */ 253733965Sjdp 253833965Sjdpstatic boolean 253933965Sjdpelf64_alpha_adjust_dynamic_symbol (info, h) 254033965Sjdp struct bfd_link_info *info; 254133965Sjdp struct elf_link_hash_entry *h; 254233965Sjdp{ 254333965Sjdp bfd *dynobj; 254433965Sjdp asection *s; 254533965Sjdp struct alpha_elf_link_hash_entry *ah; 254633965Sjdp 254733965Sjdp dynobj = elf_hash_table(info)->dynobj; 254833965Sjdp ah = (struct alpha_elf_link_hash_entry *)h; 254933965Sjdp 255033965Sjdp /* Now that we've seen all of the input symbols, finalize our decision 255133965Sjdp about whether this symbol should get a .plt entry. */ 255233965Sjdp 255389862Sobrien if (alpha_elf_dynamic_symbol_p (h, info) 255433965Sjdp && ((h->type == STT_FUNC 255533965Sjdp && !(ah->flags & ALPHA_ELF_LINK_HASH_LU_ADDR)) 255633965Sjdp || (h->type == STT_NOTYPE 255733965Sjdp && ah->flags == ALPHA_ELF_LINK_HASH_LU_FUNC)) 255833965Sjdp /* Don't prevent otherwise valid programs from linking by attempting 255933965Sjdp to create a new .got entry somewhere. A Correct Solution would be 256033965Sjdp to add a new .got section to a new object file and let it be merged 256133965Sjdp somewhere later. But for now don't bother. */ 256233965Sjdp && ah->got_entries) 256333965Sjdp { 256433965Sjdp h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; 256533965Sjdp 256633965Sjdp s = bfd_get_section_by_name(dynobj, ".plt"); 256733965Sjdp if (!s && !elf64_alpha_create_dynamic_sections (dynobj, info)) 256833965Sjdp return false; 256933965Sjdp 257033965Sjdp /* The first bit of the .plt is reserved. */ 257133965Sjdp if (s->_raw_size == 0) 257233965Sjdp s->_raw_size = PLT_HEADER_SIZE; 257333965Sjdp 257460510Sobrien h->plt.offset = s->_raw_size; 257533965Sjdp s->_raw_size += PLT_ENTRY_SIZE; 257633965Sjdp 257733965Sjdp /* If this symbol is not defined in a regular file, and we are not 257833965Sjdp generating a shared library, then set the symbol to the location 257933965Sjdp in the .plt. This is required to make function pointers compare 258033965Sjdp equal between the normal executable and the shared library. */ 258148850Sdfr if (! info->shared 258248850Sdfr && h->root.type != bfd_link_hash_defweak) 258333965Sjdp { 258433965Sjdp h->root.u.def.section = s; 258560510Sobrien h->root.u.def.value = h->plt.offset; 258633965Sjdp } 258733965Sjdp 258833965Sjdp /* We also need a JMP_SLOT entry in the .rela.plt section. */ 258933965Sjdp s = bfd_get_section_by_name (dynobj, ".rela.plt"); 259033965Sjdp BFD_ASSERT (s != NULL); 259133965Sjdp s->_raw_size += sizeof (Elf64_External_Rela); 259233965Sjdp 259333965Sjdp return true; 259433965Sjdp } 259533965Sjdp else 259633965Sjdp h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; 259733965Sjdp 259833965Sjdp /* If this is a weak symbol, and there is a real definition, the 259933965Sjdp processor independent code will have arranged for us to see the 260033965Sjdp real definition first, and we can just use the same value. */ 260133965Sjdp if (h->weakdef != NULL) 260233965Sjdp { 260333965Sjdp BFD_ASSERT (h->weakdef->root.type == bfd_link_hash_defined 260433965Sjdp || h->weakdef->root.type == bfd_link_hash_defweak); 260533965Sjdp h->root.u.def.section = h->weakdef->root.u.def.section; 260633965Sjdp h->root.u.def.value = h->weakdef->root.u.def.value; 260733965Sjdp return true; 260833965Sjdp } 260933965Sjdp 261033965Sjdp /* This is a reference to a symbol defined by a dynamic object which 261133965Sjdp is not a function. The Alpha, since it uses .got entries for all 261233965Sjdp symbols even in regular objects, does not need the hackery of a 261333965Sjdp .dynbss section and COPY dynamic relocations. */ 261433965Sjdp 261533965Sjdp return true; 261633965Sjdp} 261733965Sjdp 261838889Sjdp/* Symbol versioning can create new symbols, and make our old symbols 261938889Sjdp indirect to the new ones. Consolidate the got and reloc information 262038889Sjdp in these situations. */ 262138889Sjdp 262238889Sjdpstatic boolean 262338889Sjdpelf64_alpha_merge_ind_symbols (hi, dummy) 262438889Sjdp struct alpha_elf_link_hash_entry *hi; 262578833Sobrien PTR dummy ATTRIBUTE_UNUSED; 262638889Sjdp{ 262738889Sjdp struct alpha_elf_link_hash_entry *hs; 262838889Sjdp 262938889Sjdp if (hi->root.root.type != bfd_link_hash_indirect) 263038889Sjdp return true; 263138889Sjdp hs = hi; 263238889Sjdp do { 263338889Sjdp hs = (struct alpha_elf_link_hash_entry *)hs->root.root.u.i.link; 263438889Sjdp } while (hs->root.root.type == bfd_link_hash_indirect); 263538889Sjdp 263638889Sjdp /* Merge the flags. Whee. */ 263738889Sjdp 263838889Sjdp hs->flags |= hi->flags; 263938889Sjdp 264038889Sjdp /* Merge the .got entries. Cannibalize the old symbol's list in 264138889Sjdp doing so, since we don't need it anymore. */ 264238889Sjdp 264338889Sjdp if (hs->got_entries == NULL) 264438889Sjdp hs->got_entries = hi->got_entries; 264538889Sjdp else 264638889Sjdp { 264738889Sjdp struct alpha_elf_got_entry *gi, *gs, *gin, *gsh; 264838889Sjdp 264938889Sjdp gsh = hs->got_entries; 265038889Sjdp for (gi = hi->got_entries; gi ; gi = gin) 265138889Sjdp { 265238889Sjdp gin = gi->next; 265338889Sjdp for (gs = gsh; gs ; gs = gs->next) 265460510Sobrien if (gi->gotobj == gs->gotobj && gi->addend == gs->addend) 265538889Sjdp goto got_found; 265638889Sjdp gi->next = hs->got_entries; 265738889Sjdp hs->got_entries = gi; 265838889Sjdp got_found:; 265938889Sjdp } 266038889Sjdp } 266138889Sjdp hi->got_entries = NULL; 266238889Sjdp 266338889Sjdp /* And similar for the reloc entries. */ 266438889Sjdp 266538889Sjdp if (hs->reloc_entries == NULL) 266638889Sjdp hs->reloc_entries = hi->reloc_entries; 266738889Sjdp else 266838889Sjdp { 266938889Sjdp struct alpha_elf_reloc_entry *ri, *rs, *rin, *rsh; 267038889Sjdp 267138889Sjdp rsh = hs->reloc_entries; 267238889Sjdp for (ri = hi->reloc_entries; ri ; ri = rin) 267338889Sjdp { 267438889Sjdp rin = ri->next; 267538889Sjdp for (rs = rsh; rs ; rs = rs->next) 267638889Sjdp if (ri->rtype == rs->rtype) 267738889Sjdp { 267838889Sjdp rs->count += ri->count; 267938889Sjdp goto found_reloc; 268038889Sjdp } 268138889Sjdp ri->next = hs->reloc_entries; 268238889Sjdp hs->reloc_entries = ri; 268338889Sjdp found_reloc:; 268438889Sjdp } 268538889Sjdp } 268638889Sjdp hi->reloc_entries = NULL; 268738889Sjdp 268838889Sjdp return true; 268938889Sjdp} 269038889Sjdp 269133965Sjdp/* Is it possible to merge two object file's .got tables? */ 269233965Sjdp 269333965Sjdpstatic boolean 269433965Sjdpelf64_alpha_can_merge_gots (a, b) 269533965Sjdp bfd *a, *b; 269633965Sjdp{ 269733965Sjdp int total = alpha_elf_tdata (a)->total_got_entries; 269860510Sobrien bfd *bsub; 269933965Sjdp 270033965Sjdp /* Trivial quick fallout test. */ 270133965Sjdp if (total + alpha_elf_tdata (b)->total_got_entries <= MAX_GOT_ENTRIES) 270233965Sjdp return true; 270333965Sjdp 270433965Sjdp /* By their nature, local .got entries cannot be merged. */ 270533965Sjdp if ((total += alpha_elf_tdata (b)->n_local_got_entries) > MAX_GOT_ENTRIES) 270633965Sjdp return false; 270733965Sjdp 270833965Sjdp /* Failing the common trivial comparison, we must effectively 270933965Sjdp perform the merge. Not actually performing the merge means that 271033965Sjdp we don't have to store undo information in case we fail. */ 271160510Sobrien for (bsub = b; bsub ; bsub = alpha_elf_tdata (bsub)->in_got_link_next) 271260510Sobrien { 271360510Sobrien struct alpha_elf_link_hash_entry **hashes = alpha_elf_sym_hashes (bsub); 271460510Sobrien Elf_Internal_Shdr *symtab_hdr = &elf_tdata (bsub)->symtab_hdr; 271560510Sobrien int i, n; 271633965Sjdp 271778833Sobrien n = NUM_SHDR_ENTRIES (symtab_hdr) - symtab_hdr->sh_info; 271860510Sobrien for (i = 0; i < n; ++i) 271960510Sobrien { 272060510Sobrien struct alpha_elf_got_entry *ae, *be; 272160510Sobrien struct alpha_elf_link_hash_entry *h; 272238889Sjdp 272360510Sobrien h = hashes[i]; 272460510Sobrien while (h->root.root.type == bfd_link_hash_indirect 272560510Sobrien || h->root.root.type == bfd_link_hash_warning) 272660510Sobrien h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link; 272738889Sjdp 272860510Sobrien for (be = h->got_entries; be ; be = be->next) 272960510Sobrien { 273060510Sobrien if (be->use_count == 0) 273160510Sobrien continue; 273260510Sobrien if (be->gotobj != b) 273360510Sobrien continue; 273433965Sjdp 273560510Sobrien for (ae = h->got_entries; ae ; ae = ae->next) 273660510Sobrien if (ae->gotobj == a && ae->addend == be->addend) 273760510Sobrien goto global_found; 273833965Sjdp 273960510Sobrien if (++total > MAX_GOT_ENTRIES) 274060510Sobrien return false; 274160510Sobrien global_found:; 274260510Sobrien } 274360510Sobrien } 274460510Sobrien } 274533965Sjdp 274633965Sjdp return true; 274733965Sjdp} 274833965Sjdp 274933965Sjdp/* Actually merge two .got tables. */ 275033965Sjdp 275133965Sjdpstatic void 275233965Sjdpelf64_alpha_merge_gots (a, b) 275333965Sjdp bfd *a, *b; 275433965Sjdp{ 275560510Sobrien int total = alpha_elf_tdata (a)->total_got_entries; 275660510Sobrien bfd *bsub; 275733965Sjdp 275833965Sjdp /* Remember local expansion. */ 275933965Sjdp { 276060510Sobrien int e = alpha_elf_tdata (b)->n_local_got_entries; 276133965Sjdp total += e; 276260510Sobrien alpha_elf_tdata (a)->n_local_got_entries += e; 276333965Sjdp } 276433965Sjdp 276560510Sobrien for (bsub = b; bsub ; bsub = alpha_elf_tdata (bsub)->in_got_link_next) 276660510Sobrien { 276760510Sobrien struct alpha_elf_got_entry **local_got_entries; 276860510Sobrien struct alpha_elf_link_hash_entry **hashes; 276960510Sobrien Elf_Internal_Shdr *symtab_hdr; 277060510Sobrien int i, n; 277133965Sjdp 277260510Sobrien /* Let the local .got entries know they are part of a new subsegment. */ 277360510Sobrien local_got_entries = alpha_elf_tdata (bsub)->local_got_entries; 277460510Sobrien if (local_got_entries) 277560510Sobrien { 277660510Sobrien n = elf_tdata (bsub)->symtab_hdr.sh_info; 277760510Sobrien for (i = 0; i < n; ++i) 277860510Sobrien { 277960510Sobrien struct alpha_elf_got_entry *ent; 278060510Sobrien for (ent = local_got_entries[i]; ent; ent = ent->next) 278160510Sobrien ent->gotobj = a; 278260510Sobrien } 278360510Sobrien } 278433965Sjdp 278560510Sobrien /* Merge the global .got entries. */ 278660510Sobrien hashes = alpha_elf_sym_hashes (bsub); 278760510Sobrien symtab_hdr = &elf_tdata (bsub)->symtab_hdr; 278833965Sjdp 278978833Sobrien n = NUM_SHDR_ENTRIES (symtab_hdr) - symtab_hdr->sh_info; 279060510Sobrien for (i = 0; i < n; ++i) 279160510Sobrien { 279260510Sobrien struct alpha_elf_got_entry *ae, *be, **pbe, **start; 279360510Sobrien struct alpha_elf_link_hash_entry *h; 279438889Sjdp 279560510Sobrien h = hashes[i]; 279660510Sobrien while (h->root.root.type == bfd_link_hash_indirect 279760510Sobrien || h->root.root.type == bfd_link_hash_warning) 279860510Sobrien h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link; 279938889Sjdp 280060510Sobrien start = &h->got_entries; 280160510Sobrien for (pbe = start, be = *start; be ; pbe = &be->next, be = be->next) 280260510Sobrien { 280360510Sobrien if (be->use_count == 0) 280460510Sobrien { 280533965Sjdp *pbe = be->next; 280660510Sobrien continue; 280760510Sobrien } 280860510Sobrien if (be->gotobj != b) 280960510Sobrien continue; 281033965Sjdp 281160510Sobrien for (ae = *start; ae ; ae = ae->next) 281260510Sobrien if (ae->gotobj == a && ae->addend == be->addend) 281360510Sobrien { 281460510Sobrien ae->flags |= be->flags; 281560510Sobrien ae->use_count += be->use_count; 281660510Sobrien *pbe = be->next; 281760510Sobrien goto global_found; 281860510Sobrien } 281960510Sobrien be->gotobj = a; 282060510Sobrien total += 1; 282160510Sobrien 282260510Sobrien global_found:; 282360510Sobrien } 282460510Sobrien } 282560510Sobrien 282660510Sobrien alpha_elf_tdata (bsub)->gotobj = a; 282760510Sobrien } 282860510Sobrien alpha_elf_tdata (a)->total_got_entries = total; 282960510Sobrien 283060510Sobrien /* Merge the two in_got chains. */ 283160510Sobrien { 283260510Sobrien bfd *next; 283360510Sobrien 283460510Sobrien bsub = a; 283560510Sobrien while ((next = alpha_elf_tdata (bsub)->in_got_link_next) != NULL) 283660510Sobrien bsub = next; 283760510Sobrien 283860510Sobrien alpha_elf_tdata (bsub)->in_got_link_next = b; 283933965Sjdp } 284033965Sjdp} 284133965Sjdp 284233965Sjdp/* Calculate the offsets for the got entries. */ 284333965Sjdp 284433965Sjdpstatic boolean 284533965Sjdpelf64_alpha_calc_got_offsets_for_symbol (h, arg) 284633965Sjdp struct alpha_elf_link_hash_entry *h; 284789862Sobrien PTR arg ATTRIBUTE_UNUSED; 284833965Sjdp{ 284933965Sjdp struct alpha_elf_got_entry *gotent; 285033965Sjdp 285133965Sjdp for (gotent = h->got_entries; gotent; gotent = gotent->next) 285260510Sobrien if (gotent->use_count > 0) 285360510Sobrien { 285460510Sobrien bfd_size_type *plge 285560510Sobrien = &alpha_elf_tdata (gotent->gotobj)->got->_raw_size; 285633965Sjdp 285760510Sobrien gotent->got_offset = *plge; 285860510Sobrien *plge += 8; 285960510Sobrien } 286060510Sobrien 286133965Sjdp return true; 286233965Sjdp} 286333965Sjdp 286433965Sjdpstatic void 286533965Sjdpelf64_alpha_calc_got_offsets (info) 286633965Sjdp struct bfd_link_info *info; 286733965Sjdp{ 286833965Sjdp bfd *i, *got_list = alpha_elf_hash_table(info)->got_list; 286933965Sjdp 287033965Sjdp /* First, zero out the .got sizes, as we may be recalculating the 287133965Sjdp .got after optimizing it. */ 287233965Sjdp for (i = got_list; i ; i = alpha_elf_tdata(i)->got_link_next) 287333965Sjdp alpha_elf_tdata(i)->got->_raw_size = 0; 287433965Sjdp 287533965Sjdp /* Next, fill in the offsets for all the global entries. */ 287633965Sjdp alpha_elf_link_hash_traverse (alpha_elf_hash_table (info), 287733965Sjdp elf64_alpha_calc_got_offsets_for_symbol, 287833965Sjdp NULL); 287933965Sjdp 288033965Sjdp /* Finally, fill in the offsets for the local entries. */ 288133965Sjdp for (i = got_list; i ; i = alpha_elf_tdata(i)->got_link_next) 288233965Sjdp { 288333965Sjdp bfd_size_type got_offset = alpha_elf_tdata(i)->got->_raw_size; 288433965Sjdp bfd *j; 288533965Sjdp 288633965Sjdp for (j = i; j ; j = alpha_elf_tdata(j)->in_got_link_next) 288733965Sjdp { 288833965Sjdp struct alpha_elf_got_entry **local_got_entries, *gotent; 288933965Sjdp int k, n; 289033965Sjdp 289133965Sjdp local_got_entries = alpha_elf_tdata(j)->local_got_entries; 289233965Sjdp if (!local_got_entries) 289333965Sjdp continue; 289433965Sjdp 289533965Sjdp for (k = 0, n = elf_tdata(j)->symtab_hdr.sh_info; k < n; ++k) 289633965Sjdp for (gotent = local_got_entries[k]; gotent; gotent = gotent->next) 289760510Sobrien if (gotent->use_count > 0) 289860510Sobrien { 289960510Sobrien gotent->got_offset = got_offset; 290060510Sobrien got_offset += 8; 290160510Sobrien } 290233965Sjdp } 290333965Sjdp 290433965Sjdp alpha_elf_tdata(i)->got->_raw_size = got_offset; 290560510Sobrien alpha_elf_tdata(i)->got->_cooked_size = got_offset; 290633965Sjdp } 290733965Sjdp} 290833965Sjdp 290933965Sjdp/* Constructs the gots. */ 291033965Sjdp 291133965Sjdpstatic boolean 291260510Sobrienelf64_alpha_size_got_sections (output_bfd, info) 291389862Sobrien bfd *output_bfd ATTRIBUTE_UNUSED; 291433965Sjdp struct bfd_link_info *info; 291533965Sjdp{ 291689862Sobrien bfd *i, *got_list, *cur_got_obj = NULL; 291760510Sobrien int something_changed = 0; 291833965Sjdp 291960510Sobrien got_list = alpha_elf_hash_table (info)->got_list; 292033965Sjdp 292160510Sobrien /* On the first time through, pretend we have an existing got list 292260510Sobrien consisting of all of the input files. */ 292360510Sobrien if (got_list == NULL) 292433965Sjdp { 292560510Sobrien for (i = info->input_bfds; i ; i = i->link_next) 292660510Sobrien { 292760510Sobrien bfd *this_got = alpha_elf_tdata (i)->gotobj; 292860510Sobrien if (this_got == NULL) 292960510Sobrien continue; 293033965Sjdp 293160510Sobrien /* We are assuming no merging has yet ocurred. */ 293260510Sobrien BFD_ASSERT (this_got == i); 293333965Sjdp 293460510Sobrien if (alpha_elf_tdata (this_got)->total_got_entries > MAX_GOT_ENTRIES) 293533965Sjdp { 293660510Sobrien /* Yikes! A single object file has too many entries. */ 293760510Sobrien (*_bfd_error_handler) 293860510Sobrien (_("%s: .got subsegment exceeds 64K (size %d)"), 293989862Sobrien bfd_archive_filename (i), 294060510Sobrien alpha_elf_tdata (this_got)->total_got_entries * 8); 294160510Sobrien return false; 294233965Sjdp } 294360510Sobrien 294460510Sobrien if (got_list == NULL) 294560510Sobrien got_list = this_got; 294633965Sjdp else 294760510Sobrien alpha_elf_tdata(cur_got_obj)->got_link_next = this_got; 294860510Sobrien cur_got_obj = this_got; 294933965Sjdp } 295060510Sobrien 295160510Sobrien /* Strange degenerate case of no got references. */ 295260510Sobrien if (got_list == NULL) 295360510Sobrien return true; 295460510Sobrien 295560510Sobrien alpha_elf_hash_table (info)->got_list = got_list; 295660510Sobrien 295760510Sobrien /* Force got offsets to be recalculated. */ 295860510Sobrien something_changed = 1; 295960510Sobrien } 296060510Sobrien 296160510Sobrien cur_got_obj = got_list; 296260510Sobrien i = alpha_elf_tdata(cur_got_obj)->got_link_next; 296360510Sobrien while (i != NULL) 296460510Sobrien { 296560510Sobrien if (elf64_alpha_can_merge_gots (cur_got_obj, i)) 296660510Sobrien { 296760510Sobrien elf64_alpha_merge_gots (cur_got_obj, i); 296860510Sobrien i = alpha_elf_tdata(i)->got_link_next; 296960510Sobrien alpha_elf_tdata(cur_got_obj)->got_link_next = i; 297060510Sobrien something_changed = 1; 297160510Sobrien } 297233965Sjdp else 297333965Sjdp { 297433965Sjdp cur_got_obj = i; 297560510Sobrien i = alpha_elf_tdata(i)->got_link_next; 297633965Sjdp } 297733965Sjdp } 297833965Sjdp 297960510Sobrien /* Once the gots have been merged, fill in the got offsets for 298060510Sobrien everything therein. */ 298160510Sobrien if (1 || something_changed) 298260510Sobrien elf64_alpha_calc_got_offsets (info); 298333965Sjdp 298460510Sobrien return true; 298560510Sobrien} 298633965Sjdp 298760510Sobrienstatic boolean 298860510Sobrienelf64_alpha_always_size_sections (output_bfd, info) 298960510Sobrien bfd *output_bfd; 299060510Sobrien struct bfd_link_info *info; 299160510Sobrien{ 299260510Sobrien bfd *i; 299360510Sobrien 299460510Sobrien if (info->relocateable) 299560510Sobrien return true; 299660510Sobrien 299760510Sobrien /* First, take care of the indirect symbols created by versioning. */ 299860510Sobrien alpha_elf_link_hash_traverse (alpha_elf_hash_table (info), 299960510Sobrien elf64_alpha_merge_ind_symbols, 300060510Sobrien NULL); 300160510Sobrien 300260510Sobrien if (!elf64_alpha_size_got_sections (output_bfd, info)) 300360510Sobrien return false; 300460510Sobrien 300533965Sjdp /* Allocate space for all of the .got subsections. */ 300660510Sobrien i = alpha_elf_hash_table (info)->got_list; 300760510Sobrien for ( ; i ; i = alpha_elf_tdata(i)->got_link_next) 300833965Sjdp { 300933965Sjdp asection *s = alpha_elf_tdata(i)->got; 301033965Sjdp if (s->_raw_size > 0) 301133965Sjdp { 301233965Sjdp s->contents = (bfd_byte *) bfd_zalloc (i, s->_raw_size); 301333965Sjdp if (s->contents == NULL) 301433965Sjdp return false; 301533965Sjdp } 301633965Sjdp } 301733965Sjdp 301833965Sjdp return true; 301933965Sjdp} 302033965Sjdp 302133965Sjdp/* Work out the sizes of the dynamic relocation entries. */ 302233965Sjdp 302333965Sjdpstatic boolean 302433965Sjdpelf64_alpha_calc_dynrel_sizes (h, info) 302533965Sjdp struct alpha_elf_link_hash_entry *h; 302633965Sjdp struct bfd_link_info *info; 302733965Sjdp{ 302833965Sjdp /* If the symbol was defined as a common symbol in a regular object 302933965Sjdp file, and there was no definition in any dynamic object, then the 303033965Sjdp linker will have allocated space for the symbol in a common 303133965Sjdp section but the ELF_LINK_HASH_DEF_REGULAR flag will not have been 303233965Sjdp set. This is done for dynamic symbols in 303333965Sjdp elf_adjust_dynamic_symbol but this is not done for non-dynamic 303433965Sjdp symbols, somehow. */ 303533965Sjdp if (((h->root.elf_link_hash_flags 303633965Sjdp & (ELF_LINK_HASH_DEF_REGULAR 303733965Sjdp | ELF_LINK_HASH_REF_REGULAR 303833965Sjdp | ELF_LINK_HASH_DEF_DYNAMIC)) 303933965Sjdp == ELF_LINK_HASH_REF_REGULAR) 304033965Sjdp && (h->root.root.type == bfd_link_hash_defined 304133965Sjdp || h->root.root.type == bfd_link_hash_defweak) 304233965Sjdp && !(h->root.root.u.def.section->owner->flags & DYNAMIC)) 304333965Sjdp { 304433965Sjdp h->root.elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR; 304533965Sjdp } 304633965Sjdp 304733965Sjdp /* If the symbol is dynamic, we'll need all the relocations in their 304860510Sobrien natural form. If this is a shared object, and it has been forced 304960510Sobrien local, we'll need the same number of RELATIVE relocations. */ 305060510Sobrien 305160510Sobrien if (alpha_elf_dynamic_symbol_p (&h->root, info) || info->shared) 305233965Sjdp { 305333965Sjdp struct alpha_elf_reloc_entry *relent; 305448850Sdfr bfd *dynobj; 305548850Sdfr struct alpha_elf_got_entry *gotent; 305648850Sdfr bfd_size_type count; 305748850Sdfr asection *srel; 305833965Sjdp 305933965Sjdp for (relent = h->reloc_entries; relent; relent = relent->next) 306060510Sobrien if (relent->rtype == R_ALPHA_REFLONG 306160510Sobrien || relent->rtype == R_ALPHA_REFQUAD) 306260510Sobrien { 306360510Sobrien relent->srel->_raw_size += 306477303Sobrien sizeof (Elf64_External_Rela) * relent->count; 306589862Sobrien if (relent->reltext) 306689862Sobrien info->flags |= DT_TEXTREL; 306760510Sobrien } 306833965Sjdp 306948850Sdfr dynobj = elf_hash_table(info)->dynobj; 307048850Sdfr count = 0; 307148850Sdfr 307248850Sdfr for (gotent = h->got_entries; gotent ; gotent = gotent->next) 307348850Sdfr count++; 307448850Sdfr 307548850Sdfr /* If we are using a .plt entry, subtract one, as the first 307648850Sdfr reference uses a .rela.plt entry instead. */ 307760510Sobrien if (h->root.plt.offset != MINUS_ONE) 307848850Sdfr count--; 307948850Sdfr 308048850Sdfr if (count > 0) 308133965Sjdp { 308248850Sdfr srel = bfd_get_section_by_name (dynobj, ".rela.got"); 308348850Sdfr BFD_ASSERT (srel != NULL); 308448850Sdfr srel->_raw_size += sizeof (Elf64_External_Rela) * count; 308533965Sjdp } 308633965Sjdp } 308748850Sdfr 308833965Sjdp return true; 308933965Sjdp} 309033965Sjdp 309133965Sjdp/* Set the sizes of the dynamic sections. */ 309233965Sjdp 309333965Sjdpstatic boolean 309433965Sjdpelf64_alpha_size_dynamic_sections (output_bfd, info) 309589862Sobrien bfd *output_bfd ATTRIBUTE_UNUSED; 309633965Sjdp struct bfd_link_info *info; 309733965Sjdp{ 309833965Sjdp bfd *dynobj; 309933965Sjdp asection *s; 310033965Sjdp boolean relplt; 310133965Sjdp 310233965Sjdp dynobj = elf_hash_table(info)->dynobj; 310333965Sjdp BFD_ASSERT(dynobj != NULL); 310433965Sjdp 310533965Sjdp if (elf_hash_table (info)->dynamic_sections_created) 310633965Sjdp { 310733965Sjdp /* Set the contents of the .interp section to the interpreter. */ 310833965Sjdp if (!info->shared) 310933965Sjdp { 311033965Sjdp s = bfd_get_section_by_name (dynobj, ".interp"); 311133965Sjdp BFD_ASSERT (s != NULL); 311233965Sjdp s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER; 311333965Sjdp s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER; 311433965Sjdp } 311533965Sjdp 311633965Sjdp /* Now that we've seen all of the input files, we can decide which 311733965Sjdp symbols need dynamic relocation entries and which don't. We've 311833965Sjdp collected information in check_relocs that we can now apply to 311933965Sjdp size the dynamic relocation sections. */ 312033965Sjdp alpha_elf_link_hash_traverse (alpha_elf_hash_table (info), 312133965Sjdp elf64_alpha_calc_dynrel_sizes, 312233965Sjdp info); 312333965Sjdp 312433965Sjdp /* When building shared libraries, each local .got entry needs a 312533965Sjdp RELATIVE reloc. */ 312633965Sjdp if (info->shared) 312733965Sjdp { 312833965Sjdp bfd *i; 312933965Sjdp asection *srel; 313033965Sjdp bfd_size_type count; 313133965Sjdp 313233965Sjdp srel = bfd_get_section_by_name (dynobj, ".rela.got"); 313333965Sjdp BFD_ASSERT (srel != NULL); 313433965Sjdp 313533965Sjdp for (i = alpha_elf_hash_table(info)->got_list, count = 0; 313633965Sjdp i != NULL; 313733965Sjdp i = alpha_elf_tdata(i)->got_link_next) 313833965Sjdp count += alpha_elf_tdata(i)->n_local_got_entries; 313933965Sjdp 314077303Sobrien srel->_raw_size += count * sizeof (Elf64_External_Rela); 314133965Sjdp } 314233965Sjdp } 314333965Sjdp /* else we're not dynamic and by definition we don't need such things. */ 314433965Sjdp 314533965Sjdp /* The check_relocs and adjust_dynamic_symbol entry points have 314633965Sjdp determined the sizes of the various dynamic sections. Allocate 314733965Sjdp memory for them. */ 314833965Sjdp relplt = false; 314933965Sjdp for (s = dynobj->sections; s != NULL; s = s->next) 315033965Sjdp { 315133965Sjdp const char *name; 315233965Sjdp boolean strip; 315333965Sjdp 315433965Sjdp if (!(s->flags & SEC_LINKER_CREATED)) 315533965Sjdp continue; 315633965Sjdp 315733965Sjdp /* It's OK to base decisions on the section name, because none 315833965Sjdp of the dynobj section names depend upon the input files. */ 315933965Sjdp name = bfd_get_section_name (dynobj, s); 316033965Sjdp 316133965Sjdp /* If we don't need this section, strip it from the output file. 316233965Sjdp This is to handle .rela.bss and .rela.plt. We must create it 316333965Sjdp in create_dynamic_sections, because it must be created before 316433965Sjdp the linker maps input sections to output sections. The 316533965Sjdp linker does that before adjust_dynamic_symbol is called, and 316633965Sjdp it is that function which decides whether anything needs to 316733965Sjdp go into these sections. */ 316833965Sjdp 316933965Sjdp strip = false; 317033965Sjdp 317133965Sjdp if (strncmp (name, ".rela", 5) == 0) 317233965Sjdp { 317333965Sjdp strip = (s->_raw_size == 0); 317433965Sjdp 317533965Sjdp if (!strip) 317633965Sjdp { 317733965Sjdp if (strcmp(name, ".rela.plt") == 0) 317833965Sjdp relplt = true; 317933965Sjdp 318033965Sjdp /* We use the reloc_count field as a counter if we need 318133965Sjdp to copy relocs into the output file. */ 318233965Sjdp s->reloc_count = 0; 318333965Sjdp } 318433965Sjdp } 318533965Sjdp else if (strcmp (name, ".plt") != 0) 318633965Sjdp { 318733965Sjdp /* It's not one of our dynamic sections, so don't allocate space. */ 318833965Sjdp continue; 318933965Sjdp } 319033965Sjdp 319133965Sjdp if (strip) 319260510Sobrien _bfd_strip_section_from_output (info, s); 319333965Sjdp else 319433965Sjdp { 319533965Sjdp /* Allocate memory for the section contents. */ 319689862Sobrien s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size); 319733965Sjdp if (s->contents == NULL && s->_raw_size != 0) 319833965Sjdp return false; 319933965Sjdp } 320033965Sjdp } 320133965Sjdp 320233965Sjdp if (elf_hash_table (info)->dynamic_sections_created) 320333965Sjdp { 320433965Sjdp /* Add some entries to the .dynamic section. We fill in the 320533965Sjdp values later, in elf64_alpha_finish_dynamic_sections, but we 320633965Sjdp must add the entries now so that we get the correct size for 320733965Sjdp the .dynamic section. The DT_DEBUG entry is filled in by the 320833965Sjdp dynamic linker and used by the debugger. */ 320989862Sobrien#define add_dynamic_entry(TAG, VAL) \ 321089862Sobrien bfd_elf64_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL)) 321189862Sobrien 321233965Sjdp if (!info->shared) 321333965Sjdp { 321489862Sobrien if (!add_dynamic_entry (DT_DEBUG, 0)) 321533965Sjdp return false; 321633965Sjdp } 321733965Sjdp 321889862Sobrien if (!add_dynamic_entry (DT_PLTGOT, 0)) 321933965Sjdp return false; 322033965Sjdp 322133965Sjdp if (relplt) 322233965Sjdp { 322389862Sobrien if (!add_dynamic_entry (DT_PLTRELSZ, 0) 322489862Sobrien || !add_dynamic_entry (DT_PLTREL, DT_RELA) 322589862Sobrien || !add_dynamic_entry (DT_JMPREL, 0)) 322633965Sjdp return false; 322733965Sjdp } 322833965Sjdp 322989862Sobrien if (!add_dynamic_entry (DT_RELA, 0) 323089862Sobrien || !add_dynamic_entry (DT_RELASZ, 0) 323189862Sobrien || !add_dynamic_entry (DT_RELAENT, sizeof (Elf64_External_Rela))) 323233965Sjdp return false; 323333965Sjdp 323489862Sobrien if (info->flags & DF_TEXTREL) 323533965Sjdp { 323689862Sobrien if (!add_dynamic_entry (DT_TEXTREL, 0)) 323733965Sjdp return false; 323833965Sjdp } 323933965Sjdp } 324089862Sobrien#undef add_dynamic_entry 324133965Sjdp 324233965Sjdp return true; 324333965Sjdp} 324433965Sjdp 324533965Sjdp/* Relocate an Alpha ELF section. */ 324633965Sjdp 324733965Sjdpstatic boolean 324833965Sjdpelf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section, 324933965Sjdp contents, relocs, local_syms, local_sections) 325033965Sjdp bfd *output_bfd; 325133965Sjdp struct bfd_link_info *info; 325233965Sjdp bfd *input_bfd; 325333965Sjdp asection *input_section; 325433965Sjdp bfd_byte *contents; 325533965Sjdp Elf_Internal_Rela *relocs; 325633965Sjdp Elf_Internal_Sym *local_syms; 325733965Sjdp asection **local_sections; 325833965Sjdp{ 325933965Sjdp Elf_Internal_Shdr *symtab_hdr; 326033965Sjdp Elf_Internal_Rela *rel; 326133965Sjdp Elf_Internal_Rela *relend; 326233965Sjdp asection *sec, *sgot, *srel, *srelgot; 326333965Sjdp bfd *dynobj, *gotobj; 326433965Sjdp bfd_vma gp; 326589862Sobrien boolean ret_val = true; 326633965Sjdp 326733965Sjdp srelgot = srel = NULL; 326833965Sjdp symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; 326933965Sjdp dynobj = elf_hash_table (info)->dynobj; 327033965Sjdp if (dynobj) 327133965Sjdp { 327233965Sjdp srelgot = bfd_get_section_by_name (dynobj, ".rela.got"); 327333965Sjdp } 327433965Sjdp 327533965Sjdp /* Find the gp value for this input bfd. */ 327633965Sjdp sgot = NULL; 327733965Sjdp gp = 0; 327833965Sjdp gotobj = alpha_elf_tdata (input_bfd)->gotobj; 327933965Sjdp if (gotobj) 328033965Sjdp { 328133965Sjdp sgot = alpha_elf_tdata (gotobj)->got; 328233965Sjdp gp = _bfd_get_gp_value (gotobj); 328333965Sjdp if (gp == 0) 328433965Sjdp { 328533965Sjdp gp = (sgot->output_section->vma 328633965Sjdp + sgot->output_offset 328733965Sjdp + 0x8000); 328833965Sjdp _bfd_set_gp_value (gotobj, gp); 328933965Sjdp } 329033965Sjdp } 329133965Sjdp 329233965Sjdp rel = relocs; 329333965Sjdp relend = relocs + input_section->reloc_count; 329433965Sjdp for (; rel < relend; rel++) 329533965Sjdp { 329633965Sjdp int r_type; 329733965Sjdp reloc_howto_type *howto; 329833965Sjdp unsigned long r_symndx; 329933965Sjdp struct alpha_elf_link_hash_entry *h; 330033965Sjdp Elf_Internal_Sym *sym; 330133965Sjdp bfd_vma relocation; 330233965Sjdp bfd_vma addend; 330333965Sjdp bfd_reloc_status_type r; 330433965Sjdp 330533965Sjdp r_type = ELF64_R_TYPE(rel->r_info); 330633965Sjdp if (r_type < 0 || r_type >= (int) R_ALPHA_max) 330733965Sjdp { 330833965Sjdp bfd_set_error (bfd_error_bad_value); 330933965Sjdp return false; 331033965Sjdp } 331133965Sjdp howto = elf64_alpha_howto_table + r_type; 331233965Sjdp 331333965Sjdp r_symndx = ELF64_R_SYM(rel->r_info); 331433965Sjdp 331533965Sjdp if (info->relocateable) 331633965Sjdp { 331733965Sjdp /* This is a relocateable link. We don't have to change 331833965Sjdp anything, unless the reloc is against a section symbol, 331933965Sjdp in which case we have to adjust according to where the 332033965Sjdp section symbol winds up in the output section. */ 332160510Sobrien 332277303Sobrien /* The symbol associated with GPDISP and LITUSE is 332360510Sobrien immaterial. Only the addend is significant. */ 332460510Sobrien if (r_type == R_ALPHA_GPDISP || r_type == R_ALPHA_LITUSE) 332560510Sobrien continue; 332660510Sobrien 332733965Sjdp if (r_symndx < symtab_hdr->sh_info) 332833965Sjdp { 332933965Sjdp sym = local_syms + r_symndx; 333033965Sjdp if (ELF_ST_TYPE(sym->st_info) == STT_SECTION) 333133965Sjdp { 333233965Sjdp sec = local_sections[r_symndx]; 333333965Sjdp rel->r_addend += sec->output_offset + sym->st_value; 333433965Sjdp } 333533965Sjdp } 333633965Sjdp 333733965Sjdp continue; 333833965Sjdp } 333933965Sjdp 334033965Sjdp /* This is a final link. */ 334133965Sjdp 334233965Sjdp h = NULL; 334333965Sjdp sym = NULL; 334433965Sjdp sec = NULL; 334533965Sjdp 334633965Sjdp if (r_symndx < symtab_hdr->sh_info) 334733965Sjdp { 334833965Sjdp sym = local_syms + r_symndx; 334933965Sjdp sec = local_sections[r_symndx]; 335089862Sobrien relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel); 335133965Sjdp } 335233965Sjdp else 335333965Sjdp { 335433965Sjdp h = alpha_elf_sym_hashes (input_bfd)[r_symndx - symtab_hdr->sh_info]; 335533965Sjdp 335633965Sjdp while (h->root.root.type == bfd_link_hash_indirect 335733965Sjdp || h->root.root.type == bfd_link_hash_warning) 335833965Sjdp h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link; 335933965Sjdp 336033965Sjdp if (h->root.root.type == bfd_link_hash_defined 336133965Sjdp || h->root.root.type == bfd_link_hash_defweak) 336233965Sjdp { 336333965Sjdp sec = h->root.root.u.def.section; 336433965Sjdp 336533965Sjdp if (sec->output_section == NULL) 336633965Sjdp relocation = 0; 336733965Sjdp else 336833965Sjdp { 336933965Sjdp relocation = (h->root.root.u.def.value 337033965Sjdp + sec->output_section->vma 337133965Sjdp + sec->output_offset); 337233965Sjdp } 337333965Sjdp } 337433965Sjdp else if (h->root.root.type == bfd_link_hash_undefweak) 337533965Sjdp relocation = 0; 337689862Sobrien else if (info->shared 337789862Sobrien && (!info->symbolic || info->allow_shlib_undefined) 337868770Sobrien && !info->no_undefined 337968770Sobrien && ELF_ST_VISIBILITY (h->root.other) == STV_DEFAULT) 338033965Sjdp relocation = 0; 338133965Sjdp else 338233965Sjdp { 338333965Sjdp if (!((*info->callbacks->undefined_symbol) 338433965Sjdp (info, h->root.root.root.string, input_bfd, 338560510Sobrien input_section, rel->r_offset, 338668770Sobrien (!info->shared || info->no_undefined 338768770Sobrien || ELF_ST_VISIBILITY (h->root.other))))) 338889862Sobrien ret_val = false; 338933965Sjdp relocation = 0; 339033965Sjdp } 339133965Sjdp } 339233965Sjdp addend = rel->r_addend; 339333965Sjdp 339433965Sjdp switch (r_type) 339533965Sjdp { 339633965Sjdp case R_ALPHA_GPDISP: 339733965Sjdp { 339833965Sjdp bfd_byte *p_ldah, *p_lda; 339933965Sjdp 340033965Sjdp BFD_ASSERT(gp != 0); 340133965Sjdp 340233965Sjdp relocation = (input_section->output_section->vma 340333965Sjdp + input_section->output_offset 340433965Sjdp + rel->r_offset); 340533965Sjdp 340633965Sjdp p_ldah = contents + rel->r_offset - input_section->vma; 340733965Sjdp p_lda = p_ldah + rel->r_addend; 340833965Sjdp 340933965Sjdp r = elf64_alpha_do_reloc_gpdisp (input_bfd, gp - relocation, 341033965Sjdp p_ldah, p_lda); 341133965Sjdp } 341233965Sjdp break; 341333965Sjdp 341433965Sjdp case R_ALPHA_LITERAL: 341533965Sjdp { 341633965Sjdp struct alpha_elf_got_entry *gotent; 341760510Sobrien boolean dynamic_symbol; 341833965Sjdp 341933965Sjdp BFD_ASSERT(sgot != NULL); 342033965Sjdp BFD_ASSERT(gp != 0); 342133965Sjdp 342233965Sjdp if (h != NULL) 342333965Sjdp { 342433965Sjdp gotent = h->got_entries; 342560510Sobrien dynamic_symbol = alpha_elf_dynamic_symbol_p (&h->root, info); 342633965Sjdp } 342733965Sjdp else 342833965Sjdp { 342933965Sjdp gotent = (alpha_elf_tdata(input_bfd)-> 343033965Sjdp local_got_entries[r_symndx]); 343160510Sobrien dynamic_symbol = false; 343289862Sobrien 343389862Sobrien /* Need to adjust local GOT entries' addends for SEC_MERGE 343489862Sobrien unless it has been done already. */ 343589862Sobrien if ((sec->flags & SEC_MERGE) 343689862Sobrien && ELF_ST_TYPE (sym->st_info) == STT_SECTION 343789862Sobrien && (elf_section_data (sec)->sec_info_type 343889862Sobrien == ELF_INFO_TYPE_MERGE) 343989862Sobrien && (gotent->flags & ALPHA_ELF_GOT_ENTRY_RELOCS_XLATED) == 0) 344089862Sobrien { 344189862Sobrien struct alpha_elf_got_entry *ent; 344289862Sobrien asection *msec; 344389862Sobrien 344489862Sobrien for (ent = gotent; ent; ent = ent->next) 344589862Sobrien { 344689862Sobrien ent->flags |= ALPHA_ELF_GOT_ENTRY_RELOCS_XLATED; 344789862Sobrien if (ent->use_count == 0) 344889862Sobrien continue; 344989862Sobrien msec = sec; 345089862Sobrien ent->addend = 345189862Sobrien _bfd_merged_section_offset (output_bfd, &msec, 345289862Sobrien elf_section_data (sec)-> 345389862Sobrien sec_info, 345489862Sobrien sym->st_value 345589862Sobrien + ent->addend, 345689862Sobrien (bfd_vma) 0); 345789862Sobrien ent->addend -= sym->st_value; 345889862Sobrien ent->addend += msec->output_section->vma 345989862Sobrien + msec->output_offset 346089862Sobrien - sec->output_section->vma 346189862Sobrien - sec->output_offset; 346289862Sobrien } 346389862Sobrien } 346460510Sobrien } 346533965Sjdp 346660510Sobrien BFD_ASSERT(gotent != NULL); 346733965Sjdp 346860510Sobrien while (gotent->gotobj != gotobj || gotent->addend != addend) 346960510Sobrien gotent = gotent->next; 347033965Sjdp 347160510Sobrien BFD_ASSERT(gotent->use_count >= 1); 347233965Sjdp 347360510Sobrien /* Initialize the .got entry's value. */ 347460510Sobrien if (!(gotent->flags & ALPHA_ELF_GOT_ENTRY_RELOCS_DONE)) 347560510Sobrien { 347689862Sobrien bfd_put_64 (output_bfd, relocation + addend, 347760510Sobrien sgot->contents + gotent->got_offset); 347833965Sjdp 347960510Sobrien /* If the symbol has been forced local, output a 348060510Sobrien RELATIVE reloc, otherwise it will be handled in 348160510Sobrien finish_dynamic_symbol. */ 348260510Sobrien if (info->shared && !dynamic_symbol) 348360510Sobrien { 348460510Sobrien Elf_Internal_Rela outrel; 348533965Sjdp 348660510Sobrien BFD_ASSERT(srelgot != NULL); 348760510Sobrien 348860510Sobrien outrel.r_offset = (sgot->output_section->vma 348960510Sobrien + sgot->output_offset 349060510Sobrien + gotent->got_offset); 349160510Sobrien outrel.r_info = ELF64_R_INFO(0, R_ALPHA_RELATIVE); 349289862Sobrien outrel.r_addend = relocation + addend; 349360510Sobrien 349460510Sobrien bfd_elf64_swap_reloca_out (output_bfd, &outrel, 349560510Sobrien ((Elf64_External_Rela *) 349660510Sobrien srelgot->contents) 349760510Sobrien + srelgot->reloc_count++); 349877303Sobrien BFD_ASSERT (sizeof (Elf64_External_Rela) 349960510Sobrien * srelgot->reloc_count 350060510Sobrien <= srelgot->_cooked_size); 350133965Sjdp } 350260510Sobrien 350360510Sobrien gotent->flags |= ALPHA_ELF_GOT_ENTRY_RELOCS_DONE; 350433965Sjdp } 350533965Sjdp 350633965Sjdp /* Figure the gprel relocation. */ 350733965Sjdp addend = 0; 350833965Sjdp relocation = (sgot->output_section->vma 350933965Sjdp + sgot->output_offset 351033965Sjdp + gotent->got_offset); 351133965Sjdp relocation -= gp; 351233965Sjdp } 351333965Sjdp /* overflow handled by _bfd_final_link_relocate */ 351433965Sjdp goto default_reloc; 351533965Sjdp 351689862Sobrien case R_ALPHA_GPREL16: 351733965Sjdp case R_ALPHA_GPREL32: 351860510Sobrien case R_ALPHA_GPRELLOW: 351989862Sobrien if (h && alpha_elf_dynamic_symbol_p (&h->root, info)) 352089862Sobrien { 352189862Sobrien (*_bfd_error_handler) 352289862Sobrien (_("%s: gp-relative relocation against dynamic symbol %s"), 352389862Sobrien bfd_archive_filename (input_bfd), h->root.root.root.string); 352489862Sobrien ret_val = false; 352589862Sobrien } 352633965Sjdp BFD_ASSERT(gp != 0); 352733965Sjdp relocation -= gp; 352833965Sjdp goto default_reloc; 352933965Sjdp 353060510Sobrien case R_ALPHA_GPRELHIGH: 353189862Sobrien if (h && alpha_elf_dynamic_symbol_p (&h->root, info)) 353289862Sobrien { 353389862Sobrien (*_bfd_error_handler) 353489862Sobrien (_("%s: gp-relative relocation against dynamic symbol %s"), 353589862Sobrien bfd_archive_filename (input_bfd), h->root.root.root.string); 353689862Sobrien ret_val = false; 353789862Sobrien } 353860510Sobrien BFD_ASSERT(gp != 0); 353960510Sobrien relocation -= gp; 354060510Sobrien relocation += addend; 354160510Sobrien addend = 0; 354260510Sobrien relocation = (((bfd_signed_vma) relocation >> 16) 354360510Sobrien + ((relocation >> 15) & 1)); 354460510Sobrien goto default_reloc; 354560510Sobrien 354689862Sobrien case R_ALPHA_HINT: 354789862Sobrien /* A call to a dynamic symbol is definitely out of range of 354889862Sobrien the 16-bit displacement. Don't bother writing anything. */ 354989862Sobrien if (h && alpha_elf_dynamic_symbol_p (&h->root, info)) 355089862Sobrien { 355189862Sobrien r = bfd_reloc_ok; 355289862Sobrien break; 355389862Sobrien } 355489862Sobrien /* FALLTHRU */ 355589862Sobrien 355633965Sjdp case R_ALPHA_BRADDR: 355733965Sjdp /* The regular PC-relative stuff measures from the start of 355833965Sjdp the instruction rather than the end. */ 355933965Sjdp addend -= 4; 356033965Sjdp goto default_reloc; 356133965Sjdp 356233965Sjdp case R_ALPHA_REFLONG: 356333965Sjdp case R_ALPHA_REFQUAD: 356433965Sjdp { 356533965Sjdp Elf_Internal_Rela outrel; 356633965Sjdp 356733965Sjdp /* Careful here to remember RELATIVE relocations for global 356833965Sjdp variables for symbolic shared objects. */ 356933965Sjdp 357033965Sjdp if (h && alpha_elf_dynamic_symbol_p (&h->root, info)) 357133965Sjdp { 357233965Sjdp BFD_ASSERT(h->root.dynindx != -1); 357333965Sjdp outrel.r_info = ELF64_R_INFO(h->root.dynindx, r_type); 357433965Sjdp outrel.r_addend = addend; 357533965Sjdp addend = 0, relocation = 0; 357633965Sjdp } 357789862Sobrien else if (info->shared 357889862Sobrien && r_symndx != 0 357989862Sobrien && (input_section->flags & SEC_ALLOC)) 358033965Sjdp { 358133965Sjdp outrel.r_info = ELF64_R_INFO(0, R_ALPHA_RELATIVE); 358289862Sobrien outrel.r_addend = relocation + addend; 358333965Sjdp } 358433965Sjdp else 358533965Sjdp goto default_reloc; 358633965Sjdp 358733965Sjdp if (!srel) 358833965Sjdp { 358933965Sjdp const char *name; 359033965Sjdp 359133965Sjdp name = (bfd_elf_string_from_elf_section 359233965Sjdp (input_bfd, elf_elfheader(input_bfd)->e_shstrndx, 359333965Sjdp elf_section_data(input_section)->rel_hdr.sh_name)); 359433965Sjdp BFD_ASSERT(name != NULL); 359533965Sjdp 359633965Sjdp srel = bfd_get_section_by_name (dynobj, name); 359733965Sjdp BFD_ASSERT(srel != NULL); 359833965Sjdp } 359933965Sjdp 360089862Sobrien outrel.r_offset = 360189862Sobrien _bfd_elf_section_offset (output_bfd, info, input_section, 360289862Sobrien rel->r_offset); 360389862Sobrien if (outrel.r_offset != (bfd_vma) -1) 360433965Sjdp outrel.r_offset += (input_section->output_section->vma 360533965Sjdp + input_section->output_offset); 360633965Sjdp else 360733965Sjdp memset (&outrel, 0, sizeof outrel); 360833965Sjdp 360933965Sjdp bfd_elf64_swap_reloca_out (output_bfd, &outrel, 361033965Sjdp ((Elf64_External_Rela *) 361133965Sjdp srel->contents) 361233965Sjdp + srel->reloc_count++); 361377303Sobrien BFD_ASSERT (sizeof (Elf64_External_Rela) * srel->reloc_count 361448850Sdfr <= srel->_cooked_size); 361533965Sjdp } 361633965Sjdp goto default_reloc; 361733965Sjdp 361833965Sjdp default: 361933965Sjdp default_reloc: 362033965Sjdp r = _bfd_final_link_relocate (howto, input_bfd, input_section, 362133965Sjdp contents, rel->r_offset, relocation, 362233965Sjdp addend); 362333965Sjdp break; 362433965Sjdp } 362533965Sjdp 362633965Sjdp switch (r) 362733965Sjdp { 362833965Sjdp case bfd_reloc_ok: 362933965Sjdp break; 363033965Sjdp 363133965Sjdp case bfd_reloc_overflow: 363233965Sjdp { 363333965Sjdp const char *name; 363433965Sjdp 363589862Sobrien /* Don't warn if the overflow is due to pc relative reloc 363689862Sobrien against discarded section. Section optimization code should 363789862Sobrien handle it. */ 363889862Sobrien 363989862Sobrien if (r_symndx < symtab_hdr->sh_info 364089862Sobrien && sec != NULL && howto->pc_relative 364189862Sobrien && elf_discarded_section (sec)) 364289862Sobrien break; 364389862Sobrien 364433965Sjdp if (h != NULL) 364533965Sjdp name = h->root.root.root.string; 364633965Sjdp else 364733965Sjdp { 364833965Sjdp name = (bfd_elf_string_from_elf_section 364933965Sjdp (input_bfd, symtab_hdr->sh_link, sym->st_name)); 365033965Sjdp if (name == NULL) 365133965Sjdp return false; 365233965Sjdp if (*name == '\0') 365333965Sjdp name = bfd_section_name (input_bfd, sec); 365433965Sjdp } 365533965Sjdp if (! ((*info->callbacks->reloc_overflow) 365633965Sjdp (info, name, howto->name, (bfd_vma) 0, 365733965Sjdp input_bfd, input_section, rel->r_offset))) 365889862Sobrien ret_val = false; 365933965Sjdp } 366033965Sjdp break; 366133965Sjdp 366233965Sjdp default: 366333965Sjdp case bfd_reloc_outofrange: 366433965Sjdp abort (); 366533965Sjdp } 366633965Sjdp } 366733965Sjdp 366889862Sobrien return ret_val; 366933965Sjdp} 367033965Sjdp 367133965Sjdp/* Finish up dynamic symbol handling. We set the contents of various 367233965Sjdp dynamic sections here. */ 367333965Sjdp 367433965Sjdpstatic boolean 367533965Sjdpelf64_alpha_finish_dynamic_symbol (output_bfd, info, h, sym) 367633965Sjdp bfd *output_bfd; 367733965Sjdp struct bfd_link_info *info; 367833965Sjdp struct elf_link_hash_entry *h; 367933965Sjdp Elf_Internal_Sym *sym; 368033965Sjdp{ 368133965Sjdp bfd *dynobj = elf_hash_table(info)->dynobj; 368233965Sjdp 368360510Sobrien if (h->plt.offset != MINUS_ONE) 368433965Sjdp { 368533965Sjdp /* Fill in the .plt entry for this symbol. */ 368633965Sjdp asection *splt, *sgot, *srel; 368733965Sjdp Elf_Internal_Rela outrel; 368833965Sjdp bfd_vma got_addr, plt_addr; 368933965Sjdp bfd_vma plt_index; 369033965Sjdp struct alpha_elf_got_entry *gotent; 369133965Sjdp 369233965Sjdp BFD_ASSERT (h->dynindx != -1); 369333965Sjdp 369433965Sjdp /* The first .got entry will be updated by the .plt with the 369533965Sjdp address of the target function. */ 369633965Sjdp gotent = ((struct alpha_elf_link_hash_entry *) h)->got_entries; 369733965Sjdp BFD_ASSERT (gotent && gotent->addend == 0); 369833965Sjdp 369933965Sjdp splt = bfd_get_section_by_name (dynobj, ".plt"); 370033965Sjdp BFD_ASSERT (splt != NULL); 370133965Sjdp srel = bfd_get_section_by_name (dynobj, ".rela.plt"); 370233965Sjdp BFD_ASSERT (srel != NULL); 370333965Sjdp sgot = alpha_elf_tdata (gotent->gotobj)->got; 370433965Sjdp BFD_ASSERT (sgot != NULL); 370533965Sjdp 370633965Sjdp got_addr = (sgot->output_section->vma 370733965Sjdp + sgot->output_offset 370833965Sjdp + gotent->got_offset); 370933965Sjdp plt_addr = (splt->output_section->vma 371033965Sjdp + splt->output_offset 371160510Sobrien + h->plt.offset); 371233965Sjdp 371360510Sobrien plt_index = (h->plt.offset - PLT_HEADER_SIZE) / PLT_ENTRY_SIZE; 371433965Sjdp 371533965Sjdp /* Fill in the entry in the procedure linkage table. */ 371633965Sjdp { 371789862Sobrien bfd_vma insn1, insn2, insn3; 371833965Sjdp 371960510Sobrien insn1 = PLT_ENTRY_WORD1 | ((-(h->plt.offset + 4) >> 2) & 0x1fffff); 372038889Sjdp insn2 = PLT_ENTRY_WORD2; 372138889Sjdp insn3 = PLT_ENTRY_WORD3; 372233965Sjdp 372360510Sobrien bfd_put_32 (output_bfd, insn1, splt->contents + h->plt.offset); 372460510Sobrien bfd_put_32 (output_bfd, insn2, splt->contents + h->plt.offset + 4); 372560510Sobrien bfd_put_32 (output_bfd, insn3, splt->contents + h->plt.offset + 8); 372633965Sjdp } 372733965Sjdp 372833965Sjdp /* Fill in the entry in the .rela.plt section. */ 372933965Sjdp outrel.r_offset = got_addr; 373033965Sjdp outrel.r_info = ELF64_R_INFO(h->dynindx, R_ALPHA_JMP_SLOT); 373133965Sjdp outrel.r_addend = 0; 373233965Sjdp 373333965Sjdp bfd_elf64_swap_reloca_out (output_bfd, &outrel, 373433965Sjdp ((Elf64_External_Rela *)srel->contents 373533965Sjdp + plt_index)); 373633965Sjdp 373733965Sjdp if (!(h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)) 373833965Sjdp { 373933965Sjdp /* Mark the symbol as undefined, rather than as defined in the 374033965Sjdp .plt section. Leave the value alone. */ 374133965Sjdp sym->st_shndx = SHN_UNDEF; 374233965Sjdp } 374333965Sjdp 374433965Sjdp /* Fill in the entries in the .got. */ 374533965Sjdp bfd_put_64 (output_bfd, plt_addr, sgot->contents + gotent->got_offset); 374633965Sjdp 374733965Sjdp /* Subsequent .got entries will continue to bounce through the .plt. */ 374848850Sdfr if (gotent->next) 374933965Sjdp { 375048850Sdfr srel = bfd_get_section_by_name (dynobj, ".rela.got"); 375148850Sdfr BFD_ASSERT (! info->shared || srel != NULL); 375233965Sjdp 375348850Sdfr gotent = gotent->next; 375448850Sdfr do 375548850Sdfr { 375648850Sdfr sgot = alpha_elf_tdata(gotent->gotobj)->got; 375748850Sdfr BFD_ASSERT(sgot != NULL); 375848850Sdfr BFD_ASSERT(gotent->addend == 0); 375948850Sdfr 376048850Sdfr bfd_put_64 (output_bfd, plt_addr, 376148850Sdfr sgot->contents + gotent->got_offset); 376248850Sdfr 376348850Sdfr if (info->shared) 376448850Sdfr { 376548850Sdfr outrel.r_offset = (sgot->output_section->vma 376648850Sdfr + sgot->output_offset 376748850Sdfr + gotent->got_offset); 376848850Sdfr outrel.r_info = ELF64_R_INFO(0, R_ALPHA_RELATIVE); 376989862Sobrien outrel.r_addend = plt_addr; 377048850Sdfr 377148850Sdfr bfd_elf64_swap_reloca_out (output_bfd, &outrel, 377248850Sdfr ((Elf64_External_Rela *) 377348850Sdfr srel->contents) 377448850Sdfr + srel->reloc_count++); 377577303Sobrien BFD_ASSERT (sizeof (Elf64_External_Rela) * srel->reloc_count 377648850Sdfr <= srel->_cooked_size); 377748850Sdfr } 377848850Sdfr 377948850Sdfr gotent = gotent->next; 378048850Sdfr } 378148850Sdfr while (gotent != NULL); 378233965Sjdp } 378333965Sjdp } 378433965Sjdp else if (alpha_elf_dynamic_symbol_p (h, info)) 378533965Sjdp { 378633965Sjdp /* Fill in the dynamic relocations for this symbol's .got entries. */ 378733965Sjdp asection *srel; 378833965Sjdp Elf_Internal_Rela outrel; 378933965Sjdp struct alpha_elf_got_entry *gotent; 379033965Sjdp 379133965Sjdp srel = bfd_get_section_by_name (dynobj, ".rela.got"); 379233965Sjdp BFD_ASSERT (srel != NULL); 379333965Sjdp 379433965Sjdp outrel.r_info = ELF64_R_INFO (h->dynindx, R_ALPHA_GLOB_DAT); 379533965Sjdp for (gotent = ((struct alpha_elf_link_hash_entry *) h)->got_entries; 379633965Sjdp gotent != NULL; 379733965Sjdp gotent = gotent->next) 379833965Sjdp { 379933965Sjdp asection *sgot = alpha_elf_tdata (gotent->gotobj)->got; 380033965Sjdp outrel.r_offset = (sgot->output_section->vma 380133965Sjdp + sgot->output_offset 380233965Sjdp + gotent->got_offset); 380333965Sjdp outrel.r_addend = gotent->addend; 380433965Sjdp 380533965Sjdp bfd_elf64_swap_reloca_out (output_bfd, &outrel, 380633965Sjdp ((Elf64_External_Rela *)srel->contents 380733965Sjdp + srel->reloc_count++)); 380877303Sobrien BFD_ASSERT (sizeof (Elf64_External_Rela) * srel->reloc_count 380948850Sdfr <= srel->_cooked_size); 381033965Sjdp } 381133965Sjdp } 381233965Sjdp 381333965Sjdp /* Mark some specially defined symbols as absolute. */ 381433965Sjdp if (strcmp (h->root.root.string, "_DYNAMIC") == 0 381533965Sjdp || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0 381633965Sjdp || strcmp (h->root.root.string, "_PROCEDURE_LINKAGE_TABLE_") == 0) 381733965Sjdp sym->st_shndx = SHN_ABS; 381833965Sjdp 381933965Sjdp return true; 382033965Sjdp} 382133965Sjdp 382233965Sjdp/* Finish up the dynamic sections. */ 382333965Sjdp 382433965Sjdpstatic boolean 382533965Sjdpelf64_alpha_finish_dynamic_sections (output_bfd, info) 382633965Sjdp bfd *output_bfd; 382733965Sjdp struct bfd_link_info *info; 382833965Sjdp{ 382933965Sjdp bfd *dynobj; 383033965Sjdp asection *sdyn; 383133965Sjdp 383233965Sjdp dynobj = elf_hash_table (info)->dynobj; 383333965Sjdp sdyn = bfd_get_section_by_name (dynobj, ".dynamic"); 383433965Sjdp 383533965Sjdp if (elf_hash_table (info)->dynamic_sections_created) 383633965Sjdp { 383733965Sjdp asection *splt; 383833965Sjdp Elf64_External_Dyn *dyncon, *dynconend; 383933965Sjdp 384033965Sjdp splt = bfd_get_section_by_name (dynobj, ".plt"); 384133965Sjdp BFD_ASSERT (splt != NULL && sdyn != NULL); 384233965Sjdp 384333965Sjdp dyncon = (Elf64_External_Dyn *) sdyn->contents; 384433965Sjdp dynconend = (Elf64_External_Dyn *) (sdyn->contents + sdyn->_raw_size); 384533965Sjdp for (; dyncon < dynconend; dyncon++) 384633965Sjdp { 384733965Sjdp Elf_Internal_Dyn dyn; 384833965Sjdp const char *name; 384933965Sjdp asection *s; 385033965Sjdp 385133965Sjdp bfd_elf64_swap_dyn_in (dynobj, dyncon, &dyn); 385233965Sjdp 385333965Sjdp switch (dyn.d_tag) 385433965Sjdp { 385533965Sjdp case DT_PLTGOT: 385633965Sjdp name = ".plt"; 385733965Sjdp goto get_vma; 385833965Sjdp case DT_PLTRELSZ: 385933965Sjdp name = ".rela.plt"; 386033965Sjdp goto get_size; 386133965Sjdp case DT_JMPREL: 386233965Sjdp name = ".rela.plt"; 386333965Sjdp goto get_vma; 386433965Sjdp 386533965Sjdp case DT_RELASZ: 386633965Sjdp /* My interpretation of the TIS v1.1 ELF document indicates 386733965Sjdp that RELASZ should not include JMPREL. This is not what 386833965Sjdp the rest of the BFD does. It is, however, what the 386933965Sjdp glibc ld.so wants. Do this fixup here until we found 387033965Sjdp out who is right. */ 387133965Sjdp s = bfd_get_section_by_name (output_bfd, ".rela.plt"); 387233965Sjdp if (s) 387333965Sjdp { 387433965Sjdp dyn.d_un.d_val -= 387533965Sjdp (s->_cooked_size ? s->_cooked_size : s->_raw_size); 387633965Sjdp } 387733965Sjdp break; 387833965Sjdp 387933965Sjdp get_vma: 388033965Sjdp s = bfd_get_section_by_name (output_bfd, name); 388133965Sjdp dyn.d_un.d_ptr = (s ? s->vma : 0); 388233965Sjdp break; 388333965Sjdp 388433965Sjdp get_size: 388533965Sjdp s = bfd_get_section_by_name (output_bfd, name); 388633965Sjdp dyn.d_un.d_val = 388733965Sjdp (s->_cooked_size ? s->_cooked_size : s->_raw_size); 388833965Sjdp break; 388933965Sjdp } 389033965Sjdp 389133965Sjdp bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon); 389233965Sjdp } 389333965Sjdp 389433965Sjdp /* Initialize the PLT0 entry */ 389533965Sjdp if (splt->_raw_size > 0) 389633965Sjdp { 389733965Sjdp bfd_put_32 (output_bfd, PLT_HEADER_WORD1, splt->contents); 389833965Sjdp bfd_put_32 (output_bfd, PLT_HEADER_WORD2, splt->contents + 4); 389933965Sjdp bfd_put_32 (output_bfd, PLT_HEADER_WORD3, splt->contents + 8); 390033965Sjdp bfd_put_32 (output_bfd, PLT_HEADER_WORD4, splt->contents + 12); 390133965Sjdp 390233965Sjdp /* The next two words will be filled in by ld.so */ 390389862Sobrien bfd_put_64 (output_bfd, (bfd_vma) 0, splt->contents + 16); 390489862Sobrien bfd_put_64 (output_bfd, (bfd_vma) 0, splt->contents + 24); 390533965Sjdp 390633965Sjdp elf_section_data (splt->output_section)->this_hdr.sh_entsize = 390733965Sjdp PLT_HEADER_SIZE; 390833965Sjdp } 390933965Sjdp } 391033965Sjdp 391133965Sjdp return true; 391233965Sjdp} 391333965Sjdp 391489862Sobrien/* We need to use a special link routine to handle the .mdebug section. 391589862Sobrien We need to merge all instances of these sections together, not write 391689862Sobrien them all out sequentially. */ 391733965Sjdp 391833965Sjdpstatic boolean 391933965Sjdpelf64_alpha_final_link (abfd, info) 392033965Sjdp bfd *abfd; 392133965Sjdp struct bfd_link_info *info; 392233965Sjdp{ 392333965Sjdp asection *o; 392433965Sjdp struct bfd_link_order *p; 392589862Sobrien asection *mdebug_sec; 392633965Sjdp struct ecoff_debug_info debug; 392733965Sjdp const struct ecoff_debug_swap *swap 392833965Sjdp = get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap; 392933965Sjdp HDRR *symhdr = &debug.symbolic_header; 393033965Sjdp PTR mdebug_handle = NULL; 393133965Sjdp 393289862Sobrien /* Go through the sections and collect the mdebug information. */ 393333965Sjdp mdebug_sec = NULL; 393433965Sjdp for (o = abfd->sections; o != (asection *) NULL; o = o->next) 393533965Sjdp { 393633965Sjdp if (strcmp (o->name, ".mdebug") == 0) 393733965Sjdp { 393833965Sjdp struct extsym_info einfo; 393933965Sjdp 394033965Sjdp /* We have found the .mdebug section in the output file. 394133965Sjdp Look through all the link_orders comprising it and merge 394233965Sjdp the information together. */ 394333965Sjdp symhdr->magic = swap->sym_magic; 394433965Sjdp /* FIXME: What should the version stamp be? */ 394533965Sjdp symhdr->vstamp = 0; 394633965Sjdp symhdr->ilineMax = 0; 394733965Sjdp symhdr->cbLine = 0; 394833965Sjdp symhdr->idnMax = 0; 394933965Sjdp symhdr->ipdMax = 0; 395033965Sjdp symhdr->isymMax = 0; 395133965Sjdp symhdr->ioptMax = 0; 395233965Sjdp symhdr->iauxMax = 0; 395333965Sjdp symhdr->issMax = 0; 395433965Sjdp symhdr->issExtMax = 0; 395533965Sjdp symhdr->ifdMax = 0; 395633965Sjdp symhdr->crfd = 0; 395733965Sjdp symhdr->iextMax = 0; 395833965Sjdp 395933965Sjdp /* We accumulate the debugging information itself in the 396033965Sjdp debug_info structure. */ 396133965Sjdp debug.line = NULL; 396233965Sjdp debug.external_dnr = NULL; 396333965Sjdp debug.external_pdr = NULL; 396433965Sjdp debug.external_sym = NULL; 396533965Sjdp debug.external_opt = NULL; 396633965Sjdp debug.external_aux = NULL; 396733965Sjdp debug.ss = NULL; 396833965Sjdp debug.ssext = debug.ssext_end = NULL; 396933965Sjdp debug.external_fdr = NULL; 397033965Sjdp debug.external_rfd = NULL; 397133965Sjdp debug.external_ext = debug.external_ext_end = NULL; 397233965Sjdp 397333965Sjdp mdebug_handle = bfd_ecoff_debug_init (abfd, &debug, swap, info); 397433965Sjdp if (mdebug_handle == (PTR) NULL) 397533965Sjdp return false; 397633965Sjdp 397733965Sjdp if (1) 397833965Sjdp { 397933965Sjdp asection *s; 398033965Sjdp EXTR esym; 398189862Sobrien bfd_vma last = 0; 398233965Sjdp unsigned int i; 398333965Sjdp static const char * const name[] = 398433965Sjdp { 398533965Sjdp ".text", ".init", ".fini", ".data", 398633965Sjdp ".rodata", ".sdata", ".sbss", ".bss" 398733965Sjdp }; 398833965Sjdp static const int sc[] = { scText, scInit, scFini, scData, 398933965Sjdp scRData, scSData, scSBss, scBss }; 399033965Sjdp 399133965Sjdp esym.jmptbl = 0; 399233965Sjdp esym.cobol_main = 0; 399333965Sjdp esym.weakext = 0; 399433965Sjdp esym.reserved = 0; 399533965Sjdp esym.ifd = ifdNil; 399633965Sjdp esym.asym.iss = issNil; 399733965Sjdp esym.asym.st = stLocal; 399833965Sjdp esym.asym.reserved = 0; 399933965Sjdp esym.asym.index = indexNil; 400033965Sjdp for (i = 0; i < 8; i++) 400133965Sjdp { 400233965Sjdp esym.asym.sc = sc[i]; 400333965Sjdp s = bfd_get_section_by_name (abfd, name[i]); 400433965Sjdp if (s != NULL) 400533965Sjdp { 400633965Sjdp esym.asym.value = s->vma; 400733965Sjdp last = s->vma + s->_raw_size; 400833965Sjdp } 400933965Sjdp else 401033965Sjdp esym.asym.value = last; 401133965Sjdp 401233965Sjdp if (! bfd_ecoff_debug_one_external (abfd, &debug, swap, 401333965Sjdp name[i], &esym)) 401433965Sjdp return false; 401533965Sjdp } 401633965Sjdp } 401733965Sjdp 401833965Sjdp for (p = o->link_order_head; 401933965Sjdp p != (struct bfd_link_order *) NULL; 402033965Sjdp p = p->next) 402133965Sjdp { 402233965Sjdp asection *input_section; 402333965Sjdp bfd *input_bfd; 402433965Sjdp const struct ecoff_debug_swap *input_swap; 402533965Sjdp struct ecoff_debug_info input_debug; 402633965Sjdp char *eraw_src; 402733965Sjdp char *eraw_end; 402833965Sjdp 402933965Sjdp if (p->type != bfd_indirect_link_order) 403033965Sjdp { 403133965Sjdp if (p->type == bfd_fill_link_order) 403233965Sjdp continue; 403333965Sjdp abort (); 403433965Sjdp } 403533965Sjdp 403633965Sjdp input_section = p->u.indirect.section; 403733965Sjdp input_bfd = input_section->owner; 403833965Sjdp 403933965Sjdp if (bfd_get_flavour (input_bfd) != bfd_target_elf_flavour 404033965Sjdp || (get_elf_backend_data (input_bfd) 404133965Sjdp ->elf_backend_ecoff_debug_swap) == NULL) 404233965Sjdp { 404333965Sjdp /* I don't know what a non ALPHA ELF bfd would be 404433965Sjdp doing with a .mdebug section, but I don't really 404533965Sjdp want to deal with it. */ 404633965Sjdp continue; 404733965Sjdp } 404833965Sjdp 404933965Sjdp input_swap = (get_elf_backend_data (input_bfd) 405033965Sjdp ->elf_backend_ecoff_debug_swap); 405133965Sjdp 405233965Sjdp BFD_ASSERT (p->size == input_section->_raw_size); 405333965Sjdp 405433965Sjdp /* The ECOFF linking code expects that we have already 405533965Sjdp read in the debugging information and set up an 405633965Sjdp ecoff_debug_info structure, so we do that now. */ 405733965Sjdp if (!elf64_alpha_read_ecoff_info (input_bfd, input_section, 405833965Sjdp &input_debug)) 405933965Sjdp return false; 406033965Sjdp 406133965Sjdp if (! (bfd_ecoff_debug_accumulate 406233965Sjdp (mdebug_handle, abfd, &debug, swap, input_bfd, 406333965Sjdp &input_debug, input_swap, info))) 406433965Sjdp return false; 406533965Sjdp 406633965Sjdp /* Loop through the external symbols. For each one with 406733965Sjdp interesting information, try to find the symbol in 406833965Sjdp the linker global hash table and save the information 406933965Sjdp for the output external symbols. */ 407033965Sjdp eraw_src = input_debug.external_ext; 407133965Sjdp eraw_end = (eraw_src 407233965Sjdp + (input_debug.symbolic_header.iextMax 407333965Sjdp * input_swap->external_ext_size)); 407433965Sjdp for (; 407533965Sjdp eraw_src < eraw_end; 407633965Sjdp eraw_src += input_swap->external_ext_size) 407733965Sjdp { 407833965Sjdp EXTR ext; 407933965Sjdp const char *name; 408033965Sjdp struct alpha_elf_link_hash_entry *h; 408133965Sjdp 408233965Sjdp (*input_swap->swap_ext_in) (input_bfd, (PTR) eraw_src, &ext); 408333965Sjdp if (ext.asym.sc == scNil 408433965Sjdp || ext.asym.sc == scUndefined 408533965Sjdp || ext.asym.sc == scSUndefined) 408633965Sjdp continue; 408733965Sjdp 408833965Sjdp name = input_debug.ssext + ext.asym.iss; 408933965Sjdp h = alpha_elf_link_hash_lookup (alpha_elf_hash_table (info), 409033965Sjdp name, false, false, true); 409133965Sjdp if (h == NULL || h->esym.ifd != -2) 409233965Sjdp continue; 409333965Sjdp 409433965Sjdp if (ext.ifd != -1) 409533965Sjdp { 409633965Sjdp BFD_ASSERT (ext.ifd 409733965Sjdp < input_debug.symbolic_header.ifdMax); 409833965Sjdp ext.ifd = input_debug.ifdmap[ext.ifd]; 409933965Sjdp } 410033965Sjdp 410133965Sjdp h->esym = ext; 410233965Sjdp } 410333965Sjdp 410433965Sjdp /* Free up the information we just read. */ 410533965Sjdp free (input_debug.line); 410633965Sjdp free (input_debug.external_dnr); 410733965Sjdp free (input_debug.external_pdr); 410833965Sjdp free (input_debug.external_sym); 410933965Sjdp free (input_debug.external_opt); 411033965Sjdp free (input_debug.external_aux); 411133965Sjdp free (input_debug.ss); 411233965Sjdp free (input_debug.ssext); 411333965Sjdp free (input_debug.external_fdr); 411433965Sjdp free (input_debug.external_rfd); 411533965Sjdp free (input_debug.external_ext); 411633965Sjdp 411733965Sjdp /* Hack: reset the SEC_HAS_CONTENTS flag so that 411833965Sjdp elf_link_input_bfd ignores this section. */ 411933965Sjdp input_section->flags &=~ SEC_HAS_CONTENTS; 412033965Sjdp } 412133965Sjdp 412233965Sjdp /* Build the external symbol information. */ 412333965Sjdp einfo.abfd = abfd; 412433965Sjdp einfo.info = info; 412533965Sjdp einfo.debug = &debug; 412633965Sjdp einfo.swap = swap; 412733965Sjdp einfo.failed = false; 412833965Sjdp elf_link_hash_traverse (elf_hash_table (info), 412933965Sjdp elf64_alpha_output_extsym, 413033965Sjdp (PTR) &einfo); 413133965Sjdp if (einfo.failed) 413233965Sjdp return false; 413333965Sjdp 413433965Sjdp /* Set the size of the .mdebug section. */ 413533965Sjdp o->_raw_size = bfd_ecoff_debug_size (abfd, &debug, swap); 413633965Sjdp 413733965Sjdp /* Skip this section later on (I don't think this currently 413833965Sjdp matters, but someday it might). */ 413933965Sjdp o->link_order_head = (struct bfd_link_order *) NULL; 414033965Sjdp 414133965Sjdp mdebug_sec = o; 414233965Sjdp } 414333965Sjdp } 414433965Sjdp 414533965Sjdp /* Invoke the regular ELF backend linker to do all the work. */ 414633965Sjdp if (! bfd_elf64_bfd_final_link (abfd, info)) 414733965Sjdp return false; 414833965Sjdp 414933965Sjdp /* Now write out the computed sections. */ 415033965Sjdp 415133965Sjdp /* The .got subsections... */ 415233965Sjdp { 415333965Sjdp bfd *i, *dynobj = elf_hash_table(info)->dynobj; 415433965Sjdp for (i = alpha_elf_hash_table(info)->got_list; 415533965Sjdp i != NULL; 415633965Sjdp i = alpha_elf_tdata(i)->got_link_next) 415733965Sjdp { 415833965Sjdp asection *sgot; 415933965Sjdp 416033965Sjdp /* elf_bfd_final_link already did everything in dynobj. */ 416133965Sjdp if (i == dynobj) 416233965Sjdp continue; 416333965Sjdp 416433965Sjdp sgot = alpha_elf_tdata(i)->got; 416533965Sjdp if (! bfd_set_section_contents (abfd, sgot->output_section, 416689862Sobrien sgot->contents, 416789862Sobrien (file_ptr) sgot->output_offset, 416833965Sjdp sgot->_raw_size)) 416933965Sjdp return false; 417033965Sjdp } 417133965Sjdp } 417233965Sjdp 417333965Sjdp if (mdebug_sec != (asection *) NULL) 417433965Sjdp { 417533965Sjdp BFD_ASSERT (abfd->output_has_begun); 417633965Sjdp if (! bfd_ecoff_write_accumulated_debug (mdebug_handle, abfd, &debug, 417733965Sjdp swap, info, 417833965Sjdp mdebug_sec->filepos)) 417933965Sjdp return false; 418033965Sjdp 418133965Sjdp bfd_ecoff_debug_free (mdebug_handle, abfd, &debug, swap, info); 418233965Sjdp } 418333965Sjdp 418489862Sobrien return true; 418589862Sobrien} 418633965Sjdp 418789862Sobrienstatic enum elf_reloc_type_class 418889862Sobrienelf64_alpha_reloc_type_class (rela) 418989862Sobrien const Elf_Internal_Rela *rela; 419089862Sobrien{ 419189862Sobrien switch ((int) ELF64_R_TYPE (rela->r_info)) 419233965Sjdp { 419389862Sobrien case R_ALPHA_RELATIVE: 419489862Sobrien return reloc_class_relative; 419589862Sobrien case R_ALPHA_JMP_SLOT: 419689862Sobrien return reloc_class_plt; 419789862Sobrien case R_ALPHA_COPY: 419889862Sobrien return reloc_class_copy; 419989862Sobrien default: 420089862Sobrien return reloc_class_normal; 420133965Sjdp } 420233965Sjdp} 420333965Sjdp 420433965Sjdp/* ECOFF swapping routines. These are used when dealing with the 420533965Sjdp .mdebug section, which is in the ECOFF debugging format. Copied 420677303Sobrien from elf32-mips.c. */ 420733965Sjdpstatic const struct ecoff_debug_swap 420833965Sjdpelf64_alpha_ecoff_debug_swap = 420933965Sjdp{ 421033965Sjdp /* Symbol table magic number. */ 421133965Sjdp magicSym2, 421233965Sjdp /* Alignment of debugging information. E.g., 4. */ 421333965Sjdp 8, 421433965Sjdp /* Sizes of external symbolic information. */ 421533965Sjdp sizeof (struct hdr_ext), 421633965Sjdp sizeof (struct dnr_ext), 421733965Sjdp sizeof (struct pdr_ext), 421833965Sjdp sizeof (struct sym_ext), 421933965Sjdp sizeof (struct opt_ext), 422033965Sjdp sizeof (struct fdr_ext), 422133965Sjdp sizeof (struct rfd_ext), 422233965Sjdp sizeof (struct ext_ext), 422333965Sjdp /* Functions to swap in external symbolic data. */ 422433965Sjdp ecoff_swap_hdr_in, 422533965Sjdp ecoff_swap_dnr_in, 422633965Sjdp ecoff_swap_pdr_in, 422733965Sjdp ecoff_swap_sym_in, 422833965Sjdp ecoff_swap_opt_in, 422933965Sjdp ecoff_swap_fdr_in, 423033965Sjdp ecoff_swap_rfd_in, 423133965Sjdp ecoff_swap_ext_in, 423233965Sjdp _bfd_ecoff_swap_tir_in, 423333965Sjdp _bfd_ecoff_swap_rndx_in, 423433965Sjdp /* Functions to swap out external symbolic data. */ 423533965Sjdp ecoff_swap_hdr_out, 423633965Sjdp ecoff_swap_dnr_out, 423733965Sjdp ecoff_swap_pdr_out, 423833965Sjdp ecoff_swap_sym_out, 423933965Sjdp ecoff_swap_opt_out, 424033965Sjdp ecoff_swap_fdr_out, 424133965Sjdp ecoff_swap_rfd_out, 424233965Sjdp ecoff_swap_ext_out, 424333965Sjdp _bfd_ecoff_swap_tir_out, 424433965Sjdp _bfd_ecoff_swap_rndx_out, 424533965Sjdp /* Function to read in symbolic data. */ 424633965Sjdp elf64_alpha_read_ecoff_info 424733965Sjdp}; 424833965Sjdp 424977303Sobrien/* Use a non-standard hash bucket size of 8. */ 425077303Sobrien 425177303Sobrienconst struct elf_size_info alpha_elf_size_info = 425277303Sobrien{ 425377303Sobrien sizeof (Elf64_External_Ehdr), 425477303Sobrien sizeof (Elf64_External_Phdr), 425577303Sobrien sizeof (Elf64_External_Shdr), 425677303Sobrien sizeof (Elf64_External_Rel), 425777303Sobrien sizeof (Elf64_External_Rela), 425877303Sobrien sizeof (Elf64_External_Sym), 425977303Sobrien sizeof (Elf64_External_Dyn), 426077303Sobrien sizeof (Elf_External_Note), 426177303Sobrien 8, 426277303Sobrien 1, 426377303Sobrien 64, 8, 426477303Sobrien ELFCLASS64, EV_CURRENT, 426577303Sobrien bfd_elf64_write_out_phdrs, 426677303Sobrien bfd_elf64_write_shdrs_and_ehdr, 426777303Sobrien bfd_elf64_write_relocs, 426877303Sobrien bfd_elf64_swap_symbol_out, 426977303Sobrien bfd_elf64_slurp_reloc_table, 427077303Sobrien bfd_elf64_slurp_symbol_table, 427177303Sobrien bfd_elf64_swap_dyn_in, 427277303Sobrien bfd_elf64_swap_dyn_out, 427377303Sobrien NULL, 427477303Sobrien NULL, 427577303Sobrien NULL, 427677303Sobrien NULL 427777303Sobrien}; 427877303Sobrien 427933965Sjdp#define TARGET_LITTLE_SYM bfd_elf64_alpha_vec 428033965Sjdp#define TARGET_LITTLE_NAME "elf64-alpha" 428133965Sjdp#define ELF_ARCH bfd_arch_alpha 428278833Sobrien#define ELF_MACHINE_CODE EM_ALPHA 428378833Sobrien#define ELF_MAXPAGESIZE 0x10000 428433965Sjdp 428533965Sjdp#define bfd_elf64_bfd_link_hash_table_create \ 428633965Sjdp elf64_alpha_bfd_link_hash_table_create 428733965Sjdp 428833965Sjdp#define bfd_elf64_bfd_reloc_type_lookup \ 428933965Sjdp elf64_alpha_bfd_reloc_type_lookup 429033965Sjdp#define elf_info_to_howto \ 429133965Sjdp elf64_alpha_info_to_howto 429233965Sjdp 429333965Sjdp#define bfd_elf64_mkobject \ 429433965Sjdp elf64_alpha_mkobject 429533965Sjdp#define elf_backend_object_p \ 429633965Sjdp elf64_alpha_object_p 429733965Sjdp 429833965Sjdp#define elf_backend_section_from_shdr \ 429933965Sjdp elf64_alpha_section_from_shdr 430089862Sobrien#define elf_backend_section_flags \ 430189862Sobrien elf64_alpha_section_flags 430233965Sjdp#define elf_backend_fake_sections \ 430333965Sjdp elf64_alpha_fake_sections 430433965Sjdp 430533965Sjdp#define bfd_elf64_bfd_is_local_label_name \ 430633965Sjdp elf64_alpha_is_local_label_name 430733965Sjdp#define bfd_elf64_find_nearest_line \ 430833965Sjdp elf64_alpha_find_nearest_line 430960510Sobrien#define bfd_elf64_bfd_relax_section \ 431060510Sobrien elf64_alpha_relax_section 431133965Sjdp 431260510Sobrien#define elf_backend_add_symbol_hook \ 431360510Sobrien elf64_alpha_add_symbol_hook 431433965Sjdp#define elf_backend_check_relocs \ 431533965Sjdp elf64_alpha_check_relocs 431633965Sjdp#define elf_backend_create_dynamic_sections \ 431733965Sjdp elf64_alpha_create_dynamic_sections 431833965Sjdp#define elf_backend_adjust_dynamic_symbol \ 431933965Sjdp elf64_alpha_adjust_dynamic_symbol 432033965Sjdp#define elf_backend_always_size_sections \ 432133965Sjdp elf64_alpha_always_size_sections 432233965Sjdp#define elf_backend_size_dynamic_sections \ 432333965Sjdp elf64_alpha_size_dynamic_sections 432433965Sjdp#define elf_backend_relocate_section \ 432533965Sjdp elf64_alpha_relocate_section 432633965Sjdp#define elf_backend_finish_dynamic_symbol \ 432733965Sjdp elf64_alpha_finish_dynamic_symbol 432833965Sjdp#define elf_backend_finish_dynamic_sections \ 432933965Sjdp elf64_alpha_finish_dynamic_sections 433033965Sjdp#define bfd_elf64_bfd_final_link \ 433133965Sjdp elf64_alpha_final_link 433289862Sobrien#define elf_backend_reloc_type_class \ 433389862Sobrien elf64_alpha_reloc_type_class 433433965Sjdp 433533965Sjdp#define elf_backend_ecoff_debug_swap \ 433633965Sjdp &elf64_alpha_ecoff_debug_swap 433733965Sjdp 433877303Sobrien#define elf_backend_size_info \ 433977303Sobrien alpha_elf_size_info 434077303Sobrien 434177303Sobrien/* A few constants that determine how the .plt section is set up. */ 434233965Sjdp#define elf_backend_want_got_plt 0 434333965Sjdp#define elf_backend_plt_readonly 0 434433965Sjdp#define elf_backend_want_plt_sym 1 434560510Sobrien#define elf_backend_got_header_size 0 434660510Sobrien#define elf_backend_plt_header_size PLT_HEADER_SIZE 434733965Sjdp 434833965Sjdp#include "elf64-target.h" 4349