From 7d61373544eb18698bd9015f73940048aeb4324e Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Fri, 22 Feb 2013 17:07:36 +0100 Subject: [PATCH] re PR sanitizer/56393 (SIGSEGV when -fsanitize=address and dynamic lib with global objects) PR sanitizer/56393 * config/gnu-user.h (LIBASAN_EARLY_SPEC): Link in libasan_preinit.o if not linking a shared library. * lib/asan-dg.exp (asan_link_flags): Add -B${gccpath}/libsanitizer/asan/ to flags. * asan/Makefile.am (nodist_toolexeclib_HEADERS): Set to libasan_preinit.o. (libasan_preinit.o): Depend on asan_preinit.o. * asan/Makefile.in: Regenerated. * asan/asan_preinit.cc: New file, synced from upstream. * asan/asan_rtl.cc: Remove preinit stuff, synced from upstream. From-SVN: r196222 --- gcc/ChangeLog | 6 ++++ gcc/config/gnu-user.h | 6 ++-- gcc/testsuite/ChangeLog | 6 ++++ gcc/testsuite/lib/asan-dg.exp | 1 + libsanitizer/ChangeLog | 10 ++++++ libsanitizer/asan/Makefile.am | 4 +++ libsanitizer/asan/Makefile.in | 53 ++++++++++++++++++++++++------- libsanitizer/asan/asan_preinit.cc | 27 ++++++++++++++++ libsanitizer/asan/asan_rtl.cc | 14 -------- 9 files changed, 100 insertions(+), 27 deletions(-) create mode 100644 libsanitizer/asan/asan_preinit.cc diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e39c57fcf2d..e7cd74931d9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2013-02-22 Jakub Jelinek + + PR sanitizer/56393 + * config/gnu-user.h (LIBASAN_EARLY_SPEC): Link in libasan_preinit.o + if not linking a shared library. + 2013-02-22 Seth LaForge * config.gcc (arm*-*-eabi*): Treat arm*eb as big-endian. diff --git a/gcc/config/gnu-user.h b/gcc/config/gnu-user.h index ba627e0ab0d..6c26163b223 100644 --- a/gcc/config/gnu-user.h +++ b/gcc/config/gnu-user.h @@ -104,11 +104,13 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see it to force everything into the executable. And similarly for -ltsan. */ #if defined(HAVE_LD_STATIC_DYNAMIC) #undef LIBASAN_EARLY_SPEC -#define LIBASAN_EARLY_SPEC "%{static-libasan:%{!shared:" \ +#define LIBASAN_EARLY_SPEC "%{!shared:libasan_preinit%O%s} " \ + "%{static-libasan:%{!shared:" \ LD_STATIC_OPTION " --whole-archive -lasan --no-whole-archive " \ LD_DYNAMIC_OPTION "}}%{!static-libasan:-lasan}" #undef LIBTSAN_EARLY_SPEC -#define LIBTSAN_EARLY_SPEC "%{static-libtsan:%{!shared:" \ +#define LIBTSAN_EARLY_SPEC "%{!shared:libasan_preinit%O%s} " \ + "%{static-libtsan:%{!shared:" \ LD_STATIC_OPTION " --whole-archive -ltsan --no-whole-archive " \ LD_DYNAMIC_OPTION "}}%{!static-libtsan:-ltsan}" #endif diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 7df8623d288..351cb17d8ee 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2013-02-22 Jakub Jelinek + + PR sanitizer/56393 + * lib/asan-dg.exp (asan_link_flags): Add + -B${gccpath}/libsanitizer/asan/ to flags. + 2013-02-21 Jakub Jelinek PR middle-end/56420 diff --git a/gcc/testsuite/lib/asan-dg.exp b/gcc/testsuite/lib/asan-dg.exp index 0bc9b245d79..e0bf2da2e78 100644 --- a/gcc/testsuite/lib/asan-dg.exp +++ b/gcc/testsuite/lib/asan-dg.exp @@ -41,6 +41,7 @@ proc asan_link_flags { paths } { if { $gccpath != "" } { if { [file exists "${gccpath}/libsanitizer/asan/.libs/libasan.a"] || [file exists "${gccpath}/libsanitizer/asan/.libs/libasan.${shlib_ext}"] } { + append flags " -B${gccpath}/libsanitizer/asan/ " append flags " -L${gccpath}/libsanitizer/asan/.libs " append ld_library_path ":${gccpath}/libsanitizer/asan/.libs" } diff --git a/libsanitizer/ChangeLog b/libsanitizer/ChangeLog index 7f8f6ad7758..608ffab0851 100644 --- a/libsanitizer/ChangeLog +++ b/libsanitizer/ChangeLog @@ -1,3 +1,13 @@ +2013-02-22 Jakub Jelinek + + PR sanitizer/56393 + * asan/Makefile.am (nodist_toolexeclib_HEADERS): Set to + libasan_preinit.o. + (libasan_preinit.o): Depend on asan_preinit.o. + * asan/Makefile.in: Regenerated. + * asan/asan_preinit.cc: New file, synced from upstream. + * asan/asan_rtl.cc: Remove preinit stuff, synced from upstream. + 2013-02-21 Jack Howarth * asan/Makefile.am (libasan_la_SOURCES): Remove deprecated diff --git a/libsanitizer/asan/Makefile.am b/libsanitizer/asan/Makefile.am index b3ca3df31e1..f7847db3647 100644 --- a/libsanitizer/asan/Makefile.am +++ b/libsanitizer/asan/Makefile.am @@ -12,6 +12,7 @@ AM_CXXFLAGS += $(LIBSTDCXX_RAW_CXX_CXXFLAGS) ACLOCAL_AMFLAGS = -I $(top_srcdir) -I $(top_srcdir)/config toolexeclib_LTLIBRARIES = libasan.la +nodist_toolexeclib_HEADERS = libasan_preinit.o asan_files = \ asan_allocator.cc \ @@ -45,6 +46,9 @@ libasan_la_LIBADD += $(LIBSTDCXX_RAW_CXX_LDFLAGS) libasan_la_LDFLAGS = -version-info `grep -v '^\#' $(srcdir)/libtool-version` -lpthread -ldl +libasan_preinit.o: asan_preinit.o + cp $< $@ + # 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 # friends when we are called from the top level Makefile. diff --git a/libsanitizer/asan/Makefile.in b/libsanitizer/asan/Makefile.in index d5688be6ba2..d54f3a7be36 100644 --- a/libsanitizer/asan/Makefile.in +++ b/libsanitizer/asan/Makefile.in @@ -15,6 +15,7 @@ @SET_MAKE@ + VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ @@ -75,7 +76,8 @@ am__nobase_list = $(am__nobase_strip_setup); \ am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' -am__installdirs = "$(DESTDIR)$(toolexeclibdir)" +am__installdirs = "$(DESTDIR)$(toolexeclibdir)" \ + "$(DESTDIR)$(toolexeclibdir)" LTLIBRARIES = $(toolexeclib_LTLIBRARIES) am__DEPENDENCIES_1 = @USING_MAC_INTERPOSE_FALSE@libasan_la_DEPENDENCIES = $(top_builddir)/sanitizer_common/libsanitizer_common.la \ @@ -110,6 +112,7 @@ CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ $(LDFLAGS) -o $@ SOURCES = $(libasan_la_SOURCES) DIST_SOURCES = $(libasan_la_SOURCES) +HEADERS = $(nodist_toolexeclib_HEADERS) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) @@ -257,6 +260,7 @@ AM_CXXFLAGS = -Wall -W -Wno-unused-parameter -Wwrite-strings -pedantic \ -Wno-variadic-macros $(LIBSTDCXX_RAW_CXX_CXXFLAGS) ACLOCAL_AMFLAGS = -I $(top_srcdir) -I $(top_srcdir)/config toolexeclib_LTLIBRARIES = libasan.la +nodist_toolexeclib_HEADERS = libasan_preinit.o asan_files = \ asan_allocator.cc \ asan_allocator2.cc \ @@ -447,6 +451,26 @@ mostlyclean-libtool: clean-libtool: -rm -rf .libs _libs +install-nodist_toolexeclibHEADERS: $(nodist_toolexeclib_HEADERS) + @$(NORMAL_INSTALL) + test -z "$(toolexeclibdir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibdir)" + @list='$(nodist_toolexeclib_HEADERS)'; test -n "$(toolexeclibdir)" || list=; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(toolexeclibdir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(toolexeclibdir)" || exit $$?; \ + done + +uninstall-nodist_toolexeclibHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(nodist_toolexeclib_HEADERS)'; test -n "$(toolexeclibdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '$(DESTDIR)$(toolexeclibdir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(toolexeclibdir)" && rm -f $$files ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ @@ -532,9 +556,9 @@ distdir: $(DISTFILES) done check-am: all-am check: check-am -all-am: Makefile $(LTLIBRARIES) +all-am: Makefile $(LTLIBRARIES) $(HEADERS) installdirs: - for dir in "$(DESTDIR)$(toolexeclibdir)"; do \ + for dir in "$(DESTDIR)$(toolexeclibdir)" "$(DESTDIR)$(toolexeclibdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am @@ -591,7 +615,8 @@ install-dvi: install-dvi-am install-dvi-am: -install-exec-am: install-toolexeclibLTLIBRARIES +install-exec-am: install-nodist_toolexeclibHEADERS \ + install-toolexeclibLTLIBRARIES install-html: install-html-am @@ -631,7 +656,8 @@ ps: ps-am ps-am: -uninstall-am: uninstall-toolexeclibLTLIBRARIES +uninstall-am: uninstall-nodist_toolexeclibHEADERS \ + uninstall-toolexeclibLTLIBRARIES .MAKE: install-am install-strip @@ -642,14 +668,19 @@ uninstall-am: uninstall-toolexeclibLTLIBRARIES install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ - install-pdf install-pdf-am install-ps install-ps-am \ - install-strip install-toolexeclibLTLIBRARIES installcheck \ - installcheck-am installdirs maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-compile \ - mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ - tags uninstall uninstall-am uninstall-toolexeclibLTLIBRARIES + install-nodist_toolexeclibHEADERS install-pdf install-pdf-am \ + install-ps install-ps-am install-strip \ + install-toolexeclibLTLIBRARIES installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \ + uninstall-am uninstall-nodist_toolexeclibHEADERS \ + uninstall-toolexeclibLTLIBRARIES +libasan_preinit.o: asan_preinit.o + cp $< $@ + # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: diff --git a/libsanitizer/asan/asan_preinit.cc b/libsanitizer/asan/asan_preinit.cc new file mode 100644 index 00000000000..40309fa389d --- /dev/null +++ b/libsanitizer/asan/asan_preinit.cc @@ -0,0 +1,27 @@ +//===-- asan_preinit.cc ---------------------------------------------------===// +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of AddressSanitizer, an address sanity checker. +// +// Call __asan_init at the very early stage of process startup. +// On Linux we use .preinit_array section (unless PIC macro is defined). +//===----------------------------------------------------------------------===// +#include "asan_internal.h" + +#if ASAN_USE_PREINIT_ARRAY && !defined(PIC) + // On Linux, we force __asan_init to be called before anyone else + // by placing it into .preinit_array section. + // FIXME: do we have anything like this on Mac? + __attribute__((section(".preinit_array"), used)) + void (*__asan_preinit)(void) =__asan_init; +#elif defined(_WIN32) && defined(_DLL) + // On Windows, when using dynamic CRT (/MD), we can put a pointer + // to __asan_init into the global list of C initializers. + // See crt0dat.c in the CRT sources for the details. + #pragma section(".CRT$XIB", long, read) // NOLINT + __declspec(allocate(".CRT$XIB")) void (*__asan_preinit)() = __asan_init; +#endif diff --git a/libsanitizer/asan/asan_rtl.cc b/libsanitizer/asan/asan_rtl.cc index 4b0afd2731a..e551b6fbc26 100644 --- a/libsanitizer/asan/asan_rtl.cc +++ b/libsanitizer/asan/asan_rtl.cc @@ -519,17 +519,3 @@ void __asan_init() { Report("AddressSanitizer Init done\n"); } } - -#if ASAN_USE_PREINIT_ARRAY && !defined (PIC) - // On Linux, we force __asan_init to be called before anyone else - // by placing it into .preinit_array section. - // FIXME: do we have anything like this on Mac? - __attribute__((section(".preinit_array"), used)) - void (*__asan_preinit)(void) =__asan_init; -#elif defined(_WIN32) && defined(_DLL) - // On Windows, when using dynamic CRT (/MD), we can put a pointer - // to __asan_init into the global list of C initializers. - // See crt0dat.c in the CRT sources for the details. - #pragma section(".CRT$XIB", long, read) // NOLINT - __declspec(allocate(".CRT$XIB")) void (*__asan_preinit)() = __asan_init; -#endif