Merge "Workaround for libportable wait4 implementation."
diff --git a/ndk/platforms/android-3/include/inttypes.h b/ndk/platforms/android-3/include/inttypes.h
index 81d2315..73b22db 100644
--- a/ndk/platforms/android-3/include/inttypes.h
+++ b/ndk/platforms/android-3/include/inttypes.h
@@ -56,7 +56,7 @@
 #define	PRIdFAST64		"lld"		/* int_fast64_t */
 
 #define	PRIdMAX			"jd"		/* intmax_t */
-#define	PRIdPTR			"ld"		/* intptr_t */
+#define	PRIdPTR			"d"		/* intptr_t */
 
 #define	PRIi8			"i"		/* int8_t */
 #define	PRIi16			"i"		/* int16_t */
@@ -74,7 +74,7 @@
 #define	PRIiFAST64		"lli"		/* int_fast64_t */
 
 #define	PRIiMAX			"ji"		/* intmax_t */
-#define	PRIiPTR			"li"		/* intptr_t */
+#define	PRIiPTR			"i"		/* intptr_t */
 
 /* fprintf macros for unsigned integers */
 #define	PRIo8			"o"		/* int8_t */
@@ -93,7 +93,7 @@
 #define	PRIoFAST64		"llo"		/* int_fast64_t */
 
 #define	PRIoMAX			"jo"		/* intmax_t */
-#define	PRIoPTR			"lo"		/* intptr_t */
+#define	PRIoPTR			"o"		/* intptr_t */
 
 #define	PRIu8			"u"		/* uint8_t */
 #define	PRIu16			"u"		/* uint16_t */
@@ -111,7 +111,7 @@
 #define	PRIuFAST64		"llu"		/* uint_fast64_t */
 
 #define	PRIuMAX			"ju"		/* uintmax_t */
-#define	PRIuPTR			"lu"		/* uintptr_t */
+#define	PRIuPTR			"u"		/* uintptr_t */
 
 #define	PRIx8			"x"		/* uint8_t */
 #define	PRIx16			"x"		/* uint16_t */
@@ -129,7 +129,7 @@
 #define	PRIxFAST64		"llx"		/* uint_fast64_t */
 
 #define	PRIxMAX			"jx"		/* uintmax_t */
-#define	PRIxPTR			"lx"		/* uintptr_t */
+#define	PRIxPTR			"x"		/* uintptr_t */
 
 #define	PRIX8			"X"		/* uint8_t */
 #define	PRIX16			"X"		/* uint16_t */
@@ -147,7 +147,7 @@
 #define	PRIXFAST64		"llX"		/* uint_fast64_t */
 
 #define	PRIXMAX			"jX"		/* uintmax_t */
-#define	PRIXPTR			"lX"		/* uintptr_t */
+#define	PRIXPTR			"X"		/* uintptr_t */
 
 /* fscanf macros for signed integers */
 #define	SCNd8			"hhd"		/* int8_t */
@@ -166,7 +166,7 @@
 #define	SCNdFAST64		"lld"		/* int_fast64_t */
 
 #define	SCNdMAX			"jd"		/* intmax_t */
-#define	SCNdPTR			"ld"		/* intptr_t */
+#define	SCNdPTR			"d"		/* intptr_t */
 
 #define	SCNi8			"hhi"		/* int8_t */
 #define	SCNi16			"hi"		/* int16_t */
@@ -184,7 +184,7 @@
 #define	SCNiFAST64		"lli"		/* int_fast64_t */
 
 #define	SCNiMAX			"ji"		/* intmax_t */
-#define	SCNiPTR			"li"		/* intptr_t */
+#define	SCNiPTR			"i"		/* intptr_t */
 
 /* fscanf macros for unsigned integers */
 #define	SCNo8			"hho"		/* uint8_t */
@@ -203,7 +203,7 @@
 #define	SCNoFAST64		"llo"		/* uint_fast64_t */
 
 #define	SCNoMAX			"jo"		/* uintmax_t */
-#define	SCNoPTR			"lo"		/* uintptr_t */
+#define	SCNoPTR			"o"		/* uintptr_t */
 
 #define	SCNu8			"hhu"		/* uint8_t */
 #define	SCNu16			"hu"		/* uint16_t */
@@ -221,7 +221,7 @@
 #define	SCNuFAST64		"llu"		/* uint_fast64_t */
 
 #define	SCNuMAX			"ju"		/* uintmax_t */
