aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2011-03-29 21:18:16 +0000
committerRichard Henderson <rth@redhat.com>2011-03-29 21:18:16 +0000
commite117360eb31ae7d2d10e08274171a4159949b704 (patch)
tree65abdcd86a77df38db6bc20099dcae20331a2105 /bfd
parent6294f8ea1e9a686caac13edbe4d9df2c9620607f (diff)
downloadgdb-e117360eb31ae7d2d10e08274171a4159949b704.zip
gdb-e117360eb31ae7d2d10e08274171a4159949b704.tar.gz
gdb-e117360eb31ae7d2d10e08274171a4159949b704.tar.bz2
* elf64-alpha.c (elf64_alpha_gc_mark_hook): New.
(elf64_alpha_gc_sweep_hook): New. (elf_backend_gc_mark_hook, elf_backend_gc_sweep_hook): New. (elf_backend_can_gc_sections): New.
Diffstat (limited to 'bfd')
-rw-r--r--bfd/ChangeLog7
-rw-r--r--bfd/elf64-alpha.c93
2 files changed, 99 insertions, 1 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 80fa801..9f5d1b5 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,10 @@
+2011-03-29 Richard Henderson <rth@redhat.com>
+
+ * elf64-alpha.c (elf64_alpha_gc_mark_hook): New.
+ (elf64_alpha_gc_sweep_hook): New.
+ (elf_backend_gc_mark_hook, elf_backend_gc_sweep_hook): New.
+ (elf_backend_can_gc_sections): New.
+
2011-03-26 John Marino <binutils@marino.st>
* config.bfd: Add x86_64-*-dragonfly*, fix i386-*-dragonfly*.
diff --git a/bfd/elf64-alpha.c b/bfd/elf64-alpha.c
index aaa6e20..2b15a81 100644
--- a/bfd/elf64-alpha.c
+++ b/bfd/elf64-alpha.c
@@ -1,6 +1,6 @@
/* 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.
@@ -1988,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
@@ -5384,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