summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/elflink.c9
-rw-r--r--include/bfdlink.h5
-rw-r--r--ld/emultempl/elf32.em4
-rw-r--r--ld/ld.texinfo13
-rw-r--r--ld/ldmain.c1
-rw-r--r--ld/lexsup.c4
-rw-r--r--ld/testsuite/ld-i386/i386.exp1
-rw-r--r--ld/testsuite/ld-i386/protected6b.d6
-rw-r--r--ld/testsuite/ld-x86-64/protected6b.d6
-rw-r--r--ld/testsuite/ld-x86-64/x86-64.exp1
10 files changed, 48 insertions, 2 deletions
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 98d31080bca..5d45687c36b 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/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/emultempl/elf32.em b/ld/emultempl/elf32.em
index 5db5a93c671..3f9903519a4 100644
--- a/ld/emultempl/elf32.em
+++ b/ld/emultempl/elf32.em
@@ -2335,6 +2335,10 @@ fragment <<EOF
link_info.error_textrel = FALSE;
else if (strcmp (optarg, "textoff") == 0)
link_info.error_textrel = FALSE;
+ else if (strcmp (optarg, "extern-protected-data") == 0)
+ link_info.extern_protected_data = 1;
+ else if (strcmp (optarg, "noextern-protected-data") == 0)
+ link_info.extern_protected_data = 0;
EOF
fi
diff --git a/ld/ld.texinfo b/ld/ld.texinfo
index 5384c98bd15..62be2f9e306 100644
--- a/ld/ld.texinfo
+++ b/ld/ld.texinfo
@@ -1054,6 +1054,12 @@ shared libraries are still allowed.
@item execstack
Marks the object as requiring executable stack.
+@item extern-protected-data
+Treat protected data symbol as external when building shared library.
+Address of protected data defined in the shared library may be external,
+i.e., due to copy relocation. This option overrides linker backend
+default.
+
@item global
This option is only meaningful when building a shared object. It makes
the symbols defined by this shared object available for symbol resolution
@@ -1107,6 +1113,13 @@ Marks the object can not be dumped by @code{dldump}.
@item noexecstack
Marks the object as not requiring executable stack.
+@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.
+
@item text
Treat DT_TEXTREL in shared object as error.
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/lexsup.c b/ld/lexsup.c
index 4a71ba41cb0..adad7a80731 100644
--- a/ld/lexsup.c
+++ b/ld/lexsup.c
@@ -1677,6 +1677,10 @@ elf_shlib_list_options (FILE *file)
fprintf (file, _("\
-z nocombreloc Don't merge dynamic relocs into one section\n"));
fprintf (file, _("\
+ -z extern-protected-data Treat protected data symbol as external\n"));
+ fprintf (file, _("\
+ -z noextern-protected-data Don't treat protected data symbol as external\n"));
+ fprintf (file, _("\
-z global Make symbols in DSO available for subsequently\n\
loaded objects\n"));
fprintf (file, _("\
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"