From 74f0fb5065323b33bef71dfcbbd9b595c88c6c0c Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Tue, 15 Jan 2008 07:25:49 +0000 Subject: [PATCH] bfd/ 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. ld/ 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. --- bfd/ChangeLog | 22 ++++ bfd/elf-bfd.h | 17 ++- bfd/elf64-ppc.c | 216 ++++++++++++++++++--------------------- bfd/elf64-ppc.h | 5 +- bfd/elflink.c | 29 +++++- bfd/elfxx-target.h | 6 +- ld/ChangeLog | 8 ++ ld/emultempl/ppc64elf.em | 7 +- ld/ldlang.c | 22 +--- 9 files changed, 180 insertions(+), 152 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 4d1d643f2f..587745982c 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,25 @@ +2008-01-15 Alan Modra + + 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 * bfd-in.h (BFD_HOST_LONG_LONG): Delete. diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index 86ddd63bca..269b1150f1 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 e8d4cf9e94..a41269c555 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 , 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 cdd79d2478..687b4a1bf0 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 f9f7e13f51..ed691818c6 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 3cb124939e..53d3c34dd0 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 372422d1b0..64e6a085b2 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,11 @@ +2008-01-15 Alan Modra + + 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 Eric Botcazou diff --git a/ld/emultempl/ppc64elf.em b/ld/emultempl/ppc64elf.em index d5578c3796..b23ae4381a 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 63326e53bf..ec5f000af4 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. */ -- 2.34.1