Merge "Implement pthread_attr_getinheritsched/pthread_attr_setinheritsched."
diff --git a/android-changes-for-ndk-developers.md b/android-changes-for-ndk-developers.md
index c301857..0620d9e 100644
--- a/android-changes-for-ndk-developers.md
+++ b/android-changes-for-ndk-developers.md
@@ -376,3 +376,22 @@
```
enables logging of all errors and dlopen calls
+
+## dlclose interacts badly with thread local variables with non-trivial destructors
+
+Android allows `dlclose` to unload a library even if there are still
+thread-local variables with non-trivial destructors. This leads to
+crashes when a thread exits and attempts to call the destructor, the
+code for which has been unloaded (as in [issue 360]).
+
+[issue 360]: https://github.com/android-ndk/ndk/issues/360
+
+Not calling `dlclose` or ensuring that your library has `RTLD_NODELETE`
+set (so that calls to `dlclose` don't actually unload the library)
+are possible workarounds.
+
+| | Pre-M | M+ |
+| ----------------- | -------------------------- | ------- |
+| No workaround | Works for static STL | Broken |
+| `-Wl,-z,nodelete` | Works for static STL | Works |
+| No `dlclose` | Works | Works |
diff --git a/benchmarks/math_benchmark.cpp b/benchmarks/math_benchmark.cpp
index 7b9a283..4d9d3cb 100644
--- a/benchmarks/math_benchmark.cpp
+++ b/benchmarks/math_benchmark.cpp
@@ -69,16 +69,11 @@
}
BIONIC_BENCHMARK(BM_math_isfinite_macro);
-#if defined(__BIONIC__)
-#define test_isfinite __isfinite
-#else
-#define test_isfinite __finite
-#endif
static void BM_math_isfinite(benchmark::State& state) {
d = 0.0;
v = values[state.range(0)];
while (state.KeepRunning()) {
- d += test_isfinite(v);
+ d += isfinite(v);
}
SetLabel(state);
}
@@ -134,17 +129,15 @@
}
BIONIC_BENCHMARK(BM_math_isnormal_macro);
-#if defined(__BIONIC__)
static void BM_math_isnormal(benchmark::State& state) {
d = 0.0;
v = values[state.range(0)];
while (state.KeepRunning()) {
- d += (__isnormal)(v);
+ d += isnormal(v);
}
SetLabel(state);
}
BIONIC_BENCHMARK(BM_math_isnormal);
-#endif
static void BM_math_sin_fast(benchmark::State& state) {
d = 1.0;
@@ -202,7 +195,7 @@
d = 0.0;
v = values[state.range(0)];
while (state.KeepRunning()) {
- d += (__signbit)(v);
+ d += signbit(v);
}
SetLabel(state);
}
diff --git a/benchmarks/pthread_benchmark.cpp b/benchmarks/pthread_benchmark.cpp
index 7a967ef..1ad6345 100644
--- a/benchmarks/pthread_benchmark.cpp
+++ b/benchmarks/pthread_benchmark.cpp
@@ -137,9 +137,7 @@
}
BIONIC_BENCHMARK(BM_pthread_create);
-static void* RunThread(void* arg) {
- benchmark::State& state = *reinterpret_cast<benchmark::State*>(arg);
- state.PauseTiming();
+static void* RunThread(void*) {
return NULL;
}
@@ -148,22 +146,18 @@
pthread_t thread;
pthread_create(&thread, NULL, RunThread, &state);
pthread_join(thread, NULL);
- state.ResumeTiming();
}
}
BIONIC_BENCHMARK(BM_pthread_create_and_run);
-static void* ExitThread(void* arg) {
- benchmark::State& state = *reinterpret_cast<benchmark::State*>(arg);
- state.ResumeTiming();
+static void* ExitThread(void*) {
pthread_exit(NULL);
}
static void BM_pthread_exit_and_join(benchmark::State& state) {
while (state.KeepRunning()) {
- state.PauseTiming();
pthread_t thread;
- pthread_create(&thread, NULL, ExitThread, &state);
+ pthread_create(&thread, NULL, ExitThread, nullptr);
pthread_join(thread, NULL);
}
}
diff --git a/docs/32-bit-abi.md b/docs/32-bit-abi.md
index eecbe6d..5e3ae45 100644
--- a/docs/32-bit-abi.md
+++ b/docs/32-bit-abi.md
@@ -57,3 +57,14 @@
Android all use the 32-bit `time_t`.
In the 64-bit ABI, `time_t` is 64-bit.
+
+`pthread_mutex_t` is too small for large pids
+---------------------------------------------
+
+This doesn't generally affect Android devices, because on devices
+`/proc/sys/kernel/pid_max` is usually too small to hit the 16-bit limit,
+but 32-bit bionic's `pthread_mutex` is a total of 32 bits, leaving just
+16 bits for the owner thread id. This means bionic isn't able to support
+mutexes for tids that don't fit in 16 bits. This typically manifests as
+a hang in `pthread_mutex_lock` if the libc startup code doesn't detect
+this condition and abort.
diff --git a/docs/status.md b/docs/status.md
index e448ef7..32de91e 100644
--- a/docs/status.md
+++ b/docs/status.md
@@ -9,6 +9,7 @@
New libc functions in P:
* `__freading`/`__fwriting` (completing <stdio_ext.h>)
* `endhostent`/endnetent`/`endprotoent`/`getnetent`/`getprotoent`/`sethostent`/`setnetent`/`setprotoent` (completing <netdb.h>)
+ * `fexecve`
* `getentropy`/`getrandom` (adding <sys/random.h>)
* `getlogin_r`
* `glob`/`globfree` (adding <glob.h>)
@@ -16,6 +17,7 @@
* `iconv`/`iconv_close`/`iconv_open` (adding <iconv.h>)
* `pthread_attr_getinheritsched`/`pthread_attr_setinheritsched`/`pthread_setschedprio`
* <spawn.h>
+ * `swab`
* `syncfs`
New libc functions in O:
@@ -71,10 +73,6 @@
aio_return
aio_suspend
aio_write
-fexecve
-fmtmsg
-getdate
-getdate_err
lio_listio
pthread_cancel
pthread_mutex_consistent
@@ -89,8 +87,6 @@
pthread_setcancelstate
pthread_setcanceltype
pthread_testcancel
-sockatmark
-swab
wordexp
wordfree
```
diff --git a/libc/Android.bp b/libc/Android.bp
index 81135ea..2e5ec00 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -1534,6 +1534,7 @@
"bionic/strings_l.cpp",
"bionic/strsignal.cpp",
"bionic/strtold.cpp",
+ "bionic/swab.cpp",
"bionic/symlink.cpp",
"bionic/sync_file_range.cpp",
"bionic/sys_msg.cpp",
diff --git a/libc/NOTICE b/libc/NOTICE
index c0e6265..cbcafc8 100644
--- a/libc/NOTICE
+++ b/libc/NOTICE
@@ -3812,32 +3812,6 @@
-------------------------------------------------------------------
Copyright (c) 2003 Mike Barcroft <mike@FreeBSD.org>
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-2. 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 AUTHOR 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 AUTHOR 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2003 Mike Barcroft <mike@FreeBSD.org>
Copyright (c) 2002 David Schultz <das@FreeBSD.ORG>
All rights reserved.
diff --git a/libc/arch-common/bionic/__dso_handle.h b/libc/arch-common/bionic/__dso_handle.h
index d4bff77..fa40060 100644
--- a/libc/arch-common/bionic/__dso_handle.h
+++ b/libc/arch-common/bionic/__dso_handle.h
@@ -28,11 +28,6 @@
#ifndef CRT_LEGACY_WORKAROUND
-__attribute__ ((visibility ("hidden")))
+__attribute__((__visibility__("hidden")))
#endif
-#ifdef __aarch64__
-__attribute__ ((section (".data")))
-#else
-__attribute__ ((section (".bss")))
-#endif
-void *__dso_handle = (void *) 0;
+void* __dso_handle = (void*) 0;
diff --git a/libc/arch-common/bionic/__dso_handle_so.h b/libc/arch-common/bionic/__dso_handle_so.h
index fab328a..e2c26b6 100644
--- a/libc/arch-common/bionic/__dso_handle_so.h
+++ b/libc/arch-common/bionic/__dso_handle_so.h
@@ -26,11 +26,4 @@
* SUCH DAMAGE.
*/
-
-__attribute__ ((visibility ("hidden")))
-__attribute__ ((section (".data")))
-#ifdef __aarch64__
-void *__dso_handle = (void *) 0;
-#else
-void *__dso_handle = &__dso_handle;
-#endif
+__attribute__((__visibility__("hidden"))) void* __dso_handle = &__dso_handle;
diff --git a/libc/bionic/__libc_init_main_thread.cpp b/libc/bionic/__libc_init_main_thread.cpp
index 6d948ec..5004e24 100644
--- a/libc/bionic/__libc_init_main_thread.cpp
+++ b/libc/bionic/__libc_init_main_thread.cpp
@@ -31,6 +31,7 @@
#include "private/KernelArgumentBlock.h"
#include "private/bionic_arc4random.h"
#include "private/bionic_auxv.h"
+#include "private/bionic_defs.h"
#include "private/bionic_globals.h"
#include "private/bionic_ssp.h"
#include "pthread_internal.h"
@@ -58,6 +59,7 @@
// -fno-stack-protector because it's responsible for setting up the main
// thread's TLS (which stack protector relies on).
+__BIONIC_WEAK_FOR_NATIVE_BRIDGE
void __libc_init_main_thread(KernelArgumentBlock& args) {
__libc_auxv = args.auxv;
#if defined(__i386__)
diff --git a/libc/bionic/android_set_abort_message.cpp b/libc/bionic/android_set_abort_message.cpp
index 8c80c5a..268c4f3 100644
--- a/libc/bionic/android_set_abort_message.cpp
+++ b/libc/bionic/android_set_abort_message.cpp
@@ -32,6 +32,7 @@
#include <string.h>
#include <sys/mman.h>
+#include "private/bionic_defs.h"
#include "private/ScopedPthreadMutexLocker.h"
static pthread_mutex_t g_abort_msg_lock = PTHREAD_MUTEX_INITIALIZER;
@@ -43,6 +44,7 @@
abort_msg_t** __abort_message_ptr; // Accessible to __libc_init_common.
+__BIONIC_WEAK_FOR_NATIVE_BRIDGE
void android_set_abort_message(const char* msg) {
ScopedPthreadMutexLocker locker(&g_abort_msg_lock);
diff --git a/libc/bionic/exec.cpp b/libc/bionic/exec.cpp
index 2001106..1cf3a58 100644
--- a/libc/bionic/exec.cpp
+++ b/libc/bionic/exec.cpp
@@ -39,6 +39,8 @@
#include <string.h>
#include <unistd.h>
+#include "private/FdPath.h"
+
extern "C" char** environ;
enum ExecVariant { kIsExecL, kIsExecLE, kIsExecLP };
@@ -170,3 +172,10 @@
if (saw_EACCES) errno = EACCES;
return -1;
}
+
+int fexecve(int fd, char* const* argv, char* const* envp) {
+ // execveat with AT_EMPTY_PATH (>= 3.19) seems to offer no advantages.
+ execve(FdPath(fd).c_str(), argv, envp);
+ if (errno == ENOENT) errno = EBADF;
+ return -1;
+}
diff --git a/libc/bionic/fchmod.cpp b/libc/bionic/fchmod.cpp
index ace8c6b..a486aae 100644
--- a/libc/bionic/fchmod.cpp
+++ b/libc/bionic/fchmod.cpp
@@ -33,13 +33,14 @@
#include <unistd.h>
#include <stdio.h>
+#include "private/FdPath.h"
+
extern "C" int ___fchmod(int, mode_t);
int fchmod(int fd, mode_t mode) {
int saved_errno = errno;
int result = ___fchmod(fd, mode);
-
- if ((result == 0) || (errno != EBADF)) {
+ if (result == 0 || errno != EBADF) {
return result;
}
@@ -52,16 +53,14 @@
// on an O_PATH file descriptor, and "man open" documents fchmod
// on O_PATH file descriptors as returning EBADF.
int fd_flag = fcntl(fd, F_GETFL);
- if ((fd_flag == -1) || ((fd_flag & O_PATH) == 0)) {
+ if (fd_flag == -1 || (fd_flag & O_PATH) == 0) {
errno = EBADF;
return -1;
}
- char buf[40];
- snprintf(buf, sizeof(buf), "/proc/self/fd/%d", fd);
errno = saved_errno;
- result = chmod(buf, mode);
- if ((result == -1) && (errno == ELOOP)) {
+ result = chmod(FdPath(fd).c_str(), mode);
+ if (result == -1 && errno == ELOOP) {
// Linux does not support changing the mode of a symlink.
// For fchmodat(AT_SYMLINK_NOFOLLOW), POSIX requires a return
// value of ENOTSUP. Assume that's true here too.
diff --git a/libc/bionic/fgetxattr.cpp b/libc/bionic/fgetxattr.cpp
index 6d999bf..38b7ac3 100644
--- a/libc/bionic/fgetxattr.cpp
+++ b/libc/bionic/fgetxattr.cpp
@@ -33,13 +33,15 @@
#include <fcntl.h>
#include <stdio.h>
+#include "private/FdPath.h"
+
extern "C" ssize_t ___fgetxattr(int, const char*, void*, size_t);
ssize_t fgetxattr(int fd, const char *name, void *value, size_t size) {
int saved_errno = errno;
ssize_t result = ___fgetxattr(fd, name, value, size);
- if ((result != -1) || (errno != EBADF)) {
+ if (result != -1 || errno != EBADF) {
return result;
}
@@ -47,13 +49,11 @@
// may not directly support fgetxattr() on such a file descriptor.
// Use /proc/self/fd instead to emulate this support.
int fd_flag = fcntl(fd, F_GETFL);
- if ((fd_flag == -1) || ((fd_flag & O_PATH) == 0)) {
+ if (fd_flag == -1 || (fd_flag & O_PATH) == 0) {
errno = EBADF;
return -1;
}
- char buf[40];
- snprintf(buf, sizeof(buf), "/proc/self/fd/%d", fd);
errno = saved_errno;
- return getxattr(buf, name, value, size);
+ return getxattr(FdPath(fd).c_str(), name, value, size);
}
diff --git a/libc/bionic/flistxattr.cpp b/libc/bionic/flistxattr.cpp
index 05a96d2..8ad9b85 100644
--- a/libc/bionic/flistxattr.cpp
+++ b/libc/bionic/flistxattr.cpp
@@ -33,13 +33,14 @@
#include <fcntl.h>
#include <stdio.h>
+#include "private/FdPath.h"
+
extern "C" ssize_t ___flistxattr(int, char*, size_t);
ssize_t flistxattr(int fd, char *list, size_t size) {
int saved_errno = errno;
ssize_t result = ___flistxattr(fd, list, size);
-
- if ((result != -1) || (errno != EBADF)) {
+ if (result != -1 || errno != EBADF) {
return result;
}
@@ -47,13 +48,11 @@
// may not directly support fgetxattr() on such a file descriptor.
// Use /proc/self/fd instead to emulate this support.
int fd_flag = fcntl(fd, F_GETFL);
- if ((fd_flag == -1) || ((fd_flag & O_PATH) == 0)) {
+ if (fd_flag == -1 || (fd_flag & O_PATH) == 0) {
errno = EBADF;
return -1;
}
- char buf[40];
- snprintf(buf, sizeof(buf), "/proc/self/fd/%d", fd);
errno = saved_errno;
- return listxattr(buf, list, size);
+ return listxattr(FdPath(fd).c_str(), list, size);
}
diff --git a/libc/bionic/fpclassify.cpp b/libc/bionic/fpclassify.cpp
index 42ed3ef..7aa53f3 100644
--- a/libc/bionic/fpclassify.cpp
+++ b/libc/bionic/fpclassify.cpp
@@ -26,145 +26,80 @@
* SUCH DAMAGE.
*/
-#include <sys/types.h>
-
#include <math.h>
-#include "private/bionic_ieee.h"
+// Legacy cruft from before we had builtin implementations of the standard macros.
+// No longer declared in our <math.h>.
-// These aren't declared in our <math.h>.
-extern "C" int __isinf(double);
-extern "C" int __isnan(double);
-
-union float_u {
- float f;
- ieee_single bits;
-};
-
-union double_u {
- double d;
- ieee_double bits;
-};
-
-int __fpclassifyd(double d) {
- double_u u;
- u.d = d;
- if (u.bits.dbl_exp == 0) {
- return ((u.bits.dbl_fracl | u.bits.dbl_frach) == 0) ? FP_ZERO : FP_SUBNORMAL;
- }
- if (u.bits.dbl_exp == DBL_EXP_INFNAN) {
- return ((u.bits.dbl_fracl | u.bits.dbl_frach) == 0) ? FP_INFINITE : FP_NAN;
- }
- return FP_NORMAL;
+extern "C" int __fpclassifyd(double d) {
+ return fpclassify(d);
}
__strong_alias(__fpclassify, __fpclassifyd); // glibc uses __fpclassify, BSD __fpclassifyd.
-int __fpclassifyf(float f) {
- float_u u;
- u.f = f;
- if (u.bits.sng_exp == 0) {
- return (u.bits.sng_frac == 0) ? FP_ZERO : FP_SUBNORMAL;
- }
- if (u.bits.sng_exp == SNG_EXP_INFNAN) {
- return (u.bits.sng_frac == 0) ? FP_INFINITE : FP_NAN;
- }
- return FP_NORMAL;
+extern "C" int __fpclassifyf(float f) {
+ return fpclassify(f);
}
-int __isinf(double d) {
- return (__fpclassifyd(d) == FP_INFINITE);
+extern "C" int __isinf(double d) {
+ return isinf(d);
}
__strong_alias(isinf, __isinf);
-int __isinff(float f) {
- return (__fpclassifyf(f) == FP_INFINITE);
+extern "C" int __isinff(float f) {
+ return isinf(f);
}
__strong_alias(isinff, __isinff);
-int __isnan(double d) {
- return (__fpclassifyd(d) == FP_NAN);
+extern "C" int __isnan(double d) {
+ return isnan(d);
}
__strong_alias(isnan, __isnan);
-int __isnanf(float f) {
- return (__fpclassifyf(f) == FP_NAN);
+extern "C" int __isnanf(float f) {
+ return isnan(f);
}
__strong_alias(isnanf, __isnanf);
-int __isfinite(double d) {
- int type = __fpclassifyd(d);
- return ((type != FP_NAN) && (type != FP_INFINITE));
+extern "C" int __isfinite(double d) {
+ return isfinite(d);
}
__strong_alias(isfinite, __isfinite);
-int __isfinitef(float f) {
- int type = __fpclassifyf(f);
- return ((type != FP_NAN) && (type != FP_INFINITE));
+extern "C" int __isfinitef(float f) {
+ return isfinite(f);
}
__strong_alias(isfinitef, __isfinitef);
-int __isnormal(double d) {
- return (__fpclassifyd(d) == FP_NORMAL);
+extern "C" int __isnormal(double d) {
+ return isnormal(d);
}
__strong_alias(isnormal, __isnormal);
-int __isnormalf(float f) {
- return (__fpclassifyf(f) == FP_NORMAL);
+extern "C" int __isnormalf(float f) {
+ return isnormal(f);
}
__strong_alias(isnormalf, __isnormalf);
-#if defined(__LP64__)
-
-// LP64 uses 128-bit long doubles.
-
-union long_double_u {
- long double ld;
- ieee_ext bits;
-};
-
-#define zero_frac(b) ((b.ext_fracl | b.ext_fraclm | b.ext_frachm | b.ext_frach) == 0)
-
-int __fpclassifyl(long double ld) {
- long_double_u u;
- u.ld = ld;
- if (u.bits.ext_exp == 0) {
- return zero_frac(u.bits) ? FP_ZERO : FP_SUBNORMAL;
- }
- if (u.bits.ext_exp == EXT_EXP_INFNAN) {
- return zero_frac(u.bits) ? FP_INFINITE : FP_NAN;
- }
- return FP_NORMAL;
+extern "C" int __fpclassifyl(long double ld) {
+ return fpclassify(ld);
}
-int __isinfl(long double ld) {
- return (__fpclassifyl(ld) == FP_INFINITE);
+extern "C" int __isinfl(long double ld) {
+ return isinf(ld);
}
-int __isnanl(long double ld) {
- return (__fpclassifyl(ld) == FP_NAN);
+extern "C" int __isnanl(long double ld) {
+ return isnan(ld);
}
-int __isfinitel(long double ld) {
- int type = __fpclassifyl(ld);
- return ((type != FP_NAN) && (type != FP_INFINITE));
+extern "C" int __isfinitel(long double ld) {
+ return isfinite(ld);
}
-int __isnormall(long double ld) {
- return (__fpclassifyl(ld) == FP_NORMAL);
+extern "C" int __isnormall(long double ld) {
+ return isnormal(ld);
}
-#else
-
-// LP32 uses double as long double.
-
-__strong_alias(__fpclassifyl, __fpclassify);
-__strong_alias(__isinfl, __isinf);
-__strong_alias(__isnanl, __isnan);
-__strong_alias(__isfinitel, __isfinite);
-__strong_alias(__isnormall, __isnormal);
-
-#endif
-
__strong_alias(isinfl, __isinfl);
__strong_alias(isnanl, __isnanl);
__strong_alias(isfinitel, __isfinitel);
diff --git a/libc/bionic/fsetxattr.cpp b/libc/bionic/fsetxattr.cpp
index 6d2e868..9ad0c76 100644
--- a/libc/bionic/fsetxattr.cpp
+++ b/libc/bionic/fsetxattr.cpp
@@ -33,13 +33,14 @@
#include <fcntl.h>
#include <stdio.h>
+#include "private/FdPath.h"
+
extern "C" int ___fsetxattr(int, const char*, const void*, size_t, int);
int fsetxattr(int fd, const char* name, const void* value, size_t size, int flags) {
int saved_errno = errno;
int result = ___fsetxattr(fd, name, value, size, flags);
-
- if ((result == 0) || (errno != EBADF)) {
+ if (result == 0 || errno != EBADF) {
return result;
}
@@ -47,13 +48,11 @@
// may not directly support fsetxattr() on such a file descriptor.
// Use /proc/self/fd instead to emulate this support.
int fd_flag = fcntl(fd, F_GETFL);
- if ((fd_flag == -1) || ((fd_flag & O_PATH) == 0)) {
+ if (fd_flag == -1 || (fd_flag & O_PATH) == 0) {
errno = EBADF;
return -1;
}
- char buf[40];
- snprintf(buf, sizeof(buf), "/proc/self/fd/%d", fd);
errno = saved_errno;
- return setxattr(buf, name, value, size, flags);
+ return setxattr(FdPath(fd).c_str(), name, value, size, flags);
}
diff --git a/libc/bionic/libc_init_dynamic.cpp b/libc/bionic/libc_init_dynamic.cpp
index 349d488..0b68280 100644
--- a/libc/bionic/libc_init_dynamic.cpp
+++ b/libc/bionic/libc_init_dynamic.cpp
@@ -77,11 +77,14 @@
netdClientInit();
}
-// We flag the __libc_preinit function as a constructor to ensure
-// that its address is listed in libc.so's .init_array section.
-// This ensures that the function is called by the dynamic linker
-// as soon as the shared library is loaded.
-__attribute__((constructor)) static void __libc_preinit() {
+// We flag the __libc_preinit function as a constructor to ensure that
+// its address is listed in libc.so's .init_array section.
+// This ensures that the function is called by the dynamic linker as
+// soon as the shared library is loaded.
+// We give this constructor priority 1 because we want libc's constructor
+// to run before any others (such as the jemalloc constructor), and lower
+// is better (http://b/68046352).
+__attribute__((constructor(1))) static void __libc_preinit() {
// Read the kernel argument block pointer from TLS.
void** tls = __get_tls();
KernelArgumentBlock** args_slot = &reinterpret_cast<KernelArgumentBlock**>(tls)[TLS_SLOT_BIONIC_PREINIT];
diff --git a/libc/bionic/pty.cpp b/libc/bionic/pty.cpp
index bdabf36..599cbd2 100644
--- a/libc/bionic/pty.cpp
+++ b/libc/bionic/pty.cpp
@@ -37,6 +37,7 @@
#include <utmp.h>
#include "bionic/pthread_internal.h"
+#include "private/FdPath.h"
int getpt() {
return posix_openpt(O_RDWR|O_NOCTTY);
@@ -94,10 +95,7 @@
return errno;
}
- char path[64];
- snprintf(path, sizeof(path), "/proc/self/fd/%d", fd);
-
- ssize_t count = readlink(path, buf, len);
+ ssize_t count = readlink(FdPath(fd).c_str(), buf, len);
if (count == -1) {
return errno;
}
diff --git a/libc/bionic/swab.cpp b/libc/bionic/swab.cpp
new file mode 100644
index 0000000..bc53ba4
--- /dev/null
+++ b/libc/bionic/swab.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#include <unistd.h>
+
+void swab(const void* void_src, void* void_dst, ssize_t byte_count) {
+ const uint8_t* src = static_cast<const uint8_t*>(void_src);
+ uint8_t* dst = static_cast<uint8_t*>(void_dst);
+ while (byte_count > 1) {
+ uint8_t x = *src++;
+ uint8_t y = *src++;
+ *dst++ = y;
+ *dst++ = x;
+ byte_count -= 2;
+ }
+}
diff --git a/libc/include/bits/posix_limits.h b/libc/include/bits/posix_limits.h
index 17a39a4..8dfea52 100644
--- a/libc/include/bits/posix_limits.h
+++ b/libc/include/bits/posix_limits.h
@@ -70,7 +70,7 @@
#define _POSIX_SHELL 1 /* system. */
#define _POSIX_SPAWN __BIONIC_POSIX_FEATURE_SINCE(28) /* <spawn.h> */
#define _POSIX_SPIN_LOCKS __BIONIC_POSIX_FEATURE_SINCE(24) /* pthread_spin_*. */
-#define _POSIX_SPORADIC_SERVER _POSIX_VERSION /* sched_setparam/sched_setscheduler. */
+#define _POSIX_SPORADIC_SERVER __BIONIC_POSIX_FEATURE_MISSING /* No SCHED_SPORADIC. */
#define _POSIX_SYNCHRONIZED_IO _POSIX_VERSION
#define _POSIX_THREAD_ATTR_STACKADDR _POSIX_VERSION /* Strictly, we're missing the deprecated pthread_attr_getstackaddr/pthread_attr_setstackaddr, but we do have pthread_attr_getstack/pthread_attr_setstack. */
#define _POSIX_THREAD_ATTR_STACKSIZE _POSIX_VERSION /* pthread_attr_getstack/pthread_attr_getstacksize/pthread_attr_setstack/pthread_attr_setstacksize. */
@@ -82,7 +82,7 @@
#define _POSIX_THREAD_ROBUST_PRIO_INHERIT __BIONIC_POSIX_FEATURE_MISSING
#define _POSIX_THREAD_ROBUST_PRIO_PROTECT __BIONIC_POSIX_FEATURE_MISSING
#define _POSIX_THREAD_SAFE_FUNCTIONS _POSIX_VERSION
-#define _POSIX_THREAD_SPORADIC_SERVER _POSIX_VERSION /* sched_setparam/sched_setscheduler. */
+#define _POSIX_THREAD_SPORADIC_SERVER __BIONIC_POSIX_FEATURE_MISSING /* No SCHED_SPORADIC. */
#define _POSIX_THREADS _POSIX_VERSION /* Strictly, pthread_cancel/pthread_testcancel are missing. */
#define _POSIX_TIMEOUTS __BIONIC_POSIX_FEATURE_SINCE(21) /* pthread_mutex_timedlock arrived late. */
#define _POSIX_TIMERS _POSIX_VERSION /* clock_getres/clock_gettime/clock_settime/nanosleep/timer_create/timer_delete/timer_gettime/timer_getoverrun/timer_settime. */
@@ -94,6 +94,15 @@
#define _POSIX_VDISABLE '\0'
+#define _POSIX2_C_BIND _POSIX_VERSION
+#define _POSIX2_C_DEV __BIONIC_POSIX_FEATURE_MISSING
+#define _POSIX2_CHAR_TERM _POSIX_VERSION
+#define _POSIX2_FORT_DEV __BIONIC_POSIX_FEATURE_MISSING
+#define _POSIX2_FORT_RUN __BIONIC_POSIX_FEATURE_MISSING
+#define _POSIX2_LOCALEDEF __BIONIC_POSIX_FEATURE_MISSING
+#define _POSIX2_SW_DEV __BIONIC_POSIX_FEATURE_MISSING
+#define _POSIX2_UPE __BIONIC_POSIX_FEATURE_MISSING
+
#if defined(__LP64__)
#define _POSIX_V7_ILP32_OFF32 -1
#define _POSIX_V7_ILP32_OFFBIG -1
@@ -106,16 +115,26 @@
#define _POSIX_V7_LPBIG_OFFBIG -1
#endif
+#define _XOPEN_CRYPT __BIONIC_POSIX_FEATURE_MISSING
+#define _XOPEN_ENH_I18N 1
+#define _XOPEN_LEGACY __BIONIC_POSIX_FEATURE_MISSING
+#define _XOPEN_REALTIME 1
+#define _XOPEN_REALTIME_THREADS 1
+#define _XOPEN_SHM 1
+#define _XOPEN_STREAMS __BIONIC_POSIX_FEATURE_MISSING
+#define _XOPEN_UNIX 1
+
/* Minimum values for other maxima. These numbers are simply lower bounds mandated by POSIX. */
-/* Any constant values here other than -1 or 200809L are explicitly specified by POSIX.1-2008. */
+/* The constant values here are explicitly specified by POSIX, not implementation dependent. */
#define _POSIX_AIO_LISTIO_MAX 2
#define _POSIX_AIO_MAX 1
#define _POSIX_ARG_MAX 4096
#define _POSIX_CHILD_MAX 25
+#define _POSIX_CLOCKRES_MIN 20000000
#define _POSIX_DELAYTIMER_MAX 32
#define _POSIX_HOST_NAME_MAX 255
#define _POSIX_LINK_MAX 8
-#define _POSIX_LOGIN_NAME_MAX 9 /* includes trailing NUL */
+#define _POSIX_LOGIN_NAME_MAX 9
#define _POSIX_MAX_CANON 255
#define _POSIX_MAX_INPUT 255
#define _POSIX_MQ_OPEN_MAX 8
@@ -126,45 +145,36 @@
#define _POSIX_PATH_MAX 256
#define _POSIX_PIPE_BUF 512
#define _POSIX_RE_DUP_MAX 255
+#define _POSIX_RTSIG_MAX 8
#define _POSIX_SEM_NSEMS_MAX 256
#define _POSIX_SEM_VALUE_MAX 32767
#define _POSIX_SIGQUEUE_MAX 32
#define _POSIX_SSIZE_MAX 32767
#define _POSIX_STREAM_MAX 8
+#define _POSIX_SS_REPL_MAX 4
#define _POSIX_SYMLINK_MAX 255
#define _POSIX_SYMLOOP_MAX 8
#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4
#define _POSIX_THREAD_KEYS_MAX 128
#define _POSIX_THREAD_THREADS_MAX 64
#define _POSIX_TIMER_MAX 32
+#define _POSIX_TRACE_EVENT_NAME_MAX 30
#define _POSIX_TRACE_NAME_MAX 8
#define _POSIX_TRACE_SYS_MAX 8
#define _POSIX_TRACE_USER_EVENT_MAX 32
-#define _POSIX_TTY_NAME_MAX 9 /* includes trailing NUL */
+#define _POSIX_TTY_NAME_MAX 9
#define _POSIX_TZNAME_MAX 6
#define _POSIX2_BC_BASE_MAX 99
#define _POSIX2_BC_DIM_MAX 2048
#define _POSIX2_BC_SCALE_MAX 99
#define _POSIX2_BC_STRING_MAX 1000
#define _POSIX2_CHARCLASS_NAME_MAX 14
-#define _POSIX2_CHAR_TERM -1 /* not implemented */
#define _POSIX2_COLL_WEIGHTS_MAX 2
-#define _POSIX2_C_BIND _POSIX_VERSION
-#define _POSIX2_C_DEV -1 /* c dev utilities not implemented */
#define _POSIX2_EXPR_NEST_MAX 32
#define _POSIX2_LINE_MAX 2048
-#define _POSIX2_LOCALEDEF -1 /* localedef utilitiy not implemented */
-#define _POSIX2_RE_DUP_MAX _POSIX_RE_DUP_MAX
-#define _POSIX2_SW_DEV -1 /* software dev utilities not implemented */
-#define _POSIX2_UPE -1 /* user portability utilities not implemented */
-
-#define _XOPEN_ENH_I18N -1 /* we don't support internationalization in the C library */
-#define _XOPEN_CRYPT -1 /* don't support X/Open Encryption */
+#define _POSIX2_RE_DUP_MAX 255
#define _XOPEN_IOV_MAX 16
-#define _XOPEN_LEGACY -1 /* not support all */
-#define _XOPEN_REALTIME -1 /* we don't support all these functions */
-#define _XOPEN_REALTIME_THREADS -1 /* same here */
-#define _XOPEN_SHM -1
-#define _XOPEN_UNIX 1
+#define _XOPEN_NAME_MAX 255
+#define _XOPEN_PATH_MAX 1024
#endif
diff --git a/libc/include/limits.h b/libc/include/limits.h
index 4384f6f..48e7ea9 100644
--- a/libc/include/limits.h
+++ b/libc/include/limits.h
@@ -61,6 +61,7 @@
#else
# define LONG_BIT 32
#endif
+#define WORD_BIT 32
#define SCHAR_MAX 0x7f /* max value for a signed char */
#define SCHAR_MIN (-0x7f-1) /* min value for a signed char */
@@ -130,6 +131,8 @@
#define MB_LEN_MAX 4
+#define NZERO 20
+
#define IOV_MAX 1024
#define SEM_VALUE_MAX 0x3fffffff
diff --git a/libc/include/math.h b/libc/include/math.h
index 6f8b863..57ca260 100644
--- a/libc/include/math.h
+++ b/libc/include/math.h
@@ -352,30 +352,6 @@
#define MAXFLOAT ((float)3.40282346638528860e+38)
-/* Legacy cruft from before we had builtin implementations of the standard macros. */
-
-int __fpclassifyd(double __x) __attribute_const__;
-int __fpclassifyf(float __x) __attribute_const__;
-int __fpclassifyl(long double __x) __attribute_const__;
-
-int __isfinitef(float __x) __attribute_const__;
-int __isfinite(double __x) __attribute_const__;
-int __isfinitel(long double __x) __attribute_const__;
-
-int __isinff(float __x) __attribute_const__;
-int __isinfl(long double __x) __attribute_const__;
-
-int __isnanf(float __x) __attribute_const__ __INTRODUCED_IN(21);
-int __isnanl(long double __x) __attribute_const__;
-
-int __isnormal(double __x) __attribute_const__;
-int __isnormalf(float __x) __attribute_const__;
-int __isnormall(long double __x) __attribute_const__;
-
-int __signbit(double __x) __attribute_const__;
-int __signbitf(float __x) __attribute_const__;
-int __signbitl(long double __x) __attribute_const__;
-
/* BSD extensions. */
#if defined(__USE_BSD)
diff --git a/libc/include/unistd.h b/libc/include/unistd.h
index 9cfb918..c60cf80 100644
--- a/libc/include/unistd.h
+++ b/libc/include/unistd.h
@@ -98,6 +98,7 @@
int execlp(const char* __file, const char* __arg0, ...) __attribute__((__sentinel__));
int execle(const char* __path, const char* __arg0, ... /*, char* const* __envp */)
__attribute__((__sentinel__(1)));
+int fexecve(int __fd, char* const* __argv, char* const* __envp) __INTRODUCED_IN_FUTURE;
int nice(int __incr);
@@ -246,6 +247,8 @@
int getdomainname(char* __buf, size_t __buf_size) __INTRODUCED_IN(26);
int setdomainname(const char* __name, size_t __n) __INTRODUCED_IN(26);
+void swab(const void* __src, void* __dst, ssize_t __byte_count) __INTRODUCED_IN_FUTURE;
+
#if defined(__BIONIC_INCLUDE_FORTIFY_HEADERS)
#include <bits/fortify/unistd.h>
#endif
diff --git a/libc/libc.arm.map b/libc/libc.arm.map
index 3433398..981cea6 100644
--- a/libc/libc.arm.map
+++ b/libc/libc.arm.map
@@ -1325,6 +1325,7 @@
endhostent;
endnetent;
endprotoent;
+ fexecve;
getentropy;
getnetent;
getprotoent;
@@ -1368,6 +1369,7 @@
sethostent;
setnetent;
setprotoent;
+ swab;
syncfs;
} LIBC_O;
diff --git a/libc/libc.arm64.map b/libc/libc.arm64.map
index aa82b39..67fac4e 100644
--- a/libc/libc.arm64.map
+++ b/libc/libc.arm64.map
@@ -1245,6 +1245,7 @@
endhostent;
endnetent;
endprotoent;
+ fexecve;
getentropy;
getnetent;
getprotoent;
@@ -1288,6 +1289,7 @@
sethostent;
setnetent;
setprotoent;
+ swab;
syncfs;
} LIBC_O;
diff --git a/libc/libc.map.txt b/libc/libc.map.txt
index d3d8e0f..443d18c 100644
--- a/libc/libc.map.txt
+++ b/libc/libc.map.txt
@@ -1350,6 +1350,7 @@
endhostent;
endnetent;
endprotoent;
+ fexecve;
getentropy;
getnetent;
getprotoent;
@@ -1393,6 +1394,7 @@
sethostent;
setnetent;
setprotoent;
+ swab;
syncfs;
} LIBC_O;
diff --git a/libc/libc.mips.map b/libc/libc.mips.map
index 62e0737..0f5efff 100644
--- a/libc/libc.mips.map
+++ b/libc/libc.mips.map
@@ -1309,6 +1309,7 @@
endhostent;
endnetent;
endprotoent;
+ fexecve;
getentropy;
getnetent;
getprotoent;
@@ -1352,6 +1353,7 @@
sethostent;
setnetent;
setprotoent;
+ swab;
syncfs;
} LIBC_O;
diff --git a/libc/libc.mips64.map b/libc/libc.mips64.map
index aa82b39..67fac4e 100644
--- a/libc/libc.mips64.map
+++ b/libc/libc.mips64.map
@@ -1245,6 +1245,7 @@
endhostent;
endnetent;
endprotoent;
+ fexecve;
getentropy;
getnetent;
getprotoent;
@@ -1288,6 +1289,7 @@
sethostent;
setnetent;
setprotoent;
+ swab;
syncfs;
} LIBC_O;
diff --git a/libc/libc.x86.map b/libc/libc.x86.map
index 5cacee1..a802aa1 100644
--- a/libc/libc.x86.map
+++ b/libc/libc.x86.map
@@ -1307,6 +1307,7 @@
endhostent;
endnetent;
endprotoent;
+ fexecve;
getentropy;
getnetent;
getprotoent;
@@ -1350,6 +1351,7 @@
sethostent;
setnetent;
setprotoent;
+ swab;
syncfs;
} LIBC_O;
diff --git a/libc/libc.x86_64.map b/libc/libc.x86_64.map
index aa82b39..67fac4e 100644
--- a/libc/libc.x86_64.map
+++ b/libc/libc.x86_64.map
@@ -1245,6 +1245,7 @@
endhostent;
endnetent;
endprotoent;
+ fexecve;
getentropy;
getnetent;
getprotoent;
@@ -1288,6 +1289,7 @@
sethostent;
setnetent;
setprotoent;
+ swab;
syncfs;
} LIBC_O;
diff --git a/libc/private/CachedProperty.h b/libc/private/CachedProperty.h
index 417a855..84ead01 100644
--- a/libc/private/CachedProperty.h
+++ b/libc/private/CachedProperty.h
@@ -42,7 +42,9 @@
: property_name_(property_name),
prop_info_(nullptr),
cached_area_serial_(0),
- cached_property_serial_(0) {
+ cached_property_serial_(0),
+ is_read_only_(strncmp(property_name, "ro.", 3) == 0),
+ read_only_property_(nullptr) {
cached_value_[0] = '\0';
}
@@ -76,7 +78,9 @@
__system_property_read_callback(prop_info_, &CachedProperty::Callback, this);
}
}
-
+ if (is_read_only_ && read_only_property_ != nullptr) {
+ return read_only_property_;
+ }
return cached_value_;
}
@@ -86,10 +90,18 @@
uint32_t cached_area_serial_;
uint32_t cached_property_serial_;
char cached_value_[PROP_VALUE_MAX];
+ bool is_read_only_;
+ const char* read_only_property_;
static void Callback(void* data, const char*, const char* value, uint32_t serial) {
CachedProperty* instance = reinterpret_cast<CachedProperty*>(data);
instance->cached_property_serial_ = serial;
- strcpy(instance->cached_value_, value);
+ // Read only properties can be larger than PROP_VALUE_MAX, but also never change value or
+ // location, thus we return the pointer from the shared memory directly.
+ if (instance->is_read_only_) {
+ instance->read_only_property_ = value;
+ } else {
+ strlcpy(instance->cached_value_, value, PROP_VALUE_MAX);
+ }
}
};
diff --git a/libc/private/FdPath.h b/libc/private/FdPath.h
new file mode 100644
index 0000000..4a6a2d5
--- /dev/null
+++ b/libc/private/FdPath.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+class FdPath {
+ public:
+ explicit FdPath(int fd) {
+ snprintf(buf, sizeof(buf), "/proc/self/fd/%d", fd);
+ }
+
+ const char* c_str() {
+ return buf;
+ }
+
+ private:
+ char buf[40];
+};
diff --git a/libc/private/bionic_defs.h b/libc/private/bionic_defs.h
new file mode 100644
index 0000000..d9e016c
--- /dev/null
+++ b/libc/private/bionic_defs.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2017 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 __BIONIC_PRIVATE_BIONIC_DEFS_H_
+#define __BIONIC_PRIVATE_BIONIC_DEFS_H_
+
+/*
+ * This label is used to mark libc/libdl symbols that may need to be replaced
+ * by native bridge implementation.
+ */
+#define __BIONIC_WEAK_FOR_NATIVE_BRIDGE __attribute__((__weak__, __noinline__))
+
+#endif /* __BIONIC_PRIVATE_BIONIC_DEFS_H_ */
diff --git a/libc/stdio/fread.c b/libc/stdio/fread.c
index 7b858ae..b6a3077 100644
--- a/libc/stdio/fread.c
+++ b/libc/stdio/fread.c
@@ -43,6 +43,8 @@
size_t
fread(void *buf, size_t size, size_t count, FILE *fp) __overloadable
{
+ CHECK_FP(fp);
+
/*
* Extension: Catch integer overflow.
*/
diff --git a/libc/stdio/local.h b/libc/stdio/local.h
index bf6a8f8..02ea8f8 100644
--- a/libc/stdio/local.h
+++ b/libc/stdio/local.h
@@ -38,6 +38,9 @@
#include <pthread.h>
#include <stdbool.h>
#include <wchar.h>
+
+#include <async_safe/log.h>
+
#include "wcio.h"
/*
@@ -252,4 +255,13 @@
__END_DECLS
+// Sanity check a FILE* for nullptr, so we can emit a message while crashing
+// instead of doing a blind null-dereference.
+#define CHECK_FP(fp) \
+ do { \
+ if (__predict_false(fp == 0)) { \
+ async_safe_fatal("invalid FILE* %p passed to %s", fp, __FUNCTION__); \
+ } \
+ } while (0)
+
#endif
diff --git a/libc/stdio/stdio.cpp b/libc/stdio/stdio.cpp
index 4d6438b..cf97a3f 100644
--- a/libc/stdio/stdio.cpp
+++ b/libc/stdio/stdio.cpp
@@ -44,6 +44,8 @@
#include <sys/stat.h>
#include <unistd.h>
+#include <async_safe/log.h>
+
#include "local.h"
#include "glue.h"
#include "private/bionic_fortify.h"
@@ -261,6 +263,7 @@
// all possible, no matter what.
// TODO: rewrite this mess completely.
FILE* freopen(const char* file, const char* mode, FILE* fp) {
+ CHECK_FP(fp);
int mode_flags;
int flags = __sflags(mode, &mode_flags);
if (flags == 0) {
@@ -361,6 +364,7 @@
__strong_alias(freopen64, freopen);
int fclose(FILE* fp) {
+ CHECK_FP(fp);
if (fp->_flags == 0) {
// Already freed!
errno = EBADF;
@@ -387,6 +391,7 @@
}
int fileno_unlocked(FILE* fp) {
+ CHECK_FP(fp);
int fd = fp->_file;
if (fd == -1) {
errno = EBADF;
@@ -396,6 +401,7 @@
}
int fileno(FILE* fp) {
+ CHECK_FP(fp);
ScopedFileLock sfl(fp);
return fileno_unlocked(fp);
}
@@ -405,24 +411,29 @@
}
void clearerr(FILE* fp) {
+ CHECK_FP(fp);
ScopedFileLock sfl(fp);
clearerr_unlocked(fp);
}
int feof_unlocked(FILE* fp) {
+ CHECK_FP(fp);
return ((fp->_flags & __SEOF) != 0);
}
int feof(FILE* fp) {
+ CHECK_FP(fp);
ScopedFileLock sfl(fp);
return feof_unlocked(fp);
}
int ferror_unlocked(FILE* fp) {
+ CHECK_FP(fp);
return __sferror(fp);
}
int ferror(FILE* fp) {
+ CHECK_FP(fp);
ScopedFileLock sfl(fp);
return ferror_unlocked(fp);
}
@@ -533,24 +544,29 @@
}
int fseeko(FILE* fp, off_t offset, int whence) {
+ CHECK_FP(fp);
static_assert(sizeof(off_t) == sizeof(long), "sizeof(off_t) != sizeof(long)");
return __fseeko64(fp, offset, whence, 8*sizeof(off_t));
}
__strong_alias(fseek, fseeko);
int fseeko64(FILE* fp, off64_t offset, int whence) {
+ CHECK_FP(fp);
return __fseeko64(fp, offset, whence, 8*sizeof(off_t));
}
int fsetpos(FILE* fp, const fpos_t* pos) {
+ CHECK_FP(fp);
return fseeko(fp, *pos, SEEK_SET);
}
int fsetpos64(FILE* fp, const fpos64_t* pos) {
+ CHECK_FP(fp);
return fseeko64(fp, *pos, SEEK_SET);
}
off_t ftello(FILE* fp) {
+ CHECK_FP(fp);
static_assert(sizeof(off_t) == sizeof(long), "sizeof(off_t) != sizeof(long)");
off64_t result = ftello64(fp);
if (result > LONG_MAX) {
@@ -562,16 +578,19 @@
__strong_alias(ftell, ftello);
off64_t ftello64(FILE* fp) {
+ CHECK_FP(fp);
ScopedFileLock sfl(fp);
return __ftello64_unlocked(fp);
}
int fgetpos(FILE* fp, fpos_t* pos) {
+ CHECK_FP(fp);
*pos = ftello(fp);
return (*pos == -1) ? -1 : 0;
}
int fgetpos64(FILE* fp, fpos64_t* pos) {
+ CHECK_FP(fp);
*pos = ftello64(fp);
return (*pos == -1) ? -1 : 0;
}
@@ -642,35 +661,43 @@
}
int fprintf(FILE* fp, const char* fmt, ...) {
+ CHECK_FP(fp);
PRINTF_IMPL(vfprintf(fp, fmt, ap));
}
int fgetc(FILE* fp) {
+ CHECK_FP(fp);
return getc(fp);
}
int fputc(int c, FILE* fp) {
+ CHECK_FP(fp);
return putc(c, fp);
}
int fscanf(FILE* fp, const char* fmt, ...) {
+ CHECK_FP(fp);
PRINTF_IMPL(vfscanf(fp, fmt, ap));
}
int fwprintf(FILE* fp, const wchar_t* fmt, ...) {
+ CHECK_FP(fp);
PRINTF_IMPL(vfwprintf(fp, fmt, ap));
}
int fwscanf(FILE* fp, const wchar_t* fmt, ...) {
+ CHECK_FP(fp);
PRINTF_IMPL(vfwscanf(fp, fmt, ap));
}
int getc(FILE* fp) {
+ CHECK_FP(fp);
ScopedFileLock sfl(fp);
return getc_unlocked(fp);
}
int getc_unlocked(FILE* fp) {
+ CHECK_FP(fp);
return __sgetc(fp);
}
@@ -683,10 +710,12 @@
}
ssize_t getline(char** buf, size_t* len, FILE* fp) {
+ CHECK_FP(fp);
return getdelim(buf, len, '\n', fp);
}
wint_t getwc(FILE* fp) {
+ CHECK_FP(fp);
return fgetwc(fp);
}
@@ -699,11 +728,13 @@
}
int putc(int c, FILE* fp) {
+ CHECK_FP(fp);
ScopedFileLock sfl(fp);
return putc_unlocked(c, fp);
}
int putc_unlocked(int c, FILE* fp) {
+ CHECK_FP(fp);
if (cantwrite(fp)) {
errno = EBADF;
return EOF;
@@ -724,6 +755,7 @@
}
wint_t putwc(wchar_t wc, FILE* fp) {
+ CHECK_FP(fp);
return fputwc(wc, fp);
}
@@ -738,6 +770,7 @@
}
void rewind(FILE* fp) {
+ CHECK_FP(fp);
ScopedFileLock sfl(fp);
fseek(fp, 0, SEEK_SET);
clearerr_unlocked(fp);
@@ -748,14 +781,17 @@
}
void setbuf(FILE* fp, char* buf) {
+ CHECK_FP(fp);
setbuffer(fp, buf, BUFSIZ);
}
void setbuffer(FILE* fp, char* buf, int size) {
+ CHECK_FP(fp);
setvbuf(fp, buf, buf ? _IOFBF : _IONBF, size);
}
int setlinebuf(FILE* fp) {
+ CHECK_FP(fp);
return setvbuf(fp, nullptr, _IOLBF, 0);
}
diff --git a/libc/tools/check-symbols-glibc.py b/libc/tools/check-symbols-glibc.py
index 7657925..4de0181 100755
--- a/libc/tools/check-symbols-glibc.py
+++ b/libc/tools/check-symbols-glibc.py
@@ -184,20 +184,24 @@
])
# POSIX has some stuff that's too stupid for words (a64l) or not actually
# implemented in glibc unless you count always failing with ENOSYS as
-# being implemented (fattach).
+# being implemented (fattach). Other stuff (fmtmsg) isn't used in any
+# codebase I have access to, internal or external.
in_posix_and_glibc_but_dead_or_useless = set([
'a64l', # obsolete
'confstr', # obsolete
'endutxent', # no utmp on Android
- 'fattach', # obsolete
- 'fdetach', # obsolete
+ 'fattach', # <stropts.h> marked obsolescent
+ 'fdetach', # <stropts.h> marked obsolescent
+ 'fmtmsg', # unused
+ 'getdate', # unused
+ 'getdate_err', # unused
'gethostid', # obsolete
- 'getmsg', # obsolete
- 'getpmsg', # obsolete
+ 'getmsg', # <stropts.h> marked obsolescent
+ 'getpmsg', # <stropts.h> marked obsolescent
'getutxent', # no utmp on Android
'getutxid', # no utmp on Android
'getutxline', # no utmp on Android
- 'isastream', # obsolete
+ 'isastream', # <stropts.h> marked obsolescent
'l64a', # obsolete
'mq_close', # disallowed by SELinux
'mq_getattr', # disallowed by SELinux
@@ -211,15 +215,16 @@
'mq_unlink', # disallowed by SELinux
'pthread_getconcurrency', # marked obsolescent
'pthread_setconcurrency', # marked obsolescent
- 'putmsg', # obsolete
- 'putpmsg', # obsolete
+ 'putmsg', # <stropts.h> marked obsolescent
+ 'putpmsg', # <stropts.h> marked obsolescent
'pututxline', # no utmp on Android
'shm_open', # disallowed by SELinux
'shm_unlink', # disallowed by SELinux
'setutxent', # no utmp on Android
+ 'sockatmark', # obsolete (https://tools.ietf.org/html/rfc6093)
'strfmon', # icu4c
'strfmon_l', # icu4c
- 'ulimit', # obsolete
+ 'ulimit', # <ulimit.h> marked obsolescent
])
posix = posix - in_posix_and_glibc_but_dead_or_useless
diff --git a/libdl/Android.bp b/libdl/Android.bp
index b0bbe99..44daaec 100644
--- a/libdl/Android.bp
+++ b/libdl/Android.bp
@@ -4,7 +4,7 @@
cc_library_static {
name: "libdl_static",
- srcs: ["libdl.c", "libdl_cfi.cpp"],
+ srcs: ["libdl.cpp", "libdl_cfi.cpp"],
cflags: [
"-Wall",
diff --git a/libdl/libdl.c b/libdl/libdl.cpp
similarity index 98%
rename from libdl/libdl.c
rename to libdl/libdl.cpp
index b747c22..c834088 100644
--- a/libdl/libdl.c
+++ b/libdl/libdl.cpp
@@ -17,17 +17,18 @@
#include <dlfcn.h>
#include <link.h>
#include <stdlib.h>
-#include <stdbool.h>
#include <android/dlext.h>
// These functions are exported by the loader
// TODO(dimitry): replace these with reference to libc.so
+extern "C" {
+
__attribute__((__weak__, visibility("default")))
void* __loader_dlopen(const char* filename, int flags, const void* caller_addr);
__attribute__((__weak__, visibility("default")))
-void* __loader_dlerror();
+char* __loader_dlerror();
__attribute__((__weak__, visibility("default")))
void* __loader_dlsym(void* handle, const char* symbol, const void* caller_addr);
@@ -212,3 +213,5 @@
struct android_namespace_t* android_get_exported_namespace(const char* name) {
return __loader_android_get_exported_namespace(name);
}
+
+} // extern "C"
diff --git a/libm/Android.bp b/libm/Android.bp
index bf86264..da9c9a8 100644
--- a/libm/Android.bp
+++ b/libm/Android.bp
@@ -210,11 +210,9 @@
"sincos.c",
"fake_long_double.c",
- // Modified versions of BSD code.
- "signbit.c",
-
// Home-grown stuff.
"fabs.cpp",
+ "signbit.cpp",
],
multilib: {
diff --git a/libm/signbit.c b/libm/signbit.c
deleted file mode 100644
index b98bf45..0000000
--- a/libm/signbit.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/*-
- * Copyright (c) 2003 Mike Barcroft <mike@FreeBSD.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. 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 AUTHOR 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 AUTHOR 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.
- *
- * $FreeBSD$
- */
-
-#include <math.h>
-
-#include "fpmath.h"
-
-int __signbit(double d)
-{
- union IEEEd2bits u;
-
- u.d = d;
- return (u.bits.sign);
-}
-
-int __signbitf(float f)
-{
- union IEEEf2bits u;
-
- u.f = f;
- return (u.bits.sign);
-}
-
-#ifdef __LP64__
-int __signbitl(long double e)
-{
- union IEEEl2bits u;
-
- u.e = e;
- return (u.bits.sign);
-}
-#else // __LP32__
-__weak_reference(__signbit, __signbitl);
-#endif // __LP64__
diff --git a/libm/signbit.cpp b/libm/signbit.cpp
new file mode 100644
index 0000000..b2a5d60
--- /dev/null
+++ b/libm/signbit.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#include <math.h>
+
+// Legacy cruft from before we had builtin implementations of the standard macros.
+// No longer declared in our <math.h>.
+
+extern "C" int __signbit(double d) {
+ return signbit(d);
+}
+
+extern "C" int __signbitf(float f) {
+ return signbit(f);
+}
+
+extern "C" int __signbitl(long double ld) {
+ return signbit(ld);
+}
diff --git a/linker/linker.cpp b/linker/linker.cpp
index f6ca430..5f906c8 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -1433,6 +1433,8 @@
if (search_linked_namespaces) {
// if a library was not found - look into linked namespaces
+ // preserve current dlerror in the case it fails.
+ DlErrorRestorer dlerror_restorer;
for (auto& linked_namespace : ns->linked_namespaces()) {
if (find_library_in_linked_namespace(linked_namespace,
task)) {
@@ -1621,11 +1623,13 @@
}
// Step 4-3: Add the new global group members to all the linked namespaces
- for (auto si : new_global_group_members) {
+ if (namespaces != nullptr) {
for (auto linked_ns : *namespaces) {
- if (si->get_primary_namespace() != linked_ns) {
- linked_ns->add_soinfo(si);
- si->add_secondary_namespace(linked_ns);
+ for (auto si : new_global_group_members) {
+ if (si->get_primary_namespace() != linked_ns) {
+ linked_ns->add_soinfo(si);
+ si->add_secondary_namespace(linked_ns);
+ }
}
}
}
diff --git a/linker/linker_config.cpp b/linker/linker_config.cpp
index e036c05..f7d2c53 100644
--- a/linker/linker_config.cpp
+++ b/linker/linker_config.cpp
@@ -43,6 +43,9 @@
#include <string>
#include <unordered_map>
+#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
+#include <sys/_system_properties.h>
+
class ConfigParser {
public:
enum {
@@ -275,6 +278,15 @@
return true;
}
+static std::string getVndkVersionString() {
+ char vndk_version_str[1 + PROP_VALUE_MAX] = {};
+ __system_property_get("ro.vndk.version", vndk_version_str + 1);
+ if (strlen(vndk_version_str + 1) != 0 && strcmp(vndk_version_str + 1, "current") != 0) {
+ vndk_version_str[0] = '-';
+ }
+ return vndk_version_str;
+}
+
static Config g_config;
static constexpr const char* kDefaultConfigName = "default";
@@ -334,6 +346,9 @@
params.push_back({ "SDK_VER", buf });
}
+ static std::string vndk = getVndkVersionString();
+ params.push_back({ "VNDK_VER", vndk });
+
for (auto&& path : paths) {
format_string(&path, params);
}
diff --git a/linker/linker_globals.h b/linker/linker_globals.h
index d8134af..11ccbd5 100644
--- a/linker/linker_globals.h
+++ b/linker/linker_globals.h
@@ -32,6 +32,7 @@
#include <link.h>
#include <stddef.h>
+#include <string>
#include <unordered_map>
#include <async_safe/log.h>
@@ -39,7 +40,6 @@
#define DL_ERR(fmt, x...) \
do { \
async_safe_format_buffer(linker_get_error_buffer(), linker_get_error_buffer_size(), fmt, ##x); \
- /* If LD_DEBUG is set high enough, log every dlerror(3) message. */ \
} while (false)
#define DL_WARN(fmt, x...) \
@@ -75,4 +75,16 @@
char* linker_get_error_buffer();
size_t linker_get_error_buffer_size();
+class DlErrorRestorer {
+ public:
+ DlErrorRestorer() {
+ saved_error_msg_ = linker_get_error_buffer();
+ }
+ ~DlErrorRestorer() {
+ strlcpy(linker_get_error_buffer(), saved_error_msg_.c_str(), linker_get_error_buffer_size());
+ }
+ private:
+ std::string saved_error_msg_;
+};
+
#endif /* __LINKER_GLOBALS_H */
diff --git a/linker/linker_main.cpp b/linker/linker_main.cpp
index 4799739..317f0d2 100644
--- a/linker/linker_main.cpp
+++ b/linker/linker_main.cpp
@@ -129,9 +129,9 @@
if (path != nullptr) {
// We have historically supported ':' as well as ' ' in LD_PRELOAD.
g_ld_preload_names = android::base::Split(path, " :");
- std::remove_if(g_ld_preload_names.begin(),
- g_ld_preload_names.end(),
- [] (const std::string& s) { return s.empty(); });
+ g_ld_preload_names.erase(std::remove_if(g_ld_preload_names.begin(), g_ld_preload_names.end(),
+ [](const std::string& s) { return s.empty(); }),
+ g_ld_preload_names.end());
}
}
diff --git a/tests/dl_test.cpp b/tests/dl_test.cpp
index 2133a2c..d56b017 100644
--- a/tests/dl_test.cpp
+++ b/tests/dl_test.cpp
@@ -181,12 +181,8 @@
#endif
#if defined(__BIONIC__)
-static bool is_user_build() {
- std::string build_type = android::base::GetProperty("ro.build.type", "user");
- if (build_type == "userdebug" || build_type == "eng") {
- return false;
- }
- return true;
+static bool is_debuggable_build() {
+ return android::base::GetBoolProperty("ro.debuggable", false);
}
#endif
@@ -194,7 +190,7 @@
// whose search paths include the 'ns2/' subdir.
TEST(dl, exec_with_ld_config_file) {
#if defined(__BIONIC__)
- if (is_user_build()) {
+ if (!is_debuggable_build()) {
// LD_CONFIG_FILE is not supported on user build
return;
}
@@ -216,7 +212,7 @@
// additional namespaces other than the default namespace.
TEST(dl, exec_with_ld_config_file_with_ld_preload) {
#if defined(__BIONIC__)
- if (is_user_build()) {
+ if (!is_debuggable_build()) {
// LD_CONFIG_FILE is not supported on user build
return;
}
@@ -244,7 +240,7 @@
// This test is only for CTS.
return;
}
- if (!is_user_build()) {
+ if (is_debuggable_build()) {
// Skip the test for non production devices
return;
}
diff --git a/tests/dlext_test.cpp b/tests/dlext_test.cpp
index 7028ca7..3f6da59 100644
--- a/tests/dlext_test.cpp
+++ b/tests/dlext_test.cpp
@@ -1589,6 +1589,54 @@
ASSERT_STREQ("dlopen failed: library \"libnstest_public.so\" not found", dlerror());
}
+TEST(dlext, ns_inaccessible_error_message) {
+ // We set up 2 namespaces (a and b) and link a->b with a shared library
+ // libtestshared.so. Then try to dlopen different library with the same
+ // name from in namespace a. Note that library should not be accessible
+ // in either namespace but since it's soname is in the list of shared libs
+ // the linker will attempt to find it in linked namespace.
+ //
+ // Check the error message and make sure it mentions correct namespace name.
+ ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
+
+ android_namespace_t* ns_a =
+ android_create_namespace("ns_a",
+ nullptr,
+ (get_testlib_root() + "/private_namespace_libs").c_str(),
+ ANDROID_NAMESPACE_TYPE_ISOLATED,
+ nullptr,
+ nullptr);
+ ASSERT_TRUE(ns_a != nullptr) << dlerror();
+ ASSERT_TRUE(android_link_namespaces(ns_a, nullptr, g_core_shared_libs.c_str())) << dlerror();
+
+ android_namespace_t* ns_b =
+ android_create_namespace("ns_b",
+ nullptr,
+ get_testlib_root().c_str(),
+ ANDROID_NAMESPACE_TYPE_ISOLATED,
+ nullptr,
+ nullptr);
+ ASSERT_TRUE(ns_b != nullptr) << dlerror();
+ ASSERT_TRUE(android_link_namespaces(ns_b, nullptr, g_core_shared_libs.c_str())) << dlerror();
+
+ ASSERT_TRUE(android_link_namespaces(ns_a, ns_b, "libtestshared.so")) << dlerror();
+
+ android_dlextinfo extinfo;
+ extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
+ extinfo.library_namespace = ns_a;
+
+ std::string library_path = get_testlib_root() + "/inaccessible_libs/libtestshared.so";
+
+ void* handle = android_dlopen_ext(library_path.c_str(), RTLD_NOW, &extinfo);
+ ASSERT_TRUE(handle == nullptr);
+ std::string expected_dlerror =
+ android::base::StringPrintf("dlopen failed: library \"%s\" needed or dlopened by \"%s\""
+ " is not accessible for the namespace \"ns_a\"",
+ library_path.c_str(),
+ get_executable_path().c_str());
+ ASSERT_EQ(expected_dlerror, dlerror());
+}
+
TEST(dlext, ns_anonymous) {
static const char* root_lib = "libnstest_root.so";
std::string shared_libs = g_core_shared_libs + ":" + g_public_lib;
diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp
index adc5ee4..697b84a 100644
--- a/tests/dlfcn_test.cpp
+++ b/tests/dlfcn_test.cpp
@@ -1496,4 +1496,9 @@
ASSERT_SUBSTR(expected_dlerror.c_str(), dlerror());
}
+TEST(dlfcn, dlopen_df_1_global) {
+ void* handle = dlopen("libtest_dlopen_df_1_global.so", RTLD_NOW);
+ ASSERT_TRUE(handle != nullptr) << dlerror();
+}
+
#endif
diff --git a/tests/fcntl_test.cpp b/tests/fcntl_test.cpp
index cb00c3a..0a83dff 100644
--- a/tests/fcntl_test.cpp
+++ b/tests/fcntl_test.cpp
@@ -319,6 +319,9 @@
ASSERT_EQ(0, fstat(fd, &sb));
ASSERT_EQ(perms, (sb.st_mode & ~S_IFMT));
+ // On Android if we're not root, we won't be able to create links anyway...
+ if (getuid() != 0) return;
+
std::string final_path = android::base::StringPrintf("%s/named_now", dir.dirname);
ASSERT_EQ(0, linkat(AT_FDCWD, android::base::StringPrintf("/proc/self/fd/%d", fd).c_str(),
AT_FDCWD, final_path.c_str(),
diff --git a/tests/libs/Android.bp b/tests/libs/Android.bp
index 858f2b1..5f27387 100644
--- a/tests/libs/Android.bp
+++ b/tests/libs/Android.bp
@@ -377,6 +377,26 @@
}
// -----------------------------------------------------------------------------
+// Library with DF_1_GLOBAL which will be dlopened
+// (note: libdl_test_df_1_global above will be included in DT_NEEDED)
+// -----------------------------------------------------------------------------
+cc_test_library {
+ name: "libtest_dlopen_df_1_global",
+ defaults: ["bionic_testlib_defaults"],
+ srcs: ["dl_df_1_global_dummy.cpp"],
+ ldflags: ["-Wl,-z,global"],
+
+ target: {
+ host: {
+ // TODO (dimitry): host ld.gold does not yet support -z global
+ // remove this line once it is updated.
+ ldflags: ["-fuse-ld=bfd"],
+ },
+ },
+}
+
+
+// -----------------------------------------------------------------------------
// Library with weak function
// -----------------------------------------------------------------------------
cc_test_library {
@@ -420,6 +440,16 @@
}
// -----------------------------------------------------------------------------
+// Library for inaccessible shared library test
+// -----------------------------------------------------------------------------
+cc_test_library {
+ name: "libtestshared",
+ defaults: ["bionic_testlib_defaults"],
+ srcs: ["empty.cpp"],
+ relative_install_path: "/inaccessible_libs",
+}
+
+// -----------------------------------------------------------------------------
// Library with weak undefined function
// -----------------------------------------------------------------------------
cc_test_library {
diff --git a/tests/libs/dl_df_1_global_dummy.cpp b/tests/libs/dl_df_1_global_dummy.cpp
new file mode 100644
index 0000000..423247c
--- /dev/null
+++ b/tests/libs/dl_df_1_global_dummy.cpp
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+extern "C" int foo() {
+ return 1;
+}
diff --git a/tests/limits_test.cpp b/tests/limits_test.cpp
index 1d48ffe..e5902ad 100644
--- a/tests/limits_test.cpp
+++ b/tests/limits_test.cpp
@@ -19,9 +19,9 @@
#include <limits.h>
TEST(limits, macros) {
-#if CHAR_BIT != 8
-#error Insane CHAR_BIT
-#endif
+ ASSERT_EQ(8, CHAR_BIT);
+ ASSERT_EQ(8 * static_cast<int>(sizeof(int)), WORD_BIT);
+ ASSERT_EQ(20, NZERO);
#if !defined(MB_LEN_MAX)
#error MB_LEN_MAX
#endif
diff --git a/tests/linux_swab_test.cpp b/tests/linux_swab_test.cpp
index 6b964dc..ffd4072 100644
--- a/tests/linux_swab_test.cpp
+++ b/tests/linux_swab_test.cpp
@@ -21,7 +21,7 @@
// This test makes sure that references to all of the kernel swab
// macros/inline functions that are exported work properly.
// Verifies that any kernel header updates do not break these macros.
-TEST(swab, fswa) {
+TEST(linux_swab, smoke) {
EXPECT_EQ(0x3412U, __swab16(0x1234));
EXPECT_EQ(0x78563412U, __swab32(0x12345678U));
EXPECT_EQ(0xbaefcdab78563412ULL, __swab64(0x12345678abcdefbaULL));
diff --git a/tests/math_test.cpp b/tests/math_test.cpp
index 0fc4e50..466e697 100644
--- a/tests/math_test.cpp
+++ b/tests/math_test.cpp
@@ -176,6 +176,11 @@
ASSERT_NE(0, test_capture_signbit(-1.0L));
}
+// Historical BSD cruft that isn't exposed in <math.h> any more.
+extern "C" int __fpclassifyd(double);
+extern "C" int __fpclassifyf(float);
+extern "C" int __fpclassifyl(long double);
+
TEST(MATH_TEST, __fpclassifyd) {
#if defined(__GLIBC__)
#define __fpclassifyd __fpclassify
@@ -208,6 +213,11 @@
ASSERT_FALSE(finitef(HUGE_VALF));
}
+// Historical BSD cruft that isn't exposed in <math.h> any more.
+extern "C" int __isfinite(double);
+extern "C" int __isfinitef(float);
+extern "C" int __isfinitel(long double);
+
TEST(MATH_TEST, __isfinite) {
#if defined(__GLIBC__)
#define __isfinite __finite
@@ -243,6 +253,10 @@
ASSERT_TRUE((isinf)(HUGE_VAL));
}
+// Historical BSD cruft that isn't exposed in <math.h> any more.
+extern "C" int __isinff(float);
+extern "C" int __isinfl(long double);
+
TEST(MATH_TEST, __isinff) {
ASSERT_FALSE(__isinff(123.0f));
ASSERT_TRUE(__isinff(HUGE_VALF));
@@ -259,6 +273,10 @@
ASSERT_TRUE((isnan)(nan("")));
}
+// Historical BSD cruft that isn't exposed in <math.h> any more.
+extern "C" int __isnanf(float);
+extern "C" int __isnanl(long double);
+
TEST(MATH_TEST, __isnanf) {
ASSERT_FALSE(__isnanf(123.0f));
ASSERT_TRUE(__isnanf(nanf("")));
@@ -274,6 +292,11 @@
ASSERT_TRUE(isnanf(nanf("")));
}
+// Historical BSD cruft that isn't exposed in <math.h> any more.
+extern "C" int __isnormal(double);
+extern "C" int __isnormalf(float);
+extern "C" int __isnormall(long double);
+
TEST(MATH_TEST, __isnormal) {
#if defined(__BIONIC__)
ASSERT_TRUE(__isnormal(123.0));
@@ -301,6 +324,11 @@
#endif // __BIONIC__
}
+// Historical BSD cruft that isn't exposed in <math.h> any more.
+extern "C" int __signbit(double);
+extern "C" int __signbitf(float);
+extern "C" int __signbitl(long double);
+
TEST(MATH_TEST, __signbit) {
ASSERT_EQ(0, __signbit(0.0));
ASSERT_EQ(0, __signbit(1.0));
diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp
index ced0315..456ddde 100644
--- a/tests/unistd_test.cpp
+++ b/tests/unistd_test.cpp
@@ -686,104 +686,131 @@
ASSERT_TRUE(rc > 0 && powerof2(rc));
}
-
-TEST(UNISTD_TEST, _POSIX_macros_smoke) {
+TEST(UNISTD_TEST, _POSIX_constants) {
// Make a tight verification of _POSIX_* / _POSIX2_* / _XOPEN_* macros, to prevent change by mistake.
// Verify according to POSIX.1-2008.
EXPECT_EQ(200809L, _POSIX_VERSION);
+ EXPECT_EQ(2, _POSIX_AIO_LISTIO_MAX);
+ EXPECT_EQ(1, _POSIX_AIO_MAX);
+ EXPECT_EQ(4096, _POSIX_ARG_MAX);
+ EXPECT_EQ(25, _POSIX_CHILD_MAX);
+ EXPECT_EQ(20000000, _POSIX_CLOCKRES_MIN);
+ EXPECT_EQ(32, _POSIX_DELAYTIMER_MAX);
+ EXPECT_EQ(255, _POSIX_HOST_NAME_MAX);
+ EXPECT_EQ(8, _POSIX_LINK_MAX);
+ EXPECT_EQ(9, _POSIX_LOGIN_NAME_MAX);
+ EXPECT_EQ(255, _POSIX_MAX_CANON);
+ EXPECT_EQ(255, _POSIX_MAX_INPUT);
+ EXPECT_EQ(8, _POSIX_MQ_OPEN_MAX);
+ EXPECT_EQ(32, _POSIX_MQ_PRIO_MAX);
+ EXPECT_EQ(14, _POSIX_NAME_MAX);
+ EXPECT_EQ(8, _POSIX_NGROUPS_MAX);
+ EXPECT_EQ(20, _POSIX_OPEN_MAX);
+ EXPECT_EQ(256, _POSIX_PATH_MAX);
+ EXPECT_EQ(512, _POSIX_PIPE_BUF);
+ EXPECT_EQ(255, _POSIX_RE_DUP_MAX);
+ EXPECT_EQ(8, _POSIX_RTSIG_MAX);
+ EXPECT_EQ(256, _POSIX_SEM_NSEMS_MAX);
+ EXPECT_EQ(32767, _POSIX_SEM_VALUE_MAX);
+ EXPECT_EQ(32, _POSIX_SIGQUEUE_MAX);
+ EXPECT_EQ(32767, _POSIX_SSIZE_MAX);
+ EXPECT_EQ(8, _POSIX_STREAM_MAX);
+#if !defined(__GLIBC__)
+ EXPECT_EQ(4, _POSIX_SS_REPL_MAX);
+#endif
+ EXPECT_EQ(255, _POSIX_SYMLINK_MAX);
+ EXPECT_EQ(8, _POSIX_SYMLOOP_MAX);
+ EXPECT_EQ(4, _POSIX_THREAD_DESTRUCTOR_ITERATIONS);
+ EXPECT_EQ(128, _POSIX_THREAD_KEYS_MAX);
+ EXPECT_EQ(64, _POSIX_THREAD_THREADS_MAX);
+ EXPECT_EQ(32, _POSIX_TIMER_MAX);
+#if !defined(__GLIBC__)
+ EXPECT_EQ(30, _POSIX_TRACE_EVENT_NAME_MAX);
+ EXPECT_EQ(8, _POSIX_TRACE_NAME_MAX);
+ EXPECT_EQ(8, _POSIX_TRACE_SYS_MAX);
+ EXPECT_EQ(32, _POSIX_TRACE_USER_EVENT_MAX);
+#endif
+ EXPECT_EQ(9, _POSIX_TTY_NAME_MAX);
+ EXPECT_EQ(6, _POSIX_TZNAME_MAX);
+ EXPECT_EQ(99, _POSIX2_BC_BASE_MAX);
+ EXPECT_EQ(2048, _POSIX2_BC_DIM_MAX);
+ EXPECT_EQ(99, _POSIX2_BC_SCALE_MAX);
+ EXPECT_EQ(1000, _POSIX2_BC_STRING_MAX);
+ EXPECT_EQ(14, _POSIX2_CHARCLASS_NAME_MAX);
+ EXPECT_EQ(2, _POSIX2_COLL_WEIGHTS_MAX);
+ EXPECT_EQ(32, _POSIX2_EXPR_NEST_MAX);
+ EXPECT_EQ(2048, _POSIX2_LINE_MAX);
+ EXPECT_EQ(255, _POSIX2_RE_DUP_MAX);
+
+ EXPECT_EQ(16, _XOPEN_IOV_MAX);
+#if !defined(__GLIBC__)
+ EXPECT_EQ(255, _XOPEN_NAME_MAX);
+ EXPECT_EQ(1024, _XOPEN_PATH_MAX);
+#endif
+}
+
+TEST(UNISTD_TEST, _POSIX_options) {
EXPECT_EQ(_POSIX_VERSION, _POSIX_ADVISORY_INFO);
- EXPECT_GT(_POSIX_AIO_LISTIO_MAX, 0);
- EXPECT_GT(_POSIX_AIO_MAX, 0);
- EXPECT_GT(_POSIX_ARG_MAX, 0);
EXPECT_GT(_POSIX_BARRIERS, 0);
EXPECT_GT(_POSIX_SPIN_LOCKS, 0);
- EXPECT_GT(_POSIX_CHILD_MAX, 0);
EXPECT_NE(_POSIX_CHOWN_RESTRICTED, -1);
EXPECT_EQ(_POSIX_VERSION, _POSIX_CLOCK_SELECTION);
+#if !defined(__GLIBC__) // glibc supports ancient kernels.
EXPECT_EQ(_POSIX_VERSION, _POSIX_CPUTIME);
- EXPECT_GT(_POSIX_DELAYTIMER_MAX, 0);
+#endif
EXPECT_EQ(_POSIX_VERSION, _POSIX_FSYNC);
- EXPECT_GT(_POSIX_HOST_NAME_MAX, 0);
EXPECT_EQ(_POSIX_VERSION, _POSIX_IPV6);
EXPECT_GT(_POSIX_JOB_CONTROL, 0);
- EXPECT_GT(_POSIX_LINK_MAX, 0);
- EXPECT_GT(_POSIX_LOGIN_NAME_MAX, 0);
EXPECT_EQ(_POSIX_VERSION, _POSIX_MAPPED_FILES);
- EXPECT_GT(_POSIX_MAX_CANON, 0);
- EXPECT_GT(_POSIX_MAX_INPUT, 0);
EXPECT_EQ(_POSIX_VERSION, _POSIX_MEMLOCK);
EXPECT_EQ(_POSIX_VERSION, _POSIX_MEMLOCK_RANGE);
EXPECT_EQ(_POSIX_VERSION, _POSIX_MEMORY_PROTECTION);
+#if !defined(__GLIBC__) // glibc supports ancient kernels.
EXPECT_EQ(_POSIX_VERSION, _POSIX_MONOTONIC_CLOCK);
- EXPECT_GT(_POSIX_MQ_OPEN_MAX, 0);
- EXPECT_GT(_POSIX_MQ_PRIO_MAX, 0);
- EXPECT_GT(_POSIX_NAME_MAX, 0);
- EXPECT_GT(_POSIX_NGROUPS_MAX, 0);
+#endif
EXPECT_GT(_POSIX_NO_TRUNC, 0);
- EXPECT_GT(_POSIX_OPEN_MAX, 0);
- EXPECT_GT(_POSIX_PATH_MAX, 0);
- EXPECT_GT(_POSIX_PIPE_BUF, 0);
EXPECT_EQ(_POSIX_VERSION, _POSIX_PRIORITY_SCHEDULING);
EXPECT_EQ(_POSIX_VERSION, _POSIX_RAW_SOCKETS);
EXPECT_EQ(_POSIX_VERSION, _POSIX_READER_WRITER_LOCKS);
EXPECT_EQ(_POSIX_VERSION, _POSIX_REALTIME_SIGNALS);
EXPECT_GT(_POSIX_REGEXP, 0);
- EXPECT_GT(_POSIX_RE_DUP_MAX, 0);
EXPECT_GT(_POSIX_SAVED_IDS, 0);
EXPECT_EQ(_POSIX_VERSION, _POSIX_SEMAPHORES);
- EXPECT_GT(_POSIX_SEM_NSEMS_MAX, 0);
- EXPECT_GT(_POSIX_SEM_VALUE_MAX, 0);
EXPECT_GT(_POSIX_SHELL, 0);
- EXPECT_GT(_POSIX_SIGQUEUE_MAX, 0);
EXPECT_EQ(_POSIX_VERSION, _POSIX_SPAWN);
- EXPECT_EQ(_POSIX_VERSION, _POSIX_SPORADIC_SERVER);
- EXPECT_GT(_POSIX_SSIZE_MAX, 0);
- EXPECT_GT(_POSIX_STREAM_MAX, 0);
- EXPECT_GT(_POSIX_SYMLINK_MAX, 0);
- EXPECT_GT(_POSIX_SYMLOOP_MAX, 0);
+ EXPECT_EQ(-1, _POSIX_SPORADIC_SERVER);
EXPECT_EQ(_POSIX_VERSION, _POSIX_SYNCHRONIZED_IO);
EXPECT_EQ(_POSIX_VERSION, _POSIX_THREADS);
EXPECT_EQ(_POSIX_VERSION, _POSIX_THREAD_ATTR_STACKADDR);
EXPECT_EQ(_POSIX_VERSION, _POSIX_THREAD_ATTR_STACKSIZE);
+#if !defined(__GLIBC__) // glibc supports ancient kernels.
EXPECT_EQ(_POSIX_VERSION, _POSIX_THREAD_CPUTIME);
- EXPECT_GT(_POSIX_THREAD_DESTRUCTOR_ITERATIONS, 0);
- EXPECT_EQ(_POSIX_THREAD_KEYS_MAX, 128);
+#endif
EXPECT_EQ(_POSIX_VERSION, _POSIX_THREAD_PRIORITY_SCHEDULING);
- EXPECT_EQ(-1, _POSIX_THREAD_PRIO_INHERIT);
- EXPECT_EQ(-1, _POSIX_THREAD_PRIO_PROTECT);
EXPECT_EQ(_POSIX_VERSION, _POSIX_THREAD_PROCESS_SHARED);
EXPECT_EQ(-1, _POSIX_THREAD_ROBUST_PRIO_PROTECT);
EXPECT_EQ(_POSIX_VERSION, _POSIX_THREAD_SAFE_FUNCTIONS);
- EXPECT_EQ(_POSIX_VERSION, _POSIX_THREAD_SPORADIC_SERVER);
- EXPECT_GT(_POSIX_THREAD_THREADS_MAX, 0);
+ EXPECT_EQ(-1, _POSIX_THREAD_SPORADIC_SERVER);
EXPECT_EQ(_POSIX_VERSION, _POSIX_TIMEOUTS);
EXPECT_EQ(_POSIX_VERSION, _POSIX_TIMERS);
- EXPECT_GT(_POSIX_TIMER_MAX, 0);
EXPECT_EQ(-1, _POSIX_TRACE);
EXPECT_EQ(-1, _POSIX_TRACE_EVENT_FILTER);
EXPECT_EQ(-1, _POSIX_TRACE_INHERIT);
EXPECT_EQ(-1, _POSIX_TRACE_LOG);
- EXPECT_GT(_POSIX_TTY_NAME_MAX, 0);
EXPECT_EQ(-1, _POSIX_TYPED_MEMORY_OBJECTS);
- EXPECT_GT(_POSIX_TZNAME_MAX, 0);
EXPECT_NE(-1, _POSIX_VDISABLE);
EXPECT_EQ(_POSIX_VERSION, _POSIX2_VERSION);
- EXPECT_GT(_POSIX2_BC_BASE_MAX, 0);
- EXPECT_GT(_POSIX2_BC_DIM_MAX, 0);
- EXPECT_GT(_POSIX2_BC_SCALE_MAX, 0);
- EXPECT_GT(_POSIX2_BC_STRING_MAX, 0);
- EXPECT_GT(_POSIX2_CHARCLASS_NAME_MAX, 0);
- EXPECT_GT(_POSIX2_COLL_WEIGHTS_MAX, 0);
EXPECT_EQ(_POSIX_VERSION, _POSIX2_C_BIND);
- EXPECT_GT(_POSIX2_EXPR_NEST_MAX, 0);
- EXPECT_GT(_POSIX2_LINE_MAX, 0);
- EXPECT_GT(_POSIX2_RE_DUP_MAX, 0);
+ EXPECT_EQ(_POSIX_VERSION, _POSIX2_CHAR_TERM);
EXPECT_EQ(700, _XOPEN_VERSION);
- EXPECT_GT(_XOPEN_IOV_MAX, 0);
- EXPECT_GT(_XOPEN_UNIX, 0);
+ EXPECT_EQ(1, _XOPEN_ENH_I18N);
+ EXPECT_EQ(1, _XOPEN_REALTIME);
+ EXPECT_EQ(1, _XOPEN_REALTIME_THREADS);
+ EXPECT_EQ(1, _XOPEN_SHM);
+ EXPECT_EQ(1, _XOPEN_UNIX);
#if defined(__BIONIC__)
// These tests only pass on bionic, as bionic and glibc has different support on these macros.
@@ -792,21 +819,20 @@
EXPECT_EQ(-1, _POSIX_MESSAGE_PASSING);
EXPECT_EQ(-1, _POSIX_PRIORITIZED_IO);
EXPECT_EQ(-1, _POSIX_SHARED_MEMORY_OBJECTS);
+ EXPECT_EQ(-1, _POSIX_THREAD_PRIO_INHERIT);
+ EXPECT_EQ(-1, _POSIX_THREAD_PRIO_PROTECT);
EXPECT_EQ(-1, _POSIX_THREAD_ROBUST_PRIO_INHERIT);
- EXPECT_EQ(-1, _POSIX2_CHAR_TERM);
EXPECT_EQ(-1, _POSIX2_C_DEV);
+ EXPECT_EQ(-1, _POSIX2_FORT_DEV);
+ EXPECT_EQ(-1, _POSIX2_FORT_RUN);
EXPECT_EQ(-1, _POSIX2_LOCALEDEF);
EXPECT_EQ(-1, _POSIX2_SW_DEV);
EXPECT_EQ(-1, _POSIX2_UPE);
- EXPECT_EQ(-1, _XOPEN_ENH_I18N);
EXPECT_EQ(-1, _XOPEN_CRYPT);
EXPECT_EQ(-1, _XOPEN_LEGACY);
- EXPECT_EQ(-1, _XOPEN_REALTIME);
- EXPECT_EQ(-1, _XOPEN_REALTIME_THREADS);
- EXPECT_EQ(-1, _XOPEN_SHM);
-
+ EXPECT_EQ(-1, _XOPEN_STREAMS);
#endif // defined(__BIONIC__)
}
@@ -916,11 +942,11 @@
VERIFY_SYSCONF_POSITIVE(_SC_REGEXP);
VERIFY_SYSCONF_POSITIVE(_SC_SHELL);
VERIFY_SYSCONF_POSIX_VERSION(_SC_SPAWN);
- VERIFY_SYSCONF_POSIX_VERSION(_SC_SPORADIC_SERVER);
+ VERIFY_SYSCONF_UNSUPPORTED(_SC_SPORADIC_SERVER);
VERIFY_SYSCONF_POSITIVE(_SC_SYMLOOP_MAX);
VERIFY_SYSCONF_POSIX_VERSION(_SC_THREAD_CPUTIME);
VERIFY_SYSCONF_POSIX_VERSION(_SC_THREAD_PROCESS_SHARED);
- VERIFY_SYSCONF_POSIX_VERSION(_SC_THREAD_SPORADIC_SERVER);
+ VERIFY_SYSCONF_UNSUPPORTED(_SC_THREAD_SPORADIC_SERVER);
VERIFY_SYSCONF_POSIX_VERSION(_SC_TIMEOUTS);
VERIFY_SYSCONF_UNSUPPORTED(_SC_TRACE);
VERIFY_SYSCONF_UNSUPPORTED(_SC_TRACE_EVENT_FILTER);
@@ -959,16 +985,11 @@
VERIFY_SYSCONF_UNSUPPORTED(_SC_THREAD_ROBUST_PRIO_PROTECT);
VERIFY_SYSCONF_UNSUPPORTED(_SC_2_C_DEV);
- VERIFY_SYSCONF_UNSUPPORTED(_SC_2_CHAR_TERM);
VERIFY_SYSCONF_UNSUPPORTED(_SC_2_LOCALEDEF);
VERIFY_SYSCONF_UNSUPPORTED(_SC_2_SW_DEV);
VERIFY_SYSCONF_UNSUPPORTED(_SC_XOPEN_CRYPT);
- VERIFY_SYSCONF_UNSUPPORTED(_SC_XOPEN_ENH_I18N);
VERIFY_SYSCONF_UNSUPPORTED(_SC_XOPEN_LEGACY);
- VERIFY_SYSCONF_UNSUPPORTED(_SC_XOPEN_REALTIME);
- VERIFY_SYSCONF_UNSUPPORTED(_SC_XOPEN_REALTIME_THREADS);
- VERIFY_SYSCONF_UNSUPPORTED(_SC_XOPEN_SHM);
VERIFY_SYSCONF_UNSUPPORTED(_SC_XOPEN_UUCP);
#endif // defined(__BIONIC__)
}
@@ -1376,9 +1397,87 @@
"<unknown>: usage: run-as");
}
+TEST(UNISTD_TEST, fexecve_failure) {
+ ExecTestHelper eth;
+ errno = 0;
+ int fd = open("/", O_RDONLY);
+ ASSERT_NE(-1, fd);
+ ASSERT_EQ(-1, fexecve(fd, eth.GetArgs(), eth.GetEnv()));
+ ASSERT_EQ(EACCES, errno);
+ close(fd);
+}
+
+TEST(UNISTD_TEST, fexecve_bad_fd) {
+ ExecTestHelper eth;
+ errno = 0;
+ ASSERT_EQ(-1, fexecve(-1, eth.GetArgs(), eth.GetEnv()));
+ ASSERT_EQ(EBADF, errno);
+}
+
+TEST(UNISTD_TEST, fexecve_args) {
+ // Test basic argument passing.
+ int echo_fd = open(BIN_DIR "echo", O_RDONLY | O_CLOEXEC);
+ ASSERT_NE(-1, echo_fd);
+ ExecTestHelper eth;
+ eth.SetArgs({"echo", "hello", "world", nullptr});
+ eth.Run([&]() { fexecve(echo_fd, eth.GetArgs(), eth.GetEnv()); }, 0, "hello world\n");
+ close(echo_fd);
+
+ // Test environment variable setting too.
+ int printenv_fd = open(BIN_DIR "printenv", O_RDONLY | O_CLOEXEC);
+ ASSERT_NE(-1, printenv_fd);
+ eth.SetArgs({"printenv", nullptr});
+ eth.SetEnv({"A=B", nullptr});
+ eth.Run([&]() { fexecve(printenv_fd, eth.GetArgs(), eth.GetEnv()); }, 0, "A=B\n");
+ close(printenv_fd);
+}
+
TEST(UNISTD_TEST, getlogin_r) {
char buf[LOGIN_NAME_MAX] = {};
EXPECT_EQ(ERANGE, getlogin_r(buf, 0));
EXPECT_EQ(0, getlogin_r(buf, sizeof(buf)));
EXPECT_STREQ(getlogin(), buf);
}
+
+TEST(UNISTD_TEST, swab) {
+ // POSIX: "The swab() function shall copy nbytes bytes, which are pointed to by src,
+ // to the object pointed to by dest, exchanging adjacent bytes."
+ char buf[BUFSIZ];
+ memset(buf, 'x', sizeof(buf));
+ swab("ehll oowlr\0d", buf, 12);
+ ASSERT_STREQ("hello world", buf);
+}
+
+TEST(UNISTD_TEST, swab_odd_byte_count) {
+ // POSIX: "If nbytes is odd, swab() copies and exchanges nbytes-1 bytes and the disposition
+ // of the last byte is unspecified."
+ // ...but it seems unreasonable to not just leave the last byte alone.
+ char buf[BUFSIZ];
+ memset(buf, 'x', sizeof(buf));
+ swab("012345", buf, 3);
+ ASSERT_EQ('1', buf[0]);
+ ASSERT_EQ('0', buf[1]);
+ ASSERT_EQ('x', buf[2]);
+}
+
+TEST(UNISTD_TEST, swab_overlap) {
+ // POSIX: "If copying takes place between objects that overlap, the behavior is undefined."
+ // ...but it seems unreasonable to not just do the right thing.
+ char buf[] = "012345";
+ swab(buf, buf, 4);
+ ASSERT_EQ('1', buf[0]);
+ ASSERT_EQ('0', buf[1]);
+ ASSERT_EQ('3', buf[2]);
+ ASSERT_EQ('2', buf[3]);
+ ASSERT_EQ('4', buf[4]);
+ ASSERT_EQ('5', buf[5]);
+ ASSERT_EQ(0, buf[6]);
+}
+
+TEST(UNISTD_TEST, swab_negative_byte_count) {
+ // POSIX: "If nbytes is negative, swab() does nothing."
+ char buf[BUFSIZ];
+ memset(buf, 'x', sizeof(buf));
+ swab("hello", buf, -1);
+ ASSERT_EQ('x', buf[0]);
+}
diff --git a/tools/versioner/src/DeclarationDatabase.cpp b/tools/versioner/src/DeclarationDatabase.cpp
index 247e58b..aef4f55 100644
--- a/tools/versioner/src/DeclarationDatabase.cpp
+++ b/tools/versioner/src/DeclarationDatabase.cpp
@@ -54,17 +54,19 @@
}
}
- if (mangler->shouldMangleDeclName(decl)) {
- std::string mangled;
- llvm::raw_string_ostream ss(mangled);
- mangler->mangleName(decl, ss);
- return mangled;
- }
-
+ // The decl might not have a name (e.g. bitfields).
if (auto identifier = decl->getIdentifier()) {
+ if (mangler->shouldMangleDeclName(decl)) {
+ std::string mangled;
+ llvm::raw_string_ostream ss(mangled);
+ mangler->mangleName(decl, ss);
+ return mangled;
+ }
+
return identifier->getName();
}
- return "<error>";
+
+ return "<unnamed>";
}
bool VisitDecl(Decl* decl) {
diff --git a/tools/versioner/tests/arch_specific/headers/foo.h b/tools/versioner/tests/arch_specific/headers/foo.h
index 34035b4..4830a68 100644
--- a/tools/versioner/tests/arch_specific/headers/foo.h
+++ b/tools/versioner/tests/arch_specific/headers/foo.h
@@ -1,5 +1,13 @@
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
int foo();
#if defined(__i386__)
int bar();
#endif
+
+#if defined(__cplusplus)
+}
+#endif
diff --git a/tools/versioner/tests/compilation_error/headers/foo.h b/tools/versioner/tests/compilation_error/headers/foo.h
index c8c1473..51c087a 100644
--- a/tools/versioner/tests/compilation_error/headers/foo.h
+++ b/tools/versioner/tests/compilation_error/headers/foo.h
@@ -1 +1,9 @@
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
#error foo
+
+#if defined(__cplusplus)
+}
+#endif
diff --git a/tools/versioner/tests/dependencies/dependencies/arm/archdep/archdep.h b/tools/versioner/tests/dependencies/dependencies/arm/archdep/archdep.h
index 2005972..b2d357a 100644
--- a/tools/versioner/tests/dependencies/dependencies/arm/archdep/archdep.h
+++ b/tools/versioner/tests/dependencies/dependencies/arm/archdep/archdep.h
@@ -1 +1,9 @@
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
typedef int arm_t;
+
+#if defined(__cplusplus)
+}
+#endif
diff --git a/tools/versioner/tests/dependencies/dependencies/common/foo/foodep.h b/tools/versioner/tests/dependencies/dependencies/common/foo/foodep.h
index 9feeb6c..baa5857 100644
--- a/tools/versioner/tests/dependencies/dependencies/common/foo/foodep.h
+++ b/tools/versioner/tests/dependencies/dependencies/common/foo/foodep.h
@@ -1 +1,9 @@
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
typedef int foo_t;
+
+#if defined(__cplusplus)
+}
+#endif
diff --git a/tools/versioner/tests/dependencies/dependencies/x86/archdep/archdep.h b/tools/versioner/tests/dependencies/dependencies/x86/archdep/archdep.h
index 5cc7de2..b73f7cc 100644
--- a/tools/versioner/tests/dependencies/dependencies/x86/archdep/archdep.h
+++ b/tools/versioner/tests/dependencies/dependencies/x86/archdep/archdep.h
@@ -1 +1,9 @@
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
typedef int x86_t;
+
+#if defined(__cplusplus)
+}
+#endif
diff --git a/tools/versioner/tests/dependencies/headers/foo.h b/tools/versioner/tests/dependencies/headers/foo.h
index 4491f1c..875de1b 100644
--- a/tools/versioner/tests/dependencies/headers/foo.h
+++ b/tools/versioner/tests/dependencies/headers/foo.h
@@ -1,3 +1,7 @@
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
#include <archdep.h>
#include <foodep.h>
@@ -6,3 +10,7 @@
#elif defined(__arm__)
arm_t foo(foo_t);
#endif
+
+#if defined(__cplusplus)
+}
+#endif
diff --git a/tools/versioner/tests/future/headers/foo.h b/tools/versioner/tests/future/headers/foo.h
index 54e8f0c..51a3a1c 100644
--- a/tools/versioner/tests/future/headers/foo.h
+++ b/tools/versioner/tests/future/headers/foo.h
@@ -1 +1,9 @@
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
int foo() __INTRODUCED_IN_FUTURE;
+
+#if defined(__cplusplus)
+}
+#endif
diff --git a/tools/versioner/tests/future_arch/headers/foo.h b/tools/versioner/tests/future_arch/headers/foo.h
index 9dd976e..a3258e7 100644
--- a/tools/versioner/tests/future_arch/headers/foo.h
+++ b/tools/versioner/tests/future_arch/headers/foo.h
@@ -1,5 +1,13 @@
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
#if defined(__arm__)
int foo() __INTRODUCED_IN(9);
#else
int foo() __INTRODUCED_IN_FUTURE;
#endif
+
+#if defined(__cplusplus)
+}
+#endif
diff --git a/tools/versioner/tests/inline/headers/foo.h b/tools/versioner/tests/inline/headers/foo.h
index a61b386..a337f9c 100644
--- a/tools/versioner/tests/inline/headers/foo.h
+++ b/tools/versioner/tests/inline/headers/foo.h
@@ -1,3 +1,7 @@
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
#if __ANDROID_API__ < 12
static int foo() {
return 0;
@@ -5,3 +9,7 @@
#else
int foo() __INTRODUCED_IN(12);
#endif
+
+#if defined(__cplusplus)
+}
+#endif
diff --git a/tools/versioner/tests/missing_api/expected_fail b/tools/versioner/tests/missing_api/expected_fail
index 18e7845..9f097f7 100644
--- a/tools/versioner/tests/missing_api/expected_fail
+++ b/tools/versioner/tests/missing_api/expected_fail
@@ -1,4 +1,4 @@
foo: introduced = 9
- extern declaration @ headers/foo.h:1:1
+ extern declaration @ headers/foo.h:5:1
introduced = 9
versioner: version check failed
diff --git a/tools/versioner/tests/missing_api/headers/foo.h b/tools/versioner/tests/missing_api/headers/foo.h
index 3ff3ff7..c201dbb 100644
--- a/tools/versioner/tests/missing_api/headers/foo.h
+++ b/tools/versioner/tests/missing_api/headers/foo.h
@@ -1 +1,9 @@
-int foo() __INTRODUCED_IN(9);
\ No newline at end of file
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+int foo() __INTRODUCED_IN(9);
+
+#if defined(__cplusplus)
+}
+#endif
diff --git a/tools/versioner/tests/missing_arch/expected_fail b/tools/versioner/tests/missing_arch/expected_fail
index 82c2b28..7b33e19 100644
--- a/tools/versioner/tests/missing_arch/expected_fail
+++ b/tools/versioner/tests/missing_arch/expected_fail
@@ -1,4 +1,4 @@
foo: no availability
- extern declaration @ headers/foo.h:1:1
+ extern declaration @ headers/foo.h:5:1
no availability
versioner: version check failed
diff --git a/tools/versioner/tests/missing_arch/headers/foo.h b/tools/versioner/tests/missing_arch/headers/foo.h
index 176e7a3..5ba4794 100644
--- a/tools/versioner/tests/missing_arch/headers/foo.h
+++ b/tools/versioner/tests/missing_arch/headers/foo.h
@@ -1 +1,9 @@
-int foo();
\ No newline at end of file
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+int foo();
+
+#if defined(__cplusplus)
+}
+#endif
diff --git a/tools/versioner/tests/multiple_decl/headers/bar.h b/tools/versioner/tests/multiple_decl/headers/bar.h
index 1d3a28c..b16617b 100644
--- a/tools/versioner/tests/multiple_decl/headers/bar.h
+++ b/tools/versioner/tests/multiple_decl/headers/bar.h
@@ -1 +1,9 @@
-int foo() __REMOVED_IN(12);
\ No newline at end of file
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+int foo() __REMOVED_IN(12);
+
+#if defined(__cplusplus)
+}
+#endif
diff --git a/tools/versioner/tests/multiple_decl/headers/foo.h b/tools/versioner/tests/multiple_decl/headers/foo.h
index 1d3a28c..b16617b 100644
--- a/tools/versioner/tests/multiple_decl/headers/foo.h
+++ b/tools/versioner/tests/multiple_decl/headers/foo.h
@@ -1 +1,9 @@
-int foo() __REMOVED_IN(12);
\ No newline at end of file
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+int foo() __REMOVED_IN(12);
+
+#if defined(__cplusplus)
+}
+#endif
diff --git a/tools/versioner/tests/multiple_decl_mismatch/expected_fail b/tools/versioner/tests/multiple_decl_mismatch/expected_fail
index 8e8c846..1d1f266 100644
--- a/tools/versioner/tests/multiple_decl_mismatch/expected_fail
+++ b/tools/versioner/tests/multiple_decl_mismatch/expected_fail
@@ -1,8 +1,8 @@
versioner: inconsistent availability for symbol 'foo'
versioner: failed to calculate symbol availability
foo: invalid
- extern declaration @ headers/bar.h:1:1
+ extern declaration @ headers/bar.h:5:1
obsoleted = 12
- extern declaration @ headers/foo.h:1:1
+ extern declaration @ headers/foo.h:5:1
obsoleted = 9
versioner: sanity check failed
diff --git a/tools/versioner/tests/multiple_decl_mismatch/headers/bar.h b/tools/versioner/tests/multiple_decl_mismatch/headers/bar.h
index 1d3a28c..b16617b 100644
--- a/tools/versioner/tests/multiple_decl_mismatch/headers/bar.h
+++ b/tools/versioner/tests/multiple_decl_mismatch/headers/bar.h
@@ -1 +1,9 @@
-int foo() __REMOVED_IN(12);
\ No newline at end of file
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+int foo() __REMOVED_IN(12);
+
+#if defined(__cplusplus)
+}
+#endif
diff --git a/tools/versioner/tests/multiple_decl_mismatch/headers/foo.h b/tools/versioner/tests/multiple_decl_mismatch/headers/foo.h
index 49a73ec..8e8f98c 100644
--- a/tools/versioner/tests/multiple_decl_mismatch/headers/foo.h
+++ b/tools/versioner/tests/multiple_decl_mismatch/headers/foo.h
@@ -1 +1,9 @@
-int foo() __REMOVED_IN(9);
\ No newline at end of file
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+int foo() __REMOVED_IN(9);
+
+#if defined(__cplusplus)
+}
+#endif
diff --git a/tools/versioner/tests/multiple_definition/expected_fail b/tools/versioner/tests/multiple_definition/expected_fail
index 6c531bd..7070390 100644
--- a/tools/versioner/tests/multiple_definition/expected_fail
+++ b/tools/versioner/tests/multiple_definition/expected_fail
@@ -1,7 +1,7 @@
versioner: conflicting inline definitions:
declarations visible in: arm-9 [fob = 32], arm-9 [fob = 64], arm-12 [fob = 32], arm-12 [fob = 64]
- static definition @ headers/foo.h:1:1
+ static definition @ headers/foo.h:5:1
no availability
- static definition @ headers/bar.h:1:1
+ static definition @ headers/bar.h:5:1
no availability
versioner: sanity check failed
diff --git a/tools/versioner/tests/multiple_definition/headers/bar.h b/tools/versioner/tests/multiple_definition/headers/bar.h
index a9d0197..29592c6 100644
--- a/tools/versioner/tests/multiple_definition/headers/bar.h
+++ b/tools/versioner/tests/multiple_definition/headers/bar.h
@@ -1,3 +1,11 @@
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
static int foo() {
return 0;
}
+
+#if defined(__cplusplus)
+}
+#endif
diff --git a/tools/versioner/tests/multiple_definition/headers/foo.h b/tools/versioner/tests/multiple_definition/headers/foo.h
index a9d0197..29592c6 100644
--- a/tools/versioner/tests/multiple_definition/headers/foo.h
+++ b/tools/versioner/tests/multiple_definition/headers/foo.h
@@ -1,3 +1,11 @@
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
static int foo() {
return 0;
}
+
+#if defined(__cplusplus)
+}
+#endif
diff --git a/tools/versioner/tests/multiple_definition_ok/headers/bar.h b/tools/versioner/tests/multiple_definition_ok/headers/bar.h
index c3c87bb..6eced51 100644
--- a/tools/versioner/tests/multiple_definition_ok/headers/bar.h
+++ b/tools/versioner/tests/multiple_definition_ok/headers/bar.h
@@ -1,5 +1,13 @@
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
#if __ANDROID_API__ == 12
static int foo() {
return 0;
}
#endif
+
+#if defined(__cplusplus)
+}
+#endif
diff --git a/tools/versioner/tests/multiple_definition_ok/headers/foo.h b/tools/versioner/tests/multiple_definition_ok/headers/foo.h
index 9da9b2a..773d274 100644
--- a/tools/versioner/tests/multiple_definition_ok/headers/foo.h
+++ b/tools/versioner/tests/multiple_definition_ok/headers/foo.h
@@ -1,5 +1,13 @@
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
#if __ANDROID_API__ == 9
static int foo() {
return 0;
}
#endif
+
+#if defined(__cplusplus)
+}
+#endif
diff --git a/tools/versioner/tests/obsoleted/headers/foo.h b/tools/versioner/tests/obsoleted/headers/foo.h
index 68f3d43..e9630e5 100644
--- a/tools/versioner/tests/obsoleted/headers/foo.h
+++ b/tools/versioner/tests/obsoleted/headers/foo.h
@@ -1 +1,9 @@
-int foo() __INTRODUCED_IN(9) __REMOVED_IN(11);
\ No newline at end of file
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+int foo() __INTRODUCED_IN(9) __REMOVED_IN(11);
+
+#if defined(__cplusplus)
+}
+#endif
diff --git a/tools/versioner/tests/preprocessor/expected/foo.h b/tools/versioner/tests/preprocessor/expected/foo.h
index 73947b2..cb719f0 100644
--- a/tools/versioner/tests/preprocessor/expected/foo.h
+++ b/tools/versioner/tests/preprocessor/expected/foo.h
@@ -1,3 +1,7 @@
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
int always_available();
int also_always_available() __INTRODUCED_IN(9);
@@ -74,3 +78,7 @@
int future() __INTRODUCED_IN_FUTURE;
#endif /* __ANDROID_API__ >= __ANDROID_API_FUTURE__ */
+
+#if defined(__cplusplus)
+}
+#endif
diff --git a/tools/versioner/tests/preprocessor/headers/foo.h b/tools/versioner/tests/preprocessor/headers/foo.h
index 81c8b4b..2429334 100644
--- a/tools/versioner/tests/preprocessor/headers/foo.h
+++ b/tools/versioner/tests/preprocessor/headers/foo.h
@@ -1,3 +1,7 @@
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
int always_available();
int also_always_available() __INTRODUCED_IN(9);
@@ -42,3 +46,7 @@
int group_lp32() __INTRODUCED_IN_ARM(12) __INTRODUCED_IN_X86(12) __INTRODUCED_IN_MIPS(12);
int future() __INTRODUCED_IN_FUTURE;
+
+#if defined(__cplusplus)
+}
+#endif
diff --git a/tools/versioner/tests/preprocessor_file_offset_bits/expected/foo.h b/tools/versioner/tests/preprocessor_file_offset_bits/expected/foo.h
index 7d31ec3..dcfaaee 100644
--- a/tools/versioner/tests/preprocessor_file_offset_bits/expected/foo.h
+++ b/tools/versioner/tests/preprocessor_file_offset_bits/expected/foo.h
@@ -1,3 +1,7 @@
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
typedef int off_t;
typedef int ssize_t;
typedef unsigned size_t;
@@ -32,3 +36,7 @@
#else
off_t lseek(int __fd, off_t __offset, int __whence);
#endif
+
+#if defined(__cplusplus)
+}
+#endif
diff --git a/tools/versioner/tests/preprocessor_file_offset_bits/headers/foo.h b/tools/versioner/tests/preprocessor_file_offset_bits/headers/foo.h
index 868d1fc..5ffffa8 100644
--- a/tools/versioner/tests/preprocessor_file_offset_bits/headers/foo.h
+++ b/tools/versioner/tests/preprocessor_file_offset_bits/headers/foo.h
@@ -1,3 +1,7 @@
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
typedef int off_t;
typedef int ssize_t;
typedef unsigned size_t;
@@ -28,3 +32,7 @@
#else
off_t lseek(int __fd, off_t __offset, int __whence);
#endif
+
+#if defined(__cplusplus)
+}
+#endif
diff --git a/tools/versioner/tests/preprocessor_idempotence/expected/foo.h b/tools/versioner/tests/preprocessor_idempotence/expected/foo.h
index ed31e8b..bc442e5 100644
--- a/tools/versioner/tests/preprocessor_idempotence/expected/foo.h
+++ b/tools/versioner/tests/preprocessor_idempotence/expected/foo.h
@@ -1,3 +1,7 @@
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
#if __ANDROID_API__ >= 10
int foo() __INTRODUCED_IN(10);
#endif
@@ -10,3 +14,7 @@
int multiple_1() __INTRODUCED_IN(10);
int multiple_2() __INTRODUCED_IN(10);
#endif
+
+#if defined(__cplusplus)
+}
+#endif
diff --git a/tools/versioner/tests/preprocessor_idempotence/headers/foo.h b/tools/versioner/tests/preprocessor_idempotence/headers/foo.h
index ed31e8b..bc442e5 100644
--- a/tools/versioner/tests/preprocessor_idempotence/headers/foo.h
+++ b/tools/versioner/tests/preprocessor_idempotence/headers/foo.h
@@ -1,3 +1,7 @@
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
#if __ANDROID_API__ >= 10
int foo() __INTRODUCED_IN(10);
#endif
@@ -10,3 +14,7 @@
int multiple_1() __INTRODUCED_IN(10);
int multiple_2() __INTRODUCED_IN(10);
#endif
+
+#if defined(__cplusplus)
+}
+#endif
diff --git a/tools/versioner/tests/preprocessor_merging/expected/foo.h b/tools/versioner/tests/preprocessor_merging/expected/foo.h
index 45eb32d..ecd7f71 100644
--- a/tools/versioner/tests/preprocessor_merging/expected/foo.h
+++ b/tools/versioner/tests/preprocessor_merging/expected/foo.h
@@ -1,3 +1,7 @@
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
#if __ANDROID_API__ >= 10
int block_merging_1() __INTRODUCED_IN(10); // foo
@@ -7,3 +11,7 @@
int block_merging_4() __INTRODUCED_IN(10);
#endif /* __ANDROID_API__ >= 10 */
+
+#if defined(__cplusplus)
+}
+#endif
diff --git a/tools/versioner/tests/preprocessor_merging/headers/foo.h b/tools/versioner/tests/preprocessor_merging/headers/foo.h
index ac9564b..7aaa471 100644
--- a/tools/versioner/tests/preprocessor_merging/headers/foo.h
+++ b/tools/versioner/tests/preprocessor_merging/headers/foo.h
@@ -1,5 +1,13 @@
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
int block_merging_1() __INTRODUCED_IN(10); // foo
int block_merging_2() __INTRODUCED_IN(10); /* bar */
int block_merging_3() __INTRODUCED_IN(10); /* baz
//*/
int block_merging_4() __INTRODUCED_IN(10);
+
+#if defined(__cplusplus)
+}
+#endif
diff --git a/tools/versioner/tests/preprocessor_no_guard/expected/foo.h b/tools/versioner/tests/preprocessor_no_guard/expected/foo.h
index 2bf1dbf..3ef0c30 100644
--- a/tools/versioner/tests/preprocessor_no_guard/expected/foo.h
+++ b/tools/versioner/tests/preprocessor_no_guard/expected/foo.h
@@ -1 +1,9 @@
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
int foo() __VERSIONER_NO_GUARD __INTRODUCED_IN(14);
+
+#if defined(__cplusplus)
+}
+#endif
diff --git a/tools/versioner/tests/preprocessor_no_guard/headers/foo.h b/tools/versioner/tests/preprocessor_no_guard/headers/foo.h
index 2bf1dbf..3ef0c30 100644
--- a/tools/versioner/tests/preprocessor_no_guard/headers/foo.h
+++ b/tools/versioner/tests/preprocessor_no_guard/headers/foo.h
@@ -1 +1,9 @@
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
int foo() __VERSIONER_NO_GUARD __INTRODUCED_IN(14);
+
+#if defined(__cplusplus)
+}
+#endif
diff --git a/tools/versioner/tests/smoke/headers/foo.h b/tools/versioner/tests/smoke/headers/foo.h
index 3ff3ff7..c201dbb 100644
--- a/tools/versioner/tests/smoke/headers/foo.h
+++ b/tools/versioner/tests/smoke/headers/foo.h
@@ -1 +1,9 @@
-int foo() __INTRODUCED_IN(9);
\ No newline at end of file
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+int foo() __INTRODUCED_IN(9);
+
+#if defined(__cplusplus)
+}
+#endif
diff --git a/tools/versioner/tests/version_mismatch/expected_fail b/tools/versioner/tests/version_mismatch/expected_fail
index f83f71c..f2143a3 100644
--- a/tools/versioner/tests/version_mismatch/expected_fail
+++ b/tools/versioner/tests/version_mismatch/expected_fail
@@ -1,8 +1,8 @@
versioner: inconsistent availability for symbol 'foo'
versioner: failed to calculate symbol availability
foo: invalid
- extern declaration @ headers/foo.h:2:1
+ extern declaration @ headers/foo.h:6:1
introduced = 9
- extern declaration @ headers/foo.h:4:1
+ extern declaration @ headers/foo.h:8:1
introduced = 10
versioner: sanity check failed
diff --git a/tools/versioner/tests/version_mismatch/headers/foo.h b/tools/versioner/tests/version_mismatch/headers/foo.h
index 4604092..ea35f36 100644
--- a/tools/versioner/tests/version_mismatch/headers/foo.h
+++ b/tools/versioner/tests/version_mismatch/headers/foo.h
@@ -1,5 +1,13 @@
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
#if __ANDROID_API__ <= 9
int foo() __INTRODUCED_IN(9);
#else
int foo() __INTRODUCED_IN(10);
#endif
+
+#if defined(__cplusplus)
+}
+#endif