-#define	SCNuPTR			"lu"		/* uintptr_t */
+#define	SCNuPTR			"u"		/* uintptr_t */
 
 #define	SCNx8			"hhx"		/* uint8_t */
 #define	SCNx16			"hx"		/* uint16_t */
@@ -239,7 +239,7 @@
 #define	SCNxFAST64		"llx"		/* uint_fast64_t */
 
 #define	SCNxMAX			"jx"		/* uintmax_t */
-#define	SCNxPTR			"lx"		/* uintptr_t */
+#define	SCNxPTR			"x"		/* uintptr_t */
 
 #endif /* __cplusplus || __STDC_FORMAT_MACROS */
 
diff --git a/ndk/platforms/android-3/include/stdint.h b/ndk/platforms/android-3/include/stdint.h
index 54ea026..44613d5 100644
--- a/ndk/platforms/android-3/include/stdint.h
+++ b/ndk/platforms/android-3/include/stdint.h
@@ -234,11 +234,7 @@
 
 /* Limits of wchar_t. */
 #ifdef __STDINT_LIMITS
-   /* Also possibly defined in <wchar.h> */
-#  ifndef WCHAR_MIN
-#    define WCHAR_MIN     INT32_MIN
-#    define WCHAR_MAX     INT32_MAX
-#  endif
+#include <sys/_wchar_limits.h>
 #endif
 
 /* Limits of wint_t. */
diff --git a/ndk/platforms/android-3/include/sys/_wchar_limits.h b/ndk/platforms/android-3/include/sys/_wchar_limits.h
new file mode 100644
index 0000000..644792f
--- /dev/null
+++ b/ndk/platforms/android-3/include/sys/_wchar_limits.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#ifndef _SYS__WCHAR_LIMITS_H
+#define _SYS__WCHAR_LIMITS_H
+
+#include <android/api-level.h>
+
+/* WCHAR_MIN / WCHAR_MAX can be defined by <stdint.h> or <wchar.h>.
+ * Due to historical reasons, their definition is a bit complex.
+ *
+ * - In NDK r8e and older, all definitions of WCHAR_MIN and WCHAR_MAX
+ *   where 32-bit signed values (with one exception described below),
+ *   despite the fact that wchar_t is 'unsigned' on ARM.
+ *   See http://b.android.com/57749
+ *
+ *   This is no longer the case, unless you define _WCHAR_IS_ALWAYS_SIGNED
+ *   at compile time to restore the old (broken) behaviour. This doesn't
+ *   affect other CPU ABIs.
+ *
+ * - Before API level 9, on ARM, wchar_t was typedef to 'char' when
+ *   compiling C (not C++). Also, the definitions of WCHAR_MIN and
+ *   WCHAR_MAX differed between <stdint.h> and <wchar.h>:
+ *
+ *     <stdint.h> conditionally defined them to INT32_MIN / INT32_MAX.
+ *     <wchar.h> conditionally defined them to 0 and 255 instead.
+ *
+ *   <stdint.h> would only define WCHAR_MIN and WCHAR_MAX when:
+ *    - Compiling C sources.
+ *    - Compiling C++ sources with __STDC_LIMIT_MACROS being defined.
+ *
+ *   <wchar.h> always ends up including <stdint.h> indirectly. This
+ *   means that:
+ *
+ *     - When compiling C sources, WCHAR_MIN / WCHAR_MAX were always
+ *       defined as INT32_MIN / INT32_MAX.
+ *
+ *     - When compiling C++ sources with __STDC_LIMIT_MACROS defined,
+ *       they were always defined to INT32_MIN / INT32_MAX
+ *
+ *     - When compiling C++ sources without __STDC_LIMIT_MACROS defined,
+ *       they were defined by <wchar.h> as 0 and 255, respectively.
+ *
+ *    Keep in mind that this was ARM-specific, only for API level < 9.
+ *
+ *    If _WCHAR_IS_8BIT is defined, the same broken behaviour will
+ *    be restored. See http://b.android.com/57267
+ */ 
+#if !defined(WCHAR_MIN)
+
+#  if defined(_WCHAR_IS_8BIT) && defined(__arm__) && __ANDROID_API__ < 9
+#    if defined(__cplusplus) && !defined(__STDC_LIMIT_MACROS)
+#      define WCHAR_MIN  0
+#      define WCHAR_MAX  255
+#    else
+#      define WCHAR_MIN   (-2147483647 - 1)
+#      define WCHAR_MAX   (2147483647)
+#    endif
+#  elif defined(_WCHAR_IS_ALWAYS_SIGNED)
+#    define WCHAR_MIN   (-2147483647 - 1)
+#    define WCHAR_MAX   (2147483647)
+#  else
+  /* Otherwise, the value is derived from the toolchain configuration.
+   * to avoid putting explicit CPU checks in this header. */
+#    ifndef __WCHAR_MAX__
+#      error "__WCHAR_MAX__ is not defined. Check your toolchain!"
+#    endif
+  /* Clang does define __WCHAR_MAX__, but not __WCHAR_MIN__ */
+#    ifndef __WCHAR_MIN__
+#      if __WCHAR_MAX__ == 4294967295
+#        define __WCHAR_MIN__  (0U)
+#      elif __WCHAR_MAX__ == 2147483647
+#        define __WCHAR_MIN__  (-2147483647 - 1)
+#      else
+#        error "Invalid __WCHAR_MAX__ value. Check your toolchain!"
+#      endif
+#    endif /* !__WCHAR_MIN__ */
+#    define WCHAR_MIN    __WCHAR_MIN__
+#    define WCHAR_MAX    __WCHAR_MAX__
+#  endif /* !_WCHAR_IS_ALWAYS_SIGNED */
+
+#endif /* !WCHAR_MIN */
+
+#endif  /* _SYS__WCHAR_LIMITS_H */
diff --git a/ndk/platforms/android-3/include/sys/cdefs.h b/ndk/platforms/android-3/include/sys/cdefs.h
index 27c575c..88ce720 100644
--- a/ndk/platforms/android-3/include/sys/cdefs.h
+++ b/ndk/platforms/android-3/include/sys/cdefs.h
@@ -37,11 +37,36 @@
 #ifndef	_SYS_CDEFS_H_
 #define	_SYS_CDEFS_H_
 
