elf64-alpha.c revision 77303
133965Sjdp/* Alpha specific support for 64-bit ELF 260510Sobrien Copyright 1996, 97, 98, 1999 Free Software Foundation, Inc. 333965Sjdp Contributed by Richard Henderson <rth@tamu.edu>. 433965Sjdp 533965SjdpThis file is part of BFD, the Binary File Descriptor library. 633965Sjdp 733965SjdpThis program is free software; you can redistribute it and/or modify 833965Sjdpit under the terms of the GNU General Public License as published by 933965Sjdpthe Free Software Foundation; either version 2 of the License, or 1033965Sjdp(at your option) any later version. 1133965Sjdp 1233965SjdpThis program is distributed in the hope that it will be useful, 1333965Sjdpbut WITHOUT ANY WARRANTY; without even the implied warranty of 1433965SjdpMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1533965SjdpGNU General Public License for more details. 1633965Sjdp 1733965SjdpYou should have received a copy of the GNU General Public License 1833965Sjdpalong with this program; if not, write to the Free Software 1933965SjdpFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 2033965Sjdp 2157406Sjdp/* $FreeBSD: head/contrib/binutils/bfd/elf64-alpha.c 77303 2001-05-28 05:53:00Z obrien $ */ 2257406Sjdp 2333965Sjdp/* We need a published ABI spec for this. Until one comes out, don't 2433965Sjdp assume this'll remain unchanged forever. */ 2533965Sjdp 2633965Sjdp#include "bfd.h" 2733965Sjdp#include "sysdep.h" 2833965Sjdp#include "libbfd.h" 2933965Sjdp#include "elf-bfd.h" 3033965Sjdp 3133965Sjdp#include "elf/alpha.h" 3233965Sjdp 3333965Sjdp#define ALPHAECOFF 3433965Sjdp 3533965Sjdp#define NO_COFF_RELOCS 3633965Sjdp#define NO_COFF_SYMBOLS 3733965Sjdp#define NO_COFF_LINENOS 3833965Sjdp 3977303Sobrien/* Get the ECOFF swapping routines. Needed for the debug information. */ 4033965Sjdp#include "coff/internal.h" 4133965Sjdp#include "coff/sym.h" 4233965Sjdp#include "coff/symconst.h" 4333965Sjdp#include "coff/ecoff.h" 4433965Sjdp#include "coff/alpha.h" 4533965Sjdp#include "aout/ar.h" 4633965Sjdp#include "libcoff.h" 4733965Sjdp#include "libecoff.h" 4833965Sjdp#define ECOFF_64 4933965Sjdp#include "ecoffswap.h" 5033965Sjdp 5177303Sobrienstatic int alpha_elf_dynamic_symbol_p 5277303Sobrien PARAMS((struct elf_link_hash_entry *, struct bfd_link_info *)); 5333965Sjdpstatic struct bfd_hash_entry * elf64_alpha_link_hash_newfunc 5433965Sjdp PARAMS((struct bfd_hash_entry *, struct bfd_hash_table *, const char *)); 5533965Sjdpstatic struct bfd_link_hash_table * elf64_alpha_bfd_link_hash_table_create 5633965Sjdp PARAMS((bfd *)); 5733965Sjdp 5833965Sjdpstatic bfd_reloc_status_type elf64_alpha_reloc_nil 5933965Sjdp PARAMS((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); 6033965Sjdpstatic bfd_reloc_status_type elf64_alpha_reloc_bad 6133965Sjdp PARAMS((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); 6233965Sjdpstatic bfd_reloc_status_type elf64_alpha_do_reloc_gpdisp 6333965Sjdp PARAMS((bfd *, bfd_vma, bfd_byte *, bfd_byte *)); 6433965Sjdpstatic bfd_reloc_status_type elf64_alpha_reloc_gpdisp 6533965Sjdp PARAMS((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); 6633965Sjdp 6733965Sjdpstatic reloc_howto_type * elf64_alpha_bfd_reloc_type_lookup 6833965Sjdp PARAMS((bfd *, bfd_reloc_code_real_type)); 6933965Sjdpstatic void elf64_alpha_info_to_howto 7033965Sjdp PARAMS((bfd *, arelent *, Elf64_Internal_Rela *)); 7133965Sjdp 7277303Sobrienstatic boolean elf64_alpha_mkobject 7377303Sobrien PARAMS((bfd *)); 7433965Sjdpstatic boolean elf64_alpha_object_p 7533965Sjdp PARAMS((bfd *)); 7633965Sjdpstatic boolean elf64_alpha_section_from_shdr 7733965Sjdp PARAMS((bfd *, Elf64_Internal_Shdr *, char *)); 7833965Sjdpstatic boolean elf64_alpha_fake_sections 7933965Sjdp PARAMS((bfd *, Elf64_Internal_Shdr *, asection *)); 8033965Sjdpstatic boolean elf64_alpha_create_got_section 8133965Sjdp PARAMS((bfd *, struct bfd_link_info *)); 8233965Sjdpstatic boolean elf64_alpha_create_dynamic_sections 8333965Sjdp PARAMS((bfd *, struct bfd_link_info *)); 8433965Sjdp 8533965Sjdpstatic boolean elf64_alpha_read_ecoff_info 8633965Sjdp PARAMS((bfd *, asection *, struct ecoff_debug_info *)); 8733965Sjdpstatic boolean elf64_alpha_is_local_label_name 8833965Sjdp PARAMS((bfd *, const char *)); 8933965Sjdpstatic boolean elf64_alpha_find_nearest_line 9033965Sjdp PARAMS((bfd *, asection *, asymbol **, bfd_vma, const char **, 9133965Sjdp const char **, unsigned int *)); 9233965Sjdp 9333965Sjdp#if defined(__STDC__) || defined(ALMOST_STDC) 9433965Sjdpstruct alpha_elf_link_hash_entry; 9533965Sjdp#endif 9633965Sjdp 9733965Sjdpstatic boolean elf64_alpha_output_extsym 9833965Sjdp PARAMS((struct alpha_elf_link_hash_entry *, PTR)); 9933965Sjdp 10033965Sjdpstatic boolean elf64_alpha_can_merge_gots 10133965Sjdp PARAMS((bfd *, bfd *)); 10233965Sjdpstatic void elf64_alpha_merge_gots 10333965Sjdp PARAMS((bfd *, bfd *)); 10433965Sjdpstatic boolean elf64_alpha_calc_got_offsets_for_symbol 10533965Sjdp PARAMS ((struct alpha_elf_link_hash_entry *, PTR)); 10633965Sjdpstatic void elf64_alpha_calc_got_offsets PARAMS ((struct bfd_link_info *)); 10760510Sobrienstatic boolean elf64_alpha_size_got_sections 10860510Sobrien PARAMS ((bfd *, struct bfd_link_info *)); 10933965Sjdpstatic boolean elf64_alpha_always_size_sections 11033965Sjdp PARAMS ((bfd *, struct bfd_link_info *)); 11133965Sjdpstatic boolean elf64_alpha_calc_dynrel_sizes 11233965Sjdp PARAMS ((struct alpha_elf_link_hash_entry *, struct bfd_link_info *)); 11360510Sobrienstatic boolean elf64_alpha_add_symbol_hook 11460510Sobrien PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Sym *, 11560510Sobrien const char **, flagword *, asection **, bfd_vma *)); 11633965Sjdpstatic boolean elf64_alpha_check_relocs 11733965Sjdp PARAMS((bfd *, struct bfd_link_info *, asection *sec, 11833965Sjdp const Elf_Internal_Rela *)); 11933965Sjdpstatic boolean elf64_alpha_adjust_dynamic_symbol 12033965Sjdp PARAMS((struct bfd_link_info *, struct elf_link_hash_entry *)); 12133965Sjdpstatic boolean elf64_alpha_size_dynamic_sections 12233965Sjdp PARAMS((bfd *, struct bfd_link_info *)); 12333965Sjdpstatic boolean elf64_alpha_relocate_section 12433965Sjdp PARAMS((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, 12533965Sjdp Elf_Internal_Rela *, Elf_Internal_Sym *, asection **)); 12633965Sjdpstatic boolean elf64_alpha_finish_dynamic_symbol 12733965Sjdp PARAMS((bfd *, struct bfd_link_info *, struct elf_link_hash_entry *, 12833965Sjdp Elf_Internal_Sym *)); 12933965Sjdpstatic boolean elf64_alpha_finish_dynamic_sections 13033965Sjdp PARAMS((bfd *, struct bfd_link_info *)); 13133965Sjdpstatic boolean elf64_alpha_final_link 13233965Sjdp PARAMS((bfd *, struct bfd_link_info *)); 13348850Sdfrstatic boolean elf64_alpha_merge_ind_symbols 13448850Sdfr PARAMS((struct alpha_elf_link_hash_entry *, PTR)); 13560510Sobrienstatic Elf_Internal_Rela * elf64_alpha_find_reloc_at_ofs 13660510Sobrien PARAMS ((Elf_Internal_Rela *, Elf_Internal_Rela *, bfd_vma, int)); 13733965Sjdp 13833965Sjdpstruct alpha_elf_link_hash_entry 13933965Sjdp{ 14033965Sjdp struct elf_link_hash_entry root; 14133965Sjdp 14233965Sjdp /* External symbol information. */ 14333965Sjdp EXTR esym; 14433965Sjdp 14533965Sjdp /* Cumulative flags for all the .got entries. */ 14633965Sjdp int flags; 14733965Sjdp 14833965Sjdp /* Contexts (LITUSE) in which a literal was referenced. */ 14933965Sjdp#define ALPHA_ELF_LINK_HASH_LU_ADDR 0x01 15033965Sjdp#define ALPHA_ELF_LINK_HASH_LU_MEM 0x02 15133965Sjdp#define ALPHA_ELF_LINK_HASH_LU_BYTE 0x04 15233965Sjdp#define ALPHA_ELF_LINK_HASH_LU_FUNC 0x08 15333965Sjdp 15433965Sjdp /* Used to implement multiple .got subsections. */ 15533965Sjdp struct alpha_elf_got_entry 15633965Sjdp { 15733965Sjdp struct alpha_elf_got_entry *next; 15833965Sjdp 15933965Sjdp /* which .got subsection? */ 16033965Sjdp bfd *gotobj; 16133965Sjdp 16233965Sjdp /* the addend in effect for this entry. */ 16333965Sjdp bfd_vma addend; 16433965Sjdp 16533965Sjdp /* the .got offset for this entry. */ 16633965Sjdp int got_offset; 16733965Sjdp 16833965Sjdp int flags; 16933965Sjdp 17033965Sjdp /* An additional flag. */ 17133965Sjdp#define ALPHA_ELF_GOT_ENTRY_RELOCS_DONE 0x10 17260510Sobrien 17360510Sobrien int use_count; 17433965Sjdp } *got_entries; 17533965Sjdp 17633965Sjdp /* used to count non-got, non-plt relocations for delayed sizing 17733965Sjdp of relocation sections. */ 17833965Sjdp struct alpha_elf_reloc_entry 17933965Sjdp { 18033965Sjdp struct alpha_elf_reloc_entry *next; 18133965Sjdp 18233965Sjdp /* which .reloc section? */ 18333965Sjdp asection *srel; 18433965Sjdp 18533965Sjdp /* what kind of relocation? */ 18633965Sjdp unsigned long rtype; 18733965Sjdp 18833965Sjdp /* how many did we find? */ 18933965Sjdp unsigned long count; 19033965Sjdp } *reloc_entries; 19133965Sjdp}; 19233965Sjdp 19333965Sjdp/* Alpha ELF linker hash table. */ 19433965Sjdp 19533965Sjdpstruct alpha_elf_link_hash_table 19633965Sjdp{ 19733965Sjdp struct elf_link_hash_table root; 19833965Sjdp 19933965Sjdp /* The head of a list of .got subsections linked through 20033965Sjdp alpha_elf_tdata(abfd)->got_link_next. */ 20133965Sjdp bfd *got_list; 20233965Sjdp}; 20333965Sjdp 20433965Sjdp/* Look up an entry in a Alpha ELF linker hash table. */ 20533965Sjdp 20633965Sjdp#define alpha_elf_link_hash_lookup(table, string, create, copy, follow) \ 20733965Sjdp ((struct alpha_elf_link_hash_entry *) \ 20833965Sjdp elf_link_hash_lookup (&(table)->root, (string), (create), \ 20933965Sjdp (copy), (follow))) 21033965Sjdp 21133965Sjdp/* Traverse a Alpha ELF linker hash table. */ 21233965Sjdp 21333965Sjdp#define alpha_elf_link_hash_traverse(table, func, info) \ 21433965Sjdp (elf_link_hash_traverse \ 21533965Sjdp (&(table)->root, \ 21633965Sjdp (boolean (*) PARAMS ((struct elf_link_hash_entry *, PTR))) (func), \ 21733965Sjdp (info))) 21833965Sjdp 21933965Sjdp/* Get the Alpha ELF linker hash table from a link_info structure. */ 22033965Sjdp 22133965Sjdp#define alpha_elf_hash_table(p) \ 22233965Sjdp ((struct alpha_elf_link_hash_table *) ((p)->hash)) 22333965Sjdp 22433965Sjdp/* Get the object's symbols as our own entry type. */ 22533965Sjdp 22633965Sjdp#define alpha_elf_sym_hashes(abfd) \ 22733965Sjdp ((struct alpha_elf_link_hash_entry **)elf_sym_hashes(abfd)) 22833965Sjdp 22933965Sjdp/* Should we do dynamic things to this symbol? */ 23033965Sjdp 23177303Sobrienstatic int 23277303Sobrienalpha_elf_dynamic_symbol_p (h, info) 23377303Sobrien struct elf_link_hash_entry *h; 23477303Sobrien struct bfd_link_info *info; 23577303Sobrien{ 23677303Sobrien if (h == NULL) 23777303Sobrien return false; 23833965Sjdp 23977303Sobrien while (h->root.type == bfd_link_hash_indirect 24077303Sobrien || h->root.type == bfd_link_hash_warning) 24177303Sobrien h = (struct elf_link_hash_entry *) h->root.u.i.link; 24277303Sobrien 24377303Sobrien if (h->dynindx == -1) 24477303Sobrien return false; 24577303Sobrien if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT) 24677303Sobrien return false; 24777303Sobrien 24877303Sobrien if (h->root.type == bfd_link_hash_undefweak 24977303Sobrien || h->root.type == bfd_link_hash_defweak) 25077303Sobrien return true; 25177303Sobrien 25277303Sobrien if ((info->shared && !info->symbolic) 25377303Sobrien || ((h->elf_link_hash_flags 25477303Sobrien & (ELF_LINK_HASH_DEF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR)) 25577303Sobrien == (ELF_LINK_HASH_DEF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR))) 25677303Sobrien return true; 25777303Sobrien 25877303Sobrien return false; 25977303Sobrien} 26077303Sobrien 26133965Sjdp/* Create an entry in a Alpha ELF linker hash table. */ 26233965Sjdp 26333965Sjdpstatic struct bfd_hash_entry * 26433965Sjdpelf64_alpha_link_hash_newfunc (entry, table, string) 26533965Sjdp struct bfd_hash_entry *entry; 26633965Sjdp struct bfd_hash_table *table; 26733965Sjdp const char *string; 26833965Sjdp{ 26933965Sjdp struct alpha_elf_link_hash_entry *ret = 27033965Sjdp (struct alpha_elf_link_hash_entry *) entry; 27133965Sjdp 27233965Sjdp /* Allocate the structure if it has not already been allocated by a 27333965Sjdp subclass. */ 27433965Sjdp if (ret == (struct alpha_elf_link_hash_entry *) NULL) 27533965Sjdp ret = ((struct alpha_elf_link_hash_entry *) 27633965Sjdp bfd_hash_allocate (table, 27733965Sjdp sizeof (struct alpha_elf_link_hash_entry))); 27833965Sjdp if (ret == (struct alpha_elf_link_hash_entry *) NULL) 27933965Sjdp return (struct bfd_hash_entry *) ret; 28033965Sjdp 28133965Sjdp /* Call the allocation method of the superclass. */ 28233965Sjdp ret = ((struct alpha_elf_link_hash_entry *) 28333965Sjdp _bfd_elf_link_hash_newfunc ((struct bfd_hash_entry *) ret, 28433965Sjdp table, string)); 28533965Sjdp if (ret != (struct alpha_elf_link_hash_entry *) NULL) 28633965Sjdp { 28733965Sjdp /* Set local fields. */ 28833965Sjdp memset (&ret->esym, 0, sizeof (EXTR)); 28933965Sjdp /* We use -2 as a marker to indicate that the information has 29033965Sjdp not been set. -1 means there is no associated ifd. */ 29133965Sjdp ret->esym.ifd = -2; 29233965Sjdp ret->flags = 0; 29333965Sjdp ret->got_entries = NULL; 29433965Sjdp ret->reloc_entries = NULL; 29533965Sjdp } 29633965Sjdp 29733965Sjdp return (struct bfd_hash_entry *) ret; 29833965Sjdp} 29933965Sjdp 30033965Sjdp/* Create a Alpha ELF linker hash table. */ 30133965Sjdp 30233965Sjdpstatic struct bfd_link_hash_table * 30333965Sjdpelf64_alpha_bfd_link_hash_table_create (abfd) 30433965Sjdp bfd *abfd; 30533965Sjdp{ 30633965Sjdp struct alpha_elf_link_hash_table *ret; 30733965Sjdp 30833965Sjdp ret = ((struct alpha_elf_link_hash_table *) 30933965Sjdp bfd_zalloc (abfd, sizeof (struct alpha_elf_link_hash_table))); 31033965Sjdp if (ret == (struct alpha_elf_link_hash_table *) NULL) 31133965Sjdp return NULL; 31233965Sjdp 31333965Sjdp if (! _bfd_elf_link_hash_table_init (&ret->root, abfd, 31433965Sjdp elf64_alpha_link_hash_newfunc)) 31533965Sjdp { 31633965Sjdp bfd_release (abfd, ret); 31733965Sjdp return NULL; 31833965Sjdp } 31933965Sjdp 32033965Sjdp return &ret->root.root; 32133965Sjdp} 32233965Sjdp 32333965Sjdp/* We have some private fields hanging off of the elf_tdata structure. */ 32433965Sjdp 32533965Sjdpstruct alpha_elf_obj_tdata 32633965Sjdp{ 32733965Sjdp struct elf_obj_tdata root; 32833965Sjdp 32933965Sjdp /* For every input file, these are the got entries for that object's 33033965Sjdp local symbols. */ 33133965Sjdp struct alpha_elf_got_entry ** local_got_entries; 33233965Sjdp 33333965Sjdp /* For every input file, this is the object that owns the got that 33433965Sjdp this input file uses. */ 33533965Sjdp bfd *gotobj; 33633965Sjdp 33733965Sjdp /* For every got, this is a linked list through the objects using this got */ 33833965Sjdp bfd *in_got_link_next; 33933965Sjdp 34033965Sjdp /* For every got, this is a link to the next got subsegment. */ 34133965Sjdp bfd *got_link_next; 34233965Sjdp 34333965Sjdp /* For every got, this is the section. */ 34433965Sjdp asection *got; 34533965Sjdp 34633965Sjdp /* For every got, this is it's total number of *entries*. */ 34733965Sjdp int total_got_entries; 34833965Sjdp 34933965Sjdp /* For every got, this is the sum of the number of *entries* required 35033965Sjdp to hold all of the member object's local got. */ 35133965Sjdp int n_local_got_entries; 35233965Sjdp}; 35333965Sjdp 35433965Sjdp#define alpha_elf_tdata(abfd) \ 35533965Sjdp ((struct alpha_elf_obj_tdata *) (abfd)->tdata.any) 35633965Sjdp 35733965Sjdpstatic boolean 35833965Sjdpelf64_alpha_mkobject (abfd) 35933965Sjdp bfd *abfd; 36033965Sjdp{ 36133965Sjdp abfd->tdata.any = bfd_zalloc (abfd, sizeof (struct alpha_elf_obj_tdata)); 36233965Sjdp if (abfd->tdata.any == NULL) 36333965Sjdp return false; 36433965Sjdp return true; 36533965Sjdp} 36633965Sjdp 36733965Sjdpstatic boolean 36833965Sjdpelf64_alpha_object_p (abfd) 36933965Sjdp bfd *abfd; 37033965Sjdp{ 37133965Sjdp /* Allocate our special target data. */ 37233965Sjdp struct alpha_elf_obj_tdata *new_tdata; 37333965Sjdp new_tdata = bfd_zalloc (abfd, sizeof (struct alpha_elf_obj_tdata)); 37433965Sjdp if (new_tdata == NULL) 37533965Sjdp return false; 37633965Sjdp new_tdata->root = *abfd->tdata.elf_obj_data; 37733965Sjdp abfd->tdata.any = new_tdata; 37833965Sjdp 37933965Sjdp /* Set the right machine number for an Alpha ELF file. */ 38033965Sjdp return bfd_default_set_arch_mach (abfd, bfd_arch_alpha, 0); 38133965Sjdp} 38233965Sjdp 38333965Sjdp/* In case we're on a 32-bit machine, construct a 64-bit "-1" value 38433965Sjdp from smaller values. Start with zero, widen, *then* decrement. */ 38533965Sjdp#define MINUS_ONE (((bfd_vma)0) - 1) 38633965Sjdp 38733965Sjdpstatic reloc_howto_type elf64_alpha_howto_table[] = 38833965Sjdp{ 38933965Sjdp HOWTO (R_ALPHA_NONE, /* type */ 39033965Sjdp 0, /* rightshift */ 39133965Sjdp 0, /* size (0 = byte, 1 = short, 2 = long) */ 39233965Sjdp 8, /* bitsize */ 39333965Sjdp true, /* pc_relative */ 39433965Sjdp 0, /* bitpos */ 39533965Sjdp complain_overflow_dont, /* complain_on_overflow */ 39633965Sjdp elf64_alpha_reloc_nil, /* special_function */ 39733965Sjdp "NONE", /* name */ 39833965Sjdp false, /* partial_inplace */ 39933965Sjdp 0, /* src_mask */ 40033965Sjdp 0, /* dst_mask */ 40133965Sjdp true), /* pcrel_offset */ 40233965Sjdp 40333965Sjdp /* A 32 bit reference to a symbol. */ 40433965Sjdp HOWTO (R_ALPHA_REFLONG, /* type */ 40533965Sjdp 0, /* rightshift */ 40633965Sjdp 2, /* size (0 = byte, 1 = short, 2 = long) */ 40733965Sjdp 32, /* bitsize */ 40833965Sjdp false, /* pc_relative */ 40933965Sjdp 0, /* bitpos */ 41033965Sjdp complain_overflow_bitfield, /* complain_on_overflow */ 41133965Sjdp 0, /* special_function */ 41233965Sjdp "REFLONG", /* name */ 41333965Sjdp false, /* partial_inplace */ 41433965Sjdp 0xffffffff, /* src_mask */ 41533965Sjdp 0xffffffff, /* dst_mask */ 41633965Sjdp false), /* pcrel_offset */ 41733965Sjdp 41833965Sjdp /* A 64 bit reference to a symbol. */ 41933965Sjdp HOWTO (R_ALPHA_REFQUAD, /* type */ 42033965Sjdp 0, /* rightshift */ 42133965Sjdp 4, /* size (0 = byte, 1 = short, 2 = long) */ 42233965Sjdp 64, /* bitsize */ 42333965Sjdp false, /* pc_relative */ 42433965Sjdp 0, /* bitpos */ 42533965Sjdp complain_overflow_bitfield, /* complain_on_overflow */ 42633965Sjdp 0, /* special_function */ 42733965Sjdp "REFQUAD", /* name */ 42833965Sjdp false, /* partial_inplace */ 42933965Sjdp MINUS_ONE, /* src_mask */ 43033965Sjdp MINUS_ONE, /* dst_mask */ 43133965Sjdp false), /* pcrel_offset */ 43233965Sjdp 43333965Sjdp /* A 32 bit GP relative offset. This is just like REFLONG except 43433965Sjdp that when the value is used the value of the gp register will be 43533965Sjdp added in. */ 43633965Sjdp HOWTO (R_ALPHA_GPREL32, /* type */ 43733965Sjdp 0, /* rightshift */ 43833965Sjdp 2, /* size (0 = byte, 1 = short, 2 = long) */ 43933965Sjdp 32, /* bitsize */ 44033965Sjdp false, /* pc_relative */ 44133965Sjdp 0, /* bitpos */ 44233965Sjdp complain_overflow_bitfield, /* complain_on_overflow */ 44333965Sjdp 0, /* special_function */ 44433965Sjdp "GPREL32", /* name */ 44533965Sjdp false, /* partial_inplace */ 44633965Sjdp 0xffffffff, /* src_mask */ 44733965Sjdp 0xffffffff, /* dst_mask */ 44833965Sjdp false), /* pcrel_offset */ 44933965Sjdp 45033965Sjdp /* Used for an instruction that refers to memory off the GP register. */ 45133965Sjdp HOWTO (R_ALPHA_LITERAL, /* type */ 45233965Sjdp 0, /* rightshift */ 45333965Sjdp 2, /* size (0 = byte, 1 = short, 2 = long) */ 45433965Sjdp 16, /* bitsize */ 45533965Sjdp false, /* pc_relative */ 45633965Sjdp 0, /* bitpos */ 45733965Sjdp complain_overflow_signed, /* complain_on_overflow */ 45833965Sjdp 0, /* special_function */ 45933965Sjdp "ELF_LITERAL", /* name */ 46033965Sjdp false, /* partial_inplace */ 46133965Sjdp 0xffff, /* src_mask */ 46233965Sjdp 0xffff, /* dst_mask */ 46333965Sjdp false), /* pcrel_offset */ 46433965Sjdp 46533965Sjdp /* This reloc only appears immediately following an ELF_LITERAL reloc. 46633965Sjdp It identifies a use of the literal. The symbol index is special: 46733965Sjdp 1 means the literal address is in the base register of a memory 46833965Sjdp format instruction; 2 means the literal address is in the byte 46933965Sjdp offset register of a byte-manipulation instruction; 3 means the 47033965Sjdp literal address is in the target register of a jsr instruction. 47133965Sjdp This does not actually do any relocation. */ 47233965Sjdp HOWTO (R_ALPHA_LITUSE, /* type */ 47333965Sjdp 0, /* rightshift */ 47433965Sjdp 2, /* size (0 = byte, 1 = short, 2 = long) */ 47533965Sjdp 32, /* bitsize */ 47633965Sjdp false, /* pc_relative */ 47733965Sjdp 0, /* bitpos */ 47833965Sjdp complain_overflow_dont, /* complain_on_overflow */ 47933965Sjdp elf64_alpha_reloc_nil, /* special_function */ 48033965Sjdp "LITUSE", /* name */ 48133965Sjdp false, /* partial_inplace */ 48233965Sjdp 0, /* src_mask */ 48333965Sjdp 0, /* dst_mask */ 48433965Sjdp false), /* pcrel_offset */ 48533965Sjdp 48633965Sjdp /* Load the gp register. This is always used for a ldah instruction 48733965Sjdp which loads the upper 16 bits of the gp register. The symbol 48833965Sjdp index of the GPDISP instruction is an offset in bytes to the lda 48933965Sjdp instruction that loads the lower 16 bits. The value to use for 49033965Sjdp the relocation is the difference between the GP value and the 49133965Sjdp current location; the load will always be done against a register 49233965Sjdp holding the current address. 49333965Sjdp 49433965Sjdp NOTE: Unlike ECOFF, partial in-place relocation is not done. If 49533965Sjdp any offset is present in the instructions, it is an offset from 49633965Sjdp the register to the ldah instruction. This lets us avoid any 49733965Sjdp stupid hackery like inventing a gp value to do partial relocation 49833965Sjdp against. Also unlike ECOFF, we do the whole relocation off of 49933965Sjdp the GPDISP rather than a GPDISP_HI16/GPDISP_LO16 pair. An odd, 50033965Sjdp space consuming bit, that, since all the information was present 50133965Sjdp in the GPDISP_HI16 reloc. */ 50233965Sjdp HOWTO (R_ALPHA_GPDISP, /* type */ 50333965Sjdp 16, /* rightshift */ 50433965Sjdp 2, /* size (0 = byte, 1 = short, 2 = long) */ 50533965Sjdp 16, /* bitsize */ 50633965Sjdp false, /* pc_relative */ 50733965Sjdp 0, /* bitpos */ 50833965Sjdp complain_overflow_dont, /* complain_on_overflow */ 50933965Sjdp elf64_alpha_reloc_gpdisp, /* special_function */ 51033965Sjdp "GPDISP", /* name */ 51133965Sjdp false, /* partial_inplace */ 51233965Sjdp 0xffff, /* src_mask */ 51333965Sjdp 0xffff, /* dst_mask */ 51433965Sjdp true), /* pcrel_offset */ 51533965Sjdp 51633965Sjdp /* A 21 bit branch. */ 51733965Sjdp HOWTO (R_ALPHA_BRADDR, /* type */ 51833965Sjdp 2, /* rightshift */ 51933965Sjdp 2, /* size (0 = byte, 1 = short, 2 = long) */ 52033965Sjdp 21, /* bitsize */ 52133965Sjdp true, /* pc_relative */ 52233965Sjdp 0, /* bitpos */ 52333965Sjdp complain_overflow_signed, /* complain_on_overflow */ 52433965Sjdp 0, /* special_function */ 52533965Sjdp "BRADDR", /* name */ 52633965Sjdp false, /* partial_inplace */ 52733965Sjdp 0x1fffff, /* src_mask */ 52833965Sjdp 0x1fffff, /* dst_mask */ 52933965Sjdp true), /* pcrel_offset */ 53033965Sjdp 53133965Sjdp /* A hint for a jump to a register. */ 53233965Sjdp HOWTO (R_ALPHA_HINT, /* type */ 53333965Sjdp 2, /* rightshift */ 53433965Sjdp 2, /* size (0 = byte, 1 = short, 2 = long) */ 53533965Sjdp 14, /* bitsize */ 53633965Sjdp true, /* pc_relative */ 53733965Sjdp 0, /* bitpos */ 53833965Sjdp complain_overflow_dont, /* complain_on_overflow */ 53933965Sjdp 0, /* special_function */ 54033965Sjdp "HINT", /* name */ 54133965Sjdp false, /* partial_inplace */ 54233965Sjdp 0x3fff, /* src_mask */ 54333965Sjdp 0x3fff, /* dst_mask */ 54433965Sjdp true), /* pcrel_offset */ 54533965Sjdp 54633965Sjdp /* 16 bit PC relative offset. */ 54733965Sjdp HOWTO (R_ALPHA_SREL16, /* type */ 54833965Sjdp 0, /* rightshift */ 54933965Sjdp 1, /* size (0 = byte, 1 = short, 2 = long) */ 55033965Sjdp 16, /* bitsize */ 55133965Sjdp true, /* pc_relative */ 55233965Sjdp 0, /* bitpos */ 55333965Sjdp complain_overflow_signed, /* complain_on_overflow */ 55433965Sjdp 0, /* special_function */ 55533965Sjdp "SREL16", /* name */ 55633965Sjdp false, /* partial_inplace */ 55733965Sjdp 0xffff, /* src_mask */ 55833965Sjdp 0xffff, /* dst_mask */ 55933965Sjdp false), /* pcrel_offset */ 56033965Sjdp 56133965Sjdp /* 32 bit PC relative offset. */ 56233965Sjdp HOWTO (R_ALPHA_SREL32, /* type */ 56333965Sjdp 0, /* rightshift */ 56433965Sjdp 2, /* size (0 = byte, 1 = short, 2 = long) */ 56533965Sjdp 32, /* bitsize */ 56633965Sjdp true, /* pc_relative */ 56733965Sjdp 0, /* bitpos */ 56833965Sjdp complain_overflow_signed, /* complain_on_overflow */ 56933965Sjdp 0, /* special_function */ 57033965Sjdp "SREL32", /* name */ 57133965Sjdp false, /* partial_inplace */ 57233965Sjdp 0xffffffff, /* src_mask */ 57333965Sjdp 0xffffffff, /* dst_mask */ 57433965Sjdp false), /* pcrel_offset */ 57533965Sjdp 57633965Sjdp /* A 64 bit PC relative offset. */ 57733965Sjdp HOWTO (R_ALPHA_SREL64, /* type */ 57833965Sjdp 0, /* rightshift */ 57933965Sjdp 4, /* size (0 = byte, 1 = short, 2 = long) */ 58033965Sjdp 64, /* bitsize */ 58133965Sjdp true, /* pc_relative */ 58233965Sjdp 0, /* bitpos */ 58333965Sjdp complain_overflow_signed, /* complain_on_overflow */ 58433965Sjdp 0, /* special_function */ 58533965Sjdp "SREL64", /* name */ 58633965Sjdp false, /* partial_inplace */ 58733965Sjdp MINUS_ONE, /* src_mask */ 58833965Sjdp MINUS_ONE, /* dst_mask */ 58933965Sjdp false), /* pcrel_offset */ 59033965Sjdp 59133965Sjdp /* Push a value on the reloc evaluation stack. */ 59238889Sjdp /* Not implemented -- it's dumb. */ 59338889Sjdp HOWTO (R_ALPHA_OP_PUSH, /* type */ 59433965Sjdp 0, /* rightshift */ 59533965Sjdp 0, /* size (0 = byte, 1 = short, 2 = long) */ 59633965Sjdp 0, /* bitsize */ 59733965Sjdp false, /* pc_relative */ 59833965Sjdp 0, /* bitpos */ 59933965Sjdp complain_overflow_dont, /* complain_on_overflow */ 60033965Sjdp elf64_alpha_reloc_bad, /* special_function */ 60133965Sjdp "OP_PUSH", /* name */ 60233965Sjdp false, /* partial_inplace */ 60333965Sjdp 0, /* src_mask */ 60433965Sjdp 0, /* dst_mask */ 60533965Sjdp false), /* pcrel_offset */ 60633965Sjdp 60733965Sjdp /* Store the value from the stack at the given address. Store it in 60833965Sjdp a bitfield of size r_size starting at bit position r_offset. */ 60938889Sjdp /* Not implemented -- it's dumb. */ 61038889Sjdp HOWTO (R_ALPHA_OP_STORE, /* type */ 61133965Sjdp 0, /* rightshift */ 61233965Sjdp 4, /* size (0 = byte, 1 = short, 2 = long) */ 61333965Sjdp 64, /* bitsize */ 61433965Sjdp false, /* pc_relative */ 61533965Sjdp 0, /* bitpos */ 61633965Sjdp complain_overflow_dont, /* complain_on_overflow */ 61733965Sjdp elf64_alpha_reloc_bad, /* special_function */ 61833965Sjdp "OP_STORE", /* name */ 61933965Sjdp false, /* partial_inplace */ 62033965Sjdp 0, /* src_mask */ 62133965Sjdp MINUS_ONE, /* dst_mask */ 62233965Sjdp false), /* pcrel_offset */ 62333965Sjdp 62433965Sjdp /* Subtract the reloc address from the value on the top of the 62533965Sjdp relocation stack. */ 62638889Sjdp /* Not implemented -- it's dumb. */ 62738889Sjdp HOWTO (R_ALPHA_OP_PSUB, /* type */ 62833965Sjdp 0, /* rightshift */ 62933965Sjdp 0, /* size (0 = byte, 1 = short, 2 = long) */ 63033965Sjdp 0, /* bitsize */ 63133965Sjdp false, /* pc_relative */ 63233965Sjdp 0, /* bitpos */ 63333965Sjdp complain_overflow_dont, /* complain_on_overflow */ 63433965Sjdp elf64_alpha_reloc_bad, /* special_function */ 63533965Sjdp "OP_PSUB", /* name */ 63633965Sjdp false, /* partial_inplace */ 63733965Sjdp 0, /* src_mask */ 63833965Sjdp 0, /* dst_mask */ 63933965Sjdp false), /* pcrel_offset */ 64033965Sjdp 64133965Sjdp /* Shift the value on the top of the relocation stack right by the 64233965Sjdp given value. */ 64338889Sjdp /* Not implemented -- it's dumb. */ 64438889Sjdp HOWTO (R_ALPHA_OP_PRSHIFT, /* type */ 64533965Sjdp 0, /* rightshift */ 64633965Sjdp 0, /* size (0 = byte, 1 = short, 2 = long) */ 64733965Sjdp 0, /* bitsize */ 64833965Sjdp false, /* pc_relative */ 64933965Sjdp 0, /* bitpos */ 65033965Sjdp complain_overflow_dont, /* complain_on_overflow */ 65133965Sjdp elf64_alpha_reloc_bad, /* special_function */ 65233965Sjdp "OP_PRSHIFT", /* name */ 65333965Sjdp false, /* partial_inplace */ 65433965Sjdp 0, /* src_mask */ 65533965Sjdp 0, /* dst_mask */ 65633965Sjdp false), /* pcrel_offset */ 65733965Sjdp 65838889Sjdp /* Change the value of GP used by +r_addend until the next GPVALUE or the 65938889Sjdp end of the input bfd. */ 66038889Sjdp /* Not implemented -- it's dumb. */ 66138889Sjdp HOWTO (R_ALPHA_GPVALUE, 66238889Sjdp 0, /* rightshift */ 66338889Sjdp 0, /* size (0 = byte, 1 = short, 2 = long) */ 66438889Sjdp 0, /* bitsize */ 66538889Sjdp false, /* pc_relative */ 66638889Sjdp 0, /* bitpos */ 66738889Sjdp complain_overflow_dont, /* complain_on_overflow */ 66838889Sjdp elf64_alpha_reloc_bad, /* special_function */ 66938889Sjdp "GPVALUE", /* name */ 67038889Sjdp false, /* partial_inplace */ 67138889Sjdp 0, /* src_mask */ 67238889Sjdp 0, /* dst_mask */ 67338889Sjdp false), /* pcrel_offset */ 67438889Sjdp 67538889Sjdp /* The high 16 bits of the displacement from GP to the target. */ 67638889Sjdp HOWTO (R_ALPHA_GPRELHIGH, 67738889Sjdp 0, /* rightshift */ 67860510Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 67960510Sobrien 16, /* bitsize */ 68038889Sjdp false, /* pc_relative */ 68138889Sjdp 0, /* bitpos */ 68260510Sobrien complain_overflow_signed, /* complain_on_overflow */ 68338889Sjdp elf64_alpha_reloc_bad, /* special_function */ 68438889Sjdp "GPRELHIGH", /* name */ 68538889Sjdp false, /* partial_inplace */ 68660510Sobrien 0xffff, /* src_mask */ 68760510Sobrien 0xffff, /* dst_mask */ 68838889Sjdp false), /* pcrel_offset */ 68938889Sjdp 69038889Sjdp /* The low 16 bits of the displacement from GP to the target. */ 69138889Sjdp HOWTO (R_ALPHA_GPRELLOW, 69238889Sjdp 0, /* rightshift */ 69360510Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 69460510Sobrien 16, /* bitsize */ 69538889Sjdp false, /* pc_relative */ 69638889Sjdp 0, /* bitpos */ 69738889Sjdp complain_overflow_dont, /* complain_on_overflow */ 69838889Sjdp elf64_alpha_reloc_bad, /* special_function */ 69938889Sjdp "GPRELLOW", /* name */ 70038889Sjdp false, /* partial_inplace */ 70160510Sobrien 0xffff, /* src_mask */ 70260510Sobrien 0xffff, /* dst_mask */ 70338889Sjdp false), /* pcrel_offset */ 70438889Sjdp 70538889Sjdp /* A 16-bit displacement from the GP to the target. */ 70638889Sjdp /* XXX: Not implemented. */ 70738889Sjdp HOWTO (R_ALPHA_IMMED_GP_16, 70838889Sjdp 0, /* rightshift */ 70960510Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 71060510Sobrien 16, /* bitsize */ 71138889Sjdp false, /* pc_relative */ 71238889Sjdp 0, /* bitpos */ 71360510Sobrien complain_overflow_signed, /* complain_on_overflow */ 71460510Sobrien 0, /* special_function */ 71538889Sjdp "IMMED_GP_16", /* name */ 71638889Sjdp false, /* partial_inplace */ 71760510Sobrien 0xffff, /* src_mask */ 71860510Sobrien 0xffff, /* dst_mask */ 71938889Sjdp false), /* pcrel_offset */ 72038889Sjdp 72138889Sjdp /* The high bits of a 32-bit displacement from the GP to the target; the 72238889Sjdp low bits are supplied in the subsequent R_ALPHA_IMMED_LO32 relocs. */ 72338889Sjdp /* XXX: Not implemented. */ 72438889Sjdp HOWTO (R_ALPHA_IMMED_GP_HI32, 72538889Sjdp 0, /* rightshift */ 72638889Sjdp 0, /* size (0 = byte, 1 = short, 2 = long) */ 72738889Sjdp 0, /* bitsize */ 72838889Sjdp false, /* pc_relative */ 72938889Sjdp 0, /* bitpos */ 73038889Sjdp complain_overflow_dont, /* complain_on_overflow */ 73138889Sjdp elf64_alpha_reloc_bad, /* special_function */ 73238889Sjdp "IMMED_GP_HI32", /* name */ 73338889Sjdp false, /* partial_inplace */ 73438889Sjdp 0, /* src_mask */ 73538889Sjdp 0, /* dst_mask */ 73638889Sjdp false), /* pcrel_offset */ 73738889Sjdp 73838889Sjdp /* The high bits of a 32-bit displacement to the starting address of the 73977303Sobrien current section (the relocation target is ignored); the low bits are 74038889Sjdp supplied in the subsequent R_ALPHA_IMMED_LO32 relocs. */ 74138889Sjdp /* XXX: Not implemented. */ 74238889Sjdp HOWTO (R_ALPHA_IMMED_SCN_HI32, 74338889Sjdp 0, /* rightshift */ 74438889Sjdp 0, /* size (0 = byte, 1 = short, 2 = long) */ 74538889Sjdp 0, /* bitsize */ 74638889Sjdp false, /* pc_relative */ 74738889Sjdp 0, /* bitpos */ 74838889Sjdp complain_overflow_dont, /* complain_on_overflow */ 74938889Sjdp elf64_alpha_reloc_bad, /* special_function */ 75038889Sjdp "IMMED_SCN_HI32", /* name */ 75138889Sjdp false, /* partial_inplace */ 75238889Sjdp 0, /* src_mask */ 75338889Sjdp 0, /* dst_mask */ 75438889Sjdp false), /* pcrel_offset */ 75538889Sjdp 75638889Sjdp /* The high bits of a 32-bit displacement from the previous br, bsr, jsr 75738889Sjdp or jmp insn (as tagged by a BRADDR or HINT reloc) to the target; the 75838889Sjdp low bits are supplied by subsequent R_ALPHA_IMMED_LO32 relocs. */ 75938889Sjdp /* XXX: Not implemented. */ 76038889Sjdp HOWTO (R_ALPHA_IMMED_BR_HI32, 76138889Sjdp 0, /* rightshift */ 76238889Sjdp 0, /* size (0 = byte, 1 = short, 2 = long) */ 76338889Sjdp 0, /* bitsize */ 76438889Sjdp false, /* pc_relative */ 76538889Sjdp 0, /* bitpos */ 76638889Sjdp complain_overflow_dont, /* complain_on_overflow */ 76738889Sjdp elf64_alpha_reloc_bad, /* special_function */ 76838889Sjdp "IMMED_BR_HI32", /* name */ 76938889Sjdp false, /* partial_inplace */ 77038889Sjdp 0, /* src_mask */ 77138889Sjdp 0, /* dst_mask */ 77238889Sjdp false), /* pcrel_offset */ 77338889Sjdp 77438889Sjdp /* The low 16 bits of a displacement calculated in a previous HI32 reloc. */ 77538889Sjdp /* XXX: Not implemented. */ 77638889Sjdp HOWTO (R_ALPHA_IMMED_LO32, 77738889Sjdp 0, /* rightshift */ 77838889Sjdp 0, /* size (0 = byte, 1 = short, 2 = long) */ 77938889Sjdp 0, /* bitsize */ 78038889Sjdp false, /* pc_relative */ 78138889Sjdp 0, /* bitpos */ 78238889Sjdp complain_overflow_dont, /* complain_on_overflow */ 78338889Sjdp elf64_alpha_reloc_bad, /* special_function */ 78438889Sjdp "IMMED_LO32", /* name */ 78538889Sjdp false, /* partial_inplace */ 78638889Sjdp 0, /* src_mask */ 78738889Sjdp 0, /* dst_mask */ 78838889Sjdp false), /* pcrel_offset */ 78938889Sjdp 79077303Sobrien /* Misc ELF relocations. */ 79138889Sjdp 79238889Sjdp /* A dynamic relocation to copy the target into our .dynbss section. */ 79338889Sjdp /* Not generated, as all Alpha objects use PIC, so it is not needed. It 79438889Sjdp is present because every other ELF has one, but should not be used 79538889Sjdp because .dynbss is an ugly thing. */ 79633965Sjdp HOWTO (R_ALPHA_COPY, 79733965Sjdp 0, 79833965Sjdp 0, 79933965Sjdp 0, 80033965Sjdp false, 80133965Sjdp 0, 80233965Sjdp complain_overflow_dont, 80333965Sjdp bfd_elf_generic_reloc, 80433965Sjdp "COPY", 80533965Sjdp false, 80633965Sjdp 0, 80733965Sjdp 0, 80833965Sjdp true), 80933965Sjdp 81038889Sjdp /* A dynamic relocation for a .got entry. */ 81133965Sjdp HOWTO (R_ALPHA_GLOB_DAT, 81233965Sjdp 0, 81333965Sjdp 0, 81433965Sjdp 0, 81533965Sjdp false, 81633965Sjdp 0, 81733965Sjdp complain_overflow_dont, 81833965Sjdp bfd_elf_generic_reloc, 81933965Sjdp "GLOB_DAT", 82033965Sjdp false, 82133965Sjdp 0, 82233965Sjdp 0, 82333965Sjdp true), 82433965Sjdp 82538889Sjdp /* A dynamic relocation for a .plt entry. */ 82633965Sjdp HOWTO (R_ALPHA_JMP_SLOT, 82733965Sjdp 0, 82833965Sjdp 0, 82933965Sjdp 0, 83033965Sjdp false, 83133965Sjdp 0, 83233965Sjdp complain_overflow_dont, 83333965Sjdp bfd_elf_generic_reloc, 83433965Sjdp "JMP_SLOT", 83533965Sjdp false, 83633965Sjdp 0, 83733965Sjdp 0, 83833965Sjdp true), 83933965Sjdp 84038889Sjdp /* A dynamic relocation to add the base of the DSO to a 64-bit field. */ 84133965Sjdp HOWTO (R_ALPHA_RELATIVE, 84233965Sjdp 0, 84333965Sjdp 0, 84433965Sjdp 0, 84533965Sjdp false, 84633965Sjdp 0, 84733965Sjdp complain_overflow_dont, 84833965Sjdp bfd_elf_generic_reloc, 84933965Sjdp "RELATIVE", 85033965Sjdp false, 85133965Sjdp 0, 85233965Sjdp 0, 85333965Sjdp true) 85433965Sjdp}; 85533965Sjdp 85633965Sjdp/* A relocation function which doesn't do anything. */ 85733965Sjdp 85833965Sjdpstatic bfd_reloc_status_type 85933965Sjdpelf64_alpha_reloc_nil (abfd, reloc, sym, data, sec, output_bfd, error_message) 86033965Sjdp bfd *abfd; 86133965Sjdp arelent *reloc; 86233965Sjdp asymbol *sym; 86333965Sjdp PTR data; 86433965Sjdp asection *sec; 86533965Sjdp bfd *output_bfd; 86633965Sjdp char **error_message; 86733965Sjdp{ 86833965Sjdp if (output_bfd) 86933965Sjdp reloc->address += sec->output_offset; 87033965Sjdp return bfd_reloc_ok; 87133965Sjdp} 87233965Sjdp 87333965Sjdp/* A relocation function used for an unsupported reloc. */ 87433965Sjdp 87533965Sjdpstatic bfd_reloc_status_type 87633965Sjdpelf64_alpha_reloc_bad (abfd, reloc, sym, data, sec, output_bfd, error_message) 87733965Sjdp bfd *abfd; 87833965Sjdp arelent *reloc; 87933965Sjdp asymbol *sym; 88033965Sjdp PTR data; 88133965Sjdp asection *sec; 88233965Sjdp bfd *output_bfd; 88333965Sjdp char **error_message; 88433965Sjdp{ 88533965Sjdp if (output_bfd) 88633965Sjdp reloc->address += sec->output_offset; 88733965Sjdp return bfd_reloc_notsupported; 88833965Sjdp} 88933965Sjdp 89033965Sjdp/* Do the work of the GPDISP relocation. */ 89133965Sjdp 89233965Sjdpstatic bfd_reloc_status_type 89333965Sjdpelf64_alpha_do_reloc_gpdisp (abfd, gpdisp, p_ldah, p_lda) 89433965Sjdp bfd *abfd; 89533965Sjdp bfd_vma gpdisp; 89633965Sjdp bfd_byte *p_ldah; 89733965Sjdp bfd_byte *p_lda; 89833965Sjdp{ 89933965Sjdp bfd_reloc_status_type ret = bfd_reloc_ok; 90033965Sjdp bfd_vma addend; 90133965Sjdp unsigned long i_ldah, i_lda; 90233965Sjdp 90333965Sjdp i_ldah = bfd_get_32 (abfd, p_ldah); 90433965Sjdp i_lda = bfd_get_32 (abfd, p_lda); 90533965Sjdp 90633965Sjdp /* Complain if the instructions are not correct. */ 90733965Sjdp if (((i_ldah >> 26) & 0x3f) != 0x09 90833965Sjdp || ((i_lda >> 26) & 0x3f) != 0x08) 90933965Sjdp ret = bfd_reloc_dangerous; 91033965Sjdp 91133965Sjdp /* Extract the user-supplied offset, mirroring the sign extensions 91233965Sjdp that the instructions perform. */ 91333965Sjdp addend = ((i_ldah & 0xffff) << 16) | (i_lda & 0xffff); 91433965Sjdp addend = (addend ^ 0x80008000) - 0x80008000; 91533965Sjdp 91633965Sjdp gpdisp += addend; 91733965Sjdp 91848850Sdfr if ((bfd_signed_vma) gpdisp < -(bfd_signed_vma) 0x80000000 91948850Sdfr || (bfd_signed_vma) gpdisp >= (bfd_signed_vma) 0x7fff8000) 92033965Sjdp ret = bfd_reloc_overflow; 92133965Sjdp 92233965Sjdp /* compensate for the sign extension again. */ 92333965Sjdp i_ldah = ((i_ldah & 0xffff0000) 92433965Sjdp | (((gpdisp >> 16) + ((gpdisp >> 15) & 1)) & 0xffff)); 92533965Sjdp i_lda = (i_lda & 0xffff0000) | (gpdisp & 0xffff); 92633965Sjdp 92733965Sjdp bfd_put_32 (abfd, i_ldah, p_ldah); 92833965Sjdp bfd_put_32 (abfd, i_lda, p_lda); 92933965Sjdp 93033965Sjdp return ret; 93133965Sjdp} 93233965Sjdp 93333965Sjdp/* The special function for the GPDISP reloc. */ 93433965Sjdp 93533965Sjdpstatic bfd_reloc_status_type 93633965Sjdpelf64_alpha_reloc_gpdisp (abfd, reloc_entry, sym, data, input_section, 93733965Sjdp output_bfd, err_msg) 93833965Sjdp bfd *abfd; 93933965Sjdp arelent *reloc_entry; 94033965Sjdp asymbol *sym; 94133965Sjdp PTR data; 94233965Sjdp asection *input_section; 94333965Sjdp bfd *output_bfd; 94433965Sjdp char **err_msg; 94533965Sjdp{ 94633965Sjdp bfd_reloc_status_type ret; 94733965Sjdp bfd_vma gp, relocation; 94833965Sjdp bfd_byte *p_ldah, *p_lda; 94933965Sjdp 95033965Sjdp /* Don't do anything if we're not doing a final link. */ 95133965Sjdp if (output_bfd) 95233965Sjdp { 95333965Sjdp reloc_entry->address += input_section->output_offset; 95433965Sjdp return bfd_reloc_ok; 95533965Sjdp } 95633965Sjdp 95733965Sjdp if (reloc_entry->address > input_section->_cooked_size || 95833965Sjdp reloc_entry->address + reloc_entry->addend > input_section->_cooked_size) 95933965Sjdp return bfd_reloc_outofrange; 96033965Sjdp 96133965Sjdp /* The gp used in the portion of the output object to which this 96233965Sjdp input object belongs is cached on the input bfd. */ 96333965Sjdp gp = _bfd_get_gp_value (abfd); 96433965Sjdp 96533965Sjdp relocation = (input_section->output_section->vma 96633965Sjdp + input_section->output_offset 96733965Sjdp + reloc_entry->address); 96833965Sjdp 96933965Sjdp p_ldah = (bfd_byte *) data + reloc_entry->address; 97033965Sjdp p_lda = p_ldah + reloc_entry->addend; 97133965Sjdp 97233965Sjdp ret = elf64_alpha_do_reloc_gpdisp (abfd, gp - relocation, p_ldah, p_lda); 97333965Sjdp 97433965Sjdp /* Complain if the instructions are not correct. */ 97533965Sjdp if (ret == bfd_reloc_dangerous) 97660510Sobrien *err_msg = _("GPDISP relocation did not find ldah and lda instructions"); 97733965Sjdp 97833965Sjdp return ret; 97933965Sjdp} 98033965Sjdp 98133965Sjdp/* A mapping from BFD reloc types to Alpha ELF reloc types. */ 98233965Sjdp 98333965Sjdpstruct elf_reloc_map 98433965Sjdp{ 98533965Sjdp bfd_reloc_code_real_type bfd_reloc_val; 98633965Sjdp int elf_reloc_val; 98733965Sjdp}; 98833965Sjdp 98933965Sjdpstatic const struct elf_reloc_map elf64_alpha_reloc_map[] = 99033965Sjdp{ 99133965Sjdp {BFD_RELOC_NONE, R_ALPHA_NONE}, 99233965Sjdp {BFD_RELOC_32, R_ALPHA_REFLONG}, 99333965Sjdp {BFD_RELOC_64, R_ALPHA_REFQUAD}, 99433965Sjdp {BFD_RELOC_CTOR, R_ALPHA_REFQUAD}, 99533965Sjdp {BFD_RELOC_GPREL32, R_ALPHA_GPREL32}, 99633965Sjdp {BFD_RELOC_ALPHA_ELF_LITERAL, R_ALPHA_LITERAL}, 99733965Sjdp {BFD_RELOC_ALPHA_LITUSE, R_ALPHA_LITUSE}, 99833965Sjdp {BFD_RELOC_ALPHA_GPDISP, R_ALPHA_GPDISP}, 99933965Sjdp {BFD_RELOC_23_PCREL_S2, R_ALPHA_BRADDR}, 100033965Sjdp {BFD_RELOC_ALPHA_HINT, R_ALPHA_HINT}, 100133965Sjdp {BFD_RELOC_16_PCREL, R_ALPHA_SREL16}, 100233965Sjdp {BFD_RELOC_32_PCREL, R_ALPHA_SREL32}, 100333965Sjdp {BFD_RELOC_64_PCREL, R_ALPHA_SREL64}, 100460510Sobrien 100560510Sobrien/* The BFD_RELOC_ALPHA_USER_* relocations are used by the assembler to process 100660510Sobrien the explicit !<reloc>!sequence relocations, and are mapped into the normal 100777303Sobrien relocations at the end of processing. */ 100860510Sobrien {BFD_RELOC_ALPHA_USER_LITERAL, R_ALPHA_LITERAL}, 100960510Sobrien {BFD_RELOC_ALPHA_USER_LITUSE_BASE, R_ALPHA_LITUSE}, 101060510Sobrien {BFD_RELOC_ALPHA_USER_LITUSE_BYTOFF, R_ALPHA_LITUSE}, 101160510Sobrien {BFD_RELOC_ALPHA_USER_LITUSE_JSR, R_ALPHA_LITUSE}, 101260510Sobrien {BFD_RELOC_ALPHA_USER_GPDISP, R_ALPHA_GPDISP}, 101360510Sobrien {BFD_RELOC_ALPHA_USER_GPRELHIGH, R_ALPHA_GPRELHIGH}, 101460510Sobrien {BFD_RELOC_ALPHA_USER_GPRELLOW, R_ALPHA_GPRELLOW}, 101533965Sjdp}; 101633965Sjdp 101733965Sjdp/* Given a BFD reloc type, return a HOWTO structure. */ 101833965Sjdp 101933965Sjdpstatic reloc_howto_type * 102033965Sjdpelf64_alpha_bfd_reloc_type_lookup (abfd, code) 102133965Sjdp bfd *abfd; 102233965Sjdp bfd_reloc_code_real_type code; 102333965Sjdp{ 102433965Sjdp const struct elf_reloc_map *i, *e; 102533965Sjdp i = e = elf64_alpha_reloc_map; 102633965Sjdp e += sizeof (elf64_alpha_reloc_map) / sizeof (struct elf_reloc_map); 102733965Sjdp for (; i != e; ++i) 102833965Sjdp { 102933965Sjdp if (i->bfd_reloc_val == code) 103033965Sjdp return &elf64_alpha_howto_table[i->elf_reloc_val]; 103133965Sjdp } 103233965Sjdp return 0; 103333965Sjdp} 103433965Sjdp 103533965Sjdp/* Given an Alpha ELF reloc type, fill in an arelent structure. */ 103633965Sjdp 103733965Sjdpstatic void 103833965Sjdpelf64_alpha_info_to_howto (abfd, cache_ptr, dst) 103933965Sjdp bfd *abfd; 104033965Sjdp arelent *cache_ptr; 104133965Sjdp Elf64_Internal_Rela *dst; 104233965Sjdp{ 104333965Sjdp unsigned r_type; 104433965Sjdp 104533965Sjdp r_type = ELF64_R_TYPE(dst->r_info); 104633965Sjdp BFD_ASSERT (r_type < (unsigned int) R_ALPHA_max); 104733965Sjdp cache_ptr->howto = &elf64_alpha_howto_table[r_type]; 104833965Sjdp} 104933965Sjdp 105077303Sobrien/* These functions do relaxation for Alpha ELF. 105160510Sobrien 105260510Sobrien Currently I'm only handling what I can do with existing compiler 105360510Sobrien and assembler support, which means no instructions are removed, 105460510Sobrien though some may be nopped. At this time GCC does not emit enough 105560510Sobrien information to do all of the relaxing that is possible. It will 105660510Sobrien take some not small amount of work for that to happen. 105760510Sobrien 105860510Sobrien There are a couple of interesting papers that I once read on this 105960510Sobrien subject, that I cannot find references to at the moment, that 106060510Sobrien related to Alpha in particular. They are by David Wall, then of 106160510Sobrien DEC WRL. */ 106260510Sobrien 106360510Sobrien#define OP_LDA 0x08 106460510Sobrien#define OP_LDAH 0x09 106560510Sobrien#define INSN_JSR 0x68004000 106660510Sobrien#define INSN_JSR_MASK 0xfc00c000 106760510Sobrien#define OP_LDQ 0x29 106860510Sobrien#define OP_BR 0x30 106960510Sobrien#define OP_BSR 0x34 107060510Sobrien#define INSN_UNOP 0x2fe00000 107160510Sobrien 107260510Sobrienstruct alpha_relax_info 107360510Sobrien{ 107460510Sobrien bfd *abfd; 107560510Sobrien asection *sec; 107660510Sobrien bfd_byte *contents; 107760510Sobrien Elf_Internal_Rela *relocs, *relend; 107860510Sobrien struct bfd_link_info *link_info; 107960510Sobrien boolean changed_contents; 108060510Sobrien boolean changed_relocs; 108160510Sobrien bfd_vma gp; 108260510Sobrien bfd *gotobj; 108360510Sobrien asection *tsec; 108460510Sobrien struct alpha_elf_link_hash_entry *h; 108560510Sobrien struct alpha_elf_got_entry *gotent; 108660510Sobrien unsigned char other; 108760510Sobrien}; 108860510Sobrien 108960510Sobrienstatic Elf_Internal_Rela * elf64_alpha_relax_with_lituse 109077303Sobrien PARAMS((struct alpha_relax_info *info, bfd_vma symval, 109160510Sobrien Elf_Internal_Rela *irel, Elf_Internal_Rela *irelend)); 109260510Sobrien 109360510Sobrienstatic boolean elf64_alpha_relax_without_lituse 109477303Sobrien PARAMS((struct alpha_relax_info *info, bfd_vma symval, 109560510Sobrien Elf_Internal_Rela *irel)); 109660510Sobrien 109760510Sobrienstatic bfd_vma elf64_alpha_relax_opt_call 109860510Sobrien PARAMS((struct alpha_relax_info *info, bfd_vma symval)); 109960510Sobrien 110060510Sobrienstatic boolean elf64_alpha_relax_section 110160510Sobrien PARAMS((bfd *abfd, asection *sec, struct bfd_link_info *link_info, 110260510Sobrien boolean *again)); 110360510Sobrien 110460510Sobrienstatic Elf_Internal_Rela * 110560510Sobrienelf64_alpha_find_reloc_at_ofs (rel, relend, offset, type) 110660510Sobrien Elf_Internal_Rela *rel, *relend; 110760510Sobrien bfd_vma offset; 110860510Sobrien int type; 110960510Sobrien{ 111060510Sobrien while (rel < relend) 111160510Sobrien { 111260510Sobrien if (rel->r_offset == offset && ELF64_R_TYPE (rel->r_info) == type) 111360510Sobrien return rel; 111460510Sobrien ++rel; 111560510Sobrien } 111660510Sobrien return NULL; 111760510Sobrien} 111860510Sobrien 111960510Sobrienstatic Elf_Internal_Rela * 112060510Sobrienelf64_alpha_relax_with_lituse (info, symval, irel, irelend) 112160510Sobrien struct alpha_relax_info *info; 112260510Sobrien bfd_vma symval; 112360510Sobrien Elf_Internal_Rela *irel, *irelend; 112460510Sobrien{ 112560510Sobrien Elf_Internal_Rela *urel; 112660510Sobrien int flags, count, i; 112760510Sobrien bfd_signed_vma disp; 112860510Sobrien boolean fits16; 112960510Sobrien boolean fits32; 113060510Sobrien boolean lit_reused = false; 113160510Sobrien boolean all_optimized = true; 113260510Sobrien unsigned int lit_insn; 113360510Sobrien 113460510Sobrien lit_insn = bfd_get_32 (info->abfd, info->contents + irel->r_offset); 113560510Sobrien if (lit_insn >> 26 != OP_LDQ) 113660510Sobrien { 113760510Sobrien ((*_bfd_error_handler) 113860510Sobrien ("%s: %s+0x%lx: warning: LITERAL relocation against unexpected insn", 113960510Sobrien bfd_get_filename (info->abfd), info->sec->name, 114060510Sobrien (unsigned long)irel->r_offset)); 114160510Sobrien return irel; 114260510Sobrien } 114360510Sobrien 114460510Sobrien /* Summarize how this particular LITERAL is used. */ 114560510Sobrien for (urel = irel+1, flags = count = 0; urel < irelend; ++urel, ++count) 114660510Sobrien { 114760510Sobrien if (ELF64_R_TYPE (urel->r_info) != R_ALPHA_LITUSE) 114860510Sobrien break; 114960510Sobrien if (urel->r_addend >= 0 && urel->r_addend <= 3) 115060510Sobrien flags |= 1 << urel->r_addend; 115160510Sobrien } 115260510Sobrien 115377303Sobrien /* A little preparation for the loop... */ 115460510Sobrien disp = symval - info->gp; 115560510Sobrien 115660510Sobrien for (urel = irel+1, i = 0; i < count; ++i, ++urel) 115760510Sobrien { 115860510Sobrien unsigned int insn; 115977303Sobrien int insn_disp; 116077303Sobrien bfd_signed_vma xdisp; 116177303Sobrien 116260510Sobrien insn = bfd_get_32 (info->abfd, info->contents + urel->r_offset); 116360510Sobrien 116460510Sobrien switch (urel->r_addend) 116560510Sobrien { 116660510Sobrien default: /* 0 = ADDRESS FORMAT */ 116760510Sobrien /* This type is really just a placeholder to note that all 116860510Sobrien uses cannot be optimized, but to still allow some. */ 116960510Sobrien all_optimized = false; 117060510Sobrien break; 117160510Sobrien 117260510Sobrien case 1: /* MEM FORMAT */ 117360510Sobrien /* We can always optimize 16-bit displacements. */ 117477303Sobrien 117577303Sobrien /* Extract the displacement from the instruction, sign-extending 117677303Sobrien it if necessary, then test whether it is within 16 or 32 bits 117777303Sobrien displacement from GP. */ 117877303Sobrien insn_disp = insn & 0x0000ffff; 117977303Sobrien if (insn_disp & 0x00008000) 118077303Sobrien insn_disp |= 0xffff0000; /* Negative: sign-extend. */ 118177303Sobrien 118277303Sobrien xdisp = disp + insn_disp; 118377303Sobrien fits16 = (xdisp >= - (bfd_signed_vma) 0x00008000 && xdisp < 0x00008000); 118477303Sobrien fits32 = (xdisp >= - (bfd_signed_vma) 0x80000000 && xdisp < 0x7fff8000); 118577303Sobrien 118660510Sobrien if (fits16) 118760510Sobrien { 118877303Sobrien /* Take the op code and dest from this insn, take the base 118960510Sobrien register from the literal insn. Leave the offset alone. */ 119077303Sobrien insn = (insn & 0xffe0ffff) | (lit_insn & 0x001f0000); 119160510Sobrien urel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), 119260510Sobrien R_ALPHA_GPRELLOW); 119360510Sobrien urel->r_addend = irel->r_addend; 119460510Sobrien info->changed_relocs = true; 119560510Sobrien 119660510Sobrien bfd_put_32 (info->abfd, insn, info->contents + urel->r_offset); 119760510Sobrien info->changed_contents = true; 119860510Sobrien } 119960510Sobrien 120060510Sobrien /* If all mem+byte, we can optimize 32-bit mem displacements. */ 120160510Sobrien else if (fits32 && !(flags & ~6)) 120260510Sobrien { 120377303Sobrien /* FIXME: sanity check that lit insn Ra is mem insn Rb. */ 120460510Sobrien 120560510Sobrien irel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), 120660510Sobrien R_ALPHA_GPRELHIGH); 120760510Sobrien lit_insn = (OP_LDAH << 26) | (lit_insn & 0x03ff0000); 120860510Sobrien bfd_put_32 (info->abfd, lit_insn, 120960510Sobrien info->contents + irel->r_offset); 121060510Sobrien lit_reused = true; 121160510Sobrien info->changed_contents = true; 121260510Sobrien 121360510Sobrien urel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), 121460510Sobrien R_ALPHA_GPRELLOW); 121560510Sobrien urel->r_addend = irel->r_addend; 121660510Sobrien info->changed_relocs = true; 121760510Sobrien } 121860510Sobrien else 121960510Sobrien all_optimized = false; 122060510Sobrien break; 122160510Sobrien 122260510Sobrien case 2: /* BYTE OFFSET FORMAT */ 122360510Sobrien /* We can always optimize byte instructions. */ 122460510Sobrien 122560510Sobrien /* FIXME: sanity check the insn for byte op. Check that the 122660510Sobrien literal dest reg is indeed Rb in the byte insn. */ 122760510Sobrien 122860510Sobrien insn = (insn & ~0x001ff000) | ((symval & 7) << 13) | 0x1000; 122960510Sobrien 123060510Sobrien urel->r_info = ELF64_R_INFO (0, R_ALPHA_NONE); 123160510Sobrien urel->r_addend = 0; 123260510Sobrien info->changed_relocs = true; 123360510Sobrien 123460510Sobrien bfd_put_32 (info->abfd, insn, info->contents + urel->r_offset); 123560510Sobrien info->changed_contents = true; 123660510Sobrien break; 123760510Sobrien 123860510Sobrien case 3: /* CALL FORMAT */ 123960510Sobrien { 124060510Sobrien /* If not zero, place to jump without needing pv. */ 124160510Sobrien bfd_vma optdest = elf64_alpha_relax_opt_call (info, symval); 124260510Sobrien bfd_vma org = (info->sec->output_section->vma 124360510Sobrien + info->sec->output_offset 124460510Sobrien + urel->r_offset + 4); 124560510Sobrien bfd_signed_vma odisp; 124660510Sobrien 124760510Sobrien odisp = (optdest ? optdest : symval) - org; 124860510Sobrien if (odisp >= -0x400000 && odisp < 0x400000) 124960510Sobrien { 125060510Sobrien Elf_Internal_Rela *xrel; 125160510Sobrien 125277303Sobrien /* Preserve branch prediction call stack when possible. */ 125360510Sobrien if ((insn & INSN_JSR_MASK) == INSN_JSR) 125460510Sobrien insn = (OP_BSR << 26) | (insn & 0x03e00000); 125560510Sobrien else 125660510Sobrien insn = (OP_BR << 26) | (insn & 0x03e00000); 125777303Sobrien 125860510Sobrien urel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), 125960510Sobrien R_ALPHA_BRADDR); 126060510Sobrien urel->r_addend = irel->r_addend; 126160510Sobrien 126260510Sobrien if (optdest) 126360510Sobrien urel->r_addend += optdest - symval; 126460510Sobrien else 126560510Sobrien all_optimized = false; 126660510Sobrien 126760510Sobrien bfd_put_32 (info->abfd, insn, info->contents + urel->r_offset); 126860510Sobrien 126960510Sobrien /* Kill any HINT reloc that might exist for this insn. */ 127060510Sobrien xrel = (elf64_alpha_find_reloc_at_ofs 127177303Sobrien (info->relocs, info->relend, urel->r_offset, 127260510Sobrien R_ALPHA_HINT)); 127360510Sobrien if (xrel) 127460510Sobrien xrel->r_info = ELF64_R_INFO (0, R_ALPHA_NONE); 127560510Sobrien 127660510Sobrien info->changed_contents = true; 127760510Sobrien info->changed_relocs = true; 127860510Sobrien } 127960510Sobrien else 128060510Sobrien all_optimized = false; 128160510Sobrien 128260510Sobrien /* ??? If target gp == current gp we can eliminate the gp reload. 128360510Sobrien This does depend on every place a gp could be reloaded will 128460510Sobrien be, which currently happens for all code produced by gcc, but 128560510Sobrien not necessarily by hand-coded assembly, or if sibling calls 128677303Sobrien are enabled in gcc. 128760510Sobrien 128860510Sobrien Perhaps conditionalize this on a flag being set in the target 128960510Sobrien object file's header, and have gcc set it? */ 129060510Sobrien } 129160510Sobrien break; 129260510Sobrien } 129360510Sobrien } 129460510Sobrien 129560510Sobrien /* If all cases were optimized, we can reduce the use count on this 129660510Sobrien got entry by one, possibly eliminating it. */ 129760510Sobrien if (all_optimized) 129860510Sobrien { 129960510Sobrien info->gotent->use_count -= 1; 130060510Sobrien alpha_elf_tdata (info->gotent->gotobj)->total_got_entries -= 1; 130160510Sobrien if (!info->h) 130260510Sobrien alpha_elf_tdata (info->gotent->gotobj)->n_local_got_entries -= 1; 130360510Sobrien 130460510Sobrien /* If the literal instruction is no longer needed (it may have been 130560510Sobrien reused. We can eliminate it. 130660510Sobrien ??? For now, I don't want to deal with compacting the section, 130760510Sobrien so just nop it out. */ 130860510Sobrien if (!lit_reused) 130960510Sobrien { 131060510Sobrien irel->r_info = ELF64_R_INFO (0, R_ALPHA_NONE); 131160510Sobrien info->changed_relocs = true; 131260510Sobrien 131360510Sobrien bfd_put_32 (info->abfd, INSN_UNOP, info->contents + irel->r_offset); 131460510Sobrien info->changed_contents = true; 131560510Sobrien } 131660510Sobrien } 131760510Sobrien 131860510Sobrien return irel + count; 131960510Sobrien} 132060510Sobrien 132160510Sobrienstatic bfd_vma 132260510Sobrienelf64_alpha_relax_opt_call (info, symval) 132360510Sobrien struct alpha_relax_info *info; 132460510Sobrien bfd_vma symval; 132560510Sobrien{ 132660510Sobrien /* If the function has the same gp, and we can identify that the 132760510Sobrien function does not use its function pointer, we can eliminate the 132860510Sobrien address load. */ 132960510Sobrien 133060510Sobrien /* If the symbol is marked NOPV, we are being told the function never 133160510Sobrien needs its procedure value. */ 133277303Sobrien if ((info->other & STO_ALPHA_STD_GPLOAD) == STO_ALPHA_NOPV) 133360510Sobrien return symval; 133460510Sobrien 133560510Sobrien /* If the symbol is marked STD_GP, we are being told the function does 133677303Sobrien a normal ldgp in the first two words. */ 133777303Sobrien else if ((info->other & STO_ALPHA_STD_GPLOAD) == STO_ALPHA_STD_GPLOAD) 133860510Sobrien ; 133960510Sobrien 134060510Sobrien /* Otherwise, we may be able to identify a GP load in the first two 134160510Sobrien words, which we can then skip. */ 134277303Sobrien else 134360510Sobrien { 134460510Sobrien Elf_Internal_Rela *tsec_relocs, *tsec_relend, *tsec_free, *gpdisp; 134560510Sobrien bfd_vma ofs; 134660510Sobrien 134777303Sobrien /* Load the relocations from the section that the target symbol is in. */ 134860510Sobrien if (info->sec == info->tsec) 134960510Sobrien { 135060510Sobrien tsec_relocs = info->relocs; 135160510Sobrien tsec_relend = info->relend; 135260510Sobrien tsec_free = NULL; 135360510Sobrien } 135460510Sobrien else 135560510Sobrien { 135660510Sobrien tsec_relocs = (_bfd_elf64_link_read_relocs 135760510Sobrien (info->abfd, info->tsec, (PTR) NULL, 135860510Sobrien (Elf_Internal_Rela *) NULL, 135960510Sobrien info->link_info->keep_memory)); 136060510Sobrien if (tsec_relocs == NULL) 136160510Sobrien return 0; 136260510Sobrien tsec_relend = tsec_relocs + info->tsec->reloc_count; 136360510Sobrien tsec_free = (info->link_info->keep_memory ? NULL : tsec_relocs); 136460510Sobrien } 136560510Sobrien 136660510Sobrien /* Recover the symbol's offset within the section. */ 136760510Sobrien ofs = (symval - info->tsec->output_section->vma 136860510Sobrien - info->tsec->output_offset); 136977303Sobrien 137060510Sobrien /* Look for a GPDISP reloc. */ 137160510Sobrien gpdisp = (elf64_alpha_find_reloc_at_ofs 137260510Sobrien (tsec_relocs, tsec_relend, ofs, R_ALPHA_GPDISP)); 137360510Sobrien 137460510Sobrien if (!gpdisp || gpdisp->r_addend != 4) 137560510Sobrien { 137660510Sobrien if (tsec_free) 137760510Sobrien free (tsec_free); 137860510Sobrien return 0; 137960510Sobrien } 138060510Sobrien if (tsec_free) 138160510Sobrien free (tsec_free); 138260510Sobrien } 138360510Sobrien 138477303Sobrien /* We've now determined that we can skip an initial gp load. Verify 138560510Sobrien that the call and the target use the same gp. */ 138660510Sobrien if (info->link_info->hash->creator != info->tsec->owner->xvec 138760510Sobrien || info->gotobj != alpha_elf_tdata (info->tsec->owner)->gotobj) 138860510Sobrien return 0; 138960510Sobrien 139060510Sobrien return symval + 8; 139160510Sobrien} 139260510Sobrien 139360510Sobrienstatic boolean 139460510Sobrienelf64_alpha_relax_without_lituse (info, symval, irel) 139560510Sobrien struct alpha_relax_info *info; 139660510Sobrien bfd_vma symval; 139760510Sobrien Elf_Internal_Rela *irel; 139860510Sobrien{ 139960510Sobrien unsigned int insn; 140060510Sobrien bfd_signed_vma disp; 140160510Sobrien 140260510Sobrien /* Get the instruction. */ 140360510Sobrien insn = bfd_get_32 (info->abfd, info->contents + irel->r_offset); 140460510Sobrien 140560510Sobrien if (insn >> 26 != OP_LDQ) 140660510Sobrien { 140760510Sobrien ((*_bfd_error_handler) 140860510Sobrien ("%s: %s+0x%lx: warning: LITERAL relocation against unexpected insn", 140960510Sobrien bfd_get_filename (info->abfd), info->sec->name, 141060510Sobrien (unsigned long) irel->r_offset)); 141160510Sobrien return true; 141260510Sobrien } 141360510Sobrien 141460510Sobrien /* So we aren't told much. Do what we can with the address load and 141560510Sobrien fake the rest. All of the optimizations here require that the 141660510Sobrien offset from the GP fit in 16 bits. */ 141760510Sobrien 141860510Sobrien disp = symval - info->gp; 141960510Sobrien if (disp < -0x8000 || disp >= 0x8000) 142060510Sobrien return true; 142160510Sobrien 142260510Sobrien /* On the LITERAL instruction itself, consider exchanging 142360510Sobrien `ldq R,X(gp)' for `lda R,Y(gp)'. */ 142460510Sobrien 142560510Sobrien insn = (OP_LDA << 26) | (insn & 0x03ff0000); 142660510Sobrien bfd_put_32 (info->abfd, insn, info->contents + irel->r_offset); 142760510Sobrien info->changed_contents = true; 142860510Sobrien 142960510Sobrien irel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), R_ALPHA_GPRELLOW); 143060510Sobrien info->changed_relocs = true; 143160510Sobrien 143260510Sobrien /* Reduce the use count on this got entry by one, possibly 143360510Sobrien eliminating it. */ 143460510Sobrien info->gotent->use_count -= 1; 143560510Sobrien alpha_elf_tdata (info->gotent->gotobj)->total_got_entries -= 1; 143660510Sobrien if (!info->h) 143760510Sobrien alpha_elf_tdata (info->gotent->gotobj)->n_local_got_entries -= 1; 143860510Sobrien 143960510Sobrien /* ??? Search forward through this basic block looking for insns 144060510Sobrien that use the target register. Stop after an insn modifying the 144160510Sobrien register is seen, or after a branch or call. 144260510Sobrien 144360510Sobrien Any such memory load insn may be substituted by a load directly 144460510Sobrien off the GP. This allows the memory load insn to be issued before 144577303Sobrien the calculated GP register would otherwise be ready. 144660510Sobrien 144760510Sobrien Any such jsr insn can be replaced by a bsr if it is in range. 144860510Sobrien 144960510Sobrien This would mean that we'd have to _add_ relocations, the pain of 145060510Sobrien which gives one pause. */ 145160510Sobrien 145260510Sobrien return true; 145360510Sobrien} 145460510Sobrien 145560510Sobrienstatic boolean 145660510Sobrienelf64_alpha_relax_section (abfd, sec, link_info, again) 145760510Sobrien bfd *abfd; 145860510Sobrien asection *sec; 145960510Sobrien struct bfd_link_info *link_info; 146060510Sobrien boolean *again; 146160510Sobrien{ 146260510Sobrien Elf_Internal_Shdr *symtab_hdr; 146360510Sobrien Elf_Internal_Rela *internal_relocs; 146460510Sobrien Elf_Internal_Rela *free_relocs = NULL; 146560510Sobrien Elf_Internal_Rela *irel, *irelend; 146660510Sobrien bfd_byte *free_contents = NULL; 146760510Sobrien Elf64_External_Sym *extsyms = NULL; 146860510Sobrien Elf64_External_Sym *free_extsyms = NULL; 146960510Sobrien struct alpha_elf_got_entry **local_got_entries; 147060510Sobrien struct alpha_relax_info info; 147160510Sobrien 147260510Sobrien /* We are not currently changing any sizes, so only one pass. */ 147360510Sobrien *again = false; 147460510Sobrien 147560510Sobrien if (link_info->relocateable 147660510Sobrien || (sec->flags & SEC_RELOC) == 0 147760510Sobrien || sec->reloc_count == 0) 147860510Sobrien return true; 147960510Sobrien 148060510Sobrien /* If this is the first time we have been called for this section, 148160510Sobrien initialize the cooked size. */ 148260510Sobrien if (sec->_cooked_size == 0) 148360510Sobrien sec->_cooked_size = sec->_raw_size; 148460510Sobrien 148560510Sobrien symtab_hdr = &elf_tdata (abfd)->symtab_hdr; 148660510Sobrien local_got_entries = alpha_elf_tdata(abfd)->local_got_entries; 148760510Sobrien 148860510Sobrien /* Load the relocations for this section. */ 148960510Sobrien internal_relocs = (_bfd_elf64_link_read_relocs 149060510Sobrien (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL, 149160510Sobrien link_info->keep_memory)); 149260510Sobrien if (internal_relocs == NULL) 149360510Sobrien goto error_return; 149460510Sobrien if (! link_info->keep_memory) 149560510Sobrien free_relocs = internal_relocs; 149660510Sobrien 149777303Sobrien memset(&info, 0, sizeof (info)); 149860510Sobrien info.abfd = abfd; 149960510Sobrien info.sec = sec; 150060510Sobrien info.link_info = link_info; 150160510Sobrien info.relocs = internal_relocs; 150260510Sobrien info.relend = irelend = internal_relocs + sec->reloc_count; 150360510Sobrien 150460510Sobrien /* Find the GP for this object. */ 150560510Sobrien info.gotobj = alpha_elf_tdata (abfd)->gotobj; 150660510Sobrien if (info.gotobj) 150760510Sobrien { 150860510Sobrien asection *sgot = alpha_elf_tdata (info.gotobj)->got; 150960510Sobrien info.gp = _bfd_get_gp_value (info.gotobj); 151060510Sobrien if (info.gp == 0) 151160510Sobrien { 151260510Sobrien info.gp = (sgot->output_section->vma 151360510Sobrien + sgot->output_offset 151460510Sobrien + 0x8000); 151560510Sobrien _bfd_set_gp_value (info.gotobj, info.gp); 151660510Sobrien } 151760510Sobrien } 151860510Sobrien 151960510Sobrien for (irel = internal_relocs; irel < irelend; irel++) 152060510Sobrien { 152160510Sobrien bfd_vma symval; 152260510Sobrien Elf_Internal_Sym isym; 152360510Sobrien struct alpha_elf_got_entry *gotent; 152460510Sobrien 152560510Sobrien if (ELF64_R_TYPE (irel->r_info) != (int) R_ALPHA_LITERAL) 152660510Sobrien continue; 152760510Sobrien 152860510Sobrien /* Get the section contents. */ 152960510Sobrien if (info.contents == NULL) 153060510Sobrien { 153160510Sobrien if (elf_section_data (sec)->this_hdr.contents != NULL) 153260510Sobrien info.contents = elf_section_data (sec)->this_hdr.contents; 153360510Sobrien else 153460510Sobrien { 153560510Sobrien info.contents = (bfd_byte *) bfd_malloc (sec->_raw_size); 153660510Sobrien if (info.contents == NULL) 153760510Sobrien goto error_return; 153860510Sobrien free_contents = info.contents; 153960510Sobrien 154060510Sobrien if (! bfd_get_section_contents (abfd, sec, info.contents, 154160510Sobrien (file_ptr) 0, sec->_raw_size)) 154260510Sobrien goto error_return; 154360510Sobrien } 154460510Sobrien } 154560510Sobrien 154660510Sobrien /* Read this BFD's symbols if we haven't done so already. */ 154760510Sobrien if (extsyms == NULL) 154860510Sobrien { 154960510Sobrien if (symtab_hdr->contents != NULL) 155060510Sobrien extsyms = (Elf64_External_Sym *) symtab_hdr->contents; 155160510Sobrien else 155260510Sobrien { 155360510Sobrien extsyms = ((Elf64_External_Sym *) 155460510Sobrien bfd_malloc (symtab_hdr->sh_size)); 155560510Sobrien if (extsyms == NULL) 155660510Sobrien goto error_return; 155760510Sobrien free_extsyms = extsyms; 155860510Sobrien if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0 155960510Sobrien || (bfd_read (extsyms, 1, symtab_hdr->sh_size, abfd) 156060510Sobrien != symtab_hdr->sh_size)) 156160510Sobrien goto error_return; 156260510Sobrien } 156360510Sobrien } 156460510Sobrien 156560510Sobrien /* Get the value of the symbol referred to by the reloc. */ 156660510Sobrien if (ELF64_R_SYM (irel->r_info) < symtab_hdr->sh_info) 156760510Sobrien { 156860510Sobrien /* A local symbol. */ 156960510Sobrien bfd_elf64_swap_symbol_in (abfd, 157060510Sobrien extsyms + ELF64_R_SYM (irel->r_info), 157160510Sobrien &isym); 157260510Sobrien if (isym.st_shndx == SHN_UNDEF) 157360510Sobrien info.tsec = bfd_und_section_ptr; 157460510Sobrien else if (isym.st_shndx > 0 && isym.st_shndx < SHN_LORESERVE) 157560510Sobrien info.tsec = bfd_section_from_elf_index (abfd, isym.st_shndx); 157660510Sobrien else if (isym.st_shndx == SHN_ABS) 157760510Sobrien info.tsec = bfd_abs_section_ptr; 157860510Sobrien else if (isym.st_shndx == SHN_COMMON) 157960510Sobrien info.tsec = bfd_com_section_ptr; 158077303Sobrien else 158177303Sobrien continue; /* who knows. */ 158260510Sobrien 158360510Sobrien info.h = NULL; 158460510Sobrien info.other = isym.st_other; 158560510Sobrien gotent = local_got_entries[ELF64_R_SYM(irel->r_info)]; 158660510Sobrien symval = isym.st_value; 158760510Sobrien } 158860510Sobrien else 158960510Sobrien { 159060510Sobrien unsigned long indx; 159160510Sobrien struct alpha_elf_link_hash_entry *h; 159260510Sobrien 159360510Sobrien indx = ELF64_R_SYM (irel->r_info) - symtab_hdr->sh_info; 159460510Sobrien h = alpha_elf_sym_hashes (abfd)[indx]; 159560510Sobrien BFD_ASSERT (h != NULL); 159660510Sobrien 159760510Sobrien while (h->root.root.type == bfd_link_hash_indirect 159860510Sobrien || h->root.root.type == bfd_link_hash_warning) 159960510Sobrien h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link; 160060510Sobrien 160160510Sobrien /* We can't do anthing with undefined or dynamic symbols. */ 160260510Sobrien if (h->root.root.type == bfd_link_hash_undefined 160360510Sobrien || h->root.root.type == bfd_link_hash_undefweak 160460510Sobrien || alpha_elf_dynamic_symbol_p (&h->root, link_info)) 160560510Sobrien continue; 160660510Sobrien 160760510Sobrien info.h = h; 160860510Sobrien info.gotent = gotent; 160960510Sobrien info.tsec = h->root.root.u.def.section; 161060510Sobrien info.other = h->root.other; 161160510Sobrien gotent = h->got_entries; 161260510Sobrien symval = h->root.root.u.def.value; 161360510Sobrien } 161460510Sobrien 161560510Sobrien /* Search for the got entry to be used by this relocation. */ 161660510Sobrien while (gotent->gotobj != info.gotobj || gotent->addend != irel->r_addend) 161760510Sobrien gotent = gotent->next; 161860510Sobrien info.gotent = gotent; 161960510Sobrien 162060510Sobrien symval += info.tsec->output_section->vma + info.tsec->output_offset; 162160510Sobrien symval += irel->r_addend; 162260510Sobrien 162360510Sobrien BFD_ASSERT(info.gotent != NULL); 162460510Sobrien 162560510Sobrien /* If there exist LITUSE relocations immediately following, this 162660510Sobrien opens up all sorts of interesting optimizations, because we 162760510Sobrien now know every location that this address load is used. */ 162860510Sobrien 162960510Sobrien if (irel+1 < irelend && ELF64_R_TYPE (irel[1].r_info) == R_ALPHA_LITUSE) 163060510Sobrien { 163160510Sobrien irel = elf64_alpha_relax_with_lituse (&info, symval, irel, irelend); 163260510Sobrien if (irel == NULL) 163360510Sobrien goto error_return; 163460510Sobrien } 163560510Sobrien else 163660510Sobrien { 163760510Sobrien if (!elf64_alpha_relax_without_lituse (&info, symval, irel)) 163860510Sobrien goto error_return; 163960510Sobrien } 164060510Sobrien } 164160510Sobrien 164260510Sobrien if (!elf64_alpha_size_got_sections (abfd, link_info)) 164360510Sobrien return false; 164460510Sobrien 164560510Sobrien if (info.changed_relocs) 164660510Sobrien { 164760510Sobrien elf_section_data (sec)->relocs = internal_relocs; 164860510Sobrien } 164960510Sobrien else if (free_relocs != NULL) 165060510Sobrien { 165160510Sobrien free (free_relocs); 165260510Sobrien } 165360510Sobrien 165460510Sobrien if (info.changed_contents) 165560510Sobrien { 165660510Sobrien elf_section_data (sec)->this_hdr.contents = info.contents; 165760510Sobrien } 165860510Sobrien else if (free_contents != NULL) 165960510Sobrien { 166060510Sobrien if (! link_info->keep_memory) 166160510Sobrien free (free_contents); 166260510Sobrien else 166360510Sobrien { 166460510Sobrien /* Cache the section contents for elf_link_input_bfd. */ 166560510Sobrien elf_section_data (sec)->this_hdr.contents = info.contents; 166660510Sobrien } 166760510Sobrien } 166860510Sobrien 166960510Sobrien if (free_extsyms != NULL) 167060510Sobrien { 167160510Sobrien if (! link_info->keep_memory) 167260510Sobrien free (free_extsyms); 167360510Sobrien else 167460510Sobrien { 167560510Sobrien /* Cache the symbols for elf_link_input_bfd. */ 167660510Sobrien symtab_hdr->contents = extsyms; 167760510Sobrien } 167860510Sobrien } 167960510Sobrien 168060510Sobrien *again = info.changed_contents || info.changed_relocs; 168160510Sobrien 168260510Sobrien return true; 168360510Sobrien 168460510Sobrien error_return: 168560510Sobrien if (free_relocs != NULL) 168660510Sobrien free (free_relocs); 168760510Sobrien if (free_contents != NULL) 168860510Sobrien free (free_contents); 168960510Sobrien if (free_extsyms != NULL) 169060510Sobrien free (free_extsyms); 169160510Sobrien return false; 169260510Sobrien} 169360510Sobrien 169433965Sjdp/* PLT/GOT Stuff */ 169533965Sjdp#define PLT_HEADER_SIZE 32 169633965Sjdp#define PLT_HEADER_WORD1 0xc3600000 /* br $27,.+4 */ 169733965Sjdp#define PLT_HEADER_WORD2 0xa77b000c /* ldq $27,12($27) */ 169833965Sjdp#define PLT_HEADER_WORD3 0x47ff041f /* nop */ 169933965Sjdp#define PLT_HEADER_WORD4 0x6b7b0000 /* jmp $27,($27) */ 170033965Sjdp 170133965Sjdp#define PLT_ENTRY_SIZE 12 170238889Sjdp#define PLT_ENTRY_WORD1 0xc3800000 /* br $28, plt0 */ 170338889Sjdp#define PLT_ENTRY_WORD2 0 170438889Sjdp#define PLT_ENTRY_WORD3 0 170533965Sjdp 170633965Sjdp#define MAX_GOT_ENTRIES (64*1024 / 8) 170733965Sjdp 170868770Sobrien#ifndef ELF_DYNAMIC_INTERPRETER 170968770Sobrien#define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so" 171068770Sobrien#endif 171133965Sjdp 171233965Sjdp/* Handle an Alpha specific section when reading an object file. This 171333965Sjdp is called when elfcode.h finds a section with an unknown type. 171460510Sobrien FIXME: We need to handle the SHF_ALPHA_GPREL flag, but I'm not sure 171533965Sjdp how to. */ 171633965Sjdp 171733965Sjdpstatic boolean 171833965Sjdpelf64_alpha_section_from_shdr (abfd, hdr, name) 171933965Sjdp bfd *abfd; 172033965Sjdp Elf64_Internal_Shdr *hdr; 172133965Sjdp char *name; 172233965Sjdp{ 172333965Sjdp asection *newsect; 172433965Sjdp 172533965Sjdp /* There ought to be a place to keep ELF backend specific flags, but 172633965Sjdp at the moment there isn't one. We just keep track of the 172733965Sjdp sections by their name, instead. Fortunately, the ABI gives 172833965Sjdp suggested names for all the MIPS specific sections, so we will 172933965Sjdp probably get away with this. */ 173033965Sjdp switch (hdr->sh_type) 173133965Sjdp { 173233965Sjdp case SHT_ALPHA_DEBUG: 173333965Sjdp if (strcmp (name, ".mdebug") != 0) 173433965Sjdp return false; 173533965Sjdp break; 173633965Sjdp#ifdef ERIC_neverdef 173733965Sjdp case SHT_ALPHA_REGINFO: 173833965Sjdp if (strcmp (name, ".reginfo") != 0 173933965Sjdp || hdr->sh_size != sizeof (Elf64_External_RegInfo)) 174033965Sjdp return false; 174133965Sjdp break; 174233965Sjdp#endif 174333965Sjdp default: 174433965Sjdp return false; 174533965Sjdp } 174633965Sjdp 174733965Sjdp if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name)) 174833965Sjdp return false; 174933965Sjdp newsect = hdr->bfd_section; 175033965Sjdp 175133965Sjdp if (hdr->sh_type == SHT_ALPHA_DEBUG) 175233965Sjdp { 175333965Sjdp if (! bfd_set_section_flags (abfd, newsect, 175433965Sjdp (bfd_get_section_flags (abfd, newsect) 175533965Sjdp | SEC_DEBUGGING))) 175633965Sjdp return false; 175733965Sjdp } 175833965Sjdp 175933965Sjdp#ifdef ERIC_neverdef 176033965Sjdp /* For a .reginfo section, set the gp value in the tdata information 176133965Sjdp from the contents of this section. We need the gp value while 176233965Sjdp processing relocs, so we just get it now. */ 176333965Sjdp if (hdr->sh_type == SHT_ALPHA_REGINFO) 176433965Sjdp { 176533965Sjdp Elf64_External_RegInfo ext; 176633965Sjdp Elf64_RegInfo s; 176733965Sjdp 176833965Sjdp if (! bfd_get_section_contents (abfd, newsect, (PTR) &ext, 176933965Sjdp (file_ptr) 0, sizeof ext)) 177033965Sjdp return false; 177133965Sjdp bfd_alpha_elf64_swap_reginfo_in (abfd, &ext, &s); 177233965Sjdp elf_gp (abfd) = s.ri_gp_value; 177333965Sjdp } 177433965Sjdp#endif 177533965Sjdp 177633965Sjdp return true; 177733965Sjdp} 177833965Sjdp 177933965Sjdp/* Set the correct type for an Alpha ELF section. We do this by the 178033965Sjdp section name, which is a hack, but ought to work. */ 178133965Sjdp 178233965Sjdpstatic boolean 178333965Sjdpelf64_alpha_fake_sections (abfd, hdr, sec) 178433965Sjdp bfd *abfd; 178533965Sjdp Elf64_Internal_Shdr *hdr; 178633965Sjdp asection *sec; 178733965Sjdp{ 178833965Sjdp register const char *name; 178933965Sjdp 179033965Sjdp name = bfd_get_section_name (abfd, sec); 179133965Sjdp 179233965Sjdp if (strcmp (name, ".mdebug") == 0) 179333965Sjdp { 179433965Sjdp hdr->sh_type = SHT_ALPHA_DEBUG; 179533965Sjdp /* In a shared object on Irix 5.3, the .mdebug section has an 179633965Sjdp entsize of 0. FIXME: Does this matter? */ 179733965Sjdp if ((abfd->flags & DYNAMIC) != 0 ) 179833965Sjdp hdr->sh_entsize = 0; 179933965Sjdp else 180033965Sjdp hdr->sh_entsize = 1; 180133965Sjdp } 180233965Sjdp#ifdef ERIC_neverdef 180333965Sjdp else if (strcmp (name, ".reginfo") == 0) 180433965Sjdp { 180533965Sjdp hdr->sh_type = SHT_ALPHA_REGINFO; 180633965Sjdp /* In a shared object on Irix 5.3, the .reginfo section has an 180733965Sjdp entsize of 0x18. FIXME: Does this matter? */ 180833965Sjdp if ((abfd->flags & DYNAMIC) != 0) 180933965Sjdp hdr->sh_entsize = sizeof (Elf64_External_RegInfo); 181033965Sjdp else 181133965Sjdp hdr->sh_entsize = 1; 181233965Sjdp 181333965Sjdp /* Force the section size to the correct value, even if the 181433965Sjdp linker thinks it is larger. The link routine below will only 181533965Sjdp write out this much data for .reginfo. */ 181633965Sjdp hdr->sh_size = sec->_raw_size = sizeof (Elf64_External_RegInfo); 181733965Sjdp } 181833965Sjdp else if (strcmp (name, ".hash") == 0 181933965Sjdp || strcmp (name, ".dynamic") == 0 182033965Sjdp || strcmp (name, ".dynstr") == 0) 182133965Sjdp { 182233965Sjdp hdr->sh_entsize = 0; 182333965Sjdp hdr->sh_info = SIZEOF_ALPHA_DYNSYM_SECNAMES; 182433965Sjdp } 182533965Sjdp#endif 182633965Sjdp else if (strcmp (name, ".sdata") == 0 182733965Sjdp || strcmp (name, ".sbss") == 0 182833965Sjdp || strcmp (name, ".lit4") == 0 182933965Sjdp || strcmp (name, ".lit8") == 0) 183033965Sjdp hdr->sh_flags |= SHF_ALPHA_GPREL; 183133965Sjdp 183233965Sjdp return true; 183333965Sjdp} 183433965Sjdp 183560510Sobrien/* Hook called by the linker routine which adds symbols from an object 183660510Sobrien file. We use it to put .comm items in .sbss, and not .bss. */ 183733965Sjdp 183860510Sobrienstatic boolean 183960510Sobrienelf64_alpha_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp) 184033965Sjdp bfd *abfd; 184160510Sobrien struct bfd_link_info *info; 184260510Sobrien const Elf_Internal_Sym *sym; 184360510Sobrien const char **namep; 184460510Sobrien flagword *flagsp; 184560510Sobrien asection **secp; 184660510Sobrien bfd_vma *valp; 184733965Sjdp{ 184860510Sobrien if (sym->st_shndx == SHN_COMMON 184960510Sobrien && !info->relocateable 185060510Sobrien && sym->st_size <= bfd_get_gp_size (abfd)) 185160510Sobrien { 185260510Sobrien /* Common symbols less than or equal to -G nn bytes are 185360510Sobrien automatically put into .sbss. */ 185433965Sjdp 185560510Sobrien asection *scomm = bfd_get_section_by_name (abfd, ".scommon"); 185633965Sjdp 185760510Sobrien if (scomm == NULL) 185860510Sobrien { 185960510Sobrien scomm = bfd_make_section (abfd, ".scommon"); 186060510Sobrien if (scomm == NULL 186160510Sobrien || !bfd_set_section_flags (abfd, scomm, (SEC_ALLOC 186260510Sobrien | SEC_IS_COMMON 186360510Sobrien | SEC_LINKER_CREATED))) 186460510Sobrien return false; 186560510Sobrien } 186633965Sjdp 186760510Sobrien *secp = scomm; 186860510Sobrien *valp = sym->st_size; 186933965Sjdp } 187033965Sjdp 187160510Sobrien return true; 187233965Sjdp} 187333965Sjdp 187433965Sjdp/* Create the .got section. */ 187533965Sjdp 187633965Sjdpstatic boolean 187733965Sjdpelf64_alpha_create_got_section(abfd, info) 187833965Sjdp bfd *abfd; 187933965Sjdp struct bfd_link_info *info; 188033965Sjdp{ 188133965Sjdp asection *s; 188233965Sjdp 188333965Sjdp if (bfd_get_section_by_name (abfd, ".got")) 188433965Sjdp return true; 188533965Sjdp 188633965Sjdp s = bfd_make_section (abfd, ".got"); 188733965Sjdp if (s == NULL 188833965Sjdp || !bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD 188933965Sjdp | SEC_HAS_CONTENTS 189033965Sjdp | SEC_IN_MEMORY 189133965Sjdp | SEC_LINKER_CREATED)) 189233965Sjdp || !bfd_set_section_alignment (abfd, s, 3)) 189333965Sjdp return false; 189433965Sjdp 189533965Sjdp alpha_elf_tdata (abfd)->got = s; 189633965Sjdp 189733965Sjdp return true; 189833965Sjdp} 189933965Sjdp 190033965Sjdp/* Create all the dynamic sections. */ 190133965Sjdp 190233965Sjdpstatic boolean 190333965Sjdpelf64_alpha_create_dynamic_sections (abfd, info) 190433965Sjdp bfd *abfd; 190533965Sjdp struct bfd_link_info *info; 190633965Sjdp{ 190733965Sjdp asection *s; 190833965Sjdp struct elf_link_hash_entry *h; 190933965Sjdp 191033965Sjdp /* We need to create .plt, .rela.plt, .got, and .rela.got sections. */ 191133965Sjdp 191233965Sjdp s = bfd_make_section (abfd, ".plt"); 191333965Sjdp if (s == NULL 191433965Sjdp || ! bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD 191533965Sjdp | SEC_HAS_CONTENTS 191633965Sjdp | SEC_IN_MEMORY 191733965Sjdp | SEC_LINKER_CREATED 191833965Sjdp | SEC_CODE)) 191933965Sjdp || ! bfd_set_section_alignment (abfd, s, 3)) 192033965Sjdp return false; 192133965Sjdp 192233965Sjdp /* Define the symbol _PROCEDURE_LINKAGE_TABLE_ at the start of the 192333965Sjdp .plt section. */ 192433965Sjdp h = NULL; 192533965Sjdp if (! (_bfd_generic_link_add_one_symbol 192633965Sjdp (info, abfd, "_PROCEDURE_LINKAGE_TABLE_", BSF_GLOBAL, s, 192733965Sjdp (bfd_vma) 0, (const char *) NULL, false, 192833965Sjdp get_elf_backend_data (abfd)->collect, 192933965Sjdp (struct bfd_link_hash_entry **) &h))) 193033965Sjdp return false; 193133965Sjdp h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR; 193233965Sjdp h->type = STT_OBJECT; 193333965Sjdp 193433965Sjdp if (info->shared 193533965Sjdp && ! _bfd_elf_link_record_dynamic_symbol (info, h)) 193633965Sjdp return false; 193733965Sjdp 193833965Sjdp s = bfd_make_section (abfd, ".rela.plt"); 193933965Sjdp if (s == NULL 194033965Sjdp || !bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD 194133965Sjdp | SEC_HAS_CONTENTS 194233965Sjdp | SEC_IN_MEMORY 194333965Sjdp | SEC_LINKER_CREATED 194433965Sjdp | SEC_READONLY)) 194533965Sjdp || ! bfd_set_section_alignment (abfd, s, 3)) 194633965Sjdp return false; 194733965Sjdp 194833965Sjdp /* We may or may not have created a .got section for this object, but 194933965Sjdp we definitely havn't done the rest of the work. */ 195033965Sjdp 195133965Sjdp if (!elf64_alpha_create_got_section (abfd, info)) 195233965Sjdp return false; 195333965Sjdp 195433965Sjdp s = bfd_make_section(abfd, ".rela.got"); 195533965Sjdp if (s == NULL 195633965Sjdp || !bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD 195733965Sjdp | SEC_HAS_CONTENTS 195833965Sjdp | SEC_IN_MEMORY 195933965Sjdp | SEC_LINKER_CREATED 196033965Sjdp | SEC_READONLY)) 196133965Sjdp || !bfd_set_section_alignment (abfd, s, 3)) 196233965Sjdp return false; 196333965Sjdp 196433965Sjdp /* Define the symbol _GLOBAL_OFFSET_TABLE_ at the start of the 196533965Sjdp dynobj's .got section. We don't do this in the linker script 196633965Sjdp because we don't want to define the symbol if we are not creating 196733965Sjdp a global offset table. */ 196833965Sjdp h = NULL; 196933965Sjdp if (!(_bfd_generic_link_add_one_symbol 197033965Sjdp (info, abfd, "_GLOBAL_OFFSET_TABLE_", BSF_GLOBAL, 197133965Sjdp alpha_elf_tdata(abfd)->got, (bfd_vma) 0, (const char *) NULL, 197233965Sjdp false, get_elf_backend_data (abfd)->collect, 197333965Sjdp (struct bfd_link_hash_entry **) &h))) 197433965Sjdp return false; 197533965Sjdp h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR; 197633965Sjdp h->type = STT_OBJECT; 197733965Sjdp 197833965Sjdp if (info->shared 197933965Sjdp && ! _bfd_elf_link_record_dynamic_symbol (info, h)) 198033965Sjdp return false; 198133965Sjdp 198233965Sjdp elf_hash_table (info)->hgot = h; 198333965Sjdp 198433965Sjdp return true; 198533965Sjdp} 198633965Sjdp 198733965Sjdp/* Read ECOFF debugging information from a .mdebug section into a 198833965Sjdp ecoff_debug_info structure. */ 198933965Sjdp 199033965Sjdpstatic boolean 199133965Sjdpelf64_alpha_read_ecoff_info (abfd, section, debug) 199233965Sjdp bfd *abfd; 199333965Sjdp asection *section; 199433965Sjdp struct ecoff_debug_info *debug; 199533965Sjdp{ 199633965Sjdp HDRR *symhdr; 199733965Sjdp const struct ecoff_debug_swap *swap; 199833965Sjdp char *ext_hdr = NULL; 199933965Sjdp 200033965Sjdp swap = get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap; 200177303Sobrien memset (debug, 0, sizeof (*debug)); 200233965Sjdp 200333965Sjdp ext_hdr = (char *) bfd_malloc ((size_t) swap->external_hdr_size); 200433965Sjdp if (ext_hdr == NULL && swap->external_hdr_size != 0) 200533965Sjdp goto error_return; 200633965Sjdp 200733965Sjdp if (bfd_get_section_contents (abfd, section, ext_hdr, (file_ptr) 0, 200833965Sjdp swap->external_hdr_size) 200933965Sjdp == false) 201033965Sjdp goto error_return; 201133965Sjdp 201233965Sjdp symhdr = &debug->symbolic_header; 201333965Sjdp (*swap->swap_hdr_in) (abfd, ext_hdr, symhdr); 201433965Sjdp 201533965Sjdp /* The symbolic header contains absolute file offsets and sizes to 201633965Sjdp read. */ 201733965Sjdp#define READ(ptr, offset, count, size, type) \ 201833965Sjdp if (symhdr->count == 0) \ 201933965Sjdp debug->ptr = NULL; \ 202033965Sjdp else \ 202133965Sjdp { \ 202233965Sjdp debug->ptr = (type) bfd_malloc ((size_t) (size * symhdr->count)); \ 202333965Sjdp if (debug->ptr == NULL) \ 202433965Sjdp goto error_return; \ 202533965Sjdp if (bfd_seek (abfd, (file_ptr) symhdr->offset, SEEK_SET) != 0 \ 202633965Sjdp || (bfd_read (debug->ptr, size, symhdr->count, \ 202733965Sjdp abfd) != size * symhdr->count)) \ 202833965Sjdp goto error_return; \ 202933965Sjdp } 203033965Sjdp 203133965Sjdp READ (line, cbLineOffset, cbLine, sizeof (unsigned char), unsigned char *); 203233965Sjdp READ (external_dnr, cbDnOffset, idnMax, swap->external_dnr_size, PTR); 203333965Sjdp READ (external_pdr, cbPdOffset, ipdMax, swap->external_pdr_size, PTR); 203433965Sjdp READ (external_sym, cbSymOffset, isymMax, swap->external_sym_size, PTR); 203533965Sjdp READ (external_opt, cbOptOffset, ioptMax, swap->external_opt_size, PTR); 203633965Sjdp READ (external_aux, cbAuxOffset, iauxMax, sizeof (union aux_ext), 203733965Sjdp union aux_ext *); 203833965Sjdp READ (ss, cbSsOffset, issMax, sizeof (char), char *); 203933965Sjdp READ (ssext, cbSsExtOffset, issExtMax, sizeof (char), char *); 204033965Sjdp READ (external_fdr, cbFdOffset, ifdMax, swap->external_fdr_size, PTR); 204133965Sjdp READ (external_rfd, cbRfdOffset, crfd, swap->external_rfd_size, PTR); 204233965Sjdp READ (external_ext, cbExtOffset, iextMax, swap->external_ext_size, PTR); 204333965Sjdp#undef READ 204433965Sjdp 204533965Sjdp debug->fdr = NULL; 204633965Sjdp debug->adjust = NULL; 204733965Sjdp 204833965Sjdp return true; 204933965Sjdp 205033965Sjdp error_return: 205133965Sjdp if (ext_hdr != NULL) 205233965Sjdp free (ext_hdr); 205333965Sjdp if (debug->line != NULL) 205433965Sjdp free (debug->line); 205533965Sjdp if (debug->external_dnr != NULL) 205633965Sjdp free (debug->external_dnr); 205733965Sjdp if (debug->external_pdr != NULL) 205833965Sjdp free (debug->external_pdr); 205933965Sjdp if (debug->external_sym != NULL) 206033965Sjdp free (debug->external_sym); 206133965Sjdp if (debug->external_opt != NULL) 206233965Sjdp free (debug->external_opt); 206333965Sjdp if (debug->external_aux != NULL) 206433965Sjdp free (debug->external_aux); 206533965Sjdp if (debug->ss != NULL) 206633965Sjdp free (debug->ss); 206733965Sjdp if (debug->ssext != NULL) 206833965Sjdp free (debug->ssext); 206933965Sjdp if (debug->external_fdr != NULL) 207033965Sjdp free (debug->external_fdr); 207133965Sjdp if (debug->external_rfd != NULL) 207233965Sjdp free (debug->external_rfd); 207333965Sjdp if (debug->external_ext != NULL) 207433965Sjdp free (debug->external_ext); 207533965Sjdp return false; 207633965Sjdp} 207733965Sjdp 207833965Sjdp/* Alpha ELF local labels start with '$'. */ 207933965Sjdp 208033965Sjdpstatic boolean 208133965Sjdpelf64_alpha_is_local_label_name (abfd, name) 208233965Sjdp bfd *abfd; 208333965Sjdp const char *name; 208433965Sjdp{ 208533965Sjdp return name[0] == '$'; 208633965Sjdp} 208733965Sjdp 208833965Sjdp/* Alpha ELF follows MIPS ELF in using a special find_nearest_line 208933965Sjdp routine in order to handle the ECOFF debugging information. We 209033965Sjdp still call this mips_elf_find_line because of the slot 209133965Sjdp find_line_info in elf_obj_tdata is declared that way. */ 209233965Sjdp 209333965Sjdpstruct mips_elf_find_line 209433965Sjdp{ 209533965Sjdp struct ecoff_debug_info d; 209633965Sjdp struct ecoff_find_line i; 209733965Sjdp}; 209833965Sjdp 209933965Sjdpstatic boolean 210033965Sjdpelf64_alpha_find_nearest_line (abfd, section, symbols, offset, filename_ptr, 210133965Sjdp functionname_ptr, line_ptr) 210233965Sjdp bfd *abfd; 210333965Sjdp asection *section; 210433965Sjdp asymbol **symbols; 210533965Sjdp bfd_vma offset; 210633965Sjdp const char **filename_ptr; 210733965Sjdp const char **functionname_ptr; 210833965Sjdp unsigned int *line_ptr; 210933965Sjdp{ 211033965Sjdp asection *msec; 211133965Sjdp 211277303Sobrien if (_bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset, 211377303Sobrien filename_ptr, functionname_ptr, 211477303Sobrien line_ptr, 0, 211577303Sobrien &elf_tdata (abfd)->dwarf2_find_line_info)) 211677303Sobrien return true; 211777303Sobrien 211833965Sjdp msec = bfd_get_section_by_name (abfd, ".mdebug"); 211933965Sjdp if (msec != NULL) 212033965Sjdp { 212133965Sjdp flagword origflags; 212233965Sjdp struct mips_elf_find_line *fi; 212333965Sjdp const struct ecoff_debug_swap * const swap = 212433965Sjdp get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap; 212533965Sjdp 212633965Sjdp /* If we are called during a link, alpha_elf_final_link may have 212733965Sjdp cleared the SEC_HAS_CONTENTS field. We force it back on here 212833965Sjdp if appropriate (which it normally will be). */ 212933965Sjdp origflags = msec->flags; 213033965Sjdp if (elf_section_data (msec)->this_hdr.sh_type != SHT_NOBITS) 213133965Sjdp msec->flags |= SEC_HAS_CONTENTS; 213233965Sjdp 213333965Sjdp fi = elf_tdata (abfd)->find_line_info; 213433965Sjdp if (fi == NULL) 213533965Sjdp { 213633965Sjdp bfd_size_type external_fdr_size; 213733965Sjdp char *fraw_src; 213833965Sjdp char *fraw_end; 213933965Sjdp struct fdr *fdr_ptr; 214033965Sjdp 214133965Sjdp fi = ((struct mips_elf_find_line *) 214233965Sjdp bfd_zalloc (abfd, sizeof (struct mips_elf_find_line))); 214333965Sjdp if (fi == NULL) 214433965Sjdp { 214533965Sjdp msec->flags = origflags; 214633965Sjdp return false; 214733965Sjdp } 214833965Sjdp 214933965Sjdp if (!elf64_alpha_read_ecoff_info (abfd, msec, &fi->d)) 215033965Sjdp { 215133965Sjdp msec->flags = origflags; 215233965Sjdp return false; 215333965Sjdp } 215433965Sjdp 215533965Sjdp /* Swap in the FDR information. */ 215633965Sjdp fi->d.fdr = ((struct fdr *) 215733965Sjdp bfd_alloc (abfd, 215833965Sjdp (fi->d.symbolic_header.ifdMax * 215933965Sjdp sizeof (struct fdr)))); 216033965Sjdp if (fi->d.fdr == NULL) 216133965Sjdp { 216233965Sjdp msec->flags = origflags; 216333965Sjdp return false; 216433965Sjdp } 216533965Sjdp external_fdr_size = swap->external_fdr_size; 216633965Sjdp fdr_ptr = fi->d.fdr; 216733965Sjdp fraw_src = (char *) fi->d.external_fdr; 216833965Sjdp fraw_end = (fraw_src 216933965Sjdp + fi->d.symbolic_header.ifdMax * external_fdr_size); 217033965Sjdp for (; fraw_src < fraw_end; fraw_src += external_fdr_size, fdr_ptr++) 217133965Sjdp (*swap->swap_fdr_in) (abfd, (PTR) fraw_src, fdr_ptr); 217233965Sjdp 217333965Sjdp elf_tdata (abfd)->find_line_info = fi; 217433965Sjdp 217533965Sjdp /* Note that we don't bother to ever free this information. 217633965Sjdp find_nearest_line is either called all the time, as in 217733965Sjdp objdump -l, so the information should be saved, or it is 217833965Sjdp rarely called, as in ld error messages, so the memory 217933965Sjdp wasted is unimportant. Still, it would probably be a 218033965Sjdp good idea for free_cached_info to throw it away. */ 218133965Sjdp } 218233965Sjdp 218333965Sjdp if (_bfd_ecoff_locate_line (abfd, section, offset, &fi->d, swap, 218433965Sjdp &fi->i, filename_ptr, functionname_ptr, 218533965Sjdp line_ptr)) 218633965Sjdp { 218733965Sjdp msec->flags = origflags; 218833965Sjdp return true; 218933965Sjdp } 219033965Sjdp 219133965Sjdp msec->flags = origflags; 219233965Sjdp } 219333965Sjdp 219433965Sjdp /* Fall back on the generic ELF find_nearest_line routine. */ 219533965Sjdp 219633965Sjdp return _bfd_elf_find_nearest_line (abfd, section, symbols, offset, 219733965Sjdp filename_ptr, functionname_ptr, 219833965Sjdp line_ptr); 219933965Sjdp} 220033965Sjdp 220133965Sjdp/* Structure used to pass information to alpha_elf_output_extsym. */ 220233965Sjdp 220333965Sjdpstruct extsym_info 220433965Sjdp{ 220533965Sjdp bfd *abfd; 220633965Sjdp struct bfd_link_info *info; 220733965Sjdp struct ecoff_debug_info *debug; 220833965Sjdp const struct ecoff_debug_swap *swap; 220933965Sjdp boolean failed; 221033965Sjdp}; 221133965Sjdp 221233965Sjdpstatic boolean 221333965Sjdpelf64_alpha_output_extsym (h, data) 221433965Sjdp struct alpha_elf_link_hash_entry *h; 221533965Sjdp PTR data; 221633965Sjdp{ 221733965Sjdp struct extsym_info *einfo = (struct extsym_info *) data; 221833965Sjdp boolean strip; 221933965Sjdp asection *sec, *output_section; 222033965Sjdp 222133965Sjdp if (h->root.indx == -2) 222233965Sjdp strip = false; 222333965Sjdp else if (((h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0 222433965Sjdp || (h->root.elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) != 0) 222533965Sjdp && (h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0 222633965Sjdp && (h->root.elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) == 0) 222733965Sjdp strip = true; 222833965Sjdp else if (einfo->info->strip == strip_all 222933965Sjdp || (einfo->info->strip == strip_some 223033965Sjdp && bfd_hash_lookup (einfo->info->keep_hash, 223133965Sjdp h->root.root.root.string, 223233965Sjdp false, false) == NULL)) 223333965Sjdp strip = true; 223433965Sjdp else 223533965Sjdp strip = false; 223633965Sjdp 223733965Sjdp if (strip) 223833965Sjdp return true; 223933965Sjdp 224033965Sjdp if (h->esym.ifd == -2) 224133965Sjdp { 224233965Sjdp h->esym.jmptbl = 0; 224333965Sjdp h->esym.cobol_main = 0; 224433965Sjdp h->esym.weakext = 0; 224533965Sjdp h->esym.reserved = 0; 224633965Sjdp h->esym.ifd = ifdNil; 224733965Sjdp h->esym.asym.value = 0; 224833965Sjdp h->esym.asym.st = stGlobal; 224933965Sjdp 225033965Sjdp if (h->root.root.type != bfd_link_hash_defined 225133965Sjdp && h->root.root.type != bfd_link_hash_defweak) 225233965Sjdp h->esym.asym.sc = scAbs; 225333965Sjdp else 225433965Sjdp { 225533965Sjdp const char *name; 225633965Sjdp 225733965Sjdp sec = h->root.root.u.def.section; 225833965Sjdp output_section = sec->output_section; 225933965Sjdp 226033965Sjdp /* When making a shared library and symbol h is the one from 226133965Sjdp the another shared library, OUTPUT_SECTION may be null. */ 226233965Sjdp if (output_section == NULL) 226333965Sjdp h->esym.asym.sc = scUndefined; 226433965Sjdp else 226533965Sjdp { 226633965Sjdp name = bfd_section_name (output_section->owner, output_section); 226733965Sjdp 226833965Sjdp if (strcmp (name, ".text") == 0) 226933965Sjdp h->esym.asym.sc = scText; 227033965Sjdp else if (strcmp (name, ".data") == 0) 227133965Sjdp h->esym.asym.sc = scData; 227233965Sjdp else if (strcmp (name, ".sdata") == 0) 227333965Sjdp h->esym.asym.sc = scSData; 227433965Sjdp else if (strcmp (name, ".rodata") == 0 227533965Sjdp || strcmp (name, ".rdata") == 0) 227633965Sjdp h->esym.asym.sc = scRData; 227733965Sjdp else if (strcmp (name, ".bss") == 0) 227833965Sjdp h->esym.asym.sc = scBss; 227933965Sjdp else if (strcmp (name, ".sbss") == 0) 228033965Sjdp h->esym.asym.sc = scSBss; 228133965Sjdp else if (strcmp (name, ".init") == 0) 228233965Sjdp h->esym.asym.sc = scInit; 228333965Sjdp else if (strcmp (name, ".fini") == 0) 228433965Sjdp h->esym.asym.sc = scFini; 228533965Sjdp else 228633965Sjdp h->esym.asym.sc = scAbs; 228733965Sjdp } 228833965Sjdp } 228933965Sjdp 229033965Sjdp h->esym.asym.reserved = 0; 229133965Sjdp h->esym.asym.index = indexNil; 229233965Sjdp } 229333965Sjdp 229433965Sjdp if (h->root.root.type == bfd_link_hash_common) 229533965Sjdp h->esym.asym.value = h->root.root.u.c.size; 229633965Sjdp else if (h->root.root.type == bfd_link_hash_defined 229733965Sjdp || h->root.root.type == bfd_link_hash_defweak) 229833965Sjdp { 229933965Sjdp if (h->esym.asym.sc == scCommon) 230033965Sjdp h->esym.asym.sc = scBss; 230133965Sjdp else if (h->esym.asym.sc == scSCommon) 230233965Sjdp h->esym.asym.sc = scSBss; 230333965Sjdp 230433965Sjdp sec = h->root.root.u.def.section; 230533965Sjdp output_section = sec->output_section; 230633965Sjdp if (output_section != NULL) 230733965Sjdp h->esym.asym.value = (h->root.root.u.def.value 230833965Sjdp + sec->output_offset 230933965Sjdp + output_section->vma); 231033965Sjdp else 231133965Sjdp h->esym.asym.value = 0; 231233965Sjdp } 231333965Sjdp else if ((h->root.elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0) 231433965Sjdp { 231533965Sjdp /* Set type and value for a symbol with a function stub. */ 231633965Sjdp h->esym.asym.st = stProc; 231733965Sjdp sec = bfd_get_section_by_name (einfo->abfd, ".plt"); 231833965Sjdp if (sec == NULL) 231933965Sjdp h->esym.asym.value = 0; 232033965Sjdp else 232133965Sjdp { 232233965Sjdp output_section = sec->output_section; 232333965Sjdp if (output_section != NULL) 232460510Sobrien h->esym.asym.value = (h->root.plt.offset 232533965Sjdp + sec->output_offset 232633965Sjdp + output_section->vma); 232733965Sjdp else 232833965Sjdp h->esym.asym.value = 0; 232933965Sjdp } 233033965Sjdp#if 0 /* FIXME? */ 233133965Sjdp h->esym.ifd = 0; 233233965Sjdp#endif 233333965Sjdp } 233433965Sjdp 233533965Sjdp if (! bfd_ecoff_debug_one_external (einfo->abfd, einfo->debug, einfo->swap, 233633965Sjdp h->root.root.root.string, 233733965Sjdp &h->esym)) 233833965Sjdp { 233933965Sjdp einfo->failed = true; 234033965Sjdp return false; 234133965Sjdp } 234233965Sjdp 234333965Sjdp return true; 234433965Sjdp} 234533965Sjdp 234633965Sjdp/* FIXME: Create a runtime procedure table from the .mdebug section. 234733965Sjdp 234833965Sjdpstatic boolean 234933965Sjdpmips_elf_create_procedure_table (handle, abfd, info, s, debug) 235033965Sjdp PTR handle; 235133965Sjdp bfd *abfd; 235233965Sjdp struct bfd_link_info *info; 235333965Sjdp asection *s; 235433965Sjdp struct ecoff_debug_info *debug; 235533965Sjdp*/ 235633965Sjdp 235733965Sjdp/* Handle dynamic relocations when doing an Alpha ELF link. */ 235833965Sjdp 235933965Sjdpstatic boolean 236033965Sjdpelf64_alpha_check_relocs (abfd, info, sec, relocs) 236133965Sjdp bfd *abfd; 236233965Sjdp struct bfd_link_info *info; 236333965Sjdp asection *sec; 236433965Sjdp const Elf_Internal_Rela *relocs; 236533965Sjdp{ 236633965Sjdp bfd *dynobj; 236733965Sjdp asection *sreloc; 236833965Sjdp const char *rel_sec_name; 236933965Sjdp Elf_Internal_Shdr *symtab_hdr; 237033965Sjdp struct alpha_elf_link_hash_entry **sym_hashes; 237133965Sjdp struct alpha_elf_got_entry **local_got_entries; 237233965Sjdp const Elf_Internal_Rela *rel, *relend; 237333965Sjdp int got_created; 237433965Sjdp 237533965Sjdp if (info->relocateable) 237633965Sjdp return true; 237733965Sjdp 237833965Sjdp dynobj = elf_hash_table(info)->dynobj; 237933965Sjdp if (dynobj == NULL) 238033965Sjdp elf_hash_table(info)->dynobj = dynobj = abfd; 238133965Sjdp 238233965Sjdp sreloc = NULL; 238333965Sjdp rel_sec_name = NULL; 238433965Sjdp symtab_hdr = &elf_tdata(abfd)->symtab_hdr; 238533965Sjdp sym_hashes = alpha_elf_sym_hashes(abfd); 238633965Sjdp local_got_entries = alpha_elf_tdata(abfd)->local_got_entries; 238733965Sjdp got_created = 0; 238833965Sjdp 238933965Sjdp relend = relocs + sec->reloc_count; 239033965Sjdp for (rel = relocs; rel < relend; ++rel) 239133965Sjdp { 239233965Sjdp unsigned long r_symndx, r_type; 239333965Sjdp struct alpha_elf_link_hash_entry *h; 239433965Sjdp 239533965Sjdp r_symndx = ELF64_R_SYM (rel->r_info); 239633965Sjdp if (r_symndx < symtab_hdr->sh_info) 239733965Sjdp h = NULL; 239833965Sjdp else 239933965Sjdp { 240033965Sjdp h = sym_hashes[r_symndx - symtab_hdr->sh_info]; 240138889Sjdp 240238889Sjdp while (h->root.root.type == bfd_link_hash_indirect 240338889Sjdp || h->root.root.type == bfd_link_hash_warning) 240438889Sjdp h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link; 240538889Sjdp 240633965Sjdp h->root.elf_link_hash_flags |= ELF_LINK_HASH_REF_REGULAR; 240733965Sjdp } 240833965Sjdp r_type = ELF64_R_TYPE (rel->r_info); 240933965Sjdp 241033965Sjdp switch (r_type) 241133965Sjdp { 241233965Sjdp case R_ALPHA_LITERAL: 241333965Sjdp { 241433965Sjdp struct alpha_elf_got_entry *gotent; 241533965Sjdp int flags = 0; 241633965Sjdp 241733965Sjdp if (h) 241833965Sjdp { 241933965Sjdp /* Search for and possibly create a got entry. */ 242033965Sjdp for (gotent = h->got_entries; gotent ; gotent = gotent->next) 242133965Sjdp if (gotent->gotobj == abfd && 242233965Sjdp gotent->addend == rel->r_addend) 242333965Sjdp break; 242433965Sjdp 242533965Sjdp if (!gotent) 242633965Sjdp { 242733965Sjdp gotent = ((struct alpha_elf_got_entry *) 242833965Sjdp bfd_alloc (abfd, 242933965Sjdp sizeof (struct alpha_elf_got_entry))); 243033965Sjdp if (!gotent) 243133965Sjdp return false; 243233965Sjdp 243333965Sjdp gotent->gotobj = abfd; 243433965Sjdp gotent->addend = rel->r_addend; 243533965Sjdp gotent->got_offset = -1; 243633965Sjdp gotent->flags = 0; 243760510Sobrien gotent->use_count = 1; 243833965Sjdp 243933965Sjdp gotent->next = h->got_entries; 244033965Sjdp h->got_entries = gotent; 244133965Sjdp 244233965Sjdp alpha_elf_tdata (abfd)->total_got_entries++; 244333965Sjdp } 244460510Sobrien else 244560510Sobrien gotent->use_count += 1; 244633965Sjdp } 244733965Sjdp else 244833965Sjdp { 244933965Sjdp /* This is a local .got entry -- record for merge. */ 245033965Sjdp if (!local_got_entries) 245133965Sjdp { 245233965Sjdp size_t size; 245333965Sjdp size = (symtab_hdr->sh_info 245433965Sjdp * sizeof (struct alpha_elf_got_entry *)); 245533965Sjdp 245633965Sjdp local_got_entries = ((struct alpha_elf_got_entry **) 245733965Sjdp bfd_alloc (abfd, size)); 245833965Sjdp if (!local_got_entries) 245933965Sjdp return false; 246033965Sjdp 246133965Sjdp memset (local_got_entries, 0, size); 246233965Sjdp alpha_elf_tdata (abfd)->local_got_entries = 246333965Sjdp local_got_entries; 246433965Sjdp } 246533965Sjdp 246633965Sjdp for (gotent = local_got_entries[ELF64_R_SYM(rel->r_info)]; 246733965Sjdp gotent != NULL && gotent->addend != rel->r_addend; 246833965Sjdp gotent = gotent->next) 246933965Sjdp continue; 247033965Sjdp if (!gotent) 247133965Sjdp { 247233965Sjdp gotent = ((struct alpha_elf_got_entry *) 247333965Sjdp bfd_alloc (abfd, 247433965Sjdp sizeof (struct alpha_elf_got_entry))); 247533965Sjdp if (!gotent) 247633965Sjdp return false; 247733965Sjdp 247833965Sjdp gotent->gotobj = abfd; 247933965Sjdp gotent->addend = rel->r_addend; 248033965Sjdp gotent->got_offset = -1; 248133965Sjdp gotent->flags = 0; 248260510Sobrien gotent->use_count = 1; 248333965Sjdp 248433965Sjdp gotent->next = local_got_entries[ELF64_R_SYM(rel->r_info)]; 248533965Sjdp local_got_entries[ELF64_R_SYM(rel->r_info)] = gotent; 248633965Sjdp 248733965Sjdp alpha_elf_tdata(abfd)->total_got_entries++; 248833965Sjdp alpha_elf_tdata(abfd)->n_local_got_entries++; 248933965Sjdp } 249060510Sobrien else 249160510Sobrien gotent->use_count += 1; 249233965Sjdp } 249333965Sjdp 249433965Sjdp /* Remember how this literal is used from its LITUSEs. 249533965Sjdp This will be important when it comes to decide if we can 249633965Sjdp create a .plt entry for a function symbol. */ 249733965Sjdp if (rel+1 < relend 249833965Sjdp && ELF64_R_TYPE (rel[1].r_info) == R_ALPHA_LITUSE) 249933965Sjdp { 250033965Sjdp do 250133965Sjdp { 250233965Sjdp ++rel; 250333965Sjdp if (rel->r_addend >= 1 && rel->r_addend <= 3) 250433965Sjdp flags |= 1 << rel->r_addend; 250533965Sjdp } 250633965Sjdp while (rel+1 < relend && 250733965Sjdp ELF64_R_TYPE (rel[1].r_info) == R_ALPHA_LITUSE); 250833965Sjdp } 250933965Sjdp else 251033965Sjdp { 251133965Sjdp /* No LITUSEs -- presumably the address is not being 251233965Sjdp loaded for nothing. */ 251333965Sjdp flags = ALPHA_ELF_LINK_HASH_LU_ADDR; 251433965Sjdp } 251533965Sjdp 251633965Sjdp gotent->flags |= flags; 251733965Sjdp if (h) 251833965Sjdp { 251933965Sjdp /* Make a guess as to whether a .plt entry will be needed. */ 252033965Sjdp if ((h->flags |= flags) == ALPHA_ELF_LINK_HASH_LU_FUNC) 252133965Sjdp h->root.elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; 252233965Sjdp else 252333965Sjdp h->root.elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; 252433965Sjdp } 252533965Sjdp } 252633965Sjdp /* FALLTHRU */ 252733965Sjdp 252833965Sjdp case R_ALPHA_GPDISP: 252933965Sjdp case R_ALPHA_GPREL32: 253060510Sobrien case R_ALPHA_GPRELHIGH: 253160510Sobrien case R_ALPHA_GPRELLOW: 253233965Sjdp /* We don't actually use the .got here, but the sections must 253333965Sjdp be created before the linker maps input sections to output 253433965Sjdp sections. */ 253533965Sjdp if (!got_created) 253633965Sjdp { 253733965Sjdp if (!elf64_alpha_create_got_section (abfd, info)) 253833965Sjdp return false; 253933965Sjdp 254033965Sjdp /* Make sure the object's gotobj is set to itself so 254133965Sjdp that we default to every object with its own .got. 254233965Sjdp We'll merge .gots later once we've collected each 254333965Sjdp object's info. */ 254433965Sjdp alpha_elf_tdata(abfd)->gotobj = abfd; 254533965Sjdp 254633965Sjdp got_created = 1; 254733965Sjdp } 254833965Sjdp break; 254933965Sjdp 255033965Sjdp case R_ALPHA_SREL16: 255133965Sjdp case R_ALPHA_SREL32: 255233965Sjdp case R_ALPHA_SREL64: 255333965Sjdp if (h == NULL) 255433965Sjdp break; 255533965Sjdp /* FALLTHRU */ 255633965Sjdp 255733965Sjdp case R_ALPHA_REFLONG: 255833965Sjdp case R_ALPHA_REFQUAD: 255933965Sjdp if (rel_sec_name == NULL) 256033965Sjdp { 256133965Sjdp rel_sec_name = (bfd_elf_string_from_elf_section 256233965Sjdp (abfd, elf_elfheader(abfd)->e_shstrndx, 256333965Sjdp elf_section_data(sec)->rel_hdr.sh_name)); 256433965Sjdp if (rel_sec_name == NULL) 256533965Sjdp return false; 256633965Sjdp 256733965Sjdp BFD_ASSERT (strncmp (rel_sec_name, ".rela", 5) == 0 256833965Sjdp && strcmp (bfd_get_section_name (abfd, sec), 256933965Sjdp rel_sec_name+5) == 0); 257033965Sjdp } 257133965Sjdp 257233965Sjdp /* We need to create the section here now whether we eventually 257333965Sjdp use it or not so that it gets mapped to an output section by 257433965Sjdp the linker. If not used, we'll kill it in 257533965Sjdp size_dynamic_sections. */ 257633965Sjdp if (sreloc == NULL) 257733965Sjdp { 257833965Sjdp sreloc = bfd_get_section_by_name (dynobj, rel_sec_name); 257933965Sjdp if (sreloc == NULL) 258033965Sjdp { 258133965Sjdp sreloc = bfd_make_section (dynobj, rel_sec_name); 258233965Sjdp if (sreloc == NULL 258333965Sjdp || !bfd_set_section_flags (dynobj, sreloc, 258477303Sobrien ((sec->flags & (SEC_ALLOC 258577303Sobrien | SEC_LOAD)) 258633965Sjdp | SEC_HAS_CONTENTS 258733965Sjdp | SEC_IN_MEMORY 258833965Sjdp | SEC_LINKER_CREATED 258933965Sjdp | SEC_READONLY)) 259033965Sjdp || !bfd_set_section_alignment (dynobj, sreloc, 3)) 259133965Sjdp return false; 259233965Sjdp } 259333965Sjdp } 259433965Sjdp 259533965Sjdp if (h) 259633965Sjdp { 259733965Sjdp /* Since we havn't seen all of the input symbols yet, we 259833965Sjdp don't know whether we'll actually need a dynamic relocation 259933965Sjdp entry for this reloc. So make a record of it. Once we 260033965Sjdp find out if this thing needs dynamic relocation we'll 260177303Sobrien expand the relocation sections by the appropriate amount. */ 260233965Sjdp 260333965Sjdp struct alpha_elf_reloc_entry *rent; 260433965Sjdp 260533965Sjdp for (rent = h->reloc_entries; rent; rent = rent->next) 260633965Sjdp if (rent->rtype == r_type && rent->srel == sreloc) 260733965Sjdp break; 260833965Sjdp 260933965Sjdp if (!rent) 261033965Sjdp { 261133965Sjdp rent = ((struct alpha_elf_reloc_entry *) 261233965Sjdp bfd_alloc (abfd, 261333965Sjdp sizeof (struct alpha_elf_reloc_entry))); 261433965Sjdp if (!rent) 261533965Sjdp return false; 261633965Sjdp 261733965Sjdp rent->srel = sreloc; 261833965Sjdp rent->rtype = r_type; 261933965Sjdp rent->count = 1; 262033965Sjdp 262133965Sjdp rent->next = h->reloc_entries; 262233965Sjdp h->reloc_entries = rent; 262333965Sjdp } 262433965Sjdp else 262533965Sjdp rent->count++; 262633965Sjdp } 262760510Sobrien else if (info->shared && (sec->flags & SEC_ALLOC)) 262833965Sjdp { 262960510Sobrien /* If this is a shared library, and the section is to be 263060510Sobrien loaded into memory, we need a RELATIVE reloc. */ 263133965Sjdp sreloc->_raw_size += sizeof (Elf64_External_Rela); 263233965Sjdp } 263333965Sjdp break; 263433965Sjdp } 263533965Sjdp } 263633965Sjdp 263733965Sjdp return true; 263833965Sjdp} 263933965Sjdp 264033965Sjdp/* Adjust a symbol defined by a dynamic object and referenced by a 264133965Sjdp regular object. The current definition is in some section of the 264233965Sjdp dynamic object, but we're not including those sections. We have to 264333965Sjdp change the definition to something the rest of the link can 264433965Sjdp understand. */ 264533965Sjdp 264633965Sjdpstatic boolean 264733965Sjdpelf64_alpha_adjust_dynamic_symbol (info, h) 264833965Sjdp struct bfd_link_info *info; 264933965Sjdp struct elf_link_hash_entry *h; 265033965Sjdp{ 265133965Sjdp bfd *dynobj; 265233965Sjdp asection *s; 265333965Sjdp struct alpha_elf_link_hash_entry *ah; 265433965Sjdp 265533965Sjdp dynobj = elf_hash_table(info)->dynobj; 265633965Sjdp ah = (struct alpha_elf_link_hash_entry *)h; 265733965Sjdp 265833965Sjdp /* Now that we've seen all of the input symbols, finalize our decision 265933965Sjdp about whether this symbol should get a .plt entry. */ 266033965Sjdp 266133965Sjdp if (h->root.type != bfd_link_hash_undefweak 266233965Sjdp && alpha_elf_dynamic_symbol_p (h, info) 266333965Sjdp && ((h->type == STT_FUNC 266433965Sjdp && !(ah->flags & ALPHA_ELF_LINK_HASH_LU_ADDR)) 266533965Sjdp || (h->type == STT_NOTYPE 266633965Sjdp && ah->flags == ALPHA_ELF_LINK_HASH_LU_FUNC)) 266733965Sjdp /* Don't prevent otherwise valid programs from linking by attempting 266833965Sjdp to create a new .got entry somewhere. A Correct Solution would be 266933965Sjdp to add a new .got section to a new object file and let it be merged 267033965Sjdp somewhere later. But for now don't bother. */ 267133965Sjdp && ah->got_entries) 267233965Sjdp { 267333965Sjdp h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; 267433965Sjdp 267533965Sjdp s = bfd_get_section_by_name(dynobj, ".plt"); 267633965Sjdp if (!s && !elf64_alpha_create_dynamic_sections (dynobj, info)) 267733965Sjdp return false; 267833965Sjdp 267933965Sjdp /* The first bit of the .plt is reserved. */ 268033965Sjdp if (s->_raw_size == 0) 268133965Sjdp s->_raw_size = PLT_HEADER_SIZE; 268233965Sjdp 268360510Sobrien h->plt.offset = s->_raw_size; 268433965Sjdp s->_raw_size += PLT_ENTRY_SIZE; 268533965Sjdp 268633965Sjdp /* If this symbol is not defined in a regular file, and we are not 268733965Sjdp generating a shared library, then set the symbol to the location 268833965Sjdp in the .plt. This is required to make function pointers compare 268933965Sjdp equal between the normal executable and the shared library. */ 269048850Sdfr if (! info->shared 269148850Sdfr && h->root.type != bfd_link_hash_defweak) 269233965Sjdp { 269333965Sjdp h->root.u.def.section = s; 269460510Sobrien h->root.u.def.value = h->plt.offset; 269533965Sjdp } 269633965Sjdp 269733965Sjdp /* We also need a JMP_SLOT entry in the .rela.plt section. */ 269833965Sjdp s = bfd_get_section_by_name (dynobj, ".rela.plt"); 269933965Sjdp BFD_ASSERT (s != NULL); 270033965Sjdp s->_raw_size += sizeof (Elf64_External_Rela); 270133965Sjdp 270233965Sjdp return true; 270333965Sjdp } 270433965Sjdp else 270533965Sjdp h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; 270633965Sjdp 270733965Sjdp /* If this is a weak symbol, and there is a real definition, the 270833965Sjdp processor independent code will have arranged for us to see the 270933965Sjdp real definition first, and we can just use the same value. */ 271033965Sjdp if (h->weakdef != NULL) 271133965Sjdp { 271233965Sjdp BFD_ASSERT (h->weakdef->root.type == bfd_link_hash_defined 271333965Sjdp || h->weakdef->root.type == bfd_link_hash_defweak); 271433965Sjdp h->root.u.def.section = h->weakdef->root.u.def.section; 271533965Sjdp h->root.u.def.value = h->weakdef->root.u.def.value; 271633965Sjdp return true; 271733965Sjdp } 271833965Sjdp 271933965Sjdp /* This is a reference to a symbol defined by a dynamic object which 272033965Sjdp is not a function. The Alpha, since it uses .got entries for all 272133965Sjdp symbols even in regular objects, does not need the hackery of a 272233965Sjdp .dynbss section and COPY dynamic relocations. */ 272333965Sjdp 272433965Sjdp return true; 272533965Sjdp} 272633965Sjdp 272738889Sjdp/* Symbol versioning can create new symbols, and make our old symbols 272838889Sjdp indirect to the new ones. Consolidate the got and reloc information 272938889Sjdp in these situations. */ 273038889Sjdp 273138889Sjdpstatic boolean 273238889Sjdpelf64_alpha_merge_ind_symbols (hi, dummy) 273338889Sjdp struct alpha_elf_link_hash_entry *hi; 273438889Sjdp PTR dummy; 273538889Sjdp{ 273638889Sjdp struct alpha_elf_link_hash_entry *hs; 273738889Sjdp 273838889Sjdp if (hi->root.root.type != bfd_link_hash_indirect) 273938889Sjdp return true; 274038889Sjdp hs = hi; 274138889Sjdp do { 274238889Sjdp hs = (struct alpha_elf_link_hash_entry *)hs->root.root.u.i.link; 274338889Sjdp } while (hs->root.root.type == bfd_link_hash_indirect); 274438889Sjdp 274538889Sjdp /* Merge the flags. Whee. */ 274638889Sjdp 274738889Sjdp hs->flags |= hi->flags; 274838889Sjdp 274938889Sjdp /* Merge the .got entries. Cannibalize the old symbol's list in 275038889Sjdp doing so, since we don't need it anymore. */ 275138889Sjdp 275238889Sjdp if (hs->got_entries == NULL) 275338889Sjdp hs->got_entries = hi->got_entries; 275438889Sjdp else 275538889Sjdp { 275638889Sjdp struct alpha_elf_got_entry *gi, *gs, *gin, *gsh; 275738889Sjdp 275838889Sjdp gsh = hs->got_entries; 275938889Sjdp for (gi = hi->got_entries; gi ; gi = gin) 276038889Sjdp { 276138889Sjdp gin = gi->next; 276238889Sjdp for (gs = gsh; gs ; gs = gs->next) 276360510Sobrien if (gi->gotobj == gs->gotobj && gi->addend == gs->addend) 276438889Sjdp goto got_found; 276538889Sjdp gi->next = hs->got_entries; 276638889Sjdp hs->got_entries = gi; 276738889Sjdp got_found:; 276838889Sjdp } 276938889Sjdp } 277038889Sjdp hi->got_entries = NULL; 277138889Sjdp 277238889Sjdp /* And similar for the reloc entries. */ 277338889Sjdp 277438889Sjdp if (hs->reloc_entries == NULL) 277538889Sjdp hs->reloc_entries = hi->reloc_entries; 277638889Sjdp else 277738889Sjdp { 277838889Sjdp struct alpha_elf_reloc_entry *ri, *rs, *rin, *rsh; 277938889Sjdp 278038889Sjdp rsh = hs->reloc_entries; 278138889Sjdp for (ri = hi->reloc_entries; ri ; ri = rin) 278238889Sjdp { 278338889Sjdp rin = ri->next; 278438889Sjdp for (rs = rsh; rs ; rs = rs->next) 278538889Sjdp if (ri->rtype == rs->rtype) 278638889Sjdp { 278738889Sjdp rs->count += ri->count; 278838889Sjdp goto found_reloc; 278938889Sjdp } 279038889Sjdp ri->next = hs->reloc_entries; 279138889Sjdp hs->reloc_entries = ri; 279238889Sjdp found_reloc:; 279338889Sjdp } 279438889Sjdp } 279538889Sjdp hi->reloc_entries = NULL; 279638889Sjdp 279738889Sjdp return true; 279838889Sjdp} 279938889Sjdp 280033965Sjdp/* Is it possible to merge two object file's .got tables? */ 280133965Sjdp 280233965Sjdpstatic boolean 280333965Sjdpelf64_alpha_can_merge_gots (a, b) 280433965Sjdp bfd *a, *b; 280533965Sjdp{ 280633965Sjdp int total = alpha_elf_tdata (a)->total_got_entries; 280760510Sobrien bfd *bsub; 280833965Sjdp 280933965Sjdp /* Trivial quick fallout test. */ 281033965Sjdp if (total + alpha_elf_tdata (b)->total_got_entries <= MAX_GOT_ENTRIES) 281133965Sjdp return true; 281233965Sjdp 281333965Sjdp /* By their nature, local .got entries cannot be merged. */ 281433965Sjdp if ((total += alpha_elf_tdata (b)->n_local_got_entries) > MAX_GOT_ENTRIES) 281533965Sjdp return false; 281633965Sjdp 281733965Sjdp /* Failing the common trivial comparison, we must effectively 281833965Sjdp perform the merge. Not actually performing the merge means that 281933965Sjdp we don't have to store undo information in case we fail. */ 282060510Sobrien for (bsub = b; bsub ; bsub = alpha_elf_tdata (bsub)->in_got_link_next) 282160510Sobrien { 282260510Sobrien struct alpha_elf_link_hash_entry **hashes = alpha_elf_sym_hashes (bsub); 282360510Sobrien Elf_Internal_Shdr *symtab_hdr = &elf_tdata (bsub)->symtab_hdr; 282460510Sobrien int i, n; 282533965Sjdp 282660510Sobrien n = symtab_hdr->sh_size / symtab_hdr->sh_entsize - symtab_hdr->sh_info; 282760510Sobrien for (i = 0; i < n; ++i) 282860510Sobrien { 282960510Sobrien struct alpha_elf_got_entry *ae, *be; 283060510Sobrien struct alpha_elf_link_hash_entry *h; 283138889Sjdp 283260510Sobrien h = hashes[i]; 283360510Sobrien while (h->root.root.type == bfd_link_hash_indirect 283460510Sobrien || h->root.root.type == bfd_link_hash_warning) 283560510Sobrien h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link; 283638889Sjdp 283760510Sobrien for (be = h->got_entries; be ; be = be->next) 283860510Sobrien { 283960510Sobrien if (be->use_count == 0) 284060510Sobrien continue; 284160510Sobrien if (be->gotobj != b) 284260510Sobrien continue; 284333965Sjdp 284460510Sobrien for (ae = h->got_entries; ae ; ae = ae->next) 284560510Sobrien if (ae->gotobj == a && ae->addend == be->addend) 284660510Sobrien goto global_found; 284733965Sjdp 284860510Sobrien if (++total > MAX_GOT_ENTRIES) 284960510Sobrien return false; 285060510Sobrien global_found:; 285160510Sobrien } 285260510Sobrien } 285360510Sobrien } 285433965Sjdp 285533965Sjdp return true; 285633965Sjdp} 285733965Sjdp 285833965Sjdp/* Actually merge two .got tables. */ 285933965Sjdp 286033965Sjdpstatic void 286133965Sjdpelf64_alpha_merge_gots (a, b) 286233965Sjdp bfd *a, *b; 286333965Sjdp{ 286460510Sobrien int total = alpha_elf_tdata (a)->total_got_entries; 286560510Sobrien bfd *bsub; 286633965Sjdp 286733965Sjdp /* Remember local expansion. */ 286833965Sjdp { 286960510Sobrien int e = alpha_elf_tdata (b)->n_local_got_entries; 287033965Sjdp total += e; 287160510Sobrien alpha_elf_tdata (a)->n_local_got_entries += e; 287233965Sjdp } 287333965Sjdp 287460510Sobrien for (bsub = b; bsub ; bsub = alpha_elf_tdata (bsub)->in_got_link_next) 287560510Sobrien { 287660510Sobrien struct alpha_elf_got_entry **local_got_entries; 287760510Sobrien struct alpha_elf_link_hash_entry **hashes; 287860510Sobrien Elf_Internal_Shdr *symtab_hdr; 287960510Sobrien int i, n; 288033965Sjdp 288160510Sobrien /* Let the local .got entries know they are part of a new subsegment. */ 288260510Sobrien local_got_entries = alpha_elf_tdata (bsub)->local_got_entries; 288360510Sobrien if (local_got_entries) 288460510Sobrien { 288560510Sobrien n = elf_tdata (bsub)->symtab_hdr.sh_info; 288660510Sobrien for (i = 0; i < n; ++i) 288760510Sobrien { 288860510Sobrien struct alpha_elf_got_entry *ent; 288960510Sobrien for (ent = local_got_entries[i]; ent; ent = ent->next) 289060510Sobrien ent->gotobj = a; 289160510Sobrien } 289260510Sobrien } 289333965Sjdp 289460510Sobrien /* Merge the global .got entries. */ 289560510Sobrien hashes = alpha_elf_sym_hashes (bsub); 289660510Sobrien symtab_hdr = &elf_tdata (bsub)->symtab_hdr; 289733965Sjdp 289860510Sobrien n = symtab_hdr->sh_size / symtab_hdr->sh_entsize - symtab_hdr->sh_info; 289960510Sobrien for (i = 0; i < n; ++i) 290060510Sobrien { 290160510Sobrien struct alpha_elf_got_entry *ae, *be, **pbe, **start; 290260510Sobrien struct alpha_elf_link_hash_entry *h; 290338889Sjdp 290460510Sobrien h = hashes[i]; 290560510Sobrien while (h->root.root.type == bfd_link_hash_indirect 290660510Sobrien || h->root.root.type == bfd_link_hash_warning) 290760510Sobrien h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link; 290838889Sjdp 290960510Sobrien start = &h->got_entries; 291060510Sobrien for (pbe = start, be = *start; be ; pbe = &be->next, be = be->next) 291160510Sobrien { 291260510Sobrien if (be->use_count == 0) 291360510Sobrien { 291433965Sjdp *pbe = be->next; 291560510Sobrien continue; 291660510Sobrien } 291760510Sobrien if (be->gotobj != b) 291860510Sobrien continue; 291933965Sjdp 292060510Sobrien for (ae = *start; ae ; ae = ae->next) 292160510Sobrien if (ae->gotobj == a && ae->addend == be->addend) 292260510Sobrien { 292360510Sobrien ae->flags |= be->flags; 292460510Sobrien ae->use_count += be->use_count; 292560510Sobrien *pbe = be->next; 292660510Sobrien goto global_found; 292760510Sobrien } 292860510Sobrien be->gotobj = a; 292960510Sobrien total += 1; 293060510Sobrien 293160510Sobrien global_found:; 293260510Sobrien } 293360510Sobrien } 293460510Sobrien 293560510Sobrien alpha_elf_tdata (bsub)->gotobj = a; 293660510Sobrien } 293760510Sobrien alpha_elf_tdata (a)->total_got_entries = total; 293860510Sobrien 293960510Sobrien /* Merge the two in_got chains. */ 294060510Sobrien { 294160510Sobrien bfd *next; 294260510Sobrien 294360510Sobrien bsub = a; 294460510Sobrien while ((next = alpha_elf_tdata (bsub)->in_got_link_next) != NULL) 294560510Sobrien bsub = next; 294660510Sobrien 294760510Sobrien alpha_elf_tdata (bsub)->in_got_link_next = b; 294833965Sjdp } 294933965Sjdp} 295033965Sjdp 295133965Sjdp/* Calculate the offsets for the got entries. */ 295233965Sjdp 295333965Sjdpstatic boolean 295433965Sjdpelf64_alpha_calc_got_offsets_for_symbol (h, arg) 295533965Sjdp struct alpha_elf_link_hash_entry *h; 295633965Sjdp PTR arg; 295733965Sjdp{ 295833965Sjdp struct alpha_elf_got_entry *gotent; 295933965Sjdp 296033965Sjdp for (gotent = h->got_entries; gotent; gotent = gotent->next) 296160510Sobrien if (gotent->use_count > 0) 296260510Sobrien { 296360510Sobrien bfd_size_type *plge 296460510Sobrien = &alpha_elf_tdata (gotent->gotobj)->got->_raw_size; 296533965Sjdp 296660510Sobrien gotent->got_offset = *plge; 296760510Sobrien *plge += 8; 296860510Sobrien } 296960510Sobrien 297033965Sjdp return true; 297133965Sjdp} 297233965Sjdp 297333965Sjdpstatic void 297433965Sjdpelf64_alpha_calc_got_offsets (info) 297533965Sjdp struct bfd_link_info *info; 297633965Sjdp{ 297733965Sjdp bfd *i, *got_list = alpha_elf_hash_table(info)->got_list; 297833965Sjdp 297933965Sjdp /* First, zero out the .got sizes, as we may be recalculating the 298033965Sjdp .got after optimizing it. */ 298133965Sjdp for (i = got_list; i ; i = alpha_elf_tdata(i)->got_link_next) 298233965Sjdp alpha_elf_tdata(i)->got->_raw_size = 0; 298333965Sjdp 298433965Sjdp /* Next, fill in the offsets for all the global entries. */ 298533965Sjdp alpha_elf_link_hash_traverse (alpha_elf_hash_table (info), 298633965Sjdp elf64_alpha_calc_got_offsets_for_symbol, 298733965Sjdp NULL); 298833965Sjdp 298933965Sjdp /* Finally, fill in the offsets for the local entries. */ 299033965Sjdp for (i = got_list; i ; i = alpha_elf_tdata(i)->got_link_next) 299133965Sjdp { 299233965Sjdp bfd_size_type got_offset = alpha_elf_tdata(i)->got->_raw_size; 299333965Sjdp bfd *j; 299433965Sjdp 299533965Sjdp for (j = i; j ; j = alpha_elf_tdata(j)->in_got_link_next) 299633965Sjdp { 299733965Sjdp struct alpha_elf_got_entry **local_got_entries, *gotent; 299833965Sjdp int k, n; 299933965Sjdp 300033965Sjdp local_got_entries = alpha_elf_tdata(j)->local_got_entries; 300133965Sjdp if (!local_got_entries) 300233965Sjdp continue; 300333965Sjdp 300433965Sjdp for (k = 0, n = elf_tdata(j)->symtab_hdr.sh_info; k < n; ++k) 300533965Sjdp for (gotent = local_got_entries[k]; gotent; gotent = gotent->next) 300660510Sobrien if (gotent->use_count > 0) 300760510Sobrien { 300860510Sobrien gotent->got_offset = got_offset; 300960510Sobrien got_offset += 8; 301060510Sobrien } 301133965Sjdp } 301233965Sjdp 301333965Sjdp alpha_elf_tdata(i)->got->_raw_size = got_offset; 301460510Sobrien alpha_elf_tdata(i)->got->_cooked_size = got_offset; 301533965Sjdp } 301633965Sjdp} 301733965Sjdp 301833965Sjdp/* Constructs the gots. */ 301933965Sjdp 302033965Sjdpstatic boolean 302160510Sobrienelf64_alpha_size_got_sections (output_bfd, info) 302233965Sjdp bfd *output_bfd; 302333965Sjdp struct bfd_link_info *info; 302433965Sjdp{ 302560510Sobrien bfd *i, *got_list, *cur_got_obj; 302660510Sobrien int something_changed = 0; 302733965Sjdp 302860510Sobrien got_list = alpha_elf_hash_table (info)->got_list; 302933965Sjdp 303060510Sobrien /* On the first time through, pretend we have an existing got list 303160510Sobrien consisting of all of the input files. */ 303260510Sobrien if (got_list == NULL) 303333965Sjdp { 303460510Sobrien for (i = info->input_bfds; i ; i = i->link_next) 303560510Sobrien { 303660510Sobrien bfd *this_got = alpha_elf_tdata (i)->gotobj; 303760510Sobrien if (this_got == NULL) 303860510Sobrien continue; 303933965Sjdp 304060510Sobrien /* We are assuming no merging has yet ocurred. */ 304160510Sobrien BFD_ASSERT (this_got == i); 304233965Sjdp 304360510Sobrien if (alpha_elf_tdata (this_got)->total_got_entries > MAX_GOT_ENTRIES) 304433965Sjdp { 304560510Sobrien /* Yikes! A single object file has too many entries. */ 304660510Sobrien (*_bfd_error_handler) 304760510Sobrien (_("%s: .got subsegment exceeds 64K (size %d)"), 304860510Sobrien bfd_get_filename (i), 304960510Sobrien alpha_elf_tdata (this_got)->total_got_entries * 8); 305060510Sobrien return false; 305133965Sjdp } 305260510Sobrien 305360510Sobrien if (got_list == NULL) 305460510Sobrien got_list = this_got; 305533965Sjdp else 305660510Sobrien alpha_elf_tdata(cur_got_obj)->got_link_next = this_got; 305760510Sobrien cur_got_obj = this_got; 305833965Sjdp } 305960510Sobrien 306060510Sobrien /* Strange degenerate case of no got references. */ 306160510Sobrien if (got_list == NULL) 306260510Sobrien return true; 306360510Sobrien 306460510Sobrien alpha_elf_hash_table (info)->got_list = got_list; 306560510Sobrien 306660510Sobrien /* Force got offsets to be recalculated. */ 306760510Sobrien something_changed = 1; 306860510Sobrien } 306960510Sobrien 307060510Sobrien cur_got_obj = got_list; 307160510Sobrien i = alpha_elf_tdata(cur_got_obj)->got_link_next; 307260510Sobrien while (i != NULL) 307360510Sobrien { 307460510Sobrien if (elf64_alpha_can_merge_gots (cur_got_obj, i)) 307560510Sobrien { 307660510Sobrien elf64_alpha_merge_gots (cur_got_obj, i); 307760510Sobrien i = alpha_elf_tdata(i)->got_link_next; 307860510Sobrien alpha_elf_tdata(cur_got_obj)->got_link_next = i; 307960510Sobrien something_changed = 1; 308060510Sobrien } 308133965Sjdp else 308233965Sjdp { 308333965Sjdp cur_got_obj = i; 308460510Sobrien i = alpha_elf_tdata(i)->got_link_next; 308533965Sjdp } 308633965Sjdp } 308733965Sjdp 308860510Sobrien /* Once the gots have been merged, fill in the got offsets for 308960510Sobrien everything therein. */ 309060510Sobrien if (1 || something_changed) 309160510Sobrien elf64_alpha_calc_got_offsets (info); 309233965Sjdp 309360510Sobrien return true; 309460510Sobrien} 309533965Sjdp 309660510Sobrienstatic boolean 309760510Sobrienelf64_alpha_always_size_sections (output_bfd, info) 309860510Sobrien bfd *output_bfd; 309960510Sobrien struct bfd_link_info *info; 310060510Sobrien{ 310160510Sobrien bfd *i; 310260510Sobrien 310360510Sobrien if (info->relocateable) 310460510Sobrien return true; 310560510Sobrien 310660510Sobrien /* First, take care of the indirect symbols created by versioning. */ 310760510Sobrien alpha_elf_link_hash_traverse (alpha_elf_hash_table (info), 310860510Sobrien elf64_alpha_merge_ind_symbols, 310960510Sobrien NULL); 311060510Sobrien 311160510Sobrien if (!elf64_alpha_size_got_sections (output_bfd, info)) 311260510Sobrien return false; 311360510Sobrien 311433965Sjdp /* Allocate space for all of the .got subsections. */ 311560510Sobrien i = alpha_elf_hash_table (info)->got_list; 311660510Sobrien for ( ; i ; i = alpha_elf_tdata(i)->got_link_next) 311733965Sjdp { 311833965Sjdp asection *s = alpha_elf_tdata(i)->got; 311933965Sjdp if (s->_raw_size > 0) 312033965Sjdp { 312133965Sjdp s->contents = (bfd_byte *) bfd_zalloc (i, s->_raw_size); 312233965Sjdp if (s->contents == NULL) 312333965Sjdp return false; 312433965Sjdp } 312533965Sjdp } 312633965Sjdp 312733965Sjdp return true; 312833965Sjdp} 312933965Sjdp 313033965Sjdp/* Work out the sizes of the dynamic relocation entries. */ 313133965Sjdp 313233965Sjdpstatic boolean 313333965Sjdpelf64_alpha_calc_dynrel_sizes (h, info) 313433965Sjdp struct alpha_elf_link_hash_entry *h; 313533965Sjdp struct bfd_link_info *info; 313633965Sjdp{ 313733965Sjdp /* If the symbol was defined as a common symbol in a regular object 313833965Sjdp file, and there was no definition in any dynamic object, then the 313933965Sjdp linker will have allocated space for the symbol in a common 314033965Sjdp section but the ELF_LINK_HASH_DEF_REGULAR flag will not have been 314133965Sjdp set. This is done for dynamic symbols in 314233965Sjdp elf_adjust_dynamic_symbol but this is not done for non-dynamic 314333965Sjdp symbols, somehow. */ 314433965Sjdp if (((h->root.elf_link_hash_flags 314533965Sjdp & (ELF_LINK_HASH_DEF_REGULAR 314633965Sjdp | ELF_LINK_HASH_REF_REGULAR 314733965Sjdp | ELF_LINK_HASH_DEF_DYNAMIC)) 314833965Sjdp == ELF_LINK_HASH_REF_REGULAR) 314933965Sjdp && (h->root.root.type == bfd_link_hash_defined 315033965Sjdp || h->root.root.type == bfd_link_hash_defweak) 315133965Sjdp && !(h->root.root.u.def.section->owner->flags & DYNAMIC)) 315233965Sjdp { 315333965Sjdp h->root.elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR; 315433965Sjdp } 315533965Sjdp 315633965Sjdp /* If the symbol is dynamic, we'll need all the relocations in their 315760510Sobrien natural form. If this is a shared object, and it has been forced 315860510Sobrien local, we'll need the same number of RELATIVE relocations. */ 315960510Sobrien 316060510Sobrien if (alpha_elf_dynamic_symbol_p (&h->root, info) || info->shared) 316133965Sjdp { 316233965Sjdp struct alpha_elf_reloc_entry *relent; 316348850Sdfr bfd *dynobj; 316448850Sdfr struct alpha_elf_got_entry *gotent; 316548850Sdfr bfd_size_type count; 316648850Sdfr asection *srel; 316733965Sjdp 316833965Sjdp for (relent = h->reloc_entries; relent; relent = relent->next) 316960510Sobrien if (relent->rtype == R_ALPHA_REFLONG 317060510Sobrien || relent->rtype == R_ALPHA_REFQUAD) 317160510Sobrien { 317260510Sobrien relent->srel->_raw_size += 317377303Sobrien sizeof (Elf64_External_Rela) * relent->count; 317460510Sobrien } 317533965Sjdp 317648850Sdfr dynobj = elf_hash_table(info)->dynobj; 317748850Sdfr count = 0; 317848850Sdfr 317948850Sdfr for (gotent = h->got_entries; gotent ; gotent = gotent->next) 318048850Sdfr count++; 318148850Sdfr 318248850Sdfr /* If we are using a .plt entry, subtract one, as the first 318348850Sdfr reference uses a .rela.plt entry instead. */ 318460510Sobrien if (h->root.plt.offset != MINUS_ONE) 318548850Sdfr count--; 318648850Sdfr 318748850Sdfr if (count > 0) 318833965Sjdp { 318948850Sdfr srel = bfd_get_section_by_name (dynobj, ".rela.got"); 319048850Sdfr BFD_ASSERT (srel != NULL); 319148850Sdfr srel->_raw_size += sizeof (Elf64_External_Rela) * count; 319233965Sjdp } 319333965Sjdp } 319448850Sdfr 319533965Sjdp return true; 319633965Sjdp} 319733965Sjdp 319833965Sjdp/* Set the sizes of the dynamic sections. */ 319933965Sjdp 320033965Sjdpstatic boolean 320133965Sjdpelf64_alpha_size_dynamic_sections (output_bfd, info) 320233965Sjdp bfd *output_bfd; 320333965Sjdp struct bfd_link_info *info; 320433965Sjdp{ 320533965Sjdp bfd *dynobj; 320633965Sjdp asection *s; 320733965Sjdp boolean reltext; 320833965Sjdp boolean relplt; 320933965Sjdp 321033965Sjdp dynobj = elf_hash_table(info)->dynobj; 321133965Sjdp BFD_ASSERT(dynobj != NULL); 321233965Sjdp 321333965Sjdp if (elf_hash_table (info)->dynamic_sections_created) 321433965Sjdp { 321533965Sjdp /* Set the contents of the .interp section to the interpreter. */ 321633965Sjdp if (!info->shared) 321733965Sjdp { 321833965Sjdp s = bfd_get_section_by_name (dynobj, ".interp"); 321933965Sjdp BFD_ASSERT (s != NULL); 322033965Sjdp s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER; 322133965Sjdp s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER; 322233965Sjdp } 322333965Sjdp 322433965Sjdp /* Now that we've seen all of the input files, we can decide which 322533965Sjdp symbols need dynamic relocation entries and which don't. We've 322633965Sjdp collected information in check_relocs that we can now apply to 322733965Sjdp size the dynamic relocation sections. */ 322833965Sjdp alpha_elf_link_hash_traverse (alpha_elf_hash_table (info), 322933965Sjdp elf64_alpha_calc_dynrel_sizes, 323033965Sjdp info); 323133965Sjdp 323233965Sjdp /* When building shared libraries, each local .got entry needs a 323333965Sjdp RELATIVE reloc. */ 323433965Sjdp if (info->shared) 323533965Sjdp { 323633965Sjdp bfd *i; 323733965Sjdp asection *srel; 323833965Sjdp bfd_size_type count; 323933965Sjdp 324033965Sjdp srel = bfd_get_section_by_name (dynobj, ".rela.got"); 324133965Sjdp BFD_ASSERT (srel != NULL); 324233965Sjdp 324333965Sjdp for (i = alpha_elf_hash_table(info)->got_list, count = 0; 324433965Sjdp i != NULL; 324533965Sjdp i = alpha_elf_tdata(i)->got_link_next) 324633965Sjdp count += alpha_elf_tdata(i)->n_local_got_entries; 324733965Sjdp 324877303Sobrien srel->_raw_size += count * sizeof (Elf64_External_Rela); 324933965Sjdp } 325033965Sjdp } 325133965Sjdp /* else we're not dynamic and by definition we don't need such things. */ 325233965Sjdp 325333965Sjdp /* The check_relocs and adjust_dynamic_symbol entry points have 325433965Sjdp determined the sizes of the various dynamic sections. Allocate 325533965Sjdp memory for them. */ 325633965Sjdp reltext = false; 325733965Sjdp relplt = false; 325833965Sjdp for (s = dynobj->sections; s != NULL; s = s->next) 325933965Sjdp { 326033965Sjdp const char *name; 326133965Sjdp boolean strip; 326233965Sjdp 326333965Sjdp if (!(s->flags & SEC_LINKER_CREATED)) 326433965Sjdp continue; 326533965Sjdp 326633965Sjdp /* It's OK to base decisions on the section name, because none 326733965Sjdp of the dynobj section names depend upon the input files. */ 326833965Sjdp name = bfd_get_section_name (dynobj, s); 326933965Sjdp 327033965Sjdp /* If we don't need this section, strip it from the output file. 327133965Sjdp This is to handle .rela.bss and .rela.plt. We must create it 327233965Sjdp in create_dynamic_sections, because it must be created before 327333965Sjdp the linker maps input sections to output sections. The 327433965Sjdp linker does that before adjust_dynamic_symbol is called, and 327533965Sjdp it is that function which decides whether anything needs to 327633965Sjdp go into these sections. */ 327733965Sjdp 327833965Sjdp strip = false; 327933965Sjdp 328033965Sjdp if (strncmp (name, ".rela", 5) == 0) 328133965Sjdp { 328233965Sjdp strip = (s->_raw_size == 0); 328333965Sjdp 328433965Sjdp if (!strip) 328533965Sjdp { 328633965Sjdp const char *outname; 328733965Sjdp asection *target; 328833965Sjdp 328933965Sjdp /* If this relocation section applies to a read only 329033965Sjdp section, then we probably need a DT_TEXTREL entry. */ 329133965Sjdp outname = bfd_get_section_name (output_bfd, 329233965Sjdp s->output_section); 329333965Sjdp target = bfd_get_section_by_name (output_bfd, outname + 5); 329433965Sjdp if (target != NULL 329538889Sjdp && (target->flags & SEC_READONLY) != 0 329638889Sjdp && (target->flags & SEC_ALLOC) != 0) 329733965Sjdp reltext = true; 329833965Sjdp 329933965Sjdp if (strcmp(name, ".rela.plt") == 0) 330033965Sjdp relplt = true; 330133965Sjdp 330233965Sjdp /* We use the reloc_count field as a counter if we need 330333965Sjdp to copy relocs into the output file. */ 330433965Sjdp s->reloc_count = 0; 330533965Sjdp } 330633965Sjdp } 330733965Sjdp else if (strcmp (name, ".plt") != 0) 330833965Sjdp { 330933965Sjdp /* It's not one of our dynamic sections, so don't allocate space. */ 331033965Sjdp continue; 331133965Sjdp } 331233965Sjdp 331333965Sjdp if (strip) 331460510Sobrien _bfd_strip_section_from_output (info, s); 331533965Sjdp else 331633965Sjdp { 331733965Sjdp /* Allocate memory for the section contents. */ 331833965Sjdp s->contents = (bfd_byte *) bfd_zalloc(dynobj, s->_raw_size); 331933965Sjdp if (s->contents == NULL && s->_raw_size != 0) 332033965Sjdp return false; 332133965Sjdp } 332233965Sjdp } 332333965Sjdp 332433965Sjdp if (elf_hash_table (info)->dynamic_sections_created) 332533965Sjdp { 332633965Sjdp /* Add some entries to the .dynamic section. We fill in the 332733965Sjdp values later, in elf64_alpha_finish_dynamic_sections, but we 332833965Sjdp must add the entries now so that we get the correct size for 332933965Sjdp the .dynamic section. The DT_DEBUG entry is filled in by the 333033965Sjdp dynamic linker and used by the debugger. */ 333133965Sjdp if (!info->shared) 333233965Sjdp { 333333965Sjdp if (!bfd_elf64_add_dynamic_entry (info, DT_DEBUG, 0)) 333433965Sjdp return false; 333533965Sjdp } 333633965Sjdp 333733965Sjdp if (! bfd_elf64_add_dynamic_entry (info, DT_PLTGOT, 0)) 333833965Sjdp return false; 333933965Sjdp 334033965Sjdp if (relplt) 334133965Sjdp { 334233965Sjdp if (! bfd_elf64_add_dynamic_entry (info, DT_PLTRELSZ, 0) 334333965Sjdp || ! bfd_elf64_add_dynamic_entry (info, DT_PLTREL, DT_RELA) 334433965Sjdp || ! bfd_elf64_add_dynamic_entry (info, DT_JMPREL, 0)) 334533965Sjdp return false; 334633965Sjdp } 334733965Sjdp 334833965Sjdp if (! bfd_elf64_add_dynamic_entry (info, DT_RELA, 0) 334933965Sjdp || ! bfd_elf64_add_dynamic_entry (info, DT_RELASZ, 0) 335033965Sjdp || ! bfd_elf64_add_dynamic_entry (info, DT_RELAENT, 335177303Sobrien sizeof (Elf64_External_Rela))) 335233965Sjdp return false; 335333965Sjdp 335433965Sjdp if (reltext) 335533965Sjdp { 335633965Sjdp if (! bfd_elf64_add_dynamic_entry (info, DT_TEXTREL, 0)) 335733965Sjdp return false; 335877303Sobrien info->flags |= DF_TEXTREL; 335933965Sjdp } 336033965Sjdp } 336133965Sjdp 336233965Sjdp return true; 336333965Sjdp} 336433965Sjdp 336533965Sjdp/* Relocate an Alpha ELF section. */ 336633965Sjdp 336733965Sjdpstatic boolean 336833965Sjdpelf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section, 336933965Sjdp contents, relocs, local_syms, local_sections) 337033965Sjdp bfd *output_bfd; 337133965Sjdp struct bfd_link_info *info; 337233965Sjdp bfd *input_bfd; 337333965Sjdp asection *input_section; 337433965Sjdp bfd_byte *contents; 337533965Sjdp Elf_Internal_Rela *relocs; 337633965Sjdp Elf_Internal_Sym *local_syms; 337733965Sjdp asection **local_sections; 337833965Sjdp{ 337933965Sjdp Elf_Internal_Shdr *symtab_hdr; 338033965Sjdp Elf_Internal_Rela *rel; 338133965Sjdp Elf_Internal_Rela *relend; 338233965Sjdp asection *sec, *sgot, *srel, *srelgot; 338333965Sjdp bfd *dynobj, *gotobj; 338433965Sjdp bfd_vma gp; 338533965Sjdp 338633965Sjdp srelgot = srel = NULL; 338733965Sjdp symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; 338833965Sjdp dynobj = elf_hash_table (info)->dynobj; 338933965Sjdp if (dynobj) 339033965Sjdp { 339133965Sjdp srelgot = bfd_get_section_by_name (dynobj, ".rela.got"); 339233965Sjdp } 339333965Sjdp 339433965Sjdp /* Find the gp value for this input bfd. */ 339533965Sjdp sgot = NULL; 339633965Sjdp gp = 0; 339733965Sjdp gotobj = alpha_elf_tdata (input_bfd)->gotobj; 339833965Sjdp if (gotobj) 339933965Sjdp { 340033965Sjdp sgot = alpha_elf_tdata (gotobj)->got; 340133965Sjdp gp = _bfd_get_gp_value (gotobj); 340233965Sjdp if (gp == 0) 340333965Sjdp { 340433965Sjdp gp = (sgot->output_section->vma 340533965Sjdp + sgot->output_offset 340633965Sjdp + 0x8000); 340733965Sjdp _bfd_set_gp_value (gotobj, gp); 340833965Sjdp } 340933965Sjdp } 341033965Sjdp 341133965Sjdp rel = relocs; 341233965Sjdp relend = relocs + input_section->reloc_count; 341333965Sjdp for (; rel < relend; rel++) 341433965Sjdp { 341533965Sjdp int r_type; 341633965Sjdp reloc_howto_type *howto; 341733965Sjdp unsigned long r_symndx; 341833965Sjdp struct alpha_elf_link_hash_entry *h; 341933965Sjdp Elf_Internal_Sym *sym; 342033965Sjdp bfd_vma relocation; 342133965Sjdp bfd_vma addend; 342233965Sjdp bfd_reloc_status_type r; 342333965Sjdp 342433965Sjdp r_type = ELF64_R_TYPE(rel->r_info); 342533965Sjdp if (r_type < 0 || r_type >= (int) R_ALPHA_max) 342633965Sjdp { 342733965Sjdp bfd_set_error (bfd_error_bad_value); 342833965Sjdp return false; 342933965Sjdp } 343033965Sjdp howto = elf64_alpha_howto_table + r_type; 343133965Sjdp 343233965Sjdp r_symndx = ELF64_R_SYM(rel->r_info); 343333965Sjdp 343433965Sjdp if (info->relocateable) 343533965Sjdp { 343633965Sjdp /* This is a relocateable link. We don't have to change 343733965Sjdp anything, unless the reloc is against a section symbol, 343833965Sjdp in which case we have to adjust according to where the 343933965Sjdp section symbol winds up in the output section. */ 344060510Sobrien 344177303Sobrien /* The symbol associated with GPDISP and LITUSE is 344260510Sobrien immaterial. Only the addend is significant. */ 344360510Sobrien if (r_type == R_ALPHA_GPDISP || r_type == R_ALPHA_LITUSE) 344460510Sobrien continue; 344560510Sobrien 344633965Sjdp if (r_symndx < symtab_hdr->sh_info) 344733965Sjdp { 344833965Sjdp sym = local_syms + r_symndx; 344933965Sjdp if (ELF_ST_TYPE(sym->st_info) == STT_SECTION) 345033965Sjdp { 345133965Sjdp sec = local_sections[r_symndx]; 345233965Sjdp rel->r_addend += sec->output_offset + sym->st_value; 345333965Sjdp } 345433965Sjdp } 345533965Sjdp 345633965Sjdp continue; 345733965Sjdp } 345833965Sjdp 345933965Sjdp /* This is a final link. */ 346033965Sjdp 346133965Sjdp h = NULL; 346233965Sjdp sym = NULL; 346333965Sjdp sec = NULL; 346433965Sjdp 346533965Sjdp if (r_symndx < symtab_hdr->sh_info) 346633965Sjdp { 346733965Sjdp sym = local_syms + r_symndx; 346833965Sjdp sec = local_sections[r_symndx]; 346933965Sjdp relocation = (sec->output_section->vma 347033965Sjdp + sec->output_offset 347133965Sjdp + sym->st_value); 347233965Sjdp } 347333965Sjdp else 347433965Sjdp { 347533965Sjdp h = alpha_elf_sym_hashes (input_bfd)[r_symndx - symtab_hdr->sh_info]; 347633965Sjdp 347733965Sjdp while (h->root.root.type == bfd_link_hash_indirect 347833965Sjdp || h->root.root.type == bfd_link_hash_warning) 347933965Sjdp h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link; 348033965Sjdp 348133965Sjdp if (h->root.root.type == bfd_link_hash_defined 348233965Sjdp || h->root.root.type == bfd_link_hash_defweak) 348333965Sjdp { 348433965Sjdp sec = h->root.root.u.def.section; 348533965Sjdp 348633965Sjdp#if rth_notdef 348733965Sjdp if ((r_type == R_ALPHA_LITERAL 348833965Sjdp && elf_hash_table(info)->dynamic_sections_created 348933965Sjdp && (!info->shared 349033965Sjdp || !info->symbolic 349133965Sjdp || !(h->root.elf_link_hash_flags 349233965Sjdp & ELF_LINK_HASH_DEF_REGULAR))) 349333965Sjdp || (info->shared 349433965Sjdp && (!info->symbolic 349533965Sjdp || !(h->root.elf_link_hash_flags 349633965Sjdp & ELF_LINK_HASH_DEF_REGULAR)) 349733965Sjdp && (input_section->flags & SEC_ALLOC) 349833965Sjdp && (r_type == R_ALPHA_REFLONG 349933965Sjdp || r_type == R_ALPHA_REFQUAD 350033965Sjdp || r_type == R_ALPHA_LITERAL))) 350133965Sjdp { 350233965Sjdp /* In these cases, we don't need the relocation value. 350333965Sjdp We check specially because in some obscure cases 350433965Sjdp sec->output_section will be NULL. */ 350533965Sjdp relocation = 0; 350633965Sjdp } 350733965Sjdp#else 350833965Sjdp /* FIXME: Are not these obscure cases simply bugs? Let's 350933965Sjdp get something working and come back to this. */ 351033965Sjdp if (sec->output_section == NULL) 351133965Sjdp relocation = 0; 351233965Sjdp#endif /* rth_notdef */ 351333965Sjdp else 351433965Sjdp { 351533965Sjdp relocation = (h->root.root.u.def.value 351633965Sjdp + sec->output_section->vma 351733965Sjdp + sec->output_offset); 351833965Sjdp } 351933965Sjdp } 352033965Sjdp else if (h->root.root.type == bfd_link_hash_undefweak) 352133965Sjdp relocation = 0; 352268770Sobrien else if (info->shared && !info->symbolic 352368770Sobrien && !info->no_undefined 352468770Sobrien && ELF_ST_VISIBILITY (h->root.other) == STV_DEFAULT) 352533965Sjdp relocation = 0; 352633965Sjdp else 352733965Sjdp { 352833965Sjdp if (!((*info->callbacks->undefined_symbol) 352933965Sjdp (info, h->root.root.root.string, input_bfd, 353060510Sobrien input_section, rel->r_offset, 353168770Sobrien (!info->shared || info->no_undefined 353268770Sobrien || ELF_ST_VISIBILITY (h->root.other))))) 353333965Sjdp return false; 353433965Sjdp relocation = 0; 353533965Sjdp } 353633965Sjdp } 353733965Sjdp addend = rel->r_addend; 353833965Sjdp 353933965Sjdp switch (r_type) 354033965Sjdp { 354133965Sjdp case R_ALPHA_GPDISP: 354233965Sjdp { 354333965Sjdp bfd_byte *p_ldah, *p_lda; 354433965Sjdp 354533965Sjdp BFD_ASSERT(gp != 0); 354633965Sjdp 354733965Sjdp relocation = (input_section->output_section->vma 354833965Sjdp + input_section->output_offset 354933965Sjdp + rel->r_offset); 355033965Sjdp 355133965Sjdp p_ldah = contents + rel->r_offset - input_section->vma; 355233965Sjdp p_lda = p_ldah + rel->r_addend; 355333965Sjdp 355433965Sjdp r = elf64_alpha_do_reloc_gpdisp (input_bfd, gp - relocation, 355533965Sjdp p_ldah, p_lda); 355633965Sjdp } 355733965Sjdp break; 355833965Sjdp 355933965Sjdp case R_ALPHA_OP_PUSH: 356033965Sjdp case R_ALPHA_OP_STORE: 356133965Sjdp case R_ALPHA_OP_PSUB: 356233965Sjdp case R_ALPHA_OP_PRSHIFT: 356333965Sjdp /* We hate these silly beasts. */ 356477303Sobrien abort (); 356533965Sjdp 356633965Sjdp case R_ALPHA_LITERAL: 356733965Sjdp { 356833965Sjdp struct alpha_elf_got_entry *gotent; 356960510Sobrien boolean dynamic_symbol; 357033965Sjdp 357133965Sjdp BFD_ASSERT(sgot != NULL); 357233965Sjdp BFD_ASSERT(gp != 0); 357333965Sjdp 357433965Sjdp if (h != NULL) 357533965Sjdp { 357633965Sjdp gotent = h->got_entries; 357760510Sobrien dynamic_symbol = alpha_elf_dynamic_symbol_p (&h->root, info); 357833965Sjdp } 357933965Sjdp else 358033965Sjdp { 358133965Sjdp gotent = (alpha_elf_tdata(input_bfd)-> 358233965Sjdp local_got_entries[r_symndx]); 358360510Sobrien dynamic_symbol = false; 358460510Sobrien } 358533965Sjdp 358660510Sobrien BFD_ASSERT(gotent != NULL); 358733965Sjdp 358860510Sobrien while (gotent->gotobj != gotobj || gotent->addend != addend) 358960510Sobrien gotent = gotent->next; 359033965Sjdp 359160510Sobrien BFD_ASSERT(gotent->use_count >= 1); 359233965Sjdp 359360510Sobrien /* Initialize the .got entry's value. */ 359460510Sobrien if (!(gotent->flags & ALPHA_ELF_GOT_ENTRY_RELOCS_DONE)) 359560510Sobrien { 359660510Sobrien bfd_put_64 (output_bfd, relocation+addend, 359760510Sobrien sgot->contents + gotent->got_offset); 359833965Sjdp 359960510Sobrien /* If the symbol has been forced local, output a 360060510Sobrien RELATIVE reloc, otherwise it will be handled in 360160510Sobrien finish_dynamic_symbol. */ 360260510Sobrien if (info->shared && !dynamic_symbol) 360360510Sobrien { 360460510Sobrien Elf_Internal_Rela outrel; 360533965Sjdp 360660510Sobrien BFD_ASSERT(srelgot != NULL); 360760510Sobrien 360860510Sobrien outrel.r_offset = (sgot->output_section->vma 360960510Sobrien + sgot->output_offset 361060510Sobrien + gotent->got_offset); 361160510Sobrien outrel.r_info = ELF64_R_INFO(0, R_ALPHA_RELATIVE); 361260510Sobrien outrel.r_addend = 0; 361360510Sobrien 361460510Sobrien bfd_elf64_swap_reloca_out (output_bfd, &outrel, 361560510Sobrien ((Elf64_External_Rela *) 361660510Sobrien srelgot->contents) 361760510Sobrien + srelgot->reloc_count++); 361877303Sobrien BFD_ASSERT (sizeof (Elf64_External_Rela) 361960510Sobrien * srelgot->reloc_count 362060510Sobrien <= srelgot->_cooked_size); 362133965Sjdp } 362260510Sobrien 362360510Sobrien gotent->flags |= ALPHA_ELF_GOT_ENTRY_RELOCS_DONE; 362433965Sjdp } 362533965Sjdp 362633965Sjdp /* Figure the gprel relocation. */ 362733965Sjdp addend = 0; 362833965Sjdp relocation = (sgot->output_section->vma 362933965Sjdp + sgot->output_offset 363033965Sjdp + gotent->got_offset); 363133965Sjdp relocation -= gp; 363233965Sjdp } 363333965Sjdp /* overflow handled by _bfd_final_link_relocate */ 363433965Sjdp goto default_reloc; 363533965Sjdp 363633965Sjdp case R_ALPHA_GPREL32: 363760510Sobrien case R_ALPHA_GPRELLOW: 363833965Sjdp BFD_ASSERT(gp != 0); 363933965Sjdp relocation -= gp; 364033965Sjdp goto default_reloc; 364133965Sjdp 364260510Sobrien case R_ALPHA_GPRELHIGH: 364360510Sobrien BFD_ASSERT(gp != 0); 364460510Sobrien relocation -= gp; 364560510Sobrien relocation += addend; 364660510Sobrien addend = 0; 364760510Sobrien relocation = (((bfd_signed_vma) relocation >> 16) 364860510Sobrien + ((relocation >> 15) & 1)); 364960510Sobrien goto default_reloc; 365060510Sobrien 365133965Sjdp case R_ALPHA_BRADDR: 365233965Sjdp case R_ALPHA_HINT: 365333965Sjdp /* The regular PC-relative stuff measures from the start of 365433965Sjdp the instruction rather than the end. */ 365533965Sjdp addend -= 4; 365633965Sjdp goto default_reloc; 365733965Sjdp 365833965Sjdp case R_ALPHA_REFLONG: 365933965Sjdp case R_ALPHA_REFQUAD: 366033965Sjdp { 366133965Sjdp Elf_Internal_Rela outrel; 366233965Sjdp boolean skip; 366333965Sjdp 366433965Sjdp /* Careful here to remember RELATIVE relocations for global 366533965Sjdp variables for symbolic shared objects. */ 366633965Sjdp 366733965Sjdp if (h && alpha_elf_dynamic_symbol_p (&h->root, info)) 366833965Sjdp { 366933965Sjdp BFD_ASSERT(h->root.dynindx != -1); 367033965Sjdp outrel.r_info = ELF64_R_INFO(h->root.dynindx, r_type); 367133965Sjdp outrel.r_addend = addend; 367233965Sjdp addend = 0, relocation = 0; 367333965Sjdp } 367460510Sobrien else if (info->shared && (input_section->flags & SEC_ALLOC)) 367533965Sjdp { 367633965Sjdp outrel.r_info = ELF64_R_INFO(0, R_ALPHA_RELATIVE); 367733965Sjdp outrel.r_addend = 0; 367833965Sjdp } 367933965Sjdp else 368033965Sjdp goto default_reloc; 368133965Sjdp 368233965Sjdp if (!srel) 368333965Sjdp { 368433965Sjdp const char *name; 368533965Sjdp 368633965Sjdp name = (bfd_elf_string_from_elf_section 368733965Sjdp (input_bfd, elf_elfheader(input_bfd)->e_shstrndx, 368833965Sjdp elf_section_data(input_section)->rel_hdr.sh_name)); 368933965Sjdp BFD_ASSERT(name != NULL); 369033965Sjdp 369133965Sjdp srel = bfd_get_section_by_name (dynobj, name); 369233965Sjdp BFD_ASSERT(srel != NULL); 369333965Sjdp } 369433965Sjdp 369533965Sjdp skip = false; 369633965Sjdp 369733965Sjdp if (elf_section_data (input_section)->stab_info == NULL) 369833965Sjdp outrel.r_offset = rel->r_offset; 369933965Sjdp else 370033965Sjdp { 370133965Sjdp bfd_vma off; 370233965Sjdp 370333965Sjdp off = (_bfd_stab_section_offset 370433965Sjdp (output_bfd, &elf_hash_table (info)->stab_info, 370533965Sjdp input_section, 370633965Sjdp &elf_section_data (input_section)->stab_info, 370733965Sjdp rel->r_offset)); 370833965Sjdp if (off == (bfd_vma) -1) 370933965Sjdp skip = true; 371033965Sjdp outrel.r_offset = off; 371133965Sjdp } 371233965Sjdp 371333965Sjdp if (! skip) 371433965Sjdp outrel.r_offset += (input_section->output_section->vma 371533965Sjdp + input_section->output_offset); 371633965Sjdp else 371733965Sjdp memset (&outrel, 0, sizeof outrel); 371833965Sjdp 371933965Sjdp bfd_elf64_swap_reloca_out (output_bfd, &outrel, 372033965Sjdp ((Elf64_External_Rela *) 372133965Sjdp srel->contents) 372233965Sjdp + srel->reloc_count++); 372377303Sobrien BFD_ASSERT (sizeof (Elf64_External_Rela) * srel->reloc_count 372448850Sdfr <= srel->_cooked_size); 372533965Sjdp } 372633965Sjdp goto default_reloc; 372733965Sjdp 372833965Sjdp default: 372933965Sjdp default_reloc: 373033965Sjdp r = _bfd_final_link_relocate (howto, input_bfd, input_section, 373133965Sjdp contents, rel->r_offset, relocation, 373233965Sjdp addend); 373333965Sjdp break; 373433965Sjdp } 373533965Sjdp 373633965Sjdp switch (r) 373733965Sjdp { 373833965Sjdp case bfd_reloc_ok: 373933965Sjdp break; 374033965Sjdp 374133965Sjdp case bfd_reloc_overflow: 374233965Sjdp { 374333965Sjdp const char *name; 374433965Sjdp 374533965Sjdp if (h != NULL) 374633965Sjdp name = h->root.root.root.string; 374733965Sjdp else 374833965Sjdp { 374933965Sjdp name = (bfd_elf_string_from_elf_section 375033965Sjdp (input_bfd, symtab_hdr->sh_link, sym->st_name)); 375133965Sjdp if (name == NULL) 375233965Sjdp return false; 375333965Sjdp if (*name == '\0') 375433965Sjdp name = bfd_section_name (input_bfd, sec); 375533965Sjdp } 375633965Sjdp if (! ((*info->callbacks->reloc_overflow) 375733965Sjdp (info, name, howto->name, (bfd_vma) 0, 375833965Sjdp input_bfd, input_section, rel->r_offset))) 375933965Sjdp return false; 376033965Sjdp } 376133965Sjdp break; 376233965Sjdp 376333965Sjdp default: 376433965Sjdp case bfd_reloc_outofrange: 376533965Sjdp abort (); 376633965Sjdp } 376733965Sjdp } 376833965Sjdp 376933965Sjdp return true; 377033965Sjdp} 377133965Sjdp 377233965Sjdp/* Finish up dynamic symbol handling. We set the contents of various 377333965Sjdp dynamic sections here. */ 377433965Sjdp 377533965Sjdpstatic boolean 377633965Sjdpelf64_alpha_finish_dynamic_symbol (output_bfd, info, h, sym) 377733965Sjdp bfd *output_bfd; 377833965Sjdp struct bfd_link_info *info; 377933965Sjdp struct elf_link_hash_entry *h; 378033965Sjdp Elf_Internal_Sym *sym; 378133965Sjdp{ 378233965Sjdp bfd *dynobj = elf_hash_table(info)->dynobj; 378333965Sjdp 378460510Sobrien if (h->plt.offset != MINUS_ONE) 378533965Sjdp { 378633965Sjdp /* Fill in the .plt entry for this symbol. */ 378733965Sjdp asection *splt, *sgot, *srel; 378833965Sjdp Elf_Internal_Rela outrel; 378933965Sjdp bfd_vma got_addr, plt_addr; 379033965Sjdp bfd_vma plt_index; 379133965Sjdp struct alpha_elf_got_entry *gotent; 379233965Sjdp 379333965Sjdp BFD_ASSERT (h->dynindx != -1); 379433965Sjdp 379533965Sjdp /* The first .got entry will be updated by the .plt with the 379633965Sjdp address of the target function. */ 379733965Sjdp gotent = ((struct alpha_elf_link_hash_entry *) h)->got_entries; 379833965Sjdp BFD_ASSERT (gotent && gotent->addend == 0); 379933965Sjdp 380033965Sjdp splt = bfd_get_section_by_name (dynobj, ".plt"); 380133965Sjdp BFD_ASSERT (splt != NULL); 380233965Sjdp srel = bfd_get_section_by_name (dynobj, ".rela.plt"); 380333965Sjdp BFD_ASSERT (srel != NULL); 380433965Sjdp sgot = alpha_elf_tdata (gotent->gotobj)->got; 380533965Sjdp BFD_ASSERT (sgot != NULL); 380633965Sjdp 380733965Sjdp got_addr = (sgot->output_section->vma 380833965Sjdp + sgot->output_offset 380933965Sjdp + gotent->got_offset); 381033965Sjdp plt_addr = (splt->output_section->vma 381133965Sjdp + splt->output_offset 381260510Sobrien + h->plt.offset); 381333965Sjdp 381460510Sobrien plt_index = (h->plt.offset - PLT_HEADER_SIZE) / PLT_ENTRY_SIZE; 381533965Sjdp 381633965Sjdp /* Fill in the entry in the procedure linkage table. */ 381733965Sjdp { 381833965Sjdp unsigned insn1, insn2, insn3; 381933965Sjdp 382060510Sobrien insn1 = PLT_ENTRY_WORD1 | ((-(h->plt.offset + 4) >> 2) & 0x1fffff); 382138889Sjdp insn2 = PLT_ENTRY_WORD2; 382238889Sjdp insn3 = PLT_ENTRY_WORD3; 382333965Sjdp 382460510Sobrien bfd_put_32 (output_bfd, insn1, splt->contents + h->plt.offset); 382560510Sobrien bfd_put_32 (output_bfd, insn2, splt->contents + h->plt.offset + 4); 382660510Sobrien bfd_put_32 (output_bfd, insn3, splt->contents + h->plt.offset + 8); 382733965Sjdp } 382833965Sjdp 382933965Sjdp /* Fill in the entry in the .rela.plt section. */ 383033965Sjdp outrel.r_offset = got_addr; 383133965Sjdp outrel.r_info = ELF64_R_INFO(h->dynindx, R_ALPHA_JMP_SLOT); 383233965Sjdp outrel.r_addend = 0; 383333965Sjdp 383433965Sjdp bfd_elf64_swap_reloca_out (output_bfd, &outrel, 383533965Sjdp ((Elf64_External_Rela *)srel->contents 383633965Sjdp + plt_index)); 383733965Sjdp 383833965Sjdp if (!(h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)) 383933965Sjdp { 384033965Sjdp /* Mark the symbol as undefined, rather than as defined in the 384133965Sjdp .plt section. Leave the value alone. */ 384233965Sjdp sym->st_shndx = SHN_UNDEF; 384333965Sjdp } 384433965Sjdp 384533965Sjdp /* Fill in the entries in the .got. */ 384633965Sjdp bfd_put_64 (output_bfd, plt_addr, sgot->contents + gotent->got_offset); 384733965Sjdp 384833965Sjdp /* Subsequent .got entries will continue to bounce through the .plt. */ 384948850Sdfr if (gotent->next) 385033965Sjdp { 385148850Sdfr srel = bfd_get_section_by_name (dynobj, ".rela.got"); 385248850Sdfr BFD_ASSERT (! info->shared || srel != NULL); 385333965Sjdp 385448850Sdfr gotent = gotent->next; 385548850Sdfr do 385648850Sdfr { 385748850Sdfr sgot = alpha_elf_tdata(gotent->gotobj)->got; 385848850Sdfr BFD_ASSERT(sgot != NULL); 385948850Sdfr BFD_ASSERT(gotent->addend == 0); 386048850Sdfr 386148850Sdfr bfd_put_64 (output_bfd, plt_addr, 386248850Sdfr sgot->contents + gotent->got_offset); 386348850Sdfr 386448850Sdfr if (info->shared) 386548850Sdfr { 386648850Sdfr outrel.r_offset = (sgot->output_section->vma 386748850Sdfr + sgot->output_offset 386848850Sdfr + gotent->got_offset); 386948850Sdfr outrel.r_info = ELF64_R_INFO(0, R_ALPHA_RELATIVE); 387048850Sdfr outrel.r_addend = 0; 387148850Sdfr 387248850Sdfr bfd_elf64_swap_reloca_out (output_bfd, &outrel, 387348850Sdfr ((Elf64_External_Rela *) 387448850Sdfr srel->contents) 387548850Sdfr + srel->reloc_count++); 387677303Sobrien BFD_ASSERT (sizeof (Elf64_External_Rela) * srel->reloc_count 387748850Sdfr <= srel->_cooked_size); 387848850Sdfr } 387948850Sdfr 388048850Sdfr gotent = gotent->next; 388148850Sdfr } 388248850Sdfr while (gotent != NULL); 388333965Sjdp } 388433965Sjdp } 388533965Sjdp else if (alpha_elf_dynamic_symbol_p (h, info)) 388633965Sjdp { 388733965Sjdp /* Fill in the dynamic relocations for this symbol's .got entries. */ 388833965Sjdp asection *srel; 388933965Sjdp Elf_Internal_Rela outrel; 389033965Sjdp struct alpha_elf_got_entry *gotent; 389133965Sjdp 389233965Sjdp srel = bfd_get_section_by_name (dynobj, ".rela.got"); 389333965Sjdp BFD_ASSERT (srel != NULL); 389433965Sjdp 389533965Sjdp outrel.r_info = ELF64_R_INFO (h->dynindx, R_ALPHA_GLOB_DAT); 389633965Sjdp for (gotent = ((struct alpha_elf_link_hash_entry *) h)->got_entries; 389733965Sjdp gotent != NULL; 389833965Sjdp gotent = gotent->next) 389933965Sjdp { 390033965Sjdp asection *sgot = alpha_elf_tdata (gotent->gotobj)->got; 390133965Sjdp outrel.r_offset = (sgot->output_section->vma 390233965Sjdp + sgot->output_offset 390333965Sjdp + gotent->got_offset); 390433965Sjdp outrel.r_addend = gotent->addend; 390533965Sjdp 390633965Sjdp bfd_elf64_swap_reloca_out (output_bfd, &outrel, 390733965Sjdp ((Elf64_External_Rela *)srel->contents 390833965Sjdp + srel->reloc_count++)); 390977303Sobrien BFD_ASSERT (sizeof (Elf64_External_Rela) * srel->reloc_count 391048850Sdfr <= srel->_cooked_size); 391133965Sjdp } 391233965Sjdp } 391333965Sjdp 391433965Sjdp /* Mark some specially defined symbols as absolute. */ 391533965Sjdp if (strcmp (h->root.root.string, "_DYNAMIC") == 0 391633965Sjdp || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0 391733965Sjdp || strcmp (h->root.root.string, "_PROCEDURE_LINKAGE_TABLE_") == 0) 391833965Sjdp sym->st_shndx = SHN_ABS; 391933965Sjdp 392033965Sjdp return true; 392133965Sjdp} 392233965Sjdp 392333965Sjdp/* Finish up the dynamic sections. */ 392433965Sjdp 392533965Sjdpstatic boolean 392633965Sjdpelf64_alpha_finish_dynamic_sections (output_bfd, info) 392733965Sjdp bfd *output_bfd; 392833965Sjdp struct bfd_link_info *info; 392933965Sjdp{ 393033965Sjdp bfd *dynobj; 393133965Sjdp asection *sdyn; 393233965Sjdp 393333965Sjdp dynobj = elf_hash_table (info)->dynobj; 393433965Sjdp sdyn = bfd_get_section_by_name (dynobj, ".dynamic"); 393533965Sjdp 393633965Sjdp if (elf_hash_table (info)->dynamic_sections_created) 393733965Sjdp { 393833965Sjdp asection *splt; 393933965Sjdp Elf64_External_Dyn *dyncon, *dynconend; 394033965Sjdp 394133965Sjdp splt = bfd_get_section_by_name (dynobj, ".plt"); 394233965Sjdp BFD_ASSERT (splt != NULL && sdyn != NULL); 394333965Sjdp 394433965Sjdp dyncon = (Elf64_External_Dyn *) sdyn->contents; 394533965Sjdp dynconend = (Elf64_External_Dyn *) (sdyn->contents + sdyn->_raw_size); 394633965Sjdp for (; dyncon < dynconend; dyncon++) 394733965Sjdp { 394833965Sjdp Elf_Internal_Dyn dyn; 394933965Sjdp const char *name; 395033965Sjdp asection *s; 395133965Sjdp 395233965Sjdp bfd_elf64_swap_dyn_in (dynobj, dyncon, &dyn); 395333965Sjdp 395433965Sjdp switch (dyn.d_tag) 395533965Sjdp { 395633965Sjdp case DT_PLTGOT: 395733965Sjdp name = ".plt"; 395833965Sjdp goto get_vma; 395933965Sjdp case DT_PLTRELSZ: 396033965Sjdp name = ".rela.plt"; 396133965Sjdp goto get_size; 396233965Sjdp case DT_JMPREL: 396333965Sjdp name = ".rela.plt"; 396433965Sjdp goto get_vma; 396533965Sjdp 396633965Sjdp case DT_RELASZ: 396733965Sjdp /* My interpretation of the TIS v1.1 ELF document indicates 396833965Sjdp that RELASZ should not include JMPREL. This is not what 396933965Sjdp the rest of the BFD does. It is, however, what the 397033965Sjdp glibc ld.so wants. Do this fixup here until we found 397133965Sjdp out who is right. */ 397233965Sjdp s = bfd_get_section_by_name (output_bfd, ".rela.plt"); 397333965Sjdp if (s) 397433965Sjdp { 397533965Sjdp dyn.d_un.d_val -= 397633965Sjdp (s->_cooked_size ? s->_cooked_size : s->_raw_size); 397733965Sjdp } 397833965Sjdp break; 397933965Sjdp 398033965Sjdp get_vma: 398133965Sjdp s = bfd_get_section_by_name (output_bfd, name); 398233965Sjdp dyn.d_un.d_ptr = (s ? s->vma : 0); 398333965Sjdp break; 398433965Sjdp 398533965Sjdp get_size: 398633965Sjdp s = bfd_get_section_by_name (output_bfd, name); 398733965Sjdp dyn.d_un.d_val = 398833965Sjdp (s->_cooked_size ? s->_cooked_size : s->_raw_size); 398933965Sjdp break; 399033965Sjdp } 399133965Sjdp 399233965Sjdp bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon); 399333965Sjdp } 399433965Sjdp 399533965Sjdp /* Initialize the PLT0 entry */ 399633965Sjdp if (splt->_raw_size > 0) 399733965Sjdp { 399833965Sjdp bfd_put_32 (output_bfd, PLT_HEADER_WORD1, splt->contents); 399933965Sjdp bfd_put_32 (output_bfd, PLT_HEADER_WORD2, splt->contents + 4); 400033965Sjdp bfd_put_32 (output_bfd, PLT_HEADER_WORD3, splt->contents + 8); 400133965Sjdp bfd_put_32 (output_bfd, PLT_HEADER_WORD4, splt->contents + 12); 400233965Sjdp 400333965Sjdp /* The next two words will be filled in by ld.so */ 400433965Sjdp bfd_put_64 (output_bfd, 0, splt->contents + 16); 400533965Sjdp bfd_put_64 (output_bfd, 0, splt->contents + 24); 400633965Sjdp 400733965Sjdp elf_section_data (splt->output_section)->this_hdr.sh_entsize = 400833965Sjdp PLT_HEADER_SIZE; 400933965Sjdp } 401033965Sjdp } 401133965Sjdp 401233965Sjdp return true; 401333965Sjdp} 401433965Sjdp 401533965Sjdp/* We need to use a special link routine to handle the .reginfo and 401633965Sjdp the .mdebug sections. We need to merge all instances of these 401733965Sjdp sections together, not write them all out sequentially. */ 401833965Sjdp 401933965Sjdpstatic boolean 402033965Sjdpelf64_alpha_final_link (abfd, info) 402133965Sjdp bfd *abfd; 402233965Sjdp struct bfd_link_info *info; 402333965Sjdp{ 402433965Sjdp asection *o; 402533965Sjdp struct bfd_link_order *p; 402633965Sjdp asection *reginfo_sec, *mdebug_sec, *gptab_data_sec, *gptab_bss_sec; 402733965Sjdp struct ecoff_debug_info debug; 402833965Sjdp const struct ecoff_debug_swap *swap 402933965Sjdp = get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap; 403033965Sjdp HDRR *symhdr = &debug.symbolic_header; 403133965Sjdp PTR mdebug_handle = NULL; 403233965Sjdp 403360510Sobrien#if 0 403460510Sobrien if (++ngots == 2) 403560510Sobrien { 403660510Sobrien (*info->callbacks->warning) 403760510Sobrien (info, _("using multiple gp values"), (char *) NULL, 403860510Sobrien output_bfd, (asection *) NULL, (bfd_vma) 0); 403960510Sobrien } 404060510Sobrien#endif 404160510Sobrien 404233965Sjdp /* Go through the sections and collect the .reginfo and .mdebug 404333965Sjdp information. */ 404433965Sjdp reginfo_sec = NULL; 404533965Sjdp mdebug_sec = NULL; 404633965Sjdp gptab_data_sec = NULL; 404733965Sjdp gptab_bss_sec = NULL; 404833965Sjdp for (o = abfd->sections; o != (asection *) NULL; o = o->next) 404933965Sjdp { 405033965Sjdp#ifdef ERIC_neverdef 405133965Sjdp if (strcmp (o->name, ".reginfo") == 0) 405233965Sjdp { 405333965Sjdp memset (®info, 0, sizeof reginfo); 405433965Sjdp 405533965Sjdp /* We have found the .reginfo section in the output file. 405633965Sjdp Look through all the link_orders comprising it and merge 405733965Sjdp the information together. */ 405833965Sjdp for (p = o->link_order_head; 405933965Sjdp p != (struct bfd_link_order *) NULL; 406033965Sjdp p = p->next) 406133965Sjdp { 406233965Sjdp asection *input_section; 406333965Sjdp bfd *input_bfd; 406433965Sjdp Elf64_External_RegInfo ext; 406533965Sjdp Elf64_RegInfo sub; 406633965Sjdp 406733965Sjdp if (p->type != bfd_indirect_link_order) 406833965Sjdp { 406933965Sjdp if (p->type == bfd_fill_link_order) 407033965Sjdp continue; 407133965Sjdp abort (); 407233965Sjdp } 407333965Sjdp 407433965Sjdp input_section = p->u.indirect.section; 407533965Sjdp input_bfd = input_section->owner; 407633965Sjdp 407733965Sjdp /* The linker emulation code has probably clobbered the 407833965Sjdp size to be zero bytes. */ 407933965Sjdp if (input_section->_raw_size == 0) 408033965Sjdp input_section->_raw_size = sizeof (Elf64_External_RegInfo); 408133965Sjdp 408233965Sjdp if (! bfd_get_section_contents (input_bfd, input_section, 408333965Sjdp (PTR) &ext, 408433965Sjdp (file_ptr) 0, 408533965Sjdp sizeof ext)) 408633965Sjdp return false; 408733965Sjdp 408833965Sjdp bfd_alpha_elf64_swap_reginfo_in (input_bfd, &ext, &sub); 408933965Sjdp 409033965Sjdp reginfo.ri_gprmask |= sub.ri_gprmask; 409133965Sjdp reginfo.ri_cprmask[0] |= sub.ri_cprmask[0]; 409233965Sjdp reginfo.ri_cprmask[1] |= sub.ri_cprmask[1]; 409333965Sjdp reginfo.ri_cprmask[2] |= sub.ri_cprmask[2]; 409433965Sjdp reginfo.ri_cprmask[3] |= sub.ri_cprmask[3]; 409533965Sjdp 409633965Sjdp /* ri_gp_value is set by the function 409733965Sjdp alpha_elf_section_processing when the section is 409833965Sjdp finally written out. */ 409933965Sjdp 410033965Sjdp /* Hack: reset the SEC_HAS_CONTENTS flag so that 410133965Sjdp elf_link_input_bfd ignores this section. */ 410233965Sjdp input_section->flags &=~ SEC_HAS_CONTENTS; 410333965Sjdp } 410433965Sjdp 410533965Sjdp /* Force the section size to the value we want. */ 410633965Sjdp o->_raw_size = sizeof (Elf64_External_RegInfo); 410733965Sjdp 410833965Sjdp /* Skip this section later on (I don't think this currently 410933965Sjdp matters, but someday it might). */ 411033965Sjdp o->link_order_head = (struct bfd_link_order *) NULL; 411133965Sjdp 411233965Sjdp reginfo_sec = o; 411333965Sjdp } 411433965Sjdp#endif 411533965Sjdp 411633965Sjdp if (strcmp (o->name, ".mdebug") == 0) 411733965Sjdp { 411833965Sjdp struct extsym_info einfo; 411933965Sjdp 412033965Sjdp /* We have found the .mdebug section in the output file. 412133965Sjdp Look through all the link_orders comprising it and merge 412233965Sjdp the information together. */ 412333965Sjdp symhdr->magic = swap->sym_magic; 412433965Sjdp /* FIXME: What should the version stamp be? */ 412533965Sjdp symhdr->vstamp = 0; 412633965Sjdp symhdr->ilineMax = 0; 412733965Sjdp symhdr->cbLine = 0; 412833965Sjdp symhdr->idnMax = 0; 412933965Sjdp symhdr->ipdMax = 0; 413033965Sjdp symhdr->isymMax = 0; 413133965Sjdp symhdr->ioptMax = 0; 413233965Sjdp symhdr->iauxMax = 0; 413333965Sjdp symhdr->issMax = 0; 413433965Sjdp symhdr->issExtMax = 0; 413533965Sjdp symhdr->ifdMax = 0; 413633965Sjdp symhdr->crfd = 0; 413733965Sjdp symhdr->iextMax = 0; 413833965Sjdp 413933965Sjdp /* We accumulate the debugging information itself in the 414033965Sjdp debug_info structure. */ 414133965Sjdp debug.line = NULL; 414233965Sjdp debug.external_dnr = NULL; 414333965Sjdp debug.external_pdr = NULL; 414433965Sjdp debug.external_sym = NULL; 414533965Sjdp debug.external_opt = NULL; 414633965Sjdp debug.external_aux = NULL; 414733965Sjdp debug.ss = NULL; 414833965Sjdp debug.ssext = debug.ssext_end = NULL; 414933965Sjdp debug.external_fdr = NULL; 415033965Sjdp debug.external_rfd = NULL; 415133965Sjdp debug.external_ext = debug.external_ext_end = NULL; 415233965Sjdp 415333965Sjdp mdebug_handle = bfd_ecoff_debug_init (abfd, &debug, swap, info); 415433965Sjdp if (mdebug_handle == (PTR) NULL) 415533965Sjdp return false; 415633965Sjdp 415733965Sjdp if (1) 415833965Sjdp { 415933965Sjdp asection *s; 416033965Sjdp EXTR esym; 416133965Sjdp bfd_vma last; 416233965Sjdp unsigned int i; 416333965Sjdp static const char * const name[] = 416433965Sjdp { 416533965Sjdp ".text", ".init", ".fini", ".data", 416633965Sjdp ".rodata", ".sdata", ".sbss", ".bss" 416733965Sjdp }; 416833965Sjdp static const int sc[] = { scText, scInit, scFini, scData, 416933965Sjdp scRData, scSData, scSBss, scBss }; 417033965Sjdp 417133965Sjdp esym.jmptbl = 0; 417233965Sjdp esym.cobol_main = 0; 417333965Sjdp esym.weakext = 0; 417433965Sjdp esym.reserved = 0; 417533965Sjdp esym.ifd = ifdNil; 417633965Sjdp esym.asym.iss = issNil; 417733965Sjdp esym.asym.st = stLocal; 417833965Sjdp esym.asym.reserved = 0; 417933965Sjdp esym.asym.index = indexNil; 418033965Sjdp for (i = 0; i < 8; i++) 418133965Sjdp { 418233965Sjdp esym.asym.sc = sc[i]; 418333965Sjdp s = bfd_get_section_by_name (abfd, name[i]); 418433965Sjdp if (s != NULL) 418533965Sjdp { 418633965Sjdp esym.asym.value = s->vma; 418733965Sjdp last = s->vma + s->_raw_size; 418833965Sjdp } 418933965Sjdp else 419033965Sjdp esym.asym.value = last; 419133965Sjdp 419233965Sjdp if (! bfd_ecoff_debug_one_external (abfd, &debug, swap, 419333965Sjdp name[i], &esym)) 419433965Sjdp return false; 419533965Sjdp } 419633965Sjdp } 419733965Sjdp 419833965Sjdp for (p = o->link_order_head; 419933965Sjdp p != (struct bfd_link_order *) NULL; 420033965Sjdp p = p->next) 420133965Sjdp { 420233965Sjdp asection *input_section; 420333965Sjdp bfd *input_bfd; 420433965Sjdp const struct ecoff_debug_swap *input_swap; 420533965Sjdp struct ecoff_debug_info input_debug; 420633965Sjdp char *eraw_src; 420733965Sjdp char *eraw_end; 420833965Sjdp 420933965Sjdp if (p->type != bfd_indirect_link_order) 421033965Sjdp { 421133965Sjdp if (p->type == bfd_fill_link_order) 421233965Sjdp continue; 421333965Sjdp abort (); 421433965Sjdp } 421533965Sjdp 421633965Sjdp input_section = p->u.indirect.section; 421733965Sjdp input_bfd = input_section->owner; 421833965Sjdp 421933965Sjdp if (bfd_get_flavour (input_bfd) != bfd_target_elf_flavour 422033965Sjdp || (get_elf_backend_data (input_bfd) 422133965Sjdp ->elf_backend_ecoff_debug_swap) == NULL) 422233965Sjdp { 422333965Sjdp /* I don't know what a non ALPHA ELF bfd would be 422433965Sjdp doing with a .mdebug section, but I don't really 422533965Sjdp want to deal with it. */ 422633965Sjdp continue; 422733965Sjdp } 422833965Sjdp 422933965Sjdp input_swap = (get_elf_backend_data (input_bfd) 423033965Sjdp ->elf_backend_ecoff_debug_swap); 423133965Sjdp 423233965Sjdp BFD_ASSERT (p->size == input_section->_raw_size); 423333965Sjdp 423433965Sjdp /* The ECOFF linking code expects that we have already 423533965Sjdp read in the debugging information and set up an 423633965Sjdp ecoff_debug_info structure, so we do that now. */ 423733965Sjdp if (!elf64_alpha_read_ecoff_info (input_bfd, input_section, 423833965Sjdp &input_debug)) 423933965Sjdp return false; 424033965Sjdp 424133965Sjdp if (! (bfd_ecoff_debug_accumulate 424233965Sjdp (mdebug_handle, abfd, &debug, swap, input_bfd, 424333965Sjdp &input_debug, input_swap, info))) 424433965Sjdp return false; 424533965Sjdp 424633965Sjdp /* Loop through the external symbols. For each one with 424733965Sjdp interesting information, try to find the symbol in 424833965Sjdp the linker global hash table and save the information 424933965Sjdp for the output external symbols. */ 425033965Sjdp eraw_src = input_debug.external_ext; 425133965Sjdp eraw_end = (eraw_src 425233965Sjdp + (input_debug.symbolic_header.iextMax 425333965Sjdp * input_swap->external_ext_size)); 425433965Sjdp for (; 425533965Sjdp eraw_src < eraw_end; 425633965Sjdp eraw_src += input_swap->external_ext_size) 425733965Sjdp { 425833965Sjdp EXTR ext; 425933965Sjdp const char *name; 426033965Sjdp struct alpha_elf_link_hash_entry *h; 426133965Sjdp 426233965Sjdp (*input_swap->swap_ext_in) (input_bfd, (PTR) eraw_src, &ext); 426333965Sjdp if (ext.asym.sc == scNil 426433965Sjdp || ext.asym.sc == scUndefined 426533965Sjdp || ext.asym.sc == scSUndefined) 426633965Sjdp continue; 426733965Sjdp 426833965Sjdp name = input_debug.ssext + ext.asym.iss; 426933965Sjdp h = alpha_elf_link_hash_lookup (alpha_elf_hash_table (info), 427033965Sjdp name, false, false, true); 427133965Sjdp if (h == NULL || h->esym.ifd != -2) 427233965Sjdp continue; 427333965Sjdp 427433965Sjdp if (ext.ifd != -1) 427533965Sjdp { 427633965Sjdp BFD_ASSERT (ext.ifd 427733965Sjdp < input_debug.symbolic_header.ifdMax); 427833965Sjdp ext.ifd = input_debug.ifdmap[ext.ifd]; 427933965Sjdp } 428033965Sjdp 428133965Sjdp h->esym = ext; 428233965Sjdp } 428333965Sjdp 428433965Sjdp /* Free up the information we just read. */ 428533965Sjdp free (input_debug.line); 428633965Sjdp free (input_debug.external_dnr); 428733965Sjdp free (input_debug.external_pdr); 428833965Sjdp free (input_debug.external_sym); 428933965Sjdp free (input_debug.external_opt); 429033965Sjdp free (input_debug.external_aux); 429133965Sjdp free (input_debug.ss); 429233965Sjdp free (input_debug.ssext); 429333965Sjdp free (input_debug.external_fdr); 429433965Sjdp free (input_debug.external_rfd); 429533965Sjdp free (input_debug.external_ext); 429633965Sjdp 429733965Sjdp /* Hack: reset the SEC_HAS_CONTENTS flag so that 429833965Sjdp elf_link_input_bfd ignores this section. */ 429933965Sjdp input_section->flags &=~ SEC_HAS_CONTENTS; 430033965Sjdp } 430133965Sjdp 430233965Sjdp#ifdef ERIC_neverdef 430333965Sjdp if (info->shared) 430433965Sjdp { 430533965Sjdp /* Create .rtproc section. */ 430633965Sjdp rtproc_sec = bfd_get_section_by_name (abfd, ".rtproc"); 430733965Sjdp if (rtproc_sec == NULL) 430833965Sjdp { 430933965Sjdp flagword flags = (SEC_HAS_CONTENTS 431033965Sjdp | SEC_IN_MEMORY 431133965Sjdp | SEC_LINKER_CREATED 431233965Sjdp | SEC_READONLY); 431333965Sjdp 431433965Sjdp rtproc_sec = bfd_make_section (abfd, ".rtproc"); 431533965Sjdp if (rtproc_sec == NULL 431633965Sjdp || ! bfd_set_section_flags (abfd, rtproc_sec, flags) 431733965Sjdp || ! bfd_set_section_alignment (abfd, rtproc_sec, 12)) 431833965Sjdp return false; 431933965Sjdp } 432033965Sjdp 432133965Sjdp if (! alpha_elf_create_procedure_table (mdebug_handle, abfd, 432233965Sjdp info, rtproc_sec, &debug)) 432333965Sjdp return false; 432433965Sjdp } 432533965Sjdp#endif 432633965Sjdp 432733965Sjdp /* Build the external symbol information. */ 432833965Sjdp einfo.abfd = abfd; 432933965Sjdp einfo.info = info; 433033965Sjdp einfo.debug = &debug; 433133965Sjdp einfo.swap = swap; 433233965Sjdp einfo.failed = false; 433333965Sjdp elf_link_hash_traverse (elf_hash_table (info), 433433965Sjdp elf64_alpha_output_extsym, 433533965Sjdp (PTR) &einfo); 433633965Sjdp if (einfo.failed) 433733965Sjdp return false; 433833965Sjdp 433933965Sjdp /* Set the size of the .mdebug section. */ 434033965Sjdp o->_raw_size = bfd_ecoff_debug_size (abfd, &debug, swap); 434133965Sjdp 434233965Sjdp /* Skip this section later on (I don't think this currently 434333965Sjdp matters, but someday it might). */ 434433965Sjdp o->link_order_head = (struct bfd_link_order *) NULL; 434533965Sjdp 434633965Sjdp mdebug_sec = o; 434733965Sjdp } 434833965Sjdp 434933965Sjdp#ifdef ERIC_neverdef 435033965Sjdp if (strncmp (o->name, ".gptab.", sizeof ".gptab." - 1) == 0) 435133965Sjdp { 435233965Sjdp const char *subname; 435333965Sjdp unsigned int c; 435433965Sjdp Elf64_gptab *tab; 435533965Sjdp Elf64_External_gptab *ext_tab; 435633965Sjdp unsigned int i; 435733965Sjdp 435833965Sjdp /* The .gptab.sdata and .gptab.sbss sections hold 435933965Sjdp information describing how the small data area would 436033965Sjdp change depending upon the -G switch. These sections 436133965Sjdp not used in executables files. */ 436233965Sjdp if (! info->relocateable) 436333965Sjdp { 436433965Sjdp asection **secpp; 436533965Sjdp 436633965Sjdp for (p = o->link_order_head; 436733965Sjdp p != (struct bfd_link_order *) NULL; 436833965Sjdp p = p->next) 436933965Sjdp { 437033965Sjdp asection *input_section; 437133965Sjdp 437233965Sjdp if (p->type != bfd_indirect_link_order) 437333965Sjdp { 437433965Sjdp if (p->type == bfd_fill_link_order) 437533965Sjdp continue; 437633965Sjdp abort (); 437733965Sjdp } 437833965Sjdp 437933965Sjdp input_section = p->u.indirect.section; 438033965Sjdp 438133965Sjdp /* Hack: reset the SEC_HAS_CONTENTS flag so that 438233965Sjdp elf_link_input_bfd ignores this section. */ 438333965Sjdp input_section->flags &=~ SEC_HAS_CONTENTS; 438433965Sjdp } 438533965Sjdp 438633965Sjdp /* Skip this section later on (I don't think this 438733965Sjdp currently matters, but someday it might). */ 438833965Sjdp o->link_order_head = (struct bfd_link_order *) NULL; 438933965Sjdp 439033965Sjdp /* Really remove the section. */ 439133965Sjdp for (secpp = &abfd->sections; 439233965Sjdp *secpp != o; 439333965Sjdp secpp = &(*secpp)->next) 439433965Sjdp ; 439533965Sjdp *secpp = (*secpp)->next; 439633965Sjdp --abfd->section_count; 439733965Sjdp 439833965Sjdp continue; 439933965Sjdp } 440033965Sjdp 440133965Sjdp /* There is one gptab for initialized data, and one for 440233965Sjdp uninitialized data. */ 440333965Sjdp if (strcmp (o->name, ".gptab.sdata") == 0) 440433965Sjdp gptab_data_sec = o; 440533965Sjdp else if (strcmp (o->name, ".gptab.sbss") == 0) 440633965Sjdp gptab_bss_sec = o; 440733965Sjdp else 440833965Sjdp { 440933965Sjdp (*_bfd_error_handler) 441060510Sobrien (_("%s: illegal section name `%s'"), 441133965Sjdp bfd_get_filename (abfd), o->name); 441233965Sjdp bfd_set_error (bfd_error_nonrepresentable_section); 441333965Sjdp return false; 441433965Sjdp } 441533965Sjdp 441633965Sjdp /* The linker script always combines .gptab.data and 441733965Sjdp .gptab.sdata into .gptab.sdata, and likewise for 441833965Sjdp .gptab.bss and .gptab.sbss. It is possible that there is 441933965Sjdp no .sdata or .sbss section in the output file, in which 442033965Sjdp case we must change the name of the output section. */ 442133965Sjdp subname = o->name + sizeof ".gptab" - 1; 442233965Sjdp if (bfd_get_section_by_name (abfd, subname) == NULL) 442333965Sjdp { 442433965Sjdp if (o == gptab_data_sec) 442533965Sjdp o->name = ".gptab.data"; 442633965Sjdp else 442733965Sjdp o->name = ".gptab.bss"; 442833965Sjdp subname = o->name + sizeof ".gptab" - 1; 442933965Sjdp BFD_ASSERT (bfd_get_section_by_name (abfd, subname) != NULL); 443033965Sjdp } 443133965Sjdp 443233965Sjdp /* Set up the first entry. */ 443333965Sjdp c = 1; 443433965Sjdp tab = (Elf64_gptab *) bfd_malloc (c * sizeof (Elf64_gptab)); 443533965Sjdp if (tab == NULL) 443633965Sjdp return false; 443733965Sjdp tab[0].gt_header.gt_current_g_value = elf_gp_size (abfd); 443833965Sjdp tab[0].gt_header.gt_unused = 0; 443933965Sjdp 444033965Sjdp /* Combine the input sections. */ 444133965Sjdp for (p = o->link_order_head; 444233965Sjdp p != (struct bfd_link_order *) NULL; 444333965Sjdp p = p->next) 444433965Sjdp { 444533965Sjdp asection *input_section; 444633965Sjdp bfd *input_bfd; 444733965Sjdp bfd_size_type size; 444833965Sjdp unsigned long last; 444933965Sjdp bfd_size_type gpentry; 445033965Sjdp 445133965Sjdp if (p->type != bfd_indirect_link_order) 445233965Sjdp { 445333965Sjdp if (p->type == bfd_fill_link_order) 445433965Sjdp continue; 445533965Sjdp abort (); 445633965Sjdp } 445733965Sjdp 445833965Sjdp input_section = p->u.indirect.section; 445933965Sjdp input_bfd = input_section->owner; 446033965Sjdp 446133965Sjdp /* Combine the gptab entries for this input section one 446233965Sjdp by one. We know that the input gptab entries are 446333965Sjdp sorted by ascending -G value. */ 446433965Sjdp size = bfd_section_size (input_bfd, input_section); 446533965Sjdp last = 0; 446633965Sjdp for (gpentry = sizeof (Elf64_External_gptab); 446733965Sjdp gpentry < size; 446833965Sjdp gpentry += sizeof (Elf64_External_gptab)) 446933965Sjdp { 447033965Sjdp Elf64_External_gptab ext_gptab; 447133965Sjdp Elf64_gptab int_gptab; 447233965Sjdp unsigned long val; 447333965Sjdp unsigned long add; 447433965Sjdp boolean exact; 447533965Sjdp unsigned int look; 447633965Sjdp 447733965Sjdp if (! (bfd_get_section_contents 447833965Sjdp (input_bfd, input_section, (PTR) &ext_gptab, 447933965Sjdp gpentry, sizeof (Elf64_External_gptab)))) 448033965Sjdp { 448133965Sjdp free (tab); 448233965Sjdp return false; 448333965Sjdp } 448433965Sjdp 448533965Sjdp bfd_alpha_elf64_swap_gptab_in (input_bfd, &ext_gptab, 448633965Sjdp &int_gptab); 448733965Sjdp val = int_gptab.gt_entry.gt_g_value; 448833965Sjdp add = int_gptab.gt_entry.gt_bytes - last; 448933965Sjdp 449033965Sjdp exact = false; 449133965Sjdp for (look = 1; look < c; look++) 449233965Sjdp { 449333965Sjdp if (tab[look].gt_entry.gt_g_value >= val) 449433965Sjdp tab[look].gt_entry.gt_bytes += add; 449533965Sjdp 449633965Sjdp if (tab[look].gt_entry.gt_g_value == val) 449733965Sjdp exact = true; 449833965Sjdp } 449933965Sjdp 450033965Sjdp if (! exact) 450133965Sjdp { 450233965Sjdp Elf64_gptab *new_tab; 450333965Sjdp unsigned int max; 450433965Sjdp 450533965Sjdp /* We need a new table entry. */ 450633965Sjdp new_tab = ((Elf64_gptab *) 450733965Sjdp bfd_realloc ((PTR) tab, 450833965Sjdp (c + 1) * sizeof (Elf64_gptab))); 450933965Sjdp if (new_tab == NULL) 451033965Sjdp { 451133965Sjdp free (tab); 451233965Sjdp return false; 451333965Sjdp } 451433965Sjdp tab = new_tab; 451533965Sjdp tab[c].gt_entry.gt_g_value = val; 451633965Sjdp tab[c].gt_entry.gt_bytes = add; 451733965Sjdp 451833965Sjdp /* Merge in the size for the next smallest -G 451933965Sjdp value, since that will be implied by this new 452033965Sjdp value. */ 452133965Sjdp max = 0; 452233965Sjdp for (look = 1; look < c; look++) 452333965Sjdp { 452433965Sjdp if (tab[look].gt_entry.gt_g_value < val 452533965Sjdp && (max == 0 452633965Sjdp || (tab[look].gt_entry.gt_g_value 452733965Sjdp > tab[max].gt_entry.gt_g_value))) 452833965Sjdp max = look; 452933965Sjdp } 453033965Sjdp if (max != 0) 453133965Sjdp tab[c].gt_entry.gt_bytes += 453233965Sjdp tab[max].gt_entry.gt_bytes; 453333965Sjdp 453433965Sjdp ++c; 453533965Sjdp } 453633965Sjdp 453733965Sjdp last = int_gptab.gt_entry.gt_bytes; 453833965Sjdp } 453933965Sjdp 454033965Sjdp /* Hack: reset the SEC_HAS_CONTENTS flag so that 454133965Sjdp elf_link_input_bfd ignores this section. */ 454233965Sjdp input_section->flags &=~ SEC_HAS_CONTENTS; 454333965Sjdp } 454433965Sjdp 454533965Sjdp /* The table must be sorted by -G value. */ 454633965Sjdp if (c > 2) 454733965Sjdp qsort (tab + 1, c - 1, sizeof (tab[0]), gptab_compare); 454833965Sjdp 454933965Sjdp /* Swap out the table. */ 455033965Sjdp ext_tab = ((Elf64_External_gptab *) 455133965Sjdp bfd_alloc (abfd, c * sizeof (Elf64_External_gptab))); 455233965Sjdp if (ext_tab == NULL) 455333965Sjdp { 455433965Sjdp free (tab); 455533965Sjdp return false; 455633965Sjdp } 455733965Sjdp 455833965Sjdp for (i = 0; i < c; i++) 455933965Sjdp bfd_alpha_elf64_swap_gptab_out (abfd, tab + i, ext_tab + i); 456033965Sjdp free (tab); 456133965Sjdp 456233965Sjdp o->_raw_size = c * sizeof (Elf64_External_gptab); 456333965Sjdp o->contents = (bfd_byte *) ext_tab; 456433965Sjdp 456533965Sjdp /* Skip this section later on (I don't think this currently 456633965Sjdp matters, but someday it might). */ 456733965Sjdp o->link_order_head = (struct bfd_link_order *) NULL; 456833965Sjdp } 456933965Sjdp#endif 457033965Sjdp 457133965Sjdp } 457233965Sjdp 457333965Sjdp /* Invoke the regular ELF backend linker to do all the work. */ 457433965Sjdp if (! bfd_elf64_bfd_final_link (abfd, info)) 457533965Sjdp return false; 457633965Sjdp 457733965Sjdp /* Now write out the computed sections. */ 457833965Sjdp 457933965Sjdp /* The .got subsections... */ 458033965Sjdp { 458133965Sjdp bfd *i, *dynobj = elf_hash_table(info)->dynobj; 458233965Sjdp for (i = alpha_elf_hash_table(info)->got_list; 458333965Sjdp i != NULL; 458433965Sjdp i = alpha_elf_tdata(i)->got_link_next) 458533965Sjdp { 458633965Sjdp asection *sgot; 458733965Sjdp 458833965Sjdp /* elf_bfd_final_link already did everything in dynobj. */ 458933965Sjdp if (i == dynobj) 459033965Sjdp continue; 459133965Sjdp 459233965Sjdp sgot = alpha_elf_tdata(i)->got; 459333965Sjdp if (! bfd_set_section_contents (abfd, sgot->output_section, 459433965Sjdp sgot->contents, sgot->output_offset, 459533965Sjdp sgot->_raw_size)) 459633965Sjdp return false; 459733965Sjdp } 459833965Sjdp } 459933965Sjdp 460033965Sjdp#ifdef ERIC_neverdef 460133965Sjdp if (reginfo_sec != (asection *) NULL) 460233965Sjdp { 460333965Sjdp Elf64_External_RegInfo ext; 460433965Sjdp 460533965Sjdp bfd_alpha_elf64_swap_reginfo_out (abfd, ®info, &ext); 460633965Sjdp if (! bfd_set_section_contents (abfd, reginfo_sec, (PTR) &ext, 460733965Sjdp (file_ptr) 0, sizeof ext)) 460833965Sjdp return false; 460933965Sjdp } 461033965Sjdp#endif 461133965Sjdp 461233965Sjdp if (mdebug_sec != (asection *) NULL) 461333965Sjdp { 461433965Sjdp BFD_ASSERT (abfd->output_has_begun); 461533965Sjdp if (! bfd_ecoff_write_accumulated_debug (mdebug_handle, abfd, &debug, 461633965Sjdp swap, info, 461733965Sjdp mdebug_sec->filepos)) 461833965Sjdp return false; 461933965Sjdp 462033965Sjdp bfd_ecoff_debug_free (mdebug_handle, abfd, &debug, swap, info); 462133965Sjdp } 462233965Sjdp 462333965Sjdp if (gptab_data_sec != (asection *) NULL) 462433965Sjdp { 462533965Sjdp if (! bfd_set_section_contents (abfd, gptab_data_sec, 462633965Sjdp gptab_data_sec->contents, 462733965Sjdp (file_ptr) 0, 462833965Sjdp gptab_data_sec->_raw_size)) 462933965Sjdp return false; 463033965Sjdp } 463133965Sjdp 463233965Sjdp if (gptab_bss_sec != (asection *) NULL) 463333965Sjdp { 463433965Sjdp if (! bfd_set_section_contents (abfd, gptab_bss_sec, 463533965Sjdp gptab_bss_sec->contents, 463633965Sjdp (file_ptr) 0, 463733965Sjdp gptab_bss_sec->_raw_size)) 463833965Sjdp return false; 463933965Sjdp } 464033965Sjdp 464133965Sjdp return true; 464233965Sjdp} 464333965Sjdp 464433965Sjdp/* ECOFF swapping routines. These are used when dealing with the 464533965Sjdp .mdebug section, which is in the ECOFF debugging format. Copied 464677303Sobrien from elf32-mips.c. */ 464733965Sjdpstatic const struct ecoff_debug_swap 464833965Sjdpelf64_alpha_ecoff_debug_swap = 464933965Sjdp{ 465033965Sjdp /* Symbol table magic number. */ 465133965Sjdp magicSym2, 465233965Sjdp /* Alignment of debugging information. E.g., 4. */ 465333965Sjdp 8, 465433965Sjdp /* Sizes of external symbolic information. */ 465533965Sjdp sizeof (struct hdr_ext), 465633965Sjdp sizeof (struct dnr_ext), 465733965Sjdp sizeof (struct pdr_ext), 465833965Sjdp sizeof (struct sym_ext), 465933965Sjdp sizeof (struct opt_ext), 466033965Sjdp sizeof (struct fdr_ext), 466133965Sjdp sizeof (struct rfd_ext), 466233965Sjdp sizeof (struct ext_ext), 466333965Sjdp /* Functions to swap in external symbolic data. */ 466433965Sjdp ecoff_swap_hdr_in, 466533965Sjdp ecoff_swap_dnr_in, 466633965Sjdp ecoff_swap_pdr_in, 466733965Sjdp ecoff_swap_sym_in, 466833965Sjdp ecoff_swap_opt_in, 466933965Sjdp ecoff_swap_fdr_in, 467033965Sjdp ecoff_swap_rfd_in, 467133965Sjdp ecoff_swap_ext_in, 467233965Sjdp _bfd_ecoff_swap_tir_in, 467333965Sjdp _bfd_ecoff_swap_rndx_in, 467433965Sjdp /* Functions to swap out external symbolic data. */ 467533965Sjdp ecoff_swap_hdr_out, 467633965Sjdp ecoff_swap_dnr_out, 467733965Sjdp ecoff_swap_pdr_out, 467833965Sjdp ecoff_swap_sym_out, 467933965Sjdp ecoff_swap_opt_out, 468033965Sjdp ecoff_swap_fdr_out, 468133965Sjdp ecoff_swap_rfd_out, 468233965Sjdp ecoff_swap_ext_out, 468333965Sjdp _bfd_ecoff_swap_tir_out, 468433965Sjdp _bfd_ecoff_swap_rndx_out, 468533965Sjdp /* Function to read in symbolic data. */ 468633965Sjdp elf64_alpha_read_ecoff_info 468733965Sjdp}; 468833965Sjdp 468977303Sobrien/* Use a non-standard hash bucket size of 8. */ 469077303Sobrien 469177303Sobrienconst struct elf_size_info alpha_elf_size_info = 469277303Sobrien{ 469377303Sobrien sizeof (Elf64_External_Ehdr), 469477303Sobrien sizeof (Elf64_External_Phdr), 469577303Sobrien sizeof (Elf64_External_Shdr), 469677303Sobrien sizeof (Elf64_External_Rel), 469777303Sobrien sizeof (Elf64_External_Rela), 469877303Sobrien sizeof (Elf64_External_Sym), 469977303Sobrien sizeof (Elf64_External_Dyn), 470077303Sobrien sizeof (Elf_External_Note), 470177303Sobrien 8, 470277303Sobrien 1, 470377303Sobrien 64, 8, 470477303Sobrien ELFCLASS64, EV_CURRENT, 470577303Sobrien bfd_elf64_write_out_phdrs, 470677303Sobrien bfd_elf64_write_shdrs_and_ehdr, 470777303Sobrien bfd_elf64_write_relocs, 470877303Sobrien bfd_elf64_swap_symbol_out, 470977303Sobrien bfd_elf64_slurp_reloc_table, 471077303Sobrien bfd_elf64_slurp_symbol_table, 471177303Sobrien bfd_elf64_swap_dyn_in, 471277303Sobrien bfd_elf64_swap_dyn_out, 471377303Sobrien NULL, 471477303Sobrien NULL, 471577303Sobrien NULL, 471677303Sobrien NULL 471777303Sobrien}; 471877303Sobrien 471933965Sjdp#define TARGET_LITTLE_SYM bfd_elf64_alpha_vec 472033965Sjdp#define TARGET_LITTLE_NAME "elf64-alpha" 472133965Sjdp#define ELF_ARCH bfd_arch_alpha 472233965Sjdp#define ELF_MACHINE_CODE EM_ALPHA 472338889Sjdp#define ELF_MAXPAGESIZE 0x10000 472433965Sjdp 472533965Sjdp#define bfd_elf64_bfd_link_hash_table_create \ 472633965Sjdp elf64_alpha_bfd_link_hash_table_create 472733965Sjdp 472833965Sjdp#define bfd_elf64_bfd_reloc_type_lookup \ 472933965Sjdp elf64_alpha_bfd_reloc_type_lookup 473033965Sjdp#define elf_info_to_howto \ 473133965Sjdp elf64_alpha_info_to_howto 473233965Sjdp 473333965Sjdp#define bfd_elf64_mkobject \ 473433965Sjdp elf64_alpha_mkobject 473533965Sjdp#define elf_backend_object_p \ 473633965Sjdp elf64_alpha_object_p 473733965Sjdp 473833965Sjdp#define elf_backend_section_from_shdr \ 473933965Sjdp elf64_alpha_section_from_shdr 474033965Sjdp#define elf_backend_fake_sections \ 474133965Sjdp elf64_alpha_fake_sections 474233965Sjdp 474333965Sjdp#define bfd_elf64_bfd_is_local_label_name \ 474433965Sjdp elf64_alpha_is_local_label_name 474533965Sjdp#define bfd_elf64_find_nearest_line \ 474633965Sjdp elf64_alpha_find_nearest_line 474760510Sobrien#define bfd_elf64_bfd_relax_section \ 474860510Sobrien elf64_alpha_relax_section 474933965Sjdp 475060510Sobrien#define elf_backend_add_symbol_hook \ 475160510Sobrien elf64_alpha_add_symbol_hook 475233965Sjdp#define elf_backend_check_relocs \ 475333965Sjdp elf64_alpha_check_relocs 475433965Sjdp#define elf_backend_create_dynamic_sections \ 475533965Sjdp elf64_alpha_create_dynamic_sections 475633965Sjdp#define elf_backend_adjust_dynamic_symbol \ 475733965Sjdp elf64_alpha_adjust_dynamic_symbol 475833965Sjdp#define elf_backend_always_size_sections \ 475933965Sjdp elf64_alpha_always_size_sections 476033965Sjdp#define elf_backend_size_dynamic_sections \ 476133965Sjdp elf64_alpha_size_dynamic_sections 476233965Sjdp#define elf_backend_relocate_section \ 476333965Sjdp elf64_alpha_relocate_section 476433965Sjdp#define elf_backend_finish_dynamic_symbol \ 476533965Sjdp elf64_alpha_finish_dynamic_symbol 476633965Sjdp#define elf_backend_finish_dynamic_sections \ 476733965Sjdp elf64_alpha_finish_dynamic_sections 476833965Sjdp#define bfd_elf64_bfd_final_link \ 476933965Sjdp elf64_alpha_final_link 477033965Sjdp 477133965Sjdp#define elf_backend_ecoff_debug_swap \ 477233965Sjdp &elf64_alpha_ecoff_debug_swap 477333965Sjdp 477477303Sobrien#define elf_backend_size_info \ 477577303Sobrien alpha_elf_size_info 477677303Sobrien 477777303Sobrien/* A few constants that determine how the .plt section is set up. */ 477833965Sjdp#define elf_backend_want_got_plt 0 477933965Sjdp#define elf_backend_plt_readonly 0 478033965Sjdp#define elf_backend_want_plt_sym 1 478160510Sobrien#define elf_backend_got_header_size 0 478260510Sobrien#define elf_backend_plt_header_size PLT_HEADER_SIZE 478333965Sjdp 478433965Sjdp#include "elf64-target.h" 4785