From 99877b66add640cf4034b264219d5d8f511a5f72 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Tue, 10 Aug 2004 11:23:03 +0000 Subject: [PATCH] bfd/ * elf64-ppc.c (struct ppc_link_hash_entry): Add was_undefined. (struct ppc_link_hash_table): Remove no_multi_toc, multi_toc_needed. Make emit_stub_syms, stub_error and has_14bit_branch bit-fields. Add twiddled_syms. (link_hash_newfunc): Init was_undefined. (add_symbol_adjust): Don't set undefined dot symbols to defweak; Use undefweak instead. (ppc64_elf_check_directives): Fix undefs chain. (ppc64_elf_next_toc_section): Remove no_multi_toc and multi_toc_needed references. (ppc64_elf_size_stubs): Adjust for add_symbol_adjust change. (undo_symbol_twiddle, ppc64_elf_restore_symbols): New functions. * elf64-ppc.h (ppc64_elf_restore_symbols): Declare. ld/ * emultempl/ppc64elf.em (gld${EMULATION_NAME}_finish): Call ppc64_elf_restore_symbols. --- bfd/ChangeLog | 16 +++++ bfd/elf64-ppc.c | 136 +++++++++++++++++++++++++++++---------- bfd/elf64-ppc.h | 2 + ld/ChangeLog | 5 ++ ld/emultempl/ppc64elf.em | 2 + 5 files changed, 126 insertions(+), 35 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 5a81642f614..e3afaa480cc 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,19 @@ +2004-08-10 Alan Modra + + * elf64-ppc.c (struct ppc_link_hash_entry): Add was_undefined. + (struct ppc_link_hash_table): Remove no_multi_toc, multi_toc_needed. + Make emit_stub_syms, stub_error and has_14bit_branch bit-fields. + Add twiddled_syms. + (link_hash_newfunc): Init was_undefined. + (add_symbol_adjust): Don't set undefined dot symbols to defweak; + Use undefweak instead. + (ppc64_elf_check_directives): Fix undefs chain. + (ppc64_elf_next_toc_section): Remove no_multi_toc and multi_toc_needed + references. + (ppc64_elf_size_stubs): Adjust for add_symbol_adjust change. + (undo_symbol_twiddle, ppc64_elf_restore_symbols): New functions. + * elf64-ppc.h (ppc64_elf_restore_symbols): Declare. + 2004-08-09 Jakub Jelinek * elf64-x86-64.c (elf64_x86_64_relocate_section): For -fno-pic diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index c34bf151931..b801887a26e 100644 --- a/bfd/elf64-ppc.c +++ b/bfd/elf64-ppc.c @@ -2788,6 +2788,9 @@ struct ppc_link_hash_entry globals defined in any opd section. */ unsigned int adjust_done:1; + /* Set if we twiddled this symbol to weak at some stage. */ + unsigned int was_undefined:1; + /* Contexts in which symbol is used in the GOT (or TOC). TLS_GD .. TLS_EXPLICIT bits are or'd into the mask as the corresponding relocs are encountered during check_relocs. @@ -2836,10 +2839,6 @@ struct ppc_link_hash_table bfd_vma toc_off; } *stub_group; - /* Support for multiple toc sections. */ - unsigned int no_multi_toc; - unsigned int multi_toc_needed; - /* Temp used when calculating TOC pointers. */ bfd_vma toc_curr; @@ -2871,14 +2870,17 @@ struct ppc_link_hash_table unsigned long stub_count[ppc_stub_plt_call]; /* Set if we should emit symbols for stubs. */ - unsigned int emit_stub_syms; + unsigned int emit_stub_syms:1; /* Set on error. */ - unsigned int stub_error; + unsigned int stub_error:1; /* Flag set when small branches are detected. Used to select suitable defaults for the stub group size. */ - unsigned int has_14bit_branch; + unsigned int has_14bit_branch:1; + + /* Temp used by ppc64_elf_check_directives. */ + unsigned int twiddled_syms:1; /* Incremented every time we size stubs. */ unsigned int stub_iteration; @@ -2995,6 +2997,7 @@ link_hash_newfunc (struct bfd_hash_entry *entry, eh->is_func = 0; eh->is_func_descriptor = 0; eh->adjust_done = 0; + eh->was_undefined = 0; eh->tls_mask = 0; } @@ -3560,16 +3563,17 @@ ppc64_elf_archive_symbol_lookup (bfd *abfd, } /* This function satisfies all old ABI object references to ".bar" if a - new ABI object defines "bar". This stops later archive searches from - including an object if we already have a function descriptor - definition. It also prevents the linker complaining about undefined - symbols. */ + new ABI object defines "bar". Well, at least, undefined dot symbols + are made weak. This stops later archive searches from including an + object if we already have a function descriptor definition. It also + prevents the linker complaining about undefined symbols. */ static bfd_boolean add_symbol_adjust (struct elf_link_hash_entry *h, void *inf) { struct bfd_link_info *info; struct ppc_link_hash_table *htab; + struct ppc_link_hash_entry *eh; struct ppc_link_hash_entry *fdh; if (h->root.type == bfd_link_hash_indirect) @@ -3584,13 +3588,15 @@ add_symbol_adjust (struct elf_link_hash_entry *h, void *inf) info = inf; htab = ppc_hash_table (info); - fdh = get_fdh ((struct ppc_link_hash_entry *) h, htab); + eh = (struct ppc_link_hash_entry *) h; + fdh = get_fdh (eh, htab); if (fdh != NULL) { - h->root.type = bfd_link_hash_defweak; - h->root.u.def.section = &bfd_und_section; - h->root.u.def.value = 0; + eh->elf.root.type = bfd_link_hash_undefweak; + eh->was_undefined = 1; + htab->twiddled_syms = 1; } + return TRUE; } @@ -3598,8 +3604,45 @@ static bfd_boolean ppc64_elf_check_directives (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info) { - struct ppc_link_hash_table *htab = ppc_hash_table (info); + struct ppc_link_hash_table *htab; + + htab = ppc_hash_table (info); elf_link_hash_traverse (&htab->elf, add_symbol_adjust, info); + + /* We need to fix the undefs list for any syms we have twiddled to + undef_weak. */ + if (htab->twiddled_syms) + { + struct bfd_link_hash_entry **pun; + + pun = &htab->elf.root.undefs; + while (*pun != NULL) + { + struct bfd_link_hash_entry *h = *pun; + + if (h->type != bfd_link_hash_undefined + && h->type != bfd_link_hash_common) + { + *pun = h->und_next; + h->und_next = NULL; + if (h == htab->elf.root.undefs_tail) + { + if (pun == &htab->elf.root.undefs) + htab->elf.root.undefs_tail = NULL; + else + /* pun points at an und_next field. Go back to + the start of the link_hash_entry. */ + htab->elf.root.undefs_tail = (struct bfd_link_hash_entry *) + ((char *) pun - ((char *) &h->und_next - (char *) h)); + break; + } + } + else + pun = &h->und_next; + } + + htab->twiddled_syms = 0; + } return TRUE; } @@ -6862,20 +6905,15 @@ void ppc64_elf_next_toc_section (struct bfd_link_info *info, asection *isec) { struct ppc_link_hash_table *htab = ppc_hash_table (info); + bfd_vma addr = isec->output_offset + isec->output_section->vma; + bfd_vma off = addr - htab->toc_curr; - if (!htab->no_multi_toc) - { - bfd_vma addr = isec->output_offset + isec->output_section->vma; - bfd_vma off = addr - htab->toc_curr; - if (off + isec->size > 0x10000) - { - htab->toc_curr = addr; - htab->multi_toc_needed = 1; - } - elf_gp (isec->owner) = (htab->toc_curr - - elf_gp (isec->output_section->owner) - + TOC_BASE_OFF); - } + if (off + isec->size > 0x10000) + htab->toc_curr = addr; + + elf_gp (isec->owner) = (htab->toc_curr + - elf_gp (isec->output_section->owner) + + TOC_BASE_OFF); } /* Called after the last call to the above function. */ @@ -7222,15 +7260,12 @@ ppc64_elf_size_stubs (bfd *output_bfd, else { sym_value = 0; - /* Recognise an old ABI func code entry sym by - the weird section for a defined sym, and use - the func descriptor sym instead. */ - if (hash->elf.root.type == bfd_link_hash_defweak - && hash->elf.root.u.def.section == &bfd_und_section + /* Recognise an old ABI func code entry sym, and + use the func descriptor sym instead. */ + if (hash->elf.root.type == bfd_link_hash_undefweak && hash->elf.root.root.string[0] == '.' && (fdh = get_fdh (hash, htab)) != NULL) { - sym_sec = NULL; if (fdh->elf.root.type == bfd_link_hash_defined || fdh->elf.root.type == bfd_link_hash_defweak) { @@ -7239,6 +7274,8 @@ ppc64_elf_size_stubs (bfd *output_bfd, if (sym_sec->output_section != NULL) ok_dest = TRUE; } + else + fdh = NULL; } else if (hash->elf.root.type == bfd_link_hash_defined || hash->elf.root.type == bfd_link_hash_defweak) @@ -7289,6 +7326,7 @@ ppc64_elf_size_stubs (bfd *output_bfd, { /* Fixup old ABI sym to point at code entry. */ + hash->elf.root.type = bfd_link_hash_defweak; hash->elf.root.u.def.section = code_sec; hash->elf.root.u.def.value = sym_value; } @@ -7662,6 +7700,34 @@ ppc64_elf_build_stubs (bfd_boolean emit_stub_syms, return TRUE; } +/* This function undoes the changes made by add_symbol_adjust. */ + +static bfd_boolean +undo_symbol_twiddle (struct elf_link_hash_entry *h, void *inf ATTRIBUTE_UNUSED) +{ + struct ppc_link_hash_entry *eh; + + if (h->root.type == bfd_link_hash_indirect) + return TRUE; + + if (h->root.type == bfd_link_hash_warning) + h = (struct elf_link_hash_entry *) h->root.u.i.link; + + eh = (struct ppc_link_hash_entry *) h; + if (eh->elf.root.type != bfd_link_hash_undefweak || !eh->was_undefined) + return TRUE; + + eh->elf.root.type = bfd_link_hash_undefined; + return TRUE; +} + +void +ppc64_elf_restore_symbols (struct bfd_link_info *info) +{ + struct ppc_link_hash_table *htab = ppc_hash_table (info); + elf_link_hash_traverse (&htab->elf, undo_symbol_twiddle, info); +} + /* The RELOCATE_SECTION function is called by the ELF backend linker to handle the relocations for a section. diff --git a/bfd/elf64-ppc.h b/bfd/elf64-ppc.h index 171e5525acd..b1f4343a4ea 100644 --- a/bfd/elf64-ppc.h +++ b/bfd/elf64-ppc.h @@ -40,3 +40,5 @@ bfd_boolean ppc64_elf_size_stubs asection *(*) (const char *, asection *), void (*) (void)); bfd_boolean ppc64_elf_build_stubs (bfd_boolean, struct bfd_link_info *, char **); +void ppc64_elf_restore_symbols + (struct bfd_link_info *info); diff --git a/ld/ChangeLog b/ld/ChangeLog index 658ea4afb06..374d8ceba5b 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,8 @@ +2004-08-10 Alan Modra + + * emultempl/ppc64elf.em (gld${EMULATION_NAME}_finish): Call + ppc64_elf_restore_symbols. + 2004-08-09 Alan Modra * emultempl/ppc64elf.em (gld${EMULATION_NAME}_finish): Error if diff --git a/ld/emultempl/ppc64elf.em b/ld/emultempl/ppc64elf.em index ffd6a2bcf08..f2d5e6ebfbb 100644 --- a/ld/emultempl/ppc64elf.em +++ b/ld/emultempl/ppc64elf.em @@ -379,6 +379,8 @@ gld${EMULATION_NAME}_finish (void) if (msg != NULL) free (msg); } + + ppc64_elf_restore_symbols (&link_info); } -- 2.30.2