X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bfd%2Felf64-alpha.c;h=2b15a81c082a2c2c513845654757ac7f649cef1c;hb=e117360eb31ae7d2d10e08274171a4159949b704;hp=894757938867af89dd8076ea0824d1048758c2a3;hpb=157090f728a99fff42b3d3cc576b0c2a953e9916;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf64-alpha.c b/bfd/elf64-alpha.c index 8947579388..2b15a81c08 100644 --- a/bfd/elf64-alpha.c +++ b/bfd/elf64-alpha.c @@ -1,13 +1,13 @@ /* Alpha specific support for 64-bit ELF Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, - 2006, 2007 Free Software Foundation, Inc. + 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Contributed by Richard Henderson . This file is part of BFD, the Binary File Descriptor library. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -17,13 +17,15 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + /* We need a published ABI spec for this. Until one comes out, don't assume this'll remain unchanged forever. */ -#include "bfd.h" #include "sysdep.h" +#include "bfd.h" #include "libbfd.h" #include "elf-bfd.h" @@ -101,6 +103,57 @@ bfd_boolean elf64_alpha_use_secureplt = FALSE; #define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so" + +/* Used to implement multiple .got subsections. */ +struct alpha_elf_got_entry +{ + struct alpha_elf_got_entry *next; + + /* Which .got subsection? */ + bfd *gotobj; + + /* The addend in effect for this entry. */ + bfd_vma addend; + + /* The .got offset for this entry. */ + int got_offset; + + /* The .plt offset for this entry. */ + int plt_offset; + + /* How many references to this entry? */ + int use_count; + + /* The relocation type of this entry. */ + unsigned char reloc_type; + + /* How a LITERAL is used. */ + unsigned char flags; + + /* Have we initialized the dynamic relocation for this entry? */ + unsigned char reloc_done; + + /* Have we adjusted this entry for SEC_MERGE? */ + unsigned char reloc_xlated; +}; + +struct alpha_elf_reloc_entry +{ + struct alpha_elf_reloc_entry *next; + + /* Which .reloc section? */ + asection *srel; + + /* What kind of relocation? */ + unsigned int rtype; + + /* Is this against read-only section? */ + unsigned int reltext : 1; + + /* How many did we find? */ + unsigned long count; +}; + struct alpha_elf_link_hash_entry { struct elf_link_hash_entry root; @@ -123,56 +176,11 @@ struct alpha_elf_link_hash_entry #define ALPHA_ELF_LINK_HASH_TLS_IE 0x80 /* Used to implement multiple .got subsections. */ - struct alpha_elf_got_entry - { - struct alpha_elf_got_entry *next; - - /* Which .got subsection? */ - bfd *gotobj; - - /* The addend in effect for this entry. */ - bfd_vma addend; - - /* The .got offset for this entry. */ - int got_offset; - - /* The .plt offset for this entry. */ - int plt_offset; - - /* How many references to this entry? */ - int use_count; - - /* The relocation type of this entry. */ - unsigned char reloc_type; - - /* How a LITERAL is used. */ - unsigned char flags; - - /* Have we initialized the dynamic relocation for this entry? */ - unsigned char reloc_done; - - /* Have we adjusted this entry for SEC_MERGE? */ - unsigned char reloc_xlated; - } *got_entries; + struct alpha_elf_got_entry *got_entries; /* Used to count non-got, non-plt relocations for delayed sizing of relocation sections. */ - struct alpha_elf_reloc_entry - { - struct alpha_elf_reloc_entry *next; - - /* Which .reloc section? */ - asection *srel; - - /* What kind of relocation? */ - unsigned int rtype; - - /* Is this against read-only section? */ - unsigned int reltext : 1; - - /* How many did we find? */ - unsigned long count; - } *reloc_entries; + struct alpha_elf_reloc_entry *reloc_entries; }; /* Alpha ELF linker hash table. */ @@ -184,6 +192,10 @@ struct alpha_elf_link_hash_table /* The head of a list of .got subsections linked through alpha_elf_tdata(abfd)->got_link_next. */ bfd *got_list; + + /* The most recent relax pass that we've seen. The GOTs + should be regenerated if this doesn't match. */ + int relax_trip; }; /* Look up an entry in a Alpha ELF linker hash table. */ @@ -204,7 +216,8 @@ struct alpha_elf_link_hash_table /* Get the Alpha ELF linker hash table from a link_info structure. */ #define alpha_elf_hash_table(p) \ - ((struct alpha_elf_link_hash_table *) ((p)->hash)) + (elf_hash_table_id ((struct elf_link_hash_table *) ((p)->hash)) \ + == ALPHA_ELF_DATA ? ((struct alpha_elf_link_hash_table *) ((p)->hash)) : NULL) /* Get the object's symbols as our own entry type. */ @@ -275,7 +288,8 @@ elf64_alpha_bfd_link_hash_table_create (bfd *abfd) if (!_bfd_elf_link_hash_table_init (&ret->root, abfd, elf64_alpha_link_hash_newfunc, - sizeof (struct alpha_elf_link_hash_entry))) + sizeof (struct alpha_elf_link_hash_entry), + ALPHA_ELF_DATA)) { free (ret); return NULL; @@ -318,17 +332,16 @@ struct alpha_elf_obj_tdata #define alpha_elf_tdata(abfd) \ ((struct alpha_elf_obj_tdata *) (abfd)->tdata.any) +#define is_alpha_elf(bfd) \ + (bfd_get_flavour (bfd) == bfd_target_elf_flavour \ + && elf_tdata (bfd) != NULL \ + && elf_object_id (bfd) == ALPHA_ELF_DATA) + static bfd_boolean elf64_alpha_mkobject (bfd *abfd) { - if (abfd->tdata.any == NULL) - { - bfd_size_type amt = sizeof (struct alpha_elf_obj_tdata); - abfd->tdata.any = bfd_zalloc (abfd, amt); - if (abfd->tdata.any == NULL) - return FALSE; - } - return bfd_elf_mkobject (abfd); + return bfd_elf_allocate_object (abfd, sizeof (struct alpha_elf_obj_tdata), + ALPHA_ELF_DATA); } static bfd_boolean @@ -453,8 +466,9 @@ elf64_alpha_reloc_gpdisp (bfd *abfd, arelent *reloc_entry, from smaller values. Start with zero, widen, *then* decrement. */ #define MINUS_ONE (((bfd_vma)0) - 1) + #define SKIP_HOWTO(N) \ - HOWTO(N, 0, 0, 0, 0, 0, 0, elf64_alpha_reloc_bad, 0, 0, 0, 0, 0) + HOWTO(N, 0, 0, 0, 0, 0, complain_overflow_dont, elf64_alpha_reloc_bad, 0, 0, 0, 0, 0) static reloc_howto_type elf64_alpha_howto_table[] = { @@ -480,7 +494,7 @@ static reloc_howto_type elf64_alpha_howto_table[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ - 0, /* special_function */ + bfd_elf_generic_reloc, /* special_function */ "REFLONG", /* name */ FALSE, /* partial_inplace */ 0xffffffff, /* src_mask */ @@ -495,7 +509,7 @@ static reloc_howto_type elf64_alpha_howto_table[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ - 0, /* special_function */ + bfd_elf_generic_reloc, /* special_function */ "REFQUAD", /* name */ FALSE, /* partial_inplace */ MINUS_ONE, /* src_mask */ @@ -512,7 +526,7 @@ static reloc_howto_type elf64_alpha_howto_table[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ - 0, /* special_function */ + bfd_elf_generic_reloc, /* special_function */ "GPREL32", /* name */ FALSE, /* partial_inplace */ 0xffffffff, /* src_mask */ @@ -527,7 +541,7 @@ static reloc_howto_type elf64_alpha_howto_table[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ - 0, /* special_function */ + bfd_elf_generic_reloc, /* special_function */ "ELF_LITERAL", /* name */ FALSE, /* partial_inplace */ 0xffff, /* src_mask */ @@ -593,7 +607,7 @@ static reloc_howto_type elf64_alpha_howto_table[] = TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ - 0, /* special_function */ + bfd_elf_generic_reloc, /* special_function */ "BRADDR", /* name */ FALSE, /* partial_inplace */ 0x1fffff, /* src_mask */ @@ -608,7 +622,7 @@ static reloc_howto_type elf64_alpha_howto_table[] = TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - 0, /* special_function */ + bfd_elf_generic_reloc, /* special_function */ "HINT", /* name */ FALSE, /* partial_inplace */ 0x3fff, /* src_mask */ @@ -623,7 +637,7 @@ static reloc_howto_type elf64_alpha_howto_table[] = TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ - 0, /* special_function */ + bfd_elf_generic_reloc, /* special_function */ "SREL16", /* name */ FALSE, /* partial_inplace */ 0xffff, /* src_mask */ @@ -638,7 +652,7 @@ static reloc_howto_type elf64_alpha_howto_table[] = TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ - 0, /* special_function */ + bfd_elf_generic_reloc, /* special_function */ "SREL32", /* name */ FALSE, /* partial_inplace */ 0xffffffff, /* src_mask */ @@ -653,7 +667,7 @@ static reloc_howto_type elf64_alpha_howto_table[] = TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ - 0, /* special_function */ + bfd_elf_generic_reloc, /* special_function */ "SREL64", /* name */ FALSE, /* partial_inplace */ MINUS_ONE, /* src_mask */ @@ -675,7 +689,7 @@ static reloc_howto_type elf64_alpha_howto_table[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ - 0, /* special_function */ + bfd_elf_generic_reloc, /* special_function */ "GPRELHIGH", /* name */ FALSE, /* partial_inplace */ 0xffff, /* src_mask */ @@ -690,7 +704,7 @@ static reloc_howto_type elf64_alpha_howto_table[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - 0, /* special_function */ + bfd_elf_generic_reloc, /* special_function */ "GPRELLOW", /* name */ FALSE, /* partial_inplace */ 0xffff, /* src_mask */ @@ -705,7 +719,7 @@ static reloc_howto_type elf64_alpha_howto_table[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ - 0, /* special_function */ + bfd_elf_generic_reloc, /* special_function */ "GPREL16", /* name */ FALSE, /* partial_inplace */ 0xffff, /* src_mask */ @@ -791,7 +805,7 @@ static reloc_howto_type elf64_alpha_howto_table[] = TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ - 0, /* special_function */ + bfd_elf_generic_reloc, /* special_function */ "BRSGP", /* name */ FALSE, /* partial_inplace */ 0x1fffff, /* src_mask */ @@ -806,7 +820,7 @@ static reloc_howto_type elf64_alpha_howto_table[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ - 0, /* special_function */ + bfd_elf_generic_reloc, /* special_function */ "TLSGD", /* name */ FALSE, /* partial_inplace */ 0xffff, /* src_mask */ @@ -821,7 +835,7 @@ static reloc_howto_type elf64_alpha_howto_table[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ - 0, /* special_function */ + bfd_elf_generic_reloc, /* special_function */ "TLSLDM", /* name */ FALSE, /* partial_inplace */ 0xffff, /* src_mask */ @@ -836,7 +850,7 @@ static reloc_howto_type elf64_alpha_howto_table[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ - 0, /* special_function */ + bfd_elf_generic_reloc, /* special_function */ "DTPMOD64", /* name */ FALSE, /* partial_inplace */ MINUS_ONE, /* src_mask */ @@ -852,7 +866,7 @@ static reloc_howto_type elf64_alpha_howto_table[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ - 0, /* special_function */ + bfd_elf_generic_reloc, /* special_function */ "GOTDTPREL", /* name */ FALSE, /* partial_inplace */ 0xffff, /* src_mask */ @@ -867,7 +881,7 @@ static reloc_howto_type elf64_alpha_howto_table[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ - 0, /* special_function */ + bfd_elf_generic_reloc, /* special_function */ "DTPREL64", /* name */ FALSE, /* partial_inplace */ MINUS_ONE, /* src_mask */ @@ -882,7 +896,7 @@ static reloc_howto_type elf64_alpha_howto_table[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ - 0, /* special_function */ + bfd_elf_generic_reloc, /* special_function */ "DTPRELHI", /* name */ FALSE, /* partial_inplace */ 0xffff, /* src_mask */ @@ -897,7 +911,7 @@ static reloc_howto_type elf64_alpha_howto_table[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - 0, /* special_function */ + bfd_elf_generic_reloc, /* special_function */ "DTPRELLO", /* name */ FALSE, /* partial_inplace */ 0xffff, /* src_mask */ @@ -912,7 +926,7 @@ static reloc_howto_type elf64_alpha_howto_table[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ - 0, /* special_function */ + bfd_elf_generic_reloc, /* special_function */ "DTPREL16", /* name */ FALSE, /* partial_inplace */ 0xffff, /* src_mask */ @@ -928,7 +942,7 @@ static reloc_howto_type elf64_alpha_howto_table[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ - 0, /* special_function */ + bfd_elf_generic_reloc, /* special_function */ "GOTTPREL", /* name */ FALSE, /* partial_inplace */ 0xffff, /* src_mask */ @@ -943,7 +957,7 @@ static reloc_howto_type elf64_alpha_howto_table[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ - 0, /* special_function */ + bfd_elf_generic_reloc, /* special_function */ "TPREL64", /* name */ FALSE, /* partial_inplace */ MINUS_ONE, /* src_mask */ @@ -958,7 +972,7 @@ static reloc_howto_type elf64_alpha_howto_table[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ - 0, /* special_function */ + bfd_elf_generic_reloc, /* special_function */ "TPRELHI", /* name */ FALSE, /* partial_inplace */ 0xffff, /* src_mask */ @@ -973,7 +987,7 @@ static reloc_howto_type elf64_alpha_howto_table[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - 0, /* special_function */ + bfd_elf_generic_reloc, /* special_function */ "TPRELLO", /* name */ FALSE, /* partial_inplace */ 0xffff, /* src_mask */ @@ -988,7 +1002,7 @@ static reloc_howto_type elf64_alpha_howto_table[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ - 0, /* special_function */ + bfd_elf_generic_reloc, /* special_function */ "TPREL16", /* name */ FALSE, /* partial_inplace */ 0xffff, /* src_mask */ @@ -1228,6 +1242,9 @@ elf64_alpha_create_got_section (bfd *abfd, flagword flags; asection *s; + if (! is_alpha_elf (abfd)) + return FALSE; + flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED); s = bfd_make_section_anyway_with_flags (abfd, ".got", flags); @@ -1254,6 +1271,9 @@ elf64_alpha_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) flagword flags; struct elf_link_hash_entry *h; + if (! is_alpha_elf (abfd)) + return FALSE; + /* We need to create .plt, .rela.plt, .got, and .rela.got sections. */ flags = (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS | SEC_IN_MEMORY @@ -1737,7 +1757,6 @@ elf64_alpha_check_relocs (bfd *abfd, struct bfd_link_info *info, { bfd *dynobj; asection *sreloc; - const char *rel_sec_name; Elf_Internal_Shdr *symtab_hdr; struct alpha_elf_link_hash_entry **sym_hashes; const Elf_Internal_Rela *rel, *relend; @@ -1755,14 +1774,15 @@ elf64_alpha_check_relocs (bfd *abfd, struct bfd_link_info *info, if ((sec->flags & SEC_ALLOC) == 0) return TRUE; - dynobj = elf_hash_table(info)->dynobj; + BFD_ASSERT (is_alpha_elf (abfd)); + + dynobj = elf_hash_table (info)->dynobj; if (dynobj == NULL) - elf_hash_table(info)->dynobj = dynobj = abfd; + elf_hash_table (info)->dynobj = dynobj = abfd; sreloc = NULL; - rel_sec_name = NULL; - symtab_hdr = &elf_tdata(abfd)->symtab_hdr; - sym_hashes = alpha_elf_sym_hashes(abfd); + symtab_hdr = &elf_symtab_hdr (abfd); + sym_hashes = alpha_elf_sym_hashes (abfd); relend = relocs + sec->reloc_count; for (rel = relocs; rel < relend; ++rel) @@ -1846,8 +1866,8 @@ elf64_alpha_check_relocs (bfd *abfd, struct bfd_link_info *info, case R_ALPHA_TLSLDM: /* The symbol for a TLSLDM reloc is ignored. Collapse the - reloc to the 0 symbol so that they all match. */ - r_symndx = 0; + reloc to the STN_UNDEF (0) symbol so that they all match. */ + r_symndx = STN_UNDEF; h = 0; maybe_dynamic = FALSE; /* FALLTHRU */ @@ -1910,41 +1930,16 @@ elf64_alpha_check_relocs (bfd *abfd, struct bfd_link_info *info, if (need & NEED_DYNREL) { - if (rel_sec_name == NULL) - { - rel_sec_name = (bfd_elf_string_from_elf_section - (abfd, elf_elfheader(abfd)->e_shstrndx, - elf_section_data(sec)->rel_hdr.sh_name)); - if (rel_sec_name == NULL) - return FALSE; - - BFD_ASSERT (CONST_STRNEQ (rel_sec_name, ".rela") - && strcmp (bfd_get_section_name (abfd, sec), - rel_sec_name+5) == 0); - } - /* We need to create the section here now whether we eventually use it or not so that it gets mapped to an output section by - the linker. If not used, we'll kill it in - size_dynamic_sections. */ + the linker. If not used, we'll kill it in size_dynamic_sections. */ if (sreloc == NULL) { - sreloc = bfd_get_section_by_name (dynobj, rel_sec_name); + sreloc = _bfd_elf_make_dynamic_reloc_section + (sec, dynobj, 3, abfd, /*rela?*/ TRUE); + if (sreloc == NULL) - { - flagword flags; - - flags = (SEC_HAS_CONTENTS | SEC_IN_MEMORY - | SEC_LINKER_CREATED | SEC_READONLY); - if (sec->flags & SEC_ALLOC) - flags |= SEC_ALLOC | SEC_LOAD; - sreloc = bfd_make_section_with_flags (dynobj, - rel_sec_name, - flags); - if (sreloc == NULL - || !bfd_set_section_alignment (dynobj, sreloc, 3)) - return FALSE; - } + return FALSE; } if (h) @@ -1993,6 +1988,93 @@ elf64_alpha_check_relocs (bfd *abfd, struct bfd_link_info *info, return TRUE; } +/* Return the section that should be marked against GC for a given + relocation. */ + +static asection * +elf64_alpha_gc_mark_hook (asection *sec, struct bfd_link_info *info, + Elf_Internal_Rela *rel, + struct elf_link_hash_entry *h, Elf_Internal_Sym *sym) +{ + /* These relocations don't really reference a symbol. Instead we store + extra data in their addend slot. Ignore the symbol. */ + switch (ELF64_R_TYPE (rel->r_info)) + { + case R_ALPHA_LITUSE: + case R_ALPHA_GPDISP: + case R_ALPHA_HINT: + return NULL; + } + + return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym); +} + +/* Update the got entry reference counts for the section being removed. */ + +static bfd_boolean +elf64_alpha_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info, + asection *sec, const Elf_Internal_Rela *relocs) +{ + Elf_Internal_Shdr *symtab_hdr; + struct alpha_elf_link_hash_entry **sym_hashes; + const Elf_Internal_Rela *rel, *relend; + + if (info->relocatable) + return TRUE; + + symtab_hdr = &elf_symtab_hdr (abfd); + sym_hashes = alpha_elf_sym_hashes (abfd); + + relend = relocs + sec->reloc_count; + for (rel = relocs; rel < relend; rel++) + { + unsigned long r_symndx, r_type; + struct alpha_elf_link_hash_entry *h = NULL; + struct alpha_elf_got_entry *gotent; + + r_symndx = ELF64_R_SYM (rel->r_info); + if (r_symndx >= symtab_hdr->sh_info) + { + h = sym_hashes[r_symndx - symtab_hdr->sh_info]; + while (h->root.root.type == bfd_link_hash_indirect + || h->root.root.type == bfd_link_hash_warning) + h = (struct alpha_elf_link_hash_entry *) h->root.root.u.i.link; + } + + r_type = ELF64_R_TYPE (rel->r_info); + switch (r_type) + { + case R_ALPHA_LITERAL: + /* ??? Ignore re-computation of gotent_flags. We're not + carrying a use-count for each bit in that mask. */ + + case R_ALPHA_TLSGD: + case R_ALPHA_GOTDTPREL: + case R_ALPHA_GOTTPREL: + /* Fetch the got entry from the tables. */ + gotent = get_got_entry (abfd, h, r_type, r_symndx, rel->r_addend); + + /* The got entry *must* exist, since we should have created it + before during check_relocs. Also note that get_got_entry + assumed this was going to be another use, and so incremented + the use count again. Thus the use count must be at least the + one real use and the "use" we just added. */ + if (gotent == NULL || gotent->use_count < 2) + { + abort (); + return FALSE; + } + gotent->use_count -= 2; + break; + + default: + break; + } + } + + return TRUE; +} + /* 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 @@ -2329,7 +2411,13 @@ elf64_alpha_calc_got_offsets_for_symbol (struct alpha_elf_link_hash_entry *h, static void elf64_alpha_calc_got_offsets (struct bfd_link_info *info) { - bfd *i, *got_list = alpha_elf_hash_table(info)->got_list; + bfd *i, *got_list; + struct alpha_elf_link_hash_table * htab; + + htab = alpha_elf_hash_table (info); + if (htab == NULL) + return; + got_list = htab->got_list; /* First, zero out the .got sizes, as we may be recalculating the .got after optimizing it. */ @@ -2337,7 +2425,7 @@ elf64_alpha_calc_got_offsets (struct bfd_link_info *info) alpha_elf_tdata(i)->got->size = 0; /* Next, fill in the offsets for all the global entries. */ - alpha_elf_link_hash_traverse (alpha_elf_hash_table (info), + alpha_elf_link_hash_traverse (htab, elf64_alpha_calc_got_offsets_for_symbol, NULL); @@ -2375,9 +2463,12 @@ static bfd_boolean elf64_alpha_size_got_sections (struct bfd_link_info *info) { bfd *i, *got_list, *cur_got_obj = NULL; - int something_changed = 0; + struct alpha_elf_link_hash_table * htab; - got_list = alpha_elf_hash_table (info)->got_list; + htab = alpha_elf_hash_table (info); + if (htab == NULL) + return FALSE; + got_list = htab->got_list; /* On the first time through, pretend we have an existing got list consisting of all of the input files. */ @@ -2385,7 +2476,12 @@ elf64_alpha_size_got_sections (struct bfd_link_info *info) { for (i = info->input_bfds; i ; i = i->link_next) { - bfd *this_got = alpha_elf_tdata (i)->gotobj; + bfd *this_got; + + if (! is_alpha_elf (i)) + continue; + + this_got = alpha_elf_tdata (i)->gotobj; if (this_got == NULL) continue; @@ -2412,13 +2508,13 @@ elf64_alpha_size_got_sections (struct bfd_link_info *info) if (got_list == NULL) return TRUE; - alpha_elf_hash_table (info)->got_list = got_list; - - /* Force got offsets to be recalculated. */ - something_changed = 1; + htab->got_list = got_list; } cur_got_obj = got_list; + if (cur_got_obj == NULL) + return FALSE; + i = alpha_elf_tdata(cur_got_obj)->got_link_next; while (i != NULL) { @@ -2429,8 +2525,6 @@ elf64_alpha_size_got_sections (struct bfd_link_info *info) alpha_elf_tdata(i)->got->size = 0; i = alpha_elf_tdata(i)->got_link_next; alpha_elf_tdata(cur_got_obj)->got_link_next = i; - - something_changed = 1; } else { @@ -2441,8 +2535,7 @@ elf64_alpha_size_got_sections (struct bfd_link_info *info) /* Once the gots have been merged, fill in the got offsets for everything therein. */ - if (1 || something_changed) - elf64_alpha_calc_got_offsets (info); + elf64_alpha_calc_got_offsets (info); return TRUE; } @@ -2477,28 +2570,34 @@ elf64_alpha_size_plt_section_1 (struct alpha_elf_link_hash_entry *h, PTR data) return TRUE; } -/* Called from relax_section to rebuild the PLT in light of - potential changes in the function's status. */ +/* Called from relax_section to rebuild the PLT in light of potential changes + in the function's status. */ -static bfd_boolean +static void elf64_alpha_size_plt_section (struct bfd_link_info *info) { asection *splt, *spltrel, *sgotplt; unsigned long entries; bfd *dynobj; + struct alpha_elf_link_hash_table * htab; + + htab = alpha_elf_hash_table (info); + if (htab == NULL) + return; dynobj = elf_hash_table(info)->dynobj; splt = bfd_get_section_by_name (dynobj, ".plt"); if (splt == NULL) - return TRUE; + return; splt->size = 0; - alpha_elf_link_hash_traverse (alpha_elf_hash_table (info), + alpha_elf_link_hash_traverse (htab, elf64_alpha_size_plt_section_1, splt); /* Every plt entry requires a JMP_SLOT relocation. */ spltrel = bfd_get_section_by_name (dynobj, ".rela.plt"); + entries = 0; if (splt->size) { if (elf64_alpha_use_secureplt) @@ -2506,8 +2605,6 @@ elf64_alpha_size_plt_section (struct bfd_link_info *info) else entries = (splt->size - OLD_PLT_HEADER_SIZE) / OLD_PLT_ENTRY_SIZE; } - else - entries = 0; spltrel->size = entries * sizeof (Elf64_External_Rela); /* When using the secureplt, we need two words somewhere in the data @@ -2518,8 +2615,6 @@ elf64_alpha_size_plt_section (struct bfd_link_info *info) sgotplt = bfd_get_section_by_name (dynobj, ".got.plt"); sgotplt->size = entries ? 16 : 0; } - - return TRUE; } static bfd_boolean @@ -2527,20 +2622,24 @@ elf64_alpha_always_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED, struct bfd_link_info *info) { bfd *i; + struct alpha_elf_link_hash_table * htab; if (info->relocatable) return TRUE; + htab = alpha_elf_hash_table (info); + if (htab == NULL) + return FALSE; + /* First, take care of the indirect symbols created by versioning. */ - alpha_elf_link_hash_traverse (alpha_elf_hash_table (info), - elf64_alpha_merge_ind_symbols, + alpha_elf_link_hash_traverse (htab, elf64_alpha_merge_ind_symbols, NULL); if (!elf64_alpha_size_got_sections (info)) return FALSE; /* Allocate space for all of the .got subsections. */ - i = alpha_elf_hash_table (info)->got_list; + i = htab->got_list; for ( ; i ; i = alpha_elf_tdata(i)->got_link_next) { asection *s = alpha_elf_tdata(i)->got; @@ -2690,18 +2789,23 @@ elf64_alpha_size_rela_got_1 (struct alpha_elf_link_hash_entry *h, /* Set the sizes of the dynamic relocation sections. */ -static bfd_boolean +static void elf64_alpha_size_rela_got_section (struct bfd_link_info *info) { unsigned long entries; bfd *i, *dynobj; asection *srel; + struct alpha_elf_link_hash_table * htab; + + htab = alpha_elf_hash_table (info); + if (htab == NULL) + return; /* Shared libraries often require RELATIVE relocs, and some relocs require attention for the main application as well. */ entries = 0; - for (i = alpha_elf_hash_table(info)->got_list; + for (i = htab->got_list; i ; i = alpha_elf_tdata(i)->got_link_next) { bfd *j; @@ -2729,15 +2833,13 @@ elf64_alpha_size_rela_got_section (struct bfd_link_info *info) if (!srel) { BFD_ASSERT (entries == 0); - return TRUE; + return; } srel->size = sizeof (Elf64_External_Rela) * entries; /* Now do the non-local symbols. */ - alpha_elf_link_hash_traverse (alpha_elf_hash_table (info), + alpha_elf_link_hash_traverse (htab, elf64_alpha_size_rela_got_1, info); - - return TRUE; } /* Set the sizes of the dynamic sections. */ @@ -2749,6 +2851,11 @@ elf64_alpha_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, bfd *dynobj; asection *s; bfd_boolean relplt; + struct alpha_elf_link_hash_table * htab; + + htab = alpha_elf_hash_table (info); + if (htab == NULL) + return FALSE; dynobj = elf_hash_table(info)->dynobj; BFD_ASSERT(dynobj != NULL); @@ -2768,7 +2875,7 @@ elf64_alpha_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, symbols need dynamic relocation entries and which don't. We've collected information in check_relocs that we can now apply to size the dynamic relocation sections. */ - alpha_elf_link_hash_traverse (alpha_elf_hash_table (info), + alpha_elf_link_hash_traverse (htab, elf64_alpha_calc_dynrel_sizes, info); elf64_alpha_size_rela_got_section (info); @@ -3095,7 +3202,7 @@ elf64_alpha_relax_opt_call (struct alpha_relax_info *info, bfd_vma symval) /* We've now determined that we can skip an initial gp load. Verify that the call and the target use the same gp. */ - if (info->link_info->hash->creator != info->tsec->owner->xvec + if (info->link_info->output_bfd->xvec != info->tsec->owner->xvec || info->gotobj != alpha_elf_tdata (info->tsec->owner)->gotobj) return 0; @@ -3362,9 +3469,9 @@ elf64_alpha_relax_tls_get_addr (struct alpha_relax_info *info, bfd_vma symval, Elf_Internal_Rela *irel, bfd_boolean is_gd) { bfd_byte *pos[5]; - unsigned int insn; + unsigned int insn, tlsgd_reg; Elf_Internal_Rela *gpdisp, *hint; - bfd_boolean dynamic, use_gottprel, pos1_unusable; + bfd_boolean dynamic, use_gottprel; unsigned long new_symndx; dynamic = alpha_elf_dynamic_symbol_p (&info->h->root, info->link_info); @@ -3405,7 +3512,6 @@ elf64_alpha_relax_tls_get_addr (struct alpha_relax_info *info, bfd_vma symval, pos[2] = info->contents + irel[2].r_offset; pos[3] = info->contents + gpdisp->r_offset; pos[4] = pos[3] + gpdisp->r_addend; - pos1_unusable = FALSE; /* Generally, the positions are not allowed to be out of order, lest the modified insn sequence have different register lifetimes. We can make @@ -3416,8 +3522,6 @@ elf64_alpha_relax_tls_get_addr (struct alpha_relax_info *info, bfd_vma symval, pos[0] = pos[1]; pos[1] = tmp; } - else if (pos[1] < pos[0]) - pos1_unusable = TRUE; if (pos[1] >= pos[2] || pos[2] >= pos[3]) return TRUE; @@ -3474,7 +3578,15 @@ elf64_alpha_relax_tls_get_addr (struct alpha_relax_info *info, bfd_vma symval, as appropriate. */ use_gottprel = FALSE; - new_symndx = is_gd ? ELF64_R_SYM (irel->r_info) : 0; + new_symndx = is_gd ? ELF64_R_SYM (irel->r_info) : STN_UNDEF; + + /* Beware of the compiler hoisting part of the sequence out a loop + and adjusting the destination register for the TLSGD insn. If this + happens, there will be a move into $16 before the JSR insn, so only + transformations of the first insn pair should use this register. */ + tlsgd_reg = bfd_get_32 (info->abfd, pos[0]); + tlsgd_reg = (tlsgd_reg >> 21) & 31; + switch (!dynamic && !info->link_info->shared) { case 1: @@ -3488,7 +3600,7 @@ elf64_alpha_relax_tls_get_addr (struct alpha_relax_info *info, bfd_vma symval, if (disp >= -0x8000 && disp < 0x8000) { - insn = (OP_LDA << 26) | (16 << 21) | (31 << 16); + insn = (OP_LDA << 26) | (tlsgd_reg << 21) | (31 << 16); bfd_put_32 (info->abfd, (bfd_vma) insn, pos[0]); bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP, pos[1]); @@ -3499,11 +3611,11 @@ elf64_alpha_relax_tls_get_addr (struct alpha_relax_info *info, bfd_vma symval, } else if (disp >= -(bfd_signed_vma) 0x80000000 && disp < (bfd_signed_vma) 0x7fff8000 - && !pos1_unusable) + && pos[0] + 4 == pos[1]) { - insn = (OP_LDAH << 26) | (16 << 21) | (31 << 16); + insn = (OP_LDAH << 26) | (tlsgd_reg << 21) | (31 << 16); bfd_put_32 (info->abfd, (bfd_vma) insn, pos[0]); - insn = (OP_LDA << 26) | (16 << 21) | (16 << 16); + insn = (OP_LDA << 26) | (tlsgd_reg << 21) | (tlsgd_reg << 16); bfd_put_32 (info->abfd, (bfd_vma) insn, pos[1]); irel[0].r_offset = pos[0] - info->contents; @@ -3518,7 +3630,7 @@ elf64_alpha_relax_tls_get_addr (struct alpha_relax_info *info, bfd_vma symval, default: use_gottprel = TRUE; - insn = (OP_LDQ << 26) | (16 << 21) | (29 << 16); + insn = (OP_LDQ << 26) | (tlsgd_reg << 21) | (29 << 16); bfd_put_32 (info->abfd, (bfd_vma) insn, pos[0]); bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP, pos[1]); @@ -3608,8 +3720,13 @@ elf64_alpha_relax_section (bfd *abfd, asection *sec, Elf_Internal_Sym *isymbuf = NULL; struct alpha_elf_got_entry **local_got_entries; struct alpha_relax_info info; + struct alpha_elf_link_hash_table * htab; + + htab = alpha_elf_hash_table (link_info); + if (htab == NULL) + return FALSE; - /* We are not currently changing any sizes, so only one pass. */ + /* There's nothing to change, yet. */ *again = FALSE; if (link_info->relocatable @@ -3618,7 +3735,25 @@ elf64_alpha_relax_section (bfd *abfd, asection *sec, || sec->reloc_count == 0) return TRUE; - symtab_hdr = &elf_tdata (abfd)->symtab_hdr; + BFD_ASSERT (is_alpha_elf (abfd)); + + /* Make sure our GOT and PLT tables are up-to-date. */ + if (htab->relax_trip != link_info->relax_trip) + { + htab->relax_trip = link_info->relax_trip; + + /* This should never fail after the initial round, since the only + error is GOT overflow, and relaxation only shrinks the table. */ + if (!elf64_alpha_size_got_sections (link_info)) + abort (); + if (elf_hash_table (link_info)->dynamic_sections_created) + { + elf64_alpha_size_plt_section (link_info); + elf64_alpha_size_rela_got_section (link_info); + } + } + + symtab_hdr = &elf_symtab_hdr (abfd); local_got_entries = alpha_elf_tdata(abfd)->local_got_entries; /* Load the relocations for this section. */ @@ -3676,8 +3811,8 @@ elf64_alpha_relax_section (bfd *abfd, asection *sec, case R_ALPHA_TLSLDM: /* The symbol for a TLSLDM reloc is ignored. Collapse the - reloc to the 0 symbol so that they all match. */ - r_symndx = 0; + reloc to the STN_UNDEF (0) symbol so that they all match. */ + r_symndx = STN_UNDEF; break; default: @@ -3827,13 +3962,6 @@ elf64_alpha_relax_section (bfd *abfd, asection *sec, } } - if (!elf64_alpha_size_plt_section (link_info)) - return FALSE; - if (!elf64_alpha_size_got_sections (link_info)) - return FALSE; - if (!elf64_alpha_size_rela_got_section (link_info)) - return FALSE; - if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf) { @@ -3932,7 +4060,7 @@ elf64_alpha_relocate_section_r (bfd *output_bfd ATTRIBUTE_UNUSED, struct elf_link_hash_entry **sym_hashes; bfd_boolean ret_val = TRUE; - symtab_hdr_sh_info = elf_tdata (input_bfd)->symtab_hdr.sh_info; + symtab_hdr_sh_info = elf_symtab_hdr (input_bfd).sh_info; sym_hashes = elf_sym_hashes (input_bfd); relend = relocs + input_section->reloc_count; @@ -3984,16 +4112,10 @@ elf64_alpha_relocate_section_r (bfd *output_bfd ATTRIBUTE_UNUSED, } if (sec != NULL && elf_discarded_section (sec)) - { - /* For relocs against symbols from removed linkonce sections, - or sections discarded by a linker script, we just want the - section contents zeroed. */ - _bfd_clear_contents (elf64_alpha_howto_table + r_type, - input_bfd, contents + rel->r_offset); - rel->r_info = 0; - rel->r_addend = 0; - continue; - } + RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section, + rel, relend, + elf64_alpha_howto_table + r_type, + contents); if (sym != NULL && ELF_ST_TYPE (sym->st_info) == STT_SECTION) rel->r_addend += sec->output_offset; @@ -4020,6 +4142,8 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info, struct alpha_elf_got_entry **local_got_entries; bfd_boolean ret_val; + BFD_ASSERT (is_alpha_elf (input_bfd)); + /* Handle relocatable links with a smaller loop. */ if (info->relocatable) return elf64_alpha_relocate_section_r (output_bfd, info, input_bfd, @@ -4030,7 +4154,7 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info, ret_val = TRUE; - symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; + symtab_hdr = &elf_symtab_hdr (input_bfd); dynobj = elf_hash_table (info)->dynobj; if (dynobj) @@ -4043,7 +4167,7 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info, const char *section_name; section_name = (bfd_elf_string_from_elf_section (input_bfd, elf_elfheader(input_bfd)->e_shstrndx, - elf_section_data(input_section)->rel_hdr.sh_name)); + _bfd_elf_single_rel_hdr (input_section)->sh_name)); BFD_ASSERT(section_name != NULL); srel = bfd_get_section_by_name (dynobj, section_name); } @@ -4111,9 +4235,9 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info, r_symndx = ELF64_R_SYM(rel->r_info); /* The symbol for a TLSLDM reloc is ignored. Collapse the - reloc to the 0 symbol so that they all match. */ + reloc to the STN_UNDEF (0) symbol so that they all match. */ if (r_type == R_ALPHA_TLSLDM) - r_symndx = 0; + r_symndx = STN_UNDEF; if (r_symndx < symtab_hdr->sh_info) { @@ -4123,10 +4247,10 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info, msec = sec; value = _bfd_elf_rela_local_sym (output_bfd, sym, &msec, rel); - /* If this is a tp-relative relocation against sym 0, + /* If this is a tp-relative relocation against sym STN_UNDEF (0), this is hackery from relax_section. Force the value to be the tls module base. */ - if (r_symndx == 0 + if (r_symndx == STN_UNDEF && (r_type == R_ALPHA_TLSLDM || r_type == R_ALPHA_GOTTPREL || r_type == R_ALPHA_TPREL64 @@ -4197,15 +4321,8 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info, } if (sec != NULL && elf_discarded_section (sec)) - { - /* For relocs against symbols from removed linkonce sections, - or sections discarded by a linker script, we just want the - section contents zeroed. Avoid any special processing. */ - _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset); - rel->r_info = 0; - rel->r_addend = 0; - continue; - } + RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section, + rel, relend, howto, contents); addend = rel->r_addend; value += addend; @@ -4412,7 +4529,7 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info, dynaddend = value - dtp_base; } else if (info->shared - && r_symndx != 0 + && r_symndx != STN_UNDEF && (input_section->flags & SEC_ALLOC) && !undef_weak_ref) { @@ -4460,7 +4577,7 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info, /* ??? .eh_frame references to discarded sections will be smashed to relocations against SHN_UNDEF. The .eh_frame format allows NULL to be encoded as 0 in any format, so this works here. */ - if (r_symndx == 0) + if (r_symndx == STN_UNDEF) howto = (elf64_alpha_howto_table + (r_type - R_ALPHA_SREL32 + R_ALPHA_REFLONG)); goto default_reloc; @@ -4931,7 +5048,12 @@ elf64_alpha_final_link (bfd *abfd, struct bfd_link_info *info) const struct ecoff_debug_swap *swap = get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap; HDRR *symhdr = &debug.symbolic_header; - PTR mdebug_handle = NULL; + void * mdebug_handle = NULL; + struct alpha_elf_link_hash_table * htab; + + htab = alpha_elf_hash_table (info); + if (htab == NULL) + return FALSE; /* Go through the sections and collect the mdebug information. */ mdebug_sec = NULL; @@ -5040,15 +5162,11 @@ elf64_alpha_final_link (bfd *abfd, struct bfd_link_info *info) input_section = p->u.indirect.section; input_bfd = input_section->owner; - if (bfd_get_flavour (input_bfd) != bfd_target_elf_flavour - || (get_elf_backend_data (input_bfd) - ->elf_backend_ecoff_debug_swap) == NULL) - { - /* I don't know what a non ALPHA ELF bfd would be - doing with a .mdebug section, but I don't really - want to deal with it. */ - continue; - } + if (! is_alpha_elf (input_bfd)) + /* I don't know what a non ALPHA ELF bfd would be + doing with a .mdebug section, but I don't really + want to deal with it. */ + continue; input_swap = (get_elf_backend_data (input_bfd) ->elf_backend_ecoff_debug_swap); @@ -5071,7 +5189,7 @@ elf64_alpha_final_link (bfd *abfd, struct bfd_link_info *info) interesting information, try to find the symbol in the linker global hash table and save the information for the output external symbols. */ - eraw_src = input_debug.external_ext; + eraw_src = (char *) input_debug.external_ext; eraw_end = (eraw_src + (input_debug.symbolic_header.iextMax * input_swap->external_ext_size)); @@ -5090,8 +5208,7 @@ elf64_alpha_final_link (bfd *abfd, struct bfd_link_info *info) continue; name = input_debug.ssext + ext.asym.iss; - h = alpha_elf_link_hash_lookup (alpha_elf_hash_table (info), - name, FALSE, FALSE, TRUE); + h = alpha_elf_link_hash_lookup (htab, name, FALSE, FALSE, TRUE); if (h == NULL || h->esym.ifd != -2) continue; @@ -5155,7 +5272,7 @@ elf64_alpha_final_link (bfd *abfd, struct bfd_link_info *info) /* The .got subsections... */ { bfd *i, *dynobj = elf_hash_table(info)->dynobj; - for (i = alpha_elf_hash_table(info)->got_list; + for (i = htab->got_list; i != NULL; i = alpha_elf_tdata(i)->got_link_next) { @@ -5274,6 +5391,7 @@ static const struct elf_size_info alpha_elf_size_info = ELFCLASS64, EV_CURRENT, bfd_elf64_write_out_phdrs, bfd_elf64_write_shdrs_and_ehdr, + bfd_elf64_checksum_contents, bfd_elf64_write_relocs, bfd_elf64_swap_symbol_in, bfd_elf64_swap_symbol_out, @@ -5290,6 +5408,7 @@ static const struct elf_size_info alpha_elf_size_info = #define TARGET_LITTLE_SYM bfd_elf64_alpha_vec #define TARGET_LITTLE_NAME "elf64-alpha" #define ELF_ARCH bfd_arch_alpha +#define ELF_TARGET_ID ALPHA_ELF_DATA #define ELF_MACHINE_CODE EM_ALPHA #define ELF_MAXPAGESIZE 0x10000 #define ELF_COMMONPAGESIZE 0x2000 @@ -5325,6 +5444,8 @@ static const struct elf_size_info alpha_elf_size_info = #define elf_backend_add_symbol_hook \ elf64_alpha_add_symbol_hook +#define elf_backend_relocs_compatible \ + _bfd_elf_relocs_compatible #define elf_backend_check_relocs \ elf64_alpha_check_relocs #define elf_backend_create_dynamic_sections \ @@ -5350,6 +5471,10 @@ static const struct elf_size_info alpha_elf_size_info = #define elf_backend_reloc_type_class \ elf64_alpha_reloc_type_class +#define elf_backend_can_gc_sections 1 +#define elf_backend_gc_mark_hook elf64_alpha_gc_mark_hook +#define elf_backend_gc_sweep_hook elf64_alpha_gc_sweep_hook + #define elf_backend_ecoff_debug_swap \ &elf64_alpha_ecoff_debug_swap