From 889c2a67967f7047c245779a0a0fd8ba8796846e Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Tue, 14 Apr 2015 04:12:55 -0700 Subject: [PATCH] Add -z noextern-protected-data to ld for ELF/x86 Address of protected data defined in the shared library may be external, i.e., due to copy relocation. By default, linker backend checks if relocations against protected data symbols are valid for building shared library and issues an error if relocation isn't allowed. The new option override linker backend default. When -z noextern-protected-data is used, updates on protected data symbols by another module won't be visibile to the resulting shared library. This option is specific to ELF/i386 and ELF/x86-64. bfd/ PR ld/pr17709 * elflink.c (_bfd_elf_adjust_dynamic_copy): Check info->extern_protected_data when warning copy relocs against protected symbols. (_bfd_elf_symbol_refs_local_p): Check info->extern_protected_data when checking protected non-function symbols. include/ PR ld/pr17709 * bfdlink.h (bfd_link_info): Add extern_protected_data. ld/ PR ld/pr17709 * ld.texinfo: Document "-z noextern-protected-data". * ldmain.c (main): Initialize link_info.extern_protected_data to -1. * lexsup.c (elf_shlib_list_options): Add "-z [no]extern-protected-data". * emulparams/elf32_x86_64.sh: Source extern_protected_data.sh. * emulparams/elf_i386.sh: Likewise. * emulparams/elf_i386_be.sh: Likewise. * emulparams/elf_i386_chaos.sh: Likewise. * emulparams/elf_i386_ldso.sh: Likewise. * emulparams/elf_i386_vxworks.sh: Likewise. * emulparams/elf_k1om.sh: Likewise. * emulparams/elf_l1om.sh: Likewise. * emulparams/elf_x86_64.sh: Source extern_protected_data.sh. (PARSE_AND_LIST_OPTIONS): Renamed to ... (PARSE_AND_LIST_OPTIONS_BNDPLT): This. (PARSE_AND_LIST_ARGS_CASE_Z): Renamed to ... (PARSE_AND_LIST_ARGS_CASE_Z_BNDPLT): This. (PARSE_AND_LIST_OPTIONS): Append $PARSE_AND_LIST_OPTIONS_BNDPLT. (PARSE_AND_LIST_ARGS_CASE_Z): Append $PARSE_AND_LIST_ARGS_CASE_Z_BNDPLT. * emulparams/extern_protected_data.sh: New file. ld/testsuite/ PR ld/pr17709 * ld-i386/i386.exp: Run protected6b. * ld-i386/protected6b.d: New file. * ld-x86-64/protected6b.d: Likewise. * ld-x86-64/x86-64.exp: Run protected6b. --- bfd/ChangeLog | 9 +++++++++ bfd/elflink.c | 9 +++++++-- include/ChangeLog | 5 +++++ include/bfdlink.h | 5 +++++ ld/ChangeLog | 26 ++++++++++++++++++++++++++ ld/emulparams/elf32_x86_64.sh | 1 + ld/emulparams/elf_i386.sh | 1 + ld/emulparams/elf_i386_be.sh | 1 + ld/emulparams/elf_i386_chaos.sh | 1 + ld/emulparams/elf_i386_ldso.sh | 1 + ld/emulparams/elf_i386_vxworks.sh | 1 + ld/emulparams/elf_k1om.sh | 1 + ld/emulparams/elf_l1om.sh | 1 + ld/emulparams/elf_x86_64.sh | 7 +++++-- ld/emulparams/extern_protected_data.sh | 9 +++++++++ ld/ld.texinfo | 8 ++++++++ ld/ldmain.c | 1 + ld/testsuite/ChangeLog | 8 ++++++++ ld/testsuite/ld-i386/i386.exp | 1 + ld/testsuite/ld-i386/protected6b.d | 6 ++++++ ld/testsuite/ld-x86-64/protected6b.d | 6 ++++++ ld/testsuite/ld-x86-64/x86-64.exp | 1 + 22 files changed, 105 insertions(+), 4 deletions(-) create mode 100644 ld/emulparams/extern_protected_data.sh create mode 100644 ld/testsuite/ld-i386/protected6b.d create mode 100644 ld/testsuite/ld-x86-64/protected6b.d diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 55c37f03959..056833e6562 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,12 @@ +2015-04-14 H.J. Lu + + PR ld/pr17709 + * elflink.c (_bfd_elf_adjust_dynamic_copy): Check + info->extern_protected_data when warning copy relocs against + protected symbols. + (_bfd_elf_symbol_refs_local_p): Check info->extern_protected_data + when checking protected non-function symbols. + 2015-04-13 John Baldwin * elf.c (elfcore_grok_note): Recognize NT_X86_XSTATE on diff --git a/bfd/elflink.c b/bfd/elflink.c index e3d1abe348a..ea9246b6562 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -2675,7 +2675,9 @@ _bfd_elf_adjust_dynamic_copy (struct bfd_link_info *info, /* No error if extern_protected_data is true. */ if (h->protected_def - && !get_elf_backend_data (dynbss->owner)->extern_protected_data) + && (!info->extern_protected_data + || (info->extern_protected_data < 0 + && !get_elf_backend_data (dynbss->owner)->extern_protected_data))) info->callbacks->einfo (_("%P: copy reloc against protected `%T' is dangerous\n"), h->root.root.string); @@ -2837,7 +2839,10 @@ _bfd_elf_symbol_refs_local_p (struct elf_link_hash_entry *h, /* If extern_protected_data is false, STV_PROTECTED non-function symbols are local. */ - if (!bed->extern_protected_data && !bed->is_function_type (h->type)) + if ((!info->extern_protected_data + || (info->extern_protected_data < 0 + && !bed->extern_protected_data)) + && !bed->is_function_type (h->type)) return TRUE; /* Function pointer equality tests may require that STV_PROTECTED diff --git a/include/ChangeLog b/include/ChangeLog index 35da01586ea..7d4919d1ef5 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,8 @@ +2015-04-14 H.J. Lu + + PR ld/pr17709 + * bfdlink.h (bfd_link_info): Add extern_protected_data. + 2015-03-10 Matthew Wahab PR ld/16572 diff --git a/include/bfdlink.h b/include/bfdlink.h index 6a02a3c43bf..1b1582600a3 100644 --- a/include/bfdlink.h +++ b/include/bfdlink.h @@ -517,6 +517,11 @@ struct bfd_link_info relaxation returning true in *AGAIN. */ int relax_trip; + /* > 0 to treat protected data defined in the shared library as + reference external. 0 to treat it as internal. -1 to let + backend to decide. */ + int extern_protected_data; + /* Non-zero if auto-import thunks for DATA items in pei386 DLLs should be generated/linked against. Set to 1 if this feature is explicitly requested by the user, -1 if enabled by default. */ diff --git a/ld/ChangeLog b/ld/ChangeLog index bcad3f95f5e..3e944feb8ed 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,29 @@ +2015-04-14 H.J. Lu + + PR ld/pr17709 + * ld.texinfo: Document "-z noextern-protected-data". + * ldmain.c (main): Initialize link_info.extern_protected_data + to -1. + * lexsup.c (elf_shlib_list_options): Add + "-z [no]extern-protected-data". + * emulparams/elf32_x86_64.sh: Source extern_protected_data.sh. + * emulparams/elf_i386.sh: Likewise. + * emulparams/elf_i386_be.sh: Likewise. + * emulparams/elf_i386_chaos.sh: Likewise. + * emulparams/elf_i386_ldso.sh: Likewise. + * emulparams/elf_i386_vxworks.sh: Likewise. + * emulparams/elf_k1om.sh: Likewise. + * emulparams/elf_l1om.sh: Likewise. + * emulparams/elf_x86_64.sh: Source extern_protected_data.sh. + (PARSE_AND_LIST_OPTIONS): Renamed to ... + (PARSE_AND_LIST_OPTIONS_BNDPLT): This. + (PARSE_AND_LIST_ARGS_CASE_Z): Renamed to ... + (PARSE_AND_LIST_ARGS_CASE_Z_BNDPLT): This. + (PARSE_AND_LIST_OPTIONS): Append $PARSE_AND_LIST_OPTIONS_BNDPLT. + (PARSE_AND_LIST_ARGS_CASE_Z): Append + $PARSE_AND_LIST_ARGS_CASE_Z_BNDPLT. + * emulparams/extern_protected_data.sh: New file. + 2015-04-11 H.J. Lu * plugin.c (plugin_load_plugins): Removed an extra ';'. diff --git a/ld/emulparams/elf32_x86_64.sh b/ld/emulparams/elf32_x86_64.sh index 11d17adb1dc..8fd96fb7805 100644 --- a/ld/emulparams/elf32_x86_64.sh +++ b/ld/emulparams/elf32_x86_64.sh @@ -1,4 +1,5 @@ . ${srcdir}/emulparams/plt_unwind.sh +. ${srcdir}/emulparams/extern_protected_data.sh SCRIPT_NAME=elf ELFSIZE=32 OUTPUT_FORMAT="elf32-x86-64" diff --git a/ld/emulparams/elf_i386.sh b/ld/emulparams/elf_i386.sh index 2ebfaac8db6..ae87f6b6617 100644 --- a/ld/emulparams/elf_i386.sh +++ b/ld/emulparams/elf_i386.sh @@ -1,4 +1,5 @@ . ${srcdir}/emulparams/plt_unwind.sh +. ${srcdir}/emulparams/extern_protected_data.sh SCRIPT_NAME=elf OUTPUT_FORMAT="elf32-i386" NO_RELA_RELOCS=yes diff --git a/ld/emulparams/elf_i386_be.sh b/ld/emulparams/elf_i386_be.sh index 1e27faacd08..06a80c7ef3c 100644 --- a/ld/emulparams/elf_i386_be.sh +++ b/ld/emulparams/elf_i386_be.sh @@ -1,3 +1,4 @@ +. ${srcdir}/emulparams/extern_protected_data.sh SCRIPT_NAME=elf OUTPUT_FORMAT="elf32-i386" NO_RELA_RELOCS=yes diff --git a/ld/emulparams/elf_i386_chaos.sh b/ld/emulparams/elf_i386_chaos.sh index b3005e194bd..c59dbce1402 100644 --- a/ld/emulparams/elf_i386_chaos.sh +++ b/ld/emulparams/elf_i386_chaos.sh @@ -1,4 +1,5 @@ . ${srcdir}/emulparams/plt_unwind.sh +. ${srcdir}/emulparams/extern_protected_data.sh SCRIPT_NAME=elf_chaos OUTPUT_FORMAT="elf32-i386" TEXT_START_ADDR=0x40000000 diff --git a/ld/emulparams/elf_i386_ldso.sh b/ld/emulparams/elf_i386_ldso.sh index e1a2cb7f5ef..7fd08fe8659 100644 --- a/ld/emulparams/elf_i386_ldso.sh +++ b/ld/emulparams/elf_i386_ldso.sh @@ -1,4 +1,5 @@ . ${srcdir}/emulparams/plt_unwind.sh +. ${srcdir}/emulparams/extern_protected_data.sh SCRIPT_NAME=elf OUTPUT_FORMAT="elf32-i386" NO_RELA_RELOCS=yes diff --git a/ld/emulparams/elf_i386_vxworks.sh b/ld/emulparams/elf_i386_vxworks.sh index 61839c8f48d..306e8d3ee66 100644 --- a/ld/emulparams/elf_i386_vxworks.sh +++ b/ld/emulparams/elf_i386_vxworks.sh @@ -11,3 +11,4 @@ GENERATE_SHLIB_SCRIPT=yes GENERATE_PIE_SCRIPT=yes NO_SMALL_DATA=yes . ${srcdir}/emulparams/vxworks.sh +. ${srcdir}/emulparams/extern_protected_data.sh diff --git a/ld/emulparams/elf_k1om.sh b/ld/emulparams/elf_k1om.sh index 00bf2cadec2..0cd606a2880 100644 --- a/ld/emulparams/elf_k1om.sh +++ b/ld/emulparams/elf_k1om.sh @@ -1,4 +1,5 @@ . ${srcdir}/emulparams/plt_unwind.sh +. ${srcdir}/emulparams/extern_protected_data.sh SCRIPT_NAME=elf ELFSIZE=64 OUTPUT_FORMAT="elf64-k1om" diff --git a/ld/emulparams/elf_l1om.sh b/ld/emulparams/elf_l1om.sh index abf59f163d6..1964e857a07 100644 --- a/ld/emulparams/elf_l1om.sh +++ b/ld/emulparams/elf_l1om.sh @@ -1,4 +1,5 @@ . ${srcdir}/emulparams/plt_unwind.sh +. ${srcdir}/emulparams/extern_protected_data.sh SCRIPT_NAME=elf ELFSIZE=64 OUTPUT_FORMAT="elf64-l1om" diff --git a/ld/emulparams/elf_x86_64.sh b/ld/emulparams/elf_x86_64.sh index 984e5e92c46..a304771d9df 100644 --- a/ld/emulparams/elf_x86_64.sh +++ b/ld/emulparams/elf_x86_64.sh @@ -1,4 +1,5 @@ . ${srcdir}/emulparams/plt_unwind.sh +. ${srcdir}/emulparams/extern_protected_data.sh SCRIPT_NAME=elf ELFSIZE=64 OUTPUT_FORMAT="elf64-x86-64" @@ -36,14 +37,16 @@ case "$target" in case "$EMULATION_NAME" in *64*) LIBPATH_SUFFIX=64 - PARSE_AND_LIST_OPTIONS=' + PARSE_AND_LIST_OPTIONS_BNDPLT=' fprintf (file, _("\ -z bndplt Always generate BND prefix in PLT entries\n")); ' - PARSE_AND_LIST_ARGS_CASE_Z=' + PARSE_AND_LIST_ARGS_CASE_Z_BNDPLT=' else if (strcmp (optarg, "bndplt") == 0) link_info.bndplt = TRUE; ' + PARSE_AND_LIST_OPTIONS="$PARSE_AND_LIST_OPTIONS $PARSE_AND_LIST_OPTIONS_BNDPLT" + PARSE_AND_LIST_ARGS_CASE_Z="$PARSE_AND_LIST_ARGS_CASE_Z $PARSE_AND_LIST_ARGS_CASE_Z_BNDPLT" ;; esac ;; diff --git a/ld/emulparams/extern_protected_data.sh b/ld/emulparams/extern_protected_data.sh new file mode 100644 index 00000000000..fd4bd3b3c82 --- /dev/null +++ b/ld/emulparams/extern_protected_data.sh @@ -0,0 +1,9 @@ +PARSE_AND_LIST_OPTIONS=' + fprintf (file, _("\ + -z noextern-protected-data Do not treat protected data symbol as external\n")); +' + +PARSE_AND_LIST_ARGS_CASE_Z=' + else if (strcmp (optarg, "noextern-protected-data") == 0) + link_info.extern_protected_data = FALSE; +' diff --git a/ld/ld.texinfo b/ld/ld.texinfo index 5384c98bd15..4348c8812b4 100644 --- a/ld/ld.texinfo +++ b/ld/ld.texinfo @@ -1146,6 +1146,14 @@ Specifying zero will override any default non-zero sized @item bndplt Always generate BND prefix in PLT entries. Supported for Linux/x86_64. +@item noextern-protected-data +Don't treat protected data symbol as external when building shared +library. This option overrides linker backend default. It can be used +to workaround incorrect relocations against protected data symbols +generated by compiler. Updates on protected data symbols by another +module aren't visibile to the resulting shared library. Supported for +i386 and x86-64. + @end table Other keywords are ignored for Solaris compatibility. diff --git a/ld/ldmain.c b/ld/ldmain.c index 6674a80c894..2ecb92d00bf 100644 --- a/ld/ldmain.c +++ b/ld/ldmain.c @@ -285,6 +285,7 @@ main (int argc, char **argv) link_info.init_function = "_init"; link_info.fini_function = "_fini"; link_info.relax_pass = 1; + link_info.extern_protected_data = -1; link_info.pei386_auto_import = -1; link_info.spare_dynamic_tags = 5; link_info.path_separator = ':'; diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index 8b45279b0e8..b35eb831449 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2015-04-14 H.J. Lu + + PR ld/pr17709 + * ld-i386/i386.exp: Run protected6b. + * ld-i386/protected6b.d: New file. + * ld-x86-64/protected6b.d: Likewise. + * ld-x86-64/x86-64.exp: Run protected6b. + 2015-04-11 H.J. Lu * ld-i386/i386.exp: Run protected6a. diff --git a/ld/testsuite/ld-i386/i386.exp b/ld/testsuite/ld-i386/i386.exp index 0c0fd96b5f7..f214d896ecc 100644 --- a/ld/testsuite/ld-i386/i386.exp +++ b/ld/testsuite/ld-i386/i386.exp @@ -237,6 +237,7 @@ run_dump_test "protected3" run_dump_test "protected4" run_dump_test "protected5" run_dump_test "protected6a" +run_dump_test "protected6b" run_dump_test "tlspie1" run_dump_test "tlspie2" run_dump_test "nogot1" diff --git a/ld/testsuite/ld-i386/protected6b.d b/ld/testsuite/ld-i386/protected6b.d new file mode 100644 index 00000000000..5642c60251c --- /dev/null +++ b/ld/testsuite/ld-i386/protected6b.d @@ -0,0 +1,6 @@ +#source: protected6.s +#as: --32 +#ld: -shared -melf_i386 -z noextern-protected-data +#readelf: -r + +There are no relocations in this file. diff --git a/ld/testsuite/ld-x86-64/protected6b.d b/ld/testsuite/ld-x86-64/protected6b.d new file mode 100644 index 00000000000..8b443312d11 --- /dev/null +++ b/ld/testsuite/ld-x86-64/protected6b.d @@ -0,0 +1,6 @@ +#source: protected6.s +#as: --64 +#ld: -shared -melf_x86_64 -z noextern-protected-data +#readelf: -r + +There are no relocations in this file. diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp index 213a4c03bab..8352ad9591d 100644 --- a/ld/testsuite/ld-x86-64/x86-64.exp +++ b/ld/testsuite/ld-x86-64/x86-64.exp @@ -221,6 +221,7 @@ run_dump_test "protected3-l1om" run_dump_test "protected4" run_dump_test "protected5" run_dump_test "protected6a" +run_dump_test "protected6b" run_dump_test "protected7a" run_dump_test "protected7b" run_dump_test "tlsle1" -- 2.30.2