On Fri, Feb 22, 2013 at 4:58 PM, Jakub Jelinek <ja...@redhat.com> wrote: > On Fri, Feb 22, 2013 at 11:53:39AM +0400, Konstantin Serebryany wrote: >> Jakub, thanks again for cleaning up my mess. >> >> Here is a question regarding your fix: >> > -#if ASAN_USE_PREINIT_ARRAY >> > +#if ASAN_USE_PREINIT_ARRAY && !defined (PIC) >> >> The PIC macro is an artifact of the GCC build system and is not >> directly related the the -fPIC flag? >> As I can see, in the gcc build we compile all of asan sources twice: >> w/ and w/o "-fPIC -DPIC". >> If I move the preinit_array to a separate file (asan_preinit.cc), will >> we need to have two builds? >> I think we can just build all objects once with -fPIC and then not >> link asan_preinit.o into libasan.so >> In clang we build the static libasan with -fPIC, it doesn't hurt. >> Anyway, I've just committed >> http://llvm.org/viewvc/llvm-project?rev=175871&view=rev with >> asan_preinit.cc > > Here is corresponding gcc patch to use it. > libasan_preinit.o is installed alongside with libasan.a and libasan.so*, > and linked into executables (but not shared libraries). > > Additionally, I've added __attribute__((constructor)) to __asan_init, > to make it more likely that asan will be initialized properly even when > the executable isn't instrumented. Shared libraries linked with > -fsanitize=address will depend on libasan.so.0, and the dynamic linker first > runs constructors of dependencies before running constructors of the > libraries that have those dependencies (unless there are dependency cycles, > but that > is a user bug).
Is there a use case where __attribute__((constructor)) in asan_rtl.cc will improve our chances to run early? the compiler module already inserts the call to __asan_init into a constructor of every module it instruments. Feel free to commit the rest, thanks! --kcc > > 2013-02-22 Jakub Jelinek <ja...@redhat.com> > > 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. > Add __attribute__((constructor)) to __asan_init. > > --- gcc/config/gnu-user.h.jj 2013-02-05 16:55:01.000000000 +0100 > +++ gcc/config/gnu-user.h 2013-02-22 13:02:11.000000000 +0100 > @@ -104,11 +104,13 @@ see the files COPYING3 and COPYING.RUNTI > 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 > --- gcc/testsuite/lib/asan-dg.exp.jj 2013-01-11 09:02:39.000000000 +0100 > +++ gcc/testsuite/lib/asan-dg.exp 2013-02-22 13:06:59.437483035 +0100 > @@ -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" > } > --- libsanitizer/asan/Makefile.am.jj 2013-02-21 20:10:41.000000000 +0100 > +++ libsanitizer/asan/Makefile.am 2013-02-22 12:36:30.746317422 +0100 > @@ -12,6 +12,7 @@ AM_CXXFLAGS += $(LIBSTDCXX_RAW_CXX_CXXFL > 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 > > 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. > --- libsanitizer/asan/asan_preinit.cc.jj 2013-02-22 12:12:11.387674830 > +0100 > +++ libsanitizer/asan/asan_preinit.cc 2013-02-22 12:12:11.387674830 +0100 > @@ -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 > --- libsanitizer/asan/asan_rtl.cc.jj 2013-02-21 15:25:00.000000000 +0100 > +++ libsanitizer/asan/asan_rtl.cc 2013-02-22 13:42:27.126406632 +0100 > @@ -405,6 +405,9 @@ void NOINLINE __asan_set_death_callback( > death_callback = callback; > } > > +#if ASAN_LINUX > +__attribute__((constructor)) > +#endif > void __asan_init() { > if (asan_inited) return; > SanitizerToolName = "AddressSanitizer"; > @@ -519,17 +522,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 > --- libsanitizer/asan/Makefile.in.jj 2013-02-21 20:11:25.000000000 +0100 > +++ libsanitizer/asan/Makefile.in 2013-02-22 12:37:15.719057387 +0100 > @@ -15,6 +15,7 @@ > > @SET_MAKE@ > > + > VPATH = @srcdir@ > pkgdatadir = $(datadir)/@PACKAGE@ > pkgincludedir = $(includedir)/@PACKAGE@ > @@ -75,7 +76,8 @@ am__nobase_list = $(am__nobase_strip_set > 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_LIBT > $(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-param > -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,13 +668,18 @@ uninstall-am: uninstall-toolexeclibLTLIB > 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. > > > Jakub