/* Alpha specific support for 64-bit ELF
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
- 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+ 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
Contributed by Richard Henderson <rth@tamu.edu>.
This file is part of BFD, the Binary File Descriptor library.
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 */
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
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
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:
}
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;
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);
}
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)
{
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
}
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;
dynaddend = value - dtp_base;
}
else if (info->shared
- && r_symndx != 0
+ && r_symndx != STN_UNDEF
&& (input_section->flags & SEC_ALLOC)
&& !undef_weak_ref)
{
/* ??? .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;
#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