aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog22
-rw-r--r--bfd/elf-bfd.h17
-rw-r--r--bfd/elf64-ppc.c216
-rw-r--r--bfd/elf64-ppc.h5
-rw-r--r--bfd/elflink.c29
-rw-r--r--bfd/elfxx-target.h6
-rw-r--r--ld/ChangeLog8
-rw-r--r--ld/emultempl/ppc64elf.em7
-rw-r--r--ld/ldlang.c22
9 files changed, 180 insertions, 152 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 4d1d643..5877459 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,5 +1,27 @@
2008-01-15 Alan Modra <amodra@bigpond.net.au>
+ PR 5604
+ * elf-bfd.h (struct elf_backend_data): Add gc_keep. Remove param
+ names from others.
+ (_bfd_elf_gc_keep): Declare.
+ * elfxx-target.h (elf_backend_gc_keep): Define.
+ (elfNN_bed): Init new field.
+ * elflink.c (_bfd_elf_gc_keep): New function.
+ (bfd_elf_gc_sections): Call gc_keep.
+ * elf64-ppc.c (elf_backend_gc_keep): Define.
+ (struct _ppc64_elf_section_data): Move .opd related fields to
+ a struct so they don't occupy the same storage. Adjust accesses
+ throughout file.
+ (ppc64_elf_gc_keep): New function, split out from..
+ (ppc64_elf_gc_mark_hook): ..here. Don't call _bfd_elf_gc_mark
+ to mark .opd section, just set gc_mark.
+ (ppc64_elf_edit_opd): Remove no_opd_opt parm. Don't set opd->adjust
+ unless we are changing .opd. Test non-NULL opd->adjust at all
+ accesses throughout file.
+ * elf64-ppc.h (ppc64_elf_edit_opd): Update prototype.
+
+2008-01-15 Alan Modra <amodra@bigpond.net.au>
+
* bfd-in.h (BFD_HOST_LONG_LONG): Delete.
* bfd-in2.h: Regenerate.
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 86ddd63..269b115 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -1,6 +1,6 @@
/* BFD back-end data structures for ELF files.
Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
- 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+ 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
Written by Cygnus Support.
This file is part of BFD, the Binary File Descriptor library.
@@ -915,10 +915,15 @@ struct elf_backend_data
bfd_boolean (*elf_backend_modify_program_headers)
(bfd *, struct bfd_link_info *);
+ /* This function is called before section garbage collection to
+ mark entry symbol sections. */
+ void (*gc_keep)
+ (struct bfd_link_info *);
+
/* This function is called during section garbage collection to
mark sections that define global symbols. */
bfd_boolean (*gc_mark_dynamic_ref)
- (struct elf_link_hash_entry *h, void *inf);
+ (struct elf_link_hash_entry *, void *);
/* This function is called during section gc to discover the section a
particular relocation refers to. */
@@ -927,14 +932,13 @@ struct elf_backend_data
/* This function, if defined, is called after the first gc marking pass
to allow the backend to mark additional sections. */
bfd_boolean (*gc_mark_extra_sections)
- (struct bfd_link_info *info, elf_gc_mark_hook_fn gc_mark_hook);
+ (struct bfd_link_info *, elf_gc_mark_hook_fn);
/* This function, if defined, is called during the sweep phase of gc
in order that a backend might update any data structures it might
be maintaining. */
bfd_boolean (*gc_sweep_hook)
- (bfd *abfd, struct bfd_link_info *info, asection *o,
- const Elf_Internal_Rela *relocs);
+ (bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *);
/* This function, if defined, is called after the ELF headers have
been created. This allows for things like the OS and ABI versions
@@ -2034,6 +2038,9 @@ extern bfd_reloc_status_type _bfd_elf_rel_vtable_reloc_fn
extern bfd_boolean bfd_elf_final_link
(bfd *, struct bfd_link_info *);
+extern void _bfd_elf_gc_keep
+ (struct bfd_link_info *info);
+
extern bfd_boolean bfd_elf_gc_mark_dynamic_ref_symbol
(struct elf_link_hash_entry *h, void *inf);
diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
index e8d4cf9..a41269c 100644
--- a/bfd/elf64-ppc.c
+++ b/bfd/elf64-ppc.c
@@ -1,5 +1,5 @@
/* PowerPC64-specific support for 64-bit ELF.
- Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+ Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
Free Software Foundation, Inc.
Written by Linus Nordberg, Swox AB <info@swox.com>,
based on elf32-ppc.c by Ian Lance Taylor.
@@ -96,6 +96,7 @@ static bfd_vma opd_entry_value
#define elf_backend_as_needed_cleanup ppc64_elf_as_needed_cleanup
#define elf_backend_archive_symbol_lookup ppc64_elf_archive_symbol_lookup
#define elf_backend_check_relocs ppc64_elf_check_relocs
+#define elf_backend_gc_keep ppc64_elf_gc_keep
#define elf_backend_gc_mark_dynamic_ref ppc64_elf_gc_mark_dynamic_ref
#define elf_backend_gc_mark_hook ppc64_elf_gc_mark_hook
#define elf_backend_gc_sweep_hook ppc64_elf_gc_sweep_hook
@@ -2608,13 +2609,17 @@ struct _ppc64_elf_section_data
{
struct bfd_elf_section_data elf;
- /* An array with one entry for each opd function descriptor. */
union
{
- /* Points to the function code section for local opd entries. */
- asection **opd_func_sec;
- /* After editing .opd, adjust references to opd local syms. */
- long *opd_adjust;
+ /* An array with one entry for each opd function descriptor. */
+ struct _opd_sec_data
+ {
+ /* Points to the function code section for local opd entries. */
+ asection **func_sec;
+
+ /* After editing .opd, adjust references to opd local syms. */
+ long *adjust;
+ } opd;
/* An array for toc sections, indexed by offset/8.
Specifies the relocation symbol index used at a given toc offset. */
@@ -2648,13 +2653,13 @@ ppc64_elf_new_section_hook (bfd *abfd, asection *sec)
return _bfd_elf_new_section_hook (abfd, sec);
}
-static void *
+static struct _opd_sec_data *
get_opd_info (asection * sec)
{
if (sec != NULL
&& ppc64_elf_section_data (sec) != NULL
&& ppc64_elf_section_data (sec)->sec_type == sec_opd)
- return ppc64_elf_section_data (sec)->u.opd_adjust;
+ return &ppc64_elf_section_data (sec)->u.opd;
return NULL;
}
@@ -4438,20 +4443,14 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
if we reference an .opd symbol (a function descriptor), we
want to keep the function code symbol's section. This is
easy for global symbols, but for local syms we need to keep
- information about the associated function section. Later, if
- edit_opd deletes entries, we'll use this array to adjust
- local syms in .opd. */
- union opd_info {
- asection *func_section;
- long entry_adjust;
- };
+ information about the associated function section. */
bfd_size_type amt;
- amt = sec->size * sizeof (union opd_info) / 8;
+ amt = sec->size * sizeof (*opd_sym_map) / 8;
opd_sym_map = bfd_zalloc (abfd, amt);
if (opd_sym_map == NULL)
return FALSE;
- ppc64_elf_section_data (sec)->u.opd_func_sec = opd_sym_map;
+ ppc64_elf_section_data (sec)->u.opd.func_sec = opd_sym_map;
BFD_ASSERT (ppc64_elf_section_data (sec)->sec_type == sec_normal);
ppc64_elf_section_data (sec)->sec_type = sec_opd;
}
@@ -5069,6 +5068,45 @@ opd_entry_value (asection *opd_sec,
return val;
}
+/* Mark all our entry sym sections, both opd and code section. */
+
+static void
+ppc64_elf_gc_keep (struct bfd_link_info *info)
+{
+ struct ppc_link_hash_table *htab = ppc_hash_table (info);
+ struct bfd_sym_chain *sym;
+
+ for (sym = info->gc_sym_list; sym != NULL; sym = sym->next)
+ {
+ struct ppc_link_hash_entry *eh;
+ asection *sec;
+
+ eh = (struct ppc_link_hash_entry *)
+ elf_link_hash_lookup (&htab->elf, sym->name, FALSE, FALSE, FALSE);
+ if (eh == NULL)
+ continue;
+ if (eh->elf.root.type != bfd_link_hash_defined
+ && eh->elf.root.type != bfd_link_hash_defweak)
+ continue;
+
+ if (eh->is_func_descriptor
+ && (eh->oh->elf.root.type == bfd_link_hash_defined
+ || eh->oh->elf.root.type == bfd_link_hash_defweak))
+ {
+ sec = eh->oh->elf.root.u.def.section;
+ sec->flags |= SEC_KEEP;
+ }
+ else if (get_opd_info (eh->elf.root.u.def.section) != NULL
+ && opd_entry_value (eh->elf.root.u.def.section,
+ eh->elf.root.u.def.value,
+ &sec, NULL) != (bfd_vma) -1)
+ sec->flags |= SEC_KEEP;
+
+ sec = eh->elf.root.u.def.section;
+ sec->flags |= SEC_KEEP;
+ }
+}
+
/* Mark sections containing dynamically referenced symbols. When
building shared libraries, we must assume that any visible symbol is
referenced. */
@@ -5122,53 +5160,13 @@ ppc64_elf_gc_mark_dynamic_ref (struct elf_link_hash_entry *h, void *inf)
static asection *
ppc64_elf_gc_mark_hook (asection *sec,
- struct bfd_link_info *info,
+ struct bfd_link_info *info ATTRIBUTE_UNUSED,
Elf_Internal_Rela *rel,
struct elf_link_hash_entry *h,
Elf_Internal_Sym *sym)
{
asection *rsec;
- /* First mark all our entry sym sections. */
- if (info->gc_sym_list != NULL)
- {
- struct ppc_link_hash_table *htab = ppc_hash_table (info);
- struct bfd_sym_chain *sym = info->gc_sym_list;
-
- info->gc_sym_list = NULL;
- for (; sym != NULL; sym = sym->next)
- {
- struct ppc_link_hash_entry *eh;
-
- eh = (struct ppc_link_hash_entry *)
- elf_link_hash_lookup (&htab->elf, sym->name, FALSE, FALSE, FALSE);
- if (eh == NULL)
- continue;
- if (eh->elf.root.type != bfd_link_hash_defined
- && eh->elf.root.type != bfd_link_hash_defweak)
- continue;
-
- if (eh->is_func_descriptor
- && (eh->oh->elf.root.type == bfd_link_hash_defined
- || eh->oh->elf.root.type == bfd_link_hash_defweak))
- rsec = eh->oh->elf.root.u.def.section;
- else if (get_opd_info (eh->elf.root.u.def.section) != NULL
- && opd_entry_value (eh->elf.root.u.def.section,
- eh->elf.root.u.def.value,
- &rsec, NULL) != (bfd_vma) -1)
- ;
- else
- continue;
-
- if (!rsec->gc_mark)
- _bfd_elf_gc_mark (info, rsec, ppc64_elf_gc_mark_hook);
-
- rsec = eh->elf.root.u.def.section;
- if (!rsec->gc_mark)
- _bfd_elf_gc_mark (info, rsec, ppc64_elf_gc_mark_hook);
- }
- }
-
/* Syms return NULL if we're marking .opd, so we avoid marking all
function sections, as all functions are referenced in .opd. */
rsec = NULL;
@@ -5206,9 +5204,7 @@ ppc64_elf_gc_mark_hook (asection *sec,
|| eh->oh->elf.root.type == bfd_link_hash_defweak))
{
/* They also mark their opd section. */
- if (!eh->elf.root.u.def.section->gc_mark)
- _bfd_elf_gc_mark (info, eh->elf.root.u.def.section,
- ppc64_elf_gc_mark_hook);
+ eh->elf.root.u.def.section->gc_mark = 1;
rsec = eh->oh->elf.root.u.def.section;
}
@@ -5216,11 +5212,7 @@ ppc64_elf_gc_mark_hook (asection *sec,
&& opd_entry_value (eh->elf.root.u.def.section,
eh->elf.root.u.def.value,
&rsec, NULL) != (bfd_vma) -1)
- {
- if (!eh->elf.root.u.def.section->gc_mark)
- _bfd_elf_gc_mark (info, eh->elf.root.u.def.section,
- ppc64_elf_gc_mark_hook);
- }
+ eh->elf.root.u.def.section->gc_mark = 1;
else
rsec = h->root.u.def.section;
break;
@@ -5236,16 +5228,15 @@ ppc64_elf_gc_mark_hook (asection *sec,
}
else
{
- asection **opd_sym_section;
+ struct _opd_sec_data *opd;
rsec = bfd_section_from_elf_index (sec->owner, sym->st_shndx);
- opd_sym_section = get_opd_info (rsec);
- if (opd_sym_section != NULL)
+ opd = get_opd_info (rsec);
+ if (opd != NULL && opd->func_sec != NULL)
{
- if (!rsec->gc_mark)
- _bfd_elf_gc_mark (info, rsec, ppc64_elf_gc_mark_hook);
+ rsec->gc_mark = 1;
- rsec = opd_sym_section[(sym->st_value + rel->r_addend) / 8];
+ rsec = opd->func_sec[(sym->st_value + rel->r_addend) / 8];
}
}
@@ -6159,7 +6150,7 @@ adjust_opd_syms (struct elf_link_hash_entry *h, void *inf ATTRIBUTE_UNUSED)
{
struct ppc_link_hash_entry *eh;
asection *sym_sec;
- long *opd_adjust;
+ struct _opd_sec_data *opd;
if (h->root.type == bfd_link_hash_indirect)
return TRUE;
@@ -6176,10 +6167,10 @@ adjust_opd_syms (struct elf_link_hash_entry *h, void *inf ATTRIBUTE_UNUSED)
return TRUE;
sym_sec = eh->elf.root.u.def.section;
- opd_adjust = get_opd_info (sym_sec);
- if (opd_adjust != NULL)
+ opd = get_opd_info (sym_sec);
+ if (opd != NULL && opd->adjust != NULL)
{
- long adjust = opd_adjust[eh->elf.root.u.def.value / 8];
+ long adjust = opd->adjust[eh->elf.root.u.def.value / 8];
if (adjust == -1)
{
/* This entry has been deleted. */
@@ -6345,7 +6336,6 @@ dec_dynrel_count (bfd_vma r_info,
bfd_boolean
ppc64_elf_edit_opd (bfd *obfd, struct bfd_link_info *info,
- bfd_boolean no_opd_opt,
bfd_boolean non_overlapping)
{
bfd *ibfd;
@@ -6360,8 +6350,7 @@ ppc64_elf_edit_opd (bfd *obfd, struct bfd_link_info *info,
Elf_Internal_Sym *local_syms;
struct elf_link_hash_entry **sym_hashes;
bfd_vma offset;
- bfd_size_type amt;
- long *opd_adjust;
+ struct _opd_sec_data *opd;
bfd_boolean need_edit, add_aux_fields;
bfd_size_type cnt_16b = 0;
@@ -6369,24 +6358,6 @@ ppc64_elf_edit_opd (bfd *obfd, struct bfd_link_info *info,
if (sec == NULL || sec->size == 0)
continue;
- amt = sec->size * sizeof (long) / 8;
- opd_adjust = get_opd_info (sec);
- if (opd_adjust == NULL)
- {
- /* check_relocs hasn't been called. Must be a ld -r link
- or --just-symbols object. */
- opd_adjust = bfd_alloc (obfd, amt);
- if (opd_adjust == NULL)
- return FALSE;
- ppc64_elf_section_data (sec)->u.opd_adjust = opd_adjust;
- BFD_ASSERT (ppc64_elf_section_data (sec)->sec_type == sec_normal);
- ppc64_elf_section_data (sec)->sec_type = sec_opd;
- }
- memset (opd_adjust, 0, amt);
-
- if (no_opd_opt)
- continue;
-
if (sec->sec_info_type == ELF_INFO_TYPE_JUST_SYMS)
continue;
@@ -6530,6 +6501,14 @@ ppc64_elf_edit_opd (bfd *obfd, struct bfd_link_info *info,
bfd_byte *new_contents = NULL;
bfd_boolean skip;
long opd_ent_size;
+ bfd_size_type amt;
+
+ amt = sec->size * sizeof (long) / 8;
+ opd = &ppc64_elf_section_data (sec)->u.opd;
+ opd->adjust = bfd_zalloc (obfd, amt);
+ if (opd->adjust == NULL)
+ return FALSE;
+ ppc64_elf_section_data (sec)->sec_type = sec_opd;
/* This seems a waste of time as input .opd sections are all
zeros as generated by gcc, but I suppose there's no reason
@@ -6621,7 +6600,7 @@ ppc64_elf_edit_opd (bfd *obfd, struct bfd_link_info *info,
fdh->elf.root.u.def.value = 0;
fdh->elf.root.u.def.section = sym_sec;
}
- opd_adjust[rel->r_offset / 8] = -1;
+ opd->adjust[rel->r_offset / 8] = -1;
}
else
{
@@ -6646,7 +6625,7 @@ ppc64_elf_edit_opd (bfd *obfd, struct bfd_link_info *info,
for the function descriptor sym which we
don't have at the moment. So keep an
array of adjustments. */
- opd_adjust[rel->r_offset / 8]
+ opd->adjust[rel->r_offset / 8]
= (wptr - new_contents) - (rptr - sec->contents);
if (wptr != rptr)
@@ -6675,7 +6654,7 @@ ppc64_elf_edit_opd (bfd *obfd, struct bfd_link_info *info,
/* We need to adjust any reloc offsets to point to the
new opd entries. While we're at it, we may as well
remove redundant relocs. */
- rel->r_offset += opd_adjust[(offset - opd_ent_size) / 8];
+ rel->r_offset += opd->adjust[(offset - opd_ent_size) / 8];
if (write_rel != rel)
memcpy (write_rel, rel, sizeof (*rel));
++write_rel;
@@ -8964,7 +8943,7 @@ toc_adjusting_stub_needed (struct bfd_link_info *info, asection *isec)
struct elf_link_hash_entry *h;
Elf_Internal_Sym *sym;
asection *sym_sec;
- long *opd_adjust;
+ struct _opd_sec_data *opd;
bfd_vma sym_value;
bfd_vma dest;
@@ -9022,14 +9001,14 @@ toc_adjusting_stub_needed (struct bfd_link_info *info, asection *isec)
sym_value += rel->r_addend;
/* If this branch reloc uses an opd sym, find the code section. */
- opd_adjust = get_opd_info (sym_sec);
- if (opd_adjust != NULL)
+ opd = get_opd_info (sym_sec);
+ if (opd != NULL)
{
- if (h == NULL)
+ if (h == NULL && opd->adjust != NULL)
{
long adjust;
- adjust = opd_adjust[sym->st_value / 8];
+ adjust = opd->adjust[sym->st_value / 8];
if (adjust == -1)
/* Assume deleted functions won't ever be called. */
continue;
@@ -9384,7 +9363,7 @@ ppc64_elf_size_stubs (bfd *output_bfd,
Elf_Internal_Sym *sym;
char *stub_name;
const asection *id_sec;
- long *opd_adjust;
+ struct _opd_sec_data *opd;
r_type = ELF64_R_TYPE (irela->r_info);
r_indx = ELF64_R_SYM (irela->r_info);
@@ -9461,14 +9440,14 @@ ppc64_elf_size_stubs (bfd *output_bfd,
}
code_sec = sym_sec;
- opd_adjust = get_opd_info (sym_sec);
- if (opd_adjust != NULL)
+ opd = get_opd_info (sym_sec);
+ if (opd != NULL)
{
bfd_vma dest;
- if (hash == NULL)
+ if (hash == NULL && opd->adjust != NULL)
{
- long adjust = opd_adjust[sym_value / 8];
+ long adjust = opd->adjust[sym_value / 8];
if (adjust == -1)
continue;
sym_value += adjust;
@@ -10032,17 +10011,17 @@ ppc64_elf_relocate_section (bfd *output_bfd,
if (r_symndx < symtab_hdr->sh_info)
{
/* It's a local symbol. */
- long *opd_adjust;
+ struct _opd_sec_data *opd;
sym = local_syms + r_symndx;
sec = local_sections[r_symndx];
sym_name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym, sec);
sym_type = ELF64_ST_TYPE (sym->st_info);
relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
- opd_adjust = get_opd_info (sec);
- if (opd_adjust != NULL)
+ opd = get_opd_info (sec);
+ if (opd != NULL && opd->adjust != NULL)
{
- long adjust = opd_adjust[(sym->st_value + rel->r_addend) / 8];
+ long adjust = opd->adjust[(sym->st_value + rel->r_addend) / 8];
if (adjust == -1)
relocation = 0;
else
@@ -11361,21 +11340,22 @@ ppc64_elf_output_symbol_hook (struct bfd_link_info *info,
asection *input_sec,
struct elf_link_hash_entry *h)
{
- long *opd_adjust, adjust;
+ struct _opd_sec_data *opd;
+ long adjust;
bfd_vma value;
if (h != NULL)
return TRUE;
- opd_adjust = get_opd_info (input_sec);
- if (opd_adjust == NULL)
+ opd = get_opd_info (input_sec);
+ if (opd == NULL || opd->adjust == NULL)
return TRUE;
value = elfsym->st_value - input_sec->output_offset;
if (!info->relocatable)
value -= input_sec->output_section->vma;
- adjust = opd_adjust[value / 8];
+ adjust = opd->adjust[value / 8];
if (adjust == -1)
elfsym->st_value = 0;
else
diff --git a/bfd/elf64-ppc.h b/bfd/elf64-ppc.h
index cdd79d2..687b4a1 100644
--- a/bfd/elf64-ppc.h
+++ b/bfd/elf64-ppc.h
@@ -1,5 +1,6 @@
/* PowerPC64-specific support for 64-bit ELF.
- Copyright 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
+ Copyright 2002, 2003, 2004, 2005, 2007, 2008
+ Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
@@ -21,7 +22,7 @@
void ppc64_elf_init_stub_bfd
(bfd *, struct bfd_link_info *);
bfd_boolean ppc64_elf_edit_opd
- (bfd *, struct bfd_link_info *, bfd_boolean, bfd_boolean);
+ (bfd *, struct bfd_link_info *, bfd_boolean);
asection *ppc64_elf_tls_setup
(bfd *, struct bfd_link_info *);
bfd_boolean ppc64_elf_tls_optimize
diff --git a/bfd/elflink.c b/bfd/elflink.c
index f9f7e13..ed69181 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -1,6 +1,6 @@
/* ELF linking support for BFD.
Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
- 2005, 2006, 2007 Free Software Foundation, Inc.
+ 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
@@ -11463,6 +11463,29 @@ bfd_elf_gc_mark_dynamic_ref_symbol (struct elf_link_hash_entry *h, void *inf)
return TRUE;
}
+/* Keep all sections containing symbols undefined on the command-line,
+ and the section containing the entry symbol. */
+
+void
+_bfd_elf_gc_keep (struct bfd_link_info *info)
+{
+ struct bfd_sym_chain *sym;
+
+ for (sym = info->gc_sym_list; sym != NULL; sym = sym->next)
+ {
+ struct elf_link_hash_entry *h;
+
+ h = elf_link_hash_lookup (elf_hash_table (info), sym->name,
+ FALSE, FALSE, FALSE);
+
+ if (h != NULL
+ && (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ && !bfd_is_abs_section (h->root.u.def.section))
+ h->root.u.def.section->flags |= SEC_KEEP;
+ }
+}
+
/* Do mark and sweep of unused sections. */
bfd_boolean
@@ -11480,6 +11503,8 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info)
return TRUE;
}
+ bed->gc_keep (info);
+
/* Try to parse each bfd's .eh_frame section. Point elf_eh_frame_section
at the .eh_frame section if we can mark the FDEs individually. */
_bfd_elf_begin_eh_frame_parsing (info);
@@ -11536,7 +11561,7 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info)
/* Allow the backend to mark additional target specific sections. */
if (bed->gc_mark_extra_sections)
- bed->gc_mark_extra_sections(info, gc_mark_hook);
+ bed->gc_mark_extra_sections (info, gc_mark_hook);
/* ... and mark SEC_EXCLUDE for those that go. */
return elf_gc_sweep (abfd, info);
diff --git a/bfd/elfxx-target.h b/bfd/elfxx-target.h
index 3cb1249..53d3c34 100644
--- a/bfd/elfxx-target.h
+++ b/bfd/elfxx-target.h
@@ -1,6 +1,6 @@
/* Target definitions for NN-bit ELF
Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
- 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+ 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
@@ -132,6 +132,9 @@
#ifndef elf_backend_want_got_sym
#define elf_backend_want_got_sym 1
#endif
+#ifndef elf_backend_gc_keep
+#define elf_backend_gc_keep _bfd_elf_gc_keep
+#endif
#ifndef elf_backend_gc_mark_dynamic_ref
#define elf_backend_gc_mark_dynamic_ref bfd_elf_gc_mark_dynamic_ref_symbol
#endif
@@ -656,6 +659,7 @@ static struct elf_backend_data elfNN_bed =
elf_backend_additional_program_headers,
elf_backend_modify_segment_map,
elf_backend_modify_program_headers,
+ elf_backend_gc_keep,
elf_backend_gc_mark_dynamic_ref,
elf_backend_gc_mark_hook,
elf_backend_gc_mark_extra_sections,
diff --git a/ld/ChangeLog b/ld/ChangeLog
index 372422d..64e6a08 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,11 @@
+2008-01-15 Alan Modra <amodra@bigpond.net.au>
+
+ PR 5604
+ * ldlang.c (lang_gc_sections): Move code to set SEC_KEEP on entry
+ syms to _bfd_elf_gc_keep.
+ * emultempl/ppc64elf.em (ppc_before_allocation): Don't call
+ ppc64_elf_edit_opd if no_opd_opt.
+
2008-01-11 Tristan Gingold <gingold@adacore.com>
Eric Botcazou <ebotcazou@adacore.com>
diff --git a/ld/emultempl/ppc64elf.em b/ld/emultempl/ppc64elf.em
index d5578c3..b23ae43 100644
--- a/ld/emultempl/ppc64elf.em
+++ b/ld/emultempl/ppc64elf.em
@@ -1,5 +1,6 @@
# This shell script emits a C file. -*- C -*-
-# Copyright 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
+# Copyright 2002, 2003, 2004, 2005, 2007, 2008
+# Free Software Foundation, Inc.
#
# This file is part of the GNU Binutils.
#
@@ -103,8 +104,8 @@ ppc_before_allocation (void)
{
if (stub_file != NULL)
{
- if (!ppc64_elf_edit_opd (output_bfd, &link_info, no_opd_opt,
- non_overlapping_opd))
+ if (!no_opd_opt
+ && !ppc64_elf_edit_opd (output_bfd, &link_info, non_overlapping_opd))
einfo ("%X%P: can not edit %s %E\n", "opd");
if (ppc64_elf_tls_setup (output_bfd, &link_info) && !no_tls_opt)
diff --git a/ld/ldlang.c b/ld/ldlang.c
index 63326e5..ec5f000 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -1,6 +1,6 @@
/* Linker command language support.
Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004, 2005, 2006, 2007
+ 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
Free Software Foundation, Inc.
This file is part of the GNU Binutils.
@@ -5670,30 +5670,10 @@ lang_gc_sections_1 (lang_statement_union_type *s)
static void
lang_gc_sections (void)
{
- struct bfd_link_hash_entry *h;
- ldlang_undef_chain_list_type *ulist;
-
/* Keep all sections so marked in the link script. */
lang_gc_sections_1 (statement_list.head);
- /* Keep all sections containing symbols undefined on the command-line,
- and the section containing the entry symbol. */
-
- for (ulist = link_info.gc_sym_list; ulist; ulist = ulist->next)
- {
- h = bfd_link_hash_lookup (link_info.hash, ulist->name,
- FALSE, FALSE, FALSE);
-
- if (h != NULL
- && (h->type == bfd_link_hash_defined
- || h->type == bfd_link_hash_defweak)
- && ! bfd_is_abs_section (h->u.def.section))
- {
- h->u.def.section->flags |= SEC_KEEP;
- }
- }
-
/* SEC_EXCLUDE is ignored when doing a relocatable link, except in
the special case of debug info. (See bfd/stabs.c)
Twiddle the flag here, to simplify later linker code. */