From 794e51c094034378e14eec48b628957e71887265 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Wed, 11 Jan 2012 09:28:45 +0000 Subject: bfd/ * elf64-ppc.c: Define more insns used in plt call stubs. (ppc64_elf_brtaken_reloc): Assume isa version 2 or above. (ppc64_elf_relocate_section): Likewise. (enum ppc_stub_type): Add ppc_stub_plt_call_r2save. (struct ppc_link_hash_table): Increase size of stub_count array. Add plt_stub_align and plt_thread_safe. (ALWAYS_USE_FAKE_DEP, ALWAYS_EMIT_R2SAVE): Define. (plt_stub_size, plt_stub_pad): New functions. (build_plt_stub): Emit barriers for power7 thread safety. Don't emit needless save of r2. (build_tls_get_addr_stub): Adjust params. (ppc_build_one_stub): Handle ppc_stub_plt_call_r2save and aligning plt stubs. Adjust build_*plt_stub calls. (ppc_size_one_stub): Similarly. (ppc64_elf_size_stubs): Accept plt_thread_safe and plt_stub_align params. Choose default for plt_thread_safe based on existence of calls to thread creation functions. Modify plt_call to plt_call_r2save when no tocsave reloc found. Align tail of stub sections. (ppc64_elf_build_stubs): Align tail of stub sections. Adjust output of stub statistics. (ppc64_elf_relocate_section): Handle ppc_stub_plt_call_r2save. * elf64-ppc.h (ppc64_elf_size_stubs): Update prototype. ld/ * emultempl/ppc64elf.em (PARSE_AND_LIST_PROLOGUE, PARSE_AND_LIST_LONGOPTS, PARSE_AND_LIST_OPTIONS, PARSE_AND_LIST_ARGS_CASES): Handle --{no-,}plt-thread-safe and --{no-,}plt-align. (plt_thread_safe, plt_stub_align): New vars. (gld${EMULATION_NAME}_after_allocation): Pass them to ppc64_elf_size_stubs. Align stub sections according to plt_stub_align. * ld.texinfo: Document new command line options, and an old undocumented option. --- ld/ChangeLog | 12 +++++++++ ld/emultempl/ppc64elf.em | 66 +++++++++++++++++++++++++++++++++++++++++++----- ld/ld.texinfo | 52 ++++++++++++++++++++++++++++++++++++-- 3 files changed, 122 insertions(+), 8 deletions(-) (limited to 'ld') diff --git a/ld/ChangeLog b/ld/ChangeLog index d779176..8d4027f 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,15 @@ +2012-01-11 Alan Modra + + * emultempl/ppc64elf.em (PARSE_AND_LIST_PROLOGUE, + PARSE_AND_LIST_LONGOPTS, PARSE_AND_LIST_OPTIONS, + PARSE_AND_LIST_ARGS_CASES): Handle --{no-,}plt-thread-safe and + --{no-,}plt-align. + (plt_thread_safe, plt_stub_align): New vars. + (gld${EMULATION_NAME}_after_allocation): Pass them to + ppc64_elf_size_stubs. Align stub sections according to plt_stub_align. + * ld.texinfo: Document new command line options, and an old + undocumented option. + 2012-01-09 Roland McGrath * configure.in: Use AM_ZLIB. diff --git a/ld/emultempl/ppc64elf.em b/ld/emultempl/ppc64elf.em index 9c352ee..5b637e1 100644 --- a/ld/emultempl/ppc64elf.em +++ b/ld/emultempl/ppc64elf.em @@ -1,5 +1,5 @@ # This shell script emits a C file. -*- C -*- -# Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 +# Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 # Free Software Foundation, Inc. # # This file is part of the GNU Binutils. @@ -64,6 +64,12 @@ static int no_toc_sort = 0; /* Set if PLT call stubs should load r11. */ static int plt_static_chain = ${DEFAULT_PLT_STATIC_CHAIN-0}; +/* Set if PLT call stubs need to be thread safe on power7+. */ +static int plt_thread_safe = -1; + +/* Set if individual PLT call stubs should be aligned. */ +static int plt_stub_align = 0; + /* Whether to emit symbols for stubs. */ static int emit_stub_syms = -1; @@ -379,7 +385,8 @@ ppc_add_stub_section (const char *stub_sec_name, asection *input_section) stub_sec = bfd_make_section_anyway_with_flags (stub_file->the_bfd, stub_sec_name, flags); if (stub_sec == NULL - || !bfd_set_section_alignment (stub_file->the_bfd, stub_sec, 5)) + || !bfd_set_section_alignment (stub_file->the_bfd, stub_sec, + plt_stub_align > 5 ? plt_stub_align : 5)) goto err_ret; output_section = input_section->output_section; @@ -504,7 +511,9 @@ gld${EMULATION_NAME}_after_allocation (void) einfo ("%P: .init/.fini fragments use differing TOC pointers\n"); /* Call into the BFD backend to do the real work. */ - if (!ppc64_elf_size_stubs (&link_info, group_size, plt_static_chain)) + if (!ppc64_elf_size_stubs (&link_info, group_size, + plt_static_chain, plt_thread_safe, + plt_stub_align)) einfo ("%X%P: can not size stub section: %E\n"); } } @@ -649,7 +658,11 @@ PARSE_AND_LIST_PROLOGUE=${PARSE_AND_LIST_PROLOGUE}' #define OPTION_STUBGROUP_SIZE 321 #define OPTION_PLT_STATIC_CHAIN (OPTION_STUBGROUP_SIZE + 1) #define OPTION_NO_PLT_STATIC_CHAIN (OPTION_PLT_STATIC_CHAIN + 1) -#define OPTION_STUBSYMS (OPTION_NO_PLT_STATIC_CHAIN + 1) +#define OPTION_PLT_THREAD_SAFE (OPTION_NO_PLT_STATIC_CHAIN + 1) +#define OPTION_NO_PLT_THREAD_SAFE (OPTION_PLT_THREAD_SAFE + 1) +#define OPTION_PLT_ALIGN (OPTION_NO_PLT_THREAD_SAFE + 1) +#define OPTION_NO_PLT_ALIGN (OPTION_PLT_ALIGN + 1) +#define OPTION_STUBSYMS (OPTION_NO_PLT_ALIGN + 1) #define OPTION_NO_STUBSYMS (OPTION_STUBSYMS + 1) #define OPTION_DOTSYMS (OPTION_NO_STUBSYMS + 1) #define OPTION_NO_DOTSYMS (OPTION_DOTSYMS + 1) @@ -666,6 +679,10 @@ PARSE_AND_LIST_LONGOPTS=${PARSE_AND_LIST_LONGOPTS}' { "stub-group-size", required_argument, NULL, OPTION_STUBGROUP_SIZE }, { "plt-static-chain", no_argument, NULL, OPTION_PLT_STATIC_CHAIN }, { "no-plt-static-chain", no_argument, NULL, OPTION_NO_PLT_STATIC_CHAIN }, + { "plt-thread-safe", no_argument, NULL, OPTION_PLT_THREAD_SAFE }, + { "no-plt-thread-safe", no_argument, NULL, OPTION_NO_PLT_THREAD_SAFE }, + { "plt-align", optional_argument, NULL, OPTION_PLT_ALIGN }, + { "no-plt-align", no_argument, NULL, OPTION_NO_PLT_ALIGN }, { "emit-stub-syms", no_argument, NULL, OPTION_STUBSYMS }, { "no-emit-stub-syms", no_argument, NULL, OPTION_NO_STUBSYMS }, { "dotsyms", no_argument, NULL, OPTION_DOTSYMS }, @@ -691,10 +708,22 @@ PARSE_AND_LIST_OPTIONS=${PARSE_AND_LIST_OPTIONS}' choose suitable defaults.\n" )); fprintf (file, _("\ - --plt-static-chain PLT call stubs should load r11.\n" + --plt-static-chain PLT call stubs should load r11.${DEFAULT_PLT_STATIC_CHAIN- (default)}\n" + )); + fprintf (file, _("\ + --no-plt-static-chain PLT call stubs should not load r11.${DEFAULT_PLT_STATIC_CHAIN+ (default)}\n" + )); + fprintf (file, _("\ + --plt-thread-safe PLT call stubs with load-load barrier.\n" + )); + fprintf (file, _("\ + --no-plt-thread-safe PLT call stubs without barrier.\n" + )); + fprintf (file, _("\ + --plt-align [=] Align PLT call stubs to fit cache lines.\n" )); fprintf (file, _("\ - --no-plt-static-chain PLT call stubs should not load r11. (default)\n" + --no-plt-align Dont'\''t align individual PLT call stubs.\n" )); fprintf (file, _("\ --emit-stub-syms Label linker stubs with a symbol.\n" @@ -753,6 +782,31 @@ PARSE_AND_LIST_ARGS_CASES=${PARSE_AND_LIST_ARGS_CASES}' plt_static_chain = 0; break; + case OPTION_PLT_THREAD_SAFE: + plt_thread_safe = 1; + break; + + case OPTION_NO_PLT_THREAD_SAFE: + plt_thread_safe = 0; + break; + + case OPTION_PLT_ALIGN: + if (optarg != NULL) + { + char *end; + unsigned long val = strtoul (optarg, &end, 0); + if (*end || val > 8) + einfo (_("%P%F: invalid --plt-align `%s'\''\n"), optarg); + plt_stub_align = val; + } + else + plt_stub_align = 5; + break; + + case OPTION_NO_PLT_ALIGN: + plt_stub_align = 0; + break; + case OPTION_STUBSYMS: emit_stub_syms = 1; break; diff --git a/ld/ld.texinfo b/ld/ld.texinfo index 592e38c..6c74ff5 100644 --- a/ld/ld.texinfo +++ b/ld/ld.texinfo @@ -1,7 +1,7 @@ \input texinfo @setfilename ld.info @c Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, -@c 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 +@c 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 @c Free Software Foundation, Inc. @syncodeindex ky cp @c man begin INCLUDE @@ -6710,7 +6710,9 @@ optimization. @cindex PowerPC64 multi-TOC @kindex --no-multi-toc @item --no-multi-toc -By default, PowerPC64 GCC generates code for a TOC model where TOC +If given any toc option besides @code{-mcmodel=medium} or +@code{-mcmodel=large}, PowerPC64 GCC generates code for a TOC model +where TOC entries are accessed with a 16-bit offset from r2. This limits the total TOC size to 64K. PowerPC64 @command{ld} extends this limit by grouping code sections such that each group uses less than 64K for its @@ -6719,6 +6721,52 @@ calls. @command{ld} does not split apart input sections, so cannot help if a single input file has a @code{.toc} section that exceeds 64K, most likely from linking multiple files with @command{ld -r}. Use this option to turn off this feature. + +@cindex PowerPC64 TOC sorting +@kindex --no-toc-sort +@item --no-toc-sort +By default, @command{ld} sorts TOC sections so that those whose file +happens to have a section called @code{.init} or @code{.fini} are +placed first, followed by TOC sections referenced by code generated +with PowerPC64 gcc's @code{-mcmodel=small}, and lastly TOC sections +referenced only by code generated with PowerPC64 gcc's +@code{-mcmodel=medium} or @code{-mcmodel=large} options. Doing this +results in better TOC grouping for multi-TOC. Use this option to turn +off this feature. + +@cindex PowerPC64 PLT stub alignment +@kindex --plt-align +@kindex --no-plt-align +@item --plt-align +@itemx --no-plt-align +Use these options to control whether individual PLT call stubs are +aligned to a 32-byte boundary, or to the specified power of two +boundary when using @code{--plt-align=}. By default PLT call stubs +are packed tightly. + +@cindex PowerPC64 PLT call stub static chain +@kindex --plt-static-chain +@kindex --no-plt-static-chain +@item --plt-static-chain +@itemx --no-plt-static-chain +Use these options to control whether PLT call stubs load the static +chain pointer (r11). @code{ld} defaults to not loading the static +chain since there is never any need to do so on a PLT call. + +@cindex PowerPC64 PLT call stub thread safety +@kindex --plt-thread-safe +@kindex --no-plt-thread-safe +@item --plt-thread-safe +@itemx --no-thread-safe +With power7's weakly ordered memory model, it is possible when using +lazy binding for ld.so to update a plt entry in one thread and have +another thread see the individual plt entry words update in the wrong +order, despite ld.so carefully writing in the correct order and using +memory write barriers. To avoid this we need some sort of read +barrier in the call stub, or use LD_BIND_NOW=1. By default, @code{ld} +looks for calls to commonly used functions that create threads, and if +seen, adds the necessary barriers. Use these options to change the +default behaviour. @end table @ifclear GENERIC -- cgit v1.1