159024Sobrien/* SPARC-specific support for 64-bit ELF 2130561Sobrien Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 3218822Sdim 2003, 2004, 2005, 2007 Free Software Foundation, Inc. 459024Sobrien 5130561Sobrien This file is part of BFD, the Binary File Descriptor library. 659024Sobrien 7130561Sobrien This program is free software; you can redistribute it and/or modify 8130561Sobrien it under the terms of the GNU General Public License as published by 9130561Sobrien the Free Software Foundation; either version 2 of the License, or 10130561Sobrien (at your option) any later version. 1159024Sobrien 12130561Sobrien This program is distributed in the hope that it will be useful, 13130561Sobrien but WITHOUT ANY WARRANTY; without even the implied warranty of 14130561Sobrien MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15130561Sobrien GNU General Public License for more details. 1659024Sobrien 17130561Sobrien You should have received a copy of the GNU General Public License 18130561Sobrien along with this program; if not, write to the Free Software 19218822Sdim Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ 2059024Sobrien 21218822Sdim#include "sysdep.h" 2259024Sobrien#include "bfd.h" 2359024Sobrien#include "libbfd.h" 2459024Sobrien#include "elf-bfd.h" 25218822Sdim#include "elf/sparc.h" 2677298Sobrien#include "opcode/sparc.h" 27218822Sdim#include "elfxx-sparc.h" 2859024Sobrien 2959024Sobrien/* In case we're on a 32-bit machine, construct a 64-bit "-1" value. */ 3059024Sobrien#define MINUS_ONE (~ (bfd_vma) 0) 3159024Sobrien 3260484Sobrien/* Due to the way how we handle R_SPARC_OLO10, each entry in a SHT_RELA 3360484Sobrien section can represent up to two relocs, we must tell the user to allocate 3460484Sobrien more space. */ 3577298Sobrien 3660484Sobrienstatic long 37218822Sdimelf64_sparc_get_reloc_upper_bound (bfd *abfd ATTRIBUTE_UNUSED, asection *sec) 3860484Sobrien{ 3960484Sobrien return (sec->reloc_count * 2 + 1) * sizeof (arelent *); 4060484Sobrien} 4160484Sobrien 4260484Sobrienstatic long 43218822Sdimelf64_sparc_get_dynamic_reloc_upper_bound (bfd *abfd) 4460484Sobrien{ 4560484Sobrien return _bfd_elf_get_dynamic_reloc_upper_bound (abfd) * 2; 4660484Sobrien} 4760484Sobrien 4877298Sobrien/* Read relocations for ASECT from REL_HDR. There are RELOC_COUNT of 4960484Sobrien them. We cannot use generic elf routines for this, because R_SPARC_OLO10 5060484Sobrien has secondary addend in ELF64_R_TYPE_DATA. We handle it as two relocations 5160484Sobrien for the same location, R_SPARC_LO10 and R_SPARC_13. */ 5260484Sobrien 53130561Sobrienstatic bfd_boolean 54218822Sdimelf64_sparc_slurp_one_reloc_table (bfd *abfd, asection *asect, 55218822Sdim Elf_Internal_Shdr *rel_hdr, 56218822Sdim asymbol **symbols, bfd_boolean dynamic) 5760484Sobrien{ 5860484Sobrien PTR allocated = NULL; 5960484Sobrien bfd_byte *native_relocs; 6060484Sobrien arelent *relent; 6160484Sobrien unsigned int i; 6260484Sobrien int entsize; 6360484Sobrien bfd_size_type count; 6460484Sobrien arelent *relents; 6560484Sobrien 6689857Sobrien allocated = (PTR) bfd_malloc (rel_hdr->sh_size); 6760484Sobrien if (allocated == NULL) 6860484Sobrien goto error_return; 6960484Sobrien 7060484Sobrien if (bfd_seek (abfd, rel_hdr->sh_offset, SEEK_SET) != 0 7189857Sobrien || bfd_bread (allocated, rel_hdr->sh_size, abfd) != rel_hdr->sh_size) 7260484Sobrien goto error_return; 7360484Sobrien 7460484Sobrien native_relocs = (bfd_byte *) allocated; 7560484Sobrien 76130561Sobrien relents = asect->relocation + canon_reloc_count (asect); 7760484Sobrien 7860484Sobrien entsize = rel_hdr->sh_entsize; 7960484Sobrien BFD_ASSERT (entsize == sizeof (Elf64_External_Rela)); 8077298Sobrien 8160484Sobrien count = rel_hdr->sh_size / entsize; 8260484Sobrien 8360484Sobrien for (i = 0, relent = relents; i < count; 8460484Sobrien i++, relent++, native_relocs += entsize) 8560484Sobrien { 8660484Sobrien Elf_Internal_Rela rela; 87218822Sdim unsigned int r_type; 8860484Sobrien 89130561Sobrien bfd_elf64_swap_reloca_in (abfd, native_relocs, &rela); 9060484Sobrien 9160484Sobrien /* The address of an ELF reloc is section relative for an object 9260484Sobrien file, and absolute for an executable file or shared library. 9360484Sobrien The address of a normal BFD reloc is always section relative, 9460484Sobrien and the address of a dynamic reloc is absolute.. */ 9560484Sobrien if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0 || dynamic) 9660484Sobrien relent->address = rela.r_offset; 9760484Sobrien else 9860484Sobrien relent->address = rela.r_offset - asect->vma; 9960484Sobrien 10060484Sobrien if (ELF64_R_SYM (rela.r_info) == 0) 10160484Sobrien relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; 10260484Sobrien else 10360484Sobrien { 10460484Sobrien asymbol **ps, *s; 10560484Sobrien 10660484Sobrien ps = symbols + ELF64_R_SYM (rela.r_info) - 1; 10760484Sobrien s = *ps; 10860484Sobrien 10960484Sobrien /* Canonicalize ELF section symbols. FIXME: Why? */ 11060484Sobrien if ((s->flags & BSF_SECTION_SYM) == 0) 11160484Sobrien relent->sym_ptr_ptr = ps; 11260484Sobrien else 11360484Sobrien relent->sym_ptr_ptr = s->section->symbol_ptr_ptr; 11460484Sobrien } 11560484Sobrien 11660484Sobrien relent->addend = rela.r_addend; 11760484Sobrien 118218822Sdim r_type = ELF64_R_TYPE_ID (rela.r_info); 119218822Sdim if (r_type == R_SPARC_OLO10) 12060484Sobrien { 121218822Sdim relent->howto = _bfd_sparc_elf_info_to_howto_ptr (R_SPARC_LO10); 12260484Sobrien relent[1].address = relent->address; 12360484Sobrien relent++; 12460484Sobrien relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; 12560484Sobrien relent->addend = ELF64_R_TYPE_DATA (rela.r_info); 126218822Sdim relent->howto = _bfd_sparc_elf_info_to_howto_ptr (R_SPARC_13); 12760484Sobrien } 12860484Sobrien else 129218822Sdim relent->howto = _bfd_sparc_elf_info_to_howto_ptr (r_type); 13060484Sobrien } 13160484Sobrien 132130561Sobrien canon_reloc_count (asect) += relent - relents; 13360484Sobrien 13460484Sobrien if (allocated != NULL) 13560484Sobrien free (allocated); 13660484Sobrien 137130561Sobrien return TRUE; 13860484Sobrien 13960484Sobrien error_return: 14060484Sobrien if (allocated != NULL) 14160484Sobrien free (allocated); 142130561Sobrien return FALSE; 14360484Sobrien} 14460484Sobrien 14560484Sobrien/* Read in and swap the external relocs. */ 14660484Sobrien 147130561Sobrienstatic bfd_boolean 148218822Sdimelf64_sparc_slurp_reloc_table (bfd *abfd, asection *asect, 149218822Sdim asymbol **symbols, bfd_boolean dynamic) 15060484Sobrien{ 15160484Sobrien struct bfd_elf_section_data * const d = elf_section_data (asect); 15260484Sobrien Elf_Internal_Shdr *rel_hdr; 15360484Sobrien Elf_Internal_Shdr *rel_hdr2; 15489857Sobrien bfd_size_type amt; 15560484Sobrien 15660484Sobrien if (asect->relocation != NULL) 157130561Sobrien return TRUE; 15860484Sobrien 15960484Sobrien if (! dynamic) 16060484Sobrien { 16160484Sobrien if ((asect->flags & SEC_RELOC) == 0 16260484Sobrien || asect->reloc_count == 0) 163130561Sobrien return TRUE; 16460484Sobrien 16560484Sobrien rel_hdr = &d->rel_hdr; 16660484Sobrien rel_hdr2 = d->rel_hdr2; 16760484Sobrien 16860484Sobrien BFD_ASSERT (asect->rel_filepos == rel_hdr->sh_offset 16960484Sobrien || (rel_hdr2 && asect->rel_filepos == rel_hdr2->sh_offset)); 17060484Sobrien } 17160484Sobrien else 17260484Sobrien { 17360484Sobrien /* Note that ASECT->RELOC_COUNT tends not to be accurate in this 17460484Sobrien case because relocations against this section may use the 17560484Sobrien dynamic symbol table, and in that case bfd_section_from_shdr 17660484Sobrien in elf.c does not update the RELOC_COUNT. */ 177218822Sdim if (asect->size == 0) 178130561Sobrien return TRUE; 17960484Sobrien 18060484Sobrien rel_hdr = &d->this_hdr; 18178828Sobrien asect->reloc_count = NUM_SHDR_ENTRIES (rel_hdr); 18260484Sobrien rel_hdr2 = NULL; 18360484Sobrien } 18460484Sobrien 18589857Sobrien amt = asect->reloc_count; 18689857Sobrien amt *= 2 * sizeof (arelent); 18789857Sobrien asect->relocation = (arelent *) bfd_alloc (abfd, amt); 18860484Sobrien if (asect->relocation == NULL) 189130561Sobrien return FALSE; 19060484Sobrien 191218822Sdim /* The elf64_sparc_slurp_one_reloc_table routine increments 192130561Sobrien canon_reloc_count. */ 193130561Sobrien canon_reloc_count (asect) = 0; 19477298Sobrien 195218822Sdim if (!elf64_sparc_slurp_one_reloc_table (abfd, asect, rel_hdr, symbols, 19660484Sobrien dynamic)) 197130561Sobrien return FALSE; 19877298Sobrien 19977298Sobrien if (rel_hdr2 200218822Sdim && !elf64_sparc_slurp_one_reloc_table (abfd, asect, rel_hdr2, symbols, 20160484Sobrien dynamic)) 202130561Sobrien return FALSE; 20360484Sobrien 204130561Sobrien return TRUE; 20560484Sobrien} 20660484Sobrien 207130561Sobrien/* Canonicalize the relocs. */ 208130561Sobrien 209130561Sobrienstatic long 210218822Sdimelf64_sparc_canonicalize_reloc (bfd *abfd, sec_ptr section, 211218822Sdim arelent **relptr, asymbol **symbols) 212130561Sobrien{ 213130561Sobrien arelent *tblptr; 214130561Sobrien unsigned int i; 215130561Sobrien const struct elf_backend_data *bed = get_elf_backend_data (abfd); 216130561Sobrien 217130561Sobrien if (! bed->s->slurp_reloc_table (abfd, section, symbols, FALSE)) 218130561Sobrien return -1; 219130561Sobrien 220130561Sobrien tblptr = section->relocation; 221130561Sobrien for (i = 0; i < canon_reloc_count (section); i++) 222130561Sobrien *relptr++ = tblptr++; 223130561Sobrien 224130561Sobrien *relptr = NULL; 225130561Sobrien 226130561Sobrien return canon_reloc_count (section); 227130561Sobrien} 228130561Sobrien 229130561Sobrien 23060484Sobrien/* Canonicalize the dynamic relocation entries. Note that we return 23160484Sobrien the dynamic relocations as a single block, although they are 23260484Sobrien actually associated with particular sections; the interface, which 23360484Sobrien was designed for SunOS style shared libraries, expects that there 23460484Sobrien is only one set of dynamic relocs. Any section that was actually 23560484Sobrien installed in the BFD, and has type SHT_REL or SHT_RELA, and uses 23660484Sobrien the dynamic symbol table, is considered to be a dynamic reloc 23760484Sobrien section. */ 23860484Sobrien 23960484Sobrienstatic long 240218822Sdimelf64_sparc_canonicalize_dynamic_reloc (bfd *abfd, arelent **storage, 241218822Sdim asymbol **syms) 24260484Sobrien{ 24360484Sobrien asection *s; 24460484Sobrien long ret; 24560484Sobrien 24660484Sobrien if (elf_dynsymtab (abfd) == 0) 24760484Sobrien { 24860484Sobrien bfd_set_error (bfd_error_invalid_operation); 24960484Sobrien return -1; 25060484Sobrien } 25160484Sobrien 25260484Sobrien ret = 0; 25360484Sobrien for (s = abfd->sections; s != NULL; s = s->next) 25460484Sobrien { 25560484Sobrien if (elf_section_data (s)->this_hdr.sh_link == elf_dynsymtab (abfd) 25660484Sobrien && (elf_section_data (s)->this_hdr.sh_type == SHT_RELA)) 25760484Sobrien { 25860484Sobrien arelent *p; 25960484Sobrien long count, i; 26060484Sobrien 261218822Sdim if (! elf64_sparc_slurp_reloc_table (abfd, s, syms, TRUE)) 26260484Sobrien return -1; 263130561Sobrien count = canon_reloc_count (s); 26460484Sobrien p = s->relocation; 26560484Sobrien for (i = 0; i < count; i++) 26660484Sobrien *storage++ = p++; 26760484Sobrien ret += count; 26860484Sobrien } 26960484Sobrien } 27060484Sobrien 27160484Sobrien *storage = NULL; 27260484Sobrien 27360484Sobrien return ret; 27460484Sobrien} 27560484Sobrien 27660484Sobrien/* Write out the relocs. */ 27760484Sobrien 27860484Sobrienstatic void 279218822Sdimelf64_sparc_write_relocs (bfd *abfd, asection *sec, PTR data) 28060484Sobrien{ 281130561Sobrien bfd_boolean *failedp = (bfd_boolean *) data; 28260484Sobrien Elf_Internal_Shdr *rela_hdr; 283218822Sdim bfd_vma addr_offset; 28460484Sobrien Elf64_External_Rela *outbound_relocas, *src_rela; 28560484Sobrien unsigned int idx, count; 28660484Sobrien asymbol *last_sym = 0; 28760484Sobrien int last_sym_idx = 0; 28860484Sobrien 28960484Sobrien /* If we have already failed, don't do anything. */ 29060484Sobrien if (*failedp) 29160484Sobrien return; 29260484Sobrien 29360484Sobrien if ((sec->flags & SEC_RELOC) == 0) 29460484Sobrien return; 29560484Sobrien 29660484Sobrien /* The linker backend writes the relocs out itself, and sets the 29760484Sobrien reloc_count field to zero to inhibit writing them here. Also, 29860484Sobrien sometimes the SEC_RELOC flag gets set even when there aren't any 29960484Sobrien relocs. */ 30060484Sobrien if (sec->reloc_count == 0) 30160484Sobrien return; 30260484Sobrien 30360484Sobrien /* We can combine two relocs that refer to the same address 30460484Sobrien into R_SPARC_OLO10 if first one is R_SPARC_LO10 and the 30560484Sobrien latter is R_SPARC_13 with no associated symbol. */ 30660484Sobrien count = 0; 30760484Sobrien for (idx = 0; idx < sec->reloc_count; idx++) 30860484Sobrien { 30960484Sobrien bfd_vma addr; 31060484Sobrien 31160484Sobrien ++count; 31260484Sobrien 31360484Sobrien addr = sec->orelocation[idx]->address; 31460484Sobrien if (sec->orelocation[idx]->howto->type == R_SPARC_LO10 31560484Sobrien && idx < sec->reloc_count - 1) 31660484Sobrien { 31760484Sobrien arelent *r = sec->orelocation[idx + 1]; 31860484Sobrien 31960484Sobrien if (r->howto->type == R_SPARC_13 32060484Sobrien && r->address == addr 32160484Sobrien && bfd_is_abs_section ((*r->sym_ptr_ptr)->section) 32260484Sobrien && (*r->sym_ptr_ptr)->value == 0) 32360484Sobrien ++idx; 32460484Sobrien } 32560484Sobrien } 32660484Sobrien 32760484Sobrien rela_hdr = &elf_section_data (sec)->rel_hdr; 32860484Sobrien 32960484Sobrien rela_hdr->sh_size = rela_hdr->sh_entsize * count; 33060484Sobrien rela_hdr->contents = (PTR) bfd_alloc (abfd, rela_hdr->sh_size); 33160484Sobrien if (rela_hdr->contents == NULL) 33260484Sobrien { 333130561Sobrien *failedp = TRUE; 33460484Sobrien return; 33560484Sobrien } 33660484Sobrien 33760484Sobrien /* Figure out whether the relocations are RELA or REL relocations. */ 33860484Sobrien if (rela_hdr->sh_type != SHT_RELA) 33960484Sobrien abort (); 34060484Sobrien 341218822Sdim /* The address of an ELF reloc is section relative for an object 342218822Sdim file, and absolute for an executable file or shared library. 343218822Sdim The address of a BFD reloc is always section relative. */ 344218822Sdim addr_offset = 0; 345218822Sdim if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0) 346218822Sdim addr_offset = sec->vma; 347218822Sdim 34877298Sobrien /* orelocation has the data, reloc_count has the count... */ 34960484Sobrien outbound_relocas = (Elf64_External_Rela *) rela_hdr->contents; 35060484Sobrien src_rela = outbound_relocas; 35160484Sobrien 35260484Sobrien for (idx = 0; idx < sec->reloc_count; idx++) 35360484Sobrien { 35460484Sobrien Elf_Internal_Rela dst_rela; 35560484Sobrien arelent *ptr; 35660484Sobrien asymbol *sym; 35760484Sobrien int n; 35860484Sobrien 35960484Sobrien ptr = sec->orelocation[idx]; 36060484Sobrien sym = *ptr->sym_ptr_ptr; 36160484Sobrien if (sym == last_sym) 36260484Sobrien n = last_sym_idx; 36360484Sobrien else if (bfd_is_abs_section (sym->section) && sym->value == 0) 36460484Sobrien n = STN_UNDEF; 36560484Sobrien else 36660484Sobrien { 36760484Sobrien last_sym = sym; 36860484Sobrien n = _bfd_elf_symbol_from_bfd_symbol (abfd, &sym); 36960484Sobrien if (n < 0) 37060484Sobrien { 371130561Sobrien *failedp = TRUE; 37260484Sobrien return; 37360484Sobrien } 37460484Sobrien last_sym_idx = n; 37560484Sobrien } 37660484Sobrien 37760484Sobrien if ((*ptr->sym_ptr_ptr)->the_bfd != NULL 37860484Sobrien && (*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec 37960484Sobrien && ! _bfd_elf_validate_reloc (abfd, ptr)) 38060484Sobrien { 381130561Sobrien *failedp = TRUE; 38260484Sobrien return; 38360484Sobrien } 38460484Sobrien 38560484Sobrien if (ptr->howto->type == R_SPARC_LO10 38660484Sobrien && idx < sec->reloc_count - 1) 38760484Sobrien { 38860484Sobrien arelent *r = sec->orelocation[idx + 1]; 38960484Sobrien 39060484Sobrien if (r->howto->type == R_SPARC_13 39160484Sobrien && r->address == ptr->address 39260484Sobrien && bfd_is_abs_section ((*r->sym_ptr_ptr)->section) 39360484Sobrien && (*r->sym_ptr_ptr)->value == 0) 39460484Sobrien { 39560484Sobrien idx++; 39660484Sobrien dst_rela.r_info 39760484Sobrien = ELF64_R_INFO (n, ELF64_R_TYPE_INFO (r->addend, 39860484Sobrien R_SPARC_OLO10)); 39960484Sobrien } 40060484Sobrien else 40160484Sobrien dst_rela.r_info = ELF64_R_INFO (n, R_SPARC_LO10); 40260484Sobrien } 40360484Sobrien else 40460484Sobrien dst_rela.r_info = ELF64_R_INFO (n, ptr->howto->type); 40560484Sobrien 406218822Sdim dst_rela.r_offset = ptr->address + addr_offset; 40760484Sobrien dst_rela.r_addend = ptr->addend; 408218822Sdim 409130561Sobrien bfd_elf64_swap_reloca_out (abfd, &dst_rela, (bfd_byte *) src_rela); 41060484Sobrien ++src_rela; 41160484Sobrien } 41260484Sobrien} 41360484Sobrien 41460484Sobrien/* Hook called by the linker routine which adds symbols from an object 41560484Sobrien file. We use it for STT_REGISTER symbols. */ 41660484Sobrien 417130561Sobrienstatic bfd_boolean 418218822Sdimelf64_sparc_add_symbol_hook (bfd *abfd, struct bfd_link_info *info, 419218822Sdim Elf_Internal_Sym *sym, const char **namep, 420218822Sdim flagword *flagsp ATTRIBUTE_UNUSED, 421218822Sdim asection **secp ATTRIBUTE_UNUSED, 422218822Sdim bfd_vma *valp ATTRIBUTE_UNUSED) 42360484Sobrien{ 42489857Sobrien static const char *const stt_types[] = { "NOTYPE", "OBJECT", "FUNCTION" }; 42560484Sobrien 42660484Sobrien if (ELF_ST_TYPE (sym->st_info) == STT_REGISTER) 42760484Sobrien { 42860484Sobrien int reg; 429218822Sdim struct _bfd_sparc_elf_app_reg *p; 43077298Sobrien 43160484Sobrien reg = (int)sym->st_value; 43260484Sobrien switch (reg & ~1) 43360484Sobrien { 43460484Sobrien case 2: reg -= 2; break; 43560484Sobrien case 6: reg -= 4; break; 43660484Sobrien default: 43760484Sobrien (*_bfd_error_handler) 438218822Sdim (_("%B: Only registers %%g[2367] can be declared using STT_REGISTER"), 439218822Sdim abfd); 440130561Sobrien return FALSE; 44160484Sobrien } 44260484Sobrien 44360484Sobrien if (info->hash->creator != abfd->xvec 44460484Sobrien || (abfd->flags & DYNAMIC) != 0) 44560484Sobrien { 44660484Sobrien /* STT_REGISTER only works when linking an elf64_sparc object. 44760484Sobrien If STT_REGISTER comes from a dynamic object, don't put it into 44860484Sobrien the output bfd. The dynamic linker will recheck it. */ 44960484Sobrien *namep = NULL; 450130561Sobrien return TRUE; 45160484Sobrien } 45260484Sobrien 453218822Sdim p = _bfd_sparc_elf_hash_table(info)->app_regs + reg; 45460484Sobrien 45560484Sobrien if (p->name != NULL && strcmp (p->name, *namep)) 45660484Sobrien { 45760484Sobrien (*_bfd_error_handler) 458218822Sdim (_("Register %%g%d used incompatibly: %s in %B, previously %s in %B"), 459218822Sdim abfd, p->abfd, (int) sym->st_value, 460218822Sdim **namep ? *namep : "#scratch", 461218822Sdim *p->name ? p->name : "#scratch"); 462130561Sobrien return FALSE; 46360484Sobrien } 46460484Sobrien 46560484Sobrien if (p->name == NULL) 46660484Sobrien { 46760484Sobrien if (**namep) 46860484Sobrien { 46960484Sobrien struct elf_link_hash_entry *h; 47077298Sobrien 47160484Sobrien h = (struct elf_link_hash_entry *) 472130561Sobrien bfd_link_hash_lookup (info->hash, *namep, FALSE, FALSE, FALSE); 47360484Sobrien 47460484Sobrien if (h != NULL) 47560484Sobrien { 47660484Sobrien unsigned char type = h->type; 47760484Sobrien 47889857Sobrien if (type > STT_FUNC) 47989857Sobrien type = 0; 48060484Sobrien (*_bfd_error_handler) 481218822Sdim (_("Symbol `%s' has differing types: REGISTER in %B, previously %s in %B"), 482218822Sdim abfd, p->abfd, *namep, stt_types[type]); 483130561Sobrien return FALSE; 48460484Sobrien } 48560484Sobrien 48660484Sobrien p->name = bfd_hash_allocate (&info->hash->table, 48760484Sobrien strlen (*namep) + 1); 48860484Sobrien if (!p->name) 489130561Sobrien return FALSE; 49060484Sobrien 49160484Sobrien strcpy (p->name, *namep); 49260484Sobrien } 49360484Sobrien else 49460484Sobrien p->name = ""; 49560484Sobrien p->bind = ELF_ST_BIND (sym->st_info); 49660484Sobrien p->abfd = abfd; 49760484Sobrien p->shndx = sym->st_shndx; 49860484Sobrien } 49960484Sobrien else 50060484Sobrien { 50160484Sobrien if (p->bind == STB_WEAK 50260484Sobrien && ELF_ST_BIND (sym->st_info) == STB_GLOBAL) 50360484Sobrien { 50460484Sobrien p->bind = STB_GLOBAL; 50560484Sobrien p->abfd = abfd; 50660484Sobrien } 50760484Sobrien } 50860484Sobrien *namep = NULL; 509130561Sobrien return TRUE; 51060484Sobrien } 51199461Sobrien else if (*namep && **namep 512104834Sobrien && info->hash->creator == abfd->xvec) 51360484Sobrien { 51460484Sobrien int i; 515218822Sdim struct _bfd_sparc_elf_app_reg *p; 51660484Sobrien 517218822Sdim p = _bfd_sparc_elf_hash_table(info)->app_regs; 51860484Sobrien for (i = 0; i < 4; i++, p++) 51960484Sobrien if (p->name != NULL && ! strcmp (p->name, *namep)) 52060484Sobrien { 52160484Sobrien unsigned char type = ELF_ST_TYPE (sym->st_info); 52260484Sobrien 52389857Sobrien if (type > STT_FUNC) 52489857Sobrien type = 0; 52560484Sobrien (*_bfd_error_handler) 526218822Sdim (_("Symbol `%s' has differing types: %s in %B, previously REGISTER in %B"), 527218822Sdim abfd, p->abfd, *namep, stt_types[type]); 528130561Sobrien return FALSE; 52960484Sobrien } 53060484Sobrien } 531130561Sobrien return TRUE; 53260484Sobrien} 53360484Sobrien 534130561Sobrien/* This function takes care of emitting STT_REGISTER symbols 53560484Sobrien which we cannot easily keep in the symbol hash table. */ 53660484Sobrien 537130561Sobrienstatic bfd_boolean 538218822Sdimelf64_sparc_output_arch_syms (bfd *output_bfd ATTRIBUTE_UNUSED, 539218822Sdim struct bfd_link_info *info, 540218822Sdim PTR finfo, bfd_boolean (*func) (PTR, const char *, 541218822Sdim Elf_Internal_Sym *, 542218822Sdim asection *, 543218822Sdim struct elf_link_hash_entry *)) 54460484Sobrien{ 54560484Sobrien int reg; 546218822Sdim struct _bfd_sparc_elf_app_reg *app_regs = 547218822Sdim _bfd_sparc_elf_hash_table(info)->app_regs; 54860484Sobrien Elf_Internal_Sym sym; 54960484Sobrien 55060484Sobrien /* We arranged in size_dynamic_sections to put the STT_REGISTER entries 55160484Sobrien at the end of the dynlocal list, so they came at the end of the local 55260484Sobrien symbols in the symtab. Except that they aren't STB_LOCAL, so we need 55360484Sobrien to back up symtab->sh_info. */ 55460484Sobrien if (elf_hash_table (info)->dynlocal) 55560484Sobrien { 55660484Sobrien bfd * dynobj = elf_hash_table (info)->dynobj; 55760484Sobrien asection *dynsymsec = bfd_get_section_by_name (dynobj, ".dynsym"); 55860484Sobrien struct elf_link_local_dynamic_entry *e; 55960484Sobrien 56060484Sobrien for (e = elf_hash_table (info)->dynlocal; e ; e = e->next) 56160484Sobrien if (e->input_indx == -1) 56260484Sobrien break; 56360484Sobrien if (e) 56460484Sobrien { 56560484Sobrien elf_section_data (dynsymsec->output_section)->this_hdr.sh_info 56660484Sobrien = e->dynindx; 56760484Sobrien } 56860484Sobrien } 56960484Sobrien 57060484Sobrien if (info->strip == strip_all) 571130561Sobrien return TRUE; 57260484Sobrien 57360484Sobrien for (reg = 0; reg < 4; reg++) 57460484Sobrien if (app_regs [reg].name != NULL) 57560484Sobrien { 57660484Sobrien if (info->strip == strip_some 57760484Sobrien && bfd_hash_lookup (info->keep_hash, 57860484Sobrien app_regs [reg].name, 579130561Sobrien FALSE, FALSE) == NULL) 58060484Sobrien continue; 58160484Sobrien 58260484Sobrien sym.st_value = reg < 2 ? reg + 2 : reg + 4; 58360484Sobrien sym.st_size = 0; 58460484Sobrien sym.st_other = 0; 58560484Sobrien sym.st_info = ELF_ST_INFO (app_regs [reg].bind, STT_REGISTER); 58660484Sobrien sym.st_shndx = app_regs [reg].shndx; 58760484Sobrien if (! (*func) (finfo, app_regs [reg].name, &sym, 58860484Sobrien sym.st_shndx == SHN_ABS 589130561Sobrien ? bfd_abs_section_ptr : bfd_und_section_ptr, 590130561Sobrien NULL)) 591130561Sobrien return FALSE; 59260484Sobrien } 59360484Sobrien 594130561Sobrien return TRUE; 59560484Sobrien} 59660484Sobrien 59760484Sobrienstatic int 598218822Sdimelf64_sparc_get_symbol_type (Elf_Internal_Sym *elf_sym, int type) 59960484Sobrien{ 60060484Sobrien if (ELF_ST_TYPE (elf_sym->st_info) == STT_REGISTER) 60160484Sobrien return STT_REGISTER; 60260484Sobrien else 60360484Sobrien return type; 60460484Sobrien} 60560484Sobrien 60660484Sobrien/* A STB_GLOBAL,STT_REGISTER symbol should be BSF_GLOBAL 60760484Sobrien even in SHN_UNDEF section. */ 60860484Sobrien 60960484Sobrienstatic void 610218822Sdimelf64_sparc_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED, asymbol *asym) 61160484Sobrien{ 61260484Sobrien elf_symbol_type *elfsym; 61360484Sobrien 61460484Sobrien elfsym = (elf_symbol_type *) asym; 61560484Sobrien if (elfsym->internal_elf_sym.st_info 61660484Sobrien == ELF_ST_INFO (STB_GLOBAL, STT_REGISTER)) 61760484Sobrien { 61860484Sobrien asym->flags |= BSF_GLOBAL; 61960484Sobrien } 62060484Sobrien} 62160484Sobrien 62259024Sobrien 62389857Sobrien/* Functions for dealing with the e_flags field. */ 62478828Sobrien 62559024Sobrien/* Merge backend specific data from an object file to the output 62659024Sobrien object file when linking. */ 62759024Sobrien 628130561Sobrienstatic bfd_boolean 629218822Sdimelf64_sparc_merge_private_bfd_data (bfd *ibfd, bfd *obfd) 63059024Sobrien{ 631130561Sobrien bfd_boolean error; 63259024Sobrien flagword new_flags, old_flags; 63359024Sobrien int new_mm, old_mm; 63459024Sobrien 63559024Sobrien if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour 63659024Sobrien || bfd_get_flavour (obfd) != bfd_target_elf_flavour) 637130561Sobrien return TRUE; 63859024Sobrien 63959024Sobrien new_flags = elf_elfheader (ibfd)->e_flags; 64059024Sobrien old_flags = elf_elfheader (obfd)->e_flags; 64159024Sobrien 64259024Sobrien if (!elf_flags_init (obfd)) /* First call, no flags set */ 64359024Sobrien { 644130561Sobrien elf_flags_init (obfd) = TRUE; 64559024Sobrien elf_elfheader (obfd)->e_flags = new_flags; 64659024Sobrien } 64777298Sobrien 64859024Sobrien else if (new_flags == old_flags) /* Compatible flags are ok */ 64959024Sobrien ; 65077298Sobrien 65159024Sobrien else /* Incompatible flags */ 65259024Sobrien { 653130561Sobrien error = FALSE; 65477298Sobrien 65577298Sobrien#define EF_SPARC_ISA_EXTENSIONS \ 65677298Sobrien (EF_SPARC_SUN_US1 | EF_SPARC_SUN_US3 | EF_SPARC_HAL_R1) 65777298Sobrien 65860484Sobrien if ((ibfd->flags & DYNAMIC) != 0) 65960484Sobrien { 66060484Sobrien /* We don't want dynamic objects memory ordering and 66160484Sobrien architecture to have any role. That's what dynamic linker 66260484Sobrien should do. */ 66377298Sobrien new_flags &= ~(EF_SPARCV9_MM | EF_SPARC_ISA_EXTENSIONS); 66477298Sobrien new_flags |= (old_flags 66577298Sobrien & (EF_SPARCV9_MM | EF_SPARC_ISA_EXTENSIONS)); 66660484Sobrien } 66760484Sobrien else 66860484Sobrien { 66960484Sobrien /* Choose the highest architecture requirements. */ 67077298Sobrien old_flags |= (new_flags & EF_SPARC_ISA_EXTENSIONS); 67177298Sobrien new_flags |= (old_flags & EF_SPARC_ISA_EXTENSIONS); 67277298Sobrien if ((old_flags & (EF_SPARC_SUN_US1 | EF_SPARC_SUN_US3)) 67377298Sobrien && (old_flags & EF_SPARC_HAL_R1)) 67460484Sobrien { 675130561Sobrien error = TRUE; 67660484Sobrien (*_bfd_error_handler) 677218822Sdim (_("%B: linking UltraSPARC specific with HAL specific code"), 678218822Sdim ibfd); 67960484Sobrien } 68060484Sobrien /* Choose the most restrictive memory ordering. */ 68160484Sobrien old_mm = (old_flags & EF_SPARCV9_MM); 68260484Sobrien new_mm = (new_flags & EF_SPARCV9_MM); 68360484Sobrien old_flags &= ~EF_SPARCV9_MM; 68460484Sobrien new_flags &= ~EF_SPARCV9_MM; 68560484Sobrien if (new_mm < old_mm) 68660484Sobrien old_mm = new_mm; 68760484Sobrien old_flags |= old_mm; 68860484Sobrien new_flags |= old_mm; 68960484Sobrien } 69059024Sobrien 69159024Sobrien /* Warn about any other mismatches */ 69259024Sobrien if (new_flags != old_flags) 69359024Sobrien { 694130561Sobrien error = TRUE; 69559024Sobrien (*_bfd_error_handler) 696218822Sdim (_("%B: uses different e_flags (0x%lx) fields than previous modules (0x%lx)"), 697218822Sdim ibfd, (long) new_flags, (long) old_flags); 69859024Sobrien } 69959024Sobrien 70059024Sobrien elf_elfheader (obfd)->e_flags = old_flags; 70159024Sobrien 70259024Sobrien if (error) 70359024Sobrien { 70459024Sobrien bfd_set_error (bfd_error_bad_value); 705130561Sobrien return FALSE; 70659024Sobrien } 70759024Sobrien } 708130561Sobrien return TRUE; 70959024Sobrien} 710104834Sobrien 711104834Sobrien/* MARCO: Set the correct entry size for the .stab section. */ 712104834Sobrien 713130561Sobrienstatic bfd_boolean 714218822Sdimelf64_sparc_fake_sections (bfd *abfd ATTRIBUTE_UNUSED, 715218822Sdim Elf_Internal_Shdr *hdr ATTRIBUTE_UNUSED, 716218822Sdim asection *sec) 717104834Sobrien{ 718104834Sobrien const char *name; 719104834Sobrien 720104834Sobrien name = bfd_get_section_name (abfd, sec); 721104834Sobrien 722104834Sobrien if (strcmp (name, ".stab") == 0) 723104834Sobrien { 724104834Sobrien /* Even in the 64bit case the stab entries are only 12 bytes long. */ 725104834Sobrien elf_section_data (sec)->this_hdr.sh_entsize = 12; 726104834Sobrien } 727130561Sobrien 728130561Sobrien return TRUE; 729104834Sobrien} 73060484Sobrien 73160484Sobrien/* Print a STT_REGISTER symbol to file FILE. */ 73259024Sobrien 73360484Sobrienstatic const char * 734218822Sdimelf64_sparc_print_symbol_all (bfd *abfd ATTRIBUTE_UNUSED, PTR filep, 735218822Sdim asymbol *symbol) 73660484Sobrien{ 73760484Sobrien FILE *file = (FILE *) filep; 73860484Sobrien int reg, type; 73977298Sobrien 74060484Sobrien if (ELF_ST_TYPE (((elf_symbol_type *) symbol)->internal_elf_sym.st_info) 74160484Sobrien != STT_REGISTER) 74260484Sobrien return NULL; 74360484Sobrien 74460484Sobrien reg = ((elf_symbol_type *) symbol)->internal_elf_sym.st_value; 74560484Sobrien type = symbol->flags; 74660484Sobrien fprintf (file, "REG_%c%c%11s%c%c R", "GOLI" [reg / 8], '0' + (reg & 7), "", 74760484Sobrien ((type & BSF_LOCAL) 74860484Sobrien ? (type & BSF_GLOBAL) ? '!' : 'l' 74989857Sobrien : (type & BSF_GLOBAL) ? 'g' : ' '), 75089857Sobrien (type & BSF_WEAK) ? 'w' : ' '); 75160484Sobrien if (symbol->name == NULL || symbol->name [0] == '\0') 75260484Sobrien return "#scratch"; 75360484Sobrien else 75460484Sobrien return symbol->name; 75560484Sobrien} 75659024Sobrien 757218822Sdimstatic enum elf_reloc_type_class 758218822Sdimelf64_sparc_reloc_type_class (const Elf_Internal_Rela *rela) 75959024Sobrien{ 760218822Sdim switch ((int) ELF64_R_TYPE (rela->r_info)) 761218822Sdim { 762218822Sdim case R_SPARC_RELATIVE: 763218822Sdim return reloc_class_relative; 764218822Sdim case R_SPARC_JMP_SLOT: 765218822Sdim return reloc_class_plt; 766218822Sdim case R_SPARC_COPY: 767218822Sdim return reloc_class_copy; 768218822Sdim default: 769218822Sdim return reloc_class_normal; 770218822Sdim } 77159024Sobrien} 77259024Sobrien 77360484Sobrien/* Relocations in the 64 bit SPARC ELF ABI are more complex than in 77460484Sobrien standard ELF, because R_SPARC_OLO10 has secondary addend in 77560484Sobrien ELF64_R_TYPE_DATA field. This structure is used to redirect the 77660484Sobrien relocation handling routines. */ 77760484Sobrien 778218822Sdimconst struct elf_size_info elf64_sparc_size_info = 77960484Sobrien{ 78060484Sobrien sizeof (Elf64_External_Ehdr), 78160484Sobrien sizeof (Elf64_External_Phdr), 78260484Sobrien sizeof (Elf64_External_Shdr), 78360484Sobrien sizeof (Elf64_External_Rel), 78460484Sobrien sizeof (Elf64_External_Rela), 78560484Sobrien sizeof (Elf64_External_Sym), 78660484Sobrien sizeof (Elf64_External_Dyn), 78760484Sobrien sizeof (Elf_External_Note), 788130561Sobrien 4, /* hash-table entry size. */ 789130561Sobrien /* Internal relocations per external relocations. 79060484Sobrien For link purposes we use just 1 internal per 79160484Sobrien 1 external, for assembly and slurp symbol table 79277298Sobrien we use 2. */ 79360484Sobrien 1, 794130561Sobrien 64, /* arch_size. */ 795130561Sobrien 3, /* log_file_align. */ 79660484Sobrien ELFCLASS64, 79760484Sobrien EV_CURRENT, 79860484Sobrien bfd_elf64_write_out_phdrs, 79960484Sobrien bfd_elf64_write_shdrs_and_ehdr, 800218822Sdim elf64_sparc_write_relocs, 801104834Sobrien bfd_elf64_swap_symbol_in, 80260484Sobrien bfd_elf64_swap_symbol_out, 803218822Sdim elf64_sparc_slurp_reloc_table, 80460484Sobrien bfd_elf64_slurp_symbol_table, 80560484Sobrien bfd_elf64_swap_dyn_in, 80660484Sobrien bfd_elf64_swap_dyn_out, 807130561Sobrien bfd_elf64_swap_reloc_in, 808130561Sobrien bfd_elf64_swap_reloc_out, 809130561Sobrien bfd_elf64_swap_reloca_in, 810130561Sobrien bfd_elf64_swap_reloca_out 81160484Sobrien}; 81260484Sobrien 81359024Sobrien#define TARGET_BIG_SYM bfd_elf64_sparc_vec 81459024Sobrien#define TARGET_BIG_NAME "elf64-sparc" 81559024Sobrien#define ELF_ARCH bfd_arch_sparc 81659024Sobrien#define ELF_MAXPAGESIZE 0x100000 817218822Sdim#define ELF_COMMONPAGESIZE 0x2000 81859024Sobrien 81960484Sobrien/* This is the official ABI value. */ 82060484Sobrien#define ELF_MACHINE_CODE EM_SPARCV9 82160484Sobrien 82260484Sobrien/* This is the value that we used before the ABI was released. */ 82360484Sobrien#define ELF_MACHINE_ALT1 EM_OLD_SPARCV9 82460484Sobrien 825218822Sdim#define elf_backend_reloc_type_class \ 826218822Sdim elf64_sparc_reloc_type_class 82760484Sobrien#define bfd_elf64_get_reloc_upper_bound \ 828218822Sdim elf64_sparc_get_reloc_upper_bound 82960484Sobrien#define bfd_elf64_get_dynamic_reloc_upper_bound \ 830218822Sdim elf64_sparc_get_dynamic_reloc_upper_bound 831130561Sobrien#define bfd_elf64_canonicalize_reloc \ 832218822Sdim elf64_sparc_canonicalize_reloc 83360484Sobrien#define bfd_elf64_canonicalize_dynamic_reloc \ 834218822Sdim elf64_sparc_canonicalize_dynamic_reloc 835218822Sdim#define elf_backend_add_symbol_hook \ 836218822Sdim elf64_sparc_add_symbol_hook 837218822Sdim#define elf_backend_get_symbol_type \ 838218822Sdim elf64_sparc_get_symbol_type 839218822Sdim#define elf_backend_symbol_processing \ 840218822Sdim elf64_sparc_symbol_processing 841218822Sdim#define elf_backend_print_symbol_all \ 842218822Sdim elf64_sparc_print_symbol_all 843218822Sdim#define elf_backend_output_arch_syms \ 844218822Sdim elf64_sparc_output_arch_syms 845218822Sdim#define bfd_elf64_bfd_merge_private_bfd_data \ 846218822Sdim elf64_sparc_merge_private_bfd_data 847218822Sdim#define elf_backend_fake_sections \ 848218822Sdim elf64_sparc_fake_sections 849218822Sdim#define elf_backend_size_info \ 850218822Sdim elf64_sparc_size_info 851218822Sdim 852218822Sdim#define elf_backend_plt_sym_val \ 853218822Sdim _bfd_sparc_elf_plt_sym_val 854218822Sdim#define bfd_elf64_bfd_link_hash_table_create \ 855218822Sdim _bfd_sparc_elf_link_hash_table_create 856218822Sdim#define elf_info_to_howto \ 857218822Sdim _bfd_sparc_elf_info_to_howto 858218822Sdim#define elf_backend_copy_indirect_symbol \ 859218822Sdim _bfd_sparc_elf_copy_indirect_symbol 86059024Sobrien#define bfd_elf64_bfd_reloc_type_lookup \ 861218822Sdim _bfd_sparc_elf_reloc_type_lookup 862218822Sdim#define bfd_elf64_bfd_reloc_name_lookup \ 863218822Sdim _bfd_sparc_elf_reloc_name_lookup 86477298Sobrien#define bfd_elf64_bfd_relax_section \ 865218822Sdim _bfd_sparc_elf_relax_section 866130561Sobrien#define bfd_elf64_new_section_hook \ 867218822Sdim _bfd_sparc_elf_new_section_hook 86859024Sobrien 86959024Sobrien#define elf_backend_create_dynamic_sections \ 870218822Sdim _bfd_sparc_elf_create_dynamic_sections 871218822Sdim#define elf_backend_relocs_compatible \ 872218822Sdim _bfd_elf_relocs_compatible 87359024Sobrien#define elf_backend_check_relocs \ 874218822Sdim _bfd_sparc_elf_check_relocs 87559024Sobrien#define elf_backend_adjust_dynamic_symbol \ 876218822Sdim _bfd_sparc_elf_adjust_dynamic_symbol 877218822Sdim#define elf_backend_omit_section_dynsym \ 878218822Sdim _bfd_sparc_elf_omit_section_dynsym 87959024Sobrien#define elf_backend_size_dynamic_sections \ 880218822Sdim _bfd_sparc_elf_size_dynamic_sections 88159024Sobrien#define elf_backend_relocate_section \ 882218822Sdim _bfd_sparc_elf_relocate_section 88359024Sobrien#define elf_backend_finish_dynamic_symbol \ 884218822Sdim _bfd_sparc_elf_finish_dynamic_symbol 88559024Sobrien#define elf_backend_finish_dynamic_sections \ 886218822Sdim _bfd_sparc_elf_finish_dynamic_sections 88759024Sobrien 888218822Sdim#define bfd_elf64_mkobject \ 889218822Sdim _bfd_sparc_elf_mkobject 89059024Sobrien#define elf_backend_object_p \ 891218822Sdim _bfd_sparc_elf_object_p 892218822Sdim#define elf_backend_gc_mark_hook \ 893218822Sdim _bfd_sparc_elf_gc_mark_hook 894218822Sdim#define elf_backend_gc_sweep_hook \ 895218822Sdim _bfd_sparc_elf_gc_sweep_hook 896218822Sdim#define elf_backend_init_index_section \ 897218822Sdim _bfd_elf_init_1_index_section 89859024Sobrien 899218822Sdim#define elf_backend_can_gc_sections 1 900218822Sdim#define elf_backend_can_refcount 1 90159024Sobrien#define elf_backend_want_got_plt 0 90259024Sobrien#define elf_backend_plt_readonly 0 90359024Sobrien#define elf_backend_want_plt_sym 1 904218822Sdim#define elf_backend_got_header_size 8 905130561Sobrien#define elf_backend_rela_normal 1 90659024Sobrien 90759024Sobrien/* Section 5.2.4 of the ABI specifies a 256-byte boundary for the table. */ 90859024Sobrien#define elf_backend_plt_alignment 8 90959024Sobrien 910218822Sdim#include "elf64-target.h" 91160484Sobrien 912218822Sdim/* FreeBSD support */ 913218822Sdim#undef TARGET_BIG_SYM 914218822Sdim#define TARGET_BIG_SYM bfd_elf64_sparc_freebsd_vec 915218822Sdim#undef TARGET_BIG_NAME 916218822Sdim#define TARGET_BIG_NAME "elf64-sparc-freebsd" 917218822Sdim#undef ELF_OSABI 918218822Sdim#define ELF_OSABI ELFOSABI_FREEBSD 919218822Sdim 920218822Sdim#undef elf_backend_post_process_headers 921218822Sdim#define elf_backend_post_process_headers _bfd_elf_set_osabi 922218822Sdim#undef elf64_bed 923218822Sdim#define elf64_bed elf64_sparc_fbsd_bed 924218822Sdim 92559024Sobrien#include "elf64-target.h" 926218822Sdim 927