-
-/* our implementation of wchar_t is only 8-bit - die die non-portable code */
+/* In previous NDK releases, wchar_t was defined as 'unsigned char'
+ * when targetting API level < 9 (i.e. Froyo or older).
+ *
+ * This is no longer the case, but you can define _WCHAR_IS_8BIT
+ * at compile time to restore the old behaviour.
+ *
+ * The reason for this redefine is purely historical. Until Android 2.3,
+ * i.e. API level 9, there was absolutely no official support for wchar_t
+ * in the C library, but compiling GCC and the GNU libstdc++ required a
+ * working <wchar.h>.
+ *
+ * To allow this while keeping the C library small, wchar_t was redefined
+ * explicitely as an 8-bit unsigned integer (which is perfectly allowed
+ * by the standard) and a very small set of wcs-xxx functions provided
+ * as wrappers around the corresponding str-xxx ones.
+ *
+ * Starting with API level 9, wchar_t is properly defined as a 32-bit
+ * type (as mandated by the compiler itself), and the lines below
+ * were removed (see $NDK/platforms/android-9/include/sys/cdefs.h).
+ *
+ * Note that this only affects C source compilation. For C++, wchar_t
+ * is a compiler keyboard that cannot be redefined and is always 32-bit.
+ *
+ * On the other hand, _WCHAR_IS_8BIT also affects the definition of
+ * WCHAR_MIN, WCHAR_MAX and WEOF (see <wchar.h> comments).
+ */
+#ifdef _WCHAR_IS_8BIT
 #undef  __WCHAR_TYPE__
 #define __WCHAR_TYPE__  unsigned char
-
+#endif
 
 /*
  * Macro to test if we're using a GNU C compiler of a specific vintage
diff --git a/ndk/platforms/android-3/include/wchar.h b/ndk/platforms/android-3/include/wchar.h
index 9a6ce1d..575da4d 100644
--- a/ndk/platforms/android-3/include/wchar.h
+++ b/ndk/platforms/android-3/include/wchar.h
@@ -40,6 +40,7 @@
 #include <malloc.h>
 
 #include <stddef.h>
+#include <sys/_wchar_limits.h>
 
 /* IMPORTANT: Any code that relies on wide character support is essentially
  *            non-portable and/or broken. the only reason this header exist
@@ -70,9 +71,15 @@
     WC_TYPE_MAX
 } wctype_t;
 
-#define  WCHAR_MAX   255
-#define  WCHAR_MIN   0
+/* WEOF used to be defined as simply -1, which is
+ * invalid (the standard mandates that the expression must have wint_t
+ * type). Revert to the old broken behaviour is _WCHAR_IS_8BIT is defined.
+ * See http://b.android.com/57267 */
+#ifdef _WCHAR_IS_8BIT
 #define  WEOF        (-1)
