diff options
Diffstat (limited to 'contrib/binutils/bfd/elf64-sparc.c')
-rw-r--r-- | contrib/binutils/bfd/elf64-sparc.c | 1064 |
1 files changed, 904 insertions, 160 deletions
diff --git a/contrib/binutils/bfd/elf64-sparc.c b/contrib/binutils/bfd/elf64-sparc.c index 85dabaa..46e7775 100644 --- a/contrib/binutils/bfd/elf64-sparc.c +++ b/contrib/binutils/bfd/elf64-sparc.c @@ -1,5 +1,6 @@ /* SPARC-specific support for 64-bit ELF - Copyright (C) 1993, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + Copyright (C) 1993, 95, 96, 97, 98, 99, 2000 + Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -32,6 +33,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* In case we're on a 32-bit machine, construct a 64-bit "-1" value. */ #define MINUS_ONE (~ (bfd_vma) 0) +static struct bfd_link_hash_table * sparc64_elf_bfd_link_hash_table_create + PARAMS((bfd *)); static reloc_howto_type *sparc64_elf_reloc_type_lookup PARAMS ((bfd *, bfd_reloc_code_real_type)); static void sparc64_elf_info_to_howto @@ -51,8 +54,13 @@ static boolean sparc64_elf_adjust_dynamic_symbol PARAMS((struct bfd_link_info *, struct elf_link_hash_entry *)); static boolean sparc64_elf_size_dynamic_sections PARAMS((bfd *, struct bfd_link_info *)); -static boolean sparc64_elf_adjust_dynindx - PARAMS((struct elf_link_hash_entry *, PTR)); +static int sparc64_elf_get_symbol_type + PARAMS (( Elf_Internal_Sym *, int)); +static boolean sparc64_elf_add_symbol_hook + PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Sym *, + const char **, flagword *, asection **, bfd_vma *)); +static void sparc64_elf_symbol_processing + PARAMS ((bfd *, asymbol *)); static boolean sparc64_elf_merge_private_bfd_data PARAMS ((bfd *, bfd *)); @@ -61,6 +69,15 @@ static boolean sparc64_elf_relocate_section PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, Elf_Internal_Rela *, Elf_Internal_Sym *, asection **)); static boolean sparc64_elf_object_p PARAMS ((bfd *)); +static long sparc64_elf_get_reloc_upper_bound PARAMS ((bfd *, asection *)); +static long sparc64_elf_get_dynamic_reloc_upper_bound PARAMS ((bfd *)); +static boolean sparc64_elf_slurp_one_reloc_table + PARAMS ((bfd *, asection *, Elf_Internal_Shdr *, asymbol **, boolean)); +static boolean sparc64_elf_slurp_reloc_table + PARAMS ((bfd *, asection *, asymbol **, boolean)); +static long sparc64_elf_canonicalize_dynamic_reloc + PARAMS ((bfd *, arelent **, asymbol **)); +static void sparc64_elf_write_relocs PARAMS ((bfd *, asection *, PTR)); /* The relocation "howto" table. */ @@ -137,7 +154,7 @@ static reloc_howto_type sparc64_elf_howto_table[] = }; struct elf_reloc_map { - unsigned char bfd_reloc_val; + bfd_reloc_code_real_type bfd_reloc_val; unsigned char elf_reloc_val; }; @@ -213,10 +230,428 @@ sparc64_elf_info_to_howto (abfd, cache_ptr, dst) arelent *cache_ptr; Elf64_Internal_Rela *dst; { - BFD_ASSERT (ELF64_R_TYPE (dst->r_info) < (unsigned int) R_SPARC_max); - cache_ptr->howto = &sparc64_elf_howto_table[ELF64_R_TYPE (dst->r_info)]; + BFD_ASSERT (ELF64_R_TYPE_ID (dst->r_info) < (unsigned int) R_SPARC_max_std); + cache_ptr->howto = &sparc64_elf_howto_table[ELF64_R_TYPE_ID (dst->r_info)]; } +/* Due to the way how we handle R_SPARC_OLO10, each entry in a SHT_RELA + section can represent up to two relocs, we must tell the user to allocate + more space. */ + +static long +sparc64_elf_get_reloc_upper_bound (abfd, sec) + bfd *abfd; + asection *sec; +{ + return (sec->reloc_count * 2 + 1) * sizeof (arelent *); +} + +static long +sparc64_elf_get_dynamic_reloc_upper_bound (abfd) + bfd *abfd; +{ + return _bfd_elf_get_dynamic_reloc_upper_bound (abfd) * 2; +} + +/* Read relocations for ASECT from REL_HDR. There are RELOC_COUNT of + them. We cannot use generic elf routines for this, because R_SPARC_OLO10 + has secondary addend in ELF64_R_TYPE_DATA. We handle it as two relocations + for the same location, R_SPARC_LO10 and R_SPARC_13. */ + +static boolean +sparc64_elf_slurp_one_reloc_table (abfd, asect, rel_hdr, symbols, dynamic) + bfd *abfd; + asection *asect; + Elf_Internal_Shdr *rel_hdr; + asymbol **symbols; + boolean dynamic; +{ + struct elf_backend_data * const ebd = get_elf_backend_data (abfd); + PTR allocated = NULL; + bfd_byte *native_relocs; + arelent *relent; + unsigned int i; + int entsize; + bfd_size_type count; + arelent *relents; + + allocated = (PTR) bfd_malloc ((size_t) rel_hdr->sh_size); + if (allocated == NULL) + goto error_return; + + if (bfd_seek (abfd, rel_hdr->sh_offset, SEEK_SET) != 0 + || (bfd_read (allocated, 1, rel_hdr->sh_size, abfd) + != rel_hdr->sh_size)) + goto error_return; + + native_relocs = (bfd_byte *) allocated; + + relents = asect->relocation + asect->reloc_count; + + entsize = rel_hdr->sh_entsize; + BFD_ASSERT (entsize == sizeof (Elf64_External_Rela)); + + count = rel_hdr->sh_size / entsize; + + for (i = 0, relent = relents; i < count; + i++, relent++, native_relocs += entsize) + { + Elf_Internal_Rela rela; + + bfd_elf64_swap_reloca_in (abfd, (Elf64_External_Rela *) native_relocs, &rela); + + /* The address of an ELF reloc is section relative for an object + file, and absolute for an executable file or shared library. + The address of a normal BFD reloc is always section relative, + and the address of a dynamic reloc is absolute.. */ + if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0 || dynamic) + relent->address = rela.r_offset; + else + relent->address = rela.r_offset - asect->vma; + + if (ELF64_R_SYM (rela.r_info) == 0) + relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; + else + { + asymbol **ps, *s; + + ps = symbols + ELF64_R_SYM (rela.r_info) - 1; + s = *ps; + + /* Canonicalize ELF section symbols. FIXME: Why? */ + if ((s->flags & BSF_SECTION_SYM) == 0) + relent->sym_ptr_ptr = ps; + else + relent->sym_ptr_ptr = s->section->symbol_ptr_ptr; + } + + relent->addend = rela.r_addend; + + BFD_ASSERT (ELF64_R_TYPE_ID (rela.r_info) < (unsigned int) R_SPARC_max_std); + if (ELF64_R_TYPE_ID (rela.r_info) == R_SPARC_OLO10) + { + relent->howto = &sparc64_elf_howto_table[R_SPARC_LO10]; + relent[1].address = relent->address; + relent++; + relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; + relent->addend = ELF64_R_TYPE_DATA (rela.r_info); + relent->howto = &sparc64_elf_howto_table[R_SPARC_13]; + } + else + relent->howto = &sparc64_elf_howto_table[ELF64_R_TYPE_ID (rela.r_info)]; + } + + asect->reloc_count += relent - relents; + + if (allocated != NULL) + free (allocated); + + return true; + + error_return: + if (allocated != NULL) + free (allocated); + return false; +} + +/* Read in and swap the external relocs. */ + +static boolean +sparc64_elf_slurp_reloc_table (abfd, asect, symbols, dynamic) + bfd *abfd; + asection *asect; + asymbol **symbols; + boolean dynamic; +{ + struct bfd_elf_section_data * const d = elf_section_data (asect); + Elf_Internal_Shdr *rel_hdr; + Elf_Internal_Shdr *rel_hdr2; + + if (asect->relocation != NULL) + return true; + + if (! dynamic) + { + if ((asect->flags & SEC_RELOC) == 0 + || asect->reloc_count == 0) + return true; + + rel_hdr = &d->rel_hdr; + rel_hdr2 = d->rel_hdr2; + + BFD_ASSERT (asect->rel_filepos == rel_hdr->sh_offset + || (rel_hdr2 && asect->rel_filepos == rel_hdr2->sh_offset)); + } + else + { + /* Note that ASECT->RELOC_COUNT tends not to be accurate in this + case because relocations against this section may use the + dynamic symbol table, and in that case bfd_section_from_shdr + in elf.c does not update the RELOC_COUNT. */ + if (asect->_raw_size == 0) + return true; + + rel_hdr = &d->this_hdr; + asect->reloc_count = rel_hdr->sh_size / rel_hdr->sh_entsize; + rel_hdr2 = NULL; + } + + asect->relocation = ((arelent *) + bfd_alloc (abfd, + asect->reloc_count * 2 * sizeof (arelent))); + if (asect->relocation == NULL) + return false; + + /* The sparc64_elf_slurp_one_reloc_table routine increments reloc_count. */ + asect->reloc_count = 0; + + if (!sparc64_elf_slurp_one_reloc_table (abfd, asect, rel_hdr, symbols, + dynamic)) + return false; + + if (rel_hdr2 + && !sparc64_elf_slurp_one_reloc_table (abfd, asect, rel_hdr2, symbols, + dynamic)) + return false; + + return true; +} + +/* Canonicalize the dynamic relocation entries. Note that we return + the dynamic relocations as a single block, although they are + actually associated with particular sections; the interface, which + was designed for SunOS style shared libraries, expects that there + is only one set of dynamic relocs. Any section that was actually + installed in the BFD, and has type SHT_REL or SHT_RELA, and uses + the dynamic symbol table, is considered to be a dynamic reloc + section. */ + +static long +sparc64_elf_canonicalize_dynamic_reloc (abfd, storage, syms) + bfd *abfd; + arelent **storage; + asymbol **syms; +{ + asection *s; + long ret; + + if (elf_dynsymtab (abfd) == 0) + { + bfd_set_error (bfd_error_invalid_operation); + return -1; + } + + ret = 0; + for (s = abfd->sections; s != NULL; s = s->next) + { + if (elf_section_data (s)->this_hdr.sh_link == elf_dynsymtab (abfd) + && (elf_section_data (s)->this_hdr.sh_type == SHT_RELA)) + { + arelent *p; + long count, i; + + if (! sparc64_elf_slurp_reloc_table (abfd, s, syms, true)) + return -1; + count = s->reloc_count; + p = s->relocation; + for (i = 0; i < count; i++) + *storage++ = p++; + ret += count; + } + } + + *storage = NULL; + + return ret; +} + +/* Write out the relocs. */ + +static void +sparc64_elf_write_relocs (abfd, sec, data) + bfd *abfd; + asection *sec; + PTR data; +{ + boolean *failedp = (boolean *) data; + Elf_Internal_Shdr *rela_hdr; + Elf64_External_Rela *outbound_relocas, *src_rela; + unsigned int idx, count; + asymbol *last_sym = 0; + int last_sym_idx = 0; + + /* If we have already failed, don't do anything. */ + if (*failedp) + return; + + if ((sec->flags & SEC_RELOC) == 0) + return; + + /* The linker backend writes the relocs out itself, and sets the + reloc_count field to zero to inhibit writing them here. Also, + sometimes the SEC_RELOC flag gets set even when there aren't any + relocs. */ + if (sec->reloc_count == 0) + return; + + /* We can combine two relocs that refer to the same address + into R_SPARC_OLO10 if first one is R_SPARC_LO10 and the + latter is R_SPARC_13 with no associated symbol. */ + count = 0; + for (idx = 0; idx < sec->reloc_count; idx++) + { + bfd_vma addr; + unsigned int i; + + ++count; + + addr = sec->orelocation[idx]->address; + if (sec->orelocation[idx]->howto->type == R_SPARC_LO10 + && idx < sec->reloc_count - 1) + { + arelent *r = sec->orelocation[idx + 1]; + + if (r->howto->type == R_SPARC_13 + && r->address == addr + && bfd_is_abs_section ((*r->sym_ptr_ptr)->section) + && (*r->sym_ptr_ptr)->value == 0) + ++idx; + } + } + + rela_hdr = &elf_section_data (sec)->rel_hdr; + + rela_hdr->sh_size = rela_hdr->sh_entsize * count; + rela_hdr->contents = (PTR) bfd_alloc (abfd, rela_hdr->sh_size); + if (rela_hdr->contents == NULL) + { + *failedp = true; + return; + } + + /* Figure out whether the relocations are RELA or REL relocations. */ + if (rela_hdr->sh_type != SHT_RELA) + abort (); + + /* orelocation has the data, reloc_count has the count... */ + outbound_relocas = (Elf64_External_Rela *) rela_hdr->contents; + src_rela = outbound_relocas; + + for (idx = 0; idx < sec->reloc_count; idx++) + { + Elf_Internal_Rela dst_rela; + arelent *ptr; + asymbol *sym; + int n; + + ptr = sec->orelocation[idx]; + + /* The address of an ELF reloc is section relative for an object + file, and absolute for an executable file or shared library. + The address of a BFD reloc is always section relative. */ + if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0) + dst_rela.r_offset = ptr->address; + else + dst_rela.r_offset = ptr->address + sec->vma; + + sym = *ptr->sym_ptr_ptr; + if (sym == last_sym) + n = last_sym_idx; + else if (bfd_is_abs_section (sym->section) && sym->value == 0) + n = STN_UNDEF; + else + { + last_sym = sym; + n = _bfd_elf_symbol_from_bfd_symbol (abfd, &sym); + if (n < 0) + { + *failedp = true; + return; + } + last_sym_idx = n; + } + + if ((*ptr->sym_ptr_ptr)->the_bfd != NULL + && (*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec + && ! _bfd_elf_validate_reloc (abfd, ptr)) + { + *failedp = true; + return; + } + + if (ptr->howto->type == R_SPARC_LO10 + && idx < sec->reloc_count - 1) + { + arelent *r = sec->orelocation[idx + 1]; + + if (r->howto->type == R_SPARC_13 + && r->address == ptr->address + && bfd_is_abs_section ((*r->sym_ptr_ptr)->section) + && (*r->sym_ptr_ptr)->value == 0) + { + idx++; + dst_rela.r_info + = ELF64_R_INFO (n, ELF64_R_TYPE_INFO (r->addend, + R_SPARC_OLO10)); + } + else + dst_rela.r_info = ELF64_R_INFO (n, R_SPARC_LO10); + } + else + dst_rela.r_info = ELF64_R_INFO (n, ptr->howto->type); + + dst_rela.r_addend = ptr->addend; + bfd_elf64_swap_reloca_out (abfd, &dst_rela, src_rela); + ++src_rela; + } +} + +/* Sparc64 ELF linker hash table. */ + +struct sparc64_elf_app_reg +{ + unsigned char bind; + unsigned short shndx; + bfd *abfd; + char *name; +}; + +struct sparc64_elf_link_hash_table +{ + struct elf_link_hash_table root; + + struct sparc64_elf_app_reg app_regs [4]; +}; + +/* Get the Sparc64 ELF linker hash table from a link_info structure. */ + +#define sparc64_elf_hash_table(p) \ + ((struct sparc64_elf_link_hash_table *) ((p)->hash)) + +/* Create a Sparc64 ELF linker hash table. */ + +static struct bfd_link_hash_table * +sparc64_elf_bfd_link_hash_table_create (abfd) + bfd *abfd; +{ + struct sparc64_elf_link_hash_table *ret; + + ret = ((struct sparc64_elf_link_hash_table *) + bfd_zalloc (abfd, sizeof (struct sparc64_elf_link_hash_table))); + if (ret == (struct sparc64_elf_link_hash_table *) NULL) + return NULL; + + if (! _bfd_elf_link_hash_table_init (&ret->root, abfd, + _bfd_elf_link_hash_newfunc)) + { + bfd_release (abfd, ret); + return NULL; + } + + return &ret->root.root; +} + + /* Utility for performing the standard initial work of an instruction relocation. *PRELOCATION will contain the relocated item. @@ -441,8 +876,8 @@ sparc64_elf_build_plt (output_bfd, contents, nentries) /* sethi (. - plt0), %g1 */ sethi = 0x03000000 | (i * PLT_ENTRY_SIZE); - /* ba,a,pt %icc, plt1 */ - ba = 0x30480000 | (((contents+PLT_ENTRY_SIZE) - (entry+4)) / 4 & 0x7ffff); + /* ba,a,pt %xcc, plt1 */ + ba = 0x30680000 | (((contents+PLT_ENTRY_SIZE) - (entry+4)) / 4 & 0x7ffff); bfd_put_32 (output_bfd, sethi, entry); bfd_put_32 (output_bfd, ba, entry+4); @@ -479,7 +914,7 @@ sparc64_elf_build_plt (output_bfd, contents, nentries) bfd_put_32 (output_bfd, 0x83c3c001, entry+16); /* jmpl %o7+%g1,%g1 */ bfd_put_32 (output_bfd, 0x9e100005, entry+20); /* mov %g5,%o7 */ - bfd_put_64 (output_bfd, contents - entry+4, ptr); + bfd_put_64 (output_bfd, contents - (entry+4), ptr); } } } @@ -514,11 +949,15 @@ sparc64_elf_plt_ptr_offset (index, max) /* See above for details. */ - block = (index - LARGE_PLT_THRESHOLD) / 160; - ofs = (index - LARGE_PLT_THRESHOLD) % 160; - last = (max - LARGE_PLT_THRESHOLD) % 160; + block = (((index - LARGE_PLT_THRESHOLD) / 160) * 160) + + LARGE_PLT_THRESHOLD; + ofs = index - block; + if (block + 160 > max) + last = (max - LARGE_PLT_THRESHOLD) % 160; + else + last = 160; - return ((LARGE_PLT_THRESHOLD + block*160) * PLT_ENTRY_SIZE + return (block * PLT_ENTRY_SIZE + last * 6*4 + ofs * 8); } @@ -570,7 +1009,7 @@ sparc64_elf_check_relocs (abfd, info, sec, relocs) else h = sym_hashes[r_symndx - symtab_hdr->sh_info]; - switch (ELF64_R_TYPE (rel->r_info)) + switch (ELF64_R_TYPE_ID (rel->r_info)) { case R_SPARC_GOT10: case R_SPARC_GOT13: @@ -612,12 +1051,12 @@ sparc64_elf_check_relocs (abfd, info, sec, relocs) if (h != NULL) { - if (h->got_offset != (bfd_vma) -1) + if (h->got.offset != (bfd_vma) -1) { /* We have already allocated space in the .got. */ break; } - h->got_offset = sgot->_raw_size; + h->got.offset = sgot->_raw_size; /* Make sure this symbol is output as a dynamic symbol. */ if (h->dynindx == -1) @@ -807,16 +1246,233 @@ sparc64_elf_check_relocs (abfd, info, sec, relocs) break; default: - (*_bfd_error_handler)("%s: check_relocs: unhandled reloc type %d", + (*_bfd_error_handler)(_("%s: check_relocs: unhandled reloc type %d"), bfd_get_filename(abfd), - ELF64_R_TYPE (rel->r_info)); + ELF64_R_TYPE_ID (rel->r_info)); + return false; + } + } + + return true; +} + +/* Hook called by the linker routine which adds symbols from an object + file. We use it for STT_REGISTER symbols. */ + +static boolean +sparc64_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp) + bfd *abfd; + struct bfd_link_info *info; + const Elf_Internal_Sym *sym; + const char **namep; + flagword *flagsp; + asection **secp; + bfd_vma *valp; +{ + static char *stt_types[] = { "NOTYPE", "OBJECT", "FUNCTION" }; + + if (ELF_ST_TYPE (sym->st_info) == STT_REGISTER) + { + int reg; + struct sparc64_elf_app_reg *p; + + reg = (int)sym->st_value; + switch (reg & ~1) + { + case 2: reg -= 2; break; + case 6: reg -= 4; break; + default: + (*_bfd_error_handler) + (_("%s: Only registers %%g[2367] can be declared using STT_REGISTER"), + bfd_get_filename (abfd)); + return false; + } + + if (info->hash->creator != abfd->xvec + || (abfd->flags & DYNAMIC) != 0) + { + /* STT_REGISTER only works when linking an elf64_sparc object. + If STT_REGISTER comes from a dynamic object, don't put it into + the output bfd. The dynamic linker will recheck it. */ + *namep = NULL; + return true; + } + + p = sparc64_elf_hash_table(info)->app_regs + reg; + + if (p->name != NULL && strcmp (p->name, *namep)) + { + (*_bfd_error_handler) + (_("Register %%g%d used incompatibly: " + "previously declared in %s to %s, in %s redefined to %s"), + (int)sym->st_value, + bfd_get_filename (p->abfd), *p->name ? p->name : "#scratch", + bfd_get_filename (abfd), **namep ? *namep : "#scratch"); return false; } + + if (p->name == NULL) + { + if (**namep) + { + struct elf_link_hash_entry *h; + + h = (struct elf_link_hash_entry *) + bfd_link_hash_lookup (info->hash, *namep, false, false, false); + + if (h != NULL) + { + unsigned char type = h->type; + + if (type > STT_FUNC) type = 0; + (*_bfd_error_handler) + (_("Symbol `%s' has differing types: " + "previously %s, REGISTER in %s"), + *namep, stt_types [type], bfd_get_filename (abfd)); + return false; + } + + p->name = bfd_hash_allocate (&info->hash->table, + strlen (*namep) + 1); + if (!p->name) + return false; + + strcpy (p->name, *namep); + } + else + p->name = ""; + p->bind = ELF_ST_BIND (sym->st_info); + p->abfd = abfd; + p->shndx = sym->st_shndx; + } + else + { + if (p->bind == STB_WEAK + && ELF_ST_BIND (sym->st_info) == STB_GLOBAL) + { + p->bind = STB_GLOBAL; + p->abfd = abfd; + } + } + *namep = NULL; + return true; } + else if (! *namep || ! **namep) + return true; + else + { + int i; + struct sparc64_elf_app_reg *p; + p = sparc64_elf_hash_table(info)->app_regs; + for (i = 0; i < 4; i++, p++) + if (p->name != NULL && ! strcmp (p->name, *namep)) + { + unsigned char type = ELF_ST_TYPE (sym->st_info); + + if (type > STT_FUNC) type = 0; + (*_bfd_error_handler) + (_("Symbol `%s' has differing types: " + "REGISTER in %s, %s in %s"), + *namep, bfd_get_filename (p->abfd), stt_types [type], + bfd_get_filename (abfd)); + return false; + } + } return true; } +/* This function takes care of emiting STT_REGISTER symbols + which we cannot easily keep in the symbol hash table. */ + +static boolean +sparc64_elf_output_arch_syms (output_bfd, info, finfo, func) + bfd *output_bfd; + struct bfd_link_info *info; + PTR finfo; + boolean (*func) PARAMS ((PTR, const char *, + Elf_Internal_Sym *, asection *)); +{ + int reg; + struct sparc64_elf_app_reg *app_regs = + sparc64_elf_hash_table(info)->app_regs; + Elf_Internal_Sym sym; + + /* We arranged in size_dynamic_sections to put the STT_REGISTER entries + at the end of the dynlocal list, so they came at the end of the local + symbols in the symtab. Except that they aren't STB_LOCAL, so we need + to back up symtab->sh_info. */ + if (elf_hash_table (info)->dynlocal) + { + bfd * dynobj = elf_hash_table (info)->dynobj; + asection *dynsymsec = bfd_get_section_by_name (dynobj, ".dynsym"); + struct elf_link_local_dynamic_entry *e; + + for (e = elf_hash_table (info)->dynlocal; e ; e = e->next) + if (e->input_indx == -1) + break; + if (e) + { + elf_section_data (dynsymsec->output_section)->this_hdr.sh_info + = e->dynindx; + } + } + + if (info->strip == strip_all) + return true; + + for (reg = 0; reg < 4; reg++) + if (app_regs [reg].name != NULL) + { + if (info->strip == strip_some + && bfd_hash_lookup (info->keep_hash, + app_regs [reg].name, + false, false) == NULL) + continue; + + sym.st_value = reg < 2 ? reg + 2 : reg + 4; + sym.st_size = 0; + sym.st_other = 0; + sym.st_info = ELF_ST_INFO (app_regs [reg].bind, STT_REGISTER); + sym.st_shndx = app_regs [reg].shndx; + if (! (*func) (finfo, app_regs [reg].name, &sym, + sym.st_shndx == SHN_ABS + ? bfd_abs_section_ptr : bfd_und_section_ptr)) + return false; + } + + return true; +} + +static int +sparc64_elf_get_symbol_type (elf_sym, type) + Elf_Internal_Sym * elf_sym; + int type; +{ + if (ELF_ST_TYPE (elf_sym->st_info) == STT_REGISTER) + return STT_REGISTER; + else + return type; +} + +/* A STB_GLOBAL,STT_REGISTER symbol should be BSF_GLOBAL + even in SHN_UNDEF section. */ + +static void +sparc64_elf_symbol_processing (abfd, asym) + bfd *abfd; + asymbol *asym; +{ + elf_symbol_type *elfsym; + + elfsym = (elf_symbol_type *) asym; + if (elfsym->internal_elf_sym.st_info + == ELF_ST_INFO (STB_GLOBAL, STT_REGISTER)) + { + asym->flags |= BSF_GLOBAL; + } +} + /* Adjust a symbol defined by a dynamic object and referenced by a regular object. The current definition is in some section of the dynamic object, but we're not including those sections. We have to @@ -890,7 +1546,7 @@ sparc64_elf_adjust_dynamic_symbol (info, h) } /* To simplify matters later, just store the plt index here. */ - h->plt_offset = s->_raw_size / PLT_ENTRY_SIZE; + h->plt.offset = s->_raw_size / PLT_ENTRY_SIZE; /* Make room for this entry. */ s->_raw_size += PLT_ENTRY_SIZE; @@ -1097,15 +1753,7 @@ sparc64_elf_size_dynamic_sections (output_bfd, info) if (strip) { - asection **spp; - - for (spp = &s->output_section->owner->sections; - *spp != s->output_section; - spp = &(*spp)->next) - ; - *spp = s->output_section->next; - --s->output_section->owner->section_count; - + _bfd_strip_section_from_output (info, s); continue; } @@ -1124,6 +1772,11 @@ sparc64_elf_size_dynamic_sections (output_bfd, info) must add the entries now so that we get the correct size for the .dynamic section. The DT_DEBUG entry is filled in by the dynamic linker and used by the debugger. */ + int reg; + struct sparc64_elf_app_reg * app_regs; + struct bfd_strtab_hash *dynstr; + struct elf_link_hash_table *eht = elf_hash_table (info); + if (! info->shared) { if (! bfd_elf64_add_dynamic_entry (info, DT_DEBUG, 0)) @@ -1135,9 +1788,7 @@ sparc64_elf_size_dynamic_sections (output_bfd, info) if (! bfd_elf64_add_dynamic_entry (info, DT_PLTGOT, 0) || ! bfd_elf64_add_dynamic_entry (info, DT_PLTRELSZ, 0) || ! bfd_elf64_add_dynamic_entry (info, DT_PLTREL, DT_RELA) - || ! bfd_elf64_add_dynamic_entry (info, DT_JMPREL, 0) - || ! bfd_elf64_add_dynamic_entry (info, DT_SPARC_PLTFMT, - (info->shared != 0) + 1)) + || ! bfd_elf64_add_dynamic_entry (info, DT_JMPREL, 0)) return false; } @@ -1152,56 +1803,57 @@ sparc64_elf_size_dynamic_sections (output_bfd, info) if (! bfd_elf64_add_dynamic_entry (info, DT_TEXTREL, 0)) return false; } - } - - /* If we are generating a shared library, we generate a section - symbol for each output section for which we might need to copy - relocs. These are local symbols, which means that they must come - first in the dynamic symbol table. That means we must increment - the dynamic symbol index of every other dynamic symbol. */ - if (info->shared) - { - int c; - c = 0; - for (s = output_bfd->sections; s != NULL; s = s->next) - { - if ((s->flags & SEC_LINKER_CREATED) != 0 - || (s->flags & SEC_ALLOC) == 0) - continue; - - elf_section_data (s)->dynindx = c + 1; + /* Add dynamic STT_REGISTER symbols and corresponding DT_SPARC_REGISTER + entries if needed. */ + app_regs = sparc64_elf_hash_table (info)->app_regs; + dynstr = eht->dynstr; - /* These symbols will have no names, so we don't need to - fiddle with dynstr_index. */ + for (reg = 0; reg < 4; reg++) + if (app_regs [reg].name != NULL) + { + struct elf_link_local_dynamic_entry *entry, *e; + + if (! bfd_elf64_add_dynamic_entry (info, DT_SPARC_REGISTER, 0)) + return false; - ++c; - } + entry = (struct elf_link_local_dynamic_entry *) + bfd_hash_allocate (&info->hash->table, sizeof (*entry)); + if (entry == NULL) + return false; - elf_link_hash_traverse (elf_hash_table (info), - sparc64_elf_adjust_dynindx, - (PTR) &c); - elf_hash_table (info)->dynsymcount += c; + /* We cheat here a little bit: the symbol will not be local, so we + put it at the end of the dynlocal linked list. We will fix it + later on, as we have to fix other fields anyway. */ + entry->isym.st_value = reg < 2 ? reg + 2 : reg + 4; + entry->isym.st_size = 0; + if (*app_regs [reg].name != '\0') + entry->isym.st_name + = _bfd_stringtab_add (dynstr, app_regs[reg].name, true, false); + else + entry->isym.st_name = 0; + entry->isym.st_other = 0; + entry->isym.st_info = ELF_ST_INFO (app_regs [reg].bind, + STT_REGISTER); + entry->isym.st_shndx = app_regs [reg].shndx; + entry->next = NULL; + entry->input_bfd = output_bfd; + entry->input_indx = -1; + + if (eht->dynlocal == NULL) + eht->dynlocal = entry; + else + { + for (e = eht->dynlocal; e->next; e = e->next) + ; + e->next = entry; + } + eht->dynsymcount++; + } } return true; } - -/* Increment the index of a dynamic symbol by a given amount. Called - via elf_link_hash_traverse. */ - -static boolean -sparc64_elf_adjust_dynindx (h, cparg) - struct elf_link_hash_entry *h; - PTR cparg; -{ - int *cp = (int *) cparg; - - if (h->dynindx != -1) - h->dynindx += *cp; - return true; -} - /* Relocate a SPARC64 ELF section. */ @@ -1253,8 +1905,8 @@ sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, bfd_vma relocation; bfd_reloc_status_type r; - r_type = ELF64_R_TYPE (rel->r_info); - if (r_type < 0 || r_type >= (int) R_SPARC_max) + r_type = ELF64_R_TYPE_ID (rel->r_info); + if (r_type < 0 || r_type >= (int) R_SPARC_max_std) { bfd_set_error (bfd_error_bad_value); return false; @@ -1316,7 +1968,7 @@ sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, case R_SPARC_PCPLT22: case R_SPARC_PCPLT10: case R_SPARC_PLT64: - if (h->plt_offset != (bfd_vma) -1) + if (h->plt.offset != (bfd_vma) -1) skip_it = true; break; @@ -1397,13 +2049,14 @@ sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, } else if (h->root.type == bfd_link_hash_undefweak) relocation = 0; - else if (info->shared && !info->symbolic) + else if (info->shared && !info->symbolic && !info->no_undefined) relocation = 0; else { if (! ((*info->callbacks->undefined_symbol) (info, h->root.root.string, input_bfd, - input_section, rel->r_offset))) + input_section, rel->r_offset, + (!info->shared || info->no_undefined)))) return false; relocation = 0; } @@ -1539,7 +2192,11 @@ sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, & ELF_LINK_HASH_DEF_REGULAR) == 0)) { BFD_ASSERT (h->dynindx != -1); - outrel.r_info = ELF64_R_INFO (h->dynindx, r_type); + outrel.r_info + = ELF64_R_INFO (h->dynindx, + ELF64_R_TYPE_INFO ( + ELF64_R_TYPE_DATA (rel->r_info), + r_type)); outrel.r_addend = rel->r_addend; } else @@ -1582,14 +2239,18 @@ sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, { BFD_FAIL (); (*_bfd_error_handler) - ("%s: probably compiled without -fPIC?", + (_("%s: probably compiled without -fPIC?"), bfd_get_filename (input_bfd)); bfd_set_error (bfd_error_bad_value); return false; } } - outrel.r_info = ELF64_R_INFO (indx, r_type); + outrel.r_info + = ELF64_R_INFO (indx, + ELF64_R_TYPE_INFO ( + ELF64_R_TYPE_DATA (rel->r_info), + r_type)); outrel.r_addend = relocation + rel->r_addend; } } @@ -1605,7 +2266,7 @@ sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, reloc in an unallocated section. */ if (skip || (input_section->flags & SEC_ALLOC) != 0 - || ELF64_R_TYPE (outrel.r_info) != R_SPARC_RELATIVE) + || ELF64_R_TYPE_ID (outrel.r_info) != R_SPARC_RELATIVE) continue; } break; @@ -1627,7 +2288,7 @@ sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, if (h != NULL) { - bfd_vma off = h->got_offset; + bfd_vma off = h->got.offset; BFD_ASSERT (off != (bfd_vma) -1); if (! elf_hash_table (info)->dynamic_sections_created @@ -1654,7 +2315,7 @@ sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, { bfd_put_64 (output_bfd, relocation, sgot->contents + off); - h->got_offset |= 1; + h->got.offset |= 1; } } relocation = sgot->output_offset + off - got_base; @@ -1715,7 +2376,7 @@ sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, procedure linkage table. */ BFD_ASSERT (h != NULL); - if (h->plt_offset == (bfd_vma) -1) + if (h->plt.offset == (bfd_vma) -1) { /* We didn't make a PLT entry for this symbol. This happens when statically linking PIC code, or when @@ -1731,7 +2392,7 @@ sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, relocation = (splt->output_section->vma + splt->output_offset - + sparc64_elf_plt_entry_offset (h->plt_offset)); + + sparc64_elf_plt_entry_offset (h->plt.offset)); goto do_default; case R_SPARC_OLO10: @@ -1747,6 +2408,7 @@ sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, r = bfd_check_overflow (howto->complain_on_overflow, howto->bitsize, howto->rightshift, + bfd_arch_bits_per_address (input_bfd), relocation); } break; @@ -1768,6 +2430,7 @@ sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, r = bfd_check_overflow (howto->complain_on_overflow, howto->bitsize, howto->rightshift, + bfd_arch_bits_per_address (input_bfd), relocation); } break; @@ -1785,6 +2448,7 @@ sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, r = bfd_check_overflow (howto->complain_on_overflow, howto->bitsize, howto->rightshift, + bfd_arch_bits_per_address (input_bfd), relocation); } break; @@ -1877,7 +2541,7 @@ sparc64_elf_finish_dynamic_symbol (output_bfd, info, h, sym) dynobj = elf_hash_table (info)->dynobj; - if (h->plt_offset != (bfd_vma) -1) + if (h->plt.offset != (bfd_vma) -1) { asection *splt; asection *srela; @@ -1893,22 +2557,24 @@ sparc64_elf_finish_dynamic_symbol (output_bfd, info, h, sym) /* Fill in the entry in the .rela.plt section. */ - if (h->plt_offset < LARGE_PLT_THRESHOLD) + if (h->plt.offset < LARGE_PLT_THRESHOLD) { - rela.r_offset = sparc64_elf_plt_entry_offset (h->plt_offset); + rela.r_offset = sparc64_elf_plt_entry_offset (h->plt.offset); rela.r_addend = 0; } else { int max = splt->_raw_size / PLT_ENTRY_SIZE; - rela.r_offset = sparc64_elf_plt_ptr_offset (h->plt_offset, max); - rela.r_addend = -(sparc64_elf_plt_entry_offset (h->plt_offset) + 4); + rela.r_offset = sparc64_elf_plt_ptr_offset (h->plt.offset, max); + rela.r_addend = -(sparc64_elf_plt_entry_offset (h->plt.offset) + 4) + -(splt->output_section->vma + splt->output_offset); } + rela.r_offset += (splt->output_section->vma + splt->output_offset); rela.r_info = ELF64_R_INFO (h->dynindx, R_SPARC_JMP_SLOT); bfd_elf64_swap_reloca_out (output_bfd, &rela, ((Elf64_External_Rela *) srela->contents - + h->plt_offset)); + + h->plt.offset)); if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) { @@ -1918,7 +2584,7 @@ sparc64_elf_finish_dynamic_symbol (output_bfd, info, h, sym) } } - if (h->got_offset != (bfd_vma) -1) + if (h->got.offset != (bfd_vma) -1) { asection *sgot; asection *srela; @@ -1932,7 +2598,7 @@ sparc64_elf_finish_dynamic_symbol (output_bfd, info, h, sym) rela.r_offset = (sgot->output_section->vma + sgot->output_offset - + (h->got_offset &~ 1)); + + (h->got.offset &~ 1)); /* If this is a -Bsymbolic link, and the symbol is defined locally, we just want to emit a RELATIVE reloc. Likewise if @@ -1951,7 +2617,7 @@ sparc64_elf_finish_dynamic_symbol (output_bfd, info, h, sym) } else { - bfd_put_64 (output_bfd, (bfd_vma) 0, sgot->contents + h->got_offset); + bfd_put_64 (output_bfd, (bfd_vma) 0, sgot->contents + h->got.offset); rela.r_info = ELF64_R_INFO (h->dynindx, R_SPARC_GLOB_DAT); rela.r_addend = 0; } @@ -2003,6 +2669,7 @@ sparc64_elf_finish_dynamic_sections (output_bfd, info) struct bfd_link_info *info; { bfd *dynobj; + int stt_regidx = -1; asection *sdyn; asection *sgot; @@ -2033,6 +2700,17 @@ sparc64_elf_finish_dynamic_sections (output_bfd, info) case DT_PLTGOT: name = ".plt"; size = false; break; case DT_PLTRELSZ: name = ".rela.plt"; size = true; break; case DT_JMPREL: name = ".rela.plt"; size = false; break; + case DT_SPARC_REGISTER: + if (stt_regidx == -1) + { + stt_regidx = + _bfd_elf_link_lookup_local_dynindx (info, output_bfd, -1); + if (stt_regidx == -1) + return false; + } + dyn.d_un.d_val = stt_regidx++; + bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon); + /* fallthrough */ default: name = NULL; size = false; break; } @@ -2086,50 +2764,6 @@ sparc64_elf_finish_dynamic_sections (output_bfd, info) elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 8; - if (info->shared) - { - asection *sdynsym; - asection *s; - Elf_Internal_Sym sym; - int c; - - /* Set up the section symbols for the output sections. */ - - sdynsym = bfd_get_section_by_name (dynobj, ".dynsym"); - BFD_ASSERT (sdynsym != NULL); - - sym.st_size = 0; - sym.st_name = 0; - sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION); - sym.st_other = 0; - - c = 0; - for (s = output_bfd->sections; s != NULL; s = s->next) - { - int indx; - - if (elf_section_data (s)->dynindx == 0) - continue; - - sym.st_value = s->vma; - - indx = elf_section_data (s)->this_idx; - BFD_ASSERT (indx > 0); - sym.st_shndx = indx; - - bfd_elf64_swap_symbol_out (output_bfd, &sym, - (PTR) (((Elf64_External_Sym *) - sdynsym->contents) - + elf_section_data (s)->dynindx)); - - ++c; - } - - /* Set the sh_info field of the output .dynsym section to the - index of the first global symbol. */ - elf_section_data (sdynsym->output_section)->this_hdr.sh_info = c + 1; - } - return true; } @@ -2167,32 +2801,47 @@ sparc64_elf_merge_private_bfd_data (ibfd, obfd) { error = false; - old_flags |= (new_flags & (EF_SPARC_SUN_US1|EF_SPARC_HAL_R1)); - new_flags |= (old_flags & (EF_SPARC_SUN_US1|EF_SPARC_HAL_R1)); - if ((old_flags & (EF_SPARC_SUN_US1|EF_SPARC_HAL_R1)) == - (EF_SPARC_SUN_US1|EF_SPARC_HAL_R1)) - { - error = true; - (*_bfd_error_handler) - ("%s: linking UltraSPARC specific with HAL specific code", - bfd_get_filename (ibfd)); - } - - /* Choose the most restrictive memory ordering */ - old_mm = (old_flags & EF_SPARCV9_MM); - new_mm = (new_flags & EF_SPARCV9_MM); - old_flags &= ~EF_SPARCV9_MM; - new_flags &= ~EF_SPARCV9_MM; - if (new_mm < old_mm) old_mm = new_mm; - old_flags |= old_mm; - new_flags |= old_mm; + if ((ibfd->flags & DYNAMIC) != 0) + { + /* We don't want dynamic objects memory ordering and + architecture to have any role. That's what dynamic linker + should do. */ + old_flags &= ~(EF_SPARCV9_MM | EF_SPARC_SUN_US1 | EF_SPARC_HAL_R1); + old_flags |= (new_flags + & (EF_SPARCV9_MM + | EF_SPARC_SUN_US1 + | EF_SPARC_HAL_R1)); + } + else + { + /* Choose the highest architecture requirements. */ + old_flags |= (new_flags & (EF_SPARC_SUN_US1 | EF_SPARC_HAL_R1)); + new_flags |= (old_flags & (EF_SPARC_SUN_US1 | EF_SPARC_HAL_R1)); + if ((old_flags & (EF_SPARC_SUN_US1 | EF_SPARC_HAL_R1)) + == (EF_SPARC_SUN_US1 | EF_SPARC_HAL_R1)) + { + error = true; + (*_bfd_error_handler) + (_("%s: linking UltraSPARC specific with HAL specific code"), + bfd_get_filename (ibfd)); + } + /* Choose the most restrictive memory ordering. */ + old_mm = (old_flags & EF_SPARCV9_MM); + new_mm = (new_flags & EF_SPARCV9_MM); + old_flags &= ~EF_SPARCV9_MM; + new_flags &= ~EF_SPARCV9_MM; + if (new_mm < old_mm) + old_mm = new_mm; + old_flags |= old_mm; + new_flags |= old_mm; + } /* Warn about any other mismatches */ if (new_flags != old_flags) { error = true; (*_bfd_error_handler) - ("%s: uses different e_flags (0x%lx) fields than previous modules (0x%lx)", + (_("%s: uses different e_flags (0x%lx) fields than previous modules (0x%lx)"), bfd_get_filename (ibfd), (long)new_flags, (long)old_flags); } @@ -2206,7 +2855,34 @@ sparc64_elf_merge_private_bfd_data (ibfd, obfd) } return true; } + +/* Print a STT_REGISTER symbol to file FILE. */ +static const char * +sparc64_elf_print_symbol_all (abfd, filep, symbol) + bfd *abfd; + PTR filep; + asymbol *symbol; +{ + FILE *file = (FILE *) filep; + int reg, type; + + if (ELF_ST_TYPE (((elf_symbol_type *) symbol)->internal_elf_sym.st_info) + != STT_REGISTER) + return NULL; + + reg = ((elf_symbol_type *) symbol)->internal_elf_sym.st_value; + type = symbol->flags; + fprintf (file, "REG_%c%c%11s%c%c R", "GOLI" [reg / 8], '0' + (reg & 7), "", + ((type & BSF_LOCAL) + ? (type & BSF_GLOBAL) ? '!' : 'l' + : (type & BSF_GLOBAL) ? 'g' : ' '), + (type & BSF_WEAK) ? 'w' : ' '); + if (symbol->name == NULL || symbol->name [0] == '\0') + return "#scratch"; + else + return symbol->name; +} /* Set the right machine number for a SPARC64 ELF file. */ @@ -2221,19 +2897,78 @@ sparc64_elf_object_p (abfd) return bfd_default_set_arch_mach (abfd, bfd_arch_sparc, mach); } +/* Relocations in the 64 bit SPARC ELF ABI are more complex than in + standard ELF, because R_SPARC_OLO10 has secondary addend in + ELF64_R_TYPE_DATA field. This structure is used to redirect the + relocation handling routines. */ + +const struct elf_size_info sparc64_elf_size_info = +{ + sizeof (Elf64_External_Ehdr), + sizeof (Elf64_External_Phdr), + sizeof (Elf64_External_Shdr), + sizeof (Elf64_External_Rel), + sizeof (Elf64_External_Rela), + sizeof (Elf64_External_Sym), + sizeof (Elf64_External_Dyn), + sizeof (Elf_External_Note), + 4, /* hash-table entry size */ + /* internal relocations per external relocations. + For link purposes we use just 1 internal per + 1 external, for assembly and slurp symbol table + we use 2. */ + 1, + 64, /* arch_size */ + 8, /* file_align */ + ELFCLASS64, + EV_CURRENT, + bfd_elf64_write_out_phdrs, + bfd_elf64_write_shdrs_and_ehdr, + sparc64_elf_write_relocs, + bfd_elf64_swap_symbol_out, + sparc64_elf_slurp_reloc_table, + bfd_elf64_slurp_symbol_table, + bfd_elf64_swap_dyn_in, + bfd_elf64_swap_dyn_out, + NULL, + NULL, + NULL, + NULL +}; + #define TARGET_BIG_SYM bfd_elf64_sparc_vec #define TARGET_BIG_NAME "elf64-sparc" #define ELF_ARCH bfd_arch_sparc -#define ELF_MACHINE_CODE EM_SPARC64 #define ELF_MAXPAGESIZE 0x100000 +/* This is the official ABI value. */ +#define ELF_MACHINE_CODE EM_SPARCV9 + +/* This is the value that we used before the ABI was released. */ +#define ELF_MACHINE_ALT1 EM_OLD_SPARCV9 + +#define bfd_elf64_bfd_link_hash_table_create \ + sparc64_elf_bfd_link_hash_table_create + #define elf_info_to_howto \ sparc64_elf_info_to_howto +#define bfd_elf64_get_reloc_upper_bound \ + sparc64_elf_get_reloc_upper_bound +#define bfd_elf64_get_dynamic_reloc_upper_bound \ + sparc64_elf_get_dynamic_reloc_upper_bound +#define bfd_elf64_canonicalize_dynamic_reloc \ + sparc64_elf_canonicalize_dynamic_reloc #define bfd_elf64_bfd_reloc_type_lookup \ sparc64_elf_reloc_type_lookup #define elf_backend_create_dynamic_sections \ _bfd_elf_create_dynamic_sections +#define elf_backend_add_symbol_hook \ + sparc64_elf_add_symbol_hook +#define elf_backend_get_symbol_type \ + sparc64_elf_get_symbol_type +#define elf_backend_symbol_processing \ + sparc64_elf_symbol_processing #define elf_backend_check_relocs \ sparc64_elf_check_relocs #define elf_backend_adjust_dynamic_symbol \ @@ -2246,10 +2981,16 @@ sparc64_elf_object_p (abfd) sparc64_elf_finish_dynamic_symbol #define elf_backend_finish_dynamic_sections \ sparc64_elf_finish_dynamic_sections +#define elf_backend_print_symbol_all \ + sparc64_elf_print_symbol_all +#define elf_backend_output_arch_syms \ + sparc64_elf_output_arch_syms #define bfd_elf64_bfd_merge_private_bfd_data \ sparc64_elf_merge_private_bfd_data +#define elf_backend_size_info \ + sparc64_elf_size_info #define elf_backend_object_p \ sparc64_elf_object_p @@ -2260,4 +3001,7 @@ sparc64_elf_object_p (abfd) /* Section 5.2.4 of the ABI specifies a 256-byte boundary for the table. */ #define elf_backend_plt_alignment 8 +#define elf_backend_got_header_size 8 +#define elf_backend_plt_header_size PLT_HEADER_SIZE + #include "elf64-target.h" |