This patch is supposed to fix PR59063
(http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59063).
The original bug results from libasan providing clock_gettime wrapper
and then trying to call the "real" clock_gettime. The "real" symbol is
supposed to come from librt.so which was not necessarily linked to
executable. The net result is a NULL call.
Patch is based on Evgeniy Stepanov's and Jakub's suggestions in bugzilla
discussion. It instructs frontend to add -lrt on static Asan compilation
and also links dynamic libasan.so against librt.so.
This was tested against gcc asan testsuite on x86_64.
-Y
diff --git a/gcc/config/gnu-user.h b/gcc/config/gnu-user.h
index 6f69158..d13c21c 100644
--- a/gcc/config/gnu-user.h
+++ b/gcc/config/gnu-user.h
@@ -129,7 +129,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
/* Additional libraries needed by -static-libasan. */
#undef STATIC_LIBASAN_LIBS
-#define STATIC_LIBASAN_LIBS "-ldl -lpthread"
+#define STATIC_LIBASAN_LIBS "-ldl -lpthread -lrt"
/* Additional libraries needed by -static-libtsan. */
#undef STATIC_LIBTSAN_LIBS
diff --git a/gcc/testsuite/c-c++-common/asan/pr59063-1.c b/gcc/testsuite/c-c++-common/asan/pr59063-1.c
new file mode 100644
index 0000000..a4e01f7
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/pr59063-1.c
@@ -0,0 +1,11 @@
+/* { dg-do run } */
+
+#include <time.h>
+static int weak_gettime (clockid_t clk_id, struct timespec *tp)
+ __attribute__((__weakref__("clock_gettime")));
+int main() {
+ if (!clock_gettime)
+ return 0;
+ struct timespec ts;
+ return weak_gettime(CLOCK_MONOTONIC, &ts);
+}
diff --git a/gcc/testsuite/c-c++-common/asan/pr59063-2.c b/gcc/testsuite/c-c++-common/asan/pr59063-2.c
new file mode 100644
index 0000000..c94ffef
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/pr59063-2.c
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+/* { dg-options "-static-libasan -lstdc++" } */
+
+#include <time.h>
+static int weak_gettime (clockid_t clk_id, struct timespec *tp)
+ __attribute__((__weakref__("clock_gettime")));
+int main() {
+ if (!clock_gettime)
+ return 0;
+ struct timespec ts;
+ return weak_gettime(CLOCK_MONOTONIC, &ts);
+}
diff --git a/libsanitizer/Makefile.in b/libsanitizer/Makefile.in
index 47a8771..f342094 100644
--- a/libsanitizer/Makefile.in
+++ b/libsanitizer/Makefile.in
@@ -80,6 +80,7 @@ DIST_SUBDIRS = interception sanitizer_common lsan asan ubsan tsan
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AR = @AR@
+ASAN_LIBS = @ASAN_LIBS@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
diff --git a/libsanitizer/asan/Makefile.am b/libsanitizer/asan/Makefile.am
index 8764007..25cfd3a 100644
--- a/libsanitizer/asan/Makefile.am
+++ b/libsanitizer/asan/Makefile.am
@@ -43,7 +43,7 @@ libasan_la_LIBADD = $(top_builddir)/sanitizer_common/libsanitizer_common.la $(to
endif
libasan_la_LIBADD += $(LIBSTDCXX_RAW_CXX_LDFLAGS)
-libasan_la_LDFLAGS = -version-info `grep -v '^\#' $(srcdir)/libtool-version` -lpthread -ldl
+libasan_la_LDFLAGS = -version-info `grep -v '^\#' $(srcdir)/libtool-version` -lpthread -ldl $(ASAN_LIBS)
libasan_preinit.o: asan_preinit.o
cp $< $@
diff --git a/libsanitizer/asan/Makefile.in b/libsanitizer/asan/Makefile.in
index be8b879..d52711e 100644
--- a/libsanitizer/asan/Makefile.in
+++ b/libsanitizer/asan/Makefile.in
@@ -118,6 +118,7 @@ CTAGS = ctags
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AR = @AR@
+ASAN_LIBS = @ASAN_LIBS@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
@@ -289,7 +290,7 @@ libasan_la_SOURCES = $(asan_files)
@USING_MAC_INTERPOSE_TRUE@libasan_la_LIBADD = $(top_builddir)/sanitizer_common/libsanitizer_common.la \
@USING_MAC_INTERPOSE_TRUE@ $(top_builddir)/lsan/libsanitizer_lsan.la \
@USING_MAC_INTERPOSE_TRUE@ $(LIBSTDCXX_RAW_CXX_LDFLAGS)
-libasan_la_LDFLAGS = -version-info `grep -v '^\#' $(srcdir)/libtool-version` -lpthread -ldl
+libasan_la_LDFLAGS = -version-info `grep -v '^\#' $(srcdir)/libtool-version` -lpthread -ldl $(ASAN_LIBS)
# Work around what appears to be a GNU make bug handling MAKEFLAGS
# values defined in terms of make variables, as is the case for CC and
diff --git a/libsanitizer/configure b/libsanitizer/configure
index 5e425d1..41a84a3 100755
--- a/libsanitizer/configure
+++ b/libsanitizer/configure
@@ -604,6 +604,7 @@ ac_subst_vars='am__EXEEXT_FALSE
am__EXEEXT_TRUE
LTLIBOBJS
LIBOBJS
+ASAN_LIBS
USING_MAC_INTERPOSE_FALSE
USING_MAC_INTERPOSE_TRUE
TSAN_SUPPORTED_FALSE
@@ -11117,7 +11118,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11120 "configure"
+#line 11121 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -11223,7 +11224,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11226 "configure"
+#line 11227 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -14546,6 +14547,69 @@ else
fi
+# Check for functions needed.
+for ac_func in clock_getres clock_gettime clock_settime
+do :
+ as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+eval as_val=\$$as_ac_var
+ if test "x$as_val" = x""yes; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+
+
+# At least for glibc, clock_gettime is in librt. But don't pull that
+# in if it still doesn't give us the function we want. This
+# test is copied from libgomp.
+if test $ac_cv_func_clock_gettime = no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime in -lrt" >&5
+$as_echo_n "checking for clock_gettime in -lrt... " >&6; }
+if test "${ac_cv_lib_rt_clock_gettime+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lrt $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char clock_gettime ();
+int
+main ()
+{
+return clock_gettime ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_rt_clock_gettime=yes
+else
+ ac_cv_lib_rt_clock_gettime=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_clock_gettime" >&5
+$as_echo "$ac_cv_lib_rt_clock_gettime" >&6; }
+if test "x$ac_cv_lib_rt_clock_gettime" = x""yes; then :
+ ASAN_LIBS="-lrt $ASAN_LIBS"
+fi
+
+fi
+
ac_config_files="$ac_config_files Makefile"
diff --git a/libsanitizer/configure.ac b/libsanitizer/configure.ac
index 0b2d813..61976cd 100644
--- a/libsanitizer/configure.ac
+++ b/libsanitizer/configure.ac
@@ -87,6 +87,19 @@ case "$host" in
esac
AM_CONDITIONAL(USING_MAC_INTERPOSE, $MAC_INTERPOSE)
+# Check for functions needed.
+AC_CHECK_FUNCS(clock_getres clock_gettime clock_settime)
+
+AC_SUBST(ASAN_LIBS)
+
+# At least for glibc, clock_gettime is in librt. But don't pull that
+# in if it still doesn't give us the function we want. This
+# test is copied from libgomp.
+if test $ac_cv_func_clock_gettime = no; then
+ AC_CHECK_LIB(rt, clock_gettime,
+ [ASAN_LIBS="-lrt $ASAN_LIBS"])
+fi
+
AC_CONFIG_FILES([Makefile])
AC_CONFIG_FILES(AC_FOREACH([DIR], [interception sanitizer_common lsan asan ubsan], [DIR/Makefile ]),
diff --git a/libsanitizer/interception/Makefile.in b/libsanitizer/interception/Makefile.in
index 59b9a9a..f3da716 100644
--- a/libsanitizer/interception/Makefile.in
+++ b/libsanitizer/interception/Makefile.in
@@ -78,6 +78,7 @@ CTAGS = ctags
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AR = @AR@
+ASAN_LIBS = @ASAN_LIBS@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
diff --git a/libsanitizer/lsan/Makefile.in b/libsanitizer/lsan/Makefile.in
index e01f65b..48cf3d9 100644
--- a/libsanitizer/lsan/Makefile.in
+++ b/libsanitizer/lsan/Makefile.in
@@ -77,6 +77,7 @@ CTAGS = ctags
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AR = @AR@
+ASAN_LIBS = @ASAN_LIBS@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
diff --git a/libsanitizer/sanitizer_common/Makefile.in b/libsanitizer/sanitizer_common/Makefile.in
index 68c9849..f6f532f 100644
--- a/libsanitizer/sanitizer_common/Makefile.in
+++ b/libsanitizer/sanitizer_common/Makefile.in
@@ -89,6 +89,7 @@ CTAGS = ctags
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AR = @AR@
+ASAN_LIBS = @ASAN_LIBS@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
diff --git a/libsanitizer/tsan/Makefile.in b/libsanitizer/tsan/Makefile.in
index 95a88b2..9ebb97a 100644
--- a/libsanitizer/tsan/Makefile.in
+++ b/libsanitizer/tsan/Makefile.in
@@ -128,6 +128,7 @@ CTAGS = ctags
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AR = @AR@
+ASAN_LIBS = @ASAN_LIBS@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
diff --git a/libsanitizer/ubsan/Makefile.in b/libsanitizer/ubsan/Makefile.in
index 6812538..81a81e2 100644
--- a/libsanitizer/ubsan/Makefile.in
+++ b/libsanitizer/ubsan/Makefile.in
@@ -107,6 +107,7 @@ CTAGS = ctags
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AR = @AR@
+ASAN_LIBS = @ASAN_LIBS@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
2013-11-13 Yury Gribov <y.gri...@samsung.com>
Jakub Jelinek <ja...@redhat.com>
PR sanitizer/59063
* config/gnu-user.h: Add librt to ASAN_STATIC_LIBS.
2013-11-13 Yury Gribov <y.gri...@samsung.com>
Jakub Jelinek <ja...@redhat.com>
PR sanitizer/59063
* c-c++-common/asan/pr59063-1.c: New test.
* c-c++-common/asan/pr59063-2.c: Likewise.
2013-11-13 Yury Gribov <y.gri...@samsung.com>
Jakub Jelinek <ja...@redhat.com>
PR sanitizer/59063
* configure.ac: Check whether clock_* routines come from librt.
* asan/Makefile.am (libasan_la_LDFLAGS): Link libasan against librt if
necessary.
* asan/Makefile.in: Regenerate.
* interception/Makefile.in: Regenerate.
* lsan/Makefile.in: Regenerate.
* sanitizer_common/Makefile.in: Regenerate.
* tsan/Makefile.in: Regenerate.
* ubsan/Makefile.in: Regenerate.
* Makefile.in: Regenerate.
* configure: Regenerate.
* sanitizer_common/Makefile.in: Regenerate.