+#else
+#define  WEOF        ((wint_t)-1)
+#endif
 
 extern wint_t            btowc(int);
 extern int               fwprintf(FILE *, const wchar_t *, ...);
diff --git a/ndk/platforms/android-8/include/wchar.h b/ndk/platforms/android-8/include/wchar.h
index b9c7b0b..453b6d5 100644
--- a/ndk/platforms/android-8/include/wchar.h
+++ b/ndk/platforms/android-8/include/wchar.h
@@ -40,6 +40,7 @@
 #include <malloc.h>
 
 #include <stddef.h>
+#include <sys/_wchar_limits.h>
 
 /* IMPORTANT: Any code that relies on wide character support is essentially
  *            non-portable and/or broken. the only reason this header exist
@@ -70,9 +71,20 @@
     WC_TYPE_MAX
 } wctype_t;
 
-#define  WCHAR_MAX   255
-#define  WCHAR_MIN   0
+/* WEOF used to be defined as simply -1, which is
+ * invalid (the standard mandates that the expression must have wint_t
+ * type). Revert to the old broken behaviour is _WCHAR_IS_8BIT is defined.
+ * See http://b.android.com/57267 */
+#ifdef _WCHAR_IS_8BIT
 #define  WEOF        (-1)
+#else
+#define  WEOF        ((wint_t)-1)
+#endif
+#ifdef _WCHAR_IS_8BIT
+#define  WEOF        (-1)
+#else
+#define  WEOF        ((wint_t)-1)
+#endif
 
 extern wint_t            btowc(int);
 extern int               fwprintf(FILE *, const wchar_t *, ...);
diff --git a/ndk/platforms/android-9/arch-x86/lib/libc.a b/ndk/platforms/android-9/arch-x86/lib/libc.a
index 29b1726..788b92e 100644
--- a/ndk/platforms/android-9/arch-x86/lib/libc.a
+++ b/ndk/platforms/android-9/arch-x86/lib/libc.a
Binary files differ
diff --git a/ndk/platforms/android-9/arch-x86/symbols/libc.so.functions.txt b/ndk/platforms/android-9/arch-x86/symbols/libc.so.functions.txt
index 2c7a608..2a77c44 100644
--- a/ndk/platforms/android-9/arch-x86/symbols/libc.so.functions.txt
+++ b/ndk/platforms/android-9/arch-x86/symbols/libc.so.functions.txt
@@ -264,6 +264,7 @@
 clock_gettime
 clock_nanosleep
 clock_settime
+clone
 close
 closedir
 closelog
diff --git a/ndk/platforms/android-9/include/wchar.h b/ndk/platforms/android-9/include/wchar.h
index fea648c..806e3d1 100644
--- a/ndk/platforms/android-9/include/wchar.h
+++ b/ndk/platforms/android-9/include/wchar.h
@@ -41,13 +41,7 @@
 #include <malloc.h>
 
 #include <stddef.h>
-
-/* IMPORTANT: Any code that relies on wide character support is essentially
- *            non-portable and/or broken. the only reason this header exist
- *            is because I'm really a nice guy. However, I'm not nice enough
- *            to provide you with a real implementation. instead wchar_t == char
- *            and all wc functions are stubs to their "normal" equivalent...
- */
+#include <sys/_wchar_limits.h>
 
 __BEGIN_DECLS
 
@@ -71,8 +65,6 @@
     WC_TYPE_MAX
 } wctype_t;
 
-#define  WCHAR_MAX   INT_MAX
-#define  WCHAR_MIN   INT_MIN
 #define  WEOF        ((wint_t)(-1))
 
 extern wint_t            btowc(int);
