Re: [pcre-dev] [Bug 664] ABI breakage in PCRE 7.6

Top Page
Delete this message
Author: Craig Silverstein
Date:  
To: 664, ph10
CC: pcre-dev, iant
Subject: Re: [pcre-dev] [Bug 664] ABI breakage in PCRE 7.6
OK, here's a patch that uses the -alias flag on os x, and
__attribute__((alias)) on elf systems. Daniel, can you try this
(you can patch against svn root) and let me know if it works for you?
It worked on my simple test case, but I didn't have a convenient
real-world example to try it with.

craig

--cut here--

Index: configure.ac
===================================================================
--- configure.ac    (revision 328)
+++ configure.ac    (working copy)
@@ -319,6 +319,20 @@
 AC_SUBST(pcre_have_long_long)
 AC_SUBST(pcre_have_ulong_long)


+# Older versions of pcre defined pcrecpp::no_arg, but in new versions
+# it's called pcrecpp::RE::no_arg.  For backwards ABI compatibility,
+# we want to make one an alias for the other.  Different systems do
+# this in different ways.  Some systems (os x), can do it via an
+# -alias flag passed to the linker.
+OLD_LDFLAGS=$LDFLAGS
+LDFLAGS="$LDFLAGS -Wl,-alias,__ZN7pcrecpp2RE6no_argE,__ZN7pcrecpp6no_argE"
+# We try to run the linker with this new ld flag.  If the link fails,
+# we just give up and remove the new flag from LDFLAGS.
+AC_MSG_CHECKING([for -alias support in the linker])
+AC_LINK_IFELSE(AC_LANG_PROGRAM([],[]),
+               AC_MSG_RESULT([yes]),
+               AC_MSG_RESULT([no]); LDFLAGS="$OLD_LDFLAGS")
+
 # Checks for library functions.


 AC_CHECK_FUNCS(bcopy memmove strerror)
Index: pcrecpp.cc
===================================================================
--- pcrecpp.cc    (revision 328)
+++ pcrecpp.cc    (working copy)
@@ -59,23 +59,19 @@


 // This is for ABI compatibility with old versions of pcre (pre-7.6),
 // which defined a global no_arg variable instead of putting it in the
-// RE class.  This works on GCC >= 3, at least.  We could probably
-// have a more inclusive test if we ever needed it.  (Note that not
-// only the __attribute__ syntax, but also __USER_LABEL_PREFIX__, are
+// RE class.  This works on GCC >= 3, at least.  It definitely works
+// for ELF, but may not for other object formats (Mach-O, for
+// instance, does not support aliases.)  We could probably have a more
+// inclusive test if we ever needed it.  (Note that not only the
+// __attribute__ syntax, but also __USER_LABEL_PREFIX__, are
 // gnu-specific.)
-#if defined(__GNUC__) && __GNUC__ >= 3
-#if defined(__ELF__)
+#if defined(__GNUC__) && __GNUC__ >= 3 && defined(__ELF__)
+# define ULP_AS_STRING(x)            ULP_AS_STRING_INTERNAL(x)
+# define ULP_AS_STRING_INTERNAL(x)   #x
+# define USER_LABEL_PREFIX_STR       ULP_AS_STRING(__USER_LABEL_PREFIX__)
 extern Arg no_arg
-  __attribute__((alias(__USER_LABEL_PREFIX__ "_ZN7pcrecpp2RE6no_argE")));
-#else
-// While we know elf supports strong aliases, not all formats do (Mach
-// doesn't, for instance).  So make aliases weak by default.  This is
-// a smidge less safe in theory (conceivably, someone could override
-// this symbol in their own binary), but perfectly ok in practice.
-extern Arg no_arg
-  __attribute__((weak, alias(__USER_LABEL_PREFIX__ "_ZN7pcrecpp2RE6no_argE")));
+  __attribute__((alias(USER_LABEL_PREFIX_STR "_ZN7pcrecpp2RE6no_argE")));
 #endif
-#endif


// If a regular expression has no error, its error_ field points here
static const string empty_string;