Patchwork r196201 - in /trunk: gcc/ChangeLog gcc/config/i...

login
register
mail settings
Submitter Jakub Jelinek
Date Feb. 22, 2013, 12:58 p.m.
Message ID <20130222125809.GK1215@tucnak.zalov.cz>
Download mbox | patch
Permalink /patch/222523/
State New
Headers show

Comments

Jakub Jelinek - Feb. 22, 2013, 12:58 p.m.
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).

2013-02-22  Jakub Jelinek  <jakub@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.



	Jakub
Konstantin Serebryany - Feb. 22, 2013, 1:56 p.m.
On Fri, Feb 22, 2013 at 4:58 PM, Jakub Jelinek <jakub@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  <jakub@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
Jakub Jelinek - Feb. 22, 2013, 3:35 p.m.
On Fri, Feb 22, 2013 at 05:56:34PM +0400, Konstantin Serebryany wrote:
> Is there a use case where __attribute__((constructor)) in asan_rtl.cc
> will improve our chances to run early?

I was thinking about something like:
cat > libab.C <<\EOF
static int a[10], b;
extern "C" void bar (void) __attribute__((noinline, noclone));

extern "C" void
bar (void)
{
  asm volatile ("" : : : "memory");
  a[b]++;
  asm volatile ("" : : : "memory");
  __builtin_printf ("libab bar\n");
}

static struct B
{
  B ();
} c;

B::B ()
{
  asm volatile ("" : : : "memory");
  a[b]++;
  asm volatile ("" : : : "memory");
  __builtin_printf ("B::B ()\n");
  bar ();
}
EOF
cat > libaa.C <<\EOF
static int a[10], b;
extern "C" void bar (void) __attribute__((noinline, noclone));

extern "C" void
bar (void)
{
  asm volatile ("" : : : "memory");
  a[b]++;
  asm volatile ("" : : : "memory");
  __builtin_printf ("libaa bar\n");
}

static struct A
{
  A ();
} c;

A::A ()
{
  asm volatile ("" : : : "memory");
  a[b]++;
  asm volatile ("" : : : "memory");
  __builtin_printf ("A::A ()\n");
  bar ();
}
EOF
cat > a.c <<\EOF
int a[10];

int
main ()
{
  int i = 11;
  asm volatile ("" : "+r" (i));
  a[i] = 1;
  return 0;
}
EOF
g++ -shared -fpic -o libab.so libab.C
g++ -shared -fsanitize=address -fpic -o libaa.so libaa.C ./libab.so
gcc -g -o a a.c -B ./ -Wl,-rpath-link,.,-rpath,. -laa
./a

With the constructor attribute, you can at least fix this by
LD_PRELOAD=libasan.so.0 ./a

Without it it will just crash.

So it serves at least as a workaround for the cases where you don't want or
can't for some reason instrument the executable, and e.g. libc, libpthread
otherwise are found earlier in the search scope (then generally libasan
doesn't really work) or some constructor of a non-instrumented library calls
into a symbol earlier in the search scope in a library which has been
instrumented.

Also note that this isn't a libasan.a vs. libasan.so debate, but rather
a debate about whether we can only support instrumented binaries, or also
(with some limitations) just instrumented shared libraries and
non-instrumented binaries.

	Jakub

Patch

--- 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.