Merge "Add support for disabling the greylist." into oc-dev
am: f971076ac9
Change-Id: Ibb341dc707295b9df812a81d76f47c83da869f59
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 125b469..7b533a4 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -1,3 +1,2 @@
[Hook Scripts]
-versioner = tools/versioner/preupload.sh
notice = tools/update_notice.sh
diff --git a/libc/Android.bp b/libc/Android.bp
index 8154470..8c6f596 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -622,6 +622,13 @@
"upstream-openbsd/lib/libc/string/strcat.c",
],
},
+ kryo: {
+ exclude_srcs: [
+ "upstream-openbsd/lib/libc/string/memmove.c",
+ "upstream-openbsd/lib/libc/string/stpcpy.c",
+ "upstream-openbsd/lib/libc/string/strcat.c",
+ ],
+ },
},
arm64: {
exclude_srcs: [
@@ -1008,7 +1015,32 @@
"bionic/__strcpy_chk.cpp",
],
},
+ kryo: {
+ srcs: [
+ "arch-arm/krait/bionic/memcpy.S",
+ "arch-arm/krait/bionic/memset.S",
+ "arch-arm/krait/bionic/strcmp.S",
+ "arch-arm/krait/bionic/__strcat_chk.S",
+ "arch-arm/krait/bionic/__strcpy_chk.S",
+ // Use cortex-a15 versions of strcat/strcpy/strlen.
+ "arch-arm/cortex-a15/bionic/stpcpy.S",
+ "arch-arm/cortex-a15/bionic/strcat.S",
+ "arch-arm/cortex-a15/bionic/strcpy.S",
+ "arch-arm/cortex-a15/bionic/strlen.S",
+
+ "arch-arm/denver/bionic/memmove.S",
+ ],
+ exclude_srcs: [
+ "arch-arm/generic/bionic/memcpy.S",
+ "arch-arm/generic/bionic/memset.S",
+ "arch-arm/generic/bionic/strcmp.S",
+ "arch-arm/generic/bionic/strcpy.S",
+ "arch-arm/generic/bionic/strlen.c",
+ "bionic/__strcat_chk.cpp",
+ "bionic/__strcpy_chk.cpp",
+ ],
+ },
},
arm64: {
srcs: [
@@ -1862,28 +1894,10 @@
},
}
-// Android.mk:start
-// # crt obj files
-// # ========================================================
-// # crtbrand.c needs <stdint.h> and a #define for the platform SDK version.
-// libc_crt_target_cflags := \
-// -I$(LOCAL_PATH)/include \
-// -DPLATFORM_SDK_VERSION=$(PLATFORM_SDK_VERSION) \
-//
-// my_2nd_arch_prefix :=
-// include $(LOCAL_PATH)/arch-$(TARGET_ARCH)/$(TARGET_ARCH).mk
-// include $(LOCAL_PATH)/crt.mk
-// ifdef TARGET_2ND_ARCH
-// my_2nd_arch_prefix := $(TARGET_2ND_ARCH_VAR_PREFIX)
-// include $(LOCAL_PATH)/arch-$(TARGET_2ND_ARCH)/$(TARGET_2ND_ARCH).mk
-// include $(LOCAL_PATH)/crt.mk
-// my_2nd_arch_prefix :=
-// endif
-//
-// include $(call all-makefiles-under,$(LOCAL_PATH))
-// Android.mk:end
+// crt obj files
cc_object {
name: "crtbrand",
+ // crtbrand.c needs <stdint.h> and a #define for the platform SDK version.
local_include_dirs: ["include"],
product_variables: {
platform_sdk_version: {
@@ -1898,7 +1912,6 @@
],
}
-// Android.mk:ignore
cc_object {
name: "crtbegin_so1",
local_include_dirs: ["include"],
@@ -1910,7 +1923,6 @@
],
}
-// Android.mk:ignore
cc_object {
name: "crtbegin_so",
@@ -1924,7 +1936,6 @@
],
}
-// Android.mk:ignore
cc_object {
name: "crtend_so",
local_include_dirs: ["include"],
@@ -1936,7 +1947,6 @@
],
}
-// Android.mk:ignore
cc_object {
name: "crtbegin_static1",
local_include_dirs: ["include"],
@@ -1972,7 +1982,6 @@
defaults: ["crt_defaults"],
}
-// Android.mk:ignore
cc_object {
name: "crtbegin_static",
@@ -1983,7 +1992,6 @@
defaults: ["crt_defaults"],
}
-// Android.mk:ignore
cc_object {
name: "crtbegin_dynamic1",
local_include_dirs: ["include"],
@@ -2018,7 +2026,6 @@
defaults: ["crt_defaults"],
}
-// Android.mk:ignore
cc_object {
name: "crtbegin_dynamic",
@@ -2029,7 +2036,6 @@
defaults: ["crt_defaults"],
}
-// Android.mk:ignore
cc_object {
// We rename crtend.o to crtend_android.o to avoid a
// name clash between gcc and bionic.
@@ -2040,15 +2046,12 @@
defaults: ["crt_defaults"],
}
-// The following module lives in prebuilts/ndk because we need to preprocess the
-// headers to include ifdef guards for __ANDROID_API__. Update with
-// bionic/tools/update_headers.sh.
-// ndk_headers {
-// name: "common_libc",
-// from: "include",
-// to: "",
-// srcs: ["include/**/*.h"],
-// }
+preprocessed_ndk_headers {
+ name: "common_libc",
+ from: "include",
+ to: "",
+ license: "NOTICE",
+}
ndk_headers {
name: "libc_uapi",
diff --git a/libc/bionic/fortify.cpp b/libc/bionic/fortify.cpp
index cf2d1c2..cfbfbc5 100644
--- a/libc/bionic/fortify.cpp
+++ b/libc/bionic/fortify.cpp
@@ -133,7 +133,7 @@
void* __memchr_chk(const void* s, int c, size_t n, size_t actual_size) {
__check_buffer_access("memchr", "read from", n, actual_size);
- return memchr(s, c, n);
+ return const_cast<void*>(memchr(s, c, n));
}
// Runtime implementation of __builtin____memmove_chk (used directly by compiler, not in headers).
diff --git a/libc/bionic/libc_init_common.cpp b/libc/bionic/libc_init_common.cpp
index 9094fc5..970a49c 100644
--- a/libc/bionic/libc_init_common.cpp
+++ b/libc/bionic/libc_init_common.cpp
@@ -244,6 +244,7 @@
// of executing a setuid program or the result of an SELinux
// security transition.
static constexpr const char* UNSAFE_VARIABLE_NAMES[] = {
+ "ANDROID_DNS_MODE",
"GCONV_PATH",
"GETCONF_DIR",
"HOSTALIASES",
diff --git a/libc/bionic/memmem.cpp b/libc/bionic/memmem.cpp
index 61d681f..019e772 100644
--- a/libc/bionic/memmem.cpp
+++ b/libc/bionic/memmem.cpp
@@ -35,7 +35,7 @@
if (n < m) return nullptr;
if (m == 0) return const_cast<void*>(void_haystack);
- if (m == 1) return memchr(haystack, needle[0], n);
+ if (m == 1) return const_cast<void*>(memchr(haystack, needle[0], n));
// This uses the "Not So Naive" algorithm, a very simple but usually effective algorithm.
// http://www-igm.univ-mlv.fr/~lecroq/string/
diff --git a/libc/bionic/ndk_cruft.cpp b/libc/bionic/ndk_cruft.cpp
index c042f9f..29565a2 100644
--- a/libc/bionic/ndk_cruft.cpp
+++ b/libc/bionic/ndk_cruft.cpp
@@ -322,7 +322,7 @@
// This was removed from POSIX 2008.
char* index(const char* str, int ch) {
- return strchr(str, ch);
+ return const_cast<char*>(strchr(str, ch));
}
// This was removed from BSD.
diff --git a/libc/dns/resolv/res_cache.c b/libc/dns/resolv/res_cache.c
index 8b3c76b..82e0ddf 100644
--- a/libc/dns/resolv/res_cache.c
+++ b/libc/dns/resolv/res_cache.c
@@ -98,12 +98,6 @@
* is too short to accomodate the cached result.
*/
-/* the name of an environment variable that will be checked the first time
- * this code is called if its value is "0", then the resolver cache is
- * disabled.
- */
-#define CONFIG_ENV "BIONIC_DNSCACHE"
-
/* default number of entries kept in the cache. This value has been
* determined by browsing through various sites and counting the number
* of corresponding requests. Keep in mind that our framework is currently
@@ -1812,13 +1806,6 @@
static void
_res_cache_init(void)
{
- const char* env = getenv(CONFIG_ENV);
-
- if (env && atoi(env) == 0) {
- /* the cache is disabled */
- return;
- }
-
memset(&_res_cache_list, 0, sizeof(_res_cache_list));
pthread_mutex_init(&_res_cache_list_lock, NULL);
}
diff --git a/libc/include/math.h b/libc/include/math.h
index 8bf6fb5..7dd1539 100644
--- a/libc/include/math.h
+++ b/libc/include/math.h
@@ -153,6 +153,20 @@
long lrint(double);
long lround(double);
+/*
+ * https://code.google.com/p/android/issues/detail?id=271629
+ * To be fully compliant with C++, we need to not define these (C doesn't
+ * specify them either). Exposing these means that isinf and isnan will have a
+ * return type of int in C++ rather than bool like they're supposed to be.
+ *
+ * GNU libstdc++ 4.9 isn't able to handle a standard compliant C library. Its
+ * <cmath> will `#undef isnan` from math.h and only adds the function overloads
+ * to the std namespace, making it impossible to use both <cmath> (which gets
+ * included by a lot of other standard headers) and ::isnan.
+ */
+int(isinf)(double) __attribute_const__ __INTRODUCED_IN(21);
+int (isnan)(double) __attribute_const__;
+
double nan(const char*) __attribute_const__ __INTRODUCED_IN_ARM(13) __INTRODUCED_IN_MIPS(13)
__INTRODUCED_IN_X86(9);
diff --git a/libc/include/string.h b/libc/include/string.h
index 26bd93f..6520996 100644
--- a/libc/include/string.h
+++ b/libc/include/string.h
@@ -168,48 +168,47 @@
// trickery...
#if __ANDROID_API__ >= __ANDROID_API_J_MR1__
__BIONIC_FORTIFY_INLINE
-void* memcpy(void* _Nonnull __restrict const dst __pass_object_size0,
- const void* _Nonnull __restrict src, size_t copy_amount) __overloadable {
+void* memcpy(void* _Nonnull __restrict const dst __pass_object_size0, const void* _Nonnull __restrict src, size_t copy_amount)
+ __overloadable {
return __builtin___memcpy_chk(dst, src, copy_amount, __bos0(dst));
}
__BIONIC_FORTIFY_INLINE
-void* memmove(void* const _Nonnull dst __pass_object_size0,
- const void* _Nonnull src, size_t len) __overloadable {
+void* memmove(void* const _Nonnull dst __pass_object_size0, const void* _Nonnull src, size_t len)
+ __overloadable {
return __builtin___memmove_chk(dst, src, len, __bos0(dst));
}
#endif /* __ANDROID_API__ >= __ANDROID_API_J_MR1__ */
#if __ANDROID_API__ >= __ANDROID_API_L__
__BIONIC_FORTIFY_INLINE
-char* stpcpy(char* _Nonnull __restrict const dst __pass_object_size,
- const char* _Nonnull __restrict src) __overloadable {
+char* stpcpy(char* _Nonnull __restrict const dst __pass_object_size, const char* _Nonnull __restrict src)
+ __overloadable {
return __builtin___stpcpy_chk(dst, src, __bos(dst));
}
#endif /* __ANDROID_API__ >= __ANDROID_API_L__ */
#if __ANDROID_API__ >= __ANDROID_API_J_MR1__
__BIONIC_FORTIFY_INLINE
-char* strcpy(char* _Nonnull __restrict const dst __pass_object_size,
- const char* _Nonnull __restrict src) __overloadable {
+char* strcpy(char* _Nonnull __restrict const dst __pass_object_size, const char* _Nonnull __restrict src)
+ __overloadable {
return __builtin___strcpy_chk(dst, src, __bos(dst));
}
__BIONIC_FORTIFY_INLINE
-char* strcat(char* _Nonnull __restrict const dst __pass_object_size,
- const char* _Nonnull __restrict src) __overloadable {
+char* strcat(char* _Nonnull __restrict const dst __pass_object_size, const char* _Nonnull __restrict src)
+ __overloadable {
return __builtin___strcat_chk(dst, src, __bos(dst));
}
__BIONIC_FORTIFY_INLINE
-char* strncat(char* const _Nonnull __restrict dst __pass_object_size,
- const char* _Nonnull __restrict src, size_t n) __overloadable {
+char* strncat(char* const _Nonnull __restrict dst __pass_object_size, const char* _Nonnull __restrict src, size_t n)
+ __overloadable {
return __builtin___strncat_chk(dst, src, n, __bos(dst));
}
__BIONIC_FORTIFY_INLINE
-void* memset(void* const _Nonnull s __pass_object_size0, int c, size_t n)
- __overloadable {
+void* memset(void* const _Nonnull s __pass_object_size0, int c, size_t n) __overloadable {
return __builtin___memset_chk(s, c, n, __bos0(s));
}
#endif /* __ANDROID_API__ >= __ANDROID_API_J_MR1__ */
@@ -274,9 +273,8 @@
#if __ANDROID_API__ >= __ANDROID_API_L__
__BIONIC_FORTIFY_INLINE
-char* stpncpy(char* __restrict const _Nonnull dst __pass_object_size,
- const char* __restrict const _Nonnull src __pass_object_size,
- size_t n) __overloadable {
+char* stpncpy(char* __restrict const _Nonnull dst __pass_object_size, const char* __restrict const _Nonnull src __pass_object_size, size_t n)
+ __overloadable {
size_t bos_dst = __bos(dst);
size_t bos_src = __bos(src);
@@ -289,9 +287,8 @@
}
__BIONIC_FORTIFY_INLINE
-char* strncpy(char* __restrict const _Nonnull dst __pass_object_size,
- const char* __restrict const _Nonnull src __pass_object_size,
- size_t n) __overloadable {
+char* strncpy(char* __restrict const _Nonnull dst __pass_object_size, const char* __restrict const _Nonnull src __pass_object_size, size_t n)
+ __overloadable {
size_t bos_dst = __bos(dst);
size_t bos_src = __bos(src);
@@ -306,8 +303,8 @@
#if __ANDROID_API__ >= __ANDROID_API_J_MR1__
__BIONIC_FORTIFY_INLINE
-size_t strlcpy(char* const _Nonnull __restrict dst __pass_object_size,
- const char *_Nonnull __restrict src, size_t size) __overloadable {
+size_t strlcpy(char* const _Nonnull __restrict dst __pass_object_size, const char *_Nonnull __restrict src, size_t size)
+ __overloadable {
size_t bos = __bos(dst);
if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
@@ -318,8 +315,8 @@
}
__BIONIC_FORTIFY_INLINE
-size_t strlcat(char* const _Nonnull __restrict dst __pass_object_size,
- const char* _Nonnull __restrict src, size_t size) __overloadable {
+size_t strlcat(char* const _Nonnull __restrict dst __pass_object_size, const char* _Nonnull __restrict src, size_t size)
+ __overloadable {
size_t bos = __bos(dst);
if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
@@ -358,15 +355,14 @@
#if __ANDROID_API__ >= __ANDROID_API_J_MR2__
__BIONIC_FORTIFY_INLINE
-char* strchr(const char* const _Nonnull s __pass_object_size0, int c)
+char* strchr(const char* const _Nonnull s __pass_object_size, int c)
__overloadable {
- size_t bos = __bos0(s);
+ size_t bos = __bos(s);
if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
return __builtin_strchr(s, c);
}
- // return __builtin_strchr(s, c);
return __strchr_chk(s, c, bos);
}
@@ -390,14 +386,12 @@
* but we should also provide a FORTIFY'ed escape hatch.
*/
__BIONIC_ERROR_FUNCTION_VISIBILITY
-void* memset(void* _Nonnull s, int c, size_t n,
- struct __bionic_zero_size_is_okay_t ok)
+void* memset(void* _Nonnull s, int c, size_t n, struct __bionic_zero_size_is_okay_t ok)
__overloadable
__error_if_overflows_dst(memset, s, n, "size");
__BIONIC_FORTIFY_INLINE
-void* memset(void* const _Nonnull s __pass_object_size0, int c, size_t n,
- struct __bionic_zero_size_is_okay_t ok __attribute__((unused)))
+void* memset(void* const _Nonnull s __pass_object_size0, int c, size_t n, struct __bionic_zero_size_is_okay_t ok __attribute__((unused)))
__overloadable {
return __builtin___memset_chk(s, c, n, __bos0(s));
}
@@ -514,8 +508,7 @@
#if __ANDROID_API__ >= __ANDROID_API_J_MR1__
__BIONIC_FORTIFY_INLINE
-size_t strlcpy(char* _Nonnull __restrict dst __pass_object_size,
- const char* _Nonnull __restrict src, size_t size) {
+size_t strlcpy(char* _Nonnull __restrict dst __pass_object_size, const char* _Nonnull __restrict src, size_t size) {
size_t bos = __bos(dst);
// Compiler doesn't know destination size. Don't call __strlcpy_chk
@@ -606,6 +599,92 @@
#endif /* defined(__clang__) */
#endif /* defined(__BIONIC_FORTIFY) */
+/* Const-correct overloads. Placed after FORTIFY so we call those functions, if possible. */
+#if defined(__cplusplus) && defined(__clang__)
+/*
+ * Use two enable_ifs so these overloads don't conflict with + are preferred over libcxx's. This can
+ * be reduced to 1 after libcxx recognizes that we have const-correct overloads.
+ */
+#define __prefer_this_overload __enable_if(true, "preferred overload") __enable_if(true, "")
+extern "C++" {
+inline __always_inline
+void* __bionic_memchr(const void* const _Nonnull s __pass_object_size, int c, size_t n) {
+ return memchr(s, c, n);
+}
+
+inline __always_inline
+const void* memchr(const void* const _Nonnull s __pass_object_size, int c, size_t n)
+ __prefer_this_overload {
+ return __bionic_memchr(s, c, n);
+}
+
+inline __always_inline
+void* memchr(void* const _Nonnull s __pass_object_size, int c, size_t n) __prefer_this_overload {
+ return __bionic_memchr(s, c, n);
+}
+
+inline __always_inline
+char* __bionic_strchr(const char* const _Nonnull s __pass_object_size, int c) {
+ return strchr(s, c);
+}
+
+inline __always_inline
+const char* strchr(const char* const _Nonnull s __pass_object_size, int c)
+ __prefer_this_overload {
+ return __bionic_strchr(s, c);
+}
+
+inline __always_inline
+char* strchr(char* const _Nonnull s __pass_object_size, int c)
+ __prefer_this_overload {
+ return __bionic_strchr(s, c);
+}
+
+inline __always_inline
+char* __bionic_strrchr(const char* const _Nonnull s __pass_object_size, int c) {
+ return strrchr(s, c);
+}
+
+inline __always_inline
+const char* strrchr(const char* const _Nonnull s __pass_object_size, int c) __prefer_this_overload {
+ return __bionic_strrchr(s, c);
+}
+
+inline __always_inline
+char* strrchr(char* const _Nonnull s __pass_object_size, int c) __prefer_this_overload {
+ return __bionic_strrchr(s, c);
+}
+
+/* Functions with no FORTIFY counterpart. */
+inline __always_inline
+char* __bionic_strstr(const char* _Nonnull h, const char* _Nonnull n) { return strstr(h, n); }
+
+inline __always_inline
+const char* strstr(const char* _Nonnull h, const char* _Nonnull n) __prefer_this_overload {
+ return __bionic_strstr(h, n);
+}
+
+inline __always_inline
+char* strstr(char* _Nonnull h, const char* _Nonnull n) __prefer_this_overload {
+ return __bionic_strstr(h, n);
+}
+
+inline __always_inline
+char* __bionic_strpbrk(const char* _Nonnull h, const char* _Nonnull n) { return strpbrk(h, n); }
+
+inline __always_inline
+char* strpbrk(char* _Nonnull h, const char* _Nonnull n) __prefer_this_overload {
+ return __bionic_strpbrk(h, n);
+}
+
+inline __always_inline
+const char* strpbrk(const char* _Nonnull h, const char* _Nonnull n) __prefer_this_overload {
+ return __bionic_strpbrk(h, n);
+}
+}
+#undef __prefer_this_overload
+#endif
+
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
diff --git a/libc/include/sys/cdefs.h b/libc/include/sys/cdefs.h
index dab252d..aa93c78 100644
--- a/libc/include/sys/cdefs.h
+++ b/libc/include/sys/cdefs.h
@@ -297,9 +297,12 @@
/* __BIONIC_FORTIFY_NONSTATIC_INLINE is pointless in GCC's FORTIFY */
# define __BIONIC_FORTIFY_INLINE extern __inline__ __always_inline __attribute__((gnu_inline)) __attribute__((__artificial__))
# endif
-# define __pass_object_size __pass_object_size_n(__bos_level)
-# define __pass_object_size0 __pass_object_size_n(0)
+#else
+/* Further increase sharing for some inline functions */
+# define __pass_object_size_n(n)
#endif
+#define __pass_object_size __pass_object_size_n(__bos_level)
+#define __pass_object_size0 __pass_object_size_n(0)
/* Used to support clangisms with FORTIFY. This isn't in the FORTIFY section
* because these change how symbols are emitted. The linker must be kept happy.
diff --git a/libc/private/libc_logging.h b/libc/private/libc_logging.h
index 486ace5..73bc9a5 100644
--- a/libc/private/libc_logging.h
+++ b/libc/private/libc_logging.h
@@ -71,6 +71,7 @@
//
// Formatting routines for the C library's internal debugging.
// Unlike the usual alternatives, these don't allocate, and they don't drag in all of stdio.
+// These are async signal safe, so they can be called from signal handlers.
//
int __libc_format_buffer(char* _Nonnull buf, size_t size, const char* _Nonnull fmt, ...) __printflike(3, 4);
diff --git a/libc/versioner-dependencies/arm/arch-arm b/libc/versioner-dependencies/arm/arch-arm
new file mode 120000
index 0000000..cc94225
--- /dev/null
+++ b/libc/versioner-dependencies/arm/arch-arm
@@ -0,0 +1 @@
+../../arch-arm/include/
\ No newline at end of file
diff --git a/libc/versioner-dependencies/arm/kernel_uapi_asm-arm b/libc/versioner-dependencies/arm/kernel_uapi_asm-arm
new file mode 120000
index 0000000..3c7584d
--- /dev/null
+++ b/libc/versioner-dependencies/arm/kernel_uapi_asm-arm
@@ -0,0 +1 @@
+../../kernel/uapi/asm-arm
\ No newline at end of file
diff --git a/libc/versioner-dependencies/arm64/arch-arm64 b/libc/versioner-dependencies/arm64/arch-arm64
new file mode 120000
index 0000000..2d9128a
--- /dev/null
+++ b/libc/versioner-dependencies/arm64/arch-arm64
@@ -0,0 +1 @@
+../../arch-arm64/include/
\ No newline at end of file
diff --git a/libc/versioner-dependencies/arm64/kernel_uapi_asm-arm64 b/libc/versioner-dependencies/arm64/kernel_uapi_asm-arm64
new file mode 120000
index 0000000..7ee6fd2
--- /dev/null
+++ b/libc/versioner-dependencies/arm64/kernel_uapi_asm-arm64
@@ -0,0 +1 @@
+../../kernel/uapi/asm-arm64
\ No newline at end of file
diff --git a/libc/versioner-dependencies/common/clang-builtins b/libc/versioner-dependencies/common/clang-builtins
new file mode 120000
index 0000000..7bd481c
--- /dev/null
+++ b/libc/versioner-dependencies/common/clang-builtins
@@ -0,0 +1 @@
+../../../../external/clang/lib/Headers/
\ No newline at end of file
diff --git a/libc/versioner-dependencies/common/kernel_android_uapi b/libc/versioner-dependencies/common/kernel_android_uapi
new file mode 120000
index 0000000..fd78315
--- /dev/null
+++ b/libc/versioner-dependencies/common/kernel_android_uapi
@@ -0,0 +1 @@
+../../kernel/android/uapi/
\ No newline at end of file
diff --git a/libc/versioner-dependencies/common/kernel_uapi b/libc/versioner-dependencies/common/kernel_uapi
new file mode 120000
index 0000000..d5cb8ee
--- /dev/null
+++ b/libc/versioner-dependencies/common/kernel_uapi
@@ -0,0 +1 @@
+../../kernel/uapi/
\ No newline at end of file
diff --git a/libc/versioner-dependencies/mips/arch-mips b/libc/versioner-dependencies/mips/arch-mips
new file mode 120000
index 0000000..56ed021
--- /dev/null
+++ b/libc/versioner-dependencies/mips/arch-mips
@@ -0,0 +1 @@
+../../arch-mips/include/
\ No newline at end of file
diff --git a/libc/versioner-dependencies/mips/kernel_uapi_asm-mips b/libc/versioner-dependencies/mips/kernel_uapi_asm-mips
new file mode 120000
index 0000000..94bb3db
--- /dev/null
+++ b/libc/versioner-dependencies/mips/kernel_uapi_asm-mips
@@ -0,0 +1 @@
+../../kernel/uapi/asm-mips
\ No newline at end of file
diff --git a/libc/versioner-dependencies/mips64/arch-mips64 b/libc/versioner-dependencies/mips64/arch-mips64
new file mode 120000
index 0000000..4893b57
--- /dev/null
+++ b/libc/versioner-dependencies/mips64/arch-mips64
@@ -0,0 +1 @@
+../../arch-mips64/include/
\ No newline at end of file
diff --git a/libc/versioner-dependencies/mips64/kernel_uapi_asm-mips b/libc/versioner-dependencies/mips64/kernel_uapi_asm-mips
new file mode 120000
index 0000000..94bb3db
--- /dev/null
+++ b/libc/versioner-dependencies/mips64/kernel_uapi_asm-mips
@@ -0,0 +1 @@
+../../kernel/uapi/asm-mips
\ No newline at end of file
diff --git a/libc/versioner-dependencies/x86/arch-x86 b/libc/versioner-dependencies/x86/arch-x86
new file mode 120000
index 0000000..6426384
--- /dev/null
+++ b/libc/versioner-dependencies/x86/arch-x86
@@ -0,0 +1 @@
+../../arch-x86/include/
\ No newline at end of file
diff --git a/libc/versioner-dependencies/x86/kernel_uapi_asm-x86 b/libc/versioner-dependencies/x86/kernel_uapi_asm-x86
new file mode 120000
index 0000000..1b7a73d
--- /dev/null
+++ b/libc/versioner-dependencies/x86/kernel_uapi_asm-x86
@@ -0,0 +1 @@
+../../kernel/uapi/asm-x86/
\ No newline at end of file
diff --git a/libc/versioner-dependencies/x86_64/arch-x86_64 b/libc/versioner-dependencies/x86_64/arch-x86_64
new file mode 120000
index 0000000..684d74e
--- /dev/null
+++ b/libc/versioner-dependencies/x86_64/arch-x86_64
@@ -0,0 +1 @@
+../../arch-x86_64/include/
\ No newline at end of file
diff --git a/libc/versioner-dependencies/x86_64/kernel_uapi_asm-x86 b/libc/versioner-dependencies/x86_64/kernel_uapi_asm-x86
new file mode 120000
index 0000000..1b7a73d
--- /dev/null
+++ b/libc/versioner-dependencies/x86_64/kernel_uapi_asm-x86
@@ -0,0 +1 @@
+../../kernel/uapi/asm-x86/
\ No newline at end of file
diff --git a/linker/Android.bp b/linker/Android.bp
index 23138cf..d617189 100644
--- a/linker/Android.bp
+++ b/linker/Android.bp
@@ -119,13 +119,7 @@
"libbase",
"libz",
- "libdebuggerd_handler_core",
"libdebuggerd_handler_fallback",
- "libdebuggerd",
- "libbacktrace",
- "libunwind",
- "liblzma",
- "libcutils",
"liblog",
"libc++_static",
diff --git a/tests/fortify_test.cpp b/tests/fortify_test.cpp
index 86b282c..c21c9da 100644
--- a/tests/fortify_test.cpp
+++ b/tests/fortify_test.cpp
@@ -231,35 +231,41 @@
}
#endif
-#ifndef __clang__
-// This test is disabled in clang because clang doesn't properly detect
-// this buffer overflow. TODO: Fix clang.
TEST_F(DEATHTEST, strchr_fortified2) {
#if defined(__BIONIC__)
foo myfoo;
memcpy(myfoo.a, "0123456789", sizeof(myfoo.a));
myfoo.b[0] = '\0';
ASSERT_FORTIFY(printf("%s", strchr(myfoo.a, 'a')));
+ ASSERT_FORTIFY(printf("%s", strchr(static_cast<const char*>(myfoo.a), 'a')));
#else // __BIONIC__
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif // __BIONIC__
}
-#endif
-#ifndef __clang__
-// This test is disabled in clang because clang doesn't properly detect
-// this buffer overflow. TODO: Fix clang.
TEST_F(DEATHTEST, strrchr_fortified2) {
#if defined(__BIONIC__)
foo myfoo;
memcpy(myfoo.a, "0123456789", 10);
memcpy(myfoo.b, "01234", 6);
ASSERT_FORTIFY(printf("%s", strrchr(myfoo.a, 'a')));
+ ASSERT_FORTIFY(printf("%s", strrchr(static_cast<const char*>(myfoo.a), 'a')));
#else // __BIONIC__
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif // __BIONIC__
}
-#endif
+
+TEST_F(DEATHTEST, memchr_fortified2) {
+#if defined(__BIONIC__)
+ foo myfoo;
+ volatile int asize = sizeof(myfoo.a) + 1;
+ memcpy(myfoo.a, "0123456789", sizeof(myfoo.a));
+ ASSERT_FORTIFY(printf("%s", memchr(myfoo.a, 'a', asize)));
+ ASSERT_FORTIFY(printf("%s", memchr(static_cast<const void*>(myfoo.a), 'a', asize)));
+#else // __BIONIC__
+ GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif // __BIONIC__
+}
#ifndef __clang__
// This test is disabled in clang because clang doesn't properly detect
diff --git a/tests/sys_ptrace_test.cpp b/tests/sys_ptrace_test.cpp
index bce5898..69638be 100644
--- a/tests/sys_ptrace_test.cpp
+++ b/tests/sys_ptrace_test.cpp
@@ -17,6 +17,7 @@
#include <sys/ptrace.h>
#include <elf.h>
+#include <err.h>
#include <fcntl.h>
#include <sched.h>
#include <sys/prctl.h>
@@ -26,11 +27,16 @@
#include <sys/wait.h>
#include <unistd.h>
+#include <chrono>
+#include <thread>
+
#include <gtest/gtest.h>
#include <android-base/macros.h>
#include <android-base/unique_fd.h>
+using namespace std::chrono_literals;
+
using android::base::unique_fd;
// Host libc does not define this.
@@ -367,31 +373,39 @@
class PtraceResumptionTest : public ::testing::Test {
public:
+ unique_fd worker_pipe_write;
+
pid_t worker = -1;
+ pid_t tracer = -1;
+
PtraceResumptionTest() {
+ unique_fd worker_pipe_read;
+ int pipefd[2];
+ if (pipe2(pipefd, O_CLOEXEC) != 0) {
+ err(1, "failed to create pipe");
+ }
+
+ worker_pipe_read.reset(pipefd[0]);
+ worker_pipe_write.reset(pipefd[1]);
+
+ worker = fork();
+ if (worker == -1) {
+ err(1, "failed to fork worker");
+ } else if (worker == 0) {
+ char buf;
+ worker_pipe_write.reset();
+ TEMP_FAILURE_RETRY(read(worker_pipe_read.get(), &buf, sizeof(buf)));
+ exit(0);
+ }
}
~PtraceResumptionTest() {
}
void AssertDeath(int signo);
- void Start(std::function<void()> f) {
- unique_fd worker_pipe_read, worker_pipe_write;
- int pipefd[2];
- ASSERT_EQ(0, pipe2(pipefd, O_CLOEXEC));
- worker_pipe_read.reset(pipefd[0]);
- worker_pipe_write.reset(pipefd[1]);
- worker = fork();
- ASSERT_NE(-1, worker);
- if (worker == 0) {
- char buf;
- worker_pipe_write.reset();
- TEMP_FAILURE_RETRY(read(worker_pipe_read.get(), &buf, sizeof(buf)));
- exit(0);
- }
-
- pid_t tracer = fork();
+ void StartTracer(std::function<void()> f) {
+ tracer = fork();
ASSERT_NE(-1, tracer);
if (tracer == 0) {
f();
@@ -400,26 +414,66 @@
}
exit(0);
}
+ }
+
+ bool WaitForTracer() {
+ if (tracer == -1) {
+ errx(1, "tracer not started");
+ }
int result;
pid_t rc = waitpid(tracer, &result, 0);
- ASSERT_EQ(tracer, rc);
- EXPECT_TRUE(WIFEXITED(result) || WIFSIGNALED(result));
+ if (rc != tracer) {
+ printf("waitpid returned %d (%s)\n", rc, strerror(errno));
+ return false;
+ }
+
+ if (!WIFEXITED(result) && !WIFSIGNALED(result)) {
+ printf("!WIFEXITED && !WIFSIGNALED\n");
+ return false;
+ }
+
if (WIFEXITED(result)) {
if (WEXITSTATUS(result) != 0) {
- FAIL() << "tracer failed";
+ printf("tracer failed\n");
+ return false;
}
}
- rc = waitpid(worker, &result, WNOHANG);
- ASSERT_EQ(0, rc);
+ return true;
+ }
+
+ bool WaitForWorker() {
+ if (worker == -1) {
+ errx(1, "worker not started");
+ }
+
+ int result;
+ pid_t rc = waitpid(worker, &result, WNOHANG);
+ if (rc != 0) {
+ printf("worker exited prematurely\n");
+ return false;
+ }
worker_pipe_write.reset();
rc = waitpid(worker, &result, 0);
- ASSERT_EQ(worker, rc);
- EXPECT_TRUE(WIFEXITED(result));
- EXPECT_EQ(WEXITSTATUS(result), 0);
+ if (rc != worker) {
+ printf("waitpid for worker returned %d (%s)\n", rc, strerror(errno));
+ return false;
+ }
+
+ if (!WIFEXITED(result)) {
+ printf("worker didn't exit\n");
+ return false;
+ }
+
+ if (WEXITSTATUS(result) != 0) {
+ printf("worker exited with status %d\n", WEXITSTATUS(result));
+ return false;
+ }
+
+ return true;
}
};
@@ -436,22 +490,74 @@
}
}
+TEST_F(PtraceResumptionTest, smoke) {
+ // Make sure that the worker doesn't exit before the tracer stops tracing.
+ StartTracer([this]() {
+ ASSERT_EQ(0, ptrace(PTRACE_SEIZE, worker, 0, 0)) << strerror(errno);
+ ASSERT_EQ(0, ptrace(PTRACE_INTERRUPT, worker, 0, 0)) << strerror(errno);
+ wait_for_ptrace_stop(worker);
+ std::this_thread::sleep_for(500ms);
+ });
+
+ worker_pipe_write.reset();
+ std::this_thread::sleep_for(250ms);
+
+ int result;
+ ASSERT_EQ(0, waitpid(worker, &result, WNOHANG));
+ ASSERT_TRUE(WaitForTracer());
+ ASSERT_EQ(worker, waitpid(worker, &result, 0));
+}
+
TEST_F(PtraceResumptionTest, seize) {
- Start([this]() { ASSERT_EQ(0, ptrace(PTRACE_SEIZE, worker, 0, 0)) << strerror(errno); });
+ StartTracer([this]() { ASSERT_EQ(0, ptrace(PTRACE_SEIZE, worker, 0, 0)) << strerror(errno); });
+ ASSERT_TRUE(WaitForTracer());
+ ASSERT_TRUE(WaitForWorker());
}
TEST_F(PtraceResumptionTest, seize_interrupt) {
- Start([this]() {
+ StartTracer([this]() {
ASSERT_EQ(0, ptrace(PTRACE_SEIZE, worker, 0, 0)) << strerror(errno);
ASSERT_EQ(0, ptrace(PTRACE_INTERRUPT, worker, 0, 0)) << strerror(errno);
+ wait_for_ptrace_stop(worker);
});
+ ASSERT_TRUE(WaitForTracer());
+ ASSERT_TRUE(WaitForWorker());
}
TEST_F(PtraceResumptionTest, seize_interrupt_cont) {
- Start([this]() {
+ StartTracer([this]() {
ASSERT_EQ(0, ptrace(PTRACE_SEIZE, worker, 0, 0)) << strerror(errno);
ASSERT_EQ(0, ptrace(PTRACE_INTERRUPT, worker, 0, 0)) << strerror(errno);
wait_for_ptrace_stop(worker);
ASSERT_EQ(0, ptrace(PTRACE_CONT, worker, 0, 0)) << strerror(errno);
});
+ ASSERT_TRUE(WaitForTracer());
+ ASSERT_TRUE(WaitForWorker());
+}
+
+TEST_F(PtraceResumptionTest, zombie_seize) {
+ StartTracer([this]() { ASSERT_EQ(0, ptrace(PTRACE_SEIZE, worker, 0, 0)) << strerror(errno); });
+ ASSERT_TRUE(WaitForWorker());
+ ASSERT_TRUE(WaitForTracer());
+}
+
+TEST_F(PtraceResumptionTest, zombie_seize_interrupt) {
+ StartTracer([this]() {
+ ASSERT_EQ(0, ptrace(PTRACE_SEIZE, worker, 0, 0)) << strerror(errno);
+ ASSERT_EQ(0, ptrace(PTRACE_INTERRUPT, worker, 0, 0)) << strerror(errno);
+ wait_for_ptrace_stop(worker);
+ });
+ ASSERT_TRUE(WaitForWorker());
+ ASSERT_TRUE(WaitForTracer());
+}
+
+TEST_F(PtraceResumptionTest, zombie_seize_interrupt_cont) {
+ StartTracer([this]() {
+ ASSERT_EQ(0, ptrace(PTRACE_SEIZE, worker, 0, 0)) << strerror(errno);
+ ASSERT_EQ(0, ptrace(PTRACE_INTERRUPT, worker, 0, 0)) << strerror(errno);
+ wait_for_ptrace_stop(worker);
+ ASSERT_EQ(0, ptrace(PTRACE_CONT, worker, 0, 0)) << strerror(errno);
+ });
+ ASSERT_TRUE(WaitForWorker());
+ ASSERT_TRUE(WaitForTracer());
}
diff --git a/tools/update_headers.sh b/tools/update_headers.sh
deleted file mode 100755
index 0095d50..0000000
--- a/tools/update_headers.sh
+++ /dev/null
@@ -1,53 +0,0 @@
-#!/bin/bash
-DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
-cd $DIR
-
-which versioner >/dev/null 2>&1
-if [ $? -ne 0 ]; then
- >&2 echo "versioner not in path; run mma in $DIR/versioner"
- exit 1
-fi
-
-VERSION=$(git rev-parse --short HEAD)
-git diff-index --quiet HEAD
-DIRTY=$?
-git branch -r --contains HEAD | grep -q aosp/master
-SUBMITTED=$?
-
-if [ $DIRTY -ne 0 ]; then
- >&2 echo "Warning: bionic has uncommitted changes"
- VERSION="${VERSION}-dirty"
-elif [ $SUBMITTED -ne 0 ]; then
- >&2 echo "Warning: current HEAD does not exist in aosp/master"
- VERSION="${VERSION}-unsubmitted"
-fi
-
-PREBUILTS_DIR=$ANDROID_BUILD_TOP/prebuilts/ndk
-BRANCH_NAME=$(git -C $PREBUILTS_DIR symbolic-ref --short -q HEAD)
-if [ $? -ne 0 ]; then
- BRANCH_NAME=update-bionic-headers-$VERSION
- echo "prebuilts/ndk has detached head; creating branch $BRANCH_NAME"
- repo start $BRANCH_NAME $PREBUILTS_DIR
-else
- echo "prebuilts/ndk already on branch $BRANCH_NAME"
-fi
-
-HEADERS_INSTALL=$PREBUILTS_DIR/headers
-if [ -d "$HEADERS_INSTALL" ]; then
- git -C $PREBUILTS_DIR rm -r --ignore-unmatch $HEADERS_INSTALL
- if [ -d $HEADERS_INSTALL ]; then
- rm -r $HEADERS_INSTALL
- fi
-fi
-
-versioner -p versioner/platforms versioner/current versioner/dependencies \
- -o $HEADERS_INSTALL
-if [ $? -ne 0 ]; then
- >&2 echo "Header preprocessing failed"
- exit 1
-fi
-
-cp ../libc/NOTICE $PREBUILTS_DIR
-
-git -C $PREBUILTS_DIR add $HEADERS_INSTALL $PREBUILTS_DIR/NOTICE
-git -C $PREBUILTS_DIR commit -m "Update bionic headers to $VERSION."
diff --git a/tools/versioner/dependencies/arm/arch-arm b/tools/versioner/dependencies/arm/arch-arm
deleted file mode 120000
index ed69f41..0000000
--- a/tools/versioner/dependencies/arm/arch-arm
+++ /dev/null
@@ -1 +0,0 @@
-../../../../libc/arch-arm/include
\ No newline at end of file
diff --git a/tools/versioner/dependencies/arm/kernel_uapi_asm-arm b/tools/versioner/dependencies/arm/kernel_uapi_asm-arm
deleted file mode 120000
index fabed85..0000000
--- a/tools/versioner/dependencies/arm/kernel_uapi_asm-arm
+++ /dev/null
@@ -1 +0,0 @@
-../../../../libc/kernel/uapi/asm-arm
\ No newline at end of file
diff --git a/tools/versioner/dependencies/arm64/arch-arm64 b/tools/versioner/dependencies/arm64/arch-arm64
deleted file mode 120000
index 21a21d4..0000000
--- a/tools/versioner/dependencies/arm64/arch-arm64
+++ /dev/null
@@ -1 +0,0 @@
-../../../../libc/arch-arm64/include
\ No newline at end of file
diff --git a/tools/versioner/dependencies/arm64/kernel_uapi_asm-arm64 b/tools/versioner/dependencies/arm64/kernel_uapi_asm-arm64
deleted file mode 120000
index 16e74a3..0000000
--- a/tools/versioner/dependencies/arm64/kernel_uapi_asm-arm64
+++ /dev/null
@@ -1 +0,0 @@
-../../../../libc/kernel/uapi/asm-arm64
\ No newline at end of file
diff --git a/tools/versioner/dependencies/common/clang-builtins b/tools/versioner/dependencies/common/clang-builtins
deleted file mode 120000
index fc27e65..0000000
--- a/tools/versioner/dependencies/common/clang-builtins
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../external/clang/lib/Headers
\ No newline at end of file
diff --git a/tools/versioner/dependencies/common/kernel_android_uapi b/tools/versioner/dependencies/common/kernel_android_uapi
deleted file mode 120000
index bcf6daa..0000000
--- a/tools/versioner/dependencies/common/kernel_android_uapi
+++ /dev/null
@@ -1 +0,0 @@
-../../../../libc/kernel/android/uapi
\ No newline at end of file
diff --git a/tools/versioner/dependencies/common/kernel_uapi b/tools/versioner/dependencies/common/kernel_uapi
deleted file mode 120000
index 2a915ef..0000000
--- a/tools/versioner/dependencies/common/kernel_uapi
+++ /dev/null
@@ -1 +0,0 @@
-../../../../libc/kernel/uapi
\ No newline at end of file
diff --git a/tools/versioner/dependencies/mips/arch-mips b/tools/versioner/dependencies/mips/arch-mips
deleted file mode 120000
index 7f2f104..0000000
--- a/tools/versioner/dependencies/mips/arch-mips
+++ /dev/null
@@ -1 +0,0 @@
-../../../../libc/arch-mips/include
\ No newline at end of file
diff --git a/tools/versioner/dependencies/mips/kernel_uapi_asm-mips b/tools/versioner/dependencies/mips/kernel_uapi_asm-mips
deleted file mode 120000
index dcd1955..0000000
--- a/tools/versioner/dependencies/mips/kernel_uapi_asm-mips
+++ /dev/null
@@ -1 +0,0 @@
-../../../../libc/kernel/uapi/asm-mips
\ No newline at end of file
diff --git a/tools/versioner/dependencies/mips64/arch-mips64 b/tools/versioner/dependencies/mips64/arch-mips64
deleted file mode 120000
index 48cea72..0000000
--- a/tools/versioner/dependencies/mips64/arch-mips64
+++ /dev/null
@@ -1 +0,0 @@
-../../../../libc/arch-mips64/include
\ No newline at end of file
diff --git a/tools/versioner/dependencies/mips64/kernel_uapi_asm-mips b/tools/versioner/dependencies/mips64/kernel_uapi_asm-mips
deleted file mode 120000
index dcd1955..0000000
--- a/tools/versioner/dependencies/mips64/kernel_uapi_asm-mips
+++ /dev/null
@@ -1 +0,0 @@
-../../../../libc/kernel/uapi/asm-mips
\ No newline at end of file
diff --git a/tools/versioner/dependencies/x86/arch-x86 b/tools/versioner/dependencies/x86/arch-x86
deleted file mode 120000
index d0f016a..0000000
--- a/tools/versioner/dependencies/x86/arch-x86
+++ /dev/null
@@ -1 +0,0 @@
-../../../../libc/arch-x86/include
\ No newline at end of file
diff --git a/tools/versioner/dependencies/x86/kernel_uapi_asm-x86 b/tools/versioner/dependencies/x86/kernel_uapi_asm-x86
deleted file mode 120000
index 0efae62..0000000
--- a/tools/versioner/dependencies/x86/kernel_uapi_asm-x86
+++ /dev/null
@@ -1 +0,0 @@
-../../../../libc/kernel/uapi/asm-x86
\ No newline at end of file
diff --git a/tools/versioner/dependencies/x86_64/arch-x86_64 b/tools/versioner/dependencies/x86_64/arch-x86_64
deleted file mode 120000
index deb647d..0000000
--- a/tools/versioner/dependencies/x86_64/arch-x86_64
+++ /dev/null
@@ -1 +0,0 @@
-../../../../libc/arch-x86_64/include
\ No newline at end of file
diff --git a/tools/versioner/dependencies/x86_64/kernel_uapi_asm-x86 b/tools/versioner/dependencies/x86_64/kernel_uapi_asm-x86
deleted file mode 120000
index 0efae62..0000000
--- a/tools/versioner/dependencies/x86_64/kernel_uapi_asm-x86
+++ /dev/null
@@ -1 +0,0 @@
-../../../../libc/kernel/uapi/asm-x86
\ No newline at end of file
diff --git a/tools/versioner/preupload.sh b/tools/versioner/preupload.sh
deleted file mode 100755
index 45d6cca..0000000
--- a/tools/versioner/preupload.sh
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/bash
-
-if ! which versioner > /dev/null; then
- echo "versioner not found (lunch and mma in bionic)"
- exit 1
-fi
-
-versioner -r arm -r arm64
-exit $?
diff --git a/tools/versioner/src/Android.bp b/tools/versioner/src/Android.bp
index d1362d0..c5afa56 100644
--- a/tools/versioner/src/Android.bp
+++ b/tools/versioner/src/Android.bp
@@ -41,18 +41,8 @@
"-fno-rtti",
],
},
- darwin: {
- enabled: false,
- },
windows: {
enabled: false,
},
},
-
- product_variables: {
- unbundled_build: {
- // Only do this when Clang is available.
- enabled: false,
- },
- },
}
diff --git a/tools/versioner/src/Preprocessor.cpp b/tools/versioner/src/Preprocessor.cpp
index 86bb225..757a392 100644
--- a/tools/versioner/src/Preprocessor.cpp
+++ b/tools/versioner/src/Preprocessor.cpp
@@ -336,7 +336,6 @@
current_location.column = pos + 1;
if (line[pos] != '/') {
- D("Trailing character '%c' is not a slash: %s\n", line[pos], line.substr(pos).c_str());
valid = false;
break;
}
@@ -409,7 +408,9 @@
file_lines[loc.start.line - 1].insert(loc.start.column - 1, prologue);
}
- printf("Preprocessing %s...\n", output_path.c_str());
+ if (verbose) {
+ printf("Preprocessing %s...\n", output_path.c_str());
+ }
writeFileLines(output_path, file_lines);
}
diff --git a/tools/versioner/src/versioner.cpp b/tools/versioner/src/versioner.cpp
index e39bec0..194f276 100644
--- a/tools/versioner/src/versioner.cpp
+++ b/tools/versioner/src/versioner.cpp
@@ -435,7 +435,7 @@
fprintf(stderr, "\n");
fprintf(stderr, "Preprocessing:\n");
fprintf(stderr, " -o PATH\tpreprocess header files and emit them at PATH\n");
- fprintf(stderr, " -f\tpreprocess header files even if validation fails\n");
+ fprintf(stderr, " -f\t\tpreprocess header files even if validation fails\n");
fprintf(stderr, "\n");
fprintf(stderr, "Miscellaneous:\n");
fprintf(stderr, " -d\t\tdump function availability\n");