diff --git a/ndk/sources/android/libportable/arch-mips/pthread.c b/ndk/sources/android/libportable/arch-mips/pthread.c
index 41d9478..5b75623 100644
--- a/ndk/sources/android/libportable/arch-mips/pthread.c
+++ b/ndk/sources/android/libportable/arch-mips/pthread.c
@@ -288,13 +288,14 @@
 int WRAP(pthread_sigmask)(int portable_how, const sigset_portable_t *portable_sigset,
                              sigset_portable_t *portable_oldset)
 {
+    extern int REAL(pthread_sigmask)(int how, const sigset_t *set, sigset_t *oset);
     int portable_ret, ret;
 
     ALOGV(" ");
     ALOGV("%s(portable_how:%d portable_sigset:%p, portable_oldset:%p)", __func__,
               portable_how,   portable_sigset,    portable_oldset);
 
-    ret = do_sigmask(portable_how, portable_sigset, portable_oldset, pthread_sigmask, NULL);
+    ret = do_sigmask(portable_how, portable_sigset, portable_oldset, REAL(pthread_sigmask), NULL);
 
     portable_ret = errno_ntop(ret);
 
diff --git a/ndk/sources/android/libportable/arch-mips/signal.c b/ndk/sources/android/libportable/arch-mips/signal.c
index c1befd6..a06eff7 100644
--- a/ndk/sources/android/libportable/arch-mips/signal.c
+++ b/ndk/sources/android/libportable/arch-mips/signal.c
@@ -745,6 +745,7 @@
  */
 sighandler_portable_t WRAP(signal)(int portable_signum, sighandler_portable_t handler)
 {
+    extern __sighandler_t REAL(bsd_signal)(int, __sighandler_t);
     sighandler_portable_t rv;
 
     ALOGV(" ");
@@ -752,7 +753,7 @@
               portable_signum,    handler);
 
     /* bsd does a SA_RESTART */
-    rv = do_signal_portable(portable_signum, handler, bsd_signal);
+    rv = do_signal_portable(portable_signum, handler, REAL(bsd_signal));
 
     ALOGV("%s: return(ret:%p); }", __func__, rv);
     return rv;
@@ -761,6 +762,7 @@
 
 sighandler_portable_t WRAP(sysv_signal)(int portable_signum, sighandler_portable_t handler)
 {
+    extern __sighandler_t REAL(sysv_signal)(int, __sighandler_t);
     sighandler_portable_t rv;
 
     ALOGV(" ");
@@ -768,7 +770,7 @@
               portable_signum,    handler);
 
     /* sysv does a SA_RESETHAND */
-    rv = do_signal_portable(portable_signum, handler, sysv_signal);
+    rv = do_signal_portable(portable_signum, handler, REAL(sysv_signal));
 
     ALOGV("%s: return(ret:%p); }", __func__, rv);
     return rv;
@@ -785,6 +787,7 @@
 
 sighandler_portable_t WRAP(bsd_signal)(int portable_signum, sighandler_portable_t handler)
 {
+    extern __sighandler_t REAL(bsd_signal)(int, __sighandler_t);
     sighandler_portable_t rv;
 
     ALOGV(" ");
@@ -792,7 +795,7 @@
               portable_signum,    handler);
 
     /* bsd does a SA_RESTART */
-    rv = do_signal_portable(portable_signum, handler, bsd_signal);
+    rv = do_signal_portable(portable_signum, handler, REAL(bsd_signal));
 
     ALOGV("%s: return(ret:%p); }", __func__, rv);
     return rv;
diff --git a/ndk/tools/headers-diff-bionic-vs-ndk.py b/ndk/tools/headers-diff-bionic-vs-ndk.py
new file mode 100755
index 0000000..1f8a9e3
--- /dev/null
+++ b/ndk/tools/headers-diff-bionic-vs-ndk.py
@@ -0,0 +1,248 @@
+#!/usr/bin/python
+#
+# This tool is used to compare headers between Bionic and NDK
+# script should be in development/ndk/tools for correct roots autodetection
+#
+
+import sys, os, os.path
+import subprocess
+import argparse, textwrap
+
+class FileCollector:
+    """Collect headers from Bionic and sysroot
+
+    sysincludes data format:
+    sysincludes                     -- dict with arch as key
+    sysincludes[arch]               -- dict with includes root as key
+    sysincludes[arch][root]         -- dict with header name as key
+    sysincludes[arch][root][header] -- list [last_platform, ..., first_platform]
+    """
+
+    def __init__(self, platforms_root, archs):
+        """Init platform roots and structures before collecting"""
+        self.platforms = []
+        self.archs = archs
+        self.sysincludes = {}
+        for arch in self.archs:
+            self.sysincludes[arch] = {}
+
+        ## scaning available platforms ##
+        for dirname in os.listdir(platforms_root):
+            path = os.path.join(platforms_root, dirname)
+            if os.path.isdir(path) and ('android' in dirname):
+                self.platforms.append(dirname)
+        try:
+            self.platforms.sort(key = lambda s: int(s.split('-')[1]))
+            self.root = platforms_root
+        except Exception:
+            print 'Wrong platforms list \n{0}'.format(str(self.platforms))
+
+    def scan_dir(self, root):
+        """Non-recursive file scan in directory"""
+        files = []
+        for filename in os.listdir(root):
+            if os.path.isfile(os.path.join(root, filename)):
+                files.append(filename)
+        return files
+
+    def scan_includes(self, root):
+        """Recursive includes scan in given root"""
+        includes = []
+        includes_root = os.path.join(root, 'include')
+        if not os.path.isdir(includes_root):
+            return includes
+
+        ## recursive scanning ##
+        includes.append(('', self.scan_dir(includes_root)))
+        for dirname, dirnames, filenames in os.walk(includes_root):
+            for subdirname in dirnames:
+                path = os.path.join(dirname, subdirname)
+                relpath = os.path.relpath(path, includes_root)
+                includes.append((relpath, self.scan_dir(path)))
+
+        return includes
+
+    def scan_archs_includes(self, root):
+        """Scan includes for all defined archs in given root"""
+        includes = {}
+        includes['common'] = self.scan_includes(root)
+
+        for arch in [a for a in self.archs if a != 'common']:
+            arch_root = os.path.join(root, arch)
+            includes[arch] = self.scan_includes(arch_root)
+
+        return includes
+
+    def scan_platform_includes(self, platform):
+        """Scan all platform includes of one layer"""
+        platform_root = os.path.join(self.root, platform)
+        return self.scan_archs_includes(platform_root)
+
+    def scan_bionic_includes(self, bionic_root):
+        """Scan Bionic's libc includes"""
+        self.bionic_root = bionic_root
+        self.bionic_includes = self.scan_archs_includes(bionic_root)
+
+    def append_sysincludes(self, arch, root, headers, platform):
+        """Merge new platform includes layer with current sysincludes"""
+        if not (root in self.sysincludes[arch]):
+            self.sysincludes[arch][root] = {}
+
+        for include in headers:
+            if include in self.sysincludes[arch][root]:
+                last_platform = self.sysincludes[arch][root][include][0]
+                if platform != last_platform:
+                    self.sysincludes[arch][root][include].insert(0, platform)
+            else:
+                self.sysincludes[arch][root][include] = [platform]
+
+    def update_to_platform(self, platform):
+        """Update sysincludes state by applying new platform layer"""
+        new_includes = self.scan_platform_includes(platform)
+        for arch in self.archs:
+            for pack in new_includes[arch]:
+                self.append_sysincludes(arch, pack[0], pack[1], platform)
+
+    def scan_sysincludes(self, target_platform):
+        """Fully automated sysincludes collector upto specified platform"""
+        version = int(target_platform.split('-')[1])
+        layers = filter(lambda s: int(s.split('-')[1]) <= version, self.platforms)
+        for platform in layers:
+            self.update_to_platform(platform)
+
+
+class BionicSysincludes:
+    def set_roots(self):
+        """Automated roots initialization (AOSP oriented)"""
+        script_root = os.path.dirname(os.path.realpath(__file__))
+        self.aosp_root      = os.path.normpath(os.path.join(script_root, '../../..'))
+        self.platforms_root = os.path.join(self.aosp_root, 'development/ndk/platforms')
+        self.bionic_root    = os.path.join(self.aosp_root, 'bionic/libc')
+
+    def scan_includes(self):
+        """Scan all required includes"""
+        self.collector = FileCollector(self.platforms_root, self.archs)
+        ## detecting latest platform ##
+        self.platforms = self.collector.platforms
+        latest_platform = self.platforms[-1:][0]
+        ## scanning both includes repositories ##
+        self.collector.scan_sysincludes(latest_platform)
+        self.collector.scan_bionic_includes(self.bionic_root)
+        ## scan results ##
+        self.sysincludes     = self.collector.sysincludes
+        self.bionic_includes = self.collector.bionic_includes
+
+    def git_diff(self, file_origin, file_probe):
+        """Difference routine based on git diff"""
+        try:
+            subprocess.check_output(['git', 'diff', '--no-index', file_origin, file_probe])
+        except subprocess.CalledProcessError as error:
+            return error.output
+        return None
+
+    def match_with_bionic_includes(self):
+        """Compare headers between Bionic and sysroot"""
+        self.diffs = {}
+        ## for every arch ##
+        for arch in self.archs:
+            arch_root = (lambda s: s if s != 'common' else '')(arch)
+            ## for every includes directory ##
+            for pack in self.bionic_includes[arch]:
+                root = pack[0]
+                path_bionic = os.path.join(self.bionic_root, arch_root, 'include', root)
+                ## for every header that both in Bionic and sysroot ##
+                for include in pack[1]:
+                    if include in self.sysincludes[arch][root]:
+                        ## completing paths ##
+                        platform = self.sysincludes[arch][root][include][0]
+                        file_origin = os.path.join(path_bionic, include)
+                        file_probe  = os.path.join(self.platforms_root, platform, arch_root, 'include', root, include)
+                        ## comparison by git diff ##
+                        output = self.git_diff(file_origin, file_probe)
+                        if output is not None:
+                            if arch not in self.diffs:
+                                self.diffs[arch] = {}
+                            if root not in self.diffs[arch]:
+                                self.diffs[arch][root] = {}
+                            ## storing git diff ##
+                            self.diffs[arch][root][include] = output
+
+    def print_history(self, arch, root, header):
+        """Print human-readable list header updates across platforms"""
+        history = self.sysincludes[arch][root][header]
+        for platform in self.platforms:
+            entry = (lambda s: s.split('-')[1] if s in history else '-')(platform)
+            print '{0:3}'.format(entry),
+        print ''
+
+    def show_and_store_results(self):
+        """Print summary list of headers and write diff-report to file"""
+        try:
+            diff_fd = open(self.diff_file, 'w')
+            for arch in self.archs:
+                if arch not in self.diffs:
+                    continue
+                print '{0}/'.format(arch)
+                roots = self.diffs[arch].keys()
+                roots.sort()
+                for root in roots:
+                    print '    {0}/'.format((lambda s: s if s != '' else '../include')(root))
+                    includes = self.diffs[arch][root].keys()
+                    includes.sort()
+                    for include in includes:
+                        print '        {0:32}'.format(include),
+                        self.print_history(arch, root, include)
+                        diff = self.diffs[arch][root][include]
+                        diff_fd.write(diff)
+                        diff_fd.write('\n\n')
+                    print ''
+                print ''
+
+        finally:
+            diff_fd.close()
+
+    def main(self):
+        self.set_roots()
+        self.scan_includes()
+        self.match_with_bionic_includes()
+        self.show_and_store_results()
+
+if __name__ == '__main__':
+    ## configuring command line parser ##
+    parser = argparse.ArgumentParser(formatter_class = argparse.RawTextHelpFormatter,
+                                     description = 'Headers comparison tool between bionic and NDK platforms')
+    parser.epilog = textwrap.dedent('''
+    output format:
+    {architecture}/
+        {directory}/
+            {header name}.h  {platforms history}
+
+    platforms history format:
+        number X means header has been changed in android-X
+        `-\' means it is the same
+
+    diff-report format:
+        git diff output for all headers
+        use --diff option to specify filename
+    ''')
+
+    parser.add_argument('--archs', metavar = 'A', nargs = '+',
+                        default = ['common', 'arm', 'x86', 'mips'],
+                        help = 'list of architectures\n(default: common arm x86 mips)')
+    parser.add_argument('--diff', metavar = 'FILE', nargs = 1,
+                        default = ['headers-diff-bionic-vs-ndk.diff'],
+                        help = 'diff-report filename\n(default: `bionic-vs-sysincludes_report.diff\')')
+
+    ## parsing arguments ##
+    args = parser.parse_args()
+
+    ## doing work ##
+    app = BionicSysincludes()
+    app.archs = map((lambda s: 'arch-{0}'.format(s) if s != 'common' else s), args.archs)
+    app.diff_file = args.diff[0]
+    app.main()
+
+    print 'Headers listed above are DIFFERENT in Bionic and NDK platforms'
+    print 'See `{0}\' for details'.format(app.diff_file)
+    print 'See --help for format description.'
+    print ''