elf64-alpha.c revision 115361
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 22115361Sobrien/* $FreeBSD: head/contrib/binutils/bfd/elf64-alpha.c 115361 2003-05-28 03:32:33Z obrien $ */ 23115361Sobrien 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 78104841Sobrien PARAMS((bfd *, Elf64_Internal_Shdr *, const 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 111104841Sobrien PARAMS ((struct bfd_link_info *)); 112104841Sobrienstatic boolean elf64_alpha_size_plt_section 113104841Sobrien PARAMS ((struct bfd_link_info *)); 114104841Sobrienstatic boolean elf64_alpha_size_plt_section_1 115104841Sobrien PARAMS ((struct alpha_elf_link_hash_entry *, PTR)); 11633965Sjdpstatic boolean elf64_alpha_always_size_sections 11733965Sjdp PARAMS ((bfd *, struct bfd_link_info *)); 118104841Sobrienstatic int alpha_dynamic_entries_for_reloc 119104841Sobrien PARAMS ((int, int, int)); 12033965Sjdpstatic boolean elf64_alpha_calc_dynrel_sizes 12133965Sjdp PARAMS ((struct alpha_elf_link_hash_entry *, struct bfd_link_info *)); 122104841Sobrienstatic boolean elf64_alpha_size_rela_got_section 123104841Sobrien PARAMS ((struct bfd_link_info *)); 124104841Sobrienstatic boolean elf64_alpha_size_rela_got_1 125104841Sobrien PARAMS ((struct alpha_elf_link_hash_entry *, struct bfd_link_info *)); 12660510Sobrienstatic boolean elf64_alpha_add_symbol_hook 12760510Sobrien PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Sym *, 12860510Sobrien const char **, flagword *, asection **, bfd_vma *)); 129104841Sobrienstatic struct alpha_elf_got_entry *get_got_entry 130104841Sobrien PARAMS ((bfd *, struct alpha_elf_link_hash_entry *, unsigned long, 131104841Sobrien unsigned long, bfd_vma)); 13233965Sjdpstatic boolean elf64_alpha_check_relocs 13333965Sjdp PARAMS((bfd *, struct bfd_link_info *, asection *sec, 13433965Sjdp const Elf_Internal_Rela *)); 13533965Sjdpstatic boolean elf64_alpha_adjust_dynamic_symbol 13633965Sjdp PARAMS((struct bfd_link_info *, struct elf_link_hash_entry *)); 13733965Sjdpstatic boolean elf64_alpha_size_dynamic_sections 13833965Sjdp PARAMS((bfd *, struct bfd_link_info *)); 139104841Sobrienstatic boolean elf64_alpha_relocate_section_r 140104841Sobrien PARAMS((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, 141104841Sobrien Elf_Internal_Rela *, Elf_Internal_Sym *, asection **)); 14233965Sjdpstatic boolean elf64_alpha_relocate_section 14333965Sjdp PARAMS((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, 14433965Sjdp Elf_Internal_Rela *, Elf_Internal_Sym *, asection **)); 14533965Sjdpstatic boolean elf64_alpha_finish_dynamic_symbol 14633965Sjdp PARAMS((bfd *, struct bfd_link_info *, struct elf_link_hash_entry *, 14733965Sjdp Elf_Internal_Sym *)); 14833965Sjdpstatic boolean elf64_alpha_finish_dynamic_sections 14933965Sjdp PARAMS((bfd *, struct bfd_link_info *)); 15033965Sjdpstatic boolean elf64_alpha_final_link 15133965Sjdp PARAMS((bfd *, struct bfd_link_info *)); 15248850Sdfrstatic boolean elf64_alpha_merge_ind_symbols 15348850Sdfr PARAMS((struct alpha_elf_link_hash_entry *, PTR)); 15460510Sobrienstatic Elf_Internal_Rela * elf64_alpha_find_reloc_at_ofs 15560510Sobrien PARAMS ((Elf_Internal_Rela *, Elf_Internal_Rela *, bfd_vma, int)); 15689862Sobrienstatic enum elf_reloc_type_class elf64_alpha_reloc_type_class 15789862Sobrien PARAMS ((const Elf_Internal_Rela *)); 15833965Sjdp 15933965Sjdpstruct alpha_elf_link_hash_entry 16033965Sjdp{ 16133965Sjdp struct elf_link_hash_entry root; 16233965Sjdp 16333965Sjdp /* External symbol information. */ 16433965Sjdp EXTR esym; 16533965Sjdp 16633965Sjdp /* Cumulative flags for all the .got entries. */ 16733965Sjdp int flags; 16833965Sjdp 169104841Sobrien /* Contexts in which a literal was referenced. */ 170104841Sobrien#define ALPHA_ELF_LINK_HASH_LU_ADDR 0x01 171104841Sobrien#define ALPHA_ELF_LINK_HASH_LU_MEM 0x02 172104841Sobrien#define ALPHA_ELF_LINK_HASH_LU_BYTE 0x04 173104841Sobrien#define ALPHA_ELF_LINK_HASH_LU_JSR 0x08 174104841Sobrien#define ALPHA_ELF_LINK_HASH_LU_TLSGD 0x10 175104841Sobrien#define ALPHA_ELF_LINK_HASH_LU_TLSLDM 0x20 176104841Sobrien#define ALPHA_ELF_LINK_HASH_LU_FUNC 0x38 177104841Sobrien#define ALPHA_ELF_LINK_HASH_TLS_IE 0x40 17833965Sjdp 17933965Sjdp /* Used to implement multiple .got subsections. */ 18033965Sjdp struct alpha_elf_got_entry 18133965Sjdp { 18233965Sjdp struct alpha_elf_got_entry *next; 18333965Sjdp 18433965Sjdp /* which .got subsection? */ 18533965Sjdp bfd *gotobj; 18633965Sjdp 18733965Sjdp /* the addend in effect for this entry. */ 18833965Sjdp bfd_vma addend; 18933965Sjdp 19033965Sjdp /* the .got offset for this entry. */ 19133965Sjdp int got_offset; 19233965Sjdp 193104841Sobrien /* How many references to this entry? */ 194104841Sobrien int use_count; 19533965Sjdp 196104841Sobrien /* The relocation type of this entry. */ 197104841Sobrien unsigned char reloc_type; 19860510Sobrien 199104841Sobrien /* How a LITERAL is used. */ 200104841Sobrien unsigned char flags; 201104841Sobrien 202104841Sobrien /* Have we initialized the dynamic relocation for this entry? */ 203104841Sobrien unsigned char reloc_done; 204104841Sobrien 205104841Sobrien /* Have we adjusted this entry for SEC_MERGE? */ 206104841Sobrien unsigned char reloc_xlated; 20733965Sjdp } *got_entries; 20833965Sjdp 20933965Sjdp /* used to count non-got, non-plt relocations for delayed sizing 21033965Sjdp of relocation sections. */ 21133965Sjdp struct alpha_elf_reloc_entry 21233965Sjdp { 21333965Sjdp struct alpha_elf_reloc_entry *next; 21433965Sjdp 21533965Sjdp /* which .reloc section? */ 21633965Sjdp asection *srel; 21733965Sjdp 21833965Sjdp /* what kind of relocation? */ 21989862Sobrien unsigned int rtype; 22033965Sjdp 22189862Sobrien /* is this against read-only section? */ 22289862Sobrien unsigned int reltext : 1; 22389862Sobrien 22433965Sjdp /* how many did we find? */ 22533965Sjdp unsigned long count; 22633965Sjdp } *reloc_entries; 22733965Sjdp}; 22833965Sjdp 22933965Sjdp/* Alpha ELF linker hash table. */ 23033965Sjdp 23133965Sjdpstruct alpha_elf_link_hash_table 23233965Sjdp{ 23333965Sjdp struct elf_link_hash_table root; 23433965Sjdp 23533965Sjdp /* The head of a list of .got subsections linked through 23633965Sjdp alpha_elf_tdata(abfd)->got_link_next. */ 23733965Sjdp bfd *got_list; 23833965Sjdp}; 23933965Sjdp 24033965Sjdp/* Look up an entry in a Alpha ELF linker hash table. */ 24133965Sjdp 24233965Sjdp#define alpha_elf_link_hash_lookup(table, string, create, copy, follow) \ 24333965Sjdp ((struct alpha_elf_link_hash_entry *) \ 24433965Sjdp elf_link_hash_lookup (&(table)->root, (string), (create), \ 24533965Sjdp (copy), (follow))) 24633965Sjdp 24733965Sjdp/* Traverse a Alpha ELF linker hash table. */ 24833965Sjdp 24933965Sjdp#define alpha_elf_link_hash_traverse(table, func, info) \ 25033965Sjdp (elf_link_hash_traverse \ 25133965Sjdp (&(table)->root, \ 25233965Sjdp (boolean (*) PARAMS ((struct elf_link_hash_entry *, PTR))) (func), \ 25333965Sjdp (info))) 25433965Sjdp 25533965Sjdp/* Get the Alpha ELF linker hash table from a link_info structure. */ 25633965Sjdp 25733965Sjdp#define alpha_elf_hash_table(p) \ 25833965Sjdp ((struct alpha_elf_link_hash_table *) ((p)->hash)) 25933965Sjdp 26033965Sjdp/* Get the object's symbols as our own entry type. */ 26133965Sjdp 26233965Sjdp#define alpha_elf_sym_hashes(abfd) \ 26333965Sjdp ((struct alpha_elf_link_hash_entry **)elf_sym_hashes(abfd)) 26433965Sjdp 26533965Sjdp/* Should we do dynamic things to this symbol? */ 26633965Sjdp 26777303Sobrienstatic int 26877303Sobrienalpha_elf_dynamic_symbol_p (h, info) 26977303Sobrien struct elf_link_hash_entry *h; 27077303Sobrien struct bfd_link_info *info; 27177303Sobrien{ 27277303Sobrien if (h == NULL) 27377303Sobrien return false; 27433965Sjdp 27577303Sobrien while (h->root.type == bfd_link_hash_indirect 27677303Sobrien || h->root.type == bfd_link_hash_warning) 27777303Sobrien h = (struct elf_link_hash_entry *) h->root.u.i.link; 27877303Sobrien 27977303Sobrien if (h->dynindx == -1) 28077303Sobrien return false; 28177303Sobrien 28277303Sobrien if (h->root.type == bfd_link_hash_undefweak 28377303Sobrien || h->root.type == bfd_link_hash_defweak) 28477303Sobrien return true; 28577303Sobrien 28678833Sobrien switch (ELF_ST_VISIBILITY (h->other)) 28778833Sobrien { 28878833Sobrien case STV_DEFAULT: 28978833Sobrien break; 29078833Sobrien case STV_HIDDEN: 29178833Sobrien case STV_INTERNAL: 29278833Sobrien return false; 29378833Sobrien case STV_PROTECTED: 29478833Sobrien if (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) 29578833Sobrien return false; 29678833Sobrien break; 29778833Sobrien } 29878833Sobrien 29977303Sobrien if ((info->shared && !info->symbolic) 30077303Sobrien || ((h->elf_link_hash_flags 30177303Sobrien & (ELF_LINK_HASH_DEF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR)) 30277303Sobrien == (ELF_LINK_HASH_DEF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR))) 30377303Sobrien return true; 30477303Sobrien 30577303Sobrien return false; 30677303Sobrien} 30777303Sobrien 30833965Sjdp/* Create an entry in a Alpha ELF linker hash table. */ 30933965Sjdp 31033965Sjdpstatic struct bfd_hash_entry * 31133965Sjdpelf64_alpha_link_hash_newfunc (entry, table, string) 31233965Sjdp struct bfd_hash_entry *entry; 31333965Sjdp struct bfd_hash_table *table; 31433965Sjdp const char *string; 31533965Sjdp{ 31633965Sjdp struct alpha_elf_link_hash_entry *ret = 31733965Sjdp (struct alpha_elf_link_hash_entry *) entry; 31833965Sjdp 31933965Sjdp /* Allocate the structure if it has not already been allocated by a 32033965Sjdp subclass. */ 32133965Sjdp if (ret == (struct alpha_elf_link_hash_entry *) NULL) 32233965Sjdp ret = ((struct alpha_elf_link_hash_entry *) 32333965Sjdp bfd_hash_allocate (table, 32433965Sjdp sizeof (struct alpha_elf_link_hash_entry))); 32533965Sjdp if (ret == (struct alpha_elf_link_hash_entry *) NULL) 32633965Sjdp return (struct bfd_hash_entry *) ret; 32733965Sjdp 32833965Sjdp /* Call the allocation method of the superclass. */ 32933965Sjdp ret = ((struct alpha_elf_link_hash_entry *) 33033965Sjdp _bfd_elf_link_hash_newfunc ((struct bfd_hash_entry *) ret, 33133965Sjdp table, string)); 33233965Sjdp if (ret != (struct alpha_elf_link_hash_entry *) NULL) 33333965Sjdp { 33433965Sjdp /* Set local fields. */ 33533965Sjdp memset (&ret->esym, 0, sizeof (EXTR)); 33633965Sjdp /* We use -2 as a marker to indicate that the information has 33733965Sjdp not been set. -1 means there is no associated ifd. */ 33833965Sjdp ret->esym.ifd = -2; 33933965Sjdp ret->flags = 0; 34033965Sjdp ret->got_entries = NULL; 34133965Sjdp ret->reloc_entries = NULL; 34233965Sjdp } 34333965Sjdp 34433965Sjdp return (struct bfd_hash_entry *) ret; 34533965Sjdp} 34633965Sjdp 34733965Sjdp/* Create a Alpha ELF linker hash table. */ 34833965Sjdp 34933965Sjdpstatic struct bfd_link_hash_table * 35033965Sjdpelf64_alpha_bfd_link_hash_table_create (abfd) 35133965Sjdp bfd *abfd; 35233965Sjdp{ 35333965Sjdp struct alpha_elf_link_hash_table *ret; 35489862Sobrien bfd_size_type amt = sizeof (struct alpha_elf_link_hash_table); 35533965Sjdp 356104841Sobrien ret = (struct alpha_elf_link_hash_table *) bfd_zmalloc (amt); 35733965Sjdp if (ret == (struct alpha_elf_link_hash_table *) NULL) 35833965Sjdp return NULL; 35933965Sjdp 36033965Sjdp if (! _bfd_elf_link_hash_table_init (&ret->root, abfd, 36133965Sjdp elf64_alpha_link_hash_newfunc)) 36233965Sjdp { 363104841Sobrien free (ret); 36433965Sjdp return NULL; 36533965Sjdp } 36633965Sjdp 36733965Sjdp return &ret->root.root; 36833965Sjdp} 36933965Sjdp 37033965Sjdp/* We have some private fields hanging off of the elf_tdata structure. */ 37133965Sjdp 37233965Sjdpstruct alpha_elf_obj_tdata 37333965Sjdp{ 37433965Sjdp struct elf_obj_tdata root; 37533965Sjdp 37633965Sjdp /* For every input file, these are the got entries for that object's 37733965Sjdp local symbols. */ 37833965Sjdp struct alpha_elf_got_entry ** local_got_entries; 37933965Sjdp 38033965Sjdp /* For every input file, this is the object that owns the got that 38133965Sjdp this input file uses. */ 38233965Sjdp bfd *gotobj; 38333965Sjdp 38433965Sjdp /* For every got, this is a linked list through the objects using this got */ 38533965Sjdp bfd *in_got_link_next; 38633965Sjdp 38733965Sjdp /* For every got, this is a link to the next got subsegment. */ 38833965Sjdp bfd *got_link_next; 38933965Sjdp 39033965Sjdp /* For every got, this is the section. */ 39133965Sjdp asection *got; 39233965Sjdp 393104841Sobrien /* For every got, this is it's total number of words. */ 394104841Sobrien int total_got_size; 39533965Sjdp 396104841Sobrien /* For every got, this is the sum of the number of words required 39733965Sjdp to hold all of the member object's local got. */ 398104841Sobrien int local_got_size; 39933965Sjdp}; 40033965Sjdp 40133965Sjdp#define alpha_elf_tdata(abfd) \ 40233965Sjdp ((struct alpha_elf_obj_tdata *) (abfd)->tdata.any) 40333965Sjdp 40433965Sjdpstatic boolean 40533965Sjdpelf64_alpha_mkobject (abfd) 40633965Sjdp bfd *abfd; 40733965Sjdp{ 40889862Sobrien bfd_size_type amt = sizeof (struct alpha_elf_obj_tdata); 40989862Sobrien abfd->tdata.any = bfd_zalloc (abfd, amt); 41033965Sjdp if (abfd->tdata.any == NULL) 41133965Sjdp return false; 41233965Sjdp return true; 41333965Sjdp} 41433965Sjdp 41533965Sjdpstatic boolean 41633965Sjdpelf64_alpha_object_p (abfd) 41733965Sjdp bfd *abfd; 41833965Sjdp{ 41933965Sjdp /* Allocate our special target data. */ 42033965Sjdp struct alpha_elf_obj_tdata *new_tdata; 42189862Sobrien bfd_size_type amt = sizeof (struct alpha_elf_obj_tdata); 42289862Sobrien new_tdata = bfd_zalloc (abfd, amt); 42333965Sjdp if (new_tdata == NULL) 42433965Sjdp return false; 42533965Sjdp new_tdata->root = *abfd->tdata.elf_obj_data; 42633965Sjdp abfd->tdata.any = new_tdata; 42733965Sjdp 42833965Sjdp /* Set the right machine number for an Alpha ELF file. */ 42933965Sjdp return bfd_default_set_arch_mach (abfd, bfd_arch_alpha, 0); 43033965Sjdp} 43133965Sjdp 43233965Sjdp/* In case we're on a 32-bit machine, construct a 64-bit "-1" value 43333965Sjdp from smaller values. Start with zero, widen, *then* decrement. */ 43433965Sjdp#define MINUS_ONE (((bfd_vma)0) - 1) 43533965Sjdp 43689862Sobrien#define SKIP_HOWTO(N) \ 43789862Sobrien HOWTO(N, 0, 0, 0, 0, 0, 0, elf64_alpha_reloc_bad, 0, 0, 0, 0, 0) 43889862Sobrien 43933965Sjdpstatic reloc_howto_type elf64_alpha_howto_table[] = 44033965Sjdp{ 44133965Sjdp HOWTO (R_ALPHA_NONE, /* type */ 44233965Sjdp 0, /* rightshift */ 44333965Sjdp 0, /* size (0 = byte, 1 = short, 2 = long) */ 44433965Sjdp 8, /* bitsize */ 44533965Sjdp true, /* pc_relative */ 44633965Sjdp 0, /* bitpos */ 44733965Sjdp complain_overflow_dont, /* complain_on_overflow */ 44833965Sjdp elf64_alpha_reloc_nil, /* special_function */ 44933965Sjdp "NONE", /* name */ 45033965Sjdp false, /* partial_inplace */ 45133965Sjdp 0, /* src_mask */ 45233965Sjdp 0, /* dst_mask */ 45333965Sjdp true), /* pcrel_offset */ 45433965Sjdp 45533965Sjdp /* A 32 bit reference to a symbol. */ 45633965Sjdp HOWTO (R_ALPHA_REFLONG, /* type */ 45733965Sjdp 0, /* rightshift */ 45833965Sjdp 2, /* size (0 = byte, 1 = short, 2 = long) */ 45933965Sjdp 32, /* bitsize */ 46033965Sjdp false, /* pc_relative */ 46133965Sjdp 0, /* bitpos */ 46233965Sjdp complain_overflow_bitfield, /* complain_on_overflow */ 46333965Sjdp 0, /* special_function */ 46433965Sjdp "REFLONG", /* name */ 46533965Sjdp false, /* partial_inplace */ 46633965Sjdp 0xffffffff, /* src_mask */ 46733965Sjdp 0xffffffff, /* dst_mask */ 46833965Sjdp false), /* pcrel_offset */ 46933965Sjdp 47033965Sjdp /* A 64 bit reference to a symbol. */ 47133965Sjdp HOWTO (R_ALPHA_REFQUAD, /* type */ 47233965Sjdp 0, /* rightshift */ 47333965Sjdp 4, /* size (0 = byte, 1 = short, 2 = long) */ 47433965Sjdp 64, /* bitsize */ 47533965Sjdp false, /* pc_relative */ 47633965Sjdp 0, /* bitpos */ 47733965Sjdp complain_overflow_bitfield, /* complain_on_overflow */ 47833965Sjdp 0, /* special_function */ 47933965Sjdp "REFQUAD", /* name */ 48033965Sjdp false, /* partial_inplace */ 48133965Sjdp MINUS_ONE, /* src_mask */ 48233965Sjdp MINUS_ONE, /* dst_mask */ 48333965Sjdp false), /* pcrel_offset */ 48433965Sjdp 48533965Sjdp /* A 32 bit GP relative offset. This is just like REFLONG except 48633965Sjdp that when the value is used the value of the gp register will be 48733965Sjdp added in. */ 48833965Sjdp HOWTO (R_ALPHA_GPREL32, /* type */ 48933965Sjdp 0, /* rightshift */ 49033965Sjdp 2, /* size (0 = byte, 1 = short, 2 = long) */ 49133965Sjdp 32, /* bitsize */ 49233965Sjdp false, /* pc_relative */ 49333965Sjdp 0, /* bitpos */ 49433965Sjdp complain_overflow_bitfield, /* complain_on_overflow */ 49533965Sjdp 0, /* special_function */ 49633965Sjdp "GPREL32", /* name */ 49733965Sjdp false, /* partial_inplace */ 49833965Sjdp 0xffffffff, /* src_mask */ 49933965Sjdp 0xffffffff, /* dst_mask */ 50033965Sjdp false), /* pcrel_offset */ 50133965Sjdp 50233965Sjdp /* Used for an instruction that refers to memory off the GP register. */ 50333965Sjdp HOWTO (R_ALPHA_LITERAL, /* type */ 50433965Sjdp 0, /* rightshift */ 50589862Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 50633965Sjdp 16, /* bitsize */ 50733965Sjdp false, /* pc_relative */ 50833965Sjdp 0, /* bitpos */ 50933965Sjdp complain_overflow_signed, /* complain_on_overflow */ 51033965Sjdp 0, /* special_function */ 51133965Sjdp "ELF_LITERAL", /* name */ 51233965Sjdp false, /* partial_inplace */ 51333965Sjdp 0xffff, /* src_mask */ 51433965Sjdp 0xffff, /* dst_mask */ 51533965Sjdp false), /* pcrel_offset */ 51633965Sjdp 51733965Sjdp /* This reloc only appears immediately following an ELF_LITERAL reloc. 51833965Sjdp It identifies a use of the literal. The symbol index is special: 51933965Sjdp 1 means the literal address is in the base register of a memory 52033965Sjdp format instruction; 2 means the literal address is in the byte 52133965Sjdp offset register of a byte-manipulation instruction; 3 means the 52233965Sjdp literal address is in the target register of a jsr instruction. 52333965Sjdp This does not actually do any relocation. */ 52433965Sjdp HOWTO (R_ALPHA_LITUSE, /* type */ 52533965Sjdp 0, /* rightshift */ 52689862Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 52733965Sjdp 32, /* bitsize */ 52833965Sjdp false, /* pc_relative */ 52933965Sjdp 0, /* bitpos */ 53033965Sjdp complain_overflow_dont, /* complain_on_overflow */ 53133965Sjdp elf64_alpha_reloc_nil, /* special_function */ 53233965Sjdp "LITUSE", /* name */ 53333965Sjdp false, /* partial_inplace */ 53433965Sjdp 0, /* src_mask */ 53533965Sjdp 0, /* dst_mask */ 53633965Sjdp false), /* pcrel_offset */ 53733965Sjdp 53833965Sjdp /* Load the gp register. This is always used for a ldah instruction 53933965Sjdp which loads the upper 16 bits of the gp register. The symbol 54033965Sjdp index of the GPDISP instruction is an offset in bytes to the lda 54133965Sjdp instruction that loads the lower 16 bits. The value to use for 54233965Sjdp the relocation is the difference between the GP value and the 54333965Sjdp current location; the load will always be done against a register 54433965Sjdp holding the current address. 54533965Sjdp 54633965Sjdp NOTE: Unlike ECOFF, partial in-place relocation is not done. If 54733965Sjdp any offset is present in the instructions, it is an offset from 54833965Sjdp the register to the ldah instruction. This lets us avoid any 54933965Sjdp stupid hackery like inventing a gp value to do partial relocation 55033965Sjdp against. Also unlike ECOFF, we do the whole relocation off of 55133965Sjdp the GPDISP rather than a GPDISP_HI16/GPDISP_LO16 pair. An odd, 55233965Sjdp space consuming bit, that, since all the information was present 55333965Sjdp in the GPDISP_HI16 reloc. */ 55433965Sjdp HOWTO (R_ALPHA_GPDISP, /* type */ 55533965Sjdp 16, /* rightshift */ 55633965Sjdp 2, /* size (0 = byte, 1 = short, 2 = long) */ 55733965Sjdp 16, /* bitsize */ 55833965Sjdp false, /* pc_relative */ 55933965Sjdp 0, /* bitpos */ 56033965Sjdp complain_overflow_dont, /* complain_on_overflow */ 56133965Sjdp elf64_alpha_reloc_gpdisp, /* special_function */ 56233965Sjdp "GPDISP", /* name */ 56333965Sjdp false, /* partial_inplace */ 56433965Sjdp 0xffff, /* src_mask */ 56533965Sjdp 0xffff, /* dst_mask */ 56633965Sjdp true), /* pcrel_offset */ 56733965Sjdp 56833965Sjdp /* A 21 bit branch. */ 56933965Sjdp HOWTO (R_ALPHA_BRADDR, /* type */ 57033965Sjdp 2, /* rightshift */ 57133965Sjdp 2, /* size (0 = byte, 1 = short, 2 = long) */ 57233965Sjdp 21, /* bitsize */ 57333965Sjdp true, /* pc_relative */ 57433965Sjdp 0, /* bitpos */ 57533965Sjdp complain_overflow_signed, /* complain_on_overflow */ 57633965Sjdp 0, /* special_function */ 57733965Sjdp "BRADDR", /* name */ 57833965Sjdp false, /* partial_inplace */ 57933965Sjdp 0x1fffff, /* src_mask */ 58033965Sjdp 0x1fffff, /* dst_mask */ 58133965Sjdp true), /* pcrel_offset */ 58233965Sjdp 58333965Sjdp /* A hint for a jump to a register. */ 58433965Sjdp HOWTO (R_ALPHA_HINT, /* type */ 58533965Sjdp 2, /* rightshift */ 58689862Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 58733965Sjdp 14, /* bitsize */ 58833965Sjdp true, /* pc_relative */ 58933965Sjdp 0, /* bitpos */ 59033965Sjdp complain_overflow_dont, /* complain_on_overflow */ 59133965Sjdp 0, /* special_function */ 59233965Sjdp "HINT", /* name */ 59333965Sjdp false, /* partial_inplace */ 59433965Sjdp 0x3fff, /* src_mask */ 59533965Sjdp 0x3fff, /* dst_mask */ 59633965Sjdp true), /* pcrel_offset */ 59733965Sjdp 59833965Sjdp /* 16 bit PC relative offset. */ 59933965Sjdp HOWTO (R_ALPHA_SREL16, /* type */ 60033965Sjdp 0, /* rightshift */ 60133965Sjdp 1, /* size (0 = byte, 1 = short, 2 = long) */ 60233965Sjdp 16, /* bitsize */ 60333965Sjdp true, /* pc_relative */ 60433965Sjdp 0, /* bitpos */ 60533965Sjdp complain_overflow_signed, /* complain_on_overflow */ 60633965Sjdp 0, /* special_function */ 60733965Sjdp "SREL16", /* name */ 60833965Sjdp false, /* partial_inplace */ 60933965Sjdp 0xffff, /* src_mask */ 61033965Sjdp 0xffff, /* dst_mask */ 61178833Sobrien true), /* pcrel_offset */ 61233965Sjdp 61333965Sjdp /* 32 bit PC relative offset. */ 61433965Sjdp HOWTO (R_ALPHA_SREL32, /* type */ 61533965Sjdp 0, /* rightshift */ 61633965Sjdp 2, /* size (0 = byte, 1 = short, 2 = long) */ 61733965Sjdp 32, /* bitsize */ 61833965Sjdp true, /* pc_relative */ 61933965Sjdp 0, /* bitpos */ 62033965Sjdp complain_overflow_signed, /* complain_on_overflow */ 62133965Sjdp 0, /* special_function */ 62233965Sjdp "SREL32", /* name */ 62333965Sjdp false, /* partial_inplace */ 62433965Sjdp 0xffffffff, /* src_mask */ 62533965Sjdp 0xffffffff, /* dst_mask */ 62678833Sobrien true), /* pcrel_offset */ 62733965Sjdp 62833965Sjdp /* A 64 bit PC relative offset. */ 62933965Sjdp HOWTO (R_ALPHA_SREL64, /* type */ 63033965Sjdp 0, /* rightshift */ 63133965Sjdp 4, /* size (0 = byte, 1 = short, 2 = long) */ 63233965Sjdp 64, /* bitsize */ 63333965Sjdp true, /* pc_relative */ 63433965Sjdp 0, /* bitpos */ 63533965Sjdp complain_overflow_signed, /* complain_on_overflow */ 63633965Sjdp 0, /* special_function */ 63733965Sjdp "SREL64", /* name */ 63833965Sjdp false, /* partial_inplace */ 63933965Sjdp MINUS_ONE, /* src_mask */ 64033965Sjdp MINUS_ONE, /* dst_mask */ 64178833Sobrien true), /* pcrel_offset */ 64233965Sjdp 64389862Sobrien /* Skip 12 - 16; deprecated ECOFF relocs. */ 64489862Sobrien SKIP_HOWTO (12), 64589862Sobrien SKIP_HOWTO (13), 64689862Sobrien SKIP_HOWTO (14), 64789862Sobrien SKIP_HOWTO (15), 64889862Sobrien SKIP_HOWTO (16), 64933965Sjdp 65038889Sjdp /* The high 16 bits of the displacement from GP to the target. */ 65138889Sjdp HOWTO (R_ALPHA_GPRELHIGH, 65238889Sjdp 0, /* rightshift */ 65389862Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 65460510Sobrien 16, /* bitsize */ 65538889Sjdp false, /* pc_relative */ 65638889Sjdp 0, /* bitpos */ 65760510Sobrien complain_overflow_signed, /* complain_on_overflow */ 65889862Sobrien 0, /* special_function */ 65938889Sjdp "GPRELHIGH", /* name */ 66038889Sjdp false, /* partial_inplace */ 66160510Sobrien 0xffff, /* src_mask */ 66260510Sobrien 0xffff, /* dst_mask */ 66338889Sjdp false), /* pcrel_offset */ 66438889Sjdp 66538889Sjdp /* The low 16 bits of the displacement from GP to the target. */ 66638889Sjdp HOWTO (R_ALPHA_GPRELLOW, 66738889Sjdp 0, /* rightshift */ 66889862Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 66960510Sobrien 16, /* bitsize */ 67038889Sjdp false, /* pc_relative */ 67138889Sjdp 0, /* bitpos */ 67238889Sjdp complain_overflow_dont, /* complain_on_overflow */ 67389862Sobrien 0, /* special_function */ 67438889Sjdp "GPRELLOW", /* name */ 67538889Sjdp false, /* partial_inplace */ 67660510Sobrien 0xffff, /* src_mask */ 67760510Sobrien 0xffff, /* dst_mask */ 67838889Sjdp false), /* pcrel_offset */ 67938889Sjdp 68038889Sjdp /* A 16-bit displacement from the GP to the target. */ 68189862Sobrien HOWTO (R_ALPHA_GPREL16, 68238889Sjdp 0, /* rightshift */ 68389862Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 68460510Sobrien 16, /* bitsize */ 68538889Sjdp false, /* pc_relative */ 68638889Sjdp 0, /* bitpos */ 68760510Sobrien complain_overflow_signed, /* complain_on_overflow */ 68860510Sobrien 0, /* special_function */ 68989862Sobrien "GPREL16", /* name */ 69038889Sjdp false, /* partial_inplace */ 69160510Sobrien 0xffff, /* src_mask */ 69260510Sobrien 0xffff, /* dst_mask */ 69338889Sjdp false), /* pcrel_offset */ 69438889Sjdp 69589862Sobrien /* Skip 20 - 23; deprecated ECOFF relocs. */ 69689862Sobrien SKIP_HOWTO (20), 69789862Sobrien SKIP_HOWTO (21), 69889862Sobrien SKIP_HOWTO (22), 69989862Sobrien SKIP_HOWTO (23), 70038889Sjdp 70177303Sobrien /* Misc ELF relocations. */ 70238889Sjdp 70338889Sjdp /* A dynamic relocation to copy the target into our .dynbss section. */ 70438889Sjdp /* Not generated, as all Alpha objects use PIC, so it is not needed. It 70538889Sjdp is present because every other ELF has one, but should not be used 70638889Sjdp because .dynbss is an ugly thing. */ 70733965Sjdp HOWTO (R_ALPHA_COPY, 70833965Sjdp 0, 70933965Sjdp 0, 71033965Sjdp 0, 71133965Sjdp false, 71233965Sjdp 0, 71333965Sjdp complain_overflow_dont, 71433965Sjdp bfd_elf_generic_reloc, 71533965Sjdp "COPY", 71633965Sjdp false, 71733965Sjdp 0, 71833965Sjdp 0, 71933965Sjdp true), 72033965Sjdp 72138889Sjdp /* A dynamic relocation for a .got entry. */ 72233965Sjdp HOWTO (R_ALPHA_GLOB_DAT, 72333965Sjdp 0, 72433965Sjdp 0, 72533965Sjdp 0, 72633965Sjdp false, 72733965Sjdp 0, 72833965Sjdp complain_overflow_dont, 72933965Sjdp bfd_elf_generic_reloc, 73033965Sjdp "GLOB_DAT", 73133965Sjdp false, 73233965Sjdp 0, 73333965Sjdp 0, 73433965Sjdp true), 73533965Sjdp 73638889Sjdp /* A dynamic relocation for a .plt entry. */ 73733965Sjdp HOWTO (R_ALPHA_JMP_SLOT, 73833965Sjdp 0, 73933965Sjdp 0, 74033965Sjdp 0, 74133965Sjdp false, 74233965Sjdp 0, 74333965Sjdp complain_overflow_dont, 74433965Sjdp bfd_elf_generic_reloc, 74533965Sjdp "JMP_SLOT", 74633965Sjdp false, 74733965Sjdp 0, 74833965Sjdp 0, 74933965Sjdp true), 75033965Sjdp 75138889Sjdp /* A dynamic relocation to add the base of the DSO to a 64-bit field. */ 75233965Sjdp HOWTO (R_ALPHA_RELATIVE, 75333965Sjdp 0, 75433965Sjdp 0, 75533965Sjdp 0, 75633965Sjdp false, 75733965Sjdp 0, 75833965Sjdp complain_overflow_dont, 75933965Sjdp bfd_elf_generic_reloc, 76033965Sjdp "RELATIVE", 76133965Sjdp false, 76233965Sjdp 0, 76333965Sjdp 0, 76491049Sobrien true), 76591049Sobrien 76691049Sobrien /* A 21 bit branch that adjusts for gp loads. */ 76791049Sobrien HOWTO (R_ALPHA_BRSGP, /* type */ 76891049Sobrien 2, /* rightshift */ 76991049Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 77091049Sobrien 21, /* bitsize */ 77191049Sobrien true, /* pc_relative */ 77291049Sobrien 0, /* bitpos */ 77391049Sobrien complain_overflow_signed, /* complain_on_overflow */ 77491049Sobrien 0, /* special_function */ 77591049Sobrien "BRSGP", /* name */ 77691049Sobrien false, /* partial_inplace */ 77791049Sobrien 0x1fffff, /* src_mask */ 77891049Sobrien 0x1fffff, /* dst_mask */ 77991049Sobrien true), /* pcrel_offset */ 780104841Sobrien 781104841Sobrien /* Creates a tls_index for the symbol in the got. */ 782104841Sobrien HOWTO (R_ALPHA_TLSGD, /* type */ 783104841Sobrien 0, /* rightshift */ 784104841Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 785104841Sobrien 16, /* bitsize */ 786104841Sobrien false, /* pc_relative */ 787104841Sobrien 0, /* bitpos */ 788104841Sobrien complain_overflow_signed, /* complain_on_overflow */ 789104841Sobrien 0, /* special_function */ 790104841Sobrien "TLSGD", /* name */ 791104841Sobrien false, /* partial_inplace */ 792104841Sobrien 0xffff, /* src_mask */ 793104841Sobrien 0xffff, /* dst_mask */ 794104841Sobrien false), /* pcrel_offset */ 795104841Sobrien 796104841Sobrien /* Creates a tls_index for the (current) module in the got. */ 797104841Sobrien HOWTO (R_ALPHA_TLSLDM, /* type */ 798104841Sobrien 0, /* rightshift */ 799104841Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 800104841Sobrien 16, /* bitsize */ 801104841Sobrien false, /* pc_relative */ 802104841Sobrien 0, /* bitpos */ 803104841Sobrien complain_overflow_signed, /* complain_on_overflow */ 804104841Sobrien 0, /* special_function */ 805104841Sobrien "TLSLDM", /* name */ 806104841Sobrien false, /* partial_inplace */ 807104841Sobrien 0xffff, /* src_mask */ 808104841Sobrien 0xffff, /* dst_mask */ 809104841Sobrien false), /* pcrel_offset */ 810104841Sobrien 811104841Sobrien /* A dynamic relocation for a DTP module entry. */ 812104841Sobrien HOWTO (R_ALPHA_DTPMOD64, /* type */ 813104841Sobrien 0, /* rightshift */ 814104841Sobrien 4, /* size (0 = byte, 1 = short, 2 = long) */ 815104841Sobrien 64, /* bitsize */ 816104841Sobrien false, /* pc_relative */ 817104841Sobrien 0, /* bitpos */ 818104841Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 819104841Sobrien 0, /* special_function */ 820104841Sobrien "DTPMOD64", /* name */ 821104841Sobrien false, /* partial_inplace */ 822104841Sobrien MINUS_ONE, /* src_mask */ 823104841Sobrien MINUS_ONE, /* dst_mask */ 824104841Sobrien false), /* pcrel_offset */ 825104841Sobrien 826104841Sobrien /* Creates a 64-bit offset in the got for the displacement 827104841Sobrien from DTP to the target. */ 828104841Sobrien HOWTO (R_ALPHA_GOTDTPREL, /* type */ 829104841Sobrien 0, /* rightshift */ 830104841Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 831104841Sobrien 16, /* bitsize */ 832104841Sobrien false, /* pc_relative */ 833104841Sobrien 0, /* bitpos */ 834104841Sobrien complain_overflow_signed, /* complain_on_overflow */ 835104841Sobrien 0, /* special_function */ 836104841Sobrien "GOTDTPREL", /* name */ 837104841Sobrien false, /* partial_inplace */ 838104841Sobrien 0xffff, /* src_mask */ 839104841Sobrien 0xffff, /* dst_mask */ 840104841Sobrien false), /* pcrel_offset */ 841104841Sobrien 842104841Sobrien /* A dynamic relocation for a displacement from DTP to the target. */ 843104841Sobrien HOWTO (R_ALPHA_DTPREL64, /* type */ 844104841Sobrien 0, /* rightshift */ 845104841Sobrien 4, /* size (0 = byte, 1 = short, 2 = long) */ 846104841Sobrien 64, /* bitsize */ 847104841Sobrien false, /* pc_relative */ 848104841Sobrien 0, /* bitpos */ 849104841Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 850104841Sobrien 0, /* special_function */ 851104841Sobrien "DTPREL64", /* name */ 852104841Sobrien false, /* partial_inplace */ 853104841Sobrien MINUS_ONE, /* src_mask */ 854104841Sobrien MINUS_ONE, /* dst_mask */ 855104841Sobrien false), /* pcrel_offset */ 856104841Sobrien 857104841Sobrien /* The high 16 bits of the displacement from DTP to the target. */ 858104841Sobrien HOWTO (R_ALPHA_DTPRELHI, /* type */ 859104841Sobrien 0, /* rightshift */ 860104841Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 861104841Sobrien 16, /* bitsize */ 862104841Sobrien false, /* pc_relative */ 863104841Sobrien 0, /* bitpos */ 864104841Sobrien complain_overflow_signed, /* complain_on_overflow */ 865104841Sobrien 0, /* special_function */ 866104841Sobrien "DTPRELHI", /* name */ 867104841Sobrien false, /* partial_inplace */ 868104841Sobrien 0xffff, /* src_mask */ 869104841Sobrien 0xffff, /* dst_mask */ 870104841Sobrien false), /* pcrel_offset */ 871104841Sobrien 872104841Sobrien /* The low 16 bits of the displacement from DTP to the target. */ 873104841Sobrien HOWTO (R_ALPHA_DTPRELLO, /* type */ 874104841Sobrien 0, /* rightshift */ 875104841Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 876104841Sobrien 16, /* bitsize */ 877104841Sobrien false, /* pc_relative */ 878104841Sobrien 0, /* bitpos */ 879104841Sobrien complain_overflow_dont, /* complain_on_overflow */ 880104841Sobrien 0, /* special_function */ 881104841Sobrien "DTPRELLO", /* name */ 882104841Sobrien false, /* partial_inplace */ 883104841Sobrien 0xffff, /* src_mask */ 884104841Sobrien 0xffff, /* dst_mask */ 885104841Sobrien false), /* pcrel_offset */ 886104841Sobrien 887104841Sobrien /* A 16-bit displacement from DTP to the target. */ 888104841Sobrien HOWTO (R_ALPHA_DTPREL16, /* type */ 889104841Sobrien 0, /* rightshift */ 890104841Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 891104841Sobrien 16, /* bitsize */ 892104841Sobrien false, /* pc_relative */ 893104841Sobrien 0, /* bitpos */ 894104841Sobrien complain_overflow_signed, /* complain_on_overflow */ 895104841Sobrien 0, /* special_function */ 896104841Sobrien "DTPREL16", /* name */ 897104841Sobrien false, /* partial_inplace */ 898104841Sobrien 0xffff, /* src_mask */ 899104841Sobrien 0xffff, /* dst_mask */ 900104841Sobrien false), /* pcrel_offset */ 901104841Sobrien 902104841Sobrien /* Creates a 64-bit offset in the got for the displacement 903104841Sobrien from TP to the target. */ 904104841Sobrien HOWTO (R_ALPHA_GOTTPREL, /* type */ 905104841Sobrien 0, /* rightshift */ 906104841Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 907104841Sobrien 16, /* bitsize */ 908104841Sobrien false, /* pc_relative */ 909104841Sobrien 0, /* bitpos */ 910104841Sobrien complain_overflow_signed, /* complain_on_overflow */ 911104841Sobrien 0, /* special_function */ 912104841Sobrien "GOTTPREL", /* name */ 913104841Sobrien false, /* partial_inplace */ 914104841Sobrien 0xffff, /* src_mask */ 915104841Sobrien 0xffff, /* dst_mask */ 916104841Sobrien false), /* pcrel_offset */ 917104841Sobrien 918104841Sobrien /* A dynamic relocation for a displacement from TP to the target. */ 919104841Sobrien HOWTO (R_ALPHA_TPREL64, /* type */ 920104841Sobrien 0, /* rightshift */ 921104841Sobrien 4, /* size (0 = byte, 1 = short, 2 = long) */ 922104841Sobrien 64, /* bitsize */ 923104841Sobrien false, /* pc_relative */ 924104841Sobrien 0, /* bitpos */ 925104841Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 926104841Sobrien 0, /* special_function */ 927104841Sobrien "TPREL64", /* name */ 928104841Sobrien false, /* partial_inplace */ 929104841Sobrien MINUS_ONE, /* src_mask */ 930104841Sobrien MINUS_ONE, /* dst_mask */ 931104841Sobrien false), /* pcrel_offset */ 932104841Sobrien 933104841Sobrien /* The high 16 bits of the displacement from TP to the target. */ 934104841Sobrien HOWTO (R_ALPHA_TPRELHI, /* type */ 935104841Sobrien 0, /* rightshift */ 936104841Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 937104841Sobrien 16, /* bitsize */ 938104841Sobrien false, /* pc_relative */ 939104841Sobrien 0, /* bitpos */ 940104841Sobrien complain_overflow_signed, /* complain_on_overflow */ 941104841Sobrien 0, /* special_function */ 942104841Sobrien "TPRELHI", /* name */ 943104841Sobrien false, /* partial_inplace */ 944104841Sobrien 0xffff, /* src_mask */ 945104841Sobrien 0xffff, /* dst_mask */ 946104841Sobrien false), /* pcrel_offset */ 947104841Sobrien 948104841Sobrien /* The low 16 bits of the displacement from TP to the target. */ 949104841Sobrien HOWTO (R_ALPHA_TPRELLO, /* type */ 950104841Sobrien 0, /* rightshift */ 951104841Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 952104841Sobrien 16, /* bitsize */ 953104841Sobrien false, /* pc_relative */ 954104841Sobrien 0, /* bitpos */ 955104841Sobrien complain_overflow_dont, /* complain_on_overflow */ 956104841Sobrien 0, /* special_function */ 957104841Sobrien "TPRELLO", /* name */ 958104841Sobrien false, /* partial_inplace */ 959104841Sobrien 0xffff, /* src_mask */ 960104841Sobrien 0xffff, /* dst_mask */ 961104841Sobrien false), /* pcrel_offset */ 962104841Sobrien 963104841Sobrien /* A 16-bit displacement from TP to the target. */ 964104841Sobrien HOWTO (R_ALPHA_TPREL16, /* type */ 965104841Sobrien 0, /* rightshift */ 966104841Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 967104841Sobrien 16, /* bitsize */ 968104841Sobrien false, /* pc_relative */ 969104841Sobrien 0, /* bitpos */ 970104841Sobrien complain_overflow_signed, /* complain_on_overflow */ 971104841Sobrien 0, /* special_function */ 972104841Sobrien "TPREL16", /* name */ 973104841Sobrien false, /* partial_inplace */ 974104841Sobrien 0xffff, /* src_mask */ 975104841Sobrien 0xffff, /* dst_mask */ 976104841Sobrien false), /* pcrel_offset */ 97733965Sjdp}; 97833965Sjdp 97933965Sjdp/* A relocation function which doesn't do anything. */ 98033965Sjdp 98133965Sjdpstatic bfd_reloc_status_type 98233965Sjdpelf64_alpha_reloc_nil (abfd, reloc, sym, data, sec, output_bfd, error_message) 98378833Sobrien bfd *abfd ATTRIBUTE_UNUSED; 98433965Sjdp arelent *reloc; 98578833Sobrien asymbol *sym ATTRIBUTE_UNUSED; 98678833Sobrien PTR data ATTRIBUTE_UNUSED; 98733965Sjdp asection *sec; 98833965Sjdp bfd *output_bfd; 98978833Sobrien char **error_message ATTRIBUTE_UNUSED; 99033965Sjdp{ 99133965Sjdp if (output_bfd) 99233965Sjdp reloc->address += sec->output_offset; 99333965Sjdp return bfd_reloc_ok; 99433965Sjdp} 99533965Sjdp 99633965Sjdp/* A relocation function used for an unsupported reloc. */ 99733965Sjdp 99833965Sjdpstatic bfd_reloc_status_type 99933965Sjdpelf64_alpha_reloc_bad (abfd, reloc, sym, data, sec, output_bfd, error_message) 100078833Sobrien bfd *abfd ATTRIBUTE_UNUSED; 100133965Sjdp arelent *reloc; 100278833Sobrien asymbol *sym ATTRIBUTE_UNUSED; 100378833Sobrien PTR data ATTRIBUTE_UNUSED; 100433965Sjdp asection *sec; 100533965Sjdp bfd *output_bfd; 100678833Sobrien char **error_message ATTRIBUTE_UNUSED; 100733965Sjdp{ 100833965Sjdp if (output_bfd) 100933965Sjdp reloc->address += sec->output_offset; 101033965Sjdp return bfd_reloc_notsupported; 101133965Sjdp} 101233965Sjdp 101333965Sjdp/* Do the work of the GPDISP relocation. */ 101433965Sjdp 101533965Sjdpstatic bfd_reloc_status_type 101633965Sjdpelf64_alpha_do_reloc_gpdisp (abfd, gpdisp, p_ldah, p_lda) 101733965Sjdp bfd *abfd; 101833965Sjdp bfd_vma gpdisp; 101933965Sjdp bfd_byte *p_ldah; 102033965Sjdp bfd_byte *p_lda; 102133965Sjdp{ 102233965Sjdp bfd_reloc_status_type ret = bfd_reloc_ok; 102333965Sjdp bfd_vma addend; 102433965Sjdp unsigned long i_ldah, i_lda; 102533965Sjdp 102633965Sjdp i_ldah = bfd_get_32 (abfd, p_ldah); 102733965Sjdp i_lda = bfd_get_32 (abfd, p_lda); 102833965Sjdp 102933965Sjdp /* Complain if the instructions are not correct. */ 103033965Sjdp if (((i_ldah >> 26) & 0x3f) != 0x09 103133965Sjdp || ((i_lda >> 26) & 0x3f) != 0x08) 103233965Sjdp ret = bfd_reloc_dangerous; 103333965Sjdp 103433965Sjdp /* Extract the user-supplied offset, mirroring the sign extensions 103533965Sjdp that the instructions perform. */ 103633965Sjdp addend = ((i_ldah & 0xffff) << 16) | (i_lda & 0xffff); 103733965Sjdp addend = (addend ^ 0x80008000) - 0x80008000; 103833965Sjdp 103933965Sjdp gpdisp += addend; 104033965Sjdp 104148850Sdfr if ((bfd_signed_vma) gpdisp < -(bfd_signed_vma) 0x80000000 104248850Sdfr || (bfd_signed_vma) gpdisp >= (bfd_signed_vma) 0x7fff8000) 104333965Sjdp ret = bfd_reloc_overflow; 104433965Sjdp 104533965Sjdp /* compensate for the sign extension again. */ 104633965Sjdp i_ldah = ((i_ldah & 0xffff0000) 104733965Sjdp | (((gpdisp >> 16) + ((gpdisp >> 15) & 1)) & 0xffff)); 104833965Sjdp i_lda = (i_lda & 0xffff0000) | (gpdisp & 0xffff); 104933965Sjdp 105089862Sobrien bfd_put_32 (abfd, (bfd_vma) i_ldah, p_ldah); 105189862Sobrien bfd_put_32 (abfd, (bfd_vma) i_lda, p_lda); 105233965Sjdp 105333965Sjdp return ret; 105433965Sjdp} 105533965Sjdp 105633965Sjdp/* The special function for the GPDISP reloc. */ 105733965Sjdp 105833965Sjdpstatic bfd_reloc_status_type 105933965Sjdpelf64_alpha_reloc_gpdisp (abfd, reloc_entry, sym, data, input_section, 106033965Sjdp output_bfd, err_msg) 106133965Sjdp bfd *abfd; 106233965Sjdp arelent *reloc_entry; 106378833Sobrien asymbol *sym ATTRIBUTE_UNUSED; 106433965Sjdp PTR data; 106533965Sjdp asection *input_section; 106633965Sjdp bfd *output_bfd; 106733965Sjdp char **err_msg; 106833965Sjdp{ 106933965Sjdp bfd_reloc_status_type ret; 107033965Sjdp bfd_vma gp, relocation; 107133965Sjdp bfd_byte *p_ldah, *p_lda; 107233965Sjdp 107333965Sjdp /* Don't do anything if we're not doing a final link. */ 107433965Sjdp if (output_bfd) 107533965Sjdp { 107633965Sjdp reloc_entry->address += input_section->output_offset; 107733965Sjdp return bfd_reloc_ok; 107833965Sjdp } 107933965Sjdp 108033965Sjdp if (reloc_entry->address > input_section->_cooked_size || 108133965Sjdp reloc_entry->address + reloc_entry->addend > input_section->_cooked_size) 108233965Sjdp return bfd_reloc_outofrange; 108333965Sjdp 108433965Sjdp /* The gp used in the portion of the output object to which this 108533965Sjdp input object belongs is cached on the input bfd. */ 108633965Sjdp gp = _bfd_get_gp_value (abfd); 108733965Sjdp 108833965Sjdp relocation = (input_section->output_section->vma 108933965Sjdp + input_section->output_offset 109033965Sjdp + reloc_entry->address); 109133965Sjdp 109233965Sjdp p_ldah = (bfd_byte *) data + reloc_entry->address; 109333965Sjdp p_lda = p_ldah + reloc_entry->addend; 109433965Sjdp 109533965Sjdp ret = elf64_alpha_do_reloc_gpdisp (abfd, gp - relocation, p_ldah, p_lda); 109633965Sjdp 109733965Sjdp /* Complain if the instructions are not correct. */ 109833965Sjdp if (ret == bfd_reloc_dangerous) 109960510Sobrien *err_msg = _("GPDISP relocation did not find ldah and lda instructions"); 110033965Sjdp 110133965Sjdp return ret; 110233965Sjdp} 110333965Sjdp 110433965Sjdp/* A mapping from BFD reloc types to Alpha ELF reloc types. */ 110533965Sjdp 110633965Sjdpstruct elf_reloc_map 110733965Sjdp{ 110833965Sjdp bfd_reloc_code_real_type bfd_reloc_val; 110933965Sjdp int elf_reloc_val; 111033965Sjdp}; 111133965Sjdp 111233965Sjdpstatic const struct elf_reloc_map elf64_alpha_reloc_map[] = 111333965Sjdp{ 111489862Sobrien {BFD_RELOC_NONE, R_ALPHA_NONE}, 111589862Sobrien {BFD_RELOC_32, R_ALPHA_REFLONG}, 111689862Sobrien {BFD_RELOC_64, R_ALPHA_REFQUAD}, 111789862Sobrien {BFD_RELOC_CTOR, R_ALPHA_REFQUAD}, 111889862Sobrien {BFD_RELOC_GPREL32, R_ALPHA_GPREL32}, 111989862Sobrien {BFD_RELOC_ALPHA_ELF_LITERAL, R_ALPHA_LITERAL}, 112089862Sobrien {BFD_RELOC_ALPHA_LITUSE, R_ALPHA_LITUSE}, 112189862Sobrien {BFD_RELOC_ALPHA_GPDISP, R_ALPHA_GPDISP}, 112289862Sobrien {BFD_RELOC_23_PCREL_S2, R_ALPHA_BRADDR}, 112389862Sobrien {BFD_RELOC_ALPHA_HINT, R_ALPHA_HINT}, 112489862Sobrien {BFD_RELOC_16_PCREL, R_ALPHA_SREL16}, 112589862Sobrien {BFD_RELOC_32_PCREL, R_ALPHA_SREL32}, 112689862Sobrien {BFD_RELOC_64_PCREL, R_ALPHA_SREL64}, 112789862Sobrien {BFD_RELOC_ALPHA_GPREL_HI16, R_ALPHA_GPRELHIGH}, 112889862Sobrien {BFD_RELOC_ALPHA_GPREL_LO16, R_ALPHA_GPRELLOW}, 112989862Sobrien {BFD_RELOC_GPREL16, R_ALPHA_GPREL16}, 113091049Sobrien {BFD_RELOC_ALPHA_BRSGP, R_ALPHA_BRSGP}, 1131104841Sobrien {BFD_RELOC_ALPHA_TLSGD, R_ALPHA_TLSGD}, 1132104841Sobrien {BFD_RELOC_ALPHA_TLSLDM, R_ALPHA_TLSLDM}, 1133104841Sobrien {BFD_RELOC_ALPHA_DTPMOD64, R_ALPHA_DTPMOD64}, 1134104841Sobrien {BFD_RELOC_ALPHA_GOTDTPREL16, R_ALPHA_GOTDTPREL}, 1135104841Sobrien {BFD_RELOC_ALPHA_DTPREL64, R_ALPHA_DTPREL64}, 1136104841Sobrien {BFD_RELOC_ALPHA_DTPREL_HI16, R_ALPHA_DTPRELHI}, 1137104841Sobrien {BFD_RELOC_ALPHA_DTPREL_LO16, R_ALPHA_DTPRELLO}, 1138104841Sobrien {BFD_RELOC_ALPHA_DTPREL16, R_ALPHA_DTPREL16}, 1139104841Sobrien {BFD_RELOC_ALPHA_GOTTPREL16, R_ALPHA_GOTTPREL}, 1140104841Sobrien {BFD_RELOC_ALPHA_TPREL64, R_ALPHA_TPREL64}, 1141104841Sobrien {BFD_RELOC_ALPHA_TPREL_HI16, R_ALPHA_TPRELHI}, 1142104841Sobrien {BFD_RELOC_ALPHA_TPREL_LO16, R_ALPHA_TPRELLO}, 1143104841Sobrien {BFD_RELOC_ALPHA_TPREL16, R_ALPHA_TPREL16}, 114433965Sjdp}; 114533965Sjdp 114633965Sjdp/* Given a BFD reloc type, return a HOWTO structure. */ 114733965Sjdp 114833965Sjdpstatic reloc_howto_type * 114933965Sjdpelf64_alpha_bfd_reloc_type_lookup (abfd, code) 115078833Sobrien bfd *abfd ATTRIBUTE_UNUSED; 115133965Sjdp bfd_reloc_code_real_type code; 115233965Sjdp{ 115333965Sjdp const struct elf_reloc_map *i, *e; 115433965Sjdp i = e = elf64_alpha_reloc_map; 115533965Sjdp e += sizeof (elf64_alpha_reloc_map) / sizeof (struct elf_reloc_map); 115633965Sjdp for (; i != e; ++i) 115733965Sjdp { 115833965Sjdp if (i->bfd_reloc_val == code) 115933965Sjdp return &elf64_alpha_howto_table[i->elf_reloc_val]; 116033965Sjdp } 116133965Sjdp return 0; 116233965Sjdp} 116333965Sjdp 116433965Sjdp/* Given an Alpha ELF reloc type, fill in an arelent structure. */ 116533965Sjdp 116633965Sjdpstatic void 116733965Sjdpelf64_alpha_info_to_howto (abfd, cache_ptr, dst) 116878833Sobrien bfd *abfd ATTRIBUTE_UNUSED; 116933965Sjdp arelent *cache_ptr; 117033965Sjdp Elf64_Internal_Rela *dst; 117133965Sjdp{ 117233965Sjdp unsigned r_type; 117333965Sjdp 117433965Sjdp r_type = ELF64_R_TYPE(dst->r_info); 117533965Sjdp BFD_ASSERT (r_type < (unsigned int) R_ALPHA_max); 117633965Sjdp cache_ptr->howto = &elf64_alpha_howto_table[r_type]; 117733965Sjdp} 1178104841Sobrien 1179104841Sobrien/* These two relocations create a two-word entry in the got. */ 1180104841Sobrien#define alpha_got_entry_size(r_type) \ 1181104841Sobrien (r_type == R_ALPHA_TLSGD || r_type == R_ALPHA_TLSLDM ? 16 : 8) 1182104841Sobrien 1183104841Sobrien/* This is PT_TLS segment p_vaddr. */ 1184104841Sobrien#define alpha_get_dtprel_base(tlss) \ 1185104841Sobrien ((tlss)->start) 1186104841Sobrien 1187104841Sobrien/* Main program TLS (whose template starts at PT_TLS p_vaddr) 1188104841Sobrien is assigned offset round(16, PT_TLS p_align). */ 1189104841Sobrien#define alpha_get_tprel_base(tlss) \ 1190104841Sobrien ((tlss)->start - align_power ((bfd_vma) 16, (tlss)->align)) 119133965Sjdp 119277303Sobrien/* These functions do relaxation for Alpha ELF. 119360510Sobrien 119460510Sobrien Currently I'm only handling what I can do with existing compiler 119560510Sobrien and assembler support, which means no instructions are removed, 119660510Sobrien though some may be nopped. At this time GCC does not emit enough 119760510Sobrien information to do all of the relaxing that is possible. It will 119860510Sobrien take some not small amount of work for that to happen. 119960510Sobrien 120060510Sobrien There are a couple of interesting papers that I once read on this 120160510Sobrien subject, that I cannot find references to at the moment, that 120260510Sobrien related to Alpha in particular. They are by David Wall, then of 120360510Sobrien DEC WRL. */ 120460510Sobrien 120560510Sobrien#define OP_LDA 0x08 120660510Sobrien#define OP_LDAH 0x09 120760510Sobrien#define INSN_JSR 0x68004000 120860510Sobrien#define INSN_JSR_MASK 0xfc00c000 120960510Sobrien#define OP_LDQ 0x29 121060510Sobrien#define OP_BR 0x30 121160510Sobrien#define OP_BSR 0x34 121289862Sobrien#define INSN_UNOP 0x2ffe0000 1213104841Sobrien#define INSN_ADDQ 0x40000400 1214104841Sobrien#define INSN_RDUNIQ 0x0000009e 121560510Sobrien 121660510Sobrienstruct alpha_relax_info 121760510Sobrien{ 121860510Sobrien bfd *abfd; 121960510Sobrien asection *sec; 122060510Sobrien bfd_byte *contents; 1221104841Sobrien Elf_Internal_Shdr *symtab_hdr; 122260510Sobrien Elf_Internal_Rela *relocs, *relend; 122360510Sobrien struct bfd_link_info *link_info; 1224104841Sobrien struct elf_link_tls_segment *tls_segment; 122560510Sobrien bfd_vma gp; 122660510Sobrien bfd *gotobj; 122760510Sobrien asection *tsec; 122860510Sobrien struct alpha_elf_link_hash_entry *h; 1229104841Sobrien struct alpha_elf_got_entry **first_gotent; 123060510Sobrien struct alpha_elf_got_entry *gotent; 1231104841Sobrien boolean changed_contents; 1232104841Sobrien boolean changed_relocs; 123360510Sobrien unsigned char other; 123460510Sobrien}; 123560510Sobrien 1236104841Sobrienstatic boolean elf64_alpha_relax_with_lituse 123777303Sobrien PARAMS((struct alpha_relax_info *info, bfd_vma symval, 123860510Sobrien Elf_Internal_Rela *irel)); 123960510Sobrienstatic bfd_vma elf64_alpha_relax_opt_call 124060510Sobrien PARAMS((struct alpha_relax_info *info, bfd_vma symval)); 1241104841Sobrienstatic boolean elf64_alpha_relax_got_load 1242104841Sobrien PARAMS((struct alpha_relax_info *info, bfd_vma symval, 1243104841Sobrien Elf_Internal_Rela *irel, unsigned long)); 1244104841Sobrienstatic boolean elf64_alpha_relax_gprelhilo 1245104841Sobrien PARAMS((struct alpha_relax_info *info, bfd_vma symval, 1246104841Sobrien Elf_Internal_Rela *irel, boolean)); 1247104841Sobrienstatic boolean elf64_alpha_relax_tls_get_addr 1248104841Sobrien PARAMS((struct alpha_relax_info *info, bfd_vma symval, 1249104841Sobrien Elf_Internal_Rela *irel, boolean)); 1250104841Sobrienstatic struct elf_link_tls_segment *elf64_alpha_relax_find_tls_segment 1251104841Sobrien PARAMS((struct alpha_relax_info *, struct elf_link_tls_segment *)); 125260510Sobrienstatic boolean elf64_alpha_relax_section 125360510Sobrien PARAMS((bfd *abfd, asection *sec, struct bfd_link_info *link_info, 125460510Sobrien boolean *again)); 125560510Sobrien 125660510Sobrienstatic Elf_Internal_Rela * 125760510Sobrienelf64_alpha_find_reloc_at_ofs (rel, relend, offset, type) 125860510Sobrien Elf_Internal_Rela *rel, *relend; 125960510Sobrien bfd_vma offset; 126060510Sobrien int type; 126160510Sobrien{ 126260510Sobrien while (rel < relend) 126360510Sobrien { 126489862Sobrien if (rel->r_offset == offset 126589862Sobrien && ELF64_R_TYPE (rel->r_info) == (unsigned int) type) 126660510Sobrien return rel; 126760510Sobrien ++rel; 126860510Sobrien } 126960510Sobrien return NULL; 127060510Sobrien} 127160510Sobrien 1272104841Sobrienstatic boolean 1273104841Sobrienelf64_alpha_relax_with_lituse (info, symval, irel) 127460510Sobrien struct alpha_relax_info *info; 127560510Sobrien bfd_vma symval; 1276104841Sobrien Elf_Internal_Rela *irel; 127760510Sobrien{ 1278104841Sobrien Elf_Internal_Rela *urel, *irelend = info->relend; 127960510Sobrien int flags, count, i; 128060510Sobrien bfd_signed_vma disp; 128160510Sobrien boolean fits16; 128260510Sobrien boolean fits32; 128360510Sobrien boolean lit_reused = false; 128460510Sobrien boolean all_optimized = true; 128560510Sobrien unsigned int lit_insn; 128660510Sobrien 128760510Sobrien lit_insn = bfd_get_32 (info->abfd, info->contents + irel->r_offset); 128860510Sobrien if (lit_insn >> 26 != OP_LDQ) 128960510Sobrien { 129060510Sobrien ((*_bfd_error_handler) 129160510Sobrien ("%s: %s+0x%lx: warning: LITERAL relocation against unexpected insn", 129289862Sobrien bfd_archive_filename (info->abfd), info->sec->name, 129389862Sobrien (unsigned long) irel->r_offset)); 1294104841Sobrien return true; 129560510Sobrien } 129660510Sobrien 1297104841Sobrien /* Can't relax dynamic symbols. */ 1298104841Sobrien if (alpha_elf_dynamic_symbol_p (&info->h->root, info->link_info)) 1299104841Sobrien return true; 1300104841Sobrien 130160510Sobrien /* Summarize how this particular LITERAL is used. */ 130260510Sobrien for (urel = irel+1, flags = count = 0; urel < irelend; ++urel, ++count) 130360510Sobrien { 130460510Sobrien if (ELF64_R_TYPE (urel->r_info) != R_ALPHA_LITUSE) 130560510Sobrien break; 130689862Sobrien if (urel->r_addend <= 3) 130760510Sobrien flags |= 1 << urel->r_addend; 130860510Sobrien } 130960510Sobrien 131077303Sobrien /* A little preparation for the loop... */ 131160510Sobrien disp = symval - info->gp; 131260510Sobrien 131360510Sobrien for (urel = irel+1, i = 0; i < count; ++i, ++urel) 131460510Sobrien { 131560510Sobrien unsigned int insn; 131677303Sobrien int insn_disp; 131777303Sobrien bfd_signed_vma xdisp; 131877303Sobrien 131960510Sobrien insn = bfd_get_32 (info->abfd, info->contents + urel->r_offset); 132060510Sobrien 132160510Sobrien switch (urel->r_addend) 132260510Sobrien { 1323104841Sobrien case LITUSE_ALPHA_ADDR: 1324104841Sobrien default: 132560510Sobrien /* This type is really just a placeholder to note that all 132660510Sobrien uses cannot be optimized, but to still allow some. */ 132760510Sobrien all_optimized = false; 132860510Sobrien break; 132960510Sobrien 1330104841Sobrien case LITUSE_ALPHA_BASE: 133160510Sobrien /* We can always optimize 16-bit displacements. */ 133277303Sobrien 133377303Sobrien /* Extract the displacement from the instruction, sign-extending 133477303Sobrien it if necessary, then test whether it is within 16 or 32 bits 133577303Sobrien displacement from GP. */ 133677303Sobrien insn_disp = insn & 0x0000ffff; 1337104841Sobrien if (insn_disp & 0x8000) 1338104841Sobrien insn_disp |= ~0xffff; /* Negative: sign-extend. */ 133977303Sobrien 134077303Sobrien xdisp = disp + insn_disp; 1341104841Sobrien fits16 = (xdisp >= - (bfd_signed_vma) 0x8000 && xdisp < 0x8000); 1342104841Sobrien fits32 = (xdisp >= - (bfd_signed_vma) 0x80000000 1343104841Sobrien && xdisp < 0x7fff8000); 134477303Sobrien 134560510Sobrien if (fits16) 134660510Sobrien { 134777303Sobrien /* Take the op code and dest from this insn, take the base 134860510Sobrien register from the literal insn. Leave the offset alone. */ 134977303Sobrien insn = (insn & 0xffe0ffff) | (lit_insn & 0x001f0000); 135060510Sobrien urel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), 135189862Sobrien R_ALPHA_GPREL16); 135260510Sobrien urel->r_addend = irel->r_addend; 135360510Sobrien info->changed_relocs = true; 135460510Sobrien 135589862Sobrien bfd_put_32 (info->abfd, (bfd_vma) insn, 135689862Sobrien info->contents + urel->r_offset); 135760510Sobrien info->changed_contents = true; 135860510Sobrien } 135960510Sobrien 136060510Sobrien /* If all mem+byte, we can optimize 32-bit mem displacements. */ 136160510Sobrien else if (fits32 && !(flags & ~6)) 136260510Sobrien { 136377303Sobrien /* FIXME: sanity check that lit insn Ra is mem insn Rb. */ 136460510Sobrien 136560510Sobrien irel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), 136660510Sobrien R_ALPHA_GPRELHIGH); 136760510Sobrien lit_insn = (OP_LDAH << 26) | (lit_insn & 0x03ff0000); 136889862Sobrien bfd_put_32 (info->abfd, (bfd_vma) lit_insn, 136960510Sobrien info->contents + irel->r_offset); 137060510Sobrien lit_reused = true; 137160510Sobrien info->changed_contents = true; 137260510Sobrien 137360510Sobrien urel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), 137460510Sobrien R_ALPHA_GPRELLOW); 137560510Sobrien urel->r_addend = irel->r_addend; 137660510Sobrien info->changed_relocs = true; 137760510Sobrien } 137860510Sobrien else 137960510Sobrien all_optimized = false; 138060510Sobrien break; 138160510Sobrien 1382104841Sobrien case LITUSE_ALPHA_BYTOFF: 138360510Sobrien /* We can always optimize byte instructions. */ 138460510Sobrien 138560510Sobrien /* FIXME: sanity check the insn for byte op. Check that the 138660510Sobrien literal dest reg is indeed Rb in the byte insn. */ 138760510Sobrien 138889862Sobrien insn &= ~ (unsigned) 0x001ff000; 138989862Sobrien insn |= ((symval & 7) << 13) | 0x1000; 139060510Sobrien 139160510Sobrien urel->r_info = ELF64_R_INFO (0, R_ALPHA_NONE); 139260510Sobrien urel->r_addend = 0; 139360510Sobrien info->changed_relocs = true; 139460510Sobrien 139589862Sobrien bfd_put_32 (info->abfd, (bfd_vma) insn, 139689862Sobrien info->contents + urel->r_offset); 139760510Sobrien info->changed_contents = true; 139860510Sobrien break; 139960510Sobrien 1400104841Sobrien case LITUSE_ALPHA_JSR: 1401104841Sobrien case LITUSE_ALPHA_TLSGD: 1402104841Sobrien case LITUSE_ALPHA_TLSLDM: 140360510Sobrien { 1404104841Sobrien bfd_vma optdest, org; 140560510Sobrien bfd_signed_vma odisp; 140660510Sobrien 1407104841Sobrien /* If not zero, place to jump without needing pv. */ 1408104841Sobrien optdest = elf64_alpha_relax_opt_call (info, symval); 1409104841Sobrien org = (info->sec->output_section->vma 1410104841Sobrien + info->sec->output_offset 1411104841Sobrien + urel->r_offset + 4); 141260510Sobrien odisp = (optdest ? optdest : symval) - org; 1413104841Sobrien 141460510Sobrien if (odisp >= -0x400000 && odisp < 0x400000) 141560510Sobrien { 141660510Sobrien Elf_Internal_Rela *xrel; 141760510Sobrien 141877303Sobrien /* Preserve branch prediction call stack when possible. */ 141960510Sobrien if ((insn & INSN_JSR_MASK) == INSN_JSR) 142060510Sobrien insn = (OP_BSR << 26) | (insn & 0x03e00000); 142160510Sobrien else 142260510Sobrien insn = (OP_BR << 26) | (insn & 0x03e00000); 142377303Sobrien 142460510Sobrien urel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), 142560510Sobrien R_ALPHA_BRADDR); 142660510Sobrien urel->r_addend = irel->r_addend; 142760510Sobrien 142860510Sobrien if (optdest) 142960510Sobrien urel->r_addend += optdest - symval; 143060510Sobrien else 143160510Sobrien all_optimized = false; 143260510Sobrien 143389862Sobrien bfd_put_32 (info->abfd, (bfd_vma) insn, 143489862Sobrien info->contents + urel->r_offset); 143560510Sobrien 143660510Sobrien /* Kill any HINT reloc that might exist for this insn. */ 143760510Sobrien xrel = (elf64_alpha_find_reloc_at_ofs 143877303Sobrien (info->relocs, info->relend, urel->r_offset, 143960510Sobrien R_ALPHA_HINT)); 144060510Sobrien if (xrel) 144160510Sobrien xrel->r_info = ELF64_R_INFO (0, R_ALPHA_NONE); 144260510Sobrien 144360510Sobrien info->changed_contents = true; 144460510Sobrien info->changed_relocs = true; 144560510Sobrien } 144660510Sobrien else 144760510Sobrien all_optimized = false; 144860510Sobrien 144989862Sobrien /* Even if the target is not in range for a direct branch, 145089862Sobrien if we share a GP, we can eliminate the gp reload. */ 145189862Sobrien if (optdest) 145289862Sobrien { 145389862Sobrien Elf_Internal_Rela *gpdisp 145489862Sobrien = (elf64_alpha_find_reloc_at_ofs 1455104841Sobrien (info->relocs, irelend, urel->r_offset + 4, 1456104841Sobrien R_ALPHA_GPDISP)); 145789862Sobrien if (gpdisp) 145889862Sobrien { 1459104841Sobrien bfd_byte *p_ldah = info->contents + gpdisp->r_offset; 146089862Sobrien bfd_byte *p_lda = p_ldah + gpdisp->r_addend; 146189862Sobrien unsigned int ldah = bfd_get_32 (info->abfd, p_ldah); 146289862Sobrien unsigned int lda = bfd_get_32 (info->abfd, p_lda); 146360510Sobrien 146489862Sobrien /* Verify that the instruction is "ldah $29,0($26)". 146589862Sobrien Consider a function that ends in a noreturn call, 146689862Sobrien and that the next function begins with an ldgp, 146789862Sobrien and that by accident there is no padding between. 146889862Sobrien In that case the insn would use $27 as the base. */ 146989862Sobrien if (ldah == 0x27ba0000 && lda == 0x23bd0000) 147089862Sobrien { 147189862Sobrien bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP, p_ldah); 147289862Sobrien bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP, p_lda); 147389862Sobrien 147489862Sobrien gpdisp->r_info = ELF64_R_INFO (0, R_ALPHA_NONE); 147589862Sobrien info->changed_contents = true; 147689862Sobrien info->changed_relocs = true; 147789862Sobrien } 147889862Sobrien } 147989862Sobrien } 148060510Sobrien } 148160510Sobrien break; 148260510Sobrien } 148360510Sobrien } 148460510Sobrien 148560510Sobrien /* If all cases were optimized, we can reduce the use count on this 148660510Sobrien got entry by one, possibly eliminating it. */ 148760510Sobrien if (all_optimized) 148860510Sobrien { 1489104841Sobrien if (--info->gotent->use_count == 0) 1490104841Sobrien { 1491104841Sobrien int sz = alpha_got_entry_size (R_ALPHA_LITERAL); 1492104841Sobrien alpha_elf_tdata (info->gotobj)->total_got_size -= sz; 1493104841Sobrien if (!info->h) 1494104841Sobrien alpha_elf_tdata (info->gotobj)->local_got_size -= sz; 1495104841Sobrien } 149660510Sobrien 149760510Sobrien /* If the literal instruction is no longer needed (it may have been 1498104841Sobrien reused. We can eliminate it. */ 1499104841Sobrien /* ??? For now, I don't want to deal with compacting the section, 150060510Sobrien so just nop it out. */ 150160510Sobrien if (!lit_reused) 150260510Sobrien { 150360510Sobrien irel->r_info = ELF64_R_INFO (0, R_ALPHA_NONE); 150460510Sobrien info->changed_relocs = true; 150560510Sobrien 150689862Sobrien bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP, 150789862Sobrien info->contents + irel->r_offset); 150860510Sobrien info->changed_contents = true; 150960510Sobrien } 151060510Sobrien } 151160510Sobrien 1512104841Sobrien return true; 151360510Sobrien} 151460510Sobrien 151560510Sobrienstatic bfd_vma 151660510Sobrienelf64_alpha_relax_opt_call (info, symval) 151760510Sobrien struct alpha_relax_info *info; 151860510Sobrien bfd_vma symval; 151960510Sobrien{ 152060510Sobrien /* If the function has the same gp, and we can identify that the 152160510Sobrien function does not use its function pointer, we can eliminate the 152260510Sobrien address load. */ 152360510Sobrien 152460510Sobrien /* If the symbol is marked NOPV, we are being told the function never 152560510Sobrien needs its procedure value. */ 152677303Sobrien if ((info->other & STO_ALPHA_STD_GPLOAD) == STO_ALPHA_NOPV) 152760510Sobrien return symval; 152860510Sobrien 152960510Sobrien /* If the symbol is marked STD_GP, we are being told the function does 153077303Sobrien a normal ldgp in the first two words. */ 153177303Sobrien else if ((info->other & STO_ALPHA_STD_GPLOAD) == STO_ALPHA_STD_GPLOAD) 153260510Sobrien ; 153360510Sobrien 153460510Sobrien /* Otherwise, we may be able to identify a GP load in the first two 153560510Sobrien words, which we can then skip. */ 153677303Sobrien else 153760510Sobrien { 153860510Sobrien Elf_Internal_Rela *tsec_relocs, *tsec_relend, *tsec_free, *gpdisp; 153960510Sobrien bfd_vma ofs; 154060510Sobrien 154177303Sobrien /* Load the relocations from the section that the target symbol is in. */ 154260510Sobrien if (info->sec == info->tsec) 154360510Sobrien { 154460510Sobrien tsec_relocs = info->relocs; 154560510Sobrien tsec_relend = info->relend; 154660510Sobrien tsec_free = NULL; 154760510Sobrien } 154860510Sobrien else 154960510Sobrien { 155060510Sobrien tsec_relocs = (_bfd_elf64_link_read_relocs 155160510Sobrien (info->abfd, info->tsec, (PTR) NULL, 155260510Sobrien (Elf_Internal_Rela *) NULL, 155360510Sobrien info->link_info->keep_memory)); 155460510Sobrien if (tsec_relocs == NULL) 155560510Sobrien return 0; 155660510Sobrien tsec_relend = tsec_relocs + info->tsec->reloc_count; 155760510Sobrien tsec_free = (info->link_info->keep_memory ? NULL : tsec_relocs); 155860510Sobrien } 155960510Sobrien 156060510Sobrien /* Recover the symbol's offset within the section. */ 156160510Sobrien ofs = (symval - info->tsec->output_section->vma 156260510Sobrien - info->tsec->output_offset); 156377303Sobrien 156460510Sobrien /* Look for a GPDISP reloc. */ 156560510Sobrien gpdisp = (elf64_alpha_find_reloc_at_ofs 156660510Sobrien (tsec_relocs, tsec_relend, ofs, R_ALPHA_GPDISP)); 156760510Sobrien 156860510Sobrien if (!gpdisp || gpdisp->r_addend != 4) 156960510Sobrien { 157060510Sobrien if (tsec_free) 157160510Sobrien free (tsec_free); 157260510Sobrien return 0; 157360510Sobrien } 157460510Sobrien if (tsec_free) 157560510Sobrien free (tsec_free); 157660510Sobrien } 157760510Sobrien 157877303Sobrien /* We've now determined that we can skip an initial gp load. Verify 157960510Sobrien that the call and the target use the same gp. */ 158060510Sobrien if (info->link_info->hash->creator != info->tsec->owner->xvec 158160510Sobrien || info->gotobj != alpha_elf_tdata (info->tsec->owner)->gotobj) 158260510Sobrien return 0; 158360510Sobrien 158460510Sobrien return symval + 8; 158560510Sobrien} 158660510Sobrien 158760510Sobrienstatic boolean 1588104841Sobrienelf64_alpha_relax_got_load (info, symval, irel, r_type) 158960510Sobrien struct alpha_relax_info *info; 159060510Sobrien bfd_vma symval; 159160510Sobrien Elf_Internal_Rela *irel; 1592104841Sobrien unsigned long r_type; 159360510Sobrien{ 159460510Sobrien unsigned int insn; 159560510Sobrien bfd_signed_vma disp; 159660510Sobrien 159760510Sobrien /* Get the instruction. */ 159860510Sobrien insn = bfd_get_32 (info->abfd, info->contents + irel->r_offset); 159960510Sobrien 160060510Sobrien if (insn >> 26 != OP_LDQ) 160160510Sobrien { 1602104841Sobrien reloc_howto_type *howto = elf64_alpha_howto_table + r_type; 160360510Sobrien ((*_bfd_error_handler) 1604104841Sobrien ("%s: %s+0x%lx: warning: %s relocation against unexpected insn", 160589862Sobrien bfd_archive_filename (info->abfd), info->sec->name, 1606104841Sobrien (unsigned long) irel->r_offset, howto->name)); 160760510Sobrien return true; 160860510Sobrien } 160960510Sobrien 1610104841Sobrien /* Can't relax dynamic symbols. */ 1611104841Sobrien if (alpha_elf_dynamic_symbol_p (&info->h->root, info->link_info)) 1612104841Sobrien return true; 161360510Sobrien 1614104841Sobrien /* Can't use local-exec relocations in shared libraries. */ 1615104841Sobrien if (r_type == R_ALPHA_GOTTPREL && info->link_info->shared) 1616104841Sobrien return true; 1617104841Sobrien 1618104841Sobrien if (r_type == R_ALPHA_LITERAL) 1619104841Sobrien disp = symval - info->gp; 1620104841Sobrien else 1621104841Sobrien { 1622104841Sobrien bfd_vma dtp_base, tp_base; 1623104841Sobrien 1624104841Sobrien BFD_ASSERT (info->tls_segment != NULL); 1625104841Sobrien dtp_base = alpha_get_dtprel_base (info->tls_segment); 1626104841Sobrien tp_base = alpha_get_tprel_base (info->tls_segment); 1627104841Sobrien disp = symval - (r_type == R_ALPHA_GOTDTPREL ? dtp_base : tp_base); 1628104841Sobrien } 1629104841Sobrien 163060510Sobrien if (disp < -0x8000 || disp >= 0x8000) 163160510Sobrien return true; 163260510Sobrien 1633104841Sobrien /* Exchange LDQ for LDA. In the case of the TLS relocs, we're loading 1634104841Sobrien a constant, so force the base register to be $31. */ 1635104841Sobrien if (r_type == R_ALPHA_LITERAL) 1636104841Sobrien insn = (OP_LDA << 26) | (insn & 0x03ff0000); 1637104841Sobrien else 1638104841Sobrien insn = (OP_LDA << 26) | (insn & (31 << 21)) | (31 << 16); 163989862Sobrien bfd_put_32 (info->abfd, (bfd_vma) insn, info->contents + irel->r_offset); 164060510Sobrien info->changed_contents = true; 164160510Sobrien 1642104841Sobrien switch (r_type) 1643104841Sobrien { 1644104841Sobrien case R_ALPHA_LITERAL: 1645104841Sobrien r_type = R_ALPHA_GPREL16; 1646104841Sobrien break; 1647104841Sobrien case R_ALPHA_GOTDTPREL: 1648104841Sobrien r_type = R_ALPHA_DTPREL16; 1649104841Sobrien break; 1650104841Sobrien case R_ALPHA_GOTTPREL: 1651104841Sobrien r_type = R_ALPHA_TPREL16; 1652104841Sobrien break; 1653104841Sobrien default: 1654104841Sobrien BFD_ASSERT (0); 1655104841Sobrien return false; 1656104841Sobrien } 1657104841Sobrien 1658104841Sobrien irel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), r_type); 165960510Sobrien info->changed_relocs = true; 166060510Sobrien 166160510Sobrien /* Reduce the use count on this got entry by one, possibly 166260510Sobrien eliminating it. */ 1663104841Sobrien if (--info->gotent->use_count == 0) 1664104841Sobrien { 1665104841Sobrien int sz = alpha_got_entry_size (r_type); 1666104841Sobrien alpha_elf_tdata (info->gotobj)->total_got_size -= sz; 1667104841Sobrien if (!info->h) 1668104841Sobrien alpha_elf_tdata (info->gotobj)->local_got_size -= sz; 1669104841Sobrien } 167060510Sobrien 167160510Sobrien /* ??? Search forward through this basic block looking for insns 167260510Sobrien that use the target register. Stop after an insn modifying the 167360510Sobrien register is seen, or after a branch or call. 167460510Sobrien 167560510Sobrien Any such memory load insn may be substituted by a load directly 167660510Sobrien off the GP. This allows the memory load insn to be issued before 167777303Sobrien the calculated GP register would otherwise be ready. 167860510Sobrien 167960510Sobrien Any such jsr insn can be replaced by a bsr if it is in range. 168060510Sobrien 168160510Sobrien This would mean that we'd have to _add_ relocations, the pain of 168260510Sobrien which gives one pause. */ 168360510Sobrien 168460510Sobrien return true; 168560510Sobrien} 168660510Sobrien 168760510Sobrienstatic boolean 1688104841Sobrienelf64_alpha_relax_gprelhilo (info, symval, irel, hi) 1689104841Sobrien struct alpha_relax_info *info; 1690104841Sobrien bfd_vma symval; 1691104841Sobrien Elf_Internal_Rela *irel; 1692104841Sobrien boolean hi; 1693104841Sobrien{ 1694104841Sobrien unsigned int insn; 1695104841Sobrien bfd_signed_vma disp; 1696104841Sobrien bfd_byte *pos = info->contents + irel->r_offset; 1697104841Sobrien 1698104841Sobrien /* ??? This assumes that the compiler doesn't render 1699104841Sobrien 1700104841Sobrien array[i] 1701104841Sobrien as 1702104841Sobrien ldah t, array(gp) !gprelhigh 1703104841Sobrien s8addl i, t, t 1704104841Sobrien ldq r, array(t) !gprellow 1705104841Sobrien 1706104841Sobrien which would indeed be the most efficient way to implement this. */ 1707104841Sobrien 1708104841Sobrien return true; 1709104841Sobrien 1710104841Sobrien disp = symval - info->gp; 1711104841Sobrien if (disp < -0x8000 || disp >= 0x8000) 1712104841Sobrien return true; 1713104841Sobrien 1714104841Sobrien if (hi) 1715104841Sobrien { 1716104841Sobrien /* Nop out the high instruction. */ 1717104841Sobrien 1718104841Sobrien bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP, pos); 1719104841Sobrien info->changed_contents = true; 1720104841Sobrien 1721104841Sobrien irel->r_info = ELF64_R_INFO (0, R_ALPHA_NONE); 1722104841Sobrien irel->r_addend = 0; 1723104841Sobrien info->changed_relocs = true; 1724104841Sobrien } 1725104841Sobrien else 1726104841Sobrien { 1727104841Sobrien /* Adjust the low instruction to reference GP directly. */ 1728104841Sobrien 1729104841Sobrien insn = bfd_get_32 (info->abfd, pos); 1730104841Sobrien insn = (insn & 0xffe00000) | (29 << 16); 1731104841Sobrien bfd_put_32 (info->abfd, (bfd_vma) insn, pos); 1732104841Sobrien info->changed_contents = true; 1733104841Sobrien 1734104841Sobrien irel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), 1735104841Sobrien R_ALPHA_GPREL16); 1736104841Sobrien info->changed_relocs = true; 1737104841Sobrien } 1738104841Sobrien 1739104841Sobrien return true; 1740104841Sobrien} 1741104841Sobrien 1742104841Sobrienstatic boolean 1743104841Sobrienelf64_alpha_relax_tls_get_addr (info, symval, irel, is_gd) 1744104841Sobrien struct alpha_relax_info *info; 1745104841Sobrien bfd_vma symval; 1746104841Sobrien Elf_Internal_Rela *irel; 1747104841Sobrien boolean is_gd; 1748104841Sobrien{ 1749104841Sobrien bfd_byte *pos[5]; 1750104841Sobrien unsigned int insn; 1751104841Sobrien Elf_Internal_Rela *gpdisp, *hint; 1752104841Sobrien boolean dynamic, use_gottprel; 1753104841Sobrien 1754104841Sobrien dynamic = alpha_elf_dynamic_symbol_p (&info->h->root, info->link_info); 1755104841Sobrien 1756104841Sobrien /* ??? For LD relaxation, we need a symbol referencing the beginning 1757104841Sobrien of the TLS segment. */ 1758104841Sobrien if (!is_gd) 1759104841Sobrien return true; 1760104841Sobrien 1761104841Sobrien /* If a TLS symbol is accessed using IE at least once, there is no point 1762104841Sobrien to use dynamic model for it. */ 1763104841Sobrien if (is_gd && info->h && (info->h->flags & ALPHA_ELF_LINK_HASH_TLS_IE)) 1764104841Sobrien ; 1765104841Sobrien 1766104841Sobrien /* If the symbol is local, and we've already committed to DF_STATIC_TLS, 1767104841Sobrien then we might as well relax to IE. */ 1768104841Sobrien else if (info->link_info->shared && !dynamic 1769104841Sobrien && (info->link_info->flags & DF_STATIC_TLS)) 1770104841Sobrien ; 1771104841Sobrien 1772104841Sobrien /* Otherwise we must be building an executable to do anything. */ 1773104841Sobrien else if (info->link_info->shared) 1774104841Sobrien return true; 1775104841Sobrien 1776104841Sobrien /* The TLSGD/TLSLDM relocation must be followed by a LITERAL and 1777104841Sobrien the matching LITUSE_TLS relocations. */ 1778104841Sobrien if (irel + 2 >= info->relend) 1779104841Sobrien return true; 1780104841Sobrien if (ELF64_R_TYPE (irel[1].r_info) != R_ALPHA_LITERAL 1781104841Sobrien || ELF64_R_TYPE (irel[2].r_info) != R_ALPHA_LITUSE 1782104841Sobrien || irel[2].r_addend != (is_gd ? LITUSE_ALPHA_TLSGD : LITUSE_ALPHA_TLSLDM)) 1783104841Sobrien return true; 1784104841Sobrien 1785104841Sobrien /* There must be a GPDISP relocation positioned immediately after the 1786104841Sobrien LITUSE relocation. */ 1787104841Sobrien gpdisp = elf64_alpha_find_reloc_at_ofs (info->relocs, info->relend, 1788104841Sobrien irel[2].r_offset + 4, R_ALPHA_GPDISP); 1789104841Sobrien if (!gpdisp) 1790104841Sobrien return true; 1791104841Sobrien 1792104841Sobrien pos[0] = info->contents + irel[0].r_offset; 1793104841Sobrien pos[1] = info->contents + irel[1].r_offset; 1794104841Sobrien pos[2] = info->contents + irel[2].r_offset; 1795104841Sobrien pos[3] = info->contents + gpdisp->r_offset; 1796104841Sobrien pos[4] = pos[3] + gpdisp->r_addend; 1797104841Sobrien 1798104841Sobrien /* Only positions 0 and 1 are allowed to be out of order. */ 1799104841Sobrien if (pos[1] < pos[0]) 1800104841Sobrien { 1801104841Sobrien bfd_byte *tmp = pos[0]; 1802104841Sobrien pos[0] = pos[1]; 1803104841Sobrien pos[1] = tmp; 1804104841Sobrien } 1805104841Sobrien if (pos[1] >= pos[2] || pos[2] >= pos[3] || pos[3] >= pos[4]) 1806104841Sobrien return true; 1807104841Sobrien 1808104841Sobrien /* Reduce the use count on the LITERAL relocation. Do this before we 1809104841Sobrien smash the symndx when we adjust the relocations below. */ 1810104841Sobrien { 1811104841Sobrien struct alpha_elf_got_entry *lit_gotent; 1812104841Sobrien struct alpha_elf_link_hash_entry *lit_h; 1813104841Sobrien unsigned long indx; 1814104841Sobrien 1815104841Sobrien BFD_ASSERT (ELF64_R_SYM (irel[1].r_info) >= info->symtab_hdr->sh_info); 1816104841Sobrien indx = ELF64_R_SYM (irel[1].r_info) - info->symtab_hdr->sh_info; 1817104841Sobrien lit_h = alpha_elf_sym_hashes (info->abfd)[indx]; 1818104841Sobrien 1819104841Sobrien while (lit_h->root.root.type == bfd_link_hash_indirect 1820104841Sobrien || lit_h->root.root.type == bfd_link_hash_warning) 1821104841Sobrien lit_h = (struct alpha_elf_link_hash_entry *) lit_h->root.root.u.i.link; 1822104841Sobrien 1823104841Sobrien for (lit_gotent = lit_h->got_entries; lit_gotent ; 1824104841Sobrien lit_gotent = lit_gotent->next) 1825104841Sobrien if (lit_gotent->gotobj == info->gotobj 1826104841Sobrien && lit_gotent->reloc_type == R_ALPHA_LITERAL 1827104841Sobrien && lit_gotent->addend == irel[1].r_addend) 1828104841Sobrien break; 1829104841Sobrien BFD_ASSERT (lit_gotent); 1830104841Sobrien 1831104841Sobrien if (--lit_gotent->use_count == 0) 1832104841Sobrien { 1833104841Sobrien int sz = alpha_got_entry_size (R_ALPHA_LITERAL); 1834104841Sobrien alpha_elf_tdata (info->gotobj)->total_got_size -= sz; 1835104841Sobrien } 1836104841Sobrien } 1837104841Sobrien 1838104841Sobrien /* Change 1839104841Sobrien 1840104841Sobrien lda $16,x($gp) !tlsgd!1 1841104841Sobrien ldq $27,__tls_get_addr($gp) !literal!1 1842104841Sobrien jsr $26,($27)__tls_get_addr !lituse_tlsgd!1 1843104841Sobrien ldah $29,0($26) !gpdisp!2 1844104841Sobrien lda $29,0($29) !gpdisp!2 1845104841Sobrien to 1846104841Sobrien ldq $16,x($gp) !gottprel 1847104841Sobrien unop 1848104841Sobrien call_pal rduniq 1849104841Sobrien addq $16,$0,$0 1850104841Sobrien unop 1851104841Sobrien or the first pair to 1852104841Sobrien lda $16,x($gp) !tprel 1853104841Sobrien unop 1854104841Sobrien or 1855104841Sobrien ldah $16,x($gp) !tprelhi 1856104841Sobrien lda $16,x($16) !tprello 1857104841Sobrien 1858104841Sobrien as appropriate. */ 1859104841Sobrien 1860104841Sobrien use_gottprel = false; 1861104841Sobrien switch (!dynamic && !info->link_info->shared) 1862104841Sobrien { 1863104841Sobrien case 1: 1864104841Sobrien { 1865104841Sobrien bfd_vma tp_base; 1866104841Sobrien bfd_signed_vma disp; 1867104841Sobrien 1868104841Sobrien BFD_ASSERT (info->tls_segment != NULL); 1869104841Sobrien tp_base = alpha_get_tprel_base (info->tls_segment); 1870104841Sobrien disp = symval - tp_base; 1871104841Sobrien 1872104841Sobrien if (disp >= -0x8000 && disp < 0x8000) 1873104841Sobrien { 1874104841Sobrien insn = (OP_LDA << 26) | (16 << 21) | (31 << 16); 1875104841Sobrien bfd_put_32 (info->abfd, (bfd_vma) insn, pos[0]); 1876104841Sobrien bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP, pos[1]); 1877104841Sobrien 1878104841Sobrien irel[0].r_offset = pos[0] - info->contents; 1879104841Sobrien irel[0].r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), 1880104841Sobrien R_ALPHA_TPREL16); 1881104841Sobrien irel[1].r_info = ELF64_R_INFO (0, R_ALPHA_NONE); 1882104841Sobrien break; 1883104841Sobrien } 1884104841Sobrien else if (disp >= -(bfd_signed_vma) 0x80000000 1885104841Sobrien && disp < (bfd_signed_vma) 0x7fff8000) 1886104841Sobrien { 1887104841Sobrien insn = (OP_LDAH << 26) | (16 << 21) | (31 << 16); 1888104841Sobrien bfd_put_32 (info->abfd, (bfd_vma) insn, pos[0]); 1889104841Sobrien insn = (OP_LDA << 26) | (16 << 21) | (16 << 16); 1890104841Sobrien bfd_put_32 (info->abfd, (bfd_vma) insn, pos[1]); 1891104841Sobrien 1892104841Sobrien irel[0].r_offset = pos[0] - info->contents; 1893104841Sobrien irel[0].r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), 1894104841Sobrien R_ALPHA_TPRELHI); 1895104841Sobrien irel[1].r_offset = pos[1] - info->contents; 1896104841Sobrien irel[1].r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), 1897104841Sobrien R_ALPHA_TPRELLO); 1898104841Sobrien break; 1899104841Sobrien } 1900104841Sobrien } 1901104841Sobrien /* FALLTHRU */ 1902104841Sobrien 1903104841Sobrien default: 1904104841Sobrien use_gottprel = true; 1905104841Sobrien 1906104841Sobrien insn = (OP_LDQ << 26) | (16 << 21) | (29 << 16); 1907104841Sobrien bfd_put_32 (info->abfd, (bfd_vma) insn, pos[0]); 1908104841Sobrien bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP, pos[1]); 1909104841Sobrien 1910104841Sobrien irel[0].r_offset = pos[0] - info->contents; 1911104841Sobrien irel[0].r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), 1912104841Sobrien R_ALPHA_GOTTPREL); 1913104841Sobrien irel[1].r_info = ELF64_R_INFO (0, R_ALPHA_NONE); 1914104841Sobrien break; 1915104841Sobrien } 1916104841Sobrien 1917104841Sobrien bfd_put_32 (info->abfd, (bfd_vma) INSN_RDUNIQ, pos[2]); 1918104841Sobrien 1919104841Sobrien insn = INSN_ADDQ | (16 << 21) | (0 << 16) | (0 << 0); 1920104841Sobrien bfd_put_32 (info->abfd, (bfd_vma) insn, pos[3]); 1921104841Sobrien 1922104841Sobrien bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP, pos[4]); 1923104841Sobrien 1924104841Sobrien irel[2].r_info = ELF64_R_INFO (0, R_ALPHA_NONE); 1925104841Sobrien gpdisp->r_info = ELF64_R_INFO (0, R_ALPHA_NONE); 1926104841Sobrien 1927104841Sobrien hint = elf64_alpha_find_reloc_at_ofs (info->relocs, info->relend, 1928104841Sobrien irel[2].r_offset, R_ALPHA_HINT); 1929104841Sobrien if (hint) 1930104841Sobrien hint->r_info = ELF64_R_INFO (0, R_ALPHA_NONE); 1931104841Sobrien 1932104841Sobrien info->changed_contents = true; 1933104841Sobrien info->changed_relocs = true; 1934104841Sobrien 1935104841Sobrien /* Reduce the use count on the TLSGD/TLSLDM relocation. */ 1936104841Sobrien if (--info->gotent->use_count == 0) 1937104841Sobrien { 1938104841Sobrien int sz = alpha_got_entry_size (info->gotent->reloc_type); 1939104841Sobrien alpha_elf_tdata (info->gotobj)->total_got_size -= sz; 1940104841Sobrien if (!info->h) 1941104841Sobrien alpha_elf_tdata (info->gotobj)->local_got_size -= sz; 1942104841Sobrien } 1943104841Sobrien 1944104841Sobrien /* If we've switched to a GOTTPREL relocation, increment the reference 1945104841Sobrien count on that got entry. */ 1946104841Sobrien if (use_gottprel) 1947104841Sobrien { 1948104841Sobrien struct alpha_elf_got_entry *tprel_gotent; 1949104841Sobrien 1950104841Sobrien for (tprel_gotent = *info->first_gotent; tprel_gotent ; 1951104841Sobrien tprel_gotent = tprel_gotent->next) 1952104841Sobrien if (tprel_gotent->gotobj == info->gotobj 1953104841Sobrien && tprel_gotent->reloc_type == R_ALPHA_GOTTPREL 1954104841Sobrien && tprel_gotent->addend == irel->r_addend) 1955104841Sobrien break; 1956104841Sobrien if (tprel_gotent) 1957104841Sobrien tprel_gotent->use_count++; 1958104841Sobrien else 1959104841Sobrien { 1960104841Sobrien if (info->gotent->use_count == 0) 1961104841Sobrien tprel_gotent = info->gotent; 1962104841Sobrien else 1963104841Sobrien { 1964104841Sobrien tprel_gotent = (struct alpha_elf_got_entry *) 1965104841Sobrien bfd_alloc (info->abfd, sizeof (struct alpha_elf_got_entry)); 1966104841Sobrien if (!tprel_gotent) 1967104841Sobrien return false; 1968104841Sobrien 1969104841Sobrien tprel_gotent->next = *info->first_gotent; 1970104841Sobrien *info->first_gotent = tprel_gotent; 1971104841Sobrien 1972104841Sobrien tprel_gotent->gotobj = info->gotobj; 1973104841Sobrien tprel_gotent->addend = irel->r_addend; 1974104841Sobrien tprel_gotent->got_offset = -1; 1975104841Sobrien tprel_gotent->reloc_done = 0; 1976104841Sobrien tprel_gotent->reloc_xlated = 0; 1977104841Sobrien } 1978104841Sobrien 1979104841Sobrien tprel_gotent->use_count = 1; 1980104841Sobrien tprel_gotent->reloc_type = R_ALPHA_GOTTPREL; 1981104841Sobrien } 1982104841Sobrien } 1983104841Sobrien 1984104841Sobrien return true; 1985104841Sobrien} 1986104841Sobrien 1987104841Sobrienstatic struct elf_link_tls_segment * 1988104841Sobrienelf64_alpha_relax_find_tls_segment (info, seg) 1989104841Sobrien struct alpha_relax_info *info; 1990104841Sobrien struct elf_link_tls_segment *seg; 1991104841Sobrien{ 1992104841Sobrien bfd *output_bfd = info->sec->output_section->owner; 1993104841Sobrien asection *o; 1994104841Sobrien unsigned int align; 1995104841Sobrien bfd_vma base, end; 1996104841Sobrien 1997104841Sobrien for (o = output_bfd->sections; o ; o = o->next) 1998104841Sobrien if ((o->flags & SEC_THREAD_LOCAL) != 0 1999104841Sobrien && (o->flags & SEC_LOAD) != 0) 2000104841Sobrien break; 2001104841Sobrien if (!o) 2002104841Sobrien return NULL; 2003104841Sobrien 2004104841Sobrien base = o->vma; 2005104841Sobrien align = 0; 2006104841Sobrien 2007104841Sobrien do 2008104841Sobrien { 2009104841Sobrien bfd_vma size; 2010104841Sobrien 2011104841Sobrien if (bfd_get_section_alignment (output_bfd, o) > align) 2012104841Sobrien align = bfd_get_section_alignment (output_bfd, o); 2013104841Sobrien 2014104841Sobrien size = o->_raw_size; 2015104841Sobrien if (size == 0 && (o->flags & SEC_HAS_CONTENTS) == 0) 2016104841Sobrien { 2017104841Sobrien struct bfd_link_order *lo; 2018104841Sobrien for (lo = o->link_order_head; lo ; lo = lo->next) 2019104841Sobrien if (size < lo->offset + lo->size) 2020104841Sobrien size = lo->offset + lo->size; 2021104841Sobrien } 2022104841Sobrien end = o->vma + size; 2023104841Sobrien o = o->next; 2024104841Sobrien } 2025104841Sobrien while (o && (o->flags & SEC_THREAD_LOCAL)); 2026104841Sobrien 2027104841Sobrien seg->start = base; 2028104841Sobrien seg->size = end - base; 2029104841Sobrien seg->align = align; 2030104841Sobrien 2031104841Sobrien return seg; 2032104841Sobrien} 2033104841Sobrien 2034104841Sobrienstatic boolean 203560510Sobrienelf64_alpha_relax_section (abfd, sec, link_info, again) 203660510Sobrien bfd *abfd; 203760510Sobrien asection *sec; 203860510Sobrien struct bfd_link_info *link_info; 203960510Sobrien boolean *again; 204060510Sobrien{ 204160510Sobrien Elf_Internal_Shdr *symtab_hdr; 204260510Sobrien Elf_Internal_Rela *internal_relocs; 204360510Sobrien Elf_Internal_Rela *irel, *irelend; 2044104841Sobrien Elf_Internal_Sym *isymbuf = NULL; 204560510Sobrien struct alpha_elf_got_entry **local_got_entries; 204660510Sobrien struct alpha_relax_info info; 2047104841Sobrien struct elf_link_tls_segment tls_segment; 204860510Sobrien 204960510Sobrien /* We are not currently changing any sizes, so only one pass. */ 205060510Sobrien *again = false; 205160510Sobrien 205260510Sobrien if (link_info->relocateable 205360510Sobrien || (sec->flags & SEC_RELOC) == 0 205460510Sobrien || sec->reloc_count == 0) 205560510Sobrien return true; 205660510Sobrien 205760510Sobrien /* If this is the first time we have been called for this section, 205860510Sobrien initialize the cooked size. */ 205960510Sobrien if (sec->_cooked_size == 0) 206060510Sobrien sec->_cooked_size = sec->_raw_size; 206160510Sobrien 206260510Sobrien symtab_hdr = &elf_tdata (abfd)->symtab_hdr; 206360510Sobrien local_got_entries = alpha_elf_tdata(abfd)->local_got_entries; 206460510Sobrien 206560510Sobrien /* Load the relocations for this section. */ 206660510Sobrien internal_relocs = (_bfd_elf64_link_read_relocs 206760510Sobrien (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL, 206860510Sobrien link_info->keep_memory)); 206960510Sobrien if (internal_relocs == NULL) 2070104841Sobrien return false; 207160510Sobrien 207277303Sobrien memset(&info, 0, sizeof (info)); 207360510Sobrien info.abfd = abfd; 207460510Sobrien info.sec = sec; 207560510Sobrien info.link_info = link_info; 2076104841Sobrien info.symtab_hdr = symtab_hdr; 207760510Sobrien info.relocs = internal_relocs; 207860510Sobrien info.relend = irelend = internal_relocs + sec->reloc_count; 207960510Sobrien 2080104841Sobrien /* Find the GP for this object. Do not store the result back via 2081104841Sobrien _bfd_set_gp_value, since this could change again before final. */ 208260510Sobrien info.gotobj = alpha_elf_tdata (abfd)->gotobj; 208360510Sobrien if (info.gotobj) 208460510Sobrien { 208560510Sobrien asection *sgot = alpha_elf_tdata (info.gotobj)->got; 2086104841Sobrien info.gp = (sgot->output_section->vma 2087104841Sobrien + sgot->output_offset 2088104841Sobrien + 0x8000); 208960510Sobrien } 209060510Sobrien 2091104841Sobrien /* Get the section contents. */ 2092104841Sobrien if (elf_section_data (sec)->this_hdr.contents != NULL) 2093104841Sobrien info.contents = elf_section_data (sec)->this_hdr.contents; 2094104841Sobrien else 2095104841Sobrien { 2096104841Sobrien info.contents = (bfd_byte *) bfd_malloc (sec->_raw_size); 2097104841Sobrien if (info.contents == NULL) 2098104841Sobrien goto error_return; 2099104841Sobrien 2100104841Sobrien if (! bfd_get_section_contents (abfd, sec, info.contents, 2101104841Sobrien (file_ptr) 0, sec->_raw_size)) 2102104841Sobrien goto error_return; 2103104841Sobrien } 2104104841Sobrien 2105104841Sobrien /* Compute the TLS segment information. The version normally found in 2106104841Sobrien elf_hash_table (link_info)->tls_segment isn't built until final_link. 2107104841Sobrien ??? Probably should look into extracting this into a common function. */ 2108104841Sobrien info.tls_segment = elf64_alpha_relax_find_tls_segment (&info, &tls_segment); 2109104841Sobrien 211060510Sobrien for (irel = internal_relocs; irel < irelend; irel++) 211160510Sobrien { 211260510Sobrien bfd_vma symval; 211360510Sobrien struct alpha_elf_got_entry *gotent; 2114104841Sobrien unsigned long r_type = ELF64_R_TYPE (irel->r_info); 211560510Sobrien 2116104841Sobrien /* Early exit for unhandled or unrelaxable relocations. */ 2117104841Sobrien switch (r_type) 211860510Sobrien { 2119104841Sobrien case R_ALPHA_LITERAL: 2120104841Sobrien case R_ALPHA_GPRELHIGH: 2121104841Sobrien case R_ALPHA_GPRELLOW: 2122104841Sobrien case R_ALPHA_GOTDTPREL: 2123104841Sobrien case R_ALPHA_GOTTPREL: 2124104841Sobrien case R_ALPHA_TLSGD: 2125104841Sobrien case R_ALPHA_TLSLDM: 2126104841Sobrien break; 2127104841Sobrien default: 2128104841Sobrien continue; 212960510Sobrien } 213060510Sobrien 2131104841Sobrien /* Get the value of the symbol referred to by the reloc. */ 2132104841Sobrien if (ELF64_R_SYM (irel->r_info) < symtab_hdr->sh_info) 213360510Sobrien { 2134104841Sobrien /* A local symbol. */ 2135104841Sobrien Elf_Internal_Sym *isym; 213689862Sobrien 2137104841Sobrien /* Read this BFD's local symbols. */ 2138104841Sobrien if (isymbuf == NULL) 213960510Sobrien { 2140104841Sobrien isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; 2141104841Sobrien if (isymbuf == NULL) 2142104841Sobrien isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr, 2143104841Sobrien symtab_hdr->sh_info, 0, 2144104841Sobrien NULL, NULL, NULL); 2145104841Sobrien if (isymbuf == NULL) 214660510Sobrien goto error_return; 214760510Sobrien } 214889862Sobrien 2149104841Sobrien isym = isymbuf + ELF64_R_SYM (irel->r_info); 2150104841Sobrien if (isym->st_shndx == SHN_UNDEF) 2151104841Sobrien continue; 2152104841Sobrien else if (isym->st_shndx == SHN_ABS) 215360510Sobrien info.tsec = bfd_abs_section_ptr; 2154104841Sobrien else if (isym->st_shndx == SHN_COMMON) 215560510Sobrien info.tsec = bfd_com_section_ptr; 215677303Sobrien else 2157104841Sobrien info.tsec = bfd_section_from_elf_index (abfd, isym->st_shndx); 215860510Sobrien 215960510Sobrien info.h = NULL; 2160104841Sobrien info.other = isym->st_other; 2161104841Sobrien info.first_gotent = &local_got_entries[ELF64_R_SYM(irel->r_info)]; 2162104841Sobrien symval = isym->st_value; 216360510Sobrien } 216460510Sobrien else 216560510Sobrien { 216660510Sobrien unsigned long indx; 216760510Sobrien struct alpha_elf_link_hash_entry *h; 216860510Sobrien 216960510Sobrien indx = ELF64_R_SYM (irel->r_info) - symtab_hdr->sh_info; 217060510Sobrien h = alpha_elf_sym_hashes (abfd)[indx]; 217160510Sobrien BFD_ASSERT (h != NULL); 217260510Sobrien 217360510Sobrien while (h->root.root.type == bfd_link_hash_indirect 217460510Sobrien || h->root.root.type == bfd_link_hash_warning) 217560510Sobrien h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link; 217660510Sobrien 2177104841Sobrien /* If the symbol is undefined, we can't do anything with it. */ 2178104841Sobrien if (h->root.root.type == bfd_link_hash_undefweak 2179104841Sobrien || h->root.root.type == bfd_link_hash_undefined) 218060510Sobrien continue; 218160510Sobrien 2182104841Sobrien /* If the symbol isn't defined in the current module, again 2183104841Sobrien we can't do anything. */ 2184104841Sobrien if (!(h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)) 2185104841Sobrien continue; 2186104841Sobrien 218760510Sobrien info.h = h; 218860510Sobrien info.tsec = h->root.root.u.def.section; 218960510Sobrien info.other = h->root.other; 2190104841Sobrien info.first_gotent = &h->got_entries; 219160510Sobrien symval = h->root.root.u.def.value; 219260510Sobrien } 219360510Sobrien 219460510Sobrien /* Search for the got entry to be used by this relocation. */ 2195104841Sobrien for (gotent = *info.first_gotent; gotent ; gotent = gotent->next) 2196104841Sobrien if (gotent->gotobj == info.gotobj 2197104841Sobrien && gotent->reloc_type == r_type 2198104841Sobrien && gotent->addend == irel->r_addend) 2199104841Sobrien break; 220060510Sobrien info.gotent = gotent; 220160510Sobrien 220260510Sobrien symval += info.tsec->output_section->vma + info.tsec->output_offset; 220360510Sobrien symval += irel->r_addend; 220460510Sobrien 2205104841Sobrien switch (r_type) 2206104841Sobrien { 2207104841Sobrien case R_ALPHA_LITERAL: 2208104841Sobrien BFD_ASSERT(info.gotent != NULL); 220960510Sobrien 2210104841Sobrien /* If there exist LITUSE relocations immediately following, this 2211104841Sobrien opens up all sorts of interesting optimizations, because we 2212104841Sobrien now know every location that this address load is used. */ 2213104841Sobrien if (irel+1 < irelend 2214104841Sobrien && ELF64_R_TYPE (irel[1].r_info) == R_ALPHA_LITUSE) 2215104841Sobrien { 2216104841Sobrien if (!elf64_alpha_relax_with_lituse (&info, symval, irel)) 2217104841Sobrien goto error_return; 2218104841Sobrien } 2219104841Sobrien else 2220104841Sobrien { 2221104841Sobrien if (!elf64_alpha_relax_got_load (&info, symval, irel, r_type)) 2222104841Sobrien goto error_return; 2223104841Sobrien } 2224104841Sobrien break; 222560510Sobrien 2226104841Sobrien case R_ALPHA_GPRELHIGH: 2227104841Sobrien case R_ALPHA_GPRELLOW: 2228104841Sobrien if (!elf64_alpha_relax_gprelhilo (&info, symval, irel, 2229104841Sobrien r_type == R_ALPHA_GPRELHIGH)) 223060510Sobrien goto error_return; 2231104841Sobrien break; 2232104841Sobrien 2233104841Sobrien case R_ALPHA_GOTDTPREL: 2234104841Sobrien case R_ALPHA_GOTTPREL: 2235104841Sobrien BFD_ASSERT(info.gotent != NULL); 2236104841Sobrien if (!elf64_alpha_relax_got_load (&info, symval, irel, r_type)) 223760510Sobrien goto error_return; 2238104841Sobrien break; 2239104841Sobrien 2240104841Sobrien case R_ALPHA_TLSGD: 2241104841Sobrien case R_ALPHA_TLSLDM: 2242104841Sobrien BFD_ASSERT(info.gotent != NULL); 2243104841Sobrien if (!elf64_alpha_relax_tls_get_addr (&info, symval, irel, 2244104841Sobrien r_type == R_ALPHA_TLSGD)) 2245104841Sobrien goto error_return; 2246104841Sobrien break; 224760510Sobrien } 224860510Sobrien } 224960510Sobrien 2250104841Sobrien if (!elf64_alpha_size_plt_section (link_info)) 225160510Sobrien return false; 2252104841Sobrien if (!elf64_alpha_size_got_sections (link_info)) 2253104841Sobrien return false; 2254104841Sobrien if (!elf64_alpha_size_rela_got_section (link_info)) 2255104841Sobrien return false; 225660510Sobrien 2257104841Sobrien if (isymbuf != NULL 2258104841Sobrien && symtab_hdr->contents != (unsigned char *) isymbuf) 225960510Sobrien { 2260104841Sobrien if (!link_info->keep_memory) 2261104841Sobrien free (isymbuf); 2262104841Sobrien else 2263104841Sobrien { 2264104841Sobrien /* Cache the symbols for elf_link_input_bfd. */ 2265104841Sobrien symtab_hdr->contents = (unsigned char *) isymbuf; 2266104841Sobrien } 226760510Sobrien } 226860510Sobrien 2269104841Sobrien if (info.contents != NULL 2270104841Sobrien && elf_section_data (sec)->this_hdr.contents != info.contents) 227160510Sobrien { 2272104841Sobrien if (!info.changed_contents && !link_info->keep_memory) 2273104841Sobrien free (info.contents); 227460510Sobrien else 227560510Sobrien { 227660510Sobrien /* Cache the section contents for elf_link_input_bfd. */ 227760510Sobrien elf_section_data (sec)->this_hdr.contents = info.contents; 227860510Sobrien } 227960510Sobrien } 228060510Sobrien 2281104841Sobrien if (elf_section_data (sec)->relocs != internal_relocs) 228260510Sobrien { 2283104841Sobrien if (!info.changed_relocs) 2284104841Sobrien free (internal_relocs); 228560510Sobrien else 2286104841Sobrien elf_section_data (sec)->relocs = internal_relocs; 228760510Sobrien } 228860510Sobrien 228960510Sobrien *again = info.changed_contents || info.changed_relocs; 229060510Sobrien 229160510Sobrien return true; 229260510Sobrien 229360510Sobrien error_return: 2294104841Sobrien if (isymbuf != NULL 2295104841Sobrien && symtab_hdr->contents != (unsigned char *) isymbuf) 2296104841Sobrien free (isymbuf); 2297104841Sobrien if (info.contents != NULL 2298104841Sobrien && elf_section_data (sec)->this_hdr.contents != info.contents) 2299104841Sobrien free (info.contents); 2300104841Sobrien if (internal_relocs != NULL 2301104841Sobrien && elf_section_data (sec)->relocs != internal_relocs) 2302104841Sobrien free (internal_relocs); 230360510Sobrien return false; 230460510Sobrien} 230560510Sobrien 230633965Sjdp/* PLT/GOT Stuff */ 230733965Sjdp#define PLT_HEADER_SIZE 32 230889862Sobrien#define PLT_HEADER_WORD1 (bfd_vma) 0xc3600000 /* br $27,.+4 */ 230989862Sobrien#define PLT_HEADER_WORD2 (bfd_vma) 0xa77b000c /* ldq $27,12($27) */ 231089862Sobrien#define PLT_HEADER_WORD3 (bfd_vma) 0x47ff041f /* nop */ 231189862Sobrien#define PLT_HEADER_WORD4 (bfd_vma) 0x6b7b0000 /* jmp $27,($27) */ 231233965Sjdp 231333965Sjdp#define PLT_ENTRY_SIZE 12 231438889Sjdp#define PLT_ENTRY_WORD1 0xc3800000 /* br $28, plt0 */ 231538889Sjdp#define PLT_ENTRY_WORD2 0 231638889Sjdp#define PLT_ENTRY_WORD3 0 231733965Sjdp 2318104841Sobrien#define MAX_GOT_SIZE (64*1024) 231933965Sjdp 232068770Sobrien#define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so" 232133965Sjdp 232233965Sjdp/* Handle an Alpha specific section when reading an object file. This 232333965Sjdp is called when elfcode.h finds a section with an unknown type. 232460510Sobrien FIXME: We need to handle the SHF_ALPHA_GPREL flag, but I'm not sure 232533965Sjdp how to. */ 232633965Sjdp 232733965Sjdpstatic boolean 232833965Sjdpelf64_alpha_section_from_shdr (abfd, hdr, name) 232933965Sjdp bfd *abfd; 233033965Sjdp Elf64_Internal_Shdr *hdr; 2331104841Sobrien const char *name; 233233965Sjdp{ 233333965Sjdp asection *newsect; 233433965Sjdp 233533965Sjdp /* There ought to be a place to keep ELF backend specific flags, but 233633965Sjdp at the moment there isn't one. We just keep track of the 233733965Sjdp sections by their name, instead. Fortunately, the ABI gives 233833965Sjdp suggested names for all the MIPS specific sections, so we will 233933965Sjdp probably get away with this. */ 234033965Sjdp switch (hdr->sh_type) 234133965Sjdp { 234233965Sjdp case SHT_ALPHA_DEBUG: 234333965Sjdp if (strcmp (name, ".mdebug") != 0) 234433965Sjdp return false; 234533965Sjdp break; 234633965Sjdp default: 234733965Sjdp return false; 234833965Sjdp } 234933965Sjdp 235033965Sjdp if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name)) 235133965Sjdp return false; 235233965Sjdp newsect = hdr->bfd_section; 235333965Sjdp 235433965Sjdp if (hdr->sh_type == SHT_ALPHA_DEBUG) 235533965Sjdp { 235633965Sjdp if (! bfd_set_section_flags (abfd, newsect, 235733965Sjdp (bfd_get_section_flags (abfd, newsect) 235833965Sjdp | SEC_DEBUGGING))) 235933965Sjdp return false; 236033965Sjdp } 236133965Sjdp 236289862Sobrien return true; 236389862Sobrien} 236433965Sjdp 236589862Sobrien/* Convert Alpha specific section flags to bfd internal section flags. */ 236633965Sjdp 236789862Sobrienstatic boolean 236889862Sobrienelf64_alpha_section_flags (flags, hdr) 236989862Sobrien flagword *flags; 237089862Sobrien Elf64_Internal_Shdr *hdr; 237189862Sobrien{ 237289862Sobrien if (hdr->sh_flags & SHF_ALPHA_GPREL) 237389862Sobrien *flags |= SEC_SMALL_DATA; 237489862Sobrien 237533965Sjdp return true; 237633965Sjdp} 237733965Sjdp 237833965Sjdp/* Set the correct type for an Alpha ELF section. We do this by the 237933965Sjdp section name, which is a hack, but ought to work. */ 238033965Sjdp 238133965Sjdpstatic boolean 238233965Sjdpelf64_alpha_fake_sections (abfd, hdr, sec) 238333965Sjdp bfd *abfd; 238433965Sjdp Elf64_Internal_Shdr *hdr; 238533965Sjdp asection *sec; 238633965Sjdp{ 238733965Sjdp register const char *name; 238833965Sjdp 238933965Sjdp name = bfd_get_section_name (abfd, sec); 239033965Sjdp 239133965Sjdp if (strcmp (name, ".mdebug") == 0) 239233965Sjdp { 239333965Sjdp hdr->sh_type = SHT_ALPHA_DEBUG; 239433965Sjdp /* In a shared object on Irix 5.3, the .mdebug section has an 239533965Sjdp entsize of 0. FIXME: Does this matter? */ 239633965Sjdp if ((abfd->flags & DYNAMIC) != 0 ) 239733965Sjdp hdr->sh_entsize = 0; 239833965Sjdp else 239933965Sjdp hdr->sh_entsize = 1; 240033965Sjdp } 240189862Sobrien else if ((sec->flags & SEC_SMALL_DATA) 240289862Sobrien || strcmp (name, ".sdata") == 0 240333965Sjdp || strcmp (name, ".sbss") == 0 240433965Sjdp || strcmp (name, ".lit4") == 0 240533965Sjdp || strcmp (name, ".lit8") == 0) 240633965Sjdp hdr->sh_flags |= SHF_ALPHA_GPREL; 240733965Sjdp 240833965Sjdp return true; 240933965Sjdp} 241033965Sjdp 241160510Sobrien/* Hook called by the linker routine which adds symbols from an object 241260510Sobrien file. We use it to put .comm items in .sbss, and not .bss. */ 241333965Sjdp 241460510Sobrienstatic boolean 241560510Sobrienelf64_alpha_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp) 241633965Sjdp bfd *abfd; 241760510Sobrien struct bfd_link_info *info; 241860510Sobrien const Elf_Internal_Sym *sym; 241978833Sobrien const char **namep ATTRIBUTE_UNUSED; 242078833Sobrien flagword *flagsp ATTRIBUTE_UNUSED; 242160510Sobrien asection **secp; 242260510Sobrien bfd_vma *valp; 242333965Sjdp{ 242460510Sobrien if (sym->st_shndx == SHN_COMMON 242560510Sobrien && !info->relocateable 242689862Sobrien && sym->st_size <= elf_gp_size (abfd)) 242760510Sobrien { 242860510Sobrien /* Common symbols less than or equal to -G nn bytes are 242960510Sobrien automatically put into .sbss. */ 243033965Sjdp 243160510Sobrien asection *scomm = bfd_get_section_by_name (abfd, ".scommon"); 243233965Sjdp 243360510Sobrien if (scomm == NULL) 243460510Sobrien { 243560510Sobrien scomm = bfd_make_section (abfd, ".scommon"); 243660510Sobrien if (scomm == NULL 243760510Sobrien || !bfd_set_section_flags (abfd, scomm, (SEC_ALLOC 243860510Sobrien | SEC_IS_COMMON 243960510Sobrien | SEC_LINKER_CREATED))) 244060510Sobrien return false; 244160510Sobrien } 244233965Sjdp 244360510Sobrien *secp = scomm; 244460510Sobrien *valp = sym->st_size; 244533965Sjdp } 244633965Sjdp 244760510Sobrien return true; 244833965Sjdp} 244933965Sjdp 245033965Sjdp/* Create the .got section. */ 245133965Sjdp 245233965Sjdpstatic boolean 245333965Sjdpelf64_alpha_create_got_section(abfd, info) 245433965Sjdp bfd *abfd; 245578833Sobrien struct bfd_link_info *info ATTRIBUTE_UNUSED; 245633965Sjdp{ 245733965Sjdp asection *s; 245833965Sjdp 245933965Sjdp if (bfd_get_section_by_name (abfd, ".got")) 246033965Sjdp return true; 246133965Sjdp 246233965Sjdp s = bfd_make_section (abfd, ".got"); 246333965Sjdp if (s == NULL 246433965Sjdp || !bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD 246533965Sjdp | SEC_HAS_CONTENTS 246633965Sjdp | SEC_IN_MEMORY 246733965Sjdp | SEC_LINKER_CREATED)) 246833965Sjdp || !bfd_set_section_alignment (abfd, s, 3)) 246933965Sjdp return false; 247033965Sjdp 247133965Sjdp alpha_elf_tdata (abfd)->got = s; 247233965Sjdp 247333965Sjdp return true; 247433965Sjdp} 247533965Sjdp 247633965Sjdp/* Create all the dynamic sections. */ 247733965Sjdp 247833965Sjdpstatic boolean 247933965Sjdpelf64_alpha_create_dynamic_sections (abfd, info) 248033965Sjdp bfd *abfd; 248133965Sjdp struct bfd_link_info *info; 248233965Sjdp{ 248333965Sjdp asection *s; 248433965Sjdp struct elf_link_hash_entry *h; 2485107497Sobrien struct bfd_link_hash_entry *bh; 248633965Sjdp 248733965Sjdp /* We need to create .plt, .rela.plt, .got, and .rela.got sections. */ 248833965Sjdp 248933965Sjdp s = bfd_make_section (abfd, ".plt"); 249033965Sjdp if (s == NULL 249133965Sjdp || ! bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD 249233965Sjdp | SEC_HAS_CONTENTS 249333965Sjdp | SEC_IN_MEMORY 249433965Sjdp | SEC_LINKER_CREATED 249533965Sjdp | SEC_CODE)) 249633965Sjdp || ! bfd_set_section_alignment (abfd, s, 3)) 249733965Sjdp return false; 249833965Sjdp 249933965Sjdp /* Define the symbol _PROCEDURE_LINKAGE_TABLE_ at the start of the 250033965Sjdp .plt section. */ 2501107497Sobrien bh = NULL; 250233965Sjdp if (! (_bfd_generic_link_add_one_symbol 250333965Sjdp (info, abfd, "_PROCEDURE_LINKAGE_TABLE_", BSF_GLOBAL, s, 250433965Sjdp (bfd_vma) 0, (const char *) NULL, false, 2505107497Sobrien get_elf_backend_data (abfd)->collect, &bh))) 250633965Sjdp return false; 2507107497Sobrien h = (struct elf_link_hash_entry *) bh; 250833965Sjdp h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR; 250933965Sjdp h->type = STT_OBJECT; 251033965Sjdp 251133965Sjdp if (info->shared 251233965Sjdp && ! _bfd_elf_link_record_dynamic_symbol (info, h)) 251333965Sjdp return false; 251433965Sjdp 251533965Sjdp s = bfd_make_section (abfd, ".rela.plt"); 251633965Sjdp if (s == NULL 251733965Sjdp || !bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD 251833965Sjdp | SEC_HAS_CONTENTS 251933965Sjdp | SEC_IN_MEMORY 252033965Sjdp | SEC_LINKER_CREATED 252133965Sjdp | SEC_READONLY)) 252233965Sjdp || ! bfd_set_section_alignment (abfd, s, 3)) 252333965Sjdp return false; 252433965Sjdp 252533965Sjdp /* We may or may not have created a .got section for this object, but 252633965Sjdp we definitely havn't done the rest of the work. */ 252733965Sjdp 252833965Sjdp if (!elf64_alpha_create_got_section (abfd, info)) 252933965Sjdp return false; 253033965Sjdp 253133965Sjdp s = bfd_make_section(abfd, ".rela.got"); 253233965Sjdp if (s == NULL 253333965Sjdp || !bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD 253433965Sjdp | SEC_HAS_CONTENTS 253533965Sjdp | SEC_IN_MEMORY 253633965Sjdp | SEC_LINKER_CREATED 253733965Sjdp | SEC_READONLY)) 253833965Sjdp || !bfd_set_section_alignment (abfd, s, 3)) 253933965Sjdp return false; 254033965Sjdp 254133965Sjdp /* Define the symbol _GLOBAL_OFFSET_TABLE_ at the start of the 254233965Sjdp dynobj's .got section. We don't do this in the linker script 254333965Sjdp because we don't want to define the symbol if we are not creating 254433965Sjdp a global offset table. */ 2545107497Sobrien bh = NULL; 254633965Sjdp if (!(_bfd_generic_link_add_one_symbol 254733965Sjdp (info, abfd, "_GLOBAL_OFFSET_TABLE_", BSF_GLOBAL, 254833965Sjdp alpha_elf_tdata(abfd)->got, (bfd_vma) 0, (const char *) NULL, 2549107497Sobrien false, get_elf_backend_data (abfd)->collect, &bh))) 255033965Sjdp return false; 2551107497Sobrien h = (struct elf_link_hash_entry *) bh; 255233965Sjdp h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR; 255333965Sjdp h->type = STT_OBJECT; 255433965Sjdp 255533965Sjdp if (info->shared 255633965Sjdp && ! _bfd_elf_link_record_dynamic_symbol (info, h)) 255733965Sjdp return false; 255833965Sjdp 255933965Sjdp elf_hash_table (info)->hgot = h; 256033965Sjdp 256133965Sjdp return true; 256233965Sjdp} 256333965Sjdp 256433965Sjdp/* Read ECOFF debugging information from a .mdebug section into a 256533965Sjdp ecoff_debug_info structure. */ 256633965Sjdp 256733965Sjdpstatic boolean 256833965Sjdpelf64_alpha_read_ecoff_info (abfd, section, debug) 256933965Sjdp bfd *abfd; 257033965Sjdp asection *section; 257133965Sjdp struct ecoff_debug_info *debug; 257233965Sjdp{ 257333965Sjdp HDRR *symhdr; 257433965Sjdp const struct ecoff_debug_swap *swap; 257533965Sjdp char *ext_hdr = NULL; 257633965Sjdp 257733965Sjdp swap = get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap; 257877303Sobrien memset (debug, 0, sizeof (*debug)); 257933965Sjdp 258089862Sobrien ext_hdr = (char *) bfd_malloc (swap->external_hdr_size); 258133965Sjdp if (ext_hdr == NULL && swap->external_hdr_size != 0) 258233965Sjdp goto error_return; 258333965Sjdp 2584104841Sobrien if (! bfd_get_section_contents (abfd, section, ext_hdr, (file_ptr) 0, 2585104841Sobrien swap->external_hdr_size)) 258633965Sjdp goto error_return; 258733965Sjdp 258833965Sjdp symhdr = &debug->symbolic_header; 258933965Sjdp (*swap->swap_hdr_in) (abfd, ext_hdr, symhdr); 259033965Sjdp 259133965Sjdp /* The symbolic header contains absolute file offsets and sizes to 259233965Sjdp read. */ 259333965Sjdp#define READ(ptr, offset, count, size, type) \ 259433965Sjdp if (symhdr->count == 0) \ 259533965Sjdp debug->ptr = NULL; \ 259633965Sjdp else \ 259733965Sjdp { \ 259889862Sobrien bfd_size_type amt = (bfd_size_type) size * symhdr->count; \ 259989862Sobrien debug->ptr = (type) bfd_malloc (amt); \ 260033965Sjdp if (debug->ptr == NULL) \ 260133965Sjdp goto error_return; \ 260233965Sjdp if (bfd_seek (abfd, (file_ptr) symhdr->offset, SEEK_SET) != 0 \ 260389862Sobrien || bfd_bread (debug->ptr, amt, abfd) != amt) \ 260433965Sjdp goto error_return; \ 260533965Sjdp } 260633965Sjdp 260733965Sjdp READ (line, cbLineOffset, cbLine, sizeof (unsigned char), unsigned char *); 260833965Sjdp READ (external_dnr, cbDnOffset, idnMax, swap->external_dnr_size, PTR); 260933965Sjdp READ (external_pdr, cbPdOffset, ipdMax, swap->external_pdr_size, PTR); 261033965Sjdp READ (external_sym, cbSymOffset, isymMax, swap->external_sym_size, PTR); 261133965Sjdp READ (external_opt, cbOptOffset, ioptMax, swap->external_opt_size, PTR); 261233965Sjdp READ (external_aux, cbAuxOffset, iauxMax, sizeof (union aux_ext), 261333965Sjdp union aux_ext *); 261433965Sjdp READ (ss, cbSsOffset, issMax, sizeof (char), char *); 261533965Sjdp READ (ssext, cbSsExtOffset, issExtMax, sizeof (char), char *); 261633965Sjdp READ (external_fdr, cbFdOffset, ifdMax, swap->external_fdr_size, PTR); 261733965Sjdp READ (external_rfd, cbRfdOffset, crfd, swap->external_rfd_size, PTR); 261833965Sjdp READ (external_ext, cbExtOffset, iextMax, swap->external_ext_size, PTR); 261933965Sjdp#undef READ 262033965Sjdp 262133965Sjdp debug->fdr = NULL; 262233965Sjdp debug->adjust = NULL; 262333965Sjdp 262433965Sjdp return true; 262533965Sjdp 262633965Sjdp error_return: 262733965Sjdp if (ext_hdr != NULL) 262833965Sjdp free (ext_hdr); 262933965Sjdp if (debug->line != NULL) 263033965Sjdp free (debug->line); 263133965Sjdp if (debug->external_dnr != NULL) 263233965Sjdp free (debug->external_dnr); 263333965Sjdp if (debug->external_pdr != NULL) 263433965Sjdp free (debug->external_pdr); 263533965Sjdp if (debug->external_sym != NULL) 263633965Sjdp free (debug->external_sym); 263733965Sjdp if (debug->external_opt != NULL) 263833965Sjdp free (debug->external_opt); 263933965Sjdp if (debug->external_aux != NULL) 264033965Sjdp free (debug->external_aux); 264133965Sjdp if (debug->ss != NULL) 264233965Sjdp free (debug->ss); 264333965Sjdp if (debug->ssext != NULL) 264433965Sjdp free (debug->ssext); 264533965Sjdp if (debug->external_fdr != NULL) 264633965Sjdp free (debug->external_fdr); 264733965Sjdp if (debug->external_rfd != NULL) 264833965Sjdp free (debug->external_rfd); 264933965Sjdp if (debug->external_ext != NULL) 265033965Sjdp free (debug->external_ext); 265133965Sjdp return false; 265233965Sjdp} 265333965Sjdp 265433965Sjdp/* Alpha ELF local labels start with '$'. */ 265533965Sjdp 265633965Sjdpstatic boolean 265733965Sjdpelf64_alpha_is_local_label_name (abfd, name) 265878833Sobrien bfd *abfd ATTRIBUTE_UNUSED; 265933965Sjdp const char *name; 266033965Sjdp{ 266133965Sjdp return name[0] == '$'; 266233965Sjdp} 266333965Sjdp 266433965Sjdp/* Alpha ELF follows MIPS ELF in using a special find_nearest_line 266533965Sjdp routine in order to handle the ECOFF debugging information. We 266633965Sjdp still call this mips_elf_find_line because of the slot 266733965Sjdp find_line_info in elf_obj_tdata is declared that way. */ 266833965Sjdp 266933965Sjdpstruct mips_elf_find_line 267033965Sjdp{ 267133965Sjdp struct ecoff_debug_info d; 267233965Sjdp struct ecoff_find_line i; 267333965Sjdp}; 267433965Sjdp 267533965Sjdpstatic boolean 267633965Sjdpelf64_alpha_find_nearest_line (abfd, section, symbols, offset, filename_ptr, 267733965Sjdp functionname_ptr, line_ptr) 267833965Sjdp bfd *abfd; 267933965Sjdp asection *section; 268033965Sjdp asymbol **symbols; 268133965Sjdp bfd_vma offset; 268233965Sjdp const char **filename_ptr; 268333965Sjdp const char **functionname_ptr; 268433965Sjdp unsigned int *line_ptr; 268533965Sjdp{ 268633965Sjdp asection *msec; 268733965Sjdp 268877303Sobrien if (_bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset, 268977303Sobrien filename_ptr, functionname_ptr, 269077303Sobrien line_ptr, 0, 269177303Sobrien &elf_tdata (abfd)->dwarf2_find_line_info)) 269277303Sobrien return true; 269377303Sobrien 269433965Sjdp msec = bfd_get_section_by_name (abfd, ".mdebug"); 269533965Sjdp if (msec != NULL) 269633965Sjdp { 269733965Sjdp flagword origflags; 269833965Sjdp struct mips_elf_find_line *fi; 269933965Sjdp const struct ecoff_debug_swap * const swap = 270033965Sjdp get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap; 270133965Sjdp 270233965Sjdp /* If we are called during a link, alpha_elf_final_link may have 270333965Sjdp cleared the SEC_HAS_CONTENTS field. We force it back on here 270433965Sjdp if appropriate (which it normally will be). */ 270533965Sjdp origflags = msec->flags; 270633965Sjdp if (elf_section_data (msec)->this_hdr.sh_type != SHT_NOBITS) 270733965Sjdp msec->flags |= SEC_HAS_CONTENTS; 270833965Sjdp 270933965Sjdp fi = elf_tdata (abfd)->find_line_info; 271033965Sjdp if (fi == NULL) 271133965Sjdp { 271233965Sjdp bfd_size_type external_fdr_size; 271333965Sjdp char *fraw_src; 271433965Sjdp char *fraw_end; 271533965Sjdp struct fdr *fdr_ptr; 271689862Sobrien bfd_size_type amt = sizeof (struct mips_elf_find_line); 271733965Sjdp 271889862Sobrien fi = (struct mips_elf_find_line *) bfd_zalloc (abfd, amt); 271933965Sjdp if (fi == NULL) 272033965Sjdp { 272133965Sjdp msec->flags = origflags; 272233965Sjdp return false; 272333965Sjdp } 272433965Sjdp 272533965Sjdp if (!elf64_alpha_read_ecoff_info (abfd, msec, &fi->d)) 272633965Sjdp { 272733965Sjdp msec->flags = origflags; 272833965Sjdp return false; 272933965Sjdp } 273033965Sjdp 273133965Sjdp /* Swap in the FDR information. */ 273289862Sobrien amt = fi->d.symbolic_header.ifdMax * sizeof (struct fdr); 273389862Sobrien fi->d.fdr = (struct fdr *) bfd_alloc (abfd, amt); 273433965Sjdp if (fi->d.fdr == NULL) 273533965Sjdp { 273633965Sjdp msec->flags = origflags; 273733965Sjdp return false; 273833965Sjdp } 273933965Sjdp external_fdr_size = swap->external_fdr_size; 274033965Sjdp fdr_ptr = fi->d.fdr; 274133965Sjdp fraw_src = (char *) fi->d.external_fdr; 274233965Sjdp fraw_end = (fraw_src 274333965Sjdp + fi->d.symbolic_header.ifdMax * external_fdr_size); 274433965Sjdp for (; fraw_src < fraw_end; fraw_src += external_fdr_size, fdr_ptr++) 274533965Sjdp (*swap->swap_fdr_in) (abfd, (PTR) fraw_src, fdr_ptr); 274633965Sjdp 274733965Sjdp elf_tdata (abfd)->find_line_info = fi; 274833965Sjdp 274933965Sjdp /* Note that we don't bother to ever free this information. 275033965Sjdp find_nearest_line is either called all the time, as in 275133965Sjdp objdump -l, so the information should be saved, or it is 275233965Sjdp rarely called, as in ld error messages, so the memory 275333965Sjdp wasted is unimportant. Still, it would probably be a 275433965Sjdp good idea for free_cached_info to throw it away. */ 275533965Sjdp } 275633965Sjdp 275733965Sjdp if (_bfd_ecoff_locate_line (abfd, section, offset, &fi->d, swap, 275833965Sjdp &fi->i, filename_ptr, functionname_ptr, 275933965Sjdp line_ptr)) 276033965Sjdp { 276133965Sjdp msec->flags = origflags; 276233965Sjdp return true; 276333965Sjdp } 276433965Sjdp 276533965Sjdp msec->flags = origflags; 276633965Sjdp } 276733965Sjdp 276833965Sjdp /* Fall back on the generic ELF find_nearest_line routine. */ 276933965Sjdp 277033965Sjdp return _bfd_elf_find_nearest_line (abfd, section, symbols, offset, 277133965Sjdp filename_ptr, functionname_ptr, 277233965Sjdp line_ptr); 277333965Sjdp} 277433965Sjdp 277533965Sjdp/* Structure used to pass information to alpha_elf_output_extsym. */ 277633965Sjdp 277733965Sjdpstruct extsym_info 277833965Sjdp{ 277933965Sjdp bfd *abfd; 278033965Sjdp struct bfd_link_info *info; 278133965Sjdp struct ecoff_debug_info *debug; 278233965Sjdp const struct ecoff_debug_swap *swap; 278333965Sjdp boolean failed; 278433965Sjdp}; 278533965Sjdp 278633965Sjdpstatic boolean 278733965Sjdpelf64_alpha_output_extsym (h, data) 278833965Sjdp struct alpha_elf_link_hash_entry *h; 278933965Sjdp PTR data; 279033965Sjdp{ 279133965Sjdp struct extsym_info *einfo = (struct extsym_info *) data; 279233965Sjdp boolean strip; 279333965Sjdp asection *sec, *output_section; 279433965Sjdp 279594544Sobrien if (h->root.root.type == bfd_link_hash_warning) 279694544Sobrien h = (struct alpha_elf_link_hash_entry *) h->root.root.u.i.link; 279794544Sobrien 279833965Sjdp if (h->root.indx == -2) 279933965Sjdp strip = false; 280033965Sjdp else if (((h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0 280194544Sobrien || (h->root.elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) != 0) 280294544Sobrien && (h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0 280394544Sobrien && (h->root.elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) == 0) 280433965Sjdp strip = true; 280533965Sjdp else if (einfo->info->strip == strip_all 280694544Sobrien || (einfo->info->strip == strip_some 280794544Sobrien && bfd_hash_lookup (einfo->info->keep_hash, 280894544Sobrien h->root.root.root.string, 280994544Sobrien false, false) == NULL)) 281033965Sjdp strip = true; 281133965Sjdp else 281233965Sjdp strip = false; 281333965Sjdp 281433965Sjdp if (strip) 281533965Sjdp return true; 281633965Sjdp 281733965Sjdp if (h->esym.ifd == -2) 281833965Sjdp { 281933965Sjdp h->esym.jmptbl = 0; 282033965Sjdp h->esym.cobol_main = 0; 282133965Sjdp h->esym.weakext = 0; 282233965Sjdp h->esym.reserved = 0; 282333965Sjdp h->esym.ifd = ifdNil; 282433965Sjdp h->esym.asym.value = 0; 282533965Sjdp h->esym.asym.st = stGlobal; 282633965Sjdp 282733965Sjdp if (h->root.root.type != bfd_link_hash_defined 282894544Sobrien && h->root.root.type != bfd_link_hash_defweak) 282994544Sobrien h->esym.asym.sc = scAbs; 283033965Sjdp else 283194544Sobrien { 283294544Sobrien const char *name; 283333965Sjdp 283494544Sobrien sec = h->root.root.u.def.section; 283594544Sobrien output_section = sec->output_section; 283633965Sjdp 283794544Sobrien /* When making a shared library and symbol h is the one from 283894544Sobrien the another shared library, OUTPUT_SECTION may be null. */ 283994544Sobrien if (output_section == NULL) 284094544Sobrien h->esym.asym.sc = scUndefined; 284194544Sobrien else 284294544Sobrien { 284394544Sobrien name = bfd_section_name (output_section->owner, output_section); 284433965Sjdp 284594544Sobrien if (strcmp (name, ".text") == 0) 284694544Sobrien h->esym.asym.sc = scText; 284794544Sobrien else if (strcmp (name, ".data") == 0) 284894544Sobrien h->esym.asym.sc = scData; 284994544Sobrien else if (strcmp (name, ".sdata") == 0) 285094544Sobrien h->esym.asym.sc = scSData; 285194544Sobrien else if (strcmp (name, ".rodata") == 0 285294544Sobrien || strcmp (name, ".rdata") == 0) 285394544Sobrien h->esym.asym.sc = scRData; 285494544Sobrien else if (strcmp (name, ".bss") == 0) 285594544Sobrien h->esym.asym.sc = scBss; 285694544Sobrien else if (strcmp (name, ".sbss") == 0) 285794544Sobrien h->esym.asym.sc = scSBss; 285894544Sobrien else if (strcmp (name, ".init") == 0) 285994544Sobrien h->esym.asym.sc = scInit; 286094544Sobrien else if (strcmp (name, ".fini") == 0) 286194544Sobrien h->esym.asym.sc = scFini; 286294544Sobrien else 286394544Sobrien h->esym.asym.sc = scAbs; 286494544Sobrien } 286594544Sobrien } 286633965Sjdp 286733965Sjdp h->esym.asym.reserved = 0; 286833965Sjdp h->esym.asym.index = indexNil; 286933965Sjdp } 287033965Sjdp 287133965Sjdp if (h->root.root.type == bfd_link_hash_common) 287233965Sjdp h->esym.asym.value = h->root.root.u.c.size; 287333965Sjdp else if (h->root.root.type == bfd_link_hash_defined 287433965Sjdp || h->root.root.type == bfd_link_hash_defweak) 287533965Sjdp { 287633965Sjdp if (h->esym.asym.sc == scCommon) 287794544Sobrien h->esym.asym.sc = scBss; 287833965Sjdp else if (h->esym.asym.sc == scSCommon) 287994544Sobrien h->esym.asym.sc = scSBss; 288033965Sjdp 288133965Sjdp sec = h->root.root.u.def.section; 288233965Sjdp output_section = sec->output_section; 288333965Sjdp if (output_section != NULL) 288494544Sobrien h->esym.asym.value = (h->root.root.u.def.value 288594544Sobrien + sec->output_offset 288694544Sobrien + output_section->vma); 288733965Sjdp else 288894544Sobrien h->esym.asym.value = 0; 288933965Sjdp } 289033965Sjdp else if ((h->root.elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0) 289133965Sjdp { 289233965Sjdp /* Set type and value for a symbol with a function stub. */ 289333965Sjdp h->esym.asym.st = stProc; 289433965Sjdp sec = bfd_get_section_by_name (einfo->abfd, ".plt"); 289533965Sjdp if (sec == NULL) 289633965Sjdp h->esym.asym.value = 0; 289733965Sjdp else 289833965Sjdp { 289933965Sjdp output_section = sec->output_section; 290033965Sjdp if (output_section != NULL) 290160510Sobrien h->esym.asym.value = (h->root.plt.offset 290233965Sjdp + sec->output_offset 290333965Sjdp + output_section->vma); 290433965Sjdp else 290533965Sjdp h->esym.asym.value = 0; 290633965Sjdp } 290733965Sjdp } 290833965Sjdp 290933965Sjdp if (! bfd_ecoff_debug_one_external (einfo->abfd, einfo->debug, einfo->swap, 291094544Sobrien h->root.root.root.string, 291194544Sobrien &h->esym)) 291233965Sjdp { 291333965Sjdp einfo->failed = true; 291433965Sjdp return false; 291533965Sjdp } 291633965Sjdp 291733965Sjdp return true; 291833965Sjdp} 2919104841Sobrien 2920104841Sobrien/* Search for and possibly create a got entry. */ 292133965Sjdp 2922104841Sobrienstatic struct alpha_elf_got_entry * 2923104841Sobrienget_got_entry (abfd, h, r_type, r_symndx, r_addend) 2924104841Sobrien bfd *abfd; 2925104841Sobrien struct alpha_elf_link_hash_entry *h; 2926104841Sobrien unsigned long r_type, r_symndx; 2927104841Sobrien bfd_vma r_addend; 2928104841Sobrien{ 2929104841Sobrien struct alpha_elf_got_entry *gotent; 2930104841Sobrien struct alpha_elf_got_entry **slot; 293133965Sjdp 2932104841Sobrien if (h) 2933104841Sobrien slot = &h->got_entries; 2934104841Sobrien else 2935104841Sobrien { 2936104841Sobrien /* This is a local .got entry -- record for merge. */ 2937104841Sobrien 2938104841Sobrien struct alpha_elf_got_entry **local_got_entries; 2939104841Sobrien 2940104841Sobrien local_got_entries = alpha_elf_tdata(abfd)->local_got_entries; 2941104841Sobrien if (!local_got_entries) 2942104841Sobrien { 2943104841Sobrien bfd_size_type size; 2944104841Sobrien Elf_Internal_Shdr *symtab_hdr; 2945104841Sobrien 2946104841Sobrien symtab_hdr = &elf_tdata(abfd)->symtab_hdr; 2947104841Sobrien size = symtab_hdr->sh_info; 2948104841Sobrien size *= sizeof (struct alpha_elf_got_entry *); 2949104841Sobrien 2950104841Sobrien local_got_entries 2951104841Sobrien = (struct alpha_elf_got_entry **) bfd_zalloc (abfd, size); 2952104841Sobrien if (!local_got_entries) 2953104841Sobrien return NULL; 2954104841Sobrien 2955104841Sobrien alpha_elf_tdata (abfd)->local_got_entries = local_got_entries; 2956104841Sobrien } 2957104841Sobrien 2958104841Sobrien slot = &local_got_entries[r_symndx]; 2959104841Sobrien } 2960104841Sobrien 2961104841Sobrien for (gotent = *slot; gotent ; gotent = gotent->next) 2962104841Sobrien if (gotent->gotobj == abfd 2963104841Sobrien && gotent->reloc_type == r_type 2964104841Sobrien && gotent->addend == r_addend) 2965104841Sobrien break; 2966104841Sobrien 2967104841Sobrien if (!gotent) 2968104841Sobrien { 2969104841Sobrien int entry_size; 2970104841Sobrien bfd_size_type amt; 2971104841Sobrien 2972104841Sobrien amt = sizeof (struct alpha_elf_got_entry); 2973104841Sobrien gotent = (struct alpha_elf_got_entry *) bfd_alloc (abfd, amt); 2974104841Sobrien if (!gotent) 2975104841Sobrien return NULL; 2976104841Sobrien 2977104841Sobrien gotent->gotobj = abfd; 2978104841Sobrien gotent->addend = r_addend; 2979104841Sobrien gotent->got_offset = -1; 2980104841Sobrien gotent->use_count = 1; 2981104841Sobrien gotent->reloc_type = r_type; 2982104841Sobrien gotent->reloc_done = 0; 2983104841Sobrien gotent->reloc_xlated = 0; 2984104841Sobrien 2985104841Sobrien gotent->next = *slot; 2986104841Sobrien *slot = gotent; 2987104841Sobrien 2988104841Sobrien entry_size = alpha_got_entry_size (r_type); 2989104841Sobrien alpha_elf_tdata (abfd)->total_got_size += entry_size; 2990104841Sobrien if (!h) 2991104841Sobrien alpha_elf_tdata(abfd)->local_got_size += entry_size; 2992104841Sobrien } 2993104841Sobrien else 2994104841Sobrien gotent->use_count += 1; 2995104841Sobrien 2996104841Sobrien return gotent; 2997104841Sobrien} 2998104841Sobrien 299933965Sjdp/* Handle dynamic relocations when doing an Alpha ELF link. */ 300033965Sjdp 300133965Sjdpstatic boolean 300233965Sjdpelf64_alpha_check_relocs (abfd, info, sec, relocs) 300333965Sjdp bfd *abfd; 300433965Sjdp struct bfd_link_info *info; 300533965Sjdp asection *sec; 300633965Sjdp const Elf_Internal_Rela *relocs; 300733965Sjdp{ 300833965Sjdp bfd *dynobj; 300933965Sjdp asection *sreloc; 301033965Sjdp const char *rel_sec_name; 301133965Sjdp Elf_Internal_Shdr *symtab_hdr; 301233965Sjdp struct alpha_elf_link_hash_entry **sym_hashes; 301333965Sjdp const Elf_Internal_Rela *rel, *relend; 3014104841Sobrien boolean got_created; 301589862Sobrien bfd_size_type amt; 301633965Sjdp 301733965Sjdp if (info->relocateable) 301833965Sjdp return true; 301933965Sjdp 302033965Sjdp dynobj = elf_hash_table(info)->dynobj; 302133965Sjdp if (dynobj == NULL) 302233965Sjdp elf_hash_table(info)->dynobj = dynobj = abfd; 302333965Sjdp 302433965Sjdp sreloc = NULL; 302533965Sjdp rel_sec_name = NULL; 302633965Sjdp symtab_hdr = &elf_tdata(abfd)->symtab_hdr; 302733965Sjdp sym_hashes = alpha_elf_sym_hashes(abfd); 3028104841Sobrien got_created = false; 302933965Sjdp 303033965Sjdp relend = relocs + sec->reloc_count; 303133965Sjdp for (rel = relocs; rel < relend; ++rel) 303233965Sjdp { 3033104841Sobrien enum { 3034104841Sobrien NEED_GOT = 1, 3035104841Sobrien NEED_GOT_ENTRY = 2, 3036104841Sobrien NEED_DYNREL = 4 3037104841Sobrien }; 3038104841Sobrien 303933965Sjdp unsigned long r_symndx, r_type; 304033965Sjdp struct alpha_elf_link_hash_entry *h; 3041104841Sobrien unsigned int gotent_flags; 3042104841Sobrien boolean maybe_dynamic; 3043104841Sobrien unsigned int need; 3044104841Sobrien bfd_vma addend; 304533965Sjdp 304633965Sjdp r_symndx = ELF64_R_SYM (rel->r_info); 304733965Sjdp if (r_symndx < symtab_hdr->sh_info) 304833965Sjdp h = NULL; 304933965Sjdp else 305033965Sjdp { 305133965Sjdp h = sym_hashes[r_symndx - symtab_hdr->sh_info]; 305238889Sjdp 305338889Sjdp while (h->root.root.type == bfd_link_hash_indirect 305438889Sjdp || h->root.root.type == bfd_link_hash_warning) 305538889Sjdp h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link; 305638889Sjdp 305733965Sjdp h->root.elf_link_hash_flags |= ELF_LINK_HASH_REF_REGULAR; 305833965Sjdp } 3059104841Sobrien 3060104841Sobrien /* We can only get preliminary data on whether a symbol is 3061104841Sobrien locally or externally defined, as not all of the input files 3062104841Sobrien have yet been processed. Do something with what we know, as 3063104841Sobrien this may help reduce memory usage and processing time later. */ 3064104841Sobrien maybe_dynamic = false; 3065104841Sobrien if (h && ((info->shared 3066104841Sobrien && (!info->symbolic || info->allow_shlib_undefined)) 3067104841Sobrien || ! (h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) 3068104841Sobrien || h->root.root.type == bfd_link_hash_defweak)) 3069104841Sobrien maybe_dynamic = true; 3070104841Sobrien 3071104841Sobrien need = 0; 3072104841Sobrien gotent_flags = 0; 307333965Sjdp r_type = ELF64_R_TYPE (rel->r_info); 3074104841Sobrien addend = rel->r_addend; 307533965Sjdp 307633965Sjdp switch (r_type) 307733965Sjdp { 307833965Sjdp case R_ALPHA_LITERAL: 3079104841Sobrien need = NEED_GOT | NEED_GOT_ENTRY; 308033965Sjdp 3081104841Sobrien /* Remember how this literal is used from its LITUSEs. 3082104841Sobrien This will be important when it comes to decide if we can 3083104841Sobrien create a .plt entry for a function symbol. */ 3084104841Sobrien while (++rel < relend && ELF64_R_TYPE (rel->r_info) == R_ALPHA_LITUSE) 3085104841Sobrien if (rel->r_addend >= 1 && rel->r_addend <= 5) 3086104841Sobrien gotent_flags |= 1 << rel->r_addend; 3087104841Sobrien --rel; 308833965Sjdp 3089104841Sobrien /* No LITUSEs -- presumably the address is used somehow. */ 3090104841Sobrien if (gotent_flags == 0) 3091104841Sobrien gotent_flags = ALPHA_ELF_LINK_HASH_LU_ADDR; 3092104841Sobrien break; 309333965Sjdp 309433965Sjdp case R_ALPHA_GPDISP: 309589862Sobrien case R_ALPHA_GPREL16: 309633965Sjdp case R_ALPHA_GPREL32: 309760510Sobrien case R_ALPHA_GPRELHIGH: 309860510Sobrien case R_ALPHA_GPRELLOW: 309991049Sobrien case R_ALPHA_BRSGP: 3100104841Sobrien need = NEED_GOT; 3101104841Sobrien break; 3102104841Sobrien 3103104841Sobrien case R_ALPHA_REFLONG: 3104104841Sobrien case R_ALPHA_REFQUAD: 3105107497Sobrien if ((info->shared && (sec->flags & SEC_ALLOC)) || maybe_dynamic) 3106104841Sobrien need = NEED_DYNREL; 3107104841Sobrien break; 3108104841Sobrien 3109104841Sobrien case R_ALPHA_TLSGD: 3110104841Sobrien case R_ALPHA_TLSLDM: 3111104841Sobrien case R_ALPHA_GOTDTPREL: 3112104841Sobrien need = NEED_GOT | NEED_GOT_ENTRY; 3113104841Sobrien break; 3114104841Sobrien 3115104841Sobrien case R_ALPHA_GOTTPREL: 3116104841Sobrien need = NEED_GOT | NEED_GOT_ENTRY; 3117104841Sobrien gotent_flags = ALPHA_ELF_LINK_HASH_TLS_IE; 3118104841Sobrien if (info->shared) 3119104841Sobrien info->flags |= DF_STATIC_TLS; 3120104841Sobrien break; 3121104841Sobrien 3122104841Sobrien case R_ALPHA_TPREL64: 3123104841Sobrien if (info->shared || maybe_dynamic) 3124104841Sobrien need = NEED_DYNREL; 3125104841Sobrien if (info->shared) 3126104841Sobrien info->flags |= DF_STATIC_TLS; 3127104841Sobrien break; 3128104841Sobrien } 3129104841Sobrien 3130104841Sobrien if (need & NEED_GOT) 3131104841Sobrien { 313233965Sjdp if (!got_created) 313333965Sjdp { 313433965Sjdp if (!elf64_alpha_create_got_section (abfd, info)) 313533965Sjdp return false; 313633965Sjdp 313733965Sjdp /* Make sure the object's gotobj is set to itself so 313833965Sjdp that we default to every object with its own .got. 313933965Sjdp We'll merge .gots later once we've collected each 314033965Sjdp object's info. */ 314133965Sjdp alpha_elf_tdata(abfd)->gotobj = abfd; 314233965Sjdp 314333965Sjdp got_created = 1; 314433965Sjdp } 3145104841Sobrien } 314633965Sjdp 3147104841Sobrien if (need & NEED_GOT_ENTRY) 3148104841Sobrien { 3149104841Sobrien struct alpha_elf_got_entry *gotent; 315033965Sjdp 3151104841Sobrien gotent = get_got_entry (abfd, h, r_type, r_symndx, addend); 3152104841Sobrien if (!gotent) 3153104841Sobrien return false; 3154104841Sobrien 3155104841Sobrien if (gotent_flags) 3156104841Sobrien { 3157104841Sobrien gotent->flags |= gotent_flags; 3158104841Sobrien if (h) 3159104841Sobrien { 3160104841Sobrien gotent_flags |= h->flags; 3161104841Sobrien h->flags = gotent_flags; 3162104841Sobrien 3163104841Sobrien /* Make a guess as to whether a .plt entry is needed. */ 3164104841Sobrien if ((gotent_flags & ALPHA_ELF_LINK_HASH_LU_FUNC) 3165104841Sobrien && !(gotent_flags & ~ALPHA_ELF_LINK_HASH_LU_FUNC)) 3166104841Sobrien h->root.elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; 3167104841Sobrien else 3168104841Sobrien h->root.elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; 3169104841Sobrien } 3170104841Sobrien } 3171104841Sobrien } 3172104841Sobrien 3173104841Sobrien if (need & NEED_DYNREL) 3174104841Sobrien { 317533965Sjdp if (rel_sec_name == NULL) 317633965Sjdp { 317733965Sjdp rel_sec_name = (bfd_elf_string_from_elf_section 317833965Sjdp (abfd, elf_elfheader(abfd)->e_shstrndx, 317933965Sjdp elf_section_data(sec)->rel_hdr.sh_name)); 318033965Sjdp if (rel_sec_name == NULL) 318133965Sjdp return false; 318233965Sjdp 318333965Sjdp BFD_ASSERT (strncmp (rel_sec_name, ".rela", 5) == 0 318433965Sjdp && strcmp (bfd_get_section_name (abfd, sec), 318533965Sjdp rel_sec_name+5) == 0); 318633965Sjdp } 318733965Sjdp 318833965Sjdp /* We need to create the section here now whether we eventually 318933965Sjdp use it or not so that it gets mapped to an output section by 319033965Sjdp the linker. If not used, we'll kill it in 319133965Sjdp size_dynamic_sections. */ 319233965Sjdp if (sreloc == NULL) 319333965Sjdp { 319433965Sjdp sreloc = bfd_get_section_by_name (dynobj, rel_sec_name); 319533965Sjdp if (sreloc == NULL) 319633965Sjdp { 319789862Sobrien flagword flags; 319889862Sobrien 319933965Sjdp sreloc = bfd_make_section (dynobj, rel_sec_name); 320089862Sobrien flags = (SEC_HAS_CONTENTS | SEC_IN_MEMORY 320189862Sobrien | SEC_LINKER_CREATED | SEC_READONLY); 320289862Sobrien if (sec->flags & SEC_ALLOC) 320389862Sobrien flags |= SEC_ALLOC | SEC_LOAD; 320433965Sjdp if (sreloc == NULL 320589862Sobrien || !bfd_set_section_flags (dynobj, sreloc, flags) 320633965Sjdp || !bfd_set_section_alignment (dynobj, sreloc, 3)) 320733965Sjdp return false; 320833965Sjdp } 320933965Sjdp } 321033965Sjdp 321133965Sjdp if (h) 321233965Sjdp { 321333965Sjdp /* Since we havn't seen all of the input symbols yet, we 321433965Sjdp don't know whether we'll actually need a dynamic relocation 321533965Sjdp entry for this reloc. So make a record of it. Once we 321633965Sjdp find out if this thing needs dynamic relocation we'll 321777303Sobrien expand the relocation sections by the appropriate amount. */ 321833965Sjdp 321933965Sjdp struct alpha_elf_reloc_entry *rent; 322033965Sjdp 322133965Sjdp for (rent = h->reloc_entries; rent; rent = rent->next) 322233965Sjdp if (rent->rtype == r_type && rent->srel == sreloc) 322333965Sjdp break; 322433965Sjdp 322533965Sjdp if (!rent) 322633965Sjdp { 322789862Sobrien amt = sizeof (struct alpha_elf_reloc_entry); 322889862Sobrien rent = (struct alpha_elf_reloc_entry *) bfd_alloc (abfd, amt); 322933965Sjdp if (!rent) 323033965Sjdp return false; 323133965Sjdp 323233965Sjdp rent->srel = sreloc; 323333965Sjdp rent->rtype = r_type; 323433965Sjdp rent->count = 1; 323589862Sobrien rent->reltext = ((sec->flags & (SEC_READONLY | SEC_ALLOC)) 323689862Sobrien == (SEC_READONLY | SEC_ALLOC)); 323733965Sjdp 323833965Sjdp rent->next = h->reloc_entries; 323933965Sjdp h->reloc_entries = rent; 324033965Sjdp } 324133965Sjdp else 324233965Sjdp rent->count++; 324333965Sjdp } 3244104841Sobrien else if (info->shared) 324533965Sjdp { 324660510Sobrien /* If this is a shared library, and the section is to be 324760510Sobrien loaded into memory, we need a RELATIVE reloc. */ 324833965Sjdp sreloc->_raw_size += sizeof (Elf64_External_Rela); 3249104841Sobrien if ((sec->flags & (SEC_READONLY | SEC_ALLOC)) 3250104841Sobrien == (SEC_READONLY | SEC_ALLOC)) 325189862Sobrien info->flags |= DF_TEXTREL; 325233965Sjdp } 325333965Sjdp } 325433965Sjdp } 325533965Sjdp 325633965Sjdp return true; 325733965Sjdp} 325833965Sjdp 325933965Sjdp/* Adjust a symbol defined by a dynamic object and referenced by a 326033965Sjdp regular object. The current definition is in some section of the 326133965Sjdp dynamic object, but we're not including those sections. We have to 326233965Sjdp change the definition to something the rest of the link can 326333965Sjdp understand. */ 326433965Sjdp 326533965Sjdpstatic boolean 326633965Sjdpelf64_alpha_adjust_dynamic_symbol (info, h) 326733965Sjdp struct bfd_link_info *info; 326833965Sjdp struct elf_link_hash_entry *h; 326933965Sjdp{ 327033965Sjdp bfd *dynobj; 327133965Sjdp asection *s; 327233965Sjdp struct alpha_elf_link_hash_entry *ah; 327333965Sjdp 327433965Sjdp dynobj = elf_hash_table(info)->dynobj; 327533965Sjdp ah = (struct alpha_elf_link_hash_entry *)h; 327633965Sjdp 327733965Sjdp /* Now that we've seen all of the input symbols, finalize our decision 327833965Sjdp about whether this symbol should get a .plt entry. */ 327933965Sjdp 328089862Sobrien if (alpha_elf_dynamic_symbol_p (h, info) 328133965Sjdp && ((h->type == STT_FUNC 328233965Sjdp && !(ah->flags & ALPHA_ELF_LINK_HASH_LU_ADDR)) 328333965Sjdp || (h->type == STT_NOTYPE 3284104841Sobrien && (ah->flags & ALPHA_ELF_LINK_HASH_LU_FUNC) 3285104841Sobrien && !(ah->flags & ~ALPHA_ELF_LINK_HASH_LU_FUNC))) 328633965Sjdp /* Don't prevent otherwise valid programs from linking by attempting 328733965Sjdp to create a new .got entry somewhere. A Correct Solution would be 328833965Sjdp to add a new .got section to a new object file and let it be merged 328933965Sjdp somewhere later. But for now don't bother. */ 329033965Sjdp && ah->got_entries) 329133965Sjdp { 329233965Sjdp h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; 329333965Sjdp 329433965Sjdp s = bfd_get_section_by_name(dynobj, ".plt"); 329533965Sjdp if (!s && !elf64_alpha_create_dynamic_sections (dynobj, info)) 329633965Sjdp return false; 329733965Sjdp 329833965Sjdp /* The first bit of the .plt is reserved. */ 329933965Sjdp if (s->_raw_size == 0) 330033965Sjdp s->_raw_size = PLT_HEADER_SIZE; 330133965Sjdp 330260510Sobrien h->plt.offset = s->_raw_size; 330333965Sjdp s->_raw_size += PLT_ENTRY_SIZE; 330433965Sjdp 330533965Sjdp /* If this symbol is not defined in a regular file, and we are not 330633965Sjdp generating a shared library, then set the symbol to the location 330733965Sjdp in the .plt. This is required to make function pointers compare 330833965Sjdp equal between the normal executable and the shared library. */ 330948850Sdfr if (! info->shared 331048850Sdfr && h->root.type != bfd_link_hash_defweak) 331133965Sjdp { 331233965Sjdp h->root.u.def.section = s; 331360510Sobrien h->root.u.def.value = h->plt.offset; 331433965Sjdp } 331533965Sjdp 331633965Sjdp /* We also need a JMP_SLOT entry in the .rela.plt section. */ 331733965Sjdp s = bfd_get_section_by_name (dynobj, ".rela.plt"); 331833965Sjdp BFD_ASSERT (s != NULL); 331933965Sjdp s->_raw_size += sizeof (Elf64_External_Rela); 332033965Sjdp 332133965Sjdp return true; 332233965Sjdp } 332333965Sjdp else 332433965Sjdp h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; 332533965Sjdp 332633965Sjdp /* If this is a weak symbol, and there is a real definition, the 332733965Sjdp processor independent code will have arranged for us to see the 332833965Sjdp real definition first, and we can just use the same value. */ 332933965Sjdp if (h->weakdef != NULL) 333033965Sjdp { 333133965Sjdp BFD_ASSERT (h->weakdef->root.type == bfd_link_hash_defined 333233965Sjdp || h->weakdef->root.type == bfd_link_hash_defweak); 333333965Sjdp h->root.u.def.section = h->weakdef->root.u.def.section; 333433965Sjdp h->root.u.def.value = h->weakdef->root.u.def.value; 333533965Sjdp return true; 333633965Sjdp } 333733965Sjdp 333833965Sjdp /* This is a reference to a symbol defined by a dynamic object which 333933965Sjdp is not a function. The Alpha, since it uses .got entries for all 334033965Sjdp symbols even in regular objects, does not need the hackery of a 334133965Sjdp .dynbss section and COPY dynamic relocations. */ 334233965Sjdp 334333965Sjdp return true; 334433965Sjdp} 334533965Sjdp 334638889Sjdp/* Symbol versioning can create new symbols, and make our old symbols 334738889Sjdp indirect to the new ones. Consolidate the got and reloc information 334838889Sjdp in these situations. */ 334938889Sjdp 335038889Sjdpstatic boolean 335138889Sjdpelf64_alpha_merge_ind_symbols (hi, dummy) 335238889Sjdp struct alpha_elf_link_hash_entry *hi; 335378833Sobrien PTR dummy ATTRIBUTE_UNUSED; 335438889Sjdp{ 335538889Sjdp struct alpha_elf_link_hash_entry *hs; 335638889Sjdp 335738889Sjdp if (hi->root.root.type != bfd_link_hash_indirect) 335838889Sjdp return true; 335938889Sjdp hs = hi; 336038889Sjdp do { 336138889Sjdp hs = (struct alpha_elf_link_hash_entry *)hs->root.root.u.i.link; 336238889Sjdp } while (hs->root.root.type == bfd_link_hash_indirect); 336338889Sjdp 336438889Sjdp /* Merge the flags. Whee. */ 336538889Sjdp 336638889Sjdp hs->flags |= hi->flags; 336738889Sjdp 336838889Sjdp /* Merge the .got entries. Cannibalize the old symbol's list in 336938889Sjdp doing so, since we don't need it anymore. */ 337038889Sjdp 337138889Sjdp if (hs->got_entries == NULL) 337238889Sjdp hs->got_entries = hi->got_entries; 337338889Sjdp else 337438889Sjdp { 337538889Sjdp struct alpha_elf_got_entry *gi, *gs, *gin, *gsh; 337638889Sjdp 337738889Sjdp gsh = hs->got_entries; 337838889Sjdp for (gi = hi->got_entries; gi ; gi = gin) 337938889Sjdp { 338038889Sjdp gin = gi->next; 338138889Sjdp for (gs = gsh; gs ; gs = gs->next) 3382104841Sobrien if (gi->gotobj == gs->gotobj 3383104841Sobrien && gi->reloc_type == gs->reloc_type 3384104841Sobrien && gi->addend == gs->addend) 3385104841Sobrien { 3386104841Sobrien gi->use_count += gs->use_count; 3387104841Sobrien goto got_found; 3388104841Sobrien } 338938889Sjdp gi->next = hs->got_entries; 339038889Sjdp hs->got_entries = gi; 339138889Sjdp got_found:; 339238889Sjdp } 339338889Sjdp } 339438889Sjdp hi->got_entries = NULL; 339538889Sjdp 339638889Sjdp /* And similar for the reloc entries. */ 339738889Sjdp 339838889Sjdp if (hs->reloc_entries == NULL) 339938889Sjdp hs->reloc_entries = hi->reloc_entries; 340038889Sjdp else 340138889Sjdp { 340238889Sjdp struct alpha_elf_reloc_entry *ri, *rs, *rin, *rsh; 340338889Sjdp 340438889Sjdp rsh = hs->reloc_entries; 340538889Sjdp for (ri = hi->reloc_entries; ri ; ri = rin) 340638889Sjdp { 340738889Sjdp rin = ri->next; 340838889Sjdp for (rs = rsh; rs ; rs = rs->next) 3409104841Sobrien if (ri->rtype == rs->rtype && ri->srel == rs->srel) 341038889Sjdp { 341138889Sjdp rs->count += ri->count; 341238889Sjdp goto found_reloc; 341338889Sjdp } 341438889Sjdp ri->next = hs->reloc_entries; 341538889Sjdp hs->reloc_entries = ri; 341638889Sjdp found_reloc:; 341738889Sjdp } 341838889Sjdp } 341938889Sjdp hi->reloc_entries = NULL; 342038889Sjdp 342138889Sjdp return true; 342238889Sjdp} 342338889Sjdp 342433965Sjdp/* Is it possible to merge two object file's .got tables? */ 342533965Sjdp 342633965Sjdpstatic boolean 342733965Sjdpelf64_alpha_can_merge_gots (a, b) 342833965Sjdp bfd *a, *b; 342933965Sjdp{ 3430104841Sobrien int total = alpha_elf_tdata (a)->total_got_size; 343160510Sobrien bfd *bsub; 343233965Sjdp 343333965Sjdp /* Trivial quick fallout test. */ 3434104841Sobrien if (total + alpha_elf_tdata (b)->total_got_size <= MAX_GOT_SIZE) 343533965Sjdp return true; 343633965Sjdp 343733965Sjdp /* By their nature, local .got entries cannot be merged. */ 3438104841Sobrien if ((total += alpha_elf_tdata (b)->local_got_size) > MAX_GOT_SIZE) 343933965Sjdp return false; 344033965Sjdp 344133965Sjdp /* Failing the common trivial comparison, we must effectively 344233965Sjdp perform the merge. Not actually performing the merge means that 344333965Sjdp we don't have to store undo information in case we fail. */ 344460510Sobrien for (bsub = b; bsub ; bsub = alpha_elf_tdata (bsub)->in_got_link_next) 344560510Sobrien { 344660510Sobrien struct alpha_elf_link_hash_entry **hashes = alpha_elf_sym_hashes (bsub); 344760510Sobrien Elf_Internal_Shdr *symtab_hdr = &elf_tdata (bsub)->symtab_hdr; 344860510Sobrien int i, n; 344933965Sjdp 345078833Sobrien n = NUM_SHDR_ENTRIES (symtab_hdr) - symtab_hdr->sh_info; 345160510Sobrien for (i = 0; i < n; ++i) 345260510Sobrien { 345360510Sobrien struct alpha_elf_got_entry *ae, *be; 345460510Sobrien struct alpha_elf_link_hash_entry *h; 345538889Sjdp 345660510Sobrien h = hashes[i]; 345760510Sobrien while (h->root.root.type == bfd_link_hash_indirect 345860510Sobrien || h->root.root.type == bfd_link_hash_warning) 345960510Sobrien h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link; 346038889Sjdp 346160510Sobrien for (be = h->got_entries; be ; be = be->next) 346260510Sobrien { 346360510Sobrien if (be->use_count == 0) 346460510Sobrien continue; 346560510Sobrien if (be->gotobj != b) 346660510Sobrien continue; 346733965Sjdp 346860510Sobrien for (ae = h->got_entries; ae ; ae = ae->next) 3469104841Sobrien if (ae->gotobj == a 3470104841Sobrien && ae->reloc_type == be->reloc_type 3471104841Sobrien && ae->addend == be->addend) 347260510Sobrien goto global_found; 347333965Sjdp 3474104841Sobrien total += alpha_got_entry_size (be->reloc_type); 3475104841Sobrien if (total > MAX_GOT_SIZE) 347660510Sobrien return false; 347760510Sobrien global_found:; 347860510Sobrien } 347960510Sobrien } 348060510Sobrien } 348133965Sjdp 348233965Sjdp return true; 348333965Sjdp} 348433965Sjdp 348533965Sjdp/* Actually merge two .got tables. */ 348633965Sjdp 348733965Sjdpstatic void 348833965Sjdpelf64_alpha_merge_gots (a, b) 348933965Sjdp bfd *a, *b; 349033965Sjdp{ 3491104841Sobrien int total = alpha_elf_tdata (a)->total_got_size; 349260510Sobrien bfd *bsub; 349333965Sjdp 349433965Sjdp /* Remember local expansion. */ 349533965Sjdp { 3496104841Sobrien int e = alpha_elf_tdata (b)->local_got_size; 349733965Sjdp total += e; 3498104841Sobrien alpha_elf_tdata (a)->local_got_size += e; 349933965Sjdp } 350033965Sjdp 350160510Sobrien for (bsub = b; bsub ; bsub = alpha_elf_tdata (bsub)->in_got_link_next) 350260510Sobrien { 350360510Sobrien struct alpha_elf_got_entry **local_got_entries; 350460510Sobrien struct alpha_elf_link_hash_entry **hashes; 350560510Sobrien Elf_Internal_Shdr *symtab_hdr; 350660510Sobrien int i, n; 350733965Sjdp 350860510Sobrien /* Let the local .got entries know they are part of a new subsegment. */ 350960510Sobrien local_got_entries = alpha_elf_tdata (bsub)->local_got_entries; 351060510Sobrien if (local_got_entries) 351160510Sobrien { 351260510Sobrien n = elf_tdata (bsub)->symtab_hdr.sh_info; 351360510Sobrien for (i = 0; i < n; ++i) 351460510Sobrien { 351560510Sobrien struct alpha_elf_got_entry *ent; 351660510Sobrien for (ent = local_got_entries[i]; ent; ent = ent->next) 351760510Sobrien ent->gotobj = a; 351860510Sobrien } 351960510Sobrien } 352033965Sjdp 352160510Sobrien /* Merge the global .got entries. */ 352260510Sobrien hashes = alpha_elf_sym_hashes (bsub); 352360510Sobrien symtab_hdr = &elf_tdata (bsub)->symtab_hdr; 352433965Sjdp 352578833Sobrien n = NUM_SHDR_ENTRIES (symtab_hdr) - symtab_hdr->sh_info; 352660510Sobrien for (i = 0; i < n; ++i) 352760510Sobrien { 352860510Sobrien struct alpha_elf_got_entry *ae, *be, **pbe, **start; 352960510Sobrien struct alpha_elf_link_hash_entry *h; 353038889Sjdp 353160510Sobrien h = hashes[i]; 353260510Sobrien while (h->root.root.type == bfd_link_hash_indirect 353360510Sobrien || h->root.root.type == bfd_link_hash_warning) 353460510Sobrien h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link; 353538889Sjdp 353660510Sobrien start = &h->got_entries; 353760510Sobrien for (pbe = start, be = *start; be ; pbe = &be->next, be = be->next) 353860510Sobrien { 353960510Sobrien if (be->use_count == 0) 354060510Sobrien { 354133965Sjdp *pbe = be->next; 354260510Sobrien continue; 354360510Sobrien } 354460510Sobrien if (be->gotobj != b) 354560510Sobrien continue; 354633965Sjdp 354760510Sobrien for (ae = *start; ae ; ae = ae->next) 3548104841Sobrien if (ae->gotobj == a 3549104841Sobrien && ae->reloc_type == be->reloc_type 3550104841Sobrien && ae->addend == be->addend) 355160510Sobrien { 355260510Sobrien ae->flags |= be->flags; 355360510Sobrien ae->use_count += be->use_count; 355460510Sobrien *pbe = be->next; 355560510Sobrien goto global_found; 355660510Sobrien } 355760510Sobrien be->gotobj = a; 3558104841Sobrien total += alpha_got_entry_size (be->reloc_type); 355960510Sobrien 356060510Sobrien global_found:; 356160510Sobrien } 356260510Sobrien } 356360510Sobrien 356460510Sobrien alpha_elf_tdata (bsub)->gotobj = a; 356560510Sobrien } 3566104841Sobrien alpha_elf_tdata (a)->total_got_size = total; 356760510Sobrien 356860510Sobrien /* Merge the two in_got chains. */ 356960510Sobrien { 357060510Sobrien bfd *next; 357160510Sobrien 357260510Sobrien bsub = a; 357360510Sobrien while ((next = alpha_elf_tdata (bsub)->in_got_link_next) != NULL) 357460510Sobrien bsub = next; 357560510Sobrien 357660510Sobrien alpha_elf_tdata (bsub)->in_got_link_next = b; 357733965Sjdp } 357833965Sjdp} 357933965Sjdp 358033965Sjdp/* Calculate the offsets for the got entries. */ 358133965Sjdp 358233965Sjdpstatic boolean 358333965Sjdpelf64_alpha_calc_got_offsets_for_symbol (h, arg) 358433965Sjdp struct alpha_elf_link_hash_entry *h; 358589862Sobrien PTR arg ATTRIBUTE_UNUSED; 358633965Sjdp{ 358733965Sjdp struct alpha_elf_got_entry *gotent; 358833965Sjdp 358994544Sobrien if (h->root.root.type == bfd_link_hash_warning) 359094544Sobrien h = (struct alpha_elf_link_hash_entry *) h->root.root.u.i.link; 359194544Sobrien 359233965Sjdp for (gotent = h->got_entries; gotent; gotent = gotent->next) 359360510Sobrien if (gotent->use_count > 0) 359460510Sobrien { 359560510Sobrien bfd_size_type *plge 359660510Sobrien = &alpha_elf_tdata (gotent->gotobj)->got->_raw_size; 359733965Sjdp 359860510Sobrien gotent->got_offset = *plge; 3599104841Sobrien *plge += alpha_got_entry_size (gotent->reloc_type); 360060510Sobrien } 360160510Sobrien 360233965Sjdp return true; 360333965Sjdp} 360433965Sjdp 360533965Sjdpstatic void 360633965Sjdpelf64_alpha_calc_got_offsets (info) 360733965Sjdp struct bfd_link_info *info; 360833965Sjdp{ 360933965Sjdp bfd *i, *got_list = alpha_elf_hash_table(info)->got_list; 361033965Sjdp 361133965Sjdp /* First, zero out the .got sizes, as we may be recalculating the 361233965Sjdp .got after optimizing it. */ 361333965Sjdp for (i = got_list; i ; i = alpha_elf_tdata(i)->got_link_next) 361433965Sjdp alpha_elf_tdata(i)->got->_raw_size = 0; 361533965Sjdp 361633965Sjdp /* Next, fill in the offsets for all the global entries. */ 361733965Sjdp alpha_elf_link_hash_traverse (alpha_elf_hash_table (info), 361833965Sjdp elf64_alpha_calc_got_offsets_for_symbol, 361933965Sjdp NULL); 362033965Sjdp 362133965Sjdp /* Finally, fill in the offsets for the local entries. */ 362233965Sjdp for (i = got_list; i ; i = alpha_elf_tdata(i)->got_link_next) 362333965Sjdp { 362433965Sjdp bfd_size_type got_offset = alpha_elf_tdata(i)->got->_raw_size; 362533965Sjdp bfd *j; 362633965Sjdp 362733965Sjdp for (j = i; j ; j = alpha_elf_tdata(j)->in_got_link_next) 362833965Sjdp { 362933965Sjdp struct alpha_elf_got_entry **local_got_entries, *gotent; 363033965Sjdp int k, n; 363133965Sjdp 363233965Sjdp local_got_entries = alpha_elf_tdata(j)->local_got_entries; 363333965Sjdp if (!local_got_entries) 363433965Sjdp continue; 363533965Sjdp 363633965Sjdp for (k = 0, n = elf_tdata(j)->symtab_hdr.sh_info; k < n; ++k) 363733965Sjdp for (gotent = local_got_entries[k]; gotent; gotent = gotent->next) 363860510Sobrien if (gotent->use_count > 0) 363960510Sobrien { 364060510Sobrien gotent->got_offset = got_offset; 3641104841Sobrien got_offset += alpha_got_entry_size (gotent->reloc_type); 364260510Sobrien } 364333965Sjdp } 364433965Sjdp 364533965Sjdp alpha_elf_tdata(i)->got->_raw_size = got_offset; 364660510Sobrien alpha_elf_tdata(i)->got->_cooked_size = got_offset; 364733965Sjdp } 364833965Sjdp} 364933965Sjdp 365033965Sjdp/* Constructs the gots. */ 365133965Sjdp 365233965Sjdpstatic boolean 3653104841Sobrienelf64_alpha_size_got_sections (info) 365433965Sjdp struct bfd_link_info *info; 365533965Sjdp{ 365689862Sobrien bfd *i, *got_list, *cur_got_obj = NULL; 365760510Sobrien int something_changed = 0; 365833965Sjdp 365960510Sobrien got_list = alpha_elf_hash_table (info)->got_list; 366033965Sjdp 366160510Sobrien /* On the first time through, pretend we have an existing got list 366260510Sobrien consisting of all of the input files. */ 366360510Sobrien if (got_list == NULL) 366433965Sjdp { 366560510Sobrien for (i = info->input_bfds; i ; i = i->link_next) 366660510Sobrien { 366760510Sobrien bfd *this_got = alpha_elf_tdata (i)->gotobj; 366860510Sobrien if (this_got == NULL) 366960510Sobrien continue; 367033965Sjdp 367160510Sobrien /* We are assuming no merging has yet ocurred. */ 367260510Sobrien BFD_ASSERT (this_got == i); 367333965Sjdp 3674104841Sobrien if (alpha_elf_tdata (this_got)->total_got_size > MAX_GOT_SIZE) 367533965Sjdp { 367660510Sobrien /* Yikes! A single object file has too many entries. */ 367760510Sobrien (*_bfd_error_handler) 367860510Sobrien (_("%s: .got subsegment exceeds 64K (size %d)"), 367989862Sobrien bfd_archive_filename (i), 3680104841Sobrien alpha_elf_tdata (this_got)->total_got_size); 368160510Sobrien return false; 368233965Sjdp } 368360510Sobrien 368460510Sobrien if (got_list == NULL) 368560510Sobrien got_list = this_got; 368633965Sjdp else 368760510Sobrien alpha_elf_tdata(cur_got_obj)->got_link_next = this_got; 368860510Sobrien cur_got_obj = this_got; 368933965Sjdp } 369060510Sobrien 369160510Sobrien /* Strange degenerate case of no got references. */ 369260510Sobrien if (got_list == NULL) 369360510Sobrien return true; 369460510Sobrien 369560510Sobrien alpha_elf_hash_table (info)->got_list = got_list; 369660510Sobrien 369760510Sobrien /* Force got offsets to be recalculated. */ 369860510Sobrien something_changed = 1; 369960510Sobrien } 370060510Sobrien 370160510Sobrien cur_got_obj = got_list; 370260510Sobrien i = alpha_elf_tdata(cur_got_obj)->got_link_next; 370360510Sobrien while (i != NULL) 370460510Sobrien { 370560510Sobrien if (elf64_alpha_can_merge_gots (cur_got_obj, i)) 370660510Sobrien { 370760510Sobrien elf64_alpha_merge_gots (cur_got_obj, i); 370860510Sobrien i = alpha_elf_tdata(i)->got_link_next; 370960510Sobrien alpha_elf_tdata(cur_got_obj)->got_link_next = i; 371060510Sobrien something_changed = 1; 371160510Sobrien } 371233965Sjdp else 371333965Sjdp { 371433965Sjdp cur_got_obj = i; 371560510Sobrien i = alpha_elf_tdata(i)->got_link_next; 371633965Sjdp } 371733965Sjdp } 371833965Sjdp 371960510Sobrien /* Once the gots have been merged, fill in the got offsets for 372060510Sobrien everything therein. */ 372160510Sobrien if (1 || something_changed) 372260510Sobrien elf64_alpha_calc_got_offsets (info); 372333965Sjdp 372460510Sobrien return true; 372560510Sobrien} 372633965Sjdp 3727104841Sobrien/* Called from relax_section to rebuild the PLT in light of 3728104841Sobrien potential changes in the function's status. */ 3729104841Sobrien 373060510Sobrienstatic boolean 3731104841Sobrienelf64_alpha_size_plt_section (info) 3732104841Sobrien struct bfd_link_info *info; 3733104841Sobrien{ 3734104841Sobrien asection *splt, *spltrel; 3735104841Sobrien unsigned long entries; 3736104841Sobrien bfd *dynobj; 3737104841Sobrien 3738104841Sobrien dynobj = elf_hash_table(info)->dynobj; 3739104841Sobrien splt = bfd_get_section_by_name(dynobj, ".plt"); 3740104841Sobrien if (splt == NULL) 3741104841Sobrien return true; 3742104841Sobrien 3743104841Sobrien splt->_raw_size = 0; 3744104841Sobrien 3745104841Sobrien alpha_elf_link_hash_traverse (alpha_elf_hash_table (info), 3746104841Sobrien elf64_alpha_size_plt_section_1, splt); 3747104841Sobrien 3748104841Sobrien splt->_cooked_size = splt->_raw_size; 3749104841Sobrien 3750104841Sobrien /* Every plt entry requires a JMP_SLOT relocation. */ 3751104841Sobrien spltrel = bfd_get_section_by_name (dynobj, ".rela.plt"); 3752104841Sobrien if (splt->_raw_size) 3753104841Sobrien entries = (splt->_raw_size - PLT_HEADER_SIZE) / PLT_ENTRY_SIZE; 3754104841Sobrien else 3755104841Sobrien entries = 0; 3756104841Sobrien spltrel->_raw_size = entries * sizeof (Elf64_External_Rela); 3757104841Sobrien spltrel->_cooked_size = spltrel->_raw_size; 3758104841Sobrien 3759104841Sobrien return true; 3760104841Sobrien} 3761104841Sobrien 3762104841Sobrienstatic boolean 3763104841Sobrienelf64_alpha_size_plt_section_1 (h, data) 3764104841Sobrien struct alpha_elf_link_hash_entry *h; 3765104841Sobrien PTR data; 3766104841Sobrien{ 3767104841Sobrien asection *splt = (asection *) data; 3768104841Sobrien struct alpha_elf_got_entry *gotent; 3769104841Sobrien 3770104841Sobrien /* If we didn't need an entry before, we still don't. */ 3771104841Sobrien if (!(h->root.elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT)) 3772104841Sobrien return true; 3773104841Sobrien 3774104841Sobrien /* There must still be a LITERAL got entry for the function. */ 3775104841Sobrien for (gotent = h->got_entries; gotent ; gotent = gotent->next) 3776104841Sobrien if (gotent->reloc_type == R_ALPHA_LITERAL 3777104841Sobrien && gotent->use_count > 0) 3778104841Sobrien break; 3779104841Sobrien 3780104841Sobrien /* If there is, reset the PLT offset. If not, there's no longer 3781104841Sobrien a need for the PLT entry. */ 3782104841Sobrien if (gotent) 3783104841Sobrien { 3784104841Sobrien if (splt->_raw_size == 0) 3785104841Sobrien splt->_raw_size = PLT_HEADER_SIZE; 3786104841Sobrien h->root.plt.offset = splt->_raw_size; 3787104841Sobrien splt->_raw_size += PLT_ENTRY_SIZE; 3788104841Sobrien } 3789104841Sobrien else 3790104841Sobrien { 3791104841Sobrien h->root.elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; 3792104841Sobrien h->root.plt.offset = -1; 3793104841Sobrien } 3794104841Sobrien 3795104841Sobrien return true; 3796104841Sobrien} 3797104841Sobrien 3798104841Sobrienstatic boolean 379960510Sobrienelf64_alpha_always_size_sections (output_bfd, info) 3800104841Sobrien bfd *output_bfd ATTRIBUTE_UNUSED; 380160510Sobrien struct bfd_link_info *info; 380260510Sobrien{ 380360510Sobrien bfd *i; 380460510Sobrien 380560510Sobrien if (info->relocateable) 380660510Sobrien return true; 380760510Sobrien 380860510Sobrien /* First, take care of the indirect symbols created by versioning. */ 380960510Sobrien alpha_elf_link_hash_traverse (alpha_elf_hash_table (info), 381060510Sobrien elf64_alpha_merge_ind_symbols, 381160510Sobrien NULL); 381260510Sobrien 3813104841Sobrien if (!elf64_alpha_size_got_sections (info)) 381460510Sobrien return false; 381560510Sobrien 381633965Sjdp /* Allocate space for all of the .got subsections. */ 381760510Sobrien i = alpha_elf_hash_table (info)->got_list; 381860510Sobrien for ( ; i ; i = alpha_elf_tdata(i)->got_link_next) 381933965Sjdp { 382033965Sjdp asection *s = alpha_elf_tdata(i)->got; 382133965Sjdp if (s->_raw_size > 0) 382233965Sjdp { 382333965Sjdp s->contents = (bfd_byte *) bfd_zalloc (i, s->_raw_size); 382433965Sjdp if (s->contents == NULL) 382533965Sjdp return false; 382633965Sjdp } 382733965Sjdp } 382833965Sjdp 382933965Sjdp return true; 383033965Sjdp} 383133965Sjdp 3832104841Sobrien/* The number of dynamic relocations required by a static relocation. */ 3833104841Sobrien 3834104841Sobrienstatic int 3835104841Sobrienalpha_dynamic_entries_for_reloc (r_type, dynamic, shared) 3836104841Sobrien int r_type, dynamic, shared; 3837104841Sobrien{ 3838104841Sobrien switch (r_type) 3839104841Sobrien { 3840104841Sobrien /* May appear in GOT entries. */ 3841104841Sobrien case R_ALPHA_TLSGD: 3842104841Sobrien return (dynamic ? 2 : shared ? 1 : 0); 3843104841Sobrien case R_ALPHA_TLSLDM: 3844104841Sobrien return shared; 3845104841Sobrien case R_ALPHA_LITERAL: 3846104841Sobrien return dynamic || shared; 3847104841Sobrien case R_ALPHA_GOTDTPREL: 3848104841Sobrien case R_ALPHA_GOTTPREL: 3849104841Sobrien return dynamic; 3850104841Sobrien 3851104841Sobrien /* May appear in data sections. */ 3852104841Sobrien case R_ALPHA_REFLONG: 3853104841Sobrien case R_ALPHA_REFQUAD: 3854104841Sobrien return dynamic || shared; 3855104841Sobrien case R_ALPHA_SREL64: 3856104841Sobrien case R_ALPHA_TPREL64: 3857104841Sobrien return dynamic; 3858104841Sobrien 3859104841Sobrien /* Everything else is illegal. We'll issue an error during 3860104841Sobrien relocate_section. */ 3861104841Sobrien default: 3862104841Sobrien return 0; 3863104841Sobrien } 3864104841Sobrien} 3865104841Sobrien 386633965Sjdp/* Work out the sizes of the dynamic relocation entries. */ 386733965Sjdp 386833965Sjdpstatic boolean 386933965Sjdpelf64_alpha_calc_dynrel_sizes (h, info) 387033965Sjdp struct alpha_elf_link_hash_entry *h; 387133965Sjdp struct bfd_link_info *info; 387233965Sjdp{ 3873104841Sobrien boolean dynamic; 3874104841Sobrien struct alpha_elf_reloc_entry *relent; 3875104841Sobrien unsigned long entries; 3876104841Sobrien 387794544Sobrien if (h->root.root.type == bfd_link_hash_warning) 387894544Sobrien h = (struct alpha_elf_link_hash_entry *) h->root.root.u.i.link; 387994544Sobrien 388033965Sjdp /* If the symbol was defined as a common symbol in a regular object 388133965Sjdp file, and there was no definition in any dynamic object, then the 388233965Sjdp linker will have allocated space for the symbol in a common 388333965Sjdp section but the ELF_LINK_HASH_DEF_REGULAR flag will not have been 388433965Sjdp set. This is done for dynamic symbols in 388533965Sjdp elf_adjust_dynamic_symbol but this is not done for non-dynamic 388633965Sjdp symbols, somehow. */ 388733965Sjdp if (((h->root.elf_link_hash_flags 388833965Sjdp & (ELF_LINK_HASH_DEF_REGULAR 388933965Sjdp | ELF_LINK_HASH_REF_REGULAR 389033965Sjdp | ELF_LINK_HASH_DEF_DYNAMIC)) 389133965Sjdp == ELF_LINK_HASH_REF_REGULAR) 389233965Sjdp && (h->root.root.type == bfd_link_hash_defined 389333965Sjdp || h->root.root.type == bfd_link_hash_defweak) 389433965Sjdp && !(h->root.root.u.def.section->owner->flags & DYNAMIC)) 3895104841Sobrien h->root.elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR; 389633965Sjdp 389733965Sjdp /* If the symbol is dynamic, we'll need all the relocations in their 389860510Sobrien natural form. If this is a shared object, and it has been forced 389960510Sobrien local, we'll need the same number of RELATIVE relocations. */ 390060510Sobrien 3901104841Sobrien dynamic = alpha_elf_dynamic_symbol_p (&h->root, info); 3902104841Sobrien 3903104841Sobrien for (relent = h->reloc_entries; relent; relent = relent->next) 390433965Sjdp { 3905104841Sobrien entries = alpha_dynamic_entries_for_reloc (relent->rtype, dynamic, 3906104841Sobrien info->shared); 3907104841Sobrien if (entries) 3908104841Sobrien { 3909104841Sobrien relent->srel->_raw_size += 3910104841Sobrien entries * sizeof (Elf64_External_Rela) * relent->count; 3911104841Sobrien if (relent->reltext) 3912104841Sobrien info->flags |= DT_TEXTREL; 3913104841Sobrien } 3914104841Sobrien } 391533965Sjdp 3916104841Sobrien return true; 3917104841Sobrien} 391833965Sjdp 3919104841Sobrien/* Set the sizes of the dynamic relocation sections. */ 392048850Sdfr 3921104841Sobrienstatic boolean 3922104841Sobrienelf64_alpha_size_rela_got_section (info) 3923104841Sobrien struct bfd_link_info *info; 3924104841Sobrien{ 3925104841Sobrien unsigned long entries; 3926104841Sobrien bfd *i, *dynobj; 3927104841Sobrien asection *srel; 392848850Sdfr 3929104841Sobrien /* Shared libraries often require RELATIVE relocs, and some relocs 3930104841Sobrien require attention for the main application as well. */ 393148850Sdfr 3932104841Sobrien entries = 0; 3933104841Sobrien for (i = alpha_elf_hash_table(info)->got_list; 3934104841Sobrien i ; i = alpha_elf_tdata(i)->got_link_next) 3935104841Sobrien { 3936104841Sobrien bfd *j; 3937104841Sobrien 3938104841Sobrien for (j = i; j ; j = alpha_elf_tdata(j)->in_got_link_next) 393933965Sjdp { 3940104841Sobrien struct alpha_elf_got_entry **local_got_entries, *gotent; 3941104841Sobrien int k, n; 3942104841Sobrien 3943104841Sobrien local_got_entries = alpha_elf_tdata(j)->local_got_entries; 3944104841Sobrien if (!local_got_entries) 3945104841Sobrien continue; 3946104841Sobrien 3947104841Sobrien for (k = 0, n = elf_tdata(j)->symtab_hdr.sh_info; k < n; ++k) 3948104841Sobrien for (gotent = local_got_entries[k]; 3949104841Sobrien gotent ; gotent = gotent->next) 3950104841Sobrien if (gotent->use_count > 0) 3951104841Sobrien entries += (alpha_dynamic_entries_for_reloc 3952104841Sobrien (gotent->reloc_type, 0, info->shared)); 395333965Sjdp } 395433965Sjdp } 395548850Sdfr 3956104841Sobrien dynobj = elf_hash_table(info)->dynobj; 3957104841Sobrien srel = bfd_get_section_by_name (dynobj, ".rela.got"); 3958104841Sobrien if (!srel) 3959104841Sobrien { 3960104841Sobrien BFD_ASSERT (entries == 0); 3961104841Sobrien return true; 3962104841Sobrien } 3963104841Sobrien srel->_raw_size = sizeof (Elf64_External_Rela) * entries; 3964104841Sobrien 3965104841Sobrien /* Now do the non-local symbols. */ 3966104841Sobrien alpha_elf_link_hash_traverse (alpha_elf_hash_table (info), 3967104841Sobrien elf64_alpha_size_rela_got_1, info); 3968104841Sobrien 3969104841Sobrien srel->_cooked_size = srel->_raw_size; 3970104841Sobrien 397133965Sjdp return true; 397233965Sjdp} 397333965Sjdp 3974104841Sobrien/* Subroutine of elf64_alpha_size_rela_got_section for doing the 3975104841Sobrien global symbols. */ 3976104841Sobrien 3977104841Sobrienstatic boolean 3978104841Sobrienelf64_alpha_size_rela_got_1 (h, info) 3979104841Sobrien struct alpha_elf_link_hash_entry *h; 3980104841Sobrien struct bfd_link_info *info; 3981104841Sobrien{ 3982104841Sobrien boolean dynamic; 3983104841Sobrien struct alpha_elf_got_entry *gotent; 3984104841Sobrien unsigned long entries; 3985104841Sobrien 3986104841Sobrien if (h->root.root.type == bfd_link_hash_warning) 3987104841Sobrien h = (struct alpha_elf_link_hash_entry *) h->root.root.u.i.link; 3988104841Sobrien 3989104841Sobrien /* If the symbol is dynamic, we'll need all the relocations in their 3990104841Sobrien natural form. If this is a shared object, and it has been forced 3991104841Sobrien local, we'll need the same number of RELATIVE relocations. */ 3992104841Sobrien 3993104841Sobrien dynamic = alpha_elf_dynamic_symbol_p (&h->root, info); 3994104841Sobrien 3995104841Sobrien entries = 0; 3996104841Sobrien for (gotent = h->got_entries; gotent ; gotent = gotent->next) 3997104841Sobrien if (gotent->use_count > 0) 3998104841Sobrien entries += alpha_dynamic_entries_for_reloc (gotent->reloc_type, 3999104841Sobrien dynamic, info->shared); 4000104841Sobrien 4001104841Sobrien /* If we are using a .plt entry, subtract one, as the first 4002104841Sobrien reference uses a .rela.plt entry instead. */ 4003104841Sobrien if (h->root.plt.offset != MINUS_ONE) 4004104841Sobrien entries--; 4005104841Sobrien 4006104841Sobrien if (entries > 0) 4007104841Sobrien { 4008104841Sobrien bfd *dynobj = elf_hash_table(info)->dynobj; 4009104841Sobrien asection *srel = bfd_get_section_by_name (dynobj, ".rela.got"); 4010104841Sobrien BFD_ASSERT (srel != NULL); 4011104841Sobrien srel->_raw_size += sizeof (Elf64_External_Rela) * entries; 4012104841Sobrien } 4013104841Sobrien 4014104841Sobrien return true; 4015104841Sobrien} 4016104841Sobrien 401733965Sjdp/* Set the sizes of the dynamic sections. */ 401833965Sjdp 401933965Sjdpstatic boolean 402033965Sjdpelf64_alpha_size_dynamic_sections (output_bfd, info) 402189862Sobrien bfd *output_bfd ATTRIBUTE_UNUSED; 402233965Sjdp struct bfd_link_info *info; 402333965Sjdp{ 402433965Sjdp bfd *dynobj; 402533965Sjdp asection *s; 402633965Sjdp boolean relplt; 402733965Sjdp 402833965Sjdp dynobj = elf_hash_table(info)->dynobj; 402933965Sjdp BFD_ASSERT(dynobj != NULL); 403033965Sjdp 403133965Sjdp if (elf_hash_table (info)->dynamic_sections_created) 403233965Sjdp { 403333965Sjdp /* Set the contents of the .interp section to the interpreter. */ 403433965Sjdp if (!info->shared) 403533965Sjdp { 403633965Sjdp s = bfd_get_section_by_name (dynobj, ".interp"); 403733965Sjdp BFD_ASSERT (s != NULL); 403833965Sjdp s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER; 403933965Sjdp s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER; 404033965Sjdp } 404133965Sjdp 404233965Sjdp /* Now that we've seen all of the input files, we can decide which 404333965Sjdp symbols need dynamic relocation entries and which don't. We've 404433965Sjdp collected information in check_relocs that we can now apply to 404533965Sjdp size the dynamic relocation sections. */ 404633965Sjdp alpha_elf_link_hash_traverse (alpha_elf_hash_table (info), 4047104841Sobrien elf64_alpha_calc_dynrel_sizes, info); 404833965Sjdp 4049104841Sobrien elf64_alpha_size_rela_got_section (info); 405033965Sjdp } 405133965Sjdp /* else we're not dynamic and by definition we don't need such things. */ 405233965Sjdp 405333965Sjdp /* The check_relocs and adjust_dynamic_symbol entry points have 405433965Sjdp determined the sizes of the various dynamic sections. Allocate 405533965Sjdp memory for them. */ 405633965Sjdp relplt = false; 405733965Sjdp for (s = dynobj->sections; s != NULL; s = s->next) 405833965Sjdp { 405933965Sjdp const char *name; 406033965Sjdp boolean strip; 406133965Sjdp 406233965Sjdp if (!(s->flags & SEC_LINKER_CREATED)) 406333965Sjdp continue; 406433965Sjdp 406533965Sjdp /* It's OK to base decisions on the section name, because none 406633965Sjdp of the dynobj section names depend upon the input files. */ 406733965Sjdp name = bfd_get_section_name (dynobj, s); 406833965Sjdp 406933965Sjdp /* If we don't need this section, strip it from the output file. 407033965Sjdp This is to handle .rela.bss and .rela.plt. We must create it 407133965Sjdp in create_dynamic_sections, because it must be created before 407233965Sjdp the linker maps input sections to output sections. The 407333965Sjdp linker does that before adjust_dynamic_symbol is called, and 407433965Sjdp it is that function which decides whether anything needs to 407533965Sjdp go into these sections. */ 407633965Sjdp 407733965Sjdp strip = false; 407833965Sjdp 407933965Sjdp if (strncmp (name, ".rela", 5) == 0) 408033965Sjdp { 408133965Sjdp strip = (s->_raw_size == 0); 408233965Sjdp 408333965Sjdp if (!strip) 408433965Sjdp { 408533965Sjdp if (strcmp(name, ".rela.plt") == 0) 408633965Sjdp relplt = true; 408733965Sjdp 408833965Sjdp /* We use the reloc_count field as a counter if we need 408933965Sjdp to copy relocs into the output file. */ 409033965Sjdp s->reloc_count = 0; 409133965Sjdp } 409233965Sjdp } 409333965Sjdp else if (strcmp (name, ".plt") != 0) 409433965Sjdp { 409533965Sjdp /* It's not one of our dynamic sections, so don't allocate space. */ 409633965Sjdp continue; 409733965Sjdp } 409833965Sjdp 409933965Sjdp if (strip) 410060510Sobrien _bfd_strip_section_from_output (info, s); 410133965Sjdp else 410233965Sjdp { 410333965Sjdp /* Allocate memory for the section contents. */ 410489862Sobrien s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size); 410533965Sjdp if (s->contents == NULL && s->_raw_size != 0) 410633965Sjdp return false; 410733965Sjdp } 410833965Sjdp } 410933965Sjdp 411033965Sjdp if (elf_hash_table (info)->dynamic_sections_created) 411133965Sjdp { 411233965Sjdp /* Add some entries to the .dynamic section. We fill in the 411333965Sjdp values later, in elf64_alpha_finish_dynamic_sections, but we 411433965Sjdp must add the entries now so that we get the correct size for 411533965Sjdp the .dynamic section. The DT_DEBUG entry is filled in by the 411633965Sjdp dynamic linker and used by the debugger. */ 411789862Sobrien#define add_dynamic_entry(TAG, VAL) \ 411889862Sobrien bfd_elf64_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL)) 411989862Sobrien 412033965Sjdp if (!info->shared) 412133965Sjdp { 412289862Sobrien if (!add_dynamic_entry (DT_DEBUG, 0)) 412333965Sjdp return false; 412433965Sjdp } 412533965Sjdp 412633965Sjdp if (relplt) 412733965Sjdp { 4128102735Sobrien if (!add_dynamic_entry (DT_PLTGOT, 0) 4129102735Sobrien || !add_dynamic_entry (DT_PLTRELSZ, 0) 413089862Sobrien || !add_dynamic_entry (DT_PLTREL, DT_RELA) 413189862Sobrien || !add_dynamic_entry (DT_JMPREL, 0)) 413233965Sjdp return false; 413333965Sjdp } 413433965Sjdp 413589862Sobrien if (!add_dynamic_entry (DT_RELA, 0) 413689862Sobrien || !add_dynamic_entry (DT_RELASZ, 0) 413789862Sobrien || !add_dynamic_entry (DT_RELAENT, sizeof (Elf64_External_Rela))) 413833965Sjdp return false; 413933965Sjdp 414089862Sobrien if (info->flags & DF_TEXTREL) 414133965Sjdp { 414289862Sobrien if (!add_dynamic_entry (DT_TEXTREL, 0)) 414333965Sjdp return false; 414433965Sjdp } 414533965Sjdp } 414689862Sobrien#undef add_dynamic_entry 414733965Sjdp 414833965Sjdp return true; 414933965Sjdp} 415033965Sjdp 4151104841Sobrien/* Relocate an Alpha ELF section for a relocatable link. 4152104841Sobrien 4153104841Sobrien We don't have to change anything unless the reloc is against a section 4154104841Sobrien symbol, in which case we have to adjust according to where the section 4155104841Sobrien symbol winds up in the output section. */ 4156104841Sobrien 4157104841Sobrienstatic boolean 4158104841Sobrienelf64_alpha_relocate_section_r (output_bfd, info, input_bfd, input_section, 4159104841Sobrien contents, relocs, local_syms, local_sections) 4160104841Sobrien bfd *output_bfd ATTRIBUTE_UNUSED; 4161104841Sobrien struct bfd_link_info *info ATTRIBUTE_UNUSED; 4162104841Sobrien bfd *input_bfd; 4163104841Sobrien asection *input_section; 4164104841Sobrien bfd_byte *contents ATTRIBUTE_UNUSED; 4165104841Sobrien Elf_Internal_Rela *relocs; 4166104841Sobrien Elf_Internal_Sym *local_syms; 4167104841Sobrien asection **local_sections; 4168104841Sobrien{ 4169104841Sobrien unsigned long symtab_hdr_sh_info; 4170104841Sobrien Elf_Internal_Rela *rel; 4171104841Sobrien Elf_Internal_Rela *relend; 4172104841Sobrien boolean ret_val = true; 4173104841Sobrien 4174104841Sobrien symtab_hdr_sh_info = elf_tdata (input_bfd)->symtab_hdr.sh_info; 4175104841Sobrien 4176104841Sobrien relend = relocs + input_section->reloc_count; 4177104841Sobrien for (rel = relocs; rel < relend; rel++) 4178104841Sobrien { 4179104841Sobrien unsigned long r_symndx; 4180104841Sobrien Elf_Internal_Sym *sym; 4181104841Sobrien asection *sec; 4182104841Sobrien unsigned long r_type; 4183104841Sobrien 4184104841Sobrien r_type = ELF64_R_TYPE(rel->r_info); 4185104841Sobrien if (r_type >= R_ALPHA_max) 4186104841Sobrien { 4187104841Sobrien (*_bfd_error_handler) 4188104841Sobrien (_("%s: unknown relocation type %d"), 4189104841Sobrien bfd_archive_filename (input_bfd), (int)r_type); 4190104841Sobrien bfd_set_error (bfd_error_bad_value); 4191104841Sobrien ret_val = false; 4192104841Sobrien continue; 4193104841Sobrien } 4194104841Sobrien 4195104841Sobrien r_symndx = ELF64_R_SYM(rel->r_info); 4196104841Sobrien 4197104841Sobrien /* The symbol associated with GPDISP and LITUSE is 4198104841Sobrien immaterial. Only the addend is significant. */ 4199104841Sobrien if (r_type == R_ALPHA_GPDISP || r_type == R_ALPHA_LITUSE) 4200104841Sobrien continue; 4201104841Sobrien 4202104841Sobrien if (r_symndx < symtab_hdr_sh_info) 4203104841Sobrien { 4204104841Sobrien sym = local_syms + r_symndx; 4205104841Sobrien if (ELF_ST_TYPE(sym->st_info) == STT_SECTION) 4206104841Sobrien { 4207104841Sobrien sec = local_sections[r_symndx]; 4208104841Sobrien rel->r_addend += sec->output_offset + sym->st_value; 4209104841Sobrien } 4210104841Sobrien } 4211104841Sobrien } 4212104841Sobrien 4213104841Sobrien return ret_val; 4214104841Sobrien} 4215104841Sobrien 421633965Sjdp/* Relocate an Alpha ELF section. */ 421733965Sjdp 421833965Sjdpstatic boolean 421933965Sjdpelf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section, 422033965Sjdp contents, relocs, local_syms, local_sections) 422133965Sjdp bfd *output_bfd; 422233965Sjdp struct bfd_link_info *info; 422333965Sjdp bfd *input_bfd; 422433965Sjdp asection *input_section; 422533965Sjdp bfd_byte *contents; 422633965Sjdp Elf_Internal_Rela *relocs; 422733965Sjdp Elf_Internal_Sym *local_syms; 422833965Sjdp asection **local_sections; 422933965Sjdp{ 423033965Sjdp Elf_Internal_Shdr *symtab_hdr; 423133965Sjdp Elf_Internal_Rela *rel; 423233965Sjdp Elf_Internal_Rela *relend; 4233104841Sobrien struct elf_link_tls_segment *tls_segment; 4234104841Sobrien asection *sgot, *srel, *srelgot; 423533965Sjdp bfd *dynobj, *gotobj; 4236104841Sobrien bfd_vma gp, tp_base, dtp_base; 4237104841Sobrien struct alpha_elf_got_entry **local_got_entries; 4238104841Sobrien boolean ret_val; 4239104841Sobrien const char *section_name; 424033965Sjdp 4241104841Sobrien /* Handle relocatable links with a smaller loop. */ 4242104841Sobrien if (info->relocateable) 4243104841Sobrien return elf64_alpha_relocate_section_r (output_bfd, info, input_bfd, 4244104841Sobrien input_section, contents, relocs, 4245104841Sobrien local_syms, local_sections); 4246104841Sobrien 4247104841Sobrien /* This is a final link. */ 4248104841Sobrien 4249104841Sobrien ret_val = true; 4250104841Sobrien 425133965Sjdp symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; 4252104841Sobrien 425333965Sjdp dynobj = elf_hash_table (info)->dynobj; 425433965Sjdp if (dynobj) 4255104841Sobrien srelgot = bfd_get_section_by_name (dynobj, ".rela.got"); 4256104841Sobrien else 4257104841Sobrien srelgot = NULL; 425833965Sjdp 4259104841Sobrien section_name = (bfd_elf_string_from_elf_section 4260104841Sobrien (input_bfd, elf_elfheader(input_bfd)->e_shstrndx, 4261104841Sobrien elf_section_data(input_section)->rel_hdr.sh_name)); 4262104841Sobrien BFD_ASSERT(section_name != NULL); 4263104841Sobrien srel = bfd_get_section_by_name (dynobj, section_name); 4264104841Sobrien 426533965Sjdp /* Find the gp value for this input bfd. */ 426633965Sjdp gotobj = alpha_elf_tdata (input_bfd)->gotobj; 426733965Sjdp if (gotobj) 426833965Sjdp { 426933965Sjdp sgot = alpha_elf_tdata (gotobj)->got; 427033965Sjdp gp = _bfd_get_gp_value (gotobj); 427133965Sjdp if (gp == 0) 427233965Sjdp { 427333965Sjdp gp = (sgot->output_section->vma 427433965Sjdp + sgot->output_offset 427533965Sjdp + 0x8000); 427633965Sjdp _bfd_set_gp_value (gotobj, gp); 427733965Sjdp } 427833965Sjdp } 4279104841Sobrien else 4280104841Sobrien { 4281104841Sobrien sgot = NULL; 4282104841Sobrien gp = 0; 4283104841Sobrien } 428433965Sjdp 4285104841Sobrien local_got_entries = alpha_elf_tdata(input_bfd)->local_got_entries; 4286104841Sobrien 4287104841Sobrien tls_segment = elf_hash_table (info)->tls_segment; 4288104841Sobrien if (tls_segment) 4289104841Sobrien { 4290104841Sobrien dtp_base = alpha_get_dtprel_base (tls_segment); 4291104841Sobrien tp_base = alpha_get_tprel_base (tls_segment); 4292104841Sobrien } 4293104841Sobrien else 4294104841Sobrien dtp_base = tp_base = 0; 4295104841Sobrien 429633965Sjdp relend = relocs + input_section->reloc_count; 4297104841Sobrien for (rel = relocs; rel < relend; rel++) 429833965Sjdp { 4299104841Sobrien struct alpha_elf_link_hash_entry *h = NULL; 4300104841Sobrien struct alpha_elf_got_entry *gotent; 4301104841Sobrien bfd_reloc_status_type r; 430233965Sjdp reloc_howto_type *howto; 430333965Sjdp unsigned long r_symndx; 4304104841Sobrien Elf_Internal_Sym *sym = NULL; 4305104841Sobrien asection *sec = NULL; 4306104841Sobrien bfd_vma value; 430733965Sjdp bfd_vma addend; 4308104841Sobrien boolean dynamic_symbol_p; 4309104841Sobrien boolean undef_weak_ref = false; 4310104841Sobrien unsigned long r_type; 431133965Sjdp 431233965Sjdp r_type = ELF64_R_TYPE(rel->r_info); 4313104841Sobrien if (r_type >= R_ALPHA_max) 431433965Sjdp { 4315104841Sobrien (*_bfd_error_handler) 4316104841Sobrien (_("%s: unknown relocation type %d"), 4317104841Sobrien bfd_archive_filename (input_bfd), (int)r_type); 431833965Sjdp bfd_set_error (bfd_error_bad_value); 4319104841Sobrien ret_val = false; 4320104841Sobrien continue; 432133965Sjdp } 4322104841Sobrien 432333965Sjdp howto = elf64_alpha_howto_table + r_type; 432433965Sjdp r_symndx = ELF64_R_SYM(rel->r_info); 432533965Sjdp 4326104841Sobrien if (r_symndx < symtab_hdr->sh_info) 432733965Sjdp { 4328104841Sobrien sym = local_syms + r_symndx; 4329104841Sobrien sec = local_sections[r_symndx]; 4330104841Sobrien value = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel); 433160510Sobrien 4332104841Sobrien if (local_got_entries) 4333104841Sobrien gotent = local_got_entries[r_symndx]; 4334104841Sobrien else 4335104841Sobrien gotent = NULL; 433660510Sobrien 4337104841Sobrien /* Need to adjust local GOT entries' addends for SEC_MERGE 4338104841Sobrien unless it has been done already. */ 4339104841Sobrien if ((sec->flags & SEC_MERGE) 4340104841Sobrien && ELF_ST_TYPE (sym->st_info) == STT_SECTION 4341104841Sobrien && (elf_section_data (sec)->sec_info_type 4342104841Sobrien == ELF_INFO_TYPE_MERGE) 4343104841Sobrien && gotent 4344104841Sobrien && !gotent->reloc_xlated) 434533965Sjdp { 4346104841Sobrien struct alpha_elf_got_entry *ent; 4347104841Sobrien asection *msec; 4348104841Sobrien 4349104841Sobrien for (ent = gotent; ent; ent = ent->next) 435033965Sjdp { 4351104841Sobrien ent->reloc_xlated = 1; 4352104841Sobrien if (ent->use_count == 0) 4353104841Sobrien continue; 4354104841Sobrien msec = sec; 4355104841Sobrien ent->addend = 4356104841Sobrien _bfd_merged_section_offset (output_bfd, &msec, 4357104841Sobrien elf_section_data (sec)-> 4358104841Sobrien sec_info, 4359104841Sobrien sym->st_value + ent->addend, 4360104841Sobrien (bfd_vma) 0); 4361104841Sobrien ent->addend -= sym->st_value; 4362104841Sobrien ent->addend += msec->output_section->vma 4363104841Sobrien + msec->output_offset 4364104841Sobrien - sec->output_section->vma 4365104841Sobrien - sec->output_offset; 436633965Sjdp } 436733965Sjdp } 436833965Sjdp 4369104841Sobrien dynamic_symbol_p = false; 437033965Sjdp } 437133965Sjdp else 437233965Sjdp { 437333965Sjdp h = alpha_elf_sym_hashes (input_bfd)[r_symndx - symtab_hdr->sh_info]; 437433965Sjdp 437533965Sjdp while (h->root.root.type == bfd_link_hash_indirect 437633965Sjdp || h->root.root.type == bfd_link_hash_warning) 437733965Sjdp h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link; 437833965Sjdp 4379104841Sobrien value = 0; 438033965Sjdp if (h->root.root.type == bfd_link_hash_defined 438133965Sjdp || h->root.root.type == bfd_link_hash_defweak) 438233965Sjdp { 438333965Sjdp sec = h->root.root.u.def.section; 438433965Sjdp 4385104841Sobrien /* Detect the cases that sym_sec->output_section is 4386104841Sobrien expected to be NULL -- all cases in which the symbol 4387104841Sobrien is defined in another shared module. This includes 4388104841Sobrien PLT relocs for which we've created a PLT entry and 4389104841Sobrien other relocs for which we're prepared to create 4390104841Sobrien dynamic relocations. */ 4391104841Sobrien /* ??? Just accept it NULL and continue. */ 4392104841Sobrien 4393104841Sobrien if (sec->output_section != NULL) 4394104841Sobrien value = (h->root.root.u.def.value 4395104841Sobrien + sec->output_section->vma 4396104841Sobrien + sec->output_offset); 439733965Sjdp } 439833965Sjdp else if (h->root.root.type == bfd_link_hash_undefweak) 4399104841Sobrien undef_weak_ref = true; 440089862Sobrien else if (info->shared 440189862Sobrien && (!info->symbolic || info->allow_shlib_undefined) 440268770Sobrien && !info->no_undefined 440368770Sobrien && ELF_ST_VISIBILITY (h->root.other) == STV_DEFAULT) 4404104841Sobrien ; 440533965Sjdp else 440633965Sjdp { 440733965Sjdp if (!((*info->callbacks->undefined_symbol) 440833965Sjdp (info, h->root.root.root.string, input_bfd, 440960510Sobrien input_section, rel->r_offset, 441068770Sobrien (!info->shared || info->no_undefined 441168770Sobrien || ELF_ST_VISIBILITY (h->root.other))))) 4412104841Sobrien return false; 4413104841Sobrien ret_val = false; 4414104841Sobrien continue; 441533965Sjdp } 4416104841Sobrien 4417104841Sobrien dynamic_symbol_p = alpha_elf_dynamic_symbol_p (&h->root, info); 4418104841Sobrien gotent = h->got_entries; 441933965Sjdp } 4420104841Sobrien 442133965Sjdp addend = rel->r_addend; 4422104841Sobrien value += addend; 442333965Sjdp 4424104841Sobrien /* Search for the proper got entry. */ 4425104841Sobrien for (; gotent ; gotent = gotent->next) 4426104841Sobrien if (gotent->gotobj == gotobj 4427104841Sobrien && gotent->reloc_type == r_type 4428104841Sobrien && gotent->addend == addend) 4429104841Sobrien break; 4430104841Sobrien 443133965Sjdp switch (r_type) 443233965Sjdp { 443333965Sjdp case R_ALPHA_GPDISP: 443433965Sjdp { 443533965Sjdp bfd_byte *p_ldah, *p_lda; 443633965Sjdp 443733965Sjdp BFD_ASSERT(gp != 0); 443833965Sjdp 4439104841Sobrien value = (input_section->output_section->vma 4440104841Sobrien + input_section->output_offset 4441104841Sobrien + rel->r_offset); 444233965Sjdp 4443104841Sobrien p_ldah = contents + rel->r_offset; 444433965Sjdp p_lda = p_ldah + rel->r_addend; 444533965Sjdp 4446104841Sobrien r = elf64_alpha_do_reloc_gpdisp (input_bfd, gp - value, 444733965Sjdp p_ldah, p_lda); 444833965Sjdp } 444933965Sjdp break; 445033965Sjdp 445133965Sjdp case R_ALPHA_LITERAL: 4452104841Sobrien BFD_ASSERT(sgot != NULL); 4453104841Sobrien BFD_ASSERT(gp != 0); 4454104841Sobrien BFD_ASSERT(gotent != NULL); 4455104841Sobrien BFD_ASSERT(gotent->use_count >= 1); 445633965Sjdp 4457104841Sobrien if (!gotent->reloc_done) 4458104841Sobrien { 4459104841Sobrien gotent->reloc_done = 1; 446033965Sjdp 4461104841Sobrien bfd_put_64 (output_bfd, value, 4462104841Sobrien sgot->contents + gotent->got_offset); 446389862Sobrien 4464104841Sobrien /* If the symbol has been forced local, output a 4465104841Sobrien RELATIVE reloc, otherwise it will be handled in 4466104841Sobrien finish_dynamic_symbol. */ 4467104841Sobrien if (info->shared && !dynamic_symbol_p) 4468104841Sobrien { 4469104841Sobrien Elf_Internal_Rela outrel; 447089862Sobrien 4471104841Sobrien BFD_ASSERT(srelgot != NULL); 447233965Sjdp 4473104841Sobrien outrel.r_offset = (sgot->output_section->vma 4474104841Sobrien + sgot->output_offset 4475104841Sobrien + gotent->got_offset); 4476104841Sobrien outrel.r_info = ELF64_R_INFO (0, R_ALPHA_RELATIVE); 4477104841Sobrien outrel.r_addend = value; 447833965Sjdp 4479104841Sobrien bfd_elf64_swap_reloca_out (output_bfd, &outrel, 4480104841Sobrien ((Elf64_External_Rela *) 4481104841Sobrien srelgot->contents) 4482104841Sobrien + srelgot->reloc_count++); 4483104841Sobrien BFD_ASSERT (sizeof (Elf64_External_Rela) 4484104841Sobrien * srelgot->reloc_count 4485104841Sobrien <= srelgot->_cooked_size); 4486104841Sobrien } 4487104841Sobrien } 448833965Sjdp 4489104841Sobrien value = (sgot->output_section->vma 4490104841Sobrien + sgot->output_offset 4491104841Sobrien + gotent->got_offset); 4492104841Sobrien value -= gp; 449333965Sjdp goto default_reloc; 449433965Sjdp 4495115361Sobrien case R_ALPHA_GPREL32: 4496115361Sobrien /* If the target section was a removed linkonce section, 4497115361Sobrien r_symndx will be zero. In this case, assume that the 4498115361Sobrien switch will not be used, so don't fill it in. If we 4499115361Sobrien do nothing here, we'll get relocation truncated messages, 4500115361Sobrien due to the placement of the application above 4GB. */ 4501115361Sobrien if (r_symndx == 0) 4502115361Sobrien { 4503115361Sobrien r = bfd_reloc_ok; 4504115361Sobrien break; 4505115361Sobrien } 4506115361Sobrien /* FALLTHRU */ 4507115361Sobrien 450889862Sobrien case R_ALPHA_GPREL16: 450960510Sobrien case R_ALPHA_GPRELLOW: 4510104841Sobrien if (dynamic_symbol_p) 451189862Sobrien { 451289862Sobrien (*_bfd_error_handler) 451389862Sobrien (_("%s: gp-relative relocation against dynamic symbol %s"), 451489862Sobrien bfd_archive_filename (input_bfd), h->root.root.root.string); 451589862Sobrien ret_val = false; 451689862Sobrien } 451733965Sjdp BFD_ASSERT(gp != 0); 4518104841Sobrien value -= gp; 451933965Sjdp goto default_reloc; 452033965Sjdp 452160510Sobrien case R_ALPHA_GPRELHIGH: 4522104841Sobrien if (dynamic_symbol_p) 452389862Sobrien { 452489862Sobrien (*_bfd_error_handler) 452589862Sobrien (_("%s: gp-relative relocation against dynamic symbol %s"), 452689862Sobrien bfd_archive_filename (input_bfd), h->root.root.root.string); 452789862Sobrien ret_val = false; 452889862Sobrien } 452960510Sobrien BFD_ASSERT(gp != 0); 4530104841Sobrien value -= gp; 4531104841Sobrien value = ((bfd_signed_vma) value >> 16) + ((value >> 15) & 1); 453260510Sobrien goto default_reloc; 453360510Sobrien 453489862Sobrien case R_ALPHA_HINT: 453589862Sobrien /* A call to a dynamic symbol is definitely out of range of 453689862Sobrien the 16-bit displacement. Don't bother writing anything. */ 4537104841Sobrien if (dynamic_symbol_p) 453889862Sobrien { 453989862Sobrien r = bfd_reloc_ok; 454089862Sobrien break; 454189862Sobrien } 4542104841Sobrien /* The regular PC-relative stuff measures from the start of 4543104841Sobrien the instruction rather than the end. */ 4544104841Sobrien value -= 4; 4545104841Sobrien goto default_reloc; 454689862Sobrien 454733965Sjdp case R_ALPHA_BRADDR: 4548104841Sobrien if (dynamic_symbol_p) 4549104841Sobrien { 4550104841Sobrien (*_bfd_error_handler) 4551104841Sobrien (_("%s: pc-relative relocation against dynamic symbol %s"), 4552104841Sobrien bfd_archive_filename (input_bfd), h->root.root.root.string); 4553104841Sobrien ret_val = false; 4554104841Sobrien } 455533965Sjdp /* The regular PC-relative stuff measures from the start of 455633965Sjdp the instruction rather than the end. */ 4557104841Sobrien value -= 4; 455833965Sjdp goto default_reloc; 455933965Sjdp 456091049Sobrien case R_ALPHA_BRSGP: 456191049Sobrien { 456291049Sobrien int other; 456391049Sobrien const char *name; 456491049Sobrien 456591049Sobrien /* The regular PC-relative stuff measures from the start of 456691049Sobrien the instruction rather than the end. */ 4567104841Sobrien value -= 4; 456891049Sobrien 456991049Sobrien /* The source and destination gp must be the same. Note that 457091049Sobrien the source will always have an assigned gp, since we forced 457191049Sobrien one in check_relocs, but that the destination may not, as 4572104841Sobrien it might not have had any relocations at all. Also take 457391049Sobrien care not to crash if H is an undefined symbol. */ 457491049Sobrien if (h != NULL && sec != NULL 457591049Sobrien && alpha_elf_tdata (sec->owner)->gotobj 457691049Sobrien && gotobj != alpha_elf_tdata (sec->owner)->gotobj) 457791049Sobrien { 457891049Sobrien (*_bfd_error_handler) 457991049Sobrien (_("%s: change in gp: BRSGP %s"), 458091049Sobrien bfd_archive_filename (input_bfd), h->root.root.root.string); 458191049Sobrien ret_val = false; 458291049Sobrien } 458391049Sobrien 458491049Sobrien /* The symbol should be marked either NOPV or STD_GPLOAD. */ 458591049Sobrien if (h != NULL) 458691049Sobrien other = h->root.other; 458791049Sobrien else 458891049Sobrien other = sym->st_other; 458991049Sobrien switch (other & STO_ALPHA_STD_GPLOAD) 459091049Sobrien { 459191049Sobrien case STO_ALPHA_NOPV: 459291049Sobrien break; 459391049Sobrien case STO_ALPHA_STD_GPLOAD: 4594107497Sobrien value += 8; 459591049Sobrien break; 459691049Sobrien default: 459791049Sobrien if (h != NULL) 459891049Sobrien name = h->root.root.root.string; 459991049Sobrien else 460091049Sobrien { 460191049Sobrien name = (bfd_elf_string_from_elf_section 460291049Sobrien (input_bfd, symtab_hdr->sh_link, sym->st_name)); 460391049Sobrien if (name == NULL) 460491049Sobrien name = _("<unknown>"); 460591049Sobrien else if (name[0] == 0) 460691049Sobrien name = bfd_section_name (input_bfd, sec); 460791049Sobrien } 460891049Sobrien (*_bfd_error_handler) 460991049Sobrien (_("%s: !samegp reloc against symbol without .prologue: %s"), 461091049Sobrien bfd_archive_filename (input_bfd), name); 461191049Sobrien ret_val = false; 461291049Sobrien break; 461391049Sobrien } 461491049Sobrien 461591049Sobrien goto default_reloc; 461691049Sobrien } 461791049Sobrien 461833965Sjdp case R_ALPHA_REFLONG: 461933965Sjdp case R_ALPHA_REFQUAD: 4620104841Sobrien case R_ALPHA_DTPREL64: 4621104841Sobrien case R_ALPHA_TPREL64: 462233965Sjdp { 462333965Sjdp Elf_Internal_Rela outrel; 462433965Sjdp 462533965Sjdp /* Careful here to remember RELATIVE relocations for global 462633965Sjdp variables for symbolic shared objects. */ 462733965Sjdp 4628104841Sobrien if (dynamic_symbol_p) 462933965Sjdp { 463033965Sjdp BFD_ASSERT(h->root.dynindx != -1); 4631104841Sobrien outrel.r_info = ELF64_R_INFO (h->root.dynindx, r_type); 463233965Sjdp outrel.r_addend = addend; 4633104841Sobrien addend = 0, value = 0; 463433965Sjdp } 4635104841Sobrien else if (r_type == R_ALPHA_DTPREL64) 4636104841Sobrien { 4637104841Sobrien BFD_ASSERT(tls_segment != NULL); 4638104841Sobrien value -= dtp_base; 4639104841Sobrien goto default_reloc; 4640104841Sobrien } 4641104841Sobrien else if (r_type == R_ALPHA_TPREL64) 4642104841Sobrien { 4643104841Sobrien BFD_ASSERT(tls_segment != NULL); 4644104841Sobrien value -= dtp_base; 4645104841Sobrien goto default_reloc; 4646104841Sobrien } 464789862Sobrien else if (info->shared 464889862Sobrien && r_symndx != 0 464989862Sobrien && (input_section->flags & SEC_ALLOC)) 465033965Sjdp { 4651104841Sobrien if (r_type == R_ALPHA_REFLONG) 4652104841Sobrien { 4653104841Sobrien (*_bfd_error_handler) 4654104841Sobrien (_("%s: unhandled dynamic relocation against %s"), 4655104841Sobrien bfd_archive_filename (input_bfd), 4656104841Sobrien h->root.root.root.string); 4657104841Sobrien ret_val = false; 4658104841Sobrien } 4659104841Sobrien outrel.r_info = ELF64_R_INFO (0, R_ALPHA_RELATIVE); 4660104841Sobrien outrel.r_addend = value; 466133965Sjdp } 466233965Sjdp else 466333965Sjdp goto default_reloc; 466433965Sjdp 4665104841Sobrien BFD_ASSERT(srel != NULL); 466633965Sjdp 466789862Sobrien outrel.r_offset = 466889862Sobrien _bfd_elf_section_offset (output_bfd, info, input_section, 466989862Sobrien rel->r_offset); 467091049Sobrien if ((outrel.r_offset | 1) != (bfd_vma) -1) 467133965Sjdp outrel.r_offset += (input_section->output_section->vma 467233965Sjdp + input_section->output_offset); 467333965Sjdp else 467433965Sjdp memset (&outrel, 0, sizeof outrel); 467533965Sjdp 467633965Sjdp bfd_elf64_swap_reloca_out (output_bfd, &outrel, 467733965Sjdp ((Elf64_External_Rela *) 467833965Sjdp srel->contents) 467933965Sjdp + srel->reloc_count++); 468077303Sobrien BFD_ASSERT (sizeof (Elf64_External_Rela) * srel->reloc_count 468148850Sdfr <= srel->_cooked_size); 468233965Sjdp } 468333965Sjdp goto default_reloc; 468433965Sjdp 4685104841Sobrien case R_ALPHA_SREL16: 468699465Sobrien case R_ALPHA_SREL32: 468799465Sobrien case R_ALPHA_SREL64: 4688104841Sobrien if (dynamic_symbol_p) 4689104841Sobrien { 4690104841Sobrien (*_bfd_error_handler) 4691104841Sobrien (_("%s: pc-relative relocation against dynamic symbol %s"), 4692104841Sobrien bfd_archive_filename (input_bfd), h->root.root.root.string); 4693104841Sobrien ret_val = false; 4694104841Sobrien } 4695104841Sobrien 469699465Sobrien /* ??? .eh_frame references to discarded sections will be smashed 469799465Sobrien to relocations against SHN_UNDEF. The .eh_frame format allows 469899465Sobrien NULL to be encoded as 0 in any format, so this works here. */ 469999465Sobrien if (r_symndx == 0) 470099465Sobrien howto = (elf64_alpha_howto_table 470199465Sobrien + (r_type - R_ALPHA_SREL32 + R_ALPHA_REFLONG)); 470299465Sobrien goto default_reloc; 470399465Sobrien 4704104841Sobrien case R_ALPHA_TLSLDM: 4705104841Sobrien /* Ignore the symbol for the relocation. The result is always 4706104841Sobrien the current module. */ 4707104841Sobrien dynamic_symbol_p = 0; 4708104841Sobrien /* FALLTHRU */ 4709104841Sobrien 4710104841Sobrien case R_ALPHA_TLSGD: 4711104841Sobrien if (!gotent->reloc_done) 4712104841Sobrien { 4713104841Sobrien gotent->reloc_done = 1; 4714104841Sobrien 4715104841Sobrien /* Note that the module index for the main program is 1. */ 4716104841Sobrien bfd_put_64 (output_bfd, !info->shared && !dynamic_symbol_p, 4717104841Sobrien sgot->contents + gotent->got_offset); 4718104841Sobrien 4719104841Sobrien /* If the symbol has been forced local, output a 4720104841Sobrien DTPMOD64 reloc, otherwise it will be handled in 4721104841Sobrien finish_dynamic_symbol. */ 4722104841Sobrien if (info->shared && !dynamic_symbol_p) 4723104841Sobrien { 4724104841Sobrien Elf_Internal_Rela outrel; 4725104841Sobrien 4726104841Sobrien BFD_ASSERT(srelgot != NULL); 4727104841Sobrien 4728104841Sobrien outrel.r_offset = (sgot->output_section->vma 4729104841Sobrien + sgot->output_offset 4730104841Sobrien + gotent->got_offset); 4731104841Sobrien /* ??? Proper dynindx here. */ 4732104841Sobrien outrel.r_info = ELF64_R_INFO (0, R_ALPHA_DTPMOD64); 4733104841Sobrien outrel.r_addend = 0; 4734104841Sobrien 4735104841Sobrien bfd_elf64_swap_reloca_out (output_bfd, &outrel, 4736104841Sobrien ((Elf64_External_Rela *) 4737104841Sobrien srelgot->contents) 4738104841Sobrien + srelgot->reloc_count++); 4739104841Sobrien BFD_ASSERT (sizeof (Elf64_External_Rela) 4740104841Sobrien * srelgot->reloc_count 4741104841Sobrien <= srelgot->_cooked_size); 4742104841Sobrien } 4743104841Sobrien 4744104841Sobrien if (dynamic_symbol_p || r_type == R_ALPHA_TLSLDM) 4745104841Sobrien value = 0; 4746104841Sobrien else 4747104841Sobrien { 4748104841Sobrien BFD_ASSERT(tls_segment != NULL); 4749104841Sobrien value -= dtp_base; 4750104841Sobrien } 4751104841Sobrien bfd_put_64 (output_bfd, value, 4752104841Sobrien sgot->contents + gotent->got_offset + 8); 4753104841Sobrien } 4754104841Sobrien 4755104841Sobrien value = (sgot->output_section->vma 4756104841Sobrien + sgot->output_offset 4757104841Sobrien + gotent->got_offset); 4758104841Sobrien value -= gp; 4759104841Sobrien goto default_reloc; 4760104841Sobrien 4761104841Sobrien case R_ALPHA_DTPRELHI: 4762104841Sobrien case R_ALPHA_DTPRELLO: 4763104841Sobrien case R_ALPHA_DTPREL16: 4764104841Sobrien if (dynamic_symbol_p) 4765104841Sobrien { 4766104841Sobrien (*_bfd_error_handler) 4767104841Sobrien (_("%s: dtp-relative relocation against dynamic symbol %s"), 4768104841Sobrien bfd_archive_filename (input_bfd), h->root.root.root.string); 4769104841Sobrien ret_val = false; 4770104841Sobrien } 4771104841Sobrien BFD_ASSERT(tls_segment != NULL); 4772104841Sobrien value -= dtp_base; 4773104841Sobrien if (r_type == R_ALPHA_DTPRELHI) 4774104841Sobrien value = ((bfd_signed_vma) value >> 16) + ((value >> 15) & 1); 4775104841Sobrien goto default_reloc; 4776104841Sobrien 4777104841Sobrien case R_ALPHA_TPRELHI: 4778104841Sobrien case R_ALPHA_TPRELLO: 4779104841Sobrien case R_ALPHA_TPREL16: 4780104841Sobrien if (info->shared) 4781104841Sobrien { 4782104841Sobrien (*_bfd_error_handler) 4783104841Sobrien (_("%s: TLS local exec code cannot be linked into shared objects"), 4784104841Sobrien bfd_archive_filename (input_bfd)); 4785104841Sobrien ret_val = false; 4786104841Sobrien } 4787104841Sobrien else if (dynamic_symbol_p) 4788104841Sobrien { 4789104841Sobrien (*_bfd_error_handler) 4790104841Sobrien (_("%s: tp-relative relocation against dynamic symbol %s"), 4791104841Sobrien bfd_archive_filename (input_bfd), h->root.root.root.string); 4792104841Sobrien ret_val = false; 4793104841Sobrien } 4794104841Sobrien BFD_ASSERT(tls_segment != NULL); 4795104841Sobrien value -= tp_base; 4796104841Sobrien if (r_type == R_ALPHA_TPRELHI) 4797104841Sobrien value = ((bfd_signed_vma) value >> 16) + ((value >> 15) & 1); 4798104841Sobrien goto default_reloc; 4799104841Sobrien 4800104841Sobrien case R_ALPHA_GOTDTPREL: 4801104841Sobrien case R_ALPHA_GOTTPREL: 4802104841Sobrien BFD_ASSERT(sgot != NULL); 4803104841Sobrien BFD_ASSERT(gp != 0); 4804104841Sobrien BFD_ASSERT(gotent != NULL); 4805104841Sobrien BFD_ASSERT(gotent->use_count >= 1); 4806104841Sobrien 4807104841Sobrien if (!gotent->reloc_done) 4808104841Sobrien { 4809104841Sobrien gotent->reloc_done = 1; 4810104841Sobrien 4811104841Sobrien if (dynamic_symbol_p) 4812104841Sobrien value = 0; 4813104841Sobrien else 4814104841Sobrien { 4815104841Sobrien BFD_ASSERT(tls_segment != NULL); 4816104841Sobrien value -= (r_type == R_ALPHA_GOTDTPREL ? dtp_base : tp_base); 4817104841Sobrien } 4818104841Sobrien bfd_put_64 (output_bfd, value, 4819104841Sobrien sgot->contents + gotent->got_offset); 4820104841Sobrien } 4821104841Sobrien 4822104841Sobrien value = (sgot->output_section->vma 4823104841Sobrien + sgot->output_offset 4824104841Sobrien + gotent->got_offset); 4825104841Sobrien value -= gp; 4826104841Sobrien goto default_reloc; 4827104841Sobrien 482833965Sjdp default: 482933965Sjdp default_reloc: 483033965Sjdp r = _bfd_final_link_relocate (howto, input_bfd, input_section, 4831104841Sobrien contents, rel->r_offset, value, 0); 483233965Sjdp break; 483333965Sjdp } 483433965Sjdp 483533965Sjdp switch (r) 483633965Sjdp { 483733965Sjdp case bfd_reloc_ok: 483833965Sjdp break; 483933965Sjdp 484033965Sjdp case bfd_reloc_overflow: 484133965Sjdp { 484233965Sjdp const char *name; 484333965Sjdp 484489862Sobrien /* Don't warn if the overflow is due to pc relative reloc 484589862Sobrien against discarded section. Section optimization code should 484689862Sobrien handle it. */ 484789862Sobrien 484889862Sobrien if (r_symndx < symtab_hdr->sh_info 484989862Sobrien && sec != NULL && howto->pc_relative 485089862Sobrien && elf_discarded_section (sec)) 485189862Sobrien break; 485289862Sobrien 485333965Sjdp if (h != NULL) 485433965Sjdp name = h->root.root.root.string; 485533965Sjdp else 485633965Sjdp { 485733965Sjdp name = (bfd_elf_string_from_elf_section 485833965Sjdp (input_bfd, symtab_hdr->sh_link, sym->st_name)); 485933965Sjdp if (name == NULL) 486033965Sjdp return false; 486133965Sjdp if (*name == '\0') 486233965Sjdp name = bfd_section_name (input_bfd, sec); 486333965Sjdp } 486433965Sjdp if (! ((*info->callbacks->reloc_overflow) 486533965Sjdp (info, name, howto->name, (bfd_vma) 0, 486633965Sjdp input_bfd, input_section, rel->r_offset))) 486789862Sobrien ret_val = false; 486833965Sjdp } 486933965Sjdp break; 487033965Sjdp 487133965Sjdp default: 487233965Sjdp case bfd_reloc_outofrange: 487333965Sjdp abort (); 487433965Sjdp } 487533965Sjdp } 487633965Sjdp 487789862Sobrien return ret_val; 487833965Sjdp} 487933965Sjdp 488033965Sjdp/* Finish up dynamic symbol handling. We set the contents of various 488133965Sjdp dynamic sections here. */ 488233965Sjdp 488333965Sjdpstatic boolean 488433965Sjdpelf64_alpha_finish_dynamic_symbol (output_bfd, info, h, sym) 488533965Sjdp bfd *output_bfd; 488633965Sjdp struct bfd_link_info *info; 488733965Sjdp struct elf_link_hash_entry *h; 488833965Sjdp Elf_Internal_Sym *sym; 488933965Sjdp{ 489033965Sjdp bfd *dynobj = elf_hash_table(info)->dynobj; 489133965Sjdp 489260510Sobrien if (h->plt.offset != MINUS_ONE) 489333965Sjdp { 489433965Sjdp /* Fill in the .plt entry for this symbol. */ 489533965Sjdp asection *splt, *sgot, *srel; 489633965Sjdp Elf_Internal_Rela outrel; 489733965Sjdp bfd_vma got_addr, plt_addr; 489833965Sjdp bfd_vma plt_index; 489933965Sjdp struct alpha_elf_got_entry *gotent; 490033965Sjdp 490133965Sjdp BFD_ASSERT (h->dynindx != -1); 490233965Sjdp 490333965Sjdp /* The first .got entry will be updated by the .plt with the 490433965Sjdp address of the target function. */ 490533965Sjdp gotent = ((struct alpha_elf_link_hash_entry *) h)->got_entries; 490633965Sjdp BFD_ASSERT (gotent && gotent->addend == 0); 490733965Sjdp 490833965Sjdp splt = bfd_get_section_by_name (dynobj, ".plt"); 490933965Sjdp BFD_ASSERT (splt != NULL); 491033965Sjdp srel = bfd_get_section_by_name (dynobj, ".rela.plt"); 491133965Sjdp BFD_ASSERT (srel != NULL); 491233965Sjdp sgot = alpha_elf_tdata (gotent->gotobj)->got; 491333965Sjdp BFD_ASSERT (sgot != NULL); 491433965Sjdp 491533965Sjdp got_addr = (sgot->output_section->vma 491633965Sjdp + sgot->output_offset 491733965Sjdp + gotent->got_offset); 491833965Sjdp plt_addr = (splt->output_section->vma 491933965Sjdp + splt->output_offset 492060510Sobrien + h->plt.offset); 492133965Sjdp 492260510Sobrien plt_index = (h->plt.offset - PLT_HEADER_SIZE) / PLT_ENTRY_SIZE; 492333965Sjdp 492433965Sjdp /* Fill in the entry in the procedure linkage table. */ 492533965Sjdp { 492689862Sobrien bfd_vma insn1, insn2, insn3; 492733965Sjdp 492860510Sobrien insn1 = PLT_ENTRY_WORD1 | ((-(h->plt.offset + 4) >> 2) & 0x1fffff); 492938889Sjdp insn2 = PLT_ENTRY_WORD2; 493038889Sjdp insn3 = PLT_ENTRY_WORD3; 493133965Sjdp 493260510Sobrien bfd_put_32 (output_bfd, insn1, splt->contents + h->plt.offset); 493360510Sobrien bfd_put_32 (output_bfd, insn2, splt->contents + h->plt.offset + 4); 493460510Sobrien bfd_put_32 (output_bfd, insn3, splt->contents + h->plt.offset + 8); 493533965Sjdp } 493633965Sjdp 493733965Sjdp /* Fill in the entry in the .rela.plt section. */ 493833965Sjdp outrel.r_offset = got_addr; 493933965Sjdp outrel.r_info = ELF64_R_INFO(h->dynindx, R_ALPHA_JMP_SLOT); 494033965Sjdp outrel.r_addend = 0; 494133965Sjdp 494233965Sjdp bfd_elf64_swap_reloca_out (output_bfd, &outrel, 494333965Sjdp ((Elf64_External_Rela *)srel->contents 494433965Sjdp + plt_index)); 494533965Sjdp 494633965Sjdp if (!(h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)) 494733965Sjdp { 494833965Sjdp /* Mark the symbol as undefined, rather than as defined in the 494933965Sjdp .plt section. Leave the value alone. */ 495033965Sjdp sym->st_shndx = SHN_UNDEF; 495133965Sjdp } 495233965Sjdp 495333965Sjdp /* Fill in the entries in the .got. */ 495433965Sjdp bfd_put_64 (output_bfd, plt_addr, sgot->contents + gotent->got_offset); 495533965Sjdp 495633965Sjdp /* Subsequent .got entries will continue to bounce through the .plt. */ 495748850Sdfr if (gotent->next) 495833965Sjdp { 495948850Sdfr srel = bfd_get_section_by_name (dynobj, ".rela.got"); 496048850Sdfr BFD_ASSERT (! info->shared || srel != NULL); 496133965Sjdp 496248850Sdfr gotent = gotent->next; 496348850Sdfr do 496448850Sdfr { 496548850Sdfr sgot = alpha_elf_tdata(gotent->gotobj)->got; 496648850Sdfr BFD_ASSERT(sgot != NULL); 496748850Sdfr BFD_ASSERT(gotent->addend == 0); 496848850Sdfr 496948850Sdfr bfd_put_64 (output_bfd, plt_addr, 497048850Sdfr sgot->contents + gotent->got_offset); 497148850Sdfr 497248850Sdfr if (info->shared) 497348850Sdfr { 497448850Sdfr outrel.r_offset = (sgot->output_section->vma 497548850Sdfr + sgot->output_offset 497648850Sdfr + gotent->got_offset); 497748850Sdfr outrel.r_info = ELF64_R_INFO(0, R_ALPHA_RELATIVE); 497889862Sobrien outrel.r_addend = plt_addr; 497948850Sdfr 498048850Sdfr bfd_elf64_swap_reloca_out (output_bfd, &outrel, 498148850Sdfr ((Elf64_External_Rela *) 498248850Sdfr srel->contents) 498348850Sdfr + srel->reloc_count++); 498477303Sobrien BFD_ASSERT (sizeof (Elf64_External_Rela) * srel->reloc_count 498548850Sdfr <= srel->_cooked_size); 498648850Sdfr } 498748850Sdfr 498848850Sdfr gotent = gotent->next; 498948850Sdfr } 499048850Sdfr while (gotent != NULL); 499133965Sjdp } 499233965Sjdp } 499333965Sjdp else if (alpha_elf_dynamic_symbol_p (h, info)) 499433965Sjdp { 499533965Sjdp /* Fill in the dynamic relocations for this symbol's .got entries. */ 499633965Sjdp asection *srel; 499733965Sjdp Elf_Internal_Rela outrel; 499833965Sjdp struct alpha_elf_got_entry *gotent; 499933965Sjdp 500033965Sjdp srel = bfd_get_section_by_name (dynobj, ".rela.got"); 500133965Sjdp BFD_ASSERT (srel != NULL); 500233965Sjdp 500333965Sjdp for (gotent = ((struct alpha_elf_link_hash_entry *) h)->got_entries; 500433965Sjdp gotent != NULL; 500533965Sjdp gotent = gotent->next) 500633965Sjdp { 5007104841Sobrien asection *sgot; 5008104841Sobrien int r_type; 5009104841Sobrien 5010104841Sobrien if (gotent->use_count == 0) 5011104841Sobrien continue; 5012104841Sobrien 5013104841Sobrien sgot = alpha_elf_tdata (gotent->gotobj)->got; 501433965Sjdp outrel.r_offset = (sgot->output_section->vma 501533965Sjdp + sgot->output_offset 501633965Sjdp + gotent->got_offset); 5017104841Sobrien 5018104841Sobrien r_type = gotent->reloc_type; 5019104841Sobrien switch (r_type) 5020104841Sobrien { 5021104841Sobrien case R_ALPHA_LITERAL: 5022104841Sobrien r_type = R_ALPHA_GLOB_DAT; 5023104841Sobrien break; 5024104841Sobrien case R_ALPHA_TLSGD: 5025104841Sobrien r_type = R_ALPHA_DTPMOD64; 5026104841Sobrien break; 5027104841Sobrien case R_ALPHA_GOTDTPREL: 5028104841Sobrien r_type = R_ALPHA_DTPREL64; 5029104841Sobrien break; 5030104841Sobrien case R_ALPHA_GOTTPREL: 5031104841Sobrien r_type = R_ALPHA_TPREL64; 5032104841Sobrien break; 5033104841Sobrien case R_ALPHA_TLSLDM: 5034104841Sobrien default: 5035104841Sobrien abort (); 5036104841Sobrien } 5037104841Sobrien 5038104841Sobrien outrel.r_info = ELF64_R_INFO (h->dynindx, r_type); 503933965Sjdp outrel.r_addend = gotent->addend; 504033965Sjdp 504133965Sjdp bfd_elf64_swap_reloca_out (output_bfd, &outrel, 504233965Sjdp ((Elf64_External_Rela *)srel->contents 504333965Sjdp + srel->reloc_count++)); 5044104841Sobrien 5045104841Sobrien if (gotent->reloc_type == R_ALPHA_TLSGD) 5046104841Sobrien { 5047104841Sobrien outrel.r_offset += 8; 5048104841Sobrien outrel.r_info = ELF64_R_INFO (h->dynindx, R_ALPHA_DTPREL64); 5049104841Sobrien 5050104841Sobrien bfd_elf64_swap_reloca_out (output_bfd, &outrel, 5051104841Sobrien ((Elf64_External_Rela *)srel->contents 5052104841Sobrien + srel->reloc_count++)); 5053104841Sobrien } 5054104841Sobrien 505577303Sobrien BFD_ASSERT (sizeof (Elf64_External_Rela) * srel->reloc_count 505648850Sdfr <= srel->_cooked_size); 505733965Sjdp } 505833965Sjdp } 505933965Sjdp 506033965Sjdp /* Mark some specially defined symbols as absolute. */ 506133965Sjdp if (strcmp (h->root.root.string, "_DYNAMIC") == 0 506233965Sjdp || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0 506333965Sjdp || strcmp (h->root.root.string, "_PROCEDURE_LINKAGE_TABLE_") == 0) 506433965Sjdp sym->st_shndx = SHN_ABS; 506533965Sjdp 506633965Sjdp return true; 506733965Sjdp} 506833965Sjdp 506933965Sjdp/* Finish up the dynamic sections. */ 507033965Sjdp 507133965Sjdpstatic boolean 507233965Sjdpelf64_alpha_finish_dynamic_sections (output_bfd, info) 507333965Sjdp bfd *output_bfd; 507433965Sjdp struct bfd_link_info *info; 507533965Sjdp{ 507633965Sjdp bfd *dynobj; 507733965Sjdp asection *sdyn; 507833965Sjdp 507933965Sjdp dynobj = elf_hash_table (info)->dynobj; 508033965Sjdp sdyn = bfd_get_section_by_name (dynobj, ".dynamic"); 508133965Sjdp 508233965Sjdp if (elf_hash_table (info)->dynamic_sections_created) 508333965Sjdp { 508433965Sjdp asection *splt; 508533965Sjdp Elf64_External_Dyn *dyncon, *dynconend; 508633965Sjdp 508733965Sjdp splt = bfd_get_section_by_name (dynobj, ".plt"); 508833965Sjdp BFD_ASSERT (splt != NULL && sdyn != NULL); 508933965Sjdp 509033965Sjdp dyncon = (Elf64_External_Dyn *) sdyn->contents; 509133965Sjdp dynconend = (Elf64_External_Dyn *) (sdyn->contents + sdyn->_raw_size); 509233965Sjdp for (; dyncon < dynconend; dyncon++) 509333965Sjdp { 509433965Sjdp Elf_Internal_Dyn dyn; 509533965Sjdp const char *name; 509633965Sjdp asection *s; 509733965Sjdp 509833965Sjdp bfd_elf64_swap_dyn_in (dynobj, dyncon, &dyn); 509933965Sjdp 510033965Sjdp switch (dyn.d_tag) 510133965Sjdp { 510233965Sjdp case DT_PLTGOT: 510333965Sjdp name = ".plt"; 510433965Sjdp goto get_vma; 510533965Sjdp case DT_PLTRELSZ: 510633965Sjdp name = ".rela.plt"; 510733965Sjdp goto get_size; 510833965Sjdp case DT_JMPREL: 510933965Sjdp name = ".rela.plt"; 511033965Sjdp goto get_vma; 511133965Sjdp 511233965Sjdp case DT_RELASZ: 511333965Sjdp /* My interpretation of the TIS v1.1 ELF document indicates 511433965Sjdp that RELASZ should not include JMPREL. This is not what 511533965Sjdp the rest of the BFD does. It is, however, what the 511633965Sjdp glibc ld.so wants. Do this fixup here until we found 511733965Sjdp out who is right. */ 511833965Sjdp s = bfd_get_section_by_name (output_bfd, ".rela.plt"); 511933965Sjdp if (s) 512033965Sjdp { 512133965Sjdp dyn.d_un.d_val -= 512233965Sjdp (s->_cooked_size ? s->_cooked_size : s->_raw_size); 512333965Sjdp } 512433965Sjdp break; 512533965Sjdp 512633965Sjdp get_vma: 512733965Sjdp s = bfd_get_section_by_name (output_bfd, name); 512833965Sjdp dyn.d_un.d_ptr = (s ? s->vma : 0); 512933965Sjdp break; 513033965Sjdp 513133965Sjdp get_size: 513233965Sjdp s = bfd_get_section_by_name (output_bfd, name); 513333965Sjdp dyn.d_un.d_val = 513433965Sjdp (s->_cooked_size ? s->_cooked_size : s->_raw_size); 513533965Sjdp break; 513633965Sjdp } 513733965Sjdp 513833965Sjdp bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon); 513933965Sjdp } 514033965Sjdp 514133965Sjdp /* Initialize the PLT0 entry */ 514233965Sjdp if (splt->_raw_size > 0) 514333965Sjdp { 514433965Sjdp bfd_put_32 (output_bfd, PLT_HEADER_WORD1, splt->contents); 514533965Sjdp bfd_put_32 (output_bfd, PLT_HEADER_WORD2, splt->contents + 4); 514633965Sjdp bfd_put_32 (output_bfd, PLT_HEADER_WORD3, splt->contents + 8); 514733965Sjdp bfd_put_32 (output_bfd, PLT_HEADER_WORD4, splt->contents + 12); 514833965Sjdp 514933965Sjdp /* The next two words will be filled in by ld.so */ 515089862Sobrien bfd_put_64 (output_bfd, (bfd_vma) 0, splt->contents + 16); 515189862Sobrien bfd_put_64 (output_bfd, (bfd_vma) 0, splt->contents + 24); 515233965Sjdp 515333965Sjdp elf_section_data (splt->output_section)->this_hdr.sh_entsize = 515433965Sjdp PLT_HEADER_SIZE; 515533965Sjdp } 515633965Sjdp } 515733965Sjdp 515833965Sjdp return true; 515933965Sjdp} 516033965Sjdp 516189862Sobrien/* We need to use a special link routine to handle the .mdebug section. 516289862Sobrien We need to merge all instances of these sections together, not write 516389862Sobrien them all out sequentially. */ 516433965Sjdp 516533965Sjdpstatic boolean 516633965Sjdpelf64_alpha_final_link (abfd, info) 516733965Sjdp bfd *abfd; 516833965Sjdp struct bfd_link_info *info; 516933965Sjdp{ 517033965Sjdp asection *o; 517133965Sjdp struct bfd_link_order *p; 517289862Sobrien asection *mdebug_sec; 517333965Sjdp struct ecoff_debug_info debug; 517433965Sjdp const struct ecoff_debug_swap *swap 517533965Sjdp = get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap; 517633965Sjdp HDRR *symhdr = &debug.symbolic_header; 517733965Sjdp PTR mdebug_handle = NULL; 517833965Sjdp 517989862Sobrien /* Go through the sections and collect the mdebug information. */ 518033965Sjdp mdebug_sec = NULL; 518133965Sjdp for (o = abfd->sections; o != (asection *) NULL; o = o->next) 518233965Sjdp { 518333965Sjdp if (strcmp (o->name, ".mdebug") == 0) 518433965Sjdp { 518533965Sjdp struct extsym_info einfo; 518633965Sjdp 518733965Sjdp /* We have found the .mdebug section in the output file. 518833965Sjdp Look through all the link_orders comprising it and merge 518933965Sjdp the information together. */ 519033965Sjdp symhdr->magic = swap->sym_magic; 519133965Sjdp /* FIXME: What should the version stamp be? */ 519233965Sjdp symhdr->vstamp = 0; 519333965Sjdp symhdr->ilineMax = 0; 519433965Sjdp symhdr->cbLine = 0; 519533965Sjdp symhdr->idnMax = 0; 519633965Sjdp symhdr->ipdMax = 0; 519733965Sjdp symhdr->isymMax = 0; 519833965Sjdp symhdr->ioptMax = 0; 519933965Sjdp symhdr->iauxMax = 0; 520033965Sjdp symhdr->issMax = 0; 520133965Sjdp symhdr->issExtMax = 0; 520233965Sjdp symhdr->ifdMax = 0; 520333965Sjdp symhdr->crfd = 0; 520433965Sjdp symhdr->iextMax = 0; 520533965Sjdp 520633965Sjdp /* We accumulate the debugging information itself in the 520733965Sjdp debug_info structure. */ 520833965Sjdp debug.line = NULL; 520933965Sjdp debug.external_dnr = NULL; 521033965Sjdp debug.external_pdr = NULL; 521133965Sjdp debug.external_sym = NULL; 521233965Sjdp debug.external_opt = NULL; 521333965Sjdp debug.external_aux = NULL; 521433965Sjdp debug.ss = NULL; 521533965Sjdp debug.ssext = debug.ssext_end = NULL; 521633965Sjdp debug.external_fdr = NULL; 521733965Sjdp debug.external_rfd = NULL; 521833965Sjdp debug.external_ext = debug.external_ext_end = NULL; 521933965Sjdp 522033965Sjdp mdebug_handle = bfd_ecoff_debug_init (abfd, &debug, swap, info); 522133965Sjdp if (mdebug_handle == (PTR) NULL) 522233965Sjdp return false; 522333965Sjdp 522433965Sjdp if (1) 522533965Sjdp { 522633965Sjdp asection *s; 522733965Sjdp EXTR esym; 522889862Sobrien bfd_vma last = 0; 522933965Sjdp unsigned int i; 523033965Sjdp static const char * const name[] = 523133965Sjdp { 523233965Sjdp ".text", ".init", ".fini", ".data", 523333965Sjdp ".rodata", ".sdata", ".sbss", ".bss" 523433965Sjdp }; 523533965Sjdp static const int sc[] = { scText, scInit, scFini, scData, 523633965Sjdp scRData, scSData, scSBss, scBss }; 523733965Sjdp 523833965Sjdp esym.jmptbl = 0; 523933965Sjdp esym.cobol_main = 0; 524033965Sjdp esym.weakext = 0; 524133965Sjdp esym.reserved = 0; 524233965Sjdp esym.ifd = ifdNil; 524333965Sjdp esym.asym.iss = issNil; 524433965Sjdp esym.asym.st = stLocal; 524533965Sjdp esym.asym.reserved = 0; 524633965Sjdp esym.asym.index = indexNil; 524733965Sjdp for (i = 0; i < 8; i++) 524833965Sjdp { 524933965Sjdp esym.asym.sc = sc[i]; 525033965Sjdp s = bfd_get_section_by_name (abfd, name[i]); 525133965Sjdp if (s != NULL) 525233965Sjdp { 525333965Sjdp esym.asym.value = s->vma; 525433965Sjdp last = s->vma + s->_raw_size; 525533965Sjdp } 525633965Sjdp else 525733965Sjdp esym.asym.value = last; 525833965Sjdp 525933965Sjdp if (! bfd_ecoff_debug_one_external (abfd, &debug, swap, 526033965Sjdp name[i], &esym)) 526133965Sjdp return false; 526233965Sjdp } 526333965Sjdp } 526433965Sjdp 526533965Sjdp for (p = o->link_order_head; 526633965Sjdp p != (struct bfd_link_order *) NULL; 526733965Sjdp p = p->next) 526833965Sjdp { 526933965Sjdp asection *input_section; 527033965Sjdp bfd *input_bfd; 527133965Sjdp const struct ecoff_debug_swap *input_swap; 527233965Sjdp struct ecoff_debug_info input_debug; 527333965Sjdp char *eraw_src; 527433965Sjdp char *eraw_end; 527533965Sjdp 527633965Sjdp if (p->type != bfd_indirect_link_order) 527733965Sjdp { 5278104841Sobrien if (p->type == bfd_data_link_order) 527933965Sjdp continue; 528033965Sjdp abort (); 528133965Sjdp } 528233965Sjdp 528333965Sjdp input_section = p->u.indirect.section; 528433965Sjdp input_bfd = input_section->owner; 528533965Sjdp 528633965Sjdp if (bfd_get_flavour (input_bfd) != bfd_target_elf_flavour 528733965Sjdp || (get_elf_backend_data (input_bfd) 528833965Sjdp ->elf_backend_ecoff_debug_swap) == NULL) 528933965Sjdp { 529033965Sjdp /* I don't know what a non ALPHA ELF bfd would be 529133965Sjdp doing with a .mdebug section, but I don't really 529233965Sjdp want to deal with it. */ 529333965Sjdp continue; 529433965Sjdp } 529533965Sjdp 529633965Sjdp input_swap = (get_elf_backend_data (input_bfd) 529733965Sjdp ->elf_backend_ecoff_debug_swap); 529833965Sjdp 529933965Sjdp BFD_ASSERT (p->size == input_section->_raw_size); 530033965Sjdp 530133965Sjdp /* The ECOFF linking code expects that we have already 530233965Sjdp read in the debugging information and set up an 530333965Sjdp ecoff_debug_info structure, so we do that now. */ 530433965Sjdp if (!elf64_alpha_read_ecoff_info (input_bfd, input_section, 530533965Sjdp &input_debug)) 530633965Sjdp return false; 530733965Sjdp 530833965Sjdp if (! (bfd_ecoff_debug_accumulate 530933965Sjdp (mdebug_handle, abfd, &debug, swap, input_bfd, 531033965Sjdp &input_debug, input_swap, info))) 531133965Sjdp return false; 531233965Sjdp 531333965Sjdp /* Loop through the external symbols. For each one with 531433965Sjdp interesting information, try to find the symbol in 531533965Sjdp the linker global hash table and save the information 531633965Sjdp for the output external symbols. */ 531733965Sjdp eraw_src = input_debug.external_ext; 531833965Sjdp eraw_end = (eraw_src 531933965Sjdp + (input_debug.symbolic_header.iextMax 532033965Sjdp * input_swap->external_ext_size)); 532133965Sjdp for (; 532233965Sjdp eraw_src < eraw_end; 532333965Sjdp eraw_src += input_swap->external_ext_size) 532433965Sjdp { 532533965Sjdp EXTR ext; 532633965Sjdp const char *name; 532733965Sjdp struct alpha_elf_link_hash_entry *h; 532833965Sjdp 532933965Sjdp (*input_swap->swap_ext_in) (input_bfd, (PTR) eraw_src, &ext); 533033965Sjdp if (ext.asym.sc == scNil 533133965Sjdp || ext.asym.sc == scUndefined 533233965Sjdp || ext.asym.sc == scSUndefined) 533333965Sjdp continue; 533433965Sjdp 533533965Sjdp name = input_debug.ssext + ext.asym.iss; 533633965Sjdp h = alpha_elf_link_hash_lookup (alpha_elf_hash_table (info), 533733965Sjdp name, false, false, true); 533833965Sjdp if (h == NULL || h->esym.ifd != -2) 533933965Sjdp continue; 534033965Sjdp 534133965Sjdp if (ext.ifd != -1) 534233965Sjdp { 534333965Sjdp BFD_ASSERT (ext.ifd 534433965Sjdp < input_debug.symbolic_header.ifdMax); 534533965Sjdp ext.ifd = input_debug.ifdmap[ext.ifd]; 534633965Sjdp } 534733965Sjdp 534833965Sjdp h->esym = ext; 534933965Sjdp } 535033965Sjdp 535133965Sjdp /* Free up the information we just read. */ 535233965Sjdp free (input_debug.line); 535333965Sjdp free (input_debug.external_dnr); 535433965Sjdp free (input_debug.external_pdr); 535533965Sjdp free (input_debug.external_sym); 535633965Sjdp free (input_debug.external_opt); 535733965Sjdp free (input_debug.external_aux); 535833965Sjdp free (input_debug.ss); 535933965Sjdp free (input_debug.ssext); 536033965Sjdp free (input_debug.external_fdr); 536133965Sjdp free (input_debug.external_rfd); 536233965Sjdp free (input_debug.external_ext); 536333965Sjdp 536433965Sjdp /* Hack: reset the SEC_HAS_CONTENTS flag so that 536533965Sjdp elf_link_input_bfd ignores this section. */ 536633965Sjdp input_section->flags &=~ SEC_HAS_CONTENTS; 536733965Sjdp } 536833965Sjdp 536933965Sjdp /* Build the external symbol information. */ 537033965Sjdp einfo.abfd = abfd; 537133965Sjdp einfo.info = info; 537233965Sjdp einfo.debug = &debug; 537333965Sjdp einfo.swap = swap; 537433965Sjdp einfo.failed = false; 537533965Sjdp elf_link_hash_traverse (elf_hash_table (info), 537633965Sjdp elf64_alpha_output_extsym, 537733965Sjdp (PTR) &einfo); 537833965Sjdp if (einfo.failed) 537933965Sjdp return false; 538033965Sjdp 538133965Sjdp /* Set the size of the .mdebug section. */ 538233965Sjdp o->_raw_size = bfd_ecoff_debug_size (abfd, &debug, swap); 538333965Sjdp 538433965Sjdp /* Skip this section later on (I don't think this currently 538533965Sjdp matters, but someday it might). */ 538633965Sjdp o->link_order_head = (struct bfd_link_order *) NULL; 538733965Sjdp 538833965Sjdp mdebug_sec = o; 538933965Sjdp } 539033965Sjdp } 539133965Sjdp 539233965Sjdp /* Invoke the regular ELF backend linker to do all the work. */ 539333965Sjdp if (! bfd_elf64_bfd_final_link (abfd, info)) 539433965Sjdp return false; 539533965Sjdp 539633965Sjdp /* Now write out the computed sections. */ 539733965Sjdp 539833965Sjdp /* The .got subsections... */ 539933965Sjdp { 540033965Sjdp bfd *i, *dynobj = elf_hash_table(info)->dynobj; 540133965Sjdp for (i = alpha_elf_hash_table(info)->got_list; 540233965Sjdp i != NULL; 540333965Sjdp i = alpha_elf_tdata(i)->got_link_next) 540433965Sjdp { 540533965Sjdp asection *sgot; 540633965Sjdp 540733965Sjdp /* elf_bfd_final_link already did everything in dynobj. */ 540833965Sjdp if (i == dynobj) 540933965Sjdp continue; 541033965Sjdp 541133965Sjdp sgot = alpha_elf_tdata(i)->got; 541233965Sjdp if (! bfd_set_section_contents (abfd, sgot->output_section, 541389862Sobrien sgot->contents, 541489862Sobrien (file_ptr) sgot->output_offset, 541533965Sjdp sgot->_raw_size)) 541633965Sjdp return false; 541733965Sjdp } 541833965Sjdp } 541933965Sjdp 542033965Sjdp if (mdebug_sec != (asection *) NULL) 542133965Sjdp { 542233965Sjdp BFD_ASSERT (abfd->output_has_begun); 542333965Sjdp if (! bfd_ecoff_write_accumulated_debug (mdebug_handle, abfd, &debug, 542433965Sjdp swap, info, 542533965Sjdp mdebug_sec->filepos)) 542633965Sjdp return false; 542733965Sjdp 542833965Sjdp bfd_ecoff_debug_free (mdebug_handle, abfd, &debug, swap, info); 542933965Sjdp } 543033965Sjdp 543189862Sobrien return true; 543289862Sobrien} 543333965Sjdp 543489862Sobrienstatic enum elf_reloc_type_class 543589862Sobrienelf64_alpha_reloc_type_class (rela) 543689862Sobrien const Elf_Internal_Rela *rela; 543789862Sobrien{ 543889862Sobrien switch ((int) ELF64_R_TYPE (rela->r_info)) 543933965Sjdp { 544089862Sobrien case R_ALPHA_RELATIVE: 544189862Sobrien return reloc_class_relative; 544289862Sobrien case R_ALPHA_JMP_SLOT: 544389862Sobrien return reloc_class_plt; 544489862Sobrien case R_ALPHA_COPY: 544589862Sobrien return reloc_class_copy; 544689862Sobrien default: 544789862Sobrien return reloc_class_normal; 544833965Sjdp } 544933965Sjdp} 545033965Sjdp 545133965Sjdp/* ECOFF swapping routines. These are used when dealing with the 545233965Sjdp .mdebug section, which is in the ECOFF debugging format. Copied 545377303Sobrien from elf32-mips.c. */ 545433965Sjdpstatic const struct ecoff_debug_swap 545533965Sjdpelf64_alpha_ecoff_debug_swap = 545633965Sjdp{ 545733965Sjdp /* Symbol table magic number. */ 545833965Sjdp magicSym2, 545933965Sjdp /* Alignment of debugging information. E.g., 4. */ 546033965Sjdp 8, 546133965Sjdp /* Sizes of external symbolic information. */ 546233965Sjdp sizeof (struct hdr_ext), 546333965Sjdp sizeof (struct dnr_ext), 546433965Sjdp sizeof (struct pdr_ext), 546533965Sjdp sizeof (struct sym_ext), 546633965Sjdp sizeof (struct opt_ext), 546733965Sjdp sizeof (struct fdr_ext), 546833965Sjdp sizeof (struct rfd_ext), 546933965Sjdp sizeof (struct ext_ext), 547033965Sjdp /* Functions to swap in external symbolic data. */ 547133965Sjdp ecoff_swap_hdr_in, 547233965Sjdp ecoff_swap_dnr_in, 547333965Sjdp ecoff_swap_pdr_in, 547433965Sjdp ecoff_swap_sym_in, 547533965Sjdp ecoff_swap_opt_in, 547633965Sjdp ecoff_swap_fdr_in, 547733965Sjdp ecoff_swap_rfd_in, 547833965Sjdp ecoff_swap_ext_in, 547933965Sjdp _bfd_ecoff_swap_tir_in, 548033965Sjdp _bfd_ecoff_swap_rndx_in, 548133965Sjdp /* Functions to swap out external symbolic data. */ 548233965Sjdp ecoff_swap_hdr_out, 548333965Sjdp ecoff_swap_dnr_out, 548433965Sjdp ecoff_swap_pdr_out, 548533965Sjdp ecoff_swap_sym_out, 548633965Sjdp ecoff_swap_opt_out, 548733965Sjdp ecoff_swap_fdr_out, 548833965Sjdp ecoff_swap_rfd_out, 548933965Sjdp ecoff_swap_ext_out, 549033965Sjdp _bfd_ecoff_swap_tir_out, 549133965Sjdp _bfd_ecoff_swap_rndx_out, 549233965Sjdp /* Function to read in symbolic data. */ 549333965Sjdp elf64_alpha_read_ecoff_info 549433965Sjdp}; 549533965Sjdp 549677303Sobrien/* Use a non-standard hash bucket size of 8. */ 549777303Sobrien 5498104841Sobrienstatic const struct elf_size_info alpha_elf_size_info = 549977303Sobrien{ 550077303Sobrien sizeof (Elf64_External_Ehdr), 550177303Sobrien sizeof (Elf64_External_Phdr), 550277303Sobrien sizeof (Elf64_External_Shdr), 550377303Sobrien sizeof (Elf64_External_Rel), 550477303Sobrien sizeof (Elf64_External_Rela), 550577303Sobrien sizeof (Elf64_External_Sym), 550677303Sobrien sizeof (Elf64_External_Dyn), 550777303Sobrien sizeof (Elf_External_Note), 550877303Sobrien 8, 550977303Sobrien 1, 551077303Sobrien 64, 8, 551177303Sobrien ELFCLASS64, EV_CURRENT, 551277303Sobrien bfd_elf64_write_out_phdrs, 551377303Sobrien bfd_elf64_write_shdrs_and_ehdr, 551477303Sobrien bfd_elf64_write_relocs, 5515104841Sobrien bfd_elf64_swap_symbol_in, 551677303Sobrien bfd_elf64_swap_symbol_out, 551777303Sobrien bfd_elf64_slurp_reloc_table, 551877303Sobrien bfd_elf64_slurp_symbol_table, 551977303Sobrien bfd_elf64_swap_dyn_in, 552077303Sobrien bfd_elf64_swap_dyn_out, 552177303Sobrien NULL, 552277303Sobrien NULL, 552377303Sobrien NULL, 552477303Sobrien NULL 552577303Sobrien}; 552677303Sobrien 5527104841Sobrien#ifndef ELF_ARCH 552833965Sjdp#define TARGET_LITTLE_SYM bfd_elf64_alpha_vec 552933965Sjdp#define TARGET_LITTLE_NAME "elf64-alpha" 553033965Sjdp#define ELF_ARCH bfd_arch_alpha 553178833Sobrien#define ELF_MACHINE_CODE EM_ALPHA 553278833Sobrien#define ELF_MAXPAGESIZE 0x10000 5533104841Sobrien#endif /* ELF_ARCH */ 553433965Sjdp 553533965Sjdp#define bfd_elf64_bfd_link_hash_table_create \ 553633965Sjdp elf64_alpha_bfd_link_hash_table_create 553733965Sjdp 553833965Sjdp#define bfd_elf64_bfd_reloc_type_lookup \ 553933965Sjdp elf64_alpha_bfd_reloc_type_lookup 554033965Sjdp#define elf_info_to_howto \ 554133965Sjdp elf64_alpha_info_to_howto 554233965Sjdp 554333965Sjdp#define bfd_elf64_mkobject \ 554433965Sjdp elf64_alpha_mkobject 554533965Sjdp#define elf_backend_object_p \ 554633965Sjdp elf64_alpha_object_p 554733965Sjdp 554833965Sjdp#define elf_backend_section_from_shdr \ 554933965Sjdp elf64_alpha_section_from_shdr 555089862Sobrien#define elf_backend_section_flags \ 555189862Sobrien elf64_alpha_section_flags 555233965Sjdp#define elf_backend_fake_sections \ 555333965Sjdp elf64_alpha_fake_sections 555433965Sjdp 555533965Sjdp#define bfd_elf64_bfd_is_local_label_name \ 555633965Sjdp elf64_alpha_is_local_label_name 555733965Sjdp#define bfd_elf64_find_nearest_line \ 555833965Sjdp elf64_alpha_find_nearest_line 555960510Sobrien#define bfd_elf64_bfd_relax_section \ 556060510Sobrien elf64_alpha_relax_section 556133965Sjdp 556260510Sobrien#define elf_backend_add_symbol_hook \ 556360510Sobrien elf64_alpha_add_symbol_hook 556433965Sjdp#define elf_backend_check_relocs \ 556533965Sjdp elf64_alpha_check_relocs 556633965Sjdp#define elf_backend_create_dynamic_sections \ 556733965Sjdp elf64_alpha_create_dynamic_sections 556833965Sjdp#define elf_backend_adjust_dynamic_symbol \ 556933965Sjdp elf64_alpha_adjust_dynamic_symbol 557033965Sjdp#define elf_backend_always_size_sections \ 557133965Sjdp elf64_alpha_always_size_sections 557233965Sjdp#define elf_backend_size_dynamic_sections \ 557333965Sjdp elf64_alpha_size_dynamic_sections 557433965Sjdp#define elf_backend_relocate_section \ 557533965Sjdp elf64_alpha_relocate_section 557633965Sjdp#define elf_backend_finish_dynamic_symbol \ 557733965Sjdp elf64_alpha_finish_dynamic_symbol 557833965Sjdp#define elf_backend_finish_dynamic_sections \ 557933965Sjdp elf64_alpha_finish_dynamic_sections 558033965Sjdp#define bfd_elf64_bfd_final_link \ 558133965Sjdp elf64_alpha_final_link 558289862Sobrien#define elf_backend_reloc_type_class \ 558389862Sobrien elf64_alpha_reloc_type_class 558433965Sjdp 558533965Sjdp#define elf_backend_ecoff_debug_swap \ 558633965Sjdp &elf64_alpha_ecoff_debug_swap 558733965Sjdp 558877303Sobrien#define elf_backend_size_info \ 558977303Sobrien alpha_elf_size_info 559077303Sobrien 559177303Sobrien/* A few constants that determine how the .plt section is set up. */ 559233965Sjdp#define elf_backend_want_got_plt 0 559333965Sjdp#define elf_backend_plt_readonly 0 559433965Sjdp#define elf_backend_want_plt_sym 1 559560510Sobrien#define elf_backend_got_header_size 0 559660510Sobrien#define elf_backend_plt_header_size PLT_HEADER_SIZE 559733965Sjdp 559833965Sjdp#include "elf64-target.h" 5599