This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
RFC: PATCH to use gnu_unique_object for non-artificial DECL_ONCE_ONLY data (the plugin problem, 2/2)
- From: Jason Merrill <jason at redhat dot com>
- To: gcc-patches List <gcc-patches at gcc dot gnu dot org>
- Date: Wed, 22 Jul 2009 19:09:38 -0400
- Subject: RFC: PATCH to use gnu_unique_object for non-artificial DECL_ONCE_ONLY data (the plugin problem, 2/2)
Repeated from the previous patch:
For a while now some uses of C++ plugins (shared objects loaded with RTLD_LOCAL) have been broken because of symbol resolution rules: if you have two plugins that link against a common library, when the first one is loaded any vague linkage symbols in both the plugin and the library are resolved to the definition in the plugin, and then when the second plugin is loaded any references there are resolved to its own definitions, so any code that relies on vague linkage symbols being shared between the library and the second plugin breaks. This applies to typeinfo comparison (including in EH), and any vague linkage objects such as template static data members and inline function local statics.
This patch solves the problem for template static data members and
inline function local statics by using a new relocation type that has
just been added to GAS: basically, this new relocation type causes
affected symbols to ignore RTLD_LOCAL, so that both plugins will refer
to the definition in the first one.
I was starting to ask for approval of this patch, but it occurs to me
now that this functionality depends on ld.so support as well as
assembler support, so I'll need to figure out a way to test that too.
Any comments on the patch as it is?
Jason
2009-07-22 Jason Merrill <jason@redhat.com>
* config/elfos.h (ASM_DECLARE_OBJECT_NAME): Use gnu_unique_object
type if available.
* configure.ac: Test for it.
* configure, config.in: Regenerate.
diff --git a/gcc/config/elfos.h b/gcc/config/elfos.h
index 2d818d1..56d7b40 100644
--- a/gcc/config/elfos.h
+++ b/gcc/config/elfos.h
@@ -289,24 +289,37 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
/* Write the extra assembler code needed to declare an object properly. */
-#define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL) \
- do \
- { \
- HOST_WIDE_INT size; \
- \
- ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "object"); \
- \
- size_directive_output = 0; \
- if (!flag_inhibit_size_directive \
- && (DECL) && DECL_SIZE (DECL)) \
- { \
- size_directive_output = 1; \
- size = int_size_in_bytes (TREE_TYPE (DECL)); \
- ASM_OUTPUT_SIZE_DIRECTIVE (FILE, NAME, size); \
- } \
- \
- ASM_OUTPUT_LABEL (FILE, NAME); \
- } \
+#ifdef HAVE_GAS_GNU_UNIQUE_OBJECT
+#define USE_GNU_UNIQUE_OBJECT 1
+#else
+#define USE_GNU_UNIQUE_OBJECT 0
+#endif
+
+#define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL) \
+ do \
+ { \
+ HOST_WIDE_INT size; \
+ \
+ /* For template static data member instantiations or \
+ inline fn local statics, use gnu_unique_object so that \
+ they will be combined even under RTLD_LOCAL. */ \
+ if (USE_GNU_UNIQUE_OBJECT \
+ && !DECL_ARTIFICIAL (DECL) && DECL_ONE_ONLY (DECL)) \
+ ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "gnu_unique_object"); \
+ else \
+ ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "object"); \
+ \
+ size_directive_output = 0; \
+ if (!flag_inhibit_size_directive \
+ && (DECL) && DECL_SIZE (DECL)) \
+ { \
+ size_directive_output = 1; \
+ size = int_size_in_bytes (TREE_TYPE (DECL)); \
+ ASM_OUTPUT_SIZE_DIRECTIVE (FILE, NAME, size); \
+ } \
+ \
+ ASM_OUTPUT_LABEL (FILE, NAME); \
+ } \
while (0)
/* Output the size directive for a decl in rest_of_decl_compilation
diff --git a/gcc/configure.ac b/gcc/configure.ac
index f73fc16..0abff5b 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -3379,6 +3379,12 @@ gcc_GAS_CHECK_FEATURE([.lcomm with alignment], gcc_cv_as_lcomm_with_alignment,
[AC_DEFINE(HAVE_GAS_LCOMM_WITH_ALIGNMENT, 1,
[Define if your assembler supports .lcomm with an alignment field.])])
+gcc_GAS_CHECK_FEATURE([gnu_unique_object], gcc_cv_as_gnu_unique_object,
+ [elf,2,19,52],,
+[.type foo, @gnu_unique_object],,
+[AC_DEFINE(HAVE_GAS_GNU_UNIQUE_OBJECT, 1,
+ [Define if your assembler supports @gnu_unique_object.])])
+
AC_CACHE_CHECK([assembler for tolerance to line number 0],
[gcc_cv_as_line_zero],
[gcc_cv_as_line_zero=no
diff --git a/gcc/config.in b/gcc/config.in
index cc0202b..ee6535e 100644
--- a/gcc/config.in
+++ b/gcc/config.in
@@ -321,6 +321,12 @@
#endif
+/* Define if your assembler supports LWSYNC instructions. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_LWSYNC
+#endif
+
+
/* Define if your assembler supports mfcr field. */
#ifndef USED_FOR_TARGET
#undef HAVE_AS_MFCRF
@@ -351,22 +357,17 @@
#endif
-/* Define if your assembler supports popcntb instruction. */
+/* Define if your assembler supports popcntb field. */
#ifndef USED_FOR_TARGET
#undef HAVE_AS_POPCNTB
#endif
-/* Define if your assembler supports popcntd instruction. */
+/* Define if your assembler supports POPCNTD instructions. */
#ifndef USED_FOR_TARGET
#undef HAVE_AS_POPCNTD
#endif
-/* Define if your assembler supports lwsync instruction. */
-#ifndef USED_FOR_TARGET
-#undef HAVE_AS_LWSYNC
-#endif
-
/* Define if your assembler supports .register. */
#ifndef USED_FOR_TARGET
@@ -886,6 +887,12 @@
#endif
+/* Define if your assembler supports @gnu_unique_object. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GAS_GNU_UNIQUE_OBJECT
+#endif
+
+
/* Define if your assembler and linker support .hidden. */
#undef HAVE_GAS_HIDDEN
diff --git a/gcc/configure b/gcc/configure
index 52c5cc7..3e03983 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -28096,6 +28096,44 @@ _ACEOF
fi
+echo "$as_me:$LINENO: checking assembler for gnu_unique_object" >&5
+echo $ECHO_N "checking assembler for gnu_unique_object... $ECHO_C" >&6
+if test "${gcc_cv_as_gnu_unique_object+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ gcc_cv_as_gnu_unique_object=no
+ if test $in_tree_gas = yes; then
+ if test $in_tree_gas_is_elf = yes \
+ && test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 19 \) \* 1000 + 52`
+ then gcc_cv_as_gnu_unique_object=yes
+fi
+ elif test x$gcc_cv_as != x; then
+ echo '.type foo, @gnu_unique_object' > conftest.s
+ if { ac_try='$gcc_cv_as -o conftest.o conftest.s >&5'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }
+ then
+ gcc_cv_as_gnu_unique_object=yes
+ else
+ echo "configure: failed program was" >&5
+ cat conftest.s >&5
+ fi
+ rm -f conftest.o conftest.s
+ fi
+fi
+echo "$as_me:$LINENO: result: $gcc_cv_as_gnu_unique_object" >&5
+echo "${ECHO_T}$gcc_cv_as_gnu_unique_object" >&6
+if test $gcc_cv_as_gnu_unique_object = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_GAS_GNU_UNIQUE_OBJECT 1
+_ACEOF
+
+fi
+
echo "$as_me:$LINENO: checking assembler for tolerance to line number 0" >&5
echo $ECHO_N "checking assembler for tolerance to line number 0... $ECHO_C" >&6
if test "${gcc_cv_as_line_zero+set}" = set; then