From a38a07e07c75f3d498fb9187a7924d159be6326c Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Tue, 6 Nov 2012 05:18:03 +0000 Subject: [PATCH] bfd/ * elf64-ppc.c (struct ppc_link_hash_table): Add dot_toc_dot. (ppc64_elf_size_stubs): Lookup ".TOC.". (ppc64_elf_relocate_section): Resolve special symbol ".TOC.". gas/ * config/tc-ppc.c (ppc_elf_adjust_symtab): New function, split out.. (ppc_frob_file_before_adjust): ..from here. (md_apply_fix): Set BSF_KEEP on .TOC. if not @tocbase. * config/tc-ppc.h (ppc_elf_adjust_symtab): Declare. (tc_adjust_symtab): Define. --- bfd/ChangeLog | 8 +++++++- bfd/elf64-ppc.c | 13 +++++++++++++ gas/ChangeLog | 8 ++++++++ gas/config/tc-ppc.c | 37 ++++++++++++++++++++++++++++++++----- gas/config/tc-ppc.h | 3 +++ 5 files changed, 63 insertions(+), 6 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index cebc007944d..ebec0d78dbf 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,9 @@ +2012-11-06 Alan Modra + + * elf64-ppc.c (struct ppc_link_hash_table): Add dot_toc_dot. + (ppc64_elf_size_stubs): Lookup ".TOC.". + (ppc64_elf_relocate_section): Resolve special symbol ".TOC.". + 2012-11-06 Alan Modra * elf64-ppc.c (maybe_strip_output): Heed SEC_KEEP. @@ -1589,7 +1595,7 @@ * reloc.c: Add new ENUM for BFD_RELOC_AVR_8_LO, BFD_RELOC_AVR_8_HI, BFD_RELOC_AVR_8_HHI. * bfd-in2.h: Regenerate. - * libbfd.h: Regenrate. + * libbfd.h: Regenerate. * elf32-avr.c (elf_avr_howto_table): Add entries for R_AVR_8_LO8, R_AVR_8_HI8, R_AVR_8_HHI8. (avr_reloc_map): Add RELOC mappings for R_AVR_8_LO8, R_AVR_8_HI8, diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index 6bdc701d067..94f3c421512 100644 --- a/bfd/elf64-ppc.c +++ b/bfd/elf64-ppc.c @@ -3757,6 +3757,9 @@ struct ppc_link_hash_table struct ppc_link_hash_entry *tls_get_addr; struct ppc_link_hash_entry *tls_get_addr_fd; + /* The special .TOC. symbol. */ + struct ppc_link_hash_entry *dot_toc_dot; + /* The size of reliplt used by got entry relocs. */ bfd_size_type got_reli_size; @@ -11364,6 +11367,9 @@ ppc64_elf_size_stubs (struct bfd_link_info *info, bfd_signed_vma group_size, } } htab->plt_thread_safe = plt_thread_safe; + htab->dot_toc_dot = ((struct ppc_link_hash_entry *) + elf_link_hash_lookup (&htab->elf, ".TOC.", + FALSE, FALSE, TRUE)); stubs_always_before_branch = group_size < 0; if (group_size < 0) stub_group_size = -group_size; @@ -12362,6 +12368,13 @@ ppc64_elf_relocate_section (bfd *output_bfd, } } } + if (h_elf == &htab->dot_toc_dot->elf) + { + relocation = (TOCstart + + htab->stub_group[input_section->id].toc_off); + sec = bfd_abs_section_ptr; + unresolved_reloc = FALSE; + } } h = (struct ppc_link_hash_entry *) h_elf; diff --git a/gas/ChangeLog b/gas/ChangeLog index 474b617c2eb..9ad252f6192 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,11 @@ +2012-11-06 Alan Modra + + * config/tc-ppc.c (ppc_elf_adjust_symtab): New function, split out.. + (ppc_frob_file_before_adjust): ..from here. + (md_apply_fix): Set BSF_KEEP on .TOC. if not @tocbase. + * config/tc-ppc.h (ppc_elf_adjust_symtab): Declare. + (tc_adjust_symtab): Define. + 2012-11-06 Alan Modra * config/tc-ppc.c (md_apply_fix): Fix xcoff build breakage from diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c index c72a8632ba1..1b12f57b8cb 100644 --- a/gas/config/tc-ppc.c +++ b/gas/config/tc-ppc.c @@ -2323,11 +2323,28 @@ ppc_frob_file_before_adjust (void) && toc_reloc_types != has_large_toc_reloc && bfd_section_size (stdoutput, toc) > 0x10000) as_warn (_("TOC section size exceeds 64k")); +} + +/* .TOC. used in an opd entry as .TOC.@tocbase doesn't need to be + emitted. Other uses of .TOC. will cause the symbol to be marked + with BSF_KEEP in md_apply_fix. */ - /* Don't emit .TOC. symbol. */ - symp = symbol_find (".TOC."); - if (symp != NULL) - symbol_remove (symp, &symbol_rootP, &symbol_lastP); +void +ppc_elf_adjust_symtab (void) +{ + if (ppc_obj64) + { + symbolS *symp; + symp = symbol_find (".TOC."); + if (symp != NULL) + { + asymbol *bsym = symbol_get_bfdsym (symp); + if ((bsym->flags & BSF_KEEP) == 0) + symbol_remove (symp, &symbol_rootP, &symbol_lastP); + else + S_SET_WEAK (symp); + } + } } #endif /* OBJ_ELF */ @@ -6850,7 +6867,17 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) then the section contents are immaterial, so don't warn if they happen to overflow. Leave such warnings to ld. */ if (!fixP->fx_done) - fixP->fx_no_overflow = 1; + { + fixP->fx_no_overflow = 1; + + /* Arrange to emit .TOC. as a normal symbol if used in anything + but .TOC.@tocbase. */ + if (ppc_obj64 + && fixP->fx_r_type != BFD_RELOC_PPC64_TOC + && fixP->fx_addsy != NULL + && strcmp (S_GET_NAME (fixP->fx_addsy), ".TOC.") == 0) + symbol_get_bfdsym (fixP->fx_addsy)->flags |= BSF_KEEP; + } #else if (fixP->fx_r_type != BFD_RELOC_PPC_TOC16) fixP->fx_addnumber = 0; diff --git a/gas/config/tc-ppc.h b/gas/config/tc-ppc.h index e053c9c8277..3dd3f8190b3 100644 --- a/gas/config/tc-ppc.h +++ b/gas/config/tc-ppc.h @@ -235,6 +235,9 @@ extern int ppc_fix_adjustable (struct fix *); #define tc_frob_file_before_adjust ppc_frob_file_before_adjust extern void ppc_frob_file_before_adjust (void); +#define tc_adjust_symtab() ppc_elf_adjust_symtab () +extern void ppc_elf_adjust_symtab (void); + #endif /* OBJ_ELF */ #if defined (OBJ_ELF) || defined (OBJ_XCOFF) -- 2.30.2