aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.8/libsanitizer/asan
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.8/libsanitizer/asan')
-rw-r--r--gcc-4.8/libsanitizer/asan/Makefile.am93
-rw-r--r--gcc-4.8/libsanitizer/asan/Makefile.in686
-rw-r--r--gcc-4.8/libsanitizer/asan/asan_allocator.cc811
-rw-r--r--gcc-4.8/libsanitizer/asan/asan_allocator.h228
-rw-r--r--gcc-4.8/libsanitizer/asan/asan_allocator2.cc709
-rw-r--r--gcc-4.8/libsanitizer/asan/asan_fake_stack.cc179
-rw-r--r--gcc-4.8/libsanitizer/asan/asan_flags.h118
-rw-r--r--gcc-4.8/libsanitizer/asan/asan_globals.cc181
-rw-r--r--gcc-4.8/libsanitizer/asan/asan_intercepted_functions.h324
-rw-r--r--gcc-4.8/libsanitizer/asan/asan_interceptors.cc755
-rw-r--r--gcc-4.8/libsanitizer/asan/asan_interceptors.h36
-rw-r--r--gcc-4.8/libsanitizer/asan/asan_interface_internal.h133
-rw-r--r--gcc-4.8/libsanitizer/asan/asan_internal.h185
-rw-r--r--gcc-4.8/libsanitizer/asan/asan_linux.cc134
-rw-r--r--gcc-4.8/libsanitizer/asan/asan_lock.h1
-rw-r--r--gcc-4.8/libsanitizer/asan/asan_mac.cc452
-rw-r--r--gcc-4.8/libsanitizer/asan/asan_mac.h55
-rw-r--r--gcc-4.8/libsanitizer/asan/asan_malloc_linux.cc147
-rw-r--r--gcc-4.8/libsanitizer/asan/asan_malloc_mac.cc347
-rw-r--r--gcc-4.8/libsanitizer/asan/asan_malloc_win.cc140
-rw-r--r--gcc-4.8/libsanitizer/asan/asan_mapping.h222
-rw-r--r--gcc-4.8/libsanitizer/asan/asan_new_delete.cc67
-rw-r--r--gcc-4.8/libsanitizer/asan/asan_poisoning.cc217
-rw-r--r--gcc-4.8/libsanitizer/asan/asan_posix.cc118
-rw-r--r--gcc-4.8/libsanitizer/asan/asan_preinit.cc27
-rw-r--r--gcc-4.8/libsanitizer/asan/asan_report.cc717
-rw-r--r--gcc-4.8/libsanitizer/asan/asan_report.h55
-rw-r--r--gcc-4.8/libsanitizer/asan/asan_rtl.cc521
-rw-r--r--gcc-4.8/libsanitizer/asan/asan_stack.cc41
-rw-r--r--gcc-4.8/libsanitizer/asan/asan_stack.h64
-rw-r--r--gcc-4.8/libsanitizer/asan/asan_stats.cc91
-rw-r--r--gcc-4.8/libsanitizer/asan/asan_stats.h67
-rw-r--r--gcc-4.8/libsanitizer/asan/asan_thread.cc153
-rw-r--r--gcc-4.8/libsanitizer/asan/asan_thread.h112
-rw-r--r--gcc-4.8/libsanitizer/asan/asan_thread_registry.cc196
-rw-r--r--gcc-4.8/libsanitizer/asan/asan_thread_registry.h83
-rw-r--r--gcc-4.8/libsanitizer/asan/asan_win.cc157
-rw-r--r--gcc-4.8/libsanitizer/asan/libtool-version6
38 files changed, 8628 insertions, 0 deletions
diff --git a/gcc-4.8/libsanitizer/asan/Makefile.am b/gcc-4.8/libsanitizer/asan/Makefile.am
new file mode 100644
index 000000000..f7847db36
--- /dev/null
+++ b/gcc-4.8/libsanitizer/asan/Makefile.am
@@ -0,0 +1,93 @@
+AM_CPPFLAGS = -I $(top_srcdir)/include -I $(top_srcdir)
+
+# May be used by toolexeclibdir.
+gcc_version := $(shell cat $(top_srcdir)/../gcc/BASE-VER)
+
+DEFS = -D_GNU_SOURCE -D_DEBUG -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -DASAN_HAS_EXCEPTIONS=1 -DASAN_FLEXIBLE_MAPPING_AND_OFFSET=0 -DASAN_NEEDS_SEGV=1
+if USING_MAC_INTERPOSE
+DEFS += -DMAC_INTERPOSE_FUNCTIONS -DMISSING_BLOCKS_SUPPORT
+endif
+AM_CXXFLAGS = -Wall -W -Wno-unused-parameter -Wwrite-strings -pedantic -Wno-long-long -fPIC -fno-builtin -fno-exceptions -fomit-frame-pointer -funwind-tables -fvisibility=hidden -Wno-variadic-macros
+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 \
+ asan_allocator2.cc \
+ asan_interceptors.cc \
+ asan_mac.cc \
+ asan_malloc_mac.cc \
+ asan_new_delete.cc \
+ asan_posix.cc \
+ asan_rtl.cc \
+ asan_stats.cc \
+ asan_thread_registry.cc \
+ asan_fake_stack.cc \
+ asan_globals.cc \
+ asan_linux.cc \
+ asan_malloc_linux.cc \
+ asan_malloc_win.cc \
+ asan_poisoning.cc \
+ asan_report.cc \
+ asan_stack.cc \
+ asan_thread.cc \
+ asan_win.cc
+
+libasan_la_SOURCES = $(asan_files)
+if USING_MAC_INTERPOSE
+libasan_la_LIBADD = $(top_builddir)/sanitizer_common/libsanitizer_common.la
+else
+libasan_la_LIBADD = $(top_builddir)/sanitizer_common/libsanitizer_common.la $(top_builddir)/interception/libinterception.la
+endif
+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.
+AM_MAKEFLAGS = \
+ "AR_FLAGS=$(AR_FLAGS)" \
+ "CC_FOR_BUILD=$(CC_FOR_BUILD)" \
+ "CFLAGS=$(CFLAGS)" \
+ "CXXFLAGS=$(CXXFLAGS)" \
+ "CFLAGS_FOR_BUILD=$(CFLAGS_FOR_BUILD)" \
+ "CFLAGS_FOR_TARGET=$(CFLAGS_FOR_TARGET)" \
+ "INSTALL=$(INSTALL)" \
+ "INSTALL_DATA=$(INSTALL_DATA)" \
+ "INSTALL_PROGRAM=$(INSTALL_PROGRAM)" \
+ "INSTALL_SCRIPT=$(INSTALL_SCRIPT)" \
+ "JC1FLAGS=$(JC1FLAGS)" \
+ "LDFLAGS=$(LDFLAGS)" \
+ "LIBCFLAGS=$(LIBCFLAGS)" \
+ "LIBCFLAGS_FOR_TARGET=$(LIBCFLAGS_FOR_TARGET)" \
+ "MAKE=$(MAKE)" \
+ "MAKEINFO=$(MAKEINFO) $(MAKEINFOFLAGS)" \
+ "PICFLAG=$(PICFLAG)" \
+ "PICFLAG_FOR_TARGET=$(PICFLAG_FOR_TARGET)" \
+ "SHELL=$(SHELL)" \
+ "RUNTESTFLAGS=$(RUNTESTFLAGS)" \
+ "exec_prefix=$(exec_prefix)" \
+ "infodir=$(infodir)" \
+ "libdir=$(libdir)" \
+ "prefix=$(prefix)" \
+ "includedir=$(includedir)" \
+ "AR=$(AR)" \
+ "AS=$(AS)" \
+ "LD=$(LD)" \
+ "LIBCFLAGS=$(LIBCFLAGS)" \
+ "NM=$(NM)" \
+ "PICFLAG=$(PICFLAG)" \
+ "RANLIB=$(RANLIB)" \
+ "DESTDIR=$(DESTDIR)"
+
+MAKEOVERRIDES=
+
+## ################################################################
+
diff --git a/gcc-4.8/libsanitizer/asan/Makefile.in b/gcc-4.8/libsanitizer/asan/Makefile.in
new file mode 100644
index 000000000..d54f3a7be
--- /dev/null
+++ b/gcc-4.8/libsanitizer/asan/Makefile.in
@@ -0,0 +1,686 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+@USING_MAC_INTERPOSE_TRUE@am__append_1 = -DMAC_INTERPOSE_FUNCTIONS -DMISSING_BLOCKS_SUPPORT
+subdir = asan
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \
+ $(top_srcdir)/../config/depstand.m4 \
+ $(top_srcdir)/../config/lead-dot.m4 \
+ $(top_srcdir)/../config/libstdc++-raw-cxx.m4 \
+ $(top_srcdir)/../config/multi.m4 \
+ $(top_srcdir)/../config/override.m4 \
+ $(top_srcdir)/../ltoptions.m4 $(top_srcdir)/../ltsugar.m4 \
+ $(top_srcdir)/../ltversion.m4 $(top_srcdir)/../lt~obsolete.m4 \
+ $(top_srcdir)/acinclude.m4 $(top_srcdir)/../libtool.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+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)" \
+ "$(DESTDIR)$(toolexeclibdir)"
+LTLIBRARIES = $(toolexeclib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+@USING_MAC_INTERPOSE_FALSE@libasan_la_DEPENDENCIES = $(top_builddir)/sanitizer_common/libsanitizer_common.la \
+@USING_MAC_INTERPOSE_FALSE@ $(top_builddir)/interception/libinterception.la \
+@USING_MAC_INTERPOSE_FALSE@ $(am__DEPENDENCIES_1)
+@USING_MAC_INTERPOSE_TRUE@libasan_la_DEPENDENCIES = $(top_builddir)/sanitizer_common/libsanitizer_common.la \
+@USING_MAC_INTERPOSE_TRUE@ $(am__DEPENDENCIES_1)
+am__objects_1 = asan_allocator.lo asan_allocator2.lo \
+ asan_interceptors.lo asan_mac.lo asan_malloc_mac.lo \
+ asan_new_delete.lo asan_posix.lo asan_rtl.lo asan_stats.lo \
+ asan_thread_registry.lo asan_fake_stack.lo asan_globals.lo \
+ asan_linux.lo asan_malloc_linux.lo asan_malloc_win.lo \
+ asan_poisoning.lo asan_report.lo asan_stack.lo asan_thread.lo \
+ asan_win.lo
+am_libasan_la_OBJECTS = $(am__objects_1)
+libasan_la_OBJECTS = $(am_libasan_la_OBJECTS)
+libasan_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+ $(CXXFLAGS) $(libasan_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@
+depcomp = $(SHELL) $(top_srcdir)/../depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \
+ $(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)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCAS = @CCAS@
+CCASDEPMODE = @CCASDEPMODE@
+CCASFLAGS = @CCASFLAGS@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = -D_GNU_SOURCE -D_DEBUG -D__STDC_CONSTANT_MACROS \
+ -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS \
+ -DASAN_HAS_EXCEPTIONS=1 -DASAN_FLEXIBLE_MAPPING_AND_OFFSET=0 \
+ -DASAN_NEEDS_SEGV=1 $(am__append_1)
+DEPDIR = @DEPDIR@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBSTDCXX_RAW_CXX_CXXFLAGS = @LIBSTDCXX_RAW_CXX_CXXFLAGS@
+LIBSTDCXX_RAW_CXX_LDFLAGS = @LIBSTDCXX_RAW_CXX_LDFLAGS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+enable_shared = @enable_shared@
+enable_static = @enable_static@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+multi_basedir = @multi_basedir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_noncanonical = @target_noncanonical@
+target_os = @target_os@
+target_vendor = @target_vendor@
+toolexecdir = @toolexecdir@
+toolexeclibdir = @toolexeclibdir@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AM_CPPFLAGS = -I $(top_srcdir)/include -I $(top_srcdir)
+
+# May be used by toolexeclibdir.
+gcc_version := $(shell cat $(top_srcdir)/../gcc/BASE-VER)
+AM_CXXFLAGS = -Wall -W -Wno-unused-parameter -Wwrite-strings -pedantic \
+ -Wno-long-long -fPIC -fno-builtin -fno-exceptions \
+ -fomit-frame-pointer -funwind-tables -fvisibility=hidden \
+ -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 \
+ asan_interceptors.cc \
+ asan_mac.cc \
+ asan_malloc_mac.cc \
+ asan_new_delete.cc \
+ asan_posix.cc \
+ asan_rtl.cc \
+ asan_stats.cc \
+ asan_thread_registry.cc \
+ asan_fake_stack.cc \
+ asan_globals.cc \
+ asan_linux.cc \
+ asan_malloc_linux.cc \
+ asan_malloc_win.cc \
+ asan_poisoning.cc \
+ asan_report.cc \
+ asan_stack.cc \
+ asan_thread.cc \
+ asan_win.cc
+
+libasan_la_SOURCES = $(asan_files)
+@USING_MAC_INTERPOSE_FALSE@libasan_la_LIBADD = $(top_builddir)/sanitizer_common/libsanitizer_common.la \
+@USING_MAC_INTERPOSE_FALSE@ $(top_builddir)/interception/libinterception.la \
+@USING_MAC_INTERPOSE_FALSE@ $(LIBSTDCXX_RAW_CXX_LDFLAGS)
+@USING_MAC_INTERPOSE_TRUE@libasan_la_LIBADD = $(top_builddir)/sanitizer_common/libsanitizer_common.la \
+@USING_MAC_INTERPOSE_TRUE@ $(LIBSTDCXX_RAW_CXX_LDFLAGS)
+libasan_la_LDFLAGS = -version-info `grep -v '^\#' $(srcdir)/libtool-version` -lpthread -ldl
+
+# 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.
+AM_MAKEFLAGS = \
+ "AR_FLAGS=$(AR_FLAGS)" \
+ "CC_FOR_BUILD=$(CC_FOR_BUILD)" \
+ "CFLAGS=$(CFLAGS)" \
+ "CXXFLAGS=$(CXXFLAGS)" \
+ "CFLAGS_FOR_BUILD=$(CFLAGS_FOR_BUILD)" \
+ "CFLAGS_FOR_TARGET=$(CFLAGS_FOR_TARGET)" \
+ "INSTALL=$(INSTALL)" \
+ "INSTALL_DATA=$(INSTALL_DATA)" \
+ "INSTALL_PROGRAM=$(INSTALL_PROGRAM)" \
+ "INSTALL_SCRIPT=$(INSTALL_SCRIPT)" \
+ "JC1FLAGS=$(JC1FLAGS)" \
+ "LDFLAGS=$(LDFLAGS)" \
+ "LIBCFLAGS=$(LIBCFLAGS)" \
+ "LIBCFLAGS_FOR_TARGET=$(LIBCFLAGS_FOR_TARGET)" \
+ "MAKE=$(MAKE)" \
+ "MAKEINFO=$(MAKEINFO) $(MAKEINFOFLAGS)" \
+ "PICFLAG=$(PICFLAG)" \
+ "PICFLAG_FOR_TARGET=$(PICFLAG_FOR_TARGET)" \
+ "SHELL=$(SHELL)" \
+ "RUNTESTFLAGS=$(RUNTESTFLAGS)" \
+ "exec_prefix=$(exec_prefix)" \
+ "infodir=$(infodir)" \
+ "libdir=$(libdir)" \
+ "prefix=$(prefix)" \
+ "includedir=$(includedir)" \
+ "AR=$(AR)" \
+ "AS=$(AS)" \
+ "LD=$(LD)" \
+ "LIBCFLAGS=$(LIBCFLAGS)" \
+ "NM=$(NM)" \
+ "PICFLAG=$(PICFLAG)" \
+ "RANLIB=$(RANLIB)" \
+ "DESTDIR=$(DESTDIR)"
+
+MAKEOVERRIDES =
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .cc .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign asan/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign asan/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-toolexeclibLTLIBRARIES: $(toolexeclib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(toolexeclibdir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibdir)"
+ @list='$(toolexeclib_LTLIBRARIES)'; test -n "$(toolexeclibdir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(toolexeclibdir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(toolexeclibdir)"; \
+ }
+
+uninstall-toolexeclibLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(toolexeclib_LTLIBRARIES)'; test -n "$(toolexeclibdir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(toolexeclibdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(toolexeclibdir)/$$f"; \
+ done
+
+clean-toolexeclibLTLIBRARIES:
+ -test -z "$(toolexeclib_LTLIBRARIES)" || rm -f $(toolexeclib_LTLIBRARIES)
+ @list='$(toolexeclib_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libasan.la: $(libasan_la_OBJECTS) $(libasan_la_DEPENDENCIES)
+ $(libasan_la_LINK) -rpath $(toolexeclibdir) $(libasan_la_OBJECTS) $(libasan_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asan_allocator.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asan_allocator2.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asan_fake_stack.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asan_globals.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asan_interceptors.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asan_linux.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asan_mac.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asan_malloc_linux.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asan_malloc_mac.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asan_malloc_win.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asan_new_delete.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asan_poisoning.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asan_posix.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asan_report.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asan_rtl.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asan_stack.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asan_stats.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asan_thread.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asan_thread_registry.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asan_win.Plo@am__quote@
+
+.cc.o:
+@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
+
+.cc.obj:
+@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cc.lo:
+@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+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)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs:
+ for dir in "$(DESTDIR)$(toolexeclibdir)" "$(DESTDIR)$(toolexeclibdir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-toolexeclibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-nodist_toolexeclibHEADERS \
+ install-toolexeclibLTLIBRARIES
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-nodist_toolexeclibHEADERS \
+ uninstall-toolexeclibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-toolexeclibLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ 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-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/gcc-4.8/libsanitizer/asan/asan_allocator.cc b/gcc-4.8/libsanitizer/asan/asan_allocator.cc
new file mode 100644
index 000000000..4e97ff575
--- /dev/null
+++ b/gcc-4.8/libsanitizer/asan/asan_allocator.cc
@@ -0,0 +1,811 @@
+//===-- asan_allocator.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.
+//
+// Implementation of ASan's memory allocator.
+// Evey piece of memory (AsanChunk) allocated by the allocator
+// has a left redzone of REDZONE bytes and
+// a right redzone such that the end of the chunk is aligned by REDZONE
+// (i.e. the right redzone is between 0 and REDZONE-1).
+// The left redzone is always poisoned.
+// The right redzone is poisoned on malloc, the body is poisoned on free.
+// Once freed, a chunk is moved to a quarantine (fifo list).
+// After quarantine, a chunk is returned to freelists.
+//
+// The left redzone contains ASan's internal data and the stack trace of
+// the malloc call.
+// Once freed, the body of the chunk contains the stack trace of the free call.
+//
+//===----------------------------------------------------------------------===//
+#include "asan_allocator.h"
+
+#if ASAN_ALLOCATOR_VERSION == 1
+#include "asan_interceptors.h"
+#include "asan_internal.h"
+#include "asan_mapping.h"
+#include "asan_stats.h"
+#include "asan_report.h"
+#include "asan_thread.h"
+#include "asan_thread_registry.h"
+#include "sanitizer_common/sanitizer_allocator.h"
+#include "sanitizer_common/sanitizer_atomic.h"
+#include "sanitizer_common/sanitizer_mutex.h"
+
+namespace __asan {
+
+#define REDZONE ((uptr)(flags()->redzone))
+static const uptr kMinAllocSize = REDZONE * 2;
+static const u64 kMaxAvailableRam = 128ULL << 30; // 128G
+static const uptr kMaxThreadLocalQuarantine = 1 << 20; // 1M
+
+static const uptr kMinMmapSize = (ASAN_LOW_MEMORY) ? 4UL << 17 : 4UL << 20;
+static const uptr kMaxSizeForThreadLocalFreeList =
+ (ASAN_LOW_MEMORY) ? 1 << 15 : 1 << 17;
+
+// Size classes less than kMallocSizeClassStep are powers of two.
+// All other size classes are multiples of kMallocSizeClassStep.
+static const uptr kMallocSizeClassStepLog = 26;
+static const uptr kMallocSizeClassStep = 1UL << kMallocSizeClassStepLog;
+
+static const uptr kMaxAllowedMallocSize =
+ (SANITIZER_WORDSIZE == 32) ? 3UL << 30 : 8UL << 30;
+
+static inline uptr SizeClassToSize(u8 size_class) {
+ CHECK(size_class < kNumberOfSizeClasses);
+ if (size_class <= kMallocSizeClassStepLog) {
+ return 1UL << size_class;
+ } else {
+ return (size_class - kMallocSizeClassStepLog) * kMallocSizeClassStep;
+ }
+}
+
+static inline u8 SizeToSizeClass(uptr size) {
+ u8 res = 0;
+ if (size <= kMallocSizeClassStep) {
+ uptr rounded = RoundUpToPowerOfTwo(size);
+ res = Log2(rounded);
+ } else {
+ res = ((size + kMallocSizeClassStep - 1) / kMallocSizeClassStep)
+ + kMallocSizeClassStepLog;
+ }
+ CHECK(res < kNumberOfSizeClasses);
+ CHECK(size <= SizeClassToSize(res));
+ return res;
+}
+
+// Given REDZONE bytes, we need to mark first size bytes
+// as addressable and the rest REDZONE-size bytes as unaddressable.
+static void PoisonHeapPartialRightRedzone(uptr mem, uptr size) {
+ CHECK(size <= REDZONE);
+ CHECK(IsAligned(mem, REDZONE));
+ CHECK(IsPowerOfTwo(SHADOW_GRANULARITY));
+ CHECK(IsPowerOfTwo(REDZONE));
+ CHECK(REDZONE >= SHADOW_GRANULARITY);
+ PoisonShadowPartialRightRedzone(mem, size, REDZONE,
+ kAsanHeapRightRedzoneMagic);
+}
+
+static u8 *MmapNewPagesAndPoisonShadow(uptr size) {
+ CHECK(IsAligned(size, GetPageSizeCached()));
+ u8 *res = (u8*)MmapOrDie(size, __FUNCTION__);
+ PoisonShadow((uptr)res, size, kAsanHeapLeftRedzoneMagic);
+ if (flags()->debug) {
+ Printf("ASAN_MMAP: [%p, %p)\n", res, res + size);
+ }
+ return res;
+}
+
+// Every chunk of memory allocated by this allocator can be in one of 3 states:
+// CHUNK_AVAILABLE: the chunk is in the free list and ready to be allocated.
+// CHUNK_ALLOCATED: the chunk is allocated and not yet freed.
+// CHUNK_QUARANTINE: the chunk was freed and put into quarantine zone.
+//
+// The pseudo state CHUNK_MEMALIGN is used to mark that the address is not
+// the beginning of a AsanChunk (in which the actual chunk resides at
+// this - this->used_size).
+//
+// The magic numbers for the enum values are taken randomly.
+enum {
+ CHUNK_AVAILABLE = 0x57,
+ CHUNK_ALLOCATED = 0x32,
+ CHUNK_QUARANTINE = 0x19,
+ CHUNK_MEMALIGN = 0xDC
+};
+
+struct ChunkBase {
+ // First 8 bytes.
+ uptr chunk_state : 8;
+ uptr alloc_tid : 24;
+ uptr size_class : 8;
+ uptr free_tid : 24;
+
+ // Second 8 bytes.
+ uptr alignment_log : 8;
+ uptr alloc_type : 2;
+ uptr used_size : FIRST_32_SECOND_64(32, 54); // Size requested by the user.
+
+ // This field may overlap with the user area and thus should not
+ // be used while the chunk is in CHUNK_ALLOCATED state.
+ AsanChunk *next;
+
+ // Typically the beginning of the user-accessible memory is 'this'+REDZONE
+ // and is also aligned by REDZONE. However, if the memory is allocated
+ // by memalign, the alignment might be higher and the user-accessible memory
+ // starts at the first properly aligned address after 'this'.
+ uptr Beg() { return RoundUpTo((uptr)this + 1, 1 << alignment_log); }
+ uptr Size() { return SizeClassToSize(size_class); }
+ u8 SizeClass() { return size_class; }
+};
+
+struct AsanChunk: public ChunkBase {
+ u32 *compressed_alloc_stack() {
+ return (u32*)((uptr)this + sizeof(ChunkBase));
+ }
+ u32 *compressed_free_stack() {
+ return (u32*)((uptr)this + Max((uptr)REDZONE, (uptr)sizeof(ChunkBase)));
+ }
+
+ // The left redzone after the ChunkBase is given to the alloc stack trace.
+ uptr compressed_alloc_stack_size() {
+ if (REDZONE < sizeof(ChunkBase)) return 0;
+ return (REDZONE - sizeof(ChunkBase)) / sizeof(u32);
+ }
+ uptr compressed_free_stack_size() {
+ if (REDZONE < sizeof(ChunkBase)) return 0;
+ return (REDZONE) / sizeof(u32);
+ }
+};
+
+uptr AsanChunkView::Beg() { return chunk_->Beg(); }
+uptr AsanChunkView::End() { return Beg() + UsedSize(); }
+uptr AsanChunkView::UsedSize() { return chunk_->used_size; }
+uptr AsanChunkView::AllocTid() { return chunk_->alloc_tid; }
+uptr AsanChunkView::FreeTid() { return chunk_->free_tid; }
+
+void AsanChunkView::GetAllocStack(StackTrace *stack) {
+ StackTrace::UncompressStack(stack, chunk_->compressed_alloc_stack(),
+ chunk_->compressed_alloc_stack_size());
+}
+
+void AsanChunkView::GetFreeStack(StackTrace *stack) {
+ StackTrace::UncompressStack(stack, chunk_->compressed_free_stack(),
+ chunk_->compressed_free_stack_size());
+}
+
+static AsanChunk *PtrToChunk(uptr ptr) {
+ AsanChunk *m = (AsanChunk*)(ptr - REDZONE);
+ if (m->chunk_state == CHUNK_MEMALIGN) {
+ m = (AsanChunk*)((uptr)m - m->used_size);
+ }
+ return m;
+}
+
+void AsanChunkFifoList::PushList(AsanChunkFifoList *q) {
+ CHECK(q->size() > 0);
+ size_ += q->size();
+ append_back(q);
+ q->clear();
+}
+
+void AsanChunkFifoList::Push(AsanChunk *n) {
+ push_back(n);
+ size_ += n->Size();
+}
+
+// Interesting performance observation: this function takes up to 15% of overal
+// allocator time. That's because *first_ has been evicted from cache long time
+// ago. Not sure if we can or want to do anything with this.
+AsanChunk *AsanChunkFifoList::Pop() {
+ CHECK(first_);
+ AsanChunk *res = front();
+ size_ -= res->Size();
+ pop_front();
+ return res;
+}
+
+// All pages we ever allocated.
+struct PageGroup {
+ uptr beg;
+ uptr end;
+ uptr size_of_chunk;
+ uptr last_chunk;
+ bool InRange(uptr addr) {
+ return addr >= beg && addr < end;
+ }
+};
+
+class MallocInfo {
+ public:
+ explicit MallocInfo(LinkerInitialized x) : mu_(x) { }
+
+ AsanChunk *AllocateChunks(u8 size_class, uptr n_chunks) {
+ AsanChunk *m = 0;
+ AsanChunk **fl = &free_lists_[size_class];
+ {
+ BlockingMutexLock lock(&mu_);
+ for (uptr i = 0; i < n_chunks; i++) {
+ if (!(*fl)) {
+ *fl = GetNewChunks(size_class);
+ }
+ AsanChunk *t = *fl;
+ *fl = t->next;
+ t->next = m;
+ CHECK(t->chunk_state == CHUNK_AVAILABLE);
+ m = t;
+ }
+ }
+ return m;
+ }
+
+ void SwallowThreadLocalMallocStorage(AsanThreadLocalMallocStorage *x,
+ bool eat_free_lists) {
+ CHECK(flags()->quarantine_size > 0);
+ BlockingMutexLock lock(&mu_);
+ AsanChunkFifoList *q = &x->quarantine_;
+ if (q->size() > 0) {
+ quarantine_.PushList(q);
+ while (quarantine_.size() > (uptr)flags()->quarantine_size) {
+ QuarantinePop();
+ }
+ }
+ if (eat_free_lists) {
+ for (uptr size_class = 0; size_class < kNumberOfSizeClasses;
+ size_class++) {
+ AsanChunk *m = x->free_lists_[size_class];
+ while (m) {
+ AsanChunk *t = m->next;
+ m->next = free_lists_[size_class];
+ free_lists_[size_class] = m;
+ m = t;
+ }
+ x->free_lists_[size_class] = 0;
+ }
+ }
+ }
+
+ void BypassThreadLocalQuarantine(AsanChunk *chunk) {
+ BlockingMutexLock lock(&mu_);
+ quarantine_.Push(chunk);
+ }
+
+ AsanChunk *FindChunkByAddr(uptr addr) {
+ BlockingMutexLock lock(&mu_);
+ return FindChunkByAddrUnlocked(addr);
+ }
+
+ uptr AllocationSize(uptr ptr) {
+ if (!ptr) return 0;
+ BlockingMutexLock lock(&mu_);
+
+ // Make sure this is our chunk and |ptr| actually points to the beginning
+ // of the allocated memory.
+ AsanChunk *m = FindChunkByAddrUnlocked(ptr);
+ if (!m || m->Beg() != ptr) return 0;
+
+ if (m->chunk_state == CHUNK_ALLOCATED) {
+ return m->used_size;
+ } else {
+ return 0;
+ }
+ }
+
+ void ForceLock() {
+ mu_.Lock();
+ }
+
+ void ForceUnlock() {
+ mu_.Unlock();
+ }
+
+ void PrintStatus() {
+ BlockingMutexLock lock(&mu_);
+ uptr malloced = 0;
+
+ Printf(" MallocInfo: in quarantine: %zu malloced: %zu; ",
+ quarantine_.size() >> 20, malloced >> 20);
+ for (uptr j = 1; j < kNumberOfSizeClasses; j++) {
+ AsanChunk *i = free_lists_[j];
+ if (!i) continue;
+ uptr t = 0;
+ for (; i; i = i->next) {
+ t += i->Size();
+ }
+ Printf("%zu:%zu ", j, t >> 20);
+ }
+ Printf("\n");
+ }
+
+ PageGroup *FindPageGroup(uptr addr) {
+ BlockingMutexLock lock(&mu_);
+ return FindPageGroupUnlocked(addr);
+ }
+
+ private:
+ PageGroup *FindPageGroupUnlocked(uptr addr) {
+ int n = atomic_load(&n_page_groups_, memory_order_relaxed);
+ // If the page groups are not sorted yet, sort them.
+ if (n_sorted_page_groups_ < n) {
+ SortArray((uptr*)page_groups_, n);
+ n_sorted_page_groups_ = n;
+ }
+ // Binary search over the page groups.
+ int beg = 0, end = n;
+ while (beg < end) {
+ int med = (beg + end) / 2;
+ uptr g = (uptr)page_groups_[med];
+ if (addr > g) {
+ // 'g' points to the end of the group, so 'addr'
+ // may not belong to page_groups_[med] or any previous group.
+ beg = med + 1;
+ } else {
+ // 'addr' may belong to page_groups_[med] or a previous group.
+ end = med;
+ }
+ }
+ if (beg >= n)
+ return 0;
+ PageGroup *g = page_groups_[beg];
+ CHECK(g);
+ if (g->InRange(addr))
+ return g;
+ return 0;
+ }
+
+ // We have an address between two chunks, and we want to report just one.
+ AsanChunk *ChooseChunk(uptr addr,
+ AsanChunk *left_chunk, AsanChunk *right_chunk) {
+ // Prefer an allocated chunk or a chunk from quarantine.
+ if (left_chunk->chunk_state == CHUNK_AVAILABLE &&
+ right_chunk->chunk_state != CHUNK_AVAILABLE)
+ return right_chunk;
+ if (right_chunk->chunk_state == CHUNK_AVAILABLE &&
+ left_chunk->chunk_state != CHUNK_AVAILABLE)
+ return left_chunk;
+ // Choose based on offset.
+ sptr l_offset = 0, r_offset = 0;
+ CHECK(AsanChunkView(left_chunk).AddrIsAtRight(addr, 1, &l_offset));
+ CHECK(AsanChunkView(right_chunk).AddrIsAtLeft(addr, 1, &r_offset));
+ if (l_offset < r_offset)
+ return left_chunk;
+ return right_chunk;
+ }
+
+ AsanChunk *FindChunkByAddrUnlocked(uptr addr) {
+ PageGroup *g = FindPageGroupUnlocked(addr);
+ if (!g) return 0;
+ CHECK(g->size_of_chunk);
+ uptr offset_from_beg = addr - g->beg;
+ uptr this_chunk_addr = g->beg +
+ (offset_from_beg / g->size_of_chunk) * g->size_of_chunk;
+ CHECK(g->InRange(this_chunk_addr));
+ AsanChunk *m = (AsanChunk*)this_chunk_addr;
+ CHECK(m->chunk_state == CHUNK_ALLOCATED ||
+ m->chunk_state == CHUNK_AVAILABLE ||
+ m->chunk_state == CHUNK_QUARANTINE);
+ sptr offset = 0;
+ AsanChunkView m_view(m);
+ if (m_view.AddrIsInside(addr, 1, &offset))
+ return m;
+
+ if (m_view.AddrIsAtRight(addr, 1, &offset)) {
+ if (this_chunk_addr == g->last_chunk) // rightmost chunk
+ return m;
+ uptr right_chunk_addr = this_chunk_addr + g->size_of_chunk;
+ CHECK(g->InRange(right_chunk_addr));
+ return ChooseChunk(addr, m, (AsanChunk*)right_chunk_addr);
+ } else {
+ CHECK(m_view.AddrIsAtLeft(addr, 1, &offset));
+ if (this_chunk_addr == g->beg) // leftmost chunk
+ return m;
+ uptr left_chunk_addr = this_chunk_addr - g->size_of_chunk;
+ CHECK(g->InRange(left_chunk_addr));
+ return ChooseChunk(addr, (AsanChunk*)left_chunk_addr, m);
+ }
+ }
+
+ void QuarantinePop() {
+ CHECK(quarantine_.size() > 0);
+ AsanChunk *m = quarantine_.Pop();
+ CHECK(m);
+ // if (F_v >= 2) Printf("MallocInfo::pop %p\n", m);
+
+ CHECK(m->chunk_state == CHUNK_QUARANTINE);
+ m->chunk_state = CHUNK_AVAILABLE;
+ PoisonShadow((uptr)m, m->Size(), kAsanHeapLeftRedzoneMagic);
+ CHECK(m->alloc_tid >= 0);
+ CHECK(m->free_tid >= 0);
+
+ uptr size_class = m->SizeClass();
+ m->next = free_lists_[size_class];
+ free_lists_[size_class] = m;
+
+ // Statistics.
+ AsanStats &thread_stats = asanThreadRegistry().GetCurrentThreadStats();
+ thread_stats.real_frees++;
+ thread_stats.really_freed += m->used_size;
+ thread_stats.really_freed_redzones += m->Size() - m->used_size;
+ thread_stats.really_freed_by_size[m->SizeClass()]++;
+ }
+
+ // Get a list of newly allocated chunks.
+ AsanChunk *GetNewChunks(u8 size_class) {
+ uptr size = SizeClassToSize(size_class);
+ CHECK(IsPowerOfTwo(kMinMmapSize));
+ CHECK(size < kMinMmapSize || (size % kMinMmapSize) == 0);
+ uptr mmap_size = Max(size, kMinMmapSize);
+ uptr n_chunks = mmap_size / size;
+ CHECK(n_chunks * size == mmap_size);
+ uptr PageSize = GetPageSizeCached();
+ if (size < PageSize) {
+ // Size is small, just poison the last chunk.
+ n_chunks--;
+ } else {
+ // Size is large, allocate an extra page at right and poison it.
+ mmap_size += PageSize;
+ }
+ CHECK(n_chunks > 0);
+ u8 *mem = MmapNewPagesAndPoisonShadow(mmap_size);
+
+ // Statistics.
+ AsanStats &thread_stats = asanThreadRegistry().GetCurrentThreadStats();
+ thread_stats.mmaps++;
+ thread_stats.mmaped += mmap_size;
+ thread_stats.mmaped_by_size[size_class] += n_chunks;
+
+ AsanChunk *res = 0;
+ for (uptr i = 0; i < n_chunks; i++) {
+ AsanChunk *m = (AsanChunk*)(mem + i * size);
+ m->chunk_state = CHUNK_AVAILABLE;
+ m->size_class = size_class;
+ m->next = res;
+ res = m;
+ }
+ PageGroup *pg = (PageGroup*)(mem + n_chunks * size);
+ // This memory is already poisoned, no need to poison it again.
+ pg->beg = (uptr)mem;
+ pg->end = pg->beg + mmap_size;
+ pg->size_of_chunk = size;
+ pg->last_chunk = (uptr)(mem + size * (n_chunks - 1));
+ int idx = atomic_fetch_add(&n_page_groups_, 1, memory_order_relaxed);
+ CHECK(idx < (int)ARRAY_SIZE(page_groups_));
+ page_groups_[idx] = pg;
+ return res;
+ }
+
+ AsanChunk *free_lists_[kNumberOfSizeClasses];
+ AsanChunkFifoList quarantine_;
+ BlockingMutex mu_;
+
+ PageGroup *page_groups_[kMaxAvailableRam / kMinMmapSize];
+ atomic_uint32_t n_page_groups_;
+ int n_sorted_page_groups_;
+};
+
+static MallocInfo malloc_info(LINKER_INITIALIZED);
+
+void AsanThreadLocalMallocStorage::CommitBack() {
+ malloc_info.SwallowThreadLocalMallocStorage(this, true);
+}
+
+AsanChunkView FindHeapChunkByAddress(uptr address) {
+ return AsanChunkView(malloc_info.FindChunkByAddr(address));
+}
+
+static u8 *Allocate(uptr alignment, uptr size, StackTrace *stack,
+ AllocType alloc_type) {
+ __asan_init();
+ CHECK(stack);
+ if (size == 0) {
+ size = 1; // TODO(kcc): do something smarter
+ }
+ CHECK(IsPowerOfTwo(alignment));
+ uptr rounded_size = RoundUpTo(size, REDZONE);
+ uptr needed_size = rounded_size + REDZONE;
+ if (alignment > REDZONE) {
+ needed_size += alignment;
+ }
+ CHECK(IsAligned(needed_size, REDZONE));
+ if (size > kMaxAllowedMallocSize || needed_size > kMaxAllowedMallocSize) {
+ Report("WARNING: AddressSanitizer failed to allocate %p bytes\n",
+ (void*)size);
+ return 0;
+ }
+
+ u8 size_class = SizeToSizeClass(needed_size);
+ uptr size_to_allocate = SizeClassToSize(size_class);
+ CHECK(size_to_allocate >= kMinAllocSize);
+ CHECK(size_to_allocate >= needed_size);
+ CHECK(IsAligned(size_to_allocate, REDZONE));
+
+ if (flags()->verbosity >= 3) {
+ Printf("Allocate align: %zu size: %zu class: %u real: %zu\n",
+ alignment, size, size_class, size_to_allocate);
+ }
+
+ AsanThread *t = asanThreadRegistry().GetCurrent();
+ AsanStats &thread_stats = asanThreadRegistry().GetCurrentThreadStats();
+ // Statistics
+ thread_stats.mallocs++;
+ thread_stats.malloced += size;
+ thread_stats.malloced_redzones += size_to_allocate - size;
+ thread_stats.malloced_by_size[size_class]++;
+
+ AsanChunk *m = 0;
+ if (!t || size_to_allocate >= kMaxSizeForThreadLocalFreeList) {
+ // get directly from global storage.
+ m = malloc_info.AllocateChunks(size_class, 1);
+ thread_stats.malloc_large++;
+ } else {
+ // get from the thread-local storage.
+ AsanChunk **fl = &t->malloc_storage().free_lists_[size_class];
+ if (!*fl) {
+ uptr n_new_chunks = kMaxSizeForThreadLocalFreeList / size_to_allocate;
+ *fl = malloc_info.AllocateChunks(size_class, n_new_chunks);
+ thread_stats.malloc_small_slow++;
+ }
+ m = *fl;
+ *fl = (*fl)->next;
+ }
+ CHECK(m);
+ CHECK(m->chunk_state == CHUNK_AVAILABLE);
+ m->chunk_state = CHUNK_ALLOCATED;
+ m->alloc_type = alloc_type;
+ m->next = 0;
+ CHECK(m->Size() == size_to_allocate);
+ uptr addr = (uptr)m + REDZONE;
+ CHECK(addr <= (uptr)m->compressed_free_stack());
+
+ if (alignment > REDZONE && (addr & (alignment - 1))) {
+ addr = RoundUpTo(addr, alignment);
+ CHECK((addr & (alignment - 1)) == 0);
+ AsanChunk *p = (AsanChunk*)(addr - REDZONE);
+ p->chunk_state = CHUNK_MEMALIGN;
+ p->used_size = (uptr)p - (uptr)m;
+ m->alignment_log = Log2(alignment);
+ CHECK(m->Beg() == addr);
+ } else {
+ m->alignment_log = Log2(REDZONE);
+ }
+ CHECK(m == PtrToChunk(addr));
+ m->used_size = size;
+ CHECK(m->Beg() == addr);
+ m->alloc_tid = t ? t->tid() : 0;
+ m->free_tid = kInvalidTid;
+ StackTrace::CompressStack(stack, m->compressed_alloc_stack(),
+ m->compressed_alloc_stack_size());
+ PoisonShadow(addr, rounded_size, 0);
+ if (size < rounded_size) {
+ PoisonHeapPartialRightRedzone(addr + rounded_size - REDZONE,
+ size & (REDZONE - 1));
+ }
+ if (size <= (uptr)(flags()->max_malloc_fill_size)) {
+ REAL(memset)((void*)addr, 0, rounded_size);
+ }
+ return (u8*)addr;
+}
+
+static void Deallocate(u8 *ptr, StackTrace *stack, AllocType alloc_type) {
+ if (!ptr) return;
+ CHECK(stack);
+
+ if (flags()->debug) {
+ CHECK(malloc_info.FindPageGroup((uptr)ptr));
+ }
+
+ // Printf("Deallocate %p\n", ptr);
+ AsanChunk *m = PtrToChunk((uptr)ptr);
+
+ // Flip the chunk_state atomically to avoid race on double-free.
+ u8 old_chunk_state = atomic_exchange((atomic_uint8_t*)m, CHUNK_QUARANTINE,
+ memory_order_acq_rel);
+
+ if (old_chunk_state == CHUNK_QUARANTINE) {
+ ReportDoubleFree((uptr)ptr, stack);
+ } else if (old_chunk_state != CHUNK_ALLOCATED) {
+ ReportFreeNotMalloced((uptr)ptr, stack);
+ }
+ CHECK(old_chunk_state == CHUNK_ALLOCATED);
+ if (m->alloc_type != alloc_type && flags()->alloc_dealloc_mismatch)
+ ReportAllocTypeMismatch((uptr)ptr, stack,
+ (AllocType)m->alloc_type, (AllocType)alloc_type);
+ // With REDZONE==16 m->next is in the user area, otherwise it should be 0.
+ CHECK(REDZONE <= 16 || !m->next);
+ CHECK(m->free_tid == kInvalidTid);
+ CHECK(m->alloc_tid >= 0);
+ AsanThread *t = asanThreadRegistry().GetCurrent();
+ m->free_tid = t ? t->tid() : 0;
+ StackTrace::CompressStack(stack, m->compressed_free_stack(),
+ m->compressed_free_stack_size());
+ uptr rounded_size = RoundUpTo(m->used_size, REDZONE);
+ PoisonShadow((uptr)ptr, rounded_size, kAsanHeapFreeMagic);
+
+ // Statistics.
+ AsanStats &thread_stats = asanThreadRegistry().GetCurrentThreadStats();
+ thread_stats.frees++;
+ thread_stats.freed += m->used_size;
+ thread_stats.freed_by_size[m->SizeClass()]++;
+
+ CHECK(m->chunk_state == CHUNK_QUARANTINE);
+
+ if (t) {
+ AsanThreadLocalMallocStorage *ms = &t->malloc_storage();
+ ms->quarantine_.Push(m);
+
+ if (ms->quarantine_.size() > kMaxThreadLocalQuarantine) {
+ malloc_info.SwallowThreadLocalMallocStorage(ms, false);
+ }
+ } else {
+ malloc_info.BypassThreadLocalQuarantine(m);
+ }
+}
+
+static u8 *Reallocate(u8 *old_ptr, uptr new_size,
+ StackTrace *stack) {
+ CHECK(old_ptr && new_size);
+
+ // Statistics.
+ AsanStats &thread_stats = asanThreadRegistry().GetCurrentThreadStats();
+ thread_stats.reallocs++;
+ thread_stats.realloced += new_size;
+
+ AsanChunk *m = PtrToChunk((uptr)old_ptr);
+ CHECK(m->chunk_state == CHUNK_ALLOCATED);
+ uptr old_size = m->used_size;
+ uptr memcpy_size = Min(new_size, old_size);
+ u8 *new_ptr = Allocate(0, new_size, stack, FROM_MALLOC);
+ if (new_ptr) {
+ CHECK(REAL(memcpy) != 0);
+ REAL(memcpy)(new_ptr, old_ptr, memcpy_size);
+ Deallocate(old_ptr, stack, FROM_MALLOC);
+ }
+ return new_ptr;
+}
+
+} // namespace __asan
+
+#if !SANITIZER_SUPPORTS_WEAK_HOOKS
+// Provide default (no-op) implementation of malloc hooks.
+extern "C" {
+SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
+void __asan_malloc_hook(void *ptr, uptr size) {
+ (void)ptr;
+ (void)size;
+}
+SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
+void __asan_free_hook(void *ptr) {
+ (void)ptr;
+}
+} // extern "C"
+#endif
+
+namespace __asan {
+
+void InitializeAllocator() { }
+
+void PrintInternalAllocatorStats() {
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void *asan_memalign(uptr alignment, uptr size, StackTrace *stack,
+ AllocType alloc_type) {
+ void *ptr = (void*)Allocate(alignment, size, stack, alloc_type);
+ ASAN_MALLOC_HOOK(ptr, size);
+ return ptr;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void asan_free(void *ptr, StackTrace *stack, AllocType alloc_type) {
+ ASAN_FREE_HOOK(ptr);
+ Deallocate((u8*)ptr, stack, alloc_type);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void *asan_malloc(uptr size, StackTrace *stack) {
+ void *ptr = (void*)Allocate(0, size, stack, FROM_MALLOC);
+ ASAN_MALLOC_HOOK(ptr, size);
+ return ptr;
+}
+
+void *asan_calloc(uptr nmemb, uptr size, StackTrace *stack) {
+ if (__sanitizer::CallocShouldReturnNullDueToOverflow(size, nmemb)) return 0;
+ void *ptr = (void*)Allocate(0, nmemb * size, stack, FROM_MALLOC);
+ if (ptr)
+ REAL(memset)(ptr, 0, nmemb * size);
+ ASAN_MALLOC_HOOK(ptr, size);
+ return ptr;
+}
+
+void *asan_realloc(void *p, uptr size, StackTrace *stack) {
+ if (p == 0) {
+ void *ptr = (void*)Allocate(0, size, stack, FROM_MALLOC);
+ ASAN_MALLOC_HOOK(ptr, size);
+ return ptr;
+ } else if (size == 0) {
+ ASAN_FREE_HOOK(p);
+ Deallocate((u8*)p, stack, FROM_MALLOC);
+ return 0;
+ }
+ return Reallocate((u8*)p, size, stack);
+}
+
+void *asan_valloc(uptr size, StackTrace *stack) {
+ void *ptr = (void*)Allocate(GetPageSizeCached(), size, stack, FROM_MALLOC);
+ ASAN_MALLOC_HOOK(ptr, size);
+ return ptr;
+}
+
+void *asan_pvalloc(uptr size, StackTrace *stack) {
+ uptr PageSize = GetPageSizeCached();
+ size = RoundUpTo(size, PageSize);
+ if (size == 0) {
+ // pvalloc(0) should allocate one page.
+ size = PageSize;
+ }
+ void *ptr = (void*)Allocate(PageSize, size, stack, FROM_MALLOC);
+ ASAN_MALLOC_HOOK(ptr, size);
+ return ptr;
+}
+
+int asan_posix_memalign(void **memptr, uptr alignment, uptr size,
+ StackTrace *stack) {
+ void *ptr = Allocate(alignment, size, stack, FROM_MALLOC);
+ CHECK(IsAligned((uptr)ptr, alignment));
+ ASAN_MALLOC_HOOK(ptr, size);
+ *memptr = ptr;
+ return 0;
+}
+
+uptr asan_malloc_usable_size(void *ptr, StackTrace *stack) {
+ CHECK(stack);
+ if (ptr == 0) return 0;
+ uptr usable_size = malloc_info.AllocationSize((uptr)ptr);
+ if (flags()->check_malloc_usable_size && (usable_size == 0)) {
+ ReportMallocUsableSizeNotOwned((uptr)ptr, stack);
+ }
+ return usable_size;
+}
+
+uptr asan_mz_size(const void *ptr) {
+ return malloc_info.AllocationSize((uptr)ptr);
+}
+
+void asan_mz_force_lock() {
+ malloc_info.ForceLock();
+}
+
+void asan_mz_force_unlock() {
+ malloc_info.ForceUnlock();
+}
+
+} // namespace __asan
+
+// ---------------------- Interface ---------------- {{{1
+using namespace __asan; // NOLINT
+
+// ASan allocator doesn't reserve extra bytes, so normally we would
+// just return "size".
+uptr __asan_get_estimated_allocated_size(uptr size) {
+ if (size == 0) return 1;
+ return Min(size, kMaxAllowedMallocSize);
+}
+
+bool __asan_get_ownership(const void *p) {
+ return malloc_info.AllocationSize((uptr)p) > 0;
+}
+
+uptr __asan_get_allocated_size(const void *p) {
+ if (p == 0) return 0;
+ uptr allocated_size = malloc_info.AllocationSize((uptr)p);
+ // Die if p is not malloced or if it is already freed.
+ if (allocated_size == 0) {
+ GET_STACK_TRACE_FATAL_HERE;
+ ReportAsanGetAllocatedSizeNotOwned((uptr)p, &stack);
+ }
+ return allocated_size;
+}
+#endif // ASAN_ALLOCATOR_VERSION
diff --git a/gcc-4.8/libsanitizer/asan/asan_allocator.h b/gcc-4.8/libsanitizer/asan/asan_allocator.h
new file mode 100644
index 000000000..df2f520c4
--- /dev/null
+++ b/gcc-4.8/libsanitizer/asan/asan_allocator.h
@@ -0,0 +1,228 @@
+//===-- asan_allocator.h ----------------------------------------*- C++ -*-===//
+//
+// 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.
+//
+// ASan-private header for asan_allocator.cc.
+//===----------------------------------------------------------------------===//
+
+#ifndef ASAN_ALLOCATOR_H
+#define ASAN_ALLOCATOR_H
+
+#include "asan_internal.h"
+#include "asan_interceptors.h"
+#include "sanitizer_common/sanitizer_list.h"
+
+// We are in the process of transitioning from the old allocator (version 1)
+// to a new one (version 2). The change is quite intrusive so both allocators
+// will co-exist in the source base for a while. The actual allocator is chosen
+// at build time by redefining this macro.
+#ifndef ASAN_ALLOCATOR_VERSION
+# if (ASAN_LINUX && !ASAN_ANDROID) || ASAN_MAC || ASAN_WINDOWS
+# define ASAN_ALLOCATOR_VERSION 2
+# else
+# define ASAN_ALLOCATOR_VERSION 1
+# endif
+#endif // ASAN_ALLOCATOR_VERSION
+
+namespace __asan {
+
+enum AllocType {
+ FROM_MALLOC = 1, // Memory block came from malloc, calloc, realloc, etc.
+ FROM_NEW = 2, // Memory block came from operator new.
+ FROM_NEW_BR = 3 // Memory block came from operator new [ ]
+};
+
+static const uptr kNumberOfSizeClasses = 255;
+struct AsanChunk;
+
+void InitializeAllocator();
+
+class AsanChunkView {
+ public:
+ explicit AsanChunkView(AsanChunk *chunk) : chunk_(chunk) {}
+ bool IsValid() { return chunk_ != 0; }
+ uptr Beg(); // first byte of user memory.
+ uptr End(); // last byte of user memory.
+ uptr UsedSize(); // size requested by the user.
+ uptr AllocTid();
+ uptr FreeTid();
+ void GetAllocStack(StackTrace *stack);
+ void GetFreeStack(StackTrace *stack);
+ bool AddrIsInside(uptr addr, uptr access_size, sptr *offset) {
+ if (addr >= Beg() && (addr + access_size) <= End()) {
+ *offset = addr - Beg();
+ return true;
+ }
+ return false;
+ }
+ bool AddrIsAtLeft(uptr addr, uptr access_size, sptr *offset) {
+ (void)access_size;
+ if (addr < Beg()) {
+ *offset = Beg() - addr;
+ return true;
+ }
+ return false;
+ }
+ bool AddrIsAtRight(uptr addr, uptr access_size, sptr *offset) {
+ if (addr + access_size > End()) {
+ *offset = addr - End();
+ return true;
+ }
+ return false;
+ }
+
+ private:
+ AsanChunk *const chunk_;
+};
+
+AsanChunkView FindHeapChunkByAddress(uptr address);
+
+// List of AsanChunks with total size.
+class AsanChunkFifoList: public IntrusiveList<AsanChunk> {
+ public:
+ explicit AsanChunkFifoList(LinkerInitialized) { }
+ AsanChunkFifoList() { clear(); }
+ void Push(AsanChunk *n);
+ void PushList(AsanChunkFifoList *q);
+ AsanChunk *Pop();
+ uptr size() { return size_; }
+ void clear() {
+ IntrusiveList<AsanChunk>::clear();
+ size_ = 0;
+ }
+ private:
+ uptr size_;
+};
+
+struct AsanThreadLocalMallocStorage {
+ explicit AsanThreadLocalMallocStorage(LinkerInitialized x)
+#if ASAN_ALLOCATOR_VERSION == 1
+ : quarantine_(x)
+#endif
+ { }
+ AsanThreadLocalMallocStorage() {
+ CHECK(REAL(memset));
+ REAL(memset)(this, 0, sizeof(AsanThreadLocalMallocStorage));
+ }
+
+#if ASAN_ALLOCATOR_VERSION == 1
+ AsanChunkFifoList quarantine_;
+ AsanChunk *free_lists_[kNumberOfSizeClasses];
+#else
+ uptr quarantine_cache[16];
+ uptr allocator2_cache[96 * (512 * 8 + 16)]; // Opaque.
+#endif
+ void CommitBack();
+};
+
+// Fake stack frame contains local variables of one function.
+// This struct should fit into a stack redzone (32 bytes).
+struct FakeFrame {
+ uptr magic; // Modified by the instrumented code.
+ uptr descr; // Modified by the instrumented code.
+ FakeFrame *next;
+ u64 real_stack : 48;
+ u64 size_minus_one : 16;
+};
+
+struct FakeFrameFifo {
+ public:
+ void FifoPush(FakeFrame *node);
+ FakeFrame *FifoPop();
+ private:
+ FakeFrame *first_, *last_;
+};
+
+class FakeFrameLifo {
+ public:
+ void LifoPush(FakeFrame *node) {
+ node->next = top_;
+ top_ = node;
+ }
+ void LifoPop() {
+ CHECK(top_);
+ top_ = top_->next;
+ }
+ FakeFrame *top() { return top_; }
+ private:
+ FakeFrame *top_;
+};
+
+// For each thread we create a fake stack and place stack objects on this fake
+// stack instead of the real stack. The fake stack is not really a stack but
+// a fast malloc-like allocator so that when a function exits the fake stack
+// is not poped but remains there for quite some time until gets used again.
+// So, we poison the objects on the fake stack when function returns.
+// It helps us find use-after-return bugs.
+// We can not rely on __asan_stack_free being called on every function exit,
+// so we maintain a lifo list of all current fake frames and update it on every
+// call to __asan_stack_malloc.
+class FakeStack {
+ public:
+ FakeStack();
+ explicit FakeStack(LinkerInitialized) {}
+ void Init(uptr stack_size);
+ void StopUsingFakeStack() { alive_ = false; }
+ void Cleanup();
+ uptr AllocateStack(uptr size, uptr real_stack);
+ static void OnFree(uptr ptr, uptr size, uptr real_stack);
+ // Return the bottom of the maped region.
+ uptr AddrIsInFakeStack(uptr addr);
+ bool StackSize() { return stack_size_; }
+
+ private:
+ static const uptr kMinStackFrameSizeLog = 9; // Min frame is 512B.
+ static const uptr kMaxStackFrameSizeLog = 16; // Max stack frame is 64K.
+ static const uptr kMaxStackMallocSize = 1 << kMaxStackFrameSizeLog;
+ static const uptr kNumberOfSizeClasses =
+ kMaxStackFrameSizeLog - kMinStackFrameSizeLog + 1;
+
+ bool AddrIsInSizeClass(uptr addr, uptr size_class);
+
+ // Each size class should be large enough to hold all frames.
+ uptr ClassMmapSize(uptr size_class);
+
+ uptr ClassSize(uptr size_class) {
+ return 1UL << (size_class + kMinStackFrameSizeLog);
+ }
+
+ void DeallocateFrame(FakeFrame *fake_frame);
+
+ uptr ComputeSizeClass(uptr alloc_size);
+ void AllocateOneSizeClass(uptr size_class);
+
+ uptr stack_size_;
+ bool alive_;
+
+ uptr allocated_size_classes_[kNumberOfSizeClasses];
+ FakeFrameFifo size_classes_[kNumberOfSizeClasses];
+ FakeFrameLifo call_stack_;
+};
+
+void *asan_memalign(uptr alignment, uptr size, StackTrace *stack,
+ AllocType alloc_type);
+void asan_free(void *ptr, StackTrace *stack, AllocType alloc_type);
+
+void *asan_malloc(uptr size, StackTrace *stack);
+void *asan_calloc(uptr nmemb, uptr size, StackTrace *stack);
+void *asan_realloc(void *p, uptr size, StackTrace *stack);
+void *asan_valloc(uptr size, StackTrace *stack);
+void *asan_pvalloc(uptr size, StackTrace *stack);
+
+int asan_posix_memalign(void **memptr, uptr alignment, uptr size,
+ StackTrace *stack);
+uptr asan_malloc_usable_size(void *ptr, StackTrace *stack);
+
+uptr asan_mz_size(const void *ptr);
+void asan_mz_force_lock();
+void asan_mz_force_unlock();
+
+void PrintInternalAllocatorStats();
+
+} // namespace __asan
+#endif // ASAN_ALLOCATOR_H
diff --git a/gcc-4.8/libsanitizer/asan/asan_allocator2.cc b/gcc-4.8/libsanitizer/asan/asan_allocator2.cc
new file mode 100644
index 000000000..1ff120e55
--- /dev/null
+++ b/gcc-4.8/libsanitizer/asan/asan_allocator2.cc
@@ -0,0 +1,709 @@
+//===-- asan_allocator2.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.
+//
+// Implementation of ASan's memory allocator, 2-nd version.
+// This variant uses the allocator from sanitizer_common, i.e. the one shared
+// with ThreadSanitizer and MemorySanitizer.
+//
+// Status: under development, not enabled by default yet.
+//===----------------------------------------------------------------------===//
+#include "asan_allocator.h"
+#if ASAN_ALLOCATOR_VERSION == 2
+
+#include "asan_mapping.h"
+#include "asan_report.h"
+#include "asan_thread.h"
+#include "asan_thread_registry.h"
+#include "sanitizer_common/sanitizer_allocator.h"
+#include "sanitizer_common/sanitizer_internal_defs.h"
+#include "sanitizer_common/sanitizer_list.h"
+#include "sanitizer_common/sanitizer_stackdepot.h"
+#include "sanitizer_common/sanitizer_quarantine.h"
+
+namespace __asan {
+
+struct AsanMapUnmapCallback {
+ void OnMap(uptr p, uptr size) const {
+ PoisonShadow(p, size, kAsanHeapLeftRedzoneMagic);
+ // Statistics.
+ AsanStats &thread_stats = asanThreadRegistry().GetCurrentThreadStats();
+ thread_stats.mmaps++;
+ thread_stats.mmaped += size;
+ }
+ void OnUnmap(uptr p, uptr size) const {
+ PoisonShadow(p, size, 0);
+ // We are about to unmap a chunk of user memory.
+ // Mark the corresponding shadow memory as not needed.
+ // Since asan's mapping is compacting, the shadow chunk may be
+ // not page-aligned, so we only flush the page-aligned portion.
+ uptr page_size = GetPageSizeCached();
+ uptr shadow_beg = RoundUpTo(MemToShadow(p), page_size);
+ uptr shadow_end = RoundDownTo(MemToShadow(p + size), page_size);
+ FlushUnneededShadowMemory(shadow_beg, shadow_end - shadow_beg);
+ // Statistics.
+ AsanStats &thread_stats = asanThreadRegistry().GetCurrentThreadStats();
+ thread_stats.munmaps++;
+ thread_stats.munmaped += size;
+ }
+};
+
+#if SANITIZER_WORDSIZE == 64
+#if defined(__powerpc64__)
+const uptr kAllocatorSpace = 0xa0000000000ULL;
+#else
+const uptr kAllocatorSpace = 0x600000000000ULL;
+#endif
+const uptr kAllocatorSize = 0x10000000000ULL; // 1T.
+typedef DefaultSizeClassMap SizeClassMap;
+typedef SizeClassAllocator64<kAllocatorSpace, kAllocatorSize, 0 /*metadata*/,
+ SizeClassMap, AsanMapUnmapCallback> PrimaryAllocator;
+#elif SANITIZER_WORDSIZE == 32
+static const u64 kAddressSpaceSize = 1ULL << 32;
+typedef CompactSizeClassMap SizeClassMap;
+typedef SizeClassAllocator32<0, kAddressSpaceSize, 16,
+ SizeClassMap, AsanMapUnmapCallback> PrimaryAllocator;
+#endif
+
+typedef SizeClassAllocatorLocalCache<PrimaryAllocator> AllocatorCache;
+typedef LargeMmapAllocator<AsanMapUnmapCallback> SecondaryAllocator;
+typedef CombinedAllocator<PrimaryAllocator, AllocatorCache,
+ SecondaryAllocator> Allocator;
+
+// We can not use THREADLOCAL because it is not supported on some of the
+// platforms we care about (OSX 10.6, Android).
+// static THREADLOCAL AllocatorCache cache;
+AllocatorCache *GetAllocatorCache(AsanThreadLocalMallocStorage *ms) {
+ CHECK(ms);
+ CHECK_LE(sizeof(AllocatorCache), sizeof(ms->allocator2_cache));
+ return reinterpret_cast<AllocatorCache *>(ms->allocator2_cache);
+}
+
+static Allocator allocator;
+
+static const uptr kMaxAllowedMallocSize =
+ FIRST_32_SECOND_64(3UL << 30, 8UL << 30);
+
+static const uptr kMaxThreadLocalQuarantine =
+ FIRST_32_SECOND_64(1 << 18, 1 << 20);
+
+// Every chunk of memory allocated by this allocator can be in one of 3 states:
+// CHUNK_AVAILABLE: the chunk is in the free list and ready to be allocated.
+// CHUNK_ALLOCATED: the chunk is allocated and not yet freed.
+// CHUNK_QUARANTINE: the chunk was freed and put into quarantine zone.
+enum {
+ CHUNK_AVAILABLE = 0, // 0 is the default value even if we didn't set it.
+ CHUNK_ALLOCATED = 2,
+ CHUNK_QUARANTINE = 3
+};
+
+// Valid redzone sizes are 16, 32, 64, ... 2048, so we encode them in 3 bits.
+// We use adaptive redzones: for larger allocation larger redzones are used.
+static u32 RZLog2Size(u32 rz_log) {
+ CHECK_LT(rz_log, 8);
+ return 16 << rz_log;
+}
+
+static u32 RZSize2Log(u32 rz_size) {
+ CHECK_GE(rz_size, 16);
+ CHECK_LE(rz_size, 2048);
+ CHECK(IsPowerOfTwo(rz_size));
+ u32 res = Log2(rz_size) - 4;
+ CHECK_EQ(rz_size, RZLog2Size(res));
+ return res;
+}
+
+static uptr ComputeRZLog(uptr user_requested_size) {
+ u32 rz_log =
+ user_requested_size <= 64 - 16 ? 0 :
+ user_requested_size <= 128 - 32 ? 1 :
+ user_requested_size <= 512 - 64 ? 2 :
+ user_requested_size <= 4096 - 128 ? 3 :
+ user_requested_size <= (1 << 14) - 256 ? 4 :
+ user_requested_size <= (1 << 15) - 512 ? 5 :
+ user_requested_size <= (1 << 16) - 1024 ? 6 : 7;
+ return Max(rz_log, RZSize2Log(flags()->redzone));
+}
+
+// The memory chunk allocated from the underlying allocator looks like this:
+// L L L L L L H H U U U U U U R R
+// L -- left redzone words (0 or more bytes)
+// H -- ChunkHeader (16 bytes), which is also a part of the left redzone.
+// U -- user memory.
+// R -- right redzone (0 or more bytes)
+// ChunkBase consists of ChunkHeader and other bytes that overlap with user
+// memory.
+
+// If a memory chunk is allocated by memalign and we had to increase the
+// allocation size to achieve the proper alignment, then we store this magic
+// value in the first uptr word of the memory block and store the address of
+// ChunkBase in the next uptr.
+// M B ? ? ? L L L L L L H H U U U U U U
+// M -- magic value kMemalignMagic
+// B -- address of ChunkHeader pointing to the first 'H'
+static const uptr kMemalignMagic = 0xCC6E96B9;
+
+struct ChunkHeader {
+ // 1-st 8 bytes.
+ u32 chunk_state : 8; // Must be first.
+ u32 alloc_tid : 24;
+
+ u32 free_tid : 24;
+ u32 from_memalign : 1;
+ u32 alloc_type : 2;
+ u32 rz_log : 3;
+ // 2-nd 8 bytes
+ // This field is used for small sizes. For large sizes it is equal to
+ // SizeClassMap::kMaxSize and the actual size is stored in the
+ // SecondaryAllocator's metadata.
+ u32 user_requested_size;
+ u32 alloc_context_id;
+};
+
+struct ChunkBase : ChunkHeader {
+ // Header2, intersects with user memory.
+ AsanChunk *next;
+ u32 free_context_id;
+};
+
+static const uptr kChunkHeaderSize = sizeof(ChunkHeader);
+static const uptr kChunkHeader2Size = sizeof(ChunkBase) - kChunkHeaderSize;
+COMPILER_CHECK(kChunkHeaderSize == 16);
+COMPILER_CHECK(kChunkHeader2Size <= 16);
+
+struct AsanChunk: ChunkBase {
+ uptr Beg() { return reinterpret_cast<uptr>(this) + kChunkHeaderSize; }
+ uptr UsedSize() {
+ if (user_requested_size != SizeClassMap::kMaxSize)
+ return user_requested_size;
+ return *reinterpret_cast<uptr *>(allocator.GetMetaData(AllocBeg()));
+ }
+ void *AllocBeg() {
+ if (from_memalign)
+ return allocator.GetBlockBegin(reinterpret_cast<void *>(this));
+ return reinterpret_cast<void*>(Beg() - RZLog2Size(rz_log));
+ }
+ // We store the alloc/free stack traces in the chunk itself.
+ u32 *AllocStackBeg() {
+ return (u32*)(Beg() - RZLog2Size(rz_log));
+ }
+ uptr AllocStackSize() {
+ CHECK_LE(RZLog2Size(rz_log), kChunkHeaderSize);
+ return (RZLog2Size(rz_log) - kChunkHeaderSize) / sizeof(u32);
+ }
+ u32 *FreeStackBeg() {
+ return (u32*)(Beg() + kChunkHeader2Size);
+ }
+ uptr FreeStackSize() {
+ if (user_requested_size < kChunkHeader2Size) return 0;
+ uptr available = RoundUpTo(user_requested_size, SHADOW_GRANULARITY);
+ return (available - kChunkHeader2Size) / sizeof(u32);
+ }
+};
+
+uptr AsanChunkView::Beg() { return chunk_->Beg(); }
+uptr AsanChunkView::End() { return Beg() + UsedSize(); }
+uptr AsanChunkView::UsedSize() { return chunk_->UsedSize(); }
+uptr AsanChunkView::AllocTid() { return chunk_->alloc_tid; }
+uptr AsanChunkView::FreeTid() { return chunk_->free_tid; }
+
+static void GetStackTraceFromId(u32 id, StackTrace *stack) {
+ CHECK(id);
+ uptr size = 0;
+ const uptr *trace = StackDepotGet(id, &size);
+ CHECK_LT(size, kStackTraceMax);
+ internal_memcpy(stack->trace, trace, sizeof(uptr) * size);
+ stack->size = size;
+}
+
+void AsanChunkView::GetAllocStack(StackTrace *stack) {
+ if (flags()->use_stack_depot)
+ GetStackTraceFromId(chunk_->alloc_context_id, stack);
+ else
+ StackTrace::UncompressStack(stack, chunk_->AllocStackBeg(),
+ chunk_->AllocStackSize());
+}
+
+void AsanChunkView::GetFreeStack(StackTrace *stack) {
+ if (flags()->use_stack_depot)
+ GetStackTraceFromId(chunk_->free_context_id, stack);
+ else
+ StackTrace::UncompressStack(stack, chunk_->FreeStackBeg(),
+ chunk_->FreeStackSize());
+}
+
+struct QuarantineCallback;
+typedef Quarantine<QuarantineCallback, AsanChunk> AsanQuarantine;
+typedef AsanQuarantine::Cache QuarantineCache;
+static AsanQuarantine quarantine(LINKER_INITIALIZED);
+static QuarantineCache fallback_quarantine_cache(LINKER_INITIALIZED);
+static AllocatorCache fallback_allocator_cache;
+static SpinMutex fallback_mutex;
+
+QuarantineCache *GetQuarantineCache(AsanThreadLocalMallocStorage *ms) {
+ CHECK(ms);
+ CHECK_LE(sizeof(QuarantineCache), sizeof(ms->quarantine_cache));
+ return reinterpret_cast<QuarantineCache *>(ms->quarantine_cache);
+}
+
+struct QuarantineCallback {
+ explicit QuarantineCallback(AllocatorCache *cache)
+ : cache_(cache) {
+ }
+
+ void Recycle(AsanChunk *m) {
+ CHECK(m->chunk_state == CHUNK_QUARANTINE);
+ m->chunk_state = CHUNK_AVAILABLE;
+ CHECK_NE(m->alloc_tid, kInvalidTid);
+ CHECK_NE(m->free_tid, kInvalidTid);
+ PoisonShadow(m->Beg(),
+ RoundUpTo(m->UsedSize(), SHADOW_GRANULARITY),
+ kAsanHeapLeftRedzoneMagic);
+ void *p = reinterpret_cast<void *>(m->AllocBeg());
+ if (m->from_memalign) {
+ uptr *memalign_magic = reinterpret_cast<uptr *>(p);
+ CHECK_EQ(memalign_magic[0], kMemalignMagic);
+ CHECK_EQ(memalign_magic[1], reinterpret_cast<uptr>(m));
+ }
+
+ // Statistics.
+ AsanStats &thread_stats = asanThreadRegistry().GetCurrentThreadStats();
+ thread_stats.real_frees++;
+ thread_stats.really_freed += m->UsedSize();
+
+ allocator.Deallocate(cache_, p);
+ }
+
+ void *Allocate(uptr size) {
+ return allocator.Allocate(cache_, size, 1, false);
+ }
+
+ void Deallocate(void *p) {
+ allocator.Deallocate(cache_, p);
+ }
+
+ AllocatorCache *cache_;
+};
+
+void InitializeAllocator() {
+ allocator.Init();
+ quarantine.Init((uptr)flags()->quarantine_size, kMaxThreadLocalQuarantine);
+}
+
+static void *Allocate(uptr size, uptr alignment, StackTrace *stack,
+ AllocType alloc_type) {
+ if (!asan_inited)
+ __asan_init();
+ CHECK(stack);
+ const uptr min_alignment = SHADOW_GRANULARITY;
+ if (alignment < min_alignment)
+ alignment = min_alignment;
+ if (size == 0) {
+ // We'd be happy to avoid allocating memory for zero-size requests, but
+ // some programs/tests depend on this behavior and assume that malloc would
+ // not return NULL even for zero-size allocations. Moreover, it looks like
+ // operator new should never return NULL, and results of consecutive "new"
+ // calls must be different even if the allocated size is zero.
+ size = 1;
+ }
+ CHECK(IsPowerOfTwo(alignment));
+ uptr rz_log = ComputeRZLog(size);
+ uptr rz_size = RZLog2Size(rz_log);
+ uptr rounded_size = RoundUpTo(size, alignment);
+ if (rounded_size < kChunkHeader2Size)
+ rounded_size = kChunkHeader2Size;
+ uptr needed_size = rounded_size + rz_size;
+ if (alignment > min_alignment)
+ needed_size += alignment;
+ bool using_primary_allocator = true;
+ // If we are allocating from the secondary allocator, there will be no
+ // automatic right redzone, so add the right redzone manually.
+ if (!PrimaryAllocator::CanAllocate(needed_size, alignment)) {
+ needed_size += rz_size;
+ using_primary_allocator = false;
+ }
+ CHECK(IsAligned(needed_size, min_alignment));
+ if (size > kMaxAllowedMallocSize || needed_size > kMaxAllowedMallocSize) {
+ Report("WARNING: AddressSanitizer failed to allocate %p bytes\n",
+ (void*)size);
+ return 0;
+ }
+
+ AsanThread *t = asanThreadRegistry().GetCurrent();
+ void *allocated;
+ if (t) {
+ AllocatorCache *cache = GetAllocatorCache(&t->malloc_storage());
+ allocated = allocator.Allocate(cache, needed_size, 8, false);
+ } else {
+ SpinMutexLock l(&fallback_mutex);
+ AllocatorCache *cache = &fallback_allocator_cache;
+ allocated = allocator.Allocate(cache, needed_size, 8, false);
+ }
+ uptr alloc_beg = reinterpret_cast<uptr>(allocated);
+ // Clear the first allocated word (an old kMemalignMagic may still be there).
+ reinterpret_cast<uptr *>(alloc_beg)[0] = 0;
+ uptr alloc_end = alloc_beg + needed_size;
+ uptr beg_plus_redzone = alloc_beg + rz_size;
+ uptr user_beg = beg_plus_redzone;
+ if (!IsAligned(user_beg, alignment))
+ user_beg = RoundUpTo(user_beg, alignment);
+ uptr user_end = user_beg + size;
+ CHECK_LE(user_end, alloc_end);
+ uptr chunk_beg = user_beg - kChunkHeaderSize;
+ AsanChunk *m = reinterpret_cast<AsanChunk *>(chunk_beg);
+ m->chunk_state = CHUNK_ALLOCATED;
+ m->alloc_type = alloc_type;
+ m->rz_log = rz_log;
+ u32 alloc_tid = t ? t->tid() : 0;
+ m->alloc_tid = alloc_tid;
+ CHECK_EQ(alloc_tid, m->alloc_tid); // Does alloc_tid fit into the bitfield?
+ m->free_tid = kInvalidTid;
+ m->from_memalign = user_beg != beg_plus_redzone;
+ if (m->from_memalign) {
+ CHECK_LE(beg_plus_redzone + 2 * sizeof(uptr), user_beg);
+ uptr *memalign_magic = reinterpret_cast<uptr *>(alloc_beg);
+ memalign_magic[0] = kMemalignMagic;
+ memalign_magic[1] = chunk_beg;
+ }
+ if (using_primary_allocator) {
+ CHECK(size);
+ m->user_requested_size = size;
+ CHECK(allocator.FromPrimary(allocated));
+ } else {
+ CHECK(!allocator.FromPrimary(allocated));
+ m->user_requested_size = SizeClassMap::kMaxSize;
+ uptr *meta = reinterpret_cast<uptr *>(allocator.GetMetaData(allocated));
+ meta[0] = size;
+ meta[1] = chunk_beg;
+ }
+
+ if (flags()->use_stack_depot) {
+ m->alloc_context_id = StackDepotPut(stack->trace, stack->size);
+ } else {
+ m->alloc_context_id = 0;
+ StackTrace::CompressStack(stack, m->AllocStackBeg(), m->AllocStackSize());
+ }
+
+ uptr size_rounded_down_to_granularity = RoundDownTo(size, SHADOW_GRANULARITY);
+ // Unpoison the bulk of the memory region.
+ if (size_rounded_down_to_granularity)
+ PoisonShadow(user_beg, size_rounded_down_to_granularity, 0);
+ // Deal with the end of the region if size is not aligned to granularity.
+ if (size != size_rounded_down_to_granularity && flags()->poison_heap) {
+ u8 *shadow = (u8*)MemToShadow(user_beg + size_rounded_down_to_granularity);
+ *shadow = size & (SHADOW_GRANULARITY - 1);
+ }
+
+ AsanStats &thread_stats = asanThreadRegistry().GetCurrentThreadStats();
+ thread_stats.mallocs++;
+ thread_stats.malloced += size;
+ thread_stats.malloced_redzones += needed_size - size;
+ uptr class_id = Min(kNumberOfSizeClasses, SizeClassMap::ClassID(needed_size));
+ thread_stats.malloced_by_size[class_id]++;
+ if (needed_size > SizeClassMap::kMaxSize)
+ thread_stats.malloc_large++;
+
+ void *res = reinterpret_cast<void *>(user_beg);
+ ASAN_MALLOC_HOOK(res, size);
+ return res;
+}
+
+static void Deallocate(void *ptr, StackTrace *stack, AllocType alloc_type) {
+ uptr p = reinterpret_cast<uptr>(ptr);
+ if (p == 0) return;
+ ASAN_FREE_HOOK(ptr);
+ uptr chunk_beg = p - kChunkHeaderSize;
+ AsanChunk *m = reinterpret_cast<AsanChunk *>(chunk_beg);
+
+ // Flip the chunk_state atomically to avoid race on double-free.
+ u8 old_chunk_state = atomic_exchange((atomic_uint8_t*)m, CHUNK_QUARANTINE,
+ memory_order_relaxed);
+
+ if (old_chunk_state == CHUNK_QUARANTINE)
+ ReportDoubleFree((uptr)ptr, stack);
+ else if (old_chunk_state != CHUNK_ALLOCATED)
+ ReportFreeNotMalloced((uptr)ptr, stack);
+ CHECK(old_chunk_state == CHUNK_ALLOCATED);
+ if (m->alloc_type != alloc_type && flags()->alloc_dealloc_mismatch)
+ ReportAllocTypeMismatch((uptr)ptr, stack,
+ (AllocType)m->alloc_type, (AllocType)alloc_type);
+
+ CHECK_GE(m->alloc_tid, 0);
+ if (SANITIZER_WORDSIZE == 64) // On 32-bits this resides in user area.
+ CHECK_EQ(m->free_tid, kInvalidTid);
+ AsanThread *t = asanThreadRegistry().GetCurrent();
+ m->free_tid = t ? t->tid() : 0;
+ if (flags()->use_stack_depot) {
+ m->free_context_id = StackDepotPut(stack->trace, stack->size);
+ } else {
+ m->free_context_id = 0;
+ StackTrace::CompressStack(stack, m->FreeStackBeg(), m->FreeStackSize());
+ }
+ CHECK(m->chunk_state == CHUNK_QUARANTINE);
+ // Poison the region.
+ PoisonShadow(m->Beg(),
+ RoundUpTo(m->UsedSize(), SHADOW_GRANULARITY),
+ kAsanHeapFreeMagic);
+
+ AsanStats &thread_stats = asanThreadRegistry().GetCurrentThreadStats();
+ thread_stats.frees++;
+ thread_stats.freed += m->UsedSize();
+
+ // Push into quarantine.
+ if (t) {
+ AsanThreadLocalMallocStorage *ms = &t->malloc_storage();
+ AllocatorCache *ac = GetAllocatorCache(ms);
+ quarantine.Put(GetQuarantineCache(ms), QuarantineCallback(ac),
+ m, m->UsedSize());
+ } else {
+ SpinMutexLock l(&fallback_mutex);
+ AllocatorCache *ac = &fallback_allocator_cache;
+ quarantine.Put(&fallback_quarantine_cache, QuarantineCallback(ac),
+ m, m->UsedSize());
+ }
+}
+
+static void *Reallocate(void *old_ptr, uptr new_size, StackTrace *stack) {
+ CHECK(old_ptr && new_size);
+ uptr p = reinterpret_cast<uptr>(old_ptr);
+ uptr chunk_beg = p - kChunkHeaderSize;
+ AsanChunk *m = reinterpret_cast<AsanChunk *>(chunk_beg);
+
+ AsanStats &thread_stats = asanThreadRegistry().GetCurrentThreadStats();
+ thread_stats.reallocs++;
+ thread_stats.realloced += new_size;
+
+ CHECK(m->chunk_state == CHUNK_ALLOCATED);
+ uptr old_size = m->UsedSize();
+ uptr memcpy_size = Min(new_size, old_size);
+ void *new_ptr = Allocate(new_size, 8, stack, FROM_MALLOC);
+ if (new_ptr) {
+ CHECK(REAL(memcpy) != 0);
+ REAL(memcpy)(new_ptr, old_ptr, memcpy_size);
+ Deallocate(old_ptr, stack, FROM_MALLOC);
+ }
+ return new_ptr;
+}
+
+static AsanChunk *GetAsanChunkByAddr(uptr p) {
+ void *ptr = reinterpret_cast<void *>(p);
+ uptr alloc_beg = reinterpret_cast<uptr>(allocator.GetBlockBegin(ptr));
+ if (!alloc_beg) return 0;
+ uptr *memalign_magic = reinterpret_cast<uptr *>(alloc_beg);
+ if (memalign_magic[0] == kMemalignMagic) {
+ AsanChunk *m = reinterpret_cast<AsanChunk *>(memalign_magic[1]);
+ CHECK(m->from_memalign);
+ return m;
+ }
+ if (!allocator.FromPrimary(ptr)) {
+ uptr *meta = reinterpret_cast<uptr *>(
+ allocator.GetMetaData(reinterpret_cast<void *>(alloc_beg)));
+ AsanChunk *m = reinterpret_cast<AsanChunk *>(meta[1]);
+ return m;
+ }
+ uptr actual_size = allocator.GetActuallyAllocatedSize(ptr);
+ CHECK_LE(actual_size, SizeClassMap::kMaxSize);
+ // We know the actually allocted size, but we don't know the redzone size.
+ // Just try all possible redzone sizes.
+ for (u32 rz_log = 0; rz_log < 8; rz_log++) {
+ u32 rz_size = RZLog2Size(rz_log);
+ uptr max_possible_size = actual_size - rz_size;
+ if (ComputeRZLog(max_possible_size) != rz_log)
+ continue;
+ return reinterpret_cast<AsanChunk *>(
+ alloc_beg + rz_size - kChunkHeaderSize);
+ }
+ return 0;
+}
+
+static uptr AllocationSize(uptr p) {
+ AsanChunk *m = GetAsanChunkByAddr(p);
+ if (!m) return 0;
+ if (m->chunk_state != CHUNK_ALLOCATED) return 0;
+ if (m->Beg() != p) return 0;
+ return m->UsedSize();
+}
+
+// We have an address between two chunks, and we want to report just one.
+AsanChunk *ChooseChunk(uptr addr,
+ AsanChunk *left_chunk, AsanChunk *right_chunk) {
+ // Prefer an allocated chunk over freed chunk and freed chunk
+ // over available chunk.
+ if (left_chunk->chunk_state != right_chunk->chunk_state) {
+ if (left_chunk->chunk_state == CHUNK_ALLOCATED)
+ return left_chunk;
+ if (right_chunk->chunk_state == CHUNK_ALLOCATED)
+ return right_chunk;
+ if (left_chunk->chunk_state == CHUNK_QUARANTINE)
+ return left_chunk;
+ if (right_chunk->chunk_state == CHUNK_QUARANTINE)
+ return right_chunk;
+ }
+ // Same chunk_state: choose based on offset.
+ sptr l_offset = 0, r_offset = 0;
+ CHECK(AsanChunkView(left_chunk).AddrIsAtRight(addr, 1, &l_offset));
+ CHECK(AsanChunkView(right_chunk).AddrIsAtLeft(addr, 1, &r_offset));
+ if (l_offset < r_offset)
+ return left_chunk;
+ return right_chunk;
+}
+
+AsanChunkView FindHeapChunkByAddress(uptr addr) {
+ AsanChunk *m1 = GetAsanChunkByAddr(addr);
+ if (!m1) return AsanChunkView(m1);
+ sptr offset = 0;
+ if (AsanChunkView(m1).AddrIsAtLeft(addr, 1, &offset)) {
+ // The address is in the chunk's left redzone, so maybe it is actually
+ // a right buffer overflow from the other chunk to the left.
+ // Search a bit to the left to see if there is another chunk.
+ AsanChunk *m2 = 0;
+ for (uptr l = 1; l < GetPageSizeCached(); l++) {
+ m2 = GetAsanChunkByAddr(addr - l);
+ if (m2 == m1) continue; // Still the same chunk.
+ break;
+ }
+ if (m2 && AsanChunkView(m2).AddrIsAtRight(addr, 1, &offset))
+ m1 = ChooseChunk(addr, m2, m1);
+ }
+ return AsanChunkView(m1);
+}
+
+void AsanThreadLocalMallocStorage::CommitBack() {
+ AllocatorCache *ac = GetAllocatorCache(this);
+ quarantine.Drain(GetQuarantineCache(this), QuarantineCallback(ac));
+ allocator.SwallowCache(GetAllocatorCache(this));
+}
+
+void PrintInternalAllocatorStats() {
+ allocator.PrintStats();
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void *asan_memalign(uptr alignment, uptr size, StackTrace *stack,
+ AllocType alloc_type) {
+ return Allocate(size, alignment, stack, alloc_type);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void asan_free(void *ptr, StackTrace *stack, AllocType alloc_type) {
+ Deallocate(ptr, stack, alloc_type);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void *asan_malloc(uptr size, StackTrace *stack) {
+ return Allocate(size, 8, stack, FROM_MALLOC);
+}
+
+void *asan_calloc(uptr nmemb, uptr size, StackTrace *stack) {
+ if (CallocShouldReturnNullDueToOverflow(size, nmemb)) return 0;
+ void *ptr = Allocate(nmemb * size, 8, stack, FROM_MALLOC);
+ if (ptr)
+ REAL(memset)(ptr, 0, nmemb * size);
+ return ptr;
+}
+
+void *asan_realloc(void *p, uptr size, StackTrace *stack) {
+ if (p == 0)
+ return Allocate(size, 8, stack, FROM_MALLOC);
+ if (size == 0) {
+ Deallocate(p, stack, FROM_MALLOC);
+ return 0;
+ }
+ return Reallocate(p, size, stack);
+}
+
+void *asan_valloc(uptr size, StackTrace *stack) {
+ return Allocate(size, GetPageSizeCached(), stack, FROM_MALLOC);
+}
+
+void *asan_pvalloc(uptr size, StackTrace *stack) {
+ uptr PageSize = GetPageSizeCached();
+ size = RoundUpTo(size, PageSize);
+ if (size == 0) {
+ // pvalloc(0) should allocate one page.
+ size = PageSize;
+ }
+ return Allocate(size, PageSize, stack, FROM_MALLOC);
+}
+
+int asan_posix_memalign(void **memptr, uptr alignment, uptr size,
+ StackTrace *stack) {
+ void *ptr = Allocate(size, alignment, stack, FROM_MALLOC);
+ CHECK(IsAligned((uptr)ptr, alignment));
+ *memptr = ptr;
+ return 0;
+}
+
+uptr asan_malloc_usable_size(void *ptr, StackTrace *stack) {
+ CHECK(stack);
+ if (ptr == 0) return 0;
+ uptr usable_size = AllocationSize(reinterpret_cast<uptr>(ptr));
+ if (flags()->check_malloc_usable_size && (usable_size == 0))
+ ReportMallocUsableSizeNotOwned((uptr)ptr, stack);
+ return usable_size;
+}
+
+uptr asan_mz_size(const void *ptr) {
+ return AllocationSize(reinterpret_cast<uptr>(ptr));
+}
+
+void asan_mz_force_lock() {
+ allocator.ForceLock();
+ fallback_mutex.Lock();
+}
+
+void asan_mz_force_unlock() {
+ fallback_mutex.Unlock();
+ allocator.ForceUnlock();
+}
+
+} // namespace __asan
+
+// ---------------------- Interface ---------------- {{{1
+using namespace __asan; // NOLINT
+
+// ASan allocator doesn't reserve extra bytes, so normally we would
+// just return "size". We don't want to expose our redzone sizes, etc here.
+uptr __asan_get_estimated_allocated_size(uptr size) {
+ return size;
+}
+
+bool __asan_get_ownership(const void *p) {
+ uptr ptr = reinterpret_cast<uptr>(p);
+ return (AllocationSize(ptr) > 0);
+}
+
+uptr __asan_get_allocated_size(const void *p) {
+ if (p == 0) return 0;
+ uptr ptr = reinterpret_cast<uptr>(p);
+ uptr allocated_size = AllocationSize(ptr);
+ // Die if p is not malloced or if it is already freed.
+ if (allocated_size == 0) {
+ GET_STACK_TRACE_FATAL_HERE;
+ ReportAsanGetAllocatedSizeNotOwned(ptr, &stack);
+ }
+ return allocated_size;
+}
+
+#if !SANITIZER_SUPPORTS_WEAK_HOOKS
+// Provide default (no-op) implementation of malloc hooks.
+extern "C" {
+SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
+void __asan_malloc_hook(void *ptr, uptr size) {
+ (void)ptr;
+ (void)size;
+}
+SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
+void __asan_free_hook(void *ptr) {
+ (void)ptr;
+}
+} // extern "C"
+#endif
+
+
+#endif // ASAN_ALLOCATOR_VERSION
diff --git a/gcc-4.8/libsanitizer/asan/asan_fake_stack.cc b/gcc-4.8/libsanitizer/asan/asan_fake_stack.cc
new file mode 100644
index 000000000..1fc041575
--- /dev/null
+++ b/gcc-4.8/libsanitizer/asan/asan_fake_stack.cc
@@ -0,0 +1,179 @@
+//===-- asan_fake_stack.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.
+//
+// FakeStack is used to detect use-after-return bugs.
+//===----------------------------------------------------------------------===//
+#include "asan_allocator.h"
+#include "asan_thread.h"
+#include "asan_thread_registry.h"
+
+namespace __asan {
+
+FakeStack::FakeStack() {
+ CHECK(REAL(memset) != 0);
+ REAL(memset)(this, 0, sizeof(*this));
+}
+
+bool FakeStack::AddrIsInSizeClass(uptr addr, uptr size_class) {
+ uptr mem = allocated_size_classes_[size_class];
+ uptr size = ClassMmapSize(size_class);
+ bool res = mem && addr >= mem && addr < mem + size;
+ return res;
+}
+
+uptr FakeStack::AddrIsInFakeStack(uptr addr) {
+ for (uptr i = 0; i < kNumberOfSizeClasses; i++) {
+ if (AddrIsInSizeClass(addr, i)) return allocated_size_classes_[i];
+ }
+ return 0;
+}
+
+// We may want to compute this during compilation.
+inline uptr FakeStack::ComputeSizeClass(uptr alloc_size) {
+ uptr rounded_size = RoundUpToPowerOfTwo(alloc_size);
+ uptr log = Log2(rounded_size);
+ CHECK(alloc_size <= (1UL << log));
+ if (!(alloc_size > (1UL << (log-1)))) {
+ Printf("alloc_size %zu log %zu\n", alloc_size, log);
+ }
+ CHECK(alloc_size > (1UL << (log-1)));
+ uptr res = log < kMinStackFrameSizeLog ? 0 : log - kMinStackFrameSizeLog;
+ CHECK(res < kNumberOfSizeClasses);
+ CHECK(ClassSize(res) >= rounded_size);
+ return res;
+}
+
+void FakeFrameFifo::FifoPush(FakeFrame *node) {
+ CHECK(node);
+ node->next = 0;
+ if (first_ == 0 && last_ == 0) {
+ first_ = last_ = node;
+ } else {
+ CHECK(first_);
+ CHECK(last_);
+ last_->next = node;
+ last_ = node;
+ }
+}
+
+FakeFrame *FakeFrameFifo::FifoPop() {
+ CHECK(first_ && last_ && "Exhausted fake stack");
+ FakeFrame *res = 0;
+ if (first_ == last_) {
+ res = first_;
+ first_ = last_ = 0;
+ } else {
+ res = first_;
+ first_ = first_->next;
+ }
+ return res;
+}
+
+void FakeStack::Init(uptr stack_size) {
+ stack_size_ = stack_size;
+ alive_ = true;
+}
+
+void FakeStack::Cleanup() {
+ alive_ = false;
+ for (uptr i = 0; i < kNumberOfSizeClasses; i++) {
+ uptr mem = allocated_size_classes_[i];
+ if (mem) {
+ PoisonShadow(mem, ClassMmapSize(i), 0);
+ allocated_size_classes_[i] = 0;
+ UnmapOrDie((void*)mem, ClassMmapSize(i));
+ }
+ }
+}
+
+uptr FakeStack::ClassMmapSize(uptr size_class) {
+ return RoundUpToPowerOfTwo(stack_size_);
+}
+
+void FakeStack::AllocateOneSizeClass(uptr size_class) {
+ CHECK(ClassMmapSize(size_class) >= GetPageSizeCached());
+ uptr new_mem = (uptr)MmapOrDie(
+ ClassMmapSize(size_class), __FUNCTION__);
+ // Printf("T%d new_mem[%zu]: %p-%p mmap %zu\n",
+ // asanThreadRegistry().GetCurrent()->tid(),
+ // size_class, new_mem, new_mem + ClassMmapSize(size_class),
+ // ClassMmapSize(size_class));
+ uptr i;
+ for (i = 0; i < ClassMmapSize(size_class);
+ i += ClassSize(size_class)) {
+ size_classes_[size_class].FifoPush((FakeFrame*)(new_mem + i));
+ }
+ CHECK(i == ClassMmapSize(size_class));
+ allocated_size_classes_[size_class] = new_mem;
+}
+
+uptr FakeStack::AllocateStack(uptr size, uptr real_stack) {
+ if (!alive_) return real_stack;
+ CHECK(size <= kMaxStackMallocSize && size > 1);
+ uptr size_class = ComputeSizeClass(size);
+ if (!allocated_size_classes_[size_class]) {
+ AllocateOneSizeClass(size_class);
+ }
+ FakeFrame *fake_frame = size_classes_[size_class].FifoPop();
+ CHECK(fake_frame);
+ fake_frame->size_minus_one = size - 1;
+ fake_frame->real_stack = real_stack;
+ while (FakeFrame *top = call_stack_.top()) {
+ if (top->real_stack > real_stack) break;
+ call_stack_.LifoPop();
+ DeallocateFrame(top);
+ }
+ call_stack_.LifoPush(fake_frame);
+ uptr ptr = (uptr)fake_frame;
+ PoisonShadow(ptr, size, 0);
+ return ptr;
+}
+
+void FakeStack::DeallocateFrame(FakeFrame *fake_frame) {
+ CHECK(alive_);
+ uptr size = fake_frame->size_minus_one + 1;
+ uptr size_class = ComputeSizeClass(size);
+ CHECK(allocated_size_classes_[size_class]);
+ uptr ptr = (uptr)fake_frame;
+ CHECK(AddrIsInSizeClass(ptr, size_class));
+ CHECK(AddrIsInSizeClass(ptr + size - 1, size_class));
+ size_classes_[size_class].FifoPush(fake_frame);
+}
+
+void FakeStack::OnFree(uptr ptr, uptr size, uptr real_stack) {
+ FakeFrame *fake_frame = (FakeFrame*)ptr;
+ CHECK(fake_frame->magic = kRetiredStackFrameMagic);
+ CHECK(fake_frame->descr != 0);
+ CHECK(fake_frame->size_minus_one == size - 1);
+ PoisonShadow(ptr, size, kAsanStackAfterReturnMagic);
+}
+
+} // namespace __asan
+
+// ---------------------- Interface ---------------- {{{1
+using namespace __asan; // NOLINT
+
+uptr __asan_stack_malloc(uptr size, uptr real_stack) {
+ if (!flags()->use_fake_stack) return real_stack;
+ AsanThread *t = asanThreadRegistry().GetCurrent();
+ if (!t) {
+ // TSD is gone, use the real stack.
+ return real_stack;
+ }
+ uptr ptr = t->fake_stack().AllocateStack(size, real_stack);
+ // Printf("__asan_stack_malloc %p %zu %p\n", ptr, size, real_stack);
+ return ptr;
+}
+
+void __asan_stack_free(uptr ptr, uptr size, uptr real_stack) {
+ if (!flags()->use_fake_stack) return;
+ if (ptr != real_stack) {
+ FakeStack::OnFree(ptr, size, real_stack);
+ }
+}
diff --git a/gcc-4.8/libsanitizer/asan/asan_flags.h b/gcc-4.8/libsanitizer/asan/asan_flags.h
new file mode 100644
index 000000000..b880896c7
--- /dev/null
+++ b/gcc-4.8/libsanitizer/asan/asan_flags.h
@@ -0,0 +1,118 @@
+//===-- asan_flags.h -------------------------------------------*- C++ -*-===//
+//
+// 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.
+//
+// ASan runtime flags.
+//===----------------------------------------------------------------------===//
+
+#ifndef ASAN_FLAGS_H
+#define ASAN_FLAGS_H
+
+#include "sanitizer_common/sanitizer_internal_defs.h"
+
+// ASan flag values can be defined in four ways:
+// 1) initialized with default values at startup.
+// 2) overriden during compilation of ASan runtime by providing
+// compile definition ASAN_DEFAULT_OPTIONS.
+// 3) overriden from string returned by user-specified function
+// __asan_default_options().
+// 4) overriden from env variable ASAN_OPTIONS.
+
+namespace __asan {
+
+struct Flags {
+ // Size (in bytes) of quarantine used to detect use-after-free errors.
+ // Lower value may reduce memory usage but increase the chance of
+ // false negatives.
+ int quarantine_size;
+ // If set, uses in-process symbolizer from common sanitizer runtime.
+ bool symbolize;
+ // Verbosity level (0 - silent, 1 - a bit of output, 2+ - more output).
+ int verbosity;
+ // Size (in bytes) of redzones around heap objects.
+ // Requirement: redzone >= 32, is a power of two.
+ int redzone;
+ // If set, prints some debugging information and does additional checks.
+ bool debug;
+ // Controls the way to handle globals (0 - don't detect buffer overflow
+ // on globals, 1 - detect buffer overflow, 2 - print data about registered
+ // globals).
+ int report_globals;
+ // If set, attempts to catch initialization order issues.
+ bool check_initialization_order;
+ // Max number of stack frames kept for each allocation/deallocation.
+ int malloc_context_size;
+ // If set, uses custom wrappers and replacements for libc string functions
+ // to find more errors.
+ bool replace_str;
+ // If set, uses custom wrappers for memset/memcpy/memmove intinsics.
+ bool replace_intrin;
+ // Used on Mac only.
+ bool mac_ignore_invalid_free;
+ // ASan allocator flag. See asan_allocator.cc.
+ bool use_fake_stack;
+ // ASan allocator flag. Sets the maximal size of allocation request
+ // that would return memory filled with zero bytes.
+ int max_malloc_fill_size;
+ // Override exit status if something was reported.
+ int exitcode;
+ // If set, user may manually mark memory regions as poisoned or unpoisoned.
+ bool allow_user_poisoning;
+ // Number of seconds to sleep between printing an error report and
+ // terminating application. Useful for debug purposes (when one needs
+ // to attach gdb, for example).
+ int sleep_before_dying;
+ // If set, registers ASan custom segv handler.
+ bool handle_segv;
+ // If set, uses alternate stack for signal handling.
+ bool use_sigaltstack;
+ // Allow the users to work around the bug in Nvidia drivers prior to 295.*.
+ bool check_malloc_usable_size;
+ // If set, explicitly unmaps (huge) shadow at exit.
+ bool unmap_shadow_on_exit;
+ // If set, calls abort() instead of _exit() after printing an error report.
+ bool abort_on_error;
+ // Print various statistics after printing an error message or if atexit=1.
+ bool print_stats;
+ // Print the legend for the shadow bytes.
+ bool print_legend;
+ // If set, prints ASan exit stats even after program terminates successfully.
+ bool atexit;
+ // By default, disable core dumper on 64-bit - it makes little sense
+ // to dump 16T+ core.
+ bool disable_core;
+ // Allow the tool to re-exec the program. This may interfere badly with the
+ // debugger.
+ bool allow_reexec;
+ // Strips this prefix from file paths in error reports.
+ const char *strip_path_prefix;
+ // If set, prints not only thread creation stacks for threads in error report,
+ // but also thread creation stacks for threads that created those threads,
+ // etc. up to main thread.
+ bool print_full_thread_history;
+ // ASan will write logs to "log_path.pid" instead of stderr.
+ const char *log_path;
+ // Use fast (frame-pointer-based) unwinder on fatal errors (if available).
+ bool fast_unwind_on_fatal;
+ // Use fast (frame-pointer-based) unwinder on malloc/free (if available).
+ bool fast_unwind_on_malloc;
+ // Poison (or not) the heap memory on [de]allocation. Zero value is useful
+ // for benchmarking the allocator or instrumentator.
+ bool poison_heap;
+ // Report errors on malloc/delete, new/free, new/delete[], etc.
+ bool alloc_dealloc_mismatch;
+ // Use stack depot instead of storing stacks in the redzones.
+ bool use_stack_depot;
+};
+
+Flags *flags();
+void InitializeFlags(Flags *f, const char *env);
+
+} // namespace __asan
+
+#endif // ASAN_FLAGS_H
diff --git a/gcc-4.8/libsanitizer/asan/asan_globals.cc b/gcc-4.8/libsanitizer/asan/asan_globals.cc
new file mode 100644
index 000000000..7093c4455
--- /dev/null
+++ b/gcc-4.8/libsanitizer/asan/asan_globals.cc
@@ -0,0 +1,181 @@
+//===-- asan_globals.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.
+//
+// Handle globals.
+//===----------------------------------------------------------------------===//
+#include "asan_interceptors.h"
+#include "asan_internal.h"
+#include "asan_mapping.h"
+#include "asan_report.h"
+#include "asan_stack.h"
+#include "asan_stats.h"
+#include "asan_thread.h"
+#include "sanitizer_common/sanitizer_mutex.h"
+
+namespace __asan {
+
+typedef __asan_global Global;
+
+struct ListOfGlobals {
+ const Global *g;
+ ListOfGlobals *next;
+};
+
+static BlockingMutex mu_for_globals(LINKER_INITIALIZED);
+static LowLevelAllocator allocator_for_globals;
+static ListOfGlobals *list_of_all_globals;
+static ListOfGlobals *list_of_dynamic_init_globals;
+
+void PoisonRedZones(const Global &g) {
+ uptr aligned_size = RoundUpTo(g.size, SHADOW_GRANULARITY);
+ PoisonShadow(g.beg + aligned_size, g.size_with_redzone - aligned_size,
+ kAsanGlobalRedzoneMagic);
+ if (g.size != aligned_size) {
+ // partial right redzone
+ PoisonShadowPartialRightRedzone(
+ g.beg + RoundDownTo(g.size, SHADOW_GRANULARITY),
+ g.size % SHADOW_GRANULARITY,
+ SHADOW_GRANULARITY,
+ kAsanGlobalRedzoneMagic);
+ }
+}
+
+bool DescribeAddressIfGlobal(uptr addr, uptr size) {
+ if (!flags()->report_globals) return false;
+ BlockingMutexLock lock(&mu_for_globals);
+ bool res = false;
+ for (ListOfGlobals *l = list_of_all_globals; l; l = l->next) {
+ const Global &g = *l->g;
+ if (flags()->report_globals >= 2)
+ Report("Search Global: beg=%p size=%zu name=%s\n",
+ (void*)g.beg, g.size, (char*)g.name);
+ res |= DescribeAddressRelativeToGlobal(addr, size, g);
+ }
+ return res;
+}
+
+// Register a global variable.
+// This function may be called more than once for every global
+// so we store the globals in a map.
+static void RegisterGlobal(const Global *g) {
+ CHECK(asan_inited);
+ if (flags()->report_globals >= 2)
+ Report("Added Global: beg=%p size=%zu/%zu name=%s dyn.init=%zu\n",
+ (void*)g->beg, g->size, g->size_with_redzone, g->name,
+ g->has_dynamic_init);
+ CHECK(flags()->report_globals);
+ CHECK(AddrIsInMem(g->beg));
+ CHECK(AddrIsAlignedByGranularity(g->beg));
+ CHECK(AddrIsAlignedByGranularity(g->size_with_redzone));
+ PoisonRedZones(*g);
+ ListOfGlobals *l =
+ (ListOfGlobals*)allocator_for_globals.Allocate(sizeof(ListOfGlobals));
+ l->g = g;
+ l->next = list_of_all_globals;
+ list_of_all_globals = l;
+ if (g->has_dynamic_init) {
+ l = (ListOfGlobals*)allocator_for_globals.Allocate(sizeof(ListOfGlobals));
+ l->g = g;
+ l->next = list_of_dynamic_init_globals;
+ list_of_dynamic_init_globals = l;
+ }
+}
+
+static void UnregisterGlobal(const Global *g) {
+ CHECK(asan_inited);
+ CHECK(flags()->report_globals);
+ CHECK(AddrIsInMem(g->beg));
+ CHECK(AddrIsAlignedByGranularity(g->beg));
+ CHECK(AddrIsAlignedByGranularity(g->size_with_redzone));
+ PoisonShadow(g->beg, g->size_with_redzone, 0);
+ // We unpoison the shadow memory for the global but we do not remove it from
+ // the list because that would require O(n^2) time with the current list
+ // implementation. It might not be worth doing anyway.
+}
+
+// Poison all shadow memory for a single global.
+static void PoisonGlobalAndRedzones(const Global *g) {
+ CHECK(asan_inited);
+ CHECK(flags()->check_initialization_order);
+ CHECK(AddrIsInMem(g->beg));
+ CHECK(AddrIsAlignedByGranularity(g->beg));
+ CHECK(AddrIsAlignedByGranularity(g->size_with_redzone));
+ if (flags()->report_globals >= 3)
+ Printf("DynInitPoison : %s\n", g->name);
+ PoisonShadow(g->beg, g->size_with_redzone, kAsanInitializationOrderMagic);
+}
+
+static void UnpoisonGlobal(const Global *g) {
+ CHECK(asan_inited);
+ CHECK(flags()->check_initialization_order);
+ CHECK(AddrIsInMem(g->beg));
+ CHECK(AddrIsAlignedByGranularity(g->beg));
+ CHECK(AddrIsAlignedByGranularity(g->size_with_redzone));
+ if (flags()->report_globals >= 3)
+ Printf("DynInitUnpoison: %s\n", g->name);
+ PoisonShadow(g->beg, g->size_with_redzone, 0);
+ PoisonRedZones(*g);
+}
+
+} // namespace __asan
+
+// ---------------------- Interface ---------------- {{{1
+using namespace __asan; // NOLINT
+
+// Register an array of globals.
+void __asan_register_globals(__asan_global *globals, uptr n) {
+ if (!flags()->report_globals) return;
+ BlockingMutexLock lock(&mu_for_globals);
+ for (uptr i = 0; i < n; i++) {
+ RegisterGlobal(&globals[i]);
+ }
+}
+
+// Unregister an array of globals.
+// We must do this when a shared objects gets dlclosed.
+void __asan_unregister_globals(__asan_global *globals, uptr n) {
+ if (!flags()->report_globals) return;
+ BlockingMutexLock lock(&mu_for_globals);
+ for (uptr i = 0; i < n; i++) {
+ UnregisterGlobal(&globals[i]);
+ }
+}
+
+// This method runs immediately prior to dynamic initialization in each TU,
+// when all dynamically initialized globals are unpoisoned. This method
+// poisons all global variables not defined in this TU, so that a dynamic
+// initializer can only touch global variables in the same TU.
+void __asan_before_dynamic_init(uptr first_addr, uptr last_addr) {
+ if (!flags()->check_initialization_order) return;
+ CHECK(list_of_dynamic_init_globals);
+ BlockingMutexLock lock(&mu_for_globals);
+ bool from_current_tu = false;
+ // The list looks like:
+ // a => ... => b => last_addr => ... => first_addr => c => ...
+ // The globals of the current TU reside between last_addr and first_addr.
+ for (ListOfGlobals *l = list_of_dynamic_init_globals; l; l = l->next) {
+ if (l->g->beg == last_addr)
+ from_current_tu = true;
+ if (!from_current_tu)
+ PoisonGlobalAndRedzones(l->g);
+ if (l->g->beg == first_addr)
+ from_current_tu = false;
+ }
+ CHECK(!from_current_tu);
+}
+
+// This method runs immediately after dynamic initialization in each TU, when
+// all dynamically initialized globals except for those defined in the current
+// TU are poisoned. It simply unpoisons all dynamically initialized globals.
+void __asan_after_dynamic_init() {
+ if (!flags()->check_initialization_order) return;
+ BlockingMutexLock lock(&mu_for_globals);
+ for (ListOfGlobals *l = list_of_dynamic_init_globals; l; l = l->next)
+ UnpoisonGlobal(l->g);
+}
diff --git a/gcc-4.8/libsanitizer/asan/asan_intercepted_functions.h b/gcc-4.8/libsanitizer/asan/asan_intercepted_functions.h
new file mode 100644
index 000000000..ed75c4284
--- /dev/null
+++ b/gcc-4.8/libsanitizer/asan/asan_intercepted_functions.h
@@ -0,0 +1,324 @@
+//===-- asan_intercepted_functions.h ----------------------------*- C++ -*-===//
+//
+// 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.
+//
+// ASan-private header containing prototypes for wrapper functions and wrappers
+//===----------------------------------------------------------------------===//
+#ifndef ASAN_INTERCEPTED_FUNCTIONS_H
+#define ASAN_INTERCEPTED_FUNCTIONS_H
+
+#include "asan_internal.h"
+#include "interception/interception.h"
+#include "sanitizer_common/sanitizer_platform_interceptors.h"
+
+#include <stdarg.h>
+#include <stddef.h>
+
+using __sanitizer::uptr;
+
+// Use macro to describe if specific function should be
+// intercepted on a given platform.
+#if !defined(_WIN32)
+# define ASAN_INTERCEPT_ATOLL_AND_STRTOLL 1
+# define ASAN_INTERCEPT__LONGJMP 1
+# define ASAN_INTERCEPT_STRDUP 1
+# define ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP 1
+# define ASAN_INTERCEPT_INDEX 1
+# define ASAN_INTERCEPT_PTHREAD_CREATE 1
+# define ASAN_INTERCEPT_MLOCKX 1
+#else
+# define ASAN_INTERCEPT_ATOLL_AND_STRTOLL 0
+# define ASAN_INTERCEPT__LONGJMP 0
+# define ASAN_INTERCEPT_STRDUP 0
+# define ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP 0
+# define ASAN_INTERCEPT_INDEX 0
+# define ASAN_INTERCEPT_PTHREAD_CREATE 0
+# define ASAN_INTERCEPT_MLOCKX 0
+#endif
+
+#if defined(__linux__)
+# define ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX 1
+#else
+# define ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX 0
+#endif
+
+#if !defined(__APPLE__)
+# define ASAN_INTERCEPT_STRNLEN 1
+#else
+# define ASAN_INTERCEPT_STRNLEN 0
+#endif
+
+#if defined(__linux__) && !defined(ANDROID)
+# define ASAN_INTERCEPT_SWAPCONTEXT 1
+#else
+# define ASAN_INTERCEPT_SWAPCONTEXT 0
+#endif
+
+#if !defined(ANDROID) && !defined(_WIN32)
+# define ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 1
+#else
+# define ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 0
+#endif
+
+#if !defined(_WIN32)
+# define ASAN_INTERCEPT_SIGLONGJMP 1
+#else
+# define ASAN_INTERCEPT_SIGLONGJMP 0
+#endif
+
+#if ASAN_HAS_EXCEPTIONS && !defined(_WIN32)
+# define ASAN_INTERCEPT___CXA_THROW 1
+#else
+# define ASAN_INTERCEPT___CXA_THROW 0
+#endif
+
+#define INTERPOSE_FUNCTION(function) \
+ { reinterpret_cast<const uptr>(WRAP(function)), \
+ reinterpret_cast<const uptr>(function) }
+
+#define INTERPOSE_FUNCTION_2(function, wrapper) \
+ { reinterpret_cast<const uptr>(wrapper), \
+ reinterpret_cast<const uptr>(function) }
+
+struct interpose_substitution {
+ const uptr replacement;
+ const uptr original;
+};
+
+#define INTERPOSER(func) __attribute__((used)) \
+const interpose_substitution substitution_##func[] \
+ __attribute__((section("__DATA, __interpose"))) = { \
+ INTERPOSE_FUNCTION(func), \
+}
+
+#define INTERPOSER_2(func, wrapper) __attribute__((used)) \
+const interpose_substitution substitution_##func[] \
+ __attribute__((section("__DATA, __interpose"))) = { \
+ INTERPOSE_FUNCTION_2(func, wrapper), \
+}
+
+
+#define DECLARE_FUNCTION_AND_WRAPPER(ret_type, func, ...) \
+ ret_type func(__VA_ARGS__); \
+ ret_type WRAP(func)(__VA_ARGS__); \
+ INTERPOSER(func)
+
+// Use extern declarations of intercepted functions on Mac and Windows
+// to avoid including system headers.
+#if defined(__APPLE__) || (defined(_WIN32) && !defined(_DLL))
+extern "C" {
+// signal.h
+# if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
+struct sigaction;
+DECLARE_FUNCTION_AND_WRAPPER(int, sigaction, int sig,
+ const struct sigaction *act,
+ struct sigaction *oldact);
+DECLARE_FUNCTION_AND_WRAPPER(void*, signal, int signum, void *handler);
+# endif
+
+// setjmp.h
+DECLARE_FUNCTION_AND_WRAPPER(void, longjmp, void *env, int value);
+# if ASAN_INTERCEPT__LONGJMP
+DECLARE_FUNCTION_AND_WRAPPER(void, _longjmp, void *env, int value);
+# endif
+# if ASAN_INTERCEPT_SIGLONGJMP
+DECLARE_FUNCTION_AND_WRAPPER(void, siglongjmp, void *env, int value);
+# endif
+# if ASAN_INTERCEPT___CXA_THROW
+DECLARE_FUNCTION_AND_WRAPPER(void, __cxa_throw, void *a, void *b, void *c);
+# endif
+
+// string.h / strings.h
+DECLARE_FUNCTION_AND_WRAPPER(int, memcmp,
+ const void *a1, const void *a2, uptr size);
+DECLARE_FUNCTION_AND_WRAPPER(void*, memmove,
+ void *to, const void *from, uptr size);
+DECLARE_FUNCTION_AND_WRAPPER(void*, memcpy,
+ void *to, const void *from, uptr size);
+DECLARE_FUNCTION_AND_WRAPPER(void*, memset, void *block, int c, uptr size);
+DECLARE_FUNCTION_AND_WRAPPER(char*, strchr, const char *str, int c);
+DECLARE_FUNCTION_AND_WRAPPER(char*, strcat, /* NOLINT */
+ char *to, const char* from);
+DECLARE_FUNCTION_AND_WRAPPER(char*, strncat,
+ char *to, const char* from, uptr size);
+DECLARE_FUNCTION_AND_WRAPPER(char*, strcpy, /* NOLINT */
+ char *to, const char* from);
+DECLARE_FUNCTION_AND_WRAPPER(char*, strncpy,
+ char *to, const char* from, uptr size);
+DECLARE_FUNCTION_AND_WRAPPER(int, strcmp, const char *s1, const char* s2);
+DECLARE_FUNCTION_AND_WRAPPER(int, strncmp,
+ const char *s1, const char* s2, uptr size);
+DECLARE_FUNCTION_AND_WRAPPER(uptr, strlen, const char *s);
+# if ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP
+DECLARE_FUNCTION_AND_WRAPPER(int, strcasecmp, const char *s1, const char *s2);
+DECLARE_FUNCTION_AND_WRAPPER(int, strncasecmp,
+ const char *s1, const char *s2, uptr n);
+# endif
+# if ASAN_INTERCEPT_STRDUP
+DECLARE_FUNCTION_AND_WRAPPER(char*, strdup, const char *s);
+# endif
+# if ASAN_INTERCEPT_STRNLEN
+DECLARE_FUNCTION_AND_WRAPPER(uptr, strnlen, const char *s, uptr maxlen);
+# endif
+# if ASAN_INTERCEPT_INDEX
+char* index(const char *string, int c);
+INTERPOSER_2(index, WRAP(strchr));
+# endif
+
+// stdlib.h
+DECLARE_FUNCTION_AND_WRAPPER(int, atoi, const char *nptr);
+DECLARE_FUNCTION_AND_WRAPPER(long, atol, const char *nptr); // NOLINT
+DECLARE_FUNCTION_AND_WRAPPER(long, strtol, const char *nptr, char **endptr, int base); // NOLINT
+# if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
+DECLARE_FUNCTION_AND_WRAPPER(long long, atoll, const char *nptr); // NOLINT
+DECLARE_FUNCTION_AND_WRAPPER(long long, strtoll, const char *nptr, char **endptr, int base); // NOLINT
+# endif
+
+// unistd.h
+# if SANITIZER_INTERCEPT_READ
+DECLARE_FUNCTION_AND_WRAPPER(SSIZE_T, read, int fd, void *buf, SIZE_T count);
+# endif
+# if SANITIZER_INTERCEPT_PREAD
+DECLARE_FUNCTION_AND_WRAPPER(SSIZE_T, pread, int fd, void *buf,
+ SIZE_T count, OFF_T offset);
+# endif
+# if SANITIZER_INTERCEPT_PREAD64
+DECLARE_FUNCTION_AND_WRAPPER(SSIZE_T, pread64, int fd, void *buf,
+ SIZE_T count, OFF64_T offset);
+# endif
+
+# if SANITIZER_INTERCEPT_WRITE
+DECLARE_FUNCTION_AND_WRAPPER(SSIZE_T, write, int fd, void *ptr, SIZE_T count);
+# endif
+# if SANITIZER_INTERCEPT_PWRITE
+DECLARE_FUNCTION_AND_WRAPPER(SSIZE_T, pwrite,
+ int fd, void *ptr, SIZE_T count, OFF_T offset);
+# endif
+
+# if ASAN_INTERCEPT_MLOCKX
+// mlock/munlock
+DECLARE_FUNCTION_AND_WRAPPER(int, mlock, const void *addr, SIZE_T len);
+DECLARE_FUNCTION_AND_WRAPPER(int, munlock, const void *addr, SIZE_T len);
+DECLARE_FUNCTION_AND_WRAPPER(int, mlockall, int flags);
+DECLARE_FUNCTION_AND_WRAPPER(int, munlockall, void);
+# endif
+
+// Windows threads.
+# if defined(_WIN32)
+__declspec(dllimport)
+void* __stdcall CreateThread(void *sec, uptr st, void* start,
+ void *arg, DWORD fl, DWORD *id);
+# endif
+// Posix threads.
+# if ASAN_INTERCEPT_PTHREAD_CREATE
+DECLARE_FUNCTION_AND_WRAPPER(int, pthread_create,
+ void *thread, void *attr,
+ void *(*start_routine)(void*), void *arg);
+# endif
+
+# if SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS
+DECLARE_FUNCTION_AND_WRAPPER(void *, localtime, unsigned long *timep);
+DECLARE_FUNCTION_AND_WRAPPER(void *, localtime_r, unsigned long *timep,
+ void *result);
+DECLARE_FUNCTION_AND_WRAPPER(void *, gmtime, unsigned long *timep);
+DECLARE_FUNCTION_AND_WRAPPER(void *, gmtime_r, unsigned long *timep,
+ void *result);
+DECLARE_FUNCTION_AND_WRAPPER(char *, ctime, unsigned long *timep);
+DECLARE_FUNCTION_AND_WRAPPER(char *, ctime_r, unsigned long *timep,
+ char *result);
+DECLARE_FUNCTION_AND_WRAPPER(char *, asctime, void *tm);
+DECLARE_FUNCTION_AND_WRAPPER(char *, asctime_r, void *tm, char *result);
+# endif
+
+// stdio.h
+# if SANITIZER_INTERCEPT_SCANF
+DECLARE_FUNCTION_AND_WRAPPER(int, vscanf, const char *format, va_list ap);
+DECLARE_FUNCTION_AND_WRAPPER(int, vsscanf, const char *str, const char *format,
+ va_list ap);
+DECLARE_FUNCTION_AND_WRAPPER(int, vfscanf, void *stream, const char *format,
+ va_list ap);
+DECLARE_FUNCTION_AND_WRAPPER(int, scanf, const char *format, ...);
+DECLARE_FUNCTION_AND_WRAPPER(int, fscanf,
+ void* stream, const char *format, ...);
+DECLARE_FUNCTION_AND_WRAPPER(int, sscanf, // NOLINT
+ const char *str, const char *format, ...);
+# endif
+
+# if defined(__APPLE__)
+typedef void* pthread_workqueue_t;
+typedef void* pthread_workitem_handle_t;
+
+typedef void* dispatch_group_t;
+typedef void* dispatch_queue_t;
+typedef void* dispatch_source_t;
+typedef u64 dispatch_time_t;
+typedef void (*dispatch_function_t)(void *block);
+typedef void* (*worker_t)(void *block);
+
+DECLARE_FUNCTION_AND_WRAPPER(void, dispatch_async_f,
+ dispatch_queue_t dq,
+ void *ctxt, dispatch_function_t func);
+DECLARE_FUNCTION_AND_WRAPPER(void, dispatch_sync_f,
+ dispatch_queue_t dq,
+ void *ctxt, dispatch_function_t func);
+DECLARE_FUNCTION_AND_WRAPPER(void, dispatch_after_f,
+ dispatch_time_t when, dispatch_queue_t dq,
+ void *ctxt, dispatch_function_t func);
+DECLARE_FUNCTION_AND_WRAPPER(void, dispatch_barrier_async_f,
+ dispatch_queue_t dq,
+ void *ctxt, dispatch_function_t func);
+DECLARE_FUNCTION_AND_WRAPPER(void, dispatch_group_async_f,
+ dispatch_group_t group, dispatch_queue_t dq,
+ void *ctxt, dispatch_function_t func);
+
+# if !defined(MISSING_BLOCKS_SUPPORT)
+DECLARE_FUNCTION_AND_WRAPPER(void, dispatch_group_async,
+ dispatch_group_t dg,
+ dispatch_queue_t dq, void (^work)(void));
+DECLARE_FUNCTION_AND_WRAPPER(void, dispatch_async,
+ dispatch_queue_t dq, void (^work)(void));
+DECLARE_FUNCTION_AND_WRAPPER(void, dispatch_after,
+ dispatch_queue_t dq, void (^work)(void));
+DECLARE_FUNCTION_AND_WRAPPER(void, dispatch_source_set_event_handler,
+ dispatch_source_t ds, void (^work)(void));
+DECLARE_FUNCTION_AND_WRAPPER(void, dispatch_source_set_cancel_handler,
+ dispatch_source_t ds, void (^work)(void));
+# endif // MISSING_BLOCKS_SUPPORT
+
+typedef void malloc_zone_t;
+typedef size_t vm_size_t;
+DECLARE_FUNCTION_AND_WRAPPER(malloc_zone_t *, malloc_create_zone,
+ vm_size_t start_size, unsigned flags);
+DECLARE_FUNCTION_AND_WRAPPER(malloc_zone_t *, malloc_default_zone, void);
+DECLARE_FUNCTION_AND_WRAPPER(
+ malloc_zone_t *, malloc_default_purgeable_zone, void);
+DECLARE_FUNCTION_AND_WRAPPER(void, malloc_make_purgeable, void *ptr);
+DECLARE_FUNCTION_AND_WRAPPER(int, malloc_make_nonpurgeable, void *ptr);
+DECLARE_FUNCTION_AND_WRAPPER(void, malloc_set_zone_name,
+ malloc_zone_t *zone, const char *name);
+DECLARE_FUNCTION_AND_WRAPPER(void *, malloc, size_t size);
+DECLARE_FUNCTION_AND_WRAPPER(void, free, void *ptr);
+DECLARE_FUNCTION_AND_WRAPPER(void *, realloc, void *ptr, size_t size);
+DECLARE_FUNCTION_AND_WRAPPER(void *, calloc, size_t nmemb, size_t size);
+DECLARE_FUNCTION_AND_WRAPPER(void *, valloc, size_t size);
+DECLARE_FUNCTION_AND_WRAPPER(size_t, malloc_good_size, size_t size);
+DECLARE_FUNCTION_AND_WRAPPER(int, posix_memalign,
+ void **memptr, size_t alignment, size_t size);
+#if 0
+DECLARE_FUNCTION_AND_WRAPPER(void, _malloc_fork_prepare, void);
+DECLARE_FUNCTION_AND_WRAPPER(void, _malloc_fork_parent, void);
+DECLARE_FUNCTION_AND_WRAPPER(void, _malloc_fork_child, void);
+#endif
+
+
+
+# endif // __APPLE__
+} // extern "C"
+#endif // defined(__APPLE__) || (defined(_WIN32) && !defined(_DLL))
+
+#endif // ASAN_INTERCEPTED_FUNCTIONS_H
diff --git a/gcc-4.8/libsanitizer/asan/asan_interceptors.cc b/gcc-4.8/libsanitizer/asan/asan_interceptors.cc
new file mode 100644
index 000000000..064fc6261
--- /dev/null
+++ b/gcc-4.8/libsanitizer/asan/asan_interceptors.cc
@@ -0,0 +1,755 @@
+//===-- asan_interceptors.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.
+//
+// Intercept various libc functions.
+//===----------------------------------------------------------------------===//
+#include "asan_interceptors.h"
+
+#include "asan_allocator.h"
+#include "asan_intercepted_functions.h"
+#include "asan_internal.h"
+#include "asan_mapping.h"
+#include "asan_report.h"
+#include "asan_stack.h"
+#include "asan_stats.h"
+#include "asan_thread_registry.h"
+#include "interception/interception.h"
+#include "sanitizer_common/sanitizer_libc.h"
+
+namespace __asan {
+
+// Return true if we can quickly decide that the region is unpoisoned.
+static inline bool QuickCheckForUnpoisonedRegion(uptr beg, uptr size) {
+ if (size == 0) return true;
+ if (size <= 32)
+ return !AddressIsPoisoned(beg) &&
+ !AddressIsPoisoned(beg + size - 1) &&
+ !AddressIsPoisoned(beg + size / 2);
+ return false;
+}
+
+// We implement ACCESS_MEMORY_RANGE, ASAN_READ_RANGE,
+// and ASAN_WRITE_RANGE as macro instead of function so
+// that no extra frames are created, and stack trace contains
+// relevant information only.
+// We check all shadow bytes.
+#define ACCESS_MEMORY_RANGE(offset, size, isWrite) do { \
+ uptr __offset = (uptr)(offset); \
+ uptr __size = (uptr)(size); \
+ if (!QuickCheckForUnpoisonedRegion(__offset, __size) && \
+ __asan_region_is_poisoned(__offset, __size)) { \
+ GET_CURRENT_PC_BP_SP; \
+ __asan_report_error(pc, bp, sp, __offset, isWrite, __size); \
+ } \
+ } while (0)
+
+#define ASAN_READ_RANGE(offset, size) ACCESS_MEMORY_RANGE(offset, size, false)
+#define ASAN_WRITE_RANGE(offset, size) ACCESS_MEMORY_RANGE(offset, size, true);
+
+// Behavior of functions like "memcpy" or "strcpy" is undefined
+// if memory intervals overlap. We report error in this case.
+// Macro is used to avoid creation of new frames.
+static inline bool RangesOverlap(const char *offset1, uptr length1,
+ const char *offset2, uptr length2) {
+ return !((offset1 + length1 <= offset2) || (offset2 + length2 <= offset1));
+}
+#define CHECK_RANGES_OVERLAP(name, _offset1, length1, _offset2, length2) do { \
+ const char *offset1 = (const char*)_offset1; \
+ const char *offset2 = (const char*)_offset2; \
+ if (RangesOverlap(offset1, length1, offset2, length2)) { \
+ GET_STACK_TRACE_FATAL_HERE; \
+ ReportStringFunctionMemoryRangesOverlap(name, offset1, length1, \
+ offset2, length2, &stack); \
+ } \
+} while (0)
+
+#define ENSURE_ASAN_INITED() do { \
+ CHECK(!asan_init_is_running); \
+ if (!asan_inited) { \
+ __asan_init(); \
+ } \
+} while (0)
+
+static inline uptr MaybeRealStrnlen(const char *s, uptr maxlen) {
+#if ASAN_INTERCEPT_STRNLEN
+ if (REAL(strnlen) != 0) {
+ return REAL(strnlen)(s, maxlen);
+ }
+#endif
+ return internal_strnlen(s, maxlen);
+}
+
+void SetThreadName(const char *name) {
+ AsanThread *t = asanThreadRegistry().GetCurrent();
+ if (t)
+ t->summary()->set_name(name);
+}
+
+} // namespace __asan
+
+// ---------------------- Wrappers ---------------- {{{1
+using namespace __asan; // NOLINT
+
+#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
+ ASAN_WRITE_RANGE(ptr, size)
+#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) ASAN_READ_RANGE(ptr, size)
+#define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \
+ do { \
+ ctx = 0; \
+ (void)ctx; \
+ ENSURE_ASAN_INITED(); \
+ } while (false)
+#define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) do { } while (false)
+#define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) do { } while (false)
+#define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) SetThreadName(name)
+#include "sanitizer_common/sanitizer_common_interceptors.inc"
+
+static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) {
+ AsanThread *t = (AsanThread*)arg;
+ asanThreadRegistry().SetCurrent(t);
+ return t->ThreadStart();
+}
+
+#if ASAN_INTERCEPT_PTHREAD_CREATE
+INTERCEPTOR(int, pthread_create, void *thread,
+ void *attr, void *(*start_routine)(void*), void *arg) {
+ GET_STACK_TRACE_THREAD;
+ u32 current_tid = asanThreadRegistry().GetCurrentTidOrInvalid();
+ AsanThread *t = AsanThread::Create(current_tid, start_routine, arg, &stack);
+ asanThreadRegistry().RegisterThread(t);
+ return REAL(pthread_create)(thread, attr, asan_thread_start, t);
+}
+#endif // ASAN_INTERCEPT_PTHREAD_CREATE
+
+#if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
+INTERCEPTOR(void*, signal, int signum, void *handler) {
+ if (!AsanInterceptsSignal(signum)) {
+ return REAL(signal)(signum, handler);
+ }
+ return 0;
+}
+
+INTERCEPTOR(int, sigaction, int signum, const struct sigaction *act,
+ struct sigaction *oldact) {
+ if (!AsanInterceptsSignal(signum)) {
+ return REAL(sigaction)(signum, act, oldact);
+ }
+ return 0;
+}
+#elif ASAN_POSIX
+// We need to have defined REAL(sigaction) on posix systems.
+DEFINE_REAL(int, sigaction, int signum, const struct sigaction *act,
+ struct sigaction *oldact);
+#endif // ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
+
+#if ASAN_INTERCEPT_SWAPCONTEXT
+static void ClearShadowMemoryForContextStack(uptr stack, uptr ssize) {
+ // Align to page size.
+ uptr PageSize = GetPageSizeCached();
+ uptr bottom = stack & ~(PageSize - 1);
+ ssize += stack - bottom;
+ ssize = RoundUpTo(ssize, PageSize);
+ static const uptr kMaxSaneContextStackSize = 1 << 22; // 4 Mb
+ if (ssize && ssize <= kMaxSaneContextStackSize) {
+ PoisonShadow(bottom, ssize, 0);
+ }
+}
+
+INTERCEPTOR(int, swapcontext, struct ucontext_t *oucp,
+ struct ucontext_t *ucp) {
+ static bool reported_warning = false;
+ if (!reported_warning) {
+ Report("WARNING: ASan doesn't fully support makecontext/swapcontext "
+ "functions and may produce false positives in some cases!\n");
+ reported_warning = true;
+ }
+ // Clear shadow memory for new context (it may share stack
+ // with current context).
+ uptr stack, ssize;
+ ReadContextStack(ucp, &stack, &ssize);
+ ClearShadowMemoryForContextStack(stack, ssize);
+ int res = REAL(swapcontext)(oucp, ucp);
+ // swapcontext technically does not return, but program may swap context to
+ // "oucp" later, that would look as if swapcontext() returned 0.
+ // We need to clear shadow for ucp once again, as it may be in arbitrary
+ // state.
+ ClearShadowMemoryForContextStack(stack, ssize);
+ return res;
+}
+#endif // ASAN_INTERCEPT_SWAPCONTEXT
+
+INTERCEPTOR(void, longjmp, void *env, int val) {
+ __asan_handle_no_return();
+ REAL(longjmp)(env, val);
+}
+
+#if ASAN_INTERCEPT__LONGJMP
+INTERCEPTOR(void, _longjmp, void *env, int val) {
+ __asan_handle_no_return();
+ REAL(_longjmp)(env, val);
+}
+#endif
+
+#if ASAN_INTERCEPT_SIGLONGJMP
+INTERCEPTOR(void, siglongjmp, void *env, int val) {
+ __asan_handle_no_return();
+ REAL(siglongjmp)(env, val);
+}
+#endif
+
+#if ASAN_INTERCEPT___CXA_THROW
+INTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) {
+ CHECK(REAL(__cxa_throw));
+ __asan_handle_no_return();
+ REAL(__cxa_throw)(a, b, c);
+}
+#endif
+
+// intercept mlock and friends.
+// Since asan maps 16T of RAM, mlock is completely unfriendly to asan.
+// All functions return 0 (success).
+static void MlockIsUnsupported() {
+ static bool printed = 0;
+ if (printed) return;
+ printed = true;
+ Printf("INFO: AddressSanitizer ignores mlock/mlockall/munlock/munlockall\n");
+}
+
+extern "C" {
+INTERCEPTOR(int, mlock, const void *addr, uptr len) {
+ MlockIsUnsupported();
+ return 0;
+}
+
+INTERCEPTOR(int, munlock, const void *addr, uptr len) {
+ MlockIsUnsupported();
+ return 0;
+}
+
+INTERCEPTOR(int, mlockall, int flags) {
+ MlockIsUnsupported();
+ return 0;
+}
+
+INTERCEPTOR(int, munlockall, void) {
+ MlockIsUnsupported();
+ return 0;
+}
+} // extern "C"
+
+static inline int CharCmp(unsigned char c1, unsigned char c2) {
+ return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1;
+}
+
+static inline int CharCaseCmp(unsigned char c1, unsigned char c2) {
+ int c1_low = ToLower(c1);
+ int c2_low = ToLower(c2);
+ return c1_low - c2_low;
+}
+
+INTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) {
+ if (!asan_inited) return internal_memcmp(a1, a2, size);
+ ENSURE_ASAN_INITED();
+ unsigned char c1 = 0, c2 = 0;
+ const unsigned char *s1 = (const unsigned char*)a1;
+ const unsigned char *s2 = (const unsigned char*)a2;
+ uptr i;
+ for (i = 0; i < size; i++) {
+ c1 = s1[i];
+ c2 = s2[i];
+ if (c1 != c2) break;
+ }
+ ASAN_READ_RANGE(s1, Min(i + 1, size));
+ ASAN_READ_RANGE(s2, Min(i + 1, size));
+ return CharCmp(c1, c2);
+}
+
+INTERCEPTOR(void*, memcpy, void *to, const void *from, uptr size) {
+ if (!asan_inited) return internal_memcpy(to, from, size);
+ // memcpy is called during __asan_init() from the internals
+ // of printf(...).
+ if (asan_init_is_running) {
+ return REAL(memcpy)(to, from, size);
+ }
+ ENSURE_ASAN_INITED();
+ if (flags()->replace_intrin) {
+ if (to != from) {
+ // We do not treat memcpy with to==from as a bug.
+ // See http://llvm.org/bugs/show_bug.cgi?id=11763.
+ CHECK_RANGES_OVERLAP("memcpy", to, size, from, size);
+ }
+ ASAN_READ_RANGE(from, size);
+ ASAN_WRITE_RANGE(to, size);
+ }
+ // Interposing of resolver functions is broken on Mac OS 10.7 and 10.8.
+ // See also http://code.google.com/p/address-sanitizer/issues/detail?id=116.
+ return internal_memcpy(to, from, size);
+}
+
+INTERCEPTOR(void*, memmove, void *to, const void *from, uptr size) {
+ if (!asan_inited) return internal_memmove(to, from, size);
+ if (asan_init_is_running) {
+ return REAL(memmove)(to, from, size);
+ }
+ ENSURE_ASAN_INITED();
+ if (flags()->replace_intrin) {
+ ASAN_READ_RANGE(from, size);
+ ASAN_WRITE_RANGE(to, size);
+ }
+ // Interposing of resolver functions is broken on Mac OS 10.7 and 10.8.
+ // See also http://code.google.com/p/address-sanitizer/issues/detail?id=116.
+ return internal_memmove(to, from, size);
+}
+
+INTERCEPTOR(void*, memset, void *block, int c, uptr size) {
+ if (!asan_inited) return internal_memset(block, c, size);
+ // memset is called inside Printf.
+ if (asan_init_is_running) {
+ return REAL(memset)(block, c, size);
+ }
+ ENSURE_ASAN_INITED();
+ if (flags()->replace_intrin) {
+ ASAN_WRITE_RANGE(block, size);
+ }
+ return REAL(memset)(block, c, size);
+}
+
+INTERCEPTOR(char*, strchr, const char *str, int c) {
+ if (!asan_inited) return internal_strchr(str, c);
+ // strchr is called inside create_purgeable_zone() when MallocGuardEdges=1 is
+ // used.
+ if (asan_init_is_running) {
+ return REAL(strchr)(str, c);
+ }
+ ENSURE_ASAN_INITED();
+ char *result = REAL(strchr)(str, c);
+ if (flags()->replace_str) {
+ uptr bytes_read = (result ? result - str : REAL(strlen)(str)) + 1;
+ ASAN_READ_RANGE(str, bytes_read);
+ }
+ return result;
+}
+
+#if ASAN_INTERCEPT_INDEX
+# if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
+INTERCEPTOR(char*, index, const char *string, int c)
+ ALIAS(WRAPPER_NAME(strchr));
+# else
+DEFINE_REAL(char*, index, const char *string, int c)
+# endif
+#endif // ASAN_INTERCEPT_INDEX
+
+// For both strcat() and strncat() we need to check the validity of |to|
+// argument irrespective of the |from| length.
+INTERCEPTOR(char*, strcat, char *to, const char *from) { // NOLINT
+ ENSURE_ASAN_INITED();
+ if (flags()->replace_str) {
+ uptr from_length = REAL(strlen)(from);
+ ASAN_READ_RANGE(from, from_length + 1);
+ uptr to_length = REAL(strlen)(to);
+ ASAN_READ_RANGE(to, to_length);
+ ASAN_WRITE_RANGE(to + to_length, from_length + 1);
+ // If the copying actually happens, the |from| string should not overlap
+ // with the resulting string starting at |to|, which has a length of
+ // to_length + from_length + 1.
+ if (from_length > 0) {
+ CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1,
+ from, from_length + 1);
+ }
+ }
+ return REAL(strcat)(to, from); // NOLINT
+}
+
+INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) {
+ ENSURE_ASAN_INITED();
+ if (flags()->replace_str) {
+ uptr from_length = MaybeRealStrnlen(from, size);
+ uptr copy_length = Min(size, from_length + 1);
+ ASAN_READ_RANGE(from, copy_length);
+ uptr to_length = REAL(strlen)(to);
+ ASAN_READ_RANGE(to, to_length);
+ ASAN_WRITE_RANGE(to + to_length, from_length + 1);
+ if (from_length > 0) {
+ CHECK_RANGES_OVERLAP("strncat", to, to_length + copy_length + 1,
+ from, copy_length);
+ }
+ }
+ return REAL(strncat)(to, from, size);
+}
+
+INTERCEPTOR(int, strcmp, const char *s1, const char *s2) {
+ if (!asan_inited) return internal_strcmp(s1, s2);
+ if (asan_init_is_running) {
+ return REAL(strcmp)(s1, s2);
+ }
+ ENSURE_ASAN_INITED();
+ unsigned char c1, c2;
+ uptr i;
+ for (i = 0; ; i++) {
+ c1 = (unsigned char)s1[i];
+ c2 = (unsigned char)s2[i];
+ if (c1 != c2 || c1 == '\0') break;
+ }
+ ASAN_READ_RANGE(s1, i + 1);
+ ASAN_READ_RANGE(s2, i + 1);
+ return CharCmp(c1, c2);
+}
+
+INTERCEPTOR(char*, strcpy, char *to, const char *from) { // NOLINT
+#if defined(__APPLE__)
+ if (!asan_inited) return REAL(strcpy)(to, from); // NOLINT
+#endif
+ // strcpy is called from malloc_default_purgeable_zone()
+ // in __asan::ReplaceSystemAlloc() on Mac.
+ if (asan_init_is_running) {
+ return REAL(strcpy)(to, from); // NOLINT
+ }
+ ENSURE_ASAN_INITED();
+ if (flags()->replace_str) {
+ uptr from_size = REAL(strlen)(from) + 1;
+ CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size);
+ ASAN_READ_RANGE(from, from_size);
+ ASAN_WRITE_RANGE(to, from_size);
+ }
+ return REAL(strcpy)(to, from); // NOLINT
+}
+
+#if ASAN_INTERCEPT_STRDUP
+INTERCEPTOR(char*, strdup, const char *s) {
+#if defined(__APPLE__)
+ // FIXME: because internal_strdup() uses InternalAlloc(), which currently
+ // just calls malloc() on Mac, we can't use internal_strdup() with the
+ // dynamic runtime. We can remove the call to REAL(strdup) once InternalAlloc
+ // starts using mmap() instead.
+ // See also http://code.google.com/p/address-sanitizer/issues/detail?id=123.
+ if (!asan_inited) return REAL(strdup)(s);
+#endif
+ if (!asan_inited) return internal_strdup(s);
+ ENSURE_ASAN_INITED();
+ if (flags()->replace_str) {
+ uptr length = REAL(strlen)(s);
+ ASAN_READ_RANGE(s, length + 1);
+ }
+ return REAL(strdup)(s);
+}
+#endif
+
+INTERCEPTOR(uptr, strlen, const char *s) {
+ if (!asan_inited) return internal_strlen(s);
+ // strlen is called from malloc_default_purgeable_zone()
+ // in __asan::ReplaceSystemAlloc() on Mac.
+ if (asan_init_is_running) {
+ return REAL(strlen)(s);
+ }
+ ENSURE_ASAN_INITED();
+ uptr length = REAL(strlen)(s);
+ if (flags()->replace_str) {
+ ASAN_READ_RANGE(s, length + 1);
+ }
+ return length;
+}
+
+#if ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP
+INTERCEPTOR(int, strcasecmp, const char *s1, const char *s2) {
+ ENSURE_ASAN_INITED();
+ unsigned char c1, c2;
+ uptr i;
+ for (i = 0; ; i++) {
+ c1 = (unsigned char)s1[i];
+ c2 = (unsigned char)s2[i];
+ if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break;
+ }
+ ASAN_READ_RANGE(s1, i + 1);
+ ASAN_READ_RANGE(s2, i + 1);
+ return CharCaseCmp(c1, c2);
+}
+
+INTERCEPTOR(int, strncasecmp, const char *s1, const char *s2, uptr n) {
+ ENSURE_ASAN_INITED();
+ unsigned char c1 = 0, c2 = 0;
+ uptr i;
+ for (i = 0; i < n; i++) {
+ c1 = (unsigned char)s1[i];
+ c2 = (unsigned char)s2[i];
+ if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break;
+ }
+ ASAN_READ_RANGE(s1, Min(i + 1, n));
+ ASAN_READ_RANGE(s2, Min(i + 1, n));
+ return CharCaseCmp(c1, c2);
+}
+#endif // ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP
+
+INTERCEPTOR(int, strncmp, const char *s1, const char *s2, uptr size) {
+ if (!asan_inited) return internal_strncmp(s1, s2, size);
+ // strncmp is called from malloc_default_purgeable_zone()
+ // in __asan::ReplaceSystemAlloc() on Mac.
+ if (asan_init_is_running) {
+ return REAL(strncmp)(s1, s2, size);
+ }
+ ENSURE_ASAN_INITED();
+ unsigned char c1 = 0, c2 = 0;
+ uptr i;
+ for (i = 0; i < size; i++) {
+ c1 = (unsigned char)s1[i];
+ c2 = (unsigned char)s2[i];
+ if (c1 != c2 || c1 == '\0') break;
+ }
+ ASAN_READ_RANGE(s1, Min(i + 1, size));
+ ASAN_READ_RANGE(s2, Min(i + 1, size));
+ return CharCmp(c1, c2);
+}
+
+INTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) {
+ ENSURE_ASAN_INITED();
+ if (flags()->replace_str) {
+ uptr from_size = Min(size, MaybeRealStrnlen(from, size) + 1);
+ CHECK_RANGES_OVERLAP("strncpy", to, from_size, from, from_size);
+ ASAN_READ_RANGE(from, from_size);
+ ASAN_WRITE_RANGE(to, size);
+ }
+ return REAL(strncpy)(to, from, size);
+}
+
+#if ASAN_INTERCEPT_STRNLEN
+INTERCEPTOR(uptr, strnlen, const char *s, uptr maxlen) {
+ ENSURE_ASAN_INITED();
+ uptr length = REAL(strnlen)(s, maxlen);
+ if (flags()->replace_str) {
+ ASAN_READ_RANGE(s, Min(length + 1, maxlen));
+ }
+ return length;
+}
+#endif // ASAN_INTERCEPT_STRNLEN
+
+static inline bool IsValidStrtolBase(int base) {
+ return (base == 0) || (2 <= base && base <= 36);
+}
+
+static inline void FixRealStrtolEndptr(const char *nptr, char **endptr) {
+ CHECK(endptr != 0);
+ if (nptr == *endptr) {
+ // No digits were found at strtol call, we need to find out the last
+ // symbol accessed by strtoll on our own.
+ // We get this symbol by skipping leading blanks and optional +/- sign.
+ while (IsSpace(*nptr)) nptr++;
+ if (*nptr == '+' || *nptr == '-') nptr++;
+ *endptr = (char*)nptr;
+ }
+ CHECK(*endptr >= nptr);
+}
+
+INTERCEPTOR(long, strtol, const char *nptr, // NOLINT
+ char **endptr, int base) {
+ ENSURE_ASAN_INITED();
+ if (!flags()->replace_str) {
+ return REAL(strtol)(nptr, endptr, base);
+ }
+ char *real_endptr;
+ long result = REAL(strtol)(nptr, &real_endptr, base); // NOLINT
+ if (endptr != 0) {
+ *endptr = real_endptr;
+ }
+ if (IsValidStrtolBase(base)) {
+ FixRealStrtolEndptr(nptr, &real_endptr);
+ ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
+ }
+ return result;
+}
+
+INTERCEPTOR(int, atoi, const char *nptr) {
+#if defined(__APPLE__)
+ if (!asan_inited) return REAL(atoi)(nptr);
+#endif
+ ENSURE_ASAN_INITED();
+ if (!flags()->replace_str) {
+ return REAL(atoi)(nptr);
+ }
+ char *real_endptr;
+ // "man atoi" tells that behavior of atoi(nptr) is the same as
+ // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the
+ // parsed integer can't be stored in *long* type (even if it's
+ // different from int). So, we just imitate this behavior.
+ int result = REAL(strtol)(nptr, &real_endptr, 10);
+ FixRealStrtolEndptr(nptr, &real_endptr);
+ ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
+ return result;
+}
+
+INTERCEPTOR(long, atol, const char *nptr) { // NOLINT
+#if defined(__APPLE__)
+ if (!asan_inited) return REAL(atol)(nptr);
+#endif
+ ENSURE_ASAN_INITED();
+ if (!flags()->replace_str) {
+ return REAL(atol)(nptr);
+ }
+ char *real_endptr;
+ long result = REAL(strtol)(nptr, &real_endptr, 10); // NOLINT
+ FixRealStrtolEndptr(nptr, &real_endptr);
+ ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
+ return result;
+}
+
+#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
+INTERCEPTOR(long long, strtoll, const char *nptr, // NOLINT
+ char **endptr, int base) {
+ ENSURE_ASAN_INITED();
+ if (!flags()->replace_str) {
+ return REAL(strtoll)(nptr, endptr, base);
+ }
+ char *real_endptr;
+ long long result = REAL(strtoll)(nptr, &real_endptr, base); // NOLINT
+ if (endptr != 0) {
+ *endptr = real_endptr;
+ }
+ // If base has unsupported value, strtoll can exit with EINVAL
+ // without reading any characters. So do additional checks only
+ // if base is valid.
+ if (IsValidStrtolBase(base)) {
+ FixRealStrtolEndptr(nptr, &real_endptr);
+ ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
+ }
+ return result;
+}
+
+INTERCEPTOR(long long, atoll, const char *nptr) { // NOLINT
+ ENSURE_ASAN_INITED();
+ if (!flags()->replace_str) {
+ return REAL(atoll)(nptr);
+ }
+ char *real_endptr;
+ long long result = REAL(strtoll)(nptr, &real_endptr, 10); // NOLINT
+ FixRealStrtolEndptr(nptr, &real_endptr);
+ ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1);
+ return result;
+}
+#endif // ASAN_INTERCEPT_ATOLL_AND_STRTOLL
+
+#define ASAN_INTERCEPT_FUNC(name) do { \
+ if (!INTERCEPT_FUNCTION(name) && flags()->verbosity > 0) \
+ Report("AddressSanitizer: failed to intercept '" #name "'\n"); \
+ } while (0)
+
+#if defined(_WIN32)
+INTERCEPTOR_WINAPI(DWORD, CreateThread,
+ void* security, uptr stack_size,
+ DWORD (__stdcall *start_routine)(void*), void* arg,
+ DWORD flags, void* tid) {
+ GET_STACK_TRACE_THREAD;
+ u32 current_tid = asanThreadRegistry().GetCurrentTidOrInvalid();
+ AsanThread *t = AsanThread::Create(current_tid, start_routine, arg, &stack);
+ asanThreadRegistry().RegisterThread(t);
+ return REAL(CreateThread)(security, stack_size,
+ asan_thread_start, t, flags, tid);
+}
+
+namespace __asan {
+void InitializeWindowsInterceptors() {
+ ASAN_INTERCEPT_FUNC(CreateThread);
+}
+
+} // namespace __asan
+#endif
+
+// ---------------------- InitializeAsanInterceptors ---------------- {{{1
+namespace __asan {
+void InitializeAsanInterceptors() {
+ static bool was_called_once;
+ CHECK(was_called_once == false);
+ was_called_once = true;
+#if defined(__APPLE__)
+ return;
+#else
+ SANITIZER_COMMON_INTERCEPTORS_INIT;
+
+ // Intercept mem* functions.
+ ASAN_INTERCEPT_FUNC(memcmp);
+ ASAN_INTERCEPT_FUNC(memmove);
+ ASAN_INTERCEPT_FUNC(memset);
+ if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) {
+ ASAN_INTERCEPT_FUNC(memcpy);
+ }
+
+ // Intercept str* functions.
+ ASAN_INTERCEPT_FUNC(strcat); // NOLINT
+ ASAN_INTERCEPT_FUNC(strchr);
+ ASAN_INTERCEPT_FUNC(strcmp);
+ ASAN_INTERCEPT_FUNC(strcpy); // NOLINT
+ ASAN_INTERCEPT_FUNC(strlen);
+ ASAN_INTERCEPT_FUNC(strncat);
+ ASAN_INTERCEPT_FUNC(strncmp);
+ ASAN_INTERCEPT_FUNC(strncpy);
+#if ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP
+ ASAN_INTERCEPT_FUNC(strcasecmp);
+ ASAN_INTERCEPT_FUNC(strncasecmp);
+#endif
+#if ASAN_INTERCEPT_STRDUP
+ ASAN_INTERCEPT_FUNC(strdup);
+#endif
+#if ASAN_INTERCEPT_STRNLEN
+ ASAN_INTERCEPT_FUNC(strnlen);
+#endif
+#if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
+ ASAN_INTERCEPT_FUNC(index);
+#endif
+
+ ASAN_INTERCEPT_FUNC(atoi);
+ ASAN_INTERCEPT_FUNC(atol);
+ ASAN_INTERCEPT_FUNC(strtol);
+#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
+ ASAN_INTERCEPT_FUNC(atoll);
+ ASAN_INTERCEPT_FUNC(strtoll);
+#endif
+
+#if ASAN_INTERCEPT_MLOCKX
+ // Intercept mlock/munlock.
+ ASAN_INTERCEPT_FUNC(mlock);
+ ASAN_INTERCEPT_FUNC(munlock);
+ ASAN_INTERCEPT_FUNC(mlockall);
+ ASAN_INTERCEPT_FUNC(munlockall);
+#endif
+
+ // Intecept signal- and jump-related functions.
+ ASAN_INTERCEPT_FUNC(longjmp);
+#if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
+ ASAN_INTERCEPT_FUNC(sigaction);
+ ASAN_INTERCEPT_FUNC(signal);
+#endif
+#if ASAN_INTERCEPT_SWAPCONTEXT
+ ASAN_INTERCEPT_FUNC(swapcontext);
+#endif
+#if ASAN_INTERCEPT__LONGJMP
+ ASAN_INTERCEPT_FUNC(_longjmp);
+#endif
+#if ASAN_INTERCEPT_SIGLONGJMP
+ ASAN_INTERCEPT_FUNC(siglongjmp);
+#endif
+
+ // Intercept exception handling functions.
+#if ASAN_INTERCEPT___CXA_THROW
+ INTERCEPT_FUNCTION(__cxa_throw);
+#endif
+
+ // Intercept threading-related functions
+#if ASAN_INTERCEPT_PTHREAD_CREATE
+ ASAN_INTERCEPT_FUNC(pthread_create);
+#endif
+
+ // Some Windows-specific interceptors.
+#if defined(_WIN32)
+ InitializeWindowsInterceptors();
+#endif
+
+ if (flags()->verbosity > 0) {
+ Report("AddressSanitizer: libc interceptors initialized\n");
+ }
+#endif // __APPLE__
+}
+
+} // namespace __asan
diff --git a/gcc-4.8/libsanitizer/asan/asan_interceptors.h b/gcc-4.8/libsanitizer/asan/asan_interceptors.h
new file mode 100644
index 000000000..cae4c7f01
--- /dev/null
+++ b/gcc-4.8/libsanitizer/asan/asan_interceptors.h
@@ -0,0 +1,36 @@
+//===-- asan_interceptors.h -------------------------------------*- C++ -*-===//
+//
+// 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.
+//
+// ASan-private header for asan_interceptors.cc
+//===----------------------------------------------------------------------===//
+#ifndef ASAN_INTERCEPTORS_H
+#define ASAN_INTERCEPTORS_H
+
+#include "asan_internal.h"
+#include "interception/interception.h"
+
+DECLARE_REAL(int, memcmp, const void *a1, const void *a2, uptr size)
+DECLARE_REAL(void*, memcpy, void *to, const void *from, uptr size)
+DECLARE_REAL(void*, memset, void *block, int c, uptr size)
+DECLARE_REAL(char*, strchr, const char *str, int c)
+DECLARE_REAL(uptr, strlen, const char *s)
+DECLARE_REAL(char*, strncpy, char *to, const char *from, uptr size)
+DECLARE_REAL(uptr, strnlen, const char *s, uptr maxlen)
+DECLARE_REAL(char*, strstr, const char *s1, const char *s2)
+struct sigaction;
+DECLARE_REAL(int, sigaction, int signum, const struct sigaction *act,
+ struct sigaction *oldact)
+
+namespace __asan {
+
+void InitializeAsanInterceptors();
+
+} // namespace __asan
+
+#endif // ASAN_INTERCEPTORS_H
diff --git a/gcc-4.8/libsanitizer/asan/asan_interface_internal.h b/gcc-4.8/libsanitizer/asan/asan_interface_internal.h
new file mode 100644
index 000000000..2fd58b856
--- /dev/null
+++ b/gcc-4.8/libsanitizer/asan/asan_interface_internal.h
@@ -0,0 +1,133 @@
+//===-- asan_interface_internal.h -------------------------------*- C++ -*-===//
+//
+// 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.
+//
+// This header can be included by the instrumented program to fetch
+// data (mostly allocator statistics) from ASan runtime library.
+//===----------------------------------------------------------------------===//
+#ifndef ASAN_INTERFACE_INTERNAL_H
+#define ASAN_INTERFACE_INTERNAL_H
+
+#include "sanitizer_common/sanitizer_internal_defs.h"
+
+using __sanitizer::uptr;
+
+extern "C" {
+ // This function should be called at the very beginning of the process,
+ // before any instrumented code is executed and before any call to malloc.
+ // Everytime the asan ABI changes we also change the version number in this
+ // name. Objects build with incompatible asan ABI version
+ // will not link with run-time.
+ void __asan_init_v1() SANITIZER_INTERFACE_ATTRIBUTE;
+ #define __asan_init __asan_init_v1
+
+ // This structure describes an instrumented global variable.
+ struct __asan_global {
+ uptr beg; // The address of the global.
+ uptr size; // The original size of the global.
+ uptr size_with_redzone; // The size with the redzone.
+ const char *name; // Name as a C string.
+ uptr has_dynamic_init; // Non-zero if the global has dynamic initializer.
+ };
+
+ // These two functions should be called by the instrumented code.
+ // 'globals' is an array of structures describing 'n' globals.
+ void __asan_register_globals(__asan_global *globals, uptr n)
+ SANITIZER_INTERFACE_ATTRIBUTE;
+ void __asan_unregister_globals(__asan_global *globals, uptr n)
+ SANITIZER_INTERFACE_ATTRIBUTE;
+
+ // These two functions should be called before and after dynamic initializers
+ // run, respectively. They should be called with parameters describing all
+ // dynamically initialized globals defined in the calling TU.
+ void __asan_before_dynamic_init(uptr first_addr, uptr last_addr)
+ SANITIZER_INTERFACE_ATTRIBUTE;
+ void __asan_after_dynamic_init()
+ SANITIZER_INTERFACE_ATTRIBUTE;
+
+ // These two functions are used by the instrumented code in the
+ // use-after-return mode. __asan_stack_malloc allocates size bytes of
+ // fake stack and __asan_stack_free poisons it. real_stack is a pointer to
+ // the real stack region.
+ uptr __asan_stack_malloc(uptr size, uptr real_stack)
+ SANITIZER_INTERFACE_ATTRIBUTE;
+ void __asan_stack_free(uptr ptr, uptr size, uptr real_stack)
+ SANITIZER_INTERFACE_ATTRIBUTE;
+
+ // These two functions are used by instrumented code in the
+ // use-after-scope mode. They mark memory for local variables as
+ // unaddressable when they leave scope and addressable before the
+ // function exits.
+ void __asan_poison_stack_memory(uptr addr, uptr size)
+ SANITIZER_INTERFACE_ATTRIBUTE;
+ void __asan_unpoison_stack_memory(uptr addr, uptr size)
+ SANITIZER_INTERFACE_ATTRIBUTE;
+
+ // Performs cleanup before a NoReturn function. Must be called before things
+ // like _exit and execl to avoid false positives on stack.
+ void __asan_handle_no_return() SANITIZER_INTERFACE_ATTRIBUTE;
+
+ void __asan_poison_memory_region(void const volatile *addr, uptr size)
+ SANITIZER_INTERFACE_ATTRIBUTE;
+ void __asan_unpoison_memory_region(void const volatile *addr, uptr size)
+ SANITIZER_INTERFACE_ATTRIBUTE;
+
+ bool __asan_address_is_poisoned(void const volatile *addr)
+ SANITIZER_INTERFACE_ATTRIBUTE;
+
+ uptr __asan_region_is_poisoned(uptr beg, uptr size)
+ SANITIZER_INTERFACE_ATTRIBUTE;
+
+ void __asan_describe_address(uptr addr)
+ SANITIZER_INTERFACE_ATTRIBUTE;
+
+ void __asan_report_error(uptr pc, uptr bp, uptr sp,
+ uptr addr, bool is_write, uptr access_size)
+ SANITIZER_INTERFACE_ATTRIBUTE;
+
+ int __asan_set_error_exit_code(int exit_code)
+ SANITIZER_INTERFACE_ATTRIBUTE;
+ void __asan_set_death_callback(void (*callback)(void))
+ SANITIZER_INTERFACE_ATTRIBUTE;
+ void __asan_set_error_report_callback(void (*callback)(const char*))
+ SANITIZER_INTERFACE_ATTRIBUTE;
+
+ /* OPTIONAL */ void __asan_on_error()
+ SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+
+ /* OPTIONAL */ bool __asan_symbolize(const void *pc, char *out_buffer,
+ int out_size)
+ SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+
+ uptr __asan_get_estimated_allocated_size(uptr size)
+ SANITIZER_INTERFACE_ATTRIBUTE;
+ bool __asan_get_ownership(const void *p)
+ SANITIZER_INTERFACE_ATTRIBUTE;
+ uptr __asan_get_allocated_size(const void *p)
+ SANITIZER_INTERFACE_ATTRIBUTE;
+ uptr __asan_get_current_allocated_bytes()
+ SANITIZER_INTERFACE_ATTRIBUTE;
+ uptr __asan_get_heap_size()
+ SANITIZER_INTERFACE_ATTRIBUTE;
+ uptr __asan_get_free_bytes()
+ SANITIZER_INTERFACE_ATTRIBUTE;
+ uptr __asan_get_unmapped_bytes()
+ SANITIZER_INTERFACE_ATTRIBUTE;
+ void __asan_print_accumulated_stats()
+ SANITIZER_INTERFACE_ATTRIBUTE;
+
+ /* OPTIONAL */ const char* __asan_default_options()
+ SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+
+ /* OPTIONAL */ void __asan_malloc_hook(void *ptr, uptr size)
+ SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+ /* OPTIONAL */ void __asan_free_hook(void *ptr)
+ SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+} // extern "C"
+
+#endif // ASAN_INTERFACE_INTERNAL_H
diff --git a/gcc-4.8/libsanitizer/asan/asan_internal.h b/gcc-4.8/libsanitizer/asan/asan_internal.h
new file mode 100644
index 000000000..1ccbf1086
--- /dev/null
+++ b/gcc-4.8/libsanitizer/asan/asan_internal.h
@@ -0,0 +1,185 @@
+//===-- asan_internal.h -----------------------------------------*- C++ -*-===//
+//
+// 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.
+//
+// ASan-private header which defines various general utilities.
+//===----------------------------------------------------------------------===//
+#ifndef ASAN_INTERNAL_H
+#define ASAN_INTERNAL_H
+
+#include "asan_flags.h"
+#include "asan_interface_internal.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_internal_defs.h"
+#include "sanitizer_common/sanitizer_stacktrace.h"
+#include "sanitizer_common/sanitizer_libc.h"
+
+#if !defined(__linux__) && !defined(__APPLE__) && !defined(_WIN32)
+# error "This operating system is not supported by AddressSanitizer"
+#endif
+
+#define ASAN_DEFAULT_FAILURE_EXITCODE 1
+
+#if defined(__linux__)
+# define ASAN_LINUX 1
+#else
+# define ASAN_LINUX 0
+#endif
+
+#if defined(__APPLE__)
+# define ASAN_MAC 1
+#else
+# define ASAN_MAC 0
+#endif
+
+#if defined(_WIN32)
+# define ASAN_WINDOWS 1
+#else
+# define ASAN_WINDOWS 0
+#endif
+
+#if defined(__ANDROID__) || defined(ANDROID)
+# define ASAN_ANDROID 1
+#else
+# define ASAN_ANDROID 0
+#endif
+
+
+#define ASAN_POSIX (ASAN_LINUX || ASAN_MAC)
+
+#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
+# error "The AddressSanitizer run-time should not be"
+ " instrumented by AddressSanitizer"
+#endif
+
+// Build-time configuration options.
+
+// If set, asan will install its own SEGV signal handler.
+#ifndef ASAN_NEEDS_SEGV
+# if ASAN_ANDROID == 1
+# define ASAN_NEEDS_SEGV 0
+# else
+# define ASAN_NEEDS_SEGV 1
+# endif
+#endif
+
+// If set, asan will intercept C++ exception api call(s).
+#ifndef ASAN_HAS_EXCEPTIONS
+# define ASAN_HAS_EXCEPTIONS 1
+#endif
+
+// If set, asan uses the values of SHADOW_SCALE and SHADOW_OFFSET
+// provided by the instrumented objects. Otherwise constants are used.
+#ifndef ASAN_FLEXIBLE_MAPPING_AND_OFFSET
+# define ASAN_FLEXIBLE_MAPPING_AND_OFFSET 0
+#endif
+
+// If set, values like allocator chunk size, as well as defaults for some flags
+// will be changed towards less memory overhead.
+#ifndef ASAN_LOW_MEMORY
+#if SANITIZER_WORDSIZE == 32
+# define ASAN_LOW_MEMORY 1
+#else
+# define ASAN_LOW_MEMORY 0
+# endif
+#endif
+
+#ifndef ASAN_USE_PREINIT_ARRAY
+# define ASAN_USE_PREINIT_ARRAY (ASAN_LINUX && !ASAN_ANDROID)
+#endif
+
+// All internal functions in asan reside inside the __asan namespace
+// to avoid namespace collisions with the user programs.
+// Seperate namespace also makes it simpler to distinguish the asan run-time
+// functions from the instrumented user code in a profile.
+namespace __asan {
+
+class AsanThread;
+using __sanitizer::StackTrace;
+
+// asan_rtl.cc
+void NORETURN ShowStatsAndAbort();
+
+void ReplaceOperatorsNewAndDelete();
+// asan_malloc_linux.cc / asan_malloc_mac.cc
+void ReplaceSystemMalloc();
+
+// asan_linux.cc / asan_mac.cc / asan_win.cc
+void *AsanDoesNotSupportStaticLinkage();
+
+void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp);
+
+void MaybeReexec();
+bool AsanInterceptsSignal(int signum);
+void SetAlternateSignalStack();
+void UnsetAlternateSignalStack();
+void InstallSignalHandlers();
+void ReadContextStack(void *context, uptr *stack, uptr *ssize);
+void AsanPlatformThreadInit();
+
+// Wrapper for TLS/TSD.
+void AsanTSDInit(void (*destructor)(void *tsd));
+void *AsanTSDGet();
+void AsanTSDSet(void *tsd);
+
+void AppendToErrorMessageBuffer(const char *buffer);
+
+// asan_poisoning.cc
+// Poisons the shadow memory for "size" bytes starting from "addr".
+void PoisonShadow(uptr addr, uptr size, u8 value);
+// Poisons the shadow memory for "redzone_size" bytes starting from
+// "addr + size".
+void PoisonShadowPartialRightRedzone(uptr addr,
+ uptr size,
+ uptr redzone_size,
+ u8 value);
+
+// Platfrom-specific options.
+#ifdef __APPLE__
+bool PlatformHasDifferentMemcpyAndMemmove();
+# define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE \
+ (PlatformHasDifferentMemcpyAndMemmove())
+#else
+# define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE true
+#endif // __APPLE__
+
+// Add convenient macro for interface functions that may be represented as
+// weak hooks.
+#define ASAN_MALLOC_HOOK(ptr, size) \
+ if (&__asan_malloc_hook) __asan_malloc_hook(ptr, size)
+#define ASAN_FREE_HOOK(ptr) \
+ if (&__asan_free_hook) __asan_free_hook(ptr)
+#define ASAN_ON_ERROR() \
+ if (&__asan_on_error) __asan_on_error()
+
+extern int asan_inited;
+// Used to avoid infinite recursion in __asan_init().
+extern bool asan_init_is_running;
+extern void (*death_callback)(void);
+
+// These magic values are written to shadow for better error reporting.
+const int kAsanHeapLeftRedzoneMagic = 0xfa;
+const int kAsanHeapRightRedzoneMagic = 0xfb;
+const int kAsanHeapFreeMagic = 0xfd;
+const int kAsanStackLeftRedzoneMagic = 0xf1;
+const int kAsanStackMidRedzoneMagic = 0xf2;
+const int kAsanStackRightRedzoneMagic = 0xf3;
+const int kAsanStackPartialRedzoneMagic = 0xf4;
+const int kAsanStackAfterReturnMagic = 0xf5;
+const int kAsanInitializationOrderMagic = 0xf6;
+const int kAsanUserPoisonedMemoryMagic = 0xf7;
+const int kAsanStackUseAfterScopeMagic = 0xf8;
+const int kAsanGlobalRedzoneMagic = 0xf9;
+const int kAsanInternalHeapMagic = 0xfe;
+
+static const uptr kCurrentStackFrameMagic = 0x41B58AB3;
+static const uptr kRetiredStackFrameMagic = 0x45E0360E;
+
+} // namespace __asan
+
+#endif // ASAN_INTERNAL_H
diff --git a/gcc-4.8/libsanitizer/asan/asan_linux.cc b/gcc-4.8/libsanitizer/asan/asan_linux.cc
new file mode 100644
index 000000000..a030fcd39
--- /dev/null
+++ b/gcc-4.8/libsanitizer/asan/asan_linux.cc
@@ -0,0 +1,134 @@
+//===-- asan_linux.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.
+//
+// Linux-specific details.
+//===----------------------------------------------------------------------===//
+#ifdef __linux__
+
+#include "asan_interceptors.h"
+#include "asan_internal.h"
+#include "asan_thread.h"
+#include "asan_thread_registry.h"
+#include "sanitizer_common/sanitizer_libc.h"
+#include "sanitizer_common/sanitizer_procmaps.h"
+
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/mman.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <unwind.h>
+
+#if !ASAN_ANDROID
+// FIXME: where to get ucontext on Android?
+#include <sys/ucontext.h>
+#endif
+
+extern "C" void* _DYNAMIC;
+
+namespace __asan {
+
+void MaybeReexec() {
+ // No need to re-exec on Linux.
+}
+
+void *AsanDoesNotSupportStaticLinkage() {
+ // This will fail to link with -static.
+ return &_DYNAMIC; // defined in link.h
+}
+
+void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
+#if ASAN_ANDROID
+ *pc = *sp = *bp = 0;
+#elif defined(__arm__)
+ ucontext_t *ucontext = (ucontext_t*)context;
+ *pc = ucontext->uc_mcontext.arm_pc;
+ *bp = ucontext->uc_mcontext.arm_fp;
+ *sp = ucontext->uc_mcontext.arm_sp;
+# elif defined(__x86_64__)
+ ucontext_t *ucontext = (ucontext_t*)context;
+ *pc = ucontext->uc_mcontext.gregs[REG_RIP];
+ *bp = ucontext->uc_mcontext.gregs[REG_RBP];
+ *sp = ucontext->uc_mcontext.gregs[REG_RSP];
+# elif defined(__i386__)
+ ucontext_t *ucontext = (ucontext_t*)context;
+ *pc = ucontext->uc_mcontext.gregs[REG_EIP];
+ *bp = ucontext->uc_mcontext.gregs[REG_EBP];
+ *sp = ucontext->uc_mcontext.gregs[REG_ESP];
+# elif defined(__powerpc__) || defined(__powerpc64__)
+ ucontext_t *ucontext = (ucontext_t*)context;
+ *pc = ucontext->uc_mcontext.regs->nip;
+ *sp = ucontext->uc_mcontext.regs->gpr[PT_R1];
+ // The powerpc{,64}-linux ABIs do not specify r31 as the frame
+ // pointer, but GCC always uses r31 when we need a frame pointer.
+ *bp = ucontext->uc_mcontext.regs->gpr[PT_R31];
+# elif defined(__sparc__)
+ ucontext_t *ucontext = (ucontext_t*)context;
+ uptr *stk_ptr;
+# if defined (__arch64__)
+ *pc = ucontext->uc_mcontext.mc_gregs[MC_PC];
+ *sp = ucontext->uc_mcontext.mc_gregs[MC_O6];
+ stk_ptr = (uptr *) (*sp + 2047);
+ *bp = stk_ptr[15];
+# else
+ *pc = ucontext->uc_mcontext.gregs[REG_PC];
+ *sp = ucontext->uc_mcontext.gregs[REG_O6];
+ stk_ptr = (uptr *) *sp;
+ *bp = stk_ptr[15];
+# endif
+#else
+# error "Unsupported arch"
+#endif
+}
+
+bool AsanInterceptsSignal(int signum) {
+ return signum == SIGSEGV && flags()->handle_segv;
+}
+
+void AsanPlatformThreadInit() {
+ // Nothing here for now.
+}
+
+void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp, bool fast) {
+#if defined(__arm__) || \
+ defined(__powerpc__) || defined(__powerpc64__) || \
+ defined(__sparc__)
+ fast = false;
+#endif
+ if (!fast)
+ return stack->SlowUnwindStack(pc, max_s);
+ stack->size = 0;
+ stack->trace[0] = pc;
+ if (max_s > 1) {
+ stack->max_size = max_s;
+ if (!asan_inited) return;
+ if (AsanThread *t = asanThreadRegistry().GetCurrent())
+ stack->FastUnwindStack(pc, bp, t->stack_top(), t->stack_bottom());
+ }
+}
+
+#if !ASAN_ANDROID
+void ReadContextStack(void *context, uptr *stack, uptr *ssize) {
+ ucontext_t *ucp = (ucontext_t*)context;
+ *stack = (uptr)ucp->uc_stack.ss_sp;
+ *ssize = ucp->uc_stack.ss_size;
+}
+#else
+void ReadContextStack(void *context, uptr *stack, uptr *ssize) {
+ UNIMPLEMENTED();
+}
+#endif
+
+} // namespace __asan
+
+#endif // __linux__
diff --git a/gcc-4.8/libsanitizer/asan/asan_lock.h b/gcc-4.8/libsanitizer/asan/asan_lock.h
new file mode 100644
index 000000000..8b1378917
--- /dev/null
+++ b/gcc-4.8/libsanitizer/asan/asan_lock.h
@@ -0,0 +1 @@
+
diff --git a/gcc-4.8/libsanitizer/asan/asan_mac.cc b/gcc-4.8/libsanitizer/asan/asan_mac.cc
new file mode 100644
index 000000000..dd2657df1
--- /dev/null
+++ b/gcc-4.8/libsanitizer/asan/asan_mac.cc
@@ -0,0 +1,452 @@
+//===-- asan_mac.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.
+//
+// Mac-specific details.
+//===----------------------------------------------------------------------===//
+
+#ifdef __APPLE__
+
+#include "asan_interceptors.h"
+#include "asan_internal.h"
+#include "asan_mac.h"
+#include "asan_mapping.h"
+#include "asan_stack.h"
+#include "asan_thread.h"
+#include "asan_thread_registry.h"
+#include "sanitizer_common/sanitizer_libc.h"
+
+#include <crt_externs.h> // for _NSGetArgv
+#include <dlfcn.h> // for dladdr()
+#include <mach-o/dyld.h>
+#include <mach-o/loader.h>
+#include <sys/mman.h>
+#include <sys/resource.h>
+#include <sys/sysctl.h>
+#include <sys/ucontext.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <stdlib.h> // for free()
+#include <unistd.h>
+#include <libkern/OSAtomic.h>
+
+namespace __asan {
+
+void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
+ ucontext_t *ucontext = (ucontext_t*)context;
+# if SANITIZER_WORDSIZE == 64
+ *pc = ucontext->uc_mcontext->__ss.__rip;
+ *bp = ucontext->uc_mcontext->__ss.__rbp;
+ *sp = ucontext->uc_mcontext->__ss.__rsp;
+# else
+ *pc = ucontext->uc_mcontext->__ss.__eip;
+ *bp = ucontext->uc_mcontext->__ss.__ebp;
+ *sp = ucontext->uc_mcontext->__ss.__esp;
+# endif // SANITIZER_WORDSIZE
+}
+
+int GetMacosVersion() {
+ int mib[2] = { CTL_KERN, KERN_OSRELEASE };
+ char version[100];
+ uptr len = 0, maxlen = sizeof(version) / sizeof(version[0]);
+ for (uptr i = 0; i < maxlen; i++) version[i] = '\0';
+ // Get the version length.
+ CHECK(sysctl(mib, 2, 0, &len, 0, 0) != -1);
+ CHECK(len < maxlen);
+ CHECK(sysctl(mib, 2, version, &len, 0, 0) != -1);
+ switch (version[0]) {
+ case '9': return MACOS_VERSION_LEOPARD;
+ case '1': {
+ switch (version[1]) {
+ case '0': return MACOS_VERSION_SNOW_LEOPARD;
+ case '1': return MACOS_VERSION_LION;
+ case '2': return MACOS_VERSION_MOUNTAIN_LION;
+ default: return MACOS_VERSION_UNKNOWN;
+ }
+ }
+ default: return MACOS_VERSION_UNKNOWN;
+ }
+}
+
+bool PlatformHasDifferentMemcpyAndMemmove() {
+ // On OS X 10.7 memcpy() and memmove() are both resolved
+ // into memmove$VARIANT$sse42.
+ // See also http://code.google.com/p/address-sanitizer/issues/detail?id=34.
+ // TODO(glider): need to check dynamically that memcpy() and memmove() are
+ // actually the same function.
+ return GetMacosVersion() == MACOS_VERSION_SNOW_LEOPARD;
+}
+
+extern "C"
+void __asan_init();
+
+static const char kDyldInsertLibraries[] = "DYLD_INSERT_LIBRARIES";
+LowLevelAllocator allocator_for_env;
+
+// Change the value of the env var |name|, leaking the original value.
+// If |name_value| is NULL, the variable is deleted from the environment,
+// otherwise the corresponding "NAME=value" string is replaced with
+// |name_value|.
+void LeakyResetEnv(const char *name, const char *name_value) {
+ char ***env_ptr = _NSGetEnviron();
+ CHECK(env_ptr);
+ char **environ = *env_ptr;
+ CHECK(environ);
+ uptr name_len = internal_strlen(name);
+ while (*environ != 0) {
+ uptr len = internal_strlen(*environ);
+ if (len > name_len) {
+ const char *p = *environ;
+ if (!internal_memcmp(p, name, name_len) && p[name_len] == '=') {
+ // Match.
+ if (name_value) {
+ // Replace the old value with the new one.
+ *environ = const_cast<char*>(name_value);
+ } else {
+ // Shift the subsequent pointers back.
+ char **del = environ;
+ do {
+ del[0] = del[1];
+ } while (*del++);
+ }
+ }
+ }
+ environ++;
+ }
+}
+
+void MaybeReexec() {
+ if (!flags()->allow_reexec) return;
+ // Make sure the dynamic ASan runtime library is preloaded so that the
+ // wrappers work. If it is not, set DYLD_INSERT_LIBRARIES and re-exec
+ // ourselves.
+ Dl_info info;
+ CHECK(dladdr((void*)((uptr)__asan_init), &info));
+ char *dyld_insert_libraries =
+ const_cast<char*>(GetEnv(kDyldInsertLibraries));
+ uptr old_env_len = dyld_insert_libraries ?
+ internal_strlen(dyld_insert_libraries) : 0;
+ uptr fname_len = internal_strlen(info.dli_fname);
+ if (!dyld_insert_libraries ||
+ !REAL(strstr)(dyld_insert_libraries, info.dli_fname)) {
+ // DYLD_INSERT_LIBRARIES is not set or does not contain the runtime
+ // library.
+ char program_name[1024];
+ uint32_t buf_size = sizeof(program_name);
+ _NSGetExecutablePath(program_name, &buf_size);
+ char *new_env = const_cast<char*>(info.dli_fname);
+ if (dyld_insert_libraries) {
+ // Append the runtime dylib name to the existing value of
+ // DYLD_INSERT_LIBRARIES.
+ new_env = (char*)allocator_for_env.Allocate(old_env_len + fname_len + 2);
+ internal_strncpy(new_env, dyld_insert_libraries, old_env_len);
+ new_env[old_env_len] = ':';
+ // Copy fname_len and add a trailing zero.
+ internal_strncpy(new_env + old_env_len + 1, info.dli_fname,
+ fname_len + 1);
+ // Ok to use setenv() since the wrappers don't depend on the value of
+ // asan_inited.
+ setenv(kDyldInsertLibraries, new_env, /*overwrite*/1);
+ } else {
+ // Set DYLD_INSERT_LIBRARIES equal to the runtime dylib name.
+ setenv(kDyldInsertLibraries, info.dli_fname, /*overwrite*/0);
+ }
+ if (flags()->verbosity >= 1) {
+ Report("exec()-ing the program with\n");
+ Report("%s=%s\n", kDyldInsertLibraries, new_env);
+ Report("to enable ASan wrappers.\n");
+ Report("Set ASAN_OPTIONS=allow_reexec=0 to disable this.\n");
+ }
+ execv(program_name, *_NSGetArgv());
+ } else {
+ // DYLD_INSERT_LIBRARIES is set and contains the runtime library.
+ if (old_env_len == fname_len) {
+ // It's just the runtime library name - fine to unset the variable.
+ LeakyResetEnv(kDyldInsertLibraries, NULL);
+ } else {
+ uptr env_name_len = internal_strlen(kDyldInsertLibraries);
+ // Allocate memory to hold the previous env var name, its value, the '='
+ // sign and the '\0' char.
+ char *new_env = (char*)allocator_for_env.Allocate(
+ old_env_len + 2 + env_name_len);
+ CHECK(new_env);
+ internal_memset(new_env, '\0', old_env_len + 2 + env_name_len);
+ internal_strncpy(new_env, kDyldInsertLibraries, env_name_len);
+ new_env[env_name_len] = '=';
+ char *new_env_pos = new_env + env_name_len + 1;
+
+ // Iterate over colon-separated pieces of |dyld_insert_libraries|.
+ char *piece_start = dyld_insert_libraries;
+ char *piece_end = NULL;
+ char *old_env_end = dyld_insert_libraries + old_env_len;
+ do {
+ if (piece_start[0] == ':') piece_start++;
+ piece_end = REAL(strchr)(piece_start, ':');
+ if (!piece_end) piece_end = dyld_insert_libraries + old_env_len;
+ if ((uptr)(piece_start - dyld_insert_libraries) > old_env_len) break;
+ uptr piece_len = piece_end - piece_start;
+
+ // If the current piece isn't the runtime library name,
+ // append it to new_env.
+ if ((piece_len != fname_len) ||
+ (internal_strncmp(piece_start, info.dli_fname, fname_len) != 0)) {
+ if (new_env_pos != new_env + env_name_len + 1) {
+ new_env_pos[0] = ':';
+ new_env_pos++;
+ }
+ internal_strncpy(new_env_pos, piece_start, piece_len);
+ }
+ // Move on to the next piece.
+ new_env_pos += piece_len;
+ piece_start = piece_end;
+ } while (piece_start < old_env_end);
+
+ // Can't use setenv() here, because it requires the allocator to be
+ // initialized.
+ // FIXME: instead of filtering DYLD_INSERT_LIBRARIES here, do it in
+ // a separate function called after InitializeAllocator().
+ LeakyResetEnv(kDyldInsertLibraries, new_env);
+ }
+ }
+}
+
+// No-op. Mac does not support static linkage anyway.
+void *AsanDoesNotSupportStaticLinkage() {
+ return 0;
+}
+
+bool AsanInterceptsSignal(int signum) {
+ return (signum == SIGSEGV || signum == SIGBUS) && flags()->handle_segv;
+}
+
+void AsanPlatformThreadInit() {
+}
+
+void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp, bool fast) {
+ (void)fast;
+ stack->size = 0;
+ stack->trace[0] = pc;
+ if ((max_s) > 1) {
+ stack->max_size = max_s;
+ if (!asan_inited) return;
+ if (AsanThread *t = asanThreadRegistry().GetCurrent())
+ stack->FastUnwindStack(pc, bp, t->stack_top(), t->stack_bottom());
+ }
+}
+
+void ReadContextStack(void *context, uptr *stack, uptr *ssize) {
+ UNIMPLEMENTED();
+}
+
+// Support for the following functions from libdispatch on Mac OS:
+// dispatch_async_f()
+// dispatch_async()
+// dispatch_sync_f()
+// dispatch_sync()
+// dispatch_after_f()
+// dispatch_after()
+// dispatch_group_async_f()
+// dispatch_group_async()
+// TODO(glider): libdispatch API contains other functions that we don't support
+// yet.
+//
+// dispatch_sync() and dispatch_sync_f() are synchronous, although chances are
+// they can cause jobs to run on a thread different from the current one.
+// TODO(glider): if so, we need a test for this (otherwise we should remove
+// them).
+//
+// The following functions use dispatch_barrier_async_f() (which isn't a library
+// function but is exported) and are thus supported:
+// dispatch_source_set_cancel_handler_f()
+// dispatch_source_set_cancel_handler()
+// dispatch_source_set_event_handler_f()
+// dispatch_source_set_event_handler()
+//
+// The reference manual for Grand Central Dispatch is available at
+// http://developer.apple.com/library/mac/#documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html
+// The implementation details are at
+// http://libdispatch.macosforge.org/trac/browser/trunk/src/queue.c
+
+typedef void* dispatch_group_t;
+typedef void* dispatch_queue_t;
+typedef void* dispatch_source_t;
+typedef u64 dispatch_time_t;
+typedef void (*dispatch_function_t)(void *block);
+typedef void* (*worker_t)(void *block);
+
+// A wrapper for the ObjC blocks used to support libdispatch.
+typedef struct {
+ void *block;
+ dispatch_function_t func;
+ u32 parent_tid;
+} asan_block_context_t;
+
+// We use extern declarations of libdispatch functions here instead
+// of including <dispatch/dispatch.h>. This header is not present on
+// Mac OS X Leopard and eariler, and although we don't expect ASan to
+// work on legacy systems, it's bad to break the build of
+// LLVM compiler-rt there.
+extern "C" {
+void dispatch_async_f(dispatch_queue_t dq, void *ctxt,
+ dispatch_function_t func);
+void dispatch_sync_f(dispatch_queue_t dq, void *ctxt,
+ dispatch_function_t func);
+void dispatch_after_f(dispatch_time_t when, dispatch_queue_t dq, void *ctxt,
+ dispatch_function_t func);
+void dispatch_barrier_async_f(dispatch_queue_t dq, void *ctxt,
+ dispatch_function_t func);
+void dispatch_group_async_f(dispatch_group_t group, dispatch_queue_t dq,
+ void *ctxt, dispatch_function_t func);
+} // extern "C"
+
+static ALWAYS_INLINE
+void asan_register_worker_thread(int parent_tid, StackTrace *stack) {
+ AsanThread *t = asanThreadRegistry().GetCurrent();
+ if (!t) {
+ t = AsanThread::Create(parent_tid, 0, 0, stack);
+ asanThreadRegistry().RegisterThread(t);
+ t->Init();
+ asanThreadRegistry().SetCurrent(t);
+ }
+}
+
+// For use by only those functions that allocated the context via
+// alloc_asan_context().
+extern "C"
+void asan_dispatch_call_block_and_release(void *block) {
+ GET_STACK_TRACE_THREAD;
+ asan_block_context_t *context = (asan_block_context_t*)block;
+ if (flags()->verbosity >= 2) {
+ Report("asan_dispatch_call_block_and_release(): "
+ "context: %p, pthread_self: %p\n",
+ block, pthread_self());
+ }
+ asan_register_worker_thread(context->parent_tid, &stack);
+ // Call the original dispatcher for the block.
+ context->func(context->block);
+ asan_free(context, &stack, FROM_MALLOC);
+}
+
+} // namespace __asan
+
+using namespace __asan; // NOLINT
+
+// Wrap |ctxt| and |func| into an asan_block_context_t.
+// The caller retains control of the allocated context.
+extern "C"
+asan_block_context_t *alloc_asan_context(void *ctxt, dispatch_function_t func,
+ StackTrace *stack) {
+ asan_block_context_t *asan_ctxt =
+ (asan_block_context_t*) asan_malloc(sizeof(asan_block_context_t), stack);
+ asan_ctxt->block = ctxt;
+ asan_ctxt->func = func;
+ asan_ctxt->parent_tid = asanThreadRegistry().GetCurrentTidOrInvalid();
+ return asan_ctxt;
+}
+
+// Define interceptor for dispatch_*_f function with the three most common
+// parameters: dispatch_queue_t, context, dispatch_function_t.
+#define INTERCEPT_DISPATCH_X_F_3(dispatch_x_f) \
+ INTERCEPTOR(void, dispatch_x_f, dispatch_queue_t dq, void *ctxt, \
+ dispatch_function_t func) { \
+ GET_STACK_TRACE_THREAD; \
+ asan_block_context_t *asan_ctxt = alloc_asan_context(ctxt, func, &stack); \
+ if (flags()->verbosity >= 2) { \
+ Report(#dispatch_x_f "(): context: %p, pthread_self: %p\n", \
+ asan_ctxt, pthread_self()); \
+ PRINT_CURRENT_STACK(); \
+ } \
+ return REAL(dispatch_x_f)(dq, (void*)asan_ctxt, \
+ asan_dispatch_call_block_and_release); \
+ }
+
+INTERCEPT_DISPATCH_X_F_3(dispatch_async_f)
+INTERCEPT_DISPATCH_X_F_3(dispatch_sync_f)
+INTERCEPT_DISPATCH_X_F_3(dispatch_barrier_async_f)
+
+INTERCEPTOR(void, dispatch_after_f, dispatch_time_t when,
+ dispatch_queue_t dq, void *ctxt,
+ dispatch_function_t func) {
+ GET_STACK_TRACE_THREAD;
+ asan_block_context_t *asan_ctxt = alloc_asan_context(ctxt, func, &stack);
+ if (flags()->verbosity >= 2) {
+ Report("dispatch_after_f: %p\n", asan_ctxt);
+ PRINT_CURRENT_STACK();
+ }
+ return REAL(dispatch_after_f)(when, dq, (void*)asan_ctxt,
+ asan_dispatch_call_block_and_release);
+}
+
+INTERCEPTOR(void, dispatch_group_async_f, dispatch_group_t group,
+ dispatch_queue_t dq, void *ctxt,
+ dispatch_function_t func) {
+ GET_STACK_TRACE_THREAD;
+ asan_block_context_t *asan_ctxt = alloc_asan_context(ctxt, func, &stack);
+ if (flags()->verbosity >= 2) {
+ Report("dispatch_group_async_f(): context: %p, pthread_self: %p\n",
+ asan_ctxt, pthread_self());
+ PRINT_CURRENT_STACK();
+ }
+ REAL(dispatch_group_async_f)(group, dq, (void*)asan_ctxt,
+ asan_dispatch_call_block_and_release);
+}
+
+#if !defined(MISSING_BLOCKS_SUPPORT)
+extern "C" {
+// FIXME: consolidate these declarations with asan_intercepted_functions.h.
+void dispatch_async(dispatch_queue_t dq, void(^work)(void));
+void dispatch_group_async(dispatch_group_t dg, dispatch_queue_t dq,
+ void(^work)(void));
+void dispatch_after(dispatch_time_t when, dispatch_queue_t queue,
+ void(^work)(void));
+void dispatch_source_set_cancel_handler(dispatch_source_t ds,
+ void(^work)(void));
+void dispatch_source_set_event_handler(dispatch_source_t ds, void(^work)(void));
+}
+
+#define GET_ASAN_BLOCK(work) \
+ void (^asan_block)(void); \
+ int parent_tid = asanThreadRegistry().GetCurrentTidOrInvalid(); \
+ asan_block = ^(void) { \
+ GET_STACK_TRACE_THREAD; \
+ asan_register_worker_thread(parent_tid, &stack); \
+ work(); \
+ }
+
+INTERCEPTOR(void, dispatch_async,
+ dispatch_queue_t dq, void(^work)(void)) {
+ GET_ASAN_BLOCK(work);
+ REAL(dispatch_async)(dq, asan_block);
+}
+
+INTERCEPTOR(void, dispatch_group_async,
+ dispatch_group_t dg, dispatch_queue_t dq, void(^work)(void)) {
+ GET_ASAN_BLOCK(work);
+ REAL(dispatch_group_async)(dg, dq, asan_block);
+}
+
+INTERCEPTOR(void, dispatch_after,
+ dispatch_time_t when, dispatch_queue_t queue, void(^work)(void)) {
+ GET_ASAN_BLOCK(work);
+ REAL(dispatch_after)(when, queue, asan_block);
+}
+
+INTERCEPTOR(void, dispatch_source_set_cancel_handler,
+ dispatch_source_t ds, void(^work)(void)) {
+ GET_ASAN_BLOCK(work);
+ REAL(dispatch_source_set_cancel_handler)(ds, asan_block);
+}
+
+INTERCEPTOR(void, dispatch_source_set_event_handler,
+ dispatch_source_t ds, void(^work)(void)) {
+ GET_ASAN_BLOCK(work);
+ REAL(dispatch_source_set_event_handler)(ds, asan_block);
+}
+#endif
+
+#endif // __APPLE__
diff --git a/gcc-4.8/libsanitizer/asan/asan_mac.h b/gcc-4.8/libsanitizer/asan/asan_mac.h
new file mode 100644
index 000000000..2c162fb0c
--- /dev/null
+++ b/gcc-4.8/libsanitizer/asan/asan_mac.h
@@ -0,0 +1,55 @@
+//===-- asan_mac.h ----------------------------------------------*- C++ -*-===//
+//
+// 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.
+//
+// Mac-specific ASan definitions.
+//===----------------------------------------------------------------------===//
+#ifndef ASAN_MAC_H
+#define ASAN_MAC_H
+
+// CF_RC_BITS, the layout of CFRuntimeBase and __CFStrIsConstant are internal
+// and subject to change in further CoreFoundation versions. Apple does not
+// guarantee any binary compatibility from release to release.
+
+// See http://opensource.apple.com/source/CF/CF-635.15/CFInternal.h
+#if defined(__BIG_ENDIAN__)
+#define CF_RC_BITS 0
+#endif
+
+#if defined(__LITTLE_ENDIAN__)
+#define CF_RC_BITS 3
+#endif
+
+// See http://opensource.apple.com/source/CF/CF-635.15/CFRuntime.h
+typedef struct __CFRuntimeBase {
+ uptr _cfisa;
+ u8 _cfinfo[4];
+#if __LP64__
+ u32 _rc;
+#endif
+} CFRuntimeBase;
+
+enum {
+ MACOS_VERSION_UNKNOWN = 0,
+ MACOS_VERSION_LEOPARD,
+ MACOS_VERSION_SNOW_LEOPARD,
+ MACOS_VERSION_LION,
+ MACOS_VERSION_MOUNTAIN_LION
+};
+
+// Used by asan_malloc_mac.cc and asan_mac.cc
+extern "C" void __CFInitialize();
+
+namespace __asan {
+
+int GetMacosVersion();
+void MaybeReplaceCFAllocator();
+
+} // namespace __asan
+
+#endif // ASAN_MAC_H
diff --git a/gcc-4.8/libsanitizer/asan/asan_malloc_linux.cc b/gcc-4.8/libsanitizer/asan/asan_malloc_linux.cc
new file mode 100644
index 000000000..18e6a3be8
--- /dev/null
+++ b/gcc-4.8/libsanitizer/asan/asan_malloc_linux.cc
@@ -0,0 +1,147 @@
+//===-- asan_malloc_linux.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.
+//
+// Linux-specific malloc interception.
+// We simply define functions like malloc, free, realloc, etc.
+// They will replace the corresponding libc functions automagically.
+//===----------------------------------------------------------------------===//
+#ifdef __linux__
+
+#include "asan_allocator.h"
+#include "asan_interceptors.h"
+#include "asan_internal.h"
+#include "asan_stack.h"
+#include "asan_thread_registry.h"
+
+#if ASAN_ANDROID
+DECLARE_REAL_AND_INTERCEPTOR(void*, malloc, uptr size)
+DECLARE_REAL_AND_INTERCEPTOR(void, free, void *ptr)
+DECLARE_REAL_AND_INTERCEPTOR(void*, calloc, uptr nmemb, uptr size)
+DECLARE_REAL_AND_INTERCEPTOR(void*, realloc, void *ptr, uptr size)
+DECLARE_REAL_AND_INTERCEPTOR(void*, memalign, uptr boundary, uptr size)
+
+struct MallocDebug {
+ void* (*malloc)(uptr bytes);
+ void (*free)(void* mem);
+ void* (*calloc)(uptr n_elements, uptr elem_size);
+ void* (*realloc)(void* oldMem, uptr bytes);
+ void* (*memalign)(uptr alignment, uptr bytes);
+};
+
+const MallocDebug asan_malloc_dispatch ALIGNED(32) = {
+ WRAP(malloc), WRAP(free), WRAP(calloc), WRAP(realloc), WRAP(memalign)
+};
+
+extern "C" const MallocDebug* __libc_malloc_dispatch;
+
+namespace __asan {
+void ReplaceSystemMalloc() {
+ __libc_malloc_dispatch = &asan_malloc_dispatch;
+}
+} // namespace __asan
+
+#else // ANDROID
+
+namespace __asan {
+void ReplaceSystemMalloc() {
+}
+} // namespace __asan
+#endif // ANDROID
+
+// ---------------------- Replacement functions ---------------- {{{1
+using namespace __asan; // NOLINT
+
+INTERCEPTOR(void, free, void *ptr) {
+ GET_STACK_TRACE_FREE;
+ asan_free(ptr, &stack, FROM_MALLOC);
+}
+
+INTERCEPTOR(void, cfree, void *ptr) {
+ GET_STACK_TRACE_FREE;
+ asan_free(ptr, &stack, FROM_MALLOC);
+}
+
+INTERCEPTOR(void*, malloc, uptr size) {
+ GET_STACK_TRACE_MALLOC;
+ return asan_malloc(size, &stack);
+}
+
+INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) {
+ if (!asan_inited) {
+ // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym.
+ const uptr kCallocPoolSize = 1024;
+ static uptr calloc_memory_for_dlsym[kCallocPoolSize];
+ static uptr allocated;
+ uptr size_in_words = ((nmemb * size) + kWordSize - 1) / kWordSize;
+ void *mem = (void*)&calloc_memory_for_dlsym[allocated];
+ allocated += size_in_words;
+ CHECK(allocated < kCallocPoolSize);
+ return mem;
+ }
+ GET_STACK_TRACE_MALLOC;
+ return asan_calloc(nmemb, size, &stack);
+}
+
+INTERCEPTOR(void*, realloc, void *ptr, uptr size) {
+ GET_STACK_TRACE_MALLOC;
+ return asan_realloc(ptr, size, &stack);
+}
+
+INTERCEPTOR(void*, memalign, uptr boundary, uptr size) {
+ GET_STACK_TRACE_MALLOC;
+ return asan_memalign(boundary, size, &stack, FROM_MALLOC);
+}
+
+INTERCEPTOR(void*, __libc_memalign, uptr align, uptr s)
+ ALIAS("memalign");
+
+INTERCEPTOR(uptr, malloc_usable_size, void *ptr) {
+ GET_STACK_TRACE_MALLOC;
+ return asan_malloc_usable_size(ptr, &stack);
+}
+
+// We avoid including malloc.h for portability reasons.
+// man mallinfo says the fields are "long", but the implementation uses int.
+// It doesn't matter much -- we just need to make sure that the libc's mallinfo
+// is not called.
+struct fake_mallinfo {
+ int x[10];
+};
+
+INTERCEPTOR(struct fake_mallinfo, mallinfo, void) {
+ struct fake_mallinfo res;
+ REAL(memset)(&res, 0, sizeof(res));
+ return res;
+}
+
+INTERCEPTOR(int, mallopt, int cmd, int value) {
+ return -1;
+}
+
+INTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) {
+ GET_STACK_TRACE_MALLOC;
+ // Printf("posix_memalign: %zx %zu\n", alignment, size);
+ return asan_posix_memalign(memptr, alignment, size, &stack);
+}
+
+INTERCEPTOR(void*, valloc, uptr size) {
+ GET_STACK_TRACE_MALLOC;
+ return asan_valloc(size, &stack);
+}
+
+INTERCEPTOR(void*, pvalloc, uptr size) {
+ GET_STACK_TRACE_MALLOC;
+ return asan_pvalloc(size, &stack);
+}
+
+INTERCEPTOR(void, malloc_stats, void) {
+ __asan_print_accumulated_stats();
+}
+
+#endif // __linux__
diff --git a/gcc-4.8/libsanitizer/asan/asan_malloc_mac.cc b/gcc-4.8/libsanitizer/asan/asan_malloc_mac.cc
new file mode 100644
index 000000000..3ae6c5946
--- /dev/null
+++ b/gcc-4.8/libsanitizer/asan/asan_malloc_mac.cc
@@ -0,0 +1,347 @@
+//===-- asan_malloc_mac.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.
+//
+// Mac-specific malloc interception.
+//===----------------------------------------------------------------------===//
+
+#ifdef __APPLE__
+
+#include <AvailabilityMacros.h>
+#include <CoreFoundation/CFBase.h>
+#include <dlfcn.h>
+#include <malloc/malloc.h>
+
+#include "asan_allocator.h"
+#include "asan_interceptors.h"
+#include "asan_internal.h"
+#include "asan_mac.h"
+#include "asan_report.h"
+#include "asan_stack.h"
+#include "asan_stats.h"
+#include "asan_thread_registry.h"
+
+// Similar code is used in Google Perftools,
+// http://code.google.com/p/google-perftools.
+
+// ---------------------- Replacement functions ---------------- {{{1
+using namespace __asan; // NOLINT
+
+// TODO(glider): do we need both zones?
+static malloc_zone_t *system_malloc_zone = 0;
+static malloc_zone_t asan_zone;
+
+INTERCEPTOR(malloc_zone_t *, malloc_create_zone,
+ vm_size_t start_size, unsigned zone_flags) {
+ if (!asan_inited) __asan_init();
+ GET_STACK_TRACE_MALLOC;
+ malloc_zone_t *new_zone =
+ (malloc_zone_t*)asan_malloc(sizeof(asan_zone), &stack);
+ internal_memcpy(new_zone, &asan_zone, sizeof(asan_zone));
+ new_zone->zone_name = NULL; // The name will be changed anyway.
+ return new_zone;
+}
+
+INTERCEPTOR(malloc_zone_t *, malloc_default_zone, void) {
+ if (!asan_inited) __asan_init();
+ return &asan_zone;
+}
+
+INTERCEPTOR(malloc_zone_t *, malloc_default_purgeable_zone, void) {
+ // FIXME: ASan should support purgeable allocations.
+ // https://code.google.com/p/address-sanitizer/issues/detail?id=139
+ if (!asan_inited) __asan_init();
+ return &asan_zone;
+}
+
+INTERCEPTOR(void, malloc_make_purgeable, void *ptr) {
+ // FIXME: ASan should support purgeable allocations. Ignoring them is fine
+ // for now.
+ if (!asan_inited) __asan_init();
+}
+
+INTERCEPTOR(int, malloc_make_nonpurgeable, void *ptr) {
+ // FIXME: ASan should support purgeable allocations. Ignoring them is fine
+ // for now.
+ if (!asan_inited) __asan_init();
+ // Must return 0 if the contents were not purged since the last call to
+ // malloc_make_purgeable().
+ return 0;
+}
+
+INTERCEPTOR(void, malloc_set_zone_name, malloc_zone_t *zone, const char *name) {
+ if (!asan_inited) __asan_init();
+ // Allocate |strlen("asan-") + 1 + internal_strlen(name)| bytes.
+ size_t buflen = 6 + (name ? internal_strlen(name) : 0);
+ InternalScopedBuffer<char> new_name(buflen);
+ if (name && zone->introspect == asan_zone.introspect) {
+ internal_snprintf(new_name.data(), buflen, "asan-%s", name);
+ name = new_name.data();
+ }
+
+ // Call the system malloc's implementation for both external and our zones,
+ // since that appropriately changes VM region protections on the zone.
+ REAL(malloc_set_zone_name)(zone, name);
+}
+
+INTERCEPTOR(void *, malloc, size_t size) {
+ if (!asan_inited) __asan_init();
+ GET_STACK_TRACE_MALLOC;
+ void *res = asan_malloc(size, &stack);
+ return res;
+}
+
+INTERCEPTOR(void, free, void *ptr) {
+ if (!asan_inited) __asan_init();
+ if (!ptr) return;
+ GET_STACK_TRACE_FREE;
+ asan_free(ptr, &stack, FROM_MALLOC);
+}
+
+INTERCEPTOR(void *, realloc, void *ptr, size_t size) {
+ if (!asan_inited) __asan_init();
+ GET_STACK_TRACE_MALLOC;
+ return asan_realloc(ptr, size, &stack);
+}
+
+INTERCEPTOR(void *, calloc, size_t nmemb, size_t size) {
+ if (!asan_inited) __asan_init();
+ GET_STACK_TRACE_MALLOC;
+ return asan_calloc(nmemb, size, &stack);
+}
+
+INTERCEPTOR(void *, valloc, size_t size) {
+ if (!asan_inited) __asan_init();
+ GET_STACK_TRACE_MALLOC;
+ return asan_memalign(GetPageSizeCached(), size, &stack, FROM_MALLOC);
+}
+
+INTERCEPTOR(size_t, malloc_good_size, size_t size) {
+ if (!asan_inited) __asan_init();
+ return asan_zone.introspect->good_size(&asan_zone, size);
+}
+
+INTERCEPTOR(int, posix_memalign, void **memptr, size_t alignment, size_t size) {
+ if (!asan_inited) __asan_init();
+ CHECK(memptr);
+ GET_STACK_TRACE_MALLOC;
+ void *result = asan_memalign(alignment, size, &stack, FROM_MALLOC);
+ if (result) {
+ *memptr = result;
+ return 0;
+ }
+ return -1;
+}
+
+namespace {
+
+// TODO(glider): the mz_* functions should be united with the Linux wrappers,
+// as they are basically copied from there.
+size_t mz_size(malloc_zone_t* zone, const void* ptr) {
+ return asan_mz_size(ptr);
+}
+
+void *mz_malloc(malloc_zone_t *zone, size_t size) {
+ if (!asan_inited) {
+ CHECK(system_malloc_zone);
+ return malloc_zone_malloc(system_malloc_zone, size);
+ }
+ GET_STACK_TRACE_MALLOC;
+ return asan_malloc(size, &stack);
+}
+
+void *mz_calloc(malloc_zone_t *zone, size_t nmemb, size_t size) {
+ if (!asan_inited) {
+ // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym.
+ const size_t kCallocPoolSize = 1024;
+ static uptr calloc_memory_for_dlsym[kCallocPoolSize];
+ static size_t allocated;
+ size_t size_in_words = ((nmemb * size) + kWordSize - 1) / kWordSize;
+ void *mem = (void*)&calloc_memory_for_dlsym[allocated];
+ allocated += size_in_words;
+ CHECK(allocated < kCallocPoolSize);
+ return mem;
+ }
+ GET_STACK_TRACE_MALLOC;
+ return asan_calloc(nmemb, size, &stack);
+}
+
+void *mz_valloc(malloc_zone_t *zone, size_t size) {
+ if (!asan_inited) {
+ CHECK(system_malloc_zone);
+ return malloc_zone_valloc(system_malloc_zone, size);
+ }
+ GET_STACK_TRACE_MALLOC;
+ return asan_memalign(GetPageSizeCached(), size, &stack, FROM_MALLOC);
+}
+
+#define GET_ZONE_FOR_PTR(ptr) \
+ malloc_zone_t *zone_ptr = malloc_zone_from_ptr(ptr); \
+ const char *zone_name = (zone_ptr == 0) ? 0 : zone_ptr->zone_name
+
+void ALWAYS_INLINE free_common(void *context, void *ptr) {
+ if (!ptr) return;
+ GET_STACK_TRACE_FREE;
+ // FIXME: need to retire this flag.
+ if (!flags()->mac_ignore_invalid_free) {
+ asan_free(ptr, &stack, FROM_MALLOC);
+ } else {
+ GET_ZONE_FOR_PTR(ptr);
+ WarnMacFreeUnallocated((uptr)ptr, (uptr)zone_ptr, zone_name, &stack);
+ return;
+ }
+}
+
+// TODO(glider): the allocation callbacks need to be refactored.
+void mz_free(malloc_zone_t *zone, void *ptr) {
+ free_common(zone, ptr);
+}
+
+void *mz_realloc(malloc_zone_t *zone, void *ptr, size_t size) {
+ if (!ptr) {
+ GET_STACK_TRACE_MALLOC;
+ return asan_malloc(size, &stack);
+ } else {
+ if (asan_mz_size(ptr)) {
+ GET_STACK_TRACE_MALLOC;
+ return asan_realloc(ptr, size, &stack);
+ } else {
+ // We can't recover from reallocating an unknown address, because
+ // this would require reading at most |size| bytes from
+ // potentially unaccessible memory.
+ GET_STACK_TRACE_FREE;
+ GET_ZONE_FOR_PTR(ptr);
+ ReportMacMzReallocUnknown((uptr)ptr, (uptr)zone_ptr, zone_name, &stack);
+ }
+ }
+}
+
+void mz_destroy(malloc_zone_t* zone) {
+ // A no-op -- we will not be destroyed!
+ Report("mz_destroy() called -- ignoring\n");
+}
+
+ // from AvailabilityMacros.h
+#if defined(MAC_OS_X_VERSION_10_6) && \
+ MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
+void *mz_memalign(malloc_zone_t *zone, size_t align, size_t size) {
+ if (!asan_inited) {
+ CHECK(system_malloc_zone);
+ return malloc_zone_memalign(system_malloc_zone, align, size);
+ }
+ GET_STACK_TRACE_MALLOC;
+ return asan_memalign(align, size, &stack, FROM_MALLOC);
+}
+
+// This function is currently unused, and we build with -Werror.
+#if 0
+void mz_free_definite_size(malloc_zone_t* zone, void *ptr, size_t size) {
+ // TODO(glider): check that |size| is valid.
+ UNIMPLEMENTED();
+}
+#endif
+#endif
+
+kern_return_t mi_enumerator(task_t task, void *,
+ unsigned type_mask, vm_address_t zone_address,
+ memory_reader_t reader,
+ vm_range_recorder_t recorder) {
+ // Should enumerate all the pointers we have. Seems like a lot of work.
+ return KERN_FAILURE;
+}
+
+size_t mi_good_size(malloc_zone_t *zone, size_t size) {
+ // I think it's always safe to return size, but we maybe could do better.
+ return size;
+}
+
+boolean_t mi_check(malloc_zone_t *zone) {
+ UNIMPLEMENTED();
+}
+
+void mi_print(malloc_zone_t *zone, boolean_t verbose) {
+ UNIMPLEMENTED();
+}
+
+void mi_log(malloc_zone_t *zone, void *address) {
+ // I don't think we support anything like this
+}
+
+void mi_force_lock(malloc_zone_t *zone) {
+ asan_mz_force_lock();
+}
+
+void mi_force_unlock(malloc_zone_t *zone) {
+ asan_mz_force_unlock();
+}
+
+void mi_statistics(malloc_zone_t *zone, malloc_statistics_t *stats) {
+ AsanMallocStats malloc_stats;
+ asanThreadRegistry().FillMallocStatistics(&malloc_stats);
+ CHECK(sizeof(malloc_statistics_t) == sizeof(AsanMallocStats));
+ internal_memcpy(stats, &malloc_stats, sizeof(malloc_statistics_t));
+}
+
+#if defined(MAC_OS_X_VERSION_10_6) && \
+ MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
+boolean_t mi_zone_locked(malloc_zone_t *zone) {
+ // UNIMPLEMENTED();
+ return false;
+}
+#endif
+
+} // unnamed namespace
+
+namespace __asan {
+
+void ReplaceSystemMalloc() {
+ static malloc_introspection_t asan_introspection;
+ // Ok to use internal_memset, these places are not performance-critical.
+ internal_memset(&asan_introspection, 0, sizeof(asan_introspection));
+
+ asan_introspection.enumerator = &mi_enumerator;
+ asan_introspection.good_size = &mi_good_size;
+ asan_introspection.check = &mi_check;
+ asan_introspection.print = &mi_print;
+ asan_introspection.log = &mi_log;
+ asan_introspection.force_lock = &mi_force_lock;
+ asan_introspection.force_unlock = &mi_force_unlock;
+ asan_introspection.statistics = &mi_statistics;
+
+ internal_memset(&asan_zone, 0, sizeof(malloc_zone_t));
+
+ // Start with a version 4 zone which is used for OS X 10.4 and 10.5.
+ asan_zone.version = 4;
+ asan_zone.zone_name = "asan";
+ asan_zone.size = &mz_size;
+ asan_zone.malloc = &mz_malloc;
+ asan_zone.calloc = &mz_calloc;
+ asan_zone.valloc = &mz_valloc;
+ asan_zone.free = &mz_free;
+ asan_zone.realloc = &mz_realloc;
+ asan_zone.destroy = &mz_destroy;
+ asan_zone.batch_malloc = 0;
+ asan_zone.batch_free = 0;
+ asan_zone.introspect = &asan_introspection;
+
+ // from AvailabilityMacros.h
+#if defined(MAC_OS_X_VERSION_10_6) && \
+ MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
+ // Switch to version 6 on OSX 10.6 to support memalign.
+ asan_zone.version = 6;
+ asan_zone.free_definite_size = 0;
+ asan_zone.memalign = &mz_memalign;
+ asan_introspection.zone_locked = &mi_zone_locked;
+#endif
+
+ // Register the ASan zone.
+ malloc_zone_register(&asan_zone);
+}
+} // namespace __asan
+
+#endif // __APPLE__
diff --git a/gcc-4.8/libsanitizer/asan/asan_malloc_win.cc b/gcc-4.8/libsanitizer/asan/asan_malloc_win.cc
new file mode 100644
index 000000000..437079f5d
--- /dev/null
+++ b/gcc-4.8/libsanitizer/asan/asan_malloc_win.cc
@@ -0,0 +1,140 @@
+//===-- asan_malloc_win.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.
+//
+// Windows-specific malloc interception.
+//===----------------------------------------------------------------------===//
+#ifdef _WIN32
+
+#include "asan_allocator.h"
+#include "asan_interceptors.h"
+#include "asan_internal.h"
+#include "asan_stack.h"
+#include "interception/interception.h"
+
+#include <stddef.h>
+
+// ---------------------- Replacement functions ---------------- {{{1
+using namespace __asan; // NOLINT
+
+// FIXME: Simply defining functions with the same signature in *.obj
+// files overrides the standard functions in *.lib
+// This works well for simple helloworld-like tests but might need to be
+// revisited in the future.
+
+extern "C" {
+void free(void *ptr) {
+ GET_STACK_TRACE_FREE;
+ return asan_free(ptr, &stack, FROM_MALLOC);
+}
+
+void _free_dbg(void* ptr, int) {
+ free(ptr);
+}
+
+void cfree(void *ptr) {
+ CHECK(!"cfree() should not be used on Windows?");
+}
+
+void *malloc(size_t size) {
+ GET_STACK_TRACE_MALLOC;
+ return asan_malloc(size, &stack);
+}
+
+void* _malloc_dbg(size_t size, int , const char*, int) {
+ return malloc(size);
+}
+
+void *calloc(size_t nmemb, size_t size) {
+ GET_STACK_TRACE_MALLOC;
+ return asan_calloc(nmemb, size, &stack);
+}
+
+void* _calloc_dbg(size_t n, size_t size, int, const char*, int) {
+ return calloc(n, size);
+}
+
+void *_calloc_impl(size_t nmemb, size_t size, int *errno_tmp) {
+ return calloc(nmemb, size);
+}
+
+void *realloc(void *ptr, size_t size) {
+ GET_STACK_TRACE_MALLOC;
+ return asan_realloc(ptr, size, &stack);
+}
+
+void *_realloc_dbg(void *ptr, size_t size, int) {
+ CHECK(!"_realloc_dbg should not exist!");
+ return 0;
+}
+
+void* _recalloc(void* p, size_t n, size_t elem_size) {
+ if (!p)
+ return calloc(n, elem_size);
+ const size_t size = n * elem_size;
+ if (elem_size != 0 && size / elem_size != n)
+ return 0;
+ return realloc(p, size);
+}
+
+size_t _msize(void *ptr) {
+ GET_STACK_TRACE_MALLOC;
+ return asan_malloc_usable_size(ptr, &stack);
+}
+
+int _CrtDbgReport(int, const char*, int,
+ const char*, const char*, ...) {
+ ShowStatsAndAbort();
+}
+
+int _CrtDbgReportW(int reportType, const wchar_t*, int,
+ const wchar_t*, const wchar_t*, ...) {
+ ShowStatsAndAbort();
+}
+
+int _CrtSetReportMode(int, int) {
+ return 0;
+}
+} // extern "C"
+
+using __interception::GetRealFunctionAddress;
+
+// We don't want to include "windows.h" in this file to avoid extra attributes
+// set on malloc/free etc (e.g. dllimport), so declare a few things manually:
+extern "C" int __stdcall VirtualProtect(void* addr, size_t size,
+ DWORD prot, DWORD *old_prot);
+const int PAGE_EXECUTE_READWRITE = 0x40;
+
+namespace __asan {
+void ReplaceSystemMalloc() {
+#if defined(_DLL)
+# ifdef _WIN64
+# error ReplaceSystemMalloc was not tested on x64
+# endif
+ char *crt_malloc;
+ if (GetRealFunctionAddress("malloc", (void**)&crt_malloc)) {
+ // Replace malloc in the CRT dll with a jump to our malloc.
+ DWORD old_prot, unused;
+ CHECK(VirtualProtect(crt_malloc, 16, PAGE_EXECUTE_READWRITE, &old_prot));
+ REAL(memset)(crt_malloc, 0xCC /* int 3 */, 16); // just in case.
+
+ ptrdiff_t jmp_offset = (char*)malloc - (char*)crt_malloc - 5;
+ crt_malloc[0] = 0xE9; // jmp, should be followed by an offset.
+ REAL(memcpy)(crt_malloc + 1, &jmp_offset, sizeof(jmp_offset));
+
+ CHECK(VirtualProtect(crt_malloc, 16, old_prot, &unused));
+
+ // FYI: FlushInstructionCache is needed on Itanium etc but not on x86/x64.
+ }
+
+ // FIXME: investigate whether anything else is needed.
+#endif
+}
+} // namespace __asan
+
+#endif // _WIN32
diff --git a/gcc-4.8/libsanitizer/asan/asan_mapping.h b/gcc-4.8/libsanitizer/asan/asan_mapping.h
new file mode 100644
index 000000000..9b4dd35f1
--- /dev/null
+++ b/gcc-4.8/libsanitizer/asan/asan_mapping.h
@@ -0,0 +1,222 @@
+//===-- asan_mapping.h ------------------------------------------*- C++ -*-===//
+//
+// 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.
+//
+// Defines ASan memory mapping.
+//===----------------------------------------------------------------------===//
+#ifndef ASAN_MAPPING_H
+#define ASAN_MAPPING_H
+
+#include "asan_internal.h"
+
+// The full explanation of the memory mapping could be found here:
+// http://code.google.com/p/address-sanitizer/wiki/AddressSanitizerAlgorithm
+//
+// Typical shadow mapping on Linux/x86_64 with SHADOW_OFFSET == 0x00007fff8000:
+// || `[0x10007fff8000, 0x7fffffffffff]` || HighMem ||
+// || `[0x02008fff7000, 0x10007fff7fff]` || HighShadow ||
+// || `[0x00008fff7000, 0x02008fff6fff]` || ShadowGap ||
+// || `[0x00007fff8000, 0x00008fff6fff]` || LowShadow ||
+// || `[0x000000000000, 0x00007fff7fff]` || LowMem ||
+//
+// When SHADOW_OFFSET is zero (-pie):
+// || `[0x100000000000, 0x7fffffffffff]` || HighMem ||
+// || `[0x020000000000, 0x0fffffffffff]` || HighShadow ||
+// || `[0x000000040000, 0x01ffffffffff]` || ShadowGap ||
+//
+// Special case when something is already mapped between
+// 0x003000000000 and 0x005000000000 (e.g. when prelink is installed):
+// || `[0x10007fff8000, 0x7fffffffffff]` || HighMem ||
+// || `[0x02008fff7000, 0x10007fff7fff]` || HighShadow ||
+// || `[0x005000000000, 0x02008fff6fff]` || ShadowGap3 ||
+// || `[0x003000000000, 0x004fffffffff]` || MidMem ||
+// || `[0x000a7fff8000, 0x002fffffffff]` || ShadowGap2 ||
+// || `[0x00067fff8000, 0x000a7fff7fff]` || MidShadow ||
+// || `[0x00008fff7000, 0x00067fff7fff]` || ShadowGap ||
+// || `[0x00007fff8000, 0x00008fff6fff]` || LowShadow ||
+// || `[0x000000000000, 0x00007fff7fff]` || LowMem ||
+//
+// Default Linux/i386 mapping:
+// || `[0x40000000, 0xffffffff]` || HighMem ||
+// || `[0x28000000, 0x3fffffff]` || HighShadow ||
+// || `[0x24000000, 0x27ffffff]` || ShadowGap ||
+// || `[0x20000000, 0x23ffffff]` || LowShadow ||
+// || `[0x00000000, 0x1fffffff]` || LowMem ||
+
+#if ASAN_FLEXIBLE_MAPPING_AND_OFFSET == 1
+extern SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_mapping_scale;
+extern SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_mapping_offset;
+# define SHADOW_SCALE (__asan_mapping_scale)
+# define SHADOW_OFFSET (__asan_mapping_offset)
+#else
+# if ASAN_ANDROID
+# define SHADOW_SCALE (3)
+# define SHADOW_OFFSET (0)
+# else
+# define SHADOW_SCALE (3)
+# if SANITIZER_WORDSIZE == 32
+# define SHADOW_OFFSET (1 << 29)
+# else
+# if defined(__powerpc64__)
+# define SHADOW_OFFSET (1ULL << 41)
+# else
+# if ASAN_MAC
+# define SHADOW_OFFSET (1ULL << 44)
+# else
+# define SHADOW_OFFSET 0x7fff8000ULL
+# endif
+# endif
+# endif
+# endif
+#endif // ASAN_FLEXIBLE_MAPPING_AND_OFFSET
+
+#define SHADOW_GRANULARITY (1ULL << SHADOW_SCALE)
+#define MEM_TO_SHADOW(mem) (((mem) >> SHADOW_SCALE) + (SHADOW_OFFSET))
+#define SHADOW_TO_MEM(shadow) (((shadow) - SHADOW_OFFSET) << SHADOW_SCALE)
+
+#define kLowMemBeg 0
+#define kLowMemEnd (SHADOW_OFFSET ? SHADOW_OFFSET - 1 : 0)
+
+#define kLowShadowBeg SHADOW_OFFSET
+#define kLowShadowEnd MEM_TO_SHADOW(kLowMemEnd)
+
+#define kHighMemBeg (MEM_TO_SHADOW(kHighMemEnd) + 1)
+
+#define kHighShadowBeg MEM_TO_SHADOW(kHighMemBeg)
+#define kHighShadowEnd MEM_TO_SHADOW(kHighMemEnd)
+
+# define kMidShadowBeg MEM_TO_SHADOW(kMidMemBeg)
+# define kMidShadowEnd MEM_TO_SHADOW(kMidMemEnd)
+
+// With the zero shadow base we can not actually map pages starting from 0.
+// This constant is somewhat arbitrary.
+#define kZeroBaseShadowStart (1 << 18)
+
+#define kShadowGapBeg (kLowShadowEnd ? kLowShadowEnd + 1 \
+ : kZeroBaseShadowStart)
+#define kShadowGapEnd ((kMidMemBeg ? kMidShadowBeg : kHighShadowBeg) - 1)
+
+#define kShadowGap2Beg (kMidMemBeg ? kMidShadowEnd + 1 : 0)
+#define kShadowGap2End (kMidMemBeg ? kMidMemBeg - 1 : 0)
+
+#define kShadowGap3Beg (kMidMemBeg ? kMidMemEnd + 1 : 0)
+#define kShadowGap3End (kMidMemBeg ? kHighShadowBeg - 1 : 0)
+
+#define DO_ASAN_MAPPING_PROFILE 0 // Set to 1 to profile the functions below.
+
+#if DO_ASAN_MAPPING_PROFILE
+# define PROFILE_ASAN_MAPPING() AsanMappingProfile[__LINE__]++;
+#else
+# define PROFILE_ASAN_MAPPING()
+#endif
+
+// If 1, all shadow boundaries are constants.
+// Don't set to 1 other than for testing.
+#define ASAN_FIXED_MAPPING 0
+
+namespace __asan {
+
+extern uptr AsanMappingProfile[];
+
+#if ASAN_FIXED_MAPPING
+// Fixed mapping for 64-bit Linux. Mostly used for performance comparison
+// with non-fixed mapping. As of r175253 (Feb 2013) the performance
+// difference between fixed and non-fixed mapping is below the noise level.
+static uptr kHighMemEnd = 0x7fffffffffffULL;
+static uptr kMidMemBeg = 0x3000000000ULL;
+static uptr kMidMemEnd = 0x4fffffffffULL;
+#else
+SANITIZER_INTERFACE_ATTRIBUTE
+extern uptr kHighMemEnd, kMidMemBeg, kMidMemEnd; // Initialized in __asan_init.
+#endif
+
+static inline bool AddrIsInLowMem(uptr a) {
+ PROFILE_ASAN_MAPPING();
+ return a < kLowMemEnd;
+}
+
+static inline bool AddrIsInLowShadow(uptr a) {
+ PROFILE_ASAN_MAPPING();
+ return a >= kLowShadowBeg && a <= kLowShadowEnd;
+}
+
+static inline bool AddrIsInHighMem(uptr a) {
+ PROFILE_ASAN_MAPPING();
+ return a >= kHighMemBeg && a <= kHighMemEnd;
+}
+
+static inline bool AddrIsInMidMem(uptr a) {
+ PROFILE_ASAN_MAPPING();
+ return kMidMemBeg && a >= kMidMemBeg && a <= kMidMemEnd;
+}
+
+static inline bool AddrIsInMem(uptr a) {
+ PROFILE_ASAN_MAPPING();
+ return AddrIsInLowMem(a) || AddrIsInMidMem(a) || AddrIsInHighMem(a);
+}
+
+static inline uptr MemToShadow(uptr p) {
+ PROFILE_ASAN_MAPPING();
+ CHECK(AddrIsInMem(p));
+ return MEM_TO_SHADOW(p);
+}
+
+static inline bool AddrIsInHighShadow(uptr a) {
+ PROFILE_ASAN_MAPPING();
+ return a >= kHighShadowBeg && a <= kHighMemEnd;
+}
+
+static inline bool AddrIsInMidShadow(uptr a) {
+ PROFILE_ASAN_MAPPING();
+ return kMidMemBeg && a >= kMidShadowBeg && a <= kMidMemEnd;
+}
+
+static inline bool AddrIsInShadow(uptr a) {
+ PROFILE_ASAN_MAPPING();
+ return AddrIsInLowShadow(a) || AddrIsInMidShadow(a) || AddrIsInHighShadow(a);
+}
+
+static inline bool AddrIsInShadowGap(uptr a) {
+ PROFILE_ASAN_MAPPING();
+ if (kMidMemBeg) {
+ if (a <= kShadowGapEnd)
+ return SHADOW_OFFSET == 0 || a >= kShadowGapBeg;
+ return (a >= kShadowGap2Beg && a <= kShadowGap2End) ||
+ (a >= kShadowGap3Beg && a <= kShadowGap3End);
+ }
+ // In zero-based shadow mode we treat addresses near zero as addresses
+ // in shadow gap as well.
+ if (SHADOW_OFFSET == 0)
+ return a <= kShadowGapEnd;
+ return a >= kShadowGapBeg && a <= kShadowGapEnd;
+}
+
+static inline bool AddrIsAlignedByGranularity(uptr a) {
+ PROFILE_ASAN_MAPPING();
+ return (a & (SHADOW_GRANULARITY - 1)) == 0;
+}
+
+static inline bool AddressIsPoisoned(uptr a) {
+ PROFILE_ASAN_MAPPING();
+ const uptr kAccessSize = 1;
+ u8 *shadow_address = (u8*)MEM_TO_SHADOW(a);
+ s8 shadow_value = *shadow_address;
+ if (shadow_value) {
+ u8 last_accessed_byte = (a & (SHADOW_GRANULARITY - 1))
+ + kAccessSize - 1;
+ return (last_accessed_byte >= shadow_value);
+ }
+ return false;
+}
+
+// Must be after all calls to PROFILE_ASAN_MAPPING().
+static const uptr kAsanMappingProfileSize = __LINE__;
+
+} // namespace __asan
+
+#endif // ASAN_MAPPING_H
diff --git a/gcc-4.8/libsanitizer/asan/asan_new_delete.cc b/gcc-4.8/libsanitizer/asan/asan_new_delete.cc
new file mode 100644
index 000000000..fd47eee42
--- /dev/null
+++ b/gcc-4.8/libsanitizer/asan/asan_new_delete.cc
@@ -0,0 +1,67 @@
+//===-- asan_interceptors.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.
+//
+// Interceptors for operators new and delete.
+//===----------------------------------------------------------------------===//
+
+#include "asan_allocator.h"
+#include "asan_internal.h"
+#include "asan_stack.h"
+
+#include <stddef.h>
+
+namespace __asan {
+// This function is a no-op. We need it to make sure that object file
+// with our replacements will actually be loaded from static ASan
+// run-time library at link-time.
+void ReplaceOperatorsNewAndDelete() { }
+}
+
+using namespace __asan; // NOLINT
+
+// On Android new() goes through malloc interceptors.
+// See also https://code.google.com/p/address-sanitizer/issues/detail?id=131.
+#if !ASAN_ANDROID
+
+// Fake std::nothrow_t to avoid including <new>.
+namespace std {
+struct nothrow_t {};
+} // namespace std
+
+#define OPERATOR_NEW_BODY(type) \
+ GET_STACK_TRACE_MALLOC;\
+ return asan_memalign(0, size, &stack, type);
+
+INTERCEPTOR_ATTRIBUTE
+void *operator new(size_t size) { OPERATOR_NEW_BODY(FROM_NEW); }
+INTERCEPTOR_ATTRIBUTE
+void *operator new[](size_t size) { OPERATOR_NEW_BODY(FROM_NEW_BR); }
+INTERCEPTOR_ATTRIBUTE
+void *operator new(size_t size, std::nothrow_t const&)
+{ OPERATOR_NEW_BODY(FROM_NEW); }
+INTERCEPTOR_ATTRIBUTE
+void *operator new[](size_t size, std::nothrow_t const&)
+{ OPERATOR_NEW_BODY(FROM_NEW_BR); }
+
+#define OPERATOR_DELETE_BODY(type) \
+ GET_STACK_TRACE_FREE;\
+ asan_free(ptr, &stack, type);
+
+INTERCEPTOR_ATTRIBUTE
+void operator delete(void *ptr) { OPERATOR_DELETE_BODY(FROM_NEW); }
+INTERCEPTOR_ATTRIBUTE
+void operator delete[](void *ptr) { OPERATOR_DELETE_BODY(FROM_NEW_BR); }
+INTERCEPTOR_ATTRIBUTE
+void operator delete(void *ptr, std::nothrow_t const&)
+{ OPERATOR_DELETE_BODY(FROM_NEW); }
+INTERCEPTOR_ATTRIBUTE
+void operator delete[](void *ptr, std::nothrow_t const&)
+{ OPERATOR_DELETE_BODY(FROM_NEW_BR); }
+
+#endif
diff --git a/gcc-4.8/libsanitizer/asan/asan_poisoning.cc b/gcc-4.8/libsanitizer/asan/asan_poisoning.cc
new file mode 100644
index 000000000..7e930034b
--- /dev/null
+++ b/gcc-4.8/libsanitizer/asan/asan_poisoning.cc
@@ -0,0 +1,217 @@
+//===-- asan_poisoning.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.
+//
+// Shadow memory poisoning by ASan RTL and by user application.
+//===----------------------------------------------------------------------===//
+
+#include "asan_interceptors.h"
+#include "asan_internal.h"
+#include "asan_mapping.h"
+#include "sanitizer_common/sanitizer_libc.h"
+
+namespace __asan {
+
+void PoisonShadow(uptr addr, uptr size, u8 value) {
+ if (!flags()->poison_heap) return;
+ CHECK(AddrIsAlignedByGranularity(addr));
+ CHECK(AddrIsAlignedByGranularity(addr + size));
+ uptr shadow_beg = MemToShadow(addr);
+ uptr shadow_end = MemToShadow(addr + size - SHADOW_GRANULARITY) + 1;
+ CHECK(REAL(memset) != 0);
+ REAL(memset)((void*)shadow_beg, value, shadow_end - shadow_beg);
+}
+
+void PoisonShadowPartialRightRedzone(uptr addr,
+ uptr size,
+ uptr redzone_size,
+ u8 value) {
+ if (!flags()->poison_heap) return;
+ CHECK(AddrIsAlignedByGranularity(addr));
+ u8 *shadow = (u8*)MemToShadow(addr);
+ for (uptr i = 0; i < redzone_size;
+ i += SHADOW_GRANULARITY, shadow++) {
+ if (i + SHADOW_GRANULARITY <= size) {
+ *shadow = 0; // fully addressable
+ } else if (i >= size) {
+ *shadow = (SHADOW_GRANULARITY == 128) ? 0xff : value; // unaddressable
+ } else {
+ *shadow = size - i; // first size-i bytes are addressable
+ }
+ }
+}
+
+
+struct ShadowSegmentEndpoint {
+ u8 *chunk;
+ s8 offset; // in [0, SHADOW_GRANULARITY)
+ s8 value; // = *chunk;
+
+ explicit ShadowSegmentEndpoint(uptr address) {
+ chunk = (u8*)MemToShadow(address);
+ offset = address & (SHADOW_GRANULARITY - 1);
+ value = *chunk;
+ }
+};
+
+} // namespace __asan
+
+// ---------------------- Interface ---------------- {{{1
+using namespace __asan; // NOLINT
+
+// Current implementation of __asan_(un)poison_memory_region doesn't check
+// that user program (un)poisons the memory it owns. It poisons memory
+// conservatively, and unpoisons progressively to make sure asan shadow
+// mapping invariant is preserved (see detailed mapping description here:
+// http://code.google.com/p/address-sanitizer/wiki/AddressSanitizerAlgorithm).
+//
+// * if user asks to poison region [left, right), the program poisons
+// at least [left, AlignDown(right)).
+// * if user asks to unpoison region [left, right), the program unpoisons
+// at most [AlignDown(left), right).
+void __asan_poison_memory_region(void const volatile *addr, uptr size) {
+ if (!flags()->allow_user_poisoning || size == 0) return;
+ uptr beg_addr = (uptr)addr;
+ uptr end_addr = beg_addr + size;
+ if (flags()->verbosity >= 1) {
+ Printf("Trying to poison memory region [%p, %p)\n",
+ (void*)beg_addr, (void*)end_addr);
+ }
+ ShadowSegmentEndpoint beg(beg_addr);
+ ShadowSegmentEndpoint end(end_addr);
+ if (beg.chunk == end.chunk) {
+ CHECK(beg.offset < end.offset);
+ s8 value = beg.value;
+ CHECK(value == end.value);
+ // We can only poison memory if the byte in end.offset is unaddressable.
+ // No need to re-poison memory if it is poisoned already.
+ if (value > 0 && value <= end.offset) {
+ if (beg.offset > 0) {
+ *beg.chunk = Min(value, beg.offset);
+ } else {
+ *beg.chunk = kAsanUserPoisonedMemoryMagic;
+ }
+ }
+ return;
+ }
+ CHECK(beg.chunk < end.chunk);
+ if (beg.offset > 0) {
+ // Mark bytes from beg.offset as unaddressable.
+ if (beg.value == 0) {
+ *beg.chunk = beg.offset;
+ } else {
+ *beg.chunk = Min(beg.value, beg.offset);
+ }
+ beg.chunk++;
+ }
+ REAL(memset)(beg.chunk, kAsanUserPoisonedMemoryMagic, end.chunk - beg.chunk);
+ // Poison if byte in end.offset is unaddressable.
+ if (end.value > 0 && end.value <= end.offset) {
+ *end.chunk = kAsanUserPoisonedMemoryMagic;
+ }
+}
+
+void __asan_unpoison_memory_region(void const volatile *addr, uptr size) {
+ if (!flags()->allow_user_poisoning || size == 0) return;
+ uptr beg_addr = (uptr)addr;
+ uptr end_addr = beg_addr + size;
+ if (flags()->verbosity >= 1) {
+ Printf("Trying to unpoison memory region [%p, %p)\n",
+ (void*)beg_addr, (void*)end_addr);
+ }
+ ShadowSegmentEndpoint beg(beg_addr);
+ ShadowSegmentEndpoint end(end_addr);
+ if (beg.chunk == end.chunk) {
+ CHECK(beg.offset < end.offset);
+ s8 value = beg.value;
+ CHECK(value == end.value);
+ // We unpoison memory bytes up to enbytes up to end.offset if it is not
+ // unpoisoned already.
+ if (value != 0) {
+ *beg.chunk = Max(value, end.offset);
+ }
+ return;
+ }
+ CHECK(beg.chunk < end.chunk);
+ if (beg.offset > 0) {
+ *beg.chunk = 0;
+ beg.chunk++;
+ }
+ REAL(memset)(beg.chunk, 0, end.chunk - beg.chunk);
+ if (end.offset > 0 && end.value != 0) {
+ *end.chunk = Max(end.value, end.offset);
+ }
+}
+
+bool __asan_address_is_poisoned(void const volatile *addr) {
+ return __asan::AddressIsPoisoned((uptr)addr);
+}
+
+uptr __asan_region_is_poisoned(uptr beg, uptr size) {
+ if (!size) return 0;
+ uptr end = beg + size;
+ if (!AddrIsInMem(beg)) return beg;
+ if (!AddrIsInMem(end)) return end;
+ uptr aligned_b = RoundUpTo(beg, SHADOW_GRANULARITY);
+ uptr aligned_e = RoundDownTo(end, SHADOW_GRANULARITY);
+ uptr shadow_beg = MemToShadow(aligned_b);
+ uptr shadow_end = MemToShadow(aligned_e);
+ // First check the first and the last application bytes,
+ // then check the SHADOW_GRANULARITY-aligned region by calling
+ // mem_is_zero on the corresponding shadow.
+ if (!__asan::AddressIsPoisoned(beg) &&
+ !__asan::AddressIsPoisoned(end - 1) &&
+ (shadow_end <= shadow_beg ||
+ __sanitizer::mem_is_zero((const char *)shadow_beg,
+ shadow_end - shadow_beg)))
+ return 0;
+ // The fast check failed, so we have a poisoned byte somewhere.
+ // Find it slowly.
+ for (; beg < end; beg++)
+ if (__asan::AddressIsPoisoned(beg))
+ return beg;
+ UNREACHABLE("mem_is_zero returned false, but poisoned byte was not found");
+ return 0;
+}
+
+// This is a simplified version of __asan_(un)poison_memory_region, which
+// assumes that left border of region to be poisoned is properly aligned.
+static void PoisonAlignedStackMemory(uptr addr, uptr size, bool do_poison) {
+ if (size == 0) return;
+ uptr aligned_size = size & ~(SHADOW_GRANULARITY - 1);
+ PoisonShadow(addr, aligned_size,
+ do_poison ? kAsanStackUseAfterScopeMagic : 0);
+ if (size == aligned_size)
+ return;
+ s8 end_offset = (s8)(size - aligned_size);
+ s8* shadow_end = (s8*)MemToShadow(addr + aligned_size);
+ s8 end_value = *shadow_end;
+ if (do_poison) {
+ // If possible, mark all the bytes mapping to last shadow byte as
+ // unaddressable.
+ if (end_value > 0 && end_value <= end_offset)
+ *shadow_end = (s8)kAsanStackUseAfterScopeMagic;
+ } else {
+ // If necessary, mark few first bytes mapping to last shadow byte
+ // as addressable
+ if (end_value != 0)
+ *shadow_end = Max(end_value, end_offset);
+ }
+}
+
+void __asan_poison_stack_memory(uptr addr, uptr size) {
+ if (flags()->verbosity > 0)
+ Report("poisoning: %p %zx\n", (void*)addr, size);
+ PoisonAlignedStackMemory(addr, size, true);
+}
+
+void __asan_unpoison_stack_memory(uptr addr, uptr size) {
+ if (flags()->verbosity > 0)
+ Report("unpoisoning: %p %zx\n", (void*)addr, size);
+ PoisonAlignedStackMemory(addr, size, false);
+}
diff --git a/gcc-4.8/libsanitizer/asan/asan_posix.cc b/gcc-4.8/libsanitizer/asan/asan_posix.cc
new file mode 100644
index 000000000..177b84ae6
--- /dev/null
+++ b/gcc-4.8/libsanitizer/asan/asan_posix.cc
@@ -0,0 +1,118 @@
+//===-- asan_linux.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.
+//
+// Posix-specific details.
+//===----------------------------------------------------------------------===//
+#if defined(__linux__) || defined(__APPLE__)
+
+#include "asan_internal.h"
+#include "asan_interceptors.h"
+#include "asan_mapping.h"
+#include "asan_report.h"
+#include "asan_stack.h"
+#include "asan_thread_registry.h"
+#include "sanitizer_common/sanitizer_libc.h"
+#include "sanitizer_common/sanitizer_procmaps.h"
+
+#include <pthread.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <unistd.h>
+
+static const uptr kAltStackSize = SIGSTKSZ * 4; // SIGSTKSZ is not enough.
+
+namespace __asan {
+
+static void MaybeInstallSigaction(int signum,
+ void (*handler)(int, siginfo_t *, void *)) {
+ if (!AsanInterceptsSignal(signum))
+ return;
+ struct sigaction sigact;
+ REAL(memset)(&sigact, 0, sizeof(sigact));
+ sigact.sa_sigaction = handler;
+ sigact.sa_flags = SA_SIGINFO;
+ if (flags()->use_sigaltstack) sigact.sa_flags |= SA_ONSTACK;
+ CHECK(0 == REAL(sigaction)(signum, &sigact, 0));
+ if (flags()->verbosity >= 1) {
+ Report("Installed the sigaction for signal %d\n", signum);
+ }
+}
+
+static void ASAN_OnSIGSEGV(int, siginfo_t *siginfo, void *context) {
+ uptr addr = (uptr)siginfo->si_addr;
+ // Write the first message using the bullet-proof write.
+ if (13 != internal_write(2, "ASAN:SIGSEGV\n", 13)) Die();
+ uptr pc, sp, bp;
+ GetPcSpBp(context, &pc, &sp, &bp);
+ ReportSIGSEGV(pc, sp, bp, addr);
+}
+
+void SetAlternateSignalStack() {
+ stack_t altstack, oldstack;
+ CHECK(0 == sigaltstack(0, &oldstack));
+ // If the alternate stack is already in place, do nothing.
+ if ((oldstack.ss_flags & SS_DISABLE) == 0) return;
+ // TODO(glider): the mapped stack should have the MAP_STACK flag in the
+ // future. It is not required by man 2 sigaltstack now (they're using
+ // malloc()).
+ void* base = MmapOrDie(kAltStackSize, __FUNCTION__);
+ altstack.ss_sp = base;
+ altstack.ss_flags = 0;
+ altstack.ss_size = kAltStackSize;
+ CHECK(0 == sigaltstack(&altstack, 0));
+ if (flags()->verbosity > 0) {
+ Report("Alternative stack for T%d set: [%p,%p)\n",
+ asanThreadRegistry().GetCurrentTidOrInvalid(),
+ altstack.ss_sp, (char*)altstack.ss_sp + altstack.ss_size);
+ }
+}
+
+void UnsetAlternateSignalStack() {
+ stack_t altstack, oldstack;
+ altstack.ss_sp = 0;
+ altstack.ss_flags = SS_DISABLE;
+ altstack.ss_size = 0;
+ CHECK(0 == sigaltstack(&altstack, &oldstack));
+ UnmapOrDie(oldstack.ss_sp, oldstack.ss_size);
+}
+
+void InstallSignalHandlers() {
+ // Set the alternate signal stack for the main thread.
+ // This will cause SetAlternateSignalStack to be called twice, but the stack
+ // will be actually set only once.
+ if (flags()->use_sigaltstack) SetAlternateSignalStack();
+ MaybeInstallSigaction(SIGSEGV, ASAN_OnSIGSEGV);
+ MaybeInstallSigaction(SIGBUS, ASAN_OnSIGSEGV);
+}
+
+// ---------------------- TSD ---------------- {{{1
+
+static pthread_key_t tsd_key;
+static bool tsd_key_inited = false;
+void AsanTSDInit(void (*destructor)(void *tsd)) {
+ CHECK(!tsd_key_inited);
+ tsd_key_inited = true;
+ CHECK(0 == pthread_key_create(&tsd_key, destructor));
+}
+
+void *AsanTSDGet() {
+ CHECK(tsd_key_inited);
+ return pthread_getspecific(tsd_key);
+}
+
+void AsanTSDSet(void *tsd) {
+ CHECK(tsd_key_inited);
+ pthread_setspecific(tsd_key, tsd);
+}
+
+} // namespace __asan
+
+#endif // __linux__ || __APPLE_
diff --git a/gcc-4.8/libsanitizer/asan/asan_preinit.cc b/gcc-4.8/libsanitizer/asan/asan_preinit.cc
new file mode 100644
index 000000000..40309fa38
--- /dev/null
+++ b/gcc-4.8/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/gcc-4.8/libsanitizer/asan/asan_report.cc b/gcc-4.8/libsanitizer/asan/asan_report.cc
new file mode 100644
index 000000000..13e94c421
--- /dev/null
+++ b/gcc-4.8/libsanitizer/asan/asan_report.cc
@@ -0,0 +1,717 @@
+//===-- asan_report.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.
+//
+// This file contains error reporting code.
+//===----------------------------------------------------------------------===//
+#include "asan_flags.h"
+#include "asan_internal.h"
+#include "asan_mapping.h"
+#include "asan_report.h"
+#include "asan_stack.h"
+#include "asan_thread.h"
+#include "asan_thread_registry.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_report_decorator.h"
+#include "sanitizer_common/sanitizer_symbolizer.h"
+
+namespace __asan {
+
+// -------------------- User-specified callbacks ----------------- {{{1
+static void (*error_report_callback)(const char*);
+static char *error_message_buffer = 0;
+static uptr error_message_buffer_pos = 0;
+static uptr error_message_buffer_size = 0;
+
+void AppendToErrorMessageBuffer(const char *buffer) {
+ if (error_message_buffer) {
+ uptr length = internal_strlen(buffer);
+ CHECK_GE(error_message_buffer_size, error_message_buffer_pos);
+ uptr remaining = error_message_buffer_size - error_message_buffer_pos;
+ internal_strncpy(error_message_buffer + error_message_buffer_pos,
+ buffer, remaining);
+ error_message_buffer[error_message_buffer_size - 1] = '\0';
+ // FIXME: reallocate the buffer instead of truncating the message.
+ error_message_buffer_pos += remaining > length ? length : remaining;
+ }
+}
+
+// ---------------------- Decorator ------------------------------ {{{1
+bool PrintsToTtyCached() {
+ static int cached = 0;
+ static bool prints_to_tty;
+ if (!cached) { // Ok wrt threads since we are printing only from one thread.
+ prints_to_tty = PrintsToTty();
+ cached = 1;
+ }
+ return prints_to_tty;
+}
+class Decorator: private __sanitizer::AnsiColorDecorator {
+ public:
+ Decorator() : __sanitizer::AnsiColorDecorator(PrintsToTtyCached()) { }
+ const char *Warning() { return Red(); }
+ const char *EndWarning() { return Default(); }
+ const char *Access() { return Blue(); }
+ const char *EndAccess() { return Default(); }
+ const char *Location() { return Green(); }
+ const char *EndLocation() { return Default(); }
+ const char *Allocation() { return Magenta(); }
+ const char *EndAllocation() { return Default(); }
+
+ const char *ShadowByte(u8 byte) {
+ switch (byte) {
+ case kAsanHeapLeftRedzoneMagic:
+ case kAsanHeapRightRedzoneMagic:
+ return Red();
+ case kAsanHeapFreeMagic:
+ return Magenta();
+ case kAsanStackLeftRedzoneMagic:
+ case kAsanStackMidRedzoneMagic:
+ case kAsanStackRightRedzoneMagic:
+ case kAsanStackPartialRedzoneMagic:
+ return Red();
+ case kAsanStackAfterReturnMagic:
+ return Magenta();
+ case kAsanInitializationOrderMagic:
+ return Cyan();
+ case kAsanUserPoisonedMemoryMagic:
+ return Blue();
+ case kAsanStackUseAfterScopeMagic:
+ return Magenta();
+ case kAsanGlobalRedzoneMagic:
+ return Red();
+ case kAsanInternalHeapMagic:
+ return Yellow();
+ default:
+ return Default();
+ }
+ }
+ const char *EndShadowByte() { return Default(); }
+};
+
+// ---------------------- Helper functions ----------------------- {{{1
+
+static void PrintShadowByte(const char *before, u8 byte,
+ const char *after = "\n") {
+ Decorator d;
+ Printf("%s%s%x%x%s%s", before,
+ d.ShadowByte(byte), byte >> 4, byte & 15, d.EndShadowByte(), after);
+}
+
+static void PrintShadowBytes(const char *before, u8 *bytes,
+ u8 *guilty, uptr n) {
+ Decorator d;
+ if (before)
+ Printf("%s%p:", before, bytes);
+ for (uptr i = 0; i < n; i++) {
+ u8 *p = bytes + i;
+ const char *before = p == guilty ? "[" :
+ p - 1 == guilty ? "" : " ";
+ const char *after = p == guilty ? "]" : "";
+ PrintShadowByte(before, *p, after);
+ }
+ Printf("\n");
+}
+
+static void PrintLegend() {
+ Printf("Shadow byte legend (one shadow byte represents %d "
+ "application bytes):\n", (int)SHADOW_GRANULARITY);
+ PrintShadowByte(" Addressable: ", 0);
+ Printf(" Partially addressable: ");
+ for (uptr i = 1; i < SHADOW_GRANULARITY; i++)
+ PrintShadowByte("", i, " ");
+ Printf("\n");
+ PrintShadowByte(" Heap left redzone: ", kAsanHeapLeftRedzoneMagic);
+ PrintShadowByte(" Heap righ redzone: ", kAsanHeapRightRedzoneMagic);
+ PrintShadowByte(" Freed Heap region: ", kAsanHeapFreeMagic);
+ PrintShadowByte(" Stack left redzone: ", kAsanStackLeftRedzoneMagic);
+ PrintShadowByte(" Stack mid redzone: ", kAsanStackMidRedzoneMagic);
+ PrintShadowByte(" Stack right redzone: ", kAsanStackRightRedzoneMagic);
+ PrintShadowByte(" Stack partial redzone: ", kAsanStackPartialRedzoneMagic);
+ PrintShadowByte(" Stack after return: ", kAsanStackAfterReturnMagic);
+ PrintShadowByte(" Stack use after scope: ", kAsanStackUseAfterScopeMagic);
+ PrintShadowByte(" Global redzone: ", kAsanGlobalRedzoneMagic);
+ PrintShadowByte(" Global init order: ", kAsanInitializationOrderMagic);
+ PrintShadowByte(" Poisoned by user: ", kAsanUserPoisonedMemoryMagic);
+ PrintShadowByte(" ASan internal: ", kAsanInternalHeapMagic);
+}
+
+static void PrintShadowMemoryForAddress(uptr addr) {
+ if (!AddrIsInMem(addr))
+ return;
+ uptr shadow_addr = MemToShadow(addr);
+ const uptr n_bytes_per_row = 16;
+ uptr aligned_shadow = shadow_addr & ~(n_bytes_per_row - 1);
+ Printf("Shadow bytes around the buggy address:\n");
+ for (int i = -5; i <= 5; i++) {
+ const char *prefix = (i == 0) ? "=>" : " ";
+ PrintShadowBytes(prefix,
+ (u8*)(aligned_shadow + i * n_bytes_per_row),
+ (u8*)shadow_addr, n_bytes_per_row);
+ }
+ if (flags()->print_legend)
+ PrintLegend();
+}
+
+static void PrintZoneForPointer(uptr ptr, uptr zone_ptr,
+ const char *zone_name) {
+ if (zone_ptr) {
+ if (zone_name) {
+ Printf("malloc_zone_from_ptr(%p) = %p, which is %s\n",
+ ptr, zone_ptr, zone_name);
+ } else {
+ Printf("malloc_zone_from_ptr(%p) = %p, which doesn't have a name\n",
+ ptr, zone_ptr);
+ }
+ } else {
+ Printf("malloc_zone_from_ptr(%p) = 0\n", ptr);
+ }
+}
+
+// ---------------------- Address Descriptions ------------------- {{{1
+
+static bool IsASCII(unsigned char c) {
+ return /*0x00 <= c &&*/ c <= 0x7F;
+}
+
+// Check if the global is a zero-terminated ASCII string. If so, print it.
+static void PrintGlobalNameIfASCII(const __asan_global &g) {
+ for (uptr p = g.beg; p < g.beg + g.size - 1; p++) {
+ if (!IsASCII(*(unsigned char*)p)) return;
+ }
+ if (*(char*)(g.beg + g.size - 1) != 0) return;
+ Printf(" '%s' is ascii string '%s'\n", g.name, (char*)g.beg);
+}
+
+bool DescribeAddressRelativeToGlobal(uptr addr, uptr size,
+ const __asan_global &g) {
+ static const uptr kMinimalDistanceFromAnotherGlobal = 64;
+ if (addr <= g.beg - kMinimalDistanceFromAnotherGlobal) return false;
+ if (addr >= g.beg + g.size_with_redzone) return false;
+ Decorator d;
+ Printf("%s", d.Location());
+ if (addr < g.beg) {
+ Printf("%p is located %zd bytes to the left", (void*)addr, g.beg - addr);
+ } else if (addr + size > g.beg + g.size) {
+ if (addr < g.beg + g.size)
+ addr = g.beg + g.size;
+ Printf("%p is located %zd bytes to the right", (void*)addr,
+ addr - (g.beg + g.size));
+ } else {
+ // Can it happen?
+ Printf("%p is located %zd bytes inside", (void*)addr, addr - g.beg);
+ }
+ Printf(" of global variable '%s' (0x%zx) of size %zu\n",
+ g.name, g.beg, g.size);
+ Printf("%s", d.EndLocation());
+ PrintGlobalNameIfASCII(g);
+ return true;
+}
+
+bool DescribeAddressIfShadow(uptr addr) {
+ if (AddrIsInMem(addr))
+ return false;
+ static const char kAddrInShadowReport[] =
+ "Address %p is located in the %s.\n";
+ if (AddrIsInShadowGap(addr)) {
+ Printf(kAddrInShadowReport, addr, "shadow gap area");
+ return true;
+ }
+ if (AddrIsInHighShadow(addr)) {
+ Printf(kAddrInShadowReport, addr, "high shadow area");
+ return true;
+ }
+ if (AddrIsInLowShadow(addr)) {
+ Printf(kAddrInShadowReport, addr, "low shadow area");
+ return true;
+ }
+ CHECK(0 && "Address is not in memory and not in shadow?");
+ return false;
+}
+
+bool DescribeAddressIfStack(uptr addr, uptr access_size) {
+ AsanThread *t = asanThreadRegistry().FindThreadByStackAddress(addr);
+ if (!t) return false;
+ const sptr kBufSize = 4095;
+ char buf[kBufSize];
+ uptr offset = 0;
+ const char *frame_descr = t->GetFrameNameByAddr(addr, &offset);
+ // This string is created by the compiler and has the following form:
+ // "FunctioName n alloc_1 alloc_2 ... alloc_n"
+ // where alloc_i looks like "offset size len ObjectName ".
+ CHECK(frame_descr);
+ // Report the function name and the offset.
+ const char *name_end = internal_strchr(frame_descr, ' ');
+ CHECK(name_end);
+ buf[0] = 0;
+ internal_strncat(buf, frame_descr,
+ Min(kBufSize,
+ static_cast<sptr>(name_end - frame_descr)));
+ Decorator d;
+ Printf("%s", d.Location());
+ Printf("Address %p is located at offset %zu "
+ "in frame <%s> of T%d's stack:\n",
+ (void*)addr, offset, Demangle(buf), t->tid());
+ Printf("%s", d.EndLocation());
+ // Report the number of stack objects.
+ char *p;
+ uptr n_objects = internal_simple_strtoll(name_end, &p, 10);
+ CHECK(n_objects > 0);
+ Printf(" This frame has %zu object(s):\n", n_objects);
+ // Report all objects in this frame.
+ for (uptr i = 0; i < n_objects; i++) {
+ uptr beg, size;
+ sptr len;
+ beg = internal_simple_strtoll(p, &p, 10);
+ size = internal_simple_strtoll(p, &p, 10);
+ len = internal_simple_strtoll(p, &p, 10);
+ if (beg <= 0 || size <= 0 || len < 0 || *p != ' ') {
+ Printf("AddressSanitizer can't parse the stack frame "
+ "descriptor: |%s|\n", frame_descr);
+ break;
+ }
+ p++;
+ buf[0] = 0;
+ internal_strncat(buf, p, Min(kBufSize, len));
+ p += len;
+ Printf(" [%zu, %zu) '%s'\n", beg, beg + size, buf);
+ }
+ Printf("HINT: this may be a false positive if your program uses "
+ "some custom stack unwind mechanism or swapcontext\n"
+ " (longjmp and C++ exceptions *are* supported)\n");
+ DescribeThread(t->summary());
+ return true;
+}
+
+static void DescribeAccessToHeapChunk(AsanChunkView chunk, uptr addr,
+ uptr access_size) {
+ sptr offset;
+ Decorator d;
+ Printf("%s", d.Location());
+ if (chunk.AddrIsAtLeft(addr, access_size, &offset)) {
+ Printf("%p is located %zd bytes to the left of", (void*)addr, offset);
+ } else if (chunk.AddrIsAtRight(addr, access_size, &offset)) {
+ if (offset < 0) {
+ addr -= offset;
+ offset = 0;
+ }
+ Printf("%p is located %zd bytes to the right of", (void*)addr, offset);
+ } else if (chunk.AddrIsInside(addr, access_size, &offset)) {
+ Printf("%p is located %zd bytes inside of", (void*)addr, offset);
+ } else {
+ Printf("%p is located somewhere around (this is AddressSanitizer bug!)",
+ (void*)addr);
+ }
+ Printf(" %zu-byte region [%p,%p)\n", chunk.UsedSize(),
+ (void*)(chunk.Beg()), (void*)(chunk.End()));
+ Printf("%s", d.EndLocation());
+}
+
+// Return " (thread_name) " or an empty string if the name is empty.
+const char *ThreadNameWithParenthesis(AsanThreadSummary *t, char buff[],
+ uptr buff_len) {
+ const char *name = t->name();
+ if (*name == 0) return "";
+ buff[0] = 0;
+ internal_strncat(buff, " (", 3);
+ internal_strncat(buff, name, buff_len - 4);
+ internal_strncat(buff, ")", 2);
+ return buff;
+}
+
+const char *ThreadNameWithParenthesis(u32 tid, char buff[],
+ uptr buff_len) {
+ if (tid == kInvalidTid) return "";
+ AsanThreadSummary *t = asanThreadRegistry().FindByTid(tid);
+ return ThreadNameWithParenthesis(t, buff, buff_len);
+}
+
+void DescribeHeapAddress(uptr addr, uptr access_size) {
+ AsanChunkView chunk = FindHeapChunkByAddress(addr);
+ if (!chunk.IsValid()) return;
+ DescribeAccessToHeapChunk(chunk, addr, access_size);
+ CHECK(chunk.AllocTid() != kInvalidTid);
+ AsanThreadSummary *alloc_thread =
+ asanThreadRegistry().FindByTid(chunk.AllocTid());
+ StackTrace alloc_stack;
+ chunk.GetAllocStack(&alloc_stack);
+ AsanThread *t = asanThreadRegistry().GetCurrent();
+ CHECK(t);
+ char tname[128];
+ Decorator d;
+ if (chunk.FreeTid() != kInvalidTid) {
+ AsanThreadSummary *free_thread =
+ asanThreadRegistry().FindByTid(chunk.FreeTid());
+ Printf("%sfreed by thread T%d%s here:%s\n", d.Allocation(),
+ free_thread->tid(),
+ ThreadNameWithParenthesis(free_thread, tname, sizeof(tname)),
+ d.EndAllocation());
+ StackTrace free_stack;
+ chunk.GetFreeStack(&free_stack);
+ PrintStack(&free_stack);
+ Printf("%spreviously allocated by thread T%d%s here:%s\n",
+ d.Allocation(), alloc_thread->tid(),
+ ThreadNameWithParenthesis(alloc_thread, tname, sizeof(tname)),
+ d.EndAllocation());
+ PrintStack(&alloc_stack);
+ DescribeThread(t->summary());
+ DescribeThread(free_thread);
+ DescribeThread(alloc_thread);
+ } else {
+ Printf("%sallocated by thread T%d%s here:%s\n", d.Allocation(),
+ alloc_thread->tid(),
+ ThreadNameWithParenthesis(alloc_thread, tname, sizeof(tname)),
+ d.EndAllocation());
+ PrintStack(&alloc_stack);
+ DescribeThread(t->summary());
+ DescribeThread(alloc_thread);
+ }
+}
+
+void DescribeAddress(uptr addr, uptr access_size) {
+ // Check if this is shadow or shadow gap.
+ if (DescribeAddressIfShadow(addr))
+ return;
+ CHECK(AddrIsInMem(addr));
+ if (DescribeAddressIfGlobal(addr, access_size))
+ return;
+ if (DescribeAddressIfStack(addr, access_size))
+ return;
+ // Assume it is a heap address.
+ DescribeHeapAddress(addr, access_size);
+}
+
+// ------------------- Thread description -------------------- {{{1
+
+void DescribeThread(AsanThreadSummary *summary) {
+ CHECK(summary);
+ // No need to announce the main thread.
+ if (summary->tid() == 0 || summary->announced()) {
+ return;
+ }
+ summary->set_announced(true);
+ char tname[128];
+ Printf("Thread T%d%s", summary->tid(),
+ ThreadNameWithParenthesis(summary->tid(), tname, sizeof(tname)));
+ Printf(" created by T%d%s here:\n",
+ summary->parent_tid(),
+ ThreadNameWithParenthesis(summary->parent_tid(),
+ tname, sizeof(tname)));
+ PrintStack(summary->stack());
+ // Recursively described parent thread if needed.
+ if (flags()->print_full_thread_history) {
+ AsanThreadSummary *parent_summary =
+ asanThreadRegistry().FindByTid(summary->parent_tid());
+ DescribeThread(parent_summary);
+ }
+}
+
+// -------------------- Different kinds of reports ----------------- {{{1
+
+// Use ScopedInErrorReport to run common actions just before and
+// immediately after printing error report.
+class ScopedInErrorReport {
+ public:
+ ScopedInErrorReport() {
+ static atomic_uint32_t num_calls;
+ static u32 reporting_thread_tid;
+ if (atomic_fetch_add(&num_calls, 1, memory_order_relaxed) != 0) {
+ // Do not print more than one report, otherwise they will mix up.
+ // Error reporting functions shouldn't return at this situation, as
+ // they are defined as no-return.
+ Report("AddressSanitizer: while reporting a bug found another one."
+ "Ignoring.\n");
+ u32 current_tid = asanThreadRegistry().GetCurrentTidOrInvalid();
+ if (current_tid != reporting_thread_tid) {
+ // ASan found two bugs in different threads simultaneously. Sleep
+ // long enough to make sure that the thread which started to print
+ // an error report will finish doing it.
+ SleepForSeconds(Max(100, flags()->sleep_before_dying + 1));
+ }
+ // If we're still not dead for some reason, use raw _exit() instead of
+ // Die() to bypass any additional checks.
+ internal__exit(flags()->exitcode);
+ }
+ ASAN_ON_ERROR();
+ reporting_thread_tid = asanThreadRegistry().GetCurrentTidOrInvalid();
+ Printf("===================================================="
+ "=============\n");
+ if (reporting_thread_tid != kInvalidTid) {
+ // We started reporting an error message. Stop using the fake stack
+ // in case we call an instrumented function from a symbolizer.
+ AsanThread *curr_thread = asanThreadRegistry().GetCurrent();
+ CHECK(curr_thread);
+ curr_thread->fake_stack().StopUsingFakeStack();
+ }
+ }
+ // Destructor is NORETURN, as functions that report errors are.
+ NORETURN ~ScopedInErrorReport() {
+ // Make sure the current thread is announced.
+ AsanThread *curr_thread = asanThreadRegistry().GetCurrent();
+ if (curr_thread) {
+ DescribeThread(curr_thread->summary());
+ }
+ // Print memory stats.
+ if (flags()->print_stats)
+ __asan_print_accumulated_stats();
+ if (error_report_callback) {
+ error_report_callback(error_message_buffer);
+ }
+ Report("ABORTING\n");
+ Die();
+ }
+};
+
+static void ReportSummary(const char *error_type, StackTrace *stack) {
+ if (!stack->size) return;
+ if (IsSymbolizerAvailable()) {
+ AddressInfo ai;
+ // Currently, we include the first stack frame into the report summary.
+ // Maybe sometimes we need to choose another frame (e.g. skip memcpy/etc).
+ SymbolizeCode(stack->trace[0], &ai, 1);
+ ReportErrorSummary(error_type,
+ StripPathPrefix(ai.file, flags()->strip_path_prefix),
+ ai.line, ai.function);
+ }
+ // FIXME: do we need to print anything at all if there is no symbolizer?
+}
+
+void ReportSIGSEGV(uptr pc, uptr sp, uptr bp, uptr addr) {
+ ScopedInErrorReport in_report;
+ Decorator d;
+ Printf("%s", d.Warning());
+ Report("ERROR: AddressSanitizer: SEGV on unknown address %p"
+ " (pc %p sp %p bp %p T%d)\n",
+ (void*)addr, (void*)pc, (void*)sp, (void*)bp,
+ asanThreadRegistry().GetCurrentTidOrInvalid());
+ Printf("%s", d.EndWarning());
+ Printf("AddressSanitizer can not provide additional info.\n");
+ GET_STACK_TRACE_FATAL(pc, bp);
+ PrintStack(&stack);
+ ReportSummary("SEGV", &stack);
+}
+
+void ReportDoubleFree(uptr addr, StackTrace *stack) {
+ ScopedInErrorReport in_report;
+ Decorator d;
+ Printf("%s", d.Warning());
+ Report("ERROR: AddressSanitizer: attempting double-free on %p:\n", addr);
+ Printf("%s", d.EndWarning());
+ PrintStack(stack);
+ DescribeHeapAddress(addr, 1);
+ ReportSummary("double-free", stack);
+}
+
+void ReportFreeNotMalloced(uptr addr, StackTrace *stack) {
+ ScopedInErrorReport in_report;
+ Decorator d;
+ Printf("%s", d.Warning());
+ Report("ERROR: AddressSanitizer: attempting free on address "
+ "which was not malloc()-ed: %p\n", addr);
+ Printf("%s", d.EndWarning());
+ PrintStack(stack);
+ DescribeHeapAddress(addr, 1);
+ ReportSummary("bad-free", stack);
+}
+
+void ReportAllocTypeMismatch(uptr addr, StackTrace *stack,
+ AllocType alloc_type,
+ AllocType dealloc_type) {
+ static const char *alloc_names[] =
+ {"INVALID", "malloc", "operator new", "operator new []"};
+ static const char *dealloc_names[] =
+ {"INVALID", "free", "operator delete", "operator delete []"};
+ CHECK_NE(alloc_type, dealloc_type);
+ ScopedInErrorReport in_report;
+ Decorator d;
+ Printf("%s", d.Warning());
+ Report("ERROR: AddressSanitizer: alloc-dealloc-mismatch (%s vs %s) on %p\n",
+ alloc_names[alloc_type], dealloc_names[dealloc_type], addr);
+ Printf("%s", d.EndWarning());
+ PrintStack(stack);
+ DescribeHeapAddress(addr, 1);
+ ReportSummary("alloc-dealloc-mismatch", stack);
+ Report("HINT: if you don't care about these warnings you may set "
+ "ASAN_OPTIONS=alloc_dealloc_mismatch=0\n");
+}
+
+void ReportMallocUsableSizeNotOwned(uptr addr, StackTrace *stack) {
+ ScopedInErrorReport in_report;
+ Decorator d;
+ Printf("%s", d.Warning());
+ Report("ERROR: AddressSanitizer: attempting to call "
+ "malloc_usable_size() for pointer which is "
+ "not owned: %p\n", addr);
+ Printf("%s", d.EndWarning());
+ PrintStack(stack);
+ DescribeHeapAddress(addr, 1);
+ ReportSummary("bad-malloc_usable_size", stack);
+}
+
+void ReportAsanGetAllocatedSizeNotOwned(uptr addr, StackTrace *stack) {
+ ScopedInErrorReport in_report;
+ Decorator d;
+ Printf("%s", d.Warning());
+ Report("ERROR: AddressSanitizer: attempting to call "
+ "__asan_get_allocated_size() for pointer which is "
+ "not owned: %p\n", addr);
+ Printf("%s", d.EndWarning());
+ PrintStack(stack);
+ DescribeHeapAddress(addr, 1);
+ ReportSummary("bad-__asan_get_allocated_size", stack);
+}
+
+void ReportStringFunctionMemoryRangesOverlap(
+ const char *function, const char *offset1, uptr length1,
+ const char *offset2, uptr length2, StackTrace *stack) {
+ ScopedInErrorReport in_report;
+ Decorator d;
+ char bug_type[100];
+ internal_snprintf(bug_type, sizeof(bug_type), "%s-param-overlap", function);
+ Printf("%s", d.Warning());
+ Report("ERROR: AddressSanitizer: %s: "
+ "memory ranges [%p,%p) and [%p, %p) overlap\n", \
+ bug_type, offset1, offset1 + length1, offset2, offset2 + length2);
+ Printf("%s", d.EndWarning());
+ PrintStack(stack);
+ DescribeAddress((uptr)offset1, length1);
+ DescribeAddress((uptr)offset2, length2);
+ ReportSummary(bug_type, stack);
+}
+
+// ----------------------- Mac-specific reports ----------------- {{{1
+
+void WarnMacFreeUnallocated(
+ uptr addr, uptr zone_ptr, const char *zone_name, StackTrace *stack) {
+ // Just print a warning here.
+ Printf("free_common(%p) -- attempting to free unallocated memory.\n"
+ "AddressSanitizer is ignoring this error on Mac OS now.\n",
+ addr);
+ PrintZoneForPointer(addr, zone_ptr, zone_name);
+ PrintStack(stack);
+ DescribeHeapAddress(addr, 1);
+}
+
+void ReportMacMzReallocUnknown(
+ uptr addr, uptr zone_ptr, const char *zone_name, StackTrace *stack) {
+ ScopedInErrorReport in_report;
+ Printf("mz_realloc(%p) -- attempting to realloc unallocated memory.\n"
+ "This is an unrecoverable problem, exiting now.\n",
+ addr);
+ PrintZoneForPointer(addr, zone_ptr, zone_name);
+ PrintStack(stack);
+ DescribeHeapAddress(addr, 1);
+}
+
+void ReportMacCfReallocUnknown(
+ uptr addr, uptr zone_ptr, const char *zone_name, StackTrace *stack) {
+ ScopedInErrorReport in_report;
+ Printf("cf_realloc(%p) -- attempting to realloc unallocated memory.\n"
+ "This is an unrecoverable problem, exiting now.\n",
+ addr);
+ PrintZoneForPointer(addr, zone_ptr, zone_name);
+ PrintStack(stack);
+ DescribeHeapAddress(addr, 1);
+}
+
+} // namespace __asan
+
+// --------------------------- Interface --------------------- {{{1
+using namespace __asan; // NOLINT
+
+void __asan_report_error(uptr pc, uptr bp, uptr sp,
+ uptr addr, bool is_write, uptr access_size) {
+ ScopedInErrorReport in_report;
+
+ // Determine the error type.
+ const char *bug_descr = "unknown-crash";
+ if (AddrIsInMem(addr)) {
+ u8 *shadow_addr = (u8*)MemToShadow(addr);
+ // If we are accessing 16 bytes, look at the second shadow byte.
+ if (*shadow_addr == 0 && access_size > SHADOW_GRANULARITY)
+ shadow_addr++;
+ // If we are in the partial right redzone, look at the next shadow byte.
+ if (*shadow_addr > 0 && *shadow_addr < 128)
+ shadow_addr++;
+ switch (*shadow_addr) {
+ case kAsanHeapLeftRedzoneMagic:
+ case kAsanHeapRightRedzoneMagic:
+ bug_descr = "heap-buffer-overflow";
+ break;
+ case kAsanHeapFreeMagic:
+ bug_descr = "heap-use-after-free";
+ break;
+ case kAsanStackLeftRedzoneMagic:
+ bug_descr = "stack-buffer-underflow";
+ break;
+ case kAsanInitializationOrderMagic:
+ bug_descr = "initialization-order-fiasco";
+ break;
+ case kAsanStackMidRedzoneMagic:
+ case kAsanStackRightRedzoneMagic:
+ case kAsanStackPartialRedzoneMagic:
+ bug_descr = "stack-buffer-overflow";
+ break;
+ case kAsanStackAfterReturnMagic:
+ bug_descr = "stack-use-after-return";
+ break;
+ case kAsanUserPoisonedMemoryMagic:
+ bug_descr = "use-after-poison";
+ break;
+ case kAsanStackUseAfterScopeMagic:
+ bug_descr = "stack-use-after-scope";
+ break;
+ case kAsanGlobalRedzoneMagic:
+ bug_descr = "global-buffer-overflow";
+ break;
+ }
+ }
+ Decorator d;
+ Printf("%s", d.Warning());
+ Report("ERROR: AddressSanitizer: %s on address "
+ "%p at pc 0x%zx bp 0x%zx sp 0x%zx\n",
+ bug_descr, (void*)addr, pc, bp, sp);
+ Printf("%s", d.EndWarning());
+
+ u32 curr_tid = asanThreadRegistry().GetCurrentTidOrInvalid();
+ char tname[128];
+ Printf("%s%s of size %zu at %p thread T%d%s%s\n",
+ d.Access(),
+ access_size ? (is_write ? "WRITE" : "READ") : "ACCESS",
+ access_size, (void*)addr, curr_tid,
+ ThreadNameWithParenthesis(curr_tid, tname, sizeof(tname)),
+ d.EndAccess());
+
+ GET_STACK_TRACE_FATAL(pc, bp);
+ PrintStack(&stack);
+
+ DescribeAddress(addr, access_size);
+ ReportSummary(bug_descr, &stack);
+ PrintShadowMemoryForAddress(addr);
+}
+
+void NOINLINE __asan_set_error_report_callback(void (*callback)(const char*)) {
+ error_report_callback = callback;
+ if (callback) {
+ error_message_buffer_size = 1 << 16;
+ error_message_buffer =
+ (char*)MmapOrDie(error_message_buffer_size, __FUNCTION__);
+ error_message_buffer_pos = 0;
+ }
+}
+
+void __asan_describe_address(uptr addr) {
+ DescribeAddress(addr, 1);
+}
+
+#if !SANITIZER_SUPPORTS_WEAK_HOOKS
+// Provide default implementation of __asan_on_error that does nothing
+// and may be overriden by user.
+SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE NOINLINE
+void __asan_on_error() {}
+#endif
diff --git a/gcc-4.8/libsanitizer/asan/asan_report.h b/gcc-4.8/libsanitizer/asan/asan_report.h
new file mode 100644
index 000000000..13724dab9
--- /dev/null
+++ b/gcc-4.8/libsanitizer/asan/asan_report.h
@@ -0,0 +1,55 @@
+//===-- asan_report.h -------------------------------------------*- C++ -*-===//
+//
+// 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.
+//
+// ASan-private header for error reporting functions.
+//===----------------------------------------------------------------------===//
+
+#include "asan_allocator.h"
+#include "asan_internal.h"
+#include "asan_thread.h"
+
+namespace __asan {
+
+// The following functions prints address description depending
+// on the memory type (shadow/heap/stack/global).
+void DescribeHeapAddress(uptr addr, uptr access_size);
+bool DescribeAddressIfGlobal(uptr addr, uptr access_size);
+bool DescribeAddressRelativeToGlobal(uptr addr, uptr access_size,
+ const __asan_global &g);
+bool DescribeAddressIfShadow(uptr addr);
+bool DescribeAddressIfStack(uptr addr, uptr access_size);
+// Determines memory type on its own.
+void DescribeAddress(uptr addr, uptr access_size);
+
+void DescribeThread(AsanThreadSummary *summary);
+
+// Different kinds of error reports.
+void NORETURN ReportSIGSEGV(uptr pc, uptr sp, uptr bp, uptr addr);
+void NORETURN ReportDoubleFree(uptr addr, StackTrace *stack);
+void NORETURN ReportFreeNotMalloced(uptr addr, StackTrace *stack);
+void NORETURN ReportAllocTypeMismatch(uptr addr, StackTrace *stack,
+ AllocType alloc_type,
+ AllocType dealloc_type);
+void NORETURN ReportMallocUsableSizeNotOwned(uptr addr,
+ StackTrace *stack);
+void NORETURN ReportAsanGetAllocatedSizeNotOwned(uptr addr,
+ StackTrace *stack);
+void NORETURN ReportStringFunctionMemoryRangesOverlap(
+ const char *function, const char *offset1, uptr length1,
+ const char *offset2, uptr length2, StackTrace *stack);
+
+// Mac-specific errors and warnings.
+void WarnMacFreeUnallocated(
+ uptr addr, uptr zone_ptr, const char *zone_name, StackTrace *stack);
+void NORETURN ReportMacMzReallocUnknown(
+ uptr addr, uptr zone_ptr, const char *zone_name, StackTrace *stack);
+void NORETURN ReportMacCfReallocUnknown(
+ uptr addr, uptr zone_ptr, const char *zone_name, StackTrace *stack);
+
+} // namespace __asan
diff --git a/gcc-4.8/libsanitizer/asan/asan_rtl.cc b/gcc-4.8/libsanitizer/asan/asan_rtl.cc
new file mode 100644
index 000000000..6ddb01329
--- /dev/null
+++ b/gcc-4.8/libsanitizer/asan/asan_rtl.cc
@@ -0,0 +1,521 @@
+//===-- asan_rtl.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.
+//
+// Main file of the ASan run-time library.
+//===----------------------------------------------------------------------===//
+#include "asan_allocator.h"
+#include "asan_interceptors.h"
+#include "asan_internal.h"
+#include "asan_mapping.h"
+#include "asan_report.h"
+#include "asan_stack.h"
+#include "asan_stats.h"
+#include "asan_thread.h"
+#include "asan_thread_registry.h"
+#include "sanitizer_common/sanitizer_atomic.h"
+#include "sanitizer_common/sanitizer_flags.h"
+#include "sanitizer_common/sanitizer_libc.h"
+#include "sanitizer_common/sanitizer_symbolizer.h"
+
+namespace __asan {
+
+uptr AsanMappingProfile[kAsanMappingProfileSize];
+
+static void AsanDie() {
+ static atomic_uint32_t num_calls;
+ if (atomic_fetch_add(&num_calls, 1, memory_order_relaxed) != 0) {
+ // Don't die twice - run a busy loop.
+ while (1) { }
+ }
+ if (flags()->sleep_before_dying) {
+ Report("Sleeping for %d second(s)\n", flags()->sleep_before_dying);
+ SleepForSeconds(flags()->sleep_before_dying);
+ }
+ if (flags()->unmap_shadow_on_exit) {
+ if (kMidMemBeg) {
+ UnmapOrDie((void*)kLowShadowBeg, kMidMemBeg - kLowShadowBeg);
+ UnmapOrDie((void*)kMidMemEnd, kHighShadowEnd - kMidMemEnd);
+ } else {
+ UnmapOrDie((void*)kLowShadowBeg, kHighShadowEnd - kLowShadowBeg);
+ }
+ }
+ if (death_callback)
+ death_callback();
+ if (flags()->abort_on_error)
+ Abort();
+ internal__exit(flags()->exitcode);
+}
+
+static void AsanCheckFailed(const char *file, int line, const char *cond,
+ u64 v1, u64 v2) {
+ Report("AddressSanitizer CHECK failed: %s:%d \"%s\" (0x%zx, 0x%zx)\n",
+ file, line, cond, (uptr)v1, (uptr)v2);
+ // FIXME: check for infinite recursion without a thread-local counter here.
+ PRINT_CURRENT_STACK();
+ Die();
+}
+
+// -------------------------- Flags ------------------------- {{{1
+static const int kDeafultMallocContextSize = 30;
+
+static Flags asan_flags;
+
+Flags *flags() {
+ return &asan_flags;
+}
+
+static const char *MaybeCallAsanDefaultOptions() {
+ return (&__asan_default_options) ? __asan_default_options() : "";
+}
+
+static const char *MaybeUseAsanDefaultOptionsCompileDefiniton() {
+#ifdef ASAN_DEFAULT_OPTIONS
+// Stringize the macro value.
+# define ASAN_STRINGIZE(x) #x
+# define ASAN_STRINGIZE_OPTIONS(options) ASAN_STRINGIZE(options)
+ return ASAN_STRINGIZE_OPTIONS(ASAN_DEFAULT_OPTIONS);
+#else
+ return "";
+#endif
+}
+
+static void ParseFlagsFromString(Flags *f, const char *str) {
+ ParseFlag(str, &f->quarantine_size, "quarantine_size");
+ ParseFlag(str, &f->symbolize, "symbolize");
+ ParseFlag(str, &f->verbosity, "verbosity");
+ ParseFlag(str, &f->redzone, "redzone");
+ CHECK(f->redzone >= 16);
+ CHECK(IsPowerOfTwo(f->redzone));
+
+ ParseFlag(str, &f->debug, "debug");
+ ParseFlag(str, &f->report_globals, "report_globals");
+ ParseFlag(str, &f->check_initialization_order, "initialization_order");
+ ParseFlag(str, &f->malloc_context_size, "malloc_context_size");
+ CHECK((uptr)f->malloc_context_size <= kStackTraceMax);
+
+ ParseFlag(str, &f->replace_str, "replace_str");
+ ParseFlag(str, &f->replace_intrin, "replace_intrin");
+ ParseFlag(str, &f->mac_ignore_invalid_free, "mac_ignore_invalid_free");
+ ParseFlag(str, &f->use_fake_stack, "use_fake_stack");
+ ParseFlag(str, &f->max_malloc_fill_size, "max_malloc_fill_size");
+ ParseFlag(str, &f->exitcode, "exitcode");
+ ParseFlag(str, &f->allow_user_poisoning, "allow_user_poisoning");
+ ParseFlag(str, &f->sleep_before_dying, "sleep_before_dying");
+ ParseFlag(str, &f->handle_segv, "handle_segv");
+ ParseFlag(str, &f->use_sigaltstack, "use_sigaltstack");
+ ParseFlag(str, &f->check_malloc_usable_size, "check_malloc_usable_size");
+ ParseFlag(str, &f->unmap_shadow_on_exit, "unmap_shadow_on_exit");
+ ParseFlag(str, &f->abort_on_error, "abort_on_error");
+ ParseFlag(str, &f->print_stats, "print_stats");
+ ParseFlag(str, &f->print_legend, "print_legend");
+ ParseFlag(str, &f->atexit, "atexit");
+ ParseFlag(str, &f->disable_core, "disable_core");
+ ParseFlag(str, &f->strip_path_prefix, "strip_path_prefix");
+ ParseFlag(str, &f->allow_reexec, "allow_reexec");
+ ParseFlag(str, &f->print_full_thread_history, "print_full_thread_history");
+ ParseFlag(str, &f->log_path, "log_path");
+ ParseFlag(str, &f->fast_unwind_on_fatal, "fast_unwind_on_fatal");
+ ParseFlag(str, &f->fast_unwind_on_malloc, "fast_unwind_on_malloc");
+ ParseFlag(str, &f->poison_heap, "poison_heap");
+ ParseFlag(str, &f->alloc_dealloc_mismatch, "alloc_dealloc_mismatch");
+ ParseFlag(str, &f->use_stack_depot, "use_stack_depot");
+}
+
+void InitializeFlags(Flags *f, const char *env) {
+ internal_memset(f, 0, sizeof(*f));
+
+ f->quarantine_size = (ASAN_LOW_MEMORY) ? 1UL << 26 : 1UL << 28;
+ f->symbolize = false;
+ f->verbosity = 0;
+ f->redzone = ASAN_ALLOCATOR_VERSION == 2 ? 16 : (ASAN_LOW_MEMORY) ? 64 : 128;
+ f->debug = false;
+ f->report_globals = 1;
+ f->check_initialization_order = true;
+ f->malloc_context_size = kDeafultMallocContextSize;
+ f->replace_str = true;
+ f->replace_intrin = true;
+ f->mac_ignore_invalid_free = false;
+ f->use_fake_stack = true;
+ f->max_malloc_fill_size = 0;
+ f->exitcode = ASAN_DEFAULT_FAILURE_EXITCODE;
+ f->allow_user_poisoning = true;
+ f->sleep_before_dying = 0;
+ f->handle_segv = ASAN_NEEDS_SEGV;
+ f->use_sigaltstack = false;
+ f->check_malloc_usable_size = true;
+ f->unmap_shadow_on_exit = false;
+ f->abort_on_error = false;
+ f->print_stats = false;
+ f->print_legend = true;
+ f->atexit = false;
+ f->disable_core = (SANITIZER_WORDSIZE == 64);
+ f->strip_path_prefix = "";
+ f->allow_reexec = true;
+ f->print_full_thread_history = true;
+ f->log_path = 0;
+ f->fast_unwind_on_fatal = false;
+ f->fast_unwind_on_malloc = true;
+ f->poison_heap = true;
+ f->alloc_dealloc_mismatch = true;
+ f->use_stack_depot = true; // Only affects allocator2.
+
+ // Override from compile definition.
+ ParseFlagsFromString(f, MaybeUseAsanDefaultOptionsCompileDefiniton());
+
+ // Override from user-specified string.
+ ParseFlagsFromString(f, MaybeCallAsanDefaultOptions());
+ if (flags()->verbosity) {
+ Report("Using the defaults from __asan_default_options: %s\n",
+ MaybeCallAsanDefaultOptions());
+ }
+
+ // Override from command line.
+ ParseFlagsFromString(f, env);
+}
+
+// -------------------------- Globals --------------------- {{{1
+int asan_inited;
+bool asan_init_is_running;
+void (*death_callback)(void);
+
+#if !ASAN_FIXED_MAPPING
+uptr kHighMemEnd, kMidMemBeg, kMidMemEnd;
+#endif
+
+// -------------------------- Misc ---------------- {{{1
+void ShowStatsAndAbort() {
+ __asan_print_accumulated_stats();
+ Die();
+}
+
+// ---------------------- mmap -------------------- {{{1
+// Reserve memory range [beg, end].
+static void ReserveShadowMemoryRange(uptr beg, uptr end) {
+ CHECK((beg % GetPageSizeCached()) == 0);
+ CHECK(((end + 1) % GetPageSizeCached()) == 0);
+ uptr size = end - beg + 1;
+ void *res = MmapFixedNoReserve(beg, size);
+ if (res != (void*)beg) {
+ Report("ReserveShadowMemoryRange failed while trying to map 0x%zx bytes. "
+ "Perhaps you're using ulimit -v\n", size);
+ Abort();
+ }
+}
+
+// --------------- LowLevelAllocateCallbac ---------- {{{1
+static void OnLowLevelAllocate(uptr ptr, uptr size) {
+ PoisonShadow(ptr, size, kAsanInternalHeapMagic);
+}
+
+// -------------------------- Run-time entry ------------------- {{{1
+// exported functions
+#define ASAN_REPORT_ERROR(type, is_write, size) \
+extern "C" NOINLINE INTERFACE_ATTRIBUTE \
+void __asan_report_ ## type ## size(uptr addr); \
+void __asan_report_ ## type ## size(uptr addr) { \
+ GET_CALLER_PC_BP_SP; \
+ __asan_report_error(pc, bp, sp, addr, is_write, size); \
+}
+
+ASAN_REPORT_ERROR(load, false, 1)
+ASAN_REPORT_ERROR(load, false, 2)
+ASAN_REPORT_ERROR(load, false, 4)
+ASAN_REPORT_ERROR(load, false, 8)
+ASAN_REPORT_ERROR(load, false, 16)
+ASAN_REPORT_ERROR(store, true, 1)
+ASAN_REPORT_ERROR(store, true, 2)
+ASAN_REPORT_ERROR(store, true, 4)
+ASAN_REPORT_ERROR(store, true, 8)
+ASAN_REPORT_ERROR(store, true, 16)
+
+#define ASAN_REPORT_ERROR_N(type, is_write) \
+extern "C" NOINLINE INTERFACE_ATTRIBUTE \
+void __asan_report_ ## type ## _n(uptr addr, uptr size); \
+void __asan_report_ ## type ## _n(uptr addr, uptr size) { \
+ GET_CALLER_PC_BP_SP; \
+ __asan_report_error(pc, bp, sp, addr, is_write, size); \
+}
+
+ASAN_REPORT_ERROR_N(load, false)
+ASAN_REPORT_ERROR_N(store, true)
+
+// Force the linker to keep the symbols for various ASan interface functions.
+// We want to keep those in the executable in order to let the instrumented
+// dynamic libraries access the symbol even if it is not used by the executable
+// itself. This should help if the build system is removing dead code at link
+// time.
+static NOINLINE void force_interface_symbols() {
+ volatile int fake_condition = 0; // prevent dead condition elimination.
+ // __asan_report_* functions are noreturn, so we need a switch to prevent
+ // the compiler from removing any of them.
+ switch (fake_condition) {
+ case 1: __asan_report_load1(0); break;
+ case 2: __asan_report_load2(0); break;
+ case 3: __asan_report_load4(0); break;
+ case 4: __asan_report_load8(0); break;
+ case 5: __asan_report_load16(0); break;
+ case 6: __asan_report_store1(0); break;
+ case 7: __asan_report_store2(0); break;
+ case 8: __asan_report_store4(0); break;
+ case 9: __asan_report_store8(0); break;
+ case 10: __asan_report_store16(0); break;
+ case 12: __asan_register_globals(0, 0); break;
+ case 13: __asan_unregister_globals(0, 0); break;
+ case 14: __asan_set_death_callback(0); break;
+ case 15: __asan_set_error_report_callback(0); break;
+ case 16: __asan_handle_no_return(); break;
+ case 17: __asan_address_is_poisoned(0); break;
+ case 18: __asan_get_allocated_size(0); break;
+ case 19: __asan_get_current_allocated_bytes(); break;
+ case 20: __asan_get_estimated_allocated_size(0); break;
+ case 21: __asan_get_free_bytes(); break;
+ case 22: __asan_get_heap_size(); break;
+ case 23: __asan_get_ownership(0); break;
+ case 24: __asan_get_unmapped_bytes(); break;
+ case 25: __asan_poison_memory_region(0, 0); break;
+ case 26: __asan_unpoison_memory_region(0, 0); break;
+ case 27: __asan_set_error_exit_code(0); break;
+ case 28: __asan_stack_free(0, 0, 0); break;
+ case 29: __asan_stack_malloc(0, 0); break;
+ case 30: __asan_before_dynamic_init(0, 0); break;
+ case 31: __asan_after_dynamic_init(); break;
+ case 32: __asan_poison_stack_memory(0, 0); break;
+ case 33: __asan_unpoison_stack_memory(0, 0); break;
+ case 34: __asan_region_is_poisoned(0, 0); break;
+ case 35: __asan_describe_address(0); break;
+ }
+}
+
+static void asan_atexit() {
+ Printf("AddressSanitizer exit stats:\n");
+ __asan_print_accumulated_stats();
+ // Print AsanMappingProfile.
+ for (uptr i = 0; i < kAsanMappingProfileSize; i++) {
+ if (AsanMappingProfile[i] == 0) continue;
+ Printf("asan_mapping.h:%zd -- %zd\n", i, AsanMappingProfile[i]);
+ }
+}
+
+static void InitializeHighMemEnd() {
+#if !ASAN_FIXED_MAPPING
+#if SANITIZER_WORDSIZE == 64
+# if defined(__powerpc64__)
+ // FIXME:
+ // On PowerPC64 we have two different address space layouts: 44- and 46-bit.
+ // We somehow need to figure our which one we are using now and choose
+ // one of 0x00000fffffffffffUL and 0x00003fffffffffffUL.
+ // Note that with 'ulimit -s unlimited' the stack is moved away from the top
+ // of the address space, so simply checking the stack address is not enough.
+ kHighMemEnd = (1ULL << 44) - 1; // 0x00000fffffffffffUL
+# else
+ kHighMemEnd = (1ULL << 47) - 1; // 0x00007fffffffffffUL;
+# endif
+#else // SANITIZER_WORDSIZE == 32
+ kHighMemEnd = (1ULL << 32) - 1; // 0xffffffff;
+#endif // SANITIZER_WORDSIZE
+#endif // !ASAN_FIXED_MAPPING
+}
+
+static void ProtectGap(uptr a, uptr size) {
+ CHECK_EQ(a, (uptr)Mprotect(a, size));
+}
+
+static void PrintAddressSpaceLayout() {
+ Printf("|| `[%p, %p]` || HighMem ||\n",
+ (void*)kHighMemBeg, (void*)kHighMemEnd);
+ Printf("|| `[%p, %p]` || HighShadow ||\n",
+ (void*)kHighShadowBeg, (void*)kHighShadowEnd);
+ if (kMidMemBeg) {
+ Printf("|| `[%p, %p]` || ShadowGap3 ||\n",
+ (void*)kShadowGap3Beg, (void*)kShadowGap3End);
+ Printf("|| `[%p, %p]` || MidMem ||\n",
+ (void*)kMidMemBeg, (void*)kMidMemEnd);
+ Printf("|| `[%p, %p]` || ShadowGap2 ||\n",
+ (void*)kShadowGap2Beg, (void*)kShadowGap2End);
+ Printf("|| `[%p, %p]` || MidShadow ||\n",
+ (void*)kMidShadowBeg, (void*)kMidShadowEnd);
+ }
+ Printf("|| `[%p, %p]` || ShadowGap ||\n",
+ (void*)kShadowGapBeg, (void*)kShadowGapEnd);
+ if (kLowShadowBeg) {
+ Printf("|| `[%p, %p]` || LowShadow ||\n",
+ (void*)kLowShadowBeg, (void*)kLowShadowEnd);
+ Printf("|| `[%p, %p]` || LowMem ||\n",
+ (void*)kLowMemBeg, (void*)kLowMemEnd);
+ }
+ Printf("MemToShadow(shadow): %p %p %p %p",
+ (void*)MEM_TO_SHADOW(kLowShadowBeg),
+ (void*)MEM_TO_SHADOW(kLowShadowEnd),
+ (void*)MEM_TO_SHADOW(kHighShadowBeg),
+ (void*)MEM_TO_SHADOW(kHighShadowEnd));
+ if (kMidMemBeg) {
+ Printf(" %p %p",
+ (void*)MEM_TO_SHADOW(kMidShadowBeg),
+ (void*)MEM_TO_SHADOW(kMidShadowEnd));
+ }
+ Printf("\n");
+ Printf("red_zone=%zu\n", (uptr)flags()->redzone);
+ Printf("malloc_context_size=%zu\n", (uptr)flags()->malloc_context_size);
+
+ Printf("SHADOW_SCALE: %zx\n", (uptr)SHADOW_SCALE);
+ Printf("SHADOW_GRANULARITY: %zx\n", (uptr)SHADOW_GRANULARITY);
+ Printf("SHADOW_OFFSET: %zx\n", (uptr)SHADOW_OFFSET);
+ CHECK(SHADOW_SCALE >= 3 && SHADOW_SCALE <= 7);
+ if (kMidMemBeg)
+ CHECK(kMidShadowBeg > kLowShadowEnd &&
+ kMidMemBeg > kMidShadowEnd &&
+ kHighShadowBeg > kMidMemEnd);
+}
+
+} // namespace __asan
+
+// ---------------------- Interface ---------------- {{{1
+using namespace __asan; // NOLINT
+
+#if !SANITIZER_SUPPORTS_WEAK_HOOKS
+extern "C" {
+SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
+const char* __asan_default_options() { return ""; }
+} // extern "C"
+#endif
+
+int NOINLINE __asan_set_error_exit_code(int exit_code) {
+ int old = flags()->exitcode;
+ flags()->exitcode = exit_code;
+ return old;
+}
+
+void NOINLINE __asan_handle_no_return() {
+ int local_stack;
+ AsanThread *curr_thread = asanThreadRegistry().GetCurrent();
+ CHECK(curr_thread);
+ uptr PageSize = GetPageSizeCached();
+ uptr top = curr_thread->stack_top();
+ uptr bottom = ((uptr)&local_stack - PageSize) & ~(PageSize-1);
+ PoisonShadow(bottom, top - bottom, 0);
+}
+
+void NOINLINE __asan_set_death_callback(void (*callback)(void)) {
+ death_callback = callback;
+}
+
+void __asan_init() {
+ if (asan_inited) return;
+ SanitizerToolName = "AddressSanitizer";
+ CHECK(!asan_init_is_running && "ASan init calls itself!");
+ asan_init_is_running = true;
+ InitializeHighMemEnd();
+
+ // Make sure we are not statically linked.
+ AsanDoesNotSupportStaticLinkage();
+
+ // Install tool-specific callbacks in sanitizer_common.
+ SetDieCallback(AsanDie);
+ SetCheckFailedCallback(AsanCheckFailed);
+ SetPrintfAndReportCallback(AppendToErrorMessageBuffer);
+
+ // Initialize flags. This must be done early, because most of the
+ // initialization steps look at flags().
+ const char *options = GetEnv("ASAN_OPTIONS");
+ InitializeFlags(flags(), options);
+ __sanitizer_set_report_path(flags()->log_path);
+
+ if (flags()->verbosity && options) {
+ Report("Parsed ASAN_OPTIONS: %s\n", options);
+ }
+
+ // Re-exec ourselves if we need to set additional env or command line args.
+ MaybeReexec();
+
+ // Setup internal allocator callback.
+ SetLowLevelAllocateCallback(OnLowLevelAllocate);
+
+ if (flags()->atexit) {
+ Atexit(asan_atexit);
+ }
+
+ // interceptors
+ InitializeAsanInterceptors();
+
+ ReplaceSystemMalloc();
+ ReplaceOperatorsNewAndDelete();
+
+ uptr shadow_start = kLowShadowBeg;
+ if (kLowShadowBeg) shadow_start -= GetMmapGranularity();
+ uptr shadow_end = kHighShadowEnd;
+ bool full_shadow_is_available =
+ MemoryRangeIsAvailable(shadow_start, shadow_end);
+
+#if ASAN_LINUX && defined(__x86_64__) && !ASAN_FIXED_MAPPING
+ if (!full_shadow_is_available) {
+ kMidMemBeg = kLowMemEnd < 0x3000000000ULL ? 0x3000000000ULL : 0;
+ kMidMemEnd = kLowMemEnd < 0x3000000000ULL ? 0x4fffffffffULL : 0;
+ }
+#endif
+
+ if (flags()->verbosity)
+ PrintAddressSpaceLayout();
+
+ if (flags()->disable_core) {
+ DisableCoreDumper();
+ }
+
+ if (full_shadow_is_available) {
+ // mmap the low shadow plus at least one page at the left.
+ if (kLowShadowBeg)
+ ReserveShadowMemoryRange(shadow_start, kLowShadowEnd);
+ // mmap the high shadow.
+ ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd);
+ // protect the gap.
+ ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1);
+ } else if (kMidMemBeg &&
+ MemoryRangeIsAvailable(shadow_start, kMidMemBeg - 1) &&
+ MemoryRangeIsAvailable(kMidMemEnd + 1, shadow_end)) {
+ CHECK(kLowShadowBeg != kLowShadowEnd);
+ // mmap the low shadow plus at least one page at the left.
+ ReserveShadowMemoryRange(shadow_start, kLowShadowEnd);
+ // mmap the mid shadow.
+ ReserveShadowMemoryRange(kMidShadowBeg, kMidShadowEnd);
+ // mmap the high shadow.
+ ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd);
+ // protect the gaps.
+ ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1);
+ ProtectGap(kShadowGap2Beg, kShadowGap2End - kShadowGap2Beg + 1);
+ ProtectGap(kShadowGap3Beg, kShadowGap3End - kShadowGap3Beg + 1);
+ } else {
+ Report("Shadow memory range interleaves with an existing memory mapping. "
+ "ASan cannot proceed correctly. ABORTING.\n");
+ DumpProcessMap();
+ Die();
+ }
+
+ InstallSignalHandlers();
+ // Start symbolizer process if necessary.
+ if (flags()->symbolize) {
+ const char *external_symbolizer = GetEnv("ASAN_SYMBOLIZER_PATH");
+ if (external_symbolizer) {
+ InitializeExternalSymbolizer(external_symbolizer);
+ }
+ }
+
+ // On Linux AsanThread::ThreadStart() calls malloc() that's why asan_inited
+ // should be set to 1 prior to initializing the threads.
+ asan_inited = 1;
+ asan_init_is_running = false;
+
+ asanThreadRegistry().Init();
+ asanThreadRegistry().GetMain()->ThreadStart();
+ force_interface_symbols(); // no-op.
+
+ InitializeAllocator();
+
+ if (flags()->verbosity) {
+ Report("AddressSanitizer Init done\n");
+ }
+}
diff --git a/gcc-4.8/libsanitizer/asan/asan_stack.cc b/gcc-4.8/libsanitizer/asan/asan_stack.cc
new file mode 100644
index 000000000..999cbfba7
--- /dev/null
+++ b/gcc-4.8/libsanitizer/asan/asan_stack.cc
@@ -0,0 +1,41 @@
+//===-- asan_stack.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.
+//
+// Code for ASan stack trace.
+//===----------------------------------------------------------------------===//
+#include "asan_internal.h"
+#include "asan_flags.h"
+#include "asan_stack.h"
+
+namespace __asan {
+
+static bool MaybeCallAsanSymbolize(const void *pc, char *out_buffer,
+ int out_size) {
+ return (&__asan_symbolize) ? __asan_symbolize(pc, out_buffer, out_size)
+ : false;
+}
+
+void PrintStack(StackTrace *stack) {
+ stack->PrintStack(stack->trace, stack->size, flags()->symbolize,
+ flags()->strip_path_prefix, MaybeCallAsanSymbolize);
+}
+
+} // namespace __asan
+
+// ------------------ Interface -------------- {{{1
+
+// Provide default implementation of __asan_symbolize that does nothing
+// and may be overriden by user if he wants to use his own symbolization.
+// ASan on Windows has its own implementation of this.
+#if !defined(_WIN32) && !SANITIZER_SUPPORTS_WEAK_HOOKS
+SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE NOINLINE
+bool __asan_symbolize(const void *pc, char *out_buffer, int out_size) {
+ return false;
+}
+#endif
diff --git a/gcc-4.8/libsanitizer/asan/asan_stack.h b/gcc-4.8/libsanitizer/asan/asan_stack.h
new file mode 100644
index 000000000..6a5ffc934
--- /dev/null
+++ b/gcc-4.8/libsanitizer/asan/asan_stack.h
@@ -0,0 +1,64 @@
+//===-- asan_stack.h --------------------------------------------*- C++ -*-===//
+//
+// 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.
+//
+// ASan-private header for asan_stack.cc.
+//===----------------------------------------------------------------------===//
+#ifndef ASAN_STACK_H
+#define ASAN_STACK_H
+
+#include "sanitizer_common/sanitizer_stacktrace.h"
+#include "asan_flags.h"
+
+namespace __asan {
+
+void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp, bool fast);
+void PrintStack(StackTrace *stack);
+
+} // namespace __asan
+
+// Get the stack trace with the given pc and bp.
+// The pc will be in the position 0 of the resulting stack trace.
+// The bp may refer to the current frame or to the caller's frame.
+// fast_unwind is currently unused.
+#define GET_STACK_TRACE_WITH_PC_AND_BP(max_s, pc, bp, fast) \
+ StackTrace stack; \
+ GetStackTrace(&stack, max_s, pc, bp, fast)
+
+// NOTE: A Rule of thumb is to retrieve stack trace in the interceptors
+// as early as possible (in functions exposed to the user), as we generally
+// don't want stack trace to contain functions from ASan internals.
+
+#define GET_STACK_TRACE(max_size, fast) \
+ GET_STACK_TRACE_WITH_PC_AND_BP(max_size, \
+ StackTrace::GetCurrentPc(), GET_CURRENT_FRAME(), fast)
+
+#define GET_STACK_TRACE_FATAL(pc, bp) \
+ GET_STACK_TRACE_WITH_PC_AND_BP(kStackTraceMax, pc, bp, \
+ flags()->fast_unwind_on_fatal)
+
+#define GET_STACK_TRACE_FATAL_HERE \
+ GET_STACK_TRACE(kStackTraceMax, flags()->fast_unwind_on_fatal)
+
+#define GET_STACK_TRACE_THREAD \
+ GET_STACK_TRACE(kStackTraceMax, true)
+
+#define GET_STACK_TRACE_MALLOC \
+ GET_STACK_TRACE(flags()->malloc_context_size, \
+ flags()->fast_unwind_on_malloc)
+
+#define GET_STACK_TRACE_FREE GET_STACK_TRACE_MALLOC
+
+#define PRINT_CURRENT_STACK() \
+ { \
+ GET_STACK_TRACE(kStackTraceMax, \
+ flags()->fast_unwind_on_fatal); \
+ PrintStack(&stack); \
+ }
+
+#endif // ASAN_STACK_H
diff --git a/gcc-4.8/libsanitizer/asan/asan_stats.cc b/gcc-4.8/libsanitizer/asan/asan_stats.cc
new file mode 100644
index 000000000..935b33e20
--- /dev/null
+++ b/gcc-4.8/libsanitizer/asan/asan_stats.cc
@@ -0,0 +1,91 @@
+//===-- asan_stats.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.
+//
+// Code related to statistics collected by AddressSanitizer.
+//===----------------------------------------------------------------------===//
+#include "asan_interceptors.h"
+#include "asan_internal.h"
+#include "asan_stats.h"
+#include "asan_thread_registry.h"
+#include "sanitizer_common/sanitizer_stackdepot.h"
+
+namespace __asan {
+
+AsanStats::AsanStats() {
+ CHECK(REAL(memset) != 0);
+ REAL(memset)(this, 0, sizeof(AsanStats));
+}
+
+static void PrintMallocStatsArray(const char *prefix,
+ uptr (&array)[kNumberOfSizeClasses]) {
+ Printf("%s", prefix);
+ for (uptr i = 0; i < kNumberOfSizeClasses; i++) {
+ if (!array[i]) continue;
+ Printf("%zu:%zu; ", i, array[i]);
+ }
+ Printf("\n");
+}
+
+void AsanStats::Print() {
+ Printf("Stats: %zuM malloced (%zuM for red zones) by %zu calls\n",
+ malloced>>20, malloced_redzones>>20, mallocs);
+ Printf("Stats: %zuM realloced by %zu calls\n", realloced>>20, reallocs);
+ Printf("Stats: %zuM freed by %zu calls\n", freed>>20, frees);
+ Printf("Stats: %zuM really freed by %zu calls\n",
+ really_freed>>20, real_frees);
+ Printf("Stats: %zuM (%zuM-%zuM) mmaped; %zu maps, %zu unmaps\n",
+ (mmaped-munmaped)>>20, mmaped>>20, munmaped>>20,
+ mmaps, munmaps);
+
+ PrintMallocStatsArray(" mmaps by size class: ", mmaped_by_size);
+ PrintMallocStatsArray(" mallocs by size class: ", malloced_by_size);
+ PrintMallocStatsArray(" frees by size class: ", freed_by_size);
+ PrintMallocStatsArray(" rfrees by size class: ", really_freed_by_size);
+ Printf("Stats: malloc large: %zu small slow: %zu\n",
+ malloc_large, malloc_small_slow);
+}
+
+static BlockingMutex print_lock(LINKER_INITIALIZED);
+
+static void PrintAccumulatedStats() {
+ AsanStats stats;
+ asanThreadRegistry().GetAccumulatedStats(&stats);
+ // Use lock to keep reports from mixing up.
+ BlockingMutexLock lock(&print_lock);
+ stats.Print();
+ StackDepotStats *stack_depot_stats = StackDepotGetStats();
+ Printf("Stats: StackDepot: %zd ids; %zdM mapped\n",
+ stack_depot_stats->n_uniq_ids, stack_depot_stats->mapped >> 20);
+ PrintInternalAllocatorStats();
+}
+
+} // namespace __asan
+
+// ---------------------- Interface ---------------- {{{1
+using namespace __asan; // NOLINT
+
+uptr __asan_get_current_allocated_bytes() {
+ return asanThreadRegistry().GetCurrentAllocatedBytes();
+}
+
+uptr __asan_get_heap_size() {
+ return asanThreadRegistry().GetHeapSize();
+}
+
+uptr __asan_get_free_bytes() {
+ return asanThreadRegistry().GetFreeBytes();
+}
+
+uptr __asan_get_unmapped_bytes() {
+ return 0;
+}
+
+void __asan_print_accumulated_stats() {
+ PrintAccumulatedStats();
+}
diff --git a/gcc-4.8/libsanitizer/asan/asan_stats.h b/gcc-4.8/libsanitizer/asan/asan_stats.h
new file mode 100644
index 000000000..fd27451ae
--- /dev/null
+++ b/gcc-4.8/libsanitizer/asan/asan_stats.h
@@ -0,0 +1,67 @@
+//===-- asan_stats.h --------------------------------------------*- C++ -*-===//
+//
+// 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.
+//
+// ASan-private header for statistics.
+//===----------------------------------------------------------------------===//
+#ifndef ASAN_STATS_H
+#define ASAN_STATS_H
+
+#include "asan_allocator.h"
+#include "asan_internal.h"
+
+namespace __asan {
+
+// AsanStats struct is NOT thread-safe.
+// Each AsanThread has its own AsanStats, which are sometimes flushed
+// to the accumulated AsanStats.
+struct AsanStats {
+ // AsanStats must be a struct consisting of uptr fields only.
+ // When merging two AsanStats structs, we treat them as arrays of uptr.
+ uptr mallocs;
+ uptr malloced;
+ uptr malloced_redzones;
+ uptr frees;
+ uptr freed;
+ uptr real_frees;
+ uptr really_freed;
+ uptr really_freed_redzones;
+ uptr reallocs;
+ uptr realloced;
+ uptr mmaps;
+ uptr mmaped;
+ uptr munmaps;
+ uptr munmaped;
+ uptr mmaped_by_size[kNumberOfSizeClasses];
+ uptr malloced_by_size[kNumberOfSizeClasses];
+ uptr freed_by_size[kNumberOfSizeClasses];
+ uptr really_freed_by_size[kNumberOfSizeClasses];
+
+ uptr malloc_large;
+ uptr malloc_small_slow;
+
+ // Ctor for global AsanStats (accumulated stats and main thread stats).
+ explicit AsanStats(LinkerInitialized) { }
+ // Default ctor for thread-local stats.
+ AsanStats();
+
+ // Prints formatted stats to stderr.
+ void Print();
+};
+
+// A cross-platform equivalent of malloc_statistics_t on Mac OS.
+struct AsanMallocStats {
+ uptr blocks_in_use;
+ uptr size_in_use;
+ uptr max_size_in_use;
+ uptr size_allocated;
+};
+
+} // namespace __asan
+
+#endif // ASAN_STATS_H
diff --git a/gcc-4.8/libsanitizer/asan/asan_thread.cc b/gcc-4.8/libsanitizer/asan/asan_thread.cc
new file mode 100644
index 000000000..02f49dd59
--- /dev/null
+++ b/gcc-4.8/libsanitizer/asan/asan_thread.cc
@@ -0,0 +1,153 @@
+//===-- asan_thread.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.
+//
+// Thread-related code.
+//===----------------------------------------------------------------------===//
+#include "asan_allocator.h"
+#include "asan_interceptors.h"
+#include "asan_stack.h"
+#include "asan_thread.h"
+#include "asan_thread_registry.h"
+#include "asan_mapping.h"
+#include "sanitizer_common/sanitizer_common.h"
+
+namespace __asan {
+
+AsanThread::AsanThread(LinkerInitialized x)
+ : fake_stack_(x),
+ malloc_storage_(x),
+ stats_(x) { }
+
+AsanThread *AsanThread::Create(u32 parent_tid, thread_callback_t start_routine,
+ void *arg, StackTrace *stack) {
+ uptr PageSize = GetPageSizeCached();
+ uptr size = RoundUpTo(sizeof(AsanThread), PageSize);
+ AsanThread *thread = (AsanThread*)MmapOrDie(size, __FUNCTION__);
+ thread->start_routine_ = start_routine;
+ thread->arg_ = arg;
+
+ const uptr kSummaryAllocSize = PageSize;
+ CHECK_LE(sizeof(AsanThreadSummary), kSummaryAllocSize);
+ AsanThreadSummary *summary =
+ (AsanThreadSummary*)MmapOrDie(PageSize, "AsanThreadSummary");
+ summary->Init(parent_tid, stack);
+ summary->set_thread(thread);
+ thread->set_summary(summary);
+
+ return thread;
+}
+
+void AsanThreadSummary::TSDDtor(void *tsd) {
+ AsanThreadSummary *summary = (AsanThreadSummary*)tsd;
+ if (flags()->verbosity >= 1) {
+ Report("T%d TSDDtor\n", summary->tid());
+ }
+ if (summary->thread()) {
+ summary->thread()->Destroy();
+ }
+}
+
+void AsanThread::Destroy() {
+ if (flags()->verbosity >= 1) {
+ Report("T%d exited\n", tid());
+ }
+
+ asanThreadRegistry().UnregisterThread(this);
+ CHECK(summary()->thread() == 0);
+ // We also clear the shadow on thread destruction because
+ // some code may still be executing in later TSD destructors
+ // and we don't want it to have any poisoned stack.
+ ClearShadowForThreadStack();
+ fake_stack().Cleanup();
+ uptr size = RoundUpTo(sizeof(AsanThread), GetPageSizeCached());
+ UnmapOrDie(this, size);
+}
+
+void AsanThread::Init() {
+ SetThreadStackTopAndBottom();
+ CHECK(AddrIsInMem(stack_bottom_));
+ CHECK(AddrIsInMem(stack_top_ - 1));
+ ClearShadowForThreadStack();
+ if (flags()->verbosity >= 1) {
+ int local = 0;
+ Report("T%d: stack [%p,%p) size 0x%zx; local=%p\n",
+ tid(), (void*)stack_bottom_, (void*)stack_top_,
+ stack_top_ - stack_bottom_, &local);
+ }
+ fake_stack_.Init(stack_size());
+ AsanPlatformThreadInit();
+}
+
+thread_return_t AsanThread::ThreadStart() {
+ Init();
+ if (flags()->use_sigaltstack) SetAlternateSignalStack();
+
+ if (!start_routine_) {
+ // start_routine_ == 0 if we're on the main thread or on one of the
+ // OS X libdispatch worker threads. But nobody is supposed to call
+ // ThreadStart() for the worker threads.
+ CHECK(tid() == 0);
+ return 0;
+ }
+
+ thread_return_t res = start_routine_(arg_);
+ malloc_storage().CommitBack();
+ if (flags()->use_sigaltstack) UnsetAlternateSignalStack();
+
+ this->Destroy();
+
+ return res;
+}
+
+void AsanThread::SetThreadStackTopAndBottom() {
+ GetThreadStackTopAndBottom(tid() == 0, &stack_top_, &stack_bottom_);
+ int local;
+ CHECK(AddrIsInStack((uptr)&local));
+}
+
+void AsanThread::ClearShadowForThreadStack() {
+ PoisonShadow(stack_bottom_, stack_top_ - stack_bottom_, 0);
+}
+
+const char *AsanThread::GetFrameNameByAddr(uptr addr, uptr *offset) {
+ uptr bottom = 0;
+ if (AddrIsInStack(addr)) {
+ bottom = stack_bottom();
+ } else {
+ bottom = fake_stack().AddrIsInFakeStack(addr);
+ CHECK(bottom);
+ *offset = addr - bottom;
+ return (const char *)((uptr*)bottom)[1];
+ }
+ uptr aligned_addr = addr & ~(SANITIZER_WORDSIZE/8 - 1); // align addr.
+ u8 *shadow_ptr = (u8*)MemToShadow(aligned_addr);
+ u8 *shadow_bottom = (u8*)MemToShadow(bottom);
+
+ while (shadow_ptr >= shadow_bottom &&
+ *shadow_ptr != kAsanStackLeftRedzoneMagic) {
+ shadow_ptr--;
+ }
+
+ while (shadow_ptr >= shadow_bottom &&
+ *shadow_ptr == kAsanStackLeftRedzoneMagic) {
+ shadow_ptr--;
+ }
+
+ if (shadow_ptr < shadow_bottom) {
+ *offset = 0;
+ return "UNKNOWN";
+ }
+
+ uptr* ptr = (uptr*)SHADOW_TO_MEM((uptr)(shadow_ptr + 1));
+ CHECK(ptr[0] == kCurrentStackFrameMagic);
+ *offset = addr - (uptr)ptr;
+ return (const char*)ptr[1];
+}
+
+} // namespace __asan
diff --git a/gcc-4.8/libsanitizer/asan/asan_thread.h b/gcc-4.8/libsanitizer/asan/asan_thread.h
new file mode 100644
index 000000000..f385ec35f
--- /dev/null
+++ b/gcc-4.8/libsanitizer/asan/asan_thread.h
@@ -0,0 +1,112 @@
+//===-- asan_thread.h -------------------------------------------*- C++ -*-===//
+//
+// 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.
+//
+// ASan-private header for asan_thread.cc.
+//===----------------------------------------------------------------------===//
+#ifndef ASAN_THREAD_H
+#define ASAN_THREAD_H
+
+#include "asan_allocator.h"
+#include "asan_internal.h"
+#include "asan_stack.h"
+#include "asan_stats.h"
+#include "sanitizer_common/sanitizer_libc.h"
+
+namespace __asan {
+
+const u32 kInvalidTid = 0xffffff; // Must fit into 24 bits.
+
+class AsanThread;
+
+// These objects are created for every thread and are never deleted,
+// so we can find them by tid even if the thread is long dead.
+class AsanThreadSummary {
+ public:
+ explicit AsanThreadSummary(LinkerInitialized) { } // for T0.
+ void Init(u32 parent_tid, StackTrace *stack) {
+ parent_tid_ = parent_tid;
+ announced_ = false;
+ tid_ = kInvalidTid;
+ if (stack) {
+ internal_memcpy(&stack_, stack, sizeof(*stack));
+ }
+ thread_ = 0;
+ name_[0] = 0;
+ }
+ u32 tid() { return tid_; }
+ void set_tid(u32 tid) { tid_ = tid; }
+ u32 parent_tid() { return parent_tid_; }
+ bool announced() { return announced_; }
+ void set_announced(bool announced) { announced_ = announced; }
+ StackTrace *stack() { return &stack_; }
+ AsanThread *thread() { return thread_; }
+ void set_thread(AsanThread *thread) { thread_ = thread; }
+ static void TSDDtor(void *tsd);
+ void set_name(const char *name) {
+ internal_strncpy(name_, name, sizeof(name_) - 1);
+ }
+ const char *name() { return name_; }
+
+ private:
+ u32 tid_;
+ u32 parent_tid_;
+ bool announced_;
+ StackTrace stack_;
+ AsanThread *thread_;
+ char name_[128];
+};
+
+// AsanThreadSummary objects are never freed, so we need many of them.
+COMPILER_CHECK(sizeof(AsanThreadSummary) <= 4094);
+
+// AsanThread are stored in TSD and destroyed when the thread dies.
+class AsanThread {
+ public:
+ explicit AsanThread(LinkerInitialized); // for T0.
+ static AsanThread *Create(u32 parent_tid, thread_callback_t start_routine,
+ void *arg, StackTrace *stack);
+ void Destroy();
+
+ void Init(); // Should be called from the thread itself.
+ thread_return_t ThreadStart();
+
+ uptr stack_top() { return stack_top_; }
+ uptr stack_bottom() { return stack_bottom_; }
+ uptr stack_size() { return stack_top_ - stack_bottom_; }
+ u32 tid() { return summary_->tid(); }
+ AsanThreadSummary *summary() { return summary_; }
+ void set_summary(AsanThreadSummary *summary) { summary_ = summary; }
+
+ const char *GetFrameNameByAddr(uptr addr, uptr *offset);
+
+ bool AddrIsInStack(uptr addr) {
+ return addr >= stack_bottom_ && addr < stack_top_;
+ }
+
+ FakeStack &fake_stack() { return fake_stack_; }
+ AsanThreadLocalMallocStorage &malloc_storage() { return malloc_storage_; }
+ AsanStats &stats() { return stats_; }
+
+ private:
+ void SetThreadStackTopAndBottom();
+ void ClearShadowForThreadStack();
+ AsanThreadSummary *summary_;
+ thread_callback_t start_routine_;
+ void *arg_;
+ uptr stack_top_;
+ uptr stack_bottom_;
+
+ FakeStack fake_stack_;
+ AsanThreadLocalMallocStorage malloc_storage_;
+ AsanStats stats_;
+};
+
+} // namespace __asan
+
+#endif // ASAN_THREAD_H
diff --git a/gcc-4.8/libsanitizer/asan/asan_thread_registry.cc b/gcc-4.8/libsanitizer/asan/asan_thread_registry.cc
new file mode 100644
index 000000000..8fda9b6ea
--- /dev/null
+++ b/gcc-4.8/libsanitizer/asan/asan_thread_registry.cc
@@ -0,0 +1,196 @@
+//===-- asan_thread_registry.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.
+//
+// AsanThreadRegistry-related code. AsanThreadRegistry is a container
+// for summaries of all created threads.
+//===----------------------------------------------------------------------===//
+
+#include "asan_stack.h"
+#include "asan_thread.h"
+#include "asan_thread_registry.h"
+#include "sanitizer_common/sanitizer_common.h"
+
+namespace __asan {
+
+static AsanThreadRegistry asan_thread_registry(LINKER_INITIALIZED);
+
+AsanThreadRegistry &asanThreadRegistry() {
+ return asan_thread_registry;
+}
+
+AsanThreadRegistry::AsanThreadRegistry(LinkerInitialized x)
+ : main_thread_(x),
+ main_thread_summary_(x),
+ accumulated_stats_(x),
+ max_malloced_memory_(x),
+ mu_(x) { }
+
+void AsanThreadRegistry::Init() {
+ AsanTSDInit(AsanThreadSummary::TSDDtor);
+ main_thread_.set_summary(&main_thread_summary_);
+ main_thread_summary_.set_thread(&main_thread_);
+ RegisterThread(&main_thread_);
+ SetCurrent(&main_thread_);
+ // At this point only one thread exists.
+ inited_ = true;
+}
+
+void AsanThreadRegistry::RegisterThread(AsanThread *thread) {
+ BlockingMutexLock lock(&mu_);
+ u32 tid = n_threads_;
+ n_threads_++;
+ CHECK(n_threads_ < kMaxNumberOfThreads);
+
+ AsanThreadSummary *summary = thread->summary();
+ CHECK(summary != 0);
+ summary->set_tid(tid);
+ thread_summaries_[tid] = summary;
+}
+
+void AsanThreadRegistry::UnregisterThread(AsanThread *thread) {
+ BlockingMutexLock lock(&mu_);
+ FlushToAccumulatedStatsUnlocked(&thread->stats());
+ AsanThreadSummary *summary = thread->summary();
+ CHECK(summary);
+ summary->set_thread(0);
+}
+
+AsanThread *AsanThreadRegistry::GetMain() {
+ return &main_thread_;
+}
+
+AsanThread *AsanThreadRegistry::GetCurrent() {
+ AsanThreadSummary *summary = (AsanThreadSummary *)AsanTSDGet();
+ if (!summary) {
+#if ASAN_ANDROID
+ // On Android, libc constructor is called _after_ asan_init, and cleans up
+ // TSD. Try to figure out if this is still the main thread by the stack
+ // address. We are not entirely sure that we have correct main thread
+ // limits, so only do this magic on Android, and only if the found thread is
+ // the main thread.
+ AsanThread* thread = FindThreadByStackAddress((uptr)&summary);
+ if (thread && thread->tid() == 0) {
+ SetCurrent(thread);
+ return thread;
+ }
+#endif
+ return 0;
+ }
+ return summary->thread();
+}
+
+void AsanThreadRegistry::SetCurrent(AsanThread *t) {
+ CHECK(t->summary());
+ if (flags()->verbosity >= 2) {
+ Report("SetCurrent: %p for thread %p\n",
+ t->summary(), (void*)GetThreadSelf());
+ }
+ // Make sure we do not reset the current AsanThread.
+ CHECK(AsanTSDGet() == 0);
+ AsanTSDSet(t->summary());
+ CHECK(AsanTSDGet() == t->summary());
+}
+
+AsanStats &AsanThreadRegistry::GetCurrentThreadStats() {
+ AsanThread *t = GetCurrent();
+ return (t) ? t->stats() : main_thread_.stats();
+}
+
+void AsanThreadRegistry::GetAccumulatedStats(AsanStats *stats) {
+ BlockingMutexLock lock(&mu_);
+ UpdateAccumulatedStatsUnlocked();
+ internal_memcpy(stats, &accumulated_stats_, sizeof(accumulated_stats_));
+}
+
+uptr AsanThreadRegistry::GetCurrentAllocatedBytes() {
+ BlockingMutexLock lock(&mu_);
+ UpdateAccumulatedStatsUnlocked();
+ uptr malloced = accumulated_stats_.malloced;
+ uptr freed = accumulated_stats_.freed;
+ // Return sane value if malloced < freed due to racy
+ // way we update accumulated stats.
+ return (malloced > freed) ? malloced - freed : 1;
+}
+
+uptr AsanThreadRegistry::GetHeapSize() {
+ BlockingMutexLock lock(&mu_);
+ UpdateAccumulatedStatsUnlocked();
+ return accumulated_stats_.mmaped - accumulated_stats_.munmaped;
+}
+
+uptr AsanThreadRegistry::GetFreeBytes() {
+ BlockingMutexLock lock(&mu_);
+ UpdateAccumulatedStatsUnlocked();
+ uptr total_free = accumulated_stats_.mmaped
+ - accumulated_stats_.munmaped
+ + accumulated_stats_.really_freed
+ + accumulated_stats_.really_freed_redzones;
+ uptr total_used = accumulated_stats_.malloced
+ + accumulated_stats_.malloced_redzones;
+ // Return sane value if total_free < total_used due to racy
+ // way we update accumulated stats.
+ return (total_free > total_used) ? total_free - total_used : 1;
+}
+
+// Return several stats counters with a single call to
+// UpdateAccumulatedStatsUnlocked().
+void AsanThreadRegistry::FillMallocStatistics(AsanMallocStats *malloc_stats) {
+ BlockingMutexLock lock(&mu_);
+ UpdateAccumulatedStatsUnlocked();
+ malloc_stats->blocks_in_use = accumulated_stats_.mallocs;
+ malloc_stats->size_in_use = accumulated_stats_.malloced;
+ malloc_stats->max_size_in_use = max_malloced_memory_;
+ malloc_stats->size_allocated = accumulated_stats_.mmaped;
+}
+
+AsanThreadSummary *AsanThreadRegistry::FindByTid(u32 tid) {
+ CHECK(tid < n_threads_);
+ CHECK(thread_summaries_[tid]);
+ return thread_summaries_[tid];
+}
+
+AsanThread *AsanThreadRegistry::FindThreadByStackAddress(uptr addr) {
+ BlockingMutexLock lock(&mu_);
+ for (u32 tid = 0; tid < n_threads_; tid++) {
+ AsanThread *t = thread_summaries_[tid]->thread();
+ if (!t || !(t->fake_stack().StackSize())) continue;
+ if (t->fake_stack().AddrIsInFakeStack(addr) || t->AddrIsInStack(addr)) {
+ return t;
+ }
+ }
+ return 0;
+}
+
+void AsanThreadRegistry::UpdateAccumulatedStatsUnlocked() {
+ for (u32 tid = 0; tid < n_threads_; tid++) {
+ AsanThread *t = thread_summaries_[tid]->thread();
+ if (t != 0) {
+ FlushToAccumulatedStatsUnlocked(&t->stats());
+ }
+ }
+ // This is not very accurate: we may miss allocation peaks that happen
+ // between two updates of accumulated_stats_. For more accurate bookkeeping
+ // the maximum should be updated on every malloc(), which is unacceptable.
+ if (max_malloced_memory_ < accumulated_stats_.malloced) {
+ max_malloced_memory_ = accumulated_stats_.malloced;
+ }
+}
+
+void AsanThreadRegistry::FlushToAccumulatedStatsUnlocked(AsanStats *stats) {
+ // AsanStats consists of variables of type uptr only.
+ uptr *dst = (uptr*)&accumulated_stats_;
+ uptr *src = (uptr*)stats;
+ uptr num_fields = sizeof(AsanStats) / sizeof(uptr);
+ for (uptr i = 0; i < num_fields; i++) {
+ dst[i] += src[i];
+ src[i] = 0;
+ }
+}
+
+} // namespace __asan
diff --git a/gcc-4.8/libsanitizer/asan/asan_thread_registry.h b/gcc-4.8/libsanitizer/asan/asan_thread_registry.h
new file mode 100644
index 000000000..8c3d0c886
--- /dev/null
+++ b/gcc-4.8/libsanitizer/asan/asan_thread_registry.h
@@ -0,0 +1,83 @@
+//===-- asan_thread_registry.h ----------------------------------*- C++ -*-===//
+//
+// 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.
+//
+// ASan-private header for asan_thread_registry.cc
+//===----------------------------------------------------------------------===//
+
+#ifndef ASAN_THREAD_REGISTRY_H
+#define ASAN_THREAD_REGISTRY_H
+
+#include "asan_stack.h"
+#include "asan_stats.h"
+#include "asan_thread.h"
+#include "sanitizer_common/sanitizer_mutex.h"
+
+namespace __asan {
+
+// Stores summaries of all created threads, returns current thread,
+// thread by tid, thread by stack address. There is a single instance
+// of AsanThreadRegistry for the whole program.
+// AsanThreadRegistry is thread-safe.
+class AsanThreadRegistry {
+ public:
+ explicit AsanThreadRegistry(LinkerInitialized);
+ void Init();
+ void RegisterThread(AsanThread *thread);
+ void UnregisterThread(AsanThread *thread);
+
+ AsanThread *GetMain();
+ // Get the current thread. May return 0.
+ AsanThread *GetCurrent();
+ void SetCurrent(AsanThread *t);
+
+ u32 GetCurrentTidOrInvalid() {
+ if (!inited_) return 0;
+ AsanThread *t = GetCurrent();
+ return t ? t->tid() : kInvalidTid;
+ }
+
+ // Returns stats for GetCurrent(), or stats for
+ // T0 if GetCurrent() returns 0.
+ AsanStats &GetCurrentThreadStats();
+ // Flushes all thread-local stats to accumulated stats, and makes
+ // a copy of accumulated stats.
+ void GetAccumulatedStats(AsanStats *stats);
+ uptr GetCurrentAllocatedBytes();
+ uptr GetHeapSize();
+ uptr GetFreeBytes();
+ void FillMallocStatistics(AsanMallocStats *malloc_stats);
+
+ AsanThreadSummary *FindByTid(u32 tid);
+ AsanThread *FindThreadByStackAddress(uptr addr);
+
+ private:
+ void UpdateAccumulatedStatsUnlocked();
+ // Adds values of all counters in "stats" to accumulated stats,
+ // and fills "stats" with zeroes.
+ void FlushToAccumulatedStatsUnlocked(AsanStats *stats);
+
+ static const u32 kMaxNumberOfThreads = (1 << 22); // 4M
+ AsanThreadSummary *thread_summaries_[kMaxNumberOfThreads];
+ AsanThread main_thread_;
+ AsanThreadSummary main_thread_summary_;
+ AsanStats accumulated_stats_;
+ // Required for malloc_zone_statistics() on OS X. This can't be stored in
+ // per-thread AsanStats.
+ uptr max_malloced_memory_;
+ u32 n_threads_;
+ BlockingMutex mu_;
+ bool inited_;
+};
+
+// Returns a single instance of registry.
+AsanThreadRegistry &asanThreadRegistry();
+
+} // namespace __asan
+
+#endif // ASAN_THREAD_REGISTRY_H
diff --git a/gcc-4.8/libsanitizer/asan/asan_win.cc b/gcc-4.8/libsanitizer/asan/asan_win.cc
new file mode 100644
index 000000000..6acfeebc8
--- /dev/null
+++ b/gcc-4.8/libsanitizer/asan/asan_win.cc
@@ -0,0 +1,157 @@
+//===-- asan_win.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.
+//
+// Windows-specific details.
+//===----------------------------------------------------------------------===//
+#ifdef _WIN32
+#include <windows.h>
+
+#include <dbghelp.h>
+#include <stdlib.h>
+
+#include "asan_interceptors.h"
+#include "asan_internal.h"
+#include "asan_thread.h"
+#include "sanitizer_common/sanitizer_libc.h"
+#include "sanitizer_common/sanitizer_mutex.h"
+
+namespace __asan {
+
+// ---------------------- Stacktraces, symbols, etc. ---------------- {{{1
+static BlockingMutex dbghelp_lock(LINKER_INITIALIZED);
+static bool dbghelp_initialized = false;
+#pragma comment(lib, "dbghelp.lib")
+
+void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp, bool fast) {
+ (void)fast;
+ stack->max_size = max_s;
+ void *tmp[kStackTraceMax];
+
+ // FIXME: CaptureStackBackTrace might be too slow for us.
+ // FIXME: Compare with StackWalk64.
+ // FIXME: Look at LLVMUnhandledExceptionFilter in Signals.inc
+ uptr cs_ret = CaptureStackBackTrace(1, stack->max_size, tmp, 0);
+ uptr offset = 0;
+ // Skip the RTL frames by searching for the PC in the stacktrace.
+ // FIXME: this doesn't work well for the malloc/free stacks yet.
+ for (uptr i = 0; i < cs_ret; i++) {
+ if (pc != (uptr)tmp[i])
+ continue;
+ offset = i;
+ break;
+ }
+
+ stack->size = cs_ret - offset;
+ for (uptr i = 0; i < stack->size; i++)
+ stack->trace[i] = (uptr)tmp[i + offset];
+}
+
+// ---------------------- TSD ---------------- {{{1
+static bool tsd_key_inited = false;
+
+static __declspec(thread) void *fake_tsd = 0;
+
+void AsanTSDInit(void (*destructor)(void *tsd)) {
+ // FIXME: we're ignoring the destructor for now.
+ tsd_key_inited = true;
+}
+
+void *AsanTSDGet() {
+ CHECK(tsd_key_inited);
+ return fake_tsd;
+}
+
+void AsanTSDSet(void *tsd) {
+ CHECK(tsd_key_inited);
+ fake_tsd = tsd;
+}
+
+// ---------------------- Various stuff ---------------- {{{1
+void MaybeReexec() {
+ // No need to re-exec on Windows.
+}
+
+void *AsanDoesNotSupportStaticLinkage() {
+#if defined(_DEBUG)
+#error Please build the runtime with a non-debug CRT: /MD or /MT
+#endif
+ return 0;
+}
+
+void SetAlternateSignalStack() {
+ // FIXME: Decide what to do on Windows.
+}
+
+void UnsetAlternateSignalStack() {
+ // FIXME: Decide what to do on Windows.
+}
+
+void InstallSignalHandlers() {
+ // FIXME: Decide what to do on Windows.
+}
+
+void AsanPlatformThreadInit() {
+ // Nothing here for now.
+}
+
+void ReadContextStack(void *context, uptr *stack, uptr *ssize) {
+ UNIMPLEMENTED();
+}
+
+} // namespace __asan
+
+// ---------------------- Interface ---------------- {{{1
+using namespace __asan; // NOLINT
+
+extern "C" {
+SANITIZER_INTERFACE_ATTRIBUTE NOINLINE
+bool __asan_symbolize(const void *addr, char *out_buffer, int buffer_size) {
+ BlockingMutexLock lock(&dbghelp_lock);
+ if (!dbghelp_initialized) {
+ SymSetOptions(SYMOPT_DEFERRED_LOADS |
+ SYMOPT_UNDNAME |
+ SYMOPT_LOAD_LINES);
+ CHECK(SymInitialize(GetCurrentProcess(), 0, TRUE));
+ // FIXME: We don't call SymCleanup() on exit yet - should we?
+ dbghelp_initialized = true;
+ }
+
+ // See http://msdn.microsoft.com/en-us/library/ms680578(VS.85).aspx
+ char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(CHAR)];
+ PSYMBOL_INFO symbol = (PSYMBOL_INFO)buffer;
+ symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
+ symbol->MaxNameLen = MAX_SYM_NAME;
+ DWORD64 offset = 0;
+ BOOL got_objname = SymFromAddr(GetCurrentProcess(),
+ (DWORD64)addr, &offset, symbol);
+ if (!got_objname)
+ return false;
+
+ DWORD unused;
+ IMAGEHLP_LINE64 info;
+ info.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
+ BOOL got_fileline = SymGetLineFromAddr64(GetCurrentProcess(),
+ (DWORD64)addr, &unused, &info);
+ int written = 0;
+ out_buffer[0] = '\0';
+ // FIXME: it might be useful to print out 'obj' or 'obj+offset' info too.
+ if (got_fileline) {
+ written += internal_snprintf(out_buffer + written, buffer_size - written,
+ " %s %s:%d", symbol->Name,
+ info.FileName, info.LineNumber);
+ } else {
+ written += internal_snprintf(out_buffer + written, buffer_size - written,
+ " %s+0x%p", symbol->Name, offset);
+ }
+ return true;
+}
+} // extern "C"
+
+
+#endif // _WIN32
diff --git a/gcc-4.8/libsanitizer/asan/libtool-version b/gcc-4.8/libsanitizer/asan/libtool-version
new file mode 100644
index 000000000..204fdd2d8
--- /dev/null
+++ b/gcc-4.8/libsanitizer/asan/libtool-version
@@ -0,0 +1,6 @@
+# This file is used to maintain libtool version info for libmudflap. See
+# the libtool manual to understand the meaning of the fields. This is
+# a separate file so that version updates don't involve re-running
+# automake.
+# CURRENT:REVISION:AGE
+0:0:0